@procedures/sqlite 0.3.0 → 0.5.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 (52) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +93 -32
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/engines.d.ts +68 -0
  5. package/dist/engines.d.ts.map +1 -0
  6. package/dist/engines.js +268 -0
  7. package/dist/engines.js.map +1 -0
  8. package/dist/index.d.ts +3 -3
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +4 -4
  11. package/dist/index.js.map +1 -1
  12. package/dist/module.d.ts +13 -3
  13. package/dist/module.d.ts.map +1 -1
  14. package/dist/module.js +60 -27
  15. package/dist/module.js.map +1 -1
  16. package/dist/procedures/db/backup.d.ts +1 -1
  17. package/dist/procedures/db/backup.js +6 -6
  18. package/dist/procedures/db/backup.js.map +1 -1
  19. package/dist/procedures/db/migrate.d.ts +1 -1
  20. package/dist/procedures/db/migrate.js +8 -8
  21. package/dist/procedures/db/migrate.js.map +1 -1
  22. package/dist/procedures/db/schema.d.ts +1 -1
  23. package/dist/procedures/db/schema.js +3 -3
  24. package/dist/procedures/db/schema.js.map +1 -1
  25. package/dist/procedures/db/shared.d.ts +1 -1
  26. package/dist/procedures/db/shared.js +1 -1
  27. package/dist/procedures/db/tables.d.ts +1 -1
  28. package/dist/procedures/db/tables.js +2 -2
  29. package/dist/procedures/db/tables.js.map +1 -1
  30. package/dist/procedures/db/transaction.d.ts +1 -1
  31. package/dist/procedures/db/transaction.js +2 -2
  32. package/dist/procedures/db/transaction.js.map +1 -1
  33. package/dist/storage.d.ts +57 -16
  34. package/dist/storage.d.ts.map +1 -1
  35. package/dist/storage.js +255 -148
  36. package/dist/storage.js.map +1 -1
  37. package/dist/types.d.ts +1 -1
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/types.js +2 -2
  40. package/dist/types.js.map +1 -1
  41. package/package.json +6 -5
  42. package/src/engines.ts +360 -0
  43. package/src/index.ts +12 -4
  44. package/src/module.ts +65 -28
  45. package/src/procedures/db/backup.ts +6 -6
  46. package/src/procedures/db/migrate.ts +8 -8
  47. package/src/procedures/db/schema.ts +3 -3
  48. package/src/procedures/db/shared.ts +1 -1
  49. package/src/procedures/db/tables.ts +2 -2
  50. package/src/procedures/db/transaction.ts +2 -2
  51. package/src/storage.ts +335 -176
  52. package/src/types.ts +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # @procedures/sqlite
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 89481b0: `SqliteStorage` has two engines. The new option `engine` is `"auto"` (the default), `"node"` or `"sqljs"`.
8
+
9
+ - The engine `node` is `node:sqlite` of Node.js 22.13 and later. SQLite writes only the changed pages of the file. Before, sql.js wrote the whole file after each write, so a write to a large collection was slow.
10
+ - In the nightly benchmark, 1,000 writes one after the other to a file of 1,000 items take 141 ms with `node` and 1,246 ms with `sqljs`.
11
+ - With `node`, the file is in WAL mode with a busy timeout (the new option `busyTimeout`, 5 seconds by default). Two processes can use one file: a write waits for the lock of the other process, and the versions of the change log agree.
12
+ - The engine `sqljs` is sql.js, as before. The engine `auto` uses it when the import of `node:sqlite` fails, for example on Node.js 22.12 and before.
13
+ - The two engines use one file format: a file of one engine opens with the other, with its items and its versions.
14
+ - The guarantees stay for each engine:
15
+ - Each write runs in one transaction.
16
+ - The storages of one file in one process share one database.
17
+ - The change log and its versions stay valid after a restart.
18
+ - A storage that only reads does not make the file.
19
+ - The contract of `close()` does not change.
20
+ - The storages of one file in one process share one engine. A storage with the other engine refuses the open database.
21
+ - sql.js refuses a file with a write-ahead log of the engine `node` that holds changes.
22
+ - New: `getEngine()`, `getIds()` (the ids without the values), `isNodeSqliteAvailable()`, and `stats.engine` in `getMetadata()`.
23
+ - `getChangesSince()` reads in one read transaction, and it reads the epoch from the file at each call.
24
+ - bc74091: After `close()`, each operation of `SqliteStorage` and `MongoStorage` rejects with an error that says "closed", and a second `close()` does nothing. Before, `SqliteStorage.flush()` and an empty batch resolved after `close()`, and `MongoStorage` kept working.
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [0f75644]
29
+ - Updated dependencies [09e5566]
30
+ - Updated dependencies [ab77f75]
31
+ - Updated dependencies [a47bee6]
32
+ - Updated dependencies [bc74091]
33
+ - @procedures/client@0.5.0
34
+
35
+ ## 0.4.0
36
+
37
+ ### Minor Changes
38
+
39
+ - cc3f5f6: The SQLite procedures have the namespace `sqlite`, not the general namespace `db`: `sqlite.query`, `sqlite.execute`, `sqlite.tables`, `sqlite.schema`, `sqlite.transaction`, `sqlite.migrate` and `sqlite.backup`. The `logs.*` procedures keep their names.
40
+
41
+ The old names stay for one release as deprecated aliases (`db.query` and the others). Each alias has the same handler, the same schemas and the same effects. Its description starts with `Deprecated: use sqlite.<name>`, and its metadata has `deprecated: true`. The next release removes the aliases.
42
+
43
+ The description of the `dbPath` field does not show the home folder of the computer any more. It says `~/logs/cli/cli.db`.
44
+
45
+ ### Patch Changes
46
+
47
+ - Updated dependencies [d919678]
48
+ - Updated dependencies [057d69a]
49
+ - Updated dependencies [b2a1a1e]
50
+ - Updated dependencies [057d69a]
51
+ - Updated dependencies [057d69a]
52
+ - Updated dependencies [057d69a]
53
+ - Updated dependencies [057d69a]
54
+ - Updated dependencies [057d69a]
55
+ - Updated dependencies [afd6a19]
56
+ - Updated dependencies [057d69a]
57
+ - Updated dependencies [4e751da]
58
+ - @procedures/client@0.4.0
59
+
3
60
  ## 0.3.0
