@typicalday/firegraph 0.3.0 → 0.5.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.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Firestore } from '@google-cloud/firestore';
2
- import { G as GraphClientOptions, D as DynamicRegistryConfig, a as DynamicGraphClient, b as GraphClient, R as RegistryEntry, c as DiscoveryResult, d as GraphRegistry, e as GraphReader, f as GraphRecord, F as FindEdgesParams, Q as QueryPlan, g as FindNodesParams, T as TraversalBuilder, h as QueryFilter } from './index-CQkofEC_.cjs';
3
- export { B as BulkBatchError, i as BulkOptions, j as BulkProgress, k as BulkResult, C as CascadeResult, l as CodegenOptions, m as DefineTypeOptions, n as DiscoveredEntity, E as EdgeTopology, o as EdgeTypeData, p as FiregraphConfig, q as GraphBatch, r as GraphTransaction, s as GraphWriter, H as HopDefinition, t as HopResult, N as NodeTypeData, u as QueryMode, v as QueryOptions, S as ScanProtection, w as StoredGraphRecord, x as TraversalOptions, y as TraversalResult, V as ViewContext, z as ViewDefaultsConfig, A as ViewResolverConfig, W as WhereClause, I as defineConfig, J as generateTypes, K as resolveView } from './index-CQkofEC_.cjs';
2
+ import { G as GraphClientOptions, D as DynamicRegistryConfig, a as DynamicGraphClient, b as GraphClient, c as GraphRegistry, R as RegistryEntry, d as DiscoveryResult, e as GraphReader, M as MigrationExecutor, f as GraphRecord, F as FindEdgesParams, Q as QueryPlan, g as FindNodesParams, T as TraversalBuilder, h as MigrationFn, S as StoredMigrationStep, i as MigrationStep, j as StoredGraphRecord, k as MigrationWriteBack, l as QueryFilter } from './index-B9aodfYD.cjs';
3
+ export { B as BulkBatchError, m as BulkOptions, n as BulkProgress, o as BulkResult, C as CascadeResult, p as CodegenOptions, q as DefineTypeOptions, r as DiscoveredEntity, E as EdgeTopology, s as EdgeTypeData, t as FiregraphConfig, u as GraphBatch, v as GraphTransaction, w as GraphWriter, H as HopDefinition, x as HopResult, N as NodeTypeData, y as QueryMode, z as QueryOptions, A as ScanProtection, I as TraversalOptions, J as TraversalResult, V as ViewContext, K as ViewDefaultsConfig, L as ViewResolverConfig, W as WhereClause, O as defineConfig, P as generateTypes, U as resolveView } from './index-B9aodfYD.cjs';
4
4
  export { E as EntityViewConfig, a as EntityViewMeta, V as ViewComponentClass, b as ViewMeta, c as ViewRegistry, d as ViewRegistryInput, e as defineViews } from './views-DL60k0cf.cjs';
5
5
  export { Q as QueryClient, a as QueryClientError, b as QueryClientErrorCode, c as QueryClientOptions } from './client-Bk2Cm6xv.cjs';
6
6
 
