@push.rocks/smartmongo 2.2.0 → 3.0.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 (109) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/index.d.ts +1 -1
  3. package/dist_ts/index.js +3 -3
  4. package/dist_ts/tsmdb/engine/AggregationEngine.js +189 -0
  5. package/dist_ts/tsmdb/engine/IndexEngine.js +376 -0
  6. package/dist_ts/tsmdb/engine/QueryEngine.js +271 -0
  7. package/dist_ts/{congodb → tsmdb}/engine/TransactionEngine.d.ts +1 -1
  8. package/dist_ts/tsmdb/engine/TransactionEngine.js +287 -0
  9. package/dist_ts/tsmdb/engine/UpdateEngine.js +461 -0
  10. package/dist_ts/{congodb/errors/CongoErrors.d.ts → tsmdb/errors/TsmdbErrors.d.ts} +16 -16
  11. package/dist_ts/tsmdb/errors/TsmdbErrors.js +155 -0
  12. package/dist_ts/{congodb → tsmdb}/index.d.ts +4 -4
  13. package/dist_ts/tsmdb/index.js +26 -0
  14. package/dist_ts/{congodb → tsmdb}/server/CommandRouter.d.ts +4 -4
  15. package/dist_ts/tsmdb/server/CommandRouter.js +132 -0
  16. package/dist_ts/{congodb/server/CongoServer.d.ts → tsmdb/server/TsmdbServer.d.ts} +6 -6
  17. package/dist_ts/tsmdb/server/TsmdbServer.js +227 -0
  18. package/dist_ts/{congodb → tsmdb}/server/WireProtocol.d.ts +1 -1
  19. package/dist_ts/tsmdb/server/WireProtocol.js +298 -0
  20. package/dist_ts/{congodb → tsmdb}/server/handlers/AdminHandler.d.ts +1 -1
  21. package/dist_ts/tsmdb/server/handlers/AdminHandler.js +568 -0
  22. package/dist_ts/{congodb → tsmdb}/server/handlers/AggregateHandler.d.ts +1 -1
  23. package/dist_ts/tsmdb/server/handlers/AggregateHandler.js +277 -0
  24. package/dist_ts/{congodb → tsmdb}/server/handlers/DeleteHandler.d.ts +1 -1
  25. package/dist_ts/tsmdb/server/handlers/DeleteHandler.js +83 -0
  26. package/dist_ts/{congodb → tsmdb}/server/handlers/FindHandler.d.ts +1 -1
  27. package/dist_ts/tsmdb/server/handlers/FindHandler.js +261 -0
  28. package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.d.ts +1 -1
  29. package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.js +2 -2
  30. package/dist_ts/{congodb → tsmdb}/server/handlers/IndexHandler.d.ts +1 -1
  31. package/dist_ts/tsmdb/server/handlers/IndexHandler.js +183 -0
  32. package/dist_ts/{congodb → tsmdb}/server/handlers/InsertHandler.d.ts +1 -1
  33. package/dist_ts/tsmdb/server/handlers/InsertHandler.js +76 -0
  34. package/dist_ts/{congodb → tsmdb}/server/handlers/UpdateHandler.d.ts +1 -1
  35. package/dist_ts/tsmdb/server/handlers/UpdateHandler.js +270 -0
  36. package/dist_ts/tsmdb/server/handlers/index.js +10 -0
  37. package/dist_ts/{congodb → tsmdb}/server/index.d.ts +2 -2
  38. package/dist_ts/tsmdb/server/index.js +7 -0
  39. package/dist_ts/{congodb → tsmdb}/storage/FileStorageAdapter.d.ts +2 -2
  40. package/dist_ts/tsmdb/storage/FileStorageAdapter.js +396 -0
  41. package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.d.ts +2 -2
  42. package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.js +1 -1
  43. package/dist_ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.d.ts +2 -2
  44. package/dist_ts/tsmdb/storage/MemoryStorageAdapter.js +367 -0
  45. package/dist_ts/{congodb → tsmdb}/storage/OpLog.d.ts +1 -1
  46. package/dist_ts/tsmdb/storage/OpLog.js +221 -0
  47. package/dist_ts/tsmdb/tsmdb.plugins.js +14 -0
  48. package/dist_ts/{congodb → tsmdb}/types/interfaces.d.ts +3 -3
  49. package/dist_ts/{congodb → tsmdb}/types/interfaces.js +1 -1
  50. package/package.json +1 -1
  51. package/readme.hints.md +7 -12
  52. package/readme.md +25 -25
  53. package/ts/00_commitinfo_data.ts +1 -1
  54. package/ts/index.ts +2 -2
  55. package/ts/{congodb → tsmdb}/engine/AggregationEngine.ts +1 -1
  56. package/ts/{congodb → tsmdb}/engine/IndexEngine.ts +7 -7
  57. package/ts/{congodb → tsmdb}/engine/QueryEngine.ts +1 -1
  58. package/ts/{congodb → tsmdb}/engine/TransactionEngine.ts +12 -12
  59. package/ts/{congodb → tsmdb}/engine/UpdateEngine.ts +1 -1
  60. package/ts/{congodb/errors/CongoErrors.ts → tsmdb/errors/TsmdbErrors.ts} +34 -34
  61. package/ts/{congodb → tsmdb}/index.ts +7 -7
  62. package/ts/{congodb → tsmdb}/server/CommandRouter.ts +5 -5
  63. package/ts/{congodb/server/CongoServer.ts → tsmdb/server/TsmdbServer.ts} +8 -8
  64. package/ts/{congodb → tsmdb}/server/WireProtocol.ts +1 -1
  65. package/ts/{congodb → tsmdb}/server/handlers/AdminHandler.ts +6 -6
  66. package/ts/{congodb → tsmdb}/server/handlers/AggregateHandler.ts +1 -1
  67. package/ts/{congodb → tsmdb}/server/handlers/DeleteHandler.ts +1 -1
  68. package/ts/{congodb → tsmdb}/server/handlers/FindHandler.ts +1 -1
  69. package/ts/{congodb → tsmdb}/server/handlers/HelloHandler.ts +1 -1
  70. package/ts/{congodb → tsmdb}/server/handlers/IndexHandler.ts +1 -1
  71. package/ts/{congodb → tsmdb}/server/handlers/InsertHandler.ts +1 -1
  72. package/ts/{congodb → tsmdb}/server/handlers/UpdateHandler.ts +1 -1
  73. package/ts/{congodb → tsmdb}/server/index.ts +2 -2
  74. package/ts/{congodb → tsmdb}/storage/FileStorageAdapter.ts +2 -2
  75. package/ts/{congodb → tsmdb}/storage/IStorageAdapter.ts +2 -2
  76. package/ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.ts +2 -2
  77. package/ts/{congodb → tsmdb}/storage/OpLog.ts +1 -1
  78. package/ts/{congodb → tsmdb}/types/interfaces.ts +3 -3
  79. package/dist_ts/congodb/congodb.plugins.js +0 -14
  80. package/dist_ts/congodb/engine/AggregationEngine.js +0 -189
  81. package/dist_ts/congodb/engine/IndexEngine.js +0 -376
  82. package/dist_ts/congodb/engine/QueryEngine.js +0 -271
  83. package/dist_ts/congodb/engine/TransactionEngine.js +0 -287
  84. package/dist_ts/congodb/engine/UpdateEngine.js +0 -461
  85. package/dist_ts/congodb/errors/CongoErrors.js +0 -155
  86. package/dist_ts/congodb/index.js +0 -26
  87. package/dist_ts/congodb/server/CommandRouter.js +0 -132
  88. package/dist_ts/congodb/server/CongoServer.js +0 -227
  89. package/dist_ts/congodb/server/WireProtocol.js +0 -298
  90. package/dist_ts/congodb/server/handlers/AdminHandler.js +0 -568
  91. package/dist_ts/congodb/server/handlers/AggregateHandler.js +0 -277
  92. package/dist_ts/congodb/server/handlers/DeleteHandler.js +0 -83
  93. package/dist_ts/congodb/server/handlers/FindHandler.js +0 -261
  94. package/dist_ts/congodb/server/handlers/IndexHandler.js +0 -183
  95. package/dist_ts/congodb/server/handlers/InsertHandler.js +0 -76
  96. package/dist_ts/congodb/server/handlers/UpdateHandler.js +0 -270
  97. package/dist_ts/congodb/server/handlers/index.js +0 -10
  98. package/dist_ts/congodb/server/index.js +0 -7
  99. package/dist_ts/congodb/storage/FileStorageAdapter.js +0 -396
  100. package/dist_ts/congodb/storage/MemoryStorageAdapter.js +0 -367
  101. package/dist_ts/congodb/storage/OpLog.js +0 -221
  102. /package/dist_ts/{congodb → tsmdb}/engine/AggregationEngine.d.ts +0 -0
  103. /package/dist_ts/{congodb → tsmdb}/engine/IndexEngine.d.ts +0 -0
  104. /package/dist_ts/{congodb → tsmdb}/engine/QueryEngine.d.ts +0 -0
  105. /package/dist_ts/{congodb → tsmdb}/engine/UpdateEngine.d.ts +0 -0
  106. /package/dist_ts/{congodb → tsmdb}/server/handlers/index.d.ts +0 -0
  107. /package/dist_ts/{congodb/congodb.plugins.d.ts → tsmdb/tsmdb.plugins.d.ts} +0 -0
  108. /package/ts/{congodb → tsmdb}/server/handlers/index.ts +0 -0
  109. /package/ts/{congodb/congodb.plugins.ts → tsmdb/tsmdb.plugins.ts} +0 -0
