@topogram/cli 0.3.48 → 0.3.50
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 +9 -8
- package/README.md +4 -4
- package/package.json +1 -1
- package/src/generator/context/slice.js +131 -0
- package/src/generator/registry.js +6 -3
- package/src/generator/runtime/app-bundle.js +8 -7
- package/src/generator/runtime/compile-check.js +3 -2
- package/src/generator/runtime/environment.js +8 -7
- package/src/generator/runtime/runtime-check.js +5 -5
- package/src/generator/runtime/shared.js +9 -0
- package/src/generator/runtime/smoke.js +2 -1
- package/src/generator/surfaces/shared.js +2 -1
- package/src/generator/surfaces/web/design-intent.js +308 -0
- package/src/generator/surfaces/web/react-components.js +3 -7
- package/src/generator/surfaces/web/react.js +35 -28
- package/src/generator/surfaces/web/sveltekit-components.js +3 -7
- package/src/generator/surfaces/web/sveltekit.js +28 -23
- package/src/generator/surfaces/web/vanilla.js +102 -36
- package/src/import/core/runner.js +63 -20
- package/src/realization/ui/build-ui-shared-realization.js +48 -16
- package/src/realization/ui/build-web-realization.js +5 -38
- package/src/resolver/index.js +13 -0
- package/src/ui/taxonomy.js +201 -0
- package/src/validator/index.js +124 -4
- package/src/validator/kinds.js +21 -52
package/CHANGELOG.md
CHANGED
|
@@ -53,11 +53,12 @@
|
|
|
53
53
|
## 0.3.11 - 2026-05-01
|
|
54
54
|
|
|
55
55
|
- Add `domain` statement kind for grouping the spec by business slice
|
|
56
|
-
(
|
|
57
|
-
`name`, `description`, `status`.
|
|
58
|
-
`
|
|
59
|
-
prefix, scope-list shapes,
|
|
60
|
-
refs, and parent-domain
|
|
56
|
+
(order fulfillment, billing, support, reporting, etc.). Identifier
|
|
57
|
+
prefix `dom_`. Required fields: `name`, `description`, `status`.
|
|
58
|
+
Optional: `in_scope`, `out_of_scope`, `owners`, `parent_domain`,
|
|
59
|
+
`aliases`. Validator enforces identifier prefix, scope-list shapes,
|
|
60
|
+
owner refs (`actor`|`role`), parent_domain refs, and parent-domain
|
|
61
|
+
cycle detection.
|
|
61
62
|
- Add optional singular `domain` field on `capability`, `entity`, `rule`,
|
|
62
63
|
`verification`, `orchestration`, `operation`, and `decision`. Cross-kind
|
|
63
64
|
validator hard-errors on unknown ids and wrong-kind references.
|
|
@@ -83,9 +84,9 @@
|
|
|
83
84
|
with the `domain` row and the optional-field paragraph;
|
|
84
85
|
`docs/topogram-workspace-layout.md` appends a "Domain organization"
|
|
85
86
|
subsection.
|
|
86
|
-
- New fixture
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
- New multi-domain fixture (3 domains, 10 capabilities, 12 entities, 4
|
|
88
|
+
cross-platform projections) and golden tests at
|
|
89
|
+
`engine/tests/active/domain-kind.test.js`.
|
|
89
90
|
|
|
90
91
|
### SDLC layer (Phase 2)
|
|
91
92
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ The active product workflow is authoring-to-generated-app. Engine development sh
|
|
|
6
6
|
|
|
7
7
|
## Package Shape
|
|
8
8
|
|
|
9
|
-
The engine is the publishable
|
|
9
|
+
The engine is the publishable CLI package:
|
|
10
10
|
|
|
11
11
|
```json
|
|
12
12
|
{
|
|
@@ -17,7 +17,7 @@ The engine is the publishable private CLI package:
|
|
|
17
17
|
}
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
This lets source checkouts and
|
|
20
|
+
This lets source checkouts and package consumers call:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
topogram new ../my-app
|
|
@@ -111,7 +111,7 @@ topogram new ../todo-demo --template @topogram/template-todo
|
|
|
111
111
|
topogram new ../todo-demo --template todo
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
-
Catalog aliases resolve through the
|
|
114
|
+
Catalog aliases resolve through the public catalog index at
|
|
115
115
|
`github:attebury/topograms/topograms.catalog.json`. The catalog is package
|
|
116
116
|
backed; executable starter content still lives in template packages. Use
|
|
117
117
|
`topogram catalog show <id>` to inspect an entry and get the correct `new` or
|
|
@@ -131,7 +131,7 @@ template update metadata while keeping normal check/generate behavior.
|
|
|
131
131
|
Do not create generated projects under `engine/`. The CLI refuses paths inside the engine directory.
|
|
132
132
|
|
|
133
133
|
Template pack authoring and trust policy are documented in `../docs/template-authoring.md`.
|
|
134
|
-
Catalog layout and private access are documented in `../docs/catalog.md`.
|
|
134
|
+
Catalog layout and optional private-source access are documented in `../docs/catalog.md`.
|
|
135
135
|
Projects created from executable templates include `.topogram-template-trust.json`;
|
|
136
136
|
regenerate it with `topogram trust template` after reviewing copied
|
|
137
137
|
`implementation/` code. Use `topogram template status` for the lifecycle
|
package/package.json
CHANGED
|
@@ -194,6 +194,7 @@ function projectionSlice(graph, projectionId) {
|
|
|
194
194
|
verification_targets: recommendedVerificationTargets(graph, [projectionId, ...capabilities, ...entities, ...shapes, ...components], {
|
|
195
195
|
rationale: "Projection slices affect generated contract and runtime surfaces, so verification should follow the projection closure."
|
|
196
196
|
}),
|
|
197
|
+
ui_agent_packet: uiAgentPacketForProjection(graph, projection),
|
|
197
198
|
write_scope: buildDefaultWriteScope(),
|
|
198
199
|
review_boundary: projection.reviewBoundary || {
|
|
199
200
|
automation_class: "review_required",
|
|
@@ -286,6 +287,7 @@ function componentSlice(graph, componentId) {
|
|
|
286
287
|
verification_targets: recommendedVerificationTargets(graph, verificationScope, {
|
|
287
288
|
rationale: "Component changes affect every related projection — verification should follow the component contract closure."
|
|
288
289
|
}),
|
|
290
|
+
ui_agent_packet: uiAgentPacketForComponent(graph, component, projections),
|
|
289
291
|
write_scope: buildDefaultWriteScope(),
|
|
290
292
|
review_boundary: {
|
|
291
293
|
automation_class: "review_required",
|
|
@@ -331,6 +333,135 @@ function componentDependencyKind(dependency) {
|
|
|
331
333
|
return prefix || null;
|
|
332
334
|
}
|
|
333
335
|
|
|
336
|
+
function uiAgentPacketForProjection(graph, projection) {
|
|
337
|
+
if (!String(projection.platform || "").startsWith("ui_")) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
const sharedProjection = projection.platform === "ui_shared"
|
|
341
|
+
? projection
|
|
342
|
+
: sharedUiProjectionFor(graph, projection);
|
|
343
|
+
const ownerProjection = sharedProjection || projection;
|
|
344
|
+
return {
|
|
345
|
+
type: "ui_agent_packet",
|
|
346
|
+
version: 1,
|
|
347
|
+
ownership: {
|
|
348
|
+
componentPlacement: "ui_shared",
|
|
349
|
+
designIntent: "ui_shared",
|
|
350
|
+
concreteSurfaceOwns: ["routes", "surface_hints"]
|
|
351
|
+
},
|
|
352
|
+
sharedProjection: sharedProjection
|
|
353
|
+
? {
|
|
354
|
+
id: sharedProjection.id,
|
|
355
|
+
name: sharedProjection.name || sharedProjection.id
|
|
356
|
+
}
|
|
357
|
+
: null,
|
|
358
|
+
screens: (ownerProjection.uiScreens || []).map((screen) => ({
|
|
359
|
+
id: screen.id,
|
|
360
|
+
kind: screen.kind,
|
|
361
|
+
title: screen.title || screen.id
|
|
362
|
+
})),
|
|
363
|
+
routes: (projection.uiRoutes || []).map((route) => ({
|
|
364
|
+
screenId: route.screenId,
|
|
365
|
+
path: route.path
|
|
366
|
+
})),
|
|
367
|
+
components: (ownerProjection.uiComponents || []).map((usage) => componentUsagePacket(usage)),
|
|
368
|
+
design: designIntentPacket(ownerProjection),
|
|
369
|
+
requiredGates: uiRequiredGates(projection.id)
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function uiAgentPacketForComponent(graph, component, projectionIds) {
|
|
374
|
+
const projectionSet = new Set(projectionIds);
|
|
375
|
+
const sourceUsages = [];
|
|
376
|
+
for (const projection of graph.byKind.projection || []) {
|
|
377
|
+
for (const usage of projection.uiComponents || []) {
|
|
378
|
+
if (usage.component?.id !== component.id) continue;
|
|
379
|
+
sourceUsages.push({
|
|
380
|
+
projection: {
|
|
381
|
+
id: projection.id,
|
|
382
|
+
platform: projection.platform,
|
|
383
|
+
ownership: projection.platform === "ui_shared" ? "owner" : "concrete"
|
|
384
|
+
},
|
|
385
|
+
usage: componentUsagePacket(usage),
|
|
386
|
+
design: designIntentPacket(projection)
|
|
387
|
+
});
|
|
388
|
+
projectionSet.add(projection.id);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
type: "ui_agent_packet",
|
|
394
|
+
version: 1,
|
|
395
|
+
ownership: {
|
|
396
|
+
componentContract: "component",
|
|
397
|
+
componentPlacement: "ui_shared",
|
|
398
|
+
concreteSurfacesInherit: true
|
|
399
|
+
},
|
|
400
|
+
component: {
|
|
401
|
+
id: component.id,
|
|
402
|
+
name: component.name || component.id,
|
|
403
|
+
category: component.category || null,
|
|
404
|
+
patterns: component.componentContract?.patterns || [],
|
|
405
|
+
regions: component.componentContract?.regions || [],
|
|
406
|
+
behaviors: component.componentContract?.behaviors || []
|
|
407
|
+
},
|
|
408
|
+
sourceUsages,
|
|
409
|
+
inheritedBy: [...projectionSet]
|
|
410
|
+
.filter((projectionId) => !sourceUsages.some((entry) => entry.projection.id === projectionId))
|
|
411
|
+
.sort(),
|
|
412
|
+
requiredGates: uiRequiredGates(null, component.id)
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function sharedUiProjectionFor(graph, projection) {
|
|
417
|
+
for (const reference of projection.realizes || []) {
|
|
418
|
+
const candidate = (graph.byKind.projection || []).find((entry) => entry.id === reference.id);
|
|
419
|
+
if (candidate?.platform === "ui_shared") {
|
|
420
|
+
return candidate;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function componentUsagePacket(usage) {
|
|
427
|
+
return {
|
|
428
|
+
screenId: usage.screenId || null,
|
|
429
|
+
region: usage.region || null,
|
|
430
|
+
componentId: usage.component?.id || null,
|
|
431
|
+
dataBindings: (usage.dataBindings || []).map((binding) => ({
|
|
432
|
+
prop: binding.prop || null,
|
|
433
|
+
source: binding.source?.id || binding.source || null
|
|
434
|
+
})),
|
|
435
|
+
eventBindings: (usage.eventBindings || []).map((binding) => ({
|
|
436
|
+
event: binding.event || null,
|
|
437
|
+
action: binding.action || null,
|
|
438
|
+
target: binding.target?.id || binding.target || null
|
|
439
|
+
}))
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function designIntentPacket(projection) {
|
|
444
|
+
return (projection.uiDesign || []).map((entry) => ({
|
|
445
|
+
key: entry.key,
|
|
446
|
+
role: entry.role,
|
|
447
|
+
value: entry.value
|
|
448
|
+
}));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function uiRequiredGates(projectionId = null, componentId = null) {
|
|
452
|
+
return [
|
|
453
|
+
{ command: "topogram check", reason: "Validate shared UI ownership, taxonomy, references, and topology." },
|
|
454
|
+
{
|
|
455
|
+
command: `topogram component check${projectionId ? ` --projection ${projectionId}` : ""}${componentId ? ` --component ${componentId}` : ""}`,
|
|
456
|
+
reason: "Validate component placement, props, events, regions, and patterns."
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
command: `topogram component behavior${projectionId ? ` --projection ${projectionId}` : ""}${componentId ? ` --component ${componentId}` : ""}`,
|
|
460
|
+
reason: "Inspect behavior realizations and partial bindings before code changes."
|
|
461
|
+
}
|
|
462
|
+
];
|
|
463
|
+
}
|
|
464
|
+
|
|
334
465
|
function journeySlice(graph, journeyId) {
|
|
335
466
|
const journey = getJourneyDoc(graph, journeyId);
|
|
336
467
|
const capabilities = [...(journey.relatedCapabilities || [])].sort();
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
+
import { UI_GENERATOR_RENDERED_COMPONENT_PATTERNS } from "../ui/taxonomy.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @typedef {Object} GeneratorManifest
|
|
@@ -23,6 +24,8 @@ import { createRequire } from "node:module";
|
|
|
23
24
|
* @property {boolean} [planned]
|
|
24
25
|
*/
|
|
25
26
|
|
|
27
|
+
const RENDERED_COMPONENT_PATTERNS = [...UI_GENERATOR_RENDERED_COMPONENT_PATTERNS];
|
|
28
|
+
|
|
26
29
|
/** @type {GeneratorManifest[]} */
|
|
27
30
|
export const GENERATOR_MANIFESTS = [
|
|
28
31
|
{
|
|
@@ -60,7 +63,7 @@ export const GENERATOR_MANIFESTS = [
|
|
|
60
63
|
inputs: ["ui-web-contract"],
|
|
61
64
|
outputs: ["web-app", "generation-coverage"],
|
|
62
65
|
stack: { runtime: "browser", framework: "vanilla", language: "javascript" },
|
|
63
|
-
capabilities: { routes: true, components: false, coverage:
|
|
66
|
+
capabilities: { routes: true, components: false, coverage: true },
|
|
64
67
|
componentSupport: { patterns: [], behaviors: [], unsupported: "contract-only" },
|
|
65
68
|
source: "bundled",
|
|
66
69
|
profile: "vanilla"
|
|
@@ -76,7 +79,7 @@ export const GENERATOR_MANIFESTS = [
|
|
|
76
79
|
stack: { runtime: "node", framework: "sveltekit", language: "typescript" },
|
|
77
80
|
capabilities: { routes: true, components: true, coverage: true },
|
|
78
81
|
componentSupport: {
|
|
79
|
-
patterns:
|
|
82
|
+
patterns: RENDERED_COMPONENT_PATTERNS,
|
|
80
83
|
behaviors: ["selection", "sorting", "filtering", "search", "pagination", "bulk_action", "optimistic_update"],
|
|
81
84
|
unsupported: "warning"
|
|
82
85
|
},
|
|
@@ -94,7 +97,7 @@ export const GENERATOR_MANIFESTS = [
|
|
|
94
97
|
stack: { runtime: "browser", framework: "react", language: "typescript" },
|
|
95
98
|
capabilities: { routes: true, components: true, coverage: true },
|
|
96
99
|
componentSupport: {
|
|
97
|
-
patterns:
|
|
100
|
+
patterns: RENDERED_COMPONENT_PATTERNS,
|
|
98
101
|
behaviors: ["selection", "sorting", "filtering", "search", "pagination", "bulk_action", "optimistic_update"],
|
|
99
102
|
unsupported: "warning"
|
|
100
103
|
},
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
buildVerificationSummary,
|
|
18
18
|
getDefaultEnvironmentProjections,
|
|
19
19
|
resolveRuntimeTopology,
|
|
20
|
+
runtimeDemoUserId,
|
|
20
21
|
runtimePorts,
|
|
21
22
|
runtimeUrls
|
|
22
23
|
} from "./shared.js";
|
|
@@ -104,7 +105,7 @@ function buildAppBundlePlan(graph, options = {}) {
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
function renderAppBundleEnvExample(plan) {
|
|
107
|
-
const
|
|
108
|
+
const demoUserId = runtimeDemoUserId(plan.runtimeReference);
|
|
108
109
|
const databaseName = plan.runtimeReference.environment.databaseName || "topogram_app";
|
|
109
110
|
const topology = {
|
|
110
111
|
primaryApi: { port: plan.topology.components.find((component) => component.type === "api")?.port },
|
|
@@ -118,8 +119,8 @@ TOPOGRAM_ENVIRONMENT_PROFILE=${plan.profiles.environment}
|
|
|
118
119
|
TOPOGRAM_DEPLOY_PROFILE=${plan.profiles.deployment}
|
|
119
120
|
|
|
120
121
|
# Local runtime defaults
|
|
121
|
-
${plan.projections.api ? `SERVER_PORT=${ports.server}\n` : ""}${plan.projections.ui ? `WEB_PORT=${ports.web}\n` : ""}${plan.projections.api && plan.projections.ui ? `PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}\n` : ""}PUBLIC_TOPOGRAM_DEMO_USER_ID=${
|
|
122
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
122
|
+
${plan.projections.api ? `SERVER_PORT=${ports.server}\n` : ""}${plan.projections.ui ? `WEB_PORT=${ports.web}\n` : ""}${plan.projections.api && plan.projections.ui ? `PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}\n` : ""}PUBLIC_TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
123
|
+
TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
123
124
|
${plan.runtimeReference.environment.envExample || ""}
|
|
124
125
|
|
|
125
126
|
# Smoke-test defaults
|
|
@@ -135,8 +136,8 @@ SERVER_PORT=${ports.server}
|
|
|
135
136
|
WEB_PORT=${ports.web}
|
|
136
137
|
DATABASE_URL=file:./var/${databaseName}.sqlite
|
|
137
138
|
PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}
|
|
138
|
-
PUBLIC_TOPOGRAM_DEMO_USER_ID=${
|
|
139
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
139
|
+
PUBLIC_TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
140
|
+
TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
140
141
|
${plan.runtimeReference.environment.envExample || ""}
|
|
141
142
|
TOPOGRAM_SEED_DEMO=true
|
|
142
143
|
|
|
@@ -159,8 +160,8 @@ POSTGRES_PASSWORD=postgres
|
|
|
159
160
|
DATABASE_URL=postgresql://\${POSTGRES_USER}@localhost:5432/${databaseName}
|
|
160
161
|
DATABASE_ADMIN_URL=postgresql://\${POSTGRES_USER}@localhost:5432/postgres
|
|
161
162
|
PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}
|
|
162
|
-
PUBLIC_TOPOGRAM_DEMO_USER_ID=${
|
|
163
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
163
|
+
PUBLIC_TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
164
|
+
TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
164
165
|
${plan.runtimeReference.environment.envExample || ""}
|
|
165
166
|
TOPOGRAM_SEED_DEMO=true
|
|
166
167
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
generateWebBundle,
|
|
4
4
|
getDefaultEnvironmentProjections,
|
|
5
5
|
resolveRuntimeTopology,
|
|
6
|
+
runtimeDemoUserId,
|
|
6
7
|
runtimeUrls
|
|
7
8
|
} from "./shared.js";
|
|
8
9
|
import { getExampleImplementation } from "../../example-implementation.js";
|
|
@@ -75,13 +76,13 @@ function renderCompileCheckEnvExample(graph, options = {}) {
|
|
|
75
76
|
if (dbProjection?.platform === "db_sqlite") {
|
|
76
77
|
return `DATABASE_URL=./var/${runtimeReference.environment.databaseName || "topogram_app"}.sqlite
|
|
77
78
|
PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}
|
|
78
|
-
PUBLIC_TOPOGRAM_DEMO_USER_ID=${runtimeReference
|
|
79
|
+
PUBLIC_TOPOGRAM_DEMO_USER_ID=${runtimeDemoUserId(runtimeReference)}
|
|
79
80
|
${runtimeReference.environment.envExample || ""}
|
|
80
81
|
`;
|
|
81
82
|
}
|
|
82
83
|
return `DATABASE_URL=postgresql://postgres:postgres@localhost:5432/${runtimeReference.environment.databaseName || "topogram_app"}?schema=public
|
|
83
84
|
PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}
|
|
84
|
-
PUBLIC_TOPOGRAM_DEMO_USER_ID=${runtimeReference
|
|
85
|
+
PUBLIC_TOPOGRAM_DEMO_USER_ID=${runtimeDemoUserId(runtimeReference)}
|
|
85
86
|
${runtimeReference.environment.envExample || ""}
|
|
86
87
|
`;
|
|
87
88
|
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
dbEnvVarsForComponent,
|
|
8
8
|
getDefaultEnvironmentProjections,
|
|
9
9
|
resolveRuntimeTopology,
|
|
10
|
+
runtimeDemoUserId,
|
|
10
11
|
runtimePorts,
|
|
11
12
|
runtimeUrls
|
|
12
13
|
} from "./shared.js";
|
|
@@ -158,7 +159,7 @@ function buildEnvironmentPlan(graph, options = {}) {
|
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
function renderEnvironmentEnvExample(plan) {
|
|
161
|
-
const
|
|
162
|
+
const demoUserId = runtimeDemoUserId(plan.runtimeReference);
|
|
162
163
|
const databaseName = plan.runtimeReference.environment.databaseName || "topogram_app";
|
|
163
164
|
const urls = runtimeUrls(plan.runtimeReference, {
|
|
164
165
|
primaryApi: { port: plan.ports.server },
|
|
@@ -184,8 +185,8 @@ function renderEnvironmentEnvExample(plan) {
|
|
|
184
185
|
TOPOGRAM_ENVIRONMENT_PROFILE=${plan.environment.profile}
|
|
185
186
|
|
|
186
187
|
# Local stack ports
|
|
187
|
-
${plan.components.apis.length ? `SERVER_PORT=${plan.ports.server}\n` : ""}${plan.components.webs.length ? `WEB_PORT=${plan.ports.web}\n` : ""}${plan.components.webs.length && plan.components.apis.length ? `PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}\n` : ""}${plan.components.webs.length ? `TOPOGRAM_CORS_ORIGINS=${urls.web},http://127.0.0.1:${plan.ports.web}\n` : ""}PUBLIC_TOPOGRAM_DEMO_USER_ID=${
|
|
188
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
188
|
+
${plan.components.apis.length ? `SERVER_PORT=${plan.ports.server}\n` : ""}${plan.components.webs.length ? `WEB_PORT=${plan.ports.web}\n` : ""}${plan.components.webs.length && plan.components.apis.length ? `PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}\n` : ""}${plan.components.webs.length ? `TOPOGRAM_CORS_ORIGINS=${urls.web},http://127.0.0.1:${plan.ports.web}\n` : ""}PUBLIC_TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
189
|
+
TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
189
190
|
${plan.runtimeReference.environment.envExample || ""}
|
|
190
191
|
TOPOGRAM_SEED_DEMO=true
|
|
191
192
|
`;
|
|
@@ -204,8 +205,8 @@ WEB_PORT=${plan.ports.web}
|
|
|
204
205
|
DATABASE_URL=file:./var/${databaseName}.sqlite
|
|
205
206
|
${extraDatabaseLines ? `${extraDatabaseLines}\n` : ""}PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}
|
|
206
207
|
TOPOGRAM_CORS_ORIGINS=${urls.web},http://127.0.0.1:${plan.ports.web}
|
|
207
|
-
PUBLIC_TOPOGRAM_DEMO_USER_ID=${
|
|
208
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
208
|
+
PUBLIC_TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
209
|
+
TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
209
210
|
${plan.runtimeReference.environment.envExample || ""}
|
|
210
211
|
TOPOGRAM_SEED_DEMO=true
|
|
211
212
|
`;
|
|
@@ -229,8 +230,8 @@ DATABASE_URL=postgresql://\${POSTGRES_USER}@localhost:${plan.ports.database || 5
|
|
|
229
230
|
DATABASE_ADMIN_URL=postgresql://\${POSTGRES_USER}@localhost:${plan.ports.database || 5432}/postgres
|
|
230
231
|
${extraDatabaseLines ? `${extraDatabaseLines}\n` : ""}PUBLIC_TOPOGRAM_API_BASE_URL=${urls.api}
|
|
231
232
|
TOPOGRAM_CORS_ORIGINS=${urls.web},http://127.0.0.1:${plan.ports.web}
|
|
232
|
-
PUBLIC_TOPOGRAM_DEMO_USER_ID=${
|
|
233
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
233
|
+
PUBLIC_TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
234
|
+
TOPOGRAM_DEMO_USER_ID=${demoUserId}
|
|
234
235
|
${plan.runtimeReference.environment.envExample || ""}
|
|
235
236
|
TOPOGRAM_SEED_DEMO=true
|
|
236
237
|
`;
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
buildVerificationSummary,
|
|
4
4
|
getDefaultEnvironmentProjections,
|
|
5
5
|
resolveRuntimeTopology,
|
|
6
|
+
runtimeDemoUserId,
|
|
6
7
|
selectChecksByVerification,
|
|
7
8
|
runtimePorts,
|
|
8
9
|
runtimeUrls
|
|
@@ -74,11 +75,10 @@ function buildRuntimeCheckPlan(graph, options = {}) {
|
|
|
74
75
|
|
|
75
76
|
function renderRuntimeCheckEnvExample(graph, options = {}) {
|
|
76
77
|
const runtimeReference = getExampleImplementation(graph, options).runtime.reference;
|
|
77
|
-
const demo = runtimeReference.demoEnv;
|
|
78
78
|
const urls = runtimeUrls(runtimeReference, resolveRuntimeTopology(graph, options));
|
|
79
79
|
return `TOPOGRAM_API_BASE_URL=${urls.api}
|
|
80
80
|
TOPOGRAM_WEB_BASE_URL=${urls.web}
|
|
81
|
-
TOPOGRAM_DEMO_USER_ID=${
|
|
81
|
+
TOPOGRAM_DEMO_USER_ID=${runtimeDemoUserId(runtimeReference)}
|
|
82
82
|
${runtimeReference.environment.envExample || ""}
|
|
83
83
|
`;
|
|
84
84
|
}
|
|
@@ -166,9 +166,9 @@ function envValue(name) {
|
|
|
166
166
|
const fallbackMap = {
|
|
167
167
|
TOPOGRAM_API_BASE_URL: process.env.PUBLIC_TOPOGRAM_API_BASE_URL || "http://localhost:${ports.server}",
|
|
168
168
|
TOPOGRAM_WEB_BASE_URL: process.env.PUBLIC_TOPOGRAM_WEB_BASE_URL || \`http://localhost:\${process.env.WEB_PORT || "${ports.web}"}\`,
|
|
169
|
-
${runtimeReference.runtimeCheck.demoContainerEnvVar}: process.env.PUBLIC_TOPOGRAM_DEMO_CONTAINER_ID ||
|
|
170
|
-
${runtimeReference.runtimeCheck.demoPrimaryEnvVar}: process.env.PUBLIC_TOPOGRAM_DEMO_PRIMARY_ID ||
|
|
171
|
-
TOPOGRAM_DEMO_USER_ID: process.env.PUBLIC_TOPOGRAM_DEMO_USER_ID || "",
|
|
169
|
+
${runtimeReference.runtimeCheck.demoContainerEnvVar}: process.env.PUBLIC_TOPOGRAM_DEMO_CONTAINER_ID || "",
|
|
170
|
+
${runtimeReference.runtimeCheck.demoPrimaryEnvVar}: process.env.PUBLIC_TOPOGRAM_DEMO_PRIMARY_ID || "",
|
|
171
|
+
TOPOGRAM_DEMO_USER_ID: process.env.PUBLIC_TOPOGRAM_AUTH_USER_ID || process.env.PUBLIC_TOPOGRAM_DEMO_USER_ID || "",
|
|
172
172
|
TOPOGRAM_AUTH_USER_ID: process.env.TOPOGRAM_DEMO_USER_ID || ""
|
|
173
173
|
};
|
|
174
174
|
|
|
@@ -513,3 +513,12 @@ export function runtimeUrls(runtimeReference, topology = null) {
|
|
|
513
513
|
web: `http://localhost:${ports.web}`
|
|
514
514
|
};
|
|
515
515
|
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* @param {Record<string, any>|null|undefined} runtimeReference
|
|
519
|
+
* @returns {string}
|
|
520
|
+
*/
|
|
521
|
+
export function runtimeDemoUserId(runtimeReference) {
|
|
522
|
+
const demo = runtimeReference?.demoEnv || {};
|
|
523
|
+
return demo.userId || demo.memberId || demo.ownerId || demo.primaryActorId || "";
|
|
524
|
+
}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
buildVerificationSummary,
|
|
3
3
|
getDefaultEnvironmentProjections,
|
|
4
4
|
resolveRuntimeTopology,
|
|
5
|
+
runtimeDemoUserId,
|
|
5
6
|
runtimeUrls,
|
|
6
7
|
selectChecksByVerification
|
|
7
8
|
} from "./shared.js";
|
|
@@ -126,7 +127,7 @@ process.on("unhandledRejection", reportFatal);
|
|
|
126
127
|
const apiBase = process.env.TOPOGRAM_API_BASE_URL || "";
|
|
127
128
|
const webBase = process.env.TOPOGRAM_WEB_BASE_URL || "";
|
|
128
129
|
const demoContainerId = process.env.${runtimeReference.smoke.defaultContainerEnvVar} || "${runtimeReference.demoEnv.containerId}";
|
|
129
|
-
const demoUserId = process.env.TOPOGRAM_DEMO_USER_ID || "${runtimeReference
|
|
130
|
+
const demoUserId = process.env.TOPOGRAM_AUTH_USER_ID || process.env.TOPOGRAM_DEMO_USER_ID || "${runtimeDemoUserId(runtimeReference)}";
|
|
130
131
|
const authToken = process.env.TOPOGRAM_AUTH_TOKEN || "";
|
|
131
132
|
|
|
132
133
|
if (!apiBase || !webBase) {
|
|
@@ -38,7 +38,8 @@ export function uiProjectionCandidates(graph) {
|
|
|
38
38
|
(projection.uiAppShell || []).length > 0 ||
|
|
39
39
|
(projection.uiNavigation || []).length > 0 ||
|
|
40
40
|
(projection.uiScreenRegions || []).length > 0 ||
|
|
41
|
-
(projection.uiComponents || []).length > 0
|
|
41
|
+
(projection.uiComponents || []).length > 0 ||
|
|
42
|
+
(projection.uiDesign || []).length > 0
|
|
42
43
|
);
|
|
43
44
|
}
|
|
44
45
|
|