@wirecat/cli-core 0.0.0 → 0.18.1

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.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +344 -0
  3. package/config/biome.base.json +56 -0
  4. package/config/cspell.json +57 -0
  5. package/config/lefthook.yml +34 -0
  6. package/config/rumdl.toml +9 -0
  7. package/config/tsconfig.base.json +21 -0
  8. package/config/tsconfig.scripts.json +13 -0
  9. package/config/tsconfig.test.json +11 -0
  10. package/config/vale/CliDocs/Filler.yml +9 -0
  11. package/config/vale/CliDocs/SentenceLength.yml +6 -0
  12. package/config/vale/Tg/Tone.yml +7 -0
  13. package/dist/codegen/index.d.ts +12 -0
  14. package/dist/codegen/index.d.ts.map +1 -0
  15. package/dist/codegen/index.js +11 -0
  16. package/dist/codegen/index.js.map +1 -0
  17. package/dist/codegen/manifest.d.ts +47 -0
  18. package/dist/codegen/manifest.d.ts.map +1 -0
  19. package/dist/codegen/manifest.js +73 -0
  20. package/dist/codegen/manifest.js.map +1 -0
  21. package/dist/codegen/model.d.ts +146 -0
  22. package/dist/codegen/model.d.ts.map +1 -0
  23. package/dist/codegen/model.js +7 -0
  24. package/dist/codegen/model.js.map +1 -0
  25. package/dist/codegen/names.d.ts +4 -0
  26. package/dist/codegen/names.d.ts.map +1 -0
  27. package/dist/codegen/names.js +46 -0
  28. package/dist/codegen/names.js.map +1 -0
  29. package/dist/codegen/pipeline.d.ts +24 -0
  30. package/dist/codegen/pipeline.d.ts.map +1 -0
  31. package/dist/codegen/pipeline.js +193 -0
  32. package/dist/codegen/pipeline.js.map +1 -0
  33. package/dist/codegen/runtime.d.ts +24 -0
  34. package/dist/codegen/runtime.d.ts.map +1 -0
  35. package/dist/codegen/runtime.js +38 -0
  36. package/dist/codegen/runtime.js.map +1 -0
  37. package/dist/codegen/tree.d.ts +29 -0
  38. package/dist/codegen/tree.d.ts.map +1 -0
  39. package/dist/codegen/tree.js +87 -0
  40. package/dist/codegen/tree.js.map +1 -0
  41. package/dist/codegen/typescript.d.ts +6 -0
  42. package/dist/codegen/typescript.d.ts.map +1 -0
  43. package/dist/codegen/typescript.js +78 -0
  44. package/dist/codegen/typescript.js.map +1 -0
  45. package/dist/codegen/valibot.d.ts +10 -0
  46. package/dist/codegen/valibot.d.ts.map +1 -0
  47. package/dist/codegen/valibot.js +132 -0
  48. package/dist/codegen/valibot.js.map +1 -0
  49. package/dist/commands/index.d.ts +76 -0
  50. package/dist/commands/index.d.ts.map +1 -0
  51. package/dist/commands/index.js +62 -0
  52. package/dist/commands/index.js.map +1 -0
  53. package/dist/commands/page.d.ts +80 -0
  54. package/dist/commands/page.d.ts.map +1 -0
  55. package/dist/commands/page.js +100 -0
  56. package/dist/commands/page.js.map +1 -0
  57. package/dist/completion/index.d.ts +37 -0
  58. package/dist/completion/index.d.ts.map +1 -0
  59. package/dist/completion/index.js +87 -0
  60. package/dist/completion/index.js.map +1 -0
  61. package/dist/config.d.ts +20 -0
  62. package/dist/config.d.ts.map +1 -0
  63. package/dist/config.js +61 -0
  64. package/dist/config.js.map +1 -0
  65. package/dist/credentials.d.ts +48 -0
  66. package/dist/credentials.d.ts.map +1 -0
  67. package/dist/credentials.js +120 -0
  68. package/dist/credentials.js.map +1 -0
  69. package/dist/dev/bin.d.ts +3 -0
  70. package/dist/dev/bin.d.ts.map +1 -0
  71. package/dist/dev/bin.js +8 -0
  72. package/dist/dev/bin.js.map +1 -0
  73. package/dist/dev/main.d.ts +7 -0
  74. package/dist/dev/main.d.ts.map +1 -0
  75. package/dist/dev/main.js +149 -0
  76. package/dist/dev/main.js.map +1 -0
  77. package/dist/dev/next-version.d.ts +11 -0
  78. package/dist/dev/next-version.d.ts.map +1 -0
  79. package/dist/dev/next-version.js +33 -0
  80. package/dist/dev/next-version.js.map +1 -0
  81. package/dist/dev/slow-tests.d.ts +14 -0
  82. package/dist/dev/slow-tests.d.ts.map +1 -0
  83. package/dist/dev/slow-tests.js +17 -0
  84. package/dist/dev/slow-tests.js.map +1 -0
  85. package/dist/dev/test-matrix.d.ts +35 -0
  86. package/dist/dev/test-matrix.d.ts.map +1 -0
  87. package/dist/dev/test-matrix.js +93 -0
  88. package/dist/dev/test-matrix.js.map +1 -0
  89. package/dist/errors.d.ts +34 -0
  90. package/dist/errors.d.ts.map +1 -0
  91. package/dist/errors.js +36 -0
  92. package/dist/errors.js.map +1 -0
  93. package/dist/exit-codes.d.ts +11 -0
  94. package/dist/exit-codes.d.ts.map +1 -0
  95. package/dist/exit-codes.js +25 -0
  96. package/dist/exit-codes.js.map +1 -0
  97. package/dist/http/index.d.ts +20 -0
  98. package/dist/http/index.d.ts.map +1 -0
  99. package/dist/http/index.js +46 -0
  100. package/dist/http/index.js.map +1 -0
  101. package/dist/index.d.ts +16 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +15 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/keyring.d.ts +27 -0
  106. package/dist/keyring.d.ts.map +1 -0
  107. package/dist/keyring.js +45 -0
  108. package/dist/keyring.js.map +1 -0
  109. package/dist/logger.d.ts +12 -0
  110. package/dist/logger.d.ts.map +1 -0
  111. package/dist/logger.js +7 -0
  112. package/dist/logger.js.map +1 -0
  113. package/dist/logging.d.ts +31 -0
  114. package/dist/logging.d.ts.map +1 -0
  115. package/dist/logging.js +58 -0
  116. package/dist/logging.js.map +1 -0
  117. package/dist/mcp/index.d.ts +32 -0
  118. package/dist/mcp/index.d.ts.map +1 -0
  119. package/dist/mcp/index.js +105 -0
  120. package/dist/mcp/index.js.map +1 -0
  121. package/dist/paths.d.ts +28 -0
  122. package/dist/paths.d.ts.map +1 -0
  123. package/dist/paths.js +23 -0
  124. package/dist/paths.js.map +1 -0
  125. package/dist/pretty.d.ts +12 -0
  126. package/dist/pretty.d.ts.map +1 -0
  127. package/dist/pretty.js +83 -0
  128. package/dist/pretty.js.map +1 -0
  129. package/dist/release/index.d.ts +38 -0
  130. package/dist/release/index.d.ts.map +1 -0
  131. package/dist/release/index.js +91 -0
  132. package/dist/release/index.js.map +1 -0
  133. package/dist/release/markdown.d.ts +36 -0
  134. package/dist/release/markdown.d.ts.map +1 -0
  135. package/dist/release/markdown.js +153 -0
  136. package/dist/release/markdown.js.map +1 -0
  137. package/dist/release/structure.d.ts +16 -0
  138. package/dist/release/structure.d.ts.map +1 -0
  139. package/dist/release/structure.js +74 -0
  140. package/dist/release/structure.js.map +1 -0
  141. package/dist/renderer.d.ts +34 -0
  142. package/dist/renderer.d.ts.map +1 -0
  143. package/dist/renderer.js +55 -0
  144. package/dist/renderer.js.map +1 -0
  145. package/dist/retry.d.ts +27 -0
  146. package/dist/retry.d.ts.map +1 -0
  147. package/dist/retry.js +26 -0
  148. package/dist/retry.js.map +1 -0
  149. package/dist/sanitize.d.ts +25 -0
  150. package/dist/sanitize.d.ts.map +1 -0
  151. package/dist/sanitize.js +52 -0
  152. package/dist/sanitize.js.map +1 -0
  153. package/dist/skill/index.d.ts +78 -0
  154. package/dist/skill/index.d.ts.map +1 -0
  155. package/dist/skill/index.js +190 -0
  156. package/dist/skill/index.js.map +1 -0
  157. package/dist/streams.d.ts +24 -0
  158. package/dist/streams.d.ts.map +1 -0
  159. package/dist/streams.js +26 -0
  160. package/dist/streams.js.map +1 -0
  161. package/dist/testing/index.d.ts +24 -0
  162. package/dist/testing/index.d.ts.map +1 -0
  163. package/dist/testing/index.js +29 -0
  164. package/dist/testing/index.js.map +1 -0
  165. package/dist/time.d.ts +21 -0
  166. package/dist/time.d.ts.map +1 -0
  167. package/dist/time.js +19 -0
  168. package/dist/time.js.map +1 -0
  169. package/dist/update/index.d.ts +80 -0
  170. package/dist/update/index.d.ts.map +1 -0
  171. package/dist/update/index.js +159 -0
  172. package/dist/update/index.js.map +1 -0
  173. package/package.json +116 -2
