@topogram/cli 0.3.55 → 0.3.56

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 CHANGED
@@ -5,6 +5,24 @@
5
5
  - Install package-backed generator dependencies during `topogram template check`
6
6
  before starter validation.
7
7
 
8
+ ## 0.3.55 - 2026-05-07
9
+
10
+ - Complete the public DSL cleanup from `component` to `widget`: normalized
11
+ graph/context output now uses `widget`, `widgetBindings`, `widgetContract`,
12
+ and widget report target names without publishing component compatibility
13
+ aliases.
14
+ - Reconcile/adoption import reports now emit `widgets` in candidate model
15
+ bundles, evidence, summaries, and promoted item plans. Existing imported
16
+ workspaces with `candidates.ui.components` are still accepted as a read-only
17
+ fallback, but new import output writes `candidates.ui.widgets`.
18
+ - Old CLI names fail with explicit rename guidance instead of silently running:
19
+ `topogram component`, `--component`, `ui-component-contract`,
20
+ `component-conformance-report`, and `component-behavior-report`.
21
+ - Generator policy diagnostics now describe topology entries as runtimes
22
+ (`runtimeId`) instead of components.
23
+ - Tighten boundary tests so old public DSL vocabulary is allowed only in
24
+ migration guidance and explicit rename diagnostics.
25
+
8
26
  ## 0.3.16 - 2026-05-03
9
27
 
10
28
  - Install package-backed generator dependencies during `topogram template check`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topogram/cli",
3
- "version": "0.3.55",
3
+ "version": "0.3.56",
4
4
  "description": "Topogram CLI for checking Topogram workspaces and generating app bundles.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -41,7 +41,7 @@ import { generateVanillaWebApp } from "./surfaces/web/vanilla.js";
41
41
  * @property {Record<string, any>} graph
42
42
  * @property {Record<string, any>} projection
43
43
  * @property {Record<string, any>} runtime
44
- * @property {Record<string, any>} component Internal runtime alias.
44
+ * @property {Record<string, any>} [component] Legacy runtime alias for existing generator packages.
45
45
  * @property {Record<string, any>|null} [topology]
46
46
  * @property {Record<string, any>} [contracts]
47
47
  * @property {Record<string, any>|null} [implementation]
