@nicia-ai/typegraph 0.35.0 → 0.36.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 (116) hide show
  1. package/dist/backend/postgres/index.cjs +19 -19
  2. package/dist/backend/postgres/index.js +6 -6
  3. package/dist/backend/postgres/pglite.cjs +11 -11
  4. package/dist/backend/postgres/pglite.js +6 -6
  5. package/dist/backend/sqlite/index.cjs +9 -9
  6. package/dist/backend/sqlite/index.js +6 -6
  7. package/dist/backend/sqlite/libsql.cjs +8 -8
  8. package/dist/backend/sqlite/libsql.js +6 -6
  9. package/dist/backend/sqlite/local.cjs +16 -16
  10. package/dist/backend/sqlite/local.js +6 -6
  11. package/dist/{chunk-VPYHY3LJ.cjs → chunk-2THZ3TQI.cjs} +11 -11
  12. package/dist/{chunk-VPYHY3LJ.cjs.map → chunk-2THZ3TQI.cjs.map} +1 -1
  13. package/dist/{chunk-EM3CWPND.cjs → chunk-456Z2U7Y.cjs} +51 -51
  14. package/dist/{chunk-EM3CWPND.cjs.map → chunk-456Z2U7Y.cjs.map} +1 -1
  15. package/dist/{chunk-GSQ6NPH6.cjs → chunk-4BCU6VFZ.cjs} +7 -7
  16. package/dist/{chunk-GSQ6NPH6.cjs.map → chunk-4BCU6VFZ.cjs.map} +1 -1
  17. package/dist/chunk-4BMPGT35.cjs +12 -0
  18. package/dist/{chunk-GUR2FNB5.cjs.map → chunk-4BMPGT35.cjs.map} +1 -1
  19. package/dist/{chunk-WJT7OU7E.cjs → chunk-4CAXEB2F.cjs} +124 -92
  20. package/dist/chunk-4CAXEB2F.cjs.map +1 -0
  21. package/dist/{chunk-WDBCBWC4.js → chunk-4GX2JJXS.js} +6 -6
  22. package/dist/{chunk-WDBCBWC4.js.map → chunk-4GX2JJXS.js.map} +1 -1
  23. package/dist/{chunk-UES55P7G.js → chunk-5DIPR3L3.js} +284 -154
  24. package/dist/chunk-5DIPR3L3.js.map +1 -0
  25. package/dist/{chunk-CZQ3FO2Q.js → chunk-5VTR2F2K.js} +49 -16
  26. package/dist/chunk-5VTR2F2K.js.map +1 -0
  27. package/dist/{chunk-CTTSDJLY.cjs → chunk-5W4L6DLF.cjs} +11 -11
  28. package/dist/{chunk-CTTSDJLY.cjs.map → chunk-5W4L6DLF.cjs.map} +1 -1
  29. package/dist/{chunk-J7WFGBJR.cjs → chunk-7BQLPXK6.cjs} +865 -735
  30. package/dist/chunk-7BQLPXK6.cjs.map +1 -0
  31. package/dist/{chunk-3TWF3SH4.js → chunk-BJVEU3ZL.js} +7 -7
  32. package/dist/{chunk-3TWF3SH4.js.map → chunk-BJVEU3ZL.js.map} +1 -1
  33. package/dist/{chunk-LGEALRC6.cjs → chunk-DIK74MXX.cjs} +18 -2
  34. package/dist/chunk-DIK74MXX.cjs.map +1 -0
  35. package/dist/{chunk-QNKSQTKQ.js → chunk-DN5VP4JC.js} +48 -17
  36. package/dist/chunk-DN5VP4JC.js.map +1 -0
  37. package/dist/{chunk-4JEZZJ6S.cjs → chunk-HW3LW7DH.cjs} +39 -39
  38. package/dist/{chunk-4JEZZJ6S.cjs.map → chunk-HW3LW7DH.cjs.map} +1 -1
  39. package/dist/{chunk-JBTOYDMN.js → chunk-IU46OHVW.js} +4 -4
  40. package/dist/{chunk-JBTOYDMN.js.map → chunk-IU46OHVW.js.map} +1 -1
  41. package/dist/{chunk-FL472AMI.cjs → chunk-J3LEGNQB.cjs} +8 -8
  42. package/dist/{chunk-FL472AMI.cjs.map → chunk-J3LEGNQB.cjs.map} +1 -1
  43. package/dist/{chunk-O7UN7OXA.cjs → chunk-JFMEONLG.cjs} +80 -80
  44. package/dist/{chunk-O7UN7OXA.cjs.map → chunk-JFMEONLG.cjs.map} +1 -1
  45. package/dist/{chunk-I7ZUZKFD.js → chunk-JFUPDJXD.js} +3 -3
  46. package/dist/{chunk-I7ZUZKFD.js.map → chunk-JFUPDJXD.js.map} +1 -1
  47. package/dist/{chunk-K3PPLHY7.js → chunk-M75SUBFG.js} +7 -7
  48. package/dist/{chunk-K3PPLHY7.js.map → chunk-M75SUBFG.js.map} +1 -1
  49. package/dist/{chunk-CK5BVQOW.cjs → chunk-PWGX5DF5.cjs} +79 -79
  50. package/dist/{chunk-CK5BVQOW.cjs.map → chunk-PWGX5DF5.cjs.map} +1 -1
  51. package/dist/{chunk-KMI7LYAF.js → chunk-PZKNKG5M.js} +8 -8
  52. package/dist/{chunk-KMI7LYAF.js.map → chunk-PZKNKG5M.js.map} +1 -1
  53. package/dist/{chunk-55MZDDZV.js → chunk-RAXU3RMB.js} +4 -4
  54. package/dist/{chunk-55MZDDZV.js.map → chunk-RAXU3RMB.js.map} +1 -1
  55. package/dist/{chunk-BLZDPRXT.cjs → chunk-RSSQKPSZ.cjs} +5 -5
  56. package/dist/{chunk-BLZDPRXT.cjs.map → chunk-RSSQKPSZ.cjs.map} +1 -1
  57. package/dist/{chunk-RGPG7EOJ.js → chunk-S5F7ZLP2.js} +3 -3
  58. package/dist/{chunk-RGPG7EOJ.js.map → chunk-S5F7ZLP2.js.map} +1 -1
  59. package/dist/{chunk-QWEUYILR.js → chunk-SKCOUWAX.js} +3 -3
  60. package/dist/{chunk-QWEUYILR.js.map → chunk-SKCOUWAX.js.map} +1 -1
  61. package/dist/{chunk-QOTI55H7.js → chunk-SXGE7ITL.js} +4 -4
  62. package/dist/{chunk-QOTI55H7.js.map → chunk-SXGE7ITL.js.map} +1 -1
  63. package/dist/{chunk-RGP33ZJ5.js → chunk-VQEXF5D4.js} +7 -7
  64. package/dist/{chunk-RGP33ZJ5.js.map → chunk-VQEXF5D4.js.map} +1 -1
  65. package/dist/{chunk-MP2JQKSG.js → chunk-WI7ISNQF.js} +17 -3
  66. package/dist/chunk-WI7ISNQF.js.map +1 -0
  67. package/dist/{chunk-4TOD4LBZ.cjs → chunk-X4JBT642.cjs} +29 -29
  68. package/dist/{chunk-4TOD4LBZ.cjs.map → chunk-X4JBT642.cjs.map} +1 -1
  69. package/dist/{chunk-EMF62TZG.cjs → chunk-ZAMFOJ5P.cjs} +86 -86
  70. package/dist/{chunk-EMF62TZG.cjs.map → chunk-ZAMFOJ5P.cjs.map} +1 -1
  71. package/dist/{chunk-VSPCZAXF.js → chunk-ZIGXMKQQ.js} +3 -3
  72. package/dist/{chunk-VSPCZAXF.js.map → chunk-ZIGXMKQQ.js.map} +1 -1
  73. package/dist/{chunk-XOX22WHL.cjs → chunk-ZUNQ5BEP.cjs} +104 -71
  74. package/dist/chunk-ZUNQ5BEP.cjs.map +1 -0
  75. package/dist/graph-extension/index.cjs +19 -19
  76. package/dist/graph-extension/index.d.cts +1 -1
  77. package/dist/graph-extension/index.d.ts +1 -1
  78. package/dist/graph-extension/index.js +4 -4
  79. package/dist/graph-merge/index.cjs +82 -82
  80. package/dist/graph-merge/index.cjs.map +1 -1
  81. package/dist/graph-merge/index.d.cts +2 -2
  82. package/dist/graph-merge/index.d.ts +2 -2
  83. package/dist/graph-merge/index.js +13 -13
  84. package/dist/graph-merge/index.js.map +1 -1
  85. package/dist/{index-6CSUAq-x.d.ts → index-BFvdmBPV.d.ts} +68 -1
  86. package/dist/{index-Bks_3HHK.d.cts → index-BLtQWKRj.d.cts} +68 -1
  87. package/dist/index.cjs +144 -136
  88. package/dist/index.d.cts +3 -3
  89. package/dist/index.d.ts +3 -3
  90. package/dist/index.js +14 -14
  91. package/dist/interchange/index.cjs +27 -26
  92. package/dist/interchange/index.d.cts +1 -1
  93. package/dist/interchange/index.d.ts +1 -1
  94. package/dist/interchange/index.js +9 -8
  95. package/dist/profiler/index.d.cts +1 -1
  96. package/dist/profiler/index.d.ts +1 -1
  97. package/dist/provenance/index.cjs +31 -31
  98. package/dist/provenance/index.d.cts +1 -1
  99. package/dist/provenance/index.d.ts +1 -1
  100. package/dist/provenance/index.js +4 -4
  101. package/dist/schema/index.cjs +31 -31
  102. package/dist/schema/index.d.cts +1 -1
  103. package/dist/schema/index.d.ts +1 -1
  104. package/dist/schema/index.js +7 -7
  105. package/dist/{store-view-BSpqvAxK.d.cts → store-view-9KDOpZzF.d.cts} +250 -36
  106. package/dist/{store-view-CKbHFRnn.d.ts → store-view-DplHC3Nt.d.ts} +250 -36
  107. package/package.json +1 -1
  108. package/dist/chunk-CZQ3FO2Q.js.map +0 -1
  109. package/dist/chunk-GUR2FNB5.cjs +0 -12
  110. package/dist/chunk-J7WFGBJR.cjs.map +0 -1
  111. package/dist/chunk-LGEALRC6.cjs.map +0 -1
  112. package/dist/chunk-MP2JQKSG.js.map +0 -1
  113. package/dist/chunk-QNKSQTKQ.js.map +0 -1
  114. package/dist/chunk-UES55P7G.js.map +0 -1
  115. package/dist/chunk-WJT7OU7E.cjs.map +0 -1
  116. package/dist/chunk-XOX22WHL.cjs.map +0 -1
