@nicia-ai/typegraph 0.21.0 → 0.23.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.
Files changed (85) hide show
  1. package/dist/{ast-CSLbPIOC.d.ts → ast-C8S37w1A.d.ts} +1 -1
  2. package/dist/{ast-DogwbBqA.d.cts → ast-dgLhLOg0.d.cts} +1 -1
  3. package/dist/backend/postgres/index.cjs +169 -52
  4. package/dist/backend/postgres/index.cjs.map +1 -1
  5. package/dist/backend/postgres/index.d.cts +43 -6
  6. package/dist/backend/postgres/index.d.ts +43 -6
  7. package/dist/backend/postgres/index.js +140 -23
  8. package/dist/backend/postgres/index.js.map +1 -1
  9. package/dist/backend/sqlite/index.cjs +15 -14
  10. package/dist/backend/sqlite/index.d.cts +17 -6
  11. package/dist/backend/sqlite/index.d.ts +17 -6
  12. package/dist/backend/sqlite/index.js +5 -4
  13. package/dist/backend/sqlite/libsql.cjs +8 -7
  14. package/dist/backend/sqlite/libsql.cjs.map +1 -1
  15. package/dist/backend/sqlite/libsql.d.cts +4 -4
  16. package/dist/backend/sqlite/libsql.d.ts +4 -4
  17. package/dist/backend/sqlite/libsql.js +5 -4
  18. package/dist/backend/sqlite/libsql.js.map +1 -1
  19. package/dist/backend/sqlite/local.cjs +27 -9
  20. package/dist/backend/sqlite/local.cjs.map +1 -1
  21. package/dist/backend/sqlite/local.d.cts +4 -4
  22. package/dist/backend/sqlite/local.d.ts +4 -4
  23. package/dist/backend/sqlite/local.js +22 -5
  24. package/dist/backend/sqlite/local.js.map +1 -1
  25. package/dist/chunk-3EUKJEQ3.js +77 -0
  26. package/dist/chunk-3EUKJEQ3.js.map +1 -0
  27. package/dist/{chunk-FQCQM3KG.cjs → chunk-3JK66E3I.cjs} +4 -2
  28. package/dist/chunk-3JK66E3I.cjs.map +1 -0
  29. package/dist/{chunk-SMMOAVJ5.js → chunk-3PPEHLGK.js} +3 -3
  30. package/dist/{chunk-SMMOAVJ5.js.map → chunk-3PPEHLGK.js.map} +1 -1
  31. package/dist/{chunk-4XNE2JG3.js → chunk-753F33CV.js} +4 -2
  32. package/dist/chunk-753F33CV.js.map +1 -0
  33. package/dist/{chunk-Q73OWTJY.cjs → chunk-7OD2EPN4.cjs} +130 -106
  34. package/dist/chunk-7OD2EPN4.cjs.map +1 -0
  35. package/dist/chunk-7TU5EWQ7.js +47 -0
  36. package/dist/chunk-7TU5EWQ7.js.map +1 -0
  37. package/dist/{chunk-NRNJ52AA.js → chunk-EP2KSSD5.js} +41 -25
  38. package/dist/chunk-EP2KSSD5.js.map +1 -0
  39. package/dist/{chunk-UQVBVBVG.js → chunk-H2CAJ4ZV.js} +71 -45
  40. package/dist/chunk-H2CAJ4ZV.js.map +1 -0
  41. package/dist/chunk-HTGDWIDE.cjs +89 -0
  42. package/dist/chunk-HTGDWIDE.cjs.map +1 -0
  43. package/dist/{chunk-CQL6FOTT.cjs → chunk-O5BRZEIZ.cjs} +58 -42
  44. package/dist/chunk-O5BRZEIZ.cjs.map +1 -0
  45. package/dist/{chunk-2X7P7AD5.cjs → chunk-PEE4EWXZ.cjs} +22 -22
  46. package/dist/{chunk-2X7P7AD5.cjs.map → chunk-PEE4EWXZ.cjs.map} +1 -1
  47. package/dist/chunk-RNUNP5JD.cjs +52 -0
  48. package/dist/chunk-RNUNP5JD.cjs.map +1 -0
  49. package/dist/{ddl-BqkTShcR.d.ts → ddl-1tFIvt9V.d.ts} +3 -3
  50. package/dist/{ddl-Dk1NDN3M.d.cts → ddl-B_H8JM-E.d.cts} +3 -3
  51. package/dist/index.cjs +267 -198
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +53 -9
  54. package/dist/index.d.ts +53 -9
  55. package/dist/index.js +209 -142
  56. package/dist/index.js.map +1 -1
  57. package/dist/indexes/index.cjs +16 -16
  58. package/dist/indexes/index.d.cts +5 -5
  59. package/dist/indexes/index.d.ts +5 -5
  60. package/dist/indexes/index.js +2 -2
  61. package/dist/interchange/index.d.cts +4 -4
  62. package/dist/interchange/index.d.ts +4 -4
  63. package/dist/{manager-BPK-2PUI.d.cts → manager-Vkz28eAC.d.cts} +1 -1
  64. package/dist/{manager-0jVZtiE8.d.ts → manager-nIhmttD-.d.ts} +1 -1
  65. package/dist/profiler/index.d.cts +6 -6
  66. package/dist/profiler/index.d.ts +6 -6
  67. package/dist/schema/index.d.cts +4 -4
  68. package/dist/schema/index.d.ts +4 -4
  69. package/dist/{sqlite-D1rrwcir.d.cts → sqlite-D0aceIe0.d.cts} +1 -1
  70. package/dist/{sqlite-W3rmJMlc.d.ts → sqlite-SUxbZqfy.d.ts} +1 -1
  71. package/dist/{store-C0q13mtJ.d.ts → store-CpvwTMxV.d.cts} +58 -8
  72. package/dist/{store-2QW2SIRk.d.cts → store-U3i2tUch.d.ts} +58 -8
  73. package/dist/{types-IMQCuser.d.ts → types-C-zfYDJB.d.ts} +2 -2
  74. package/dist/{types-vgjar7Ch.d.cts → types-CQx4iW5Y.d.cts} +2 -2
  75. package/dist/{types-CQF88McG.d.ts → types-Qk2l3IkQ.d.cts} +20 -1
  76. package/dist/{types-CQF88McG.d.cts → types-Qk2l3IkQ.d.ts} +20 -1
  77. package/dist/{types-CglvhPKz.d.ts → types-qYFZ9SqD.d.ts} +1 -1
  78. package/dist/{types-D23slCOA.d.cts → types-yH4_p0XB.d.cts} +1 -1
  79. package/package.json +15 -1
  80. package/dist/chunk-4XNE2JG3.js.map +0 -1
  81. package/dist/chunk-CQL6FOTT.cjs.map +0 -1
  82. package/dist/chunk-FQCQM3KG.cjs.map +0 -1
  83. package/dist/chunk-NRNJ52AA.js.map +0 -1
  84. package/dist/chunk-Q73OWTJY.cjs.map +0 -1
  85. package/dist/chunk-UQVBVBVG.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
+ var chunkHTGDWIDE_cjs = require('./chunk-HTGDWIDE.cjs');
3
4
  var chunkHRNQ3DVJ_cjs = require('./chunk-HRNQ3DVJ.cjs');
4
5
  var chunkWRWVWKQL_cjs = require('./chunk-WRWVWKQL.cjs');
6
+ var chunkRNUNP5JD_cjs = require('./chunk-RNUNP5JD.cjs');
5
7
  var chunkO5PST6TB_cjs = require('./chunk-O5PST6TB.cjs');
6
- var chunkFQCQM3KG_cjs = require('./chunk-FQCQM3KG.cjs');
8
+ var chunk3JK66E3I_cjs = require('./chunk-3JK66E3I.cjs');
7
9
  var chunkUVZHTBZ5_cjs = require('./chunk-UVZHTBZ5.cjs');
8
10
  var zod = require('zod');
9
11
  var drizzleOrm = require('drizzle-orm');
