@crustjs/extensions 0.2.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 +21 -0
- package/README.md +13 -0
- package/dist/index.d.ts +287 -0
- package/dist/index.js +1857 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chenxin Yan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @crustjs/extensions
|
|
2
|
+
|
|
3
|
+
Official Extensions for the Crust CLI framework
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun add @crustjs/extensions
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
Full docs: [crustjs.com/docs/modules/extensions](https://crustjs.com/docs/modules/extensions)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { CommandDefinition, CommandSnapshot, Extension, ExtensionContext, ExtensionFactory, ExtensionId, RootMetaKey } from "@crustjs/core";
|
|
2
|
+
//#region src/completion/index.d.ts
|
|
3
|
+
/** The set of shells supported by the v1 completion extension. */
|
|
4
|
+
type CompletionShell = "bash" | "zsh" | "fish";
|
|
5
|
+
/** Options for the completion Extension. */
|
|
6
|
+
interface CompletionOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Subcommand name. Override only if the default conflicts with an existing user-defined command.
|
|
9
|
+
*
|
|
10
|
+
* @default "completion"
|
|
11
|
+
*/
|
|
12
|
+
command?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Binary name embedded in generated scripts (the `complete -F` target,
|
|
15
|
+
* the `#compdef` line, the `complete -c <bin>` rules).
|
|
16
|
+
* Applies to the runtime command and build hook; set it when `crust build --name`
|
|
17
|
+
* or the npm bin key installs the CLI under a different name.
|
|
18
|
+
*
|
|
19
|
+
* @default The root command's `meta.name`
|
|
20
|
+
*/
|
|
21
|
+
binName?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Free-form version string embedded in generated script headers. The
|
|
24
|
+
* walker does not parse it.
|
|
25
|
+
*
|
|
26
|
+
* @default The root command's `meta.version`
|
|
27
|
+
*/
|
|
28
|
+
version?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Render inputs shared by the pure shell renderers. */
|
|
31
|
+
type CompletionRenderOptions = Pick<CompletionOptions, "binName" | "version">;
|
|
32
|
+
/** Render a bash completion script from a prepared root Command Snapshot. */
|
|
33
|
+
export declare function renderBashCompletion(root: CommandSnapshot, options?: CompletionRenderOptions): string;
|
|
34
|
+
/** Render a zsh completion script from a prepared root Command Snapshot. */
|
|
35
|
+
export declare function renderZshCompletion(root: CommandSnapshot, options?: CompletionRenderOptions): string;
|
|
36
|
+
/** Render a fish completion script from a prepared root Command Snapshot. */
|
|
37
|
+
export declare function renderFishCompletion(root: CommandSnapshot, options?: CompletionRenderOptions): string;
|
|
38
|
+
/**
|
|
39
|
+
* Build an Extension that contributes a `completion <shell>` command
|
|
40
|
+
* which emits a tab-completion script for bash, zsh, or fish.
|
|
41
|
+
*
|
|
42
|
+
* **Strategy: pure-static.** The action walks the final root snapshot, so
|
|
43
|
+
* registration order is irrelevant — any commands or recursive flags added
|
|
44
|
+
* by other Extensions are visible by the time we generate the script. The
|
|
45
|
+
* walker projects Core's documentation model to a small completion model; per-shell
|
|
46
|
+
* renderers turn that into a self-contained shell script with no runtime
|
|
47
|
+
* callbacks.
|
|
48
|
+
*
|
|
49
|
+
* **Print vs `--output-dir`.**
|
|
50
|
+
* - With no `--output-dir`: print the script for the requested `<shell>`
|
|
51
|
+
* to stdout (the install pattern is
|
|
52
|
+
* `mycli completion bash > ~/.local/share/...`).
|
|
53
|
+
* - With `--output-dir <path>`: write **all** supported shells' files
|
|
54
|
+
* into the directory using the canonical per-shell filename
|
|
55
|
+
* (`<bin>` for bash, `_<bin>` for zsh, `<bin>.fish` for fish). This
|
|
56
|
+
* is the artifact-generation path used by Homebrew, Nix, and similar
|
|
57
|
+
* distribution channels — distributors run it once at packaging time
|
|
58
|
+
* and the resulting files become drop-ins.
|
|
59
|
+
*
|
|
60
|
+
* **Build hook.** `crust build` writes the same three files under
|
|
61
|
+
* `<outDir>/completions/`; `--package` stages that directory. The binary name
|
|
62
|
+
* defaults to the snapshot's `meta.name`, unless `options.binName` is set.
|
|
63
|
+
*/
|
|
64
|
+
export declare const completion: ExtensionFactory<[options?: CompletionOptions], {}, [], [], readonly CommandDefinition<any, any, any, any>[]>;
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/did-you-mean.d.ts
|
|
67
|
+
interface DidYouMeanOptions {
|
|
68
|
+
/**
|
|
69
|
+
* Presentation mode for command-not-found errors.
|
|
70
|
+
*
|
|
71
|
+
* `"error"` writes the message and visible commands to stderr. `"help"`
|
|
72
|
+
* writes the message and parent command help to stdout.
|
|
73
|
+
*
|
|
74
|
+
* @default "error"
|
|
75
|
+
*/
|
|
76
|
+
mode?: "error" | "help";
|
|
77
|
+
}
|
|
78
|
+
export declare const didYouMean: ExtensionFactory<[options?: DidYouMeanOptions]>;
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/help.d.ts
|
|
81
|
+
export declare function renderHelp(command: CommandSnapshot, path?: readonly string[]): string;
|
|
82
|
+
declare const helpFlags: readonly [{
|
|
83
|
+
readonly name: "help";
|
|
84
|
+
readonly type: "boolean";
|
|
85
|
+
readonly short: "h";
|
|
86
|
+
readonly noNegate: true;
|
|
87
|
+
readonly description: "Show help";
|
|
88
|
+
}];
|
|
89
|
+
export declare const help: ExtensionFactory<[], {}, [], typeof helpFlags>;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/no-color.d.ts
|
|
92
|
+
declare const colorFlags: readonly [{
|
|
93
|
+
readonly name: "color";
|
|
94
|
+
readonly type: "boolean";
|
|
95
|
+
readonly description: "Enable colored output";
|
|
96
|
+
}];
|
|
97
|
+
/**
|
|
98
|
+
* Adds a recursive `--color` / `--no-color` flag pair that scopes the
|
|
99
|
+
* standard color environment variables around command execution:
|
|
100
|
+
*
|
|
101
|
+
* - `--color` sets `FORCE_COLOR=3` (and clears `NO_COLOR`, so strict
|
|
102
|
+
* no-color.org-only child processes also comply) — forces all ANSI on
|
|
103
|
+
* (truecolor), overriding non-TTY detection. Any color library that
|
|
104
|
+
* honors `FORCE_COLOR` (including `@crustjs/style` and chalk) obeys it,
|
|
105
|
+
* and child processes inherit it.
|
|
106
|
+
* - `--no-color` sets `NO_COLOR=1` (and clears `FORCE_COLOR` so the flag
|
|
107
|
+
* wins over ambient env) — suppresses colors while non-color modifiers
|
|
108
|
+
* and hyperlinks keep following TTY detection, per
|
|
109
|
+
* [no-color.org](https://no-color.org/).
|
|
110
|
+
*
|
|
111
|
+
* Previous values are restored after the command finishes. When overlapping
|
|
112
|
+
* programmatic runs in one process use opposite flags, the later run wins
|
|
113
|
+
* mid-flight (the env is process-global); the ambient values are restored
|
|
114
|
+
* once all runs finish.
|
|
115
|
+
*/
|
|
116
|
+
export declare const noColor: ExtensionFactory<[], {}, [], typeof colorFlags>;
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/update-notifier.d.ts
|
|
119
|
+
type UpdateNotifierPackageManager = "npm" | "pnpm" | "yarn" | "bun";
|
|
120
|
+
type UpdateCommandResolver = (info: {
|
|
121
|
+
packageName: string;
|
|
122
|
+
packageManager: UpdateNotifierPackageManager;
|
|
123
|
+
}) => string;
|
|
124
|
+
interface UpdateNotifierState {
|
|
125
|
+
lastCheckedAt: number;
|
|
126
|
+
latestVersion?: string;
|
|
127
|
+
lastNotifiedVersion?: string;
|
|
128
|
+
}
|
|
129
|
+
interface UpdateNotifierCacheAdapter {
|
|
130
|
+
read(): Promise<UpdateNotifierState | null | undefined>;
|
|
131
|
+
write(state: UpdateNotifierState): Promise<void>;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Cache configuration for the update notifier extension.
|
|
135
|
+
*
|
|
136
|
+
* Wraps a {@link UpdateNotifierCacheAdapter} with cache-specific settings.
|
|
137
|
+
*/
|
|
138
|
+
interface UpdateNotifierCacheConfig {
|
|
139
|
+
/**
|
|
140
|
+
* Persistence adapter for reading and writing notifier state.
|
|
141
|
+
*
|
|
142
|
+
* When omitted, the built-in `@crustjs/store` persistence is used, so
|
|
143
|
+
* `intervalMs` can be tuned without reimplementing storage.
|
|
144
|
+
*/
|
|
145
|
+
adapter?: UpdateNotifierCacheAdapter;
|
|
146
|
+
/**
|
|
147
|
+
* Minimum interval in milliseconds between network update checks.
|
|
148
|
+
*
|
|
149
|
+
* Cached results are reused until this interval elapses.
|
|
150
|
+
*
|
|
151
|
+
* @default 86_400_000 (24 hours)
|
|
152
|
+
*/
|
|
153
|
+
intervalMs?: number;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Configuration options for the update notifier extension.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { updateNotifier } from "@crustjs/extensions";
|
|
161
|
+
*
|
|
162
|
+
* updateNotifier({ packageName: "my-cli" });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
interface UpdateNotifierOptions {
|
|
166
|
+
/**
|
|
167
|
+
* Override the current version of the CLI package.
|
|
168
|
+
*
|
|
169
|
+
* @default The root command's `meta.version`
|
|
170
|
+
*/
|
|
171
|
+
currentVersion?: string;
|
|
172
|
+
/**
|
|
173
|
+
* The npm package name to check for updates.
|
|
174
|
+
*/
|
|
175
|
+
packageName: string;
|
|
176
|
+
/**
|
|
177
|
+
* Network request timeout in milliseconds for the registry check.
|
|
178
|
+
*
|
|
179
|
+
* If the check does not complete within this duration, it is silently
|
|
180
|
+
* aborted and treated as a soft failure. This timeout does not bound cache
|
|
181
|
+
* operations or the entire postRun hook.
|
|
182
|
+
*
|
|
183
|
+
* @default 5_000 (5 seconds)
|
|
184
|
+
*/
|
|
185
|
+
timeoutMs?: number;
|
|
186
|
+
/**
|
|
187
|
+
* Custom npm registry URL to query for the latest version.
|
|
188
|
+
*
|
|
189
|
+
* @default "https://registry.npmjs.org"
|
|
190
|
+
*/
|
|
191
|
+
registryUrl?: string;
|
|
192
|
+
/**
|
|
193
|
+
* Upgrade command shown in the notice.
|
|
194
|
+
*
|
|
195
|
+
* Pass a string for a fixed command, a callback to build one from the
|
|
196
|
+
* package name and detected package manager, or a scope to generate the
|
|
197
|
+
* package manager's standard local/global command. When omitted, the notice
|
|
198
|
+
* does not suggest a command.
|
|
199
|
+
*/
|
|
200
|
+
updateCommand?: string | UpdateCommandResolver | {
|
|
201
|
+
scope: "global" | "local";
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Documentation URL shown after the update notice.
|
|
205
|
+
*/
|
|
206
|
+
updateDocsUrl?: string;
|
|
207
|
+
/**
|
|
208
|
+
* Cache configuration for cross-run persistence.
|
|
209
|
+
*
|
|
210
|
+
* By default, notifier state is persisted in the platform-standard state
|
|
211
|
+
* directory for {@link packageName}. Set to `false` to disable persistence,
|
|
212
|
+
* provide `intervalMs` alone to tune the built-in cache interval, or
|
|
213
|
+
* provide a custom adapter to control storage.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* cache: false
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
cache?: false | UpdateNotifierCacheConfig;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Creates an update notifier extension that checks the npm registry after a
|
|
224
|
+
* successful command action and displays a notice when a newer version is available.
|
|
225
|
+
*
|
|
226
|
+
* **Behavior:**
|
|
227
|
+
* - By default, checks are cached for 24 hours in the package's state directory.
|
|
228
|
+
* - `cache: false` disables cross-run persistence.
|
|
229
|
+
* - A custom cache adapter can override the built-in persistence.
|
|
230
|
+
* - The notice is command-less unless `updateCommand` is configured.
|
|
231
|
+
* - The postRun hook awaits the network check and cache reads and writes,
|
|
232
|
+
* delaying invocation completion after the action.
|
|
233
|
+
* - `timeoutMs` bounds only the network request, defaulting to 5 seconds.
|
|
234
|
+
* - Network, cache, and parsing errors are silently swallowed. A missing
|
|
235
|
+
* current version throws a DEFINITION error before that recovery block.
|
|
236
|
+
* - Update notices are intentionally written to the invocation's stderr callback.
|
|
237
|
+
* - Duplicate notifications for the same version are suppressed.
|
|
238
|
+
*
|
|
239
|
+
* @param options - Extension configuration. `packageName` is required.
|
|
240
|
+
* @returns An Extension registered with `.extend()`.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* import { Crust } from "@crustjs/core";
|
|
245
|
+
* import { updateNotifier } from "@crustjs/extensions";
|
|
246
|
+
*
|
|
247
|
+
* const app = new Crust("my-cli", { description: "My awesome CLI", version: "1.2.3" })
|
|
248
|
+
* .extend(updateNotifier({ packageName: "my-cli" }))
|
|
249
|
+
* .action(() => {
|
|
250
|
+
* console.log("Hello!");
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* await app.execute();
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export declare const updateNotifier: ExtensionFactory<[options: UpdateNotifierOptions]>;
|
|
257
|
+
//#endregion
|
|
258
|
+
//#region src/version.d.ts
|
|
259
|
+
type VersionValue = string | (() => string);
|
|
260
|
+
interface VersionOptions {
|
|
261
|
+
/**
|
|
262
|
+
* Output format. `"plain"` prints the bare version (script-friendly:
|
|
263
|
+
* `$(cli --version)`); a function receives the resolved version and the
|
|
264
|
+
* extension context and returns the line to print.
|
|
265
|
+
*
|
|
266
|
+
* @default `${rootName} v${version}`
|
|
267
|
+
*/
|
|
268
|
+
readonly format?: "plain" | ((version: string, context: ExtensionContext) => string);
|
|
269
|
+
}
|
|
270
|
+
declare const versionFlags: readonly [{
|
|
271
|
+
readonly name: "version";
|
|
272
|
+
readonly type: "boolean";
|
|
273
|
+
readonly short: "v";
|
|
274
|
+
readonly noNegate: true;
|
|
275
|
+
readonly description: "Show version number";
|
|
276
|
+
readonly recursive: false;
|
|
277
|
+
}];
|
|
278
|
+
type VersionRegistration<K extends RootMetaKey> = Extension<{}, [], typeof versionFlags, [], K>;
|
|
279
|
+
/** Explicit values supply their own version; omitted values require root metadata. */
|
|
280
|
+
interface VersionExtension {
|
|
281
|
+
(value: VersionValue, options?: VersionOptions): VersionRegistration<never>;
|
|
282
|
+
(value?: VersionValue, options?: VersionOptions): VersionRegistration<"version">;
|
|
283
|
+
readonly id: ExtensionId;
|
|
284
|
+
}
|
|
285
|
+
export declare const version: VersionExtension;
|
|
286
|
+
//#endregion
|
|
287
|
+
export type { CompletionOptions, CompletionRenderOptions, CompletionShell, DidYouMeanOptions, UpdateCommandResolver, UpdateNotifierCacheAdapter, UpdateNotifierCacheConfig, UpdateNotifierOptions, UpdateNotifierPackageManager, UpdateNotifierState, VersionExtension, VersionOptions, VersionValue };
|