@velarscript-labs/sqlite 0.2.2 → 0.3.2

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 CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.2 — 2026-08-25
4
+
5
+ - Rebuild the frozen Node library artifact with VelarScript 0.15, require the
6
+ 0.15 language generation, and depend on Database 0.3.2.
7
+
8
+ ## 0.3.1 — 2026-08-24
9
+
10
+ - Require VelarScript language generation 0.14, verify distribution with CLI
11
+ 0.14.2, and depend on the matching Database 0.3.1 compatibility release.
12
+
13
+ ## 0.3.0 — 2026-08-24
14
+
15
+ - Accept only opaque structured Database statements; runtime values now reach
16
+ Node's `SQLTagStore` exclusively as bound values and prepared statements are
17
+ cached with a bounded LRU.
18
+ - Parse every statement with SQLite's own grammar-derived `sqlite3-parser` and
19
+ reject invalid, multi-statement, trailing, or raw-placeholder SQL before it
20
+ reaches the native driver.
21
+ - Enable defensive mode, foreign keys, safe integer reads, disabled extensions,
22
+ strict parameter names, explicit SQLite resource limits, and an authorizer
23
+ that denies attached databases and extension loading.
24
+ - Add checked journal/read-only/cache options, an escaped `sqliteLiteral`
25
+ helper for DDL and PRAGMA positions, and a quoted `sqliteIdentifier` helper
26
+ for runtime-selected table or column names.
27
+
3
28
  ## 0.2.2 — 2026-08-24
4
29
 
5
30
  - Publish the readable `.vel` source together with frozen Node-targeted Velar
package/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # @velarscript-labs/sqlite
2
2
 
3
- A bounded asynchronous SQLite capability for VelarScript Node applications,
4
- backed by Node's built-in SQLite driver on one owned Worker thread.
3
+ An injection-resistant, bounded asynchronous SQLite capability for VelarScript
4
+ Node applications, backed by Node's built-in SQLite driver on one owned Worker.
5
5
 
6
- The API deliberately stops at parameterized SQL. It does not provide models,
7
- repositories, schema inference, an ORM, or application migrations. Those are
8
- application data and policy, not a reusable driver concern.
6
+ The API accepts only structured `DatabaseStatement` values from
7
+ `@velarscript-labs/database`. Runtime values remain separate from SQL grammar,
8
+ then Node's `SQLTagStore` binds them into cached prepared statements. Every SQL
9
+ shape is parsed as exactly one SQLite statement before native execution.
9
10
 
10
11
  ```velar
12
+ import {sqlConcat, sqlParameter, sqlTuple, trustedSql} from "@velarscript-labs/database"
11
13
  import {SqliteTransaction, openSqlite} from "@velarscript-labs/sqlite"
12
14
 
13
15
  type User:
@@ -15,24 +17,54 @@ type User:
15
17
  name: string
16
18
 
17
19
  using database = await openSqlite("app.sqlite")
18
- await database.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
20
+ await database.execute(trustedSql(
21
+ "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)",
22
+ ))
19
23
 
20
24
  async def create(transaction: SqliteTransaction) -> User:
21
- await transaction.execute("INSERT INTO users (id, name) VALUES (?, ?)", [1, "Ada"])
22
- return (await transaction.one("SELECT id, name FROM users WHERE id = ?", User, [1]))!
25
+ await transaction.execute(sqlConcat([
26
+ trustedSql("INSERT INTO users (id, name) VALUES "),
27
+ sqlTuple([1, "Ada"]),
28
+ ]))
29
+ return (await transaction.one(sqlConcat([
30
+ trustedSql("SELECT id, name FROM users WHERE id = "),
31
+ sqlParameter(1),
32
+ ]), User))!
23
33
 
24
34
  const user = await database.transaction(create)
25
35
  ```
26
36
 
27
- ## Bounds and concurrency
37
+ Use `sqliteLiteral` only where SQLite grammar does not accept a bound value,
38
+ such as a schema default or PRAGMA assignment. It safely quotes strings and
39
+ validates finite numbers. Ordinary reads and writes use `sqlParameter`,
40
+ `sqlTuple`, or `sqlRows`.
28
41
 
42
+ Use `sqliteIdentifier` when a table or column name must be selected at runtime.
43
+ It quotes the complete value as one SQLite identifier; it never treats the
44
+ value as SQL grammar.
45
+
46
+ ## Security and bounds
47
+
48
+ - SQL fragments cannot contain raw `?` placeholders. Every runtime value is
49
+ bound by `SQLTagStore`; it is never interpolated into SQL text.
50
+ - A SQLite-grammar parser rejects invalid SQL, multiple statements, and trailing
51
+ statements before native execution.
52
+ - Defensive mode, foreign keys, safe-integer reads, strict named-parameter
53
+ handling, and disabled extension loading are enforced on every connection.
54
+ - SQLite `ATTACH`/`DETACH` and `load_extension` are denied by the authorizer;
55
+ the run-time attach limit is also zero.
56
+ - SQL length, value length, columns, expression depth, compound selects, VM
57
+ operations, function arguments, variables, LIKE patterns, and trigger depth
58
+ have explicit connection limits.
29
59
  - One Worker owns one SQLite connection; all connection operations are queued
30
60
  and serialized.
31
61
  - `queueCapacity` bounds admitted operations. Default 64, maximum 1,024.
62
+ - `statementCacheCapacity` bounds the prepared-statement LRU. Default 128,
63
+ maximum 1,024.
32
64
  - One statement accepts at most 999 parameters and 1 MiB of SQL text.
33
65
  - `maxRows` defaults to 10,000 and is capped at 1,000,000.
34
66
  - `maxResultBytes` defaults to 64 MiB and is capped at 128 MiB. It also bounds
35
- parameter bytes for one operation.
67
+ parameter bytes for one operation and SQLite value length.
36
68
  - Numbers must be finite; integer parameters and results must fit JavaScript's
37
69
  safe integer range. BLOB values use `Bytes`.
38
70
  - A transaction callback is the exclusive connection owner. Use the supplied
@@ -43,5 +75,5 @@ const user = await database.transaction(create)
43
75
  - `close` is idempotent, joins concurrent callers, drains admitted work, rolls
44
76
  back an active transaction, closes the driver, and waits for the Worker.
45
77
 
46
- Cancellation and streaming are intentionally absent from version 0.2. They
47
- will not be claimed until their cleanup and backpressure contracts are proven.
78
+ This package still does not own models, repositories, schema inference, an ORM,
79
+ or application migrations. Those remain application data and policy.