@push.rocks/smartmongo 2.2.0 → 4.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 (126) 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/{congodb → tsmdb}/engine/IndexEngine.d.ts +23 -3
  6. package/dist_ts/tsmdb/engine/IndexEngine.js +678 -0
  7. package/dist_ts/tsmdb/engine/QueryEngine.js +271 -0
  8. package/dist_ts/tsmdb/engine/QueryPlanner.d.ts +64 -0
  9. package/dist_ts/tsmdb/engine/QueryPlanner.js +308 -0
  10. package/dist_ts/tsmdb/engine/SessionEngine.d.ts +117 -0
  11. package/dist_ts/tsmdb/engine/SessionEngine.js +232 -0
  12. package/dist_ts/{congodb → tsmdb}/engine/TransactionEngine.d.ts +1 -1
  13. package/dist_ts/tsmdb/engine/TransactionEngine.js +287 -0
  14. package/dist_ts/tsmdb/engine/UpdateEngine.js +461 -0
  15. package/dist_ts/{congodb/errors/CongoErrors.d.ts → tsmdb/errors/TsmdbErrors.d.ts} +16 -16
  16. package/dist_ts/tsmdb/errors/TsmdbErrors.js +155 -0
  17. package/dist_ts/{congodb → tsmdb}/index.d.ts +11 -4
  18. package/dist_ts/tsmdb/index.js +31 -0
  19. package/dist_ts/tsmdb/server/CommandRouter.d.ts +87 -0
  20. package/dist_ts/tsmdb/server/CommandRouter.js +222 -0
  21. package/dist_ts/{congodb/server/CongoServer.d.ts → tsmdb/server/TsmdbServer.d.ts} +6 -6
  22. package/dist_ts/tsmdb/server/TsmdbServer.js +229 -0
  23. package/dist_ts/{congodb → tsmdb}/server/WireProtocol.d.ts +1 -1
  24. package/dist_ts/tsmdb/server/WireProtocol.js +298 -0
  25. package/dist_ts/{congodb → tsmdb}/server/handlers/AdminHandler.d.ts +1 -1
  26. package/dist_ts/tsmdb/server/handlers/AdminHandler.js +668 -0
  27. package/dist_ts/{congodb → tsmdb}/server/handlers/AggregateHandler.d.ts +1 -1
  28. package/dist_ts/tsmdb/server/handlers/AggregateHandler.js +277 -0
  29. package/dist_ts/{congodb → tsmdb}/server/handlers/DeleteHandler.d.ts +1 -1
  30. package/dist_ts/tsmdb/server/handlers/DeleteHandler.js +95 -0
  31. package/dist_ts/{congodb → tsmdb}/server/handlers/FindHandler.d.ts +1 -1
  32. package/dist_ts/tsmdb/server/handlers/FindHandler.js +291 -0
  33. package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.d.ts +1 -1
  34. package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.js +2 -2
  35. package/dist_ts/{congodb → tsmdb}/server/handlers/IndexHandler.d.ts +1 -1
  36. package/dist_ts/tsmdb/server/handlers/IndexHandler.js +183 -0
  37. package/dist_ts/{congodb → tsmdb}/server/handlers/InsertHandler.d.ts +1 -1
  38. package/dist_ts/tsmdb/server/handlers/InsertHandler.js +79 -0
  39. package/dist_ts/{congodb → tsmdb}/server/handlers/UpdateHandler.d.ts +1 -1
  40. package/dist_ts/tsmdb/server/handlers/UpdateHandler.js +296 -0
  41. package/dist_ts/tsmdb/server/handlers/index.js +10 -0
  42. package/dist_ts/{congodb → tsmdb}/server/index.d.ts +2 -2
  43. package/dist_ts/tsmdb/server/index.js +7 -0
  44. package/dist_ts/{congodb → tsmdb}/storage/FileStorageAdapter.d.ts +27 -3
  45. package/dist_ts/tsmdb/storage/FileStorageAdapter.js +465 -0
  46. package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.d.ts +7 -2
  47. package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.js +1 -1
  48. package/dist_ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.d.ts +3 -2
  49. package/dist_ts/tsmdb/storage/MemoryStorageAdapter.js +378 -0
  50. package/dist_ts/{congodb → tsmdb}/storage/OpLog.d.ts +1 -1
  51. package/dist_ts/tsmdb/storage/OpLog.js +221 -0
  52. package/dist_ts/tsmdb/storage/WAL.d.ts +117 -0
  53. package/dist_ts/tsmdb/storage/WAL.js +286 -0
  54. package/dist_ts/tsmdb/tsmdb.plugins.js +14 -0
  55. package/dist_ts/{congodb → tsmdb}/types/interfaces.d.ts +3 -3
  56. package/dist_ts/{congodb → tsmdb}/types/interfaces.js +1 -1
  57. package/dist_ts/tsmdb/utils/checksum.d.ts +30 -0
  58. package/dist_ts/tsmdb/utils/checksum.js +77 -0
  59. package/dist_ts/tsmdb/utils/index.d.ts +1 -0
  60. package/dist_ts/tsmdb/utils/index.js +2 -0
  61. package/package.json +1 -1
  62. package/readme.hints.md +7 -12
  63. package/readme.md +25 -25
  64. package/ts/00_commitinfo_data.ts +1 -1
  65. package/ts/index.ts +2 -2
  66. package/ts/{congodb → tsmdb}/engine/AggregationEngine.ts +1 -1
  67. package/ts/tsmdb/engine/IndexEngine.ts +798 -0
  68. package/ts/{congodb → tsmdb}/engine/QueryEngine.ts +1 -1
  69. package/ts/tsmdb/engine/QueryPlanner.ts +393 -0
  70. package/ts/tsmdb/engine/SessionEngine.ts +292 -0
  71. package/ts/{congodb → tsmdb}/engine/TransactionEngine.ts +12 -12
  72. package/ts/{congodb → tsmdb}/engine/UpdateEngine.ts +1 -1
  73. package/ts/{congodb/errors/CongoErrors.ts → tsmdb/errors/TsmdbErrors.ts} +34 -34
  74. package/ts/{congodb → tsmdb}/index.ts +16 -7
  75. package/ts/{congodb → tsmdb}/server/CommandRouter.ts +114 -5
  76. package/ts/{congodb/server/CongoServer.ts → tsmdb/server/TsmdbServer.ts} +11 -8
  77. package/ts/{congodb → tsmdb}/server/WireProtocol.ts +1 -1
  78. package/ts/{congodb → tsmdb}/server/handlers/AdminHandler.ts +116 -11
  79. package/ts/{congodb → tsmdb}/server/handlers/AggregateHandler.ts +1 -1
  80. package/ts/{congodb → tsmdb}/server/handlers/DeleteHandler.ts +18 -3
  81. package/ts/{congodb → tsmdb}/server/handlers/FindHandler.ts +43 -14
  82. package/ts/{congodb → tsmdb}/server/handlers/HelloHandler.ts +1 -1
  83. package/ts/{congodb → tsmdb}/server/handlers/IndexHandler.ts +1 -1
  84. package/ts/{congodb → tsmdb}/server/handlers/InsertHandler.ts +7 -1
  85. package/ts/{congodb → tsmdb}/server/handlers/UpdateHandler.ts +34 -5
  86. package/ts/{congodb → tsmdb}/server/index.ts +2 -2
  87. package/ts/{congodb → tsmdb}/storage/FileStorageAdapter.ts +90 -7
  88. package/ts/{congodb → tsmdb}/storage/IStorageAdapter.ts +8 -2
  89. package/ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.ts +14 -2
  90. package/ts/{congodb → tsmdb}/storage/OpLog.ts +1 -1
  91. package/ts/tsmdb/storage/WAL.ts +375 -0
  92. package/ts/{congodb → tsmdb}/types/interfaces.ts +3 -3
  93. package/ts/tsmdb/utils/checksum.ts +88 -0
  94. package/ts/tsmdb/utils/index.ts +1 -0
  95. package/dist_ts/congodb/congodb.plugins.js +0 -14
  96. package/dist_ts/congodb/engine/AggregationEngine.js +0 -189
  97. package/dist_ts/congodb/engine/IndexEngine.js +0 -376
  98. package/dist_ts/congodb/engine/QueryEngine.js +0 -271
  99. package/dist_ts/congodb/engine/TransactionEngine.js +0 -287
  100. package/dist_ts/congodb/engine/UpdateEngine.js +0 -461
  101. package/dist_ts/congodb/errors/CongoErrors.js +0 -155
  102. package/dist_ts/congodb/index.js +0 -26
  103. package/dist_ts/congodb/server/CommandRouter.d.ts +0 -51
  104. package/dist_ts/congodb/server/CommandRouter.js +0 -132
  105. package/dist_ts/congodb/server/CongoServer.js +0 -227
  106. package/dist_ts/congodb/server/WireProtocol.js +0 -298
  107. package/dist_ts/congodb/server/handlers/AdminHandler.js +0 -568
  108. package/dist_ts/congodb/server/handlers/AggregateHandler.js +0 -277
  109. package/dist_ts/congodb/server/handlers/DeleteHandler.js +0 -83
  110. package/dist_ts/congodb/server/handlers/FindHandler.js +0 -261
  111. package/dist_ts/congodb/server/handlers/IndexHandler.js +0 -183
  112. package/dist_ts/congodb/server/handlers/InsertHandler.js +0 -76
  113. package/dist_ts/congodb/server/handlers/UpdateHandler.js +0 -270
  114. package/dist_ts/congodb/server/handlers/index.js +0 -10
  115. package/dist_ts/congodb/server/index.js +0 -7
  116. package/dist_ts/congodb/storage/FileStorageAdapter.js +0 -396
  117. package/dist_ts/congodb/storage/MemoryStorageAdapter.js +0 -367
  118. package/dist_ts/congodb/storage/OpLog.js +0 -221
  119. package/ts/congodb/engine/IndexEngine.ts +0 -479
  120. /package/dist_ts/{congodb → tsmdb}/engine/AggregationEngine.d.ts +0 -0
  121. /package/dist_ts/{congodb → tsmdb}/engine/QueryEngine.d.ts +0 -0
  122. /package/dist_ts/{congodb → tsmdb}/engine/UpdateEngine.d.ts +0 -0
  123. /package/dist_ts/{congodb → tsmdb}/server/handlers/index.d.ts +0 -0
  124. /package/dist_ts/{congodb/congodb.plugins.d.ts → tsmdb/tsmdb.plugins.d.ts} +0 -0
  125. /package/ts/{congodb → tsmdb}/server/handlers/index.ts +0 -0
  126. /package/ts/{congodb/congodb.plugins.ts → tsmdb/tsmdb.plugins.ts} +0 -0
