@modernrelay/orbit-omnigraph 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.
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/chunk-32TESFMK.js +517 -0
- package/dist/chunk-32TESFMK.js.map +1 -0
- package/dist/codegen-cli.js +280 -0
- package/dist/codegen-cli.js.map +1 -0
- package/dist/index.d.ts +540 -0
- package/dist/index.js +428 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +32 -0
- package/dist/server.js +12 -0
- package/dist/server.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
// src/idCodec.ts
|
|
2
|
+
function encodeSourceId(kind, sourceId) {
|
|
3
|
+
return JSON.stringify([kind, sourceId]);
|
|
4
|
+
}
|
|
5
|
+
function decodeSourceId(id) {
|
|
6
|
+
let parsed;
|
|
7
|
+
try {
|
|
8
|
+
parsed = JSON.parse(id);
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (!Array.isArray(parsed) || parsed.length !== 2) return null;
|
|
13
|
+
const [kind, sourceId] = parsed;
|
|
14
|
+
if (typeof kind !== "string" || typeof sourceId !== "string") return null;
|
|
15
|
+
return { kind, sourceId };
|
|
16
|
+
}
|
|
17
|
+
function encodeSyntheticEdgeId(edgeName, source, target) {
|
|
18
|
+
return JSON.stringify(["synthetic-edge", edgeName, source, target]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/pgSchema.ts
|
|
22
|
+
var SCALARS = /* @__PURE__ */ new Set([
|
|
23
|
+
"String",
|
|
24
|
+
"Blob",
|
|
25
|
+
"Bool",
|
|
26
|
+
"I32",
|
|
27
|
+
"I64",
|
|
28
|
+
"U32",
|
|
29
|
+
"U64",
|
|
30
|
+
"F32",
|
|
31
|
+
"F64",
|
|
32
|
+
"Date",
|
|
33
|
+
"DateTime"
|
|
34
|
+
]);
|
|
35
|
+
function stripComments(src) {
|
|
36
|
+
let out = "";
|
|
37
|
+
let i = 0;
|
|
38
|
+
const n = src.length;
|
|
39
|
+
while (i < n) {
|
|
40
|
+
const ch = src.charAt(i);
|
|
41
|
+
if (ch === '"') {
|
|
42
|
+
out += ch;
|
|
43
|
+
i++;
|
|
44
|
+
while (i < n) {
|
|
45
|
+
const c = src.charAt(i);
|
|
46
|
+
out += c;
|
|
47
|
+
i++;
|
|
48
|
+
if (c === "\\" && i < n) {
|
|
49
|
+
out += src.charAt(i);
|
|
50
|
+
i++;
|
|
51
|
+
} else if (c === '"') break;
|
|
52
|
+
}
|
|
53
|
+
} else if (ch === "/" && src.charAt(i + 1) === "/") {
|
|
54
|
+
while (i < n && src.charAt(i) !== "\n") i++;
|
|
55
|
+
} else if (ch === "/" && src.charAt(i + 1) === "*") {
|
|
56
|
+
i += 2;
|
|
57
|
+
while (i < n && !(src.charAt(i) === "*" && src.charAt(i + 1) === "/")) {
|
|
58
|
+
out += src.charAt(i) === "\n" ? "\n" : " ";
|
|
59
|
+
i++;
|
|
60
|
+
}
|
|
61
|
+
i += 2;
|
|
62
|
+
} else {
|
|
63
|
+
out += ch;
|
|
64
|
+
i++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
function findBlockEnd(src, openIdx) {
|
|
70
|
+
let depth = 0;
|
|
71
|
+
let i = openIdx;
|
|
72
|
+
const n = src.length;
|
|
73
|
+
while (i < n) {
|
|
74
|
+
const ch = src.charAt(i);
|
|
75
|
+
if (ch === '"') {
|
|
76
|
+
i++;
|
|
77
|
+
while (i < n) {
|
|
78
|
+
const c = src.charAt(i);
|
|
79
|
+
i++;
|
|
80
|
+
if (c === "\\") i++;
|
|
81
|
+
else if (c === '"') break;
|
|
82
|
+
}
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (ch === "{") depth++;
|
|
86
|
+
else if (ch === "}") {
|
|
87
|
+
depth--;
|
|
88
|
+
if (depth === 0) return i + 1;
|
|
89
|
+
}
|
|
90
|
+
i++;
|
|
91
|
+
}
|
|
92
|
+
return n;
|
|
93
|
+
}
|
|
94
|
+
function splitStatements(body) {
|
|
95
|
+
const out = [];
|
|
96
|
+
let depth = 0;
|
|
97
|
+
let current = "";
|
|
98
|
+
let i = 0;
|
|
99
|
+
const n = body.length;
|
|
100
|
+
while (i < n) {
|
|
101
|
+
const ch = body.charAt(i);
|
|
102
|
+
if (ch === '"') {
|
|
103
|
+
current += ch;
|
|
104
|
+
i++;
|
|
105
|
+
while (i < n) {
|
|
106
|
+
const c = body.charAt(i);
|
|
107
|
+
current += c;
|
|
108
|
+
i++;
|
|
109
|
+
if (c === "\\" && i < n) {
|
|
110
|
+
current += body.charAt(i);
|
|
111
|
+
i++;
|
|
112
|
+
} else if (c === '"') break;
|
|
113
|
+
}
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (ch === "(" || ch === "[") depth++;
|
|
117
|
+
else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
|
|
118
|
+
if (ch === "\n" && depth === 0) {
|
|
119
|
+
out.push(current);
|
|
120
|
+
current = "";
|
|
121
|
+
} else {
|
|
122
|
+
current += ch;
|
|
123
|
+
}
|
|
124
|
+
i++;
|
|
125
|
+
}
|
|
126
|
+
out.push(current);
|
|
127
|
+
return out.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
128
|
+
}
|
|
129
|
+
function scanAnnotations(src, start) {
|
|
130
|
+
const anns = [];
|
|
131
|
+
let i = start;
|
|
132
|
+
const n = src.length;
|
|
133
|
+
for (; ; ) {
|
|
134
|
+
let j = i;
|
|
135
|
+
while (j < n && /\s/.test(src.charAt(j))) j++;
|
|
136
|
+
if (src.charAt(j) !== "@") break;
|
|
137
|
+
const m = /^@([A-Za-z_]\w*)/.exec(src.slice(j));
|
|
138
|
+
if (!m || m[1] === void 0) break;
|
|
139
|
+
const name = m[1];
|
|
140
|
+
let end = j + m[0].length;
|
|
141
|
+
let args;
|
|
142
|
+
if (src.charAt(end) === "(") {
|
|
143
|
+
let depth = 0;
|
|
144
|
+
let k = end;
|
|
145
|
+
while (k < n) {
|
|
146
|
+
const ch = src.charAt(k);
|
|
147
|
+
if (ch === '"') {
|
|
148
|
+
k++;
|
|
149
|
+
while (k < n) {
|
|
150
|
+
const c = src.charAt(k);
|
|
151
|
+
k++;
|
|
152
|
+
if (c === "\\") k++;
|
|
153
|
+
else if (c === '"') break;
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (ch === "(") depth++;
|
|
158
|
+
else if (ch === ")") {
|
|
159
|
+
depth--;
|
|
160
|
+
if (depth === 0) {
|
|
161
|
+
k++;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
k++;
|
|
166
|
+
}
|
|
167
|
+
args = src.slice(end + 1, k - 1);
|
|
168
|
+
end = k;
|
|
169
|
+
}
|
|
170
|
+
const entry = { name, raw: src.slice(j, end) };
|
|
171
|
+
if (args !== void 0) entry.args = args;
|
|
172
|
+
anns.push(entry);
|
|
173
|
+
i = end;
|
|
174
|
+
}
|
|
175
|
+
return { anns, end: i };
|
|
176
|
+
}
|
|
177
|
+
function splitArgs(args) {
|
|
178
|
+
const out = [];
|
|
179
|
+
let depth = 0;
|
|
180
|
+
let current = "";
|
|
181
|
+
for (let i = 0; i < args.length; i++) {
|
|
182
|
+
const ch = args.charAt(i);
|
|
183
|
+
if (ch === '"') {
|
|
184
|
+
current += ch;
|
|
185
|
+
i++;
|
|
186
|
+
while (i < args.length) {
|
|
187
|
+
const c = args.charAt(i);
|
|
188
|
+
current += c;
|
|
189
|
+
if (c === "\\") {
|
|
190
|
+
i++;
|
|
191
|
+
current += args.charAt(i);
|
|
192
|
+
} else if (c === '"') break;
|
|
193
|
+
i++;
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (ch === "(" || ch === "[") depth++;
|
|
198
|
+
else if (ch === ")" || ch === "]") depth = Math.max(0, depth - 1);
|
|
199
|
+
if (ch === "," && depth === 0) {
|
|
200
|
+
out.push(current);
|
|
201
|
+
current = "";
|
|
202
|
+
} else {
|
|
203
|
+
current += ch;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
out.push(current);
|
|
207
|
+
return out.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
208
|
+
}
|
|
209
|
+
function parseTypeRef(text) {
|
|
210
|
+
let i = 0;
|
|
211
|
+
const n = text.length;
|
|
212
|
+
while (i < n && /\s/.test(text.charAt(i))) i++;
|
|
213
|
+
let type;
|
|
214
|
+
if (text.charAt(i) === "[") {
|
|
215
|
+
const m = /^\[\s*([A-Za-z_]\w*)\s*\]/.exec(text.slice(i));
|
|
216
|
+
if (m && m[1] !== void 0 && SCALARS.has(m[1])) {
|
|
217
|
+
type = { kind: "list", element: m[1] };
|
|
218
|
+
i += m[0].length;
|
|
219
|
+
} else {
|
|
220
|
+
const close = text.indexOf("]", i);
|
|
221
|
+
const end = close === -1 ? n : close + 1;
|
|
222
|
+
type = { kind: "unknown", raw: text.slice(i, end).trim() };
|
|
223
|
+
i = end;
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
const m = /^([A-Za-z_]\w*)/.exec(text.slice(i));
|
|
227
|
+
if (!m || m[1] === void 0) {
|
|
228
|
+
return { type: { kind: "unknown", raw: text.trim() }, optional: false, end: n };
|
|
229
|
+
}
|
|
230
|
+
const ident = m[1];
|
|
231
|
+
i += m[0].length;
|
|
232
|
+
if ((ident === "enum" || ident === "Vector") && text.charAt(i) === "(") {
|
|
233
|
+
let depth = 0;
|
|
234
|
+
let k = i;
|
|
235
|
+
while (k < n) {
|
|
236
|
+
const ch = text.charAt(k);
|
|
237
|
+
if (ch === "(") depth++;
|
|
238
|
+
else if (ch === ")") {
|
|
239
|
+
depth--;
|
|
240
|
+
if (depth === 0) {
|
|
241
|
+
k++;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
k++;
|
|
246
|
+
}
|
|
247
|
+
const inner = text.slice(i + 1, k - 1);
|
|
248
|
+
i = k;
|
|
249
|
+
if (ident === "enum") {
|
|
250
|
+
const values = splitArgs(inner).map((v) => v.replace(/^"(.*)"$/s, "$1"));
|
|
251
|
+
type = { kind: "enum", values };
|
|
252
|
+
} else {
|
|
253
|
+
const dim = Number.parseInt(inner.trim(), 10);
|
|
254
|
+
type = Number.isFinite(dim) ? { kind: "vector", dim } : { kind: "unknown", raw: `Vector(${inner})` };
|
|
255
|
+
}
|
|
256
|
+
} else if (SCALARS.has(ident)) {
|
|
257
|
+
type = ident;
|
|
258
|
+
} else {
|
|
259
|
+
type = { kind: "unknown", raw: ident };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
let optional = false;
|
|
263
|
+
if (text.charAt(i) === "?") {
|
|
264
|
+
optional = true;
|
|
265
|
+
i++;
|
|
266
|
+
}
|
|
267
|
+
return { type, optional, end: i };
|
|
268
|
+
}
|
|
269
|
+
function parseBody(body) {
|
|
270
|
+
const properties = [];
|
|
271
|
+
const constraints = [];
|
|
272
|
+
for (const stmt of splitStatements(body)) {
|
|
273
|
+
if (stmt.startsWith("@")) {
|
|
274
|
+
const { anns: anns2 } = scanAnnotations(stmt, 0);
|
|
275
|
+
for (const a of anns2) constraints.push(a.raw);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const head = /^([A-Za-z_]\w*)\s*:\s*/.exec(stmt);
|
|
279
|
+
if (!head || head[1] === void 0) continue;
|
|
280
|
+
const name = head[1];
|
|
281
|
+
const rest = stmt.slice(head[0].length);
|
|
282
|
+
const { type, optional, end } = parseTypeRef(rest);
|
|
283
|
+
const { anns } = scanAnnotations(rest, end);
|
|
284
|
+
properties.push({
|
|
285
|
+
name,
|
|
286
|
+
type,
|
|
287
|
+
optional,
|
|
288
|
+
key: anns.some((a) => a.name === "key"),
|
|
289
|
+
unique: anns.some((a) => a.name === "unique"),
|
|
290
|
+
index: anns.some((a) => a.name === "index"),
|
|
291
|
+
annotations: anns.map((a) => a.raw)
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
for (const raw of constraints) {
|
|
295
|
+
const m = /^@(key|unique|index)\((.*)\)$/s.exec(raw);
|
|
296
|
+
if (!m || m[1] === void 0 || m[2] === void 0) continue;
|
|
297
|
+
const flag = m[1];
|
|
298
|
+
for (const propName of splitArgs(m[2])) {
|
|
299
|
+
const prop = properties.find((p) => p.name === propName);
|
|
300
|
+
if (prop) prop[flag] = true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return { properties, constraints };
|
|
304
|
+
}
|
|
305
|
+
function parsePgSchema(source) {
|
|
306
|
+
const src = stripComments(source);
|
|
307
|
+
const interfaces = [];
|
|
308
|
+
const nodes = [];
|
|
309
|
+
const edges = [];
|
|
310
|
+
const headRe = /\b(interface|node|edge)\s+([A-Za-z_]\w*)/g;
|
|
311
|
+
let m;
|
|
312
|
+
while ((m = headRe.exec(src)) !== null) {
|
|
313
|
+
const kw = m[1];
|
|
314
|
+
const name = m[2];
|
|
315
|
+
if (kw === void 0 || name === void 0) continue;
|
|
316
|
+
let pos = headRe.lastIndex;
|
|
317
|
+
if (kw === "edge") {
|
|
318
|
+
const em = /^\s*:\s*([A-Za-z_]\w*)\s*->\s*([A-Za-z_]\w*)/.exec(src.slice(pos));
|
|
319
|
+
if (!em || em[1] === void 0 || em[2] === void 0) continue;
|
|
320
|
+
pos += em[0].length;
|
|
321
|
+
const { anns, end } = scanAnnotations(src, pos);
|
|
322
|
+
pos = end;
|
|
323
|
+
let body2 = { properties: [], constraints: [] };
|
|
324
|
+
let braceIdx2 = pos;
|
|
325
|
+
while (braceIdx2 < src.length && /\s/.test(src.charAt(braceIdx2))) braceIdx2++;
|
|
326
|
+
if (src.charAt(braceIdx2) === "{") {
|
|
327
|
+
const blockEnd2 = findBlockEnd(src, braceIdx2);
|
|
328
|
+
body2 = parseBody(src.slice(braceIdx2 + 1, blockEnd2 - 1));
|
|
329
|
+
pos = blockEnd2;
|
|
330
|
+
}
|
|
331
|
+
const card = anns.find((a) => a.name === "card")?.args?.trim();
|
|
332
|
+
const edge = {
|
|
333
|
+
name,
|
|
334
|
+
from: em[1],
|
|
335
|
+
to: em[2],
|
|
336
|
+
annotations: anns.map((a) => a.raw),
|
|
337
|
+
properties: body2.properties,
|
|
338
|
+
constraints: body2.constraints,
|
|
339
|
+
...card !== void 0 ? { card } : {}
|
|
340
|
+
};
|
|
341
|
+
edges.push(edge);
|
|
342
|
+
headRe.lastIndex = pos;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
let impls = [];
|
|
346
|
+
if (kw === "node") {
|
|
347
|
+
const im = /^\s*implements\s+([A-Za-z_]\w*(?:\s*,\s*[A-Za-z_]\w*)*)/.exec(src.slice(pos));
|
|
348
|
+
if (im && im[1] !== void 0) {
|
|
349
|
+
impls = im[1].split(",").map((s) => s.trim());
|
|
350
|
+
pos += im[0].length;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
let braceIdx = pos;
|
|
354
|
+
while (braceIdx < src.length && /\s/.test(src.charAt(braceIdx))) braceIdx++;
|
|
355
|
+
if (src.charAt(braceIdx) !== "{") continue;
|
|
356
|
+
const blockEnd = findBlockEnd(src, braceIdx);
|
|
357
|
+
const body = parseBody(src.slice(braceIdx + 1, blockEnd - 1));
|
|
358
|
+
headRe.lastIndex = blockEnd;
|
|
359
|
+
if (kw === "interface") {
|
|
360
|
+
interfaces.push({ name, properties: body.properties, constraints: body.constraints });
|
|
361
|
+
} else {
|
|
362
|
+
nodes.push({
|
|
363
|
+
name,
|
|
364
|
+
implements: impls,
|
|
365
|
+
properties: body.properties,
|
|
366
|
+
constraints: body.constraints
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
for (const node of nodes) {
|
|
371
|
+
if (node.implements.length === 0) continue;
|
|
372
|
+
const own = new Set(node.properties.map((p) => p.name));
|
|
373
|
+
const inherited = [];
|
|
374
|
+
for (const ifaceName of node.implements) {
|
|
375
|
+
const iface = interfaces.find((i) => i.name === ifaceName);
|
|
376
|
+
if (!iface) continue;
|
|
377
|
+
for (const p of iface.properties) {
|
|
378
|
+
if (!own.has(p.name) && !inherited.some((q) => q.name === p.name)) inherited.push(p);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
node.properties = [...inherited, ...node.properties];
|
|
382
|
+
}
|
|
383
|
+
return { interfaces, nodes, edges };
|
|
384
|
+
}
|
|
385
|
+
function edgeEndpointTypes(schema, edgeName) {
|
|
386
|
+
const lower = edgeName.toLowerCase();
|
|
387
|
+
const edge = schema.edges.find((e) => e.name === edgeName) ?? schema.edges.find((e) => e.name.toLowerCase() === lower);
|
|
388
|
+
return edge ? { from: edge.from, to: edge.to } : null;
|
|
389
|
+
}
|
|
390
|
+
function schemaFingerprint(source) {
|
|
391
|
+
const MASK64 = 0xffffffffffffffffn;
|
|
392
|
+
let h = 0xcbf29ce484222325n;
|
|
393
|
+
const bytes = new TextEncoder().encode(source);
|
|
394
|
+
for (const b of bytes) {
|
|
395
|
+
h ^= BigInt(b);
|
|
396
|
+
h = h * 0x100000001b3n & MASK64;
|
|
397
|
+
}
|
|
398
|
+
return h.toString(16).padStart(16, "0");
|
|
399
|
+
}
|
|
400
|
+
function bigIntKeyWarnings(schema) {
|
|
401
|
+
const out = [];
|
|
402
|
+
for (const t of [...schema.nodes, ...schema.edges]) {
|
|
403
|
+
for (const p of t.properties) {
|
|
404
|
+
if ((p.type === "I64" || p.type === "U64") && (p.key || p.name === "id")) {
|
|
405
|
+
out.push({ type: t.name, property: p.name });
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return out;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// src/normalize.ts
|
|
413
|
+
var UnknownEdgeTypeError = class extends Error {
|
|
414
|
+
name = "UnknownEdgeTypeError";
|
|
415
|
+
edgeName;
|
|
416
|
+
constructor(edgeName) {
|
|
417
|
+
super(
|
|
418
|
+
`Unknown edge type '${edgeName}': not declared in the graph schema, so its endpoint node types cannot be resolved (spec B.3).`
|
|
419
|
+
);
|
|
420
|
+
this.edgeName = edgeName;
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
var InvalidExportLineError = class extends Error {
|
|
424
|
+
name = "InvalidExportLineError";
|
|
425
|
+
constructor(message) {
|
|
426
|
+
super(message);
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
function isRecord(v) {
|
|
430
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
431
|
+
}
|
|
432
|
+
function classifyExportLine(line) {
|
|
433
|
+
if (!isRecord(line) || !isRecord(line["data"])) return { kind: "unknown" };
|
|
434
|
+
const data = line["data"];
|
|
435
|
+
if (typeof line["edge"] === "string" && typeof line["from"] === "string" && typeof line["to"] === "string") {
|
|
436
|
+
return { kind: "edge", edge: line["edge"], from: line["from"], to: line["to"], data };
|
|
437
|
+
}
|
|
438
|
+
if (typeof line["type"] === "string") {
|
|
439
|
+
return { kind: "node", type: line["type"], data };
|
|
440
|
+
}
|
|
441
|
+
return { kind: "unknown" };
|
|
442
|
+
}
|
|
443
|
+
var MS_PER_DAY = 864e5;
|
|
444
|
+
function formatEpochDay(days) {
|
|
445
|
+
const d = new Date(days * MS_PER_DAY);
|
|
446
|
+
const t = d.getTime();
|
|
447
|
+
if (!Number.isFinite(t)) return String(days);
|
|
448
|
+
const y = d.getUTCFullYear();
|
|
449
|
+
const year = y < 0 ? `-${String(-y).padStart(6, "0")}` : y > 9999 ? `+${String(y).padStart(6, "0")}` : String(y).padStart(4, "0");
|
|
450
|
+
const month = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
451
|
+
const day = String(d.getUTCDate()).padStart(2, "0");
|
|
452
|
+
return `${year}-${month}-${day}`;
|
|
453
|
+
}
|
|
454
|
+
function normalizeValue(type, value) {
|
|
455
|
+
if (type === void 0 || value === null || value === void 0) return value;
|
|
456
|
+
if (type === "Date" && typeof value === "number" && Number.isInteger(value)) {
|
|
457
|
+
return formatEpochDay(value);
|
|
458
|
+
}
|
|
459
|
+
if (type === "DateTime" && typeof value === "number" && Number.isFinite(value)) {
|
|
460
|
+
const d = new Date(value);
|
|
461
|
+
return Number.isFinite(d.getTime()) ? d.toISOString() : value;
|
|
462
|
+
}
|
|
463
|
+
if (type === "Blob" && typeof value === "string" && value.startsWith("base64:")) {
|
|
464
|
+
return `data:application/octet-stream;base64,${value.slice("base64:".length)}`;
|
|
465
|
+
}
|
|
466
|
+
return value;
|
|
467
|
+
}
|
|
468
|
+
function propTypeMap(t) {
|
|
469
|
+
const map = /* @__PURE__ */ new Map();
|
|
470
|
+
if (t) for (const p of t.properties) map.set(p.name, p.type);
|
|
471
|
+
return map;
|
|
472
|
+
}
|
|
473
|
+
function normalizeData(data, types) {
|
|
474
|
+
const out = {};
|
|
475
|
+
for (const [k, v] of Object.entries(data)) out[k] = normalizeValue(types.get(k), v);
|
|
476
|
+
return out;
|
|
477
|
+
}
|
|
478
|
+
function requireStringId(data, what) {
|
|
479
|
+
const id = data["id"];
|
|
480
|
+
if (typeof id !== "string") {
|
|
481
|
+
throw new InvalidExportLineError(
|
|
482
|
+
`${what} export line has ${id === void 0 ? "no" : "a non-string"} 'data.id' \u2014 cannot build a stable orbit id (spec B.3).`
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
return id;
|
|
486
|
+
}
|
|
487
|
+
var ORBIT_TYPE_KEY = "orbit:type";
|
|
488
|
+
function normalizeNode(line, schema) {
|
|
489
|
+
const nodeType = schema.nodes.find((n) => n.name === line.type);
|
|
490
|
+
const id = encodeSourceId(line.type, requireStringId(line.data, `Node '${line.type}'`));
|
|
491
|
+
return {
|
|
492
|
+
id,
|
|
493
|
+
// The discriminator is adapter-owned identity metadata. It lands LAST so
|
|
494
|
+
// a forward-compatible export field literally named `orbit:type` cannot
|
|
495
|
+
// forge the value the generated attrs unions promise (B.3/B.6).
|
|
496
|
+
attrs: { ...normalizeData(line.data, propTypeMap(nodeType)), [ORBIT_TYPE_KEY]: line.type }
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function normalizeEdge(line, schema) {
|
|
500
|
+
const endpoints = edgeEndpointTypes(schema, line.edge);
|
|
501
|
+
if (endpoints === null) throw new UnknownEdgeTypeError(line.edge);
|
|
502
|
+
const lower = line.edge.toLowerCase();
|
|
503
|
+
const edgeType = schema.edges.find((e) => e.name === line.edge) ?? schema.edges.find((e) => e.name.toLowerCase() === lower);
|
|
504
|
+
const id = encodeSourceId(line.edge, requireStringId(line.data, `Edge '${line.edge}'`));
|
|
505
|
+
return {
|
|
506
|
+
id,
|
|
507
|
+
source: encodeSourceId(endpoints.from, line.from),
|
|
508
|
+
target: encodeSourceId(endpoints.to, line.to),
|
|
509
|
+
// As on nodes, the adapter's resolved edge name lands last and always
|
|
510
|
+
// wins the discriminator key; a source `type` property is ordinary data.
|
|
511
|
+
attrs: { ...normalizeData(line.data, propTypeMap(edgeType)), [ORBIT_TYPE_KEY]: line.edge }
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export { InvalidExportLineError, ORBIT_TYPE_KEY, UnknownEdgeTypeError, bigIntKeyWarnings, classifyExportLine, decodeSourceId, edgeEndpointTypes, encodeSourceId, encodeSyntheticEdgeId, normalizeEdge, normalizeNode, parsePgSchema, schemaFingerprint };
|
|
516
|
+
//# sourceMappingURL=chunk-32TESFMK.js.map
|
|
517
|
+
//# sourceMappingURL=chunk-32TESFMK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/idCodec.ts","../src/pgSchema.ts","../src/normalize.ts"],"names":["anns","body","braceIdx","blockEnd"],"mappings":"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","file":"chunk-32TESFMK.js","sourcesContent":["/**\n * Identity codec (spec Appendix B.3 / B.4).\n *\n * Omnigraph node ids are unique **per type only** (derived from the `@key`\n * tuple within each type's table), so unqualified ids are unsound as orbit\n * `NodeId`s. Every adapter path — nodes, edges, search results, view state,\n * services — MUST qualify ids through this one collision-proof tuple codec.\n * `JSON.stringify` of a fixed-arity string tuple is injective over its inputs\n * (quotes, brackets, commas, and unicode in either component are escaped), so\n * no `(kind, sourceId)` pair can collide with a different pair.\n *\n * Human-readable labels stay separate from identity; there is deliberately no\n * `namespaceIds:false` escape hatch (B.3).\n */\n\nexport interface DecodedSourceId {\n /** The namespace component: a node type name or an edge type name. */\n kind: string;\n /** The physical Omnigraph id within that type's table. */\n sourceId: string;\n}\n\n/**\n * Encode a `(kind, sourceId)` pair as a collision-proof orbit id.\n *\n * - Nodes: `encodeSourceId(NodeType, data.id)`\n * - Edges: `encodeSourceId(EdgeName, data.id)`; endpoints use\n * `encodeSourceId(endpointType, from|to)` (B.3).\n */\nexport function encodeSourceId(kind: string, sourceId: string): string {\n return JSON.stringify([kind, sourceId]);\n}\n\n/**\n * Decode an id produced by {@link encodeSourceId}.\n *\n * Returns `null` for anything that does not conform exactly (non-JSON input,\n * non-array JSON, wrong arity — including synthetic edge ids, which are\n * 4-tuples — or non-string elements). Never throws.\n */\nexport function decodeSourceId(id: string): DecodedSourceId | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(id);\n } catch {\n return null;\n }\n if (!Array.isArray(parsed) || parsed.length !== 2) return null;\n const [kind, sourceId] = parsed as unknown[];\n if (typeof kind !== 'string' || typeof sourceId !== 'string') return null;\n return { kind, sourceId };\n}\n\n/**\n * Synthetic edge id for **query-derived** subgraphs (spec §5 rule, B.4).\n *\n * The GQ grammar has no edge variable, so the query path can never surface\n * physical edge ids; query-derived edges are identified by\n * `['synthetic-edge', EdgeName, source, target]` where `source`/`target` are\n * the already-encoded endpoint node ids.\n *\n * Exported for the future query path (B.5 expansion recipe — post-v1).\n * Caveats (B.4): parallel edges collapse under this scheme, and a dataset\n * MUST NOT mix synthetic ids with physical `/export` ids for the same edges —\n * one scheme per dataset, never both. Because a synthetic id is a 4-tuple,\n * {@link decodeSourceId} rejects it (`null`), keeping the two schemes\n * mechanically un-confusable.\n */\nexport function encodeSyntheticEdgeId(edgeName: string, source: string, target: string): string {\n return JSON.stringify(['synthetic-edge', edgeName, source, target]);\n}\n","/**\n * `.pg` schema model + tolerant parser (spec Appendix B.3 / B.6).\n *\n * The adapter needs three things from the graph schema, all served here:\n * 1. edge endpoint-type resolution (B.3 — export edge lines carry bare\n * `from`/`to` ids without endpoint types),\n * 2. per-property wire-type knowledge for temporal/blob normalization (B.6),\n * 3. a stable schema fingerprint for the export revision stamp (B.2).\n *\n * The parser is deliberately tolerant: it extracts the declarations it\n * understands (interfaces, node blocks, edge declarations, properties,\n * constraints) and preserves anything else — unknown annotations survive as\n * raw strings, unknown type spellings become `{ kind: 'unknown' }` — so a\n * newer server grammar degrades gracefully instead of failing the load.\n *\n * Browser-safe: no `node:` imports. The fingerprint is a pure FNV-1a 64-bit\n * hash rather than `node:crypto` sha256 so this module can sit on the\n * browser entry's critical path.\n */\n\n// ---------------------------------------------------------------------------\n// Model\n// ---------------------------------------------------------------------------\n\n/** Closed scalar set per the `.pg` grammar (docs/user/schema). */\nexport type PgScalarName =\n | 'String'\n | 'Blob'\n | 'Bool'\n | 'I32'\n | 'I64'\n | 'U32'\n | 'U64'\n | 'F32'\n | 'F64'\n | 'Date'\n | 'DateTime';\n\nexport type PgType =\n | PgScalarName\n | { kind: 'vector'; dim: number }\n | { kind: 'enum'; values: readonly string[] }\n | { kind: 'list'; element: PgScalarName }\n | { kind: 'unknown'; raw: string };\n\nexport interface PgProperty {\n name: string;\n type: PgType;\n /** `T?` nullability. */\n optional: boolean;\n /** Set by inline `@key` or a body-level `@key(...)` naming this property. */\n key: boolean;\n /** Set by inline `@unique` or a body-level `@unique(...)` naming this property. */\n unique: boolean;\n /** Set by inline `@index` or a body-level `@index(...)` naming this property. */\n index: boolean;\n /** Every annotation as written (`'@key'`, `'@embed(\"body\")'`) — unknown ones preserved verbatim. */\n annotations: readonly string[];\n}\n\nexport interface PgInterfaceType {\n name: string;\n properties: readonly PgProperty[];\n /** Body-level constraint declarations preserved verbatim (e.g. `'@unique(a, b)'`). */\n constraints: readonly string[];\n}\n\nexport interface PgNodeType {\n name: string;\n /** Interface names from the `implements` clause (already expanded into `properties`). */\n implements: readonly string[];\n properties: readonly PgProperty[];\n constraints: readonly string[];\n}\n\nexport interface PgEdgeType {\n name: string;\n /** Source (from) node type name. */\n from: string;\n /** Destination (to) node type name. */\n to: string;\n /** Raw `@card` bounds, e.g. `'1..1'`, `'0..*'`. Absent means the default `0..*`. */\n card?: string;\n /** Header annotations as written (including the `@card(...)` one, if any). */\n annotations: readonly string[];\n properties: readonly PgProperty[];\n constraints: readonly string[];\n}\n\nexport interface PgSchema {\n interfaces: readonly PgInterfaceType[];\n nodes: readonly PgNodeType[];\n edges: readonly PgEdgeType[];\n}\n\nconst SCALARS: ReadonlySet<string> = new Set<PgScalarName>([\n 'String',\n 'Blob',\n 'Bool',\n 'I32',\n 'I64',\n 'U32',\n 'U64',\n 'F32',\n 'F64',\n 'Date',\n 'DateTime',\n]);\n\n// ---------------------------------------------------------------------------\n// Lexical helpers (string-aware; `.pg` strings are double-quoted with `\\` escapes)\n// ---------------------------------------------------------------------------\n\n/** Blank out line and block comments, preserving newlines and string literals. */\nfunction stripComments(src: string): string {\n let out = '';\n let i = 0;\n const n = src.length;\n while (i < n) {\n const ch = src.charAt(i);\n if (ch === '\"') {\n out += ch;\n i++;\n while (i < n) {\n const c = src.charAt(i);\n out += c;\n i++;\n if (c === '\\\\' && i < n) {\n out += src.charAt(i);\n i++;\n } else if (c === '\"') break;\n }\n } else if (ch === '/' && src.charAt(i + 1) === '/') {\n while (i < n && src.charAt(i) !== '\\n') i++;\n } else if (ch === '/' && src.charAt(i + 1) === '*') {\n i += 2;\n while (i < n && !(src.charAt(i) === '*' && src.charAt(i + 1) === '/')) {\n out += src.charAt(i) === '\\n' ? '\\n' : ' ';\n i++;\n }\n i += 2;\n } else {\n out += ch;\n i++;\n }\n }\n return out;\n}\n\n/** Index just past the `}` matching the `{` at `openIdx`, or `src.length` if unbalanced. */\nfunction findBlockEnd(src: string, openIdx: number): number {\n let depth = 0;\n let i = openIdx;\n const n = src.length;\n while (i < n) {\n const ch = src.charAt(i);\n if (ch === '\"') {\n i++;\n while (i < n) {\n const c = src.charAt(i);\n i++;\n if (c === '\\\\') i++;\n else if (c === '\"') break;\n }\n continue;\n }\n if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) return i + 1;\n }\n i++;\n }\n return n;\n}\n\n/** Split a block body into statements at newlines that sit outside parens/brackets/strings. */\nfunction splitStatements(body: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let current = '';\n let i = 0;\n const n = body.length;\n while (i < n) {\n const ch = body.charAt(i);\n if (ch === '\"') {\n current += ch;\n i++;\n while (i < n) {\n const c = body.charAt(i);\n current += c;\n i++;\n if (c === '\\\\' && i < n) {\n current += body.charAt(i);\n i++;\n } else if (c === '\"') break;\n }\n continue;\n }\n if (ch === '(' || ch === '[') depth++;\n else if (ch === ')' || ch === ']') depth = Math.max(0, depth - 1);\n if (ch === '\\n' && depth === 0) {\n out.push(current);\n current = '';\n } else {\n current += ch;\n }\n i++;\n }\n out.push(current);\n return out.map((s) => s.trim()).filter((s) => s.length > 0);\n}\n\ninterface RawAnnotation {\n name: string;\n args?: string;\n raw: string;\n}\n\n/** Scan a run of `@ident` / `@ident(...)` annotations starting at `start`. */\nfunction scanAnnotations(src: string, start: number): { anns: RawAnnotation[]; end: number } {\n const anns: RawAnnotation[] = [];\n let i = start;\n const n = src.length;\n for (;;) {\n let j = i;\n while (j < n && /\\s/.test(src.charAt(j))) j++;\n if (src.charAt(j) !== '@') break;\n const m = /^@([A-Za-z_]\\w*)/.exec(src.slice(j));\n if (!m || m[1] === undefined) break;\n const name = m[1];\n let end = j + m[0].length;\n let args: string | undefined;\n if (src.charAt(end) === '(') {\n let depth = 0;\n let k = end;\n while (k < n) {\n const ch = src.charAt(k);\n if (ch === '\"') {\n k++;\n while (k < n) {\n const c = src.charAt(k);\n k++;\n if (c === '\\\\') k++;\n else if (c === '\"') break;\n }\n continue;\n }\n if (ch === '(') depth++;\n else if (ch === ')') {\n depth--;\n if (depth === 0) {\n k++;\n break;\n }\n }\n k++;\n }\n args = src.slice(end + 1, k - 1);\n end = k;\n }\n const entry: RawAnnotation = { name, raw: src.slice(j, end) };\n if (args !== undefined) entry.args = args;\n anns.push(entry);\n i = end;\n }\n return { anns, end: i };\n}\n\n/** Split on top-level commas (outside parens/strings), trim, drop empties. */\nfunction splitArgs(args: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let current = '';\n for (let i = 0; i < args.length; i++) {\n const ch = args.charAt(i);\n if (ch === '\"') {\n current += ch;\n i++;\n while (i < args.length) {\n const c = args.charAt(i);\n current += c;\n if (c === '\\\\') {\n i++;\n current += args.charAt(i);\n } else if (c === '\"') break;\n i++;\n }\n continue;\n }\n if (ch === '(' || ch === '[') depth++;\n else if (ch === ')' || ch === ']') depth = Math.max(0, depth - 1);\n if (ch === ',' && depth === 0) {\n out.push(current);\n current = '';\n } else {\n current += ch;\n }\n }\n out.push(current);\n return out.map((s) => s.trim()).filter((s) => s.length > 0);\n}\n\n// ---------------------------------------------------------------------------\n// Statement parsing\n// ---------------------------------------------------------------------------\n\ninterface MutableTypeBody {\n properties: PgProperty[];\n constraints: string[];\n}\n\nfunction parseTypeRef(text: string): { type: PgType; optional: boolean; end: number } {\n let i = 0;\n const n = text.length;\n while (i < n && /\\s/.test(text.charAt(i))) i++;\n let type: PgType;\n if (text.charAt(i) === '[') {\n const m = /^\\[\\s*([A-Za-z_]\\w*)\\s*\\]/.exec(text.slice(i));\n if (m && m[1] !== undefined && SCALARS.has(m[1])) {\n type = { kind: 'list', element: m[1] as PgScalarName };\n i += m[0].length;\n } else {\n const close = text.indexOf(']', i);\n const end = close === -1 ? n : close + 1;\n type = { kind: 'unknown', raw: text.slice(i, end).trim() };\n i = end;\n }\n } else {\n const m = /^([A-Za-z_]\\w*)/.exec(text.slice(i));\n if (!m || m[1] === undefined) {\n return { type: { kind: 'unknown', raw: text.trim() }, optional: false, end: n };\n }\n const ident = m[1];\n i += m[0].length;\n if ((ident === 'enum' || ident === 'Vector') && text.charAt(i) === '(') {\n let depth = 0;\n let k = i;\n while (k < n) {\n const ch = text.charAt(k);\n if (ch === '(') depth++;\n else if (ch === ')') {\n depth--;\n if (depth === 0) {\n k++;\n break;\n }\n }\n k++;\n }\n const inner = text.slice(i + 1, k - 1);\n i = k;\n if (ident === 'enum') {\n const values = splitArgs(inner).map((v) => v.replace(/^\"(.*)\"$/s, '$1'));\n type = { kind: 'enum', values };\n } else {\n const dim = Number.parseInt(inner.trim(), 10);\n type = Number.isFinite(dim)\n ? { kind: 'vector', dim }\n : { kind: 'unknown', raw: `Vector(${inner})` };\n }\n } else if (SCALARS.has(ident)) {\n type = ident as PgScalarName;\n } else {\n type = { kind: 'unknown', raw: ident };\n }\n }\n let optional = false;\n if (text.charAt(i) === '?') {\n optional = true;\n i++;\n }\n return { type, optional, end: i };\n}\n\nfunction parseBody(body: string): MutableTypeBody {\n const properties: PgProperty[] = [];\n const constraints: string[] = [];\n for (const stmt of splitStatements(body)) {\n if (stmt.startsWith('@')) {\n const { anns } = scanAnnotations(stmt, 0);\n for (const a of anns) constraints.push(a.raw);\n continue;\n }\n const head = /^([A-Za-z_]\\w*)\\s*:\\s*/.exec(stmt);\n if (!head || head[1] === undefined) continue; // tolerant: skip unrecognized statements\n const name = head[1];\n const rest = stmt.slice(head[0].length);\n const { type, optional, end } = parseTypeRef(rest);\n const { anns } = scanAnnotations(rest, end);\n properties.push({\n name,\n type,\n optional,\n key: anns.some((a) => a.name === 'key'),\n unique: anns.some((a) => a.name === 'unique'),\n index: anns.some((a) => a.name === 'index'),\n annotations: anns.map((a) => a.raw),\n });\n }\n // Body-level @key(a, b) / @unique(a) / @index(a) constraints flag the named properties.\n for (const raw of constraints) {\n const m = /^@(key|unique|index)\\((.*)\\)$/s.exec(raw);\n if (!m || m[1] === undefined || m[2] === undefined) continue;\n const flag = m[1] as 'key' | 'unique' | 'index';\n for (const propName of splitArgs(m[2])) {\n const prop = properties.find((p) => p.name === propName);\n if (prop) prop[flag] = true;\n }\n }\n return { properties, constraints };\n}\n\n// ---------------------------------------------------------------------------\n// Top-level parse\n// ---------------------------------------------------------------------------\n\n/**\n * Parse `.pg` source into a {@link PgSchema}. Tolerant by design: malformed\n * or unrecognized declarations are skipped, not fatal; `implements` clauses\n * are expanded into node properties (node-declared properties win on name\n * collisions, matching the server's table layout).\n */\nexport function parsePgSchema(source: string): PgSchema {\n const src = stripComments(source);\n const interfaces: PgInterfaceType[] = [];\n const nodes: (PgNodeType & { properties: PgProperty[] })[] = [];\n const edges: PgEdgeType[] = [];\n\n const headRe = /\\b(interface|node|edge)\\s+([A-Za-z_]\\w*)/g;\n let m: RegExpExecArray | null;\n while ((m = headRe.exec(src)) !== null) {\n const kw = m[1];\n const name = m[2];\n if (kw === undefined || name === undefined) continue;\n let pos = headRe.lastIndex;\n\n if (kw === 'edge') {\n const em = /^\\s*:\\s*([A-Za-z_]\\w*)\\s*->\\s*([A-Za-z_]\\w*)/.exec(src.slice(pos));\n if (!em || em[1] === undefined || em[2] === undefined) continue; // tolerant skip\n pos += em[0].length;\n const { anns, end } = scanAnnotations(src, pos);\n pos = end;\n let body: MutableTypeBody = { properties: [], constraints: [] };\n let braceIdx = pos;\n while (braceIdx < src.length && /\\s/.test(src.charAt(braceIdx))) braceIdx++;\n if (src.charAt(braceIdx) === '{') {\n const blockEnd = findBlockEnd(src, braceIdx);\n body = parseBody(src.slice(braceIdx + 1, blockEnd - 1));\n pos = blockEnd;\n }\n const card = anns.find((a) => a.name === 'card')?.args?.trim();\n const edge: PgEdgeType = {\n name,\n from: em[1],\n to: em[2],\n annotations: anns.map((a) => a.raw),\n properties: body.properties,\n constraints: body.constraints,\n ...(card !== undefined ? { card } : {}),\n };\n edges.push(edge);\n headRe.lastIndex = pos;\n continue;\n }\n\n // interface / node: optional `implements A, B` (node only), then a block.\n let impls: string[] = [];\n if (kw === 'node') {\n const im = /^\\s*implements\\s+([A-Za-z_]\\w*(?:\\s*,\\s*[A-Za-z_]\\w*)*)/.exec(src.slice(pos));\n if (im && im[1] !== undefined) {\n impls = im[1].split(',').map((s) => s.trim());\n pos += im[0].length;\n }\n }\n let braceIdx = pos;\n while (braceIdx < src.length && /\\s/.test(src.charAt(braceIdx))) braceIdx++;\n if (src.charAt(braceIdx) !== '{') continue; // tolerant skip\n const blockEnd = findBlockEnd(src, braceIdx);\n const body = parseBody(src.slice(braceIdx + 1, blockEnd - 1));\n headRe.lastIndex = blockEnd;\n if (kw === 'interface') {\n interfaces.push({ name, properties: body.properties, constraints: body.constraints });\n } else {\n nodes.push({\n name,\n implements: impls,\n properties: body.properties,\n constraints: body.constraints,\n });\n }\n }\n\n // Expand implements clauses: interface properties precede the node's own,\n // except where the node re-declares a name (node declaration wins).\n for (const node of nodes) {\n if (node.implements.length === 0) continue;\n const own = new Set(node.properties.map((p) => p.name));\n const inherited: PgProperty[] = [];\n for (const ifaceName of node.implements) {\n const iface = interfaces.find((i) => i.name === ifaceName);\n if (!iface) continue; // tolerant: unknown interface\n for (const p of iface.properties) {\n if (!own.has(p.name) && !inherited.some((q) => q.name === p.name)) inherited.push(p);\n }\n }\n node.properties = [...inherited, ...node.properties];\n }\n\n return { interfaces, nodes, edges };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve an edge type's declared endpoint node types (B.3). Export edge\n * lines carry bare `from`/`to` ids, so endpoint types come from here. Edge\n * names match exactly first, then case-insensitively (the server matches edge\n * names case-insensitively). Returns `null` for an unknown edge name.\n */\nexport function edgeEndpointTypes(\n schema: PgSchema,\n edgeName: string,\n): { from: string; to: string } | null {\n const lower = edgeName.toLowerCase();\n const edge =\n schema.edges.find((e) => e.name === edgeName) ??\n schema.edges.find((e) => e.name.toLowerCase() === lower);\n return edge ? { from: edge.from, to: edge.to } : null;\n}\n\n/**\n * Stable fingerprint of `.pg` source for the B.2 revision stamp: FNV-1a\n * 64-bit over the UTF-8 bytes of the source, as 16 lowercase hex chars.\n *\n * Pure and browser-safe (no `node:crypto`). Hashes the source **verbatim**:\n * any textual change — including comments or whitespace — changes the\n * fingerprint, which is the conservative choice for drift detection.\n */\nexport function schemaFingerprint(source: string): string {\n const MASK64 = 0xffffffffffffffffn;\n let h = 0xcbf29ce484222325n;\n const bytes = new TextEncoder().encode(source);\n for (const b of bytes) {\n h ^= BigInt(b);\n h = (h * 0x100000001b3n) & MASK64;\n }\n return h.toString(16).padStart(16, '0');\n}\n\nexport interface BigIntKeyWarning {\n /** Node or edge type name. */\n type: string;\n /** The hazardous property. */\n property: string;\n}\n\n/**\n * B.6 hazard scan: `I64`/`U64` properties used as identity (`@key` or named\n * `id`). The HTTP path emits native JSON numbers even past ±2^53 — silently\n * rounded by `JSON.parse`, unrescued by the SDK — so two distinct big-int ids\n * can collapse after rounding, violating §5. Surface these before loading.\n */\nexport function bigIntKeyWarnings(schema: PgSchema): BigIntKeyWarning[] {\n const out: BigIntKeyWarning[] = [];\n for (const t of [...schema.nodes, ...schema.edges]) {\n for (const p of t.properties) {\n if ((p.type === 'I64' || p.type === 'U64') && (p.key || p.name === 'id')) {\n out.push({ type: t.name, property: p.name });\n }\n }\n }\n return out;\n}\n","/**\n * Export-line classification and normalization (spec Appendix B.2 / B.3 / B.6).\n *\n * `/export` streams NDJSON — one JSON object per line, `data` passed through\n * **verbatim** by the SDK. This module turns those lines into orbit\n * `GraphNode`/`GraphEdge` values:\n *\n * - ids are namespaced through the B.3 codec (`encodeSourceId`),\n * - the node/edge KIND is injected as {@link ORBIT_TYPE_KEY} — namespaced so\n * a schema's own `type` property passes through as ordinary data (B.6),\n * - edge endpoint types are resolved from the `.pg` schema (edge lines carry\n * bare `from`/`to` ids — B.3),\n * - attr values are normalized to the query-path string forms (B.6) so\n * generated types and §16.6 temporal dimensions see one encoding\n * regardless of read path:\n * * `Date` — export sends **days since Unix epoch** (number) →\n * `'YYYY-MM-DD'` (UTC)\n * * `DateTime` — export sends **epoch milliseconds** (number) →\n * ISO 8601 (`'YYYY-MM-DDTHH:MM:SS.mmmZ'`)\n * * `Blob` — inline internal blobs arrive as `'base64:<data>'` →\n * `'data:application/octet-stream;base64,<data>'`;\n * external-URI refs pass through verbatim (B.10)\n * * everything else — verbatim.\n *\n * Non-finite float sentinels (`'NaN'`/`'Infinity'`/`'-Infinity'`) are a\n * **query-path-only** encoding: a non-finite stored float aborts `/export`\n * server-side, so export-loaded data never contains the sentinels (B.6).\n * This module therefore does NOT special-case them.\n */\n\nimport type { GraphEdge, GraphNode } from '@modernrelay/orbit-core';\nimport { encodeSourceId } from './idCodec';\nimport {\n edgeEndpointTypes,\n type PgEdgeType,\n type PgNodeType,\n type PgProperty,\n type PgSchema,\n type PgType,\n} from './pgSchema';\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/** An edge line names an edge type the `.pg` schema does not declare (B.3). */\nexport class UnknownEdgeTypeError extends Error {\n override readonly name = 'UnknownEdgeTypeError';\n readonly edgeName: string;\n constructor(edgeName: string) {\n super(\n `Unknown edge type '${edgeName}': not declared in the graph schema, so its ` +\n `endpoint node types cannot be resolved (spec B.3).`,\n );\n this.edgeName = edgeName;\n }\n}\n\n/** An export line is structurally unusable (e.g. missing/non-string `data.id`). */\nexport class InvalidExportLineError extends Error {\n override readonly name = 'InvalidExportLineError';\n constructor(message: string) {\n super(message);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Classification (B.2 line shapes)\n// ---------------------------------------------------------------------------\n\nexport interface NodeExportLine {\n kind: 'node';\n type: string;\n data: Record<string, unknown>;\n}\n\nexport interface EdgeExportLine {\n kind: 'edge';\n edge: string;\n from: string;\n to: string;\n data: Record<string, unknown>;\n}\n\nexport type ClassifiedExportLine = NodeExportLine | EdgeExportLine | { kind: 'unknown' };\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Classify one parsed export line per the B.2 shapes:\n * - node line: `{\"type\": \"<NodeType>\", \"data\": {\"id\", …props}}`\n * - edge line: `{\"edge\": \"<EdgeName>\", \"from\": <src id>, \"to\": <dst id>, \"data\": {\"id\", …props}}`\n * Anything else is `{ kind: 'unknown' }`.\n */\nexport function classifyExportLine(line: unknown): ClassifiedExportLine {\n if (!isRecord(line) || !isRecord(line['data'])) return { kind: 'unknown' };\n const data = line['data'];\n if (\n typeof line['edge'] === 'string' &&\n typeof line['from'] === 'string' &&\n typeof line['to'] === 'string'\n ) {\n return { kind: 'edge', edge: line['edge'], from: line['from'], to: line['to'], data };\n }\n if (typeof line['type'] === 'string') {\n return { kind: 'node', type: line['type'], data };\n }\n return { kind: 'unknown' };\n}\n\n// ---------------------------------------------------------------------------\n// Value normalization (B.6)\n// ---------------------------------------------------------------------------\n\nconst MS_PER_DAY = 86_400_000;\n\n/** Format an epoch-day count as `'YYYY-MM-DD'` (UTC). Handles negative days. */\nfunction formatEpochDay(days: number): string {\n const d = new Date(days * MS_PER_DAY);\n const t = d.getTime();\n if (!Number.isFinite(t)) return String(days); // out of Date range — leave a readable value\n const y = d.getUTCFullYear();\n const year =\n y < 0\n ? `-${String(-y).padStart(6, '0')}`\n : y > 9999\n ? `+${String(y).padStart(6, '0')}`\n : String(y).padStart(4, '0');\n const month = String(d.getUTCMonth() + 1).padStart(2, '0');\n const day = String(d.getUTCDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\nfunction normalizeValue(type: PgType | undefined, value: unknown): unknown {\n if (type === undefined || value === null || value === undefined) return value;\n if (type === 'Date' && typeof value === 'number' && Number.isInteger(value)) {\n return formatEpochDay(value);\n }\n if (type === 'DateTime' && typeof value === 'number' && Number.isFinite(value)) {\n const d = new Date(value);\n return Number.isFinite(d.getTime()) ? d.toISOString() : value;\n }\n if (type === 'Blob' && typeof value === 'string' && value.startsWith('base64:')) {\n return `data:application/octet-stream;base64,${value.slice('base64:'.length)}`;\n }\n return value;\n}\n\nfunction propTypeMap(t: PgNodeType | PgEdgeType | undefined): ReadonlyMap<string, PgType> {\n const map = new Map<string, PgType>();\n if (t) for (const p of t.properties as readonly PgProperty[]) map.set(p.name, p.type);\n return map;\n}\n\nfunction normalizeData(\n data: Record<string, unknown>,\n types: ReadonlyMap<string, PgType>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(data)) out[k] = normalizeValue(types.get(k), v);\n return out;\n}\n\nfunction requireStringId(data: Record<string, unknown>, what: string): string {\n const id = data['id'];\n if (typeof id !== 'string') {\n throw new InvalidExportLineError(\n `${what} export line has ${id === undefined ? 'no' : 'a non-string'} 'data.id' — ` +\n `cannot build a stable orbit id (spec B.3).`,\n );\n }\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// Node / edge normalization (B.3)\n// ---------------------------------------------------------------------------\n\n/**\n * The adapter's node/edge KIND discriminator key (B.3/B.6).\n *\n * Namespaced on purpose: the adapter injects this field into someone else's\n * data, so it takes the awkward key and leaves the generic word `type` to the\n * schema author, who means something real by it (`Company.type = investor`).\n * A colon is illegal in `.pg` identifiers, so no schema property can ever\n * claim this key — the collision class is closed by construction, and a\n * source-declared `type` now flows through untouched with no preservation\n * mechanism, no warning, and no schema migration. Same convention as\n * GraphQL's `__typename` / JSON-LD's `@type`.\n */\nexport const ORBIT_TYPE_KEY = 'orbit:type';\n\n/**\n * Normalize a node export line to a `GraphNode`:\n * `id = encodeSourceId(type, data.id)`, `attrs = { …data, 'orbit:type' }`\n * with B.6 value normalization driven by the schema's property types. A node\n * type absent from the schema is tolerated — its attrs pass through verbatim\n * (identity never needs the schema on the node path).\n */\nexport function normalizeNode(\n line: { type: string; data: Record<string, unknown> },\n schema: PgSchema,\n): GraphNode {\n const nodeType = schema.nodes.find((n) => n.name === line.type);\n const id = encodeSourceId(line.type, requireStringId(line.data, `Node '${line.type}'`));\n return {\n id,\n // The discriminator is adapter-owned identity metadata. It lands LAST so\n // a forward-compatible export field literally named `orbit:type` cannot\n // forge the value the generated attrs unions promise (B.3/B.6).\n attrs: { ...normalizeData(line.data, propTypeMap(nodeType)), [ORBIT_TYPE_KEY]: line.type },\n };\n}\n\n/**\n * Normalize an edge export line to a `GraphEdge`:\n * `id = encodeSourceId(edge, data.id)`; `source`/`target` namespace the bare\n * `from`/`to` ids with the endpoint node types resolved from the schema\n * (B.3). Throws {@link UnknownEdgeTypeError} when the schema does not declare\n * the edge — endpoint identity cannot be constructed without it.\n */\nexport function normalizeEdge(\n line: { edge: string; from: string; to: string; data: Record<string, unknown> },\n schema: PgSchema,\n): GraphEdge {\n const endpoints = edgeEndpointTypes(schema, line.edge);\n if (endpoints === null) throw new UnknownEdgeTypeError(line.edge);\n const lower = line.edge.toLowerCase();\n const edgeType =\n schema.edges.find((e) => e.name === line.edge) ??\n schema.edges.find((e) => e.name.toLowerCase() === lower);\n const id = encodeSourceId(line.edge, requireStringId(line.data, `Edge '${line.edge}'`));\n return {\n id,\n source: encodeSourceId(endpoints.from, line.from),\n target: encodeSourceId(endpoints.to, line.to),\n // As on nodes, the adapter's resolved edge name lands last and always\n // wins the discriminator key; a source `type` property is ordinary data.\n attrs: { ...normalizeData(line.data, propTypeMap(edgeType)), [ORBIT_TYPE_KEY]: line.edge },\n };\n}\n"]}
|