| ... | ... | @@ -1,10 +1,7 @@ |
| 1 | 1 | import type { ProjectScript } from "@t3tools/contracts"; |
| 2 | 2 | |
| 3 | | import { isWindowsPlatform } from "./lib/utils"; |
| 4 | | |
| 5 | 3 | const SCRIPT_RUN_COMMAND_PATTERN = /^script\.([a-z0-9][a-z0-9-]*)\.run$/; |
| 6 | 4 | const MAX_SCRIPT_ID_LENGTH = 64; |
| 7 | | const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/; |
| 8 | 5 | |
| 9 | 6 | function normalizeScriptId(value: string): string { |
| 10 | 7 | const cleaned = value |
| ... | ... | @@ -52,37 +49,6 @@ export function nextProjectScriptId(name: string, existingIds: Iterable<string>) |
| 52 | 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 | 52 | interface ProjectScriptRuntimeEnvInput { |
| 87 | 53 | project: { |
| 88 | 54 | cwd: string; |