@tanstack/db 0.4.19 → 0.5.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 (153) hide show
  1. package/dist/cjs/collection/change-events.cjs +10 -12
  2. package/dist/cjs/collection/change-events.cjs.map +1 -1
  3. package/dist/cjs/collection/change-events.d.cts +1 -8
  4. package/dist/cjs/collection/index.cjs +19 -1
  5. package/dist/cjs/collection/index.cjs.map +1 -1
  6. package/dist/cjs/collection/index.d.cts +7 -5
  7. package/dist/cjs/collection/sync.cjs +7 -1
  8. package/dist/cjs/collection/sync.cjs.map +1 -1
  9. package/dist/cjs/errors.cjs +9 -4
  10. package/dist/cjs/errors.cjs.map +1 -1
  11. package/dist/cjs/errors.d.cts +4 -1
  12. package/dist/cjs/index.cjs +21 -3
  13. package/dist/cjs/index.cjs.map +1 -1
  14. package/dist/cjs/index.d.cts +2 -0
  15. package/dist/cjs/indexes/auto-index.cjs +7 -3
  16. package/dist/cjs/indexes/auto-index.cjs.map +1 -1
  17. package/dist/cjs/local-storage.cjs.map +1 -1
  18. package/dist/cjs/local-storage.d.cts +2 -2
  19. package/dist/cjs/query/builder/functions.cjs +34 -0
  20. package/dist/cjs/query/builder/functions.cjs.map +1 -1
  21. package/dist/cjs/query/builder/functions.d.cts +5 -0
  22. package/dist/cjs/query/builder/index.cjs +2 -2
  23. package/dist/cjs/query/builder/index.cjs.map +1 -1
  24. package/dist/cjs/query/builder/types.d.cts +18 -24
  25. package/dist/cjs/query/compiler/evaluators.cjs +57 -4
  26. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
  27. package/dist/cjs/query/compiler/evaluators.d.cts +13 -0
  28. package/dist/cjs/query/compiler/expressions.cjs +4 -1
  29. package/dist/cjs/query/compiler/expressions.cjs.map +1 -1
  30. package/dist/cjs/query/compiler/group-by.cjs +3 -3
  31. package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
  32. package/dist/cjs/query/compiler/index.cjs +2 -2
  33. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  34. package/dist/cjs/query/compiler/order-by.cjs +18 -6
  35. package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
  36. package/dist/cjs/query/compiler/order-by.d.cts +7 -1
  37. package/dist/cjs/query/expression-helpers.cjs +217 -0
  38. package/dist/cjs/query/expression-helpers.cjs.map +1 -0
  39. package/dist/cjs/query/expression-helpers.d.cts +216 -0
  40. package/dist/cjs/query/index.d.cts +2 -0
  41. package/dist/cjs/query/live/collection-config-builder.cjs +34 -2
  42. package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
  43. package/dist/cjs/query/live/collection-config-builder.d.cts +7 -1
  44. package/dist/cjs/query/live/collection-registry.cjs +2 -1
  45. package/dist/cjs/query/live/collection-registry.cjs.map +1 -1
  46. package/dist/cjs/query/live/collection-registry.d.cts +1 -1
  47. package/dist/cjs/query/live/internal.cjs +5 -0
  48. package/dist/cjs/query/live/internal.cjs.map +1 -0
  49. package/dist/cjs/query/live/internal.d.cts +13 -0
  50. package/dist/cjs/query/live/types.d.cts +6 -1
  51. package/dist/cjs/query/predicate-utils.cjs +816 -0
  52. package/dist/cjs/query/predicate-utils.cjs.map +1 -0
  53. package/dist/cjs/query/predicate-utils.d.cts +116 -0
  54. package/dist/cjs/query/subset-dedupe.cjs +111 -0
  55. package/dist/cjs/query/subset-dedupe.cjs.map +1 -0
  56. package/dist/cjs/query/subset-dedupe.d.cts +66 -0
  57. package/dist/cjs/types.d.cts +31 -2
  58. package/dist/cjs/utils/comparison.cjs +30 -0
  59. package/dist/cjs/utils/comparison.cjs.map +1 -1
  60. package/dist/cjs/utils/comparison.d.cts +7 -1
  61. package/dist/cjs/utils/index-optimization.cjs +26 -22
  62. package/dist/cjs/utils/index-optimization.cjs.map +1 -1
  63. package/dist/cjs/utils/index-optimization.d.cts +5 -4
  64. package/dist/esm/collection/change-events.d.ts +1 -8
  65. package/dist/esm/collection/change-events.js +7 -9
  66. package/dist/esm/collection/change-events.js.map +1 -1
  67. package/dist/esm/collection/index.d.ts +7 -5
  68. package/dist/esm/collection/index.js +19 -1
  69. package/dist/esm/collection/index.js.map +1 -1
  70. package/dist/esm/collection/sync.js +7 -1
  71. package/dist/esm/collection/sync.js.map +1 -1
  72. package/dist/esm/errors.d.ts +4 -1
  73. package/dist/esm/errors.js +9 -4
  74. package/dist/esm/errors.js.map +1 -1
  75. package/dist/esm/index.d.ts +2 -0
  76. package/dist/esm/index.js +19 -1
  77. package/dist/esm/index.js.map +1 -1
  78. package/dist/esm/indexes/auto-index.js +7 -3
  79. package/dist/esm/indexes/auto-index.js.map +1 -1
  80. package/dist/esm/local-storage.d.ts +2 -2
  81. package/dist/esm/local-storage.js.map +1 -1
  82. package/dist/esm/query/builder/functions.d.ts +5 -0
  83. package/dist/esm/query/builder/functions.js +34 -0
  84. package/dist/esm/query/builder/functions.js.map +1 -1
  85. package/dist/esm/query/builder/index.js +2 -2
  86. package/dist/esm/query/builder/index.js.map +1 -1
  87. package/dist/esm/query/builder/types.d.ts +18 -24
  88. package/dist/esm/query/compiler/evaluators.d.ts +13 -0
  89. package/dist/esm/query/compiler/evaluators.js +59 -6
  90. package/dist/esm/query/compiler/evaluators.js.map +1 -1
  91. package/dist/esm/query/compiler/expressions.js +4 -1
  92. package/dist/esm/query/compiler/expressions.js.map +1 -1
  93. package/dist/esm/query/compiler/group-by.js +4 -4
  94. package/dist/esm/query/compiler/group-by.js.map +1 -1
  95. package/dist/esm/query/compiler/index.js +3 -3
  96. package/dist/esm/query/compiler/index.js.map +1 -1
  97. package/dist/esm/query/compiler/order-by.d.ts +7 -1
  98. package/dist/esm/query/compiler/order-by.js +18 -6
  99. package/dist/esm/query/compiler/order-by.js.map +1 -1
  100. package/dist/esm/query/expression-helpers.d.ts +216 -0
  101. package/dist/esm/query/expression-helpers.js +217 -0
  102. package/dist/esm/query/expression-helpers.js.map +1 -0
  103. package/dist/esm/query/index.d.ts +2 -0
  104. package/dist/esm/query/live/collection-config-builder.d.ts +7 -1
  105. package/dist/esm/query/live/collection-config-builder.js +34 -2
  106. package/dist/esm/query/live/collection-config-builder.js.map +1 -1
  107. package/dist/esm/query/live/collection-registry.d.ts +1 -1
  108. package/dist/esm/query/live/collection-registry.js +2 -1
  109. package/dist/esm/query/live/collection-registry.js.map +1 -1
  110. package/dist/esm/query/live/internal.d.ts +13 -0
  111. package/dist/esm/query/live/internal.js +5 -0
  112. package/dist/esm/query/live/internal.js.map +1 -0
  113. package/dist/esm/query/live/types.d.ts +6 -1
  114. package/dist/esm/query/predicate-utils.d.ts +116 -0
  115. package/dist/esm/query/predicate-utils.js +816 -0
  116. package/dist/esm/query/predicate-utils.js.map +1 -0
  117. package/dist/esm/query/subset-dedupe.d.ts +66 -0
  118. package/dist/esm/query/subset-dedupe.js +111 -0
  119. package/dist/esm/query/subset-dedupe.js.map +1 -0
  120. package/dist/esm/types.d.ts +31 -2
  121. package/dist/esm/utils/comparison.d.ts +7 -1
  122. package/dist/esm/utils/comparison.js +30 -0
  123. package/dist/esm/utils/comparison.js.map +1 -1
  124. package/dist/esm/utils/index-optimization.d.ts +5 -4
  125. package/dist/esm/utils/index-optimization.js +26 -22
  126. package/dist/esm/utils/index-optimization.js.map +1 -1
  127. package/package.json +2 -2
  128. package/src/collection/change-events.ts +14 -24
  129. package/src/collection/index.ts +34 -6
  130. package/src/collection/sync.ts +9 -1
  131. package/src/errors.ts +20 -4
  132. package/src/index.ts +4 -0
  133. package/src/indexes/auto-index.ts +8 -4
  134. package/src/local-storage.ts +11 -3
  135. package/src/query/builder/functions.ts +39 -0
  136. package/src/query/builder/index.ts +2 -2
  137. package/src/query/builder/types.ts +19 -27
  138. package/src/query/compiler/evaluators.ts +103 -5
  139. package/src/query/compiler/expressions.ts +3 -0
  140. package/src/query/compiler/group-by.ts +4 -4
  141. package/src/query/compiler/index.ts +3 -3
  142. package/src/query/compiler/order-by.ts +33 -7
  143. package/src/query/expression-helpers.ts +522 -0
  144. package/src/query/index.ts +12 -0
  145. package/src/query/live/collection-config-builder.ts +54 -2
  146. package/src/query/live/collection-registry.ts +3 -2
  147. package/src/query/live/internal.ts +15 -0
  148. package/src/query/live/types.ts +11 -1
  149. package/src/query/predicate-utils.ts +1415 -0
  150. package/src/query/subset-dedupe.ts +243 -0
  151. package/src/types.ts +41 -2
  152. package/src/utils/comparison.ts +70 -1
  153. package/src/utils/index-optimization.ts +77 -63
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","sources":["../../src/errors.ts"],"sourcesContent":["// Root error class for all TanStack DB errors\nexport class TanStackDBError extends Error {\n constructor(message: string) {\n super(message)\n this.name = `TanStackDBError`\n }\n}\n\n// Base error classes\nexport class NonRetriableError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `NonRetriableError`\n }\n}\n\n// Schema validation error (exported from index for backward compatibility)\nexport class SchemaValidationError extends TanStackDBError {\n type: `insert` | `update`\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>\n\n constructor(\n type: `insert` | `update`,\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>,\n message?: string\n ) {\n const defaultMessage = `${type === `insert` ? `Insert` : `Update`} validation failed: ${issues\n .map((issue) => `\\n- ${issue.message} - path: ${issue.path}`)\n .join(``)}`\n\n super(message || defaultMessage)\n this.name = `SchemaValidationError`\n this.type = type\n this.issues = issues\n }\n}\n\n// Module Instance Errors\nexport class DuplicateDbInstanceError extends TanStackDBError {\n constructor() {\n super(\n `Multiple instances of @tanstack/db detected!\\n\\n` +\n `This causes transaction context to be lost because each instance maintains ` +\n `its own transaction stack.\\n\\n` +\n `Common causes:\\n` +\n `1. Different versions of @tanstack/db installed\\n` +\n `2. Incompatible peer dependency versions in packages\\n` +\n `3. Module resolution issues in bundler configuration\\n\\n` +\n `To fix:\\n` +\n `1. Check installed versions: npm list @tanstack/db (or pnpm/yarn list)\\n` +\n `2. Force a single version using package manager overrides:\\n` +\n ` - npm: \"overrides\" in package.json\\n` +\n ` - pnpm: \"pnpm.overrides\" in package.json\\n` +\n ` - yarn: \"resolutions\" in package.json\\n` +\n `3. Clear node_modules and lockfile, then reinstall\\n\\n` +\n `To temporarily disable this check (not recommended):\\n` +\n `Set environment variable: TANSTACK_DB_DISABLE_DUP_CHECK=1\\n\\n` +\n `See: https://tanstack.com/db/latest/docs/troubleshooting#duplicate-instances`\n )\n this.name = `DuplicateDbInstanceError`\n }\n}\n\n// Collection Configuration Errors\nexport class CollectionConfigurationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionConfigurationError`\n }\n}\n\nexport class CollectionRequiresConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a config`)\n }\n}\n\nexport class CollectionRequiresSyncConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a sync config`)\n }\n}\n\nexport class InvalidSchemaError extends CollectionConfigurationError {\n constructor() {\n super(`Schema must implement the standard-schema interface`)\n }\n}\n\nexport class SchemaMustBeSynchronousError extends CollectionConfigurationError {\n constructor() {\n super(`Schema validation must be synchronous`)\n }\n}\n\n// Collection State Errors\nexport class CollectionStateError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionStateError`\n }\n}\n\nexport class CollectionInErrorStateError extends CollectionStateError {\n constructor(operation: string, collectionId: string) {\n super(\n `Cannot perform ${operation} on collection \"${collectionId}\" - collection is in error state. Try calling cleanup() and restarting the collection.`\n )\n }\n}\n\nexport class InvalidCollectionStatusTransitionError extends CollectionStateError {\n constructor(from: string, to: string, collectionId: string) {\n super(\n `Invalid collection status transition from \"${from}\" to \"${to}\" for collection \"${collectionId}\"`\n )\n }\n}\n\nexport class CollectionIsInErrorStateError extends CollectionStateError {\n constructor() {\n super(`Collection is in error state`)\n }\n}\n\nexport class NegativeActiveSubscribersError extends CollectionStateError {\n constructor() {\n super(`Active subscribers count is negative - this should never happen`)\n }\n}\n\n// Collection Operation Errors\nexport class CollectionOperationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionOperationError`\n }\n}\n\nexport class UndefinedKeyError extends CollectionOperationError {\n constructor(item: any) {\n super(\n `An object was created without a defined key: ${JSON.stringify(item)}`\n )\n }\n}\n\nexport class DuplicateKeyError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Cannot insert document with ID \"${key}\" because it already exists in the collection`\n )\n }\n}\n\nexport class DuplicateKeySyncError extends CollectionOperationError {\n constructor(key: string | number, collectionId: string) {\n super(\n `Cannot insert document with key \"${key}\" from sync because it already exists in the collection \"${collectionId}\"`\n )\n }\n}\n\nexport class MissingUpdateArgumentError extends CollectionOperationError {\n constructor() {\n super(`The first argument to update is missing`)\n }\n}\n\nexport class NoKeysPassedToUpdateError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to update`)\n }\n}\n\nexport class UpdateKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `The key \"${key}\" was passed to update but an object for this key was not found in the collection`\n )\n }\n}\n\nexport class KeyUpdateNotAllowedError extends CollectionOperationError {\n constructor(originalKey: string | number, newKey: string | number) {\n super(\n `Updating the key of an item is not allowed. Original key: \"${originalKey}\", Attempted new key: \"${newKey}\". Please delete the old item and create a new one if a key change is necessary.`\n )\n }\n}\n\nexport class NoKeysPassedToDeleteError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to delete`)\n }\n}\n\nexport class DeleteKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Collection.delete was called with key '${key}' but there is no item in the collection with this key`\n )\n }\n}\n\n// Collection Handler Errors\nexport class MissingHandlerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `MissingHandlerError`\n }\n}\n\nexport class MissingInsertHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`\n )\n }\n}\n\nexport class MissingUpdateHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`\n )\n }\n}\n\nexport class MissingDeleteHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`\n )\n }\n}\n\n// Transaction Errors\nexport class TransactionError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `TransactionError`\n }\n}\n\nexport class MissingMutationFunctionError extends TransactionError {\n constructor() {\n super(`mutationFn is required when creating a transaction`)\n }\n}\n\nexport class OnMutateMustBeSynchronousError extends TransactionError {\n constructor() {\n super(\n `onMutate must be synchronous and cannot return a promise. Remove async/await or returned promises from onMutate.`\n )\n this.name = `OnMutateMustBeSynchronousError`\n }\n}\n\nexport class TransactionNotPendingMutateError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .mutate() as the transaction is no longer pending`\n )\n }\n}\n\nexport class TransactionAlreadyCompletedRollbackError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .rollback() as the transaction is already completed`\n )\n }\n}\n\nexport class TransactionNotPendingCommitError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .commit() as the transaction is no longer pending`\n )\n }\n}\n\nexport class NoPendingSyncTransactionWriteError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to write to`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedWriteError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't still write to it.`\n )\n }\n}\n\nexport class NoPendingSyncTransactionCommitError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to commit`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't commit it again.`\n )\n }\n}\n\n// Query Builder Errors\nexport class QueryBuilderError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryBuilderError`\n }\n}\n\nexport class OnlyOneSourceAllowedError extends QueryBuilderError {\n constructor(context: string) {\n super(`Only one source is allowed in the ${context}`)\n }\n}\n\nexport class SubQueryMustHaveFromClauseError extends QueryBuilderError {\n constructor(context: string) {\n super(`A sub query passed to a ${context} must have a from clause itself`)\n }\n}\n\nexport class InvalidSourceError extends QueryBuilderError {\n constructor(alias: string) {\n super(\n `Invalid source for live query: The value provided for alias \"${alias}\" is not a Collection or subquery. Live queries only accept Collection instances or subqueries. Please ensure you're passing a valid Collection or QueryBuilder, not a plain array or other data type.`\n )\n }\n}\n\nexport class JoinConditionMustBeEqualityError extends QueryBuilderError {\n constructor() {\n super(`Join condition must be an equality expression`)\n }\n}\n\nexport class QueryMustHaveFromClauseError extends QueryBuilderError {\n constructor() {\n super(`Query must have a from clause`)\n }\n}\n\n// Query Compilation Errors\nexport class QueryCompilationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryCompilationError`\n }\n}\n\nexport class DistinctRequiresSelectError extends QueryCompilationError {\n constructor() {\n super(`DISTINCT requires a SELECT clause.`)\n }\n}\n\nexport class HavingRequiresGroupByError extends QueryCompilationError {\n constructor() {\n super(`HAVING clause requires GROUP BY clause`)\n }\n}\n\nexport class LimitOffsetRequireOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `LIMIT and OFFSET require an ORDER BY clause to ensure deterministic results`\n )\n }\n}\n\n/**\n * Error thrown when a collection input stream is not found during query compilation.\n * In self-joins, each alias (e.g., 'employee', 'manager') requires its own input stream.\n */\nexport class CollectionInputNotFoundError extends QueryCompilationError {\n constructor(\n alias: string,\n collectionId?: string,\n availableKeys?: Array<string>\n ) {\n const details = collectionId\n ? `alias \"${alias}\" (collection \"${collectionId}\")`\n : `collection \"${alias}\"`\n const availableKeysMsg = availableKeys?.length\n ? `. Available keys: ${availableKeys.join(`, `)}`\n : ``\n super(`Input for ${details} not found in inputs map${availableKeysMsg}`)\n }\n}\n\n/**\n * Error thrown when a subquery uses the same alias as its parent query.\n * This causes issues because parent and subquery would share the same input streams,\n * leading to empty results or incorrect data (aggregation cross-leaking).\n */\nexport class DuplicateAliasInSubqueryError extends QueryCompilationError {\n constructor(alias: string, parentAliases: Array<string>) {\n super(\n `Subquery uses alias \"${alias}\" which is already used in the parent query. ` +\n `Each alias must be unique across parent and subquery contexts. ` +\n `Parent query aliases: ${parentAliases.join(`, `)}. ` +\n `Please rename \"${alias}\" in either the parent query or subquery to avoid conflicts.`\n )\n }\n}\n\nexport class UnsupportedFromTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unsupported FROM type: ${type}`)\n }\n}\n\nexport class UnknownExpressionTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unknown expression type: ${type}`)\n }\n}\n\nexport class EmptyReferencePathError extends QueryCompilationError {\n constructor() {\n super(`Reference path cannot be empty`)\n }\n}\n\nexport class UnknownFunctionError extends QueryCompilationError {\n constructor(functionName: string) {\n super(`Unknown function: ${functionName}`)\n }\n}\n\nexport class JoinCollectionNotFoundError extends QueryCompilationError {\n constructor(collectionId: string) {\n super(`Collection \"${collectionId}\" not found during compilation of join`)\n }\n}\n\n// JOIN Operation Errors\nexport class JoinError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `JoinError`\n }\n}\n\nexport class UnsupportedJoinTypeError extends JoinError {\n constructor(joinType: string) {\n super(`Unsupported join type: ${joinType}`)\n }\n}\n\nexport class InvalidJoinConditionSameSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: both expressions refer to the same source \"${sourceAlias}\"`\n )\n }\n}\n\nexport class InvalidJoinConditionSourceMismatchError extends JoinError {\n constructor() {\n super(`Invalid join condition: expressions must reference source aliases`)\n }\n}\n\nexport class InvalidJoinConditionLeftSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: left expression refers to an unavailable source \"${sourceAlias}\"`\n )\n }\n}\n\nexport class InvalidJoinConditionRightSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: right expression does not refer to the joined source \"${sourceAlias}\"`\n )\n }\n}\n\nexport class InvalidJoinCondition extends JoinError {\n constructor() {\n super(`Invalid join condition`)\n }\n}\n\nexport class UnsupportedJoinSourceTypeError extends JoinError {\n constructor(type: string) {\n super(`Unsupported join source type: ${type}`)\n }\n}\n\n// GROUP BY and Aggregation Errors\nexport class GroupByError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `GroupByError`\n }\n}\n\nexport class NonAggregateExpressionNotInGroupByError extends GroupByError {\n constructor(alias: string) {\n super(\n `Non-aggregate expression '${alias}' in SELECT must also appear in GROUP BY clause`\n )\n }\n}\n\nexport class UnsupportedAggregateFunctionError extends GroupByError {\n constructor(functionName: string) {\n super(`Unsupported aggregate function: ${functionName}`)\n }\n}\n\nexport class AggregateFunctionNotInSelectError extends GroupByError {\n constructor(functionName: string) {\n super(\n `Aggregate function in HAVING clause must also be in SELECT clause: ${functionName}`\n )\n }\n}\n\nexport class UnknownHavingExpressionTypeError extends GroupByError {\n constructor(type: string) {\n super(`Unknown expression type in HAVING clause: ${type}`)\n }\n}\n\n// Storage Errors\nexport class StorageError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `StorageError`\n }\n}\n\nexport class SerializationError extends StorageError {\n constructor(operation: string, originalError: string) {\n super(\n `Cannot ${operation} item because it cannot be JSON serialized: ${originalError}`\n )\n }\n}\n\n// LocalStorage Collection Errors\nexport class LocalStorageCollectionError extends StorageError {\n constructor(message: string) {\n super(message)\n this.name = `LocalStorageCollectionError`\n }\n}\n\nexport class StorageKeyRequiredError extends LocalStorageCollectionError {\n constructor() {\n super(`[LocalStorageCollection] storageKey must be provided.`)\n }\n}\n\nexport class InvalidStorageDataFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string, key: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\" for key \"${key}\".`\n )\n }\n}\n\nexport class InvalidStorageObjectFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\". Expected object format.`\n )\n }\n}\n\n// Sync Cleanup Errors\nexport class SyncCleanupError extends TanStackDBError {\n constructor(collectionId: string, error: Error | string) {\n const message = error instanceof Error ? error.message : String(error)\n super(\n `Collection \"${collectionId}\" sync cleanup function threw an error: ${message}`\n )\n this.name = `SyncCleanupError`\n }\n}\n\n// Query Optimizer Errors\nexport class QueryOptimizerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryOptimizerError`\n }\n}\n\nexport class CannotCombineEmptyExpressionListError extends QueryOptimizerError {\n constructor() {\n super(`Cannot combine empty expression list`)\n }\n}\n\n/**\n * Internal error when the query optimizer fails to convert a WHERE clause to a collection filter.\n */\nexport class WhereClauseConversionError extends QueryOptimizerError {\n constructor(collectionId: string, alias: string) {\n super(\n `Failed to convert WHERE clause to collection filter for collection '${collectionId}' alias '${alias}'. This indicates a bug in the query optimization logic.`\n )\n }\n}\n\n/**\n * Error when a subscription cannot be found during lazy join processing.\n * For subqueries, aliases may be remapped (e.g., 'activeUser' → 'user').\n */\nexport class SubscriptionNotFoundError extends QueryCompilationError {\n constructor(\n resolvedAlias: string,\n originalAlias: string,\n collectionId: string,\n availableAliases: Array<string>\n ) {\n super(\n `Internal error: subscription for alias '${resolvedAlias}' (remapped from '${originalAlias}', collection '${collectionId}') is missing in join pipeline. Available aliases: ${availableAliases.join(`, `)}. This indicates a bug in alias tracking.`\n )\n }\n}\n\n/**\n * Error thrown when aggregate expressions are used outside of a GROUP BY context.\n */\nexport class AggregateNotSupportedError extends QueryCompilationError {\n constructor() {\n super(\n `Aggregate expressions are not supported in this context. Use GROUP BY clause for aggregates.`\n )\n }\n}\n\n/**\n * Internal error when the compiler returns aliases that don't have corresponding input streams.\n * This should never happen since all aliases come from user declarations.\n */\nexport class MissingAliasInputsError extends QueryCompilationError {\n constructor(missingAliases: Array<string>) {\n super(\n `Internal error: compiler returned aliases without inputs: ${missingAliases.join(`, `)}. ` +\n `This indicates a bug in query compilation. Please report this issue.`\n )\n }\n}\n\n/**\n * Error thrown when setWindow is called on a collection without an ORDER BY clause.\n */\nexport class SetWindowRequiresOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `setWindow() can only be called on collections with an ORDER BY clause. ` +\n `Add .orderBy() to your query to enable window movement.`\n )\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.cjs","sources":["../../src/errors.ts"],"sourcesContent":["// Root error class for all TanStack DB errors\nexport class TanStackDBError extends Error {\n constructor(message: string) {\n super(message)\n this.name = `TanStackDBError`\n }\n}\n\n// Base error classes\nexport class NonRetriableError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `NonRetriableError`\n }\n}\n\n// Schema validation error (exported from index for backward compatibility)\nexport class SchemaValidationError extends TanStackDBError {\n type: `insert` | `update`\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>\n\n constructor(\n type: `insert` | `update`,\n issues: ReadonlyArray<{\n message: string\n path?: ReadonlyArray<string | number | symbol>\n }>,\n message?: string\n ) {\n const defaultMessage = `${type === `insert` ? `Insert` : `Update`} validation failed: ${issues\n .map((issue) => `\\n- ${issue.message} - path: ${issue.path}`)\n .join(``)}`\n\n super(message || defaultMessage)\n this.name = `SchemaValidationError`\n this.type = type\n this.issues = issues\n }\n}\n\n// Module Instance Errors\nexport class DuplicateDbInstanceError extends TanStackDBError {\n constructor() {\n super(\n `Multiple instances of @tanstack/db detected!\\n\\n` +\n `This causes transaction context to be lost because each instance maintains ` +\n `its own transaction stack.\\n\\n` +\n `Common causes:\\n` +\n `1. Different versions of @tanstack/db installed\\n` +\n `2. Incompatible peer dependency versions in packages\\n` +\n `3. Module resolution issues in bundler configuration\\n\\n` +\n `To fix:\\n` +\n `1. Check installed versions: npm list @tanstack/db (or pnpm/yarn list)\\n` +\n `2. Force a single version using package manager overrides:\\n` +\n ` - npm: \"overrides\" in package.json\\n` +\n ` - pnpm: \"pnpm.overrides\" in package.json\\n` +\n ` - yarn: \"resolutions\" in package.json\\n` +\n `3. Clear node_modules and lockfile, then reinstall\\n\\n` +\n `To temporarily disable this check (not recommended):\\n` +\n `Set environment variable: TANSTACK_DB_DISABLE_DUP_CHECK=1\\n\\n` +\n `See: https://tanstack.com/db/latest/docs/troubleshooting#duplicate-instances`\n )\n this.name = `DuplicateDbInstanceError`\n }\n}\n\n// Collection Configuration Errors\nexport class CollectionConfigurationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionConfigurationError`\n }\n}\n\nexport class CollectionRequiresConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a config`)\n }\n}\n\nexport class CollectionRequiresSyncConfigError extends CollectionConfigurationError {\n constructor() {\n super(`Collection requires a sync config`)\n }\n}\n\nexport class InvalidSchemaError extends CollectionConfigurationError {\n constructor() {\n super(`Schema must implement the standard-schema interface`)\n }\n}\n\nexport class SchemaMustBeSynchronousError extends CollectionConfigurationError {\n constructor() {\n super(`Schema validation must be synchronous`)\n }\n}\n\n// Collection State Errors\nexport class CollectionStateError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionStateError`\n }\n}\n\nexport class CollectionInErrorStateError extends CollectionStateError {\n constructor(operation: string, collectionId: string) {\n super(\n `Cannot perform ${operation} on collection \"${collectionId}\" - collection is in error state. Try calling cleanup() and restarting the collection.`\n )\n }\n}\n\nexport class InvalidCollectionStatusTransitionError extends CollectionStateError {\n constructor(from: string, to: string, collectionId: string) {\n super(\n `Invalid collection status transition from \"${from}\" to \"${to}\" for collection \"${collectionId}\"`\n )\n }\n}\n\nexport class CollectionIsInErrorStateError extends CollectionStateError {\n constructor() {\n super(`Collection is in error state`)\n }\n}\n\nexport class NegativeActiveSubscribersError extends CollectionStateError {\n constructor() {\n super(`Active subscribers count is negative - this should never happen`)\n }\n}\n\n// Collection Operation Errors\nexport class CollectionOperationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `CollectionOperationError`\n }\n}\n\nexport class UndefinedKeyError extends CollectionOperationError {\n constructor(item: any) {\n super(\n `An object was created without a defined key: ${JSON.stringify(item)}`\n )\n }\n}\n\nexport class DuplicateKeyError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Cannot insert document with ID \"${key}\" because it already exists in the collection`\n )\n }\n}\n\nexport class DuplicateKeySyncError extends CollectionOperationError {\n constructor(\n key: string | number,\n collectionId: string,\n options?: { hasCustomGetKey?: boolean; hasJoins?: boolean }\n ) {\n const baseMessage = `Cannot insert document with key \"${key}\" from sync because it already exists in the collection \"${collectionId}\"`\n\n // Provide enhanced guidance when custom getKey is used with joins\n if (options?.hasCustomGetKey && options.hasJoins) {\n super(\n `${baseMessage}. ` +\n `This collection uses a custom getKey with joined queries. ` +\n `Joined queries can produce multiple rows with the same key when relationships are not 1:1. ` +\n `Consider: (1) using a composite key in your getKey function (e.g., \\`\\${item.key1}-\\${item.key2}\\`), ` +\n `(2) ensuring your join produces unique rows per key, or (3) removing the custom getKey ` +\n `to use the default composite key behavior.`\n )\n } else {\n super(baseMessage)\n }\n }\n}\n\nexport class MissingUpdateArgumentError extends CollectionOperationError {\n constructor() {\n super(`The first argument to update is missing`)\n }\n}\n\nexport class NoKeysPassedToUpdateError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to update`)\n }\n}\n\nexport class UpdateKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `The key \"${key}\" was passed to update but an object for this key was not found in the collection`\n )\n }\n}\n\nexport class KeyUpdateNotAllowedError extends CollectionOperationError {\n constructor(originalKey: string | number, newKey: string | number) {\n super(\n `Updating the key of an item is not allowed. Original key: \"${originalKey}\", Attempted new key: \"${newKey}\". Please delete the old item and create a new one if a key change is necessary.`\n )\n }\n}\n\nexport class NoKeysPassedToDeleteError extends CollectionOperationError {\n constructor() {\n super(`No keys were passed to delete`)\n }\n}\n\nexport class DeleteKeyNotFoundError extends CollectionOperationError {\n constructor(key: string | number) {\n super(\n `Collection.delete was called with key '${key}' but there is no item in the collection with this key`\n )\n }\n}\n\n// Collection Handler Errors\nexport class MissingHandlerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `MissingHandlerError`\n }\n}\n\nexport class MissingInsertHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.insert called directly (not within an explicit transaction) but no 'onInsert' handler is configured.`\n )\n }\n}\n\nexport class MissingUpdateHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.update called directly (not within an explicit transaction) but no 'onUpdate' handler is configured.`\n )\n }\n}\n\nexport class MissingDeleteHandlerError extends MissingHandlerError {\n constructor() {\n super(\n `Collection.delete called directly (not within an explicit transaction) but no 'onDelete' handler is configured.`\n )\n }\n}\n\n// Transaction Errors\nexport class TransactionError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `TransactionError`\n }\n}\n\nexport class MissingMutationFunctionError extends TransactionError {\n constructor() {\n super(`mutationFn is required when creating a transaction`)\n }\n}\n\nexport class OnMutateMustBeSynchronousError extends TransactionError {\n constructor() {\n super(\n `onMutate must be synchronous and cannot return a promise. Remove async/await or returned promises from onMutate.`\n )\n this.name = `OnMutateMustBeSynchronousError`\n }\n}\n\nexport class TransactionNotPendingMutateError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .mutate() as the transaction is no longer pending`\n )\n }\n}\n\nexport class TransactionAlreadyCompletedRollbackError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .rollback() as the transaction is already completed`\n )\n }\n}\n\nexport class TransactionNotPendingCommitError extends TransactionError {\n constructor() {\n super(\n `You can no longer call .commit() as the transaction is no longer pending`\n )\n }\n}\n\nexport class NoPendingSyncTransactionWriteError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to write to`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedWriteError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't still write to it.`\n )\n }\n}\n\nexport class NoPendingSyncTransactionCommitError extends TransactionError {\n constructor() {\n super(`No pending sync transaction to commit`)\n }\n}\n\nexport class SyncTransactionAlreadyCommittedError extends TransactionError {\n constructor() {\n super(\n `The pending sync transaction is already committed, you can't commit it again.`\n )\n }\n}\n\n// Query Builder Errors\nexport class QueryBuilderError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryBuilderError`\n }\n}\n\nexport class OnlyOneSourceAllowedError extends QueryBuilderError {\n constructor(context: string) {\n super(`Only one source is allowed in the ${context}`)\n }\n}\n\nexport class SubQueryMustHaveFromClauseError extends QueryBuilderError {\n constructor(context: string) {\n super(`A sub query passed to a ${context} must have a from clause itself`)\n }\n}\n\nexport class InvalidSourceError extends QueryBuilderError {\n constructor(alias: string) {\n super(\n `Invalid source for live query: The value provided for alias \"${alias}\" is not a Collection or subquery. Live queries only accept Collection instances or subqueries. Please ensure you're passing a valid Collection or QueryBuilder, not a plain array or other data type.`\n )\n }\n}\n\nexport class JoinConditionMustBeEqualityError extends QueryBuilderError {\n constructor() {\n super(`Join condition must be an equality expression`)\n }\n}\n\nexport class QueryMustHaveFromClauseError extends QueryBuilderError {\n constructor() {\n super(`Query must have a from clause`)\n }\n}\n\n// Query Compilation Errors\nexport class QueryCompilationError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryCompilationError`\n }\n}\n\nexport class DistinctRequiresSelectError extends QueryCompilationError {\n constructor() {\n super(`DISTINCT requires a SELECT clause.`)\n }\n}\n\nexport class HavingRequiresGroupByError extends QueryCompilationError {\n constructor() {\n super(`HAVING clause requires GROUP BY clause`)\n }\n}\n\nexport class LimitOffsetRequireOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `LIMIT and OFFSET require an ORDER BY clause to ensure deterministic results`\n )\n }\n}\n\n/**\n * Error thrown when a collection input stream is not found during query compilation.\n * In self-joins, each alias (e.g., 'employee', 'manager') requires its own input stream.\n */\nexport class CollectionInputNotFoundError extends QueryCompilationError {\n constructor(\n alias: string,\n collectionId?: string,\n availableKeys?: Array<string>\n ) {\n const details = collectionId\n ? `alias \"${alias}\" (collection \"${collectionId}\")`\n : `collection \"${alias}\"`\n const availableKeysMsg = availableKeys?.length\n ? `. Available keys: ${availableKeys.join(`, `)}`\n : ``\n super(`Input for ${details} not found in inputs map${availableKeysMsg}`)\n }\n}\n\n/**\n * Error thrown when a subquery uses the same alias as its parent query.\n * This causes issues because parent and subquery would share the same input streams,\n * leading to empty results or incorrect data (aggregation cross-leaking).\n */\nexport class DuplicateAliasInSubqueryError extends QueryCompilationError {\n constructor(alias: string, parentAliases: Array<string>) {\n super(\n `Subquery uses alias \"${alias}\" which is already used in the parent query. ` +\n `Each alias must be unique across parent and subquery contexts. ` +\n `Parent query aliases: ${parentAliases.join(`, `)}. ` +\n `Please rename \"${alias}\" in either the parent query or subquery to avoid conflicts.`\n )\n }\n}\n\nexport class UnsupportedFromTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unsupported FROM type: ${type}`)\n }\n}\n\nexport class UnknownExpressionTypeError extends QueryCompilationError {\n constructor(type: string) {\n super(`Unknown expression type: ${type}`)\n }\n}\n\nexport class EmptyReferencePathError extends QueryCompilationError {\n constructor() {\n super(`Reference path cannot be empty`)\n }\n}\n\nexport class UnknownFunctionError extends QueryCompilationError {\n constructor(functionName: string) {\n super(`Unknown function: ${functionName}`)\n }\n}\n\nexport class JoinCollectionNotFoundError extends QueryCompilationError {\n constructor(collectionId: string) {\n super(`Collection \"${collectionId}\" not found during compilation of join`)\n }\n}\n\n// JOIN Operation Errors\nexport class JoinError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `JoinError`\n }\n}\n\nexport class UnsupportedJoinTypeError extends JoinError {\n constructor(joinType: string) {\n super(`Unsupported join type: ${joinType}`)\n }\n}\n\nexport class InvalidJoinConditionSameSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: both expressions refer to the same source \"${sourceAlias}\"`\n )\n }\n}\n\nexport class InvalidJoinConditionSourceMismatchError extends JoinError {\n constructor() {\n super(`Invalid join condition: expressions must reference source aliases`)\n }\n}\n\nexport class InvalidJoinConditionLeftSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: left expression refers to an unavailable source \"${sourceAlias}\"`\n )\n }\n}\n\nexport class InvalidJoinConditionRightSourceError extends JoinError {\n constructor(sourceAlias: string) {\n super(\n `Invalid join condition: right expression does not refer to the joined source \"${sourceAlias}\"`\n )\n }\n}\n\nexport class InvalidJoinCondition extends JoinError {\n constructor() {\n super(`Invalid join condition`)\n }\n}\n\nexport class UnsupportedJoinSourceTypeError extends JoinError {\n constructor(type: string) {\n super(`Unsupported join source type: ${type}`)\n }\n}\n\n// GROUP BY and Aggregation Errors\nexport class GroupByError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `GroupByError`\n }\n}\n\nexport class NonAggregateExpressionNotInGroupByError extends GroupByError {\n constructor(alias: string) {\n super(\n `Non-aggregate expression '${alias}' in SELECT must also appear in GROUP BY clause`\n )\n }\n}\n\nexport class UnsupportedAggregateFunctionError extends GroupByError {\n constructor(functionName: string) {\n super(`Unsupported aggregate function: ${functionName}`)\n }\n}\n\nexport class AggregateFunctionNotInSelectError extends GroupByError {\n constructor(functionName: string) {\n super(\n `Aggregate function in HAVING clause must also be in SELECT clause: ${functionName}`\n )\n }\n}\n\nexport class UnknownHavingExpressionTypeError extends GroupByError {\n constructor(type: string) {\n super(`Unknown expression type in HAVING clause: ${type}`)\n }\n}\n\n// Storage Errors\nexport class StorageError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `StorageError`\n }\n}\n\nexport class SerializationError extends StorageError {\n constructor(operation: string, originalError: string) {\n super(\n `Cannot ${operation} item because it cannot be JSON serialized: ${originalError}`\n )\n }\n}\n\n// LocalStorage Collection Errors\nexport class LocalStorageCollectionError extends StorageError {\n constructor(message: string) {\n super(message)\n this.name = `LocalStorageCollectionError`\n }\n}\n\nexport class StorageKeyRequiredError extends LocalStorageCollectionError {\n constructor() {\n super(`[LocalStorageCollection] storageKey must be provided.`)\n }\n}\n\nexport class InvalidStorageDataFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string, key: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\" for key \"${key}\".`\n )\n }\n}\n\nexport class InvalidStorageObjectFormatError extends LocalStorageCollectionError {\n constructor(storageKey: string) {\n super(\n `[LocalStorageCollection] Invalid data format in storage key \"${storageKey}\". Expected object format.`\n )\n }\n}\n\n// Sync Cleanup Errors\nexport class SyncCleanupError extends TanStackDBError {\n constructor(collectionId: string, error: Error | string) {\n const message = error instanceof Error ? error.message : String(error)\n super(\n `Collection \"${collectionId}\" sync cleanup function threw an error: ${message}`\n )\n this.name = `SyncCleanupError`\n }\n}\n\n// Query Optimizer Errors\nexport class QueryOptimizerError extends TanStackDBError {\n constructor(message: string) {\n super(message)\n this.name = `QueryOptimizerError`\n }\n}\n\nexport class CannotCombineEmptyExpressionListError extends QueryOptimizerError {\n constructor() {\n super(`Cannot combine empty expression list`)\n }\n}\n\n/**\n * Internal error when the query optimizer fails to convert a WHERE clause to a collection filter.\n */\nexport class WhereClauseConversionError extends QueryOptimizerError {\n constructor(collectionId: string, alias: string) {\n super(\n `Failed to convert WHERE clause to collection filter for collection '${collectionId}' alias '${alias}'. This indicates a bug in the query optimization logic.`\n )\n }\n}\n\n/**\n * Error when a subscription cannot be found during lazy join processing.\n * For subqueries, aliases may be remapped (e.g., 'activeUser' → 'user').\n */\nexport class SubscriptionNotFoundError extends QueryCompilationError {\n constructor(\n resolvedAlias: string,\n originalAlias: string,\n collectionId: string,\n availableAliases: Array<string>\n ) {\n super(\n `Internal error: subscription for alias '${resolvedAlias}' (remapped from '${originalAlias}', collection '${collectionId}') is missing in join pipeline. Available aliases: ${availableAliases.join(`, `)}. This indicates a bug in alias tracking.`\n )\n }\n}\n\n/**\n * Error thrown when aggregate expressions are used outside of a GROUP BY context.\n */\nexport class AggregateNotSupportedError extends QueryCompilationError {\n constructor() {\n super(\n `Aggregate expressions are not supported in this context. Use GROUP BY clause for aggregates.`\n )\n }\n}\n\n/**\n * Internal error when the compiler returns aliases that don't have corresponding input streams.\n * This should never happen since all aliases come from user declarations.\n */\nexport class MissingAliasInputsError extends QueryCompilationError {\n constructor(missingAliases: Array<string>) {\n super(\n `Internal error: compiler returned aliases without inputs: ${missingAliases.join(`, `)}. ` +\n `This indicates a bug in query compilation. Please report this issue.`\n )\n }\n}\n\n/**\n * Error thrown when setWindow is called on a collection without an ORDER BY clause.\n */\nexport class SetWindowRequiresOrderByError extends QueryCompilationError {\n constructor() {\n super(\n `setWindow() can only be called on collections with an ORDER BY clause. ` +\n `Add .orderBy() to your query to enable window movement.`\n )\n }\n}\n"],"names":[],"mappings":"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"}
@@ -58,7 +58,10 @@ export declare class DuplicateKeyError extends CollectionOperationError {
58
58
  constructor(key: string | number);
59
59
  }
60
60
  export declare class DuplicateKeySyncError extends CollectionOperationError {
61
- constructor(key: string | number, collectionId: string);
61
+ constructor(key: string | number, collectionId: string, options?: {
62
+ hasCustomGetKey?: boolean;
63
+ hasJoins?: boolean;
64
+ });
62
65
  }
63
66
  export declare class MissingUpdateArgumentError extends CollectionOperationError {
64
67
  constructor();
@@ -13,10 +13,13 @@ const pacedMutations = require("./paced-mutations.cjs");
13
13
  const baseIndex = require("./indexes/base-index.cjs");
14
14
  const btreeIndex = require("./indexes/btree-index.cjs");
15
15
  const lazyIndex = require("./indexes/lazy-index.cjs");
16
- const index$1 = require("./query/builder/index.cjs");
16
+ const expressionHelpers = require("./query/expression-helpers.cjs");
17
17
  const functions = require("./query/builder/functions.cjs");
18
+ const index$1 = require("./query/builder/index.cjs");
18
19
  const index$2 = require("./query/compiler/index.cjs");
19
20
  const liveQueryCollection = require("./query/live-query-collection.cjs");
21
+ const predicateUtils = require("./query/predicate-utils.cjs");
22
+ const subsetDedupe = require("./query/subset-dedupe.cjs");
20
23
  const debounceStrategy = require("./strategies/debounceStrategy.cjs");
21
24
  const queueStrategy = require("./strategies/queueStrategy.cjs");
22
25
  const throttleStrategy = require("./strategies/throttleStrategy.cjs");
@@ -121,8 +124,13 @@ exports.IndexOperation = baseIndex.IndexOperation;
121
124
  exports.BTreeIndex = btreeIndex.BTreeIndex;
122
125
  exports.IndexProxy = lazyIndex.IndexProxy;
123
126
  exports.LazyIndexWrapper = lazyIndex.LazyIndexWrapper;
124
- exports.BaseQueryBuilder = index$1.BaseQueryBuilder;
125
- exports.Query = index$1.Query;
127
+ exports.extractFieldPath = expressionHelpers.extractFieldPath;
128
+ exports.extractSimpleComparisons = expressionHelpers.extractSimpleComparisons;
129
+ exports.extractValue = expressionHelpers.extractValue;
130
+ exports.parseLoadSubsetOptions = expressionHelpers.parseLoadSubsetOptions;
131
+ exports.parseOrderByExpression = expressionHelpers.parseOrderByExpression;
132
+ exports.parseWhereExpression = expressionHelpers.parseWhereExpression;
133
+ exports.walkExpression = expressionHelpers.walkExpression;
126
134
  exports.add = functions.add;
127
135
  exports.and = functions.and;
128
136
  exports.avg = functions.avg;
@@ -144,12 +152,22 @@ exports.lte = functions.lte;
144
152
  exports.max = functions.max;
145
153
  exports.min = functions.min;
146
154
  exports.not = functions.not;
155
+ exports.operators = functions.operators;
147
156
  exports.or = functions.or;
148
157
  exports.sum = functions.sum;
149
158
  exports.upper = functions.upper;
159
+ exports.BaseQueryBuilder = index$1.BaseQueryBuilder;
160
+ exports.Query = index$1.Query;
150
161
  exports.compileQuery = index$2.compileQuery;
151
162
  exports.createLiveQueryCollection = liveQueryCollection.createLiveQueryCollection;
152
163
  exports.liveQueryCollectionOptions = liveQueryCollection.liveQueryCollectionOptions;
164
+ exports.isLimitSubset = predicateUtils.isLimitSubset;
165
+ exports.isOrderBySubset = predicateUtils.isOrderBySubset;
166
+ exports.isPredicateSubset = predicateUtils.isPredicateSubset;
167
+ exports.isWhereSubset = predicateUtils.isWhereSubset;
168
+ exports.minusWherePredicates = predicateUtils.minusWherePredicates;
169
+ exports.unionWherePredicates = predicateUtils.unionWherePredicates;
170
+ exports.DeduplicatedLoadSubset = subsetDedupe.DeduplicatedLoadSubset;
153
171
  exports.debounceStrategy = debounceStrategy.debounceStrategy;
154
172
  exports.queueStrategy = queueStrategy.queueStrategy;
155
173
  exports.throttleStrategy = throttleStrategy.throttleStrategy;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -15,5 +15,7 @@ export * from './indexes/base-index.js';
15
15
  export * from './indexes/btree-index.js';
16
16
  export * from './indexes/lazy-index.js';
17
17
  export { type IndexOptions } from './indexes/index-options.js';
18
+ export * from './query/expression-helpers.js';
18
19
  export type { Collection } from './collection/index.js';
19
20
  export { IR };
21
+ export { operators, type OperatorName } from './query/builder/functions.js';
@@ -8,12 +8,16 @@ function shouldAutoIndex(collection) {
8
8
  }
9
9
  return true;
10
10
  }
