@flaks/onerecord 0.1.2 → 0.2.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.
Files changed (74) hide show
  1. package/CHANGELOG.md +215 -5
  2. package/MIGRATING.md +77 -5
  3. package/README.md +62 -10
  4. package/dist/booking-flow/index.d.ts +1 -1
  5. package/dist/booking-flow/index.d.ts.map +1 -1
  6. package/dist/booking-flow/index.js +1 -1
  7. package/dist/booking-flow/index.js.map +1 -1
  8. package/dist/booking-flow/transitions.d.ts +21 -0
  9. package/dist/booking-flow/transitions.d.ts.map +1 -1
  10. package/dist/booking-flow/transitions.js +57 -5
  11. package/dist/booking-flow/transitions.js.map +1 -1
  12. package/dist/codes/fsu-event-codes.d.ts +6 -6
  13. package/dist/codes/fsu-event-codes.d.ts.map +1 -1
  14. package/dist/codes/fsu-event-codes.js +11 -9
  15. package/dist/codes/fsu-event-codes.js.map +1 -1
  16. package/dist/dispatch/context-order.d.ts +28 -0
  17. package/dist/dispatch/context-order.d.ts.map +1 -0
  18. package/dist/dispatch/context-order.js +21 -0
  19. package/dist/dispatch/context-order.js.map +1 -0
  20. package/dist/dispatch/domain-constraints.d.ts +44 -0
  21. package/dist/dispatch/domain-constraints.d.ts.map +1 -0
  22. package/dist/dispatch/domain-constraints.js +69 -0
  23. package/dist/dispatch/domain-constraints.js.map +1 -0
  24. package/dist/dispatch/field-types.d.ts +30 -0
  25. package/dist/dispatch/field-types.d.ts.map +1 -0
  26. package/dist/dispatch/field-types.js +88 -0
  27. package/dist/dispatch/field-types.js.map +1 -0
  28. package/dist/dispatch/graph-walk.d.ts +23 -0
  29. package/dist/dispatch/graph-walk.d.ts.map +1 -0
  30. package/dist/dispatch/graph-walk.js +206 -0
  31. package/dist/dispatch/graph-walk.js.map +1 -0
  32. package/dist/dispatch/index.d.ts +30 -0
  33. package/dist/dispatch/index.d.ts.map +1 -0
  34. package/dist/dispatch/index.js +36 -0
  35. package/dist/dispatch/index.js.map +1 -0
  36. package/dist/dispatch/iri-canonical.d.ts +28 -0
  37. package/dist/dispatch/iri-canonical.d.ts.map +1 -0
  38. package/dist/dispatch/iri-canonical.js +55 -0
  39. package/dist/dispatch/iri-canonical.js.map +1 -0
  40. package/dist/error/format.d.ts.map +1 -1
  41. package/dist/error/format.js +8 -0
  42. package/dist/error/format.js.map +1 -1
  43. package/dist/facade.d.ts +42 -0
  44. package/dist/facade.d.ts.map +1 -1
  45. package/dist/facade.js +8 -0
  46. package/dist/facade.js.map +1 -1
  47. package/dist/factory.d.ts +12 -0
  48. package/dist/factory.d.ts.map +1 -1
  49. package/dist/factory.js +10 -1
  50. package/dist/factory.js.map +1 -1
  51. package/dist/index.d.ts +12 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +10 -1
  54. package/dist/index.js.map +1 -1
  55. package/dist/iri/dereference.d.ts +42 -0
  56. package/dist/iri/dereference.d.ts.map +1 -0
  57. package/dist/iri/dereference.js +75 -0
  58. package/dist/iri/dereference.js.map +1 -0
  59. package/dist/result.d.ts +27 -1
  60. package/dist/result.d.ts.map +1 -1
  61. package/dist/result.js +9 -0
  62. package/dist/result.js.map +1 -1
  63. package/dist/safety/blank-node.d.ts +20 -0
  64. package/dist/safety/blank-node.d.ts.map +1 -0
  65. package/dist/safety/blank-node.js +59 -0
  66. package/dist/safety/blank-node.js.map +1 -0
  67. package/dist/safety/pre-validate.d.ts.map +1 -1
  68. package/dist/safety/pre-validate.js +12 -72
  69. package/dist/safety/pre-validate.js.map +1 -1
  70. package/dist/safety/walk-graph.d.ts +30 -0
  71. package/dist/safety/walk-graph.d.ts.map +1 -0
  72. package/dist/safety/walk-graph.js +100 -0
  73. package/dist/safety/walk-graph.js.map +1 -0
  74. package/package.json +3 -4
