argsbarg 4.1.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -1
- package/README.md +91 -85
- package/docs/README.md +8 -8
- package/docs/ai-skills.md +9 -9
- package/docs/bundled-docs.md +5 -5
- package/docs/cli-program.md +13 -11
- package/docs/config-schema.md +36 -9
- package/docs/configure.md +177 -0
- package/docs/developing.md +7 -7
- package/docs/distribution-homebrew.md +104 -0
- package/docs/mcp.md +11 -12
- package/docs/output-schema.md +1 -1
- package/examples/full-example/Formula/.gitkeep +0 -0
- package/examples/full-example/README.md +98 -0
- package/examples/full-example/biome.json +22 -0
- package/examples/{consumer-app → full-example}/bun.lock +2 -0
- package/examples/full-example/justfile +134 -0
- package/examples/{consumer-app → full-example}/package.json +10 -3
- package/examples/{consumer-app → full-example}/schemas/generated/app-config.json +1 -1
- package/examples/{consumer-app → full-example}/schemas/generated/status.json +1 -1
- package/examples/full-example/scripts/create-identity.ts +11 -0
- package/examples/full-example/scripts/formula-shared.ts +73 -0
- package/examples/full-example/scripts/gen-dev-formula.ts +26 -0
- package/examples/full-example/scripts/print-identity.ts +27 -0
- package/examples/full-example/src/commands/echo/command.ts +21 -0
- package/examples/full-example/src/commands/status/command.test.ts +10 -0
- package/examples/full-example/src/commands/status/command.ts +36 -0
- package/examples/{consumer-app → full-example}/src/commands/status/types.ts +1 -1
- package/examples/full-example/src/index.ts +10 -0
- package/examples/full-example/src/program.ts +57 -0
- package/examples/{consumer-app → full-example}/src/types.ts +1 -1
- package/examples/nested.ts +1 -3
- package/index.d.ts +49 -81
- package/package.json +2 -2
- package/src/builtins/builtins.test.ts +84 -64
- package/src/builtins/completion-group.ts +17 -17
- package/src/builtins/configure-copy.ts +86 -0
- package/src/builtins/configure.ts +70 -0
- package/src/builtins/dispatch.ts +13 -9
- package/src/builtins/index.ts +1 -1
- package/src/builtins/mcp.ts +2 -2
- package/src/builtins/registry.ts +6 -4
- package/src/capabilities.ts +22 -15
- package/src/cli-tool/cli-smoke.test.ts +29 -0
- package/src/cli-tool/create.test.ts +141 -0
- package/src/cli-tool/create.ts +402 -0
- package/{examples/consumer-app/capabilities.test.ts → src/cli-tool/full-example-capabilities.test.ts} +16 -15
- package/src/cli-tool/main.ts +8 -0
- package/src/cli-tool/post-create.ts +111 -0
- package/src/cli-tool/program.ts +97 -0
- package/src/cli-tool/prompt.ts +28 -0
- package/src/cli-tool/run-create.ts +138 -0
- package/src/cli.ts +0 -2
- package/src/config/bootstrap.ts +27 -18
- package/src/config/file.test.ts +1 -1
- package/src/config/resolve.test.ts +167 -0
- package/src/config/resolve.ts +52 -8
- package/src/configure/configure.test.ts +148 -0
- package/src/configure/index.ts +284 -0
- package/src/configure/prompt.ts +40 -0
- package/src/docs/api-guide.test.ts +4 -5
- package/src/docs/builtin.ts +3 -5
- package/src/docs/docs.test.ts +6 -5
- package/src/docs/mcp-guide.ts +11 -12
- package/src/index.ts +5 -12
- package/src/install/binary-placement.test.ts +101 -0
- package/src/install/binary-placement.ts +47 -0
- package/src/install/install-validate.test.ts +5 -5
- package/src/install/normalize-uninstall.ts +11 -0
- package/src/install/normalize.ts +4 -19
- package/src/install/opts.ts +17 -0
- package/src/install/paths.ts +0 -22
- package/src/install/plan.ts +14 -6
- package/src/install/shell.ts +0 -14
- package/src/install/status.test.ts +6 -6
- package/src/install/status.ts +0 -6
- package/src/install/target-effective.ts +8 -10
- package/src/install/target-scope.ts +26 -36
- package/src/install/target-types.ts +0 -16
- package/src/install/targets/app.ts +19 -28
- package/src/install/targets/configure.ts +6 -2
- package/src/install/targets/index.ts +0 -3
- package/src/install/targets.test.ts +26 -44
- package/src/invoke.test.ts +1 -1
- package/src/mcp/env.test.ts +92 -0
- package/src/mcp/env.ts +15 -14
- package/src/mcp/tools.ts +1 -1
- package/src/mcp.integration.test.ts +4 -4
- package/src/parse.test.ts +13 -14
- package/src/prompt.ts +10 -0
- package/src/schema.ts +1 -1
- package/src/skill/hint.ts +2 -2
- package/src/types.ts +48 -22
- package/src/validate.ts +22 -28
- package/docs/install.md +0 -290
- package/docs/templates/cursor/rules/cli-program.mdc +0 -31
- package/examples/config-app/main.ts +0 -20
- package/examples/config-app/program.ts +0 -78
- package/examples/config-app/schema.ts +0 -37
- package/examples/config-app/types.ts +0 -19
- package/examples/consumer-app/README.md +0 -56
- package/examples/consumer-app/src/main.ts +0 -15
- package/examples/consumer-app/src/program.ts +0 -108
- package/src/builtins/install.ts +0 -136
- package/src/install/app.ts +0 -94
- package/src/install/bootstrap.ts +0 -22
- package/src/install/completions.ts +0 -56
- package/src/install/index.ts +0 -415
- package/src/install/install.test.ts +0 -333
- package/src/install/targets/completions.ts +0 -133
- package/src/install/update.test.ts +0 -123
- package/src/install/update.ts +0 -54
- /package/examples/{consumer-app → full-example}/schemas/configSchemas.ts +0 -0
- /package/examples/{consumer-app → full-example}/schemas/outputSchemas.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.test.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/discover-schema-roots.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen/naming.ts +0 -0
- /package/examples/{consumer-app → full-example}/scripts/schemagen.ts +0 -0
- /package/examples/{consumer-app → full-example}/tsconfig.json +0 -0
package/src/install/index.ts
DELETED
|
@@ -1,415 +0,0 @@
|
|
|
1
|
-
import { readSync } from "node:fs";
|
|
2
|
-
import { resolveCapabilities } from "../capabilities.ts";
|
|
3
|
-
import { displayAppConfigPath, runInstallConfigure } from "../config/bootstrap.ts";
|
|
4
|
-
import { cliSkillInstall, skillTargetFromActionKind } from "../skill/install.ts";
|
|
5
|
-
import type { CliProgram } from "../types.ts";
|
|
6
|
-
import { normalizeInstallRawOpts } from "./normalize.ts";
|
|
7
|
-
import { resolveInstallPaths } from "./paths.ts";
|
|
8
|
-
import { buildInstallPlan, buildUpdatePlan, type InstallAction, type InstallOpts } from "./plan.ts";
|
|
9
|
-
import {
|
|
10
|
-
installErr,
|
|
11
|
-
installInfo,
|
|
12
|
-
installOut,
|
|
13
|
-
printInstallStatus,
|
|
14
|
-
writeInteractiveInstallIntro,
|
|
15
|
-
} from "./status.ts";
|
|
16
|
-
import { resolveEffectiveInstallTargets } from "./target-effective.ts";
|
|
17
|
-
import { runTargetPreflight } from "./target-plan-build.ts";
|
|
18
|
-
import type { InstallActionKind } from "./target-types.ts";
|
|
19
|
-
import {
|
|
20
|
-
buildUninstallPlan,
|
|
21
|
-
skillDirFromUninstallSummary,
|
|
22
|
-
type UninstallAction,
|
|
23
|
-
uninstallSkillDir,
|
|
24
|
-
} from "./uninstall.ts";
|
|
25
|
-
import { cliUpdate } from "./update.ts";
|
|
26
|
-
|
|
27
|
-
export function parseInstallOpts(raw: Record<string, string>): InstallOpts {
|
|
28
|
-
const flag = (name: string) => raw[name] === "1";
|
|
29
|
-
return {
|
|
30
|
-
all: flag("all"),
|
|
31
|
-
app: flag("app"),
|
|
32
|
-
completions: flag("completions"),
|
|
33
|
-
skill: flag("skill"),
|
|
34
|
-
mcp: flag("mcp"),
|
|
35
|
-
reinstall: flag("reinstall"),
|
|
36
|
-
update: flag("update"),
|
|
37
|
-
from: raw.from,
|
|
38
|
-
status: flag("status"),
|
|
39
|
-
uninstall: flag("uninstall"),
|
|
40
|
-
configure: flag("configure"),
|
|
41
|
-
yes: flag("yes"),
|
|
42
|
-
dry: flag("dry"),
|
|
43
|
-
json: flag("json"),
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function validateInstallOpts(opts: InstallOpts): string | null {
|
|
48
|
-
const configureOnlyInstall =
|
|
49
|
-
opts.configure &&
|
|
50
|
-
!opts.uninstall &&
|
|
51
|
-
!opts.all &&
|
|
52
|
-
!opts.app &&
|
|
53
|
-
!opts.completions &&
|
|
54
|
-
!opts.skill &&
|
|
55
|
-
!opts.mcp &&
|
|
56
|
-
!opts.reinstall &&
|
|
57
|
-
!opts.update &&
|
|
58
|
-
!opts.status;
|
|
59
|
-
|
|
60
|
-
if (configureOnlyInstall) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (opts.json) {
|
|
65
|
-
opts.yes = true;
|
|
66
|
-
}
|
|
67
|
-
if (opts.reinstall) {
|
|
68
|
-
opts.yes = true;
|
|
69
|
-
}
|
|
70
|
-
if (opts.update) {
|
|
71
|
-
opts.yes = true;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const mutationFlags =
|
|
75
|
-
opts.all ||
|
|
76
|
-
opts.app ||
|
|
77
|
-
opts.completions ||
|
|
78
|
-
opts.skill ||
|
|
79
|
-
opts.mcp ||
|
|
80
|
-
opts.reinstall ||
|
|
81
|
-
opts.update ||
|
|
82
|
-
opts.uninstall ||
|
|
83
|
-
opts.configure;
|
|
84
|
-
if (opts.status && mutationFlags) {
|
|
85
|
-
return "--status is mutually exclusive with install/reinstall/uninstall targets.";
|
|
86
|
-
}
|
|
87
|
-
if (
|
|
88
|
-
opts.reinstall &&
|
|
89
|
-
(opts.all ||
|
|
90
|
-
opts.completions ||
|
|
91
|
-
opts.skill ||
|
|
92
|
-
opts.mcp ||
|
|
93
|
-
opts.uninstall ||
|
|
94
|
-
opts.status ||
|
|
95
|
-
opts.update ||
|
|
96
|
-
opts.configure)
|
|
97
|
-
) {
|
|
98
|
-
return "--reinstall cannot be combined with other target flags.";
|
|
99
|
-
}
|
|
100
|
-
if (
|
|
101
|
-
opts.update &&
|
|
102
|
-
(opts.all ||
|
|
103
|
-
opts.app ||
|
|
104
|
-
opts.completions ||
|
|
105
|
-
opts.skill ||
|
|
106
|
-
opts.mcp ||
|
|
107
|
-
opts.uninstall ||
|
|
108
|
-
opts.status ||
|
|
109
|
-
opts.reinstall ||
|
|
110
|
-
opts.configure)
|
|
111
|
-
) {
|
|
112
|
-
return "--update cannot be combined with other target flags.";
|
|
113
|
-
}
|
|
114
|
-
if (opts.uninstall && (opts.reinstall || opts.update || opts.status)) {
|
|
115
|
-
return "--uninstall cannot be combined with --reinstall, --update, or --status.";
|
|
116
|
-
}
|
|
117
|
-
if (opts.uninstall) {
|
|
118
|
-
const hasUninstallTarget =
|
|
119
|
-
opts.all || opts.app || opts.completions || opts.skill || opts.mcp || opts.configure;
|
|
120
|
-
if (!hasUninstallTarget) {
|
|
121
|
-
return "Specify at least one target: --all, --app, --completions, --skill, --mcp, or --configure.";
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (!opts.status && !opts.reinstall && !opts.update && !opts.uninstall) {
|
|
125
|
-
const hasTarget =
|
|
126
|
-
opts.all || opts.app || opts.completions || opts.skill || opts.mcp || opts.configure;
|
|
127
|
-
if (!hasTarget) {
|
|
128
|
-
return "Specify at least one target: --all, --app, --completions, --skill, --mcp, or --configure.";
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function parseSelectionIndices(input: string, max: number): number[] | null {
|
|
135
|
-
const trimmed = input.trim();
|
|
136
|
-
if (!trimmed) return null;
|
|
137
|
-
const parts = trimmed.split(/[\s,]+/).filter(Boolean);
|
|
138
|
-
const indices: number[] = [];
|
|
139
|
-
for (const part of parts) {
|
|
140
|
-
const n = Number(part);
|
|
141
|
-
if (!Number.isInteger(n) || n < 1 || n > max) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
if (!indices.includes(n)) {
|
|
145
|
-
indices.push(n);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return indices.sort((a, b) => a - b);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/** Interactive install: item 1 is the app when the plan leads with `app`. */
|
|
152
|
-
export function interactiveSelectionAssumesApp(
|
|
153
|
-
actions: Array<InstallAction | UninstallAction>,
|
|
154
|
-
uninstall: boolean,
|
|
155
|
-
): boolean {
|
|
156
|
-
if (uninstall) return false;
|
|
157
|
-
const first = actions[0];
|
|
158
|
-
return first !== undefined && "kind" in first && first.kind === "app";
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function mergeInteractiveSelection(
|
|
162
|
-
indices: number[],
|
|
163
|
-
count: number,
|
|
164
|
-
alwaysIncludeFirst: boolean,
|
|
165
|
-
): number[] {
|
|
166
|
-
if (!alwaysIncludeFirst || count === 0 || indices.includes(1)) {
|
|
167
|
-
return indices;
|
|
168
|
-
}
|
|
169
|
-
return [1, ...indices].sort((a, b) => a - b);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function promptSelectiveConfirm(count: number, alwaysIncludeFirst: boolean): number[] | null {
|
|
173
|
-
const hint = alwaysIncludeFirst
|
|
174
|
-
? "Proceed [y/N], or numbers to include (e.g. 2,3): "
|
|
175
|
-
: "Proceed [y/N], or numbers to include (e.g. 1,3): ";
|
|
176
|
-
process.stderr.write(hint);
|
|
177
|
-
const buf = Buffer.alloc(256);
|
|
178
|
-
const n = readSync(0, buf, { length: 256 });
|
|
179
|
-
const ans = buf.toString("utf8", 0, n).trim();
|
|
180
|
-
if (ans === "y" || ans === "Y") {
|
|
181
|
-
return Array.from({ length: count }, (_, i) => i + 1);
|
|
182
|
-
}
|
|
183
|
-
if (ans === "n" || ans === "N" || ans === "") {
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
const parsed = parseSelectionIndices(ans, count);
|
|
187
|
-
if (!parsed) return null;
|
|
188
|
-
return mergeInteractiveSelection(parsed, count, alwaysIncludeFirst);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function runSkillAction(root: CliProgram, kind: InstallActionKind, opts: InstallOpts): string[] {
|
|
192
|
-
const target = skillTargetFromActionKind(kind);
|
|
193
|
-
if (!target) return [];
|
|
194
|
-
return cliSkillInstall(root, target, {
|
|
195
|
-
global: true,
|
|
196
|
-
rimraf: true,
|
|
197
|
-
dry: opts.dry,
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function executePlan(
|
|
202
|
-
root: CliProgram,
|
|
203
|
-
actions: Array<InstallAction | UninstallAction>,
|
|
204
|
-
opts: InstallOpts,
|
|
205
|
-
showProgress: boolean,
|
|
206
|
-
): string[] {
|
|
207
|
-
const changed: string[] = [];
|
|
208
|
-
const paths = resolveInstallPaths(root);
|
|
209
|
-
for (const action of actions) {
|
|
210
|
-
if (showProgress) {
|
|
211
|
-
installInfo(action.message, opts);
|
|
212
|
-
}
|
|
213
|
-
if ("kind" in action && action.kind) {
|
|
214
|
-
const skillTarget = skillTargetFromActionKind(action.kind);
|
|
215
|
-
if (skillTarget) {
|
|
216
|
-
changed.push(...runSkillAction(root, action.kind as InstallActionKind, opts));
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (!("kind" in action) || !action.kind) {
|
|
221
|
-
const skillDir = skillDirFromUninstallSummary(action.summary, paths);
|
|
222
|
-
if (skillDir) {
|
|
223
|
-
changed.push(...uninstallSkillDir(skillDir, !!opts.dry));
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
changed.push(...action.run());
|
|
228
|
-
}
|
|
229
|
-
return changed;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function shouldRunConfigureWizardAfterInstall(root: CliProgram, opts: InstallOpts): boolean {
|
|
233
|
-
if (opts.uninstall || opts.reinstall || opts.update || opts.status || !root.appConfig) {
|
|
234
|
-
return false;
|
|
235
|
-
}
|
|
236
|
-
if (!opts.all && !opts.app && !opts.completions && !opts.skill && !opts.mcp) {
|
|
237
|
-
return false;
|
|
238
|
-
}
|
|
239
|
-
const effective = resolveEffectiveInstallTargets(root.install, root);
|
|
240
|
-
return effective.configure.includedInAll && effective.configure.enabled;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/** Runs install/reinstall/uninstall mutations without exiting the process. */
|
|
244
|
-
export async function runInstallMutation(
|
|
245
|
-
root: CliProgram,
|
|
246
|
-
rawOpts: Record<string, string>,
|
|
247
|
-
): Promise<{
|
|
248
|
-
changed: string[];
|
|
249
|
-
opts: InstallOpts;
|
|
250
|
-
paths: ReturnType<typeof resolveInstallPaths>;
|
|
251
|
-
}> {
|
|
252
|
-
const normalized = normalizeInstallRawOpts(rawOpts);
|
|
253
|
-
const opts = parseInstallOpts(normalized);
|
|
254
|
-
const err = validateInstallOpts(opts);
|
|
255
|
-
if (err) {
|
|
256
|
-
throw new Error(err);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const paths = resolveInstallPaths(root);
|
|
260
|
-
|
|
261
|
-
if (opts.status) {
|
|
262
|
-
printInstallStatus(root, opts);
|
|
263
|
-
return { changed: [], opts, paths };
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
let actions: Array<InstallAction | UninstallAction>;
|
|
267
|
-
if (opts.uninstall) {
|
|
268
|
-
actions = buildUninstallPlan(root, paths, opts);
|
|
269
|
-
} else if (opts.reinstall) {
|
|
270
|
-
actions = buildUpdatePlan(root, paths, opts);
|
|
271
|
-
} else {
|
|
272
|
-
actions = buildInstallPlan(root, paths, opts);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const installActions = actions.filter(
|
|
276
|
-
(a): a is InstallAction => "kind" in a && typeof a.kind === "string" && a.kind.includes("-mcp"),
|
|
277
|
-
);
|
|
278
|
-
if (!opts.uninstall && resolveCapabilities(root).mcp && installActions.length > 0) {
|
|
279
|
-
runTargetPreflight(root, paths, opts, installActions);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
let selectedActions = actions;
|
|
283
|
-
const autoYes = !!(opts.yes || opts.json || opts.reinstall || opts.update || opts.dry);
|
|
284
|
-
|
|
285
|
-
if (!autoYes && !opts.json && process.stdin.isTTY) {
|
|
286
|
-
writeInteractiveInstallIntro(root);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (actions.length === 0) {
|
|
290
|
-
return { changed: [], opts, paths };
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (!autoYes) {
|
|
294
|
-
installOut(
|
|
295
|
-
`About to ${opts.uninstall ? "remove" : opts.reinstall ? "reinstall" : "install"}:`,
|
|
296
|
-
opts,
|
|
297
|
-
);
|
|
298
|
-
for (let i = 0; i < actions.length; i++) {
|
|
299
|
-
installOut(` ${i + 1}. ${actions[i]?.summary}`, opts);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (!autoYes) {
|
|
304
|
-
if (!process.stdin.isTTY) {
|
|
305
|
-
throw new Error("Refusing to proceed without --yes (stdin is not a TTY).");
|
|
306
|
-
}
|
|
307
|
-
const assumeApp = interactiveSelectionAssumesApp(actions, !!opts.uninstall);
|
|
308
|
-
const selection = promptSelectiveConfirm(actions.length, assumeApp);
|
|
309
|
-
if (!selection) {
|
|
310
|
-
throw new Error("Aborted.");
|
|
311
|
-
}
|
|
312
|
-
process.stderr.write("Done.\n");
|
|
313
|
-
selectedActions = selection.map((i) => actions[i - 1]).filter(Boolean) as typeof actions;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
const changed = executePlan(root, selectedActions, opts, autoYes);
|
|
317
|
-
return { changed, opts, paths };
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/** Main install command orchestrator. */
|
|
321
|
-
export async function cliInstall(
|
|
322
|
-
root: CliProgram,
|
|
323
|
-
rawOpts: Record<string, string>,
|
|
324
|
-
): Promise<never> {
|
|
325
|
-
const normalized = normalizeInstallRawOpts(rawOpts);
|
|
326
|
-
const opts = parseInstallOpts(normalized);
|
|
327
|
-
|
|
328
|
-
const configureOnly =
|
|
329
|
-
opts.configure &&
|
|
330
|
-
!opts.uninstall &&
|
|
331
|
-
!opts.all &&
|
|
332
|
-
!opts.app &&
|
|
333
|
-
!opts.completions &&
|
|
334
|
-
!opts.skill &&
|
|
335
|
-
!opts.mcp;
|
|
336
|
-
|
|
337
|
-
if (configureOnly) {
|
|
338
|
-
if (!root.appConfig) {
|
|
339
|
-
installErr("This app does not support --configure.");
|
|
340
|
-
process.exit(1);
|
|
341
|
-
}
|
|
342
|
-
if (process.stdin.isTTY) {
|
|
343
|
-
writeInteractiveInstallIntro(root);
|
|
344
|
-
}
|
|
345
|
-
const result = runInstallConfigure(root, { context: "standalone" });
|
|
346
|
-
if (result.changed) {
|
|
347
|
-
installOut(`Wrote config: ${displayAppConfigPath(root)}`, opts);
|
|
348
|
-
} else {
|
|
349
|
-
installOut(`Config unchanged: ${displayAppConfigPath(root)}`, opts);
|
|
350
|
-
}
|
|
351
|
-
process.exit(0);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const err = validateInstallOpts(opts);
|
|
355
|
-
if (err) {
|
|
356
|
-
installErr(err);
|
|
357
|
-
process.exit(1);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
if (opts.update) {
|
|
361
|
-
if (!resolveCapabilities(root).update) {
|
|
362
|
-
installErr("Remote updates are not supported by this app.");
|
|
363
|
-
process.exit(1);
|
|
364
|
-
}
|
|
365
|
-
await cliUpdate(root);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
let result: Awaited<ReturnType<typeof runInstallMutation>>;
|
|
369
|
-
try {
|
|
370
|
-
result = await runInstallMutation(root, normalized);
|
|
371
|
-
} catch (err) {
|
|
372
|
-
installErr(err instanceof Error ? err.message : String(err));
|
|
373
|
-
process.exit(1);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const { changed, opts: mutationOpts, paths } = result;
|
|
377
|
-
|
|
378
|
-
if (mutationOpts.status) {
|
|
379
|
-
process.exit(0);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (
|
|
383
|
-
shouldRunConfigureWizardAfterInstall(root, mutationOpts) &&
|
|
384
|
-
!mutationOpts.uninstall &&
|
|
385
|
-
!mutationOpts.dry
|
|
386
|
-
) {
|
|
387
|
-
const configResult = runInstallConfigure(root, { context: "after-install" });
|
|
388
|
-
if (configResult.changed) {
|
|
389
|
-
installOut(`Wrote config: ${displayAppConfigPath(root)}`, mutationOpts);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
if (mutationOpts.json) {
|
|
394
|
-
process.stdout.write(`${JSON.stringify(changed, null, 2)}\n`);
|
|
395
|
-
process.exit(0);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (changed.length > 0) {
|
|
399
|
-
const verb = mutationOpts.uninstall
|
|
400
|
-
? "Removed"
|
|
401
|
-
: mutationOpts.reinstall
|
|
402
|
-
? "Reinstalled"
|
|
403
|
-
: "Installed";
|
|
404
|
-
installOut(`${verb} ${changed.length} file(s).`, mutationOpts);
|
|
405
|
-
if (
|
|
406
|
-
!mutationOpts.uninstall &&
|
|
407
|
-
(mutationOpts.all || mutationOpts.app) &&
|
|
408
|
-
changed.some((p) => p === paths.bashRc || p === paths.zshRc || p === paths.appPath)
|
|
409
|
-
) {
|
|
410
|
-
installOut("Open a new shell, or run: hash -r (bash) / rehash (zsh)", mutationOpts);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
process.exit(0);
|
|
415
|
-
}
|