@operato/twin-kernel 0.8.1 → 0.8.2
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/package.json +1 -1
- package/dist/capability.d.ts +0 -142
- package/dist/capability.js +0 -127
- package/dist/capacity.d.ts +0 -99
- package/dist/capacity.js +0 -172
- package/dist/contract.d.ts +0 -3489
- package/dist/contract.js +0 -1216
- package/dist/domain-catalog.d.ts +0 -280
- package/dist/domain-catalog.js +0 -322
- package/dist/domain-definition.d.ts +0 -306
- package/dist/domain-definition.js +0 -102
- package/dist/ems-profile.d.ts +0 -147
- package/dist/ems-profile.js +0 -367
- package/dist/energy-ingest.d.ts +0 -214
- package/dist/energy-ingest.js +0 -801
- package/dist/epcis.d.ts +0 -458
- package/dist/epcis.js +0 -640
- package/dist/face2-adapter.d.ts +0 -191
- package/dist/face2-adapter.js +0 -284
- package/dist/iso-duration.d.ts +0 -5
- package/dist/iso-duration.js +0 -43
- package/dist/master-data.d.ts +0 -80
- package/dist/master-data.js +0 -168
- package/dist/mes-profile.d.ts +0 -14
- package/dist/mes-profile.js +0 -59
- package/dist/operational-ingest.d.ts +0 -44
- package/dist/operational-ingest.js +0 -379
- package/dist/operations-capability.d.ts +0 -117
- package/dist/operations-capability.js +0 -120
- package/dist/scenario-validate.d.ts +0 -15
- package/dist/scenario-validate.js +0 -72
- package/dist/vocabulary.d.ts +0 -28
- package/dist/vocabulary.js +0 -81
- package/dist/wms-profile.d.ts +0 -20
- package/dist/wms-profile.js +0 -58
- package/dist/yms-profile.d.ts +0 -15
- package/dist/yms-profile.js +0 -39
package/dist/master-data.js
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { ILMD_ATTR } from "./epcis.js";
|
|
2
|
-
/*
|
|
3
|
-
* **마스터데이터 — 변하지 않는 속성이 들어오는 문** (2026-08-28).
|
|
4
|
-
*
|
|
5
|
-
* ── 무엇이 없어서 무엇이 망가졌나 ───────────────────────────────────────────
|
|
6
|
-
* 커널에 마스터데이터라는 개념이 없었다. 그래서 유통기한 같은 값이 갈 곳이 **사건밖에** 없었고,
|
|
7
|
-
* 표준은 그 값을 `ObjectEvent(action=ADD)` 와 변환 사건에만 실을 수 있게 한다(EPCIS 2.0 §7.3.8).
|
|
8
|
-
*
|
|
9
|
-
* 그 제약이 유입 쪽에서 이렇게 나타났다. 전량을 읽는 원본(식품 제조 MES)이 재고를 다시 말할 때마다,
|
|
10
|
-
* 유통기한을 실으려고 **들어오지 않은 것을 `ADD` 라고** 말했다. 그리고 `ilmd` 는 사건 단위라서 자리별로
|
|
11
|
-
* 묶을 수도 없어 낱개로 나갔다 — 재기동 한 번에 2,665건이다.
|
|
12
|
-
*
|
|
13
|
-
* 나르는 방법의 제약이 사실의 뜻을 정한 것이고, 순서가 거꾸로였다.
|
|
14
|
-
*
|
|
15
|
-
* ── 표준이 둔 자리 ──────────────────────────────────────────────────────────
|
|
16
|
-
* 표준은 이런 값을 **어휘 요소의 속성**으로 담는 자리를 사건과 별개로 갖고 있다.
|
|
17
|
-
*
|
|
18
|
-
* 어휘 타입 urn:epcglobal:epcis:vtype:EPCClass · ReadPoint · BizLocation
|
|
19
|
-
* 어휘 요소 { id, attributes }
|
|
20
|
-
*
|
|
21
|
-
* 속성 **이름**은 EPCIS 본문이 정하지 않고 상위 문서(CBV 마스터데이터)의 몫이다(§7.3.8 이 미룬다).
|
|
22
|
-
* 그래서 이 모듈은 이름을 해석하지 않고 **그대로 보관한다** — 아는 이름만 상태 축으로 옮기고, 모르는
|
|
23
|
-
* 것은 잃지 않는다. 우리가 생산할 때 쓰는 이름은 `ILMD_ATTR` 한 곳에 모여 있고 사건 경로와 같은
|
|
24
|
-
* 상수다(이름이 바뀌면 한 곳만 고친다).
|
|
25
|
-
*
|
|
26
|
-
* ── 무엇을 이 문으로 보내지 않나 ────────────────────────────────────────────
|
|
27
|
-
* **변하는 값은 사건이다.** 수량·위치·상태·진행은 이 문으로 오지 않는다. 여기 오는 것은 그 물건의
|
|
28
|
-
* 생애 동안 같은 값뿐이고, 그래서 「그때는 얼마였나」라는 물음이 성립하지 않는다 — 시각축이 없는 값이다.
|
|
29
|
-
*
|
|
30
|
-
* 그 성질이 「지난 기록에 적지 않는다」의 근거다. 사건에서 파생되는 상태가 아니라 **선언된 것**이므로
|
|
31
|
-
* 모델·자재 선언과 같은 자리에 산다. 다만 중간 저장본에는 담는다(되세울 때 원본을 다시 읽지 않게).
|
|
32
|
-
*
|
|
33
|
-
* 설계: `operato-twin/design/plans/master-data.md`
|
|
34
|
-
*/
|
|
35
|
-
/** 표준 어휘 타입 — 이 세 가지가 우리 상태 축에 닿는다. 그 밖은 보관하고 알린다. */
|
|
36
|
-
export const VOCABULARY_TYPE = {
|
|
37
|
-
/** 품목·로트 클래스의 속성 — 유통기한·로트번호가 여기 온다. */
|
|
38
|
-
epcClass: 'urn:epcglobal:epcis:vtype:EPCClass',
|
|
39
|
-
/** 관측 지점의 속성. */
|
|
40
|
-
readPoint: 'urn:epcglobal:epcis:vtype:ReadPoint',
|
|
41
|
-
/** 업무 자리의 속성. */
|
|
42
|
-
bizLocation: 'urn:epcglobal:epcis:vtype:BizLocation'
|
|
43
|
-
};
|
|
44
|
-
/** 이 레코드가 마스터데이터인가 — 갈래 판정은 **커널이 한 곳에서** 한다(어휘 넷을 가르는 방식과 같다). */
|
|
45
|
-
export function isMasterDataRecord(record) {
|
|
46
|
-
if (!record || typeof record !== 'object')
|
|
47
|
-
return false;
|
|
48
|
-
const r = record;
|
|
49
|
-
return typeof r.vocabularyType === 'string' && !!r.vocabularyType && typeof r.id === 'string' && !!r.id && isPlainObject(r.attributes);
|
|
50
|
-
}
|
|
51
|
-
function isPlainObject(v) {
|
|
52
|
-
return !!v && typeof v === 'object' && !Array.isArray(v);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* 마스터데이터를 받아들인다 — **거부한 것은 이유와 함께 남는다**(다른 어휘와 같은 규율).
|
|
56
|
-
*
|
|
57
|
-
* 빈 속성은 거부한다: 「이 로트에 대해 아무것도 모른다」를 보내는 것은 아무 뜻이 없고, 받아 두면
|
|
58
|
-
* 기존 값을 지우려는 것인지 아무 말도 아닌지 구별할 수 없다.
|
|
59
|
-
*/
|
|
60
|
-
export function ingestMasterData(records) {
|
|
61
|
-
const arr = Array.isArray(records) ? records : records ? [records] : [];
|
|
62
|
-
const accepted = [];
|
|
63
|
-
const rejected = [];
|
|
64
|
-
for (const r of arr) {
|
|
65
|
-
const errors = [];
|
|
66
|
-
if (!isMasterDataRecord(r))
|
|
67
|
-
errors.push('vocabularyType · id · attributes 가 있어야 한다');
|
|
68
|
-
else if (!Object.keys(r.attributes).length)
|
|
69
|
-
errors.push('attributes 가 비었다 — 아무 뜻이 없는 진술이다');
|
|
70
|
-
/* 값이 `null` 인 속성은 「지운다」는 뜻이므로 빈 진술이 아니다(위 검사가 이름 수를 세므로 통과한다). */
|
|
71
|
-
if (errors.length)
|
|
72
|
-
rejected.push({ record: r, errors });
|
|
73
|
-
else
|
|
74
|
-
accepted.push({ vocabularyType: r.vocabularyType, id: r.id, attributes: { ...r.attributes } });
|
|
75
|
-
}
|
|
76
|
-
return { accepted, rejected };
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* 클래스 단위 마스터 표 — 관측 리듀서가 든다.
|
|
80
|
-
*
|
|
81
|
-
* 물품은 자리마다 따로 서지만(`클래스@자리`) 이 속성은 **클래스의 것**이다. 그래서 물품마다 복사해
|
|
82
|
-
* 두지 않고 클래스로 한 번 들고, 물품을 세울 때 본다. 마스터가 관측보다 늦게 와도 값이 서는 이유다.
|
|
83
|
-
*/
|
|
84
|
-
export class ClassMasterTable {
|
|
85
|
-
byId = new Map();
|
|
86
|
-
/**
|
|
87
|
-
* 속성을 **합친다** — 덮지 않는다(한 번에 일부만 오는 원본이 있다). 바뀐 식별자를 돌려준다.
|
|
88
|
-
*
|
|
89
|
-
* ── 지우는 법 ───────────────────────────────────────────────────────────────
|
|
90
|
-
* 값에 `null` 을 실으면 **그 속성을 지운다**(「모름으로 되돌린다」). 합치기만 하면 원본에서 지운 값이
|
|
91
|
-
* 트윈에 영원히 남고, 그것을 표현할 방법이 없으면 「지웠다」와 「이번엔 말하지 않았다」가 같아진다.
|
|
92
|
-
*
|
|
93
|
-
* `undefined` 는 지우지 않는다 — 그것은 「이 진술에 그 속성이 없다」이고, 원본이 일부만 보내는
|
|
94
|
-
* 정상이다. 두 뜻을 갈라 둔다.
|
|
95
|
-
*
|
|
96
|
-
* 속성이 하나도 남지 않으면 그 요소를 표에서 버린다(빈 껍데기를 들고 있지 않는다).
|
|
97
|
-
*/
|
|
98
|
-
merge(elements) {
|
|
99
|
-
const touched = [];
|
|
100
|
-
for (const e of elements) {
|
|
101
|
-
const next = { ...(this.byId.get(e.id) ?? {}) };
|
|
102
|
-
for (const [name, value] of Object.entries(e.attributes)) {
|
|
103
|
-
if (value === null)
|
|
104
|
-
delete next[name];
|
|
105
|
-
else if (value !== undefined)
|
|
106
|
-
next[name] = value;
|
|
107
|
-
}
|
|
108
|
-
if (Object.keys(next).length)
|
|
109
|
-
this.byId.set(e.id, next);
|
|
110
|
-
else
|
|
111
|
-
this.byId.delete(e.id);
|
|
112
|
-
touched.push(e.id);
|
|
113
|
-
}
|
|
114
|
-
return touched;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* 그 식별자의 항목을 버린다 — **아무도 가리키지 않게 된 뒤**에만 부른다.
|
|
118
|
-
*
|
|
119
|
-
* 로트는 계속 새로 생기므로 이 표는 스스로 줄지 않는다. 하루 수백 로트면 1년에 수십만 항목이고,
|
|
120
|
-
* 그것을 아무도 지우지 않으면 재기동으로만 줄어든다(그리고 중간 저장본이 그만큼 커진다).
|
|
121
|
-
*/
|
|
122
|
-
forget(id) {
|
|
123
|
-
return this.byId.delete(id);
|
|
124
|
-
}
|
|
125
|
-
attributesOf(id) {
|
|
126
|
-
return id ? this.byId.get(id) : undefined;
|
|
127
|
-
}
|
|
128
|
-
get size() {
|
|
129
|
-
return this.byId.size;
|
|
130
|
-
}
|
|
131
|
-
serialize() {
|
|
132
|
-
return Object.fromEntries(this.byId);
|
|
133
|
-
}
|
|
134
|
-
restore(saved) {
|
|
135
|
-
this.byId.clear();
|
|
136
|
-
if (!isPlainObject(saved))
|
|
137
|
-
return;
|
|
138
|
-
for (const [id, attrs] of Object.entries(saved))
|
|
139
|
-
if (isPlainObject(attrs))
|
|
140
|
-
this.byId.set(id, { ...attrs });
|
|
141
|
-
}
|
|
142
|
-
clear() {
|
|
143
|
-
this.byId.clear();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/** 마스터 속성에서 유통기한을 읽는다 — 사건의 `ilmd` 와 **같은 이름**을 본다. */
|
|
147
|
-
export function expiryFromAttributes(attrs) {
|
|
148
|
-
return readEpochMs(attrs?.[ILMD_ATTR.expiry]);
|
|
149
|
-
}
|
|
150
|
-
/** 마스터 속성에서 로트 번호를 읽는다 — 사건의 `ilmd` 와 같은 이름. */
|
|
151
|
-
export function lotFromAttributes(attrs) {
|
|
152
|
-
const v = attrs?.[ILMD_ATTR.lot];
|
|
153
|
-
return typeof v === 'string' && v.trim() ? v.trim() : undefined;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* 시각 값을 밀리초로 — 숫자와 문자열을 모두 읽는다(원본이 둘 다 쓴다).
|
|
157
|
-
*
|
|
158
|
-
* 읽을 수 없으면 `undefined` 다. 「지금」으로 메우면 기한이 지난 재고가 멀쩡해 보이고, 0 으로 메우면
|
|
159
|
-
* 멀쩡한 재고가 기한 지난 것으로 보인다 — 둘 다 사실이 아니다.
|
|
160
|
-
*/
|
|
161
|
-
function readEpochMs(raw) {
|
|
162
|
-
if (typeof raw === 'number')
|
|
163
|
-
return Number.isFinite(raw) ? raw : undefined;
|
|
164
|
-
if (typeof raw !== 'string' || !raw.trim())
|
|
165
|
-
return undefined;
|
|
166
|
-
const at = Date.parse(raw);
|
|
167
|
-
return Number.isNaN(at) ? undefined : at;
|
|
168
|
-
}
|
package/dist/mes-profile.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { TwinTypeInfo } from './domain-catalog.ts';
|
|
2
|
-
export declare const MES_BIZSTEP: {
|
|
3
|
-
readonly receiving: "urn:epcglobal:cbv:bizstep:receiving";
|
|
4
|
-
readonly producing: "urn:epcglobal:cbv:bizstep:commissioning";
|
|
5
|
-
readonly storing: "urn:epcglobal:cbv:bizstep:storing";
|
|
6
|
-
};
|
|
7
|
-
/** 작업지시(Work Order) = 생산 오더 거래 유형. */
|
|
8
|
-
export declare const BTT_PRODORDER = "urn:epcglobal:cbv:btt:prodorder";
|
|
9
|
-
/** 직렬 SGTIN URI (원자재 단위·완제품). */
|
|
10
|
-
export declare function sgtinUri(companyPrefix: string, itemRef: string, serial: number): string;
|
|
11
|
-
/** MES 자리 타입 카탈로그 — 커널이 키로 쓰는 제조 로케이션 타입(locationByType/.type). 도메인 SSOT.
|
|
12
|
-
* 트레일러 제조 라인: 자재→프레임 절단→용접→도장→조립→완성차(kernel ROUTE 와 일치). */
|
|
13
|
-
export declare const MES_LOCATION_TYPES: readonly ["raw-store", "cut-station", "weld-station", "paint-booth", "assembly-line", "fg-store"];
|
|
14
|
-
export declare const MES_TYPES: TwinTypeInfo[];
|
package/dist/mes-profile.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// MES bizStep — CBV 재사용. producing = commissioning(신규 제품 커미셔닝).
|
|
2
|
-
export const MES_BIZSTEP = {
|
|
3
|
-
receiving: 'urn:epcglobal:cbv:bizstep:receiving', // 원자재 수령
|
|
4
|
-
producing: 'urn:epcglobal:cbv:bizstep:commissioning', // 생산(제품 최초 생성)
|
|
5
|
-
storing: 'urn:epcglobal:cbv:bizstep:storing' // 완제품 저장
|
|
6
|
-
};
|
|
7
|
-
/** 작업지시(Work Order) = 생산 오더 거래 유형. */
|
|
8
|
-
export const BTT_PRODORDER = 'urn:epcglobal:cbv:btt:prodorder';
|
|
9
|
-
/** 직렬 SGTIN URI (원자재 단위·완제품). */
|
|
10
|
-
export function sgtinUri(companyPrefix, itemRef, serial) {
|
|
11
|
-
return `urn:epc:id:sgtin:${companyPrefix}.${itemRef}.${serial}`;
|
|
12
|
-
}
|
|
13
|
-
/** MES 자리 타입 카탈로그 — 커널이 키로 쓰는 제조 로케이션 타입(locationByType/.type). 도메인 SSOT.
|
|
14
|
-
* 트레일러 제조 라인: 자재→프레임 절단→용접→도장→조립→완성차(kernel ROUTE 와 일치). */
|
|
15
|
-
export const MES_LOCATION_TYPES = ['raw-store', 'cut-station', 'weld-station', 'paint-booth', 'assembly-line', 'fg-store'];
|
|
16
|
-
/*
|
|
17
|
-
* 트윈 타입 서술(ADR-0018 확장) — 자리 키는 MES_LOCATION_TYPES 단일 출처에서 파생 + 설비(자원) 타입 추가.
|
|
18
|
-
* MES=ISA-95 앵커: 스테이션=WorkCenter, 저장소=bizLocation. 설비(가공설비)=Equipment/자산(GIAI). key 는 flow resourceType 과 일치.
|
|
19
|
-
*/
|
|
20
|
-
// label 은 언어 중립 i18n 키(twin.type.<key>) — cls(표준 클래스)만 자리별 메타로 유지. 사람 언어는 표현계층(L2).
|
|
21
|
-
const MES_LOCATION_CLS = {
|
|
22
|
-
'raw-store': { epcis: 'bizLocation' },
|
|
23
|
-
'cut-station': { isa95: 'WorkCenter', epcis: 'bizLocation' },
|
|
24
|
-
'weld-station': { isa95: 'WorkCenter', epcis: 'bizLocation' },
|
|
25
|
-
'paint-booth': { isa95: 'WorkCenter', epcis: 'bizLocation' },
|
|
26
|
-
'assembly-line': { isa95: 'WorkCenter', epcis: 'bizLocation' },
|
|
27
|
-
'fg-store': { epcis: 'bizLocation' }
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* 자리의 **ISA-95 계층 단** — 여기가 단이 가장 크게 갈리는 곳이다.
|
|
31
|
-
*
|
|
32
|
-
* · `assembly-line` = 라인 → `ProductionLine`(`WorkCenter` 의 한 종류)
|
|
33
|
-
* · `cut-station`·`weld-station`·`paint-booth` = 라인 안의 작업 자리 → `WorkCell`(`WorkUnit` 의 한 종류)
|
|
34
|
-
* · `raw-store`·`fg-store` = 보관 구역 → `StorageZone`
|
|
35
|
-
*
|
|
36
|
-
* ── 남은 어긋남 (2026-08-14, 지금 고치지 않는다) ─────────────────────────────
|
|
37
|
-
* 스테이션들의 `standardClass.isa95` 는 예전부터 `WorkCenter` 로 적혀 있다. 그런데 `WorkCenter` 는
|
|
38
|
-
* ProcessCell·ProductionLine·ProductionUnit·StorageZone 의 **총칭**이므로, 라인 안의 작업 자리는
|
|
39
|
-
* 엄밀히는 `WorkUnit` 계열이다. 즉 클래스 투영이 한 단 위를 가리키고 있다.
|
|
40
|
-
*
|
|
41
|
-
* 여기서 그것을 바꾸지 않는다: `standardClass` 는 적합성 표가 세는 값이고(`isa95-coverage`),
|
|
42
|
-
* 바꾸면 그 표의 숫자가 함께 움직인다. **단(`level`)과 클래스(`standardClass`)는 다른 축**이므로
|
|
43
|
-
* 단을 옳게 적는 것으로 계층 질의는 살아난다. 클래스 재검토는 적합성 표와 함께 다룰 일이다.
|
|
44
|
-
*/
|
|
45
|
-
const MES_LOCATION_LEVEL = {
|
|
46
|
-
'raw-store': 'StorageZone',
|
|
47
|
-
'cut-station': 'WorkCell',
|
|
48
|
-
'weld-station': 'WorkCell',
|
|
49
|
-
'paint-booth': 'WorkCell',
|
|
50
|
-
'assembly-line': 'ProductionLine',
|
|
51
|
-
'fg-store': 'StorageZone'
|
|
52
|
-
};
|
|
53
|
-
export const MES_TYPES = [
|
|
54
|
-
...MES_LOCATION_TYPES.map((k) => ({ key: k, role: 'location', label: `twin.type.${k}`, standardClass: MES_LOCATION_CLS[k] ?? {}, identity: { scheme: 'gs1:SGLN' }, level: MES_LOCATION_LEVEL[k], capabilities: ['storable'] })),
|
|
55
|
-
{ key: 'cutter', role: 'equipment', label: 'twin.type.cutter', standardClass: { isa95: 'Equipment', iso55000: 'Asset' }, identity: { scheme: 'gs1:GIAI' }, capabilities: ['processable', 'operable'] },
|
|
56
|
-
{ key: 'welder', role: 'equipment', label: 'twin.type.welder', standardClass: { isa95: 'Equipment', iso55000: 'Asset' }, identity: { scheme: 'gs1:GIAI' }, capabilities: ['processable', 'operable'] },
|
|
57
|
-
{ key: 'painter', role: 'equipment', label: 'twin.type.painter', standardClass: { isa95: 'Equipment', iso55000: 'Asset' }, identity: { scheme: 'gs1:GIAI' }, capabilities: ['processable', 'operable'] },
|
|
58
|
-
{ key: 'assembler', role: 'equipment', label: 'twin.type.assembler', standardClass: { isa95: 'Equipment', iso55000: 'Asset' }, identity: { scheme: 'gs1:GIAI' }, capabilities: ['processable', 'operable'] }
|
|
59
|
-
];
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { IngestResult } from './face2-adapter.ts';
|
|
2
|
-
/** 이 문이 받는 여섯 가지 — 리듀서가 다루는 것과 같은 목록(주목 확인은 우리 안의 행위라 제외). */
|
|
3
|
-
export type OperationalKind = 'task' | 'equipment' | 'person' | 'asset' | 'order' | 'quality' | 'test' | 'observation' | 'complete';
|
|
4
|
-
/**
|
|
5
|
-
* 정규 운영 레코드 — **델타의 필드 이름 + 시각(`at`)**.
|
|
6
|
-
*
|
|
7
|
-
* `at` 은 봉투의 `eventTime` 이 된다(리듀서가 늦게 온 옛 사실을 걸러내는 기준). 페이로드에는 싣지
|
|
8
|
-
* 않는다 — 델타에 없는 필드이고, 같은 사실이 두 시각을 갖지 않게.
|
|
9
|
-
*/
|
|
10
|
-
export interface OperationalRecordEnvelopeFields {
|
|
11
|
-
/** 발생 시각(ISO) — 없으면 `defaultEventTime`, 그것도 없으면 거부한다. */
|
|
12
|
-
at?: string;
|
|
13
|
-
/** 기록 시각(ISO) — 같은 발생 시각이 겹칠 때의 보조 순서. 리듀서가 페이로드에서 읽는다. */
|
|
14
|
-
recordTime?: string;
|
|
15
|
-
}
|
|
16
|
-
export type OperationalRecord = Record<string, unknown> & OperationalRecordEnvelopeFields;
|
|
17
|
-
export interface OperationalIngestOptions {
|
|
18
|
-
tenantId: string;
|
|
19
|
-
/** 레코드에 시각이 없을 때 쓸 값 — 주지 않으면 그 레코드를 거부한다. */
|
|
20
|
-
defaultEventTime?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* 이 레코드가 어느 운영 사실인가 — **라우팅 판정을 한 곳에 둔다**(소비처가 각자 짐작하지 않게).
|
|
24
|
-
*
|
|
25
|
-
* EPCIS·에너지와 겹치지 않게 본다: `epc`·`meterId` 가 있으면 그쪽 어휘이고, `equipmentId` 는 설비
|
|
26
|
-
* **에너지** 상태의 이름이다(운영 설비는 `moverId`). 품질은 설비와 정체 필드를 공유하므로 `good` 으로
|
|
27
|
-
* 가른다 — 둘 다 아니면 어느 쪽인지 모르는 것이고, 모르면 받지 않는다.
|
|
28
|
-
*
|
|
29
|
-
* ── 순서가 뜻을 갖는다: **주체와 참조는 다르다** ────────────────────────────
|
|
30
|
-
* 정체 필드는 하나만 오지 않는다. 설비·사람·자산 델타는 「지금 붙어 있는 작업」(`taskId`)을 함께 싣고,
|
|
31
|
-
* 작업 델타는 「소속 오더」(`orderId`)를 함께 싣는다. 그래서 아무 정체 필드나 먼저 보면 **참조를 주체로
|
|
32
|
-
* 읽는다** — 실제로 그랬다: `moverId` + `taskId` 인 설비 사실을 작업으로 읽어 「계약에 없는 필드」로
|
|
33
|
-
* 거부했다. 자원(설비·사람·자산)을 먼저 보고, 작업을 오더보다 먼저 본다.
|
|
34
|
-
*/
|
|
35
|
-
export declare function operationalKindOf(record: unknown): OperationalKind | undefined;
|
|
36
|
-
/** 이 레코드가 운영 사실인가 — 호스트의 라우팅이 묻는 자리. */
|
|
37
|
-
export declare function isOperationalRecord(record: unknown): boolean;
|
|
38
|
-
/**
|
|
39
|
-
* 운영 레코드들을 봉투로 — 유효한 것만 통과하고 나머지는 **이유와 함께** 남는다.
|
|
40
|
-
*
|
|
41
|
-
* 봉투는 다른 어휘와 같은 것을 쓴다(`CanonicalEnvelope`) — 그래서 저널·리플레이·시간여행·성과 폴드를
|
|
42
|
-
* 그대로 얻는다. 어휘만 자기 것이다.
|
|
43
|
-
*/
|
|
44
|
-
export declare function ingestOperationalRecords(records: OperationalRecord | OperationalRecord[] | undefined | null, opts: OperationalIngestOptions): IngestResult;
|