@nicia-ai/typegraph 0.12.0 → 0.14.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/postgres/index.cjs +28 -28
- package/dist/backend/postgres/index.d.cts +1 -1
- package/dist/backend/postgres/index.d.ts +1 -1
- package/dist/backend/postgres/index.js +4 -4
- package/dist/backend/sqlite/index.cjs +14 -14
- 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/backend/sqlite/local.cjs +7 -7
- package/dist/backend/sqlite/local.d.cts +1 -1
- package/dist/backend/sqlite/local.d.ts +1 -1
- package/dist/backend/sqlite/local.js +4 -4
- package/dist/{chunk-U3452TEU.js → chunk-6GWJH6AR.js} +15 -27
- package/dist/chunk-6GWJH6AR.js.map +1 -0
- package/dist/{chunk-52WSY6G5.js → chunk-BNIBR5U2.js} +70 -31
- package/dist/chunk-BNIBR5U2.js.map +1 -0
- package/dist/{chunk-54WJF3DW.js → chunk-GNIYZKBI.js} +29 -3
- package/dist/chunk-GNIYZKBI.js.map +1 -0
- package/dist/{chunk-2XPKLHHH.cjs → chunk-KE2BL3JZ.cjs} +74 -35
- package/dist/chunk-KE2BL3JZ.cjs.map +1 -0
- package/dist/{chunk-PYV4ADC6.js → chunk-KLOSTZDQ.js} +141 -13
- package/dist/chunk-KLOSTZDQ.js.map +1 -0
- package/dist/{chunk-JQDWEX6V.cjs → chunk-LELLOHJK.cjs} +22 -34
- package/dist/chunk-LELLOHJK.cjs.map +1 -0
- package/dist/{chunk-2WVFEIHR.cjs → chunk-MME3H4ZF.cjs} +40 -2
- package/dist/chunk-MME3H4ZF.cjs.map +1 -0
- package/dist/{chunk-NZMKJHE2.cjs → chunk-OEKH5PWL.cjs} +15 -15
- package/dist/{chunk-NZMKJHE2.cjs.map → chunk-OEKH5PWL.cjs.map} +1 -1
- package/dist/{chunk-7VITUTRA.cjs → chunk-QFZ5QB2J.cjs} +140 -12
- package/dist/chunk-QFZ5QB2J.cjs.map +1 -0
- package/dist/{chunk-J4SICP3X.js → chunk-RVUEBUBH.js} +3 -3
- package/dist/{chunk-J4SICP3X.js.map → chunk-RVUEBUBH.js.map} +1 -1
- package/dist/index.cjs +483 -597
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -9
- package/dist/index.d.ts +12 -9
- package/dist/index.js +445 -559
- package/dist/index.js.map +1 -1
- package/dist/indexes/index.cjs +16 -16
- package/dist/indexes/index.js +2 -2
- package/dist/interchange/index.d.cts +3 -3
- package/dist/interchange/index.d.ts +3 -3
- package/dist/{manager-DGSnJa1v.d.cts → manager-oh2mTMvy.d.cts} +1 -1
- package/dist/{manager-BCLhWysp.d.ts → manager-qRSdnKEO.d.ts} +1 -1
- package/dist/profiler/index.cjs +6 -6
- package/dist/profiler/index.cjs.map +1 -1
- package/dist/profiler/index.d.cts +3 -3
- package/dist/profiler/index.d.ts +3 -3
- package/dist/profiler/index.js +6 -6
- package/dist/profiler/index.js.map +1 -1
- package/dist/schema/index.cjs +20 -20
- package/dist/schema/index.d.cts +4 -4
- package/dist/schema/index.d.ts +4 -4
- package/dist/schema/index.js +2 -2
- package/dist/{store-BcnA11lH.d.ts → store-B9ItxA-Q.d.ts} +56 -17
- package/dist/{store-NEa4EFFD.d.cts → store-BJPIoe8u.d.cts} +56 -17
- package/dist/{types-1YJKodRv.d.ts → types-5t_MIcvv.d.ts} +12 -6
- package/dist/{types-GLkwvQvS.d.cts → types-Ckfwgv9l.d.cts} +12 -6
- package/package.json +1 -1
- package/dist/chunk-2WVFEIHR.cjs.map +0 -1
- package/dist/chunk-2XPKLHHH.cjs.map +0 -1
- package/dist/chunk-52WSY6G5.js.map +0 -1
- package/dist/chunk-54WJF3DW.js.map +0 -1
- package/dist/chunk-7VITUTRA.cjs.map +0 -1
- package/dist/chunk-JQDWEX6V.cjs.map +0 -1
- package/dist/chunk-PYV4ADC6.js.map +0 -1
- package/dist/chunk-U3452TEU.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,18 +1,68 @@
|
|
|
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-
|
|
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-KLOSTZDQ.js';
|
|
2
|
+
export { isMetaEdge } from './chunk-KLOSTZDQ.js';
|
|
3
3
|
import { NODE_TYPE_BRAND, EDGE_TYPE_BRAND, nowIso, validateOptionalIsoDate, getNodeKinds, getEdgeKinds } from './chunk-IRFD3MEU.js';
|
|
4
4
|
export { defineGraph, getEdgeKinds, getNodeKinds, isEdgeType, isEdgeTypeWithEndpoints, isGraphDef, isNodeType } from './chunk-IRFD3MEU.js';
|
|
5
|
-
import { ConfigurationError, UnsupportedPredicateError, ValidationError, CompilerInvariantError, KindNotFoundError,
|
|
5
|
+
import { ConfigurationError, UnsupportedPredicateError, ValidationError, CompilerInvariantError, KindNotFoundError, DatabaseOperationError, EdgeNotFoundError, NodeConstraintNotFoundError, RestrictedDeleteError, NodeNotFoundError, EndpointNotFoundError, UniquenessError, CardinalityError, EndpointError, DisjointError } from './chunk-SJ2QMDXY.js';
|
|
6
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
|
-
import { getDialect, NODE_META_KEYS, EDGE_META_KEYS } from './chunk-
|
|
7
|
+
import { MAX_PG_IDENTIFIER_LENGTH, DEFAULT_PAGINATION_LIMIT, getDialect, DEFAULT_STREAM_BATCH_SIZE, NODE_META_KEYS, EDGE_META_KEYS, SQLITE_PATH_DELIMITER, PG_ARRAY_START, PG_ARRAY_END, PG_PATH_ELEMENT_SEPARATOR, fnv1aBase36 } from './chunk-GNIYZKBI.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';
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
import { sql, Placeholder } from 'drizzle-orm';
|
|
12
12
|
import { nanoid } from 'nanoid';
|
|
13
13
|
|
|
14
|
+
// src/store/reserved-keys.ts
|
|
15
|
+
var RESERVED_NODE_KEYS = /* @__PURE__ */ new Set([
|
|
16
|
+
"id",
|
|
17
|
+
"kind",
|
|
18
|
+
"meta"
|
|
19
|
+
]);
|
|
20
|
+
var RESERVED_EDGE_KEYS = /* @__PURE__ */ new Set([
|
|
21
|
+
"id",
|
|
22
|
+
"kind",
|
|
23
|
+
"meta",
|
|
24
|
+
"fromKind",
|
|
25
|
+
"fromId",
|
|
26
|
+
"toKind",
|
|
27
|
+
"toId"
|
|
28
|
+
]);
|
|
29
|
+
var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
|
|
30
|
+
"__proto__",
|
|
31
|
+
"constructor",
|
|
32
|
+
"prototype"
|
|
33
|
+
]);
|
|
34
|
+
function validateProjectionField(field2, entityType, kind) {
|
|
35
|
+
const reserved = entityType === "node" ? RESERVED_NODE_KEYS : RESERVED_EDGE_KEYS;
|
|
36
|
+
if (reserved.has(field2)) {
|
|
37
|
+
throw new ConfigurationError(
|
|
38
|
+
`Projection field "${field2}" on ${entityType} kind "${kind}" conflicts with a reserved structural key`,
|
|
39
|
+
{ field: field2, kind, entityType, reservedKeys: [...reserved] },
|
|
40
|
+
{
|
|
41
|
+
suggestion: `Remove "${field2}" from the projection. Structural fields (${[...reserved].join(", ")}) are included automatically when relevant.`
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (PROTOTYPE_POLLUTION_KEYS.has(field2)) {
|
|
46
|
+
throw new ConfigurationError(
|
|
47
|
+
`Projection field "${field2}" on ${entityType} kind "${kind}" is not allowed`,
|
|
48
|
+
{ field: field2, kind, entityType },
|
|
49
|
+
{
|
|
50
|
+
suggestion: `"${field2}" cannot be used as a projection field name.`
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function filterReservedKeys(props, reservedKeys) {
|
|
56
|
+
const filtered = {};
|
|
57
|
+
for (const [key, value] of Object.entries(props)) {
|
|
58
|
+
if (!reservedKeys.has(key)) {
|
|
59
|
+
filtered[key] = value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return filtered;
|
|
63
|
+
}
|
|
64
|
+
|
|
14
65
|
// src/core/node.ts
|
|
15
|
-
var RESERVED_NODE_KEYS = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
|
|
16
66
|
function validateSchemaKeys(schema, name) {
|
|
17
67
|
const shape = schema.shape;
|
|
18
68
|
const conflicts = Object.keys(shape).filter(
|
|
@@ -37,15 +87,6 @@ function defineNode(name, options) {
|
|
|
37
87
|
description: options.description
|
|
38
88
|
});
|
|
39
89
|
}
|
|
40
|
-
var RESERVED_EDGE_KEYS = /* @__PURE__ */ new Set([
|
|
41
|
-
"id",
|
|
42
|
-
"kind",
|
|
43
|
-
"meta",
|
|
44
|
-
"fromKind",
|
|
45
|
-
"fromId",
|
|
46
|
-
"toKind",
|
|
47
|
-
"toId"
|
|
48
|
-
]);
|
|
49
90
|
var EMPTY_SCHEMA = z.object({});
|
|
50
91
|
function validateSchemaKeys2(schema, name) {
|
|
51
92
|
const shape = schema.shape;
|
|
@@ -1376,14 +1417,14 @@ function extractVectorSimilarityPredicates(predicates) {
|
|
|
1376
1417
|
break;
|
|
1377
1418
|
}
|
|
1378
1419
|
case "and": {
|
|
1379
|
-
for (const
|
|
1380
|
-
visit(
|
|
1420
|
+
for (const predicate2 of expr.predicates) {
|
|
1421
|
+
visit(predicate2, inDisallowedBranch);
|
|
1381
1422
|
}
|
|
1382
1423
|
break;
|
|
1383
1424
|
}
|
|
1384
1425
|
case "or": {
|
|
1385
|
-
for (const
|
|
1386
|
-
visit(
|
|
1426
|
+
for (const predicate2 of expr.predicates) {
|
|
1427
|
+
visit(predicate2, true);
|
|
1387
1428
|
}
|
|
1388
1429
|
break;
|
|
1389
1430
|
}
|
|
@@ -2406,6 +2447,9 @@ function compileTemporalFilter(options) {
|
|
|
2406
2447
|
return sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${now}) AND (${validTo} IS NULL OR ${validTo} > ${now})`;
|
|
2407
2448
|
}
|
|
2408
2449
|
case "asOf": {
|
|
2450
|
+
if (asOf === void 0) {
|
|
2451
|
+
throw new Error(`asOf timestamp is required for temporal mode "asOf"`);
|
|
2452
|
+
}
|
|
2409
2453
|
const timestamp = asOf;
|
|
2410
2454
|
return sql`${deletedAt} IS NULL AND (${validFrom} IS NULL OR ${validFrom} <= ${timestamp}) AND (${validTo} IS NULL OR ${validTo} > ${timestamp})`;
|
|
2411
2455
|
}
|
|
@@ -2813,7 +2857,7 @@ function lowerSetOperationToLogicalPlan(input) {
|
|
|
2813
2857
|
}
|
|
2814
2858
|
|
|
2815
2859
|
// src/query/compiler/recursive.ts
|
|
2816
|
-
var MAX_RECURSIVE_DEPTH =
|
|
2860
|
+
var MAX_RECURSIVE_DEPTH = 10;
|
|
2817
2861
|
var MAX_EXPLICIT_RECURSIVE_DEPTH = 1e3;
|
|
2818
2862
|
var NO_ALWAYS_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
|
|
2819
2863
|
function runRecursiveQueryPassPipeline(ast, graphId, ctx) {
|
|
@@ -3306,15 +3350,14 @@ var DEFAULT_TABLE_NAMES = {
|
|
|
3306
3350
|
edges: "typegraph_edges",
|
|
3307
3351
|
embeddings: "typegraph_node_embeddings"
|
|
3308
3352
|
};
|
|
3309
|
-
var MAX_IDENTIFIER_LENGTH = 63;
|
|
3310
3353
|
var VALID_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_$]*$/i;
|
|
3311
3354
|
function validateTableName(name, label) {
|
|
3312
3355
|
if (!name || name.length === 0) {
|
|
3313
3356
|
throw new ConfigurationError(`${label} table name cannot be empty`);
|
|
3314
3357
|
}
|
|
3315
|
-
if (name.length >
|
|
3358
|
+
if (name.length > MAX_PG_IDENTIFIER_LENGTH) {
|
|
3316
3359
|
throw new ConfigurationError(
|
|
3317
|
-
`${label} table name exceeds maximum length of ${
|
|
3360
|
+
`${label} table name exceeds maximum length of ${MAX_PG_IDENTIFIER_LENGTH} characters`
|
|
3318
3361
|
);
|
|
3319
3362
|
}
|
|
3320
3363
|
if (!VALID_IDENTIFIER_PATTERN.test(name)) {
|
|
@@ -3397,64 +3440,13 @@ function decodeByValueType(value, valueType) {
|
|
|
3397
3440
|
}
|
|
3398
3441
|
}
|
|
3399
3442
|
|
|
3400
|
-
// src/store/reserved-keys.ts
|
|
3401
|
-
var RESERVED_NODE_KEYS2 = /* @__PURE__ */ new Set([
|
|
3402
|
-
"id",
|
|
3403
|
-
"kind",
|
|
3404
|
-
"meta"
|
|
3405
|
-
]);
|
|
3406
|
-
var RESERVED_EDGE_KEYS2 = /* @__PURE__ */ new Set([
|
|
3407
|
-
"id",
|
|
3408
|
-
"kind",
|
|
3409
|
-
"meta",
|
|
3410
|
-
"fromKind",
|
|
3411
|
-
"fromId",
|
|
3412
|
-
"toKind",
|
|
3413
|
-
"toId"
|
|
3414
|
-
]);
|
|
3415
|
-
var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
|
|
3416
|
-
"__proto__",
|
|
3417
|
-
"constructor",
|
|
3418
|
-
"prototype"
|
|
3419
|
-
]);
|
|
3420
|
-
function validateProjectionField(field2, entityType, kind) {
|
|
3421
|
-
const reserved = entityType === "node" ? RESERVED_NODE_KEYS2 : RESERVED_EDGE_KEYS2;
|
|
3422
|
-
if (reserved.has(field2)) {
|
|
3423
|
-
throw new ConfigurationError(
|
|
3424
|
-
`Projection field "${field2}" on ${entityType} kind "${kind}" conflicts with a reserved structural key`,
|
|
3425
|
-
{ field: field2, kind, entityType, reservedKeys: [...reserved] },
|
|
3426
|
-
{
|
|
3427
|
-
suggestion: `Remove "${field2}" from the projection. Structural fields (${[...reserved].join(", ")}) are included automatically when relevant.`
|
|
3428
|
-
}
|
|
3429
|
-
);
|
|
3430
|
-
}
|
|
3431
|
-
if (PROTOTYPE_POLLUTION_KEYS.has(field2)) {
|
|
3432
|
-
throw new ConfigurationError(
|
|
3433
|
-
`Projection field "${field2}" on ${entityType} kind "${kind}" is not allowed`,
|
|
3434
|
-
{ field: field2, kind, entityType },
|
|
3435
|
-
{
|
|
3436
|
-
suggestion: `"${field2}" cannot be used as a projection field name.`
|
|
3437
|
-
}
|
|
3438
|
-
);
|
|
3439
|
-
}
|
|
3440
|
-
}
|
|
3441
|
-
function filterReservedKeys(props, reservedKeys) {
|
|
3442
|
-
const filtered = {};
|
|
3443
|
-
for (const [key, value] of Object.entries(props)) {
|
|
3444
|
-
if (!reservedKeys.has(key)) {
|
|
3445
|
-
filtered[key] = value;
|
|
3446
|
-
}
|
|
3447
|
-
}
|
|
3448
|
-
return filtered;
|
|
3449
|
-
}
|
|
3450
|
-
|
|
3451
3443
|
// src/store/row-mappers.ts
|
|
3452
3444
|
function nullToUndefined2(value) {
|
|
3453
3445
|
return value === null ? void 0 : value;
|
|
3454
3446
|
}
|
|
3455
3447
|
function rowToNode(row) {
|
|
3456
3448
|
const rawProps = JSON.parse(row.props);
|
|
3457
|
-
const props = filterReservedKeys(rawProps,
|
|
3449
|
+
const props = filterReservedKeys(rawProps, RESERVED_NODE_KEYS);
|
|
3458
3450
|
return {
|
|
3459
3451
|
kind: row.kind,
|
|
3460
3452
|
id: row.id,
|
|
@@ -3474,7 +3466,7 @@ function rowToNodeMeta(row) {
|
|
|
3474
3466
|
}
|
|
3475
3467
|
function rowToEdge(row) {
|
|
3476
3468
|
const rawProps = JSON.parse(row.props);
|
|
3477
|
-
const props = filterReservedKeys(rawProps,
|
|
3469
|
+
const props = filterReservedKeys(rawProps, RESERVED_EDGE_KEYS);
|
|
3478
3470
|
return {
|
|
3479
3471
|
id: row.id,
|
|
3480
3472
|
kind: row.kind,
|
|
@@ -3498,17 +3490,6 @@ function rowToEdgeMeta(row) {
|
|
|
3498
3490
|
|
|
3499
3491
|
// src/store/subgraph.ts
|
|
3500
3492
|
var DEFAULT_SUBGRAPH_MAX_DEPTH = 10;
|
|
3501
|
-
var MAX_PG_IDENTIFIER_LENGTH = 63;
|
|
3502
|
-
function fnv1aBase36(input) {
|
|
3503
|
-
let hash = 2166136261;
|
|
3504
|
-
for (const character of input) {
|
|
3505
|
-
const codePoint = character.codePointAt(0);
|
|
3506
|
-
if (codePoint === void 0) continue;
|
|
3507
|
-
hash ^= codePoint;
|
|
3508
|
-
hash = Math.imul(hash, 16777619);
|
|
3509
|
-
}
|
|
3510
|
-
return (hash >>> 0).toString(36);
|
|
3511
|
-
}
|
|
3512
3493
|
var TEXT_ENCODER = new TextEncoder();
|
|
3513
3494
|
function truncateToBytes(value, maxBytes) {
|
|
3514
3495
|
const encoded = TEXT_ENCODER.encode(value);
|
|
@@ -3540,7 +3521,7 @@ async function executeSubgraph(params) {
|
|
|
3540
3521
|
}
|
|
3541
3522
|
const maxDepth = Math.min(
|
|
3542
3523
|
options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
|
|
3543
|
-
|
|
3524
|
+
MAX_EXPLICIT_RECURSIVE_DEPTH
|
|
3544
3525
|
);
|
|
3545
3526
|
const ctx = {
|
|
3546
3527
|
graphId: params.graphId,
|
|
@@ -4224,6 +4205,7 @@ function compileFieldColumnForSetOp(field2, prefix, dialect) {
|
|
|
4224
4205
|
updated_at: "_updated_at",
|
|
4225
4206
|
deleted_at: "_deleted_at"
|
|
4226
4207
|
};
|
|
4208
|
+
if (columnName === void 0) return sql.raw(`${cteName}.${alias}_props`);
|
|
4227
4209
|
const suffix = columnMap[columnName];
|
|
4228
4210
|
if (suffix) {
|
|
4229
4211
|
return sql.raw(`${cteName}.${alias}${suffix}`);
|
|
@@ -4302,18 +4284,18 @@ function buildSetOperationSuffixClauses(op, dialect) {
|
|
|
4302
4284
|
);
|
|
4303
4285
|
}
|
|
4304
4286
|
const orderParts = [];
|
|
4305
|
-
for (const
|
|
4306
|
-
const projected = matchFieldToProjection(
|
|
4287
|
+
for (const orderSpec of op.orderBy) {
|
|
4288
|
+
const projected = matchFieldToProjection(orderSpec.field, projection);
|
|
4307
4289
|
if (!projected) {
|
|
4308
|
-
const fieldDesc =
|
|
4290
|
+
const fieldDesc = orderSpec.field.jsonPointer ? `${orderSpec.field.alias}.props${orderSpec.field.jsonPointer}` : `${orderSpec.field.alias}.${orderSpec.field.path.join(".")}`;
|
|
4309
4291
|
const availableFields = projection.fields.map((f) => f.outputName).join(", ");
|
|
4310
4292
|
throw new UnsupportedPredicateError(
|
|
4311
4293
|
`Set operation ORDER BY field "${fieldDesc}" is not in the projection. ORDER BY for UNION/INTERSECT/EXCEPT must reference projected columns. Available columns: ${availableFields}`
|
|
4312
4294
|
);
|
|
4313
4295
|
}
|
|
4314
4296
|
const columnRef = sql.raw(dialect.quoteIdentifier(projected.outputName));
|
|
4315
|
-
const dir = sql.raw(
|
|
4316
|
-
const nulls =
|
|
4297
|
+
const dir = sql.raw(orderSpec.direction.toUpperCase());
|
|
4298
|
+
const nulls = orderSpec.nulls ?? (orderSpec.direction === "asc" ? "last" : "first");
|
|
4317
4299
|
const nullsDir = sql.raw(nulls === "first" ? "DESC" : "ASC");
|
|
4318
4300
|
orderParts.push(
|
|
4319
4301
|
sql`(${columnRef} IS NULL) ${nullsDir}`,
|
|
@@ -5180,13 +5162,14 @@ function generateId() {
|
|
|
5180
5162
|
|
|
5181
5163
|
// src/utils/path.ts
|
|
5182
5164
|
function parseSqlitePath(path) {
|
|
5183
|
-
|
|
5165
|
+
const emptyPath = `${SQLITE_PATH_DELIMITER}${SQLITE_PATH_DELIMITER}`;
|
|
5166
|
+
if (!path || path === emptyPath) return [];
|
|
5184
5167
|
const trimmed = path.slice(1, -1);
|
|
5185
5168
|
if (trimmed === "") return [];
|
|
5186
|
-
return trimmed.split(
|
|
5169
|
+
return trimmed.split(SQLITE_PATH_DELIMITER);
|
|
5187
5170
|
}
|
|
5188
5171
|
function isSqlitePath(value) {
|
|
5189
|
-
return typeof value === "string" && value.startsWith(
|
|
5172
|
+
return typeof value === "string" && value.startsWith(SQLITE_PATH_DELIMITER) && value.endsWith(SQLITE_PATH_DELIMITER);
|
|
5190
5173
|
}
|
|
5191
5174
|
function normalizePath(value) {
|
|
5192
5175
|
if (Array.isArray(value)) {
|
|
@@ -5201,20 +5184,20 @@ function normalizePath(value) {
|
|
|
5201
5184
|
return [];
|
|
5202
5185
|
}
|
|
5203
5186
|
function isPostgresTextArray(value) {
|
|
5204
|
-
return typeof value === "string" && value.startsWith(
|
|
5187
|
+
return typeof value === "string" && value.startsWith(PG_ARRAY_START) && value.endsWith(PG_ARRAY_END);
|
|
5205
5188
|
}
|
|
5206
5189
|
function parsePostgresTextArray(value) {
|
|
5207
5190
|
const inner = value.slice(1, -1);
|
|
5208
5191
|
if (inner === "") return [];
|
|
5209
|
-
return inner.split(
|
|
5192
|
+
return inner.split(PG_PATH_ELEMENT_SEPARATOR);
|
|
5210
5193
|
}
|
|
5211
5194
|
|
|
5212
5195
|
// src/query/execution/result-mapper.ts
|
|
5213
5196
|
function transformPathColumns(rows, state, _dialect) {
|
|
5214
5197
|
const pathAliases = [];
|
|
5215
|
-
for (const
|
|
5216
|
-
if (
|
|
5217
|
-
pathAliases.push(
|
|
5198
|
+
for (const traversal of state.traversals) {
|
|
5199
|
+
if (traversal.variableLength?.pathAlias !== void 0) {
|
|
5200
|
+
pathAliases.push(traversal.variableLength.pathAlias);
|
|
5218
5201
|
}
|
|
5219
5202
|
}
|
|
5220
5203
|
if (pathAliases.length === 0) return rows;
|
|
@@ -5238,8 +5221,8 @@ function transformPathColumns(rows, state, _dialect) {
|
|
|
5238
5221
|
}
|
|
5239
5222
|
return changed ? result : rows;
|
|
5240
5223
|
}
|
|
5241
|
-
var
|
|
5242
|
-
var
|
|
5224
|
+
var RESERVED_NODE_KEYS2 = /* @__PURE__ */ new Set(["id", "kind", "meta"]);
|
|
5225
|
+
var RESERVED_EDGE_KEYS2 = /* @__PURE__ */ new Set(["id", "kind", "fromId", "toId", "meta"]);
|
|
5243
5226
|
function nullToUndefined3(value) {
|
|
5244
5227
|
return value === null ? void 0 : value;
|
|
5245
5228
|
}
|
|
@@ -5277,7 +5260,7 @@ function buildSelectableNode(row, alias) {
|
|
|
5277
5260
|
deletedAt
|
|
5278
5261
|
}
|
|
5279
5262
|
};
|
|
5280
|
-
assignPropsExcludingReserved(result, rawProps,
|
|
5263
|
+
assignPropsExcludingReserved(result, rawProps, RESERVED_NODE_KEYS2);
|
|
5281
5264
|
return result;
|
|
5282
5265
|
}
|
|
5283
5266
|
function buildSelectableNodeOrUndefined(row, alias) {
|
|
@@ -5319,7 +5302,7 @@ function buildSelectableEdge(row, alias) {
|
|
|
5319
5302
|
deletedAt
|
|
5320
5303
|
}
|
|
5321
5304
|
};
|
|
5322
|
-
assignPropsExcludingReserved(result, rawProps,
|
|
5305
|
+
assignPropsExcludingReserved(result, rawProps, RESERVED_EDGE_KEYS2);
|
|
5323
5306
|
return result;
|
|
5324
5307
|
}
|
|
5325
5308
|
function buildSelectContext(row, startAlias, traversals) {
|
|
@@ -5447,7 +5430,7 @@ async function* createStreamIterable(batchSize, paginate) {
|
|
|
5447
5430
|
}
|
|
5448
5431
|
}
|
|
5449
5432
|
function getStreamBatchSize(options) {
|
|
5450
|
-
return options?.batchSize ??
|
|
5433
|
+
return options?.batchSize ?? DEFAULT_STREAM_BATCH_SIZE;
|
|
5451
5434
|
}
|
|
5452
5435
|
|
|
5453
5436
|
// src/query/ast.ts
|
|
@@ -5859,6 +5842,9 @@ function buildSelectiveContext(row, plans, traversals) {
|
|
|
5859
5842
|
return context;
|
|
5860
5843
|
}
|
|
5861
5844
|
function buildOptionalAliasValue(row, plan) {
|
|
5845
|
+
if (plan.idOutputName === void 0) {
|
|
5846
|
+
return void 0;
|
|
5847
|
+
}
|
|
5862
5848
|
const idValue = row[plan.idOutputName];
|
|
5863
5849
|
if (idValue === null || idValue === void 0) {
|
|
5864
5850
|
return void 0;
|
|
@@ -7335,7 +7321,7 @@ var ExecutableQuery = class _ExecutableQuery {
|
|
|
7335
7321
|
);
|
|
7336
7322
|
}
|
|
7337
7323
|
const isBackward = options.last !== void 0 || options.before !== void 0;
|
|
7338
|
-
const limit = options.first ?? options.last ??
|
|
7324
|
+
const limit = options.first ?? options.last ?? DEFAULT_PAGINATION_LIMIT;
|
|
7339
7325
|
const cursor = options.after ?? options.before;
|
|
7340
7326
|
let cursorData;
|
|
7341
7327
|
if (cursor) {
|
|
@@ -7658,7 +7644,8 @@ var TraversalBuilder = class _TraversalBuilder {
|
|
|
7658
7644
|
}
|
|
7659
7645
|
/**
|
|
7660
7646
|
* Enables variable-length (recursive) traversal.
|
|
7661
|
-
*
|
|
7647
|
+
* Defaults to MAX_RECURSIVE_DEPTH (10) hops with cycle prevention.
|
|
7648
|
+
* Use `maxHops` to override (up to MAX_EXPLICIT_RECURSIVE_DEPTH).
|
|
7662
7649
|
*/
|
|
7663
7650
|
recursive(options) {
|
|
7664
7651
|
const minDepth = options?.minHops ?? this.#variableLength.minDepth;
|
|
@@ -8919,6 +8906,35 @@ function createEdgeCollection(config) {
|
|
|
8919
8906
|
executeHardDelete: executeEdgeHardDelete2,
|
|
8920
8907
|
matchesTemporalMode
|
|
8921
8908
|
} = config;
|
|
8909
|
+
const mapRows = (rows) => rows.map((row) => narrowEdge(rowToEdge2(row)));
|
|
8910
|
+
async function findEdgesFrom(from, target) {
|
|
8911
|
+
const rows = await target.findEdgesByKind({
|
|
8912
|
+
graphId,
|
|
8913
|
+
kind,
|
|
8914
|
+
fromKind: from.kind,
|
|
8915
|
+
fromId: from.id,
|
|
8916
|
+
excludeDeleted: true
|
|
8917
|
+
});
|
|
8918
|
+
return mapRows(rows);
|
|
8919
|
+
}
|
|
8920
|
+
async function findEdgesTo(to, target) {
|
|
8921
|
+
const rows = await target.findEdgesByKind({
|
|
8922
|
+
graphId,
|
|
8923
|
+
kind,
|
|
8924
|
+
toKind: to.kind,
|
|
8925
|
+
toId: to.id,
|
|
8926
|
+
excludeDeleted: true
|
|
8927
|
+
});
|
|
8928
|
+
return mapRows(rows);
|
|
8929
|
+
}
|
|
8930
|
+
function buildFindByEndpointsOptions(options) {
|
|
8931
|
+
const result = {};
|
|
8932
|
+
if (options?.matchOn !== void 0)
|
|
8933
|
+
result.matchOn = options.matchOn;
|
|
8934
|
+
if (options?.props !== void 0)
|
|
8935
|
+
result.props = options.props;
|
|
8936
|
+
return result;
|
|
8937
|
+
}
|
|
8922
8938
|
return {
|
|
8923
8939
|
async create(from, to, props, options) {
|
|
8924
8940
|
const result = await executeEdgeCreate2(
|
|
@@ -8974,24 +8990,32 @@ function createEdgeCollection(config) {
|
|
|
8974
8990
|
return narrowEdge(result);
|
|
8975
8991
|
},
|
|
8976
8992
|
async findFrom(from) {
|
|
8977
|
-
|
|
8978
|
-
graphId,
|
|
8979
|
-
kind,
|
|
8980
|
-
fromKind: from.kind,
|
|
8981
|
-
fromId: from.id,
|
|
8982
|
-
excludeDeleted: true
|
|
8983
|
-
});
|
|
8984
|
-
return rows.map((row) => narrowEdge(rowToEdge2(row)));
|
|
8993
|
+
return findEdgesFrom(from, backend);
|
|
8985
8994
|
},
|
|
8986
8995
|
async findTo(to) {
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
}
|
|
8994
|
-
|
|
8996
|
+
return findEdgesTo(to, backend);
|
|
8997
|
+
},
|
|
8998
|
+
batchFindFrom(from) {
|
|
8999
|
+
return { executeOn: (target) => findEdgesFrom(from, target) };
|
|
9000
|
+
},
|
|
9001
|
+
batchFindTo(to) {
|
|
9002
|
+
return { executeOn: (target) => findEdgesTo(to, target) };
|
|
9003
|
+
},
|
|
9004
|
+
batchFindByEndpoints(from, to, options) {
|
|
9005
|
+
return {
|
|
9006
|
+
executeOn: async (target) => {
|
|
9007
|
+
const result = await config.executeFindByEndpoints(
|
|
9008
|
+
kind,
|
|
9009
|
+
from.kind,
|
|
9010
|
+
from.id,
|
|
9011
|
+
to.kind,
|
|
9012
|
+
to.id,
|
|
9013
|
+
target,
|
|
9014
|
+
buildFindByEndpointsOptions(options)
|
|
9015
|
+
);
|
|
9016
|
+
return result === void 0 ? [] : [narrowEdge(result)];
|
|
9017
|
+
}
|
|
9018
|
+
};
|
|
8995
9019
|
},
|
|
8996
9020
|
async delete(id) {
|
|
8997
9021
|
await executeEdgeDelete2(id, backend);
|
|
@@ -9025,7 +9049,7 @@ function createEdgeCollection(config) {
|
|
|
9025
9049
|
if (options?.limit !== void 0) params.limit = options.limit;
|
|
9026
9050
|
if (options?.offset !== void 0) params.offset = options.offset;
|
|
9027
9051
|
const rows = await backend.findEdgesByKind(params);
|
|
9028
|
-
return rows
|
|
9052
|
+
return mapRows(rows);
|
|
9029
9053
|
},
|
|
9030
9054
|
async count(options) {
|
|
9031
9055
|
const mode = options?.temporalMode ?? defaultTemporalMode;
|
|
@@ -9154,11 +9178,6 @@ function createEdgeCollection(config) {
|
|
|
9154
9178
|
await deleteAll(backend);
|
|
9155
9179
|
},
|
|
9156
9180
|
async findByEndpoints(from, to, options) {
|
|
9157
|
-
const findOptions = {};
|
|
9158
|
-
if (options?.matchOn !== void 0)
|
|
9159
|
-
findOptions.matchOn = options.matchOn;
|
|
9160
|
-
if (options?.props !== void 0)
|
|
9161
|
-
findOptions.props = options.props;
|
|
9162
9181
|
const result = await config.executeFindByEndpoints(
|
|
9163
9182
|
kind,
|
|
9164
9183
|
from.kind,
|
|
@@ -9166,7 +9185,7 @@ function createEdgeCollection(config) {
|
|
|
9166
9185
|
to.kind,
|
|
9167
9186
|
to.id,
|
|
9168
9187
|
backend,
|
|
9169
|
-
|
|
9188
|
+
buildFindByEndpointsOptions(options)
|
|
9170
9189
|
);
|
|
9171
9190
|
return result === void 0 ? void 0 : narrowEdge(result);
|
|
9172
9191
|
},
|
|
@@ -10400,6 +10419,9 @@ async function executeEdgeGetOrCreateByEndpoints(ctx, kind, fromKind, fromId, to
|
|
|
10400
10419
|
return { edge: edge2, action: "updated" };
|
|
10401
10420
|
}
|
|
10402
10421
|
const cardinality = registration.cardinality ?? "many";
|
|
10422
|
+
if (deletedRow === void 0) {
|
|
10423
|
+
throw new Error("Expected deletedRow to be defined");
|
|
10424
|
+
}
|
|
10403
10425
|
const matchedDeletedRow = deletedRow;
|
|
10404
10426
|
const effectiveValidTo = matchedDeletedRow.valid_to;
|
|
10405
10427
|
const constraintContext = {
|
|
@@ -10519,6 +10541,9 @@ async function executeEdgeBulkGetOrCreateByEndpoints(ctx, kind, items, backend,
|
|
|
10519
10541
|
});
|
|
10520
10542
|
} else {
|
|
10521
10543
|
const bestRow = liveRow ?? deletedRow;
|
|
10544
|
+
if (bestRow === void 0) {
|
|
10545
|
+
throw new Error("Expected at least one of liveRow or deletedRow");
|
|
10546
|
+
}
|
|
10522
10547
|
toFetch.push({
|
|
10523
10548
|
index,
|
|
10524
10549
|
row: bestRow,
|
|
@@ -10819,11 +10844,12 @@ function getNodeRegistration(graph, kind) {
|
|
|
10819
10844
|
if (registration === void 0) throw new KindNotFoundError(kind, "node");
|
|
10820
10845
|
return registration;
|
|
10821
10846
|
}
|
|
10847
|
+
var CACHE_KEY_SEPARATOR = "\0";
|
|
10822
10848
|
function buildNodeCacheKey(graphId, kind, id) {
|
|
10823
|
-
return `${graphId}
|
|
10849
|
+
return `${graphId}${CACHE_KEY_SEPARATOR}${kind}${CACHE_KEY_SEPARATOR}${id}`;
|
|
10824
10850
|
}
|
|
10825
10851
|
function buildUniqueCacheKey(graphId, nodeKind, constraintName, key) {
|
|
10826
|
-
return `${graphId}
|
|
10852
|
+
return `${graphId}${CACHE_KEY_SEPARATOR}${nodeKind}${CACHE_KEY_SEPARATOR}${constraintName}${CACHE_KEY_SEPARATOR}${key}`;
|
|
10827
10853
|
}
|
|
10828
10854
|
function createNodeAlreadyExistsError(kind, id) {
|
|
10829
10855
|
return new ValidationError(
|
|
@@ -10860,6 +10886,23 @@ function createPendingUniqueRow(graphId, nodeKind, constraintName, key, nodeId)
|
|
|
10860
10886
|
deleted_at: void 0
|
|
10861
10887
|
};
|
|
10862
10888
|
}
|
|
10889
|
+
function resolveConstraint(graph, kind, constraintName) {
|
|
10890
|
+
const registration = getNodeRegistration(graph, kind);
|
|
10891
|
+
const constraints = registration.unique ?? [];
|
|
10892
|
+
const constraint = constraints.find(
|
|
10893
|
+
(candidate) => candidate.name === constraintName
|
|
10894
|
+
);
|
|
10895
|
+
if (constraint === void 0) {
|
|
10896
|
+
throw new NodeConstraintNotFoundError(constraintName, kind);
|
|
10897
|
+
}
|
|
10898
|
+
return constraint;
|
|
10899
|
+
}
|
|
10900
|
+
function createUniquenessContext(graphId, registry, backend) {
|
|
10901
|
+
return { graphId, registry, backend };
|
|
10902
|
+
}
|
|
10903
|
+
function createEmbeddingSyncContext(graphId, nodeKind, nodeId, backend) {
|
|
10904
|
+
return { graphId, nodeKind, nodeId, backend };
|
|
10905
|
+
}
|
|
10863
10906
|
function createNodeBatchValidationBackend(graphId, registry, backend) {
|
|
10864
10907
|
const nodeCache = /* @__PURE__ */ new Map();
|
|
10865
10908
|
const pendingNodes = /* @__PURE__ */ new Map();
|
|
@@ -10868,12 +10911,8 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
|
|
|
10868
10911
|
async function getNodeCached(lookupGraphId, kind, id) {
|
|
10869
10912
|
const cacheKey = buildNodeCacheKey(lookupGraphId, kind, id);
|
|
10870
10913
|
const pendingNode = pendingNodes.get(cacheKey);
|
|
10871
|
-
if (pendingNode !== void 0)
|
|
10872
|
-
|
|
10873
|
-
}
|
|
10874
|
-
if (nodeCache.has(cacheKey)) {
|
|
10875
|
-
return nodeCache.get(cacheKey);
|
|
10876
|
-
}
|
|
10914
|
+
if (pendingNode !== void 0) return pendingNode;
|
|
10915
|
+
if (nodeCache.has(cacheKey)) return nodeCache.get(cacheKey);
|
|
10877
10916
|
const existing = await backend.getNode(lookupGraphId, kind, id);
|
|
10878
10917
|
nodeCache.set(cacheKey, existing);
|
|
10879
10918
|
return existing;
|
|
@@ -10895,16 +10934,14 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
|
|
|
10895
10934
|
pendingOwner
|
|
10896
10935
|
);
|
|
10897
10936
|
}
|
|
10898
|
-
if (uniqueCache.has(cacheKey))
|
|
10899
|
-
return uniqueCache.get(cacheKey);
|
|
10900
|
-
}
|
|
10937
|
+
if (uniqueCache.has(cacheKey)) return uniqueCache.get(cacheKey);
|
|
10901
10938
|
const existing = await backend.checkUnique(params);
|
|
10902
10939
|
uniqueCache.set(cacheKey, existing);
|
|
10903
10940
|
return existing;
|
|
10904
10941
|
}
|
|
10905
10942
|
function registerPendingNode(params) {
|
|
10906
10943
|
const cacheKey = buildNodeCacheKey(params.graphId, params.kind, params.id);
|
|
10907
|
-
|
|
10944
|
+
pendingNodes.set(cacheKey, {
|
|
10908
10945
|
graph_id: params.graphId,
|
|
10909
10946
|
kind: params.kind,
|
|
10910
10947
|
id: params.id,
|
|
@@ -10915,14 +10952,11 @@ function createNodeBatchValidationBackend(graphId, registry, backend) {
|
|
|
10915
10952
|
created_at: "",
|
|
10916
10953
|
updated_at: "",
|
|
10917
10954
|
deleted_at: void 0
|
|
10918
|
-
};
|
|
10919
|
-
pendingNodes.set(cacheKey, pendingNode);
|
|
10955
|
+
});
|
|
10920
10956
|
}
|
|
10921
10957
|
function registerPendingUniqueEntries(kind, id, props, constraints) {
|
|
10922
10958
|
for (const constraint of constraints) {
|
|
10923
|
-
if (!checkWherePredicate(constraint, props))
|
|
10924
|
-
continue;
|
|
10925
|
-
}
|
|
10959
|
+
if (!checkWherePredicate(constraint, props)) continue;
|
|
10926
10960
|
const key = computeUniqueKey(
|
|
10927
10961
|
props,
|
|
10928
10962
|
constraint.fields,
|
|
@@ -10984,14 +11018,9 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend) {
|
|
|
10984
11018
|
backend
|
|
10985
11019
|
};
|
|
10986
11020
|
await checkDisjointnessConstraint(constraintContext, kind, id);
|
|
10987
|
-
const uniquenessContext = {
|
|
10988
|
-
graphId: ctx.graphId,
|
|
10989
|
-
registry: ctx.registry,
|
|
10990
|
-
backend
|
|
10991
|
-
};
|
|
10992
11021
|
const uniqueConstraints = registration.unique ?? [];
|
|
10993
11022
|
await checkUniquenessConstraints(
|
|
10994
|
-
|
|
11023
|
+
createUniquenessContext(ctx.graphId, ctx.registry, backend),
|
|
10995
11024
|
kind,
|
|
10996
11025
|
id,
|
|
10997
11026
|
validatedProps,
|
|
@@ -11014,64 +11043,99 @@ async function validateAndPrepareNodeCreate(ctx, input, id, backend) {
|
|
|
11014
11043
|
};
|
|
11015
11044
|
}
|
|
11016
11045
|
async function finalizeNodeCreate(ctx, prepared, backend) {
|
|
11017
|
-
const uniquenessContext = {
|
|
11018
|
-
graphId: ctx.graphId,
|
|
11019
|
-
registry: ctx.registry,
|
|
11020
|
-
backend
|
|
11021
|
-
};
|
|
11022
11046
|
await insertUniquenessEntries(
|
|
11023
|
-
|
|
11047
|
+
createUniquenessContext(ctx.graphId, ctx.registry, backend),
|
|
11024
11048
|
prepared.kind,
|
|
11025
11049
|
prepared.id,
|
|
11026
11050
|
prepared.validatedProps,
|
|
11027
11051
|
prepared.uniqueConstraints
|
|
11028
11052
|
);
|
|
11029
|
-
const embeddingSyncContext = {
|
|
11030
|
-
graphId: ctx.graphId,
|
|
11031
|
-
nodeKind: prepared.kind,
|
|
11032
|
-
nodeId: prepared.id,
|
|
11033
|
-
backend
|
|
11034
|
-
};
|
|
11035
11053
|
await syncEmbeddings(
|
|
11036
|
-
|
|
11054
|
+
createEmbeddingSyncContext(
|
|
11055
|
+
ctx.graphId,
|
|
11056
|
+
prepared.kind,
|
|
11057
|
+
prepared.id,
|
|
11058
|
+
backend
|
|
11059
|
+
),
|
|
11037
11060
|
prepared.nodeKind.schema,
|
|
11038
11061
|
prepared.validatedProps
|
|
11039
11062
|
);
|
|
11040
11063
|
}
|
|
11041
|
-
async function
|
|
11042
|
-
const kind = input
|
|
11043
|
-
const
|
|
11044
|
-
const
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
}
|
|
11056
|
-
await finalizeNodeCreate(ctx, prepared, backend);
|
|
11057
|
-
if (row === void 0) return;
|
|
11058
|
-
return rowToNode(row);
|
|
11064
|
+
async function performNodeUpdate(ctx, input, backend, options) {
|
|
11065
|
+
const { kind, id } = input;
|
|
11066
|
+
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11067
|
+
const existing = await backend.getNode(ctx.graphId, kind, id);
|
|
11068
|
+
if (!existing || existing.deleted_at && !options?.clearDeleted) {
|
|
11069
|
+
throw new NodeNotFoundError(kind, id);
|
|
11070
|
+
}
|
|
11071
|
+
const existingProps = JSON.parse(existing.props);
|
|
11072
|
+
const mergedProps = { ...existingProps, ...input.props };
|
|
11073
|
+
const nodeKind = registration.type;
|
|
11074
|
+
const validatedProps = validateNodeProps(nodeKind.schema, mergedProps, {
|
|
11075
|
+
kind,
|
|
11076
|
+
operation: "update",
|
|
11077
|
+
id
|
|
11059
11078
|
});
|
|
11079
|
+
const validTo = validateOptionalIsoDate(input.validTo, "validTo");
|
|
11080
|
+
await updateUniquenessEntries(
|
|
11081
|
+
createUniquenessContext(ctx.graphId, ctx.registry, backend),
|
|
11082
|
+
kind,
|
|
11083
|
+
id,
|
|
11084
|
+
existingProps,
|
|
11085
|
+
validatedProps,
|
|
11086
|
+
registration.unique ?? []
|
|
11087
|
+
);
|
|
11088
|
+
const updateParams = {
|
|
11089
|
+
graphId: ctx.graphId,
|
|
11090
|
+
kind,
|
|
11091
|
+
id,
|
|
11092
|
+
props: validatedProps,
|
|
11093
|
+
incrementVersion: true
|
|
11094
|
+
};
|
|
11095
|
+
if (validTo !== void 0) updateParams.validTo = validTo;
|
|
11096
|
+
if (options?.clearDeleted) updateParams.clearDeleted = true;
|
|
11097
|
+
const row = await backend.updateNode(updateParams);
|
|
11098
|
+
await syncEmbeddings(
|
|
11099
|
+
createEmbeddingSyncContext(ctx.graphId, kind, id, backend),
|
|
11100
|
+
nodeKind.schema,
|
|
11101
|
+
validatedProps
|
|
11102
|
+
);
|
|
11103
|
+
return rowToNode(row);
|
|
11060
11104
|
}
|
|
11061
|
-
async function
|
|
11062
|
-
const
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11105
|
+
async function enforceDeleteBehavior(ctx, kind, id, mode, backend, registration) {
|
|
11106
|
+
const deleteBehavior = registration.onDelete ?? "restrict";
|
|
11107
|
+
const connectedEdges = await backend.findEdgesConnectedTo({
|
|
11108
|
+
graphId: ctx.graphId,
|
|
11109
|
+
nodeKind: kind,
|
|
11110
|
+
nodeId: id
|
|
11111
|
+
});
|
|
11112
|
+
if (connectedEdges.length === 0) return;
|
|
11113
|
+
switch (deleteBehavior) {
|
|
11114
|
+
case "restrict": {
|
|
11115
|
+
const edgeKinds = [...new Set(connectedEdges.map((edge) => edge.kind))];
|
|
11116
|
+
throw new RestrictedDeleteError({
|
|
11117
|
+
nodeKind: kind,
|
|
11118
|
+
nodeId: id,
|
|
11119
|
+
edgeCount: connectedEdges.length,
|
|
11120
|
+
edgeKinds
|
|
11121
|
+
});
|
|
11122
|
+
}
|
|
11123
|
+
case "cascade":
|
|
11124
|
+
case "disconnect": {
|
|
11125
|
+
for (const edge of connectedEdges) {
|
|
11126
|
+
await (mode === "hard" ? backend.hardDeleteEdge({
|
|
11127
|
+
graphId: ctx.graphId,
|
|
11128
|
+
id: edge.id
|
|
11129
|
+
}) : backend.deleteEdge({
|
|
11130
|
+
graphId: ctx.graphId,
|
|
11131
|
+
id: edge.id
|
|
11132
|
+
}));
|
|
11133
|
+
}
|
|
11134
|
+
break;
|
|
11135
|
+
}
|
|
11068
11136
|
}
|
|
11069
|
-
return result;
|
|
11070
11137
|
}
|
|
11071
|
-
async function
|
|
11072
|
-
if (inputs.length === 0) {
|
|
11073
|
-
return;
|
|
11074
|
-
}
|
|
11138
|
+
async function prepareBatchCreates(ctx, inputs, backend) {
|
|
11075
11139
|
const {
|
|
11076
11140
|
backend: validationBackend,
|
|
11077
11141
|
registerPendingNode,
|
|
@@ -11098,46 +11162,109 @@ async function executeNodeCreateNoReturnBatch(ctx, inputs, backend) {
|
|
|
11098
11162
|
const batchInsertParams = preparedCreates.map(
|
|
11099
11163
|
(prepared) => prepared.insertParams
|
|
11100
11164
|
);
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
|
|
11165
|
+
return { preparedCreates, batchInsertParams };
|
|
11166
|
+
}
|
|
11167
|
+
async function findUniqueRowAcrossKinds(backend, graphId, constraintName, key, kindsToCheck, includeDeleted) {
|
|
11168
|
+
for (const kindToCheck of kindsToCheck) {
|
|
11169
|
+
const row = await backend.checkUnique({
|
|
11170
|
+
graphId,
|
|
11171
|
+
nodeKind: kindToCheck,
|
|
11172
|
+
constraintName,
|
|
11173
|
+
key,
|
|
11174
|
+
includeDeleted
|
|
11175
|
+
});
|
|
11176
|
+
if (row !== void 0) return row;
|
|
11110
11177
|
}
|
|
11178
|
+
return void 0;
|
|
11111
11179
|
}
|
|
11112
|
-
async function
|
|
11113
|
-
|
|
11114
|
-
|
|
11180
|
+
async function batchCheckUniqueAcrossKinds(backend, graphId, constraintName, uniqueKeys, kindsToCheck, includeDeleted) {
|
|
11181
|
+
const existingByKey = /* @__PURE__ */ new Map();
|
|
11182
|
+
for (const kindToCheck of kindsToCheck) {
|
|
11183
|
+
if (backend.checkUniqueBatch === void 0) {
|
|
11184
|
+
for (const key of uniqueKeys) {
|
|
11185
|
+
if (existingByKey.has(key)) continue;
|
|
11186
|
+
const row = await backend.checkUnique({
|
|
11187
|
+
graphId,
|
|
11188
|
+
nodeKind: kindToCheck,
|
|
11189
|
+
constraintName,
|
|
11190
|
+
key,
|
|
11191
|
+
includeDeleted
|
|
11192
|
+
});
|
|
11193
|
+
if (row !== void 0) {
|
|
11194
|
+
existingByKey.set(row.key, row);
|
|
11195
|
+
}
|
|
11196
|
+
}
|
|
11197
|
+
} else {
|
|
11198
|
+
const rows = await backend.checkUniqueBatch({
|
|
11199
|
+
graphId,
|
|
11200
|
+
nodeKind: kindToCheck,
|
|
11201
|
+
constraintName,
|
|
11202
|
+
keys: uniqueKeys,
|
|
11203
|
+
includeDeleted
|
|
11204
|
+
});
|
|
11205
|
+
for (const row of rows) {
|
|
11206
|
+
if (!existingByKey.has(row.key)) {
|
|
11207
|
+
existingByKey.set(row.key, row);
|
|
11208
|
+
}
|
|
11209
|
+
}
|
|
11210
|
+
}
|
|
11115
11211
|
}
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
const
|
|
11122
|
-
|
|
11123
|
-
const id = input.id ?? generateId();
|
|
11212
|
+
return existingByKey;
|
|
11213
|
+
}
|
|
11214
|
+
async function executeNodeCreateInternal(ctx, input, backend, options) {
|
|
11215
|
+
const kind = input.kind;
|
|
11216
|
+
const id = input.id ?? generateId();
|
|
11217
|
+
const opContext = ctx.createOperationContext("create", "node", kind, id);
|
|
11218
|
+
return ctx.withOperationHooks(opContext, async () => {
|
|
11124
11219
|
const prepared = await validateAndPrepareNodeCreate(
|
|
11125
11220
|
ctx,
|
|
11126
11221
|
input,
|
|
11127
11222
|
id,
|
|
11128
|
-
|
|
11223
|
+
backend
|
|
11129
11224
|
);
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11225
|
+
let row;
|
|
11226
|
+
{
|
|
11227
|
+
row = await backend.insertNode(prepared.insertParams);
|
|
11228
|
+
}
|
|
11229
|
+
await finalizeNodeCreate(ctx, prepared, backend);
|
|
11230
|
+
if (row === void 0) return;
|
|
11231
|
+
return rowToNode(row);
|
|
11232
|
+
});
|
|
11233
|
+
}
|
|
11234
|
+
async function executeNodeCreate(ctx, input, backend) {
|
|
11235
|
+
const result = await executeNodeCreateInternal(ctx, input, backend);
|
|
11236
|
+
if (!result) {
|
|
11237
|
+
throw new DatabaseOperationError(
|
|
11238
|
+
"Node create failed: expected created node row",
|
|
11239
|
+
{ operation: "insert", entity: "node" }
|
|
11137
11240
|
);
|
|
11138
11241
|
}
|
|
11139
|
-
|
|
11140
|
-
|
|
11242
|
+
return result;
|
|
11243
|
+
}
|
|
11244
|
+
async function executeNodeCreateNoReturnBatch(ctx, inputs, backend) {
|
|
11245
|
+
if (inputs.length === 0) return;
|
|
11246
|
+
const { preparedCreates, batchInsertParams } = await prepareBatchCreates(
|
|
11247
|
+
ctx,
|
|
11248
|
+
inputs,
|
|
11249
|
+
backend
|
|
11250
|
+
);
|
|
11251
|
+
if (backend.insertNodesBatch === void 0) {
|
|
11252
|
+
for (const insertParams of batchInsertParams) {
|
|
11253
|
+
await (backend.insertNodeNoReturn?.(insertParams) ?? backend.insertNode(insertParams));
|
|
11254
|
+
}
|
|
11255
|
+
} else {
|
|
11256
|
+
await backend.insertNodesBatch(batchInsertParams);
|
|
11257
|
+
}
|
|
11258
|
+
for (const prepared of preparedCreates) {
|
|
11259
|
+
await finalizeNodeCreate(ctx, prepared, backend);
|
|
11260
|
+
}
|
|
11261
|
+
}
|
|
11262
|
+
async function executeNodeCreateBatch(ctx, inputs, backend) {
|
|
11263
|
+
if (inputs.length === 0) return [];
|
|
11264
|
+
const { preparedCreates, batchInsertParams } = await prepareBatchCreates(
|
|
11265
|
+
ctx,
|
|
11266
|
+
inputs,
|
|
11267
|
+
backend
|
|
11141
11268
|
);
|
|
11142
11269
|
let rows;
|
|
11143
11270
|
if (backend.insertNodesBatchReturning === void 0) {
|
|
@@ -11155,170 +11282,40 @@ async function executeNodeCreateBatch(ctx, inputs, backend) {
|
|
|
11155
11282
|
return rows.map((row) => rowToNode(row));
|
|
11156
11283
|
}
|
|
11157
11284
|
async function executeNodeUpdate(ctx, input, backend, options) {
|
|
11158
|
-
const
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
const mergedProps = { ...existingProps, ...input.props };
|
|
11169
|
-
const nodeKind = registration.type;
|
|
11170
|
-
const validatedProps = validateNodeProps(nodeKind.schema, mergedProps, {
|
|
11171
|
-
kind,
|
|
11172
|
-
operation: "update",
|
|
11173
|
-
id
|
|
11174
|
-
});
|
|
11175
|
-
const validTo = validateOptionalIsoDate(input.validTo, "validTo");
|
|
11176
|
-
const uniquenessContext = {
|
|
11177
|
-
graphId: ctx.graphId,
|
|
11178
|
-
registry: ctx.registry,
|
|
11179
|
-
backend
|
|
11180
|
-
};
|
|
11181
|
-
await updateUniquenessEntries(
|
|
11182
|
-
uniquenessContext,
|
|
11183
|
-
kind,
|
|
11184
|
-
id,
|
|
11185
|
-
existingProps,
|
|
11186
|
-
validatedProps,
|
|
11187
|
-
registration.unique ?? []
|
|
11188
|
-
);
|
|
11189
|
-
const updateParams = {
|
|
11190
|
-
graphId: ctx.graphId,
|
|
11191
|
-
kind,
|
|
11192
|
-
id,
|
|
11193
|
-
props: validatedProps,
|
|
11194
|
-
incrementVersion: true
|
|
11195
|
-
};
|
|
11196
|
-
if (validTo !== void 0) updateParams.validTo = validTo;
|
|
11197
|
-
if (options?.clearDeleted) updateParams.clearDeleted = true;
|
|
11198
|
-
const row = await backend.updateNode(updateParams);
|
|
11199
|
-
const embeddingSyncContext = {
|
|
11200
|
-
graphId: ctx.graphId,
|
|
11201
|
-
nodeKind: kind,
|
|
11202
|
-
nodeId: id,
|
|
11203
|
-
backend
|
|
11204
|
-
};
|
|
11205
|
-
await syncEmbeddings(embeddingSyncContext, nodeKind.schema, validatedProps);
|
|
11206
|
-
return rowToNode(row);
|
|
11207
|
-
});
|
|
11285
|
+
const opContext = ctx.createOperationContext(
|
|
11286
|
+
"update",
|
|
11287
|
+
"node",
|
|
11288
|
+
input.kind,
|
|
11289
|
+
input.id
|
|
11290
|
+
);
|
|
11291
|
+
return ctx.withOperationHooks(
|
|
11292
|
+
opContext,
|
|
11293
|
+
() => performNodeUpdate(ctx, input, backend, options)
|
|
11294
|
+
);
|
|
11208
11295
|
}
|
|
11209
11296
|
async function executeNodeUpsertUpdate(ctx, input, backend, options) {
|
|
11210
|
-
|
|
11211
|
-
const id = input.id;
|
|
11212
|
-
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11213
|
-
const existing = await backend.getNode(ctx.graphId, kind, id);
|
|
11214
|
-
if (!existing || existing.deleted_at && !options?.clearDeleted) {
|
|
11215
|
-
throw new NodeNotFoundError(kind, id);
|
|
11216
|
-
}
|
|
11217
|
-
const existingProps = JSON.parse(existing.props);
|
|
11218
|
-
const mergedProps = { ...existingProps, ...input.props };
|
|
11219
|
-
const nodeKind = registration.type;
|
|
11220
|
-
const validatedProps = validateNodeProps(nodeKind.schema, mergedProps, {
|
|
11221
|
-
kind,
|
|
11222
|
-
operation: "update",
|
|
11223
|
-
id
|
|
11224
|
-
});
|
|
11225
|
-
const validTo = validateOptionalIsoDate(input.validTo, "validTo");
|
|
11226
|
-
const uniquenessContext = {
|
|
11227
|
-
graphId: ctx.graphId,
|
|
11228
|
-
registry: ctx.registry,
|
|
11229
|
-
backend
|
|
11230
|
-
};
|
|
11231
|
-
await updateUniquenessEntries(
|
|
11232
|
-
uniquenessContext,
|
|
11233
|
-
kind,
|
|
11234
|
-
id,
|
|
11235
|
-
existingProps,
|
|
11236
|
-
validatedProps,
|
|
11237
|
-
registration.unique ?? []
|
|
11238
|
-
);
|
|
11239
|
-
const updateParams = {
|
|
11240
|
-
graphId: ctx.graphId,
|
|
11241
|
-
kind,
|
|
11242
|
-
id,
|
|
11243
|
-
props: validatedProps,
|
|
11244
|
-
incrementVersion: true
|
|
11245
|
-
};
|
|
11246
|
-
if (validTo !== void 0) updateParams.validTo = validTo;
|
|
11247
|
-
if (options?.clearDeleted) updateParams.clearDeleted = true;
|
|
11248
|
-
const row = await backend.updateNode(updateParams);
|
|
11249
|
-
const embeddingSyncContext = {
|
|
11250
|
-
graphId: ctx.graphId,
|
|
11251
|
-
nodeKind: kind,
|
|
11252
|
-
nodeId: id,
|
|
11253
|
-
backend
|
|
11254
|
-
};
|
|
11255
|
-
await syncEmbeddings(embeddingSyncContext, nodeKind.schema, validatedProps);
|
|
11256
|
-
return rowToNode(row);
|
|
11297
|
+
return performNodeUpdate(ctx, input, backend, options);
|
|
11257
11298
|
}
|
|
11258
11299
|
async function executeNodeDelete(ctx, kind, id, backend) {
|
|
11259
11300
|
const opContext = ctx.createOperationContext("delete", "node", kind, id);
|
|
11260
11301
|
return ctx.withOperationHooks(opContext, async () => {
|
|
11261
11302
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11262
11303
|
const existing = await backend.getNode(ctx.graphId, kind, id);
|
|
11263
|
-
if (!existing || existing.deleted_at)
|
|
11264
|
-
return;
|
|
11265
|
-
}
|
|
11304
|
+
if (!existing || existing.deleted_at) return;
|
|
11266
11305
|
const existingProps = JSON.parse(existing.props);
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
graphId: ctx.graphId,
|
|
11270
|
-
nodeKind: kind,
|
|
11271
|
-
nodeId: id
|
|
11272
|
-
});
|
|
11273
|
-
if (connectedEdges.length > 0) {
|
|
11274
|
-
switch (deleteBehavior) {
|
|
11275
|
-
case "restrict": {
|
|
11276
|
-
const edgeKinds = [
|
|
11277
|
-
...new Set(connectedEdges.map((edge) => edge.kind))
|
|
11278
|
-
];
|
|
11279
|
-
throw new RestrictedDeleteError({
|
|
11280
|
-
nodeKind: kind,
|
|
11281
|
-
nodeId: id,
|
|
11282
|
-
edgeCount: connectedEdges.length,
|
|
11283
|
-
edgeKinds
|
|
11284
|
-
});
|
|
11285
|
-
}
|
|
11286
|
-
case "cascade":
|
|
11287
|
-
case "disconnect": {
|
|
11288
|
-
for (const edge of connectedEdges) {
|
|
11289
|
-
await backend.deleteEdge({
|
|
11290
|
-
graphId: ctx.graphId,
|
|
11291
|
-
id: edge.id
|
|
11292
|
-
});
|
|
11293
|
-
}
|
|
11294
|
-
break;
|
|
11295
|
-
}
|
|
11296
|
-
}
|
|
11297
|
-
}
|
|
11298
|
-
await backend.deleteNode({
|
|
11299
|
-
graphId: ctx.graphId,
|
|
11300
|
-
kind,
|
|
11301
|
-
id
|
|
11302
|
-
});
|
|
11303
|
-
const uniquenessContext = {
|
|
11304
|
-
graphId: ctx.graphId,
|
|
11305
|
-
registry: ctx.registry,
|
|
11306
|
-
backend
|
|
11307
|
-
};
|
|
11306
|
+
await enforceDeleteBehavior(ctx, kind, id, "soft", backend, registration);
|
|
11307
|
+
await backend.deleteNode({ graphId: ctx.graphId, kind, id });
|
|
11308
11308
|
await deleteUniquenessEntries(
|
|
11309
|
-
|
|
11309
|
+
createUniquenessContext(ctx.graphId, ctx.registry, backend),
|
|
11310
11310
|
kind,
|
|
11311
11311
|
existingProps,
|
|
11312
11312
|
registration.unique ?? []
|
|
11313
11313
|
);
|
|
11314
11314
|
const nodeKind = registration.type;
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
nodeKind
|
|
11318
|
-
|
|
11319
|
-
backend
|
|
11320
|
-
};
|
|
11321
|
-
await deleteNodeEmbeddings(embeddingSyncContext, nodeKind.schema);
|
|
11315
|
+
await deleteNodeEmbeddings(
|
|
11316
|
+
createEmbeddingSyncContext(ctx.graphId, kind, id, backend),
|
|
11317
|
+
nodeKind.schema
|
|
11318
|
+
);
|
|
11322
11319
|
});
|
|
11323
11320
|
}
|
|
11324
11321
|
async function executeNodeHardDelete(ctx, kind, id, backend) {
|
|
@@ -11326,59 +11323,14 @@ async function executeNodeHardDelete(ctx, kind, id, backend) {
|
|
|
11326
11323
|
return ctx.withOperationHooks(opContext, async () => {
|
|
11327
11324
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11328
11325
|
const existing = await backend.getNode(ctx.graphId, kind, id);
|
|
11329
|
-
if (!existing)
|
|
11330
|
-
|
|
11331
|
-
}
|
|
11332
|
-
const deleteBehavior = registration.onDelete ?? "restrict";
|
|
11333
|
-
const connectedEdges = await backend.findEdgesConnectedTo({
|
|
11334
|
-
graphId: ctx.graphId,
|
|
11335
|
-
nodeKind: kind,
|
|
11336
|
-
nodeId: id
|
|
11337
|
-
});
|
|
11338
|
-
if (connectedEdges.length > 0) {
|
|
11339
|
-
switch (deleteBehavior) {
|
|
11340
|
-
case "restrict": {
|
|
11341
|
-
const edgeKinds = [
|
|
11342
|
-
...new Set(connectedEdges.map((edge) => edge.kind))
|
|
11343
|
-
];
|
|
11344
|
-
throw new RestrictedDeleteError({
|
|
11345
|
-
nodeKind: kind,
|
|
11346
|
-
nodeId: id,
|
|
11347
|
-
edgeCount: connectedEdges.length,
|
|
11348
|
-
edgeKinds
|
|
11349
|
-
});
|
|
11350
|
-
}
|
|
11351
|
-
case "cascade":
|
|
11352
|
-
case "disconnect": {
|
|
11353
|
-
for (const edge of connectedEdges) {
|
|
11354
|
-
await backend.hardDeleteEdge({
|
|
11355
|
-
graphId: ctx.graphId,
|
|
11356
|
-
id: edge.id
|
|
11357
|
-
});
|
|
11358
|
-
}
|
|
11359
|
-
break;
|
|
11360
|
-
}
|
|
11361
|
-
}
|
|
11362
|
-
}
|
|
11326
|
+
if (!existing) return;
|
|
11327
|
+
await enforceDeleteBehavior(ctx, kind, id, "hard", backend, registration);
|
|
11363
11328
|
const hardDelete = async (target) => {
|
|
11364
|
-
await target.hardDeleteNode({
|
|
11365
|
-
graphId: ctx.graphId,
|
|
11366
|
-
kind,
|
|
11367
|
-
id
|
|
11368
|
-
});
|
|
11329
|
+
await target.hardDeleteNode({ graphId: ctx.graphId, kind, id });
|
|
11369
11330
|
};
|
|
11370
11331
|
await ("transaction" in backend && backend.capabilities.transactions ? backend.transaction(async (tx) => hardDelete(tx)) : hardDelete(backend));
|
|
11371
11332
|
});
|
|
11372
11333
|
}
|
|
11373
|
-
function resolveConstraint(graph, kind, constraintName) {
|
|
11374
|
-
const registration = getNodeRegistration(graph, kind);
|
|
11375
|
-
const constraints = registration.unique ?? [];
|
|
11376
|
-
const constraint = constraints.find((c) => c.name === constraintName);
|
|
11377
|
-
if (constraint === void 0) {
|
|
11378
|
-
throw new NodeConstraintNotFoundError(constraintName, kind);
|
|
11379
|
-
}
|
|
11380
|
-
return constraint;
|
|
11381
|
-
}
|
|
11382
11334
|
async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, props, backend, options) {
|
|
11383
11335
|
const ifExists = options?.ifExists ?? "return";
|
|
11384
11336
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
@@ -11389,8 +11341,11 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
|
|
|
11389
11341
|
});
|
|
11390
11342
|
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
11391
11343
|
if (!checkWherePredicate(constraint, validatedProps)) {
|
|
11392
|
-
const
|
|
11393
|
-
|
|
11344
|
+
const node = await executeNodeCreate(
|
|
11345
|
+
ctx,
|
|
11346
|
+
{ kind, props: validatedProps },
|
|
11347
|
+
backend
|
|
11348
|
+
);
|
|
11394
11349
|
return { node, action: "created" };
|
|
11395
11350
|
}
|
|
11396
11351
|
const key = computeUniqueKey(
|
|
@@ -11403,23 +11358,20 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
|
|
|
11403
11358
|
constraint.scope,
|
|
11404
11359
|
ctx.registry
|
|
11405
11360
|
);
|
|
11406
|
-
|
|
11407
|
-
|
|
11408
|
-
|
|
11409
|
-
|
|
11410
|
-
|
|
11411
|
-
|
|
11412
|
-
|
|
11413
|
-
|
|
11414
|
-
});
|
|
11415
|
-
if (row !== void 0) {
|
|
11416
|
-
existingUniqueRow = row;
|
|
11417
|
-
break;
|
|
11418
|
-
}
|
|
11419
|
-
}
|
|
11361
|
+
const existingUniqueRow = await findUniqueRowAcrossKinds(
|
|
11362
|
+
backend,
|
|
11363
|
+
ctx.graphId,
|
|
11364
|
+
constraint.name,
|
|
11365
|
+
key,
|
|
11366
|
+
kindsToCheck,
|
|
11367
|
+
true
|
|
11368
|
+
);
|
|
11420
11369
|
if (existingUniqueRow === void 0) {
|
|
11421
|
-
const
|
|
11422
|
-
|
|
11370
|
+
const node = await executeNodeCreate(
|
|
11371
|
+
ctx,
|
|
11372
|
+
{ kind, props: validatedProps },
|
|
11373
|
+
backend
|
|
11374
|
+
);
|
|
11423
11375
|
return { node, action: "created" };
|
|
11424
11376
|
}
|
|
11425
11377
|
const existingRow = await backend.getNode(
|
|
@@ -11428,8 +11380,11 @@ async function executeNodeGetOrCreateByConstraint(ctx, kind, constraintName, pro
|
|
|
11428
11380
|
existingUniqueRow.node_id
|
|
11429
11381
|
);
|
|
11430
11382
|
if (existingRow === void 0) {
|
|
11431
|
-
const
|
|
11432
|
-
|
|
11383
|
+
const node = await executeNodeCreate(
|
|
11384
|
+
ctx,
|
|
11385
|
+
{ kind, props: validatedProps },
|
|
11386
|
+
backend
|
|
11387
|
+
);
|
|
11433
11388
|
return { node, action: "created" };
|
|
11434
11389
|
}
|
|
11435
11390
|
const isSoftDeleted = existingRow.deleted_at !== void 0;
|
|
@@ -11468,20 +11423,14 @@ async function executeNodeFindByConstraint(ctx, kind, constraintName, props, bac
|
|
|
11468
11423
|
constraint.scope,
|
|
11469
11424
|
ctx.registry
|
|
11470
11425
|
);
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
});
|
|
11480
|
-
if (row !== void 0) {
|
|
11481
|
-
existingUniqueRow = row;
|
|
11482
|
-
break;
|
|
11483
|
-
}
|
|
11484
|
-
}
|
|
11426
|
+
const existingUniqueRow = await findUniqueRowAcrossKinds(
|
|
11427
|
+
backend,
|
|
11428
|
+
ctx.graphId,
|
|
11429
|
+
constraint.name,
|
|
11430
|
+
key,
|
|
11431
|
+
kindsToCheck,
|
|
11432
|
+
false
|
|
11433
|
+
);
|
|
11485
11434
|
if (existingUniqueRow === void 0) return void 0;
|
|
11486
11435
|
const existingRow = await backend.getNode(
|
|
11487
11436
|
ctx.graphId,
|
|
@@ -11492,11 +11441,7 @@ async function executeNodeFindByConstraint(ctx, kind, constraintName, props, bac
|
|
|
11492
11441
|
return void 0;
|
|
11493
11442
|
return rowToNode(existingRow);
|
|
11494
11443
|
}
|
|
11495
|
-
|
|
11496
|
-
if (items.length === 0) return [];
|
|
11497
|
-
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11498
|
-
const nodeKind = registration.type;
|
|
11499
|
-
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
11444
|
+
function validateAndComputeKeys(nodeKind, kind, constraint, items) {
|
|
11500
11445
|
const validated = [];
|
|
11501
11446
|
for (const item of items) {
|
|
11502
11447
|
const validatedProps = validateNodeProps(nodeKind.schema, item.props, {
|
|
@@ -11511,49 +11456,35 @@ async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items,
|
|
|
11511
11456
|
) : void 0;
|
|
11512
11457
|
validated.push({ validatedProps, key });
|
|
11513
11458
|
}
|
|
11514
|
-
|
|
11459
|
+
return validated;
|
|
11460
|
+
}
|
|
11461
|
+
function collectUniqueKeys(validated) {
|
|
11462
|
+
return [
|
|
11515
11463
|
...new Set(
|
|
11516
|
-
validated.map((
|
|
11464
|
+
validated.map((entry) => entry.key).filter((key) => key !== void 0)
|
|
11517
11465
|
)
|
|
11518
11466
|
];
|
|
11467
|
+
}
|
|
11468
|
+
async function executeNodeBulkFindByConstraint(ctx, kind, constraintName, items, backend) {
|
|
11469
|
+
if (items.length === 0) return [];
|
|
11470
|
+
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11471
|
+
const nodeKind = registration.type;
|
|
11472
|
+
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
11473
|
+
const validated = validateAndComputeKeys(nodeKind, kind, constraint, items);
|
|
11474
|
+
const uniqueKeys = collectUniqueKeys(validated);
|
|
11519
11475
|
const kindsToCheck = getKindsForUniquenessCheck(
|
|
11520
11476
|
kind,
|
|
11521
11477
|
constraint.scope,
|
|
11522
11478
|
ctx.registry
|
|
11523
11479
|
);
|
|
11524
|
-
const existingByKey =
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11532
|
-
nodeKind: kindToCheck,
|
|
11533
|
-
constraintName: constraint.name,
|
|
11534
|
-
key,
|
|
11535
|
-
includeDeleted: false
|
|
11536
|
-
});
|
|
11537
|
-
if (row !== void 0) {
|
|
11538
|
-
existingByKey.set(row.key, row);
|
|
11539
|
-
}
|
|
11540
|
-
}
|
|
11541
|
-
} else {
|
|
11542
|
-
const rows = await backend.checkUniqueBatch({
|
|
11543
|
-
graphId: ctx.graphId,
|
|
11544
|
-
nodeKind: kindToCheck,
|
|
11545
|
-
constraintName: constraint.name,
|
|
11546
|
-
keys: uniqueKeys,
|
|
11547
|
-
includeDeleted: false
|
|
11548
|
-
});
|
|
11549
|
-
for (const row of rows) {
|
|
11550
|
-
if (!existingByKey.has(row.key)) {
|
|
11551
|
-
existingByKey.set(row.key, row);
|
|
11552
|
-
}
|
|
11553
|
-
}
|
|
11554
|
-
}
|
|
11555
|
-
}
|
|
11556
|
-
}
|
|
11480
|
+
const existingByKey = uniqueKeys.length > 0 ? await batchCheckUniqueAcrossKinds(
|
|
11481
|
+
backend,
|
|
11482
|
+
ctx.graphId,
|
|
11483
|
+
constraint.name,
|
|
11484
|
+
uniqueKeys,
|
|
11485
|
+
kindsToCheck,
|
|
11486
|
+
false
|
|
11487
|
+
) : /* @__PURE__ */ new Map();
|
|
11557
11488
|
const results = Array.from({ length: items.length });
|
|
11558
11489
|
const seenKeys = /* @__PURE__ */ new Map();
|
|
11559
11490
|
for (const [index, { key }] of validated.entries()) {
|
|
@@ -11591,73 +11522,28 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11591
11522
|
const registration = getNodeRegistration(ctx.graph, kind);
|
|
11592
11523
|
const nodeKind = registration.type;
|
|
11593
11524
|
const constraint = resolveConstraint(ctx.graph, kind, constraintName);
|
|
11594
|
-
const validated =
|
|
11595
|
-
|
|
11596
|
-
const validatedProps = validateNodeProps(nodeKind.schema, item.props, {
|
|
11597
|
-
kind,
|
|
11598
|
-
operation: "create"
|
|
11599
|
-
});
|
|
11600
|
-
const applies = checkWherePredicate(constraint, validatedProps);
|
|
11601
|
-
const key = applies ? computeUniqueKey(
|
|
11602
|
-
validatedProps,
|
|
11603
|
-
constraint.fields,
|
|
11604
|
-
constraint.collation
|
|
11605
|
-
) : void 0;
|
|
11606
|
-
validated.push({ validatedProps, key });
|
|
11607
|
-
}
|
|
11608
|
-
const uniqueKeys = [
|
|
11609
|
-
...new Set(
|
|
11610
|
-
validated.map((v) => v.key).filter((k) => k !== void 0)
|
|
11611
|
-
)
|
|
11612
|
-
];
|
|
11525
|
+
const validated = validateAndComputeKeys(nodeKind, kind, constraint, items);
|
|
11526
|
+
const uniqueKeys = collectUniqueKeys(validated);
|
|
11613
11527
|
const kindsToCheck = getKindsForUniquenessCheck(
|
|
11614
11528
|
kind,
|
|
11615
11529
|
constraint.scope,
|
|
11616
11530
|
ctx.registry
|
|
11617
11531
|
);
|
|
11618
|
-
const existingByKey =
|
|
11619
|
-
|
|
11620
|
-
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
|
|
11625
|
-
|
|
11626
|
-
nodeKind: kindToCheck,
|
|
11627
|
-
constraintName: constraint.name,
|
|
11628
|
-
key,
|
|
11629
|
-
includeDeleted: true
|
|
11630
|
-
});
|
|
11631
|
-
if (row !== void 0) {
|
|
11632
|
-
existingByKey.set(row.key, row);
|
|
11633
|
-
}
|
|
11634
|
-
}
|
|
11635
|
-
} else {
|
|
11636
|
-
const rows = await backend.checkUniqueBatch({
|
|
11637
|
-
graphId: ctx.graphId,
|
|
11638
|
-
nodeKind: kindToCheck,
|
|
11639
|
-
constraintName: constraint.name,
|
|
11640
|
-
keys: uniqueKeys,
|
|
11641
|
-
includeDeleted: true
|
|
11642
|
-
});
|
|
11643
|
-
for (const row of rows) {
|
|
11644
|
-
if (!existingByKey.has(row.key)) {
|
|
11645
|
-
existingByKey.set(row.key, row);
|
|
11646
|
-
}
|
|
11647
|
-
}
|
|
11648
|
-
}
|
|
11649
|
-
}
|
|
11650
|
-
}
|
|
11532
|
+
const existingByKey = uniqueKeys.length > 0 ? await batchCheckUniqueAcrossKinds(
|
|
11533
|
+
backend,
|
|
11534
|
+
ctx.graphId,
|
|
11535
|
+
constraint.name,
|
|
11536
|
+
uniqueKeys,
|
|
11537
|
+
kindsToCheck,
|
|
11538
|
+
true
|
|
11539
|
+
) : /* @__PURE__ */ new Map();
|
|
11651
11540
|
const toCreate = [];
|
|
11652
11541
|
const toFetch = [];
|
|
11653
11542
|
const duplicateOf = [];
|
|
11654
11543
|
const seenKeys = /* @__PURE__ */ new Map();
|
|
11655
11544
|
for (const [index, { validatedProps, key }] of validated.entries()) {
|
|
11656
11545
|
if (key === void 0) {
|
|
11657
|
-
toCreate.push({
|
|
11658
|
-
index,
|
|
11659
|
-
input: { kind, props: validatedProps }
|
|
11660
|
-
});
|
|
11546
|
+
toCreate.push({ index, input: { kind, props: validatedProps } });
|
|
11661
11547
|
continue;
|
|
11662
11548
|
}
|
|
11663
11549
|
const previousIndex = seenKeys.get(key);
|
|
@@ -11668,10 +11554,7 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11668
11554
|
seenKeys.set(key, index);
|
|
11669
11555
|
const existing = existingByKey.get(key);
|
|
11670
11556
|
if (existing === void 0) {
|
|
11671
|
-
toCreate.push({
|
|
11672
|
-
index,
|
|
11673
|
-
input: { kind, props: validatedProps }
|
|
11674
|
-
});
|
|
11557
|
+
toCreate.push({ index, input: { kind, props: validatedProps } });
|
|
11675
11558
|
} else {
|
|
11676
11559
|
toFetch.push({
|
|
11677
11560
|
index,
|
|
@@ -11705,8 +11588,11 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11705
11588
|
nodeId
|
|
11706
11589
|
);
|
|
11707
11590
|
if (existingRow === void 0) {
|
|
11708
|
-
const
|
|
11709
|
-
|
|
11591
|
+
const node = await executeNodeCreate(
|
|
11592
|
+
ctx,
|
|
11593
|
+
{ kind, props: validatedProps },
|
|
11594
|
+
backend
|
|
11595
|
+
);
|
|
11710
11596
|
results[index] = { node, action: "created" };
|
|
11711
11597
|
continue;
|
|
11712
11598
|
}
|