@topogram/cli 0.3.44 → 0.3.45
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
CHANGED
package/src/cli.js
CHANGED
|
@@ -595,9 +595,9 @@ function printGeneratorHelp() {
|
|
|
595
595
|
console.log("Inspects generator manifests and checks generator pack conformance.");
|
|
596
596
|
console.log("");
|
|
597
597
|
console.log("Notes:");
|
|
598
|
-
console.log(" - list shows bundled generators plus installed package-backed generators declared in package.json.");
|
|
599
|
-
console.log(" - show accepts an installed package name or a bundled fallback generator id.");
|
|
600
|
-
console.log(" - check validates a local generator package path or an already installed package.");
|
|
598
|
+
console.log(" - list shows bundled generators plus installed package-backed generators declared in package.json; it reads manifests only.");
|
|
599
|
+
console.log(" - show accepts an installed package name or a bundled fallback generator id; it does not load adapter code.");
|
|
600
|
+
console.log(" - check validates a local generator package path or an already installed package by loading the adapter and running smoke generation.");
|
|
601
601
|
console.log(" - Topogram does not install generator packages during show or check.");
|
|
602
602
|
console.log(` - package-backed project generators are governed by ${GENERATOR_POLICY_FILE}; bundled topogram/* generators are allowed.`);
|
|
603
603
|
console.log("");
|
|
@@ -1250,6 +1250,7 @@ function printGeneratorCheck(payload) {
|
|
|
1250
1250
|
console.log(`Projection platforms: ${payload.manifest.projectionPlatforms.join(", ")}`);
|
|
1251
1251
|
console.log(`Source mode: ${payload.manifest.source}`);
|
|
1252
1252
|
}
|
|
1253
|
+
console.log("Executes package code: yes (loads adapter and runs smoke generate)");
|
|
1253
1254
|
console.log("");
|
|
1254
1255
|
console.log("Checks:");
|
|
1255
1256
|
for (const check of payload.checks || []) {
|
|
@@ -1285,6 +1286,8 @@ function generatorManifestSummary(manifest, metadata = {}) {
|
|
|
1285
1286
|
stack: manifest.stack || {},
|
|
1286
1287
|
capabilities: manifest.capabilities || {},
|
|
1287
1288
|
source: manifest.source,
|
|
1289
|
+
loadsAdapter: false,
|
|
1290
|
+
executesPackageCode: false,
|
|
1288
1291
|
...(manifest.profile ? { profile: manifest.profile } : {}),
|
|
1289
1292
|
...(manifest.package ? { package: manifest.package } : {}),
|
|
1290
1293
|
...(installCommand ? { installCommand } : {}),
|
|
@@ -1496,6 +1499,8 @@ function printGeneratorList(payload) {
|
|
|
1496
1499
|
const stack = Object.values(generator.stack || {}).join(" + ") || "not declared";
|
|
1497
1500
|
console.log(`- ${id}${generator.version ? `@${generator.version}` : ""} (${generator.surface || "unknown"}, ${status})`);
|
|
1498
1501
|
console.log(` Source: ${generator.source}`);
|
|
1502
|
+
console.log(" Adapter loaded: no");
|
|
1503
|
+
console.log(" Executes package code: no");
|
|
1499
1504
|
if (generator.source === "package") {
|
|
1500
1505
|
console.log(` Installed: ${generator.installed ? "yes" : "no"}`);
|
|
1501
1506
|
}
|
|
@@ -1529,6 +1534,8 @@ function printGeneratorShow(payload) {
|
|
|
1529
1534
|
console.log(`Generator: ${generator.id}@${generator.version}`);
|
|
1530
1535
|
console.log(`Surface: ${generator.surface}`);
|
|
1531
1536
|
console.log(`Source: ${generator.source}${generator.planned ? " (planned)" : ""}`);
|
|
1537
|
+
console.log("Adapter loaded: no");
|
|
1538
|
+
console.log("Executes package code: no");
|
|
1532
1539
|
if (generator.source === "package") {
|
|
1533
1540
|
console.log(`Installed: ${generator.installed ? "yes" : "no"}`);
|
|
1534
1541
|
}
|
|
@@ -10,6 +10,10 @@ import {
|
|
|
10
10
|
resolveGeneratorManifestForBinding,
|
|
11
11
|
validateGeneratorManifest
|
|
12
12
|
} from "./registry.js";
|
|
13
|
+
import {
|
|
14
|
+
generatorPolicyDiagnosticsForBindings,
|
|
15
|
+
loadGeneratorPolicy
|
|
16
|
+
} from "../generator-policy.js";
|
|
13
17
|
import { generateDbContractGraph } from "./surfaces/databases/contract.js";
|
|
14
18
|
import { generateDbLifecyclePlan } from "./surfaces/databases/lifecycle-shared.js";
|
|
15
19
|
import {
|
|
@@ -252,6 +256,26 @@ function loadPackageGeneratorAdapter(manifest, component, options = {}) {
|
|
|
252
256
|
throw new Error(`Component '${component?.id || "unknown"}' generator '${manifest.id}@${manifest.version}' is package-backed but does not declare a package.`);
|
|
253
257
|
}
|
|
254
258
|
const rootDir = options.configDir || options.rootDir || process.cwd();
|
|
259
|
+
const diagnostics = generatorPolicyDiagnosticsForBindings(
|
|
260
|
+
loadGeneratorPolicy(rootDir),
|
|
261
|
+
[{
|
|
262
|
+
componentId: String(component?.id || "unknown"),
|
|
263
|
+
componentType: String(component?.type || manifest.surface || "unknown"),
|
|
264
|
+
projection: String(component?.projection?.id || component?.projection || "unknown"),
|
|
265
|
+
generatorId: String(component?.generator?.id || manifest.id),
|
|
266
|
+
version: String(component?.generator?.version || manifest.version),
|
|
267
|
+
packageName
|
|
268
|
+
}],
|
|
269
|
+
"generator-adapter"
|
|
270
|
+
);
|
|
271
|
+
const errors = diagnostics.filter((diagnostic) => diagnostic.severity === "error");
|
|
272
|
+
if (errors.length > 0) {
|
|
273
|
+
throw new Error(errors.map((diagnostic) =>
|
|
274
|
+
diagnostic.suggestedFix
|
|
275
|
+
? `${diagnostic.message} Suggested fix: ${diagnostic.suggestedFix}`
|
|
276
|
+
: diagnostic.message
|
|
277
|
+
).join("\n"));
|
|
278
|
+
}
|
|
255
279
|
let moduleValue;
|
|
256
280
|
try {
|
|
257
281
|
moduleValue = requireFromProject(rootDir)(packageName);
|
package/src/generator/check.js
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
* @property {Array<{ name: string, ok: boolean, message: string }>} checks
|
|
26
26
|
* @property {string[]} errors
|
|
27
27
|
* @property {{ files: number, artifacts: number, diagnostics: number }|null} smoke
|
|
28
|
+
* @property {boolean} executesPackageCode
|
|
28
29
|
*/
|
|
29
30
|
|
|
30
31
|
/**
|
|
@@ -238,7 +239,8 @@ export function checkGeneratorPack(sourceSpec, options = {}) {
|
|
|
238
239
|
manifest: null,
|
|
239
240
|
checks: [],
|
|
240
241
|
errors: [],
|
|
241
|
-
smoke: null
|
|
242
|
+
smoke: null,
|
|
243
|
+
executesPackageCode: true
|
|
242
244
|
};
|
|
243
245
|
|
|
244
246
|
/** @type {any|null} */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import { getProjection } from "../shared.js";
|
|
4
|
+
import { generateServerContract } from "./server-contract.js";
|
|
4
5
|
|
|
5
6
|
function renderPackageJson(profile) {
|
|
6
7
|
const dependencies = profile === "express"
|
|
@@ -41,10 +42,10 @@ function routePath(path) {
|
|
|
41
42
|
return String(path || "/").replace(/:([A-Za-z0-9_]+)/g, ":$1");
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
function renderHonoIndex(projection) {
|
|
45
|
-
const routes = (
|
|
45
|
+
function renderHonoIndex(projection, contract) {
|
|
46
|
+
const routes = (contract.routes || []).map((route) => {
|
|
46
47
|
const method = String(route.method || "GET").toLowerCase();
|
|
47
|
-
return `app.${method}("${routePath(route.path)}", (c) => c.json({ ok: true, capability: "${route.capabilityId}", input: { params: c.req.param(), query: c.req.query() } }, ${route.
|
|
48
|
+
return `app.${method}("${routePath(route.path)}", (c) => c.json({ ok: true, capability: "${route.capabilityId}", input: { params: c.req.param(), query: c.req.query() } }, ${route.successStatus || 200} as any));`;
|
|
48
49
|
}).join("\n");
|
|
49
50
|
return `import { serve } from "@hono/node-server";
|
|
50
51
|
import { Hono } from "hono";
|
|
@@ -65,10 +66,10 @@ function expressPath(path) {
|
|
|
65
66
|
return routePath(path);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
function renderExpressIndex(projection) {
|
|
69
|
-
const routes = (
|
|
69
|
+
function renderExpressIndex(projection, contract) {
|
|
70
|
+
const routes = (contract.routes || []).map((route) => {
|
|
70
71
|
const method = String(route.method || "GET").toLowerCase();
|
|
71
|
-
return `app.${method}("${expressPath(route.path)}", (req, res) => res.status(${route.
|
|
72
|
+
return `app.${method}("${expressPath(route.path)}", (req, res) => res.status(${route.successStatus || 200}).json({ ok: true, capability: "${route.capabilityId}", input: { params: req.params, query: req.query } }));`;
|
|
72
73
|
}).join("\n");
|
|
73
74
|
return `import express from "express";
|
|
74
75
|
|
|
@@ -88,10 +89,11 @@ app.listen(port, () => {
|
|
|
88
89
|
|
|
89
90
|
export function generateStatelessServer(graph, options = {}) {
|
|
90
91
|
const projection = getProjection(graph, options.projectionId);
|
|
92
|
+
const contract = generateServerContract(graph, { ...options, projectionId: projection.id });
|
|
91
93
|
const profile = options.profile === "express" ? "express" : "hono";
|
|
92
94
|
return {
|
|
93
95
|
"package.json": renderPackageJson(profile),
|
|
94
96
|
"tsconfig.json": renderTsconfig(),
|
|
95
|
-
"src/index.ts": profile === "express" ? renderExpressIndex(projection) : renderHonoIndex(projection)
|
|
97
|
+
"src/index.ts": profile === "express" ? renderExpressIndex(projection, contract) : renderHonoIndex(projection, contract)
|
|
96
98
|
};
|
|
97
99
|
}
|