@@ -1,23 +1,23 @@
1
- import { createEdgeRowMapper, createNodeRowMapper, POSTGRES_ROW_MAPPER_CONFIG, SQLITE_ROW_MAPPER_CONFIG, quoteIdentifier, EMPTY_REQUIRED_COLUMNS, addRequiredColumn, mapSelectiveSystemFieldToColumn, markFieldRefAsRequired, findSelectivePropsFieldForFieldRef, markSelectiveFieldAsRequired, NODE_COLUMNS, shouldProjectColumn, isIdFieldRef, isAggregateExpr, EDGE_COLUMNS } from './chunk-55MZDDZV.js';
2
- import { rowToNode, executeNodeBulkFindByIndex, executeNodeBulkFindByConstraint, executeNodeFindByConstraint, executeNodeBulkGetOrCreateByConstraint, executeNodeGetOrCreateByConstraint, executeNodeHardDelete, executeNodeDelete, executeNodeUpsertUpdate, executeNodeUpdate, executeNodeCreateNoReturnBatch, executeNodeCreateBatch, executeNodeCreate, rowToEdge, runInWriteTransaction, checkCardinalityConstraint, runHookedWriteOperation, rowToNodeMeta, rowToEdgeMeta } from './chunk-QNKSQTKQ.js';
3
- import { loadAndMergeGraphExtensionDocument, ensureSchema, loadAndVerifyGraph, buildKindRegistry, mergeGraphExtension, commitNewSchemaVersion, applyDeprecatedKinds, loadActiveSchemaWithBootstrap, parseSerializedSchema, extensionKindNames, serializeSchemaProperties, buildGraphExtensionOntologyKeySet, compileTimeOntologyKey, getTypeName, serializeIndexDeclaration } from './chunk-K3PPLHY7.js';
4
- import { sortedReplacer, canonicalEqual } from './chunk-UR7W5YQK.js';
5
- import { isKnownKind, validateEdgeProps } from './chunk-QWEUYILR.js';
1
+ import { createEdgeRowMapper, createNodeRowMapper, POSTGRES_ROW_MAPPER_CONFIG, SQLITE_ROW_MAPPER_CONFIG, quoteIdentifier, EMPTY_REQUIRED_COLUMNS, addRequiredColumn, mapSelectiveSystemFieldToColumn, markFieldRefAsRequired, findSelectivePropsFieldForFieldRef, markSelectiveFieldAsRequired, NODE_COLUMNS, shouldProjectColumn, isIdFieldRef, isAggregateExpr, EDGE_COLUMNS } from './chunk-RAXU3RMB.js';
2
+ import { rowToNode, executeNodeBulkFindByIndex, executeNodeBulkFindByConstraint, executeNodeFindByConstraint, executeNodeBulkGetOrCreateByConstraint, executeNodeGetOrCreateByConstraint, executeNodeHardDelete, executeNodeDelete, nodeUpsertDirtyCheck, executeNodeUpsertUpdate, executeNodeUpdate, executeNodeCreateNoReturnBatch, executeNodeCreateBatch, executeNodeCreate, rowToEdge, runInWriteTransaction, checkCardinalityConstraint, runHookedWriteOperation, rowToNodeMeta, rowToEdgeMeta } from './chunk-DN5VP4JC.js';
3
+ import { loadAndMergeGraphExtensionDocument, ensureSchema, loadAndVerifyGraph, buildKindRegistry, mergeGraphExtension, commitNewSchemaVersion, applyDeprecatedKinds, loadActiveSchemaWithBootstrap, parseSerializedSchema, extensionKindNames, serializeSchemaProperties, buildGraphExtensionOntologyKeySet, compileTimeOntologyKey, getTypeName, serializeIndexDeclaration } from './chunk-M75SUBFG.js';
4
+ import { isKnownKind, validateEdgeProps } from './chunk-SKCOUWAX.js';
5
+ import { canonicalEqual, sortedReplacer } from './chunk-UR7W5YQK.js';
6
6
  import { generateIndexDDL } from './chunk-UZV3AZKF.js';
