@wirecat/cli-base 0.0.0-stage → 0.21.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/LICENSE +204 -0
- package/README.md +376 -2
- package/config/biome.base.json +56 -0
- package/config/cspell.json +57 -0
- package/config/lefthook.yml +34 -0
- package/config/rumdl.toml +9 -0
- package/config/tsconfig.base.json +21 -0
- package/config/tsconfig.scripts.json +13 -0
- package/config/tsconfig.test.json +11 -0
- package/config/vale/CliDocs/Filler.yml +9 -0
- package/config/vale/CliDocs/SentenceLength.yml +6 -0
- package/config/vale/Tg/Tone.yml +7 -0
- package/config/wirecat/LICENSE +204 -0
- package/config/wirecat/biome.base.json +56 -0
- package/config/wirecat/check.mjs +41 -0
- package/config/wirecat/cspell.json +80 -0
- package/config/wirecat/lefthook.yml +26 -0
- package/config/wirecat/manifest.json +23 -0
- package/config/wirecat/markdownlint.json +10 -0
- package/config/wirecat/rumdl.toml +9 -0
- package/dist/codegen/index.d.ts +12 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +11 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/manifest.d.ts +47 -0
- package/dist/codegen/manifest.d.ts.map +1 -0
- package/dist/codegen/manifest.js +73 -0
- package/dist/codegen/manifest.js.map +1 -0
- package/dist/codegen/model.d.ts +146 -0
- package/dist/codegen/model.d.ts.map +1 -0
- package/dist/codegen/model.js +7 -0
- package/dist/codegen/model.js.map +1 -0
- package/dist/codegen/names.d.ts +4 -0
- package/dist/codegen/names.d.ts.map +1 -0
- package/dist/codegen/names.js +46 -0
- package/dist/codegen/names.js.map +1 -0
- package/dist/codegen/pipeline.d.ts +24 -0
- package/dist/codegen/pipeline.d.ts.map +1 -0
- package/dist/codegen/pipeline.js +193 -0
- package/dist/codegen/pipeline.js.map +1 -0
- package/dist/codegen/runtime.d.ts +24 -0
- package/dist/codegen/runtime.d.ts.map +1 -0
- package/dist/codegen/runtime.js +38 -0
- package/dist/codegen/runtime.js.map +1 -0
- package/dist/codegen/tree.d.ts +29 -0
- package/dist/codegen/tree.d.ts.map +1 -0
- package/dist/codegen/tree.js +87 -0
- package/dist/codegen/tree.js.map +1 -0
- package/dist/codegen/typescript.d.ts +6 -0
- package/dist/codegen/typescript.d.ts.map +1 -0
- package/dist/codegen/typescript.js +78 -0
- package/dist/codegen/typescript.js.map +1 -0
- package/dist/codegen/valibot.d.ts +10 -0
- package/dist/codegen/valibot.d.ts.map +1 -0
- package/dist/codegen/valibot.js +132 -0
- package/dist/codegen/valibot.js.map +1 -0
- package/dist/commands/index.d.ts +76 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +62 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/page.d.ts +80 -0
- package/dist/commands/page.d.ts.map +1 -0
- package/dist/commands/page.js +100 -0
- package/dist/commands/page.js.map +1 -0
- package/dist/completion/index.d.ts +37 -0
- package/dist/completion/index.d.ts.map +1 -0
- package/dist/completion/index.js +87 -0
- package/dist/completion/index.js.map +1 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +61 -0
- package/dist/config.js.map +1 -0
- package/dist/credentials.d.ts +48 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +120 -0
- package/dist/credentials.js.map +1 -0
- package/dist/deadline.d.ts +14 -0
- package/dist/deadline.d.ts.map +1 -0
- package/dist/deadline.js +88 -0
- package/dist/deadline.js.map +1 -0
- package/dist/dev/bin.d.ts +3 -0
- package/dist/dev/bin.d.ts.map +1 -0
- package/dist/dev/bin.js +8 -0
- package/dist/dev/bin.js.map +1 -0
- package/dist/dev/main.d.ts +7 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/dev/main.js +149 -0
- package/dist/dev/main.js.map +1 -0
- package/dist/dev/next-version.d.ts +11 -0
- package/dist/dev/next-version.d.ts.map +1 -0
- package/dist/dev/next-version.js +33 -0
- package/dist/dev/next-version.js.map +1 -0
- package/dist/dev/slow-tests.d.ts +14 -0
- package/dist/dev/slow-tests.d.ts.map +1 -0
- package/dist/dev/slow-tests.js +17 -0
- package/dist/dev/slow-tests.js.map +1 -0
- package/dist/dev/test-matrix.d.ts +35 -0
- package/dist/dev/test-matrix.d.ts.map +1 -0
- package/dist/dev/test-matrix.js +93 -0
- package/dist/dev/test-matrix.js.map +1 -0
- package/dist/errors.d.ts +34 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/errors.js.map +1 -0
- package/dist/executable.d.ts +3 -0
- package/dist/executable.d.ts.map +1 -0
- package/dist/executable.js +41 -0
- package/dist/executable.js.map +1 -0
- package/dist/exit-codes.d.ts +11 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +25 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/http/index.d.ts +20 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +46 -0
- package/dist/http/index.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/keyring.d.ts +27 -0
- package/dist/keyring.d.ts.map +1 -0
- package/dist/keyring.js +45 -0
- package/dist/keyring.js.map +1 -0
- 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/logger.d.ts +12 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +7 -0
- package/dist/logger.js.map +1 -0
- package/dist/logging.d.ts +31 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +58 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp/index.d.ts +32 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +113 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/output-buffer.d.ts +16 -0
- package/dist/output-buffer.d.ts.map +1 -0
- package/dist/output-buffer.js +69 -0
- package/dist/output-buffer.js.map +1 -0
- package/dist/paths.d.ts +35 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +45 -0
- package/dist/paths.js.map +1 -0
- package/dist/pretty.d.ts +12 -0
- package/dist/pretty.d.ts.map +1 -0
- package/dist/pretty.js +83 -0
- package/dist/pretty.js.map +1 -0
- package/dist/release/index.d.ts +38 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +91 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/markdown.d.ts +36 -0
- package/dist/release/markdown.d.ts.map +1 -0
- package/dist/release/markdown.js +153 -0
- package/dist/release/markdown.js.map +1 -0
- package/dist/release/structure.d.ts +16 -0
- package/dist/release/structure.d.ts.map +1 -0
- package/dist/release/structure.js +74 -0
- package/dist/release/structure.js.map +1 -0
- package/dist/renderer.d.ts +34 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +55 -0
- package/dist/renderer.js.map +1 -0
- package/dist/result-fields.d.ts +4 -0
- package/dist/result-fields.d.ts.map +1 -0
- package/dist/result-fields.js +56 -0
- package/dist/result-fields.js.map +1 -0
- package/dist/retry.d.ts +27 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +26 -0
- package/dist/retry.js.map +1 -0
- package/dist/sanitize.d.ts +25 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +52 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/skill/index.d.ts +78 -0
- package/dist/skill/index.d.ts.map +1 -0
- package/dist/skill/index.js +190 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/streams.d.ts +24 -0
- package/dist/streams.d.ts.map +1 -0
- package/dist/streams.js +26 -0
- package/dist/streams.js.map +1 -0
- package/dist/testing/index.d.ts +24 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +29 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/time.d.ts +21 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +19 -0
- package/dist/time.js.map +1 -0
- package/dist/update/index.d.ts +76 -0
- package/dist/update/index.d.ts.map +1 -0
- package/dist/update/index.js +160 -0
- package/dist/update/index.js.map +1 -0
- package/package.json +126 -3
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { win32 } from "node:path";
|
|
3
|
+
const variable = (env, name) => Object.entries(env).find(([key]) => key.toUpperCase() === name)?.[1];
|
|
4
|
+
export const executableOnPath = (command, env, platform = process.platform, exists = existsSync) => {
|
|
5
|
+
if (platform !== "win32" || win32.isAbsolute(command))
|
|
6
|
+
return command;
|
|
7
|
+
if (/[\\/]/.test(command))
|
|
8
|
+
return command;
|
|
9
|
+
const extensions = win32.extname(command)
|
|
10
|
+
? [""]
|
|
11
|
+
: (variable(env, "PATHEXT") ?? ".EXE;.COM;.CMD;.BAT").split(";").filter((ext) => /^\.[a-z0-9]+$/i.test(ext));
|
|
12
|
+
for (const entry of (variable(env, "PATH") ?? "").split(";")) {
|
|
13
|
+
const directory = entry.replace(/^"(.*)"$/, "$1");
|
|
14
|
+
for (const extension of extensions) {
|
|
15
|
+
const candidate = win32.join(directory, command + extension);
|
|
16
|
+
if (exists(candidate))
|
|
17
|
+
return candidate;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return command;
|
|
21
|
+
};
|
|
22
|
+
export const executableEnvironment = (env, platform = process.platform) => {
|
|
23
|
+
if (platform !== "win32")
|
|
24
|
+
return env;
|
|
25
|
+
const configured = variable(env, "COMSPEC");
|
|
26
|
+
const system = variable(env, "SYSTEMROOT");
|
|
27
|
+
const shell = configured
|
|
28
|
+
? configured
|
|
29
|
+
: system && win32.isAbsolute(system)
|
|
30
|
+
? win32.join(system, "System32", "cmd.exe")
|
|
31
|
+
: undefined;
|
|
32
|
+
if (!shell)
|
|
33
|
+
return env;
|
|
34
|
+
const result = { ...env };
|
|
35
|
+
for (const key of Object.keys(result))
|
|
36
|
+
if (key.toUpperCase() === "COMSPEC")
|
|
37
|
+
delete result[key];
|
|
38
|
+
result.comspec = shell;
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=executable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executable.js","sourceRoot":"","sources":["../src/executable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAEjC,MAAM,QAAQ,GAAG,CAAC,GAAsB,EAAE,IAAY,EAAE,EAAE,CACxD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAEtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAe,EACf,GAAsB,EACtB,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EAC5C,MAAM,GAA8B,UAAU,EACtC,EAAE;IACV,IAAI,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAA;IACrE,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAA;IACzC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QACvC,CAAC,CAAC,CAAC,EAAE,CAAC;QACN,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,qBAAqB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAC9G,KAAK,MAAM,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QACjD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC,CAAA;YAC5D,IAAI,MAAM,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAA;QACzC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,GAAsB,EACtB,QAAQ,GAAoB,OAAO,CAAC,QAAQ,EACzB,EAAE;IACrB,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,GAAG,CAAA;IACpC,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,UAAU;QACtB,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;YAClC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC;YAC3C,CAAC,CAAC,SAAS,CAAA;IACf,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAA;IACtB,MAAM,MAAM,GAAG,EAAE,GAAG,GAAG,EAAE,CAAA;IACzB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;IAC9F,MAAM,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ErrorCode } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* One mapping, so a script can branch on `$?` without parsing text. Defined here rather than at
|
|
4
|
+
* each command site: numbers invented per command are how two of them end up disagreeing.
|
|
5
|
+
*
|
|
6
|
+
* 130 for a cancellation is the shell's convention for SIGINT.
|
|
7
|
+
*/
|
|
8
|
+
export declare const EXIT_CODES: Record<ErrorCode, number>;
|
|
9
|
+
export declare const exitCodeFor: (code: ErrorCode) => number;
|
|
10
|
+
export declare const GENERIC_FAILURE = 1;
|
|
11
|
+
//# sourceMappingURL=exit-codes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.d.ts","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAehD,CAAA;AAED,eAAO,MAAM,WAAW,SAAU,SAAS,KAAG,MAA0B,CAAA;AAExE,eAAO,MAAM,eAAe,IAAI,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One mapping, so a script can branch on `$?` without parsing text. Defined here rather than at
|
|
3
|
+
* each command site: numbers invented per command are how two of them end up disagreeing.
|
|
4
|
+
*
|
|
5
|
+
* 130 for a cancellation is the shell's convention for SIGINT.
|
|
6
|
+
*/
|
|
7
|
+
export const EXIT_CODES = {
|
|
8
|
+
validation_error: 2,
|
|
9
|
+
configuration_error: 3,
|
|
10
|
+
authentication_error: 4,
|
|
11
|
+
permission_error: 5,
|
|
12
|
+
not_found: 6,
|
|
13
|
+
confirmation_required: 7,
|
|
14
|
+
rate_limited: 8,
|
|
15
|
+
timeout: 9,
|
|
16
|
+
network_error: 10,
|
|
17
|
+
provider_error: 11,
|
|
18
|
+
provider_unavailable: 12,
|
|
19
|
+
invalid_response: 13,
|
|
20
|
+
outcome_unknown: 14,
|
|
21
|
+
cancelled: 130,
|
|
22
|
+
};
|
|
23
|
+
export const exitCodeFor = (code) => EXIT_CODES[code];
|
|
24
|
+
export const GENERIC_FAILURE = 1;
|
|
25
|
+
//# sourceMappingURL=exit-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-codes.js","sourceRoot":"","sources":["../src/exit-codes.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAA8B;IACnD,gBAAgB,EAAE,CAAC;IACnB,mBAAmB,EAAE,CAAC;IACtB,oBAAoB,EAAE,CAAC;IACvB,gBAAgB,EAAE,CAAC;IACnB,SAAS,EAAE,CAAC;IACZ,qBAAqB,EAAE,CAAC;IACxB,YAAY,EAAE,CAAC;IACf,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,EAAE;IACjB,cAAc,EAAE,EAAE;IAClB,oBAAoB,EAAE,EAAE;IACxB,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE,EAAE;IACnB,SAAS,EAAE,GAAG;CACf,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAe,EAAU,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;AAExE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HTTP layer, deliberately behind its own entry point.
|
|
3
|
+
*
|
|
4
|
+
* A CLI that speaks a socket, a message bus or a local database has no business depending on
|
|
5
|
+
* status-code semantics and `Retry-After` parsing. Import `@wirecat/cli-base/http` only when
|
|
6
|
+
* the thing on the other end is actually HTTP.
|
|
7
|
+
*/
|
|
8
|
+
import type { ErrorCode } from "../errors.js";
|
|
9
|
+
import type { WallClock } from "../time.js";
|
|
10
|
+
/** The one function an HTTP client needs from its environment. A Worker, a browser, a test and Node all satisfy it. */
|
|
11
|
+
export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
12
|
+
/** `Retry-After` is either a number of seconds or an HTTP date. Both forms occur in the wild. */
|
|
13
|
+
export declare const parseRetryAfter: (header: string | null | undefined, now: WallClock) => number | undefined;
|
|
14
|
+
/** A Unix timestamp in seconds, the shape several providers use for `X-RateLimit-Reset`. */
|
|
15
|
+
export declare const parseRateLimitReset: (header: string | null | undefined, now: WallClock) => number | undefined;
|
|
16
|
+
/** What the provider asked us to wait, if it asked at all. Its timing beats our own backoff. */
|
|
17
|
+
export declare const providerWaitMs: (headers: Headers, now: WallClock) => number | undefined;
|
|
18
|
+
export declare const retryableStatus: (status: number) => boolean;
|
|
19
|
+
export declare const statusToCode: (status: number) => ErrorCode;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C,uHAAuH;AACvH,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEhG,iGAAiG;AACjG,eAAO,MAAM,eAAe,WAAY,MAAM,GAAG,IAAI,GAAG,SAAS,OAAO,SAAS,KAAG,MAAM,GAAG,SAa5F,CAAA;AAED,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,WAAY,MAAM,GAAG,IAAI,GAAG,SAAS,OAAO,SAAS,KAAG,MAAM,GAAG,SAQhG,CAAA;AAED,gGAAgG;AAChG,eAAO,MAAM,cAAc,YAAa,OAAO,OAAO,SAAS,KAAG,MAAM,GAAG,SACqC,CAAA;AAEhH,eAAO,MAAM,eAAe,WAAY,MAAM,KAAG,OAA4D,CAAA;AAE7G,eAAO,MAAM,YAAY,WAAY,MAAM,KAAG,SAS7C,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** `Retry-After` is either a number of seconds or an HTTP date. Both forms occur in the wild. */
|
|
2
|
+
export const parseRetryAfter = (header, now) => {
|
|
3
|
+
if (!header)
|
|
4
|
+
return undefined;
|
|
5
|
+
const trimmed = header.trim();
|
|
6
|
+
if (/^\d+$/.test(trimmed))
|
|
7
|
+
return Number(trimmed) * 1000;
|
|
8
|
+
const at = Date.parse(trimmed);
|
|
9
|
+
if (Number.isNaN(at))
|
|
10
|
+
return undefined;
|
|
11
|
+
const delta = at - now().getTime();
|
|
12
|
+
// A date already in the past would otherwise become a zero wait, and a zero wait against a rate
|
|
13
|
+
// limit is a hot loop.
|
|
14
|
+
return delta > 0 ? delta : undefined;
|
|
15
|
+
};
|
|
16
|
+
/** A Unix timestamp in seconds, the shape several providers use for `X-RateLimit-Reset`. */
|
|
17
|
+
export const parseRateLimitReset = (header, now) => {
|
|
18
|
+
if (!header)
|
|
19
|
+
return undefined;
|
|
20
|
+
const seconds = Number(header.trim());
|
|
21
|
+
if (!Number.isFinite(seconds))
|
|
22
|
+
return undefined;
|
|
23
|
+
const delta = seconds * 1000 - now().getTime();
|
|
24
|
+
return delta > 0 ? delta : undefined;
|
|
25
|
+
};
|
|
26
|
+
/** What the provider asked us to wait, if it asked at all. Its timing beats our own backoff. */
|
|
27
|
+
export const providerWaitMs = (headers, now) => parseRetryAfter(headers.get("retry-after"), now) ?? parseRateLimitReset(headers.get("x-ratelimit-reset"), now);
|
|
28
|
+
export const retryableStatus = (status) => status === 408 || status === 429 || status >= 500;
|
|
29
|
+
export const statusToCode = (status) => {
|
|
30
|
+
if (status === 400 || status === 422)
|
|
31
|
+
return "validation_error";
|
|
32
|
+
if (status === 401)
|
|
33
|
+
return "authentication_error";
|
|
34
|
+
if (status === 403)
|
|
35
|
+
return "permission_error";
|
|
36
|
+
if (status === 404)
|
|
37
|
+
return "not_found";
|
|
38
|
+
if (status === 408)
|
|
39
|
+
return "timeout";
|
|
40
|
+
if (status === 429)
|
|
41
|
+
return "rate_limited";
|
|
42
|
+
if (status === 502 || status === 503 || status === 504)
|
|
43
|
+
return "provider_unavailable";
|
|
44
|
+
return "provider_error";
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAaA,iGAAiG;AACjG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAiC,EAAE,GAAc,EAAsB,EAAE;IACvG,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAE7B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC7B,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IAExD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,SAAS,CAAA;IAEtC,MAAM,KAAK,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAA;IAClC,gGAAgG;IAChG,uBAAuB;IACvB,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AACtC,CAAC,CAAA;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAiC,EAAE,GAAc,EAAsB,EAAE;IAC3G,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAE7B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAA;IAE/C,MAAM,KAAK,GAAG,OAAO,GAAG,IAAI,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAA;IAC9C,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AACtC,CAAC,CAAA;AAED,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAE,GAAc,EAAsB,EAAE,CACrF,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,GAAG,CAAC,IAAI,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,GAAG,CAAC,CAAA;AAEhH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAc,EAAW,EAAE,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAA;AAE7G,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAc,EAAa,EAAE;IACxD,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,kBAAkB,CAAA;IAC/D,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,sBAAsB,CAAA;IACjD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,kBAAkB,CAAA;IAC7C,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,WAAW,CAAA;IACtC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,SAAS,CAAA;IACpC,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,cAAc,CAAA;IACzC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,sBAAsB,CAAA;IACrF,OAAO,gBAAgB,CAAA;AACzB,CAAC,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { loadConfigFile, saveConfigFile, writeSecurely } from "./config.js";
|
|
2
|
+
export type { CredentialSource, CredentialStorage, CredentialsOptions, StoredCredential } from "./credentials.js";
|
|
3
|
+
export { CREDENTIAL_STORAGE, Credentials, keyringService } from "./credentials.js";
|
|
4
|
+
export { createDeadline, type Deadline, type DeadlineOptions } from "./deadline.js";
|
|
5
|
+
export { CliError, type CliErrorDetails, type ErrorCode, errorCodes, isCliError } from "./errors.js";
|
|
6
|
+
export { EXIT_CODES, exitCodeFor, GENERIC_FAILURE } from "./exit-codes.js";
|
|
7
|
+
export { brokenKeyring, type KeyringStore, memoryKeyring, systemKeyring } from "./keyring.js";
|
|
8
|
+
export { type LegacyMove, legacyMacPaths, type MigrateLegacyPathsOptions, migrateLegacyMacPaths, } from "./legacy-paths.js";
|
|
9
|
+
export { type Logger, noopLogger } from "./logger.js";
|
|
10
|
+
export { createFileLogger, type FileLogger, type FileLoggerOptions, REDACTED_FIELDS } from "./logging.js";
|
|
11
|
+
export { createOutputBuffer, type OutputBuffer, type OutputBufferOptions } from "./output-buffer.js";
|
|
12
|
+
export { configFilePath, type Paths, type PathsOptions, pathsAreOverridden, resolvePaths } from "./paths.js";
|
|
13
|
+
export { indent, type PrettyOptions, renderPretty } from "./pretty.js";
|
|
14
|
+
export { createRenderer, RENDER_FORMATS, type Renderer, type RendererOptions, type RenderFormat, } from "./renderer.js";
|
|
15
|
+
export { fieldsOf, projectFields } from "./result-fields.js";
|
|
16
|
+
export { backoffMs, DEFAULT_RETRY, isTransportFailure, type RetryConfig } from "./retry.js";
|
|
17
|
+
export { singleLine, visibleControls } from "./sanitize.js";
|
|
18
|
+
export { captureStreams, processStreams, type Streams } from "./streams.js";
|
|
19
|
+
export { abortError, type MonotonicClock, monotonic, realSleep, type SleepLike, type SleepReason, type WallClock, wallClock, } from "./time.js";
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,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
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { loadConfigFile, saveConfigFile, writeSecurely } from "./config.js";
|
|
2
|
+
export { CREDENTIAL_STORAGE, Credentials, keyringService } from "./credentials.js";
|
|
3
|
+
export { createDeadline } from "./deadline.js";
|
|
4
|
+
export { CliError, errorCodes, isCliError } from "./errors.js";
|
|
5
|
+
export { EXIT_CODES, exitCodeFor, GENERIC_FAILURE } from "./exit-codes.js";
|
|
6
|
+
export { brokenKeyring, memoryKeyring, systemKeyring } from "./keyring.js";
|
|
7
|
+
export { legacyMacPaths, migrateLegacyMacPaths, } from "./legacy-paths.js";
|
|
8
|
+
export { noopLogger } from "./logger.js";
|
|
9
|
+
export { createFileLogger, REDACTED_FIELDS } from "./logging.js";
|
|
10
|
+
export { createOutputBuffer } from "./output-buffer.js";
|
|
11
|
+
export { configFilePath, pathsAreOverridden, resolvePaths } from "./paths.js";
|
|
12
|
+
export { indent, renderPretty } from "./pretty.js";
|
|
13
|
+
export { createRenderer, RENDER_FORMATS, } from "./renderer.js";
|
|
14
|
+
export { fieldsOf, projectFields } from "./result-fields.js";
|
|
15
|
+
export { backoffMs, DEFAULT_RETRY, isTransportFailure } from "./retry.js";
|
|
16
|
+
export { singleLine, visibleControls } from "./sanitize.js";
|
|
17
|
+
export { captureStreams, processStreams } from "./streams.js";
|
|
18
|
+
export { abortError, monotonic, realSleep, wallClock, } from "./time.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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,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,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one seam through which the OS keychain is reached.
|
|
3
|
+
*
|
|
4
|
+
* **What backs it, per platform** — `@napi-rs/keyring` 2.1.0, checked 2026-09-19:
|
|
5
|
+
* macOS uses the Keychain and Windows the Credential Manager, both part of the OS; Linux and the
|
|
6
|
+
* BSDs use the Secret Service over D-Bus, which a headless machine, a container, WSL or a CI
|
|
7
|
+
* runner usually does not have. There is nothing to install either way — the package ships
|
|
8
|
+
* prebuilt binaries for twelve platform triples including musl, so no Rust toolchain and no
|
|
9
|
+
* node-gyp — but on Linux **the daemon may simply not be there**, which is why every caller must
|
|
10
|
+
* handle this throwing. `Credentials` does, by warning once and writing a 0600 file instead.
|
|
11
|
+
* Injected like `fetch` in core, so
|
|
12
|
+
* "no test touched the developer's real keychain" is a property of the code rather than a hope
|
|
13
|
+
* about every test remembering to opt out.
|
|
14
|
+
*/
|
|
15
|
+
export interface KeyringStore {
|
|
16
|
+
get(service: string, account: string): string | null;
|
|
17
|
+
set(service: string, account: string, secret: string): void;
|
|
18
|
+
delete(service: string, account: string): boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const systemKeyring: KeyringStore;
|
|
21
|
+
/** An in-memory stand-in. Every test uses this; none can reach the real keychain. */
|
|
22
|
+
export declare const memoryKeyring: (initial?: Record<string, string>) => KeyringStore & {
|
|
23
|
+
entries: Map<string, string>;
|
|
24
|
+
};
|
|
25
|
+
/** Refuses every operation, so the fallback path can be tested. */
|
|
26
|
+
export declare const brokenKeyring: (message?: string) => KeyringStore;
|
|
27
|
+
//# sourceMappingURL=keyring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyring.d.ts","sourceRoot":"","sources":["../src/keyring.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACpD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3D,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAA;CAClD;AAoBD,eAAO,MAAM,aAAa,EAAE,YAQ3B,CAAA;AAED,qFAAqF;AACrF,eAAO,MAAM,aAAa,aACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC9B,YAAY,GAAG;IAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAY/C,CAAA;AAED,mEAAmE;AACnE,eAAO,MAAM,aAAa,wBAA8C,YAUtE,CAAA"}
|
package/dist/keyring.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
let cached;
|
|
4
|
+
// Loaded on first use, not at import: `@napi-rs/keyring` is a native module, and a machine
|
|
5
|
+
// where its binary is missing must still be able to run in file mode.
|
|
6
|
+
const entryClass = () => {
|
|
7
|
+
cached ??= require("@napi-rs/keyring").Entry;
|
|
8
|
+
return cached;
|
|
9
|
+
};
|
|
10
|
+
export const systemKeyring = {
|
|
11
|
+
// Returns null for an absent entry rather than throwing — measured against @napi-rs/keyring
|
|
12
|
+
// on 2026-09-13, and the difference matters: a throw here means the keychain is unusable.
|
|
13
|
+
get: (service, account) => new (entryClass())(service, account).getPassword(),
|
|
14
|
+
set: (service, account, secret) => {
|
|
15
|
+
;
|
|
16
|
+
new (entryClass())(service, account).setPassword(secret);
|
|
17
|
+
},
|
|
18
|
+
delete: (service, account) => new (entryClass())(service, account).deletePassword(),
|
|
19
|
+
};
|
|
20
|
+
/** An in-memory stand-in. Every test uses this; none can reach the real keychain. */
|
|
21
|
+
export const memoryKeyring = (initial = {}) => {
|
|
22
|
+
const entries = new Map(Object.entries(initial));
|
|
23
|
+
const key = (service, account) => `${service}:${account}`;
|
|
24
|
+
return {
|
|
25
|
+
entries,
|
|
26
|
+
get: (service, account) => entries.get(key(service, account)) ?? null,
|
|
27
|
+
set: (service, account, secret) => {
|
|
28
|
+
entries.set(key(service, account), secret);
|
|
29
|
+
},
|
|
30
|
+
delete: (service, account) => entries.delete(key(service, account)),
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/** Refuses every operation, so the fallback path can be tested. */
|
|
34
|
+
export const brokenKeyring = (message = "no secret service available") => ({
|
|
35
|
+
get: () => {
|
|
36
|
+
throw new Error(message);
|
|
37
|
+
},
|
|
38
|
+
set: () => {
|
|
39
|
+
throw new Error(message);
|
|
40
|
+
},
|
|
41
|
+
delete: () => {
|
|
42
|
+
throw new Error(message);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=keyring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyring.js","sourceRoot":"","sources":["../src/keyring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AA8B3C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9C,IAAI,MAAoC,CAAA;AAExC,2FAA2F;AAC3F,sEAAsE;AACtE,MAAM,UAAU,GAAG,GAAqB,EAAE;IACxC,MAAM,KAAM,OAAO,CAAC,kBAAkB,CAAiC,CAAC,KAAK,CAAA;IAC7E,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,4FAA4F;IAC5F,0FAA0F;IAC1F,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE;IAC7E,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;QAChC,CAAC;QAAA,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3D,CAAC;IACD,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE;CACpF,CAAA;AAED,qFAAqF;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,OAAO,GAA2B,EAAE,EACa,EAAE;IACnD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAChD,MAAM,GAAG,GAAG,CAAC,OAAe,EAAE,OAAe,EAAE,EAAE,CAAC,GAAG,OAAO,IAAI,OAAO,EAAE,CAAA;IAEzE,OAAO;QACL,OAAO;QACP,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,IAAI;QACrE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;YAChC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAA;QAC5C,CAAC;QACD,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;KACpE,CAAA;AACH,CAAC,CAAA;AAED,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAO,GAAG,6BAA6B,EAAgB,EAAE,CAAC,CAAC;IACvF,GAAG,EAAE,GAAG,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;IACD,GAAG,EAAE,GAAG,EAAE;QACR,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;IACD,MAAM,EAAE,GAAG,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;CACF,CAAC,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/logger.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The only logging contract core knows about. The CLI adapts Pino to it; a Worker can pass
|
|
3
|
+
* its own. Core never imports a logging library — see docs/dev/ARCHITECTURE.md.
|
|
4
|
+
*/
|
|
5
|
+
export interface Logger {
|
|
6
|
+
debug(event: object, message?: string): void;
|
|
7
|
+
info(event: object, message?: string): void;
|
|
8
|
+
warn(event: object, message?: string): void;
|
|
9
|
+
error(event: object, message?: string): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const noopLogger: Logger;
|
|
12
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7C;AAED,eAAO,MAAM,UAAU,EAAE,MAKxB,CAAA"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,UAAU,GAAW;IAChC,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Logger } from "./logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Field names whose value must never reach a log file. This is the **second** line of defence, not
|
|
4
|
+
* the first: a secret should not be handed to a logger at all. Redaction catches the one that
|
|
5
|
+
* slipped into a nested object nobody thought about.
|
|
6
|
+
*/
|
|
7
|
+
export declare const REDACTED_FIELDS: string[];
|
|
8
|
+
export interface FileLogger extends Logger {
|
|
9
|
+
/** Must be awaited before the process exits, or the tail of the file is lost. */
|
|
10
|
+
close(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export interface FileLoggerOptions {
|
|
13
|
+
/** Where the JSON lines go. Omit for a logger that writes nowhere. */
|
|
14
|
+
path?: string;
|
|
15
|
+
level?: string;
|
|
16
|
+
base?: Record<string, unknown>;
|
|
17
|
+
/** Added to `REDACTED_FIELDS` — the names only this program knows about. */
|
|
18
|
+
redact?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* Told once when the file cannot be opened or written; every record after that is dropped.
|
|
21
|
+
* Without it the failure is silent, so a host that promised a log should say it is gone.
|
|
22
|
+
*/
|
|
23
|
+
onError?: (error: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Structured records for machines: JSON lines, no ANSI ever, secrets redacted. The terminal is a
|
|
27
|
+
* different concern and goes through the renderer — a spinner frame must never reach a log file,
|
|
28
|
+
* and a log record must never reach stdout.
|
|
29
|
+
*/
|
|
30
|
+
export declare const createFileLogger: ({ path, level, base, redact, onError, }?: FileLoggerOptions) => FileLogger;
|
|
31
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC;;;;GAIG;AACH,eAAO,MAAM,eAAe,UAa3B,CAAA;AAED,MAAM,WAAW,UAAW,SAAQ,MAAM;IACxC,iFAAiF;IACjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,6CAM1B,iBAAiB,KAAQ,UA8B3B,CAAA"}
|
package/dist/logging.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createWriteStream } from "node:fs";
|
|
2
|
+
import { pino } from "pino";
|
|
3
|
+
/**
|
|
4
|
+
* Field names whose value must never reach a log file. This is the **second** line of defence, not
|
|
5
|
+
* the first: a secret should not be handed to a logger at all. Redaction catches the one that
|
|
6
|
+
* slipped into a nested object nobody thought about.
|
|
7
|
+
*/
|
|
8
|
+
export const REDACTED_FIELDS = [
|
|
9
|
+
"authorization",
|
|
10
|
+
"Authorization",
|
|
11
|
+
"apiKey",
|
|
12
|
+
"api_key",
|
|
13
|
+
"token",
|
|
14
|
+
"accessToken",
|
|
15
|
+
"access_token",
|
|
16
|
+
"refreshToken",
|
|
17
|
+
"password",
|
|
18
|
+
"secret",
|
|
19
|
+
"verifyCode",
|
|
20
|
+
"phone",
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Structured records for machines: JSON lines, no ANSI ever, secrets redacted. The terminal is a
|
|
24
|
+
* different concern and goes through the renderer — a spinner frame must never reach a log file,
|
|
25
|
+
* and a log record must never reach stdout.
|
|
26
|
+
*/
|
|
27
|
+
export const createFileLogger = ({ path, level = "info", base = {}, redact = [], onError = () => { }, } = {}) => {
|
|
28
|
+
if (!path)
|
|
29
|
+
return { ...silent, close: async () => { } };
|
|
30
|
+
// A plain append stream, not a worker transport: logging must not need a second process, and
|
|
31
|
+
// `sync: false` drops the tail of the file when a command exits — which is exactly the failure
|
|
32
|
+
// the log exists to explain.
|
|
33
|
+
const file = createWriteStream(path, { flags: "a" });
|
|
34
|
+
// The open is asynchronous, so a directory removed a moment ago surfaces here as an `error`
|
|
35
|
+
// event — and one with no listener kills the process the log was only meant to describe.
|
|
36
|
+
file.on("error", onError);
|
|
37
|
+
const fields = [...new Set([...REDACTED_FIELDS, ...redact])];
|
|
38
|
+
const paths = fields.flatMap((field) => [field, `*.${field}`, `*.*.${field}`]);
|
|
39
|
+
const logger = pino({ level, base, redact: { paths, censor: "[redacted]" }, timestamp: pino.stdTimeFunctions.isoTime }, file);
|
|
40
|
+
return {
|
|
41
|
+
debug: (event, message) => logger.debug(event, message),
|
|
42
|
+
info: (event, message) => logger.info(event, message),
|
|
43
|
+
warn: (event, message) => logger.warn(event, message),
|
|
44
|
+
error: (event, message) => logger.error(event, message),
|
|
45
|
+
close: () => new Promise((resolve) => {
|
|
46
|
+
file.end(() => {
|
|
47
|
+
resolve();
|
|
48
|
+
});
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
const silent = {
|
|
53
|
+
debug: () => { },
|
|
54
|
+
info: () => { },
|
|
55
|
+
warn: () => { },
|
|
56
|
+
error: () => { },
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAG3B;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,eAAe;IACf,eAAe;IACf,QAAQ;IACR,SAAS;IACT,OAAO;IACP,aAAa;IACb,cAAc;IACd,cAAc;IACd,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,OAAO;CACR,CAAA;AAqBD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,EAC/B,IAAI,EACJ,KAAK,GAAG,MAAM,EACd,IAAI,GAAG,EAAE,EACT,MAAM,GAAG,EAAE,EACX,OAAO,GAAG,GAAG,EAAE,GAAE,CAAC,GACnB,GAAsB,EAAE,EAAc,EAAE;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC,EAAE,CAAA;IAEtD,6FAA6F;IAC7F,+FAA+F;IAC/F,6BAA6B;IAC7B,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IACpD,4FAA4F;IAC5F,yFAAyF;IACzF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACzB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,eAAe,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,EAAE,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAA;IAE9E,MAAM,MAAM,GAAG,IAAI,CACjB,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAClG,IAAI,CACL,CAAA;IAED,OAAO;QACL,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;QACvD,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;QACrD,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;QACrD,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;QACvD,KAAK,EAAE,GAAG,EAAE,CACV,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;gBACZ,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC;KACL,CAAA;AACH,CAAC,CAAA;AAED,MAAM,MAAM,GAAW;IACrB,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAA"}
|