@semics-tech/mongolite 1.0.0 → 1.1.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/dist/cjs/db.js ADDED
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SQLiteDB = void 0;
7
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
8
+ /**
9
+ * SQLiteDB class provides a wrapper around the better-sqlite3 library
10
+ * to simplify database operations.
11
+ */
12
+ class SQLiteDB {
13
+ /**
14
+ * Creates an instance of SQLiteDB.
15
+ * @param {string | MongoLiteOptions} dbPathOrOptions - The path to the SQLite database file or an options object.
16
+ * Use ':memory:' for an in-memory database.
17
+ */
18
+ constructor(dbPathOrOptions) {
19
+ this.db = null;
20
+ this.openPromise = null;
21
+ if (typeof dbPathOrOptions === 'string') {
22
+ this.filePath = dbPathOrOptions;
23
+ this.verbose = false;
24
+ this.readOnly = false;
25
+ this.WAL = false;
26
+ }
27
+ else {
28
+ this.filePath = dbPathOrOptions.filePath;
29
+ this.verbose = dbPathOrOptions.verbose || false;
30
+ this.readOnly = dbPathOrOptions.readOnly || false;
31
+ this.WAL = dbPathOrOptions.WAL || true;
32
+ }
33
+ }
34
+ /**
35
+ * Opens the database connection if it's not already open.
36
+ * @returns {Promise<void>} A promise that resolves when the connection is open.
37
+ */
38
+ async connect() {
39
+ if (this.db && this.openPromise) {
40
+ return this.openPromise;
41
+ }
42
+ if (this.db) {
43
+ // Already connected and openPromise is null (should not happen with proper logic)
44
+ return Promise.resolve();
45
+ }
46
+ this.openPromise = new Promise((resolve, reject) => {
47
+ try {
48
+ const options = {
49
+ readonly: this.readOnly,
50
+ verbose: this.verbose ? console.log : undefined,
51
+ };
52
+ this.db = new better_sqlite3_1.default(this.filePath, options);
53
+ // Enable Write-Ahead Logging if requested
54
+ if (this.WAL && !this.readOnly) {
55
+ this.db.pragma('journal_mode = WAL');
56
+ }
57
+ // Register regexp UDF for $regex operator support.
58
+ // WARNING: Patterns are compiled via JavaScript RegExp. User-supplied patterns that are
59
+ // not validated for catastrophic backtracking (ReDoS) could block the event loop.
60
+ // Avoid using untrusted/unvalidated patterns with $regex in security-sensitive contexts.
61
+ this.db.function('regexp', { deterministic: true }, (pattern, value) => {
62
+ if (typeof pattern !== 'string' || value === null || value === undefined)
63
+ return 0;
64
+ try {
65
+ return new RegExp(pattern).test(String(value)) ? 1 : 0;
66
+ }
67
+ catch {
68
+ return 0;
69
+ }
70
+ });
71
+ // Register regexp_flags UDF for $regex with $options support
72
+ this.db.function('regexp_flags', { deterministic: true }, (pattern, flags, value) => {
73
+ if (typeof pattern !== 'string' || value === null || value === undefined)
74
+ return 0;
75
+ try {
76
+ const f = typeof flags === 'string' ? flags : '';
77
+ return new RegExp(pattern, f).test(String(value)) ? 1 : 0;
78
+ }
79
+ catch {
80
+ return 0;
81
+ }
82
+ });
83
+ if (this.verbose) {
84
+ console.log(`SQLite database opened: ${this.filePath}`);
85
+ }
86
+ resolve();
87
+ }
88
+ catch (err) {
89
+ console.error(`Error opening database ${this.filePath}:`, err.message);
90
+ this.db = null;
91
+ this.openPromise = null;
92
+ reject(err);
93
+ }
94
+ });
95
+ return this.openPromise;
96
+ }
97
+ /**
98
+ * Ensures the database connection is open before performing an operation.
99
+ * @private
100
+ * @returns {Promise<Database.Database>} The active database instance.
101
+ * @throws {Error} If the database is not connected.
102
+ */
103
+ async ensureConnected() {
104
+ if (!this.db || !this.openPromise) {
105
+ await this.connect();
106
+ }
107
+ else {
108
+ await this.openPromise; // Wait for any ongoing connection attempt
109
+ }
110
+ if (!this.db) {
111
+ // This should ideally not be reached if connect() works correctly
112
+ throw new Error('Database is not connected. Connection attempt failed.');
113
+ }
114
+ return this.db;
115
+ }
116
+ /**
117
+ * Executes a SQL query that does not return rows (e.g., INSERT, UPDATE, DELETE, CREATE).
118
+ * @param {string} sql - The SQL query string.
119
+ * @param {any[]} [params=[]] - Parameters for the SQL query.
120
+ * @returns {Promise<{ lastID: number, changes: number }>} Result of the execution.
121
+ */
122
+ async run(sql, params = []) {
123
+ const dbInstance = await this.ensureConnected();
124
+ try {
125
+ const result = dbInstance.prepare(sql).run(...params);
126
+ return {
127
+ lastID: result.lastInsertRowid,
128
+ changes: result.changes,
129
+ };
130
+ }
131
+ catch (err) {
132
+ console.error(`Error running SQL: ${sql}`, err);
133
+ throw err;
134
+ }
135
+ }
136
+ /**
137
+ * Executes a SQL query that returns a single row.
138
+ * @param {string} sql - The SQL query string.
139
+ * @param {any[]} [params=[]] - Parameters for the SQL query.
140
+ * @returns {Promise<T | undefined>} The first row found, or undefined.
141
+ */
142
+ async get(sql, params = []) {
143
+ const dbInstance = await this.ensureConnected();
144
+ try {
145
+ return dbInstance.prepare(sql).get(...params);
146
+ }
147
+ catch (err) {
148
+ console.error(`Error getting SQL: ${sql}`, err);
149
+ throw err;
150
+ }
151
+ }
152
+ /**
153
+ * Executes a SQL query that returns multiple rows.
154
+ * @param {string} sql - The SQL query string.
155
+ * @param {any[]} [params=[]] - Parameters for the SQL query.
156
+ * @returns {Promise<T[]>} An array of rows.
157
+ */
158
+ async all(sql, params = []) {
159
+ const dbInstance = await this.ensureConnected();
160
+ try {
161
+ return dbInstance.prepare(sql).all(...params);
162
+ }
163
+ catch (err) {
164
+ console.error(`Error getting all SQL: ${sql}`, err);
165
+ throw err;
166
+ }
167
+ }
168
+ /**
169
+ * Executes multiple SQL statements.
170
+ * @param {string} sql - SQL string with multiple statements.
171
+ * @returns {Promise<void>}
172
+ */
173
+ async exec(sql) {
174
+ const dbInstance = await this.ensureConnected();
175
+ try {
176
+ dbInstance.exec(sql);
177
+ return Promise.resolve();
178
+ }
179
+ catch (err) {
180
+ console.error(`Error executing SQL: ${sql}`, err);
181
+ throw err;
182
+ }
183
+ }
184
+ /**
185
+ * Closes the database connection.
186
+ * @returns {Promise<void>} A promise that resolves when the connection is closed.
187
+ */
188
+ async close() {
189
+ if (this.openPromise) {
190
+ await this.openPromise; // Ensure any pending connection attempt is finished
191
+ }
192
+ if (this.db) {
193
+ try {
194
+ this.db.close();
195
+ if (this.verbose) {
196
+ console.log(`SQLite database closed: ${this.filePath}`);
197
+ }
198
+ }
199
+ catch (err) {
200
+ console.error(`Error closing database ${this.filePath}:`, err.message);
201
+ throw err; // Re-throw the error to indicate failure
202
+ }
203
+ finally {
204
+ this.db = null;
205
+ this.openPromise = null;
206
+ }
207
+ }
208
+ else {
209
+ // If db is null, it's already considered closed or was never opened.
210
+ this.db = null;
211
+ this.openPromise = null;
212
+ }
213
+ }
214
+ /**
215
+ * Gets the underlying better-sqlite3 Database instance.
216
+ * Useful for operations not covered by this wrapper, like transactions.
217
+ * @returns {Promise<Database.Database>} The raw database object.
218
+ * @throws {Error} If the database is not connected.
219
+ */
220
+ async getDbInstance() {
221
+ return this.ensureConnected();
222
+ }
223
+ /**
224
+ * Prepares a SQL statement for later execution.
225
+ * @param {string} sql - The SQL query string.
226
+ * @returns {Promise<Statement>} A prepared statement that can be executed multiple times.
227
+ */
228
+ async prepare(sql) {
229
+ const dbInstance = await this.ensureConnected();
230
+ return dbInstance.prepare(sql);
231
+ }
232
+ /**
233
+ * Begins a transaction.
234
+ * @returns {Promise<void>}
235
+ */
236
+ async beginTransaction() {
237
+ const dbInstance = await this.ensureConnected();
238
+ dbInstance.prepare('BEGIN').run();
239
+ return Promise.resolve();
240
+ }
241
+ /**
242
+ * Commits a transaction.
243
+ * @returns {Promise<void>}
244
+ */
245
+ async commitTransaction() {
246
+ const dbInstance = await this.ensureConnected();
247
+ dbInstance.prepare('COMMIT').run();
248
+ return Promise.resolve();
249
+ }
250
+ /**
251
+ * Rolls back a transaction.
252
+ * @returns {Promise<void>}
253
+ */
254
+ async rollbackTransaction() {
255
+ const dbInstance = await this.ensureConnected();
256
+ dbInstance.prepare('ROLLBACK').run();
257
+ return Promise.resolve();
258
+ }
259
+ }
260
+ exports.SQLiteDB = SQLiteDB;
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.QueryDebugger = void 0;
40
+ const index_js_1 = require("../index.js");
41
+ const findCursor_js_1 = require("../cursors/findCursor.js");
42
+ const readline = __importStar(require("readline"));
43
+ const path_1 = __importDefault(require("path"));
44
+ class QueryDebugger {
45
+ constructor(options = {}) {
46
+ this.currentCollection = null;
47
+ this.lastFilter = null;
48
+ this.lastSqlQuery = null;
49
+ const dbPath = options.database || path_1.default.join(process.cwd(), 'mongolite.db');
50
+ this.client = new index_js_1.MongoLite(dbPath, { verbose: options.verbose });
51
+ this.rl = readline.createInterface({
52
+ input: process.stdin,
53
+ output: process.stdout,
54
+ prompt: 'mongolite-debug> ',
55
+ });
56
+ if (options.collection) {
57
+ this.currentCollection = options.collection;
58
+ }
59
+ }
60
+ async start() {
61
+ console.log('Commands:');
62
+ console.log(' .help - Show this help');
63
+ console.log(' .collections - List all collections');
64
+ console.log(' .use <collection> - Select a collection to work with');
65
+ console.log(' .find <filter> - Convert find filter to SQL and execute');
66
+ console.log(' .sql <query> - Execute raw SQL query');
67
+ console.log(' .last - Show last generated SQL');
68
+ console.log(' .sample [count] - Show sample documents from current collection');
69
+ console.log(' .exit - Exit the debugger');
70
+ console.log('');
71
+ try {
72
+ await this.client.connect();
73
+ console.log('✅ Connected to database.');
74
+ }
75
+ catch (error) {
76
+ console.error('❌ Failed to connect to database:', error instanceof Error ? error.message : error);
77
+ throw error;
78
+ }
79
+ if (this.currentCollection) {
80
+ console.log(`Current collection: ${this.currentCollection}`);
81
+ }
82
+ this.rl.prompt();
83
+ this.rl.on('line', async (input) => {
84
+ const trimmed = input.trim();
85
+ if (trimmed === '.exit') {
86
+ await this.cleanup();
87
+ return;
88
+ }
89
+ try {
90
+ await this.handleCommand(trimmed);
91
+ }
92
+ catch (error) {
93
+ console.error('Error:', error instanceof Error ? error.message : error);
94
+ }
95
+ this.rl.prompt();
96
+ });
97
+ this.rl.on('close', async () => {
98
+ await this.cleanup();
99
+ });
100
+ }
101
+ async handleCommand(input) {
102
+ if (input === '.help') {
103
+ this.showHelp();
104
+ return;
105
+ }
106
+ if (input === '.collections') {
107
+ await this.listCollections();
108
+ return;
109
+ }
110
+ if (input.startsWith('.use ')) {
111
+ const collection = input.slice(5).trim();
112
+ this.currentCollection = collection;
113
+ console.log(`Switched to collection: ${collection}`);
114
+ return;
115
+ }
116
+ if (input.startsWith('.find ')) {
117
+ await this.handleFindCommand(input.slice(6).trim());
118
+ return;
119
+ }
120
+ if (input.startsWith('.sql ')) {
121
+ await this.handleSqlCommand(input.slice(5).trim());
122
+ return;
123
+ }
124
+ if (input === '.last') {
125
+ this.showLastQuery();
126
+ return;
127
+ }
128
+ if (input.startsWith('.sample')) {
129
+ const parts = input.split(' ');
130
+ const count = parts.length > 1 ? parseInt(parts[1]) || 5 : 5;
131
+ await this.showSample(count);
132
+ return;
133
+ }
134
+ console.log('Unknown command. Type .help for available commands.');
135
+ }
136
+ showHelp() {
137
+ console.log('');
138
+ console.log('Available commands:');
139
+ console.log(' .help - Show this help');
140
+ console.log(' .collections - List all collections');
141
+ console.log(' .use <collection> - Select a collection to work with');
142
+ console.log(' .find <filter> - Convert find filter to SQL and execute');
143
+ console.log(' .sql <query> - Execute raw SQL query');
144
+ console.log(' .last - Show last generated SQL');
145
+ console.log(' .sample [count] - Show sample documents from current collection');
146
+ console.log(' .exit - Exit the debugger');
147
+ console.log('');
148
+ console.log('Examples:');
149
+ console.log(' .use users');
150
+ console.log(' .find {"age": {"$gt": 25}}');
151
+ console.log(' .find {"name": "John", "age": {"$in": [25, 30, 35]}}');
152
+ console.log(' .sql SELECT * FROM users WHERE json_extract(data, "$.age") > 25');
153
+ console.log('');
154
+ }
155
+ async listCollections() {
156
+ try {
157
+ const collections = await this.client.listCollections().toArray();
158
+ if (collections.length === 0) {
159
+ console.log('No collections found.');
160
+ }
161
+ else {
162
+ console.log('Collections:');
163
+ collections.forEach((collection) => {
164
+ const marker = collection === this.currentCollection ? ' (current)' : '';
165
+ console.log(` - ${collection}${marker}`);
166
+ });
167
+ }
168
+ }
169
+ catch (error) {
170
+ console.error('Error listing collections:', error instanceof Error ? error.message : error);
171
+ }
172
+ }
173
+ async handleFindCommand(filterStr) {
174
+ if (!this.currentCollection) {
175
+ console.log('No collection selected. Use .use <collection> first.');
176
+ return;
177
+ }
178
+ let filter;
179
+ try {
180
+ filter = JSON.parse(filterStr);
181
+ }
182
+ catch (error) {
183
+ console.log('Invalid JSON filter:', error instanceof Error ? error.message : error);
184
+ return;
185
+ }
186
+ this.lastFilter = filter;
187
+ // Create a collection and a find cursor to extract the SQL
188
+ const collection = this.client.collection(this.currentCollection);
189
+ // We need to access the internal SQL generation. Let's create a custom cursor
190
+ // that exposes the SQL generation logic
191
+ const debugCursor = new DebugFindCursor(collection.db, this.currentCollection, filter, { verbose: true });
192
+ this.lastSqlQuery = debugCursor.getSQL();
193
+ console.log('');
194
+ console.log('📝 Generated SQL:');
195
+ console.log('Query:', this.lastSqlQuery.sql);
196
+ console.log('Parameters:', JSON.stringify(this.lastSqlQuery.params));
197
+ console.log('');
198
+ // Execute the query and show results
199
+ try {
200
+ const results = await debugCursor.toArray();
201
+ console.log(`📊 Results (${results.length} documents):`);
202
+ if (results.length > 0) {
203
+ results.forEach((doc, index) => {
204
+ console.log(`[${index}]`, JSON.stringify(doc, null, 2));
205
+ });
206
+ }
207
+ else {
208
+ console.log('No documents found.');
209
+ }
210
+ }
211
+ catch (error) {
212
+ console.error('Execution error:', error instanceof Error ? error.message : error);
213
+ }
214
+ }
215
+ async handleSqlCommand(sqlQuery) {
216
+ if (!this.currentCollection) {
217
+ console.log('No collection selected. Use .use <collection> first.');
218
+ return;
219
+ }
220
+ try {
221
+ // Get the database instance to execute raw SQL
222
+ const db = this.client.db;
223
+ console.log('');
224
+ console.log('🔧 Executing SQL:');
225
+ console.log(sqlQuery);
226
+ console.log('');
227
+ const results = await db.all(sqlQuery);
228
+ console.log(`📊 Results (${results.length} rows):`);
229
+ if (results.length > 0) {
230
+ results.forEach((row, index) => {
231
+ console.log(`[${index}]`, JSON.stringify(row, null, 2));
232
+ });
233
+ }
234
+ else {
235
+ console.log('No rows returned.');
236
+ }
237
+ }
238
+ catch (error) {
239
+ console.error('SQL execution error:', error instanceof Error ? error.message : error);
240
+ }
241
+ }
242
+ showLastQuery() {
243
+ if (!this.lastSqlQuery) {
244
+ console.log('No previous query to show.');
245
+ return;
246
+ }
247
+ console.log('');
248
+ console.log('📝 Last Generated SQL:');
249
+ console.log('Query:', this.lastSqlQuery.sql);
250
+ console.log('Parameters:', JSON.stringify(this.lastSqlQuery.params));
251
+ if (this.lastFilter) {
252
+ console.log('Original Filter:', JSON.stringify(this.lastFilter, null, 2));
253
+ }
254
+ console.log('');
255
+ }
256
+ async showSample(count) {
257
+ if (!this.currentCollection) {
258
+ console.log('No collection selected. Use .use <collection> first.');
259
+ return;
260
+ }
261
+ try {
262
+ const collection = this.client.collection(this.currentCollection);
263
+ const results = await collection.find({}).limit(count).toArray();
264
+ console.log('');
265
+ console.log(`📋 Sample documents from "${this.currentCollection}" (${results.length} of ${count} requested):`);
266
+ if (results.length > 0) {
267
+ results.forEach((doc, index) => {
268
+ console.log(`[${index}]`, JSON.stringify(doc, null, 2));
269
+ });
270
+ }
271
+ else {
272
+ console.log('Collection is empty.');
273
+ }
274
+ console.log('');
275
+ }
276
+ catch (error) {
277
+ console.error('Error fetching sample:', error instanceof Error ? error.message : error);
278
+ }
279
+ }
280
+ async cleanup() {
281
+ console.log('\nClosing database connection...');
282
+ await this.client.close();
283
+ this.rl.close();
284
+ process.exit(0);
285
+ }
286
+ }
287
+ exports.QueryDebugger = QueryDebugger;
288
+ // Extended FindCursor that exposes SQL generation
289
+ class DebugFindCursor extends findCursor_js_1.FindCursor {
290
+ constructor(db, collectionName, filter, options = {}) {
291
+ super(db, collectionName, filter, options);
292
+ }
293
+ getSQL() {
294
+ // Access the private queryParts property
295
+ return this.queryParts;
296
+ }
297
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.MongoLite = exports.NodeSqliteAdapter = exports.BrowserSqliteAdapter = exports.CloudflareDurableObjectAdapter = exports.ChangeStream = exports.MongoLiteCollection = void 0;
18
+ const node_sqlite_js_1 = require("./adapters/node-sqlite.js");
19
+ const mongo_client_js_1 = require("./mongo-client.js");
20
+ var collection_js_1 = require("./collection.js");
21
+ Object.defineProperty(exports, "MongoLiteCollection", { enumerable: true, get: function () { return collection_js_1.MongoLiteCollection; } });
22
+ __exportStar(require("./types.js"), exports);
23
+ var changeStream_js_1 = require("./changeStream.js");
24
+ Object.defineProperty(exports, "ChangeStream", { enumerable: true, get: function () { return changeStream_js_1.ChangeStream; } });
25
+ var cloudflare_js_1 = require("./adapters/cloudflare.js");
26
+ Object.defineProperty(exports, "CloudflareDurableObjectAdapter", { enumerable: true, get: function () { return cloudflare_js_1.CloudflareDurableObjectAdapter; } });
27
+ var browser_js_1 = require("./adapters/browser.js");
28
+ Object.defineProperty(exports, "BrowserSqliteAdapter", { enumerable: true, get: function () { return browser_js_1.BrowserSqliteAdapter; } });
29
+ var node_sqlite_js_2 = require("./adapters/node-sqlite.js");
30
+ Object.defineProperty(exports, "NodeSqliteAdapter", { enumerable: true, get: function () { return node_sqlite_js_2.NodeSqliteAdapter; } });
31
+ /**
32
+ * MongoLite class is the main entry point for interacting with the SQLite-backed database.
33
+ *
34
+ * You can construct it with:
35
+ * - A file path string — uses the built-in `node:sqlite` adapter (`NodeSqliteAdapter`).
36
+ * Requires Node.js 22.5.0+; for older runtimes, import `MongoLite` from
37
+ * `@semics-tech/mongolite/better-sqlite3` instead.
38
+ * - A `MongoLiteClientOptions` object — uses the built-in adapter with options.
39
+ * - An `IDatabaseAdapter` instance — use a custom adapter such as
40
+ * `CloudflareDurableObjectAdapter` for Cloudflare Durable Objects.
41
+ */
42
+ class MongoLite extends mongo_client_js_1.MongoLite {
43
+ /**
44
+ * Creates a new MongoLite client instance.
45
+ * @param dbPathOrOptions Path to the SQLite database file, an options object,
46
+ * or an `IDatabaseAdapter` for custom backends.
47
+ */
48
+ constructor(dbPathOrOptions, options = {}) {
49
+ if (dbPathOrOptions &&
50
+ typeof dbPathOrOptions === 'object' &&
51
+ typeof dbPathOrOptions.connect === 'function' &&
52
+ typeof dbPathOrOptions.run === 'function' &&
53
+ typeof dbPathOrOptions.get === 'function' &&
54
+ typeof dbPathOrOptions.all === 'function' &&
55
+ typeof dbPathOrOptions.exec === 'function' &&
56
+ typeof dbPathOrOptions.close === 'function') {
57
+ // Custom adapter (e.g. CloudflareDurableObjectAdapter)
58
+ super(dbPathOrOptions, options);
59
+ }
60
+ else {
61
+ super(new node_sqlite_js_1.NodeSqliteAdapter(dbPathOrOptions), options);
62
+ }
63
+ }
64
+ }
65
+ exports.MongoLite = MongoLite;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongoLite = void 0;
4
+ const collection_js_1 = require("./collection.js");
5
+ /**
6
+ * Core MongoLite client. Accepts any `IDatabaseAdapter` implementation.
7
+ *
8
+ * This class is intentionally free of `better-sqlite3` dependencies so that it
9
+ * can be bundled for Cloudflare Workers / Durable Objects. For Node.js use, prefer
10
+ * importing `MongoLite` from the package root, which adds convenient constructor
11
+ * overloads for file paths and options objects.
12
+ */
13
+ class MongoLite {
14
+ constructor(adapter, options = {}) {
15
+ this.db = adapter;
16
+ this.options = options;
17
+ }
18
+ /**
19
+ * Connects to the database.
20
+ * For most custom adapters (e.g. Cloudflare) this is a no-op.
21
+ */
22
+ async connect() {
23
+ return this.db.connect();
24
+ }
25
+ /**
26
+ * Returns the underlying database adapter instance.
27
+ */
28
+ get database() {
29
+ return this.db;
30
+ }
31
+ /**
32
+ * Closes the database connection.
33
+ * For most custom adapters (e.g. Cloudflare) this is a no-op.
34
+ */
35
+ async close() {
36
+ return this.db.close();
37
+ }
38
+ /**
39
+ * Lists all collections (tables) in the database.
40
+ * @returns An object with a `toArray` method that resolves to an array of collection names.
41
+ */
42
+ listCollections() {
43
+ return {
44
+ toArray: async () => {
45
+ const result = await this.db.all(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`);
46
+ return result.map((row) => row.name);
47
+ },
48
+ };
49
+ }
50
+ /**
51
+ * Returns a typed collection handle.
52
+ * @param name The collection (table) name.
53
+ */
54
+ collection(name) {
55
+ return new collection_js_1.MongoLiteCollection(this.db, name, this.options);
56
+ }
57
+ }
58
+ exports.MongoLite = MongoLite;
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });