swarmkit 0.0.6 → 0.0.7
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/dist/cli.js +2 -0
- package/dist/commands/configure/configure.d.ts +5 -0
- package/dist/commands/configure/configure.js +354 -0
- package/dist/commands/configure/configure.test.d.ts +1 -0
- package/dist/commands/configure/configure.test.js +539 -0
- package/dist/commands/configure/read-config.d.ts +12 -0
- package/dist/commands/configure/read-config.js +81 -0
- package/dist/commands/configure.d.ts +2 -0
- package/dist/commands/configure.js +14 -0
- package/dist/commands/init/phases/configure.js +0 -21
- package/dist/commands/init/phases/global-setup.d.ts +1 -1
- package/dist/commands/init/phases/global-setup.js +22 -44
- package/dist/commands/init/phases/integrations.d.ts +16 -0
- package/dist/commands/init/phases/integrations.js +172 -0
- package/dist/commands/init/phases/package-config.d.ts +10 -0
- package/dist/commands/init/phases/package-config.js +117 -0
- package/dist/commands/init/phases/phases.test.d.ts +1 -0
- package/dist/commands/init/phases/phases.test.js +711 -0
- package/dist/commands/init/phases/project.js +17 -0
- package/dist/commands/init/phases/review.d.ts +8 -0
- package/dist/commands/init/phases/review.js +79 -0
- package/dist/commands/init/phases/use-case.js +41 -27
- package/dist/commands/init/phases/wizard-flow.test.d.ts +1 -0
- package/dist/commands/init/phases/wizard-flow.test.js +657 -0
- package/dist/commands/init/phases/wizard-modes.test.d.ts +1 -0
- package/dist/commands/init/phases/wizard-modes.test.js +270 -0
- package/dist/commands/init/state.d.ts +31 -1
- package/dist/commands/init/state.js +4 -0
- package/dist/commands/init/state.test.js +7 -0
- package/dist/commands/init/wizard.d.ts +1 -0
- package/dist/commands/init/wizard.js +31 -23
- package/dist/commands/init.js +2 -0
- package/dist/packages/registry.d.ts +66 -0
- package/dist/packages/registry.js +258 -0
- package/dist/packages/setup.d.ts +42 -0
- package/dist/packages/setup.js +244 -15
- package/dist/packages/setup.test.js +520 -13
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { select, password } from "@inquirer/prompts";
|
|
2
|
-
import chalk from "chalk";
|
|
3
2
|
import { readConfig, writeConfig } from "../../../config/global.js";
|
|
4
3
|
import { writeKey } from "../../../config/keys.js";
|
|
5
4
|
import * as ui from "../../../utils/ui.js";
|
|
@@ -61,25 +60,5 @@ export async function configureKeys(state) {
|
|
|
61
60
|
writeConfig(config);
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
|
-
// Always ask for Anthropic key (needed for agents)
|
|
65
|
-
console.log();
|
|
66
|
-
const hasAnthropicKey = !!process.env["ANTHROPIC_API_KEY"];
|
|
67
|
-
if (hasAnthropicKey) {
|
|
68
|
-
ui.info(`Anthropic API key detected from environment ${chalk.dim("(ANTHROPIC_API_KEY)")}`);
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
const anthropicKey = await password({
|
|
72
|
-
message: "Anthropic API key (for running agents):",
|
|
73
|
-
mask: "*",
|
|
74
|
-
});
|
|
75
|
-
if (anthropicKey) {
|
|
76
|
-
updated.apiKeys["anthropic"] = anthropicKey;
|
|
77
|
-
writeKey("anthropic", anthropicKey);
|
|
78
|
-
ui.success("Anthropic API key stored");
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
ui.info("Skipped — you can set ANTHROPIC_API_KEY later.");
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
63
|
return updated;
|
|
85
64
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { WizardState } from "../state.js";
|
|
2
|
-
export declare function initGlobal(state: WizardState): Promise<void>;
|
|
2
|
+
export declare function initGlobal(state: WizardState, force?: boolean): Promise<void>;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { input, select } from "@inquirer/prompts";
|
|
2
1
|
import chalk from "chalk";
|
|
3
2
|
import { GLOBAL_CONFIG_DIRS, isGlobalInit, initGlobalPackage, } from "../../../packages/setup.js";
|
|
4
3
|
import * as ui from "../../../utils/ui.js";
|
|
5
4
|
/** Global packages in setup order */
|
|
6
|
-
const GLOBAL_SETUP_ORDER = ["skill-tree", "openhive"];
|
|
7
|
-
export async function initGlobal(state) {
|
|
5
|
+
const GLOBAL_SETUP_ORDER = ["skill-tree", "openhive", "claude-code-swarm"];
|
|
6
|
+
export async function initGlobal(state, force = false) {
|
|
8
7
|
const globalPackages = GLOBAL_SETUP_ORDER.filter((pkg) => state.selectedPackages.includes(pkg));
|
|
9
8
|
if (globalPackages.length === 0)
|
|
10
9
|
return;
|
|
11
|
-
const uninitialized =
|
|
10
|
+
const uninitialized = force
|
|
11
|
+
? globalPackages
|
|
12
|
+
: globalPackages.filter((pkg) => !isGlobalInit(pkg));
|
|
12
13
|
if (uninitialized.length === 0) {
|
|
13
14
|
ui.blank();
|
|
14
15
|
ui.info("All global packages already configured.");
|
|
@@ -19,51 +20,23 @@ export async function initGlobal(state) {
|
|
|
19
20
|
packages: state.selectedPackages,
|
|
20
21
|
embeddingProvider: state.embeddingProvider,
|
|
21
22
|
apiKeys: state.apiKeys,
|
|
23
|
+
packageConfigs: state.packageConfigs,
|
|
22
24
|
};
|
|
23
25
|
for (const pkg of uninitialized) {
|
|
26
|
+
// Skip packages whose CLI wizard already ran in the config phase
|
|
27
|
+
if (state.packageConfigs[pkg]?.usedCliWizard) {
|
|
28
|
+
ui.success(`${pkg} ${chalk.dim("(configured via wizard)")}`);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
24
31
|
let openhiveOpts;
|
|
25
|
-
//
|
|
32
|
+
// Build OpenhiveOptions from packageConfigs (collected in the config phase)
|
|
26
33
|
if (pkg === "openhive") {
|
|
27
|
-
|
|
28
|
-
ui.info("Configuring OpenHive...");
|
|
29
|
-
console.log();
|
|
30
|
-
const name = await input({
|
|
31
|
-
message: "OpenHive instance name:",
|
|
32
|
-
default: "OpenHive",
|
|
33
|
-
});
|
|
34
|
-
const port = await input({
|
|
35
|
-
message: "OpenHive port:",
|
|
36
|
-
default: "3000",
|
|
37
|
-
});
|
|
38
|
-
const verification = await select({
|
|
39
|
-
message: "Registration mode:",
|
|
40
|
-
choices: [
|
|
41
|
-
{ name: "Open — anyone can register", value: "open" },
|
|
42
|
-
{
|
|
43
|
-
name: "Invite — require an invite code",
|
|
44
|
-
value: "invite",
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: "Manual — admin approves each",
|
|
48
|
-
value: "manual",
|
|
49
|
-
},
|
|
50
|
-
],
|
|
51
|
-
});
|
|
52
|
-
const authMode = await select({
|
|
53
|
-
message: "Auth mode:",
|
|
54
|
-
choices: [
|
|
55
|
-
{ name: "Local — no login, single-user", value: "local" },
|
|
56
|
-
{
|
|
57
|
-
name: "Token — email/password registration",
|
|
58
|
-
value: "token",
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
});
|
|
34
|
+
const values = state.packageConfigs.openhive?.values ?? {};
|
|
62
35
|
openhiveOpts = {
|
|
63
|
-
name,
|
|
64
|
-
port: parseInt(port, 10) || 3000,
|
|
65
|
-
authMode,
|
|
66
|
-
verification,
|
|
36
|
+
name: values.name ?? "OpenHive",
|
|
37
|
+
port: parseInt(String(values.port ?? "3000"), 10) || 3000,
|
|
38
|
+
authMode: values.authMode ?? "local",
|
|
39
|
+
verification: values.verification ?? "open",
|
|
67
40
|
};
|
|
68
41
|
}
|
|
69
42
|
const result = await initGlobalPackage(pkg, ctx, openhiveOpts);
|
|
@@ -73,6 +46,11 @@ export async function initGlobal(state) {
|
|
|
73
46
|
: "";
|
|
74
47
|
if (result.success) {
|
|
75
48
|
ui.success(`${pkg} ${chalk.dim("→")} ~/${configDir}/${suffix}`);
|
|
49
|
+
state.configsWritten.push({
|
|
50
|
+
package: pkg,
|
|
51
|
+
path: `~/${configDir}/`,
|
|
52
|
+
description: `Global ${pkg} config`,
|
|
53
|
+
});
|
|
76
54
|
}
|
|
77
55
|
else {
|
|
78
56
|
ui.fail(`${pkg}: ${result.message ?? "setup failed"}`);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { WizardState } from "../state.js";
|
|
2
|
+
/**
|
|
3
|
+
* Phase: Integration wiring.
|
|
4
|
+
*
|
|
5
|
+
* Walks through active integrations between selected packages:
|
|
6
|
+
* - Auto-detected integrations (requiresWiring: false) are shown as info
|
|
7
|
+
* - Wirable integrations get interactive config prompts
|
|
8
|
+
*/
|
|
9
|
+
export declare function configureIntegrations(state: WizardState): Promise<WizardState>;
|
|
10
|
+
/**
|
|
11
|
+
* Apply collected integration wiring values to package config files on disk.
|
|
12
|
+
*
|
|
13
|
+
* Each configOption in INTEGRATIONS specifies a targetPackage and configPath.
|
|
14
|
+
* This function reads the target config file, patches the value, and writes it back.
|
|
15
|
+
*/
|
|
16
|
+
export declare function applyIntegrationWiring(state: WizardState): void;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { getActiveIntegrations } from "../../../packages/registry.js";
|
|
6
|
+
import { projectConfigDirs, GLOBAL_CONFIG_DIRS, } from "../../../packages/setup.js";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import * as ui from "../../../utils/ui.js";
|
|
9
|
+
/**
|
|
10
|
+
* Phase: Integration wiring.
|
|
11
|
+
*
|
|
12
|
+
* Walks through active integrations between selected packages:
|
|
13
|
+
* - Auto-detected integrations (requiresWiring: false) are shown as info
|
|
14
|
+
* - Wirable integrations get interactive config prompts
|
|
15
|
+
*/
|
|
16
|
+
export async function configureIntegrations(state) {
|
|
17
|
+
const updated = { ...state, integrationWiring: [...state.integrationWiring] };
|
|
18
|
+
const activeIntegrations = getActiveIntegrations(updated.selectedPackages);
|
|
19
|
+
if (activeIntegrations.length === 0)
|
|
20
|
+
return updated;
|
|
21
|
+
const autoDetected = activeIntegrations.filter((i) => !i.requiresWiring);
|
|
22
|
+
const wirable = activeIntegrations.filter((i) => i.requiresWiring && i.configOptions && i.configOptions.length > 0);
|
|
23
|
+
ui.heading(" Integration wiring");
|
|
24
|
+
// Show auto-detected integrations
|
|
25
|
+
if (autoDetected.length > 0) {
|
|
26
|
+
for (const integration of autoDetected) {
|
|
27
|
+
const [a, b] = integration.packages;
|
|
28
|
+
ui.success(`${a} ${chalk.dim("↔")} ${b} ${chalk.dim(integration.description)} ${chalk.dim("(auto-detected)")}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Walk through wirable integrations
|
|
32
|
+
if (wirable.length > 0 && !updated.quick) {
|
|
33
|
+
for (const integration of wirable) {
|
|
34
|
+
const [a, b] = integration.packages;
|
|
35
|
+
const key = `${a}:${b}`;
|
|
36
|
+
console.log();
|
|
37
|
+
console.log(` ${chalk.bold(a)} ${chalk.dim("↔")} ${chalk.bold(b)}`);
|
|
38
|
+
ui.info(integration.description);
|
|
39
|
+
const enable = await confirm({
|
|
40
|
+
message: `Configure this integration?`,
|
|
41
|
+
default: true,
|
|
42
|
+
});
|
|
43
|
+
const wiring = {
|
|
44
|
+
key,
|
|
45
|
+
enabled: enable,
|
|
46
|
+
values: {},
|
|
47
|
+
};
|
|
48
|
+
if (enable && integration.configOptions) {
|
|
49
|
+
for (const option of integration.configOptions) {
|
|
50
|
+
const value = await promptConfigOption(option);
|
|
51
|
+
wiring.values[option.key] = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
updated.integrationWiring.push(wiring);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (wirable.length > 0) {
|
|
58
|
+
// Quick mode — show what's available but skip config
|
|
59
|
+
for (const integration of wirable) {
|
|
60
|
+
const [a, b] = integration.packages;
|
|
61
|
+
ui.info(`${a} ${chalk.dim("↔")} ${b} ${chalk.dim(integration.description)} ${chalk.dim("(configure later)")}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return updated;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Apply collected integration wiring values to package config files on disk.
|
|
68
|
+
*
|
|
69
|
+
* Each configOption in INTEGRATIONS specifies a targetPackage and configPath.
|
|
70
|
+
* This function reads the target config file, patches the value, and writes it back.
|
|
71
|
+
*/
|
|
72
|
+
export function applyIntegrationWiring(state) {
|
|
73
|
+
if (state.integrationWiring.length === 0)
|
|
74
|
+
return;
|
|
75
|
+
const cwd = process.cwd();
|
|
76
|
+
const activeIntegrations = getActiveIntegrations(state.selectedPackages);
|
|
77
|
+
for (const wiring of state.integrationWiring) {
|
|
78
|
+
if (!wiring.enabled)
|
|
79
|
+
continue;
|
|
80
|
+
// Find the matching integration definition to get configOptions
|
|
81
|
+
const integration = activeIntegrations.find((i) => {
|
|
82
|
+
const [a, b] = i.packages;
|
|
83
|
+
return `${a}:${b}` === wiring.key;
|
|
84
|
+
});
|
|
85
|
+
if (!integration?.configOptions)
|
|
86
|
+
continue;
|
|
87
|
+
// Apply each config option that has a collected value
|
|
88
|
+
for (const option of integration.configOptions) {
|
|
89
|
+
const value = wiring.values[option.key];
|
|
90
|
+
if (value === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
applyWiringValue(option.targetPackage, option.configPath, value, cwd, state.usePrefix);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Write a single value to a package's config file on disk.
|
|
98
|
+
*/
|
|
99
|
+
function applyWiringValue(pkg, configPath, value, cwd, usePrefix) {
|
|
100
|
+
const filePath = resolveConfigFile(pkg, cwd, usePrefix);
|
|
101
|
+
if (!filePath)
|
|
102
|
+
return;
|
|
103
|
+
try {
|
|
104
|
+
const config = existsSync(filePath)
|
|
105
|
+
? JSON.parse(readFileSync(filePath, "utf-8"))
|
|
106
|
+
: {};
|
|
107
|
+
setNestedValue(config, configPath, value);
|
|
108
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n");
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Non-fatal — integration wiring is best-effort
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function resolveConfigFile(pkg, cwd, usePrefix) {
|
|
115
|
+
const configDirs = projectConfigDirs(usePrefix);
|
|
116
|
+
const configFile = pkg === "sessionlog" ? "settings.json" : "config.json";
|
|
117
|
+
// Check project config
|
|
118
|
+
const projectDir = configDirs[pkg];
|
|
119
|
+
if (projectDir) {
|
|
120
|
+
const projectPath = join(cwd, projectDir, configFile);
|
|
121
|
+
if (existsSync(projectPath))
|
|
122
|
+
return projectPath;
|
|
123
|
+
}
|
|
124
|
+
// Check global config
|
|
125
|
+
const globalDir = GLOBAL_CONFIG_DIRS[pkg];
|
|
126
|
+
if (globalDir) {
|
|
127
|
+
const globalPath = join(homedir(), globalDir, "config.json");
|
|
128
|
+
if (existsSync(globalPath))
|
|
129
|
+
return globalPath;
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
function setNestedValue(obj, keyPath, value) {
|
|
134
|
+
const parts = keyPath.split(".");
|
|
135
|
+
let target = obj;
|
|
136
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
137
|
+
if (typeof target[parts[i]] !== "object" || target[parts[i]] === null) {
|
|
138
|
+
target[parts[i]] = {};
|
|
139
|
+
}
|
|
140
|
+
target = target[parts[i]];
|
|
141
|
+
}
|
|
142
|
+
const finalKey = parts[parts.length - 1];
|
|
143
|
+
if (typeof value === "string" && /^\d+(\.\d+)?$/.test(value)) {
|
|
144
|
+
target[finalKey] = parseFloat(value);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
target[finalKey] = value;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Prompt the user for a single integration config option */
|
|
151
|
+
async function promptConfigOption(option) {
|
|
152
|
+
switch (option.type) {
|
|
153
|
+
case "confirm":
|
|
154
|
+
return confirm({
|
|
155
|
+
message: option.label,
|
|
156
|
+
default: option.default,
|
|
157
|
+
});
|
|
158
|
+
case "select":
|
|
159
|
+
return select({
|
|
160
|
+
message: option.label,
|
|
161
|
+
choices: option.choices ?? [],
|
|
162
|
+
default: option.default,
|
|
163
|
+
});
|
|
164
|
+
case "input":
|
|
165
|
+
return input({
|
|
166
|
+
message: option.label,
|
|
167
|
+
default: option.default,
|
|
168
|
+
});
|
|
169
|
+
default:
|
|
170
|
+
return option.default;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WizardState } from "../state.js";
|
|
2
|
+
/**
|
|
3
|
+
* Phase: Per-package interactive configuration.
|
|
4
|
+
*
|
|
5
|
+
* For each selected package that has setup config:
|
|
6
|
+
* - If quick mode, skip entirely (defaults will be used)
|
|
7
|
+
* - If package has a cliWizard, offer to delegate to it
|
|
8
|
+
* - If package has inlineOptions (and no wizard or wizard declined), walk through prompts
|
|
9
|
+
*/
|
|
10
|
+
export declare function configurePackages(state: WizardState): Promise<WizardState>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { confirm, input, select, password } from "@inquirer/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { PACKAGES } from "../../../packages/registry.js";
|
|
4
|
+
import { runPackageWizard, relocateAfterWizard, PREFIX_ENV_VARS, PROJECT_ROOT, } from "../../../packages/setup.js";
|
|
5
|
+
import * as ui from "../../../utils/ui.js";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
/**
|
|
8
|
+
* Phase: Per-package interactive configuration.
|
|
9
|
+
*
|
|
10
|
+
* For each selected package that has setup config:
|
|
11
|
+
* - If quick mode, skip entirely (defaults will be used)
|
|
12
|
+
* - If package has a cliWizard, offer to delegate to it
|
|
13
|
+
* - If package has inlineOptions (and no wizard or wizard declined), walk through prompts
|
|
14
|
+
*/
|
|
15
|
+
export async function configurePackages(state) {
|
|
16
|
+
const updated = { ...state, packageConfigs: { ...state.packageConfigs } };
|
|
17
|
+
const configurablePackages = updated.selectedPackages.filter((pkg) => PACKAGES[pkg]?.setup);
|
|
18
|
+
if (configurablePackages.length === 0 || updated.quick) {
|
|
19
|
+
return updated;
|
|
20
|
+
}
|
|
21
|
+
ui.heading(" Package configuration");
|
|
22
|
+
ui.info("Configure each package, or accept defaults.");
|
|
23
|
+
const cwd = process.cwd();
|
|
24
|
+
for (const pkgName of configurablePackages) {
|
|
25
|
+
const pkg = PACKAGES[pkgName];
|
|
26
|
+
const setupConfig = pkg.setup;
|
|
27
|
+
const config = { values: {}, usedCliWizard: false };
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(` ${chalk.bold(pkgName)} ${chalk.dim(pkg.description)}`);
|
|
30
|
+
// Try CLI wizard first if available
|
|
31
|
+
if (setupConfig.cliWizard) {
|
|
32
|
+
const useWizard = await confirm({
|
|
33
|
+
message: `Run ${pkgName}'s interactive setup wizard?`,
|
|
34
|
+
default: false,
|
|
35
|
+
});
|
|
36
|
+
if (useWizard) {
|
|
37
|
+
// Build prefix-aware env vars for project-level packages
|
|
38
|
+
const wizardConfig = { ...setupConfig.cliWizard };
|
|
39
|
+
if (updated.usePrefix && PREFIX_ENV_VARS[pkgName]) {
|
|
40
|
+
const envVar = PREFIX_ENV_VARS[pkgName];
|
|
41
|
+
const prefixDir = PROJECT_ROOT + "/" +
|
|
42
|
+
(pkgName === "opentasks" ? "opentasks" :
|
|
43
|
+
pkgName === "self-driving-repo" ? "self-driving" :
|
|
44
|
+
pkgName === "openteams" ? "openteams" :
|
|
45
|
+
pkgName === "cognitive-core" ? "cognitive-core" : pkgName);
|
|
46
|
+
wizardConfig.env = {
|
|
47
|
+
...wizardConfig.env,
|
|
48
|
+
// Some packages need absolute paths, others relative
|
|
49
|
+
[envVar]: pkgName === "cognitive-core"
|
|
50
|
+
? join(cwd, prefixDir)
|
|
51
|
+
: prefixDir,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const result = await runPackageWizard(pkgName, wizardConfig, updated, { cwd });
|
|
55
|
+
if (result.success) {
|
|
56
|
+
// Relocate from flat to prefixed location if needed
|
|
57
|
+
relocateAfterWizard(cwd, pkgName, updated.usePrefix);
|
|
58
|
+
config.usedCliWizard = true;
|
|
59
|
+
ui.success(`${pkgName} wizard completed.`);
|
|
60
|
+
updated.packageConfigs[pkgName] = config;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
ui.warn(`${pkgName} wizard failed: ${result.message ?? "unknown error"}`);
|
|
65
|
+
ui.info("Falling back to inline configuration.");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Inline options
|
|
70
|
+
if (setupConfig.inlineOptions && setupConfig.inlineOptions.length > 0) {
|
|
71
|
+
const customize = await confirm({
|
|
72
|
+
message: `Customize ${pkgName} settings?`,
|
|
73
|
+
default: false,
|
|
74
|
+
});
|
|
75
|
+
if (customize) {
|
|
76
|
+
for (const option of setupConfig.inlineOptions) {
|
|
77
|
+
// Check conditional visibility
|
|
78
|
+
if (option.when && !option.when(updated.selectedPackages)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const value = await promptOption(option);
|
|
82
|
+
config.values[option.key] = value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
updated.packageConfigs[pkgName] = config;
|
|
87
|
+
}
|
|
88
|
+
return updated;
|
|
89
|
+
}
|
|
90
|
+
/** Prompt the user for a single inline option */
|
|
91
|
+
async function promptOption(option) {
|
|
92
|
+
switch (option.type) {
|
|
93
|
+
case "confirm":
|
|
94
|
+
return confirm({
|
|
95
|
+
message: option.label,
|
|
96
|
+
default: option.default,
|
|
97
|
+
});
|
|
98
|
+
case "select":
|
|
99
|
+
return select({
|
|
100
|
+
message: option.label,
|
|
101
|
+
choices: option.choices ?? [],
|
|
102
|
+
default: option.default,
|
|
103
|
+
});
|
|
104
|
+
case "input":
|
|
105
|
+
return input({
|
|
106
|
+
message: option.label,
|
|
107
|
+
default: option.default,
|
|
108
|
+
});
|
|
109
|
+
case "password":
|
|
110
|
+
return password({
|
|
111
|
+
message: option.label,
|
|
112
|
+
mask: "*",
|
|
113
|
+
});
|
|
114
|
+
default:
|
|
115
|
+
return option.default;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|