@@ -1,9 +1,9 @@
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 { IStoredDocument, IOpLogEntry, Document } from '../types/interfaces.js';
4
4
 
5
5
  /**
6
- * In-memory storage adapter for CongoDB
6
+ * In-memory storage adapter for TsmDB
7
7
  * Optionally supports persistence to a file
8
8
  */
9
9
  export class MemoryStorageAdapter implements IStorageAdapter {
@@ -196,6 +196,18 @@ export class MemoryStorageAdapter implements IStorageAdapter {
196
196
  return Array.from(collection.values());
197
197
  }
198
198
 
199
+ async findByIds(dbName: string, collName: string, ids: Set<string>): Promise<IStoredDocument[]> {
200
+ const collection = this.ensureCollection(dbName, collName);
201
+ const results: IStoredDocument[] = [];
202
+ for (const id of ids) {
203
+ const doc = collection.get(id);
204
+ if (doc) {
205
+ results.push(doc);
206
+ }
207
+ }
208
+ return results;
209
+ }
210
+
199
211
  async findById(dbName: string, collName: string, id: plugins.bson.ObjectId): Promise<IStoredDocument | null> {
200
212
  const collection = this.ensureCollection(dbName, collName);
201
213
  return collection.get(id.toHexString()) || null;
@@ -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,375 @@
1
+ import * as plugins from '../tsmdb.plugins.js';
2
+ import type { Document, IStoredDocument } from '../types/interfaces.js';
3
+
4
+ /**
5
+ * WAL entry operation types
6
+ */
7
+ export type TWalOperation = 'insert' | 'update' | 'delete' | 'checkpoint' | 'begin' | 'commit' | 'abort';
8
+
9
+ /**
10
+ * WAL entry structure
11
+ */
12
+ export interface IWalEntry {
13
+ /** Log Sequence Number - monotonically increasing */
14
+ lsn: number;
15
+ /** Timestamp of the operation */
16
+ timestamp: number;
17
+ /** Operation type */
18
+ operation: TWalOperation;
19
+ /** Database name */
20
+ dbName: string;
21
+ /** Collection name */
22
+ collName: string;
23
+ /** Document ID (hex string) */
24
+ documentId: string;
25
+ /** Document data (BSON serialized, base64 encoded) */
26
+ data?: string;
27
+ /** Previous document data for updates (for rollback) */
28
+ previousData?: string;
29
+ /** Transaction ID if part of a transaction */
30
+ txnId?: string;
31
+ /** CRC32 checksum of the entry (excluding this field) */
32
+ checksum: number;
33
+ }
34
+
35
+ /**
36
+ * Checkpoint record
37
+ */
38
+ interface ICheckpointRecord {
39
+ lsn: number;
40
+ timestamp: number;
41
+ lastCommittedLsn: number;
42
+ }
43
+
44
+ /**
45
+ * Write-Ahead Log (WAL) for durability and crash recovery
46
+ *
47
+ * The WAL ensures durability by writing operations to a log file before
48
+ * they are applied to the main storage. On crash recovery, uncommitted
49
+ * operations can be replayed to restore the database to a consistent state.
50
+ */
51
+ export class WAL {
52
+ private walPath: string;
53
+ private currentLsn: number = 0;
54
+ private lastCheckpointLsn: number = 0;
55
+ private entries: IWalEntry[] = [];
56
+ private isInitialized: boolean = false;
57
+ private fs = new plugins.smartfs.SmartFs(new plugins.smartfs.SmartFsProviderNode());
58
+
59
+ // In-memory uncommitted entries per transaction
60
+ private uncommittedTxns: Map<string, IWalEntry[]> = new Map();
61
+
62
+ // Checkpoint interval (number of entries between checkpoints)
63
+ private checkpointInterval: number = 1000;
64
+
65
+ constructor(walPath: string, options?: { checkpointInterval?: number }) {
66
+ this.walPath = walPath;
67
+ if (options?.checkpointInterval) {
68
+ this.checkpointInterval = options.checkpointInterval;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Initialize the WAL, loading existing entries and recovering if needed
74
+ */
75
+ async initialize(): Promise<{ recoveredEntries: IWalEntry[] }> {
76
+ if (this.isInitialized) {
77
+ return { recoveredEntries: [] };
78
+ }
79
+
80
+ // Ensure WAL directory exists
81
+ const walDir = this.walPath.substring(0, this.walPath.lastIndexOf('/'));
82
+ if (walDir) {
83
+ await this.fs.directory(walDir).recursive().create();
84
+ }
85
+
86
+ // Try to load existing WAL
87
+ const exists = await this.fs.file(this.walPath).exists();
88
+ if (exists) {
89
+ const content = await this.fs.file(this.walPath).encoding('utf8').read();
90
+ const lines = (content as string).split('\n').filter(line => line.trim());
91
+
92
+ for (const line of lines) {
93
+ try {
94
+ const entry = JSON.parse(line) as IWalEntry;
95
+ // Verify checksum
96
+ if (this.verifyChecksum(entry)) {
97
+ this.entries.push(entry);
98
+ if (entry.lsn > this.currentLsn) {
99
+ this.currentLsn = entry.lsn;
100
+ }
101
+ if (entry.operation === 'checkpoint') {
102
+ this.lastCheckpointLsn = entry.lsn;
103
+ }
104
+ }
105
+ } catch {
106
+ // Skip corrupted entries
107
+ console.warn('Skipping corrupted WAL entry');
108
+ }
109
+ }
110
+ }
111
+
112
+ this.isInitialized = true;
113
+
114
+ // Return entries after last checkpoint that need recovery
115
+ const recoveredEntries = this.entries.filter(
116
+ e => e.lsn > this.lastCheckpointLsn &&
117
+ (e.operation === 'insert' || e.operation === 'update' || e.operation === 'delete')
118
+ );
119
+
120
+ return { recoveredEntries };
121
+ }
122
+
123
+ /**
124
+ * Log an insert operation
125
+ */
126
+ async logInsert(dbName: string, collName: string, doc: IStoredDocument, txnId?: string): Promise<number> {
127
+ return this.appendEntry({
128
+ operation: 'insert',
129
+ dbName,
130
+ collName,
131
+ documentId: doc._id.toHexString(),
132
+ data: this.serializeDocument(doc),
133
+ txnId,
134
+ });
135
+ }
136
+
137
+ /**
138
+ * Log an update operation
139
+ */
140
+ async logUpdate(
141
+ dbName: string,
142
+ collName: string,
143
+ oldDoc: IStoredDocument,
144
+ newDoc: IStoredDocument,
145
+ txnId?: string
146
+ ): Promise<number> {
147
+ return this.appendEntry({
148
+ operation: 'update',
149
+ dbName,
150
+ collName,
151
+ documentId: oldDoc._id.toHexString(),
152
+ data: this.serializeDocument(newDoc),
153
+ previousData: this.serializeDocument(oldDoc),
154
+ txnId,
155
+ });
156
+ }
157
+
158
+ /**
159
+ * Log a delete operation
160
+ */
161
+ async logDelete(dbName: string, collName: string, doc: IStoredDocument, txnId?: string): Promise<number> {
162
+ return this.appendEntry({
163
+ operation: 'delete',
164
+ dbName,
165
+ collName,
166
+ documentId: doc._id.toHexString(),
167
+ previousData: this.serializeDocument(doc),
168
+ txnId,
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Log transaction begin
174
+ */
175
+ async logBeginTransaction(txnId: string): Promise<number> {
176
+ this.uncommittedTxns.set(txnId, []);
177
+ return this.appendEntry({
178
+ operation: 'begin',
179
+ dbName: '',
180
+ collName: '',
181
+ documentId: '',
182
+ txnId,
183
+ });
184
+ }
185
+
186
+ /**
187
+ * Log transaction commit
188
+ */
189
+ async logCommitTransaction(txnId: string): Promise<number> {
190
+ this.uncommittedTxns.delete(txnId);
191
+ return this.appendEntry({
192
+ operation: 'commit',
193
+ dbName: '',
194
+ collName: '',
195
+ documentId: '',
196
+ txnId,
197
+ });
198
+ }
199
+
200
+ /**
201
+ * Log transaction abort
202
+ */
203
+ async logAbortTransaction(txnId: string): Promise<number> {
204
+ this.uncommittedTxns.delete(txnId);
205
+ return this.appendEntry({
206
+ operation: 'abort',
207
+ dbName: '',
208
+ collName: '',
209
+ documentId: '',
210
+ txnId,
211
+ });
212
+ }
213
+
214
+ /**
215
+ * Get entries to roll back for an aborted transaction
216
+ */
217
+ getTransactionEntries(txnId: string): IWalEntry[] {
218
+ return this.entries.filter(e => e.txnId === txnId);
219
+ }
220
+
221
+ /**
222
+ * Create a checkpoint - marks a consistent point in the log
223
+ */
224
+ async checkpoint(): Promise<number> {
225
+ const lsn = await this.appendEntry({
226
+ operation: 'checkpoint',
227
+ dbName: '',
228
+ collName: '',
229
+ documentId: '',
230
+ });
231
+ this.lastCheckpointLsn = lsn;
232
+
233
+ // Truncate old entries (keep only entries after checkpoint)
234
+ await this.truncate();
235
+
236
+ return lsn;
237
+ }
238
+
239
+ /**
240
+ * Truncate the WAL file, removing entries before the last checkpoint
241
+ */
242
+ private async truncate(): Promise<void> {
243
+ // Keep entries after last checkpoint
244
+ const newEntries = this.entries.filter(e => e.lsn >= this.lastCheckpointLsn);
245
+ this.entries = newEntries;
246
+
247
+ // Rewrite the WAL file
248
+ const lines = this.entries.map(e => JSON.stringify(e)).join('\n');
249
+ await this.fs.file(this.walPath).encoding('utf8').write(lines);
250
+ }
251
+
252
+ /**
253
+ * Get current LSN
254
+ */
255
+ getCurrentLsn(): number {
256
+ return this.currentLsn;
257
+ }
258
+
259
+ /**
260
+ * Get entries after a specific LSN (for recovery)
261
+ */
262
+ getEntriesAfter(lsn: number): IWalEntry[] {
263
+ return this.entries.filter(e => e.lsn > lsn);
264
+ }
265
+
266
+ /**
267
+ * Close the WAL
268
+ */
269
+ async close(): Promise<void> {
270
+ if (this.isInitialized) {
271
+ // Final checkpoint before close
272
+ await this.checkpoint();
273
+ }
274
+ this.isInitialized = false;
275
+ }
276
+
277
+ // ============================================================================
278
+ // Private Methods
279
+ // ============================================================================
280
+
281
+ private async appendEntry(
282
+ partial: Omit<IWalEntry, 'lsn' | 'timestamp' | 'checksum'>
283
+ ): Promise<number> {
284
+ await this.initialize();
285
+
286
+ this.currentLsn++;
287
+ const entry: IWalEntry = {
288
+ ...partial,
289
+ lsn: this.currentLsn,
290
+ timestamp: Date.now(),
291
+ checksum: 0, // Will be calculated
292
+ };
293
+
294
+ // Calculate checksum
295
+ entry.checksum = this.calculateChecksum(entry);
296
+
297
+ // Track in transaction if applicable
298
+ if (partial.txnId && this.uncommittedTxns.has(partial.txnId)) {
299
+ this.uncommittedTxns.get(partial.txnId)!.push(entry);
300
+ }
301
+
302
+ // Add to in-memory log
303
+ this.entries.push(entry);
304
+
305
+ // Append to file (append mode for durability)
306
+ await this.fs.file(this.walPath).encoding('utf8').append(JSON.stringify(entry) + '\n');
307
+
308
+ // Check if we need a checkpoint
309
+ if (this.entries.length - this.lastCheckpointLsn >= this.checkpointInterval) {
310
+ await this.checkpoint();
311
+ }
312
+
313
+ return entry.lsn;
314
+ }
315
+
316
+ private serializeDocument(doc: Document): string {
317
+ // Serialize document to BSON and encode as base64
318
+ const bsonData = plugins.bson.serialize(doc);
319
+ return Buffer.from(bsonData).toString('base64');
320
+ }
321
+
322
+ private deserializeDocument(data: string): Document {
323
+ // Decode base64 and deserialize from BSON
324
+ const buffer = Buffer.from(data, 'base64');
325
+ return plugins.bson.deserialize(buffer);
326
+ }
327
+
328
+ private calculateChecksum(entry: IWalEntry): number {
329
+ // Simple CRC32-like checksum
330
+ const str = JSON.stringify({
331
+ lsn: entry.lsn,
332
+ timestamp: entry.timestamp,
333
+ operation: entry.operation,
334
+ dbName: entry.dbName,
335
+ collName: entry.collName,
336
+ documentId: entry.documentId,
337
+ data: entry.data,
338
+ previousData: entry.previousData,
339
+ txnId: entry.txnId,
340
+ });
341
+
342
+ let crc = 0xFFFFFFFF;
343
+ for (let i = 0; i < str.length; i++) {
344
+ crc ^= str.charCodeAt(i);
345
+ for (let j = 0; j < 8; j++) {
346
+ crc = (crc >>> 1) ^ (crc & 1 ? 0xEDB88320 : 0);
347
+ }
348
+ }
349
+ return (~crc) >>> 0;
350
+ }
351
+
352
+ private verifyChecksum(entry: IWalEntry): boolean {
353
+ const savedChecksum = entry.checksum;
354
+ entry.checksum = 0;
355
+ const calculatedChecksum = this.calculateChecksum(entry);
356
+ entry.checksum = savedChecksum;
357
+ return calculatedChecksum === savedChecksum;
358
+ }
359
+
360
+ /**
361
+ * Recover document from WAL entry
362
+ */
363
+ recoverDocument(entry: IWalEntry): IStoredDocument | null {
364
+ if (!entry.data) return null;
365
+ return this.deserializeDocument(entry.data) as IStoredDocument;
366
+ }
367
+
368
+ /**
369
+ * Recover previous document state from WAL entry (for rollback)
370
+ */
371
+ recoverPreviousDocument(entry: IWalEntry): IStoredDocument | null {
372
+ if (!entry.previousData) return null;
373
+ return this.deserializeDocument(entry.previousData) as IStoredDocument;
374
+ }
375
+ }
@@ -1,4 +1,4 @@
1
- import type * as plugins from '../congodb.plugins.js';
1
+ import type * as plugins from '../tsmdb.plugins.js';
2
2
 
3
3
  // ============================================================================
4
4
  // Document Types
@@ -14,7 +14,7 @@ export interface WithId<TSchema> {
14
14
  // Client Options
15
15
  // ============================================================================
16
16
 
17
- export interface ICongoClientOptions {
17
+ export interface ITsmdbClientOptions {
18
18
  /** Storage adapter type: 'memory' or 'file' */
19
19
  storageType?: 'memory' | 'file';
20
20
  /** Path for file-based storage */
@@ -30,7 +30,7 @@ export interface ICongoClientOptions {
30
30
  // ============================================================================
31
31
 
32
32
  export interface IParsedConnectionString {
33
- protocol: 'congo';
33
+ protocol: 'tsmdb';
34
34
  storageType: 'memory' | 'file';
35
35
  options: {
36
36
  persist?: string;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * CRC32 checksum utilities for data integrity
3
+ */
4
+
5
+ // CRC32 lookup table
6
+ const CRC32_TABLE: number[] = [];
7
+
8
+ // Initialize the CRC32 table
9
+ function initCRC32Table(): void {
10
+ if (CRC32_TABLE.length > 0) return;
11
+
12
+ for (let i = 0; i < 256; i++) {
13
+ let crc = i;
14
+ for (let j = 0; j < 8; j++) {
15
+ crc = (crc & 1) ? (0xEDB88320 ^ (crc >>> 1)) : (crc >>> 1);
16
+ }
17
+ CRC32_TABLE[i] = crc >>> 0;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Calculate CRC32 checksum for a string
23
+ */
24
+ export function calculateCRC32(data: string): number {
25
+ initCRC32Table();
26
+
27
+ let crc = 0xFFFFFFFF;
28
+ for (let i = 0; i < data.length; i++) {
29
+ const byte = data.charCodeAt(i) & 0xFF;
30
+ crc = CRC32_TABLE[(crc ^ byte) & 0xFF] ^ (crc >>> 8);
31
+ }
32
+ return (~crc) >>> 0;
33
+ }
34
+
35
+ /**
36
+ * Calculate CRC32 checksum for a Buffer
37
+ */
38
+ export function calculateCRC32Buffer(data: Buffer): number {
39
+ initCRC32Table();
40
+
41
+ let crc = 0xFFFFFFFF;
42
+ for (let i = 0; i < data.length; i++) {
43
+ crc = CRC32_TABLE[(crc ^ data[i]) & 0xFF] ^ (crc >>> 8);
44
+ }
45
+ return (~crc) >>> 0;
46
+ }
47
+
48
+ /**
49
+ * Calculate checksum for a document (serialized as JSON)
50
+ */
51
+ export function calculateDocumentChecksum(doc: Record<string, any>): number {
52
+ // Exclude _checksum field from calculation
53
+ const { _checksum, ...docWithoutChecksum } = doc;
54
+ const json = JSON.stringify(docWithoutChecksum);
55
+ return calculateCRC32(json);
56
+ }
57
+
58
+ /**
59
+ * Add checksum to a document
60
+ */
61
+ export function addChecksum<T extends Record<string, any>>(doc: T): T & { _checksum: number } {
62
+ const checksum = calculateDocumentChecksum(doc);
63
+ return { ...doc, _checksum: checksum };
64
+ }
65
+
66
+ /**
67
+ * Verify checksum of a document
68
+ * Returns true if checksum is valid or if document has no checksum
69
+ */
70
+ export function verifyChecksum(doc: Record<string, any>): boolean {
71
+ if (!('_checksum' in doc)) {
72
+ // No checksum to verify
73
+ return true;
74
+ }
75
+
76
+ const storedChecksum = doc._checksum;
77
+ const calculatedChecksum = calculateDocumentChecksum(doc);
78
+
79
+ return storedChecksum === calculatedChecksum;
80
+ }
81
+
82
+ /**
83
+ * Remove checksum from a document
84
+ */
85
+ export function removeChecksum<T extends Record<string, any>>(doc: T): Omit<T, '_checksum'> {
86
+ const { _checksum, ...docWithoutChecksum } = doc;
87
+ return docWithoutChecksum as Omit<T, '_checksum'>;
88
+ }
@@ -0,0 +1 @@
1
+ export * from './checksum.js';
@@ -1,14 +0,0 @@
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZ29kYi5wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY29uZ29kYi9jb25nb2RiLnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFFL0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBRXJELGFBQWE7QUFDYixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUUvQixPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO0FBRXZCLHdDQUF3QztBQUN4QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQzlCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxPQUFPLENBQUMifQ==