@wirecat/cli-core 0.19.3 → 0.20.0
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/README.md +1 -1
- package/config/wirecat/lefthook.yml +1 -9
- package/config/wirecat/manifest.json +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/legacy-paths.d.ts +33 -0
- package/dist/legacy-paths.d.ts.map +1 -0
- package/dist/legacy-paths.js +128 -0
- package/dist/legacy-paths.js.map +1 -0
- package/dist/paths.d.ts +11 -4
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +37 -15
- package/dist/paths.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ streams.stderr // []
|
|
|
41
41
|
| `createDeadline` | cooperative command cancellation with injected sleep and a parent abort signal |
|
|
42
42
|
| `time` | monotonic and wall clocks, and the one sleep that both timeouts and backoff use |
|
|
43
43
|
| `logger` | the four-method interface a host adapts Pino to — this package logs nothing itself |
|
|
44
|
-
| `paths` |
|
|
44
|
+
| `paths` | config, state and cache in the XDG layout on Linux and macOS (`~/.config`, `~/.local/share`, `~/.cache`) and the `AppData` one on Windows, each overridable by environment variable; `migrateLegacyMacPaths` moves an older release's `~/Library` folders once |
|
|
45
45
|
| `config` | JSON config loading that names the bad field, and an atomic write that locks the directory down |
|
|
46
46
|
| `credentials` | environment → keyring → file, warning once and falling through when the keyring refuses |
|
|
47
47
|
| `logging` | a Pino adapter writing JSON lines with secrets redacted by field name; a file that cannot be written is reported to `onError`, never thrown |
|
|
@@ -12,7 +12,7 @@ pre-commit:
|
|
|
12
12
|
glob: "*.{ts,tsx,js,mjs,cjs,json,jsonc}"
|
|
13
13
|
# Staged files only. The whole-repo run is the CI gate; running it per-commit is how people
|
|
14
14
|
# end up reaching for --no-verify, which is worse than no hook.
|
|
15
|
-
run:
|
|
15
|
+
run: node node_modules/@biomejs/biome/bin/biome check --no-errors-on-unmatched --files-ignore-unknown=true {staged_files}
|
|
16
16
|
|
|
17
17
|
gitleaks:
|
|
18
18
|
# Staged content only, and it warns rather than blocks when gitleaks is not installed: a
|
|
@@ -24,11 +24,3 @@ pre-commit:
|
|
|
24
24
|
echo "gitleaks is not installed — staged changes were NOT scanned for secrets."
|
|
25
25
|
echo " install: https://github.com/gitleaks/gitleaks#installing (CI scans regardless)"
|
|
26
26
|
fi
|
|
27
|
-
|
|
28
|
-
pre-push:
|
|
29
|
-
parallel: true
|
|
30
|
-
commands:
|
|
31
|
-
typecheck:
|
|
32
|
-
# A messaging CLI's parity check builds into the same dist/ as typecheck, so it runs here, after
|
|
33
|
-
# it, rather than as a command of its own beside it. A project without the script skips it.
|
|
34
|
-
run: pnpm -s run --if-present typecheck && pnpm -s run --if-present parity:check
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "https://github.com/WireCatLabs/community",
|
|
3
|
-
"revision": "
|
|
3
|
+
"revision": "5d00ac9d7e80eeedb4ec4c3c6748ad2ccf2af657",
|
|
4
4
|
"files": {
|
|
5
5
|
"biome.base.json": "83a43910f2530e21d720e3ad4c3fc7fcb16ba36253c6dbc720b3c68a4dd80893",
|
|
6
6
|
"cspell.json": "8241122ed4d461976a838099b265ef8f2689a066608257b6fdc250d9b49b58aa",
|
|
7
|
-
"lefthook.yml": "
|
|
7
|
+
"lefthook.yml": "2f65a2e3103006d43f6d6f0a07ab333c132286157763222a59a5a22676acd391",
|
|
8
8
|
"markdownlint.json": "5ed7d6980054c539f3f3c0e47a090f1a725b15be2c486a769a836bc6cd48ad2d",
|
|
9
9
|
"rumdl.toml": "048b929176f13234324f5825d1e811397f1491b9cb6684a1953e268e2c2ed863",
|
|
10
10
|
"check.mjs": "34b266411eaab7707030915f645308e86784b1574b21fa44ca974861a90c9ce1"
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { createDeadline, type Deadline, type DeadlineOptions } from "./deadline.
|
|
|
5
5
|
export { CliError, type CliErrorDetails, type ErrorCode, errorCodes, isCliError } from "./errors.js";
|
|
6
6
|
export { EXIT_CODES, exitCodeFor, GENERIC_FAILURE } from "./exit-codes.js";
|
|
7
7
|
export { brokenKeyring, type KeyringStore, memoryKeyring, systemKeyring } from "./keyring.js";
|
|
8
|
+
export { type LegacyMove, legacyMacPaths, type MigrateLegacyPathsOptions, migrateLegacyMacPaths, } from "./legacy-paths.js";
|
|
8
9
|
export { type Logger, noopLogger } from "./logger.js";
|
|
9
10
|
export { createFileLogger, type FileLogger, type FileLoggerOptions, REDACTED_FIELDS } from "./logging.js";
|
|
10
11
|
export { createOutputBuffer, type OutputBuffer, type OutputBufferOptions } from "./output-buffer.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACjH,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AACnF,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7F,OAAO,EAAE,KAAK,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACpG,OAAO,EAAE,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC5G,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EACL,cAAc,EACd,cAAc,EACd,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3E,OAAO,EACL,UAAU,EACV,KAAK,cAAc,EACnB,SAAS,EACT,SAAS,EACT,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,SAAS,GACV,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACjH,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClF,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AACnF,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7F,OAAO,EACL,KAAK,UAAU,EACf,cAAc,EACd,KAAK,yBAAyB,EAC9B,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,KAAK,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACpG,OAAO,EAAE,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC5G,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EACL,cAAc,EACd,cAAc,EACd,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3E,OAAO,EACL,UAAU,EACV,KAAK,cAAc,EACnB,SAAS,EACT,SAAS,EACT,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,SAAS,GACV,MAAM,WAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { createDeadline } from "./deadline.js";
|
|
|
4
4
|
export { CliError, errorCodes, isCliError } from "./errors.js";
|
|
5
5
|
export { EXIT_CODES, exitCodeFor, GENERIC_FAILURE } from "./exit-codes.js";
|
|
6
6
|
export { brokenKeyring, memoryKeyring, systemKeyring } from "./keyring.js";
|
|
7
|
+
export { legacyMacPaths, migrateLegacyMacPaths, } from "./legacy-paths.js";
|
|
7
8
|
export { noopLogger } from "./logger.js";
|
|
8
9
|
export { createFileLogger, REDACTED_FIELDS } from "./logging.js";
|
|
9
10
|
export { createOutputBuffer } from "./output-buffer.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClF,OAAO,EAAE,cAAc,EAAuC,MAAM,eAAe,CAAA;AACnF,OAAO,EAAE,QAAQ,EAAwC,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAqB,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7F,OAAO,EAAe,UAAU,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAA2C,eAAe,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,kBAAkB,EAA+C,MAAM,oBAAoB,CAAA;AACpG,OAAO,EAAE,cAAc,EAAiC,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC5G,OAAO,EAAE,MAAM,EAAsB,YAAY,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EACL,cAAc,EACd,cAAc,GAIf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAoB,MAAM,YAAY,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAgB,MAAM,cAAc,CAAA;AAC3E,OAAO,EACL,UAAU,EAEV,SAAS,EACT,SAAS,EAIT,SAAS,GACV,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAClF,OAAO,EAAE,cAAc,EAAuC,MAAM,eAAe,CAAA;AACnF,OAAO,EAAE,QAAQ,EAAwC,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACpG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAqB,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC7F,OAAO,EAEL,cAAc,EAEd,qBAAqB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAe,UAAU,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAA2C,eAAe,EAAE,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,kBAAkB,EAA+C,MAAM,oBAAoB,CAAA;AACpG,OAAO,EAAE,cAAc,EAAiC,kBAAkB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC5G,OAAO,EAAE,MAAM,EAAsB,YAAY,EAAE,MAAM,aAAa,CAAA;AACtE,OAAO,EACL,cAAc,EACd,cAAc,GAIf,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAoB,MAAM,YAAY,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAgB,MAAM,cAAc,CAAA;AAC3E,OAAO,EACL,UAAU,EAEV,SAAS,EACT,SAAS,EAIT,SAAS,GACV,MAAM,WAAW,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Paths, type PathsOptions } from "./paths.js";
|
|
2
|
+
export interface LegacyMove {
|
|
3
|
+
kind: keyof Paths;
|
|
4
|
+
from: string;
|
|
5
|
+
to: string;
|
|
6
|
+
/** Copied across file systems rather than renamed: the old folder is still there. */
|
|
7
|
+
copied: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface MigrateLegacyPathsOptions extends PathsOptions {
|
|
10
|
+
rename?: (from: string, to: string) => void;
|
|
11
|
+
/** The processes, as text, that hold files under `dirs` open; empty when none does. Defaults to lsof. */
|
|
12
|
+
holders?: (dirs: string[]) => string[];
|
|
13
|
+
}
|
|
14
|
+
/** Where `env-paths` put each directory on macOS, before this package switched to XDG there. */
|
|
15
|
+
export declare const legacyMacPaths: (appName: string, env?: NodeJS.ProcessEnv) => Paths;
|
|
16
|
+
declare const runLsof: (args: string[]) => string;
|
|
17
|
+
/**
|
|
18
|
+
* Only files open right now: a file written by path and closed again, like a lock or a journal,
|
|
19
|
+
* is invisible here, so a caller that knows its own lock files should add them through `holders`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const lsofHolders: (dirs: string[], run?: typeof runLsof) => string[];
|
|
22
|
+
/**
|
|
23
|
+
* Moves the folders an earlier release kept under `~/Library` to the XDG ones `resolvePaths` now
|
|
24
|
+
* gives on macOS. Call it once at program start, before anything resolves a path — a write that
|
|
25
|
+
* creates the new folder first would leave the old data behind for good.
|
|
26
|
+
*
|
|
27
|
+
* It moves all pending folders or none, and throws when `holders` (lsof by default) shows a file
|
|
28
|
+
* open in any of them: a running `serve` keeps writing into the folder it opened, and data it
|
|
29
|
+
* writes after the move is lost. Cheap when there is nothing to do: one `lstat` per folder.
|
|
30
|
+
*/
|
|
31
|
+
export declare const migrateLegacyMacPaths: (options: MigrateLegacyPathsOptions) => LegacyMove[];
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=legacy-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-paths.d.ts","sourceRoot":"","sources":["../src/legacy-paths.ts"],"names":[],"mappings":"AAKA,OAAO,EAAc,KAAK,KAAK,EAAE,KAAK,YAAY,EAAoC,MAAM,YAAY,CAAA;AAExG,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,KAAK,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,qFAAqF;IACrF,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,yBAA0B,SAAQ,YAAY;IAC7D,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,yGAAyG;IACzG,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;CACvC;AAED,gGAAgG;AAChG,eAAO,MAAM,cAAc,YAAa,MAAM,QAAO,MAAM,CAAC,UAAU,KAAiB,KAOtF,CAAA;AAkBD,QAAA,MAAM,OAAO,SAAU,MAAM,EAAE,WAAmF,CAAA;AAElH;;;GAGG;AACH,eAAO,MAAM,WAAW,SAAU,MAAM,EAAE,2BAAkB,MAAM,EAoB9D,CAAA;AAiCJ;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,YAAa,yBAAyB,KAAG,UAAU,EAmDpF,CAAA"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { cpSync, lstatSync, mkdirSync, readdirSync, renameSync, rmSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join, relative } from "node:path";
|
|
5
|
+
import { CliError } from "./errors.js";
|
|
6
|
+
import { PATH_KINDS, pathsAreOverridden, resolvePaths } from "./paths.js";
|
|
7
|
+
/** Where `env-paths` put each directory on macOS, before this package switched to XDG there. */
|
|
8
|
+
export const legacyMacPaths = (appName, env = process.env) => {
|
|
9
|
+
const library = join(env.HOME || homedir(), "Library");
|
|
10
|
+
return {
|
|
11
|
+
config: join(library, "Preferences", appName),
|
|
12
|
+
state: join(library, "Application Support", appName),
|
|
13
|
+
cache: join(library, "Caches", appName),
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
const kindOf = (path) => {
|
|
17
|
+
try {
|
|
18
|
+
return lstatSync(path).isDirectory() ? "dir" : "other";
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return "none";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const isFreeTarget = (path) => {
|
|
25
|
+
const kind = kindOf(path);
|
|
26
|
+
return kind === "none" || (kind === "dir" && readdirSync(path).length === 0);
|
|
27
|
+
};
|
|
28
|
+
// An absolute path: an MCP host may start the CLI with a PATH that has no /usr/sbin.
|
|
29
|
+
const LSOF = "/usr/sbin/lsof";
|
|
30
|
+
const runLsof = (args) => execFileSync(LSOF, args, { encoding: "utf8", timeout: 30_000, stdio: "pipe" });
|
|
31
|
+
/**
|
|
32
|
+
* Only files open right now: a file written by path and closed again, like a lock or a journal,
|
|
33
|
+
* is invisible here, so a caller that knows its own lock files should add them through `holders`.
|
|
34
|
+
*/
|
|
35
|
+
export const lsofHolders = (dirs, run = runLsof) => dirs.flatMap((dir) => {
|
|
36
|
+
let listed;
|
|
37
|
+
try {
|
|
38
|
+
listed = run(["-t", "+D", dir]);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
// lsof exits 1 both when nothing is open and when it hit a warning; the PIDs are on stdout either way.
|
|
42
|
+
const failure = error;
|
|
43
|
+
if (failure.status !== 1)
|
|
44
|
+
throw new CliError("configuration_error", `could not check whether a process has files open in ${dir}, so nothing was moved: ${failure.message}. ` +
|
|
45
|
+
`Run \`lsof +D "${dir}"\`, stop what it lists, and run the command again.`);
|
|
46
|
+
listed = failure.stdout ?? "";
|
|
47
|
+
}
|
|
48
|
+
return listed
|
|
49
|
+
.split("\n")
|
|
50
|
+
.filter((pid) => pid && pid !== String(process.pid))
|
|
51
|
+
.map((pid) => `pid ${pid} (${dir})`);
|
|
52
|
+
});
|
|
53
|
+
const listTree = (root) => readdirSync(root, { recursive: true, withFileTypes: true })
|
|
54
|
+
.map((entry) => {
|
|
55
|
+
const path = join(entry.parentPath, entry.name);
|
|
56
|
+
const stat = lstatSync(path);
|
|
57
|
+
return `${relative(root, path)}:${stat.isDirectory() ? "dir" : stat.size}`;
|
|
58
|
+
})
|
|
59
|
+
.sort();
|
|
60
|
+
/**
|
|
61
|
+
* A copy goes to a sibling first and is renamed in only once checked: a half-written folder at
|
|
62
|
+
* the new path would read as "already migrated" on the next start and hide the old data for good.
|
|
63
|
+
*/
|
|
64
|
+
const copyInto = (from, to) => {
|
|
65
|
+
const draft = `${to}.migrating-${process.pid}`;
|
|
66
|
+
try {
|
|
67
|
+
cpSync(from, draft, { recursive: true, preserveTimestamps: true, verbatimSymlinks: true, errorOnExist: true });
|
|
68
|
+
if (listTree(from).join("\n") !== listTree(draft).join("\n"))
|
|
69
|
+
throw new Error("the copy differs from the original");
|
|
70
|
+
renameSync(draft, to);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
rmSync(draft, { recursive: true, force: true });
|
|
74
|
+
throw new CliError("configuration_error", `could not copy ${from} to ${to}, nothing moved: ${error.message}`);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
// Two CLIs starting together can race for the same folder, e.g. the shared store under cli-messaging.
|
|
78
|
+
const movedByAnother = (from, to) => kindOf(from) === "none" || !isFreeTarget(to);
|
|
79
|
+
/**
|
|
80
|
+
* Moves the folders an earlier release kept under `~/Library` to the XDG ones `resolvePaths` now
|
|
81
|
+
* gives on macOS. Call it once at program start, before anything resolves a path — a write that
|
|
82
|
+
* creates the new folder first would leave the old data behind for good.
|
|
83
|
+
*
|
|
84
|
+
* It moves all pending folders or none, and throws when `holders` (lsof by default) shows a file
|
|
85
|
+
* open in any of them: a running `serve` keeps writing into the folder it opened, and data it
|
|
86
|
+
* writes after the move is lost. Cheap when there is nothing to do: one `lstat` per folder.
|
|
87
|
+
*/
|
|
88
|
+
export const migrateLegacyMacPaths = (options) => {
|
|
89
|
+
const { appName, env = process.env, platform = process.platform, rename = renameSync, holders = lsofHolders, } = options;
|
|
90
|
+
if (platform !== "darwin" || pathsAreOverridden(options))
|
|
91
|
+
return [];
|
|
92
|
+
const legacy = legacyMacPaths(appName, env);
|
|
93
|
+
const current = resolvePaths({ ...options, env, platform });
|
|
94
|
+
const pending = PATH_KINDS.filter((kind) => legacy[kind] !== current[kind] &&
|
|
95
|
+
kindOf(legacy[kind]) === "dir" &&
|
|
96
|
+
readdirSync(legacy[kind]).length > 0 &&
|
|
97
|
+
isFreeTarget(current[kind]));
|
|
98
|
+
if (pending.length === 0)
|
|
99
|
+
return [];
|
|
100
|
+
const busy = holders(pending.map((kind) => legacy[kind]));
|
|
101
|
+
if (busy.length > 0)
|
|
102
|
+
throw new CliError("configuration_error", `${appName} now keeps its files outside ~/Library and must move ${pending.map((kind) => legacy[kind]).join(", ")} ` +
|
|
103
|
+
`to ${pending.map((kind) => current[kind]).join(", ")}, but another process has files there open ` +
|
|
104
|
+
`(${busy.join(", ")}). Stop it — a running \`serve\` or MCP server — and run the command again.`, { busy });
|
|
105
|
+
const moves = [];
|
|
106
|
+
for (const kind of pending) {
|
|
107
|
+
const from = legacy[kind];
|
|
108
|
+
const to = current[kind];
|
|
109
|
+
mkdirSync(dirname(to), { recursive: true });
|
|
110
|
+
try {
|
|
111
|
+
rename(from, to);
|
|
112
|
+
moves.push({ kind, from, to, copied: false });
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error.code === "EXDEV") {
|
|
116
|
+
copyInto(from, to);
|
|
117
|
+
moves.push({ kind, from, to, copied: true });
|
|
118
|
+
}
|
|
119
|
+
else if (!movedByAnother(from, to)) {
|
|
120
|
+
throw new CliError("configuration_error", `could not move ${from} to ${to}: ${error.message}`, {
|
|
121
|
+
moved: moves,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return moves;
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=legacy-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-paths.js","sourceRoot":"","sources":["../src/legacy-paths.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
CHANGED
|
@@ -15,13 +15,20 @@ export interface PathsOptions {
|
|
|
15
15
|
*/
|
|
16
16
|
prefix?: string;
|
|
17
17
|
env?: NodeJS.ProcessEnv;
|
|
18
|
+
platform?: NodeJS.Platform;
|
|
18
19
|
}
|
|
20
|
+
export declare const PATH_KINDS: readonly ["config", "state", "cache"];
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
22
|
+
* The XDG layout on macOS too: a CLI user expects `~/.config`, and one layout is one set of docs.
|
|
23
|
+
* Windows keeps the layout `env-paths` gave it, so nothing there moves. Everything is read from
|
|
24
|
+
* `env`, never the global one, so a test can point every directory at a temp folder.
|
|
23
25
|
*/
|
|
24
|
-
export declare const
|
|
26
|
+
export declare const defaultPaths: ({ appName, env, platform }: PathsOptions) => Paths;
|
|
27
|
+
/**
|
|
28
|
+
* Each directory is overridable by environment variable, which is what makes a test — and a
|
|
29
|
+
* throwaway profile — possible without touching the real ones.
|
|
30
|
+
*/
|
|
31
|
+
export declare const resolvePaths: (options: PathsOptions) => Paths;
|
|
25
32
|
/** Whether any of the three directories came from the environment rather than the OS convention. */
|
|
26
33
|
export declare const pathsAreOverridden: ({ appName, prefix, env }: PathsOptions) => boolean;
|
|
27
34
|
export declare const configFilePath: (configDir: string, fileName?: string) => string;
|
package/dist/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,KAAK;IACpB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,KAAK;IACpB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;CAC3B;AAED,eAAO,MAAM,UAAU,YAAI,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAU,CAAA;AAM/D;;;;GAIG;AACH,eAAO,MAAM,YAAY,+BAAiE,YAAY,KAAG,KAiBxG,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,YAAa,YAAY,KAAG,KAQpD,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,6BAA4C,YAAY,KAAG,OACP,CAAA;AAEnF,eAAO,MAAM,cAAc,cAAe,MAAM,wBAA6B,MAAmC,CAAA"}
|
package/dist/paths.js
CHANGED
|
@@ -1,23 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join, posix, win32 } from "node:path";
|
|
3
|
+
export const PATH_KINDS = ["config", "state", "cache"];
|
|
4
|
+
const OVERRIDES = { config: "CONFIG_DIR", state: "STATE_DIR", cache: "CACHE_DIR" };
|
|
5
|
+
const overrideName = (appName, prefix, kind) => `${prefix ?? appName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_${OVERRIDES[kind]}`;
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
+
* The XDG layout on macOS too: a CLI user expects `~/.config`, and one layout is one set of docs.
|
|
8
|
+
* Windows keeps the layout `env-paths` gave it, so nothing there moves. Everything is read from
|
|
9
|
+
* `env`, never the global one, so a test can point every directory at a temp folder.
|
|
7
10
|
*/
|
|
8
|
-
export const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
export const defaultPaths = ({ appName, env = process.env, platform = process.platform }) => {
|
|
12
|
+
if (platform === "win32") {
|
|
13
|
+
const home = env.USERPROFILE || homedir();
|
|
14
|
+
const roaming = env.APPDATA || win32.join(home, "AppData", "Roaming");
|
|
15
|
+
const local = env.LOCALAPPDATA || win32.join(home, "AppData", "Local");
|
|
16
|
+
return {
|
|
17
|
+
config: win32.join(roaming, appName, "Config"),
|
|
18
|
+
state: win32.join(local, appName, "Data"),
|
|
19
|
+
cache: win32.join(local, appName, "Cache"),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const home = env.HOME || homedir();
|
|
11
23
|
return {
|
|
12
|
-
config: env
|
|
13
|
-
state: env
|
|
14
|
-
cache: env
|
|
24
|
+
config: posix.join(env.XDG_CONFIG_HOME || posix.join(home, ".config"), appName),
|
|
25
|
+
state: posix.join(env.XDG_DATA_HOME || posix.join(home, ".local", "share"), appName),
|
|
26
|
+
cache: posix.join(env.XDG_CACHE_HOME || posix.join(home, ".cache"), appName),
|
|
15
27
|
};
|
|
16
28
|
};
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Each directory is overridable by environment variable, which is what makes a test — and a
|
|
31
|
+
* throwaway profile — possible without touching the real ones.
|
|
32
|
+
*/
|
|
33
|
+
export const resolvePaths = (options) => {
|
|
34
|
+
const { appName, prefix, env = process.env } = options;
|
|
35
|
+
const base = defaultPaths(options);
|
|
36
|
+
return {
|
|
37
|
+
config: env[overrideName(appName, prefix, "config")] ?? base.config,
|
|
38
|
+
state: env[overrideName(appName, prefix, "state")] ?? base.state,
|
|
39
|
+
cache: env[overrideName(appName, prefix, "cache")] ?? base.cache,
|
|
40
|
+
};
|
|
21
41
|
};
|
|
42
|
+
/** Whether any of the three directories came from the environment rather than the OS convention. */
|
|
43
|
+
export const pathsAreOverridden = ({ appName, prefix, env = process.env }) => PATH_KINDS.some((kind) => env[overrideName(appName, prefix, kind)] !== undefined);
|
|
22
44
|
export const configFilePath = (configDir, fileName = "config.json") => join(configDir, fileName);
|
|
23
45
|
//# sourceMappingURL=paths.js.map
|
package/dist/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAuB9C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAU,CAAA;AAC/D,MAAM,SAAS,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAW,CAAA;AAE3F,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,MAA0B,EAAE,IAAiB,EAAE,EAAE,CACtF,GAAG,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAA;AAEpF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAgB,EAAS,EAAE;IAC/G,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,IAAI,OAAO,EAAE,CAAA;QACzC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;QACrE,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;QACtE,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC;YAC9C,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;YACzC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC;SAC3C,CAAA;IACH,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,OAAO,EAAE,CAAA;IAClC,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAC/E,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QACpF,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;KAC7E,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAqB,EAAS,EAAE;IAC3D,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,CAAA;IACtD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAA;IAClC,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM;QACnE,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK;QAChE,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK;KACjE,CAAA;AACH,CAAC,CAAA;AAED,oGAAoG;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAgB,EAAW,EAAE,CAClG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;AAEnF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAAiB,EAAE,QAAQ,GAAG,aAAa,EAAU,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "The parts every command line tool needs: output modes, terminal rendering, error model, exit codes, credentials, clocks",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -90,12 +90,12 @@
|
|
|
90
90
|
"prepublishOnly": "pnpm build",
|
|
91
91
|
"standards:check": "node config/wirecat/check.mjs",
|
|
92
92
|
"docs:lint": "markdownlint-cli2",
|
|
93
|
-
"docs:spell": "cspell lint --config cspell.json --no-progress README.md"
|
|
93
|
+
"docs:spell": "cspell lint --config cspell.json --no-progress README.md",
|
|
94
|
+
"ci:quick": "pnpm typecheck"
|
|
94
95
|
},
|
|
95
96
|
"dependencies": {
|
|
96
97
|
"cli-table3": "^0.6.5",
|
|
97
98
|
"cross-spawn": "7.0.6",
|
|
98
|
-
"env-paths": "^4.0.0",
|
|
99
99
|
"picocolors": "^1.1.1",
|
|
100
100
|
"pino": "^10.3.1",
|
|
101
101
|
"valibot": "^1.5.0"
|
|
@@ -105,18 +105,18 @@
|
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
107
|
"@biomejs/biome": "2.5.15",
|
|
108
|
+
"@cspell/dict-en-gb": "5.0.34",
|
|
109
|
+
"@cspell/dict-es-es": "3.0.9",
|
|
110
|
+
"@cspell/dict-ru_ru": "2.3.3",
|
|
108
111
|
"@types/cross-spawn": "6.0.6",
|
|
109
112
|
"@types/node": "^22.20.4",
|
|
110
113
|
"@vitest/coverage-v8": "^5.0.2",
|
|
111
114
|
"commander": "^15.0.0",
|
|
115
|
+
"cspell": "10.3.6",
|
|
112
116
|
"lefthook": "2.1.16",
|
|
117
|
+
"markdownlint-cli2": "0.23.3",
|
|
113
118
|
"typescript": "^7.0.2",
|
|
114
|
-
"vitest": "^5.0.2"
|
|
115
|
-
"@cspell/dict-en-gb": "5.0.34",
|
|
116
|
-
"@cspell/dict-es-es": "3.0.9",
|
|
117
|
-
"@cspell/dict-ru_ru": "2.3.3",
|
|
118
|
-
"cspell": "10.3.6",
|
|
119
|
-
"markdownlint-cli2": "0.23.3"
|
|
119
|
+
"vitest": "^5.0.2"
|
|
120
120
|
},
|
|
121
121
|
"publishConfig": {
|
|
122
122
|
"access": "public"
|