@things-factory/headless-twin 10.0.12 → 10.0.13
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/dist-server/engine/canonical-ingest.d.ts +57 -2
- package/dist-server/engine/canonical-ingest.js +43 -2
- package/dist-server/engine/canonical-ingest.js.map +1 -1
- package/dist-server/engine/command-routing.js +1 -1
- package/dist-server/engine/command-routing.js.map +1 -1
- package/dist-server/engine/index.d.ts +3 -0
- package/dist-server/engine/index.js +4 -0
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/ingest-health.d.ts +335 -0
- package/dist-server/engine/ingest-health.js +434 -0
- package/dist-server/engine/ingest-health.js.map +1 -0
- package/dist-server/engine/integration-coverage.d.ts +76 -0
- package/dist-server/engine/integration-coverage.js +73 -0
- package/dist-server/engine/integration-coverage.js.map +1 -0
- package/dist-server/engine/integration-probes.d.ts +65 -0
- package/dist-server/engine/integration-probes.js +100 -0
- package/dist-server/engine/integration-probes.js.map +1 -0
- package/dist-server/engine/integration-runner.d.ts +45 -0
- package/dist-server/engine/integration-runner.js +59 -0
- package/dist-server/engine/integration-runner.js.map +1 -0
- package/dist-server/engine/integration-target-profile.d.ts +57 -0
- package/dist-server/engine/integration-target-profile.js +79 -0
- package/dist-server/engine/integration-target-profile.js.map +1 -0
- package/dist-server/engine/kpi-fold.d.ts +27 -0
- package/dist-server/engine/kpi-fold.js +47 -4
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.js +128 -14
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/live-feed-registry.js +2 -16
- package/dist-server/engine/live-feed-registry.js.map +1 -1
- package/dist-server/engine/load-meter.d.ts +1 -1
- package/dist-server/engine/load-meter.js +12 -3
- package/dist-server/engine/load-meter.js.map +1 -1
- package/dist-server/engine/log.d.ts +18 -0
- package/dist-server/engine/log.js +80 -0
- package/dist-server/engine/log.js.map +1 -0
- package/dist-server/engine/loop-lag.d.ts +54 -0
- package/dist-server/engine/loop-lag.js +87 -0
- package/dist-server/engine/loop-lag.js.map +1 -0
- package/dist-server/engine/model-gap.d.ts +108 -0
- package/dist-server/engine/model-gap.js +95 -0
- package/dist-server/engine/model-gap.js.map +1 -0
- package/dist-server/engine/restart-policy.d.ts +3 -3
- package/dist-server/engine/restart-policy.js +4 -4
- package/dist-server/engine/restart-policy.js.map +1 -1
- package/dist-server/engine/runtime-key.js +1 -1
- package/dist-server/engine/runtime-key.js.map +1 -1
- package/dist-server/engine/stage-path.d.ts +83 -0
- package/dist-server/engine/stage-path.js +118 -0
- package/dist-server/engine/stage-path.js.map +1 -0
- package/dist-server/engine/twin-engine.d.ts +352 -16
- package/dist-server/engine/twin-engine.js +1037 -166
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/index.js +34 -2
- package/dist-server/index.js.map +1 -1
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.d.ts +5 -0
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js +58 -0
- package/dist-server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.js.map +1 -0
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.d.ts +5 -0
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js +55 -0
- package/dist-server/migrations/1786200000000-CarryLiveFeedCursor.js.map +1 -0
- package/dist-server/migrations/index.js +7 -1
- package/dist-server/migrations/index.js.map +1 -1
- package/dist-server/service/index.d.ts +5 -2
- package/dist-server/service/index.js +18 -7
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/discovery-result.d.ts +1 -1
- package/dist-server/service/reference/discovery-result.js +1 -1
- package/dist-server/service/reference/discovery-result.js.map +1 -1
- package/dist-server/service/reference/index.d.ts +4 -1
- package/dist-server/service/reference/index.js +6 -1
- package/dist-server/service/reference/index.js.map +1 -1
- package/dist-server/service/reference/reference-adapter.d.ts +184 -3
- package/dist-server/service/reference/reference-adapter.js +28 -4
- package/dist-server/service/reference/reference-adapter.js.map +1 -1
- package/dist-server/service/reference/reference-assessment.d.ts +68 -0
- package/dist-server/service/reference/reference-assessment.js +136 -0
- package/dist-server/service/reference/reference-assessment.js.map +1 -0
- package/dist-server/service/reference/reference-live.d.ts +12 -1
- package/dist-server/service/reference/reference-live.js +116 -11
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +47 -1
- package/dist-server/service/reference/reference-master.js +34 -4
- package/dist-server/service/reference/reference-master.js.map +1 -1
- package/dist-server/service/reference/reference-probe.d.ts +92 -0
- package/dist-server/service/reference/reference-probe.js +186 -0
- package/dist-server/service/reference/reference-probe.js.map +1 -0
- package/dist-server/service/reference/reference-progress-subscription.d.ts +17 -0
- package/dist-server/service/reference/reference-progress-subscription.js +94 -0
- package/dist-server/service/reference/reference-progress-subscription.js.map +1 -0
- package/dist-server/service/reference/reference-progress.d.ts +38 -0
- package/dist-server/service/reference/reference-progress.js +71 -0
- package/dist-server/service/reference/reference-progress.js.map +1 -0
- package/dist-server/service/reference/reference-resolver.js +210 -43
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/reference/twin-reference.d.ts +32 -0
- package/dist-server/service/reference/twin-reference.js +10 -0
- package/dist-server/service/reference/twin-reference.js.map +1 -1
- package/dist-server/service/twin-control/twin-control-mutation.js +4 -3
- package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
- package/dist-server/service/twin-event/journal-count.d.ts +21 -0
- package/dist-server/service/twin-event/journal-count.js +26 -0
- package/dist-server/service/twin-event/journal-count.js.map +1 -0
- package/dist-server/service/twin-event/twin-event-keys.d.ts +9 -0
- package/dist-server/service/twin-event/twin-event-keys.js +15 -18
- package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-type.d.ts +3 -1
- package/dist-server/service/twin-event/twin-event-type.js +18 -1
- package/dist-server/service/twin-event/twin-event-type.js.map +1 -1
- package/dist-server/service/twin-event/twin-event.d.ts +1 -0
- package/dist-server/service/twin-event/twin-event.js +9 -1
- package/dist-server/service/twin-event/twin-event.js.map +1 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js +2 -1
- package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
- package/dist-server/service/twin-ingest-window/index.d.ts +5 -0
- package/dist-server/service/twin-ingest-window/index.js +10 -0
- package/dist-server/service/twin-ingest-window/index.js.map +1 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.d.ts +12 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js +123 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window-query.js.map +1 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.d.ts +1 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js +51 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window-writer.js.map +1 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window.d.ts +16 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window.js +108 -0
- package/dist-server/service/twin-ingest-window/twin-ingest-window.js.map +1 -0
- package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
- package/dist-server/service/twin-journal/twin-journal-query.js +58 -5
- package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +14 -0
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +72 -2
- package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
- package/dist-server/service/twin-metrics/twin-metrics-query.d.ts +1 -0
- package/dist-server/service/twin-metrics/twin-metrics-query.js +78 -3
- package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
- package/dist-server/service/twin-model/axis-journal-evidence.d.ts +2 -0
- package/dist-server/service/twin-model/axis-journal-evidence.js +89 -0
- package/dist-server/service/twin-model/axis-journal-evidence.js.map +1 -0
- package/dist-server/service/twin-model/epcis-coverage.d.ts +1 -1
- package/dist-server/service/twin-model/epcis-coverage.js +19 -7
- package/dist-server/service/twin-model/epcis-coverage.js.map +1 -1
- package/dist-server/service/twin-model/iec61850-coverage.d.ts +1 -1
- package/dist-server/service/twin-model/iec61850-coverage.js +18 -7
- package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -1
- package/dist-server/service/twin-model/isa95-coverage.d.ts +14 -0
- package/dist-server/service/twin-model/isa95-coverage.js +23 -9
- package/dist-server/service/twin-model/isa95-coverage.js.map +1 -1
- package/dist-server/service/twin-model/item-ref.d.ts +24 -0
- package/dist-server/service/twin-model/item-ref.js +88 -0
- package/dist-server/service/twin-model/item-ref.js.map +1 -0
- package/dist-server/service/twin-model/name-index.d.ts +36 -0
- package/dist-server/service/twin-model/name-index.js +116 -0
- package/dist-server/service/twin-model/name-index.js.map +1 -0
- package/dist-server/service/twin-model/project-structure.js +1 -1
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/status-tally.d.ts +9 -0
- package/dist-server/service/twin-model/status-tally.js +37 -0
- package/dist-server/service/twin-model/status-tally.js.map +1 -0
- package/dist-server/service/twin-model/twin-lineage-query.js +40 -12
- package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.js +38 -39
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-query.js +156 -4
- package/dist-server/service/twin-model/twin-model-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js +7 -0
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
- package/dist-server/service/twin-readiness/index.d.ts +2 -0
- package/dist-server/service/twin-readiness/index.js +6 -0
- package/dist-server/service/twin-readiness/index.js.map +1 -0
- package/dist-server/service/twin-readiness/twin-readiness-query.d.ts +3 -0
- package/dist-server/service/twin-readiness/twin-readiness-query.js +103 -0
- package/dist-server/service/twin-readiness/twin-readiness-query.js.map +1 -0
- package/dist-server/service/twin-space/twin-space-resolver.d.ts +2 -2
- package/dist-server/service/twin-space/twin-space-resolver.js +5 -4
- package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
- package/dist-shared/entity-delta.d.ts +23 -3
- package/dist-shared/entity-delta.js +12 -8
- package/dist-shared/entity-delta.js.map +1 -1
- package/dist-shared/kpi-broadcast.js +1 -1
- package/dist-shared/kpi-broadcast.js.map +1 -1
- package/dist-shared/touched-items.d.ts +7 -0
- package/dist-shared/touched-items.js +80 -0
- package/dist-shared/touched-items.js.map +1 -0
- package/package.json +7 -7
- package/server/engine/canonical-ingest.ts +92 -7
- package/server/engine/command-routing.ts +1 -1
- package/server/engine/index.ts +4 -0
- package/server/engine/ingest-health.ts +704 -0
- package/server/engine/integration-coverage.ts +147 -0
- package/server/engine/integration-probes.ts +144 -0
- package/server/engine/integration-runner.ts +95 -0
- package/server/engine/integration-target-profile.ts +103 -0
- package/server/engine/kpi-fold.ts +72 -4
- package/server/engine/kpi-query.ts +129 -15
- package/server/engine/live-feed-registry.ts +2 -1
- package/server/engine/load-meter.ts +12 -3
- package/server/engine/log.ts +72 -0
- package/server/engine/loop-lag.ts +120 -0
- package/server/engine/model-gap.ts +168 -0
- package/server/engine/restart-policy.ts +4 -4
- package/server/engine/runtime-key.ts +1 -1
- package/server/engine/stage-path.ts +172 -0
- package/server/engine/twin-engine.ts +1135 -162
- package/server/index.ts +35 -2
- package/server/migrations/1786100000000-PromoteEventActionAndSyncWarnings.ts +54 -0
- package/server/migrations/1786200000000-CarryLiveFeedCursor.ts +53 -0
- package/server/migrations/index.ts +7 -1
- package/server/service/index.ts +11 -0
- package/server/service/reference/discovery-result.ts +1 -1
- package/server/service/reference/index.ts +6 -1
- package/server/service/reference/reference-adapter.ts +197 -5
- package/server/service/reference/reference-assessment.ts +215 -0
- package/server/service/reference/reference-live.ts +123 -11
- package/server/service/reference/reference-master.ts +64 -4
- package/server/service/reference/reference-probe.ts +264 -0
- package/server/service/reference/reference-progress-subscription.ts +73 -0
- package/server/service/reference/reference-progress.ts +95 -0
- package/server/service/reference/reference-resolver.ts +200 -12
- package/server/service/reference/twin-reference.ts +39 -1
- package/server/service/twin-control/twin-control-mutation.ts +4 -3
- package/server/service/twin-event/journal-count.ts +53 -0
- package/server/service/twin-event/twin-event-keys.ts +16 -1
- package/server/service/twin-event/twin-event-type.ts +26 -2
- package/server/service/twin-event/twin-event.ts +7 -0
- package/server/service/twin-forecast/twin-forecast-query.ts +2 -1
- package/server/service/twin-ingest-window/index.ts +7 -0
- package/server/service/twin-ingest-window/twin-ingest-window-query.ts +125 -0
- package/server/service/twin-ingest-window/twin-ingest-window-writer.ts +57 -0
- package/server/service/twin-ingest-window/twin-ingest-window.ts +113 -0
- package/server/service/twin-instance/twin-instance.ts +1 -1
- package/server/service/twin-journal/twin-journal-query.ts +59 -5
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +77 -3
- package/server/service/twin-metrics/twin-metrics-query.ts +81 -3
- package/server/service/twin-model/axis-journal-evidence.ts +57 -0
- package/server/service/twin-model/epcis-coverage.ts +2 -8
- package/server/service/twin-model/iec61850-coverage.ts +2 -8
- package/server/service/twin-model/isa95-coverage.ts +22 -9
- package/server/service/twin-model/item-ref.ts +80 -0
- package/server/service/twin-model/name-index.ts +94 -0
- package/server/service/twin-model/project-structure.ts +1 -1
- package/server/service/twin-model/status-tally.ts +37 -0
- package/server/service/twin-model/twin-lineage-query.ts +38 -9
- package/server/service/twin-model/twin-model-item-query.ts +26 -27
- package/server/service/twin-model/twin-model-query.ts +155 -4
- package/server/service/twin-model/twin-model-tree-query.ts +7 -0
- package/server/service/twin-readiness/index.ts +3 -0
- package/server/service/twin-readiness/twin-readiness-query.ts +96 -0
- package/server/service/twin-space/twin-space-resolver.ts +5 -4
- package/shared/entity-delta.ts +31 -7
- package/shared/kpi-broadcast.ts +1 -1
- package/shared/touched-items.ts +73 -0
- package/test/axis-journal-evidence.test.ts +71 -0
- package/test/axis-read.test.ts +101 -1
- package/test/boot-resume.test.ts +92 -26
- package/test/broadcast-cost-baseline.test.ts +200 -0
- package/test/broadcast-period.test.ts +58 -0
- package/test/canonical-ingest-vocabularies.test.ts +36 -1
- package/test/canonical-quantity-door.test.ts +61 -0
- package/test/command-routing.test.ts +1 -1
- package/test/declared-location-types.test.ts +89 -0
- package/test/discovery-result.test.ts +1 -1
- package/test/duration-estimators.test.ts +1 -1
- package/test/entity-delta.test.ts +2 -2
- package/test/ingest-bench.test.ts +3 -3
- package/test/ingest-health-engine.test.ts +248 -0
- package/test/ingest-health-wiring.test.ts +119 -0
- package/test/ingest-health.test.ts +306 -0
- package/test/ingest-history.test.ts +247 -0
- package/test/integration-probes.test.ts +103 -0
- package/test/integration-runner.test.ts +95 -0
- package/test/item-ref.test.ts +78 -0
- package/test/journal-read-discipline.test.ts +177 -0
- package/test/journal-retention.test.ts +133 -0
- package/test/journal-sort-axis.test.ts +142 -0
- package/test/journal-write-door.test.ts +110 -0
- package/test/journal-write-trend.test.ts +115 -0
- package/test/kernel-kind-guard.test.ts +4 -4
- package/test/kpi-fold.test.ts +90 -3
- package/test/kpi-query-bench.test.ts +2 -2
- package/test/lineage-survives-restart.test.ts +17 -1
- package/test/live-cursor-wiring.test.ts +87 -0
- package/test/live-feed-registry.test.ts +9 -1
- package/test/live-kernel-facts.test.ts +7 -7
- package/test/live-mirror-parity.test.ts +6 -0
- package/test/load-meter.test.ts +29 -15
- package/test/local-declarations.test.ts +1 -1
- package/test/log-stamp.test.ts +59 -0
- package/test/loop-lag.test.ts +82 -0
- package/test/model-gap.test.ts +153 -0
- package/test/oee-accumulator.test.ts +4 -0
- package/test/operational-vocabulary.test.ts +4 -4
- package/test/read-failure-visible.test.ts +145 -0
- package/test/reference-grounding.test.ts +70 -0
- package/test/resolve-ts-siblings.mjs +52 -0
- package/test/restart-policy.test.ts +7 -7
- package/test/revision-axis.test.ts +93 -0
- package/test/runtime-key.test.ts +2 -2
- package/test/scale-twin-bench.test.ts +2 -2
- package/test/spec-coverage.test.ts +1 -1
- package/test/stage-path.test.ts +95 -0
- package/test/standard-coverage.test.ts +15 -3
- package/test/status-tally.test.ts +55 -0
- package/test/structure-revision-db.test.ts +4 -0
- package/test/tenant-registry-db.test.ts +1 -1
- package/test/time-range.test.ts +152 -0
- package/test/touched-items.test.ts +61 -0
- package/test/twin-event-keys.test.ts +10 -2
- package/test/twin-model-item-db.test.ts +2 -0
- package/test/warm-start-seam.test.ts +4 -0
- package/test/yield-loop.test.ts +57 -2
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TwinReferenceResolver = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const type_graphql_1 = require("type-graphql");
|
|
6
5
|
const shell_1 = require("@things-factory/shell");
|
|
6
|
+
const reference_progress_js_1 = require("./reference-progress.js");
|
|
7
|
+
const reference_assessment_js_1 = require("./reference-assessment.js");
|
|
8
|
+
const type_graphql_1 = require("type-graphql");
|
|
9
|
+
const shell_2 = require("@things-factory/shell");
|
|
7
10
|
const index_js_1 = require("../../engine/index.js");
|
|
8
11
|
const restart_policy_js_1 = require("../../engine/restart-policy.js");
|
|
9
12
|
const twin_kernel_1 = require("@operato/twin-kernel");
|
|
@@ -85,7 +88,7 @@ async function resolveSiteEquipmentKnobs(knobs, effective, domainId, spaceId) {
|
|
|
85
88
|
continue;
|
|
86
89
|
}
|
|
87
90
|
if (ids === undefined) {
|
|
88
|
-
const rows = await (0,
|
|
91
|
+
const rows = await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId }, spaceId } });
|
|
89
92
|
const seen = new Map();
|
|
90
93
|
for (const r of rows) {
|
|
91
94
|
for (const e of (0, twin_kernel_1.readBoardEquipment)(r.model ?? {})) {
|
|
@@ -107,7 +110,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
107
110
|
const domainId = context.state.domain.id;
|
|
108
111
|
const out = [];
|
|
109
112
|
for (const m of (0, reference_registry_js_1.listReferences)()) {
|
|
110
|
-
const reg = await (0,
|
|
113
|
+
const reg = await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId: m.source } });
|
|
111
114
|
out.push({
|
|
112
115
|
source: m.source,
|
|
113
116
|
system: m.system,
|
|
@@ -160,7 +163,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
160
163
|
*/
|
|
161
164
|
async resyncTwin(instanceId, context) {
|
|
162
165
|
const domainId = context.state.domain.id;
|
|
163
|
-
const inst = await (0,
|
|
166
|
+
const inst = await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } });
|
|
164
167
|
if (!inst)
|
|
165
168
|
return { ok: false, error: `unknown twin: ${instanceId}` };
|
|
166
169
|
const origin = inst.origin;
|
|
@@ -169,8 +172,35 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
169
172
|
ok: false,
|
|
170
173
|
error: `twin "${instanceId}" does not remember where it came from — it cannot be re-read. Re-create it from its template or reference so the origin is recorded.`
|
|
171
174
|
};
|
|
175
|
+
/*
|
|
176
|
+
* 진행을 알리는 통로 — 만들 때와 **같은 것**이다. 레퍼런스에서 온 트윈만 알린다(템플릿에서 온
|
|
177
|
+
* 트윈은 원본을 읽지 않으므로 알릴 단계가 없다).
|
|
178
|
+
*
|
|
179
|
+
* 분모는 그 어댑터가 선언한 단계 수다(`masterSteps`) + 호스트 단계. 선언하지 않은 어댑터는
|
|
180
|
+
* `total` 이 없고, 그때 화면은 퍼센트를 만들지 않는다 — 모르는 진행률을 지어내지 않는다.
|
|
181
|
+
*/
|
|
182
|
+
const progressSource = origin.kind === 'reference' ? origin.source : undefined;
|
|
183
|
+
const refRow = progressSource
|
|
184
|
+
? await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source: progressSource } })
|
|
185
|
+
: null;
|
|
186
|
+
const adapterForSteps = refRow ? (0, reference_adapter_js_1.getAdapter)(refRow.adapterType) : undefined;
|
|
187
|
+
const declaredSteps = adapterForSteps?.masterSteps?.length;
|
|
188
|
+
const stepTotal = declaredSteps === undefined ? undefined : declaredSteps + reference_progress_js_1.HOST_STEPS.length;
|
|
189
|
+
const siteId = origin.siteId ?? instanceId;
|
|
190
|
+
let lastDone = 0;
|
|
191
|
+
let lastStep = (adapterForSteps?.masterSteps?.[0] ?? 'provision');
|
|
192
|
+
const emit = (p) => {
|
|
193
|
+
if (!progressSource)
|
|
194
|
+
return;
|
|
195
|
+
lastDone = p.done;
|
|
196
|
+
lastStep = p.step;
|
|
197
|
+
shell_1.pubsub.publish('twin-reference-progress', {
|
|
198
|
+
twinReferenceProgress: { ...p, siteId, siteIndex: 0, siteCount: 1, total: p.total ?? stepTotal, source: progressSource }
|
|
199
|
+
});
|
|
200
|
+
};
|
|
172
201
|
try {
|
|
173
|
-
const master = await this.masterFromOrigin(domainId, origin, instanceId);
|
|
202
|
+
const master = await this.masterFromOrigin(domainId, origin, instanceId, st => emit({ step: st.key, done: st.done, total: stepTotal, detail: st.detail }));
|
|
203
|
+
emit({ step: 'provision', done: declaredSteps ?? 0, total: stepTotal });
|
|
174
204
|
/*
|
|
175
205
|
* **어느 현장의 트윈이었나를 지킨다** — 다시 읽기는 구조만 새로 그리는 일이고, 현장 소속은 그때
|
|
176
206
|
* 사람이 고른 것이다. 기억이 없는 옛 트윈은 **지금 있는 현장**을 그대로 쓴다(빈손으로 두면 템플릿
|
|
@@ -179,14 +209,44 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
179
209
|
const keepSpace = origin.spaceId || inst.spaceId;
|
|
180
210
|
/* 다시 읽기는 **구조만** 새로 그린다 — 재기동 정책은 그 트윈의 선언이므로 그대로 지킨다. */
|
|
181
211
|
const res = await index_js_1.TwinEngine.ingestMaster(domainId, master, (0, restart_policy_js_1.readRestartPolicy)(inst.restartPolicy, `resync of twin "${instanceId}"`), keepSpace ? { spaceId: keepSpace } : undefined, context.state.user);
|
|
212
|
+
emit({ step: 'start', done: (declaredSteps ?? 0) + 1, total: stepTotal });
|
|
213
|
+
/*
|
|
214
|
+
* **총평도 새로 남긴다.** 다시 읽었는데 총평이 옛것이면 화면이 지난 읽기를 현재로 보여 준다 —
|
|
215
|
+
* 그 표를 보고 사람이 원본을 고치러 간다.
|
|
216
|
+
*/
|
|
217
|
+
if (refRow && progressSource) {
|
|
218
|
+
const prevSpec = refRow.scopeSpec ?? {};
|
|
219
|
+
await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).update({ id: refRow.id }, {
|
|
220
|
+
scopeSpec: { ...prevSpec, assessments: { ...(prevSpec.assessments ?? {}), [siteId]: (0, reference_assessment_js_1.assessMaster)(master, siteId) } }
|
|
221
|
+
});
|
|
222
|
+
}
|
|
182
223
|
return { ok: true, instanceId: res.instanceId, spaceId: res.spaceId, warnings: res.warnings };
|
|
183
224
|
}
|
|
184
225
|
catch (e) {
|
|
226
|
+
/* 막힌 자리를 그대로 알린다 — 「끝낸 수」의 다음 단계다(만들 때와 같은 규칙). */
|
|
227
|
+
emit({
|
|
228
|
+
step: (adapterForSteps?.masterSteps?.[lastDone] ?? lastStep),
|
|
229
|
+
done: lastDone,
|
|
230
|
+
total: stepTotal,
|
|
231
|
+
failed: true,
|
|
232
|
+
error: e?.message ?? String(e)
|
|
233
|
+
});
|
|
185
234
|
return refusal(context, e, 'resync failed');
|
|
186
235
|
}
|
|
187
236
|
}
|
|
188
237
|
/** 기억해 둔 원천에서 마스터를 다시 얻는다 — 어댑터든 템플릿이든 이 한 곳에서 갈린다. */
|
|
189
|
-
async masterFromOrigin(domainId, origin, instanceId
|
|
238
|
+
async masterFromOrigin(domainId, origin, instanceId,
|
|
239
|
+
/*
|
|
240
|
+
* **다시 읽기도 진행을 보여야 한다** (2026-08-22).
|
|
241
|
+
*
|
|
242
|
+
* 만들 때는 8단계가 화면에 흐르는데 다시 읽을 때는 아무것도 없었다 — 사용자가 버튼을 누르고
|
|
243
|
+
* 「진행되고 있는지 확인할 수가 없다」고 했다. 실제로 chef 는 원본 읽기가 14~21초이고 그 사이
|
|
244
|
+
* 화면에 아무 변화가 없다.
|
|
245
|
+
*
|
|
246
|
+
* 통로는 만들 때와 **같은 것**이다(`twin-reference-progress`). 화면도 같은 표시를 쓴다 —
|
|
247
|
+
* 두 벌을 만들면 한쪽만 고쳐지고 사람은 같은 일이 다르게 보이는 것을 결함으로 읽는다.
|
|
248
|
+
*/
|
|
249
|
+
onStep) {
|
|
190
250
|
if (origin.kind === 'template') {
|
|
191
251
|
const tpl = (0, template_registry_js_1.getTemplate)(origin.templateId);
|
|
192
252
|
if (!tpl)
|
|
@@ -202,7 +262,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
202
262
|
const inMemory = (0, reference_registry_js_1.getReference)(origin.source);
|
|
203
263
|
if (inMemory)
|
|
204
264
|
return { ...inMemory, origin };
|
|
205
|
-
const ref = await (0,
|
|
265
|
+
const ref = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source: origin.source } });
|
|
206
266
|
if (!ref)
|
|
207
267
|
throw new Error(`reference "${origin.source}" is no longer registered — nothing to re-read from`);
|
|
208
268
|
const adapter = (0, reference_adapter_js_1.getAdapter)(ref.adapterType);
|
|
@@ -225,7 +285,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
225
285
|
*/
|
|
226
286
|
const picked = (0, reference_master_js_1.pickOriginSite)(sites, origin);
|
|
227
287
|
if (picked.site)
|
|
228
|
-
return { ...(await adapter.fetchMaster(cfg, picked.site)), origin };
|
|
288
|
+
return { ...(await adapter.fetchMaster(cfg, picked.site, onStep)), origin };
|
|
229
289
|
if (picked.reason === 'site-gone')
|
|
230
290
|
throw new Error(`reference "${origin.source}" no longer reports site "${origin.siteId}" — refusing to overwrite this twin with a different site`);
|
|
231
291
|
for (const site of sites) {
|
|
@@ -299,9 +359,16 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
299
359
|
*/
|
|
300
360
|
async twinReferences(context) {
|
|
301
361
|
const domainId = context.state.domain.id;
|
|
302
|
-
const rows = await (0,
|
|
303
|
-
|
|
304
|
-
|
|
362
|
+
const rows = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).find({ where: { domain: { id: domainId } } });
|
|
363
|
+
/*
|
|
364
|
+
* provenance 라이브 대조 — 지워진 트윈은 producedCount 에서 자동 제외(상태 동기의 lazy 방식).
|
|
365
|
+
*
|
|
366
|
+
* **id 만 읽는다** (2026-08-21). 예전에는 인스턴스 행 전체를 읽었고, 그 행에는 **모델 JSON** 이
|
|
367
|
+
* 들어 있다(자리 수백 개 + 발자국 좌표). 그래서 이 목록을 여는 데 수 메가바이트를 읽고 파싱했고,
|
|
368
|
+
* 화면은 그동안 「아직 연결된 시스템이 없습니다」를 보이고 있었다 — 사용자에게는 「없다」는 답으로
|
|
369
|
+
* 읽힌다. 여기서 필요한 것은 살아 있는 id 집합 하나다.
|
|
370
|
+
*/
|
|
371
|
+
const liveIds = new Set((await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } }, select: ['instanceId'] })).map(i => i.instanceId));
|
|
305
372
|
return rows.map(r => {
|
|
306
373
|
const produced = (r.scopeSpec?.produced ?? []).filter(p => liveIds.has(p.instanceId));
|
|
307
374
|
return {
|
|
@@ -321,8 +388,8 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
321
388
|
*/
|
|
322
389
|
async twinConnections(context) {
|
|
323
390
|
const domainId = context.state.domain.id;
|
|
324
|
-
const rows = await (0,
|
|
325
|
-
const liveIds = new Set((await (0,
|
|
391
|
+
const rows = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).find({ where: { domain: { id: domainId } } });
|
|
392
|
+
const liveIds = new Set((await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => i.instanceId));
|
|
326
393
|
const groups = new Map();
|
|
327
394
|
for (const r of rows) {
|
|
328
395
|
const connectorType = r.scopeSpec?.connectorType ?? r.adapterType;
|
|
@@ -342,11 +409,11 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
342
409
|
/** 한 Connection 그룹 노드 상세 — 그 아래 생성된 트윈 인스턴스(라이브 대조·상태·기동여부). */
|
|
343
410
|
async twinConnection(source, context) {
|
|
344
411
|
const domainId = context.state.domain.id;
|
|
345
|
-
const r = await (0,
|
|
412
|
+
const r = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: domainId }, source } });
|
|
346
413
|
if (!r)
|
|
347
414
|
return null;
|
|
348
415
|
const produced = (r.scopeSpec?.produced ?? []);
|
|
349
|
-
const instMap = new Map((await (0,
|
|
416
|
+
const instMap = new Map((await (0, shell_2.getRepository)(twin_instance_js_1.TwinInstance).find({ where: { domain: { id: domainId } } })).map(i => [i.instanceId, i]));
|
|
350
417
|
const instances = produced
|
|
351
418
|
.filter(p => instMap.has(p.instanceId))
|
|
352
419
|
.map(p => {
|
|
@@ -366,24 +433,44 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
366
433
|
}
|
|
367
434
|
/** 단건 상세(뷰/편집) — connectionConfig 포함, 어댑터 스키마의 secret 필드는 마스킹(있으면 '••••••'). */
|
|
368
435
|
async twinReference(source, context) {
|
|
369
|
-
const r = await (0,
|
|
436
|
+
const r = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } });
|
|
370
437
|
if (!r)
|
|
371
438
|
return null;
|
|
372
439
|
const secretKeys = new Set(((0, reference_adapter_js_1.getAdapter)(r.adapterType)?.meta?.configSchema ?? []).filter(f => f.secret).map(f => f.key));
|
|
373
440
|
const cfg = {};
|
|
374
441
|
for (const [k, v] of Object.entries(r.connectionConfig ?? {}))
|
|
375
442
|
cfg[k] = secretKeys.has(k) ? (v ? '••••••' : '') : v;
|
|
443
|
+
/*
|
|
444
|
+
* **이 연결이 만든 트윈 id 를 함께 낸다.** 상세 화면이 「이 연결이 잘 동기화되고 있나」를 물으려면
|
|
445
|
+
* 어느 트윈을 물어야 하는지 알아야 한다. 예전에는 개수(`producedCount`)만 있어서 화면이 id 를
|
|
446
|
+
* 알 방법이 없었다.
|
|
447
|
+
*/
|
|
448
|
+
const producedInstanceIds = [
|
|
449
|
+
...new Set((r.scopeSpec?.produced ?? [])
|
|
450
|
+
.map((p) => p?.instanceId)
|
|
451
|
+
.filter((x) => typeof x === 'string' && !!x))
|
|
452
|
+
];
|
|
376
453
|
return {
|
|
377
454
|
source: r.source, system: r.system, siteName: r.siteName, description: r.description,
|
|
378
|
-
adapterType: r.adapterType, connectionConfig: cfg, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError
|
|
455
|
+
adapterType: r.adapterType, connectionConfig: cfg, status: r.status, lastSyncedAt: r.lastSyncedAt, lastError: r.lastError,
|
|
456
|
+
producedInstanceIds
|
|
379
457
|
};
|
|
380
458
|
}
|
|
381
459
|
referenceAdapters() {
|
|
382
|
-
|
|
460
|
+
/*
|
|
461
|
+
* **능력을 함께 낸다** (2026-08-21).
|
|
462
|
+
*
|
|
463
|
+
* `capabilities` 는 어댑터 뿌리에 있고 `meta` 에는 없었다. 그래서 연결 화면이 「이 원본이 라이브를
|
|
464
|
+
* 낼 수 있나」를 알 수 없었고, 트윈을 만들 때 `live` 를 말하지 못해 **재기동 정책이 없다고 거절**됐다
|
|
465
|
+
* (실 연동에서 그것에 막혔다 — 미러는 정의상 `resync` 이므로 `live` 하나로 정해진다).
|
|
466
|
+
*
|
|
467
|
+
* 화면이 그 사실을 알아야 정책을 사람에게 물을지 스스로 정할지 가를 수 있다.
|
|
468
|
+
*/
|
|
469
|
+
return (0, reference_adapter_js_1.listAdapters)().map(a => ({ type: a.type, ...(a.meta ?? {}), capabilities: a.capabilities ?? [] }));
|
|
383
470
|
}
|
|
384
471
|
async saveTwinReference(source, patch, context) {
|
|
385
472
|
const domainId = context.state.domain.id;
|
|
386
|
-
const repo = (0,
|
|
473
|
+
const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
|
|
387
474
|
const existing = await repo.findOne({ where: { domain: { id: domainId }, source } });
|
|
388
475
|
const saved = await repo.save(repo.create({
|
|
389
476
|
...(existing ?? {}),
|
|
@@ -406,7 +493,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
406
493
|
/** 연결 해제 — removeTwins=true 면 이 레퍼런스가 만든 트윈(provenance)도 함께 제거(라이프사이클 연쇄). 기본은 트윈 보존(분리). */
|
|
407
494
|
async deleteTwinReference(source, context, removeTwins) {
|
|
408
495
|
const domainId = context.state.domain.id;
|
|
409
|
-
const repo = (0,
|
|
496
|
+
const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
|
|
410
497
|
const ref = await repo.findOne({ where: { domain: { id: domainId }, source } });
|
|
411
498
|
if (removeTwins && ref) {
|
|
412
499
|
for (const p of (ref.scopeSpec?.produced ?? [])) {
|
|
@@ -422,7 +509,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
422
509
|
return true;
|
|
423
510
|
}
|
|
424
511
|
async testReferenceConnection(source, context) {
|
|
425
|
-
const repo = (0,
|
|
512
|
+
const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
|
|
426
513
|
const ref = await repo.findOne({ where: { domain: { id: context.state.domain.id }, source } });
|
|
427
514
|
if (!ref)
|
|
428
515
|
return { ok: false, error: `unknown reference: ${source}` };
|
|
@@ -450,7 +537,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
450
537
|
* 연결에서 가장 자주 막히는 자리인데 자격이 틀렸는지 주소가 틀렸는지 알 수 없었다.
|
|
451
538
|
* 판정과 문장 형태는 `discovery-result`(순수)가 갖는다.
|
|
452
539
|
*/
|
|
453
|
-
const ref = await (0,
|
|
540
|
+
const ref = await (0, shell_2.getRepository)(twin_reference_js_1.TwinReference).findOne({ where: { domain: { id: context.state.domain.id }, source } });
|
|
454
541
|
if (!ref)
|
|
455
542
|
return (0, discovery_result_js_1.failed)((0, discovery_result_js_1.referenceNotFound)(source));
|
|
456
543
|
const adapter = (0, reference_adapter_js_1.getAdapter)(ref.adapterType);
|
|
@@ -486,7 +573,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
486
573
|
*/
|
|
487
574
|
async importTwinReference(source, context, siteIds, start, live, spaceId, restartPolicy) {
|
|
488
575
|
const domainId = context.state.domain.id;
|
|
489
|
-
const repo = (0,
|
|
576
|
+
const repo = (0, shell_2.getRepository)(twin_reference_js_1.TwinReference);
|
|
490
577
|
const ref = await repo.findOne({ where: { domain: { id: domainId }, source } });
|
|
491
578
|
if (!ref)
|
|
492
579
|
return { ok: false, error: `unknown reference: ${source}` };
|
|
@@ -504,9 +591,55 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
504
591
|
return { ok: false, error: refusal.message, errorCode: refusal.code, errorParams: refusal.params };
|
|
505
592
|
const instances = [];
|
|
506
593
|
const failed = [];
|
|
507
|
-
|
|
594
|
+
/*
|
|
595
|
+
* **진행을 구독으로 흘린다** (2026-08-21).
|
|
596
|
+
*
|
|
597
|
+
* 마스터 읽기는 원본에 여러 질의를 보내는 긴 작업이고, 화면은 그 사이 아무것도 알 수 없었다.
|
|
598
|
+
* 단계를 아는 것은 어댑터뿐이므로 어댑터가 말하고(표준 낱말), 호스트가 자기 두 단계(생성·기동)를
|
|
599
|
+
* 더해 흘린다.
|
|
600
|
+
*
|
|
601
|
+
* **분모는 어댑터가 선언한 것**이다(`masterSteps`). 선언하지 않은 어댑터는 `total` 이 없고, 그때
|
|
602
|
+
* 화면은 퍼센트를 만들지 않는다 — 모르는 진행률을 지어내지 않는다.
|
|
603
|
+
*/
|
|
604
|
+
const declared = adapter.masterSteps?.length;
|
|
605
|
+
const stepTotal = declared === undefined ? undefined : declared + reference_progress_js_1.HOST_STEPS.length;
|
|
606
|
+
const emit = (p) => shell_1.pubsub.publish('twin-reference-progress', {
|
|
607
|
+
twinReferenceProgress: { ...p, siteCount: sites.length, total: p.total ?? stepTotal, source }
|
|
608
|
+
});
|
|
609
|
+
/*
|
|
610
|
+
* **읽은 뒤의 총평을 사이트마다 남긴다** (2026-08-22).
|
|
611
|
+
*
|
|
612
|
+
* 총평은 읽는 순간에만 있었다 — 대화상자를 닫으면 사라지고, 다시 보려면 같은 읽기를 또 해야 했다.
|
|
613
|
+
* 그런데 사람이 그것을 묻는 자리는 「모델 살펴보기」다(트윈을 보다가 「이건 왜 비었나」를 묻는다).
|
|
614
|
+
* 그래서 레퍼런스 행에 남겨 그 화면이 언제든 읽게 한다.
|
|
615
|
+
*
|
|
616
|
+
* 사실만 담는다(`assessMaster`) — 문장은 화면이 만들고, 더 알고 싶을 때 AI 가 이 사실만 근거로
|
|
617
|
+
* 서술한다. 다시 읽으면 그 사이트의 총평이 새것으로 바뀐다(지난 읽기의 총평을 현재로 보이게
|
|
618
|
+
* 두지 않는다).
|
|
619
|
+
*/
|
|
620
|
+
const assessments = {};
|
|
621
|
+
for (const [siteIndex, site] of sites.entries()) {
|
|
622
|
+
/*
|
|
623
|
+
* **실패를 실제로 막힌 단계에 적는다** (2026-08-22).
|
|
624
|
+
*
|
|
625
|
+
* 예전에는 실패를 무조건 `provision` 으로 적었다. 그래서 원본을 읽다 끊긴 것도 화면에는
|
|
626
|
+
* 「트윈 생성에서 실패」로 떴다 — 사람이 원인을 엉뚱한 자리에서 찾는다(실제로 그렇게 됐다).
|
|
627
|
+
*
|
|
628
|
+
* 규약이 답을 준다: `done` 은 **끝낸 단계 수**다(`ReferenceProgress.done`). 그러면 지금 막힌 것은
|
|
629
|
+
* 그 다음 단계, 즉 `masterSteps[done]` 이다. 그 표를 넘어서면(호스트 단계) 마지막으로 알린 것을 쓴다.
|
|
630
|
+
*
|
|
631
|
+
* 이 규칙은 두 가지 보고 방식에 함께 맞는다 — 단계 **시작**에 알리는 어댑터(`done` 이 아직 0)와
|
|
632
|
+
* 단계 **완료**에 알리는 어댑터(`done` 이 1 늘어난다) 모두 「끝낸 수」만 지키면 된다.
|
|
633
|
+
*/
|
|
634
|
+
let lastDone = 0;
|
|
635
|
+
let lastStep = (adapter.masterSteps?.[0] ?? 'provision');
|
|
636
|
+
const track = (p) => {
|
|
637
|
+
lastDone = p.done;
|
|
638
|
+
lastStep = p.step;
|
|
639
|
+
emit(p);
|
|
640
|
+
};
|
|
508
641
|
try {
|
|
509
|
-
const master = await adapter.fetchMaster(cfg, site);
|
|
642
|
+
const master = await adapter.fetchMaster(cfg, site, st => track({ siteId: site.siteId, siteIndex, step: st.key, done: st.done, total: stepTotal, detail: st.detail }));
|
|
510
643
|
/* 어느 레퍼런스의 **어느 사이트**에서 왔는지 남긴다 — 다시 읽기가 같은 어댑터·같은 사이트로 돌아오려면
|
|
511
644
|
사이트 정체가 있어야 한다(`source` 는 참조 이름이라 사이트 전부에 같다). */
|
|
512
645
|
/*
|
|
@@ -514,11 +647,18 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
514
647
|
* 미러는 정의상 `resync` 다(외부가 진실이므로 우리 과거를 이어 붙이지 않는다). 시뮬로 띄우려면
|
|
515
648
|
* 스스로 선언해야 한다 — 그 자리에서 우리가 고르면 재기동마다 이력을 지우는 트윈이 조용히 생긴다.
|
|
516
649
|
*/
|
|
650
|
+
assessments[site.siteId] = (0, reference_assessment_js_1.assessMaster)(master, site.siteId);
|
|
517
651
|
const policy = (0, restart_policy_js_1.readRestartPolicy)(restartPolicy ?? (live ? 'resync' : undefined), `importTwinReference("${source}")`);
|
|
652
|
+
track({ siteId: site.siteId, siteIndex, step: 'provision', done: declared ?? 0, total: stepTotal });
|
|
518
653
|
const res = await index_js_1.TwinEngine.ingestMaster(domainId, { ...master, origin: { kind: 'reference', source, siteId: site.siteId, ...(spaceId ? { spaceId } : {}) } }, policy, { spaceId }, context.state.user);
|
|
654
|
+
track({ siteId: site.siteId, siteIndex, step: 'start', done: (declared ?? 0) + 1, total: stepTotal });
|
|
519
655
|
if (start !== false) {
|
|
520
656
|
// live=true + 어댑터가 openLiveFeed 지원 → mirror(실 이벤트 미러). 아니면 sim 기동(fallback).
|
|
521
|
-
|
|
657
|
+
/* 읽기 커서를 저장할 자리를 함께 넘긴다 — 레퍼런스의 이름은 호스트가 붙이는 것이고
|
|
658
|
+
커넥터는 그것을 알 수 없다(§`startReferenceLiveFeed`). */
|
|
659
|
+
const wentLive = live
|
|
660
|
+
? await (0, reference_live_js_1.startReferenceLiveFeed)(domainId, ref.adapterType, cfg, site, res.instanceId, ref.source)
|
|
661
|
+
: false;
|
|
522
662
|
if (!wentLive)
|
|
523
663
|
await index_js_1.TwinEngine.startFromRegistry(domainId, res.instanceId);
|
|
524
664
|
instances.push({ siteId: site.siteId, instanceId: res.instanceId, spaceId: res.spaceId, mode: wentLive ? 'live' : 'sim', warnings: res.warnings });
|
|
@@ -528,6 +668,12 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
528
668
|
}
|
|
529
669
|
}
|
|
530
670
|
catch (e) {
|
|
671
|
+
/*
|
|
672
|
+
* **실패한 단계를 그대로 알린다.** 화면이 진행 표시를 지우지 않고 그 자리를 붉게 두어야
|
|
673
|
+
* 사람이 「어디까지 갔는지」를 안다. 막힌 자리는 「끝낸 수」의 다음 단계다(위 주석).
|
|
674
|
+
*/
|
|
675
|
+
const at = (adapter.masterSteps?.[lastDone] ?? lastStep);
|
|
676
|
+
emit({ siteId: site.siteId, siteIndex, step: at, done: lastDone, total: stepTotal, failed: true, error: e?.message ?? String(e) });
|
|
531
677
|
failed.push({ siteId: site.siteId, error: e?.message ?? 'failed' });
|
|
532
678
|
}
|
|
533
679
|
}
|
|
@@ -537,6 +683,10 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
537
683
|
await repo.update({ id: ref.id }, {
|
|
538
684
|
status: 'connected',
|
|
539
685
|
lastSyncedAt: new Date().toISOString(),
|
|
686
|
+
/* 못 옮긴 값을 **세어 남긴다**. 아무 인스턴스도 보고하지 않았으면 `null` — 「없었다」로 위장하지 않는다. */
|
|
687
|
+
lastWarningCount: instances.some((i) => Array.isArray(i.warnings))
|
|
688
|
+
? instances.reduce((n, i) => n + (Array.isArray(i.warnings) ? i.warnings.length : 0), 0)
|
|
689
|
+
: null,
|
|
540
690
|
/*
|
|
541
691
|
* **영어 canonical 로 남긴다.** 이 값은 DB 에 저장되고 연결 화면이 그대로 뿌린다 — 예전에는
|
|
542
692
|
* 한글 산문(`N개 사이트 실패`)이라 다섯 언어 화면에 한글이 새어 나갔다. 어댑터가 주는 사유도
|
|
@@ -544,7 +694,24 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
544
694
|
* 어느 사이트가 왜 실패했는지는 `failed[]` 가 답한다 — 화면이 그것을 보여 준다.
|
|
545
695
|
*/
|
|
546
696
|
lastError: failed.length ? `${failed.length} of ${sites.length} site(s) failed: ${failed.map((f) => f.siteId).join(', ')}` : null,
|
|
547
|
-
|
|
697
|
+
/*
|
|
698
|
+
* ── 실패 사유를 **남긴다** (2026-08-21) ────────────────────────────────
|
|
699
|
+
*
|
|
700
|
+
* 사유는 대화상자에만 있었다. 닫으면 사라지고, 다시 보려면 같은 실패를 다시 만들어야 했다 —
|
|
701
|
+
* 실제로 「승화푸드」 연결이 그 상태였다(요약 한 줄만 남고 원인은 어디에도 없었다).
|
|
702
|
+
*
|
|
703
|
+
* `scopeSpec` 은 이미 이 레퍼런스의 부속 사실을 담는 자리이므로(`produced`) 스키마를 늘리지 않고
|
|
704
|
+
* 여기 적는다. 성공한 회차에는 **비운다** — 지나간 실패를 현재 상태처럼 보이게 두지 않는다.
|
|
705
|
+
*/
|
|
706
|
+
scopeSpec: {
|
|
707
|
+
...(ref.scopeSpec ?? {}),
|
|
708
|
+
produced: [...prev, ...producedNew],
|
|
709
|
+
/* 이번에 읽은 사이트의 총평만 갈아 끼운다 — 읽지 않은 사이트의 것은 그대로 둔다. */
|
|
710
|
+
assessments: { ...((ref.scopeSpec ?? {}).assessments ?? {}), ...assessments },
|
|
711
|
+
...(failed.length
|
|
712
|
+
? { lastFailures: failed.map((f) => ({ siteId: f.siteId, error: f.error, at: new Date().toISOString() })) }
|
|
713
|
+
: { lastFailures: [] })
|
|
714
|
+
}
|
|
548
715
|
});
|
|
549
716
|
return { ok: instances.length > 0, instances, failed };
|
|
550
717
|
}
|
|
@@ -557,7 +724,7 @@ let TwinReferenceResolver = class TwinReferenceResolver {
|
|
|
557
724
|
};
|
|
558
725
|
exports.TwinReferenceResolver = TwinReferenceResolver;
|
|
559
726
|
tslib_1.__decorate([
|
|
560
|
-
(0, type_graphql_1.Query)(returns => [
|
|
727
|
+
(0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List registered reference sources (virtual or real adapters) available to ingest.' }),
|
|
561
728
|
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
562
729
|
tslib_1.__metadata("design:type", Function),
|
|
563
730
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
@@ -565,7 +732,7 @@ tslib_1.__decorate([
|
|
|
565
732
|
], TwinReferenceResolver.prototype, "referenceSources", null);
|
|
566
733
|
tslib_1.__decorate([
|
|
567
734
|
(0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
|
|
568
|
-
(0, type_graphql_1.Mutation)(returns =>
|
|
735
|
+
(0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
|
|
569
736
|
description: "Ingest a registered reference source into a twin (space + instance). Optionally start it. restartPolicy declares how the new twin treats its own past on reboot: 'resync' (read the source again) | 'resume' (continue its journal) | 'reset' (wipe and replay from the seed). It has no default — a twin cannot exist without the declaration."
|
|
570
737
|
}),
|
|
571
738
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|
|
@@ -578,7 +745,7 @@ tslib_1.__decorate([
|
|
|
578
745
|
], TwinReferenceResolver.prototype, "importFromReference", null);
|
|
579
746
|
tslib_1.__decorate([
|
|
580
747
|
(0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
|
|
581
|
-
(0, type_graphql_1.Mutation)(returns =>
|
|
748
|
+
(0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
|
|
582
749
|
description: "Re-read a twin's structure from the source it remembers (TwinInstance.origin). Works for both reference- and template-born twins. A running mirror adopts the new structure without stopping; a running simulation is refused."
|
|
583
750
|
}),
|
|
584
751
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('instanceId')),
|
|
@@ -588,7 +755,7 @@ tslib_1.__decorate([
|
|
|
588
755
|
tslib_1.__metadata("design:returntype", Promise)
|
|
589
756
|
], TwinReferenceResolver.prototype, "resyncTwin", null);
|
|
590
757
|
tslib_1.__decorate([
|
|
591
|
-
(0, type_graphql_1.Query)(returns => [
|
|
758
|
+
(0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List registered twin templates (parameterized archetypes) with their knob schema.' }),
|
|
592
759
|
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
593
760
|
tslib_1.__metadata("design:type", Function),
|
|
594
761
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
@@ -596,11 +763,11 @@ tslib_1.__decorate([
|
|
|
596
763
|
], TwinReferenceResolver.prototype, "twinTemplates", null);
|
|
597
764
|
tslib_1.__decorate([
|
|
598
765
|
(0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
|
|
599
|
-
(0, type_graphql_1.Mutation)(returns =>
|
|
766
|
+
(0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
|
|
600
767
|
description: "Instantiate a twin template with params → synthetic master → ingest (+start+scenario). restartPolicy declares how the new twin treats its own past on reboot ('resync' | 'resume' | 'reset') — there is no default. Returns {ok, instanceId, spaceId}."
|
|
601
768
|
}),
|
|
602
769
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('templateId')),
|
|
603
|
-
tslib_1.__param(1, (0, type_graphql_1.Arg)('params', type =>
|
|
770
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('params', type => shell_2.ScalarObject)),
|
|
604
771
|
tslib_1.__param(2, (0, type_graphql_1.Arg)('restartPolicy')),
|
|
605
772
|
tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
|
|
606
773
|
tslib_1.__param(4, (0, type_graphql_1.Arg)('start', { nullable: true })),
|
|
@@ -610,7 +777,7 @@ tslib_1.__decorate([
|
|
|
610
777
|
tslib_1.__metadata("design:returntype", Promise)
|
|
611
778
|
], TwinReferenceResolver.prototype, "createFromTemplate", null);
|
|
612
779
|
tslib_1.__decorate([
|
|
613
|
-
(0, type_graphql_1.Query)(returns => [
|
|
780
|
+
(0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List tenant-scoped persisted twin references (adapter-backed).' }),
|
|
614
781
|
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
615
782
|
tslib_1.__metadata("design:type", Function),
|
|
616
783
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
@@ -623,14 +790,14 @@ tslib_1.__decorate([
|
|
|
623
790
|
tslib_1.__metadata("design:returntype", Array)
|
|
624
791
|
], TwinReferenceResolver.prototype, "referenceAdapterTypes", null);
|
|
625
792
|
tslib_1.__decorate([
|
|
626
|
-
(0, type_graphql_1.Query)(returns => [
|
|
793
|
+
(0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'Group integration items 2-tier: connector type ▸ connection ▸ produced twins. (reference-management §2.3)' }),
|
|
627
794
|
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
628
795
|
tslib_1.__metadata("design:type", Function),
|
|
629
796
|
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
630
797
|
tslib_1.__metadata("design:returntype", Promise)
|
|
631
798
|
], TwinReferenceResolver.prototype, "twinConnections", null);
|
|
632
799
|
tslib_1.__decorate([
|
|
633
|
-
(0, type_graphql_1.Query)(returns =>
|
|
800
|
+
(0, type_graphql_1.Query)(returns => shell_2.ScalarObject, { nullable: true, description: 'One connection grouping location with its produced twin instances (live-checked). (reference-management §2.3)' }),
|
|
634
801
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|
|
635
802
|
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
636
803
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -638,7 +805,7 @@ tslib_1.__decorate([
|
|
|
638
805
|
tslib_1.__metadata("design:returntype", Promise)
|
|
639
806
|
], TwinReferenceResolver.prototype, "twinConnection", null);
|
|
640
807
|
tslib_1.__decorate([
|
|
641
|
-
(0, type_graphql_1.Query)(returns =>
|
|
808
|
+
(0, type_graphql_1.Query)(returns => shell_2.ScalarObject, { nullable: true, description: 'Get one tenant-scoped reference with its connection config (secret fields masked) for view/edit.' }),
|
|
642
809
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|
|
643
810
|
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
644
811
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -646,16 +813,16 @@ tslib_1.__decorate([
|
|
|
646
813
|
tslib_1.__metadata("design:returntype", Promise)
|
|
647
814
|
], TwinReferenceResolver.prototype, "twinReference", null);
|
|
648
815
|
tslib_1.__decorate([
|
|
649
|
-
(0, type_graphql_1.Query)(returns => [
|
|
816
|
+
(0, type_graphql_1.Query)(returns => [shell_2.ScalarObject], { description: 'List reference connector metadata (label, domain, config schema, availability, capabilities) for the connect UI.' }),
|
|
650
817
|
tslib_1.__metadata("design:type", Function),
|
|
651
818
|
tslib_1.__metadata("design:paramtypes", []),
|
|
652
819
|
tslib_1.__metadata("design:returntype", Array)
|
|
653
820
|
], TwinReferenceResolver.prototype, "referenceAdapters", null);
|
|
654
821
|
tslib_1.__decorate([
|
|
655
822
|
(0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
|
|
656
|
-
(0, type_graphql_1.Mutation)(returns =>
|
|
823
|
+
(0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, { description: 'Create or update a tenant-scoped twin reference (persisted).' }),
|
|
657
824
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|
|
658
|
-
tslib_1.__param(1, (0, type_graphql_1.Arg)('patch', type =>
|
|
825
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('patch', type => shell_2.ScalarObject)),
|
|
659
826
|
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
660
827
|
tslib_1.__metadata("design:type", Function),
|
|
661
828
|
tslib_1.__metadata("design:paramtypes", [String, Object, Object]),
|
|
@@ -673,7 +840,7 @@ tslib_1.__decorate([
|
|
|
673
840
|
], TwinReferenceResolver.prototype, "deleteTwinReference", null);
|
|
674
841
|
tslib_1.__decorate([
|
|
675
842
|
(0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
|
|
676
|
-
(0, type_graphql_1.Mutation)(returns =>
|
|
843
|
+
(0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, { description: 'Test a reference connection via its adapter; updates status.' }),
|
|
677
844
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|
|
678
845
|
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
679
846
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -681,7 +848,7 @@ tslib_1.__decorate([
|
|
|
681
848
|
tslib_1.__metadata("design:returntype", Promise)
|
|
682
849
|
], TwinReferenceResolver.prototype, "testReferenceConnection", null);
|
|
683
850
|
tslib_1.__decorate([
|
|
684
|
-
(0, type_graphql_1.Query)(returns =>
|
|
851
|
+
(0, type_graphql_1.Query)(returns => shell_2.ScalarObject, { description: 'Discover sites/factories exposed by a reference. Returns { sites, error? } — an empty list with no error means the system genuinely has none, which is different from a failure.' }),
|
|
685
852
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|
|
686
853
|
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
687
854
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -690,7 +857,7 @@ tslib_1.__decorate([
|
|
|
690
857
|
], TwinReferenceResolver.prototype, "discoverReferenceSites", null);
|
|
691
858
|
tslib_1.__decorate([
|
|
692
859
|
(0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
|
|
693
|
-
(0, type_graphql_1.Mutation)(returns =>
|
|
860
|
+
(0, type_graphql_1.Mutation)(returns => shell_2.ScalarObject, {
|
|
694
861
|
description: "Create twins from a reference: discover sites → filter by siteIds (if given) → fetch master(s) → provision. spaceId co-locates the twin into an existing space (one site only). start=false to only provision; live=true to run as a mirror (adapter openLiveFeed → live projector) instead of sim. restartPolicy declares how each new twin treats its own past on reboot ('resync' | 'resume' | 'reset'); omit it and live=true implies 'resync' — a mirror reads the source again — while a simulation must declare 'resume' or 'reset' for itself."
|
|
695
862
|
}),
|
|
696
863
|
tslib_1.__param(0, (0, type_graphql_1.Arg)('source')),
|