@modernrelay/orbit-omnigraph 0.18.0 → 0.19.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/dist/index.d.ts CHANGED
@@ -24,8 +24,8 @@ interface DecodedSourceId {
24
24
  /**
25
25
  * Encode a `(kind, sourceId)` pair as a collision-proof orbit id.
26
26
  *
27
- * - Nodes: `encodeSourceId(NodeType, data.id)`
28
- * - Edges: `encodeSourceId(EdgeName, data.id)`; endpoints use
27
+ * - Nodes: `encodeSourceId(NodeType, id)` using the top-level export id
28
+ * - Edges: `encodeSourceId(EdgeName, id)` using the top-level export id; endpoints use
29
29
  * `encodeSourceId(endpointType, from|to)`.
30
30
  */
31
31
  declare function encodeSourceId(kind: string, sourceId: string): string;
@@ -166,10 +166,10 @@ interface BigIntKeyWarning {
166
166
  property: string;
167
167
  }
168
168
  /**
169
- * Find `I64`/`U64` properties used as identity (`@key` or named `id`). The
169
+ * Find `I64`/`U64` properties used as schema keys (`@key`). The
170
170
  * HTTP path emits native JSON numbers even past ±2^53, where `JSON.parse`
171
- * silently rounds them, so two distinct big-int ids can collapse. Surface
172
- * these hazards before loading.
171
+ * silently rounds them. Physical entity ids are separate strings and stay
172
+ * exact; warn that key attributes themselves may lose precision.
173
173
  */
174
174
  declare function bigIntKeyWarnings(schema: PgSchema): BigIntKeyWarning[];
175
175
 
@@ -185,22 +185,19 @@ declare function bigIntKeyWarnings(schema: PgSchema): BigIntKeyWarning[];
185
185
  * a schema's own `type` property passes through as ordinary data,
186
186
  * - edge endpoint types are resolved from the `.pg` schema because edge lines
187
187
  * carry bare `from`/`to` ids,
188
- * - attr values are normalized to the query-path string forms so
189
- * generated types and 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'`)
188
+ * - attr values are normalized for generated types and temporal dimensions:
189
+ * * `Date` — export sends `'YYYY-MM-DD'`; signed years use ISO's six digits
190
+ * * `DateTime` — export sends a UTC string without a timezone suffix →
191
+ * ISO 8601 with explicit UTC (`'YYYY-MM-DDTHH:MM:SS.mmmZ'`)
195
192
  * * `Blob` — inline internal blobs arrive as `'base64:<data>'` →
196
193
  * `'data:application/octet-stream;base64,<data>'`;
197
194
  * external-URI refs pass through verbatim
198
- * * everything else — verbatim.
195
+ * * missing nullable schema properties — explicit `null`
196
+ * * everything else — verbatim. Physical identity is top-level `id`;
197
+ * `data.id`, when present, is an ordinary user property.
199
198
  *
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.
203
- * This module therefore does NOT special-case them.
199
+ * The server rejects non-finite stored floats during export. Computed
200
+ * non-finite query values render as null; neither path uses string sentinels.
204
201
  */
205
202
 
206
203
  /** An edge line names an edge type the `.pg` schema does not declare. */
@@ -209,7 +206,7 @@ declare class UnknownEdgeTypeError extends Error {
209
206
  readonly edgeName: string;
210
207
  constructor(edgeName: string);
211
208
  }
212
- /** An export line is structurally unusable (e.g. missing/non-string `data.id`). */
209
+ /** An export line is structurally unusable (e.g. missing/non-string `id`). */
213
210
  declare class InvalidExportLineError extends Error {
214
211
  readonly name = "InvalidExportLineError";
215
212
  constructor(message: string);
@@ -217,11 +214,13 @@ declare class InvalidExportLineError extends Error {
217
214
  interface NodeExportLine {
218
215
  kind: 'node';
219
216
  type: string;
217
+ id: string;
220
218
  data: Record<string, unknown>;
221
219
  }
222
220
  interface EdgeExportLine {
223
221
  kind: 'edge';
224
222
  edge: string;
223
+ id: string;
225
224
  from: string;
226
225
  to: string;
227
226
  data: Record<string, unknown>;
@@ -231,9 +230,10 @@ type ClassifiedExportLine = NodeExportLine | EdgeExportLine | {
231
230
  };
232
231
  /**
233
232
  * Classify one parsed export line using the adapter's wire 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' }`.
233
+ * - node line: `{"type": "<NodeType>", "id": <id>, "data": {…props}}`
234
+ * - edge line: `{"edge": "<EdgeName>", "id": <id>, "from": <src id>, "to": <dst id>, "data": {…props}}`
235
+ * Unknown envelopes return `{ kind: 'unknown' }`. Recognized entities without
236
+ * a physical identity reject instead of falling back to a user property.
237
237
  */
238
238
  declare function classifyExportLine(line: unknown): ClassifiedExportLine;
239
239
  /**
@@ -251,24 +251,26 @@ declare function classifyExportLine(line: unknown): ClassifiedExportLine;
251
251
  declare const ORBIT_TYPE_KEY = "orbit:type";
252
252
  /**
253
253
  * Normalize a node export line to a `GraphNode`:
254
- * `id = encodeSourceId(type, data.id)`, `attrs = { …data, 'orbit:type' }`
254
+ * `id = encodeSourceId(type, id)`, `attrs = { …data, 'orbit:type' }`
255
255
  * with value normalization driven by the schema's property types. A node type
256
256
  * absent from the schema is tolerated — its attrs pass through verbatim
257
257
  * (identity never needs the schema on the node path).
258
258
  */
259
259
  declare function normalizeNode(line: {
260
260
  type: string;
261
+ id: string;
261
262
  data: Record<string, unknown>;
262
263
  }, schema: PgSchema): GraphNode;
263
264
  /**
264
265
  * Normalize an edge export line to a `GraphEdge`:
265
- * `id = encodeSourceId(edge, data.id)`; `source`/`target` namespace the bare
266
+ * `id = encodeSourceId(edge, id)`; `source`/`target` namespace the bare
266
267
  * `from`/`to` ids with the endpoint node types resolved from the schema.
267
268
  * Throws {@link UnknownEdgeTypeError} when the schema does not declare
268
269
  * the edge — endpoint identity cannot be constructed without it.
269
270
  */
270
271
  declare function normalizeEdge(line: {
271
272
  edge: string;
273
+ id: string;
272
274
  from: string;
273
275
  to: string;
274
276
  data: Record<string, unknown>;
@@ -381,8 +383,9 @@ interface OmnigraphLoadResult {
381
383
  serverVersion: string;
382
384
  /**
383
385
  * Non-fatal observations: SDK/server major.minor mismatch, accepted
384
- * drift, big-int identity hazards, and skipped unknown lines. Never
385
- * hides a retry or accepted-drift decision.
386
+ * drift, big-int key attribute precision hazards, and skipped unknown
387
+ * lines. Never hides a retry or accepted-drift decision. HTTP API contract
388
+ * mismatches are fatal errors, not warnings.
386
389
  */
387
390
  warnings: string[];
388
391
  }
@@ -500,12 +503,12 @@ declare function createOmnigraphSource(options: OmnigraphSourceOptions): Omnigra
500
503
  */
501
504
 
502
505
  /** One stored-query result row: projection column → value. Bare-variable
503
- * projections (`return { $s }`) hold whole-node structs including `id`. */
506
+ * projections (`return { $s }`) hold whole-node structs including `@id`. */
504
507
  type OmnigraphSearchRow = Record<string, unknown>;
505
508
  /**
506
509
  * The required column→node-type mapping:
507
510
  *
508
- * - a record `{ '$s': 'Signal' }` — the FIRST listed column present in a row
511
+ * - a record `{ s: 'Signal' }` — the FIRST listed column present in a row
509
512
  * with a node struct supplies the physical id, encoded under the mapped
510
513
  * type name;
511
514
  * - or a per-row function returning the node type name — the row's first
@@ -544,4 +547,5 @@ interface OmnigraphSearchServiceOptions<N = Record<string, unknown>> {
544
547
  */
545
548
  declare function createOmnigraphSearchService<N = Record<string, unknown>>(options: OmnigraphSearchServiceOptions<N>): SearchService<N>;
546
549
 
547
- 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 };
550
+ export { InvalidExportLineError, ORBIT_TYPE_KEY, OmnigraphDriftError, UnknownEdgeTypeError, bigIntKeyWarnings, classifyExportLine, createOmnigraphSearchService, createOmnigraphSource, decodeSourceId, edgeEndpointTypes, encodeSourceId, encodeSyntheticEdgeId, normalizeEdge, normalizeNode, parsePgSchema, schemaFingerprint };
551
+ export type { BigIntKeyWarning, ClassifiedExportLine, DecodedSourceId, EdgeExportLine, IngestTarget, NodeExportLine, OmnigraphDataRef, OmnigraphDriftPolicy, OmnigraphLoadCounts, OmnigraphLoadProgress, OmnigraphLoadResult, OmnigraphSearchRow, OmnigraphSearchServiceOptions, OmnigraphSearchTypeOf, OmnigraphSource, OmnigraphSourceOptions, PgEdgeType, PgInterfaceType, PgNodeType, PgProperty, PgScalarName, PgSchema, PgType };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { encodeSourceId, parsePgSchema, schemaFingerprint, bigIntKeyWarnings, classifyExportLine, normalizeNode, normalizeEdge } from './chunk-PPUJ64QF.js';
2
- export { InvalidExportLineError, ORBIT_TYPE_KEY, UnknownEdgeTypeError, bigIntKeyWarnings, classifyExportLine, decodeSourceId, edgeEndpointTypes, encodeSourceId, encodeSyntheticEdgeId, normalizeEdge, normalizeNode, parsePgSchema, schemaFingerprint } from './chunk-PPUJ64QF.js';
1
+ import { encodeSourceId, parsePgSchema, schemaFingerprint, bigIntKeyWarnings, classifyExportLine, normalizeNode, normalizeEdge } from './chunk-TFBKN675.js';
2
+ export { InvalidExportLineError, ORBIT_TYPE_KEY, UnknownEdgeTypeError, bigIntKeyWarnings, classifyExportLine, decodeSourceId, edgeEndpointTypes, encodeSourceId, encodeSyntheticEdgeId, normalizeEdge, normalizeNode, parsePgSchema, schemaFingerprint } from './chunk-TFBKN675.js';
3
3
  import { SERVER_VERSION, OmnigraphError } from '@modernrelay/omnigraph';
4
4
  import { OrbitOperationError } from '@modernrelay/orbit-core';
5
5
 
@@ -57,7 +57,8 @@ function throwIfAborted(signal) {
57
57
  function isAbortError(err) {
58
58
  return err instanceof Error && err.name === "AbortError";
59
59
  }
60
- function mapError(err) {
60
+ function mapError(err, signal) {
61
+ throwIfAborted(signal);
61
62
  if (err instanceof OmnigraphError && !isAbortError(err)) {
62
63
  return new Error(`omnigraph: ${err.name} (status ${err.status}): ${err.message}`);
63
64
  }
@@ -85,14 +86,13 @@ function createOmnigraphSource(options) {
85
86
  const client = options.client.graph(graphId);
86
87
  const datasetKey = typeNames === void 0 ? `og:${graphId}:${branch}` : `og:${graphId}:${branch}:types=${typeNames.join(",")}`;
87
88
  async function newestHead(signal) {
88
- const commits = await client.commits.list({ branch }, callOpts(signal));
89
- const newest = commits[0];
90
- if (newest === void 0) {
89
+ const { headCommitId } = await client.commits.list({ branch, limit: 1 }, callOpts(signal));
90
+ if (headCommitId == null) {
91
91
  throw new Error(
92
92
  `omnigraph: branch '${branch}' of graph '${graphId}' has no commits \u2014 nothing to export`
93
93
  );
94
94
  }
95
- return newest.graphCommitId;
95
+ return headCommitId;
96
96
  }
97
97
  async function runAttempt(target, signal, warnings, attempt) {
98
98
  throwIfAborted(signal);
@@ -104,7 +104,7 @@ function createOmnigraphSource(options) {
104
104
  for (const hazard of bigIntKeyWarnings(schema)) {
105
105
  pushUnique(
106
106
  warnings,
107
- `omnigraph: ${hazard.type}.${hazard.property} is a 64-bit integer used as identity \u2014 JSON parsing silently rounds values past \xB12^53, which can collapse distinct ids`
107
+ `omnigraph: ${hazard.type}.${hazard.property} is a 64-bit integer schema key \u2014 JSON parsing silently rounds attribute values past \xB12^53; physical ids remain exact strings`
108
108
  );
109
109
  }
110
110
  const provisionalRef = {
@@ -279,7 +279,7 @@ function createOmnigraphSource(options) {
279
279
  } catch {
280
280
  }
281
281
  }
282
- throw mapError(err);
282
+ throw mapError(err, signal);
283
283
  } finally {
284
284
  try {
285
285
  await iterator.return?.();
@@ -293,7 +293,7 @@ function createOmnigraphSource(options) {
293
293
  try {
294
294
  serverVersion = (await client.health(callOpts(signal))).version;
295
295
  } catch (err) {
296
- throw mapError(err);
296
+ throw mapError(err, signal);
297
297
  }
298
298
  const server = majorMinor(serverVersion);
299
299
  const sdk = majorMinor(SERVER_VERSION);
@@ -307,7 +307,7 @@ function createOmnigraphSource(options) {
307
307
  try {
308
308
  outcome = await runAttempt(target, signal, warnings, attempt);
309
309
  } catch (err) {
310
- throw mapError(err);
310
+ throw mapError(err, signal);
311
311
  }
312
312
  if (outcome.kind === "retry") continue;
313
313
  return {
@@ -342,7 +342,7 @@ function mapError2(err) {
342
342
  return err;
343
343
  }
344
344
  function isNodeStruct(value) {
345
- return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.id === "string";
345
+ return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value["@id"] === "string";
346
346
  }
347
347
  function extractRows(response, queryName) {
348
348
  const rows = response.rows;
@@ -370,15 +370,15 @@ function resolveIdentity(row, typeOf, queryName) {
370
370
  }
371
371
  for (const key of Object.keys(row)) {
372
372
  const value = row[key];
373
- if (isNodeStruct(value)) return { kind, sourceId: value.id };
373
+ if (isNodeStruct(value)) return { kind, sourceId: value["@id"] };
374
374
  }
375
375
  throw new Error(
376
- `omnigraph: '${queryName}' search row has no node-struct column (an object with a string 'id') \u2014 project the matched entity bare (return { $s }) so its physical id is available`
376
+ `omnigraph: '${queryName}' search row has no node-struct column (an object with a string '@id') \u2014 project the matched entity bare (return { $s }) so its physical id is available`
377
377
  );
378
378
  }
379
379
  for (const [column, kind] of Object.entries(typeOf)) {
380
380
  const value = row[column];
381
- if (isNodeStruct(value)) return { kind, sourceId: value.id };
381
+ if (isNodeStruct(value)) return { kind, sourceId: value["@id"] };
382
382
  }
383
383
  throw new Error(
384
384
  `omnigraph: '${queryName}' search row has no node struct under the mapped column(s) ${JSON.stringify(Object.keys(typeOf))} \u2014 the typeOf record must key the columns that contain bare-variable node projections`
@@ -420,6 +420,7 @@ function createOmnigraphSearchService(options) {
420
420
  try {
421
421
  response = await client.queries.invoke(queryName, input, { signal: ctx.signal });
422
422
  } catch (err) {
423
+ throwIfAborted2(ctx.signal, queryName);
423
424
  throw mapError2(err);
424
425
  }
425
426
  throwIfAborted2(ctx.signal, queryName);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/loader.ts","../src/searchService.ts"],"names":["activeSession","throwIfAborted","isAbortError","mapError","OmnigraphError"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * v1 export loader.\n *\n * The organizing rule: graphs load via `og.export` — one streamed\n * NDJSON pass, edge lines first (lexicographic table-key order), driven\n * straight into a `purpose:'replace'` ingest session on the target. Queries\n * never introduce nodes or edges.\n *\n * Revision stamp: the canonical `sourceRevision` hashes\n * `{ graphId, branch, headBefore, headAfter, schemaFingerprint }` (plus the\n * sorted `typeNames` subset when the export is partial), but\n * `headAfter` is only knowable after the stream — while core's\n * `BeginIngestOptions` requires `sourceRevision` up front for a replace\n * session. Resolution: under the rejecting/retrying policies the session\n * begins under the PROVISIONAL revision (the canonical hash with\n * `headAfter:= headBefore`), the stream appends into it, and `headAfter` is\n * captured BEFORE `commit`. `accept-warn` is the exception: normalized\n * batches are buffered until `headAfter` is known, then appended once into a\n * session opened with the canonical FINAL revision:\n *\n * - equal heads → provisional === final; commit cleanly. The session only\n * ever commits a revision whose hash is truthful.\n * - drifted heads → `driftPolicy` decides: `'reject'` aborts the session\n * (graph untouched) and throws {@link OmnigraphDriftError};\n * `'accept-warn'` commits the buffered export under the\n * final revision, records BOTH heads in `dataRef`, and\n * adds a warning;\n * `'retry-once'` aborts and restarts the whole load once\n * (a second drift rejects).\n *\n * This is sound because a replace session is atomic and invisible until\n * commit: nothing is published under a revision the policy did not\n * explicitly accept.\n *\n * Error surface: SDK typed errors never cross this package's public\n * surface — they are mapped to plain `Error`s with a stable `omnigraph:`\n * message prefix.\n */\n\nimport { OmnigraphError, SERVER_VERSION } from '@modernrelay/omnigraph';\nimport type { CallOptions, ExportInput, Omnigraph } from '@modernrelay/omnigraph';\nimport { OrbitOperationError } from '@modernrelay/orbit-core';\nimport type { GraphEdge, GraphNode, IngestBatch, IngestSession } from '@modernrelay/orbit-core';\n\nimport { classifyExportLine, normalizeEdge, normalizeNode } from './normalize';\nimport { bigIntKeyWarnings, parsePgSchema, schemaFingerprint } from './pgSchema';\nimport type { PgSchema } from './pgSchema';\nimport type {\n IngestTarget,\n OmnigraphDataRef,\n OmnigraphLoadResult,\n OmnigraphSourceOptions,\n} from './types';\n\nconst DEFAULT_BATCH_SIZE = 2000;\n\n/**\n * Finite whole-export cap for the necessarily atomic replace session. A\n * whole-graph load stages EVERY row before commit, so this is a total-load\n * memory bound, not a backpressure window — real graphs routinely exceed\n * 100 MB of serialized rows (the intel fixture streams ~128 MB), so the\n * default is deliberately generous; callers with tighter memory budgets pass\n * `maxPendingBytes` explicitly.\n */\nconst DEFAULT_MAX_PENDING_BYTES = 512 * 1024 * 1024;\n\n/** Stateless and safe to reuse; counts serialized UTF-8 rather than UTF-16 code units. */\nconst UTF8_ENCODER = new TextEncoder();\n\n/**\n * Raised when a branch moves during export and the configured drift policy\n * rejects the load. The session is aborted and the target graph is untouched.\n */\nexport class OmnigraphDriftError extends Error {\n override readonly name = 'OmnigraphDriftError';\n readonly graphId: string;\n readonly branch: string;\n readonly headBefore: string;\n readonly headAfter: string;\n constructor(graphId: string, branch: string, headBefore: string, headAfter: string) {\n super(\n `omnigraph: branch '${branch}' of graph '${graphId}' changed during export ` +\n `(head ${headBefore} → ${headAfter}); session aborted per driftPolicy (` +\n `service:omnigraph-source-changed-during-export)`,\n );\n this.graphId = graphId;\n this.branch = branch;\n this.headBefore = headBefore;\n this.headAfter = headAfter;\n }\n}\n\n/** The one load path a v1 source exposes. */\nexport interface OmnigraphSource {\n /**\n * Stream one export of the configured graph/branch into `target` via a\n * `purpose:'replace'` ingest session. Resolves with the revision-stamped\n * result; rejects with the session aborted and the target untouched.\n * `signal` aborts both the HTTP stream and the session.\n */\n load(target: IngestTarget, signal?: AbortSignal): Promise<OmnigraphLoadResult>;\n}\n\n// ---------------------------------------------------------------------------\n// Small pure helpers\n// ---------------------------------------------------------------------------\n\n/** FNV-1a 64-bit over the UTF-8 bytes of `s`, as 16 lowercase hex chars. */\nfunction hash64(s: string): string {\n const MASK64 = 0xffffffffffffffffn;\n let h = 0xcbf29ce484222325n;\n for (const b of new TextEncoder().encode(s)) {\n h ^= BigInt(b);\n h = (h * 0x100000001b3n) & MASK64;\n }\n return h.toString(16).padStart(16, '0');\n}\n\n/**\n * The canonical adapter source revision: a hash of the readable `dataRef` object\n * `{ graphId, branch, headBefore, headAfter, schemaFingerprint, typeNames? }`\n * (`dataRef` itself retains the readable form).\n */\nfunction canonicalSourceRevision(ref: OmnigraphDataRef): string {\n // typeNames joins the tuple ONLY when present, so full-export\n // hashes stay byte-identical to every previously persisted revision.\n const tuple: unknown[] = [\n ref.graphId,\n ref.branch,\n ref.headBefore,\n ref.headAfter,\n ref.schemaFingerprint,\n ];\n if (ref.typeNames !== undefined) tuple.push(ref.typeNames);\n return `og:${hash64(JSON.stringify(tuple))}`;\n}\n\n/** `'0.8.1'` → `'0.8'`; null when unparseable. */\nfunction majorMinor(version: string): string | null {\n const m = /^(\\d+)\\.(\\d+)/.exec(version);\n return m ? `${m[1]}.${m[2]}` : null;\n}\n\n/** CallOptions without an explicit-undefined signal (exactOptionalPropertyTypes). */\nfunction callOpts(signal: AbortSignal | undefined): CallOptions {\n return signal ? { signal } : {};\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new DOMException('omnigraph: load aborted by caller signal', 'AbortError');\n }\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof Error && err.name === 'AbortError';\n}\n\n/**\n * SDK typed errors (`NetworkError`, `ConflictError`, …) never leak across the\n * public surface; they rethrow as plain `Error`s with a stable prefix.\n * Abort rejections and this package's own errors pass through unchanged.\n */\nfunction mapError(err: unknown): unknown {\n if (err instanceof OmnigraphError && !isAbortError(err)) {\n return new Error(`omnigraph: ${err.name} (status ${err.status}): ${err.message}`);\n }\n return err;\n}\n\nfunction pushUnique(warnings: string[], warning: string): void {\n if (!warnings.includes(warning)) warnings.push(warning);\n}\n\n// ---------------------------------------------------------------------------\n// createOmnigraphSource\n// ---------------------------------------------------------------------------\n\ninterface AttemptSuccess {\n kind: 'done';\n sourceRevision: string;\n dataRef: OmnigraphDataRef;\n counts: { lines: number; nodes: number; edges: number; bytes: number };\n}\n\ninterface AttemptRetry {\n kind: 'retry';\n}\n\n/**\n * Create a v1 export-backed data source. The client must be\n * preconfigured. In the browser, use a safe same-origin or public client;\n * there is deliberately no `baseUrl`/`token` option here. Authenticated\n * construction lives only in `@modernrelay/orbit-omnigraph/server`.\n */\nexport function createOmnigraphSource(options: OmnigraphSourceOptions): OmnigraphSource {\n const graphId = options.graphId;\n const branch = options.branch ?? 'main';\n const batchSize =\n options.batchSize === undefined ? DEFAULT_BATCH_SIZE : options.batchSize;\n if (!Number.isSafeInteger(batchSize) || batchSize <= 0) {\n throw new TypeError('createOmnigraphSource: batchSize must be a positive safe integer');\n }\n const maxPendingBytes =\n options.maxPendingBytes === undefined ? DEFAULT_MAX_PENDING_BYTES : options.maxPendingBytes;\n if (!Number.isSafeInteger(maxPendingBytes) || maxPendingBytes <= 0) {\n throw new TypeError(\n 'createOmnigraphSource: maxPendingBytes must be a positive safe integer',\n );\n }\n const driftPolicy = options.driftPolicy ?? 'reject';\n const onProgress = options.onProgress;\n // Sorted canonical form: ['B','A'] and ['A','B'] are the SAME subset and\n // must produce the same identity coordinate.\n const typeNames =\n options.typeNames === undefined ? undefined : [...options.typeNames].sort();\n /** Every call is scoped to the graph (SDK cluster routing). */\n const client: Omnigraph = options.client.graph(graphId);\n // A partial export is a DIFFERENT dataset lifetime than the full graph;\n // positions, selection, and history must not carry across subsets.\n const datasetKey =\n typeNames === undefined\n ? `og:${graphId}:${branch}`\n : `og:${graphId}:${branch}:types=${typeNames.join(',')}`;\n\n async function newestHead(signal: AbortSignal | undefined): Promise<string> {\n const commits = await client.commits.list({ branch }, callOpts(signal));\n const newest = commits[0]; // SDK: most recent first\n if (newest === undefined) {\n throw new Error(\n `omnigraph: branch '${branch}' of graph '${graphId}' has no commits — nothing to export`,\n );\n }\n return newest.graphCommitId;\n }\n\n async function runAttempt(\n target: IngestTarget,\n signal: AbortSignal | undefined,\n warnings: string[],\n attempt: number,\n ): Promise<AttemptSuccess | AttemptRetry> {\n throwIfAborted(signal);\n // Pin the target's SOURCE lineage before any remote work: a competing\n // replace/snapshot landing mid-stream must fail the load. Overlay-only\n // model advances are benign for a replace commit (it supersedes overlays\n // anyway), so the CAS base itself is read fresh at each beginIngest\n // pinning it here made long accept-warn streams fail late (and livelock)\n // under unrelated concurrent overlay traffic.\n const baseSource = target.getRevisions().source;\n\n // The before/after head bracket must enclose BOTH the schema read and the\n // export. Otherwise a schema migration between schema.get and the first\n // head sample could look quiescent while we normalize with stale types.\n const headBefore = await newestHead(signal);\n\n // Endpoint-type resolution + wire-type normalization + the fingerprint\n // half of the revision stamp.\n const schemaSource = (await client.schema.get(callOpts(signal))).schemaSource;\n const schema: PgSchema = parsePgSchema(schemaSource);\n const fingerprint = schemaFingerprint(schemaSource);\n for (const hazard of bigIntKeyWarnings(schema)) {\n pushUnique(\n warnings,\n `omnigraph: ${hazard.type}.${hazard.property} is a 64-bit integer used as identity — ` +\n `JSON parsing silently rounds values past ±2^53, which can collapse distinct ids`,\n );\n }\n // NOTE: a schema-declared `type` property needs no warning — the\n // adapter's discriminator lives at the namespaced ORBIT_TYPE_KEY, so the\n // source's own `type` loads as ordinary data with nothing to report.\n\n const provisionalRef: OmnigraphDataRef = {\n graphId,\n branch,\n headBefore,\n headAfter: headBefore, // provisional: assume quiescence, verify after the stream\n schemaFingerprint: fingerprint,\n ...(typeNames !== undefined ? { typeNames } : {}),\n };\n const provisionalRevision = canonicalSourceRevision(provisionalRef);\n\n function beginSession(sourceRevision: string): IngestSession {\n const now = target.getRevisions();\n if (now.source !== baseSource) {\n throw new Error(\n `omnigraph: the target's source lineage changed while the load was streaming ` +\n `(a competing replace or snapshot landed); aborting instead of overwriting it`,\n );\n }\n return target.beginIngest({\n purpose: 'replace',\n datasetKey,\n sourceRevision,\n baseModelRevision: now.model,\n maxPendingBytes,\n });\n }\n\n // `accept-warn` cannot open a truthful session until headAfter is known.\n // Buffer only that opt-in policy; rejecting/retrying loads keep streaming\n // directly into the atomic target under the provisional revision.\n let session: IngestSession | undefined =\n driftPolicy === 'accept-warn' ? undefined : beginSession(provisionalRevision);\n const requestId = hash64(`${datasetKey}|${provisionalRevision}|${attempt}`);\n\n interface BufferedBatch {\n nodes: GraphNode[];\n edges: GraphEdge[];\n bytes: number;\n progress: { lines: number; nodes: number; edges: number; bytes: number };\n }\n const bufferedBatches: Array<BufferedBatch | undefined> | undefined =\n driftPolicy === 'accept-warn' ? [] : undefined;\n\n let lines = 0;\n let nodeCount = 0;\n let edgeCount = 0;\n let bytes = 0;\n let unknown = 0;\n let sequence = 0;\n let pendingNodes: GraphNode[] = [];\n let pendingEdges: GraphEdge[] = [];\n let pendingBytes = 0;\n let acceptedBytes = 0;\n\n /**\n * Replace ingestion is atomic, so neither core staging nor accept-warn's\n * adapter buffer can drain before commit. Enforce the same finite\n * whole-load budget before retaining the next normalized row.\n */\n function accountAcceptedBytes(lineBytes: number): void {\n const next = acceptedBytes + lineBytes;\n if (next > maxPendingBytes) {\n throw new OrbitOperationError(\n { code: 'queue-overflow', queuedBytes: next, limit: maxPendingBytes },\n `omnigraph: export rows require at least ${next} bytes, exceeding ` +\n `maxPendingBytes ${maxPendingBytes}; load aborted before commit`,\n );\n }\n acceptedBytes = next;\n pendingBytes += lineBytes;\n }\n\n /** Await every append; retain bounded adapter-side pending batches. */\n async function flush(): Promise<void> {\n if (pendingNodes.length === 0 && pendingEdges.length === 0) return;\n const nodes = pendingNodes;\n const edges = pendingEdges;\n const batchBytes = pendingBytes;\n const progress = { lines, nodes: nodeCount, edges: edgeCount, bytes };\n pendingNodes = [];\n pendingEdges = [];\n pendingBytes = 0;\n\n if (bufferedBatches !== undefined) {\n bufferedBatches.push({ nodes, edges, bytes: batchBytes, progress });\n return;\n }\n\n const activeSession = session;\n if (activeSession === undefined) throw new Error('omnigraph: internal missing ingest session');\n const batch: IngestBatch = {\n sequence,\n batchId: `og:${requestId}:${sequence}`,\n bytes: batchBytes,\n };\n if (edges.length > 0) batch.edges = edges;\n if (nodes.length > 0) batch.nodes = nodes;\n sequence += 1;\n await activeSession.append(batch);\n onProgress?.(progress);\n }\n\n /** Commit buffered accept-warn rows once, under the now-known final revision. */\n async function commitBuffered(sourceRevision: string): Promise<void> {\n if (bufferedBatches === undefined) {\n throw new Error('omnigraph: internal missing accept-warn batch buffer');\n }\n const finalSession = beginSession(sourceRevision);\n session = finalSession;\n const finalRequestId = hash64(`${datasetKey}|${sourceRevision}|${attempt}`);\n for (let i = 0; i < bufferedBatches.length; i++) {\n throwIfAborted(signal);\n const buffered = bufferedBatches[i];\n if (buffered === undefined) continue;\n // Release the buffer's array slot as soon as ownership passes to the\n // target session; the local `buffered` reference dies this iteration.\n bufferedBatches[i] = undefined;\n const batch: IngestBatch = {\n sequence: i,\n batchId: `og:${finalRequestId}:${i}`,\n bytes: buffered.bytes,\n };\n if (buffered.edges.length > 0) batch.edges = buffered.edges;\n if (buffered.nodes.length > 0) batch.nodes = buffered.nodes;\n await finalSession.append(batch);\n onProgress?.(buffered.progress);\n }\n bufferedBatches.length = 0;\n throwIfAborted(signal);\n await finalSession.commit();\n }\n\n // Bind the iterator ONCE and\n // make sure early exits cancel the underlying stream via `return`.\n const exportInput: ExportInput = { branch, ...(typeNames !== undefined ? { typeNames } : {}) };\n const iterator = client\n .export<Record<string, unknown>>(exportInput, callOpts(signal))\n [Symbol.asyncIterator]();\n\n try {\n for (;;) {\n throwIfAborted(signal);\n const step = await iterator.next();\n if (step.done === true) break;\n const line = step.value;\n lines += 1;\n // The SDK exposes parsed rows rather than raw chunks. Re-serialize to\n // UTF-8 and include one NDJSON newline: a conservative, consistent\n // accounting unit for progress, batches, and the whole-load cap.\n const lineBytes = UTF8_ENCODER.encode(JSON.stringify(line)).byteLength + 1;\n bytes += lineBytes;\n const classified = classifyExportLine(line);\n if (classified.kind === 'node') {\n const node = normalizeNode(classified, schema);\n accountAcceptedBytes(lineBytes);\n pendingNodes.push(node);\n nodeCount += 1;\n } else if (classified.kind === 'edge') {\n const edge = normalizeEdge(classified, schema);\n accountAcceptedBytes(lineBytes);\n pendingEdges.push(edge);\n edgeCount += 1;\n } else {\n unknown += 1;\n }\n if (pendingNodes.length + pendingEdges.length >= batchSize) await flush();\n }\n await flush();\n\n if (unknown > 0) {\n pushUnique(warnings, `omnigraph: skipped ${unknown} unrecognized export line(s)`);\n }\n\n // Revision stamp, second half: the head AFTER the stream, captured\n // BEFORE commit.\n throwIfAborted(signal);\n const headAfter = await newestHead(signal);\n throwIfAborted(signal);\n const counts = { lines, nodes: nodeCount, edges: edgeCount, bytes };\n\n if (driftPolicy === 'accept-warn') {\n const finalRef: OmnigraphDataRef = { ...provisionalRef, headAfter };\n const finalRevision = canonicalSourceRevision(finalRef);\n if (headAfter !== headBefore) {\n pushUnique(\n warnings,\n `omnigraph: branch '${branch}' advanced during export (head ${headBefore} → ` +\n `${headAfter}); committed under the canonical final revision per ` +\n `driftPolicy:'accept-warn' — dataRef records both heads`,\n );\n }\n await commitBuffered(finalRevision);\n return { kind: 'done', sourceRevision: finalRevision, dataRef: finalRef, counts };\n }\n\n if (headAfter === headBefore) {\n const activeSession = session;\n if (activeSession === undefined) throw new Error('omnigraph: internal missing ingest session');\n await activeSession.commit();\n return { kind: 'done', sourceRevision: provisionalRevision, dataRef: provisionalRef, counts };\n }\n\n // Branch drift maps to service:omnigraph-source-changed-during-export.\n const activeSession = session;\n if (activeSession === undefined) throw new Error('omnigraph: internal missing ingest session');\n await activeSession.abort('omnigraph: source changed during export');\n if (driftPolicy === 'retry-once' && attempt === 1) {\n pushUnique(\n warnings,\n `omnigraph: branch '${branch}' advanced during export (head ${headBefore} → ` +\n `${headAfter}); load restarted once per driftPolicy:'retry-once'`,\n );\n return { kind: 'retry' };\n }\n throw new OmnigraphDriftError(graphId, branch, headBefore, headAfter);\n } catch (err) {\n if (session?.state === 'open') {\n try {\n await session.abort(err);\n } catch {\n // the original failure wins\n }\n }\n throw mapError(err);\n } finally {\n // Cancel the underlying NDJSON stream on any non-exhausted exit.\n try {\n await iterator.return?.();\n } catch {\n // stream teardown must never mask the outcome\n }\n }\n }\n\n async function load(target: IngestTarget, signal?: AbortSignal): Promise<OmnigraphLoadResult> {\n const warnings: string[] = [];\n\n // Surface an SDK/server major.minor mismatch as a warning, never a hard\n // failure.\n let serverVersion: string;\n try {\n serverVersion = (await client.health(callOpts(signal))).version;\n } catch (err) {\n throw mapError(err);\n }\n const server = majorMinor(serverVersion);\n const sdk = majorMinor(SERVER_VERSION);\n if (server === null || server !== sdk) {\n warnings.push(\n `omnigraph: server version ${serverVersion} does not match the SDK-pinned server ` +\n `version ${SERVER_VERSION} (major.minor differ) — SDK behavior is undefined ` +\n `against this server`,\n );\n }\n\n for (let attempt = 1; ; attempt += 1) {\n let outcome: AttemptSuccess | AttemptRetry;\n try {\n outcome = await runAttempt(target, signal, warnings, attempt);\n } catch (err) {\n // Covers SDK errors thrown before the session/stream phase\n // (schema.get, commits.list); mapError is a no-op on already-mapped\n // or package-owned errors.\n throw mapError(err);\n }\n if (outcome.kind === 'retry') continue;\n return {\n sourceRevision: outcome.sourceRevision,\n dataRef: outcome.dataRef,\n counts: outcome.counts,\n serverVersion,\n warnings,\n };\n }\n }\n\n return { load };\n}\n","/**\n * Stored-query `SearchService` integration.\n *\n * A stored query using `bm25`/`fuzzy`/`nearest`/`rrf` with\n * `order { score desc } limit K` returns entity rows plus a score column; this\n * module wires it as a `SearchService` via\n * `og.queries.invoke(name, { params, branch })`, passing\n * `RequestContext.signal` through SDK `CallOptions`. Core performs revision\n * admission — the service only declares `revisionDependencies: ['source']`\n * (results come from the server-side branch, so they are invalidated by a\n * source change, never by client-side model/scope drift).\n *\n * Identity: Omnigraph ids are unique per type only, and a query row\n * carries no type discriminator of its own — so the adapter REQUIRES a\n * caller-supplied column→node-type mapping (`typeOf`), either a\n * `{ column: NodeType }` record keyed by the projection columns that hold\n * bare-variable node structs, or a per-row function. Every returned id is\n * qualified through `encodeSourceId(nodeType, physicalId)` — the same codec\n * every other adapter path uses — so results round-trip `decodeSourceId` and\n * match export-loaded node ids exactly.\n *\n * Partial-load caveat: search runs server-side over the whole branch, so a\n * partial export load can return ids outside the loaded set.\n * `activateSearchResult` classifies those as `'not-loaded'`; constrain the\n * stored query to the loaded types, or load the full graph, to avoid the\n * mismatch.\n *\n * Error surface: SDK typed errors never cross this package's public\n * surface — they rethrow as plain `Error`s with the stable `omnigraph:`\n * prefix. Abort rejections pass through unchanged.\n */\n\nimport { OmnigraphError } from '@modernrelay/omnigraph';\nimport type { InvokeQueryInput, Omnigraph } from '@modernrelay/omnigraph';\nimport type { RequestContext, SearchResult, SearchService } from '@modernrelay/orbit-core';\n\nimport { encodeSourceId } from './idCodec';\n\n/** One stored-query result row: projection column → value. Bare-variable\n * projections (`return { $s }`) hold whole-node structs including `id`. */\nexport type OmnigraphSearchRow = Record<string, unknown>;\n\n/**\n * The required column→node-type mapping:\n *\n * - a record `{ '$s': 'Signal' }` — the FIRST listed column present in a row\n * with a node struct supplies the physical id, encoded under the mapped\n * type name;\n * - or a per-row function returning the node type name — the row's first\n * node-struct column (row key order) supplies the physical id.\n */\nexport type OmnigraphSearchTypeOf =\n | ((row: OmnigraphSearchRow) => string)\n | Readonly<Record<string, string>>;\n\nexport interface OmnigraphSearchServiceOptions<N = Record<string, unknown>> {\n /** A **preconfigured** SDK client — no `baseUrl`/`token` here. */\n client: Omnigraph;\n /** Cluster graph id; the invoke is scoped via `client.graph(graphId)`. */\n graphId: string;\n /** Branch the stored query reads. Default `'main'`. */\n branch?: string;\n /** Registry name of the stored search query (`POST /queries/{name}`).\n * Invoking a known name works whether or not it is `mcp.expose`d. */\n queryName: string;\n /** Builds the stored query's `params` object from the call.\n * Default: `(q, limit) => ({ q, limit })`. */\n params?: (q: string, limit: number) => Record<string, unknown>;\n /** REQUIRED mapping from row to node type — see\n * {@link OmnigraphSearchTypeOf}. */\n typeOf: OmnigraphSearchTypeOf;\n /** Column whose value becomes `label` (String-coerced when present).\n * Default: the first string-valued column in row key order. */\n labelColumn?: string;\n /** Full custom row→result escape hatch: overrides the default mapping\n * (including `typeOf`/`labelColumn`); return `null` to skip a row. The\n * returned `id` MUST already be type-qualified via `encodeSourceId`. */\n mapRow?: (row: OmnigraphSearchRow) => SearchResult<N> | null;\n}\n\n// ---------------------------------------------------------------------------\n// Small pure helpers\n// ---------------------------------------------------------------------------\n\nfunction defaultParams(q: string, limit: number): Record<string, unknown> {\n return { q, limit };\n}\n\nfunction throwIfAborted(signal: AbortSignal, queryName: string): void {\n if (signal.aborted) {\n throw new DOMException(\n `omnigraph: search query '${queryName}' aborted by request signal`,\n 'AbortError',\n );\n }\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof Error && err.name === 'AbortError';\n}\n\n/** SDK typed errors rethrow as plain prefixed `Error`s; abort rejections\n * and everything else pass through unchanged. */\nfunction mapError(err: unknown): unknown {\n if (err instanceof OmnigraphError && !isAbortError(err)) {\n return new Error(`omnigraph: ${err.name} (status ${err.status}): ${err.message}`);\n }\n return err;\n}\n\n/** A bare-variable projection value: a whole-node struct carrying its\n * physical id (`return { $s }` yields `{ id,...props }`). */\nfunction isNodeStruct(value: unknown): value is { id: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n typeof (value as { id?: unknown }).id === 'string'\n );\n}\n\n/** The invoke response must be a READ envelope with tabular rows — a stored\n * mutation (Change envelope) or malformed body is a hard error. */\nfunction extractRows(response: unknown, queryName: string): readonly OmnigraphSearchRow[] {\n const rows = (response as { rows?: unknown }).rows;\n if (!Array.isArray(rows)) {\n throw new Error(\n `omnigraph: stored query '${queryName}' did not return a read envelope with rows — ` +\n `the configured search query must be a stored READ query (not a mutation)`,\n );\n }\n for (const row of rows) {\n if (typeof row !== 'object' || row === null || Array.isArray(row)) {\n throw new Error(\n `omnigraph: stored query '${queryName}' returned a non-object row — ` +\n `expected column→value row objects`,\n );\n }\n }\n return rows as OmnigraphSearchRow[];\n}\n\ninterface ResolvedIdentity {\n kind: string;\n sourceId: string;\n}\n\n/** Resolve the `(nodeType, physicalId)` pair for one row via `typeOf`. */\nfunction resolveIdentity(\n row: OmnigraphSearchRow,\n typeOf: OmnigraphSearchTypeOf,\n queryName: string,\n): ResolvedIdentity {\n if (typeof typeOf === 'function') {\n const kind = typeOf(row);\n if (typeof kind !== 'string' || kind.length === 0) {\n throw new Error(\n `omnigraph: typeOf returned ${JSON.stringify(kind)} for a '${queryName}' search row — ` +\n `typeOf must return a non-empty node type name`,\n );\n }\n for (const key of Object.keys(row)) {\n const value = row[key];\n if (isNodeStruct(value)) return { kind, sourceId: value.id };\n }\n throw new Error(\n `omnigraph: '${queryName}' search row has no node-struct column (an object with a ` +\n `string 'id') — project the matched entity bare (return { $s }) so its physical ` +\n `id is available`,\n );\n }\n for (const [column, kind] of Object.entries(typeOf)) {\n const value = row[column];\n if (isNodeStruct(value)) return { kind, sourceId: value.id };\n }\n throw new Error(\n `omnigraph: '${queryName}' search row has no node struct under the mapped column(s) ` +\n `${JSON.stringify(Object.keys(typeOf))} — the typeOf record must key the ` +\n `columns that contain bare-variable node projections`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// createOmnigraphSearchService\n// ---------------------------------------------------------------------------\n\n/**\n * Create the stored-query search service. Plug it into core as\n * `services.search`; the instance owns `RequestContext` creation,\n * revision-keyed caching, supersede cancellation, and stale-result rejection\n * at admission.\n */\nexport function createOmnigraphSearchService<N = Record<string, unknown>>(\n options: OmnigraphSearchServiceOptions<N>,\n): SearchService<N> {\n const { graphId, queryName, typeOf, labelColumn, mapRow } = options;\n const branch = options.branch ?? 'main';\n const buildParams = options.params ?? defaultParams;\n /** Every call is scoped to the graph (SDK cluster routing). */\n const client: Omnigraph = options.client.graph(graphId);\n\n function mapRowDefault(row: OmnigraphSearchRow): SearchResult<N> {\n const { kind, sourceId } = resolveIdentity(row, typeOf, queryName);\n const result: SearchResult<N> = { id: encodeSourceId(kind, sourceId) };\n\n const score = row['score'];\n if (typeof score === 'number' && Number.isFinite(score)) result.score = score;\n\n if (labelColumn !== undefined) {\n const value = row[labelColumn];\n if (typeof value === 'string' || typeof value === 'number') result.label = String(value);\n } else {\n for (const key of Object.keys(row)) {\n if (key === 'score') continue; // the score lane never doubles as a label\n const value = row[key];\n if (typeof value === 'string') {\n result.label = value;\n break;\n }\n }\n }\n return result;\n }\n\n return {\n revisionDependencies: ['source'],\n async search(\n q: string,\n searchOptions: { limit: number },\n ctx: RequestContext,\n ): Promise<readonly SearchResult<N>[]> {\n throwIfAborted(ctx.signal, queryName);\n const limit = Number.isFinite(searchOptions.limit) ? Math.floor(searchOptions.limit) : 0;\n if (q.length === 0 || limit <= 0) return [];\n\n const input: InvokeQueryInput = { branch, params: buildParams(q, limit) };\n let response: unknown;\n try {\n response = await client.queries.invoke(queryName, input, { signal: ctx.signal });\n } catch (err) {\n throw mapError(err);\n }\n throwIfAborted(ctx.signal, queryName);\n\n const rows = extractRows(response, queryName);\n const results: SearchResult<N>[] = [];\n for (const row of rows) {\n if (results.length >= limit) break; // defensive cap — the query owns K\n const mapped = mapRow !== undefined ? mapRow(row) : mapRowDefault(row);\n if (mapped !== null) results.push(mapped);\n }\n return results;\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/loader.ts","../src/searchService.ts"],"names":["activeSession","throwIfAborted","isAbortError","mapError","OmnigraphError"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * v1 export loader.\n *\n * The organizing rule: graphs load via `og.export` — one streamed\n * NDJSON pass, edge lines first (lexicographic table-key order), driven\n * straight into a `purpose:'replace'` ingest session on the target. Queries\n * never introduce nodes or edges.\n *\n * Revision stamp: the canonical `sourceRevision` hashes\n * `{ graphId, branch, headBefore, headAfter, schemaFingerprint }` (plus the\n * sorted `typeNames` subset when the export is partial), but\n * `headAfter` is only knowable after the stream — while core's\n * `BeginIngestOptions` requires `sourceRevision` up front for a replace\n * session. Resolution: under the rejecting/retrying policies the session\n * begins under the PROVISIONAL revision (the canonical hash with\n * `headAfter:= headBefore`), the stream appends into it, and `headAfter` is\n * captured BEFORE `commit`. `accept-warn` is the exception: normalized\n * batches are buffered until `headAfter` is known, then appended once into a\n * session opened with the canonical FINAL revision:\n *\n * - equal heads → provisional === final; commit cleanly. The session only\n * ever commits a revision whose hash is truthful.\n * - drifted heads → `driftPolicy` decides: `'reject'` aborts the session\n * (graph untouched) and throws {@link OmnigraphDriftError};\n * `'accept-warn'` commits the buffered export under the\n * final revision, records BOTH heads in `dataRef`, and\n * adds a warning;\n * `'retry-once'` aborts and restarts the whole load once\n * (a second drift rejects).\n *\n * This is sound because a replace session is atomic and invisible until\n * commit: nothing is published under a revision the policy did not\n * explicitly accept.\n *\n * Error surface: SDK typed errors never cross this package's public\n * surface — they are mapped to plain `Error`s with a stable `omnigraph:`\n * message prefix.\n */\n\nimport { OmnigraphError, SERVER_VERSION } from '@modernrelay/omnigraph';\nimport type { CallOptions, ExportInput, Omnigraph } from '@modernrelay/omnigraph';\nimport { OrbitOperationError } from '@modernrelay/orbit-core';\nimport type { GraphEdge, GraphNode, IngestBatch, IngestSession } from '@modernrelay/orbit-core';\n\nimport { classifyExportLine, normalizeEdge, normalizeNode } from './normalize';\nimport { bigIntKeyWarnings, parsePgSchema, schemaFingerprint } from './pgSchema';\nimport type { PgSchema } from './pgSchema';\nimport type {\n IngestTarget,\n OmnigraphDataRef,\n OmnigraphLoadResult,\n OmnigraphSourceOptions,\n} from './types';\n\nconst DEFAULT_BATCH_SIZE = 2000;\n\n/**\n * Finite whole-export cap for the necessarily atomic replace session. A\n * whole-graph load stages EVERY row before commit, so this is a total-load\n * memory bound, not a backpressure window — real graphs routinely exceed\n * 100 MB of serialized rows (the intel fixture streams ~128 MB), so the\n * default is deliberately generous; callers with tighter memory budgets pass\n * `maxPendingBytes` explicitly.\n */\nconst DEFAULT_MAX_PENDING_BYTES = 512 * 1024 * 1024;\n\n/** Stateless and safe to reuse; counts serialized UTF-8 rather than UTF-16 code units. */\nconst UTF8_ENCODER = new TextEncoder();\n\n/**\n * Raised when a branch moves during export and the configured drift policy\n * rejects the load. The session is aborted and the target graph is untouched.\n */\nexport class OmnigraphDriftError extends Error {\n override readonly name = 'OmnigraphDriftError';\n readonly graphId: string;\n readonly branch: string;\n readonly headBefore: string;\n readonly headAfter: string;\n constructor(graphId: string, branch: string, headBefore: string, headAfter: string) {\n super(\n `omnigraph: branch '${branch}' of graph '${graphId}' changed during export ` +\n `(head ${headBefore} → ${headAfter}); session aborted per driftPolicy (` +\n `service:omnigraph-source-changed-during-export)`,\n );\n this.graphId = graphId;\n this.branch = branch;\n this.headBefore = headBefore;\n this.headAfter = headAfter;\n }\n}\n\n/** The one load path a v1 source exposes. */\nexport interface OmnigraphSource {\n /**\n * Stream one export of the configured graph/branch into `target` via a\n * `purpose:'replace'` ingest session. Resolves with the revision-stamped\n * result; rejects with the session aborted and the target untouched.\n * `signal` aborts both the HTTP stream and the session.\n */\n load(target: IngestTarget, signal?: AbortSignal): Promise<OmnigraphLoadResult>;\n}\n\n// ---------------------------------------------------------------------------\n// Small pure helpers\n// ---------------------------------------------------------------------------\n\n/** FNV-1a 64-bit over the UTF-8 bytes of `s`, as 16 lowercase hex chars. */\nfunction hash64(s: string): string {\n const MASK64 = 0xffffffffffffffffn;\n let h = 0xcbf29ce484222325n;\n for (const b of new TextEncoder().encode(s)) {\n h ^= BigInt(b);\n h = (h * 0x100000001b3n) & MASK64;\n }\n return h.toString(16).padStart(16, '0');\n}\n\n/**\n * The canonical adapter source revision: a hash of the readable `dataRef` object\n * `{ graphId, branch, headBefore, headAfter, schemaFingerprint, typeNames? }`\n * (`dataRef` itself retains the readable form).\n */\nfunction canonicalSourceRevision(ref: OmnigraphDataRef): string {\n // typeNames joins the tuple ONLY when present, so full-export\n // hashes stay byte-identical to every previously persisted revision.\n const tuple: unknown[] = [\n ref.graphId,\n ref.branch,\n ref.headBefore,\n ref.headAfter,\n ref.schemaFingerprint,\n ];\n if (ref.typeNames !== undefined) tuple.push(ref.typeNames);\n return `og:${hash64(JSON.stringify(tuple))}`;\n}\n\n/** `'0.8.1'` → `'0.8'`; null when unparseable. */\nfunction majorMinor(version: string): string | null {\n const m = /^(\\d+)\\.(\\d+)/.exec(version);\n return m ? `${m[1]}.${m[2]}` : null;\n}\n\n/** CallOptions without an explicit-undefined signal (exactOptionalPropertyTypes). */\nfunction callOpts(signal: AbortSignal | undefined): CallOptions {\n return signal ? { signal } : {};\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new DOMException('omnigraph: load aborted by caller signal', 'AbortError');\n }\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof Error && err.name === 'AbortError';\n}\n\n/**\n * SDK typed errors (`NetworkError`, `ConflictError`, …) never leak across the\n * public surface; they rethrow as plain `Error`s with a stable prefix.\n * Abort rejections and this package's own errors pass through unchanged.\n */\nfunction mapError(err: unknown, signal?: AbortSignal): unknown {\n throwIfAborted(signal);\n if (err instanceof OmnigraphError && !isAbortError(err)) {\n return new Error(`omnigraph: ${err.name} (status ${err.status}): ${err.message}`);\n }\n return err;\n}\n\nfunction pushUnique(warnings: string[], warning: string): void {\n if (!warnings.includes(warning)) warnings.push(warning);\n}\n\n// ---------------------------------------------------------------------------\n// createOmnigraphSource\n// ---------------------------------------------------------------------------\n\ninterface AttemptSuccess {\n kind: 'done';\n sourceRevision: string;\n dataRef: OmnigraphDataRef;\n counts: { lines: number; nodes: number; edges: number; bytes: number };\n}\n\ninterface AttemptRetry {\n kind: 'retry';\n}\n\n/**\n * Create a v1 export-backed data source. The client must be\n * preconfigured. In the browser, use a safe same-origin or public client;\n * there is deliberately no `baseUrl`/`token` option here. Authenticated\n * construction lives only in `@modernrelay/orbit-omnigraph/server`.\n */\nexport function createOmnigraphSource(options: OmnigraphSourceOptions): OmnigraphSource {\n const graphId = options.graphId;\n const branch = options.branch ?? 'main';\n const batchSize =\n options.batchSize === undefined ? DEFAULT_BATCH_SIZE : options.batchSize;\n if (!Number.isSafeInteger(batchSize) || batchSize <= 0) {\n throw new TypeError('createOmnigraphSource: batchSize must be a positive safe integer');\n }\n const maxPendingBytes =\n options.maxPendingBytes === undefined ? DEFAULT_MAX_PENDING_BYTES : options.maxPendingBytes;\n if (!Number.isSafeInteger(maxPendingBytes) || maxPendingBytes <= 0) {\n throw new TypeError(\n 'createOmnigraphSource: maxPendingBytes must be a positive safe integer',\n );\n }\n const driftPolicy = options.driftPolicy ?? 'reject';\n const onProgress = options.onProgress;\n // Sorted canonical form: ['B','A'] and ['A','B'] are the SAME subset and\n // must produce the same identity coordinate.\n const typeNames =\n options.typeNames === undefined ? undefined : [...options.typeNames].sort();\n /** Every call is scoped to the graph (SDK cluster routing). */\n const client: Omnigraph = options.client.graph(graphId);\n // A partial export is a DIFFERENT dataset lifetime than the full graph;\n // positions, selection, and history must not carry across subsets.\n const datasetKey =\n typeNames === undefined\n ? `og:${graphId}:${branch}`\n : `og:${graphId}:${branch}:types=${typeNames.join(',')}`;\n\n async function newestHead(signal: AbortSignal | undefined): Promise<string> {\n // A fresh first page captures the current branch head. We only need that\n // coordinate, not the full history or a continuation pinned to an old head.\n const { headCommitId } = await client.commits.list({ branch, limit: 1 }, callOpts(signal));\n if (headCommitId == null) {\n throw new Error(\n `omnigraph: branch '${branch}' of graph '${graphId}' has no commits — nothing to export`,\n );\n }\n return headCommitId;\n }\n\n async function runAttempt(\n target: IngestTarget,\n signal: AbortSignal | undefined,\n warnings: string[],\n attempt: number,\n ): Promise<AttemptSuccess | AttemptRetry> {\n throwIfAborted(signal);\n // Pin the target's SOURCE lineage before any remote work: a competing\n // replace/snapshot landing mid-stream must fail the load. Overlay-only\n // model advances are benign for a replace commit (it supersedes overlays\n // anyway), so the CAS base itself is read fresh at each beginIngest\n // pinning it here made long accept-warn streams fail late (and livelock)\n // under unrelated concurrent overlay traffic.\n const baseSource = target.getRevisions().source;\n\n // The before/after head bracket must enclose BOTH the schema read and the\n // export. Otherwise a schema migration between schema.get and the first\n // head sample could look quiescent while we normalize with stale types.\n const headBefore = await newestHead(signal);\n\n // Endpoint-type resolution + wire-type normalization + the fingerprint\n // half of the revision stamp.\n const schemaSource = (await client.schema.get(callOpts(signal))).schemaSource;\n const schema: PgSchema = parsePgSchema(schemaSource);\n const fingerprint = schemaFingerprint(schemaSource);\n for (const hazard of bigIntKeyWarnings(schema)) {\n pushUnique(\n warnings,\n `omnigraph: ${hazard.type}.${hazard.property} is a 64-bit integer schema key — ` +\n `JSON parsing silently rounds attribute values past ±2^53; physical ids remain exact strings`,\n );\n }\n // NOTE: a schema-declared `type` property needs no warning — the\n // adapter's discriminator lives at the namespaced ORBIT_TYPE_KEY, so the\n // source's own `type` loads as ordinary data with nothing to report.\n\n const provisionalRef: OmnigraphDataRef = {\n graphId,\n branch,\n headBefore,\n headAfter: headBefore, // provisional: assume quiescence, verify after the stream\n schemaFingerprint: fingerprint,\n ...(typeNames !== undefined ? { typeNames } : {}),\n };\n const provisionalRevision = canonicalSourceRevision(provisionalRef);\n\n function beginSession(sourceRevision: string): IngestSession {\n const now = target.getRevisions();\n if (now.source !== baseSource) {\n throw new Error(\n `omnigraph: the target's source lineage changed while the load was streaming ` +\n `(a competing replace or snapshot landed); aborting instead of overwriting it`,\n );\n }\n return target.beginIngest({\n purpose: 'replace',\n datasetKey,\n sourceRevision,\n baseModelRevision: now.model,\n maxPendingBytes,\n });\n }\n\n // `accept-warn` cannot open a truthful session until headAfter is known.\n // Buffer only that opt-in policy; rejecting/retrying loads keep streaming\n // directly into the atomic target under the provisional revision.\n let session: IngestSession | undefined =\n driftPolicy === 'accept-warn' ? undefined : beginSession(provisionalRevision);\n const requestId = hash64(`${datasetKey}|${provisionalRevision}|${attempt}`);\n\n interface BufferedBatch {\n nodes: GraphNode[];\n edges: GraphEdge[];\n bytes: number;\n progress: { lines: number; nodes: number; edges: number; bytes: number };\n }\n const bufferedBatches: Array<BufferedBatch | undefined> | undefined =\n driftPolicy === 'accept-warn' ? [] : undefined;\n\n let lines = 0;\n let nodeCount = 0;\n let edgeCount = 0;\n let bytes = 0;\n let unknown = 0;\n let sequence = 0;\n let pendingNodes: GraphNode[] = [];\n let pendingEdges: GraphEdge[] = [];\n let pendingBytes = 0;\n let acceptedBytes = 0;\n\n /**\n * Replace ingestion is atomic, so neither core staging nor accept-warn's\n * adapter buffer can drain before commit. Enforce the same finite\n * whole-load budget before retaining the next normalized row.\n */\n function accountAcceptedBytes(lineBytes: number): void {\n const next = acceptedBytes + lineBytes;\n if (next > maxPendingBytes) {\n throw new OrbitOperationError(\n { code: 'queue-overflow', queuedBytes: next, limit: maxPendingBytes },\n `omnigraph: export rows require at least ${next} bytes, exceeding ` +\n `maxPendingBytes ${maxPendingBytes}; load aborted before commit`,\n );\n }\n acceptedBytes = next;\n pendingBytes += lineBytes;\n }\n\n /** Await every append; retain bounded adapter-side pending batches. */\n async function flush(): Promise<void> {\n if (pendingNodes.length === 0 && pendingEdges.length === 0) return;\n const nodes = pendingNodes;\n const edges = pendingEdges;\n const batchBytes = pendingBytes;\n const progress = { lines, nodes: nodeCount, edges: edgeCount, bytes };\n pendingNodes = [];\n pendingEdges = [];\n pendingBytes = 0;\n\n if (bufferedBatches !== undefined) {\n bufferedBatches.push({ nodes, edges, bytes: batchBytes, progress });\n return;\n }\n\n const activeSession = session;\n if (activeSession === undefined) throw new Error('omnigraph: internal missing ingest session');\n const batch: IngestBatch = {\n sequence,\n batchId: `og:${requestId}:${sequence}`,\n bytes: batchBytes,\n };\n if (edges.length > 0) batch.edges = edges;\n if (nodes.length > 0) batch.nodes = nodes;\n sequence += 1;\n await activeSession.append(batch);\n onProgress?.(progress);\n }\n\n /** Commit buffered accept-warn rows once, under the now-known final revision. */\n async function commitBuffered(sourceRevision: string): Promise<void> {\n if (bufferedBatches === undefined) {\n throw new Error('omnigraph: internal missing accept-warn batch buffer');\n }\n const finalSession = beginSession(sourceRevision);\n session = finalSession;\n const finalRequestId = hash64(`${datasetKey}|${sourceRevision}|${attempt}`);\n for (let i = 0; i < bufferedBatches.length; i++) {\n throwIfAborted(signal);\n const buffered = bufferedBatches[i];\n if (buffered === undefined) continue;\n // Release the buffer's array slot as soon as ownership passes to the\n // target session; the local `buffered` reference dies this iteration.\n bufferedBatches[i] = undefined;\n const batch: IngestBatch = {\n sequence: i,\n batchId: `og:${finalRequestId}:${i}`,\n bytes: buffered.bytes,\n };\n if (buffered.edges.length > 0) batch.edges = buffered.edges;\n if (buffered.nodes.length > 0) batch.nodes = buffered.nodes;\n await finalSession.append(batch);\n onProgress?.(buffered.progress);\n }\n bufferedBatches.length = 0;\n throwIfAborted(signal);\n await finalSession.commit();\n }\n\n // Bind the iterator ONCE and\n // make sure early exits cancel the underlying stream via `return`.\n const exportInput: ExportInput = { branch, ...(typeNames !== undefined ? { typeNames } : {}) };\n const iterator = client\n .export<Record<string, unknown>>(exportInput, callOpts(signal))\n [Symbol.asyncIterator]();\n\n try {\n for (;;) {\n throwIfAborted(signal);\n const step = await iterator.next();\n if (step.done === true) break;\n const line = step.value;\n lines += 1;\n // The SDK exposes parsed rows rather than raw chunks. Re-serialize to\n // UTF-8 and include one NDJSON newline: a conservative, consistent\n // accounting unit for progress, batches, and the whole-load cap.\n const lineBytes = UTF8_ENCODER.encode(JSON.stringify(line)).byteLength + 1;\n bytes += lineBytes;\n const classified = classifyExportLine(line);\n if (classified.kind === 'node') {\n const node = normalizeNode(classified, schema);\n accountAcceptedBytes(lineBytes);\n pendingNodes.push(node);\n nodeCount += 1;\n } else if (classified.kind === 'edge') {\n const edge = normalizeEdge(classified, schema);\n accountAcceptedBytes(lineBytes);\n pendingEdges.push(edge);\n edgeCount += 1;\n } else {\n unknown += 1;\n }\n if (pendingNodes.length + pendingEdges.length >= batchSize) await flush();\n }\n await flush();\n\n if (unknown > 0) {\n pushUnique(warnings, `omnigraph: skipped ${unknown} unrecognized export line(s)`);\n }\n\n // Revision stamp, second half: the head AFTER the stream, captured\n // BEFORE commit.\n throwIfAborted(signal);\n const headAfter = await newestHead(signal);\n throwIfAborted(signal);\n const counts = { lines, nodes: nodeCount, edges: edgeCount, bytes };\n\n if (driftPolicy === 'accept-warn') {\n const finalRef: OmnigraphDataRef = { ...provisionalRef, headAfter };\n const finalRevision = canonicalSourceRevision(finalRef);\n if (headAfter !== headBefore) {\n pushUnique(\n warnings,\n `omnigraph: branch '${branch}' advanced during export (head ${headBefore} → ` +\n `${headAfter}); committed under the canonical final revision per ` +\n `driftPolicy:'accept-warn' — dataRef records both heads`,\n );\n }\n await commitBuffered(finalRevision);\n return { kind: 'done', sourceRevision: finalRevision, dataRef: finalRef, counts };\n }\n\n if (headAfter === headBefore) {\n const activeSession = session;\n if (activeSession === undefined) throw new Error('omnigraph: internal missing ingest session');\n await activeSession.commit();\n return { kind: 'done', sourceRevision: provisionalRevision, dataRef: provisionalRef, counts };\n }\n\n // Branch drift maps to service:omnigraph-source-changed-during-export.\n const activeSession = session;\n if (activeSession === undefined) throw new Error('omnigraph: internal missing ingest session');\n await activeSession.abort('omnigraph: source changed during export');\n if (driftPolicy === 'retry-once' && attempt === 1) {\n pushUnique(\n warnings,\n `omnigraph: branch '${branch}' advanced during export (head ${headBefore} → ` +\n `${headAfter}); load restarted once per driftPolicy:'retry-once'`,\n );\n return { kind: 'retry' };\n }\n throw new OmnigraphDriftError(graphId, branch, headBefore, headAfter);\n } catch (err) {\n if (session?.state === 'open') {\n try {\n await session.abort(err);\n } catch {\n // the original failure wins\n }\n }\n throw mapError(err, signal);\n } finally {\n // Cancel the underlying NDJSON stream on any non-exhausted exit.\n try {\n await iterator.return?.();\n } catch {\n // stream teardown must never mask the outcome\n }\n }\n }\n\n async function load(target: IngestTarget, signal?: AbortSignal): Promise<OmnigraphLoadResult> {\n const warnings: string[] = [];\n\n // Surface build-version skew as a warning after the SDK verifies the\n // HTTP API contract. Contract mismatches are hard failures.\n let serverVersion: string;\n try {\n serverVersion = (await client.health(callOpts(signal))).version;\n } catch (err) {\n throw mapError(err, signal);\n }\n const server = majorMinor(serverVersion);\n const sdk = majorMinor(SERVER_VERSION);\n if (server === null || server !== sdk) {\n warnings.push(\n `omnigraph: server version ${serverVersion} does not match the SDK-pinned server ` +\n `version ${SERVER_VERSION} (major.minor differ) — SDK behavior is undefined ` +\n `against this server`,\n );\n }\n\n for (let attempt = 1; ; attempt += 1) {\n let outcome: AttemptSuccess | AttemptRetry;\n try {\n outcome = await runAttempt(target, signal, warnings, attempt);\n } catch (err) {\n // Covers SDK errors thrown before the session/stream phase\n // (schema.get, commits.list); mapError is a no-op on already-mapped\n // or package-owned errors.\n throw mapError(err, signal);\n }\n if (outcome.kind === 'retry') continue;\n return {\n sourceRevision: outcome.sourceRevision,\n dataRef: outcome.dataRef,\n counts: outcome.counts,\n serverVersion,\n warnings,\n };\n }\n }\n\n return { load };\n}\n","/**\n * Stored-query `SearchService` integration.\n *\n * A stored query using `bm25`/`fuzzy`/`nearest`/`rrf` with\n * `order { score desc } limit K` returns entity rows plus a score column; this\n * module wires it as a `SearchService` via\n * `og.queries.invoke(name, { params, branch })`, passing\n * `RequestContext.signal` through SDK `CallOptions`. Core performs revision\n * admission — the service only declares `revisionDependencies: ['source']`\n * (results come from the server-side branch, so they are invalidated by a\n * source change, never by client-side model/scope drift).\n *\n * Identity: Omnigraph ids are unique per type only, and a query row\n * carries no type discriminator of its own — so the adapter REQUIRES a\n * caller-supplied column→node-type mapping (`typeOf`), either a\n * `{ column: NodeType }` record keyed by the projection columns that hold\n * bare-variable node structs, or a per-row function. Every returned id is\n * qualified through `encodeSourceId(nodeType, physicalId)` — the same codec\n * every other adapter path uses — so results round-trip `decodeSourceId` and\n * match export-loaded node ids exactly.\n *\n * Partial-load caveat: search runs server-side over the whole branch, so a\n * partial export load can return ids outside the loaded set.\n * `activateSearchResult` classifies those as `'not-loaded'`; constrain the\n * stored query to the loaded types, or load the full graph, to avoid the\n * mismatch.\n *\n * Error surface: SDK typed errors never cross this package's public\n * surface — they rethrow as plain `Error`s with the stable `omnigraph:`\n * prefix. Abort rejections pass through unchanged.\n */\n\nimport { OmnigraphError } from '@modernrelay/omnigraph';\nimport type { InvokeQueryInput, Omnigraph } from '@modernrelay/omnigraph';\nimport type { RequestContext, SearchResult, SearchService } from '@modernrelay/orbit-core';\n\nimport { encodeSourceId } from './idCodec';\n\n/** One stored-query result row: projection column → value. Bare-variable\n * projections (`return { $s }`) hold whole-node structs including `@id`. */\nexport type OmnigraphSearchRow = Record<string, unknown>;\n\n/**\n * The required column→node-type mapping:\n *\n * - a record `{ s: 'Signal' }` — the FIRST listed column present in a row\n * with a node struct supplies the physical id, encoded under the mapped\n * type name;\n * - or a per-row function returning the node type name — the row's first\n * node-struct column (row key order) supplies the physical id.\n */\nexport type OmnigraphSearchTypeOf =\n | ((row: OmnigraphSearchRow) => string)\n | Readonly<Record<string, string>>;\n\nexport interface OmnigraphSearchServiceOptions<N = Record<string, unknown>> {\n /** A **preconfigured** SDK client — no `baseUrl`/`token` here. */\n client: Omnigraph;\n /** Cluster graph id; the invoke is scoped via `client.graph(graphId)`. */\n graphId: string;\n /** Branch the stored query reads. Default `'main'`. */\n branch?: string;\n /** Registry name of the stored search query (`POST /queries/{name}`).\n * Invoking a known name works whether or not it is `mcp.expose`d. */\n queryName: string;\n /** Builds the stored query's `params` object from the call.\n * Default: `(q, limit) => ({ q, limit })`. */\n params?: (q: string, limit: number) => Record<string, unknown>;\n /** REQUIRED mapping from row to node type — see\n * {@link OmnigraphSearchTypeOf}. */\n typeOf: OmnigraphSearchTypeOf;\n /** Column whose value becomes `label` (String-coerced when present).\n * Default: the first string-valued column in row key order. */\n labelColumn?: string;\n /** Full custom row→result escape hatch: overrides the default mapping\n * (including `typeOf`/`labelColumn`); return `null` to skip a row. The\n * returned `id` MUST already be type-qualified via `encodeSourceId`. */\n mapRow?: (row: OmnigraphSearchRow) => SearchResult<N> | null;\n}\n\n// ---------------------------------------------------------------------------\n// Small pure helpers\n// ---------------------------------------------------------------------------\n\nfunction defaultParams(q: string, limit: number): Record<string, unknown> {\n return { q, limit };\n}\n\nfunction throwIfAborted(signal: AbortSignal, queryName: string): void {\n if (signal.aborted) {\n throw new DOMException(\n `omnigraph: search query '${queryName}' aborted by request signal`,\n 'AbortError',\n );\n }\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof Error && err.name === 'AbortError';\n}\n\n/** SDK typed errors rethrow as plain prefixed `Error`s; abort rejections\n * and everything else pass through unchanged. */\nfunction mapError(err: unknown): unknown {\n if (err instanceof OmnigraphError && !isAbortError(err)) {\n return new Error(`omnigraph: ${err.name} (status ${err.status}): ${err.message}`);\n }\n return err;\n}\n\n/** A bare-variable projection value: a whole-node struct carrying its\n * physical id (`return { $s }` yields `s: { '@id': ..., ...props }`). */\nfunction isNodeStruct(value: unknown): value is { '@id': string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n typeof (value as { '@id'?: unknown })['@id'] === 'string'\n );\n}\n\n/** The invoke response must be a READ envelope with tabular rows — a stored\n * mutation (Change envelope) or malformed body is a hard error. */\nfunction extractRows(response: unknown, queryName: string): readonly OmnigraphSearchRow[] {\n const rows = (response as { rows?: unknown }).rows;\n if (!Array.isArray(rows)) {\n throw new Error(\n `omnigraph: stored query '${queryName}' did not return a read envelope with rows — ` +\n `the configured search query must be a stored READ query (not a mutation)`,\n );\n }\n for (const row of rows) {\n if (typeof row !== 'object' || row === null || Array.isArray(row)) {\n throw new Error(\n `omnigraph: stored query '${queryName}' returned a non-object row — ` +\n `expected column→value row objects`,\n );\n }\n }\n return rows as OmnigraphSearchRow[];\n}\n\ninterface ResolvedIdentity {\n kind: string;\n sourceId: string;\n}\n\n/** Resolve the `(nodeType, physicalId)` pair for one row via `typeOf`. */\nfunction resolveIdentity(\n row: OmnigraphSearchRow,\n typeOf: OmnigraphSearchTypeOf,\n queryName: string,\n): ResolvedIdentity {\n if (typeof typeOf === 'function') {\n const kind = typeOf(row);\n if (typeof kind !== 'string' || kind.length === 0) {\n throw new Error(\n `omnigraph: typeOf returned ${JSON.stringify(kind)} for a '${queryName}' search row — ` +\n `typeOf must return a non-empty node type name`,\n );\n }\n for (const key of Object.keys(row)) {\n const value = row[key];\n if (isNodeStruct(value)) return { kind, sourceId: value['@id'] };\n }\n throw new Error(\n `omnigraph: '${queryName}' search row has no node-struct column (an object with a ` +\n `string '@id') — project the matched entity bare (return { $s }) so its physical ` +\n `id is available`,\n );\n }\n for (const [column, kind] of Object.entries(typeOf)) {\n const value = row[column];\n if (isNodeStruct(value)) return { kind, sourceId: value['@id'] };\n }\n throw new Error(\n `omnigraph: '${queryName}' search row has no node struct under the mapped column(s) ` +\n `${JSON.stringify(Object.keys(typeOf))} — the typeOf record must key the ` +\n `columns that contain bare-variable node projections`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// createOmnigraphSearchService\n// ---------------------------------------------------------------------------\n\n/**\n * Create the stored-query search service. Plug it into core as\n * `services.search`; the instance owns `RequestContext` creation,\n * revision-keyed caching, supersede cancellation, and stale-result rejection\n * at admission.\n */\nexport function createOmnigraphSearchService<N = Record<string, unknown>>(\n options: OmnigraphSearchServiceOptions<N>,\n): SearchService<N> {\n const { graphId, queryName, typeOf, labelColumn, mapRow } = options;\n const branch = options.branch ?? 'main';\n const buildParams = options.params ?? defaultParams;\n /** Every call is scoped to the graph (SDK cluster routing). */\n const client: Omnigraph = options.client.graph(graphId);\n\n function mapRowDefault(row: OmnigraphSearchRow): SearchResult<N> {\n const { kind, sourceId } = resolveIdentity(row, typeOf, queryName);\n const result: SearchResult<N> = { id: encodeSourceId(kind, sourceId) };\n\n const score = row['score'];\n if (typeof score === 'number' && Number.isFinite(score)) result.score = score;\n\n if (labelColumn !== undefined) {\n const value = row[labelColumn];\n if (typeof value === 'string' || typeof value === 'number') result.label = String(value);\n } else {\n for (const key of Object.keys(row)) {\n if (key === 'score') continue; // the score lane never doubles as a label\n const value = row[key];\n if (typeof value === 'string') {\n result.label = value;\n break;\n }\n }\n }\n return result;\n }\n\n return {\n revisionDependencies: ['source'],\n async search(\n q: string,\n searchOptions: { limit: number },\n ctx: RequestContext,\n ): Promise<readonly SearchResult<N>[]> {\n throwIfAborted(ctx.signal, queryName);\n const limit = Number.isFinite(searchOptions.limit) ? Math.floor(searchOptions.limit) : 0;\n if (q.length === 0 || limit <= 0) return [];\n\n const input: InvokeQueryInput = { branch, params: buildParams(q, limit) };\n let response: unknown;\n try {\n response = await client.queries.invoke(queryName, input, { signal: ctx.signal });\n } catch (err) {\n // Stored-query POSTs can also mutate, so the SDK reports a dispatched\n // cancellation conservatively. This service's contract is read-only;\n // retain Orbit's AbortError surface when its caller cancelled.\n throwIfAborted(ctx.signal, queryName);\n throw mapError(err);\n }\n throwIfAborted(ctx.signal, queryName);\n\n const rows = extractRows(response, queryName);\n const results: SearchResult<N>[] = [];\n for (const row of rows) {\n if (results.length >= limit) break; // defensive cap — the query owns K\n const mapped = mapRow !== undefined ? mapRow(row) : mapRowDefault(row);\n if (mapped !== null) results.push(mapped);\n }\n return results;\n },\n };\n}\n"]}
package/dist/server.d.ts CHANGED
@@ -5,8 +5,7 @@ import { FetchLike, Omnigraph } from '@modernrelay/omnigraph';
5
5
  *
6
6
  * This module is the ONLY place in the adapter where an authenticated
7
7
  * Omnigraph client is constructed. It must never be imported from browser
8
- * code: `omnigraph-server` ships no CORS configuration and uses static
9
- * bearer tokens (secret material), so browser deployments pass a
8
+ * code: this helper uses a static bearer token (secret material), so browser deployments pass a
10
9
  * preconfigured safe same-origin/public client to `createOmnigraphSource`
11
10
  * instead — typically routing reads through a proxy/BFF. The client-bundle
12
11
  * exclusion gate in `scripts/pack-smoke.mjs` checks the
@@ -29,4 +28,5 @@ interface OmnigraphServerClientOptions {
29
28
  */
30
29
  declare function createOmnigraphServerClient(options: OmnigraphServerClientOptions): Omnigraph;
31
30
 
32
- export { type OmnigraphServerClientOptions, createOmnigraphServerClient };
31
+ export { createOmnigraphServerClient };
32
+ export type { OmnigraphServerClientOptions };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts"],"names":[],"mappings":";;;AA+BO,SAAS,4BAA4B,OAAA,EAAkD;AAC5F,EAAA,MAAM,OAAyB,EAAE,OAAA,EAAS,QAAQ,OAAA,EAAS,KAAA,EAAO,QAAQ,KAAA,EAAM;AAChF,EAAA,IAAI,OAAA,CAAQ,KAAA,KAAU,MAAA,EAAW,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACtD,EAAA,OAAO,IAAI,UAAU,IAAI,CAAA;AAC3B","file":"server.js","sourcesContent":["/**\n * @modernrelay/orbit-omnigraph/server — **SERVER-ONLY** entry.\n *\n * This module is the ONLY place in the adapter where an authenticated\n * Omnigraph client is constructed. It must never be imported from browser\n * code: `omnigraph-server` ships no CORS configuration and uses static\n * bearer tokens (secret material), so browser deployments pass a\n * preconfigured safe same-origin/public client to `createOmnigraphSource`\n * instead — typically routing reads through a proxy/BFF. The client-bundle\n * exclusion gate in `scripts/pack-smoke.mjs` checks the\n * `createOmnigraphServerClient` sentinel and enforces that the browser entry\n * never pulls this module in.\n */\n\nimport { Omnigraph } from '@modernrelay/omnigraph';\nimport type { FetchLike, OmnigraphOptions } from '@modernrelay/omnigraph';\n\nexport interface OmnigraphServerClientOptions {\n /** Base URL of the omnigraph-server, e.g. `http://127.0.0.1:8080`. */\n baseUrl: string;\n /** Static bearer token — secret material; must stay server-side. */\n token: string;\n /** Inject a custom fetch (tracing, agents, testing). */\n fetch?: FetchLike;\n}\n\n/**\n * Construct an authenticated Omnigraph SDK client for server-only use. Pass\n * the result to `createOmnigraphSource({ client,... })` in server code, or\n * hand graph-scoped clones out via `client.graph(id)`.\n */\nexport function createOmnigraphServerClient(options: OmnigraphServerClientOptions): Omnigraph {\n const opts: OmnigraphOptions = { baseUrl: options.baseUrl, token: options.token };\n if (options.fetch !== undefined) opts.fetch = options.fetch;\n return new Omnigraph(opts);\n}\n"]}
1
+ {"version":3,"sources":["../src/server.ts"],"names":[],"mappings":";;;AA8BO,SAAS,4BAA4B,OAAA,EAAkD;AAC5F,EAAA,MAAM,OAAyB,EAAE,OAAA,EAAS,QAAQ,OAAA,EAAS,KAAA,EAAO,QAAQ,KAAA,EAAM;AAChF,EAAA,IAAI,OAAA,CAAQ,KAAA,KAAU,MAAA,EAAW,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACtD,EAAA,OAAO,IAAI,UAAU,IAAI,CAAA;AAC3B","file":"server.js","sourcesContent":["/**\n * @modernrelay/orbit-omnigraph/server — **SERVER-ONLY** entry.\n *\n * This module is the ONLY place in the adapter where an authenticated\n * Omnigraph client is constructed. It must never be imported from browser\n * code: this helper uses a static bearer token (secret material), so browser deployments pass a\n * preconfigured safe same-origin/public client to `createOmnigraphSource`\n * instead — typically routing reads through a proxy/BFF. The client-bundle\n * exclusion gate in `scripts/pack-smoke.mjs` checks the\n * `createOmnigraphServerClient` sentinel and enforces that the browser entry\n * never pulls this module in.\n */\n\nimport { Omnigraph } from '@modernrelay/omnigraph';\nimport type { FetchLike, OmnigraphOptions } from '@modernrelay/omnigraph';\n\nexport interface OmnigraphServerClientOptions {\n /** Base URL of the omnigraph-server, e.g. `http://127.0.0.1:8080`. */\n baseUrl: string;\n /** Static bearer token — secret material; must stay server-side. */\n token: string;\n /** Inject a custom fetch (tracing, agents, testing). */\n fetch?: FetchLike;\n}\n\n/**\n * Construct an authenticated Omnigraph SDK client for server-only use. Pass\n * the result to `createOmnigraphSource({ client,... })` in server code, or\n * hand graph-scoped clones out via `client.graph(id)`.\n */\nexport function createOmnigraphServerClient(options: OmnigraphServerClientOptions): Omnigraph {\n const opts: OmnigraphOptions = { baseUrl: options.baseUrl, token: options.token };\n if (options.fetch !== undefined) opts.fetch = options.fetch;\n return new Omnigraph(opts);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modernrelay/orbit-omnigraph",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "Omnigraph adapter for Orbit: og.export() loader with drift policies, .pg schema parser, and typed codegen.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -9,6 +9,9 @@
9
9
  "directory": "packages/omnigraph"
10
10
  },
11
11
  "type": "module",
12
+ "engines": {
13
+ "node": ">=22"
14
+ },
12
15
  "sideEffects": false,
13
16
  "files": [
14
17
  "dist"
@@ -30,12 +33,13 @@
30
33
  "orbit-omnigraph-codegen": "./dist/codegen-cli.js"
31
34
  },
32
35
  "dependencies": {
33
- "@modernrelay/omnigraph": "0.10.0",
34
- "@modernrelay/orbit-core": "0.18.0"
36
+ "@modernrelay/omnigraph": "0.14.0",
37
+ "@modernrelay/orbit-core": "0.19.0"
35
38
  },
36
39
  "devDependencies": {
37
- "typescript": "^5.6.0",
38
- "vitest": "^3.0.0"
40
+ "typescript": "^7.0.2",
41
+ "vitest": "^5.0.5",
42
+ "@types/node": "^26.6.5"
39
43
  },
40
44
  "scripts": {
41
45
  "build": "tsup",