@semics-tech/mongolite 1.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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +179 -0
  3. package/dist/adapters/browser.d.ts +97 -0
  4. package/dist/adapters/browser.js +103 -0
  5. package/dist/adapters/browser.js.map +1 -0
  6. package/dist/adapters/cloudflare.d.ts +106 -0
  7. package/dist/adapters/cloudflare.js +94 -0
  8. package/dist/adapters/cloudflare.js.map +1 -0
  9. package/dist/bin/mongolite-debug.d.ts +2 -0
  10. package/dist/bin/mongolite-debug.js +115 -0
  11. package/dist/bin/mongolite-debug.js.map +1 -0
  12. package/dist/changeStream.d.ts +114 -0
  13. package/dist/changeStream.js +338 -0
  14. package/dist/changeStream.js.map +1 -0
  15. package/dist/cloudflare.d.ts +39 -0
  16. package/dist/cloudflare.js +39 -0
  17. package/dist/cloudflare.js.map +1 -0
  18. package/dist/collection.d.ts +274 -0
  19. package/dist/collection.js +1706 -0
  20. package/dist/collection.js.map +1 -0
  21. package/dist/cursors/findCursor.d.ts +101 -0
  22. package/dist/cursors/findCursor.js +757 -0
  23. package/dist/cursors/findCursor.js.map +1 -0
  24. package/dist/db.d.ts +116 -0
  25. package/dist/db.js +254 -0
  26. package/dist/db.js.map +1 -0
  27. package/dist/debugger/query-debugger.d.ts +22 -0
  28. package/dist/debugger/query-debugger.js +258 -0
  29. package/dist/debugger/query-debugger.js.map +1 -0
  30. package/dist/index.d.ts +30 -0
  31. package/dist/index.js +40 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/mongo-client.d.ts +56 -0
  34. package/dist/mongo-client.js +55 -0
  35. package/dist/mongo-client.js.map +1 -0
  36. package/dist/types.d.ts +318 -0
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/utils/indexing.d.ts +4 -0
  40. package/dist/utils/indexing.js +43 -0
  41. package/dist/utils/indexing.js.map +1 -0
  42. package/dist/utils/projection.d.ts +16 -0
  43. package/dist/utils/projection.js +98 -0
  44. package/dist/utils/projection.js.map +1 -0
  45. package/dist/utils/queryOperators.d.ts +16 -0
  46. package/dist/utils/queryOperators.js +138 -0
  47. package/dist/utils/queryOperators.js.map +1 -0
  48. package/package.json +92 -0
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ import { QueryDebugger } from '../debugger/query-debugger.js';
3
+ import path from 'path';
4
+ // CLI argument parsing
5
+ function parseArgs() {
6
+ const args = process.argv.slice(2);
7
+ const options = {};
8
+ for (let i = 0; i < args.length; i++) {
9
+ const arg = args[i];
10
+ if (arg === '--verbose' || arg === '-v') {
11
+ options.verbose = true;
12
+ }
13
+ else if (arg === '--collection' || arg === '-c') {
14
+ options.collection = args[++i];
15
+ }
16
+ else if (arg === '--database' || arg === '-d') {
17
+ options.database = args[++i];
18
+ }
19
+ else if (arg === '--help' || arg === '-h') {
20
+ options.help = true;
21
+ }
22
+ }
23
+ return options;
24
+ }
25
+ function showHelp() {
26
+ console.log('MongoLite Query Debugger');
27
+ console.log('');
28
+ console.log('Interactive debugging tool for MongoLite queries.');
29
+ console.log('');
30
+ console.log('Usage: npx mongolite-debug [options]');
31
+ console.log('');
32
+ console.log('Options:');
33
+ console.log(' -d, --database <path> Database file path (default: ./mongolite.db)');
34
+ console.log(' -c, --collection <name> Initial collection to use');
35
+ console.log(' -v, --verbose Enable verbose output');
36
+ console.log(' -h, --help Show this help');
37
+ console.log('');
38
+ console.log('Interactive Commands:');
39
+ console.log(' .help Show available commands');
40
+ console.log(' .collections List all collections');
41
+ console.log(' .use <collection> Select a collection to work with');
42
+ console.log(' .find <filter> Convert find filter to SQL and execute');
43
+ console.log(' .sql <query> Execute raw SQL query');
44
+ console.log(' .last Show last generated SQL');
45
+ console.log(' .sample [count] Show sample documents from current collection');
46
+ console.log(' .exit Exit the debugger');
47
+ console.log('');
48
+ console.log('Examples:');
49
+ console.log(' npx mongolite-debug -d ./myapp.db -c users');
50
+ console.log(' npx mongolite-debug --verbose');
51
+ console.log('');
52
+ console.log(' # Inside the debugger:');
53
+ console.log(' .use users');
54
+ console.log(' .find {"age": {"$gt": 25}}');
55
+ console.log(' .sql SELECT * FROM users WHERE json_extract(data, "$.age") > 25');
56
+ console.log('');
57
+ }
58
+ async function main() {
59
+ const options = parseArgs();
60
+ if (options.help) {
61
+ showHelp();
62
+ process.exit(0);
63
+ }
64
+ // Set default database path if not provided
65
+ if (!options.database) {
66
+ // Look for common database files in the current directory
67
+ const cwd = process.cwd();
68
+ const commonNames = [
69
+ 'mongolite.db',
70
+ 'mongolite.sqlite',
71
+ 'database.db',
72
+ 'database.sqlite',
73
+ 'app.db',
74
+ 'app.sqlite',
75
+ ];
76
+ // Check if any common database files exist
77
+ const { existsSync } = await import('fs');
78
+ let foundDb = false;
79
+ for (const name of commonNames) {
80
+ const dbPath = path.join(cwd, name);
81
+ if (existsSync(dbPath)) {
82
+ options.database = dbPath;
83
+ foundDb = true;
84
+ break;
85
+ }
86
+ }
87
+ if (!foundDb) {
88
+ options.database = path.join(cwd, 'mongolite.db');
89
+ }
90
+ }
91
+ console.log('🔍 MongoLite Query Debugger (npx version)');
92
+ console.log(`📁 Database: ${options.database}`);
93
+ if (options.collection) {
94
+ console.log(`📋 Initial collection: ${options.collection}`);
95
+ }
96
+ console.log('');
97
+ try {
98
+ const queryDebugger = new QueryDebugger(options);
99
+ await queryDebugger.start();
100
+ }
101
+ catch (error) {
102
+ console.error('Fatal error:', error instanceof Error ? error.message : error);
103
+ if (error instanceof Error && error.message.includes('SQLITE_CANTOPEN')) {
104
+ console.error('');
105
+ console.error('💡 Tip: Make sure the database file exists or specify a different path with -d');
106
+ console.error(' Example: npx mongolite-debug -d ./path/to/your/database.db');
107
+ }
108
+ process.exit(1);
109
+ }
110
+ }
111
+ main().catch((error) => {
112
+ console.error('Unexpected error:', error);
113
+ process.exit(1);
114
+ });
115
+ //# sourceMappingURL=mongolite-debug.js.map
@@ -0,0 +1 @@
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 type { IDatabaseAdapter } 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: IDatabaseAdapter, 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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAkDtC,MAAM,OAAO,YAAwD,SAAQ,YAAY;IAOvF,YACmB,EAAoB,EACpB,cAAsB,EACtB,UAAkC,EAAE;QAErD,KAAK,EAAE,CAAC;QAJS,OAAE,GAAF,EAAE,CAAkB;QACpB,mBAAc,GAAd,cAAc,CAAQ;QACtB,YAAO,GAAP,OAAO,CAA6B;QAT/C,WAAM,GAAG,KAAK,CAAC;QACf,iBAAY,GAA0B,IAAI,CAAC;QAC3C,oBAAe,GAAG,CAAC,CAAC;QACpB,WAAM,GAA8B,EAAE,CAAC;QAS7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC;QACnD,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB;QAC/B,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB;QAChC,MAAM,cAAc,GAAG;;;;;;;;;;;;;KAatB,CAAC;QAEF,MAAM,cAAc,GAAG;;;KAGtB,CAAC;QAEF,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACnC,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa;QACzB,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAE3C,6CAA6C;QAC7C,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,CAAC;QAChF,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,CAAC;QAChF,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,CAAC;QAEhF,iBAAiB;QACjB,MAAM,gBAAgB,GAAG;wBACL,cAAc;yBACb,cAAc;;;;;;uBAMhB,cAAc;;;KAGhC,CAAC;QAEF,iBAAiB;QACjB,MAAM,gBAAgB,GAAG;wBACL,cAAc;yBACb,cAAc;;;;;;;uBAOhB,cAAc;;;;KAIhC,CAAC;QAEF,iBAAiB;QACjB,MAAM,gBAAgB,GAAG;wBACL,cAAc;yBACb,cAAc;;;;;;uBAMhB,cAAc;;;KAGhC,CAAC;QAEF,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACrC,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACrC,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAExB,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;YACzC,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,mBAAmB;IAC9B,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc;QAC1B,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAExB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAW/B;;iCAE2B,EAC3B,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,CAC5C,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,MAAM;gBAAE,MAAM;YAEvB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;YAE1D,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAE5B,wBAAwB;gBACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;gBAE/B,oCAAoC;gBACpC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;oBAC5C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YAED,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,EAAE,CAAC;QACnC,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAAC,MAUlC;QACC,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,MAAM,kBAAkB,GAAG,MAAM,CAAC,oBAAoB;YACpD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC;YACzC,CAAC,CAAC,SAAS,CAAC;QAEd,IAAI,iBAA2E,CAAC;QAEhF,IAAI,MAAM,CAAC,cAAc,KAAK,QAAQ,IAAI,YAAY,IAAI,kBAAkB,EAAE,CAAC;YAC7E,iBAAiB,GAAG,IAAI,CAAC,wBAAwB,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,SAAS,GAA4B;YACzC,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,EAAE,yDAAyD;YAC9E,aAAa,EAAE,MAAM,CAAC,cAAc;YACpC,WAAW,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YACvC,WAAW,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE;YACxC,EAAE,EAAE;gBACF,EAAE,EAAE,WAAW,EAAE,mCAAmC;gBACpD,IAAI,EAAE,MAAM,CAAC,eAAe;aAC7B;SACF,CAAC;QAEF,qCAAqC;QACrC,IAAI,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;YAC1D,SAAS,CAAC,YAAY,GAAG,YAAY;gBACnC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE,GAAG,YAAY,EAAE;gBAC9C,CAAC,CAAC,SAAS,CAAC;QAChB,CAAC;QAED,mDAAmD;QACnD,IAAI,IAAI,CAAC,+BAA+B,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;YAChE,SAAS,CAAC,wBAAwB,GAAG,kBAAkB;gBACrD,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,WAAW,EAAE,GAAG,kBAAkB,EAAE;gBACpD,CAAC,CAAC,SAAS,CAAC;QAChB,CAAC;QAED,IAAI,iBAAiB,EAAE,CAAC;YACtB,SAAS,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAClD,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACK,wBAAwB,CAC9B,MAAe,EACf,KAAc;QAEd,MAAM,aAAa,GAA4B,EAAE,CAAC;QAClD,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,kDAAkD;QAClD,IACE,OAAO,MAAM,KAAK,QAAQ;YAC1B,MAAM,KAAK,IAAI;YACf,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI,EACd,CAAC;YACD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;QAC1C,CAAC;QAED,4DAA4D;QAC5D,MAAM,SAAS,GAAG,MAAiC,CAAC;QACpD,MAAM,QAAQ,GAAG,KAAgC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE/E,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC;gBACvB,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;iBAAM,IACL,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC;gBACnB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAChE,CAAC;gBACD,aAAa,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;IAC1C,CAAC;IAED;;OAEG;IACK,yBAAyB,CAAC,aAAkC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,SAAS,CAAC;QAEtD,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,SAAS;gBACZ,OAAO,aAAa,KAAK,QAAQ,CAAC;YACpC,KAAK,cAAc,CAAC;YACpB,KAAK,eAAe,CAAC;YACrB,KAAK,UAAU;gBACb,OAAO,CACL,aAAa,KAAK,QAAQ,IAAI,aAAa,KAAK,QAAQ,IAAI,aAAa,KAAK,SAAS,CACxF,CAAC;YACJ;gBACE,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED;;OAEG;IACK,+BAA+B,CAAC,aAAkC;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,wBAAwB,IAAI,KAAK,CAAC;QAE9D,IAAI,MAAM,KAAK,KAAK;YAAE,OAAO,KAAK,CAAC;QAEnC,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,QAAQ,CAAC;IACjG,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,SAAkC;QACrD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEtC,mDAAmD;QACnD,6CAA6C;QAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAI,SAAgD,CAAC,GAAG,CAAC,CAAC;YACxE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzE,uCAAuC;gBACvC,sCAAsC;gBACtC,SAAS;YACX,CAAC;iBAAM,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;gBAC9B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAG,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,uBAAuB;gBACvB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAClC,MAAM,QAAQ,GAAG,GAAG,EAAE;wBACpB,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;wBACxC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBACtC,OAAO,EAAE,CAAC;oBACZ,CAAC,CAAC;oBAEF,MAAM,OAAO,GAAG,GAAG,EAAE;wBACnB,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;wBACxC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBACtC,OAAO,EAAE,CAAC;oBACZ,CAAC,CAAC;oBAEF,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;oBAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC9B,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAExB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,EAAE,KAAK,EAAE,EAA6B,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC9D,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACtD,CAAC;QAED,uBAAuB;QACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,QAAQ,GAAG,CAAC,SAAkC,EAAE,EAAE;gBACtD,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACxC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACtC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7C,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACxC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACtC,OAAO,CAAC,EAAE,KAAK,EAAE,EAA6B,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,CAAC,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC;QAE3C,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,CAAC;YAChF,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,CAAC;YAChF,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,CAAC;QAClF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,+BAA+B;YAC/B,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Cloudflare-safe entry point for MongoLite.
3
+ *
4
+ * Import from `@semics-tech/mongolite/cloudflare` inside Cloudflare Workers / Durable Objects.
5
+ * This module does **not** import `better-sqlite3`, so it bundles cleanly with `wrangler`.
6
+ *
7
+ * ## Requirements
8
+ *
9
+ * - Enable **Node.js compatibility** in your Worker configuration (e.g. `nodejs_compat`
10
+ * flag in `wrangler.toml`/`wrangler.jsonc`). The `ChangeStream` class depends on
11
+ * Node's built-in `events` module, which requires this flag even if you don't use
12
+ * change streams directly.
13
+ *
14
+ * ## Usage
15
+ *
16
+ * ```ts
17
+ * import { DurableObject } from 'cloudflare:workers';
18
+ * import { MongoLite, CloudflareDurableObjectAdapter } from '@semics-tech/mongolite/cloudflare';
19
+ *
20
+ * export class MyDurableObject extends DurableObject {
21
+ * private client: MongoLite;
22
+ *
23
+ * constructor(ctx: DurableObjectState, env: Env) {
24
+ * super(ctx, env);
25
+ * this.client = new MongoLite(new CloudflareDurableObjectAdapter(ctx.storage.sql));
26
+ * ctx.blockConcurrencyWhile(() => this.client.collection('users').ensureTable());
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ export { MongoLite } from './mongo-client.js';
32
+ export type { MongoLiteBaseOptions } from './mongo-client.js';
33
+ export { CloudflareDurableObjectAdapter } from './adapters/cloudflare.js';
34
+ export type { SqlStorage, SqlStorageCursor, SqlStorageValue, } from './adapters/cloudflare.js';
35
+ export type { IDatabaseAdapter } from './db.js';
36
+ export { MongoLiteCollection } from './collection.js';
37
+ export * from './types.js';
38
+ export { ChangeStream } from './changeStream.js';
39
+ export type { ChangeStreamDocument, ChangeStreamOptions, ChangeOperationType, } from './changeStream.js';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Cloudflare-safe entry point for MongoLite.
3
+ *
4
+ * Import from `@semics-tech/mongolite/cloudflare` inside Cloudflare Workers / Durable Objects.
5
+ * This module does **not** import `better-sqlite3`, so it bundles cleanly with `wrangler`.
6
+ *
7
+ * ## Requirements
8
+ *
9
+ * - Enable **Node.js compatibility** in your Worker configuration (e.g. `nodejs_compat`
10
+ * flag in `wrangler.toml`/`wrangler.jsonc`). The `ChangeStream` class depends on
11
+ * Node's built-in `events` module, which requires this flag even if you don't use
12
+ * change streams directly.
13
+ *
14
+ * ## Usage
15
+ *
16
+ * ```ts
17
+ * import { DurableObject } from 'cloudflare:workers';
18
+ * import { MongoLite, CloudflareDurableObjectAdapter } from '@semics-tech/mongolite/cloudflare';
19
+ *
20
+ * export class MyDurableObject extends DurableObject {
21
+ * private client: MongoLite;
22
+ *
23
+ * constructor(ctx: DurableObjectState, env: Env) {
24
+ * super(ctx, env);
25
+ * this.client = new MongoLite(new CloudflareDurableObjectAdapter(ctx.storage.sql));
26
+ * ctx.blockConcurrencyWhile(() => this.client.collection('users').ensureTable());
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ // Core MongoLite class — accepts any IDatabaseAdapter, no better-sqlite3 dependency.
32
+ export { MongoLite } from './mongo-client.js';
33
+ // Cloudflare-specific adapter
34
+ export { CloudflareDurableObjectAdapter } from './adapters/cloudflare.js';
35
+ export { MongoLiteCollection } from './collection.js';
36
+ export * from './types.js';
37
+ // Change streams (requires nodejs_compat in Workers)
38
+ export { ChangeStream } from './changeStream.js';
39
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../src/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,qFAAqF;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG9C,8BAA8B;AAC9B,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAS1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,cAAc,YAAY,CAAC;AAE3B,qDAAqD;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}