@@ -1930,9 +1932,9 @@ function validateTableName(name, label) {
1930
1932
  if (!name || name.length === 0) {
1931
1933
  throw new chunkO5PST6TB_cjs.ConfigurationError(`${label} table name cannot be empty`);
1932
1934
  }
1933
- if (name.length > chunkFQCQM3KG_cjs.MAX_PG_IDENTIFIER_LENGTH) {
1935
+ if (name.length > chunk3JK66E3I_cjs.MAX_PG_IDENTIFIER_LENGTH) {
1934
1936
  throw new chunkO5PST6TB_cjs.ConfigurationError(
1935
- `${label} table name exceeds maximum length of ${chunkFQCQM3KG_cjs.MAX_PG_IDENTIFIER_LENGTH} characters`
1937
+ `${label} table name exceeds maximum length of ${chunk3JK66E3I_cjs.MAX_PG_IDENTIFIER_LENGTH} characters`
1936
1938
  );
1937
1939
  }
1938
1940
  if (!VALID_IDENTIFIER_PATTERN.test(name)) {
@@ -1941,7 +1943,7 @@ function validateTableName(name, label) {
1941
1943
  );
1942
1944
  }
1943
1945
  }
1944
- function quoteIdentifier(name) {
1946
+ function quoteIdentifier2(name) {
1945
1947
  return `"${name.replaceAll('"', '""')}"`;
1946
1948
  }
1947
1949
  function createSqlSchema(names = {}) {
@@ -1952,10 +1954,10 @@ function createSqlSchema(names = {}) {
1952
1954
  validateTableName(tables.fulltext, "fulltext");
1953
1955
  return {
1954
1956
  tables,
1955
- nodesTable: drizzleOrm.sql.raw(quoteIdentifier(tables.nodes)),
1956
- edgesTable: drizzleOrm.sql.raw(quoteIdentifier(tables.edges)),
1957
- embeddingsTable: drizzleOrm.sql.raw(quoteIdentifier(tables.embeddings)),
1958
- fulltextTable: drizzleOrm.sql.raw(quoteIdentifier(tables.fulltext))
1957
+ nodesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.nodes)),
1958
+ edgesTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.edges)),
1959
+ embeddingsTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.embeddings)),
1960
+ fulltextTable: drizzleOrm.sql.raw(quoteIdentifier2(tables.fulltext))
1959
1961
  };
1960
1962
  }
1961
1963
  var DEFAULT_SQL_SCHEMA = createSqlSchema();
@@ -1993,76 +1995,6 @@ function compileTypedJsonExtract(input) {
1993
1995
  }
1994
1996
  }
1995
1997
  }
1996
- var NODE_COLUMNS = [
1997
- "id",
1998
- "kind",
1999
- "props",
2000
- "version",
2001
- "valid_from",
2002
- "valid_to",
2003
- "created_at",
2004
- "updated_at",
2005
- "deleted_at"
2006
- ];
2007
- var EDGE_COLUMNS = [
2008
- "id",
2009
- "kind",
2010
- "from_id",
2011
- "to_id",
2012
- "props",
2013
- "valid_from",
2014
- "valid_to",
2015
- "created_at",
2016
- "updated_at",
2017
- "deleted_at"
2018
- ];
2019
- var EMPTY_REQUIRED_COLUMNS = /* @__PURE__ */ new Set();
2020
- function quoteIdentifier2(identifier) {
2021
- return drizzleOrm.sql.raw(`"${identifier.replaceAll('"', '""')}"`);
2022
- }
2023
- function shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns) {
2024
- if (alwaysRequiredColumns?.has(column)) return true;
2025
- if (requiredColumns === void 0) return true;
2026
- return requiredColumns.has(column);
2027
- }
2028
- function addRequiredColumn(requiredColumnsByAlias, alias, column) {
2029
- const existing = requiredColumnsByAlias.get(alias);
2030
- if (existing) {
2031
- existing.add(column);
2032
- return;
2033
- }
2034
- requiredColumnsByAlias.set(alias, /* @__PURE__ */ new Set([column]));
2035
- }
2036
- function markFieldRefAsRequired(requiredColumnsByAlias, field2) {
2037
- const column = field2.path[0];
2038
- if (column === void 0) return;
2039
- addRequiredColumn(requiredColumnsByAlias, field2.alias, column);
2040
- }
2041
- function mapSelectiveSystemFieldToColumn(field2) {
2042
- if (field2 === "fromId") return "from_id";
2043
- if (field2 === "toId") return "to_id";
2044
- if (field2.startsWith("meta.")) {
2045
- return field2.slice(5).replaceAll(/([A-Z])/g, "_$1").toLowerCase();
2046
- }
2047
- return field2;
2048
- }
2049
- function markSelectiveFieldAsRequired(requiredColumnsByAlias, field2) {
2050
- if (field2.isSystemField) {
2051
- addRequiredColumn(
2052
- requiredColumnsByAlias,
2053
- field2.alias,
2054
- mapSelectiveSystemFieldToColumn(field2.field)
2055
- );
2056
- return;
2057
- }
2058
- addRequiredColumn(requiredColumnsByAlias, field2.alias, "props");
2059
- }
2060
- function isIdFieldRef(field2) {
2061
- return field2.path.length === 1 && field2.path[0] === "id" && field2.jsonPointer === void 0;
2062
- }
2063
- function isAggregateExpr(source) {
2064
- return "__type" in source && source.__type === "aggregate";
2065
- }
2066
1998
 
2067
1999
  // src/query/compiler/emitter/standard-builders.ts