@@ -26,6 +26,17 @@ declare function createGraphClient(db: Firestore, collectionPath: string, option
26
26
  * ```
27
27
  */
28
28
  declare function createRegistry(input: RegistryEntry[] | DiscoveryResult): GraphRegistry;
29
+ /**
30
+ * Create a merged registry where `base` entries take priority and `extension`
31
+ * entries fill in gaps. Lookups and validation check `base` first; only if the
32
+ * triple is not found there does the merged registry fall through to
33
+ * `extension`.
34
+ *
35
+ * The `entries()` method returns a deduplicated list (base wins on collision).
36
+ * The `lookupByAxbType()` method merges results from both registries,
37
+ * deduplicating by triple key with base entries winning.
38
+ */
39
+ declare function createMergedRegistry(base: GraphRegistry, extension: GraphRegistry): GraphRegistry;
29
40
 
30
41
  /** The aType used for node type definition meta-nodes. */
31
42
  declare const META_NODE_TYPE = "nodeType";
@@ -57,8 +68,9 @@ declare function generateDeterministicUid(metaType: string, name: string): strin
57
68
  * meta-type entries, so meta-type writes remain validateable after a reload.
58
69
  *
59
70
  * @param reader - A GraphReader pointed at the collection containing meta-nodes.
71
+ * @param executor - Optional custom executor for compiling stored migration source strings.
60
72
  */
61
- declare function createRegistryFromGraph(reader: GraphReader): Promise<GraphRegistry>;
73
+ declare function createRegistryFromGraph(reader: GraphReader, executor?: MigrationExecutor): Promise<GraphRegistry>;
62
74
 
63
75
  declare function generateId(): string;
64
76
 
@@ -116,6 +128,9 @@ declare class QuerySafetyError extends FiregraphError {
116
128
  declare class RegistryScopeError extends FiregraphError {
117
129
  constructor(aType: string, axbType: string, bType: string, scopePath: string, allowedIn: string[]);
118
130
  }
131
+ declare class MigrationError extends FiregraphError {
132
+ constructor(message: string);
133
+ }
119
134
 
120
135
  /**
121
136
  * Entity Discovery — convention-based auto-discovery of entities from
@@ -277,6 +292,162 @@ declare function compileSchema(schema: object, label?: string): (data: unknown)
277
292
  */
278
293
  declare function jsonSchemaToFieldMeta(schema: any): FieldMeta[];
279
294
 
295
+ /**
296
+ * Sandbox module for compiling dynamic registry migration source strings
297
+ * into executable functions.
298
+ *
299
+ * Uses a dedicated worker thread with SES (Secure ECMAScript) Compartments
300
+ * for isolation. SES `lockdown()` and `Compartment` evaluation run in the
301
+ * worker thread so that the host process's intrinsics remain unaffected.
302
+ *
303
+ * Each migration function runs in a hardened compartment with no ambient
304
+ * authority — no access to `process`, `require`, `fetch`, `setTimeout`,
305
+ * or any other host-provided globals. Data crosses the compartment boundary
306
+ * as JSON strings to prevent prototype chain escapes.
307
+ *
308
+ * Static registry migrations are already in-memory functions and never
309
+ * go through this module.
310
+ */
311
+
312
+ /**
313
+ * Default executor using a worker-thread SES Compartment with JSON marshaling.
314
+ *
315
+ * Migration source is compiled and executed inside an isolated SES
316
+ * Compartment running in a dedicated worker thread. The worker calls
317
+ * `lockdown()` in its own V8 isolate, leaving the host process's
318
+ * intrinsics completely unaffected.
319
+ *
320
+ * Data crosses the compartment boundary as JSON strings, preventing
321
+ * prototype chain escapes. The compartment receives only `JSON` as an
322
+ * endowment for parsing/stringifying data.
323
+ *
324
+ * The returned `MigrationFn` always returns a `Promise` (communication
325
+ * with the worker is inherently async via `postMessage`).
326
+ */
327
+ declare function defaultExecutor(source: string): MigrationFn;
328
+ /**
329
+ * Eagerly validate a migration source string by compiling it in the
330
+ * sandbox worker (or via a custom executor) without executing it.
331
+ *
332
+ * Use this to catch syntax errors at define-time or reload-time rather
333
+ * than at first migration execution.
334
+ *
335
+ * @throws {MigrationError} If the source is syntactically invalid or
336
+ * does not produce a function.
337
+ */
338
+ declare function precompileSource(source: string, executor?: MigrationExecutor): Promise<void>;
339
+ /**
340
+ * Compile a stored migration source string into an executable function.
341
+ * Results are cached by SHA-256 hash of the source string so repeated
342
+ * reads never re-parse the same migration.
343
+ *
344
+ * **Important:** When using the default executor, this function does NOT
345
+ * validate the source synchronously — validation is deferred to the
346
+ * worker thread at execution time. Callers that need eager validation
347
+ * (e.g., `defineNodeType`, `reloadRegistry`) should call
348
+ * `precompileSource()` before or alongside `compileMigrationFn()`.
349
+ */
350
+ declare function compileMigrationFn(source: string, executor?: MigrationExecutor): MigrationFn;
351
+ /**
352
+ * Batch compile stored migration steps into executable MigrationStep[].
353
+ *
354
+ * With the default executor, source validation is deferred to execution
355
+ * time. Use `precompileSource()` to validate eagerly — see
356
+ * `createRegistryFromGraph()` for the recommended pattern.
357
+ */
358
+ declare function compileMigrations(stored: StoredMigrationStep[], executor?: MigrationExecutor): MigrationStep[];
359
+ /**
360
+ * Terminate the sandbox worker thread. The worker will be respawned
361
+ * on the next `defaultExecutor` call.
362
+ *
363
+ * Primarily useful for test cleanup to avoid vitest hanging on
364
+ * unfinished worker threads.
365
+ */
366
+ declare function destroySandboxWorker(): Promise<void>;
367
+
368
+ /**
369
+ * Firestore-aware serialization for the sandbox migration pipeline.
370
+ *
371
+ * Firestore documents can contain special types (Timestamp, GeoPoint,
372
+ * VectorValue, DocumentReference) that don't survive plain JSON
373
+ * round-tripping. This module provides tagged serialization: Firestore
374
+ * types are wrapped in tagged plain objects before JSON marshaling and
375
+ * reconstructed after.
376
+ *
377
+ * Only used by the `defaultExecutor` sandbox path. Static migrations
378
+ * (in-memory functions) receive raw Firestore objects directly.
379
+ */
380
+
381
+ /** Sentinel key used to tag serialized Firestore types. */
382
+ declare const SERIALIZATION_TAG: "__firegraph_ser__";
383
+ /** Check if a value is a tagged serialized Firestore type. */
384
+ declare function isTaggedValue(value: unknown): boolean;
385
+ /**
386
+ * Recursively walk a data object and replace Firestore types with tagged
387
+ * plain objects suitable for JSON serialization.
388
+ *
389
+ * Returns a new object tree — the input is never mutated.
390
+ */
391
+ declare function serializeFirestoreTypes(data: Record<string, unknown>): Record<string, unknown>;
392
+ /**
393
+ * Recursively walk a data object and reconstruct Firestore types from
394
+ * tagged plain objects.
395
+ *
396
+ * @param data - The data to deserialize (typically from JSON.parse)
397
+ * @param db - Optional Firestore instance for DocumentReference reconstruction.
398
+ * If not provided, tagged DocumentReferences are left as-is with a one-time warning.
399
+ *
400
+ * Returns a new object tree — the input is never mutated.
401
+ */
402
+ declare function deserializeFirestoreTypes(data: Record<string, unknown>, db?: Firestore): Record<string, unknown>;
403
+
404
+ /**
405
+ * Migration pipeline for auto-migrating records on read.
406
+ *
407
+ * When a record's `v` is behind the version derived from the registry
408
+ * entry's migrations, the pipeline applies migration steps sequentially
409
+ * to bring the data up to the current version.
410
+ */
411
+
412
+ /** Result of attempting to migrate a single record. */
413
+ interface MigrationResult {
414
+ record: StoredGraphRecord;
415
+ migrated: boolean;
416
+ /** Resolved write-back mode for this record (entry-level > global > 'off'). */
417
+ writeBack: MigrationWriteBack;
418
+ }
419
+ /**
420
+ * Apply a chain of migration steps to transform data from `currentVersion`
421
+ * to `targetVersion`. Throws `MigrationError` if the chain is incomplete
422
+ * or a migration function fails.
423
+ *
424
+ * Returns the migrated data payload only — the caller is responsible for
425
+ * stamping `v` on the record envelope.
426
+ */
427
+ declare function applyMigrationChain(data: Record<string, unknown>, currentVersion: number, targetVersion: number, migrations: MigrationStep[]): Promise<Record<string, unknown>>;
428
+ /**
429
+ * Validate that a migration chain forms a contiguous path from version 0
430
+ * to the highest `toVersion`. Throws `MigrationError` if the chain has
431
+ * gaps or duplicate `fromVersion` values.
432
+ *
433
+ * Called at registry construction time to catch incomplete chains early,
434
+ * rather than at read time when a record is migrated.
435
+ */
436
+ declare function validateMigrationChain(migrations: MigrationStep[], label: string): void;
437
+ /**
438
+ * Attempt to migrate a single record based on its registry entry.
439
+ *
440
+ * Returns the original record unchanged if no migration is needed
441
+ * (no schema version, already at current version, or no migrations defined).
442
+ */
443
+ declare function migrateRecord(record: StoredGraphRecord, registry: GraphRegistry, globalWriteBack?: MigrationWriteBack): Promise<MigrationResult>;
444
+ /**
445
+ * Migrate an array of records, returning all results.
446
+ * If any single migration fails, the entire call rejects — a broken
447
+ * migration function is a bug that should surface immediately.
448
+ */
449
+ declare function migrateRecords(records: StoredGraphRecord[], registry: GraphRegistry, globalWriteBack?: MigrationWriteBack): Promise<MigrationResult[]>;
450
+
280
451
  interface FirestoreIndexField {
281
452
  fieldPath: string;
282
453
  order: 'ASCENDING' | 'DESCENDING';
@@ -336,4 +507,4 @@ declare function analyzeQuerySafety(filters: QueryFilter[]): QuerySafetyResult;
336
507
  */
337
508
  declare const DEFAULT_QUERY_LIMIT = 500;
338
509
 
339
- export { BOOTSTRAP_ENTRIES, DEFAULT_QUERY_LIMIT, type DiscoverResult, DiscoveryError, DiscoveryResult, type DiscoveryWarning, DynamicGraphClient, DynamicRegistryConfig, DynamicRegistryError, EDGE_TYPE_SCHEMA, EdgeNotFoundError, type FieldMeta, FindEdgesParams, FindNodesParams, FiregraphError, type FirestoreIndex, type FirestoreIndexConfig, type FirestoreIndexField, GraphClient, GraphClientOptions, GraphReader, GraphRecord, GraphRegistry, InvalidQueryError, META_EDGE_TYPE, META_NODE_TYPE, NODE_TYPE_SCHEMA, NodeNotFoundError, QueryFilter, QueryPlan, QuerySafetyError, type QuerySafetyResult, RegistryEntry, RegistryScopeError, RegistryViolationError, TraversalBuilder, TraversalError, ValidationError, analyzeQuerySafety, buildEdgeQueryPlan, buildEdgeRecord, buildNodeQueryPlan, buildNodeRecord, compileSchema, computeEdgeDocId, computeNodeDocId, createBootstrapRegistry, createGraphClient, createRegistry, createRegistryFromGraph, createTraversal, discoverEntities, generateDeterministicUid, generateId, generateIndexConfig, isAncestorUid, jsonSchemaToFieldMeta, matchScope, matchScopeAny, resolveAncestorCollection };
510
+ export { BOOTSTRAP_ENTRIES, DEFAULT_QUERY_LIMIT, type DiscoverResult, DiscoveryError, DiscoveryResult, type DiscoveryWarning, DynamicGraphClient, DynamicRegistryConfig, DynamicRegistryError, EDGE_TYPE_SCHEMA, EdgeNotFoundError, type FieldMeta, FindEdgesParams, FindNodesParams, FiregraphError, type FirestoreIndex, type FirestoreIndexConfig, type FirestoreIndexField, GraphClient, GraphClientOptions, GraphReader, GraphRecord, GraphRegistry, InvalidQueryError, META_EDGE_TYPE, META_NODE_TYPE, MigrationError, MigrationExecutor, MigrationFn, type MigrationResult, MigrationStep, MigrationWriteBack, NODE_TYPE_SCHEMA, NodeNotFoundError, QueryFilter, QueryPlan, QuerySafetyError, type QuerySafetyResult, RegistryEntry, RegistryScopeError, RegistryViolationError, SERIALIZATION_TAG, StoredGraphRecord, StoredMigrationStep, TraversalBuilder, TraversalError, ValidationError, analyzeQuerySafety, applyMigrationChain, buildEdgeQueryPlan, buildEdgeRecord, buildNodeQueryPlan, buildNodeRecord, compileMigrationFn, compileMigrations, compileSchema, computeEdgeDocId, computeNodeDocId, createBootstrapRegistry, createGraphClient, createMergedRegistry, createRegistry, createRegistryFromGraph, createTraversal, defaultExecutor, deserializeFirestoreTypes, destroySandboxWorker, discoverEntities, generateDeterministicUid, generateId, generateIndexConfig, isAncestorUid, isTaggedValue, jsonSchemaToFieldMeta, matchScope, matchScopeAny, migrateRecord, migrateRecords, precompileSource, resolveAncestorCollection, serializeFirestoreTypes, validateMigrationChain };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Firestore } from '@google-cloud/firestore';
2
- import { G as GraphClientOptions, D as DynamicRegistryConfig, a as DynamicGraphClient, b as GraphClient, R as RegistryEntry, c as DiscoveryResult, d as GraphRegistry, e as GraphReader, f as GraphRecord, F as FindEdgesParams, Q as QueryPlan, g as FindNodesParams, T as TraversalBuilder, h as QueryFilter } from './index-CQkofEC_.js';
3
- export { B as BulkBatchError, i as BulkOptions, j as BulkProgress, k as BulkResult, C as CascadeResult, l as CodegenOptions, m as DefineTypeOptions, n as DiscoveredEntity, E as EdgeTopology, o as EdgeTypeData, p as FiregraphConfig, q as GraphBatch, r as GraphTransaction, s as GraphWriter, H as HopDefinition, t as HopResult, N as NodeTypeData, u as QueryMode, v as QueryOptions, S as ScanProtection, w as StoredGraphRecord, x as TraversalOptions, y as TraversalResult, V as ViewContext, z as ViewDefaultsConfig, A as ViewResolverConfig, W as WhereClause, I as defineConfig, J as generateTypes, K as resolveView } from './index-CQkofEC_.js';
2
+ import { G as GraphClientOptions, D as DynamicRegistryConfig, a as DynamicGraphClient, b as GraphClient, c as GraphRegistry, R as RegistryEntry, d as DiscoveryResult, e as GraphReader, M as MigrationExecutor, f as GraphRecord, F as FindEdgesParams, Q as QueryPlan, g as FindNodesParams, T as TraversalBuilder, h as MigrationFn, S as StoredMigrationStep, i as MigrationStep, j as StoredGraphRecord, k as MigrationWriteBack, l as QueryFilter } from './index-B9aodfYD.js';
3
+ export { B as BulkBatchError, m as BulkOptions, n as BulkProgress, o as BulkResult, C as CascadeResult, p as CodegenOptions, q as DefineTypeOptions, r as DiscoveredEntity, E as EdgeTopology, s as EdgeTypeData, t as FiregraphConfig, u as GraphBatch, v as GraphTransaction, w as GraphWriter, H as HopDefinition, x as HopResult, N as NodeTypeData, y as QueryMode, z as QueryOptions, A as ScanProtection, I as TraversalOptions, J as TraversalResult, V as ViewContext, K as ViewDefaultsConfig, L as ViewResolverConfig, W as WhereClause, O as defineConfig, P as generateTypes, U as resolveView } from './index-B9aodfYD.js';
4
4
  export { E as EntityViewConfig, a as EntityViewMeta, V as ViewComponentClass, b as ViewMeta, c as ViewRegistry, d as ViewRegistryInput, e as defineViews } from './views-DL60k0cf.js';
5
5
  export { Q as QueryClient, a as QueryClientError, b as QueryClientErrorCode, c as QueryClientOptions } from './client-Bk2Cm6xv.js';
6
6
 
@@ -26,6 +26,17 @@ declare function createGraphClient(db: Firestore, collectionPath: string, option
26
26
  * ```
27
27
  */
28
28
  declare function createRegistry(input: RegistryEntry[] | DiscoveryResult): GraphRegistry;
29
+ /**
30
+ * Create a merged registry where `base` entries take priority and `extension`
31
+ * entries fill in gaps. Lookups and validation check `base` first; only if the
32
+ * triple is not found there does the merged registry fall through to
33
+ * `extension`.
34
+ *
35
+ * The `entries()` method returns a deduplicated list (base wins on collision).
36
+ * The `lookupByAxbType()` method merges results from both registries,
37
+ * deduplicating by triple key with base entries winning.
38
+ */
39
+ declare function createMergedRegistry(base: GraphRegistry, extension: GraphRegistry): GraphRegistry;
29
40
 
30
41
  /** The aType used for node type definition meta-nodes. */
31
42
  declare const META_NODE_TYPE = "nodeType";
@@ -57,8 +68,9 @@ declare function generateDeterministicUid(metaType: string, name: string): strin
57
68
  * meta-type entries, so meta-type writes remain validateable after a reload.
58
69
  *
59
70
  * @param reader - A GraphReader pointed at the collection containing meta-nodes.
71
+ * @param executor - Optional custom executor for compiling stored migration source strings.
60
72
  */
61
- declare function createRegistryFromGraph(reader: GraphReader): Promise<GraphRegistry>;
73
+ declare function createRegistryFromGraph(reader: GraphReader, executor?: MigrationExecutor): Promise<GraphRegistry>;
62
74
 
63
75
  declare function generateId(): string;
64
76
 
@@ -116,6 +128,9 @@ declare class QuerySafetyError extends FiregraphError {
116
128
  declare class RegistryScopeError extends FiregraphError {
117
129
  constructor(aType: string, axbType: string, bType: string, scopePath: string, allowedIn: string[]);
118
130
  }
131
+ declare class MigrationError extends FiregraphError {
132
+ constructor(message: string);
133
+ }
119
134
 
120
135
  /**
121
136
  * Entity Discovery — convention-based auto-discovery of entities from
@@ -277,6 +292,162 @@ declare function compileSchema(schema: object, label?: string): (data: unknown)
277
292
  */
278
293
  declare function jsonSchemaToFieldMeta(schema: any): FieldMeta[];
279
294
 
295
+ /**
296
+ * Sandbox module for compiling dynamic registry migration source strings
297
+ * into executable functions.
298
+ *
299
+ * Uses a dedicated worker thread with SES (Secure ECMAScript) Compartments
300
+ * for isolation. SES `lockdown()` and `Compartment` evaluation run in the
301
+ * worker thread so that the host process's intrinsics remain unaffected.
302
+ *
303
+ * Each migration function runs in a hardened compartment with no ambient
304
+ * authority — no access to `process`, `require`, `fetch`, `setTimeout`,
305
+ * or any other host-provided globals. Data crosses the compartment boundary
306
+ * as JSON strings to prevent prototype chain escapes.
307
+ *
308
+ * Static registry migrations are already in-memory functions and never
309
+ * go through this module.
310
+ */
311
+
312
+ /**
313
+ * Default executor using a worker-thread SES Compartment with JSON marshaling.
314
+ *
315
+ * Migration source is compiled and executed inside an isolated SES
316
+ * Compartment running in a dedicated worker thread. The worker calls
317
+ * `lockdown()` in its own V8 isolate, leaving the host process's
318
+ * intrinsics completely unaffected.
319
+ *
320
+ * Data crosses the compartment boundary as JSON strings, preventing
321
+ * prototype chain escapes. The compartment receives only `JSON` as an
322
+ * endowment for parsing/stringifying data.
323
+ *
324
+ * The returned `MigrationFn` always returns a `Promise` (communication
325
+ * with the worker is inherently async via `postMessage`).
326
+ */
327
+ declare function defaultExecutor(source: string): MigrationFn;
328
+ /**
329
+ * Eagerly validate a migration source string by compiling it in the
330
+ * sandbox worker (or via a custom executor) without executing it.
331
+ *
332
+ * Use this to catch syntax errors at define-time or reload-time rather
333
+ * than at first migration execution.
334
+ *
335
+ * @throws {MigrationError} If the source is syntactically invalid or
336
+ * does not produce a function.
337
+ */
338
+ declare function precompileSource(source: string, executor?: MigrationExecutor): Promise<void>;
339
+ /**
340
+ * Compile a stored migration source string into an executable function.
341
+ * Results are cached by SHA-256 hash of the source string so repeated
342
+ * reads never re-parse the same migration.
343
+ *
344
+ * **Important:** When using the default executor, this function does NOT
345
+ * validate the source synchronously — validation is deferred to the
346
+ * worker thread at execution time. Callers that need eager validation
347
+ * (e.g., `defineNodeType`, `reloadRegistry`) should call
348
+ * `precompileSource()` before or alongside `compileMigrationFn()`.
349
+ */
350
+ declare function compileMigrationFn(source: string, executor?: MigrationExecutor): MigrationFn;
351
+ /**
352
+ * Batch compile stored migration steps into executable MigrationStep[].
353
+ *
354
+ * With the default executor, source validation is deferred to execution
355
+ * time. Use `precompileSource()` to validate eagerly — see
356
+ * `createRegistryFromGraph()` for the recommended pattern.
357
+ */
358
+ declare function compileMigrations(stored: StoredMigrationStep[], executor?: MigrationExecutor): MigrationStep[];
359
+ /**
360
+ * Terminate the sandbox worker thread. The worker will be respawned
361
+ * on the next `defaultExecutor` call.
362
+ *
363
+ * Primarily useful for test cleanup to avoid vitest hanging on
364
+ * unfinished worker threads.
365
+ */
366
+ declare function destroySandboxWorker(): Promise<void>;
367
+
368
+ /**
369
+ * Firestore-aware serialization for the sandbox migration pipeline.
370
+ *
371
+ * Firestore documents can contain special types (Timestamp, GeoPoint,
372
+ * VectorValue, DocumentReference) that don't survive plain JSON
373
+ * round-tripping. This module provides tagged serialization: Firestore
374
+ * types are wrapped in tagged plain objects before JSON marshaling and
375
+ * reconstructed after.
376
+ *
377
+ * Only used by the `defaultExecutor` sandbox path. Static migrations
378
+ * (in-memory functions) receive raw Firestore objects directly.
379
+ */
380
+
381
+ /** Sentinel key used to tag serialized Firestore types. */
382
+ declare const SERIALIZATION_TAG: "__firegraph_ser__";
383
+ /** Check if a value is a tagged serialized Firestore type. */
384
+ declare function isTaggedValue(value: unknown): boolean;
385
+ /**
386
+ * Recursively walk a data object and replace Firestore types with tagged
387
+ * plain objects suitable for JSON serialization.
388
+ *
389
+ * Returns a new object tree — the input is never mutated.
390
+ */
391
+ declare function serializeFirestoreTypes(data: Record<string, unknown>): Record<string, unknown>;
392
+ /**
393
+ * Recursively walk a data object and reconstruct Firestore types from
394
+ * tagged plain objects.
395
+ *
396
+ * @param data - The data to deserialize (typically from JSON.parse)
397
+ * @param db - Optional Firestore instance for DocumentReference reconstruction.
398
+ * If not provided, tagged DocumentReferences are left as-is with a one-time warning.
399
+ *
400
+ * Returns a new object tree — the input is never mutated.
401
+ */
402
+ declare function deserializeFirestoreTypes(data: Record<string, unknown>, db?: Firestore): Record<string, unknown>;
403
+
404
+ /**
405
+ * Migration pipeline for auto-migrating records on read.
406
+ *
407
+ * When a record's `v` is behind the version derived from the registry
408
+ * entry's migrations, the pipeline applies migration steps sequentially
409
+ * to bring the data up to the current version.
410
+ */
411
+
412
+ /** Result of attempting to migrate a single record. */
413
+ interface MigrationResult {
414
+ record: StoredGraphRecord;
415
+ migrated: boolean;
416
+ /** Resolved write-back mode for this record (entry-level > global > 'off'). */
417
+ writeBack: MigrationWriteBack;
418
+ }
419
+ /**
420
+ * Apply a chain of migration steps to transform data from `currentVersion`
421
+ * to `targetVersion`. Throws `MigrationError` if the chain is incomplete
422
+ * or a migration function fails.
423
+ *
424
+ * Returns the migrated data payload only — the caller is responsible for
425
+ * stamping `v` on the record envelope.
426
+ */
427
+ declare function applyMigrationChain(data: Record<string, unknown>, currentVersion: number, targetVersion: number, migrations: MigrationStep[]): Promise<Record<string, unknown>>;
428
+ /**
429
+ * Validate that a migration chain forms a contiguous path from version 0
430
+ * to the highest `toVersion`. Throws `MigrationError` if the chain has
431
+ * gaps or duplicate `fromVersion` values.
432
+ *
433
+ * Called at registry construction time to catch incomplete chains early,
434
+ * rather than at read time when a record is migrated.
435
+ */
436
+ declare function validateMigrationChain(migrations: MigrationStep[], label: string): void;
437
+ /**
438
+ * Attempt to migrate a single record based on its registry entry.
439
+ *
440
+ * Returns the original record unchanged if no migration is needed
441
+ * (no schema version, already at current version, or no migrations defined).
442
+ */
443
+ declare function migrateRecord(record: StoredGraphRecord, registry: GraphRegistry, globalWriteBack?: MigrationWriteBack): Promise<MigrationResult>;
444
+ /**
445
+ * Migrate an array of records, returning all results.
446
+ * If any single migration fails, the entire call rejects — a broken
447
+ * migration function is a bug that should surface immediately.
448
+ */
449
+ declare function migrateRecords(records: StoredGraphRecord[], registry: GraphRegistry, globalWriteBack?: MigrationWriteBack): Promise<MigrationResult[]>;
450
+
280
451
  interface FirestoreIndexField {
281
452
  fieldPath: string;
282
453
  order: 'ASCENDING' | 'DESCENDING';
@@ -336,4 +507,4 @@ declare function analyzeQuerySafety(filters: QueryFilter[]): QuerySafetyResult;
336
507
  */
337
508
  declare const DEFAULT_QUERY_LIMIT = 500;
338
509
 
339
- export { BOOTSTRAP_ENTRIES, DEFAULT_QUERY_LIMIT, type DiscoverResult, DiscoveryError, DiscoveryResult, type DiscoveryWarning, DynamicGraphClient, DynamicRegistryConfig, DynamicRegistryError, EDGE_TYPE_SCHEMA, EdgeNotFoundError, type FieldMeta, FindEdgesParams, FindNodesParams, FiregraphError, type FirestoreIndex, type FirestoreIndexConfig, type FirestoreIndexField, GraphClient, GraphClientOptions, GraphReader, GraphRecord, GraphRegistry, InvalidQueryError, META_EDGE_TYPE, META_NODE_TYPE, NODE_TYPE_SCHEMA, NodeNotFoundError, QueryFilter, QueryPlan, QuerySafetyError, type QuerySafetyResult, RegistryEntry, RegistryScopeError, RegistryViolationError, TraversalBuilder, TraversalError, ValidationError, analyzeQuerySafety, buildEdgeQueryPlan, buildEdgeRecord, buildNodeQueryPlan, buildNodeRecord, compileSchema, computeEdgeDocId, computeNodeDocId, createBootstrapRegistry, createGraphClient, createRegistry, createRegistryFromGraph, createTraversal, discoverEntities, generateDeterministicUid, generateId, generateIndexConfig, isAncestorUid, jsonSchemaToFieldMeta, matchScope, matchScopeAny, resolveAncestorCollection };
510
+ export { BOOTSTRAP_ENTRIES, DEFAULT_QUERY_LIMIT, type DiscoverResult, DiscoveryError, DiscoveryResult, type DiscoveryWarning, DynamicGraphClient, DynamicRegistryConfig, DynamicRegistryError, EDGE_TYPE_SCHEMA, EdgeNotFoundError, type FieldMeta, FindEdgesParams, FindNodesParams, FiregraphError, type FirestoreIndex, type FirestoreIndexConfig, type FirestoreIndexField, GraphClient, GraphClientOptions, GraphReader, GraphRecord, GraphRegistry, InvalidQueryError, META_EDGE_TYPE, META_NODE_TYPE, MigrationError, MigrationExecutor, MigrationFn, type MigrationResult, MigrationStep, MigrationWriteBack, NODE_TYPE_SCHEMA, NodeNotFoundError, QueryFilter, QueryPlan, QuerySafetyError, type QuerySafetyResult, RegistryEntry, RegistryScopeError, RegistryViolationError, SERIALIZATION_TAG, StoredGraphRecord, StoredMigrationStep, TraversalBuilder, TraversalError, ValidationError, analyzeQuerySafety, applyMigrationChain, buildEdgeQueryPlan, buildEdgeRecord, buildNodeQueryPlan, buildNodeRecord, compileMigrationFn, compileMigrations, compileSchema, computeEdgeDocId, computeNodeDocId, createBootstrapRegistry, createGraphClient, createMergedRegistry, createRegistry, createRegistryFromGraph, createTraversal, defaultExecutor, deserializeFirestoreTypes, destroySandboxWorker, discoverEntities, generateDeterministicUid, generateId, generateIndexConfig, isAncestorUid, isTaggedValue, jsonSchemaToFieldMeta, matchScope, matchScopeAny, migrateRecord, migrateRecords, precompileSource, resolveAncestorCollection, serializeFirestoreTypes, validateMigrationChain };