@things-factory/headless-twin 10.0.11 → 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 +81 -3
- package/dist-server/engine/canonical-ingest.js +89 -10
- 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/declared-stimulus.d.ts +43 -0
- package/dist-server/engine/declared-stimulus.js +57 -0
- package/dist-server/engine/declared-stimulus.js.map +1 -0
- package/dist-server/engine/index.d.ts +5 -0
- package/dist-server/engine/index.js +6 -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 +39 -0
- package/dist-server/engine/kpi-fold.js +68 -5
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.d.ts +3 -3
- package/dist-server/engine/kpi-query.js +132 -18
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/live-feed-registry.d.ts +1 -1
- package/dist-server/engine/live-feed-registry.js +3 -17
- 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/local-declarations.d.ts +3 -6
- package/dist-server/engine/local-declarations.js +97 -16
- package/dist-server/engine/local-declarations.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/measured-yield.d.ts +42 -0
- package/dist-server/engine/measured-yield.js +75 -0
- package/dist-server/engine/measured-yield.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/operation-basis.d.ts +16 -0
- package/dist-server/engine/operation-basis.js +20 -2
- package/dist-server/engine/operation-basis.js.map +1 -1
- package/dist-server/engine/property-effects.js +17 -0
- package/dist-server/engine/property-effects.js.map +1 -1
- package/dist-server/engine/restart-policy.d.ts +13 -0
- package/dist-server/engine/restart-policy.js +52 -0
- package/dist-server/engine/restart-policy.js.map +1 -0
- package/dist-server/engine/runtime-key.js +1 -1
- package/dist-server/engine/runtime-key.js.map +1 -1
- package/dist-server/engine/spec-coverage.d.ts +8 -0
- package/dist-server/engine/spec-coverage.js +3 -1
- package/dist-server/engine/spec-coverage.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 +400 -31
- package/dist-server/engine/twin-engine.js +1198 -187
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/index.js +35 -3
- 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/control-routing.d.ts +14 -0
- package/dist-server/service/reference/control-routing.js +64 -0
- package/dist-server/service/reference/control-routing.js.map +1 -0
- 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 +5 -1
- package/dist-server/service/reference/index.js +8 -1
- package/dist-server/service/reference/index.js.map +1 -1
- package/dist-server/service/reference/reference-adapter.d.ts +251 -3
- package/dist-server/service/reference/reference-adapter.js +43 -1
- 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 +119 -14
- 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.d.ts +3 -3
- package/dist-server/service/reference/reference-resolver.js +242 -58
- 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-audit/command-audit.d.ts +34 -0
- package/dist-server/service/twin-audit/command-audit.js +15 -1
- package/dist-server/service/twin-audit/command-audit.js.map +1 -1
- package/dist-server/service/twin-audit/twin-audit-event.d.ts +3 -0
- package/dist-server/service/twin-audit/twin-audit-event.js +10 -0
- package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -1
- package/dist-server/service/twin-control/twin-control-mutation.d.ts +15 -2
- package/dist-server/service/twin-control/twin-control-mutation.js +88 -36
- 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.d.ts +1 -1
- package/dist-server/service/twin-instance/twin-instance.js +2 -2
- 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 +74 -3
- 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 +157 -5
- 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 +164 -15
- package/server/engine/command-routing.ts +1 -1
- package/server/engine/declared-stimulus.ts +66 -0
- package/server/engine/index.ts +6 -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 +101 -5
- package/server/engine/kpi-query.ts +137 -23
- package/server/engine/live-feed-registry.ts +4 -3
- package/server/engine/load-meter.ts +12 -3
- package/server/engine/local-declarations.ts +97 -19
- package/server/engine/log.ts +72 -0
- package/server/engine/loop-lag.ts +120 -0
- package/server/engine/measured-yield.ts +89 -0
- package/server/engine/model-gap.ts +168 -0
- package/server/engine/operation-basis.ts +33 -2
- package/server/engine/property-effects.ts +17 -0
- package/server/engine/restart-policy.ts +55 -0
- package/server/engine/runtime-key.ts +1 -1
- package/server/engine/spec-coverage.ts +23 -3
- package/server/engine/stage-path.ts +172 -0
- package/server/engine/twin-engine.ts +1318 -186
- package/server/index.ts +36 -3
- 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/control-routing.ts +62 -0
- package/server/service/reference/discovery-result.ts +1 -1
- package/server/service/reference/index.ts +7 -1
- package/server/service/reference/reference-adapter.ts +275 -5
- package/server/service/reference/reference-assessment.ts +215 -0
- package/server/service/reference/reference-live.ts +126 -14
- 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 +246 -19
- package/server/service/reference/twin-reference.ts +39 -1
- package/server/service/twin-audit/command-audit.ts +34 -1
- package/server/service/twin-audit/twin-audit-event.ts +20 -0
- package/server/service/twin-control/twin-control-mutation.ts +78 -30
- 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 +16 -10
- package/server/service/twin-journal/twin-journal-query.ts +59 -5
- package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +79 -4
- 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 +156 -5
- 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/adopt-structure-live.test.ts +7 -7
- package/test/axis-journal-evidence.test.ts +71 -0
- package/test/axis-read.test.ts +101 -1
- package/test/boot-resume.test.ts +93 -27
- 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/control-capability.test.ts +103 -0
- package/test/declared-location-types.test.ts +89 -0
- package/test/declared-stimulus.test.ts +88 -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/ingest-running-guard.test.ts +5 -5
- package/test/instance-cache-lifecycle.test.ts +1 -1
- 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-baseline-db.test.ts +1 -1
- package/test/kpi-fold.test.ts +90 -3
- package/test/kpi-query-bench.test.ts +3 -3
- package/test/lineage-survives-restart.test.ts +20 -4
- package/test/live-cursor-wiring.test.ts +87 -0
- package/test/live-feed-registry.test.ts +15 -7
- 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 +109 -2
- package/test/log-stamp.test.ts +59 -0
- package/test/loop-lag.test.ts +82 -0
- package/test/measured-yield.test.ts +90 -0
- package/test/model-gap.test.ts +153 -0
- package/test/oee-accumulator.test.ts +4 -0
- package/test/operation-basis.test.ts +28 -1
- package/test/operational-vocabulary.test.ts +108 -0
- package/test/operations-capability-db.test.ts +4 -4
- package/test/project-structure-db.test.ts +1 -1
- package/test/projection-reaches-screen.test.ts +1 -1
- package/test/property-effects.test.ts +28 -0
- 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 +111 -0
- package/test/resync-origin-site.test.ts +7 -1
- 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/source-outcome-audit.test.ts +104 -0
- 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 +31 -27
- package/test/tenant-registry-db.test.ts +3 -3
- 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 +5 -3
- package/test/twin-model-tree-db.test.ts +7 -7
- package/test/twin-origin-resync.test.ts +4 -4
- package/test/warm-start-seam.test.ts +4 -0
- package/test/yield-loop.test.ts +199 -0
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twin-space-resolver.js","sourceRoot":"","sources":["../../../server/service/twin-space/twin-space-resolver.ts"],"names":[],"mappings":";;;;AAAA,+CAA4E;AAE5E,iDAAmE;AAEnE,mDAA2C;AAC3C,iFAAwE;AACxE,6DAAoD;AACpD,iDAAyC;AACzC,wEAAgE;AAChE,2EAAkE;AAClE,oDAAkD;AAClD,mDAA0E;AAC1E,6DAA+F;AAE/F;;;GAGG;AAEI,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAC5B,uEAAuE;IACvE;;;;;;;;;OASG;IAEG,AAAN,KAAK,CAAC,UAAU,CAAQ,OAAwB;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5C,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC;YACnG;8EACkE;YAClE,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;YAChH,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;SACpJ,CAAC,CAAA;QAEF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAA;QAC1C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,EAAE,CAAA;YACzB,IAAI,GAAG;gBAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC1D,CAAC;QACD,oEAAoE;QACpE,MAAM,OAAO,GAAG,IAAI,GAAG,EAA+B,CAAA;QACtD,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,IAAK,CAAS,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAA;QAE5J,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAClB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;YACpC,OAAO;gBACL,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,uBAAuB,EAAE,CAAC,CAAC,uBAAuB;gBAClD,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,mBAAmB,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC;gBAC5C,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,MAAM,EAAE,KAAK,EAAE,MAAM;aACtB,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,0BAA0B;IAEpB,AAAN,KAAK,CAAC,SAAS,CAAiB,OAAe,EAAS,OAAwB;QAC9E,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,CAAC,GAAG,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QAClG,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;QACnB,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;QACnJ,MAAM,eAAe,GAAU,EAAE,CAAA;QACjC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;YAC3J,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;QACnR,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,uBAAuB,EAAE,CAAC,CAAC,uBAAuB,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,CAAA;IACxN,CAAC;IAIK,AAAN,KAAK,CAAC,aAAa,CACD,OAAe,EACK,KAAU,EACvC,OAAwB;QAE/B,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAA;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACrF,mEAAmE;QACnE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,IAAI,EAAE,CAAA;QAC3C,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;QACzG,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;;;;;;OASG;IAMG,AAAN,KAAK,CAAC,eAAe,CAAiB,OAAe,EAAS,OAAwB;QACpF,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,0DAA0D;QAC1D,8DAA8D;QAC9D,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACtG,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,CAAA;YACpD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,SAAS,EAAE,iBAAiB;gBAC5B,WAAW,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAClF,KAAK,EAAE,UAAU,OAAO,eAAe,KAAK,CAAC,MAAM,yCAAyC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;aAChH,CAAA;QACH,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACtG,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;YAChI,KAAK,MAAM,GAAG,IAAI,IAAI;gBAAE,MAAM,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAS,EAAE,CAAC,CAAA;YAC7I,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAS,EAAE,CAAC,CAAA;YACxH,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAS,EAAE,CAAC,CAAA,CAAC,kBAAkB;QAC9H,CAAC;QACD,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,OAAO,EAAE,CAAC,CAAA;QACnF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;IACrB,CAAC;IAED;;;;;;;;;;OAUG;IAMG,AAAN,KAAK,CAAC,eAAe,CACA,UAAkB,EACrB,OAAe,EACxB,OAAwB,EACyE,MAAgB;QAExH,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,QAAQ,GAAG,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAA;QAC5C,MAAM,SAAS,GAAG,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAA;QAE1C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAA;QACxF,MAAM,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC3H,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QAEpF,4CAA4C;QAC5C,MAAM,SAAS,GAAG,EAAE;YAClB,CAAC,CAAC,CAAC,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACtI,CAAC,CAAC,EAAE,CAAA;QACN,MAAM,uBAAuB,GAAG,IAAI;YAClC,CAAC,CAAC,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAS,EAAE,EAAE,CAAC;YACnI,CAAC,CAAC,CAAC,CAAA;QACL,MAAM,KAAK,GAAQ,IAAI,EAAE,KAAK,IAAI,EAAE,CAAA;QACpC,MAAM,QAAQ,GAA2B,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;QAE7F,MAAM,SAAS,GAAG,IAAA,kCAAkB,EAAC;YACnC,UAAU,EAAE,IAAI,EAAE,UAAU;YAC5B,WAAW,EAAE,IAAI,EAAE,OAAO;YAC1B,SAAS,EAAE,OAAO;YAClB,aAAa,EAAE,CAAC,CAAC,EAAE;YACnB,OAAO,EAAG,IAAY,EAAE,OAAO;YAC/B,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,qBAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC;YAC7D,YAAY,EAAE,IAAI,EAAE,QAAQ,IAAI,SAAS;YACzC,UAAU,EAAE,EAAE,EAAE,QAAQ,IAAI,SAAS;YACrC,QAAQ;YACR,SAAS;YACT,uBAAuB;SACxB,CAAC,CAAA;QACF,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAA;YAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QAChG,CAAC;QACD,IAAI,MAAM;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAA;QAE3E,0DAA0D;QAC1D,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAA;QACnC,MAAM,QAAQ,GAAG,MAAM,qBAAU,CAAC,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;QAC7E,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAI,IAAY,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;QAEpF;;;WAGG;QACH,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,oCAAc,CAAC,CAAA;YAC1C,MAAM,IAAI,CAAC,IAAI,CACb,IAAI,CAAC,MAAM,CAAC;gBACV,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;gBAC5B,UAAU;gBACV,WAAW,EAAE,kBAAkB;gBAC/B,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE;gBAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;aAC3F,CAAC,CACV,CAAA;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,6CAA6C,UAAU,GAAG,EAAE,GAAG,CAAC,CAAA;QAChF,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAA;IACnD,CAAC;IAED;;;;;;OAMG;IAMG,AAAN,KAAK,CAAC,mBAAmB,CACJ,UAAkB,EAC9B,OAAwB,EAC4E,MAAgB;QAE3H,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,QAAQ,GAAG,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAA;QAC5C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAA;QACxF,MAAM,IAAI,GAAG,IAAI,EAAE,OAAO;YACxB,CAAC,CAAC,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACxG,CAAC,CAAC,IAAI,CAAA;QACR,MAAM,uBAAuB,GAAG,IAAI;YAClC,CAAC,CAAC,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAS,EAAE,EAAE,CAAC;YACnI,CAAC,CAAC,CAAC,CAAA;QAEL,MAAM,SAAS,GAAG,IAAA,oCAAoB,EAAC;YACrC,UAAU,EAAE,IAAI,EAAE,UAAU;YAC5B,WAAW,EAAE,IAAI,EAAE,OAAO;YAC1B,OAAO,EAAG,IAAY,EAAE,OAAO;YAC/B,uBAAuB;YACvB,YAAY,EAAE,IAAI,EAAE,QAAQ,IAAI,SAAS;SAC1C,CAAC,CAAA;QACF,IAAI,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAA;YAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;QAChG,CAAC;QACD,IAAI,MAAM;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAA;QAE3E;+EACuE;QACvE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,GAAI,IAAI,EAAE,KAAa,IAAI,EAAE,CAAA;QAClE,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAG,IAAY,CAAC,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAW,EAAE,KAAK,EAAE,CAAC,CAAA;QAEhF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,oCAAc,CAAC,CAAA;YAC1C,MAAM,IAAI,CAAC,IAAI,CACb,IAAI,CAAC,MAAM,CAAC;gBACV,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;gBAC5B,UAAU;gBACV,WAAW,EAAE,sBAAsB;gBACnC,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE;gBAC/B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;aAC9E,CAAC,CACV,CAAA;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,+CAA+C,UAAU,GAAG,EAAE,GAAG,CAAC,CAAA;QAClF,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAA;IACnD,CAAC;IAED;;;;;;;;OAQG;IAKG,AAAN,KAAK,CAAC,kBAAkB,CACf,OAAwB,EACK,OAAgB;QAEpD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,SAAS,GAAG,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAA;QAC9F,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,+BAAY,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAA;QAChG,MAAM,OAAO,GAAG,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAChI,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAClH,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;QAEhI,MAAM,YAAY,GAA6B,EAAE,CAAA;QACjD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,GAAG,GAAI,CAAS,CAAC,KAAK,EAAE,OAAO,CAAA;YACrC,IAAI,CAAC,GAAG;gBAAE,SACT;YAAA,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAC5C,CAAC;QAED;;;WAGG;QACH,MAAM,UAAU,GAAuC,EAAE,CAAA;QACzD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,GAAG,GAAI,CAAS,CAAC,cAAc,EAAE,EAAE,CAAA;YACzC,IAAI,CAAC,GAAG;gBAAE,SAAQ;YAClB,MAAM,CAAC,GAAQ,CAAC,CAAC,OAAO,IAAI,EAAE,CAAA;YAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,CAAA;YACnC,IAAI,CAAC,CAAC,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;YAC1D,MAAM,OAAO,GAAa,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YAC3H,KAAK,MAAM,CAAC,IAAI,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;QACvF,CAAC;QAED;yEACiE;QACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAE,CAAC,CAAC,MAAc,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAAA;QAEzF,MAAM,QAAQ,GAAG,IAAA,wCAAmB,EAAC;YACnC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC,uBAAuB,EAAE,CAAC,CAAC;YACxG,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAC1B,MAAM,KAAK,GAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAA;gBAChC;;;;mBAIG;gBACH,MAAM,IAAI,GAAQ,qBAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;oBAC5D,CAAC,CAAC,qBAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC;oBAC7C,CAAC,CAAC,SAAS,CAAA;gBACb,OAAO;oBACL,UAAU,EAAE,CAAC,CAAC,UAAU;oBACxB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,YAAY,EAAE,KAAK,CAAC,OAAO;oBAC3B,OAAO,EAAG,CAAS,CAAC,OAAO;oBAC3B,WAAW,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;oBAC3E,YAAY,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;oBAC5E,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC;oBAC9D,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACzE,CAAA;YACH,CAAC,CAAC;YACF,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjC,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,OAAO,EAAG,CAAS,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE;gBACxC,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAG,CAAC,CAAC,MAAc,EAAE,OAAO,IAAI,IAAI;gBAC3C,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;aACjC,CAAC,CAAC;YACH,YAAY;YACZ,QAAQ;SACT,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;QAC3G,OAAO,IAAA,iCAAY,EAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IAED;;;;;;;;;;OAUG;IAMG,AAAN,KAAK,CAAC,wBAAwB,CACrB,OAAwB,EACK,OAAgB;QAEpD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,SAAS,GAAG,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAA;QAC1C,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAA;QACtD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE;SACtF,CAAC,CAAA;QACF,MAAM,QAAQ,GAAU,EAAE,CAAA;QAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAS,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;YACtI,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;YAC5D,IAAI,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC;gBAAE,SAAQ,CAAC,WAAW;YACrE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;YACtD,MAAM,IAAI,GAAG,OAAO,EAAE,EAAE,IAAI,IAAI,CAAA;YAChC,IAAI,OAAO,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;gBAAE,SAAQ;YACtC,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;YACnF,IAAI,OAAO;gBAAE,KAAK,MAAM,CAAC,IAAI,IAAI;oBAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC;wBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;YAC5J,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,gCAAgC,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QACpH,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;IACvD,CAAC;IAED,6DAA6D;IAEvD,AAAN,KAAK,CAAC,SAAS,CAAiB,OAAe,EAAS,OAAwB;QAC9E,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;QACzI,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAClH,CAAC;IAIK,AAAN,KAAK,CAAC,YAAY,CACA,OAAe,EAChB,MAAc,EACO,KAAU,EACvC,OAAwB;QAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACtG,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,OAAO,aAAa,CAAC,CAAA;QAC3D,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAA;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QAC7G,MAAM,IAAI,CAAC,IAAI,CACb,IAAI,CAAC,MAAM,CAAC;YACV,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;YACnB,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS;YAC/B,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAS;YAC9B,MAAM;YACN,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI,IAAI,MAAM;YAC7C,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI;YACnC,QAAQ,EAAE,KAAK,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ;YAC7E,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM;SAC1C,CAAC,CACH,CAAA;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IAGG,AAAN,KAAK,CAAC,cAAc,CAAiB,OAAe,EAAiB,MAAc,EAAS,OAAwB;QAClH,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACtG,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QACxB,gBAAgB;QAChB,MAAM,QAAQ,GAAG,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QACxI,6FAA6F;QAC7F,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAChI,IAAI,WAAW,GAAG,CAAC,CAAA;QACnB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;YAC9H,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAE,CAAC,CAAC,OAAe,EAAE,OAAO,KAAK,MAAM,IAAK,CAAC,CAAC,OAAe,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM,CAAA;QAC1H,CAAC;QACD,IAAI,QAAQ,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,SAAS,MAAM,6BAA6B,QAAQ,SAAS,WAAW,mBAAmB,CAAC,CAAA;QAC9G,CAAC;QACD,MAAM,IAAA,qBAAa,EAAC,uBAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAS,EAAE,MAAM,EAAE,CAAC,CAAA;QACjH,OAAO,IAAI,CAAA;IACb,CAAC;IAED,uEAAuE;IAGjE,AAAN,KAAK,CAAC,uBAAuB,CACX,OAAe,EACG,GAAQ,EACnC,OAAwB;QAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACtG,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,OAAO,EAAE,EAAE,CAAA;QACtE,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAA;QACnD,MAAM,QAAQ,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC/E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAS,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACvO,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAA;IACnC,CAAC;IAIK,AAAN,KAAK,CAAC,yBAAyB,CAAY,EAAU,EAAS,OAAwB;QACpF,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,cAAc,EAAE,EAAE,EAAE,EAAS,EAAE,CAAC,CAAA;QAC7G,MAAM,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,EAAE,EAAS,CAAC,CAAA;QACnG,OAAO,IAAI,CAAA;IACb,CAAC;IAIK,AAAN,KAAK,CAAC,wBAAwB,CAAiB,OAAe,EAAgB,KAAa,EAAS,OAAwB;QAC1H,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,SAAS,GAAG,IAAA,qBAAa,EAAC,yBAAS,CAAC,CAAA;QAC1C,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;QACvF,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QACxB,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;QACpF,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,sDAAuB,CAAC,CAAA;QACtD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACjG,KAAK,MAAM,GAAG,IAAI,IAAI;YAAE,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,CAAC;gBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC,CAAC,CAAA;QAC/I,OAAO,IAAI,CAAA;IACb,CAAC;IAED,oEAAoE;IAG9D,AAAN,KAAK,CAAC,aAAa,CACQ,gBAAwB,EACd,IAAS,EACrC,OAAwB;QAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;QACxC,MAAM,IAAI,GAAG,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAA;QACzC,MAAM,QAAQ,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACjF;mFAC2E;QAC3E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAS,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACjS,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAA;IACnC,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CAAY,EAAU,EAAS,OAAwB;QAC1E,MAAM,IAAA,qBAAa,EAAC,kCAAa,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAS,EAAE,EAAE,EAAS,CAAC,CAAA;QACxG,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AAjhBY,8CAAiB;AAatB;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,oBAAY,CAAC,EAAE,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;IACrF,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;mDAmCtB;AAIK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;IAC5G,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IAAmB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kDAWtD;AAIK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,mFAAmF,EAAE,CAAC;IAEhI,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IACd,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,CAAC,CAAA;IAClC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;sDASP;AAiBK;IALL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE;QACjC,WAAW,EACT,kKAAkK;KACrK,CAAC;IACqB,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IAAmB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wDAuB5D;AAkBK;IALL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE;QACjC,WAAW,EACT,6PAA6P;KAChQ,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IACd,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC,CAAA;;;;wDAkExG;AAcK;IALL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE;QACjC,WAAW,EACT,+OAA+O;KAClP,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC,CAAA;;;;4DAgD3G;AAeK;IAJL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,oBAAY,CAAC,EAAE;QAChC,WAAW,EACT,0OAA0O;KAC7O,CAAC;IAEC,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;;;;2DAuEpC;AAkBK;IALL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE;QACjC,WAAW,EACT,6OAA6O;KAChP,CAAC;IAEC,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;;;;iEAqBpC;AAIK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,oBAAY,CAAC,EAAE,EAAE,WAAW,EAAE,uFAAuF,EAAE,CAAC;IAC1H,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IAAmB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kDAItD;AAIK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,kFAAkF,EAAE,CAAC;IAE/H,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IACd,mBAAA,IAAA,kBAAG,EAAC,QAAQ,CAAC,CAAA;IACb,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,CAAC,CAAA;IAClC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;qDAoBP;AASK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,0GAA0G,EAAE,CAAC;IACpI,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IAAmB,mBAAA,IAAA,kBAAG,EAAC,QAAQ,CAAC,CAAA;IAAkB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;uDAkB1F;AAKK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,iEAAiE,EAAE,CAAC;IAEnH,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IACd,mBAAA,IAAA,kBAAG,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,CAAC,CAAA;IAChC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;gEASP;AAIK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;IACvD,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kEAK5D;AAIK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;IAC5D,mBAAA,IAAA,kBAAG,EAAC,SAAS,CAAC,CAAA;IAAmB,mBAAA,IAAA,kBAAG,EAAC,OAAO,CAAC,CAAA;IAAiB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;iEAUlG;AAKK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,WAAW,EAAE,kFAAkF,EAAE,CAAC;IAEpI,mBAAA,IAAA,kBAAG,EAAC,kBAAkB,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,EAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,CAAC,CAAA;IACjC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;sDASP;AAIK;IAFL,IAAA,wBAAS,EAAC,uGAAuG,CAAC;IAClH,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,wBAAwB,EAAE,CAAC;IACjD,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wDAGlD;4BAhhBU,iBAAiB;IAD7B,IAAA,uBAAQ,GAAE;GACE,iBAAiB,CAihB7B","sourcesContent":["import { Arg, Ctx, Mutation, Query, Resolver, Directive} from 'type-graphql'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { TwinSpace } from './twin-space.js'\nimport { TwinSpaceRepresentation } from './twin-space-representation.js'\nimport { TwinSpaceArea } from './twin-space-area.js'\nimport { TwinArea } from './twin-area.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinAuditEvent } from '../twin-audit/twin-audit-event.js'\nimport { TwinEngine } from '../../engine/index.js'\nimport { judgeMoveTwinSpace, judgeDetachTwinSpace } from './move-space.js'\nimport { checkSpaceIntegrity, sortFindings, type IntegrityPolygon } from './space-integrity.js'\n\n/*\n * 공간 구성 채널(design/ui/space-composition.md) — Site(Space) + 복수 표현(Representation) + 영역(Area).\n * model 내용은 board-service Board 에(표현 config.boardId 참조, 중복 저장 금지). 모두 domain 스코프.\n */\n@Resolver()\nexport class TwinSpaceResolver {\n /* ── Space(Site) ────────────────────────────────────────────────── */\n /**\n * 이 테넌트의 현장 목록.\n *\n * ── 세 번만 묻는다 (2026-08-13) ──────────────────────────────────────────\n * 예전에는 현장마다 표현 수를 세고 인스턴스를 조회했다 — 현장 13곳이면 **질의 27번**이고, 첫\n * 호출이 2.4초였다(헤더가 뜰 때마다 이 목록을 읽는다). 규모가 커지면 그대로 자란다.\n *\n * 이제 세 번 묻고 메모리에서 맞춘다: 현장 · 표현(공간 id 만) · 인스턴스(필요한 컬럼만).\n * 표현은 **id 만 실어 온다**(`loadRelationIds`) — 설정 blob 을 읽어 세는 것은 낭비다.\n */\n @Query(returns => [ScalarObject], { description: 'List tenant Spaces (Sites) in the current domain.' })\n async twinSpaces(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const [rows, reps, insts] = await Promise.all([\n getRepository(TwinSpace).find({ where: { domain: { id: domainId } }, order: { createdAt: 'ASC' } }),\n /* 관계를 **조인해서** 읽는다 — `loadRelationIds`+`select` 조합은 관계 자리를 비워 두어\n 표현 수가 전부 0 이 됐다(2026-08-13 실측으로 잡음). 조인 한 번이 현장마다 세는 것보다 싸다. */\n getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId } }, relations: { space: true } }),\n getRepository(TwinInstance).find({ where: { domain: { id: domainId } }, select: { instanceId: true, spaceId: true, purpose: true, copyOf: true } })\n ])\n\n const repCount = new Map<string, number>()\n for (const rep of reps) {\n const sid = rep.space?.id\n if (sid) repCount.set(sid, (repCount.get(sid) ?? 0) + 1)\n }\n /* 벤치 여부·원본 참조 — 인스턴스 purpose 근거(1급). 사본 현장을 헤더 선택기에서 구별·선택 가능하게. */\n const benchOf = new Map<string, { copyOf?: string }>()\n for (const i of insts) if ((i as any).purpose === 'bench' && i.spaceId && !benchOf.has(i.spaceId)) benchOf.set(i.spaceId, { copyOf: i.copyOf ?? undefined })\n\n return rows.map(r => {\n const bench = benchOf.get(r.spaceId)\n return {\n spaceId: r.spaceId,\n name: r.name,\n description: r.description,\n geo: r.geo,\n timezone: r.timezone,\n primaryRepresentationId: r.primaryRepresentationId,\n extentX: r.extentX,\n extentY: r.extentY,\n representationCount: repCount.get(r.id) ?? 0,\n bench: !!bench,\n copyOf: bench?.copyOf\n }\n })\n }\n\n /** 단건 — 표현(+영역) 트리 포함. */\n @Query(returns => ScalarObject, { nullable: true, description: 'Get one Space with its representations (and their areas).' })\n async twinSpace(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const domainId = context.state.domain.id\n const r = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!r) return null\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: r.id } }, order: { seq: 'ASC' } })\n const representations: any[] = []\n for (const rep of reps) {\n const areas = await getRepository(TwinSpaceArea).find({ where: { domain: { id: domainId }, representation: { id: rep.id } }, order: { createdAt: 'ASC' } })\n representations.push({ id: rep.id, type: rep.type, name: rep.name, seq: rep.seq, isPrimary: rep.isPrimary, config: rep.config, areas: areas.map(a => ({ id: a.id, name: a.name, type: a.type, geometry: a.geometry, drillTo: a.drillTo, binding: a.binding, style: a.style })) })\n }\n return { spaceId: r.spaceId, name: r.name, description: r.description, geo: r.geo, timezone: r.timezone, primaryRepresentationId: r.primaryRepresentationId, extentX: r.extentX, extentY: r.extentY, representations }\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Create or update a Space (name/description/geo/timezone/primaryRepresentationId).' })\n async saveTwinSpace(\n @Arg('spaceId') spaceId: string,\n @Arg('patch', type => ScalarObject) patch: any,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const repo = getRepository(TwinSpace)\n const domainId = context.state.domain.id\n const existing = await repo.findOne({ where: { domain: { id: domainId }, spaceId } })\n /* 진짜 부분 병합 — patch 에 준 키만 갱신(나머지 필드 보존). id 는 관계로 재설정하지 않도록 제외. */\n const { id: _drop, ...clean } = patch ?? {}\n await repo.save(repo.create({ ...(existing ?? {}), ...clean, domain: { id: domainId } as any, spaceId }))\n return true\n }\n\n /**\n * 공간 삭제 — **이 공간의 트윈이 있으면 거절한다.** 그래서 트윈이 현장을 잃는 일은 없다.\n *\n * ── 왜 모양을 바꿨나 (2026-08-13) ────────────────────────────────────────\n * 예전에는 `Boolean` 을 돌려주고 거절은 **한국어 문장을 던졌다.** 두 가지가 틀렸다:\n * ① 서버가 화면의 말을 정했다 — 일본어·스페인어 사용자에게 한국어가 새어 나간다.\n * ② 던진 예외를 화면이 받지 않아 **아무 일도 없는 것처럼** 보였다. 사용자는 삭제를 눌렀고\n * 화면은 그대로였다. 거절을 조용히 하는 것은 실패보다 나쁘다.\n * 이제 `{ok, errorCode, errorParams}` 로 낸다 — 화면이 `twin.compose.del.<code>` 로 말을 만든다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Delete a Space and its representations/areas. Refused while twins still live in it (a twin never loses its site this way). Returns {ok, errorCode, errorParams}.'\n })\n async deleteTwinSpace(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<any> {\n const domainId = context.state.domain.id\n // 라이프사이클 가드 — 이 공간에 바인딩된 트윈 인스턴스가 있으면 삭제 차단(dangling 방지).\n // spaceId 컬럼(space #3) 로 직접 질의 — 전 인스턴스 로드+JS필터 제거(효율·1급 질의).\n const bound = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n if (bound.length) {\n const twins = bound.map(i => i.name || i.instanceId)\n return {\n ok: false,\n errorCode: 'space-has-twins',\n errorParams: { spaceId, count: bound.length, twins: twins.slice(0, 5).join(', ') },\n error: `space \"${spaceId}\" still has ${bound.length} twin(s) — remove or move them first (${twins.join(', ')})`\n }\n }\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (space) {\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n for (const rep of reps) await getRepository(TwinSpaceArea).delete({ domain: { id: domainId } as any, representation: { id: rep.id } as any })\n await getRepository(TwinSpaceRepresentation).delete({ domain: { id: domainId } as any, space: { id: space.id } as any })\n await getRepository(TwinArea).delete({ domain: { id: domainId } as any, space: { id: space.id } as any }) // 논리 area 도 함께 정리\n }\n await getRepository(TwinSpace).delete({ domain: { id: domainId } as any, spaceId })\n return { ok: true }\n }\n\n /**\n * 이미 있는 트윈을 이 현장으로 가져온다 — **소속 갱신**(이력 이전이 아니다).\n *\n * 저널·투영 행은 `instanceId` 로 매여 있어 트윈을 따라오고, 구역·표현은 공간의 것이라 남는다\n * (근거·판정: `move-space.ts`). 그래서 이 뮤테이션이 쓰는 것은 두 곳뿐이다 —\n * 레지스트리의 `spaceId` 와 저장된 model 의 `spaceId`(커널·보드가 같은 공간을 가리켜야 한다).\n * 새 공간의 시간대로 `utcOffsetMinutes` 도 다시 파생한다(공간이 시간의 기준이다).\n *\n * `dryRun` 은 **같은 판정을 미리** 보여 준다 — 화면이 잃을 것을 먼저 말하고 사용자가 정한다.\n * 판정을 두 벌로 두면 미리보기와 실제가 어긋나므로 한 함수를 두 번 부른다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Move an existing twin into a space (co-locate it as another lens). The journal and projected rows follow the twin; areas and representations stay with the old space. dryRun returns the same judgement without writing. Returns {ok, warnings, errorCode}.'\n })\n async moveTwinToSpace(\n @Arg('instanceId') instanceId: string,\n @Arg('spaceId') spaceId: string,\n @Ctx() context: ResolverContext,\n @Arg('dryRun', { nullable: true, description: 'Judge only — report refusal/warnings without moving.' }) dryRun?: boolean\n ): Promise<any> {\n const domainId = context.state.domain.id\n const instRepo = getRepository(TwinInstance)\n const spaceRepo = getRepository(TwinSpace)\n\n const inst = await instRepo.findOne({ where: { domain: { id: domainId }, instanceId } })\n const from = inst?.spaceId ? await spaceRepo.findOne({ where: { domain: { id: domainId }, spaceId: inst.spaceId } }) : null\n const to = await spaceRepo.findOne({ where: { domain: { id: domainId }, spaceId } })\n\n /* 판정에 필요한 사실만 모아 넘긴다 — 판정 자체는 순수 모듈이 한다. */\n const toAreaIds = to\n ? (await getRepository(TwinArea).find({ where: { domain: { id: domainId } as any, space: { id: to.id } as any } })).map(a => a.areaId)\n : []\n const fromRepresentationCount = from\n ? await getRepository(TwinSpaceRepresentation).count({ where: { domain: { id: domainId } as any, space: { id: from.id } as any } })\n : 0\n const model: any = inst?.model ?? {}\n const areaRefs: (string | undefined)[] = (model.locations ?? []).map((l: any) => l?.parentId)\n\n const judgement = judgeMoveTwinSpace({\n instanceId: inst?.instanceId,\n fromSpaceId: inst?.spaceId,\n toSpaceId: spaceId,\n toSpaceExists: !!to,\n purpose: (inst as any)?.purpose,\n running: !!inst && !!TwinEngine.runtime(domainId, instanceId),\n fromTimezone: from?.timezone ?? undefined,\n toTimezone: to?.timezone ?? undefined,\n areaRefs,\n toAreaIds,\n fromRepresentationCount\n })\n if (judgement.refusal) {\n const r = judgement.refusal\n return { ok: false, error: r.message, errorCode: r.code, errorParams: r.params, warnings: [] }\n }\n if (dryRun) return { ok: true, dryRun: true, warnings: judgement.warnings }\n\n /* 두 곳을 함께 쓴다 — 레지스트리와 model 이 다른 공간을 가리키면 보드·커널이 갈라진다. */\n const moved = { ...model, spaceId }\n const withTime = await TwinEngine.withSpaceTimeBase(moved, domainId, spaceId)\n await instRepo.save(instRepo.create({ ...(inst as any), spaceId, model: withTime }))\n\n /*\n * 감사 기록 — 소속을 바꾼 것은 사람의 결정이고, 나중에 \"왜 이 트윈이 저 현장에 있나\" 를 묻게 된다.\n * 기록이 실패해도 이전 결과는 돌려준다(감사가 본업을 막지 않는다). 다만 삼키지 않고 로그에 남긴다.\n */\n try {\n const repo = getRepository(TwinAuditEvent)\n await repo.save(\n repo.create({\n domain: context.state.domain,\n instanceId,\n commandType: 'twin.moveToSpace',\n accepted: true,\n origin: 'user',\n actorId: context.state.user?.id,\n args: { from: inst?.spaceId ?? null, to: spaceId, warnings: judgement.warnings.map(w => w.code) }\n } as any)\n )\n } catch (err) {\n console.error(`[twin-space] move audit not recorded for \"${instanceId}\"`, err)\n }\n\n return { ok: true, warnings: judgement.warnings }\n }\n\n /**\n * 트윈을 현장에서 뗀다 — **어느 현장에도 속하지 않음**으로 되돌린다.\n *\n * 더하기·옮기기만 있으면 잘못 넣은 것을 되돌릴 수 없다. 떼도 저널·로케이션·설비는 트윈에 남고\n * (`instanceId` 로 매여 있다), 구역·표현은 옛 현장에 남는다. 잃는 것은 **볼 무대**다 —\n * 판정이 그것을 말한다(`judgeDetachTwinSpace`). `dryRun` 은 같은 판정을 미리 낸다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Detach a twin from its space (it ends up on no site). The journal and projected rows stay with the twin; areas and representations stay with the space. dryRun returns the same judgement without writing. Returns {ok, warnings, errorCode}.'\n })\n async detachTwinFromSpace(\n @Arg('instanceId') instanceId: string,\n @Ctx() context: ResolverContext,\n @Arg('dryRun', { nullable: true, description: 'Judge only — report refusal/warnings without detaching.' }) dryRun?: boolean\n ): Promise<any> {\n const domainId = context.state.domain.id\n const instRepo = getRepository(TwinInstance)\n const inst = await instRepo.findOne({ where: { domain: { id: domainId }, instanceId } })\n const from = inst?.spaceId\n ? await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId: inst.spaceId } })\n : null\n const fromRepresentationCount = from\n ? await getRepository(TwinSpaceRepresentation).count({ where: { domain: { id: domainId } as any, space: { id: from.id } as any } })\n : 0\n\n const judgement = judgeDetachTwinSpace({\n instanceId: inst?.instanceId,\n fromSpaceId: inst?.spaceId,\n purpose: (inst as any)?.purpose,\n fromRepresentationCount,\n fromTimezone: from?.timezone ?? undefined\n })\n if (judgement.refusal) {\n const r = judgement.refusal\n return { ok: false, error: r.message, errorCode: r.code, errorParams: r.params, warnings: [] }\n }\n if (dryRun) return { ok: true, dryRun: true, warnings: judgement.warnings }\n\n /* 두 곳을 함께 비운다 — 레지스트리와 model 이 어긋나면 어느 쪽이 사실인지 알 수 없다.\n 시간 기준(utcOffsetMinutes)은 **남긴다**: 지우면 조용히 UTC 로 읽힌다(판정이 그렇게 말했다). */\n const { spaceId: _dropped, ...model } = (inst?.model as any) ?? {}\n await instRepo.update({ id: (inst as any).id }, { spaceId: null as any, model })\n\n try {\n const repo = getRepository(TwinAuditEvent)\n await repo.save(\n repo.create({\n domain: context.state.domain,\n instanceId,\n commandType: 'twin.detachFromSpace',\n accepted: true,\n origin: 'user',\n actorId: context.state.user?.id,\n args: { from: inst?.spaceId ?? null, warnings: judgement.warnings.map(w => w.code) }\n } as any)\n )\n } catch (err) {\n console.error(`[twin-space] detach audit not recorded for \"${instanceId}\"`, err)\n }\n\n return { ok: true, warnings: judgement.warnings }\n }\n\n /**\n * 공간 ↔ 트윈 ↔ 가시화 정합성 점검 — **사실을 모아 순수 판정에 넘긴다.**\n *\n * 세 축은 서로를 id 로만 가리키고 DB 가 그 참조를 지켜 주지 않는다. 트윈을 옮기거나 떼거나 원본을\n * 다시 읽으면 아무 오류 없이 **가리킬 것이 없는 도형**과 **소속 없는 로케이션**이 남는다. 사람이\n * 눈으로 대조하던 일을 기계가 한다(판정·근거: `space-integrity.ts`).\n *\n * `spaceId` 를 주면 그 현장만, 없으면 테넌트 전체를 본다.\n */\n @Query(returns => [ScalarObject], {\n description:\n 'Check space ↔ twin ↔ visualization integrity: dangling site refs, registry/model mismatch, polygons binding areas or entities that are not there, primary representation, unbound board representations. Pass spaceId to check one site.'\n })\n async twinSpaceIntegrity(\n @Ctx() context: ResolverContext,\n @Arg('spaceId', { nullable: true }) spaceId?: string\n ): Promise<any[]> {\n const domainId = context.state.domain.id\n const spaceRows = await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })\n const instRows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n const repRows = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId } }, relations: ['space'] })\n const areaRows = await getRepository(TwinArea).find({ where: { domain: { id: domainId } }, relations: ['space'] })\n const polyRows = await getRepository(TwinSpaceArea).find({ where: { domain: { id: domainId } }, relations: ['representation'] })\n\n const areasBySpace: Record<string, string[]> = {}\n for (const a of areaRows) {\n const sid = (a as any).space?.spaceId\n if (!sid) continue\n ;(areasBySpace[sid] ??= []).push(a.areaId)\n }\n\n /*\n * 폴리곤 바인딩의 실제 모양은 `{ groupId?, locationId?, locationIds? }` 다(지도 저작기 기준).\n * 여러 로케이션을 묶은 도형은 **각각을 따로** 본다 — 하나만 끊겨도 그 도형은 반쯤 거짓이 된다.\n */\n const polysByRep: Record<string, IntegrityPolygon[]> = {}\n for (const p of polyRows) {\n const rid = (p as any).representation?.id\n if (!rid) continue\n const b: any = p.binding ?? {}\n const list = polysByRep[rid] ??= []\n if (b.groupId) list.push({ id: p.id, groupId: b.groupId })\n const targets: string[] = [...(b.locationId ? [b.locationId] : []), ...(Array.isArray(b.locationIds) ? b.locationIds : [])]\n for (const t of targets) list.push({ id: p.id, targetKind: 'location', targetId: t })\n }\n\n /* 보드 id 는 표현 config 가 들고 있다 — 존재 확인은 보드 서비스의 일이므로, 여기서는 표현이\n 가리키는 값이 있는지만 본다(없는 보드까지 보려면 board-service 를 물어야 한다: 아래 주석). */\n const boardIds = repRows.map(r => (r.config as any)?.boardId).filter(Boolean) as string[]\n\n const findings = checkSpaceIntegrity({\n spaces: spaceRows.map(s => ({ spaceId: s.spaceId, primaryRepresentationId: s.primaryRepresentationId })),\n instances: instRows.map(i => {\n const model: any = i.model ?? {}\n /*\n * 어휘가 맞는지는 **실행 중인 트윈만** 답할 수 있다 — 커널이 무엇을 버렸는지는 런타임의 사실이다.\n * 정지한 트윈은 `undefined`(모른다)로 둔다. 저널을 다시 접어 알아내지는 않는다: 이 질의는\n * 테넌트 전체를 훑으므로 트윈마다 폴드를 걸면 정합성 점검이 가장 무거운 질의가 된다.\n */\n const live: any = TwinEngine.isRunning(domainId, i.instanceId)\n ? TwinEngine.snapshot(domainId, i.instanceId)\n : undefined\n return {\n instanceId: i.instanceId,\n spaceId: i.spaceId,\n modelSpaceId: model.spaceId,\n purpose: (i as any).purpose,\n locationIds: (model.locations ?? []).map((l: any) => l?.id).filter(Boolean),\n equipmentIds: (model.equipment ?? []).map((e: any) => e?.id).filter(Boolean),\n areaRefs: (model.locations ?? []).map((l: any) => l?.parentId),\n ...(Array.isArray(live?.unhandled) ? { unhandled: live.unhandled } : {})\n }\n }),\n representations: repRows.map(r => ({\n id: r.id,\n spaceId: (r as any).space?.spaceId ?? '',\n type: r.type,\n boardId: (r.config as any)?.boardId ?? null,\n polygons: polysByRep[r.id] ?? []\n })),\n areasBySpace,\n boardIds\n })\n\n const scoped = spaceId ? findings.filter(f => f.spaceId === spaceId || (!f.spaceId && !spaceId)) : findings\n return sortFindings(scoped)\n }\n\n /**\n * 기계적으로 고칠 수 있는 어긋남만 고친다 — **사람의 판단이 필요한 것은 손대지 않는다.**\n *\n * 지금 고치는 것은 하나다: **대표 표현 포인터**. 공간이 없는 표현 id 를 가리키고 있으면, 행의\n * `isPrimary` 가 켜진 표현(없으면 첫 표현)으로 다시 가리키고, 표현이 없으면 비운다. 근거가 있고\n * 답이 하나뿐인 부류라 자동으로 고쳐도 사실을 바꾸지 않는다.\n *\n * 폴리곤이 없는 구역·개체를 가리키는 것은 **고치지 않는다.** 그 도형을 지워야 하는지, 트윈을 다시\n * 데려와야 하는지, 구역을 다시 그려야 하는지는 사람이 정할 일이다 — 기계가 고르면 사용자가 그린\n * 도형이 조용히 사라진다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Repair mechanically fixable space integrity findings (currently: a primary representation pointer that points nowhere). Dangling polygon bindings are left alone — that is a human decision. Returns {repaired:[{spaceId, code}], skipped}.'\n })\n async repairTwinSpaceIntegrity(\n @Ctx() context: ResolverContext,\n @Arg('spaceId', { nullable: true }) spaceId?: string\n ): Promise<any> {\n const domainId = context.state.domain.id\n const spaceRepo = getRepository(TwinSpace)\n const repRepo = getRepository(TwinSpaceRepresentation)\n const spaces = await spaceRepo.find({\n where: spaceId ? { domain: { id: domainId }, spaceId } : { domain: { id: domainId } }\n })\n const repaired: any[] = []\n for (const space of spaces) {\n const reps = await repRepo.find({ where: { domain: { id: domainId } as any, space: { id: space.id } as any }, order: { seq: 'ASC' } })\n const pointer = (space.primaryRepresentationId ?? '').trim()\n if (pointer && reps.some(r => r.id === pointer)) continue /* 이미 옳다 */\n const primary = reps.find(r => r.isPrimary) ?? reps[0]\n const next = primary?.id ?? null\n if (pointer === (next ?? '')) continue\n await spaceRepo.save(spaceRepo.create({ ...space, primaryRepresentationId: next }))\n if (primary) for (const r of reps) if (!!r.isPrimary !== (r.id === primary.id)) await repRepo.save(repRepo.create({ ...r, isPrimary: r.id === primary.id }))\n repaired.push({ spaceId: space.spaceId, code: 'primary-representation-missing', from: pointer || null, to: next })\n }\n return { ok: true, repaired, count: repaired.length }\n }\n\n /* ── Area(논리 구역, 표현 무관·공유·계층) — area 단일화 space #2 ─────── */\n @Query(returns => [ScalarObject], { description: 'List logical areas (representation-agnostic hierarchy) of a space. (area unification)' })\n async twinAreas(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const rows = await getRepository(TwinArea).find({ where: { domain: { id: domainId }, space: { spaceId } }, order: { createdAt: 'ASC' } })\n return rows.map(a => ({ areaId: a.areaId, name: a.name, type: a.type, parentId: a.parentId, layout: a.layout }))\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Create/update a logical area (shared across representations). (area unification)' })\n async saveTwinArea(\n @Arg('spaceId') spaceId: string,\n @Arg('areaId') areaId: string,\n @Arg('patch', type => ScalarObject) patch: any,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const domainId = context.state.domain.id\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) throw new Error(`space \"${spaceId}\" not found`)\n const repo = getRepository(TwinArea)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, space: { id: space.id }, areaId } })\n await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n space: { id: space.id } as any,\n areaId,\n name: patch?.name ?? existing?.name ?? areaId,\n type: patch?.type ?? existing?.type,\n parentId: patch?.parentId !== undefined ? patch.parentId : existing?.parentId,\n layout: patch?.layout ?? existing?.layout\n })\n )\n return true\n }\n\n /*\n * 참조기반 회수(reference-counted) — area 는 참조가 남아 있으면 삭제 차단, 고아면 제거.\n * 참조: 자식 area(parentId) · 표현별 폴리곤(TwinSpaceArea binding.groupId/areaId).\n * (노드/엔티티 담김·drillTo 참조는 P2 areaId 배선 후 확장.)\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a logical area only if unreferenced (reference-counted). Throws if referenced. (area unification)' })\n async deleteTwinArea(@Arg('spaceId') spaceId: string, @Arg('areaId') areaId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const domainId = context.state.domain.id\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) return false\n // 참조 1: 자식 area\n const children = await getRepository(TwinArea).count({ where: { domain: { id: domainId }, space: { id: space.id }, parentId: areaId } })\n // 참조 2: 표현별 폴리곤(이 공간의 표현들에 이 area 를 그린 것). binding.groupId/areaId 는 JSON → 로드 후 JS 필터(멀티DB).\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n let polygonRefs = 0\n for (const rep of reps) {\n const polys = await getRepository(TwinSpaceArea).find({ where: { domain: { id: domainId }, representation: { id: rep.id } } })\n polygonRefs += polys.filter(p => (p.binding as any)?.groupId === areaId || (p.binding as any)?.areaId === areaId).length\n }\n if (children > 0 || polygonRefs > 0) {\n throw new Error(`area \"${areaId}\" 는 참조가 남아 삭제할 수 없습니다 (자식 ${children}, 폴리곤 ${polygonRefs}). 참조 제거 후 삭제하세요.`)\n }\n await getRepository(TwinArea).delete({ domain: { id: domainId } as any, space: { id: space.id } as any, areaId })\n return true\n }\n\n /* ── Representation ─────────────────────────────────────────────── */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create/update a representation (map|image|model). Returns {id}.' })\n async saveSpaceRepresentation(\n @Arg('spaceId') spaceId: string,\n @Arg('rep', type => ScalarObject) rep: any,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) return { ok: false, error: `space not found: ${spaceId}` }\n const repo = getRepository(TwinSpaceRepresentation)\n const existing = rep?.id ? await repo.findOne({ where: { id: rep.id } }) : null\n const saved = await repo.save(repo.create({ ...(existing ?? {}), domain: { id: domainId } as any, space: { id: space.id } as any, type: rep.type, name: rep.name, seq: rep.seq ?? 0, isPrimary: !!rep.isPrimary, config: rep.config }))\n return { ok: true, id: saved.id }\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a representation and its areas.' })\n async deleteSpaceRepresentation(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const domainId = context.state.domain.id\n await getRepository(TwinSpaceArea).delete({ domain: { id: domainId } as any, representation: { id } as any })\n await getRepository(TwinSpaceRepresentation).delete({ domain: { id: domainId } as any, id } as any)\n return true\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Set the primary representation of a space.' })\n async setPrimaryRepresentation(@Arg('spaceId') spaceId: string, @Arg('repId') repId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const domainId = context.state.domain.id\n const spaceRepo = getRepository(TwinSpace)\n const space = await spaceRepo.findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) return false\n await spaceRepo.save(spaceRepo.create({ ...space, primaryRepresentationId: repId }))\n const repRepo = getRepository(TwinSpaceRepresentation)\n const reps = await repRepo.find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n for (const rep of reps) if (!!rep.isPrimary !== (rep.id === repId)) await repRepo.save(repRepo.create({ ...rep, isPrimary: rep.id === repId }))\n return true\n }\n\n /* ── Area (map/image 폴리곤) ────────────────────────────────────── */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create/update a polygon area (geometry + drillTo model + binding). Returns {id}.' })\n async saveSpaceArea(\n @Arg('representationId') representationId: string,\n @Arg('area', type => ScalarObject) area: any,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinSpaceArea)\n const existing = area?.id ? await repo.findOne({ where: { id: area.id } }) : null\n /* drillTo/binding 은 선택적 링크 — 클라가 해제(undefined)로 보내면 JSON 에서 키가 빠져 TypeORM 이 \"변경 없음\"으로\n * 무시하므로 기존 값이 남는다. null 로 강제해 명시적으로 컬럼을 비운다(저장은 늘 전체 필드를 보냄 → 덮어쓰기 안전). */\n const saved = await repo.save(repo.create({ ...(existing ?? {}), domain: { id: domainId } as any, representation: { id: representationId } as any, name: area.name, type: area.type, geometry: area.geometry, drillTo: area.drillTo ?? null, binding: area.binding ?? null, style: area.style }))\n return { ok: true, id: saved.id }\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a polygon area.' })\n async deleteSpaceArea(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n await getRepository(TwinSpaceArea).delete({ domain: { id: context.state.domain.id } as any, id } as any)\n return true\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"twin-space-resolver.js","sourceRoot":"","sources":["../../../server/service/twin-space/twin-space-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { twinError } from '../../engine/log.js'\nimport { Arg, Ctx, Mutation, Query, Resolver, Directive} from 'type-graphql'\n\nimport { ScalarObject, getRepository } from '@things-factory/shell'\n\nimport { TwinSpace } from './twin-space.js'\nimport { TwinSpaceRepresentation } from './twin-space-representation.js'\nimport { TwinSpaceArea } from './twin-space-area.js'\nimport { TwinArea } from './twin-area.js'\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinAuditEvent } from '../twin-audit/twin-audit-event.js'\nimport { TwinEngine } from '../../engine/index.js'\nimport { judgeMoveTwinSpace, judgeDetachTwinSpace } from './move-space.js'\nimport { checkSpaceIntegrity, sortFindings, type IntegrityPolygon } from './space-integrity.js'\n\n/*\n * 공간 구성 채널(design/ui/space-composition.md) — Site(Space) + 복수 표현(Representation) + 영역(Area).\n * model 내용은 board-service Board 에(표현 config.boardId 참조, 중복 저장 금지). 모두 domain 스코프.\n */\n@Resolver()\nexport class TwinSpaceResolver {\n /* ── Space(Site) ────────────────────────────────────────────────── */\n /**\n * 이 테넌트의 현장 목록.\n *\n * ── 세 번만 묻는다 (2026-08-13) ──────────────────────────────────────────\n * 예전에는 현장마다 표현 수를 세고 인스턴스를 조회했다 — 현장 13곳이면 **질의 27번**이고, 첫\n * 호출이 2.4초였다(헤더가 뜰 때마다 이 목록을 읽는다). 규모가 커지면 그대로 자란다.\n *\n * 이제 세 번 묻고 메모리에서 맞춘다: 현장 · 표현(공간 id 만) · 인스턴스(필요한 컬럼만).\n * 표현은 **id 만 실어 온다**(`loadRelationIds`) — 설정 blob 을 읽어 세는 것은 낭비다.\n */\n @Query(returns => [ScalarObject], { description: 'List tenant Spaces (Sites) in the current domain.' })\n async twinSpaces(@Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const [rows, reps, insts] = await Promise.all([\n getRepository(TwinSpace).find({ where: { domain: { id: domainId } }, order: { createdAt: 'ASC' } }),\n /* 관계를 **조인해서** 읽는다 — `loadRelationIds`+`select` 조합은 관계 자리를 비워 두어\n 표현 수가 전부 0 이 됐다(2026-08-13 실측으로 잡음). 조인 한 번이 현장마다 세는 것보다 싸다. */\n getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId } }, relations: { space: true } }),\n getRepository(TwinInstance).find({ where: { domain: { id: domainId } }, select: { instanceId: true, spaceId: true, purpose: true, copyOf: true } })\n ])\n\n const repCount = new Map<string, number>()\n for (const rep of reps) {\n const sid = rep.space?.id\n if (sid) repCount.set(sid, (repCount.get(sid) ?? 0) + 1)\n }\n /* 벤치 여부·원본 참조 — 인스턴스 purpose 근거(1급). 사본 현장을 헤더 선택기에서 구별·선택 가능하게. */\n const benchOf = new Map<string, { copyOf?: string }>()\n for (const i of insts) if ((i as any).purpose === 'bench' && i.spaceId && !benchOf.has(i.spaceId)) benchOf.set(i.spaceId, { copyOf: i.copyOf ?? undefined })\n\n return rows.map(r => {\n const bench = benchOf.get(r.spaceId)\n return {\n spaceId: r.spaceId,\n name: r.name,\n description: r.description,\n geo: r.geo,\n timezone: r.timezone,\n primaryRepresentationId: r.primaryRepresentationId,\n extentX: r.extentX,\n extentY: r.extentY,\n representationCount: repCount.get(r.id) ?? 0,\n bench: !!bench,\n copyOf: bench?.copyOf\n }\n })\n }\n\n /** 단건 — 표현(+영역) 트리 포함. */\n @Query(returns => ScalarObject, { nullable: true, description: 'Get one Space with its representations (and their areas).' })\n async twinSpace(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<any | null> {\n const domainId = context.state.domain.id\n const r = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!r) return null\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: r.id } }, order: { seq: 'ASC' } })\n const representations: any[] = []\n for (const rep of reps) {\n const areas = await getRepository(TwinSpaceArea).find({ where: { domain: { id: domainId }, representation: { id: rep.id } }, order: { createdAt: 'ASC' } })\n representations.push({ id: rep.id, type: rep.type, name: rep.name, seq: rep.seq, isPrimary: rep.isPrimary, config: rep.config, areas: areas.map(a => ({ id: a.id, name: a.name, type: a.type, geometry: a.geometry, drillTo: a.drillTo, binding: a.binding, style: a.style })) })\n }\n return { spaceId: r.spaceId, name: r.name, description: r.description, geo: r.geo, timezone: r.timezone, primaryRepresentationId: r.primaryRepresentationId, extentX: r.extentX, extentY: r.extentY, representations }\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Create or update a Space (name/description/geo/timezone/primaryRepresentationId).' })\n async saveTwinSpace(\n @Arg('spaceId') spaceId: string,\n @Arg('patch', type => ScalarObject) patch: any,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const repo = getRepository(TwinSpace)\n const domainId = context.state.domain.id\n const existing = await repo.findOne({ where: { domain: { id: domainId }, spaceId } })\n /* 진짜 부분 병합 — patch 에 준 키만 갱신(나머지 필드 보존). id 는 관계로 재설정하지 않도록 제외. */\n const { id: _drop, ...clean } = patch ?? {}\n await repo.save(repo.create({ ...(existing ?? {}), ...clean, domain: { id: domainId } as any, spaceId }))\n return true\n }\n\n /**\n * 공간 삭제 — **이 공간의 트윈이 있으면 거절한다.** 그래서 트윈이 현장을 잃는 일은 없다.\n *\n * ── 왜 모양을 바꿨나 (2026-08-13) ────────────────────────────────────────\n * 예전에는 `Boolean` 을 돌려주고 거절은 **한국어 문장을 냈다.** 두 가지가 틀렸다:\n * ① 서버가 화면의 말을 정했다 — 일본어·스페인어 사용자에게 한국어가 새어 나간다.\n * ② 오류를 낸 예외를 화면이 받지 않아 **아무 일도 없는 것처럼** 보였다. 사용자는 삭제를 눌렀고\n * 화면은 그대로였다. 거절을 조용히 하는 것은 실패보다 나쁘다.\n * 이제 `{ok, errorCode, errorParams}` 로 낸다 — 화면이 `twin.compose.del.<code>` 로 말을 만든다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Delete a Space and its representations/areas. Refused while twins still live in it (a twin never loses its site this way). Returns {ok, errorCode, errorParams}.'\n })\n async deleteTwinSpace(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<any> {\n const domainId = context.state.domain.id\n // 라이프사이클 가드 — 이 공간에 바인딩된 트윈 인스턴스가 있으면 삭제 차단(dangling 방지).\n // spaceId 컬럼(space #3) 로 직접 질의 — 전 인스턴스 로드+JS필터 제거(효율·1급 질의).\n const bound = await getRepository(TwinInstance).find({ where: { domain: { id: domainId }, spaceId } })\n if (bound.length) {\n const twins = bound.map(i => i.name || i.instanceId)\n return {\n ok: false,\n errorCode: 'space-has-twins',\n errorParams: { spaceId, count: bound.length, twins: twins.slice(0, 5).join(', ') },\n error: `space \"${spaceId}\" still has ${bound.length} twin(s) — remove or move them first (${twins.join(', ')})`\n }\n }\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (space) {\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n for (const rep of reps) await getRepository(TwinSpaceArea).delete({ domain: { id: domainId } as any, representation: { id: rep.id } as any })\n await getRepository(TwinSpaceRepresentation).delete({ domain: { id: domainId } as any, space: { id: space.id } as any })\n await getRepository(TwinArea).delete({ domain: { id: domainId } as any, space: { id: space.id } as any }) // 논리 area 도 함께 정리\n }\n await getRepository(TwinSpace).delete({ domain: { id: domainId } as any, spaceId })\n return { ok: true }\n }\n\n /**\n * 이미 있는 트윈을 이 현장으로 가져온다 — **소속 갱신**(이력 이전이 아니다).\n *\n * 저널·투영 행은 `instanceId` 로 매여 있어 트윈을 따라오고, 구역·표현은 공간의 것이라 남는다\n * (근거·판정: `move-space.ts`). 그래서 이 뮤테이션이 쓰는 것은 두 곳뿐이다 —\n * 레지스트리의 `spaceId` 와 저장된 model 의 `spaceId`(커널·보드가 같은 공간을 가리켜야 한다).\n * 새 공간의 시간대로 `utcOffsetMinutes` 도 다시 파생한다(공간이 시간의 기준이다).\n *\n * `dryRun` 은 **같은 판정을 미리** 보여 준다 — 화면이 잃을 것을 먼저 말하고 사용자가 정한다.\n * 판정을 두 벌로 두면 미리보기와 실제가 어긋나므로 한 함수를 두 번 부른다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Move an existing twin into a space (co-locate it as another lens). The journal and projected rows follow the twin; areas and representations stay with the old space. dryRun returns the same judgement without writing. Returns {ok, warnings, errorCode}.'\n })\n async moveTwinToSpace(\n @Arg('instanceId') instanceId: string,\n @Arg('spaceId') spaceId: string,\n @Ctx() context: ResolverContext,\n @Arg('dryRun', { nullable: true, description: 'Judge only — report refusal/warnings without moving.' }) dryRun?: boolean\n ): Promise<any> {\n const domainId = context.state.domain.id\n const instRepo = getRepository(TwinInstance)\n const spaceRepo = getRepository(TwinSpace)\n\n const inst = await instRepo.findOne({ where: { domain: { id: domainId }, instanceId } })\n const from = inst?.spaceId ? await spaceRepo.findOne({ where: { domain: { id: domainId }, spaceId: inst.spaceId } }) : null\n const to = await spaceRepo.findOne({ where: { domain: { id: domainId }, spaceId } })\n\n /* 판정에 필요한 사실만 모아 넘긴다 — 판정 자체는 순수 모듈이 한다. */\n const toAreaIds = to\n ? (await getRepository(TwinArea).find({ where: { domain: { id: domainId } as any, space: { id: to.id } as any } })).map(a => a.areaId)\n : []\n const fromRepresentationCount = from\n ? await getRepository(TwinSpaceRepresentation).count({ where: { domain: { id: domainId } as any, space: { id: from.id } as any } })\n : 0\n const model: any = inst?.model ?? {}\n const areaRefs: (string | undefined)[] = (model.locations ?? []).map((l: any) => l?.parentId)\n\n const judgement = judgeMoveTwinSpace({\n instanceId: inst?.instanceId,\n fromSpaceId: inst?.spaceId,\n toSpaceId: spaceId,\n toSpaceExists: !!to,\n purpose: (inst as any)?.purpose,\n running: !!inst && !!TwinEngine.runtime(domainId, instanceId),\n fromTimezone: from?.timezone ?? undefined,\n toTimezone: to?.timezone ?? undefined,\n areaRefs,\n toAreaIds,\n fromRepresentationCount\n })\n if (judgement.refusal) {\n const r = judgement.refusal\n return { ok: false, error: r.message, errorCode: r.code, errorParams: r.params, warnings: [] }\n }\n if (dryRun) return { ok: true, dryRun: true, warnings: judgement.warnings }\n\n /* 두 곳을 함께 쓴다 — 레지스트리와 model 이 다른 공간을 가리키면 보드·커널이 갈라진다. */\n const moved = { ...model, spaceId }\n const withTime = await TwinEngine.withSpaceTimeBase(moved, domainId, spaceId)\n await instRepo.save(instRepo.create({ ...(inst as any), spaceId, model: withTime }))\n\n /*\n * 감사 기록 — 소속을 바꾼 것은 사람의 결정이고, 나중에 \"왜 이 트윈이 저 현장에 있나\" 를 묻게 된다.\n * 기록이 실패해도 이전 결과는 돌려준다(감사가 본업을 막지 않는다). 다만 삼키지 않고 로그에 남긴다.\n */\n try {\n const repo = getRepository(TwinAuditEvent)\n await repo.save(\n repo.create({\n domain: context.state.domain,\n instanceId,\n commandType: 'twin.moveToSpace',\n accepted: true,\n origin: 'user',\n actorId: context.state.user?.id,\n args: { from: inst?.spaceId ?? null, to: spaceId, warnings: judgement.warnings.map(w => w.code) }\n } as any)\n )\n } catch (err) {\n twinError(`[twin-space] move audit not recorded for \"${instanceId}\"`, err)\n }\n\n return { ok: true, warnings: judgement.warnings }\n }\n\n /**\n * 트윈을 현장에서 뗀다 — **어느 현장에도 속하지 않음**으로 되돌린다.\n *\n * 더하기·옮기기만 있으면 잘못 넣은 것을 되돌릴 수 없다. 떼도 저널·로케이션·설비는 트윈에 남고\n * (`instanceId` 로 매여 있다), 구역·표현은 옛 현장에 남는다. 잃는 것은 **볼 무대**다 —\n * 판정이 그것을 말한다(`judgeDetachTwinSpace`). `dryRun` 은 같은 판정을 미리 낸다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Detach a twin from its space (it ends up on no site). The journal and projected rows stay with the twin; areas and representations stay with the space. dryRun returns the same judgement without writing. Returns {ok, warnings, errorCode}.'\n })\n async detachTwinFromSpace(\n @Arg('instanceId') instanceId: string,\n @Ctx() context: ResolverContext,\n @Arg('dryRun', { nullable: true, description: 'Judge only — report refusal/warnings without detaching.' }) dryRun?: boolean\n ): Promise<any> {\n const domainId = context.state.domain.id\n const instRepo = getRepository(TwinInstance)\n const inst = await instRepo.findOne({ where: { domain: { id: domainId }, instanceId } })\n const from = inst?.spaceId\n ? await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId: inst.spaceId } })\n : null\n const fromRepresentationCount = from\n ? await getRepository(TwinSpaceRepresentation).count({ where: { domain: { id: domainId } as any, space: { id: from.id } as any } })\n : 0\n\n const judgement = judgeDetachTwinSpace({\n instanceId: inst?.instanceId,\n fromSpaceId: inst?.spaceId,\n purpose: (inst as any)?.purpose,\n fromRepresentationCount,\n fromTimezone: from?.timezone ?? undefined\n })\n if (judgement.refusal) {\n const r = judgement.refusal\n return { ok: false, error: r.message, errorCode: r.code, errorParams: r.params, warnings: [] }\n }\n if (dryRun) return { ok: true, dryRun: true, warnings: judgement.warnings }\n\n /* 두 곳을 함께 비운다 — 레지스트리와 model 이 어긋나면 어느 쪽이 사실인지 알 수 없다.\n 시간 기준(utcOffsetMinutes)은 **남긴다**: 지우면 조용히 UTC 로 읽힌다(판정이 그렇게 말했다). */\n const { spaceId: _dropped, ...model } = (inst?.model as any) ?? {}\n await instRepo.update({ id: (inst as any).id }, { spaceId: null as any, model })\n\n try {\n const repo = getRepository(TwinAuditEvent)\n await repo.save(\n repo.create({\n domain: context.state.domain,\n instanceId,\n commandType: 'twin.detachFromSpace',\n accepted: true,\n origin: 'user',\n actorId: context.state.user?.id,\n args: { from: inst?.spaceId ?? null, warnings: judgement.warnings.map(w => w.code) }\n } as any)\n )\n } catch (err) {\n twinError(`[twin-space] detach audit not recorded for \"${instanceId}\"`, err)\n }\n\n return { ok: true, warnings: judgement.warnings }\n }\n\n /**\n * 공간 ↔ 트윈 ↔ 가시화 정합성 점검 — **사실을 모아 순수 판정에 넘긴다.**\n *\n * 세 축은 서로를 id 로만 가리키고 DB 가 그 참조를 지켜 주지 않는다. 트윈을 옮기거나 떼거나 원본을\n * 다시 읽으면 아무 오류 없이 **가리킬 것이 없는 도형**과 **소속 없는 로케이션**이 남는다. 사람이\n * 눈으로 대조하던 일을 기계가 한다(판정·근거: `space-integrity.ts`).\n *\n * `spaceId` 를 주면 그 현장만, 없으면 테넌트 전체를 본다.\n */\n @Query(returns => [ScalarObject], {\n description:\n 'Check space ↔ twin ↔ visualization integrity: dangling site refs, registry/model mismatch, polygons binding areas or entities that are not there, primary representation, unbound board representations. Pass spaceId to check one site.'\n })\n async twinSpaceIntegrity(\n @Ctx() context: ResolverContext,\n @Arg('spaceId', { nullable: true }) spaceId?: string\n ): Promise<any[]> {\n const domainId = context.state.domain.id\n const spaceRows = await getRepository(TwinSpace).find({ where: { domain: { id: domainId } } })\n const instRows = await getRepository(TwinInstance).find({ where: { domain: { id: domainId } } })\n const repRows = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId } }, relations: ['space'] })\n const areaRows = await getRepository(TwinArea).find({ where: { domain: { id: domainId } }, relations: ['space'] })\n const polyRows = await getRepository(TwinSpaceArea).find({ where: { domain: { id: domainId } }, relations: ['representation'] })\n\n const areasBySpace: Record<string, string[]> = {}\n for (const a of areaRows) {\n const sid = (a as any).space?.spaceId\n if (!sid) continue\n ;(areasBySpace[sid] ??= []).push(a.areaId)\n }\n\n /*\n * 폴리곤 바인딩의 실제 모양은 `{ groupId?, locationId?, locationIds? }` 다(지도 저작기 기준).\n * 여러 로케이션을 묶은 도형은 **각각을 따로** 본다 — 하나만 끊겨도 그 도형은 반쯤 거짓이 된다.\n */\n const polysByRep: Record<string, IntegrityPolygon[]> = {}\n for (const p of polyRows) {\n const rid = (p as any).representation?.id\n if (!rid) continue\n const b: any = p.binding ?? {}\n const list = polysByRep[rid] ??= []\n if (b.groupId) list.push({ id: p.id, groupId: b.groupId })\n const targets: string[] = [...(b.locationId ? [b.locationId] : []), ...(Array.isArray(b.locationIds) ? b.locationIds : [])]\n for (const t of targets) list.push({ id: p.id, targetKind: 'location', targetId: t })\n }\n\n /* 보드 id 는 표현 config 가 들고 있다 — 존재 확인은 보드 서비스의 일이므로, 여기서는 표현이\n 가리키는 값이 있는지만 본다(없는 보드까지 보려면 board-service 를 물어야 한다: 아래 주석). */\n const boardIds = repRows.map(r => (r.config as any)?.boardId).filter(Boolean) as string[]\n\n const findings = checkSpaceIntegrity({\n spaces: spaceRows.map(s => ({ spaceId: s.spaceId, primaryRepresentationId: s.primaryRepresentationId })),\n instances: instRows.map(i => {\n const model: any = i.model ?? {}\n /*\n * 어휘가 맞는지는 **실행 중인 트윈만** 답할 수 있다 — 커널이 무엇을 버렸는지는 런타임의 사실이다.\n * 정지한 트윈은 `undefined`(모른다)로 둔다. 저널을 다시 접어 알아내지는 않는다: 이 질의는\n * 테넌트 전체를 훑으므로 트윈마다 폴드를 걸면 정합성 점검이 가장 무거운 질의가 된다.\n */\n const live: any = TwinEngine.isRunning(domainId, i.instanceId)\n ? TwinEngine.snapshot(domainId, i.instanceId)\n : undefined\n return {\n instanceId: i.instanceId,\n spaceId: i.spaceId,\n modelSpaceId: model.spaceId,\n purpose: (i as any).purpose,\n locationIds: (model.locations ?? []).map((l: any) => l?.id).filter(Boolean),\n equipmentIds: (model.equipment ?? []).map((e: any) => e?.id).filter(Boolean),\n areaRefs: (model.locations ?? []).map((l: any) => l?.parentId),\n ...(Array.isArray(live?.unhandled) ? { unhandled: live.unhandled } : {})\n }\n }),\n representations: repRows.map(r => ({\n id: r.id,\n spaceId: (r as any).space?.spaceId ?? '',\n type: r.type,\n boardId: (r.config as any)?.boardId ?? null,\n polygons: polysByRep[r.id] ?? []\n })),\n areasBySpace,\n boardIds\n })\n\n const scoped = spaceId ? findings.filter(f => f.spaceId === spaceId || (!f.spaceId && !spaceId)) : findings\n return sortFindings(scoped)\n }\n\n /**\n * 기계적으로 고칠 수 있는 어긋남만 고친다 — **사람의 판단이 필요한 것은 손대지 않는다.**\n *\n * 지금 고치는 것은 하나다: **대표 표현 포인터**. 공간이 없는 표현 id 를 가리키고 있으면, 행의\n * `isPrimary` 가 켜진 표현(없으면 첫 표현)으로 다시 가리키고, 표현이 없으면 비운다. 근거가 있고\n * 답이 하나뿐인 부류라 자동으로 고쳐도 사실을 바꾸지 않는다.\n *\n * 폴리곤이 없는 구역·개체를 가리키는 것은 **고치지 않는다.** 그 도형을 지워야 하는지, 트윈을 다시\n * 데려와야 하는지, 구역을 다시 그려야 하는지는 사람이 정할 일이다 — 기계가 고르면 사용자가 그린\n * 도형이 조용히 사라진다.\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, {\n description:\n 'Repair mechanically fixable space integrity findings (currently: a primary representation pointer that points nowhere). Dangling polygon bindings are left alone — that is a human decision. Returns {repaired:[{spaceId, code}], skipped}.'\n })\n async repairTwinSpaceIntegrity(\n @Ctx() context: ResolverContext,\n @Arg('spaceId', { nullable: true }) spaceId?: string\n ): Promise<any> {\n const domainId = context.state.domain.id\n const spaceRepo = getRepository(TwinSpace)\n const repRepo = getRepository(TwinSpaceRepresentation)\n const spaces = await spaceRepo.find({\n where: spaceId ? { domain: { id: domainId }, spaceId } : { domain: { id: domainId } }\n })\n const repaired: any[] = []\n for (const space of spaces) {\n const reps = await repRepo.find({ where: { domain: { id: domainId } as any, space: { id: space.id } as any }, order: { seq: 'ASC' } })\n const pointer = (space.primaryRepresentationId ?? '').trim()\n if (pointer && reps.some(r => r.id === pointer)) continue /* 이미 옳다 */\n const primary = reps.find(r => r.isPrimary) ?? reps[0]\n const next = primary?.id ?? null\n if (pointer === (next ?? '')) continue\n await spaceRepo.save(spaceRepo.create({ ...space, primaryRepresentationId: next }))\n if (primary) for (const r of reps) if (!!r.isPrimary !== (r.id === primary.id)) await repRepo.save(repRepo.create({ ...r, isPrimary: r.id === primary.id }))\n repaired.push({ spaceId: space.spaceId, code: 'primary-representation-missing', from: pointer || null, to: next })\n }\n return { ok: true, repaired, count: repaired.length }\n }\n\n /* ── Area(논리 구역, 표현 무관·공유·계층) — area 단일화 space #2 ─────── */\n @Query(returns => [ScalarObject], { description: 'List logical areas (representation-agnostic hierarchy) of a space. (area unification)' })\n async twinAreas(@Arg('spaceId') spaceId: string, @Ctx() context: ResolverContext): Promise<any[]> {\n const domainId = context.state.domain.id\n const rows = await getRepository(TwinArea).find({ where: { domain: { id: domainId }, space: { spaceId } }, order: { createdAt: 'ASC' } })\n return rows.map(a => ({ areaId: a.areaId, name: a.name, type: a.type, parentId: a.parentId, layout: a.layout }))\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Create/update a logical area (shared across representations). (area unification)' })\n async saveTwinArea(\n @Arg('spaceId') spaceId: string,\n @Arg('areaId') areaId: string,\n @Arg('patch', type => ScalarObject) patch: any,\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const domainId = context.state.domain.id\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) throw new Error(`space \"${spaceId}\" not found`)\n const repo = getRepository(TwinArea)\n const existing = await repo.findOne({ where: { domain: { id: domainId }, space: { id: space.id }, areaId } })\n await repo.save(\n repo.create({\n ...(existing ?? {}),\n domain: { id: domainId } as any,\n space: { id: space.id } as any,\n areaId,\n name: patch?.name ?? existing?.name ?? areaId,\n type: patch?.type ?? existing?.type,\n parentId: patch?.parentId !== undefined ? patch.parentId : existing?.parentId,\n layout: patch?.layout ?? existing?.layout\n })\n )\n return true\n }\n\n /*\n * 참조기반 회수(reference-counted) — area 는 참조가 남아 있으면 삭제 차단, 고아면 제거.\n * 참조: 자식 area(parentId) · 표현별 폴리곤(TwinSpaceArea binding.groupId/areaId).\n * (노드/엔티티 담김·drillTo 참조는 P2 areaId 배선 후 확장.)\n */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a logical area only if unreferenced (reference-counted). Throws if referenced. (area unification)' })\n async deleteTwinArea(@Arg('spaceId') spaceId: string, @Arg('areaId') areaId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const domainId = context.state.domain.id\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) return false\n // 참조 1: 자식 area\n const children = await getRepository(TwinArea).count({ where: { domain: { id: domainId }, space: { id: space.id }, parentId: areaId } })\n // 참조 2: 표현별 폴리곤(이 공간의 표현들에 이 area 를 그린 것). binding.groupId/areaId 는 JSON → 로드 후 JS 필터(멀티DB).\n const reps = await getRepository(TwinSpaceRepresentation).find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n let polygonRefs = 0\n for (const rep of reps) {\n const polys = await getRepository(TwinSpaceArea).find({ where: { domain: { id: domainId }, representation: { id: rep.id } } })\n polygonRefs += polys.filter(p => (p.binding as any)?.groupId === areaId || (p.binding as any)?.areaId === areaId).length\n }\n if (children > 0 || polygonRefs > 0) {\n throw new Error(`area \"${areaId}\" 는 참조가 남아 삭제할 수 없습니다 (자식 ${children}, 폴리곤 ${polygonRefs}). 참조 제거 후 삭제하세요.`)\n }\n await getRepository(TwinArea).delete({ domain: { id: domainId } as any, space: { id: space.id } as any, areaId })\n return true\n }\n\n /* ── Representation ─────────────────────────────────────────────── */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create/update a representation (map|image|model). Returns {id}.' })\n async saveSpaceRepresentation(\n @Arg('spaceId') spaceId: string,\n @Arg('rep', type => ScalarObject) rep: any,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const space = await getRepository(TwinSpace).findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) return { ok: false, error: `space not found: ${spaceId}` }\n const repo = getRepository(TwinSpaceRepresentation)\n const existing = rep?.id ? await repo.findOne({ where: { id: rep.id } }) : null\n const saved = await repo.save(repo.create({ ...(existing ?? {}), domain: { id: domainId } as any, space: { id: space.id } as any, type: rep.type, name: rep.name, seq: rep.seq ?? 0, isPrimary: !!rep.isPrimary, config: rep.config }))\n return { ok: true, id: saved.id }\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a representation and its areas.' })\n async deleteSpaceRepresentation(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const domainId = context.state.domain.id\n await getRepository(TwinSpaceArea).delete({ domain: { id: domainId } as any, representation: { id } as any })\n await getRepository(TwinSpaceRepresentation).delete({ domain: { id: domainId } as any, id } as any)\n return true\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Set the primary representation of a space.' })\n async setPrimaryRepresentation(@Arg('spaceId') spaceId: string, @Arg('repId') repId: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const domainId = context.state.domain.id\n const spaceRepo = getRepository(TwinSpace)\n const space = await spaceRepo.findOne({ where: { domain: { id: domainId }, spaceId } })\n if (!space) return false\n await spaceRepo.save(spaceRepo.create({ ...space, primaryRepresentationId: repId }))\n const repRepo = getRepository(TwinSpaceRepresentation)\n const reps = await repRepo.find({ where: { domain: { id: domainId }, space: { id: space.id } } })\n for (const rep of reps) if (!!rep.isPrimary !== (rep.id === repId)) await repRepo.save(repRepo.create({ ...rep, isPrimary: rep.id === repId }))\n return true\n }\n\n /* ── Area (map/image 폴리곤) ────────────────────────────────────── */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'Create/update a polygon area (geometry + drillTo model + binding). Returns {id}.' })\n async saveSpaceArea(\n @Arg('representationId') representationId: string,\n @Arg('area', type => ScalarObject) area: any,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain.id\n const repo = getRepository(TwinSpaceArea)\n const existing = area?.id ? await repo.findOne({ where: { id: area.id } }) : null\n /* drillTo/binding 은 선택적 링크 — 클라가 해제(undefined)로 보내면 JSON 에서 키가 빠져 TypeORM 이 \"변경 없음\"으로\n * 무시하므로 기존 값이 남는다. null 로 강제해 명시적으로 컬럼을 비운다(저장은 늘 전체 필드를 보냄 → 덮어쓰기 안전). */\n const saved = await repo.save(repo.create({ ...(existing ?? {}), domain: { id: domainId } as any, representation: { id: representationId } as any, name: area.name, type: area.type, geometry: area.geometry, drillTo: area.drillTo ?? null, binding: area.binding ?? null, style: area.style }))\n return { ok: true, id: saved.id }\n }\n\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'Delete a polygon area.' })\n async deleteSpaceArea(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n await getRepository(TwinSpaceArea).delete({ domain: { id: context.state.domain.id } as any, id } as any)\n return true\n }\n}\n"]}
|
|
@@ -19,11 +19,31 @@ export declare const personsTag: (instanceId: string) => string;
|
|
|
19
19
|
export declare const assetsTag: (instanceId: string) => string;
|
|
20
20
|
export declare const energyTag: (instanceId: string) => string;
|
|
21
21
|
/**
|
|
22
|
-
* 물품 집약의 상한 — 큰 현장은 물품이 수만 개라, 전량을 매
|
|
22
|
+
* 물품 집약의 상한 — 큰 현장은 물품이 수만 개라, 전량을 매 브로드캐스팅에 실으면 전달이 현장을 느리게 한다.
|
|
23
23
|
*
|
|
24
24
|
* **조용히 자르지 않는다**: 넘치면 `total`(전체 수)과 `truncated`(잘린 수)를 함께 실어, 소비처가
|
|
25
25
|
* "이게 전부" 라고 오해하지 않게 한다. 개별 물품은 태그별 delta 로 따로 나가고 그쪽은 시그니처 dedup
|
|
26
|
-
* 이 걸려 **변한 것만**
|
|
26
|
+
* 이 걸려 **변한 것만** 재브로드캐스팅된다.
|
|
27
27
|
*/
|
|
28
28
|
export declare const ITEMS_AGGREGATE_LIMIT = 500;
|
|
29
|
-
|
|
29
|
+
/**
|
|
30
|
+
* 물품 축만 **범위를 줄일 수 있다** (2026-08-21).
|
|
31
|
+
*
|
|
32
|
+
* ── 왜 이 인자가 생겼나 ─────────────────────────────────────────────────────
|
|
33
|
+
* 브로드캐스팅 한 번이 만드는 payload 는 엔티티 수만큼이고 그 대부분이 물품이다(실측: 엔티티 3,611 중
|
|
34
|
+
* 물품 2,400 · 만드는 데 1.8ms · 문자열로 바꾸는 데 1.0ms). 바뀐 것이 물품 하나여도 전부 만들어
|
|
35
|
+
* 「같다」를 확인하고 버렸다.
|
|
36
|
+
*
|
|
37
|
+
* `items` 를 주면 **그 태그의 물품만** 개별 payload 를 만든다. 주지 않으면(`undefined`) 전부 만든다 —
|
|
38
|
+
* 부르는 쪽이 무엇이 바뀌었는지 말할 수 없을 때의 답이다.
|
|
39
|
+
*
|
|
40
|
+
* **집약 뷰는 범위를 받지 않는다.** 집약은 목록 전체가 한 payload 라서, 한 물품이 바뀌면 그 payload 는
|
|
41
|
+
* 통째로 새로 만들어야 한다(상한 500으로 이미 묶여 있다). 자리·설비·인원·자산·작업·오더도 범위를 받지
|
|
42
|
+
* 않는다 — 수가 적고, 잘못 걸러서 잃는 것이 크다(자리 점유는 물품이 떠난 자리와 도착한 자리가 함께
|
|
43
|
+
* 바뀌는데 사건은 한 지점만 말한다).
|
|
44
|
+
*/
|
|
45
|
+
export interface EntityDeltaScope {
|
|
46
|
+
/** 개별 payload 를 만들 물품 태그. 없으면 전부. */
|
|
47
|
+
items?: ReadonlySet<string>;
|
|
48
|
+
}
|
|
49
|
+
export declare function buildEntityDeltas(state: any, instanceId: string, scope?: EntityDeltaScope): EntityDelta[];
|
|
@@ -73,7 +73,7 @@ exports.energyTag = energyTag;
|
|
|
73
73
|
const EXCLUDED = new Set(['id', 'epc', 'oee']);
|
|
74
74
|
/**
|
|
75
75
|
* OEE 원시 비율/카운트 → 표시용 정수 퍼센트 + 카운트.
|
|
76
|
-
* 원시 누적 ms(idleMs 등)는 매 delta 증가해 무변화-생략을 무력화하므로 제외(유휴 자원의 매초
|
|
76
|
+
* 원시 누적 ms(idleMs 등)는 매 delta 증가해 무변화-생략을 무력화하므로 제외(유휴 자원의 매초 재브로드캐스팅 억제).
|
|
77
77
|
* oee 미측정이면 undefined.
|
|
78
78
|
*/
|
|
79
79
|
function shapeOee(o) {
|
|
@@ -121,11 +121,11 @@ function aggregateItem(entity, idKey) {
|
|
|
121
121
|
return out;
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
|
-
* 물품 집약의 상한 — 큰 현장은 물품이 수만 개라, 전량을 매
|
|
124
|
+
* 물품 집약의 상한 — 큰 현장은 물품이 수만 개라, 전량을 매 브로드캐스팅에 실으면 전달이 현장을 느리게 한다.
|
|
125
125
|
*
|
|
126
126
|
* **조용히 자르지 않는다**: 넘치면 `total`(전체 수)과 `truncated`(잘린 수)를 함께 실어, 소비처가
|
|
127
127
|
* "이게 전부" 라고 오해하지 않게 한다. 개별 물품은 태그별 delta 로 따로 나가고 그쪽은 시그니처 dedup
|
|
128
|
-
* 이 걸려 **변한 것만**
|
|
128
|
+
* 이 걸려 **변한 것만** 재브로드캐스팅된다.
|
|
129
129
|
*/
|
|
130
130
|
exports.ITEMS_AGGREGATE_LIMIT = 500;
|
|
131
131
|
/**
|
|
@@ -176,7 +176,7 @@ function energyByLocation(state) {
|
|
|
176
176
|
}
|
|
177
177
|
return out;
|
|
178
178
|
}
|
|
179
|
-
function buildEntityDeltas(state, instanceId) {
|
|
179
|
+
function buildEntityDeltas(state, instanceId, scope) {
|
|
180
180
|
const out = [];
|
|
181
181
|
const locEnergy = energyByLocation(state);
|
|
182
182
|
for (const n of state?.locations ?? []) {
|
|
@@ -208,9 +208,13 @@ function buildEntityDeltas(state, instanceId) {
|
|
|
208
208
|
out.push({ tag: t.id, data: payloadOf('task', t) });
|
|
209
209
|
}
|
|
210
210
|
for (const it of state?.items ?? []) {
|
|
211
|
-
/* 물품의 태그는 epc(개체 식별자) —
|
|
212
|
-
if (it?.epc)
|
|
213
|
-
|
|
211
|
+
/* 물품의 태그는 epc(개체 식별자) — 자리·설비와 달리 id 가 아니다. */
|
|
212
|
+
if (!it?.epc)
|
|
213
|
+
continue;
|
|
214
|
+
/* 범위가 주어졌으면 그 안의 물품만 만든다 — 나머지는 값이 그대로이므로 보낼 것이 없다. */
|
|
215
|
+
if (scope?.items && !scope.items.has(it.epc))
|
|
216
|
+
continue;
|
|
217
|
+
out.push({ tag: it.epc, data: payloadOf('item', it) });
|
|
214
218
|
}
|
|
215
219
|
/* ── 집약 뷰 ──────────────────────────────────────────────────────────────
|
|
216
220
|
* 런타임에 생기고 사라지는 엔티티(오더·작업·물품)는 보드에 개별 배치할 수 없다 → 한 컴포넌트가
|
|
@@ -275,7 +279,7 @@ function buildEntityDeltas(state, instanceId) {
|
|
|
275
279
|
...(energy.contractKW !== undefined ? { contractKW: energy.contractKW } : {}),
|
|
276
280
|
...(energy.open ? { open: energy.open } : {}),
|
|
277
281
|
...(energy.peakSince ? { peakSince: energy.peakSince } : {}),
|
|
278
|
-
/* 마감된 구간은 **최근 것만** 낸다 — 하루치를 매
|
|
282
|
+
/* 마감된 구간은 **최근 것만** 낸다 — 하루치를 매 브로드캐스팅에 실으면 채널이 그것으로 찬다.
|
|
279
283
|
전체 수는 함께 낸다(조용히 자르지 않는다). */
|
|
280
284
|
recent: (energy.closed ?? []).slice(-8),
|
|
281
285
|
closedTotal: energy.closedTotal ?? 0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-delta.js","sourceRoot":"","sources":["../shared/entity-delta.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;AA0BH,oCAIC;AAsHD,8CAgHC;AA7PD,uEAAuE;AACvE;;;;;;;;GAQG;AACU,QAAA,iBAAiB,GAAG,YAAY,CAAA;AAChC,QAAA,gBAAgB,GAAG,WAAW,CAAA;AAC9B,QAAA,gBAAgB,GAAG,WAAW,CAAA;AAC9B,QAAA,kBAAkB,GAAG,aAAa,CAAA;AAClC,QAAA,iBAAiB,GAAG,YAAY,CAAA;AAC7C,uDAAuD;AAC1C,QAAA,iBAAiB,GAAG,YAAY,CAAA;AAE7C,yDAAyD;AACzD,SAAgB,YAAY,CAAC,MAAc,EAAE,UAAkB;IAC7D,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAA;IAEnG,OAAO,GAAG,MAAM,IAAI,UAAU,EAAE,CAAA;AAClC,CAAC;AAEM,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,yBAAiB,EAAE,UAAU,CAAC,CAAA;AAA/E,QAAA,SAAS,aAAsE;AACrF,MAAM,QAAQ,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,wBAAgB,EAAE,UAAU,CAAC,CAAA;AAA7E,QAAA,QAAQ,YAAqE;AACnF,MAAM,QAAQ,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,wBAAgB,EAAE,UAAU,CAAC,CAAA;AAA7E,QAAA,QAAQ,YAAqE;AACnF,MAAM,UAAU,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,0BAAkB,EAAE,UAAU,CAAC,CAAA;AAAjF,QAAA,UAAU,cAAuE;AACvF,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,yBAAiB,EAAE,UAAU,CAAC,CAAA;AAA/E,QAAA,SAAS,aAAsE;AACrF,MAAM,SAAS,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,YAAY,CAAC,yBAAiB,EAAE,UAAU,CAAC,CAAA;AAA/E,QAAA,SAAS,aAAsE;AAE5F;;;;;GAKG;AACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;AAE9C;;;;GAIG;AACH,SAAS,QAAQ,CAAC,CAAM;IACtB,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAA;IACxB,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;QAC3C,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;QACrD,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;QACnD,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC;QAC3C,IAAI,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC;QACtB,KAAK,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC;KACzB,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,UAAkB,EAAE,MAAW;IAChD,0CAA0C;IAC1C,MAAM,IAAI,GAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QAClD,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,SAAQ;QAChD,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACb,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,MAAW,EAAE,KAAmB;IACrD,MAAM,GAAG,GAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAA;IAC7C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,SAAS;YAAE,SAAQ;QAC3D,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,IAAI,MAAM;QAAE,GAAG,CAAC,GAAG,GAAG,MAAM,CAAA;IAC5B,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;GAMG;AACU,QAAA,qBAAqB,GAAG,GAAG,CAAA;AAExC;;;;;;;;;;;;;;;GAeG;AACH,SAAS,gBAAgB,CAAC,KAAU;IAClC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAmC,CAAA;IACtD,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,CAAA;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,GAAG,CAAA;IAExD,gEAAgE;IAChE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,SAAS,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,YAAY;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;IAErG,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACjD,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAc,EAAE,eAAe,EAAE,CAAC,EAAE,CACzE;QAAC,GAAG,CAAC,MAAmB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QACrC,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAA;QAC1F,4DAA4D;QAC5D,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAAE,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QAChF,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;YAAE,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;QACpF,6DAA6D;QAC7D,IAAI,EAAE,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;YACnD,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,GAAG;gBAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;QAC3E,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IACnB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAgB,iBAAiB,CAAC,KAAU,EAAE,UAAkB;IAC9D,MAAM,GAAG,GAAkB,EAAE,CAAA;IAC7B,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAEzC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC,6DAA6D;QAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAClC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IAC/G,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC;QACvC;6CACqC;QACrC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;QACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC5B,IAAI,GAAG;YAAE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACvB,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/B,CAAC;IACD,gDAAgD;IAChD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IACvD,CAAC;IACD,uCAAuC;IACvC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QACpC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QACpC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QACnC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IACrD,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QACpC,+CAA+C;QAC/C,IAAI,EAAE,EAAE,GAAG;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;IACrE,CAAC;IAED;;kCAE8B;IAC9B,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,EAAE,CAAA;IAClC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAA,iBAAS,EAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAE5H,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,EAAE,CAAA;IAChC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAA,gBAAQ,EAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAExH;kDAC8C;IAC9C,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,EAAE,CAAA;IACpC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAA,kBAAU,EAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAEhI,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,IAAI,EAAE,CAAA;IAClC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAA,iBAAS,EAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAE5H,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,IAAI,EAAE,CAAA;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,6BAAqB,CAAC,CAAA;IACnD,GAAG,CAAC,IAAI,CAAC;QACP,GAAG,EAAE,IAAA,gBAAQ,EAAC,UAAU,CAAC;QACzB,IAAI,EAAE;YACJ,MAAM,EAAE,OAAO;YACf,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACvD,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,iDAAiD;YACjD,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnF;KACF,CAAC,CAAA;IAEF;;;;;;;;;;;;OAYG;IACH,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,CAAA;IAC5B,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC,EAAE,EAAE,EAAE;gBAAE,SAAQ;YACrB,GAAG,CAAC,IAAI,CAAC;gBACP,GAAG,EAAE,EAAE,CAAC,EAAE;gBACV,IAAI,EAAE;oBACJ,MAAM,EAAE,OAAO;oBACf,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7C,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAChD,GAAG,CAAC,EAAE,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxE,yDAAyD;oBACzD,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjF,eAAe,EAAE,EAAE,CAAC,eAAe,IAAI,CAAC;iBACzC;aACF,CAAC,CAAA;QACJ,CAAC;QACD,GAAG,CAAC,IAAI,CAAC;YACP,GAAG,EAAE,IAAA,iBAAS,EAAC,UAAU,CAAC;YAC1B,IAAI,EAAE;gBACJ,MAAM,EAAE,QAAQ;gBAChB,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7E,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7C,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D;+CAC+B;gBAC/B,MAAM,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBACvC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,CAAC;aACrC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC","sourcesContent":["/*\n * 트윈 State 스냅샷 → 라이브 바인딩 delta 목록 (순수 매핑 — pubsub/도메인 무관 → 단위 테스트 가능).\n * publishEntityData 가 이 목록을 엔티티별 시그니처로 dedup 후 data(tag) 채널로 발행한다.\n *\n * ── 규율: 레퍼런스가 아는 것은 **전부** 내보낸다 ────────────────────────────\n * 트윈에서 사소한 속성은 없다. 소속 구역·소속 팔레트·수량·만료처럼 곁가지로 보이는 값이 실제로는\n * 구역 롤업·적재 표현·로트 추적의 전제다. 그래서 여기서 **필드를 손으로 골라 담지 않는다.**\n *\n * 예전에는 엔티티마다 필요할 것 같은 필드만 열거했고, 그 결과 계약에 있는 것이 조용히 누락됐다\n * (2026-08-01 감사: 노드 parentId 누락 · 작업 전량 누락 · 물품 전량 누락). 화이트리스트 방식은\n * **계약이 자라도 화면이 따라오지 못한다** — 커널이 속성을 늘릴 때마다 이 파일을 고쳐야 하고, 고치는\n * 것을 잊으면 아무 신호 없이 정보가 사라진다.\n *\n * 그래서 반대로 한다: **상태 객체가 가진 것을 그대로 통과**시키고, 통과시키지 **않을** 것만 이유와 함께\n * 열거한다(EXCLUDED). 새 속성은 자동으로 화면에 도달하고, 빼려면 이유를 적어야 한다.\n *\n * ── 표식은 도메인 낱말을 훔치지 않는다 ─────────────────────────────────────\n * 예전 payload 는 엔티티 종류 표식을 `kind` 로 실었다. 그런데 `kind` 는 **도메인의 낱말**이다 —\n * 무버 kind=cutter, 작업 kind=putaway, 오더 kind=workorder. 표식이 그 이름을 차지하면 도메인 속성을\n * 실을 자리가 없어진다(같은 병을 오늘 ox-timeline 의 `group` 에서도 고쳤다).\n * 그래서 표식은 `entity`(우리 이름)로 옮기고 `kind` 는 도메인에 돌려준다.\n *\n * payload 계약(씬 컴포넌트가 소비): `entity`(표식) + 그 엔티티의 모든 속성(도메인 `kind` 포함).\n * entity = location · equipment · person · asset · order · task · item,\n * 그리고 집약 태그(__orders__ · __tasks__ · __items__ · __persons__ · __assets__).\n */\n\nexport interface EntityDelta {\n tag: string\n data: any\n}\n\n/** 집약 고정 태그 — 클라 provider 와 일치해야 한다(런타임 생성 엔티티는 개별 배치가 불가하므로 집약 뷰). */\n/*\n * 집약 채널의 접두사 — **실제 태그는 트윈 식별자를 붙여 만든다.**\n *\n * 예전에는 이 상수가 곧 태그였다. 그런데 발행 키는 (도메인, 태그)이고, **한 공간에 트윈이 여럿**\n * 있으면(실측: 3곳 × 3개) 셋이 같은 태그로 발행해 서로 덮었다. 보드의 주문 목록판이 세 공장의 주문\n * 중 마지막에 도착한 것을 보여 준다 — 오류 없이.\n *\n * 구간 성과 태그가 이미 `__kpi__:<트윈>` 으로 트윈을 붙이고 있었다(`kpi-broadcast.ts`). 같은 규약으로 맞춘다.\n */\nexport const ORDERS_TAG_PREFIX = '__orders__'\nexport const TASKS_TAG_PREFIX = '__tasks__'\nexport const ITEMS_TAG_PREFIX = '__items__'\nexport const PERSONS_TAG_PREFIX = '__persons__'\nexport const ASSETS_TAG_PREFIX = '__assets__'\n/** 에너지 집약 — 수요 구간·피크·계약은 **트윈 하나의 사실**이라 개체 태그가 없다. */\nexport const ENERGY_TAG_PREFIX = '__energy__'\n\n/** 이 트윈의 집약 채널 태그. 트윈 식별자가 없으면 만들지 않는다 — 덮어쓰기의 원인이었다. */\nexport function aggregateTag(prefix: string, instanceId: string): string {\n if (!instanceId) throw new Error('aggregateTag: instanceId required — 트윈 구분이 없는 태그는 다른 트윈의 것을 덮는다')\n\n return `${prefix}:${instanceId}`\n}\n\nexport const ordersTag = (instanceId: string) => aggregateTag(ORDERS_TAG_PREFIX, instanceId)\nexport const tasksTag = (instanceId: string) => aggregateTag(TASKS_TAG_PREFIX, instanceId)\nexport const itemsTag = (instanceId: string) => aggregateTag(ITEMS_TAG_PREFIX, instanceId)\nexport const personsTag = (instanceId: string) => aggregateTag(PERSONS_TAG_PREFIX, instanceId)\nexport const assetsTag = (instanceId: string) => aggregateTag(ASSETS_TAG_PREFIX, instanceId)\nexport const energyTag = (instanceId: string) => aggregateTag(ENERGY_TAG_PREFIX, instanceId)\n\n/**\n * 통과시키지 않는 필드 — **빼는 데는 이유가 필요하다.**\n *\n * · `id`/`epc` — 태그로 이미 나가므로 개별 payload 에 중복해 싣지 않는다(집약 뷰에는 넣는다).\n * · `oee` — 원시 누적(idleMs 등)이 매 delta 증가해 \"무변화 생략\" 을 무력화한다. shapeOee 로 정형화해 얹는다.\n */\nconst EXCLUDED = new Set(['id', 'epc', 'oee'])\n\n/**\n * OEE 원시 비율/카운트 → 표시용 정수 퍼센트 + 카운트.\n * 원시 누적 ms(idleMs 등)는 매 delta 증가해 무변화-생략을 무력화하므로 제외(유휴 자원의 매초 재방송 억제).\n * oee 미측정이면 undefined.\n */\nfunction shapeOee(o: any): any {\n if (!o) return undefined\n return {\n overall: Math.round((o.overall ?? 0) * 100),\n availability: Math.round((o.availability ?? 0) * 100),\n performance: Math.round((o.performance ?? 0) * 100),\n quality: Math.round((o.quality ?? 0) * 100),\n good: o.goodCount ?? 0,\n scrap: o.scrapCount ?? 0\n }\n}\n\n/**\n * 엔티티 하나의 payload — `entity` 표식 + 나머지 전부(도메인 `kind` 포함).\n *\n * `undefined` 값은 싣지 않는다(키의 유무가 시그니처를 흔들지 않게). 값이 없는 것과 키가 없는 것은\n * 소비처에서 같으므로 안전하고, 무변화 생략이 잘 듣는다.\n */\nfunction payloadOf(entityKind: string, entity: any): any {\n /* 표식은 `entity` — 도메인의 `kind` 를 덮지 않는다. */\n const data: any = { entity: entityKind }\n for (const [k, v] of Object.entries(entity ?? {})) {\n if (EXCLUDED.has(k) || v === undefined) continue\n data[k] = v\n }\n return data\n}\n\n/**\n * 집약 뷰의 항목 — 개별 payload 와 같은 내용 + 식별자.\n * 집약은 \"전체를 한 컴포넌트가 추적\" 하는 용도라 식별자가 있어야 한다.\n */\nfunction aggregateItem(entity: any, idKey: 'id' | 'epc'): any {\n const out: any = { [idKey]: entity?.[idKey] }\n for (const [k, v] of Object.entries(entity ?? {})) {\n if (k === idKey || k === 'oee' || v === undefined) continue\n out[k] = v\n }\n const shaped = shapeOee(entity?.oee)\n if (shaped) out.oee = shaped\n return out\n}\n\n/**\n * 물품 집약의 상한 — 큰 현장은 물품이 수만 개라, 전량을 매 방송에 실으면 전달이 현장을 느리게 한다.\n *\n * **조용히 자르지 않는다**: 넘치면 `total`(전체 수)과 `truncated`(잘린 수)를 함께 실어, 소비처가\n * \"이게 전부\" 라고 오해하지 않게 한다. 개별 물품은 태그별 delta 로 따로 나가고 그쪽은 시그니처 dedup\n * 이 걸려 **변한 것만** 재방송된다.\n */\nexport const ITEMS_AGGREGATE_LIMIT = 500\n\n/**\n * 자리별 에너지 — **그 자리의 계량기들이 잰 것**을 그 자리 태그에 실을 수 있게 모은다.\n *\n * ── 왜 자리에도 필요한가 (2026-08-14) ───────────────────────────────────────\n * 카탈로그는 자리에도 `metered` 를 준다(수전·분기·구역 계량은 재는 자리다). 그런데 값은 계량기\n * **설비** 태그로만 나갔다. 그래서 계통도의 분기 자리에 계량 컴포넌트를 놓으면 **영원히 「—」** 였다 —\n * 능력은 「잰다」고 말하는데 값이 오지 않는 자리.\n *\n * 「이 구간이 얼마를 먹나」는 자리의 사실이고, 사람은 계통도의 자리에 붙여 본다.\n *\n * ── 계층은 여기서 문제가 되지 않는다 ────────────────────────────────────────\n * 각 자리에는 **그 자리에 붙은 계량기만** 더한다(수전 자리에는 수전 계량기, 분기 자리에는 그 분기의\n * 것). 커널이 부하를 뿌리로만 세는 것과 다른 층의 계산이다 — 여기서는 자리마다 자기 것을 말한다.\n *\n * 근거를 함께 낸다(`meters`) — 그 자리의 수가 어느 계량기에서 왔는지 되짚을 수 있어야 한다.\n */\nfunction energyByLocation(state: any): Map<string, Record<string, unknown>> {\n const out = new Map<string, Record<string, unknown>>()\n const points = state?.energy?.points\n if (!Array.isArray(points) || !points.length) return out\n\n /* 계량기 → 자리. 자리를 모르는 계량기는 자리 payload 에 실을 데가 없다(설비 태그로만 나간다). */\n const locOf = new Map<string, string>()\n for (const e of state?.equipment ?? []) if (e?.id && e?.homeLocation) locOf.set(e.id, e.homeLocation)\n\n for (const pt of points) {\n const loc = pt?.id ? locOf.get(pt.id) : undefined\n if (!loc) continue\n const acc = out.get(loc) ?? { meters: [] as string[], samplesInWindow: 0 }\n ;(acc.meters as string[]).push(pt.id)\n acc.samplesInWindow = Number(acc.samplesInWindow ?? 0) + (Number(pt.samplesInWindow) || 0)\n /* 값은 **있는 것만** 더한다 — 하나도 없으면 키를 만들지 않는다(0 은 「안 썼다」가 된다). */\n if (Number.isFinite(Number(pt.kW))) acc.kW = Number(acc.kW ?? 0) + Number(pt.kW)\n if (Number.isFinite(Number(pt.kWh))) acc.kWh = Number(acc.kWh ?? 0) + Number(pt.kWh)\n /* 나이는 **가장 최근**을 쓴다 — 자리에 계량기가 여럿이면 그중 마지막 관측이 그 자리의 나이다. */\n if (pt.atMs !== undefined) {\n const iso = new Date(Number(pt.atMs)).toISOString()\n if (!acc.measuredAt || String(acc.measuredAt) < iso) acc.measuredAt = iso\n }\n out.set(loc, acc)\n }\n return out\n}\n\nexport function buildEntityDeltas(state: any, instanceId: string): EntityDelta[] {\n const out: EntityDelta[] = []\n const locEnergy = energyByLocation(state)\n\n for (const n of state?.locations ?? []) {\n /* 에너지는 자리 payload 에 **합친다** — 같은 태그로 두 번 보내면 뒤엣것이 앞을 덮는다. */\n const energy = locEnergy.get(n.id)\n out.push({ tag: n.id, data: energy ? { ...payloadOf('location', n), ...energy } : payloadOf('location', n) })\n }\n for (const m of state?.equipment ?? []) {\n /* Mobile(location/motion) + Operable(status/held) + Processable(oee) — 한 payload 로.\n * oee 만 정형화가 필요해 따로 얹는다(나머지는 통과). */\n const data = payloadOf('equipment', m)\n const oee = shapeOee(m?.oee)\n if (oee) data.oee = oee\n out.push({ tag: m.id, data })\n }\n /* 사람 — 설비와 별개 엔티티다. 같은 통과 규칙(가진 것을 전부 내보낸다). */\n for (const p of state?.persons ?? []) {\n out.push({ tag: p.id, data: payloadOf('person', p) })\n }\n /* 물리 자산(반복사용) — 물품도 설비도 아닌 네 번째 자원. */\n for (const a of state?.assets ?? []) {\n out.push({ tag: a.id, data: payloadOf('asset', a) })\n }\n for (const o of state?.orders ?? []) {\n out.push({ tag: o.id, data: payloadOf('order', o) })\n }\n for (const t of state?.tasks ?? []) {\n out.push({ tag: t.id, data: payloadOf('task', t) })\n }\n for (const it of state?.items ?? []) {\n /* 물품의 태그는 epc(개체 식별자) — 노드·무버와 달리 id 가 아니다. */\n if (it?.epc) out.push({ tag: it.epc, data: payloadOf('item', it) })\n }\n\n /* ── 집약 뷰 ──────────────────────────────────────────────────────────────\n * 런타임에 생기고 사라지는 엔티티(오더·작업·물품)는 보드에 개별 배치할 수 없다 → 한 컴포넌트가\n * 전체를 추적하는 집약 태그를 항상 방출한다. */\n const orders = state?.orders ?? []\n out.push({ tag: ordersTag(instanceId), data: { entity: 'orders', orders: orders.map((o: any) => aggregateItem(o, 'id')) } })\n\n const tasks = state?.tasks ?? []\n out.push({ tag: tasksTag(instanceId), data: { entity: 'tasks', tasks: tasks.map((t: any) => aggregateItem(t, 'id')) } })\n\n /* 사람 집약 — 인원은 보드에 개별 배치할 수도 있지만(설비처럼), 전체를 한눈에 보는 소비처도 있다.\n * 인원을 선언하지 않은 트윈에서는 빈 배열이 나간다(없음과 모름을 구별). */\n const persons = state?.persons ?? []\n out.push({ tag: personsTag(instanceId), data: { entity: 'persons', persons: persons.map((p: any) => aggregateItem(p, 'id')) } })\n\n const assets = state?.assets ?? []\n out.push({ tag: assetsTag(instanceId), data: { entity: 'assets', assets: assets.map((a: any) => aggregateItem(a, 'id')) } })\n\n const items = state?.items ?? []\n const shown = items.slice(0, ITEMS_AGGREGATE_LIMIT)\n out.push({\n tag: itemsTag(instanceId),\n data: {\n entity: 'items',\n items: shown.map((it: any) => aggregateItem(it, 'epc')),\n total: items.length,\n /* 잘렸으면 그 사실을 말한다 — \"이게 전부\" 로 읽히면 재고를 과소 판단한다. */\n ...(items.length > shown.length ? { truncated: items.length - shown.length } : {})\n }\n })\n\n /*\n * ── 에너지 (EMS) ─────────────────────────────────────────────────────────\n *\n * 계측은 `state.energy` 에 산다 — 자원 축(`equipment`·`locations`)이 아니다. 그래서 이 매핑이 없으면\n * 보드에 놓은 계량기가 **아무 값도 받지 못한다**(컴포넌트는 있는데 영원히 빈 모습).\n *\n * 두 갈래로 낸다:\n * · **개체별** — 계량 지점 하나하나의 마지막 관측(kW·kWh·역률·시각). 태그는 그 설비 id 다.\n * · **집약** — 수요 구간·피크·계약전력. 이것은 트윈 하나의 사실이라 개체에 실을 수 없다.\n *\n * 값이 없으면 **키를 넣지 않는다**(0 으로 만들지 않는다) — 「못 읽었다」와 「0 이었다」는 다른 사실이고,\n * 그 구별이 이 트윈의 값어치다.\n */\n const energy = state?.energy\n if (energy) {\n for (const pt of energy.points ?? []) {\n if (!pt?.id) continue\n out.push({\n tag: pt.id,\n data: {\n entity: 'meter',\n ...(pt.kW !== undefined ? { kW: pt.kW } : {}),\n ...(pt.kWh !== undefined ? { kWh: pt.kWh } : {}),\n ...(pt.powerFactor !== undefined ? { powerFactor: pt.powerFactor } : {}),\n /* 마지막 표본 시각 — 계측이 끊긴 것을 화면이 스스로 알 수 있게(우리가 판정하지 않는다). */\n ...(pt.atMs !== undefined ? { measuredAt: new Date(pt.atMs).toISOString() } : {}),\n samplesInWindow: pt.samplesInWindow ?? 0\n }\n })\n }\n out.push({\n tag: energyTag(instanceId),\n data: {\n entity: 'energy',\n ...(energy.contractKW !== undefined ? { contractKW: energy.contractKW } : {}),\n ...(energy.open ? { open: energy.open } : {}),\n ...(energy.peakSince ? { peakSince: energy.peakSince } : {}),\n /* 마감된 구간은 **최근 것만** 낸다 — 하루치를 매 방송에 실으면 채널이 그것으로 찬다.\n 전체 수는 함께 낸다(조용히 자르지 않는다). */\n recent: (energy.closed ?? []).slice(-8),\n closedTotal: energy.closedTotal ?? 0\n }\n })\n }\n\n return out\n}\n"]}
|
|
1
|
+
{"version":3,"file":"entity-delta.js","sourceRoot":"","sources":["../shared/entity-delta.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 트윈 State 스냅샷 → 라이브 바인딩 delta 목록 (순수 매핑 — pubsub/도메인 무관 → 단위 테스트 가능).\n * publishEntityData 가 이 목록을 엔티티별 시그니처로 dedup 후 data(tag) 채널로 발행한다.\n *\n * ── 규율: 레퍼런스가 아는 것은 **전부** 내보낸다 ────────────────────────────\n * 트윈에서 사소한 속성은 없다. 소속 구역·소속 팔레트·수량·만료처럼 곁가지로 보이는 값이 실제로는\n * 구역 롤업·적재 표현·로트 추적의 전제다. 그래서 여기서 **필드를 손으로 골라 담지 않는다.**\n *\n * 예전에는 엔티티마다 필요할 것 같은 필드만 열거했고, 그 결과 계약에 있는 것이 조용히 누락됐다\n * (2026-08-01 감사: 노드 parentId 누락 · 작업 전량 누락 · 물품 전량 누락). 화이트리스트 방식은\n * **계약이 자라도 화면이 따라오지 못한다** — 커널이 속성을 늘릴 때마다 이 파일을 고쳐야 하고, 고치는\n * 것을 잊으면 아무 신호 없이 정보가 사라진다.\n *\n * 그래서 반대로 한다: **상태 객체가 가진 것을 그대로 통과**시키고, 통과시키지 **않을** 것만 이유와 함께\n * 열거한다(EXCLUDED). 새 속성은 자동으로 화면에 도달하고, 빼려면 이유를 적어야 한다.\n *\n * ── 표식은 도메인 낱말을 훔치지 않는다 ─────────────────────────────────────\n * 예전 payload 는 엔티티 종류 표식을 `kind` 로 실었다. 그런데 `kind` 는 **도메인의 낱말**이다 —\n * 무버 kind=cutter, 작업 kind=putaway, 오더 kind=workorder. 표식이 그 이름을 차지하면 도메인 속성을\n * 실을 자리가 없어진다(같은 병을 오늘 ox-timeline 의 `group` 에서도 고쳤다).\n * 그래서 표식은 `entity`(우리 이름)로 옮기고 `kind` 는 도메인에 돌려준다.\n *\n * payload 계약(씬 컴포넌트가 소비): `entity`(표식) + 그 엔티티의 모든 속성(도메인 `kind` 포함).\n * entity = location · equipment · person · asset · order · task · item,\n * 그리고 집약 태그(__orders__ · __tasks__ · __items__ · __persons__ · __assets__).\n */\n\nexport interface EntityDelta {\n tag: string\n data: any\n}\n\n/** 집약 고정 태그 — 클라 provider 와 일치해야 한다(런타임 생성 엔티티는 개별 배치가 불가하므로 집약 뷰). */\n/*\n * 집약 채널의 접두사 — **실제 태그는 트윈 식별자를 붙여 만든다.**\n *\n * 예전에는 이 상수가 곧 태그였다. 그런데 발행 키는 (도메인, 태그)이고, **한 공간에 트윈이 여럿**\n * 있으면(실측: 3곳 × 3개) 셋이 같은 태그로 발행해 서로 덮었다. 보드의 주문 목록판이 세 공장의 주문\n * 중 마지막에 도착한 것을 보여 준다 — 오류 없이.\n *\n * 구간 성과 태그가 이미 `__kpi__:<트윈>` 으로 트윈을 붙이고 있었다(`kpi-broadcast.ts`). 같은 규약으로 맞춘다.\n */\nexport const ORDERS_TAG_PREFIX = '__orders__'\nexport const TASKS_TAG_PREFIX = '__tasks__'\nexport const ITEMS_TAG_PREFIX = '__items__'\nexport const PERSONS_TAG_PREFIX = '__persons__'\nexport const ASSETS_TAG_PREFIX = '__assets__'\n/** 에너지 집약 — 수요 구간·피크·계약은 **트윈 하나의 사실**이라 개체 태그가 없다. */\nexport const ENERGY_TAG_PREFIX = '__energy__'\n\n/** 이 트윈의 집약 채널 태그. 트윈 식별자가 없으면 만들지 않는다 — 덮어쓰기의 원인이었다. */\nexport function aggregateTag(prefix: string, instanceId: string): string {\n if (!instanceId) throw new Error('aggregateTag: instanceId required — 트윈 구분이 없는 태그는 다른 트윈의 것을 덮는다')\n\n return `${prefix}:${instanceId}`\n}\n\nexport const ordersTag = (instanceId: string) => aggregateTag(ORDERS_TAG_PREFIX, instanceId)\nexport const tasksTag = (instanceId: string) => aggregateTag(TASKS_TAG_PREFIX, instanceId)\nexport const itemsTag = (instanceId: string) => aggregateTag(ITEMS_TAG_PREFIX, instanceId)\nexport const personsTag = (instanceId: string) => aggregateTag(PERSONS_TAG_PREFIX, instanceId)\nexport const assetsTag = (instanceId: string) => aggregateTag(ASSETS_TAG_PREFIX, instanceId)\nexport const energyTag = (instanceId: string) => aggregateTag(ENERGY_TAG_PREFIX, instanceId)\n\n/**\n * 통과시키지 않는 필드 — **빼는 데는 이유가 필요하다.**\n *\n * · `id`/`epc` — 태그로 이미 나가므로 개별 payload 에 중복해 싣지 않는다(집약 뷰에는 넣는다).\n * · `oee` — 원시 누적(idleMs 등)이 매 delta 증가해 \"무변화 생략\" 을 무력화한다. shapeOee 로 정형화해 얹는다.\n */\nconst EXCLUDED = new Set(['id', 'epc', 'oee'])\n\n/**\n * OEE 원시 비율/카운트 → 표시용 정수 퍼센트 + 카운트.\n * 원시 누적 ms(idleMs 등)는 매 delta 증가해 무변화-생략을 무력화하므로 제외(유휴 자원의 매초 재브로드캐스팅 억제).\n * oee 미측정이면 undefined.\n */\nfunction shapeOee(o: any): any {\n if (!o) return undefined\n return {\n overall: Math.round((o.overall ?? 0) * 100),\n availability: Math.round((o.availability ?? 0) * 100),\n performance: Math.round((o.performance ?? 0) * 100),\n quality: Math.round((o.quality ?? 0) * 100),\n good: o.goodCount ?? 0,\n scrap: o.scrapCount ?? 0\n }\n}\n\n/**\n * 엔티티 하나의 payload — `entity` 표식 + 나머지 전부(도메인 `kind` 포함).\n *\n * `undefined` 값은 싣지 않는다(키의 유무가 시그니처를 흔들지 않게). 값이 없는 것과 키가 없는 것은\n * 소비처에서 같으므로 안전하고, 무변화 생략이 잘 듣는다.\n */\nfunction payloadOf(entityKind: string, entity: any): any {\n /* 표식은 `entity` — 도메인의 `kind` 를 덮지 않는다. */\n const data: any = { entity: entityKind }\n for (const [k, v] of Object.entries(entity ?? {})) {\n if (EXCLUDED.has(k) || v === undefined) continue\n data[k] = v\n }\n return data\n}\n\n/**\n * 집약 뷰의 항목 — 개별 payload 와 같은 내용 + 식별자.\n * 집약은 \"전체를 한 컴포넌트가 추적\" 하는 용도라 식별자가 있어야 한다.\n */\nfunction aggregateItem(entity: any, idKey: 'id' | 'epc'): any {\n const out: any = { [idKey]: entity?.[idKey] }\n for (const [k, v] of Object.entries(entity ?? {})) {\n if (k === idKey || k === 'oee' || v === undefined) continue\n out[k] = v\n }\n const shaped = shapeOee(entity?.oee)\n if (shaped) out.oee = shaped\n return out\n}\n\n/**\n * 물품 집약의 상한 — 큰 현장은 물품이 수만 개라, 전량을 매 브로드캐스팅에 실으면 전달이 현장을 느리게 한다.\n *\n * **조용히 자르지 않는다**: 넘치면 `total`(전체 수)과 `truncated`(잘린 수)를 함께 실어, 소비처가\n * \"이게 전부\" 라고 오해하지 않게 한다. 개별 물품은 태그별 delta 로 따로 나가고 그쪽은 시그니처 dedup\n * 이 걸려 **변한 것만** 재브로드캐스팅된다.\n */\nexport const ITEMS_AGGREGATE_LIMIT = 500\n\n/**\n * 자리별 에너지 — **그 자리의 계량기들이 잰 것**을 그 자리 태그에 실을 수 있게 모은다.\n *\n * ── 왜 자리에도 필요한가 (2026-08-14) ───────────────────────────────────────\n * 카탈로그는 자리에도 `metered` 를 준다(수전·분기·구역 계량은 재는 자리다). 그런데 값은 계량기\n * **설비** 태그로만 나갔다. 그래서 계통도의 분기 자리에 계량 컴포넌트를 놓으면 **영원히 「—」** 였다 —\n * 능력은 「잰다」고 말하는데 값이 오지 않는 자리.\n *\n * 「이 구간이 얼마를 먹나」는 자리의 사실이고, 사람은 계통도의 자리에 붙여 본다.\n *\n * ── 계층은 여기서 문제가 되지 않는다 ────────────────────────────────────────\n * 각 자리에는 **그 자리에 붙은 계량기만** 더한다(수전 자리에는 수전 계량기, 분기 자리에는 그 분기의\n * 것). 커널이 부하를 뿌리로만 세는 것과 다른 층의 계산이다 — 여기서는 자리마다 자기 것을 말한다.\n *\n * 근거를 함께 낸다(`meters`) — 그 자리의 수가 어느 계량기에서 왔는지 되짚을 수 있어야 한다.\n */\nfunction energyByLocation(state: any): Map<string, Record<string, unknown>> {\n const out = new Map<string, Record<string, unknown>>()\n const points = state?.energy?.points\n if (!Array.isArray(points) || !points.length) return out\n\n /* 계량기 → 자리. 자리를 모르는 계량기는 자리 payload 에 실을 데가 없다(설비 태그로만 나간다). */\n const locOf = new Map<string, string>()\n for (const e of state?.equipment ?? []) if (e?.id && e?.homeLocation) locOf.set(e.id, e.homeLocation)\n\n for (const pt of points) {\n const loc = pt?.id ? locOf.get(pt.id) : undefined\n if (!loc) continue\n const acc = out.get(loc) ?? { meters: [] as string[], samplesInWindow: 0 }\n ;(acc.meters as string[]).push(pt.id)\n acc.samplesInWindow = Number(acc.samplesInWindow ?? 0) + (Number(pt.samplesInWindow) || 0)\n /* 값은 **있는 것만** 더한다 — 하나도 없으면 키를 만들지 않는다(0 은 「안 썼다」가 된다). */\n if (Number.isFinite(Number(pt.kW))) acc.kW = Number(acc.kW ?? 0) + Number(pt.kW)\n if (Number.isFinite(Number(pt.kWh))) acc.kWh = Number(acc.kWh ?? 0) + Number(pt.kWh)\n /* 나이는 **가장 최근**을 쓴다 — 자리에 계량기가 여럿이면 그중 마지막 관측이 그 자리의 나이다. */\n if (pt.atMs !== undefined) {\n const iso = new Date(Number(pt.atMs)).toISOString()\n if (!acc.measuredAt || String(acc.measuredAt) < iso) acc.measuredAt = iso\n }\n out.set(loc, acc)\n }\n return out\n}\n\n/**\n * 물품 축만 **범위를 줄일 수 있다** (2026-08-21).\n *\n * ── 왜 이 인자가 생겼나 ─────────────────────────────────────────────────────\n * 브로드캐스팅 한 번이 만드는 payload 는 엔티티 수만큼이고 그 대부분이 물품이다(실측: 엔티티 3,611 중\n * 물품 2,400 · 만드는 데 1.8ms · 문자열로 바꾸는 데 1.0ms). 바뀐 것이 물품 하나여도 전부 만들어\n * 「같다」를 확인하고 버렸다.\n *\n * `items` 를 주면 **그 태그의 물품만** 개별 payload 를 만든다. 주지 않으면(`undefined`) 전부 만든다 —\n * 부르는 쪽이 무엇이 바뀌었는지 말할 수 없을 때의 답이다.\n *\n * **집약 뷰는 범위를 받지 않는다.** 집약은 목록 전체가 한 payload 라서, 한 물품이 바뀌면 그 payload 는\n * 통째로 새로 만들어야 한다(상한 500으로 이미 묶여 있다). 자리·설비·인원·자산·작업·오더도 범위를 받지\n * 않는다 — 수가 적고, 잘못 걸러서 잃는 것이 크다(자리 점유는 물품이 떠난 자리와 도착한 자리가 함께\n * 바뀌는데 사건은 한 지점만 말한다).\n */\nexport interface EntityDeltaScope {\n /** 개별 payload 를 만들 물품 태그. 없으면 전부. */\n items?: ReadonlySet<string>\n}\n\nexport function buildEntityDeltas(state: any, instanceId: string, scope?: EntityDeltaScope): EntityDelta[] {\n const out: EntityDelta[] = []\n const locEnergy = energyByLocation(state)\n\n for (const n of state?.locations ?? []) {\n /* 에너지는 자리 payload 에 **합친다** — 같은 태그로 두 번 보내면 뒤엣것이 앞을 덮는다. */\n const energy = locEnergy.get(n.id)\n out.push({ tag: n.id, data: energy ? { ...payloadOf('location', n), ...energy } : payloadOf('location', n) })\n }\n for (const m of state?.equipment ?? []) {\n /* Mobile(location/motion) + Operable(status/held) + Processable(oee) — 한 payload 로.\n * oee 만 정형화가 필요해 따로 얹는다(나머지는 통과). */\n const data = payloadOf('equipment', m)\n const oee = shapeOee(m?.oee)\n if (oee) data.oee = oee\n out.push({ tag: m.id, data })\n }\n /* 사람 — 설비와 별개 엔티티다. 같은 통과 규칙(가진 것을 전부 내보낸다). */\n for (const p of state?.persons ?? []) {\n out.push({ tag: p.id, data: payloadOf('person', p) })\n }\n /* 물리 자산(반복사용) — 물품도 설비도 아닌 네 번째 자원. */\n for (const a of state?.assets ?? []) {\n out.push({ tag: a.id, data: payloadOf('asset', a) })\n }\n for (const o of state?.orders ?? []) {\n out.push({ tag: o.id, data: payloadOf('order', o) })\n }\n for (const t of state?.tasks ?? []) {\n out.push({ tag: t.id, data: payloadOf('task', t) })\n }\n for (const it of state?.items ?? []) {\n /* 물품의 태그는 epc(개체 식별자) — 자리·설비와 달리 id 가 아니다. */\n if (!it?.epc) continue\n /* 범위가 주어졌으면 그 안의 물품만 만든다 — 나머지는 값이 그대로이므로 보낼 것이 없다. */\n if (scope?.items && !scope.items.has(it.epc)) continue\n out.push({ tag: it.epc, data: payloadOf('item', it) })\n }\n\n /* ── 집약 뷰 ──────────────────────────────────────────────────────────────\n * 런타임에 생기고 사라지는 엔티티(오더·작업·물품)는 보드에 개별 배치할 수 없다 → 한 컴포넌트가\n * 전체를 추적하는 집약 태그를 항상 방출한다. */\n const orders = state?.orders ?? []\n out.push({ tag: ordersTag(instanceId), data: { entity: 'orders', orders: orders.map((o: any) => aggregateItem(o, 'id')) } })\n\n const tasks = state?.tasks ?? []\n out.push({ tag: tasksTag(instanceId), data: { entity: 'tasks', tasks: tasks.map((t: any) => aggregateItem(t, 'id')) } })\n\n /* 사람 집약 — 인원은 보드에 개별 배치할 수도 있지만(설비처럼), 전체를 한눈에 보는 소비처도 있다.\n * 인원을 선언하지 않은 트윈에서는 빈 배열이 나간다(없음과 모름을 구별). */\n const persons = state?.persons ?? []\n out.push({ tag: personsTag(instanceId), data: { entity: 'persons', persons: persons.map((p: any) => aggregateItem(p, 'id')) } })\n\n const assets = state?.assets ?? []\n out.push({ tag: assetsTag(instanceId), data: { entity: 'assets', assets: assets.map((a: any) => aggregateItem(a, 'id')) } })\n\n const items = state?.items ?? []\n const shown = items.slice(0, ITEMS_AGGREGATE_LIMIT)\n out.push({\n tag: itemsTag(instanceId),\n data: {\n entity: 'items',\n items: shown.map((it: any) => aggregateItem(it, 'epc')),\n total: items.length,\n /* 잘렸으면 그 사실을 말한다 — \"이게 전부\" 로 읽히면 재고를 과소 판단한다. */\n ...(items.length > shown.length ? { truncated: items.length - shown.length } : {})\n }\n })\n\n /*\n * ── 에너지 (EMS) ─────────────────────────────────────────────────────────\n *\n * 계측은 `state.energy` 에 산다 — 자원 축(`equipment`·`locations`)이 아니다. 그래서 이 매핑이 없으면\n * 보드에 놓은 계량기가 **아무 값도 받지 못한다**(컴포넌트는 있는데 영원히 빈 모습).\n *\n * 두 갈래로 낸다:\n * · **개체별** — 계량 지점 하나하나의 마지막 관측(kW·kWh·역률·시각). 태그는 그 설비 id 다.\n * · **집약** — 수요 구간·피크·계약전력. 이것은 트윈 하나의 사실이라 개체에 실을 수 없다.\n *\n * 값이 없으면 **키를 넣지 않는다**(0 으로 만들지 않는다) — 「못 읽었다」와 「0 이었다」는 다른 사실이고,\n * 그 구별이 이 트윈의 값어치다.\n */\n const energy = state?.energy\n if (energy) {\n for (const pt of energy.points ?? []) {\n if (!pt?.id) continue\n out.push({\n tag: pt.id,\n data: {\n entity: 'meter',\n ...(pt.kW !== undefined ? { kW: pt.kW } : {}),\n ...(pt.kWh !== undefined ? { kWh: pt.kWh } : {}),\n ...(pt.powerFactor !== undefined ? { powerFactor: pt.powerFactor } : {}),\n /* 마지막 표본 시각 — 계측이 끊긴 것을 화면이 스스로 알 수 있게(우리가 판정하지 않는다). */\n ...(pt.atMs !== undefined ? { measuredAt: new Date(pt.atMs).toISOString() } : {}),\n samplesInWindow: pt.samplesInWindow ?? 0\n }\n })\n }\n out.push({\n tag: energyTag(instanceId),\n data: {\n entity: 'energy',\n ...(energy.contractKW !== undefined ? { contractKW: energy.contractKW } : {}),\n ...(energy.open ? { open: energy.open } : {}),\n ...(energy.peakSince ? { peakSince: energy.peakSince } : {}),\n /* 마감된 구간은 **최근 것만** 낸다 — 하루치를 매 브로드캐스팅에 실으면 채널이 그것으로 찬다.\n 전체 수는 함께 낸다(조용히 자르지 않는다). */\n recent: (energy.closed ?? []).slice(-8),\n closedTotal: energy.closedTotal ?? 0\n }\n })\n }\n\n return out\n}\n"]}
|
|
@@ -4,7 +4,7 @@ exports.kpiTag = exports.KPI_TAG_PREFIX = void 0;
|
|
|
4
4
|
/*
|
|
5
5
|
* 구간 성과 카드의 **대상 식별자**.
|
|
6
6
|
*
|
|
7
|
-
* 예전에는 이 파일이
|
|
7
|
+
* 예전에는 이 파일이 브로드캐스팅 payload 도 만들었다(`shapeKpiBroadcast`). 2026-08-06 에 브로드캐스팅을 없애고 카드가
|
|
8
8
|
* `twinKpi` 를 직접 묻게 바꿔서, 남은 것은 팔레트가 대상을 가리킬 때 쓰는 식별자뿐이다.
|
|
9
9
|
* 왜 바꿨는지는 `twin-engine.ts` 의 주석과 `operato-twin/client/scene/twin-kpi-source.ts` 에 있다.
|
|
10
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kpi-broadcast.js","sourceRoot":"","sources":["../shared/kpi-broadcast.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACU,QAAA,cAAc,GAAG,SAAS,CAAA;AAEvC,sBAAsB;AACf,MAAM,MAAM,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,GAAG,sBAAc,IAAI,UAAU,EAAE,CAAA;AAAlE,QAAA,MAAM,UAA4D;AAE/E,kFAAkF","sourcesContent":["/*\n * 구간 성과 카드의 **대상 식별자**.\n *\n * 예전에는 이 파일이
|
|
1
|
+
{"version":3,"file":"kpi-broadcast.js","sourceRoot":"","sources":["../shared/kpi-broadcast.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACU,QAAA,cAAc,GAAG,SAAS,CAAA;AAEvC,sBAAsB;AACf,MAAM,MAAM,GAAG,CAAC,UAAkB,EAAE,EAAE,CAAC,GAAG,sBAAc,IAAI,UAAU,EAAE,CAAA;AAAlE,QAAA,MAAM,UAA4D;AAE/E,kFAAkF","sourcesContent":["/*\n * 구간 성과 카드의 **대상 식별자**.\n *\n * 예전에는 이 파일이 브로드캐스팅 payload 도 만들었다(`shapeKpiBroadcast`). 2026-08-06 에 브로드캐스팅을 없애고 카드가\n * `twinKpi` 를 직접 묻게 바꿔서, 남은 것은 팔레트가 대상을 가리킬 때 쓰는 식별자뿐이다.\n * 왜 바꿨는지는 `twin-engine.ts` 의 주석과 `operato-twin/client/scene/twin-kpi-source.ts` 에 있다.\n */\nexport const KPI_TAG_PREFIX = '__kpi__'\n\n/** 이 트윈의 구간 성과 태그. */\nexport const kpiTag = (instanceId: string) => `${KPI_TAG_PREFIX}:${instanceId}`\n\n/** 표식은 `entity` 로 — `kind` 는 도메인의 낱말이라 표식이 훔치지 않는다(`entity-delta.ts` 와 같은 규약). */\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 이 사건이 건드린 물품 태그들. **말할 수 없으면 `null`** — 호출자는 그때 전부 다시 만든다.
|
|
3
|
+
*
|
|
4
|
+
* 개체를 말하는 자리를 전부 본다: `epcList`(관측·커미셔닝) · `parentID`(집약의 부모) ·
|
|
5
|
+
* `childEPCs`(집약의 자식) · `inputEPCList`·`outputEPCList`(변환의 입출력).
|
|
6
|
+
*/
|
|
7
|
+
export declare function touchedItemKeys(envelope: any): Set<string> | null;
|