2068
2000
  function compileColumnReference(tableAlias, column) {
@@ -2072,7 +2004,7 @@ function compileColumnReference(tableAlias, column) {
2072
2004
  return drizzleOrm.sql`${drizzleOrm.sql.raw(tableAlias)}.${drizzleOrm.sql.raw(column)}`;
2073
2005
  }
2074
2006
  function qualifyColumn(owner, name) {
2075
- return drizzleOrm.sql`${quoteIdentifier2(owner)}.${quoteIdentifier2(name)}`;
2007
+ return drizzleOrm.sql`${chunkHTGDWIDE_cjs.quoteIdentifier(owner)}.${chunkHTGDWIDE_cjs.quoteIdentifier(name)}`;
2076
2008
  }
2077
2009
  var SCOPED_RELEVANCE_NODES_ALIAS = "scoped_relevance_nodes";
2078
2010
  function buildScopedNodeIdsSubquery(nodeAlias) {
@@ -2082,20 +2014,20 @@ function buildScopedNodeIdsSubquery(nodeAlias) {
2082
2014
  SELECT DISTINCT
2083
2015
  ${qualifyColumn(cteAlias, `${nodeAlias}_id`)} AS node_id,
2084
2016
  ${qualifyColumn(cteAlias, `${nodeAlias}_kind`)} AS node_kind
2085
- FROM ${quoteIdentifier2(cteAlias)}
2017
+ FROM ${chunkHTGDWIDE_cjs.quoteIdentifier(cteAlias)}
2086
2018
  ) AS ${drizzleOrm.sql.raw(SCOPED_RELEVANCE_NODES_ALIAS)}
2087
2019
  `;
2088
2020
  }
2089
2021
  function compileNodeSelectColumns(tableAlias, alias, requiredColumns) {
2090
- return NODE_COLUMNS.filter(
2091
- (column) => column === "id" || column === "kind" || shouldProjectColumn(requiredColumns, column)
2022
+ return chunkHTGDWIDE_cjs.NODE_COLUMNS.filter(
2023
+ (column) => column === "id" || column === "kind" || chunkHTGDWIDE_cjs.shouldProjectColumn(requiredColumns, column)
2092
2024
  ).map(
2093
2025
  (column) => drizzleOrm.sql`${compileColumnReference(tableAlias, column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
2094
2026
  );
2095
2027
  }
2096
2028
  function compileEdgeSelectColumns(tableAlias, alias, requiredColumns) {
2097
- return EDGE_COLUMNS.filter(
2098
- (column) => shouldProjectColumn(requiredColumns, column)
2029
+ return chunkHTGDWIDE_cjs.EDGE_COLUMNS.filter(
2030
+ (column) => chunkHTGDWIDE_cjs.shouldProjectColumn(requiredColumns, column)
2099
2031
  ).map(
2100
2032
  (column) => drizzleOrm.sql`${compileColumnReference(tableAlias, column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
2101
2033
  );
@@ -2104,6 +2036,7 @@ function buildStandardStartCte(input) {
2104
2036
  const { ast, ctx, graphId, predicateIndex, requiredColumnsByAlias } = input;
2105
2037
  const alias = ast.start.alias;
2106
2038
  const kinds = ast.start.kinds;
2039
+ const cteMaterialization = ctx.dialect.capabilities.emitNotMaterializedHint ? drizzleOrm.sql`NOT MATERIALIZED ` : drizzleOrm.sql``;
2107
2040
  const kindFilter = compileKindFilter(drizzleOrm.sql.raw("kind"), kinds);
2108
2041
  const temporalFilter = input.temporalFilterPass.forAlias();
2109
2042
  const cteContext = { ...ctx, cteColumnPrefix: "" };
@@ -2117,15 +2050,20 @@ function buildStandardStartCte(input) {
2117
2050
  temporalFilter,
2118
2051
  ...predicateClauses
2119
2052
  ];
2120
- const effectiveRequiredColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(alias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
2053
+ const effectiveRequiredColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(alias) ?? chunkHTGDWIDE_cjs.EMPTY_REQUIRED_COLUMNS : void 0;
2054
+ const limitClause = input.limitOffset === void 0 ? drizzleOrm.sql`` : input.limitOffset.offset === void 0 ? drizzleOrm.sql`
2055
+ LIMIT ${input.limitOffset.limit}
2056
+ ` : drizzleOrm.sql`
2057
+ LIMIT ${input.limitOffset.limit} OFFSET ${input.limitOffset.offset}
2058
+ `;
2121
2059
  return drizzleOrm.sql`
2122
- cte_${drizzleOrm.sql.raw(alias)} AS (
2060
+ cte_${drizzleOrm.sql.raw(alias)} AS ${cteMaterialization}(
2123
2061
  SELECT ${drizzleOrm.sql.join(
2124
2062
  compileNodeSelectColumns(void 0, alias, effectiveRequiredColumns),
2125
2063
  drizzleOrm.sql`, `
2126
2064
  )}
2127
2065
  FROM ${ctx.schema.nodesTable}
2128
- WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
2066
+ WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}${limitClause}
2129
2067
  )
2130
2068
  `;
2131
2069
  }
@@ -2178,8 +2116,8 @@ function buildStandardTraversalCte(input) {
2178
2116
  const previousAlias = traversal.joinFromAlias;
2179
2117
  const edgeAlias = traversal.edgeAlias;
2180
2118
  const nodeAlias = traversal.nodeAlias;
2181
- const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
2182
- const requiredEdgeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(edgeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
2119
+ const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? chunkHTGDWIDE_cjs.EMPTY_REQUIRED_COLUMNS : void 0;
2120
+ const requiredEdgeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(edgeAlias) ?? chunkHTGDWIDE_cjs.EMPTY_REQUIRED_COLUMNS : void 0;
2183
2121
  const previousRowColumns = carryForwardPreviousColumns ? [drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.*`] : [
2184
2122
  drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_id AS ${drizzleOrm.sql.raw(previousAlias)}_id`,
2185
2123
  drizzleOrm.sql`cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAlias)}_kind AS ${drizzleOrm.sql.raw(previousAlias)}_kind`
@@ -2189,7 +2127,7 @@ function buildStandardTraversalCte(input) {
2189
2127
  ...compileEdgeSelectColumns("e", edgeAlias, requiredEdgeColumns),
2190
2128
  ...compileNodeSelectColumns("n", nodeAlias, requiredNodeColumns)
2191
2129
  ];
2192
- const cteMaterialization = materializeCte ? drizzleOrm.sql`MATERIALIZED ` : drizzleOrm.sql``;
2130
+ const cteMaterialization = materializeCte ? drizzleOrm.sql`MATERIALIZED ` : ctx.dialect.capabilities.emitNotMaterializedHint ? drizzleOrm.sql`NOT MATERIALIZED ` : drizzleOrm.sql``;
2193
2131
  function compileTraversalBranch(branch) {
2194
2132
  const whereClauses = [
2195
2133
  ...baseWhereClauses,
@@ -2311,7 +2249,7 @@ function compileAggregateExprFromSource(expr, dialect) {
2311
2249
  }
2312
2250
  }
2313
2251
  function compileProjectedSource(field2, dialect) {
2314
- if (isAggregateExpr(field2.source)) {
2252
+ if (chunkHTGDWIDE_cjs.isAggregateExpr(field2.source)) {
2315
2253
  return compileAggregateExprFromSource(field2.source, dialect);
2316
2254
  }
2317
2255
  const cteAlias = field2.cteAlias ?? `cte_${field2.source.alias}`;
@@ -2338,7 +2276,7 @@ function buildStandardProjection(input) {
2338
2276
  }
2339
2277
  const projectedFields = fields.map((field2) => {
2340
2278
  const source = compileProjectedSource(field2, dialect);
2341
- return drizzleOrm.sql`${source} AS ${quoteIdentifier2(field2.outputName)}`;
2279
+ return drizzleOrm.sql`${source} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(field2.outputName)}`;
2342
2280
  });
2343
2281
  return drizzleOrm.sql.join(projectedFields, drizzleOrm.sql`, `);
2344
2282
  }
@@ -2357,8 +2295,8 @@ function compileSelectiveProjection(fields, dialect, ast, collapsedTraversalCteA
2357
2295
  const columns = fields.map((field2) => {
2358
2296
  const cteAlias = collapsedTraversalCteAlias ?? aliasToCte.get(field2.alias) ?? `cte_${field2.alias}`;
2359
2297
  if (field2.isSystemField) {
2360
- const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
2361
- return drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier2(field2.outputName)}`;
2298
+ const dbColumn = chunkHTGDWIDE_cjs.mapSelectiveSystemFieldToColumn(field2.field);
2299
+ return drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(field2.outputName)}`;
2362
2300
  }
2363
2301
  const propsColumn = `${field2.alias}_props`;
2364
2302
  const column = drizzleOrm.sql`${drizzleOrm.sql.raw(cteAlias)}.${drizzleOrm.sql.raw(propsColumn)}`;
@@ -2369,7 +2307,7 @@ function compileSelectiveProjection(fields, dialect, ast, collapsedTraversalCteA
2369
2307
  pointer,
2370
2308
  valueType: field2.valueType
2371
2309
  });
2372
- return drizzleOrm.sql`${extracted} AS ${quoteIdentifier2(field2.outputName)}`;
2310
+ return drizzleOrm.sql`${extracted} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(field2.outputName)}`;
2373
2311
  });
2374
2312
  return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
2375
2313
  }
@@ -3170,7 +3108,7 @@ function lowerComposableQueryToLogicalPlanNode(query, dialect, graphId, nextPlan
3170
3108
  nextPlanNodeId
3171
3109
  });
3172
3110
  }
3173
- const dialectAdapter = chunkFQCQM3KG_cjs.getDialect(dialect);
3111
+ const dialectAdapter = chunk3JK66E3I_cjs.getDialect(dialect);
3174
3112
  const vectorPredicate = runVectorPredicatePass(
3175
3113
  query,
3176
3114
  dialectAdapter
@@ -3439,8 +3377,8 @@ function compileRecursiveCte(ast, traversal, graphId, ctx, requiredColumnsByAlia
3439
3377
  if (previousNodeKinds.length > 1) {
3440
3378
  recursiveJoinRequiredColumns.add("kind");
3441
3379
  }
3442
- const requiredStartColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(startAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
3443
- const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? EMPTY_REQUIRED_COLUMNS : void 0;
3380
+ const requiredStartColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(startAlias) ?? chunkHTGDWIDE_cjs.EMPTY_REQUIRED_COLUMNS : void 0;
3381
+ const requiredNodeColumns = requiredColumnsByAlias ? requiredColumnsByAlias.get(nodeAlias) ?? chunkHTGDWIDE_cjs.EMPTY_REQUIRED_COLUMNS : void 0;
3444
3382
  const startColumnsFromBase = compileNodeSelectColumnsFromTable(
3445
3383
  "n0",
3446
3384
  startAlias,
@@ -3636,30 +3574,30 @@ function collectRequiredColumnsByAlias(ast, traversal) {
3636
3574
  const previousNodeKinds = [
3637
3575
  .../* @__PURE__ */ new Set([...ast.start.kinds, ...traversal.nodeKinds])
3638
3576
  ];
3639
- addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "id");
3577
+ chunkHTGDWIDE_cjs.addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "id");
3640
3578
  if (previousNodeKinds.length > 1) {
3641
- addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "kind");
3579
+ chunkHTGDWIDE_cjs.addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "kind");
3642
3580
  }
3643
3581
  for (const field2 of selectiveFields) {
3644
- markSelectiveFieldAsRequired(requiredColumnsByAlias, field2);
3582
+ chunkHTGDWIDE_cjs.markSelectiveFieldAsRequired(requiredColumnsByAlias, field2);
3645
3583
  }
3646
3584
  if (ast.orderBy) {
3647
3585
  for (const orderSpec of ast.orderBy) {
3648
- markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
3586
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
3649
3587
  }
3650
3588
  }
3651
3589
  return requiredColumnsByAlias;
3652
3590
  }
3653
3591
  function compileNodeSelectColumnsFromTable(tableAlias, alias, requiredColumns, alwaysRequiredColumns) {
3654
- return NODE_COLUMNS.filter(
3655
- (column) => shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
3592
+ return chunkHTGDWIDE_cjs.NODE_COLUMNS.filter(
3593
+ (column) => chunkHTGDWIDE_cjs.shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
3656
3594
  ).map(
3657
3595
  (column) => drizzleOrm.sql`${drizzleOrm.sql.raw(tableAlias)}.${drizzleOrm.sql.raw(column)} AS ${drizzleOrm.sql.raw(`${alias}_${column}`)}`
3658
3596
  );
3659
3597
  }
3660
3598
  function compileNodeSelectColumnsFromRecursiveRow(alias, requiredColumns, alwaysRequiredColumns) {
3661
- return NODE_COLUMNS.filter(
3662
- (column) => shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
3599
+ return chunkHTGDWIDE_cjs.NODE_COLUMNS.filter(
3600
+ (column) => chunkHTGDWIDE_cjs.shouldProjectColumn(requiredColumns, column, alwaysRequiredColumns)
3663
3601
  ).map((column) => {
3664
3602
  const projected = `${alias}_${column}`;
3665
3603
  return drizzleOrm.sql`r.${drizzleOrm.sql.raw(projected)} AS ${drizzleOrm.sql.raw(projected)}`;
@@ -3700,10 +3638,10 @@ function compileRecursiveProjection(ast, traversal, dialect) {
3700
3638
  drizzleOrm.sql`${drizzleOrm.sql.raw(nodeAlias)}_deleted_at`
3701
3639
  ];
3702
3640
  if (vl.depthAlias !== void 0) {
3703
- fields.push(drizzleOrm.sql`depth AS ${quoteIdentifier2(vl.depthAlias)}`);
3641
+ fields.push(drizzleOrm.sql`depth AS ${chunkHTGDWIDE_cjs.quoteIdentifier(vl.depthAlias)}`);
3704
3642
  }
3705
3643
  if (vl.pathAlias !== void 0) {
3706
- fields.push(drizzleOrm.sql`path AS ${quoteIdentifier2(vl.pathAlias)}`);
3644
+ fields.push(drizzleOrm.sql`path AS ${chunkHTGDWIDE_cjs.quoteIdentifier(vl.pathAlias)}`);
3707
3645
  }
3708
3646
  return drizzleOrm.sql.join(fields, drizzleOrm.sql`, `);
3709
3647
  }
@@ -3716,8 +3654,8 @@ function compileRecursiveSelectiveProjection(fields, ast, traversal, dialect) {
3716
3654
  );
3717
3655
  }
3718
3656
  if (field2.isSystemField) {
3719
- const dbColumn = mapSelectiveSystemFieldToColumn(field2.field);
3720
- return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${quoteIdentifier2(field2.outputName)}`;
3657
+ const dbColumn = chunkHTGDWIDE_cjs.mapSelectiveSystemFieldToColumn(field2.field);
3658
+ return drizzleOrm.sql`${drizzleOrm.sql.raw(`${field2.alias}_${dbColumn}`)} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(field2.outputName)}`;
3721
3659
  }
