@things-factory/headless-twin 10.0.18 โ 10.1.0
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 +10 -1
- package/dist-server/engine/canonical-ingest.js +110 -33
- package/dist-server/engine/canonical-ingest.js.map +1 -1
- package/dist-server/engine/event-time.d.ts +25 -0
- package/dist-server/engine/event-time.js +98 -0
- package/dist-server/engine/event-time.js.map +1 -0
- package/dist-server/engine/index.d.ts +2 -0
- package/dist-server/engine/index.js +23 -0
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/engine/ingest-dedupe.d.ts +18 -6
- package/dist-server/engine/ingest-dedupe.js +201 -15
- package/dist-server/engine/ingest-dedupe.js.map +1 -1
- package/dist-server/engine/ingest-health.d.ts +60 -1
- package/dist-server/engine/ingest-health.js +43 -8
- package/dist-server/engine/ingest-health.js.map +1 -1
- package/dist-server/engine/kpi-fold.d.ts +19 -0
- package/dist-server/engine/kpi-fold.js +4 -1
- package/dist-server/engine/kpi-fold.js.map +1 -1
- package/dist-server/engine/kpi-query.js +23 -3
- package/dist-server/engine/kpi-query.js.map +1 -1
- package/dist-server/engine/oee-accumulator.d.ts +35 -2
- package/dist-server/engine/oee-accumulator.js +56 -4
- package/dist-server/engine/oee-accumulator.js.map +1 -1
- package/dist-server/engine/twin-engine.d.ts +72 -3
- package/dist-server/engine/twin-engine.js +118 -5
- package/dist-server/engine/twin-engine.js.map +1 -1
- package/dist-server/index.js +21 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.d.ts +5 -0
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js +66 -0
- package/dist-server/migrations/1786600000000-RenameOperatoMesAdapterType.js.map +1 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.d.ts +5 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js +79 -0
- package/dist-server/migrations/1786700000000-AddDispatchRetryColumns.js.map +1 -0
- package/dist-server/migrations/index.js +5 -1
- package/dist-server/migrations/index.js.map +1 -1
- package/dist-server/routes.js +19 -16
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/actuation/actuation-advisor.d.ts +60 -0
- package/dist-server/service/actuation/actuation-advisor.js +53 -0
- package/dist-server/service/actuation/actuation-advisor.js.map +1 -0
- package/dist-server/service/actuation/actuation-outcome.d.ts +52 -0
- package/dist-server/service/actuation/actuation-outcome.js +34 -0
- package/dist-server/service/actuation/actuation-outcome.js.map +1 -0
- package/dist-server/service/actuation/actuation-rule-resolver.d.ts +19 -0
- package/dist-server/service/actuation/actuation-rule-resolver.js +161 -0
- package/dist-server/service/actuation/actuation-rule-resolver.js.map +1 -0
- package/dist-server/service/actuation/actuation-rule.d.ts +55 -0
- package/dist-server/service/actuation/actuation-rule.js +130 -0
- package/dist-server/service/actuation/actuation-rule.js.map +1 -0
- package/dist-server/service/actuation/approval-gateway.d.ts +20 -0
- package/dist-server/service/actuation/approval-gateway.js +14 -0
- package/dist-server/service/actuation/approval-gateway.js.map +1 -0
- package/dist-server/service/actuation/catch-up-effects.d.ts +16 -0
- package/dist-server/service/actuation/catch-up-effects.js +120 -0
- package/dist-server/service/actuation/catch-up-effects.js.map +1 -0
- package/dist-server/service/actuation/command-dispatcher.d.ts +230 -0
- package/dist-server/service/actuation/command-dispatcher.js +269 -0
- package/dist-server/service/actuation/command-dispatcher.js.map +1 -0
- package/dist-server/service/actuation/command-store.d.ts +11 -0
- package/dist-server/service/actuation/command-store.js +219 -0
- package/dist-server/service/actuation/command-store.js.map +1 -0
- package/dist-server/service/actuation/dispatch-after-approval.d.ts +11 -0
- package/dist-server/service/actuation/dispatch-after-approval.js +73 -0
- package/dist-server/service/actuation/dispatch-after-approval.js.map +1 -0
- package/dist-server/service/actuation/effect-match.d.ts +53 -0
- package/dist-server/service/actuation/effect-match.js +65 -0
- package/dist-server/service/actuation/effect-match.js.map +1 -0
- package/dist-server/service/actuation/index.d.ts +25 -0
- package/dist-server/service/actuation/index.js +30 -0
- package/dist-server/service/actuation/index.js.map +1 -0
- package/dist-server/service/actuation/retry-plan.d.ts +63 -0
- package/dist-server/service/actuation/retry-plan.js +99 -0
- package/dist-server/service/actuation/retry-plan.js.map +1 -0
- package/dist-server/service/actuation/rule-evaluate.d.ts +127 -0
- package/dist-server/service/actuation/rule-evaluate.js +205 -0
- package/dist-server/service/actuation/rule-evaluate.js.map +1 -0
- package/dist-server/service/actuation/rule-loop.d.ts +5 -0
- package/dist-server/service/actuation/rule-loop.js +156 -0
- package/dist-server/service/actuation/rule-loop.js.map +1 -0
- package/dist-server/service/actuation/rule-runner.d.ts +52 -0
- package/dist-server/service/actuation/rule-runner.js +135 -0
- package/dist-server/service/actuation/rule-runner.js.map +1 -0
- package/dist-server/service/actuation/rule-wiring.d.ts +24 -0
- package/dist-server/service/actuation/rule-wiring.js +80 -0
- package/dist-server/service/actuation/rule-wiring.js.map +1 -0
- package/dist-server/service/actuation/settle-effects.d.ts +21 -0
- package/dist-server/service/actuation/settle-effects.js +101 -0
- package/dist-server/service/actuation/settle-effects.js.map +1 -0
- package/dist-server/service/actuation/sweep-dispatch.d.ts +37 -0
- package/dist-server/service/actuation/sweep-dispatch.js +125 -0
- package/dist-server/service/actuation/sweep-dispatch.js.map +1 -0
- package/dist-server/service/actuation/twin-command-resolver.d.ts +120 -0
- package/dist-server/service/actuation/twin-command-resolver.js +406 -0
- package/dist-server/service/actuation/twin-command-resolver.js.map +1 -0
- package/dist-server/service/actuation/twin-command.d.ts +111 -0
- package/dist-server/service/actuation/twin-command.js +170 -0
- package/dist-server/service/actuation/twin-command.js.map +1 -0
- package/dist-server/service/actuation/twin-now.d.ts +41 -0
- package/dist-server/service/actuation/twin-now.js +65 -0
- package/dist-server/service/actuation/twin-now.js.map +1 -0
- package/dist-server/service/index.d.ts +5 -2
- package/dist-server/service/index.js +28 -17
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/actuation-routing.d.ts +60 -0
- package/dist-server/service/reference/actuation-routing.js +126 -0
- package/dist-server/service/reference/actuation-routing.js.map +1 -0
- package/dist-server/service/reference/actuation-target.d.ts +65 -0
- package/dist-server/service/reference/actuation-target.js +94 -0
- package/dist-server/service/reference/actuation-target.js.map +1 -0
- package/dist-server/service/reference/connection-portability-resolver.d.ts +29 -0
- package/dist-server/service/reference/connection-portability-resolver.js +181 -0
- package/dist-server/service/reference/connection-portability-resolver.js.map +1 -0
- package/dist-server/service/reference/connection-portability.d.ts +138 -0
- package/dist-server/service/reference/connection-portability.js +230 -0
- package/dist-server/service/reference/connection-portability.js.map +1 -0
- package/dist-server/service/reference/fill-cadence.d.ts +17 -0
- package/dist-server/service/reference/fill-cadence.js +31 -0
- package/dist-server/service/reference/fill-cadence.js.map +1 -0
- package/dist-server/service/reference/fill-dedupe.d.ts +16 -0
- package/dist-server/service/reference/fill-dedupe.js +63 -0
- package/dist-server/service/reference/fill-dedupe.js.map +1 -0
- package/dist-server/service/reference/fill-loop.d.ts +35 -0
- package/dist-server/service/reference/fill-loop.js +187 -0
- package/dist-server/service/reference/fill-loop.js.map +1 -0
- package/dist-server/service/reference/fill-span.d.ts +10 -0
- package/dist-server/service/reference/fill-span.js +37 -0
- package/dist-server/service/reference/fill-span.js.map +1 -0
- package/dist-server/service/reference/hook-contract.d.ts +149 -22
- package/dist-server/service/reference/hook-contract.js +236 -23
- package/dist-server/service/reference/hook-contract.js.map +1 -1
- package/dist-server/service/reference/hook-rejected.d.ts +25 -0
- package/dist-server/service/reference/hook-rejected.js +48 -0
- package/dist-server/service/reference/hook-rejected.js.map +1 -0
- package/dist-server/service/reference/hook-store.d.ts +3 -0
- package/dist-server/service/reference/hook-store.js +28 -0
- package/dist-server/service/reference/hook-store.js.map +1 -0
- package/dist-server/service/reference/index.d.ts +4 -1
- package/dist-server/service/reference/index.js +5 -1
- package/dist-server/service/reference/index.js.map +1 -1
- package/dist-server/service/reference/live-cadence.d.ts +68 -0
- package/dist-server/service/reference/live-cadence.js +44 -0
- package/dist-server/service/reference/live-cadence.js.map +1 -0
- package/dist-server/service/reference/live-feed-lease.d.ts +15 -0
- package/dist-server/service/reference/live-feed-lease.js +56 -0
- package/dist-server/service/reference/live-feed-lease.js.map +1 -0
- package/dist-server/service/reference/live-ingest.d.ts +21 -0
- package/dist-server/service/reference/live-ingest.js +66 -0
- package/dist-server/service/reference/live-ingest.js.map +1 -0
- package/dist-server/service/reference/reference-adapter.d.ts +355 -2
- package/dist-server/service/reference/reference-adapter.js +19 -1
- package/dist-server/service/reference/reference-adapter.js.map +1 -1
- package/dist-server/service/reference/reference-fill-run.d.ts +50 -0
- package/dist-server/service/reference/reference-fill-run.js +142 -0
- package/dist-server/service/reference/reference-fill-run.js.map +1 -0
- package/dist-server/service/reference/reference-fill.d.ts +90 -0
- package/dist-server/service/reference/reference-fill.js +141 -0
- package/dist-server/service/reference/reference-fill.js.map +1 -0
- package/dist-server/service/reference/reference-hook.d.ts +64 -6
- package/dist-server/service/reference/reference-hook.js +265 -27
- package/dist-server/service/reference/reference-hook.js.map +1 -1
- package/dist-server/service/reference/reference-link-groups.d.ts +10 -0
- package/dist-server/service/reference/reference-link-groups.js +15 -0
- package/dist-server/service/reference/reference-link-groups.js.map +1 -0
- package/dist-server/service/reference/reference-links.d.ts +14 -0
- package/dist-server/service/reference/reference-links.js +73 -0
- package/dist-server/service/reference/reference-links.js.map +1 -0
- package/dist-server/service/reference/reference-live.d.ts +1 -0
- package/dist-server/service/reference/reference-live.js +32 -6
- package/dist-server/service/reference/reference-live.js.map +1 -1
- package/dist-server/service/reference/reference-master.d.ts +56 -2
- package/dist-server/service/reference/reference-master.js +33 -3
- package/dist-server/service/reference/reference-master.js.map +1 -1
- package/dist-server/service/reference/reference-resolver.d.ts +27 -0
- package/dist-server/service/reference/reference-resolver.js +79 -1
- package/dist-server/service/reference/reference-resolver.js.map +1 -1
- package/dist-server/service/twin-event/twin-event-keys.d.ts +31 -3
- package/dist-server/service/twin-event/twin-event-keys.js +36 -4
- package/dist-server/service/twin-event/twin-event-keys.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 +11 -2
- package/dist-server/service/twin-event/twin-event.js.map +1 -1
- package/dist-server/service/twin-model/choose-recipe.d.ts +15 -0
- package/dist-server/service/twin-model/choose-recipe.js +33 -0
- package/dist-server/service/twin-model/choose-recipe.js.map +1 -0
- package/dist-server/service/twin-model/external-resolver.d.ts +76 -0
- package/dist-server/service/twin-model/external-resolver.js +109 -0
- package/dist-server/service/twin-model/external-resolver.js.map +1 -0
- package/dist-server/service/twin-model/project-structure.js +16 -3
- package/dist-server/service/twin-model/project-structure.js.map +1 -1
- package/dist-server/service/twin-model/twin-equipment.d.ts +17 -0
- package/dist-server/service/twin-model/twin-equipment.js +10 -0
- package/dist-server/service/twin-model/twin-equipment.js.map +1 -1
- package/dist-server/service/twin-model/twin-lineage-query.js +75 -1
- package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-item-query.js +94 -5
- package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -1
- package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -1
- package/dist-server/service/twin-space/twin-space.d.ts +29 -0
- package/dist-server/service/twin-space/twin-space.js +13 -0
- package/dist-server/service/twin-space/twin-space.js.map +1 -1
- package/dist-server/service/twin-subject/event-subjects.d.ts +3 -1
- package/dist-server/service/twin-subject/event-subjects.js +8 -1
- package/dist-server/service/twin-subject/event-subjects.js.map +1 -1
- package/dist-shared/entity-delta.js +1 -1
- package/dist-shared/entity-delta.js.map +1 -1
- package/package.json +7 -7
- package/server/engine/canonical-ingest.ts +119 -33
- package/server/engine/event-time.ts +96 -0
- package/server/engine/index.ts +20 -0
- package/server/engine/ingest-dedupe.ts +203 -27
- package/server/engine/ingest-health.ts +91 -6
- package/server/engine/kpi-fold.ts +24 -1
- package/server/engine/kpi-query.ts +23 -4
- package/server/engine/oee-accumulator.ts +80 -8
- package/server/engine/twin-engine.ts +119 -5
- package/server/index.ts +23 -0
- package/server/migrations/1786600000000-RenameOperatoMesAdapterType.ts +66 -0
- package/server/migrations/1786700000000-AddDispatchRetryColumns.ts +82 -0
- package/server/migrations/index.ts +5 -1
- package/server/routes.ts +19 -20
- package/server/service/actuation/actuation-advisor.ts +124 -0
- package/server/service/actuation/actuation-outcome.ts +97 -0
- package/server/service/actuation/actuation-rule-resolver.ts +147 -0
- package/server/service/actuation/actuation-rule.ts +139 -0
- package/server/service/actuation/approval-gateway.ts +44 -0
- package/server/service/actuation/catch-up-effects.ts +152 -0
- package/server/service/actuation/command-dispatcher.ts +511 -0
- package/server/service/actuation/command-store.ts +236 -0
- package/server/service/actuation/dispatch-after-approval.ts +71 -0
- package/server/service/actuation/effect-match.ts +124 -0
- package/server/service/actuation/index.ts +27 -0
- package/server/service/actuation/retry-plan.ts +145 -0
- package/server/service/actuation/rule-evaluate.ts +352 -0
- package/server/service/actuation/rule-loop.ts +160 -0
- package/server/service/actuation/rule-runner.ts +216 -0
- package/server/service/actuation/rule-wiring.ts +84 -0
- package/server/service/actuation/settle-effects.ts +115 -0
- package/server/service/actuation/sweep-dispatch.ts +179 -0
- package/server/service/actuation/twin-command-resolver.ts +387 -0
- package/server/service/actuation/twin-command.ts +232 -0
- package/server/service/actuation/twin-now.ts +97 -0
- package/server/service/index.ts +11 -0
- package/server/service/reference/actuation-routing.ts +165 -0
- package/server/service/reference/actuation-target.ts +163 -0
- package/server/service/reference/connection-portability-resolver.ts +171 -0
- package/server/service/reference/connection-portability.ts +285 -0
- package/server/service/reference/fill-cadence.ts +29 -0
- package/server/service/reference/fill-dedupe.ts +66 -0
- package/server/service/reference/fill-loop.ts +153 -0
- package/server/service/reference/fill-span.ts +31 -0
- package/server/service/reference/hook-contract.ts +280 -22
- package/server/service/reference/hook-rejected.ts +53 -0
- package/server/service/reference/hook-store.ts +28 -0
- package/server/service/reference/index.ts +5 -1
- package/server/service/reference/live-cadence.ts +129 -0
- package/server/service/reference/live-feed-lease.ts +56 -0
- package/server/service/reference/live-ingest.ts +94 -0
- package/server/service/reference/reference-adapter.ts +392 -5
- package/server/service/reference/reference-fill-run.ts +165 -0
- package/server/service/reference/reference-fill.ts +223 -0
- package/server/service/reference/reference-hook.ts +355 -32
- package/server/service/reference/reference-link-groups.ts +21 -0
- package/server/service/reference/reference-links.ts +77 -0
- package/server/service/reference/reference-live.ts +30 -5
- package/server/service/reference/reference-master.ts +90 -5
- package/server/service/reference/reference-resolver.ts +77 -2
- package/server/service/twin-event/twin-event-keys.ts +37 -4
- package/server/service/twin-event/twin-event.ts +18 -1
- package/server/service/twin-model/choose-recipe.ts +31 -0
- package/server/service/twin-model/external-resolver.ts +161 -0
- package/server/service/twin-model/project-structure.ts +16 -3
- package/server/service/twin-model/twin-equipment.ts +22 -0
- package/server/service/twin-model/twin-lineage-query.ts +82 -1
- package/server/service/twin-model/twin-model-item-query.ts +95 -4
- package/server/service/twin-model/twin-model-tree-query.ts +1 -1
- package/server/service/twin-space/twin-space.ts +39 -0
- package/server/service/twin-subject/event-subjects.ts +8 -1
- package/shared/entity-delta.ts +1 -1
- package/test/ack-shape-alignment.test.ts +97 -0
- package/test/actuation-approval-door.test.ts +421 -0
- package/test/actuation-dispatch.test.ts +209 -0
- package/test/actuation-effect.test.ts +162 -0
- package/test/actuation-outcome.test.ts +152 -0
- package/test/actuation-rule-runner.test.ts +281 -0
- package/test/actuation-rule.test.ts +266 -0
- package/test/actuation-seam.test.ts +249 -0
- package/test/actuation-settle.test.ts +164 -0
- package/test/actuation-target.test.ts +145 -0
- package/test/canonical-ingest-vocabularies.test.ts +49 -2
- package/test/capability-mapping.test.ts +1 -1
- package/test/choose-recipe.test.ts +117 -0
- package/test/command-store-writes-columns.test.ts +126 -0
- package/test/connection-portability-doors.test.ts +87 -0
- package/test/connector-capability-declaration.test.ts +54 -4
- package/test/declaration-reaches-model.test.ts +43 -0
- package/test/dedupe-transformation.test.ts +112 -0
- package/test/entity-delta.test.ts +1 -1
- package/test/event-subjects.test.ts +2 -1
- package/test/external-resolver.test.ts +171 -0
- package/test/fill-dedupe.test.ts +59 -0
- package/test/fill-loop.test.ts +35 -0
- package/test/first-envelope.test.ts +153 -0
- package/test/fold-shift-dst.test.ts +110 -0
- package/test/home-in-area.test.ts +90 -0
- package/test/hook-rejected-shape.test.ts +86 -0
- package/test/hook-response-sum.test.ts +193 -0
- package/test/hook-sequence.test.ts +333 -0
- package/test/ingest-dedupe.test.ts +56 -0
- package/test/ingest-expected-quiet.test.ts +111 -0
- package/test/ingest-idempotent.test.ts +79 -0
- package/test/ingest-reconcile-four-ways.test.ts +97 -0
- package/test/ingest-rules-header.test.ts +100 -0
- package/test/ingest-window-rolls-unobserved.test.ts +72 -0
- package/test/intake-mapping-parity.test.ts +175 -0
- package/test/live-cadence.test.ts +170 -0
- package/test/live-feed-lease.test.ts +63 -0
- package/test/live-mirror-parity.test.ts +1 -1
- package/test/oee-accumulator.test.ts +3 -3
- package/test/oee-site-calendar.test.ts +146 -0
- package/test/order-and-transaction-split.test.ts +107 -0
- package/test/reference-fill.test.ts +235 -0
- package/test/reference-hook.test.ts +114 -23
- package/test/reference-links.test.ts +56 -0
- package/test/retry-plan.test.ts +139 -0
- package/test/sweep-dispatch.test.ts +191 -0
- package/test/twin-event-keys.test.ts +20 -6
- package/test/twin-model-item-db.test.ts +6 -6
- package/test/twin-model-tree-db.test.ts +6 -6
- package/tsconfig.shared.tsbuildinfo +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twin-event-keys.js","sourceRoot":"","sources":["../../../server/service/twin-event/twin-event-keys.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"twin-event-keys.js","sourceRoot":"","sources":["../../../server/service/twin-event/twin-event-keys.ts"],"names":[],"mappings":"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","sourcesContent":["import { twinWarn } from '../../engine/log.js'\n/*\n * ์ ๋ ๊ฒ์ ํค ์ถ์ถ โ **์์**. ์ธ์ ์คํธ๊ฐ ๊ธฐ๋กํ ๋ ํ ๋ฒ ๋ฝ์ ์ธ๋ฑ์ค ๊ฐ๋ฅํ ์ค์ปฌ๋ผ์ผ๋ก ์น๊ฒฉํ๋ค.\n *\n * โโ ์ ์น๊ฒฉํ๋๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ์ฉ์๊ฐ ์ ๋์์ ์ค์ ๋ก ์ฐพ๋ ๊ฒ์ \"์ด ํ๋ ํธ์ ์ด๋ ฅ\", \"์ด ์ค๋๊ฐ ์ด๋๊น์ง ๊ฐ๋\", \"์ด ๋ํฌ์์\n * ๋ฌด์จ ์ผ์ด ์์๋\" ๋ค. ๊ทธ๋ฐ๋ฐ ๊ทธ ๊ฐ๋ค์ ์ ๋ถ `payload`(simple-json = TEXT) **์**์ ์์๋ค.\n * things-factory ๋ 5๊ฐ DB ๋๋ผ์ด๋ฒ๋ฅผ ์ง์ํด์ผ ํด์ DB๋ณ JSON ์ฐ์ฐ์๋ฅผ ์ธ ์ ์๋ค โ\n * ์ฆ ์น๊ฒฉ ์์ด๋ **์ด๋ค ๋ฐฉ๋ฒ์ผ๋ก๋ ์๋ฒ์์ ๊ทธ ์กฐ๊ฑด์ผ๋ก ๊ฑฐ๋ฅผ ์ ์์๋ค**. ํด๋ผ์ด์ธํธ๊ฐ ๋ฐ์์จ\n * ๋ช ์ฒ ๊ฑด ์์์๋ง ์ฐพ๋ ์๋์ด ์ต์ ์ด์๊ณ , ์ ๋์ด ์ปค์ง์๋ก ๊ทธ ์๋์ ๊ฑฐ์ง๋ง์ ๊ฐ๊น์์ง๋ค.\n *\n * ๊ทธ๋์ ๊ฒ์ ์ถ์ด ๋๋ ๊ฐ๋ง ๊ณจ๋ผ ์ปฌ๋ผ์ผ๋ก ๊บผ๋ธ๋ค. payload ๋ ๊ทธ๋๋ก ๋๋ค(์ ๋ณธ์ ์ฌ์ ํ payload โ\n * ์ด๊ฑด ํ์ ์์ธ์ด์ง ์๋ก์ด ์ง์ค์ด ์๋๋ค).\n *\n * โโ ์ ์ฌ๊ธฐ(์์ ๋ชจ๋)์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ธฐ๋ก ๊ฒฝ๋ก๊ฐ ๋์ด๋ค(`persistBatch` ๋ผ์ด๋ธ ๋ฒํฌ ยท `persist` ์ฌ ๋จ๊ฑด). ๋ ๊ณณ์ ๊ฐ์ ์ ์ผ๋ฉด\n * ๋ฐ๋์ ์ด๊ธ๋๊ณ , ์ด๊ธ๋ ์์ธ์ \"์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ์ด๋ฒคํธ\" ๋ฅผ ๋ง๋ ๋ค โ ์ ๋์์ ๊ฐ์ฅ ๋์ ๊ฒฐํจ์ด๋ค.\n */\n\n/** ์น๊ฒฉ๋ ๊ฒ์ ํค โ ์ ๋ถ ์ ํ์ . ๋ฝํ์ง ์์ผ๋ฉด **๋น ๋ฌธ์์ด์ด ์๋๋ผ undefined**(๊ฒฐ์ธกโ ๋น๊ฐ). */\nexport interface TwinEventKeys {\n action?: string\n bizStep?: string\n epc?: string\n orderId?: string\n bizTransaction?: string\n locationId?: string\n moverId?: string\n}\n\n/*\n * ์ปฌ๋ผ ๊ธธ์ด ์ํ. GS1 ์๋ณ์(EPC URNยทGDTIยทSGLN)๋ ๊ท๊ฒฉ์ ์ด๋ณด๋ค ํจ์ฌ ์งง๋ค.\n * ๋์น๋ ๊ฐ์ด ์ค๋ฉด **์๋ฆฌ์ง ์๊ณ ์๋ฅด์ง ์๊ณ ** ๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค โ ์์ธ์ด ์๋ณธ๊ณผ ๋ค๋ฅด๋ฉด ๊ฒ์ ๊ฒฐ๊ณผ๊ฐ ๊ฑฐ์ง์ด ๋๋๋ฐ,\n * ๊ทธ ์ฌ์ค์ด ์ด๋์๋ ์ ๋จ์ผ๋ฉด ์๋ฌด๋ ๋ชจ๋ฅธ๋ค.\n */\nconst MAX_KEY = 255\n\nfunction clip(v: unknown, field: string): string | undefined {\n if (v === undefined || v === null) return undefined\n const s = String(v)\n if (!s) return undefined\n if (s.length <= MAX_KEY) return s\n twinWarn(\n `[twin-event-keys] ${field} exceeds ${MAX_KEY} chars and was clipped for indexing โ ` +\n `search on this value may be incomplete. payload keeps the full value. (${s.slice(0, 60)}โฆ)`\n )\n return s.slice(0, MAX_KEY)\n}\n\n/** CBV bizStep URN ์ ๋๋ง๋. ์์ผ๋ฉด ์ด๋ฒคํธ ํ์
์์ ์ ์ถ(`epcis.` ์ ๋ ์ ๊ฑฐ). */\nexport function bizStepOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n const tail = String(d.bizStep ?? '').split(':').pop()\n return tail || String(envelope?.eventType ?? '').replace('epcis.', '') || undefined\n}\n\n/**\n * ํ๋ชฉ ์๋ณ์ โ **์ ์ฒด ๊ฐ**์ ์ ์ฅํ๋ค(๋๋ง๋๋ง ์ ์ฅํ์ง ์๋๋ค).\n *\n * ํ์์ฉ ์ถ์ฝ์ ํ๋ฉด์ด ํ๊ณ , ์์ธ์ ์๋ณธ์ ๊ฐ๋๋ค. `search` ๋ ๋ถ๋ถ์ผ์น(contains)๋ผ\n * ์ ์ฒด๋ฅผ ์ ์ฅํด ๋๋ฉด ๋๋ง๋(\"402.2\")๋ก๋ URN ์ ์ฒด๋ก๋ ์ฐพํ๋ค. ๋ฐ๋๋ก ๋๋ง๋๋ง ์ ์ฅํ๋ฉด\n * URN ์ผ๋ก ์ฐพ๋ ๊ฒฝ๋ก๊ฐ ์ฌ๋ผ์ง๋ค.\n */\nexport function epcOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n return d.epcList?.[0] ?? d.parentID ?? d.quantityList?.[0]?.epcClass ?? undefined\n}\n\n/**\n * ์ค๋ ์๋ณ์ โ ์ด์ ๋ธํ์ `orderId` ์ฐ์ , EPCIS ๋ `bizTransactionList`.\n *\n * โโ ์ค์ธก (2026-08-24) โ ์ด ์ปฌ๋ผ์ด **์ ๋ถ ๋น์ด ์์๋ค** โโโโโโโโโโโโโโโโโโโโโโ\n * ์ฌ๊ธฐ๊ฐ ์ฐพ๋ ์ด๋ฆ์ด `d.order` ์๋ค. ๊ทธ๋ฐ๋ฐ ์ปค๋์ด ๋ด๋ ์ด๋ฆ์ **`orderId`** ๋ค\n * (`OrderStatusDelta.orderId` ยท `TaskStatusDelta.orderId`). `d.order` ๋ฅผ ๋ด๋ ์ฝ๋๋ ์ปค๋์ **ํ ๊ณณ๋\n * ์๋ค** โ ์ฃฝ์ ๊ฐ์ง์๋ค. ๊ทธ๋์ ์ด์ ๋ธํ๋ ์ด ์ปฌ๋ผ์ ํ ๋ฒ๋ ์ฑ์ฐ์ง ๋ชปํ๋ค.\n *\n * order.status 29,403,565 ํ โ order_id ๋น์ด ์์ 29,403,565 (100%)\n * task.status 191,175 ํ โ ๋น์ด ์์ 191,175 (100%)\n *\n * ๊ทธ ๊ฒฐ๊ณผ ์์ธ `ix_twin_event_4` ๊ฐ **์๊ธฐ ์ฃผ์์ด ์ ์ด ๋ ์ฉ๋**(ใ์ด ์ค๋๊ฐ ์ด๋๊น์ง ๊ฐ๋ใ)๋ก ์ธ ์\n * ์์๋ค. ํ๋ฉด์ ์ค๋๋ฅผ ๋๋ฌ๋ ใ์ฐ๊ฒฐ๋ ์ด๋ฒคํธ๊ฐ ์์ต๋๋คใ๋ฅผ ๋๊ณ , ๊ทธ ๋ต์ ์ง์ ๊ฒฐ๊ณผ๋ก๋ ์ ์งํ๋ค โ\n * ์์ ์ ์ด๋๋ก ์ฎ๊ฒจ๋ 0 ์ด์๋ค.\n *\n * **๊ณผ๊ฑฐ ํ์ ์ฑ์์ง์ง ์๋๋ค**(์ฌ์ฉ์ ๊ฒฐ์ 2026-08-24, `moverId` ๋์ ๊ฐ์ ๋ฐฉ์). ์์ผ๋ก ๋ค์ด์ค๋\n * ์ฌ๊ฑด๋ถํฐ ์กฐํ๋๋ค.\n *\n * โโ ํ ์นธ์ ๋ ๋ฑ๋ง์ด ๋ค์ด ์์๋ค (2026-09-05 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ์ฃผ์์ด ์ด๋ฏธ ์๊ณ ์์๋ค โ ใEPCIS ์ `bizTransactionList` ๋ **๊ฑฐ๋**(PO/SO)์ด๊ณ ์ค๋์ ๊ฐ์\n * ๊ฒ์ด ์๋ ์ ์๋คใ. ๊ทธ๋ฐ๋ฐ ๊ทธ ๋์ **๊ฐ์ ์นธ์** ๋ฃ๊ณ ์์๋ค. ๊ทธ๋์ ์ด๋ ๊ฒ ๋๋ค.\n *\n * order.status order-1 ๋ด๋ถ ์ค๋ id\n * epcis.TransformationEvent urn:epc:id:gdti:9521321.403.1 GS1 ๊ฑฐ๋ ์๋ณ์\n * epcis.TransactionEvent urn:epc:id:gdti:9521321.403.1\n *\n * ํ ์ค๋์ ์ด๋ ฅ์ด **์์ธ ์์์ ๋ ์ชฝ์ผ๋ก ๊ฐ๋ผ์ง๋ค.** ์ด๋ ์ด๋ฆ์ผ๋ก ๋ฌผ์ด๋ ์ ๋ฐ๋ง ๋์ค๊ณ ,\n * ์ค๋ฅ๋ ๋์ง ์๋๋ค. ์ค์ธก: ์ดํ๊ฐ ์์ธ ํ 10,004๊ฐ.\n *\n * ์ด๊ฒ์ด ์ค์ ๋ก ๋ง์ ๊ฒ โ ใ์ด ๊ฐ์ฒด๋ฅผ ์ด๋ ๋ ์ํผ๋ก ๋ง๋ค์๋ใ๋ค. ๋ต์ ๊ธฐ๋ก๋์ด ์๋ค(์ค๋ ์ฌ๊ฑด์ด\n * `recipeKey` ๋ฅผ ๋ ๋ค, ์ค์ธก 328,021/328,021 = 100%). ๋ณํ ์ฌ๊ฑด์ ๊ทธ ์ค๋๋ฅผ GDTI ๋ก ๊ฐ๋ฆฌํค๋๋ฐ\n * ์ค๋ ์ฌ๊ฑด์ `order-1` ๋ก ์ ํ ์์ด **์์ธ์ผ๋ก ์ด์ ์๊ฐ ์์๋ค.**\n *\n * ๊ทธ๋์ ์นธ์ ๊ฐ๋๋ค(์ฌ์ฉ์ ๊ฒฐ์ 2026-09-05).\n *\n * orderId ๋ด๋ถ ์ค๋ id โ ์ฝ๊ธฐ ๋ชจ๋ธ์ ์ด์์ \n * bizTransaction GS1 ๊ฑฐ๋ ์๋ณ์ โ ํ์ค์ด ๋งํ๋ ๊ทธ ๊ฑฐ๋\n *\n * ์ค๋ ์ฌ๊ฑด์ **๋ ๋ค** ๋ ๋ค(`order.status` ์ payload ์ `orderId` ์ `bizTransaction` ์ด ํจ๊ป\n * ์๋ค). ๊ทธ๋์ EPCIS ์ฌ๊ฑด์ ๊ฑฐ๋ ์๋ณ์๋ก ์ค๋๋ฅผ ์ฐพ์ ์ ์๋ค โ ์ด ๋ ์นธ์ด ๊ทธ ๋ค๋ฆฌ๋ค.\n */\nexport function orderOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n return d.orderId ?? undefined\n}\n\n/**\n * **๊ทธ ์ฌ๊ฑด์ด ๊ฐ๋ฆฌํค๋ ๊ฑฐ๋** โ EPCIS `bizTransactionList` ์ ์ฒซ ํญ๋ชฉ, ๋๋ ์ด์ ๋ธํ๊ฐ ์ง์ ๋ ๊ฐ.\n *\n * ์ค๋๊ฐ ์๋๋ค. ํ์ค์ด ๋งํ๋ ๊ฑฐ๋(PO/SO/์์ฐ์ค๋)์ด๊ณ , ํ ์ค๋๊ฐ ์ฌ๋ฌ ๊ฑฐ๋์ ๊ฑธ๋ฆด ์๋ ์๋ค.\n * ๊ทธ ๊ตฌ๋ณ์ ์งํค๋ ค๊ณ `orderId` ์ ๊ฐ๋ผ ๋์๋ค โ ํฉ์น๋ฉด ์ ์ฃผ์์ ๊ทธ ์ผ์ด ๋ค์ ๋๋ค.\n */\nexport function bizTransactionOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n return d.bizTransactionList?.[0]?.bizTransaction ?? d.bizTransaction ?? undefined\n}\n\n/**\n * ์์น โ EPCIS ๋ ์ฝ์ ์ง์ (readPoint) ์ฐ์ , ์์ผ๋ฉด ์
๋ฌด ์์น(bizLocation).\n * ์ด์ ๋ธํ(๋ฌด๋ฒ ์ด๋ ๋ฑ)๋ ๊ทธ ๋์ด ์๊ณ ํ๋ฒํ `location` ์ ์ด๋ค โ ๋น ๋จ๋ฆฌ๋ฉด ์ค๋น๊ฐ ์ด๋์\n * ๋ฌด์์ ํ๋์ง๊ฐ ์์น ์ถ์์ ํต์งธ๋ก ์ฌ๋ผ์ง๋ค.\n */\nexport function locationOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n return d.readPoint?.id ?? d.bizLocation?.id ?? d.location ?? undefined\n}\n\n/**\n * ์ค๋นยท๋ฌด๋ฒ โ ์ด์ ๋ธํ(equipment.statusยทtask.status)๊ฐ ๋์์ ๊ฐ๋ฆฌํค๋ ์ถ.\n *\n * EPCIS ์ดํ๊ฐ ์๋๋ผ์ ๋ค๋ฅธ ์ถ ์ด๋์๋ ์ ์กํ๋ค. ์ด๊ฒ ์์ผ๋ฉด \"์ด ์ง๊ฒ์ฐจ๊ฐ ์ค๋ ๋ฌด์์ ํ๋\" ๋ฅผ\n * ์๋ฒ์์ ๋ฌผ์ ๋ฐฉ๋ฒ์ด ์์ด, ํ๋ฉด์ด ์ ๋์ ํต์งธ๋ก ๋ฐ์ ์ ์ ์กฐํํ๋ ์๋ฐ์ ์๋ค.\n */\nexport function equipmentIdOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n /*\n * โโ ์ค์ธก (2026-08-24) โ ๋ ๊ฐ๋๋ฅผ ๋์น๊ณ ์์๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ์ฃผ์์ด `task.status` ๋ฅผ ์ถ์ฒ๋ก **์ ์ด ๋์๋๋ฐ** ์ด ํจ์๋ `d.moverId` ๋ง ๋ดค๋ค. ์์
์ด ์์์\n * ๊ฐ๋ฆฌํค๋ ์ด๋ฆ์ `resourceRef` ๋ค(`TaskStatusDelta.resourceRef`) โ ๊ทธ๋์ ์์
191,175 ํ ์ ๋ถ\n * ์ด ์ปฌ๋ผ์ด ๋น์๊ณ , ใ์ด ์ง๊ฒ์ฐจ๊ฐ ์ค๋ ๋ฌด์์ ํ๋ใ์์ **์์
์ด ํต์งธ๋ก ๋น ์ก๋ค.**\n *\n * ๊ทธ๋ฆฌ๊ณ ์๋์ง ์ฌ๊ฑด์ `equipmentId` ๋ฅผ ์ด๋ค(์ดํ๊ฐ `movers`โ`equipment` ๋ก ๊ฐ๋ช
๋ ๋ค์ ์๊ธด\n * ์ฑ๋์ด๋ค). ์ค์ธก `energy.equipment` 31,079 ํ ์ ๋ถ ๋น์ด ์์๋ค โ ใ์ด ์ค๋น๊ฐ ์ผ๋ง๋ฅผ ๋จน์๋ใ๋ฅผ\n * ์ค๋น ์ถ์ผ๋ก ๋ฌผ์ ์ ์์๋ค.\n *\n * ์
์ ํจ๊ป ๋ณธ๋ค. ๊ฐ๋ช
์ธ๋๊ฐ ์์ฌ ์๋ ๊ฒ์ ์ ๋์ ์ฑ์ง์ด๊ณ , ์ฝ๋ ์ชฝ์ด ๊ทธ๊ฒ์ ํก์ํ๋ค.\n */\n return d.moverId ?? d.resourceRef ?? d.equipmentId ?? undefined\n}\n\n/**\n * EPCIS ํ์ โ `ADD`ยท`OBSERVE`ยท`DELETE`. ์ธ ๊ฐ์ด ์๋๋ฉด `undefined`(์์ฒ์ ์ก๊ฐ์ ์์ธ์ ๋ฃ์ง ์๋๋ค).\n *\n * ์ด ํค๋ ๊ฒ์ ์ถ์ด ์๋๋ผ **ํ๋ณ์**์ด๋ค: ๋ํ์ด ์ฝ๋ ์ค๋
์ท์ ์๋ฆฌ์ ์ผ๋ก `DELETE` ๋ฅผ ๋ชป ๋ธ๋ค.\n * ๊ทธ๋์ ใ์ด ํธ์์ด ๋ฐ์ถ์ ํ ๋ฒ์ด๋ผ๋ ๊ณ์ฐํ๋๊ฐใ๊ฐ ์ง์ง delta ํผ๋์ ์ฆ๊ฑฐ์ธ๋ฐ, payload ์์ ์๋\n * ๋์์๋ 5๊ฐ ๋๋ผ์ด๋ฒ ์ด๋์์๋ ๊ทธ ์ง๋ฌธ์ ํ ์ ์์๋ค. ์ด์ ๋ธํ์๋ ํ์๊ฐ ์๋ค โ ๋น์ด๋ค.\n */\nexport function actionOf(envelope: any): string | undefined {\n const a = (envelope?.data ?? envelope ?? {}).action\n return a === 'ADD' || a === 'OBSERVE' || a === 'DELETE' ? a : undefined\n}\n\n/** ํ ์ด๋ฒคํธ์์ ์น๊ฒฉ ํค ์ ๋ถ โ ๊ธฐ๋ก ๊ฒฝ๋ก๊ฐ ์ด ํจ์ ํ๋๋ง ๋ถ๋ฅธ๋ค. */\nexport function twinEventKeys(envelope: any): TwinEventKeys {\n return {\n action: actionOf(envelope),\n bizStep: clip(bizStepOf(envelope), 'bizStep'),\n epc: clip(epcOf(envelope), 'epc'),\n orderId: clip(orderOf(envelope), 'orderId'),\n bizTransaction: clip(bizTransactionOf(envelope), 'bizTransaction'),\n locationId: clip(locationOf(envelope), 'locationId'),\n moverId: clip(equipmentIdOf(envelope), 'moverId')\n }\n}\n"]}
|
|
@@ -22,6 +22,7 @@ const shell_1 = require("@things-factory/shell");
|
|
|
22
22
|
* ix_2 (domain, instanceId, eventType, revision) ํ์
ํํฐ + ์ ๋ ฌ ๋์ ์ถฉ์กฑ(์ค์ผ์ค ํ๋ฉด task/equipment)
|
|
23
23
|
* ix_3 (domain, instanceId, epc) "์ด ๋ฌผ๊ฑด์ ์ด๋ ฅ" โ Entity360 ์ ๋ณธ์ง ์ง๋ฌธ
|
|
24
24
|
* ix_4 (domain, instanceId, orderId) "์ด ์ค๋๊ฐ ์ด๋๊น์ง ๊ฐ๋"
|
|
25
|
+
* ix_9 (domain, instanceId, bizTransaction) "์ด ๊ฑฐ๋์ ๋ฌด์จ ์ผ์ด ์์๋" โ EPCISโ์ค๋์ ๋ค๋ฆฌ
|
|
25
26
|
*
|
|
26
27
|
* bizStepยทlocationIdยทmoverId ๋ ์ปฌ๋ผ๋ง ๋๊ณ ์ธ๋ฑ์ค๋ ๋์ง ์๋๋ค โ ํ ํธ์ ์์์ ์นด๋๋๋ฆฌํฐ๊ฐ
|
|
27
28
|
* ๋ฎ์(์
๋ฌด๋จ๊ณ ๋ช ๊ฐ, ์์น ์๋ฐฑ, ์ค๋น ์์ญ) (domain,instanceId) ๋ก ์ด๋ฏธ ์ขํ์ง ๋ค์ ์์ฌ ํํฐ๋ก
|
|
@@ -121,9 +122,14 @@ tslib_1.__decorate([
|
|
|
121
122
|
], TwinEvent.prototype, "epc", void 0);
|
|
122
123
|
tslib_1.__decorate([
|
|
123
124
|
(0, typeorm_1.Column)({ length: 255, nullable: true }),
|
|
124
|
-
(0, type_graphql_1.Field)({ nullable: true, description: '
|
|
125
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Internal order identifier, promoted from the payload for indexed lookup of one order history.' }),
|
|
125
126
|
tslib_1.__metadata("design:type", String)
|
|
126
127
|
], TwinEvent.prototype, "orderId", void 0);
|
|
128
|
+
tslib_1.__decorate([
|
|
129
|
+
(0, typeorm_1.Column)({ length: 255, nullable: true }),
|
|
130
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Business transaction identifier (PO / SO / production order), promoted from the payload for indexed lookup of one transaction.' }),
|
|
131
|
+
tslib_1.__metadata("design:type", String)
|
|
132
|
+
], TwinEvent.prototype, "bizTransaction", void 0);
|
|
127
133
|
tslib_1.__decorate([
|
|
128
134
|
(0, typeorm_1.Column)({ length: 255, nullable: true }),
|
|
129
135
|
(0, type_graphql_1.Field)({ nullable: true, description: 'Location identifier (read point, business location, or the plain location an operational delta carries), promoted from the payload for indexed filtering.' }),
|
|
@@ -184,7 +190,10 @@ exports.TwinEvent = TwinEvent = tslib_1.__decorate([
|
|
|
184
190
|
* ์ ๋ฆฌ๋ ํ ์ฐฝ์ 2์ด๋ง ์ฐ๋๋ก ์์ฐ์ด ๊ฑธ๋ ค ์์ด์, ๊ทธ 2์ด๋ฅผ ์ฃผ์ฌ์ ๋ค ์ฐ๊ณ 44๊ฑด๋ง ์ง์ฐ๊ณ ๋ฉ์ท๋ค.
|
|
185
191
|
*/
|
|
186
192
|
,
|
|
187
|
-
(0, typeorm_1.Index)('ix_twin_event_8', (e) => [e.domain, e.instanceId, e.createdAt], { unique: false })
|
|
193
|
+
(0, typeorm_1.Index)('ix_twin_event_8', (e) => [e.domain, e.instanceId, e.createdAt], { unique: false })
|
|
194
|
+
/* ix_9 โ "์ด ๊ฑฐ๋์ ๋ฌด์จ ์ผ์ด ์์๋". EPCIS ์ฌ๊ฑด์์ ์ค๋๋ก ๊ฑด๋๊ฐ๋ ๋ค๋ฆฌ(ยง`bizTransaction`). */
|
|
195
|
+
,
|
|
196
|
+
(0, typeorm_1.Index)('ix_twin_event_9', (e) => [e.domain, e.instanceId, e.bizTransaction], { unique: false }),
|
|
188
197
|
(0, type_graphql_1.ObjectType)({ description: 'Append-only twin event journal record (EPCIS event or operational delta).' })
|
|
189
198
|
], TwinEvent);
|
|
190
199
|
//# sourceMappingURL=twin-event.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twin-event.js","sourceRoot":"","sources":["../../../server/service/twin-event/twin-event.ts"],"names":[],"mappings":";;;;AAAA,qCAAgH;AAChH,+CAAyD;AAEzD,iDAA4D;AAE5D;;;;;;GAMG;AACH;;;;;;;;;;;;;;;GAeG;AAsCI,IAAM,SAAS,GAAf,MAAM,SAAS;CAiIrB,CAAA;AAjIY,8BAAS;AAGX;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;qCAC1D;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uBAAuB,EAAE,CAAC;sCACvE,cAAM;yCAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;;2CACtB;AASjB;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;;6CACzD;AAKlB;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,sEAAsE,EAAE,CAAC;;4CAC9E;AAIjB;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;;2CAC/F;AAcjB;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2KAA2K,EAAE,CAAC;;+CAC5M;AAqBrB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC;sCACjF,IAAI;IAEhB;;;;;;;;;;;;;;;;;;OAkBG;IACH;;;;;;;;OAQG;;4CA7Ba;AAgChB;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kKAAkK,EAAE,CAAC;;gDACrL;AAKtB;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACtC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oJAAoJ,EAAE,CAAC;;yCAC9K;AAIf;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oFAAoF,EAAE,CAAC;;0CAC7G;AAIhB;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kHAAkH,EAAE,CAAC;;sCAC/I;AAIZ;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+GAA+G,EAAE,CAAC;;0CACxI;AAIhB;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2JAA2J,EAAE,CAAC;;6CACjL;AAInB;IAFC,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uVAAuV,EAAE,CAAC;;0CAChX;AAIhB;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC/C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oEAAoE,EAAE,CAAC;;0CACtH;AAIb;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;sCAClF,IAAI;4CAAA;oBAhIL,SAAS;IArCrB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACnG,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACpG,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAChH,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC9F,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACnG,gEAAgE;;IAC/D,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC3F,4DAA4D;;IAC3D,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAClG;;;;;;;;;;;;OAYG;;IACF,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAClH;;;;;;;;;;OAUG;;IACF,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACpG,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,2EAA2E,EAAE,CAAC;GAC5F,SAAS,CAiIrB","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID, Int } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\n/*\n * TwinEvent โ append-only ํธ์ ์ด๋ฒคํธ ์ ๋(EPCIS ์ด๋ฒคํธ + ์ด์ ๋ธํ).\n * ์ปค๋ EventJournal ์ ์์ ๋์ โ ์ํ=์ด๋ฒคํธ์ด์ ํจ์(์ฌ๋ถํ
์ DBโreplay ์ฌ๊ตฌ์ฑ).\n * append-only ์ด๋ฏ๋ก updater/deletedAt ์์(์ด๋ ฅ CRUD ๊ฐ ์๋๋ผ ๋ถ๋ณ ์ด๋ฒคํธ ์คํธ๋ฆผ).\n * payload ๋ simple-json(๋ฉํฐDB ์ด์ โ postgres/mysql/sqlite/mssql/oracle ๊ณตํต, DB-specific JSON ํ์
๊ธ์ง).\n * (CLAUDE.md: ๋ชจ๋ @ObjectType/@Field ๋ ์๋ฌธ description ํ์.)\n */\n/*\n * โโ ์ธ๋ฑ์ค ์ค๊ณ (2026-07-31) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ๋ **์ธ์ ์คํธ ๊ฒฝ๋ก์ ๋จ๊ฑฐ์ด append-only ํ
์ด๋ธ**์ด๋ค. ์ธ๋ฑ์ค ํ๋ํ๋๊ฐ ์ฐ๊ธฐ ์ฆํญ์ด๋ฏ๋ก\n * \"์์ผ๋ฉด ์ข์\" ์ธ๋ฑ์ค๋ฅผ ๋ถ์ด์ง ์๋๋ค. ์ค์ ์ง์ ํจํด์ ๋์ํ๋ ๊ฒ๋ง ๋๋ค.\n *\n * ix_0 (domain, instanceId, revision) ์์ฅ ๊ธฐ๋ณธ ์ ๋ ฌยท์ปค์ ํ์ด์งยทreplay(ASC ์ฃผ์ฌ)\n * ix_1 (domain, instanceId, eventTime) ์๊ฐ ์ปค์(untilTime)ยท์๊ฐ์ฐฝ KPI โ ๊ฑฐ์ ๋ชจ๋ ์กฐํ๊ฐ ํ๋ค\n * ix_2 (domain, instanceId, eventType, revision) ํ์
ํํฐ + ์ ๋ ฌ ๋์ ์ถฉ์กฑ(์ค์ผ์ค ํ๋ฉด task/equipment)\n * ix_3 (domain, instanceId, epc) \"์ด ๋ฌผ๊ฑด์ ์ด๋ ฅ\" โ Entity360 ์ ๋ณธ์ง ์ง๋ฌธ\n * ix_4 (domain, instanceId, orderId) \"์ด ์ค๋๊ฐ ์ด๋๊น์ง ๊ฐ๋\"\n *\n * bizStepยทlocationIdยทmoverId ๋ ์ปฌ๋ผ๋ง ๋๊ณ ์ธ๋ฑ์ค๋ ๋์ง ์๋๋ค โ ํ ํธ์ ์์์ ์นด๋๋๋ฆฌํฐ๊ฐ\n * ๋ฎ์(์
๋ฌด๋จ๊ณ ๋ช ๊ฐ, ์์น ์๋ฐฑ, ์ค๋น ์์ญ) (domain,instanceId) ๋ก ์ด๋ฏธ ์ขํ์ง ๋ค์ ์์ฌ ํํฐ๋ก\n * ์ถฉ๋ถํ๊ณ , ๋จ๊ฑฐ์ด ํ์ ์ธ๋ฑ์ค๋ฅผ ๋ ์น์ ๊ฐ์น๊ฐ ์๋ค. ์ ๋ ํ๋๊ฐ ์์ฃผ ์ปค์ ธ์ ์ด ์ถ๋ค์ ์กฐํ๊ฐ\n * ๋๋ ค์ง๋ฉด ๊ทธ๋ ์ธก์ ์ ๊ทผ๊ฑฐ๋ก ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ ์ผ์ด์ง, ์ง๋ ์น์ด ์ฐ๊ธฐ๋ฅผ ๋ฌด๊ฒ๊ฒ ํ ์ผ์ ์๋๋ค.\n */\n@Entity()\n@Index('ix_twin_event_0', (e: TwinEvent) => [e.domain, e.instanceId, e.revision], { unique: false })\n@Index('ix_twin_event_1', (e: TwinEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })\n@Index('ix_twin_event_2', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.revision], { unique: false })\n@Index('ix_twin_event_3', (e: TwinEvent) => [e.domain, e.instanceId, e.epc], { unique: false })\n@Index('ix_twin_event_4', (e: TwinEvent) => [e.domain, e.instanceId, e.orderId], { unique: false })\n/* ix_5 โ \"์ด ์ง์๊ฐ ๋ฌด์์ ์ผ์ผ์ผฐ๋\". ๊ฐ์ฌ ๊ธฐ๋ก์ commandId ๋ก ์ ๋์ ๋ค์ ๊ณ์ฐํ๋ ์ถ. */\n@Index('ix_twin_event_5', (e: TwinEvent) => [e.domain, e.correlationId], { unique: false })\n/* ix_6 โ \"๋ฐ์ถ์ ํ ๋ฒ์ด๋ผ๋ ๊ณ์ฐํ๋\". ์์ผ๋ฉด ๊ทธ ์ง๋ฌธ์ด ์ธ์คํด์ค ์ ๋ ์ ๋ ์ฃผ์ฌ๊ฐ ๋๋ค. */\n@Index('ix_twin_event_6', (e: TwinEvent) => [e.domain, e.instanceId, e.action], { unique: false })\n/*\n * ix_7 โ **\"์ด ์ข
๋ฅ์ ์ฌ์ค์ ์๊ฐ์์ผ๋ก\"** (2026-08-25 ์ค์ธก์ผ๋ก ์ถ๊ฐ)\n *\n * ์ด ์ถ์ด ์์ด์ ๊ณต์ ํ์๋ผ์ธ์ด 22์ด์๋ค. ์ข
๋ฅ๋ก ๊ฑฐ๋ฅด๊ณ ์๊ฐ์ผ๋ก ์ ๋ ฌํ๋ ์กฐํ๊ฐ ๊ฐ ๊ณณ์ด ์์๋ค:\n *\n * ix_2 (โฆ, eventType, revision) ์ข
๋ฅ๋ ๊ฑธ๋ฌ์ง๊ณ ์ ๋ ฌ์ด **์ ํ ์์**๋ค โ 4์ ์ฌ์ค์ ์ต๊ทผ์ผ๋ก ๊ทธ๋ ธ๋ค\n * ix_1 (โฆ, eventTime) ์ ๋ ฌ์ ๋ง๊ณ **์ข
๋ฅ๋ฅผ ๋ชป ๊ฑฐ๋ฅธ๋ค** โ ํ๋ง๋ค ํ
์ด๋ธ์ ์ด์ด ํ์ธํ๋ค\n *\n * ๋ค์ชฝ์ผ๋ก ๊ฑธ์ผ๋ฉด ๊ทธ ํธ์์์ ์ฐพ๋ ์ข
๋ฅ๊ฐ ๋ฉ์ถ ์์ ๊น์ง์ ๋ชจ๋ ํ์ ์ฝ๊ณ ๋ฒ๋ฆฐ๋ค. ์นํํธ๋์์ ์์
\n * ์ฌ์ค์ 8์ 22์ผ์ ๋ฉ์ถฐ ์๊ณ ๊ทธ ๋ค๋ก ๋ฆฌ๋น์ ์ด 110๋ง ๋์์ผ๋ฏ๋ก, 200๊ฑด์ ๋ฟ๊ธฐ๊น์ง 110๋ง ํ์ ์ด์๋ค.\n *\n * ์ ์ฃผ์์ด ใ์ธก์ ์ ๊ทผ๊ฑฐ๋ก ์ถ๊ฐํ ์ผ์ด์ง ์ง๋ ์น์ ์ผ์ ์๋๋คใ๋ผ๊ณ ์ ์ด ๋์๋ค. ๊ทธ ์ธก์ ์ด ๋์๋ค.\n */\n@Index('ix_twin_event_7', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.eventTime], { unique: false })\n/*\n * ix_8 โ **\"์ด ํธ์์ ์ค๋๋ ๊ธฐ๋ก\"** (2026-08-27 ์ค์ธก์ผ๋ก ์ถ๊ฐ)\n *\n * ๋ณด๊ด ๊ธฐ๊ฐ ์ ๋ฆฌ๊ฐ `created_at` ์ผ๋ก ์๋ฅด๋๋ฐ(๋ณด๊ด์ ์ ์ฅ ๋์ด์ ๋ฌธ์ ๋ค) ๊ทธ ์ถ์ ์ธ๋ฑ์ค๊ฐ ์์๋ค.\n * ๊ทธ๋์ ์ ๋ฆฌ๊ฐ ๋งค ๋ฐฐ์น๋ง๋ค ๊ทธ ํธ์์ ์ ๋์ ์ ๋ ์ฃผ์ฌํ๋ค.\n *\n * hatio-mx2 ์ 7์ผ ๋ฐ ํ์ ์ธ๊ธฐ 208์ด โ 1,029๋ง ํ์ ์ ๋ถ ์ฝ๋๋ค(7์ผ ๋ฐ์ 2,446๊ฑด๋ฟ์ด๋ค)\n * revision ์ผ๋ก ํ ํ ์ง๊ธฐ 0.004์ด\n *\n * ์ ๋ฆฌ๋ ํ ์ฐฝ์ 2์ด๋ง ์ฐ๋๋ก ์์ฐ์ด ๊ฑธ๋ ค ์์ด์, ๊ทธ 2์ด๋ฅผ ์ฃผ์ฌ์ ๋ค ์ฐ๊ณ 44๊ฑด๋ง ์ง์ฐ๊ณ ๋ฉ์ท๋ค.\n */\n@Index('ix_twin_event_8', (e: TwinEvent) => [e.domain, e.instanceId, e.createdAt], { unique: false })\n@ObjectType({ description: 'Append-only twin event journal record (EPCIS event or operational delta).' })\nexport class TwinEvent {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the event record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinEvent) => e.domain)\n domainId?: string\n\n /*\n * ์ด ์ฌ์ค์ ๋ธ ํธ์. **๋น ์ ์๋ค** โ ์ ๋ ํ์ ๋ง๋๋ ๊ณณ์ `journalRow` ํ๋๋ฟ์ด๊ณ ๊ฑฐ๊ธฐ์\n * ํ์ ์ธ์๋ก ๋ฐ๋๋ค. nullable ๋ก ๋๋ฉด ์ฝ๋ ์ชฝ์ด ๋งค๋ฒ `?? ''` ๋ฅผ ๋ฌ๊ฒ ๋๊ณ , ๊ทธ ๋ฐฉ์ด๊ฐ ์ค์ ๋ก๋\n * ์ผ์ด๋์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ๋๋ผ \"๋น ์ธ์คํด์ค์ ์ด๋ฒคํธ\" ๋ผ๋ ์๋ ๊ฐ๋
์ ์ฝ๋์ ๋จ๊ธด๋ค.\n */\n @Column()\n @Field({ description: 'Twin runtime instance id that emitted the event.' })\n instanceId: string\n\n /* ์ปค๋ ๋ดํฌ์ ํ์ ํ๋(`CanonicalEnvelope.eventType`)๋ผ ๋น ์ ์๋ค โ ๊ณ์ฝ์ ๊ทธ๋๋ก ์ฎ๊ธด๋ค. */\n @Column()\n @Field({ description: 'Event type: epcis.* | task.status | equipment.status | order.status.' })\n eventType: string\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Monotonic state revision at which the event was emitted.' })\n revision?: number\n\n /**\n * ์ด ์ฌ์ค์ด **์ด๋ ๊ณต์ฅ์์** ์ผ์ด๋ฌ๋ โ `TwinStructure.rev`.\n *\n * ์ด๊ฒ์ด ์๋ ์์ ์๋ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ฉด ์ ๋์ ํต์งธ๋ก ์ง์ฐ๋ ๊ฒ์ด ์ ์ผํ ๊ธธ์ด์๋ค(์ ์ง์ฐ๋ฉด ์\n * ์ด๋ฒคํธ๋ฅผ ์ ๊ณต์ฅ์ ๋๊ณ ๊ณ์ฐํด ์ด๋ ฅ์ด ๊ฑฐ์ง๋ง์ ํ๋ค). ์ด ํ ์นธ์ด ์
์งธ ๊ธธ์ ์ฐ๋ค โ ์ฌ์์ด\n * ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ ์ง์ ์์ ์ ํํ ๋ค ์ด์ด์ ๊ณ์ฐํ๋ค.\n *\n * **๋น์ด ์์ ์ ์๋ค**: ์ปฌ๋ผ์ด ์๊ธฐ๊ธฐ ์ ์ ์ฐ์ธ ํ์ด๋ค. ๊ทธ ํ๋ค์ **๊ฐ์ฅ ์ค๋๋ ๋ฆฌ๋น์ **์\n * ์ํ๋ค(0 ์ ์ฑ์ ๋ฃ์ง ์๋๋ค โ 0 ์ \"๋ชจ๋ฆ\" ์ด ์๋๋ผ ์ ํจํ ๋ฒํธ์ฒ๋ผ ๋ณด์ธ๋ค).\n */\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Structure revision (TwinStructure.rev) in force when this event happened. Absent on rows written before structure revisions existed; those belong to the oldest revision.' })\n structureRev?: number\n\n /*\n * ์ด ์ฌ์ค์ด ์ผ์ด๋ ์๊ฐ(ํธ์์ ์๊ณ). **๋ ์ง ํ์
์ด๋ค.**\n *\n * ์์ ์๋ ๋ฌธ์์ด์ด์๋ค. ์ฝ์ ๋๋ง๋ค `Date.parse` ํ๊ณ , ์ ๋ ฌ์ UTC ISO ๋ง ๋ค์ด์จ๋ค๋ ์ ์ ์์์\n * ์ฌ์ ์ ๋น๊ต๊ฐ ์ฐ์ฐํ ๋ง์๋ค โ `+09:00` ์คํ์
ํ๊ธฐ๊ฐ ํ๋ ์์ด๋ฉด ์๋ฆฌ์ง ์๊ณ ์์๊ฐ ํ๋ฆฐ๋ค.\n * ๊ทธ ์ ์ ๋ ์ปฌ๋ผ ์ด๋์๋ ์ ํ ์์ง ์์๋ค.\n *\n * **ํ์
์ด๋ฆ์ ์ ์ง ์๋๋ค** (2026-08-19 Postgres ๋ถํ
์คํจ๋ก ๊ณ ์นจ).\n *\n * `datetime` ์ ์ ์๋๋ Postgres ๊ฐ ๋ถํ
์ค์ ๊ฑฐ์ ํ๋ค(`DataTypeNotSupportedError`) โ ๊ทธ ์ด๋ฆ์\n * sqliteยทMySQL ์ ๊ฒ์ด๊ณ Postgres ๋ `timestamp` ๋ง ์๋ค. ๊ฑฐ๊พธ๋ก `timestamp` ๋ sqlite ๊ฐ ๋ชจ๋ฅธ๋ค:\n * **๋ค์ฏ ๋๋ผ์ด๋ฒ์ ๋ค ํตํ๋ ์ด๋ฆ์ด ์์ ์๋ค.**\n *\n * ๊ทธ๋์ ์ด๋ฆ์ ๊ณ ๋ฅด๋ ์ผ์ TypeORM ์ ๋งก๊ธด๋ค. `emitDecoratorMetadata` ๊ฐ ์ผ์ ธ ์์ผ๋ฏ๋ก ์ด ์์ฑ์\n * TS ํ์
(`Date`)์์ ๋๋ผ์ด๋ฒ๋ณ ํ์
์ ์ค์ค๋ก ๊ณ ๋ฅธ๋ค(Postgres `timestamp` ยท sqliteยทMySQL `datetime`).\n * ์ด ๋ ํฌ์ ๋ค์ค DB ๊ท์ฝ์ด ์๊ตฌํ๋ ๊ฒ์ด ๋ฐ๋ก ๊ทธ๊ฒ์ด๋ค โ ๋๋ผ์ด๋ฒ ๋ฐฉ์ธ์ ์ฝ๋์ ์ ์ง ์๋๋ค.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Time at which the fact happened on the twin clock.' })\n eventTime?: Date\n\n /*\n * โโ ์น๊ฒฉ๋ ๊ฒ์ ์ถ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * payload ์์ ์๋ ๊ฐ์ ์ธ์ ์คํธ ์์ ์ ๊บผ๋ด ์ค์ปฌ๋ผ์ผ๋ก ๋๋ค(`twin-event-keys.ts` ๊ฐ ๋จ๋
์์ ).\n * payload ๊ฐ ์ฌ์ ํ ์ ๋ณธ์ด๊ณ ์ด๊ฒ๋ค์ **ํ์ ์์ธ**์ด๋ค โ ์๋ก์ด ์ง์ค์ด ์๋๋ผ ์ฐพ์ ์ ์๊ฒ ํ๋ ์ฅ์น.\n * simple-json(TEXT) ์์ ๊ฐ์ 5๊ฐ DB ๋๋ผ์ด๋ฒ ๊ณตํต์ผ๋ก ๊ฑฐ๋ฅผ ๋ฐฉ๋ฒ์ด ์์ด์(๋ฉํฐDB ํธํ ๊ท์น์\n * DB๋ณ JSON ์ฐ์ฐ์ ๊ธ์ง) ์น๊ฒฉ ์ธ์ ์ ํ์ง๊ฐ ์๋ค.\n * ๊ธธ์ด ์ํ 255 ๋ GS1 ์๋ณ์ ๊ท๊ฒฉ ๋๋น ์ถฉ๋ถํ๋ฉฐ, ๋์น๋ ๊ฐ์ ์๋ฆฌ์ง ์๊ณ ์๋ฆฌ์ง ์๊ณ ๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค.\n *\n * โโ ์ถ์ ์๋ก ์ถ๊ฐํ ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ์น๊ฒฉ ์ปฌ๋ผ์ ๋ง๋ค๋ฉด **์ด๋ฏธ ์์ธ ํ์ ๋น์ด ์๋ค.** ๊ทธ ํ๋ค์ ์ ์ถ์ผ๋ก ๊ฒ์๋์ง ์๊ณ ,\n * ์ฌ์ฉ์์๊ฒ๋ \"๊ณผ๊ฑฐ๊ฐ ์๋ ๊ฒ\" ์ผ๋ก ๋ณด์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋น ์ง ๋ฐ์ดํฐ).\n *\n * ์์ ์๋ ๊ธฐ๋ ํ
์ด ๋งค๋ฒ ํ
์ด๋ธ์ ์ดํด ์ฑ์ ๋ค. ๊ทธ๊ฑด ๋ ๊ฐ์ง๋ก ํ๋ ธ๋ค โ ์ ๋์ด ์ปค์ง์๋ก ๋ถํ
์ด\n * ๋๋ ค์ง๊ณ , \"bizStep ์ด ๋น์์ผ๋ฉด ์ ํ\" ์ด๋ผ๋ ์ ์ ๋ฅผ ์ฝ๋์ ๊ณ ์ ํด ๊ทธ ์ ์ ๊ฐ ๊นจ์ง๋ ์๊ฐ\n * (๊ฐ์ฌ ํ์ฒ๋ผ ์
๋ฌด ๋จ๊ณ๊ฐ ์๋ ํ) ๋งค ๋ถํ
๋ง๋ค ํ๋์๋ค. ๊ทธ๋์ ๊ฑท์ด๋๋ค(git: backfill-keys.ts).\n *\n * ์ฑ์ฐ๋ ์ผ์ **๋ง์ด๊ทธ๋ ์ด์
ํ ๋ฒ**์ด ๋ง๋ค(`yarn migration`). ๊ทธ ์ปฌ๋ผ์ ๋ง๋ ๊ฒ์ ๊ทธ๋ ์ด๋ค โ\n * ๋ฒ์ฉ ์ค์บ๋๋ฅผ ๋์ด๋ฆฌ์ง ๋ง ๊ฒ. ๊ฐ๋ฐ ๋ฐ์ดํ๋ผ๋ฉด ๊ทธ๋ฅ ๋ฒ๋ฆฌ๋ ๊ฒ๋ ๋ต์ด๋ค.\n */\n /**\n * ์ด ์ฌ์ค์ ์ผ์ผํจ **์ง์** โ ์ปค๋์ด ์ปค๋งจ๋์์ ์ด์ด ์ค ์๊ด๊ฐ(๊ธฐ๋ณธ์ commandId).\n *\n * ์ด๊ฒ์ด ๊ฐ์ฌ ๊ธฐ๋ก(TwinAuditEvent.commandId)๊ณผ ์ ๋์ ์๋ ์ ์ผํ ๋ค๋ฆฌ๋ค. ์์ผ๋ฉด ์น์ธ ๊ธฐ๋ก์\n * \"์ฌ๋์ด ํ๋ฝํ๋ค\" ๊น์ง์ด๊ณ , ๊ทธ ๋ค ๊ณต์ฅ์ด ์ค์ ๋ก ์ด๋ป๊ฒ ์์ง์๋์ง์ ์ด์ด์ง์ง ์๋๋ค.\n *\n * **๋๋ถ๋ถ์ ํ์ ๋น์ด ์๋ค** โ ์ปค๋งจ๋๊ฐ ์๋๋ผ ์๋ฎฌ ์๊ฐ์ด ๋ณ์ ์ฌ์ค์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๊ฒ์ด ์ ์์ด๊ณ ,\n * ๋น์ด ์๋ค๊ณ \"๋ ์ฑ์์ง ์ ํ\" ์ผ๋ก ๋ณด๋ฉด ์ ๋๋ค(๊ฐ์ ์คํด๋ฅผ bizStep ์์ ์ด๋ฏธ ํ ๋ฒ ํ๋ค).\n */\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Id of the command that caused this fact (kernel correlation id; defaults to the commandId). Empty for facts that simulation time produced rather than a command.' })\n correlationId?: string\n\n /* ์ ํ์ ๋น์ด ์๋ค โ ์น๊ฒฉ ์ ์ ๊ธฐ๋ก๋ ๊ฒ์ด๋ผ **๋ชจ๋ฅธ๋ค**(0 ์ด๋ OBSERVE ๋ก ์์ฅํ์ง ์๋๋ค). */\n @Column({ length: 16, nullable: true })\n @Field({ nullable: true, description: 'EPCIS action (ADD / OBSERVE / DELETE), promoted from the payload. Empty for operational deltas, and for rows journaled before this column existed.' })\n action?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Business step (CBV bizStep tail), promoted from the payload for indexed filtering.' })\n bizStep?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Item identifier (EPC / EPC class / parent id), promoted from the payload for indexed lookup of one item history.' })\n epc?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Business transaction identifier (PO / SO), promoted from the payload for indexed lookup of one order history.' })\n orderId?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Location identifier (read point, business location, or the plain location an operational delta carries), promoted from the payload for indexed filtering.' })\n locationId?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Equipment identifier carried by operational deltas, promoted from the payload so one machine history can be asked for on the server. The column keeps the legacy name `moverId`: the journal is append-only history and mixing two names for the same fact across time is worse than an outdated name. Renaming belongs with event-schema versioning.' })\n moverId?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Raw canonical envelope (EPCIS event or operational delta) as JSON.' })\n payload?: any\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Wall-clock timestamp when the record was persisted.' })\n createdAt?: Date\n}\n"]}
|
|
1
|
+
{"version":3,"file":"twin-event.js","sourceRoot":"","sources":["../../../server/service/twin-event/twin-event.ts"],"names":[],"mappings":"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","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID, Int } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\n/*\n * TwinEvent โ append-only ํธ์ ์ด๋ฒคํธ ์ ๋(EPCIS ์ด๋ฒคํธ + ์ด์ ๋ธํ).\n * ์ปค๋ EventJournal ์ ์์ ๋์ โ ์ํ=์ด๋ฒคํธ์ด์ ํจ์(์ฌ๋ถํ
์ DBโreplay ์ฌ๊ตฌ์ฑ).\n * append-only ์ด๋ฏ๋ก updater/deletedAt ์์(์ด๋ ฅ CRUD ๊ฐ ์๋๋ผ ๋ถ๋ณ ์ด๋ฒคํธ ์คํธ๋ฆผ).\n * payload ๋ simple-json(๋ฉํฐDB ์ด์ โ postgres/mysql/sqlite/mssql/oracle ๊ณตํต, DB-specific JSON ํ์
๊ธ์ง).\n * (CLAUDE.md: ๋ชจ๋ @ObjectType/@Field ๋ ์๋ฌธ description ํ์.)\n */\n/*\n * โโ ์ธ๋ฑ์ค ์ค๊ณ (2026-07-31) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ๋ **์ธ์ ์คํธ ๊ฒฝ๋ก์ ๋จ๊ฑฐ์ด append-only ํ
์ด๋ธ**์ด๋ค. ์ธ๋ฑ์ค ํ๋ํ๋๊ฐ ์ฐ๊ธฐ ์ฆํญ์ด๋ฏ๋ก\n * \"์์ผ๋ฉด ์ข์\" ์ธ๋ฑ์ค๋ฅผ ๋ถ์ด์ง ์๋๋ค. ์ค์ ์ง์ ํจํด์ ๋์ํ๋ ๊ฒ๋ง ๋๋ค.\n *\n * ix_0 (domain, instanceId, revision) ์์ฅ ๊ธฐ๋ณธ ์ ๋ ฌยท์ปค์ ํ์ด์งยทreplay(ASC ์ฃผ์ฌ)\n * ix_1 (domain, instanceId, eventTime) ์๊ฐ ์ปค์(untilTime)ยท์๊ฐ์ฐฝ KPI โ ๊ฑฐ์ ๋ชจ๋ ์กฐํ๊ฐ ํ๋ค\n * ix_2 (domain, instanceId, eventType, revision) ํ์
ํํฐ + ์ ๋ ฌ ๋์ ์ถฉ์กฑ(์ค์ผ์ค ํ๋ฉด task/equipment)\n * ix_3 (domain, instanceId, epc) \"์ด ๋ฌผ๊ฑด์ ์ด๋ ฅ\" โ Entity360 ์ ๋ณธ์ง ์ง๋ฌธ\n * ix_4 (domain, instanceId, orderId) \"์ด ์ค๋๊ฐ ์ด๋๊น์ง ๊ฐ๋\"\n * ix_9 (domain, instanceId, bizTransaction) \"์ด ๊ฑฐ๋์ ๋ฌด์จ ์ผ์ด ์์๋\" โ EPCISโ์ค๋์ ๋ค๋ฆฌ\n *\n * bizStepยทlocationIdยทmoverId ๋ ์ปฌ๋ผ๋ง ๋๊ณ ์ธ๋ฑ์ค๋ ๋์ง ์๋๋ค โ ํ ํธ์ ์์์ ์นด๋๋๋ฆฌํฐ๊ฐ\n * ๋ฎ์(์
๋ฌด๋จ๊ณ ๋ช ๊ฐ, ์์น ์๋ฐฑ, ์ค๋น ์์ญ) (domain,instanceId) ๋ก ์ด๋ฏธ ์ขํ์ง ๋ค์ ์์ฌ ํํฐ๋ก\n * ์ถฉ๋ถํ๊ณ , ๋จ๊ฑฐ์ด ํ์ ์ธ๋ฑ์ค๋ฅผ ๋ ์น์ ๊ฐ์น๊ฐ ์๋ค. ์ ๋ ํ๋๊ฐ ์์ฃผ ์ปค์ ธ์ ์ด ์ถ๋ค์ ์กฐํ๊ฐ\n * ๋๋ ค์ง๋ฉด ๊ทธ๋ ์ธก์ ์ ๊ทผ๊ฑฐ๋ก ์ธ๋ฑ์ค๋ฅผ ์ถ๊ฐํ ์ผ์ด์ง, ์ง๋ ์น์ด ์ฐ๊ธฐ๋ฅผ ๋ฌด๊ฒ๊ฒ ํ ์ผ์ ์๋๋ค.\n */\n@Entity()\n@Index('ix_twin_event_0', (e: TwinEvent) => [e.domain, e.instanceId, e.revision], { unique: false })\n@Index('ix_twin_event_1', (e: TwinEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })\n@Index('ix_twin_event_2', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.revision], { unique: false })\n@Index('ix_twin_event_3', (e: TwinEvent) => [e.domain, e.instanceId, e.epc], { unique: false })\n@Index('ix_twin_event_4', (e: TwinEvent) => [e.domain, e.instanceId, e.orderId], { unique: false })\n/* ix_5 โ \"์ด ์ง์๊ฐ ๋ฌด์์ ์ผ์ผ์ผฐ๋\". ๊ฐ์ฌ ๊ธฐ๋ก์ commandId ๋ก ์ ๋์ ๋ค์ ๊ณ์ฐํ๋ ์ถ. */\n@Index('ix_twin_event_5', (e: TwinEvent) => [e.domain, e.correlationId], { unique: false })\n/* ix_6 โ \"๋ฐ์ถ์ ํ ๋ฒ์ด๋ผ๋ ๊ณ์ฐํ๋\". ์์ผ๋ฉด ๊ทธ ์ง๋ฌธ์ด ์ธ์คํด์ค ์ ๋ ์ ๋ ์ฃผ์ฌ๊ฐ ๋๋ค. */\n@Index('ix_twin_event_6', (e: TwinEvent) => [e.domain, e.instanceId, e.action], { unique: false })\n/*\n * ix_7 โ **\"์ด ์ข
๋ฅ์ ์ฌ์ค์ ์๊ฐ์์ผ๋ก\"** (2026-08-25 ์ค์ธก์ผ๋ก ์ถ๊ฐ)\n *\n * ์ด ์ถ์ด ์์ด์ ๊ณต์ ํ์๋ผ์ธ์ด 22์ด์๋ค. ์ข
๋ฅ๋ก ๊ฑฐ๋ฅด๊ณ ์๊ฐ์ผ๋ก ์ ๋ ฌํ๋ ์กฐํ๊ฐ ๊ฐ ๊ณณ์ด ์์๋ค:\n *\n * ix_2 (โฆ, eventType, revision) ์ข
๋ฅ๋ ๊ฑธ๋ฌ์ง๊ณ ์ ๋ ฌ์ด **์ ํ ์์**๋ค โ 4์ ์ฌ์ค์ ์ต๊ทผ์ผ๋ก ๊ทธ๋ ธ๋ค\n * ix_1 (โฆ, eventTime) ์ ๋ ฌ์ ๋ง๊ณ **์ข
๋ฅ๋ฅผ ๋ชป ๊ฑฐ๋ฅธ๋ค** โ ํ๋ง๋ค ํ
์ด๋ธ์ ์ด์ด ํ์ธํ๋ค\n *\n * ๋ค์ชฝ์ผ๋ก ๊ฑธ์ผ๋ฉด ๊ทธ ํธ์์์ ์ฐพ๋ ์ข
๋ฅ๊ฐ ๋ฉ์ถ ์์ ๊น์ง์ ๋ชจ๋ ํ์ ์ฝ๊ณ ๋ฒ๋ฆฐ๋ค. ์นํํธ๋์์ ์์
\n * ์ฌ์ค์ 8์ 22์ผ์ ๋ฉ์ถฐ ์๊ณ ๊ทธ ๋ค๋ก ๋ฆฌ๋น์ ์ด 110๋ง ๋์์ผ๋ฏ๋ก, 200๊ฑด์ ๋ฟ๊ธฐ๊น์ง 110๋ง ํ์ ์ด์๋ค.\n *\n * ์ ์ฃผ์์ด ใ์ธก์ ์ ๊ทผ๊ฑฐ๋ก ์ถ๊ฐํ ์ผ์ด์ง ์ง๋ ์น์ ์ผ์ ์๋๋คใ๋ผ๊ณ ์ ์ด ๋์๋ค. ๊ทธ ์ธก์ ์ด ๋์๋ค.\n */\n@Index('ix_twin_event_7', (e: TwinEvent) => [e.domain, e.instanceId, e.eventType, e.eventTime], { unique: false })\n/*\n * ix_8 โ **\"์ด ํธ์์ ์ค๋๋ ๊ธฐ๋ก\"** (2026-08-27 ์ค์ธก์ผ๋ก ์ถ๊ฐ)\n *\n * ๋ณด๊ด ๊ธฐ๊ฐ ์ ๋ฆฌ๊ฐ `created_at` ์ผ๋ก ์๋ฅด๋๋ฐ(๋ณด๊ด์ ์ ์ฅ ๋์ด์ ๋ฌธ์ ๋ค) ๊ทธ ์ถ์ ์ธ๋ฑ์ค๊ฐ ์์๋ค.\n * ๊ทธ๋์ ์ ๋ฆฌ๊ฐ ๋งค ๋ฐฐ์น๋ง๋ค ๊ทธ ํธ์์ ์ ๋์ ์ ๋ ์ฃผ์ฌํ๋ค.\n *\n * hatio-mx2 ์ 7์ผ ๋ฐ ํ์ ์ธ๊ธฐ 208์ด โ 1,029๋ง ํ์ ์ ๋ถ ์ฝ๋๋ค(7์ผ ๋ฐ์ 2,446๊ฑด๋ฟ์ด๋ค)\n * revision ์ผ๋ก ํ ํ ์ง๊ธฐ 0.004์ด\n *\n * ์ ๋ฆฌ๋ ํ ์ฐฝ์ 2์ด๋ง ์ฐ๋๋ก ์์ฐ์ด ๊ฑธ๋ ค ์์ด์, ๊ทธ 2์ด๋ฅผ ์ฃผ์ฌ์ ๋ค ์ฐ๊ณ 44๊ฑด๋ง ์ง์ฐ๊ณ ๋ฉ์ท๋ค.\n */\n@Index('ix_twin_event_8', (e: TwinEvent) => [e.domain, e.instanceId, e.createdAt], { unique: false })\n/* ix_9 โ \"์ด ๊ฑฐ๋์ ๋ฌด์จ ์ผ์ด ์์๋\". EPCIS ์ฌ๊ฑด์์ ์ค๋๋ก ๊ฑด๋๊ฐ๋ ๋ค๋ฆฌ(ยง`bizTransaction`). */\n@Index('ix_twin_event_9', (e: TwinEvent) => [e.domain, e.instanceId, e.bizTransaction], { unique: false })\n@ObjectType({ description: 'Append-only twin event journal record (EPCIS event or operational delta).' })\nexport class TwinEvent {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the event record.' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'Owning tenant domain.' })\n domain?: Domain\n\n @RelationId((e: TwinEvent) => e.domain)\n domainId?: string\n\n /*\n * ์ด ์ฌ์ค์ ๋ธ ํธ์. **๋น ์ ์๋ค** โ ์ ๋ ํ์ ๋ง๋๋ ๊ณณ์ `journalRow` ํ๋๋ฟ์ด๊ณ ๊ฑฐ๊ธฐ์\n * ํ์ ์ธ์๋ก ๋ฐ๋๋ค. nullable ๋ก ๋๋ฉด ์ฝ๋ ์ชฝ์ด ๋งค๋ฒ `?? ''` ๋ฅผ ๋ฌ๊ฒ ๋๊ณ , ๊ทธ ๋ฐฉ์ด๊ฐ ์ค์ ๋ก๋\n * ์ผ์ด๋์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ๋๋ผ \"๋น ์ธ์คํด์ค์ ์ด๋ฒคํธ\" ๋ผ๋ ์๋ ๊ฐ๋
์ ์ฝ๋์ ๋จ๊ธด๋ค.\n */\n @Column()\n @Field({ description: 'Twin runtime instance id that emitted the event.' })\n instanceId: string\n\n /* ์ปค๋ ๋ดํฌ์ ํ์ ํ๋(`CanonicalEnvelope.eventType`)๋ผ ๋น ์ ์๋ค โ ๊ณ์ฝ์ ๊ทธ๋๋ก ์ฎ๊ธด๋ค. */\n @Column()\n @Field({ description: 'Event type: epcis.* | task.status | equipment.status | order.status.' })\n eventType: string\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Monotonic state revision at which the event was emitted.' })\n revision?: number\n\n /**\n * ์ด ์ฌ์ค์ด **์ด๋ ๊ณต์ฅ์์** ์ผ์ด๋ฌ๋ โ `TwinStructure.rev`.\n *\n * ์ด๊ฒ์ด ์๋ ์์ ์๋ ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ฉด ์ ๋์ ํต์งธ๋ก ์ง์ฐ๋ ๊ฒ์ด ์ ์ผํ ๊ธธ์ด์๋ค(์ ์ง์ฐ๋ฉด ์\n * ์ด๋ฒคํธ๋ฅผ ์ ๊ณต์ฅ์ ๋๊ณ ๊ณ์ฐํด ์ด๋ ฅ์ด ๊ฑฐ์ง๋ง์ ํ๋ค). ์ด ํ ์นธ์ด ์
์งธ ๊ธธ์ ์ฐ๋ค โ ์ฌ์์ด\n * ๊ตฌ์กฐ๊ฐ ๋ฐ๋๋ ์ง์ ์์ ์ ํํ ๋ค ์ด์ด์ ๊ณ์ฐํ๋ค.\n *\n * **๋น์ด ์์ ์ ์๋ค**: ์ปฌ๋ผ์ด ์๊ธฐ๊ธฐ ์ ์ ์ฐ์ธ ํ์ด๋ค. ๊ทธ ํ๋ค์ **๊ฐ์ฅ ์ค๋๋ ๋ฆฌ๋น์ **์\n * ์ํ๋ค(0 ์ ์ฑ์ ๋ฃ์ง ์๋๋ค โ 0 ์ \"๋ชจ๋ฆ\" ์ด ์๋๋ผ ์ ํจํ ๋ฒํธ์ฒ๋ผ ๋ณด์ธ๋ค).\n */\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'Structure revision (TwinStructure.rev) in force when this event happened. Absent on rows written before structure revisions existed; those belong to the oldest revision.' })\n structureRev?: number\n\n /*\n * ์ด ์ฌ์ค์ด ์ผ์ด๋ ์๊ฐ(ํธ์์ ์๊ณ). **๋ ์ง ํ์
์ด๋ค.**\n *\n * ์์ ์๋ ๋ฌธ์์ด์ด์๋ค. ์ฝ์ ๋๋ง๋ค `Date.parse` ํ๊ณ , ์ ๋ ฌ์ UTC ISO ๋ง ๋ค์ด์จ๋ค๋ ์ ์ ์์์\n * ์ฌ์ ์ ๋น๊ต๊ฐ ์ฐ์ฐํ ๋ง์๋ค โ `+09:00` ์คํ์
ํ๊ธฐ๊ฐ ํ๋ ์์ด๋ฉด ์๋ฆฌ์ง ์๊ณ ์์๊ฐ ํ๋ฆฐ๋ค.\n * ๊ทธ ์ ์ ๋ ์ปฌ๋ผ ์ด๋์๋ ์ ํ ์์ง ์์๋ค.\n *\n * **ํ์
์ด๋ฆ์ ์ ์ง ์๋๋ค** (2026-08-19 Postgres ๋ถํ
์คํจ๋ก ๊ณ ์นจ).\n *\n * `datetime` ์ ์ ์๋๋ Postgres ๊ฐ ๋ถํ
์ค์ ๊ฑฐ์ ํ๋ค(`DataTypeNotSupportedError`) โ ๊ทธ ์ด๋ฆ์\n * sqliteยทMySQL ์ ๊ฒ์ด๊ณ Postgres ๋ `timestamp` ๋ง ์๋ค. ๊ฑฐ๊พธ๋ก `timestamp` ๋ sqlite ๊ฐ ๋ชจ๋ฅธ๋ค:\n * **๋ค์ฏ ๋๋ผ์ด๋ฒ์ ๋ค ํตํ๋ ์ด๋ฆ์ด ์์ ์๋ค.**\n *\n * ๊ทธ๋์ ์ด๋ฆ์ ๊ณ ๋ฅด๋ ์ผ์ TypeORM ์ ๋งก๊ธด๋ค. `emitDecoratorMetadata` ๊ฐ ์ผ์ ธ ์์ผ๋ฏ๋ก ์ด ์์ฑ์\n * TS ํ์
(`Date`)์์ ๋๋ผ์ด๋ฒ๋ณ ํ์
์ ์ค์ค๋ก ๊ณ ๋ฅธ๋ค(Postgres `timestamp` ยท sqliteยทMySQL `datetime`).\n * ์ด ๋ ํฌ์ ๋ค์ค DB ๊ท์ฝ์ด ์๊ตฌํ๋ ๊ฒ์ด ๋ฐ๋ก ๊ทธ๊ฒ์ด๋ค โ ๋๋ผ์ด๋ฒ ๋ฐฉ์ธ์ ์ฝ๋์ ์ ์ง ์๋๋ค.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Time at which the fact happened on the twin clock.' })\n eventTime?: Date\n\n /*\n * โโ ์น๊ฒฉ๋ ๊ฒ์ ์ถ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * payload ์์ ์๋ ๊ฐ์ ์ธ์ ์คํธ ์์ ์ ๊บผ๋ด ์ค์ปฌ๋ผ์ผ๋ก ๋๋ค(`twin-event-keys.ts` ๊ฐ ๋จ๋
์์ ).\n * payload ๊ฐ ์ฌ์ ํ ์ ๋ณธ์ด๊ณ ์ด๊ฒ๋ค์ **ํ์ ์์ธ**์ด๋ค โ ์๋ก์ด ์ง์ค์ด ์๋๋ผ ์ฐพ์ ์ ์๊ฒ ํ๋ ์ฅ์น.\n * simple-json(TEXT) ์์ ๊ฐ์ 5๊ฐ DB ๋๋ผ์ด๋ฒ ๊ณตํต์ผ๋ก ๊ฑฐ๋ฅผ ๋ฐฉ๋ฒ์ด ์์ด์(๋ฉํฐDB ํธํ ๊ท์น์\n * DB๋ณ JSON ์ฐ์ฐ์ ๊ธ์ง) ์น๊ฒฉ ์ธ์ ์ ํ์ง๊ฐ ์๋ค.\n * ๊ธธ์ด ์ํ 255 ๋ GS1 ์๋ณ์ ๊ท๊ฒฉ ๋๋น ์ถฉ๋ถํ๋ฉฐ, ๋์น๋ ๊ฐ์ ์๋ฆฌ์ง ์๊ณ ์๋ฆฌ์ง ์๊ณ ๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค.\n *\n * โโ ์ถ์ ์๋ก ์ถ๊ฐํ ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ ์น๊ฒฉ ์ปฌ๋ผ์ ๋ง๋ค๋ฉด **์ด๋ฏธ ์์ธ ํ์ ๋น์ด ์๋ค.** ๊ทธ ํ๋ค์ ์ ์ถ์ผ๋ก ๊ฒ์๋์ง ์๊ณ ,\n * ์ฌ์ฉ์์๊ฒ๋ \"๊ณผ๊ฑฐ๊ฐ ์๋ ๊ฒ\" ์ผ๋ก ๋ณด์ธ๋ค(์๋ฆฌ์ง ์๊ณ ๋น ์ง ๋ฐ์ดํฐ).\n *\n * ์์ ์๋ ๊ธฐ๋ ํ
์ด ๋งค๋ฒ ํ
์ด๋ธ์ ์ดํด ์ฑ์ ๋ค. ๊ทธ๊ฑด ๋ ๊ฐ์ง๋ก ํ๋ ธ๋ค โ ์ ๋์ด ์ปค์ง์๋ก ๋ถํ
์ด\n * ๋๋ ค์ง๊ณ , \"bizStep ์ด ๋น์์ผ๋ฉด ์ ํ\" ์ด๋ผ๋ ์ ์ ๋ฅผ ์ฝ๋์ ๊ณ ์ ํด ๊ทธ ์ ์ ๊ฐ ๊นจ์ง๋ ์๊ฐ\n * (๊ฐ์ฌ ํ์ฒ๋ผ ์
๋ฌด ๋จ๊ณ๊ฐ ์๋ ํ) ๋งค ๋ถํ
๋ง๋ค ํ๋์๋ค. ๊ทธ๋์ ๊ฑท์ด๋๋ค(git: backfill-keys.ts).\n *\n * ์ฑ์ฐ๋ ์ผ์ **๋ง์ด๊ทธ๋ ์ด์
ํ ๋ฒ**์ด ๋ง๋ค(`yarn migration`). ๊ทธ ์ปฌ๋ผ์ ๋ง๋ ๊ฒ์ ๊ทธ๋ ์ด๋ค โ\n * ๋ฒ์ฉ ์ค์บ๋๋ฅผ ๋์ด๋ฆฌ์ง ๋ง ๊ฒ. ๊ฐ๋ฐ ๋ฐ์ดํ๋ผ๋ฉด ๊ทธ๋ฅ ๋ฒ๋ฆฌ๋ ๊ฒ๋ ๋ต์ด๋ค.\n */\n /**\n * ์ด ์ฌ์ค์ ์ผ์ผํจ **์ง์** โ ์ปค๋์ด ์ปค๋งจ๋์์ ์ด์ด ์ค ์๊ด๊ฐ(๊ธฐ๋ณธ์ commandId).\n *\n * ์ด๊ฒ์ด ๊ฐ์ฌ ๊ธฐ๋ก(TwinAuditEvent.commandId)๊ณผ ์ ๋์ ์๋ ์ ์ผํ ๋ค๋ฆฌ๋ค. ์์ผ๋ฉด ์น์ธ ๊ธฐ๋ก์\n * \"์ฌ๋์ด ํ๋ฝํ๋ค\" ๊น์ง์ด๊ณ , ๊ทธ ๋ค ๊ณต์ฅ์ด ์ค์ ๋ก ์ด๋ป๊ฒ ์์ง์๋์ง์ ์ด์ด์ง์ง ์๋๋ค.\n *\n * **๋๋ถ๋ถ์ ํ์ ๋น์ด ์๋ค** โ ์ปค๋งจ๋๊ฐ ์๋๋ผ ์๋ฎฌ ์๊ฐ์ด ๋ณ์ ์ฌ์ค์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๊ฒ์ด ์ ์์ด๊ณ ,\n * ๋น์ด ์๋ค๊ณ \"๋ ์ฑ์์ง ์ ํ\" ์ผ๋ก ๋ณด๋ฉด ์ ๋๋ค(๊ฐ์ ์คํด๋ฅผ bizStep ์์ ์ด๋ฏธ ํ ๋ฒ ํ๋ค).\n */\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Id of the command that caused this fact (kernel correlation id; defaults to the commandId). Empty for facts that simulation time produced rather than a command.' })\n correlationId?: string\n\n /* ์ ํ์ ๋น์ด ์๋ค โ ์น๊ฒฉ ์ ์ ๊ธฐ๋ก๋ ๊ฒ์ด๋ผ **๋ชจ๋ฅธ๋ค**(0 ์ด๋ OBSERVE ๋ก ์์ฅํ์ง ์๋๋ค). */\n @Column({ length: 16, nullable: true })\n @Field({ nullable: true, description: 'EPCIS action (ADD / OBSERVE / DELETE), promoted from the payload. Empty for operational deltas, and for rows journaled before this column existed.' })\n action?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Business step (CBV bizStep tail), promoted from the payload for indexed filtering.' })\n bizStep?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Item identifier (EPC / EPC class / parent id), promoted from the payload for indexed lookup of one item history.' })\n epc?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Internal order identifier, promoted from the payload for indexed lookup of one order history.' })\n orderId?: string\n\n /*\n * **๊ฑฐ๋ ์๋ณ์๋ ์ค๋ ์๋ณ์์ ๋ค๋ฅธ ๊ฒ์ด๋ค.**\n *\n * ์ ์๋ ๋์ด ํ ์นธ(`orderId`)์ ๋ค์ด๊ฐ๋ค. ๊ทธ๋์ ํ ์ค๋์ ์ด๋ ฅ์ด ์์ธ ์์์ ๋ ์ชฝ์ผ๋ก\n * ๊ฐ๋ผ์ก๋ค โ ์ด์ ๋ธํ๋ `order-1`, EPCIS ์ฌ๊ฑด์ `urn:epc:id:gdti:โฆ` ๋ก ์ ํ ์ด๋ ์ด๋ฆ์ผ๋ก\n * ๋ฌผ์ด๋ ์ ๋ฐ๋ง ๋์๋ค(์ค์ธก 2026-09-05: ์ดํ๊ฐ ์์ธ ํ 10,004๊ฐ, ์ค๋ฅ๋ ๋์ง ์์).\n *\n * ์ค๋ ์ฌ๊ฑด์ ๋ ๊ฐ์ ๋ค ๋ค๊ณ ์๋ค. ๊ทธ๋์ ์ด ์นธ์ด **EPCIS ์ฌ๊ฑด์์ ์ค๋๋ก ๊ฑด๋๊ฐ๋ ๋ค๋ฆฌ**๊ฐ\n * ๋๋ค โ ใ์ด ๊ฐ์ฒด๋ฅผ ์ด๋ ๋ ์ํผ๋ก ๋ง๋ค์๋ใ๊ฐ ๊ทธ ๋ค๋ฆฌ๋ก ๋ตํด์ง๋ค.\n */\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Business transaction identifier (PO / SO / production order), promoted from the payload for indexed lookup of one transaction.' })\n bizTransaction?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Location identifier (read point, business location, or the plain location an operational delta carries), promoted from the payload for indexed filtering.' })\n locationId?: string\n\n @Column({ length: 255, nullable: true })\n @Field({ nullable: true, description: 'Equipment identifier carried by operational deltas, promoted from the payload so one machine history can be asked for on the server. The column keeps the legacy name `moverId`: the journal is append-only history and mixing two names for the same fact across time is worse than an outdated name. Renaming belongs with event-schema versioning.' })\n moverId?: string\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Raw canonical envelope (EPCIS event or operational delta) as JSON.' })\n payload?: any\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Wall-clock timestamp when the record was persisted.' })\n createdAt?: Date\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ์ง์ํ์ง ์๋ ๊ท์น.
|
|
3
|
+
*
|
|
4
|
+
* order ์ค๋๊ฐ ๋งํ๋ค. ํ์ด ๋์ด๋ ์ด์ด๋ ๊ทธ๊ฒ์ ์ด๋ค
|
|
5
|
+
* only-candidate ์ค๋๋ ๋ง ์ ํ์ง๋ง ํ๋ณด๊ฐ ํ๋๋ค โ ๊ณ ๋ฅผ ๊ฒ์ด ์์ผ๋ฉด ์ง์์ด ์๋๋ค
|
|
6
|
+
* ambiguous ํ๋ณด๊ฐ ๋ ์ด์์ธ๋ฐ ๋งํด ์ฃผ๋ ๊ฒ์ด ์๋ค โ **๋ตํ์ง ์๋๋ค**
|
|
7
|
+
* said-but-undeclared ์ค๋๋ ๋งํ๋๋ฐ ๊ทธ ๋ ์ํผ๊ฐ ์ ์ธ์ ์๋ค โ ๋ชจ๋ฅด๋ ๊ฒ์ด ์๋๋ผ ์ด๊ธ๋ ๊ฒ์ด๋ค
|
|
8
|
+
*
|
|
9
|
+
* ๋ง์ง๋ง ๋์ ๊ฐ๋ฅด๋ ์ด์ : ์ฌ๋์ด ํ ์ผ์ด ๋ค๋ฅด๋ค. ์ด๊ธ๋จ์ ์ ์ธ์ด๋ ์๋ณธ์ ๊ณ ์น ์ผ์ด๊ณ ,
|
|
10
|
+
* ๋ชจํธํจ์ ๊ทธ ๊ฐ์ฒด๊ฐ ์ด๋ ๊ฒ์ผ๋ก ๋ง๋ค์ด์ก๋์ง ๊ธฐ๋ก์ด ์๋ ์ผ์ด๋ค.
|
|
11
|
+
*/
|
|
12
|
+
export declare function chooseRecipe(recipes: any[], candidates: any[], saidRecipeKey: string | undefined): {
|
|
13
|
+
recipe?: any;
|
|
14
|
+
basis: 'order' | 'only-candidate' | 'ambiguous' | 'said-but-undeclared' | 'none';
|
|
15
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chooseRecipe = chooseRecipe;
|
|
4
|
+
/*
|
|
5
|
+
* **์ด๋ ๋ ์ํผ๋ก ๋ง๋ค์๋** โ ํ์ ๋ง. ์์ํ๋ค.
|
|
6
|
+
*
|
|
7
|
+
* โโ ์ ๋ฐ๋ก ์๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
8
|
+
* ๊ณ๋ณด ์ง์๋ TypeORM ๊ณผ shell ์ ๋์ด์จ๋ค. ๊ท์น๋ง ์ฌ๋ ค๋ ์ํ์ด ๊ทธ๊ฒ๊น์ง ๋ค๊ณ ์ค๋ฉด ๋ฌด๊ฒ๊ณ , ์ด
|
|
9
|
+
* ์ ์ฅ์์์ ๊ทธ ์ด์ ๋ก ์ํ์ด ์ ์๋ ์ผ์ ๊ฒช์๋ค. ํ๋จ๊ณผ ๋ฐฐ์ ์ ๋๋๋ค โ ์ฌ๊ธฐ๋ ๊ฐ๋ง ๋ณด๊ณ ๋ตํ๋ค.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* ์ง์ํ์ง ์๋ ๊ท์น.
|
|
13
|
+
*
|
|
14
|
+
* order ์ค๋๊ฐ ๋งํ๋ค. ํ์ด ๋์ด๋ ์ด์ด๋ ๊ทธ๊ฒ์ ์ด๋ค
|
|
15
|
+
* only-candidate ์ค๋๋ ๋ง ์ ํ์ง๋ง ํ๋ณด๊ฐ ํ๋๋ค โ ๊ณ ๋ฅผ ๊ฒ์ด ์์ผ๋ฉด ์ง์์ด ์๋๋ค
|
|
16
|
+
* ambiguous ํ๋ณด๊ฐ ๋ ์ด์์ธ๋ฐ ๋งํด ์ฃผ๋ ๊ฒ์ด ์๋ค โ **๋ตํ์ง ์๋๋ค**
|
|
17
|
+
* said-but-undeclared ์ค๋๋ ๋งํ๋๋ฐ ๊ทธ ๋ ์ํผ๊ฐ ์ ์ธ์ ์๋ค โ ๋ชจ๋ฅด๋ ๊ฒ์ด ์๋๋ผ ์ด๊ธ๋ ๊ฒ์ด๋ค
|
|
18
|
+
*
|
|
19
|
+
* ๋ง์ง๋ง ๋์ ๊ฐ๋ฅด๋ ์ด์ : ์ฌ๋์ด ํ ์ผ์ด ๋ค๋ฅด๋ค. ์ด๊ธ๋จ์ ์ ์ธ์ด๋ ์๋ณธ์ ๊ณ ์น ์ผ์ด๊ณ ,
|
|
20
|
+
* ๋ชจํธํจ์ ๊ทธ ๊ฐ์ฒด๊ฐ ์ด๋ ๊ฒ์ผ๋ก ๋ง๋ค์ด์ก๋์ง ๊ธฐ๋ก์ด ์๋ ์ผ์ด๋ค.
|
|
21
|
+
*/
|
|
22
|
+
function chooseRecipe(recipes, candidates, saidRecipeKey) {
|
|
23
|
+
if (saidRecipeKey) {
|
|
24
|
+
const said = recipes.find((r) => r?.key === saidRecipeKey);
|
|
25
|
+
return said ? { recipe: said, basis: 'order' } : { basis: 'said-but-undeclared' };
|
|
26
|
+
}
|
|
27
|
+
if (candidates.length === 1)
|
|
28
|
+
return { recipe: candidates[0], basis: 'only-candidate' };
|
|
29
|
+
if (candidates.length > 1)
|
|
30
|
+
return { basis: 'ambiguous' };
|
|
31
|
+
return { basis: 'none' };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=choose-recipe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choose-recipe.js","sourceRoot":"","sources":["../../../server/service/twin-model/choose-recipe.ts"],"names":[],"mappings":";;AAkBA,oCAYC;AA9BD;;;;;;GAMG;AACH;;;;;;;;;;GAUG;AACH,SAAgB,YAAY,CAC1B,OAAc,EACd,UAAiB,EACjB,aAAiC;IAEjC,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,aAAa,CAAC,CAAA;QAC/D,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAA;IACnF,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACtF,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;IACxD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;AAC1B,CAAC","sourcesContent":["/*\n * **์ด๋ ๋ ์ํผ๋ก ๋ง๋ค์๋** โ ํ์ ๋ง. ์์ํ๋ค.\n *\n * โโ ์ ๋ฐ๋ก ์๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ณ๋ณด ์ง์๋ TypeORM ๊ณผ shell ์ ๋์ด์จ๋ค. ๊ท์น๋ง ์ฌ๋ ค๋ ์ํ์ด ๊ทธ๊ฒ๊น์ง ๋ค๊ณ ์ค๋ฉด ๋ฌด๊ฒ๊ณ , ์ด\n * ์ ์ฅ์์์ ๊ทธ ์ด์ ๋ก ์ํ์ด ์ ์๋ ์ผ์ ๊ฒช์๋ค. ํ๋จ๊ณผ ๋ฐฐ์ ์ ๋๋๋ค โ ์ฌ๊ธฐ๋ ๊ฐ๋ง ๋ณด๊ณ ๋ตํ๋ค.\n */\n/**\n * ์ง์ํ์ง ์๋ ๊ท์น.\n *\n * order ์ค๋๊ฐ ๋งํ๋ค. ํ์ด ๋์ด๋ ์ด์ด๋ ๊ทธ๊ฒ์ ์ด๋ค\n * only-candidate ์ค๋๋ ๋ง ์ ํ์ง๋ง ํ๋ณด๊ฐ ํ๋๋ค โ ๊ณ ๋ฅผ ๊ฒ์ด ์์ผ๋ฉด ์ง์์ด ์๋๋ค\n * ambiguous ํ๋ณด๊ฐ ๋ ์ด์์ธ๋ฐ ๋งํด ์ฃผ๋ ๊ฒ์ด ์๋ค โ **๋ตํ์ง ์๋๋ค**\n * said-but-undeclared ์ค๋๋ ๋งํ๋๋ฐ ๊ทธ ๋ ์ํผ๊ฐ ์ ์ธ์ ์๋ค โ ๋ชจ๋ฅด๋ ๊ฒ์ด ์๋๋ผ ์ด๊ธ๋ ๊ฒ์ด๋ค\n *\n * ๋ง์ง๋ง ๋์ ๊ฐ๋ฅด๋ ์ด์ : ์ฌ๋์ด ํ ์ผ์ด ๋ค๋ฅด๋ค. ์ด๊ธ๋จ์ ์ ์ธ์ด๋ ์๋ณธ์ ๊ณ ์น ์ผ์ด๊ณ ,\n * ๋ชจํธํจ์ ๊ทธ ๊ฐ์ฒด๊ฐ ์ด๋ ๊ฒ์ผ๋ก ๋ง๋ค์ด์ก๋์ง ๊ธฐ๋ก์ด ์๋ ์ผ์ด๋ค.\n */\nexport function chooseRecipe(\n recipes: any[],\n candidates: any[],\n saidRecipeKey: string | undefined\n): { recipe?: any; basis: 'order' | 'only-candidate' | 'ambiguous' | 'said-but-undeclared' | 'none' } {\n if (saidRecipeKey) {\n const said = recipes.find((r: any) => r?.key === saidRecipeKey)\n return said ? { recipe: said, basis: 'order' } : { basis: 'said-but-undeclared' }\n }\n if (candidates.length === 1) return { recipe: candidates[0], basis: 'only-candidate' }\n if (candidates.length > 1) return { basis: 'ambiguous' }\n return { basis: 'none' }\n}\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** ๋ฐ์ ์ฌ๋ ๋์ ํ๋ โ ํ๋ฉด์ด ์ด๋ฆ์ ๋ณด์ด๊ณ ๊ฐ ๊ณณ์ ์ ํ ์ ์๊ฒ. */
|
|
2
|
+
export interface ExternalRef {
|
|
3
|
+
id: string;
|
|
4
|
+
/** ์ฌ๋์ด ์ฝ๋ ์ด๋ฆ. ์์ผ๋ฉด ํ๋ฉด์ด id ๋ฅผ ๋ณด์ธ๋ค(์ง์ด๋ด์ง ์๋๋ค). */
|
|
5
|
+
name?: string;
|
|
6
|
+
/**
|
|
7
|
+
* ๊ทธ ์ ํ์์ ์ด๊ฒ์ ์ด ์ ์๋ ์๋ฆฌ โ ์์ผ๋ฉด ํ๋ฉด์ด ๋งํฌ๋ฅผ ๋ง๋ค์ง ์๋๋ค.
|
|
8
|
+
*
|
|
9
|
+
* ๋ง๋ค๋ฅธ ๋งํฌ๋ฅผ ๋ง๋ค์ง ์๋ ๊ฒ์ด ์ด ์นธ์ ์์ ์ด๋ค. ๋๋ฌ์ ์๋ฌด ์ผ๋ ์ ์ผ์ด๋๋ฉด ์ฌ๋์ ๊ทธ๊ฒ์
|
|
10
|
+
* ๊ฒฐํจ์ผ๋ก ์ฝ๋๋ค.
|
|
11
|
+
*/
|
|
12
|
+
href?: string;
|
|
13
|
+
/** ๊ทธ id ๊ฐ ์ค์ ๋ก ์๋ โ **์์ผ๋ฉด ์๋ค๊ณ ๋งํ๋ค.** ๋ต์์ ๋นผ์ง ์๋๋ค. */
|
|
14
|
+
missing?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* ๋ฐ์์ ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค โ ๋ค์ด์ค๋ ๊ด๊ณ ํ ๋ฌถ์.
|
|
18
|
+
*
|
|
19
|
+
* `tense` ๋ฅผ **์ ํ์ด ์ ์ธํ๋ค**(๊ณ์ฝ์ `RelationTense`). ์ค์ ยท์ํ ๊ตฌ๊ฐ์ ์ง๋ ์ผ์ด๊ณ ์ ๋น ๊ณํยท
|
|
20
|
+
* ์ง์๋ ์์ ์ผ์ด๋ค โ ใ๊ฑธ๋ฆฐ ๊ฒ์ด ์ดใ์ด ๋ ๋ป์ด ๋๋ ์๋ฆฌ์ด๋ฏ๋ก ๋ฌถ์์ด ์ค์ค๋ก ๋งํด์ผ ํ๋ค.
|
|
21
|
+
*/
|
|
22
|
+
export interface ExternalIncoming {
|
|
23
|
+
/** ๊ด๊ณ์ ์ด๋ฆ(i18n ํค) โ ๊ณ์ฝ์ `via` ์ ๊ฐ์ ๊ท์น. ์ ํ์ ์๊ธฐ ์ ๋๋ฅผ ์ด๋ค. */
|
|
24
|
+
via: string;
|
|
25
|
+
/** ์ด๋์ ์ค๋ โ ์ฌ๋์ด ์ฝ๋ ์ถ ์ด๋ฆ์ด ์๋๋ผ ๊ทธ ์ ํ์ ์ถ ํค๋ค. */
|
|
26
|
+
from: string;
|
|
27
|
+
/** ์ธ์ ์ ์ผ์ธ๊ฐ. ์ ์ฃผ๋ฉด ใ์ ์ธ์ด ๋งํ์ง ์์๋คใ๋ค โ `standing` ์ผ๋ก ๋ฐ๊พธ์ง ์๋๋ค. */
|
|
28
|
+
tense?: 'past' | 'future' | 'standing';
|
|
29
|
+
ids: string[];
|
|
30
|
+
/** ์ ์ฒด ์ โ `ids` ๊ฐ ์๋ ธ์ด๋ ๋ช์ธ์ง ๋งํ๋ค. */
|
|
31
|
+
total: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* ํ external ๋์์ ํธ๋ ์ ํ ์ชฝ ๊ตฌํ.
|
|
35
|
+
*
|
|
36
|
+
* ๋ ๋ค ์ ํ์ด๋ค. ์ด๋ฆ๋ง ๋ ์ค ์ ์๋ ์ ํ๊ณผ ๋ค์ด์ค๋ ๊ด๊ณ๋ง ๋ผ ์ ์๋ ์ ํ์ด ๋ค ์๋ค โ ํ๋๋ง
|
|
37
|
+
* ๊ฝ์๋ ๊ทธ๋งํผ์ ๋ตํด์ง๋ค.
|
|
38
|
+
*/
|
|
39
|
+
export interface ExternalResolver {
|
|
40
|
+
/** ๊ณ์ฝ์ `target.entity` ์ **๊ฐ์ ๋ฑ๋ง**. ๋ค๋ฅด๋ฉด ์๋ฌด ๊ด๊ณ์๋ ์ ๋ถ๋๋ค. */
|
|
41
|
+
entity: string;
|
|
42
|
+
/** ์ด id ๋ค์ด ๋ฌด์์ธ๊ฐ. */
|
|
43
|
+
resolve?(domainId: string, ids: readonly string[]): Promise<ExternalRef[]>;
|
|
44
|
+
/** ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค. */
|
|
45
|
+
incoming?(domainId: string, instanceId: string, axis: string, itemId: string): Promise<ExternalIncoming[]>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* ํด์๊ธฐ๋ฅผ ๊ฝ๋๋ค โ **๋ถํ
์์ ํ ๋ฒ.**
|
|
49
|
+
*
|
|
50
|
+
* ๊ฐ์ `entity` ๋ฅผ ๋ ๋ฒ ๊ฝ์ผ๋ฉด ๋ค์ฃ๊ฒ์ด ์ด๊ธด๋ค. ๊ทธ๊ฒ์ด ๊ฐ๋ฐ ์ค ์ฌ์ ์ฌ์ ์ ์ ๋์์ด๊ณ , ์ด์์์
|
|
51
|
+
* ์ผ์ด๋๋ฉด ๋ ์ ํ์ด ๊ฐ์ ๋์์ ์๊ธฐ ๊ฒ์ด๋ผ ๋งํ๋ ๊ฒ์ด๋ฏ๋ก **๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค** โ ์กฐ์ฉํ ๋ฎ์ผ๋ฉด
|
|
52
|
+
* ์ด๋ ์ชฝ์ด ๋ตํ๊ณ ์๋์ง ์๋ฌด๋ ๋ชจ๋ฅธ๋ค.
|
|
53
|
+
*/
|
|
54
|
+
export declare function registerExternalResolver(r: ExternalResolver, warn?: (msg: string) => void): void;
|
|
55
|
+
/** ์ง๊ธ ๊ฝํ ์๋ ๊ฒ๋ค โ ใ๋ฌด์์ ํ ์ ์๋ใ๋ฅผ ๋ฐ์์ ์ด ์ ์๊ฒ. */
|
|
56
|
+
export declare function externalResolverEntities(): string[];
|
|
57
|
+
/** ์ํ์ด ์ฌ๊ธฐ๋์ ๋ฃ์ ์ ์๊ฒ. */
|
|
58
|
+
export declare function clearExternalResolvers(): void;
|
|
59
|
+
/**
|
|
60
|
+
* ๊ทธ id ๋ค์ ํผ๋ค โ **๋ชป ํ๋ฉด ๋ชป ํผ๋ค๊ณ ๋งํ๋ค.**
|
|
61
|
+
*
|
|
62
|
+
* ํด์๊ธฐ๊ฐ ํฐ์ ธ๋ 360 ์ ์ฒด๋ฅผ ์ฃฝ์ด์ง ์๋๋ค. ํ ๊ด๊ณ๊ฐ ๋ต์ ๋ชป ํ๋ ๊ฒ๊ณผ ํ๋ฉด์ด ์ ๋จ๋ ๊ฒ์ ๋ค๋ฅธ
|
|
63
|
+
* ์ฌ๊ณ ์ด๊ณ , ๋ค์ฃ๊ฒ์ด ํจ์ฌ ๋์๋ค.
|
|
64
|
+
*/
|
|
65
|
+
export declare function resolveExternal(entity: string, domainId: string, ids: readonly string[], warn?: (msg: string) => void): Promise<{
|
|
66
|
+
refs?: ExternalRef[];
|
|
67
|
+
unresolved?: 'no-resolver' | 'failed';
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* ๋ฐ์์ ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค์ ๋ชจ์๋ค.
|
|
71
|
+
*
|
|
72
|
+
* ๊ฝํ ๊ฒ์ด ์์ผ๋ฉด **๋น ๋ฐฐ์ด์ด์ง ์ค๋ฅ๊ฐ ์๋๋ค** โ ๋ฐ์์ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด ์๋ ๋์์ด ์ ์์ด๋ค.
|
|
73
|
+
* ๋ค๋ง ใํด์๊ธฐ๊ฐ ์์ด์ ๋ชจ๋ฅธ๋คใ์ ใ์๋คใ๋ ๋ค๋ฅด๋ฏ๋ก, ๊ทธ ๊ตฌ๋ณ์ `externalResolverEntities()` ๋ก
|
|
74
|
+
* ๋ฐ์์ ์ฐ๋ค.
|
|
75
|
+
*/
|
|
76
|
+
export declare function externalIncoming(domainId: string, instanceId: string, axis: string, itemId: string, warn?: (msg: string) => void): Promise<ExternalIncoming[]>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* **board ๋ฐ์ ๊ฐ๋ฆฌํค๋ ๊ด๊ณ๋ฅผ ํธ๋ ์๋ฆฌ** โ ์ ์ธ์ ์๊ณ ์ฝ๋๊ฐ 0๊ณณ์ด๋ ์ด์์.
|
|
4
|
+
*
|
|
5
|
+
* โโ ๋ฌด์์ด ์์๋ (2026-09-05 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
6
|
+
* ๊ณ์ฝ์ด `target: { kind: 'external', entity: โฆ }` ๋ฅผ ์ ์ธํ๊ณ ์ฃผ์์ ใํด์๋ ํธ์คํธ๊ฐ ํ๋คใ๊ณ
|
|
7
|
+
* ์ ์ด ๋์๋ค. ๊ทธ๋ฐ๋ฐ **`headless-twin/server` ์ด๋์๋ `kind === 'external'` ์ ๋ค๋ฃจ๋ ์ฝ๋๊ฐ
|
|
8
|
+
* ์์๋ค**(0๊ณณ).
|
|
9
|
+
*
|
|
10
|
+
* `space.area` ๊ฐ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ ์ด์ ๋ ์ด์์๊ฐ ์์ด์๊ฐ ์๋๋ผ **ํธ์คํธ์์ ๊ทธ๊ฒ์ด ํ๋ฒํ FK
|
|
11
|
+
* ๋ผ์**๋ค. TypeORM ๋ฉํ๋ฐ์ดํฐ๊ฐ ์ฐ์ฐํ ๋ตํด ์ค ๊ฒ์ด์ง ์ ์ธ์ด ๊ธธ์ ๋ธ ๊ฒ์ด ์๋๋ค.
|
|
12
|
+
*
|
|
13
|
+
* โโ ์ ์ง๊ธ ์ฑ์ฐ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
14
|
+
* ์์นจ์๋ ใ์๋ฌด๋ ์ ๋งํ์ผ๋ ๊ธํ์ง ์๋คใ๋ก ์ ์๋ค. **๊ทธ ํ๋จ์ด ๊ท๋ชจ๋ฅผ ์๊ฒ ์ก์ ๊ฒ์ด์๋ค.**
|
|
15
|
+
*
|
|
16
|
+
* 360(ํ ๋์์ ๊ฑธ๋ฆฐ ๊ฒ์ ํ์๋ฆฌ์)์ ์๋น์ฒ๋ ๋ฌดํํ ๋์ด๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ ์ ํ์ ์๊ธฐ ์ ์ฅ์๊ฐ
|
|
17
|
+
* ๊ด๊ณ์ ์์ฒ์ด ๋๋ค โ MES ์ ์ค์ ยท์ํ ๊ตฌ๊ฐยท์ ๋น ๊ณํ์ด ๊ทธ๋ ๊ณ , ๋ค์ ์ ํ๋ ๊ทธ๋ด ๊ฒ์ด๋ค.
|
|
18
|
+
*
|
|
19
|
+
* ๊ทธ๋ **์ ์ธ์ ใ๋ฐ์ ๊ฐ๋ฆฌํจ๋คใ๊ณ ๋งํ๋๋ฐ ํธ๋ ๊ธธ์ด ์์ผ๋ฉด ์ ํ๋ง๋ค ์๊ธฐ ๊ธธ์ ๋ธ๋ค.** ๊ทธ๊ฒ์ด
|
|
20
|
+
* ์ ํํ ใ๋ฌดํํ ๊ฐ๋ฆฐ๋คใ๋ค. ์ด ํ์ผ์ด ๊ทธ ๊ฐ๋ฆผ์ ๋ง๋๋ค.
|
|
21
|
+
*
|
|
22
|
+
* โโ ์ปค๋์ ์ด๋ ํ์ธ์ง ๋ชจ๋ฅธ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
23
|
+
* ๊ณ์ฝ์ ใ์ด ์ถ์ด ๋ฐ์ ๊ฐ๋ฆฌํจ๋คใ๊น์ง๋ง ์๋ค. **ใ์ด๋ ํ์ ์ด๋ ์นธใ์ ์ ํ์ด ์๋ค.** ๊ทธ๋์ ์ ํ์ด
|
|
24
|
+
* ๋ถํ
์์ ํด์๊ธฐ๋ฅผ ๊ฝ๋๋ค โ ์ฅ๋ถ ๊ธฐ๋ก๊ธฐ(`installIngestWindowWriter`)์ ๊ฐ์ ๊ท์จ์ด๋ค.
|
|
25
|
+
*
|
|
26
|
+
* ์ปค๋์ด ํ ์ด๋ฆ์ ์๊ฒ ๋๋ฉด ํ ์ ํ์ ์ ์ฅ ๊ตฌ์กฐ์ ๋งค์ด๊ณ , ๋ค์ ์ ํ์ด ๋ค๋ฅธ ํ๋ฅผ ์ฐ๋ฉด ์ปค๋์ ๋
|
|
27
|
+
* ๊ณ ์ณ์ผ ํ๋ค.
|
|
28
|
+
*
|
|
29
|
+
* โโ ์๋ ๊ฒ์ ์จ๊ธฐ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
30
|
+
* ํด์๊ธฐ๊ฐ ์์ผ๋ฉด **๊ทธ ์ฌ์ค์ ๋ธ๋ค**(`unresolved`). ๋งํฌ๋ฅผ ์ง์ฐ๋ฉด ํ๋ฉด์ ใ๊ทธ๋ฐ ๊ด๊ณ๊ฐ ์๋คใ๋ก
|
|
31
|
+
* ์ฝ๊ณ , ์ค์ ๋ก๋ ใ์๋ฌด๋ ๋ตํ ์ ์๋คใ๋ค. ๊ทธ ๋์ ์ฌ๋์ด ํ ์ผ์ด ๋ค๋ฅด๋ค.
|
|
32
|
+
*/
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.registerExternalResolver = registerExternalResolver;
|
|
35
|
+
exports.externalResolverEntities = externalResolverEntities;
|
|
36
|
+
exports.clearExternalResolvers = clearExternalResolvers;
|
|
37
|
+
exports.resolveExternal = resolveExternal;
|
|
38
|
+
exports.externalIncoming = externalIncoming;
|
|
39
|
+
const resolvers = new Map();
|
|
40
|
+
/**
|
|
41
|
+
* ํด์๊ธฐ๋ฅผ ๊ฝ๋๋ค โ **๋ถํ
์์ ํ ๋ฒ.**
|
|
42
|
+
*
|
|
43
|
+
* ๊ฐ์ `entity` ๋ฅผ ๋ ๋ฒ ๊ฝ์ผ๋ฉด ๋ค์ฃ๊ฒ์ด ์ด๊ธด๋ค. ๊ทธ๊ฒ์ด ๊ฐ๋ฐ ์ค ์ฌ์ ์ฌ์ ์ ์ ๋์์ด๊ณ , ์ด์์์
|
|
44
|
+
* ์ผ์ด๋๋ฉด ๋ ์ ํ์ด ๊ฐ์ ๋์์ ์๊ธฐ ๊ฒ์ด๋ผ ๋งํ๋ ๊ฒ์ด๋ฏ๋ก **๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค** โ ์กฐ์ฉํ ๋ฎ์ผ๋ฉด
|
|
45
|
+
* ์ด๋ ์ชฝ์ด ๋ตํ๊ณ ์๋์ง ์๋ฌด๋ ๋ชจ๋ฅธ๋ค.
|
|
46
|
+
*/
|
|
47
|
+
function registerExternalResolver(r, warn) {
|
|
48
|
+
const entity = String(r?.entity ?? '').trim();
|
|
49
|
+
if (!entity) {
|
|
50
|
+
warn?.('[external-resolver] entity ์๋ ํด์๊ธฐ๋ ๊ฝ์ง ์๋๋ค โ ์๋ฌด ๊ด๊ณ์๋ ์ ๋ถ๋๋ค');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (resolvers.has(entity)) {
|
|
54
|
+
warn?.(`[external-resolver] '${entity}' ํด์๊ธฐ๋ฅผ ๋ฎ์ด์ด๋ค โ ๋ ์ ํ์ด ๊ฐ์ ๋์์ ๋ตํ๋ ค ํ๋ฉด ๊ทธ์ค ํ๋๋ง ๋ตํ๋ค`);
|
|
55
|
+
}
|
|
56
|
+
resolvers.set(entity, { ...r, entity });
|
|
57
|
+
}
|
|
58
|
+
/** ์ง๊ธ ๊ฝํ ์๋ ๊ฒ๋ค โ ใ๋ฌด์์ ํ ์ ์๋ใ๋ฅผ ๋ฐ์์ ์ด ์ ์๊ฒ. */
|
|
59
|
+
function externalResolverEntities() {
|
|
60
|
+
return [...resolvers.keys()].sort();
|
|
61
|
+
}
|
|
62
|
+
/** ์ํ์ด ์ฌ๊ธฐ๋์ ๋ฃ์ ์ ์๊ฒ. */
|
|
63
|
+
function clearExternalResolvers() {
|
|
64
|
+
resolvers.clear();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* ๊ทธ id ๋ค์ ํผ๋ค โ **๋ชป ํ๋ฉด ๋ชป ํผ๋ค๊ณ ๋งํ๋ค.**
|
|
68
|
+
*
|
|
69
|
+
* ํด์๊ธฐ๊ฐ ํฐ์ ธ๋ 360 ์ ์ฒด๋ฅผ ์ฃฝ์ด์ง ์๋๋ค. ํ ๊ด๊ณ๊ฐ ๋ต์ ๋ชป ํ๋ ๊ฒ๊ณผ ํ๋ฉด์ด ์ ๋จ๋ ๊ฒ์ ๋ค๋ฅธ
|
|
70
|
+
* ์ฌ๊ณ ์ด๊ณ , ๋ค์ฃ๊ฒ์ด ํจ์ฌ ๋์๋ค.
|
|
71
|
+
*/
|
|
72
|
+
async function resolveExternal(entity, domainId, ids, warn) {
|
|
73
|
+
const r = resolvers.get(entity);
|
|
74
|
+
if (!r?.resolve)
|
|
75
|
+
return { unresolved: 'no-resolver' };
|
|
76
|
+
try {
|
|
77
|
+
return { refs: await r.resolve(domainId, ids) };
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
warn?.(`[external-resolver] '${entity}' ํด์๊ฐ ์คํจํ๋ค โ ${String(e?.message ?? e)}`);
|
|
81
|
+
return { unresolved: 'failed' };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* ๋ฐ์์ ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค์ ๋ชจ์๋ค.
|
|
86
|
+
*
|
|
87
|
+
* ๊ฝํ ๊ฒ์ด ์์ผ๋ฉด **๋น ๋ฐฐ์ด์ด์ง ์ค๋ฅ๊ฐ ์๋๋ค** โ ๋ฐ์์ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด ์๋ ๋์์ด ์ ์์ด๋ค.
|
|
88
|
+
* ๋ค๋ง ใํด์๊ธฐ๊ฐ ์์ด์ ๋ชจ๋ฅธ๋คใ์ ใ์๋คใ๋ ๋ค๋ฅด๋ฏ๋ก, ๊ทธ ๊ตฌ๋ณ์ `externalResolverEntities()` ๋ก
|
|
89
|
+
* ๋ฐ์์ ์ฐ๋ค.
|
|
90
|
+
*/
|
|
91
|
+
async function externalIncoming(domainId, instanceId, axis, itemId, warn) {
|
|
92
|
+
const out = [];
|
|
93
|
+
for (const r of resolvers.values()) {
|
|
94
|
+
if (!r.incoming)
|
|
95
|
+
continue;
|
|
96
|
+
try {
|
|
97
|
+
const got = await r.incoming(domainId, instanceId, axis, itemId);
|
|
98
|
+
/* ๋น ๋ฌถ์์ ์ฃ์ง ์๋๋ค โ ์ฌ๊ธฐ์๋ ใ๊ทธ ์ ํ์ด ์ด ์ถ์ ์ ๋ณธ๋คใ๋ ๋ป์ด๊ณ ํ ๋ง์ด ์๋ค. */
|
|
99
|
+
for (const g of got ?? [])
|
|
100
|
+
if (g && g.total > 0)
|
|
101
|
+
out.push(g);
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
warn?.(`[external-resolver] '${r.entity}' ์ ๋ค์ด์ค๋ ๊ด๊ณ ์กฐํ๊ฐ ์คํจํ๋ค โ ${String(e?.message ?? e)}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=external-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-resolver.js","sourceRoot":"","sources":["../../../server/service/twin-model/external-resolver.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;;AA4DH,4DAUC;AAGD,4DAEC;AAGD,wDAEC;AAQD,0CAcC;AASD,4CAmBC;AA/ED,MAAM,SAAS,GAAG,IAAI,GAAG,EAA4B,CAAA;AAErD;;;;;;GAMG;AACH,SAAgB,wBAAwB,CAAC,CAAmB,EAAE,IAA4B;IACxF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC,2DAA2D,CAAC,CAAA;QACnE,OAAM;IACR,CAAC;IACD,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,IAAI,EAAE,CAAC,wBAAwB,MAAM,8CAA8C,CAAC,CAAA;IACtF,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;AACzC,CAAC;AAED,8CAA8C;AAC9C,SAAgB,wBAAwB;IACtC,OAAO,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;AACrC,CAAC;AAED,wBAAwB;AACxB,SAAgB,sBAAsB;IACpC,SAAS,CAAC,KAAK,EAAE,CAAA;AACnB,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,QAAgB,EAChB,GAAsB,EACtB,IAA4B;IAE5B,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/B,IAAI,CAAC,CAAC,EAAE,OAAO;QAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,CAAA;IACrD,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAA;IACjD,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,IAAI,EAAE,CAAC,wBAAwB,MAAM,gBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,CAAA;QAC/E,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAA;IACjC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,UAAkB,EAClB,IAAY,EACZ,MAAc,EACd,IAA4B;IAE5B,MAAM,GAAG,GAAuB,EAAE,CAAA;IAClC,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,CAAC,QAAQ;YAAE,SAAQ;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YAChE,yDAAyD;YACzD,KAAK,MAAM,CAAC,IAAI,GAAG,IAAI,EAAE;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC;oBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAC9D,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,IAAI,EAAE,CAAC,wBAAwB,CAAC,CAAC,MAAM,0BAA0B,MAAM,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,CAAA;QAC7F,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC","sourcesContent":["/*\n * **board ๋ฐ์ ๊ฐ๋ฆฌํค๋ ๊ด๊ณ๋ฅผ ํธ๋ ์๋ฆฌ** โ ์ ์ธ์ ์๊ณ ์ฝ๋๊ฐ 0๊ณณ์ด๋ ์ด์์.\n *\n * โโ ๋ฌด์์ด ์์๋ (2026-09-05 ์ค์ธก) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ณ์ฝ์ด `target: { kind: 'external', entity: โฆ }` ๋ฅผ ์ ์ธํ๊ณ ์ฃผ์์ ใํด์๋ ํธ์คํธ๊ฐ ํ๋คใ๊ณ \n * ์ ์ด ๋์๋ค. ๊ทธ๋ฐ๋ฐ **`headless-twin/server` ์ด๋์๋ `kind === 'external'` ์ ๋ค๋ฃจ๋ ์ฝ๋๊ฐ\n * ์์๋ค**(0๊ณณ).\n *\n * `space.area` ๊ฐ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ ์ด์ ๋ ์ด์์๊ฐ ์์ด์๊ฐ ์๋๋ผ **ํธ์คํธ์์ ๊ทธ๊ฒ์ด ํ๋ฒํ FK\n * ๋ผ์**๋ค. TypeORM ๋ฉํ๋ฐ์ดํฐ๊ฐ ์ฐ์ฐํ ๋ตํด ์ค ๊ฒ์ด์ง ์ ์ธ์ด ๊ธธ์ ๋ธ ๊ฒ์ด ์๋๋ค.\n *\n * โโ ์ ์ง๊ธ ์ฑ์ฐ๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์์นจ์๋ ใ์๋ฌด๋ ์ ๋งํ์ผ๋ ๊ธํ์ง ์๋คใ๋ก ์ ์๋ค. **๊ทธ ํ๋จ์ด ๊ท๋ชจ๋ฅผ ์๊ฒ ์ก์ ๊ฒ์ด์๋ค.**\n *\n * 360(ํ ๋์์ ๊ฑธ๋ฆฐ ๊ฒ์ ํ์๋ฆฌ์)์ ์๋น์ฒ๋ ๋ฌดํํ ๋์ด๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ฐ ์ ํ์ ์๊ธฐ ์ ์ฅ์๊ฐ\n * ๊ด๊ณ์ ์์ฒ์ด ๋๋ค โ MES ์ ์ค์ ยท์ํ ๊ตฌ๊ฐยท์ ๋น ๊ณํ์ด ๊ทธ๋ ๊ณ , ๋ค์ ์ ํ๋ ๊ทธ๋ด ๊ฒ์ด๋ค.\n *\n * ๊ทธ๋ **์ ์ธ์ ใ๋ฐ์ ๊ฐ๋ฆฌํจ๋คใ๊ณ ๋งํ๋๋ฐ ํธ๋ ๊ธธ์ด ์์ผ๋ฉด ์ ํ๋ง๋ค ์๊ธฐ ๊ธธ์ ๋ธ๋ค.** ๊ทธ๊ฒ์ด\n * ์ ํํ ใ๋ฌดํํ ๊ฐ๋ฆฐ๋คใ๋ค. ์ด ํ์ผ์ด ๊ทธ ๊ฐ๋ฆผ์ ๋ง๋๋ค.\n *\n * โโ ์ปค๋์ ์ด๋ ํ์ธ์ง ๋ชจ๋ฅธ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ๊ณ์ฝ์ ใ์ด ์ถ์ด ๋ฐ์ ๊ฐ๋ฆฌํจ๋คใ๊น์ง๋ง ์๋ค. **ใ์ด๋ ํ์ ์ด๋ ์นธใ์ ์ ํ์ด ์๋ค.** ๊ทธ๋์ ์ ํ์ด\n * ๋ถํ
์์ ํด์๊ธฐ๋ฅผ ๊ฝ๋๋ค โ ์ฅ๋ถ ๊ธฐ๋ก๊ธฐ(`installIngestWindowWriter`)์ ๊ฐ์ ๊ท์จ์ด๋ค.\n *\n * ์ปค๋์ด ํ ์ด๋ฆ์ ์๊ฒ ๋๋ฉด ํ ์ ํ์ ์ ์ฅ ๊ตฌ์กฐ์ ๋งค์ด๊ณ , ๋ค์ ์ ํ์ด ๋ค๋ฅธ ํ๋ฅผ ์ฐ๋ฉด ์ปค๋์ ๋\n * ๊ณ ์ณ์ผ ํ๋ค.\n *\n * โโ ์๋ ๊ฒ์ ์จ๊ธฐ์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ํด์๊ธฐ๊ฐ ์์ผ๋ฉด **๊ทธ ์ฌ์ค์ ๋ธ๋ค**(`unresolved`). ๋งํฌ๋ฅผ ์ง์ฐ๋ฉด ํ๋ฉด์ ใ๊ทธ๋ฐ ๊ด๊ณ๊ฐ ์๋คใ๋ก\n * ์ฝ๊ณ , ์ค์ ๋ก๋ ใ์๋ฌด๋ ๋ตํ ์ ์๋คใ๋ค. ๊ทธ ๋์ ์ฌ๋์ด ํ ์ผ์ด ๋ค๋ฅด๋ค.\n */\n\n/** ๋ฐ์ ์ฌ๋ ๋์ ํ๋ โ ํ๋ฉด์ด ์ด๋ฆ์ ๋ณด์ด๊ณ ๊ฐ ๊ณณ์ ์ ํ ์ ์๊ฒ. */\nexport interface ExternalRef {\n id: string\n /** ์ฌ๋์ด ์ฝ๋ ์ด๋ฆ. ์์ผ๋ฉด ํ๋ฉด์ด id ๋ฅผ ๋ณด์ธ๋ค(์ง์ด๋ด์ง ์๋๋ค). */\n name?: string\n /**\n * ๊ทธ ์ ํ์์ ์ด๊ฒ์ ์ด ์ ์๋ ์๋ฆฌ โ ์์ผ๋ฉด ํ๋ฉด์ด ๋งํฌ๋ฅผ ๋ง๋ค์ง ์๋๋ค.\n *\n * ๋ง๋ค๋ฅธ ๋งํฌ๋ฅผ ๋ง๋ค์ง ์๋ ๊ฒ์ด ์ด ์นธ์ ์์ ์ด๋ค. ๋๋ฌ์ ์๋ฌด ์ผ๋ ์ ์ผ์ด๋๋ฉด ์ฌ๋์ ๊ทธ๊ฒ์\n * ๊ฒฐํจ์ผ๋ก ์ฝ๋๋ค.\n */\n href?: string\n /** ๊ทธ id ๊ฐ ์ค์ ๋ก ์๋ โ **์์ผ๋ฉด ์๋ค๊ณ ๋งํ๋ค.** ๋ต์์ ๋นผ์ง ์๋๋ค. */\n missing?: boolean\n}\n\n/**\n * ๋ฐ์์ ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค โ ๋ค์ด์ค๋ ๊ด๊ณ ํ ๋ฌถ์.\n *\n * `tense` ๋ฅผ **์ ํ์ด ์ ์ธํ๋ค**(๊ณ์ฝ์ `RelationTense`). ์ค์ ยท์ํ ๊ตฌ๊ฐ์ ์ง๋ ์ผ์ด๊ณ ์ ๋น ๊ณํยท\n * ์ง์๋ ์์ ์ผ์ด๋ค โ ใ๊ฑธ๋ฆฐ ๊ฒ์ด ์ดใ์ด ๋ ๋ป์ด ๋๋ ์๋ฆฌ์ด๋ฏ๋ก ๋ฌถ์์ด ์ค์ค๋ก ๋งํด์ผ ํ๋ค.\n */\nexport interface ExternalIncoming {\n /** ๊ด๊ณ์ ์ด๋ฆ(i18n ํค) โ ๊ณ์ฝ์ `via` ์ ๊ฐ์ ๊ท์น. ์ ํ์ ์๊ธฐ ์ ๋๋ฅผ ์ด๋ค. */\n via: string\n /** ์ด๋์ ์ค๋ โ ์ฌ๋์ด ์ฝ๋ ์ถ ์ด๋ฆ์ด ์๋๋ผ ๊ทธ ์ ํ์ ์ถ ํค๋ค. */\n from: string\n /** ์ธ์ ์ ์ผ์ธ๊ฐ. ์ ์ฃผ๋ฉด ใ์ ์ธ์ด ๋งํ์ง ์์๋คใ๋ค โ `standing` ์ผ๋ก ๋ฐ๊พธ์ง ์๋๋ค. */\n tense?: 'past' | 'future' | 'standing'\n ids: string[]\n /** ์ ์ฒด ์ โ `ids` ๊ฐ ์๋ ธ์ด๋ ๋ช์ธ์ง ๋งํ๋ค. */\n total: number\n}\n\n/**\n * ํ external ๋์์ ํธ๋ ์ ํ ์ชฝ ๊ตฌํ.\n *\n * ๋ ๋ค ์ ํ์ด๋ค. ์ด๋ฆ๋ง ๋ ์ค ์ ์๋ ์ ํ๊ณผ ๋ค์ด์ค๋ ๊ด๊ณ๋ง ๋ผ ์ ์๋ ์ ํ์ด ๋ค ์๋ค โ ํ๋๋ง\n * ๊ฝ์๋ ๊ทธ๋งํผ์ ๋ตํด์ง๋ค.\n */\nexport interface ExternalResolver {\n /** ๊ณ์ฝ์ `target.entity` ์ **๊ฐ์ ๋ฑ๋ง**. ๋ค๋ฅด๋ฉด ์๋ฌด ๊ด๊ณ์๋ ์ ๋ถ๋๋ค. */\n entity: string\n /** ์ด id ๋ค์ด ๋ฌด์์ธ๊ฐ. */\n resolve?(domainId: string, ids: readonly string[]): Promise<ExternalRef[]>\n /** ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค. */\n incoming?(domainId: string, instanceId: string, axis: string, itemId: string): Promise<ExternalIncoming[]>\n}\n\nconst resolvers = new Map<string, ExternalResolver>()\n\n/**\n * ํด์๊ธฐ๋ฅผ ๊ฝ๋๋ค โ **๋ถํ
์์ ํ ๋ฒ.**\n *\n * ๊ฐ์ `entity` ๋ฅผ ๋ ๋ฒ ๊ฝ์ผ๋ฉด ๋ค์ฃ๊ฒ์ด ์ด๊ธด๋ค. ๊ทธ๊ฒ์ด ๊ฐ๋ฐ ์ค ์ฌ์ ์ฌ์ ์ ์ ๋์์ด๊ณ , ์ด์์์\n * ์ผ์ด๋๋ฉด ๋ ์ ํ์ด ๊ฐ์ ๋์์ ์๊ธฐ ๊ฒ์ด๋ผ ๋งํ๋ ๊ฒ์ด๋ฏ๋ก **๊ฒฝ๊ณ ๋ฅผ ๋จ๊ธด๋ค** โ ์กฐ์ฉํ ๋ฎ์ผ๋ฉด\n * ์ด๋ ์ชฝ์ด ๋ตํ๊ณ ์๋์ง ์๋ฌด๋ ๋ชจ๋ฅธ๋ค.\n */\nexport function registerExternalResolver(r: ExternalResolver, warn?: (msg: string) => void): void {\n const entity = String(r?.entity ?? '').trim()\n if (!entity) {\n warn?.('[external-resolver] entity ์๋ ํด์๊ธฐ๋ ๊ฝ์ง ์๋๋ค โ ์๋ฌด ๊ด๊ณ์๋ ์ ๋ถ๋๋ค')\n return\n }\n if (resolvers.has(entity)) {\n warn?.(`[external-resolver] '${entity}' ํด์๊ธฐ๋ฅผ ๋ฎ์ด์ด๋ค โ ๋ ์ ํ์ด ๊ฐ์ ๋์์ ๋ตํ๋ ค ํ๋ฉด ๊ทธ์ค ํ๋๋ง ๋ตํ๋ค`)\n }\n resolvers.set(entity, { ...r, entity })\n}\n\n/** ์ง๊ธ ๊ฝํ ์๋ ๊ฒ๋ค โ ใ๋ฌด์์ ํ ์ ์๋ใ๋ฅผ ๋ฐ์์ ์ด ์ ์๊ฒ. */\nexport function externalResolverEntities(): string[] {\n return [...resolvers.keys()].sort()\n}\n\n/** ์ํ์ด ์ฌ๊ธฐ๋์ ๋ฃ์ ์ ์๊ฒ. */\nexport function clearExternalResolvers(): void {\n resolvers.clear()\n}\n\n/**\n * ๊ทธ id ๋ค์ ํผ๋ค โ **๋ชป ํ๋ฉด ๋ชป ํผ๋ค๊ณ ๋งํ๋ค.**\n *\n * ํด์๊ธฐ๊ฐ ํฐ์ ธ๋ 360 ์ ์ฒด๋ฅผ ์ฃฝ์ด์ง ์๋๋ค. ํ ๊ด๊ณ๊ฐ ๋ต์ ๋ชป ํ๋ ๊ฒ๊ณผ ํ๋ฉด์ด ์ ๋จ๋ ๊ฒ์ ๋ค๋ฅธ\n * ์ฌ๊ณ ์ด๊ณ , ๋ค์ฃ๊ฒ์ด ํจ์ฌ ๋์๋ค.\n */\nexport async function resolveExternal(\n entity: string,\n domainId: string,\n ids: readonly string[],\n warn?: (msg: string) => void\n): Promise<{ refs?: ExternalRef[]; unresolved?: 'no-resolver' | 'failed' }> {\n const r = resolvers.get(entity)\n if (!r?.resolve) return { unresolved: 'no-resolver' }\n try {\n return { refs: await r.resolve(domainId, ids) }\n } catch (e: any) {\n warn?.(`[external-resolver] '${entity}' ํด์๊ฐ ์คํจํ๋ค โ ${String(e?.message ?? e)}`)\n return { unresolved: 'failed' }\n }\n}\n\n/**\n * ๋ฐ์์ ์ด ๋์์ ๊ฐ๋ฆฌํค๋ ๊ฒ๋ค์ ๋ชจ์๋ค.\n *\n * ๊ฝํ ๊ฒ์ด ์์ผ๋ฉด **๋น ๋ฐฐ์ด์ด์ง ์ค๋ฅ๊ฐ ์๋๋ค** โ ๋ฐ์์ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด ์๋ ๋์์ด ์ ์์ด๋ค.\n * ๋ค๋ง ใํด์๊ธฐ๊ฐ ์์ด์ ๋ชจ๋ฅธ๋คใ์ ใ์๋คใ๋ ๋ค๋ฅด๋ฏ๋ก, ๊ทธ ๊ตฌ๋ณ์ `externalResolverEntities()` ๋ก\n * ๋ฐ์์ ์ฐ๋ค.\n */\nexport async function externalIncoming(\n domainId: string,\n instanceId: string,\n axis: string,\n itemId: string,\n warn?: (msg: string) => void\n): Promise<ExternalIncoming[]> {\n const out: ExternalIncoming[] = []\n for (const r of resolvers.values()) {\n if (!r.incoming) continue\n try {\n const got = await r.incoming(domainId, instanceId, axis, itemId)\n /* ๋น ๋ฌถ์์ ์ฃ์ง ์๋๋ค โ ์ฌ๊ธฐ์๋ ใ๊ทธ ์ ํ์ด ์ด ์ถ์ ์ ๋ณธ๋คใ๋ ๋ป์ด๊ณ ํ ๋ง์ด ์๋ค. */\n for (const g of got ?? []) if (g && g.total > 0) out.push(g)\n } catch (e: any) {\n warn?.(`[external-resolver] '${r.entity}' ์ ๋ค์ด์ค๋ ๊ด๊ณ ์กฐํ๊ฐ ์คํจํ๋ค โ ${String(e?.message ?? e)}`)\n }\n }\n return out\n}\n"]}
|
|
@@ -104,10 +104,21 @@ async function projectStructure(domainId, instanceId, model, sourceRef) {
|
|
|
104
104
|
const equipment = (model?.equipment ?? [])
|
|
105
105
|
.filter((m) => m?.id)
|
|
106
106
|
.map((m) => {
|
|
107
|
+
/*
|
|
108
|
+
* โโ ์ค๋น๋ ์๋ฆฌ์๋ ๊ตฌ์ญ์๋ ์ค ์ ์๋ค (2026-09-06) โโโโโโโโโโโโโโโโโโโโโ
|
|
109
|
+
* ์๋ฆฌ ๋ชฉ๋ก์์ ๋จผ์ ์ฐพ๊ณ , ์์ผ๋ฉด ๊ตฌ์ญ์์ ์ฐพ๋๋ค. `locations.parentId` ๊ฐ ์ด๋ฏธ ๊ฐ์ ๊ท์จ์
|
|
110
|
+
* ์ด๋ค(ยง`parentIsLocation`).
|
|
111
|
+
*
|
|
112
|
+
* ์ค๋ฌผ์ด ์๋ค โ `EQ-CAM-SHOWER-01`(์์ด์ค์)์ด `LINE-CAM`(๊ตฌ์ญ)์ ๋ธ๋ ค ์๊ณ , ๋ผ์ธ ์ ์ฒด์
|
|
113
|
+
* ๋ถ๋ ์ค๋น๋ ์๋ฆฌ ํ๋๋ฅผ ๊ณ ๋ฅผ ์ ์๋ค. ๊ทธ๋์ ์๋ฆฌ์์๋ง ์ฐพ์์ **๋์ด์ง ์ฐธ์กฐ๋ก ๋ณด๊ณ **ํ๋ค.
|
|
114
|
+
*
|
|
115
|
+
* ๋ง์คํฐ๊ฐ `homeLocationKind: 'area'` ๋ก ๋งํด ์ฃผ์ง๋ง ์ฌ๊ธฐ์๋ ์กฐํ๋ก ํ์ ํ๋ค โ ์ ํธ์์
|
|
116
|
+
* model ์๋ ๊ทธ ์นธ์ด ์๊ณ , ์๋ ๊ฒ์ ๋ชป ์ฐพ์๋ค๊ณ ๋งํ๋ ๊ฒ์ด ๋ ๋์๋ค.
|
|
117
|
+
*/
|
|
107
118
|
const home = m.homeLocation ? locOf.get(m.homeLocation) : undefined;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (m.homeLocation && !home)
|
|
119
|
+
const homeArea = m.homeLocation && !home ? areaOf.get(m.homeLocation) : undefined;
|
|
120
|
+
/* ๋์ด์ง ๊ธฐ์ค ์๋ฆฌ๋ **์ด๋ฆ์ ๋๊ณ ** ๋ณด๊ณ ํ๋ค โ ์๋ฆฌ์๋ ๊ตฌ์ญ์๋ ์์ ๋๋ง์ด๋ค. */
|
|
121
|
+
if (m.homeLocation && !home && !homeArea)
|
|
111
122
|
unresolvedHome.push(`${m.id}โ${m.homeLocation}`);
|
|
112
123
|
return eqRepo.create({
|
|
113
124
|
...scope,
|
|
@@ -122,6 +133,8 @@ async function projectStructure(domainId, instanceId, model, sourceRef) {
|
|
|
122
133
|
/* ๊ฒฐ๊ณผ๊น์ง โ ์ฐธ์กฐ๋ง ์์ผ๋ฉด "๋ฌด์์ผ๋ก ๊ฒ์ฆํ๋ค" ๊น์ง๊ณ , ์๊ฒฉ ์ฑ๋ฆฝ์ ๊ฒฐ๊ณผ๊ฐ ๋งํ๋ค. */
|
|
123
134
|
testResults: m.testResults ?? null,
|
|
124
135
|
homeLocation: home ? { id: home.id } : null,
|
|
136
|
+
/* ๋ ๋ค ์ฐจ๋ ์ผ์ ์๋ค โ ์๋ฆฌ์์ ์ฐพ์์ผ๋ฉด ๊ตฌ์ญ์ ์ ๋ณธ๋ค. */
|
|
137
|
+
homeArea: homeArea ? { id: homeArea.id } : null,
|
|
125
138
|
mtbfMs: m.mtbfMs ?? null,
|
|
126
139
|
mttrMs: m.mttrMs ?? null,
|
|
127
140
|
/* ์ ์ธ๋ ์ ์ฒด์ฑ โ ์์ ์๋ ์ ์ธ์ ์๋ `gs1Id` ๋ฅผ ์ฝ์ด ์ด ์นธ์ด ๋ ๋น์ด ์์๋ค. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-structure.js","sourceRoot":"","sources":["../../../server/service/twin-model/project-structure.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\n\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinArea } from '../twin-space/twin-area.js'\nimport { TwinLocation } from './twin-location.js'\nimport { TwinEquipment } from './twin-equipment.js'\nimport { TwinOperation } from './twin-operation.js'\nimport { readBoardEquipment } from '@operato/ops-contract'\n\n/*\n * ๊ตฌ์กฐ ํฌ์ โ `model`(์ปค๋ ์
๋ ฅ ๋ฌธ์) โ **ํ์ค ์ํฐํฐ ํ**(ADR-0032).\n *\n * โโ ์ ์ ๋ ๊ต์ฒด์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ๋ค์ **์๋ณธ์์ ์จ ์บ์**๋ค(ADR-0032-D). ์๋ณธ์ด ์ง์ค์ด๋ฏ๋ก diff ๋ก ์๋ผ๋ ๊ฒ๋ณด๋ค\n * **๋งค๋ฒ ๊ทธ๋๋ก ๋ค์ ๊ทธ๋ฆฌ๋ ๊ฒ**์ด ๋ง๋ค โ diff ๋ \"์ฐ๋ฆฌ ์ชฝ์ ๋จ๊ฒจ์ผ ํ ๊ฒ์ด ์๋ค\" ๋ ์ ์ ๋ฅผ\n * ๊น๊ณ , ๊ทธ ์ ์ ๊ฐ ์์ ์นจ๋ฒ์ ์์์ด๋ค.\n *\n * ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด ์๋ช
(`TwinStructure.signature`)์ด ๊ฐ์ ๋ ๊ฑด๋๋ฐ๋ ์ฅ์น๊ฐ ์ด๋ฏธ ์์ผ๋ฏ๋ก\n * ๊ทธ๊ฒ์ ์์ ๋๋ค. ์ฌ๊ธฐ์ diff ๋ฅผ ๋ฐ๋ช
ํ์ง ์๋๋ค.\n *\n * โโ ์์๊ฐ ์ค์ํ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ค๋น๊ฐ ์๋ฆฌ๋ฅผ FK ๋ก ๊ฐ๋ฆฌํค๋ฏ๋ก **์๋ฆฌ๋ฅผ ๋จผ์ ** ๋ฃ๋๋ค. ์ง์ฐ๋ ๊ฒ์ ๋ฐ๋ ์์๋ค.\n * (์๋ฆฌ ์ญ์ ์ ์ค๋น์ `homeLocation` ์ `SET NULL` ์ด์ง๋ง, ์ ๋ ๊ต์ฒด์์๋ ๋ ๋ค ์ง์ด๋ค.)\n */\nexport interface ProjectionReport {\n locations: number\n equipment: number\n operations: number\n /** ์๋ฆฌ๋ฅผ ๋ชป ์ฐพ์ ๊ธฐ์ค ์๋ฆฌ๋ฅผ ๋น์ด ์ค๋น โ **์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๋๋ค.** */\n unresolvedHome: string[]\n /** ๊ตฌ์ญ์ ๋ชป ์ฐพ์ ๋น์ด ์๋ฆฌ. ๊ตฌ์ญ์ model ๋ฐ(ํธ์คํธ ๊ฐ๋
)์ด๋ผ ์ด๊ธ๋ ์ ์๋ค. */\n unresolvedArea: string[]\n}\n\n/**\n * ์ด ํธ์์ ๊ตฌ์กฐ ํ์ **์๋ณธ ๊ทธ๋๋ก ๋ค์ ๊ทธ๋ฆฐ๋ค.**\n *\n * `sourceRef` ๋ ์ด๋ ์๋ณธ์์ ์๋์ง๋ค(`ReferenceMaster.source` = instanceId). ์๋ ํ์\n * ๋ง๋ค ์ ์๋ค โ ์บ์๋ผ๋ ์ฌ์ค์ ๊ตฌ์กฐ๋ก ์งํจ๋ค.\n */\nexport async function projectStructure(domainId: string, instanceId: string, model: any, sourceRef: string): Promise<ProjectionReport> {\n const instance = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!instance) throw new Error(`cannot project structure: twin instance \"${instanceId}\" is not registered`)\n\n /*\n * **๊ฐ์ id ๊ฐ ๋์ด๋ฉด ๊ทธ ์ฌ์ค์ ๋งํ๋ค** โ ์ ์ฝ ์๋ฐ ๋ฌธ๊ตฌ๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ณด์ด์ง ์๋๋ค.\n *\n * ์ค์ธก(2026-08-18): ํ์ฅ ๊ฐ์ ๊ทธ ํ์ฅ์ ํธ์ ์ ๋ถ์ ์น๋ค๊ฐ ํ ํธ์์์ ํฌ์์ด ํฐ์ก๋ค. ์ฌ๋ผ์จ ๊ฒ์\n * `SQLITE_CONSTRAINT: UNIQUE constraint failed: twin_equipment...` ๋ฟ์ด๋ผ **๋ฌด์์ด ์๋ชป๋๋์ง ์๋ฌด๋\n * ์ ์ ์์๋ค.** ์์ธ์ ๊ทธ ๋ชจ๋ธ์ ์ค๋น `load-1` ์ด ๋ ๋ฒ ๋ค์ด ์๋ ๊ฒ์ด๋ค(id ๋ ํธ์ ์์์ ์ ์ผํด์ผ\n * ํ๋ค). ์๋ฆฌ์ง ์๊ณ ํ๋๋ง ๋จ๊ธฐ์ง ์๋๋ค โ ๊ทธ๊ฒ์ ๋ชจ๋ธ๋ง ์ค๋ฅ๋ฅผ ๊ฐ์ถ๋ ์ผ์ด๊ณ , ์ด๋ ์ชฝ์ด ๋ง๋์ง ์ฐ๋ฆฌ๋\n * ๋ชจ๋ฅธ๋ค.\n */\n const dupOf = (list: any[] | undefined, what: string): string | undefined => {\n const seen = new Set<string>()\n for (const e of list ?? []) {\n const id = String(e?.id ?? '')\n if (!id) continue\n if (seen.has(id)) return `twin \"${instanceId}\" has two ${what} with id \"${id}\" โ ids must be unique within a twin, so the model cannot be projected`\n seen.add(id)\n }\n return undefined\n }\n const dupMsg = dupOf(model?.locations, 'locations') ?? dupOf(readBoardEquipment(model), 'equipment')\n if (dupMsg) throw new Error(dupMsg)\n\n const locRepo = getRepository(TwinLocation)\n const eqRepo = getRepository(TwinEquipment)\n const opRepo = getRepository(TwinOperation)\n const scope = { domain: { id: domainId } as any, instance: { id: instance.id } as any }\n const ingestedAt = new Date()\n\n /*\n * ์ ๋ ๊ต์ฒด โ ์ด ํ๋ค์ **์๋ณธ์์ ์จ ์บ์**์ด๋ฏ๋ก ๋งค๋ฒ ๊ทธ๋๋ก ๋ค์ ๊ทธ๋ฆฐ๋ค.\n * diff ๋ก ์๋ผ๋ ๊ฒ์ \"์ฐ๋ฆฌ ์ชฝ์ ๋จ๊ฒจ์ผ ํ ๊ฒ์ด ์๋ค\" ๋ ์ ์ ๋ฅผ ๊น๊ณ , ๊ทธ ์ ์ ๊ฐ ์์ ์นจ๋ฒ์ ์์์ด๋ค.\n *\n * **๊ด์ธก์ผ๋ก ์๋ ์์์ ์ฌ๊ธฐ ์ฐ์ง ์๋๋ค.** ์ปค๋์ ๋ง์คํฐ์ ์๋ ์ค๋น๋ ์ด๋ฒคํธ๋ก ์๊ฒ ๋์ง๋ง\n * (`observed-reducer` ์ `origin: 'observed'`), ๊ทธ๊ฒ์ ์ด ํ์ ๋ฐ์ด ๋ฃ์ผ๋ฉด **์ฐ๊ธฐ ๊ฒฝ๋ก๊ฐ ๋**์ด ๋๊ณ \n * ํฑ ๋ฃจํ์์ DB ๋ก ์ฐ๋ ๊ธธ์ด ์๊ธด๋ค(ADR-0032-D ์๋ฐ). ๊ทธ ์ฐจ์ด๋ **์กฐํ ์์ ์ ๋น๊ตํด ๋ณด๊ณ **ํ๋ค โ\n * ์จ๊ฒจ์ผ ํ ๋ถ์ผ์น๊ฐ ์๋๋ผ \"์๋ณธ์ด ๋ชจ๋ฅด๋ ์ค๋น๊ฐ ์คํ ์ค์ด๋ค\" ๋ ์ฌ์ค์ด๋ค.\n */\n await eqRepo.delete(scope)\n await opRepo.delete(scope)\n await locRepo.delete(scope)\n\n /* ๊ตฌ์ญ์ model ๋ฐ์ ์ฐ๋ค(ํธ์คํธ์ TwinArea). ์ด๋ฆ์ผ๋ก ์ฐพ์ FK ๋ฅผ ์๋๋ค. */\n const areas = await getRepository(TwinArea).find({ where: { domain: { id: domainId } as any } })\n const areaOf = new Map(areas.map(a => [a.areaId, a]))\n const unresolvedArea: string[] = []\n\n /*\n * โโ ์ ๊ธฐ ์๋ฅ๋ฅผ ใ๊ตฌ์ญใ์ผ๋ก ์ฝ์ง ์๋๋ค (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์๋ฆฌ์ ๋ถ๋ชจ๊ฐ **๋ค๋ฅธ ์๋ฆฌ**์ผ ์ ์๋ค(๋ถ๊ธฐ์ ์๋ฅ๋ ์์ ์ด๋ค). ๊ทธ ๋ถ๋ชจ๋ฅผ ๊ตฌ์ญ ํ์์ ์ฐพ์ผ๋ฉด ๋น์ฐํ\n * ์๊ณ , ์์ ์๋ ๊ทธ๊ฒ์ ๋งค๋ฒ ใ๊ตฌ์ญ์ด ์ด ํธ์์ ์๋คใ๋ก ๊ฒฝ๊ณ ํ๋ค โ ์๋์ง ํธ์์ ์ธ์ ์คํธํ ๋๋ง๋ค\n * ๋ถ๊ธฐ ์๋งํผ ๊ฑฐ์ง ๊ฒฝ๋ณด๊ฐ ๋ฌ๋ค. ๊ฒฝ๋ณด๊ฐ ์์์ด ๋๋ฉด **์ฌ๋์ด ๊ฒฝ๋ณด ์์ฒด๋ฅผ ์ฝ์ง ์๊ฒ ๋๋ค.**\n *\n * ์๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ถ๋ชจ๋ ๊ณ์ธต(์๋ฆฌ โ ์๋ฆฌ)์ด๊ณ , ๊ตฌ์ญ์ model ๋ฐ์ ๋ค๋ฅธ ํ๋ค. ๊ทธ๋์ ๋ถ๋ชจ๊ฐ ์ด ๋ชจ๋ธ์\n * ์๋ฆฌ์ด๋ฉด ๊ตฌ์ญ ํด์์ **์๋ํ์ง ์๋๋ค**(์๋ ๊ฒ์ ๋ชป ์ฐพ์๋ค๊ณ ๋งํ์ง ์๋๋ค).\n */\n const locationIds = new Set((model?.locations ?? []).filter((l: any) => l?.id).map((l: any) => String(l.id)))\n\n const locations: TwinLocation[] = (model?.locations ?? [])\n .filter((l: any) => l?.id)\n .map((l: any) => {\n const parentIsLocation = l.parentId ? locationIds.has(String(l.parentId)) : false\n const area = l.parentId && !parentIsLocation ? areaOf.get(l.parentId) : undefined\n if (l.parentId && !parentIsLocation && !area) unresolvedArea.push(`${l.id}โ${l.parentId}`)\n return locRepo.create({\n ...scope,\n locationId: l.id,\n /* **์ด๋ฆ์ ์ฎ๊ธด๋ค.** ๋ฒ๋ฆฌ๊ณ ์์๋ค โ ๊ทธ๋์ ํ๋ฉด์ ์๋ฆฌ id ๋ง ๋จ์๋ค(ยงname ์ฃผ์ ์ฐธ์กฐ). */\n name: l.name ?? null,\n description: l.description ?? null,\n type: l.type,\n capacity: l.capacity ?? null,\n parallelism: l.parallelism ?? null,\n area: area ? ({ id: area.id } as any) : null,\n gs1Id: l.gs1Id ?? null,\n /* ์๋ฆฌ์ ์์ฑ๋ ์ฎ๊ธด๋ค โ ์ฎ๊ธฐ์ง ์์ผ๋ฉด ๊ณ์ฝ์ ๋ ฅยท์๊ธ์ด ํญ๋ชฉ ํจ๋์์ ์ฌ๋ผ์ง๋ค(๋ค์ด์จ ๊ฒ์ด ์๋ ๋๋ฝ). */\n properties: l.properties ?? null,\n sourceRef,\n ingestedAt\n } as any)\n })\n const savedLocations = locations.length ? await locRepo.save(locations, { chunk: 500 }) : []\n const locOf = new Map(savedLocations.map(l => [l.locationId, l]))\n\n const unresolvedHome: string[] = []\n const equipment: TwinEquipment[] = (model?.equipment ?? [])\n .filter((m: any) => m?.id)\n .map((m: any) => {\n const home = m.homeLocation ? locOf.get(m.homeLocation) : undefined\n /* ๋์ด์ง ๊ธฐ์ค ์๋ฆฌ๋ **์ด๋ฆ์ ๋๊ณ ** ๋ณด๊ณ ํ๋ค. ์์ ์๋ ํ๋ฉด์ด ๊ฒฝ๊ณ ํ ๋ฟ์ด์๊ณ \n ๋ค๋ฅธ ๊ฒฝ๋ก๋ก ๋ค์ด์จ ๋ฐ์ดํฐ๋ ์๋ฌด๋ ์ ๋ดค๋ค. */\n if (m.homeLocation && !home) unresolvedHome.push(`${m.id}โ${m.homeLocation}`)\n return eqRepo.create({\n ...scope,\n equipmentId: m.id,\n name: m.name ?? null,\n description: m.description ?? null,\n kind: m.kind,\n /* ์์ฑ๋ ์ฎ๊ธด๋ค โ ํ์ ์๋ฆฌ๊ฐ ์์ด ํ๋ฆฌ๊ณ ์์๋ค(์๋น์ฒ๊ฐ ์ค์ ๋ก ์ฝ๋ ์ฌ์ค์ด๋ค: ์ฃผํ ์๋). */\n properties: m.properties ?? null,\n /* ์ํ ์ฐธ์กฐ๋ ํจ๊ป โ ํ๋ฆฌ๋ฉด ๋ช
์ธ ์ชฝ์์ \"๋๊ฐ ๋๋ฅผ ๊ฐ๋ฆฌํค๋\" ์ ์ด ์ค๋น๊ฐ ๋น ์ง๋ค. */\n testSpecificationIds: m.testSpecificationIds ?? null,\n /* ๊ฒฐ๊ณผ๊น์ง โ ์ฐธ์กฐ๋ง ์์ผ๋ฉด \"๋ฌด์์ผ๋ก ๊ฒ์ฆํ๋ค\" ๊น์ง๊ณ , ์๊ฒฉ ์ฑ๋ฆฝ์ ๊ฒฐ๊ณผ๊ฐ ๋งํ๋ค. */\n testResults: m.testResults ?? null,\n homeLocation: home ? ({ id: home.id } as any) : null,\n mtbfMs: m.mtbfMs ?? null,\n mttrMs: m.mttrMs ?? null,\n /* ์ ์ธ๋ ์ ์ฒด์ฑ โ ์์ ์๋ ์ ์ธ์ ์๋ `gs1Id` ๋ฅผ ์ฝ์ด ์ด ์นธ์ด ๋ ๋น์ด ์์๋ค. */\n identity: (m as any).identity ?? null,\n sourceRef,\n ingestedAt\n } as any)\n })\n if (equipment.length) await eqRepo.save(equipment, { chunk: 500 })\n\n const operations: TwinOperation[] = (model?.operations ?? [])\n .filter((o: any) => o?.key)\n .map((o: any, i: number) =>\n opRepo.create({\n ...scope,\n operationKey: o.key,\n /*\n * ๊ณต์ ์ ๋ง์คํฐ๊ฐ `label` ๋ก ๋งํ๋ค โ ํ์์๋ **๊ท์ฝ์ ์ด๋ฆ ํ๋๋ง** ๋๋ค.\n *\n * ํ๋์ `label` ์ปฌ๋ผ๋ ํจ๊ป ๋จ๊ฒจ ๋๋๋ ์กฐํ ํ๋ฉด์ \"์ด๋ฆ\" ์ด์ด **๋ ๊ฐ** ๋ด๋ค(๊ฐ์ ๊ฐ์ด\n * ๋ ๋ฒ). ์ดํ๋ฅผ ํ๋๋ก ํ๋ค๊ณ ํ๋ฉด์ ๋์ ๋จ๊ธฐ๋ฉด ๋ฐ๋์ ์ด๋ ๊ฒ ์์ด ๋์จ๋ค.\n */\n name: o.name ?? o.label ?? null,\n description: o.description ?? null,\n intent: o.intent ?? null,\n locationType: o.locationType ?? null,\n resourceType: o.resourceType ?? null,\n /* ์์์๊ฐ์ ISO 8601 ๋ฌธ์์ด์ด ์ ๋ณธ โ ๋ถ์ผ๋ก ์ค์ด๋ฉด ์ด๊ฐ ์ค๋ฅ ์์ด ์ฌ๋ผ์ง๋ค. */\n duration: o.duration ?? null,\n variability: o.variability ?? null,\n parameters: o.parameters ?? null,\n /* **๋ค ์์ ๋ช
์ธ๋ฅผ ํจ๊ป ์ฎ๊ธด๋ค.** ์
์ด ๋น ์ ธ ์์ด์ ์กฐํ ํ๋ฉด์ด \"์๋ณธ์ด ๋งํ ๊ฐ\" ์ด๋ผ ์ ๊ณ ๋\n ๋ท ์ค ํ๋๋ง ๋ณด์๋ค โ ์ฌ๋์ด ํ์ํ ๊ณต์ ์ ๋ณด๊ณ ์ฌ๋์ด ํ์ ์๋ค๊ณ ๊ฒฐ๋ก ๋ด๊ฒ ๋๋ค. */\n personnelSpecification: o.personnelSpecification ?? null,\n physicalAssetSpecification: o.physicalAssetSpecification ?? null,\n materialSpecification: o.materialSpecification ?? null,\n seq: i,\n sourceRef,\n ingestedAt\n } as any)\n )\n if (operations.length) await opRepo.save(operations, { chunk: 500 })\n\n return {\n locations: savedLocations.length,\n equipment: equipment.length,\n operations: operations.length,\n unresolvedHome,\n unresolvedArea\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"project-structure.js","sourceRoot":"","sources":["../../../server/service/twin-model/project-structure.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository } from '@things-factory/shell'\n\nimport { TwinInstance } from '../twin-instance/twin-instance.js'\nimport { TwinArea } from '../twin-space/twin-area.js'\nimport { TwinLocation } from './twin-location.js'\nimport { TwinEquipment } from './twin-equipment.js'\nimport { TwinOperation } from './twin-operation.js'\nimport { readBoardEquipment } from '@operato/ops-contract'\n\n/*\n * ๊ตฌ์กฐ ํฌ์ โ `model`(์ปค๋ ์
๋ ฅ ๋ฌธ์) โ **ํ์ค ์ํฐํฐ ํ**(ADR-0032).\n *\n * โโ ์ ์ ๋ ๊ต์ฒด์ธ๊ฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ด ํ๋ค์ **์๋ณธ์์ ์จ ์บ์**๋ค(ADR-0032-D). ์๋ณธ์ด ์ง์ค์ด๋ฏ๋ก diff ๋ก ์๋ผ๋ ๊ฒ๋ณด๋ค\n * **๋งค๋ฒ ๊ทธ๋๋ก ๋ค์ ๊ทธ๋ฆฌ๋ ๊ฒ**์ด ๋ง๋ค โ diff ๋ \"์ฐ๋ฆฌ ์ชฝ์ ๋จ๊ฒจ์ผ ํ ๊ฒ์ด ์๋ค\" ๋ ์ ์ ๋ฅผ\n * ๊น๊ณ , ๊ทธ ์ ์ ๊ฐ ์์ ์นจ๋ฒ์ ์์์ด๋ค.\n *\n * ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด ์๋ช
(`TwinStructure.signature`)์ด ๊ฐ์ ๋ ๊ฑด๋๋ฐ๋ ์ฅ์น๊ฐ ์ด๋ฏธ ์์ผ๋ฏ๋ก\n * ๊ทธ๊ฒ์ ์์ ๋๋ค. ์ฌ๊ธฐ์ diff ๋ฅผ ๋ฐ๋ช
ํ์ง ์๋๋ค.\n *\n * โโ ์์๊ฐ ์ค์ํ๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n * ์ค๋น๊ฐ ์๋ฆฌ๋ฅผ FK ๋ก ๊ฐ๋ฆฌํค๋ฏ๋ก **์๋ฆฌ๋ฅผ ๋จผ์ ** ๋ฃ๋๋ค. ์ง์ฐ๋ ๊ฒ์ ๋ฐ๋ ์์๋ค.\n * (์๋ฆฌ ์ญ์ ์ ์ค๋น์ `homeLocation` ์ `SET NULL` ์ด์ง๋ง, ์ ๋ ๊ต์ฒด์์๋ ๋ ๋ค ์ง์ด๋ค.)\n */\nexport interface ProjectionReport {\n locations: number\n equipment: number\n operations: number\n /** ์๋ฆฌ๋ฅผ ๋ชป ์ฐพ์ ๊ธฐ์ค ์๋ฆฌ๋ฅผ ๋น์ด ์ค๋น โ **์๋ฆฌ์ง ์๊ณ ๋๊ธฐ์ง ์๋๋ค.** */\n unresolvedHome: string[]\n /** ๊ตฌ์ญ์ ๋ชป ์ฐพ์ ๋น์ด ์๋ฆฌ. ๊ตฌ์ญ์ model ๋ฐ(ํธ์คํธ ๊ฐ๋
)์ด๋ผ ์ด๊ธ๋ ์ ์๋ค. */\n unresolvedArea: string[]\n}\n\n/**\n * ์ด ํธ์์ ๊ตฌ์กฐ ํ์ **์๋ณธ ๊ทธ๋๋ก ๋ค์ ๊ทธ๋ฆฐ๋ค.**\n *\n * `sourceRef` ๋ ์ด๋ ์๋ณธ์์ ์๋์ง๋ค(`ReferenceMaster.source` = instanceId). ์๋ ํ์\n * ๋ง๋ค ์ ์๋ค โ ์บ์๋ผ๋ ์ฌ์ค์ ๊ตฌ์กฐ๋ก ์งํจ๋ค.\n */\nexport async function projectStructure(domainId: string, instanceId: string, model: any, sourceRef: string): Promise<ProjectionReport> {\n const instance = await getRepository(TwinInstance).findOne({ where: { domain: { id: domainId }, instanceId } })\n if (!instance) throw new Error(`cannot project structure: twin instance \"${instanceId}\" is not registered`)\n\n /*\n * **๊ฐ์ id ๊ฐ ๋์ด๋ฉด ๊ทธ ์ฌ์ค์ ๋งํ๋ค** โ ์ ์ฝ ์๋ฐ ๋ฌธ๊ตฌ๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ณด์ด์ง ์๋๋ค.\n *\n * ์ค์ธก(2026-08-18): ํ์ฅ ๊ฐ์ ๊ทธ ํ์ฅ์ ํธ์ ์ ๋ถ์ ์น๋ค๊ฐ ํ ํธ์์์ ํฌ์์ด ํฐ์ก๋ค. ์ฌ๋ผ์จ ๊ฒ์\n * `SQLITE_CONSTRAINT: UNIQUE constraint failed: twin_equipment...` ๋ฟ์ด๋ผ **๋ฌด์์ด ์๋ชป๋๋์ง ์๋ฌด๋\n * ์ ์ ์์๋ค.** ์์ธ์ ๊ทธ ๋ชจ๋ธ์ ์ค๋น `load-1` ์ด ๋ ๋ฒ ๋ค์ด ์๋ ๊ฒ์ด๋ค(id ๋ ํธ์ ์์์ ์ ์ผํด์ผ\n * ํ๋ค). ์๋ฆฌ์ง ์๊ณ ํ๋๋ง ๋จ๊ธฐ์ง ์๋๋ค โ ๊ทธ๊ฒ์ ๋ชจ๋ธ๋ง ์ค๋ฅ๋ฅผ ๊ฐ์ถ๋ ์ผ์ด๊ณ , ์ด๋ ์ชฝ์ด ๋ง๋์ง ์ฐ๋ฆฌ๋\n * ๋ชจ๋ฅธ๋ค.\n */\n const dupOf = (list: any[] | undefined, what: string): string | undefined => {\n const seen = new Set<string>()\n for (const e of list ?? []) {\n const id = String(e?.id ?? '')\n if (!id) continue\n if (seen.has(id)) return `twin \"${instanceId}\" has two ${what} with id \"${id}\" โ ids must be unique within a twin, so the model cannot be projected`\n seen.add(id)\n }\n return undefined\n }\n const dupMsg = dupOf(model?.locations, 'locations') ?? dupOf(readBoardEquipment(model), 'equipment')\n if (dupMsg) throw new Error(dupMsg)\n\n const locRepo = getRepository(TwinLocation)\n const eqRepo = getRepository(TwinEquipment)\n const opRepo = getRepository(TwinOperation)\n const scope = { domain: { id: domainId } as any, instance: { id: instance.id } as any }\n const ingestedAt = new Date()\n\n /*\n * ์ ๋ ๊ต์ฒด โ ์ด ํ๋ค์ **์๋ณธ์์ ์จ ์บ์**์ด๋ฏ๋ก ๋งค๋ฒ ๊ทธ๋๋ก ๋ค์ ๊ทธ๋ฆฐ๋ค.\n * diff ๋ก ์๋ผ๋ ๊ฒ์ \"์ฐ๋ฆฌ ์ชฝ์ ๋จ๊ฒจ์ผ ํ ๊ฒ์ด ์๋ค\" ๋ ์ ์ ๋ฅผ ๊น๊ณ , ๊ทธ ์ ์ ๊ฐ ์์ ์นจ๋ฒ์ ์์์ด๋ค.\n *\n * **๊ด์ธก์ผ๋ก ์๋ ์์์ ์ฌ๊ธฐ ์ฐ์ง ์๋๋ค.** ์ปค๋์ ๋ง์คํฐ์ ์๋ ์ค๋น๋ ์ด๋ฒคํธ๋ก ์๊ฒ ๋์ง๋ง\n * (`observed-reducer` ์ `origin: 'observed'`), ๊ทธ๊ฒ์ ์ด ํ์ ๋ฐ์ด ๋ฃ์ผ๋ฉด **์ฐ๊ธฐ ๊ฒฝ๋ก๊ฐ ๋**์ด ๋๊ณ \n * ํฑ ๋ฃจํ์์ DB ๋ก ์ฐ๋ ๊ธธ์ด ์๊ธด๋ค(ADR-0032-D ์๋ฐ). ๊ทธ ์ฐจ์ด๋ **์กฐํ ์์ ์ ๋น๊ตํด ๋ณด๊ณ **ํ๋ค โ\n * ์จ๊ฒจ์ผ ํ ๋ถ์ผ์น๊ฐ ์๋๋ผ \"์๋ณธ์ด ๋ชจ๋ฅด๋ ์ค๋น๊ฐ ์คํ ์ค์ด๋ค\" ๋ ์ฌ์ค์ด๋ค.\n */\n await eqRepo.delete(scope)\n await opRepo.delete(scope)\n await locRepo.delete(scope)\n\n /* ๊ตฌ์ญ์ model ๋ฐ์ ์ฐ๋ค(ํธ์คํธ์ TwinArea). ์ด๋ฆ์ผ๋ก ์ฐพ์ FK ๋ฅผ ์๋๋ค. */\n const areas = await getRepository(TwinArea).find({ where: { domain: { id: domainId } as any } })\n const areaOf = new Map(areas.map(a => [a.areaId, a]))\n const unresolvedArea: string[] = []\n\n /*\n * โโ ์ ๊ธฐ ์๋ฅ๋ฅผ ใ๊ตฌ์ญใ์ผ๋ก ์ฝ์ง ์๋๋ค (2026-08-18) โโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์๋ฆฌ์ ๋ถ๋ชจ๊ฐ **๋ค๋ฅธ ์๋ฆฌ**์ผ ์ ์๋ค(๋ถ๊ธฐ์ ์๋ฅ๋ ์์ ์ด๋ค). ๊ทธ ๋ถ๋ชจ๋ฅผ ๊ตฌ์ญ ํ์์ ์ฐพ์ผ๋ฉด ๋น์ฐํ\n * ์๊ณ , ์์ ์๋ ๊ทธ๊ฒ์ ๋งค๋ฒ ใ๊ตฌ์ญ์ด ์ด ํธ์์ ์๋คใ๋ก ๊ฒฝ๊ณ ํ๋ค โ ์๋์ง ํธ์์ ์ธ์ ์คํธํ ๋๋ง๋ค\n * ๋ถ๊ธฐ ์๋งํผ ๊ฑฐ์ง ๊ฒฝ๋ณด๊ฐ ๋ฌ๋ค. ๊ฒฝ๋ณด๊ฐ ์์์ด ๋๋ฉด **์ฌ๋์ด ๊ฒฝ๋ณด ์์ฒด๋ฅผ ์ฝ์ง ์๊ฒ ๋๋ค.**\n *\n * ์๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ถ๋ชจ๋ ๊ณ์ธต(์๋ฆฌ โ ์๋ฆฌ)์ด๊ณ , ๊ตฌ์ญ์ model ๋ฐ์ ๋ค๋ฅธ ํ๋ค. ๊ทธ๋์ ๋ถ๋ชจ๊ฐ ์ด ๋ชจ๋ธ์\n * ์๋ฆฌ์ด๋ฉด ๊ตฌ์ญ ํด์์ **์๋ํ์ง ์๋๋ค**(์๋ ๊ฒ์ ๋ชป ์ฐพ์๋ค๊ณ ๋งํ์ง ์๋๋ค).\n */\n const locationIds = new Set((model?.locations ?? []).filter((l: any) => l?.id).map((l: any) => String(l.id)))\n\n const locations: TwinLocation[] = (model?.locations ?? [])\n .filter((l: any) => l?.id)\n .map((l: any) => {\n const parentIsLocation = l.parentId ? locationIds.has(String(l.parentId)) : false\n const area = l.parentId && !parentIsLocation ? areaOf.get(l.parentId) : undefined\n if (l.parentId && !parentIsLocation && !area) unresolvedArea.push(`${l.id}โ${l.parentId}`)\n return locRepo.create({\n ...scope,\n locationId: l.id,\n /* **์ด๋ฆ์ ์ฎ๊ธด๋ค.** ๋ฒ๋ฆฌ๊ณ ์์๋ค โ ๊ทธ๋์ ํ๋ฉด์ ์๋ฆฌ id ๋ง ๋จ์๋ค(ยงname ์ฃผ์ ์ฐธ์กฐ). */\n name: l.name ?? null,\n description: l.description ?? null,\n type: l.type,\n capacity: l.capacity ?? null,\n parallelism: l.parallelism ?? null,\n area: area ? ({ id: area.id } as any) : null,\n gs1Id: l.gs1Id ?? null,\n /* ์๋ฆฌ์ ์์ฑ๋ ์ฎ๊ธด๋ค โ ์ฎ๊ธฐ์ง ์์ผ๋ฉด ๊ณ์ฝ์ ๋ ฅยท์๊ธ์ด ํญ๋ชฉ ํจ๋์์ ์ฌ๋ผ์ง๋ค(๋ค์ด์จ ๊ฒ์ด ์๋ ๋๋ฝ). */\n properties: l.properties ?? null,\n sourceRef,\n ingestedAt\n } as any)\n })\n const savedLocations = locations.length ? await locRepo.save(locations, { chunk: 500 }) : []\n const locOf = new Map(savedLocations.map(l => [l.locationId, l]))\n\n const unresolvedHome: string[] = []\n const equipment: TwinEquipment[] = (model?.equipment ?? [])\n .filter((m: any) => m?.id)\n .map((m: any) => {\n /*\n * โโ ์ค๋น๋ ์๋ฆฌ์๋ ๊ตฌ์ญ์๋ ์ค ์ ์๋ค (2026-09-06) โโโโโโโโโโโโโโโโโโโโโ\n * ์๋ฆฌ ๋ชฉ๋ก์์ ๋จผ์ ์ฐพ๊ณ , ์์ผ๋ฉด ๊ตฌ์ญ์์ ์ฐพ๋๋ค. `locations.parentId` ๊ฐ ์ด๋ฏธ ๊ฐ์ ๊ท์จ์\n * ์ด๋ค(ยง`parentIsLocation`).\n *\n * ์ค๋ฌผ์ด ์๋ค โ `EQ-CAM-SHOWER-01`(์์ด์ค์)์ด `LINE-CAM`(๊ตฌ์ญ)์ ๋ธ๋ ค ์๊ณ , ๋ผ์ธ ์ ์ฒด์\n * ๋ถ๋ ์ค๋น๋ ์๋ฆฌ ํ๋๋ฅผ ๊ณ ๋ฅผ ์ ์๋ค. ๊ทธ๋์ ์๋ฆฌ์์๋ง ์ฐพ์์ **๋์ด์ง ์ฐธ์กฐ๋ก ๋ณด๊ณ **ํ๋ค.\n *\n * ๋ง์คํฐ๊ฐ `homeLocationKind: 'area'` ๋ก ๋งํด ์ฃผ์ง๋ง ์ฌ๊ธฐ์๋ ์กฐํ๋ก ํ์ ํ๋ค โ ์ ํธ์์\n * model ์๋ ๊ทธ ์นธ์ด ์๊ณ , ์๋ ๊ฒ์ ๋ชป ์ฐพ์๋ค๊ณ ๋งํ๋ ๊ฒ์ด ๋ ๋์๋ค.\n */\n const home = m.homeLocation ? locOf.get(m.homeLocation) : undefined\n const homeArea = m.homeLocation && !home ? areaOf.get(m.homeLocation) : undefined\n /* ๋์ด์ง ๊ธฐ์ค ์๋ฆฌ๋ **์ด๋ฆ์ ๋๊ณ ** ๋ณด๊ณ ํ๋ค โ ์๋ฆฌ์๋ ๊ตฌ์ญ์๋ ์์ ๋๋ง์ด๋ค. */\n if (m.homeLocation && !home && !homeArea) unresolvedHome.push(`${m.id}โ${m.homeLocation}`)\n return eqRepo.create({\n ...scope,\n equipmentId: m.id,\n name: m.name ?? null,\n description: m.description ?? null,\n kind: m.kind,\n /* ์์ฑ๋ ์ฎ๊ธด๋ค โ ํ์ ์๋ฆฌ๊ฐ ์์ด ํ๋ฆฌ๊ณ ์์๋ค(์๋น์ฒ๊ฐ ์ค์ ๋ก ์ฝ๋ ์ฌ์ค์ด๋ค: ์ฃผํ ์๋). */\n properties: m.properties ?? null,\n /* ์ํ ์ฐธ์กฐ๋ ํจ๊ป โ ํ๋ฆฌ๋ฉด ๋ช
์ธ ์ชฝ์์ \"๋๊ฐ ๋๋ฅผ ๊ฐ๋ฆฌํค๋\" ์ ์ด ์ค๋น๊ฐ ๋น ์ง๋ค. */\n testSpecificationIds: m.testSpecificationIds ?? null,\n /* ๊ฒฐ๊ณผ๊น์ง โ ์ฐธ์กฐ๋ง ์์ผ๋ฉด \"๋ฌด์์ผ๋ก ๊ฒ์ฆํ๋ค\" ๊น์ง๊ณ , ์๊ฒฉ ์ฑ๋ฆฝ์ ๊ฒฐ๊ณผ๊ฐ ๋งํ๋ค. */\n testResults: m.testResults ?? null,\n homeLocation: home ? ({ id: home.id } as any) : null,\n /* ๋ ๋ค ์ฐจ๋ ์ผ์ ์๋ค โ ์๋ฆฌ์์ ์ฐพ์์ผ๋ฉด ๊ตฌ์ญ์ ์ ๋ณธ๋ค. */\n homeArea: homeArea ? ({ id: homeArea.id } as any) : null,\n mtbfMs: m.mtbfMs ?? null,\n mttrMs: m.mttrMs ?? null,\n /* ์ ์ธ๋ ์ ์ฒด์ฑ โ ์์ ์๋ ์ ์ธ์ ์๋ `gs1Id` ๋ฅผ ์ฝ์ด ์ด ์นธ์ด ๋ ๋น์ด ์์๋ค. */\n identity: (m as any).identity ?? null,\n sourceRef,\n ingestedAt\n } as any)\n })\n if (equipment.length) await eqRepo.save(equipment, { chunk: 500 })\n\n const operations: TwinOperation[] = (model?.operations ?? [])\n .filter((o: any) => o?.key)\n .map((o: any, i: number) =>\n opRepo.create({\n ...scope,\n operationKey: o.key,\n /*\n * ๊ณต์ ์ ๋ง์คํฐ๊ฐ `label` ๋ก ๋งํ๋ค โ ํ์์๋ **๊ท์ฝ์ ์ด๋ฆ ํ๋๋ง** ๋๋ค.\n *\n * ํ๋์ `label` ์ปฌ๋ผ๋ ํจ๊ป ๋จ๊ฒจ ๋๋๋ ์กฐํ ํ๋ฉด์ \"์ด๋ฆ\" ์ด์ด **๋ ๊ฐ** ๋ด๋ค(๊ฐ์ ๊ฐ์ด\n * ๋ ๋ฒ). ์ดํ๋ฅผ ํ๋๋ก ํ๋ค๊ณ ํ๋ฉด์ ๋์ ๋จ๊ธฐ๋ฉด ๋ฐ๋์ ์ด๋ ๊ฒ ์์ด ๋์จ๋ค.\n */\n name: o.name ?? o.label ?? null,\n description: o.description ?? null,\n intent: o.intent ?? null,\n locationType: o.locationType ?? null,\n resourceType: o.resourceType ?? null,\n /* ์์์๊ฐ์ ISO 8601 ๋ฌธ์์ด์ด ์ ๋ณธ โ ๋ถ์ผ๋ก ์ค์ด๋ฉด ์ด๊ฐ ์ค๋ฅ ์์ด ์ฌ๋ผ์ง๋ค. */\n duration: o.duration ?? null,\n variability: o.variability ?? null,\n parameters: o.parameters ?? null,\n /* **๋ค ์์ ๋ช
์ธ๋ฅผ ํจ๊ป ์ฎ๊ธด๋ค.** ์
์ด ๋น ์ ธ ์์ด์ ์กฐํ ํ๋ฉด์ด \"์๋ณธ์ด ๋งํ ๊ฐ\" ์ด๋ผ ์ ๊ณ ๋\n ๋ท ์ค ํ๋๋ง ๋ณด์๋ค โ ์ฌ๋์ด ํ์ํ ๊ณต์ ์ ๋ณด๊ณ ์ฌ๋์ด ํ์ ์๋ค๊ณ ๊ฒฐ๋ก ๋ด๊ฒ ๋๋ค. */\n personnelSpecification: o.personnelSpecification ?? null,\n physicalAssetSpecification: o.physicalAssetSpecification ?? null,\n materialSpecification: o.materialSpecification ?? null,\n seq: i,\n sourceRef,\n ingestedAt\n } as any)\n )\n if (operations.length) await opRepo.save(operations, { chunk: 500 })\n\n return {\n locations: savedLocations.length,\n equipment: equipment.length,\n operations: operations.length,\n unresolvedHome,\n unresolvedArea\n }\n}\n"]}
|