@@ -0,0 +1,271 @@
1
+ import * as plugins from '../tsmdb.plugins.js';
2
+ // Import mingo Query class
3
+ import { Query } from 'mingo';
4
+ /**
5
+ * Query engine using mingo for MongoDB-compatible query matching
6
+ */
7
+ export class QueryEngine {
8
+ /**
9
+ * Filter documents by a MongoDB query filter
10
+ */
11
+ static filter(documents, filter) {
12
+ if (!filter || Object.keys(filter).length === 0) {
13
+ return documents;
14
+ }
15
+ const query = new Query(filter);
16
+ return documents.filter(doc => query.test(doc));
17
+ }
18
+ /**
19
+ * Test if a single document matches a filter
20
+ */
21
+ static matches(document, filter) {
22
+ if (!filter || Object.keys(filter).length === 0) {
23
+ return true;
24
+ }
25
+ const query = new Query(filter);
26
+ return query.test(document);
27
+ }
28
+ /**
29
+ * Find a single document matching the filter
30
+ */
31
+ static findOne(documents, filter) {
32
+ if (!filter || Object.keys(filter).length === 0) {
33
+ return documents[0] || null;
34
+ }
35
+ const query = new Query(filter);
36
+ for (const doc of documents) {
37
+ if (query.test(doc)) {
38
+ return doc;
39
+ }
40
+ }
41
+ return null;
42
+ }
43
+ /**
44
+ * Sort documents by a sort specification
45
+ */
46
+ static sort(documents, sort) {
47
+ if (!sort) {
48
+ return documents;
49
+ }
50
+ // Normalize sort specification to array of [field, direction] pairs
51
+ const sortFields = [];
52
+ if (Array.isArray(sort)) {
53
+ for (const [field, direction] of sort) {
54
+ sortFields.push([field, this.normalizeDirection(direction)]);
55
+ }
56
+ }
57
+ else {
58
+ for (const [field, direction] of Object.entries(sort)) {
59
+ sortFields.push([field, this.normalizeDirection(direction)]);
60
+ }
61
+ }
62
+ return [...documents].sort((a, b) => {
63
+ for (const [field, direction] of sortFields) {
64
+ const aVal = this.getNestedValue(a, field);
65
+ const bVal = this.getNestedValue(b, field);
66
+ const comparison = this.compareValues(aVal, bVal);
67
+ if (comparison !== 0) {
68
+ return comparison * direction;
69
+ }
70
+ }
71
+ return 0;
72
+ });
73
+ }
74
+ /**
75
+ * Apply projection to documents
76
+ */
77
+ static project(documents, projection) {
78
+ if (!projection || Object.keys(projection).length === 0) {
79
+ return documents;
80
+ }
81
+ // Determine if this is inclusion or exclusion projection
82
+ const keys = Object.keys(projection);
83
+ const hasInclusion = keys.some(k => k !== '_id' && projection[k] === 1);
84
+ const hasExclusion = keys.some(k => k !== '_id' && projection[k] === 0);
85
+ // Can't mix inclusion and exclusion (except for _id)
86
+ if (hasInclusion && hasExclusion) {
87
+ throw new Error('Cannot mix inclusion and exclusion in projection');
88
+ }
89
+ return documents.map(doc => {
90
+ if (hasInclusion) {
91
+ // Inclusion projection
92
+ const result = {};
93
+ // Handle _id
94
+ if (projection._id !== 0 && projection._id !== false) {
95
+ result._id = doc._id;
96
+ }
97
+ for (const key of keys) {
98
+ if (key === '_id')
99
+ continue;
100
+ if (projection[key] === 1 || projection[key] === true) {
101
+ const value = this.getNestedValue(doc, key);
102
+ if (value !== undefined) {
103
+ this.setNestedValue(result, key, value);
104
+ }
105
+ }
106
+ }
107
+ return result;
108
+ }
109
+ else {
110
+ // Exclusion projection - start with copy and remove fields
111
+ const result = { ...doc };
112
+ for (const key of keys) {
113
+ if (projection[key] === 0 || projection[key] === false) {
114
+ this.deleteNestedValue(result, key);
115
+ }
116
+ }
117
+ return result;
118
+ }
119
+ });
120
+ }
121
+ /**
122
+ * Get distinct values for a field
123
+ */
124
+ static distinct(documents, field, filter) {
125
+ let docs = documents;
126
+ if (filter && Object.keys(filter).length > 0) {
127
+ docs = this.filter(documents, filter);
128
+ }
129
+ const values = new Set();
130
+ for (const doc of docs) {
131
+ const value = this.getNestedValue(doc, field);
132
+ if (value !== undefined) {
133
+ if (Array.isArray(value)) {
134
+ // For arrays, add each element
135
+ for (const v of value) {
136
+ values.add(this.toComparable(v));
137
+ }
138
+ }
139
+ else {
140
+ values.add(this.toComparable(value));
141
+ }
142
+ }
143
+ }
144
+ return Array.from(values);
145
+ }
146
+ /**
147
+ * Normalize sort direction to 1 or -1
148
+ */
149
+ static normalizeDirection(direction) {
150
+ if (typeof direction === 'number') {
151
+ return direction > 0 ? 1 : -1;
152
+ }
153
+ if (direction === 'asc' || direction === 'ascending') {
154
+ return 1;
155
+ }
156
+ return -1;
157
+ }
158
+ /**
159
+ * Get a nested value from an object using dot notation
160
+ */
161
+ static getNestedValue(obj, path) {
162
+ const parts = path.split('.');
163
+ let current = obj;
164
+ for (const part of parts) {
165
+ if (current === null || current === undefined) {
166
+ return undefined;
167
+ }
168
+ if (Array.isArray(current)) {
169
+ // Handle array access
170
+ const index = parseInt(part, 10);
171
+ if (!isNaN(index)) {
172
+ current = current[index];
173
+ }
174
+ else {
175
+ // Get the field from all array elements
176
+ return current.map(item => this.getNestedValue(item, part)).flat();
177
+ }
178
+ }
179
+ else {
180
+ current = current[part];
181
+ }
182
+ }
183
+ return current;
184
+ }
185
+ /**
186
+ * Set a nested value in an object using dot notation
187
+ */
188
+ static setNestedValue(obj, path, value) {
189
+ const parts = path.split('.');
190
+ let current = obj;
191
+ for (let i = 0; i < parts.length - 1; i++) {
192
+ const part = parts[i];
193
+ if (!(part in current)) {
194
+ current[part] = {};
195
+ }
196
+ current = current[part];
197
+ }
198
+ current[parts[parts.length - 1]] = value;
199
+ }
200
+ /**
201
+ * Delete a nested value from an object using dot notation
202
+ */
203
+ static deleteNestedValue(obj, path) {
204
+ const parts = path.split('.');
205
+ let current = obj;
206
+ for (let i = 0; i < parts.length - 1; i++) {
207
+ const part = parts[i];
208
+ if (!(part in current)) {
209
+ return;
210
+ }
211
+ current = current[part];
212
+ }
213
+ delete current[parts[parts.length - 1]];
214
+ }
215
+ /**
216
+ * Compare two values for sorting
217
+ */
218
+ static compareValues(a, b) {
219
+ // Handle undefined/null
220
+ if (a === undefined && b === undefined)
221
+ return 0;
222
+ if (a === undefined)
223
+ return -1;
224
+ if (b === undefined)
225
+ return 1;
226
+ if (a === null && b === null)
227
+ return 0;
228
+ if (a === null)
229
+ return -1;
230
+ if (b === null)
231
+ return 1;
232
+ // Handle ObjectId
233
+ if (a instanceof plugins.bson.ObjectId && b instanceof plugins.bson.ObjectId) {
234
+ return a.toHexString().localeCompare(b.toHexString());
235
+ }
236
+ // Handle dates
237
+ if (a instanceof Date && b instanceof Date) {
238
+ return a.getTime() - b.getTime();
239
+ }
240
+ // Handle numbers
241
+ if (typeof a === 'number' && typeof b === 'number') {
242
+ return a - b;
243
+ }
244
+ // Handle strings
245
+ if (typeof a === 'string' && typeof b === 'string') {
246
+ return a.localeCompare(b);
247
+ }
248
+ // Handle booleans
249
+ if (typeof a === 'boolean' && typeof b === 'boolean') {
250
+ return (a ? 1 : 0) - (b ? 1 : 0);
251
+ }
252
+ // Fall back to string comparison
253
+ return String(a).localeCompare(String(b));
254
+ }
255
+ /**
256
+ * Convert a value to a comparable form (for distinct)
257
+ */
258
+ static toComparable(value) {
259
+ if (value instanceof plugins.bson.ObjectId) {
260
+ return value.toHexString();
261
+ }
262
+ if (value instanceof Date) {
263
+ return value.toISOString();
264
+ }
265
+ if (typeof value === 'object' && value !== null) {
266
+ return JSON.stringify(value);
267
+ }
268
+ return value;
269
+ }
270
+ }
271
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUXVlcnlFbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9lbmdpbmUvUXVlcnlFbmdpbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUcvQywyQkFBMkI7QUFDM0IsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUU5Qjs7R0FFRztBQUNILE1BQU0sT0FBTyxXQUFXO0lBQ3RCOztPQUVHO0lBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUE0QixFQUFFLE1BQWdCO1FBQzFELElBQUksQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDaEQsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ2hDLE9BQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQWtCLEVBQUUsTUFBZ0I7UUFDakQsSUFBSSxDQUFDLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNoRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUE0QixFQUFF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
@@ -1,4 +1,4 @@
1
- import * as plugins from '../congodb.plugins.js';
1
+ import * as plugins from '../tsmdb.plugins.js';
2
2
  import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