7
7
  import { NODE_META_KEYS, EDGE_META_KEYS } from './chunk-OR5ZA5WP.js';
8
8
  import { sha256Hex, fnv1aBase36 } from './chunk-W63OVYY4.js';
9
9
  import { getDialect, assertVectorMinScore, vectorScoreExpression, vectorMinScoreCondition } from './chunk-FPIZFYHE.js';
10
10
  import { createSchemaIntrospector } from './chunk-5SEGFTZX.js';
11
- import { IncompatibleChangeError, RemoveCompileTimeKindError, KindHasReferentsError } from './chunk-QOTI55H7.js';
12
- import { validateProjectionField } from './chunk-RGPG7EOJ.js';
11
+ import { IncompatibleChangeError, RemoveCompileTimeKindError, KindHasReferentsError } from './chunk-SXGE7ITL.js';
12
+ import { validateProjectionField } from './chunk-S5F7ZLP2.js';
13
13
  import { compareStrings, compareCodePoints } from './chunk-BYPOGQWK.js';
14
- import { resolveReadCoordinate, withRecordedCoordinate, describeCoordinate, coordinateContext, DEFAULT_SQL_SCHEMA, requireSqlSchema, recordedReadSchemaFor, assertRevisionTrackableBackend, createSqlSchema, requireExternalRecordedReadSource, createRecordedReadBinding, createRecordedBackend, readRecordedClock, asRecordedInstant, ensureRevisionOrigin, withRecordedFlushObserver, recordedCaptureRequiresCallbackTransactionError, assertRecordedCaptureTransactionIsolation, createRecordedTransactionScope, lockRecordedGraphWrite, createHistoryUnsafeSqlRef, createRevisionTrackingUnsafeSqlRef, generateId, vectorSlotKey, computeFulltextContent, advanceRevisionClock, recordedReadSqlSchema, requireRecordedReadBinding, runInsertBatch, edgeInsertDispatch, runInsertBatchReturning, getEmbeddingFields, getNodeRowsByIds, getEdgeRowsByIds, assertValidRecordedInstant, validateEdgeEndpoints, recordedBindParamBudget, closeRecordedHardDeletedKind, ALIAS_CTE_PREFIX, EMBEDDINGS_CTE_ALIAS, FULLTEXT_CTE_ALIAS, HYBRID_CANDIDATES_CTE_ALIAS } from './chunk-CZQ3FO2Q.js';
14
+ import { resolveReadCoordinate, withRecordedCoordinate, describeCoordinate, coordinateContext, DEFAULT_SQL_SCHEMA, requireSqlSchema, recordedReadSchemaFor, assertRevisionTrackableBackend, createSqlSchema, requireExternalRecordedReadSource, createRecordedReadBinding, createRecordedBackend, readRecordedClock, asRecordedInstant, ensureRevisionOrigin, withRecordedFlushObserver, recordedCaptureRequiresCallbackTransactionError, assertRecordedCaptureTransactionIsolation, createRecordedTransactionScope, lockRecordedGraphWrite, createHistoryUnsafeSqlRef, createRevisionTrackingUnsafeSqlRef, generateId, vectorSlotKey, computeFulltextContent, advanceRevisionClock, recordedReadSqlSchema, requireRecordedReadBinding, runInsertBatch, edgeInsertDispatch, runInsertBatchReturning, getEmbeddingFields, getNodeRowsByIds, getEdgeRowsByIds, assertValidRecordedInstant, validateEdgeEndpoints, recordedBindParamBudget, closeRecordedHardDeletedKind, ALIAS_CTE_PREFIX, EMBEDDINGS_CTE_ALIAS, FULLTEXT_CTE_ALIAS, HYBRID_CANDIDATES_CTE_ALIAS } from './chunk-5VTR2F2K.js';
15
15
  import { markAnnIndexScan, asCompiledSelectSql, isRawExecutable, annIndexScanTypes, asCompiledRowsSql, markForceCustomPlan, asCompiledStatementSql } from './chunk-UT3S4SEN.js';
16
- import { isParameterRef, fieldRef, buildFieldBuilderForTypeInfo, stringField, createFulltextAccessor, CURRENT_READ_INSTANT_PLACEHOLDER, withPinnedReadInstant, runOptionallyInTransaction, baseField, objectField, arrayField, dateField, numberField, rowPropsToObject, createBackendOverlay, compileKindFilter, currentReadInstant, compileTemporalFilter, sqlValueList, chunk, buildPredicateIndex, compileFieldValue, extractVectorSimilarityPredicates, extractFulltextMatchPredicates, currentReadInstantFor, extractTemporalOptions, compilePredicateExpression, getPredicatesForAlias, getNodeKindsForAlias, getHybridTargetAlias, compilePredicateClauses } from './chunk-JBTOYDMN.js';
17
- import { withRecordedRelationsPrecondition, nowIso, validateOptionalCanonicalIsoDate, isMissingTableError } from './chunk-I7ZUZKFD.js';
16
+ import { isParameterRef, fieldRef, buildFieldBuilderForTypeInfo, stringField, createFulltextAccessor, CURRENT_READ_INSTANT_PLACEHOLDER, withPinnedReadInstant, runOptionallyInTransaction, baseField, objectField, arrayField, dateField, numberField, rowPropsToObject, createBackendOverlay, compileKindFilter, currentReadInstant, compileTemporalFilter, sqlValueList, chunk, buildPredicateIndex, compileFieldValue, extractVectorSimilarityPredicates, extractFulltextMatchPredicates, currentReadInstantFor, extractTemporalOptions, compilePredicateExpression, getPredicatesForAlias, getNodeKindsForAlias, getHybridTargetAlias, compilePredicateClauses } from './chunk-IU46OHVW.js';
17
+ import { withRecordedRelationsPrecondition, nowIso, validateOptionalCanonicalIsoDate, isMissingTableError } from './chunk-JFUPDJXD.js';
18
18
  import { DEFAULT_PAGINATION_LIMIT, DEFAULT_STREAM_BATCH_SIZE, SQLITE_PATH_DELIMITER, PG_ARRAY_START, PG_ARRAY_END, PG_PATH_ELEMENT_SEPARATOR, MAX_PG_IDENTIFIER_LENGTH } from './chunk-OHMP6N2J.js';
