@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,367 @@
1
+ import * as plugins from '../tsmdb.plugins.js';
2
+ /**
3
+ * In-memory storage adapter for TsmDB
4
+ * Optionally supports persistence to a file
5
+ */
6
+ export class MemoryStorageAdapter {
7
+ // Database -> Collection -> Documents
8
+ databases = new Map();
9
+ // Database -> Collection -> Indexes
10
+ indexes = new Map();
11
+ // OpLog entries
12
+ opLog = [];
13
+ opLogCounter = 0;
14
+ // Persistence settings
15
+ persistPath;
16
+ persistInterval;
17
+ fs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
18
+ constructor(options) {
19
+ this.persistPath = options?.persistPath;
20
+ if (this.persistPath && options?.persistIntervalMs) {
21
+ this.persistInterval = setInterval(() => {
22
+ this.persist().catch(console.error);
23
+ }, options.persistIntervalMs);
24
+ }
25
+ }
26
+ async initialize() {
27
+ if (this.persistPath) {
28
+ await this.restore();
29
+ }
30
+ }
31
+ async close() {
32
+ if (this.persistInterval) {
33
+ clearInterval(this.persistInterval);
34
+ }
35
+ if (this.persistPath) {
36
+ await this.persist();
37
+ }
38
+ }
39
+ // ============================================================================
40
+ // Database Operations
41
+ // ============================================================================
42
+ async listDatabases() {
43
+ return Array.from(this.databases.keys());
44
+ }
45
+ async createDatabase(dbName) {
46
+ if (!this.databases.has(dbName)) {
47
+ this.databases.set(dbName, new Map());
48
+ this.indexes.set(dbName, new Map());
49
+ }
50
+ }
51
+ async dropDatabase(dbName) {
52
+ const existed = this.databases.has(dbName);
53
+ this.databases.delete(dbName);
54
+ this.indexes.delete(dbName);
55
+ return existed;
56
+ }
57
+ async databaseExists(dbName) {
58
+ return this.databases.has(dbName);
59
+ }
60
+ // ============================================================================
61
+ // Collection Operations
62
+ // ============================================================================
63
+ async listCollections(dbName) {
64
+ const db = this.databases.get(dbName);
65
+ return db ? Array.from(db.keys()) : [];
66
+ }
67
+ async createCollection(dbName, collName) {
68
+ await this.createDatabase(dbName);
69
+ const db = this.databases.get(dbName);
70
+ if (!db.has(collName)) {
71
+ db.set(collName, new Map());
72
+ // Initialize default _id index
73
+ const dbIndexes = this.indexes.get(dbName);
74
+ dbIndexes.set(collName, [{ name: '_id_', key: { _id: 1 }, unique: true }]);
75
+ }
76
+ }
77
+ async dropCollection(dbName, collName) {
78
+ const db = this.databases.get(dbName);
79
+ if (!db)
80
+ return false;
81
+ const existed = db.has(collName);
82
+ db.delete(collName);
83
+ const dbIndexes = this.indexes.get(dbName);
84
+ if (dbIndexes) {
85
+ dbIndexes.delete(collName);
86
+ }
87
+ return existed;
88
+ }
89
+ async collectionExists(dbName, collName) {
90
+ const db = this.databases.get(dbName);
91
+ return db ? db.has(collName) : false;
92
+ }
93
+ async renameCollection(dbName, oldName, newName) {
94
+ const db = this.databases.get(dbName);
95
+ if (!db || !db.has(oldName)) {
96
+ throw new Error(`Collection ${oldName} not found`);
97
+ }
98
+ const collection = db.get(oldName);
99
+ db.set(newName, collection);
100
+ db.delete(oldName);
101
+ // Also rename indexes
102
+ const dbIndexes = this.indexes.get(dbName);
103
+ if (dbIndexes && dbIndexes.has(oldName)) {
104
+ const collIndexes = dbIndexes.get(oldName);
105
+ dbIndexes.set(newName, collIndexes);
106
+ dbIndexes.delete(oldName);
107
+ }
108
+ }
109
+ // ============================================================================
110
+ // Document Operations
111
+ // ============================================================================
112
+ getCollection(dbName, collName) {
113
+ const db = this.databases.get(dbName);
114
+ if (!db) {
115
+ throw new Error(`Database ${dbName} not found`);
116
+ }
117
+ const collection = db.get(collName);
118
+ if (!collection) {
119
+ throw new Error(`Collection ${collName} not found`);
120
+ }
121
+ return collection;
122
+ }
123
+ ensureCollection(dbName, collName) {
124
+ if (!this.databases.has(dbName)) {
125
+ this.databases.set(dbName, new Map());
126
+ this.indexes.set(dbName, new Map());
127
+ }
128
+ const db = this.databases.get(dbName);
129
+ if (!db.has(collName)) {
130
+ db.set(collName, new Map());
131
+ const dbIndexes = this.indexes.get(dbName);
132
+ dbIndexes.set(collName, [{ name: '_id_', key: { _id: 1 }, unique: true }]);
133
+ }
134
+ return db.get(collName);
135
+ }
136
+ async insertOne(dbName, collName, doc) {
137
+ const collection = this.ensureCollection(dbName, collName);
138
+ const storedDoc = {
139
+ ...doc,
140
+ _id: doc._id instanceof plugins.bson.ObjectId ? doc._id : new plugins.bson.ObjectId(doc._id),
141
+ };
142
+ if (!storedDoc._id) {
143
+ storedDoc._id = new plugins.bson.ObjectId();
144
+ }
145
+ const idStr = storedDoc._id.toHexString();
146
+ if (collection.has(idStr)) {
147
+ throw new Error(`Duplicate key error: _id ${idStr}`);
148
+ }
149
+ collection.set(idStr, storedDoc);
150
+ return storedDoc;
151
+ }
152
+ async insertMany(dbName, collName, docs) {
153
+ const results = [];
154
+ for (const doc of docs) {
155
+ results.push(await this.insertOne(dbName, collName, doc));
156
+ }
157
+ return results;
158
+ }
159
+ async findAll(dbName, collName) {
160
+ const collection = this.ensureCollection(dbName, collName);
161
+ return Array.from(collection.values());
162
+ }
163
+ async findById(dbName, collName, id) {
164
+ const collection = this.ensureCollection(dbName, collName);
165
+ return collection.get(id.toHexString()) || null;
166
+ }
167
+ async updateById(dbName, collName, id, doc) {
168
+ const collection = this.ensureCollection(dbName, collName);
169
+ const idStr = id.toHexString();
170
+ if (!collection.has(idStr)) {
171
+ return false;
172
+ }
173
+ collection.set(idStr, doc);
174
+ return true;
175
+ }
176
+ async deleteById(dbName, collName, id) {
177
+ const collection = this.ensureCollection(dbName, collName);
178
+ return collection.delete(id.toHexString());
179
+ }
180
+ async deleteByIds(dbName, collName, ids) {
181
+ let count = 0;
182
+ for (const id of ids) {
183
+ if (await this.deleteById(dbName, collName, id)) {
184
+ count++;
185
+ }
186
+ }
187
+ return count;
188
+ }
189
+ async count(dbName, collName) {
190
+ const collection = this.ensureCollection(dbName, collName);
191
+ return collection.size;
192
+ }
193
+ // ============================================================================
194
+ // Index Operations
195
+ // ============================================================================
196
+ async saveIndex(dbName, collName, indexName, indexSpec) {
197
+ await this.createCollection(dbName, collName);
198
+ const dbIndexes = this.indexes.get(dbName);
199
+ let collIndexes = dbIndexes.get(collName);
200
+ if (!collIndexes) {
201
+ collIndexes = [{ name: '_id_', key: { _id: 1 }, unique: true }];
202
+ dbIndexes.set(collName, collIndexes);
203
+ }
204
+ // Check if index already exists
205
+ const existingIndex = collIndexes.findIndex(i => i.name === indexName);
206
+ if (existingIndex >= 0) {
207
+ collIndexes[existingIndex] = { name: indexName, ...indexSpec };
208
+ }
209
+ else {
210
+ collIndexes.push({ name: indexName, ...indexSpec });
211
+ }
212
+ }
213
+ async getIndexes(dbName, collName) {
214
+ const dbIndexes = this.indexes.get(dbName);
215
+ if (!dbIndexes)
216
+ return [{ name: '_id_', key: { _id: 1 }, unique: true }];
217
+ const collIndexes = dbIndexes.get(collName);
218
+ return collIndexes || [{ name: '_id_', key: { _id: 1 }, unique: true }];
219
+ }
220
+ async dropIndex(dbName, collName, indexName) {
221
+ if (indexName === '_id_') {
222
+ throw new Error('Cannot drop _id index');
223
+ }
224
+ const dbIndexes = this.indexes.get(dbName);
225
+ if (!dbIndexes)
226
+ return false;
227
+ const collIndexes = dbIndexes.get(collName);
228
+ if (!collIndexes)
229
+ return false;
230
+ const idx = collIndexes.findIndex(i => i.name === indexName);
231
+ if (idx >= 0) {
232
+ collIndexes.splice(idx, 1);
233
+ return true;
234
+ }
235
+ return false;
236
+ }
237
+ // ============================================================================
238
+ // OpLog Operations
239
+ // ============================================================================
240
+ async appendOpLog(entry) {
241
+ this.opLog.push(entry);
242
+ // Trim oplog if it gets too large (keep last 10000 entries)
243
+ if (this.opLog.length > 10000) {
244
+ this.opLog = this.opLog.slice(-10000);
245
+ }
246
+ }
247
+ async getOpLogAfter(ts, limit = 1000) {
248
+ const tsValue = ts.toNumber();
249
+ const entries = this.opLog.filter(e => e.ts.toNumber() > tsValue);
250
+ return entries.slice(0, limit);
251
+ }
252
+ async getLatestOpLogTimestamp() {
253
+ if (this.opLog.length === 0)
254
+ return null;
255
+ return this.opLog[this.opLog.length - 1].ts;
256
+ }
257
+ /**
258
+ * Generate a new timestamp for oplog entries
259
+ */
260
+ generateTimestamp() {
261
+ this.opLogCounter++;
262
+ return new plugins.bson.Timestamp({ t: Math.floor(Date.now() / 1000), i: this.opLogCounter });
263
+ }
264
+ // ============================================================================
265
+ // Transaction Support
266
+ // ============================================================================
267
+ async createSnapshot(dbName, collName) {
268
+ const docs = await this.findAll(dbName, collName);
269
+ // Deep clone the documents for snapshot isolation
270
+ return docs.map(doc => JSON.parse(JSON.stringify(doc)));
271
+ }
272
+ async hasConflicts(dbName, collName, ids, snapshotTime) {
273
+ // Check if any of the given document IDs have been modified after snapshotTime
274
+ const ns = `${dbName}.${collName}`;
275
+ const modifiedIds = new Set();
276
+ for (const entry of this.opLog) {
277
+ if (entry.ts.greaterThan(snapshotTime) && entry.ns === ns) {
278
+ if (entry.o._id) {
279
+ modifiedIds.add(entry.o._id.toString());
280
+ }
281
+ if (entry.o2?._id) {
282
+ modifiedIds.add(entry.o2._id.toString());
283
+ }
284
+ }
285
+ }
286
+ for (const id of ids) {
287
+ if (modifiedIds.has(id.toString())) {
288
+ return true;
289
+ }
290
+ }
291
+ return false;
292
+ }
293
+ // ============================================================================
294
+ // Persistence
295
+ // ============================================================================
296
+ async persist() {
297
+ if (!this.persistPath)
298
+ return;
299
+ const data = {
300
+ databases: {},
301
+ indexes: {},
302
+ opLogCounter: this.opLogCounter,
303
+ };
304
+ for (const [dbName, collections] of this.databases) {
305
+ data.databases[dbName] = {};
306
+ for (const [collName, docs] of collections) {
307
+ data.databases[dbName][collName] = Array.from(docs.values());
308
+ }
309
+ }
310
+ for (const [dbName, collIndexes] of this.indexes) {
311
+ data.indexes[dbName] = {};
312
+ for (const [collName, indexes] of collIndexes) {
313
+ data.indexes[dbName][collName] = indexes;
314
+ }
315
+ }
316
+ // Ensure parent directory exists
317
+ const dir = this.persistPath.substring(0, this.persistPath.lastIndexOf('/'));
318
+ if (dir) {
319
+ await this.fs.directory(dir).recursive().create();
320
+ }
321
+ await this.fs.file(this.persistPath).encoding('utf8').write(JSON.stringify(data, null, 2));
322
+ }
323
+ async restore() {
324
+ if (!this.persistPath)
325
+ return;
326
+ try {
327
+ const exists = await this.fs.file(this.persistPath).exists();
328
+ if (!exists)
329
+ return;
330
+ const content = await this.fs.file(this.persistPath).encoding('utf8').read();
331
+ const data = JSON.parse(content);
332
+ this.databases.clear();
333
+ this.indexes.clear();
334
+ for (const [dbName, collections] of Object.entries(data.databases || {})) {
335
+ const dbMap = new Map();
336
+ this.databases.set(dbName, dbMap);
337
+ for (const [collName, docs] of Object.entries(collections)) {
338
+ const collMap = new Map();
339
+ for (const doc of docs) {
340
+ // Restore ObjectId
341
+ if (doc._id && typeof doc._id === 'string') {
342
+ doc._id = new plugins.bson.ObjectId(doc._id);
343
+ }
344
+ else if (doc._id && typeof doc._id === 'object' && doc._id.$oid) {
345
+ doc._id = new plugins.bson.ObjectId(doc._id.$oid);
346
+ }
347
+ collMap.set(doc._id.toHexString(), doc);
348
+ }
349
+ dbMap.set(collName, collMap);
350
+ }
351
+ }
352
+ for (const [dbName, collIndexes] of Object.entries(data.indexes || {})) {
353
+ const indexMap = new Map();
354
+ this.indexes.set(dbName, indexMap);
355
+ for (const [collName, indexes] of Object.entries(collIndexes)) {
356
+ indexMap.set(collName, indexes);
357
+ }
358
+ }
359
+ this.opLogCounter = data.opLogCounter || 0;
360
+ }
361
+ catch (error) {
362
+ // If restore fails, start fresh
363
+ console.warn('Failed to restore from persistence:', error);
364
+ }
365
+ }
366
+ }
367
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWVtb3J5U3RvcmFnZUFkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9zdG9yYWdlL01lbW9yeVN0b3JhZ2VBZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFJL0M7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLG9CQUFvQjtJQUMvQixzQ0FBc0M7SUFDOUIsU0FBUyxHQUEyRCxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRXRGLG9DQUFvQztJQUM1QixPQUFPLEdBTVIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUVqQixnQkFBZ0I7SUFDUixLQUFLLEdBQWtCLEVBQUUsQ0FBQztJQUMxQixZQUFZLEdBQUcsQ0FBQyxDQUFDO0lBRXpCLHVCQUF1QjtJQUNmLFdBQVcsQ0FBVTtJQUNyQixlQUFlLENBQWtDO0lBQ2pELEVBQUUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7SUFFcEYsWUFBWSxPQUE4RDtRQUN4RSxJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sRUFBRSxXQUFXLENBQUM7UUFDeEMsSUFBSSxJQUFJLENBQUMsV0FBVyxJQUFJLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxDQUFDO1lBQ25ELElBQUksQ0FBQyxlQUFlLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDdEMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdEMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2hDLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLFVBQVU7UUFDZCxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQixNQUFNLElBQUksQ0FB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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 './IStorageAdapter.js';
3
3
  import type { IOpLogEntry, Document, IResumeToken, ChangeStreamOperationType } from '../types/interfaces.js';
