mongolite-ts 0.4.0 → 0.6.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.
- package/README.md +223 -0
- package/dist/bin/mongolite-debug.js +2 -2
- package/dist/bin/mongolite-debug.js.map +1 -1
- package/dist/changeStream.d.ts +114 -0
- package/dist/changeStream.js +338 -0
- package/dist/changeStream.js.map +1 -0
- package/dist/collection.d.ts +26 -0
- package/dist/collection.js +188 -9
- package/dist/collection.js.map +1 -1
- package/dist/cursors/findCursor.js +112 -5
- package/dist/cursors/findCursor.js.map +1 -1
- package/dist/database-manager.d.ts +1 -0
- package/dist/database-manager.js +2 -0
- package/dist/database-manager.js.map +1 -0
- package/dist/debugger/query-debugger.js +2 -2
- package/dist/debugger/query-debugger.js.map +1 -1
- package/dist/document-utils.d.ts +34 -0
- package/dist/document-utils.js +101 -0
- package/dist/document-utils.js.map +1 -0
- package/dist/find-cursor.d.ts +51 -0
- package/dist/find-cursor.js +204 -0
- package/dist/find-cursor.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/plugins/mongodbSync.d.ts +128 -0
- package/dist/plugins/mongodbSync.js +339 -0
- package/dist/plugins/mongodbSync.js.map +1 -0
- package/dist/query-builder.d.ts +18 -0
- package/dist/query-builder.js +358 -0
- package/dist/query-builder.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/update-operations.d.ts +17 -0
- package/dist/update-operations.js +147 -0
- package/dist/update-operations.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,49 @@ A MongoDB-like client that uses SQLite as its underlying persistent store. Writt
|
|
|
16
16
|
* Written in TypeScript with strong typing.
|
|
17
17
|
* 100% test coverage (aiming for).
|
|
18
18
|
* **Interactive Query Debugger** - Debug complex queries with `npx mongolite-debug`
|
|
19
|
+
* **JSON Safety & Data Integrity** - Comprehensive protection against malformed JSON and data corruption
|
|
20
|
+
* **Change Streams** - Real-time change tracking similar to MongoDB's `changeStream = collection.watch()`
|
|
21
|
+
|
|
22
|
+
## JSON Safety & Data Integrity
|
|
23
|
+
|
|
24
|
+
MongoLite includes robust safeguards to prevent and handle malformed JSON data that could cause application failures or data corruption:
|
|
25
|
+
|
|
26
|
+
### Document Validation
|
|
27
|
+
- **Pre-storage validation**: Automatically validates documents before insertion to prevent storing invalid data
|
|
28
|
+
- **Type safety**: Rejects non-JSON-serializable data (functions, symbols, BigInt, RegExp, circular references)
|
|
29
|
+
- **Round-trip verification**: Ensures all data can be safely stored and retrieved
|
|
30
|
+
|
|
31
|
+
### Malformed JSON Recovery
|
|
32
|
+
- **Graceful degradation**: Handles corrupted JSON data without crashing your application
|
|
33
|
+
- **Automatic recovery**: Attempts to fix common JSON corruption issues (escaped quotes, backslashes)
|
|
34
|
+
- **Fallback objects**: Returns special marker objects for unrecoverable data with debugging information
|
|
35
|
+
- **Error logging**: Detailed logging for debugging and monitoring data integrity issues
|
|
36
|
+
|
|
37
|
+
### Example Usage
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// Document validation prevents invalid data
|
|
41
|
+
try {
|
|
42
|
+
await collection.insertOne({
|
|
43
|
+
name: 'user',
|
|
44
|
+
invalidFunction: () => 'not allowed' // This will be rejected
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.log('Validation error:', error.message);
|
|
48
|
+
// "Cannot insert document: Document validation failed: Functions are not allowed in documents"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Corrupted data recovery
|
|
52
|
+
const doc = await collection.findOne({ _id: 'some-id' });
|
|
53
|
+
if (doc && '__mongoLiteCorrupted' in doc) {
|
|
54
|
+
console.log('Found corrupted document');
|
|
55
|
+
console.log('Original data:', doc.__originalData);
|
|
56
|
+
console.log('Error details:', doc.__error);
|
|
57
|
+
// Handle corruption appropriately
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For detailed information about JSON safety features, see [JSON_SAFETY.md](./docs/JSON_SAFETY.md).
|
|
19
62
|
|
|
20
63
|
## Installation
|
|
21
64
|
|
|
@@ -113,6 +156,154 @@ async function main() {
|
|
|
113
156
|
main();
|
|
114
157
|
```
|
|
115
158
|
|
|
159
|
+
## Change Streams
|
|
160
|
+
|
|
161
|
+
MongoLite supports real-time change tracking through change streams, similar to MongoDB's `collection.watch()` feature. Change streams allow you to monitor and react to data changes (inserts, updates, deletes) in real-time.
|
|
162
|
+
|
|
163
|
+
### Basic Usage
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { MongoLite } from 'mongolite-ts';
|
|
167
|
+
|
|
168
|
+
const client = new MongoLite('./mydatabase.sqlite');
|
|
169
|
+
const collection = client.collection('users');
|
|
170
|
+
|
|
171
|
+
// Create a change stream
|
|
172
|
+
const changeStream = collection.watch({
|
|
173
|
+
fullDocument: 'updateLookup', // Include full document on updates
|
|
174
|
+
fullDocumentBeforeChange: 'whenAvailable' // Include document before change
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Listen for changes
|
|
178
|
+
changeStream.on('change', (change) => {
|
|
179
|
+
console.log('Change detected:', {
|
|
180
|
+
operation: change.operationType, // 'insert', 'update', 'delete'
|
|
181
|
+
documentId: change.documentKey._id,
|
|
182
|
+
collection: change.ns.coll,
|
|
183
|
+
timestamp: change.clusterTime
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (change.fullDocument) {
|
|
187
|
+
console.log('New document state:', change.fullDocument);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (change.updateDescription) {
|
|
191
|
+
console.log('Updated fields:', change.updateDescription.updatedFields);
|
|
192
|
+
console.log('Removed fields:', change.updateDescription.removedFields);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Handle errors
|
|
197
|
+
changeStream.on('error', (error) => {
|
|
198
|
+
console.error('Change stream error:', error);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Perform operations - changes will be captured
|
|
202
|
+
await collection.insertOne({ name: 'Alice', age: 30 });
|
|
203
|
+
await collection.updateOne({ name: 'Alice' }, { $set: { age: 31 } });
|
|
204
|
+
await collection.deleteOne({ name: 'Alice' });
|
|
205
|
+
|
|
206
|
+
// Close the change stream when done
|
|
207
|
+
changeStream.close();
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Async Iteration
|
|
211
|
+
|
|
212
|
+
Change streams support async iteration for a more declarative approach:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const changeStream = collection.watch();
|
|
216
|
+
|
|
217
|
+
// Use async iteration
|
|
218
|
+
for await (const change of changeStream) {
|
|
219
|
+
console.log('Change detected:', change.operationType);
|
|
220
|
+
|
|
221
|
+
// Process the change...
|
|
222
|
+
|
|
223
|
+
// Break after processing some changes
|
|
224
|
+
if (someCondition) {
|
|
225
|
+
changeStream.close();
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Change Stream Options
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
interface ChangeStreamOptions {
|
|
235
|
+
// Filter to apply to change events
|
|
236
|
+
filter?: Filter<ChangeStreamDocument>;
|
|
237
|
+
|
|
238
|
+
// Whether to include the full document in insert and update operations
|
|
239
|
+
fullDocument?: 'default' | 'updateLookup' | 'whenAvailable' | 'required';
|
|
240
|
+
|
|
241
|
+
// Whether to include the full document before the change
|
|
242
|
+
fullDocumentBeforeChange?: 'off' | 'whenAvailable' | 'required';
|
|
243
|
+
|
|
244
|
+
// Maximum number of events to buffer
|
|
245
|
+
maxBufferSize?: number;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Example with options
|
|
249
|
+
const changeStream = collection.watch({
|
|
250
|
+
fullDocument: 'updateLookup',
|
|
251
|
+
fullDocumentBeforeChange: 'whenAvailable',
|
|
252
|
+
maxBufferSize: 500
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Change Document Structure
|
|
257
|
+
|
|
258
|
+
Each change event contains detailed information about the operation:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
interface ChangeStreamDocument {
|
|
262
|
+
_id: string; // Unique change event ID
|
|
263
|
+
operationType: 'insert' | 'update' | 'delete' | 'replace';
|
|
264
|
+
clusterTime?: Date; // Timestamp of the change
|
|
265
|
+
fullDocument?: T; // Full document (based on options)
|
|
266
|
+
fullDocumentBeforeChange?: T; // Document before change (based on options)
|
|
267
|
+
documentKey: { _id: string }; // ID of the affected document
|
|
268
|
+
ns: { // Namespace information
|
|
269
|
+
db: string; // Database name
|
|
270
|
+
coll: string; // Collection name
|
|
271
|
+
};
|
|
272
|
+
updateDescription?: { // Update details (for update operations)
|
|
273
|
+
updatedFields: Record<string, unknown>;
|
|
274
|
+
removedFields: string[];
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Implementation Details
|
|
280
|
+
|
|
281
|
+
- **SQLite Triggers**: Uses SQLite triggers to capture changes automatically
|
|
282
|
+
- **Change Log Table**: Stores change events in a dedicated `__mongolite_changes__` table
|
|
283
|
+
- **Polling**: Efficiently polls for new changes every 100ms
|
|
284
|
+
- **Cleanup**: Automatically cleans up triggers when change streams are closed
|
|
285
|
+
- **Error Handling**: Robust error handling for database operations and malformed data
|
|
286
|
+
|
|
287
|
+
### Best Practices
|
|
288
|
+
|
|
289
|
+
1. **Close Change Streams**: Always close change streams when done to free resources
|
|
290
|
+
2. **Error Handling**: Implement proper error handling for change stream events
|
|
291
|
+
3. **Buffer Management**: Consider the `maxBufferSize` option for high-volume scenarios
|
|
292
|
+
4. **Cleanup**: Call `changeStream.cleanup()` to remove triggers if needed
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Proper cleanup
|
|
296
|
+
try {
|
|
297
|
+
const changeStream = collection.watch();
|
|
298
|
+
|
|
299
|
+
// ... use change stream
|
|
300
|
+
|
|
301
|
+
} finally {
|
|
302
|
+
changeStream.close();
|
|
303
|
+
await changeStream.cleanup(); // Remove triggers if needed
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
116
307
|
## Query Debugger
|
|
117
308
|
|
|
118
309
|
MongoLite includes an interactive query debugger to help you debug complex queries and understand how MongoDB-style filters are converted to SQL.
|
|
@@ -214,6 +405,38 @@ Deletes a single document matching the filter.
|
|
|
214
405
|
* `filter`: The selection criteria for the deletion.
|
|
215
406
|
* Returns `DeleteResult`: `{ acknowledged: boolean; deletedCount: number; }`.
|
|
216
407
|
|
|
408
|
+
#### `watch(options?: ChangeStreamOptions<T>): ChangeStream<T>`
|
|
409
|
+
|
|
410
|
+
Opens a change stream to watch for changes on this collection. Returns a ChangeStream that emits events when documents are inserted, updated, or deleted.
|
|
411
|
+
|
|
412
|
+
* `options`: Optional configuration for the change stream
|
|
413
|
+
* `fullDocument`: Controls when to include the full document ('default', 'updateLookup', 'whenAvailable', 'required')
|
|
414
|
+
* `fullDocumentBeforeChange`: Controls when to include the document before change ('off', 'whenAvailable', 'required')
|
|
415
|
+
* `maxBufferSize`: Maximum number of events to buffer (default: 1000)
|
|
416
|
+
* Returns a `ChangeStream` instance that extends EventEmitter and supports async iteration.
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
// Basic change stream
|
|
420
|
+
const changeStream = collection.watch();
|
|
421
|
+
changeStream.on('change', (change) => {
|
|
422
|
+
console.log('Change detected:', change);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// With options
|
|
426
|
+
const changeStream = collection.watch({
|
|
427
|
+
fullDocument: 'updateLookup',
|
|
428
|
+
fullDocumentBeforeChange: 'whenAvailable'
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
// Async iteration
|
|
432
|
+
for await (const change of changeStream) {
|
|
433
|
+
console.log('Change:', change.operationType);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Always close when done
|
|
437
|
+
changeStream.close();
|
|
438
|
+
```
|
|
439
|
+
|
|
217
440
|
|
|
218
441
|
### `FindCursor<T>`
|
|
219
442
|
|
|
@@ -71,7 +71,7 @@ async function main() {
|
|
|
71
71
|
'database.db',
|
|
72
72
|
'database.sqlite',
|
|
73
73
|
'app.db',
|
|
74
|
-
'app.sqlite'
|
|
74
|
+
'app.sqlite',
|
|
75
75
|
];
|
|
76
76
|
// Check if any common database files exist
|
|
77
77
|
const { existsSync } = await import('fs');
|
|
@@ -108,7 +108,7 @@ async function main() {
|
|
|
108
108
|
process.exit(1);
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
main().catch(error => {
|
|
111
|
+
main().catch((error) => {
|
|
112
112
|
console.error('Unexpected error:', error);
|
|
113
113
|
process.exit(1);
|
|
114
114
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongolite-debug.js","sourceRoot":"","sources":["../../src/bin/mongolite-debug.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"mongolite-debug.js","sourceRoot":"","sources":["../../src/bin/mongolite-debug.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { SQLiteDB } from './db.js';
|
|
3
|
+
import { DocumentWithId, Filter } from './types.js';
|
|
4
|
+
export type ChangeOperationType = 'insert' | 'update' | 'delete' | 'replace';
|
|
5
|
+
export interface ChangeStreamDocument<T extends DocumentWithId = DocumentWithId> {
|
|
6
|
+
_id: string;
|
|
7
|
+
operationType: ChangeOperationType;
|
|
8
|
+
clusterTime?: Date;
|
|
9
|
+
fullDocument?: T;
|
|
10
|
+
fullDocumentBeforeChange?: T;
|
|
11
|
+
documentKey: {
|
|
12
|
+
_id: string;
|
|
13
|
+
};
|
|
14
|
+
ns: {
|
|
15
|
+
db: string;
|
|
16
|
+
coll: string;
|
|
17
|
+
};
|
|
18
|
+
updateDescription?: {
|
|
19
|
+
updatedFields: Record<string, unknown>;
|
|
20
|
+
removedFields: string[];
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface ChangeStreamOptions<T extends DocumentWithId = DocumentWithId> {
|
|
24
|
+
/**
|
|
25
|
+
* Filter to apply to change events
|
|
26
|
+
*/
|
|
27
|
+
filter?: Filter<ChangeStreamDocument<T>>;
|
|
28
|
+
/**
|
|
29
|
+
* Whether to include the full document in insert and update operations
|
|
30
|
+
*/
|
|
31
|
+
fullDocument?: 'default' | 'updateLookup' | 'whenAvailable' | 'required';
|
|
32
|
+
/**
|
|
33
|
+
* Whether to include the full document before the change for update operations
|
|
34
|
+
*/
|
|
35
|
+
fullDocumentBeforeChange?: 'off' | 'whenAvailable' | 'required';
|
|
36
|
+
/**
|
|
37
|
+
* Resume token for resuming change streams (not implemented in this version)
|
|
38
|
+
*/
|
|
39
|
+
resumeAfter?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Maximum number of events to buffer
|
|
42
|
+
*/
|
|
43
|
+
maxBufferSize?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare class ChangeStream<T extends DocumentWithId = DocumentWithId> extends EventEmitter {
|
|
46
|
+
private readonly db;
|
|
47
|
+
private readonly collectionName;
|
|
48
|
+
private readonly options;
|
|
49
|
+
private closed;
|
|
50
|
+
private pollInterval;
|
|
51
|
+
private lastProcessedId;
|
|
52
|
+
private buffer;
|
|
53
|
+
private readonly maxBufferSize;
|
|
54
|
+
constructor(db: SQLiteDB, collectionName: string, options?: ChangeStreamOptions<T>);
|
|
55
|
+
/**
|
|
56
|
+
* Sets up the change tracking infrastructure
|
|
57
|
+
*/
|
|
58
|
+
private setupChangeTracking;
|
|
59
|
+
/**
|
|
60
|
+
* Creates the change log table if it doesn't exist
|
|
61
|
+
*/
|
|
62
|
+
private ensureChangeLogTable;
|
|
63
|
+
/**
|
|
64
|
+
* Sets up triggers for tracking changes on the collection
|
|
65
|
+
*/
|
|
66
|
+
private setupTriggers;
|
|
67
|
+
/**
|
|
68
|
+
* Starts polling for new changes
|
|
69
|
+
*/
|
|
70
|
+
private startPolling;
|
|
71
|
+
/**
|
|
72
|
+
* Polls for new changes from the change log
|
|
73
|
+
*/
|
|
74
|
+
private pollForChanges;
|
|
75
|
+
/**
|
|
76
|
+
* Transforms a raw change event from the database into a ChangeStreamDocument
|
|
77
|
+
*/
|
|
78
|
+
private transformChangeEvent;
|
|
79
|
+
/**
|
|
80
|
+
* Computes the update description by comparing before and after documents
|
|
81
|
+
*/
|
|
82
|
+
private computeUpdateDescription;
|
|
83
|
+
/**
|
|
84
|
+
* Determines if the full document should be included
|
|
85
|
+
*/
|
|
86
|
+
private shouldIncludeFullDocument;
|
|
87
|
+
/**
|
|
88
|
+
* Determines if the full document before change should be included
|
|
89
|
+
*/
|
|
90
|
+
private shouldIncludeFullDocumentBefore;
|
|
91
|
+
/**
|
|
92
|
+
* Checks if a change document passes the filter
|
|
93
|
+
*/
|
|
94
|
+
private passesFilter;
|
|
95
|
+
/**
|
|
96
|
+
* Returns an async iterator for the change stream
|
|
97
|
+
*/
|
|
98
|
+
[Symbol.asyncIterator](): AsyncIterableIterator<ChangeStreamDocument<T>>;
|
|
99
|
+
/**
|
|
100
|
+
* Closes the change stream
|
|
101
|
+
*/
|
|
102
|
+
close(): void;
|
|
103
|
+
/**
|
|
104
|
+
* Returns the next change document
|
|
105
|
+
*/
|
|
106
|
+
next(): Promise<{
|
|
107
|
+
value: ChangeStreamDocument<T>;
|
|
108
|
+
done: boolean;
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Cleanup triggers when the change stream is destroyed
|
|
112
|
+
*/
|
|
113
|
+
cleanup(): Promise<void>;
|
|
114
|
+
}
|