3722
3660
  const column = drizzleOrm.sql.raw(`${field2.alias}_props`);
3723
3661
  const extracted = compileTypedJsonExtract({
@@ -3726,14 +3664,14 @@ function compileRecursiveSelectiveProjection(fields, ast, traversal, dialect) {
3726
3664
  pointer: chunkUVZHTBZ5_cjs.jsonPointer([field2.field]),
3727
3665
  valueType: field2.valueType
3728
3666
  });
3729
- return drizzleOrm.sql`${extracted} AS ${quoteIdentifier2(field2.outputName)}`;
3667
+ return drizzleOrm.sql`${extracted} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(field2.outputName)}`;
3730
3668
  });
3731
3669
  const vl = traversal.variableLength;
3732
3670
  if (vl.depthAlias !== void 0) {
3733
- columns.push(drizzleOrm.sql`depth AS ${quoteIdentifier2(vl.depthAlias)}`);
3671
+ columns.push(drizzleOrm.sql`depth AS ${chunkHTGDWIDE_cjs.quoteIdentifier(vl.depthAlias)}`);
3734
3672
  }
3735
3673
  if (vl.pathAlias !== void 0) {
3736
- columns.push(drizzleOrm.sql`path AS ${quoteIdentifier2(vl.pathAlias)}`);
3674
+ columns.push(drizzleOrm.sql`path AS ${chunkHTGDWIDE_cjs.quoteIdentifier(vl.pathAlias)}`);
3737
3675
  }
3738
3676
  return drizzleOrm.sql.join(columns, drizzleOrm.sql`, `);
3739
3677
  }
@@ -4000,9 +3938,9 @@ function truncateToBytes(value, maxBytes) {
4000
3938
  }
4001
3939
  function projectionAlias(entityPrefix, kind, field2) {
4002
3940
  const prefix = entityPrefix === "node" ? "sg_n" : "sg_e";
4003
- const hash = chunkFQCQM3KG_cjs.fnv1aBase36(`${kind}\0${field2}`);
3941
+ const hash = chunk3JK66E3I_cjs.fnv1aBase36(`${kind}\0${field2}`);
4004
3942
  const fixedBytes = prefix.length + 1 + 1 + hash.length;
4005
- const maxKindBytes = chunkFQCQM3KG_cjs.MAX_PG_IDENTIFIER_LENGTH - fixedBytes;
3943
+ const maxKindBytes = chunk3JK66E3I_cjs.MAX_PG_IDENTIFIER_LENGTH - fixedBytes;
4006
3944
  const truncatedKind = truncateToBytes(kind, maxKindBytes);
4007
3945
  return `${prefix}_${truncatedKind}_${hash}`;
4008
3946
  }
@@ -4248,7 +4186,7 @@ function buildProjectedPropertyColumns(alias, plan, dialect) {
4248
4186
  valueType: fieldPlan.typeInfo?.valueType
4249
4187
  });
4250
4188
  columns.push(
4251
- drizzleOrm.sql`CASE WHEN ${drizzleOrm.sql.raw(alias)}.kind = ${kind} THEN ${extracted} ELSE NULL END AS ${quoteIdentifier2(fieldPlan.outputName)}`
4189
+ drizzleOrm.sql`CASE WHEN ${drizzleOrm.sql.raw(alias)}.kind = ${kind} THEN ${extracted} ELSE NULL END AS ${chunkHTGDWIDE_cjs.quoteIdentifier(fieldPlan.outputName)}`
4252
4190
  );
4253
4191
  }
4254
4192
  }