4
4
  /**
@@ -0,0 +1,221 @@
1
+ import * as plugins from '../tsmdb.plugins.js';
2
+ /**
3
+ * Operation Log for tracking all mutations
4
+ * Used primarily for change stream support
5
+ */
6
+ export class OpLog {
7
+ storage;
8
+ counter = 0;
9
+ listeners = [];
10
+ constructor(storage) {
11
+ this.storage = storage;
12
+ }
13
+ /**
14
+ * Generate a new timestamp for oplog entries
15
+ */
16
+ generateTimestamp() {
17
+ this.counter++;
18
+ return new plugins.bson.Timestamp({ t: Math.floor(Date.now() / 1000), i: this.counter });
19
+ }
20
+ /**
21
+ * Generate a resume token from a timestamp
22
+ */
23
+ generateResumeToken(ts) {
24
+ // Create a resume token similar to MongoDB's format
25
+ // It's a base64-encoded BSON document containing the timestamp
26
+ const tokenData = {
27
+ _data: Buffer.from(JSON.stringify({
28
+ ts: { t: ts.high, i: ts.low },
29
+ version: 1,
30
+ })).toString('base64'),
31
+ };
32
+ return tokenData;
33
+ }
34
+ /**
35
+ * Parse a resume token to get the timestamp
36
+ */
37
+ parseResumeToken(token) {
38
+ try {
39
+ const data = JSON.parse(Buffer.from(token._data, 'base64').toString('utf-8'));
40
+ return new plugins.bson.Timestamp({ t: data.ts.t, i: data.ts.i });
41
+ }
42
+ catch {
43
+ throw new Error('Invalid resume token');
44
+ }
45
+ }
46
+ /**
47
+ * Record an insert operation
48
+ */
49
+ async recordInsert(dbName, collName, document, txnInfo) {
50
+ const entry = {
51
+ ts: this.generateTimestamp(),
52
+ op: 'i',
53
+ ns: `${dbName}.${collName}`,
54
+ o: document,
55
+ ...txnInfo,
56
+ };
57
+ await this.storage.appendOpLog(entry);
58
+ this.notifyListeners(entry);
59
+ return entry;
60
+ }
61
+ /**
62
+ * Record an update operation
63
+ */
64
+ async recordUpdate(dbName, collName, filter, update, txnInfo) {
65
+ const entry = {
66
+ ts: this.generateTimestamp(),
67
+ op: 'u',
68
+ ns: `${dbName}.${collName}`,
69
+ o: update,
70
+ o2: filter,
71
+ ...txnInfo,
72
+ };
73
+ await this.storage.appendOpLog(entry);
74
+ this.notifyListeners(entry);
75
+ return entry;
76
+ }
77
+ /**
78
+ * Record a delete operation
79
+ */
80
+ async recordDelete(dbName, collName, filter, txnInfo) {
81
+ const entry = {
82
+ ts: this.generateTimestamp(),
83
+ op: 'd',
84
+ ns: `${dbName}.${collName}`,
85
+ o: filter,
86
+ ...txnInfo,
87
+ };
88
+ await this.storage.appendOpLog(entry);
89
+ this.notifyListeners(entry);
90
+ return entry;
91
+ }
92
+ /**
93
+ * Record a command (drop, rename, etc.)
94
+ */
95
+ async recordCommand(dbName, command) {
96
+ const entry = {
97
+ ts: this.generateTimestamp(),
98
+ op: 'c',
99
+ ns: `${dbName}.$cmd`,
100
+ o: command,
101
+ };
102
+ await this.storage.appendOpLog(entry);
103
+ this.notifyListeners(entry);
104
+ return entry;
105
+ }
106
+ /**
107
+ * Get oplog entries after a timestamp
108
+ */
109
+ async getEntriesAfter(ts, limit) {
110
+ return this.storage.getOpLogAfter(ts, limit);
111
+ }
112
+ /**
113
+ * Get the latest timestamp
114
+ */
115
+ async getLatestTimestamp() {
116
+ return this.storage.getLatestOpLogTimestamp();
117
+ }
118
+ /**
119
+ * Subscribe to oplog changes (for change streams)
120
+ */
121
+ subscribe(listener) {
122
+ this.listeners.push(listener);
123
+ return () => {
124
+ const idx = this.listeners.indexOf(listener);
125
+ if (idx >= 0) {
126
+ this.listeners.splice(idx, 1);
127
+ }
128
+ };
129
+ }
130
+ /**
131
+ * Notify all listeners of a new entry
132
+ */
133
+ notifyListeners(entry) {
134
+ for (const listener of this.listeners) {
135
+ try {
136
+ listener(entry);
137
+ }
138
+ catch (error) {
139
+ console.error('Error in oplog listener:', error);
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Convert an oplog entry to a change stream document
145
+ */
146
+ opLogEntryToChangeEvent(entry, fullDocument, fullDocumentBeforeChange) {
147
+ const [db, coll] = entry.ns.split('.');
148
+ const resumeToken = this.generateResumeToken(entry.ts);
149
+ const baseEvent = {
150
+ _id: resumeToken,
151
+ ns: { db, coll: coll === '$cmd' ? undefined : coll },
152
+ clusterTime: entry.ts,
153
+ };
154
+ switch (entry.op) {
155
+ case 'i':
156
+ return {
157
+ ...baseEvent,
158
+ operationType: 'insert',
159
+ fullDocument: fullDocument || entry.o,
160
+ documentKey: entry.o._id ? { _id: entry.o._id } : undefined,
161
+ };
162
+ case 'u':
163
+ const updateEvent = {
164
+ ...baseEvent,
165
+ operationType: 'update',
166
+ documentKey: entry.o2?._id ? { _id: entry.o2._id } : undefined,
167
+ };
168
+ if (fullDocument) {
169
+ updateEvent.fullDocument = fullDocument;
170
+ }
171
+ if (fullDocumentBeforeChange) {
172
+ updateEvent.fullDocumentBeforeChange = fullDocumentBeforeChange;
173
+ }
174
+ // Parse update description
175
+ if (entry.o.$set || entry.o.$unset) {
176
+ updateEvent.updateDescription = {
177
+ updatedFields: entry.o.$set || {},
178
+ removedFields: entry.o.$unset ? Object.keys(entry.o.$unset) : [],
179
+ };
180
+ }
181
+ return updateEvent;
182
+ case 'd':
183
+ return {
184
+ ...baseEvent,
185
+ operationType: 'delete',
186
+ documentKey: entry.o._id ? { _id: entry.o._id } : undefined,
187
+ fullDocumentBeforeChange,
188
+ };
189
+ case 'c':
190
+ if (entry.o.drop) {
191
+ return {
192
+ ...baseEvent,
193
+ operationType: 'drop',
194
+ ns: { db, coll: entry.o.drop },
195
+ };
196
+ }
197
+ if (entry.o.dropDatabase) {
198
+ return {
199
+ ...baseEvent,
200
+ operationType: 'dropDatabase',
201
+ };
202
+ }
203
+ if (entry.o.renameCollection) {
204
+ return {
205
+ ...baseEvent,
206
+ operationType: 'rename',
207
+ };
208
+ }
209
+ return {
210
+ ...baseEvent,
211
+ operationType: 'invalidate',
212
+ };
213
+ default:
214
+ return {
215
+ ...baseEvent,
216
+ operationType: 'invalidate',
217
+ };
218
+ }
219
+ }
220
+ }
221
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3BMb2cuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c21kYi9zdG9yYWdlL09wTG9nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFJL0M7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLEtBQUs7SUFDUixPQUFPLENBQWtCO0lBQ3pCLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDWixTQUFTLEdBQXdDLEVBQUUsQ0FBQztJQUU1RCxZQUFZLE9BQXdCO1FBQ2xDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNILGlCQUFpQjtRQUNmLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNmLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsbUJBQW1CLENBQUMsRUFBMEI7UUFDNUMsb0RBQW9EO1FBQ3BELCtEQUErRDtRQUMvRCxNQUFNLFNBQVMsR0FBRztZQUNoQixLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNoQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRTtnQkFDN0IsT0FBTyxFQUFFLENBQUM7YUFDWCxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO1NBQ3ZCLENBQUM7UUFDRixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0IsQ0FBQyxLQUFt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
@@ -0,0 +1,14 @@
1
+ // @push.rocks scope
2
+ import * as smartfs from '@push.rocks/smartfs';
3
+ import * as smartpath from '@push.rocks/smartpath';
4
+ import * as smartpromise from '@push.rocks/smartpromise';
5
+ import * as smartrx from '@push.rocks/smartrx';
6
+ export { smartfs, smartpath, smartpromise, smartrx };
7
+ // thirdparty
8
+ import * as bson from 'bson';
9
+ import * as mingo from 'mingo';
10
+ export { bson, mingo };
11
+ // Re-export commonly used mingo classes
12
+ export { Query } from 'mingo';
13
+ export { Aggregator } from 'mingo';
14
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHNtZGIucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3RzbWRiL3RzbWRiLnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFFL0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBRXJELGFBQWE7QUFDYixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUUvQixPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO0FBRXZCLHdDQUF3QztBQUN4QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQzlCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxPQUFPLENBQUMifQ==