@plurnk/plurnk-execs-sqlite 1.3.12 → 1.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/README.md CHANGED
@@ -2,30 +2,31 @@
2
2
 
3
3
  SQLite runtime executor for [plurnk-service](https://github.com/plurnk/plurnk-service)'s `exec` scheme. Runs the `sqlite` runtime tag **in-process** via Node's builtin `node:sqlite` — no subprocess.
4
4
 
5
- A `@plurnk/plurnk-execs-*` sibling built on the [plurnk-execs](https://github.com/plurnk/plurnk-execs) framework.
5
+ A `@plurnk/plurnk-execs-*` sibling built on the [plurnk-execs](https://github.com/plurnk/plurnk-service/tree/main/plurnk-execs) framework.
6
6
 
7
7
  ## Runtime tag
8
8
 
9
- | Tag | Glyph | Engine |
10
- |---|---|---|
11
- | `sqlite` | 🗃 | `node:sqlite` (Node 25 builtin) |
9
+ | Tag | Glyph | Engine |
10
+ | -------- | ----- | ------------------------------------------- |
11
+ | `sqlite` | 🗃 | `node:sqlite` in the supported Node runtime |
12
12
 
13
13
  ## Database target
14
14
 
15
15
  The EXEC target slot is the database file; with no target it defaults to an ephemeral in-memory db:
16
16
 
17
- ```
18
- <<EXEC[sqlite]:SELECT * FROM users:EXEC → :memory: (fresh per worker)
19
- <<EXEC[sqlite](./app.db):SELECT * FROM users:EXEC → ./app.db (persistent)
17
+ ```plurnk
18
+ <<EXEC[sqlite]:SELECT * FROM users:EXEC
19
+ <<EXEC[sqlite](./app.db):SELECT * FROM users:EXEC
20
20
  ```
21
21
 
22
- `:memory:` is ephemeral — state does not persist across EXECs. Pass a file path for persistence.
22
+ With no target, a fresh `:memory:` database exists for that operation only.
23
+ State does not persist across EXECs. Pass a file path for persistence.
23
24
 
24
25
  ### Transient tabular calculations
25
26
 
26
27
  With no target, `:memory:` is a scratch calculator over ad-hoc tables — build one inline with `VALUES` and aggregate, no schema or file needed:
27
28
 
28
- ```
29
+ ```plurnk
29
30
  <<EXEC[sqlite]:WITH t(item,qty,price) AS (VALUES ('a',3,2),('b',1,5)) SELECT sum(qty*price) AS total, sum(qty*price)*1.0/sum(qty) AS avg_price FROM t:EXEC
30
31
  ```
31
32
 
@@ -38,11 +39,22 @@ Writes to the `results` channel as `application/json`, ready for the jsonpath bo
38
39
  - **Row-returning statements** (SELECT, RETURNING, PRAGMA) → an array of row objects.
39
40
  - **Mutations** (INSERT/UPDATE/DELETE/DDL) → `{ changes, lastInsertRowid }`.
40
41
 
41
- The query/mutation split is decided by the prepared statement's `columns()`, never by parsing the SQL. One statement per EXEC. Errors emit a `TelemetryEvent` (`source: "exec:sqlite"`): `sqlite_open_failed`, `sqlite_error`.
42
+ The query/mutation split is decided by the prepared statement's `columns()`,
43
+ never by parsing the SQL. One statement per EXEC. Errors return RFC 9457
44
+ Problems in the terminal operation result.
45
+
46
+ ## Configuration
47
+
48
+ The framework's `PLURNK_EXECS_ERROR_DETAIL_LIMIT` bounds SQLite diagnostics and
49
+ rejected SQL tails included in Problem facts.
42
50
 
43
51
  ## Availability & proposal gating
44
52
 
45
- `probe()` always reports available (`node:sqlite` is a builtin). `effect(target)` marks `:memory:` (and no target) as `pure` (auto-run) and a file-backed db as `host` (propose) — classified by the target only, never by inspecting the SQL.
53
+ `probe()` reports available because `node:sqlite` is part of the supported Node
54
+ >=26 runtime. `effect(target)` marks `:memory:` and no target as `pure`, while a
55
+ file-backed database is `host`. The former bypasses the proposal gate and the
56
+ latter requires it; both produce their result through the background stream
57
+ path ({§executor-effect}). Classification uses only the target, never the SQL.
46
58
 
47
59
  ## Tests
48
60
 
package/dist/Sqlite.d.ts CHANGED
@@ -4,6 +4,6 @@ export default class Sqlite extends BaseExecutor {
4
4
  get channels(): Readonly<Record<string, ChannelDecl>>;
5
5
  probe(): Promise<RuntimeAvailability>;
6
6
  effect(target: string | null): Effect;
7
- run({ command, cwd, target, signal, write, setState, emit }: ExecArgs): Promise<ExecResult>;
7
+ run({ command, cwd, target, signal, write, setState }: ExecArgs): Promise<ExecResult>;
8
8
  }
9
9
  //# sourceMappingURL=Sqlite.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../src/Sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAoC3G,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,YAAY;IAC5C,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAEpD;IAGc,KAAK,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAEnD;IAIQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE7C;IAEK,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CA4ChG;CACJ"}
1
+ {"version":3,"file":"Sqlite.d.ts","sourceRoot":"","sources":["../src/Sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAwB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAkC3G,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,YAAY;IAC5C,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAEpD;IAGc,KAAK,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAEnD;IAIQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE7C;IAEK,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAiH1F;CACJ"}
package/dist/Sqlite.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { isAbsolute, resolve } from "node:path";
2
2
  import { DatabaseSync } from "node:sqlite";
3
- import { BaseExecutor } from "@plurnk/plurnk-execs";
3
+ import { BaseExecutor, ErrorDetail, Results } from "@plurnk/plurnk-execs";
4
4
  const MEMORY = ":memory:";
5
5
  // Resolve the EXEC (target) slot to a db path: a relative target resolves
6
- // against cwd (the workspace, plurnk-execs#15); null — or an explicit
6
+ // against cwd ({§executor-sinks}); null — or an explicit
7
7
  // `:memory:` — means no file target → an ephemeral in-memory db.
8
8
  const dbPath = (cwd, target) => {
9
9
  if (target === null || target === MEMORY)
@@ -28,13 +28,11 @@ const stripComments = (sql) => sql.replace(/--[^\n]*/g, "").replace(/\/\*[\s\S]*
28
28
  // objects; mutations write `{ changes, lastInsertRowid }`. The query/mutation
29
29
  // split is decided by `columns()` — never by parsing the SQL.
30
30
  //
31
- // NOTE: `effect()` (per-runtime proposal gating; :memory:→pure, file→host) is
32
- // pending the contract addition in plurnk-service#182 and lands when that does.
33
31
  export default class Sqlite extends BaseExecutor {
34
32
  get channels() {
35
33
  return { results: { mimetype: "application/json" } };
36
34
  }
37
- // Always available — node:sqlite is a Node 25 builtin, in-process.
35
+ // Always available in the package's supported Node >=26 runtime.
38
36
  async probe() {
39
37
  return { available: true, detail: "node:sqlite" };
40
38
  }
@@ -43,40 +41,70 @@ export default class Sqlite extends BaseExecutor {
43
41
  effect(target) {
44
42
  return target === null || target === MEMORY ? "pure" : "host";
45
43
  }
46
- async run({ command, cwd, target, signal, write, setState, emit }) {
44
+ async run({ command, cwd, target, signal, write, setState }) {
47
45
  // node:sqlite is fully synchronous — no await point to interrupt mid-query —
48
- // so the only place to honor an abort is before the work starts (SPEC §6).
46
+ // so the only place to honor an abort is before the work starts
47
+ // ({§executor-cancellation}).
49
48
  // Matters for a file-backed (host) statement: a cancel/KILL that lands first
50
49
  // must not still mutate the db.
51
50
  if (signal.aborted) {
52
51
  setState("results", "errored");
53
- return { status: 499 };
52
+ return Results.failure("executor:sqlite", "cancelled", 499, "SQLite execution was cancelled.", {}, {
53
+ stage: "execution",
54
+ retryable: false,
55
+ });
54
56
  }
55
57
  const path = dbPath(cwd, target);
56
58
  const sql = command.trim();
57
- const fail = (kind, message, status = 500) => {
58
- emit({ source: "exec:sqlite", kind, message });
59
+ const errorPreview = ErrorDetail.configuredLimit();
60
+ const fail = (kind, message, status = 500, extensions = {}) => {
59
61
  setState("results", "errored");
60
- return { status };
62
+ return Results.failure("executor:sqlite", kind, status, message, {}, {
63
+ database: path,
64
+ ...extensions,
65
+ });
61
66
  };
67
+ if (errorPreview === null) {
68
+ setState("results", "errored");
69
+ return ErrorDetail.invalidConfiguration("executor:sqlite");
70
+ }
62
71
  let db;
63
72
  try {
64
73
  db = new DatabaseSync(path);
65
74
  }
66
75
  catch (err) {
67
- return fail("sqlite_open_failed", `cannot open database '${path}': ${err.message}`);
76
+ return fail("sqlite-open-failed", `SQLite could not open '${path}': ${ErrorDetail.preview(err, errorPreview)}`, 500, {
77
+ stage: "open",
78
+ recovery: "Use an accessible SQLite database target.",
79
+ });
80
+ }
81
+ let stmt;
82
+ try {
83
+ stmt = db.prepare(sql);
84
+ }
85
+ catch (err) {
86
+ db.close();
87
+ return fail("sqlite-invalid-statement", `SQLite could not prepare the statement: ${ErrorDetail.preview(err, errorPreview)}`, 400, {
88
+ stage: "prepare",
89
+ recovery: "Correct the SQL statement.",
90
+ retryable: false,
91
+ });
68
92
  }
69
93
  try {
70
- const stmt = db.prepare(sql);
71
94
  // One statement per op is the contract (the results channel is one JSON
72
95
  // doc) — but SQLite's prepare compiles only the FIRST statement and
73
96
  // silently ignores the rest, so a sqlite3-CLI-style script would
74
- // partially execute under a 200 (#493). sourceSQL is the compiled
97
+ // partially execute under a 200. sourceSQL is the compiled
75
98
  // statement's own text: any real SQL left after it is a dropped tail —
76
99
  // fail-hard, never truncate silently. Trailing whitespace/comments pass.
77
100
  const tail = stripComments(sql.slice(stmt.sourceSQL.length)).trim();
78
101
  if (tail !== "") {
79
- return fail("sqlite_multi_statement", `one SQL statement per op — the tail '${tail.slice(0, 60)}' would be silently dropped; split into one op per statement`, 400);
102
+ return fail("sqlite-multi-statement", "SQLite execution accepts exactly one statement, but the command contains a second statement.", 400, {
103
+ stage: "prepare",
104
+ rejectedTail: ErrorDetail.preview(tail, errorPreview),
105
+ recovery: "Run each SQL statement in a separate operation.",
106
+ retryable: false,
107
+ });
80
108
  }
81
109
  // Non-empty columns ⇒ a row-returning statement; empty ⇒ a mutation.
82
110
  const output = stmt.columns().length > 0 ? stmt.all() : stmt.run();
@@ -85,7 +113,9 @@ export default class Sqlite extends BaseExecutor {
85
113
  return { status: 200 };
86
114
  }
87
115
  catch (err) {
88
- return fail("sqlite_error", `${err.message}; db='${path}'`);
116
+ return fail("sqlite-error", `SQLite could not execute the statement: ${ErrorDetail.preview(err, errorPreview)}`, 500, {
117
+ stage: "execution",
118
+ });
89
119
  }
90
120
  finally {
91
121
  db.close();
@@ -1 +1 @@
1
- {"version":3,"file":"Sqlite.js","sourceRoot":"","sources":["../src/Sqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Sqlite.js","sourceRoot":"","sources":["../src/Sqlite.ts"],"names":[],"mappings":"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"}
package/docs/sqlite.md CHANGED
@@ -2,11 +2,19 @@
2
2
 
3
3
  Runs **one SQL statement** in-process via `node:sqlite` and writes the result to the `results` channel as `application/json` — ready for a jsonpath body-matcher.
4
4
 
5
- One statement per op is **enforced**: a `sqlite3`-style multi-statement script fails with `sqlite_multi_statement` (400) naming the dropped tail — SQLite compiles only the first statement, and partial execution must never pass as success (#493). Split scripts into one op per statement. Trailing semicolons and comments are fine. Dot-commands (`.tables`, `.schema`) are sqlite3-shell features, not SQL — use their SQL equivalents (`SELECT name FROM sqlite_master`).
5
+ One statement per operation is enforced. A multi-statement script fails with
6
+ `sqlite_multi_statement` (400) and names the rejected tail; partial execution
7
+ never passes as success. Trailing semicolons and comments are allowed.
8
+ Dot-commands such as `.tables` and `.schema` belong to the sqlite3 shell rather
9
+ than SQL. Use their SQL equivalents, such as querying `sqlite_master`.
6
10
 
7
11
  ## Database target
8
12
 
9
- `EXEC[sqlite](./app.db):…` runs against the file `./app.db` (created if absent) — a persistent, host-mutating database. With **no target** it runs against an ephemeral `:memory:` database that's gone when the statement finishes (pure, auto-run). A directory is never a valid target and falls back to `:memory:`.
13
+ `EXEC[sqlite](./app.db):…` runs against the file `./app.db` (created if absent),
14
+ a persistent host-mutating database that requires proposal review. With no
15
+ target, it runs against a fresh `:memory:` database that is gone when the
16
+ operation finishes and bypasses proposal review. A directory is not a database
17
+ target; core routes it as a working directory, leaving SQLite in memory.
10
18
 
11
19
  ## Query vs mutation
12
20
 
@@ -15,4 +23,6 @@ The result shape is decided by the statement's columns, never by parsing the SQL
15
23
  - **Row-returning** (SELECT, RETURNING, PRAGMA) → an array of row objects.
16
24
  - **Mutation** (INSERT / UPDATE / DELETE / CREATE) → `{ changes, lastInsertRowid }`.
17
25
 
18
- Large integers come back stringified (JSON can't hold a bigint). A SQL or open error closes `results` as `errored` with status 500 and a `sqlite_error` telemetry note.
26
+ Large integers come back stringified (JSON cannot hold a bigint). Failures close
27
+ `results` as `errored` with an RFC 9457 Problem: invalid authored SQL is 400, a
28
+ missing database target is 404, and runtime/open failures are 500.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plurnk/plurnk-execs-sqlite",
3
- "version": "1.3.12",
3
+ "version": "1.4.0",
4
4
  "description": "SQLite runtime executor for plurnk-service's exec scheme — runs the sqlite runtime tag in-process via node:sqlite, results as application/json.",
5
5
  "keywords": [
6
6
  "plurnk",
@@ -10,13 +10,14 @@
10
10
  "sqlite",
11
11
  "sql"
12
12
  ],
13
- "homepage": "https://github.com/plurnk/plurnk-execs-sqlite#readme",
13
+ "homepage": "https://github.com/plurnk/plurnk-service/tree/main/plurnk-execs-sqlite#readme",
14
14
  "bugs": {
15
- "url": "https://github.com/plurnk/plurnk-execs-sqlite/issues"
15
+ "url": "https://repo.possumtech.com/plurnk/plurnk-service/issues"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "git+https://github.com/plurnk/plurnk-execs-sqlite.git"
19
+ "url": "git+https://github.com/plurnk/plurnk-service.git",
20
+ "directory": "plurnk-execs-sqlite"
20
21
  },
21
22
  "engines": {
22
23
  "node": ">=26"
@@ -52,14 +53,15 @@
52
53
  ],
53
54
  "scripts": {
54
55
  "test:lint": "tsc --noEmit",
55
- "test:unit": "node --conditions=plurnk-dev --test \"src/**/*.test.ts\"",
56
+ "test:unit": "node --conditions=plurnk-dev --env-file-if-exists=../plurnk-execs/.env.defaults --test \"src/**/*.test.ts\"",
56
57
  "test": "npm run test:lint && npm run test:unit",
58
+ "build:clean": "rm -rf dist",
57
59
  "build:dist": "tsc -p tsconfig.build.json",
58
- "build": "npm run build:dist",
60
+ "build": "npm run build:clean && npm run build:dist",
59
61
  "prepack": "npm run build",
60
62
  "prepublishOnly": "npm audit --audit-level=moderate && npm test"
61
63
  },
62
64
  "peerDependencies": {
63
- "@plurnk/plurnk-execs": "^1.3.12"
65
+ "@plurnk/plurnk-execs": "^1.4.0"
64
66
  }
65
67
  }