@procedures/sqlite 0.2.3 → 0.4.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/CHANGELOG.md +74 -0
- package/README.md +147 -17
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/module.d.ts +13 -2
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +135 -18
- package/dist/module.js.map +1 -1
- package/dist/procedures/db/backup.d.ts +19 -0
- package/dist/procedures/db/backup.d.ts.map +1 -0
- package/dist/procedures/db/backup.js +61 -0
- package/dist/procedures/db/backup.js.map +1 -0
- package/dist/procedures/db/index.d.ts +6 -0
- package/dist/procedures/db/index.d.ts.map +1 -0
- package/dist/procedures/db/index.js +6 -0
- package/dist/procedures/db/index.js.map +1 -0
- package/dist/procedures/db/migrate.d.ts +24 -0
- package/dist/procedures/db/migrate.d.ts.map +1 -0
- package/dist/procedures/db/migrate.js +110 -0
- package/dist/procedures/db/migrate.js.map +1 -0
- package/dist/procedures/db/schema.d.ts +13 -0
- package/dist/procedures/db/schema.d.ts.map +1 -0
- package/dist/procedures/db/schema.js +33 -0
- package/dist/procedures/db/schema.js.map +1 -0
- package/dist/procedures/db/shared.d.ts +25 -0
- package/dist/procedures/db/shared.d.ts.map +1 -0
- package/dist/procedures/db/shared.js +105 -0
- package/dist/procedures/db/shared.js.map +1 -0
- package/dist/procedures/db/tables.d.ts +12 -0
- package/dist/procedures/db/tables.d.ts.map +1 -0
- package/dist/procedures/db/tables.js +22 -0
- package/dist/procedures/db/tables.js.map +1 -0
- package/dist/procedures/db/transaction.d.ts +14 -0
- package/dist/procedures/db/transaction.d.ts.map +1 -0
- package/dist/procedures/db/transaction.js +44 -0
- package/dist/procedures/db/transaction.js.map +1 -0
- package/dist/storage.d.ts +123 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +525 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +131 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +109 -0
- package/dist/types.js.map +1 -1
- package/package.json +9 -3
- package/src/index.ts +28 -2
- package/src/module.ts +167 -19
- package/src/procedures/db/backup.ts +62 -0
- package/src/procedures/db/index.ts +5 -0
- package/src/procedures/db/migrate.ts +121 -0
- package/src/procedures/db/schema.ts +71 -0
- package/src/procedures/db/shared.ts +109 -0
- package/src/procedures/db/tables.ts +27 -0
- package/src/procedures/db/transaction.ts +43 -0
- package/src/storage.ts +591 -0
- package/src/types.ts +270 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
# @procedures/sqlite
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
The description of the `dbPath` field does not show the home folder of the computer any more. It says `~/logs/cli/cli.db`.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [d919678]
|
|
16
|
+
- Updated dependencies [057d69a]
|
|
17
|
+
- Updated dependencies [b2a1a1e]
|
|
18
|
+
- Updated dependencies [057d69a]
|
|
19
|
+
- Updated dependencies [057d69a]
|
|
20
|
+
- Updated dependencies [057d69a]
|
|
21
|
+
- Updated dependencies [057d69a]
|
|
22
|
+
- Updated dependencies [057d69a]
|
|
23
|
+
- Updated dependencies [afd6a19]
|
|
24
|
+
- Updated dependencies [057d69a]
|
|
25
|
+
- Updated dependencies [4e751da]
|
|
26
|
+
- @procedures/client@0.4.0
|
|
27
|
+
|
|
28
|
+
## 0.3.0
|
|
29
|
+
|
|
30
|
+
### Minor Changes
|
|
31
|
+
|
|
32
|
+
- 89d8a4a: Three procedures only read now (CAP-1, CAP-2, CAP-3, roadmap R7), so a read-only session (`mark mcp --read-only`) serves them. `db.query` refuses a statement that changes data (`PRAGMA query_only`), and the file keeps its bytes. `mongo.documents.aggregate` refuses `$out` and `$merge`, also in the pipelines of `$facet`, `$lookup` and `$unionWith`. `logs.query` gives no entries for a missing file or table, and does not make them.
|
|
33
|
+
- 94dd2a0: Five database procedures (roadmap R44). `db.tables` lists the tables and views, and `db.schema` gives the columns, indexes and foreign keys of a table. Both only read, and a missing file is an error. `db.query` stays read only.
|
|
34
|
+
|
|
35
|
+
`db.transaction` puts a list of statements in one transaction, and rolls it back when one fails. `db.migrate` applies numbered migrations from a folder or a list, in one transaction, with a table of the applied migrations and their sha256. A second call applies nothing. `db.backup` copies a database to a new file and checks the copy. It does not replace a file. With `vacuum: true`, it compacts the copy.
|
|
36
|
+
- 4ef0d44: The new collection storage `SqliteStorage` (roadmap R45) keeps the items of one collection in one table of a SQLite database: a file, or `:memory:`. It implements `CollectionStorage`, so a `ProcedureServer`, an `ApiStorage` server and a `HybridStorage` use it as they use `InMemoryStorage`. The new entry `@procedures/sqlite/storage` has it alone, and the package root exports it too.
|
|
37
|
+
|
|
38
|
+
The table has the columns `id` and `value` (the JSON text of the item). The name of the table starts with a letter and has only letters, digits and underscores. `getChangesSince()` reads a change log in the tables `_storage_log` and `_storage_versions`, with versions `<epoch>:<seq>` as `InMemoryStorage` has. The epoch stays in the file, so a version stays valid after a restart. The option `maxTombstones` limits the deletes that the log keeps.
|
|
39
|
+
|
|
40
|
+
Each write runs in a transaction, so a batch that fails changes nothing. The storage keeps the database in memory and writes the file after each write. One file write can hold the changes of several writes. The storages of one file in one process share one database. A storage that only reads does not make the file.
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- Updated dependencies [ddea529]
|
|
45
|
+
- Updated dependencies [b2a3e3a]
|
|
46
|
+
- Updated dependencies [a8c47f1]
|
|
47
|
+
- Updated dependencies [381ce3a]
|
|
48
|
+
- Updated dependencies [0c627f8]
|
|
49
|
+
- Updated dependencies [ae7f05f]
|
|
50
|
+
- Updated dependencies [7873940]
|
|
51
|
+
- Updated dependencies [a70d445]
|
|
52
|
+
- Updated dependencies [bc70357]
|
|
53
|
+
- Updated dependencies [07cc998]
|
|
54
|
+
- Updated dependencies [a6b01a9]
|
|
55
|
+
- Updated dependencies [c799cdd]
|
|
56
|
+
- Updated dependencies [540f8d9]
|
|
57
|
+
- Updated dependencies [b6daaec]
|
|
58
|
+
- Updated dependencies [5b9264e]
|
|
59
|
+
- Updated dependencies [956e88b]
|
|
60
|
+
- Updated dependencies [ff62281]
|
|
61
|
+
- Updated dependencies [d81d0ed]
|
|
62
|
+
- Updated dependencies [aa67cc7]
|
|
63
|
+
- Updated dependencies [061fa22]
|
|
64
|
+
- Updated dependencies [cfb9d69]
|
|
65
|
+
- Updated dependencies [43f7de5]
|
|
66
|
+
- Updated dependencies [b07bb50]
|
|
67
|
+
- Updated dependencies [4a3bfa1]
|
|
68
|
+
- Updated dependencies [bd0b626]
|
|
69
|
+
- Updated dependencies [a6be873]
|
|
70
|
+
- Updated dependencies [fb30718]
|
|
71
|
+
- Updated dependencies [c5528e4]
|
|
72
|
+
- Updated dependencies [fee5d9c]
|
|
73
|
+
- Updated dependencies [21f7743]
|
|
74
|
+
- Updated dependencies [31a0b46]
|
|
75
|
+
- @procedures/client@0.3.0
|
|
76
|
+
|
|
3
77
|
## 0.2.3
|
|
4
78
|
|
|
5
79
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -15,11 +15,20 @@ SQLite database operations via client procedures. Execute queries and store stru
|
|
|
15
15
|
- **Logging procedures**: Store and query structured application logs
|
|
16
16
|
- **Migration support**: Schema versioning and migration utilities
|
|
17
17
|
- **Default log database**: Pre-configured logging at `~/logs/cli/cli.db`
|
|
18
|
+
- **A collection storage**: `SqliteStorage` keeps a collection in a SQLite table, with a change log
|
|
18
19
|
|
|
19
|
-
The package has
|
|
20
|
-
- **Database**: `
|
|
20
|
+
The package has 9 procedures. Its register entry (`import "@procedures/sqlite/register"`) registers them:
|
|
21
|
+
- **Database**: `sqlite.query`, `sqlite.execute`, `sqlite.tables`, `sqlite.schema`, `sqlite.transaction`, `sqlite.migrate`, `sqlite.backup`
|
|
21
22
|
- **Logs**: `logs.store`, `logs.query`
|
|
22
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
|
+
|
|
23
32
|
## Architecture
|
|
24
33
|
|
|
25
34
|
```mermaid
|
|
@@ -33,7 +42,7 @@ graph TB
|
|
|
33
42
|
Register["register.ts<br/>(Auto-registers procedures)"]
|
|
34
43
|
|
|
35
44
|
subgraph "Procedure Categories"
|
|
36
|
-
DB["Database Procedures<br/>
|
|
45
|
+
DB["Database Procedures<br/>sqlite.query, sqlite.execute, sqlite.tables, sqlite.schema,<br/>sqlite.transaction, sqlite.migrate, sqlite.backup"]
|
|
37
46
|
Logs["Log Procedures<br/>logs.store, logs.query"]
|
|
38
47
|
end
|
|
39
48
|
|
|
@@ -147,7 +156,7 @@ You can override this path in each procedure call:
|
|
|
147
156
|
|
|
148
157
|
```typescript
|
|
149
158
|
await client.exec(
|
|
150
|
-
["
|
|
159
|
+
["sqlite", "query"],
|
|
151
160
|
{
|
|
152
161
|
sql: "SELECT * FROM logs",
|
|
153
162
|
dbPath: "./custom/path/database.db"
|
|
@@ -159,13 +168,13 @@ await client.exec(
|
|
|
159
168
|
|
|
160
169
|
### Database Procedures
|
|
161
170
|
|
|
162
|
-
#### `
|
|
171
|
+
#### `sqlite.query`
|
|
163
172
|
|
|
164
173
|
Execute a SQL SELECT query and return rows.
|
|
165
174
|
|
|
166
175
|
```typescript
|
|
167
176
|
const result = await client.exec(
|
|
168
|
-
["
|
|
177
|
+
["sqlite", "query"],
|
|
169
178
|
{
|
|
170
179
|
sql: "SELECT * FROM logs WHERE level = ? ORDER BY timestamp DESC",
|
|
171
180
|
params: ["error"]
|
|
@@ -196,7 +205,7 @@ interface DbQueryOutput<T = Record<string, unknown>> {
|
|
|
196
205
|
**Example:**
|
|
197
206
|
```typescript
|
|
198
207
|
const result = await client.exec(
|
|
199
|
-
["
|
|
208
|
+
["sqlite", "query"],
|
|
200
209
|
{
|
|
201
210
|
sql: `
|
|
202
211
|
SELECT level, COUNT(*) as count
|
|
@@ -211,13 +220,13 @@ const result = await client.exec(
|
|
|
211
220
|
// result.rows = [{ level: "info", count: 45 }, { level: "error", count: 2 }]
|
|
212
221
|
```
|
|
213
222
|
|
|
214
|
-
#### `
|
|
223
|
+
#### `sqlite.execute`
|
|
215
224
|
|
|
216
225
|
Execute a SQL statement (INSERT, UPDATE, DELETE) and return the number of affected rows.
|
|
217
226
|
|
|
218
227
|
```typescript
|
|
219
228
|
const result = await client.exec(
|
|
220
|
-
["
|
|
229
|
+
["sqlite", "execute"],
|
|
221
230
|
{
|
|
222
231
|
sql: "DELETE FROM logs WHERE timestamp < ?",
|
|
223
232
|
params: ["2024-01-01"]
|
|
@@ -247,7 +256,7 @@ interface DbExecuteOutput {
|
|
|
247
256
|
```typescript
|
|
248
257
|
// INSERT
|
|
249
258
|
await client.exec(
|
|
250
|
-
["
|
|
259
|
+
["sqlite", "execute"],
|
|
251
260
|
{
|
|
252
261
|
sql: "INSERT INTO users (name, email) VALUES (?, ?)",
|
|
253
262
|
params: ["Alice", "alice@example.com"]
|
|
@@ -256,7 +265,7 @@ await client.exec(
|
|
|
256
265
|
|
|
257
266
|
// UPDATE
|
|
258
267
|
await client.exec(
|
|
259
|
-
["
|
|
268
|
+
["sqlite", "execute"],
|
|
260
269
|
{
|
|
261
270
|
sql: "UPDATE users SET active = ? WHERE id = ?",
|
|
262
271
|
params: [true, 123]
|
|
@@ -265,7 +274,7 @@ await client.exec(
|
|
|
265
274
|
|
|
266
275
|
// DELETE
|
|
267
276
|
await client.exec(
|
|
268
|
-
["
|
|
277
|
+
["sqlite", "execute"],
|
|
269
278
|
{
|
|
270
279
|
sql: "DELETE FROM users WHERE active = ?",
|
|
271
280
|
params: [false]
|
|
@@ -273,6 +282,65 @@ await client.exec(
|
|
|
273
282
|
);
|
|
274
283
|
```
|
|
275
284
|
|
|
285
|
+
#### `sqlite.tables`
|
|
286
|
+
|
|
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.
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
const { tables } = await client.exec(["sqlite", "tables"], { dbPath: "./app.db" });
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
#### `sqlite.schema`
|
|
294
|
+
|
|
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.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
const schema = await client.exec(["sqlite", "schema"], { dbPath: "./app.db", table: "users" });
|
|
299
|
+
// schema.columns: [{ name: "id", type: "INTEGER", notNull: false, defaultValue: null, primaryKey: 1 }, ...]
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### `sqlite.transaction`
|
|
303
|
+
|
|
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.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const { results, changes } = await client.exec(["sqlite", "transaction"], {
|
|
308
|
+
dbPath: "./app.db",
|
|
309
|
+
statements: [
|
|
310
|
+
{ sql: "UPDATE accounts SET balance = balance - ? WHERE id = ?", params: [10, 1] },
|
|
311
|
+
{ sql: "UPDATE accounts SET balance = balance + ? WHERE id = ?", params: [10, 2] },
|
|
312
|
+
{ sql: "SELECT id, balance FROM accounts" },
|
|
313
|
+
],
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### `sqlite.migrate`
|
|
318
|
+
|
|
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`.
|
|
320
|
+
|
|
321
|
+
- The table `schema_migrations` (or the `table` of the input) records each applied migration and the sha256 of its SQL.
|
|
322
|
+
- The pending migrations are in one transaction. When one fails, the procedure applies none of them.
|
|
323
|
+
- A second call applies nothing, and does not write the file.
|
|
324
|
+
- When the SQL of an applied migration changes, the procedure refuses the call. The sha256 reads CRLF line ends as LF.
|
|
325
|
+
- A migration must not hold `BEGIN`, `COMMIT` or `ROLLBACK`.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const { applied, skipped, version } = await client.exec(["sqlite", "migrate"], {
|
|
329
|
+
dbPath: "./app.db",
|
|
330
|
+
folder: "./migrations",
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
#### `sqlite.backup`
|
|
335
|
+
|
|
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.
|
|
337
|
+
|
|
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.
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
const { path, bytes } = await client.exec(["sqlite", "backup"], { dbPath: "./app.db", to: "./backups/app-2026-10-16.db" });
|
|
342
|
+
```
|
|
343
|
+
|
|
276
344
|
### Log Procedures
|
|
277
345
|
|
|
278
346
|
#### `logs.store`
|
|
@@ -425,6 +493,65 @@ const { logs } = await client.exec(
|
|
|
425
493
|
);
|
|
426
494
|
```
|
|
427
495
|
|
|
496
|
+
## The collection storage
|
|
497
|
+
|
|
498
|
+
`SqliteStorage` keeps the items of one collection in one table of a SQLite database. It implements `CollectionStorage` of `@procedures/client`. A `ProcedureServer`, an `ApiStorage` server and a `HybridStorage` use it as they use `InMemoryStorage`.
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
import { SqliteStorage } from "@procedures/sqlite/storage";
|
|
502
|
+
|
|
503
|
+
const users = new SqliteStorage<User>({ path: "./data/app.db", table: "users" });
|
|
504
|
+
await users.set("u1", { name: "Ada" });
|
|
505
|
+
await users.setBatch([["u2", { name: "Bob" }], ["u3", { name: "Cy" }]]);
|
|
506
|
+
const changes = await users.getChangesSince(); // { version, full: true, changed, deleted: [] }
|
|
507
|
+
await users.close();
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The entry `@procedures/sqlite/storage` has the storage alone. The package root exports it too.
|
|
511
|
+
|
|
512
|
+
### The table and the values
|
|
513
|
+
|
|
514
|
+
- The option `path` is a database file, or `:memory:` for a database that lives as long as the storage.
|
|
515
|
+
- The option `table` is the name of the table. It starts with a letter, and it has only letters, digits and underscores. The prefix `sqlite_` is not permitted.
|
|
516
|
+
- The table has the columns `id` and `value`. The value is the JSON text of the item.
|
|
517
|
+
- A value without JSON text, for example `undefined` or a `BigInt`, is a `TypeError`. The storage writes nothing then.
|
|
518
|
+
- A read gives a new copy of the item.
|
|
519
|
+
- The order of the items is the order of the first write of each id, as in a `Map`.
|
|
520
|
+
|
|
521
|
+
### The change log and the versions
|
|
522
|
+
|
|
523
|
+
- `getChangesSince(version)` gives the items that changed and the ids that were deleted after a version. `HybridStorage` uses it for a delta sync.
|
|
524
|
+
- A version is `<epoch>:<seq>`, as in `InMemoryStorage`. The table `_storage_versions` keeps the epoch, so a version stays valid after a restart.
|
|
525
|
+
- The table `_storage_log` keeps the last change of each id. The option `maxTombstones` (10000 by default) limits the deletes that it keeps.
|
|
526
|
+
- A version that is older than the dropped deletes gives all items (`full: true`).
|
|
527
|
+
- Write the table only through the storage. A change from other SQL is not in the change log.
|
|
528
|
+
|
|
529
|
+
### The transactions and the file
|
|
530
|
+
|
|
531
|
+
- Each write runs in a transaction with the change log. A batch that fails changes nothing.
|
|
532
|
+
- The storage keeps the database in memory, and it writes the file after each write. The write ends after the file write.
|
|
533
|
+
- When several writes wait, one file write holds their changes.
|
|
534
|
+
- A failed file write fails the write. The change stays in memory, and `flush()` or the next write writes it.
|
|
535
|
+
- A storage that only reads does not make the file.
|
|
536
|
+
- The storages of one file in one process share one database. Thus the storages of two tables in one file keep their items.
|
|
537
|
+
- Another process, and the procedures `sqlite.query` and `sqlite.execute`, do not share this database. Do not write the file from them while a storage has it open.
|
|
538
|
+
|
|
539
|
+
### The durable local copy of `HybridStorage`
|
|
540
|
+
|
|
541
|
+
`HybridStorage` of `@procedures/store` takes the storage of its local copy in the option `local`. With a `SqliteStorage`, the local copy stays after a restart. A new storage in `local-only` mode then reads the items of the last run, without the remote.
|
|
542
|
+
|
|
543
|
+
```ts
|
|
544
|
+
import { HybridStorage } from "@procedures/store";
|
|
545
|
+
import { FileQueueStore } from "@procedures/store/file-queue";
|
|
546
|
+
import { SqliteStorage } from "@procedures/sqlite/storage";
|
|
547
|
+
|
|
548
|
+
const users = new HybridStorage(remote, {
|
|
549
|
+
mode: "write-back",
|
|
550
|
+
local: new SqliteStorage({ path: "./users.db", table: "users" }),
|
|
551
|
+
queueStore: new FileQueueStore("./users.queue.jsonl"),
|
|
552
|
+
});
|
|
553
|
+
```
|
|
554
|
+
|
|
428
555
|
## Usage Examples
|
|
429
556
|
|
|
430
557
|
### Basic Database Operations
|
|
@@ -437,7 +564,7 @@ const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
|
|
|
437
564
|
|
|
438
565
|
// Create a table
|
|
439
566
|
await client.exec(
|
|
440
|
-
["
|
|
567
|
+
["sqlite", "execute"],
|
|
441
568
|
{
|
|
442
569
|
sql: `
|
|
443
570
|
CREATE TABLE IF NOT EXISTS users (
|
|
@@ -454,7 +581,7 @@ await client.exec(
|
|
|
454
581
|
|
|
455
582
|
// Insert data
|
|
456
583
|
await client.exec(
|
|
457
|
-
["
|
|
584
|
+
["sqlite", "execute"],
|
|
458
585
|
{
|
|
459
586
|
sql: "INSERT INTO users (name, email) VALUES (?, ?)",
|
|
460
587
|
params: ["Alice Johnson", "alice@example.com"],
|
|
@@ -464,7 +591,7 @@ await client.exec(
|
|
|
464
591
|
|
|
465
592
|
// Query data
|
|
466
593
|
const result = await client.exec(
|
|
467
|
-
["
|
|
594
|
+
["sqlite", "query"],
|
|
468
595
|
{
|
|
469
596
|
sql: "SELECT * FROM users WHERE active = ? ORDER BY created_at DESC",
|
|
470
597
|
params: [1],
|
|
@@ -628,7 +755,7 @@ interface User {
|
|
|
628
755
|
}
|
|
629
756
|
|
|
630
757
|
const result = await client.call<DbQueryOutput<User>>(
|
|
631
|
-
["
|
|
758
|
+
["sqlite", "query"],
|
|
632
759
|
{
|
|
633
760
|
sql: "SELECT * FROM users WHERE active = ?",
|
|
634
761
|
params: [true],
|
|
@@ -708,7 +835,10 @@ export type {
|
|
|
708
835
|
client-sqlite/
|
|
709
836
|
├── src/
|
|
710
837
|
│ ├── types.ts # Type definitions
|
|
711
|
-
│ ├──
|
|
838
|
+
│ ├── module.ts # The procedures as data, and the sqlite.query, sqlite.execute and logs.* handlers
|
|
839
|
+
│ ├── register.ts # The ./register entry: registers the module
|
|
840
|
+
│ ├── storage.ts # SqliteStorage, the collection storage (the ./storage entry)
|
|
841
|
+
│ ├── procedures/db/ # sqlite.tables, sqlite.schema, sqlite.transaction, sqlite.migrate, sqlite.backup
|
|
712
842
|
│ └── index.ts # Main entry point
|
|
713
843
|
├── dist/ # Compiled output
|
|
714
844
|
├── package.json
|