@prefixcheck/edi 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PrefixCheck
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # @prefixcheck/edi
2
+
3
+ Operator-grade EDIFACT **CODECO** + **COPRAR** decoder, **SMDG-aware** validator, and **cross-message reconciler** for container-shipping operations. Pure TypeScript, zero dependencies, browser- and Node-friendly.
4
+
5
+ ```bash
6
+ npm install @prefixcheck/edi
7
+ ```
8
+
9
+ ```ts
10
+ import { parse, diagnoseSingle, reconcile, SAMPLE_CODECO, SAMPLE_COPRAR } from "@prefixcheck/edi";
11
+
12
+ const parsed = parse(SAMPLE_CODECO);
13
+ console.log(parsed.message?.type); // "CODECO"
14
+ console.log(parsed.segments.length); // 30
15
+
16
+ const diags = diagnoseSingle(parsed);
17
+ console.log(diags); // [] when the message is clean
18
+
19
+ const coprar = parse(SAMPLE_COPRAR);
20
+ const codeco = parse(SAMPLE_CODECO);
21
+ const report = reconcile(coprar, codeco);
22
+ console.log(report.matched); // [{ number: "MSCU1234566", diffs: [] }]
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Why this library exists
28
+
29
+ Container-shipping EDI is a closed-world skill. The people who know CODECO and COPRAR sell consulting, not libraries. Existing open-source EDIFACT parsers tell you _what each segment is_; none of them tell you _what's wrong_ with the message you have, _speak SMDG_, _validate ISO 6346 check digits_, or _reconcile a COPRAR against its matching CODECO_. That's the gap this library fills.
30
+
31
+ Built on:
32
+
33
+ - **UN/EDIFACT D.00B** directories (UNECE)
34
+ - **SMDG 2.1.3 ST VGM** Implementation Guides for CODECO + COPRAR
35
+ - **SMDG Recommendation 07** (code lists), JM4/120 (FTX), JM4/272 (damage)
36
+ - **ISO 6346** mod-11 check-digit algorithm
37
+ - Operator-side guides from DAKOSY (Hamburg), Valenciaport PCS, Transnet, EPB Bilbao
38
+
39
+ ---
40
+
41
+ ## What's in the box
42
+
43
+ ### Parser (`parse`)
44
+
45
+ EDIFACT tokenizer that handles:
46
+
47
+ - Optional **UNA** service segment for delimiter overrides
48
+ - **UNB / UNZ** interchange envelope extraction
49
+ - **UNH / UNT** message envelope extraction
50
+ - Release-character escape (default `?`) for literal delimiters
51
+ - Whitespace normalisation between segments (handles both single-line and CR/LF-separated transmissions)
52
+ - Bare segment bodies, full interchanges, or anything in between
53
+
54
+ Output is a `ParsedMessage` with structured `segments[]`, envelope metadata, and warnings.
55
+
56
+ ### Schema (`SEGMENTS`, `CODE_LISTS`, `CODECO`, `COPRAR`)
57
+
58
+ A 32-segment dictionary with operator-grade explanations for every common CODECO/COPRAR segment, plus 17 code-list lookups:
59
+
60
+ | List | Codes | Source |
61
+ | ------------------------------------------- | ------------------------------ | ----------------------------- |
62
+ | `BGM.docname`, `BGM.function` | Document + function codes | UN/CEFACT 1001, 1225 |
63
+ | `DTM.qualifier`, `DTM.format` | Date/time qualifiers + formats | UN/CEFACT 2005, 2379 |
64
+ | `LOC.qualifier` | Place qualifiers | UN/CEFACT 3227 |
65
+ | `EQD.type`, `EQD.supplier`, `EQD.fullEmpty` | Equipment metadata | UN/CEFACT 8053, 8077, 8169 |
66
+ | `STS.code` | Status codes + SMDG attributes | UN/CEFACT 9015 + SMDG JM4/170 |
67
+ | `RFF.qualifier` | Reference qualifiers | UN/CEFACT 1153 |
68
+ | `NAD.party` | Party qualifiers | UN/CEFACT 3035 |
69
+ | `MEA.qualifier`, `MEA.unit` | Measurement + units | UN/CEFACT 6313, 6411 |
70
+ | `VGM.method` | SOLAS VGM method codes | SMDG 2.1.3 ST VGM |
71
+ | `HAN.code` | Handling instruction codes | UN/CEFACT 4079 + SMDG JM4/121 |
72
+ | `SEL.party` | Seal-applying party | UN/CEFACT 9303 |
73
+ | `FTX.qualifier` | Free text qualifiers | UN/CEFACT 4451 |
74
+ | `TDT.mode`, `TDT.idCodeList` | Transport mode + ID code lists | UN/CEFACT 8067, 1131 |
75
+ | `CNT.qualifier` | Control total qualifiers | UN/CEFACT 6069 |
76
+ | `UNB.syntax` | Syntax level codes | UN/CEFACT 0001 |
77
+
78
+ ### Diagnostics (`diagnoseSingle`)
79
+
80
+ Eleven validation rules implementing the operator-grade checks that paid EDI consultants run:
81
+
82
+ | Code | Level | Catches |
83
+ | -------------------- | ----------- | ------------------------------------------------ |
84
+ | `BAD_CHECK_DIGIT` | error | Container number fails ISO 6346 mod-11 |
85
+ | `BAD_BIC_FORMAT` | warn | Equipment ID not in 4-letter + 7-digit shape |
86
+ | `BAD_LOCODE_FORMAT` | warn | LOC place doesn't match UN/LOCODE pattern |
87
+ | `DTM_FORMAT` | warn / info | Date format not SMDG-mandated 203 |
88
+ | `MISSING_NAD_CF` | error | No container operator party (SMDG requires it) |
89
+ | `EMPTY_BUT_HEAVY` | error | EQD declared empty but gross weight exceeds tare |
90
+ | `UNKNOWN_SIZETYPE` | warn | ISO 4-char size-type not in catalogue |
91
+ | `UNT_COUNT_WRONG` | error | UNT count ≠ actual UNH→UNT inclusive count |
92
+ | `CNT_EQD_MISMATCH` | error | CNT+16 disagrees with EQD count |
93
+ | `REEFER_WITHOUT_TMP` | warn | R-type ISO size but no TMP setpoint |
94
+ | `LOAD_BUT_EMPTY` | warn | COPRAR Load order but EQD declares empty |
95
+ | `MISSING_VGM` | warn | Full container on Load order missing SOLAS VGM |
96
+ | `CHARSET_LOWERCASE` | warn | UNB declares UNOA but body contains lowercase |
97
+
98
+ ### Reconcile (`reconcile`)
99
+
100
+ Cross-message matching for a COPRAR + its matching CODECO. For every shared container number, compares the relevant operator-level fields and surfaces diffs at the right severity:
101
+
102
+ | Field | Tolerance | Severity |
103
+ | ------------------ | ----------- | -------- |
104
+ | ISO size-type | exact match | error |
105
+ | Full/empty | exact match | error |
106
+ | POL | exact match | error |
107
+ | POD | exact match | error |
108
+ | Booking ref | exact match | warn |
109
+ | Gross weight | ±2% | warn |
110
+ | VGM | ±5% | warn |
111
+ | Reefer temperature | ±1°C | warn |
112
+
113
+ Also returns:
114
+
115
+ - `matched[]` — containers in both messages, with field-level diffs
116
+ - `inCoprarOnly[]` — expected on load list but never gated
117
+ - `inCodecoOnly[]` — gated but not on the load list
118
+
119
+ ---
120
+
121
+ ## API
122
+
123
+ ### `parse(rawInput: string): ParsedMessage`
124
+
125
+ Tokenize raw EDIFACT text. Accepts bare message bodies or full interchanges. Always returns a `ParsedMessage` — never throws.
126
+
127
+ ### `diagnoseSingle(parsed: ParsedMessage): Diagnostic[]`
128
+
129
+ Run all single-message diagnostic rules. Empty array = clean.
130
+
131
+ ### `reconcile(coprar: ParsedMessage, codeco: ParsedMessage): ReconcileReport`
132
+
133
+ Cross-message reconciliation. See the table above for fields and tolerances.
134
+
135
+ ### `detectMessageType(parsed: ParsedMessage): "CODECO" | "COPRAR" | null`
136
+
137
+ Detect the message type. Checks UNH first, falls back to BGM document code.
138
+
139
+ ### `lookup(listName: string, code: string): string | null`
140
+
141
+ Decode any code-list value to plain English. See the code-list table above for the available `listName` values.
142
+
143
+ ### `segmentInfo(tag: string): SegmentInfo`
144
+
145
+ Get the operator-grade English explanation for a 3-letter segment tag. Returns a fallback for unknown tags.
146
+
147
+ ### `validateCheckDigit(code: string): boolean`
148
+
149
+ ISO 6346 mod-11 check-digit validation. Same algorithm used by all major terminal operating systems.
150
+
151
+ ### `decodeISOSizeType(code: string): string | null`
152
+
153
+ Decode a 4-character ISO 6346 size-type code (e.g. `45R1`) into operator-readable parts (`40ft · Integral reefer · 9ft 6in (high cube) · variant 1`).
154
+
155
+ ### `extractContainerNumbers(parsed: ParsedMessage): string[]` / `extractUNLocodes(parsed: ParsedMessage): string[]`
156
+
157
+ Find every ISO 6346-shaped container number / 5-character UN/LOCODE in a parsed message. Useful for cross-referencing to external registries.
158
+
159
+ ### `SAMPLE_CODECO` / `SAMPLE_COPRAR`
160
+
161
+ Real-shape SMDG 2.1.3 D.00B sample messages with valid ISO 6346 check digits. Use for demos, tests, and documentation. The two samples share container `MSCU1234566` so `reconcile()` produces a clean match.
162
+
163
+ ---
164
+
165
+ ## TypeScript
166
+
167
+ Full type definitions are bundled. Import the type-only surface if you need it:
168
+
169
+ ```ts
170
+ import type {
171
+ ParsedMessage,
172
+ Segment,
173
+ Diagnostic,
174
+ ReconcileReport,
175
+ MessageType,
176
+ MessageSchema,
177
+ } from "@prefixcheck/edi";
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Browser usage
183
+
184
+ Works in any modern browser via a bundler (Vite, Rollup, Webpack, esbuild). No DOM or Node-only APIs are used.
185
+
186
+ The companion in-browser decoder lives at [prefixcheck.com/container-edi/](https://prefixcheck.com/container-edi/) — same parser, same schemas, same diagnostics, with a UI.
187
+
188
+ ---
189
+
190
+ ## What this library does NOT do
191
+
192
+ - **Send or receive messages.** This is a read-side library. It does not transmit, queue, or talk to any EDI VAN or carrier network.
193
+ - **Generate messages from scratch.** Decoding is one direction. Building a CODECO or COPRAR for transmission still needs the terminal operating system (Navis, CATOS, RBS) or an EDI authoring tool.
194
+ - **Persist or aggregate.** Each call to `parse()` is stateless. The library has no storage layer.
195
+ - **Cover every EDIFACT message type.** Scope is CODECO + COPRAR. Other container-shipping messages (BAPLIE, IFTSTA, IFTMIN, COREOR, COARRI, VERMAS, COPARN) are not implemented in this release.
196
+
197
+ ---
198
+
199
+ ## License
200
+
201
+ MIT
@@ -0,0 +1,5 @@
1
+ export { parse, extractContainerNumbers, extractUNLocodes, DEFAULT_DELIMITERS } from "./parser.js";
2
+ export { validateCheckDigit, decodeISOSizeType, detectMessageType, lookup, segmentInfo, diagnoseSingle, reconcile, CODECO, COPRAR, SEGMENTS, CODE_LISTS, type SegmentInfo, } from "./schemas.js";
3
+ export { SAMPLE_CODECO, SAMPLE_COPRAR } from "./samples.js";
4
+ export type { Delimiters, Segment, Interchange, Message, ParsedMessage, Diagnostic, ReconcileDiff, MatchedContainer, ReconcileReport, MessageType, MessageSchema, } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEnG,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,EACN,WAAW,EACX,cAAc,EACd,SAAS,EACT,MAAM,EACN,MAAM,EACN,QAAQ,EACR,UAAU,EACV,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE5D,YAAY,EACV,UAAU,EACV,OAAO,EACP,WAAW,EACX,OAAO,EACP,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ // ============================================================
2
+ // @prefixcheck/edi · public entry
3
+ //
4
+ // Operator-grade EDIFACT CODECO + COPRAR decoder, SMDG validator,
5
+ // and COPRAR ↔ CODECO reconciler. Pure TypeScript, zero deps,
6
+ // browser- and Node-friendly.
7
+ //
8
+ // Quick start:
9
+ //
10
+ // import { parse, diagnoseSingle, reconcile, SAMPLE_CODECO } from "@prefixcheck/edi";
11
+ //
12
+ // const parsed = parse(SAMPLE_CODECO);
13
+ // console.log(parsed.message?.type); // "CODECO"
14
+ // console.log(parsed.segments.length); // 30
15
+ //
16
+ // const diags = diagnoseSingle(parsed);
17
+ // console.log(diags); // [] when clean
18
+ //
19
+ // const coprar = parse(coprarText);
20
+ // const codeco = parse(codecoText);
21
+ // const report = reconcile(coprar, codeco);
22
+ // console.log(report.matched.length, "matched");
23
+ //
24
+ // See the README for the full API + diagnostic rule catalogue.
25
+ // ============================================================
26
+ export { parse, extractContainerNumbers, extractUNLocodes, DEFAULT_DELIMITERS } from "./parser.js";
27
+ export { validateCheckDigit, decodeISOSizeType, detectMessageType, lookup, segmentInfo, diagnoseSingle, reconcile, CODECO, COPRAR, SEGMENTS, CODE_LISTS, } from "./schemas.js";
28
+ export { SAMPLE_CODECO, SAMPLE_COPRAR } from "./samples.js";
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kCAAkC;AAClC,EAAE;AACF,kEAAkE;AAClE,8DAA8D;AAC9D,8BAA8B;AAC9B,EAAE;AACF,eAAe;AACf,EAAE;AACF,wFAAwF;AACxF,EAAE;AACF,yCAAyC;AACzC,6DAA6D;AAC7D,uDAAuD;AACvD,EAAE;AACF,0CAA0C;AAC1C,kEAAkE;AAClE,EAAE;AACF,sCAAsC;AACtC,sCAAsC;AACtC,8CAA8C;AAC9C,mDAAmD;AACnD,EAAE;AACF,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEnG,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,MAAM,EACN,WAAW,EACX,cAAc,EACd,SAAS,EACT,MAAM,EACN,MAAM,EACN,QAAQ,EACR,UAAU,GAEX,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { Delimiters, ParsedMessage } from "./types.js";
2
+ export declare const DEFAULT_DELIMITERS: Delimiters;
3
+ /**
4
+ * Tokenize a raw EDIFACT string into structured form.
5
+ *
6
+ * Accepts any of:
7
+ * - bare message body (UNH ... UNT)
8
+ * - full interchange (optional UNA, UNB ... UNZ wrapping one or more messages)
9
+ * - whitespace-separated segments (newlines between `'` terminators)
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { parse } from "@prefixcheck/edi";
14
+ * const parsed = parse("UNH+1+CODECO:D:00B:UN:SMDG21'BGM+34+REF+9'...");
15
+ * console.log(parsed.message?.type); // "CODECO"
16
+ * ```
17
+ */
18
+ export declare function parse(rawInput: string): ParsedMessage;
19
+ /**
20
+ * Extract every ISO 6346-shaped container number (4 letters + 7 digits)
21
+ * found anywhere in the parsed message. Useful for cross-referencing
22
+ * to a registry or driving downstream linking.
23
+ */
24
+ export declare function extractContainerNumbers(parsed: ParsedMessage): string[];
25
+ /**
26
+ * Extract every UN/LOCODE-shaped token (5 chars: 2-letter country
27
+ * code + 3-letter/digit location code) from LOC segments specifically.
28
+ */
29
+ export declare function extractUNLocodes(parsed: ParsedMessage): string[];
30
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,UAAU,EAAwB,aAAa,EAAW,MAAM,YAAY,CAAC;AAE3F,eAAO,MAAM,kBAAkB,EAAE,UAOjB,CAAC;AA6IjB;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CA8CrD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAcvE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,EAAE,CAYhE"}
package/dist/parser.js ADDED
@@ -0,0 +1,247 @@
1
+ // ============================================================
2
+ // @prefixcheck/edi · EDIFACT tokenizer + envelope handling
3
+ //
4
+ // Universal layer that turns raw EDIFACT text into a structured
5
+ // object tree. The schema layer (CODECO/COPRAR validation) runs
6
+ // on top of this and is loaded separately so new message types
7
+ // can be added without touching the parser.
8
+ //
9
+ // EDIFACT delimiter conventions:
10
+ // element separator default '+'
11
+ // composite separator default ':'
12
+ // segment terminator default "'"
13
+ // release character default '?' (escapes the next char)
14
+ // decimal default '.' (or ',')
15
+ // repetition default '*'
16
+ //
17
+ // The optional UNA segment at the start of an interchange overrides
18
+ // the defaults. Format: `UNA:+.? '` — exactly 6 single-character
19
+ // overrides in the order: composite, element, decimal, release,
20
+ // repetition, segment.
21
+ // ============================================================
22
+ export const DEFAULT_DELIMITERS = Object.freeze({
23
+ element: "+",
24
+ composite: ":",
25
+ segment: "'",
26
+ release: "?",
27
+ decimal: ".",
28
+ repetition: "*",
29
+ });
30
+ function parseUNA(raw) {
31
+ if (raw.length < 9 || raw.slice(0, 3) !== "UNA") {
32
+ return { delimiters: { ...DEFAULT_DELIMITERS }, rest: raw };
33
+ }
34
+ const spec = raw.slice(3, 9);
35
+ return {
36
+ delimiters: {
37
+ composite: spec[0],
38
+ element: spec[1],
39
+ decimal: spec[2],
40
+ release: spec[3],
41
+ repetition: spec[4],
42
+ segment: spec[5],
43
+ },
44
+ rest: raw.slice(9),
45
+ };
46
+ }
47
+ /**
48
+ * Split text by an unescaped delimiter character. A delimiter preceded
49
+ * by the release character (default `?`) is a literal, not a delimiter.
50
+ *
51
+ * Note: this function PRESERVES release-character escape sequences in
52
+ * the output. The escape (`?X`) stays as `?X` so that downstream splits
53
+ * (e.g., element → composite → sub-element) can also honour escapes.
54
+ * The final value layer strips escapes with `unescape()`.
55
+ */
56
+ function splitUnescaped(text, delim, release) {
57
+ const parts = [];
58
+ let buf = "";
59
+ for (let i = 0; i < text.length; i++) {
60
+ const c = text[i];
61
+ if (c === release && i + 1 < text.length) {
62
+ buf += c + text[i + 1];
63
+ i++;
64
+ continue;
65
+ }
66
+ if (c === delim) {
67
+ parts.push(buf);
68
+ buf = "";
69
+ continue;
70
+ }
71
+ buf += c;
72
+ }
73
+ parts.push(buf);
74
+ return parts;
75
+ }
76
+ /**
77
+ * Strip release-character escape sequences from a sub-element value.
78
+ * Called only at the leaf layer, after all splitting is done.
79
+ */
80
+ function unescape(text, release) {
81
+ let out = "";
82
+ for (let i = 0; i < text.length; i++) {
83
+ if (text[i] === release && i + 1 < text.length) {
84
+ out += text[i + 1];
85
+ i++;
86
+ }
87
+ else {
88
+ out += text[i];
89
+ }
90
+ }
91
+ return out;
92
+ }
93
+ /**
94
+ * Strip whitespace following each segment terminator without touching
95
+ * content inside segments. Human-readable transmission commonly
96
+ * inserts `\r\n` after each terminator; not part of the standard
97
+ * but ubiquitous in archived files and operator pastes.
98
+ */
99
+ function normalizeWhitespace(text, segDelim) {
100
+ let out = "";
101
+ for (let i = 0; i < text.length; i++) {
102
+ const c = text[i];
103
+ out += c;
104
+ if (c === segDelim) {
105
+ while (i + 1 < text.length && /\s/.test(text[i + 1]))
106
+ i++;
107
+ }
108
+ }
109
+ return out;
110
+ }
111
+ function extractEnvelopes(segments) {
112
+ let interchange = null;
113
+ let message = null;
114
+ const warnings = [];
115
+ const first = segments[0];
116
+ const last = segments[segments.length - 1];
117
+ if (first && first.tag === "UNB") {
118
+ interchange = {
119
+ syntaxId: (first.elements[0] || [])[0] || "",
120
+ syntaxVer: (first.elements[0] || [])[1] || "",
121
+ sender: (first.elements[1] || [])[0] || "",
122
+ senderQual: (first.elements[1] || [])[1] || "",
123
+ recipient: (first.elements[2] || [])[0] || "",
124
+ recipQual: (first.elements[2] || [])[1] || "",
125
+ dateTime: (first.elements[3] || []).join(":") || "",
126
+ controlRef: (first.elements[4] || [])[0] || "",
127
+ };
128
+ if (!last || last.tag !== "UNZ") {
129
+ warnings.push("UNB interchange header found but no UNZ trailer.");
130
+ }
131
+ }
132
+ for (let i = 0; i < segments.length; i++) {
133
+ if (segments[i].tag === "UNH") {
134
+ const unh = segments[i];
135
+ message = {
136
+ controlRef: (unh.elements[0] || [])[0] || "",
137
+ type: (unh.elements[1] || [])[0] || "",
138
+ version: (unh.elements[1] || [])[1] || "",
139
+ release: (unh.elements[1] || [])[2] || "",
140
+ agency: (unh.elements[1] || [])[3] || "",
141
+ assocCode: (unh.elements[1] || [])[4] || "",
142
+ };
143
+ break;
144
+ }
145
+ }
146
+ if (!message) {
147
+ warnings.push("No UNH message header found. Parsed as raw segment body.");
148
+ }
149
+ return { interchange, message, envelopeWarnings: warnings };
150
+ }
151
+ /**
152
+ * Tokenize a raw EDIFACT string into structured form.
153
+ *
154
+ * Accepts any of:
155
+ * - bare message body (UNH ... UNT)
156
+ * - full interchange (optional UNA, UNB ... UNZ wrapping one or more messages)
157
+ * - whitespace-separated segments (newlines between `'` terminators)
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * import { parse } from "@prefixcheck/edi";
162
+ * const parsed = parse("UNH+1+CODECO:D:00B:UN:SMDG21'BGM+34+REF+9'...");
163
+ * console.log(parsed.message?.type); // "CODECO"
164
+ * ```
165
+ */
166
+ export function parse(rawInput) {
167
+ if (!rawInput || typeof rawInput !== "string") {
168
+ return {
169
+ interchange: null,
170
+ message: null,
171
+ segments: [],
172
+ delimiters: { ...DEFAULT_DELIMITERS },
173
+ envelopeWarnings: ["Empty input."],
174
+ };
175
+ }
176
+ // Strip BOM + outer whitespace
177
+ const trimmed = rawInput.replace(/^/, "").trim();
178
+ const unaResult = parseUNA(trimmed);
179
+ const delim = unaResult.delimiters;
180
+ const body = normalizeWhitespace(unaResult.rest, delim.segment);
181
+ const rawSegments = splitUnescaped(body, delim.segment, delim.release);
182
+ const segments = [];
183
+ let bodyIndex = 0;
184
+ for (let s = 0; s < rawSegments.length; s++) {
185
+ const segText = rawSegments[s].trim();
186
+ if (!segText)
187
+ continue;
188
+ const elements = splitUnescaped(segText, delim.element, delim.release);
189
+ const tagRaw = elements.shift() || "";
190
+ const tag = unescape(tagRaw, delim.release);
191
+ // Composite split → unescape each leaf sub-element value.
192
+ const composed = elements.map((el) => splitUnescaped(el, delim.composite, delim.release).map((v) => unescape(v, delim.release)));
193
+ segments.push({
194
+ tag,
195
+ index: bodyIndex++,
196
+ elements: composed,
197
+ raw: unescape(segText, delim.release),
198
+ });
199
+ }
200
+ const env = extractEnvelopes(segments);
201
+ return {
202
+ interchange: env.interchange,
203
+ message: env.message,
204
+ segments,
205
+ delimiters: delim,
206
+ envelopeWarnings: env.envelopeWarnings,
207
+ };
208
+ }
209
+ /**
210
+ * Extract every ISO 6346-shaped container number (4 letters + 7 digits)
211
+ * found anywhere in the parsed message. Useful for cross-referencing
212
+ * to a registry or driving downstream linking.
213
+ */
214
+ export function extractContainerNumbers(parsed) {
215
+ const pattern = /\b[A-Z]{4}\d{7}\b/g;
216
+ const seen = new Set();
217
+ const out = [];
218
+ for (const seg of parsed.segments) {
219
+ const matches = seg.raw.match(pattern) || [];
220
+ for (const m of matches) {
221
+ if (!seen.has(m)) {
222
+ seen.add(m);
223
+ out.push(m);
224
+ }
225
+ }
226
+ }
227
+ return out;
228
+ }
229
+ /**
230
+ * Extract every UN/LOCODE-shaped token (5 chars: 2-letter country
231
+ * code + 3-letter/digit location code) from LOC segments specifically.
232
+ */
233
+ export function extractUNLocodes(parsed) {
234
+ const seen = new Set();
235
+ const out = [];
236
+ for (const seg of parsed.segments) {
237
+ if (seg.tag !== "LOC")
238
+ continue;
239
+ const place = (seg.elements[1] || [])[0];
240
+ if (place && /^[A-Z]{2}[A-Z0-9]{3}$/.test(place) && !seen.has(place)) {
241
+ seen.add(place);
242
+ out.push(place);
243
+ }
244
+ }
245
+ return out;
246
+ }
247
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A complete SMDG-shape CODECO message: gate-in report from
3
+ * terminal ECT Rotterdam to carrier MSC, one full 40-foot
4
+ * high-cube container (MSCU1234566) bound for New York.
5
+ */
6
+ export declare const SAMPLE_CODECO = "UNA:+.? '\nUNB+UNOA:2+TERMINAL01:ZZZ+MSCU:ZZZ+260524:1430+CDC00012345'\nUNH+CDC0001+CODECO:D:00B:UN:SMDG21'\nBGM+34:::TRANSPORT EQUIPMENT GATE IN REPORT+CDC0001+9'\nDTM+137:202605241430:203'\nTDT+20+251NB+3+31+MSCU:172:20'\nLOC+9+NLRTM:139:6+ECT:TER:ZZZ'\nDTM+178:202605241425:203'\nNAD+CF+MSC:160:20'\nNAD+TR+ECT:160:20'\nNAD+CA+MSCU:172:20'\nEQD+CN+MSCU1234566+45G1:102:5++2+4'\nRFF+BN:BKG778899'\nRFF+BM:MSCUNLRTM0042'\nRFF+EQ:MSCU1234566'\nDTM+178:202605241425:203'\nLOC+9+NLRTM:139:6+ECT:TER:ZZZ'\nLOC+11+USNYC:139:6'\nLOC+165+USNYC:139:6'\nMEA+AAE+AET+KGM:28450'\nMEA+AAL++KGM:3920'\nMEA+VGM++KGM:28450'\nSEL+CN789456+CA'\nSEL+TR556677+TR'\nFTX+AAA+++FULL CONTAINER GATE IN'\nEQA+CH+CHSU0099887'\nSTS+1+2'\nDTM+178:202605241430:203'\nCNT+16:1'\nUNT+28+CDC0001'\nUNZ+1+CDC00012345'";
7
+ /**
8
+ * A complete SMDG-shape COPRAR Load order: carrier MSC instructs
9
+ * terminal ECT Rotterdam to load three containers on vessel
10
+ * MSC MAYA (voyage 251NB) bound for New York. The first container
11
+ * (MSCU1234566) matches the CODECO sample above so the pair
12
+ * cross-reconciles cleanly. Container 3 is a frozen reefer.
13
+ */
14
+ export declare const SAMPLE_COPRAR = "UNA:+.? '\nUNB+UNOA:2+MSCU:ZZZ+TERMINAL01:ZZZ+260524:1200+CPR00098765'\nUNH+CPR0001+COPRAR:D:00B:UN:SMDG21'\nBGM+45+CPR0001+9'\nDTM+137:202605241200:203'\nRFF+XXX:VOY-251NB-LOAD'\nTDT+20+251NB+1+13+MSCU:172:20+++9876543:146:11::MSC MAYA'\nLOC+9+NLRTM:139:6+ECT:TER:ZZZ'\nDTM+133:202605260800:203'\nLOC+11+USNYC:139:6'\nDTM+132:202606051400:203'\nNAD+CA+MSCU:172:20'\nNAD+CF+MSC:160:20'\nNAD+TR+ECT:160:20'\nEQD+CN+MSCU1234566+45G1:102:5++4+4'\nRFF+BN:BKG778899'\nRFF+BM:MSCUNLRTM0042'\nLOC+9+NLRTM:139:6'\nLOC+11+USNYC:139:6'\nMEA+AAE++KGM:28450'\nMEA+AAL++KGM:3920'\nMEA+VGM++KGM:28450'\nTPL+++147:021082'\nEQD+CN+MSCU2345672+22G1:102:5++4+4'\nRFF+BN:BKG778900'\nRFF+BM:MSCUNLRTM0043'\nLOC+9+NLRTM:139:6'\nLOC+11+USNYC:139:6'\nMEA+AAE++KGM:18200'\nMEA+AAL++KGM:2230'\nMEA+VGM++KGM:18200'\nTPL+++147:019084'\nEQD+CN+MSCU3456789+45R1:102:5++4+4'\nRFF+BN:BKG778901'\nRFF+BM:MSCUNLRTM0044'\nLOC+9+NLRTM:139:6'\nLOC+11+USNYC:139:6'\nTMP+2+-018:CEL'\nRNG+5+CEL:-020:-015'\nMEA+AAE++KGM:27800'\nMEA+AAL++KGM:4500'\nMEA+VGM++KGM:27800'\nEQA+RG+MSCG0001122'\nTPL+++147:023086'\nCNT+16:3'\nCNT+7:5'\nUNT+46+CPR0001'\nUNZ+1+CPR00098765'";
15
+ //# sourceMappingURL=samples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"samples.d.ts","sourceRoot":"","sources":["../src/samples.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,eAAO,MAAM,aAAa,uxBA8BP,CAAC;AAEpB;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,2mCA+CP,CAAC"}