@mudah-cli/mudah 0.7.0 → 0.9.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 +70 -0
- package/dist/autocomplete.d.ts +8 -0
- package/dist/autocomplete.js +38 -0
- package/dist/autocomplete.js.map +1 -0
- package/dist/built-ins.d.ts +9 -0
- package/dist/built-ins.js +144 -0
- package/dist/built-ins.js.map +1 -0
- package/dist/commands/autocomplete.command.d.ts +11 -0
- package/dist/commands/autocomplete.command.js +16 -0
- package/dist/commands/autocomplete.command.js.map +1 -0
- package/dist/commands/build.command.d.ts +1 -0
- package/dist/commands/build.command.js +2 -1
- package/dist/commands/build.command.js.map +1 -1
- package/dist/commands/cache.command.d.ts +11 -0
- package/dist/commands/cache.command.js +47 -0
- package/dist/commands/cache.command.js.map +1 -0
- package/dist/commands/complete.command.d.ts +13 -0
- package/dist/commands/complete.command.js +23 -0
- package/dist/commands/complete.command.js.map +1 -0
- package/dist/commands/config.diff.command.d.ts +8 -0
- package/dist/commands/config.diff.command.js +96 -0
- package/dist/commands/config.diff.command.js.map +1 -0
- package/dist/commands/config.set.command.d.ts +8 -0
- package/dist/commands/config.set.command.js +66 -0
- package/dist/commands/config.set.command.js.map +1 -0
- package/dist/commands/config.show.command.d.ts +8 -0
- package/dist/commands/config.show.command.js +38 -0
- package/dist/commands/config.show.command.js.map +1 -0
- package/dist/commands/config.source.command.d.ts +8 -0
- package/dist/commands/config.source.command.js +42 -0
- package/dist/commands/config.source.command.js.map +1 -0
- package/dist/commands/config.validate.command.d.ts +14 -0
- package/dist/commands/config.validate.command.js +63 -0
- package/dist/commands/config.validate.command.js.map +1 -0
- package/dist/commands/dev.command.d.ts +1 -0
- package/dist/commands/dev.command.js +1 -0
- package/dist/commands/dev.command.js.map +1 -1
- package/dist/commands/docs.widgets.command.d.ts +11 -0
- package/dist/commands/docs.widgets.command.js +17 -0
- package/dist/commands/docs.widgets.command.js.map +1 -0
- package/dist/commands/doctor.command.d.ts +1 -0
- package/dist/commands/doctor.command.js +36 -6
- package/dist/commands/doctor.command.js.map +1 -1
- package/dist/commands/graph.command.d.ts +10 -0
- package/dist/commands/graph.command.js +21 -0
- package/dist/commands/graph.command.js.map +1 -0
- package/dist/commands/help.command.d.ts +1 -0
- package/dist/commands/help.command.js +2 -2
- package/dist/commands/help.command.js.map +1 -1
- package/dist/commands/info.command.d.ts +8 -0
- package/dist/commands/info.command.js +61 -0
- package/dist/commands/info.command.js.map +1 -0
- package/dist/commands/lsp.command.d.ts +12 -0
- package/dist/commands/lsp.command.js +57 -0
- package/dist/commands/lsp.command.js.map +1 -0
- package/dist/commands/make.command.d.ts +2 -0
- package/dist/commands/make.command.js +75 -4
- package/dist/commands/make.command.js.map +1 -1
- package/dist/commands/plugins.list.command.d.ts +12 -0
- package/dist/commands/plugins.list.command.js +29 -0
- package/dist/commands/plugins.list.command.js.map +1 -0
- package/dist/commands/plugins.update.command.d.ts +29 -0
- package/dist/commands/plugins.update.command.js +78 -0
- package/dist/commands/plugins.update.command.js.map +1 -0
- package/dist/commands/plugins.watch.command.d.ts +10 -0
- package/dist/commands/plugins.watch.command.js +37 -0
- package/dist/commands/plugins.watch.command.js.map +1 -0
- package/dist/commands/replay.command.d.ts +10 -0
- package/dist/commands/replay.command.js +50 -0
- package/dist/commands/replay.command.js.map +1 -0
- package/dist/commands/storybook.command.d.ts +11 -0
- package/dist/commands/storybook.command.js +84 -0
- package/dist/commands/storybook.command.js.map +1 -0
- package/dist/commands/telemetry.command.d.ts +12 -0
- package/dist/commands/telemetry.command.js +55 -0
- package/dist/commands/telemetry.command.js.map +1 -0
- package/dist/commands/test.command.d.ts +13 -0
- package/dist/commands/test.command.js +83 -0
- package/dist/commands/test.command.js.map +1 -0
- package/dist/commands/tutorial.command.d.ts +12 -0
- package/dist/commands/tutorial.command.js +57 -0
- package/dist/commands/tutorial.command.js.map +1 -0
- package/dist/commands/version.command.d.ts +1 -0
- package/dist/commands/version.command.js +1 -0
- package/dist/commands/version.command.js.map +1 -1
- package/dist/commands/watch.command.d.ts +13 -0
- package/dist/commands/watch.command.js +62 -0
- package/dist/commands/watch.command.js.map +1 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/lsp.d.ts +147 -0
- package/dist/lsp.js +497 -0
- package/dist/lsp.js.map +1 -0
- package/dist/run.d.ts +4 -2
- package/dist/run.js +372 -37
- package/dist/run.js.map +1 -1
- package/dist/watcher.d.ts +20 -1
- package/dist/watcher.js +41 -4
- package/dist/watcher.js.map +1 -1
- package/package.json +27 -10
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mudah Contributors
|
|
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,70 @@
|
|
|
1
|
+
# @mudah-cli/mudah
|
|
2
|
+
|
|
3
|
+
*An ergonomic, animation-rich CLI framework* for the modern terminal. This is the umbrella
|
|
4
|
+
package: one dependency that wires the whole stack together with `run()`, command
|
|
5
|
+
auto-discovery, providers, and 26 built-in commands.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @mudah-cli/mudah
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or scaffold a complete app:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm create @mudah-cli/mudah my-app
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
An app's `bin/<name>` stub is three lines:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
#!/usr/bin/env node
|
|
25
|
+
import { run } from '@mudah-cli/mudah';
|
|
26
|
+
process.exitCode = await run();
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Commands are one file each, default-exporting a `Command`:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
// src/commands/deploy.command.ts
|
|
33
|
+
import { Command } from '@mudah-cli/mudah';
|
|
34
|
+
|
|
35
|
+
export default class DeployCommand extends Command {
|
|
36
|
+
signature = 'deploy {branch?} [--force]';
|
|
37
|
+
description = 'Deploy the application';
|
|
38
|
+
|
|
39
|
+
async handle(): Promise<number> {
|
|
40
|
+
this.output.section(`Deploying ${this.arg('branch') ?? 'main'}`);
|
|
41
|
+
this.output.success('Deployed.');
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Subpaths keep imports focused:
|
|
48
|
+
|
|
49
|
+
| Import | Contents |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `@mudah-cli/mudah` | `run()`, `Command`, `Application`, `ServiceProvider`, config, terminal |
|
|
52
|
+
| `@mudah-cli/mudah/tui` | `Program`, `Screen`, `Column`, `Row`, `Split`, widgets |
|
|
53
|
+
| `@mudah-cli/mudah/testing` | `TestApp`, `TestTui` |
|
|
54
|
+
| `@mudah-cli/mudah/ui` | `Output`, themes, tables, panels, markdown |
|
|
55
|
+
| `@mudah-cli/mudah/terminal` | capability detection, OSC, key/mouse parsing |
|
|
56
|
+
| `@mudah-cli/mudah/animation` | `Spinner`, `ProgressBar`, `TaskRunner` |
|
|
57
|
+
|
|
58
|
+
Every app ships with `help`, `version`, `make`, `build`, `doctor`, `dev`, `watch`, `test`,
|
|
59
|
+
`config:*`, `plugins:*`, and more — see the
|
|
60
|
+
[full list](https://github.com/thesimonharms/mudah#built-in-commands). Global flags: `--json`,
|
|
61
|
+
`--plain`, `--profile`, `--timeout`, `--memory`, `--headless`, `--trace`, `--a11y-tree`,
|
|
62
|
+
`--autocomplete`.
|
|
63
|
+
|
|
64
|
+
Requires Node ≥ 26 (or Bun). Zero third-party runtime dependencies.
|
|
65
|
+
|
|
66
|
+
## Links
|
|
67
|
+
|
|
68
|
+
- [Full documentation](https://github.com/thesimonharms/mudah#readme)
|
|
69
|
+
- [llms.txt](https://github.com/thesimonharms/mudah/blob/main/llms.txt) — compact agent reference
|
|
70
|
+
- [License: MIT](LICENSE)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Shells that `--autocomplete` / `autocomplete` can emit a script for. */
|
|
2
|
+
export type AutocompleteShell = 'bash' | 'zsh' | 'fish';
|
|
3
|
+
export declare function normalizeAutocompleteShell(value: string | undefined): AutocompleteShell;
|
|
4
|
+
/**
|
|
5
|
+
* Emit a shell integration script that calls `<bin> complete` so the
|
|
6
|
+
* kernel's {@link ConsoleKernel.complete} results drive tab completion.
|
|
7
|
+
*/
|
|
8
|
+
export declare function renderAutocompleteScript(bin: string, shell?: AutocompleteShell): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function normalizeAutocompleteShell(value) {
|
|
2
|
+
if (value === 'zsh' || value === 'fish' || value === 'bash')
|
|
3
|
+
return value;
|
|
4
|
+
return 'bash';
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Emit a shell integration script that calls `<bin> complete` so the
|
|
8
|
+
* kernel's {@link ConsoleKernel.complete} results drive tab completion.
|
|
9
|
+
*/
|
|
10
|
+
export function renderAutocompleteScript(bin, shell = 'bash') {
|
|
11
|
+
const name = bin.length > 0 ? bin : 'mudah';
|
|
12
|
+
if (shell === 'zsh') {
|
|
13
|
+
return `#compdef ${name}
|
|
14
|
+
# Mudah zsh completion — calls \`${name} complete\`
|
|
15
|
+
_${name}_complete() {
|
|
16
|
+
local -a opts
|
|
17
|
+
opts=(\${(f)"$(\${words[1]} complete -- \${words[2,-1]} 2>/dev/null)"})
|
|
18
|
+
_describe 'commands' opts
|
|
19
|
+
}
|
|
20
|
+
_${name}_complete
|
|
21
|
+
`;
|
|
22
|
+
}
|
|
23
|
+
if (shell === 'fish') {
|
|
24
|
+
return `# Mudah fish completion — calls \`${name} complete\`
|
|
25
|
+
complete -c ${name} -f -a '(${name} complete (commandline -opc)[2..-1])'
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
return `# Mudah bash completion — calls \`${name} complete\`
|
|
29
|
+
_${name}_complete() {
|
|
30
|
+
local cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
31
|
+
local words
|
|
32
|
+
words="$(\${COMP_WORDS[0]} complete -- "\${COMP_WORDS[@]:1}" 2>/dev/null)"
|
|
33
|
+
COMPREPLY=($(compgen -W "\${words}" -- "\${cur}"))
|
|
34
|
+
}
|
|
35
|
+
complete -F _${name}_complete ${name}
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=autocomplete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocomplete.js","sourceRoot":"","sources":["../src/autocomplete.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,0BAA0B,CAAC,KAAyB;IAClE,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAW,EAAE,KAAK,GAAsB,MAAM;IACrF,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;IAC5C,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QACpB,OAAO,YAAY,IAAI;mCACQ,IAAI;GACpC,IAAI;;;;;GAKJ,IAAI;CACN,CAAC;IACA,CAAC;IACD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,qCAAqC,IAAI;cACtC,IAAI,YAAY,IAAI;CACjC,CAAC;IACA,CAAC;IACD,OAAO,qCAAqC,IAAI;GAC/C,IAAI;;;;;;eAMQ,IAAI,aAAa,IAAI;CACnC,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ConsoleKernel } from '@mudah-cli/console';
|
|
2
|
+
/** First argv token that is not a flag. Used to load `watch`/`dev` targets. */
|
|
3
|
+
export declare function firstNonFlag(tokens: readonly string[]): string | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Register framework commands the current argv needs.
|
|
6
|
+
* Help and completion load every remaining name. A normal command loads
|
|
7
|
+
* only that name (and `watch`/`dev` also load their target).
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerWantedFrameworkBuiltIns(kernel: ConsoleKernel, seen: Set<string>, argv: readonly string[], listing: boolean): Promise<void>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { parseSignature } from '@mudah-cli/console';
|
|
2
|
+
function wrapDefault(load) {
|
|
3
|
+
return async () => load();
|
|
4
|
+
}
|
|
5
|
+
const FRAMEWORK_BUILTINS = [
|
|
6
|
+
{ name: 'make', load: wrapDefault(() => import('./commands/make.command.js')) },
|
|
7
|
+
{ name: 'build', load: wrapDefault(() => import('./commands/build.command.js')) },
|
|
8
|
+
{ name: 'doctor', load: wrapDefault(() => import('./commands/doctor.command.js')) },
|
|
9
|
+
{ name: 'config:show', load: wrapDefault(() => import('./commands/config.show.command.js')) },
|
|
10
|
+
{ name: 'config:diff', load: wrapDefault(() => import('./commands/config.diff.command.js')) },
|
|
11
|
+
{ name: 'info', load: wrapDefault(() => import('./commands/info.command.js')) },
|
|
12
|
+
{ name: 'config:set', load: wrapDefault(() => import('./commands/config.set.command.js')) },
|
|
13
|
+
{ name: 'config:source', load: wrapDefault(() => import('./commands/config.source.command.js')) },
|
|
14
|
+
{ name: 'config:validate', load: wrapDefault(() => import('./commands/config.validate.command.js')) },
|
|
15
|
+
{
|
|
16
|
+
name: 'dev',
|
|
17
|
+
load: async (kernel) => {
|
|
18
|
+
const { default: DevCommand } = await import('./commands/dev.command.js');
|
|
19
|
+
return {
|
|
20
|
+
default: class extends DevCommand {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(kernel);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{ name: 'plugins:list', load: wrapDefault(() => import('./commands/plugins.list.command.js')) },
|
|
29
|
+
{ name: 'plugins:update', load: wrapDefault(() => import('./commands/plugins.update.command.js')) },
|
|
30
|
+
{ name: 'plugins:watch', load: wrapDefault(() => import('./commands/plugins.watch.command.js')) },
|
|
31
|
+
{ name: 'cache', load: wrapDefault(() => import('./commands/cache.command.js')) },
|
|
32
|
+
{ name: 'telemetry', load: wrapDefault(() => import('./commands/telemetry.command.js')) },
|
|
33
|
+
{ name: 'graph', load: wrapDefault(() => import('./commands/graph.command.js')) },
|
|
34
|
+
{ name: 'autocomplete', load: wrapDefault(() => import('./commands/autocomplete.command.js')) },
|
|
35
|
+
{
|
|
36
|
+
name: 'complete',
|
|
37
|
+
load: async (kernel) => {
|
|
38
|
+
const { default: CompleteCommand } = await import('./commands/complete.command.js');
|
|
39
|
+
return {
|
|
40
|
+
default: class extends CompleteCommand {
|
|
41
|
+
constructor() {
|
|
42
|
+
super(kernel);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'watch',
|
|
50
|
+
load: async (kernel) => {
|
|
51
|
+
const { default: WatchCommand } = await import('./commands/watch.command.js');
|
|
52
|
+
return {
|
|
53
|
+
default: class extends WatchCommand {
|
|
54
|
+
constructor() {
|
|
55
|
+
super(kernel);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{ name: 'tutorial', load: wrapDefault(() => import('./commands/tutorial.command.js')) },
|
|
62
|
+
{ name: 'lsp', load: wrapDefault(() => import('./commands/lsp.command.js')) },
|
|
63
|
+
{ name: 'replay', load: wrapDefault(() => import('./commands/replay.command.js')) },
|
|
64
|
+
{ name: 'test', load: wrapDefault(() => import('./commands/test.command.js')) },
|
|
65
|
+
{ name: 'storybook', load: wrapDefault(() => import('./commands/storybook.command.js')) },
|
|
66
|
+
{ name: 'docs:widgets', load: wrapDefault(() => import('./commands/docs.widgets.command.js')) },
|
|
67
|
+
];
|
|
68
|
+
const VALUE_FLAGS = new Set(['--debounce', '--speed', '--cols', '--rows', '--format', '--to']);
|
|
69
|
+
/** First argv token that is not a flag. Used to load `watch`/`dev` targets. */
|
|
70
|
+
export function firstNonFlag(tokens) {
|
|
71
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
72
|
+
const token = tokens[i];
|
|
73
|
+
if (token.startsWith('--') && token.includes('='))
|
|
74
|
+
continue;
|
|
75
|
+
if (token.startsWith('-')) {
|
|
76
|
+
if (VALUE_FLAGS.has(token))
|
|
77
|
+
i += 1;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
return token;
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
function nameTaken(seen, name) {
|
|
85
|
+
if (seen.has(name))
|
|
86
|
+
return true;
|
|
87
|
+
const prefix = `${name}:`;
|
|
88
|
+
for (const existing of seen) {
|
|
89
|
+
if (existing.startsWith(prefix))
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
function registerIfFree(kernel, seen, module) {
|
|
95
|
+
try {
|
|
96
|
+
const name = parseSignature(new module.default().signature ?? '').name;
|
|
97
|
+
if (name === '' || nameTaken(seen, name))
|
|
98
|
+
return;
|
|
99
|
+
seen.add(name);
|
|
100
|
+
kernel.register(module);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Signature-less modules are skipped; kernel.register throws elsewhere.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function registerMatching(kernel, seen, token) {
|
|
107
|
+
for (const spec of FRAMEWORK_BUILTINS) {
|
|
108
|
+
if (spec.name !== token && !spec.name.startsWith(`${token}:`))
|
|
109
|
+
continue;
|
|
110
|
+
if (nameTaken(seen, spec.name))
|
|
111
|
+
continue;
|
|
112
|
+
registerIfFree(kernel, seen, await spec.load(kernel));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function registerAllFrameworkBuiltIns(kernel, seen) {
|
|
116
|
+
for (const spec of FRAMEWORK_BUILTINS) {
|
|
117
|
+
if (nameTaken(seen, spec.name))
|
|
118
|
+
continue;
|
|
119
|
+
registerIfFree(kernel, seen, await spec.load(kernel));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Register framework commands the current argv needs.
|
|
124
|
+
* Help and completion load every remaining name. A normal command loads
|
|
125
|
+
* only that name (and `watch`/`dev` also load their target).
|
|
126
|
+
*/
|
|
127
|
+
export async function registerWantedFrameworkBuiltIns(kernel, seen, argv, listing) {
|
|
128
|
+
if (listing) {
|
|
129
|
+
await registerAllFrameworkBuiltIns(kernel, seen);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const first = argv[0];
|
|
133
|
+
if (first === undefined) {
|
|
134
|
+
await registerAllFrameworkBuiltIns(kernel, seen);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
await registerMatching(kernel, seen, first);
|
|
138
|
+
if (first === 'watch' || first === 'dev') {
|
|
139
|
+
const target = firstNonFlag(argv.slice(1));
|
|
140
|
+
if (target !== undefined)
|
|
141
|
+
await registerMatching(kernel, seen, target);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=built-ins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"built-ins.js","sourceRoot":"","sources":["../src/built-ins.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@mudah-cli/console';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in `autocomplete` — print a bash/zsh/fish completion script
|
|
4
|
+
* that calls `<bin> complete`.
|
|
5
|
+
*/
|
|
6
|
+
export default class AutocompleteCommand extends Command {
|
|
7
|
+
signature: string;
|
|
8
|
+
description: string;
|
|
9
|
+
descriptionKey: string;
|
|
10
|
+
handle(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@mudah-cli/console';
|
|
2
|
+
import { normalizeAutocompleteShell, renderAutocompleteScript } from '../autocomplete.js';
|
|
3
|
+
/**
|
|
4
|
+
* Built-in `autocomplete` — print a bash/zsh/fish completion script
|
|
5
|
+
* that calls `<bin> complete`.
|
|
6
|
+
*/
|
|
7
|
+
export default class AutocompleteCommand extends Command {
|
|
8
|
+
signature = 'autocomplete {shell=bash}';
|
|
9
|
+
description = 'Emit a shell completion script';
|
|
10
|
+
descriptionKey = 'cmd.autocomplete.description';
|
|
11
|
+
async handle() {
|
|
12
|
+
const shell = normalizeAutocompleteShell(String(this.arg('shell') ?? 'bash'));
|
|
13
|
+
this.output.raw(renderAutocompleteScript(this.app.manifest.bin, shell));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=autocomplete.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocomplete.command.js","sourceRoot":"","sources":["../../src/commands/autocomplete.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAE1F;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,OAAO;IACtD,SAAS,GAAG,2BAA2B,CAAC;IACxC,WAAW,GAAG,gCAAgC,CAAC;IAC/C,cAAc,GAAG,8BAA8B,CAAC;IAEhD,KAAK,CAAC,MAAM;QACV,MAAM,KAAK,GAAG,0BAA0B,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { Command } from '@mudah-cli/console';
|
|
4
4
|
function runChild(command, args, cwd) {
|
|
5
5
|
return new Promise((resolve) => {
|
|
@@ -15,6 +15,7 @@ function runChild(command, args, cwd) {
|
|
|
15
15
|
export default class BuildCommand extends Command {
|
|
16
16
|
signature = 'build';
|
|
17
17
|
description = 'Build the application (runs the package.json build script)';
|
|
18
|
+
descriptionKey = 'cmd.build.description';
|
|
18
19
|
async handle() {
|
|
19
20
|
const pkgPath = `${this.app.basePath}/package.json`;
|
|
20
21
|
let pkg;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.command.js","sourceRoot":"","sources":["../../src/commands/build.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"build.command.js","sourceRoot":"","sources":["../../src/commands/build.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,SAAS,QAAQ,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW;IAC5D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC9D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IAC/C,SAAS,GAAG,OAAO,CAAC;IACpB,WAAW,GAAG,4DAA4D,CAAC;IAC3E,cAAc,GAAG,uBAAuB,CAAC;IAEzC,KAAK,CAAC,MAAM;QACV,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,eAAe,CAAC;QACpD,IAAI,GAAyC,CAAC;QAC9C,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,CAAC,UAAU,CAAC,6CAA6C,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;YACvE,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,YAAY,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YACvC,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,IAAI,GAAG,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from '@mudah-cli/console';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in `cache` — list or clear `.mudah/cache/` and mention the
|
|
4
|
+
* update-check cache directory from {@link defaultCacheDir}.
|
|
5
|
+
*/
|
|
6
|
+
export default class CacheCommand extends Command {
|
|
7
|
+
signature: string;
|
|
8
|
+
description: string;
|
|
9
|
+
descriptionKey: string;
|
|
10
|
+
handle(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { mkdirSync, readdirSync, rmSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { Command } from '@mudah-cli/console';
|
|
4
|
+
import { defaultCacheDir, t } from '@mudah-cli/core';
|
|
5
|
+
/**
|
|
6
|
+
* Built-in `cache` — list or clear `.mudah/cache/` and mention the
|
|
7
|
+
* update-check cache directory from {@link defaultCacheDir}.
|
|
8
|
+
*/
|
|
9
|
+
export default class CacheCommand extends Command {
|
|
10
|
+
signature = 'cache {action=ls}';
|
|
11
|
+
description = 'List or clear the local Mudah cache';
|
|
12
|
+
descriptionKey = 'cmd.cache.description';
|
|
13
|
+
async handle() {
|
|
14
|
+
const action = String(this.arg('action') ?? 'ls');
|
|
15
|
+
if (action !== 'ls' && action !== 'clear') {
|
|
16
|
+
throw this.usageError(`Unknown cache action "${action}".`, 'Use ls or clear.');
|
|
17
|
+
}
|
|
18
|
+
const appCache = join(this.app.basePath, '.mudah', 'cache');
|
|
19
|
+
const updateCache = defaultCacheDir();
|
|
20
|
+
if (action === 'clear') {
|
|
21
|
+
rmSync(appCache, { recursive: true, force: true });
|
|
22
|
+
mkdirSync(appCache, { recursive: true });
|
|
23
|
+
this.output.success(`Cleared ${appCache}`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.output.section('Cache');
|
|
27
|
+
this.output.keyValue('app', appCache);
|
|
28
|
+
this.output.keyValue('updates', updateCache);
|
|
29
|
+
const entries = listDir(appCache);
|
|
30
|
+
if (entries.length === 0) {
|
|
31
|
+
this.output.info(t('cache.empty'));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
for (const name of entries) {
|
|
35
|
+
this.output.bullet(name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function listDir(dir) {
|
|
40
|
+
try {
|
|
41
|
+
return readdirSync(dir).sort();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=cache.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.command.js","sourceRoot":"","sources":["../../src/commands/cache.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IAC/C,SAAS,GAAG,mBAAmB,CAAC;IAChC,WAAW,GAAG,qCAAqC,CAAC;IACpD,cAAc,GAAG,uBAAuB,CAAC;IAEzC,KAAK,CAAC,MAAM;QACV,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;QAClD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC1C,MAAM,IAAI,CAAC,UAAU,CAAC,yBAAyB,MAAM,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACjF,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;QAEtC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF;AAED,SAAS,OAAO,CAAC,GAAW;IAC1B,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command, type ConsoleKernel } from '@mudah-cli/console';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in `complete` — print tab-completion candidates for a partial argv.
|
|
4
|
+
* Shell integration scripts (`--autocomplete`) call this.
|
|
5
|
+
*/
|
|
6
|
+
export default class CompleteCommand extends Command {
|
|
7
|
+
signature: string;
|
|
8
|
+
description: string;
|
|
9
|
+
descriptionKey: string;
|
|
10
|
+
private kernel;
|
|
11
|
+
constructor(kernel: ConsoleKernel);
|
|
12
|
+
handle(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Command } from '@mudah-cli/console';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in `complete` — print tab-completion candidates for a partial argv.
|
|
4
|
+
* Shell integration scripts (`--autocomplete`) call this.
|
|
5
|
+
*/
|
|
6
|
+
export default class CompleteCommand extends Command {
|
|
7
|
+
signature = 'complete {line?}';
|
|
8
|
+
description = 'Print tab-completion candidates';
|
|
9
|
+
descriptionKey = 'cmd.complete.description';
|
|
10
|
+
kernel;
|
|
11
|
+
constructor(kernel) {
|
|
12
|
+
super();
|
|
13
|
+
this.kernel = kernel;
|
|
14
|
+
}
|
|
15
|
+
async handle() {
|
|
16
|
+
const line = this.arg('line');
|
|
17
|
+
const argv = line === undefined || line === '' ? [] : String(line).split(/\s+/);
|
|
18
|
+
const candidates = this.kernel.complete(argv);
|
|
19
|
+
if (candidates.length > 0)
|
|
20
|
+
this.output.raw(candidates.join('\n'));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=complete.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complete.command.js","sourceRoot":"","sources":["../../src/commands/complete.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAsB,MAAM,oBAAoB,CAAC;AAEjE;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IAClD,SAAS,GAAG,kBAAkB,CAAC;IAC/B,WAAW,GAAG,iCAAiC,CAAC;IAChD,cAAc,GAAG,0BAA0B,CAAC;IAEpC,MAAM,CAAgB;IAE9B,YAAY,MAAqB;QAC/B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChF,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Command } from '@mudah-cli/console';
|
|
2
|
+
/** Built-in `config:diff {baseline?}` command. */
|
|
3
|
+
export default class ConfigDiffCommand extends Command {
|
|
4
|
+
signature: string;
|
|
5
|
+
description: string;
|
|
6
|
+
descriptionKey: string;
|
|
7
|
+
handle(): Promise<0 | 1 | undefined>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { isPlainObject, redactSecrets } from '@mudah-cli/config';
|
|
4
|
+
import { Command } from '@mudah-cli/console';
|
|
5
|
+
const MASK = '[redacted]';
|
|
6
|
+
/** Flatten an object into dot-path -> stringified leaf values. */
|
|
7
|
+
function flatten(value, prefix = '') {
|
|
8
|
+
const out = {};
|
|
9
|
+
if (isPlainObject(value)) {
|
|
10
|
+
for (const [key, val] of Object.entries(value)) {
|
|
11
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
12
|
+
if (isPlainObject(val))
|
|
13
|
+
Object.assign(out, flatten(val, path));
|
|
14
|
+
else
|
|
15
|
+
out[path] = Array.isArray(val) ? JSON.stringify(val) : String(val);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
/** Compare two flattened configs into added/removed/changed buckets. */
|
|
21
|
+
function diffFlat(base, current) {
|
|
22
|
+
const added = {};
|
|
23
|
+
const removed = {};
|
|
24
|
+
const changed = {};
|
|
25
|
+
for (const key of new Set([...Object.keys(base), ...Object.keys(current)])) {
|
|
26
|
+
const inBase = key in base;
|
|
27
|
+
const inCurrent = key in current;
|
|
28
|
+
if (inCurrent && !inBase)
|
|
29
|
+
added[key] = current[key];
|
|
30
|
+
else if (!inCurrent && inBase)
|
|
31
|
+
removed[key] = base[key];
|
|
32
|
+
else if (base[key] !== current[key])
|
|
33
|
+
changed[key] = { from: base[key], to: current[key] };
|
|
34
|
+
}
|
|
35
|
+
return { added, removed, changed };
|
|
36
|
+
}
|
|
37
|
+
function renderDiff(diff) {
|
|
38
|
+
const lines = [];
|
|
39
|
+
for (const key of Object.keys(diff.removed).sort())
|
|
40
|
+
lines.push(`- ${key} = ${diff.removed[key]}`);
|
|
41
|
+
for (const key of Object.keys(diff.added).sort())
|
|
42
|
+
lines.push(`+ ${key} = ${diff.added[key]}`);
|
|
43
|
+
for (const key of Object.keys(diff.changed).sort()) {
|
|
44
|
+
lines.push(`~ ${key}: ${diff.changed[key].from} -> ${diff.changed[key].to}`);
|
|
45
|
+
}
|
|
46
|
+
return lines;
|
|
47
|
+
}
|
|
48
|
+
/** Built-in `config:diff {baseline?}` command. */
|
|
49
|
+
export default class ConfigDiffCommand extends Command {
|
|
50
|
+
signature = 'config:diff {baseline?}';
|
|
51
|
+
description = 'Diff current config against a baseline JSON file (secrets are redacted)';
|
|
52
|
+
descriptionKey = 'cmd.config.diff.description';
|
|
53
|
+
async handle() {
|
|
54
|
+
const cfg = this.app.config();
|
|
55
|
+
const current = redactSecrets(cfg.all(), { mask: MASK });
|
|
56
|
+
const baselinePath = this.arg('baseline');
|
|
57
|
+
let baseline;
|
|
58
|
+
if (baselinePath !== undefined) {
|
|
59
|
+
const resolved = resolve(this.app.basePath, baselinePath);
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = readFileSync(resolved, 'utf8');
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
66
|
+
this.output.error(`Could not read baseline "${baselinePath}": ${message}`);
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
baseline = JSON.parse(raw);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
74
|
+
this.output.error(`Baseline "${baselinePath}" is not valid JSON: ${message}`);
|
|
75
|
+
return 1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
baseline = {};
|
|
80
|
+
}
|
|
81
|
+
const diff = diffFlat(flatten(redactSecrets(baseline, { mask: MASK })), flatten(current));
|
|
82
|
+
if (this.output.isMachineReadable) {
|
|
83
|
+
this.output.emit('data', 'config', diff);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (Object.keys(diff.added).length === 0 &&
|
|
87
|
+
Object.keys(diff.removed).length === 0 &&
|
|
88
|
+
Object.keys(diff.changed).length === 0) {
|
|
89
|
+
this.output.success('Config matches the baseline.');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
this.output.raw(`${renderDiff(diff).join('\n')}\n`);
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=config.diff.command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.diff.command.js","sourceRoot":"","sources":["../../src/commands/config.diff.command.ts"],"names":[],"mappings":"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"}
|