@topogram/cli 0.3.62 → 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.
- package/package.json +1 -1
- package/src/adoption/plan.d.ts +6 -0
- package/src/adoption/reporting.d.ts +10 -0
- package/src/adoption/review-groups.d.ts +6 -0
- package/src/agent-brief.d.ts +3 -0
- package/src/agent-brief.js +495 -0
- package/src/agent-ops/query-builders.d.ts +26 -0
- package/src/archive/archive.d.ts +2 -0
- package/src/archive/compact.d.ts +1 -0
- package/src/archive/unarchive.d.ts +1 -0
- package/src/catalog.d.ts +10 -0
- package/src/catalog.js +62 -66
- package/src/cli/catalog-alias.d.ts +1 -0
- package/src/cli/command-parser.js +38 -0
- package/src/cli/command-parsers/core.js +102 -0
- package/src/cli/command-parsers/generator.js +39 -0
- package/src/cli/command-parsers/import.js +44 -0
- package/src/cli/command-parsers/legacy-workflow.js +21 -0
- package/src/cli/command-parsers/project.js +47 -0
- package/src/cli/command-parsers/sdlc.js +47 -0
- package/src/cli/command-parsers/shared.js +51 -0
- package/src/cli/command-parsers/template.js +48 -0
- package/src/cli/commands/agent.js +47 -0
- package/src/cli/commands/catalog.js +617 -0
- package/src/cli/commands/check.js +268 -0
- package/src/cli/commands/doctor.js +268 -0
- package/src/cli/commands/emit.js +149 -0
- package/src/cli/commands/generate.js +96 -0
- package/src/cli/commands/generator-policy.js +785 -0
- package/src/cli/commands/generator.js +443 -0
- package/src/cli/commands/import-runner.js +157 -0
- package/src/cli/commands/import.js +1734 -0
- package/src/cli/commands/inspect.js +55 -0
- package/src/cli/commands/new.js +94 -0
- package/src/cli/commands/package.js +815 -0
- package/src/cli/commands/query.js +1302 -0
- package/src/cli/commands/release-rollout.js +257 -0
- package/src/cli/commands/release-shared.js +528 -0
- package/src/cli/commands/release-status.js +429 -0
- package/src/cli/commands/release.js +107 -0
- package/src/cli/commands/sdlc.js +168 -0
- package/src/cli/commands/setup.js +76 -0
- package/src/cli/commands/source.js +291 -0
- package/src/cli/commands/template-runner.js +198 -0
- package/src/cli/commands/template.js +2145 -0
- package/src/cli/commands/trust.js +219 -0
- package/src/cli/commands/version.js +40 -0
- package/src/cli/commands/widget.js +168 -0
- package/src/cli/commands/workflow.js +63 -0
- package/src/cli/dispatcher.js +392 -0
- package/src/cli/help-dispatch.js +188 -0
- package/src/cli/help.js +296 -0
- package/src/cli/migration-guidance.js +59 -0
- package/src/cli/options.js +96 -0
- package/src/cli/output-safety.js +107 -0
- package/src/cli/path-normalization.js +29 -0
- package/src/cli.js +47 -11711
- package/src/example-implementation.d.ts +2 -0
- package/src/format.d.ts +1 -0
- package/src/generator/check.d.ts +1 -0
- package/src/generator/context/bundle.d.ts +1 -0
- package/src/generator/context/shared.d.ts +2 -0
- package/src/generator/native/parity-bundle.js +2 -1
- package/src/generator/surfaces/web/html-escape.js +22 -0
- package/src/generator/surfaces/web/react.js +10 -8
- package/src/generator/surfaces/web/sveltekit.js +7 -5
- package/src/generator/surfaces/web/vanilla.js +8 -4
- package/src/generator.d.ts +2 -0
- package/src/github-client.js +520 -0
- package/src/import/core/shared.js +20 -62
- package/src/import/extractors/api/flutter-dio.js +4 -8
- package/src/import/extractors/api/react-native-repository.js +4 -8
- package/src/import/index.d.ts +4 -0
- package/src/import/provenance.d.ts +4 -0
- package/src/new-project.js +100 -11
- package/src/npm-safety.js +79 -0
- package/src/parser.d.ts +1 -0
- package/src/path-helpers.d.ts +1 -0
- package/src/path-helpers.js +20 -0
- package/src/project-config.js +1 -0
- package/src/reconcile/docs.d.ts +8 -0
- package/src/reconcile/journeys.d.ts +1 -0
- package/src/resolver.d.ts +1 -0
- package/src/runtime-support.js +29 -0
- package/src/sdlc/adopt.d.ts +1 -0
- package/src/sdlc/check.d.ts +1 -0
- package/src/sdlc/explain.d.ts +1 -0
- package/src/sdlc/release.d.ts +1 -0
- package/src/sdlc/scaffold.d.ts +1 -0
- package/src/sdlc/transition.d.ts +1 -0
- package/src/text-helpers.d.ts +6 -0
- package/src/text-helpers.js +245 -0
- package/src/topogram-config.js +306 -0
- package/src/validator.d.ts +2 -0
- package/src/workflows/adoption/index.js +26 -0
- package/src/workflows/docs-generate.js +262 -0
- package/src/workflows/docs-scan.js +703 -0
- package/src/workflows/docs.js +15 -0
- package/src/workflows/import-app/api.js +799 -0
- package/src/workflows/import-app/db.js +538 -0
- package/src/workflows/import-app/index.js +30 -0
- package/src/workflows/import-app/shared.js +218 -0
- package/src/workflows/import-app/ui.js +443 -0
- package/src/workflows/import-app/workflow.js +159 -0
- package/src/workflows/reconcile/adoption-plan.js +742 -0
- package/src/workflows/reconcile/auth.js +692 -0
- package/src/workflows/reconcile/bundle-core.js +600 -0
- package/src/workflows/reconcile/bundle-shared.js +75 -0
- package/src/workflows/reconcile/candidate-model.js +477 -0
- package/src/workflows/reconcile/canonical-surface.js +264 -0
- package/src/workflows/reconcile/gap-report.js +333 -0
- package/src/workflows/reconcile/ids.js +6 -0
- package/src/workflows/reconcile/impacts.js +625 -0
- package/src/workflows/reconcile/index.js +7 -0
- package/src/workflows/reconcile/renderers.js +461 -0
- package/src/workflows/reconcile/summary.js +90 -0
- package/src/workflows/reconcile/workflow.js +309 -0
- package/src/workflows/shared.js +189 -0
- package/src/workflows/types.d.ts +93 -0
- package/src/workflows.d.ts +1 -0
- 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
|
+
}
|