4
61
 
5
62
  ### Minor Changes
package/README.md CHANGED
@@ -18,9 +18,17 @@ SQLite database operations via client procedures. Execute queries and store stru
18
18
  - **A collection storage**: `SqliteStorage` keeps a collection in a SQLite table, with a change log
19
19
 
20
20
  The package has 9 procedures. Its register entry (`import "@procedures/sqlite/register"`) registers them:
21
- - **Database**: `db.query`, `db.execute`, `db.tables`, `db.schema`, `db.transaction`, `db.migrate`, `db.backup`
21
+ - **Database**: `sqlite.query`, `sqlite.execute`, `sqlite.tables`, `sqlite.schema`, `sqlite.transaction`, `sqlite.migrate`, `sqlite.backup`
22
22
  - **Logs**: `logs.store`, `logs.query`
23
23
 
24
+ ### The old names `db.*`
25
+
26
+ In version 0.3.0 and before, the database procedures had the namespace `db`. The general name `db` did not tell the database. Since version 0.4.0, the namespace is `sqlite`.
27
+
28
+ The old names stay for one release as deprecated aliases: `db.query`, `db.execute`, `db.tables`, `db.schema`, `db.transaction`, `db.migrate` and `db.backup`. Each alias has the same handler, the same schemas and the same effects as its new procedure. Its description starts with `Deprecated: use sqlite.<name>`. The next release removes the aliases.
29
+
30
+ The MCP server (`bundle-mcp`) does not expose the aliases. Its tools are `sqlite.query`, `sqlite.execute`, `sqlite.tables` and `sqlite.schema`. The `logs.*` procedures keep their names.
31
+
24
32
  ## Architecture
25
33
 
26
34
  ```mermaid
@@ -34,7 +42,7 @@ graph TB
34
42
  Register["register.ts<br/>(Auto-registers procedures)"]
35
43
 
36
44
  subgraph "Procedure Categories"
37
- DB["Database Procedures<br/>db.query, db.execute, db.tables, db.schema,<br/>db.transaction, db.migrate, db.backup"]
45
+ DB["Database Procedures<br/>sqlite.query, sqlite.execute, sqlite.tables, sqlite.schema,<br/>sqlite.transaction, sqlite.migrate, sqlite.backup"]
38
46
  Logs["Log Procedures<br/>logs.store, logs.query"]
39
47
  end
40
48
 
@@ -148,7 +156,7 @@ You can override this path in each procedure call:
148
156
 
149
157
  ```typescript