@@ -0,0 +1,16 @@
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 { CliError, type CliErrorDetails, type ErrorCode, errorCodes, isCliError } from "./errors.js";
5
+ export { EXIT_CODES, exitCodeFor, GENERIC_FAILURE } from "./exit-codes.js";
6
+ export { brokenKeyring, type KeyringStore, memoryKeyring, systemKeyring } from "./keyring.js";
7
+ export { type Logger, noopLogger } from "./logger.js";
8
+ export { createFileLogger, type FileLogger, type FileLoggerOptions, REDACTED_FIELDS } from "./logging.js";
9
+ export { configFilePath, type Paths, type PathsOptions, pathsAreOverridden, resolvePaths } from "./paths.js";
10
+ export { indent, type PrettyOptions, renderPretty } from "./pretty.js";
11
+ export { createRenderer, RENDER_FORMATS, type Renderer, type RendererOptions, type RenderFormat, } from "./renderer.js";
12
+ export { backoffMs, DEFAULT_RETRY, isTransportFailure, type RetryConfig } from "./retry.js";
13
+ export { singleLine, visibleControls } from "./sanitize.js";
14
+ export { captureStreams, processStreams, type Streams } from "./streams.js";
15
+ export { abortError, type MonotonicClock, monotonic, realSleep, type SleepLike, type SleepReason, type WallClock, wallClock, } from "./time.js";
16
+ //# 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,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,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,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,15 @@
1
+ export { loadConfigFile, saveConfigFile, writeSecurely } from "./config.js";
2
+ export { CREDENTIAL_STORAGE, Credentials, keyringService } from "./credentials.js";
3
+ export { CliError, errorCodes, isCliError } from "./errors.js";
4
+ export { EXIT_CODES, exitCodeFor, GENERIC_FAILURE } from "./exit-codes.js";
5
+ export { brokenKeyring, memoryKeyring, systemKeyring } from "./keyring.js";
6
+ export { noopLogger } from "./logger.js";
7
+ export { createFileLogger, REDACTED_FIELDS } from "./logging.js";
8
+ export { configFilePath, pathsAreOverridden, resolvePaths } from "./paths.js";
9
+ export { indent, renderPretty } from "./pretty.js";
10
+ export { createRenderer, RENDER_FORMATS, } from "./renderer.js";
11
+ export { backoffMs, DEFAULT_RETRY, isTransportFailure } from "./retry.js";
12
+ export { singleLine, visibleControls } from "./sanitize.js";
13
+ export { captureStreams, processStreams } from "./streams.js";
14
+ export { abortError, monotonic, realSleep, wallClock, } from "./time.js";
15
+ //# 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,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,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,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"}
@@ -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,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,7 @@
1
+ export const noopLogger = {
2
+ debug: () => { },
3
+ info: () => { },
4
+ warn: () => { },
5
+ error: () => { },
6
+ };
7
+ //# sourceMappingURL=logger.js.map
@@ -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"}
@@ -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"}
@@ -0,0 +1,32 @@
1
+ import { type ChildProcessWithoutNullStreams } from "node:child_process";
2
+ export type McpClient = "codex" | "claude-code";
3
+ export interface StdioEntry {
4
+ type: "stdio";
5
+ command: string;
6
+ args: string[];
7
+ env?: Record<string, string>;
8
+ }
9
+ export interface CommandResult {
10
+ status: number | null;
11
+ error?: Error;
12
+ stdout: string;
13
+ stderr: string;
14
+ }
15
+ export type RunCommand = (file: string, args: string[]) => CommandResult;
16
+ export declare const setupArguments: (client: McpClient, name: string, entry: StdioEntry) => string[];
17
+ export declare const installStdioEntry: (client: McpClient, name: string, entry: StdioEntry, { run }?: {
18
+ run?: RunCommand;
19
+ }) => {
20
+ client: McpClient;
21
+ name: string;
22
+ command: string[];
23
+ };
24
+ export interface ProbeResult {
25
+ tools: string[];
26
+ potentialWrites: string[];
27
+ }
28
+ export declare const probeStdio: (entry: StdioEntry, { timeoutMs, start, }?: {
29
+ timeoutMs?: number;
30
+ start?: (file: string, args: string[], env: NodeJS.ProcessEnv) => ChildProcessWithoutNullStreams;
31
+ }) => Promise<ProbeResult>;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,8BAA8B,EAAS,MAAM,oBAAoB,CAAA;AAG/E,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,aAAa,CAAA;AAE/C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,aAAa,CAAA;AASxE,eAAO,MAAM,cAAc,WAAY,SAAS,QAAQ,MAAM,SAAS,UAAU,KAAG,MAAM,EAIzF,CAAA;AAED,eAAO,MAAM,iBAAiB,WACpB,SAAS,QACX,MAAM,SACL,UAAU,YACE;IAAE,GAAG,CAAC,EAAE,UAAU,CAAA;CAAE,KACtC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CActD,CAAA;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,eAAe,EAAE,MAAM,EAAE,CAAA;CAC1B;AAED,eAAO,MAAM,UAAU,UACd,UAAU,0BAId;IACD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,KAAK,8BAA8B,CAAA;CACjG,KACA,OAAO,CAAC,WAAW,CAkErB,CAAA"}
@@ -0,0 +1,105 @@
1
+ import { spawn } from "node:child_process";
2
+ import crossSpawn from "cross-spawn";
3
+ const realRun = (file, args) => {
4
+ const result = crossSpawn.sync(file, args, { encoding: "utf8", timeout: 10_000, maxBuffer: 256_000 });
5
+ return { status: result.status, error: result.error, stdout: result.stdout ?? "", stderr: result.stderr ?? "" };
6
+ };
7
+ const executable = (client) => (client === "codex" ? "codex" : "claude");
8
+ export const setupArguments = (client, name, entry) => {
9
+ const variables = Object.entries(entry.env ?? {}).flatMap(([key, value]) => ["--env", `${key}=${value}`]);
10
+ if (client === "codex")
11
+ return ["mcp", "add", name, ...variables, "--", entry.command, ...entry.args];
12
+ return ["mcp", "add", "--scope", "user", name, ...variables, "--", entry.command, ...entry.args];
13
+ };
14
+ export const installStdioEntry = (client, name, entry, { run = realRun } = {}) => {
15
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name))
16
+ throw new Error("the MCP name must be letters, digits, _ or -");
17
+ if (!entry.command || entry.args.some((arg) => arg.includes("\0")))
18
+ throw new Error("invalid MCP command");
19
+ const file = executable(client);
20
+ const existing = run(file, ["mcp", "get", name, ...(client === "codex" ? ["--json"] : [])]);
21
+ if (existing.error)
22
+ throw new Error(`${file} is not installed or could not be started`);
23
+ if (existing.status === 0)
24
+ throw new Error(`${name} is already configured in ${file}; remove it there first`);
25
+ if (existing.status !== 0 && !/No MCP server named/i.test(existing.stdout + existing.stderr)) {
26
+ throw new Error(`${file} could not check its MCP configuration`);
27
+ }
28
+ const args = setupArguments(client, name, entry);
29
+ const added = run(file, args);
30
+ if (added.status !== 0 || added.error)
31
+ throw new Error(`${file} could not add ${name}`);
32
+ return { client, name, command: [entry.command, ...entry.args] };
33
+ };
34
+ export const probeStdio = async (entry, { timeoutMs = 10_000, start = (file, args, env) => spawn(file, args, { env, stdio: "pipe" }), } = {}) => {
35
+ const child = start(entry.command, entry.args, { ...process.env, ...entry.env });
36
+ let buffer = "";
37
+ let timer;
38
+ const pending = new Map();
39
+ const request = (id, method, params) => new Promise((resolve, reject) => {
40
+ pending.set(id, { resolve, reject });
41
+ child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}\n`);
42
+ });
43
+ const fail = (error) => {
44
+ for (const waiter of pending.values())
45
+ waiter.reject(error);
46
+ pending.clear();
47
+ };
48
+ child.on("error", () => fail(new Error("the MCP server could not be started")));
49
+ child.on("exit", () => fail(new Error("the MCP server exited before answering")));
50
+ child.stdin.on("error", () => fail(new Error("the MCP server closed its input")));
51
+ child.stdout.setEncoding("utf8");
52
+ child.stdout.on("data", (chunk) => {
53
+ buffer += chunk;
54
+ if (buffer.length > 1_000_000)
55
+ return fail(new Error("the MCP server sent too much output"));
56
+ for (let newline = buffer.indexOf("\n"); newline !== -1; newline = buffer.indexOf("\n")) {
57
+ const line = buffer.slice(0, newline);
58
+ buffer = buffer.slice(newline + 1);
59
+ try {
60
+ const value = JSON.parse(line);
61
+ if (typeof value.id !== "number")
62
+ continue;
63
+ const waiter = pending.get(value.id);
64
+ if (!waiter)
65
+ continue;
66
+ pending.delete(value.id);
67
+ if (value.error)
68
+ waiter.reject(new Error("the MCP server rejected the handshake"));
69
+ else
70
+ waiter.resolve(value.result ?? {});
71
+ }
72
+ catch {
73
+ fail(new Error("the MCP server sent invalid JSON"));
74
+ }
75
+ }
76
+ });
77
+ try {
78
+ timer = setTimeout(() => fail(new Error("the MCP server did not answer in time")), timeoutMs);
79
+ await request(1, "initialize", {
80
+ protocolVersion: "2025-11-25",
81
+ capabilities: {},
82
+ clientInfo: { name: "cli-core-mcp-doctor", version: "1" },
83
+ });
84
+ child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" })}\n`);
85
+ const result = await request(2, "tools/list", {});
86
+ const tools = result.tools;
87
+ if (!Array.isArray(tools))
88
+ throw new Error("the MCP server returned no tool list");
89
+ const named = tools.filter((item) => item !== null && typeof item === "object" && "name" in item && typeof item.name === "string");
90
+ if (named.length !== tools.length)
91
+ throw new Error("the MCP server returned an invalid tool list");
92
+ return {
93
+ tools: named.map((item) => item.name),
94
+ potentialWrites: named.filter((item) => item.annotations?.readOnlyHint !== true).map((item) => item.name),
95
+ };
96
+ }
97
+ finally {
98
+ if (timer)
99
+ clearTimeout(timer);
100
+ pending.clear();
101
+ child.stdin.end();
102
+ child.kill();
103
+ }
104
+ };
105
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface Paths {
2
+ /** `config.json`, and the credential file when the keyring is unavailable. */
3
+ config: string;
4
+ /** Everything the program writes for itself: sessions, run artifacts, databases. */
5
+ state: string;
6
+ /** Data that can be deleted without losing anything the user typed. */
7
+ cache: string;
8
+ }
9
+ export interface PathsOptions {
10
+ /** Directory name under the OS convention — the command's name, not the package's. */
11
+ appName: string;
12
+ /**
13
+ * Environment variable prefix for the overrides, e.g. `MAX` gives `MAX_CONFIG_DIR`.
14
+ * Defaults to the app name, upper-cased, with anything that is not a letter or digit as `_`.
15
+ */
16
+ prefix?: string;
17
+ env?: NodeJS.ProcessEnv;
18
+ }
19
+ /**
20
+ * `env-paths` rather than a hand-rolled `~/.config`, so macOS and Windows land where those systems
21
+ * expect. Each directory is overridable by environment variable, which is what makes a test —
22
+ * and a throwaway profile — possible without touching the real ones.
23
+ */
24
+ export declare const resolvePaths: ({ appName, prefix, env }: PathsOptions) => Paths;
25
+ /** Whether any of the three directories came from the environment rather than the OS convention. */
26
+ export declare const pathsAreOverridden: ({ appName, prefix, env }: PathsOptions) => boolean;
27
+ export declare const configFilePath: (configDir: string, fileName?: string) => string;
28
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +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;CACxB;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,6BAA4C,YAAY,KAAG,KASnF,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,6BAA4C,YAAY,KAAG,OAGzF,CAAA;AAED,eAAO,MAAM,cAAc,cAAe,MAAM,wBAA6B,MAAmC,CAAA"}
package/dist/paths.js ADDED
@@ -0,0 +1,23 @@
1
+ import { join } from "node:path";
2
+ import envPaths from "env-paths";
3
+ /**
4
+ * `env-paths` rather than a hand-rolled `~/.config`, so macOS and Windows land where those systems
5
+ * expect. Each directory is overridable by environment variable, which is what makes a test —
6
+ * and a throwaway profile — possible without touching the real ones.
7
+ */
8
+ export const resolvePaths = ({ appName, prefix, env = process.env }) => {
9
+ const base = envPaths(appName, { suffix: "" });
10
+ const key = (name) => `${prefix ?? appName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_${name}`;
11
+ return {
12
+ config: env[key("CONFIG_DIR")] ?? base.config,
13
+ state: env[key("STATE_DIR")] ?? base.data,
14
+ cache: env[key("CACHE_DIR")] ?? base.cache,
15
+ };
16
+ };
17
+ /** Whether any of the three directories came from the environment rather than the OS convention. */
18
+ export const pathsAreOverridden = ({ appName, prefix, env = process.env }) => {
19
+ const stem = prefix ?? appName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
20
+ return ["CONFIG_DIR", "STATE_DIR", "CACHE_DIR"].some((name) => env[`${stem}_${name}`] !== undefined);
21
+ };
22
+ export const configFilePath = (configDir, fileName = "config.json") => join(configDir, fileName);
23
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,QAAQ,MAAM,WAAW,CAAA;AAsBhC;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAgB,EAAS,EAAE;IAC1F,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IAC9C,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAA;IAErG,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM;QAC7C,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI;QACzC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK;KAC3C,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;IAClG,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAA;IACvE,OAAO,CAAC,YAAY,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,KAAK,SAAS,CAAC,CAAA;AACtG,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAAiB,EAAE,QAAQ,GAAG,aAAa,EAAU,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA"}
@@ -0,0 +1,12 @@
1
+ export interface PrettyOptions {
2
+ color: boolean;
3
+ }
4
+ /**
5
+ * Three shapes and a fallback, not a renderer per endpoint. A list of like objects becomes a
6
+ * table, a single object becomes labelled lines, everything else is printed as JSON — which is
7
+ * honest about the fact that we do not know what it is.
8
+ */
9
+ export declare const renderPretty: (value: unknown, options: PrettyOptions) => string;
10
+ /** Shifts every line right; an empty line stays empty, so no trailing spaces reach the terminal. */
11
+ export declare const indent: (text: string, spaces: number) => string;
12
+ //# sourceMappingURL=pretty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pretty.d.ts","sourceRoot":"","sources":["../src/pretty.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAA;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,OAAO,WAAW,aAAa,KAAG,MAmBrE,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,MAAM,SAAU,MAAM,UAAU,MAAM,KAAG,MAIvC,CAAA"}
package/dist/pretty.js ADDED
@@ -0,0 +1,83 @@
1
+ import Table from "cli-table3";
2
+ import pc from "picocolors";
3
+ import { visibleControls } from "./sanitize.js";
4
+ /**
5
+ * Three shapes and a fallback, not a renderer per endpoint. A list of like objects becomes a
6
+ * table, a single object becomes labelled lines, everything else is printed as JSON — which is
7
+ * honest about the fact that we do not know what it is.
8
+ */
9
+ export const renderPretty = (value, options) => {
10
+ const paint = palette(options.color);
11
+ if (Array.isArray(value)) {
12
+ if (value.length === 0)
13
+ return paint.dim("(nothing)");
14
+ return isRowLike(value) ? renderTable(value, paint) : renderJson(value);
15
+ }
16
+ if (isPlainObject(value)) {
17
+ const listKey = Object.keys(value).find((key) => Array.isArray(value[key]) && isRowLike(value[key]));
18
+ if (listKey) {
19
+ const rest = Object.fromEntries(Object.entries(value).filter(([key]) => key !== listKey));
20
+ const table = renderTable(value[listKey], paint);
21
+ return Object.keys(rest).length > 0 ? `${table}\n\n${renderFields(rest, paint)}` : table;
22
+ }
23
+ return renderFields(value, paint);
24
+ }
25
+ return renderJson(value);
26
+ };
27
+ /** Shifts every line right; an empty line stays empty, so no trailing spaces reach the terminal. */
28
+ export const indent = (text, spaces) => text
29
+ .split("\n")
30
+ .map((line) => (line === "" ? line : `${" ".repeat(spaces)}${line}`))
31
+ .join("\n");
32
+ const palette = (color) => ({
33
+ dim: (text) => (color ? pc.dim(text) : text),
34
+ bold: (text) => (color ? pc.bold(text) : text),
35
+ label: (text) => (color ? pc.cyan(text) : text),
36
+ });
37
+ const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
38
+ const isRowLike = (value) => value.length > 0 && value.every((item) => isPlainObject(item)) && value.length <= 500;
39
+ const renderTable = (rows, paint) => {
40
+ const columns = [...new Set(rows.flatMap((row) => Object.keys(row)))];
41
+ const table = new Table({
42
+ head: columns.map((column) => paint.bold(visibleControls(column))),
43
+ // `chars: {}` is not enough — cli-table3 falls back to its own defaults for anything unset.
44
+ style: { head: [], border: [], "padding-left": 0, "padding-right": 2 },
45
+ chars: BORDERLESS,
46
+ });
47
+ for (const row of rows)
48
+ table.push(columns.map((column) => cell(row[column])));
49
+ return table.toString();
50
+ };
51
+ const renderFields = (fields, paint) => {
52
+ const rows = Object.entries(fields).map(([key, value]) => ({ label: visibleControls(key), value }));
53
+ const width = Math.max(...rows.map((row) => row.label.length));
54
+ return rows.map((row) => `${paint.label(row.label.padEnd(width))} ${cell(row.value)}`).join("\n");
55
+ };
56
+ const cell = (value) => {
57
+ if (value === null || value === undefined)
58
+ return "";
59
+ // Sanitised before the table measures it, so an escaped sequence widens the column it is in
60
+ // rather than silently overflowing it.
61
+ if (typeof value === "object")
62
+ return visibleControls(JSON.stringify(value));
63
+ return visibleControls(String(value));
64
+ };
65
+ const renderJson = (value) => JSON.stringify(value, null, 2);
66
+ const BORDERLESS = {
67
+ top: "",
68
+ "top-mid": "",
69
+ "top-left": "",
70
+ "top-right": "",
71
+ bottom: "",
72
+ "bottom-mid": "",
73
+ "bottom-left": "",
74
+ "bottom-right": "",
75
+ left: "",
76
+ "left-mid": "",
77
+ mid: "",
78
+ "mid-mid": "",
79
+ right: "",
80
+ "right-mid": "",
81
+ middle: "",
82
+ };
83
+ //# sourceMappingURL=pretty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pretty.js","sourceRoot":"","sources":["../src/pretty.ts"],"names":[],"mappings":"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"}