@mesh-tech/mesh-cli 0.18.2 → 0.19.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/README.md +111 -56
- package/dist/bin/mesh.js +4843 -4077
- package/dist/bin/mesh.js.map +4 -4
- package/dist/build-info.json +2 -2
- package/dist/src/commands/create-app.d.ts +28 -0
- package/dist/src/commands/create-app.d.ts.map +1 -1
- package/dist/src/commands/create-app.js +45 -1
- package/dist/src/commands/create-app.js.map +1 -1
- package/dist/src/commands/dev-doctor.js +2 -2
- package/dist/src/commands/dev-doctor.js.map +1 -1
- package/dist/src/commands/init/wizard.d.ts +216 -0
- package/dist/src/commands/init/wizard.d.ts.map +1 -0
- package/dist/src/commands/init/wizard.js +471 -0
- package/dist/src/commands/init/wizard.js.map +1 -0
- package/dist/src/commands/init.d.ts +14 -6
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +41 -15
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/local/dev-local.d.ts.map +1 -1
- package/dist/src/commands/local/dev-local.js +6 -0
- package/dist/src/commands/local/dev-local.js.map +1 -1
- package/dist/src/commands/login.d.ts +76 -5
- package/dist/src/commands/login.d.ts.map +1 -1
- package/dist/src/commands/login.js +161 -60
- package/dist/src/commands/login.js.map +1 -1
- package/dist/src/commands/registry.d.ts +133 -10
- package/dist/src/commands/registry.d.ts.map +1 -1
- package/dist/src/commands/registry.js +238 -86
- package/dist/src/commands/registry.js.map +1 -1
- package/dist/src/commands/temporal.js +37 -23
- package/dist/src/commands/temporal.js.map +3 -3
- package/dist/src/docs/registry-docs.d.ts.map +1 -1
- package/dist/src/docs/registry-docs.js +8 -3
- package/dist/src/docs/registry-docs.js.map +1 -1
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +5 -1
- package/dist/src/program.js.map +1 -1
- package/dist/src/utils/auth-preflight.d.ts +51 -20
- package/dist/src/utils/auth-preflight.d.ts.map +1 -1
- package/dist/src/utils/auth-preflight.js +48 -21
- package/dist/src/utils/auth-preflight.js.map +1 -1
- package/dist/src/utils/mesh-json.d.ts +58 -0
- package/dist/src/utils/mesh-json.d.ts.map +1 -0
- package/dist/src/utils/mesh-json.js +85 -0
- package/dist/src/utils/mesh-json.js.map +1 -0
- package/dist/src/utils/registry-broker.d.ts +12 -29
- package/dist/src/utils/registry-broker.d.ts.map +1 -1
- package/dist/src/utils/registry-broker.js +12 -29
- package/dist/src/utils/registry-broker.js.map +1 -1
- package/dist/src/utils/registry-identity.d.ts +170 -0
- package/dist/src/utils/registry-identity.d.ts.map +1 -0
- package/dist/src/utils/registry-identity.js +273 -0
- package/dist/src/utils/registry-identity.js.map +1 -0
- package/package.json +3 -2
- package/skills/core/SKILL.md +6 -5
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bare `mesh init` — the guided setup of a machine and a repo for one tenant.
|
|
3
|
+
*
|
|
4
|
+
* Four questions and four steps, in order:
|
|
5
|
+
*
|
|
6
|
+
* 1. tenant — which tenant this repo belongs to
|
|
7
|
+
* 2. mode — local only (`mesh start` / `mesh dev`) or a deployed platform
|
|
8
|
+
* 3. registry — package-registry access, signing in if the machine has none
|
|
9
|
+
* 4. platform — (deployed only) `mesh login <tenant>.<env>` in-process
|
|
10
|
+
* 5. repo — bootstrap an empty apps repo, or check an existing one
|
|
11
|
+
* 6. skills — the agent skills the repo's packages ship
|
|
12
|
+
*
|
|
13
|
+
* Two identities never mix: the registry step talks to the ONE global package
|
|
14
|
+
* registry and never needs a context; the platform step is the only place a
|
|
15
|
+
* `<tenant>.<env>` context appears, and the local branch never mentions it.
|
|
16
|
+
*
|
|
17
|
+
* Every step is data (`WizardStep` → `StepResult`) so the summary, the exit
|
|
18
|
+
* code and the `--json` document are one reducer over one list, and a step
|
|
19
|
+
* that fails without blocking (a registry 403 — the user needs the summary to
|
|
20
|
+
* know whom to ask) lets the rest run. Every prompt has a flag, so a runner
|
|
21
|
+
* with `--tenant … --local --yes` sees no prompt at all.
|
|
22
|
+
*/
|
|
23
|
+
import * as fs from "fs";
|
|
24
|
+
import * as path from "path";
|
|
25
|
+
import chalk from "chalk";
|
|
26
|
+
import { logInfo, logWarn } from "../../utils/log.js";
|
|
27
|
+
import { MeshCliError, emitJsonPayload } from "../../utils/errors.js";
|
|
28
|
+
import { probeRegistryToken } from "../../utils/auth-preflight.js";
|
|
29
|
+
import { RegistryNotAuthorizedError } from "../registry.js";
|
|
30
|
+
import { readRegistrySession } from "../../utils/registry-identity.js";
|
|
31
|
+
import { findMeshJson, isValidTenantName, writeMeshJson } from "../../utils/mesh-json.js";
|
|
32
|
+
import { discoverConfigForContext, isRemoteEnvironment, readCredentials, renderNoConfigHelp, runLoginFlow, tokenStillValid, } from "../login.js";
|
|
33
|
+
import { bootstrapAppsRepo, isInsidePlatformMonorepo, shouldBootstrapAppsRepo } from "../create-app.js";
|
|
34
|
+
import { resolveTargetRoot, syncSkills } from "../skills.js";
|
|
35
|
+
import { detectLocalTenant } from "../local/dev-local.js";
|
|
36
|
+
/** Printed when the registry step has no session and no way to sign in. */
|
|
37
|
+
export const NO_SESSION_NO_TTY_MESSAGE = "No registry session and no terminal to sign in with.\n" +
|
|
38
|
+
" On a headless box: mesh registry login --device (one-time, prints a code)\n" +
|
|
39
|
+
" In CI with AWS creds: mesh registry login --ci";
|
|
40
|
+
/** Printed when a non-TTY run has no `--tenant`. */
|
|
41
|
+
export const TENANT_REQUIRED_MESSAGE = "--tenant is required (no TTY for interactive mode)";
|
|
42
|
+
/** Exit code for a Ctrl-C at a prompt: nothing half-written, conventional SIGINT code. */
|
|
43
|
+
export const INTERRUPTED_EXIT_CODE = 130;
|
|
44
|
+
const STEP_LABELS = {
|
|
45
|
+
registry: "Registry access",
|
|
46
|
+
platform: "Platform sign-in",
|
|
47
|
+
repo: "Repo",
|
|
48
|
+
skills: "Agent skills",
|
|
49
|
+
};
|
|
50
|
+
// ── pure parts ──────────────────────────────────────────────────────────────
|
|
51
|
+
/**
|
|
52
|
+
* The exit code for a finished run: 1 when any step failed (blocking or not
|
|
53
|
+
* — a registry 403 still means the machine is not set up), else 0.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* wizardExitCode([{ name: "Registry access", status: "fail", detail: "…", blocking: false }]); // → 1
|
|
57
|
+
*/
|
|
58
|
+
export function wizardExitCode(steps) {
|
|
59
|
+
return steps.some((s) => s.status === "fail") ? 1 : 0;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The commands to run next, by mode.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* wizardNextCommands({ platform: "dev" }); // → ["mesh create-app", "mesh deploy up # from the app directory"]
|
|
66
|
+
*/
|
|
67
|
+
export function wizardNextCommands(mode) {
|
|
68
|
+
return mode === "local"
|
|
69
|
+
? ["mesh create-app"]
|
|
70
|
+
: ["mesh create-app", "mesh deploy up # from the app directory, once it exists"];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Whether the wizard should stop after `result`: a failing step that did not
|
|
74
|
+
* opt out of blocking.
|
|
75
|
+
*/
|
|
76
|
+
export function stepBlocks(result) {
|
|
77
|
+
return result.status === "fail" && result.blocking !== false;
|
|
78
|
+
}
|
|
79
|
+
/** The mode as a short phrase for the summary heading. */
|
|
80
|
+
export function describeMode(mode) {
|
|
81
|
+
return mode === "local" ? "local only" : `deployed platform (${mode.platform})`;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Render the summary check-list — the same lines for a terminal and for the
|
|
85
|
+
* stderr side of `--json`.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* renderWizardSummary({ tenant: "acme", mode: "local", steps: [], next: ["mesh create-app"] });
|
|
89
|
+
*/
|
|
90
|
+
export function renderWizardSummary(outcome, opts = {}) {
|
|
91
|
+
const paint = opts.color === false ? { green: (s) => s, red: (s) => s, yellow: (s) => s, dim: (s) => s, cyan: (s) => s } : chalk;
|
|
92
|
+
const icon = (status) => status === "pass" ? paint.green("✔") : status === "fail" ? paint.red("✘") : status === "warn" ? paint.yellow("▲") : paint.dim("–");
|
|
93
|
+
const lines = [`Setup summary — tenant ${outcome.tenant} (${describeMode(outcome.mode)})`];
|
|
94
|
+
for (const step of outcome.steps) {
|
|
95
|
+
lines.push(` ${icon(step.status)} ${step.name.padEnd(18)} ${step.detail}`);
|
|
96
|
+
if (step.fix && step.status !== "pass")
|
|
97
|
+
lines.push(` ${paint.dim("→ run:")} ${paint.cyan(step.fix)}`);
|
|
98
|
+
}
|
|
99
|
+
lines.push("", "Next:");
|
|
100
|
+
for (const cmd of outcome.next)
|
|
101
|
+
lines.push(` ${cmd}`);
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Resolve the answers that need no prompt: flags first, then `--yes`
|
|
106
|
+
* defaults, then what the repo already records. Returns the questions still
|
|
107
|
+
* open so the caller prompts for exactly those.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* resolveAnswers({ tenant: "acme", local: true }, null, false)
|
|
111
|
+
* // → { tenant: "acme", mode: "local", open: [] }
|
|
112
|
+
*/
|
|
113
|
+
export function resolveAnswers(opts, recorded, interactive) {
|
|
114
|
+
const open = [];
|
|
115
|
+
let tenant = opts.tenant;
|
|
116
|
+
if (tenant !== undefined && !isValidTenantName(tenant)) {
|
|
117
|
+
throw new MeshCliError(`Invalid tenant name '${tenant}' (lowercase alphanumeric + dashes, starting with a letter).`);
|
|
118
|
+
}
|
|
119
|
+
if (!tenant && (opts.yes || !interactive) && recorded)
|
|
120
|
+
tenant = recorded.tenant;
|
|
121
|
+
if (!tenant) {
|
|
122
|
+
if (!interactive)
|
|
123
|
+
throw new MeshCliError(TENANT_REQUIRED_MESSAGE);
|
|
124
|
+
open.push("tenant");
|
|
125
|
+
}
|
|
126
|
+
let mode;
|
|
127
|
+
if (opts.local && opts.platform) {
|
|
128
|
+
throw new MeshCliError("--local and --platform are mutually exclusive.");
|
|
129
|
+
}
|
|
130
|
+
if (opts.platform)
|
|
131
|
+
mode = { platform: opts.platform };
|
|
132
|
+
else if (opts.local)
|
|
133
|
+
mode = "local";
|
|
134
|
+
else if (opts.yes || !interactive) {
|
|
135
|
+
mode = recorded && recorded.platform !== "local" ? { platform: recorded.platform } : "local";
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
open.push("mode");
|
|
139
|
+
}
|
|
140
|
+
return { tenant, mode, open };
|
|
141
|
+
}
|
|
142
|
+
// ── steps ───────────────────────────────────────────────────────────────────
|
|
143
|
+
/** The registry step, exported so a test can drive the real thing through its seams. */
|
|
144
|
+
export const registryStep = {
|
|
145
|
+
name: "registry",
|
|
146
|
+
async run(ctx) {
|
|
147
|
+
const name = STEP_LABELS.registry;
|
|
148
|
+
const probe = await (ctx.seams?.probe ?? probeRegistryToken)();
|
|
149
|
+
if (probe.state === "fresh") {
|
|
150
|
+
const session = readRegistrySession();
|
|
151
|
+
return { name, status: "pass", detail: `Registry access OK (${session ? `signed in as ${session.email}` : "token valid"})` };
|
|
152
|
+
}
|
|
153
|
+
if (probe.state === "unreachable") {
|
|
154
|
+
return {
|
|
155
|
+
name,
|
|
156
|
+
status: "warn",
|
|
157
|
+
detail: `could not reach the registry to verify access (${probe.detail ?? "unknown error"})`,
|
|
158
|
+
fix: "mesh registry login",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (!ctx.interactive && !ctx.device && !ctx.profile) {
|
|
162
|
+
logWarn(NO_SESSION_NO_TTY_MESSAGE);
|
|
163
|
+
return { name, status: "fail", detail: NO_SESSION_NO_TTY_MESSAGE.split("\n")[0], fix: "mesh registry login --device", blocking: true };
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const login = ctx.seams?.runRegistryLogin ??
|
|
167
|
+
(async (opts) => {
|
|
168
|
+
const { runRegistryLogin } = await import("../registry.js");
|
|
169
|
+
await runRegistryLogin(undefined, opts);
|
|
170
|
+
});
|
|
171
|
+
await login({ device: ctx.device, profile: ctx.profile });
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
175
|
+
if (err instanceof RegistryNotAuthorizedError) {
|
|
176
|
+
// The account is fine; the grant is missing. Not blocking: the repo
|
|
177
|
+
// steps still tell the user what else is set up, and the summary
|
|
178
|
+
// carries the "whom to ask" line.
|
|
179
|
+
return {
|
|
180
|
+
name,
|
|
181
|
+
status: "fail",
|
|
182
|
+
detail: `not authorized — ${message.split("\n")[0]}`,
|
|
183
|
+
fix: "ask a Mesh platform admin for the registry:read role, then: mesh registry login",
|
|
184
|
+
blocking: false,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
name,
|
|
189
|
+
status: "fail",
|
|
190
|
+
detail: message.split("\n")[0],
|
|
191
|
+
fix: ctx.device || ctx.remote ? "mesh registry login --device" : "mesh registry login",
|
|
192
|
+
blocking: true,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const session = readRegistrySession();
|
|
196
|
+
return { name, status: "pass", detail: `Registry access OK (${session ? `signed in as ${session.email}` : "token written"})` };
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
const platformStep = {
|
|
200
|
+
name: "platform",
|
|
201
|
+
async run(ctx) {
|
|
202
|
+
const name = STEP_LABELS.platform;
|
|
203
|
+
if (!ctx.context)
|
|
204
|
+
return { name, status: "skip", detail: "local only — no platform to sign in to" };
|
|
205
|
+
const context = ctx.context;
|
|
206
|
+
const cached = readCredentials(context);
|
|
207
|
+
if (cached && tokenStillValid(cached.expiresAt)) {
|
|
208
|
+
return { name, status: "pass", detail: `signed in to ${context}${cached.email ? ` as ${cached.email}` : ""}` };
|
|
209
|
+
}
|
|
210
|
+
const config = await discoverConfigForContext(context);
|
|
211
|
+
if (!config) {
|
|
212
|
+
logWarn(renderNoConfigHelp(context));
|
|
213
|
+
return { name, status: "fail", detail: `no configuration found for ${context} (see above)`, fix: `mesh login ${context}` };
|
|
214
|
+
}
|
|
215
|
+
if (!ctx.interactive && !ctx.device) {
|
|
216
|
+
return { name, status: "fail", detail: `no session for ${context} and no terminal to sign in with`, fix: `mesh login ${context} --device` };
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
await runLoginFlow(context, config, { device: ctx.device });
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
return { name, status: "fail", detail: `sign-in failed: ${err.message}`, fix: `mesh login ${context}${ctx.device ? " --device" : ""}` };
|
|
223
|
+
}
|
|
224
|
+
const creds = readCredentials(context);
|
|
225
|
+
return {
|
|
226
|
+
name,
|
|
227
|
+
status: "pass",
|
|
228
|
+
detail: `signed in to ${context}${creds?.email ? ` as ${creds.email}` : ""} — tenant registration: mesh init app-tenant --context ${context} --hub-url <hub api url>`,
|
|
229
|
+
};
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* Classify `cwd` for the repo step. Pure over the filesystem; exported for
|
|
234
|
+
* tests.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* classifyRepo("/tmp/empty-git-clone"); // → "empty-apps-repo"
|
|
238
|
+
*/
|
|
239
|
+
export function classifyRepo(cwd) {
|
|
240
|
+
if (isInsidePlatformMonorepo(cwd))
|
|
241
|
+
return { kind: "platform-monorepo", root: resolveTargetRoot(cwd) };
|
|
242
|
+
if (shouldBootstrapAppsRepo(cwd))
|
|
243
|
+
return { kind: "empty-apps-repo", root: cwd };
|
|
244
|
+
const root = resolveTargetRoot(cwd);
|
|
245
|
+
const inRepo = fs.existsSync(path.join(root, ".git"));
|
|
246
|
+
if (!inRepo)
|
|
247
|
+
return { kind: "no-repo", root };
|
|
248
|
+
const hasWorkspace = fs.existsSync(path.join(root, "pnpm-workspace.yaml")) || fs.existsSync(path.join(root, "pnpm-lock.yaml"));
|
|
249
|
+
const hasApps = fs.existsSync(path.join(root, "apps")) || fs.existsSync(path.join(root, "tenants"));
|
|
250
|
+
if (hasWorkspace || hasApps)
|
|
251
|
+
return { kind: "apps-repo", root };
|
|
252
|
+
return { kind: "other-repo", root };
|
|
253
|
+
}
|
|
254
|
+
const repoStep = {
|
|
255
|
+
name: "repo",
|
|
256
|
+
async run(ctx) {
|
|
257
|
+
const name = STEP_LABELS.repo;
|
|
258
|
+
if (ctx.skipRepo)
|
|
259
|
+
return { name, status: "skip", detail: "--skip-repo" };
|
|
260
|
+
const { kind, root } = classifyRepo(ctx.cwd);
|
|
261
|
+
switch (kind) {
|
|
262
|
+
case "platform-monorepo":
|
|
263
|
+
return { name, status: "skip", detail: "inside mesh-platform — apps here link workspace packages; nothing to set up" };
|
|
264
|
+
case "no-repo":
|
|
265
|
+
return {
|
|
266
|
+
name,
|
|
267
|
+
status: "skip",
|
|
268
|
+
detail: `not in a git repo — clone (or git init) your ${ctx.tenant}-mesh-apps repo and re-run mesh init there`,
|
|
269
|
+
};
|
|
270
|
+
case "other-repo":
|
|
271
|
+
return {
|
|
272
|
+
name,
|
|
273
|
+
status: "warn",
|
|
274
|
+
detail: "this repo is not a Mesh apps repo (no pnpm workspace, no apps/)",
|
|
275
|
+
fix: "mesh create-app # scaffolds an app and the workspace files around it",
|
|
276
|
+
};
|
|
277
|
+
case "empty-apps-repo": {
|
|
278
|
+
const go = ctx.yes || !ctx.interactive
|
|
279
|
+
? true
|
|
280
|
+
: await ctx.prompts.confirm({ message: `Empty repo — bootstrap the ${ctx.tenant}-mesh-apps layout here?`, default: true });
|
|
281
|
+
if (!go)
|
|
282
|
+
return { name, status: "skip", detail: "empty repo left as is", fix: "mesh create-app" };
|
|
283
|
+
const created = bootstrapAppsRepo(root, ctx.tenant);
|
|
284
|
+
return { name, status: "pass", detail: `bootstrapped apps repo: ${created.join(", ")}` };
|
|
285
|
+
}
|
|
286
|
+
case "apps-repo": {
|
|
287
|
+
const missing = [];
|
|
288
|
+
if (!fs.existsSync(path.join(root, "package.json")))
|
|
289
|
+
missing.push("package.json");
|
|
290
|
+
if (!fs.existsSync(path.join(root, "pnpm-workspace.yaml")) && !fs.existsSync(path.join(root, "pnpm-lock.yaml"))) {
|
|
291
|
+
missing.push("pnpm-workspace.yaml");
|
|
292
|
+
}
|
|
293
|
+
if (missing.length) {
|
|
294
|
+
return { name, status: "warn", detail: `apps repo missing ${missing.join(", ")}`, fix: "mesh create-app # writes the workspace files" };
|
|
295
|
+
}
|
|
296
|
+
return { name, status: "pass", detail: `apps repo at ${root}` };
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
const skillsStep = {
|
|
302
|
+
name: "skills",
|
|
303
|
+
async run(ctx) {
|
|
304
|
+
const name = STEP_LABELS.skills;
|
|
305
|
+
if (ctx.skipRepo)
|
|
306
|
+
return { name, status: "skip", detail: "--skip-repo" };
|
|
307
|
+
const { kind, root } = classifyRepo(ctx.cwd);
|
|
308
|
+
if (kind !== "apps-repo" && kind !== "empty-apps-repo") {
|
|
309
|
+
return { name, status: "skip", detail: "no apps repo to install skills into" };
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
// In fix mode a `false` return is not a failure: the base skills are
|
|
313
|
+
// written; the platform skills arrive with the packages, so the sync
|
|
314
|
+
// asks to be re-run after the first install — the doctor reads it the
|
|
315
|
+
// same way.
|
|
316
|
+
const complete = syncSkills(root);
|
|
317
|
+
return complete
|
|
318
|
+
? { name, status: "pass", detail: "base skills + Intent discovery in sync" }
|
|
319
|
+
: { name, status: "pass", detail: "base skills synced — after pnpm install, run: mesh skills sync (platform skills)" };
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
return { name, status: "fail", detail: `skills sync failed: ${err.message}`, fix: "mesh skills sync", blocking: false };
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
/** The steps in run order. Exported so tests can drive the reducer with fakes. */
|
|
327
|
+
export const WIZARD_STEPS = [registryStep, platformStep, repoStep, skillsStep];
|
|
328
|
+
/**
|
|
329
|
+
* Run `steps` in order, stopping after the first blocking failure. Pure over
|
|
330
|
+
* the steps' results — the reducer the CLI and the tests share.
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* const steps = await runWizardSteps(ctx, WIZARD_STEPS);
|
|
334
|
+
*/
|
|
335
|
+
export async function runWizardSteps(ctx, steps) {
|
|
336
|
+
const results = [];
|
|
337
|
+
for (const step of steps) {
|
|
338
|
+
const result = await step.run(ctx);
|
|
339
|
+
results.push(result);
|
|
340
|
+
if (stepBlocks(result))
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
return results;
|
|
344
|
+
}
|
|
345
|
+
// ── the command ─────────────────────────────────────────────────────────────
|
|
346
|
+
async function inquirerPrompts() {
|
|
347
|
+
const [{ default: input }, { default: select }, { default: confirm }] = await Promise.all([
|
|
348
|
+
import("@inquirer/input"),
|
|
349
|
+
import("@inquirer/select"),
|
|
350
|
+
import("@inquirer/confirm"),
|
|
351
|
+
]);
|
|
352
|
+
return {
|
|
353
|
+
input: (args) => input(args),
|
|
354
|
+
select: (args) => select(args),
|
|
355
|
+
confirm: (args) => confirm(args),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
function isInterrupt(err) {
|
|
359
|
+
return err instanceof Error && err.name === "ExitPromptError";
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* The wizard entry point behind bare `mesh init`.
|
|
363
|
+
*
|
|
364
|
+
* Returns the process exit code instead of exiting, so the caller decides
|
|
365
|
+
* (and a test can assert on it). Ctrl-C at a prompt returns 130 with nothing
|
|
366
|
+
* written. All human output goes to stderr under `--json`, leaving stdout for
|
|
367
|
+
* the one document.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* process.exitCode = await runInitWizard({ tenant: "acme", local: true, yes: true });
|
|
371
|
+
*/
|
|
372
|
+
export async function runInitWizard(opts, deps = {}) {
|
|
373
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
374
|
+
const interactive = deps.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
375
|
+
const remote = deps.remote ?? isRemoteEnvironment();
|
|
376
|
+
const recorded = findMeshJson(cwd)?.data ?? null;
|
|
377
|
+
const origLog = console.log;
|
|
378
|
+
if (opts.json)
|
|
379
|
+
console.log = (...a) => console.error(...a);
|
|
380
|
+
try {
|
|
381
|
+
const answers = resolveAnswers(opts, recorded, interactive);
|
|
382
|
+
const prompts = deps.prompts ?? (answers.open.length ? await inquirerPrompts() : {});
|
|
383
|
+
let tenant = answers.tenant;
|
|
384
|
+
if (!tenant) {
|
|
385
|
+
const detected = recorded?.tenant ?? (() => {
|
|
386
|
+
try {
|
|
387
|
+
const t = detectLocalTenant(cwd);
|
|
388
|
+
return t === "local" ? undefined : t;
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
return undefined;
|
|
392
|
+
}
|
|
393
|
+
})();
|
|
394
|
+
tenant = await prompts.input({
|
|
395
|
+
message: "Tenant name",
|
|
396
|
+
default: detected,
|
|
397
|
+
validate: (v) => (isValidTenantName(v) ? true : "lowercase letters, digits and dashes, starting with a letter"),
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
let mode = answers.mode;
|
|
401
|
+
if (!mode) {
|
|
402
|
+
const choice = await prompts.select({
|
|
403
|
+
message: "Where does this tenant run?",
|
|
404
|
+
choices: [
|
|
405
|
+
{ name: "Local only (mesh start / mesh dev — no deployed platform yet)", value: "local" },
|
|
406
|
+
{ name: `A deployed Mesh platform (I have a ${tenant}.<env> context)`, value: "deployed" },
|
|
407
|
+
],
|
|
408
|
+
default: recorded && recorded.platform !== "local" ? "deployed" : "local",
|
|
409
|
+
});
|
|
410
|
+
if (choice === "local")
|
|
411
|
+
mode = "local";
|
|
412
|
+
else {
|
|
413
|
+
const env = await prompts.input({
|
|
414
|
+
message: "Environment",
|
|
415
|
+
default: recorded && recorded.platform !== "local" ? recorded.platform : "dev",
|
|
416
|
+
validate: (v) => (/^[a-z][a-z0-9-]*$/.test(v) ? true : "lowercase letters, digits and dashes"),
|
|
417
|
+
});
|
|
418
|
+
mode = { platform: env };
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
const ctx = {
|
|
422
|
+
cwd,
|
|
423
|
+
tenant,
|
|
424
|
+
mode,
|
|
425
|
+
context: mode === "local" ? null : `${tenant}.${mode.platform}`,
|
|
426
|
+
device: opts.device,
|
|
427
|
+
profile: opts.profile,
|
|
428
|
+
interactive,
|
|
429
|
+
remote,
|
|
430
|
+
yes: Boolean(opts.yes),
|
|
431
|
+
skipRepo: Boolean(opts.skipRepo),
|
|
432
|
+
prompts,
|
|
433
|
+
seams: deps.seams,
|
|
434
|
+
};
|
|
435
|
+
logInfo(`Setting up tenant '${tenant}' (${describeMode(mode)})…`);
|
|
436
|
+
const steps = await runWizardSteps(ctx, deps.steps ?? WIZARD_STEPS);
|
|
437
|
+
// Persist what was answered so a re-run pre-fills — only where there is a
|
|
438
|
+
// repo of ours to record it in.
|
|
439
|
+
// Only a Mesh apps repo (or the empty clone that just became one) gets
|
|
440
|
+
// the record — never an unrelated checkout the wizard happens to run in.
|
|
441
|
+
const { kind, root } = classifyRepo(cwd);
|
|
442
|
+
if (!opts.skipRepo && (kind === "apps-repo" || kind === "empty-apps-repo")) {
|
|
443
|
+
const written = writeMeshJson(root, { tenant, platform: mode === "local" ? "local" : mode.platform });
|
|
444
|
+
logInfo(`Recorded tenant + mode in ${written}`);
|
|
445
|
+
}
|
|
446
|
+
const outcome = { tenant, mode, steps, next: wizardNextCommands(mode) };
|
|
447
|
+
const code = wizardExitCode(steps);
|
|
448
|
+
if (opts.json) {
|
|
449
|
+
console.log = origLog;
|
|
450
|
+
emitJsonPayload({ ok: code === 0, ...outcome });
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
console.log("");
|
|
454
|
+
console.log(renderWizardSummary(outcome));
|
|
455
|
+
console.log("");
|
|
456
|
+
}
|
|
457
|
+
return code;
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
if (isInterrupt(err)) {
|
|
461
|
+
console.error("");
|
|
462
|
+
logWarn("Interrupted — nothing was written.");
|
|
463
|
+
return INTERRUPTED_EXIT_CODE;
|
|
464
|
+
}
|
|
465
|
+
throw err;
|
|
466
|
+
}
|
|
467
|
+
finally {
|
|
468
|
+
console.log = origLog;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
//# sourceMappingURL=wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../../../src/commands/init/wizard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* mesh init
|
|
3
|
-
*
|
|
2
|
+
* mesh init — bare: the guided setup wizard (`./init/wizard.ts`);
|
|
3
|
+
* `init platform <tenant>`: scaffold a platform repo;
|
|
4
|
+
* `init app-tenant`: the doctor for a tenant apps repo (design §3.1,
|
|
5
|
+
* AC A1–A3), described below.
|
|
4
6
|
*
|
|
5
7
|
* Runs a read-only check pipeline; every failure names the exact `mesh`
|
|
6
8
|
* command that fixes it (never a person — A2). Re-running IS the doctor
|
|
@@ -36,8 +38,15 @@ interface CheckResult {
|
|
|
36
38
|
* the command `--fix` actually executes: `runRegistryLogin` is called with the
|
|
37
39
|
* doctor's own `--profile` (or none), so advertising a hardcoded
|
|
38
40
|
* `--profile mesh-dev` would be a command the doctor never runs.
|
|
41
|
+
*
|
|
42
|
+
* The registry is global, so the command never carries a context — the bare
|
|
43
|
+
* form is the one that works on a machine that has never signed in.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* registryFixCommand(); // → "mesh registry login"
|
|
47
|
+
* registryFixCommand("mesh-dev"); // → "mesh registry login --profile mesh-dev"
|
|
39
48
|
*/
|
|
40
|
-
export declare function registryFixCommand(profile?: string
|
|
49
|
+
export declare function registryFixCommand(profile?: string): string;
|
|
41
50
|
/**
|
|
42
51
|
* The two registry checks, exported for tests.
|
|
43
52
|
*
|
|
@@ -51,14 +60,13 @@ export declare function registryFixCommand(profile?: string, context?: string):
|
|
|
51
60
|
* expiry. `mesh registry login` now removes it, so it is the fix for both.
|
|
52
61
|
*/
|
|
53
62
|
export declare function registryChecks(args: {
|
|
54
|
-
context: string;
|
|
55
63
|
fix: boolean;
|
|
56
64
|
/** AWS SSO profile to log in with — threaded from `mesh init app-tenant --profile`. */
|
|
57
65
|
profile?: string;
|
|
58
66
|
/** Test seam — defaults to the real network probe against ~/.npmrc. */
|
|
59
67
|
probe?: typeof probeRegistryToken;
|
|
60
|
-
/** Test seam — defaults to `runRegistryLogin
|
|
61
|
-
login?: (
|
|
68
|
+
/** Test seam — defaults to `runRegistryLogin` (context-free: the registry is global). */
|
|
69
|
+
login?: () => Promise<void>;
|
|
62
70
|
}): Promise<CheckResult[]>;
|
|
63
71
|
export declare function registerInitCommands(program: Command): void;
|
|
64
72
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,OAAO,EAGL,kBAAkB,EACnB,MAAM,4BAA4B,CAAC;AAMpC,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAgCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,OAAO,CAAC;IACb,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAClC,yFAAyF;IACzF,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAqFzB;AA6HD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+I3D"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* mesh init
|
|
3
|
-
*
|
|
2
|
+
* mesh init — bare: the guided setup wizard (`./init/wizard.ts`);
|
|
3
|
+
* `init platform <tenant>`: scaffold a platform repo;
|
|
4
|
+
* `init app-tenant`: the doctor for a tenant apps repo (design §3.1,
|
|
5
|
+
* AC A1–A3), described below.
|
|
4
6
|
*
|
|
5
7
|
* Runs a read-only check pipeline; every failure names the exact `mesh`
|
|
6
8
|
* command that fixes it (never a person — A2). Re-running IS the doctor
|
|
@@ -64,13 +66,16 @@ function readHomeNpmrc() {
|
|
|
64
66
|
* the command `--fix` actually executes: `runRegistryLogin` is called with the
|
|
65
67
|
* doctor's own `--profile` (or none), so advertising a hardcoded
|
|
66
68
|
* `--profile mesh-dev` would be a command the doctor never runs.
|
|
69
|
+
*
|
|
70
|
+
* The registry is global, so the command never carries a context — the bare
|
|
71
|
+
* form is the one that works on a machine that has never signed in.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* registryFixCommand(); // → "mesh registry login"
|
|
75
|
+
* registryFixCommand("mesh-dev"); // → "mesh registry login --profile mesh-dev"
|
|
67
76
|
*/
|
|
68
|
-
export function registryFixCommand(profile
|
|
69
|
-
|
|
70
|
-
// `mesh registry login` skips the broker entirely — so advertising the bare
|
|
71
|
-
// form sends someone with no AWS account to a command that cannot work.
|
|
72
|
-
const base = context ? `mesh registry login ${context}` : "mesh registry login";
|
|
73
|
-
return profile ? `${base} --profile ${profile}` : base;
|
|
77
|
+
export function registryFixCommand(profile) {
|
|
78
|
+
return profile ? `mesh registry login --profile ${profile}` : "mesh registry login";
|
|
74
79
|
}
|
|
75
80
|
/**
|
|
76
81
|
* The two registry checks, exported for tests.
|
|
@@ -85,16 +90,16 @@ export function registryFixCommand(profile, context) {
|
|
|
85
90
|
* expiry. `mesh registry login` now removes it, so it is the fix for both.
|
|
86
91
|
*/
|
|
87
92
|
export async function registryChecks(args) {
|
|
88
|
-
const {
|
|
93
|
+
const { fix, profile } = args;
|
|
89
94
|
const probe = args.probe ?? probeRegistryToken;
|
|
90
95
|
const login = args.login ??
|
|
91
|
-
(async (
|
|
96
|
+
(async () => {
|
|
92
97
|
const { runRegistryLogin } = await import("./registry.js");
|
|
93
|
-
await runRegistryLogin(
|
|
98
|
+
await runRegistryLogin(undefined, profile ? { profile } : {});
|
|
94
99
|
});
|
|
95
100
|
// The command we ADVERTISE must be the command `--fix` RUNS — otherwise the
|
|
96
101
|
// doctor tells you to pass a profile it then silently drops.
|
|
97
|
-
const REGISTRY_FIX = registryFixCommand(profile
|
|
102
|
+
const REGISTRY_FIX = registryFixCommand(profile);
|
|
98
103
|
let tokenState = await probe({ npmrcPath: homeNpmrcPath() });
|
|
99
104
|
let hijack = findUnscopedCodeArtifactRegistry(readHomeNpmrc());
|
|
100
105
|
let repaired = false;
|
|
@@ -102,7 +107,7 @@ export async function registryChecks(args) {
|
|
|
102
107
|
// One login repairs both: it refreshes the token AND strips the unscoped line.
|
|
103
108
|
if (fix && (tokenState.state === "expired" || tokenState.state === "missing" || hijack)) {
|
|
104
109
|
try {
|
|
105
|
-
await login(
|
|
110
|
+
await login();
|
|
106
111
|
repaired = true;
|
|
107
112
|
tokenState = await probe({ npmrcPath: homeNpmrcPath() });
|
|
108
113
|
hijack = findUnscopedCodeArtifactRegistry(readHomeNpmrc());
|
|
@@ -184,7 +189,7 @@ async function runChecks(args) {
|
|
|
184
189
|
checks.push({ name: "Public npm not hijacked", status: "pass", detail: "local context — no registry required" });
|
|
185
190
|
}
|
|
186
191
|
else {
|
|
187
|
-
checks.push(...(await registryChecks({
|
|
192
|
+
checks.push(...(await registryChecks({ fix, profile })));
|
|
188
193
|
}
|
|
189
194
|
// 3 + 4. Platform tenant + app tenant via the Hub API (the registry)
|
|
190
195
|
const hub = await probeHubTenants(hubUrl, accessToken);
|
|
@@ -263,7 +268,28 @@ async function runChecks(args) {
|
|
|
263
268
|
return checks;
|
|
264
269
|
}
|
|
265
270
|
export function registerInitCommands(program) {
|
|
266
|
-
const init = program
|
|
271
|
+
const init = program
|
|
272
|
+
.command("init")
|
|
273
|
+
// The wizard's flags (--tenant, --profile, --json, …) overlap the
|
|
274
|
+
// subcommands' own. Positional options keep them apart: options before a
|
|
275
|
+
// subcommand name belong to the wizard, options after it to the subcommand,
|
|
276
|
+
// so `mesh init app-tenant --json` still reaches the doctor unchanged.
|
|
277
|
+
.enablePositionalOptions()
|
|
278
|
+
.description("Set up this machine and repo for a tenant — a guided wizard with no subcommand (tenant, local or deployed, package-registry sign-in, repo, skills); `init platform` scaffolds a platform repo, `init app-tenant` is the apps-repo doctor")
|
|
279
|
+
.option("--tenant <name>", "app tenant this repo belongs to (prompted when omitted on a TTY)")
|
|
280
|
+
.option("--local", "local only — mesh start / mesh dev, no deployed platform (the default)")
|
|
281
|
+
.option("--platform <env>", "a deployed platform's environment; signs in to <tenant>.<env>")
|
|
282
|
+
.option("--device", "device-code sign-in for the registry and platform steps (headless / SSH)")
|
|
283
|
+
.option("--profile <aws-profile>", "deployers only: AWS profile that can read the registry (skips the broker)")
|
|
284
|
+
.option("--skip-repo", "do not bootstrap, check or record anything in the current repo", false)
|
|
285
|
+
.option("--yes", "accept every default and never prompt", false)
|
|
286
|
+
.option("--json", "one JSON document on stdout ({tenant, mode, steps, next}); human output on stderr", false)
|
|
287
|
+
.action(async (opts) => {
|
|
288
|
+
const { runInitWizard } = await import("./init/wizard.js");
|
|
289
|
+
const code = await runInitWizard(opts);
|
|
290
|
+
if (code !== 0)
|
|
291
|
+
process.exitCode = code;
|
|
292
|
+
});
|
|
267
293
|
init
|
|
268
294
|
.command("platform <tenant>")
|
|
269
295
|
.description("Scaffold a tenant PLATFORM repo (core + platform Pulumi layers on @mesh-tech/infra-components) that deploys with `mesh deploy` unmodified — the proven mesh-sandbox shape, annotated.")
|