@things-factory/headless-twin 10.0.8 โ†’ 10.0.10

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.
Files changed (381) hide show
  1. package/dist-server/engine/attention-digest.d.ts +52 -0
  2. package/dist-server/engine/attention-digest.js +76 -0
  3. package/dist-server/engine/attention-digest.js.map +1 -0
  4. package/dist-server/engine/canonical-ingest.d.ts +2 -2
  5. package/dist-server/engine/canonical-ingest.js +24 -2
  6. package/dist-server/engine/canonical-ingest.js.map +1 -1
  7. package/dist-server/engine/command-routing.d.ts +33 -0
  8. package/dist-server/engine/command-routing.js +53 -0
  9. package/dist-server/engine/command-routing.js.map +1 -0
  10. package/dist-server/engine/energy-topology.d.ts +86 -0
  11. package/dist-server/engine/energy-topology.js +144 -0
  12. package/dist-server/engine/energy-topology.js.map +1 -0
  13. package/dist-server/engine/index.d.ts +11 -0
  14. package/dist-server/engine/index.js +17 -0
  15. package/dist-server/engine/index.js.map +1 -1
  16. package/dist-server/engine/kpi-baseline.d.ts +78 -0
  17. package/dist-server/engine/kpi-baseline.js +123 -0
  18. package/dist-server/engine/kpi-baseline.js.map +1 -0
  19. package/dist-server/engine/kpi-fold.d.ts +137 -1
  20. package/dist-server/engine/kpi-fold.js +225 -0
  21. package/dist-server/engine/kpi-fold.js.map +1 -1
  22. package/dist-server/engine/kpi-query.d.ts +32 -1
  23. package/dist-server/engine/kpi-query.js +262 -20
  24. package/dist-server/engine/kpi-query.js.map +1 -1
  25. package/dist-server/engine/kpi-target.d.ts +17 -0
  26. package/dist-server/engine/kpi-target.js +24 -2
  27. package/dist-server/engine/kpi-target.js.map +1 -1
  28. package/dist-server/engine/live-attentions.d.ts +1 -0
  29. package/dist-server/engine/live-attentions.js +7 -1
  30. package/dist-server/engine/live-attentions.js.map +1 -1
  31. package/dist-server/engine/live-feed-registry.d.ts +25 -0
  32. package/dist-server/engine/live-feed-registry.js +51 -0
  33. package/dist-server/engine/live-feed-registry.js.map +1 -0
  34. package/dist-server/engine/load-meter.d.ts +181 -0
  35. package/dist-server/engine/load-meter.js +267 -0
  36. package/dist-server/engine/load-meter.js.map +1 -0
  37. package/dist-server/engine/local-declarations.d.ts +262 -0
  38. package/dist-server/engine/local-declarations.js +528 -0
  39. package/dist-server/engine/local-declarations.js.map +1 -0
  40. package/dist-server/engine/model-basis.d.ts +39 -6
  41. package/dist-server/engine/model-basis.js +69 -9
  42. package/dist-server/engine/model-basis.js.map +1 -1
  43. package/dist-server/engine/model-vocabulary.d.ts +17 -0
  44. package/dist-server/engine/model-vocabulary.js +81 -0
  45. package/dist-server/engine/model-vocabulary.js.map +1 -0
  46. package/dist-server/engine/oee-accumulator.d.ts +28 -0
  47. package/dist-server/engine/oee-accumulator.js +26 -1
  48. package/dist-server/engine/oee-accumulator.js.map +1 -1
  49. package/dist-server/engine/operation-basis.d.ts +32 -0
  50. package/dist-server/engine/operation-basis.js +87 -0
  51. package/dist-server/engine/operation-basis.js.map +1 -0
  52. package/dist-server/engine/property-effects.d.ts +30 -0
  53. package/dist-server/engine/property-effects.js +192 -0
  54. package/dist-server/engine/property-effects.js.map +1 -0
  55. package/dist-server/engine/runtime-key.d.ts +15 -0
  56. package/dist-server/engine/runtime-key.js +64 -0
  57. package/dist-server/engine/runtime-key.js.map +1 -0
  58. package/dist-server/engine/spec-coverage.js +3 -3
  59. package/dist-server/engine/spec-coverage.js.map +1 -1
  60. package/dist-server/engine/state-axes.d.ts +21 -0
  61. package/dist-server/engine/state-axes.js +59 -0
  62. package/dist-server/engine/state-axes.js.map +1 -0
  63. package/dist-server/engine/structure-diff.js +1 -1
  64. package/dist-server/engine/structure-diff.js.map +1 -1
  65. package/dist-server/engine/travel-estimator.d.ts +9 -2
  66. package/dist-server/engine/travel-estimator.js +11 -6
  67. package/dist-server/engine/travel-estimator.js.map +1 -1
  68. package/dist-server/engine/twin-engine.d.ts +418 -57
  69. package/dist-server/engine/twin-engine.js +1599 -306
  70. package/dist-server/engine/twin-engine.js.map +1 -1
  71. package/dist-server/engine/warm-start.d.ts +93 -13
  72. package/dist-server/engine/warm-start.js +114 -14
  73. package/dist-server/engine/warm-start.js.map +1 -1
  74. package/dist-server/index.d.ts +1 -0
  75. package/dist-server/index.js +17 -11
  76. package/dist-server/index.js.map +1 -1
  77. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.d.ts +5 -0
  78. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js +48 -0
  79. package/dist-server/migrations/1786000000000-RenameTwinInstanceBoardToModel.js.map +1 -0
  80. package/dist-server/migrations/index.d.ts +2 -0
  81. package/dist-server/migrations/index.js +10 -0
  82. package/dist-server/migrations/index.js.map +1 -0
  83. package/dist-server/service/index.d.ts +3 -2
  84. package/dist-server/service/index.js +25 -17
  85. package/dist-server/service/index.js.map +1 -1
  86. package/dist-server/service/reference/discovery-result.d.ts +34 -0
  87. package/dist-server/service/reference/discovery-result.js +84 -0
  88. package/dist-server/service/reference/discovery-result.js.map +1 -0
  89. package/dist-server/service/reference/ingest-space.d.ts +53 -0
  90. package/dist-server/service/reference/ingest-space.js +79 -0
  91. package/dist-server/service/reference/ingest-space.js.map +1 -0
  92. package/dist-server/service/reference/knob-defaults.d.ts +20 -0
  93. package/dist-server/service/reference/knob-defaults.js +59 -0
  94. package/dist-server/service/reference/knob-defaults.js.map +1 -0
  95. package/dist-server/service/reference/reference-live.d.ts +23 -0
  96. package/dist-server/service/reference/reference-live.js +123 -6
  97. package/dist-server/service/reference/reference-live.js.map +1 -1
  98. package/dist-server/service/reference/reference-master.d.ts +227 -11
  99. package/dist-server/service/reference/reference-master.js +206 -25
  100. package/dist-server/service/reference/reference-master.js.map +1 -1
  101. package/dist-server/service/reference/reference-resolver.d.ts +33 -3
  102. package/dist-server/service/reference/reference-resolver.js +290 -23
  103. package/dist-server/service/reference/reference-resolver.js.map +1 -1
  104. package/dist-server/service/reference/template-registry.d.ts +19 -3
  105. package/dist-server/service/reference/template-registry.js.map +1 -1
  106. package/dist-server/service/twin-attention/twin-attention-query.d.ts +8 -1
  107. package/dist-server/service/twin-attention/twin-attention-query.js +39 -8
  108. package/dist-server/service/twin-attention/twin-attention-query.js.map +1 -1
  109. package/dist-server/service/twin-audit/command-audit.d.ts +37 -0
  110. package/dist-server/service/twin-audit/command-audit.js +53 -0
  111. package/dist-server/service/twin-audit/command-audit.js.map +1 -0
  112. package/dist-server/service/twin-audit/index.d.ts +4 -0
  113. package/dist-server/service/twin-audit/index.js +8 -0
  114. package/dist-server/service/twin-audit/index.js.map +1 -0
  115. package/dist-server/service/twin-audit/twin-audit-event.d.ts +24 -0
  116. package/dist-server/service/twin-audit/twin-audit-event.js +125 -0
  117. package/dist-server/service/twin-audit/twin-audit-event.js.map +1 -0
  118. package/dist-server/service/twin-audit/twin-audit-query.d.ts +4 -0
  119. package/dist-server/service/twin-audit/twin-audit-query.js +76 -0
  120. package/dist-server/service/twin-audit/twin-audit-query.js.map +1 -0
  121. package/dist-server/service/twin-control/twin-control-mutation.d.ts +2 -0
  122. package/dist-server/service/twin-control/twin-control-mutation.js +50 -11
  123. package/dist-server/service/twin-control/twin-control-mutation.js.map +1 -1
  124. package/dist-server/service/twin-event/twin-event-keys.d.ts +1 -1
  125. package/dist-server/service/twin-event/twin-event-keys.js +1 -1
  126. package/dist-server/service/twin-event/twin-event-keys.js.map +1 -1
  127. package/dist-server/service/twin-event/twin-event.d.ts +14 -5
  128. package/dist-server/service/twin-event/twin-event.js +46 -14
  129. package/dist-server/service/twin-event/twin-event.js.map +1 -1
  130. package/dist-server/service/twin-forecast/forecast-metrics.d.ts +13 -0
  131. package/dist-server/service/twin-forecast/forecast-metrics.js +57 -0
  132. package/dist-server/service/twin-forecast/forecast-metrics.js.map +1 -0
  133. package/dist-server/service/twin-forecast/forecast-tuning.d.ts +12 -0
  134. package/dist-server/service/twin-forecast/forecast-tuning.js +44 -0
  135. package/dist-server/service/twin-forecast/forecast-tuning.js.map +1 -0
  136. package/dist-server/service/twin-forecast/gap-analytics.d.ts +28 -2
  137. package/dist-server/service/twin-forecast/gap-analytics.js +43 -17
  138. package/dist-server/service/twin-forecast/gap-analytics.js.map +1 -1
  139. package/dist-server/service/twin-forecast/twin-forecast-query.js +219 -39
  140. package/dist-server/service/twin-forecast/twin-forecast-query.js.map +1 -1
  141. package/dist-server/service/twin-instance/twin-instance.d.ts +38 -5
  142. package/dist-server/service/twin-instance/twin-instance.js +66 -18
  143. package/dist-server/service/twin-instance/twin-instance.js.map +1 -1
  144. package/dist-server/service/twin-journal/twin-journal-query.d.ts +11 -4
  145. package/dist-server/service/twin-journal/twin-journal-query.js +95 -15
  146. package/dist-server/service/twin-journal/twin-journal-query.js.map +1 -1
  147. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.d.ts +11 -5
  148. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js +46 -27
  149. package/dist-server/service/twin-lifecycle/twin-lifecycle-mutation.js.map +1 -1
  150. package/dist-server/service/twin-metrics/twin-metrics-query.d.ts +1 -0
  151. package/dist-server/service/twin-metrics/twin-metrics-query.js +63 -1
  152. package/dist-server/service/twin-metrics/twin-metrics-query.js.map +1 -1
  153. package/dist-server/service/twin-model/epcis-coverage.d.ts +14 -0
  154. package/dist-server/service/twin-model/epcis-coverage.js +174 -0
  155. package/dist-server/service/twin-model/epcis-coverage.js.map +1 -0
  156. package/dist-server/service/twin-model/iec61850-coverage.d.ts +14 -0
  157. package/dist-server/service/twin-model/iec61850-coverage.js +98 -0
  158. package/dist-server/service/twin-model/iec61850-coverage.js.map +1 -0
  159. package/dist-server/service/twin-model/index.d.ts +13 -0
  160. package/dist-server/service/twin-model/index.js +29 -0
  161. package/dist-server/service/twin-model/index.js.map +1 -0
  162. package/dist-server/service/twin-model/isa95-coverage.d.ts +48 -0
  163. package/dist-server/service/twin-model/isa95-coverage.js +155 -0
  164. package/dist-server/service/twin-model/isa95-coverage.js.map +1 -0
  165. package/dist-server/service/twin-model/project-structure.d.ts +16 -0
  166. package/dist-server/service/twin-model/project-structure.js +173 -0
  167. package/dist-server/service/twin-model/project-structure.js.map +1 -0
  168. package/dist-server/service/twin-model/standard-coverage.d.ts +9 -0
  169. package/dist-server/service/twin-model/standard-coverage.js +37 -0
  170. package/dist-server/service/twin-model/standard-coverage.js.map +1 -0
  171. package/dist-server/service/twin-model/twin-equipment.d.ts +64 -0
  172. package/dist-server/service/twin-model/twin-equipment.js +134 -0
  173. package/dist-server/service/twin-model/twin-equipment.js.map +1 -0
  174. package/dist-server/service/twin-model/twin-lineage-query.d.ts +3 -0
  175. package/dist-server/service/twin-model/twin-lineage-query.js +206 -0
  176. package/dist-server/service/twin-model/twin-lineage-query.js.map +1 -0
  177. package/dist-server/service/twin-model/twin-location.d.ts +58 -0
  178. package/dist-server/service/twin-model/twin-location.js +130 -0
  179. package/dist-server/service/twin-model/twin-location.js.map +1 -0
  180. package/dist-server/service/twin-model/twin-model-item-query.d.ts +141 -0
  181. package/dist-server/service/twin-model/twin-model-item-query.js +852 -0
  182. package/dist-server/service/twin-model/twin-model-item-query.js.map +1 -0
  183. package/dist-server/service/twin-model/twin-model-mutation.d.ts +57 -0
  184. package/dist-server/service/twin-model/twin-model-mutation.js +490 -0
  185. package/dist-server/service/twin-model/twin-model-mutation.js.map +1 -0
  186. package/dist-server/service/twin-model/twin-model-query.d.ts +43 -0
  187. package/dist-server/service/twin-model/twin-model-query.js +551 -0
  188. package/dist-server/service/twin-model/twin-model-query.js.map +1 -0
  189. package/dist-server/service/twin-model/twin-model-tree-query.d.ts +3 -0
  190. package/dist-server/service/twin-model/twin-model-tree-query.js +158 -0
  191. package/dist-server/service/twin-model/twin-model-tree-query.js.map +1 -0
  192. package/dist-server/service/twin-model/twin-operation.d.ts +61 -0
  193. package/dist-server/service/twin-model/twin-operation.js +137 -0
  194. package/dist-server/service/twin-model/twin-operation.js.map +1 -0
  195. package/dist-server/service/twin-space/move-space.d.ts +65 -0
  196. package/dist-server/service/twin-space/move-space.js +166 -0
  197. package/dist-server/service/twin-space/move-space.js.map +1 -0
  198. package/dist-server/service/twin-space/space-integrity.d.ts +97 -0
  199. package/dist-server/service/twin-space/space-integrity.js +182 -0
  200. package/dist-server/service/twin-space/space-integrity.js.map +1 -0
  201. package/dist-server/service/twin-space/twin-space-area.js +4 -4
  202. package/dist-server/service/twin-space/twin-space-area.js.map +1 -1
  203. package/dist-server/service/twin-space/twin-space-representation.js +6 -6
  204. package/dist-server/service/twin-space/twin-space-representation.js.map +1 -1
  205. package/dist-server/service/twin-space/twin-space-resolver.d.ts +63 -1
  206. package/dist-server/service/twin-space/twin-space-resolver.js +365 -18
  207. package/dist-server/service/twin-space/twin-space-resolver.js.map +1 -1
  208. package/dist-server/service/twin-space/twin-space.d.ts +17 -1
  209. package/dist-server/service/twin-space/twin-space.js +15 -5
  210. package/dist-server/service/twin-space/twin-space.js.map +1 -1
  211. package/dist-server/service/twin-state/twin-state-subscription.js +1 -1
  212. package/dist-server/service/twin-state/twin-state-subscription.js.map +1 -1
  213. package/dist-server/service/twin-structure/twin-structure.d.ts +1 -1
  214. package/dist-server/service/twin-structure/twin-structure.js +8 -7
  215. package/dist-server/service/twin-structure/twin-structure.js.map +1 -1
  216. package/dist-server/service/twin-target/twin-target-resolver.js +21 -4
  217. package/dist-server/service/twin-target/twin-target-resolver.js.map +1 -1
  218. package/dist-shared/axis-read.d.ts +12 -0
  219. package/dist-shared/axis-read.js +32 -0
  220. package/dist-shared/axis-read.js.map +1 -0
  221. package/dist-shared/entity-delta.d.ts +29 -0
  222. package/dist-shared/entity-delta.js +287 -0
  223. package/dist-shared/entity-delta.js.map +1 -0
  224. package/dist-shared/kpi-broadcast.d.ts +4 -0
  225. package/dist-shared/kpi-broadcast.js +16 -0
  226. package/dist-shared/kpi-broadcast.js.map +1 -0
  227. package/dist-shared/twin-level.d.ts +23 -0
  228. package/dist-shared/twin-level.js +52 -0
  229. package/dist-shared/twin-level.js.map +1 -0
  230. package/package.json +14 -12
  231. package/server/engine/attention-digest.ts +102 -0
  232. package/server/engine/canonical-ingest.ts +36 -4
  233. package/server/engine/command-routing.ts +67 -0
  234. package/server/engine/energy-topology.ts +189 -0
  235. package/server/engine/index.ts +17 -0
  236. package/server/engine/kpi-baseline.ts +202 -0
  237. package/server/engine/kpi-fold.ts +389 -1
  238. package/server/engine/kpi-query.ts +295 -22
  239. package/server/engine/kpi-target.ts +24 -2
  240. package/server/engine/live-attentions.ts +7 -2
  241. package/server/engine/live-feed-registry.ts +58 -0
  242. package/server/engine/load-meter.ts +384 -0
  243. package/server/engine/local-declarations.ts +700 -0
  244. package/server/engine/model-basis.ts +78 -10
  245. package/server/engine/model-vocabulary.ts +82 -0
  246. package/server/engine/oee-accumulator.ts +34 -1
  247. package/server/engine/operation-basis.ts +100 -0
  248. package/server/engine/property-effects.ts +199 -0
  249. package/server/engine/runtime-key.ts +58 -0
  250. package/server/engine/spec-coverage.ts +3 -3
  251. package/server/engine/state-axes.ts +60 -0
  252. package/server/engine/structure-diff.ts +1 -1
  253. package/server/engine/travel-estimator.ts +11 -6
  254. package/server/engine/twin-engine.ts +1710 -297
  255. package/server/engine/warm-start.ts +207 -22
  256. package/server/index.ts +13 -10
  257. package/server/migrations/1786000000000-RenameTwinInstanceBoardToModel.ts +43 -0
  258. package/server/migrations/index.ts +7 -0
  259. package/server/service/index.ts +9 -1
  260. package/server/service/reference/discovery-result.ts +95 -0
  261. package/server/service/reference/ingest-space.ts +104 -0
  262. package/server/service/reference/knob-defaults.ts +59 -0
  263. package/server/service/reference/reference-live.ts +121 -6
  264. package/server/service/reference/reference-master.ts +362 -35
  265. package/server/service/reference/reference-resolver.ts +307 -23
  266. package/server/service/reference/template-registry.ts +20 -5
  267. package/server/service/twin-attention/twin-attention-query.ts +43 -6
  268. package/server/service/twin-audit/command-audit.ts +81 -0
  269. package/server/service/twin-audit/index.ts +5 -0
  270. package/server/service/twin-audit/twin-audit-event.ts +112 -0
  271. package/server/service/twin-audit/twin-audit-query.ts +72 -0
  272. package/server/service/twin-control/twin-control-mutation.ts +53 -13
  273. package/server/service/twin-event/twin-event-keys.ts +1 -1
  274. package/server/service/twin-event/twin-event.ts +52 -15
  275. package/server/service/twin-forecast/forecast-metrics.ts +60 -0
  276. package/server/service/twin-forecast/forecast-tuning.ts +40 -0
  277. package/server/service/twin-forecast/gap-analytics.ts +48 -9
  278. package/server/service/twin-forecast/twin-forecast-query.ts +211 -38
  279. package/server/service/twin-instance/twin-instance.ts +127 -22
  280. package/server/service/twin-journal/twin-journal-query.ts +108 -14
  281. package/server/service/twin-lifecycle/twin-lifecycle-mutation.ts +40 -23
  282. package/server/service/twin-metrics/twin-metrics-query.ts +60 -3
  283. package/server/service/twin-model/epcis-coverage.ts +195 -0
  284. package/server/service/twin-model/iec61850-coverage.ts +117 -0
  285. package/server/service/twin-model/index.ts +25 -0
  286. package/server/service/twin-model/isa95-coverage.ts +190 -0
  287. package/server/service/twin-model/project-structure.ts +199 -0
  288. package/server/service/twin-model/standard-coverage.ts +35 -0
  289. package/server/service/twin-model/twin-equipment.ts +150 -0
  290. package/server/service/twin-model/twin-lineage-query.ts +193 -0
  291. package/server/service/twin-model/twin-location.ts +140 -0
  292. package/server/service/twin-model/twin-model-item-query.ts +848 -0
  293. package/server/service/twin-model/twin-model-mutation.ts +503 -0
  294. package/server/service/twin-model/twin-model-query.ts +537 -0
  295. package/server/service/twin-model/twin-model-tree-query.ts +180 -0
  296. package/server/service/twin-model/twin-operation.ts +150 -0
  297. package/server/service/twin-space/move-space.ts +262 -0
  298. package/server/service/twin-space/space-integrity.ts +293 -0
  299. package/server/service/twin-space/twin-space-area.ts +4 -4
  300. package/server/service/twin-space/twin-space-representation.ts +6 -6
  301. package/server/service/twin-space/twin-space-resolver.ts +365 -22
  302. package/server/service/twin-space/twin-space.ts +40 -6
  303. package/server/service/twin-state/twin-state-subscription.ts +1 -1
  304. package/server/service/twin-structure/twin-structure.ts +10 -7
  305. package/server/service/twin-target/twin-target-resolver.ts +22 -4
  306. package/shared/axis-read.ts +28 -0
  307. package/shared/entity-delta.ts +286 -0
  308. package/shared/kpi-broadcast.ts +13 -0
  309. package/shared/twin-level.ts +48 -0
  310. package/test/adopt-structure-live.test.ts +133 -0
  311. package/test/attention-digest.test.ts +135 -0
  312. package/test/axis-read.test.ts +87 -0
  313. package/test/boot-resume.test.ts +205 -0
  314. package/test/canonical-ingest-vocabularies.test.ts +118 -0
  315. package/test/capability-mapping.test.ts +5 -5
  316. package/test/command-routing.test.ts +61 -0
  317. package/test/declaration-reaches-model.test.ts +178 -0
  318. package/test/discovery-result.test.ts +75 -0
  319. package/test/energy-topology.test.ts +113 -0
  320. package/test/entity-delta.test.ts +195 -25
  321. package/test/event-time-column.test.ts +67 -0
  322. package/test/forecast-metrics.test.ts +71 -0
  323. package/test/forecast-tuning.test.ts +42 -0
  324. package/test/gap-analytics.test.ts +34 -7
  325. package/test/ingest-bench.test.ts +9 -9
  326. package/test/ingest-running-guard.test.ts +136 -0
  327. package/test/ingest-space.test.ts +78 -0
  328. package/test/instance-cache-lifecycle.test.ts +110 -0
  329. package/test/kernel-kind-guard.test.ts +96 -0
  330. package/test/knob-defaults.test.ts +72 -0
  331. package/test/kpi-baseline-db.test.ts +216 -0
  332. package/test/kpi-baseline.test.ts +196 -0
  333. package/test/kpi-fold.test.ts +393 -2
  334. package/test/kpi-query-bench.test.ts +130 -0
  335. package/test/lineage-survives-restart.test.ts +203 -0
  336. package/test/live-feed-registry.test.ts +67 -0
  337. package/test/live-kernel-facts.test.ts +161 -0
  338. package/test/live-mirror-parity.test.ts +54 -14
  339. package/test/load-meter.test.ts +314 -0
  340. package/test/local-declarations.test.ts +554 -0
  341. package/test/master-to-twin.test.ts +128 -36
  342. package/test/model-basis.test.ts +56 -1
  343. package/test/model-vocabulary.test.ts +114 -0
  344. package/test/move-space.test.ts +149 -0
  345. package/test/mutation-gate.test.ts +122 -0
  346. package/test/oee-accumulator.test.ts +90 -7
  347. package/test/operation-basis.test.ts +100 -0
  348. package/test/operations-capability-db.test.ts +165 -0
  349. package/test/project-structure-db.test.ts +226 -0
  350. package/test/projection-reaches-screen.test.ts +272 -0
  351. package/test/property-effects.test.ts +96 -0
  352. package/test/registry-key-guard.test.ts +80 -0
  353. package/test/resync-origin-site.test.ts +77 -0
  354. package/test/runtime-key.test.ts +66 -0
  355. package/test/scale-twin-bench.test.ts +7 -7
  356. package/test/snapshot-freshness.test.ts +60 -0
  357. package/test/space-integrity.test.ts +223 -0
  358. package/test/standard-coverage.test.ts +94 -0
  359. package/test/state-axes.test.ts +74 -0
  360. package/test/streamline-e2e.test.ts +16 -16
  361. package/test/structure-revision-db.test.ts +16 -15
  362. package/test/tenant-registry-db.test.ts +149 -0
  363. package/test/twin-audit.test.ts +83 -0
  364. package/test/twin-model-item-db.test.ts +275 -0
  365. package/test/twin-model-tree-db.test.ts +176 -0
  366. package/test/twin-origin-resync.test.ts +114 -0
  367. package/test/warm-start-seam.test.ts +140 -0
  368. package/test/warm-start.test.ts +223 -4
  369. package/tsconfig.json +6 -1
  370. package/tsconfig.shared.json +23 -0
  371. package/tsconfig.shared.tsbuildinfo +1 -0
  372. package/tsconfig.tsbuildinfo +1 -0
  373. package/dist-server/engine/entity-delta.d.ts +0 -19
  374. package/dist-server/engine/entity-delta.js +0 -161
  375. package/dist-server/engine/entity-delta.js.map +0 -1
  376. package/dist-server/service/twin-event/backfill-keys.d.ts +0 -11
  377. package/dist-server/service/twin-event/backfill-keys.js +0 -63
  378. package/dist-server/service/twin-event/backfill-keys.js.map +0 -1
  379. package/dist-server/tsconfig.tsbuildinfo +0 -1
  380. package/server/engine/entity-delta.ts +0 -169
  381. package/server/service/twin-event/backfill-keys.ts +0 -72
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TwinAuditEvent = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const typeorm_1 = require("typeorm");
6
+ const type_graphql_1 = require("type-graphql");
7
+ const shell_1 = require("@things-factory/shell");
8
+ /*
9
+ * TwinAuditEvent โ€” **์‚ฌ๋žŒ์ด ๋ฌด์—‡์„ ํ—ˆ๋ฝํ–ˆ๋Š”๊ฐ€.**
10
+ *
11
+ * โ”€โ”€ ์™œ ์ €๋„(TwinEvent)์ด ์•„๋‹Œ๊ฐ€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
12
+ * ์ฒ˜์Œ์—๋Š” ์ €๋„์— ํ•จ๊ป˜ ๋„ฃ์—ˆ๋‹ค. "๊ฐ์‚ฌ๋Š” ์›์žฅ์—์„œ ํ•˜๋‹ˆ๊นŒ" ๋ผ๋Š” ์ด์œ ์˜€๋Š”๋ฐ, ๊ทธ๊ฑด **ํ™”๋ฉด์˜ ํŽธ์˜**์˜€๊ณ 
13
+ * ์ €์žฅ ๊ตฌ์กฐ๋ฅผ ์ •ํ•  ๊ทผ๊ฑฐ๊ฐ€ ๋ชป ๋๋‹ค. ๋„ฃ์ž๋งˆ์ž ์˜ˆ์™ธ๊ฐ€ ๋„ท ์ƒ๊ฒผ๋‹ค โ€” ๋ฆฌํ”Œ๋ ˆ์ด์—์„œ ๋นผ๊ณ , ๋ฐฑํ•„์—์„œ ๋นผ๊ณ ,
14
+ * ์›์žฅ ๊ฑฐ๋ž˜ ๋ถ„๋ฅ˜์—์„œ ๋นผ๊ณ , ์›์žฅ ๋ Œ๋”์—์„œ ๊ฐˆ๋ž๋‹ค. **์˜ˆ์™ธ๊ฐ€ ๋„ท์ด๋ฉด ์„ค๊ณ„๊ฐ€ "์—ฌ๊ธฐ ์•„๋‹ˆ๋‹ค" ๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด๋‹ค.**
15
+ *
16
+ * ๊ฐˆ๋ผ ๋‘๋ฉด ์˜ˆ์™ธ๊ฐ€ 0 ์ด๊ณ , ์˜คํžˆ๋ ค ์–ป๋Š”๋‹ค:
17
+ * ยท ํ–‰์œ„์ž๊ฐ€ **์ปฌ๋Ÿผ**์ด ๋œ๋‹ค โ€” "๋ˆ„๊ฐ€ ์Šน์ธํ•œ ๊ฒƒ ์ „๋ถ€" ๋Š” ๊ฐ์‚ฌ์˜ ๊ธฐ๋ณธ ์งˆ๋ฌธ์ธ๋ฐ payload ์•ˆ์—์„œ๋Š” ๋ชป ์ฐพ์•˜๋‹ค
18
+ * ยท revision ์ด ์—†๋‹ค. ์ €๋„์—์„œ๋Š” ๊ทธ ์นธ์„ ๋น„์›Œ "์ƒํƒœ๊ฐ€ ์•„๋‹˜" ์„ ๋œปํ•˜๊ฒŒ ์ผ๋Š”๋ฐ, ์—†์Œ์„ ์ข…๋ฅ˜ ํ‘œ์‹œ๋กœ
19
+ * ์“ฐ๋Š” ๊ฒƒ์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฌธ์ œ๋ฅผ ๋ƒˆ๋‹ค(๋ฐฑํ•„์˜ `bizStep IS NULL = ์˜› ํ–‰` ์ „์ œ๊ฐ€ ์ด๊ฒƒ ๋•Œ๋ฌธ์— ๊นจ์กŒ๋‹ค)
20
+ * ยท bizStep ์˜ค์—ผ์ด ์—†๋‹ค โ€” ์ €๋„์˜ ํ‚ค ์ถ”์ถœ๊ธฐ๋Š” ๊ฐ’์ด ์—†์œผ๋ฉด ์ด๋ฒคํŠธ ํƒ€์ž…์œผ๋กœ ๋Œ€์ฒดํ•˜๋ฏ€๋กœ,
21
+ * ๊ฐ์‚ฌ ํ–‰์„ ํƒœ์šฐ๋ฉด CBV ํ‘œ์ค€ ์–ดํœ˜ ์ปฌ๋Ÿผ์— `governance.command` ๊ฐ€ ๋ฐ•ํžŒ๋‹ค
22
+ *
23
+ * โ”€โ”€ ๋ฌด์—‡์„ ๋ฏฟ๋Š”๊ฐ€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
24
+ * **์‹ ์›ยท์‹œ๊ฐ์€ ์„œ๋ฒ„๊ฐ€ ๊ฐ์ธํ•œ๋‹ค.** ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งํ•œ ์‹ ์›์„ ๊ทธ๋Œ€๋กœ ์ ์œผ๋ฉด ์œ„์กฐ๊ฐ€ ์ž์œ ๋กœ์›Œ ๊ทธ ๊ธฐ๋ก์€
25
+ * ์•„๋ฌด๊ฒƒ๋„ ์ฆ๋ช…ํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์„ธ์…˜์ด ์•„๋Š” ์‚ฌ์šฉ์ž์™€ ์„œ๋ฒ„ ์‹œ๊ฐ๋งŒ ์‹ ๋ขฐํ•œ๋‹ค.
26
+ * ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ›๋Š” ๊ฒƒ์€ **์˜๋„**๋ฟ์ด๋‹ค โ€” ์–ด๋””์„œ ์‹œ์ž‘๋๋‚˜(origin), ์™œ ํ•˜๋‚˜(reason).
27
+ */
28
+ let TwinAuditEvent = class TwinAuditEvent {
29
+ };
30
+ exports.TwinAuditEvent = TwinAuditEvent;
31
+ tslib_1.__decorate([
32
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
33
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID, { description: 'Unique identifier of the audit record.' }),
34
+ tslib_1.__metadata("design:type", String)
35
+ ], TwinAuditEvent.prototype, "id", void 0);
36
+ tslib_1.__decorate([
37
+ (0, typeorm_1.ManyToOne)(type => shell_1.Domain),
38
+ (0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true, description: 'Owning tenant domain.' }),
39
+ tslib_1.__metadata("design:type", shell_1.Domain)
40
+ ], TwinAuditEvent.prototype, "domain", void 0);
41
+ tslib_1.__decorate([
42
+ (0, typeorm_1.RelationId)((e) => e.domain),
43
+ tslib_1.__metadata("design:type", String)
44
+ ], TwinAuditEvent.prototype, "domainId", void 0);
45
+ tslib_1.__decorate([
46
+ (0, typeorm_1.Column)(),
47
+ (0, type_graphql_1.Field)({ description: 'Twin runtime instance the command was aimed at.' }),
48
+ tslib_1.__metadata("design:type", String)
49
+ ], TwinAuditEvent.prototype, "instanceId", void 0);
50
+ tslib_1.__decorate([
51
+ (0, typeorm_1.Column)({ type: 'datetime' }),
52
+ (0, type_graphql_1.Field)({ description: 'Server time when the command was dispatched.' }),
53
+ tslib_1.__metadata("design:type", Date)
54
+ ], TwinAuditEvent.prototype, "eventTime", void 0);
55
+ tslib_1.__decorate([
56
+ (0, typeorm_1.Column)({ nullable: true }),
57
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Client-supplied command id, for correlating with kernel logs.' }),
58
+ tslib_1.__metadata("design:type", String)
59
+ ], TwinAuditEvent.prototype, "commandId", void 0);
60
+ tslib_1.__decorate([
61
+ (0, typeorm_1.Column)({ nullable: true }),
62
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Command type (e.g. order.hold, equipment.repair).' }),
63
+ tslib_1.__metadata("design:type", String)
64
+ ], TwinAuditEvent.prototype, "commandType", void 0);
65
+ tslib_1.__decorate([
66
+ (0, typeorm_1.Column)({ nullable: true }),
67
+ (0, type_graphql_1.Field)({ nullable: true, description: "Where the command originated: 'user' | 'ai' | 'automation' | 'unknown'." }),
68
+ tslib_1.__metadata("design:type", String)
69
+ ], TwinAuditEvent.prototype, "origin", void 0);
70
+ tslib_1.__decorate([
71
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
72
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Why this action โ€” the rationale shown on the approval card.' }),
73
+ tslib_1.__metadata("design:type", String)
74
+ ], TwinAuditEvent.prototype, "reason", void 0);
75
+ tslib_1.__decorate([
76
+ (0, typeorm_1.Column)({ nullable: true }),
77
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Approving user id, stamped by the server from the session.' }),
78
+ tslib_1.__metadata("design:type", String)
79
+ ], TwinAuditEvent.prototype, "actorId", void 0);
80
+ tslib_1.__decorate([
81
+ (0, typeorm_1.Column)({ nullable: true }),
82
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Approving user email, stamped by the server from the session.' }),
83
+ tslib_1.__metadata("design:type", String)
84
+ ], TwinAuditEvent.prototype, "actorEmail", void 0);
85
+ tslib_1.__decorate([
86
+ (0, typeorm_1.Column)({ nullable: true }),
87
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Approving user name, stamped by the server from the session.' }),
88
+ tslib_1.__metadata("design:type", String)
89
+ ], TwinAuditEvent.prototype, "actorName", void 0);
90
+ tslib_1.__decorate([
91
+ (0, typeorm_1.Column)({ default: false }),
92
+ (0, type_graphql_1.Field)({ description: 'Whether the kernel accepted the command.' }),
93
+ tslib_1.__metadata("design:type", Boolean)
94
+ ], TwinAuditEvent.prototype, "accepted", void 0);
95
+ tslib_1.__decorate([
96
+ (0, typeorm_1.Column)({ nullable: true }),
97
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Language-neutral rejection code when the kernel refused.' }),
98
+ tslib_1.__metadata("design:type", String)
99
+ ], TwinAuditEvent.prototype, "errorCode", void 0);
100
+ tslib_1.__decorate([
101
+ (0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
102
+ (0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'Command arguments as given.' }),
103
+ tslib_1.__metadata("design:type", Object)
104
+ ], TwinAuditEvent.prototype, "args", void 0);
105
+ tslib_1.__decorate([
106
+ (0, typeorm_1.Column)({ default: false }),
107
+ (0, type_graphql_1.Field)({ description: 'True when args were too large and stored truncated.' }),
108
+ tslib_1.__metadata("design:type", Boolean)
109
+ ], TwinAuditEvent.prototype, "argsTruncated", void 0);
110
+ tslib_1.__decorate([
111
+ (0, typeorm_1.CreateDateColumn)(),
112
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Timestamp when the audit row was written.' }),
113
+ tslib_1.__metadata("design:type", Date)
114
+ ], TwinAuditEvent.prototype, "createdAt", void 0);
115
+ exports.TwinAuditEvent = TwinAuditEvent = tslib_1.__decorate([
116
+ (0, typeorm_1.Entity)()
117
+ /* ๋ชฉ๋ก ๊ธฐ๋ณธ ์ •๋ ฌ โ€” ์ตœ๊ทผ ๊ฒƒ๋ถ€ํ„ฐ. ๊ฐ์‚ฌ๋Š” "์š”์ฆ˜ ๋ฌด์Šจ ์ผ์ด ์žˆ์—ˆ๋‚˜" ๋กœ ์‹œ์ž‘ํ•œ๋‹ค. */
118
+ ,
119
+ (0, typeorm_1.Index)('ix_twin_audit_0', (e) => [e.domain, e.instanceId, e.eventTime], { unique: false })
120
+ /* ํ–‰์œ„์ž๋กœ ์ฐพ๊ธฐ โ€” ์ €๋„์— ์žˆ์„ ๋•Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ–ˆ๋˜ ์งˆ๋ฌธ("๊น€ํ˜„์žฅ์ด ์Šน์ธํ•œ ๊ฒƒ ์ „๋ถ€"). */
121
+ ,
122
+ (0, typeorm_1.Index)('ix_twin_audit_1', (e) => [e.domain, e.actorEmail, e.eventTime], { unique: false }),
123
+ (0, type_graphql_1.ObjectType)({ description: 'Audit record of a twin command: who approved what, and what the kernel answered.' })
124
+ ], TwinAuditEvent);
125
+ //# sourceMappingURL=twin-audit-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twin-audit-event.js","sourceRoot":"","sources":["../../../server/service/twin-audit/twin-audit-event.ts"],"names":[],"mappings":";;;;AAAA,qCAAgH;AAChH,+CAAoD;AAEpD,iDAA4D;AAE5D;;;;;;;;;;;;;;;;;;;GAmBG;AAOI,IAAM,cAAc,GAApB,MAAM,cAAc;CAgF1B,CAAA;AAhFY,wCAAc;AAGhB;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;0CAC1D;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;8CAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;;gDAC3B;AAIjB;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;;kDACxD;AAUlB;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAC5B,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;sCAC5D,IAAI;iDAAA;AAIf;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;;iDACtF;AAIlB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;;mDACxE;AAKpB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yEAAyE,EAAE,CAAC;;8CACnG;AAIf;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6DAA6D,EAAE,CAAC;;8CACvF;AAKf;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAAC;;+CACrF;AAIhB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;;kDACrF;AAInB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;;iDACrF;AAKlB;IAFC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;;gDAClD;AAIjB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;;iDACjF;AAQlB;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,6BAA6B,EAAE,CAAC;;4CAClF;AAIV;IAFC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;;qDACxD;AAItB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC;sCACxE,IAAI;iDAAA;yBA/EL,cAAc;IAN1B,IAAA,gBAAM,GAAE;IACT,mDAAmD;;IAClD,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1G,oDAAoD;;IACnD,IAAA,eAAK,EAAC,iBAAiB,EAAE,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACzG,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,kFAAkF,EAAE,CAAC;GACnG,cAAc,CAgF1B","sourcesContent":["import { CreateDateColumn, Entity, Index, Column, RelationId, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'\nimport { ObjectType, Field, ID } from 'type-graphql'\n\nimport { Domain, ScalarObject } from '@things-factory/shell'\n\n/*\n * TwinAuditEvent โ€” **์‚ฌ๋žŒ์ด ๋ฌด์—‡์„ ํ—ˆ๋ฝํ–ˆ๋Š”๊ฐ€.**\n *\n * โ”€โ”€ ์™œ ์ €๋„(TwinEvent)์ด ์•„๋‹Œ๊ฐ€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * ์ฒ˜์Œ์—๋Š” ์ €๋„์— ํ•จ๊ป˜ ๋„ฃ์—ˆ๋‹ค. \"๊ฐ์‚ฌ๋Š” ์›์žฅ์—์„œ ํ•˜๋‹ˆ๊นŒ\" ๋ผ๋Š” ์ด์œ ์˜€๋Š”๋ฐ, ๊ทธ๊ฑด **ํ™”๋ฉด์˜ ํŽธ์˜**์˜€๊ณ \n * ์ €์žฅ ๊ตฌ์กฐ๋ฅผ ์ •ํ•  ๊ทผ๊ฑฐ๊ฐ€ ๋ชป ๋๋‹ค. ๋„ฃ์ž๋งˆ์ž ์˜ˆ์™ธ๊ฐ€ ๋„ท ์ƒ๊ฒผ๋‹ค โ€” ๋ฆฌํ”Œ๋ ˆ์ด์—์„œ ๋นผ๊ณ , ๋ฐฑํ•„์—์„œ ๋นผ๊ณ ,\n * ์›์žฅ ๊ฑฐ๋ž˜ ๋ถ„๋ฅ˜์—์„œ ๋นผ๊ณ , ์›์žฅ ๋ Œ๋”์—์„œ ๊ฐˆ๋ž๋‹ค. **์˜ˆ์™ธ๊ฐ€ ๋„ท์ด๋ฉด ์„ค๊ณ„๊ฐ€ \"์—ฌ๊ธฐ ์•„๋‹ˆ๋‹ค\" ๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด๋‹ค.**\n *\n * ๊ฐˆ๋ผ ๋‘๋ฉด ์˜ˆ์™ธ๊ฐ€ 0 ์ด๊ณ , ์˜คํžˆ๋ ค ์–ป๋Š”๋‹ค:\n * ยท ํ–‰์œ„์ž๊ฐ€ **์ปฌ๋Ÿผ**์ด ๋œ๋‹ค โ€” \"๋ˆ„๊ฐ€ ์Šน์ธํ•œ ๊ฒƒ ์ „๋ถ€\" ๋Š” ๊ฐ์‚ฌ์˜ ๊ธฐ๋ณธ ์งˆ๋ฌธ์ธ๋ฐ payload ์•ˆ์—์„œ๋Š” ๋ชป ์ฐพ์•˜๋‹ค\n * ยท revision ์ด ์—†๋‹ค. ์ €๋„์—์„œ๋Š” ๊ทธ ์นธ์„ ๋น„์›Œ \"์ƒํƒœ๊ฐ€ ์•„๋‹˜\" ์„ ๋œปํ•˜๊ฒŒ ์ผ๋Š”๋ฐ, ์—†์Œ์„ ์ข…๋ฅ˜ ํ‘œ์‹œ๋กœ\n * ์“ฐ๋Š” ๊ฒƒ์ด ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฌธ์ œ๋ฅผ ๋ƒˆ๋‹ค(๋ฐฑํ•„์˜ `bizStep IS NULL = ์˜› ํ–‰` ์ „์ œ๊ฐ€ ์ด๊ฒƒ ๋•Œ๋ฌธ์— ๊นจ์กŒ๋‹ค)\n * ยท bizStep ์˜ค์—ผ์ด ์—†๋‹ค โ€” ์ €๋„์˜ ํ‚ค ์ถ”์ถœ๊ธฐ๋Š” ๊ฐ’์ด ์—†์œผ๋ฉด ์ด๋ฒคํŠธ ํƒ€์ž…์œผ๋กœ ๋Œ€์ฒดํ•˜๋ฏ€๋กœ,\n * ๊ฐ์‚ฌ ํ–‰์„ ํƒœ์šฐ๋ฉด CBV ํ‘œ์ค€ ์–ดํœ˜ ์ปฌ๋Ÿผ์— `governance.command` ๊ฐ€ ๋ฐ•ํžŒ๋‹ค\n *\n * โ”€โ”€ ๋ฌด์—‡์„ ๋ฏฟ๋Š”๊ฐ€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\n * **์‹ ์›ยท์‹œ๊ฐ์€ ์„œ๋ฒ„๊ฐ€ ๊ฐ์ธํ•œ๋‹ค.** ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋งํ•œ ์‹ ์›์„ ๊ทธ๋Œ€๋กœ ์ ์œผ๋ฉด ์œ„์กฐ๊ฐ€ ์ž์œ ๋กœ์›Œ ๊ทธ ๊ธฐ๋ก์€\n * ์•„๋ฌด๊ฒƒ๋„ ์ฆ๋ช…ํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์„ธ์…˜์ด ์•„๋Š” ์‚ฌ์šฉ์ž์™€ ์„œ๋ฒ„ ์‹œ๊ฐ๋งŒ ์‹ ๋ขฐํ•œ๋‹ค.\n * ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ›๋Š” ๊ฒƒ์€ **์˜๋„**๋ฟ์ด๋‹ค โ€” ์–ด๋””์„œ ์‹œ์ž‘๋๋‚˜(origin), ์™œ ํ•˜๋‚˜(reason).\n */\n@Entity()\n/* ๋ชฉ๋ก ๊ธฐ๋ณธ ์ •๋ ฌ โ€” ์ตœ๊ทผ ๊ฒƒ๋ถ€ํ„ฐ. ๊ฐ์‚ฌ๋Š” \"์š”์ฆ˜ ๋ฌด์Šจ ์ผ์ด ์žˆ์—ˆ๋‚˜\" ๋กœ ์‹œ์ž‘ํ•œ๋‹ค. */\n@Index('ix_twin_audit_0', (e: TwinAuditEvent) => [e.domain, e.instanceId, e.eventTime], { unique: false })\n/* ํ–‰์œ„์ž๋กœ ์ฐพ๊ธฐ โ€” ์ €๋„์— ์žˆ์„ ๋•Œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ–ˆ๋˜ ์งˆ๋ฌธ(\"๊น€ํ˜„์žฅ์ด ์Šน์ธํ•œ ๊ฒƒ ์ „๋ถ€\"). */\n@Index('ix_twin_audit_1', (e: TwinAuditEvent) => [e.domain, e.actorEmail, e.eventTime], { unique: false })\n@ObjectType({ description: 'Audit record of a twin command: who approved what, and what the kernel answered.' })\nexport class TwinAuditEvent {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the audit 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: TwinAuditEvent) => e.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Twin runtime instance the command was aimed at.' })\n instanceId: string\n\n /*\n * ์„œ๋ฒ„ ์‹œ๊ฐ. ํด๋ผ์ด์–ธํŠธ ์‹œ๊ณ„๋ฅผ ๋ฏฟ์ง€ ์•Š๋Š”๋‹ค โ€” ๊ธฐ๋ก์˜ ์‹œ๊ฐ„์ถ•์ด ๋‹จ๋ง ์„ค์ •์— ์ขŒ์šฐ๋˜๋ฉด ์•ˆ ๋œ๋‹ค.\n *\n * `datetime` ์„ ์“ด๋‹ค. `timestamp` ๋Š” **sqlite ๊ฐ€ ์ง€์›ํ•˜์ง€ ์•Š์•„** 5๊ฐœ ๋“œ๋ผ์ด๋ฒ„ ๊ณตํ†ต์ด ์•„๋‹ˆ๋‹ค\n * (์‹ค์ œ๋กœ ๊ทธ๋ ‡๊ฒŒ ์ผ๋‹ค๊ฐ€ DB ๋ฅผ ์“ฐ๋Š” ๊ฒ€์‚ฌ 33๊ฐœ๊ฐ€ ํ•œ๊บผ๋ฒˆ์— ํ„ฐ์กŒ๋‹ค).\n */\n @Column({ type: 'datetime' })\n @Field({ description: 'Server time when the command was dispatched.' })\n eventTime: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Client-supplied command id, for correlating with kernel logs.' })\n commandId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Command type (e.g. order.hold, equipment.repair).' })\n commandType?: string\n\n /* 'user' | 'ai' | 'automation' | 'unknown'. ๋ชจ๋ฅด๋ฉด unknown ์ด์ง€ ์‚ฌ๋žŒ์ด ํ•œ ๊ฒƒ์œผ๋กœ ์น˜์ง€ ์•Š๋Š”๋‹ค. */\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"Where the command originated: 'user' | 'ai' | 'automation' | 'unknown'.\" })\n origin?: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Why this action โ€” the rationale shown on the approval card.' })\n reason?: string\n\n /* โ”€โ”€ ์‹ ์›: ์„ธ์…˜์—์„œ๋งŒ ์˜จ๋‹ค โ”€โ”€ */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user id, stamped by the server from the session.' })\n actorId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user email, stamped by the server from the session.' })\n actorEmail?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Approving user name, stamped by the server from the session.' })\n actorName?: string\n\n /* โ”€โ”€ ๊ฒฐ๊ณผ: ๊ฑฐ์ ˆ๋„ ๋‚จ๊ธด๋‹ค โ”€โ”€ */\n @Column({ default: false })\n @Field({ description: 'Whether the kernel accepted the command.' })\n accepted: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Language-neutral rejection code when the kernel refused.' })\n errorCode?: string\n\n /**\n * ๋ช…๋ น ์ธ์ž โ€” **์›ํ˜• ๊ทธ๋Œ€๋กœ.** ๋ฌด์—‡์— ๋Œ€ํ•œ ๋ช…๋ น์ด์—ˆ๋Š”์ง€๊ฐ€ ๊ฐ์‚ฌ์˜ ํ•ต์‹ฌ์ด๋ผ ์š”์•ฝํ•˜์ง€ ์•Š๋Š”๋‹ค.\n * ์ง€๋‚˜์น˜๊ฒŒ ํฌ๋ฉด ์ž๋ฅด๋˜ `argsTruncated` ๋กœ ์ž˜๋ž๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋‚จ๊ธด๋‹ค(์กฐ์šฉํžˆ ๋ฒ„๋ฆฌ์ง€ ์•Š๋Š”๋‹ค).\n */\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => ScalarObject, { nullable: true, description: 'Command arguments as given.' })\n args?: any\n\n @Column({ default: false })\n @Field({ description: 'True when args were too large and stored truncated.' })\n argsTruncated: boolean\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Timestamp when the audit row was written.' })\n createdAt?: Date\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { ListParam } from '@things-factory/shell';
2
+ export declare class TwinAuditQuery {
3
+ twinAuditList(params: ListParam, context: ResolverContext): Promise<any>;
4
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TwinAuditQuery = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const shell_1 = require("@things-factory/shell");
7
+ const twin_audit_event_js_1 = require("./twin-audit-event.js");
8
+ /*
9
+ * ์Šน์ธ ๊ธฐ๋ก ์กฐํšŒ โ€” **๊ฐ์‚ฌ์˜ ๊ธฐ๋ณธ ์งˆ๋ฌธ์— ๋‹ตํ•œ๋‹ค.**
10
+ *
11
+ * "์š”์ฆ˜ ๋ฌด์Šจ ์กฐ์น˜๊ฐ€ ๋‚˜๊ฐ”๋‚˜" โ†’ ์ตœ๊ทผ์ˆœ ๋ชฉ๋ก
12
+ * "๊น€ํ˜„์žฅ์ด ์Šน์ธํ•œ ๊ฒƒ ์ „๋ถ€" โ†’ ํ–‰์œ„์ž ๊ฒ€์ƒ‰(์ธ๋ฑ์Šค ์žˆ์Œ)
13
+ * "AI ๊ฐ€ ์ œ์•ˆํ•œ ๊ฒƒ๋งŒ" โ†’ origin ํ•„ํ„ฐ
14
+ * "๊ฑฐ์ ˆ๋œ ์‹œ๋„" โ†’ accepted ํ•„ํ„ฐ
15
+ *
16
+ * ์ €๋„์— ์„ž์—ฌ ์žˆ์„ ๋•Œ๋Š” ์ด ์ค‘ ์–ด๋А ๊ฒƒ๋„ ๋ชป ํ–ˆ๋‹ค โ€” ํ–‰์œ„์ž๊ฐ€ payload JSON ์•ˆ์ด๋ผ ์ธ๋ฑ์Šค๋ฅผ ๊ฑธ ์ˆ˜ ์—†์—ˆ๋‹ค.
17
+ */
18
+ /** ์‹œ๊ฐ ํ•„ํ„ฐ ๊ฐ’์„ ๋‚ ์งœ๋กœ โ€” ๋ชป ์ฝ๋Š” ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค(์ง€์–ด๋‚ด์ง€ ์•Š๋Š”๋‹ค). */
19
+ function toDateValue(v) {
20
+ const one = (x) => {
21
+ if (x instanceof Date)
22
+ return x;
23
+ const t = typeof x === 'string' ? Date.parse(x) : NaN;
24
+ return Number.isNaN(t) ? x : new Date(t);
25
+ };
26
+ return Array.isArray(v) ? v.map(one) : one(v);
27
+ }
28
+ let TwinAuditQuery = class TwinAuditQuery {
29
+ /* ์กฐํšŒ ๊ฒŒ์ดํŠธ๋Š” ๋‹ฌ์ง€ ์•Š๋Š”๋‹ค โ€” ์ด ์ €์žฅ์†Œ์˜ ๊ทœ์•ฝ์ด๊ณ (mutation-gate ๊ฒ€์‚ฌ๊ฐ€ ์ •๋ณธ์„ ์ง€ํ‚จ๋‹ค),
30
+ ๋„๋ฉ”์ธ ํ•„ํ„ฐ๊ฐ€ ํ…Œ๋„ŒํŠธ ๊ฒฝ๊ณ„๋ฅผ ์ด๋ฏธ ์ง€ํ‚จ๋‹ค. ํ…Œ๋„ŒํŠธ๋ฅผ ๋„˜์–ด ์ฝ๋Š” ๊ณ„๊ธฐํŒ๋งŒ OPS_GATE ๋ฅผ ์“ด๋‹ค. */
31
+ async twinAuditList(params, context) {
32
+ const domainId = context.state.domain?.id;
33
+ if (!domainId)
34
+ return { items: [], total: 0 };
35
+ const effective = {
36
+ ...(params ?? {}),
37
+ /* ๊ธฐ๋ณธ ์ •๋ ฌ โ€” ์ตœ๊ทผ ๊ฒƒ๋ถ€ํ„ฐ. ๊ฐ์‚ฌ๋Š” "์š”์ฆ˜" ์—์„œ ์‹œ์ž‘ํ•œ๋‹ค. */
38
+ sortings: params?.sortings?.length ? params.sortings : [{ name: 'eventTime', desc: true }],
39
+ /* ์‹œ๊ฐ ํ•„ํ„ฐ๋Š” ๋‚ ์งœ๋กœ ์˜ฎ๊ฒจ์„œ ๋„˜๊ธด๋‹ค โ€” ๋ฌธ์ž์—ด ๊ทธ๋Œ€๋กœ๋ฉด ์กฐ์šฉํžˆ 0๊ฑด์ด ๋œ๋‹ค(์ €๋„๊ณผ ๊ฐ™์€ ์ด์œ ). */
40
+ filters: (params?.filters ?? []).map(f => (f.name === 'eventTime' ? { ...f, value: toDateValue(f.value) } : f))
41
+ };
42
+ const qb = (0, shell_1.getQueryBuilderFromListParams)({
43
+ repository: (0, shell_1.getRepository)(twin_audit_event_js_1.TwinAuditEvent),
44
+ params: effective,
45
+ domain: context.state.domain,
46
+ alias: 'a',
47
+ /*
48
+ * `searchables` ๋Š” ์ „๋ถ€ **์‹ค์ปฌ๋Ÿผ**์ด๋‹ค โ€” ํ”„๋ ˆ์ž„์›Œํฌ ์งˆ์˜ ๋นŒ๋”๋Š” ์—ฌ๊ธฐ ์—†๋Š” ์ปฌ๋Ÿผ์˜ LIKE ๋ฅผ
49
+ * ๊ฒฝ๊ณ  ํ›„ ๋ฌด์‹œํ•œ๋‹ค(์ธ๋ฑ์Šค ์—†๋Š” ์ „์ฒด ์Šค์บ” ๋ฐฉ์ง€). ํ–‰์œ„์ž๋กœ ์ฐพ๋Š” ๊ฒƒ์ด ์ด ํ…Œ์ด๋ธ”์„ ๊ตฌ๋ถ„ํ•œ ์ด์œ ๋‹ค.
50
+ */
51
+ searchables: ['actorEmail', 'actorName', 'commandType', 'origin', 'errorCode', 'reason'],
52
+ sortables: ['eventTime', 'commandType', 'actorEmail', 'origin', 'accepted'],
53
+ /* ๊ฐ์‚ฌ ๋ชฉ๋ก์€ ์‚ฌ๋žŒ์ด ์ฝ๋Š” ์†๋„๋กœ ๋ณธ๋‹ค โ€” ํฌ๊ฒŒ ํผ ์˜ค๋Š” ๊ฒƒ์ด ์ด๋“์ด ์•„๋‹ˆ๋‹ค. */
54
+ defaultLimit: 50,
55
+ maxLimit: 200
56
+ });
57
+ const [items, total] = await qb.getManyAndCount();
58
+ return { items, total };
59
+ }
60
+ };
61
+ exports.TwinAuditQuery = TwinAuditQuery;
62
+ tslib_1.__decorate([
63
+ (0, type_graphql_1.Query)(returns => shell_1.ScalarObject, {
64
+ nullable: true,
65
+ description: 'List twin command audit records (who approved what, and what the kernel answered) with the standard list contract, plus the total match count.'
66
+ }),
67
+ tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
68
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
69
+ tslib_1.__metadata("design:type", Function),
70
+ tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
71
+ tslib_1.__metadata("design:returntype", Promise)
72
+ ], TwinAuditQuery.prototype, "twinAuditList", null);
73
+ exports.TwinAuditQuery = TwinAuditQuery = tslib_1.__decorate([
74
+ (0, type_graphql_1.Resolver)()
75
+ ], TwinAuditQuery);
76
+ //# sourceMappingURL=twin-audit-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twin-audit-query.js","sourceRoot":"","sources":["../../../server/service/twin-audit/twin-audit-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Args, Ctx, Query, Resolver } from 'type-graphql'\n\nimport { ListParam, getQueryBuilderFromListParams, getRepository, ScalarObject } from '@things-factory/shell'\n\nimport { TwinAuditEvent } from './twin-audit-event.js'\n\n/*\n * ์Šน์ธ ๊ธฐ๋ก ์กฐํšŒ โ€” **๊ฐ์‚ฌ์˜ ๊ธฐ๋ณธ ์งˆ๋ฌธ์— ๋‹ตํ•œ๋‹ค.**\n *\n * \"์š”์ฆ˜ ๋ฌด์Šจ ์กฐ์น˜๊ฐ€ ๋‚˜๊ฐ”๋‚˜\" โ†’ ์ตœ๊ทผ์ˆœ ๋ชฉ๋ก\n * \"๊น€ํ˜„์žฅ์ด ์Šน์ธํ•œ ๊ฒƒ ์ „๋ถ€\" โ†’ ํ–‰์œ„์ž ๊ฒ€์ƒ‰(์ธ๋ฑ์Šค ์žˆ์Œ)\n * \"AI ๊ฐ€ ์ œ์•ˆํ•œ ๊ฒƒ๋งŒ\" โ†’ origin ํ•„ํ„ฐ\n * \"๊ฑฐ์ ˆ๋œ ์‹œ๋„\" โ†’ accepted ํ•„ํ„ฐ\n *\n * ์ €๋„์— ์„ž์—ฌ ์žˆ์„ ๋•Œ๋Š” ์ด ์ค‘ ์–ด๋А ๊ฒƒ๋„ ๋ชป ํ–ˆ๋‹ค โ€” ํ–‰์œ„์ž๊ฐ€ payload JSON ์•ˆ์ด๋ผ ์ธ๋ฑ์Šค๋ฅผ ๊ฑธ ์ˆ˜ ์—†์—ˆ๋‹ค.\n */\n/** ์‹œ๊ฐ ํ•„ํ„ฐ ๊ฐ’์„ ๋‚ ์งœ๋กœ โ€” ๋ชป ์ฝ๋Š” ๊ฐ’์€ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค(์ง€์–ด๋‚ด์ง€ ์•Š๋Š”๋‹ค). */\nfunction toDateValue(v: any): any {\n const one = (x: any) => {\n if (x instanceof Date) return x\n const t = typeof x === 'string' ? Date.parse(x) : NaN\n return Number.isNaN(t) ? x : new Date(t)\n }\n return Array.isArray(v) ? v.map(one) : one(v)\n}\n\n@Resolver()\nexport class TwinAuditQuery {\n /* ์กฐํšŒ ๊ฒŒ์ดํŠธ๋Š” ๋‹ฌ์ง€ ์•Š๋Š”๋‹ค โ€” ์ด ์ €์žฅ์†Œ์˜ ๊ทœ์•ฝ์ด๊ณ (mutation-gate ๊ฒ€์‚ฌ๊ฐ€ ์ •๋ณธ์„ ์ง€ํ‚จ๋‹ค),\n ๋„๋ฉ”์ธ ํ•„ํ„ฐ๊ฐ€ ํ…Œ๋„ŒํŠธ ๊ฒฝ๊ณ„๋ฅผ ์ด๋ฏธ ์ง€ํ‚จ๋‹ค. ํ…Œ๋„ŒํŠธ๋ฅผ ๋„˜์–ด ์ฝ๋Š” ๊ณ„๊ธฐํŒ๋งŒ OPS_GATE ๋ฅผ ์“ด๋‹ค. */\n @Query(returns => ScalarObject, {\n nullable: true,\n description:\n 'List twin command audit records (who approved what, and what the kernel answered) with the standard list contract, plus the total match count.'\n })\n async twinAuditList(\n /* ํ‘œ์ค€ ๋ชฉ๋ก ๊ณ„์•ฝ์€ `@Args` ๋กœ ํŽผ์ณ ๋ฐ›๋Š”๋‹ค โ€” `@Arg` ๋กœ ๋ฐ›์œผ๋ฉด type-graphql ์ด ์ž…๋ ฅ ํƒ€์ž…์„\n ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•ด **์Šคํ‚ค๋งˆ ์กฐ๋ฆฝ ์ž์ฒด๊ฐ€ ์‹คํŒจ**ํ•œ๋‹ค(์„œ๋ฒ„๊ฐ€ ์•„์˜ˆ ์•ˆ ๋œฌ๋‹ค). */\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<any> {\n const domainId = context.state.domain?.id\n if (!domainId) return { items: [], total: 0 }\n\n const effective: ListParam = {\n ...(params ?? ({} as ListParam)),\n /* ๊ธฐ๋ณธ ์ •๋ ฌ โ€” ์ตœ๊ทผ ๊ฒƒ๋ถ€ํ„ฐ. ๊ฐ์‚ฌ๋Š” \"์š”์ฆ˜\" ์—์„œ ์‹œ์ž‘ํ•œ๋‹ค. */\n sortings: params?.sortings?.length ? params.sortings : [{ name: 'eventTime', desc: true }],\n /* ์‹œ๊ฐ ํ•„ํ„ฐ๋Š” ๋‚ ์งœ๋กœ ์˜ฎ๊ฒจ์„œ ๋„˜๊ธด๋‹ค โ€” ๋ฌธ์ž์—ด ๊ทธ๋Œ€๋กœ๋ฉด ์กฐ์šฉํžˆ 0๊ฑด์ด ๋œ๋‹ค(์ €๋„๊ณผ ๊ฐ™์€ ์ด์œ ). */\n filters: (params?.filters ?? []).map(f => (f.name === 'eventTime' ? { ...f, value: toDateValue(f.value) } : f))\n }\n\n const qb = getQueryBuilderFromListParams({\n repository: getRepository(TwinAuditEvent),\n params: effective,\n domain: context.state.domain,\n alias: 'a',\n /*\n * `searchables` ๋Š” ์ „๋ถ€ **์‹ค์ปฌ๋Ÿผ**์ด๋‹ค โ€” ํ”„๋ ˆ์ž„์›Œํฌ ์งˆ์˜ ๋นŒ๋”๋Š” ์—ฌ๊ธฐ ์—†๋Š” ์ปฌ๋Ÿผ์˜ LIKE ๋ฅผ\n * ๊ฒฝ๊ณ  ํ›„ ๋ฌด์‹œํ•œ๋‹ค(์ธ๋ฑ์Šค ์—†๋Š” ์ „์ฒด ์Šค์บ” ๋ฐฉ์ง€). ํ–‰์œ„์ž๋กœ ์ฐพ๋Š” ๊ฒƒ์ด ์ด ํ…Œ์ด๋ธ”์„ ๊ตฌ๋ถ„ํ•œ ์ด์œ ๋‹ค.\n */\n searchables: ['actorEmail', 'actorName', 'commandType', 'origin', 'errorCode', 'reason'],\n sortables: ['eventTime', 'commandType', 'actorEmail', 'origin', 'accepted'],\n /* ๊ฐ์‚ฌ ๋ชฉ๋ก์€ ์‚ฌ๋žŒ์ด ์ฝ๋Š” ์†๋„๋กœ ๋ณธ๋‹ค โ€” ํฌ๊ฒŒ ํผ ์˜ค๋Š” ๊ฒƒ์ด ์ด๋“์ด ์•„๋‹ˆ๋‹ค. */\n defaultLimit: 50,\n maxLimit: 200\n })\n\n const [items, total] = await qb.getManyAndCount()\n return { items, total }\n }\n}\n"]}
@@ -3,6 +3,8 @@ export declare class TwinControlMutation {
3
3
  dispatchTwinCommand(instanceId: string, command: any, context: ResolverContext): Promise<{
4
4
  accepted: boolean;
5
5
  error?: string;
6
+ errorCode?: string;
7
+ errorParams?: Record<string, string | number>;
6
8
  }>;
7
9
  /** Scenario ์ฑ„๋„ โ€” ์ƒ์„ฑ๊ธฐ ์‹œ๋‚˜๋ฆฌ์˜ค ์ œ์–ด(load/start/pause/setSpeed). */
8
10
  controlTwinScenario(instanceId: string, action: string, context: ResolverContext, scenario?: any): Promise<boolean>;
@@ -3,8 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TwinControlMutation = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const type_graphql_1 = require("type-graphql");
6
+ const twin_kernel_1 = require("@operato/twin-kernel");
6
7
  const shell_1 = require("@things-factory/shell");
8
+ const shell_2 = require("@things-factory/shell");
7
9
  const index_js_1 = require("../../engine/index.js");
10
+ const twin_audit_event_js_1 = require("../twin-audit/twin-audit-event.js");
11
+ const command_audit_js_1 = require("../twin-audit/command-audit.js");
8
12
  /*
9
13
  * ํŠธ์œˆ CommandยทScenario ์ฑ„๋„ โ€” ์ƒํ–ฅ mutation.
10
14
  * Command: runtime.dispatch(ํ–‰์œ„). Scenario: runtime.scenario.load/start/pause/setSpeed(์˜ˆ์ธก ์ž๊ทน).
@@ -17,31 +21,64 @@ let TwinControlMutation = class TwinControlMutation {
17
21
  /** Command ์ฑ„๋„ โ€” ์˜ค๋” hold/resume/release ๋“ฑ. ์ปค๋„ dispatch ๋กœ ์œ„์ž„, ack{accepted,error} ๋ฐ˜ํ™˜. */
18
22
  async dispatchTwinCommand(instanceId, command, context) {
19
23
  const domainId = context.state.domain?.id;
20
- const inst = index_js_1.TwinEngine.instances[instanceId];
21
- if (!inst || inst.domainId !== domainId) {
22
- return { accepted: false, error: 'instance not found in your domain' };
23
- }
24
- /* tenantId ๋ฅผ ํ˜ธ์ถœ์ž ๋„๋ฉ”์ธ์œผ๋กœ ๊ฐ์ธ(๊ฐ์‚ฌยท๋ฌด๊ฒฐ์„ฑ) โ€” ํด๋ผ ์œ„์กฐ ๋ฐฉ์ง€. */
25
- const ack = inst.runtime.dispatch({ ...command, tenantId: domainId });
26
- /* ๋ผ์ด๋ธŒ ๊ตฌ์กฐ ๋ณ€์ด(resource.add)๋Š” ์ €์žฅ board ์—๋„ ๋ฐ˜์˜ โ€” ํ”„๋กœ๋น„์ €๋‹ ํŽธ์ง‘๊ธฐยท์žฌ๊ธฐ๋™์ด ์ถ”๊ฐ€๋ถ„์„ ์žƒ์ง€ ์•Š๊ฒŒ. */
24
+ if (!domainId)
25
+ return { accepted: false, error: 'no-domain', errorCode: 'no-domain' };
26
+ /*
27
+ * ๋ผ์šฐํŒ…์€ ์—”์ง„์ด ํ•œ๋‹ค โ€” ์˜ˆ์ „์—๋Š” ์—ฌ๊ธฐ์„œ `inst.runtime.dispatch` ๋ฅผ ๊ณง๋ฐ”๋กœ ๋ถˆ๋ €๊ณ , `runtime` ์ด
28
+ * ์‹œ๋ฎฌ์—๋งŒ ์žˆ์–ด์„œ ๋ฏธ๋Ÿฌ ํŠธ์œˆ์—์„œ๋Š” ์ด ํ•œ ์ค„์ด TypeError ๋กœ ํ„ฐ์กŒ๋‹ค(๊น”๋”ํ•œ ๊ฑฐ์ ˆ์ด ์•„๋‹ˆ๋ผ ์‹คํŒจ).
29
+ * ๊ถŒ์œ„(๋ชจ๋“œ) ร— ์„ฑ๊ฒฉ(์ฃผ์„/์•ก์ถ”์—์ด์…˜) ํŒ์ •์€ ํ•œ ๊ณณ์—๋งŒ ๋‘”๋‹ค.
30
+ */
31
+ /* ์›๋ณธ์„ ๊ทธ๋Œ€๋กœ ๊ฐ์‚ฌ์— ๋„˜๊ธด๋‹ค โ€” ๋ฌด์—‡์ด ๋“ค์–ด์™”๋Š”์ง€๊ฐ€ ๊ธฐ๋ก์˜ ๋Œ€์ƒ์ด๋‹ค(์ •๊ทœํ™”๋Š” ๊ฐ์‚ฌ ๋ชจ๋“ˆ์ด ํ•œ๋‹ค). */
32
+ const cmdWithOrigin = command;
33
+ const ack = await index_js_1.TwinEngine.dispatchCommand(domainId, instanceId, command);
34
+ /* ๋ผ์ด๋ธŒ ๊ตฌ์กฐ ๋ณ€์ด(resource.add)๋Š” ์ €์žฅ model ์—๋„ ๋ฐ˜์˜ โ€” ํ”„๋กœ๋น„์ €๋‹ ํŽธ์ง‘๊ธฐยท์žฌ๊ธฐ๋™์ด ์ถ”๊ฐ€๋ถ„์„ ์žƒ์ง€ ์•Š๊ฒŒ. */
27
35
  if (ack?.accepted && command?.type === 'resource.add') {
28
36
  await index_js_1.TwinEngine.syncBoardEquipment(domainId, instanceId).catch(err => console.error('twin syncBoardEquipment fail', err));
29
37
  }
30
- return { accepted: !!ack?.accepted, error: ack?.error };
38
+ /*
39
+ * ๊ฐ์‚ฌ ๊ธฐ๋ก โ€” ์Šน์ธ ๊ฒŒ์ดํŠธ๊ฐ€ ์•ž์„ ๋ง‰๊ณ , ์ด ์ค„์ด ๋’ค๋ฅผ ์„ค๋ช…ํ•œ๋‹ค. ๋‘˜ ๋‹ค ์žˆ์–ด์•ผ "์‚ฌ๋žŒ ์†์„ ๊ฑฐ์ณค๋‹ค" ๋ฅผ
40
+ * ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ปค๋„์ด ๊ฑฐ์ ˆํ•œ ๊ฒƒ๋„ ๋‚จ๊ธด๋‹ค โ€” ๋ฌด์—‡์„ ์‹œ๋„ํ–ˆ๋Š”์ง€๊ฐ€ ๊ฐ์‚ฌ์˜ ์ ˆ๋ฐ˜์ด๋‹ค.
41
+ *
42
+ * ๊ธฐ๋ก์ด ์‹คํŒจํ•ด๋„ ์ปค๋งจ๋“œ ๊ฒฐ๊ณผ๋Š” ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค€๋‹ค. ๊ฐ์‚ฌ๊ฐ€ ๋ณธ์—…์„ ๋ง‰์œผ๋ฉด ์•ˆ ๋˜์ง€๋งŒ, ์‹คํŒจ๋ฅผ ์‚ผํ‚ค์ง€๋„
43
+ * ์•Š๋Š”๋‹ค(๋กœ๊ทธ์— ๋‚จ๊ธด๋‹ค) โ€” ์กฐ์šฉํžˆ ์•ˆ ๋‚จ์œผ๋ฉด ๋‚˜์ค‘์— "๊ธฐ๋ก์ด ์—†๋‹ค" ์™€ "์ผ์ด ์—†์—ˆ๋‹ค" ๋ฅผ ๊ตฌ๋ถ„ ๋ชป ํ•œ๋‹ค.
44
+ */
45
+ try {
46
+ const audit = (0, command_audit_js_1.buildCommandAudit)({ command: cmdWithOrigin, ack, actor: context.state.user, at: new Date() });
47
+ const repo = (0, shell_2.getRepository)(twin_audit_event_js_1.TwinAuditEvent);
48
+ await repo.save(repo.create({ domain: context.state.domain, instanceId, ...audit }));
49
+ }
50
+ catch (err) {
51
+ console.error(`[twin-control] command audit not recorded for "${instanceId}"`, err);
52
+ }
53
+ /* ๊ฑฐ์ ˆ ์‚ฌ์œ ๋Š” **์–ธ์–ด ์ค‘๋ฆฝ ์ฝ”๋“œ**๋กœ ํ•จ๊ป˜ ๋Œ๋ ค์ค€๋‹ค โ€” ํ™”๋ฉด์ด `twin.cmderr.<code>` ๋กœ ์‚ฌ๋žŒ ๋ง์„ ๋งŒ๋“ ๋‹ค. */
54
+ return { accepted: !!ack?.accepted, error: ack?.error, errorCode: ack?.errorCode, errorParams: ack?.errorParams };
31
55
  }
32
56
  /** Scenario ์ฑ„๋„ โ€” ์ƒ์„ฑ๊ธฐ ์‹œ๋‚˜๋ฆฌ์˜ค ์ œ์–ด(load/start/pause/setSpeed). */
33
57
  async controlTwinScenario(instanceId, action, context, scenario) {
34
58
  const domainId = context.state.domain?.id;
35
- const inst = index_js_1.TwinEngine.instances[instanceId];
36
- if (!inst || inst.domainId !== domainId)
59
+ /* ํ…Œ๋„ŒํŠธ ๊ฒฉ๋ฆฌ โ€” ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์ง์ ‘ ์ƒ‰์ธํ•˜์ง€ ์•Š๋Š”๋‹ค(ํ‚ค์— ๋„๋ฉ”์ธ์ด ๋“ค์–ด ์žˆ๋‹ค). */
60
+ if (!index_js_1.TwinEngine.owns(domainId, instanceId))
37
61
  return false;
38
- const runtime = inst.runtime;
62
+ const runtime = index_js_1.TwinEngine.runtime(domainId, instanceId);
39
63
  /*
40
64
  * ์ž๊ทน ์ฃผ์ž… ๊ฐ€๋“œ โ€” mirror ํŠธ์œˆ(์™ธ๋ถ€ ์‹ค๋ฌผ์ด ์ง„์‹ค)์€ ์ปค๋„ ์‹œ๋‚˜๋ฆฌ์˜ค ์—”์ง„์ด ์—†๋‹ค(startLive=projector, runtime ์—†์Œ).
41
65
  * what-if ๋ฅผ ์—ฌ๊ธฐ์— ์ฃผ์ž…ํ•˜๋ฉด ํ˜„์‹ค์„ ์˜ค์—ผ์‹œํ‚ค๋ฏ€๋กœ ๊ฑฐ๋ถ€ํ•œ๋‹ค(sim-experiment/sim-world ๋งŒ ์ž๊ทน ๊ฐ€๋Šฅ). silent throw ๋ฐฉ์ง€.
42
66
  */
43
67
  if (!runtime?.scenario)
44
68
  return false;
69
+ /*
70
+ * **์ž˜๋ชป๋œ ์„ ์–ธ์€ ๋ฌธ ์•ž์—์„œ ๋ง‰๋Š”๋‹ค.** ์˜ˆ์ „์—๋Š” ๊ฒ€์ฆ ์—†์ด ์‹ค์—ˆ๊ณ , ๋‹ค์Œ tick ์—์„œ `rate.meanPerHour`
71
+ * ๋ฅผ ์ฝ๋‹ค ํ„ฐ์ ธ **์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‚ด๋ ค๊ฐ”๋‹ค**(ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๊ฐ’ ํ•˜๋‚˜๋กœ ์•ฑ ์ „์ฒด๊ฐ€ ์ฃฝ์—ˆ๋‹ค).
72
+ * ๊ทœ์น™์€ ์ปค๋„์ด ๋“ค๊ณ  ์žˆ๋‹ค(๊ณ„์•ฝ์˜ ์ฃผ์ธ) โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ ๋”ฐ๋กœ ๋งŒ๋“ค๋ฉด ๋ฐฉ์–ธ์ด ์ƒ๊ธด๋‹ค.
73
+ */
74
+ if (action === 'load') {
75
+ const v = (0, twin_kernel_1.validateScenario)(scenario);
76
+ if (v.ok === false) {
77
+ /* ์‚ฌ์œ ๋ฅผ ๋กœ๊ทธ๋กœ ๋‚จ๊ธด๋‹ค โ€” ์ด ๋ฎคํ…Œ์ด์…˜์˜ ๋ฐ˜ํ™˜์€ Boolean ๊ณ„์•ฝ์ด๋ผ ์‚ฌ์œ ๋ฅผ ์‹ค์–ด ๋ณด๋‚ผ ์ž๋ฆฌ๊ฐ€ ์—†๋‹ค. */
78
+ console.warn(`[twin] scenario rejected for "${instanceId}": ${v.errorCode} ${JSON.stringify(v.errorParams ?? {})}`);
79
+ return false;
80
+ }
81
+ }
45
82
  if (action === 'load' && scenario)
46
83
  runtime.scenario.load(scenario);
47
84
  else if (action === 'start')
@@ -57,6 +94,7 @@ let TwinControlMutation = class TwinControlMutation {
57
94
  };
58
95
  exports.TwinControlMutation = TwinControlMutation;
59
96
  tslib_1.__decorate([
97
+ (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
60
98
  (0, type_graphql_1.Mutation)(returns => shell_1.ScalarObject, { description: 'dispatch a twin command (order.hold/resume/release โ€ฆ). Returns {accepted, error?}.' }),
61
99
  tslib_1.__param(0, (0, type_graphql_1.Arg)('instanceId')),
62
100
  tslib_1.__param(1, (0, type_graphql_1.Arg)('command', type => shell_1.ScalarObject)),
@@ -66,6 +104,7 @@ tslib_1.__decorate([
66
104
  tslib_1.__metadata("design:returntype", Promise)
67
105
  ], TwinControlMutation.prototype, "dispatchTwinCommand", null);
68
106
  tslib_1.__decorate([
107
+ (0, type_graphql_1.Directive)('@privilege(category: "twin", privilege: "mutation", domainOwnerGranted: true, superUserGranted: true)'),
69
108
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'control twin scenario (load|start|pause|setSpeed)' }),
70
109
  tslib_1.__param(0, (0, type_graphql_1.Arg)('instanceId')),
71
110
  tslib_1.__param(1, (0, type_graphql_1.Arg)('action')),
@@ -1 +1 @@
1
- {"version":3,"file":"twin-control-mutation.js","sourceRoot":"","sources":["../../../server/service/twin-control/twin-control-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\n\n/*\n * ํŠธ์œˆ CommandยทScenario ์ฑ„๋„ โ€” ์ƒํ–ฅ mutation.\n * Command: runtime.dispatch(ํ–‰์œ„). Scenario: runtime.scenario.load/start/pause/setSpeed(์˜ˆ์ธก ์ž๊ทน).\n * (State ํ•˜ํ–ฅ์€ twin-state subscription. tick ์€ ์›Œ์ปค.)\n *\n * ์ธ๊ฐ€: data ๊ตฌ๋… ๋ฆฌ์กธ๋ฒ„์™€ ๋Œ€์นญ์œผ๋กœ, ๋Œ€์ƒ ์ธ์Šคํ„ด์Šค๊ฐ€ **ํ˜ธ์ถœ์ž ๋„๋ฉ”์ธ ์†Œ์†**์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค(cross-tenant ์ปค๋งจ๋“œ ์ฃผ์ž… ์ฐจ๋‹จ).\n * command ์ฑ„๋„์€ sim ์ƒํƒœ๋ฅผ ๋ณ€์ดํ•˜๋ฏ€๋กœ ๋„๋ฉ”์ธ ์Šค์ฝ”ํ”„๊ฐ€ ํ•„์ˆ˜.\n */\n@Resolver()\nexport class TwinControlMutation {\n /** Command ์ฑ„๋„ โ€” ์˜ค๋” hold/resume/release ๋“ฑ. ์ปค๋„ dispatch ๋กœ ์œ„์ž„, ack{accepted,error} ๋ฐ˜ํ™˜. */\n @Mutation(returns => ScalarObject, { description: 'dispatch a twin command (order.hold/resume/release โ€ฆ). Returns {accepted, error?}.' })\n async dispatchTwinCommand(\n @Arg('instanceId') instanceId: string,\n @Arg('command', type => ScalarObject) command: any,\n @Ctx() context: ResolverContext\n ): Promise<{ accepted: boolean; error?: string }> {\n const domainId = context.state.domain?.id\n const inst = TwinEngine.instances[instanceId]\n if (!inst || inst.domainId !== domainId) {\n return { accepted: false, error: 'instance not found in your domain' }\n }\n /* tenantId ๋ฅผ ํ˜ธ์ถœ์ž ๋„๋ฉ”์ธ์œผ๋กœ ๊ฐ์ธ(๊ฐ์‚ฌยท๋ฌด๊ฒฐ์„ฑ) โ€” ํด๋ผ ์œ„์กฐ ๋ฐฉ์ง€. */\n const ack = inst.runtime.dispatch({ ...command, tenantId: domainId })\n /* ๋ผ์ด๋ธŒ ๊ตฌ์กฐ ๋ณ€์ด(resource.add)๋Š” ์ €์žฅ board ์—๋„ ๋ฐ˜์˜ โ€” ํ”„๋กœ๋น„์ €๋‹ ํŽธ์ง‘๊ธฐยท์žฌ๊ธฐ๋™์ด ์ถ”๊ฐ€๋ถ„์„ ์žƒ์ง€ ์•Š๊ฒŒ. */\n if (ack?.accepted && command?.type === 'resource.add') {\n await TwinEngine.syncBoardEquipment(domainId, instanceId).catch(err => console.error('twin syncBoardEquipment fail', err))\n }\n return { accepted: !!ack?.accepted, error: ack?.error }\n }\n\n /** Scenario ์ฑ„๋„ โ€” ์ƒ์„ฑ๊ธฐ ์‹œ๋‚˜๋ฆฌ์˜ค ์ œ์–ด(load/start/pause/setSpeed). */\n @Mutation(returns => Boolean, { description: 'control twin scenario (load|start|pause|setSpeed)' })\n async controlTwinScenario(\n @Arg('instanceId') instanceId: string,\n @Arg('action') action: string,\n @Ctx() context: ResolverContext,\n @Arg('scenario', type => ScalarObject, { nullable: true }) scenario?: any\n ): Promise<boolean> {\n const domainId = context.state.domain?.id\n const inst = TwinEngine.instances[instanceId]\n if (!inst || inst.domainId !== domainId) return false\n const runtime = inst.runtime\n /*\n * ์ž๊ทน ์ฃผ์ž… ๊ฐ€๋“œ โ€” mirror ํŠธ์œˆ(์™ธ๋ถ€ ์‹ค๋ฌผ์ด ์ง„์‹ค)์€ ์ปค๋„ ์‹œ๋‚˜๋ฆฌ์˜ค ์—”์ง„์ด ์—†๋‹ค(startLive=projector, runtime ์—†์Œ).\n * what-if ๋ฅผ ์—ฌ๊ธฐ์— ์ฃผ์ž…ํ•˜๋ฉด ํ˜„์‹ค์„ ์˜ค์—ผ์‹œํ‚ค๋ฏ€๋กœ ๊ฑฐ๋ถ€ํ•œ๋‹ค(sim-experiment/sim-world ๋งŒ ์ž๊ทน ๊ฐ€๋Šฅ). silent throw ๋ฐฉ์ง€.\n */\n if (!runtime?.scenario) return false\n if (action === 'load' && scenario) runtime.scenario.load(scenario)\n else if (action === 'start') runtime.scenario.start()\n else if (action === 'pause') runtime.scenario.pause()\n else if (action === 'setSpeed' && scenario?.speed != null) runtime.scenario.setSpeed(Number(scenario.speed))\n else return false\n return true\n }\n}\n"]}
1
+ {"version":3,"file":"twin-control-mutation.js","sourceRoot":"","sources":["../../../server/service/twin-control/twin-control-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Mutation, Resolver, Directive} from 'type-graphql'\n\nimport { validateScenario } from '@operato/twin-kernel'\n\nimport { ScalarObject } from '@things-factory/shell'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { TwinEngine } from '../../engine/index.js'\nimport { TwinAuditEvent } from '../twin-audit/twin-audit-event.js'\nimport { buildCommandAudit } from '../twin-audit/command-audit.js'\n\n/*\n * ํŠธ์œˆ CommandยทScenario ์ฑ„๋„ โ€” ์ƒํ–ฅ mutation.\n * Command: runtime.dispatch(ํ–‰์œ„). Scenario: runtime.scenario.load/start/pause/setSpeed(์˜ˆ์ธก ์ž๊ทน).\n * (State ํ•˜ํ–ฅ์€ twin-state subscription. tick ์€ ์›Œ์ปค.)\n *\n * ์ธ๊ฐ€: data ๊ตฌ๋… ๋ฆฌ์กธ๋ฒ„์™€ ๋Œ€์นญ์œผ๋กœ, ๋Œ€์ƒ ์ธ์Šคํ„ด์Šค๊ฐ€ **ํ˜ธ์ถœ์ž ๋„๋ฉ”์ธ ์†Œ์†**์ธ์ง€ ๊ฒ€์ฆํ•œ๋‹ค(cross-tenant ์ปค๋งจ๋“œ ์ฃผ์ž… ์ฐจ๋‹จ).\n * command ์ฑ„๋„์€ sim ์ƒํƒœ๋ฅผ ๋ณ€์ดํ•˜๋ฏ€๋กœ ๋„๋ฉ”์ธ ์Šค์ฝ”ํ”„๊ฐ€ ํ•„์ˆ˜.\n */\n@Resolver()\nexport class TwinControlMutation {\n /** Command ์ฑ„๋„ โ€” ์˜ค๋” hold/resume/release ๋“ฑ. ์ปค๋„ dispatch ๋กœ ์œ„์ž„, ack{accepted,error} ๋ฐ˜ํ™˜. */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => ScalarObject, { description: 'dispatch a twin command (order.hold/resume/release โ€ฆ). Returns {accepted, error?}.' })\n async dispatchTwinCommand(\n @Arg('instanceId') instanceId: string,\n @Arg('command', type => ScalarObject) command: any,\n @Ctx() context: ResolverContext\n ): Promise<{ accepted: boolean; error?: string; errorCode?: string; errorParams?: Record<string, string | number> }> {\n const domainId = context.state.domain?.id\n if (!domainId) return { accepted: false, error: 'no-domain', errorCode: 'no-domain' }\n /*\n * ๋ผ์šฐํŒ…์€ ์—”์ง„์ด ํ•œ๋‹ค โ€” ์˜ˆ์ „์—๋Š” ์—ฌ๊ธฐ์„œ `inst.runtime.dispatch` ๋ฅผ ๊ณง๋ฐ”๋กœ ๋ถˆ๋ €๊ณ , `runtime` ์ด\n * ์‹œ๋ฎฌ์—๋งŒ ์žˆ์–ด์„œ ๋ฏธ๋Ÿฌ ํŠธ์œˆ์—์„œ๋Š” ์ด ํ•œ ์ค„์ด TypeError ๋กœ ํ„ฐ์กŒ๋‹ค(๊น”๋”ํ•œ ๊ฑฐ์ ˆ์ด ์•„๋‹ˆ๋ผ ์‹คํŒจ).\n * ๊ถŒ์œ„(๋ชจ๋“œ) ร— ์„ฑ๊ฒฉ(์ฃผ์„/์•ก์ถ”์—์ด์…˜) ํŒ์ •์€ ํ•œ ๊ณณ์—๋งŒ ๋‘”๋‹ค.\n */\n /* ์›๋ณธ์„ ๊ทธ๋Œ€๋กœ ๊ฐ์‚ฌ์— ๋„˜๊ธด๋‹ค โ€” ๋ฌด์—‡์ด ๋“ค์–ด์™”๋Š”์ง€๊ฐ€ ๊ธฐ๋ก์˜ ๋Œ€์ƒ์ด๋‹ค(์ •๊ทœํ™”๋Š” ๊ฐ์‚ฌ ๋ชจ๋“ˆ์ด ํ•œ๋‹ค). */\n const cmdWithOrigin = command\n const ack = await TwinEngine.dispatchCommand(domainId, instanceId, command)\n /* ๋ผ์ด๋ธŒ ๊ตฌ์กฐ ๋ณ€์ด(resource.add)๋Š” ์ €์žฅ model ์—๋„ ๋ฐ˜์˜ โ€” ํ”„๋กœ๋น„์ €๋‹ ํŽธ์ง‘๊ธฐยท์žฌ๊ธฐ๋™์ด ์ถ”๊ฐ€๋ถ„์„ ์žƒ์ง€ ์•Š๊ฒŒ. */\n if (ack?.accepted && command?.type === 'resource.add') {\n await TwinEngine.syncBoardEquipment(domainId, instanceId).catch(err => console.error('twin syncBoardEquipment fail', err))\n }\n /*\n * ๊ฐ์‚ฌ ๊ธฐ๋ก โ€” ์Šน์ธ ๊ฒŒ์ดํŠธ๊ฐ€ ์•ž์„ ๋ง‰๊ณ , ์ด ์ค„์ด ๋’ค๋ฅผ ์„ค๋ช…ํ•œ๋‹ค. ๋‘˜ ๋‹ค ์žˆ์–ด์•ผ \"์‚ฌ๋žŒ ์†์„ ๊ฑฐ์ณค๋‹ค\" ๋ฅผ\n * ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ปค๋„์ด ๊ฑฐ์ ˆํ•œ ๊ฒƒ๋„ ๋‚จ๊ธด๋‹ค โ€” ๋ฌด์—‡์„ ์‹œ๋„ํ–ˆ๋Š”์ง€๊ฐ€ ๊ฐ์‚ฌ์˜ ์ ˆ๋ฐ˜์ด๋‹ค.\n *\n * ๊ธฐ๋ก์ด ์‹คํŒจํ•ด๋„ ์ปค๋งจ๋“œ ๊ฒฐ๊ณผ๋Š” ๊ทธ๋Œ€๋กœ ๋Œ๋ ค์ค€๋‹ค. ๊ฐ์‚ฌ๊ฐ€ ๋ณธ์—…์„ ๋ง‰์œผ๋ฉด ์•ˆ ๋˜์ง€๋งŒ, ์‹คํŒจ๋ฅผ ์‚ผํ‚ค์ง€๋„\n * ์•Š๋Š”๋‹ค(๋กœ๊ทธ์— ๋‚จ๊ธด๋‹ค) โ€” ์กฐ์šฉํžˆ ์•ˆ ๋‚จ์œผ๋ฉด ๋‚˜์ค‘์— \"๊ธฐ๋ก์ด ์—†๋‹ค\" ์™€ \"์ผ์ด ์—†์—ˆ๋‹ค\" ๋ฅผ ๊ตฌ๋ถ„ ๋ชป ํ•œ๋‹ค.\n */\n try {\n const audit = buildCommandAudit({ command: cmdWithOrigin, ack, actor: context.state.user, at: new Date() })\n const repo = getRepository(TwinAuditEvent)\n await repo.save(repo.create({ domain: context.state.domain, instanceId, ...audit }))\n } catch (err) {\n console.error(`[twin-control] command audit not recorded for \"${instanceId}\"`, err)\n }\n\n /* ๊ฑฐ์ ˆ ์‚ฌ์œ ๋Š” **์–ธ์–ด ์ค‘๋ฆฝ ์ฝ”๋“œ**๋กœ ํ•จ๊ป˜ ๋Œ๋ ค์ค€๋‹ค โ€” ํ™”๋ฉด์ด `twin.cmderr.<code>` ๋กœ ์‚ฌ๋žŒ ๋ง์„ ๋งŒ๋“ ๋‹ค. */\n return { accepted: !!ack?.accepted, error: ack?.error, errorCode: ack?.errorCode, errorParams: ack?.errorParams }\n }\n\n /** Scenario ์ฑ„๋„ โ€” ์ƒ์„ฑ๊ธฐ ์‹œ๋‚˜๋ฆฌ์˜ค ์ œ์–ด(load/start/pause/setSpeed). */\n @Directive('@privilege(category: \"twin\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)')\n @Mutation(returns => Boolean, { description: 'control twin scenario (load|start|pause|setSpeed)' })\n async controlTwinScenario(\n @Arg('instanceId') instanceId: string,\n @Arg('action') action: string,\n @Ctx() context: ResolverContext,\n @Arg('scenario', type => ScalarObject, { nullable: true }) scenario?: any\n ): Promise<boolean> {\n const domainId = context.state.domain?.id\n /* ํ…Œ๋„ŒํŠธ ๊ฒฉ๋ฆฌ โ€” ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์ง์ ‘ ์ƒ‰์ธํ•˜์ง€ ์•Š๋Š”๋‹ค(ํ‚ค์— ๋„๋ฉ”์ธ์ด ๋“ค์–ด ์žˆ๋‹ค). */\n if (!TwinEngine.owns(domainId, instanceId)) return false\n const runtime = TwinEngine.runtime(domainId, instanceId)\n /*\n * ์ž๊ทน ์ฃผ์ž… ๊ฐ€๋“œ โ€” mirror ํŠธ์œˆ(์™ธ๋ถ€ ์‹ค๋ฌผ์ด ์ง„์‹ค)์€ ์ปค๋„ ์‹œ๋‚˜๋ฆฌ์˜ค ์—”์ง„์ด ์—†๋‹ค(startLive=projector, runtime ์—†์Œ).\n * what-if ๋ฅผ ์—ฌ๊ธฐ์— ์ฃผ์ž…ํ•˜๋ฉด ํ˜„์‹ค์„ ์˜ค์—ผ์‹œํ‚ค๋ฏ€๋กœ ๊ฑฐ๋ถ€ํ•œ๋‹ค(sim-experiment/sim-world ๋งŒ ์ž๊ทน ๊ฐ€๋Šฅ). silent throw ๋ฐฉ์ง€.\n */\n if (!runtime?.scenario) return false\n /*\n * **์ž˜๋ชป๋œ ์„ ์–ธ์€ ๋ฌธ ์•ž์—์„œ ๋ง‰๋Š”๋‹ค.** ์˜ˆ์ „์—๋Š” ๊ฒ€์ฆ ์—†์ด ์‹ค์—ˆ๊ณ , ๋‹ค์Œ tick ์—์„œ `rate.meanPerHour`\n * ๋ฅผ ์ฝ๋‹ค ํ„ฐ์ ธ **์„œ๋ฒ„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‚ด๋ ค๊ฐ”๋‹ค**(ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๊ฐ’ ํ•˜๋‚˜๋กœ ์•ฑ ์ „์ฒด๊ฐ€ ์ฃฝ์—ˆ๋‹ค).\n * ๊ทœ์น™์€ ์ปค๋„์ด ๋“ค๊ณ  ์žˆ๋‹ค(๊ณ„์•ฝ์˜ ์ฃผ์ธ) โ€” ํ˜ธ์ŠคํŠธ๊ฐ€ ๋”ฐ๋กœ ๋งŒ๋“ค๋ฉด ๋ฐฉ์–ธ์ด ์ƒ๊ธด๋‹ค.\n */\n if (action === 'load') {\n const v = validateScenario(scenario)\n if (v.ok === false) {\n /* ์‚ฌ์œ ๋ฅผ ๋กœ๊ทธ๋กœ ๋‚จ๊ธด๋‹ค โ€” ์ด ๋ฎคํ…Œ์ด์…˜์˜ ๋ฐ˜ํ™˜์€ Boolean ๊ณ„์•ฝ์ด๋ผ ์‚ฌ์œ ๋ฅผ ์‹ค์–ด ๋ณด๋‚ผ ์ž๋ฆฌ๊ฐ€ ์—†๋‹ค. */\n console.warn(`[twin] scenario rejected for \"${instanceId}\": ${v.errorCode} ${JSON.stringify(v.errorParams ?? {})}`)\n return false\n }\n }\n if (action === 'load' && scenario) runtime.scenario.load(scenario)\n else if (action === 'start') runtime.scenario.start()\n else if (action === 'pause') runtime.scenario.pause()\n else if (action === 'setSpeed' && scenario?.speed != null) runtime.scenario.setSpeed(Number(scenario.speed))\n else return false\n return true\n }\n}\n"]}
@@ -28,7 +28,7 @@ export declare function locationOf(envelope: any): string | undefined;
28
28
  * ์„ค๋น„ยท๋ฌด๋ฒ„ โ€” ์šด์˜ ๋ธํƒ€(equipment.statusยทtask.status)๊ฐ€ ๋Œ€์ƒ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ถ•.
29
29
  *
30
30
  * EPCIS ์–ดํœ˜๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ๋‹ค๋ฅธ ์ถ• ์–ด๋””์—๋„ ์•ˆ ์žกํžŒ๋‹ค. ์ด๊ฒŒ ์—†์œผ๋ฉด "์ด ์ง€๊ฒŒ์ฐจ๊ฐ€ ์˜ค๋Š˜ ๋ฌด์—‡์„ ํ–ˆ๋‚˜" ๋ฅผ
31
- * ์„œ๋ฒ„์—์„œ ๋ฌผ์„ ๋ฐฉ๋ฒ•์ด ์—†์–ด, ํ™”๋ฉด์ด ์ €๋„์„ ํ†ต์งธ๋กœ ๋ฐ›์•„ ํ›‘๋Š” ์ˆ˜๋ฐ–์— ์—†๋‹ค.
31
+ * ์„œ๋ฒ„์—์„œ ๋ฌผ์„ ๋ฐฉ๋ฒ•์ด ์—†์–ด, ํ™”๋ฉด์ด ์ €๋„์„ ํ†ต์งธ๋กœ ๋ฐ›์•„ ์ „์ˆ˜ ์กฐํšŒํ•˜๋Š” ์ˆ˜๋ฐ–์— ์—†๋‹ค.
32
32
  */
33
33
  export declare function equipmentIdOf(envelope: any): string | undefined;
34
34
  /** ํ•œ ์ด๋ฒคํŠธ์—์„œ ์Šน๊ฒฉ ํ‚ค ์ „๋ถ€ โ€” ๊ธฐ๋ก ๊ฒฝ๋กœ๊ฐ€ ์ด ํ•จ์ˆ˜ ํ•˜๋‚˜๋งŒ ๋ถ€๋ฅธ๋‹ค. */
@@ -76,7 +76,7 @@ function locationOf(envelope) {
76
76
  * ์„ค๋น„ยท๋ฌด๋ฒ„ โ€” ์šด์˜ ๋ธํƒ€(equipment.statusยทtask.status)๊ฐ€ ๋Œ€์ƒ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ถ•.
77
77
  *
78
78
  * EPCIS ์–ดํœ˜๊ฐ€ ์•„๋‹ˆ๋ผ์„œ ๋‹ค๋ฅธ ์ถ• ์–ด๋””์—๋„ ์•ˆ ์žกํžŒ๋‹ค. ์ด๊ฒŒ ์—†์œผ๋ฉด "์ด ์ง€๊ฒŒ์ฐจ๊ฐ€ ์˜ค๋Š˜ ๋ฌด์—‡์„ ํ–ˆ๋‚˜" ๋ฅผ
79
- * ์„œ๋ฒ„์—์„œ ๋ฌผ์„ ๋ฐฉ๋ฒ•์ด ์—†์–ด, ํ™”๋ฉด์ด ์ €๋„์„ ํ†ต์งธ๋กœ ๋ฐ›์•„ ํ›‘๋Š” ์ˆ˜๋ฐ–์— ์—†๋‹ค.
79
+ * ์„œ๋ฒ„์—์„œ ๋ฌผ์„ ๋ฐฉ๋ฒ•์ด ์—†์–ด, ํ™”๋ฉด์ด ์ €๋„์„ ํ†ต์งธ๋กœ ๋ฐ›์•„ ์ „์ˆ˜ ์กฐํšŒํ•˜๋Š” ์ˆ˜๋ฐ–์— ์—†๋‹ค.
80
80
  */
81
81
  function equipmentIdOf(envelope) {
82
82
  const d = envelope?.data ?? envelope ?? {};
@@ -1 +1 @@
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":["/*\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 bizStep?: string\n epc?: string\n orderId?: 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 console.warn(\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/** ๊ฑฐ๋ž˜ ์‹๋ณ„์ž(PO/SO) โ€” EPCIS bizTransactionList ์šฐ์„ , ์šด์˜ ๋ธํƒ€๋Š” `order`. */\nexport function orderOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n return d.bizTransactionList?.[0]?.bizTransaction ?? d.order ?? 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 return d.moverId ?? undefined\n}\n\n/** ํ•œ ์ด๋ฒคํŠธ์—์„œ ์Šน๊ฒฉ ํ‚ค ์ „๋ถ€ โ€” ๊ธฐ๋ก ๊ฒฝ๋กœ๊ฐ€ ์ด ํ•จ์ˆ˜ ํ•˜๋‚˜๋งŒ ๋ถ€๋ฅธ๋‹ค. */\nexport function twinEventKeys(envelope: any): TwinEventKeys {\n return {\n bizStep: clip(bizStepOf(envelope), 'bizStep'),\n epc: clip(epcOf(envelope), 'epc'),\n orderId: clip(orderOf(envelope), 'orderId'),\n locationId: clip(locationOf(envelope), 'locationId'),\n moverId: clip(equipmentIdOf(envelope), 'moverId')\n }\n}\n"]}
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":["/*\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 bizStep?: string\n epc?: string\n orderId?: 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 console.warn(\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/** ๊ฑฐ๋ž˜ ์‹๋ณ„์ž(PO/SO) โ€” EPCIS bizTransactionList ์šฐ์„ , ์šด์˜ ๋ธํƒ€๋Š” `order`. */\nexport function orderOf(envelope: any): string | undefined {\n const d = envelope?.data ?? envelope ?? {}\n return d.bizTransactionList?.[0]?.bizTransaction ?? d.order ?? 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 return d.moverId ?? undefined\n}\n\n/** ํ•œ ์ด๋ฒคํŠธ์—์„œ ์Šน๊ฒฉ ํ‚ค ์ „๋ถ€ โ€” ๊ธฐ๋ก ๊ฒฝ๋กœ๊ฐ€ ์ด ํ•จ์ˆ˜ ํ•˜๋‚˜๋งŒ ๋ถ€๋ฅธ๋‹ค. */\nexport function twinEventKeys(envelope: any): TwinEventKeys {\n return {\n bizStep: clip(bizStepOf(envelope), 'bizStep'),\n epc: clip(epcOf(envelope), 'epc'),\n orderId: clip(orderOf(envelope), 'orderId'),\n locationId: clip(locationOf(envelope), 'locationId'),\n moverId: clip(equipmentIdOf(envelope), 'moverId')\n }\n}\n"]}
@@ -3,22 +3,31 @@ export declare class TwinEvent {
3
3
  readonly id: string;
4
4
  domain?: Domain;
5
5
  domainId?: string;
6
- instanceId?: string;
7
- tenantId?: string;
8
- eventType?: string;
6
+ instanceId: string;
7
+ eventType: string;
9
8
  revision?: number;
10
9
  /**
11
10
  * ์ด ์‚ฌ์‹ค์ด **์–ด๋А ๊ณต์žฅ์—์„œ** ์ผ์–ด๋‚ฌ๋‚˜ โ€” `TwinStructure.rev`.
12
11
  *
13
12
  * ์ด๊ฒƒ์ด ์—†๋˜ ์‹œ์ ˆ์—๋Š” ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ๋ฉด ์ €๋„์„ ํ†ต์งธ๋กœ ์ง€์šฐ๋Š” ๊ฒƒ์ด ์œ ์ผํ•œ ๊ธธ์ด์—ˆ๋‹ค(์•ˆ ์ง€์šฐ๋ฉด ์˜›
14
13
  * ์ด๋ฒคํŠธ๋ฅผ ์ƒˆ ๊ณต์žฅ์— ๋Œ€๊ณ  ์ ‘์–ด ์ด๋ ฅ์ด ๊ฑฐ์ง“๋ง์„ ํ•œ๋‹ค). ์ด ํ•œ ์นธ์ด ์…‹์งธ ๊ธธ์„ ์—ฐ๋‹ค โ€” ์žฌ์ƒ์ด
15
- * ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ๋Š” ์ง€์ ์—์„œ ๊ฐˆ์•„ํƒ„ ๋’ค ์ด์–ด ์ ‘๋Š”๋‹ค.
14
+ * ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ๋Š” ์ง€์ ์—์„œ ์ „ํ™˜ํ•œ ๋’ค ์ด์–ด ์ ‘๋Š”๋‹ค.
16
15
  *
17
16
  * **๋น„์–ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค**: ์ปฌ๋Ÿผ์ด ์ƒ๊ธฐ๊ธฐ ์ „์— ์“ฐ์ธ ํ–‰์ด๋‹ค. ๊ทธ ํ–‰๋“ค์€ **๊ฐ€์žฅ ์˜ค๋ž˜๋œ ๋ฆฌ๋น„์ „**์—
18
17
  * ์†ํ•œ๋‹ค(0 ์„ ์ฑ„์›Œ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค โ€” 0 ์€ "๋ชจ๋ฆ„" ์ด ์•„๋‹ˆ๋ผ ์œ ํšจํ•œ ๋ฒˆํ˜ธ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค).
19
18
  */
20
19
  structureRev?: number;
21
- eventTime?: string;
20
+ eventTime?: Date;
21
+ /**
22
+ * ์ด ์‚ฌ์‹ค์„ ์ผ์œผํ‚จ **์ง€์‹œ** โ€” ์ปค๋„์ด ์ปค๋งจ๋“œ์—์„œ ์ด์–ด ์ค€ ์ƒ๊ด€๊ฐ’(๊ธฐ๋ณธ์€ commandId).
23
+ *
24
+ * ์ด๊ฒƒ์ด ๊ฐ์‚ฌ ๊ธฐ๋ก(TwinAuditEvent.commandId)๊ณผ ์ €๋„์„ ์ž‡๋Š” ์œ ์ผํ•œ ๋‹ค๋ฆฌ๋‹ค. ์—†์œผ๋ฉด ์Šน์ธ ๊ธฐ๋ก์€
25
+ * "์‚ฌ๋žŒ์ด ํ—ˆ๋ฝํ–ˆ๋‹ค" ๊นŒ์ง€์ด๊ณ , ๊ทธ ๋’ค ๊ณต์žฅ์ด ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์›€์ง์˜€๋Š”์ง€์™€ ์ด์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.
26
+ *
27
+ * **๋Œ€๋ถ€๋ถ„์˜ ํ–‰์€ ๋น„์–ด ์žˆ๋‹ค** โ€” ์ปค๋งจ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‹œ๋ฎฌ ์‹œ๊ฐ„์ด ๋‚ณ์€ ์‚ฌ์‹ค์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๊ฒƒ์ด ์ •์ƒ์ด๊ณ ,
28
+ * ๋น„์–ด ์žˆ๋‹ค๊ณ  "๋œ ์ฑ„์›Œ์ง„ ์˜› ํ–‰" ์œผ๋กœ ๋ณด๋ฉด ์•ˆ ๋œ๋‹ค(๊ฐ™์€ ์˜คํ•ด๋ฅผ bizStep ์—์„œ ์ด๋ฏธ ํ•œ ๋ฒˆ ํ–ˆ๋‹ค).
29
+ */
30
+ correlationId?: string;
22
31
  bizStep?: string;
23
32
  epc?: string;
24
33
  orderId?: string;
@@ -25,7 +25,7 @@ const shell_1 = require("@things-factory/shell");
25
25
  *
26
26
  * bizStepยทlocationIdยทmoverId ๋Š” ์ปฌ๋Ÿผ๋งŒ ๋‘๊ณ  ์ธ๋ฑ์Šค๋Š” ๋‘์ง€ ์•Š๋Š”๋‹ค โ€” ํ•œ ํŠธ์œˆ ์•ˆ์—์„œ ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€
27
27
  * ๋‚ฎ์•„(์—…๋ฌด๋‹จ๊ณ„ ๋ช‡ ๊ฐœ, ์œ„์น˜ ์ˆ˜๋ฐฑ, ์„ค๋น„ ์ˆ˜์‹ญ) (domain,instanceId) ๋กœ ์ด๋ฏธ ์ขํ˜€์ง„ ๋’ค์˜ ์ž”์—ฌ ํ•„ํ„ฐ๋กœ
28
- * ์ถฉ๋ถ„ํ•˜๊ณ , ๋œจ๊ฑฐ์šด ํ‘œ์— ์ธ๋ฑ์Šค๋ฅผ ๋” ์–น์„ ๊ฐ’์–ด์น˜๊ฐ€ ์—†๋‹ค. ์ €๋„ ํ•˜๋‚˜๊ฐ€ ์•„์ฃผ ์ปค์ ธ์„œ ์ด ์ถ•๋“ค์˜ ์กฐํšŒ๊ฐ€
28
+ * ์ถฉ๋ถ„ํ•˜๊ณ , ๋œจ๊ฑฐ์šด ํ‘œ์— ์ธ๋ฑ์Šค๋ฅผ ๋” ์–น์„ ๊ฐ€์น˜๊ฐ€ ์—†๋‹ค. ์ €๋„ ํ•˜๋‚˜๊ฐ€ ์•„์ฃผ ์ปค์ ธ์„œ ์ด ์ถ•๋“ค์˜ ์กฐํšŒ๊ฐ€
29
29
  * ๋А๋ ค์ง€๋ฉด ๊ทธ๋•Œ ์ธก์ •์„ ๊ทผ๊ฑฐ๋กœ ์ธ๋ฑ์Šค๋ฅผ ์ถ”๊ฐ€ํ•  ์ผ์ด์ง€, ์ง€๋ ˆ ์–น์–ด ์“ฐ๊ธฐ๋ฅผ ๋ฌด๊ฒ๊ฒŒ ํ•  ์ผ์€ ์•„๋‹ˆ๋‹ค.
30
30
  */
31
31
  let TwinEvent = class TwinEvent {
@@ -46,18 +46,13 @@ tslib_1.__decorate([
46
46
  tslib_1.__metadata("design:type", String)
47
47
  ], TwinEvent.prototype, "domainId", void 0);
48
48
  tslib_1.__decorate([
49
- (0, typeorm_1.Column)({ nullable: true }),
50
- (0, type_graphql_1.Field)({ nullable: true, description: 'Twin runtime instance id that emitted the event.' }),
49
+ (0, typeorm_1.Column)(),
50
+ (0, type_graphql_1.Field)({ description: 'Twin runtime instance id that emitted the event.' }),
51
51
  tslib_1.__metadata("design:type", String)
52
52
  ], TwinEvent.prototype, "instanceId", void 0);
53
53
  tslib_1.__decorate([
54
- (0, typeorm_1.Column)({ nullable: true }),
55
- (0, type_graphql_1.Field)({ nullable: true, description: 'Kernel tenant id carried on the canonical envelope.' }),
56
- tslib_1.__metadata("design:type", String)
57
- ], TwinEvent.prototype, "tenantId", void 0);
58
- tslib_1.__decorate([
59
- (0, typeorm_1.Column)({ nullable: true }),
60
- (0, type_graphql_1.Field)({ nullable: true, description: 'Event type: epcis.* | task.status | equipment.status | order.status.' }),
54
+ (0, typeorm_1.Column)(),
55
+ (0, type_graphql_1.Field)({ description: 'Event type: epcis.* | task.status | equipment.status | order.status.' }),
61
56
  tslib_1.__metadata("design:type", String)
62
57
  ], TwinEvent.prototype, "eventType", void 0);
63
58
  tslib_1.__decorate([
@@ -71,10 +66,44 @@ tslib_1.__decorate([
71
66
  tslib_1.__metadata("design:type", Number)
72
67
  ], TwinEvent.prototype, "structureRev", void 0);
73
68
  tslib_1.__decorate([
74
- (0, typeorm_1.Column)({ nullable: true }),
75
- (0, type_graphql_1.Field)({ nullable: true, description: 'Simulation event time (ISO 8601).' }),
76
- tslib_1.__metadata("design:type", String)
69
+ (0, typeorm_1.Column)({ type: 'datetime', nullable: true }),
70
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Time at which the fact happened on the twin clock.' }),
71
+ tslib_1.__metadata("design:type", Date
72
+ /*
73
+ * โ”€โ”€ ์Šน๊ฒฉ๋œ ๊ฒ€์ƒ‰ ์ถ• โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
74
+ * payload ์•ˆ์— ์žˆ๋˜ ๊ฐ’์„ ์ธ์ œ์ŠคํŠธ ์‹œ์ ์— ๊บผ๋‚ด ์‹ค์ปฌ๋Ÿผ์œผ๋กœ ๋‘”๋‹ค(`twin-event-keys.ts` ๊ฐ€ ๋‹จ๋… ์†Œ์œ ).
75
+ * payload ๊ฐ€ ์—ฌ์ „ํžˆ ์ •๋ณธ์ด๊ณ  ์ด๊ฒƒ๋“ค์€ **ํŒŒ์ƒ ์ƒ‰์ธ**์ด๋‹ค โ€” ์ƒˆ๋กœ์šด ์ง„์‹ค์ด ์•„๋‹ˆ๋ผ ์ฐพ์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์žฅ์น˜.
76
+ * simple-json(TEXT) ์•ˆ์˜ ๊ฐ’์€ 5๊ฐœ DB ๋“œ๋ผ์ด๋ฒ„ ๊ณตํ†ต์œผ๋กœ ๊ฑฐ๋ฅผ ๋ฐฉ๋ฒ•์ด ์—†์–ด์„œ(๋ฉ€ํ‹ฐDB ํ˜ธํ™˜ ๊ทœ์น™์ƒ
77
+ * DB๋ณ„ JSON ์—ฐ์‚ฐ์ž ๊ธˆ์ง€) ์Šน๊ฒฉ ์™ธ์˜ ์„ ํƒ์ง€๊ฐ€ ์—†๋‹ค.
78
+ * ๊ธธ์ด ์ƒํ•œ 255 ๋Š” GS1 ์‹๋ณ„์ž ๊ทœ๊ฒฉ ๋Œ€๋น„ ์ถฉ๋ถ„ํ•˜๋ฉฐ, ๋„˜์น˜๋Š” ๊ฐ’์€ ์กฐ์šฉํžˆ ์ž˜๋ฆฌ์ง€ ์•Š๊ณ  ๊ฒฝ๊ณ ๋ฅผ ๋‚จ๊ธด๋‹ค.
79
+ *
80
+ * โ”€โ”€ ์ถ•์„ ์ƒˆ๋กœ ์ถ”๊ฐ€ํ•  ๋•Œ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
81
+ * ์ƒˆ ์Šน๊ฒฉ ์ปฌ๋Ÿผ์„ ๋งŒ๋“ค๋ฉด **์ด๋ฏธ ์Œ“์ธ ํ–‰์€ ๋น„์–ด ์žˆ๋‹ค.** ๊ทธ ํ–‰๋“ค์€ ์ƒˆ ์ถ•์œผ๋กœ ๊ฒ€์ƒ‰๋˜์ง€ ์•Š๊ณ ,
82
+ * ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” "๊ณผ๊ฑฐ๊ฐ€ ์—†๋Š” ๊ฒƒ" ์œผ๋กœ ๋ณด์ธ๋‹ค(์กฐ์šฉํžˆ ๋น ์ง„ ๋ฐ์ดํ„ฐ).
83
+ *
84
+ * ์˜ˆ์ „์—๋Š” ๊ธฐ๋™ ํ›…์ด ๋งค๋ฒˆ ํ…Œ์ด๋ธ”์„ ์‚ดํŽด ์ฑ„์› ๋‹ค. ๊ทธ๊ฑด ๋‘ ๊ฐ€์ง€๋กœ ํ‹€๋ ธ๋‹ค โ€” ์ €๋„์ด ์ปค์งˆ์ˆ˜๋ก ๋ถ€ํŒ…์ด
85
+ * ๋А๋ ค์ง€๊ณ , "bizStep ์ด ๋น„์—ˆ์œผ๋ฉด ์˜› ํ–‰" ์ด๋ผ๋Š” ์ „์ œ๋ฅผ ์ฝ”๋“œ์— ๊ณ ์ •ํ•ด ๊ทธ ์ „์ œ๊ฐ€ ๊นจ์ง€๋Š” ์ˆœ๊ฐ„
86
+ * (๊ฐ์‚ฌ ํ–‰์ฒ˜๋Ÿผ ์—…๋ฌด ๋‹จ๊ณ„๊ฐ€ ์—†๋Š” ํ–‰) ๋งค ๋ถ€ํŒ…๋งˆ๋‹ค ํ—›๋Œ์•˜๋‹ค. ๊ทธ๋ž˜์„œ ๊ฑท์–ด๋ƒˆ๋‹ค(git: backfill-keys.ts).
87
+ *
88
+ * ์ฑ„์šฐ๋Š” ์ผ์€ **๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•œ ๋ฒˆ**์ด ๋งž๋‹ค(`yarn migration`). ๊ทธ ์ปฌ๋Ÿผ์— ๋งž๋Š” ๊ฒƒ์„ ๊ทธ๋•Œ ์“ด๋‹ค โ€”
89
+ * ๋ฒ”์šฉ ์Šค์บ๋„ˆ๋ฅผ ๋˜์‚ด๋ฆฌ์ง€ ๋ง ๊ฒƒ. ๊ฐœ๋ฐœ ๋ฐ์ดํƒ€๋ผ๋ฉด ๊ทธ๋ƒฅ ๋ฒ„๋ฆฌ๋Š” ๊ฒƒ๋„ ๋‹ต์ด๋‹ค.
90
+ */
91
+ /**
92
+ * ์ด ์‚ฌ์‹ค์„ ์ผ์œผํ‚จ **์ง€์‹œ** โ€” ์ปค๋„์ด ์ปค๋งจ๋“œ์—์„œ ์ด์–ด ์ค€ ์ƒ๊ด€๊ฐ’(๊ธฐ๋ณธ์€ commandId).
93
+ *
94
+ * ์ด๊ฒƒ์ด ๊ฐ์‚ฌ ๊ธฐ๋ก(TwinAuditEvent.commandId)๊ณผ ์ €๋„์„ ์ž‡๋Š” ์œ ์ผํ•œ ๋‹ค๋ฆฌ๋‹ค. ์—†์œผ๋ฉด ์Šน์ธ ๊ธฐ๋ก์€
95
+ * "์‚ฌ๋žŒ์ด ํ—ˆ๋ฝํ–ˆ๋‹ค" ๊นŒ์ง€์ด๊ณ , ๊ทธ ๋’ค ๊ณต์žฅ์ด ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์›€์ง์˜€๋Š”์ง€์™€ ์ด์–ด์ง€์ง€ ์•Š๋Š”๋‹ค.
96
+ *
97
+ * **๋Œ€๋ถ€๋ถ„์˜ ํ–‰์€ ๋น„์–ด ์žˆ๋‹ค** โ€” ์ปค๋งจ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‹œ๋ฎฌ ์‹œ๊ฐ„์ด ๋‚ณ์€ ์‚ฌ์‹ค์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๊ฒƒ์ด ์ •์ƒ์ด๊ณ ,
98
+ * ๋น„์–ด ์žˆ๋‹ค๊ณ  "๋œ ์ฑ„์›Œ์ง„ ์˜› ํ–‰" ์œผ๋กœ ๋ณด๋ฉด ์•ˆ ๋œ๋‹ค(๊ฐ™์€ ์˜คํ•ด๋ฅผ bizStep ์—์„œ ์ด๋ฏธ ํ•œ ๋ฒˆ ํ–ˆ๋‹ค).
99
+ */
100
+ )
77
101
  ], TwinEvent.prototype, "eventTime", void 0);
102
+ tslib_1.__decorate([
103
+ (0, typeorm_1.Column)({ length: 255, nullable: true }),
104
+ (0, type_graphql_1.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.' }),
105
+ tslib_1.__metadata("design:type", String)
106
+ ], TwinEvent.prototype, "correlationId", void 0);
78
107
  tslib_1.__decorate([
79
108
  (0, typeorm_1.Column)({ length: 255, nullable: true }),
80
109
  (0, type_graphql_1.Field)({ nullable: true, description: 'Business step (CBV bizStep tail), promoted from the payload for indexed filtering.' }),
@@ -116,7 +145,10 @@ exports.TwinEvent = TwinEvent = tslib_1.__decorate([
116
145
  (0, typeorm_1.Index)('ix_twin_event_1', (e) => [e.domain, e.instanceId, e.eventTime], { unique: false }),
117
146
  (0, typeorm_1.Index)('ix_twin_event_2', (e) => [e.domain, e.instanceId, e.eventType, e.revision], { unique: false }),
118
147
  (0, typeorm_1.Index)('ix_twin_event_3', (e) => [e.domain, e.instanceId, e.epc], { unique: false }),
119
- (0, typeorm_1.Index)('ix_twin_event_4', (e) => [e.domain, e.instanceId, e.orderId], { unique: false }),
148
+ (0, typeorm_1.Index)('ix_twin_event_4', (e) => [e.domain, e.instanceId, e.orderId], { unique: false })
149
+ /* ix_5 โ€” "์ด ์ง€์‹œ๊ฐ€ ๋ฌด์—‡์„ ์ผ์œผ์ผฐ๋‚˜". ๊ฐ์‚ฌ ๊ธฐ๋ก์˜ commandId ๋กœ ์ €๋„์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜๋Š” ์ถ•. */
150
+ ,
151
+ (0, typeorm_1.Index)('ix_twin_event_5', (e) => [e.domain, e.correlationId], { unique: false }),
120
152
  (0, type_graphql_1.ObjectType)({ description: 'Append-only twin event journal record (EPCIS event or operational delta).' })
121
153
  ], TwinEvent);
122
154
  //# sourceMappingURL=twin-event.js.map