@nicia-ai/typegraph 0.9.1 → 0.10.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 +183 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +183 -21
- package/dist/index.js.map +1 -1
- package/dist/interchange/index.d.cts +1 -1
- package/dist/interchange/index.d.ts +1 -1
- package/dist/profiler/index.d.cts +1 -1
- package/dist/profiler/index.d.ts +1 -1
- package/dist/{store-wqOO3GSy.d.ts → store-BcFe9jJe.d.ts} +80 -3
- package/dist/{store-DgzIgrmn.d.cts → store-NE18RGqV.d.cts} +80 -3
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -2522,14 +2522,8 @@ function compileAggregateExprFromSource(expr, dialect) {
|
|
|
2522
2522
|
const { field: field2 } = expr;
|
|
2523
2523
|
const fn = expr.function;
|
|
2524
2524
|
switch (fn) {
|
|
2525
|
-
case "count":
|
|
2526
|
-
|
|
2527
|
-
return drizzleOrm.sql`COUNT(${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(field2.alias)}_id)`;
|
|
2528
|
-
}
|
|
2529
|
-
case "countDistinct": {
|
|
2530
|
-
const cteAlias = `cte_${field2.alias}`;
|
|
2531
|
-
return drizzleOrm.sql`COUNT(DISTINCT ${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(field2.alias)}_id)`;
|
|
2532
|
-
}
|
|
2525
|
+
case "count":
|
|
2526
|
+
case "countDistinct":
|
|
2533
2527
|
case "sum":
|
|
2534
2528
|
case "avg":
|
|
2535
2529
|
case "min":
|
|
@@ -2541,6 +2535,9 @@ function compileAggregateExprFromSource(expr, dialect) {
|
|
|
2541
2535
|
field2.valueType,
|
|
2542
2536
|
cteAlias
|
|
2543
2537
|
);
|
|
2538
|
+
if (fn === "countDistinct") {
|
|
2539
|
+
return drizzleOrm.sql`COUNT(DISTINCT ${column})`;
|
|
2540
|
+
}
|
|
2544
2541
|
return drizzleOrm.sql`${drizzleOrm.sql.raw(fn.toUpperCase())}(${column})`;
|
|
2545
2542
|
}
|
|
2546
2543
|
default: {
|
|
@@ -3036,7 +3033,7 @@ function compileRecursiveCte(ast, traversal, graphId, ctx, requiredColumnsByAlia
|
|
|
3036
3033
|
recursiveBaseWhereClauses.push(cycleCheck);
|
|
3037
3034
|
}
|
|
3038
3035
|
recursiveBaseWhereClauses.push(...edgePredicates, ...targetNodePredicates);
|
|
3039
|
-
function
|
|
3036
|
+
function compileRecursiveBranch2(branch) {
|
|
3040
3037
|
const recursiveFilterClauses = [
|
|
3041
3038
|
...recursiveBaseWhereClauses,
|
|
3042
3039
|
compileKindFilter2(branch.edgeKinds, "e.kind"),
|
|
@@ -3091,7 +3088,7 @@ function compileRecursiveCte(ast, traversal, graphId, ctx, requiredColumnsByAlia
|
|
|
3091
3088
|
const directTargetField = direction === "out" ? "to_id" : "from_id";
|
|
3092
3089
|
const directJoinKindField = direction === "out" ? "from_kind" : "to_kind";
|
|
3093
3090
|
const directTargetKindField = direction === "out" ? "to_kind" : "from_kind";
|
|
3094
|
-
const directBranch =
|
|
3091
|
+
const directBranch = compileRecursiveBranch2({
|
|
3095
3092
|
joinField: directJoinField,
|
|
3096
3093
|
targetField: directTargetField,
|
|
3097
3094
|
joinKindField: directJoinKindField,
|
|
@@ -3107,7 +3104,7 @@ function compileRecursiveCte(ast, traversal, graphId, ctx, requiredColumnsByAlia
|
|
|
3107
3104
|
(kind) => directEdgeKinds.includes(kind)
|
|
3108
3105
|
);
|
|
3109
3106
|
const duplicateGuard = overlappingKinds.length > 0 ? drizzleOrm.sql`NOT (e.from_id = e.to_id AND ${compileKindFilter2(overlappingKinds, "e.kind")})` : void 0;
|
|
3110
|
-
const inverseBranch =
|
|
3107
|
+
const inverseBranch = compileRecursiveBranch2({
|
|
3111
3108
|
joinField: inverseJoinField,
|
|
3112
3109
|
targetField: inverseTargetField,
|
|
3113
3110
|
joinKindField: inverseJoinKindField,
|
|
@@ -3650,19 +3647,17 @@ function compilePrefixedSelect(ast, prefix, dialect) {
|
|
|
3650
3647
|
function compileFieldValueForSetOp(source, prefix, alias, dialect) {
|
|
3651
3648
|
if ("__type" in source && source.__type === "aggregate") {
|
|
3652
3649
|
const { field: field2, function: fn } = source;
|
|
3653
|
-
const cteName = `cte_${prefix}_${field2.alias}`;
|
|
3654
3650
|
switch (fn) {
|
|
3655
|
-
case "count":
|
|
3656
|
-
|
|
3657
|
-
}
|
|
3658
|
-
case "countDistinct": {
|
|
3659
|
-
return drizzleOrm.sql`COUNT(DISTINCT ${drizzleOrm.sql.raw(cteName)}.${drizzleOrm.sql.raw(field2.alias)}_id)`;
|
|
3660
|
-
}
|
|
3651
|
+
case "count":
|
|
3652
|
+
case "countDistinct":
|
|
3661
3653
|
case "sum":
|
|
3662
3654
|
case "avg":
|
|
3663
3655
|
case "min":
|
|
3664
3656
|
case "max": {
|
|
3665
3657
|
const column = compileFieldColumnForSetOp(field2, prefix, dialect);
|
|
3658
|
+
if (fn === "countDistinct") {
|
|
3659
|
+
return drizzleOrm.sql`COUNT(DISTINCT ${column})`;
|
|
3660
|
+
}
|
|
3666
3661
|
return drizzleOrm.sql`${drizzleOrm.sql.raw(fn.toUpperCase())}(${column})`;
|
|
3667
3662
|
}
|
|
3668
3663
|
default: {
|
|
@@ -3876,9 +3871,7 @@ function collectRequiredColumnsByAlias2(ast) {
|
|
|
3876
3871
|
markFieldRefAsRequired(requiredColumnsByAlias, source);
|
|
3877
3872
|
} else {
|
|
3878
3873
|
addRequiredColumn(requiredColumnsByAlias, source.field.alias, "id");
|
|
3879
|
-
|
|
3880
|
-
markFieldRefAsRequired(requiredColumnsByAlias, source.field);
|
|
3881
|
-
}
|
|
3874
|
+
markFieldRefAsRequired(requiredColumnsByAlias, source.field);
|
|
3882
3875
|
}
|
|
3883
3876
|
}
|
|
3884
3877
|
}
|
|
@@ -11195,6 +11188,142 @@ async function executeNodeBulkGetOrCreateByConstraint(ctx, kind, constraintName,
|
|
|
11195
11188
|
}
|
|
11196
11189
|
return results;
|
|
11197
11190
|
}
|
|
11191
|
+
var DEFAULT_SUBGRAPH_MAX_DEPTH = 10;
|
|
11192
|
+
function normalizeProps(value) {
|
|
11193
|
+
return typeof value === "string" ? value : JSON.stringify(value ?? {});
|
|
11194
|
+
}
|
|
11195
|
+
async function executeSubgraph(params) {
|
|
11196
|
+
const { options } = params;
|
|
11197
|
+
if (options.edges.length === 0) {
|
|
11198
|
+
return { nodes: [], edges: [] };
|
|
11199
|
+
}
|
|
11200
|
+
const maxDepth = Math.min(
|
|
11201
|
+
options.maxDepth ?? DEFAULT_SUBGRAPH_MAX_DEPTH,
|
|
11202
|
+
MAX_RECURSIVE_DEPTH
|
|
11203
|
+
);
|
|
11204
|
+
const ctx = {
|
|
11205
|
+
graphId: params.graphId,
|
|
11206
|
+
rootId: params.rootId,
|
|
11207
|
+
edgeKinds: options.edges,
|
|
11208
|
+
maxDepth,
|
|
11209
|
+
includeKinds: options.includeKinds,
|
|
11210
|
+
excludeRoot: options.excludeRoot ?? false,
|
|
11211
|
+
direction: options.direction ?? "out",
|
|
11212
|
+
cyclePolicy: options.cyclePolicy ?? "prevent",
|
|
11213
|
+
dialect: params.dialect,
|
|
11214
|
+
schema: params.schema ?? DEFAULT_SQL_SCHEMA,
|
|
11215
|
+
backend: params.backend
|
|
11216
|
+
};
|
|
11217
|
+
const reachableCte = buildReachableCte(ctx);
|
|
11218
|
+
const includedIdsCte = buildIncludedIdsCte(ctx);
|
|
11219
|
+
const [nodeRows, edgeRows] = await Promise.all([
|
|
11220
|
+
fetchSubgraphNodes(ctx, reachableCte, includedIdsCte),
|
|
11221
|
+
fetchSubgraphEdges(ctx, reachableCte, includedIdsCte)
|
|
11222
|
+
]);
|
|
11223
|
+
const nodes = nodeRows.map(
|
|
11224
|
+
(row) => rowToNode({ ...row, props: normalizeProps(row.props) })
|
|
11225
|
+
);
|
|
11226
|
+
const edges = edgeRows.map(
|
|
11227
|
+
(row) => rowToEdge({ ...row, props: normalizeProps(row.props) })
|
|
11228
|
+
);
|
|
11229
|
+
return {
|
|
11230
|
+
nodes,
|
|
11231
|
+
edges
|
|
11232
|
+
};
|
|
11233
|
+
}
|
|
11234
|
+
function buildReachableCte(ctx) {
|
|
11235
|
+
const shouldTrackPath = ctx.cyclePolicy === "prevent";
|
|
11236
|
+
const edgeKindFilter = compileKindFilter(drizzleOrm.sql.raw("e.kind"), ctx.edgeKinds);
|
|
11237
|
+
const initialPath = shouldTrackPath ? ctx.dialect.initializePath(drizzleOrm.sql.raw("n.id")) : void 0;
|
|
11238
|
+
const pathExtension = shouldTrackPath ? ctx.dialect.extendPath(drizzleOrm.sql.raw("r.path"), drizzleOrm.sql.raw("n.id")) : void 0;
|
|
11239
|
+
const cycleCheck = shouldTrackPath ? ctx.dialect.cycleCheck(drizzleOrm.sql.raw("n.id"), drizzleOrm.sql.raw("r.path")) : void 0;
|
|
11240
|
+
const baseColumns = [drizzleOrm.sql`n.id`, drizzleOrm.sql`n.kind`, drizzleOrm.sql`0 AS depth`];
|
|
11241
|
+
if (initialPath !== void 0) {
|
|
11242
|
+
baseColumns.push(drizzleOrm.sql`${initialPath} AS path`);
|
|
11243
|
+
}
|
|
11244
|
+
const baseCase = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(baseColumns, drizzleOrm.sql`, `)} FROM ${ctx.schema.nodesTable} n WHERE n.graph_id = ${ctx.graphId} AND n.id = ${ctx.rootId} AND n.deleted_at IS NULL`;
|
|
11245
|
+
const recursiveColumns = [
|
|
11246
|
+
drizzleOrm.sql`n.id`,
|
|
11247
|
+
drizzleOrm.sql`n.kind`,
|
|
11248
|
+
drizzleOrm.sql`r.depth + 1 AS depth`
|
|
11249
|
+
];
|
|
11250
|
+
if (pathExtension !== void 0) {
|
|
11251
|
+
recursiveColumns.push(drizzleOrm.sql`${pathExtension} AS path`);
|
|
11252
|
+
}
|
|
11253
|
+
const recursiveWhereClauses = [
|
|
11254
|
+
drizzleOrm.sql`e.graph_id = ${ctx.graphId}`,
|
|
11255
|
+
edgeKindFilter,
|
|
11256
|
+
drizzleOrm.sql`e.deleted_at IS NULL`,
|
|
11257
|
+
drizzleOrm.sql`n.deleted_at IS NULL`,
|
|
11258
|
+
drizzleOrm.sql`r.depth < ${ctx.maxDepth}`
|
|
11259
|
+
];
|
|
11260
|
+
if (cycleCheck !== void 0) {
|
|
11261
|
+
recursiveWhereClauses.push(cycleCheck);
|
|
11262
|
+
}
|
|
11263
|
+
const forceWorktableOuterJoinOrder = ctx.dialect.capabilities.forceRecursiveWorktableOuterJoinOrder;
|
|
11264
|
+
const recursiveCase = ctx.direction === "both" ? compileBidirectionalBranch({
|
|
11265
|
+
recursiveColumns,
|
|
11266
|
+
whereClauses: recursiveWhereClauses,
|
|
11267
|
+
forceWorktableOuterJoinOrder,
|
|
11268
|
+
schema: ctx.schema
|
|
11269
|
+
}) : compileRecursiveBranch({
|
|
11270
|
+
recursiveColumns,
|
|
11271
|
+
whereClauses: recursiveWhereClauses,
|
|
11272
|
+
joinField: "from_id",
|
|
11273
|
+
targetField: "to_id",
|
|
11274
|
+
targetKindField: "to_kind",
|
|
11275
|
+
forceWorktableOuterJoinOrder,
|
|
11276
|
+
schema: ctx.schema
|
|
11277
|
+
});
|
|
11278
|
+
return drizzleOrm.sql`WITH RECURSIVE reachable AS (${baseCase} UNION ALL ${recursiveCase})`;
|
|
11279
|
+
}
|
|
11280
|
+
function compileRecursiveBranch(params) {
|
|
11281
|
+
const columns = [...params.recursiveColumns];
|
|
11282
|
+
const selectClause = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)}`;
|
|
11283
|
+
const nodeJoin = drizzleOrm.sql`JOIN ${params.schema.nodesTable} n ON n.graph_id = e.graph_id AND n.id = e.${drizzleOrm.sql.raw(params.targetField)} AND n.kind = e.${drizzleOrm.sql.raw(params.targetKindField)}`;
|
|
11284
|
+
if (params.forceWorktableOuterJoinOrder) {
|
|
11285
|
+
const allWhere = [
|
|
11286
|
+
...params.whereClauses,
|
|
11287
|
+
drizzleOrm.sql`e.${drizzleOrm.sql.raw(params.joinField)} = r.id`
|
|
11288
|
+
];
|
|
11289
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r CROSS JOIN ${params.schema.edgesTable} e ${nodeJoin} WHERE ${drizzleOrm.sql.join(allWhere, drizzleOrm.sql` AND `)}`;
|
|
11290
|
+
}
|
|
11291
|
+
const where = [...params.whereClauses];
|
|
11292
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r JOIN ${params.schema.edgesTable} e ON e.${drizzleOrm.sql.raw(params.joinField)} = r.id ${nodeJoin} WHERE ${drizzleOrm.sql.join(where, drizzleOrm.sql` AND `)}`;
|
|
11293
|
+
}
|
|
11294
|
+
function compileBidirectionalBranch(params) {
|
|
11295
|
+
const columns = [...params.recursiveColumns];
|
|
11296
|
+
const selectClause = drizzleOrm.sql`SELECT ${drizzleOrm.sql.join(columns, drizzleOrm.sql`, `)}`;
|
|
11297
|
+
const nodeJoin = drizzleOrm.sql`JOIN ${params.schema.nodesTable} n ON n.graph_id = e.graph_id AND ((e.to_id = r.id AND n.id = e.from_id AND n.kind = e.from_kind) OR (e.from_id = r.id AND n.id = e.to_id AND n.kind = e.to_kind))`;
|
|
11298
|
+
if (params.forceWorktableOuterJoinOrder) {
|
|
11299
|
+
const allWhere = [
|
|
11300
|
+
...params.whereClauses,
|
|
11301
|
+
drizzleOrm.sql`(e.from_id = r.id OR e.to_id = r.id)`
|
|
11302
|
+
];
|
|
11303
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r CROSS JOIN ${params.schema.edgesTable} e ${nodeJoin} WHERE ${drizzleOrm.sql.join(allWhere, drizzleOrm.sql` AND `)}`;
|
|
11304
|
+
}
|
|
11305
|
+
return drizzleOrm.sql`${selectClause} FROM reachable r JOIN ${params.schema.edgesTable} e ON (e.from_id = r.id OR e.to_id = r.id) ${nodeJoin} WHERE ${drizzleOrm.sql.join([...params.whereClauses], drizzleOrm.sql` AND `)}`;
|
|
11306
|
+
}
|
|
11307
|
+
function buildIncludedIdsCte(ctx) {
|
|
11308
|
+
const filters = [];
|
|
11309
|
+
if (ctx.includeKinds !== void 0 && ctx.includeKinds.length > 0) {
|
|
11310
|
+
filters.push(compileKindFilter(drizzleOrm.sql.raw("kind"), ctx.includeKinds));
|
|
11311
|
+
}
|
|
11312
|
+
if (ctx.excludeRoot) {
|
|
11313
|
+
filters.push(drizzleOrm.sql`id != ${ctx.rootId}`);
|
|
11314
|
+
}
|
|
11315
|
+
const whereClause = filters.length > 0 ? drizzleOrm.sql` WHERE ${drizzleOrm.sql.join(filters, drizzleOrm.sql` AND `)}` : drizzleOrm.sql``;
|
|
11316
|
+
return drizzleOrm.sql`, included_ids AS (SELECT DISTINCT id FROM reachable${whereClause})`;
|
|
11317
|
+
}
|
|
11318
|
+
async function fetchSubgraphNodes(ctx, reachableCte, includedIdsCte) {
|
|
11319
|
+
const query = drizzleOrm.sql`${reachableCte}${includedIdsCte} SELECT n.kind, n.id, n.props, n.version, n.valid_from, n.valid_to, n.created_at, n.updated_at, n.deleted_at FROM ${ctx.schema.nodesTable} n WHERE n.graph_id = ${ctx.graphId} AND n.id IN (SELECT id FROM included_ids)`;
|
|
11320
|
+
return ctx.backend.execute(query);
|
|
11321
|
+
}
|
|
11322
|
+
async function fetchSubgraphEdges(ctx, reachableCte, includedIdsCte) {
|
|
11323
|
+
const edgeKindFilter = compileKindFilter(drizzleOrm.sql.raw("e.kind"), ctx.edgeKinds);
|
|
11324
|
+
const query = drizzleOrm.sql`${reachableCte}${includedIdsCte} SELECT e.id, e.kind, e.from_kind, e.from_id, e.to_kind, e.to_id, e.props, e.valid_from, e.valid_to, e.created_at, e.updated_at, e.deleted_at FROM ${ctx.schema.edgesTable} e WHERE e.graph_id = ${ctx.graphId} AND ${edgeKindFilter} AND e.deleted_at IS NULL AND e.from_id IN (SELECT id FROM included_ids) AND e.to_id IN (SELECT id FROM included_ids)`;
|
|
11325
|
+
return ctx.backend.execute(query);
|
|
11326
|
+
}
|
|
11198
11327
|
|
|
11199
11328
|
// src/store/store.ts
|
|
11200
11329
|
var Store = class {
|
|
@@ -11398,6 +11527,39 @@ var Store = class {
|
|
|
11398
11527
|
query() {
|
|
11399
11528
|
return this.#createQueryForBackend(this.#backend);
|
|
11400
11529
|
}
|
|
11530
|
+
// === Subgraph Extraction ===
|
|
11531
|
+
/**
|
|
11532
|
+
* Extracts a typed subgraph by traversing from a root node.
|
|
11533
|
+
*
|
|
11534
|
+
* Performs a BFS traversal from `rootId` following the specified edge kinds,
|
|
11535
|
+
* then returns all reachable nodes and the edges connecting them.
|
|
11536
|
+
*
|
|
11537
|
+
* @example
|
|
11538
|
+
* ```typescript
|
|
11539
|
+
* const result = await store.subgraph(run.id, {
|
|
11540
|
+
* edges: ["has_task", "runs_agent", "uses_skill"],
|
|
11541
|
+
* maxDepth: 4,
|
|
11542
|
+
* includeKinds: ["Run", "Task", "Agent", "Skill"],
|
|
11543
|
+
* });
|
|
11544
|
+
*
|
|
11545
|
+
* for (const node of result.nodes) {
|
|
11546
|
+
* switch (node.kind) {
|
|
11547
|
+
* case "Task": console.log(node.name); break;
|
|
11548
|
+
* case "Agent": console.log(node.model); break;
|
|
11549
|
+
* }
|
|
11550
|
+
* }
|
|
11551
|
+
* ```
|
|
11552
|
+
*/
|
|
11553
|
+
async subgraph(rootId, options) {
|
|
11554
|
+
return executeSubgraph({
|
|
11555
|
+
graphId: this.graphId,
|
|
11556
|
+
rootId,
|
|
11557
|
+
backend: this.#backend,
|
|
11558
|
+
dialect: chunk2WVFEIHR_cjs.getDialect(this.#backend.dialect),
|
|
11559
|
+
schema: this.#schema,
|
|
11560
|
+
options
|
|
11561
|
+
});
|
|
11562
|
+
}
|
|
11401
11563
|
// === Transactions ===
|
|
11402
11564
|
/**
|
|
11403
11565
|
* Executes a function within a transaction.
|