@@ -1,30 +1,32 @@
1
- // Codes verified against IATA-Cargo XFSU-Status-Codes.xlsx via the fixture
2
- // at test/fixtures/iata/xfsu-status-codes.json (Task 37a). Per spec
3
- // acceptance #2: exactly 26 codes.
1
+ // Codes derived from IATA-Cargo XFSU Status Codes.xlsx via the sibling
2
+ // onerecord-xlsx-tools convert script; pinned by SHA256 of the upstream
3
+ // xlsx blob in test/fixtures/iata/xfsu-status-codes.json. v0.2.0 adopted
4
+ // the upstream 26 codes (Phase 0.2 Outcome C, see spec §2.4); 6 codes
5
+ // changed in each direction vs. the v0.1.x hand-pin.
4
6
  export const FSU_EVENT_CODES = Object.freeze({
5
7
  ARR: 'ARR',
6
8
  AWD: 'AWD',
7
9
  AWR: 'AWR',
8
10
  BKD: 'BKD',
9
11
  CCD: 'CCD',
10
- CLR: 'CLR',
11
12
  CRC: 'CRC',
12
13
  DDL: 'DDL',
13
14
  DEP: 'DEP',
14
15
  DIS: 'DIS',
15
16
  DLV: 'DLV',
17
+ DOC: 'DOC',
18
+ DPU: 'DPU',
19
+ FIW: 'FIW',
16
20
  FOH: 'FOH',
17
- FOO: 'FOO',
18
- FWB: 'FWB',
21
+ FOW: 'FOW',
19
22
  MAN: 'MAN',
20
23
  NFD: 'NFD',
21
- OFD: 'OFD',
24
+ OCI: 'OCI',
25
+ OSI: 'OSI',
22
26
  PRE: 'PRE',
23
27
  RCF: 'RCF',
24
- RCM: 'RCM',
25
28
  RCS: 'RCS',
26
29
  RCT: 'RCT',
27
- RCV: 'RCV',
28
30
  TFD: 'TFD',
29
31
  TGC: 'TGC',
30
32
  TRM: 'TRM',
@@ -1 +1 @@
1
- {"version":3,"file":"fsu-event-codes.js","sourceRoot":"","sources":["../../src/codes/fsu-event-codes.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,oEAAoE;AACpE,mCAAmC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;CACF,CAAC,CAAA;AASX,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;AACjC,CAAC"}
1
+ {"version":3,"file":"fsu-event-codes.js","sourceRoot":"","sources":["../../src/codes/fsu-event-codes.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,wEAAwE;AACxE,yEAAyE;AACzE,sEAAsE;AACtE,qDAAqD;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;CACF,CAAC,CAAA;AASX,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAA;AACjC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Per JSON-LD 1.1 §3.7, when `@context` is an array, later items
3
+ * override earlier ones for term definitions. The OneRecord spec §7.1
4
+ * doesn't pin the array form explicitly, but consumers relying on the
5
+ * default `assertContextAllowed`'s set semantics would silently accept
6
+ * `["https://onerecord.iata.org/ns/cargo", "https://attacker.com/ns"]`
7
+ * — where the later URL could override cargo term definitions.
8
+ *
9
+ * Closes deviation #10 (v0.2.0 — deferral E). Opt-in via dispatch only:
10
+ * default per-class deserializers preserve v0.1.x set semantics for
11
+ * non-breaking compatibility.
12
+ */
13
+ export interface ContextOrderResult {
14
+ ok: boolean;
15
+ /** When ok is false, the unallowed last element. */
16
+ lastUnallowed?: string;
17
+ }
18
+ /**
19
+ * Check that the LAST element of an array `@context` is in the
20
+ * allowlist (= the "effective" context for term definitions). String-form
21
+ * `@context` is delegated to `assertContextAllowed` (set semantics);
22
+ * this function only fires for array form.
23
+ *
24
+ * Returns `{ ok: true }` for non-arrays or arrays where the last
25
+ * element is allowed.
26
+ */
27
+ export declare function checkContextOrder(context: unknown, allowedContexts?: readonly string[]): ContextOrderResult;
28
+ //# sourceMappingURL=context-order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-order.d.ts","sourceRoot":"","sources":["../../src/dispatch/context-order.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAA;IACX,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,eAAe,GAAE,SAAS,MAAM,EAAqB,GACpD,kBAAkB,CAMpB"}
@@ -0,0 +1,21 @@
1
+ import { ALLOWED_CONTEXTS } from '../context.js';
2
+ /**
3
+ * Check that the LAST element of an array `@context` is in the
4
+ * allowlist (= the "effective" context for term definitions). String-form
5
+ * `@context` is delegated to `assertContextAllowed` (set semantics);
6
+ * this function only fires for array form.
7
+ *
8
+ * Returns `{ ok: true }` for non-arrays or arrays where the last
9
+ * element is allowed.
10
+ */
11
+ export function checkContextOrder(context, allowedContexts = ALLOWED_CONTEXTS) {
12
+ if (!Array.isArray(context) || context.length === 0)
13
+ return { ok: true };
14
+ const last = context[context.length - 1];
15
+ if (typeof last !== 'string')
16
+ return { ok: true }; // shape error — handled elsewhere
17
+ if (allowedContexts.includes(last))
18
+ return { ok: true };
19
+ return { ok: false, lastUnallowed: last };
20
+ }
21
+ //# sourceMappingURL=context-order.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-order.js","sourceRoot":"","sources":["../../src/dispatch/context-order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAqBhD;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAgB,EAChB,kBAAqC,gBAAgB;IAErD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;IACxE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA,CAAC,kCAAkC;IACpF,IAAI,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;IACvD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Domain-semantic constraints that the v0.1.x Zod schemas mark as
3
+ * optional but spec §5.x requires. Used by `dispatchGraphWalk` to emit
4
+ * `domain_constraint_violation` for missing-but-required fields.
5
+ *
6
+ * Closes deviation #6 PARTIALLY (v0.2 — deferral F):
7
+ * - graph-cardinality (this file) — DONE
8
+ * - AWB number consistency between Waybill ↔ embedded Shipments — v0.3
9
+ * - total-pieces / total-weight sums between Shipment ↔ Pieces — v0.3
10
+ * - reference resolvability for cross-graph IRIs — v0.3
11
+ *
12
+ * v0.2 scope chosen for high spec-fidelity-per-LOC ratio: cardinality
13
+ * is a clear-cut spec rule (`MUST have`) and surfaces meaningful
14
+ * violations early. The other sub-items require either deeper graph
15
+ * traversal (sums) or external resolution (resolvability).
16
+ *
17
+ * Opt-in via the dispatch path; default per-class deserializers stay
18
+ * v0.1.x-permissive.
19
+ */
20
+ export interface DomainConstraint {
21
+ /** Field that must be present on the root LO. */
22
+ field: string;
23
+ /** Cardinality requirement (`required` = present + non-null). */
24
+ cardinality: 'required';
25
+ /** Spec section reference for the constraint. */
26
+ specRef: string;
27
+ }
28
+ export declare const DOMAIN_CONSTRAINTS: Readonly<Record<string, DomainConstraint[]>>;
29
+ export interface DomainConstraintViolation {
30
+ className: string;
31
+ field: string;
32
+ expected: 'required';
33
+ specRef: string;
34
+ }
35
+ /**
36
+ * Validate root-level cardinality constraints for the given root class.
37
+ * Returns the FIRST missing-required-field violation, or undefined if all
38
+ * required fields are present.
39
+ *
40
+ * Only checks root-level constraints — nested LO-in-LO cardinality is
41
+ * deferred to v0.3 (alongside the other deviation #6 sub-items).
42
+ */
43
+ export declare function checkDomainConstraints(rootClass: string, root: Record<string, unknown>): DomainConstraintViolation | undefined;
44
+ //# sourceMappingURL=domain-constraints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-constraints.d.ts","sourceRoot":"","sources":["../../src/dispatch/domain-constraints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,iEAAiE;IACjE,WAAW,EAAE,UAAU,CAAA;IACvB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAe1E,CAAA;AAEF,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,UAAU,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,yBAAyB,GAAG,SAAS,CAuBvC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Domain-semantic constraints that the v0.1.x Zod schemas mark as
3
+ * optional but spec §5.x requires. Used by `dispatchGraphWalk` to emit
4
+ * `domain_constraint_violation` for missing-but-required fields.
5
+ *
6
+ * Closes deviation #6 PARTIALLY (v0.2 — deferral F):
7
+ * - graph-cardinality (this file) — DONE
8
+ * - AWB number consistency between Waybill ↔ embedded Shipments — v0.3
9
+ * - total-pieces / total-weight sums between Shipment ↔ Pieces — v0.3
10
+ * - reference resolvability for cross-graph IRIs — v0.3
11
+ *
12
+ * v0.2 scope chosen for high spec-fidelity-per-LOC ratio: cardinality
13
+ * is a clear-cut spec rule (`MUST have`) and surfaces meaningful
14
+ * violations early. The other sub-items require either deeper graph
15
+ * traversal (sums) or external resolution (resolvability).
16
+ *
17
+ * Opt-in via the dispatch path; default per-class deserializers stay
18
+ * v0.1.x-permissive.
19
+ */
20
+ export const DOMAIN_CONSTRAINTS = Object.freeze({
21
+ Waybill: [
22
+ {
23
+ field: 'shipmentInformation',
24
+ cardinality: 'required',
25
+ specRef: 'data model 3.2 §5.1',
26
+ },
27
+ ],
28
+ Shipment: [
29
+ {
30
+ field: 'containedPieces',
31
+ cardinality: 'required',
32
+ specRef: 'data model 3.2 §5.2',
33
+ },
34
+ ],
35
+ });
36
+ /**
37
+ * Validate root-level cardinality constraints for the given root class.
38
+ * Returns the FIRST missing-required-field violation, or undefined if all
39
+ * required fields are present.
40
+ *
41
+ * Only checks root-level constraints — nested LO-in-LO cardinality is
42
+ * deferred to v0.3 (alongside the other deviation #6 sub-items).
43
+ */
44
+ export function checkDomainConstraints(rootClass, root) {
45
+ const constraints = DOMAIN_CONSTRAINTS[rootClass];
46
+ if (!constraints)
47
+ return undefined;
48
+ for (const c of constraints) {
49
+ const v = root[c.field];
50
+ if (v === undefined || v === null) {
51
+ return {
52
+ className: rootClass,
53
+ field: c.field,
54
+ expected: c.cardinality,
55
+ specRef: c.specRef,
56
+ };
57
+ }
58
+ if (Array.isArray(v) && v.length === 0) {
59
+ return {
60
+ className: rootClass,
61
+ field: c.field,
62
+ expected: c.cardinality,
63
+ specRef: c.specRef,
64
+ };
65
+ }
66
+ }
67
+ return undefined;
68
+ }
69
+ //# sourceMappingURL=domain-constraints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-constraints.js","sourceRoot":"","sources":["../../src/dispatch/domain-constraints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAWH,MAAM,CAAC,MAAM,kBAAkB,GAAiD,MAAM,CAAC,MAAM,CAAC;IAC5F,OAAO,EAAE;QACP;YACE,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EAAE,UAAU;YACvB,OAAO,EAAE,qBAAqB;SAC/B;KACF;IACD,QAAQ,EAAE;QACR;YACE,KAAK,EAAE,iBAAiB;YACxB,WAAW,EAAE,UAAU;YACvB,OAAO,EAAE,qBAAqB;SAC/B;KACF;CACF,CAAC,CAAA;AASF;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,IAA6B;IAE7B,MAAM,WAAW,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAA;IACjD,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAA;IAClC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QACvB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YAClC,OAAO;gBACL,SAAS,EAAE,SAAS;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,QAAQ,EAAE,CAAC,CAAC,WAAW;gBACvB,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAA;QACH,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,OAAO;gBACL,SAAS,EAAE,SAAS;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,QAAQ,EAAE,CAAC,CAAC,WAAW;gBACvB,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAA;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Static map: '<Class>.<field>' -> expected `@type` of an embedded
3
+ * object or IRI-referenced node. Used by `dispatchGraphWalk` to emit
4
+ * `wrong_type_for_endpoint` when an embedded node's `@type` does not
5
+ * match the field's contract.
6
+ *
7
+ * Coverage: every field in the 32-class data model that points at
8
+ * another logistics-object node (via `safeIri()` reference or
9
+ * embedded array). Scalar fields and external-endpoint URLs
10
+ * (`Subscription.notificationEndpoint`, `ServerInformation.serverEndpoint`)
11
+ * are intentionally omitted — those don't resolve to a OneRecord type.
12
+ *
13
+ * Polymorphic fields are marked with `'*'`. The graph-walker treats
14
+ * `'*'` as "any logistics-object type accepted".
15
+ *
16
+ * Maintenance: when adding a new class or field that holds a
17
+ * cross-reference, also add the expected-type mapping here. The
18
+ * graph-walker only checks mapped fields, so omission is silent —
19
+ * a missing entry means "not validated".
20
+ */
21
+ export declare const FIELD_TYPES: Readonly<Record<string, string>>;
22
+ /**
23
+ * Look up the expected `@type` for a given (className, fieldName).
24
+ * Returns `undefined` for fields not in the map (= not validated by
25
+ * the graph-walker — either scalar or out-of-scope external URL).
26
+ * Returns `'*'` for polymorphic fields where any logistics-object
27
+ * `@type` is valid.
28
+ */
29
+ export declare function expectedTypeFor(className: string, fieldName: string): string | undefined;
30
+ //# sourceMappingURL=field-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-types.d.ts","sourceRoot":"","sources":["../../src/dispatch/field-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqEvD,CAAA;AAEF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExF"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Static map: '<Class>.<field>' -> expected `@type` of an embedded
3
+ * object or IRI-referenced node. Used by `dispatchGraphWalk` to emit
4
+ * `wrong_type_for_endpoint` when an embedded node's `@type` does not
5
+ * match the field's contract.
6
+ *
7
+ * Coverage: every field in the 32-class data model that points at
8
+ * another logistics-object node (via `safeIri()` reference or
9
+ * embedded array). Scalar fields and external-endpoint URLs
10
+ * (`Subscription.notificationEndpoint`, `ServerInformation.serverEndpoint`)
11
+ * are intentionally omitted — those don't resolve to a OneRecord type.
12
+ *
13
+ * Polymorphic fields are marked with `'*'`. The graph-walker treats
14
+ * `'*'` as "any logistics-object type accepted".
15
+ *
16
+ * Maintenance: when adding a new class or field that holds a
17
+ * cross-reference, also add the expected-type mapping here. The
18
+ * graph-walker only checks mapped fields, so omission is silent —
19
+ * a missing entry means "not validated".
20
+ */
21
+ export const FIELD_TYPES = Object.freeze({
22
+ // Access-delegation
23
+ 'AccessDelegationRequest.accessDelegation': 'AccessDelegation',
24
+ 'AccessDelegation.delegatedTo': 'Party',
25
+ 'AccessDelegation.delegatedFrom': 'Party',
26
+ // Account number
27
+ 'AccountNumber.issuedBy': 'Organization',
28
+ // Booking ecosystem
29
+ 'Booking.forBookingRequest': 'BookingRequest',
30
+ 'Booking.forBookingOption': 'BookingOption',
31
+ 'BookingOption.forBookingRequest': 'BookingRequest',
32
+ 'BookingOption.preferences': 'BookingPreferences',
33
+ 'BookingOptionRequest.forBookingOption': 'BookingOption',
34
+ 'BookingRequest.requestor': 'Party',
35
+ 'BookingRequest.preferences': 'BookingPreferences',
36
+ 'BookingSegment.transportMovement': 'TransportMovement',
37
+ 'BookingSegment.loadingLocation': 'Location',
38
+ 'BookingSegment.unloadingLocation': 'Location',
39
+ 'BookingShipment.forShipment': 'Shipment',
40
+ // Change ecosystem
41
+ 'Change.hasOperation': 'Operation', // embedded array, not IRI ref
42
+ 'ChangeRequest.forLogisticsObject': '*', // polymorphic
43
+ 'ChangeRequest.hasChange': 'Change',
44
+ // Handling
45
+ 'HandlingService.provider': 'Party',
46
+ 'HandlingService.forShipment': 'Shipment',
47
+ // Location ↔ Address
48
+ 'Location.address': 'Address',
49
+ // Logistics event
50
+ 'LogisticsEvent.eventLocation': 'Location',
51
+ 'LogisticsEvent.relatedTransportMovement': 'TransportMovement',
52
+ // Notification
53
+ 'Notification.relatedLogisticsObject': '*', // polymorphic
54
+ // Organization / Party
55
+ 'Organization.address': 'Address',
56
+ 'Organization.contactPersons': 'Person',
57
+ 'Party.partyDetails': '*', // polymorphic — Person or Organization
58
+ 'Party.accountNumbers': 'AccountNumber',
59
+ // Shipment / Piece
60
+ 'Shipment.containedPieces': 'Piece',
61
+ 'Shipment.consignee': 'Party',
62
+ 'Shipment.shipper': 'Party',
63
+ // Subscription
64
+ 'SubscriptionRequest.subscription': 'Subscription',
65
+ 'Subscription.topic': '*', // polymorphic — any logistics object class IRI
66
+ 'Subscription.subscriber': 'Party',
67
+ // Transport movement
68
+ 'TransportMovement.departureLocation': 'Location',
69
+ 'TransportMovement.arrivalLocation': 'Location',
70
+ 'TransportMovement.movementTimes': 'MovementTime',
71
+ // Verification
72
+ 'VerificationRequest.verification': 'Verification',
73
+ 'Verification.verifiedObject': '*', // polymorphic
74
+ // Waybill
75
+ 'Waybill.shipmentInformation': 'Shipment',
76
+ 'Waybill.referredBookingOption': 'BookingOption',
77
+ });
78
+ /**
79
+ * Look up the expected `@type` for a given (className, fieldName).
80
+ * Returns `undefined` for fields not in the map (= not validated by
81
+ * the graph-walker — either scalar or out-of-scope external URL).
82
+ * Returns `'*'` for polymorphic fields where any logistics-object
83
+ * `@type` is valid.
84
+ */
85
+ export function expectedTypeFor(className, fieldName) {
86
+ return FIELD_TYPES[`${className}.${fieldName}`];
87
+ }
88
+ //# sourceMappingURL=field-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-types.js","sourceRoot":"","sources":["../../src/dispatch/field-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,WAAW,GAAqC,MAAM,CAAC,MAAM,CAAC;IACzE,oBAAoB;IACpB,0CAA0C,EAAE,kBAAkB;IAC9D,8BAA8B,EAAE,OAAO;IACvC,gCAAgC,EAAE,OAAO;IAEzC,iBAAiB;IACjB,wBAAwB,EAAE,cAAc;IAExC,oBAAoB;IACpB,2BAA2B,EAAE,gBAAgB;IAC7C,0BAA0B,EAAE,eAAe;IAC3C,iCAAiC,EAAE,gBAAgB;IACnD,2BAA2B,EAAE,oBAAoB;IACjD,uCAAuC,EAAE,eAAe;IACxD,0BAA0B,EAAE,OAAO;IACnC,4BAA4B,EAAE,oBAAoB;IAClD,kCAAkC,EAAE,mBAAmB;IACvD,gCAAgC,EAAE,UAAU;IAC5C,kCAAkC,EAAE,UAAU;IAC9C,6BAA6B,EAAE,UAAU;IAEzC,mBAAmB;IACnB,qBAAqB,EAAE,WAAW,EAAE,8BAA8B;IAClE,kCAAkC,EAAE,GAAG,EAAE,cAAc;IACvD,yBAAyB,EAAE,QAAQ;IAEnC,WAAW;IACX,0BAA0B,EAAE,OAAO;IACnC,6BAA6B,EAAE,UAAU;IAEzC,qBAAqB;IACrB,kBAAkB,EAAE,SAAS;IAE7B,kBAAkB;IAClB,8BAA8B,EAAE,UAAU;IAC1C,yCAAyC,EAAE,mBAAmB;IAE9D,eAAe;IACf,qCAAqC,EAAE,GAAG,EAAE,cAAc;IAE1D,uBAAuB;IACvB,sBAAsB,EAAE,SAAS;IACjC,6BAA6B,EAAE,QAAQ;IACvC,oBAAoB,EAAE,GAAG,EAAE,uCAAuC;IAClE,sBAAsB,EAAE,eAAe;IAEvC,mBAAmB;IACnB,0BAA0B,EAAE,OAAO;IACnC,oBAAoB,EAAE,OAAO;IAC7B,kBAAkB,EAAE,OAAO;IAE3B,eAAe;IACf,kCAAkC,EAAE,cAAc;IAClD,oBAAoB,EAAE,GAAG,EAAE,+CAA+C;IAC1E,yBAAyB,EAAE,OAAO;IAElC,qBAAqB;IACrB,qCAAqC,EAAE,UAAU;IACjD,mCAAmC,EAAE,UAAU;IAC/C,iCAAiC,EAAE,cAAc;IAEjD,eAAe;IACf,kCAAkC,EAAE,cAAc;IAClD,6BAA6B,EAAE,GAAG,EAAE,cAAc;IAElD,UAAU;IACV,6BAA6B,EAAE,UAAU;IACzC,+BAA+B,EAAE,eAAe;CACjD,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB,EAAE,SAAiB;IAClE,OAAO,WAAW,CAAC,GAAG,SAAS,IAAI,SAAS,EAAE,CAAC,CAAA;AACjD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { ParseResult } from '../result.js';
2
+ /**
3
+ * Cross-node graph integrity analysis. Runs as a single walk via
4
+ * `walkGraph`'s visitor; emits at most one of:
5
+ * - `duplicate_id_in_graph` — two distinct nodes share an `@id`.
6
+ * - `missing_id` — a node embedded in a cross-reference position has no `@id`.
7
+ * - `wrong_type_for_endpoint` — a node's `@type` does not match the
8
+ * declared expected type for the field that references it.
9
+ * - `missing_type` — a non-leaf node lacks `@type`.
10
+ * - `iri_not_canonical` — an IRI string is not in canonical form
11
+ * (lowercase scheme/host, no default port; RFC 3987 + spec §3.2).
12
+ *
13
+ * Returns `ok: true` if the graph is structurally sound (per spec §3.2 + §7.1).
14
+ *
15
+ * Does NOT replace per-class Zod schema validation — that runs after this
16
+ * pass succeeds, in `dispatch.deserialize.<Class>`.
17
+ *
18
+ * v0.2: containing-class tracking via path-keyed map of object @types,
19
+ * so `wrong_type_for_endpoint` and `missing_id` checks fire for all
20
+ * embedded references, not just direct children of the root.
21
+ */
22
+ export declare function dispatchGraphWalk(input: unknown, rootClass: string): ParseResult<true>;
23
+ //# sourceMappingURL=graph-walk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-walk.d.ts","sourceRoot":"","sources":["../../src/dispatch/graph-walk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,cAAc,CAAA;AAO3D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAmItF"}
@@ -0,0 +1,206 @@
1
+ import { walkGraph } from '../safety/walk-graph.js';
2
+ import { checkContextOrder } from './context-order.js';
3
+ import { checkDomainConstraints } from './domain-constraints.js';
4
+ import { expectedTypeFor } from './field-types.js';
5
+ import { checkIriCanonical, looksLikeIri } from './iri-canonical.js';
6
+ /**
7
+ * Cross-node graph integrity analysis. Runs as a single walk via
8
+ * `walkGraph`'s visitor; emits at most one of:
9
+ * - `duplicate_id_in_graph` — two distinct nodes share an `@id`.
10
+ * - `missing_id` — a node embedded in a cross-reference position has no `@id`.
11
+ * - `wrong_type_for_endpoint` — a node's `@type` does not match the
12
+ * declared expected type for the field that references it.
13
+ * - `missing_type` — a non-leaf node lacks `@type`.
14
+ * - `iri_not_canonical` — an IRI string is not in canonical form
15
+ * (lowercase scheme/host, no default port; RFC 3987 + spec §3.2).
16
+ *
17
+ * Returns `ok: true` if the graph is structurally sound (per spec §3.2 + §7.1).
18
+ *
19
+ * Does NOT replace per-class Zod schema validation — that runs after this
20
+ * pass succeeds, in `dispatch.deserialize.<Class>`.
21
+ *
22
+ * v0.2: containing-class tracking via path-keyed map of object @types,
23
+ * so `wrong_type_for_endpoint` and `missing_id` checks fire for all
24
+ * embedded references, not just direct children of the root.
25
+ */
26
+ export function dispatchGraphWalk(input, rootClass) {
27
+ // context_order_violation (deviation #10 closure, deferral E): if the
28
+ // root @context is an array, verify the LAST element is allowed.
29
+ // Per JSON-LD 1.1 §3.7 later items override earlier ones for term
30
+ // definitions; the last item is the effective cargo-term context.
31
+ // String-form @context is delegated to assertContextAllowed (already
32
+ // runs in the per-class deserializer).
33
+ if (typeof input === 'object' && input !== null && '@context' in input) {
34
+ const ctx = input['@context'];
35
+ const orderR = checkContextOrder(ctx);
36
+ if (!orderR.ok && orderR.lastUnallowed !== undefined) {
37
+ return {
38
+ ok: false,
39
+ error: {
40
+ kind: 'context_order_violation',
41
+ got: ctx,
42
+ lastUnallowed: orderR.lastUnallowed,
43
+ path: '$["@context"]',
44
+ },
45
+ };
46
+ }
47
+ }
48
+ // domain_constraint_violation (deviation #6 partial closure, deferral F):
49
+ // root-level cardinality constraints from spec §5.x. Today: Waybill
50
+ // requires shipmentInformation; Shipment requires containedPieces.
51
+ // v0.3 expands with AWB consistency, total-pieces/weight sums, and
52
+ // reference resolvability.
53
+ if (typeof input === 'object' && input !== null && !Array.isArray(input)) {
54
+ const violation = checkDomainConstraints(rootClass, input);
55
+ if (violation) {
56
+ return {
57
+ ok: false,
58
+ error: {
59
+ kind: 'domain_constraint_violation',
60
+ className: violation.className,
61
+ field: violation.field,
62
+ expected: violation.expected,
63
+ specRef: violation.specRef,
64
+ path: `$.${violation.field}`,
65
+ },
66
+ };
67
+ }
68
+ }
69
+ const seen = new Map(); // @id -> first path seen
70
+ // Path-keyed @type lookup: maps each object node's path to its declared
71
+ // (or root-defaulted) @type. Used to resolve the containing class when
72
+ // checking wrong_type_for_endpoint / missing_id at any depth.
73
+ const pathToType = new Map();
74
+ pathToType.set('$', rootClass);
75
+ let firstError;
76
+ const walkR = walkGraph(input, {}, (node, path, _depth) => {
77
+ if (firstError)
78
+ return; // short-circuit on first error
79
+ // iri_not_canonical: check every IRI-shaped string value in the
80
+ // graph (deviation #9 closure, deferral D). Runs before the
81
+ // object-only checks below because string values are visited
82
+ // separately by walkGraph.
83
+ if (typeof node === 'string' && looksLikeIri(node)) {
84
+ const r = checkIriCanonical(node);
85
+ if (!r.canonical && r.reason) {
86
+ firstError = {
87
+ kind: 'iri_not_canonical',
88
+ iri: node,
89
+ reason: r.reason,
90
+ path,
91
+ };
92
+ }
93
+ return;
94
+ }
95
+ if (typeof node !== 'object' || node === null || Array.isArray(node))
96
+ return;
97
+ const obj = node;
98
+ const id = typeof obj['@id'] === 'string' ? obj['@id'] : undefined;
99
+ const type = typeof obj['@type'] === 'string' ? obj['@type'] : undefined;
100
+ // Record this object's @type by path so children can find their
101
+ // containing class. Falls back to rootClass for the root path.
102
+ if (type)
103
+ pathToType.set(path, type);
104
+ // missing_type: every non-leaf node must declare @type
105
+ if (!type && hasObjectChildren(obj)) {
106
+ firstError = { kind: 'missing_type', path };
107
+ return;
108
+ }
109
+ const parentField = pathToParentField(path);
110
+ const containingClass = parentField ? containingClassFor(path, pathToType) : undefined;
111
+ // missing_id: nodes embedded in cross-reference positions must have @id.
112
+ // Cross-reference positions are fields in FIELD_TYPES for the containing class.
113
+ if (parentField && containingClass && !id && requiresId(parentField, containingClass)) {
114
+ firstError = {
115
+ kind: 'missing_id',
116
+ objectType: type ?? 'unknown',
117
+ path,
118
+ };
119
+ return;
120
+ }
121
+ // duplicate_id_in_graph
122
+ if (id) {
123
+ if (seen.has(id)) {
124
+ firstError = { kind: 'duplicate_id_in_graph', iri: id, path };
125
+ return;
126
+ }
127
+ seen.set(id, path);
128
+ }
129
+ // wrong_type_for_endpoint: embedded @type must match the field's
130
+ // expected class. Now checked at any depth — containing class
131
+ // resolved via the path-keyed @type map.
132
+ if (type && parentField && containingClass) {
133
+ const expected = expectedTypeFor(containingClass, parentField);
134
+ if (expected && expected !== '*' && expected !== type) {
135
+ firstError = {
136
+ kind: 'wrong_type_for_endpoint',
137
+ expected,
138
+ got: type,
139
+ path,
140
+ };
141
+ }
142
+ }
143
+ });
144
+ if (!walkR.ok)
145
+ return walkR; // safety-limit error
146
+ if (firstError)
147
+ return { ok: false, error: firstError };
148
+ return { ok: true, value: true };
149
+ }
150
+ function hasObjectChildren(obj) {
151
+ for (const v of Object.values(obj)) {
152
+ if (typeof v === 'object' && v !== null)
153
+ return true;
154
+ }
155
+ return false;
156
+ }
157
+ /**
158
+ * Path format: `$`, `$.<field>`, `$.<field>[<n>]`, `$.<field>.<sub>`,
159
+ * `$.<field>[<n>].<sub>`. Returns the immediate parent field name.
160
+ * Returns `undefined` for the root path `$`.
161
+ */
162
+ function pathToParentField(path) {
163
+ if (path === '$')
164
+ return undefined;
165
+ const last = path.split('.').pop();
166
+ if (!last)
167
+ return undefined;
168
+ return last.replace(/\[\d+\]$/, ''); // strip array index suffix
169
+ }
170
+ /**
171
+ * Resolve the containing class for the node at `path` by looking up the
172
+ * @type recorded at the parent object's path. Skips array-index segments
173
+ * (those don't carry their own @type).
174
+ *
175
+ * Examples (rootClass = 'Waybill'):
176
+ * - `$.shipmentInformation` → parent path `$` → 'Waybill'
177
+ * - `$.shipmentInformation.consignee` → parent path `$.shipmentInformation`
178
+ * → whatever @type was declared on that node (typically 'Shipment')
179
+ * - `$.containedPieces[0]` → strip `[0]` then `.containedPieces` → '$' → 'Waybill'
180
+ * (the array container itself isn't an object node so we step past it)
181
+ * - `$.containedPieces[0].dimensions` → parent path `$.containedPieces[0]`
182
+ * → @type at that path (typically 'Piece')
183
+ */
184
+ function containingClassFor(path, pathToType) {
185
+ if (path === '$')
186
+ return undefined;
187
+ // Strip the trailing `.field` or `[N]` segment to get the parent path.
188
+ const stripped = path.replace(/\[\d+\]$/, '');
189
+ const lastDot = stripped.lastIndexOf('.');
190
+ if (lastDot < 0)
191
+ return undefined;
192
+ let parentPath = stripped.slice(0, lastDot);
193
+ if (parentPath === '')
194
+ parentPath = '$';
195
+ return pathToType.get(parentPath);
196
+ }
197
+ /**
198
+ * A field requires `@id` on referenced nodes if it's in `FIELD_TYPES`
199
+ * for the given containing class (= the field points at another
200
+ * logistics-object node). Scalar fields and unmapped fields don't
201
+ * require `@id`.
202
+ */
203
+ function requiresId(parentField, containingClass) {
204
+ return expectedTypeFor(containingClass, parentField) !== undefined;
205
+ }
206
+ //# sourceMappingURL=graph-walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-walk.js","sourceRoot":"","sources":["../../src/dispatch/graph-walk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { type ClassName } from '../factory-classes.js';
2
+ import type { ParseResult } from '../result.js';
3
+ /**
4
+ * Build the per-class deserialize map by wrapping each module's
5
+ * `deserialize<ClassName>` function with the graph-walk pre-pass.
6
+ *
7
+ * Failure of the graph-walk pre-pass returns the underlying ParseError
8
+ * untouched; per-class Zod validation only runs if the pre-pass passes.
9
+ */
10
+ type DispatchDeserializeMap = {
11
+ readonly [C in ClassName]: (raw: unknown) => ParseResult<unknown>;
12
+ };
13
+ /**
14
+ * Opt-in dispatch facade per spec §13. Use:
15
+ * import { dispatch } from '@flaks/onerecord'
16
+ * const r = dispatch.deserialize.Waybill(input)
17
+ *
18
+ * Each per-class deserializer runs the graph-walk pre-pass before
19
+ * delegating to the per-class Zod schema. The default per-class
20
+ * deserializers (`WaybillCodec.deserialize`, `onerecord.deserialize.Waybill`)
21
+ * are unchanged — graph-walk is opt-in.
22
+ *
23
+ * For state-bound graph-walk (per-call limits, IRI strategy etc.), use
24
+ * `createMapper({ graphWalk: true })` instead.
25
+ */
26
+ export declare const dispatch: Readonly<{
27
+ deserialize: Readonly<DispatchDeserializeMap>;
28
+ }>;
29
+ export {};
30
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dispatch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C;;;;;;GAMG;AACH,KAAK,sBAAsB,GAAG;IAC5B,QAAQ,EAAE,CAAC,IAAI,SAAS,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,WAAW,CAAC,OAAO,CAAC;CAClE,CAAA;AAuBD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ;;EAEnB,CAAA"}