@@ -88,7 +88,23 @@ function requiredManifest(generatorId) {
88
88
  * @returns {string}
89
89
  */
90
90
  function runtimeFor(context) {
91
- return context.runtime || context.component || {};
91
+ return normalizeRuntimeForGenerator(context.runtime || context.component || {});
92
+ }
93
+
94
+ /**
95
+ * Keep package-backed generator context canonical while preserving aliases for already-published adapters.
96
+ *
97
+ * @param {Record<string, any>} runtime
98
+ * @returns {Record<string, any>}
99
+ */
100
+ function normalizeRuntimeForGenerator(runtime) {
101
+ const apiRuntime = runtime.apiRuntime || runtime.apiComponent || null;
102
+ const databaseRuntime = runtime.databaseRuntime || runtime.databaseComponent || null;
103
+ return {
104
+ ...runtime,
105
+ ...(apiRuntime ? { apiRuntime, apiComponent: apiRuntime } : {}),
106
+ ...(databaseRuntime ? { databaseRuntime, databaseComponent: databaseRuntime } : {})
107
+ };
92
108
  }
93
109
 
94
110
  /**
@@ -108,7 +124,7 @@ function projectionIdFor(context) {
108
124
  function serverOptions(context, profile) {
109
125
  const projectionId = projectionIdFor(context);
110
126
  const runtime = runtimeFor(context);
111
- const dbProjectionId = runtime.databaseComponent?.projection?.id || context.options?.dbProjectionId;
127
+ const dbProjectionId = runtime.databaseRuntime?.projection?.id || runtime.databaseComponent?.projection?.id || context.options?.dbProjectionId;
112
128
  return {
113
129
  ...(context.options || {}),
114
130
  projectionId,
@@ -178,7 +194,7 @@ export const BUNDLED_GENERATOR_ADAPTERS = [
178
194
  manifest: requiredManifest("topogram/hono"),
179
195
  generate(context) {
180
196
  const runtime = runtimeFor(context);
181
- if (runtime && !runtime.databaseComponent) {
197
+ if (runtime && !runtime.databaseRuntime) {
182
198
  return fileResult(generateStatelessServer(context.graph, serverOptions(context, "hono")));
183
199
  }
184
200
  return fileResult(generateHonoServer(context.graph, serverOptions(context, "hono")));
@@ -188,7 +204,7 @@ export const BUNDLED_GENERATOR_ADAPTERS = [
188
204
  manifest: requiredManifest("topogram/express"),
189
205
  generate(context) {
190
206
  const runtime = runtimeFor(context);
191
- if (runtime && !runtime.databaseComponent) {
207
+ if (runtime && !runtime.databaseRuntime) {
192
208
  return fileResult(generateStatelessServer(context.graph, serverOptions(context, "express")));
193
209
  }
194
210
  return fileResult(generateExpressServer(context.graph, serverOptions(context, "express")));
@@ -413,7 +413,7 @@ function noopBundle(name, message) {
413
413
  export function generateAppBundle(graph, options = {}) {
414
414
  const plan = buildAppBundlePlan(graph, options);
415
415
  const topology = resolveRuntimeTopology(graph, options);
416
- const fullStack = topology.apiComponents.length > 0 && topology.webComponents.length > 0 && topology.dbComponents.length > 0;
416
+ const fullStack = topology.apiRuntimes.length > 0 && topology.webRuntimes.length > 0 && topology.dbRuntimes.length > 0;
417
417
  const envBundle = generateEnvironmentBundle(graph, { ...options, profileId: plan.profiles.environment });
418
418
  const deployBundle = fullStack
419
419
  ? generateDeploymentBundle(graph, { ...options, profileId: plan.profiles.deployment })
@@ -29,13 +29,13 @@ function runtimeReferenceFor(graph, options = {}) {
29
29
  function buildCompileCheckPlan(graph, options = {}) {
30
30
  const topology = resolveRuntimeTopology(graph, options);
31
31
  const { apiProjection, uiProjection, dbProjection } = getDefaultEnvironmentProjections(graph, options);
32
- const apiChecks = topology.apiComponents.map((component, index) => ({
32
+ const apiChecks = topology.apiRuntimes.map((component, index) => ({
33
33
  id: index === 0 ? "server_typecheck" : `server_typecheck_${component.id}`,
34
34
  cwd: topology.serviceDir(component),
35
35
  install: "npm install --no-audit --no-fund",
36
36
  command: "npm run check"
37
37
  }));
38
- const webChecks = topology.webComponents.flatMap((component, index) => [
38
+ const webChecks = topology.webRuntimes.flatMap((component, index) => [
39
39
  {
40
40
  id: index === 0 ? "web_typecheck" : `web_typecheck_${component.id}`,
41
41
  cwd: topology.webDir(component),
@@ -150,11 +150,11 @@ export function generateCompileCheckBundle(graph, options = {}) {
150
150
  "compile-check-plan.json": `${JSON.stringify(plan, null, 2)}\n`,
151
151
  "scripts/check.sh": renderCompileCheckScript(plan)
152
152
  };
153
- for (const component of topology.apiComponents) {
153
+ for (const component of topology.apiRuntimes) {
154
154
  const serverBundle = generateServerBundle(graph, component.projection.id, { ...options, component });
155
155
  mergeBundleFiles(files, topology.serviceDir(component), serverBundle);
156
156
  }
157
- for (const component of topology.webComponents) {
157
+ for (const component of topology.webRuntimes) {
158
158
  const webBundle = generateWebBundle(graph, component.projection.id, { ...options, component });
159
159
  mergeBundleFiles(files, topology.webDir(component), webBundle);
160
160
  }
@@ -262,19 +262,19 @@ export function generateDeploymentBundle(graph, options = {}) {
262
262
  files["railway.json"] = renderRailwayJson(plan);
263
263
  }
264
264
 
265
- for (const component of topology.apiComponents) {
265
+ for (const component of topology.apiRuntimes) {
266
266
  const serverBundle = generateServerBundle(graph, component.projection.id, { ...options, component });
267
267
  mergeNamedBundles(files, {
268
268
  [topology.serviceDir(component)]: serverBundle
269
269
  });
270
270
  }
271
- for (const component of topology.webComponents) {
271
+ for (const component of topology.webRuntimes) {
272
272
  const webBundle = generateWebBundle(graph, component.projection.id, { ...options, component });
273
273
  mergeNamedBundles(files, {
274
274
  [topology.webDir(component)]: webBundle
275
275
  });
276
276
  }
277
- for (const component of topology.dbComponents) {
277
+ for (const component of topology.dbRuntimes) {
278
278
  const dbBundle = generateDbBundle(graph, component.projection.id, { ...options, component });
279
279
  mergeNamedBundles(files, {
280
280
  [topology.dbDir(component)]: dbBundle
@@ -113,24 +113,24 @@ function buildEnvironmentPlan(graph, options = {}) {
113
113
  scripts: "scripts"
114
114
  },
115
115
  runtimes: {
116
- apis: topology.apiComponents.map((component) => ({
116
+ apis: topology.apiRuntimes.map((component) => ({
117
117
  id: component.id,
118
118
  projection: component.projection.id,
119
119
  port: component.port || ports.server,
120
120
  dir: topology.serviceDir(component),
121
121
  uses_database: component.database,
122
- databaseEnv: component.databaseComponent
123
- ? dbEnvVarsForComponent(component.databaseComponent, { primary: component.databaseComponent?.id === topology.primaryDb?.id })
122
+ databaseEnv: component.databaseRuntime
123
+ ? dbEnvVarsForComponent(component.databaseRuntime, { primary: component.databaseRuntime?.id === topology.primaryDb?.id })
124
124
  : null
125
125
  })),
126
- webs: topology.webComponents.map((component) => ({
126
+ webs: topology.webRuntimes.map((component) => ({
127
127
  id: component.id,
128
128
  projection: component.projection.id,
129
129
  port: component.port || ports.web,
130
130
  dir: topology.webDir(component),
131
131
  uses_api: component.api
132
132
  })),
133
- databases: topology.dbComponents.map((component) => ({
133
+ databases: topology.dbRuntimes.map((component) => ({
134
134
  id: component.id,
135
135
  projection: component.projection.id,
136
136
  type: component.projection.type,
@@ -330,7 +330,7 @@ function renderEnvironmentLoadEnvScript() {
330
330
  function renderEnvironmentBootstrapDbScript(plan) {
331
331
  const dbBootstrapLines = plan.runtimes.databases.map((component) => {
332
332
  const env = component.env;
333
- const runtimeApi = plan.runtimes.apis.find((apiComponent) => apiComponent.uses_database === component.id);
333
+ const runtimeApi = plan.runtimes.apis.find((apiRuntime) => apiRuntime.uses_database === component.id);
334
334
  const assignments = [
335
335
  `DATABASE_URL="\${${env.databaseUrl}:-}"`,
336
336
  `DATABASE_ADMIN_URL="\${${env.databaseAdminUrl}:-}"`,
@@ -393,12 +393,12 @@ function renderEnvironmentWebDevScript(plan, component = plan.runtimes.webs[0],
393
393
  if (!component) {
394
394
  return renderEnvAwareShellScript(['echo "No web runtimes are configured."']);
395
395
  }
396
- const apiComponent = plan.runtimes.apis.find((entry) => entry.id === component.uses_api) || plan.runtimes.apis[0];
396
+ const apiRuntime = plan.runtimes.apis.find((entry) => entry.id === component.uses_api) || plan.runtimes.apis[0];
397
397
  const guardPortsScript = options.componentScript ? '"$ROOT_DIR/scripts/guard-ports.mjs"' : '"$SCRIPT_DIR/guard-ports.mjs"';
398
398
  return renderEnvAwareShellScript([
399
399
  `node ${guardPortsScript} web`,
400
400
  "",
401
- ...(apiComponent ? [`export PUBLIC_TOPOGRAM_API_BASE_URL="\${PUBLIC_TOPOGRAM_API_BASE_URL:-http://localhost:\${${apiComponent.id.toUpperCase()}_PORT:-\${SERVER_PORT:-${apiComponent.port}}}}"`] : []),
401
+ ...(apiRuntime ? [`export PUBLIC_TOPOGRAM_API_BASE_URL="\${PUBLIC_TOPOGRAM_API_BASE_URL:-http://localhost:\${${apiRuntime.id.toUpperCase()}_PORT:-\${SERVER_PORT:-${apiRuntime.port}}}}"`] : []),
402
402
  `export TOPOGRAM_CORS_ORIGINS="\${TOPOGRAM_CORS_ORIGINS:-http://localhost:\${${component.id.toUpperCase()}_PORT:-\${WEB_PORT:-${component.port}}},http://127.0.0.1:\${${component.id.toUpperCase()}_PORT:-\${WEB_PORT:-${component.port}}}}"`,
403
403
  "",
404
404
  `cd "$ROOT_DIR/${component.dir}"`,
@@ -612,19 +612,19 @@ export function generateEnvironmentBundle(graph, options = {}) {
612
612
  files["scripts/docker-stack.sh"] = renderEnvironmentDockerStackScript();
613
613
  }
614
614
 
615
- for (const component of topology.apiComponents) {
615
+ for (const component of topology.apiRuntimes) {
616
616
  const serverBundle = generateServerBundle(graph, component.projection.id, { ...options, component });
617
617
  mergeNamedBundles(files, {
618
618
  [topology.serviceDir(component)]: serverBundle
619
619
  });
620
620
  }
621
- for (const component of topology.webComponents) {
621
+ for (const component of topology.webRuntimes) {
622
622
  const webBundle = generateWebBundle(graph, component.projection.id, { ...options, component });
623
623
  mergeNamedBundles(files, {
624
624
  [topology.webDir(component)]: webBundle
625
625
  });
626
626
  }
627
- for (const component of topology.dbComponents) {
627
+ for (const component of topology.dbRuntimes) {
628
628
  const dbBundle = generateDbBundle(graph, component.projection.id, { ...options, component });
629
629
  mergeNamedBundles(files, {
630
630
  [topology.dbDir(component)]: dbBundle
@@ -27,8 +27,10 @@ import { defaultProjectConfigForGraph, validateProjectConfig } from "../../proje
27
27
  * @property {string|null} [api]
28
28
  * @property {string|null} [database]
29
29
  * @property {Record<string, string>} [env]
30
- * @property {RuntimeComponent|null} [apiComponent]
31
- * @property {RuntimeComponent|null} [databaseComponent]
30
+ * @property {RuntimeComponent|null} [apiRuntime]
31
+ * @property {RuntimeComponent|null} [databaseRuntime]
32
+ * @property {RuntimeComponent|null} [apiComponent] Legacy adapter alias for apiRuntime.
33
+ * @property {RuntimeComponent|null} [databaseComponent] Legacy adapter alias for databaseRuntime.
32
34
  */
33
35
 
34
36
  /**
@@ -39,10 +41,13 @@ import { defaultProjectConfigForGraph, validateProjectConfig } from "../../proje
39
41
  * @typedef {Object} RuntimeTopology
40
42
  * @property {import("../../project-config.js").ProjectConfig} config
41
43
  * @property {RuntimeComponent[]} runtimes
42
- * @property {RuntimeComponent[]} components
43
- * @property {RuntimeComponent[]} apiComponents
44
- * @property {RuntimeComponent[]} webComponents
45
- * @property {RuntimeComponent[]} dbComponents
44
+ * @property {RuntimeComponent[]} apiRuntimes
45
+ * @property {RuntimeComponent[]} webRuntimes
46
+ * @property {RuntimeComponent[]} dbRuntimes
47
+ * @property {RuntimeComponent[]} components Legacy alias for runtimes.
48
+ * @property {RuntimeComponent[]} apiComponents Legacy alias for apiRuntimes.
49
+ * @property {RuntimeComponent[]} webComponents Legacy alias for webRuntimes.
50
+ * @property {RuntimeComponent[]} dbComponents Legacy alias for dbRuntimes.
46
51
  * @property {RuntimeComponent|null} primaryApi
47
52
  * @property {RuntimeComponent|null} primaryWeb
48
53
  * @property {RuntimeComponent|null} primaryDb
@@ -65,7 +70,8 @@ import { defaultProjectConfigForGraph, validateProjectConfig } from "../../proje
65
70
  * @property {string} [dbProjectionId]
66
71
  * @property {string} [configDir]
67
72
  * @property {string} [projectRoot]
68
- * @property {RuntimeComponent} [component]
73
+ * @property {RuntimeComponent} [runtime]
74
+ * @property {RuntimeComponent} [component] Legacy alias for runtime.
69
75
  */
70
76
 
71
77
  /**
@@ -327,14 +333,15 @@ export function getDefaultEnvironmentProjections(graph, options = {}) {
327
333
  */
328
334
  export function generateServerBundle(graph, projectionId, options = {}) {
329
335
  const topology = resolveRuntimeTopology(graph, options);
330
- const component = options.component || topology.apiComponents.find((entry) => entry.projection.id === projectionId);
331
- if (!component) {
332
- throw new Error(`No api topology component found for projection '${projectionId}'`);
336
+ const runtime = options.runtime || options.component || topology.apiRuntimes.find((entry) => entry.projection.id === projectionId);
337
+ if (!runtime) {
338
+ throw new Error(`No api runtime found for projection '${projectionId}'`);
333
339
  }
334
340
  return generateWithComponentGenerator({
335
341
  graph,
336
- projection: component.projection,
337
- component,
342
+ projection: runtime.projection,
343
+ runtime,
344
+ component: runtime,
338
345
  topology,
339
346
  implementation: options.implementation || null,
340
347
  options: { ...options, projectionId }
@@ -349,14 +356,15 @@ export function generateServerBundle(graph, projectionId, options = {}) {
349
356
  */
350
357
  export function generateWebBundle(graph, projectionId, options = {}) {
351
358
  const topology = resolveRuntimeTopology(graph, options);
352
- const component = options.component || topology.webComponents.find((entry) => entry.projection.id === projectionId);
353
- if (!component) {
354
- throw new Error(`No web topology component found for projection '${projectionId}'`);
359
+ const runtime = options.runtime || options.component || topology.webRuntimes.find((entry) => entry.projection.id === projectionId);
360
+ if (!runtime) {
361
+ throw new Error(`No web runtime found for projection '${projectionId}'`);
355
362
  }
356
363
  return generateWithComponentGenerator({
357
364
  graph,
358
- projection: component.projection,
359
- component,
365
+ projection: runtime.projection,
366
+ runtime,
367
+ component: runtime,
360
368
  topology,
361
369
  implementation: options.implementation || null,
362
370
  options: { ...options, projectionId }
@@ -371,14 +379,15 @@ export function generateWebBundle(graph, projectionId, options = {}) {
371
379
  */
372
380
  export function generateDbBundle(graph, projectionId, options = {}) {
373
381
  const topology = resolveRuntimeTopology(graph, options);
374
- const component = options.component || topology.dbComponents.find((entry) => entry.projection.id === projectionId);
375
- if (!component) {
376
- throw new Error(`No database topology component found for projection '${projectionId}'`);
382
+ const runtime = options.runtime || options.component || topology.dbRuntimes.find((entry) => entry.projection.id === projectionId);
383
+ if (!runtime) {
384
+ throw new Error(`No database runtime found for projection '${projectionId}'`);
377
385
  }
378
386
  return generateWithComponentGenerator({
379
387
  graph,
380
388
  projection: getProjection(graph, projectionId),
381
- component,
389
+ runtime,
390
+ component: runtime,
382
391
  topology,
383
392
  implementation: options.implementation || null,
384
393
  options: { ...options, projectionId }
@@ -438,10 +447,12 @@ function decorateRuntimes(graph, config) {
438
447
  const byId = new Map(runtimes.map((runtime) => [runtime.id, runtime]));
439
448
  for (const runtime of runtimes) {
440
449
  if (runtime.kind === "api_service" && runtime.database) {
441
- runtime.databaseComponent = byId.get(runtime.database) || null;
450
+ runtime.databaseRuntime = byId.get(runtime.database) || null;
451
+ runtime.databaseComponent = runtime.databaseRuntime;
442
452
  }
443
453
  if (runtime.kind === "web_surface" && runtime.api) {
444
- runtime.apiComponent = byId.get(runtime.api) || null;
454
+ runtime.apiRuntime = byId.get(runtime.api) || null;
455
+ runtime.apiComponent = runtime.apiRuntime;
445
456
  }
446
457
  }
447
458
  return runtimes;
@@ -462,20 +473,23 @@ export function resolveRuntimeTopology(graph, options = {}) {
462
473
  throw new Error(validation.errors.map((error) => error.message).join("\n"));
463
474
  }
464
475
  const runtimes = decorateRuntimes(graph, config);
465
- const apiComponents = runtimes.filter((runtime) => runtime.kind === "api_service");
466
- const webComponents = runtimes.filter((runtime) => runtime.kind === "web_surface");
467
- const dbComponents = runtimes.filter((runtime) => runtime.kind === "database");
468
- const primaryApi = apiComponents[0] || null;
469
- const primaryWeb = webComponents[0] || null;
470
- const primaryDb = primaryApi?.databaseComponent || dbComponents[0] || null;
476
+ const apiRuntimes = runtimes.filter((runtime) => runtime.kind === "api_service");
477
+ const webRuntimes = runtimes.filter((runtime) => runtime.kind === "web_surface");
478
+ const dbRuntimes = runtimes.filter((runtime) => runtime.kind === "database");
479
+ const primaryApi = apiRuntimes[0] || null;
480
+ const primaryWeb = webRuntimes[0] || null;
481
+ const primaryDb = primaryApi?.databaseRuntime || dbRuntimes[0] || null;
471
482
 
472
483
  return {
473
484
  config,
474
485
  runtimes,
475
486
  components: runtimes,
476
- apiComponents,
477
- webComponents,
478
- dbComponents,
487
+ apiRuntimes,
488
+ webRuntimes,
489
+ dbRuntimes,
490
+ apiComponents: apiRuntimes,
491
+ webComponents: webRuntimes,
492
+ dbComponents: dbRuntimes,
479
493
  primaryApi,
480
494
  primaryWeb,
481
495
  primaryDb,
@@ -57,11 +57,13 @@ export function generateDbTarget(target, graph, options = {}) {
57
57
  : generatePostgresDbLifecyclePlan(graph, options);
58
58
  }
59
59
  if (target === "db-lifecycle-bundle") {
60
- if (options.component?.generator?.id) {
60
+ const runtime = options.runtime || options.component;
61
+ if (runtime?.generator?.id) {
61
62
  return generateWithComponentGenerator({
62
63
  graph,
63
- projection: options.component.projection,
64
- component: options.component,
64
+ projection: runtime.projection,
65
+ runtime,
66
+ component: runtime,
65
67
  topology: options.topology || null,
66
68
  implementation: options.implementation || null,
67
69
  options
@@ -8,11 +8,13 @@ export function generateAppTarget(target, graph, options = {}) {
8
8
  return generateBackendTarget(target, graph, options);
9
9
  }
10
10
  if (target === "swiftui-app") {
11
- if (options.component?.generator?.id) {
11
+ const runtime = options.runtime || options.component;
12
+ if (runtime?.generator?.id) {
12
13
  return generateWithComponentGenerator({
13
14
  graph,
14
- projection: options.component.projection,
15
- component: options.component,
15
+ projection: runtime.projection,
16
+ runtime,
17
+ component: runtime,
16
18
  topology: options.topology || null,
17
19
  implementation: options.implementation || null,
18
20
  options
@@ -12,11 +12,13 @@ export function generateBackendTarget(target, graph, options = {}) {
12
12
  return generatePersistenceScaffold(graph, options);
13
13
  }
14
14
  if (target === "hono-server") {
15
- if (options.component?.generator?.id) {
15
+ const runtime = options.runtime || options.component;
16
+ if (runtime?.generator?.id) {
16
17
  return generateWithComponentGenerator({
17
18
  graph,
18
- projection: options.component.projection,
19
- component: options.component,
19
+ projection: runtime.projection,
20
+ runtime,
21
+ component: runtime,
20
22
  topology: options.topology || null,
21
23
  implementation: options.implementation || null,
22
24
  options
@@ -25,11 +27,13 @@ export function generateBackendTarget(target, graph, options = {}) {
25
27
  return generateHonoServer(graph, options);
26
28
  }
27
29
  if (target === "express-server") {
28
- if (options.component?.generator?.id) {
30
+ const runtime = options.runtime || options.component;
31
+ if (runtime?.generator?.id) {
29
32
  return generateWithComponentGenerator({
30
33
  graph,
31
- projection: options.component.projection,
32
- component: options.component,
34
+ projection: runtime.projection,
35
+ runtime,
36
+ component: runtime,
33
37
  topology: options.topology || null,
34
38
  implementation: options.implementation || null,
35
39
  options
@@ -15,17 +15,19 @@ import {
15
15
 
16
16
  export function generateWebApp(graph, options = {}) {
17
17
  const projection = getProjection(graph, options.projectionId);
18
- if (options.component?.generator?.id) {
18
+ const runtime = options.runtime || options.component;
19
+ if (runtime?.generator?.id) {
19
20
  return generateWithComponentGenerator({
20
21
  graph,
21
22
  projection,
22
- component: options.component,
23
+ runtime,
24
+ component: runtime,
23
25
  topology: options.topology || null,
24
26
  implementation: options.implementation || null,
25
27
  options: { ...options, projectionId: projection.id }
26
28
  }).files;
27
29
  }
28
- const profile = generatorProfile(options.component?.generator?.id, null) || generatorDefaultsMap(projection).profile || "sveltekit";
30
+ const profile = generatorProfile(runtime?.generator?.id, null) || generatorDefaultsMap(projection).profile || "sveltekit";
29
31
  if (profile === "vanilla") {
30
32
  return generateVanillaWebApp(graph, options);
31
33
  }