mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 09:07:40 +00:00
* perf(orcad): keep the server bundle ASCII so V8 stores it one byte per character 129 non-ASCII characters in regex literals (and three in a String.raw plugin template) made V8 hold the whole ~11 MB orcad-server.js source as a two-byte string. Write them as \uXXXX escapes and fail the build if any return. Co-Authored-By: Claude <noreply@anthropic.com> * fix(orcad): keep license comments ASCII and name the module the guard trips on esbuild gathers legal comments at the end of the bundle; escape that comment so a dependency's license text cannot fail the ASCII guard, while licenses still ship with the code. The guard now reports the offset and, from an unminified rebuild, the module the character came from. A dark-switch build is covered. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
/** Windows normalizes these names even when the host doing validation does not. */
|
|
const WINDOWS_DEVICE_NAME_RE =
|
|
/^(?:con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9\u00B9\u00B2\u00B3]|lpt[1-9\u00B9\u00B2\u00B3])(?:\..*)?$/i
|
|
|
|
const WINDOWS_FORBIDDEN_CHAR_RE = /[<>:"|?*]/
|
|
|
|
export function pluginPathSegmentError(segment: string): string | null {
|
|
if (segment.length === 0 || segment === '.' || segment === '..') {
|
|
return 'empty and dot path segments are not allowed'
|
|
}
|
|
if (segment.endsWith('.') || segment.endsWith(' ')) {
|
|
return 'path segments may not end with a dot or space'
|
|
}
|
|
if (
|
|
WINDOWS_FORBIDDEN_CHAR_RE.test(segment) ||
|
|
[...segment].some((character) => character.charCodeAt(0) <= 31)
|
|
) {
|
|
return 'path segment contains a Windows-forbidden character or alternate-data-stream colon'
|
|
}
|
|
if (WINDOWS_DEVICE_NAME_RE.test(segment)) {
|
|
return 'path segment is a Windows reserved device name'
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function pluginRelativePathError(value: string): string | null {
|
|
if (value.length === 0 || value.startsWith('/') || value.startsWith('\\')) {
|
|
return 'must be a non-empty relative path'
|
|
}
|
|
const segments = value.split(/[\\/]/)
|
|
for (const segment of segments) {
|
|
const error = pluginPathSegmentError(segment)
|
|
if (error) {
|
|
return error
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
export function isSafePluginRelativePath(value: string): boolean {
|
|
return pluginRelativePathError(value) === null
|
|
}
|