@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
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
import { GraphEdge, GraphNode, BeginIngestOptions, IngestSession, Revisions, GraphDiagnostic, SearchResult, SearchService } from '@modernrelay/orbit-core';
|
|
2
|
+
import { Omnigraph } from '@modernrelay/omnigraph';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Identity codec (spec Appendix B.3 / B.4).
|
|
6
|
+
*
|
|
7
|
+
* Omnigraph node ids are unique **per type only** (derived from the `@key`
|
|
8
|
+
* tuple within each type's table), so unqualified ids are unsound as orbit
|
|
9
|
+
* `NodeId`s. Every adapter path — nodes, edges, search results, view state,
|
|
10
|
+
* services — MUST qualify ids through this one collision-proof tuple codec.
|
|
11
|
+
* `JSON.stringify` of a fixed-arity string tuple is injective over its inputs
|
|
12
|
+
* (quotes, brackets, commas, and unicode in either component are escaped), so
|
|
13
|
+
* no `(kind, sourceId)` pair can collide with a different pair.
|
|
14
|
+
*
|
|
15
|
+
* Human-readable labels stay separate from identity; there is deliberately no
|
|
16
|
+
* `namespaceIds:false` escape hatch (B.3).
|
|
17
|
+
*/
|
|
18
|
+
interface DecodedSourceId {
|
|
19
|
+
/** The namespace component: a node type name or an edge type name. */
|
|
20
|
+
kind: string;
|
|
21
|
+
/** The physical Omnigraph id within that type's table. */
|
|
22
|
+
sourceId: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Encode a `(kind, sourceId)` pair as a collision-proof orbit id.
|
|
26
|
+
*
|
|
27
|
+
* - Nodes: `encodeSourceId(NodeType, data.id)`
|
|
28
|
+
* - Edges: `encodeSourceId(EdgeName, data.id)`; endpoints use
|
|
29
|
+
* `encodeSourceId(endpointType, from|to)` (B.3).
|
|
30
|
+
*/
|
|
31
|
+
declare function encodeSourceId(kind: string, sourceId: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Decode an id produced by {@link encodeSourceId}.
|
|
34
|
+
*
|
|
35
|
+
* Returns `null` for anything that does not conform exactly (non-JSON input,
|
|
36
|
+
* non-array JSON, wrong arity — including synthetic edge ids, which are
|
|
37
|
+
* 4-tuples — or non-string elements). Never throws.
|
|
38
|
+
*/
|
|
39
|
+
declare function decodeSourceId(id: string): DecodedSourceId | null;
|
|
40
|
+
/**
|
|
41
|
+
* Synthetic edge id for **query-derived** subgraphs (spec §5 rule, B.4).
|
|
42
|
+
*
|
|
43
|
+
* The GQ grammar has no edge variable, so the query path can never surface
|
|
44
|
+
* physical edge ids; query-derived edges are identified by
|
|
45
|
+
* `['synthetic-edge', EdgeName, source, target]` where `source`/`target` are
|
|
46
|
+
* the already-encoded endpoint node ids.
|
|
47
|
+
*
|
|
48
|
+
* Exported for the future query path (B.5 expansion recipe — post-v1).
|
|
49
|
+
* Caveats (B.4): parallel edges collapse under this scheme, and a dataset
|
|
50
|
+
* MUST NOT mix synthetic ids with physical `/export` ids for the same edges —
|
|
51
|
+
* one scheme per dataset, never both. Because a synthetic id is a 4-tuple,
|
|
52
|
+
* {@link decodeSourceId} rejects it (`null`), keeping the two schemes
|
|
53
|
+
* mechanically un-confusable.
|
|
54
|
+
*/
|
|
55
|
+
declare function encodeSyntheticEdgeId(edgeName: string, source: string, target: string): string;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* `.pg` schema model + tolerant parser (spec Appendix B.3 / B.6).
|
|
59
|
+
*
|
|
60
|
+
* The adapter needs three things from the graph schema, all served here:
|
|
61
|
+
* 1. edge endpoint-type resolution (B.3 — export edge lines carry bare
|
|
62
|
+
* `from`/`to` ids without endpoint types),
|
|
63
|
+
* 2. per-property wire-type knowledge for temporal/blob normalization (B.6),
|
|
64
|
+
* 3. a stable schema fingerprint for the export revision stamp (B.2).
|
|
65
|
+
*
|
|
66
|
+
* The parser is deliberately tolerant: it extracts the declarations it
|
|
67
|
+
* understands (interfaces, node blocks, edge declarations, properties,
|
|
68
|
+
* constraints) and preserves anything else — unknown annotations survive as
|
|
69
|
+
* raw strings, unknown type spellings become `{ kind: 'unknown' }` — so a
|
|
70
|
+
* newer server grammar degrades gracefully instead of failing the load.
|
|
71
|
+
*
|
|
72
|
+
* Browser-safe: no `node:` imports. The fingerprint is a pure FNV-1a 64-bit
|
|
73
|
+
* hash rather than `node:crypto` sha256 so this module can sit on the
|
|
74
|
+
* browser entry's critical path.
|
|
75
|
+
*/
|
|
76
|
+
/** Closed scalar set per the `.pg` grammar (docs/user/schema). */
|
|
77
|
+
type PgScalarName = 'String' | 'Blob' | 'Bool' | 'I32' | 'I64' | 'U32' | 'U64' | 'F32' | 'F64' | 'Date' | 'DateTime';
|
|
78
|
+
type PgType = PgScalarName | {
|
|
79
|
+
kind: 'vector';
|
|
80
|
+
dim: number;
|
|
81
|
+
} | {
|
|
82
|
+
kind: 'enum';
|
|
83
|
+
values: readonly string[];
|
|
84
|
+
} | {
|
|
85
|
+
kind: 'list';
|
|
86
|
+
element: PgScalarName;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'unknown';
|
|
89
|
+
raw: string;
|
|
90
|
+
};
|
|
91
|
+
interface PgProperty {
|
|
92
|
+
name: string;
|
|
93
|
+
type: PgType;
|
|
94
|
+
/** `T?` nullability. */
|
|
95
|
+
optional: boolean;
|
|
96
|
+
/** Set by inline `@key` or a body-level `@key(...)` naming this property. */
|
|
97
|
+
key: boolean;
|
|
98
|
+
/** Set by inline `@unique` or a body-level `@unique(...)` naming this property. */
|
|
99
|
+
unique: boolean;
|
|
100
|
+
/** Set by inline `@index` or a body-level `@index(...)` naming this property. */
|
|
101
|
+
index: boolean;
|
|
102
|
+
/** Every annotation as written (`'@key'`, `'@embed("body")'`) — unknown ones preserved verbatim. */
|
|
103
|
+
annotations: readonly string[];
|
|
104
|
+
}
|
|
105
|
+
interface PgInterfaceType {
|
|
106
|
+
name: string;
|
|
107
|
+
properties: readonly PgProperty[];
|
|
108
|
+
/** Body-level constraint declarations preserved verbatim (e.g. `'@unique(a, b)'`). */
|
|
109
|
+
constraints: readonly string[];
|
|
110
|
+
}
|
|
111
|
+
interface PgNodeType {
|
|
112
|
+
name: string;
|
|
113
|
+
/** Interface names from the `implements` clause (already expanded into `properties`). */
|
|
114
|
+
implements: readonly string[];
|
|
115
|
+
properties: readonly PgProperty[];
|
|
116
|
+
constraints: readonly string[];
|
|
117
|
+
}
|
|
118
|
+
interface PgEdgeType {
|
|
119
|
+
name: string;
|
|
120
|
+
/** Source (from) node type name. */
|
|
121
|
+
from: string;
|
|
122
|
+
/** Destination (to) node type name. */
|
|
123
|
+
to: string;
|
|
124
|
+
/** Raw `@card` bounds, e.g. `'1..1'`, `'0..*'`. Absent means the default `0..*`. */
|
|
125
|
+
card?: string;
|
|
126
|
+
/** Header annotations as written (including the `@card(...)` one, if any). */
|
|
127
|
+
annotations: readonly string[];
|
|
128
|
+
properties: readonly PgProperty[];
|
|
129
|
+
constraints: readonly string[];
|
|
130
|
+
}
|
|
131
|
+
interface PgSchema {
|
|
132
|
+
interfaces: readonly PgInterfaceType[];
|
|
133
|
+
nodes: readonly PgNodeType[];
|
|
134
|
+
edges: readonly PgEdgeType[];
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Parse `.pg` source into a {@link PgSchema}. Tolerant by design: malformed
|
|
138
|
+
* or unrecognized declarations are skipped, not fatal; `implements` clauses
|
|
139
|
+
* are expanded into node properties (node-declared properties win on name
|
|
140
|
+
* collisions, matching the server's table layout).
|
|
141
|
+
*/
|
|
142
|
+
declare function parsePgSchema(source: string): PgSchema;
|
|
143
|
+
/**
|
|
144
|
+
* Resolve an edge type's declared endpoint node types (B.3). Export edge
|
|
145
|
+
* lines carry bare `from`/`to` ids, so endpoint types come from here. Edge
|
|
146
|
+
* names match exactly first, then case-insensitively (the server matches edge
|
|
147
|
+
* names case-insensitively). Returns `null` for an unknown edge name.
|
|
148
|
+
*/
|
|
149
|
+
declare function edgeEndpointTypes(schema: PgSchema, edgeName: string): {
|
|
150
|
+
from: string;
|
|
151
|
+
to: string;
|
|
152
|
+
} | null;
|
|
153
|
+
/**
|
|
154
|
+
* Stable fingerprint of `.pg` source for the B.2 revision stamp: FNV-1a
|
|
155
|
+
* 64-bit over the UTF-8 bytes of the source, as 16 lowercase hex chars.
|
|
156
|
+
*
|
|
157
|
+
* Pure and browser-safe (no `node:crypto`). Hashes the source **verbatim**:
|
|
158
|
+
* any textual change — including comments or whitespace — changes the
|
|
159
|
+
* fingerprint, which is the conservative choice for drift detection.
|
|
160
|
+
*/
|
|
161
|
+
declare function schemaFingerprint(source: string): string;
|
|
162
|
+
interface BigIntKeyWarning {
|
|
163
|
+
/** Node or edge type name. */
|
|
164
|
+
type: string;
|
|
165
|
+
/** The hazardous property. */
|
|
166
|
+
property: string;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* B.6 hazard scan: `I64`/`U64` properties used as identity (`@key` or named
|
|
170
|
+
* `id`). The HTTP path emits native JSON numbers even past ±2^53 — silently
|
|
171
|
+
* rounded by `JSON.parse`, unrescued by the SDK — so two distinct big-int ids
|
|
172
|
+
* can collapse after rounding, violating §5. Surface these before loading.
|
|
173
|
+
*/
|
|
174
|
+
declare function bigIntKeyWarnings(schema: PgSchema): BigIntKeyWarning[];
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Export-line classification and normalization (spec Appendix B.2 / B.3 / B.6).
|
|
178
|
+
*
|
|
179
|
+
* `/export` streams NDJSON — one JSON object per line, `data` passed through
|
|
180
|
+
* **verbatim** by the SDK. This module turns those lines into orbit
|
|
181
|
+
* `GraphNode`/`GraphEdge` values:
|
|
182
|
+
*
|
|
183
|
+
* - ids are namespaced through the B.3 codec (`encodeSourceId`),
|
|
184
|
+
* - the node/edge KIND is injected as {@link ORBIT_TYPE_KEY} — namespaced so
|
|
185
|
+
* a schema's own `type` property passes through as ordinary data (B.6),
|
|
186
|
+
* - edge endpoint types are resolved from the `.pg` schema (edge lines carry
|
|
187
|
+
* bare `from`/`to` ids — B.3),
|
|
188
|
+
* - attr values are normalized to the query-path string forms (B.6) so
|
|
189
|
+
* generated types and §16.6 temporal dimensions see one encoding
|
|
190
|
+
* regardless of read path:
|
|
191
|
+
* * `Date` — export sends **days since Unix epoch** (number) →
|
|
192
|
+
* `'YYYY-MM-DD'` (UTC)
|
|
193
|
+
* * `DateTime` — export sends **epoch milliseconds** (number) →
|
|
194
|
+
* ISO 8601 (`'YYYY-MM-DDTHH:MM:SS.mmmZ'`)
|
|
195
|
+
* * `Blob` — inline internal blobs arrive as `'base64:<data>'` →
|
|
196
|
+
* `'data:application/octet-stream;base64,<data>'`;
|
|
197
|
+
* external-URI refs pass through verbatim (B.10)
|
|
198
|
+
* * everything else — verbatim.
|
|
199
|
+
*
|
|
200
|
+
* Non-finite float sentinels (`'NaN'`/`'Infinity'`/`'-Infinity'`) are a
|
|
201
|
+
* **query-path-only** encoding: a non-finite stored float aborts `/export`
|
|
202
|
+
* server-side, so export-loaded data never contains the sentinels (B.6).
|
|
203
|
+
* This module therefore does NOT special-case them.
|
|
204
|
+
*/
|
|
205
|
+
|
|
206
|
+
/** An edge line names an edge type the `.pg` schema does not declare (B.3). */
|
|
207
|
+
declare class UnknownEdgeTypeError extends Error {
|
|
208
|
+
readonly name = "UnknownEdgeTypeError";
|
|
209
|
+
readonly edgeName: string;
|
|
210
|
+
constructor(edgeName: string);
|
|
211
|
+
}
|
|
212
|
+
/** An export line is structurally unusable (e.g. missing/non-string `data.id`). */
|
|
213
|
+
declare class InvalidExportLineError extends Error {
|
|
214
|
+
readonly name = "InvalidExportLineError";
|
|
215
|
+
constructor(message: string);
|
|
216
|
+
}
|
|
217
|
+
interface NodeExportLine {
|
|
218
|
+
kind: 'node';
|
|
219
|
+
type: string;
|
|
220
|
+
data: Record<string, unknown>;
|
|
221
|
+
}
|
|
222
|
+
interface EdgeExportLine {
|
|
223
|
+
kind: 'edge';
|
|
224
|
+
edge: string;
|
|
225
|
+
from: string;
|
|
226
|
+
to: string;
|
|
227
|
+
data: Record<string, unknown>;
|
|
228
|
+
}
|
|
229
|
+
type ClassifiedExportLine = NodeExportLine | EdgeExportLine | {
|
|
230
|
+
kind: 'unknown';
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* Classify one parsed export line per the B.2 shapes:
|
|
234
|
+
* - node line: `{"type": "<NodeType>", "data": {"id", …props}}`
|
|
235
|
+
* - edge line: `{"edge": "<EdgeName>", "from": <src id>, "to": <dst id>, "data": {"id", …props}}`
|
|
236
|
+
* Anything else is `{ kind: 'unknown' }`.
|
|
237
|
+
*/
|
|
238
|
+
declare function classifyExportLine(line: unknown): ClassifiedExportLine;
|
|
239
|
+
/**
|
|
240
|
+
* The adapter's node/edge KIND discriminator key (B.3/B.6).
|
|
241
|
+
*
|
|
242
|
+
* Namespaced on purpose: the adapter injects this field into someone else's
|
|
243
|
+
* data, so it takes the awkward key and leaves the generic word `type` to the
|
|
244
|
+
* schema author, who means something real by it (`Company.type = investor`).
|
|
245
|
+
* A colon is illegal in `.pg` identifiers, so no schema property can ever
|
|
246
|
+
* claim this key — the collision class is closed by construction, and a
|
|
247
|
+
* source-declared `type` now flows through untouched with no preservation
|
|
248
|
+
* mechanism, no warning, and no schema migration. Same convention as
|
|
249
|
+
* GraphQL's `__typename` / JSON-LD's `@type`.
|
|
250
|
+
*/
|
|
251
|
+
declare const ORBIT_TYPE_KEY = "orbit:type";
|
|
252
|
+
/**
|
|
253
|
+
* Normalize a node export line to a `GraphNode`:
|
|
254
|
+
* `id = encodeSourceId(type, data.id)`, `attrs = { …data, 'orbit:type' }`
|
|
255
|
+
* with B.6 value normalization driven by the schema's property types. A node
|
|
256
|
+
* type absent from the schema is tolerated — its attrs pass through verbatim
|
|
257
|
+
* (identity never needs the schema on the node path).
|
|
258
|
+
*/
|
|
259
|
+
declare function normalizeNode(line: {
|
|
260
|
+
type: string;
|
|
261
|
+
data: Record<string, unknown>;
|
|
262
|
+
}, schema: PgSchema): GraphNode;
|
|
263
|
+
/**
|
|
264
|
+
* Normalize an edge export line to a `GraphEdge`:
|
|
265
|
+
* `id = encodeSourceId(edge, data.id)`; `source`/`target` namespace the bare
|
|
266
|
+
* `from`/`to` ids with the endpoint node types resolved from the schema
|
|
267
|
+
* (B.3). Throws {@link UnknownEdgeTypeError} when the schema does not declare
|
|
268
|
+
* the edge — endpoint identity cannot be constructed without it.
|
|
269
|
+
*/
|
|
270
|
+
declare function normalizeEdge(line: {
|
|
271
|
+
edge: string;
|
|
272
|
+
from: string;
|
|
273
|
+
to: string;
|
|
274
|
+
data: Record<string, unknown>;
|
|
275
|
+
}, schema: PgSchema): GraphEdge;
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Public types for the v1 export loader (spec Appendix B.1/B.2/B.8/B.10).
|
|
279
|
+
*
|
|
280
|
+
* The organizing rule of the v1 adapter (B.10): graphs load via `og.export()`;
|
|
281
|
+
* queries only ever resolve ids. These types describe that one load path —
|
|
282
|
+
* its options, its ingestion target seam, and its revision-stamped result.
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
/** Cumulative progress, reported after every appended batch (B.2). */
|
|
286
|
+
interface OmnigraphLoadProgress {
|
|
287
|
+
/** Export lines consumed so far (nodes + edges + skipped unknowns). */
|
|
288
|
+
lines: number;
|
|
289
|
+
/** Node lines normalized so far. */
|
|
290
|
+
nodes: number;
|
|
291
|
+
/** Edge lines normalized so far. */
|
|
292
|
+
edges: number;
|
|
293
|
+
/** Serialized UTF-8 NDJSON bytes consumed so far (including line breaks). */
|
|
294
|
+
bytes: number;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* B.2 revision-stamp drift policy: what to do when the branch head observed
|
|
298
|
+
* after the export stream differs from the head observed before it.
|
|
299
|
+
*
|
|
300
|
+
* - `'reject'` (default): abort the session and throw — the graph is left
|
|
301
|
+
* untouched. The right choice for durable/shareable sessions.
|
|
302
|
+
* - `'accept-warn'`: buffer the export, then commit under the canonical final
|
|
303
|
+
* revision once `headAfter` is known; both heads are recorded in `dataRef`
|
|
304
|
+
* and a warning is added when they differ.
|
|
305
|
+
* - `'retry-once'`: abort, restart the whole load once; a second drift
|
|
306
|
+
* rejects.
|
|
307
|
+
*/
|
|
308
|
+
type OmnigraphDriftPolicy = 'reject' | 'accept-warn' | 'retry-once';
|
|
309
|
+
interface OmnigraphSourceOptions {
|
|
310
|
+
/**
|
|
311
|
+
* A **preconfigured** SDK client. In the browser this must be a safe
|
|
312
|
+
* same-origin or public client — this option surface deliberately accepts
|
|
313
|
+
* no `baseUrl`/`token` pair (B.1): authenticated client construction lives
|
|
314
|
+
* ONLY in `@modernrelay/orbit-omnigraph/server`
|
|
315
|
+
* (`createOmnigraphServerClient`), which is excluded from client bundles.
|
|
316
|
+
*/
|
|
317
|
+
client: Omnigraph;
|
|
318
|
+
/** Cluster graph id; every call is scoped to it via `client.graph(graphId)`. */
|
|
319
|
+
graphId: string;
|
|
320
|
+
/** Branch to export (B.2 — export is branch-only). Default `'main'`. */
|
|
321
|
+
branch?: string;
|
|
322
|
+
/**
|
|
323
|
+
* Partial per-type load (B.10): forwarded as the SDK `ExportInput.typeNames`
|
|
324
|
+
* field (wire form `type_names`). Omit to export every table.
|
|
325
|
+
*/
|
|
326
|
+
typeNames?: readonly string[];
|
|
327
|
+
/** Export lines per `IngestBatch` append. Default 2000. */
|
|
328
|
+
batchSize?: number;
|
|
329
|
+
/**
|
|
330
|
+
* Whole-load byte budget for the atomic replace. Because atomic staging
|
|
331
|
+
* cannot drain before commit, exceeding this finite cap aborts the load
|
|
332
|
+
* without publishing a partial graph. Must be a positive safe integer.
|
|
333
|
+
* Default 64 MiB.
|
|
334
|
+
*/
|
|
335
|
+
maxPendingBytes?: number;
|
|
336
|
+
/** B.2 drift policy. Default `'reject'`. */
|
|
337
|
+
driftPolicy?: OmnigraphDriftPolicy;
|
|
338
|
+
/** Called after every appended batch with cumulative counts. */
|
|
339
|
+
onProgress?: (p: OmnigraphLoadProgress) => void;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* B.8 view-state `dataRef` (v1: branch-based). The readable object behind the
|
|
343
|
+
* canonical `sourceRevision` hash; retained so hosts can display/persist the
|
|
344
|
+
* exact coordinates a session was loaded from. `headBefore !== headAfter`
|
|
345
|
+
* only ever appears under `driftPolicy: 'accept-warn'`.
|
|
346
|
+
*/
|
|
347
|
+
interface OmnigraphDataRef {
|
|
348
|
+
graphId: string;
|
|
349
|
+
branch: string;
|
|
350
|
+
/** Branch head commit id captured before the export stream. */
|
|
351
|
+
headBefore: string;
|
|
352
|
+
/** Branch head commit id captured after the stream, before commit. */
|
|
353
|
+
headAfter: string;
|
|
354
|
+
/** Fingerprint of the `.pg` schema source (see `schemaFingerprint`). */
|
|
355
|
+
schemaFingerprint: string;
|
|
356
|
+
}
|
|
357
|
+
interface OmnigraphLoadCounts {
|
|
358
|
+
lines: number;
|
|
359
|
+
nodes: number;
|
|
360
|
+
edges: number;
|
|
361
|
+
/** Serialized UTF-8 NDJSON bytes streamed (including line breaks). */
|
|
362
|
+
bytes: number;
|
|
363
|
+
}
|
|
364
|
+
interface OmnigraphLoadResult {
|
|
365
|
+
/**
|
|
366
|
+
* The committed source coordinate: the canonical hash of `dataRef` (B.2).
|
|
367
|
+
* Stable across identical replays — a second load of a quiescent branch
|
|
368
|
+
* commits idempotently (§5: same `{datasetKey, sourceRevision}` publishes
|
|
369
|
+
* nothing).
|
|
370
|
+
*/
|
|
371
|
+
sourceRevision: string;
|
|
372
|
+
dataRef: OmnigraphDataRef;
|
|
373
|
+
counts: OmnigraphLoadCounts;
|
|
374
|
+
/** `og.health().version` — the server build the load ran against. */
|
|
375
|
+
serverVersion: string;
|
|
376
|
+
/**
|
|
377
|
+
* Non-fatal observations: SDK/server major.minor mismatch (B.1), accepted
|
|
378
|
+
* drift (B.2), B.6 big-int identity hazards, skipped unknown lines. Never
|
|
379
|
+
* hides a retry or accepted-drift decision.
|
|
380
|
+
*/
|
|
381
|
+
warnings: string[];
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Minimal structural ingestion target (§7.5) — deliberately decoupled from
|
|
385
|
+
* `GraphInstance`. The loader needs exactly the ingest seam and nothing else,
|
|
386
|
+
* so any object with these members works: a real `GraphInstance` (which
|
|
387
|
+
* satisfies this interface structurally), a recorder, or a headless pipeline.
|
|
388
|
+
*/
|
|
389
|
+
interface IngestTarget {
|
|
390
|
+
beginIngest(opts: BeginIngestOptions): IngestSession;
|
|
391
|
+
getRevisions(): Revisions;
|
|
392
|
+
getDiagnostics?(): readonly GraphDiagnostic[];
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* v1 export loader (spec Appendix B.2 / B.8 / B.10).
|
|
397
|
+
*
|
|
398
|
+
* The organizing rule (B.10): graphs load via `og.export()` — one streamed
|
|
399
|
+
* NDJSON pass, edge lines first (lexicographic table-key order), driven
|
|
400
|
+
* straight into a `purpose:'replace'` ingest session on the target. Queries
|
|
401
|
+
* never introduce nodes or edges.
|
|
402
|
+
*
|
|
403
|
+
* Revision stamp (B.2): the canonical `sourceRevision` hashes
|
|
404
|
+
* `{ graphId, branch, headBefore, headAfter, schemaFingerprint }`, but
|
|
405
|
+
* `headAfter` is only knowable after the stream — while core's
|
|
406
|
+
* `BeginIngestOptions` requires `sourceRevision` up front for a replace
|
|
407
|
+
* session. Resolution: under the rejecting/retrying policies the session
|
|
408
|
+
* begins under the PROVISIONAL revision (the canonical hash with
|
|
409
|
+
* `headAfter := headBefore`), the stream appends into it, and `headAfter` is
|
|
410
|
+
* captured BEFORE `commit()`. `accept-warn` is the exception: normalized
|
|
411
|
+
* batches are buffered until `headAfter` is known, then appended once into a
|
|
412
|
+
* session opened with the canonical FINAL revision:
|
|
413
|
+
*
|
|
414
|
+
* - equal heads → provisional === final; commit cleanly. The session only
|
|
415
|
+
* ever commits a revision whose hash is truthful.
|
|
416
|
+
* - drifted heads → `driftPolicy` decides: `'reject'` aborts the session
|
|
417
|
+
* (graph untouched) and throws {@link OmnigraphDriftError};
|
|
418
|
+
* `'accept-warn'` commits the buffered export under the
|
|
419
|
+
* final revision, records BOTH heads in `dataRef`, and
|
|
420
|
+
* adds a warning;
|
|
421
|
+
* `'retry-once'` aborts and restarts the whole load once
|
|
422
|
+
* (a second drift rejects).
|
|
423
|
+
*
|
|
424
|
+
* This is sound because a replace session is atomic and invisible until
|
|
425
|
+
* commit (§7.5): nothing is published under a revision the policy did not
|
|
426
|
+
* explicitly accept.
|
|
427
|
+
*
|
|
428
|
+
* Error surface (B.9): SDK typed errors never cross this package's public
|
|
429
|
+
* surface — they are mapped to plain `Error`s with a stable `omnigraph:`
|
|
430
|
+
* message prefix.
|
|
431
|
+
*/
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* B.2 drift under `driftPolicy: 'reject'` (or a second drift under
|
|
435
|
+
* `'retry-once'`): the branch head moved while the export streamed, the
|
|
436
|
+
* session was aborted, and the target graph is untouched.
|
|
437
|
+
*/
|
|
438
|
+
declare class OmnigraphDriftError extends Error {
|
|
439
|
+
readonly name = "OmnigraphDriftError";
|
|
440
|
+
readonly graphId: string;
|
|
441
|
+
readonly branch: string;
|
|
442
|
+
readonly headBefore: string;
|
|
443
|
+
readonly headAfter: string;
|
|
444
|
+
constructor(graphId: string, branch: string, headBefore: string, headAfter: string);
|
|
445
|
+
}
|
|
446
|
+
/** The one load path a v1 source exposes (B.10). */
|
|
447
|
+
interface OmnigraphSource {
|
|
448
|
+
/**
|
|
449
|
+
* Stream one export of the configured graph/branch into `target` via a
|
|
450
|
+
* `purpose:'replace'` ingest session. Resolves with the revision-stamped
|
|
451
|
+
* result; rejects with the session aborted and the target untouched.
|
|
452
|
+
* `signal` aborts both the HTTP stream and the session.
|
|
453
|
+
*/
|
|
454
|
+
load(target: IngestTarget, signal?: AbortSignal): Promise<OmnigraphLoadResult>;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Create a v1 export-backed data source (B.2/B.10). The client must be
|
|
458
|
+
* preconfigured (B.1): in the browser a safe same-origin or public client —
|
|
459
|
+
* there is deliberately no `baseUrl`/`token` option here. Authenticated
|
|
460
|
+
* construction lives only in `@modernrelay/orbit-omnigraph/server`.
|
|
461
|
+
*/
|
|
462
|
+
declare function createOmnigraphSource(options: OmnigraphSourceOptions): OmnigraphSource;
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* B.7 stored-query `SearchService` (§16.5).
|
|
466
|
+
*
|
|
467
|
+
* A stored query using `bm25`/`fuzzy`/`nearest`/`rrf` with
|
|
468
|
+
* `order { score desc } limit K` returns entity rows plus a score column; this
|
|
469
|
+
* module wires it as a §16.5 `SearchService` via
|
|
470
|
+
* `og.queries.invoke(name, { params, branch })`, passing
|
|
471
|
+
* `RequestContext.signal` through SDK `CallOptions`. Core performs revision
|
|
472
|
+
* admission — the service only declares `revisionDependencies: ['source']`
|
|
473
|
+
* (results come from the server-side branch, so they are invalidated by a
|
|
474
|
+
* source change, never by client-side model/scope drift).
|
|
475
|
+
*
|
|
476
|
+
* Identity (B.3): Omnigraph ids are unique per type only, and a query row
|
|
477
|
+
* carries no type discriminator of its own — so the adapter REQUIRES a
|
|
478
|
+
* caller-supplied column→node-type mapping (`typeOf`), either a
|
|
479
|
+
* `{ column: NodeType }` record keyed by the projection columns that hold
|
|
480
|
+
* bare-variable node structs, or a per-row function. Every returned id is
|
|
481
|
+
* qualified through `encodeSourceId(nodeType, physicalId)` — the same codec
|
|
482
|
+
* every other adapter path uses — so results round-trip `decodeSourceId` and
|
|
483
|
+
* match export-loaded node ids exactly.
|
|
484
|
+
*
|
|
485
|
+
* v1 caveat (B.7): search runs server-side over the WHOLE branch, so against
|
|
486
|
+
* a partial export load it can return ids outside the loaded set. §16.5
|
|
487
|
+
* classifies those as `'not-loaded'` at activation; constrain the stored
|
|
488
|
+
* query to the loaded types, or load the full graph, to avoid the mismatch.
|
|
489
|
+
*
|
|
490
|
+
* Error surface (B.9): SDK typed errors never cross this package's public
|
|
491
|
+
* surface — they rethrow as plain `Error`s with the stable `omnigraph:`
|
|
492
|
+
* prefix. Abort rejections pass through unchanged.
|
|
493
|
+
*/
|
|
494
|
+
|
|
495
|
+
/** One stored-query result row: projection column → value. Bare-variable
|
|
496
|
+
* projections (`return { $s }`) hold whole-node structs including `id`. */
|
|
497
|
+
type OmnigraphSearchRow = Record<string, unknown>;
|
|
498
|
+
/**
|
|
499
|
+
* The required B.3 column→node-type mapping:
|
|
500
|
+
*
|
|
501
|
+
* - a record `{ '$s': 'Signal' }` — the FIRST listed column present in a row
|
|
502
|
+
* with a node struct supplies the physical id, encoded under the mapped
|
|
503
|
+
* type name;
|
|
504
|
+
* - or a per-row function returning the node type name — the row's first
|
|
505
|
+
* node-struct column (row key order) supplies the physical id.
|
|
506
|
+
*/
|
|
507
|
+
type OmnigraphSearchTypeOf = ((row: OmnigraphSearchRow) => string) | Readonly<Record<string, string>>;
|
|
508
|
+
interface OmnigraphSearchServiceOptions<N = Record<string, unknown>> {
|
|
509
|
+
/** A **preconfigured** SDK client (B.1) — no `baseUrl`/`token` here. */
|
|
510
|
+
client: Omnigraph;
|
|
511
|
+
/** Cluster graph id; the invoke is scoped via `client.graph(graphId)`. */
|
|
512
|
+
graphId: string;
|
|
513
|
+
/** Branch the stored query reads (B.7). Default `'main'`. */
|
|
514
|
+
branch?: string;
|
|
515
|
+
/** Registry name of the stored search query (`POST /queries/{name}`).
|
|
516
|
+
* Invoking a known name works whether or not it is `mcp.expose`d. */
|
|
517
|
+
queryName: string;
|
|
518
|
+
/** Builds the stored query's `params` object from the §16.5 call.
|
|
519
|
+
* Default: `(q, limit) => ({ q, limit })`. */
|
|
520
|
+
params?: (q: string, limit: number) => Record<string, unknown>;
|
|
521
|
+
/** REQUIRED B.3 mapping from row to node type — see
|
|
522
|
+
* {@link OmnigraphSearchTypeOf}. */
|
|
523
|
+
typeOf: OmnigraphSearchTypeOf;
|
|
524
|
+
/** Column whose value becomes `label` (String()-coerced when present).
|
|
525
|
+
* Default: the first string-valued column in row key order. */
|
|
526
|
+
labelColumn?: string;
|
|
527
|
+
/** Full custom row→result escape hatch: overrides the default mapping
|
|
528
|
+
* (including `typeOf`/`labelColumn`); return `null` to skip a row. The
|
|
529
|
+
* returned `id` MUST already be B.3-encoded via `encodeSourceId`. */
|
|
530
|
+
mapRow?: (row: OmnigraphSearchRow) => SearchResult<N> | null;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Create the B.7 stored-query search service. Plug it into core as
|
|
534
|
+
* `services.search`; the instance owns `RequestContext` creation,
|
|
535
|
+
* revision-keyed caching, supersede cancellation, and stale-result rejection
|
|
536
|
+
* at admission (§16.5).
|
|
537
|
+
*/
|
|
538
|
+
declare function createOmnigraphSearchService<N = Record<string, unknown>>(options: OmnigraphSearchServiceOptions<N>): SearchService<N>;
|
|
539
|
+
|
|
540
|
+
export { type BigIntKeyWarning, type ClassifiedExportLine, type DecodedSourceId, type EdgeExportLine, type IngestTarget, InvalidExportLineError, type NodeExportLine, ORBIT_TYPE_KEY, type OmnigraphDataRef, OmnigraphDriftError, type OmnigraphDriftPolicy, type OmnigraphLoadCounts, type OmnigraphLoadProgress, type OmnigraphLoadResult, type OmnigraphSearchRow, type OmnigraphSearchServiceOptions, type OmnigraphSearchTypeOf, type OmnigraphSource, type OmnigraphSourceOptions, type PgEdgeType, type PgInterfaceType, type PgNodeType, type PgProperty, type PgScalarName, type PgSchema, type PgType, UnknownEdgeTypeError, bigIntKeyWarnings, classifyExportLine, createOmnigraphSearchService, createOmnigraphSource, decodeSourceId, edgeEndpointTypes, encodeSourceId, encodeSyntheticEdgeId, normalizeEdge, normalizeNode, parsePgSchema, schemaFingerprint };
|