@typicalday/firegraph 0.3.0 → 0.4.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/README.md +1 -1
- package/dist/codegen/index.d.cts +1 -1
- package/dist/codegen/index.d.ts +1 -1
- package/dist/editor/server/index.mjs +77 -12
- package/dist/{index-CQkofEC_.d.cts → index-DR3jF5_b.d.cts} +11 -2
- package/dist/{index-CQkofEC_.d.ts → index-DR3jF5_b.d.ts} +11 -2
- package/dist/index.cjs +79 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +78 -12
- package/dist/index.js.map +1 -1
- package/package.json +23 -25
package/README.md
CHANGED
|
@@ -340,7 +340,7 @@ Key behaviors:
|
|
|
340
340
|
- **After `reloadRegistry()`**: Domain writes are validated against the compiled registry. Unknown types are always rejected.
|
|
341
341
|
- **Upsert semantics**: Calling `defineNodeType('tour', ...)` twice overwrites the previous definition. After reloading, the latest schema is used.
|
|
342
342
|
- **Separate collection**: Meta-nodes can be stored in a different collection via `registryMode: { mode: 'dynamic', collection: 'meta' }`.
|
|
343
|
-
- **
|
|
343
|
+
- **Merged mode**: Provide both `registry` (static) and `registryMode` (dynamic) to get a merged registry where static entries take priority and dynamic definitions can only add new types — not override existing ones.
|
|
344
344
|
|
|
345
345
|
Dynamic registry returns a `DynamicGraphClient` which extends `GraphClient` with `defineNodeType()`, `defineEdgeType()`, and `reloadRegistry()`. Transactions and batches also validate against the compiled dynamic registry.
|
|
346
346
|
|
package/dist/codegen/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { l as CodegenOptions, J as generateTypes } from '../index-
|
|
1
|
+
export { l as CodegenOptions, J as generateTypes } from '../index-DR3jF5_b.cjs';
|
|
2
2
|
import '@google-cloud/firestore';
|
package/dist/codegen/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { l as CodegenOptions, J as generateTypes } from '../index-
|
|
1
|
+
export { l as CodegenOptions, J as generateTypes } from '../index-DR3jF5_b.js';
|
|
2
2
|
import '@google-cloud/firestore';
|
|
@@ -30072,6 +30072,9 @@ function matchSegments(path4, pi, pattern, qi) {
|
|
|
30072
30072
|
function tripleKey(aType, axbType, bType) {
|
|
30073
30073
|
return `${aType}:${axbType}:${bType}`;
|
|
30074
30074
|
}
|
|
30075
|
+
function tripleKeyFor(e) {
|
|
30076
|
+
return tripleKey(e.aType, e.axbType, e.bType);
|
|
30077
|
+
}
|
|
30075
30078
|
function createRegistry(input) {
|
|
30076
30079
|
const map2 = /* @__PURE__ */ new Map();
|
|
30077
30080
|
let entries;
|
|
@@ -30138,6 +30141,45 @@ function createRegistry(input) {
|
|
|
30138
30141
|
}
|
|
30139
30142
|
};
|
|
30140
30143
|
}
|
|
30144
|
+
function createMergedRegistry(base, extension) {
|
|
30145
|
+
const baseKeys = new Set(base.entries().map(tripleKeyFor));
|
|
30146
|
+
return {
|
|
30147
|
+
lookup(aType, axbType, bType) {
|
|
30148
|
+
return base.lookup(aType, axbType, bType) ?? extension.lookup(aType, axbType, bType);
|
|
30149
|
+
},
|
|
30150
|
+
lookupByAxbType(axbType) {
|
|
30151
|
+
const baseResults = base.lookupByAxbType(axbType);
|
|
30152
|
+
const extResults = extension.lookupByAxbType(axbType);
|
|
30153
|
+
if (extResults.length === 0) return baseResults;
|
|
30154
|
+
if (baseResults.length === 0) return extResults;
|
|
30155
|
+
const seen = new Set(baseResults.map(tripleKeyFor));
|
|
30156
|
+
const merged = [...baseResults];
|
|
30157
|
+
for (const entry of extResults) {
|
|
30158
|
+
if (!seen.has(tripleKeyFor(entry))) {
|
|
30159
|
+
merged.push(entry);
|
|
30160
|
+
}
|
|
30161
|
+
}
|
|
30162
|
+
return Object.freeze(merged);
|
|
30163
|
+
},
|
|
30164
|
+
validate(aType, axbType, bType, data, scopePath) {
|
|
30165
|
+
if (baseKeys.has(tripleKey(aType, axbType, bType))) {
|
|
30166
|
+
return base.validate(aType, axbType, bType, data, scopePath);
|
|
30167
|
+
}
|
|
30168
|
+
return extension.validate(aType, axbType, bType, data, scopePath);
|
|
30169
|
+
},
|
|
30170
|
+
entries() {
|
|
30171
|
+
const extEntries = extension.entries();
|
|
30172
|
+
if (extEntries.length === 0) return base.entries();
|
|
30173
|
+
const merged = [...base.entries()];
|
|
30174
|
+
for (const entry of extEntries) {
|
|
30175
|
+
if (!baseKeys.has(tripleKeyFor(entry))) {
|
|
30176
|
+
merged.push(entry);
|
|
30177
|
+
}
|
|
30178
|
+
}
|
|
30179
|
+
return Object.freeze(merged);
|
|
30180
|
+
}
|
|
30181
|
+
};
|
|
30182
|
+
}
|
|
30141
30183
|
function discoveryToEntries(discovery) {
|
|
30142
30184
|
const entries = [];
|
|
30143
30185
|
for (const [name, entity] of discovery.nodes) {
|
|
@@ -30304,14 +30346,12 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30304
30346
|
this.db = db2;
|
|
30305
30347
|
this.scopePath = scopePath;
|
|
30306
30348
|
this.adapter = createFirestoreAdapter(db2, collectionPath);
|
|
30307
|
-
if (options?.registry && options?.registryMode) {
|
|
30308
|
-
throw new DynamicRegistryError(
|
|
30309
|
-
'Cannot provide both "registry" and "registryMode". Use "registry" for static mode or "registryMode" for dynamic mode.'
|
|
30310
|
-
);
|
|
30311
|
-
}
|
|
30312
30349
|
if (options?.registryMode) {
|
|
30313
30350
|
this.dynamicConfig = options.registryMode;
|
|
30314
30351
|
this.bootstrapRegistry = createBootstrapRegistry();
|
|
30352
|
+
if (options.registry) {
|
|
30353
|
+
this.staticRegistry = options.registry;
|
|
30354
|
+
}
|
|
30315
30355
|
const metaCollectionPath = options.registryMode.collection;
|
|
30316
30356
|
if (metaCollectionPath && metaCollectionPath !== collectionPath) {
|
|
30317
30357
|
this.metaAdapter = createFirestoreAdapter(db2, metaCollectionPath);
|
|
@@ -30363,18 +30403,20 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30363
30403
|
/**
|
|
30364
30404
|
* Get the appropriate registry for validating a write to the given type.
|
|
30365
30405
|
*
|
|
30366
|
-
* - Static mode: returns staticRegistry (or undefined if none set)
|
|
30367
|
-
* - Dynamic mode:
|
|
30406
|
+
* - Static-only mode: returns staticRegistry (or undefined if none set)
|
|
30407
|
+
* - Dynamic mode (pure or merged):
|
|
30368
30408
|
* - Meta-types (nodeType, edgeType): validated against bootstrapRegistry
|
|
30369
30409
|
* - Domain types: validated against dynamicRegistry (falls back to
|
|
30370
30410
|
* bootstrapRegistry which rejects unknown types)
|
|
30411
|
+
* - Merged mode: dynamicRegistry is a merged wrapper (static + dynamic
|
|
30412
|
+
* extension), so static entries take priority automatically.
|
|
30371
30413
|
*/
|
|
30372
30414
|
getRegistryForType(aType) {
|
|
30373
30415
|
if (!this.dynamicConfig) return this.staticRegistry;
|
|
30374
30416
|
if (aType === META_NODE_TYPE || aType === META_EDGE_TYPE) {
|
|
30375
30417
|
return this.bootstrapRegistry;
|
|
30376
30418
|
}
|
|
30377
|
-
return this.dynamicRegistry ?? this.bootstrapRegistry;
|
|
30419
|
+
return this.dynamicRegistry ?? this.staticRegistry ?? this.bootstrapRegistry;
|
|
30378
30420
|
}
|
|
30379
30421
|
/**
|
|
30380
30422
|
* Get the Firestore adapter for writing the given type.
|
|
@@ -30388,13 +30430,13 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30388
30430
|
}
|
|
30389
30431
|
/**
|
|
30390
30432
|
* Get the combined registry for transaction/batch context.
|
|
30391
|
-
* In static mode, returns staticRegistry.
|
|
30433
|
+
* In static-only mode, returns staticRegistry.
|
|
30392
30434
|
* In dynamic mode, returns dynamicRegistry (which includes bootstrap entries)
|
|
30393
|
-
* or
|
|
30435
|
+
* or falls back to staticRegistry (merged mode) or bootstrapRegistry.
|
|
30394
30436
|
*/
|
|
30395
30437
|
getCombinedRegistry() {
|
|
30396
30438
|
if (!this.dynamicConfig) return this.staticRegistry;
|
|
30397
|
-
return this.dynamicRegistry ?? this.bootstrapRegistry;
|
|
30439
|
+
return this.dynamicRegistry ?? this.staticRegistry ?? this.bootstrapRegistry;
|
|
30398
30440
|
}
|
|
30399
30441
|
// ---------------------------------------------------------------------------
|
|
30400
30442
|
// Query dispatch
|
|
@@ -30591,6 +30633,11 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30591
30633
|
`Cannot define type "${name}": this name is reserved for the meta-registry.`
|
|
30592
30634
|
);
|
|
30593
30635
|
}
|
|
30636
|
+
if (this.staticRegistry?.lookup(name, NODE_RELATION, name)) {
|
|
30637
|
+
throw new DynamicRegistryError(
|
|
30638
|
+
`Cannot define node type "${name}": already defined in the static registry.`
|
|
30639
|
+
);
|
|
30640
|
+
}
|
|
30594
30641
|
const uid = generateDeterministicUid(META_NODE_TYPE, name);
|
|
30595
30642
|
const data = { name, jsonSchema };
|
|
30596
30643
|
if (description !== void 0) data.description = description;
|
|
@@ -30612,6 +30659,19 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30612
30659
|
`Cannot define type "${name}": this name is reserved for the meta-registry.`
|
|
30613
30660
|
);
|
|
30614
30661
|
}
|
|
30662
|
+
if (this.staticRegistry) {
|
|
30663
|
+
const fromTypes = Array.isArray(topology.from) ? topology.from : [topology.from];
|
|
30664
|
+
const toTypes = Array.isArray(topology.to) ? topology.to : [topology.to];
|
|
30665
|
+
for (const aType of fromTypes) {
|
|
30666
|
+
for (const bType of toTypes) {
|
|
30667
|
+
if (this.staticRegistry.lookup(aType, name, bType)) {
|
|
30668
|
+
throw new DynamicRegistryError(
|
|
30669
|
+
`Cannot define edge type "${name}" for (${aType}) -> (${bType}): already defined in the static registry.`
|
|
30670
|
+
);
|
|
30671
|
+
}
|
|
30672
|
+
}
|
|
30673
|
+
}
|
|
30674
|
+
}
|
|
30615
30675
|
const uid = generateDeterministicUid(META_EDGE_TYPE, name);
|
|
30616
30676
|
const data = {
|
|
30617
30677
|
name,
|
|
@@ -30636,7 +30696,12 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
30636
30696
|
);
|
|
30637
30697
|
}
|
|
30638
30698
|
const reader = this.createMetaReader();
|
|
30639
|
-
|
|
30699
|
+
const dynamicOnly = await createRegistryFromGraph(reader);
|
|
30700
|
+
if (this.staticRegistry) {
|
|
30701
|
+
this.dynamicRegistry = createMergedRegistry(this.staticRegistry, dynamicOnly);
|
|
30702
|
+
} else {
|
|
30703
|
+
this.dynamicRegistry = dynamicOnly;
|
|
30704
|
+
}
|
|
30640
30705
|
}
|
|
30641
30706
|
/**
|
|
30642
30707
|
* Create a GraphReader for the meta-collection.
|
|
@@ -316,7 +316,16 @@ interface EdgeTypeData {
|
|
|
316
316
|
}
|
|
317
317
|
type ScanProtection = 'error' | 'warn' | 'off';
|
|
318
318
|
interface GraphClientOptions {
|
|
319
|
-
/**
|
|
319
|
+
/**
|
|
320
|
+
* Static registry built from code/discovery.
|
|
321
|
+
*
|
|
322
|
+
* When provided alone, all writes are validated against this registry.
|
|
323
|
+
*
|
|
324
|
+
* When provided together with `registryMode`, operates in **merged mode**:
|
|
325
|
+
* static entries take priority and cannot be overridden by dynamic
|
|
326
|
+
* definitions. Dynamic definitions can only add new types. The merged
|
|
327
|
+
* client is returned as a `DynamicGraphClient`.
|
|
328
|
+
*/
|
|
320
329
|
registry?: GraphRegistry;
|
|
321
330
|
/** Dynamic registry mode — type definitions stored as graph data. */
|
|
322
331
|
registryMode?: DynamicRegistryConfig;
|
|
@@ -531,4 +540,4 @@ interface CodegenOptions {
|
|
|
531
540
|
*/
|
|
532
541
|
declare function generateTypes(discovery: DiscoveryResult, options?: CodegenOptions): Promise<string>;
|
|
533
542
|
|
|
534
|
-
export { type ViewResolverConfig as A, type BulkBatchError as B, type CascadeResult as C, type DynamicRegistryConfig as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, defineConfig as I, generateTypes as J, resolveView as K, type NodeTypeData as N, type QueryPlan as Q, type RegistryEntry as R, type ScanProtection as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type DynamicGraphClient as a, type GraphClient as b, type
|
|
543
|
+
export { type ViewResolverConfig as A, type BulkBatchError as B, type CascadeResult as C, type DynamicRegistryConfig as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, defineConfig as I, generateTypes as J, resolveView as K, type NodeTypeData as N, type QueryPlan as Q, type RegistryEntry as R, type ScanProtection as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type DynamicGraphClient as a, type GraphClient as b, type GraphRegistry as c, type DiscoveryResult as d, type GraphReader as e, type GraphRecord as f, type FindNodesParams as g, type QueryFilter as h, type BulkOptions as i, type BulkProgress as j, type BulkResult as k, type CodegenOptions as l, type DefineTypeOptions as m, type DiscoveredEntity as n, type EdgeTypeData as o, type FiregraphConfig as p, type GraphBatch as q, type GraphTransaction as r, type GraphWriter as s, type HopResult as t, type QueryMode as u, type QueryOptions as v, type StoredGraphRecord as w, type TraversalOptions as x, type TraversalResult as y, type ViewDefaultsConfig as z };
|
|
@@ -316,7 +316,16 @@ interface EdgeTypeData {
|
|
|
316
316
|
}
|
|
317
317
|
type ScanProtection = 'error' | 'warn' | 'off';
|
|
318
318
|
interface GraphClientOptions {
|
|
319
|
-
/**
|
|
319
|
+
/**
|
|
320
|
+
* Static registry built from code/discovery.
|
|
321
|
+
*
|
|
322
|
+
* When provided alone, all writes are validated against this registry.
|
|
323
|
+
*
|
|
324
|
+
* When provided together with `registryMode`, operates in **merged mode**:
|
|
325
|
+
* static entries take priority and cannot be overridden by dynamic
|
|
326
|
+
* definitions. Dynamic definitions can only add new types. The merged
|
|
327
|
+
* client is returned as a `DynamicGraphClient`.
|
|
328
|
+
*/
|
|
320
329
|
registry?: GraphRegistry;
|
|
321
330
|
/** Dynamic registry mode — type definitions stored as graph data. */
|
|
322
331
|
registryMode?: DynamicRegistryConfig;
|
|
@@ -531,4 +540,4 @@ interface CodegenOptions {
|
|
|
531
540
|
*/
|
|
532
541
|
declare function generateTypes(discovery: DiscoveryResult, options?: CodegenOptions): Promise<string>;
|
|
533
542
|
|
|
534
|
-
export { type ViewResolverConfig as A, type BulkBatchError as B, type CascadeResult as C, type DynamicRegistryConfig as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, defineConfig as I, generateTypes as J, resolveView as K, type NodeTypeData as N, type QueryPlan as Q, type RegistryEntry as R, type ScanProtection as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type DynamicGraphClient as a, type GraphClient as b, type
|
|
543
|
+
export { type ViewResolverConfig as A, type BulkBatchError as B, type CascadeResult as C, type DynamicRegistryConfig as D, type EdgeTopology as E, type FindEdgesParams as F, type GraphClientOptions as G, type HopDefinition as H, defineConfig as I, generateTypes as J, resolveView as K, type NodeTypeData as N, type QueryPlan as Q, type RegistryEntry as R, type ScanProtection as S, type TraversalBuilder as T, type ViewContext as V, type WhereClause as W, type DynamicGraphClient as a, type GraphClient as b, type GraphRegistry as c, type DiscoveryResult as d, type GraphReader as e, type GraphRecord as f, type FindNodesParams as g, type QueryFilter as h, type BulkOptions as i, type BulkProgress as j, type BulkResult as k, type CodegenOptions as l, type DefineTypeOptions as m, type DiscoveredEntity as n, type EdgeTypeData as o, type FiregraphConfig as p, type GraphBatch as q, type GraphTransaction as r, type GraphWriter as s, type HopResult as t, type QueryMode as u, type QueryOptions as v, type StoredGraphRecord as w, type TraversalOptions as x, type TraversalResult as y, type ViewDefaultsConfig as z };
|
package/dist/index.cjs
CHANGED
|
@@ -59,6 +59,7 @@ __export(index_exports, {
|
|
|
59
59
|
computeNodeDocId: () => computeNodeDocId,
|
|
60
60
|
createBootstrapRegistry: () => createBootstrapRegistry,
|
|
61
61
|
createGraphClient: () => createGraphClient,
|
|
62
|
+
createMergedRegistry: () => createMergedRegistry,
|
|
62
63
|
createRegistry: () => createRegistry,
|
|
63
64
|
createRegistryFromGraph: () => createRegistryFromGraph,
|
|
64
65
|
createTraversal: () => createTraversal,
|
|
@@ -845,6 +846,9 @@ function matchSegments(path, pi, pattern, qi) {
|
|
|
845
846
|
function tripleKey(aType, axbType, bType) {
|
|
846
847
|
return `${aType}:${axbType}:${bType}`;
|
|
847
848
|
}
|
|
849
|
+
function tripleKeyFor(e) {
|
|
850
|
+
return tripleKey(e.aType, e.axbType, e.bType);
|
|
851
|
+
}
|
|
848
852
|
function createRegistry(input) {
|
|
849
853
|
const map = /* @__PURE__ */ new Map();
|
|
850
854
|
let entries;
|
|
@@ -911,6 +915,45 @@ function createRegistry(input) {
|
|
|
911
915
|
}
|
|
912
916
|
};
|
|
913
917
|
}
|
|
918
|
+
function createMergedRegistry(base, extension) {
|
|
919
|
+
const baseKeys = new Set(base.entries().map(tripleKeyFor));
|
|
920
|
+
return {
|
|
921
|
+
lookup(aType, axbType, bType) {
|
|
922
|
+
return base.lookup(aType, axbType, bType) ?? extension.lookup(aType, axbType, bType);
|
|
923
|
+
},
|
|
924
|
+
lookupByAxbType(axbType) {
|
|
925
|
+
const baseResults = base.lookupByAxbType(axbType);
|
|
926
|
+
const extResults = extension.lookupByAxbType(axbType);
|
|
927
|
+
if (extResults.length === 0) return baseResults;
|
|
928
|
+
if (baseResults.length === 0) return extResults;
|
|
929
|
+
const seen = new Set(baseResults.map(tripleKeyFor));
|
|
930
|
+
const merged = [...baseResults];
|
|
931
|
+
for (const entry of extResults) {
|
|
932
|
+
if (!seen.has(tripleKeyFor(entry))) {
|
|
933
|
+
merged.push(entry);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
return Object.freeze(merged);
|
|
937
|
+
},
|
|
938
|
+
validate(aType, axbType, bType, data, scopePath) {
|
|
939
|
+
if (baseKeys.has(tripleKey(aType, axbType, bType))) {
|
|
940
|
+
return base.validate(aType, axbType, bType, data, scopePath);
|
|
941
|
+
}
|
|
942
|
+
return extension.validate(aType, axbType, bType, data, scopePath);
|
|
943
|
+
},
|
|
944
|
+
entries() {
|
|
945
|
+
const extEntries = extension.entries();
|
|
946
|
+
if (extEntries.length === 0) return base.entries();
|
|
947
|
+
const merged = [...base.entries()];
|
|
948
|
+
for (const entry of extEntries) {
|
|
949
|
+
if (!baseKeys.has(tripleKeyFor(entry))) {
|
|
950
|
+
merged.push(entry);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
return Object.freeze(merged);
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
}
|
|
914
957
|
function discoveryToEntries(discovery) {
|
|
915
958
|
const entries = [];
|
|
916
959
|
for (const [name, entity] of discovery.nodes) {
|
|
@@ -1077,14 +1120,12 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
1077
1120
|
this.db = db;
|
|
1078
1121
|
this.scopePath = scopePath;
|
|
1079
1122
|
this.adapter = createFirestoreAdapter(db, collectionPath);
|
|
1080
|
-
if (options?.registry && options?.registryMode) {
|
|
1081
|
-
throw new DynamicRegistryError(
|
|
1082
|
-
'Cannot provide both "registry" and "registryMode". Use "registry" for static mode or "registryMode" for dynamic mode.'
|
|
1083
|
-
);
|
|
1084
|
-
}
|
|
1085
1123
|
if (options?.registryMode) {
|
|
1086
1124
|
this.dynamicConfig = options.registryMode;
|
|
1087
1125
|
this.bootstrapRegistry = createBootstrapRegistry();
|
|
1126
|
+
if (options.registry) {
|
|
1127
|
+
this.staticRegistry = options.registry;
|
|
1128
|
+
}
|
|
1088
1129
|
const metaCollectionPath = options.registryMode.collection;
|
|
1089
1130
|
if (metaCollectionPath && metaCollectionPath !== collectionPath) {
|
|
1090
1131
|
this.metaAdapter = createFirestoreAdapter(db, metaCollectionPath);
|
|
@@ -1136,18 +1177,20 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
1136
1177
|
/**
|
|
1137
1178
|
* Get the appropriate registry for validating a write to the given type.
|
|
1138
1179
|
*
|
|
1139
|
-
* - Static mode: returns staticRegistry (or undefined if none set)
|
|
1140
|
-
* - Dynamic mode:
|
|
1180
|
+
* - Static-only mode: returns staticRegistry (or undefined if none set)
|
|
1181
|
+
* - Dynamic mode (pure or merged):
|
|
1141
1182
|
* - Meta-types (nodeType, edgeType): validated against bootstrapRegistry
|
|
1142
1183
|
* - Domain types: validated against dynamicRegistry (falls back to
|
|
1143
1184
|
* bootstrapRegistry which rejects unknown types)
|
|
1185
|
+
* - Merged mode: dynamicRegistry is a merged wrapper (static + dynamic
|
|
1186
|
+
* extension), so static entries take priority automatically.
|
|
1144
1187
|
*/
|
|
1145
1188
|
getRegistryForType(aType) {
|
|
1146
1189
|
if (!this.dynamicConfig) return this.staticRegistry;
|
|
1147
1190
|
if (aType === META_NODE_TYPE || aType === META_EDGE_TYPE) {
|
|
1148
1191
|
return this.bootstrapRegistry;
|
|
1149
1192
|
}
|
|
1150
|
-
return this.dynamicRegistry ?? this.bootstrapRegistry;
|
|
1193
|
+
return this.dynamicRegistry ?? this.staticRegistry ?? this.bootstrapRegistry;
|
|
1151
1194
|
}
|
|
1152
1195
|
/**
|
|
1153
1196
|
* Get the Firestore adapter for writing the given type.
|
|
@@ -1161,13 +1204,13 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
1161
1204
|
}
|
|
1162
1205
|
/**
|
|
1163
1206
|
* Get the combined registry for transaction/batch context.
|
|
1164
|
-
* In static mode, returns staticRegistry.
|
|
1207
|
+
* In static-only mode, returns staticRegistry.
|
|
1165
1208
|
* In dynamic mode, returns dynamicRegistry (which includes bootstrap entries)
|
|
1166
|
-
* or
|
|
1209
|
+
* or falls back to staticRegistry (merged mode) or bootstrapRegistry.
|
|
1167
1210
|
*/
|
|
1168
1211
|
getCombinedRegistry() {
|
|
1169
1212
|
if (!this.dynamicConfig) return this.staticRegistry;
|
|
1170
|
-
return this.dynamicRegistry ?? this.bootstrapRegistry;
|
|
1213
|
+
return this.dynamicRegistry ?? this.staticRegistry ?? this.bootstrapRegistry;
|
|
1171
1214
|
}
|
|
1172
1215
|
// ---------------------------------------------------------------------------
|
|
1173
1216
|
// Query dispatch
|
|
@@ -1364,6 +1407,11 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
1364
1407
|
`Cannot define type "${name}": this name is reserved for the meta-registry.`
|
|
1365
1408
|
);
|
|
1366
1409
|
}
|
|
1410
|
+
if (this.staticRegistry?.lookup(name, NODE_RELATION, name)) {
|
|
1411
|
+
throw new DynamicRegistryError(
|
|
1412
|
+
`Cannot define node type "${name}": already defined in the static registry.`
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1367
1415
|
const uid = generateDeterministicUid(META_NODE_TYPE, name);
|
|
1368
1416
|
const data = { name, jsonSchema };
|
|
1369
1417
|
if (description !== void 0) data.description = description;
|
|
@@ -1385,6 +1433,19 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
1385
1433
|
`Cannot define type "${name}": this name is reserved for the meta-registry.`
|
|
1386
1434
|
);
|
|
1387
1435
|
}
|
|
1436
|
+
if (this.staticRegistry) {
|
|
1437
|
+
const fromTypes = Array.isArray(topology.from) ? topology.from : [topology.from];
|
|
1438
|
+
const toTypes = Array.isArray(topology.to) ? topology.to : [topology.to];
|
|
1439
|
+
for (const aType of fromTypes) {
|
|
1440
|
+
for (const bType of toTypes) {
|
|
1441
|
+
if (this.staticRegistry.lookup(aType, name, bType)) {
|
|
1442
|
+
throw new DynamicRegistryError(
|
|
1443
|
+
`Cannot define edge type "${name}" for (${aType}) -> (${bType}): already defined in the static registry.`
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1388
1449
|
const uid = generateDeterministicUid(META_EDGE_TYPE, name);
|
|
1389
1450
|
const data = {
|
|
1390
1451
|
name,
|
|
@@ -1409,7 +1470,12 @@ var GraphClientImpl = class _GraphClientImpl {
|
|
|
1409
1470
|
);
|
|
1410
1471
|
}
|
|
1411
1472
|
const reader = this.createMetaReader();
|
|
1412
|
-
|
|
1473
|
+
const dynamicOnly = await createRegistryFromGraph(reader);
|
|
1474
|
+
if (this.staticRegistry) {
|
|
1475
|
+
this.dynamicRegistry = createMergedRegistry(this.staticRegistry, dynamicOnly);
|
|
1476
|
+
} else {
|
|
1477
|
+
this.dynamicRegistry = dynamicOnly;
|
|
1478
|
+
}
|
|
1413
1479
|
}
|
|
1414
1480
|
/**
|
|
1415
1481
|
* Create a GraphReader for the meta-collection.
|
|
@@ -2431,6 +2497,7 @@ var QueryClient = class {
|
|
|
2431
2497
|
computeNodeDocId,
|
|
2432
2498
|
createBootstrapRegistry,
|
|
2433
2499
|
createGraphClient,
|
|
2500
|
+
createMergedRegistry,
|
|
2434
2501
|
createRegistry,
|
|
2435
2502
|
createRegistryFromGraph,
|
|
2436
2503
|
createTraversal,
|