19
19
  import { getSearchableFields, resolveEmbeddingFields, resolveDeclaredFulltextLanguage } from './chunk-KBGQIPRQ.js';
20
- import { ConfigurationError, UnsupportedPredicateError, ValidationError, KindNotFoundError, EndpointError, EagerMaterializationError, CompilerInvariantError, CardinalityError, EdgeNotFoundError, DatabaseOperationError, EndpointNotFoundError } from './chunk-MP2JQKSG.js';
20
+ import { ConfigurationError, UnsupportedPredicateError, ValidationError, KindNotFoundError, EndpointError, EagerMaterializationError, CompilerInvariantError, CardinalityError, EdgeNotFoundError, DatabaseOperationError, EndpointNotFoundError } from './chunk-WI7ISNQF.js';
21
21
  import { jsonPointer, parseJsonPointer, resolveJsonPointer } from './chunk-G6Q5UM7U.js';
22
22
  import { Placeholder, sql } from 'drizzle-orm';
23
23
 
@@ -10955,32 +10955,70 @@ function createEdgeCollection(config) {
10955
10955
  const upsertAll = async (target) => {
10956
10956
  const ids = items.map((item) => item.id);
10957
10957
  const existingMap = await getEdgeRowsByIds(target, graphId, ids);
10958
+ const results2 = Array.from({ length: items.length });
10958
10959
  const toCreate = [];
10959
10960
  const toUpdate = [];
10961
+ const pending = /* @__PURE__ */ new Map();
10962
+ const deferred = [];
10960
10963
  let itemIndex = 0;
10961
10964
  for (const item of items) {
10962
- const existing = existingMap.get(item.id);
10963
- if (existing) {
10964
- toUpdate.push({
10965
- index: itemIndex,
10966
- input: buildUpdateEdgeInput(item.id, item.props ?? {}, item),
10967
- clearDeleted: existing.deleted_at !== void 0
10968
- });
10969
- } else {
10965
+ const pendingEntry = pending.get(item.id);
10966
+ const original = existingMap.get(item.id);
10967
+ const inputProps = item.props ?? {};
10968
+ if (pendingEntry === void 0 && original === void 0) {
10970
10969
  toCreate.push({
10971
10970
  index: itemIndex,
10972
10971
  input: buildCreateEdgeInput(
10973
10972
  kind,
10974
10973
  item.from,
10975
10974
  item.to,
10976
- item.props ?? {},
10975
+ inputProps,
10977
10976
  item
10978
10977
  )
10979
10978
  });
10979
+ itemIndex++;
10980
+ continue;
10981
+ }
10982
+ const deletedAt = pendingEntry === void 0 ? original.deleted_at : void 0;
10983
+ let dirty;
10984
+ if (config.upsertDirtyCheck !== void 0) {
10985
+ const currentProps = pendingEntry?.props ?? rowPropsToObject(original.props);
10986
+ try {
10987
+ dirty = config.upsertDirtyCheck(
10988
+ original?.kind ?? kind,
10989
+ item.id,
10990
+ currentProps,
10991
+ inputProps
10992
+ );
10993
+ } catch {
10994
+ dirty = void 0;
10995
+ }
10996
+ }
10997
+ const coalesce = dirty?.unchanged === true && deletedAt === void 0 && item.validFrom === void 0 && item.validTo === void 0;
10998
+ if (coalesce) {
10999
+ if (pendingEntry === void 0) {
11000
+ results2[itemIndex] = narrowEdge(rowToEdge2(original));
11001
+ } else {
11002
+ deferred.push({
11003
+ index: itemIndex,
11004
+ sourceIndex: pendingEntry.sourceIndex
11005
+ });
11006
+ }
11007
+ } else {
11008
+ toUpdate.push({
11009
+ index: itemIndex,
11010
+ input: buildUpdateEdgeInput(item.id, inputProps, item),
11011
+ clearDeleted: deletedAt !== void 0
11012
+ });
11013
+ if (dirty !== void 0) {
11014
+ pending.set(item.id, {
11015
+ props: dirty.validatedProps,
11016
+ sourceIndex: itemIndex
11017
+ });
11018
+ }
10980
11019
  }
10981
11020
  itemIndex++;
10982
11021
  }
10983
- const results2 = Array.from({ length: items.length });
10984
11022
  if (toCreate.length > 0) {
10985
11023
  const createInputs = toCreate.map((entry2) => entry2.input);
10986
11024
  const created = await executeEdgeCreateBatch2(createInputs, target);
@@ -10994,10 +11032,13 @@ function createEdgeCollection(config) {
10994
11032
  });
10995
11033
  results2[entry2.index] = narrowEdge(result);
10996
11034
  }
10997
- return results2;
11035
+ for (const { index, sourceIndex } of deferred) {
11036
+ results2[index] = results2[sourceIndex];
11037
+ }
11038
+ return { results: results2, mutations: toCreate.length + toUpdate.length };
10998
11039
  };
10999
- const results = backend.capabilities.transactions && "transaction" in backend ? await backend.transaction(async (txBackend) => upsertAll(txBackend)) : await upsertAll(backend);
11000
- await config.maybeRefreshStatisticsAfterBulk?.(results.length);
11040
+ const { results, mutations } = backend.capabilities.transactions && "transaction" in backend ? await backend.transaction(async (txBackend) => upsertAll(txBackend)) : await upsertAll(backend);
11041
+ await config.maybeRefreshStatisticsAfterBulk?.(mutations);
11001
11042
  return results;
11002
11043
  },
11003
11044
  async bulkInsert(items) {
@@ -11091,6 +11132,18 @@ function createEdgeCollection(config) {
11091
11132
  };
11092
11133
  }
11093
11134
 
