@topogram/cli 0.3.78 → 0.3.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/package.json +2 -2
- package/src/agent-brief.js +29 -23
- package/src/agent-ops/query-builders/change-risk/{import-plan.js → extract-plan.js} +1 -1
- package/src/agent-ops/query-builders/change-risk/review-packets.js +5 -5
- package/src/agent-ops/query-builders/change-risk.js +1 -1
- package/src/agent-ops/query-builders/common.js +2 -2
- package/src/agent-ops/query-builders/multi-agent.js +1 -1
- package/src/agent-ops/query-builders/workflow-context-shared.js +4 -4
- package/src/catalog/provenance.js +1 -1
- package/src/cli/catalog-alias.d.ts +2 -0
- package/src/cli/catalog-alias.js +2 -2
- package/src/cli/command-parser.js +2 -0
- package/src/cli/command-parsers/core.js +9 -5
- package/src/cli/command-parsers/extractor.js +40 -0
- package/src/cli/command-parsers/import.js +11 -17
- package/src/cli/command-parsers/project.js +0 -3
- package/src/cli/commands/catalog/copy.js +3 -3
- package/src/cli/commands/catalog/help.js +1 -2
- package/src/cli/commands/catalog/list.js +7 -4
- package/src/cli/commands/catalog/show.js +4 -4
- package/src/cli/commands/copy.js +356 -0
- package/src/cli/commands/doctor.js +1 -1
- package/src/cli/commands/extractor.js +451 -0
- package/src/cli/commands/import/adopt.js +9 -9
- package/src/cli/commands/import/check.js +15 -15
- package/src/cli/commands/import/diff.js +6 -6
- package/src/cli/commands/import/help.js +45 -34
- package/src/cli/commands/import/paths.js +3 -3
- package/src/cli/commands/import/plan.js +8 -8
- package/src/cli/commands/import/refresh.js +25 -24
- package/src/cli/commands/import/status-history.js +4 -4
- package/src/cli/commands/import/workspace.js +24 -18
- package/src/cli/commands/import-runner.js +10 -7
- package/src/cli/commands/import.js +4 -1
- package/src/cli/commands/init.js +67 -0
- package/src/cli/commands/query/{import-adopt.js → extract-adopt.js} +2 -2
- package/src/cli/commands/query/runner/change.js +2 -2
- package/src/cli/commands/query/runner/{import-adopt.js → extract-adopt.js} +9 -9
- package/src/cli/commands/query/runner/index.js +1 -1
- package/src/cli/commands/query/runner/workflow.js +7 -7
- package/src/cli/commands/query/workspace.js +4 -4
- package/src/cli/commands/release-status.js +2 -2
- package/src/cli/commands/source.js +2 -2
- package/src/cli/commands/template/check.js +2 -2
- package/src/cli/commands/template/list-show.js +4 -4
- package/src/cli/dispatcher.js +32 -3
- package/src/cli/help-dispatch.js +33 -8
- package/src/cli/help.js +79 -52
- package/src/cli/migration-guidance.js +9 -0
- package/src/cli/options.js +17 -0
- package/src/extractor/check.js +155 -0
- package/src/extractor/packages.js +295 -0
- package/src/extractor/registry.js +196 -0
- package/src/extractor-policy.js +249 -0
- package/src/generator/check.js +24 -87
- package/src/generator/context/bundle.js +14 -7
- package/src/generator/context/diff.js +8 -1
- package/src/generator/context/digest.js +10 -1
- package/src/generator/context/shared/domain-sdlc.js +5 -1
- package/src/generator/context/shared/relationships.js +20 -5
- package/src/generator/context/shared/summaries.js +26 -0
- package/src/generator/context/shared.d.ts +1 -0
- package/src/generator/context/shared.js +1 -0
- package/src/generator/context/slice/core.js +9 -5
- package/src/generator/context/slice/sdlc.js +31 -2
- package/src/generator/context/task-mode.js +3 -3
- package/src/generator/registry/index.js +16 -75
- package/src/generator-policy.js +9 -57
- package/src/import/core/registry.d.ts +3 -0
- package/src/import/core/registry.js +82 -8
- package/src/import/core/runner/reports.js +4 -4
- package/src/import/core/runner/run.js +2 -0
- package/src/import/core/runner/tracks.js +66 -4
- package/src/import/provenance.js +18 -17
- package/src/init-project.js +215 -0
- package/src/new-project/constants.js +1 -1
- package/src/new-project/create.js +2 -2
- package/src/new-project/project-files.js +7 -7
- package/src/package-adapters/adapter.js +64 -0
- package/src/package-adapters/file-map.js +30 -0
- package/src/package-adapters/index.js +27 -0
- package/src/package-adapters/manifest.js +108 -0
- package/src/package-adapters/policy.js +81 -0
- package/src/package-adapters/spec.js +51 -0
- package/src/reconcile/journeys.js +8 -3
- package/src/record-blocks.js +125 -0
- package/src/resolver/index.js +3 -0
- package/src/resolver/journeys.js +74 -0
- package/src/resolver/normalize.js +25 -0
- package/src/sdlc/adopt.js +1 -1
- package/src/validator/common.js +34 -1
- package/src/validator/index.js +4 -0
- package/src/validator/kinds.d.ts +2 -0
- package/src/validator/kinds.js +34 -1
- package/src/validator/per-kind/journey.js +233 -0
- package/src/workflows/docs-generate.js +4 -1
- package/src/workflows/reconcile/bundle-core/index.js +4 -2
- package/src/workflows/reconcile/canonical-surface.js +4 -1
- package/src/cli/commands/new.js +0 -94
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
catalogEntryPackageSpec,
|
|
8
|
+
copyCatalogTopogramEntry,
|
|
9
|
+
findCatalogEntry,
|
|
10
|
+
loadCatalog,
|
|
11
|
+
TOPOGRAM_SOURCE_FILE
|
|
12
|
+
} from "../../catalog.js";
|
|
13
|
+
import { GENERATOR_POLICY_FILE } from "../../generator-policy.js";
|
|
14
|
+
import { createNewProject } from "../../new-project.js";
|
|
15
|
+
import { copyPath, ensureEmptyDirectory } from "../../catalog/files.js";
|
|
16
|
+
import { writeTopogramSourceRecord } from "../../catalog/provenance.js";
|
|
17
|
+
import { DEFAULT_TOPO_FOLDER_NAME, DEFAULT_WORKSPACE_PATH, resolvePackageWorkspace } from "../../workspace-paths.js";
|
|
18
|
+
import { formatCatalogTemplateAliasError, suggestCatalogTemplateIds } from "../catalog-alias.js";
|
|
19
|
+
import {
|
|
20
|
+
buildCatalogListPayload,
|
|
21
|
+
printCatalogList
|
|
22
|
+
} from "./catalog/list.js";
|
|
23
|
+
import { shellCommandArg } from "./catalog/shared.js";
|
|
24
|
+
import { stableStringify } from "../../format.js";
|
|
25
|
+
|
|
26
|
+
const ENGINE_ROOT = path.resolve(decodeURIComponent(new URL("../../../", import.meta.url).pathname));
|
|
27
|
+
const TEMPLATES_ROOT = path.join(ENGINE_ROOT, "templates");
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} source
|
|
31
|
+
* @returns {boolean}
|
|
32
|
+
*/
|
|
33
|
+
function isCatalogIdCandidate(source) {
|
|
34
|
+
return Boolean(source) &&
|
|
35
|
+
!source.startsWith("@") &&
|
|
36
|
+
!source.startsWith("./") &&
|
|
37
|
+
!source.startsWith("../") &&
|
|
38
|
+
!path.isAbsolute(source) &&
|
|
39
|
+
!source.includes("/") &&
|
|
40
|
+
!source.endsWith(".tgz");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {ReturnType<typeof createNewProject>} result
|
|
45
|
+
* @param {string} cwd
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
function displayProjectRootForCopy(result, cwd) {
|
|
49
|
+
const relativeProjectRoot = path.relative(cwd, result.projectRoot);
|
|
50
|
+
return !relativeProjectRoot || relativeProjectRoot.startsWith("..")
|
|
51
|
+
? result.projectRoot
|
|
52
|
+
: relativeProjectRoot;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {string} targetPath
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
59
|
+
function assertProjectTargetOutsideEngine(targetPath) {
|
|
60
|
+
const projectRoot = path.resolve(targetPath);
|
|
61
|
+
const relativeToEngine = path.relative(ENGINE_ROOT, projectRoot);
|
|
62
|
+
if (relativeToEngine === "" || (!relativeToEngine.startsWith("..") && !path.isAbsolute(relativeToEngine))) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Refusing to copy a project inside the engine directory. Use a path outside engine, for example '../${path.basename(projectRoot)}'.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {string} source
|
|
71
|
+
* @param {string} targetPath
|
|
72
|
+
* @param {{ catalogSource?: string|null, version?: string|null }} options
|
|
73
|
+
* @returns {{ ok: boolean, action: "copy_topogram", source: string, id: string, kind: "topogram", packageSpec: string, targetPath: string, provenancePath: string, files: string[], diagnostics: any[], errors: string[] }|null}
|
|
74
|
+
*/
|
|
75
|
+
function tryCopyCatalogTopogram(source, targetPath, options) {
|
|
76
|
+
if (!isCatalogIdCandidate(source)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const loaded = loadCatalog(options.catalogSource || null);
|
|
80
|
+
const entry = findCatalogEntry(loaded.catalog, source, "topogram");
|
|
81
|
+
if (!entry) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const copied = copyCatalogTopogramEntry(entry, targetPath, {
|
|
85
|
+
catalogSource: loaded.source,
|
|
86
|
+
version: options.version || null
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
action: "copy_topogram",
|
|
90
|
+
source: loaded.source,
|
|
91
|
+
...copied,
|
|
92
|
+
diagnostics: [],
|
|
93
|
+
errors: []
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} source
|
|
99
|
+
* @param {string} targetPath
|
|
100
|
+
* @param {{ catalogSource?: string|null, version?: string|null }} options
|
|
101
|
+
* @returns {{ templateName: string, provenance: any|null }}
|
|
102
|
+
*/
|
|
103
|
+
function resolveCopyTemplateSource(source, targetPath, options) {
|
|
104
|
+
void targetPath;
|
|
105
|
+
if (!isCatalogIdCandidate(source)) {
|
|
106
|
+
return { templateName: source, provenance: null };
|
|
107
|
+
}
|
|
108
|
+
const loaded = loadCatalog(options.catalogSource || null);
|
|
109
|
+
const entry = findCatalogEntry(loaded.catalog, source, "template");
|
|
110
|
+
if (!entry) {
|
|
111
|
+
throw new Error(formatCatalogTemplateAliasError(source, loaded.source, null, {
|
|
112
|
+
suggestions: suggestCatalogTemplateIds(loaded.catalog, source)
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
const packageSpec = catalogEntryPackageSpec(entry, options.version || null);
|
|
116
|
+
return {
|
|
117
|
+
templateName: packageSpec,
|
|
118
|
+
provenance: {
|
|
119
|
+
id: entry.id,
|
|
120
|
+
source: loaded.source,
|
|
121
|
+
package: entry.package,
|
|
122
|
+
version: options.version || entry.defaultVersion,
|
|
123
|
+
packageSpec,
|
|
124
|
+
includesExecutableImplementation: Boolean(entry.trust?.includesExecutableImplementation)
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {string} sourcePath
|
|
131
|
+
* @param {string} targetPath
|
|
132
|
+
* @returns {{ ok: boolean, action: "copy_topogram", source: string, id: string, kind: "topogram", packageSpec: string, targetPath: string, provenancePath: string, files: string[], diagnostics: any[], errors: string[] }}
|
|
133
|
+
*/
|
|
134
|
+
function copyLocalTopogramSource(sourcePath, targetPath) {
|
|
135
|
+
const packageRoot = path.resolve(sourcePath);
|
|
136
|
+
if (!fs.existsSync(packageRoot) || !fs.statSync(packageRoot).isDirectory()) {
|
|
137
|
+
throw new Error(`Copy source '${sourcePath}' was not found.`);
|
|
138
|
+
}
|
|
139
|
+
if (fs.existsSync(path.join(packageRoot, "implementation"))) {
|
|
140
|
+
throw new Error(`Topogram source '${sourcePath}' contains implementation/, which is not allowed for pure topogram copy.`);
|
|
141
|
+
}
|
|
142
|
+
const packageWorkspace = resolvePackageWorkspace(packageRoot);
|
|
143
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
144
|
+
ensureEmptyDirectory(resolvedTarget);
|
|
145
|
+
/** @type {string[]} */
|
|
146
|
+
const files = [];
|
|
147
|
+
copyPath(packageWorkspace.root, path.join(resolvedTarget, DEFAULT_TOPO_FOLDER_NAME), DEFAULT_TOPO_FOLDER_NAME, files);
|
|
148
|
+
for (const fileName of ["topogram.project.json", "README.md"]) {
|
|
149
|
+
const sourceFile = path.join(packageRoot, fileName);
|
|
150
|
+
if (!fs.existsSync(sourceFile) || !fs.statSync(sourceFile).isFile()) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (fileName === "topogram.project.json") {
|
|
154
|
+
const projectConfig = JSON.parse(fs.readFileSync(sourceFile, "utf8"));
|
|
155
|
+
projectConfig.workspace = DEFAULT_WORKSPACE_PATH;
|
|
156
|
+
fs.writeFileSync(path.join(resolvedTarget, fileName), `${JSON.stringify(projectConfig, null, 2)}\n`, "utf8");
|
|
157
|
+
files.push(fileName);
|
|
158
|
+
} else {
|
|
159
|
+
copyPath(sourceFile, path.join(resolvedTarget, fileName), fileName, files);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const sourceId = path.basename(packageRoot);
|
|
163
|
+
const provenance = writeTopogramSourceRecord(resolvedTarget, {
|
|
164
|
+
catalogSource: null,
|
|
165
|
+
entry: {
|
|
166
|
+
id: sourceId,
|
|
167
|
+
package: sourcePath,
|
|
168
|
+
defaultVersion: "local"
|
|
169
|
+
},
|
|
170
|
+
packageSpec: sourcePath,
|
|
171
|
+
version: "local"
|
|
172
|
+
});
|
|
173
|
+
return {
|
|
174
|
+
ok: true,
|
|
175
|
+
action: "copy_topogram",
|
|
176
|
+
source: sourcePath,
|
|
177
|
+
id: sourceId,
|
|
178
|
+
kind: "topogram",
|
|
179
|
+
packageSpec: sourcePath,
|
|
180
|
+
targetPath: resolvedTarget,
|
|
181
|
+
provenancePath: provenance.path,
|
|
182
|
+
files: files.sort((a, b) => a.localeCompare(b)),
|
|
183
|
+
diagnostics: [],
|
|
184
|
+
errors: []
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @param {ReturnType<typeof createNewProject>} result
|
|
190
|
+
* @returns {Record<string, any>}
|
|
191
|
+
*/
|
|
192
|
+
function templateCopyPayload(result) {
|
|
193
|
+
return {
|
|
194
|
+
ok: true,
|
|
195
|
+
action: "copy_template",
|
|
196
|
+
kind: "template",
|
|
197
|
+
projectRoot: result.projectRoot,
|
|
198
|
+
templateName: result.templateName,
|
|
199
|
+
template: result.template,
|
|
200
|
+
topogramPath: result.topogramPath,
|
|
201
|
+
appPath: result.appPath,
|
|
202
|
+
warnings: result.warnings,
|
|
203
|
+
diagnostics: [],
|
|
204
|
+
errors: []
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param {ReturnType<typeof createNewProject>} result
|
|
210
|
+
* @param {string} cwd
|
|
211
|
+
* @returns {void}
|
|
212
|
+
*/
|
|
213
|
+
export function printTemplateCopyResult(result, cwd) {
|
|
214
|
+
const template = result.template || {};
|
|
215
|
+
console.log(`Copied Topogram template to ${result.projectRoot}.`);
|
|
216
|
+
console.log(`Template: ${result.templateName}`);
|
|
217
|
+
console.log(`Source: ${template.source || "unknown"}`);
|
|
218
|
+
if (template.sourceSpec) {
|
|
219
|
+
console.log(`Source spec: ${template.sourceSpec}`);
|
|
220
|
+
}
|
|
221
|
+
if (template.catalog) {
|
|
222
|
+
console.log(`Catalog: ${template.catalog.id} from ${template.catalog.source}`);
|
|
223
|
+
console.log(`Package: ${template.catalog.packageSpec}`);
|
|
224
|
+
}
|
|
225
|
+
console.log(`Executable implementation: ${template.includesExecutableImplementation ? "yes" : "no"}`);
|
|
226
|
+
console.log("Policy: topogram.template-policy.json");
|
|
227
|
+
console.log(`Generator policy: ${GENERATOR_POLICY_FILE}`);
|
|
228
|
+
console.log("Template files: .topogram-template-files.json");
|
|
229
|
+
if (template.includesExecutableImplementation) {
|
|
230
|
+
console.log("Trust: .topogram-template-trust.json");
|
|
231
|
+
}
|
|
232
|
+
for (const warning of result.warnings) {
|
|
233
|
+
console.warn(`Warning: ${warning}`);
|
|
234
|
+
}
|
|
235
|
+
console.log("");
|
|
236
|
+
console.log("Next steps:");
|
|
237
|
+
console.log(` cd ${displayProjectRootForCopy(result, cwd)}`);
|
|
238
|
+
console.log(" npm install");
|
|
239
|
+
console.log(" npm run agent:brief");
|
|
240
|
+
console.log(" npm run doctor");
|
|
241
|
+
console.log(" npm run source:status");
|
|
242
|
+
console.log(" npm run template:explain");
|
|
243
|
+
console.log(" npm run check");
|
|
244
|
+
console.log(" npm run generator:policy:status");
|
|
245
|
+
console.log(" npm run generator:policy:check");
|
|
246
|
+
if (template.includesExecutableImplementation) {
|
|
247
|
+
console.log(" npm run template:policy:explain");
|
|
248
|
+
console.log(" npm run trust:status");
|
|
249
|
+
}
|
|
250
|
+
console.log(" npm run generate");
|
|
251
|
+
console.log(" npm run verify");
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @param {any} payload
|
|
256
|
+
* @returns {void}
|
|
257
|
+
*/
|
|
258
|
+
export function printTopogramCopy(payload) {
|
|
259
|
+
console.log(`Copied topogram '${payload.id}' to ${payload.targetPath}.`);
|
|
260
|
+
console.log(`Package: ${payload.packageSpec}`);
|
|
261
|
+
console.log(`Source provenance: ${payload.provenancePath}`);
|
|
262
|
+
console.log(`Files: ${payload.files.length}`);
|
|
263
|
+
console.log(`${TOPOGRAM_SOURCE_FILE} records copy provenance only. Local edits are allowed.`);
|
|
264
|
+
console.log("");
|
|
265
|
+
console.log("Next steps:");
|
|
266
|
+
console.log(` cd ${shellCommandArg(path.relative(process.cwd(), payload.targetPath) || ".")}`);
|
|
267
|
+
console.log(" topogram source status --local");
|
|
268
|
+
console.log(" topogram check");
|
|
269
|
+
console.log(" topogram generate");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @param {{ commandArgs: Record<string, any>, catalogSource?: string|null, requestedVersion?: string|null, json?: boolean, cwd?: string }} context
|
|
274
|
+
* @returns {number}
|
|
275
|
+
*/
|
|
276
|
+
export function runCopyCommand(context) {
|
|
277
|
+
const {
|
|
278
|
+
commandArgs,
|
|
279
|
+
catalogSource = null,
|
|
280
|
+
requestedVersion = null,
|
|
281
|
+
json = false,
|
|
282
|
+
cwd = process.cwd()
|
|
283
|
+
} = context;
|
|
284
|
+
|
|
285
|
+
if (commandArgs.copyCommand === "list") {
|
|
286
|
+
const payload = buildCatalogListPayload(catalogSource || null);
|
|
287
|
+
if (json) {
|
|
288
|
+
console.log(stableStringify(payload));
|
|
289
|
+
} else {
|
|
290
|
+
printCatalogList(payload);
|
|
291
|
+
}
|
|
292
|
+
return 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const source = commandArgs.copySource;
|
|
296
|
+
const targetPath = commandArgs.inputPath;
|
|
297
|
+
if (!source || String(source).startsWith("-")) {
|
|
298
|
+
throw new Error("topogram copy requires <source>.");
|
|
299
|
+
}
|
|
300
|
+
if (!targetPath || String(targetPath).startsWith("-")) {
|
|
301
|
+
throw new Error("topogram copy requires <target>.");
|
|
302
|
+
}
|
|
303
|
+
assertProjectTargetOutsideEngine(targetPath);
|
|
304
|
+
|
|
305
|
+
let catalogTopogram;
|
|
306
|
+
try {
|
|
307
|
+
catalogTopogram = tryCopyCatalogTopogram(source, targetPath, {
|
|
308
|
+
catalogSource,
|
|
309
|
+
version: requestedVersion
|
|
310
|
+
});
|
|
311
|
+
} catch (error) {
|
|
312
|
+
if (isCatalogIdCandidate(source)) {
|
|
313
|
+
throw new Error(formatCatalogTemplateAliasError(source, catalogSource || null, error));
|
|
314
|
+
}
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
317
|
+
if (catalogTopogram) {
|
|
318
|
+
if (json) {
|
|
319
|
+
console.log(stableStringify(catalogTopogram));
|
|
320
|
+
} else {
|
|
321
|
+
printTopogramCopy(catalogTopogram);
|
|
322
|
+
}
|
|
323
|
+
return catalogTopogram.ok ? 0 : 1;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (source === "." || source.startsWith("./") || source.startsWith("../") || path.isAbsolute(source)) {
|
|
327
|
+
const localRoot = path.resolve(source);
|
|
328
|
+
if (fs.existsSync(path.join(localRoot, DEFAULT_TOPO_FOLDER_NAME)) && !fs.existsSync(path.join(localRoot, "topogram-template.json"))) {
|
|
329
|
+
const payload = copyLocalTopogramSource(source, targetPath);
|
|
330
|
+
if (json) {
|
|
331
|
+
console.log(stableStringify(payload));
|
|
332
|
+
} else {
|
|
333
|
+
printTopogramCopy(payload);
|
|
334
|
+
}
|
|
335
|
+
return payload.ok ? 0 : 1;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const resolvedTemplate = resolveCopyTemplateSource(source, targetPath, {
|
|
340
|
+
catalogSource,
|
|
341
|
+
version: requestedVersion
|
|
342
|
+
});
|
|
343
|
+
const result = createNewProject({
|
|
344
|
+
targetPath,
|
|
345
|
+
templateName: resolvedTemplate.templateName,
|
|
346
|
+
templateProvenance: resolvedTemplate.provenance,
|
|
347
|
+
engineRoot: ENGINE_ROOT,
|
|
348
|
+
templatesRoot: TEMPLATES_ROOT
|
|
349
|
+
});
|
|
350
|
+
if (json) {
|
|
351
|
+
console.log(stableStringify(templateCopyPayload(result)));
|
|
352
|
+
} else {
|
|
353
|
+
printTemplateCopyResult(result, cwd);
|
|
354
|
+
}
|
|
355
|
+
return 0;
|
|
356
|
+
}
|
|
@@ -37,7 +37,7 @@ export function printDoctorHelp() {
|
|
|
37
37
|
console.log(" npm install --save-dev @topogram/cli");
|
|
38
38
|
console.log(" npx topogram doctor");
|
|
39
39
|
console.log(" npx topogram template list");
|
|
40
|
-
console.log(" npx topogram
|
|
40
|
+
console.log(" npx topogram copy hello-web ./my-app");
|
|
41
41
|
console.log("");
|
|
42
42
|
console.log("Related setup commands:");
|
|
43
43
|
console.log(" topogram setup package-auth");
|