@topogram/cli 0.3.63 → 0.3.64

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.
Files changed (121) hide show
  1. package/package.json +1 -1
  2. package/src/adoption/plan.d.ts +6 -0
  3. package/src/adoption/reporting.d.ts +10 -0
  4. package/src/adoption/review-groups.d.ts +6 -0
  5. package/src/agent-brief.d.ts +3 -0
  6. package/src/agent-brief.js +495 -0
  7. package/src/agent-ops/query-builders.d.ts +26 -0
  8. package/src/archive/archive.d.ts +2 -0
  9. package/src/archive/compact.d.ts +1 -0
  10. package/src/archive/unarchive.d.ts +1 -0
  11. package/src/catalog.d.ts +10 -0
  12. package/src/catalog.js +62 -66
  13. package/src/cli/catalog-alias.d.ts +1 -0
  14. package/src/cli/command-parser.js +38 -0
  15. package/src/cli/command-parsers/core.js +102 -0
  16. package/src/cli/command-parsers/generator.js +39 -0
  17. package/src/cli/command-parsers/import.js +44 -0
  18. package/src/cli/command-parsers/legacy-workflow.js +21 -0
  19. package/src/cli/command-parsers/project.js +47 -0
  20. package/src/cli/command-parsers/sdlc.js +47 -0
  21. package/src/cli/command-parsers/shared.js +51 -0
  22. package/src/cli/command-parsers/template.js +48 -0
  23. package/src/cli/commands/agent.js +47 -0
  24. package/src/cli/commands/catalog.js +617 -0
  25. package/src/cli/commands/check.js +268 -0
  26. package/src/cli/commands/doctor.js +268 -0
  27. package/src/cli/commands/emit.js +149 -0
  28. package/src/cli/commands/generate.js +96 -0
  29. package/src/cli/commands/generator-policy.js +785 -0
  30. package/src/cli/commands/generator.js +443 -0
  31. package/src/cli/commands/import-runner.js +157 -0
  32. package/src/cli/commands/import.js +1734 -0
  33. package/src/cli/commands/inspect.js +55 -0
  34. package/src/cli/commands/new.js +94 -0
  35. package/src/cli/commands/package.js +815 -0
  36. package/src/cli/commands/query.js +1302 -0
  37. package/src/cli/commands/release-rollout.js +257 -0
  38. package/src/cli/commands/release-shared.js +528 -0
  39. package/src/cli/commands/release-status.js +429 -0
  40. package/src/cli/commands/release.js +107 -0
  41. package/src/cli/commands/sdlc.js +168 -0
  42. package/src/cli/commands/setup.js +76 -0
  43. package/src/cli/commands/source.js +291 -0
  44. package/src/cli/commands/template-runner.js +198 -0
  45. package/src/cli/commands/template.js +2145 -0
  46. package/src/cli/commands/trust.js +219 -0
  47. package/src/cli/commands/version.js +40 -0
  48. package/src/cli/commands/widget.js +168 -0
  49. package/src/cli/commands/workflow.js +63 -0
  50. package/src/cli/dispatcher.js +392 -0
  51. package/src/cli/help-dispatch.js +188 -0
  52. package/src/cli/help.js +296 -0
  53. package/src/cli/migration-guidance.js +59 -0
  54. package/src/cli/options.js +96 -0
  55. package/src/cli/output-safety.js +107 -0
  56. package/src/cli/path-normalization.js +29 -0
  57. package/src/cli.js +47 -11711
  58. package/src/example-implementation.d.ts +2 -0
  59. package/src/format.d.ts +1 -0
  60. package/src/generator/check.d.ts +1 -0
  61. package/src/generator/context/bundle.d.ts +1 -0
  62. package/src/generator/context/shared.d.ts +2 -0
  63. package/src/generator/native/parity-bundle.js +2 -1
  64. package/src/generator/surfaces/web/html-escape.js +22 -0
  65. package/src/generator/surfaces/web/react.js +10 -8
  66. package/src/generator/surfaces/web/sveltekit.js +7 -5
  67. package/src/generator/surfaces/web/vanilla.js +8 -4
  68. package/src/generator.d.ts +2 -0
  69. package/src/github-client.js +520 -0
  70. package/src/import/core/shared.js +20 -62
  71. package/src/import/extractors/api/flutter-dio.js +4 -8
  72. package/src/import/extractors/api/react-native-repository.js +4 -8
  73. package/src/import/index.d.ts +4 -0
  74. package/src/import/provenance.d.ts +4 -0
  75. package/src/new-project.js +100 -11
  76. package/src/npm-safety.js +79 -0
  77. package/src/parser.d.ts +1 -0
  78. package/src/path-helpers.d.ts +1 -0
  79. package/src/path-helpers.js +20 -0
  80. package/src/project-config.js +1 -0
  81. package/src/reconcile/docs.d.ts +8 -0
  82. package/src/reconcile/journeys.d.ts +1 -0
  83. package/src/resolver.d.ts +1 -0
  84. package/src/runtime-support.js +29 -0
  85. package/src/sdlc/adopt.d.ts +1 -0
  86. package/src/sdlc/check.d.ts +1 -0
  87. package/src/sdlc/explain.d.ts +1 -0
  88. package/src/sdlc/release.d.ts +1 -0
  89. package/src/sdlc/scaffold.d.ts +1 -0
  90. package/src/sdlc/transition.d.ts +1 -0
  91. package/src/text-helpers.d.ts +6 -0
  92. package/src/text-helpers.js +245 -0
  93. package/src/topogram-config.js +306 -0
  94. package/src/validator.d.ts +2 -0
  95. package/src/workflows/adoption/index.js +26 -0
  96. package/src/workflows/docs-generate.js +262 -0
  97. package/src/workflows/docs-scan.js +703 -0
  98. package/src/workflows/docs.js +15 -0
  99. package/src/workflows/import-app/api.js +799 -0
  100. package/src/workflows/import-app/db.js +538 -0
  101. package/src/workflows/import-app/index.js +30 -0
  102. package/src/workflows/import-app/shared.js +218 -0
  103. package/src/workflows/import-app/ui.js +443 -0
  104. package/src/workflows/import-app/workflow.js +159 -0
  105. package/src/workflows/reconcile/adoption-plan.js +742 -0
  106. package/src/workflows/reconcile/auth.js +692 -0
  107. package/src/workflows/reconcile/bundle-core.js +600 -0
  108. package/src/workflows/reconcile/bundle-shared.js +75 -0
  109. package/src/workflows/reconcile/candidate-model.js +477 -0
  110. package/src/workflows/reconcile/canonical-surface.js +264 -0
  111. package/src/workflows/reconcile/gap-report.js +333 -0
  112. package/src/workflows/reconcile/ids.js +6 -0
  113. package/src/workflows/reconcile/impacts.js +625 -0
  114. package/src/workflows/reconcile/index.js +7 -0
  115. package/src/workflows/reconcile/renderers.js +461 -0
  116. package/src/workflows/reconcile/summary.js +90 -0
  117. package/src/workflows/reconcile/workflow.js +309 -0
  118. package/src/workflows/shared.js +189 -0
  119. package/src/workflows/types.d.ts +93 -0
  120. package/src/workflows.d.ts +1 -0
  121. package/src/workflows.js +10 -7652