11135
+ // src/store/collections/coalesce.ts
11136
+ function shouldCoalesceUpsert(existing, options, runDirtyCheck) {
11137
+ if (runDirtyCheck === void 0 || existing.deleted_at !== void 0 || options?.validFrom !== void 0 || options?.validTo !== void 0) {
11138
+ return false;
11139
+ }
11140
+ try {
11141
+ return runDirtyCheck().unchanged;
11142
+ } catch {
11143
+ return false;
11144
+ }
11145
+ }
11146
+
11094
11147
  // src/store/collections/node-collection.ts
11095
11148
  function narrowNode(node) {
11096
11149
  return node;
@@ -11218,11 +11271,19 @@ function createNodeCollection(config) {
11218
11271
  async upsertByIdFromRecord(id, data, options) {
11219
11272
  const existing = await backend.getNode(graphId, kind, id);
11220
11273
  if (existing) {
11221
- const clearDeleted = existing.deleted_at !== void 0;
11274
+ const runDirtyCheck = config.upsertDirtyCheck && (() => config.upsertDirtyCheck(
11275
+ kind,
11276
+ id,
11277
+ rowPropsToObject(existing.props),
11278
+ data
11279
+ ));
11280
+ if (shouldCoalesceUpsert(existing, options, runDirtyCheck)) {
11281
+ return narrowNode(rowToNode2(existing));
11282
+ }
11222
11283
  const result2 = await executeNodeUpdate2(
11223
11284
  buildUpdateInput(kind, id, data, options),
11224
11285
  backend,
11225
- { clearDeleted }
11286
+ { clearDeleted: existing.deleted_at !== void 0 }
11226
11287
  );
11227
11288
  return narrowNode(result2);
11228
11289
  }
@@ -11263,26 +11324,63 @@ function createNodeCollection(config) {
11263
11324
  existingMap.set(row.id, row);
11264
11325
  }
11265
11326
  }
11327
+ const results2 = Array.from({ length: items.length });
11266
11328
  const toCreate = [];
11267
11329
  const toUpdate = [];
11330
+ const pending = /* @__PURE__ */ new Map();
11331
+ const deferred = [];
11268
11332
  let itemIndex = 0;
11269
11333
  for (const item of items) {
11270
- const existing = existingMap.get(item.id);
11271
- if (existing) {
11272
- toUpdate.push({
11334
+ const pendingEntry = pending.get(item.id);
11335
+ const original = existingMap.get(item.id);
11336
+ if (pendingEntry === void 0 && original === void 0) {
11337
+ toCreate.push({
11273
11338
  index: itemIndex,
11274
- input: buildUpdateInput(kind, item.id, item.props, item),
11275
- clearDeleted: existing.deleted_at !== void 0
11339
+ input: buildCreateInput(kind, item.props, item)
11276
11340
  });
11341
+ itemIndex++;
11342
+ continue;
11343
+ }
11344
+ const deletedAt = pendingEntry === void 0 ? original.deleted_at : void 0;
11345
+ let dirty;
11346
+ if (config.upsertDirtyCheck !== void 0) {
11347
+ const currentProps = pendingEntry?.props ?? rowPropsToObject(original.props);
11348
+ try {
11349
+ dirty = config.upsertDirtyCheck(
11350
+ kind,
11351
+ item.id,
11352
+ currentProps,
11353
+ item.props
11354
+ );
11355
+ } catch {
11356
+ dirty = void 0;
11357
+ }
11358
+ }
11359
+ const coalesce = dirty?.unchanged === true && deletedAt === void 0 && item.validFrom === void 0 && item.validTo === void 0;
11360
+ if (coalesce) {
11361
+ if (pendingEntry === void 0) {
11362
+ results2[itemIndex] = narrowNode(rowToNode2(original));
11363
+ } else {
11364
+ deferred.push({
11365
+ index: itemIndex,
11366
+ sourceIndex: pendingEntry.sourceIndex
11367
+ });
11368
+ }
11277
11369
  } else {
11278
- toCreate.push({
11370
+ toUpdate.push({
11279
11371
  index: itemIndex,
11280
- input: buildCreateInput(kind, item.props, item)
11372
+ input: buildUpdateInput(kind, item.id, item.props, item),
11373
+ clearDeleted: deletedAt !== void 0
11281
11374
  });
11375
+ if (dirty !== void 0) {
11376
+ pending.set(item.id, {
11377
+ props: dirty.validatedProps,
11378
+ sourceIndex: itemIndex
11379
+ });
11380
+ }
11282
11381
  }
11283
11382
  itemIndex++;
11284
11383
  }
11285
- const results2 = Array.from({ length: items.length });
11286
11384
  if (toCreate.length > 0) {
11287
11385
  const createInputs = toCreate.map((entry2) => entry2.input);
11288
11386
  const created = await executeNodeCreateBatch2(createInputs, target);
@@ -11296,10 +11394,13 @@ function createNodeCollection(config) {
11296
11394
  });
11297
11395
  results2[entry2.index] = narrowNode(result);
11298
11396
  }
11299
- return results2;
11397
+ for (const { index, sourceIndex } of deferred) {
11398
+ results2[index] = results2[sourceIndex];
11399
+ }
11400
+ return { results: results2, mutations: toCreate.length + toUpdate.length };
11300
11401
  };
11301
- const results = backend.capabilities.transactions && "transaction" in backend ? await backend.transaction(async (txBackend) => upsertAll(txBackend)) : await upsertAll(backend);
11302
- await config.maybeRefreshStatisticsAfterBulk?.(results.length);
11402
+ const { results, mutations } = backend.capabilities.transactions && "transaction" in backend ? await backend.transaction(async (txBackend) => upsertAll(txBackend)) : await upsertAll(backend);
11403
+ await config.maybeRefreshStatisticsAfterBulk?.(mutations);
11303
11404
  return results;
11304
11405
  },
11305
11406
  async bulkInsert(items) {
@@ -12697,21 +12798,45 @@ async function executeEdgeCreateBatch(ctx, inputs, backend) {
12697
12798
  return rows.map((row) => rowToEdge(row));
12698
12799
  });
12699
12800
  }
12801
+ function computeEdgeUpdate(ctx, kind, id, existingProps, inputProps) {
12802
+ const registration = getEdgeRegistration(ctx.graph, kind);
12803
+ return validateEdgeProps(
12804
+ registration.type.schema,
12805
+ { ...existingProps, ...inputProps },
12806
+ { kind, operation: "update", id }
12807
+ );
12808
+ }
12809
+ function resolveEdgeUpdateProps(ctx, existing, inputProps) {
12810
+ const existingProps = rowPropsToObject(existing.props);
12811
+ const validatedProps = computeEdgeUpdate(
12812
+ ctx,
12813
+ existing.kind,
12814
+ existing.id,
12815
+ existingProps,
12816
+ inputProps
12817
+ );
12818
+ return { existingProps, validatedProps };
12819
+ }
12820
+ function edgeUpsertDirtyCheck(ctx, kind, id, existingProps, inputProps) {
12821
+ const validatedProps = computeEdgeUpdate(
12822
+ ctx,
12823
+ kind,
12824
+ id,
12825
+ existingProps,
12826
+ inputProps
12827
+ );
12828
+ return {
12829
+ validatedProps,
12830
+ unchanged: canonicalEqual(validatedProps, existingProps)
12831
+ };
12832
+ }
12700
12833
  async function performEdgeUpdate(ctx, input, target, options) {
12701
12834
  const id = input.id;
12702
12835
  const existing = await target.getEdge(ctx.graphId, id);
12703
12836
  if (!existing || !options?.clearDeleted && existing.deleted_at) {
12704
12837
  throw new EdgeNotFoundError("unknown", id);
12705
12838
  }
12706
- const registration = getEdgeRegistration(ctx.graph, existing.kind);
12707
- const edgeKind = registration.type;
12708
- const existingProps = rowPropsToObject(existing.props);
12709
- const mergedProps = { ...existingProps, ...input.props };
12710
- const validatedProps = validateEdgeProps(edgeKind.schema, mergedProps, {
12711
- kind: existing.kind,
12712
- operation: "update",
12713
- id
12714
- });
12839
+ const { validatedProps } = resolveEdgeUpdateProps(ctx, existing, input.props);
12715
12840
  const validTo = validateOptionalCanonicalIsoDate(input.validTo, "validTo");
12716
12841
  const updateParams = {
12717
12842
  graphId: ctx.graphId,
@@ -13369,27 +13494,48 @@ function increment(counts, kind, count2) {
13369
13494
  counts[kind] = (counts[kind] ?? 0) + count2;
13370
13495
  }
13371
13496
  function createTransactionReceiptRecorder() {
13372
- const nodes = createCountBucket();
13373
- const edges = createCountBucket();
13374
- let total = 0;
13497
+ const counters = {
13498
+ nodes: createCountBucket(),
13499
+ edges: createCountBucket(),
13500
+ total: 0
13501
+ };
13502
+ let sealed = false;
13375
13503
  return {
13376
13504
  recordNode(kind, count2) {
13377
- increment(nodes, kind, count2);
13378
- total += count2;
13505
+ increment(counters.nodes, kind, count2);
13506
+ counters.total += count2;
13379
13507
  },
13380
13508
  recordEdge(kind, count2) {
13381
- increment(edges, kind, count2);
13382
- total += count2;
13509
+ increment(counters.edges, kind, count2);
13510
+ counters.total += count2;
13383
13511
  },
13384
13512
  snapshot(recorded) {
13385
13513
  return Object.freeze({
13386
13514
  writes: Object.freeze({
13387
- nodes: Object.freeze(Object.assign(createCountBucket(), nodes)),
13388
- edges: Object.freeze(Object.assign(createCountBucket(), edges)),
13389
- total
13515
+ nodes: Object.freeze(
13516
+ Object.assign(createCountBucket(), counters.nodes)
13517
+ ),
13518
+ edges: Object.freeze(
13519
+ Object.assign(createCountBucket(), counters.edges)
13520
+ ),
13521
+ total: counters.total
13390
13522
  }),
13391
13523
  ...recorded === void 0 ? {} : { recorded }
13392
13524
  });
13525
+ },
13526
+ seal() {
13527
+ sealed = true;
13528
+ },
13529
+ assertWritable() {
13530
+ if (sealed) {
13531
+ throw new ConfigurationError(
13532
+ "Transaction context is sealed: a write happened through the receipt-tracked collections after the transaction callback returned.",
13533
+ {},
13534
+ {
13535
+ suggestion: "Perform all writes inside the transactionWithReceipt / withRecordedTransaction callback; do not reuse the transaction context after it returns."
13536
+ }
13537
+ );
13538
+ }
13393
13539
  }
13394
13540
  };
13395
13541
  }
@@ -13423,7 +13569,7 @@ function memoizedProxyGet(target, shouldWrap, wrap) {
13423
13569
  }
13424
13570
  });
13425
13571
  }
13426
- function wrapWriteCollection(collection, kind, surface, record) {
13572
+ function wrapWriteCollection(collection, kind, surface, record, assertWritable) {
13427
13573
  return memoizedProxyGet(
13428
13574
  collection,
13429
13575
  (property) => surface.methodNames.has(property),
@@ -13431,6 +13577,7 @@ function wrapWriteCollection(collection, kind, surface, record) {
13431
13577
  if (!isWrappedMethod(value)) return value;
13432
13578
  const method = property;
13433
13579
  const wrapped = async (...args) => {
13580
+ assertWritable();
13434
13581
  const count2 = surface.counters[method](args);
13435
13582
  const result = await Reflect.apply(value, collection, args);
13436
13583
  record(kind, count2);
@@ -13455,7 +13602,8 @@ function wrapTransactionCollections(nodes, edges, recorder) {
13455
13602
  collection,
13456
13603
  kind,
13457
13604
  NODE_WRITE_SURFACE,
13458
- recorder.recordNode
13605
+ recorder.recordNode,
13606
+ recorder.assertWritable
13459
13607
  )
13460
13608
  ),
13461
13609
  edges: wrapCollections(
@@ -13464,7 +13612,8 @@ function wrapTransactionCollections(nodes, edges, recorder) {
13464
13612
  collection,
13465
13613
  kind,
13466
13614
  EDGE_WRITE_SURFACE,
13467
- recorder.recordEdge
13615
+ recorder.recordEdge,
13616
+ recorder.assertWritable
13468
13617
  )
13469
13618
  )
13470
13619
  };
@@ -13505,6 +13654,7 @@ function rowMapperConfigFor(backend) {
13505
13654
  function asError(error) {
13506
13655
  return error instanceof Error ? error : new Error(String(error));
13507
13656
  }
13657
+ var EMPTY_RECORDED_FLUSH_INSTANTS = /* @__PURE__ */ new Map();
13508
13658
  function transactionOutcome(result, recorder, recordedByGraph, graphId) {
13509
13659
  const recorded = recordedByGraph?.get(graphId);
13510
13660
  return {
@@ -13899,6 +14049,10 @@ var Store = class _Store {
13899
14049
  backend,
13900
14050
  options
13901
14051
  ),
14052
+ // Present only when opted in; its absence is the coalesce off switch.
14053
+ ...this.#options?.coalesceUnchangedUpserts === true && {
14054
+ upsertDirtyCheck: (kind, id, existingProps, inputProps) => nodeUpsertDirtyCheck(ctx, kind, id, existingProps, inputProps)
14055
+ },
13902
14056
  executeDelete: (kind, id, backend) => executeNodeDelete(ctx, kind, id, backend),
13903
14057
  executeHardDelete: (kind, id, backend) => executeNodeHardDelete(ctx, kind, id, backend),
13904
14058
  temporalRowMatcher: (options) => this.#temporalRowMatcher(options),
@@ -13953,6 +14107,10 @@ var Store = class _Store {
13953
14107
  executeCreateNoReturnBatch: (inputs, backend) => executeEdgeCreateNoReturnBatch(ctx, inputs, backend),
13954
14108
  executeUpdate: (input, backend) => executeEdgeUpdate(ctx, input, backend),
13955
14109
  executeUpsertUpdate: (input, backend, options) => executeEdgeUpsertUpdate(ctx, input, backend, options),
14110
+ // Present only when opted in; its absence is the coalesce off switch.
14111
+ ...this.#options?.coalesceUnchangedUpserts === true && {
14112
+ upsertDirtyCheck: (kind, id, existingProps, inputProps) => edgeUpsertDirtyCheck(ctx, kind, id, existingProps, inputProps)
14113
+ },
13956
14114
  executeDelete: (id, backend) => executeEdgeDelete(ctx, id, backend),
13957
14115
  executeHardDelete: (id, backend) => executeEdgeHardDelete(ctx, id, backend),
13958
14116
  temporalRowMatcher: (options) => this.#temporalRowMatcher(options),
@@ -14422,9 +14580,11 @@ var Store = class _Store {
14422
14580
  receiptRecorder
14423
14581
  ));
14424
14582
  }
14425
- const result = await invoke({
14583
+ const fallbackContext = {
14426
14584
  nodes,
14427
14585
  edges,
14586
+ // No real transaction: `tx.sql` is absent and there is no atomicity.
14587
+ sqlAvailability: "unavailable",
14428
14588
  backend: this.#backend,
14429
14589
  getNodeCollection: (kind) => this.#resolveDynamicNodeCollection(nodes, kind),
14430
14590
  // No transaction, no deferral: operations apply as they happen, so
@@ -14433,7 +14593,10 @@ var Store = class _Store {
14433
14593
  this.#createOperationContext(operation, "node", kind, id),
14434
14594
  hookedFunction
14435
14595
  )
14436
- });
14596
+ };
14597
+ const result = await invoke(
14598
+ receiptRecorder === void 0 ? fallbackContext : this.#attachMeasure(fallbackContext)
14599
+ );
14437
14600
  return { result, recordedByGraph: void 0 };
14438
14601
  }
14439
14602
  const pending = [];
@@ -14468,83 +14631,9 @@ var Store = class _Store {
14468
14631
  throw error;
14469
14632
  }
14470
14633
  }
14471
- /**
14472
- * Adopts a caller-owned, already-open Drizzle transaction so the graph
14473
- * store and the caller's relational writes commit or roll back as one
14474
- * Postgres/SQLite transaction (#134).
14475
- *
14476
- * Use this when the **relational layer owns the transaction**: the
14477
- * caller has opened a transaction and needs TypeGraph writes enlisted
14478
- * on the *same* connection. Unlike {@link transaction}, this opens no
14479
- * transaction — the caller's transaction is the single commit/rollback
14480
- * boundary.
14481
- *
14482
- * `withTransaction` is driver-agnostic; how the caller opens the
14483
- * transaction is not. **Async drivers** (node-postgres,
14484
- * `neon-serverless` Pool, libsql) use `db.transaction(async …)`.
14485
- * **Synchronous `better-sqlite3`** cannot — its driver rejects an
14486
- * `async` transaction callback (`Transaction function cannot return a
14487
- * promise`) and the async continuation would run outside the
14488
- * rolled-back transaction — so the caller opens the transaction with
14489
- * explicit `BEGIN`/`COMMIT`/`ROLLBACK` on the single connection
14490
- * instead. See the "Cross-Store Transactions" recipe for both shapes.
14491
- *
14492
- * The returned context reuses this store's already-resolved
14493
- * schema/registry: it runs **no** schema bootstrap, `evolve`, or
14494
- * migration, and emits **no DDL** inside the caller's transaction.
14495
- * Fulltext operations assert the durable materialization marker (a
14496
- * cached SELECT) and throw {@link StoreNotInitializedError} on a
14497
- * missing/stale/failed marker rather than migrating mid-transaction —
14498
- * so boot the parent store via `createStoreWithSchema` once at
14499
- * startup.
14500
- *
14501
- * @example
14502
- * ```typescript
14503
- * // Async driver (Postgres / libsql):
14504
- * await db.transaction(async (sqlTx) => {
14505
- * const connector = await createConnectorRow(sqlTx, input); // Drizzle
14506
- * const txStore = store.withTransaction(sqlTx);
14507
- * await txStore.nodes.ArtifactSource.create({ // TypeGraph
14508
- * connectorId: connector.id,
14509
- * });
14510
- * }); // one COMMIT / ROLLBACK across both layers
14511
- * ```
14512
- *
14513
- * **The caller owns the connection — don't overlap writes on it.** The graph
14514
- * store and your Drizzle writes share the one connection the caller's
14515
- * transaction pinned. TypeGraph serializes the statements *its* collections
14516
- * issue, but your raw Drizzle statements (and any graph write run alongside
14517
- * them) are yours to sequence: a `Promise.all` mixing the two races two
14518
- * queries on that connection — the overlap Postgres removes in `pg@9`. Await
14519
- * each write before starting the next.
14520
- *
14521
- * Not available when the store was created with `{ history: true }`: a
14522
- * caller-owned transaction context would let writes happen after capture has
14523
- * lost its flush point, so this throws `ConfigurationError`
14524
- * (`RECORDED_CAPTURE_REQUIRES_CALLBACK_TRANSACTION`). Use
14525
- * {@link Store.withRecordedTransaction} on a history-enabled store, which
14526
- * adopts the same external transaction but flushes recorded-time capture
14527
- * before the caller commits.
14528
- *
14529
- * @throws {ConfigurationError} when the store has history capture enabled
14530
- * (use {@link Store.withRecordedTransaction} instead), or when the backend
14531
- * cannot adopt an external transaction — either it is not a Drizzle
14532
- * Postgres/SQLite backend, or `backend.capabilities.transactions` is `false`
14533
- * (`drizzle-orm/neon-http`, Cloudflare D1, SQLite
14534
- * `transactionMode: "none"`). A non-atomic fallback is deliberately
14535
- * not offered here: the caller's relational write *would* still
14536
- * commit, defeating the purpose of cross-store atomicity.
14537
- * @throws {StoreNotInitializedError} at point of use, when a fulltext
14538
- * operation on the returned context observes a missing/stale/failed
14539
- * durable materialization marker (parent store not booted via
14540
- * `createStoreWithSchema`). Rolls back the caller's transaction
14541
- * without emitting any DDL.
14542
- */
14543
14634
  withTransaction(externalTx) {
14544
14635
  if (this.#captureEnabled) {
14545
- throw recordedCaptureRequiresCallbackTransactionError({
14546
- code: "RECORDED_CAPTURE_REQUIRES_CALLBACK_TRANSACTION"
14547
- });
14636
+ throw recordedCaptureRequiresCallbackTransactionError();
14548
14637
  }
14549
14638
  const adopt = this.#backend.adoptTransaction;
14550
14639
  if (!adopt) {
@@ -14572,17 +14661,62 @@ var Store = class _Store {
14572
14661
  }
14573
14662
  const scope = this.#captureEnabled ? createRecordedTransactionScope(txBackend, this.#sqlSchema()) : {
14574
14663
  backend: txBackend,
14575
- flush: () => Promise.resolve()
14664
+ flush: () => Promise.resolve(EMPTY_RECORDED_FLUSH_INSTANTS)
14576
14665
  };
14577
14666
  if (this.#captureEnabled) {
14578
14667
  await lockRecordedGraphWrite(scope.backend, this.graphId);
14579
14668
  }
14669
+ const receiptRecorder = createTransactionReceiptRecorder();
14580
14670
  const invoke = fn;
14581
14671
  const result = await invoke(
14582
- this.#buildTransactionContext(scope.backend, externalTx)
14672
+ this.#buildTransactionContext(
14673
+ scope.backend,
14674
+ externalTx,
14675
+ void 0,
14676
+ receiptRecorder
14677
+ )
14583
14678
  );
14584
- await scope.flush();
14585
- return result;
14679
+ const recordedByGraph = await scope.flush();
14680
+ if (!this.#captureEnabled) receiptRecorder.seal();
14681
+ return transactionOutcome(
14682
+ result,
14683
+ receiptRecorder,
14684
+ recordedByGraph,
14685
+ this.graphId
14686
+ );
14687
+ }
14688
+ /**
14689
+ * Decorates a receipt-enabled transaction `context` with `measure`.
14690
+ * Attribution is structural: `measure` wraps the context's *own* (already
14691
+ * outer-recording) collections a second time with a fresh scope recorder, so a
14692
+ * write through the scoped context counts in the scope and — via the inner
14693
+ * wrapper it delegates to — the outer receipt, while a write through the outer
14694
+ * `context` never reaches the scope recorder. This makes overlapping/concurrent
14695
+ * measures safe by construction (each holds its own scope recorder) and lets
14696
+ * scopes nest: the scoped context is itself decorated, so `scoped.measure(...)`
14697
+ * chains one more wrapper. The scoped context's `getNodeCollection` resolves
14698
+ * against the scope-wrapped map too, so dynamic-kind writes are attributed like
14699
+ * `scoped.nodes.<Kind>`. The scope receipt's `recorded` is always undefined —
14700
+ * the recorded instant is a whole-transaction flush concern.
14701
+ */
14702
+ #attachMeasure(context) {
14703
+ const measure = async (fn) => {
14704
+ const scopeRecorder = createTransactionReceiptRecorder();
14705
+ const { nodes, edges } = wrapTransactionCollections(
14706
+ context.nodes,
14707
+ context.edges,
14708
+ scopeRecorder
14709
+ );
14710
+ const scoped = this.#attachMeasure({
14711
+ ...context,
14712
+ nodes,
14713
+ edges,
14714
+ getNodeCollection: (kind) => this.#resolveDynamicNodeCollection(nodes, kind)
14715
+ });
14716
+ const result = await fn(scoped);
14717
+ return { result, receipt: scopeRecorder.snapshot() };
14718
+ };
14719
+ return { ...context, measure };
14586
14720
  }