3
3
  import type { IStoredDocument, ITransactionOptions } from '../types/interfaces.js';
4
4
  /**
@@ -0,0 +1,287 @@
1
+ import * as plugins from '../tsmdb.plugins.js';
2
+ import { TsmdbTransactionError, TsmdbWriteConflictError } from '../errors/TsmdbErrors.js';
3
+ /**
4
+ * Transaction engine for ACID transaction support
5
+ */
6
+ export class TransactionEngine {
7
+ storage;
8
+ transactions = new Map();
9
+ txnCounter = 0;
10
+ constructor(storage) {
11
+ this.storage = storage;
12
+ }
13
+ /**
14
+ * Start a new transaction
15
+ */
16
+ startTransaction(sessionId, options) {
17
+ this.txnCounter++;
18
+ const txnId = `txn_${sessionId}_${this.txnCounter}`;
19
+ const transaction = {
20
+ id: txnId,
21
+ sessionId,
22
+ startTime: new plugins.bson.Timestamp({ t: Math.floor(Date.now() / 1000), i: this.txnCounter }),
23
+ status: 'active',
24
+ readSet: new Map(),
25
+ writeSet: new Map(),
26
+ snapshots: new Map(),
27
+ };
28
+ this.transactions.set(txnId, transaction);
29
+ return txnId;
30
+ }
31
+ /**
32
+ * Get a transaction by ID
33
+ */
34
+ getTransaction(txnId) {
35
+ return this.transactions.get(txnId);
36
+ }
37
+ /**
38
+ * Check if a transaction is active
39
+ */
40
+ isActive(txnId) {
41
+ const txn = this.transactions.get(txnId);
42
+ return txn?.status === 'active';
43
+ }
44
+ /**
45
+ * Get or create a snapshot for a namespace
46
+ */
47
+ async getSnapshot(txnId, dbName, collName) {
48
+ const txn = this.transactions.get(txnId);
49
+ if (!txn || txn.status !== 'active') {
50
+ throw new TsmdbTransactionError('Transaction is not active');
51
+ }
52
+ const ns = `${dbName}.${collName}`;
53
+ if (!txn.snapshots.has(ns)) {
54
+ const snapshot = await this.storage.createSnapshot(dbName, collName);
55
+ txn.snapshots.set(ns, snapshot);
56
+ }
57
+ // Apply transaction writes to snapshot
58
+ const snapshot = txn.snapshots.get(ns);
59
+ const writes = txn.writeSet.get(ns);
60
+ if (!writes) {
61
+ return snapshot;
62
+ }
63
+ // Create a modified view of the snapshot
64
+ const result = [];
65
+ const deletedIds = new Set();
66
+ const modifiedDocs = new Map();
67
+ for (const [idStr, write] of writes) {
68
+ if (write.op === 'delete') {
69
+ deletedIds.add(idStr);
70
+ }
71
+ else if (write.op === 'update' || write.op === 'insert') {
72
+ if (write.doc) {
73
+ modifiedDocs.set(idStr, write.doc);
74
+ }
75
+ }
76
+ }
77
+ // Add existing documents (not deleted, possibly modified)
78
+ for (const doc of snapshot) {
79
+ const idStr = doc._id.toHexString();
80
+ if (deletedIds.has(idStr)) {
81
+ continue;
82
+ }
83
+ if (modifiedDocs.has(idStr)) {
84
+ result.push(modifiedDocs.get(idStr));
85
+ modifiedDocs.delete(idStr);
86
+ }
87
+ else {
88
+ result.push(doc);
89
+ }
90
+ }
91
+ // Add new documents (inserts)
92
+ for (const doc of modifiedDocs.values()) {
93
+ result.push(doc);
94
+ }
95
+ return result;
96
+ }
97
+ /**
98
+ * Record a read operation
99
+ */
100
+ recordRead(txnId, dbName, collName, docIds) {
101
+ const txn = this.transactions.get(txnId);
102
+ if (!txn || txn.status !== 'active')
103
+ return;
104
+ const ns = `${dbName}.${collName}`;
105
+ if (!txn.readSet.has(ns)) {
106
+ txn.readSet.set(ns, new Set());
107
+ }
108
+ const readSet = txn.readSet.get(ns);
109
+ for (const id of docIds) {
110
+ readSet.add(id);
111
+ }
112
+ }
113
+ /**
114
+ * Record a write operation (insert)
115
+ */
116
+ recordInsert(txnId, dbName, collName, doc) {
117
+ const txn = this.transactions.get(txnId);
118
+ if (!txn || txn.status !== 'active') {
119
+ throw new TsmdbTransactionError('Transaction is not active');
120
+ }
121
+ const ns = `${dbName}.${collName}`;
122
+ if (!txn.writeSet.has(ns)) {
123
+ txn.writeSet.set(ns, new Map());
124
+ }
125
+ txn.writeSet.get(ns).set(doc._id.toHexString(), {
126
+ op: 'insert',
127
+ doc,
128
+ });
129
+ }
130
+ /**
131
+ * Record a write operation (update)
132
+ */
133
+ recordUpdate(txnId, dbName, collName, originalDoc, updatedDoc) {
134
+ const txn = this.transactions.get(txnId);
135
+ if (!txn || txn.status !== 'active') {
136
+ throw new TsmdbTransactionError('Transaction is not active');
137
+ }
138
+ const ns = `${dbName}.${collName}`;
139
+ if (!txn.writeSet.has(ns)) {
140
+ txn.writeSet.set(ns, new Map());
141
+ }
142
+ const idStr = originalDoc._id.toHexString();
143
+ const existing = txn.writeSet.get(ns).get(idStr);
144
+ // If we already have a write for this document, update it
145
+ if (existing) {
146
+ existing.doc = updatedDoc;
147
+ }
148
+ else {
149
+ txn.writeSet.get(ns).set(idStr, {
150
+ op: 'update',
151
+ doc: updatedDoc,
152
+ originalDoc,
153
+ });
154
+ }
155
+ }
156
+ /**
157
+ * Record a write operation (delete)
158
+ */
159
+ recordDelete(txnId, dbName, collName, doc) {
160
+ const txn = this.transactions.get(txnId);
161
+ if (!txn || txn.status !== 'active') {
162
+ throw new TsmdbTransactionError('Transaction is not active');
163
+ }
164
+ const ns = `${dbName}.${collName}`;
165
+ if (!txn.writeSet.has(ns)) {
166
+ txn.writeSet.set(ns, new Map());
167
+ }
168
+ const idStr = doc._id.toHexString();
169
+ const existing = txn.writeSet.get(ns).get(idStr);
170
+ if (existing && existing.op === 'insert') {
171
+ // If we inserted and then deleted, just remove the write
172
+ txn.writeSet.get(ns).delete(idStr);
173
+ }
174
+ else {
175
+ txn.writeSet.get(ns).set(idStr, {
176
+ op: 'delete',
177
+ originalDoc: doc,
178
+ });
179
+ }
180
+ }
181
+ /**
182
+ * Commit a transaction
183
+ */
184
+ async commitTransaction(txnId) {
185
+ const txn = this.transactions.get(txnId);
186
+ if (!txn) {
187
+ throw new TsmdbTransactionError('Transaction not found');
188
+ }
189
+ if (txn.status !== 'active') {
190
+ throw new TsmdbTransactionError(`Cannot commit transaction in state: ${txn.status}`);
191
+ }
192
+ // Check for write conflicts
193
+ for (const [ns, writes] of txn.writeSet) {
194
+ const [dbName, collName] = ns.split('.');
195
+ const ids = Array.from(writes.keys()).map(id => new plugins.bson.ObjectId(id));
196
+ const hasConflicts = await this.storage.hasConflicts(dbName, collName, ids, txn.startTime);
197
+ if (hasConflicts) {
198
+ txn.status = 'aborted';
199
+ throw new TsmdbWriteConflictError();
200
+ }
201
+ }
202
+ // Apply all writes
203
+ for (const [ns, writes] of txn.writeSet) {
204
+ const [dbName, collName] = ns.split('.');
205
+ for (const [idStr, write] of writes) {
206
+ switch (write.op) {
207
+ case 'insert':
208
+ if (write.doc) {
209
+ await this.storage.insertOne(dbName, collName, write.doc);
210
+ }
211
+ break;
212
+ case 'update':
213
+ if (write.doc) {
214
+ await this.storage.updateById(dbName, collName, new plugins.bson.ObjectId(idStr), write.doc);
215
+ }
216
+ break;
217
+ case 'delete':
218
+ await this.storage.deleteById(dbName, collName, new plugins.bson.ObjectId(idStr));
219
+ break;
220
+ }
221
+ }
222
+ }
223
+ txn.status = 'committed';
224
+ }
225
+ /**
226
+ * Abort a transaction
227
+ */
228
+ async abortTransaction(txnId) {
229
+ const txn = this.transactions.get(txnId);
230
+ if (!txn) {
231
+ throw new TsmdbTransactionError('Transaction not found');
232
+ }
233
+ if (txn.status !== 'active') {
234
+ // Already committed or aborted, just return
235
+ return;
236
+ }
237
+ // Simply discard all buffered writes
238
+ txn.writeSet.clear();
239
+ txn.readSet.clear();
240
+ txn.snapshots.clear();
241
+ txn.status = 'aborted';
242
+ }
243
+ /**
244
+ * End a transaction (cleanup)
245
+ */
246
+ endTransaction(txnId) {
247
+ this.transactions.delete(txnId);
248
+ }
249
+ /**
250
+ * Get all pending writes for a namespace
251
+ */
252
+ getPendingWrites(txnId, dbName, collName) {
253
+ const txn = this.transactions.get(txnId);
254
+ if (!txn)
255
+ return undefined;
256
+ const ns = `${dbName}.${collName}`;
257
+ return txn.writeSet.get(ns);
258
+ }
259
+ /**
260
+ * Execute a callback within a transaction, with automatic retry on conflict
261
+ */
262
+ async withTransaction(sessionId, callback, options) {
263
+ const maxRetries = options?.maxRetries ?? 3;
264
+ let lastError;
265
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
266
+ const txnId = this.startTransaction(sessionId, options);
267
+ try {
268
+ const result = await callback(txnId);
269
+ await this.commitTransaction(txnId);
270
+ this.endTransaction(txnId);
271
+ return result;
272
+ }
273
+ catch (error) {
274
+ await this.abortTransaction(txnId);
275
+ this.endTransaction(txnId);
276
+ if (error instanceof TsmdbWriteConflictError && attempt < maxRetries - 1) {
277
+ // Retry on write conflict
278
+ lastError = error;
279
+ continue;
280
+ }
281
+ throw error;
282
+ }
283
+ }
284
+ throw lastError || new TsmdbTransactionError('Transaction failed after max retries');
285
+ }
286
+ }
287
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVHJhbnNhY3Rpb25FbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9lbmdpbmUvVHJhbnNhY3Rpb25FbmdpbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxxQkFBcUIsQ0FBQztBQUcvQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQWUxRjs7R0FFRztBQUNILE1BQU0sT0FBTyxpQkFBaUI7SUFDcEIsT0FBTyxDQUFrQjtJQUN6QixZQUFZLEdBQW1DLElBQUksR0FBRyxFQUFFLENBQUM7SUFDekQsVUFBVSxHQUFHLENBQUMsQ0FBQztJQUV2QixZQUFZLE9BQXdCO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNILGdCQUFnQixDQUFDLFNBQWlCLEVBQUUsT0FBNkI7UUFDL0QsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sS0FBSyxHQUFHLE9BQU8sU0FBUyxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUVwRCxNQUFNLFdBQVcsR0FBc0I7WUFDckMsRUFBRSxFQUFFLEtBQUs7WUFDVCxTQUFTO1lBQ1QsU0FBUyxFQUFFLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUMvRixNQUFNLEVBQUUsUUFBUTtZQUNoQixPQUFPLEVBQUUsSUFBSSxHQUFHLEVBQUU7WUFDbEIsUUFBUSxFQUFFLElBQUksR0FBRyxFQUFFO1lBQ25CLFNBQVMsRUFBRSxJQUFJLEdBQUcsRUFBRTtTQUNyQixDQUFDO1FBRUYsSUFBSSxD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