@descryy/core 0.1.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/LICENSE +21 -0
- package/dist/capabilities/index.d.ts +3 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +2 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/capabilities/preconditions.d.ts +99 -0
- package/dist/capabilities/preconditions.d.ts.map +1 -0
- package/dist/capabilities/preconditions.js +94 -0
- package/dist/capabilities/preconditions.js.map +1 -0
- package/dist/contracts/engine.d.ts +90 -0
- package/dist/contracts/engine.d.ts.map +1 -0
- package/dist/contracts/engine.js +291 -0
- package/dist/contracts/engine.js.map +1 -0
- package/dist/contracts/index.d.ts +9 -0
- package/dist/contracts/index.d.ts.map +1 -0
- package/dist/contracts/index.js +5 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/orphans.d.ts +96 -0
- package/dist/contracts/orphans.d.ts.map +1 -0
- package/dist/contracts/orphans.js +241 -0
- package/dist/contracts/orphans.js.map +1 -0
- package/dist/contracts/paths.d.ts +132 -0
- package/dist/contracts/paths.d.ts.map +1 -0
- package/dist/contracts/paths.js +245 -0
- package/dist/contracts/paths.js.map +1 -0
- package/dist/contracts/shapes.d.ts +99 -0
- package/dist/contracts/shapes.d.ts.map +1 -0
- package/dist/contracts/shapes.js +196 -0
- package/dist/contracts/shapes.js.map +1 -0
- package/dist/governance/budget.d.ts +89 -0
- package/dist/governance/budget.d.ts.map +1 -0
- package/dist/governance/budget.js +101 -0
- package/dist/governance/budget.js.map +1 -0
- package/dist/governance/candidate-boundary.d.ts +49 -0
- package/dist/governance/candidate-boundary.d.ts.map +1 -0
- package/dist/governance/candidate-boundary.js +51 -0
- package/dist/governance/candidate-boundary.js.map +1 -0
- package/dist/governance/escalation.d.ts +63 -0
- package/dist/governance/escalation.d.ts.map +1 -0
- package/dist/governance/escalation.js +72 -0
- package/dist/governance/escalation.js.map +1 -0
- package/dist/governance/fact-boundary.d.ts +77 -0
- package/dist/governance/fact-boundary.d.ts.map +1 -0
- package/dist/governance/fact-boundary.js +91 -0
- package/dist/governance/fact-boundary.js.map +1 -0
- package/dist/governance/finding-funnel.d.ts +109 -0
- package/dist/governance/finding-funnel.d.ts.map +1 -0
- package/dist/governance/finding-funnel.js +137 -0
- package/dist/governance/finding-funnel.js.map +1 -0
- package/dist/governance/index.d.ts +11 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +6 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/graph/build.d.ts +127 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +0 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/cross-language.d.ts +70 -0
- package/dist/graph/cross-language.d.ts.map +1 -0
- package/dist/graph/cross-language.js +104 -0
- package/dist/graph/cross-language.js.map +1 -0
- package/dist/graph/index.d.ts +11 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +6 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/merge.d.ts +95 -0
- package/dist/graph/merge.d.ts.map +1 -0
- package/dist/graph/merge.js +131 -0
- package/dist/graph/merge.js.map +1 -0
- package/dist/graph/persist.d.ts +42 -0
- package/dist/graph/persist.d.ts.map +1 -0
- package/dist/graph/persist.js +52 -0
- package/dist/graph/persist.js.map +1 -0
- package/dist/graph/runtime-confirmation.d.ts +169 -0
- package/dist/graph/runtime-confirmation.d.ts.map +1 -0
- package/dist/graph/runtime-confirmation.js +318 -0
- package/dist/graph/runtime-confirmation.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/ledger/index.d.ts +5 -0
- package/dist/ledger/index.d.ts.map +1 -0
- package/dist/ledger/index.js +3 -0
- package/dist/ledger/index.js.map +1 -0
- package/dist/ledger/mint.d.ts +81 -0
- package/dist/ledger/mint.d.ts.map +1 -0
- package/dist/ledger/mint.js +138 -0
- package/dist/ledger/mint.js.map +1 -0
- package/dist/ledger/resolve.d.ts +124 -0
- package/dist/ledger/resolve.d.ts.map +1 -0
- package/dist/ledger/resolve.js +290 -0
- package/dist/ledger/resolve.js.map +1 -0
- package/dist/multipr/fingerprint.d.ts +56 -0
- package/dist/multipr/fingerprint.d.ts.map +1 -0
- package/dist/multipr/fingerprint.js +169 -0
- package/dist/multipr/fingerprint.js.map +1 -0
- package/dist/multipr/hidden-dependency.d.ts +120 -0
- package/dist/multipr/hidden-dependency.d.ts.map +1 -0
- package/dist/multipr/hidden-dependency.js +185 -0
- package/dist/multipr/hidden-dependency.js.map +1 -0
- package/dist/multipr/index.d.ts +14 -0
- package/dist/multipr/index.d.ts.map +1 -0
- package/dist/multipr/index.js +8 -0
- package/dist/multipr/index.js.map +1 -0
- package/dist/multipr/mechanical.d.ts +239 -0
- package/dist/multipr/mechanical.d.ts.map +1 -0
- package/dist/multipr/mechanical.js +333 -0
- package/dist/multipr/mechanical.js.map +1 -0
- package/dist/multipr/migration-heads.d.ts +160 -0
- package/dist/multipr/migration-heads.d.ts.map +1 -0
- package/dist/multipr/migration-heads.js +212 -0
- package/dist/multipr/migration-heads.js.map +1 -0
- package/dist/multipr/overlap.d.ts +186 -0
- package/dist/multipr/overlap.d.ts.map +1 -0
- package/dist/multipr/overlap.js +254 -0
- package/dist/multipr/overlap.js.map +1 -0
- package/dist/multipr/scope-store.d.ts +105 -0
- package/dist/multipr/scope-store.d.ts.map +1 -0
- package/dist/multipr/scope-store.js +182 -0
- package/dist/multipr/scope-store.js.map +1 -0
- package/dist/multipr/superseded.d.ts +133 -0
- package/dist/multipr/superseded.d.ts.map +1 -0
- package/dist/multipr/superseded.js +128 -0
- package/dist/multipr/superseded.js.map +1 -0
- package/dist/query/confirmed-facts.d.ts +56 -0
- package/dist/query/confirmed-facts.d.ts.map +1 -0
- package/dist/query/confirmed-facts.js +64 -0
- package/dist/query/confirmed-facts.js.map +1 -0
- package/dist/query/declared-value-closure.d.ts +126 -0
- package/dist/query/declared-value-closure.d.ts.map +1 -0
- package/dist/query/declared-value-closure.js +156 -0
- package/dist/query/declared-value-closure.js.map +1 -0
- package/dist/query/index.d.ts +28 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +15 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/memory.d.ts +20 -0
- package/dist/query/memory.d.ts.map +1 -0
- package/dist/query/memory.js +55 -0
- package/dist/query/memory.js.map +1 -0
- package/dist/query/provider.d.ts +127 -0
- package/dist/query/provider.d.ts.map +1 -0
- package/dist/query/provider.js +54 -0
- package/dist/query/provider.js.map +1 -0
- package/dist/query/queries.d.ts +119 -0
- package/dist/query/queries.d.ts.map +1 -0
- package/dist/query/queries.js +267 -0
- package/dist/query/queries.js.map +1 -0
- package/dist/query/refusal-fetch.d.ts +114 -0
- package/dist/query/refusal-fetch.d.ts.map +1 -0
- package/dist/query/refusal-fetch.js +200 -0
- package/dist/query/refusal-fetch.js.map +1 -0
- package/dist/query/refusal-questions.d.ts +123 -0
- package/dist/query/refusal-questions.d.ts.map +1 -0
- package/dist/query/refusal-questions.js +122 -0
- package/dist/query/refusal-questions.js.map +1 -0
- package/dist/query/root-cause-score.d.ts +218 -0
- package/dist/query/root-cause-score.d.ts.map +1 -0
- package/dist/query/root-cause-score.js +251 -0
- package/dist/query/root-cause-score.js.map +1 -0
- package/dist/query/row-closure-picture.d.ts +108 -0
- package/dist/query/row-closure-picture.d.ts.map +1 -0
- package/dist/query/row-closure-picture.js +131 -0
- package/dist/query/row-closure-picture.js.map +1 -0
- package/dist/query/similar-incidents.d.ts +76 -0
- package/dist/query/similar-incidents.d.ts.map +1 -0
- package/dist/query/similar-incidents.js +169 -0
- package/dist/query/similar-incidents.js.map +1 -0
- package/dist/query/sqlite.d.ts +13 -0
- package/dist/query/sqlite.d.ts.map +1 -0
- package/dist/query/sqlite.js +54 -0
- package/dist/query/sqlite.js.map +1 -0
- package/dist/query/traverse.d.ts +110 -0
- package/dist/query/traverse.d.ts.map +1 -0
- package/dist/query/traverse.js +0 -0
- package/dist/query/traverse.js.map +1 -0
- package/dist/query/unresolved.d.ts +195 -0
- package/dist/query/unresolved.d.ts.map +1 -0
- package/dist/query/unresolved.js +225 -0
- package/dist/query/unresolved.js.map +1 -0
- package/dist/query/verification-status.d.ts +134 -0
- package/dist/query/verification-status.d.ts.map +1 -0
- package/dist/query/verification-status.js +163 -0
- package/dist/query/verification-status.js.map +1 -0
- package/dist/recording/index.d.ts +26 -0
- package/dist/recording/index.d.ts.map +1 -0
- package/dist/recording/index.js +30 -0
- package/dist/recording/index.js.map +1 -0
- package/dist/recording/migrate.d.ts +22 -0
- package/dist/recording/migrate.d.ts.map +1 -0
- package/dist/recording/migrate.js +51 -0
- package/dist/recording/migrate.js.map +1 -0
- package/dist/recording/reader.d.ts +27 -0
- package/dist/recording/reader.d.ts.map +1 -0
- package/dist/recording/reader.js +55 -0
- package/dist/recording/reader.js.map +1 -0
- package/dist/recording/redact.d.ts +63 -0
- package/dist/recording/redact.d.ts.map +1 -0
- package/dist/recording/redact.js +98 -0
- package/dist/recording/redact.js.map +1 -0
- package/dist/recording/schema.d.ts +41 -0
- package/dist/recording/schema.d.ts.map +1 -0
- package/dist/recording/schema.js +104 -0
- package/dist/recording/schema.js.map +1 -0
- package/dist/recording/writer.d.ts +120 -0
- package/dist/recording/writer.d.ts.map +1 -0
- package/dist/recording/writer.js +81 -0
- package/dist/recording/writer.js.map +1 -0
- package/dist/scoping/fanout.d.ts +86 -0
- package/dist/scoping/fanout.d.ts.map +1 -0
- package/dist/scoping/fanout.js +95 -0
- package/dist/scoping/fanout.js.map +1 -0
- package/dist/scoping/index.d.ts +10 -0
- package/dist/scoping/index.d.ts.map +1 -0
- package/dist/scoping/index.js +6 -0
- package/dist/scoping/index.js.map +1 -0
- package/dist/scoping/score.d.ts +83 -0
- package/dist/scoping/score.d.ts.map +1 -0
- package/dist/scoping/score.js +125 -0
- package/dist/scoping/score.js.map +1 -0
- package/dist/scoping/tiers.d.ts +32 -0
- package/dist/scoping/tiers.d.ts.map +1 -0
- package/dist/scoping/tiers.js +35 -0
- package/dist/scoping/tiers.js.map +1 -0
- package/dist/scoping/traverse.d.ts +60 -0
- package/dist/scoping/traverse.d.ts.map +1 -0
- package/dist/scoping/traverse.js +172 -0
- package/dist/scoping/traverse.js.map +1 -0
- package/dist/scoping/weights.d.ts +97 -0
- package/dist/scoping/weights.d.ts.map +1 -0
- package/dist/scoping/weights.js +167 -0
- package/dist/scoping/weights.js.map +1 -0
- package/dist/sources/git/diff.d.ts +53 -0
- package/dist/sources/git/diff.d.ts.map +1 -0
- package/dist/sources/git/diff.js +140 -0
- package/dist/sources/git/diff.js.map +1 -0
- package/dist/sources/git/env.d.ts +2 -0
- package/dist/sources/git/env.d.ts.map +1 -0
- package/dist/sources/git/env.js +21 -0
- package/dist/sources/git/env.js.map +1 -0
- package/dist/sources/git/history.d.ts +140 -0
- package/dist/sources/git/history.d.ts.map +1 -0
- package/dist/sources/git/history.js +314 -0
- package/dist/sources/git/history.js.map +1 -0
- package/dist/sources/git/index.d.ts +7 -0
- package/dist/sources/git/index.d.ts.map +1 -0
- package/dist/sources/git/index.js +4 -0
- package/dist/sources/git/index.js.map +1 -0
- package/dist/sources/git/source.d.ts +95 -0
- package/dist/sources/git/source.d.ts.map +1 -0
- package/dist/sources/git/source.js +0 -0
- package/dist/sources/git/source.js.map +1 -0
- package/dist/sources/migrations/dialects.d.ts +59 -0
- package/dist/sources/migrations/dialects.d.ts.map +1 -0
- package/dist/sources/migrations/dialects.js +84 -0
- package/dist/sources/migrations/dialects.js.map +1 -0
- package/dist/sources/migrations/index.d.ts +3 -0
- package/dist/sources/migrations/index.d.ts.map +1 -0
- package/dist/sources/migrations/index.js +2 -0
- package/dist/sources/migrations/index.js.map +1 -0
- package/dist/sources/migrations/read.d.ts +113 -0
- package/dist/sources/migrations/read.d.ts.map +1 -0
- package/dist/sources/migrations/read.js +270 -0
- package/dist/sources/migrations/read.js.map +1 -0
- package/dist/sources/workspace/index.d.ts +3 -0
- package/dist/sources/workspace/index.d.ts.map +1 -0
- package/dist/sources/workspace/index.js +2 -0
- package/dist/sources/workspace/index.js.map +1 -0
- package/dist/sources/workspace/workspace.d.ts +64 -0
- package/dist/sources/workspace/workspace.d.ts.map +1 -0
- package/dist/sources/workspace/workspace.js +294 -0
- package/dist/sources/workspace/workspace.js.map +1 -0
- package/dist/store/driver/driver.d.ts +82 -0
- package/dist/store/driver/driver.d.ts.map +1 -0
- package/dist/store/driver/driver.js +31 -0
- package/dist/store/driver/driver.js.map +1 -0
- package/dist/store/driver/node-sqlite.d.ts +28 -0
- package/dist/store/driver/node-sqlite.d.ts.map +1 -0
- package/dist/store/driver/node-sqlite.js +188 -0
- package/dist/store/driver/node-sqlite.js.map +1 -0
- package/dist/store/index.d.ts +33 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +46 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/migrate.d.ts +68 -0
- package/dist/store/migrate.d.ts.map +1 -0
- package/dist/store/migrate.js +140 -0
- package/dist/store/migrate.js.map +1 -0
- package/dist/store/reader.d.ts +127 -0
- package/dist/store/reader.d.ts.map +1 -0
- package/dist/store/reader.js +269 -0
- package/dist/store/reader.js.map +1 -0
- package/dist/store/schema.d.ts +87 -0
- package/dist/store/schema.d.ts.map +1 -0
- package/dist/store/schema.js +322 -0
- package/dist/store/schema.js.map +1 -0
- package/dist/store/writer.d.ts +116 -0
- package/dist/store/writer.d.ts.map +1 -0
- package/dist/store/writer.js +279 -0
- package/dist/store/writer.js.map +1 -0
- package/dist/tiers/certify.d.ts +375 -0
- package/dist/tiers/certify.d.ts.map +1 -0
- package/dist/tiers/certify.js +434 -0
- package/dist/tiers/certify.js.map +1 -0
- package/dist/tiers/index.d.ts +5 -0
- package/dist/tiers/index.d.ts.map +1 -0
- package/dist/tiers/index.js +3 -0
- package/dist/tiers/index.js.map +1 -0
- package/dist/tiers/ladder.d.ts +73 -0
- package/dist/tiers/ladder.d.ts.map +1 -0
- package/dist/tiers/ladder.js +197 -0
- package/dist/tiers/ladder.js.map +1 -0
- package/dist/validation/config-graph.d.ts +104 -0
- package/dist/validation/config-graph.d.ts.map +1 -0
- package/dist/validation/config-graph.js +205 -0
- package/dist/validation/config-graph.js.map +1 -0
- package/dist/validation/env.d.ts +243 -0
- package/dist/validation/env.d.ts.map +1 -0
- package/dist/validation/env.js +447 -0
- package/dist/validation/env.js.map +1 -0
- package/dist/validation/index.d.ts +16 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +9 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/join-substitution.d.ts +186 -0
- package/dist/validation/join-substitution.d.ts.map +1 -0
- package/dist/validation/join-substitution.js +191 -0
- package/dist/validation/join-substitution.js.map +1 -0
- package/dist/validation/migrations.d.ts +133 -0
- package/dist/validation/migrations.d.ts.map +1 -0
- package/dist/validation/migrations.js +315 -0
- package/dist/validation/migrations.js.map +1 -0
- package/dist/validation/nodes.d.ts +32 -0
- package/dist/validation/nodes.d.ts.map +1 -0
- package/dist/validation/nodes.js +45 -0
- package/dist/validation/nodes.js.map +1 -0
- package/dist/validation/rollback.d.ts +124 -0
- package/dist/validation/rollback.d.ts.map +1 -0
- package/dist/validation/rollback.js +302 -0
- package/dist/validation/rollback.js.map +1 -0
- package/dist/validation/route-drift.d.ts +108 -0
- package/dist/validation/route-drift.d.ts.map +1 -0
- package/dist/validation/route-drift.js +103 -0
- package/dist/validation/route-drift.js.map +1 -0
- package/dist/validation/sources.d.ts +153 -0
- package/dist/validation/sources.d.ts.map +1 -0
- package/dist/validation/sources.js +409 -0
- package/dist/validation/sources.js.map +1 -0
- package/dist/worker/index.d.ts +5 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +3 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/pool.d.ts +73 -0
- package/dist/worker/pool.d.ts.map +1 -0
- package/dist/worker/pool.js +203 -0
- package/dist/worker/pool.js.map +1 -0
- package/dist/worker/protocol.d.ts +91 -0
- package/dist/worker/protocol.d.ts.map +1 -0
- package/dist/worker/protocol.js +19 -0
- package/dist/worker/protocol.js.map +1 -0
- package/dist/worker/traversal.worker.d.ts +25 -0
- package/dist/worker/traversal.worker.d.ts.map +1 -0
- package/dist/worker/traversal.worker.js +124 -0
- package/dist/worker/traversal.worker.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workspace declaration — DEC-075 §7.
|
|
3
|
+
*
|
|
4
|
+
* A multi-repo or monorepo run needs two facts a graph cannot supply on its
|
|
5
|
+
* own: which package roots exist, and which of them are meant to talk to
|
|
6
|
+
* each other. `descry.json` at the repository root is where both are
|
|
7
|
+
* declared, with an optional `descry` key inside `package.json` or
|
|
8
|
+
* `pyproject.toml` for a project that would rather not add a file. The root
|
|
9
|
+
* file wins where more than one location is present — it is the one
|
|
10
|
+
* location that works for a locally installed tool with no hosted backend,
|
|
11
|
+
* and it is greppable.
|
|
12
|
+
*
|
|
13
|
+
* ## Nx, Turborepo, pnpm and npm workspaces are read for the package LIST,
|
|
14
|
+
* ## and never for a pairing
|
|
15
|
+
*
|
|
16
|
+
* Enumerating packages from a workspace manifest is reading a declaration —
|
|
17
|
+
* the manifest states which directories are packages, so there is nothing to
|
|
18
|
+
* infer. Deciding that `apps/web` talks to `apps/api` is a name inference,
|
|
19
|
+
* and the correct mechanism already exists one layer up: a pairing is either
|
|
20
|
+
* declared here, in `descry.json`, or it falls out of a real
|
|
21
|
+
* `USES_API`/`SERVES_API` join at R3. This module supplies the declared half
|
|
22
|
+
* only; it does not guess a pairing from two directory names that sound
|
|
23
|
+
* related, for the same reason a Python `Company` must not join a
|
|
24
|
+
* TypeScript `Company` on a shared word.
|
|
25
|
+
*
|
|
26
|
+
* ## Precision over recall in the glob reader
|
|
27
|
+
*
|
|
28
|
+
* `workspaces` in `package.json` and `packages:` in `pnpm-workspace.yaml`
|
|
29
|
+
* hold globs, not paths. Only the one shape actually used across real
|
|
30
|
+
* monorepos in this project's own reference set — `dir/*`, one segment of
|
|
31
|
+
* wildcard at the end — is expanded, by listing `dir`'s subdirectories that
|
|
32
|
+
* themselves contain a `package.json`. A more elaborate glob (`**`, a
|
|
33
|
+
* mid-path wildcard, a negation) is left unexpanded and disclosed on
|
|
34
|
+
* `unexpandedGlobs` rather than approximated — an approximated package list
|
|
35
|
+
* silently mis-scopes every check that follows it.
|
|
36
|
+
*/
|
|
37
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
38
|
+
import { join } from "node:path";
|
|
39
|
+
const toForwardSlash = (p) => p.replace(/\\/g, "/");
|
|
40
|
+
function readJson(path) {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** A pairing entry as `descry.json` or `package.json#descry` may spell it. */
|
|
49
|
+
function readPairings(value) {
|
|
50
|
+
if (!Array.isArray(value))
|
|
51
|
+
return [];
|
|
52
|
+
const pairings = [];
|
|
53
|
+
for (const entry of value) {
|
|
54
|
+
if (entry === null || typeof entry !== "object")
|
|
55
|
+
continue;
|
|
56
|
+
const from = entry.from;
|
|
57
|
+
const to = entry.to;
|
|
58
|
+
if (typeof from === "string" && typeof to === "string")
|
|
59
|
+
pairings.push({ from, to });
|
|
60
|
+
}
|
|
61
|
+
return pairings;
|
|
62
|
+
}
|
|
63
|
+
function readPackages(value) {
|
|
64
|
+
if (!Array.isArray(value))
|
|
65
|
+
return undefined;
|
|
66
|
+
return value.filter((p) => typeof p === "string").map(toForwardSlash);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `[tool.descry]` inside `pyproject.toml`, read narrowly. This is not a TOML
|
|
70
|
+
* parser: it recognises exactly `packages = [...]` and a `pairings` array of
|
|
71
|
+
* inline `{ from = "...", to = "..." }` tables, both on lines belonging to
|
|
72
|
+
* the `[tool.descry]` table, and refuses (returns `undefined`) on anything
|
|
73
|
+
* it is not confident it read correctly — a wrong read here silently
|
|
74
|
+
* mis-scopes a whole run, so guessing is the wrong trade.
|
|
75
|
+
*/
|
|
76
|
+
function readPyprojectDescry(root) {
|
|
77
|
+
const path = join(root, "pyproject.toml");
|
|
78
|
+
if (!existsSync(path))
|
|
79
|
+
return undefined;
|
|
80
|
+
let text;
|
|
81
|
+
try {
|
|
82
|
+
text = readFileSync(path, "utf8");
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const lines = text.split("\n");
|
|
88
|
+
let inTable = false;
|
|
89
|
+
let packages;
|
|
90
|
+
const pairings = [];
|
|
91
|
+
for (const raw of lines) {
|
|
92
|
+
const line = raw.trim();
|
|
93
|
+
if (/^\[.*\]$/.test(line)) {
|
|
94
|
+
inTable = line === "[tool.descry]";
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (!inTable)
|
|
98
|
+
continue;
|
|
99
|
+
const packagesMatch = /^packages\s*=\s*(\[.*\])\s*$/.exec(line);
|
|
100
|
+
const packagesGroup = packagesMatch?.[1];
|
|
101
|
+
if (packagesGroup !== undefined) {
|
|
102
|
+
const arr = tryParseJsonArray(packagesGroup);
|
|
103
|
+
if (arr !== undefined)
|
|
104
|
+
packages = readPackages(arr);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const pairingsMatch = /^pairings\s*=\s*\[(.*)\]\s*$/.exec(line);
|
|
108
|
+
const pairingsGroup = pairingsMatch?.[1];
|
|
109
|
+
if (pairingsGroup !== undefined) {
|
|
110
|
+
// `{ from = "a", to = "b" }, { from = "c", to = "d" }` — TOML inline
|
|
111
|
+
// tables use `=`, JSON uses `:`; translate the narrow shape this
|
|
112
|
+
// reader accepts rather than reaching for a general parser.
|
|
113
|
+
const asJson = `[${pairingsGroup.replace(/(\bfrom\s*=|\bto\s*=)/g, (m) => (m.startsWith("from") ? '"from":' : '"to":'))}]`;
|
|
114
|
+
const arr = tryParseJsonArray(asJson);
|
|
115
|
+
if (arr !== undefined)
|
|
116
|
+
pairings.push(...readPairings(arr));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (packages === undefined && pairings.length === 0)
|
|
120
|
+
return undefined;
|
|
121
|
+
return { packages, pairings };
|
|
122
|
+
}
|
|
123
|
+
function tryParseJsonArray(text) {
|
|
124
|
+
try {
|
|
125
|
+
const parsed = JSON.parse(text.replace(/'/g, '"'));
|
|
126
|
+
return Array.isArray(parsed) ? parsed : undefined;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function readDescryJson(root) {
|
|
133
|
+
const path = join(root, "descry.json");
|
|
134
|
+
if (!existsSync(path))
|
|
135
|
+
return undefined;
|
|
136
|
+
const parsed = readJson(path);
|
|
137
|
+
if (parsed === undefined || typeof parsed !== "object" || parsed === null)
|
|
138
|
+
return undefined;
|
|
139
|
+
const obj = parsed;
|
|
140
|
+
return { packages: readPackages(obj.packages), pairings: readPairings(obj.pairings) };
|
|
141
|
+
}
|
|
142
|
+
function readPackageJsonDescry(root) {
|
|
143
|
+
const path = join(root, "package.json");
|
|
144
|
+
if (!existsSync(path))
|
|
145
|
+
return undefined;
|
|
146
|
+
const parsed = readJson(path);
|
|
147
|
+
if (parsed === undefined || typeof parsed !== "object" || parsed === null)
|
|
148
|
+
return undefined;
|
|
149
|
+
const descry = parsed.descry;
|
|
150
|
+
if (descry === undefined || typeof descry !== "object" || descry === null)
|
|
151
|
+
return undefined;
|
|
152
|
+
const obj = descry;
|
|
153
|
+
return { packages: readPackages(obj.packages), pairings: readPairings(obj.pairings) };
|
|
154
|
+
}
|
|
155
|
+
/** `dir/*` only — the one glob shape this project's own reference monorepos actually use. */
|
|
156
|
+
function expandSingleStarGlob(root, glob) {
|
|
157
|
+
if (!glob.endsWith("/*") || glob.slice(0, -2).includes("*"))
|
|
158
|
+
return { unexpanded: true };
|
|
159
|
+
const dir = glob.slice(0, -2);
|
|
160
|
+
const abs = join(root, dir);
|
|
161
|
+
if (!existsSync(abs) || !statSync(abs).isDirectory())
|
|
162
|
+
return { expanded: [] };
|
|
163
|
+
const expanded = [];
|
|
164
|
+
for (const entry of readdirSync(abs, { withFileTypes: true })) {
|
|
165
|
+
if (!entry.isDirectory())
|
|
166
|
+
continue;
|
|
167
|
+
if (existsSync(join(abs, entry.name, "package.json")))
|
|
168
|
+
expanded.push(toForwardSlash(join(dir, entry.name)));
|
|
169
|
+
}
|
|
170
|
+
return { expanded };
|
|
171
|
+
}
|
|
172
|
+
function readPackageListFromManifests(root) {
|
|
173
|
+
const pkgJsonPath = join(root, "package.json");
|
|
174
|
+
if (existsSync(pkgJsonPath)) {
|
|
175
|
+
const parsed = readJson(pkgJsonPath);
|
|
176
|
+
if (parsed !== undefined && typeof parsed === "object" && parsed !== null) {
|
|
177
|
+
const ws = parsed.workspaces;
|
|
178
|
+
const globs = Array.isArray(ws)
|
|
179
|
+
? ws.filter((g) => typeof g === "string")
|
|
180
|
+
: ws !== null && typeof ws === "object" && Array.isArray(ws.packages)
|
|
181
|
+
? ws.packages.filter((g) => typeof g === "string")
|
|
182
|
+
: undefined;
|
|
183
|
+
if (globs !== undefined) {
|
|
184
|
+
const packages = [];
|
|
185
|
+
const unexpanded = [];
|
|
186
|
+
for (const g of globs) {
|
|
187
|
+
if (!g.includes("*")) {
|
|
188
|
+
packages.push(toForwardSlash(g));
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
const r = expandSingleStarGlob(root, g);
|
|
192
|
+
if ("unexpanded" in r)
|
|
193
|
+
unexpanded.push(g);
|
|
194
|
+
else
|
|
195
|
+
packages.push(...r.expanded);
|
|
196
|
+
}
|
|
197
|
+
return { packages, source: "package.json#workspaces", unexpandedGlobs: unexpanded };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const pnpmPath = join(root, "pnpm-workspace.yaml");
|
|
202
|
+
if (existsSync(pnpmPath)) {
|
|
203
|
+
let text;
|
|
204
|
+
try {
|
|
205
|
+
text = readFileSync(pnpmPath, "utf8");
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
text = "";
|
|
209
|
+
}
|
|
210
|
+
const lines = text.split("\n");
|
|
211
|
+
let inPackages = false;
|
|
212
|
+
const globs = [];
|
|
213
|
+
for (const raw of lines) {
|
|
214
|
+
if (/^packages\s*:\s*$/.test(raw.trim())) {
|
|
215
|
+
inPackages = true;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (inPackages) {
|
|
219
|
+
const m = /^\s*-\s*['"]?([^'"]+?)['"]?\s*$/.exec(raw);
|
|
220
|
+
const glob = m?.[1];
|
|
221
|
+
if (glob !== undefined) {
|
|
222
|
+
globs.push(glob);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (raw.trim() !== "")
|
|
226
|
+
inPackages = false; // a dedented, non-list line ends the block
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const packages = [];
|
|
230
|
+
const unexpanded = [];
|
|
231
|
+
for (const g of globs) {
|
|
232
|
+
if (!g.includes("*")) {
|
|
233
|
+
packages.push(toForwardSlash(g));
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const r = expandSingleStarGlob(root, g);
|
|
237
|
+
if ("unexpanded" in r)
|
|
238
|
+
unexpanded.push(g);
|
|
239
|
+
else
|
|
240
|
+
packages.push(...r.expanded);
|
|
241
|
+
}
|
|
242
|
+
return { packages, source: "pnpm-workspace.yaml", unexpandedGlobs: unexpanded };
|
|
243
|
+
}
|
|
244
|
+
return { packages: [], source: "none", unexpandedGlobs: [] };
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Resolve `root`'s workspace declaration: which packages it holds and which
|
|
248
|
+
* of them are declared as talking to each other. `descry.json` wins over a
|
|
249
|
+
* `package.json#descry` key, which wins over `pyproject.toml`'s
|
|
250
|
+
* `[tool.descry]` table; the first one found is used whole, never merged
|
|
251
|
+
* across locations — a package list assembled from two files is a package
|
|
252
|
+
* list nobody wrote down.
|
|
253
|
+
*/
|
|
254
|
+
export function resolveWorkspace(root) {
|
|
255
|
+
let raw;
|
|
256
|
+
let declarationSource;
|
|
257
|
+
const fromDescryJson = readDescryJson(root);
|
|
258
|
+
if (fromDescryJson !== undefined) {
|
|
259
|
+
raw = fromDescryJson;
|
|
260
|
+
declarationSource = "descry.json";
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const fromPackageJson = readPackageJsonDescry(root);
|
|
264
|
+
if (fromPackageJson !== undefined) {
|
|
265
|
+
raw = fromPackageJson;
|
|
266
|
+
declarationSource = "package.json#descry";
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
const fromPyproject = readPyprojectDescry(root);
|
|
270
|
+
raw = fromPyproject;
|
|
271
|
+
declarationSource = fromPyproject !== undefined ? "pyproject.toml#tool.descry" : "none";
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (raw?.packages !== undefined) {
|
|
275
|
+
return {
|
|
276
|
+
root,
|
|
277
|
+
declarationSource,
|
|
278
|
+
packages: raw.packages,
|
|
279
|
+
packagesSource: "declared",
|
|
280
|
+
pairings: raw.pairings,
|
|
281
|
+
unexpandedGlobs: [],
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
const fromManifests = readPackageListFromManifests(root);
|
|
285
|
+
return {
|
|
286
|
+
root,
|
|
287
|
+
declarationSource,
|
|
288
|
+
packages: fromManifests.packages,
|
|
289
|
+
packagesSource: fromManifests.source,
|
|
290
|
+
pairings: raw?.pairings ?? [],
|
|
291
|
+
unexpandedGlobs: fromManifests.unexpandedGlobs,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../../src/sources/workspace/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SQL driver interface — DEC-018.
|
|
3
|
+
*
|
|
4
|
+
* `node:sqlite` is an experimental API on an LTS runtime: it landed in 22.5 and
|
|
5
|
+
* its surface has moved across 22.x minors. That is an acceptable risk *behind
|
|
6
|
+
* an interface* and an unacceptable one spread through the engine, which is the
|
|
7
|
+
* only reason this file exists. A later swap to `better-sqlite3`, `libsql` or a
|
|
8
|
+
* Postgres-backed driver should be a day's work, and `driver.contract.test.ts`
|
|
9
|
+
* is what makes that estimate real rather than hopeful.
|
|
10
|
+
*
|
|
11
|
+
* Three of the nine methods are NOT thin delegations, verified against Node
|
|
12
|
+
* v22.23.1: `DatabaseSync` has no `transaction`, no `pragma` and no `backup`.
|
|
13
|
+
* Those are better-sqlite3 idioms. They are part of this interface anyway
|
|
14
|
+
* because every engine caller needs them and every driver can implement them —
|
|
15
|
+
* putting them here is what stops `BEGIN`/`COMMIT` string handling leaking into
|
|
16
|
+
* the writer.
|
|
17
|
+
*/
|
|
18
|
+
/** Everything SQLite can bind. Deliberately narrow — no implicit coercion. */
|
|
19
|
+
export type SqlParam = null | number | bigint | string | Uint8Array;
|
|
20
|
+
export interface RunResult {
|
|
21
|
+
readonly changes: number;
|
|
22
|
+
readonly lastInsertRowid: number | bigint;
|
|
23
|
+
}
|
|
24
|
+
export interface SqlStatement<Row = Record<string, unknown>> {
|
|
25
|
+
all(...params: SqlParam[]): Row[];
|
|
26
|
+
get(...params: SqlParam[]): Row | undefined;
|
|
27
|
+
run(...params: SqlParam[]): RunResult;
|
|
28
|
+
/** Streams rows. Use for large result sets so a traversal never materialises a whole table. */
|
|
29
|
+
iterate(...params: SqlParam[]): IterableIterator<Row>;
|
|
30
|
+
}
|
|
31
|
+
export interface OpenOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Write-ahead logging. On by default: the traversal worker holds a read-only
|
|
34
|
+
* handle (the plan's Step 10), and without WAL a writer blocks every reader,
|
|
35
|
+
* which is exactly the stall that breaks streaming-first.
|
|
36
|
+
*
|
|
37
|
+
* Ignored for `:memory:`, where SQLite has no journal to write ahead to.
|
|
38
|
+
*/
|
|
39
|
+
readonly wal?: boolean;
|
|
40
|
+
readonly readOnly?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface DriverVersion {
|
|
43
|
+
/** Which implementation is behind the interface, e.g. `node-sqlite`. */
|
|
44
|
+
readonly driver: string;
|
|
45
|
+
/** The underlying engine version, e.g. `3.51.3`. */
|
|
46
|
+
readonly engine: string;
|
|
47
|
+
}
|
|
48
|
+
export interface SqlDriver {
|
|
49
|
+
open(path: string, options?: OpenOptions): void;
|
|
50
|
+
close(): void;
|
|
51
|
+
exec(sql: string): void;
|
|
52
|
+
prepare<Row = Record<string, unknown>>(sql: string): SqlStatement<Row>;
|
|
53
|
+
/**
|
|
54
|
+
* Run `fn` inside a transaction, committing on return and rolling back on
|
|
55
|
+
* throw. Nesting uses SAVEPOINT, so a nested failure unwinds to its own entry
|
|
56
|
+
* point rather than aborting the outer transaction.
|
|
57
|
+
*
|
|
58
|
+
* Synchronous on purpose. `node:sqlite` is a synchronous API, and an `async`
|
|
59
|
+
* callback here would let unrelated work interleave inside the transaction
|
|
60
|
+
* while still looking atomic.
|
|
61
|
+
*/
|
|
62
|
+
transaction<T>(fn: () => T): T;
|
|
63
|
+
/** `pragma("journal_mode")` reads; `pragma("journal_mode = WAL")` sets. */
|
|
64
|
+
pragma<T = unknown>(statement: string): T | undefined;
|
|
65
|
+
loadExtension(path: string): void;
|
|
66
|
+
backup(destinationPath: string): Promise<void>;
|
|
67
|
+
version(): DriverVersion;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Thrown for driver-layer failures so callers never have to match on engine text.
|
|
71
|
+
*
|
|
72
|
+
* Declared as a field plus a constructor-body assignment rather than a parameter
|
|
73
|
+
* property: parameter properties are not erasable syntax, so Node's type
|
|
74
|
+
* stripping cannot run them (tsconfig `erasableSyntaxOnly`, echoed by the lint).
|
|
75
|
+
*/
|
|
76
|
+
export declare class DriverError extends Error {
|
|
77
|
+
readonly name = "DriverError";
|
|
78
|
+
constructor(message: string, options?: {
|
|
79
|
+
cause?: unknown;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../src/store/driver/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACzD,GAAG,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,EAAE,CAAC;IAClC,GAAG,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,GAAG,SAAS,CAAC;IAC5C,GAAG,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IACtC,+FAA+F;IAC/F,OAAO,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAEvE;;;;;;;;OAQG;IACH,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAE/B,2EAA2E;IAC3E,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;IAEtD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,IAAI,aAAa,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,SAAkB,IAAI,iBAAiB;gBAE3B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAG3D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SQL driver interface — DEC-018.
|
|
3
|
+
*
|
|
4
|
+
* `node:sqlite` is an experimental API on an LTS runtime: it landed in 22.5 and
|
|
5
|
+
* its surface has moved across 22.x minors. That is an acceptable risk *behind
|
|
6
|
+
* an interface* and an unacceptable one spread through the engine, which is the
|
|
7
|
+
* only reason this file exists. A later swap to `better-sqlite3`, `libsql` or a
|
|
8
|
+
* Postgres-backed driver should be a day's work, and `driver.contract.test.ts`
|
|
9
|
+
* is what makes that estimate real rather than hopeful.
|
|
10
|
+
*
|
|
11
|
+
* Three of the nine methods are NOT thin delegations, verified against Node
|
|
12
|
+
* v22.23.1: `DatabaseSync` has no `transaction`, no `pragma` and no `backup`.
|
|
13
|
+
* Those are better-sqlite3 idioms. They are part of this interface anyway
|
|
14
|
+
* because every engine caller needs them and every driver can implement them —
|
|
15
|
+
* putting them here is what stops `BEGIN`/`COMMIT` string handling leaking into
|
|
16
|
+
* the writer.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Thrown for driver-layer failures so callers never have to match on engine text.
|
|
20
|
+
*
|
|
21
|
+
* Declared as a field plus a constructor-body assignment rather than a parameter
|
|
22
|
+
* property: parameter properties are not erasable syntax, so Node's type
|
|
23
|
+
* stripping cannot run them (tsconfig `erasableSyntaxOnly`, echoed by the lint).
|
|
24
|
+
*/
|
|
25
|
+
export class DriverError extends Error {
|
|
26
|
+
name = "DriverError";
|
|
27
|
+
constructor(message, options) {
|
|
28
|
+
super(message, options);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../src/store/driver/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA8DH;;;;;;GAMG;AACH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAClB,IAAI,GAAG,aAAa,CAAC;IAEvC,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `node:sqlite` driver — the only file in the engine that imports it.
|
|
3
|
+
*
|
|
4
|
+
* Two hazards live here and nowhere else, both verified on Node v22.23.1:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Rows come back with a null prototype.** `hasOwnProperty`, `instanceof`
|
|
7
|
+
* and anything walking the prototype chain break on them, and the failure
|
|
8
|
+
* is remote from the cause. Every row is copied into an ordinary object
|
|
9
|
+
* before it leaves this file. DEC-018 states the rule; the contract suite
|
|
10
|
+
* enforces it.
|
|
11
|
+
* 2. **`DatabaseSync` has no `transaction`, `pragma` or `backup`.** Those are
|
|
12
|
+
* better-sqlite3 idioms. They are synthesised below so that no caller ever
|
|
13
|
+
* writes `BEGIN` as a string.
|
|
14
|
+
*/
|
|
15
|
+
import { type DriverVersion, type OpenOptions, type SqlDriver, type SqlStatement } from "./driver.ts";
|
|
16
|
+
export declare class NodeSqliteDriver implements SqlDriver {
|
|
17
|
+
#private;
|
|
18
|
+
open(path: string, options?: OpenOptions): void;
|
|
19
|
+
close(): void;
|
|
20
|
+
exec(sql: string): void;
|
|
21
|
+
prepare<Row = Record<string, unknown>>(sql: string): SqlStatement<Row>;
|
|
22
|
+
transaction<T>(fn: () => T): T;
|
|
23
|
+
pragma<T = unknown>(statement: string): T | undefined;
|
|
24
|
+
loadExtension(path: string): void;
|
|
25
|
+
backup(destinationPath: string): Promise<void>;
|
|
26
|
+
version(): DriverVersion;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=node-sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-sqlite.d.ts","sourceRoot":"","sources":["../../../src/store/driver/node-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,WAAW,EAEhB,KAAK,SAAS,EAEd,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAwCrB,qBAAa,gBAAiB,YAAW,SAAS;;IAUhD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,IAAI;IAsBnD,KAAK,IAAI,IAAI;IAOb,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAQvB,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC;IAQtE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IA0B9B,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAqBrD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgB3B,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQpD,OAAO,IAAI,aAAa;CAKzB"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `node:sqlite` driver — the only file in the engine that imports it.
|
|
3
|
+
*
|
|
4
|
+
* Two hazards live here and nowhere else, both verified on Node v22.23.1:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Rows come back with a null prototype.** `hasOwnProperty`, `instanceof`
|
|
7
|
+
* and anything walking the prototype chain break on them, and the failure
|
|
8
|
+
* is remote from the cause. Every row is copied into an ordinary object
|
|
9
|
+
* before it leaves this file. DEC-018 states the rule; the contract suite
|
|
10
|
+
* enforces it.
|
|
11
|
+
* 2. **`DatabaseSync` has no `transaction`, `pragma` or `backup`.** Those are
|
|
12
|
+
* better-sqlite3 idioms. They are synthesised below so that no caller ever
|
|
13
|
+
* writes `BEGIN` as a string.
|
|
14
|
+
*/
|
|
15
|
+
import { DatabaseSync, backup as sqliteBackup } from "node:sqlite";
|
|
16
|
+
import { DriverError, } from "./driver.js";
|
|
17
|
+
/**
|
|
18
|
+
* Copy a null-prototype row into an ordinary object.
|
|
19
|
+
*
|
|
20
|
+
* Shallow on purpose: SQLite returns flat rows of primitives, so there is no
|
|
21
|
+
* nesting to walk, and a deep clone would silently copy `Uint8Array` blobs.
|
|
22
|
+
*/
|
|
23
|
+
function rehydrate(row) {
|
|
24
|
+
return { ...row };
|
|
25
|
+
}
|
|
26
|
+
class NodeSqliteStatement {
|
|
27
|
+
#statement;
|
|
28
|
+
constructor(statement) {
|
|
29
|
+
this.#statement = statement;
|
|
30
|
+
}
|
|
31
|
+
all(...params) {
|
|
32
|
+
return this.#statement.all(...params).map((r) => rehydrate(r));
|
|
33
|
+
}
|
|
34
|
+
get(...params) {
|
|
35
|
+
const row = this.#statement.get(...params);
|
|
36
|
+
return row === undefined ? undefined : rehydrate(row);
|
|
37
|
+
}
|
|
38
|
+
run(...params) {
|
|
39
|
+
const result = this.#statement.run(...params);
|
|
40
|
+
return { changes: Number(result.changes), lastInsertRowid: result.lastInsertRowid };
|
|
41
|
+
}
|
|
42
|
+
*iterate(...params) {
|
|
43
|
+
for (const row of this.#statement.iterate(...params)) {
|
|
44
|
+
yield rehydrate(row);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export class NodeSqliteDriver {
|
|
49
|
+
#db = null;
|
|
50
|
+
/** SAVEPOINT depth, so nested transactions unwind to their own entry point. */
|
|
51
|
+
#depth = 0;
|
|
52
|
+
#require() {
|
|
53
|
+
if (this.#db === null)
|
|
54
|
+
throw new DriverError("driver is not open");
|
|
55
|
+
return this.#db;
|
|
56
|
+
}
|
|
57
|
+
open(path, options = {}) {
|
|
58
|
+
if (this.#db !== null)
|
|
59
|
+
throw new DriverError("driver is already open");
|
|
60
|
+
try {
|
|
61
|
+
this.#db = new DatabaseSync(path, { readOnly: options.readOnly ?? false });
|
|
62
|
+
}
|
|
63
|
+
catch (cause) {
|
|
64
|
+
throw new DriverError(`could not open database at ${path}`, { cause });
|
|
65
|
+
}
|
|
66
|
+
if (options.readOnly === true)
|
|
67
|
+
return;
|
|
68
|
+
// An in-memory database has no journal to write ahead to; asking for WAL
|
|
69
|
+
// there is silently ignored by SQLite, so skip it rather than pretend.
|
|
70
|
+
if ((options.wal ?? true) && path !== ":memory:") {
|
|
71
|
+
this.pragma("journal_mode = WAL");
|
|
72
|
+
}
|
|
73
|
+
// Without this, a concurrent reader gets SQLITE_BUSY immediately instead of
|
|
74
|
+
// waiting — which surfaces as a flaky failure the moment the traversal
|
|
75
|
+
// worker of Step 10 exists.
|
|
76
|
+
this.pragma("busy_timeout = 5000");
|
|
77
|
+
this.pragma("foreign_keys = ON");
|
|
78
|
+
}
|
|
79
|
+
close() {
|
|
80
|
+
if (this.#db === null)
|
|
81
|
+
return;
|
|
82
|
+
this.#db.close();
|
|
83
|
+
this.#db = null;
|
|
84
|
+
this.#depth = 0;
|
|
85
|
+
}
|
|
86
|
+
exec(sql) {
|
|
87
|
+
try {
|
|
88
|
+
this.#require().exec(sql);
|
|
89
|
+
}
|
|
90
|
+
catch (cause) {
|
|
91
|
+
throw new DriverError(`exec failed: ${firstLine(sql)}`, { cause });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
prepare(sql) {
|
|
95
|
+
try {
|
|
96
|
+
return new NodeSqliteStatement(this.#require().prepare(sql));
|
|
97
|
+
}
|
|
98
|
+
catch (cause) {
|
|
99
|
+
throw new DriverError(`prepare failed: ${firstLine(sql)}`, { cause });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
transaction(fn) {
|
|
103
|
+
const db = this.#require();
|
|
104
|
+
const nested = this.#depth > 0;
|
|
105
|
+
const name = `descry_sp_${this.#depth}`;
|
|
106
|
+
db.exec(nested ? `SAVEPOINT ${name}` : "BEGIN");
|
|
107
|
+
this.#depth += 1;
|
|
108
|
+
try {
|
|
109
|
+
const result = fn();
|
|
110
|
+
db.exec(nested ? `RELEASE ${name}` : "COMMIT");
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
// If the rollback itself fails the connection is unusable; surfacing the
|
|
115
|
+
// original error is still the right call, because the rollback failure is
|
|
116
|
+
// a consequence of it rather than an independent fact.
|
|
117
|
+
try {
|
|
118
|
+
db.exec(nested ? `ROLLBACK TO ${name}; RELEASE ${name}` : "ROLLBACK");
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
/* deliberately swallowed — see above */
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
this.#depth -= 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
pragma(statement) {
|
|
130
|
+
const db = this.#require();
|
|
131
|
+
const sql = `PRAGMA ${statement}`;
|
|
132
|
+
// A setting pragma returns no rows; a reading one returns exactly one.
|
|
133
|
+
// `prepare().get()` covers both, but SQLite rejects some setting pragmas
|
|
134
|
+
// through the statement API, so fall back to exec.
|
|
135
|
+
try {
|
|
136
|
+
const row = db.prepare(sql).get();
|
|
137
|
+
if (row === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
const values = Object.values(rehydrate(row));
|
|
140
|
+
return values[0];
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
try {
|
|
144
|
+
db.exec(sql);
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
catch (cause) {
|
|
148
|
+
throw new DriverError(`pragma failed: ${statement}`, { cause });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
loadExtension(path) {
|
|
153
|
+
const db = this.#require();
|
|
154
|
+
try {
|
|
155
|
+
db.enableLoadExtension(true);
|
|
156
|
+
db.loadExtension(path);
|
|
157
|
+
}
|
|
158
|
+
catch (cause) {
|
|
159
|
+
throw new DriverError(`could not load extension ${path}`, { cause });
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
try {
|
|
163
|
+
db.enableLoadExtension(false);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
/* the handle is already unusable if this throws */
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async backup(destinationPath) {
|
|
171
|
+
try {
|
|
172
|
+
await sqliteBackup(this.#require(), destinationPath);
|
|
173
|
+
}
|
|
174
|
+
catch (cause) {
|
|
175
|
+
throw new DriverError(`backup to ${destinationPath} failed`, { cause });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
version() {
|
|
179
|
+
const row = this.#require().prepare("SELECT sqlite_version() AS v").get();
|
|
180
|
+
const engine = rehydrate(row).v;
|
|
181
|
+
return { driver: "node-sqlite", engine: typeof engine === "string" ? engine : "unknown" };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function firstLine(sql) {
|
|
185
|
+
const line = sql.trim().split("\n", 1)[0] ?? "";
|
|
186
|
+
return line.length > 120 ? `${line.slice(0, 117)}...` : line;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=node-sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-sqlite.js","sourceRoot":"","sources":["../../../src/store/driver/node-sqlite.ts"],"names":[],"mappings":"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"}
|