| ... | @@ -1,10 +1,7 @@ | ... | @@ -1,10 +1,7 @@ |
| 1 | import type { ProjectScript } from "@t3tools/contracts"; | 1 | import type { ProjectScript } from "@t3tools/contracts"; |
| 2 | | 2 | |
| 3 | import { isWindowsPlatform } from "./lib/utils"; | | |
| 4 | | | |
| 5 | const SCRIPT_RUN_COMMAND_PATTERN = /^script\.([a-z0-9][a-z0-9-]*)\.run$/; | 3 | const SCRIPT_RUN_COMMAND_PATTERN = /^script\.([a-z0-9][a-z0-9-]*)\.run$/; |
| 6 | const MAX_SCRIPT_ID_LENGTH = 64; | 4 | const MAX_SCRIPT_ID_LENGTH = 64; |
| 7 | const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/; | | |
| 8 | | 5 | |
| 9 | function normalizeScriptId(value: string): string { | 6 | function normalizeScriptId(value: string): string { |
| 10 | const cleaned = value | 7 | const cleaned = value |
| ... | @@ -52,37 +49,6 @@ export function nextProjectScriptId(name: string, existingIds: Iterable<string>) | ... | @@ -52,37 +49,6 @@ export function nextProjectScriptId(name: string, existingIds: Iterable<string>) |
| 52 | return `${baseId}-${Date.now()}`.slice(0, MAX_SCRIPT_ID_LENGTH); | 49 | return `${baseId}-${Date.now()}`.slice(0, MAX_SCRIPT_ID_LENGTH); |
| 53 | } | 50 | } |
| 54 | | 51 | |
| 55 | function shellEscapePosix(value: string): string { | | |
| 56 | return `'${value.replace(/'/g, `'\\''`)}'`; | | |
| 57 | } | | |
| 58 | | | |
| 59 | function shellEscapeWindowsSetValue(value: string): string { | | |
| 60 | return value.replace(/\^/g, "^^").replace(/%/g, "^%").replace(/"/g, '""'); | | |
| 61 | } | | |
| 62 | | | |
| 63 | function injectEnvIntoShellCommand( | | |
| 64 | command: string, | | |
| 65 | env: Record<string, string>, | | |
| 66 | platform = typeof navigator === "undefined" ? "" : navigator.platform, | | |
| 67 | ): string { | | |
| 68 | const entries = Object.entries(env).filter( | | |
| 69 | ([key, value]) => ENV_KEY_PATTERN.test(key) && value.length > 0, | | |
| 70 | ); | | |
| 71 | if (entries.length === 0) { | | |
| 72 | return command; | | |
| 73 | } | | |
| 74 | | | |
| 75 | if (isWindowsPlatform(platform)) { | | |
| 76 | const prefixes = entries.map( | | |
| 77 | ([key, value]) => `set "${key}=${shellEscapeWindowsSetValue(value)}"`, | | |
| 78 | ); | | |
| 79 | return `${prefixes.join(" && ")} && ${command}`; | | |
| 80 | } | | |
| 81 | | | |
| 82 | const assignments = entries.map(([key, value]) => `${key}=${shellEscapePosix(value)}`).join(" "); | | |
| 83 | return `env ${assignments} ${command}`; | | |
| 84 | } | | |
| 85 | | | |
| 86 | interface ProjectScriptRuntimeEnvInput { | 52 | interface ProjectScriptRuntimeEnvInput { |
| 87 | project: { | 53 | project: { |
| 88 | cwd: string; | 54 | cwd: string; |