@wirecat/cli-base 0.0.0-stage → 0.22.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 +390 -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/document.d.ts +72 -0
- package/dist/commands/document.d.ts.map +1 -0
- package/dist/commands/document.js +71 -0
- package/dist/commands/document.js.map +1 -0
- package/dist/commands/index.d.ts +83 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +85 -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/lint.d.ts +31 -0
- package/dist/dev/lint.d.ts.map +1 -0
- package/dist/dev/lint.js +148 -0
- package/dist/dev/lint.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 +279 -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 +40 -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/standards/errors.d.ts +40 -0
- package/dist/standards/errors.d.ts.map +1 -0
- package/dist/standards/errors.js +33 -0
- package/dist/standards/errors.js.map +1 -0
- package/dist/standards/index.d.ts +8 -0
- package/dist/standards/index.d.ts.map +1 -0
- package/dist/standards/index.js +8 -0
- package/dist/standards/index.js.map +1 -0
- package/dist/standards/lint.d.ts +29 -0
- package/dist/standards/lint.d.ts.map +1 -0
- package/dist/standards/lint.js +50 -0
- package/dist/standards/lint.js.map +1 -0
- package/dist/standards/log.d.ts +21 -0
- package/dist/standards/log.d.ts.map +1 -0
- package/dist/standards/log.js +18 -0
- package/dist/standards/log.js.map +1 -0
- package/dist/standards/output.d.ts +126 -0
- package/dist/standards/output.d.ts.map +1 -0
- package/dist/standards/output.js +54 -0
- package/dist/standards/output.js.map +1 -0
- package/dist/standards/registry.d.ts +18 -0
- package/dist/standards/registry.d.ts.map +1 -0
- package/dist/standards/registry.js +41 -0
- package/dist/standards/registry.js.map +1 -0
- package/dist/standards/steps.d.ts +28 -0
- package/dist/standards/steps.d.ts.map +1 -0
- package/dist/standards/steps.js +56 -0
- package/dist/standards/steps.js.map +1 -0
- package/dist/standards/vocabulary.d.ts +40 -0
- package/dist/standards/vocabulary.d.ts.map +1 -0
- package/dist/standards/vocabulary.js +242 -0
- package/dist/standards/vocabulary.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 +135 -4
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The command registry: the whole command tree of a CLI as data, however each command came to be.
|
|
3
|
+
*
|
|
4
|
+
* It walks the live Commander tree rather than a list written by hand, so a command built in a
|
|
5
|
+
* loop from a catalog shows up exactly like one written in a file. What the tree cannot say — where
|
|
6
|
+
* a command came from, whether it changes anything, whether it is on its way out — is attached with
|
|
7
|
+
* `annotate`.
|
|
8
|
+
*
|
|
9
|
+
* Behind its own entry point for the same reason `/http` is: Commander is only a type here, and the
|
|
10
|
+
* root of this package stays free of any command-line framework.
|
|
11
|
+
*/
|
|
12
|
+
import type { Command } from "commander";
|
|
13
|
+
export type Origin = "handwritten" | "generated";
|
|
14
|
+
export type CommandState = "beta" | "deprecated";
|
|
15
|
+
export interface CommandMeta {
|
|
16
|
+
origin?: Origin;
|
|
17
|
+
/** The catalog operation a generated command was made from. */
|
|
18
|
+
operationId?: string;
|
|
19
|
+
/** True when running the command changes something: a write, wherever it lands. */
|
|
20
|
+
mutates?: boolean;
|
|
21
|
+
/** With `mutates`: what it changes is only on this machine — a file, the keyring — never the service. */
|
|
22
|
+
local?: boolean;
|
|
23
|
+
state?: CommandState;
|
|
24
|
+
examples?: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
export interface ArgumentInfo {
|
|
27
|
+
name: string;
|
|
28
|
+
required: boolean;
|
|
29
|
+
variadic: boolean;
|
|
30
|
+
description: string;
|
|
31
|
+
choices?: readonly string[];
|
|
32
|
+
default?: unknown;
|
|
33
|
+
}
|
|
34
|
+
export interface OptionInfo {
|
|
35
|
+
flags: string;
|
|
36
|
+
description: string;
|
|
37
|
+
/** False for a plain switch like `--json`, so an agent knows not to look for a value. */
|
|
38
|
+
takesValue: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the option itself must be given. Deliberately not Commander's `required`, which means
|
|
41
|
+
* "takes a value when present" — reading that as "you must pass this" is the obvious misreading.
|
|
42
|
+
*/
|
|
43
|
+
mandatory: boolean;
|
|
44
|
+
choices?: readonly string[];
|
|
45
|
+
default?: unknown;
|
|
46
|
+
env?: string;
|
|
47
|
+
/** Options that may not be given together with this one. */
|
|
48
|
+
conflicts?: readonly string[];
|
|
49
|
+
/** Values this option sets on others when they are not given. */
|
|
50
|
+
implies?: Readonly<Record<string, unknown>>;
|
|
51
|
+
}
|
|
52
|
+
export interface CommandInfo {
|
|
53
|
+
/** What to pass to the CLI, already split: `["runs", "list"]`. */
|
|
54
|
+
path: readonly string[];
|
|
55
|
+
name: string;
|
|
56
|
+
summary?: string;
|
|
57
|
+
description: string;
|
|
58
|
+
usage: string;
|
|
59
|
+
origin: Origin;
|
|
60
|
+
operationId?: string;
|
|
61
|
+
mutates?: boolean;
|
|
62
|
+
local?: boolean;
|
|
63
|
+
state?: CommandState;
|
|
64
|
+
examples?: readonly string[];
|
|
65
|
+
arguments: readonly ArgumentInfo[];
|
|
66
|
+
options: readonly OptionInfo[];
|
|
67
|
+
commands: readonly CommandInfo[];
|
|
68
|
+
}
|
|
69
|
+
/** Attaches what the tree cannot say. Repeated calls merge; the command is returned for chaining. */
|
|
70
|
+
export declare const annotate: <T extends Command>(command: T, meta: CommandMeta) => T;
|
|
71
|
+
export declare const metaOf: (command: Command) => CommandMeta;
|
|
72
|
+
export declare const describeProgram: (root: Command) => CommandInfo[];
|
|
73
|
+
export declare const describeOptions: (command: Command) => OptionInfo[];
|
|
74
|
+
export declare const flatten: (commands: readonly CommandInfo[]) => CommandInfo[];
|
|
75
|
+
export { type CommandsDocument, type CommandsDocumentAbout, commandsDocument, commandsDocumentJsonSchema, commandsDocumentSchema, parseCommandsDocument, } from "./document.js";
|
|
76
|
+
export { COMMANDS_PAGE_LABELS, type CommandsPage, type CommandsPageLabels, type CommandsPageText, commandsPage, } from "./page.js";
|
|
77
|
+
/**
|
|
78
|
+
* Refuses a command path that arrived as one argument — `"projects add" --help`, what a zsh loop over
|
|
79
|
+
* `$c` passes. Commander settles `--help` for an unknown word before any hook runs and prints the root
|
|
80
|
+
* help, so the words are checked before parsing. Pass the words after a leading profile, if any.
|
|
81
|
+
*/
|
|
82
|
+
export declare const refuseJoinedPath: (root: Command, args: readonly string[]) => void;
|
|
83
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAY,OAAO,EAAU,MAAM,WAAW,CAAA;AAG1D,MAAM,MAAM,MAAM,GAAG,aAAa,GAAG,WAAW,CAAA;AAChD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,YAAY,CAAA;AAEhD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yGAAyG;IACzG,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,yFAAyF;IACzF,UAAU,EAAE,OAAO,CAAA;IACnB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,4DAA4D;IAC5D,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7B,iEAAiE;IACjE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAC5C;AAED,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,SAAS,EAAE,SAAS,YAAY,EAAE,CAAA;IAClC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IAC9B,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;CACjC;AAID,qGAAqG;AACrG,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,OAAO,WAAW,CAAC,QAAQ,WAAW,KAAG,CAG3E,CAAA;AAED,eAAO,MAAM,MAAM,YAAa,OAAO,KAAG,WAAwC,CAAA;AAElF,eAAO,MAAM,eAAe,SAAU,OAAO,KAAG,WAAW,EACK,CAAA;AAEhE,eAAO,MAAM,eAAe,YAAa,OAAO,KAAG,UAAU,EACW,CAAA;AAExE,eAAO,MAAM,OAAO,aAAc,SAAS,WAAW,EAAE,KAAG,WAAW,EACE,CAAA;AA8DxE,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,gBAAgB,EAChB,0BAA0B,EAC1B,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,oBAAoB,EACpB,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,YAAY,GACb,MAAM,WAAW,CAAA;AAElB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,SAAU,OAAO,QAAQ,SAAS,MAAM,EAAE,KAAG,IAgBzE,CAAA"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { CliError } from "../errors.js";
|
|
2
|
+
const labels = new WeakMap();
|
|
3
|
+
/** Attaches what the tree cannot say. Repeated calls merge; the command is returned for chaining. */
|
|
4
|
+
export const annotate = (command, meta) => {
|
|
5
|
+
labels.set(command, { ...labels.get(command), ...meta });
|
|
6
|
+
return command;
|
|
7
|
+
};
|
|
8
|
+
export const metaOf = (command) => labels.get(command) ?? {};
|
|
9
|
+
export const describeProgram = (root) => visible(root).map((child) => describe(child, root.name(), []));
|
|
10
|
+
export const describeOptions = (command) => command.options.filter((option) => !option.hidden).map(describeOption);
|
|
11
|
+
export const flatten = (commands) => commands.flatMap((command) => [command, ...flatten(command.commands)]);
|
|
12
|
+
const describe = (command, cli, parents) => {
|
|
13
|
+
const path = [...parents, command.name()];
|
|
14
|
+
const args = command.registeredArguments.map(describeArgument);
|
|
15
|
+
const options = describeOptions(command);
|
|
16
|
+
const { origin = "handwritten", ...meta } = metaOf(command);
|
|
17
|
+
const usage = [
|
|
18
|
+
cli,
|
|
19
|
+
...path,
|
|
20
|
+
...args.map((argument) => (argument.required ? `<${argument.name}>` : `[${argument.name}]`)),
|
|
21
|
+
options.length > 0 ? "[options]" : "",
|
|
22
|
+
]
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.join(" ");
|
|
25
|
+
return {
|
|
26
|
+
path,
|
|
27
|
+
name: command.name(),
|
|
28
|
+
...(command.summary() ? { summary: command.summary() } : {}),
|
|
29
|
+
description: command.description(),
|
|
30
|
+
usage,
|
|
31
|
+
origin,
|
|
32
|
+
...meta,
|
|
33
|
+
arguments: args,
|
|
34
|
+
options,
|
|
35
|
+
commands: visible(command).map((child) => describe(child, cli, path)),
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
// `addCommand(command, { hidden: true })` sets only this; Commander has no public getter for it.
|
|
39
|
+
const visible = (command) => command.commands.filter((child) => !child._hidden);
|
|
40
|
+
const describeArgument = (argument) => ({
|
|
41
|
+
name: argument.name(),
|
|
42
|
+
required: argument.required,
|
|
43
|
+
variadic: argument.variadic,
|
|
44
|
+
description: argument.description,
|
|
45
|
+
...(argument.argChoices ? { choices: argument.argChoices } : {}),
|
|
46
|
+
...(argument.defaultValue === undefined ? {} : { default: argument.defaultValue }),
|
|
47
|
+
});
|
|
48
|
+
const describeOption = (option) => {
|
|
49
|
+
const { conflictsWith = [], implied } = option;
|
|
50
|
+
return {
|
|
51
|
+
flags: option.flags,
|
|
52
|
+
description: option.description,
|
|
53
|
+
takesValue: option.required || option.optional,
|
|
54
|
+
mandatory: option.mandatory,
|
|
55
|
+
...(option.argChoices ? { choices: option.argChoices } : {}),
|
|
56
|
+
...(option.defaultValue === undefined ? {} : { default: option.defaultValue }),
|
|
57
|
+
...(option.envVar ? { env: option.envVar } : {}),
|
|
58
|
+
...(conflictsWith.length > 0 ? { conflicts: conflictsWith } : {}),
|
|
59
|
+
...(implied ? { implies: implied } : {}),
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
export { commandsDocument, commandsDocumentJsonSchema, commandsDocumentSchema, parseCommandsDocument, } from "./document.js";
|
|
63
|
+
export { COMMANDS_PAGE_LABELS, commandsPage, } from "./page.js";
|
|
64
|
+
/**
|
|
65
|
+
* Refuses a command path that arrived as one argument — `"projects add" --help`, what a zsh loop over
|
|
66
|
+
* `$c` passes. Commander settles `--help` for an unknown word before any hook runs and prints the root
|
|
67
|
+
* help, so the words are checked before parsing. Pass the words after a leading profile, if any.
|
|
68
|
+
*/
|
|
69
|
+
export const refuseJoinedPath = (root, args) => {
|
|
70
|
+
let command = root;
|
|
71
|
+
const path = [];
|
|
72
|
+
for (const arg of args) {
|
|
73
|
+
if (arg.startsWith("-"))
|
|
74
|
+
return;
|
|
75
|
+
const [first = "", ...rest] = arg.trim().split(/\s+/);
|
|
76
|
+
const next = command.commands.find((child) => child.name() === first || child.aliases().includes(first));
|
|
77
|
+
if (next === undefined)
|
|
78
|
+
return;
|
|
79
|
+
if (rest.length > 0)
|
|
80
|
+
throw new CliError("validation_error", `"${arg}" was given as one argument; run: ${[root.name(), ...path, first, ...rest].join(" ")}`);
|
|
81
|
+
path.push(first);
|
|
82
|
+
command = next;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { CommandInfo, OptionInfo } from "./index.js";
|
|
2
|
+
/** The labels of the tables; the same for every CLI writing in one language. */
|
|
3
|
+
export type CommandsPageLabels = {
|
|
4
|
+
option: string;
|
|
5
|
+
does: string;
|
|
6
|
+
argument: string;
|
|
7
|
+
isWhat: string;
|
|
8
|
+
required: string;
|
|
9
|
+
optional: string;
|
|
10
|
+
/** Precedes a default: `Default` → "… Default: `20`." */
|
|
11
|
+
defaultIs: string;
|
|
12
|
+
/** Precedes the allowed values: `One of` → "… One of: `new`, `old`." */
|
|
13
|
+
oneOf: string;
|
|
14
|
+
code: string;
|
|
15
|
+
when: string;
|
|
16
|
+
success: string;
|
|
17
|
+
otherwise: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const COMMANDS_PAGE_LABELS: {
|
|
20
|
+
readonly en: {
|
|
21
|
+
readonly option: "Option";
|
|
22
|
+
readonly does: "What it does";
|
|
23
|
+
readonly argument: "Argument";
|
|
24
|
+
readonly isWhat: "What it is";
|
|
25
|
+
readonly required: "required";
|
|
26
|
+
readonly optional: "optional";
|
|
27
|
+
readonly defaultIs: "Default";
|
|
28
|
+
readonly oneOf: "One of";
|
|
29
|
+
readonly code: "Code";
|
|
30
|
+
readonly when: "When";
|
|
31
|
+
readonly success: "it worked";
|
|
32
|
+
readonly otherwise: "anything else";
|
|
33
|
+
};
|
|
34
|
+
readonly ru: {
|
|
35
|
+
readonly option: "Опция";
|
|
36
|
+
readonly does: "Что делает";
|
|
37
|
+
readonly argument: "Аргумент";
|
|
38
|
+
readonly isWhat: "Что это";
|
|
39
|
+
readonly required: "обязательный";
|
|
40
|
+
readonly optional: "необязательный";
|
|
41
|
+
readonly defaultIs: "По умолчанию";
|
|
42
|
+
readonly oneOf: "Одно из";
|
|
43
|
+
readonly code: "Код";
|
|
44
|
+
readonly when: "Когда";
|
|
45
|
+
readonly success: "получилось";
|
|
46
|
+
readonly otherwise: "всё остальное";
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
/** The CLI's own words: everything on the page that is not read out of the program. */
|
|
50
|
+
export type CommandsPageText = {
|
|
51
|
+
/** The first line, an HTML comment saying the page is generated and by what. */
|
|
52
|
+
banner: string;
|
|
53
|
+
title: string;
|
|
54
|
+
/** Markdown between the title and the global options. */
|
|
55
|
+
intro: string;
|
|
56
|
+
globalHeading: string;
|
|
57
|
+
globalIntro: string;
|
|
58
|
+
/** Shown under a command that changes something outside this machine. */
|
|
59
|
+
mutates: string;
|
|
60
|
+
/** Shown instead under a command marked `local`, which changes only this machine; without it, nothing is. */
|
|
61
|
+
mutatesLocal?: string;
|
|
62
|
+
exitHeading: string;
|
|
63
|
+
exitIntro: string;
|
|
64
|
+
/** Markdown after the exit codes; may be empty. */
|
|
65
|
+
outro: string;
|
|
66
|
+
};
|
|
67
|
+
export type CommandsPage = {
|
|
68
|
+
cli: string;
|
|
69
|
+
commands: readonly CommandInfo[];
|
|
70
|
+
options: readonly OptionInfo[];
|
|
71
|
+
labels: CommandsPageLabels;
|
|
72
|
+
text: CommandsPageText;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* The whole `docs/commands.md`: every command at any depth, every option and argument, the exit
|
|
76
|
+
* codes. Descriptions are quoted as `--help` prints them, untranslated — a translation here would
|
|
77
|
+
* give the sentence a second home, and the one on screen is the one that gets corrected.
|
|
78
|
+
*/
|
|
79
|
+
export declare const commandsPage: ({ cli, commands, options, labels, text }: CommandsPage) => string;
|
|
80
|
+
//# sourceMappingURL=page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/commands/page.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvE,gFAAgF;AAChF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,eAAO,MAAM,oBAAoB;;iBAE7B,MAAM,EAAE,QAAQ;iBAChB,IAAI,EAAE,cAAc;iBACpB,QAAQ,EAAE,UAAU;iBACpB,MAAM,EAAE,YAAY;iBACpB,QAAQ,EAAE,UAAU;iBACpB,QAAQ,EAAE,UAAU;iBACpB,SAAS,EAAE,SAAS;iBACpB,KAAK,EAAE,QAAQ;iBACf,IAAI,EAAE,MAAM;iBACZ,IAAI,EAAE,MAAM;iBACZ,OAAO,EAAE,WAAW;iBACpB,SAAS,EAAE,eAAe;;;iBAG1B,MAAM,EAAE,OAAO;iBACf,IAAI,EAAE,YAAY;iBAClB,QAAQ,EAAE,UAAU;iBACpB,MAAM,EAAE,SAAS;iBACjB,QAAQ,EAAE,cAAc;iBACxB,QAAQ,EAAE,gBAAgB;iBAC1B,SAAS,EAAE,cAAc;iBACzB,KAAK,EAAE,SAAS;iBAChB,IAAI,EAAE,KAAK;iBACX,IAAI,EAAE,OAAO;iBACb,OAAO,EAAE,YAAY;iBACrB,SAAS,EAAE,eAAe;;CAEyB,CAAA;AAEvD,uFAAuF;AACvF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAA;IACf,6GAA6G;IAC7G,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;IAChC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAA;IAC9B,MAAM,EAAE,kBAAkB,CAAA;IAC1B,IAAI,EAAE,gBAAgB,CAAA;CACvB,CAAA;AAWD;;;;GAIG;AACH,eAAO,MAAM,YAAY,6CAA8C,YAAY,KAAG,MAkErF,CAAA"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { EXIT_CODES } from "../exit-codes.js";
|
|
2
|
+
export const COMMANDS_PAGE_LABELS = {
|
|
3
|
+
en: {
|
|
4
|
+
option: "Option",
|
|
5
|
+
does: "What it does",
|
|
6
|
+
argument: "Argument",
|
|
7
|
+
isWhat: "What it is",
|
|
8
|
+
required: "required",
|
|
9
|
+
optional: "optional",
|
|
10
|
+
defaultIs: "Default",
|
|
11
|
+
oneOf: "One of",
|
|
12
|
+
code: "Code",
|
|
13
|
+
when: "When",
|
|
14
|
+
success: "it worked",
|
|
15
|
+
otherwise: "anything else",
|
|
16
|
+
},
|
|
17
|
+
ru: {
|
|
18
|
+
option: "Опция",
|
|
19
|
+
does: "Что делает",
|
|
20
|
+
argument: "Аргумент",
|
|
21
|
+
isWhat: "Что это",
|
|
22
|
+
required: "обязательный",
|
|
23
|
+
optional: "необязательный",
|
|
24
|
+
defaultIs: "По умолчанию",
|
|
25
|
+
oneOf: "Одно из",
|
|
26
|
+
code: "Код",
|
|
27
|
+
when: "Когда",
|
|
28
|
+
success: "получилось",
|
|
29
|
+
otherwise: "всё остальное",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
/** A cell that will not break the table it sits in; `~~struck~~` in a description would strike the row. */
|
|
33
|
+
const cell = (text) => (text ?? "").replace(/\|/g, "\\|").replace(/~/g, "\\~").replace(/\n+/g, " ").trim();
|
|
34
|
+
const sentence = (text) => {
|
|
35
|
+
const said = cell(text);
|
|
36
|
+
return said === "" || /[.!?]$/.test(said) ? said : `${said}.`;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The whole `docs/commands.md`: every command at any depth, every option and argument, the exit
|
|
40
|
+
* codes. Descriptions are quoted as `--help` prints them, untranslated — a translation here would
|
|
41
|
+
* give the sentence a second home, and the one on screen is the one that gets corrected.
|
|
42
|
+
*/
|
|
43
|
+
export const commandsPage = ({ cli, commands, options, labels, text }) => {
|
|
44
|
+
// What a value may be and what it is when left out: Commander keeps both out of the description.
|
|
45
|
+
const extras = ({ choices, default: fallback }) => [
|
|
46
|
+
choices ? ` ${labels.oneOf}: ${choices.map((choice) => `\`${choice}\``).join(", ")}.` : "",
|
|
47
|
+
fallback === undefined || fallback === false ? "" : ` ${labels.defaultIs}: \`${String(fallback)}\`.`,
|
|
48
|
+
].join("");
|
|
49
|
+
// The flags go through `cell` too: `--order <recent|name>` would otherwise split the row.
|
|
50
|
+
const optionRows = (list) => list.map((option) => `| \`${cell(option.flags)}\` | ${sentence(option.description)}${extras(option)} |`).join("\n");
|
|
51
|
+
const argumentRows = (list) => list
|
|
52
|
+
.map((argument) => `| \`${cell(argument.name)}\` | ${argument.required ? labels.required : labels.optional} | ${sentence(argument.description)}${extras(argument)} |`)
|
|
53
|
+
.join("\n");
|
|
54
|
+
const body = (command) => {
|
|
55
|
+
const parts = [cell(command.description), ""];
|
|
56
|
+
const label = command.mutates ? (command.local ? text.mutatesLocal : text.mutates) : undefined;
|
|
57
|
+
if (label)
|
|
58
|
+
parts.push(label, "");
|
|
59
|
+
parts.push("```sh", command.usage, "```");
|
|
60
|
+
if (command.arguments.length > 0)
|
|
61
|
+
parts.push("", `| ${labels.argument} | | ${labels.isWhat} |`, "|---|---|---|", argumentRows(command.arguments));
|
|
62
|
+
if (command.options.length > 0)
|
|
63
|
+
parts.push("", `| ${labels.option} | ${labels.does} |`, "|---|---|", optionRows(command.options));
|
|
64
|
+
return parts;
|
|
65
|
+
};
|
|
66
|
+
// A group shows its own usage only when it takes options of its own, as `doctor --online` does.
|
|
67
|
+
const section = (command, depth) => {
|
|
68
|
+
const heading = `${"#".repeat(Math.min(depth, 4))} \`${cli} ${command.path.join(" ")}\``;
|
|
69
|
+
if (command.commands.length === 0)
|
|
70
|
+
return [heading, "", ...body(command)].join("\n");
|
|
71
|
+
const own = command.options.length > 0 ? body(command) : [cell(command.description)];
|
|
72
|
+
return [heading, "", ...own, "", command.commands.map((child) => section(child, depth + 1)).join("\n\n")]
|
|
73
|
+
.join("\n")
|
|
74
|
+
.trimEnd();
|
|
75
|
+
};
|
|
76
|
+
const exitCodes = [
|
|
77
|
+
`| ${labels.code} | ${labels.when} |`,
|
|
78
|
+
"|---|---|",
|
|
79
|
+
`| \`0\` | ${labels.success} |`,
|
|
80
|
+
...Object.entries(EXIT_CODES).map(([name, code]) => `| \`${code}\` | \`${name}\` |`),
|
|
81
|
+
`| \`1\` | ${labels.otherwise} |`,
|
|
82
|
+
].join("\n");
|
|
83
|
+
return [
|
|
84
|
+
text.banner,
|
|
85
|
+
`# ${text.title}`,
|
|
86
|
+
text.intro,
|
|
87
|
+
`## ${text.globalHeading}`,
|
|
88
|
+
text.globalIntro,
|
|
89
|
+
[`| ${labels.option} | ${labels.does} |`, "|---|---|", optionRows(options)].join("\n"),
|
|
90
|
+
commands.map((command) => section(command, 2)).join("\n\n"),
|
|
91
|
+
`## ${text.exitHeading}`,
|
|
92
|
+
text.exitIntro,
|
|
93
|
+
exitCodes,
|
|
94
|
+
text.outro,
|
|
95
|
+
]
|
|
96
|
+
.filter((part) => part !== "")
|
|
97
|
+
.join("\n\n")
|
|
98
|
+
.concat("\n");
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/commands/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAqB7C,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,EAAE,EAAE;QACF,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,SAAS;QACpB,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,eAAe;KAC3B;IACD,EAAE,EAAE;QACF,MAAM,EAAE,OAAO;QACf,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,cAAc;QACxB,QAAQ,EAAE,gBAAgB;QAC1B,SAAS,EAAE,cAAc;QACzB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,YAAY;QACrB,SAAS,EAAE,eAAe;KAC3B;CACoD,CAAA;AA6BvD,2GAA2G;AAC3G,MAAM,IAAI,GAAG,CAAC,IAAwB,EAAU,EAAE,CAChD,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;AAErF,MAAM,QAAQ,GAAG,CAAC,IAAwB,EAAU,EAAE;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACvB,OAAO,IAAI,KAAK,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAA;AAC/D,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAgB,EAAU,EAAE;IAC7F,iGAAiG;IACjG,MAAM,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAsD,EAAE,EAAE,CACpG;QACE,OAAO,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC1F,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK;KACrG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEZ,0FAA0F;IAC1F,MAAM,UAAU,GAAG,CAAC,IAA2B,EAAE,EAAE,CACjD,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAErH,MAAM,YAAY,GAAG,CAAC,IAA6B,EAAE,EAAE,CACrD,IAAI;SACD,GAAG,CACF,CAAC,QAAQ,EAAE,EAAE,CACX,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,MAAM,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CACrJ;SACA,IAAI,CAAC,IAAI,CAAC,CAAA;IAEf,MAAM,IAAI,GAAG,CAAC,OAAoB,EAAY,EAAE;QAC9C,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAA;QAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC9F,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAChC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACzC,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,MAAM,CAAC,QAAQ,QAAQ,MAAM,CAAC,MAAM,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAA;QACjH,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,MAAM,CAAC,MAAM,MAAM,MAAM,CAAC,IAAI,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;QACnG,OAAO,KAAK,CAAA;IACd,CAAC,CAAA;IAED,gGAAgG;IAChG,MAAM,OAAO,GAAG,CAAC,OAAoB,EAAE,KAAa,EAAU,EAAE;QAC9D,MAAM,OAAO,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAA;QACxF,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACpF,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAA;QACpF,OAAO,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACtG,IAAI,CAAC,IAAI,CAAC;aACV,OAAO,EAAE,CAAA;IACd,CAAC,CAAA;IAED,MAAM,SAAS,GAAG;QAChB,KAAK,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,IAAI;QACrC,WAAW;QACX,aAAa,MAAM,CAAC,OAAO,IAAI;QAC/B,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,OAAO,IAAI,UAAU,IAAI,MAAM,CAAC;QACpF,aAAa,MAAM,CAAC,SAAS,IAAI;KAClC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,OAAO;QACL,IAAI,CAAC,MAAM;QACX,KAAK,IAAI,CAAC,KAAK,EAAE;QACjB,IAAI,CAAC,KAAK;QACV,MAAM,IAAI,CAAC,aAAa,EAAE;QAC1B,IAAI,CAAC,WAAW;QAChB,CAAC,KAAK,MAAM,CAAC,MAAM,MAAM,MAAM,CAAC,IAAI,IAAI,EAAE,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACtF,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3D,MAAM,IAAI,CAAC,WAAW,EAAE;QACxB,IAAI,CAAC,SAAS;QACd,SAAS;QACT,IAAI,CAAC,KAAK;KACX;SACE,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;SAC7B,IAAI,CAAC,MAAM,CAAC;SACZ,MAAM,CAAC,IAAI,CAAC,CAAA;AACjB,CAAC,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell completion over the command registry: which word may come next, as data.
|
|
3
|
+
*
|
|
4
|
+
* It speaks the protocol of the shell scripts `@bomb.sh/tab` generates — the shell runs
|
|
5
|
+
* `<cli> complete -- <words>` and reads `value<TAB>description` lines ending in `:<directive>` —
|
|
6
|
+
* so a CLI prints those scripts with tab and answers the requests with this. Nothing here reads a
|
|
7
|
+
* terminal, a file or the network: the words come in, the suggestions go out, and where values come
|
|
8
|
+
* from (a local cache, a config file) is the CLI's business, handed in as `sources`.
|
|
9
|
+
*/
|
|
10
|
+
import type { CommandInfo, OptionInfo } from "../commands/index.js";
|
|
11
|
+
export interface Suggestion {
|
|
12
|
+
value: string;
|
|
13
|
+
description: string;
|
|
14
|
+
}
|
|
15
|
+
/** Values for one argument or option. Called on every Tab, so it must be cheap and must not connect anywhere. */
|
|
16
|
+
export type Values = () => readonly (string | Suggestion)[];
|
|
17
|
+
export interface CompletionSources {
|
|
18
|
+
/** By argument name, as registered: `chat`, `person`. */
|
|
19
|
+
arguments?: Readonly<Record<string, Values>>;
|
|
20
|
+
/** By long option name without dashes: `chat` for `--chat <id>`. */
|
|
21
|
+
options?: Readonly<Record<string, Values>>;
|
|
22
|
+
/** Offered alongside the top-level commands — a profile name that may come first, say. */
|
|
23
|
+
firstWord?: Values;
|
|
24
|
+
}
|
|
25
|
+
export interface CompletionRequest {
|
|
26
|
+
commands: readonly CommandInfo[];
|
|
27
|
+
globalOptions?: readonly OptionInfo[];
|
|
28
|
+
/** Everything after `complete --`; the last word is the one being typed, `""` for a fresh one. */
|
|
29
|
+
words: readonly string[];
|
|
30
|
+
sources?: CompletionSources;
|
|
31
|
+
}
|
|
32
|
+
/** Tells the shell not to fall back to file names when nothing matched. */
|
|
33
|
+
export declare const NO_FILE_COMPLETION = 4;
|
|
34
|
+
export declare const suggest: ({ commands, globalOptions, words, sources }: CompletionRequest) => Suggestion[];
|
|
35
|
+
/** The answer in the form the shell script reads. */
|
|
36
|
+
export declare const formatSuggestions: (suggestions: readonly Suggestion[]) => string;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAgB,WAAW,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,iHAAiH;AACjH,MAAM,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,MAAM,GAAG,UAAU,CAAC,EAAE,CAAA;AAE3D,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5C,oEAAoE;IACpE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC1C,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;IAChC,aAAa,CAAC,EAAE,SAAS,UAAU,EAAE,CAAA;IACrC,kGAAkG;IAClG,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B;AAED,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAEnC,eAAO,MAAM,OAAO,gDAA2D,iBAAiB,KAAG,UAAU,EA2C5G,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,gBAAiB,SAAS,UAAU,EAAE,KAAG,MAC4C,CAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** Tells the shell not to fall back to file names when nothing matched. */
|
|
2
|
+
export const NO_FILE_COMPLETION = 4;
|
|
3
|
+
export const suggest = ({ commands, globalOptions = [], words, sources = {} }) => {
|
|
4
|
+
const typed = words.at(-1) ?? "";
|
|
5
|
+
const before = words.slice(0, -1);
|
|
6
|
+
let level = commands;
|
|
7
|
+
let current;
|
|
8
|
+
let positional = 0;
|
|
9
|
+
let pending;
|
|
10
|
+
for (const word of before) {
|
|
11
|
+
if (pending) {
|
|
12
|
+
pending = undefined;
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (word.startsWith("-")) {
|
|
16
|
+
const option = findOption(word, current, globalOptions);
|
|
17
|
+
if (option?.takesValue && !word.includes("="))
|
|
18
|
+
pending = option;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const child = level.find((command) => command.name === word);
|
|
22
|
+
if (child) {
|
|
23
|
+
current = child;
|
|
24
|
+
level = child.commands;
|
|
25
|
+
positional = 0;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
positional += 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const candidates = pending
|
|
32
|
+
? optionValues(pending, sources)
|
|
33
|
+
: typed.startsWith("-")
|
|
34
|
+
? typed.includes("=")
|
|
35
|
+
? valuesAfterEquals(typed, current, globalOptions, sources)
|
|
36
|
+
: optionNames(current, globalOptions)
|
|
37
|
+
: [
|
|
38
|
+
...level.filter((command) => command.state !== "deprecated").map(asSuggestion),
|
|
39
|
+
...(current ? argumentValues(current.arguments, positional, sources) : []),
|
|
40
|
+
...(current ? [] : resolve(sources.firstWord)),
|
|
41
|
+
];
|
|
42
|
+
const unique = new Map(candidates.map((candidate) => [candidate.value, candidate]));
|
|
43
|
+
return [...unique.values()].filter(({ value }) => value.startsWith(typed));
|
|
44
|
+
};
|
|
45
|
+
/** The answer in the form the shell script reads. */
|
|
46
|
+
export const formatSuggestions = (suggestions) => [...suggestions.map(({ value, description }) => `${value}\t${description}`), `:${NO_FILE_COMPLETION}`].join("\n");
|
|
47
|
+
const asSuggestion = (command) => ({
|
|
48
|
+
value: command.name,
|
|
49
|
+
description: command.summary ?? command.description,
|
|
50
|
+
});
|
|
51
|
+
const longName = (option) => option.flags.match(/--([\w-]+)/)?.[1];
|
|
52
|
+
const findOption = (word, current, globals) => {
|
|
53
|
+
const name = word.replace(/^-+/, "").split("=")[0];
|
|
54
|
+
const matches = (option) => longName(option) === name || option.flags.split(/[ ,]+/).includes(`-${name}`);
|
|
55
|
+
return [...(current?.options ?? []), ...globals].find(matches);
|
|
56
|
+
};
|
|
57
|
+
const optionNames = (current, globals) => [...(current?.options ?? []), ...globals].flatMap((option) => {
|
|
58
|
+
const name = longName(option);
|
|
59
|
+
return name ? [{ value: `--${name}`, description: option.description }] : [];
|
|
60
|
+
});
|
|
61
|
+
/** `--kind <dialog|group|channel>`: Commander does not know these as choices, but the flags say them. */
|
|
62
|
+
const inlineChoices = (flags) => flags.match(/<([^>]*\|[^>]*)>/)?.[1]?.split("|") ?? [];
|
|
63
|
+
const optionValues = (option, sources) => {
|
|
64
|
+
const name = longName(option);
|
|
65
|
+
return [
|
|
66
|
+
...[...(option.choices ?? []), ...inlineChoices(option.flags)].map((value) => ({ value, description: "" })),
|
|
67
|
+
...resolve(name ? sources.options?.[name] : undefined),
|
|
68
|
+
];
|
|
69
|
+
};
|
|
70
|
+
const valuesAfterEquals = (typed, current, globals, sources) => {
|
|
71
|
+
const [flag] = typed.split("=");
|
|
72
|
+
const option = findOption(flag ?? "", current, globals);
|
|
73
|
+
if (!option?.takesValue)
|
|
74
|
+
return [];
|
|
75
|
+
return optionValues(option, sources).map(({ value, description }) => ({ value: `${flag}=${value}`, description }));
|
|
76
|
+
};
|
|
77
|
+
const argumentValues = (args, position, sources) => {
|
|
78
|
+
const argument = args[position] ?? (args.at(-1)?.variadic ? args.at(-1) : undefined);
|
|
79
|
+
if (!argument)
|
|
80
|
+
return [];
|
|
81
|
+
return [
|
|
82
|
+
...(argument.choices ?? []).map((value) => ({ value, description: "" })),
|
|
83
|
+
...resolve(sources.arguments?.[argument.name]),
|
|
84
|
+
];
|
|
85
|
+
};
|
|
86
|
+
const resolve = (values) => (values?.() ?? []).map((value) => (typeof value === "string" ? { value, description: "" } : value));
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
/**
|
|
3
|
+
* Atomic, and the directory is locked down before the first write.
|
|
4
|
+
*
|
|
5
|
+
* Atomic because a partial credential file loses **every** profile's secret, not just the one
|
|
6
|
+
* being written, and the window for that is exactly a Ctrl+C mid-write. The directory mode matters
|
|
7
|
+
* as much as the file's: `0o600` on a file inside a world-readable directory is worth little.
|
|
8
|
+
* ⚠ Both modes are ignored on Windows.
|
|
9
|
+
*/
|
|
10
|
+
export declare const writeSecurely: (path: string, contents: string, mode: number) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Reads and validates a JSON config. A missing file is not an error — it is a program that has not
|
|
13
|
+
* been configured yet — but a malformed one is, and it says which field and why.
|
|
14
|
+
*
|
|
15
|
+
* The schema belongs to the host: what a profile holds is the one thing no shared package can know.
|
|
16
|
+
*/
|
|
17
|
+
export declare const loadConfigFile: <TSchema extends v.GenericSchema>(path: string, schema: TSchema, fallback: () => v.InferOutput<TSchema>) => v.InferOutput<TSchema>;
|
|
18
|
+
/** Config is not a secret, so it is `0644`; the credential file next to it is not. */
|
|
19
|
+
export declare const saveConfigFile: (path: string, config: unknown) => void;
|
|
20
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAE5B;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,SAAU,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAG,IAe5E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,SAAS,CAAC,CAAC,aAAa,QACtD,MAAM,UACJ,OAAO,YACL,MAAM,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,KACrC,CAAC,CAAC,WAAW,CAAC,OAAO,CAqBvB,CAAA;AAED,sFAAsF;AACtF,eAAO,MAAM,cAAc,SAAU,MAAM,UAAU,OAAO,KAAG,IAE9D,CAAA"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import * as v from "valibot";
|
|
5
|
+
/**
|
|
6
|
+
* Atomic, and the directory is locked down before the first write.
|
|
7
|
+
*
|
|
8
|
+
* Atomic because a partial credential file loses **every** profile's secret, not just the one
|
|
9
|
+
* being written, and the window for that is exactly a Ctrl+C mid-write. The directory mode matters
|
|
10
|
+
* as much as the file's: `0o600` on a file inside a world-readable directory is worth little.
|
|
11
|
+
* ⚠ Both modes are ignored on Windows.
|
|
12
|
+
*/
|
|
13
|
+
export const writeSecurely = (path, contents, mode) => {
|
|
14
|
+
const dir = dirname(path);
|
|
15
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
16
|
+
// An unguessable name opened with `wx` fails on anything already there, a planted symlink
|
|
17
|
+
// included, instead of writing through it.
|
|
18
|
+
const temp = join(dir, `.${randomBytes(8).toString("hex")}.tmp`);
|
|
19
|
+
try {
|
|
20
|
+
writeFileSync(temp, contents, { mode, flag: "wx" });
|
|
21
|
+
// A rename within one directory is atomic on every platform we target.
|
|
22
|
+
renameSync(temp, path);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
rmSync(temp, { force: true });
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Reads and validates a JSON config. A missing file is not an error — it is a program that has not
|
|
31
|
+
* been configured yet — but a malformed one is, and it says which field and why.
|
|
32
|
+
*
|
|
33
|
+
* The schema belongs to the host: what a profile holds is the one thing no shared package can know.
|
|
34
|
+
*/
|
|
35
|
+
export const loadConfigFile = (path, schema, fallback) => {
|
|
36
|
+
let text;
|
|
37
|
+
try {
|
|
38
|
+
text = readFileSync(path, "utf8");
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return fallback();
|
|
42
|
+
}
|
|
43
|
+
let parsed;
|
|
44
|
+
try {
|
|
45
|
+
parsed = JSON.parse(text);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
throw new Error(`${path} is not valid JSON`);
|
|
49
|
+
}
|
|
50
|
+
const result = v.safeParse(schema, parsed);
|
|
51
|
+
if (!result.success) {
|
|
52
|
+
const problems = result.issues.map((issue) => `${v.getDotPath(issue) ?? "(root)"}: ${issue.message}`);
|
|
53
|
+
throw new Error(`${path} is not a valid config:\n ${problems.join("\n ")}`);
|
|
54
|
+
}
|
|
55
|
+
return result.output;
|
|
56
|
+
};
|
|
57
|
+
/** Config is not a secret, so it is `0644`; the credential file next to it is not. */
|
|
58
|
+
export const saveConfigFile = (path, config) => {
|
|
59
|
+
writeSecurely(path, `${JSON.stringify(config, null, 2)}\n`, 0o644);
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACpF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAE5B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,IAAY,EAAQ,EAAE;IAClF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAEhD,0FAA0F;IAC1F,2CAA2C;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAChE,IAAI,CAAC;QACH,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACnD,uEAAuE;QACvE,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAC7B,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,IAAY,EACZ,MAAe,EACf,QAAsC,EACd,EAAE;IAC1B,IAAI,IAAY,CAAA;IAChB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,EAAE,CAAA;IACnB,CAAC;IAED,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,CAAC,CAAA;IAC9C,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QACrG,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,8BAA8B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC/E,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC,CAAA;AAED,sFAAsF;AACtF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,MAAe,EAAQ,EAAE;IACpE,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AACpE,CAAC,CAAA"}
|