@utaba/deep-memory 0.5.0 → 0.6.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.cjs +354 -362
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +352 -361
- package/dist/index.js.map +1 -1
- package/dist/providers/index.d.cts +18 -10
- package/dist/providers/index.d.ts +18 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -901,310 +901,6 @@ function validateTraversalSpec(spec, vocabulary, capabilities) {
|
|
|
901
901
|
};
|
|
902
902
|
}
|
|
903
903
|
|
|
904
|
-
// src/relationships/compilers/GremlinCompiler.ts
|
|
905
|
-
var DEFAULT_ESTIMATED_FANOUT_PER_HOP = 10;
|
|
906
|
-
var GremlinCompiler = class {
|
|
907
|
-
language = "gremlin";
|
|
908
|
-
compile(spec, _vocabulary) {
|
|
909
|
-
const parts = [];
|
|
910
|
-
const params = {};
|
|
911
|
-
let paramIndex = 0;
|
|
912
|
-
let estimatedFanOut = 1;
|
|
913
|
-
const nextParam = (value) => {
|
|
914
|
-
const name = `p${paramIndex++}`;
|
|
915
|
-
params[name] = value;
|
|
916
|
-
return name;
|
|
917
|
-
};
|
|
918
|
-
parts.push("g.V()");
|
|
919
|
-
if (spec.start.entityId) {
|
|
920
|
-
const p = nextParam(spec.start.entityId);
|
|
921
|
-
parts.push(`.has('id', ${p})`);
|
|
922
|
-
} else if (spec.start.entityType) {
|
|
923
|
-
const p = nextParam(spec.start.entityType);
|
|
924
|
-
parts.push(`.has('entityType', ${p})`);
|
|
925
|
-
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
926
|
-
}
|
|
927
|
-
if (spec.start.filter) {
|
|
928
|
-
for (const f of spec.start.filter) {
|
|
929
|
-
parts.push(compilePropertyFilter(f, nextParam));
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
const steps = spec.steps ?? [];
|
|
933
|
-
for (const step of steps) {
|
|
934
|
-
if (step.repeat) {
|
|
935
|
-
parts.push(compileRepeatStep(step, nextParam));
|
|
936
|
-
estimatedFanOut *= step.repeat.maxDepth * DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
937
|
-
} else if (step.relationshipFilter && step.relationshipFilter.length > 0) {
|
|
938
|
-
parts.push(compileEdgeStep(step, nextParam));
|
|
939
|
-
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
940
|
-
} else {
|
|
941
|
-
parts.push(compileSimpleStep(step, nextParam));
|
|
942
|
-
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
943
|
-
}
|
|
944
|
-
if (step.entityTypes && step.entityTypes.length > 0) {
|
|
945
|
-
const typeParams = step.entityTypes.map((t) => nextParam(t));
|
|
946
|
-
parts.push(`.has('entityType', within(${typeParams.join(", ")}))`);
|
|
947
|
-
}
|
|
948
|
-
if (step.entityFilter) {
|
|
949
|
-
for (const f of step.entityFilter) {
|
|
950
|
-
parts.push(compilePropertyFilter(f, nextParam));
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
}
|
|
954
|
-
if (spec.returnMode === "all") {
|
|
955
|
-
}
|
|
956
|
-
if (spec.dedup !== false) {
|
|
957
|
-
parts.push(".dedup()");
|
|
958
|
-
}
|
|
959
|
-
const limit = spec.limit ?? 50;
|
|
960
|
-
const offset = spec.offset ?? 0;
|
|
961
|
-
const pOffset = nextParam(offset);
|
|
962
|
-
const pEnd = nextParam(offset + limit);
|
|
963
|
-
parts.push(`.range(${pOffset}, ${pEnd})`);
|
|
964
|
-
params["_limit"] = limit;
|
|
965
|
-
params["_offset"] = offset;
|
|
966
|
-
if (spec.returnMode === "path") {
|
|
967
|
-
parts.push(".path()");
|
|
968
|
-
}
|
|
969
|
-
if (spec.returnMode !== "path") {
|
|
970
|
-
parts.push(".valueMap(true)");
|
|
971
|
-
}
|
|
972
|
-
return {
|
|
973
|
-
query: parts.join(""),
|
|
974
|
-
params,
|
|
975
|
-
estimatedFanOut: Math.min(estimatedFanOut, 1e4)
|
|
976
|
-
};
|
|
977
|
-
}
|
|
978
|
-
};
|
|
979
|
-
function compileSimpleStep(step, nextParam) {
|
|
980
|
-
const types = step.relationshipTypes;
|
|
981
|
-
const typeArgs = types ? types.map((t) => nextParam(t)).join(", ") : "";
|
|
982
|
-
switch (step.direction) {
|
|
983
|
-
case "out":
|
|
984
|
-
return types ? `.out(${typeArgs})` : ".out()";
|
|
985
|
-
case "in":
|
|
986
|
-
return types ? `.in(${typeArgs})` : ".in()";
|
|
987
|
-
case "both":
|
|
988
|
-
return types ? `.both(${typeArgs})` : ".both()";
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
function compileEdgeStep(step, nextParam) {
|
|
992
|
-
const parts = [];
|
|
993
|
-
const types = step.relationshipTypes;
|
|
994
|
-
const typeArgs = types ? types.map((t) => nextParam(t)).join(", ") : "";
|
|
995
|
-
switch (step.direction) {
|
|
996
|
-
case "out":
|
|
997
|
-
parts.push(types ? `.outE(${typeArgs})` : ".outE()");
|
|
998
|
-
break;
|
|
999
|
-
case "in":
|
|
1000
|
-
parts.push(types ? `.inE(${typeArgs})` : ".inE()");
|
|
1001
|
-
break;
|
|
1002
|
-
case "both":
|
|
1003
|
-
parts.push(types ? `.bothE(${typeArgs})` : ".bothE()");
|
|
1004
|
-
break;
|
|
1005
|
-
}
|
|
1006
|
-
if (step.relationshipFilter) {
|
|
1007
|
-
for (const f of step.relationshipFilter) {
|
|
1008
|
-
parts.push(compilePropertyFilter(f, nextParam));
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
switch (step.direction) {
|
|
1012
|
-
case "out":
|
|
1013
|
-
parts.push(".inV()");
|
|
1014
|
-
break;
|
|
1015
|
-
case "in":
|
|
1016
|
-
parts.push(".outV()");
|
|
1017
|
-
break;
|
|
1018
|
-
case "both":
|
|
1019
|
-
parts.push(".otherV()");
|
|
1020
|
-
break;
|
|
1021
|
-
}
|
|
1022
|
-
return parts.join("");
|
|
1023
|
-
}
|
|
1024
|
-
function compileRepeatStep(step, nextParam) {
|
|
1025
|
-
const parts = [];
|
|
1026
|
-
const innerStep = step.relationshipFilter?.length ? compileEdgeStep({ ...step, repeat: void 0 }, nextParam) : compileSimpleStep(step, nextParam);
|
|
1027
|
-
if (step.repeat?.emitIntermediates !== false) {
|
|
1028
|
-
parts.push(".emit()");
|
|
1029
|
-
}
|
|
1030
|
-
parts.push(`.repeat(${innerStep.startsWith(".") ? `__${innerStep}` : innerStep})`);
|
|
1031
|
-
if (step.repeat?.until && step.repeat.until.length > 0) {
|
|
1032
|
-
const untilParts = step.repeat.until.map((f) => compilePropertyFilter(f, nextParam));
|
|
1033
|
-
parts.push(`.until(${untilParts.join("")})`);
|
|
1034
|
-
}
|
|
1035
|
-
if (step.repeat?.maxDepth) {
|
|
1036
|
-
const p = nextParam(step.repeat.maxDepth);
|
|
1037
|
-
parts.push(`.times(${p})`);
|
|
1038
|
-
}
|
|
1039
|
-
if (step.repeat?.emitIntermediates === false) {
|
|
1040
|
-
parts.push(".emit()");
|
|
1041
|
-
}
|
|
1042
|
-
return parts.join("");
|
|
1043
|
-
}
|
|
1044
|
-
function compilePropertyFilter(filter, nextParam) {
|
|
1045
|
-
const key = nextParam(filter.key);
|
|
1046
|
-
switch (filter.operator) {
|
|
1047
|
-
case "eq": {
|
|
1048
|
-
const val = nextParam(filter.value);
|
|
1049
|
-
return `.has(${key}, ${val})`;
|
|
1050
|
-
}
|
|
1051
|
-
case "neq": {
|
|
1052
|
-
const val = nextParam(filter.value);
|
|
1053
|
-
return `.has(${key}, neq(${val}))`;
|
|
1054
|
-
}
|
|
1055
|
-
case "gt": {
|
|
1056
|
-
const val = nextParam(filter.value);
|
|
1057
|
-
return `.has(${key}, gt(${val}))`;
|
|
1058
|
-
}
|
|
1059
|
-
case "gte": {
|
|
1060
|
-
const val = nextParam(filter.value);
|
|
1061
|
-
return `.has(${key}, gte(${val}))`;
|
|
1062
|
-
}
|
|
1063
|
-
case "lt": {
|
|
1064
|
-
const val = nextParam(filter.value);
|
|
1065
|
-
return `.has(${key}, lt(${val}))`;
|
|
1066
|
-
}
|
|
1067
|
-
case "lte": {
|
|
1068
|
-
const val = nextParam(filter.value);
|
|
1069
|
-
return `.has(${key}, lte(${val}))`;
|
|
1070
|
-
}
|
|
1071
|
-
case "contains": {
|
|
1072
|
-
const val = nextParam(filter.value);
|
|
1073
|
-
return `.has(${key}, containing(${val}))`;
|
|
1074
|
-
}
|
|
1075
|
-
case "isNull":
|
|
1076
|
-
return `.hasNot(${key})`;
|
|
1077
|
-
case "isNotNull":
|
|
1078
|
-
return `.has(${key})`;
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// src/relationships/compilers/CypherCompiler.ts
|
|
1083
|
-
var DEFAULT_ESTIMATED_FANOUT_PER_HOP2 = 10;
|
|
1084
|
-
var CypherCompiler = class {
|
|
1085
|
-
language = "cypher";
|
|
1086
|
-
compile(spec, _vocabulary) {
|
|
1087
|
-
const params = {};
|
|
1088
|
-
let paramIndex = 0;
|
|
1089
|
-
let estimatedFanOut = 1;
|
|
1090
|
-
const whereClauses = [];
|
|
1091
|
-
let nodeIndex = 0;
|
|
1092
|
-
const nextParam = (value) => {
|
|
1093
|
-
const name = `p${paramIndex++}`;
|
|
1094
|
-
params[name] = value;
|
|
1095
|
-
return `$${name}`;
|
|
1096
|
-
};
|
|
1097
|
-
const startNode = `n${nodeIndex++}`;
|
|
1098
|
-
let matchParts = [];
|
|
1099
|
-
if (spec.start.entityId) {
|
|
1100
|
-
matchParts.push(`(${startNode})`);
|
|
1101
|
-
whereClauses.push(`${startNode}.id = ${nextParam(spec.start.entityId)}`);
|
|
1102
|
-
} else if (spec.start.entityType) {
|
|
1103
|
-
matchParts.push(`(${startNode})`);
|
|
1104
|
-
whereClauses.push(`${startNode}.entityType = ${nextParam(spec.start.entityType)}`);
|
|
1105
|
-
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP2;
|
|
1106
|
-
} else {
|
|
1107
|
-
matchParts.push(`(${startNode})`);
|
|
1108
|
-
}
|
|
1109
|
-
if (spec.start.filter) {
|
|
1110
|
-
for (const f of spec.start.filter) {
|
|
1111
|
-
whereClauses.push(compilePropertyFilterCypher(startNode, f, nextParam));
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
let lastNode = startNode;
|
|
1115
|
-
const steps = spec.steps ?? [];
|
|
1116
|
-
for (let i = 0; i < steps.length; i++) {
|
|
1117
|
-
const step = steps[i];
|
|
1118
|
-
const targetNode = `n${nodeIndex++}`;
|
|
1119
|
-
const relAlias = `r${i}`;
|
|
1120
|
-
const relTypes = step.relationshipTypes?.length ? step.relationshipTypes.join("|") : "";
|
|
1121
|
-
const relTypePattern = relTypes ? `:${relTypes}` : "";
|
|
1122
|
-
const depthPattern = step.repeat ? `*1..${step.repeat.maxDepth}` : "";
|
|
1123
|
-
let pattern;
|
|
1124
|
-
switch (step.direction) {
|
|
1125
|
-
case "out":
|
|
1126
|
-
pattern = `-[${relAlias}${relTypePattern}${depthPattern}]->(${targetNode})`;
|
|
1127
|
-
break;
|
|
1128
|
-
case "in":
|
|
1129
|
-
pattern = `<-[${relAlias}${relTypePattern}${depthPattern}]-(${targetNode})`;
|
|
1130
|
-
break;
|
|
1131
|
-
case "both":
|
|
1132
|
-
pattern = `-[${relAlias}${relTypePattern}${depthPattern}]-(${targetNode})`;
|
|
1133
|
-
break;
|
|
1134
|
-
}
|
|
1135
|
-
matchParts.push(pattern);
|
|
1136
|
-
estimatedFanOut *= step.repeat ? step.repeat.maxDepth * DEFAULT_ESTIMATED_FANOUT_PER_HOP2 : DEFAULT_ESTIMATED_FANOUT_PER_HOP2;
|
|
1137
|
-
if (step.entityTypes && step.entityTypes.length > 0) {
|
|
1138
|
-
const typeParam = nextParam(step.entityTypes);
|
|
1139
|
-
whereClauses.push(`${targetNode}.entityType IN ${typeParam}`);
|
|
1140
|
-
}
|
|
1141
|
-
if (step.entityFilter) {
|
|
1142
|
-
for (const f of step.entityFilter) {
|
|
1143
|
-
whereClauses.push(compilePropertyFilterCypher(targetNode, f, nextParam));
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
if (step.relationshipFilter) {
|
|
1147
|
-
for (const f of step.relationshipFilter) {
|
|
1148
|
-
whereClauses.push(compilePropertyFilterCypher(relAlias, f, nextParam));
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
lastNode = targetNode;
|
|
1152
|
-
}
|
|
1153
|
-
const matchClause = `MATCH ${matchParts[0]}${matchParts.slice(1).join("")}`;
|
|
1154
|
-
const whereClause = whereClauses.length > 0 ? `
|
|
1155
|
-
WHERE ${whereClauses.join(" AND ")}` : "";
|
|
1156
|
-
let returnClause;
|
|
1157
|
-
if (spec.returnMode === "path") {
|
|
1158
|
-
const allNodes = Array.from({ length: nodeIndex }, (_, i) => `n${i}`);
|
|
1159
|
-
const allRels = steps.map((_, i) => `r${i}`);
|
|
1160
|
-
returnClause = `RETURN ${[...allNodes, ...allRels].join(", ")}`;
|
|
1161
|
-
} else if (spec.returnMode === "all") {
|
|
1162
|
-
const allNodes = Array.from({ length: nodeIndex }, (_, i) => `n${i}`);
|
|
1163
|
-
returnClause = spec.dedup !== false ? `RETURN DISTINCT ${allNodes.join(", ")}` : `RETURN ${allNodes.join(", ")}`;
|
|
1164
|
-
} else {
|
|
1165
|
-
returnClause = spec.dedup !== false ? `RETURN DISTINCT ${lastNode}` : `RETURN ${lastNode}`;
|
|
1166
|
-
}
|
|
1167
|
-
const offset = spec.offset ?? 0;
|
|
1168
|
-
const limit = spec.limit ?? 50;
|
|
1169
|
-
const skipClause = offset > 0 ? `
|
|
1170
|
-
SKIP ${nextParam(offset)}` : "";
|
|
1171
|
-
const limitClause = `
|
|
1172
|
-
LIMIT ${nextParam(limit)}`;
|
|
1173
|
-
params["_limit"] = limit;
|
|
1174
|
-
params["_offset"] = offset;
|
|
1175
|
-
const query = `${matchClause}${whereClause}
|
|
1176
|
-
${returnClause}${skipClause}${limitClause}`;
|
|
1177
|
-
return {
|
|
1178
|
-
query,
|
|
1179
|
-
params,
|
|
1180
|
-
estimatedFanOut: Math.min(estimatedFanOut, 1e4)
|
|
1181
|
-
};
|
|
1182
|
-
}
|
|
1183
|
-
};
|
|
1184
|
-
function compilePropertyFilterCypher(nodeAlias, filter, nextParam) {
|
|
1185
|
-
const prop = `${nodeAlias}.${filter.key}`;
|
|
1186
|
-
switch (filter.operator) {
|
|
1187
|
-
case "eq":
|
|
1188
|
-
return `${prop} = ${nextParam(filter.value)}`;
|
|
1189
|
-
case "neq":
|
|
1190
|
-
return `${prop} <> ${nextParam(filter.value)}`;
|
|
1191
|
-
case "gt":
|
|
1192
|
-
return `${prop} > ${nextParam(filter.value)}`;
|
|
1193
|
-
case "gte":
|
|
1194
|
-
return `${prop} >= ${nextParam(filter.value)}`;
|
|
1195
|
-
case "lt":
|
|
1196
|
-
return `${prop} < ${nextParam(filter.value)}`;
|
|
1197
|
-
case "lte":
|
|
1198
|
-
return `${prop} <= ${nextParam(filter.value)}`;
|
|
1199
|
-
case "contains":
|
|
1200
|
-
return `${prop} CONTAINS ${nextParam(filter.value)}`;
|
|
1201
|
-
case "isNull":
|
|
1202
|
-
return `${prop} IS NULL`;
|
|
1203
|
-
case "isNotNull":
|
|
1204
|
-
return `${prop} IS NOT NULL`;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
904
|
// src/relationships/PropertyFilterMatcher.ts
|
|
1209
905
|
function matchesPropertyFilters(properties, filters) {
|
|
1210
906
|
return filters.every((filter) => matchesSingleFilter(properties, filter));
|
|
@@ -1737,8 +1433,9 @@ var GraphTraversal = class {
|
|
|
1737
1433
|
}
|
|
1738
1434
|
/**
|
|
1739
1435
|
* Execute a structured traversal.
|
|
1740
|
-
* Validates the spec,
|
|
1741
|
-
* falls back to
|
|
1436
|
+
* Validates the spec, delegates to the GraphTraversalProvider if one is
|
|
1437
|
+
* registered (the provider owns native compilation), or falls back to
|
|
1438
|
+
* application-level BFS over StorageProvider.
|
|
1742
1439
|
*/
|
|
1743
1440
|
async traverse(spec) {
|
|
1744
1441
|
const capabilities = this.graphTraversalProvider?.getCapabilities();
|
|
@@ -1753,19 +1450,8 @@ var GraphTraversal = class {
|
|
|
1753
1450
|
}
|
|
1754
1451
|
throw new TraversalValidationError(structErrors.length > 0 ? structErrors : validation.errors);
|
|
1755
1452
|
}
|
|
1756
|
-
if (this.graphTraversalProvider
|
|
1757
|
-
|
|
1758
|
-
let compiledQuery;
|
|
1759
|
-
if (language === "gremlin") {
|
|
1760
|
-
const compiler = new GremlinCompiler();
|
|
1761
|
-
const compiled = compiler.compile(spec, vocabulary);
|
|
1762
|
-
compiledQuery = compiled.query;
|
|
1763
|
-
} else if (language === "cypher") {
|
|
1764
|
-
const compiler = new CypherCompiler();
|
|
1765
|
-
const compiled = compiler.compile(spec, vocabulary);
|
|
1766
|
-
compiledQuery = compiled.query;
|
|
1767
|
-
}
|
|
1768
|
-
return this.graphTraversalProvider.traverse(this.repositoryId, spec, compiledQuery);
|
|
1453
|
+
if (this.graphTraversalProvider) {
|
|
1454
|
+
return this.graphTraversalProvider.traverse(this.repositoryId, spec);
|
|
1769
1455
|
}
|
|
1770
1456
|
return executeFallbackTraversal(this.repositoryId, this.storage, spec);
|
|
1771
1457
|
}
|
|
@@ -3352,7 +3038,7 @@ var EventBus = class {
|
|
|
3352
3038
|
};
|
|
3353
3039
|
|
|
3354
3040
|
// src/portability/RepositoryExporter.ts
|
|
3355
|
-
var LIBRARY_VERSION = true ? "0.
|
|
3041
|
+
var LIBRARY_VERSION = true ? "0.6.0" : "0.1.0";
|
|
3356
3042
|
var RepositoryExporter = class {
|
|
3357
3043
|
storage;
|
|
3358
3044
|
provenance;
|
|
@@ -4318,54 +4004,358 @@ var DeepMemory = class {
|
|
|
4318
4004
|
relationshipCount
|
|
4319
4005
|
});
|
|
4320
4006
|
}
|
|
4321
|
-
/**
|
|
4322
|
-
* Import a repository from a stream of chunks.
|
|
4323
|
-
* Use for large repositories to avoid loading everything into memory.
|
|
4324
|
-
*/
|
|
4325
|
-
async importRepositoryStream(header, chunks, options) {
|
|
4326
|
-
await this.ensureInitialized();
|
|
4327
|
-
const importer = new RepositoryImporter({
|
|
4328
|
-
storage: this.storage,
|
|
4329
|
-
actorId: this.provenance.getContext().actorId,
|
|
4330
|
-
onProgress: (progress) => this.globalEventBus.emit("import:progress", progress)
|
|
4331
|
-
});
|
|
4332
|
-
await this.globalEventBus.emit("import:started", { repositoryId: options.target.repositoryId });
|
|
4333
|
-
const result = await importer.importStream(header, chunks, options);
|
|
4334
|
-
if (result.success) {
|
|
4335
|
-
await this.globalEventBus.emit("import:completed", {
|
|
4336
|
-
repositoryId: result.repositoryId,
|
|
4337
|
-
entitiesImported: result.statistics.entitiesImported,
|
|
4338
|
-
relationshipsImported: result.statistics.relationshipsImported
|
|
4339
|
-
});
|
|
4340
|
-
} else {
|
|
4341
|
-
await this.globalEventBus.emit("import:failed", {
|
|
4342
|
-
repositoryId: result.repositoryId,
|
|
4343
|
-
error: result.warnings.map((w) => w.message).join("; ")
|
|
4344
|
-
});
|
|
4007
|
+
/**
|
|
4008
|
+
* Import a repository from a stream of chunks.
|
|
4009
|
+
* Use for large repositories to avoid loading everything into memory.
|
|
4010
|
+
*/
|
|
4011
|
+
async importRepositoryStream(header, chunks, options) {
|
|
4012
|
+
await this.ensureInitialized();
|
|
4013
|
+
const importer = new RepositoryImporter({
|
|
4014
|
+
storage: this.storage,
|
|
4015
|
+
actorId: this.provenance.getContext().actorId,
|
|
4016
|
+
onProgress: (progress) => this.globalEventBus.emit("import:progress", progress)
|
|
4017
|
+
});
|
|
4018
|
+
await this.globalEventBus.emit("import:started", { repositoryId: options.target.repositoryId });
|
|
4019
|
+
const result = await importer.importStream(header, chunks, options);
|
|
4020
|
+
if (result.success) {
|
|
4021
|
+
await this.globalEventBus.emit("import:completed", {
|
|
4022
|
+
repositoryId: result.repositoryId,
|
|
4023
|
+
entitiesImported: result.statistics.entitiesImported,
|
|
4024
|
+
relationshipsImported: result.statistics.relationshipsImported
|
|
4025
|
+
});
|
|
4026
|
+
} else {
|
|
4027
|
+
await this.globalEventBus.emit("import:failed", {
|
|
4028
|
+
repositoryId: result.repositoryId,
|
|
4029
|
+
error: result.warnings.map((w) => w.message).join("; ")
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
4032
|
+
return result;
|
|
4033
|
+
}
|
|
4034
|
+
/** Subscribe to global events */
|
|
4035
|
+
on(event, handler) {
|
|
4036
|
+
return this.globalEventBus.on(event, handler);
|
|
4037
|
+
}
|
|
4038
|
+
/** Update the provenance context (e.g., new conversation) */
|
|
4039
|
+
updateProvenance(context) {
|
|
4040
|
+
this.provenance.updateContext(context);
|
|
4041
|
+
this.globalEventBus.updateProvenance(this.provenance.getContext());
|
|
4042
|
+
}
|
|
4043
|
+
/** Dispose of all resources */
|
|
4044
|
+
async dispose() {
|
|
4045
|
+
this.globalEventBus.removeAllListeners();
|
|
4046
|
+
if (this.graphTraversalProvider?.dispose) {
|
|
4047
|
+
await this.graphTraversalProvider.dispose();
|
|
4048
|
+
}
|
|
4049
|
+
if (this.storage.dispose) {
|
|
4050
|
+
await this.storage.dispose();
|
|
4051
|
+
}
|
|
4052
|
+
this.initialized = false;
|
|
4053
|
+
}
|
|
4054
|
+
};
|
|
4055
|
+
|
|
4056
|
+
// src/relationships/compilers/GremlinCompiler.ts
|
|
4057
|
+
var DEFAULT_ESTIMATED_FANOUT_PER_HOP = 10;
|
|
4058
|
+
var GremlinCompiler = class {
|
|
4059
|
+
language = "gremlin";
|
|
4060
|
+
compile(spec, _vocabulary) {
|
|
4061
|
+
const parts = [];
|
|
4062
|
+
const params = {};
|
|
4063
|
+
let paramIndex = 0;
|
|
4064
|
+
let estimatedFanOut = 1;
|
|
4065
|
+
const nextParam = (value) => {
|
|
4066
|
+
const name = `p${paramIndex++}`;
|
|
4067
|
+
params[name] = value;
|
|
4068
|
+
return name;
|
|
4069
|
+
};
|
|
4070
|
+
parts.push("g.V()");
|
|
4071
|
+
if (spec.start.entityId) {
|
|
4072
|
+
const p = nextParam(spec.start.entityId);
|
|
4073
|
+
parts.push(`.has('id', ${p})`);
|
|
4074
|
+
} else if (spec.start.entityType) {
|
|
4075
|
+
const p = nextParam(spec.start.entityType);
|
|
4076
|
+
parts.push(`.has('entityType', ${p})`);
|
|
4077
|
+
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
4078
|
+
}
|
|
4079
|
+
if (spec.start.filter) {
|
|
4080
|
+
for (const f of spec.start.filter) {
|
|
4081
|
+
parts.push(compilePropertyFilter(f, nextParam));
|
|
4082
|
+
}
|
|
4083
|
+
}
|
|
4084
|
+
const steps = spec.steps ?? [];
|
|
4085
|
+
for (const step of steps) {
|
|
4086
|
+
if (step.repeat) {
|
|
4087
|
+
parts.push(compileRepeatStep(step, nextParam));
|
|
4088
|
+
estimatedFanOut *= step.repeat.maxDepth * DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
4089
|
+
} else if (step.relationshipFilter && step.relationshipFilter.length > 0) {
|
|
4090
|
+
parts.push(compileEdgeStep(step, nextParam));
|
|
4091
|
+
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
4092
|
+
} else {
|
|
4093
|
+
parts.push(compileSimpleStep(step, nextParam));
|
|
4094
|
+
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP;
|
|
4095
|
+
}
|
|
4096
|
+
if (step.entityTypes && step.entityTypes.length > 0) {
|
|
4097
|
+
const typeParams = step.entityTypes.map((t) => nextParam(t));
|
|
4098
|
+
parts.push(`.has('entityType', within(${typeParams.join(", ")}))`);
|
|
4099
|
+
}
|
|
4100
|
+
if (step.entityFilter) {
|
|
4101
|
+
for (const f of step.entityFilter) {
|
|
4102
|
+
parts.push(compilePropertyFilter(f, nextParam));
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
if (spec.returnMode === "all") {
|
|
4107
|
+
}
|
|
4108
|
+
if (spec.dedup !== false) {
|
|
4109
|
+
parts.push(".dedup()");
|
|
4110
|
+
}
|
|
4111
|
+
const limit = spec.limit ?? 50;
|
|
4112
|
+
const offset = spec.offset ?? 0;
|
|
4113
|
+
const pOffset = nextParam(offset);
|
|
4114
|
+
const pEnd = nextParam(offset + limit);
|
|
4115
|
+
parts.push(`.range(${pOffset}, ${pEnd})`);
|
|
4116
|
+
params["_limit"] = limit;
|
|
4117
|
+
params["_offset"] = offset;
|
|
4118
|
+
if (spec.returnMode === "path") {
|
|
4119
|
+
parts.push(".path()");
|
|
4120
|
+
}
|
|
4121
|
+
if (spec.returnMode !== "path") {
|
|
4122
|
+
parts.push(".valueMap(true)");
|
|
4123
|
+
}
|
|
4124
|
+
return {
|
|
4125
|
+
query: parts.join(""),
|
|
4126
|
+
params,
|
|
4127
|
+
estimatedFanOut: Math.min(estimatedFanOut, 1e4)
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
};
|
|
4131
|
+
function compileSimpleStep(step, nextParam) {
|
|
4132
|
+
const types = step.relationshipTypes;
|
|
4133
|
+
const typeArgs = types ? types.map((t) => nextParam(t)).join(", ") : "";
|
|
4134
|
+
switch (step.direction) {
|
|
4135
|
+
case "out":
|
|
4136
|
+
return types ? `.out(${typeArgs})` : ".out()";
|
|
4137
|
+
case "in":
|
|
4138
|
+
return types ? `.in(${typeArgs})` : ".in()";
|
|
4139
|
+
case "both":
|
|
4140
|
+
return types ? `.both(${typeArgs})` : ".both()";
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
function compileEdgeStep(step, nextParam) {
|
|
4144
|
+
const parts = [];
|
|
4145
|
+
const types = step.relationshipTypes;
|
|
4146
|
+
const typeArgs = types ? types.map((t) => nextParam(t)).join(", ") : "";
|
|
4147
|
+
switch (step.direction) {
|
|
4148
|
+
case "out":
|
|
4149
|
+
parts.push(types ? `.outE(${typeArgs})` : ".outE()");
|
|
4150
|
+
break;
|
|
4151
|
+
case "in":
|
|
4152
|
+
parts.push(types ? `.inE(${typeArgs})` : ".inE()");
|
|
4153
|
+
break;
|
|
4154
|
+
case "both":
|
|
4155
|
+
parts.push(types ? `.bothE(${typeArgs})` : ".bothE()");
|
|
4156
|
+
break;
|
|
4157
|
+
}
|
|
4158
|
+
if (step.relationshipFilter) {
|
|
4159
|
+
for (const f of step.relationshipFilter) {
|
|
4160
|
+
parts.push(compilePropertyFilter(f, nextParam));
|
|
4345
4161
|
}
|
|
4346
|
-
return result;
|
|
4347
4162
|
}
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4163
|
+
switch (step.direction) {
|
|
4164
|
+
case "out":
|
|
4165
|
+
parts.push(".inV()");
|
|
4166
|
+
break;
|
|
4167
|
+
case "in":
|
|
4168
|
+
parts.push(".outV()");
|
|
4169
|
+
break;
|
|
4170
|
+
case "both":
|
|
4171
|
+
parts.push(".otherV()");
|
|
4172
|
+
break;
|
|
4351
4173
|
}
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4174
|
+
return parts.join("");
|
|
4175
|
+
}
|
|
4176
|
+
function compileRepeatStep(step, nextParam) {
|
|
4177
|
+
const parts = [];
|
|
4178
|
+
const innerStep = step.relationshipFilter?.length ? compileEdgeStep({ ...step, repeat: void 0 }, nextParam) : compileSimpleStep(step, nextParam);
|
|
4179
|
+
if (step.repeat?.emitIntermediates !== false) {
|
|
4180
|
+
parts.push(".emit()");
|
|
4356
4181
|
}
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4182
|
+
parts.push(`.repeat(${innerStep.startsWith(".") ? `__${innerStep}` : innerStep})`);
|
|
4183
|
+
if (step.repeat?.until && step.repeat.until.length > 0) {
|
|
4184
|
+
const untilParts = step.repeat.until.map((f) => compilePropertyFilter(f, nextParam));
|
|
4185
|
+
parts.push(`.until(${untilParts.join("")})`);
|
|
4186
|
+
}
|
|
4187
|
+
if (step.repeat?.maxDepth) {
|
|
4188
|
+
const p = nextParam(step.repeat.maxDepth);
|
|
4189
|
+
parts.push(`.times(${p})`);
|
|
4190
|
+
}
|
|
4191
|
+
if (step.repeat?.emitIntermediates === false) {
|
|
4192
|
+
parts.push(".emit()");
|
|
4193
|
+
}
|
|
4194
|
+
return parts.join("");
|
|
4195
|
+
}
|
|
4196
|
+
function compilePropertyFilter(filter, nextParam) {
|
|
4197
|
+
const key = nextParam(filter.key);
|
|
4198
|
+
switch (filter.operator) {
|
|
4199
|
+
case "eq": {
|
|
4200
|
+
const val = nextParam(filter.value);
|
|
4201
|
+
return `.has(${key}, ${val})`;
|
|
4362
4202
|
}
|
|
4363
|
-
|
|
4364
|
-
|
|
4203
|
+
case "neq": {
|
|
4204
|
+
const val = nextParam(filter.value);
|
|
4205
|
+
return `.has(${key}, neq(${val}))`;
|
|
4365
4206
|
}
|
|
4366
|
-
|
|
4207
|
+
case "gt": {
|
|
4208
|
+
const val = nextParam(filter.value);
|
|
4209
|
+
return `.has(${key}, gt(${val}))`;
|
|
4210
|
+
}
|
|
4211
|
+
case "gte": {
|
|
4212
|
+
const val = nextParam(filter.value);
|
|
4213
|
+
return `.has(${key}, gte(${val}))`;
|
|
4214
|
+
}
|
|
4215
|
+
case "lt": {
|
|
4216
|
+
const val = nextParam(filter.value);
|
|
4217
|
+
return `.has(${key}, lt(${val}))`;
|
|
4218
|
+
}
|
|
4219
|
+
case "lte": {
|
|
4220
|
+
const val = nextParam(filter.value);
|
|
4221
|
+
return `.has(${key}, lte(${val}))`;
|
|
4222
|
+
}
|
|
4223
|
+
case "contains": {
|
|
4224
|
+
const val = nextParam(filter.value);
|
|
4225
|
+
return `.has(${key}, containing(${val}))`;
|
|
4226
|
+
}
|
|
4227
|
+
case "isNull":
|
|
4228
|
+
return `.hasNot(${key})`;
|
|
4229
|
+
case "isNotNull":
|
|
4230
|
+
return `.has(${key})`;
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
|
|
4234
|
+
// src/relationships/compilers/CypherCompiler.ts
|
|
4235
|
+
var DEFAULT_ESTIMATED_FANOUT_PER_HOP2 = 10;
|
|
4236
|
+
var CypherCompiler = class {
|
|
4237
|
+
language = "cypher";
|
|
4238
|
+
compile(spec, _vocabulary) {
|
|
4239
|
+
const params = {};
|
|
4240
|
+
let paramIndex = 0;
|
|
4241
|
+
let estimatedFanOut = 1;
|
|
4242
|
+
const whereClauses = [];
|
|
4243
|
+
let nodeIndex = 0;
|
|
4244
|
+
const nextParam = (value) => {
|
|
4245
|
+
const name = `p${paramIndex++}`;
|
|
4246
|
+
params[name] = value;
|
|
4247
|
+
return `$${name}`;
|
|
4248
|
+
};
|
|
4249
|
+
const startNode = `n${nodeIndex++}`;
|
|
4250
|
+
let matchParts = [];
|
|
4251
|
+
if (spec.start.entityId) {
|
|
4252
|
+
matchParts.push(`(${startNode})`);
|
|
4253
|
+
whereClauses.push(`${startNode}.id = ${nextParam(spec.start.entityId)}`);
|
|
4254
|
+
} else if (spec.start.entityType) {
|
|
4255
|
+
matchParts.push(`(${startNode})`);
|
|
4256
|
+
whereClauses.push(`${startNode}.entityType = ${nextParam(spec.start.entityType)}`);
|
|
4257
|
+
estimatedFanOut *= DEFAULT_ESTIMATED_FANOUT_PER_HOP2;
|
|
4258
|
+
} else {
|
|
4259
|
+
matchParts.push(`(${startNode})`);
|
|
4260
|
+
}
|
|
4261
|
+
if (spec.start.filter) {
|
|
4262
|
+
for (const f of spec.start.filter) {
|
|
4263
|
+
whereClauses.push(compilePropertyFilterCypher(startNode, f, nextParam));
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
let lastNode = startNode;
|
|
4267
|
+
const steps = spec.steps ?? [];
|
|
4268
|
+
for (let i = 0; i < steps.length; i++) {
|
|
4269
|
+
const step = steps[i];
|
|
4270
|
+
const targetNode = `n${nodeIndex++}`;
|
|
4271
|
+
const relAlias = `r${i}`;
|
|
4272
|
+
const relTypes = step.relationshipTypes?.length ? step.relationshipTypes.join("|") : "";
|
|
4273
|
+
const relTypePattern = relTypes ? `:${relTypes}` : "";
|
|
4274
|
+
const depthPattern = step.repeat ? `*1..${step.repeat.maxDepth}` : "";
|
|
4275
|
+
let pattern;
|
|
4276
|
+
switch (step.direction) {
|
|
4277
|
+
case "out":
|
|
4278
|
+
pattern = `-[${relAlias}${relTypePattern}${depthPattern}]->(${targetNode})`;
|
|
4279
|
+
break;
|
|
4280
|
+
case "in":
|
|
4281
|
+
pattern = `<-[${relAlias}${relTypePattern}${depthPattern}]-(${targetNode})`;
|
|
4282
|
+
break;
|
|
4283
|
+
case "both":
|
|
4284
|
+
pattern = `-[${relAlias}${relTypePattern}${depthPattern}]-(${targetNode})`;
|
|
4285
|
+
break;
|
|
4286
|
+
}
|
|
4287
|
+
matchParts.push(pattern);
|
|
4288
|
+
estimatedFanOut *= step.repeat ? step.repeat.maxDepth * DEFAULT_ESTIMATED_FANOUT_PER_HOP2 : DEFAULT_ESTIMATED_FANOUT_PER_HOP2;
|
|
4289
|
+
if (step.entityTypes && step.entityTypes.length > 0) {
|
|
4290
|
+
const typeParam = nextParam(step.entityTypes);
|
|
4291
|
+
whereClauses.push(`${targetNode}.entityType IN ${typeParam}`);
|
|
4292
|
+
}
|
|
4293
|
+
if (step.entityFilter) {
|
|
4294
|
+
for (const f of step.entityFilter) {
|
|
4295
|
+
whereClauses.push(compilePropertyFilterCypher(targetNode, f, nextParam));
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
if (step.relationshipFilter) {
|
|
4299
|
+
for (const f of step.relationshipFilter) {
|
|
4300
|
+
whereClauses.push(compilePropertyFilterCypher(relAlias, f, nextParam));
|
|
4301
|
+
}
|
|
4302
|
+
}
|
|
4303
|
+
lastNode = targetNode;
|
|
4304
|
+
}
|
|
4305
|
+
const matchClause = `MATCH ${matchParts[0]}${matchParts.slice(1).join("")}`;
|
|
4306
|
+
const whereClause = whereClauses.length > 0 ? `
|
|
4307
|
+
WHERE ${whereClauses.join(" AND ")}` : "";
|
|
4308
|
+
let returnClause;
|
|
4309
|
+
if (spec.returnMode === "path") {
|
|
4310
|
+
const allNodes = Array.from({ length: nodeIndex }, (_, i) => `n${i}`);
|
|
4311
|
+
const allRels = steps.map((_, i) => `r${i}`);
|
|
4312
|
+
returnClause = `RETURN ${[...allNodes, ...allRels].join(", ")}`;
|
|
4313
|
+
} else if (spec.returnMode === "all") {
|
|
4314
|
+
const allNodes = Array.from({ length: nodeIndex }, (_, i) => `n${i}`);
|
|
4315
|
+
returnClause = spec.dedup !== false ? `RETURN DISTINCT ${allNodes.join(", ")}` : `RETURN ${allNodes.join(", ")}`;
|
|
4316
|
+
} else {
|
|
4317
|
+
returnClause = spec.dedup !== false ? `RETURN DISTINCT ${lastNode}` : `RETURN ${lastNode}`;
|
|
4318
|
+
}
|
|
4319
|
+
const offset = spec.offset ?? 0;
|
|
4320
|
+
const limit = spec.limit ?? 50;
|
|
4321
|
+
const skipClause = offset > 0 ? `
|
|
4322
|
+
SKIP ${nextParam(offset)}` : "";
|
|
4323
|
+
const limitClause = `
|
|
4324
|
+
LIMIT ${nextParam(limit)}`;
|
|
4325
|
+
params["_limit"] = limit;
|
|
4326
|
+
params["_offset"] = offset;
|
|
4327
|
+
const query = `${matchClause}${whereClause}
|
|
4328
|
+
${returnClause}${skipClause}${limitClause}`;
|
|
4329
|
+
return {
|
|
4330
|
+
query,
|
|
4331
|
+
params,
|
|
4332
|
+
estimatedFanOut: Math.min(estimatedFanOut, 1e4)
|
|
4333
|
+
};
|
|
4367
4334
|
}
|
|
4368
4335
|
};
|
|
4336
|
+
function compilePropertyFilterCypher(nodeAlias, filter, nextParam) {
|
|
4337
|
+
const prop = `${nodeAlias}.${filter.key}`;
|
|
4338
|
+
switch (filter.operator) {
|
|
4339
|
+
case "eq":
|
|
4340
|
+
return `${prop} = ${nextParam(filter.value)}`;
|
|
4341
|
+
case "neq":
|
|
4342
|
+
return `${prop} <> ${nextParam(filter.value)}`;
|
|
4343
|
+
case "gt":
|
|
4344
|
+
return `${prop} > ${nextParam(filter.value)}`;
|
|
4345
|
+
case "gte":
|
|
4346
|
+
return `${prop} >= ${nextParam(filter.value)}`;
|
|
4347
|
+
case "lt":
|
|
4348
|
+
return `${prop} < ${nextParam(filter.value)}`;
|
|
4349
|
+
case "lte":
|
|
4350
|
+
return `${prop} <= ${nextParam(filter.value)}`;
|
|
4351
|
+
case "contains":
|
|
4352
|
+
return `${prop} CONTAINS ${nextParam(filter.value)}`;
|
|
4353
|
+
case "isNull":
|
|
4354
|
+
return `${prop} IS NULL`;
|
|
4355
|
+
case "isNotNull":
|
|
4356
|
+
return `${prop} IS NOT NULL`;
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4369
4359
|
|
|
4370
4360
|
// src/providers-builtin/InMemoryStorageProvider.ts
|
|
4371
4361
|
var InMemoryStorageProvider = class {
|
|
@@ -5099,6 +5089,7 @@ export {
|
|
|
5099
5089
|
VocabularyValidationError,
|
|
5100
5090
|
generateId,
|
|
5101
5091
|
isValidUuid,
|
|
5102
|
-
matchesPropertyFilters
|
|
5092
|
+
matchesPropertyFilters,
|
|
5093
|
+
projectEntity
|
|
5103
5094
|
};
|
|
5104
5095
|
//# sourceMappingURL=index.js.map
|