@cavelang/store 0.27.3 → 0.29.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/Authors.md +5 -0
- package/License.md +6 -0
- package/README.md +121 -14
- package/dist/src/adapter-entry.d.ts +9 -0
- package/dist/src/adapter-entry.d.ts.map +1 -0
- package/dist/src/adapter-entry.js +7 -0
- package/dist/src/adapter-entry.js.map +1 -0
- package/dist/src/adapter.d.ts +51 -0
- package/dist/src/adapter.d.ts.map +1 -0
- package/dist/src/adapter.js +3 -0
- package/dist/src/adapter.js.map +1 -0
- package/dist/src/backup.d.ts +23 -0
- package/dist/src/backup.d.ts.map +1 -0
- package/dist/src/backup.js +164 -0
- package/dist/src/backup.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/node-adapter-entry.d.ts +3 -0
- package/dist/src/node-adapter-entry.d.ts.map +1 -0
- package/dist/src/node-adapter-entry.js +3 -0
- package/dist/src/node-adapter-entry.js.map +1 -0
- package/dist/src/node-adapter.d.ts +4 -0
- package/dist/src/node-adapter.d.ts.map +1 -0
- package/dist/src/node-adapter.js +20 -0
- package/dist/src/node-adapter.js.map +1 -0
- package/dist/src/open.d.ts +3 -18
- package/dist/src/open.d.ts.map +1 -1
- package/dist/src/open.js +4 -52
- package/dist/src/open.js.map +1 -1
- package/dist/src/provenance.d.ts +24 -0
- package/dist/src/provenance.d.ts.map +1 -0
- package/dist/src/provenance.js +75 -0
- package/dist/src/provenance.js.map +1 -0
- package/dist/src/query-sql.d.ts +45 -0
- package/dist/src/query-sql.d.ts.map +1 -0
- package/dist/src/query-sql.js +77 -0
- package/dist/src/query-sql.js.map +1 -0
- package/dist/src/record.d.ts +29 -0
- package/dist/src/record.d.ts.map +1 -0
- package/dist/src/record.js +50 -0
- package/dist/src/record.js.map +1 -0
- package/dist/src/resolve.d.ts +2 -2
- package/dist/src/resolve.d.ts.map +1 -1
- package/dist/src/resolve.js +0 -0
- package/dist/src/resolve.js.map +1 -1
- package/dist/src/runtime.d.ts +16 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/runtime.js +43 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/schema.d.ts +10 -6
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +113 -9
- package/dist/src/schema.js.map +1 -1
- package/dist/src/sensitivity.d.ts +24 -0
- package/dist/src/sensitivity.d.ts.map +1 -0
- package/dist/src/sensitivity.js +34 -0
- package/dist/src/sensitivity.js.map +1 -0
- package/dist/src/store.d.ts +40 -14
- package/dist/src/store.d.ts.map +1 -1
- package/dist/src/store.js +113 -74
- package/dist/src/store.js.map +1 -1
- package/package.json +25 -6
- package/src/adapter-entry.ts +18 -0
- package/src/adapter.ts +57 -0
- package/src/backup.ts +188 -0
- package/src/index.ts +8 -0
- package/src/node-adapter-entry.ts +3 -0
- package/src/node-adapter.ts +23 -0
- package/src/open.ts +7 -80
- package/src/provenance.ts +109 -0
- package/src/query-sql.ts +99 -0
- package/src/record.ts +82 -0
- package/src/resolve.ts +0 -0
- package/src/runtime.ts +78 -0
- package/src/schema.ts +137 -10
- package/src/sensitivity.ts +42 -0
- package/src/store.ts +140 -82
package/Authors.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Authors
|
|
2
|
+
|
|
3
|
+
By adding their name to this file, all listed authors confirm they have copyright over their contributions to this project and are waiving these rights, placing their work in the public domain in accordance with the CC0 1.0 Universal Public Domain Dedication.
|
|
4
|
+
|
|
5
|
+
- Mirek Rusin (Switzerland)
|
package/License.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
|
2
|
+
|
|
3
|
+
To the extent possible under law, the authors listed in [Authors.md](./Authors.md) have waived all copyright and related or neighboring rights to this software and associated documentation files (the "Software").
|
|
4
|
+
|
|
5
|
+
For more information, please see:
|
|
6
|
+
https://creativecommons.org/publicdomain/zero/1.0/
|
package/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# @cavelang/store
|
|
2
2
|
|
|
3
|
-
CAVE persistence
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
CAVE persistence through an explicit synchronous SQLite adapter. The default
|
|
4
|
+
Node entry uses the builtin `node:sqlite` with no native dependencies; browser
|
|
5
|
+
runtimes can inject a WASM implementation. Implements the spec §13 storage model: the exact §13.1/§13.2
|
|
6
|
+
schema (`cave_claim`, `cave_context`, `cave_provenance`, `cave_tag`, `cave_edge`, `cave_fts`
|
|
7
|
+
full-text index), append-only belief series, and inverse-aware reads.
|
|
7
8
|
|
|
8
9
|
```ts
|
|
9
10
|
import { open } from '@cavelang/store'
|
|
@@ -15,24 +16,108 @@ monorepo CONTAINS packages/api @ 90%
|
|
|
15
16
|
`)
|
|
16
17
|
store.currentBeliefs() // one row — one fact, one key, conf 0.9
|
|
17
18
|
store.reverse('packages/api') // [{ verb: 'CONTAINS', rel: 'PART-OF', source: 'monorepo' }]
|
|
18
|
-
store.exportText({ current: true }) // canonical
|
|
19
|
+
store.exportText({ current: true }) // canonical text through internal
|
|
20
|
+
store.exportText({ maxSensitivity: 'restricted' }) // complete portable history
|
|
19
21
|
```
|
|
20
22
|
|
|
23
|
+
Runtime selection is explicit at non-Node composition boundaries:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { openWith, type SqliteAdapter } from '@cavelang/store/adapter'
|
|
27
|
+
|
|
28
|
+
declare const adapter: SqliteAdapter
|
|
29
|
+
const store = openWith(adapter, ':memory:')
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`SqliteAdapter` declares the SQL statement surface plus immediate/savepoint
|
|
33
|
+
transactions, FTS4 or FTS5, optional extension loading, and optional exact
|
|
34
|
+
snapshot support. The concrete Node adapter is also available from
|
|
35
|
+
`@cavelang/store/adapter/node`. The shared adapter contract suite runs against
|
|
36
|
+
both Node SQLite and the website's SQL.js/WASM adapter.
|
|
37
|
+
|
|
38
|
+
## Composable query SQL
|
|
39
|
+
|
|
40
|
+
`QuerySql` is the public source of truth for semantics shared by store,
|
|
41
|
+
CAVE-Q, shapes, generated clients, and views:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { QuerySql } from '@cavelang/store'
|
|
45
|
+
|
|
46
|
+
const boundary = QuerySql.asOfBoundary('2026-07-16')!
|
|
47
|
+
const currentThen = QuerySql.current(QuerySql.claims(boundary))
|
|
48
|
+
const rows = store.db.prepare(`SELECT * FROM (${currentThen}) WHERE conf > 0`).all()
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`current()` selects latest tx per claim key without filtering negation or
|
|
52
|
+
retraction; consumers add those predicates for their read mode. `aliasEdges`,
|
|
53
|
+
`aliasPairs`, `aliasClosure`, and `aliasSame` implement entity-only current
|
|
54
|
+
positive ALIAS semantics. `transactionBounds` and `asOfBoundary` use
|
|
55
|
+
`Time.parseBoundary` for shared whole-period/whole-second semantics
|
|
56
|
+
(offset-less timestamps are UTC) and exact-transaction rules. Fragments own no
|
|
57
|
+
ordering or outer filtering, so consumers can extend them without copying
|
|
58
|
+
semantic clauses.
|
|
59
|
+
|
|
60
|
+
## External records
|
|
61
|
+
|
|
62
|
+
Database rows (`Row.t`, snake_case columns) are the storage-oriented API and
|
|
63
|
+
may evolve with the schema. Use `store.recordOf(row)` for serialized or
|
|
64
|
+
cross-process data. It returns `cave.claim/v1`: transaction identity (`id`,
|
|
65
|
+
`tx`, `key`), canonical CAVE text, the semantic `Claim.t`, and explicit
|
|
66
|
+
provenance dimensions. `Record.encode`/`Record.decode` own the JSON contract;
|
|
67
|
+
decoding rejects unknown versions and verifies transaction, key, and canonical
|
|
68
|
+
text identity. The checked-in v1 fixture is the compatibility baseline for
|
|
69
|
+
future decoders.
|
|
70
|
+
|
|
21
71
|
## Semantics
|
|
22
72
|
|
|
73
|
+
- **Schema upgrades are explicit** (§13.2.1): `PRAGMA user_version` records
|
|
74
|
+
the local format (current version 1; version 0 is the unversioned legacy
|
|
75
|
+
baseline). `open()` rejects newer stores, applies every older migration in
|
|
76
|
+
order with its backfill and version update in one `BEGIN IMMEDIATE`
|
|
77
|
+
transaction, then validates required tables, indexes, and columns. A crash
|
|
78
|
+
leaves a resumable old or complete new version—never a committed half-step.
|
|
79
|
+
Migrations are forward-only; make rollback points by closing all users and
|
|
80
|
+
copying the closed SQLite file before upgrade.
|
|
81
|
+
- **Exact backup is an online SQLite snapshot** (§13.2.2): `backup()` runs
|
|
82
|
+
`VACUUM INTO` to a temporary sibling, verifies integrity, foreign keys and
|
|
83
|
+
schema, fsyncs it, computes SHA-256, and atomically publishes it. WAL-visible
|
|
84
|
+
committed rows and concurrent readers/writers are safe. `restoreBackup()`
|
|
85
|
+
verifies the source and temporary copy before atomic publication and refuses
|
|
86
|
+
destination WAL/SHM/journal sidecars. `verifyBackup()` supports independent checks.
|
|
23
87
|
- **Append-only** (§9.1): `ingest` only inserts; every row carries a
|
|
24
88
|
monotonic UUIDv7 in `id` and `tx`, so `MAX(tx)` per `claim_key` is the
|
|
25
|
-
current belief. Each ingest call is one SQLite transaction.
|
|
89
|
+
current belief. Each ingest call is one SQLite transaction. Outer writes
|
|
90
|
+
reserve SQLite's write lock and re-observe `MAX(tx)` before minting, so
|
|
91
|
+
concurrent processes allocate in commit order; lock contention waits for
|
|
92
|
+
up to five seconds before surfacing `SQLITE_BUSY`.
|
|
93
|
+
- **History is permanent** (§9.6): retraction appends a `0%` row; it never
|
|
94
|
+
erases the earlier row, `raw_line`, metadata, FTS text, export, backup, or
|
|
95
|
+
peer copy. The store has no row-level redact/forget API because local
|
|
96
|
+
deletion cannot guarantee erasure across SQLite remnants and distributed
|
|
97
|
+
copies. Keep secrets and selectively erasable data out of CAVE; recover
|
|
98
|
+
from accidental ingestion by quarantining every copy and rebuilding from
|
|
99
|
+
reviewed safe input.
|
|
100
|
+
- **Publication is sensitivity-scoped** (§9.7):
|
|
101
|
+
`#sensitivity:public|internal|confidential|restricted` labels each immutable
|
|
102
|
+
row; unlabeled means `internal`, while flat, malformed and unknown labels
|
|
103
|
+
fail closed as `restricted`. Export defaults to a maximum of `internal`.
|
|
104
|
+
Select `restricted` explicitly for complete portable text history. This is routing metadata,
|
|
105
|
+
not encryption, access control, erasure or a retention boundary.
|
|
26
106
|
- **One row per fact** (§13.3): inverse writes are canonicalized before
|
|
27
107
|
keying (`@cavelang/canonical`), inverse *reads* are query-time views —
|
|
28
108
|
`forward()` uses the subject index, `reverse()` the object index with the
|
|
29
109
|
relation named via the registry's `inverseOf`. Nothing is materialized.
|
|
30
|
-
- **Registry persistence is in-band**: `REVERSE` and `X IS verb` claims are
|
|
110
|
+
- **Registry persistence is in-band**: `REVERSE`, `RENAMED-TO`, and `X IS verb` claims are
|
|
31
111
|
ordinary rows; on open the store replays them (in tx order) on top of the
|
|
32
112
|
initial registry, which defaults to the standard §5.5 prelude pairs. The
|
|
33
113
|
replay predicate mirrors the canonicalizer exactly — qualifier-condition
|
|
34
114
|
rows never declare, and `X IS verb` needs a verb-shaped subject — so the
|
|
35
115
|
registry after reopen equals the registry at close.
|
|
116
|
+
- **Verb renames preserve history** (§5.8): after `OLD RENAMED-TO NEW`,
|
|
117
|
+
either spelling writes the stable `OLD` storage verb and therefore the same
|
|
118
|
+
claim key. `NEW` is preferred for authors while `OLD` remains compatible;
|
|
119
|
+
declaration replay on reopen and `registryAsOf` preserve the same
|
|
120
|
+
transaction-time boundary semantics as inverse declarations.
|
|
36
121
|
- **Traversal defaults**: `forward`/`reverse`/`topicMembers`/`topicsOf`
|
|
37
122
|
read *current beliefs* and skip negated (`VERB NOT`) and retracted
|
|
38
123
|
(`@ 0%`) rows; opt back in with `{ negated: true, retracted: true }`.
|
|
@@ -52,6 +137,18 @@ store.exportText({ current: true }) // canonical CAVE text back out
|
|
|
52
137
|
different actors keeps separate belief series (§9.4). A written `@src:`
|
|
53
138
|
always wins; `raw_line` stays as authored. Interchange replay (`cave
|
|
54
139
|
import`) passes no source, preserving exported keys.
|
|
140
|
+
- **Provenance dimensions are explicit** (§9.5.1): every row projects
|
|
141
|
+
actor, physical source, lifecycle run, and `scope:` domain into indexed
|
|
142
|
+
`cave_provenance` entries. Contexts and keys remain the compatibility text
|
|
143
|
+
representation. Lifecycle systems use `run` lookup rather than authored
|
|
144
|
+
`src:` strings; resolution reads actor/source. Opening old stores backfills
|
|
145
|
+
only established actor/run prefixes, decoded sources, and explicit scopes.
|
|
146
|
+
- **Source spans retain source identity** (§9.8):
|
|
147
|
+
`@src:docs/design%20notes.md#L10-L20` carries a one-based inclusive range;
|
|
148
|
+
`SourceSpan` owns escaping and parsing. The exact context remains in the
|
|
149
|
+
claim key, while resolution/reliability strip the line fragment before
|
|
150
|
+
policy matching. `AppendOptions.contexts` lets connectors attach structured
|
|
151
|
+
spans before keying without rewriting generated CAVE text.
|
|
55
152
|
- **Contradiction resolution is opt-in** (§26): `{ resolve: true }` on
|
|
56
153
|
traversal reads only the winners — coexisting series about one fact
|
|
57
154
|
(claim key modulo `src:` contexts and polarity) collapse to the row the
|
|
@@ -74,6 +171,7 @@ store.exportText({ current: true }) // canonical CAVE text back out
|
|
|
74
171
|
| `insertResult(result, {source})` | | append a pre-canonicalized `@cavelang/canonical` result |
|
|
75
172
|
| `currentBeliefs({minConf})` | §13.5 | latest row per key |
|
|
76
173
|
| `currentBelief(key)` / `history(key)` | §9.1 | one fact's belief series |
|
|
174
|
+
| `provenanceOf(rowOrId)` / `byProvenance(dimension, value)` | §9.5.1 | inspect or filter actor/source/run/domain |
|
|
77
175
|
| `resolvedBeliefs({aliases})` | §26 | one winner per resolution group |
|
|
78
176
|
| `contested({aliases})` | §26.4 | contested groups, candidates ranked winner-first — the fusion feed |
|
|
79
177
|
| `resolutionPolicy()` | §26.3 | effective policy: built-ins merged with in-band declarations |
|
|
@@ -83,11 +181,14 @@ store.exportText({ current: true }) // canonical CAVE text back out
|
|
|
83
181
|
| `byTag(key, value?)` | §13.5 | flat (`value` omitted → `IS NULL`) or scoped |
|
|
84
182
|
| `byContext(ctx)` | §13.5 | context filter |
|
|
85
183
|
| `topicMembers(t)` / `topicsOf(e)` | §11.2 | topic layer over `CONTAINS` |
|
|
86
|
-
| `search(q, {raw})` | §13.2 |
|
|
184
|
+
| `search(q, {raw, limit, maxSensitivity})` | §13.2 | adapter full-text search; literal phrase by default, `limit` caps in the query; sensitivity is opt-in for enclosing publication surfaces |
|
|
87
185
|
| `edgesOf(id)` | §13.2 | qualifier/grouping edges with roles |
|
|
88
186
|
| `toClaim(row)` | | reconstruct the canonical claim + side tables |
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
187
|
+
| `registry()` / `baseRegistry()` | §5.5 | current registry and its configured pre-declaration base |
|
|
188
|
+
| `recordOf(row)` | | map a storage row to the stable `cave.claim/v1` JSON contract |
|
|
189
|
+
| `exportText({current, tx, maxSensitivity})` | §9.7 | emit sensitivity-scoped canonical CAVE text (default maximum `internal`); `tx` includes replayable `;@` row identities; `current` compacts, never sanitizes; complete portable history requires `restricted` |
|
|
190
|
+
| `backup(store, path)` / `verifyBackup(path)` / `restoreBackup(snapshot, path)` | §13.2.2 | exact verified SQLite snapshot lifecycle |
|
|
191
|
+
| `adapter` / `db` | | selected adapter capabilities and its raw structural database handle |
|
|
91
192
|
|
|
92
193
|
## Storage decisions
|
|
93
194
|
|
|
@@ -100,14 +201,19 @@ store.exportText({ current: true }) // canonical CAVE text back out
|
|
|
100
201
|
normalized §13.4 forms. Same for `delta_*`.
|
|
101
202
|
- **`id` doubles as `tx`** by default: a UUIDv7 is both unique and
|
|
102
203
|
time-ordered, and per-row tx ids keep same-document belief updates
|
|
103
|
-
ordered by line.
|
|
104
|
-
|
|
204
|
+
ordered by line. Allocation is database-serialized across processes;
|
|
205
|
+
nested store transactions remain savepoints.
|
|
206
|
+
- **`search()` phrase-quotes by default** — SQLite full-text syntax would parse
|
|
105
207
|
`token-expiry` as a column filter; `{ raw: true }` opts into full MATCH
|
|
106
208
|
syntax.
|
|
107
209
|
- **Current-only export remaps edge endpoints** to the current row of each
|
|
108
210
|
endpoint's claim key: a superseded qualified parent keeps its `WHEN`
|
|
109
211
|
attached to the surviving belief, and orphaned condition claims are never
|
|
110
212
|
promoted to top-level facts.
|
|
213
|
+
- **Sensitivity filtering follows current resolution**: the latest row is
|
|
214
|
+
selected before its audience is checked, so a hidden current belief never
|
|
215
|
+
revives an older visible row. Full-history export checks each row. Edges with
|
|
216
|
+
either endpoint hidden are omitted.
|
|
111
217
|
|
|
112
218
|
## Tests
|
|
113
219
|
|
|
@@ -124,5 +230,6 @@ cross-actor retraction, stamped round-trips), the §26 resolution policy
|
|
|
124
230
|
(human-over-ingest precedence, reliability weighting, longest-prefix
|
|
125
231
|
specificity, polarity contests, no self-elevation, alias-widened
|
|
126
232
|
groups, contested ranking), the §11.2 topic reads, edge persistence,
|
|
127
|
-
registry rebuild across reopen, transactional strict ingest and export
|
|
128
|
-
round-trips
|
|
233
|
+
registry and lifecycle rebuild across reopen, transactional strict ingest and export
|
|
234
|
+
round-trips, ordered schema migration, newer-version rejection, transactional
|
|
235
|
+
rollback/retry, and closed-file backup recovery.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Explicit, runtime-neutral SQLite composition surface. */
|
|
2
|
+
export { openWith } from './runtime.ts';
|
|
3
|
+
export type { Store } from './runtime.ts';
|
|
4
|
+
export * as Resolve from './resolve.ts';
|
|
5
|
+
export * as Row from './row.ts';
|
|
6
|
+
export * as QuerySql from './query-sql.ts';
|
|
7
|
+
export * as Record from './record.ts';
|
|
8
|
+
export type { Adapter as SqliteAdapter, BackupCapability as SqliteBackupCapability, Capabilities as SqliteCapabilities, Database as SqliteDatabase, OpenOptions as SqliteOpenOptions, Row as SqliteRow, Statement as SqliteStatement, Value as SqliteValue, } from './adapter.ts';
|
|
9
|
+
//# sourceMappingURL=adapter-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-entry.d.ts","sourceRoot":"","sources":["../../src/adapter-entry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,YAAY,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,YAAY,EACV,OAAO,IAAI,aAAa,EACxB,gBAAgB,IAAI,sBAAsB,EAC1C,YAAY,IAAI,kBAAkB,EAClC,QAAQ,IAAI,cAAc,EAC1B,WAAW,IAAI,iBAAiB,EAChC,GAAG,IAAI,SAAS,EAChB,SAAS,IAAI,eAAe,EAC5B,KAAK,IAAI,WAAW,GACrB,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Explicit, runtime-neutral SQLite composition surface. */
|
|
2
|
+
export { openWith } from "./runtime.js";
|
|
3
|
+
export * as Resolve from "./resolve.js";
|
|
4
|
+
export * as Row from "./row.js";
|
|
5
|
+
export * as QuerySql from "./query-sql.js";
|
|
6
|
+
export * as Record from "./record.js";
|
|
7
|
+
//# sourceMappingURL=adapter-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-entry.js","sourceRoot":"","sources":["../../src/adapter-entry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Runtime-neutral SQLite contract used by the CAVE store. */
|
|
2
|
+
export type Value = null | number | bigint | string | Uint8Array;
|
|
3
|
+
export type Row = Record<string, unknown>;
|
|
4
|
+
export type Statement = {
|
|
5
|
+
readonly all: (...params: Value[]) => Row[];
|
|
6
|
+
readonly get: (...params: Value[]) => Row | undefined;
|
|
7
|
+
readonly run: (...params: Value[]) => {
|
|
8
|
+
readonly changes: number | bigint;
|
|
9
|
+
readonly lastInsertRowid: number | bigint;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export type Database = {
|
|
13
|
+
readonly exec: (sql: string) => void;
|
|
14
|
+
readonly prepare: (sql: string) => Statement;
|
|
15
|
+
readonly close: () => void;
|
|
16
|
+
};
|
|
17
|
+
export type OpenOptions = {
|
|
18
|
+
readonly readOnly?: boolean;
|
|
19
|
+
/** Permit native extension loading when the implementation supports it. */
|
|
20
|
+
readonly allowExtension?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type BackupCapability = {
|
|
23
|
+
/** Absolute or implementation-defined source location; null for memory stores. */
|
|
24
|
+
readonly location: (db: Database) => string | null;
|
|
25
|
+
readonly inTransaction: (db: Database) => boolean;
|
|
26
|
+
/** Write a transactionally consistent standalone database image. */
|
|
27
|
+
readonly write: (db: Database, destination: string) => void;
|
|
28
|
+
};
|
|
29
|
+
export type Capabilities = {
|
|
30
|
+
/** CAVE requires immediate write transactions and nested savepoints. */
|
|
31
|
+
readonly transactions: {
|
|
32
|
+
readonly immediate: true;
|
|
33
|
+
readonly savepoints: true;
|
|
34
|
+
};
|
|
35
|
+
/** Full-text virtual-table implementation used by the schema. */
|
|
36
|
+
readonly fullText: 'fts4' | 'fts5';
|
|
37
|
+
/** Optional loading of native SQLite extensions. */
|
|
38
|
+
readonly loadExtension?: (db: Database, path: string) => void;
|
|
39
|
+
/** Optional exact snapshot support. */
|
|
40
|
+
readonly backup?: BackupCapability;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* A synchronous SQLite implementation. Runtime selection happens by passing
|
|
44
|
+
* one of these to `openWith`, never by replacing source modules at build time.
|
|
45
|
+
*/
|
|
46
|
+
export type Adapter = {
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly capabilities: Capabilities;
|
|
49
|
+
readonly open: (path: string, options?: OpenOptions) => Database;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAE9D,MAAM,MAAM,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAA;AAChE,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEzC,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,EAAE,CAAA;IAC3C,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,SAAS,CAAA;IACrD,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK;QACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;QACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAA;KAC1C,CAAA;CACF,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAA;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B,2EAA2E;IAC3E,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,MAAM,GAAG,IAAI,CAAA;IAClD,QAAQ,CAAC,aAAa,EAAE,CAAC,EAAE,EAAE,QAAQ,KAAK,OAAO,CAAA;IACjD,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5D,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,wEAAwE;IACxE,QAAQ,CAAC,YAAY,EAAE;QACrB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;QACxB,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;KAC1B,CAAA;IACD,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IAClC,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7D,uCAAuC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAA;CACnC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAA;IACnC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,QAAQ,CAAA;CACjE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/adapter.ts"],"names":[],"mappings":"AAAA,8DAA8D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Exact SQLite snapshot backup, verification, and atomic restore. */
|
|
2
|
+
import type { Store } from './store.ts';
|
|
3
|
+
export type Snapshot = {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly bytes: number;
|
|
6
|
+
readonly sha256: string;
|
|
7
|
+
readonly schemaVersion: number;
|
|
8
|
+
readonly rows: number;
|
|
9
|
+
readonly maxTx: null | string;
|
|
10
|
+
};
|
|
11
|
+
export type WriteOptions = {
|
|
12
|
+
/** Replace an existing destination atomically. Never permits source = destination. */
|
|
13
|
+
readonly force?: boolean;
|
|
14
|
+
};
|
|
15
|
+
/** Validate a standalone snapshot without migrating or mutating it. */
|
|
16
|
+
export declare const verifyBackup: (path: string, expectedSha256?: string) => Snapshot;
|
|
17
|
+
/** Create and atomically publish a verified, point-in-time SQLite snapshot. */
|
|
18
|
+
export declare const backup: (store: Store, destination: string, options?: WriteOptions) => Snapshot;
|
|
19
|
+
/** Verify a snapshot, then atomically restore its exact bytes to a stopped destination. */
|
|
20
|
+
export declare const restoreBackup: (snapshotPath: string, destination: string, options?: WriteOptions & {
|
|
21
|
+
expectedSha256?: string;
|
|
22
|
+
}) => Snapshot;
|
|
23
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/backup.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAQtE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAIvC,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,sFAAsF;IACtF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB,CAAA;AAgED,uEAAuE;AACvE,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,EAAE,iBAAiB,MAAM,KAAG,QAmCpE,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,aAAa,MAAM,EAAE,UAAS,YAAiB,KAAG,QA2BtF,CAAA;AAED,2FAA2F;AAC3F,eAAO,MAAM,aAAa,GACxB,cAAc,MAAM,EACpB,aAAa,MAAM,EACnB,UAAS,YAAY,GAAG;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,KACvD,QA0BF,CAAA"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/** Exact SQLite snapshot backup, verification, and atomic restore. */
|
|
2
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
3
|
+
import { closeSync, copyFileSync, existsSync, fsyncSync, linkSync, openSync, readSync, realpathSync, renameSync, rmSync, statSync } from 'node:fs';
|
|
4
|
+
import { basename, dirname, resolve } from 'node:path';
|
|
5
|
+
import { nodeSqliteAdapter } from "./node-adapter.js";
|
|
6
|
+
import * as Schema from "./schema.js";
|
|
7
|
+
const temporaryPath = (destination) => {
|
|
8
|
+
const target = resolve(destination);
|
|
9
|
+
return resolve(dirname(target), `.${basename(target)}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`);
|
|
10
|
+
};
|
|
11
|
+
const hashFile = (path) => {
|
|
12
|
+
const hash = createHash('sha256');
|
|
13
|
+
const fd = openSync(path, 'r');
|
|
14
|
+
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
15
|
+
try {
|
|
16
|
+
for (;;) {
|
|
17
|
+
const size = readSync(fd, buffer, 0, buffer.length, null);
|
|
18
|
+
if (size === 0)
|
|
19
|
+
break;
|
|
20
|
+
hash.update(buffer.subarray(0, size));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
closeSync(fd);
|
|
25
|
+
}
|
|
26
|
+
return hash.digest('hex');
|
|
27
|
+
};
|
|
28
|
+
const syncFile = (path) => {
|
|
29
|
+
const fd = openSync(path, 'r');
|
|
30
|
+
try {
|
|
31
|
+
fsyncSync(fd);
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
closeSync(fd);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const syncDirectory = (path) => {
|
|
38
|
+
let fd;
|
|
39
|
+
try {
|
|
40
|
+
fd = openSync(dirname(resolve(path)), 'r');
|
|
41
|
+
fsyncSync(fd);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Some platforms do not permit opening/fsyncing a directory. The fully
|
|
45
|
+
// written database itself is still synced before publication.
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
if (fd !== undefined)
|
|
49
|
+
closeSync(fd);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const publish = (temporary, destination, force) => {
|
|
53
|
+
const target = resolve(destination);
|
|
54
|
+
if (force) {
|
|
55
|
+
renameSync(temporary, target);
|
|
56
|
+
syncDirectory(target);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// A hard link publishes the fully written inode atomically and fails if a
|
|
60
|
+
// racing process created the destination after the initial existence check.
|
|
61
|
+
linkSync(temporary, target);
|
|
62
|
+
rmSync(temporary);
|
|
63
|
+
syncDirectory(target);
|
|
64
|
+
};
|
|
65
|
+
const samePath = (left, right) => existsSync(left) && existsSync(right) ?
|
|
66
|
+
realpathSync(left) === realpathSync(right) :
|
|
67
|
+
resolve(left) === resolve(right);
|
|
68
|
+
/** Validate a standalone snapshot without migrating or mutating it. */
|
|
69
|
+
export const verifyBackup = (path, expectedSha256) => {
|
|
70
|
+
const target = resolve(path);
|
|
71
|
+
if (!existsSync(target)) {
|
|
72
|
+
throw new Error(`CAVE backup: ${target}: no such file`);
|
|
73
|
+
}
|
|
74
|
+
const db = nodeSqliteAdapter.open(target, { readOnly: true });
|
|
75
|
+
let schemaVersion = 0;
|
|
76
|
+
let rows = 0;
|
|
77
|
+
let maxTx = null;
|
|
78
|
+
try {
|
|
79
|
+
const integrity = db.prepare('PRAGMA integrity_check').all();
|
|
80
|
+
if (integrity.length !== 1 || integrity[0]?.integrity_check !== 'ok') {
|
|
81
|
+
throw new Error(`integrity_check failed: ${integrity.map(row => row.integrity_check).join('; ')}`);
|
|
82
|
+
}
|
|
83
|
+
const foreignKeys = db.prepare('PRAGMA foreign_key_check').all();
|
|
84
|
+
if (foreignKeys.length > 0) {
|
|
85
|
+
throw new Error(`foreign_key_check failed for ${foreignKeys.length} row(s)`);
|
|
86
|
+
}
|
|
87
|
+
schemaVersion = db.prepare('PRAGMA user_version').get().user_version;
|
|
88
|
+
if (schemaVersion !== Schema.currentVersion) {
|
|
89
|
+
throw new Error(`schema version ${schemaVersion} is not the exact-backup format ${Schema.currentVersion}`);
|
|
90
|
+
}
|
|
91
|
+
Schema.validate(db, schemaVersion);
|
|
92
|
+
const summary = db.prepare('SELECT COUNT(*) AS rows, MAX(tx) AS max_tx FROM cave_claim').get();
|
|
93
|
+
rows = summary.rows;
|
|
94
|
+
maxTx = summary.max_tx;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
db.close();
|
|
98
|
+
}
|
|
99
|
+
const sha256 = hashFile(target);
|
|
100
|
+
if (expectedSha256 !== undefined && sha256 !== expectedSha256.toLowerCase()) {
|
|
101
|
+
throw new Error(`CAVE backup: SHA-256 mismatch: expected ${expectedSha256.toLowerCase()}, got ${sha256}`);
|
|
102
|
+
}
|
|
103
|
+
return { path: target, bytes: statSync(target).size, sha256, schemaVersion, rows, maxTx };
|
|
104
|
+
};
|
|
105
|
+
/** Create and atomically publish a verified, point-in-time SQLite snapshot. */
|
|
106
|
+
export const backup = (store, destination, options = {}) => {
|
|
107
|
+
const target = resolve(destination);
|
|
108
|
+
const capability = store.adapter.capabilities.backup;
|
|
109
|
+
if (capability === undefined) {
|
|
110
|
+
throw new Error(`CAVE backup: SQLite adapter ${JSON.stringify(store.adapter.name)} does not support exact snapshots`);
|
|
111
|
+
}
|
|
112
|
+
const source = capability.location(store.db);
|
|
113
|
+
if (source !== null && samePath(source, target)) {
|
|
114
|
+
throw new Error('CAVE backup: destination is the source database');
|
|
115
|
+
}
|
|
116
|
+
if (existsSync(target) && options.force !== true) {
|
|
117
|
+
throw new Error(`CAVE backup: ${target} already exists; pass force to replace it`);
|
|
118
|
+
}
|
|
119
|
+
if (capability.inTransaction(store.db)) {
|
|
120
|
+
throw new Error('CAVE backup: cannot snapshot inside an open transaction');
|
|
121
|
+
}
|
|
122
|
+
const temporary = temporaryPath(target);
|
|
123
|
+
try {
|
|
124
|
+
capability.write(store.db, temporary);
|
|
125
|
+
syncFile(temporary);
|
|
126
|
+
const checked = verifyBackup(temporary);
|
|
127
|
+
publish(temporary, target, options.force === true);
|
|
128
|
+
return { ...checked, path: target };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
rmSync(temporary, { force: true });
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
/** Verify a snapshot, then atomically restore its exact bytes to a stopped destination. */
|
|
136
|
+
export const restoreBackup = (snapshotPath, destination, options = {}) => {
|
|
137
|
+
const source = resolve(snapshotPath);
|
|
138
|
+
const target = resolve(destination);
|
|
139
|
+
if (samePath(source, target)) {
|
|
140
|
+
throw new Error('CAVE restore: snapshot and destination are the same file');
|
|
141
|
+
}
|
|
142
|
+
if (existsSync(target) && options.force !== true) {
|
|
143
|
+
throw new Error(`CAVE restore: ${target} already exists; pass force to replace it`);
|
|
144
|
+
}
|
|
145
|
+
for (const suffix of ['-wal', '-shm', '-journal']) {
|
|
146
|
+
if (existsSync(`${target}${suffix}`)) {
|
|
147
|
+
throw new Error(`CAVE restore: refusing while ${target}${suffix} exists; stop all users and remove stale sidecars`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const checked = verifyBackup(source, options.expectedSha256);
|
|
151
|
+
const temporary = temporaryPath(target);
|
|
152
|
+
try {
|
|
153
|
+
copyFileSync(source, temporary);
|
|
154
|
+
syncFile(temporary);
|
|
155
|
+
const copied = verifyBackup(temporary, checked.sha256);
|
|
156
|
+
publish(temporary, target, options.force === true);
|
|
157
|
+
return { ...copied, path: target };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
rmSync(temporary, { force: true });
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/backup.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -13,9 +13,17 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export * as Resolve from './resolve.ts';
|
|
15
15
|
export * as Row from './row.ts';
|
|
16
|
+
export * as QuerySql from './query-sql.ts';
|
|
17
|
+
export * as Record from './record.ts';
|
|
18
|
+
export * as Provenance from './provenance.ts';
|
|
16
19
|
export * as Schema from './schema.ts';
|
|
20
|
+
export * as Sensitivity from './sensitivity.ts';
|
|
21
|
+
export { backup, restoreBackup, verifyBackup } from './backup.ts';
|
|
22
|
+
export type { Snapshot as BackupSnapshot, WriteOptions as BackupWriteOptions } from './backup.ts';
|
|
17
23
|
export { open } from './open.ts';
|
|
18
24
|
export type { Store } from './open.ts';
|
|
19
25
|
export { defaultDbPath } from './store.ts';
|
|
20
26
|
export type { AppendOptions, ForwardFact, IngestResult, ReverseFact, TraverseOptions } from './store.ts';
|
|
27
|
+
export type { Dimension as ProvenanceDimension, Input as ProvenanceInput, t as ProvenanceRecord } from './provenance.ts';
|
|
28
|
+
export type { Level as SensitivityLevel } from './sensitivity.ts';
|
|
21
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,YAAY,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACjE,YAAY,EAAE,QAAQ,IAAI,cAAc,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAA;AACjG,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,YAAY,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC1C,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACxG,YAAY,EAAE,SAAS,IAAI,mBAAmB,EAAE,KAAK,IAAI,eAAe,EAAE,CAAC,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACxH,YAAY,EAAE,KAAK,IAAI,gBAAgB,EAAE,MAAM,kBAAkB,CAAA"}
|
package/dist/src/index.js
CHANGED
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export * as Resolve from "./resolve.js";
|
|
15
15
|
export * as Row from "./row.js";
|
|
16
|
+
export * as QuerySql from "./query-sql.js";
|
|
17
|
+
export * as Record from "./record.js";
|
|
18
|
+
export * as Provenance from "./provenance.js";
|
|
16
19
|
export * as Schema from "./schema.js";
|
|
20
|
+
export * as Sensitivity from "./sensitivity.js";
|
|
21
|
+
export { backup, restoreBackup, verifyBackup } from "./backup.js";
|
|
17
22
|
export { open } from "./open.js";
|
|
18
23
|
export { defaultDbPath } from "./store.js";
|
|
19
24
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter-entry.d.ts","sourceRoot":"","sources":["../../src/node-adapter-entry.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter-entry.js","sourceRoot":"","sources":["../../src/node-adapter-entry.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.d.ts","sourceRoot":"","sources":["../../src/node-adapter.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAG1E,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,cAAc,CAAA;AAIrD,eAAO,MAAM,iBAAiB,EAAE,OAe/B,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Node.js builtin SQLite implementation of the CAVE adapter contract. */
|
|
2
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
3
|
+
const asNodeDatabase = (db) => db;
|
|
4
|
+
export const nodeSqliteAdapter = {
|
|
5
|
+
name: 'node:sqlite',
|
|
6
|
+
capabilities: {
|
|
7
|
+
transactions: { immediate: true, savepoints: true },
|
|
8
|
+
fullText: 'fts5',
|
|
9
|
+
loadExtension: (db, path) => asNodeDatabase(db).loadExtension(path),
|
|
10
|
+
backup: {
|
|
11
|
+
location: db => asNodeDatabase(db).location(),
|
|
12
|
+
inTransaction: db => asNodeDatabase(db).isTransaction,
|
|
13
|
+
write: (db, destination) => {
|
|
14
|
+
db.prepare('VACUUM INTO ?').run(destination);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
open: (path, options = {}) => new DatabaseSync(path, options),
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=node-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.js","sourceRoot":"","sources":["../../src/node-adapter.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG1C,MAAM,cAAc,GAAG,CAAC,EAAY,EAAgB,EAAE,CAAC,EAAkB,CAAA;AAEzE,MAAM,CAAC,MAAM,iBAAiB,GAAY;IACxC,IAAI,EAAE,aAAa;IACnB,YAAY,EAAE;QACZ,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE;QACnD,QAAQ,EAAE,MAAM;QAChB,aAAa,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC;QACnE,MAAM,EAAE;YACN,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;YAC7C,aAAa,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,aAAa;YACrD,KAAK,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE;gBACzB,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YAC9C,CAAC;SACF;KACF;IACD,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;CAC9D,CAAA"}
|