mongolite-ts 0.5.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 CHANGED
@@ -17,6 +17,7 @@ A MongoDB-like client that uses SQLite as its underlying persistent store. Writt
17
17
  * 100% test coverage (aiming for).
18
18
  * **Interactive Query Debugger** - Debug complex queries with `npx mongolite-debug`
19
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()`
20
21
 
21
22
  ## JSON Safety & Data Integrity
22
23
 
@@ -155,6 +156,154 @@ async function main() {
155
156
  main();
156
157
  ```
157
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
+
158
307
  ## Query Debugger
159
308
 
160
309
  MongoLite includes an interactive query debugger to help you debug complex queries and understand how MongoDB-style filters are converted to SQL.
@@ -256,6 +405,38 @@ Deletes a single document matching the filter.
256
405
  * `filter`: The selection criteria for the deletion.
257
406
  * Returns `DeleteResult`: `{ acknowledged: boolean; deletedCount: number; }`.
258
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
+
259
440
 
260
441
  ### `FindCursor<T>`
261
442
 
@@ -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
+ }
@@ -0,0 +1,338 @@
1
+ import { EventEmitter } from 'events';
2
+ export class ChangeStream extends EventEmitter {
3
+ constructor(db, collectionName, options = {}) {
4
+ super();
5
+ this.db = db;
6
+ this.collectionName = collectionName;
7
+ this.options = options;
8
+ this.closed = false;
9
+ this.pollInterval = null;
10
+ this.lastProcessedId = 0;
11
+ this.buffer = [];
12
+ this.maxBufferSize = options.maxBufferSize || 1000;
13
+ this.setupChangeTracking();
14
+ this.startPolling();
15
+ }
16
+ /**
17
+ * Sets up the change tracking infrastructure
18
+ */
19
+ async setupChangeTracking() {
20
+ await this.ensureChangeLogTable();
21
+ await this.setupTriggers();
22
+ }
23
+ /**
24
+ * Creates the change log table if it doesn't exist
25
+ */
26
+ async ensureChangeLogTable() {
27
+ const createTableSQL = `
28
+ CREATE TABLE IF NOT EXISTS __mongolite_changes__ (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
31
+ operation_type TEXT NOT NULL,
32
+ collection_name TEXT NOT NULL,
33
+ document_id TEXT NOT NULL,
34
+ full_document TEXT,
35
+ full_document_before TEXT,
36
+ updated_fields TEXT,
37
+ removed_fields TEXT,
38
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
39
+ );
40
+ `;
41
+ const createIndexSQL = `
42
+ CREATE INDEX IF NOT EXISTS idx_mongolite_changes_collection_timestamp
43
+ ON __mongolite_changes__ (collection_name, timestamp);
44
+ `;
45
+ await this.db.exec(createTableSQL);
46
+ await this.db.exec(createIndexSQL);
47
+ }
48
+ /**
49
+ * Sets up triggers for tracking changes on the collection
50
+ */
51
+ async setupTriggers() {
52
+ const collectionName = this.collectionName;
53
+ // Drop existing triggers for this collection
54
+ await this.db.exec(`DROP TRIGGER IF EXISTS "${collectionName}_insert_trigger"`);
55
+ await this.db.exec(`DROP TRIGGER IF EXISTS "${collectionName}_update_trigger"`);
56
+ await this.db.exec(`DROP TRIGGER IF EXISTS "${collectionName}_delete_trigger"`);
57
+ // Insert trigger
58
+ const insertTriggerSQL = `
59
+ CREATE TRIGGER "${collectionName}_insert_trigger"
60
+ AFTER INSERT ON "${collectionName}"
61
+ FOR EACH ROW
62
+ BEGIN
63
+ INSERT INTO __mongolite_changes__ (
64
+ operation_type, collection_name, document_id, full_document
65
+ ) VALUES (
66
+ 'insert', '${collectionName}', NEW._id, NEW.data
67
+ );
68
+ END;
69
+ `;
70
+ // Update trigger
71
+ const updateTriggerSQL = `
72
+ CREATE TRIGGER "${collectionName}_update_trigger"
73
+ AFTER UPDATE ON "${collectionName}"
74
+ FOR EACH ROW
75
+ BEGIN
76
+ INSERT INTO __mongolite_changes__ (
77
+ operation_type, collection_name, document_id,
78
+ full_document, full_document_before
79
+ ) VALUES (
80
+ 'update', '${collectionName}', NEW._id,
81
+ NEW.data, OLD.data
82
+ );
83
+ END;
84
+ `;
85
+ // Delete trigger
86
+ const deleteTriggerSQL = `
87
+ CREATE TRIGGER "${collectionName}_delete_trigger"
88
+ AFTER DELETE ON "${collectionName}"
89
+ FOR EACH ROW
90
+ BEGIN
91
+ INSERT INTO __mongolite_changes__ (
92
+ operation_type, collection_name, document_id, full_document_before
93
+ ) VALUES (
94
+ 'delete', '${collectionName}', OLD._id, OLD.data
95
+ );
96
+ END;
97
+ `;
98
+ await this.db.exec(insertTriggerSQL);
99
+ await this.db.exec(updateTriggerSQL);
100
+ await this.db.exec(deleteTriggerSQL);
101
+ }
102
+ /**
103
+ * Starts polling for new changes
104
+ */
105
+ startPolling() {
106
+ if (this.closed)
107
+ return;
108
+ this.pollInterval = setInterval(async () => {
109
+ try {
110
+ await this.pollForChanges();
111
+ }
112
+ catch (error) {
113
+ this.emit('error', error);
114
+ }
115
+ }, 100); // Poll every 100ms
116
+ }
117
+ /**
118
+ * Polls for new changes from the change log
119
+ */
120
+ async pollForChanges() {
121
+ if (this.closed)
122
+ return;
123
+ const changes = await this.db.all(`SELECT * FROM __mongolite_changes__
124
+ WHERE collection_name = ? AND id > ?
125
+ ORDER BY id ASC LIMIT 100`, [this.collectionName, this.lastProcessedId]);
126
+ for (const change of changes) {
127
+ if (this.closed)
128
+ break;
129
+ const changeDoc = await this.transformChangeEvent(change);
130
+ if (this.passesFilter(changeDoc)) {
131
+ this.buffer.push(changeDoc);
132
+ // Emit the change event
133
+ this.emit('change', changeDoc);
134
+ // Clean buffer if it gets too large
135
+ if (this.buffer.length > this.maxBufferSize) {
136
+ this.buffer = this.buffer.slice(-this.maxBufferSize);
137
+ }
138
+ }
139
+ this.lastProcessedId = change.id;
140
+ }
141
+ }
142
+ /**
143
+ * Transforms a raw change event from the database into a ChangeStreamDocument
144
+ */
145
+ async transformChangeEvent(change) {
146
+ const fullDocument = change.full_document ? JSON.parse(change.full_document) : undefined;
147
+ const fullDocumentBefore = change.full_document_before
148
+ ? JSON.parse(change.full_document_before)
149
+ : undefined;
150
+ let updateDescription;
151
+ if (change.operation_type === 'update' && fullDocument && fullDocumentBefore) {
152
+ updateDescription = this.computeUpdateDescription(fullDocumentBefore, fullDocument);
153
+ }
154
+ const changeDoc = {
155
+ _id: `${change.id}`, // Use the change log ID as the change stream document ID
156
+ operationType: change.operation_type,
157
+ clusterTime: new Date(change.timestamp),
158
+ documentKey: { _id: change.document_id },
159
+ ns: {
160
+ db: 'mongolite', // You could make this configurable
161
+ coll: change.collection_name,
162
+ },
163
+ };
164
+ // Add full document based on options
165
+ if (this.shouldIncludeFullDocument(change.operation_type)) {
166
+ changeDoc.fullDocument = fullDocument
167
+ ? { _id: change.document_id, ...fullDocument }
168
+ : undefined;
169
+ }
170
+ // Add full document before change based on options
171
+ if (this.shouldIncludeFullDocumentBefore(change.operation_type)) {
172
+ changeDoc.fullDocumentBeforeChange = fullDocumentBefore
173
+ ? { _id: change.document_id, ...fullDocumentBefore }
174
+ : undefined;
175
+ }
176
+ if (updateDescription) {
177
+ changeDoc.updateDescription = updateDescription;
178
+ }
179
+ return changeDoc;
180
+ }
181
+ /**
182
+ * Computes the update description by comparing before and after documents
183
+ */
184
+ computeUpdateDescription(before, after) {
185
+ const updatedFields = {};
186
+ const removedFields = [];
187
+ // Type guard to ensure we have objects to compare
188
+ if (typeof before !== 'object' ||
189
+ before === null ||
190
+ typeof after !== 'object' ||
191
+ after === null) {
192
+ return { updatedFields, removedFields };
193
+ }
194
+ // Simple comparison - this could be made more sophisticated
195
+ const beforeObj = before;
196
+ const afterObj = after;
197
+ const allKeys = new Set([...Object.keys(beforeObj), ...Object.keys(afterObj)]);
198
+ for (const key of allKeys) {
199
+ if (!(key in afterObj)) {
200
+ removedFields.push(key);
201
+ }
202
+ else if (!(key in beforeObj) ||
203
+ JSON.stringify(beforeObj[key]) !== JSON.stringify(afterObj[key])) {
204
+ updatedFields[key] = afterObj[key];
205
+ }
206
+ }
207
+ return { updatedFields, removedFields };
208
+ }
209
+ /**
210
+ * Determines if the full document should be included
211
+ */
212
+ shouldIncludeFullDocument(operationType) {
213
+ const option = this.options.fullDocument || 'default';
214
+ switch (option) {
215
+ case 'default':
216
+ return operationType === 'insert';
217
+ case 'updateLookup':
218
+ case 'whenAvailable':
219
+ case 'required':
220
+ return (operationType === 'insert' || operationType === 'update' || operationType === 'replace');
221
+ default:
222
+ return false;
223
+ }
224
+ }
225
+ /**
226
+ * Determines if the full document before change should be included
227
+ */
228
+ shouldIncludeFullDocumentBefore(operationType) {
229
+ const option = this.options.fullDocumentBeforeChange || 'off';
230
+ if (option === 'off')
231
+ return false;
232
+ return operationType === 'update' || operationType === 'replace' || operationType === 'delete';
233
+ }
234
+ /**
235
+ * Checks if a change document passes the filter
236
+ */
237
+ passesFilter(changeDoc) {
238
+ if (!this.options.filter)
239
+ return true;
240
+ // Simple filter implementation - could be enhanced
241
+ // For now, just check basic equality filters
242
+ for (const [key, value] of Object.entries(this.options.filter)) {
243
+ const docValue = changeDoc[key];
244
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
245
+ // Handle operators like $in, $eq, etc.
246
+ // This is a simplified implementation
247
+ continue;
248
+ }
249
+ else if (docValue !== value) {
250
+ return false;
251
+ }
252
+ }
253
+ return true;
254
+ }
255
+ /**
256
+ * Returns an async iterator for the change stream
257
+ */
258
+ async *[Symbol.asyncIterator]() {
259
+ while (!this.closed) {
260
+ if (this.buffer.length > 0) {
261
+ yield this.buffer.shift();
262
+ }
263
+ else {
264
+ // Wait for next change
265
+ await new Promise((resolve) => {
266
+ const onChange = () => {
267
+ this.removeListener('change', onChange);
268
+ this.removeListener('close', onClose);
269
+ resolve();
270
+ };
271
+ const onClose = () => {
272
+ this.removeListener('change', onChange);
273
+ this.removeListener('close', onClose);
274
+ resolve();
275
+ };
276
+ this.once('change', onChange);
277
+ this.once('close', onClose);
278
+ });
279
+ }
280
+ }
281
+ }
282
+ /**
283
+ * Closes the change stream
284
+ */
285
+ close() {
286
+ if (this.closed)
287
+ return;
288
+ this.closed = true;
289
+ if (this.pollInterval) {
290
+ clearInterval(this.pollInterval);
291
+ this.pollInterval = null;
292
+ }
293
+ this.emit('close');
294
+ this.removeAllListeners();
295
+ }
296
+ /**
297
+ * Returns the next change document
298
+ */
299
+ async next() {
300
+ if (this.closed) {
301
+ return { value: {}, done: true };
302
+ }
303
+ if (this.buffer.length > 0) {
304
+ return { value: this.buffer.shift(), done: false };
305
+ }
306
+ // Wait for next change
307
+ return new Promise((resolve) => {
308
+ const onChange = (changeDoc) => {
309
+ this.removeListener('change', onChange);
310
+ this.removeListener('close', onClose);
311
+ resolve({ value: changeDoc, done: false });
312
+ };
313
+ const onClose = () => {
314
+ this.removeListener('change', onChange);
315
+ this.removeListener('close', onClose);
316
+ resolve({ value: {}, done: true });
317
+ };
318
+ this.once('change', onChange);
319
+ this.once('close', onClose);
320
+ });
321
+ }
322
+ /**
323
+ * Cleanup triggers when the change stream is destroyed
324
+ */
325
+ async cleanup() {
326
+ const collectionName = this.collectionName;
327
+ try {
328
+ await this.db.exec(`DROP TRIGGER IF EXISTS "${collectionName}_insert_trigger"`);
329
+ await this.db.exec(`DROP TRIGGER IF EXISTS "${collectionName}_update_trigger"`);
330
+ await this.db.exec(`DROP TRIGGER IF EXISTS "${collectionName}_delete_trigger"`);
331
+ }
332
+ catch (error) {
333
+ // Ignore errors during cleanup
334
+ console.warn('Error during change stream cleanup:', error);
335
+ }
336
+ }
337
+ }
338
+ //# sourceMappingURL=changeStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changeStream.js","sourceRoot":"","sources":["../src/changeStream.ts"],"names":[],"mappings":"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"}