scene-capability-engine 3.6.32 → 3.6.37
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 +109 -11
- package/README.md +119 -122
- package/README.zh.md +123 -121
- package/bin/scene-capability-engine.js +12 -1
- package/docs/331-poc-adaptation-roadmap.md +3 -3
- package/docs/README.md +21 -32
- package/docs/auto-refactor-index.md +384 -0
- package/docs/command-reference.md +99 -7
- package/docs/faq.md +1 -1
- package/docs/interactive-customization/331-poc-sce-integration-checklist.md +3 -3
- package/docs/interactive-customization/moqui-interactive-template-playbook.md +4 -4
- package/docs/interactive-customization/phase-acceptance-evidence.md +2 -2
- package/docs/magicball-adaptation-task-checklist-v1.md +385 -0
- package/docs/magicball-app-bundle-sqlite-and-command-draft.md +539 -0
- package/docs/magicball-capability-iteration-api.md +2 -0
- package/docs/magicball-capability-iteration-ui.md +2 -0
- package/docs/magicball-capability-library.md +2 -0
- package/docs/magicball-cli-invocation-examples.md +336 -0
- package/docs/magicball-frontend-state-and-command-mapping.md +244 -0
- package/docs/magicball-integration-doc-index.md +137 -0
- package/docs/magicball-integration-issue-tracker.md +218 -0
- package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +249 -0
- package/docs/magicball-sce-adaptation-guide.md +203 -0
- package/docs/magicball-three-mode-alignment-plan.md +551 -0
- package/docs/magicball-ui-surface-checklist.md +126 -0
- package/docs/magicball-write-auth-adaptation-guide.md +328 -0
- package/docs/moqui-standard-rebuild-guide.md +6 -6
- package/docs/moqui-template-core-library-playbook.md +1 -1
- package/docs/refactor-completion-roadmap.md +116 -0
- package/docs/release-checklist.md +50 -27
- package/docs/releases/README.md +1 -0
- package/docs/releases/v3.6.37.md +22 -0
- package/docs/steering-strategy-guide.md +7 -7
- package/docs/troubleshooting.md +1 -1
- package/docs/zh/README.md +27 -30
- package/docs/zh/refactor-completion-roadmap.md +116 -0
- package/docs/zh/release-checklist.md +40 -17
- package/docs/zh/releases/README.md +1 -0
- package/docs/zh/releases/v3.6.37.md +22 -0
- package/lib/app/registry-config.js +73 -0
- package/lib/app/registry-sync-service.js +228 -0
- package/lib/auto/archive-schema-service.js +276 -0
- package/lib/auto/archive-summary.js +60 -0
- package/lib/auto/batch-goal-input-service.js +543 -0
- package/lib/auto/batch-output.js +201 -0
- package/lib/auto/batch-summary-storage-service.js +110 -0
- package/lib/auto/close-loop-batch-service.js +116 -0
- package/lib/auto/close-loop-controller-service.js +287 -0
- package/lib/auto/close-loop-program-service.js +283 -0
- package/lib/auto/close-loop-recovery-service.js +191 -0
- package/lib/auto/close-loop-session-storage-service.js +50 -0
- package/lib/auto/controller-lock-service.js +55 -0
- package/lib/auto/controller-output.js +32 -0
- package/lib/auto/controller-queue-service.js +127 -0
- package/lib/auto/controller-session-storage-service.js +105 -0
- package/lib/auto/governance-advisory-service.js +208 -0
- package/lib/auto/governance-close-loop-service.js +411 -0
- package/lib/auto/governance-maintenance-presenter.js +162 -0
- package/lib/auto/governance-maintenance-service.js +112 -0
- package/lib/auto/governance-session-presenter.js +70 -0
- package/lib/auto/governance-session-storage-service.js +198 -0
- package/lib/auto/governance-signals.js +139 -0
- package/lib/auto/governance-stats-presenter.js +337 -0
- package/lib/auto/governance-stats-service.js +115 -0
- package/lib/auto/governance-summary.js +703 -0
- package/lib/auto/handoff-capability-matrix-service.js +281 -0
- package/lib/auto/handoff-evidence-review-service.js +251 -0
- package/lib/auto/handoff-release-evidence-service.js +190 -0
- package/lib/auto/handoff-release-gate-history-loaders-service.js +502 -0
- package/lib/auto/handoff-release-gate-history-service.js +257 -0
- package/lib/auto/handoff-reporting-service.js +1407 -0
- package/lib/auto/handoff-run-service.js +486 -0
- package/lib/auto/handoff-snapshots-service.js +645 -0
- package/lib/auto/observability-service.js +132 -0
- package/lib/auto/output-writer.js +34 -0
- package/lib/auto/program-auto-remediation-service.js +130 -0
- package/lib/auto/program-diagnostics.js +138 -0
- package/lib/auto/program-governance-helpers.js +306 -0
- package/lib/auto/program-governance-loop-service.js +413 -0
- package/lib/auto/program-output.js +106 -0
- package/lib/auto/program-summary.js +183 -0
- package/lib/auto/recovery-memory-service.js +684 -0
- package/lib/auto/recovery-selection-service.js +52 -0
- package/lib/auto/retention-policy.js +98 -0
- package/lib/auto/session-persistence-service.js +106 -0
- package/lib/auto/session-presenter.js +105 -0
- package/lib/auto/session-prune-service.js +190 -0
- package/lib/auto/session-query-service.js +249 -0
- package/lib/auto/spec-protection.js +141 -0
- package/lib/commands/adopt.js +4 -4
- package/lib/commands/app.js +911 -0
- package/lib/commands/assurance.js +212 -0
- package/lib/commands/auto.js +1093 -11065
- package/lib/commands/mode.js +321 -0
- package/lib/commands/ontology.js +415 -0
- package/lib/commands/pm.js +422 -0
- package/lib/ontology/seed-profiles.js +160 -0
- package/lib/spec/bootstrap/context-collector.js +1 -1
- package/lib/state/sce-state-store.js +3369 -1200
- package/lib/steering/adoption-config.js +2 -2
- package/lib/steering/compliance-cache.js +2 -2
- package/lib/steering/steering-manager.js +4 -4
- package/lib/task/task-claimer.js +1 -2
- package/lib/workspace/multi/workspace-context-resolver.js +3 -3
- package/lib/workspace/multi/workspace-state-manager.js +0 -164
- package/lib/workspace/sce-tracking-audit.js +1 -1
- package/lib/workspace/takeover-baseline.js +1 -1
- package/package.json +1 -1
- package/template/.sce/README.md +1 -1
- package/template/.sce/steering/CORE_PRINCIPLES.md +1 -1
- package/bin/kse.js +0 -3
|
@@ -0,0 +1,911 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const { ensureWriteAuthorization } = require('../security/write-authorization');
|
|
5
|
+
const { getSceStateStore } = require('../state/sce-state-store');
|
|
6
|
+
const { loadAppRegistryConfig, saveAppRegistryConfig } = require('../app/registry-config');
|
|
7
|
+
const { syncBundleRegistry, syncServiceCatalog } = require('../app/registry-sync-service');
|
|
8
|
+
|
|
9
|
+
function normalizeString(value) {
|
|
10
|
+
if (typeof value !== 'string') {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
return value.trim();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function normalizePositiveInteger(value, fallback = 50, max = 1000) {
|
|
17
|
+
const parsed = Number.parseInt(`${value}`, 10);
|
|
18
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
return Math.min(parsed, max);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function normalizeBoolean(value, fallback = false) {
|
|
25
|
+
if (typeof value === 'boolean') {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
const normalized = normalizeString(`${value || ''}`).toLowerCase();
|
|
29
|
+
if (!normalized) {
|
|
30
|
+
return fallback;
|
|
31
|
+
}
|
|
32
|
+
if (['1', 'true', 'yes', 'on'].includes(normalized)) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (['0', 'false', 'no', 'off'].includes(normalized)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return fallback;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function createStore(dependencies = {}) {
|
|
42
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
43
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
44
|
+
const env = dependencies.env || process.env;
|
|
45
|
+
return dependencies.stateStore || getSceStateStore(projectPath, {
|
|
46
|
+
fileSystem,
|
|
47
|
+
env
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function printPayload(payload, options = {}, title = 'App Bundle') {
|
|
52
|
+
if (options.json) {
|
|
53
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
console.log(chalk.blue(title));
|
|
58
|
+
if (payload.mode) {
|
|
59
|
+
console.log(` Mode: ${payload.mode}`);
|
|
60
|
+
}
|
|
61
|
+
if (payload.summary && typeof payload.summary === 'object') {
|
|
62
|
+
for (const [key, value] of Object.entries(payload.summary)) {
|
|
63
|
+
console.log(` ${key}: ${value}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(payload.items)) {
|
|
67
|
+
payload.items.forEach((item) => {
|
|
68
|
+
console.log(` - ${item.app_id} | ${item.app_key} | ${item.app_name} | ${item.status}`);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function buildBundleSummary(graph = {}) {
|
|
74
|
+
const bundle = graph.bundle || {};
|
|
75
|
+
const runtimeRelease = graph.runtime_release || {};
|
|
76
|
+
const ontologyBundle = graph.ontology_bundle || {};
|
|
77
|
+
const engineeringProject = graph.engineering_project || {};
|
|
78
|
+
const sceneBindings = Array.isArray(graph.scene_bindings) ? graph.scene_bindings : [];
|
|
79
|
+
return {
|
|
80
|
+
app_id: bundle.app_id || null,
|
|
81
|
+
app_key: bundle.app_key || null,
|
|
82
|
+
app_name: bundle.app_name || null,
|
|
83
|
+
status: bundle.status || null,
|
|
84
|
+
environment: bundle.environment || null,
|
|
85
|
+
runtime_version: runtimeRelease.runtime_version || null,
|
|
86
|
+
ontology_version: ontologyBundle.ontology_version || null,
|
|
87
|
+
code_version: engineeringProject.code_version || null,
|
|
88
|
+
scene_binding_count: sceneBindings.length
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function buildRuntimeSummary(graph = {}) {
|
|
93
|
+
const bundle = graph.bundle || {};
|
|
94
|
+
const runtimeRelease = graph.runtime_release || {};
|
|
95
|
+
const metadata = bundle.metadata && typeof bundle.metadata === 'object' ? bundle.metadata : {};
|
|
96
|
+
const installation = metadata.runtime_installation && typeof metadata.runtime_installation === 'object'
|
|
97
|
+
? metadata.runtime_installation
|
|
98
|
+
: {};
|
|
99
|
+
const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object'
|
|
100
|
+
? metadata.service_catalog
|
|
101
|
+
: {};
|
|
102
|
+
const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
|
|
103
|
+
return {
|
|
104
|
+
app_id: bundle.app_id || null,
|
|
105
|
+
app_name: bundle.app_name || null,
|
|
106
|
+
runtime_release_id: bundle.runtime_release_id || runtimeRelease.release_id || null,
|
|
107
|
+
runtime_version: runtimeRelease.runtime_version || null,
|
|
108
|
+
release_status: runtimeRelease.release_status || null,
|
|
109
|
+
runtime_status: runtimeRelease.runtime_status || null,
|
|
110
|
+
install_status: installation.status || 'not-installed',
|
|
111
|
+
install_root: installation.install_root || null,
|
|
112
|
+
release_count: releases.length,
|
|
113
|
+
active_release_id: installation.release_id || bundle.runtime_release_id || runtimeRelease.release_id || null
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function buildEngineeringSummary(graph = {}) {
|
|
118
|
+
const bundle = graph.bundle || {};
|
|
119
|
+
const engineeringProject = graph.engineering_project || {};
|
|
120
|
+
const metadata = engineeringProject.metadata && typeof engineeringProject.metadata === 'object'
|
|
121
|
+
? engineeringProject.metadata
|
|
122
|
+
: {};
|
|
123
|
+
return {
|
|
124
|
+
app_id: bundle.app_id || null,
|
|
125
|
+
app_name: bundle.app_name || null,
|
|
126
|
+
engineering_project_id: engineeringProject.engineering_project_id || null,
|
|
127
|
+
project_name: engineeringProject.project_name || null,
|
|
128
|
+
repo_url: engineeringProject.repo_url || null,
|
|
129
|
+
current_branch: engineeringProject.current_branch || null,
|
|
130
|
+
workspace_path: engineeringProject.workspace_path || null,
|
|
131
|
+
code_version: engineeringProject.code_version || null,
|
|
132
|
+
dirty_state: engineeringProject.dirty_state === true,
|
|
133
|
+
hydrated: Boolean(metadata.hydration && metadata.hydration.status === 'ready'),
|
|
134
|
+
active: Boolean(metadata.activation && metadata.activation.active === true)
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function deriveEngineeringProjectId(bundle = {}) {
|
|
139
|
+
const appKey = normalizeString(bundle.app_key);
|
|
140
|
+
if (appKey) {
|
|
141
|
+
return `eng.${appKey.replace(/[^a-zA-Z0-9._-]+/g, '-')}`;
|
|
142
|
+
}
|
|
143
|
+
const appId = normalizeString(bundle.app_id).replace(/^app\./, '');
|
|
144
|
+
return appId ? `eng.${appId.replace(/[^a-zA-Z0-9._-]+/g, '-')}` : null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function graphToRegisterPayload(graph = {}) {
|
|
148
|
+
const bundle = graph.bundle || {};
|
|
149
|
+
const runtimeRelease = graph.runtime_release || {};
|
|
150
|
+
const ontologyBundle = graph.ontology_bundle || {};
|
|
151
|
+
const engineeringProject = graph.engineering_project || {};
|
|
152
|
+
return {
|
|
153
|
+
app_id: bundle.app_id,
|
|
154
|
+
app_key: bundle.app_key,
|
|
155
|
+
app_name: bundle.app_name,
|
|
156
|
+
app_slug: bundle.app_slug || undefined,
|
|
157
|
+
workspace_id: bundle.workspace_id || undefined,
|
|
158
|
+
runtime_release_id: bundle.runtime_release_id || undefined,
|
|
159
|
+
ontology_bundle_id: bundle.ontology_bundle_id || undefined,
|
|
160
|
+
engineering_project_id: bundle.engineering_project_id || undefined,
|
|
161
|
+
default_scene_id: bundle.default_scene_id || undefined,
|
|
162
|
+
environment: bundle.environment || undefined,
|
|
163
|
+
status: bundle.status || undefined,
|
|
164
|
+
source_origin: bundle.source_origin || undefined,
|
|
165
|
+
tags: Array.isArray(bundle.tags) ? bundle.tags : [],
|
|
166
|
+
metadata: bundle.metadata && typeof bundle.metadata === 'object' ? bundle.metadata : {},
|
|
167
|
+
runtime: runtimeRelease && runtimeRelease.release_id ? {
|
|
168
|
+
release_id: runtimeRelease.release_id,
|
|
169
|
+
runtime_version: runtimeRelease.runtime_version,
|
|
170
|
+
release_channel: runtimeRelease.release_channel,
|
|
171
|
+
release_status: runtimeRelease.release_status,
|
|
172
|
+
entrypoint: runtimeRelease.entrypoint,
|
|
173
|
+
runtime_status: runtimeRelease.runtime_status,
|
|
174
|
+
release_notes_file: runtimeRelease.release_notes_file,
|
|
175
|
+
release_evidence_file: runtimeRelease.release_evidence_file,
|
|
176
|
+
published_at: runtimeRelease.published_at,
|
|
177
|
+
source_updated_at: runtimeRelease.source_updated_at,
|
|
178
|
+
metadata: runtimeRelease.metadata || {}
|
|
179
|
+
} : undefined,
|
|
180
|
+
ontology: ontologyBundle && ontologyBundle.ontology_bundle_id ? {
|
|
181
|
+
ontology_bundle_id: ontologyBundle.ontology_bundle_id,
|
|
182
|
+
ontology_version: ontologyBundle.ontology_version,
|
|
183
|
+
template_version: ontologyBundle.template_version,
|
|
184
|
+
capability_catalog_version: ontologyBundle.capability_catalog_version,
|
|
185
|
+
triad_revision: ontologyBundle.triad_revision,
|
|
186
|
+
triad_status: ontologyBundle.triad_status,
|
|
187
|
+
publish_readiness: ontologyBundle.publish_readiness,
|
|
188
|
+
template_source: ontologyBundle.template_source,
|
|
189
|
+
capability_set: Array.isArray(ontologyBundle.capability_set) ? ontologyBundle.capability_set : [],
|
|
190
|
+
summary: ontologyBundle.summary || {},
|
|
191
|
+
metadata: ontologyBundle.metadata || {}
|
|
192
|
+
} : undefined,
|
|
193
|
+
engineering: engineeringProject && engineeringProject.engineering_project_id ? {
|
|
194
|
+
engineering_project_id: engineeringProject.engineering_project_id,
|
|
195
|
+
project_key: engineeringProject.project_key,
|
|
196
|
+
project_name: engineeringProject.project_name,
|
|
197
|
+
repo_url: engineeringProject.repo_url,
|
|
198
|
+
repo_provider: engineeringProject.repo_provider,
|
|
199
|
+
default_branch: engineeringProject.default_branch,
|
|
200
|
+
current_branch: engineeringProject.current_branch,
|
|
201
|
+
commit_sha: engineeringProject.commit_sha,
|
|
202
|
+
workspace_path: engineeringProject.workspace_path,
|
|
203
|
+
code_version: engineeringProject.code_version,
|
|
204
|
+
synced_runtime_release_id: engineeringProject.synced_runtime_release_id,
|
|
205
|
+
dirty_state: engineeringProject.dirty_state === true,
|
|
206
|
+
auth_policy: engineeringProject.auth_policy || {},
|
|
207
|
+
metadata: engineeringProject.metadata || {}
|
|
208
|
+
} : undefined,
|
|
209
|
+
scene_bindings: Array.isArray(graph.scene_bindings) ? graph.scene_bindings.map((item) => ({
|
|
210
|
+
scene_id: item.scene_id,
|
|
211
|
+
binding_role: item.binding_role,
|
|
212
|
+
source: item.source,
|
|
213
|
+
metadata: item.metadata || {}
|
|
214
|
+
})) : []
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async function requireAppGraph(appRef, dependencies = {}) {
|
|
219
|
+
const store = createStore(dependencies);
|
|
220
|
+
const graph = await store.getAppBundleGraph(appRef);
|
|
221
|
+
if (!graph) {
|
|
222
|
+
throw new Error(`app bundle not found: ${appRef}`);
|
|
223
|
+
}
|
|
224
|
+
return { store, graph };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function ensureAuthorized(action, options = {}, dependencies = {}) {
|
|
228
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
229
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
230
|
+
const env = dependencies.env || process.env;
|
|
231
|
+
await ensureWriteAuthorization(action, {
|
|
232
|
+
authLease: options.authLease,
|
|
233
|
+
authPassword: options.authPassword,
|
|
234
|
+
actor: options.actor
|
|
235
|
+
}, {
|
|
236
|
+
projectPath,
|
|
237
|
+
fileSystem,
|
|
238
|
+
env
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function runAppBundleListCommand(options = {}, dependencies = {}) {
|
|
243
|
+
const store = createStore(dependencies);
|
|
244
|
+
const items = await store.listAppBundles({
|
|
245
|
+
limit: normalizePositiveInteger(options.limit, 50, 1000),
|
|
246
|
+
status: options.status,
|
|
247
|
+
environment: options.environment,
|
|
248
|
+
workspaceId: options.workspaceId,
|
|
249
|
+
query: options.query
|
|
250
|
+
});
|
|
251
|
+
const payload = {
|
|
252
|
+
mode: 'app-bundle-list',
|
|
253
|
+
generated_at: new Date().toISOString(),
|
|
254
|
+
query: {
|
|
255
|
+
limit: normalizePositiveInteger(options.limit, 50, 1000),
|
|
256
|
+
status: normalizeString(options.status) || null,
|
|
257
|
+
environment: normalizeString(options.environment) || null,
|
|
258
|
+
workspace_id: normalizeString(options.workspaceId) || null,
|
|
259
|
+
query: normalizeString(options.query) || null
|
|
260
|
+
},
|
|
261
|
+
summary: {
|
|
262
|
+
total: Array.isArray(items) ? items.length : 0
|
|
263
|
+
},
|
|
264
|
+
items: Array.isArray(items) ? items : []
|
|
265
|
+
};
|
|
266
|
+
printPayload(payload, options, 'App Bundle List');
|
|
267
|
+
return payload;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function runAppBundleShowCommand(options = {}, dependencies = {}) {
|
|
271
|
+
const appRef = normalizeString(options.app || options.appRef);
|
|
272
|
+
if (!appRef) {
|
|
273
|
+
throw new Error('--app is required');
|
|
274
|
+
}
|
|
275
|
+
const { graph } = await requireAppGraph(appRef, dependencies);
|
|
276
|
+
const payload = {
|
|
277
|
+
mode: 'app-bundle-show',
|
|
278
|
+
generated_at: new Date().toISOString(),
|
|
279
|
+
query: {
|
|
280
|
+
app: appRef
|
|
281
|
+
},
|
|
282
|
+
summary: buildBundleSummary(graph),
|
|
283
|
+
bundle: graph.bundle,
|
|
284
|
+
runtime_release: graph.runtime_release,
|
|
285
|
+
ontology_bundle: graph.ontology_bundle,
|
|
286
|
+
engineering_project: graph.engineering_project,
|
|
287
|
+
scene_bindings: graph.scene_bindings || []
|
|
288
|
+
};
|
|
289
|
+
printPayload(payload, options, 'App Bundle Show');
|
|
290
|
+
return payload;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async function runAppBundleRegisterCommand(options = {}, dependencies = {}) {
|
|
294
|
+
const inputFile = normalizeString(options.input);
|
|
295
|
+
if (!inputFile) {
|
|
296
|
+
throw new Error('--input is required');
|
|
297
|
+
}
|
|
298
|
+
await ensureAuthorized('app:bundle:register', options, dependencies);
|
|
299
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
300
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
301
|
+
const env = dependencies.env || process.env;
|
|
302
|
+
const resolvedInput = path.isAbsolute(inputFile)
|
|
303
|
+
? inputFile
|
|
304
|
+
: path.join(projectPath, inputFile);
|
|
305
|
+
const payloadJson = await fileSystem.readJson(resolvedInput);
|
|
306
|
+
const store = createStore({ ...dependencies, projectPath, fileSystem, env });
|
|
307
|
+
const graph = await store.registerAppBundle(payloadJson);
|
|
308
|
+
const payload = {
|
|
309
|
+
mode: 'app-bundle-register',
|
|
310
|
+
success: true,
|
|
311
|
+
input_file: resolvedInput,
|
|
312
|
+
summary: buildBundleSummary(graph),
|
|
313
|
+
bundle: graph.bundle,
|
|
314
|
+
runtime_release: graph.runtime_release,
|
|
315
|
+
ontology_bundle: graph.ontology_bundle,
|
|
316
|
+
engineering_project: graph.engineering_project,
|
|
317
|
+
scene_bindings: graph.scene_bindings || []
|
|
318
|
+
};
|
|
319
|
+
printPayload(payload, options, 'App Bundle Register');
|
|
320
|
+
return payload;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async function runAppEngineeringShowCommand(options = {}, dependencies = {}) {
|
|
324
|
+
const appRef = normalizeString(options.app);
|
|
325
|
+
if (!appRef) {
|
|
326
|
+
throw new Error('--app is required');
|
|
327
|
+
}
|
|
328
|
+
const { graph } = await requireAppGraph(appRef, dependencies);
|
|
329
|
+
const payload = {
|
|
330
|
+
mode: 'app-engineering-show',
|
|
331
|
+
generated_at: new Date().toISOString(),
|
|
332
|
+
query: {
|
|
333
|
+
app: appRef
|
|
334
|
+
},
|
|
335
|
+
summary: buildEngineeringSummary(graph),
|
|
336
|
+
bundle: graph.bundle,
|
|
337
|
+
engineering_project: graph.engineering_project,
|
|
338
|
+
scene_bindings: graph.scene_bindings || []
|
|
339
|
+
};
|
|
340
|
+
printPayload(payload, options, 'App Engineering Show');
|
|
341
|
+
return payload;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
async function runAppEngineeringAttachCommand(options = {}, dependencies = {}) {
|
|
345
|
+
const appRef = normalizeString(options.app);
|
|
346
|
+
if (!appRef) {
|
|
347
|
+
throw new Error('--app is required');
|
|
348
|
+
}
|
|
349
|
+
const repoUrl = normalizeString(options.repo);
|
|
350
|
+
if (!repoUrl) {
|
|
351
|
+
throw new Error('--repo is required');
|
|
352
|
+
}
|
|
353
|
+
await ensureAuthorized('app:engineering:attach', options, dependencies);
|
|
354
|
+
const { store, graph } = await requireAppGraph(appRef, dependencies);
|
|
355
|
+
const nextPayload = graphToRegisterPayload(graph);
|
|
356
|
+
const bundle = graph.bundle || {};
|
|
357
|
+
const currentEngineering = nextPayload.engineering && typeof nextPayload.engineering === 'object'
|
|
358
|
+
? nextPayload.engineering
|
|
359
|
+
: {};
|
|
360
|
+
const engineeringProjectId = currentEngineering.engineering_project_id || deriveEngineeringProjectId(bundle);
|
|
361
|
+
const nowIso = new Date().toISOString();
|
|
362
|
+
nextPayload.engineering_project_id = engineeringProjectId;
|
|
363
|
+
nextPayload.engineering = {
|
|
364
|
+
...currentEngineering,
|
|
365
|
+
engineering_project_id: engineeringProjectId,
|
|
366
|
+
project_name: normalizeString(options.projectName) || currentEngineering.project_name || bundle.app_name || null,
|
|
367
|
+
project_key: normalizeString(options.projectKey) || currentEngineering.project_key || bundle.app_key || null,
|
|
368
|
+
repo_url: repoUrl,
|
|
369
|
+
repo_provider: normalizeString(options.provider) || currentEngineering.repo_provider || null,
|
|
370
|
+
default_branch: normalizeString(options.branch) || currentEngineering.default_branch || null,
|
|
371
|
+
current_branch: normalizeString(options.branch) || currentEngineering.current_branch || null,
|
|
372
|
+
workspace_path: normalizeString(options.workspacePath) || currentEngineering.workspace_path || null,
|
|
373
|
+
code_version: normalizeString(options.codeVersion) || currentEngineering.code_version || null,
|
|
374
|
+
dirty_state: currentEngineering.dirty_state === true,
|
|
375
|
+
metadata: {
|
|
376
|
+
...(currentEngineering.metadata || {}),
|
|
377
|
+
attachment: {
|
|
378
|
+
attached_at: nowIso,
|
|
379
|
+
source: 'sce app engineering attach',
|
|
380
|
+
repo_url: repoUrl
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
const updated = await store.registerAppBundle(nextPayload);
|
|
385
|
+
const payload = {
|
|
386
|
+
mode: 'app-engineering-attach',
|
|
387
|
+
success: true,
|
|
388
|
+
summary: buildEngineeringSummary(updated),
|
|
389
|
+
bundle: updated.bundle,
|
|
390
|
+
engineering_project: updated.engineering_project,
|
|
391
|
+
scene_bindings: updated.scene_bindings || []
|
|
392
|
+
};
|
|
393
|
+
printPayload(payload, options, 'App Engineering Attach');
|
|
394
|
+
return payload;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
async function runAppEngineeringHydrateCommand(options = {}, dependencies = {}) {
|
|
398
|
+
const appRef = normalizeString(options.app);
|
|
399
|
+
if (!appRef) {
|
|
400
|
+
throw new Error('--app is required');
|
|
401
|
+
}
|
|
402
|
+
await ensureAuthorized('app:engineering:hydrate', options, dependencies);
|
|
403
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
404
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
405
|
+
const { store, graph } = await requireAppGraph(appRef, { ...dependencies, projectPath, fileSystem });
|
|
406
|
+
const bundle = graph.bundle || {};
|
|
407
|
+
const nextPayload = graphToRegisterPayload(graph);
|
|
408
|
+
const currentEngineering = nextPayload.engineering && typeof nextPayload.engineering === 'object'
|
|
409
|
+
? nextPayload.engineering
|
|
410
|
+
: {};
|
|
411
|
+
const engineeringProjectId = currentEngineering.engineering_project_id || deriveEngineeringProjectId(bundle);
|
|
412
|
+
const workspacePath = normalizeString(options.workspacePath)
|
|
413
|
+
|| normalizeString(currentEngineering.workspace_path)
|
|
414
|
+
|| path.join(projectPath, '.sce', 'apps', bundle.app_key || bundle.app_id || engineeringProjectId, 'engineering');
|
|
415
|
+
await fileSystem.ensureDir(workspacePath);
|
|
416
|
+
const nowIso = new Date().toISOString();
|
|
417
|
+
nextPayload.engineering_project_id = engineeringProjectId;
|
|
418
|
+
nextPayload.engineering = {
|
|
419
|
+
...currentEngineering,
|
|
420
|
+
engineering_project_id: engineeringProjectId,
|
|
421
|
+
workspace_path: workspacePath,
|
|
422
|
+
metadata: {
|
|
423
|
+
...(currentEngineering.metadata || {}),
|
|
424
|
+
hydration: {
|
|
425
|
+
status: 'ready',
|
|
426
|
+
hydrated_at: nowIso,
|
|
427
|
+
source: 'sce app engineering hydrate'
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
const updated = await store.registerAppBundle(nextPayload);
|
|
432
|
+
const payload = {
|
|
433
|
+
mode: 'app-engineering-hydrate',
|
|
434
|
+
success: true,
|
|
435
|
+
summary: buildEngineeringSummary(updated),
|
|
436
|
+
bundle: updated.bundle,
|
|
437
|
+
engineering_project: updated.engineering_project,
|
|
438
|
+
hydrated_workspace_path: workspacePath
|
|
439
|
+
};
|
|
440
|
+
printPayload(payload, options, 'App Engineering Hydrate');
|
|
441
|
+
return payload;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
async function runAppEngineeringActivateCommand(options = {}, dependencies = {}) {
|
|
445
|
+
const appRef = normalizeString(options.app);
|
|
446
|
+
if (!appRef) {
|
|
447
|
+
throw new Error('--app is required');
|
|
448
|
+
}
|
|
449
|
+
await ensureAuthorized('app:engineering:activate', options, dependencies);
|
|
450
|
+
const { store, graph } = await requireAppGraph(appRef, dependencies);
|
|
451
|
+
const nextPayload = graphToRegisterPayload(graph);
|
|
452
|
+
const bundle = graph.bundle || {};
|
|
453
|
+
const currentEngineering = nextPayload.engineering && typeof nextPayload.engineering === 'object'
|
|
454
|
+
? nextPayload.engineering
|
|
455
|
+
: {};
|
|
456
|
+
const engineeringProjectId = currentEngineering.engineering_project_id || deriveEngineeringProjectId(bundle);
|
|
457
|
+
const workspacePath = normalizeString(options.workspacePath) || normalizeString(currentEngineering.workspace_path);
|
|
458
|
+
if (!workspacePath) {
|
|
459
|
+
throw new Error('engineering workspace_path is not set; run app engineering attach/hydrate first or pass --workspace-path');
|
|
460
|
+
}
|
|
461
|
+
const nowIso = new Date().toISOString();
|
|
462
|
+
nextPayload.engineering_project_id = engineeringProjectId;
|
|
463
|
+
nextPayload.engineering = {
|
|
464
|
+
...currentEngineering,
|
|
465
|
+
engineering_project_id: engineeringProjectId,
|
|
466
|
+
workspace_path: workspacePath,
|
|
467
|
+
metadata: {
|
|
468
|
+
...(currentEngineering.metadata || {}),
|
|
469
|
+
activation: {
|
|
470
|
+
active: true,
|
|
471
|
+
activated_at: nowIso,
|
|
472
|
+
source: 'sce app engineering activate'
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
const updated = await store.registerAppBundle(nextPayload);
|
|
477
|
+
const payload = {
|
|
478
|
+
mode: 'app-engineering-activate',
|
|
479
|
+
success: true,
|
|
480
|
+
summary: buildEngineeringSummary(updated),
|
|
481
|
+
bundle: updated.bundle,
|
|
482
|
+
engineering_project: updated.engineering_project,
|
|
483
|
+
activated_workspace_path: workspacePath
|
|
484
|
+
};
|
|
485
|
+
printPayload(payload, options, 'App Engineering Activate');
|
|
486
|
+
return payload;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
async function runAppRegistryStatusCommand(options = {}, dependencies = {}) {
|
|
490
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
491
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
492
|
+
const loaded = await loadAppRegistryConfig(projectPath, fileSystem);
|
|
493
|
+
const payload = {
|
|
494
|
+
mode: 'app-registry-status',
|
|
495
|
+
generated_at: new Date().toISOString(),
|
|
496
|
+
config_path: loaded.config_path,
|
|
497
|
+
config: loaded.config
|
|
498
|
+
};
|
|
499
|
+
printPayload(payload, options, 'App Registry Status');
|
|
500
|
+
return payload;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
async function runAppRegistryConfigureCommand(options = {}, dependencies = {}) {
|
|
504
|
+
await ensureAuthorized('app:registry:configure', options, dependencies);
|
|
505
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
506
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
507
|
+
const saved = await saveAppRegistryConfig({
|
|
508
|
+
bundle_registry: {
|
|
509
|
+
repo_url: normalizeString(options.bundleRepoUrl) || undefined,
|
|
510
|
+
branch: normalizeString(options.bundleBranch) || undefined,
|
|
511
|
+
index_url: normalizeString(options.bundleIndexUrl) || undefined
|
|
512
|
+
},
|
|
513
|
+
service_catalog: {
|
|
514
|
+
repo_url: normalizeString(options.serviceRepoUrl) || undefined,
|
|
515
|
+
branch: normalizeString(options.serviceBranch) || undefined,
|
|
516
|
+
index_url: normalizeString(options.serviceIndexUrl) || undefined
|
|
517
|
+
}
|
|
518
|
+
}, projectPath, fileSystem);
|
|
519
|
+
const payload = {
|
|
520
|
+
mode: 'app-registry-configure',
|
|
521
|
+
success: true,
|
|
522
|
+
config_path: saved.config_path,
|
|
523
|
+
config: saved.config
|
|
524
|
+
};
|
|
525
|
+
printPayload(payload, options, 'App Registry Configure');
|
|
526
|
+
return payload;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
async function runAppRegistrySyncBundlesCommand(options = {}, dependencies = {}) {
|
|
530
|
+
const store = createStore(dependencies);
|
|
531
|
+
const payload = await syncBundleRegistry(options, { ...dependencies, stateStore: store });
|
|
532
|
+
printPayload(payload, options, 'App Registry Sync Bundles');
|
|
533
|
+
return payload;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
async function runAppRegistrySyncCatalogCommand(options = {}, dependencies = {}) {
|
|
537
|
+
const store = createStore(dependencies);
|
|
538
|
+
const payload = await syncServiceCatalog(options, { ...dependencies, stateStore: store });
|
|
539
|
+
printPayload(payload, options, 'App Registry Sync Catalog');
|
|
540
|
+
return payload;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
async function runAppRegistrySyncAllCommand(options = {}, dependencies = {}) {
|
|
544
|
+
const store = createStore(dependencies);
|
|
545
|
+
const bundle = await syncBundleRegistry(options, { ...dependencies, stateStore: store });
|
|
546
|
+
const catalog = await syncServiceCatalog(options, { ...dependencies, stateStore: store });
|
|
547
|
+
const payload = {
|
|
548
|
+
mode: 'app-registry-sync',
|
|
549
|
+
generated_at: new Date().toISOString(),
|
|
550
|
+
bundle_registry: bundle,
|
|
551
|
+
service_catalog: catalog,
|
|
552
|
+
summary: {
|
|
553
|
+
bundle_synced_count: bundle.synced_count,
|
|
554
|
+
catalog_synced_count: catalog.synced_count
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
printPayload(payload, options, 'App Registry Sync');
|
|
558
|
+
return payload;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
async function runAppRuntimeShowCommand(options = {}, dependencies = {}) {
|
|
562
|
+
const appRef = normalizeString(options.app);
|
|
563
|
+
if (!appRef) {
|
|
564
|
+
throw new Error('--app is required');
|
|
565
|
+
}
|
|
566
|
+
const { graph } = await requireAppGraph(appRef, dependencies);
|
|
567
|
+
const metadata = graph.bundle && graph.bundle.metadata && typeof graph.bundle.metadata === 'object' ? graph.bundle.metadata : {};
|
|
568
|
+
const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object' ? metadata.service_catalog : {};
|
|
569
|
+
const payload = {
|
|
570
|
+
mode: 'app-runtime-show',
|
|
571
|
+
generated_at: new Date().toISOString(),
|
|
572
|
+
query: {
|
|
573
|
+
app: appRef
|
|
574
|
+
},
|
|
575
|
+
summary: buildRuntimeSummary(graph),
|
|
576
|
+
bundle: graph.bundle,
|
|
577
|
+
runtime_release: graph.runtime_release,
|
|
578
|
+
runtime_installation: metadata.runtime_installation || null,
|
|
579
|
+
service_catalog: {
|
|
580
|
+
default_release_id: serviceCatalog.default_release_id || null,
|
|
581
|
+
release_count: Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases.length : 0,
|
|
582
|
+
source: serviceCatalog.source || null
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
printPayload(payload, options, 'App Runtime Show');
|
|
586
|
+
return payload;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
async function runAppRuntimeReleasesCommand(options = {}, dependencies = {}) {
|
|
590
|
+
const appRef = normalizeString(options.app);
|
|
591
|
+
if (!appRef) {
|
|
592
|
+
throw new Error('--app is required');
|
|
593
|
+
}
|
|
594
|
+
const { graph } = await requireAppGraph(appRef, dependencies);
|
|
595
|
+
const metadata = graph.bundle && graph.bundle.metadata && typeof graph.bundle.metadata === 'object' ? graph.bundle.metadata : {};
|
|
596
|
+
const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object' ? metadata.service_catalog : {};
|
|
597
|
+
const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
|
|
598
|
+
const payload = {
|
|
599
|
+
mode: 'app-runtime-releases',
|
|
600
|
+
generated_at: new Date().toISOString(),
|
|
601
|
+
query: {
|
|
602
|
+
app: appRef
|
|
603
|
+
},
|
|
604
|
+
summary: {
|
|
605
|
+
total: releases.length,
|
|
606
|
+
default_release_id: serviceCatalog.default_release_id || null
|
|
607
|
+
},
|
|
608
|
+
items: releases,
|
|
609
|
+
view_model: {
|
|
610
|
+
type: 'table',
|
|
611
|
+
columns: ['release_id', 'runtime_version', 'release_channel', 'release_status', 'runtime_status', 'published_at']
|
|
612
|
+
},
|
|
613
|
+
mb_status: graph.runtime_release && graph.runtime_release.runtime_status ? graph.runtime_release.runtime_status : (graph.bundle && graph.bundle.status ? graph.bundle.status : 'unknown')
|
|
614
|
+
};
|
|
615
|
+
printPayload(payload, options, 'App Runtime Releases');
|
|
616
|
+
return payload;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
async function runAppRuntimeInstallCommand(options = {}, dependencies = {}) {
|
|
620
|
+
const appRef = normalizeString(options.app);
|
|
621
|
+
if (!appRef) {
|
|
622
|
+
throw new Error('--app is required');
|
|
623
|
+
}
|
|
624
|
+
await ensureAuthorized('app:runtime:install', options, dependencies);
|
|
625
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
626
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
627
|
+
const { store, graph } = await requireAppGraph(appRef, dependencies);
|
|
628
|
+
const nextPayload = graphToRegisterPayload(graph);
|
|
629
|
+
const serviceCatalog = nextPayload.metadata && nextPayload.metadata.service_catalog && typeof nextPayload.metadata.service_catalog === 'object'
|
|
630
|
+
? nextPayload.metadata.service_catalog
|
|
631
|
+
: {};
|
|
632
|
+
const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
|
|
633
|
+
const releaseId = normalizeString(options.release) || normalizeString(serviceCatalog.default_release_id) || normalizeString(releases[0] && releases[0].release_id);
|
|
634
|
+
const selectedRelease = releases.find((item) => normalizeString(item && item.release_id) == releaseId) || null;
|
|
635
|
+
if (!selectedRelease) {
|
|
636
|
+
throw new Error('runtime release not found; sync service catalog first or pass --release with a valid release id');
|
|
637
|
+
}
|
|
638
|
+
const installRoot = normalizeString(options.installRoot) || path.join(projectPath, '.sce', 'apps', nextPayload.app_key || nextPayload.app_id, 'runtime', releaseId);
|
|
639
|
+
await fileSystem.ensureDir(installRoot);
|
|
640
|
+
nextPayload.metadata = nextPayload.metadata || {};
|
|
641
|
+
nextPayload.metadata.runtime_installation = {
|
|
642
|
+
status: 'installed',
|
|
643
|
+
install_root: installRoot,
|
|
644
|
+
release_id: releaseId,
|
|
645
|
+
installed_at: new Date().toISOString(),
|
|
646
|
+
source: 'sce app runtime install'
|
|
647
|
+
};
|
|
648
|
+
const updated = await store.registerAppBundle(nextPayload);
|
|
649
|
+
const payload = {
|
|
650
|
+
mode: 'app-runtime-install',
|
|
651
|
+
success: true,
|
|
652
|
+
summary: buildRuntimeSummary(updated),
|
|
653
|
+
runtime_installation: updated.bundle && updated.bundle.metadata ? updated.bundle.metadata.runtime_installation : null
|
|
654
|
+
};
|
|
655
|
+
printPayload(payload, options, 'App Runtime Install');
|
|
656
|
+
return payload;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
async function runAppRuntimeActivateCommand(options = {}, dependencies = {}) {
|
|
660
|
+
const appRef = normalizeString(options.app);
|
|
661
|
+
if (!appRef) {
|
|
662
|
+
throw new Error('--app is required');
|
|
663
|
+
}
|
|
664
|
+
await ensureAuthorized('app:runtime:activate', options, dependencies);
|
|
665
|
+
const { store, graph } = await requireAppGraph(appRef, dependencies);
|
|
666
|
+
const nextPayload = graphToRegisterPayload(graph);
|
|
667
|
+
const serviceCatalog = nextPayload.metadata && nextPayload.metadata.service_catalog && typeof nextPayload.metadata.service_catalog === 'object'
|
|
668
|
+
? nextPayload.metadata.service_catalog
|
|
669
|
+
: {};
|
|
670
|
+
const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
|
|
671
|
+
const releaseId = normalizeString(options.release) || normalizeString(serviceCatalog.default_release_id) || normalizeString(releases[0] && releases[0].release_id);
|
|
672
|
+
const selectedRelease = releases.find((item) => normalizeString(item && item.release_id) == releaseId) || null;
|
|
673
|
+
if (!selectedRelease) {
|
|
674
|
+
throw new Error('runtime release not found; sync service catalog first or pass --release with a valid release id');
|
|
675
|
+
}
|
|
676
|
+
nextPayload.runtime_release_id = releaseId;
|
|
677
|
+
nextPayload.runtime = {
|
|
678
|
+
release_id: releaseId,
|
|
679
|
+
runtime_version: normalizeString(selectedRelease.runtime_version),
|
|
680
|
+
release_channel: normalizeString(selectedRelease.release_channel) || null,
|
|
681
|
+
release_status: normalizeString(selectedRelease.release_status) || 'published',
|
|
682
|
+
entrypoint: normalizeString(selectedRelease.entrypoint) || null,
|
|
683
|
+
runtime_status: normalizeString(selectedRelease.runtime_status) || 'ready',
|
|
684
|
+
release_notes_file: normalizeString(selectedRelease.release_notes_file) || null,
|
|
685
|
+
release_evidence_file: normalizeString(selectedRelease.release_evidence_file) || null,
|
|
686
|
+
published_at: normalizeString(selectedRelease.published_at) || null,
|
|
687
|
+
metadata: selectedRelease.metadata && typeof selectedRelease.metadata === 'object' ? selectedRelease.metadata : {}
|
|
688
|
+
};
|
|
689
|
+
nextPayload.metadata = nextPayload.metadata || {};
|
|
690
|
+
nextPayload.metadata.runtime_activation = {
|
|
691
|
+
active_release_id: releaseId,
|
|
692
|
+
activated_at: new Date().toISOString(),
|
|
693
|
+
source: 'sce app runtime activate'
|
|
694
|
+
};
|
|
695
|
+
const updated = await store.registerAppBundle(nextPayload);
|
|
696
|
+
const payload = {
|
|
697
|
+
mode: 'app-runtime-activate',
|
|
698
|
+
success: true,
|
|
699
|
+
summary: buildRuntimeSummary(updated),
|
|
700
|
+
runtime_release: updated.runtime_release,
|
|
701
|
+
runtime_activation: updated.bundle && updated.bundle.metadata ? updated.bundle.metadata.runtime_activation : null
|
|
702
|
+
};
|
|
703
|
+
printPayload(payload, options, 'App Runtime Activate');
|
|
704
|
+
return payload;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
function safeRun(handler, options = {}, context = 'app command') {
|
|
708
|
+
Promise.resolve(handler(options))
|
|
709
|
+
.catch((error) => {
|
|
710
|
+
if (options.json) {
|
|
711
|
+
console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
|
|
712
|
+
} else {
|
|
713
|
+
console.error(chalk.red(`${context} failed:`), error.message);
|
|
714
|
+
}
|
|
715
|
+
process.exitCode = 1;
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
function registerAppCommands(program) {
|
|
720
|
+
const app = program
|
|
721
|
+
.command('app')
|
|
722
|
+
.description('Manage app bundles that bind application/ontology/engineering projections');
|
|
723
|
+
|
|
724
|
+
const bundle = app
|
|
725
|
+
.command('bundle')
|
|
726
|
+
.description('Manage app bundle registry');
|
|
727
|
+
|
|
728
|
+
bundle
|
|
729
|
+
.command('list')
|
|
730
|
+
.description('List app bundles')
|
|
731
|
+
.option('--limit <n>', 'Maximum rows', '50')
|
|
732
|
+
.option('--status <status>', 'Filter by status')
|
|
733
|
+
.option('--environment <env>', 'Filter by environment')
|
|
734
|
+
.option('--workspace-id <id>', 'Filter by workspace id')
|
|
735
|
+
.option('--query <text>', 'Free-text query against id/key/name')
|
|
736
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
737
|
+
.action((options) => safeRun(runAppBundleListCommand, options, 'app bundle list'));
|
|
738
|
+
|
|
739
|
+
bundle
|
|
740
|
+
.command('show')
|
|
741
|
+
.description('Show one app bundle with linked runtime/ontology/engineering records')
|
|
742
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
743
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
744
|
+
.action((options) => safeRun(runAppBundleShowCommand, options, 'app bundle show'));
|
|
745
|
+
|
|
746
|
+
bundle
|
|
747
|
+
.command('register')
|
|
748
|
+
.description('Register or update an app bundle from JSON input')
|
|
749
|
+
.requiredOption('--input <path>', 'Bundle JSON input file')
|
|
750
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
751
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
752
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
753
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
754
|
+
.action((options) => safeRun(runAppBundleRegisterCommand, options, 'app bundle register'));
|
|
755
|
+
|
|
756
|
+
const registry = app
|
|
757
|
+
.command('registry')
|
|
758
|
+
.description('Manage remote app bundle and service catalog registry configuration');
|
|
759
|
+
|
|
760
|
+
registry
|
|
761
|
+
.command('status')
|
|
762
|
+
.description('Show current registry configuration')
|
|
763
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
764
|
+
.action((options) => safeRun(runAppRegistryStatusCommand, options, 'app registry status'));
|
|
765
|
+
|
|
766
|
+
registry
|
|
767
|
+
.command('configure')
|
|
768
|
+
.description('Configure bundle registry and service catalog sources')
|
|
769
|
+
.option('--bundle-repo-url <url>', 'Bundle registry repository URL')
|
|
770
|
+
.option('--bundle-branch <branch>', 'Bundle registry branch')
|
|
771
|
+
.option('--bundle-index-url <url>', 'Bundle registry index URL')
|
|
772
|
+
.option('--service-repo-url <url>', 'Service catalog repository URL')
|
|
773
|
+
.option('--service-branch <branch>', 'Service catalog branch')
|
|
774
|
+
.option('--service-index-url <url>', 'Service catalog index URL')
|
|
775
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
776
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
777
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
778
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
779
|
+
.action((options) => safeRun(runAppRegistryConfigureCommand, options, 'app registry configure'));
|
|
780
|
+
|
|
781
|
+
registry
|
|
782
|
+
.command('sync-bundles')
|
|
783
|
+
.description('Sync remote app bundle registry into local SCE app bundle state')
|
|
784
|
+
.option('--index-url <url-or-path>', 'Override bundle index URL/path')
|
|
785
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
786
|
+
.action((options) => safeRun(runAppRegistrySyncBundlesCommand, options, 'app registry sync bundles'));
|
|
787
|
+
|
|
788
|
+
registry
|
|
789
|
+
.command('sync-catalog')
|
|
790
|
+
.description('Sync remote app service catalog into local app bundle runtime metadata')
|
|
791
|
+
.option('--index-url <url-or-path>', 'Override service catalog index URL/path')
|
|
792
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
793
|
+
.action((options) => safeRun(runAppRegistrySyncCatalogCommand, options, 'app registry sync catalog'));
|
|
794
|
+
|
|
795
|
+
registry
|
|
796
|
+
.command('sync')
|
|
797
|
+
.description('Sync both app bundle registry and app service catalog')
|
|
798
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
799
|
+
.action((options) => safeRun(runAppRegistrySyncAllCommand, options, 'app registry sync'));
|
|
800
|
+
|
|
801
|
+
const runtime = app
|
|
802
|
+
.command('runtime')
|
|
803
|
+
.description('Manage runtime projection for one app bundle');
|
|
804
|
+
|
|
805
|
+
runtime
|
|
806
|
+
.command('show')
|
|
807
|
+
.description('Show runtime projection for one app bundle')
|
|
808
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
809
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
810
|
+
.action((options) => safeRun(runAppRuntimeShowCommand, options, 'app runtime show'));
|
|
811
|
+
|
|
812
|
+
runtime
|
|
813
|
+
.command('releases')
|
|
814
|
+
.description('List runtime releases known for one app bundle')
|
|
815
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
816
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
817
|
+
.action((options) => safeRun(runAppRuntimeReleasesCommand, options, 'app runtime releases'));
|
|
818
|
+
|
|
819
|
+
runtime
|
|
820
|
+
.command('install')
|
|
821
|
+
.description('Install runtime release for one app bundle')
|
|
822
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
823
|
+
.option('--release <release-id>', 'Runtime release id')
|
|
824
|
+
.option('--install-root <path>', 'Install root path')
|
|
825
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
826
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
827
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
828
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
829
|
+
.action((options) => safeRun(runAppRuntimeInstallCommand, options, 'app runtime install'));
|
|
830
|
+
|
|
831
|
+
runtime
|
|
832
|
+
.command('activate')
|
|
833
|
+
.description('Activate runtime release for one app bundle')
|
|
834
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
835
|
+
.option('--release <release-id>', 'Runtime release id')
|
|
836
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
837
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
838
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
839
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
840
|
+
.action((options) => safeRun(runAppRuntimeActivateCommand, options, 'app runtime activate'));
|
|
841
|
+
|
|
842
|
+
const engineering = app
|
|
843
|
+
.command('engineering')
|
|
844
|
+
.description('Manage engineering project projection for one app bundle');
|
|
845
|
+
|
|
846
|
+
engineering
|
|
847
|
+
.command('show')
|
|
848
|
+
.description('Show engineering projection for one app bundle')
|
|
849
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
850
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
851
|
+
.action((options) => safeRun(runAppEngineeringShowCommand, options, 'app engineering show'));
|
|
852
|
+
|
|
853
|
+
engineering
|
|
854
|
+
.command('attach')
|
|
855
|
+
.description('Attach engineering project metadata to one app bundle')
|
|
856
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
857
|
+
.requiredOption('--repo <repo-url>', 'Repository url')
|
|
858
|
+
.option('--provider <provider>', 'Repository provider')
|
|
859
|
+
.option('--branch <branch>', 'Default/current branch')
|
|
860
|
+
.option('--workspace-path <path>', 'Workspace path to bind')
|
|
861
|
+
.option('--project-name <name>', 'Project display name override')
|
|
862
|
+
.option('--project-key <key>', 'Project key override')
|
|
863
|
+
.option('--code-version <version>', 'Code version summary')
|
|
864
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
865
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
866
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
867
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
868
|
+
.action((options) => safeRun(runAppEngineeringAttachCommand, options, 'app engineering attach'));
|
|
869
|
+
|
|
870
|
+
engineering
|
|
871
|
+
.command('hydrate')
|
|
872
|
+
.description('Prepare local engineering workspace for one app bundle')
|
|
873
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
874
|
+
.option('--workspace-path <path>', 'Explicit workspace path')
|
|
875
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
876
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
877
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
878
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
879
|
+
.action((options) => safeRun(runAppEngineeringHydrateCommand, options, 'app engineering hydrate'));
|
|
880
|
+
|
|
881
|
+
engineering
|
|
882
|
+
.command('activate')
|
|
883
|
+
.description('Activate engineering workspace for one app bundle')
|
|
884
|
+
.requiredOption('--app <app-id-or-key>', 'App id or app key')
|
|
885
|
+
.option('--workspace-path <path>', 'Override workspace path for activation')
|
|
886
|
+
.option('--auth-lease <lease-id>', 'Write authorization lease id')
|
|
887
|
+
.option('--auth-password <password>', 'Inline auth password if policy allows')
|
|
888
|
+
.option('--actor <actor>', 'Audit actor override')
|
|
889
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
890
|
+
.action((options) => safeRun(runAppEngineeringActivateCommand, options, 'app engineering activate'));
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
module.exports = {
|
|
894
|
+
runAppBundleListCommand,
|
|
895
|
+
runAppBundleShowCommand,
|
|
896
|
+
runAppBundleRegisterCommand,
|
|
897
|
+
runAppRegistryStatusCommand,
|
|
898
|
+
runAppRegistryConfigureCommand,
|
|
899
|
+
runAppRegistrySyncBundlesCommand,
|
|
900
|
+
runAppRegistrySyncCatalogCommand,
|
|
901
|
+
runAppRegistrySyncAllCommand,
|
|
902
|
+
runAppRuntimeShowCommand,
|
|
903
|
+
runAppRuntimeReleasesCommand,
|
|
904
|
+
runAppRuntimeInstallCommand,
|
|
905
|
+
runAppRuntimeActivateCommand,
|
|
906
|
+
runAppEngineeringShowCommand,
|
|
907
|
+
runAppEngineeringAttachCommand,
|
|
908
|
+
runAppEngineeringHydrateCommand,
|
|
909
|
+
runAppEngineeringActivateCommand,
|
|
910
|
+
registerAppCommands
|
|
911
|
+
};
|