@cleocode/paths 2026.9.20 → 2026.9.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cleo-paths.d.ts +144 -30
- package/dist/cleo-paths.d.ts.map +1 -1
- package/dist/cleo-paths.js +183 -54
- package/dist/cleo-paths.js.map +1 -1
- package/dist/exec-path.d.ts +183 -0
- package/dist/exec-path.d.ts.map +1 -0
- package/dist/exec-path.js +266 -0
- package/dist/exec-path.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/platform-paths.d.ts +21 -0
- package/dist/platform-paths.d.ts.map +1 -1
- package/dist/platform-paths.js +29 -4
- package/dist/platform-paths.js.map +1 -1
- package/dist/worktree-paths.d.ts +17 -0
- package/dist/worktree-paths.d.ts.map +1 -1
- package/dist/worktree-paths.js +21 -0
- package/dist/worktree-paths.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform PATH composition and executable lookup.
|
|
3
|
+
*
|
|
4
|
+
* `PATH` is `:`-delimited on POSIX and `;`-delimited on Windows, where the
|
|
5
|
+
* variable is also commonly spelled `Path` and a bare command name resolves
|
|
6
|
+
* through `PATHEXT` (`git` → `git.exe`, `cleo` → `cleo.cmd`). Building PATH as
|
|
7
|
+
* `${dir}:${PATH}` on Windows fuses the new directory with the first real
|
|
8
|
+
* entry, and splitting on `:` cuts every `C:\…` drive-letter entry in half, so
|
|
9
|
+
* each helper here takes the platform explicitly (defaulting to the running
|
|
10
|
+
* one) and joins with that platform's path module. Tests inject `win32` on
|
|
11
|
+
* any host.
|
|
12
|
+
*
|
|
13
|
+
* Lookups are in-process filesystem probes — no `which`/`where` child — so
|
|
14
|
+
* they behave identically on every OS and cost no process spawn.
|
|
15
|
+
*
|
|
16
|
+
* @task T12605
|
|
17
|
+
*/
|
|
18
|
+
/** Platform-injection options shared by the PATH helpers. */
|
|
19
|
+
export interface ExecPathOptions {
|
|
20
|
+
/** Platform whose PATH rules apply. @defaultValue `process.platform` */
|
|
21
|
+
platform?: NodeJS.Platform;
|
|
22
|
+
/** Environment holding `PATH`/`Path` and `PATHEXT`. @defaultValue `process.env` */
|
|
23
|
+
env?: NodeJS.ProcessEnv;
|
|
24
|
+
/**
|
|
25
|
+
* Predicate deciding whether a candidate file is runnable.
|
|
26
|
+
* @defaultValue a regular file that is executable (POSIX) or exists (win32)
|
|
27
|
+
*/
|
|
28
|
+
isExecutable?: (candidate: string) => boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Return the PATH list delimiter for a platform (`;` on win32, `:` elsewhere).
|
|
32
|
+
*
|
|
33
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
34
|
+
* @returns The delimiter character.
|
|
35
|
+
*/
|
|
36
|
+
export declare function pathDelimiterFor(platform?: NodeJS.Platform): string;
|
|
37
|
+
/**
|
|
38
|
+
* Return the environment key that holds the executable search path.
|
|
39
|
+
*
|
|
40
|
+
* Windows environment names are case-insensitive and the system spelling is
|
|
41
|
+
* `Path`; writing a second `PATH` key beside it leaves the child with two
|
|
42
|
+
* conflicting values. The existing key is reused whatever its case.
|
|
43
|
+
*
|
|
44
|
+
* @param env - Environment to inspect.
|
|
45
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
46
|
+
* @returns `PATH`, or the existing case-variant on win32.
|
|
47
|
+
*/
|
|
48
|
+
export declare function pathEnvKey(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): string;
|
|
49
|
+
/**
|
|
50
|
+
* Split a PATH value into its non-empty directory entries.
|
|
51
|
+
*
|
|
52
|
+
* @param value - Raw PATH value (may be undefined).
|
|
53
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
54
|
+
* @returns Directory entries in search order.
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* splitPathEnv('C:\\Windows;C:\\Git\\cmd', 'win32'); // ['C:\\Windows', 'C:\\Git\\cmd']
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function splitPathEnv(value: string | undefined, platform?: NodeJS.Platform): string[];
|
|
61
|
+
/**
|
|
62
|
+
* Prepend a directory to a PATH value using the platform's delimiter.
|
|
63
|
+
*
|
|
64
|
+
* @param dir - Directory to search first.
|
|
65
|
+
* @param currentPath - Existing PATH value (may be empty or undefined).
|
|
66
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
67
|
+
* @returns The composed PATH value; `dir` alone when `currentPath` is empty.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* prependPathEntry('C:\\shim', 'C:\\Windows', 'win32'); // 'C:\\shim;C:\\Windows'
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function prependPathEntry(dir: string, currentPath: string | undefined, platform?: NodeJS.Platform): string;
|
|
74
|
+
/**
|
|
75
|
+
* List the file names a bare command can resolve to on a platform.
|
|
76
|
+
*
|
|
77
|
+
* On win32 each `PATHEXT` extension is tried, and the bare name only when it
|
|
78
|
+
* already carries one of those extensions. Elsewhere the name is used as-is.
|
|
79
|
+
*
|
|
80
|
+
* @param name - Command name, e.g. `git`.
|
|
81
|
+
* @param opts - Platform and environment overrides.
|
|
82
|
+
* @returns Candidate file names in resolution order.
|
|
83
|
+
*/
|
|
84
|
+
export declare function executableNames(name: string, opts?: ExecPathOptions): string[];
|
|
85
|
+
/**
|
|
86
|
+
* Resolve a command to the absolute path the OS would run, or `null`.
|
|
87
|
+
*
|
|
88
|
+
* Honours the platform's PATH delimiter, the win32 `Path` spelling, and
|
|
89
|
+
* `PATHEXT`. A name containing a path separator is checked directly rather
|
|
90
|
+
* than searched for.
|
|
91
|
+
*
|
|
92
|
+
* @param name - Command name or path.
|
|
93
|
+
* @param opts - Platform, environment and executability overrides.
|
|
94
|
+
* @returns Absolute path of the first match, or `null`.
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* findOnPath('git'); // '/usr/bin/git' on Linux, 'C:\\Program Files\\Git\\cmd\\git.exe' on Windows
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function findOnPath(name: string, opts?: ExecPathOptions): string | null;
|
|
101
|
+
/** A shell command line resolved to an argv the platform can spawn. */
|
|
102
|
+
export interface ShellInvocation {
|
|
103
|
+
/** Shell executable. */
|
|
104
|
+
file: string;
|
|
105
|
+
/** Arguments that make the shell run the command line once. */
|
|
106
|
+
args: string[];
|
|
107
|
+
/** Pass to `child_process` so cmd.exe receives the quoted line untouched. */
|
|
108
|
+
windowsVerbatimArguments: boolean;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Resolve how to run a shell command line on a platform.
|
|
112
|
+
*
|
|
113
|
+
* `/bin/sh -c` on POSIX; on win32 `%ComSpec%` (cmd.exe) with `/d /s /c` and
|
|
114
|
+
* the line quoted verbatim — the same resolution Node applies for
|
|
115
|
+
* `shell: true`, made explicit so every caller that runs user-authored
|
|
116
|
+
* command strings (worktree hooks, release build commands) shares one
|
|
117
|
+
* resolver and tests can pin the platform.
|
|
118
|
+
*
|
|
119
|
+
* @param command - Command line to run.
|
|
120
|
+
* @param opts - Platform and environment overrides.
|
|
121
|
+
* @returns The executable, its argv and the verbatim-arguments flag.
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* const sh = shellInvocation('pnpm build');
|
|
125
|
+
* execFile(sh.file, sh.args, { windowsVerbatimArguments: sh.windowsVerbatimArguments });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function shellInvocation(command: string, opts?: ExecPathOptions): ShellInvocation;
|
|
129
|
+
/**
|
|
130
|
+
* Quote one argument for a `.cmd`/`.bat` target launched through cmd.exe.
|
|
131
|
+
*
|
|
132
|
+
* Two layers, as cmd parses the line and the batch file's program parses its
|
|
133
|
+
* argv: MSVCRT quoting (backslashes before a quote doubled, the quote
|
|
134
|
+
* escaped, the whole argument wrapped in quotes), then every cmd
|
|
135
|
+
* metacharacter caret-escaped TWICE — cmd re-parses the line when it
|
|
136
|
+
* dispatches a batch file, consuming one caret layer each pass. Because every
|
|
137
|
+
* quote is escaped, cmd never sees a quoted region in which operators such as
|
|
138
|
+
* `&` or `|` would be live. `%VAR%` expands before carets are processed, but
|
|
139
|
+
* `%NAME^%` names a variable (`NAME^`) that is never defined, and an undefined
|
|
140
|
+
* reference is left verbatim on a `cmd /c` line. This is the scheme `cross-spawn` uses against the BatBadBut class
|
|
141
|
+
* (CVE-2024-27980).
|
|
142
|
+
*
|
|
143
|
+
* @param arg - Literal argument.
|
|
144
|
+
* @returns The escaped token.
|
|
145
|
+
* @throws When `arg` holds CR or LF: cmd.exe ends the command at a line
|
|
146
|
+
* break and no escape can carry one into a batch file.
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* quoteCmdArg('a b'); // '^^^"a^^^ b^^^"'
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export declare function quoteCmdArg(arg: string): string;
|
|
153
|
+
/** An executable plus argv, resolved for `child_process.spawn` on a platform. */
|
|
154
|
+
export interface SpawnInvocation {
|
|
155
|
+
/** File to spawn. */
|
|
156
|
+
file: string;
|
|
157
|
+
/** Arguments to pass. */
|
|
158
|
+
args: string[];
|
|
159
|
+
/** Pass through to `spawn` — `true` only for the cmd.exe batch form. */
|
|
160
|
+
windowsVerbatimArguments: boolean;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Resolve how to spawn `command args` without a shell on any platform.
|
|
164
|
+
*
|
|
165
|
+
* POSIX: returned unchanged. win32: the command is resolved to the absolute
|
|
166
|
+
* path {@link findOnPath} finds, because Node's own lookup tries only `.exe`
|
|
167
|
+
* and `.com`. A `.cmd`/`.bat` target (every npm-installed CLI) cannot be
|
|
168
|
+
* spawned directly — Node refuses since CVE-2024-27980 — so it is launched
|
|
169
|
+
* through `%ComSpec% /d /s /c` with every token escaped by {@link quoteCmdArg}.
|
|
170
|
+
*
|
|
171
|
+
* @param command - Command name or path.
|
|
172
|
+
* @param args - Literal arguments.
|
|
173
|
+
* @param opts - Platform and environment overrides.
|
|
174
|
+
* @returns The spawnable invocation.
|
|
175
|
+
* @throws When a batch-file argument contains a line break (see {@link quoteCmdArg}).
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* const inv = resolveSpawnInvocation('codex', ['--full-auto', promptFile]);
|
|
179
|
+
* spawn(inv.file, inv.args, { windowsVerbatimArguments: inv.windowsVerbatimArguments });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export declare function resolveSpawnInvocation(command: string, args: readonly string[], opts?: ExecPathOptions): SpawnInvocation;
|
|
183
|
+
//# sourceMappingURL=exec-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-path.d.ts","sourceRoot":"","sources":["../src/exec-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAC/C;AAKD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,MAAM,CAErF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAGR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,EAAE,CAEV;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAER;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,MAAM,EAAE,CAWlF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,MAAM,GAAG,IAAI,CAgBlF;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,6EAA6E;IAC7E,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,eAAe,CAS5F;AAKD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK/C;AA2BD,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wEAAwE;IACxE,wBAAwB,EAAE,OAAO,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,GAAE,eAAoB,GACzB,eAAe,CAYjB"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform PATH composition and executable lookup.
|
|
3
|
+
*
|
|
4
|
+
* `PATH` is `:`-delimited on POSIX and `;`-delimited on Windows, where the
|
|
5
|
+
* variable is also commonly spelled `Path` and a bare command name resolves
|
|
6
|
+
* through `PATHEXT` (`git` → `git.exe`, `cleo` → `cleo.cmd`). Building PATH as
|
|
7
|
+
* `${dir}:${PATH}` on Windows fuses the new directory with the first real
|
|
8
|
+
* entry, and splitting on `:` cuts every `C:\…` drive-letter entry in half, so
|
|
9
|
+
* each helper here takes the platform explicitly (defaulting to the running
|
|
10
|
+
* one) and joins with that platform's path module. Tests inject `win32` on
|
|
11
|
+
* any host.
|
|
12
|
+
*
|
|
13
|
+
* Lookups are in-process filesystem probes — no `which`/`where` child — so
|
|
14
|
+
* they behave identically on every OS and cost no process spawn.
|
|
15
|
+
*
|
|
16
|
+
* @task T12605
|
|
17
|
+
*/
|
|
18
|
+
import { accessSync, constants, statSync } from 'node:fs';
|
|
19
|
+
import { posix, win32 } from 'node:path';
|
|
20
|
+
/** `PATHEXT` used on Windows when the variable is unset. */
|
|
21
|
+
const DEFAULT_PATHEXT = '.COM;.EXE;.BAT;.CMD';
|
|
22
|
+
/**
|
|
23
|
+
* Return the PATH list delimiter for a platform (`;` on win32, `:` elsewhere).
|
|
24
|
+
*
|
|
25
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
26
|
+
* @returns The delimiter character.
|
|
27
|
+
*/
|
|
28
|
+
export function pathDelimiterFor(platform = process.platform) {
|
|
29
|
+
return platform === 'win32' ? win32.delimiter : posix.delimiter;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Return the environment key that holds the executable search path.
|
|
33
|
+
*
|
|
34
|
+
* Windows environment names are case-insensitive and the system spelling is
|
|
35
|
+
* `Path`; writing a second `PATH` key beside it leaves the child with two
|
|
36
|
+
* conflicting values. The existing key is reused whatever its case.
|
|
37
|
+
*
|
|
38
|
+
* @param env - Environment to inspect.
|
|
39
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
40
|
+
* @returns `PATH`, or the existing case-variant on win32.
|
|
41
|
+
*/
|
|
42
|
+
export function pathEnvKey(env = process.env, platform = process.platform) {
|
|
43
|
+
if (platform !== 'win32')
|
|
44
|
+
return 'PATH';
|
|
45
|
+
return Object.keys(env).find((key) => key.toUpperCase() === 'PATH') ?? 'PATH';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Split a PATH value into its non-empty directory entries.
|
|
49
|
+
*
|
|
50
|
+
* @param value - Raw PATH value (may be undefined).
|
|
51
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
52
|
+
* @returns Directory entries in search order.
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* splitPathEnv('C:\\Windows;C:\\Git\\cmd', 'win32'); // ['C:\\Windows', 'C:\\Git\\cmd']
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function splitPathEnv(value, platform = process.platform) {
|
|
59
|
+
return (value ?? '').split(pathDelimiterFor(platform)).filter(Boolean);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Prepend a directory to a PATH value using the platform's delimiter.
|
|
63
|
+
*
|
|
64
|
+
* @param dir - Directory to search first.
|
|
65
|
+
* @param currentPath - Existing PATH value (may be empty or undefined).
|
|
66
|
+
* @param platform - Target platform. @defaultValue `process.platform`
|
|
67
|
+
* @returns The composed PATH value; `dir` alone when `currentPath` is empty.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* prependPathEntry('C:\\shim', 'C:\\Windows', 'win32'); // 'C:\\shim;C:\\Windows'
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function prependPathEntry(dir, currentPath, platform = process.platform) {
|
|
74
|
+
return currentPath ? `${dir}${pathDelimiterFor(platform)}${currentPath}` : dir;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* List the file names a bare command can resolve to on a platform.
|
|
78
|
+
*
|
|
79
|
+
* On win32 each `PATHEXT` extension is tried, and the bare name only when it
|
|
80
|
+
* already carries one of those extensions. Elsewhere the name is used as-is.
|
|
81
|
+
*
|
|
82
|
+
* @param name - Command name, e.g. `git`.
|
|
83
|
+
* @param opts - Platform and environment overrides.
|
|
84
|
+
* @returns Candidate file names in resolution order.
|
|
85
|
+
*/
|
|
86
|
+
export function executableNames(name, opts = {}) {
|
|
87
|
+
const platform = opts.platform ?? process.platform;
|
|
88
|
+
if (platform !== 'win32')
|
|
89
|
+
return [name];
|
|
90
|
+
const env = opts.env ?? process.env;
|
|
91
|
+
const exts = (env[pathExtKey(env)] || DEFAULT_PATHEXT)
|
|
92
|
+
.split(';')
|
|
93
|
+
.map((ext) => ext.trim().toLowerCase())
|
|
94
|
+
.filter(Boolean);
|
|
95
|
+
const lower = name.toLowerCase();
|
|
96
|
+
if (exts.some((ext) => lower.endsWith(ext)))
|
|
97
|
+
return [name];
|
|
98
|
+
return exts.map((ext) => `${name}${ext}`);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Resolve a command to the absolute path the OS would run, or `null`.
|
|
102
|
+
*
|
|
103
|
+
* Honours the platform's PATH delimiter, the win32 `Path` spelling, and
|
|
104
|
+
* `PATHEXT`. A name containing a path separator is checked directly rather
|
|
105
|
+
* than searched for.
|
|
106
|
+
*
|
|
107
|
+
* @param name - Command name or path.
|
|
108
|
+
* @param opts - Platform, environment and executability overrides.
|
|
109
|
+
* @returns Absolute path of the first match, or `null`.
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* findOnPath('git'); // '/usr/bin/git' on Linux, 'C:\\Program Files\\Git\\cmd\\git.exe' on Windows
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export function findOnPath(name, opts = {}) {
|
|
116
|
+
const platform = opts.platform ?? process.platform;
|
|
117
|
+
const env = opts.env ?? process.env;
|
|
118
|
+
const pathApi = platform === 'win32' ? win32 : posix;
|
|
119
|
+
const isExecutable = opts.isExecutable ?? ((p) => defaultIsExecutable(p, platform));
|
|
120
|
+
const names = executableNames(name, { platform, env });
|
|
121
|
+
const hasSeparator = platform === 'win32' ? /[\\/]/.test(name) : name.includes('/');
|
|
122
|
+
const dirs = hasSeparator ? [''] : splitPathEnv(env[pathEnvKey(env, platform)], platform);
|
|
123
|
+
for (const dir of dirs) {
|
|
124
|
+
for (const candidateName of names) {
|
|
125
|
+
const candidate = dir ? pathApi.join(dir, candidateName) : candidateName;
|
|
126
|
+
if (isExecutable(candidate))
|
|
127
|
+
return pathApi.resolve(candidate);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Resolve how to run a shell command line on a platform.
|
|
134
|
+
*
|
|
135
|
+
* `/bin/sh -c` on POSIX; on win32 `%ComSpec%` (cmd.exe) with `/d /s /c` and
|
|
136
|
+
* the line quoted verbatim — the same resolution Node applies for
|
|
137
|
+
* `shell: true`, made explicit so every caller that runs user-authored
|
|
138
|
+
* command strings (worktree hooks, release build commands) shares one
|
|
139
|
+
* resolver and tests can pin the platform.
|
|
140
|
+
*
|
|
141
|
+
* @param command - Command line to run.
|
|
142
|
+
* @param opts - Platform and environment overrides.
|
|
143
|
+
* @returns The executable, its argv and the verbatim-arguments flag.
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const sh = shellInvocation('pnpm build');
|
|
147
|
+
* execFile(sh.file, sh.args, { windowsVerbatimArguments: sh.windowsVerbatimArguments });
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export function shellInvocation(command, opts = {}) {
|
|
151
|
+
const platform = opts.platform ?? process.platform;
|
|
152
|
+
if (platform !== 'win32') {
|
|
153
|
+
return { file: '/bin/sh', args: ['-c', command], windowsVerbatimArguments: false };
|
|
154
|
+
}
|
|
155
|
+
const env = opts.env ?? process.env;
|
|
156
|
+
const comSpecKey = Object.keys(env).find((key) => key.toUpperCase() === 'COMSPEC');
|
|
157
|
+
const file = (comSpecKey && env[comSpecKey]) || 'cmd.exe';
|
|
158
|
+
return { file, args: ['/d', '/s', '/c', `"${command}"`], windowsVerbatimArguments: true };
|
|
159
|
+
}
|
|
160
|
+
/** cmd.exe metacharacters; each is caret-escaped so cmd treats it literally. */
|
|
161
|
+
const CMD_META = /([()\][%!^"`<>&|;, *?])/g;
|
|
162
|
+
/**
|
|
163
|
+
* Quote one argument for a `.cmd`/`.bat` target launched through cmd.exe.
|
|
164
|
+
*
|
|
165
|
+
* Two layers, as cmd parses the line and the batch file's program parses its
|
|
166
|
+
* argv: MSVCRT quoting (backslashes before a quote doubled, the quote
|
|
167
|
+
* escaped, the whole argument wrapped in quotes), then every cmd
|
|
168
|
+
* metacharacter caret-escaped TWICE — cmd re-parses the line when it
|
|
169
|
+
* dispatches a batch file, consuming one caret layer each pass. Because every
|
|
170
|
+
* quote is escaped, cmd never sees a quoted region in which operators such as
|
|
171
|
+
* `&` or `|` would be live. `%VAR%` expands before carets are processed, but
|
|
172
|
+
* `%NAME^%` names a variable (`NAME^`) that is never defined, and an undefined
|
|
173
|
+
* reference is left verbatim on a `cmd /c` line. This is the scheme `cross-spawn` uses against the BatBadBut class
|
|
174
|
+
* (CVE-2024-27980).
|
|
175
|
+
*
|
|
176
|
+
* @param arg - Literal argument.
|
|
177
|
+
* @returns The escaped token.
|
|
178
|
+
* @throws When `arg` holds CR or LF: cmd.exe ends the command at a line
|
|
179
|
+
* break and no escape can carry one into a batch file.
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* quoteCmdArg('a b'); // '^^^"a^^^ b^^^"'
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
export function quoteCmdArg(arg) {
|
|
186
|
+
if (/[\r\n]/.test(arg))
|
|
187
|
+
throw new Error('E_UNSAFE_BATCH_ARG: a .cmd/.bat argument cannot contain a line break');
|
|
188
|
+
const msvcrt = `"${escapeMsvcrt(arg)}"`;
|
|
189
|
+
return msvcrt.replace(CMD_META, '^$1').replace(CMD_META, '^$1');
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* MSVCRT-escape an argument's body in ONE linear pass: a run of backslashes
|
|
193
|
+
* is doubled when it precedes a quote (the quote itself is then escaped) or
|
|
194
|
+
* the end of the argument, and kept as-is otherwise. The regex form
|
|
195
|
+
* `/(\\*)"/g` is quadratic on long backslash runs — the ReDoS class of
|
|
196
|
+
* cross-spawn's CVE-2024-21538 — and this input is untrusted prompt text.
|
|
197
|
+
*/
|
|
198
|
+
function escapeMsvcrt(arg) {
|
|
199
|
+
let out = '';
|
|
200
|
+
let slashes = 0;
|
|
201
|
+
for (const ch of arg) {
|
|
202
|
+
if (ch === '\\') {
|
|
203
|
+
slashes++;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (ch === '"') {
|
|
207
|
+
out += `${'\\'.repeat(slashes * 2)}\\"`;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
out += `${'\\'.repeat(slashes)}${ch}`;
|
|
211
|
+
}
|
|
212
|
+
slashes = 0;
|
|
213
|
+
}
|
|
214
|
+
return out + '\\'.repeat(slashes * 2);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Resolve how to spawn `command args` without a shell on any platform.
|
|
218
|
+
*
|
|
219
|
+
* POSIX: returned unchanged. win32: the command is resolved to the absolute
|
|
220
|
+
* path {@link findOnPath} finds, because Node's own lookup tries only `.exe`
|
|
221
|
+
* and `.com`. A `.cmd`/`.bat` target (every npm-installed CLI) cannot be
|
|
222
|
+
* spawned directly — Node refuses since CVE-2024-27980 — so it is launched
|
|
223
|
+
* through `%ComSpec% /d /s /c` with every token escaped by {@link quoteCmdArg}.
|
|
224
|
+
*
|
|
225
|
+
* @param command - Command name or path.
|
|
226
|
+
* @param args - Literal arguments.
|
|
227
|
+
* @param opts - Platform and environment overrides.
|
|
228
|
+
* @returns The spawnable invocation.
|
|
229
|
+
* @throws When a batch-file argument contains a line break (see {@link quoteCmdArg}).
|
|
230
|
+
* @example
|
|
231
|
+
* ```ts
|
|
232
|
+
* const inv = resolveSpawnInvocation('codex', ['--full-auto', promptFile]);
|
|
233
|
+
* spawn(inv.file, inv.args, { windowsVerbatimArguments: inv.windowsVerbatimArguments });
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
export function resolveSpawnInvocation(command, args, opts = {}) {
|
|
237
|
+
const platform = opts.platform ?? process.platform;
|
|
238
|
+
if (platform !== 'win32') {
|
|
239
|
+
return { file: command, args: [...args], windowsVerbatimArguments: false };
|
|
240
|
+
}
|
|
241
|
+
const resolved = findOnPath(command, opts) ?? command;
|
|
242
|
+
if (!/\.(cmd|bat)$/i.test(resolved)) {
|
|
243
|
+
return { file: resolved, args: [...args], windowsVerbatimArguments: false };
|
|
244
|
+
}
|
|
245
|
+
const line = [resolved.replace(CMD_META, '^$1'), ...args.map(quoteCmdArg)].join(' ');
|
|
246
|
+
const shell = shellInvocation(line, opts);
|
|
247
|
+
return { file: shell.file, args: shell.args, windowsVerbatimArguments: true };
|
|
248
|
+
}
|
|
249
|
+
/** Environment key for `PATHEXT`, matched case-insensitively. */
|
|
250
|
+
function pathExtKey(env) {
|
|
251
|
+
return Object.keys(env).find((key) => key.toUpperCase() === 'PATHEXT') ?? 'PATHEXT';
|
|
252
|
+
}
|
|
253
|
+
/** A regular file that the current user may execute (existence alone on win32). */
|
|
254
|
+
function defaultIsExecutable(candidate, platform) {
|
|
255
|
+
try {
|
|
256
|
+
if (!statSync(candidate).isFile())
|
|
257
|
+
return false;
|
|
258
|
+
if (platform !== 'win32')
|
|
259
|
+
accessSync(candidate, constants.X_OK);
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=exec-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-path.js","sourceRoot":"","sources":["../src/exec-path.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
* - Worktree primitives: {@link computeProjectHash},
|
|
15
15
|
* {@link resolveWorktreeRootForHash}, {@link resolveTaskWorktreePath},
|
|
16
16
|
* {@link getCleoWorktreesRoot}, {@link resolveWorktreeIndexPath}
|
|
17
|
+
* - {@link getCleoStateDir} — CLEO state dir (XDG state on Linux, `<cleoHome>/state` elsewhere)
|
|
18
|
+
* - {@link expandTildePath} — `~` expansion via `os.homedir()`
|
|
17
19
|
* - {@link isAbsolutePath} — cross-platform abs-path check
|
|
20
|
+
* - Executable search: {@link findOnPath}, {@link prependPathEntry},
|
|
21
|
+
* {@link splitPathEnv} (PATH delimiter + PATHEXT aware, T12605)
|
|
18
22
|
* - Portable identity: {@link readPortableProjectId} (tracked `.cleo/project-id`, T12325)
|
|
19
23
|
*
|
|
20
24
|
* @packageDocumentation
|
|
@@ -22,9 +26,10 @@
|
|
|
22
26
|
* @task T11008
|
|
23
27
|
*/
|
|
24
28
|
export { isAbsolutePath } from './abs-path.js';
|
|
25
|
-
export { _resetCleoPlatformPathsCache, canonicalizePath, computeCanonicalProjectId, getCanonicalTemplatesTildePath, getCleoHome, getCleoPlatformPaths, getCleoSystemInfo, getCleoTemplatesTildePath, legacyProjectId, type ResolvedProject, resolveCanonicalCleoDir, resolveLegacyCleoDir, resolveProjectByCwd, } from './cleo-paths.js';
|
|
29
|
+
export { _resetCleoPlatformPathsCache, canonicalizePath, computeCanonicalProjectId, computePathFingerprintId, type DeclaredProjectIdentity, getCanonicalTemplatesTildePath, getCleoHome, getCleoPlatformPaths, getCleoStateDir, getCleoSystemInfo, getCleoTemplatesTildePath, legacyAliasClaimants, legacyProjectId, type RecordedProjectPath, type ResolvedProject, readDeclaredProjectIdentity, resolveCanonicalCleoDir, resolveLegacyCleoDir, resolveProjectByCwd, resolveStableDeviceIdPath, } from './cleo-paths.js';
|
|
30
|
+
export { type ExecPathOptions, executableNames, findOnPath, pathDelimiterFor, pathEnvKey, prependPathEntry, quoteCmdArg, resolveSpawnInvocation, type ShellInvocation, type SpawnInvocation, shellInvocation, splitPathEnv, } from './exec-path.js';
|
|
26
31
|
export { type EnforceOptions, enforceNodeVersion, evaluateNodeVersion, FALLBACK_MIN_NODE, getRequiredNodeVersion, type NodeManager, type NodeVersionVerdict, parseSemver, type Semver, type UpgradeHint, } from './node-version-gate.js';
|
|
27
|
-
export { createPlatformPathsResolver, type PlatformPaths, type PlatformPathsResolver, type SystemInfo, } from './platform-paths.js';
|
|
32
|
+
export { createPlatformPathsResolver, expandTildePath, type PlatformPaths, type PlatformPathsResolver, type SystemInfo, } from './platform-paths.js';
|
|
28
33
|
export { formatPortableProjectId, isValidPortableProjectId, PORTABLE_PROJECT_ID_FILE, type PortableProjectIdRead, parsePortableProjectId, portableProjectIdPath, readPortableProjectId, } from './portable-project-id.js';
|
|
29
|
-
export { computeProjectHash, getCleoWorktreesRoot, resolveTaskWorktreePath, resolveWorktreeIndexPath, resolveWorktreeRootForHash, } from './worktree-paths.js';
|
|
34
|
+
export { computeProjectHash, getCleoWorktreesRoot, resolveTaskWorktreePath, resolveWorktreeIndexPath, resolveWorktreeRootForHash, resolveWorktreeTaskLockPath, } from './worktree-paths.js';
|
|
30
35
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,4BAA4B,EAC5B,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,8BAA8B,EAC9B,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EACf,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,eAAe,EACpB,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,cAAc,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,WAAW,EACX,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,qBAAqB,EAC1B,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
* - Worktree primitives: {@link computeProjectHash},
|
|
15
15
|
* {@link resolveWorktreeRootForHash}, {@link resolveTaskWorktreePath},
|
|
16
16
|
* {@link getCleoWorktreesRoot}, {@link resolveWorktreeIndexPath}
|
|
17
|
+
* - {@link getCleoStateDir} — CLEO state dir (XDG state on Linux, `<cleoHome>/state` elsewhere)
|
|
18
|
+
* - {@link expandTildePath} — `~` expansion via `os.homedir()`
|
|
17
19
|
* - {@link isAbsolutePath} — cross-platform abs-path check
|
|
20
|
+
* - Executable search: {@link findOnPath}, {@link prependPathEntry},
|
|
21
|
+
* {@link splitPathEnv} (PATH delimiter + PATHEXT aware, T12605)
|
|
18
22
|
* - Portable identity: {@link readPortableProjectId} (tracked `.cleo/project-id`, T12325)
|
|
19
23
|
*
|
|
20
24
|
* @packageDocumentation
|
|
@@ -22,9 +26,10 @@
|
|
|
22
26
|
* @task T11008
|
|
23
27
|
*/
|
|
24
28
|
export { isAbsolutePath } from './abs-path.js';
|
|
25
|
-
export { _resetCleoPlatformPathsCache, canonicalizePath, computeCanonicalProjectId, getCanonicalTemplatesTildePath, getCleoHome, getCleoPlatformPaths, getCleoSystemInfo, getCleoTemplatesTildePath, legacyProjectId, resolveCanonicalCleoDir, resolveLegacyCleoDir, resolveProjectByCwd, } from './cleo-paths.js';
|
|
29
|
+
export { _resetCleoPlatformPathsCache, canonicalizePath, computeCanonicalProjectId, computePathFingerprintId, getCanonicalTemplatesTildePath, getCleoHome, getCleoPlatformPaths, getCleoStateDir, getCleoSystemInfo, getCleoTemplatesTildePath, legacyAliasClaimants, legacyProjectId, readDeclaredProjectIdentity, resolveCanonicalCleoDir, resolveLegacyCleoDir, resolveProjectByCwd, resolveStableDeviceIdPath, } from './cleo-paths.js';
|
|
30
|
+
export { executableNames, findOnPath, pathDelimiterFor, pathEnvKey, prependPathEntry, quoteCmdArg, resolveSpawnInvocation, shellInvocation, splitPathEnv, } from './exec-path.js';
|
|
26
31
|
export { enforceNodeVersion, evaluateNodeVersion, FALLBACK_MIN_NODE, getRequiredNodeVersion, parseSemver, } from './node-version-gate.js';
|
|
27
|
-
export { createPlatformPathsResolver, } from './platform-paths.js';
|
|
32
|
+
export { createPlatformPathsResolver, expandTildePath, } from './platform-paths.js';
|
|
28
33
|
export { formatPortableProjectId, isValidPortableProjectId, PORTABLE_PROJECT_ID_FILE, parsePortableProjectId, portableProjectIdPath, readPortableProjectId, } from './portable-project-id.js';
|
|
29
|
-
export { computeProjectHash, getCleoWorktreesRoot, resolveTaskWorktreePath, resolveWorktreeIndexPath, resolveWorktreeRootForHash, } from './worktree-paths.js';
|
|
34
|
+
export { computeProjectHash, getCleoWorktreesRoot, resolveTaskWorktreePath, resolveWorktreeIndexPath, resolveWorktreeRootForHash, resolveWorktreeTaskLockPath, } from './worktree-paths.js';
|
|
30
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,4BAA4B,EAC5B,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EAExB,8BAA8B,EAC9B,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,eAAe,EAGf,2BAA2B,EAC3B,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,sBAAsB,EAGtB,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAEL,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EAGtB,WAAW,GAGZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,2BAA2B,EAC3B,eAAe,GAIhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EAExB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC"}
|
package/dist/platform-paths.d.ts
CHANGED
|
@@ -89,6 +89,27 @@ export interface PlatformPathsResolver {
|
|
|
89
89
|
*/
|
|
90
90
|
resetCache(): void;
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Expand a leading `~` in a user-supplied path to the user's home directory.
|
|
94
|
+
*
|
|
95
|
+
* Uses `os.homedir()`, which reads `USERPROFILE` on Windows — unlike
|
|
96
|
+
* `process.env.HOME`, which is unset there and turns `~/x` into the relative
|
|
97
|
+
* path `x`. Accepts `~`, `~/x`, and on Windows `~\x`. Any other input,
|
|
98
|
+
* including `~user/x`, is returned unchanged.
|
|
99
|
+
*
|
|
100
|
+
* @param path - Path that may start with `~`.
|
|
101
|
+
* @param home - Home directory to expand into. Defaults to `os.homedir()`.
|
|
102
|
+
* @returns The expanded path, or `path` unchanged when it has no leading `~`.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* expandTildePath('~/.pi/x.cant'); // "/home/me/.pi/x.cant" on Linux
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @public
|
|
110
|
+
* @task T12608
|
|
111
|
+
*/
|
|
112
|
+
export declare function expandTildePath(path: string, home?: string): string;
|
|
92
113
|
/**
|
|
93
114
|
* Create a platform-paths resolver bound to a specific app name and home env var.
|
|
94
115
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-paths.d.ts","sourceRoot":"","sources":["../src/platform-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,gBAAgB,IAAI,aAAa,CAAC;IAElC;;;;;OAKG;IACH,aAAa,IAAI,UAAU,CAAC;IAE5B;;;;;OAKG;IACH,UAAU,IAAI,IAAI,CAAC;CACpB;AAqBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,qBAAqB,CAyCvB"}
|
|
1
|
+
{"version":3,"file":"platform-paths.d.ts","sourceRoot":"","sources":["../src/platform-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,gBAAgB,IAAI,aAAa,CAAC;IAElC;;;;;OAKG;IACH,aAAa,IAAI,UAAU,CAAC;IAE5B;;;;;OAKG;IACH,UAAU,IAAI,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,MAAM,CAK9E;AAqBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,qBAAqB,CAyCvB"}
|
package/dist/platform-paths.js
CHANGED
|
@@ -18,6 +18,32 @@
|
|
|
18
18
|
import { arch, homedir, hostname, platform, release } from 'node:os';
|
|
19
19
|
import { isAbsolute, join } from 'node:path';
|
|
20
20
|
import envPaths from 'env-paths';
|
|
21
|
+
/**
|
|
22
|
+
* Expand a leading `~` in a user-supplied path to the user's home directory.
|
|
23
|
+
*
|
|
24
|
+
* Uses `os.homedir()`, which reads `USERPROFILE` on Windows — unlike
|
|
25
|
+
* `process.env.HOME`, which is unset there and turns `~/x` into the relative
|
|
26
|
+
* path `x`. Accepts `~`, `~/x`, and on Windows `~\x`. Any other input,
|
|
27
|
+
* including `~user/x`, is returned unchanged.
|
|
28
|
+
*
|
|
29
|
+
* @param path - Path that may start with `~`.
|
|
30
|
+
* @param home - Home directory to expand into. Defaults to `os.homedir()`.
|
|
31
|
+
* @returns The expanded path, or `path` unchanged when it has no leading `~`.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* expandTildePath('~/.pi/x.cant'); // "/home/me/.pi/x.cant" on Linux
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
* @task T12608
|
|
40
|
+
*/
|
|
41
|
+
export function expandTildePath(path, home = homedir()) {
|
|
42
|
+
if (path === '~')
|
|
43
|
+
return home;
|
|
44
|
+
const separatorAfterTilde = path.startsWith('~/') || (process.platform === 'win32' && path.startsWith('~\\'));
|
|
45
|
+
return separatorAfterTilde ? join(home, path.slice(2)) : path;
|
|
46
|
+
}
|
|
21
47
|
/**
|
|
22
48
|
* Normalize a home-override env var value to an absolute path.
|
|
23
49
|
*
|
|
@@ -33,10 +59,9 @@ function resolveHomeOverride(value) {
|
|
|
33
59
|
const trimmed = value.trim();
|
|
34
60
|
if (trimmed.length === 0)
|
|
35
61
|
return undefined;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return join(homedir(), trimmed.slice(2));
|
|
62
|
+
const expanded = expandTildePath(trimmed);
|
|
63
|
+
if (expanded !== trimmed)
|
|
64
|
+
return expanded;
|
|
40
65
|
if (isAbsolute(trimmed))
|
|
41
66
|
return trimmed;
|
|
42
67
|
return join(homedir(), trimmed);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-paths.js","sourceRoot":"","sources":["../src/platform-paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,QAAQ,MAAM,WAAW,CAAC;AAiFjC
|
|
1
|
+
{"version":3,"file":"platform-paths.js","sourceRoot":"","sources":["../src/platform-paths.ts"],"names":[],"mappings":"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"}
|