@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/LICENSE +1 -1
- package/README.md +38 -0
- package/dist/adapters/node-sqlite.d.ts +61 -0
- package/dist/adapters/node-sqlite.js +196 -0
- package/dist/adapters/node-sqlite.js.map +1 -0
- package/dist/better-sqlite3.d.ts +49 -0
- package/dist/better-sqlite3.js +60 -0
- package/dist/better-sqlite3.js.map +1 -0
- package/dist/bin/mongolite-debug.js +0 -0
- package/dist/cjs/adapters/browser.js +106 -0
- package/dist/cjs/adapters/cloudflare.js +97 -0
- package/dist/cjs/adapters/node-sqlite.js +199 -0
- package/dist/cjs/better-sqlite3.js +80 -0
- package/dist/cjs/bin/mongolite-debug.js +152 -0
- package/dist/cjs/changeStream.js +341 -0
- package/dist/cjs/cloudflare.js +59 -0
- package/dist/cjs/collection.js +1709 -0
- package/dist/cjs/cursors/findCursor.js +760 -0
- package/dist/cjs/db.js +260 -0
- package/dist/cjs/debugger/query-debugger.js +297 -0
- package/dist/cjs/index.js +65 -0
- package/dist/cjs/mongo-client.js +58 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils/indexing.js +45 -0
- package/dist/cjs/utils/projection.js +101 -0
- package/dist/cjs/utils/queryOperators.js +142 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/package.json +20 -10
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -32,6 +32,13 @@ A MongoDB-like client backed by SQLite. Use a familiar MongoDB API with the simp
|
|
|
32
32
|
npm install @semics-tech/mongolite
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Requires **Node.js 22.5.0+** by default — the main entry point is backed by
|
|
36
|
+
Node's built-in `node:sqlite` module, so there's no native addon to install or
|
|
37
|
+
build. On an older Node.js runtime, use the `better-sqlite3`-backed adapter
|
|
38
|
+
instead; see [Native `node:sqlite` vs. `better-sqlite3`](#native-nodesqlite-vs-better-sqlite3) below.
|
|
39
|
+
|
|
40
|
+
Ships both ESM (`import`) and CommonJS (`require`) builds — use whichever your project already uses.
|
|
41
|
+
|
|
35
42
|
## Quick Start
|
|
36
43
|
|
|
37
44
|
```typescript
|
|
@@ -112,6 +119,37 @@ await users.insertOne({ name: 'Alice', age: 30 });
|
|
|
112
119
|
await client.close();
|
|
113
120
|
```
|
|
114
121
|
|
|
122
|
+
### `better-sqlite3` (optional, for Node.js <22.5 or Bun)
|
|
123
|
+
|
|
124
|
+
The default backend above uses Node's built-in `node:sqlite` module, which
|
|
125
|
+
requires Node.js 22.5.0+. If you're on an older Node.js runtime, or you
|
|
126
|
+
simply prefer the more battle-tested native addon, import from the
|
|
127
|
+
`@semics-tech/mongolite/better-sqlite3` entry point instead. `better-sqlite3` is an
|
|
128
|
+
**optional dependency** — install it yourself if it wasn't already pulled in:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npm install better-sqlite3
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { MongoLite } from '@semics-tech/mongolite/better-sqlite3';
|
|
136
|
+
|
|
137
|
+
const client = new MongoLite('./myapp.sqlite');
|
|
138
|
+
await client.connect();
|
|
139
|
+
const users = client.collection('users');
|
|
140
|
+
await users.insertOne({ name: 'Alice', age: 30 });
|
|
141
|
+
await client.close();
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
<a id="native-nodesqlite-vs-better-sqlite3"></a>
|
|
145
|
+
> **Which one should I use?** `node:sqlite` (the default) is still marked
|
|
146
|
+
> experimental upstream but requires no native build step, which is why it's
|
|
147
|
+
> the default here. `better-sqlite3` is the older, more battle-tested native
|
|
148
|
+
> addon — reach for it if you're stuck on Node.js <22.5, targeting Bun without
|
|
149
|
+
> a `node:sqlite` polyfill, or want to avoid depending on an experimental
|
|
150
|
+
> Node.js API in production. Both implement the same `IDatabaseAdapter`
|
|
151
|
+
> interface, so switching between them is a one-line import change.
|
|
152
|
+
|
|
115
153
|
### Browser (via sql.js)
|
|
116
154
|
|
|
117
155
|
Requires [sql.js](https://www.npmjs.com/package/sql.js) (`npm install sql.js`).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { IDatabaseAdapter, MongoLiteOptions } from '../db.js';
|
|
3
|
+
/**
|
|
4
|
+
* Database adapter backed by Node.js's built-in `node:sqlite` module — no native
|
|
5
|
+
* addon, no prebuilt binary, no `node-gyp`. Requires Node.js 22.5.0+ (the module
|
|
6
|
+
* is marked experimental by Node.js until it graduates to stable).
|
|
7
|
+
*
|
|
8
|
+
* ## Usage
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { MongoLite, NodeSqliteAdapter } from '@semics-tech/mongolite';
|
|
12
|
+
*
|
|
13
|
+
* const client = new MongoLite(new NodeSqliteAdapter('./data.db'));
|
|
14
|
+
* await client.connect();
|
|
15
|
+
* const users = client.collection('users');
|
|
16
|
+
* await users.insertOne({ name: 'Alice', age: 30 });
|
|
17
|
+
* await client.close();
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* ## Limitations
|
|
21
|
+
*
|
|
22
|
+
* - **Experimental.** `node:sqlite` is still marked experimental upstream and its
|
|
23
|
+
* API may change between Node.js minor versions.
|
|
24
|
+
* - **Node.js 22.5.0+ only.** Importing this adapter on an older runtime (or on
|
|
25
|
+
* Bun/Deno without a `node:sqlite` polyfill) throws at import time.
|
|
26
|
+
* - Rows are returned with a `null` prototype (per `node:sqlite`'s API). Plain
|
|
27
|
+
* property access (`row.foo`) and `JSON.stringify`/`Object.keys` all work as
|
|
28
|
+
* expected; `row.hasOwnProperty(...)` does not.
|
|
29
|
+
*/
|
|
30
|
+
export declare class NodeSqliteAdapter implements IDatabaseAdapter {
|
|
31
|
+
private db;
|
|
32
|
+
private readonly filePath;
|
|
33
|
+
private readonly verbose;
|
|
34
|
+
private readonly readOnly;
|
|
35
|
+
private readonly WAL;
|
|
36
|
+
private openPromise;
|
|
37
|
+
/**
|
|
38
|
+
* @param dbPathOrOptions Path to the SQLite database file (use `':memory:'`
|
|
39
|
+
* for an in-memory database), or an options object mirroring the built-in
|
|
40
|
+
* `better-sqlite3` adapter's `MongoLiteOptions`.
|
|
41
|
+
*/
|
|
42
|
+
constructor(dbPathOrOptions: string | MongoLiteOptions);
|
|
43
|
+
/**
|
|
44
|
+
* Opens the database connection if it's not already open.
|
|
45
|
+
*/
|
|
46
|
+
connect(): Promise<void>;
|
|
47
|
+
private ensureConnected;
|
|
48
|
+
run(sql: string, params?: unknown[]): Promise<{
|
|
49
|
+
lastID: number;
|
|
50
|
+
changes: number;
|
|
51
|
+
}>;
|
|
52
|
+
get<T>(sql: string, params?: unknown[]): Promise<T | undefined>;
|
|
53
|
+
all<T>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
54
|
+
exec(sql: string): Promise<void>;
|
|
55
|
+
close(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the underlying `node:sqlite` `DatabaseSync` instance.
|
|
58
|
+
* Useful for operations not covered by this wrapper.
|
|
59
|
+
*/
|
|
60
|
+
getDbInstance(): Promise<DatabaseSync>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
/**
|
|
3
|
+
* Database adapter backed by Node.js's built-in `node:sqlite` module — no native
|
|
4
|
+
* addon, no prebuilt binary, no `node-gyp`. Requires Node.js 22.5.0+ (the module
|
|
5
|
+
* is marked experimental by Node.js until it graduates to stable).
|
|
6
|
+
*
|
|
7
|
+
* ## Usage
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { MongoLite, NodeSqliteAdapter } from '@semics-tech/mongolite';
|
|
11
|
+
*
|
|
12
|
+
* const client = new MongoLite(new NodeSqliteAdapter('./data.db'));
|
|
13
|
+
* await client.connect();
|
|
14
|
+
* const users = client.collection('users');
|
|
15
|
+
* await users.insertOne({ name: 'Alice', age: 30 });
|
|
16
|
+
* await client.close();
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* ## Limitations
|
|
20
|
+
*
|
|
21
|
+
* - **Experimental.** `node:sqlite` is still marked experimental upstream and its
|
|
22
|
+
* API may change between Node.js minor versions.
|
|
23
|
+
* - **Node.js 22.5.0+ only.** Importing this adapter on an older runtime (or on
|
|
24
|
+
* Bun/Deno without a `node:sqlite` polyfill) throws at import time.
|
|
25
|
+
* - Rows are returned with a `null` prototype (per `node:sqlite`'s API). Plain
|
|
26
|
+
* property access (`row.foo`) and `JSON.stringify`/`Object.keys` all work as
|
|
27
|
+
* expected; `row.hasOwnProperty(...)` does not.
|
|
28
|
+
*/
|
|
29
|
+
export class NodeSqliteAdapter {
|
|
30
|
+
/**
|
|
31
|
+
* @param dbPathOrOptions Path to the SQLite database file (use `':memory:'`
|
|
32
|
+
* for an in-memory database), or an options object mirroring the built-in
|
|
33
|
+
* `better-sqlite3` adapter's `MongoLiteOptions`.
|
|
34
|
+
*/
|
|
35
|
+
constructor(dbPathOrOptions) {
|
|
36
|
+
this.db = null;
|
|
37
|
+
this.openPromise = null;
|
|
38
|
+
if (typeof dbPathOrOptions === 'string') {
|
|
39
|
+
this.filePath = dbPathOrOptions;
|
|
40
|
+
this.verbose = false;
|
|
41
|
+
this.readOnly = false;
|
|
42
|
+
this.WAL = false;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.filePath = dbPathOrOptions.filePath;
|
|
46
|
+
this.verbose = dbPathOrOptions.verbose || false;
|
|
47
|
+
this.readOnly = dbPathOrOptions.readOnly || false;
|
|
48
|
+
this.WAL = dbPathOrOptions.WAL || true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Opens the database connection if it's not already open.
|
|
53
|
+
*/
|
|
54
|
+
async connect() {
|
|
55
|
+
if (this.db && this.openPromise) {
|
|
56
|
+
return this.openPromise;
|
|
57
|
+
}
|
|
58
|
+
if (this.db) {
|
|
59
|
+
return Promise.resolve();
|
|
60
|
+
}
|
|
61
|
+
this.openPromise = new Promise((resolve, reject) => {
|
|
62
|
+
try {
|
|
63
|
+
this.db = new DatabaseSync(this.filePath, { readOnly: this.readOnly });
|
|
64
|
+
if (this.WAL && !this.readOnly) {
|
|
65
|
+
this.db.exec('PRAGMA journal_mode = WAL');
|
|
66
|
+
}
|
|
67
|
+
// Register regexp UDF for $regex operator support.
|
|
68
|
+
// WARNING: Patterns are compiled via JavaScript RegExp. User-supplied patterns that are
|
|
69
|
+
// not validated for catastrophic backtracking (ReDoS) could block the event loop.
|
|
70
|
+
// Avoid using untrusted/unvalidated patterns with $regex in security-sensitive contexts.
|
|
71
|
+
this.db.function('regexp', { deterministic: true }, (pattern, value) => {
|
|
72
|
+
if (typeof pattern !== 'string' || value === null || value === undefined)
|
|
73
|
+
return 0;
|
|
74
|
+
try {
|
|
75
|
+
return new RegExp(pattern).test(String(value)) ? 1 : 0;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// Register regexp_flags UDF for $regex with $options support
|
|
82
|
+
this.db.function('regexp_flags', { deterministic: true }, (pattern, flags, value) => {
|
|
83
|
+
if (typeof pattern !== 'string' || value === null || value === undefined)
|
|
84
|
+
return 0;
|
|
85
|
+
try {
|
|
86
|
+
const f = typeof flags === 'string' ? flags : '';
|
|
87
|
+
return new RegExp(pattern, f).test(String(value)) ? 1 : 0;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
if (this.verbose) {
|
|
94
|
+
console.log(`SQLite database opened (node:sqlite): ${this.filePath}`);
|
|
95
|
+
}
|
|
96
|
+
resolve();
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
console.error(`Error opening database ${this.filePath}:`, err.message);
|
|
100
|
+
this.db = null;
|
|
101
|
+
this.openPromise = null;
|
|
102
|
+
reject(err);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return this.openPromise;
|
|
106
|
+
}
|
|
107
|
+
async ensureConnected() {
|
|
108
|
+
if (!this.db || !this.openPromise) {
|
|
109
|
+
await this.connect();
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
await this.openPromise;
|
|
113
|
+
}
|
|
114
|
+
if (!this.db) {
|
|
115
|
+
throw new Error('Database is not connected. Connection attempt failed.');
|
|
116
|
+
}
|
|
117
|
+
return this.db;
|
|
118
|
+
}
|
|
119
|
+
async run(sql, params = []) {
|
|
120
|
+
const dbInstance = await this.ensureConnected();
|
|
121
|
+
try {
|
|
122
|
+
const result = dbInstance.prepare(sql).run(...params);
|
|
123
|
+
return {
|
|
124
|
+
lastID: Number(result.lastInsertRowid),
|
|
125
|
+
changes: Number(result.changes),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
console.error(`Error running SQL: ${sql}`, err);
|
|
130
|
+
throw err;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async get(sql, params = []) {
|
|
134
|
+
const dbInstance = await this.ensureConnected();
|
|
135
|
+
try {
|
|
136
|
+
return dbInstance.prepare(sql).get(...params);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
console.error(`Error getting SQL: ${sql}`, err);
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async all(sql, params = []) {
|
|
144
|
+
const dbInstance = await this.ensureConnected();
|
|
145
|
+
try {
|
|
146
|
+
return dbInstance.prepare(sql).all(...params);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.error(`Error getting all SQL: ${sql}`, err);
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async exec(sql) {
|
|
154
|
+
const dbInstance = await this.ensureConnected();
|
|
155
|
+
try {
|
|
156
|
+
dbInstance.exec(sql);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
console.error(`Error executing SQL: ${sql}`, err);
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async close() {
|
|
164
|
+
if (this.openPromise) {
|
|
165
|
+
await this.openPromise;
|
|
166
|
+
}
|
|
167
|
+
if (this.db) {
|
|
168
|
+
try {
|
|
169
|
+
this.db.close();
|
|
170
|
+
if (this.verbose) {
|
|
171
|
+
console.log(`SQLite database closed (node:sqlite): ${this.filePath}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
console.error(`Error closing database ${this.filePath}:`, err.message);
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
this.db = null;
|
|
180
|
+
this.openPromise = null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
this.db = null;
|
|
185
|
+
this.openPromise = null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Gets the underlying `node:sqlite` `DatabaseSync` instance.
|
|
190
|
+
* Useful for operations not covered by this wrapper.
|
|
191
|
+
*/
|
|
192
|
+
async getDbInstance() {
|
|
193
|
+
return this.ensureConnected();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=node-sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../src/adapters/node-sqlite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `better-sqlite3`-backed entry point for MongoLite.
|
|
3
|
+
*
|
|
4
|
+
* The main `@semics-tech/mongolite` entry point defaults to `NodeSqliteAdapter`, backed by
|
|
5
|
+
* Node.js's built-in `node:sqlite` module, which requires Node.js 22.5.0+. Import
|
|
6
|
+
* from `@semics-tech/mongolite/better-sqlite3` instead if you need to run on an older
|
|
7
|
+
* Node.js runtime, or you simply prefer the more battle-tested `better-sqlite3`
|
|
8
|
+
* native addon.
|
|
9
|
+
*
|
|
10
|
+
* `better-sqlite3` is an **optional dependency** of this package — install it
|
|
11
|
+
* yourself if it wasn't already pulled in:
|
|
12
|
+
*
|
|
13
|
+
* ```bash
|
|
14
|
+
* npm install better-sqlite3
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* ## Usage
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { MongoLite } from '@semics-tech/mongolite/better-sqlite3';
|
|
21
|
+
*
|
|
22
|
+
* const client = new MongoLite('./myapp.sqlite');
|
|
23
|
+
* await client.connect();
|
|
24
|
+
* const users = client.collection('users');
|
|
25
|
+
* await users.insertOne({ name: 'Alice', age: 30 });
|
|
26
|
+
* await client.close();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import type { IDatabaseAdapter, MongoLiteOptions as DBMongoLiteOptions } from './db.js';
|
|
30
|
+
import { MongoLite as MongoLiteBase, MongoLiteBaseOptions } from './mongo-client.js';
|
|
31
|
+
export { MongoLiteCollection } from './collection.js';
|
|
32
|
+
export * from './types.js';
|
|
33
|
+
export { ChangeStream } from './changeStream.js';
|
|
34
|
+
export type { ChangeStreamDocument, ChangeStreamOptions, ChangeOperationType, } from './changeStream.js';
|
|
35
|
+
export type { IDatabaseAdapter } from './db.js';
|
|
36
|
+
export { SQLiteDB } from './db.js';
|
|
37
|
+
export interface MongoLiteClientOptions extends DBMongoLiteOptions {
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* MongoLite client backed by the `better-sqlite3` native addon.
|
|
41
|
+
*
|
|
42
|
+
* You can construct it with:
|
|
43
|
+
* - A file path string — uses the built-in `SQLiteDB` (`better-sqlite3`) adapter.
|
|
44
|
+
* - A `MongoLiteClientOptions` object — uses the built-in adapter with options.
|
|
45
|
+
* - An `IDatabaseAdapter` instance — use a custom adapter for other backends.
|
|
46
|
+
*/
|
|
47
|
+
export declare class MongoLite extends MongoLiteBase {
|
|
48
|
+
constructor(dbPathOrOptions: string | MongoLiteClientOptions | IDatabaseAdapter, options?: MongoLiteBaseOptions);
|
|
49
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `better-sqlite3`-backed entry point for MongoLite.
|
|
3
|
+
*
|
|
4
|
+
* The main `@semics-tech/mongolite` entry point defaults to `NodeSqliteAdapter`, backed by
|
|
5
|
+
* Node.js's built-in `node:sqlite` module, which requires Node.js 22.5.0+. Import
|
|
6
|
+
* from `@semics-tech/mongolite/better-sqlite3` instead if you need to run on an older
|
|
7
|
+
* Node.js runtime, or you simply prefer the more battle-tested `better-sqlite3`
|
|
8
|
+
* native addon.
|
|
9
|
+
*
|
|
10
|
+
* `better-sqlite3` is an **optional dependency** of this package — install it
|
|
11
|
+
* yourself if it wasn't already pulled in:
|
|
12
|
+
*
|
|
13
|
+
* ```bash
|
|
14
|
+
* npm install better-sqlite3
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* ## Usage
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { MongoLite } from '@semics-tech/mongolite/better-sqlite3';
|
|
21
|
+
*
|
|
22
|
+
* const client = new MongoLite('./myapp.sqlite');
|
|
23
|
+
* await client.connect();
|
|
24
|
+
* const users = client.collection('users');
|
|
25
|
+
* await users.insertOne({ name: 'Alice', age: 30 });
|
|
26
|
+
* await client.close();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { SQLiteDB } from './db.js';
|
|
30
|
+
import { MongoLite as MongoLiteBase } from './mongo-client.js';
|
|
31
|
+
export { MongoLiteCollection } from './collection.js';
|
|
32
|
+
export * from './types.js';
|
|
33
|
+
export { ChangeStream } from './changeStream.js';
|
|
34
|
+
export { SQLiteDB } from './db.js';
|
|
35
|
+
/**
|
|
36
|
+
* MongoLite client backed by the `better-sqlite3` native addon.
|
|
37
|
+
*
|
|
38
|
+
* You can construct it with:
|
|
39
|
+
* - A file path string — uses the built-in `SQLiteDB` (`better-sqlite3`) adapter.
|
|
40
|
+
* - A `MongoLiteClientOptions` object — uses the built-in adapter with options.
|
|
41
|
+
* - An `IDatabaseAdapter` instance — use a custom adapter for other backends.
|
|
42
|
+
*/
|
|
43
|
+
export class MongoLite extends MongoLiteBase {
|
|
44
|
+
constructor(dbPathOrOptions, options = {}) {
|
|
45
|
+
if (dbPathOrOptions &&
|
|
46
|
+
typeof dbPathOrOptions === 'object' &&
|
|
47
|
+
typeof dbPathOrOptions.connect === 'function' &&
|
|
48
|
+
typeof dbPathOrOptions.run === 'function' &&
|
|
49
|
+
typeof dbPathOrOptions.get === 'function' &&
|
|
50
|
+
typeof dbPathOrOptions.all === 'function' &&
|
|
51
|
+
typeof dbPathOrOptions.exec === 'function' &&
|
|
52
|
+
typeof dbPathOrOptions.close === 'function') {
|
|
53
|
+
super(dbPathOrOptions, options);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
super(new SQLiteDB(dbPathOrOptions), options);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=better-sqlite3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"better-sqlite3.js","sourceRoot":"","sources":["../src/better-sqlite3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,SAAS,IAAI,aAAa,EAAwB,MAAM,mBAAmB,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOjD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAInC;;;;;;;GAOG;AACH,MAAM,OAAO,SAAU,SAAQ,aAAa;IAC1C,YACE,eAAmE,EACnE,UAAgC,EAAE;QAElC,IACE,eAAe;YACf,OAAO,eAAe,KAAK,QAAQ;YACnC,OAAQ,eAAoC,CAAC,OAAO,KAAK,UAAU;YACnE,OAAQ,eAAoC,CAAC,GAAG,KAAK,UAAU;YAC/D,OAAQ,eAAoC,CAAC,GAAG,KAAK,UAAU;YAC/D,OAAQ,eAAoC,CAAC,GAAG,KAAK,UAAU;YAC/D,OAAQ,eAAoC,CAAC,IAAI,KAAK,UAAU;YAChE,OAAQ,eAAoC,CAAC,KAAK,KAAK,UAAU,EACjE,CAAC;YACD,KAAK,CAAC,eAAmC,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,QAAQ,CAAC,eAAkD,CAAC,EAAE,OAAO,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;CACF"}
|
|
File without changes
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BrowserSqliteAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Database adapter that wraps a {@link SqlJsDatabase} instance, enabling MongoLite
|
|
6
|
+
* to run in browser environments via [sql.js](https://sql.js.org/).
|
|
7
|
+
*
|
|
8
|
+
* ## Usage
|
|
9
|
+
*
|
|
10
|
+
* Install [sql.js](https://www.npmjs.com/package/sql.js) and initialise it before
|
|
11
|
+
* constructing the adapter:
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* import initSqlJs from 'sql.js';
|
|
15
|
+
* import { MongoLite, BrowserSqliteAdapter } from '@semics-tech/mongolite';
|
|
16
|
+
*
|
|
17
|
+
* const SQL = await initSqlJs({
|
|
18
|
+
* locateFile: (file) => `https://cdn.jsdelivr.net/npm/sql.js/dist/${file}`,
|
|
19
|
+
* });
|
|
20
|
+
* const sqlJsDb = new SQL.Database(); // in-memory; persist via OPFS or IndexedDB
|
|
21
|
+
*
|
|
22
|
+
* const client = new MongoLite(new BrowserSqliteAdapter(sqlJsDb));
|
|
23
|
+
* await client.connect();
|
|
24
|
+
* const users = client.collection('users');
|
|
25
|
+
* await users.insertOne({ name: 'Alice', age: 30 });
|
|
26
|
+
* await client.close();
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* ## Limitations
|
|
30
|
+
*
|
|
31
|
+
* - **`$regex` queries are not supported** — sql.js does not ship with a `regexp()`
|
|
32
|
+
* SQL function. Use JS-side filtering as a workaround.
|
|
33
|
+
* - **`lastID` / `changes`** are not exposed by the sql.js API. `run()` always
|
|
34
|
+
* returns `{ lastID: 0, changes: 0 }`, which is safe because MongoLite does not
|
|
35
|
+
* use these values internally.
|
|
36
|
+
* - **Persistence** — by default sql.js stores data in memory. For durable storage
|
|
37
|
+
* use the OPFS back-end or export the database buffer to IndexedDB.
|
|
38
|
+
*/
|
|
39
|
+
class BrowserSqliteAdapter {
|
|
40
|
+
/**
|
|
41
|
+
* @param db An initialised sql.js `Database` instance.
|
|
42
|
+
*/
|
|
43
|
+
constructor(db) {
|
|
44
|
+
this.db = db;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* No-op: sql.js Database is already open on construction.
|
|
48
|
+
*/
|
|
49
|
+
async connect() {
|
|
50
|
+
// Nothing to do — the sql.js Database is ready to use immediately.
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Closes the underlying sql.js Database and frees its WASM memory.
|
|
54
|
+
*/
|
|
55
|
+
async close() {
|
|
56
|
+
this.db.close();
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Executes a DML statement (INSERT, UPDATE, DELETE) with optional bound parameters.
|
|
60
|
+
* Returns `{ lastID: 0, changes: 0 }` — sql.js does not expose these values.
|
|
61
|
+
*/
|
|
62
|
+
async run(sql, params = []) {
|
|
63
|
+
this.db.run(sql, params);
|
|
64
|
+
return { lastID: 0, changes: 0 };
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Executes a SQL query and returns the first matching row, or `undefined`.
|
|
68
|
+
*/
|
|
69
|
+
async get(sql, params = []) {
|
|
70
|
+
const stmt = this.db.prepare(sql);
|
|
71
|
+
try {
|
|
72
|
+
stmt.bind(params);
|
|
73
|
+
if (stmt.step()) {
|
|
74
|
+
return stmt.getAsObject();
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
stmt.free();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Executes a SQL query and returns all matching rows.
|
|
84
|
+
*/
|
|
85
|
+
async all(sql, params = []) {
|
|
86
|
+
const stmt = this.db.prepare(sql);
|
|
87
|
+
try {
|
|
88
|
+
stmt.bind(params);
|
|
89
|
+
const rows = [];
|
|
90
|
+
while (stmt.step()) {
|
|
91
|
+
rows.push(stmt.getAsObject());
|
|
92
|
+
}
|
|
93
|
+
return rows;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
stmt.free();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Executes one or more SQL statements (DDL, transactions, etc.).
|
|
101
|
+
*/
|
|
102
|
+
async exec(sql) {
|
|
103
|
+
this.db.exec(sql);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.BrowserSqliteAdapter = BrowserSqliteAdapter;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CloudflareDurableObjectAdapter = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Database adapter that wraps the Cloudflare Durable Objects `SqlStorage` API,
|
|
6
|
+
* allowing MongoLite to be used inside a Cloudflare Durable Object.
|
|
7
|
+
*
|
|
8
|
+
* ## Usage
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { DurableObject } from 'cloudflare:workers';
|
|
12
|
+
* import { MongoLite, CloudflareDurableObjectAdapter } from '@semics-tech/mongolite/cloudflare';
|
|
13
|
+
*
|
|
14
|
+
* export class MyDurableObject extends DurableObject {
|
|
15
|
+
* private client: MongoLite;
|
|
16
|
+
*
|
|
17
|
+
* constructor(ctx: DurableObjectState, env: Env) {
|
|
18
|
+
* super(ctx, env);
|
|
19
|
+
* const adapter = new CloudflareDurableObjectAdapter(ctx.storage.sql);
|
|
20
|
+
* this.client = new MongoLite(adapter);
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* async fetch(request: Request) {
|
|
24
|
+
* await this.client.connect();
|
|
25
|
+
* const users = this.client.collection('users');
|
|
26
|
+
* await users.insertOne({ name: 'Alice', age: 30 });
|
|
27
|
+
* const user = await users.findOne({ name: 'Alice' });
|
|
28
|
+
* return Response.json(user);
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* ## Limitations
|
|
34
|
+
*
|
|
35
|
+
* - **`$regex` queries are not supported.** Cloudflare's SQLite does not allow custom
|
|
36
|
+
* SQL functions, so the `regexp()` UDF registered by the default Node.js adapter is
|
|
37
|
+
* unavailable. Queries using `$regex` will throw a SQL error at runtime.
|
|
38
|
+
* - `WAL` mode and most `PRAGMA` statements are not available in Cloudflare Durable
|
|
39
|
+
* Objects (Cloudflare manages this internally).
|
|
40
|
+
* - Change Streams (`collection.watch()`) use SQL triggers and a change-log table.
|
|
41
|
+
* They work in Cloudflare Durable Objects, but the polling mechanism relies on
|
|
42
|
+
* `setInterval`, which is supported in the Workers runtime.
|
|
43
|
+
*/
|
|
44
|
+
class CloudflareDurableObjectAdapter {
|
|
45
|
+
/**
|
|
46
|
+
* @param sql The `SqlStorage` instance from a Cloudflare Durable Object context
|
|
47
|
+
* (i.e. `ctx.storage.sql`).
|
|
48
|
+
*/
|
|
49
|
+
constructor(sql) {
|
|
50
|
+
this.sql = sql;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* No-op: Cloudflare Durable Objects manage the storage lifecycle automatically.
|
|
54
|
+
*/
|
|
55
|
+
async connect() {
|
|
56
|
+
// Nothing to do — the SqlStorage instance is already live.
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* No-op: Cloudflare Durable Objects manage the storage lifecycle automatically.
|
|
60
|
+
*/
|
|
61
|
+
async close() {
|
|
62
|
+
// Nothing to do — storage is managed by the Durable Object runtime.
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Executes a SQL statement that does not return rows (INSERT, UPDATE, DELETE, DDL).
|
|
66
|
+
*/
|
|
67
|
+
async run(sql, params = []) {
|
|
68
|
+
const cursor = this.sql.exec(sql, ...params);
|
|
69
|
+
return { lastID: 0, changes: cursor.rowsWritten };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Executes a SQL query and returns the first matching row, or `undefined`.
|
|
73
|
+
*/
|
|
74
|
+
async get(sql, params = []) {
|
|
75
|
+
const rows = this.sql.exec(sql, ...params).toArray();
|
|
76
|
+
return rows[0];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Executes a SQL query and returns all matching rows.
|
|
80
|
+
*/
|
|
81
|
+
async all(sql, params = []) {
|
|
82
|
+
return this.sql.exec(sql, ...params).toArray();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Executes a single SQL statement (DDL, transactions, etc.).
|
|
86
|
+
*
|
|
87
|
+
* Cloudflare's `SqlStorage.exec` only supports one statement at a time, and
|
|
88
|
+
* some valid statements (e.g. `CREATE TRIGGER ... BEGIN ...; ...; END;`)
|
|
89
|
+
* contain internal semicolons. Callers must therefore pass exactly one
|
|
90
|
+
* statement per call; this method will not attempt to split multi-statement
|
|
91
|
+
* SQL strings.
|
|
92
|
+
*/
|
|
93
|
+
async exec(sql) {
|
|
94
|
+
this.sql.exec(sql);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.CloudflareDurableObjectAdapter = CloudflareDurableObjectAdapter;
|