11
- function ensureIndexForField(fieldName, fieldPath, collection, compareOptions = utils.DEFAULT_COMPARE_OPTIONS, compareFn) {
11
+ function ensureIndexForField(fieldName, fieldPath, collection, compareOptions, compareFn) {
12
12
  if (!shouldAutoIndex(collection)) {
13
13
  return;
14
14
  }
15
+ const compareOpts = compareOptions ?? {
16
+ ...utils.DEFAULT_COMPARE_OPTIONS,
17
+ ...collection.compareOptions
18
+ };
15
19
  const existingIndex = Array.from(collection.indexes.values()).find(
16
- (index) => index.matchesField(fieldPath) && index.matchesCompareOptions(compareOptions)
20
+ (index) => index.matchesField(fieldPath) && index.matchesCompareOptions(compareOpts)
17
21
  );
18
22
  if (existingIndex) {
19
23
  return;
@@ -30,7 +34,7 @@ function ensureIndexForField(fieldName, fieldPath, collection, compareOptions =
30
34
  {
31
35
  name: `auto:${fieldPath.join(`.`)}`,
32
36
  indexType: btreeIndex.BTreeIndex,
33
- options: compareFn ? { compareFn, compareOptions } : {}
37
+ options: compareFn ? { compareFn, compareOptions: compareOpts } : {}
34
38
  }
35
39
  );
36
40
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"auto-index.cjs","sources":["../../../src/indexes/auto-index.ts"],"sourcesContent":["import { DEFAULT_COMPARE_OPTIONS } from \"../utils\"\nimport { BTreeIndex } from \"./btree-index\"\nimport type { CompareOptions } from \"../query/builder/types\"\nimport type { BasicExpression } from \"../query/ir\"\nimport type { CollectionImpl } from \"../collection/index.js\"\n\nexport interface AutoIndexConfig {\n autoIndex?: `off` | `eager`\n}\n\nfunction shouldAutoIndex(collection: CollectionImpl<any, any, any, any, any>) {\n // Only proceed if auto-indexing is enabled\n if (collection.config.autoIndex !== `eager`) {\n return false\n }\n\n return true\n}\n\nexport function ensureIndexForField<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n fieldName: string,\n fieldPath: Array<string>,\n collection: CollectionImpl<T, TKey, any, any, any>,\n compareOptions: CompareOptions = DEFAULT_COMPARE_OPTIONS,\n compareFn?: (a: any, b: any) => number\n) {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n // Check if we already have an index for this field\n const existingIndex = Array.from(collection.indexes.values()).find(\n (index) =>\n index.matchesField(fieldPath) &&\n index.matchesCompareOptions(compareOptions)\n )\n\n if (existingIndex) {\n return // Index already exists\n }\n\n // Create a new index for this field using the collection's createIndex method\n try {\n // Use the proxy-based approach to create the proper accessor for nested paths\n collection.createIndex(\n (row) => {\n // Navigate through the field path\n let current: any = row\n for (const part of fieldPath) {\n current = current[part]\n }\n return current\n },\n {\n name: `auto:${fieldPath.join(`.`)}`,\n indexType: BTreeIndex,\n options: compareFn ? { compareFn, compareOptions } : {},\n }\n )\n } catch (error) {\n console.warn(\n `${collection.id ? `[${collection.id}] ` : ``}Failed to create auto-index for field path \"${fieldPath.join(`.`)}\":`,\n error\n )\n }\n}\n\n/**\n * Analyzes a where expression and creates indexes for all simple operations on single fields\n */\nexport function ensureIndexForExpression<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n expression: BasicExpression,\n collection: CollectionImpl<T, TKey, any, any, any>\n): void {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n // Extract all indexable expressions and create indexes for them\n const indexableExpressions = extractIndexableExpressions(expression)\n\n for (const { fieldName, fieldPath } of indexableExpressions) {\n ensureIndexForField(fieldName, fieldPath, collection)\n }\n}\n\n/**\n * Extracts all indexable expressions from a where expression\n */\nfunction extractIndexableExpressions(\n expression: BasicExpression\n): Array<{ fieldName: string; fieldPath: Array<string> }> {\n const results: Array<{ fieldName: string; fieldPath: Array<string> }> = []\n\n function extractFromExpression(expr: BasicExpression): void {\n if (expr.type !== `func`) {\n return\n }\n\n const func = expr as any\n\n // Handle 'and' expressions by recursively processing all arguments\n if (func.name === `and`) {\n for (const arg of func.args) {\n extractFromExpression(arg)\n }\n return\n }\n\n // Check if this is a supported operation\n const supportedOperations = [`eq`, `gt`, `gte`, `lt`, `lte`, `in`]\n if (!supportedOperations.includes(func.name)) {\n return\n }\n\n // Check if the first argument is a property reference\n if (func.args.length < 1 || func.args[0].type !== `ref`) {\n return\n }\n\n const fieldRef = func.args[0]\n const fieldPath = fieldRef.path\n\n // Skip if the path is empty\n if (fieldPath.length === 0) {\n return\n }\n\n // For nested paths, use the full path joined with underscores as the field name\n // For simple paths, use the first (and only) element\n const fieldName = fieldPath.join(`_`)\n results.push({ fieldName, fieldPath })\n }\n\n extractFromExpression(expression)\n return results\n}\n"],"names":["DEFAULT_COMPARE_OPTIONS","BTreeIndex"],"mappings":";;;;AAUA,SAAS,gBAAgB,YAAqD;AAE5E,MAAI,WAAW,OAAO,cAAc,SAAS;AAC3C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,oBAId,WACA,WACA,YACA,iBAAiCA,MAAAA,yBACjC,WACA;AACA,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,KAAK,WAAW,QAAQ,OAAA,CAAQ,EAAE;AAAA,IAC5D,CAAC,UACC,MAAM,aAAa,SAAS,KAC5B,MAAM,sBAAsB,cAAc;AAAA,EAAA;AAG9C,MAAI,eAAe;AACjB;AAAA,EACF;AAGA,MAAI;AAEF,eAAW;AAAA,MACT,CAAC,QAAQ;AAEP,YAAI,UAAe;AACnB,mBAAW,QAAQ,WAAW;AAC5B,oBAAU,QAAQ,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM,QAAQ,UAAU,KAAK,GAAG,CAAC;AAAA,QACjC,WAAWC,WAAAA;AAAAA,QACX,SAAS,YAAY,EAAE,WAAW,eAAA,IAAmB,CAAA;AAAA,MAAC;AAAA,IACxD;AAAA,EAEJ,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,GAAG,WAAW,KAAK,IAAI,WAAW,EAAE,OAAO,EAAE,+CAA+C,UAAU,KAAK,GAAG,CAAC;AAAA,MAC/G;AAAA,IAAA;AAAA,EAEJ;AACF;AAKO,SAAS,yBAId,YACA,YACM;AACN,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,uBAAuB,4BAA4B,UAAU;AAEnE,aAAW,EAAE,WAAW,UAAA,KAAe,sBAAsB;AAC3D,wBAAoB,WAAW,WAAW,UAAU;AAAA,EACtD;AACF;AAKA,SAAS,4BACP,YACwD;AACxD,QAAM,UAAkE,CAAA;AAExE,WAAS,sBAAsB,MAA6B;AAC1D,QAAI,KAAK,SAAS,QAAQ;AACxB;AAAA,IACF;AAEA,UAAM,OAAO;AAGb,QAAI,KAAK,SAAS,OAAO;AACvB,iBAAW,OAAO,KAAK,MAAM;AAC3B,8BAAsB,GAAG;AAAA,MAC3B;AACA;AAAA,IACF;AAGA,UAAM,sBAAsB,CAAC,MAAM,MAAM,OAAO,MAAM,OAAO,IAAI;AACjE,QAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,GAAG;AAC5C;AAAA,IACF;AAGA,QAAI,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,EAAE,SAAS,OAAO;AACvD;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,KAAK,CAAC;AAC5B,UAAM,YAAY,SAAS;AAG3B,QAAI,UAAU,WAAW,GAAG;AAC1B;AAAA,IACF;AAIA,UAAM,YAAY,UAAU,KAAK,GAAG;AACpC,YAAQ,KAAK,EAAE,WAAW,UAAA,CAAW;AAAA,EACvC;AAEA,wBAAsB,UAAU;AAChC,SAAO;AACT;;;"}
1
+ {"version":3,"file":"auto-index.cjs","sources":["../../../src/indexes/auto-index.ts"],"sourcesContent":["import { DEFAULT_COMPARE_OPTIONS } from \"../utils\"\nimport { BTreeIndex } from \"./btree-index\"\nimport type { CompareOptions } from \"../query/builder/types\"\nimport type { BasicExpression } from \"../query/ir\"\nimport type { CollectionImpl } from \"../collection/index.js\"\n\nexport interface AutoIndexConfig {\n autoIndex?: `off` | `eager`\n}\n\nfunction shouldAutoIndex(collection: CollectionImpl<any, any, any, any, any>) {\n // Only proceed if auto-indexing is enabled\n if (collection.config.autoIndex !== `eager`) {\n return false\n }\n\n return true\n}\n\nexport function ensureIndexForField<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n fieldName: string,\n fieldPath: Array<string>,\n collection: CollectionImpl<T, TKey, any, any, any>,\n compareOptions?: CompareOptions,\n compareFn?: (a: any, b: any) => number\n) {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n const compareOpts = compareOptions ?? {\n ...DEFAULT_COMPARE_OPTIONS,\n ...collection.compareOptions,\n }\n\n // Check if we already have an index for this field\n const existingIndex = Array.from(collection.indexes.values()).find(\n (index) =>\n index.matchesField(fieldPath) && index.matchesCompareOptions(compareOpts)\n )\n\n if (existingIndex) {\n return // Index already exists\n }\n\n // Create a new index for this field using the collection's createIndex method\n try {\n // Use the proxy-based approach to create the proper accessor for nested paths\n collection.createIndex(\n (row) => {\n // Navigate through the field path\n let current: any = row\n for (const part of fieldPath) {\n current = current[part]\n }\n return current\n },\n {\n name: `auto:${fieldPath.join(`.`)}`,\n indexType: BTreeIndex,\n options: compareFn ? { compareFn, compareOptions: compareOpts } : {},\n }\n )\n } catch (error) {\n console.warn(\n `${collection.id ? `[${collection.id}] ` : ``}Failed to create auto-index for field path \"${fieldPath.join(`.`)}\":`,\n error\n )\n }\n}\n\n/**\n * Analyzes a where expression and creates indexes for all simple operations on single fields\n */\nexport function ensureIndexForExpression<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n expression: BasicExpression,\n collection: CollectionImpl<T, TKey, any, any, any>\n): void {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n // Extract all indexable expressions and create indexes for them\n const indexableExpressions = extractIndexableExpressions(expression)\n\n for (const { fieldName, fieldPath } of indexableExpressions) {\n ensureIndexForField(fieldName, fieldPath, collection)\n }\n}\n\n/**\n * Extracts all indexable expressions from a where expression\n */\nfunction extractIndexableExpressions(\n expression: BasicExpression\n): Array<{ fieldName: string; fieldPath: Array<string> }> {\n const results: Array<{ fieldName: string; fieldPath: Array<string> }> = []\n\n function extractFromExpression(expr: BasicExpression): void {\n if (expr.type !== `func`) {\n return\n }\n\n const func = expr as any\n\n // Handle 'and' expressions by recursively processing all arguments\n if (func.name === `and`) {\n for (const arg of func.args) {\n extractFromExpression(arg)\n }\n return\n }\n\n // Check if this is a supported operation\n const supportedOperations = [`eq`, `gt`, `gte`, `lt`, `lte`, `in`]\n if (!supportedOperations.includes(func.name)) {\n return\n }\n\n // Check if the first argument is a property reference\n if (func.args.length < 1 || func.args[0].type !== `ref`) {\n return\n }\n\n const fieldRef = func.args[0]\n const fieldPath = fieldRef.path\n\n // Skip if the path is empty\n if (fieldPath.length === 0) {\n return\n }\n\n // For nested paths, use the full path joined with underscores as the field name\n // For simple paths, use the first (and only) element\n const fieldName = fieldPath.join(`_`)\n results.push({ fieldName, fieldPath })\n }\n\n extractFromExpression(expression)\n return results\n}\n"],"names":["DEFAULT_COMPARE_OPTIONS","BTreeIndex"],"mappings":";;;;AAUA,SAAS,gBAAgB,YAAqD;AAE5E,MAAI,WAAW,OAAO,cAAc,SAAS;AAC3C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,oBAId,WACA,WACA,YACA,gBACA,WACA;AACA,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAEA,QAAM,cAAc,kBAAkB;AAAA,IACpC,GAAGA,MAAAA;AAAAA,IACH,GAAG,WAAW;AAAA,EAAA;AAIhB,QAAM,gBAAgB,MAAM,KAAK,WAAW,QAAQ,OAAA,CAAQ,EAAE;AAAA,IAC5D,CAAC,UACC,MAAM,aAAa,SAAS,KAAK,MAAM,sBAAsB,WAAW;AAAA,EAAA;AAG5E,MAAI,eAAe;AACjB;AAAA,EACF;AAGA,MAAI;AAEF,eAAW;AAAA,MACT,CAAC,QAAQ;AAEP,YAAI,UAAe;AACnB,mBAAW,QAAQ,WAAW;AAC5B,oBAAU,QAAQ,IAAI;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,MAAM,QAAQ,UAAU,KAAK,GAAG,CAAC;AAAA,QACjC,WAAWC,WAAAA;AAAAA,QACX,SAAS,YAAY,EAAE,WAAW,gBAAgB,YAAA,IAAgB,CAAA;AAAA,MAAC;AAAA,IACrE;AAAA,EAEJ,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,GAAG,WAAW,KAAK,IAAI,WAAW,EAAE,OAAO,EAAE,+CAA+C,UAAU,KAAK,GAAG,CAAC;AAAA,MAC/G;AAAA,IAAA;AAAA,EAEJ;AACF;AAKO,SAAS,yBAId,YACA,YACM;AACN,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,uBAAuB,4BAA4B,UAAU;AAEnE,aAAW,EAAE,WAAW,UAAA,KAAe,sBAAsB;AAC3D,wBAAoB,WAAW,WAAW,UAAU;AAAA,EACtD;AACF;AAKA,SAAS,4BACP,YACwD;AACxD,QAAM,UAAkE,CAAA;AAExE,WAAS,sBAAsB,MAA6B;AAC1D,QAAI,KAAK,SAAS,QAAQ;AACxB;AAAA,IACF;AAEA,UAAM,OAAO;AAGb,QAAI,KAAK,SAAS,OAAO;AACvB,iBAAW,OAAO,KAAK,MAAM;AAC3B,8BAAsB,GAAG;AAAA,MAC3B;AACA;AAAA,IACF;AAGA,UAAM,sBAAsB,CAAC,MAAM,MAAM,OAAO,MAAM,OAAO,IAAI;AACjE,QAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,GAAG;AAC5C;AAAA,IACF;AAGA,QAAI,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,EAAE,SAAS,OAAO;AACvD;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,KAAK,CAAC;AAC5B,UAAM,YAAY,SAAS;AAG3B,QAAI,UAAU,WAAW,GAAG;AAC1B;AAAA,IACF;AAIA,UAAM,YAAY,UAAU,KAAK,GAAG;AACpC,YAAQ,KAAK,EAAE,WAAW,UAAA,CAAW;AAAA,EACvC;AAEA,wBAAsB,UAAU;AAChC,SAAO;AACT;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"local-storage.cjs","sources":["../../src/local-storage.ts"],"sourcesContent":["import {\n InvalidStorageDataFormatError,\n InvalidStorageObjectFormatError,\n SerializationError,\n StorageKeyRequiredError,\n} from \"./errors\"\nimport type {\n BaseCollectionConfig,\n CollectionConfig,\n DeleteMutationFnParams,\n InferSchemaOutput,\n InsertMutationFnParams,\n PendingMutation,\n SyncConfig,\n UpdateMutationFnParams,\n UtilsRecord,\n} from \"./types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\n/**\n * Storage API interface - subset of DOM Storage that we need\n */\nexport type StorageApi = Pick<Storage, `getItem` | `setItem` | `removeItem`>\n\n/**\n * Storage event API - subset of Window for 'storage' events only\n */\nexport type StorageEventApi = {\n addEventListener: (\n type: `storage`,\n listener: (event: StorageEvent) => void\n ) => void\n removeEventListener: (\n type: `storage`,\n listener: (event: StorageEvent) => void\n ) => void\n}\n\n/**\n * Internal storage format that includes version tracking\n */\ninterface StoredItem<T> {\n versionKey: string\n data: T\n}\n\nexport interface Parser {\n parse: (data: string) => unknown\n stringify: (data: unknown) => string\n}\n\n/**\n * Configuration interface for localStorage collection options\n * @template T - The type of items in the collection\n * @template TSchema - The schema type for validation\n * @template TKey - The type of the key returned by `getKey`\n */\nexport interface LocalStorageCollectionConfig<\n T extends object = object,\n TSchema extends StandardSchemaV1 = never,\n TKey extends string | number = string | number,\n> extends BaseCollectionConfig<T, TKey, TSchema> {\n /**\n * The key to use for storing the collection data in localStorage/sessionStorage\n */\n storageKey: string\n\n /**\n * Storage API to use (defaults to window.localStorage)\n * Can be any object that implements the Storage interface (e.g., sessionStorage)\n */\n storage?: StorageApi\n\n /**\n * Storage event API to use for cross-tab synchronization (defaults to window)\n * Can be any object that implements addEventListener/removeEventListener for storage events\n */\n storageEventApi?: StorageEventApi\n\n /**\n * Parser to use for serializing and deserializing data to and from storage\n * Defaults to JSON\n */\n parser?: Parser\n}\n\n/**\n * Type for the clear utility function\n */\nexport type ClearStorageFn = () => void\n\n/**\n * Type for the getStorageSize utility function\n */\nexport type GetStorageSizeFn = () => number\n\n/**\n * LocalStorage collection utilities type\n */\nexport interface LocalStorageCollectionUtils extends UtilsRecord {\n clearStorage: ClearStorageFn\n getStorageSize: GetStorageSizeFn\n /**\n * Accepts mutations from a transaction that belong to this collection and persists them to localStorage.\n * This should be called in your transaction's mutationFn to persist local-storage data.\n *\n * @param transaction - The transaction containing mutations to accept\n * @example\n * const localSettings = createCollection(localStorageCollectionOptions({...}))\n *\n * const tx = createTransaction({\n * mutationFn: async ({ transaction }) => {\n * // Make API call first\n * await api.save(...)\n * // Then persist local-storage mutations after success\n * localSettings.utils.acceptMutations(transaction)\n * }\n * })\n */\n acceptMutations: (transaction: {\n mutations: Array<PendingMutation<Record<string, unknown>>>\n }) => void\n}\n\n/**\n * Validates that a value can be JSON serialized\n * @param parser - The parser to use for serialization\n * @param value - The value to validate for JSON serialization\n * @param operation - The operation type being performed (for error messages)\n * @throws Error if the value cannot be JSON serialized\n */\nfunction validateJsonSerializable(\n parser: Parser,\n value: any,\n operation: string\n): void {\n try {\n parser.stringify(value)\n } catch (error) {\n throw new SerializationError(\n operation,\n error instanceof Error ? error.message : String(error)\n )\n }\n}\n\n/**\n * Generate a UUID for version tracking\n * @returns A unique identifier string for tracking data versions\n */\nfunction generateUuid(): string {\n return crypto.randomUUID()\n}\n\n/**\n * Creates an in-memory storage implementation that mimics the StorageApi interface\n * Used as a fallback when localStorage is not available (e.g., server-side rendering)\n * @returns An object implementing the StorageApi interface using an in-memory Map\n */\nfunction createInMemoryStorage(): StorageApi {\n const storage = new Map<string, string>()\n\n return {\n getItem(key: string): string | null {\n return storage.get(key) ?? null\n },\n setItem(key: string, value: string): void {\n storage.set(key, value)\n },\n removeItem(key: string): void {\n storage.delete(key)\n },\n }\n}\n\n/**\n * Creates a no-op storage event API for environments without window (e.g., server-side)\n * This provides the required interface but doesn't actually listen to any events\n * since cross-tab synchronization is not possible in server environments\n * @returns An object implementing the StorageEventApi interface with no-op methods\n */\nfunction createNoOpStorageEventApi(): StorageEventApi {\n return {\n addEventListener: () => {\n // No-op: cannot listen to storage events without window\n },\n removeEventListener: () => {\n // No-op: cannot remove listeners without window\n },\n }\n}\n\n/**\n * Creates localStorage collection options for use with a standard Collection\n *\n * This function creates a collection that persists data to localStorage/sessionStorage\n * and synchronizes changes across browser tabs using storage events.\n *\n * **Fallback Behavior:**\n *\n * When localStorage is not available (e.g., in server-side rendering environments),\n * this function automatically falls back to an in-memory storage implementation.\n * This prevents errors during module initialization and allows the collection to\n * work in any environment, though data will not persist across page reloads or\n * be shared across tabs when using the in-memory fallback.\n *\n * **Using with Manual Transactions:**\n *\n * For manual transactions, you must call `utils.acceptMutations()` in your transaction's `mutationFn`\n * to persist changes made during `tx.mutate()`. This is necessary because local-storage collections\n * don't participate in the standard mutation handler flow for manual transactions.\n *\n * @template TExplicit - The explicit type of items in the collection (highest priority)\n * @template TSchema - The schema type for validation and type inference (second priority)\n * @template TFallback - The fallback type if no explicit or schema type is provided\n * @param config - Configuration options for the localStorage collection\n * @returns Collection options with utilities including clearStorage, getStorageSize, and acceptMutations\n *\n * @example\n * // Basic localStorage collection\n * const collection = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'todos',\n * getKey: (item) => item.id,\n * })\n * )\n *\n * @example\n * // localStorage collection with custom storage\n * const collection = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'todos',\n * storage: window.sessionStorage, // Use sessionStorage instead\n * getKey: (item) => item.id,\n * })\n * )\n *\n * @example\n * // localStorage collection with mutation handlers\n * const collection = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'todos',\n * getKey: (item) => item.id,\n * onInsert: async ({ transaction }) => {\n * console.log('Item inserted:', transaction.mutations[0].modified)\n * },\n * })\n * )\n *\n * @example\n * // Using with manual transactions\n * const localSettings = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'user-settings',\n * getKey: (item) => item.id,\n * })\n * )\n *\n * const tx = createTransaction({\n * mutationFn: async ({ transaction }) => {\n * // Use settings data in API call\n * const settingsMutations = transaction.mutations.filter(m => m.collection === localSettings)\n * await api.updateUserProfile({ settings: settingsMutations[0]?.modified })\n *\n * // Persist local-storage mutations after API success\n * localSettings.utils.acceptMutations(transaction)\n * }\n * })\n *\n * tx.mutate(() => {\n * localSettings.insert({ id: 'theme', value: 'dark' })\n * apiCollection.insert({ id: 2, data: 'profile data' })\n * })\n *\n * await tx.commit()\n */\n\n// Overload for when schema is provided\nexport function localStorageCollectionOptions<\n T extends StandardSchemaV1,\n TKey extends string | number = string | number,\n>(\n config: LocalStorageCollectionConfig<InferSchemaOutput<T>, T, TKey> & {\n schema: T\n }\n): CollectionConfig<InferSchemaOutput<T>, TKey, T> & {\n id: string\n utils: LocalStorageCollectionUtils\n schema: T\n}\n\n// Overload for when no schema is provided\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function localStorageCollectionOptions<\n T extends object,\n TKey extends string | number = string | number,\n>(\n config: LocalStorageCollectionConfig<T, never, TKey> & {\n schema?: never // prohibit schema\n }\n): CollectionConfig<T, TKey> & {\n id: string\n utils: LocalStorageCollectionUtils\n schema?: never // no schema in the result\n}\n\nexport function localStorageCollectionOptions(\n config: LocalStorageCollectionConfig<any, any, string | number>\n): Omit<CollectionConfig<any, string | number, any>, `id`> & {\n id: string\n utils: LocalStorageCollectionUtils\n schema?: StandardSchemaV1\n} {\n // Validate required parameters\n if (!config.storageKey) {\n throw new StorageKeyRequiredError()\n }\n\n // Default to window.localStorage if no storage is provided\n // Fall back to in-memory storage if localStorage is not available (e.g., server-side rendering)\n const storage =\n config.storage ||\n (typeof window !== `undefined` ? window.localStorage : null) ||\n createInMemoryStorage()\n\n // Default to window for storage events if not provided\n // Fall back to no-op storage event API if window is not available (e.g., server-side rendering)\n const storageEventApi =\n config.storageEventApi ||\n (typeof window !== `undefined` ? window : null) ||\n createNoOpStorageEventApi()\n\n // Default to JSON parser if no parser is provided\n const parser = config.parser || JSON\n\n // Track the last known state to detect changes\n const lastKnownData = new Map<string | number, StoredItem<any>>()\n\n // Create the sync configuration\n const sync = createLocalStorageSync<any>(\n config.storageKey,\n storage,\n storageEventApi,\n parser,\n config.getKey,\n lastKnownData\n )\n\n /**\n * Save data to storage\n * @param dataMap - Map of items with version tracking to save to storage\n */\n const saveToStorage = (\n dataMap: Map<string | number, StoredItem<any>>\n ): void => {\n try {\n // Convert Map to object format for storage\n const objectData: Record<string, StoredItem<any>> = {}\n dataMap.forEach((storedItem, key) => {\n objectData[String(key)] = storedItem\n })\n const serialized = parser.stringify(objectData)\n storage.setItem(config.storageKey, serialized)\n } catch (error) {\n console.error(\n `[LocalStorageCollection] Error saving data to storage key \"${config.storageKey}\":`,\n error\n )\n throw error\n }\n }\n\n /**\n * Removes all collection data from the configured storage\n */\n const clearStorage: ClearStorageFn = (): void => {\n storage.removeItem(config.storageKey)\n }\n\n /**\n * Get the size of the stored data in bytes (approximate)\n * @returns The approximate size in bytes of the stored collection data\n */\n const getStorageSize: GetStorageSizeFn = (): number => {\n const data = storage.getItem(config.storageKey)\n return data ? new Blob([data]).size : 0\n }\n\n /*\n * Create wrapper handlers for direct persistence operations that perform actual storage operations\n * Wraps the user's onInsert handler to also save changes to localStorage\n */\n const wrappedOnInsert = async (params: InsertMutationFnParams<any>) => {\n // Validate that all values in the transaction can be JSON serialized\n params.transaction.mutations.forEach((mutation) => {\n validateJsonSerializable(parser, mutation.modified, `insert`)\n })\n\n // Call the user handler BEFORE persisting changes (if provided)\n let handlerResult: any = {}\n if (config.onInsert) {\n handlerResult = (await config.onInsert(params)) ?? {}\n }\n\n // Always persist to storage\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Add new items with version keys\n params.transaction.mutations.forEach((mutation) => {\n // Use the engine's pre-computed key for consistency\n const key = mutation.key\n const storedItem: StoredItem<any> = {\n versionKey: generateUuid(),\n data: mutation.modified,\n }\n lastKnownData.set(key, storedItem)\n })\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm mutations through sync interface (moves from optimistic to synced state)\n // without reloading from storage\n sync.confirmOperationsSync(params.transaction.mutations)\n\n return handlerResult\n }\n\n const wrappedOnUpdate = async (params: UpdateMutationFnParams<any>) => {\n // Validate that all values in the transaction can be JSON serialized\n params.transaction.mutations.forEach((mutation) => {\n validateJsonSerializable(parser, mutation.modified, `update`)\n })\n\n // Call the user handler BEFORE persisting changes (if provided)\n let handlerResult: any = {}\n if (config.onUpdate) {\n handlerResult = (await config.onUpdate(params)) ?? {}\n }\n\n // Always persist to storage\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Update items with new version keys\n params.transaction.mutations.forEach((mutation) => {\n // Use the engine's pre-computed key for consistency\n const key = mutation.key\n const storedItem: StoredItem<any> = {\n versionKey: generateUuid(),\n data: mutation.modified,\n }\n lastKnownData.set(key, storedItem)\n })\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm mutations through sync interface (moves from optimistic to synced state)\n // without reloading from storage\n sync.confirmOperationsSync(params.transaction.mutations)\n\n return handlerResult\n }\n\n const wrappedOnDelete = async (params: DeleteMutationFnParams<any>) => {\n // Call the user handler BEFORE persisting changes (if provided)\n let handlerResult: any = {}\n if (config.onDelete) {\n handlerResult = (await config.onDelete(params)) ?? {}\n }\n\n // Always persist to storage\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Remove items\n params.transaction.mutations.forEach((mutation) => {\n // Use the engine's pre-computed key for consistency\n const key = mutation.key\n lastKnownData.delete(key)\n })\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm mutations through sync interface (moves from optimistic to synced state)\n // without reloading from storage\n sync.confirmOperationsSync(params.transaction.mutations)\n\n return handlerResult\n }\n\n // Extract standard Collection config properties\n const {\n storageKey: _storageKey,\n storage: _storage,\n storageEventApi: _storageEventApi,\n onInsert: _onInsert,\n onUpdate: _onUpdate,\n onDelete: _onDelete,\n id,\n ...restConfig\n } = config\n\n // Default id to a pattern based on storage key if not provided\n const collectionId = id ?? `local-collection:${config.storageKey}`\n\n /**\n * Accepts mutations from a transaction that belong to this collection and persists them to storage\n */\n const acceptMutations = (transaction: {\n mutations: Array<PendingMutation<Record<string, unknown>>>\n }) => {\n // Filter mutations that belong to this collection\n // Use collection ID for filtering if collection reference isn't available yet\n const collectionMutations = transaction.mutations.filter((m) => {\n // Try to match by collection reference first\n if (sync.collection && m.collection === sync.collection) {\n return true\n }\n // Fall back to matching by collection ID\n return m.collection.id === collectionId\n })\n\n if (collectionMutations.length === 0) {\n return\n }\n\n // Validate all mutations can be serialized before modifying storage\n for (const mutation of collectionMutations) {\n switch (mutation.type) {\n case `insert`:\n case `update`:\n validateJsonSerializable(parser, mutation.modified, mutation.type)\n break\n case `delete`:\n validateJsonSerializable(parser, mutation.original, mutation.type)\n break\n }\n }\n\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Apply each mutation\n for (const mutation of collectionMutations) {\n // Use the engine's pre-computed key to avoid key derivation issues\n const key = mutation.key\n\n switch (mutation.type) {\n case `insert`:\n case `update`: {\n const storedItem: StoredItem<Record<string, unknown>> = {\n versionKey: generateUuid(),\n data: mutation.modified,\n }\n lastKnownData.set(key, storedItem)\n break\n }\n case `delete`: {\n lastKnownData.delete(key)\n break\n }\n }\n }\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm the mutations in the collection to move them from optimistic to synced state\n // This writes them through the sync interface to make them \"synced\" instead of \"optimistic\"\n sync.confirmOperationsSync(collectionMutations)\n }\n\n return {\n ...restConfig,\n id: collectionId,\n sync,\n onInsert: wrappedOnInsert,\n onUpdate: wrappedOnUpdate,\n onDelete: wrappedOnDelete,\n utils: {\n clearStorage,\n getStorageSize,\n acceptMutations,\n },\n }\n}\n\n/**\n * Load data from storage and return as a Map\n * @param parser - The parser to use for deserializing the data\n * @param storageKey - The key used to store data in the storage API\n * @param storage - The storage API to load from (localStorage, sessionStorage, etc.)\n * @returns Map of stored items with version tracking, or empty Map if loading fails\n */\nfunction loadFromStorage<T extends object>(\n storageKey: string,\n storage: StorageApi,\n parser: Parser\n): Map<string | number, StoredItem<T>> {\n try {\n const rawData = storage.getItem(storageKey)\n if (!rawData) {\n return new Map()\n }\n\n const parsed = parser.parse(rawData)\n const dataMap = new Map<string | number, StoredItem<T>>()\n\n // Handle object format where keys map to StoredItem values\n if (\n typeof parsed === `object` &&\n parsed !== null &&\n !Array.isArray(parsed)\n ) {\n Object.entries(parsed).forEach(([key, value]) => {\n // Runtime check to ensure the value has the expected StoredItem structure\n if (\n value &&\n typeof value === `object` &&\n `versionKey` in value &&\n `data` in value\n ) {\n const storedItem = value as StoredItem<T>\n dataMap.set(key, storedItem)\n } else {\n throw new InvalidStorageDataFormatError(storageKey, key)\n }\n })\n } else {\n throw new InvalidStorageObjectFormatError(storageKey)\n }\n\n return dataMap\n } catch (error) {\n console.warn(\n `[LocalStorageCollection] Error loading data from storage key \"${storageKey}\":`,\n error\n )\n return new Map()\n }\n}\n\n/**\n * Internal function to create localStorage sync configuration\n * Creates a sync configuration that handles localStorage persistence and cross-tab synchronization\n * @param storageKey - The key used for storing data in localStorage\n * @param storage - The storage API to use (localStorage, sessionStorage, etc.)\n * @param storageEventApi - The event API for listening to storage changes\n * @param getKey - Function to extract the key from an item\n * @param lastKnownData - Map tracking the last known state for change detection\n * @returns Sync configuration with manual trigger capability\n */\nfunction createLocalStorageSync<T extends object>(\n storageKey: string,\n storage: StorageApi,\n storageEventApi: StorageEventApi,\n parser: Parser,\n _getKey: (item: T) => string | number,\n lastKnownData: Map<string | number, StoredItem<T>>\n): SyncConfig<T> & {\n manualTrigger?: () => void\n collection: any\n confirmOperationsSync: (mutations: Array<any>) => void\n} {\n let syncParams: Parameters<SyncConfig<T>[`sync`]>[0] | null = null\n let collection: any = null\n\n /**\n * Compare two Maps to find differences using version keys\n * @param oldData - The previous state of stored items\n * @param newData - The current state of stored items\n * @returns Array of changes with type, key, and value information\n */\n const findChanges = (\n oldData: Map<string | number, StoredItem<T>>,\n newData: Map<string | number, StoredItem<T>>\n ): Array<{\n type: `insert` | `update` | `delete`\n key: string | number\n value?: T\n }> => {\n const changes: Array<{\n type: `insert` | `update` | `delete`\n key: string | number\n value?: T\n }> = []\n\n // Check for deletions and updates\n oldData.forEach((oldStoredItem, key) => {\n const newStoredItem = newData.get(key)\n if (!newStoredItem) {\n changes.push({ type: `delete`, key, value: oldStoredItem.data })\n } else if (oldStoredItem.versionKey !== newStoredItem.versionKey) {\n changes.push({ type: `update`, key, value: newStoredItem.data })\n }\n })\n\n // Check for insertions\n newData.forEach((newStoredItem, key) => {\n if (!oldData.has(key)) {\n changes.push({ type: `insert`, key, value: newStoredItem.data })\n }\n })\n\n return changes\n }\n\n /**\n * Process storage changes and update collection\n * Loads new data from storage, compares with last known state, and applies changes\n */\n const processStorageChanges = () => {\n if (!syncParams) return\n\n const { begin, write, commit } = syncParams\n\n // Load the new data\n const newData = loadFromStorage<T>(storageKey, storage, parser)\n\n // Find the specific changes\n const changes = findChanges(lastKnownData, newData)\n\n if (changes.length > 0) {\n begin()\n changes.forEach(({ type, value }) => {\n if (value) {\n validateJsonSerializable(parser, value, type)\n write({ type, value })\n }\n })\n commit()\n\n // Update lastKnownData\n lastKnownData.clear()\n newData.forEach((storedItem, key) => {\n lastKnownData.set(key, storedItem)\n })\n }\n }\n\n const syncConfig: SyncConfig<T> & {\n manualTrigger?: () => void\n collection: any\n } = {\n sync: (params: Parameters<SyncConfig<T>[`sync`]>[0]) => {\n const { begin, write, commit, markReady } = params\n\n // Store sync params and collection for later use\n syncParams = params\n collection = params.collection\n\n // Initial load\n const initialData = loadFromStorage<T>(storageKey, storage, parser)\n if (initialData.size > 0) {\n begin()\n initialData.forEach((storedItem) => {\n validateJsonSerializable(parser, storedItem.data, `load`)\n write({ type: `insert`, value: storedItem.data })\n })\n commit()\n }\n\n // Update lastKnownData\n lastKnownData.clear()\n initialData.forEach((storedItem, key) => {\n lastKnownData.set(key, storedItem)\n })\n\n // Mark collection as ready after initial load\n markReady()\n\n // Listen for storage events from other tabs\n const handleStorageEvent = (event: StorageEvent) => {\n // Only respond to changes to our specific key and from our storage\n if (event.key !== storageKey || event.storageArea !== storage) {\n return\n }\n\n processStorageChanges()\n }\n\n // Add storage event listener for cross-tab sync\n storageEventApi.addEventListener(`storage`, handleStorageEvent)\n\n // Note: Cleanup is handled automatically by the collection when it's disposed\n },\n\n /**\n * Get sync metadata - returns storage key information\n * @returns Object containing storage key and storage type metadata\n */\n getSyncMetadata: () => ({\n storageKey,\n storageType:\n storage === (typeof window !== `undefined` ? window.localStorage : null)\n ? `localStorage`\n : `custom`,\n }),\n\n // Manual trigger function for local updates\n manualTrigger: processStorageChanges,\n\n // Collection instance reference\n collection,\n }\n\n /**\n * Confirms mutations by writing them through the sync interface\n * This moves mutations from optimistic to synced state\n * @param mutations - Array of mutation objects to confirm\n */\n const confirmOperationsSync = (mutations: Array<any>) => {\n if (!syncParams) {\n // Sync not initialized yet, mutations will be handled on next sync\n return\n }\n\n const { begin, write, commit } = syncParams\n\n // Write the mutations through sync to confirm them\n begin()\n mutations.forEach((mutation: any) => {\n write({\n type: mutation.type,\n value:\n mutation.type === `delete` ? mutation.original : mutation.modified,\n })\n })\n commit()\n }\n\n return {\n ...syncConfig,\n confirmOperationsSync,\n }\n}\n"],"names":["SerializationError","StorageKeyRequiredError","InvalidStorageDataFormatError","InvalidStorageObjectFormatError"],"mappings":"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"}
1
+ {"version":3,"file":"local-storage.cjs","sources":["../../src/local-storage.ts"],"sourcesContent":["import {\n InvalidStorageDataFormatError,\n InvalidStorageObjectFormatError,\n SerializationError,\n StorageKeyRequiredError,\n} from \"./errors\"\nimport type {\n BaseCollectionConfig,\n CollectionConfig,\n DeleteMutationFnParams,\n InferSchemaOutput,\n InsertMutationFnParams,\n PendingMutation,\n SyncConfig,\n UpdateMutationFnParams,\n UtilsRecord,\n} from \"./types\"\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\"\n\n/**\n * Storage API interface - subset of DOM Storage that we need\n */\nexport type StorageApi = Pick<Storage, `getItem` | `setItem` | `removeItem`>\n\n/**\n * Storage event API - subset of Window for 'storage' events only\n */\nexport type StorageEventApi = {\n addEventListener: (\n type: `storage`,\n listener: (event: StorageEvent) => void\n ) => void\n removeEventListener: (\n type: `storage`,\n listener: (event: StorageEvent) => void\n ) => void\n}\n\n/**\n * Internal storage format that includes version tracking\n */\ninterface StoredItem<T> {\n versionKey: string\n data: T\n}\n\nexport interface Parser {\n parse: (data: string) => unknown\n stringify: (data: unknown) => string\n}\n\n/**\n * Configuration interface for localStorage collection options\n * @template T - The type of items in the collection\n * @template TSchema - The schema type for validation\n * @template TKey - The type of the key returned by `getKey`\n */\nexport interface LocalStorageCollectionConfig<\n T extends object = object,\n TSchema extends StandardSchemaV1 = never,\n TKey extends string | number = string | number,\n> extends BaseCollectionConfig<T, TKey, TSchema> {\n /**\n * The key to use for storing the collection data in localStorage/sessionStorage\n */\n storageKey: string\n\n /**\n * Storage API to use (defaults to window.localStorage)\n * Can be any object that implements the Storage interface (e.g., sessionStorage)\n */\n storage?: StorageApi\n\n /**\n * Storage event API to use for cross-tab synchronization (defaults to window)\n * Can be any object that implements addEventListener/removeEventListener for storage events\n */\n storageEventApi?: StorageEventApi\n\n /**\n * Parser to use for serializing and deserializing data to and from storage\n * Defaults to JSON\n */\n parser?: Parser\n}\n\n/**\n * Type for the clear utility function\n */\nexport type ClearStorageFn = () => void\n\n/**\n * Type for the getStorageSize utility function\n */\nexport type GetStorageSizeFn = () => number\n\n/**\n * LocalStorage collection utilities type\n */\nexport interface LocalStorageCollectionUtils extends UtilsRecord {\n clearStorage: ClearStorageFn\n getStorageSize: GetStorageSizeFn\n /**\n * Accepts mutations from a transaction that belong to this collection and persists them to localStorage.\n * This should be called in your transaction's mutationFn to persist local-storage data.\n *\n * @param transaction - The transaction containing mutations to accept\n * @example\n * const localSettings = createCollection(localStorageCollectionOptions({...}))\n *\n * const tx = createTransaction({\n * mutationFn: async ({ transaction }) => {\n * // Make API call first\n * await api.save(...)\n * // Then persist local-storage mutations after success\n * localSettings.utils.acceptMutations(transaction)\n * }\n * })\n */\n acceptMutations: (transaction: {\n mutations: Array<PendingMutation<Record<string, unknown>>>\n }) => void\n}\n\n/**\n * Validates that a value can be JSON serialized\n * @param parser - The parser to use for serialization\n * @param value - The value to validate for JSON serialization\n * @param operation - The operation type being performed (for error messages)\n * @throws Error if the value cannot be JSON serialized\n */\nfunction validateJsonSerializable(\n parser: Parser,\n value: any,\n operation: string\n): void {\n try {\n parser.stringify(value)\n } catch (error) {\n throw new SerializationError(\n operation,\n error instanceof Error ? error.message : String(error)\n )\n }\n}\n\n/**\n * Generate a UUID for version tracking\n * @returns A unique identifier string for tracking data versions\n */\nfunction generateUuid(): string {\n return crypto.randomUUID()\n}\n\n/**\n * Creates an in-memory storage implementation that mimics the StorageApi interface\n * Used as a fallback when localStorage is not available (e.g., server-side rendering)\n * @returns An object implementing the StorageApi interface using an in-memory Map\n */\nfunction createInMemoryStorage(): StorageApi {\n const storage = new Map<string, string>()\n\n return {\n getItem(key: string): string | null {\n return storage.get(key) ?? null\n },\n setItem(key: string, value: string): void {\n storage.set(key, value)\n },\n removeItem(key: string): void {\n storage.delete(key)\n },\n }\n}\n\n/**\n * Creates a no-op storage event API for environments without window (e.g., server-side)\n * This provides the required interface but doesn't actually listen to any events\n * since cross-tab synchronization is not possible in server environments\n * @returns An object implementing the StorageEventApi interface with no-op methods\n */\nfunction createNoOpStorageEventApi(): StorageEventApi {\n return {\n addEventListener: () => {\n // No-op: cannot listen to storage events without window\n },\n removeEventListener: () => {\n // No-op: cannot remove listeners without window\n },\n }\n}\n\n/**\n * Creates localStorage collection options for use with a standard Collection\n *\n * This function creates a collection that persists data to localStorage/sessionStorage\n * and synchronizes changes across browser tabs using storage events.\n *\n * **Fallback Behavior:**\n *\n * When localStorage is not available (e.g., in server-side rendering environments),\n * this function automatically falls back to an in-memory storage implementation.\n * This prevents errors during module initialization and allows the collection to\n * work in any environment, though data will not persist across page reloads or\n * be shared across tabs when using the in-memory fallback.\n *\n * **Using with Manual Transactions:**\n *\n * For manual transactions, you must call `utils.acceptMutations()` in your transaction's `mutationFn`\n * to persist changes made during `tx.mutate()`. This is necessary because local-storage collections\n * don't participate in the standard mutation handler flow for manual transactions.\n *\n * @template TExplicit - The explicit type of items in the collection (highest priority)\n * @template TSchema - The schema type for validation and type inference (second priority)\n * @template TFallback - The fallback type if no explicit or schema type is provided\n * @param config - Configuration options for the localStorage collection\n * @returns Collection options with utilities including clearStorage, getStorageSize, and acceptMutations\n *\n * @example\n * // Basic localStorage collection\n * const collection = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'todos',\n * getKey: (item) => item.id,\n * })\n * )\n *\n * @example\n * // localStorage collection with custom storage\n * const collection = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'todos',\n * storage: window.sessionStorage, // Use sessionStorage instead\n * getKey: (item) => item.id,\n * })\n * )\n *\n * @example\n * // localStorage collection with mutation handlers\n * const collection = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'todos',\n * getKey: (item) => item.id,\n * onInsert: async ({ transaction }) => {\n * console.log('Item inserted:', transaction.mutations[0].modified)\n * },\n * })\n * )\n *\n * @example\n * // Using with manual transactions\n * const localSettings = createCollection(\n * localStorageCollectionOptions({\n * storageKey: 'user-settings',\n * getKey: (item) => item.id,\n * })\n * )\n *\n * const tx = createTransaction({\n * mutationFn: async ({ transaction }) => {\n * // Use settings data in API call\n * const settingsMutations = transaction.mutations.filter(m => m.collection === localSettings)\n * await api.updateUserProfile({ settings: settingsMutations[0]?.modified })\n *\n * // Persist local-storage mutations after API success\n * localSettings.utils.acceptMutations(transaction)\n * }\n * })\n *\n * tx.mutate(() => {\n * localSettings.insert({ id: 'theme', value: 'dark' })\n * apiCollection.insert({ id: 2, data: 'profile data' })\n * })\n *\n * await tx.commit()\n */\n\n// Overload for when schema is provided\nexport function localStorageCollectionOptions<\n T extends StandardSchemaV1,\n TKey extends string | number = string | number,\n>(\n config: LocalStorageCollectionConfig<InferSchemaOutput<T>, T, TKey> & {\n schema: T\n }\n): CollectionConfig<\n InferSchemaOutput<T>,\n TKey,\n T,\n LocalStorageCollectionUtils\n> & {\n id: string\n utils: LocalStorageCollectionUtils\n schema: T\n}\n\n// Overload for when no schema is provided\n// the type T needs to be passed explicitly unless it can be inferred from the getKey function in the config\nexport function localStorageCollectionOptions<\n T extends object,\n TKey extends string | number = string | number,\n>(\n config: LocalStorageCollectionConfig<T, never, TKey> & {\n schema?: never // prohibit schema\n }\n): CollectionConfig<T, TKey, never, LocalStorageCollectionUtils> & {\n id: string\n utils: LocalStorageCollectionUtils\n schema?: never // no schema in the result\n}\n\nexport function localStorageCollectionOptions(\n config: LocalStorageCollectionConfig<any, any, string | number>\n): Omit<\n CollectionConfig<any, string | number, any, LocalStorageCollectionUtils>,\n `id`\n> & {\n id: string\n utils: LocalStorageCollectionUtils\n schema?: StandardSchemaV1\n} {\n // Validate required parameters\n if (!config.storageKey) {\n throw new StorageKeyRequiredError()\n }\n\n // Default to window.localStorage if no storage is provided\n // Fall back to in-memory storage if localStorage is not available (e.g., server-side rendering)\n const storage =\n config.storage ||\n (typeof window !== `undefined` ? window.localStorage : null) ||\n createInMemoryStorage()\n\n // Default to window for storage events if not provided\n // Fall back to no-op storage event API if window is not available (e.g., server-side rendering)\n const storageEventApi =\n config.storageEventApi ||\n (typeof window !== `undefined` ? window : null) ||\n createNoOpStorageEventApi()\n\n // Default to JSON parser if no parser is provided\n const parser = config.parser || JSON\n\n // Track the last known state to detect changes\n const lastKnownData = new Map<string | number, StoredItem<any>>()\n\n // Create the sync configuration\n const sync = createLocalStorageSync<any>(\n config.storageKey,\n storage,\n storageEventApi,\n parser,\n config.getKey,\n lastKnownData\n )\n\n /**\n * Save data to storage\n * @param dataMap - Map of items with version tracking to save to storage\n */\n const saveToStorage = (\n dataMap: Map<string | number, StoredItem<any>>\n ): void => {\n try {\n // Convert Map to object format for storage\n const objectData: Record<string, StoredItem<any>> = {}\n dataMap.forEach((storedItem, key) => {\n objectData[String(key)] = storedItem\n })\n const serialized = parser.stringify(objectData)\n storage.setItem(config.storageKey, serialized)\n } catch (error) {\n console.error(\n `[LocalStorageCollection] Error saving data to storage key \"${config.storageKey}\":`,\n error\n )\n throw error\n }\n }\n\n /**\n * Removes all collection data from the configured storage\n */\n const clearStorage: ClearStorageFn = (): void => {\n storage.removeItem(config.storageKey)\n }\n\n /**\n * Get the size of the stored data in bytes (approximate)\n * @returns The approximate size in bytes of the stored collection data\n */\n const getStorageSize: GetStorageSizeFn = (): number => {\n const data = storage.getItem(config.storageKey)\n return data ? new Blob([data]).size : 0\n }\n\n /*\n * Create wrapper handlers for direct persistence operations that perform actual storage operations\n * Wraps the user's onInsert handler to also save changes to localStorage\n */\n const wrappedOnInsert = async (params: InsertMutationFnParams<any>) => {\n // Validate that all values in the transaction can be JSON serialized\n params.transaction.mutations.forEach((mutation) => {\n validateJsonSerializable(parser, mutation.modified, `insert`)\n })\n\n // Call the user handler BEFORE persisting changes (if provided)\n let handlerResult: any = {}\n if (config.onInsert) {\n handlerResult = (await config.onInsert(params)) ?? {}\n }\n\n // Always persist to storage\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Add new items with version keys\n params.transaction.mutations.forEach((mutation) => {\n // Use the engine's pre-computed key for consistency\n const key = mutation.key\n const storedItem: StoredItem<any> = {\n versionKey: generateUuid(),\n data: mutation.modified,\n }\n lastKnownData.set(key, storedItem)\n })\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm mutations through sync interface (moves from optimistic to synced state)\n // without reloading from storage\n sync.confirmOperationsSync(params.transaction.mutations)\n\n return handlerResult\n }\n\n const wrappedOnUpdate = async (params: UpdateMutationFnParams<any>) => {\n // Validate that all values in the transaction can be JSON serialized\n params.transaction.mutations.forEach((mutation) => {\n validateJsonSerializable(parser, mutation.modified, `update`)\n })\n\n // Call the user handler BEFORE persisting changes (if provided)\n let handlerResult: any = {}\n if (config.onUpdate) {\n handlerResult = (await config.onUpdate(params)) ?? {}\n }\n\n // Always persist to storage\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Update items with new version keys\n params.transaction.mutations.forEach((mutation) => {\n // Use the engine's pre-computed key for consistency\n const key = mutation.key\n const storedItem: StoredItem<any> = {\n versionKey: generateUuid(),\n data: mutation.modified,\n }\n lastKnownData.set(key, storedItem)\n })\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm mutations through sync interface (moves from optimistic to synced state)\n // without reloading from storage\n sync.confirmOperationsSync(params.transaction.mutations)\n\n return handlerResult\n }\n\n const wrappedOnDelete = async (params: DeleteMutationFnParams<any>) => {\n // Call the user handler BEFORE persisting changes (if provided)\n let handlerResult: any = {}\n if (config.onDelete) {\n handlerResult = (await config.onDelete(params)) ?? {}\n }\n\n // Always persist to storage\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Remove items\n params.transaction.mutations.forEach((mutation) => {\n // Use the engine's pre-computed key for consistency\n const key = mutation.key\n lastKnownData.delete(key)\n })\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm mutations through sync interface (moves from optimistic to synced state)\n // without reloading from storage\n sync.confirmOperationsSync(params.transaction.mutations)\n\n return handlerResult\n }\n\n // Extract standard Collection config properties\n const {\n storageKey: _storageKey,\n storage: _storage,\n storageEventApi: _storageEventApi,\n onInsert: _onInsert,\n onUpdate: _onUpdate,\n onDelete: _onDelete,\n id,\n ...restConfig\n } = config\n\n // Default id to a pattern based on storage key if not provided\n const collectionId = id ?? `local-collection:${config.storageKey}`\n\n /**\n * Accepts mutations from a transaction that belong to this collection and persists them to storage\n */\n const acceptMutations = (transaction: {\n mutations: Array<PendingMutation<Record<string, unknown>>>\n }) => {\n // Filter mutations that belong to this collection\n // Use collection ID for filtering if collection reference isn't available yet\n const collectionMutations = transaction.mutations.filter((m) => {\n // Try to match by collection reference first\n if (sync.collection && m.collection === sync.collection) {\n return true\n }\n // Fall back to matching by collection ID\n return m.collection.id === collectionId\n })\n\n if (collectionMutations.length === 0) {\n return\n }\n\n // Validate all mutations can be serialized before modifying storage\n for (const mutation of collectionMutations) {\n switch (mutation.type) {\n case `insert`:\n case `update`:\n validateJsonSerializable(parser, mutation.modified, mutation.type)\n break\n case `delete`:\n validateJsonSerializable(parser, mutation.original, mutation.type)\n break\n }\n }\n\n // Use lastKnownData (in-memory cache) instead of reading from storage\n // Apply each mutation\n for (const mutation of collectionMutations) {\n // Use the engine's pre-computed key to avoid key derivation issues\n const key = mutation.key\n\n switch (mutation.type) {\n case `insert`:\n case `update`: {\n const storedItem: StoredItem<Record<string, unknown>> = {\n versionKey: generateUuid(),\n data: mutation.modified,\n }\n lastKnownData.set(key, storedItem)\n break\n }\n case `delete`: {\n lastKnownData.delete(key)\n break\n }\n }\n }\n\n // Save to storage\n saveToStorage(lastKnownData)\n\n // Confirm the mutations in the collection to move them from optimistic to synced state\n // This writes them through the sync interface to make them \"synced\" instead of \"optimistic\"\n sync.confirmOperationsSync(collectionMutations)\n }\n\n return {\n ...restConfig,\n id: collectionId,\n sync,\n onInsert: wrappedOnInsert,\n onUpdate: wrappedOnUpdate,\n onDelete: wrappedOnDelete,\n utils: {\n clearStorage,\n getStorageSize,\n acceptMutations,\n },\n }\n}\n\n/**\n * Load data from storage and return as a Map\n * @param parser - The parser to use for deserializing the data\n * @param storageKey - The key used to store data in the storage API\n * @param storage - The storage API to load from (localStorage, sessionStorage, etc.)\n * @returns Map of stored items with version tracking, or empty Map if loading fails\n */\nfunction loadFromStorage<T extends object>(\n storageKey: string,\n storage: StorageApi,\n parser: Parser\n): Map<string | number, StoredItem<T>> {\n try {\n const rawData = storage.getItem(storageKey)\n if (!rawData) {\n return new Map()\n }\n\n const parsed = parser.parse(rawData)\n const dataMap = new Map<string | number, StoredItem<T>>()\n\n // Handle object format where keys map to StoredItem values\n if (\n typeof parsed === `object` &&\n parsed !== null &&\n !Array.isArray(parsed)\n ) {\n Object.entries(parsed).forEach(([key, value]) => {\n // Runtime check to ensure the value has the expected StoredItem structure\n if (\n value &&\n typeof value === `object` &&\n `versionKey` in value &&\n `data` in value\n ) {\n const storedItem = value as StoredItem<T>\n dataMap.set(key, storedItem)\n } else {\n throw new InvalidStorageDataFormatError(storageKey, key)\n }\n })\n } else {\n throw new InvalidStorageObjectFormatError(storageKey)\n }\n\n return dataMap\n } catch (error) {\n console.warn(\n `[LocalStorageCollection] Error loading data from storage key \"${storageKey}\":`,\n error\n )\n return new Map()\n }\n}\n\n/**\n * Internal function to create localStorage sync configuration\n * Creates a sync configuration that handles localStorage persistence and cross-tab synchronization\n * @param storageKey - The key used for storing data in localStorage\n * @param storage - The storage API to use (localStorage, sessionStorage, etc.)\n * @param storageEventApi - The event API for listening to storage changes\n * @param getKey - Function to extract the key from an item\n * @param lastKnownData - Map tracking the last known state for change detection\n * @returns Sync configuration with manual trigger capability\n */\nfunction createLocalStorageSync<T extends object>(\n storageKey: string,\n storage: StorageApi,\n storageEventApi: StorageEventApi,\n parser: Parser,\n _getKey: (item: T) => string | number,\n lastKnownData: Map<string | number, StoredItem<T>>\n): SyncConfig<T> & {\n manualTrigger?: () => void\n collection: any\n confirmOperationsSync: (mutations: Array<any>) => void\n} {\n let syncParams: Parameters<SyncConfig<T>[`sync`]>[0] | null = null\n let collection: any = null\n\n /**\n * Compare two Maps to find differences using version keys\n * @param oldData - The previous state of stored items\n * @param newData - The current state of stored items\n * @returns Array of changes with type, key, and value information\n */\n const findChanges = (\n oldData: Map<string | number, StoredItem<T>>,\n newData: Map<string | number, StoredItem<T>>\n ): Array<{\n type: `insert` | `update` | `delete`\n key: string | number\n value?: T\n }> => {\n const changes: Array<{\n type: `insert` | `update` | `delete`\n key: string | number\n value?: T\n }> = []\n\n // Check for deletions and updates\n oldData.forEach((oldStoredItem, key) => {\n const newStoredItem = newData.get(key)\n if (!newStoredItem) {\n changes.push({ type: `delete`, key, value: oldStoredItem.data })\n } else if (oldStoredItem.versionKey !== newStoredItem.versionKey) {\n changes.push({ type: `update`, key, value: newStoredItem.data })\n }\n })\n\n // Check for insertions\n newData.forEach((newStoredItem, key) => {\n if (!oldData.has(key)) {\n changes.push({ type: `insert`, key, value: newStoredItem.data })\n }\n })\n\n return changes\n }\n\n /**\n * Process storage changes and update collection\n * Loads new data from storage, compares with last known state, and applies changes\n */\n const processStorageChanges = () => {\n if (!syncParams) return\n\n const { begin, write, commit } = syncParams\n\n // Load the new data\n const newData = loadFromStorage<T>(storageKey, storage, parser)\n\n // Find the specific changes\n const changes = findChanges(lastKnownData, newData)\n\n if (changes.length > 0) {\n begin()\n changes.forEach(({ type, value }) => {\n if (value) {\n validateJsonSerializable(parser, value, type)\n write({ type, value })\n }\n })\n commit()\n\n // Update lastKnownData\n lastKnownData.clear()\n newData.forEach((storedItem, key) => {\n lastKnownData.set(key, storedItem)\n })\n }\n }\n\n const syncConfig: SyncConfig<T> & {\n manualTrigger?: () => void\n collection: any\n } = {\n sync: (params: Parameters<SyncConfig<T>[`sync`]>[0]) => {\n const { begin, write, commit, markReady } = params\n\n // Store sync params and collection for later use\n syncParams = params\n collection = params.collection\n\n // Initial load\n const initialData = loadFromStorage<T>(storageKey, storage, parser)\n if (initialData.size > 0) {\n begin()\n initialData.forEach((storedItem) => {\n validateJsonSerializable(parser, storedItem.data, `load`)\n write({ type: `insert`, value: storedItem.data })\n })\n commit()\n }\n\n // Update lastKnownData\n lastKnownData.clear()\n initialData.forEach((storedItem, key) => {\n lastKnownData.set(key, storedItem)\n })\n\n // Mark collection as ready after initial load\n markReady()\n\n // Listen for storage events from other tabs\n const handleStorageEvent = (event: StorageEvent) => {\n // Only respond to changes to our specific key and from our storage\n if (event.key !== storageKey || event.storageArea !== storage) {\n return\n }\n\n processStorageChanges()\n }\n\n // Add storage event listener for cross-tab sync\n storageEventApi.addEventListener(`storage`, handleStorageEvent)\n\n // Note: Cleanup is handled automatically by the collection when it's disposed\n },\n\n /**\n * Get sync metadata - returns storage key information\n * @returns Object containing storage key and storage type metadata\n */\n getSyncMetadata: () => ({\n storageKey,\n storageType:\n storage === (typeof window !== `undefined` ? window.localStorage : null)\n ? `localStorage`\n : `custom`,\n }),\n\n // Manual trigger function for local updates\n manualTrigger: processStorageChanges,\n\n // Collection instance reference\n collection,\n }\n\n /**\n * Confirms mutations by writing them through the sync interface\n * This moves mutations from optimistic to synced state\n * @param mutations - Array of mutation objects to confirm\n */\n const confirmOperationsSync = (mutations: Array<any>) => {\n if (!syncParams) {\n // Sync not initialized yet, mutations will be handled on next sync\n return\n }\n\n const { begin, write, commit } = syncParams\n\n // Write the mutations through sync to confirm them\n begin()\n mutations.forEach((mutation: any) => {\n write({\n type: mutation.type,\n value:\n mutation.type === `delete` ? mutation.original : mutation.modified,\n })\n })\n commit()\n }\n\n return {\n ...syncConfig,\n confirmOperationsSync,\n }\n}\n"],"names":["SerializationError","StorageKeyRequiredError","InvalidStorageDataFormatError","InvalidStorageObjectFormatError"],"mappings":";;;AAmIA,SAAS,yBACP,QACA,OACA,WACM;AACN,MAAI;AACF,WAAO,UAAU,KAAK;AAAA,EACxB,SAAS,OAAO;AACd,UAAM,IAAIA,OAAAA;AAAAA,MACR;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAAA;AAAA,EAEzD;AACF;AAMA,SAAS,eAAuB;AAC9B,SAAO,OAAO,WAAA;AAChB;AAOA,SAAS,wBAAoC;AAC3C,QAAM,8BAAc,IAAA;AAEpB,SAAO;AAAA,IACL,QAAQ,KAA4B;AAClC,aAAO,QAAQ,IAAI,GAAG,KAAK;AAAA,IAC7B;AAAA,IACA,QAAQ,KAAa,OAAqB;AACxC,cAAQ,IAAI,KAAK,KAAK;AAAA,IACxB;AAAA,IACA,WAAW,KAAmB;AAC5B,cAAQ,OAAO,GAAG;AAAA,IACpB;AAAA,EAAA;AAEJ;AAQA,SAAS,4BAA6C;AACpD,SAAO;AAAA,IACL,kBAAkB,MAAM;AAAA,IAExB;AAAA,IACA,qBAAqB,MAAM;AAAA,IAE3B;AAAA,EAAA;AAEJ;AAyHO,SAAS,8BACd,QAQA;AAEA,MAAI,CAAC,OAAO,YAAY;AACtB,UAAM,IAAIC,OAAAA,wBAAA;AAAA,EACZ;AAIA,QAAM,UACJ,OAAO,YACN,OAAO,WAAW,cAAc,OAAO,eAAe,SACvD,sBAAA;AAIF,QAAM,kBACJ,OAAO,oBACN,OAAO,WAAW,cAAc,SAAS,SAC1C,0BAAA;AAGF,QAAM,SAAS,OAAO,UAAU;AAGhC,QAAM,oCAAoB,IAAA;AAG1B,QAAM,OAAO;AAAA,IACX,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EAAA;AAOF,QAAM,gBAAgB,CACpB,YACS;AACT,QAAI;AAEF,YAAM,aAA8C,CAAA;AACpD,cAAQ,QAAQ,CAAC,YAAY,QAAQ;AACnC,mBAAW,OAAO,GAAG,CAAC,IAAI;AAAA,MAC5B,CAAC;AACD,YAAM,aAAa,OAAO,UAAU,UAAU;AAC9C,cAAQ,QAAQ,OAAO,YAAY,UAAU;AAAA,IAC/C,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,8DAA8D,OAAO,UAAU;AAAA,QAC/E;AAAA,MAAA;AAEF,YAAM;AAAA,IACR;AAAA,EACF;AAKA,QAAM,eAA+B,MAAY;AAC/C,YAAQ,WAAW,OAAO,UAAU;AAAA,EACtC;AAMA,QAAM,iBAAmC,MAAc;AACrD,UAAM,OAAO,QAAQ,QAAQ,OAAO,UAAU;AAC9C,WAAO,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO;AAAA,EACxC;AAMA,QAAM,kBAAkB,OAAO,WAAwC;AAErE,WAAO,YAAY,UAAU,QAAQ,CAAC,aAAa;AACjD,+BAAyB,QAAQ,SAAS,UAAU,QAAQ;AAAA,IAC9D,CAAC;AAGD,QAAI,gBAAqB,CAAA;AACzB,QAAI,OAAO,UAAU;AACnB,sBAAiB,MAAM,OAAO,SAAS,MAAM,KAAM,CAAA;AAAA,IACrD;AAKA,WAAO,YAAY,UAAU,QAAQ,CAAC,aAAa;AAEjD,YAAM,MAAM,SAAS;AACrB,YAAM,aAA8B;AAAA,QAClC,YAAY,aAAA;AAAA,QACZ,MAAM,SAAS;AAAA,MAAA;AAEjB,oBAAc,IAAI,KAAK,UAAU;AAAA,IACnC,CAAC;AAGD,kBAAc,aAAa;AAI3B,SAAK,sBAAsB,OAAO,YAAY,SAAS;AAEvD,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,OAAO,WAAwC;AAErE,WAAO,YAAY,UAAU,QAAQ,CAAC,aAAa;AACjD,+BAAyB,QAAQ,SAAS,UAAU,QAAQ;AAAA,IAC9D,CAAC;AAGD,QAAI,gBAAqB,CAAA;AACzB,QAAI,OAAO,UAAU;AACnB,sBAAiB,MAAM,OAAO,SAAS,MAAM,KAAM,CAAA;AAAA,IACrD;AAKA,WAAO,YAAY,UAAU,QAAQ,CAAC,aAAa;AAEjD,YAAM,MAAM,SAAS;AACrB,YAAM,aAA8B;AAAA,QAClC,YAAY,aAAA;AAAA,QACZ,MAAM,SAAS;AAAA,MAAA;AAEjB,oBAAc,IAAI,KAAK,UAAU;AAAA,IACnC,CAAC;AAGD,kBAAc,aAAa;AAI3B,SAAK,sBAAsB,OAAO,YAAY,SAAS;AAEvD,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,OAAO,WAAwC;AAErE,QAAI,gBAAqB,CAAA;AACzB,QAAI,OAAO,UAAU;AACnB,sBAAiB,MAAM,OAAO,SAAS,MAAM,KAAM,CAAA;AAAA,IACrD;AAKA,WAAO,YAAY,UAAU,QAAQ,CAAC,aAAa;AAEjD,YAAM,MAAM,SAAS;AACrB,oBAAc,OAAO,GAAG;AAAA,IAC1B,CAAC;AAGD,kBAAc,aAAa;AAI3B,SAAK,sBAAsB,OAAO,YAAY,SAAS;AAEvD,WAAO;AAAA,EACT;AAGA,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AAGJ,QAAM,eAAe,MAAM,oBAAoB,OAAO,UAAU;AAKhE,QAAM,kBAAkB,CAAC,gBAEnB;AAGJ,UAAM,sBAAsB,YAAY,UAAU,OAAO,CAAC,MAAM;AAE9D,UAAI,KAAK,cAAc,EAAE,eAAe,KAAK,YAAY;AACvD,eAAO;AAAA,MACT;AAEA,aAAO,EAAE,WAAW,OAAO;AAAA,IAC7B,CAAC;AAED,QAAI,oBAAoB,WAAW,GAAG;AACpC;AAAA,IACF;AAGA,eAAW,YAAY,qBAAqB;AAC1C,cAAQ,SAAS,MAAA;AAAA,QACf,KAAK;AAAA,QACL,KAAK;AACH,mCAAyB,QAAQ,SAAS,UAAU,SAAS,IAAI;AACjE;AAAA,QACF,KAAK;AACH,mCAAyB,QAAQ,SAAS,UAAU,SAAS,IAAI;AACjE;AAAA,MAAA;AAAA,IAEN;AAIA,eAAW,YAAY,qBAAqB;AAE1C,YAAM,MAAM,SAAS;AAErB,cAAQ,SAAS,MAAA;AAAA,QACf,KAAK;AAAA,QACL,KAAK,UAAU;AACb,gBAAM,aAAkD;AAAA,YACtD,YAAY,aAAA;AAAA,YACZ,MAAM,SAAS;AAAA,UAAA;AAEjB,wBAAc,IAAI,KAAK,UAAU;AACjC;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,wBAAc,OAAO,GAAG;AACxB;AAAA,QACF;AAAA,MAAA;AAAA,IAEJ;AAGA,kBAAc,aAAa;AAI3B,SAAK,sBAAsB,mBAAmB;AAAA,EAChD;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,IAAI;AAAA,IACJ;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAEJ;AASA,SAAS,gBACP,YACA,SACA,QACqC;AACrC,MAAI;AACF,UAAM,UAAU,QAAQ,QAAQ,UAAU;AAC1C,QAAI,CAAC,SAAS;AACZ,iCAAW,IAAA;AAAA,IACb;AAEA,UAAM,SAAS,OAAO,MAAM,OAAO;AACnC,UAAM,8BAAc,IAAA;AAGpB,QACE,OAAO,WAAW,YAClB,WAAW,QACX,CAAC,MAAM,QAAQ,MAAM,GACrB;AACA,aAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAE/C,YACE,SACA,OAAO,UAAU,YACjB,gBAAgB,SAChB,UAAU,OACV;AACA,gBAAM,aAAa;AACnB,kBAAQ,IAAI,KAAK,UAAU;AAAA,QAC7B,OAAO;AACL,gBAAM,IAAIC,OAAAA,8BAA8B,YAAY,GAAG;AAAA,QACzD;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,YAAM,IAAIC,OAAAA,gCAAgC,UAAU;AAAA,IACtD;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ;AAAA,MACN,iEAAiE,UAAU;AAAA,MAC3E;AAAA,IAAA;AAEF,+BAAW,IAAA;AAAA,EACb;AACF;AAYA,SAAS,uBACP,YACA,SACA,iBACA,QACA,SACA,eAKA;AACA,MAAI,aAA0D;AAC9D,MAAI,aAAkB;AAQtB,QAAM,cAAc,CAClB,SACA,YAKI;AACJ,UAAM,UAID,CAAA;AAGL,YAAQ,QAAQ,CAAC,eAAe,QAAQ;AACtC,YAAM,gBAAgB,QAAQ,IAAI,GAAG;AACrC,UAAI,CAAC,eAAe;AAClB,gBAAQ,KAAK,EAAE,MAAM,UAAU,KAAK,OAAO,cAAc,MAAM;AAAA,MACjE,WAAW,cAAc,eAAe,cAAc,YAAY;AAChE,gBAAQ,KAAK,EAAE,MAAM,UAAU,KAAK,OAAO,cAAc,MAAM;AAAA,MACjE;AAAA,IACF,CAAC;AAGD,YAAQ,QAAQ,CAAC,eAAe,QAAQ;AACtC,UAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,gBAAQ,KAAK,EAAE,MAAM,UAAU,KAAK,OAAO,cAAc,MAAM;AAAA,MACjE;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAMA,QAAM,wBAAwB,MAAM;AAClC,QAAI,CAAC,WAAY;AAEjB,UAAM,EAAE,OAAO,OAAO,OAAA,IAAW;AAGjC,UAAM,UAAU,gBAAmB,YAAY,SAAS,MAAM;AAG9D,UAAM,UAAU,YAAY,eAAe,OAAO;AAElD,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAA;AACA,cAAQ,QAAQ,CAAC,EAAE,MAAM,YAAY;AACnC,YAAI,OAAO;AACT,mCAAyB,QAAQ,OAAO,IAAI;AAC5C,gBAAM,EAAE,MAAM,OAAO;AAAA,QACvB;AAAA,MACF,CAAC;AACD,aAAA;AAGA,oBAAc,MAAA;AACd,cAAQ,QAAQ,CAAC,YAAY,QAAQ;AACnC,sBAAc,IAAI,KAAK,UAAU;AAAA,MACnC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,aAGF;AAAA,IACF,MAAM,CAAC,WAAiD;AACtD,YAAM,EAAE,OAAO,OAAO,QAAQ,cAAc;AAG5C,mBAAa;AACb,mBAAa,OAAO;AAGpB,YAAM,cAAc,gBAAmB,YAAY,SAAS,MAAM;AAClE,UAAI,YAAY,OAAO,GAAG;AACxB,cAAA;AACA,oBAAY,QAAQ,CAAC,eAAe;AAClC,mCAAyB,QAAQ,WAAW,MAAM,MAAM;AACxD,gBAAM,EAAE,MAAM,UAAU,OAAO,WAAW,MAAM;AAAA,QAClD,CAAC;AACD,eAAA;AAAA,MACF;AAGA,oBAAc,MAAA;AACd,kBAAY,QAAQ,CAAC,YAAY,QAAQ;AACvC,sBAAc,IAAI,KAAK,UAAU;AAAA,MACnC,CAAC;AAGD,gBAAA;AAGA,YAAM,qBAAqB,CAAC,UAAwB;AAElD,YAAI,MAAM,QAAQ,cAAc,MAAM,gBAAgB,SAAS;AAC7D;AAAA,QACF;AAEA,8BAAA;AAAA,MACF;AAGA,sBAAgB,iBAAiB,WAAW,kBAAkB;AAAA,IAGhE;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,iBAAiB,OAAO;AAAA,MACtB;AAAA,MACA,aACE,aAAa,OAAO,WAAW,cAAc,OAAO,eAAe,QAC/D,iBACA;AAAA,IAAA;AAAA;AAAA,IAIR,eAAe;AAAA;AAAA,IAGf;AAAA,EAAA;AAQF,QAAM,wBAAwB,CAAC,cAA0B;AACvD,QAAI,CAAC,YAAY;AAEf;AAAA,IACF;AAEA,UAAM,EAAE,OAAO,OAAO,OAAA,IAAW;AAGjC,UAAA;AACA,cAAU,QAAQ,CAAC,aAAkB;AACnC,YAAM;AAAA,QACJ,MAAM,SAAS;AAAA,QACf,OACE,SAAS,SAAS,WAAW,SAAS,WAAW,SAAS;AAAA,MAAA,CAC7D;AAAA,IACH,CAAC;AACD,WAAA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,EAAA;AAEJ;;"}
@@ -163,14 +163,14 @@ export interface LocalStorageCollectionUtils extends UtilsRecord {
163
163
  */
164
164
  export declare function localStorageCollectionOptions<T extends StandardSchemaV1, TKey extends string | number = string | number>(config: LocalStorageCollectionConfig<InferSchemaOutput<T>, T, TKey> & {
165
165
  schema: T;
166
- }): CollectionConfig<InferSchemaOutput<T>, TKey, T> & {
166
+ }): CollectionConfig<InferSchemaOutput<T>, TKey, T, LocalStorageCollectionUtils> & {
167
167
  id: string;
168
168
  utils: LocalStorageCollectionUtils;
169
169
  schema: T;
170
170
  };
171
171
  export declare function localStorageCollectionOptions<T extends object, TKey extends string | number = string | number>(config: LocalStorageCollectionConfig<T, never, TKey> & {
172
172
  schema?: never;
173
- }): CollectionConfig<T, TKey> & {
173
+ }): CollectionConfig<T, TKey, never, LocalStorageCollectionUtils> & {
174
174
  id: string;
175
175
  utils: LocalStorageCollectionUtils;
176
176
  schema?: never;
@@ -101,6 +101,39 @@ const comparisonFunctions = [
101
101
  `like`,
102
102
  `ilike`
103
103
  ];
104
+ const operators = [
105
+ // Comparison operators
106
+ `eq`,
107
+ `gt`,
108
+ `gte`,
109
+ `lt`,
110
+ `lte`,
111
+ `in`,
112
+ `like`,
113
+ `ilike`,
114
+ // Logical operators
115
+ `and`,
116
+ `or`,
117
+ `not`,
118
+ // Null checking
119
+ `isNull`,
120
+ `isUndefined`,
121
+ // String functions
122
+ `upper`,
123
+ `lower`,
124
+ `length`,
125
+ `concat`,
126
+ // Numeric functions
127
+ `add`,
128
+ // Utility functions
129
+ `coalesce`,
130
+ // Aggregate functions
131
+ `count`,
132
+ `avg`,
133
+ `sum`,
134
+ `min`,
135
+ `max`
136
+ ];
104
137
  exports.add = add;
105
138
  exports.and = and;
106
139
  exports.avg = avg;
@@ -123,6 +156,7 @@ exports.lte = lte;
123
156
  exports.max = max;
124
157
  exports.min = min;
125
158
  exports.not = not;
159
+ exports.operators = operators;
126
160
  exports.or = or;
127
161
  exports.sum = sum;
128
162
  exports.upper = upper;
@@ -1 +1 @@
1
- {"version":3,"file":"functions.cjs","sources":["../../../../src/query/builder/functions.ts"],"sourcesContent":["import { Aggregate, Func } from \"../ir\"\nimport { toExpression } from \"./ref-proxy.js\"\nimport type { BasicExpression } from \"../ir\"\nimport type { RefProxy } from \"./ref-proxy.js\"\nimport type { RefLeaf } from \"./types.js\"\n\ntype StringRef =\n | RefLeaf<string>\n | RefLeaf<string | null>\n | RefLeaf<string | undefined>\ntype StringRefProxy =\n | RefProxy<string>\n | RefProxy<string | null>\n | RefProxy<string | undefined>\ntype StringBasicExpression =\n | BasicExpression<string>\n | BasicExpression<string | null>\n | BasicExpression<string | undefined>\ntype StringLike =\n | StringRef\n | StringRefProxy\n | StringBasicExpression\n | string\n | null\n | undefined\n\ntype ComparisonOperand<T> =\n | RefProxy<T>\n | RefLeaf<T>\n | T\n | BasicExpression<T>\n | undefined\n | null\ntype ComparisonOperandPrimitive<T extends string | number | boolean> =\n | T\n | BasicExpression<T>\n | undefined\n | null\n\n// Helper type for any expression-like value\ntype ExpressionLike = BasicExpression | RefProxy<any> | RefLeaf<any> | any\n\n// Helper type to extract the underlying type from various expression types\ntype ExtractType<T> =\n T extends RefProxy<infer U>\n ? U\n : T extends RefLeaf<infer U>\n ? U\n : T extends BasicExpression<infer U>\n ? U\n : T\n\n// Helper type to determine aggregate return type based on input nullability\ntype AggregateReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends number | undefined | null | Date | bigint\n ? Aggregate<U>\n : Aggregate<number | undefined | null | Date | bigint>\n : Aggregate<number | undefined | null | Date | bigint>\n\n// Helper type to determine string function return type based on input nullability\ntype StringFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | undefined | null\n ? BasicExpression<U>\n : BasicExpression<string | undefined | null>\n : BasicExpression<string | undefined | null>\n\n// Helper type to determine numeric function return type based on input nullability\n// This handles string, array, and number inputs for functions like length()\ntype NumericFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | Array<any> | undefined | null | number\n ? BasicExpression<MapToNumber<U>>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Transform string/array types to number while preserving nullability\ntype MapToNumber<T> = T extends string | Array<any>\n ? number\n : T extends undefined\n ? undefined\n : T extends null\n ? null\n : T\n\n// Helper type for binary numeric operations (combines nullability of both operands)\ntype BinaryNumericReturnType<T1, T2> =\n ExtractType<T1> extends infer U1\n ? ExtractType<T2> extends infer U2\n ? U1 extends number\n ? U2 extends number\n ? BasicExpression<number>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : U2 extends number | null\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : U1 extends number | undefined\n ? U2 extends number\n ? BasicExpression<number | undefined>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : BasicExpression<number | undefined | null>\n : U1 extends number | null\n ? U2 extends number\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Operators\n\nexport function eq<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function eq<T extends string | number | boolean>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function eq(left: any, right: any): BasicExpression<boolean> {\n return new Func(`eq`, [toExpression(left), toExpression(right)])\n}\n\nexport function gt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function gt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gt`, [toExpression(left), toExpression(right)])\n}\n\nexport function gte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function gte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gte`, [toExpression(left), toExpression(right)])\n}\n\nexport function lt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function lt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lt`, [toExpression(left), toExpression(right)])\n}\n\nexport function lte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function lte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lte`, [toExpression(left), toExpression(right)])\n}\n\n// Overloads for and() - support 2 or more arguments\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `and`,\n allArgs.map((arg) => toExpression(arg))\n )\n}\n\n// Overloads for or() - support 2 or more arguments\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `or`,\n allArgs.map((arg) => toExpression(arg))\n )\n}\n\nexport function not(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`not`, [toExpression(value)])\n}\n\n// Null/undefined checking functions\nexport function isUndefined(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isUndefined`, [toExpression(value)])\n}\n\nexport function isNull(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isNull`, [toExpression(value)])\n}\n\nexport function inArray(\n value: ExpressionLike,\n array: ExpressionLike\n): BasicExpression<boolean> {\n return new Func(`in`, [toExpression(value), toExpression(array)])\n}\n\nexport function like(\n left: StringLike,\n right: StringLike\n): BasicExpression<boolean>\nexport function like(left: any, right: any): BasicExpression<boolean> {\n return new Func(`like`, [toExpression(left), toExpression(right)])\n}\n\nexport function ilike(\n left: StringLike,\n right: StringLike\n): BasicExpression<boolean> {\n return new Func(`ilike`, [toExpression(left), toExpression(right)])\n}\n\n// Functions\n\nexport function upper<T extends ExpressionLike>(\n arg: T\n): StringFunctionReturnType<T> {\n return new Func(`upper`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function lower<T extends ExpressionLike>(\n arg: T\n): StringFunctionReturnType<T> {\n return new Func(`lower`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function length<T extends ExpressionLike>(\n arg: T\n): NumericFunctionReturnType<T> {\n return new Func(`length`, [toExpression(arg)]) as NumericFunctionReturnType<T>\n}\n\nexport function concat(\n ...args: Array<ExpressionLike>\n): BasicExpression<string> {\n return new Func(\n `concat`,\n args.map((arg) => toExpression(arg))\n )\n}\n\nexport function coalesce(...args: Array<ExpressionLike>): BasicExpression<any> {\n return new Func(\n `coalesce`,\n args.map((arg) => toExpression(arg))\n )\n}\n\nexport function add<T1 extends ExpressionLike, T2 extends ExpressionLike>(\n left: T1,\n right: T2\n): BinaryNumericReturnType<T1, T2> {\n return new Func(`add`, [\n toExpression(left),\n toExpression(right),\n ]) as BinaryNumericReturnType<T1, T2>\n}\n\n// Aggregates\n\nexport function count(arg: ExpressionLike): Aggregate<number> {\n return new Aggregate(`count`, [toExpression(arg)])\n}\n\nexport function avg<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`avg`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function sum<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`sum`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function min<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`min`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function max<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`max`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\n/**\n * List of comparison function names that can be used with indexes\n */\nexport const comparisonFunctions = [\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n] as const\n"],"names":["Func","toExpression","Aggregate"],"mappings":"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"}
1
+ {"version":3,"file":"functions.cjs","sources":["../../../../src/query/builder/functions.ts"],"sourcesContent":["import { Aggregate, Func } from \"../ir\"\nimport { toExpression } from \"./ref-proxy.js\"\nimport type { BasicExpression } from \"../ir\"\nimport type { RefProxy } from \"./ref-proxy.js\"\nimport type { RefLeaf } from \"./types.js\"\n\ntype StringRef =\n | RefLeaf<string>\n | RefLeaf<string | null>\n | RefLeaf<string | undefined>\ntype StringRefProxy =\n | RefProxy<string>\n | RefProxy<string | null>\n | RefProxy<string | undefined>\ntype StringBasicExpression =\n | BasicExpression<string>\n | BasicExpression<string | null>\n | BasicExpression<string | undefined>\ntype StringLike =\n | StringRef\n | StringRefProxy\n | StringBasicExpression\n | string\n | null\n | undefined\n\ntype ComparisonOperand<T> =\n | RefProxy<T>\n | RefLeaf<T>\n | T\n | BasicExpression<T>\n | undefined\n | null\ntype ComparisonOperandPrimitive<T extends string | number | boolean> =\n | T\n | BasicExpression<T>\n | undefined\n | null\n\n// Helper type for any expression-like value\ntype ExpressionLike = BasicExpression | RefProxy<any> | RefLeaf<any> | any\n\n// Helper type to extract the underlying type from various expression types\ntype ExtractType<T> =\n T extends RefProxy<infer U>\n ? U\n : T extends RefLeaf<infer U>\n ? U\n : T extends BasicExpression<infer U>\n ? U\n : T\n\n// Helper type to determine aggregate return type based on input nullability\ntype AggregateReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends number | undefined | null | Date | bigint\n ? Aggregate<U>\n : Aggregate<number | undefined | null | Date | bigint>\n : Aggregate<number | undefined | null | Date | bigint>\n\n// Helper type to determine string function return type based on input nullability\ntype StringFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | undefined | null\n ? BasicExpression<U>\n : BasicExpression<string | undefined | null>\n : BasicExpression<string | undefined | null>\n\n// Helper type to determine numeric function return type based on input nullability\n// This handles string, array, and number inputs for functions like length()\ntype NumericFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | Array<any> | undefined | null | number\n ? BasicExpression<MapToNumber<U>>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Transform string/array types to number while preserving nullability\ntype MapToNumber<T> = T extends string | Array<any>\n ? number\n : T extends undefined\n ? undefined\n : T extends null\n ? null\n : T\n\n// Helper type for binary numeric operations (combines nullability of both operands)\ntype BinaryNumericReturnType<T1, T2> =\n ExtractType<T1> extends infer U1\n ? ExtractType<T2> extends infer U2\n ? U1 extends number\n ? U2 extends number\n ? BasicExpression<number>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : U2 extends number | null\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : U1 extends number | undefined\n ? U2 extends number\n ? BasicExpression<number | undefined>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : BasicExpression<number | undefined | null>\n : U1 extends number | null\n ? U2 extends number\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Operators\n\nexport function eq<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function eq<T extends string | number | boolean>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function eq(left: any, right: any): BasicExpression<boolean> {\n return new Func(`eq`, [toExpression(left), toExpression(right)])\n}\n\nexport function gt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function gt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gt`, [toExpression(left), toExpression(right)])\n}\n\nexport function gte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function gte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gte`, [toExpression(left), toExpression(right)])\n}\n\nexport function lt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function lt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lt`, [toExpression(left), toExpression(right)])\n}\n\nexport function lte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function lte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lte`, [toExpression(left), toExpression(right)])\n}\n\n// Overloads for and() - support 2 or more arguments\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `and`,\n allArgs.map((arg) => toExpression(arg))\n )\n}\n\n// Overloads for or() - support 2 or more arguments\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `or`,\n allArgs.map((arg) => toExpression(arg))\n )\n}\n\nexport function not(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`not`, [toExpression(value)])\n}\n\n// Null/undefined checking functions\nexport function isUndefined(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isUndefined`, [toExpression(value)])\n}\n\nexport function isNull(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isNull`, [toExpression(value)])\n}\n\nexport function inArray(\n value: ExpressionLike,\n array: ExpressionLike\n): BasicExpression<boolean> {\n return new Func(`in`, [toExpression(value), toExpression(array)])\n}\n\nexport function like(\n left: StringLike,\n right: StringLike\n): BasicExpression<boolean>\nexport function like(left: any, right: any): BasicExpression<boolean> {\n return new Func(`like`, [toExpression(left), toExpression(right)])\n}\n\nexport function ilike(\n left: StringLike,\n right: StringLike\n): BasicExpression<boolean> {\n return new Func(`ilike`, [toExpression(left), toExpression(right)])\n}\n\n// Functions\n\nexport function upper<T extends ExpressionLike>(\n arg: T\n): StringFunctionReturnType<T> {\n return new Func(`upper`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function lower<T extends ExpressionLike>(\n arg: T\n): StringFunctionReturnType<T> {\n return new Func(`lower`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function length<T extends ExpressionLike>(\n arg: T\n): NumericFunctionReturnType<T> {\n return new Func(`length`, [toExpression(arg)]) as NumericFunctionReturnType<T>\n}\n\nexport function concat(\n ...args: Array<ExpressionLike>\n): BasicExpression<string> {\n return new Func(\n `concat`,\n args.map((arg) => toExpression(arg))\n )\n}\n\nexport function coalesce(...args: Array<ExpressionLike>): BasicExpression<any> {\n return new Func(\n `coalesce`,\n args.map((arg) => toExpression(arg))\n )\n}\n\nexport function add<T1 extends ExpressionLike, T2 extends ExpressionLike>(\n left: T1,\n right: T2\n): BinaryNumericReturnType<T1, T2> {\n return new Func(`add`, [\n toExpression(left),\n toExpression(right),\n ]) as BinaryNumericReturnType<T1, T2>\n}\n\n// Aggregates\n\nexport function count(arg: ExpressionLike): Aggregate<number> {\n return new Aggregate(`count`, [toExpression(arg)])\n}\n\nexport function avg<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`avg`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function sum<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`sum`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function min<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`min`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function max<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`max`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\n/**\n * List of comparison function names that can be used with indexes\n */\nexport const comparisonFunctions = [\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n] as const\n\n/**\n * All supported operator names in TanStack DB expressions\n */\nexport const operators = [\n // Comparison operators\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n // Logical operators\n `and`,\n `or`,\n `not`,\n // Null checking\n `isNull`,\n `isUndefined`,\n // String functions\n `upper`,\n `lower`,\n `length`,\n `concat`,\n // Numeric functions\n `add`,\n // Utility functions\n `coalesce`,\n // Aggregate functions\n `count`,\n `avg`,\n `sum`,\n `min`,\n `max`,\n] as const\n\nexport type OperatorName = (typeof operators)[number]\n"],"names":["Func","toExpression","Aggregate"],"mappings":"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"}
@@ -54,4 +54,9 @@ export declare function max<T extends ExpressionLike>(arg: T): AggregateReturnTy
54
54
  * List of comparison function names that can be used with indexes
55
55
  */
56
56
  export declare const comparisonFunctions: readonly ["eq", "gt", "gte", "lt", "lte", "in", "like", "ilike"];
57
+ /**
58
+ * All supported operator names in TanStack DB expressions
59
+ */
60
+ export declare const operators: readonly ["eq", "gt", "gte", "lt", "lte", "in", "like", "ilike", "and", "or", "not", "isNull", "isUndefined", "upper", "lower", "length", "concat", "add", "coalesce", "count", "avg", "sum", "min", "max"];
61
+ export type OperatorName = (typeof operators)[number];
57
62
  export {};