@topogram/cli 0.3.78 → 0.3.79
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-parsers/core.js +9 -5
- 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/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 +43 -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 +16 -16
- package/src/cli/commands/import-runner.js +6 -5
- 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 +18 -3
- package/src/cli/help-dispatch.js +22 -8
- package/src/cli/help.js +68 -52
- package/src/cli/migration-guidance.js +9 -0
- 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/import/core/runner/reports.js +4 -4
- package/src/import/provenance.js +16 -16
- 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/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,233 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
JOURNEY_IDENTIFIER_PATTERN
|
|
5
|
+
} from "../kinds.js";
|
|
6
|
+
import {
|
|
7
|
+
pushError
|
|
8
|
+
} from "../utils.js";
|
|
9
|
+
import {
|
|
10
|
+
parseRecordBlock,
|
|
11
|
+
recordField,
|
|
12
|
+
recordString,
|
|
13
|
+
recordStringList,
|
|
14
|
+
recordSymbol,
|
|
15
|
+
recordSymbolList
|
|
16
|
+
} from "../../record-blocks.js";
|
|
17
|
+
|
|
18
|
+
const STEP_FIELDS = new Set(["id", "intent", "commands", "expects", "after", "notes"]);
|
|
19
|
+
const ALTERNATE_FIELDS = new Set(["id", "from", "condition", "commands", "expects", "notes"]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {ValidationErrors} errors
|
|
23
|
+
* @param {TopogramStatement} statement
|
|
24
|
+
* @returns {void}
|
|
25
|
+
*/
|
|
26
|
+
function validateJourneyIdentifier(errors, statement) {
|
|
27
|
+
if (!JOURNEY_IDENTIFIER_PATTERN.test(statement.id)) {
|
|
28
|
+
pushError(
|
|
29
|
+
errors,
|
|
30
|
+
`Journey identifier '${statement.id}' must match ${JOURNEY_IDENTIFIER_PATTERN.source}`,
|
|
31
|
+
statement.loc
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {ValidationErrors} errors
|
|
38
|
+
* @param {TopogramStatement} statement
|
|
39
|
+
* @param {TopogramField} field
|
|
40
|
+
* @param {Set<string>} allowedFields
|
|
41
|
+
* @param {string[]} requiredFields
|
|
42
|
+
* @returns {import("../../record-blocks.js").TopogramRecordBlock | null}
|
|
43
|
+
*/
|
|
44
|
+
function validateRecordBlock(errors, statement, field, allowedFields, requiredFields) {
|
|
45
|
+
if (field.value.type !== "block") {
|
|
46
|
+
pushError(errors, `Field '${field.key}' on journey ${statement.id} must be a block`, field.loc);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const record = parseRecordBlock(/** @type {import("../../parser.js").AstBlock} */ (/** @type {unknown} */ (field.value)));
|
|
51
|
+
for (const recordFieldEntry of record.fieldOrder) {
|
|
52
|
+
if (!recordFieldEntry.key) {
|
|
53
|
+
pushError(errors, `Each '${field.key}' record entry on journey ${statement.id} must start with a field name`, recordFieldEntry.loc);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (!allowedFields.has(recordFieldEntry.key)) {
|
|
57
|
+
pushError(errors, `Unsupported '${field.key}' field '${recordFieldEntry.key}' on journey ${statement.id}`, recordFieldEntry.loc);
|
|
58
|
+
}
|
|
59
|
+
const entries = record.fields.get(recordFieldEntry.key) || [];
|
|
60
|
+
if (entries.length > 1 && entries[1] === recordFieldEntry) {
|
|
61
|
+
pushError(errors, `Duplicate '${field.key}' field '${recordFieldEntry.key}' on journey ${statement.id}`, recordFieldEntry.loc);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const required of requiredFields) {
|
|
66
|
+
if (!record.fields.has(required)) {
|
|
67
|
+
pushError(errors, `Journey ${statement.id} ${field.key} record requires '${required}'`, field.loc);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return record;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {ValidationErrors} errors
|
|
76
|
+
* @param {TopogramStatement} statement
|
|
77
|
+
* @param {import("../../record-blocks.js").TopogramRecordBlock} record
|
|
78
|
+
* @param {string} fieldName
|
|
79
|
+
* @param {"symbol" | "string" | "symbol_list" | "string_list"} expected
|
|
80
|
+
* @returns {void}
|
|
81
|
+
*/
|
|
82
|
+
function validateRecordFieldShape(errors, statement, record, fieldName, expected) {
|
|
83
|
+
const field = recordField(record, fieldName);
|
|
84
|
+
if (!field || !field.value) return;
|
|
85
|
+
if (expected === "symbol" && field.value.type !== "symbol") {
|
|
86
|
+
pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a symbol`, field.loc);
|
|
87
|
+
}
|
|
88
|
+
if (expected === "string" && field.value.type !== "string") {
|
|
89
|
+
pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a string`, field.loc);
|
|
90
|
+
}
|
|
91
|
+
if (expected === "symbol_list" && field.value.type !== "list") {
|
|
92
|
+
pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a list of symbols`, field.loc);
|
|
93
|
+
}
|
|
94
|
+
if (expected === "string_list" && field.value.type !== "list") {
|
|
95
|
+
pushError(errors, `Journey ${statement.id} record field '${fieldName}' must be a list of strings`, field.loc);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {ValidationErrors} errors
|
|
101
|
+
* @param {TopogramStatement} statement
|
|
102
|
+
* @param {TopogramFieldMap} fieldMap
|
|
103
|
+
* @returns {Set<string>}
|
|
104
|
+
*/
|
|
105
|
+
function validateStepRecords(errors, statement, fieldMap) {
|
|
106
|
+
const fields = fieldMap.get("step") || [];
|
|
107
|
+
/** @type {Set<string>} */
|
|
108
|
+
const stepIds = new Set();
|
|
109
|
+
if (fields.length === 0) {
|
|
110
|
+
pushError(errors, `Journey ${statement.id} must include at least one step`, statement.loc);
|
|
111
|
+
return stepIds;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (const field of fields) {
|
|
115
|
+
const record = validateRecordBlock(errors, statement, field, STEP_FIELDS, ["id", "intent"]);
|
|
116
|
+
if (!record) continue;
|
|
117
|
+
validateRecordFieldShape(errors, statement, record, "id", "symbol");
|
|
118
|
+
validateRecordFieldShape(errors, statement, record, "intent", "string");
|
|
119
|
+
validateRecordFieldShape(errors, statement, record, "commands", "string_list");
|
|
120
|
+
validateRecordFieldShape(errors, statement, record, "expects", "string_list");
|
|
121
|
+
validateRecordFieldShape(errors, statement, record, "after", "symbol_list");
|
|
122
|
+
validateRecordFieldShape(errors, statement, record, "notes", "string");
|
|
123
|
+
|
|
124
|
+
const stepId = recordSymbol(record, "id");
|
|
125
|
+
if (!stepId) continue;
|
|
126
|
+
if (!/^[a-z][a-z0-9_]*$/.test(stepId)) {
|
|
127
|
+
pushError(errors, `Journey ${statement.id} step id must match /^[a-z][a-z0-9_]*$/`, recordField(record, "id")?.loc || field.loc);
|
|
128
|
+
}
|
|
129
|
+
if (stepIds.has(stepId)) {
|
|
130
|
+
pushError(errors, `Journey ${statement.id} has duplicate step '${stepId}'`, recordField(record, "id")?.loc || field.loc);
|
|
131
|
+
}
|
|
132
|
+
stepIds.add(stepId);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for (const field of fields) {
|
|
136
|
+
if (field.value.type !== "block") continue;
|
|
137
|
+
const record = parseRecordBlock(/** @type {import("../../parser.js").AstBlock} */ (/** @type {unknown} */ (field.value)));
|
|
138
|
+
const stepId = recordSymbol(record, "id") || "unknown";
|
|
139
|
+
for (const afterId of recordSymbolList(record, "after")) {
|
|
140
|
+
if (!stepIds.has(afterId)) {
|
|
141
|
+
pushError(errors, `Journey ${statement.id} step '${stepId}' after references missing step '${afterId}'`, recordField(record, "after")?.loc || field.loc);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return stepIds;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param {ValidationErrors} errors
|
|
151
|
+
* @param {TopogramStatement} statement
|
|
152
|
+
* @param {TopogramFieldMap} fieldMap
|
|
153
|
+
* @param {Set<string>} stepIds
|
|
154
|
+
* @returns {void}
|
|
155
|
+
*/
|
|
156
|
+
function validateAlternateRecords(errors, statement, fieldMap, stepIds) {
|
|
157
|
+
const fields = fieldMap.get("alternate") || [];
|
|
158
|
+
/** @type {Set<string>} */
|
|
159
|
+
const alternateIds = new Set();
|
|
160
|
+
for (const field of fields) {
|
|
161
|
+
const record = validateRecordBlock(errors, statement, field, ALTERNATE_FIELDS, ["id", "from", "condition"]);
|
|
162
|
+
if (!record) continue;
|
|
163
|
+
validateRecordFieldShape(errors, statement, record, "id", "symbol");
|
|
164
|
+
validateRecordFieldShape(errors, statement, record, "from", "symbol");
|
|
165
|
+
validateRecordFieldShape(errors, statement, record, "condition", "string");
|
|
166
|
+
validateRecordFieldShape(errors, statement, record, "commands", "string_list");
|
|
167
|
+
validateRecordFieldShape(errors, statement, record, "expects", "string_list");
|
|
168
|
+
validateRecordFieldShape(errors, statement, record, "notes", "string");
|
|
169
|
+
|
|
170
|
+
const alternateId = recordSymbol(record, "id");
|
|
171
|
+
if (alternateId) {
|
|
172
|
+
if (!/^[a-z][a-z0-9_]*$/.test(alternateId)) {
|
|
173
|
+
pushError(errors, `Journey ${statement.id} alternate id must match /^[a-z][a-z0-9_]*$/`, recordField(record, "id")?.loc || field.loc);
|
|
174
|
+
}
|
|
175
|
+
if (alternateIds.has(alternateId)) {
|
|
176
|
+
pushError(errors, `Journey ${statement.id} has duplicate alternate '${alternateId}'`, recordField(record, "id")?.loc || field.loc);
|
|
177
|
+
}
|
|
178
|
+
alternateIds.add(alternateId);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const fromStep = recordSymbol(record, "from");
|
|
182
|
+
if (fromStep && !stepIds.has(fromStep)) {
|
|
183
|
+
pushError(errors, `Journey ${statement.id} alternate '${alternateId || "unknown"}' from references missing step '${fromStep}'`, recordField(record, "from")?.loc || field.loc);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @param {ValidationErrors} errors
|
|
190
|
+
* @param {TopogramStatement} statement
|
|
191
|
+
* @param {TopogramFieldMap} fieldMap
|
|
192
|
+
* @returns {void}
|
|
193
|
+
*/
|
|
194
|
+
function validateTopLevelListShapes(errors, statement, fieldMap) {
|
|
195
|
+
const stringListFields = ["success_signals", "failure_signals", "tags"];
|
|
196
|
+
for (const key of stringListFields) {
|
|
197
|
+
const field = fieldMap.get(key)?.[0];
|
|
198
|
+
if (!field || field.value.type !== "list") continue;
|
|
199
|
+
for (const item of field.value.items) {
|
|
200
|
+
if (item.type !== "string" && key !== "tags") {
|
|
201
|
+
pushError(errors, `Journey ${statement.id} field '${key}' must contain strings`, item.loc);
|
|
202
|
+
}
|
|
203
|
+
if (key === "tags" && item.type !== "symbol" && item.type !== "string") {
|
|
204
|
+
pushError(errors, `Journey ${statement.id} field '${key}' must contain symbols or strings`, item.loc);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Keep referenced imports used by checkJs while making the expected record
|
|
212
|
+
* helper vocabulary obvious to future validators.
|
|
213
|
+
*/
|
|
214
|
+
void recordString;
|
|
215
|
+
void recordStringList;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @param {ValidationErrors} errors
|
|
219
|
+
* @param {TopogramStatement} statement
|
|
220
|
+
* @param {TopogramFieldMap} fieldMap
|
|
221
|
+
* @param {TopogramRegistry} registry
|
|
222
|
+
* @returns {void}
|
|
223
|
+
*/
|
|
224
|
+
export function validateJourney(errors, statement, fieldMap, registry) {
|
|
225
|
+
void registry;
|
|
226
|
+
if (statement.kind !== "journey") {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
validateJourneyIdentifier(errors, statement);
|
|
230
|
+
validateTopLevelListShapes(errors, statement, fieldMap);
|
|
231
|
+
const stepIds = validateStepRecords(errors, statement, fieldMap);
|
|
232
|
+
validateAlternateRecords(errors, statement, fieldMap, stepIds);
|
|
233
|
+
}
|
|
@@ -215,7 +215,10 @@ export function generateDocsWorkflow(inputPath) {
|
|
|
215
215
|
export function generateJourneyDraftsWorkflow(inputPath) {
|
|
216
216
|
const paths = normalizeWorkspacePaths(inputPath);
|
|
217
217
|
const graph = loadResolvedGraph(paths.topogramRoot);
|
|
218
|
-
const canonicalJourneys =
|
|
218
|
+
const canonicalJourneys = [
|
|
219
|
+
...(graph.byKind?.journey || []),
|
|
220
|
+
...(graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey")
|
|
221
|
+
];
|
|
219
222
|
const { drafts, skippedEntities } = buildJourneyDraftsReconcile(graph);
|
|
220
223
|
/** @type {WorkflowFiles} */
|
|
221
224
|
/** @type {WorkflowFiles} */
|
|
@@ -62,9 +62,11 @@ export function bundleLabelFromConceptId(conceptId) {
|
|
|
62
62
|
/** @param {ResolvedGraph} graph @returns {any} */
|
|
63
63
|
export function canonicalJourneyCoverage(graph) {
|
|
64
64
|
const journeyDocs = (graph?.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey");
|
|
65
|
+
const journeyStatements = graph?.byKind?.journey || [];
|
|
66
|
+
const journeys = [...journeyStatements, ...journeyDocs];
|
|
65
67
|
return {
|
|
66
|
-
byEntityId: new Set(
|
|
67
|
-
byCapabilityId: new Set(
|
|
68
|
+
byEntityId: new Set(journeys.flatMap((/** @type {any} */ journey) => journey.relatedEntities || [])),
|
|
69
|
+
byCapabilityId: new Set(journeys.flatMap((/** @type {any} */ journey) => journey.relatedCapabilities || []))
|
|
68
70
|
};
|
|
69
71
|
}
|
|
70
72
|
|
|
@@ -133,7 +133,10 @@ export function collectCanonicalWorkflowSurface(graph) {
|
|
|
133
133
|
|
|
134
134
|
/** @param {ResolvedGraph} graph @returns {any} */
|
|
135
135
|
export function collectCanonicalActorRoleSurface(graph) {
|
|
136
|
-
const journeyDocs =
|
|
136
|
+
const journeyDocs = [
|
|
137
|
+
...(graph.byKind?.journey || []),
|
|
138
|
+
...(graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "journey")
|
|
139
|
+
];
|
|
137
140
|
const workflowDocs = (graph.docs || []).filter((/** @type {any} */ doc) => doc.kind === "workflow");
|
|
138
141
|
return {
|
|
139
142
|
actor_ids: ((graph.byKind.actor || []).map((/** @type {any} */ entry) => entry.id)).sort(),
|
package/src/cli/commands/new.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
|
|
5
|
-
import { resolveCatalogTemplateAlias } from "../catalog-alias.js";
|
|
6
|
-
import { GENERATOR_POLICY_FILE } from "../../generator-policy.js";
|
|
7
|
-
import { createNewProject } from "../../new-project.js";
|
|
8
|
-
|
|
9
|
-
const ENGINE_ROOT = path.resolve(decodeURIComponent(new URL("../../../", import.meta.url).pathname));
|
|
10
|
-
const TEMPLATES_ROOT = path.join(ENGINE_ROOT, "templates");
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param {ReturnType<typeof createNewProject>} result
|
|
14
|
-
* @param {string} cwd
|
|
15
|
-
* @returns {string}
|
|
16
|
-
*/
|
|
17
|
-
function displayProjectRootForNewProject(result, cwd) {
|
|
18
|
-
const relativeProjectRoot = path.relative(cwd, result.projectRoot);
|
|
19
|
-
return !relativeProjectRoot || relativeProjectRoot.startsWith("..")
|
|
20
|
-
? result.projectRoot
|
|
21
|
-
: relativeProjectRoot;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {ReturnType<typeof createNewProject>} result
|
|
26
|
-
* @param {string} cwd
|
|
27
|
-
* @returns {void}
|
|
28
|
-
*/
|
|
29
|
-
export function printNewProjectResult(result, cwd) {
|
|
30
|
-
const template = result.template || {};
|
|
31
|
-
console.log(`Created Topogram project at ${result.projectRoot}.`);
|
|
32
|
-
console.log(`Template: ${result.templateName}`);
|
|
33
|
-
console.log(`Source: ${template.source || "unknown"}`);
|
|
34
|
-
if (template.sourceSpec) {
|
|
35
|
-
console.log(`Source spec: ${template.sourceSpec}`);
|
|
36
|
-
}
|
|
37
|
-
if (template.catalog) {
|
|
38
|
-
console.log(`Catalog: ${template.catalog.id} from ${template.catalog.source}`);
|
|
39
|
-
console.log(`Package: ${template.catalog.packageSpec}`);
|
|
40
|
-
}
|
|
41
|
-
console.log(`Executable implementation: ${template.includesExecutableImplementation ? "yes" : "no"}`);
|
|
42
|
-
console.log("Policy: topogram.template-policy.json");
|
|
43
|
-
console.log(`Generator policy: ${GENERATOR_POLICY_FILE}`);
|
|
44
|
-
console.log("Template files: .topogram-template-files.json");
|
|
45
|
-
if (template.includesExecutableImplementation) {
|
|
46
|
-
console.log("Trust: .topogram-template-trust.json");
|
|
47
|
-
}
|
|
48
|
-
for (const warning of result.warnings) {
|
|
49
|
-
console.warn(`Warning: ${warning}`);
|
|
50
|
-
}
|
|
51
|
-
console.log("");
|
|
52
|
-
console.log("Next steps:");
|
|
53
|
-
console.log(` cd ${displayProjectRootForNewProject(result, cwd)}`);
|
|
54
|
-
console.log(" npm install");
|
|
55
|
-
console.log(" npm run agent:brief");
|
|
56
|
-
console.log(" npm run doctor");
|
|
57
|
-
console.log(" npm run source:status");
|
|
58
|
-
console.log(" npm run template:explain");
|
|
59
|
-
console.log(" npm run check");
|
|
60
|
-
console.log(" npm run generator:policy:status");
|
|
61
|
-
console.log(" npm run generator:policy:check");
|
|
62
|
-
if (template.includesExecutableImplementation) {
|
|
63
|
-
console.log(" npm run template:policy:explain");
|
|
64
|
-
console.log(" npm run trust:status");
|
|
65
|
-
}
|
|
66
|
-
console.log(" npm run generate");
|
|
67
|
-
console.log(" npm run verify");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* @param {string} inputPath
|
|
72
|
-
* @param {{ templateName: string, catalogSource?: string|null, cwd?: string }} options
|
|
73
|
-
* @returns {number}
|
|
74
|
-
*/
|
|
75
|
-
export function runNewProjectCommand(inputPath, options) {
|
|
76
|
-
const cwd = options.cwd || process.cwd();
|
|
77
|
-
const projectRoot = path.resolve(inputPath);
|
|
78
|
-
const relativeToEngine = path.relative(ENGINE_ROOT, projectRoot);
|
|
79
|
-
if (relativeToEngine === "" || (!relativeToEngine.startsWith("..") && !path.isAbsolute(relativeToEngine))) {
|
|
80
|
-
throw new Error(
|
|
81
|
-
`Refusing to create a generated project inside the engine directory. Use a path outside engine, for example '../${path.basename(projectRoot)}'.`
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
const resolvedTemplate = resolveCatalogTemplateAlias(options.templateName, options.catalogSource || null);
|
|
85
|
-
const result = createNewProject({
|
|
86
|
-
targetPath: inputPath,
|
|
87
|
-
templateName: resolvedTemplate.templateName,
|
|
88
|
-
templateProvenance: resolvedTemplate.provenance,
|
|
89
|
-
engineRoot: ENGINE_ROOT,
|
|
90
|
-
templatesRoot: TEMPLATES_ROOT
|
|
91
|
-
});
|
|
92
|
-
printNewProjectResult(result, cwd);
|
|
93
|
-
return 0;
|
|
94
|
-
}
|