@nicia-ai/typegraph 0.3.1 → 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/backend/drizzle/index.cjs +6 -6
- package/dist/backend/drizzle/index.d.cts +1 -1
- package/dist/backend/drizzle/index.d.ts +1 -1
- package/dist/backend/drizzle/index.js +4 -4
- package/dist/backend/drizzle/postgres.cjs +4 -4
- package/dist/backend/drizzle/postgres.d.cts +1 -1
- package/dist/backend/drizzle/postgres.d.ts +1 -1
- package/dist/backend/drizzle/postgres.js +3 -3
- package/dist/backend/drizzle/sqlite.cjs +4 -4
- package/dist/backend/drizzle/sqlite.d.cts +1 -1
- package/dist/backend/drizzle/sqlite.d.ts +1 -1
- package/dist/backend/drizzle/sqlite.js +3 -3
- package/dist/backend/postgres/index.cjs +4 -4
- package/dist/backend/postgres/index.d.cts +1 -1
- package/dist/backend/postgres/index.d.ts +1 -1
- package/dist/backend/postgres/index.js +3 -3
- package/dist/backend/sqlite/index.cjs +6 -6
- package/dist/backend/sqlite/index.d.cts +1 -1
- package/dist/backend/sqlite/index.d.ts +1 -1
- package/dist/backend/sqlite/index.js +4 -4
- package/dist/{chunk-OYL2SGBD.cjs → chunk-44SXEVF4.cjs} +18 -2
- package/dist/chunk-44SXEVF4.cjs.map +1 -0
- package/dist/{chunk-F2BZSEFE.js → chunk-4MTYE6CF.js} +4 -4
- package/dist/{chunk-F2BZSEFE.js.map → chunk-4MTYE6CF.js.map} +1 -1
- package/dist/{chunk-4HARSV2G.js → chunk-6HFWKZU5.js} +61 -3
- package/dist/chunk-6HFWKZU5.js.map +1 -0
- package/dist/{chunk-F23W4W3A.cjs → chunk-ENXM4W4M.cjs} +18 -18
- package/dist/{chunk-F23W4W3A.cjs.map → chunk-ENXM4W4M.cjs.map} +1 -1
- package/dist/{chunk-ZJHQZZT2.cjs → chunk-K2ROKOK3.cjs} +6 -6
- package/dist/{chunk-ZJHQZZT2.cjs.map → chunk-K2ROKOK3.cjs.map} +1 -1
- package/dist/{chunk-46YY2FRV.js → chunk-KKFJJYCP.js} +3 -3
- package/dist/{chunk-46YY2FRV.js.map → chunk-KKFJJYCP.js.map} +1 -1
- package/dist/{chunk-CMHFS34N.cjs → chunk-KPU6TLUV.cjs} +16 -16
- package/dist/{chunk-CMHFS34N.cjs.map → chunk-KPU6TLUV.cjs.map} +1 -1
- package/dist/{chunk-DD6ONEBN.cjs → chunk-LDM2AFKZ.cjs} +12 -12
- package/dist/{chunk-DD6ONEBN.cjs.map → chunk-LDM2AFKZ.cjs.map} +1 -1
- package/dist/{chunk-NP4G4ZKM.js → chunk-M5SOQ7UV.js} +4 -4
- package/dist/{chunk-NP4G4ZKM.js.map → chunk-M5SOQ7UV.js.map} +1 -1
- package/dist/{chunk-SFY2PPOY.cjs → chunk-PW5BSBZV.cjs} +68 -10
- package/dist/chunk-PW5BSBZV.cjs.map +1 -0
- package/dist/{chunk-O5XPCJLF.js → chunk-SJ2QMDXY.js} +18 -3
- package/dist/chunk-SJ2QMDXY.js.map +1 -0
- package/dist/{chunk-XDTYTNYL.js → chunk-TGDFBLGS.js} +3 -3
- package/dist/{chunk-XDTYTNYL.js.map → chunk-TGDFBLGS.js.map} +1 -1
- package/dist/{index-Dkicw49A.d.ts → index-DyrR_d-H.d.cts} +9 -1
- package/dist/{index-Dkicw49A.d.cts → index-DyrR_d-H.d.ts} +9 -1
- package/dist/index.cjs +1130 -218
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +924 -16
- package/dist/index.js.map +1 -1
- package/dist/interchange/index.cjs +7 -7
- package/dist/interchange/index.d.cts +3 -3
- package/dist/interchange/index.d.ts +3 -3
- package/dist/interchange/index.js +2 -2
- package/dist/{manager-e9LXthrx.d.ts → manager-DXC7CqKG.d.ts} +1 -1
- package/dist/{manager-Jc5Btay9.d.cts → manager-DiPf-0GG.d.cts} +1 -1
- package/dist/profiler/index.d.cts +3 -3
- package/dist/profiler/index.d.ts +3 -3
- package/dist/schema/index.cjs +22 -22
- package/dist/schema/index.d.cts +5 -5
- package/dist/schema/index.d.ts +5 -5
- package/dist/schema/index.js +4 -4
- package/dist/{store-DM3Tk3Pw.d.ts → store-DODIWZxC.d.ts} +145 -7
- package/dist/{store-nbBybLWP.d.cts → store-nDW3GOFb.d.cts} +145 -7
- package/dist/{types-Cdbi4hcx.d.ts → types-DpIoePMI.d.ts} +19 -0
- package/dist/{types-DDP0MGBF.d.cts → types-WX8V9dqn.d.cts} +19 -0
- package/package.json +2 -2
- package/dist/chunk-4HARSV2G.js.map +0 -1
- package/dist/chunk-O5XPCJLF.js.map +0 -1
- package/dist/chunk-OYL2SGBD.cjs.map +0 -1
- package/dist/chunk-SFY2PPOY.cjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { META_EDGE_BRAND, META_EDGE_SUB_CLASS_OF, META_EDGE_NARROWER, META_EDGE_BROADER, META_EDGE_RELATED_TO, META_EDGE_EQUIVALENT_TO, META_EDGE_SAME_AS, META_EDGE_DIFFERENT_FROM, META_EDGE_DISJOINT_WITH, META_EDGE_HAS_PART, META_EDGE_PART_OF, META_EDGE_INVERSE_OF, META_EDGE_IMPLIES, ensureSchema, computeClosuresFromOntology, createEmptyClosures, KindRegistry, validateNodeProps, validateEdgeProps } from './chunk-
|
|
2
|
-
export { isMetaEdge } from './chunk-
|
|
3
|
-
import { NODE_TYPE_BRAND, EDGE_TYPE_BRAND, nowIso, validateOptionalIsoDate, getNodeKinds, getEdgeKinds } from './chunk-
|
|
4
|
-
export { defineGraph, getEdgeKinds, getNodeKinds, isEdgeType, isEdgeTypeWithEndpoints, isGraphDef, isNodeType } from './chunk-
|
|
5
|
-
import { ConfigurationError, UnsupportedPredicateError, ValidationError, CompilerInvariantError, KindNotFoundError, RestrictedDeleteError, NodeNotFoundError, DatabaseOperationError, EdgeNotFoundError, UniquenessError, EndpointNotFoundError, EndpointError, DisjointError
|
|
6
|
-
export { CardinalityError, CompilerInvariantError, ConfigurationError, DatabaseOperationError, DisjointError, EdgeNotFoundError, EndpointError, EndpointNotFoundError, KindNotFoundError, MigrationError, NodeNotFoundError, RestrictedDeleteError, SchemaMismatchError, TypeGraphError, UniquenessError, UnsupportedPredicateError, ValidationError, VersionConflictError, getErrorSuggestion, isConstraintError, isSystemError, isTypeGraphError, isUserRecoverable } from './chunk-
|
|
1
|
+
import { META_EDGE_BRAND, META_EDGE_SUB_CLASS_OF, META_EDGE_NARROWER, META_EDGE_BROADER, META_EDGE_RELATED_TO, META_EDGE_EQUIVALENT_TO, META_EDGE_SAME_AS, META_EDGE_DIFFERENT_FROM, META_EDGE_DISJOINT_WITH, META_EDGE_HAS_PART, META_EDGE_PART_OF, META_EDGE_INVERSE_OF, META_EDGE_IMPLIES, ensureSchema, computeClosuresFromOntology, createEmptyClosures, KindRegistry, validateNodeProps, validateEdgeProps } from './chunk-M5SOQ7UV.js';
|
|
2
|
+
export { isMetaEdge } from './chunk-M5SOQ7UV.js';
|
|
3
|
+
import { NODE_TYPE_BRAND, EDGE_TYPE_BRAND, nowIso, validateOptionalIsoDate, getNodeKinds, getEdgeKinds } from './chunk-TGDFBLGS.js';
|
|
4
|
+
export { defineGraph, getEdgeKinds, getNodeKinds, isEdgeType, isEdgeTypeWithEndpoints, isGraphDef, isNodeType } from './chunk-TGDFBLGS.js';
|
|
5
|
+
import { ConfigurationError, UnsupportedPredicateError, ValidationError, CompilerInvariantError, KindNotFoundError, RestrictedDeleteError, NodeNotFoundError, DatabaseOperationError, EdgeNotFoundError, NodeConstraintNotFoundError, UniquenessError, EndpointNotFoundError, CardinalityError, EndpointError, DisjointError } from './chunk-SJ2QMDXY.js';
|
|
6
|
+
export { CardinalityError, CompilerInvariantError, ConfigurationError, DatabaseOperationError, DisjointError, EdgeNotFoundError, EndpointError, EndpointNotFoundError, KindNotFoundError, MigrationError, NodeConstraintNotFoundError, NodeNotFoundError, RestrictedDeleteError, SchemaMismatchError, TypeGraphError, UniquenessError, UnsupportedPredicateError, ValidationError, VersionConflictError, getErrorSuggestion, isConstraintError, isSystemError, isTypeGraphError, isUserRecoverable } from './chunk-SJ2QMDXY.js';
|
|
7
7
|
import { getDialect, NODE_META_KEYS, EDGE_META_KEYS } from './chunk-54WJF3DW.js';
|
|
8
8
|
import { jsonPointer, parseJsonPointer, createSchemaIntrospector, normalizeJsonPointer, joinJsonPointers, resolveFieldTypeInfoAtJsonPointer, getEmbeddingDimensions, isEmbeddingSchema } from './chunk-K7SQ3SWP.js';
|
|
9
9
|
export { MAX_JSON_POINTER_DEPTH, embedding, getEmbeddingDimensions, isEmbeddingSchema, joinJsonPointers, jsonPointer, normalizeJsonPointer, parseJsonPointer } from './chunk-K7SQ3SWP.js';
|
|
@@ -8452,7 +8452,7 @@ function createEdgeCollection(config) {
|
|
|
8452
8452
|
const results = await executeEdgeCreateBatch2(batchInputs, backend);
|
|
8453
8453
|
return narrowEdges(results);
|
|
8454
8454
|
},
|
|
8455
|
-
async
|
|
8455
|
+
async bulkUpsertById(items) {
|
|
8456
8456
|
if (items.length === 0) return [];
|
|
8457
8457
|
const upsertAll = async (target) => {
|
|
8458
8458
|
const ids = items.map((item) => item.id);
|
|
@@ -8478,7 +8478,7 @@ function createEdgeCollection(config) {
|
|
|
8478
8478
|
if (existing) {
|
|
8479
8479
|
const input = {
|
|
8480
8480
|
id: item.id,
|
|
8481
|
-
props: item.props
|
|
8481
|
+
props: item.props
|
|
8482
8482
|
};
|
|
8483
8483
|
if (item.validTo !== void 0) input.validTo = item.validTo;
|
|
8484
8484
|
toUpdate.push({
|
|
@@ -8494,7 +8494,7 @@ function createEdgeCollection(config) {
|
|
|
8494
8494
|
fromId: item.from.id,
|
|
8495
8495
|
toKind: item.to.kind,
|
|
8496
8496
|
toId: item.to.id,
|
|
8497
|
-
props: item.props
|
|
8497
|
+
props: item.props
|
|
8498
8498
|
};
|
|
8499
8499
|
if (item.validFrom !== void 0) input.validFrom = item.validFrom;
|
|
8500
8500
|
if (item.validTo !== void 0) input.validTo = item.validTo;
|
|
@@ -8548,6 +8548,74 @@ function createEdgeCollection(config) {
|
|
|
8548
8548
|
return;
|
|
8549
8549
|
}
|
|
8550
8550
|
await deleteAll(backend);
|
|
8551
|
+
},
|
|
8552
|
+
async findByEndpoints(from, to, options) {
|
|
8553
|
+
const findOptions = {};
|
|
8554
|
+
if (options?.matchOn !== void 0)
|
|
8555
|
+
findOptions.matchOn = options.matchOn;
|
|
8556
|
+
if (options?.props !== void 0)
|
|
8557
|
+
findOptions.props = options.props;
|
|
8558
|
+
const result = await config.executeFindByEndpoints(
|
|
8559
|
+
kind,
|
|
8560
|
+
from.kind,
|
|
8561
|
+
from.id,
|
|
8562
|
+
to.kind,
|
|
8563
|
+
to.id,
|
|
8564
|
+
backend,
|
|
8565
|
+
findOptions
|
|
8566
|
+
);
|
|
8567
|
+
return result === void 0 ? void 0 : narrowEdge(result);
|
|
8568
|
+
},
|
|
8569
|
+
async getOrCreateByEndpoints(from, to, props, options) {
|
|
8570
|
+
const getOrCreateOptions = {};
|
|
8571
|
+
if (options?.matchOn !== void 0)
|
|
8572
|
+
getOrCreateOptions.matchOn = options.matchOn;
|
|
8573
|
+
if (options?.ifExists !== void 0)
|
|
8574
|
+
getOrCreateOptions.ifExists = options.ifExists;
|
|
8575
|
+
const result = await config.executeGetOrCreateByEndpoints(
|
|
8576
|
+
kind,
|
|
8577
|
+
from.kind,
|
|
8578
|
+
from.id,
|
|
8579
|
+
to.kind,
|
|
8580
|
+
to.id,
|
|
8581
|
+
props,
|
|
8582
|
+
backend,
|
|
8583
|
+
getOrCreateOptions
|
|
8584
|
+
);
|
|
8585
|
+
return { edge: narrowEdge(result.edge), action: result.action };
|
|
8586
|
+
},
|
|
8587
|
+
async bulkGetOrCreateByEndpoints(items, options) {
|
|
8588
|
+
if (items.length === 0) return [];
|
|
8589
|
+
const mappedItems = items.map((item) => ({
|
|
8590
|
+
fromKind: item.from.kind,
|
|
8591
|
+
fromId: item.from.id,
|
|
8592
|
+
toKind: item.to.kind,
|
|
8593
|
+
toId: item.to.id,
|
|
8594
|
+
props: item.props
|
|
8595
|
+
}));
|
|
8596
|
+
const getOrCreateOptions = {};
|
|
8597
|
+
if (options?.matchOn !== void 0)
|
|
8598
|
+
getOrCreateOptions.matchOn = options.matchOn;
|
|
8599
|
+
if (options?.ifExists !== void 0)
|
|
8600
|
+
getOrCreateOptions.ifExists = options.ifExists;
|
|
8601
|
+
const getOrCreateAll = async (target) => {
|
|
8602
|
+
const results = await config.executeBulkGetOrCreateByEndpoints(
|
|
8603
|
+
kind,
|
|
8604
|
+
mappedItems,
|
|
8605
|
+
target,
|
|
8606
|
+
getOrCreateOptions
|
|
8607
|
+
);
|
|
8608
|
+
return results.map((result) => ({
|
|
8609
|
+
edge: narrowEdge(result.edge),
|
|
8610
|
+
action: result.action
|
|
8611
|
+
}));
|
|
8612
|
+
};
|
|
8613
|
+
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
8614
|
+
return backend.transaction(
|
|
8615
|
+
async (txBackend) => getOrCreateAll(txBackend)
|
|
8616
|
+
);
|
|
8617
|
+
}
|
|
8618
|
+
return getOrCreateAll(backend);
|
|
8551
8619
|
}
|
|
8552
8620
|
};
|
|
8553
8621
|
}
|
|
@@ -8586,7 +8654,11 @@ function createNodeCollection(config) {
|
|
|
8586
8654
|
executeDelete: executeNodeDelete2,
|
|
8587
8655
|
executeHardDelete: executeNodeHardDelete2,
|
|
8588
8656
|
matchesTemporalMode,
|
|
8589
|
-
createQuery
|
|
8657
|
+
createQuery,
|
|
8658
|
+
executeGetOrCreateByConstraint,
|
|
8659
|
+
executeBulkGetOrCreateByConstraint,
|
|
8660
|
+
executeFindByConstraint,
|
|
8661
|
+
executeBulkFindByConstraint
|
|
8590
8662
|
} = config;
|
|
8591
8663
|
return {
|
|
8592
8664
|
async create(props, options) {
|
|
@@ -8696,7 +8768,7 @@ function createNodeCollection(config) {
|
|
|
8696
8768
|
}
|
|
8697
8769
|
return backend.countNodesByKind(params);
|
|
8698
8770
|
},
|
|
8699
|
-
async
|
|
8771
|
+
async upsertById(id, props, options) {
|
|
8700
8772
|
const existing = await backend.getNode(graphId, kind, id);
|
|
8701
8773
|
if (existing) {
|
|
8702
8774
|
const input = {
|
|
@@ -8737,7 +8809,7 @@ function createNodeCollection(config) {
|
|
|
8737
8809
|
const results = await executeNodeCreateBatch2(batchInputs, backend);
|
|
8738
8810
|
return narrowNodes(results);
|
|
8739
8811
|
},
|
|
8740
|
-
async
|
|
8812
|
+
async bulkUpsertById(items) {
|
|
8741
8813
|
if (items.length === 0) return [];
|
|
8742
8814
|
const upsertAll = async (target) => {
|
|
8743
8815
|
const ids = items.map((item) => item.id);
|
|
@@ -8834,6 +8906,68 @@ function createNodeCollection(config) {
|
|
|
8834
8906
|
return;
|
|
8835
8907
|
}
|
|
8836
8908
|
await deleteAll(backend);
|
|
8909
|
+
},
|
|
8910
|
+
async findByConstraint(constraintName, props) {
|
|
8911
|
+
const result = await executeFindByConstraint(
|
|
8912
|
+
kind,
|
|
8913
|
+
constraintName,
|
|
8914
|
+
props,
|
|
8915
|
+
backend
|
|
8916
|
+
);
|
|
8917
|
+
return result === void 0 ? void 0 : narrowNode(result);
|
|
8918
|
+
},
|
|
8919
|
+
async bulkFindByConstraint(constraintName, items) {
|
|
8920
|
+
if (items.length === 0) return [];
|
|
8921
|
+
const mappedItems = items.map((item) => ({
|
|
8922
|
+
props: item.props
|
|
8923
|
+
}));
|
|
8924
|
+
const results = await executeBulkFindByConstraint(
|
|
8925
|
+
kind,
|
|
8926
|
+
constraintName,
|
|
8927
|
+
mappedItems,
|
|
8928
|
+
backend
|
|
8929
|
+
);
|
|
8930
|
+
return results.map(
|
|
8931
|
+
(result) => result === void 0 ? void 0 : narrowNode(result)
|
|
8932
|
+
);
|
|
8933
|
+
},
|
|
8934
|
+
async getOrCreateByConstraint(constraintName, props, options) {
|
|
8935
|
+
const execute = async (target) => {
|
|
8936
|
+
const result = await executeGetOrCreateByConstraint(
|
|
8937
|
+
kind,
|
|
8938
|
+
constraintName,
|
|
8939
|
+
props,
|
|
8940
|
+
target,
|
|
8941
|
+
options
|
|
8942
|
+
);
|
|
8943
|
+
return result;
|
|
8944
|
+
};
|
|
8945
|
+
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
8946
|
+
return backend.transaction(async (txBackend) => execute(txBackend));
|
|
8947
|
+
}
|
|
8948
|
+
return execute(backend);
|
|
8949
|
+
},
|
|
8950
|
+
async bulkGetOrCreateByConstraint(constraintName, items, options) {
|
|
8951
|
+
if (items.length === 0) return [];
|
|
8952
|
+
const mappedItems = items.map((item) => ({
|
|
8953
|
+
props: item.props
|
|
8954
|
+
}));
|
|
8955
|
+
const getOrCreateAll = async (target) => {
|
|
8956
|
+
const results = await executeBulkGetOrCreateByConstraint(
|
|
8957
|
+
kind,
|
|
8958
|
+
constraintName,
|
|
8959
|
+
mappedItems,
|
|
8960
|
+
target,
|
|
8961
|
+
options
|
|
8962
|
+
);
|
|
8963
|
+
return results;
|
|
8964
|
+
};
|
|
8965
|
+
if (backend.capabilities.transactions && "transaction" in backend) {
|
|
8966
|
+
return backend.transaction(
|
|
8967
|
+
async (txBackend) => getOrCreateAll(txBackend)
|
|
8968
|
+
);
|
|
8969
|
+
}
|
|
8970
|
+
return getOrCreateAll(backend);
|
|
8837
8971
|
}
|
|
8838
8972
|
};
|
|
8839
8973
|
}
|
|
@@ -8891,16 +9025,18 @@ function createEdgeCollectionsProxy(graph, graphId, registry, backend, operation
|
|
|
8891
9025
|
}
|
|
8892
9026
|
|
|
8893
9027
|
// src/constraints/index.ts
|
|
9028
|
+
var UNIQUE_KEY_SEPARATOR = "";
|
|
9029
|
+
var UNIQUE_KEY_NULL_MARKER = "";
|
|
8894
9030
|
function computeUniqueKey(props, fields, collation) {
|
|
8895
9031
|
const values = fields.map((field2) => {
|
|
8896
9032
|
const value = props[field2];
|
|
8897
9033
|
if (value === void 0 || value === null) {
|
|
8898
|
-
return
|
|
9034
|
+
return UNIQUE_KEY_NULL_MARKER;
|
|
8899
9035
|
}
|
|
8900
9036
|
const stringValue = typeof value === "string" ? value : typeof value === "number" || typeof value === "boolean" ? value.toString() : JSON.stringify(value);
|
|
8901
9037
|
return collation === "caseInsensitive" ? stringValue.toLowerCase() : stringValue;
|
|
8902
9038
|
});
|
|
8903
|
-
return values.join(
|
|
9039
|
+
return values.join(UNIQUE_KEY_SEPARATOR);
|
|
8904
9040
|
}
|
|
8905
9041
|
function checkWherePredicate(constraint, props) {
|
|
8906
9042
|
if (!constraint.where) {
|
|
@@ -9577,6 +9713,343 @@ async function executeEdgeHardDelete(ctx, id, backend) {
|
|
|
9577
9713
|
});
|
|
9578
9714
|
});
|
|
9579
9715
|
}
|
|
9716
|
+
var RECORD_SEP = "";
|
|
9717
|
+
var UNIT_SEP = "";
|
|
9718
|
+
var UNDEFINED_SENTINEL = "";
|
|
9719
|
+
function validateMatchOnFields(schema, matchOn, edgeKind) {
|
|
9720
|
+
if (matchOn.length === 0) return;
|
|
9721
|
+
const shape = schema.shape;
|
|
9722
|
+
if (shape === void 0) {
|
|
9723
|
+
throw new ValidationError(
|
|
9724
|
+
`Edge kind "${edgeKind}" has no schema shape to validate matchOn fields against`,
|
|
9725
|
+
{
|
|
9726
|
+
kind: edgeKind,
|
|
9727
|
+
operation: "create",
|
|
9728
|
+
issues: matchOn.map((field2) => ({
|
|
9729
|
+
path: field2,
|
|
9730
|
+
message: `Field "${field2}" does not exist in edge schema`
|
|
9731
|
+
}))
|
|
9732
|
+
}
|
|
9733
|
+
);
|
|
9734
|
+
}
|
|
9735
|
+
const invalidFields = matchOn.filter((field2) => !(field2 in shape));
|
|
9736
|
+
if (invalidFields.length > 0) {
|
|
9737
|
+
throw new ValidationError(
|
|
9738
|
+
`Invalid matchOn fields for edge kind "${edgeKind}": ${invalidFields.join(", ")}`,
|
|
9739
|
+
{
|
|
9740
|
+
kind: edgeKind,
|
|
9741
|
+
operation: "create",
|
|
9742
|
+
issues: invalidFields.map((field2) => ({
|
|
9743
|
+
path: field2,
|
|
9744
|
+
message: `Field "${field2}" does not exist in edge schema`
|
|
9745
|
+
}))
|
|
9746
|
+
}
|
|
9747
|
+
);
|
|
9748
|
+
}
|
|
9749
|
+
}
|
|
9750
|
+
function stableStringify(value) {
|
|
9751
|
+
if (value === void 0) return UNDEFINED_SENTINEL;
|
|
9752
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
9753
|
+
if (Array.isArray(value)) {
|
|
9754
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
9755
|
+
}
|
|
9756
|
+
const sorted = Object.keys(value).toSorted();
|
|
9757
|
+
const entries = sorted.map(
|
|
9758
|
+
(key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`
|
|
9759
|
+
);
|
|
9760
|
+
return `{${entries.join(",")}}`;
|
|
9761
|
+
}
|
|
9762
|
+
function buildEdgeCompositeKey(fromKind, fromId, toKind, toId, props, matchOn) {
|
|
9763
|
+
const endpointPart = `${fromKind}${RECORD_SEP}${fromId}${RECORD_SEP}${toKind}${RECORD_SEP}${toId}`;
|
|
9764
|
+
if (matchOn.length === 0) return endpointPart;
|
|
9765
|
+
const sortedFields = [...matchOn].toSorted();
|
|
9766
|
+
const propertyParts = sortedFields.map(
|
|
9767
|
+
(field2) => `${RECORD_SEP}${field2}${UNIT_SEP}${stableStringify(props[field2])}`
|
|
9768
|
+
);
|
|
9769
|
+
return endpointPart + propertyParts.join("");
|
|
9770
|
+
}
|
|
9771
|
+
function buildEndpointPairKey(fromKind, fromId, toKind, toId) {
|
|
9772
|
+
return `${fromKind}${RECORD_SEP}${fromId}${RECORD_SEP}${toKind}${RECORD_SEP}${toId}`;
|
|
9773
|
+
}
|
|
9774
|
+
function findMatchingEdge(rows, matchOn, inputProps) {
|
|
9775
|
+
let liveRow;
|
|
9776
|
+
let deletedRow;
|
|
9777
|
+
for (const row of rows) {
|
|
9778
|
+
if (matchOn.length > 0) {
|
|
9779
|
+
const rowProps = JSON.parse(row.props);
|
|
9780
|
+
const matches = matchOn.every(
|
|
9781
|
+
(field2) => stableStringify(rowProps[field2]) === stableStringify(inputProps[field2])
|
|
9782
|
+
);
|
|
9783
|
+
if (!matches) continue;
|
|
9784
|
+
}
|
|
9785
|
+
if (row.deleted_at === void 0) {
|
|
9786
|
+
liveRow ??= row;
|
|
9787
|
+
} else {
|
|
9788
|
+
deletedRow ??= row;
|
|
9789
|
+
}
|
|
9790
|
+
if (liveRow !== void 0) break;
|
|
9791
|
+
}
|
|
9792
|
+
return { liveRow, deletedRow };
|
|
9793
|
+
}
|
|
9794
|
+
async function executeEdgeFindByEndpoints(ctx, kind, fromKind, fromId, toKind, toId, backend, options) {
|
|
9795
|
+
const matchOn = options?.matchOn ?? [];
|
|
9796
|
+
const props = options?.props ?? {};
|
|
9797
|
+
const registration = getEdgeRegistration(ctx.graph, kind);
|
|
9798
|
+
const edgeKind = registration.type;
|
|
9799
|
+
if (matchOn.length > 0) {
|
|
9800
|
+
validateMatchOnFields(edgeKind.schema, matchOn, kind);
|
|
9801
|
+
}
|
|
9802
|
+
const candidateRows = await backend.findEdgesByKind({
|
|
9803
|
+
graphId: ctx.graphId,
|
|
9804
|
+
kind,
|
|
9805
|
+
fromKind,
|
|
9806
|
+
fromId,
|
|
9807
|
+
toKind,
|
|
9808
|
+
toId,
|
|
9809
|
+
excludeDeleted: true
|
|
9810
|
+
});
|
|
9811
|
+
if (candidateRows.length === 0) return void 0;
|
|
9812
|
+
if (matchOn.length === 0) return rowToEdge(candidateRows[0]);
|
|
9813
|
+
const { liveRow } = findMatchingEdge(candidateRows, matchOn, props);
|
|
9814
|
+
return liveRow === void 0 ? void 0 : rowToEdge(liveRow);
|
|
9815
|
+
}
|
|
9816
|
+
async function executeEdgeGetOrCreateByEndpoints(ctx, kind, fromKind, fromId, toKind, toId, props, backend, options) {
|
|
9817
|
+
const ifExists = options?.ifExists ?? "return";
|
|
9818
|
+
const matchOn = options?.matchOn ?? [];
|
|
9819
|
+
const registration = getEdgeRegistration(ctx.graph, kind);
|
|
9820
|
+
const edgeKind = registration.type;
|
|
9821
|
+
const validatedProps = validateEdgeProps(edgeKind.schema, props, {
|
|
9822
|
+
kind,
|
|
9823
|
+
operation: "create"
|
|
9824
|
+
});
|
|
9825
|
+
validateMatchOnFields(edgeKind.schema, matchOn, kind);
|
|
9826
|
+
const candidateRows = await backend.findEdgesByKind({
|
|
9827
|
+
graphId: ctx.graphId,
|
|
9828
|
+
kind,
|
|
9829
|
+
fromKind,
|
|
9830
|
+
fromId,
|
|
9831
|
+
toKind,
|
|
9832
|
+
toId,
|
|
9833
|
+
excludeDeleted: false,
|
|
9834
|
+
temporalMode: "includeTombstones"
|
|
9835
|
+
});
|
|
9836
|
+
const { liveRow, deletedRow } = findMatchingEdge(
|
|
9837
|
+
candidateRows,
|
|
9838
|
+
matchOn,
|
|
9839
|
+
validatedProps
|
|
9840
|
+
);
|
|
9841
|
+
if (liveRow === void 0 && deletedRow === void 0) {
|
|
9842
|
+
const input = {
|
|
9843
|
+
kind,
|
|
9844
|
+
fromKind,
|
|
9845
|
+
fromId,
|
|
9846
|
+
toKind,
|
|
9847
|
+
toId,
|
|
9848
|
+
props: validatedProps
|
|
9849
|
+
};
|
|
9850
|
+
const edge2 = await executeEdgeCreate(ctx, input, backend);
|
|
9851
|
+
return { edge: edge2, action: "created" };
|
|
9852
|
+
}
|
|
9853
|
+
if (liveRow !== void 0) {
|
|
9854
|
+
if (ifExists === "return") {
|
|
9855
|
+
return { edge: rowToEdge(liveRow), action: "found" };
|
|
9856
|
+
}
|
|
9857
|
+
const edge2 = await executeEdgeUpsertUpdate(
|
|
9858
|
+
ctx,
|
|
9859
|
+
{ id: liveRow.id, props: validatedProps },
|
|
9860
|
+
backend
|
|
9861
|
+
);
|
|
9862
|
+
return { edge: edge2, action: "updated" };
|
|
9863
|
+
}
|
|
9864
|
+
const cardinality = registration.cardinality ?? "many";
|
|
9865
|
+
const matchedDeletedRow = deletedRow;
|
|
9866
|
+
const effectiveValidTo = matchedDeletedRow.valid_to;
|
|
9867
|
+
const constraintContext = {
|
|
9868
|
+
graphId: ctx.graphId,
|
|
9869
|
+
registry: ctx.registry,
|
|
9870
|
+
backend
|
|
9871
|
+
};
|
|
9872
|
+
await checkCardinalityConstraint(
|
|
9873
|
+
constraintContext,
|
|
9874
|
+
kind,
|
|
9875
|
+
cardinality,
|
|
9876
|
+
fromKind,
|
|
9877
|
+
fromId,
|
|
9878
|
+
toKind,
|
|
9879
|
+
toId,
|
|
9880
|
+
effectiveValidTo
|
|
9881
|
+
);
|
|
9882
|
+
const edge = await executeEdgeUpsertUpdate(
|
|
9883
|
+
ctx,
|
|
9884
|
+
{ id: matchedDeletedRow.id, props: validatedProps },
|
|
9885
|
+
backend,
|
|
9886
|
+
{ clearDeleted: true }
|
|
9887
|
+
);
|
|
9888
|
+
return { edge, action: "resurrected" };
|
|
9889
|
+
}
|
|
9890
|
+
async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend, options) {
|
|
9891
|
+
if (items.length === 0) return [];
|
|
9892
|
+
const ifExists = options?.ifExists ?? "return";
|
|
9893
|
+
const matchOn = options?.matchOn ?? [];
|
|
9894
|
+
const registration = getEdgeRegistration(ctx.graph, kind);
|
|
9895
|
+
const edgeKind = registration.type;
|
|
9896
|
+
const cardinality = registration.cardinality ?? "many";
|
|
9897
|
+
validateMatchOnFields(edgeKind.schema, matchOn, kind);
|
|
9898
|
+
const validated = [];
|
|
9899
|
+
for (const item of items) {
|
|
9900
|
+
const validatedProps = validateEdgeProps(edgeKind.schema, item.props, {
|
|
9901
|
+
kind,
|
|
9902
|
+
operation: "create"
|
|
9903
|
+
});
|
|
9904
|
+
const compositeKey = buildEdgeCompositeKey(
|
|
9905
|
+
item.fromKind,
|
|
9906
|
+
item.fromId,
|
|
9907
|
+
item.toKind,
|
|
9908
|
+
item.toId,
|
|
9909
|
+
validatedProps,
|
|
9910
|
+
matchOn
|
|
9911
|
+
);
|
|
9912
|
+
const endpointKey = buildEndpointPairKey(
|
|
9913
|
+
item.fromKind,
|
|
9914
|
+
item.fromId,
|
|
9915
|
+
item.toKind,
|
|
9916
|
+
item.toId
|
|
9917
|
+
);
|
|
9918
|
+
validated.push({
|
|
9919
|
+
fromKind: item.fromKind,
|
|
9920
|
+
fromId: item.fromId,
|
|
9921
|
+
toKind: item.toKind,
|
|
9922
|
+
toId: item.toId,
|
|
9923
|
+
validatedProps,
|
|
9924
|
+
compositeKey,
|
|
9925
|
+
endpointKey
|
|
9926
|
+
});
|
|
9927
|
+
}
|
|
9928
|
+
const uniqueEndpoints = /* @__PURE__ */ new Map();
|
|
9929
|
+
for (const entry of validated) {
|
|
9930
|
+
if (!uniqueEndpoints.has(entry.endpointKey)) {
|
|
9931
|
+
uniqueEndpoints.set(entry.endpointKey, {
|
|
9932
|
+
fromKind: entry.fromKind,
|
|
9933
|
+
fromId: entry.fromId,
|
|
9934
|
+
toKind: entry.toKind,
|
|
9935
|
+
toId: entry.toId
|
|
9936
|
+
});
|
|
9937
|
+
}
|
|
9938
|
+
}
|
|
9939
|
+
const rowsByEndpoint = /* @__PURE__ */ new Map();
|
|
9940
|
+
for (const [endpointKey, endpoint] of uniqueEndpoints) {
|
|
9941
|
+
const rows = await backend.findEdgesByKind({
|
|
9942
|
+
graphId: ctx.graphId,
|
|
9943
|
+
kind,
|
|
9944
|
+
fromKind: endpoint.fromKind,
|
|
9945
|
+
fromId: endpoint.fromId,
|
|
9946
|
+
toKind: endpoint.toKind,
|
|
9947
|
+
toId: endpoint.toId,
|
|
9948
|
+
excludeDeleted: false,
|
|
9949
|
+
temporalMode: "includeTombstones"
|
|
9950
|
+
});
|
|
9951
|
+
rowsByEndpoint.set(endpointKey, rows);
|
|
9952
|
+
}
|
|
9953
|
+
const toCreate = [];
|
|
9954
|
+
const toFetch = [];
|
|
9955
|
+
const duplicateOf = [];
|
|
9956
|
+
const seenKeys = /* @__PURE__ */ new Map();
|
|
9957
|
+
for (const [index, entry] of validated.entries()) {
|
|
9958
|
+
const previousIndex = seenKeys.get(entry.compositeKey);
|
|
9959
|
+
if (previousIndex !== void 0) {
|
|
9960
|
+
duplicateOf.push({ index, sourceIndex: previousIndex });
|
|
9961
|
+
continue;
|
|
9962
|
+
}
|
|
9963
|
+
seenKeys.set(entry.compositeKey, index);
|
|
9964
|
+
const candidateRows = rowsByEndpoint.get(entry.endpointKey) ?? [];
|
|
9965
|
+
const { liveRow, deletedRow } = findMatchingEdge(
|
|
9966
|
+
candidateRows,
|
|
9967
|
+
matchOn,
|
|
9968
|
+
entry.validatedProps
|
|
9969
|
+
);
|
|
9970
|
+
if (liveRow === void 0 && deletedRow === void 0) {
|
|
9971
|
+
toCreate.push({
|
|
9972
|
+
index,
|
|
9973
|
+
input: {
|
|
9974
|
+
kind,
|
|
9975
|
+
fromKind: entry.fromKind,
|
|
9976
|
+
fromId: entry.fromId,
|
|
9977
|
+
toKind: entry.toKind,
|
|
9978
|
+
toId: entry.toId,
|
|
9979
|
+
props: entry.validatedProps
|
|
9980
|
+
}
|
|
9981
|
+
});
|
|
9982
|
+
} else {
|
|
9983
|
+
const bestRow = liveRow ?? deletedRow;
|
|
9984
|
+
toFetch.push({
|
|
9985
|
+
index,
|
|
9986
|
+
row: bestRow,
|
|
9987
|
+
isDeleted: liveRow === void 0,
|
|
9988
|
+
validatedProps: entry.validatedProps,
|
|
9989
|
+
fromKind: entry.fromKind,
|
|
9990
|
+
fromId: entry.fromId,
|
|
9991
|
+
toKind: entry.toKind,
|
|
9992
|
+
toId: entry.toId
|
|
9993
|
+
});
|
|
9994
|
+
}
|
|
9995
|
+
}
|
|
9996
|
+
const results = Array.from({ length: items.length });
|
|
9997
|
+
if (toCreate.length > 0) {
|
|
9998
|
+
const createInputs = toCreate.map((entry) => entry.input);
|
|
9999
|
+
const createdEdges = await executeEdgeCreateBatch(
|
|
10000
|
+
ctx,
|
|
10001
|
+
createInputs,
|
|
10002
|
+
backend
|
|
10003
|
+
);
|
|
10004
|
+
for (const [batchIndex, entry] of toCreate.entries()) {
|
|
10005
|
+
results[entry.index] = {
|
|
10006
|
+
edge: createdEdges[batchIndex],
|
|
10007
|
+
action: "created"
|
|
10008
|
+
};
|
|
10009
|
+
}
|
|
10010
|
+
}
|
|
10011
|
+
for (const entry of toFetch) {
|
|
10012
|
+
if (entry.isDeleted) {
|
|
10013
|
+
const effectiveValidTo = entry.row.valid_to;
|
|
10014
|
+
const constraintContext = {
|
|
10015
|
+
graphId: ctx.graphId,
|
|
10016
|
+
registry: ctx.registry,
|
|
10017
|
+
backend
|
|
10018
|
+
};
|
|
10019
|
+
await checkCardinalityConstraint(
|
|
10020
|
+
constraintContext,
|
|
10021
|
+
kind,
|
|
10022
|
+
cardinality,
|
|
10023
|
+
entry.fromKind,
|
|
10024
|
+
entry.fromId,
|
|
10025
|
+
entry.toKind,
|
|
10026
|
+
entry.toId,
|
|
10027
|
+
effectiveValidTo
|
|
10028
|
+
);
|
|
10029
|
+
const edge = await executeEdgeUpsertUpdate(
|
|
10030
|
+
ctx,
|
|
10031
|
+
{ id: entry.row.id, props: entry.validatedProps },
|
|
10032
|
+
backend,
|
|
10033
|
+
{ clearDeleted: true }
|
|
10034
|
+
);
|
|
10035
|
+
results[entry.index] = { edge, action: "resurrected" };
|
|
10036
|
+
} else if (ifExists === "update") {
|
|
10037
|
+
const edge = await executeEdgeUpsertUpdate(
|
|
10038
|
+
ctx,
|
|
10039
|
+
{ id: entry.row.id, props: entry.validatedProps },
|
|
10040
|
+
backend
|
|
10041
|
+
);
|
|
10042
|
+
results[entry.index] = { edge, action: "updated" };
|
|
10043
|
+
} else {
|
|
10044
|
+
results[entry.index] = { edge: rowToEdge(entry.row), action: "found" };
|
|
10045
|
+
}
|
|
10046
|
+
}
|
|
10047
|
+
for (const { index, sourceIndex } of duplicateOf) {
|
|
10048
|
+
const sourceResult = results[sourceIndex];
|
|
10049
|
+
results[index] = { edge: sourceResult.edge, action: "found" };
|
|
10050
|
+
}
|
|
10051
|
+
return results;
|
|
10052
|
+
}
|
|
9580
10053
|
|
|
9581
10054
|
// src/store/embedding-sync.ts
|
|
9582
10055
|
function getEmbeddingFields(schema) {
|
|
@@ -10359,6 +10832,371 @@ async function executeNodeHardDelete(ctx, kind, id, backend) {
|
|
|
10359
10832
|
await ("transaction" in backend && backend.capabilities.transactions ? backend.transaction(async (tx) => hardDelete(tx)) : hardDelete(backend));
|
|
10360
10833
|
});
|
|
10361
10834
|
}
|
|
10835
|
+
function resolveConstraint(graph, kind, constraintName) {
|
|
10836
|
+
const registration = getNodeRegistration(graph, kind);
|
|
10837
|
+
const constraints = registration.unique ?? [];
|
|
10838
|
+
const constraint = constraints.find((c) => c.name === constraintName);
|
|
10839
|
+
if (constraint === void 0) {
|
|
10840
|
+
throw new NodeConstraintNotFoundError(constraintName, kind);
|
|
10841
|
+
}
|
|
10842
|
+
return constraint;
|
|
10843
|
+
}
|
|
10844
|
+
async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, props, backend, options) {
|
|
10845
|
+
const ifExists = options?.ifExists ?? "return";
|
|
10846
|
+
const registration = getNodeRegistration(ctx.graph, kind);
|
|
10847
|
+
const nodeKind = registration.type;
|
|
10848
|
+
const validatedProps = validateNodeProps(nodeKind.schema, props, {
|
|
10849
|
+
kind,
|
|
10850
|
+
operation: "create"
|
|
10851
|
+
});
|
|
10852
|
+
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
10853
|
+
if (!checkWherePredicate(constraint, validatedProps)) {
|
|
10854
|
+
const input = { kind, props: validatedProps };
|
|
10855
|
+
const node = await executeNodeCreate(ctx, input, backend);
|
|
10856
|
+
return { node, action: "created" };
|
|
10857
|
+
}
|
|
10858
|
+
const key = computeUniqueKey(
|
|
10859
|
+
validatedProps,
|
|
10860
|
+
constraint.fields,
|
|
10861
|
+
constraint.collation
|
|
10862
|
+
);
|
|
10863
|
+
const kindsToCheck = getKindsForUniquenessCheck(
|
|
10864
|
+
kind,
|
|
10865
|
+
constraint.scope,
|
|
10866
|
+
ctx.registry
|
|
10867
|
+
);
|
|
10868
|
+
let existingUniqueRow;
|
|
10869
|
+
for (const kindToCheck of kindsToCheck) {
|
|
10870
|
+
const row = await backend.checkUnique({
|
|
10871
|
+
graphId: ctx.graphId,
|
|
10872
|
+
nodeKind: kindToCheck,
|
|
10873
|
+
constraintName: constraint.name,
|
|
10874
|
+
key,
|
|
10875
|
+
includeDeleted: true
|
|
10876
|
+
});
|
|
10877
|
+
if (row !== void 0) {
|
|
10878
|
+
existingUniqueRow = row;
|
|
10879
|
+
break;
|
|
10880
|
+
}
|
|
10881
|
+
}
|
|
10882
|
+
if (existingUniqueRow === void 0) {
|
|
10883
|
+
const input = { kind, props: validatedProps };
|
|
10884
|
+
const node = await executeNodeCreate(ctx, input, backend);
|
|
10885
|
+
return { node, action: "created" };
|
|
10886
|
+
}
|
|
10887
|
+
const existingRow = await backend.getNode(
|
|
10888
|
+
ctx.graphId,
|
|
10889
|
+
existingUniqueRow.concrete_kind,
|
|
10890
|
+
existingUniqueRow.node_id
|
|
10891
|
+
);
|
|
10892
|
+
if (existingRow === void 0) {
|
|
10893
|
+
const input = { kind, props: validatedProps };
|
|
10894
|
+
const node = await executeNodeCreate(ctx, input, backend);
|
|
10895
|
+
return { node, action: "created" };
|
|
10896
|
+
}
|
|
10897
|
+
const isSoftDeleted = existingRow.deleted_at !== void 0;
|
|
10898
|
+
if (isSoftDeleted || ifExists === "update") {
|
|
10899
|
+
const concreteKind = existingUniqueRow.concrete_kind;
|
|
10900
|
+
const node = await executeNodeUpsertUpdate(
|
|
10901
|
+
ctx,
|
|
10902
|
+
{
|
|
10903
|
+
kind: concreteKind,
|
|
10904
|
+
id: existingRow.id,
|
|
10905
|
+
props: validatedProps
|
|
10906
|
+
},
|
|
10907
|
+
backend,
|
|
10908
|
+
{ clearDeleted: isSoftDeleted }
|
|
10909
|
+
);
|
|
10910
|
+
return { node, action: isSoftDeleted ? "resurrected" : "updated" };
|
|
10911
|
+
}
|
|
10912
|
+
return { node: rowToNode(existingRow), action: "found" };
|
|
10913
|
+
}
|
|
10914
|
+
async function executeNodeFindByConstraint(ctx, kind, constraintName, props, backend) {
|
|
10915
|
+
const registration = getNodeRegistration(ctx.graph, kind);
|
|
10916
|
+
const nodeKind = registration.type;
|
|
10917
|
+
const validatedProps = validateNodeProps(nodeKind.schema, props, {
|
|
10918
|
+
kind,
|
|
10919
|
+
operation: "create"
|
|
10920
|
+
});
|
|
10921
|
+
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
10922
|
+
if (!checkWherePredicate(constraint, validatedProps)) return void 0;
|
|
10923
|
+
const key = computeUniqueKey(
|
|
10924
|
+
validatedProps,
|
|
10925
|
+
constraint.fields,
|
|
10926
|
+
constraint.collation
|
|
10927
|
+
);
|
|
10928
|
+
const kindsToCheck = getKindsForUniquenessCheck(
|
|
10929
|
+
kind,
|
|
10930
|
+
constraint.scope,
|
|
10931
|
+
ctx.registry
|
|
10932
|
+
);
|
|
10933
|
+
let existingUniqueRow;
|
|
10934
|
+
for (const kindToCheck of kindsToCheck) {
|
|
10935
|
+
const row = await backend.checkUnique({
|
|
10936
|
+
graphId: ctx.graphId,
|
|
10937
|
+
nodeKind: kindToCheck,
|
|
10938
|
+
constraintName: constraint.name,
|
|
10939
|
+
key,
|
|
10940
|
+
includeDeleted: false
|
|
10941
|
+
});
|
|
10942
|
+
if (row !== void 0) {
|
|
10943
|
+
existingUniqueRow = row;
|
|
10944
|
+
break;
|
|
10945
|
+
}
|
|
10946
|
+
}
|
|
10947
|
+
if (existingUniqueRow === void 0) return void 0;
|
|
10948
|
+
const existingRow = await backend.getNode(
|
|
10949
|
+
ctx.graphId,
|
|
10950
|
+
existingUniqueRow.concrete_kind,
|
|
10951
|
+
existingUniqueRow.node_id
|
|
10952
|
+
);
|
|
10953
|
+
if (existingRow === void 0 || existingRow.deleted_at !== void 0)
|
|
10954
|
+
return void 0;
|
|
10955
|
+
return rowToNode(existingRow);
|
|
10956
|
+
}
|
|
10957
|
+
async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items, backend) {
|
|
10958
|
+
if (items.length === 0) return [];
|
|
10959
|
+
const registration = getNodeRegistration(ctx.graph, kind);
|
|
10960
|
+
const nodeKind = registration.type;
|
|
10961
|
+
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
10962
|
+
const validated = [];
|
|
10963
|
+
for (const item of items) {
|
|
10964
|
+
const validatedProps = validateNodeProps(nodeKind.schema, item.props, {
|
|
10965
|
+
kind,
|
|
10966
|
+
operation: "create"
|
|
10967
|
+
});
|
|
10968
|
+
const applies = checkWherePredicate(constraint, validatedProps);
|
|
10969
|
+
const key = applies ? computeUniqueKey(
|
|
10970
|
+
validatedProps,
|
|
10971
|
+
constraint.fields,
|
|
10972
|
+
constraint.collation
|
|
10973
|
+
) : void 0;
|
|
10974
|
+
validated.push({ validatedProps, key });
|
|
10975
|
+
}
|
|
10976
|
+
const uniqueKeys = [
|
|
10977
|
+
...new Set(
|
|
10978
|
+
validated.map((v) => v.key).filter((k) => k !== void 0)
|
|
10979
|
+
)
|
|
10980
|
+
];
|
|
10981
|
+
const kindsToCheck = getKindsForUniquenessCheck(
|
|
10982
|
+
kind,
|
|
10983
|
+
constraint.scope,
|
|
10984
|
+
ctx.registry
|
|
10985
|
+
);
|
|
10986
|
+
const existingByKey = /* @__PURE__ */ new Map();
|
|
10987
|
+
if (uniqueKeys.length > 0) {
|
|
10988
|
+
for (const kindToCheck of kindsToCheck) {
|
|
10989
|
+
if (backend.checkUniqueBatch === void 0) {
|
|
10990
|
+
for (const key of uniqueKeys) {
|
|
10991
|
+
if (existingByKey.has(key)) continue;
|
|
10992
|
+
const row = await backend.checkUnique({
|
|
10993
|
+
graphId: ctx.graphId,
|
|
10994
|
+
nodeKind: kindToCheck,
|
|
10995
|
+
constraintName: constraint.name,
|
|
10996
|
+
key,
|
|
10997
|
+
includeDeleted: false
|
|
10998
|
+
});
|
|
10999
|
+
if (row !== void 0) {
|
|
11000
|
+
existingByKey.set(row.key, row);
|
|
11001
|
+
}
|
|
11002
|
+
}
|
|
11003
|
+
} else {
|
|
11004
|
+
const rows = await backend.checkUniqueBatch({
|
|
11005
|
+
graphId: ctx.graphId,
|
|
11006
|
+
nodeKind: kindToCheck,
|
|
11007
|
+
constraintName: constraint.name,
|
|
11008
|
+
keys: uniqueKeys,
|
|
11009
|
+
includeDeleted: false
|
|
11010
|
+
});
|
|
11011
|
+
for (const row of rows) {
|
|
11012
|
+
if (!existingByKey.has(row.key)) {
|
|
11013
|
+
existingByKey.set(row.key, row);
|
|
11014
|
+
}
|
|
11015
|
+
}
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
}
|
|
11019
|
+
const results = Array.from({ length: items.length });
|
|
11020
|
+
const seenKeys = /* @__PURE__ */ new Map();
|
|
11021
|
+
for (const [index, { key }] of validated.entries()) {
|
|
11022
|
+
if (key === void 0) {
|
|
11023
|
+
results[index] = void 0;
|
|
11024
|
+
continue;
|
|
11025
|
+
}
|
|
11026
|
+
const previousIndex = seenKeys.get(key);
|
|
11027
|
+
if (previousIndex !== void 0) {
|
|
11028
|
+
results[index] = results[previousIndex];
|
|
11029
|
+
continue;
|
|
11030
|
+
}
|
|
11031
|
+
seenKeys.set(key, index);
|
|
11032
|
+
const existing = existingByKey.get(key);
|
|
11033
|
+
if (existing === void 0) {
|
|
11034
|
+
results[index] = void 0;
|
|
11035
|
+
continue;
|
|
11036
|
+
}
|
|
11037
|
+
const existingRow = await backend.getNode(
|
|
11038
|
+
ctx.graphId,
|
|
11039
|
+
existing.concrete_kind,
|
|
11040
|
+
existing.node_id
|
|
11041
|
+
);
|
|
11042
|
+
if (existingRow === void 0 || existingRow.deleted_at !== void 0) {
|
|
11043
|
+
results[index] = void 0;
|
|
11044
|
+
continue;
|
|
11045
|
+
}
|
|
11046
|
+
results[index] = rowToNode(existingRow);
|
|
11047
|
+
}
|
|
11048
|
+
return results;
|
|
11049
|
+
}
|
|
11050
|
+
async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName, items, backend, options) {
|
|
11051
|
+
if (items.length === 0) return [];
|
|
11052
|
+
const ifExists = options?.ifExists ?? "return";
|
|
11053
|
+
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11054
|
+
const nodeKind = registration.type;
|
|
11055
|
+
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
11056
|
+
const validated = [];
|
|
11057
|
+
for (const item of items) {
|
|
11058
|
+
const validatedProps = validateNodeProps(nodeKind.schema, item.props, {
|
|
11059
|
+
kind,
|
|
11060
|
+
operation: "create"
|
|
11061
|
+
});
|
|
11062
|
+
const applies = checkWherePredicate(constraint, validatedProps);
|
|
11063
|
+
const key = applies ? computeUniqueKey(
|
|
11064
|
+
validatedProps,
|
|
11065
|
+
constraint.fields,
|
|
11066
|
+
constraint.collation
|
|
11067
|
+
) : void 0;
|
|
11068
|
+
validated.push({ validatedProps, key });
|
|
11069
|
+
}
|
|
11070
|
+
const uniqueKeys = [
|
|
11071
|
+
...new Set(
|
|
11072
|
+
validated.map((v) => v.key).filter((k) => k !== void 0)
|
|
11073
|
+
)
|
|
11074
|
+
];
|
|
11075
|
+
const kindsToCheck = getKindsForUniquenessCheck(
|
|
11076
|
+
kind,
|
|
11077
|
+
constraint.scope,
|
|
11078
|
+
ctx.registry
|
|
11079
|
+
);
|
|
11080
|
+
const existingByKey = /* @__PURE__ */ new Map();
|
|
11081
|
+
if (uniqueKeys.length > 0) {
|
|
11082
|
+
for (const kindToCheck of kindsToCheck) {
|
|
11083
|
+
if (backend.checkUniqueBatch === void 0) {
|
|
11084
|
+
for (const key of uniqueKeys) {
|
|
11085
|
+
if (existingByKey.has(key)) continue;
|
|
11086
|
+
const row = await backend.checkUnique({
|
|
11087
|
+
graphId: ctx.graphId,
|
|
11088
|
+
nodeKind: kindToCheck,
|
|
11089
|
+
constraintName: constraint.name,
|
|
11090
|
+
key,
|
|
11091
|
+
includeDeleted: true
|
|
11092
|
+
});
|
|
11093
|
+
if (row !== void 0) {
|
|
11094
|
+
existingByKey.set(row.key, row);
|
|
11095
|
+
}
|
|
11096
|
+
}
|
|
11097
|
+
} else {
|
|
11098
|
+
const rows = await backend.checkUniqueBatch({
|
|
11099
|
+
graphId: ctx.graphId,
|
|
11100
|
+
nodeKind: kindToCheck,
|
|
11101
|
+
constraintName: constraint.name,
|
|
11102
|
+
keys: uniqueKeys,
|
|
11103
|
+
includeDeleted: true
|
|
11104
|
+
});
|
|
11105
|
+
for (const row of rows) {
|
|
11106
|
+
if (!existingByKey.has(row.key)) {
|
|
11107
|
+
existingByKey.set(row.key, row);
|
|
11108
|
+
}
|
|
11109
|
+
}
|
|
11110
|
+
}
|
|
11111
|
+
}
|
|
11112
|
+
}
|
|
11113
|
+
const toCreate = [];
|
|
11114
|
+
const toFetch = [];
|
|
11115
|
+
const duplicateOf = [];
|
|
11116
|
+
const seenKeys = /* @__PURE__ */ new Map();
|
|
11117
|
+
for (const [index, { validatedProps, key }] of validated.entries()) {
|
|
11118
|
+
if (key === void 0) {
|
|
11119
|
+
toCreate.push({
|
|
11120
|
+
index,
|
|
11121
|
+
input: { kind, props: validatedProps }
|
|
11122
|
+
});
|
|
11123
|
+
continue;
|
|
11124
|
+
}
|
|
11125
|
+
const previousIndex = seenKeys.get(key);
|
|
11126
|
+
if (previousIndex !== void 0) {
|
|
11127
|
+
duplicateOf.push({ index, sourceIndex: previousIndex });
|
|
11128
|
+
continue;
|
|
11129
|
+
}
|
|
11130
|
+
seenKeys.set(key, index);
|
|
11131
|
+
const existing = existingByKey.get(key);
|
|
11132
|
+
if (existing === void 0) {
|
|
11133
|
+
toCreate.push({
|
|
11134
|
+
index,
|
|
11135
|
+
input: { kind, props: validatedProps }
|
|
11136
|
+
});
|
|
11137
|
+
} else {
|
|
11138
|
+
toFetch.push({
|
|
11139
|
+
index,
|
|
11140
|
+
nodeId: existing.node_id,
|
|
11141
|
+
concreteKind: existing.concrete_kind,
|
|
11142
|
+
validatedProps,
|
|
11143
|
+
isSoftDeleted: existing.deleted_at !== void 0
|
|
11144
|
+
});
|
|
11145
|
+
}
|
|
11146
|
+
}
|
|
11147
|
+
const results = Array.from({ length: items.length });
|
|
11148
|
+
if (toCreate.length > 0) {
|
|
11149
|
+
const createInputs = toCreate.map((entry) => entry.input);
|
|
11150
|
+
const createdNodes = await executeNodeCreateBatch(
|
|
11151
|
+
ctx,
|
|
11152
|
+
createInputs,
|
|
11153
|
+
backend
|
|
11154
|
+
);
|
|
11155
|
+
for (const [batchIndex, entry] of toCreate.entries()) {
|
|
11156
|
+
results[entry.index] = {
|
|
11157
|
+
node: createdNodes[batchIndex],
|
|
11158
|
+
action: "created"
|
|
11159
|
+
};
|
|
11160
|
+
}
|
|
11161
|
+
}
|
|
11162
|
+
for (const entry of toFetch) {
|
|
11163
|
+
const { index, concreteKind, validatedProps, isSoftDeleted, nodeId } = entry;
|
|
11164
|
+
const existingRow = await backend.getNode(
|
|
11165
|
+
ctx.graphId,
|
|
11166
|
+
concreteKind,
|
|
11167
|
+
nodeId
|
|
11168
|
+
);
|
|
11169
|
+
if (existingRow === void 0) {
|
|
11170
|
+
const input = { kind, props: validatedProps };
|
|
11171
|
+
const node = await executeNodeCreate(ctx, input, backend);
|
|
11172
|
+
results[index] = { node, action: "created" };
|
|
11173
|
+
continue;
|
|
11174
|
+
}
|
|
11175
|
+
if (isSoftDeleted || ifExists === "update") {
|
|
11176
|
+
const node = await executeNodeUpsertUpdate(
|
|
11177
|
+
ctx,
|
|
11178
|
+
{
|
|
11179
|
+
kind: concreteKind,
|
|
11180
|
+
id: existingRow.id,
|
|
11181
|
+
props: validatedProps
|
|
11182
|
+
},
|
|
11183
|
+
backend,
|
|
11184
|
+
{ clearDeleted: isSoftDeleted }
|
|
11185
|
+
);
|
|
11186
|
+
results[index] = {
|
|
11187
|
+
node,
|
|
11188
|
+
action: isSoftDeleted ? "resurrected" : "updated"
|
|
11189
|
+
};
|
|
11190
|
+
} else {
|
|
11191
|
+
results[index] = { node: rowToNode(existingRow), action: "found" };
|
|
11192
|
+
}
|
|
11193
|
+
}
|
|
11194
|
+
for (const { index, sourceIndex } of duplicateOf) {
|
|
11195
|
+
const sourceResult = results[sourceIndex];
|
|
11196
|
+
results[index] = { node: sourceResult.node, action: "found" };
|
|
11197
|
+
}
|
|
11198
|
+
return results;
|
|
11199
|
+
}
|
|
10362
11200
|
|
|
10363
11201
|
// src/store/store.ts
|
|
10364
11202
|
var Store = class {
|
|
@@ -10472,7 +11310,31 @@ var Store = class {
|
|
|
10472
11310
|
executeDelete: (kind, id, backend) => executeNodeDelete(ctx, kind, id, backend),
|
|
10473
11311
|
executeHardDelete: (kind, id, backend) => executeNodeHardDelete(ctx, kind, id, backend),
|
|
10474
11312
|
matchesTemporalMode: (row, options) => this.#matchesTemporalMode(row, options),
|
|
10475
|
-
createQuery: () => this.query()
|
|
11313
|
+
createQuery: () => this.query(),
|
|
11314
|
+
executeGetOrCreateByConstraint: (kind, constraintName, props, backend, options) => executeNodeGetOrCreateByConstraint(
|
|
11315
|
+
ctx,
|
|
11316
|
+
kind,
|
|
11317
|
+
constraintName,
|
|
11318
|
+
props,
|
|
11319
|
+
backend,
|
|
11320
|
+
options
|
|
11321
|
+
),
|
|
11322
|
+
executeBulkGetOrCreateByConstraint: (kind, constraintName, items, backend, options) => executeNodeBulkGetOrCreateByConstraint(
|
|
11323
|
+
ctx,
|
|
11324
|
+
kind,
|
|
11325
|
+
constraintName,
|
|
11326
|
+
items,
|
|
11327
|
+
backend,
|
|
11328
|
+
options
|
|
11329
|
+
),
|
|
11330
|
+
executeFindByConstraint: (kind, constraintName, props, backend) => executeNodeFindByConstraint(ctx, kind, constraintName, props, backend),
|
|
11331
|
+
executeBulkFindByConstraint: (kind, constraintName, items, backend) => executeNodeBulkFindByConstraint(
|
|
11332
|
+
ctx,
|
|
11333
|
+
kind,
|
|
11334
|
+
constraintName,
|
|
11335
|
+
items,
|
|
11336
|
+
backend
|
|
11337
|
+
)
|
|
10476
11338
|
};
|
|
10477
11339
|
}
|
|
10478
11340
|
/**
|
|
@@ -10491,7 +11353,35 @@ var Store = class {
|
|
|
10491
11353
|
executeDelete: (id, backend) => executeEdgeDelete(ctx, id, backend),
|
|
10492
11354
|
executeHardDelete: (id, backend) => executeEdgeHardDelete(ctx, id, backend),
|
|
10493
11355
|
matchesTemporalMode: (row, options) => this.#matchesTemporalMode(row, options),
|
|
10494
|
-
createQuery: () => this.query()
|
|
11356
|
+
createQuery: () => this.query(),
|
|
11357
|
+
executeGetOrCreateByEndpoints: (kind, fromKind, fromId, toKind, toId, props, backend, options) => executeEdgeGetOrCreateByEndpoints(
|
|
11358
|
+
ctx,
|
|
11359
|
+
kind,
|
|
11360
|
+
fromKind,
|
|
11361
|
+
fromId,
|
|
11362
|
+
toKind,
|
|
11363
|
+
toId,
|
|
11364
|
+
props,
|
|
11365
|
+
backend,
|
|
11366
|
+
options
|
|
11367
|
+
),
|
|
11368
|
+
executeBulkGetOrCreateByEndpoints: (kind, items, backend, options) => executeEdgeBulkGetOrCreateByEndpoints(
|
|
11369
|
+
ctx,
|
|
11370
|
+
kind,
|
|
11371
|
+
items,
|
|
11372
|
+
backend,
|
|
11373
|
+
options
|
|
11374
|
+
),
|
|
11375
|
+
executeFindByEndpoints: (kind, fromKind, fromId, toKind, toId, backend, options) => executeEdgeFindByEndpoints(
|
|
11376
|
+
ctx,
|
|
11377
|
+
kind,
|
|
11378
|
+
fromKind,
|
|
11379
|
+
fromId,
|
|
11380
|
+
toKind,
|
|
11381
|
+
toId,
|
|
11382
|
+
backend,
|
|
11383
|
+
options
|
|
11384
|
+
)
|
|
10495
11385
|
};
|
|
10496
11386
|
}
|
|
10497
11387
|
// === Query Builder ===
|
|
@@ -10558,6 +11448,24 @@ var Store = class {
|
|
|
10558
11448
|
return fn({ nodes, edges });
|
|
10559
11449
|
});
|
|
10560
11450
|
}
|
|
11451
|
+
// === Graph Lifecycle ===
|
|
11452
|
+
/**
|
|
11453
|
+
* Hard-deletes all data for this graph from the database.
|
|
11454
|
+
*
|
|
11455
|
+
* Removes all nodes, edges, uniqueness entries, embeddings, and schema versions
|
|
11456
|
+
* for this graph's ID. No hooks, no per-row logic. Wrapped in a transaction
|
|
11457
|
+
* when the backend supports it.
|
|
11458
|
+
*
|
|
11459
|
+
* The store is usable after clearing — new data can be created immediately.
|
|
11460
|
+
*/
|
|
11461
|
+
async clear() {
|
|
11462
|
+
const doClear = async (target) => {
|
|
11463
|
+
await target.clearGraph(this.graphId);
|
|
11464
|
+
};
|
|
11465
|
+
await (this.#backend.capabilities.transactions ? this.#backend.transaction(async (tx) => doClear(tx)) : doClear(this.#backend));
|
|
11466
|
+
this.#nodeCollections = void 0;
|
|
11467
|
+
this.#edgeCollections = void 0;
|
|
11468
|
+
}
|
|
10561
11469
|
// === Lifecycle ===
|
|
10562
11470
|
/**
|
|
10563
11471
|
* Closes the store and releases underlying resources.
|