@@ -4833,7 +4771,7 @@ function isColumnPruningEnabled(ast) {
4833
4771
  function markPredicateFieldsAsRequired(requiredColumnsByAlias, expression) {
4834
4772
  switch (expression.__type) {
4835
4773
  case "comparison": {
4836
- markFieldRefAsRequired(requiredColumnsByAlias, expression.left);
4774
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, expression.left);
4837
4775
  return;
4838
4776
  }
4839
4777
  case "string_op":
@@ -4841,7 +4779,7 @@ function markPredicateFieldsAsRequired(requiredColumnsByAlias, expression) {
4841
4779
  case "between":
4842
4780
  case "array_op":
4843
4781
  case "object_op": {
4844
- markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4782
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4845
4783
  return;
4846
4784
  }
4847
4785
  case "and":
@@ -4859,22 +4797,22 @@ function markPredicateFieldsAsRequired(requiredColumnsByAlias, expression) {
4859
4797
  return;
4860
4798
  }
4861
4799
  case "aggregate_comparison": {
4862
- markFieldRefAsRequired(
4800
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(
4863
4801
  requiredColumnsByAlias,
4864
4802
  expression.aggregate.field
4865
4803
  );
4866
4804
  return;
4867
4805
  }
4868
4806
  case "in_subquery": {
4869
- markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4807
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4870
4808
  return;
4871
4809
  }
4872
4810
  case "vector_similarity": {
4873
- markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4811
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4874
4812
  return;
4875
4813
  }
4876
4814
  case "fulltext_match": {
4877
- markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4815
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, expression.field);
4878
4816
  return;
4879
4817
  }
4880
4818
  case "exists": {
@@ -4884,33 +4822,33 @@ function markPredicateFieldsAsRequired(requiredColumnsByAlias, expression) {
4884
4822
  }
4885
4823
  function collectRequiredColumnsByAlias2(ast) {
4886
4824
  const requiredColumnsByAlias = /* @__PURE__ */ new Map();
4887
- addRequiredColumn(requiredColumnsByAlias, ast.start.alias, "id");
4825
+ chunkHTGDWIDE_cjs.addRequiredColumn(requiredColumnsByAlias, ast.start.alias, "id");
4888
4826
  for (const traversal of ast.traversals) {
4889
- addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "id");
4827
+ chunkHTGDWIDE_cjs.addRequiredColumn(requiredColumnsByAlias, traversal.nodeAlias, "id");
4890
4828
  }
4891
4829
  if (ast.selectiveFields && ast.selectiveFields.length > 0) {
4892
4830
  for (const field2 of ast.selectiveFields) {
4893
- markSelectiveFieldAsRequired(requiredColumnsByAlias, field2);
4831
+ chunkHTGDWIDE_cjs.markSelectiveFieldAsRequired(requiredColumnsByAlias, field2);
4894
4832
  }
4895
4833
  } else {
4896
4834
  for (const projectedField of ast.projection.fields) {
4897
4835
  const source = projectedField.source;
4898
4836
  if (source.__type === "field_ref") {
4899
- markFieldRefAsRequired(requiredColumnsByAlias, source);
4837
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, source);
4900
4838
  } else {
4901
- addRequiredColumn(requiredColumnsByAlias, source.field.alias, "id");
4902
- markFieldRefAsRequired(requiredColumnsByAlias, source.field);
4839
+ chunkHTGDWIDE_cjs.addRequiredColumn(requiredColumnsByAlias, source.field.alias, "id");
4840
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, source.field);
4903
4841
  }
4904
4842
  }
4905
4843
  }
4906
4844
  if (ast.groupBy) {
4907
4845
  for (const field2 of ast.groupBy.fields) {
4908
- markFieldRefAsRequired(requiredColumnsByAlias, field2);
4846
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, field2);
4909
4847
  }
4910
4848
  }
4911
4849
  if (ast.orderBy) {
4912
4850
  for (const orderSpec of ast.orderBy) {
4913
- markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
4851
+ chunkHTGDWIDE_cjs.markFieldRefAsRequired(requiredColumnsByAlias, orderSpec.field);
4914
4852
  }
4915
4853
  }
4916
4854
  if (ast.having) {
@@ -4924,7 +4862,7 @@ function collectRequiredColumnsByAlias2(ast) {
4924
4862
  function hasIdEqualityPredicate(expression, alias) {
4925
4863
  switch (expression.__type) {
4926
4864
  case "comparison": {
4927
- return expression.op === "eq" && expression.left.alias === alias && isIdFieldRef(expression.left);
4865
+ return expression.op === "eq" && expression.left.alias === alias && chunkHTGDWIDE_cjs.isIdFieldRef(expression.left);
4928
4866
  }
4929
4867
  case "and": {
4930
4868
  return expression.predicates.some(
@@ -5245,7 +5183,7 @@ function compileSetOperation2(op, graphId, options = "sqlite") {
5245
5183
  );
5246
5184
  }
5247
5185
  function resolveDialectAdapter(dialect, fulltextStrategy) {
5248
- const baseAdapter = chunkFQCQM3KG_cjs.getDialect(dialect);
5186
+ const baseAdapter = chunk3JK66E3I_cjs.getDialect(dialect);
5249
5187
  if (fulltextStrategy === void 0 || fulltextStrategy === baseAdapter.fulltext) {
5250
5188
  return baseAdapter;
5251
5189
  }
@@ -5276,39 +5214,50 @@ function resolveCountAggregateFastPath(ast) {
5276
5214
  return void 0;
5277
5215
  }
5278
5216
  const groupField = ast.groupBy.fields[0];
5279
- if (groupField.alias !== ast.start.alias || !isIdFieldRef(groupField)) {
5217
+ if (groupField.alias !== ast.start.alias || !chunkHTGDWIDE_cjs.isIdFieldRef(groupField)) {
5280
5218
  return void 0;
5281
5219
  }
5282
- let requiresCount = false;
5283
- let requiresCountDistinct = false;
5220
+ let requiresNodeCount = false;
5221
+ let requiresNodeCountDistinct = false;
5222
+ let requiresEdgeCount = false;
5223
+ let requiresEdgeCountDistinct = false;
5284
5224
  for (const projectedField of ast.projection.fields) {
5285
5225
  const source = projectedField.source;
5286
- if (!isAggregateExpr(source)) {
5226
+ if (!chunkHTGDWIDE_cjs.isAggregateExpr(source)) {
5287
5227
  if (source.alias !== ast.start.alias) {
5288
5228
  return void 0;
5289
5229
  }
5290
5230
  continue;
5291
5231
  }
5292
- if (source.field.alias !== traversal.nodeAlias || !isIdFieldRef(source.field)) {
5232
+ if (!chunkHTGDWIDE_cjs.isIdFieldRef(source.field)) {
5233
+ return void 0;
5234
+ }
5235
+ const isNodeTarget = source.field.alias === traversal.nodeAlias;
5236
+ const isEdgeTarget = source.field.alias === traversal.edgeAlias;
5237
+ if (!isNodeTarget && !isEdgeTarget) {
5293
5238
  return void 0;
5294
5239
  }
5295
5240
  if (source.function === "count") {
5296
- requiresCount = true;
5241
+ if (isNodeTarget) requiresNodeCount = true;
5242
+ else requiresEdgeCount = true;
5297
5243
  continue;
5298
5244
  }
5299
5245
  if (source.function === "countDistinct") {
5300
- requiresCountDistinct = true;
5246
+ if (isNodeTarget) requiresNodeCountDistinct = true;
5247
+ else requiresEdgeCountDistinct = true;
5301
5248
  continue;
5302
5249
  }
5303
5250
  return void 0;
5304
5251
  }
5305
- if (!requiresCount && !requiresCountDistinct) {
5252
+ if (!requiresNodeCount && !requiresNodeCountDistinct && !requiresEdgeCount && !requiresEdgeCountDistinct) {
5306
5253
  return void 0;
5307
5254
  }
5308
5255
  return {
5309
5256
  traversal,
5310
- requiresCount,
5311
- requiresCountDistinct
5257
+ requiresNodeCount,
5258
+ requiresNodeCountDistinct,
5259
+ requiresEdgeCount,
5260
+ requiresEdgeCountDistinct
5312
5261
  };
5313
5262
  }
5314
5263
  function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredColumnsByAlias, predicateIndex, temporalFilterPass) {
@@ -5316,15 +5265,23 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
5316
5265
  if (!plan) {
5317
5266
  return void 0;
5318
5267
  }
5319
- const { traversal, requiresCount, requiresCountDistinct } = plan;
5268
+ const {
5269
+ traversal,
5270
+ requiresNodeCount,
5271
+ requiresNodeCountDistinct,
5272
+ requiresEdgeCount,
5273
+ requiresEdgeCountDistinct
5274
+ } = plan;
5320
5275
  const { dialect } = ctx;
5321
5276
  const startAlias = ast.start.alias;
5322
5277
  const previousAlias = traversal.joinFromAlias;
5323
5278
  const previousAliasIdColumn = `${previousAlias}_id`;
5324
5279
  const previousAliasKindColumn = `${previousAlias}_kind`;
5325
5280
  const countCteAlias = `cte_${traversal.nodeAlias}_counts`;
5326
- const countColumn = `${traversal.nodeAlias}_count`;
5327
- const countDistinctColumn = `${traversal.nodeAlias}_count_distinct`;
5281
+ const nodeCountColumn = `${traversal.nodeAlias}_count`;
5282
+ const nodeCountDistinctColumn = `${traversal.nodeAlias}_count_distinct`;
5283
+ const edgeCountColumn = `${traversal.edgeAlias}_count`;
5284
+ const edgeCountDistinctColumn = `${traversal.edgeAlias}_count_distinct`;
5328
5285
  const previousNodeKinds = getNodeKindsForAlias(ast, traversal.joinFromAlias);
5329
5286
  const edgeKinds = [...new Set(traversal.edgeKinds)];
5330
5287
  const nodeKinds = traversal.nodeKinds;
@@ -5350,34 +5307,68 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
5350
5307
  const targetField = traversal.direction === "out" ? "to_id" : "from_id";
5351
5308
  const joinKindField = traversal.direction === "out" ? "from_kind" : "to_kind";
5352
5309
  const targetKindField = traversal.direction === "out" ? "to_kind" : "from_kind";
5310
+ const hasNodePredicates = nodePredicateClauses.length > 0;
5311
+ const requiresNodeJoin = requiresNodeCount || requiresNodeCountDistinct || hasNodePredicates;
5312
+ const useInnerJoin = hasNodePredicates;
5353
5313
  const whereClauses = [
5354
5314
  drizzleOrm.sql`e.graph_id = ${graphId}`,
5355
5315
  compileKindFilter(drizzleOrm.sql.raw("e.kind"), edgeKinds),
5356
5316
  compileKindFilter(drizzleOrm.sql.raw(`e.${joinKindField}`), previousNodeKinds),
5357
5317
  compileKindFilter(drizzleOrm.sql.raw(`e.${targetKindField}`), nodeKinds),
5358
- compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds),
5359
5318
  edgeTemporalFilter,
5360
- nodeTemporalFilter,
5361
- ...nodePredicateClauses,
5362
- ...edgePredicateClauses
5319
+ ...edgePredicateClauses,
5320
+ // INNER JOIN mode: node-side filters in WHERE constrain every aggregate.
5321
+ ...requiresNodeJoin && useInnerJoin ? [
5322
+ compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds),
5323
+ nodeTemporalFilter,
5324
+ ...nodePredicateClauses
5325
+ ] : []
5363
5326
  ];
5327
+ const nodeJoinOnClauses = requiresNodeJoin ? useInnerJoin ? (
5328
+ // INNER JOIN: only the key conditions; filters live in WHERE.
5329
+ [
5330
+ drizzleOrm.sql`n.graph_id = e.graph_id`,
5331
+ drizzleOrm.sql`n.id = e.${drizzleOrm.sql.raw(targetField)}`,
5332
+ drizzleOrm.sql`n.kind = e.${drizzleOrm.sql.raw(targetKindField)}`
5333
+ ]
5334
+ ) : [
5335
+ drizzleOrm.sql`n.graph_id = e.graph_id`,
5336
+ drizzleOrm.sql`n.id = e.${drizzleOrm.sql.raw(targetField)}`,
5337
+ drizzleOrm.sql`n.kind = e.${drizzleOrm.sql.raw(targetKindField)}`,
5338
+ compileKindFilter(drizzleOrm.sql.raw("n.kind"), nodeKinds),
5339
+ nodeTemporalFilter
5340
+ ] : [];
5364
5341
  const aggregateColumns = [];
5365
- if (requiresCount) {
5366
- aggregateColumns.push(drizzleOrm.sql`COUNT(n.id) AS ${drizzleOrm.sql.raw(countColumn)}`);
5342
+ if (requiresNodeCount) {
5343
+ aggregateColumns.push(drizzleOrm.sql`COUNT(n.id) AS ${drizzleOrm.sql.raw(nodeCountColumn)}`);
5344
+ }
5345
+ if (requiresNodeCountDistinct) {
5346
+ aggregateColumns.push(
5347
+ drizzleOrm.sql`COUNT(DISTINCT n.id) AS ${drizzleOrm.sql.raw(nodeCountDistinctColumn)}`
5348
+ );
5367
5349
  }
5368
- if (requiresCountDistinct) {
5350
+ if (requiresEdgeCount) {
5351
+ aggregateColumns.push(drizzleOrm.sql`COUNT(e.id) AS ${drizzleOrm.sql.raw(edgeCountColumn)}`);
5352
+ }
5353
+ if (requiresEdgeCountDistinct) {
5369
5354
  aggregateColumns.push(
5370
- drizzleOrm.sql`COUNT(DISTINCT n.id) AS ${drizzleOrm.sql.raw(countDistinctColumn)}`
5355
+ drizzleOrm.sql`COUNT(DISTINCT e.id) AS ${drizzleOrm.sql.raw(edgeCountDistinctColumn)}`
5371
5356
  );
5372
5357
  }
5358
+ const startCteLimit = traversal.optional && ast.orderBy === void 0 && ast.limit !== void 0 ? { limit: ast.limit, offset: ast.offset } : void 0;
5373
5359
  const startCte = buildStandardStartCte({
5374
5360
  ast,
5375
5361
  ctx,
5376
5362
  graphId,
5377
5363
  predicateIndex,
5378
5364
  requiredColumnsByAlias,
5379
- temporalFilterPass
5365
+ temporalFilterPass,
5366
+ ...startCteLimit === void 0 ? {} : { limitOffset: startCteLimit }
5380
5367
  });
5368
+ const targetNodeJoinKeyword = useInnerJoin ? "JOIN" : "LEFT JOIN";
5369
+ const targetNodeJoin = requiresNodeJoin ? drizzleOrm.sql`
5370
+ ${drizzleOrm.sql.raw(targetNodeJoinKeyword)} ${ctx.schema.nodesTable} n ON ${drizzleOrm.sql.join(nodeJoinOnClauses, drizzleOrm.sql` AND `)}
5371
+ ` : drizzleOrm.sql``;
5381
5372
  const countCte = drizzleOrm.sql`
5382
5373
  ${drizzleOrm.sql.raw(countCteAlias)} AS (
5383
5374
  SELECT
@@ -5386,32 +5377,36 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
5386
5377
  ${drizzleOrm.sql.join(aggregateColumns, drizzleOrm.sql`, `)}
5387
5378
  FROM cte_${drizzleOrm.sql.raw(previousAlias)}
5388
5379
  JOIN ${ctx.schema.edgesTable} e ON cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasIdColumn)} = e.${drizzleOrm.sql.raw(joinField)}
5389
- AND cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)} = e.${drizzleOrm.sql.raw(joinKindField)}
5390
- JOIN ${ctx.schema.nodesTable} n ON n.graph_id = e.graph_id
5391
- AND n.id = e.${drizzleOrm.sql.raw(targetField)}
5392
- AND n.kind = e.${drizzleOrm.sql.raw(targetKindField)}
5380
+ AND cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)} = e.${drizzleOrm.sql.raw(joinKindField)}${targetNodeJoin}
5393
5381
  WHERE ${drizzleOrm.sql.join(whereClauses, drizzleOrm.sql` AND `)}
5394
5382
  GROUP BY
5395
5383
  cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasIdColumn)},
5396
5384
  cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)}
5397
5385
  )
5398
5386
  `;
5387
+ function resolveCountColumn(source) {
5388
+ const isEdge = source.field.alias === traversal.edgeAlias;
5389
+ if (source.function === "countDistinct") {
5390
+ return isEdge ? edgeCountDistinctColumn : nodeCountDistinctColumn;
5391
+ }
5392
+ return isEdge ? edgeCountColumn : nodeCountColumn;
5393
+ }
5399
5394
  const projection = drizzleOrm.sql.join(
5400
5395
  ast.projection.fields.map((projectedField) => {
5401
5396
  const source = projectedField.source;
5402
- if (!isAggregateExpr(source)) {
5397
+ if (!chunkHTGDWIDE_cjs.isAggregateExpr(source)) {
5403
5398
  const value = compileFieldValue(
5404
5399
  source,
5405
5400
  dialect,
5406
5401
  source.valueType,
5407
5402
  `cte_${source.alias}`
5408
5403
  );
5409
- return drizzleOrm.sql`${value} AS ${quoteIdentifier2(projectedField.outputName)}`;
5404
+ return drizzleOrm.sql`${value} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(projectedField.outputName)}`;
5410
5405
  }
5411
- const projectedCountColumn = source.function === "countDistinct" ? countDistinctColumn : countColumn;
5406
+ const projectedCountColumn = resolveCountColumn(source);
5412
5407
  const countValue = drizzleOrm.sql`${drizzleOrm.sql.raw(countCteAlias)}.${drizzleOrm.sql.raw(projectedCountColumn)}`;
5413
5408
  const aggregateValue = traversal.optional ? drizzleOrm.sql`COALESCE(${countValue}, 0)` : countValue;
5414
- return drizzleOrm.sql`${aggregateValue} AS ${quoteIdentifier2(projectedField.outputName)}`;
5409
+ return drizzleOrm.sql`${aggregateValue} AS ${chunkHTGDWIDE_cjs.quoteIdentifier(projectedField.outputName)}`;
5415
5410
  }),
5416
5411
  drizzleOrm.sql`, `
5417
5412
  );
@@ -5423,19 +5418,29 @@ function compileCountAggregateFastPath(ast, graphId, ctx, logicalPlan, requiredC
5423
5418
  AND ${drizzleOrm.sql.raw(countCteAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)} = cte_${drizzleOrm.sql.raw(previousAlias)}.${drizzleOrm.sql.raw(previousAliasKindColumn)}
5424
5419
  `;
5425
5420
  const orderBy = buildStandardOrderBy({ ast, dialect });
5426
- const limitOffset = buildLimitOffsetClause({
5427
- limit: ast.limit,
5428
- offset: ast.offset
5429
- });
5421
+ const emittedLogicalPlan = startCteLimit === void 0 ? logicalPlan : stripLimitOffsetFromPlan(logicalPlan);
5422
+ const limitOffset = startCteLimit === void 0 ? buildLimitOffsetClause({ limit: ast.limit, offset: ast.offset }) : void 0;
5430
5423
  return emitStandardQuerySql({
5431
5424
  ctes: [startCte, countCte],
5432
5425
  fromClause,
5433
5426
  ...orderBy === void 0 ? {} : { orderBy },
5434
5427
  ...limitOffset === void 0 ? {} : { limitOffset },
5435
- logicalPlan,
5428
+ logicalPlan: emittedLogicalPlan,
5436
5429
  projection
5437
5430
  });
5438
5431
  }
5432
+ function stripLimitOffsetFromPlan(plan) {
5433
+ return { ...plan, root: stripLimitOffsetFromPlanNode(plan.root) };
5434
+ }
5435
+ function stripLimitOffsetFromPlanNode(node) {
5436
+ if (node.op === "limit_offset") {
5437
+ return stripLimitOffsetFromPlanNode(node.input);
5438
+ }
5439
+ if ("input" in node) {
5440
+ return { ...node, input: stripLimitOffsetFromPlanNode(node.input) };
5441
+ }
5442
+ return node;
5443
+ }
5439
5444
  var STANDARD_QUERY_STRATEGY_HANDLERS = {
5440
5445
  cte_project: compileStandardQueryWithCteStrategy
5441
5446
  };
@@ -5776,14 +5781,14 @@ function generateId() {
5776
5781
 
5777
5782
  // src/utils/path.ts
5778
5783
  function parseSqlitePath(path) {
5779
- const emptyPath = `${chunkFQCQM3KG_cjs.SQLITE_PATH_DELIMITER}${chunkFQCQM3KG_cjs.SQLITE_PATH_DELIMITER}`;
5784
+ const emptyPath = `${chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER}${chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER}`;
5780
5785
  if (!path || path === emptyPath) return [];
5781
5786
  const trimmed = path.slice(1, -1);
5782
5787
  if (trimmed === "") return [];
5783
- return trimmed.split(chunkFQCQM3KG_cjs.SQLITE_PATH_DELIMITER);
5788
+ return trimmed.split(chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER);
5784
5789
  }
5785
5790
  function isSqlitePath(value) {
5786
- return typeof value === "string" && value.startsWith(chunkFQCQM3KG_cjs.SQLITE_PATH_DELIMITER) && value.endsWith(chunkFQCQM3KG_cjs.SQLITE_PATH_DELIMITER);
5791
+ return typeof value === "string" && value.startsWith(chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER) && value.endsWith(chunk3JK66E3I_cjs.SQLITE_PATH_DELIMITER);
5787
5792
  }
5788
5793
  function normalizePath(value) {
5789
5794
  if (Array.isArray(value)) {
@@ -5798,12 +5803,12 @@ function normalizePath(value) {
5798
5803
  return [];
5799
5804
  }
5800
5805
  function isPostgresTextArray(value) {
5801
- return typeof value === "string" && value.startsWith(chunkFQCQM3KG_cjs.PG_ARRAY_START) && value.endsWith(chunkFQCQM3KG_cjs.PG_ARRAY_END);
5806
+ return typeof value === "string" && value.startsWith(chunk3JK66E3I_cjs.PG_ARRAY_START) && value.endsWith(chunk3JK66E3I_cjs.PG_ARRAY_END);
5802
5807
  }
5803
5808
  function parsePostgresTextArray(value) {
5804
5809
  const inner = value.slice(1, -1);
5805
5810
  if (inner === "") return [];
5806
- return inner.split(chunkFQCQM3KG_cjs.PG_PATH_ELEMENT_SEPARATOR);
5811
+ return inner.split(chunk3JK66E3I_cjs.PG_PATH_ELEMENT_SEPARATOR);
5807
5812
  }
5808
5813
 
5809
5814
  // src/query/execution/result-mapper.ts
@@ -6040,7 +6045,7 @@ async function* createStreamIterable(batchSize, paginate) {
6040
6045
  }
6041
6046
  }
6042
6047
  function getStreamBatchSize(options) {
6043
- return options?.batchSize ?? chunkFQCQM3KG_cjs.DEFAULT_STREAM_BATCH_SIZE;
6048
+ return options?.batchSize ?? chunk3JK66E3I_cjs.DEFAULT_STREAM_BATCH_SIZE;
6044
6049
  }
6045
6050
 
6046
6051
  // src/query/execution/field-tracker.ts
@@ -6122,7 +6127,7 @@ function createNodeTrackingProxy(alias, kindNames, tracker, options) {
6122
6127
  return getPlaceholderForSystemField(property, options.mode);
6123
6128
  }
6124
6129
  if (property === "meta") {
6125
- for (const key of chunkFQCQM3KG_cjs.NODE_META_KEYS) {
6130
+ for (const key of chunk3JK66E3I_cjs.NODE_META_KEYS) {
6126
6131
  tracker.record(alias, `meta.${key}`, true);
6127
6132
  }
6128
6133
  return buildNodeMetaPlaceholder(options.mode);
@@ -6155,7 +6160,7 @@ function createEdgeTrackingProxy(alias, edgeKindNames, tracker, options) {
6155
6160
  return getPlaceholderForSystemField(property, options.mode);
6156
6161
  }
6157
6162
  if (property === "meta") {
6158
- for (const key of chunkFQCQM3KG_cjs.EDGE_META_KEYS) {
6163
+ for (const key of chunk3JK66E3I_cjs.EDGE_META_KEYS) {
6159
6164
  tracker.record(alias, `meta.${key}`, true);
6160
6165
  }
6161
6166
  return buildEdgeMetaPlaceholder(options.mode);
@@ -6924,7 +6929,7 @@ function substituteParameters(ast, bindings) {
6924
6929
  };
6925
6930
  }
6926
6931
  function fillPlaceholders(params, bindings, dialect) {
6927
- const adapter = chunkFQCQM3KG_cjs.getDialect(dialect);
6932
+ const adapter = chunk3JK66E3I_cjs.getDialect(dialect);
6928
6933
  return params.map((parameter) => {
6929
6934
  if (parameter instanceof drizzleOrm.Placeholder) {
6930
6935
  const name = parameter.name;
@@ -8019,7 +8024,7 @@ var ExecutableQuery = class _ExecutableQuery {
8019
8024
  );
8020
8025
  }
8021
8026
  const isBackward = options.last !== void 0 || options.before !== void 0;
8022
- const limit = options.first ?? options.last ?? chunkFQCQM3KG_cjs.DEFAULT_PAGINATION_LIMIT;
8027
+ const limit = options.first ?? options.last ?? chunk3JK66E3I_cjs.DEFAULT_PAGINATION_LIMIT;
8023
8028
  const cursor = options.after ?? options.before;
8024
8029
  let cursorData;
8025
8030
  if (cursor) {
@@ -9360,6 +9365,12 @@ function countDistinct(alias, field2) {
9360
9365
  }
9361
9366
  };
9362
9367
  }
9368
+ function countEdges(edgeAlias) {
9369
+ return count(edgeAlias);
9370
+ }
9371
+ function countDistinctEdges(edgeAlias) {
9372
+ return countDistinct(edgeAlias);
9373
+ }
9363
9374
  function sum(alias, field2) {
9364
9375
  return {
9365
9376
  __type: "aggregate",
@@ -9765,7 +9776,7 @@ function createGraphAlgorithms(params) {
9765
9776
  const ctx = {
9766
9777
  graphId: params.graphId,
9767
9778
  backend: params.backend,
9768
- dialect: chunkFQCQM3KG_cjs.getDialect(params.backend.dialect),
9779
+ dialect: chunk3JK66E3I_cjs.getDialect(params.backend.dialect),
9769
9780
  schema: params.schema ?? (params.backend.tableNames ? createSqlSchema(params.backend.tableNames) : createSqlSchema()),
9770
9781
  defaultTemporalMode: params.defaultTemporalMode
9771
9782
  };
@@ -12705,17 +12716,17 @@ async function rebuildFulltextIndex(ctx, nodeKind, options) {
12705
12716
  if (remaining > 0 && pageResult.skippedIds.length > 0) {
12706
12717
  skippedIds.push(...pageResult.skippedIds.slice(0, remaining));
12707
12718
  }
12708
- await backend.transaction(async (tx) => {
12719
+ const writePage = async (target) => {
12709
12720
  if (pageResult.toUpsert.length > 0) {
12710
- if (tx.upsertFulltextBatch) {
12711
- await tx.upsertFulltextBatch({
12721
+ if (target.upsertFulltextBatch) {
12722
+ await target.upsertFulltextBatch({
12712
12723
  graphId: ctx.graphId,
12713
12724
  nodeKind: kind,
12714
12725
  rows: pageResult.toUpsert
12715
12726
  });
12716
- } else if (tx.upsertFulltext) {
12727
+ } else if (target.upsertFulltext) {
12717
12728
  for (const item of pageResult.toUpsert) {
12718
- await tx.upsertFulltext({
12729
+ await target.upsertFulltext({
12719
12730
  graphId: ctx.graphId,
12720
12731
  nodeKind: kind,
12721
12732
  nodeId: item.nodeId,
@@ -12726,15 +12737,15 @@ async function rebuildFulltextIndex(ctx, nodeKind, options) {
12726
12737
  }
12727
12738
  }
12728
12739
  if (pageResult.toDelete.length > 0) {
12729
- if (tx.deleteFulltextBatch) {
12730
- await tx.deleteFulltextBatch({
12740
+ if (target.deleteFulltextBatch) {
12741
+ await target.deleteFulltextBatch({
12731
12742
  graphId: ctx.graphId,
12732
12743
  nodeKind: kind,
12733
12744
  nodeIds: pageResult.toDelete
12734
12745
  });
12735
- } else if (tx.deleteFulltext) {
12746
+ } else if (target.deleteFulltext) {
12736
12747
  for (const nodeId of pageResult.toDelete) {
12737
- await tx.deleteFulltext({
12748
+ await target.deleteFulltext({
12738
12749
  graphId: ctx.graphId,
12739
12750
  nodeKind: kind,
12740
12751
  nodeId
@@ -12742,7 +12753,8 @@ async function rebuildFulltextIndex(ctx, nodeKind, options) {
12742
12753
  }
12743
12754
  }
12744
12755
  }
12745
- });
12756
+ };
12757
+ await chunkRNUNP5JD_cjs.runOptionallyInTransaction(backend, writePage);
12746
12758
  processed += rows.length;
12747
12759
  upserted += pageResult.toUpsert.length;
12748
12760
  cleared += pageResult.toDelete.length;
@@ -13424,12 +13436,19 @@ var Store = class {
13424
13436
  }
13425
13437
  // === Batch Query Execution ===
13426
13438
  /**
13427
- * Executes multiple queries over a single connection with snapshot consistency.
13439
+ * Executes multiple queries and returns a typed tuple of results.
13428
13440
  *
13429
- * Acquires one connection via an implicit transaction, executes each query
13430
- * sequentially on that connection, and returns a typed tuple of results.
13431
- * Each query preserves its own result type, projection, filtering,
13432
- * sorting, and pagination.
13441
+ * Each query preserves its own result type, projection, filtering, sorting,
13442
+ * and pagination.
13443
+ *
13444
+ * **Snapshot consistency is conditional.** When
13445
+ * `backend.capabilities.transactions` is `true`, queries run sequentially
13446
+ * on a single connection inside an implicit transaction and observe the
13447
+ * same database snapshot. When transactions are unavailable
13448
+ * (Cloudflare D1, `drizzle-orm/neon-http`), queries run sequentially over
13449
+ * independent connections and may observe writes that landed between them.
13450
+ * Branch on `backend.capabilities.transactions` if you need a guaranteed
13451
+ * snapshot.
13433
13452
  *
13434
13453
  * Read-only — use `bulkCreate`, `bulkInsert`, etc. for write batching.
13435
13454
  *
@@ -13453,10 +13472,10 @@ var Store = class {
13453
13472
  * @returns A tuple with per-query typed results, preserving input order
13454
13473
  */
13455
13474
  async batch(...queries) {
13456
- return this.#backend.transaction(async (txBackend) => {
13475
+ return chunkRNUNP5JD_cjs.runOptionallyInTransaction(this.#backend, async (target) => {
13457
13476
  const results = [];
13458
13477
  for (const query of queries) {
13459
- const result = await query.executeOn(txBackend);
13478
+ const result = await query.executeOn(target);
13460
13479
  results.push(result);
13461
13480
  }
13462
13481
  return results;
@@ -13495,7 +13514,7 @@ var Store = class {
13495
13514
  graphId: this.graphId,
13496
13515
  rootId,
13497
13516
  backend: this.#backend,
13498
- dialect: chunkFQCQM3KG_cjs.getDialect(this.#backend.dialect),
13517
+ dialect: chunk3JK66E3I_cjs.getDialect(this.#backend.dialect),
13499
13518
  schema: this.#schema,
13500
13519
  options
13501
13520
  });
@@ -13520,8 +13539,26 @@ var Store = class {
13520
13539
  * );
13521
13540
  * });
13522
13541
  * ```
13542
+ *
13543
+ * **Backends without transactions.** When `backend.capabilities.transactions`
13544
+ * is `false` (Cloudflare D1, `drizzle-orm/neon-http`), this method runs the
13545
+ * callback against the same backend used outside `transaction()` — writes
13546
+ * are applied as they happen and a thrown error does **not** roll back
13547
+ * earlier writes inside the callback. Branch on
13548
+ * `backend.capabilities.transactions` if you require atomicity:
13549
+ *
13550
+ * ```typescript
13551
+ * if (backend.capabilities.transactions) {
13552
+ * await store.transaction(async (tx) => { ... });
13553
+ * } else {
13554
+ * // sequential, non-atomic — handle partial-failure recovery yourself
13555
+ * }
13556
+ * ```
13523
13557
  */
13524
13558
  async transaction(fn) {
13559
+ if (!this.#backend.capabilities.transactions) {
13560
+ return fn({ nodes: this.nodes, edges: this.edges });
13561
+ }
13525
13562
  return this.#backend.transaction(async (txBackend) => {
13526
13563
  const txNodeOperations = {
13527
13564
  ...this.#nodeOperations,
@@ -13569,6 +13606,36 @@ var Store = class {
13569
13606
  this.#search = void 0;
13570
13607
  }
13571
13608
  // === Lifecycle ===
13609
+ /**
13610
+ * Refreshes the backend's query-planner statistics.
13611
+ *
13612
+ * Call this once after a large initial import or bulk backfill. The
13613
+ * planner uses table statistics to choose between TypeGraph's
13614
+ * multi-column indexes; without fresh stats a forward traversal can
13615
+ * pick a reverse index and run an order of magnitude slower than
13616
+ * needed. Autovacuum / background statistics will catch up
13617
+ * eventually, but calling this explicitly after a bulk load gives
13618
+ * you correct latencies immediately.
13619
+ *
13620
+ * Implementations:
13621
+ * - SQLite runs `ANALYZE`, populating `sqlite_stat1`
13622
+ * - PostgreSQL runs `ANALYZE` on the TypeGraph-managed tables
13623
+ *
13624
+ * Costs a few tens of milliseconds at the sizes this library is
13625
+ * designed for. Safe to call at any time.
13626
+ *
13627
+ * @example
13628
+ * ```typescript
13629
+ * // After a bulk import
13630
+ * for (const batch of batches) {
13631
+ * await store.nodes.Document.bulkCreate(batch);
13632
+ * }
13633
+ * await store.refreshStatistics();
13634
+ * ```
13635
+ */
13636
+ async refreshStatistics() {
13637
+ await this.#backend.refreshStatistics();
13638
+ }
13572
13639
  /**
13573
13640
  * Closes the store and releases underlying resources.
13574
13641
  *
@@ -13807,11 +13874,11 @@ Object.defineProperty(exports, "isUserRecoverable", {
13807
13874
  });
13808
13875
  Object.defineProperty(exports, "fts5Strategy", {
13809
13876
  enumerable: true,
13810
- get: function () { return chunkFQCQM3KG_cjs.fts5Strategy; }
13877
+ get: function () { return chunk3JK66E3I_cjs.fts5Strategy; }
13811
13878
  });
13812
13879
  Object.defineProperty(exports, "tsvectorStrategy", {
13813
13880
  enumerable: true,
13814
- get: function () { return chunkFQCQM3KG_cjs.tsvectorStrategy; }
13881
+ get: function () { return chunk3JK66E3I_cjs.tsvectorStrategy; }
13815
13882
  });
13816
13883
  Object.defineProperty(exports, "DEFAULT_SEARCHABLE_LANGUAGE", {
13817
13884
  enumerable: true,
@@ -13876,6 +13943,8 @@ exports.composeFragments = composeFragments;
13876
13943
  exports.core = core;
13877
13944
  exports.count = count;
13878
13945
  exports.countDistinct = countDistinct;
13946
+ exports.countDistinctEdges = countDistinctEdges;
13947
+ exports.countEdges = countEdges;
13879
13948
  exports.createExternalRef = createExternalRef;
13880
13949
  exports.createFragment = createFragment;
13881
13950
  exports.createQueryBuilder = createQueryBuilder;