@@ -0,0 +1,443 @@
1
+ // @ts-check
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ import { stableStringify } from "../../format.js";
7
+ import { checkGeneratorPack } from "../../generator/check.js";
8
+ import {
9
+ GENERATOR_MANIFESTS,
10
+ getGeneratorManifest,
11
+ loadPackageGeneratorManifest,
12
+ packageGeneratorInstallCommand
13
+ } from "../../generator/registry.js";
14
+ import { GENERATOR_POLICY_FILE } from "../../generator-policy.js";
15
+
16
+ /**
17
+ * @returns {void}
18
+ */
19
+ export function printGeneratorHelp() {
20
+ console.log("Usage: topogram generator list [--json]");
21
+ console.log(" or: topogram generator show <id-or-package> [--json]");
22
+ console.log(" or: topogram generator check <path-or-package> [--json]");
23
+ console.log(" or: topogram generator policy init [path] [--json]");
24
+ console.log(" or: topogram generator policy status [path] [--json]");
25
+ console.log(" or: topogram generator policy check [path] [--json]");
26
+ console.log(" or: topogram generator policy explain [path] [--json]");
27
+ console.log(" or: topogram generator policy pin [package@version] [path] [--json]");
28
+ console.log("");
29
+ console.log("Inspects generator manifests and checks generator pack conformance.");
30
+ console.log("");
31
+ console.log("Notes:");
32
+ console.log(" - list shows bundled generators plus installed package-backed generators declared in package.json; it reads manifests only.");
33
+ console.log(" - show accepts an installed package name or a bundled fallback generator id; it does not load adapter code.");
34
+ console.log(" - check validates a local generator package path or an already installed package by loading the adapter and running smoke generation.");
35
+ console.log(" - Topogram does not install generator packages during show or check.");
36
+ console.log(` - package-backed project generators are governed by ${GENERATOR_POLICY_FILE}; bundled topogram/* generators are allowed.`);
37
+ console.log("");
38
+ console.log("Examples:");
39
+ console.log(" topogram generator list");
40
+ console.log(" topogram generator list --json");
41
+ console.log(" topogram generator show @topogram/generator-react-web");
42
+ console.log(" topogram generator show @scope/topogram-generator-web --json");
43
+ console.log(" topogram generator check ./generator-package");
44
+ console.log(" topogram generator check @scope/topogram-generator-web --json");
45
+ console.log(" topogram generator policy init");
46
+ console.log(" topogram generator policy status --json");
47
+ console.log(" topogram generator policy check --json");
48
+ console.log(" topogram generator policy pin @topogram/generator-react-web@1");
49
+ }
50
+
51
+ /**
52
+ * @param {ReturnType<typeof checkGeneratorPack>} payload
53
+ * @returns {void}
54
+ */
55
+ export function printGeneratorCheck(payload) {
56
+ console.log(payload.ok ? "Generator check passed." : "Generator check found issues.");
57
+ console.log(`Source: ${payload.sourceSpec}`);
58
+ console.log(`Type: ${payload.source}`);
59
+ if (payload.packageName) {
60
+ console.log(`Package: ${payload.packageName}`);
61
+ }
62
+ if (payload.manifestPath) {
63
+ console.log(`Manifest: ${payload.manifestPath}`);
64
+ }
65
+ if (payload.manifest) {
66
+ console.log(`Generator: ${payload.manifest.id}@${payload.manifest.version}`);
67
+ console.log(`Surface: ${payload.manifest.surface}`);
68
+ console.log(`Projection types: ${payload.manifest.projectionTypes.join(", ")}`);
69
+ console.log(`Source mode: ${payload.manifest.source}`);
70
+ }
71
+ console.log("Executes package code: yes (loads adapter and runs smoke generate)");
72
+ console.log("");
73
+ console.log("Checks:");
74
+ for (const check of payload.checks || []) {
75
+ console.log(`- ${check.ok ? "PASS" : "FAIL"} ${check.name}: ${check.message}`);
76
+ }
77
+ if (payload.smoke) {
78
+ console.log("");
79
+ console.log(`Smoke output: ${payload.smoke.files} file(s), ${payload.smoke.artifacts} artifact(s), ${payload.smoke.diagnostics} diagnostic(s)`);
80
+ }
81
+ if ((payload.errors || []).length > 0) {
82
+ console.log("");
83
+ console.log("Errors:");
84
+ for (const error of payload.errors) {
85
+ console.log(`- ${error}`);
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * @param {import("../../generator/registry.js").GeneratorManifest} manifest
92
+ * @param {{ source?: string|null, manifestPath?: string|null, packageRoot?: string|null, installed?: boolean, errors?: string[] }} [metadata]
93
+ * @returns {Record<string, any>}
94
+ */
95
+ function generatorManifestSummary(manifest, metadata = {}) {
96
+ const installCommand = manifest.package ? packageGeneratorInstallCommand(manifest.package) : null;
97
+ return {
98
+ id: manifest.id,
99
+ version: manifest.version,
100
+ surface: manifest.surface,
101
+ projectionTypes: manifest.projectionTypes || [],
102
+ inputs: manifest.inputs || [],
103
+ outputs: manifest.outputs || [],
104
+ stack: manifest.stack || {},
105
+ capabilities: manifest.capabilities || {},
106
+ source: manifest.source,
107
+ loadsAdapter: false,
108
+ executesPackageCode: false,
109
+ ...(manifest.profile ? { profile: manifest.profile } : {}),
110
+ ...(manifest.package ? { package: manifest.package } : {}),
111
+ ...(installCommand ? { installCommand } : {}),
112
+ ...(manifest.planned ? { planned: true } : {}),
113
+ installed: metadata.installed !== false,
114
+ manifestPath: metadata.manifestPath || null,
115
+ packageRoot: metadata.packageRoot || null,
116
+ errors: metadata.errors || []
117
+ };
118
+ }
119
+
120
+ /**
121
+ * @param {string} surface
122
+ * @param {string[]} [projectionTypes]
123
+ * @returns {string}
124
+ */
125
+ function exampleProjectionId(surface, projectionTypes = []) {
126
+ const projectionType = projectionTypes[0] || "";
127
+ if (surface === "api") return "proj_api";
128
+ if (surface === "database") return projectionType === "db_contract" ? "proj_db" : "proj_db";
129
+ if (surface === "native") return projectionType === "android_surface" ? "proj_android_surface" : "proj_ios_surface";
130
+ return "proj_web_surface";
131
+ }
132
+
133
+ /**
134
+ * @param {import("../../generator/registry.js").GeneratorManifest} manifest
135
+ * @returns {Record<string, any>}
136
+ */
137
+ function exampleTopologyBinding(manifest) {
138
+ const runtimeId = manifest.surface === "api"
139
+ ? "app_api"
140
+ : manifest.surface === "database"
141
+ ? "app_db"
142
+ : manifest.surface === "native"
143
+ ? "app_ios"
144
+ : "app_web";
145
+ return {
146
+ id: runtimeId,
147
+ kind: manifest.runtimeKinds?.[0] || manifest.surface,
148
+ projection: exampleProjectionId(manifest.surface, manifest.projectionTypes),
149
+ generator: {
150
+ id: manifest.id,
151
+ version: manifest.version,
152
+ ...(manifest.package ? { package: manifest.package } : {})
153
+ }
154
+ };
155
+ }
156
+
157
+ /**
158
+ * @param {string} cwd
159
+ * @returns {string[]}
160
+ */
161
+ function declaredGeneratorPackages(cwd) {
162
+ const packagePath = path.join(cwd, "package.json");
163
+ if (!fs.existsSync(packagePath)) {
164
+ return [];
165
+ }
166
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
167
+ const dependencyBuckets = [
168
+ packageJson.dependencies,
169
+ packageJson.devDependencies,
170
+ packageJson.optionalDependencies,
171
+ packageJson.peerDependencies
172
+ ];
173
+ const packages = new Set();
174
+ for (const dependencies of dependencyBuckets) {
175
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) {
176
+ continue;
177
+ }
178
+ for (const name of Object.keys(dependencies)) {
179
+ if (name.includes("topogram-generator") || name.startsWith("@topogram/generator-")) {
180
+ packages.add(name);
181
+ }
182
+ }
183
+ }
184
+ return [...packages].sort();
185
+ }
186
+
187
+ /**
188
+ * @param {string} cwd
189
+ * @returns {{ ok: boolean, cwd: string, generators: Record<string, any>[], summary: Record<string, number> }}
190
+ */
191
+ export function buildGeneratorListPayload(cwd) {
192
+ const generators = GENERATOR_MANIFESTS
193
+ .map((manifest) => generatorManifestSummary(manifest))
194
+ .sort((left, right) => left.id.localeCompare(right.id));
195
+ for (const packageName of declaredGeneratorPackages(cwd)) {
196
+ const loaded = loadPackageGeneratorManifest(packageName, cwd);
197
+ if (loaded.manifest) {
198
+ generators.push(generatorManifestSummary(loaded.manifest, {
199
+ installed: true,
200
+ manifestPath: loaded.manifestPath,
201
+ packageRoot: loaded.packageRoot,
202
+ errors: loaded.errors
203
+ }));
204
+ } else {
205
+ const installCommand = packageGeneratorInstallCommand(packageName);
206
+ generators.push({
207
+ id: null,
208
+ version: null,
209
+ surface: null,
210
+ projectionTypes: [],
211
+ inputs: [],
212
+ outputs: [],
213
+ stack: {},
214
+ capabilities: {},
215
+ source: "package",
216
+ package: packageName,
217
+ ...(installCommand ? { installCommand } : {}),
218
+ installed: false,
219
+ manifestPath: loaded.manifestPath,
220
+ packageRoot: loaded.packageRoot,
221
+ errors: loaded.errors
222
+ });
223
+ }
224
+ }
225
+ generators.sort((left, right) => String(left.id || left.package || "").localeCompare(String(right.id || right.package || "")));
226
+ return {
227
+ ok: generators.every((generator) => generator.errors.length === 0),
228
+ cwd,
229
+ generators,
230
+ summary: {
231
+ total: generators.length,
232
+ bundled: generators.filter((generator) => generator.source === "bundled").length,
233
+ package: generators.filter((generator) => generator.source === "package").length,
234
+ installed: generators.filter((generator) => generator.installed).length,
235
+ planned: generators.filter((generator) => generator.planned).length
236
+ }
237
+ };
238
+ }
239
+
240
+ /**
241
+ * @param {string} spec
242
+ * @returns {string}
243
+ */
244
+ function packageNameFromPackageSpec(spec) {
245
+ if (spec.startsWith("@")) {
246
+ const segments = spec.split("/");
247
+ if (segments.length < 2) {
248
+ throw new Error(`Invalid scoped package spec '${spec}'.`);
249
+ }
250
+ const scope = segments[0];
251
+ const nameAndVersion = segments.slice(1).join("/");
252
+ const versionIndex = nameAndVersion.indexOf("@");
253
+ return `${scope}/${versionIndex >= 0 ? nameAndVersion.slice(0, versionIndex) : nameAndVersion}`;
254
+ }
255
+ const versionIndex = spec.indexOf("@");
256
+ return versionIndex >= 0 ? spec.slice(0, versionIndex) : spec;
257
+ }
258
+
259
+ /**
260
+ * @param {string} spec
261
+ * @param {string} cwd
262
+ * @returns {{ ok: boolean, sourceSpec: string, generator: Record<string, any>|null, exampleTopologyBinding: Record<string, any>|null, errors: string[] }}
263
+ */
264
+ export function buildGeneratorShowPayload(spec, cwd) {
265
+ const errors = [];
266
+ if (!spec || spec.startsWith("-")) {
267
+ return {
268
+ ok: false,
269
+ sourceSpec: spec || "",
270
+ generator: null,
271
+ exampleTopologyBinding: null,
272
+ errors: ["Usage: topogram generator show <id-or-package>"]
273
+ };
274
+ }
275
+ const bundled = getGeneratorManifest(spec);
276
+ if (bundled) {
277
+ return {
278
+ ok: true,
279
+ sourceSpec: spec,
280
+ generator: generatorManifestSummary(bundled),
281
+ exampleTopologyBinding: exampleTopologyBinding(bundled),
282
+ errors: []
283
+ };
284
+ }
285
+ let packageName = spec;
286
+ try {
287
+ packageName = packageNameFromPackageSpec(spec);
288
+ } catch (error) {
289
+ errors.push(error instanceof Error ? error.message : String(error));
290
+ }
291
+ if (errors.length === 0) {
292
+ const loaded = loadPackageGeneratorManifest(packageName, cwd);
293
+ if (loaded.manifest) {
294
+ return {
295
+ ok: true,
296
+ sourceSpec: spec,
297
+ generator: generatorManifestSummary(loaded.manifest, {
298
+ installed: true,
299
+ manifestPath: loaded.manifestPath,
300
+ packageRoot: loaded.packageRoot,
301
+ errors: loaded.errors
302
+ }),
303
+ exampleTopologyBinding: exampleTopologyBinding(loaded.manifest),
304
+ errors: []
305
+ };
306
+ }
307
+ errors.push(...loaded.errors);
308
+ }
309
+ return {
310
+ ok: false,
311
+ sourceSpec: spec,
312
+ generator: null,
313
+ exampleTopologyBinding: null,
314
+ errors
315
+ };
316
+ }
317
+
318
+ /**
319
+ * @param {ReturnType<typeof buildGeneratorListPayload>} payload
320
+ * @returns {void}
321
+ */
322
+ export function printGeneratorList(payload) {
323
+ console.log("Topogram generators");
324
+ console.log(`Bundled: ${payload.summary.bundled}; package-backed: ${payload.summary.package}; installed: ${payload.summary.installed}; planned: ${payload.summary.planned}`);
325
+ console.log("");
326
+ for (const generator of payload.generators) {
327
+ const id = generator.id || generator.package || "unknown";
328
+ const status = generator.errors.length > 0
329
+ ? "invalid"
330
+ : generator.planned
331
+ ? "planned"
332
+ : generator.source === "package"
333
+ ? (generator.installed ? "package installed" : "package missing")
334
+ : "bundled";
335
+ const platforms = generator.projectionTypes.join(", ") || "none";
336
+ const stack = Object.values(generator.stack || {}).join(" + ") || "not declared";
337
+ console.log(`- ${id}${generator.version ? `@${generator.version}` : ""} (${generator.surface || "unknown"}, ${status})`);
338
+ console.log(` Source: ${generator.source}`);
339
+ console.log(" Adapter loaded: no");
340
+ console.log(" Executes package code: no");
341
+ if (generator.source === "package") {
342
+ console.log(` Installed: ${generator.installed ? "yes" : "no"}`);
343
+ }
344
+ console.log(` Platforms: ${platforms}`);
345
+ console.log(` Stack: ${stack}`);
346
+ if (generator.package) {
347
+ console.log(` Package: ${generator.package}`);
348
+ }
349
+ if (generator.installCommand) {
350
+ console.log(` Install: ${generator.installCommand}`);
351
+ }
352
+ for (const error of generator.errors || []) {
353
+ console.log(` Error: ${error}`);
354
+ }
355
+ }
356
+ }
357
+
358
+ /**
359
+ * @param {ReturnType<typeof buildGeneratorShowPayload>} payload
360
+ * @returns {void}
361
+ */
362
+ export function printGeneratorShow(payload) {
363
+ if (!payload.ok || !payload.generator) {
364
+ console.log("Generator not found.");
365
+ for (const error of payload.errors || []) {
366
+ console.log(`- ${error}`);
367
+ }
368
+ return;
369
+ }
370
+ const generator = payload.generator;
371
+ console.log(`Generator: ${generator.id}@${generator.version}`);
372
+ console.log(`Surface: ${generator.surface}`);
373
+ console.log(`Source: ${generator.source}${generator.planned ? " (planned)" : ""}`);
374
+ console.log("Adapter loaded: no");
375
+ console.log("Executes package code: no");
376
+ if (generator.source === "package") {
377
+ console.log(`Installed: ${generator.installed ? "yes" : "no"}`);
378
+ }
379
+ if (generator.package) {
380
+ console.log(`Package: ${generator.package}`);
381
+ }
382
+ if (generator.installCommand) {
383
+ console.log(`Install: ${generator.installCommand}`);
384
+ }
385
+ if (generator.manifestPath) {
386
+ console.log(`Manifest: ${generator.manifestPath}`);
387
+ }
388
+ console.log(`Projection types: ${generator.projectionTypes.join(", ") || "none"}`);
389
+ console.log(`Inputs: ${generator.inputs.join(", ") || "none"}`);
390
+ console.log(`Outputs: ${generator.outputs.join(", ") || "none"}`);
391
+ console.log(`Stack: ${Object.entries(generator.stack || {}).map(([key, value]) => `${key}=${value}`).join(", ") || "not declared"}`);
392
+ console.log(`Capabilities: ${Object.entries(generator.capabilities || {}).map(([key, value]) => `${key}=${value}`).join(", ") || "not declared"}`);
393
+ console.log("");
394
+ console.log("Example topology binding:");
395
+ console.log(stableStringify(payload.exampleTopologyBinding));
396
+ }
397
+
398
+
399
+ /**
400
+ * @param {{
401
+ * commandArgs: Record<string, any>,
402
+ * inputPath: string|null|undefined,
403
+ * json: boolean,
404
+ * cwd: string
405
+ * }} context
406
+ * @returns {number}
407
+ */
408
+ export function runGeneratorCommand(context) {
409
+ const { commandArgs, inputPath, json, cwd } = context;
410
+ if (commandArgs.generatorCommand === "check") {
411
+ const payload = checkGeneratorPack(inputPath || "", { cwd });
412
+ if (json) {
413
+ console.log(stableStringify(payload));
414
+ } else {
415
+ printGeneratorCheck(payload);
416
+ }
417
+ return payload.ok ? 0 : 1;
418
+ }
419
+
420
+ if (commandArgs.generatorCommand === "list") {
421
+ const payload = buildGeneratorListPayload(cwd);
422
+ if (json) {
423
+ console.log(stableStringify(payload));
424
+ } else {
425
+ printGeneratorList(payload);
426
+ }
427
+ return payload.ok ? 0 : 1;
428
+ }
429
+
430
+ if (commandArgs.generatorCommand === "show") {
431
+ const payload = buildGeneratorShowPayload(inputPath || "", cwd);
432
+ if (json) {
433
+ console.log(stableStringify(payload));
434
+ } else {
435
+ printGeneratorShow(payload);
436
+ }
437
+ return payload.ok ? 0 : 1;
438
+ }
439
+
440
+ throw new Error(`Unknown generator command '${commandArgs.generatorCommand}'`);
441
+ }
442
+
443
+ export { checkGeneratorPack };
@@ -0,0 +1,157 @@
1
+ // @ts-check
2
+
3
+ import { stableStringify } from "../../format.js";
4
+ import {
5
+ buildBrownfieldImportAdoptListPayload,
6
+ buildBrownfieldImportAdoptPayload,
7
+ buildBrownfieldImportCheckPayload,
8
+ buildBrownfieldImportDiffPayload,
9
+ buildBrownfieldImportHistoryPayload,
10
+ buildBrownfieldImportPlanPayload,
11
+ buildBrownfieldImportRefreshPayload,
12
+ buildBrownfieldImportStatusPayload,
13
+ buildBrownfieldImportWorkspacePayload,
14
+ printBrownfieldImportAdopt,
15
+ printBrownfieldImportAdoptList,
16
+ printBrownfieldImportCheck,
17
+ printBrownfieldImportDiff,
18
+ printBrownfieldImportHistory,
19
+ printBrownfieldImportPlan,
20
+ printBrownfieldImportRefresh,
21
+ printBrownfieldImportStatus,
22
+ printBrownfieldImportWorkspace,
23
+ printImportHelp
24
+ } from "./import.js";
25
+
26
+ /**
27
+ * @param {{ commandArgs: Record<string, any>, inputPath: string|null|undefined, outPath?: string|null, fromValue?: string|null, reasonValue?: string|null, refreshAdopted?: boolean, dryRun?: boolean, write?: boolean, force?: boolean, json?: boolean }} context
28
+ * @returns {number}
29
+ */
30
+ export function runImportCommand(context) {
31
+ const {
32
+ commandArgs,
33
+ inputPath,
34
+ outPath = null,
35
+ fromValue = null,
36
+ reasonValue = null,
37
+ refreshAdopted = false,
38
+ dryRun = false,
39
+ write = false,
40
+ force = false,
41
+ json = false
42
+ } = context;
43
+ const command = commandArgs.importCommand;
44
+
45
+ if (command === "workspace") {
46
+ if (!outPath) {
47
+ console.error("Missing required --out <target>.");
48
+ printImportHelp();
49
+ return 1;
50
+ }
51
+ const payload = buildBrownfieldImportWorkspacePayload(inputPath || "", outPath, { from: fromValue });
52
+ if (json) {
53
+ console.log(stableStringify(payload));
54
+ } else {
55
+ printBrownfieldImportWorkspace(payload);
56
+ }
57
+ return 0;
58
+ }
59
+
60
+ if (command === "diff") {
61
+ const payload = buildBrownfieldImportDiffPayload(inputPath || ".", { sourcePath: fromValue });
62
+ if (json) {
63
+ console.log(stableStringify(payload));
64
+ } else {
65
+ printBrownfieldImportDiff(payload);
66
+ }
67
+ return 0;
68
+ }
69
+
70
+ if (command === "refresh") {
71
+ const payload = buildBrownfieldImportRefreshPayload(inputPath || ".", { sourcePath: fromValue, dryRun });
72
+ if (json) {
73
+ console.log(stableStringify(payload));
74
+ } else {
75
+ printBrownfieldImportRefresh(payload);
76
+ }
77
+ return payload.ok ? 0 : 1;
78
+ }
79
+
80
+ if (command === "check") {
81
+ const payload = buildBrownfieldImportCheckPayload(inputPath || ".");
82
+ if (json) {
83
+ console.log(stableStringify(payload));
84
+ } else {
85
+ printBrownfieldImportCheck(payload);
86
+ }
87
+ return payload.ok ? 0 : 1;
88
+ }
89
+
90
+ if (command === "plan") {
91
+ const payload = buildBrownfieldImportPlanPayload(inputPath || ".");
92
+ if (json) {
93
+ console.log(stableStringify(payload));
94
+ } else {
95
+ printBrownfieldImportPlan(payload);
96
+ }
97
+ return 0;
98
+ }
99
+
100
+ if (command === "adopt-list") {
101
+ const payload = buildBrownfieldImportAdoptListPayload(inputPath || ".");
102
+ if (json) {
103
+ console.log(stableStringify(payload));
104
+ } else {
105
+ printBrownfieldImportAdoptList(payload);
106
+ }
107
+ return 0;
108
+ }
109
+
110
+ if (command === "adopt") {
111
+ if (!commandArgs.importAdoptSelector || commandArgs.importAdoptSelector.startsWith("-")) {
112
+ console.error("Missing required <selector>.");
113
+ printImportHelp();
114
+ return 1;
115
+ }
116
+ if (write && dryRun) {
117
+ console.error("Use either --dry-run or --write, not both.");
118
+ printImportHelp();
119
+ return 1;
120
+ }
121
+ const payload = buildBrownfieldImportAdoptPayload(commandArgs.importAdoptSelector, inputPath || ".", {
122
+ dryRun,
123
+ write,
124
+ force,
125
+ reason: reasonValue,
126
+ refreshAdopted
127
+ });
128
+ if (json) {
129
+ console.log(stableStringify(payload));
130
+ } else {
131
+ printBrownfieldImportAdopt(payload);
132
+ }
133
+ return payload.ok ? 0 : 1;
134
+ }
135
+
136
+ if (command === "status") {
137
+ const payload = buildBrownfieldImportStatusPayload(inputPath || ".");
138
+ if (json) {
139
+ console.log(stableStringify(payload));
140
+ } else {
141
+ printBrownfieldImportStatus(payload);
142
+ }
143
+ return payload.ok ? 0 : 1;
144
+ }
145
+
146
+ if (command === "history") {
147
+ const payload = buildBrownfieldImportHistoryPayload(inputPath || ".", { verify: commandArgs.verify });
148
+ if (json) {
149
+ console.log(stableStringify(payload));
150
+ } else {
151
+ printBrownfieldImportHistory(payload);
152
+ }
153
+ return payload.ok ? 0 : 1;
154
+ }
155
+
156
+ throw new Error(`Unknown import command '${command}'`);
157
+ }