@tanstack/db 0.0.1

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 (154) hide show
  1. package/README.md +37 -0
  2. package/dist/cjs/SortedMap.cjs +140 -0
  3. package/dist/cjs/SortedMap.cjs.map +1 -0
  4. package/dist/cjs/SortedMap.d.cts +91 -0
  5. package/dist/cjs/collection.cjs +597 -0
  6. package/dist/cjs/collection.cjs.map +1 -0
  7. package/dist/cjs/collection.d.cts +176 -0
  8. package/dist/cjs/deferred.cjs +25 -0
  9. package/dist/cjs/deferred.cjs.map +1 -0
  10. package/dist/cjs/deferred.d.cts +20 -0
  11. package/dist/cjs/errors.cjs +10 -0
  12. package/dist/cjs/errors.cjs.map +1 -0
  13. package/dist/cjs/errors.d.cts +3 -0
  14. package/dist/cjs/index.cjs +33 -0
  15. package/dist/cjs/index.cjs.map +1 -0
  16. package/dist/cjs/index.d.cts +9 -0
  17. package/dist/cjs/proxy.cjs +654 -0
  18. package/dist/cjs/proxy.cjs.map +1 -0
  19. package/dist/cjs/proxy.d.cts +59 -0
  20. package/dist/cjs/query/compiled-query.cjs +162 -0
  21. package/dist/cjs/query/compiled-query.cjs.map +1 -0
  22. package/dist/cjs/query/compiled-query.d.cts +22 -0
  23. package/dist/cjs/query/evaluators.cjs +146 -0
  24. package/dist/cjs/query/evaluators.cjs.map +1 -0
  25. package/dist/cjs/query/evaluators.d.cts +9 -0
  26. package/dist/cjs/query/extractors.cjs +122 -0
  27. package/dist/cjs/query/extractors.cjs.map +1 -0
  28. package/dist/cjs/query/extractors.d.cts +22 -0
  29. package/dist/cjs/query/functions.cjs +152 -0
  30. package/dist/cjs/query/functions.cjs.map +1 -0
  31. package/dist/cjs/query/functions.d.cts +21 -0
  32. package/dist/cjs/query/group-by.cjs +91 -0
  33. package/dist/cjs/query/group-by.cjs.map +1 -0
  34. package/dist/cjs/query/group-by.d.cts +40 -0
  35. package/dist/cjs/query/index.d.cts +5 -0
  36. package/dist/cjs/query/joins.cjs +155 -0
  37. package/dist/cjs/query/joins.cjs.map +1 -0
  38. package/dist/cjs/query/joins.d.cts +14 -0
  39. package/dist/cjs/query/key-by.cjs +43 -0
  40. package/dist/cjs/query/key-by.cjs.map +1 -0
  41. package/dist/cjs/query/key-by.d.cts +3 -0
  42. package/dist/cjs/query/order-by.cjs +229 -0
  43. package/dist/cjs/query/order-by.cjs.map +1 -0
  44. package/dist/cjs/query/order-by.d.cts +3 -0
  45. package/dist/cjs/query/pipeline-compiler.cjs +94 -0
  46. package/dist/cjs/query/pipeline-compiler.cjs.map +1 -0
  47. package/dist/cjs/query/pipeline-compiler.d.cts +9 -0
  48. package/dist/cjs/query/query-builder.cjs +314 -0
  49. package/dist/cjs/query/query-builder.cjs.map +1 -0
  50. package/dist/cjs/query/query-builder.d.cts +219 -0
  51. package/dist/cjs/query/schema.d.cts +98 -0
  52. package/dist/cjs/query/select.cjs +107 -0
  53. package/dist/cjs/query/select.cjs.map +1 -0
  54. package/dist/cjs/query/select.d.cts +3 -0
  55. package/dist/cjs/query/types.d.cts +188 -0
  56. package/dist/cjs/query/utils.cjs +154 -0
  57. package/dist/cjs/query/utils.cjs.map +1 -0
  58. package/dist/cjs/query/utils.d.cts +37 -0
  59. package/dist/cjs/transactions.cjs +137 -0
  60. package/dist/cjs/transactions.cjs.map +1 -0
  61. package/dist/cjs/transactions.d.cts +27 -0
  62. package/dist/cjs/types.d.cts +94 -0
  63. package/dist/cjs/utils.cjs +17 -0
  64. package/dist/cjs/utils.cjs.map +1 -0
  65. package/dist/cjs/utils.d.cts +3 -0
  66. package/dist/esm/SortedMap.d.ts +91 -0
  67. package/dist/esm/SortedMap.js +140 -0
  68. package/dist/esm/SortedMap.js.map +1 -0
  69. package/dist/esm/collection.d.ts +176 -0
  70. package/dist/esm/collection.js +597 -0
  71. package/dist/esm/collection.js.map +1 -0
  72. package/dist/esm/deferred.d.ts +20 -0
  73. package/dist/esm/deferred.js +25 -0
  74. package/dist/esm/deferred.js.map +1 -0
  75. package/dist/esm/errors.d.ts +3 -0
  76. package/dist/esm/errors.js +10 -0
  77. package/dist/esm/errors.js.map +1 -0
  78. package/dist/esm/index.d.ts +9 -0
  79. package/dist/esm/index.js +33 -0
  80. package/dist/esm/index.js.map +1 -0
  81. package/dist/esm/proxy.d.ts +59 -0
  82. package/dist/esm/proxy.js +654 -0
  83. package/dist/esm/proxy.js.map +1 -0
  84. package/dist/esm/query/compiled-query.d.ts +22 -0
  85. package/dist/esm/query/compiled-query.js +162 -0
  86. package/dist/esm/query/compiled-query.js.map +1 -0
  87. package/dist/esm/query/evaluators.d.ts +9 -0
  88. package/dist/esm/query/evaluators.js +146 -0
  89. package/dist/esm/query/evaluators.js.map +1 -0
  90. package/dist/esm/query/extractors.d.ts +22 -0
  91. package/dist/esm/query/extractors.js +122 -0
  92. package/dist/esm/query/extractors.js.map +1 -0
  93. package/dist/esm/query/functions.d.ts +21 -0
  94. package/dist/esm/query/functions.js +152 -0
  95. package/dist/esm/query/functions.js.map +1 -0
  96. package/dist/esm/query/group-by.d.ts +40 -0
  97. package/dist/esm/query/group-by.js +91 -0
  98. package/dist/esm/query/group-by.js.map +1 -0
  99. package/dist/esm/query/index.d.ts +5 -0
  100. package/dist/esm/query/joins.d.ts +14 -0
  101. package/dist/esm/query/joins.js +155 -0
  102. package/dist/esm/query/joins.js.map +1 -0
  103. package/dist/esm/query/key-by.d.ts +3 -0
  104. package/dist/esm/query/key-by.js +43 -0
  105. package/dist/esm/query/key-by.js.map +1 -0
  106. package/dist/esm/query/order-by.d.ts +3 -0
  107. package/dist/esm/query/order-by.js +229 -0
  108. package/dist/esm/query/order-by.js.map +1 -0
  109. package/dist/esm/query/pipeline-compiler.d.ts +9 -0
  110. package/dist/esm/query/pipeline-compiler.js +94 -0
  111. package/dist/esm/query/pipeline-compiler.js.map +1 -0
  112. package/dist/esm/query/query-builder.d.ts +219 -0
  113. package/dist/esm/query/query-builder.js +314 -0
  114. package/dist/esm/query/query-builder.js.map +1 -0
  115. package/dist/esm/query/schema.d.ts +98 -0
  116. package/dist/esm/query/select.d.ts +3 -0
  117. package/dist/esm/query/select.js +107 -0
  118. package/dist/esm/query/select.js.map +1 -0
  119. package/dist/esm/query/types.d.ts +188 -0
  120. package/dist/esm/query/utils.d.ts +37 -0
  121. package/dist/esm/query/utils.js +154 -0
  122. package/dist/esm/query/utils.js.map +1 -0
  123. package/dist/esm/transactions.d.ts +27 -0
  124. package/dist/esm/transactions.js +137 -0
  125. package/dist/esm/transactions.js.map +1 -0
  126. package/dist/esm/types.d.ts +94 -0
  127. package/dist/esm/utils.d.ts +3 -0
  128. package/dist/esm/utils.js +17 -0
  129. package/dist/esm/utils.js.map +1 -0
  130. package/package.json +57 -0
  131. package/src/SortedMap.ts +163 -0
  132. package/src/collection.ts +919 -0
  133. package/src/deferred.ts +47 -0
  134. package/src/errors.ts +6 -0
  135. package/src/index.ts +12 -0
  136. package/src/proxy.ts +1104 -0
  137. package/src/query/compiled-query.ts +193 -0
  138. package/src/query/evaluators.ts +222 -0
  139. package/src/query/extractors.ts +211 -0
  140. package/src/query/functions.ts +297 -0
  141. package/src/query/group-by.ts +137 -0
  142. package/src/query/index.ts +5 -0
  143. package/src/query/joins.ts +247 -0
  144. package/src/query/key-by.ts +61 -0
  145. package/src/query/order-by.ts +312 -0
  146. package/src/query/pipeline-compiler.ts +152 -0
  147. package/src/query/query-builder.ts +898 -0
  148. package/src/query/schema.ts +255 -0
  149. package/src/query/select.ts +173 -0
  150. package/src/query/types.ts +417 -0
  151. package/src/query/utils.ts +245 -0
  152. package/src/transactions.ts +198 -0
  153. package/src/types.ts +125 -0
  154. package/src/utils.ts +15 -0
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const deferred = require("./deferred.cjs");
4
+ function generateUUID() {
5
+ if (typeof crypto !== `undefined` && typeof crypto.randomUUID === `function`) {
6
+ return crypto.randomUUID();
7
+ }
8
+ return `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g, function(c) {
9
+ const r = Math.random() * 16 | 0;
10
+ const v = c === `x` ? r : r & 3 | 8;
11
+ return v.toString(16);
12
+ });
13
+ }
14
+ const transactions = [];
15
+ function createTransaction(config) {
16
+ if (typeof config.mutationFn === `undefined`) {
17
+ throw `mutationFn is required when creating a transaction`;
18
+ }
19
+ let transactionId = config.id;
20
+ if (!transactionId) {
21
+ transactionId = generateUUID();
22
+ }
23
+ const newTransaction = new Transaction({ ...config, id: transactionId });
24
+ transactions.push(newTransaction);
25
+ return newTransaction;
26
+ }
27
+ let transactionStack = [];
28
+ function getActiveTransaction() {
29
+ if (transactionStack.length > 0) {
30
+ return transactionStack.slice(-1)[0];
31
+ } else {
32
+ return void 0;
33
+ }
34
+ }
35
+ function registerTransaction(tx) {
36
+ transactionStack.push(tx);
37
+ }
38
+ function unregisterTransaction(tx) {
39
+ transactionStack = transactionStack.filter((t) => t.id !== tx.id);
40
+ }
41
+ class Transaction {
42
+ constructor(config) {
43
+ this.id = config.id;
44
+ this.mutationFn = config.mutationFn;
45
+ this.state = `pending`;
46
+ this.mutations = [];
47
+ this.isPersisted = deferred.createDeferred();
48
+ this.autoCommit = config.autoCommit ?? true;
49
+ this.createdAt = /* @__PURE__ */ new Date();
50
+ this.metadata = config.metadata ?? {};
51
+ }
52
+ setState(newState) {
53
+ this.state = newState;
54
+ }
55
+ mutate(callback) {
56
+ if (this.state !== `pending`) {
57
+ throw `You can no longer call .mutate() as the transaction is no longer pending`;
58
+ }
59
+ registerTransaction(this);
60
+ try {
61
+ callback();
62
+ } finally {
63
+ unregisterTransaction(this);
64
+ }
65
+ if (this.autoCommit) {
66
+ this.commit();
67
+ }
68
+ return this;
69
+ }
70
+ applyMutations(mutations) {
71
+ for (const newMutation of mutations) {
72
+ const existingIndex = this.mutations.findIndex(
73
+ (m) => m.key === newMutation.key
74
+ );
75
+ if (existingIndex >= 0) {
76
+ this.mutations[existingIndex] = newMutation;
77
+ } else {
78
+ this.mutations.push(newMutation);
79
+ }
80
+ }
81
+ }
82
+ rollback(config) {
83
+ var _a;
84
+ const isSecondaryRollback = (config == null ? void 0 : config.isSecondaryRollback) ?? false;
85
+ if (this.state === `completed`) {
86
+ throw `You can no longer call .rollback() as the transaction is already completed`;
87
+ }
88
+ this.setState(`failed`);
89
+ if (!isSecondaryRollback) {
90
+ const mutationKeys = /* @__PURE__ */ new Set();
91
+ this.mutations.forEach((m) => mutationKeys.add(m.key));
92
+ transactions.forEach(
93
+ (t) => t.state === `pending` && t.mutations.some((m) => mutationKeys.has(m.key)) && t.rollback({ isSecondaryRollback: true })
94
+ );
95
+ }
96
+ this.isPersisted.reject((_a = this.error) == null ? void 0 : _a.error);
97
+ this.touchCollection();
98
+ return this;
99
+ }
100
+ // Tell collection that something has changed with the transaction
101
+ touchCollection() {
102
+ const hasCalled = /* @__PURE__ */ new Set();
103
+ this.mutations.forEach((mutation) => {
104
+ if (!hasCalled.has(mutation.collection.id)) {
105
+ mutation.collection.transactions.setState((state) => state);
106
+ mutation.collection.commitPendingTransactions();
107
+ hasCalled.add(mutation.collection.id);
108
+ }
109
+ });
110
+ }
111
+ async commit() {
112
+ if (this.state !== `pending`) {
113
+ throw `You can no longer call .commit() as the transaction is no longer pending`;
114
+ }
115
+ this.setState(`persisting`);
116
+ if (this.mutations.length === 0) {
117
+ this.setState(`completed`);
118
+ }
119
+ try {
120
+ await this.mutationFn({ transaction: this });
121
+ this.setState(`completed`);
122
+ this.touchCollection();
123
+ this.isPersisted.resolve(this);
124
+ } catch (error) {
125
+ this.error = {
126
+ message: error instanceof Error ? error.message : String(error),
127
+ error: error instanceof Error ? error : new Error(String(error))
128
+ };
129
+ return this.rollback();
130
+ }
131
+ return this;
132
+ }
133
+ }
134
+ exports.Transaction = Transaction;
135
+ exports.createTransaction = createTransaction;
136
+ exports.getActiveTransaction = getActiveTransaction;
137
+ //# sourceMappingURL=transactions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactions.cjs","sources":["../../src/transactions.ts"],"sourcesContent":["import { createDeferred } from \"./deferred\"\nimport type { Deferred } from \"./deferred\"\nimport type {\n PendingMutation,\n TransactionConfig,\n TransactionState,\n} from \"./types\"\n\nfunction generateUUID() {\n // Check if crypto.randomUUID is available (modern browsers and Node.js 15+)\n if (\n typeof crypto !== `undefined` &&\n typeof crypto.randomUUID === `function`\n ) {\n return crypto.randomUUID()\n }\n\n // Fallback implementation for older environments\n return `xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g, function (c) {\n const r = (Math.random() * 16) | 0\n const v = c === `x` ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n\nconst transactions: Array<Transaction> = []\n\nexport function createTransaction(config: TransactionConfig): Transaction {\n if (typeof config.mutationFn === `undefined`) {\n throw `mutationFn is required when creating a transaction`\n }\n\n let transactionId = config.id\n if (!transactionId) {\n transactionId = generateUUID()\n }\n const newTransaction = new Transaction({ ...config, id: transactionId })\n transactions.push(newTransaction)\n\n return newTransaction\n}\n\nlet transactionStack: Array<Transaction> = []\n\nexport function getActiveTransaction(): Transaction | undefined {\n if (transactionStack.length > 0) {\n return transactionStack.slice(-1)[0]\n } else {\n return undefined\n }\n}\n\nfunction registerTransaction(tx: Transaction) {\n transactionStack.push(tx)\n}\n\nfunction unregisterTransaction(tx: Transaction) {\n transactionStack = transactionStack.filter((t) => t.id !== tx.id)\n}\n\nexport class Transaction {\n public id: string\n public state: TransactionState\n public mutationFn\n public mutations: Array<PendingMutation<any>>\n public isPersisted: Deferred<Transaction>\n public autoCommit: boolean\n public createdAt: Date\n public metadata: Record<string, unknown>\n public error?: {\n message: string\n error: Error\n }\n\n constructor(config: TransactionConfig) {\n this.id = config.id!\n this.mutationFn = config.mutationFn\n this.state = `pending`\n this.mutations = []\n this.isPersisted = createDeferred()\n this.autoCommit = config.autoCommit ?? true\n this.createdAt = new Date()\n this.metadata = config.metadata ?? {}\n }\n\n setState(newState: TransactionState) {\n this.state = newState\n }\n\n mutate(callback: () => void): Transaction {\n if (this.state !== `pending`) {\n throw `You can no longer call .mutate() as the transaction is no longer pending`\n }\n\n registerTransaction(this)\n try {\n callback()\n } finally {\n unregisterTransaction(this)\n }\n\n if (this.autoCommit) {\n this.commit()\n }\n\n return this\n }\n\n applyMutations(mutations: Array<PendingMutation<any>>): void {\n for (const newMutation of mutations) {\n const existingIndex = this.mutations.findIndex(\n (m) => m.key === newMutation.key\n )\n\n if (existingIndex >= 0) {\n // Replace existing mutation\n this.mutations[existingIndex] = newMutation\n } else {\n // Insert new mutation\n this.mutations.push(newMutation)\n }\n }\n }\n\n rollback(config?: { isSecondaryRollback?: boolean }): Transaction {\n const isSecondaryRollback = config?.isSecondaryRollback ?? false\n if (this.state === `completed`) {\n throw `You can no longer call .rollback() as the transaction is already completed`\n }\n\n this.setState(`failed`)\n\n // See if there's any other transactions w/ mutations on the same keys\n // and roll them back as well.\n if (!isSecondaryRollback) {\n const mutationKeys = new Set()\n this.mutations.forEach((m) => mutationKeys.add(m.key))\n transactions.forEach(\n (t) =>\n t.state === `pending` &&\n t.mutations.some((m) => mutationKeys.has(m.key)) &&\n t.rollback({ isSecondaryRollback: true })\n )\n }\n\n // Reject the promise\n this.isPersisted.reject(this.error?.error)\n\n this.touchCollection()\n\n return this\n }\n\n // Tell collection that something has changed with the transaction\n touchCollection(): void {\n const hasCalled = new Set()\n this.mutations.forEach((mutation) => {\n if (!hasCalled.has(mutation.collection.id)) {\n mutation.collection.transactions.setState((state) => state)\n mutation.collection.commitPendingTransactions()\n hasCalled.add(mutation.collection.id)\n }\n })\n }\n\n async commit(): Promise<Transaction> {\n if (this.state !== `pending`) {\n throw `You can no longer call .commit() as the transaction is no longer pending`\n }\n\n this.setState(`persisting`)\n\n if (this.mutations.length === 0) {\n this.setState(`completed`)\n }\n\n // Run mutationFn\n try {\n await this.mutationFn({ transaction: this })\n\n this.setState(`completed`)\n this.touchCollection()\n\n this.isPersisted.resolve(this)\n } catch (error) {\n // Update transaction with error information\n this.error = {\n message: error instanceof Error ? error.message : String(error),\n error: error instanceof Error ? error : new Error(String(error)),\n }\n\n // rollback the transaction\n return this.rollback()\n }\n\n return this\n }\n}\n"],"names":["createDeferred"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { Deferred } from './deferred.cjs';
2
+ import { PendingMutation, TransactionConfig, TransactionState } from './types.cjs';
3
+ export declare function createTransaction(config: TransactionConfig): Transaction;
4
+ export declare function getActiveTransaction(): Transaction | undefined;
5
+ export declare class Transaction {
6
+ id: string;
7
+ state: TransactionState;
8
+ mutationFn: import('./types.cjs').MutationFn;
9
+ mutations: Array<PendingMutation<any>>;
10
+ isPersisted: Deferred<Transaction>;
11
+ autoCommit: boolean;
12
+ createdAt: Date;
13
+ metadata: Record<string, unknown>;
14
+ error?: {
15
+ message: string;
16
+ error: Error;
17
+ };
18
+ constructor(config: TransactionConfig);
19
+ setState(newState: TransactionState): void;
20
+ mutate(callback: () => void): Transaction;
21
+ applyMutations(mutations: Array<PendingMutation<any>>): void;
22
+ rollback(config?: {
23
+ isSecondaryRollback?: boolean;
24
+ }): Transaction;
25
+ touchCollection(): void;
26
+ commit(): Promise<Transaction>;
27
+ }
@@ -0,0 +1,94 @@
1
+ import { Collection } from './collection.cjs';
2
+ import { StandardSchemaV1 } from '@standard-schema/spec';
3
+ import { Transaction } from './transactions.cjs';
4
+ export type TransactionState = `pending` | `persisting` | `completed` | `failed`;
5
+ /**
6
+ * Represents a pending mutation within a transaction
7
+ * Contains information about the original and modified data, as well as metadata
8
+ */
9
+ export interface PendingMutation<T extends object = Record<string, unknown>> {
10
+ mutationId: string;
11
+ original: Record<string, unknown>;
12
+ modified: Record<string, unknown>;
13
+ changes: Record<string, unknown>;
14
+ key: string;
15
+ type: OperationType;
16
+ metadata: unknown;
17
+ syncMetadata: Record<string, unknown>;
18
+ createdAt: Date;
19
+ updatedAt: Date;
20
+ collection: Collection<T>;
21
+ }
22
+ /**
23
+ * Configuration options for creating a new transaction
24
+ */
25
+ export type MutationFnParams = {
26
+ transaction: Transaction;
27
+ };
28
+ export type MutationFn = (params: MutationFnParams) => Promise<any>;
29
+ export interface TransactionConfig {
30
+ /** Unique identifier for the transaction */
31
+ id?: string;
32
+ autoCommit?: boolean;
33
+ mutationFn: MutationFn;
34
+ /** Custom metadata to associate with the transaction */
35
+ metadata?: Record<string, unknown>;
36
+ }
37
+ export type { Transaction };
38
+ type Value<TExtensions = never> = string | number | boolean | bigint | null | TExtensions | Array<Value<TExtensions>> | {
39
+ [key: string]: Value<TExtensions>;
40
+ };
41
+ export type Row<TExtensions = never> = Record<string, Value<TExtensions>>;
42
+ export type OperationType = `insert` | `update` | `delete`;
43
+ export interface SyncConfig<T extends object = Record<string, unknown>> {
44
+ sync: (params: {
45
+ collection: Collection<T>;
46
+ begin: () => void;
47
+ write: (message: ChangeMessage<T>) => void;
48
+ commit: () => void;
49
+ }) => void;
50
+ /**
51
+ * Get the sync metadata for insert operations
52
+ * @returns Record containing primaryKey and relation information
53
+ */
54
+ getSyncMetadata?: () => Record<string, unknown>;
55
+ }
56
+ export interface ChangeMessage<T extends object = Record<string, unknown>> {
57
+ key: string;
58
+ value: T;
59
+ previousValue?: T;
60
+ type: OperationType;
61
+ metadata?: Record<string, unknown>;
62
+ }
63
+ export interface OptimisticChangeMessage<T extends object = Record<string, unknown>> extends ChangeMessage<T> {
64
+ isActive?: boolean;
65
+ }
66
+ /**
67
+ * The Standard Schema interface.
68
+ * This follows the standard-schema specification: https://github.com/standard-schema/standard-schema
69
+ */
70
+ export type StandardSchema<T> = StandardSchemaV1 & {
71
+ "~standard": {
72
+ types?: {
73
+ input: T;
74
+ output: T;
75
+ };
76
+ };
77
+ };
78
+ /**
79
+ * Type alias for StandardSchema
80
+ */
81
+ export type StandardSchemaAlias<T = unknown> = StandardSchema<T>;
82
+ export interface OperationConfig {
83
+ metadata?: Record<string, unknown>;
84
+ }
85
+ export interface InsertConfig {
86
+ key?: string | Array<string | undefined>;
87
+ metadata?: Record<string, unknown>;
88
+ }
89
+ export interface CollectionConfig<T extends object = Record<string, unknown>> {
90
+ id: string;
91
+ sync: SyncConfig<T>;
92
+ schema?: StandardSchema<T>;
93
+ }
94
+ export type ChangesPayload<T extends object = Record<string, unknown>> = Array<ChangeMessage<T>>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function getLockedObjects() {
4
+ return /* @__PURE__ */ new Set();
5
+ }
6
+ let globalVersion = 0;
7
+ function getGlobalVersion() {
8
+ return globalVersion;
9
+ }
10
+ function advanceGlobalVersion() {
11
+ console.log(`==== advancing global version`, globalVersion + 1);
12
+ return globalVersion++;
13
+ }
14
+ exports.advanceGlobalVersion = advanceGlobalVersion;
15
+ exports.getGlobalVersion = getGlobalVersion;
16
+ exports.getLockedObjects = getLockedObjects;
17
+ //# sourceMappingURL=utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["export function getLockedObjects(): Set<string> {\n // Stub implementation that returns an empty Set\n return new Set()\n}\n\nlet globalVersion = 0\n\nexport function getGlobalVersion(): number {\n return globalVersion\n}\n\nexport function advanceGlobalVersion(): number {\n console.log(`==== advancing global version`, globalVersion + 1)\n return globalVersion++\n}\n"],"names":[],"mappings":";;AAAO,SAAS,mBAAgC;AAE9C,6BAAW,IAAI;AACjB;AAEA,IAAI,gBAAgB;AAEb,SAAS,mBAA2B;AAClC,SAAA;AACT;AAEO,SAAS,uBAA+B;AACrC,UAAA,IAAI,iCAAiC,gBAAgB,CAAC;AACvD,SAAA;AACT;;;;"}
@@ -0,0 +1,3 @@
1
+ export declare function getLockedObjects(): Set<string>;
2
+ export declare function getGlobalVersion(): number;
3
+ export declare function advanceGlobalVersion(): number;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * A Map implementation that keeps its entries sorted based on a comparator function
3
+ * @template TKey - The type of keys in the map
4
+ * @template TValue - The type of values in the map
5
+ */
6
+ export declare class SortedMap<TKey, TValue> {
7
+ private map;
8
+ private sortedKeys;
9
+ private comparator;
10
+ /**
11
+ * Creates a new SortedMap instance
12
+ *
13
+ * @param comparator - Optional function to compare values for sorting
14
+ */
15
+ constructor(comparator?: (a: TValue, b: TValue) => number);
16
+ /**
17
+ * Default comparator function used when none is provided
18
+ *
19
+ * @param a - First value to compare
20
+ * @param b - Second value to compare
21
+ * @returns -1 if a < b, 1 if a > b, 0 if equal
22
+ */
23
+ private defaultComparator;
24
+ /**
25
+ * Sets a key-value pair in the map and maintains sort order
26
+ *
27
+ * @param key - The key to set
28
+ * @param value - The value to associate with the key
29
+ * @returns This SortedMap instance for chaining
30
+ */
31
+ set(key: TKey, value: TValue): this;
32
+ /**
33
+ * Gets a value by its key
34
+ *
35
+ * @param key - The key to look up
36
+ * @returns The value associated with the key, or undefined if not found
37
+ */
38
+ get(key: TKey): TValue | undefined;
39
+ /**
40
+ * Removes a key-value pair from the map
41
+ *
42
+ * @param key - The key to remove
43
+ * @returns True if the key was found and removed, false otherwise
44
+ */
45
+ delete(key: TKey): boolean;
46
+ /**
47
+ * Checks if a key exists in the map
48
+ *
49
+ * @param key - The key to check
50
+ * @returns True if the key exists, false otherwise
51
+ */
52
+ has(key: TKey): boolean;
53
+ /**
54
+ * Removes all key-value pairs from the map
55
+ */
56
+ clear(): void;
57
+ /**
58
+ * Gets the number of key-value pairs in the map
59
+ */
60
+ get size(): number;
61
+ /**
62
+ * Default iterator that returns entries in sorted order
63
+ *
64
+ * @returns An iterator for the map's entries
65
+ */
66
+ [Symbol.iterator](): IterableIterator<[TKey, TValue]>;
67
+ /**
68
+ * Returns an iterator for the map's entries in sorted order
69
+ *
70
+ * @returns An iterator for the map's entries
71
+ */
72
+ entries(): IterableIterator<[TKey, TValue]>;
73
+ /**
74
+ * Returns an iterator for the map's keys in sorted order
75
+ *
76
+ * @returns An iterator for the map's keys
77
+ */
78
+ keys(): IterableIterator<TKey>;
79
+ /**
80
+ * Returns an iterator for the map's values in sorted order
81
+ *
82
+ * @returns An iterator for the map's values
83
+ */
84
+ values(): IterableIterator<TValue>;
85
+ /**
86
+ * Executes a callback function for each key-value pair in the map in sorted order
87
+ *
88
+ * @param callbackfn - Function to execute for each entry
89
+ */
90
+ forEach(callbackfn: (value: TValue, key: TKey, map: Map<TKey, TValue>) => void): void;
91
+ }
@@ -0,0 +1,140 @@
1
+ class SortedMap {
2
+ /**
3
+ * Creates a new SortedMap instance
4
+ *
5
+ * @param comparator - Optional function to compare values for sorting
6
+ */
7
+ constructor(comparator) {
8
+ this.map = /* @__PURE__ */ new Map();
9
+ this.sortedKeys = [];
10
+ this.comparator = comparator || this.defaultComparator;
11
+ }
12
+ /**
13
+ * Default comparator function used when none is provided
14
+ *
15
+ * @param a - First value to compare
16
+ * @param b - Second value to compare
17
+ * @returns -1 if a < b, 1 if a > b, 0 if equal
18
+ */
19
+ defaultComparator(a, b) {
20
+ if (a < b) return -1;
21
+ if (a > b) return 1;
22
+ return 0;
23
+ }
24
+ /**
25
+ * Sets a key-value pair in the map and maintains sort order
26
+ *
27
+ * @param key - The key to set
28
+ * @param value - The value to associate with the key
29
+ * @returns This SortedMap instance for chaining
30
+ */
31
+ set(key, value) {
32
+ this.map.set(key, value);
33
+ if (!this.sortedKeys.includes(key)) {
34
+ this.sortedKeys.push(key);
35
+ }
36
+ this.sortedKeys.sort((a, b) => {
37
+ const valueA = this.map.get(a);
38
+ const valueB = this.map.get(b);
39
+ return this.comparator(valueA, valueB);
40
+ });
41
+ return this;
42
+ }
43
+ /**
44
+ * Gets a value by its key
45
+ *
46
+ * @param key - The key to look up
47
+ * @returns The value associated with the key, or undefined if not found
48
+ */
49
+ get(key) {
50
+ return this.map.get(key);
51
+ }
52
+ /**
53
+ * Removes a key-value pair from the map
54
+ *
55
+ * @param key - The key to remove
56
+ * @returns True if the key was found and removed, false otherwise
57
+ */
58
+ delete(key) {
59
+ if (this.map.delete(key)) {
60
+ const index = this.sortedKeys.indexOf(key);
61
+ this.sortedKeys.splice(index, 1);
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+ /**
67
+ * Checks if a key exists in the map
68
+ *
69
+ * @param key - The key to check
70
+ * @returns True if the key exists, false otherwise
71
+ */
72
+ has(key) {
73
+ return this.map.has(key);
74
+ }
75
+ /**
76
+ * Removes all key-value pairs from the map
77
+ */
78
+ clear() {
79
+ this.map.clear();
80
+ this.sortedKeys = [];
81
+ }
82
+ /**
83
+ * Gets the number of key-value pairs in the map
84
+ */
85
+ get size() {
86
+ return this.map.size;
87
+ }
88
+ /**
89
+ * Default iterator that returns entries in sorted order
90
+ *
91
+ * @returns An iterator for the map's entries
92
+ */
93
+ *[Symbol.iterator]() {
94
+ for (const key of this.sortedKeys) {
95
+ yield [key, this.map.get(key)];
96
+ }
97
+ }
98
+ /**
99
+ * Returns an iterator for the map's entries in sorted order
100
+ *
101
+ * @returns An iterator for the map's entries
102
+ */
103
+ entries() {
104
+ return this[Symbol.iterator]();
105
+ }
106
+ /**
107
+ * Returns an iterator for the map's keys in sorted order
108
+ *
109
+ * @returns An iterator for the map's keys
110
+ */
111
+ keys() {
112
+ return this.sortedKeys[Symbol.iterator]();
113
+ }
114
+ /**
115
+ * Returns an iterator for the map's values in sorted order
116
+ *
117
+ * @returns An iterator for the map's values
118
+ */
119
+ values() {
120
+ return (function* () {
121
+ for (const key of this.sortedKeys) {
122
+ yield this.map.get(key);
123
+ }
124
+ }).call(this);
125
+ }
126
+ /**
127
+ * Executes a callback function for each key-value pair in the map in sorted order
128
+ *
129
+ * @param callbackfn - Function to execute for each entry
130
+ */
131
+ forEach(callbackfn) {
132
+ for (const key of this.sortedKeys) {
133
+ callbackfn(this.map.get(key), key, this.map);
134
+ }
135
+ }
136
+ }
137
+ export {
138
+ SortedMap
139
+ };
140
+ //# sourceMappingURL=SortedMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SortedMap.js","sources":["../../src/SortedMap.ts"],"sourcesContent":["/**\n * A Map implementation that keeps its entries sorted based on a comparator function\n * @template TKey - The type of keys in the map\n * @template TValue - The type of values in the map\n */\nexport class SortedMap<TKey, TValue> {\n private map: Map<TKey, TValue>\n private sortedKeys: Array<TKey>\n private comparator: (a: TValue, b: TValue) => number\n\n /**\n * Creates a new SortedMap instance\n *\n * @param comparator - Optional function to compare values for sorting\n */\n constructor(comparator?: (a: TValue, b: TValue) => number) {\n this.map = new Map<TKey, TValue>()\n this.sortedKeys = []\n this.comparator = comparator || this.defaultComparator\n }\n\n /**\n * Default comparator function used when none is provided\n *\n * @param a - First value to compare\n * @param b - Second value to compare\n * @returns -1 if a < b, 1 if a > b, 0 if equal\n */\n private defaultComparator(a: TValue, b: TValue): number {\n if (a < b) return -1\n if (a > b) return 1\n return 0\n }\n\n /**\n * Sets a key-value pair in the map and maintains sort order\n *\n * @param key - The key to set\n * @param value - The value to associate with the key\n * @returns This SortedMap instance for chaining\n */\n set(key: TKey, value: TValue): this {\n this.map.set(key, value)\n\n if (!this.sortedKeys.includes(key)) {\n this.sortedKeys.push(key)\n }\n\n // Re-sort keys based on values\n this.sortedKeys.sort((a, b) => {\n const valueA = this.map.get(a)!\n const valueB = this.map.get(b)!\n return this.comparator(valueA, valueB)\n })\n\n return this\n }\n\n /**\n * Gets a value by its key\n *\n * @param key - The key to look up\n * @returns The value associated with the key, or undefined if not found\n */\n get(key: TKey): TValue | undefined {\n return this.map.get(key)\n }\n\n /**\n * Removes a key-value pair from the map\n *\n * @param key - The key to remove\n * @returns True if the key was found and removed, false otherwise\n */\n delete(key: TKey): boolean {\n if (this.map.delete(key)) {\n const index = this.sortedKeys.indexOf(key)\n this.sortedKeys.splice(index, 1)\n return true\n }\n return false\n }\n\n /**\n * Checks if a key exists in the map\n *\n * @param key - The key to check\n * @returns True if the key exists, false otherwise\n */\n has(key: TKey): boolean {\n return this.map.has(key)\n }\n\n /**\n * Removes all key-value pairs from the map\n */\n clear(): void {\n this.map.clear()\n this.sortedKeys = []\n }\n\n /**\n * Gets the number of key-value pairs in the map\n */\n get size(): number {\n return this.map.size\n }\n\n /**\n * Default iterator that returns entries in sorted order\n *\n * @returns An iterator for the map's entries\n */\n *[Symbol.iterator](): IterableIterator<[TKey, TValue]> {\n for (const key of this.sortedKeys) {\n yield [key, this.map.get(key)!] as [TKey, TValue]\n }\n }\n\n /**\n * Returns an iterator for the map's entries in sorted order\n *\n * @returns An iterator for the map's entries\n */\n entries(): IterableIterator<[TKey, TValue]> {\n return this[Symbol.iterator]()\n }\n\n /**\n * Returns an iterator for the map's keys in sorted order\n *\n * @returns An iterator for the map's keys\n */\n keys(): IterableIterator<TKey> {\n return this.sortedKeys[Symbol.iterator]()\n }\n\n /**\n * Returns an iterator for the map's values in sorted order\n *\n * @returns An iterator for the map's values\n */\n values(): IterableIterator<TValue> {\n return function* (this: SortedMap<TKey, TValue>) {\n for (const key of this.sortedKeys) {\n yield this.map.get(key)!\n }\n }.call(this)\n }\n\n /**\n * Executes a callback function for each key-value pair in the map in sorted order\n *\n * @param callbackfn - Function to execute for each entry\n */\n forEach(\n callbackfn: (value: TValue, key: TKey, map: Map<TKey, TValue>) => void\n ): void {\n for (const key of this.sortedKeys) {\n callbackfn(this.map.get(key)!, key, this.map)\n }\n }\n}\n"],"names":[],"mappings":"AAKO,MAAM,UAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUnC,YAAY,YAA+C;AACpD,SAAA,0BAAU,IAAkB;AACjC,SAAK,aAAa,CAAC;AACd,SAAA,aAAa,cAAc,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU/B,kBAAkB,GAAW,GAAmB;AAClD,QAAA,IAAI,EAAU,QAAA;AACd,QAAA,IAAI,EAAU,QAAA;AACX,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUT,IAAI,KAAW,OAAqB;AAC7B,SAAA,IAAI,IAAI,KAAK,KAAK;AAEvB,QAAI,CAAC,KAAK,WAAW,SAAS,GAAG,GAAG;AAC7B,WAAA,WAAW,KAAK,GAAG;AAAA,IAAA;AAI1B,SAAK,WAAW,KAAK,CAAC,GAAG,MAAM;AAC7B,YAAM,SAAS,KAAK,IAAI,IAAI,CAAC;AAC7B,YAAM,SAAS,KAAK,IAAI,IAAI,CAAC;AACtB,aAAA,KAAK,WAAW,QAAQ,MAAM;AAAA,IAAA,CACtC;AAEM,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,IAAI,KAA+B;AAC1B,WAAA,KAAK,IAAI,IAAI,GAAG;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzB,OAAO,KAAoB;AACzB,QAAI,KAAK,IAAI,OAAO,GAAG,GAAG;AACxB,YAAM,QAAQ,KAAK,WAAW,QAAQ,GAAG;AACpC,WAAA,WAAW,OAAO,OAAO,CAAC;AACxB,aAAA;AAAA,IAAA;AAEF,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAST,IAAI,KAAoB;AACf,WAAA,KAAK,IAAI,IAAI,GAAG;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMzB,QAAc;AACZ,SAAK,IAAI,MAAM;AACf,SAAK,aAAa,CAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,IAAI,OAAe;AACjB,WAAO,KAAK,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlB,EAAE,OAAO,QAAQ,IAAsC;AAC1C,eAAA,OAAO,KAAK,YAAY;AACjC,YAAM,CAAC,KAAK,KAAK,IAAI,IAAI,GAAG,CAAE;AAAA,IAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,UAA4C;AACnC,WAAA,KAAK,OAAO,QAAQ,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ/B,OAA+B;AAC7B,WAAO,KAAK,WAAW,OAAO,QAAQ,EAAE;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1C,SAAmC;AACjC,YAAO,aAA0C;AACpC,iBAAA,OAAO,KAAK,YAAY;AAC3B,cAAA,KAAK,IAAI,IAAI,GAAG;AAAA,MAAA;AAAA,IACxB,GACA,KAAK,IAAI;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQb,QACE,YACM;AACK,eAAA,OAAO,KAAK,YAAY;AACjC,iBAAW,KAAK,IAAI,IAAI,GAAG,GAAI,KAAK,KAAK,GAAG;AAAA,IAAA;AAAA,EAC9C;AAEJ;"}