150
158
  await client.exec(
151
- ["db", "query"],
159
+ ["sqlite", "query"],
152
160
  {
153
161
  sql: "SELECT * FROM logs",
154
162
  dbPath: "./custom/path/database.db"
@@ -160,13 +168,13 @@ await client.exec(
160
168
 
161
169
  ### Database Procedures
162
170
 
163
- #### `db.query`
171
+ #### `sqlite.query`
164
172
 
165
173
  Execute a SQL SELECT query and return rows.
166
174
 
167
175
  ```typescript
168
176
  const result = await client.exec(
169
- ["db", "query"],
177
+ ["sqlite", "query"],
170
178
  {
171
179
  sql: "SELECT * FROM logs WHERE level = ? ORDER BY timestamp DESC",
172
180
  params: ["error"]
@@ -197,7 +205,7 @@ interface DbQueryOutput<T = Record<string, unknown>> {
197
205
  **Example:**
198
206
  ```typescript
199
207
  const result = await client.exec(
200
- ["db", "query"],
208
+ ["sqlite", "query"],
201
209
  {
202
210
  sql: `
203
211
  SELECT level, COUNT(*) as count
@@ -212,13 +220,13 @@ const result = await client.exec(
212
220
  // result.rows = [{ level: "info", count: 45 }, { level: "error", count: 2 }]
213
221
  ```
214
222
 
215
- #### `db.execute`
223
+ #### `sqlite.execute`
216
224
 
217
225
  Execute a SQL statement (INSERT, UPDATE, DELETE) and return the number of affected rows.
218
226
 
219
227
  ```typescript
220
228
  const result = await client.exec(
221
- ["db", "execute"],
229
+ ["sqlite", "execute"],
222
230
  {
223
231
  sql: "DELETE FROM logs WHERE timestamp < ?",
224
232
  params: ["2024-01-01"]
@@ -248,7 +256,7 @@ interface DbExecuteOutput {
248
256
  ```typescript
249
257
  // INSERT
250
258
  await client.exec(
251
- ["db", "execute"],
259
+ ["sqlite", "execute"],
252
260
  {
253
261
  sql: "INSERT INTO users (name, email) VALUES (?, ?)",
254
262
  params: ["Alice", "alice@example.com"]
@@ -257,7 +265,7 @@ await client.exec(
257
265
 
258
266
  // UPDATE
259
267
  await client.exec(
260
- ["db", "execute"],
268
+ ["sqlite", "execute"],
261
269
  {
262
270
  sql: "UPDATE users SET active = ? WHERE id = ?",
263
271
  params: [true, 123]
@@ -266,7 +274,7 @@ await client.exec(
266
274
 
267
275
  // DELETE
268
276
  await client.exec(
269
- ["db", "execute"],
277
+ ["sqlite", "execute"],
270
278
  {
271
279
  sql: "DELETE FROM users WHERE active = ?",
272
280
  params: [false]
@@ -274,29 +282,29 @@ await client.exec(
274
282
  );
275
283
  ```
276
284
 
277
- #### `db.tables`
285
+ #### `sqlite.tables`
278
286
 
279
287
  The procedure lists the tables and the views of a database, without the internal `sqlite_` tables. Each item has the `name`, the `type` and the `sql` that made it. With `views: false`, it gives only the tables. The procedure only reads. A missing file is an error (`ENOENT`), and the procedure does not make it.
280
288
 
281
289
  ```typescript
282
- const { tables } = await client.exec(["db", "tables"], { dbPath: "./app.db" });
290
+ const { tables } = await client.exec(["sqlite", "tables"], { dbPath: "./app.db" });
283
291
  ```
284
292
 
285
- #### `db.schema`
293
+ #### `sqlite.schema`
286
294
 
287
295
  The procedure gives the `columns`, the `indexes` and the `foreignKeys` of a table, or the columns of a view. The name of the table goes to SQLite as a bound value, not as SQL text. The procedure only reads.
288
296
 
289
297
  ```typescript
290
- const schema = await client.exec(["db", "schema"], { dbPath: "./app.db", table: "users" });
298
+ const schema = await client.exec(["sqlite", "schema"], { dbPath: "./app.db", table: "users" });
291
299
  // schema.columns: [{ name: "id", type: "INTEGER", notNull: false, defaultValue: null, primaryKey: 1 }, ...]
292
300
  ```
293
301
 
294
- #### `db.transaction`
302
+ #### `sqlite.transaction`
295
303
 
296
304
  The procedure puts a list of statements in one transaction. When one statement fails, it rolls back the transaction, and the file stays as it was. The `params` of a statement bind to one statement. Without `params`, one `sql` can hold several statements. A statement that gives rows (`SELECT`, or `RETURNING`) gives its `rows` in its result. The procedure refuses `BEGIN`, `COMMIT`, `ROLLBACK`, `SAVEPOINT` and `RELEASE`, because it controls the transaction itself.
297
305
 
298
306
  ```typescript
299
- const { results, changes } = await client.exec(["db", "transaction"], {
307
+ const { results, changes } = await client.exec(["sqlite", "transaction"], {
300
308
  dbPath: "./app.db",
301
309
  statements: [
302
310
  { sql: "UPDATE accounts SET balance = balance - ? WHERE id = ?", params: [10, 1] },
@@ -306,7 +314,7 @@ const { results, changes } = await client.exec(["db", "transaction"], {
306
314
  });
307
315
  ```
308
316
 
309
- #### `db.migrate`
317
+ #### `sqlite.migrate`
310
318
 
311
319
  The procedure applies the numbered migrations that the database does not have, in the order of their numbers. The migrations come from a `folder` or from a list (`migrations`). In a folder, each migration is a file `<number>_<name>.sql`, for example `001_create_users.sql`. The procedure ignores the files that do not end in `.sql`.
312
320
 
@@ -317,20 +325,20 @@ The procedure applies the numbered migrations that the database does not have, i
317
325
  - A migration must not hold `BEGIN`, `COMMIT` or `ROLLBACK`.
318
326
 
319
327
  ```typescript
320
- const { applied, skipped, version } = await client.exec(["db", "migrate"], {
328
+ const { applied, skipped, version } = await client.exec(["sqlite", "migrate"], {
321
329
  dbPath: "./app.db",
322
330
  folder: "./migrations",
323
331
  });
324
332
  ```
325
333
 
326
- #### `db.backup`
334
+ #### `sqlite.backup`
327
335
 
328
336
  The procedure copies a database to a new file (`to`). It does not replace a file, and it does not write the source. With `vacuum: true`, it compacts the copy.
329
337
 
330
338
  This package uses SQLite in WebAssembly (sql.js). The database is in the memory of the module. `VACUUM INTO` and the backup API of SQLite write into the file system of the module, not to the disk. Thus the procedure writes the image of the database (its `export()`). It takes the image in the file queue of the database, where no other call of the process changes it. It writes the image to a file next to the target, checks it with `PRAGMA integrity_check`, and then renames it.
331
339
 
332
340
  ```typescript
333
- const { path, bytes } = await client.exec(["db", "backup"], { dbPath: "./app.db", to: "./backups/app-2026-10-16.db" });
341
+ const { path, bytes } = await client.exec(["sqlite", "backup"], { dbPath: "./app.db", to: "./backups/app-2026-10-16.db" });
334
342
  ```
335
343
 
336
344
  ### Log Procedures
@@ -496,11 +504,38 @@ const users = new SqliteStorage<User>({ path: "./data/app.db", table: "users" })
496
504
  await users.set("u1", { name: "Ada" });
497
505
  await users.setBatch([["u2", { name: "Bob" }], ["u3", { name: "Cy" }]]);
498
506
  const changes = await users.getChangesSince(); // { version, full: true, changed, deleted: [] }
507
+ await users.getEngine(); // "node" on Node.js 22.13 or later
499
508
  await users.close();
500
509
  ```
501
510
 
502
511
  The entry `@procedures/sqlite/storage` has the storage alone. The package root exports it too.
503
512
 
513
+ ### The engines
514
+
515
+ The storage has two SQLite engines. The option `engine` selects one.
516
+
517
+ | `engine` | The engine | The file write |
518
+ |---|---|---|
519
+ | `node` | `node:sqlite` of Node.js, without a native build | SQLite writes only the changed pages. The file is in WAL mode. |
520
+ | `sqljs` | sql.js (SQLite in WebAssembly), through `@mark1russell7/docker-sqlite` | The storage keeps the database in memory, and it writes the whole file after a write. |
521
+ | `auto` (the default) | `node` when Node.js has `node:sqlite`, and else `sqljs` | |
522
+
523
+ - Node.js 22.13 and later have `node:sqlite` without a flag. Node.js 22.5 to 22.12 have it only with the flag `--experimental-sqlite`. Node.js 22.0 to 22.4 do not have it.
524
+ - Node.js 22 shows the warning `ExperimentalWarning: SQLite is an experimental feature` at the first open of the engine `node`. Node.js 24 and 26 do not show it.
525
+ - Node.js 26.11 renamed the class `DatabaseSync` to `Database`. The storage uses `Database` when the module has it, and else `DatabaseSync`.
526
+ - With `auto`, the storage uses `sqljs` when the import of `node:sqlite` fails. With `node`, the open fails then, and each operation gives the error.
527
+ - The two engines use the same file format. A file that one engine writes opens with the other engine, with its items and its versions.
528
+ - `getEngine()` gives the engine of the storage. `getMetadata()` gives it in `stats.engine`. `isNodeSqliteAvailable()` tells if this Node.js has `node:sqlite`.
529
+
530
+ The nightly benchmarks (`bench/storage.bench.ts`) measure the two engines in a file. These are the mean times of one CI run with Node.js 26 on Linux:
531
+
532
+ | The benchmark | `node` | `sqljs` |
533
+ |---|---|---|
534
+ | 1,000 calls of `set()`, one after the other, in a table of 1,000 items | 141 ms | 1,246 ms |
535
+ | One `getAll()` of a table of 10,000 items | 20 ms | 28 ms |
536
+
537
+ The engine `sqljs` writes the whole file at each write, so its write time grows with the size of the file.
538
+
504
539
  ### The table and the values
505
540
 
506
541
  - The option `path` is a database file, or `:memory:` for a database that lives as long as the storage.
@@ -508,6 +543,7 @@ The entry `@procedures/sqlite/storage` has the storage alone. The package root e
508
543
  - The table has the columns `id` and `value`. The value is the JSON text of the item.
509
544
  - A value without JSON text, for example `undefined` or a `BigInt`, is a `TypeError`. The storage writes nothing then.
510
545
  - A read gives a new copy of the item.
546
+ - `getIds()` gives the ids in the order of the items, and it does not read the values. A full sync of `HybridStorage` uses it.
511
547
  - The order of the items is the order of the first write of each id, as in a `Map`.
512
548
 
513
549
  ### The change log and the versions
@@ -516,17 +552,40 @@ The entry `@procedures/sqlite/storage` has the storage alone. The package root e
516
552
  - A version is `<epoch>:<seq>`, as in `InMemoryStorage`. The table `_storage_versions` keeps the epoch, so a version stays valid after a restart.
517
553
  - The table `_storage_log` keeps the last change of each id. The option `maxTombstones` (10000 by default) limits the deletes that it keeps.
518
554
  - A version that is older than the dropped deletes gives all items (`full: true`).
555
+ - A delta follows the order of the last change of each id, as in each other storage. A full result follows the order of the items.
519
556
  - Write the table only through the storage. A change from other SQL is not in the change log.
520
557
 
521
558
  ### The transactions and the file
522
559
 
523
560
  - Each write runs in a transaction with the change log. A batch that fails changes nothing.
524
- - The storage keeps the database in memory, and it writes the file after each write. The write ends after the file write.
525
- - When several writes wait, one file write holds their changes.
526
- - A failed file write fails the write. The change stays in memory, and `flush()` or the next write writes it.
527
- - A storage that only reads does not make the file.
561
+ - A write ends after its change is in the file.
562
+ - A storage that only reads does not make the file. The storage makes the file, and its folder, at the first write that changes an item.
563
+ - `close()` writes the file and releases the database. After it, each operation rejects, also `flush()` and an empty batch. A second `close()` does nothing.
528
564
  - The storages of one file in one process share one database. Thus the storages of two tables in one file keep their items.
529
- - Another process, and the procedures `db.query` and `db.execute`, do not share this database. Do not write the file from them while a storage has it open.
565
+ - The first storage of a file sets the engine of the shared database. A later storage with the engine `auto` uses it. A later storage with the other engine refuses it.
566
+
567
+ The engine `node`:
568
+
569
+ - The commit of a transaction writes the change to the file. `flush()` has nothing to write.
570
+ - The file is in WAL mode, with `synchronous = NORMAL`. After a crash, the file stays consistent. A power loss can lose the last commits.
571
+ - A write that cannot make the file fails, and it changes nothing.
572
+ - A read-only file opens. The reads work, and each write fails.
573
+
574
+ The engine `sqljs`:
575
+
576
+ - The storage keeps the database in memory, and it writes the whole file after each write. When several writes wait, one file write holds their changes.
577
+ - A failed file write fails the write. The change stays in memory, and `flush()` or the next write writes it.
578
+ - The storage refuses a file with a write-ahead log (`<file>-wal`) of the engine `node`. The log can hold changes that are not in the file. Open the file with the engine `node` one time, or close the process that has it open.
579
+
580
+ ### Two processes on one file
581
+
582
+ - With the engine `node` in each process, two processes can use one file at the same time.
583
+ - SQLite locks the file for each write. A write waits for the lock of another process for `busyTimeout` (5 seconds by default). After it, the write fails with `database is locked`.
584
+ - In WAL mode, a read does not wait for a write of another process.
585
+ - Each write reads the version counter in its transaction, so the versions of the two processes agree. `getChangesSince()` reads in one read transaction.
586
+ - A storage that opened before the file existed opens the file when another process makes it.
587
+ - The engine `sqljs` does not coordinate with another process. Its whole-file write replaces the writes of the other process. Do not use it on a file that another process writes.
588
+ - The procedures `sqlite.query` and `sqlite.execute` use sql.js, and they do not share the database of the storages. Do not write the file from them while a storage has it open.
530
589
 
531
590
  ### The durable local copy of `HybridStorage`
532
591
 
@@ -556,7 +615,7 @@ const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
556
615
 
557
616
  // Create a table
558
617
  await client.exec(
559
- ["db", "execute"],
618
+ ["sqlite", "execute"],
560
619
  {
561
620
  sql: `
562
621
  CREATE TABLE IF NOT EXISTS users (
@@ -573,7 +632,7 @@ await client.exec(
573
632
 
574
633
  // Insert data
575
634
  await client.exec(
576
- ["db", "execute"],
635
+ ["sqlite", "execute"],
577
636
  {
578
637
  sql: "INSERT INTO users (name, email) VALUES (?, ?)",
579
638
  params: ["Alice Johnson", "alice@example.com"],
@@ -583,7 +642,7 @@ await client.exec(
583
642
 
584
643
  // Query data
585
644
  const result = await client.exec(
586
- ["db", "query"],
645
+ ["sqlite", "query"],
587
646
  {
588
647
  sql: "SELECT * FROM users WHERE active = ? ORDER BY created_at DESC",
589
648
  params: [1],
@@ -747,7 +806,7 @@ interface User {
747
806
  }
748
807
 
749
808
  const result = await client.call<DbQueryOutput<User>>(
750
- ["db", "query"],
809
+ ["sqlite", "query"],
751
810
  {
752
811
  sql: "SELECT * FROM users WHERE active = ?",
753
812
  params: [true],
@@ -827,11 +886,13 @@ export type {
827
886
  client-sqlite/
828
887
  ├── src/
829
888
  │ ├── types.ts # Type definitions
830
- │ ├── module.ts # The procedures as data, and the db.query, db.execute and logs.* handlers
889
+ │ ├── module.ts # The procedures as data, and the sqlite.query, sqlite.execute and logs.* handlers
831
890
  │ ├── register.ts # The ./register entry: registers the module
832
891
  │ ├── storage.ts # SqliteStorage, the collection storage (the ./storage entry)
833
- │ ├── procedures/db/ # db.tables, db.schema, db.transaction, db.migrate, db.backup
892
+ │ ├── engines.ts # The engines of SqliteStorage: node:sqlite and sql.js
893
+ │ ├── procedures/db/ # sqlite.tables, sqlite.schema, sqlite.transaction, sqlite.migrate, sqlite.backup
834
894
  │ └── index.ts # Main entry point
895
+ ├── bench/ # The benchmarks of the engines (the nightly workflow runs them)
835
896
  ├── dist/ # Compiled output
836
897
  ├── package.json
837
898
  ├── tsconfig.json