14587
14721
  /**
14588
14722
  * Builds the `{ nodes, edges, sql }` projection bound to a
@@ -14628,24 +14762,20 @@ var Store = class _Store {
14628
14762
  ));
14629
14763
  }
14630
14764
  const getNodeCollection = (kind) => this.#resolveDynamicNodeCollection(nodes, kind);
14631
- if (sql17 === void 0) {
14632
- return {
14633
- nodes,
14634
- edges,
14635
- backend: txBackend,
14636
- getNodeCollection,
14637
- runNodeOperationHooks
14638
- };
14639
- }
14640
- const exposedSql = this.#captureEnabled ? createHistoryUnsafeSqlRef() : this.#revisionTrackingEnabled ? createRevisionTrackingUnsafeSqlRef() : sql17;
14641
- return {
14765
+ const sqlAvailability = this.#captureEnabled ? "history" : this.#revisionTrackingEnabled ? "revisionTracking" : sql17 === void 0 ? "unavailable" : "available";
14766
+ const base = {
14642
14767
  nodes,
14643
14768
  edges,
14644
- sql: exposedSql,
14769
+ sqlAvailability,
14645
14770
  backend: txBackend,
14646
14771
  getNodeCollection,
14647
14772
  runNodeOperationHooks
14648
14773
  };
14774
+ const withSql = sql17 === void 0 ? base : {
14775
+ ...base,
14776
+ sql: this.#captureEnabled ? createHistoryUnsafeSqlRef() : this.#revisionTrackingEnabled ? createRevisionTrackingUnsafeSqlRef() : sql17
14777
+ };
14778
+ return receiptRecorder === void 0 ? withSql : this.#attachMeasure(withSql);
14649
14779
  }
14650
14780
  // === Graph Lifecycle ===
14651
14781
  /**
@@ -15512,5 +15642,5 @@ async function createVerifiedStore(graph, backend, options) {
15512
15642
  }
15513
15643
 
15514
15644
  export { ExecutableAggregateQuery, ExecutableQuery, MAX_EXPLICIT_RECURSIVE_DEPTH, MAX_RECURSIVE_DEPTH, PreparedQuery, QueryBuilder, RecordedStoreView, StoreSearch, StoreView, UnionableQuery, avg, composeFragments, count, countDistinct, countDistinctEdges, countEdges, createFragment, createQueryBuilder, createStore, createStoreWithSchema, createVerifiedStore, defineSubgraphProject, field, having, havingEq, havingGt, havingGte, havingLt, havingLte, limitFragment, max, min, offsetFragment, orderByFragment, sum };
15515
- //# sourceMappingURL=chunk-UES55P7G.js.map
15516
- //# sourceMappingURL=chunk-UES55P7G.js.map
15645
+ //# sourceMappingURL=chunk-5DIPR3L3.js.map
15646
+ //# sourceMappingURL=chunk-5DIPR3L3.js.map