@nicia-ai/typegraph 0.65.0 → 0.66.1
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 +33 -0
- package/dist/{atomic-mutation-program-BznZQ06C.d.ts → atomic-mutation-program-BhP75Qn0.d.ts} +1 -1
- package/dist/{atomic-mutation-program-Bfu5z-je.d.cts → atomic-mutation-program-DMdmc4s0.d.cts} +1 -1
- package/dist/backend/drizzle/engine/index.cjs +13 -13
- package/dist/backend/drizzle/engine/index.d.cts +9 -9
- package/dist/backend/drizzle/engine/index.d.ts +9 -9
- package/dist/backend/drizzle/engine/index.js +8 -8
- package/dist/backend/drizzle/indexes.d.cts +1 -1
- package/dist/backend/drizzle/indexes.d.ts +1 -1
- package/dist/backend/index.cjs +91 -91
- package/dist/backend/index.d.cts +7 -7
- package/dist/backend/index.d.ts +7 -7
- package/dist/backend/index.js +8 -8
- package/dist/backend/postgres/index.cjs +23 -23
- package/dist/backend/postgres/index.d.cts +8 -8
- package/dist/backend/postgres/index.d.ts +8 -8
- package/dist/backend/postgres/index.js +8 -8
- package/dist/backend/postgres/pglite-store.cjs +1 -1
- package/dist/backend/postgres/pglite-store.d.cts +6 -6
- package/dist/backend/postgres/pglite-store.d.ts +6 -6
- package/dist/backend/postgres/pglite-store.js +1 -1
- package/dist/backend/postgres/pglite.cjs +10 -10
- package/dist/backend/postgres/pglite.d.cts +3 -3
- package/dist/backend/postgres/pglite.d.ts +3 -3
- package/dist/backend/postgres/pglite.js +9 -9
- package/dist/backend/sqlite/index.cjs +21 -21
- package/dist/backend/sqlite/index.d.cts +7 -7
- package/dist/backend/sqlite/index.d.ts +7 -7
- package/dist/backend/sqlite/index.js +8 -8
- package/dist/backend/sqlite/libsql.cjs +14 -14
- package/dist/backend/sqlite/libsql.d.cts +3 -3
- package/dist/backend/sqlite/libsql.d.ts +3 -3
- package/dist/backend/sqlite/libsql.js +8 -8
- package/dist/backend/sqlite/local-store.cjs +1 -1
- package/dist/backend/sqlite/local-store.d.cts +6 -6
- package/dist/backend/sqlite/local-store.d.ts +6 -6
- package/dist/backend/sqlite/local-store.js +1 -1
- package/dist/backend/sqlite/local.cjs +10 -10
- package/dist/backend/sqlite/local.d.cts +3 -3
- package/dist/backend/sqlite/local.d.ts +3 -3
- package/dist/backend/sqlite/local.js +9 -9
- package/dist/{chunk-PFXNQFFY.js → chunk-2DJKHZQ4.js} +75 -8
- package/dist/chunk-2DJKHZQ4.js.map +1 -0
- package/dist/{chunk-337ONI2I.js → chunk-3SUZXB5X.js} +146 -80
- package/dist/chunk-3SUZXB5X.js.map +1 -0
- package/dist/{chunk-4VTCIEK3.js → chunk-4TQOIBWH.js} +3 -3
- package/dist/{chunk-4VTCIEK3.js.map → chunk-4TQOIBWH.js.map} +1 -1
- package/dist/{chunk-JRWKRBI5.cjs → chunk-5JOCIMQ3.cjs} +6 -6
- package/dist/{chunk-JRWKRBI5.cjs.map → chunk-5JOCIMQ3.cjs.map} +1 -1
- package/dist/{chunk-BWQA3POT.cjs → chunk-6B3LQUYG.cjs} +206 -138
- package/dist/chunk-6B3LQUYG.cjs.map +1 -0
- package/dist/{chunk-RQPCUHIH.js → chunk-6ECNYQDW.js} +3 -3
- package/dist/{chunk-RQPCUHIH.js.map → chunk-6ECNYQDW.js.map} +1 -1
- package/dist/{chunk-OLB75LRQ.js → chunk-6GKKAQMW.js} +5 -5
- package/dist/{chunk-OLB75LRQ.js.map → chunk-6GKKAQMW.js.map} +1 -1
- package/dist/{chunk-OC5ROP7V.cjs → chunk-6JRVV2SS.cjs} +8 -2
- package/dist/chunk-6JRVV2SS.cjs.map +1 -0
- package/dist/{chunk-DSX3P4S5.cjs → chunk-76OB5RSH.cjs} +6 -6
- package/dist/{chunk-DSX3P4S5.cjs.map → chunk-76OB5RSH.cjs.map} +1 -1
- package/dist/{chunk-DHRLOQLQ.cjs → chunk-7LQTDGV5.cjs} +11 -11
- package/dist/{chunk-DHRLOQLQ.cjs.map → chunk-7LQTDGV5.cjs.map} +1 -1
- package/dist/{chunk-Q25QYSOH.js → chunk-7YJHUY4T.js} +9 -9
- package/dist/{chunk-Q25QYSOH.js.map → chunk-7YJHUY4T.js.map} +1 -1
- package/dist/{chunk-JERQGJKG.cjs → chunk-ANMCKLZQ.cjs} +18 -18
- package/dist/{chunk-JERQGJKG.cjs.map → chunk-ANMCKLZQ.cjs.map} +1 -1
- package/dist/{chunk-BBOMNH44.js → chunk-BABP4D5B.js} +3 -3
- package/dist/{chunk-BBOMNH44.js.map → chunk-BABP4D5B.js.map} +1 -1
- package/dist/{chunk-EVGZ2TRQ.js → chunk-BE75G3M5.js} +3 -3
- package/dist/{chunk-EVGZ2TRQ.js.map → chunk-BE75G3M5.js.map} +1 -1
- package/dist/{chunk-FXGZT3WO.cjs → chunk-BX42F7IJ.cjs} +41 -41
- package/dist/{chunk-FXGZT3WO.cjs.map → chunk-BX42F7IJ.cjs.map} +1 -1
- package/dist/{chunk-G6T23JU7.js → chunk-CDKNGCE7.js} +3 -3
- package/dist/{chunk-G6T23JU7.js.map → chunk-CDKNGCE7.js.map} +1 -1
- package/dist/{chunk-BNTJ5YFO.cjs → chunk-EACDHXJL.cjs} +4 -4
- package/dist/{chunk-BNTJ5YFO.cjs.map → chunk-EACDHXJL.cjs.map} +1 -1
- package/dist/{chunk-SNDJUTMB.cjs → chunk-EBQX7MYL.cjs} +72 -72
- package/dist/{chunk-SNDJUTMB.cjs.map → chunk-EBQX7MYL.cjs.map} +1 -1
- package/dist/{chunk-GKSAEUX6.js → chunk-FXOFJ4FS.js} +7 -7
- package/dist/{chunk-GKSAEUX6.js.map → chunk-FXOFJ4FS.js.map} +1 -1
- package/dist/{chunk-ZOWRACZQ.cjs → chunk-G7OKJDMG.cjs} +5 -5
- package/dist/{chunk-ZOWRACZQ.cjs.map → chunk-G7OKJDMG.cjs.map} +1 -1
- package/dist/{chunk-MKJPBSID.cjs → chunk-I7SBZJI2.cjs} +4 -4
- package/dist/{chunk-MKJPBSID.cjs.map → chunk-I7SBZJI2.cjs.map} +1 -1
- package/dist/{chunk-H346QK3V.cjs → chunk-K7YACILO.cjs} +9 -9
- package/dist/{chunk-H346QK3V.cjs.map → chunk-K7YACILO.cjs.map} +1 -1
- package/dist/{chunk-3KWF25MF.cjs → chunk-MN325MG4.cjs} +313 -246
- package/dist/chunk-MN325MG4.cjs.map +1 -0
- package/dist/{chunk-KDNRACRG.cjs → chunk-MRUOOAIQ.cjs} +4 -4
- package/dist/{chunk-KDNRACRG.cjs.map → chunk-MRUOOAIQ.cjs.map} +1 -1
- package/dist/{chunk-HTSJTWUT.js → chunk-OF63ZHSD.js} +4 -4
- package/dist/{chunk-HTSJTWUT.js.map → chunk-OF63ZHSD.js.map} +1 -1
- package/dist/{chunk-NGA3THGU.cjs → chunk-QR7W37HG.cjs} +14 -14
- package/dist/{chunk-NGA3THGU.cjs.map → chunk-QR7W37HG.cjs.map} +1 -1
- package/dist/{chunk-QFEO4M5W.js → chunk-RTPMG6LQ.js} +11 -11
- package/dist/{chunk-QFEO4M5W.js.map → chunk-RTPMG6LQ.js.map} +1 -1
- package/dist/{chunk-PFD4NUYV.js → chunk-SSDHR2C2.js} +3 -3
- package/dist/{chunk-PFD4NUYV.js.map → chunk-SSDHR2C2.js.map} +1 -1
- package/dist/{chunk-THK3SCQA.js → chunk-SYXTWPX6.js} +5 -5
- package/dist/{chunk-THK3SCQA.js.map → chunk-SYXTWPX6.js.map} +1 -1
- package/dist/{chunk-XSLQYGNR.cjs → chunk-T3VU3YRQ.cjs} +69 -69
- package/dist/{chunk-XSLQYGNR.cjs.map → chunk-T3VU3YRQ.cjs.map} +1 -1
- package/dist/{chunk-MIBWA6HX.js → chunk-TR7QTODF.js} +213 -33
- package/dist/chunk-TR7QTODF.js.map +1 -0
- package/dist/{chunk-AD3NLSV5.js → chunk-TU22BFMP.js} +8 -2
- package/dist/chunk-TU22BFMP.js.map +1 -0
- package/dist/{chunk-WTMSUIRO.js → chunk-UFKYMQJ5.js} +3 -3
- package/dist/{chunk-WTMSUIRO.js.map → chunk-UFKYMQJ5.js.map} +1 -1
- package/dist/{chunk-35LDKSMM.cjs → chunk-VNJMM2QQ.cjs} +30 -30
- package/dist/{chunk-35LDKSMM.cjs.map → chunk-VNJMM2QQ.cjs.map} +1 -1
- package/dist/{chunk-53ZEBIMD.js → chunk-WB55URNM.js} +6 -6
- package/dist/{chunk-53ZEBIMD.js.map → chunk-WB55URNM.js.map} +1 -1
- package/dist/{chunk-L2GBVYRU.cjs → chunk-WWSYGZED.cjs} +11 -11
- package/dist/{chunk-L2GBVYRU.cjs.map → chunk-WWSYGZED.cjs.map} +1 -1
- package/dist/{chunk-D2JPOFRZ.cjs → chunk-WY3IFEKV.cjs} +191 -191
- package/dist/{chunk-D2JPOFRZ.cjs.map → chunk-WY3IFEKV.cjs.map} +1 -1
- package/dist/{chunk-3RSFLZ7A.cjs → chunk-Y4X6ODVY.cjs} +943 -763
- package/dist/chunk-Y4X6ODVY.cjs.map +1 -0
- package/dist/{chunk-VZRXXABW.js → chunk-YHMXF7OZ.js} +5 -5
- package/dist/{chunk-VZRXXABW.js.map → chunk-YHMXF7OZ.js.map} +1 -1
- package/dist/{chunk-VROJKWZ7.js → chunk-ZONDBN6H.js} +5 -5
- package/dist/{chunk-VROJKWZ7.js.map → chunk-ZONDBN6H.js.map} +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/{ddl-DvW9aobX.d.ts → ddl-2q7xLM1X.d.ts} +3 -3
- package/dist/{ddl-BjuXbPfw.d.cts → ddl-D_09BfbN.d.cts} +3 -3
- package/dist/graph-extension/index.d.cts +2 -2
- package/dist/graph-extension/index.d.ts +2 -2
- package/dist/graph-merge/index.cjs +156 -156
- package/dist/graph-merge/index.d.cts +7 -7
- package/dist/graph-merge/index.d.ts +7 -7
- package/dist/graph-merge/index.js +14 -14
- package/dist/{graph-templates-1vMqlPsu.d.cts → graph-templates-B5Q7oYAA.d.cts} +2 -2
- package/dist/{graph-templates-Y52w16dH.d.ts → graph-templates-D9N-Z9kw.d.ts} +2 -2
- package/dist/index.cjs +99 -99
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +18 -18
- package/dist/indexes/index.d.cts +4 -4
- package/dist/indexes/index.d.ts +4 -4
- package/dist/{ingestion-import-target-CCKeXZbW.d.ts → ingestion-import-target-B8EU6ug2.d.ts} +1 -1
- package/dist/{ingestion-import-target-774QRgkF.d.cts → ingestion-import-target-C5sHNFJF.d.cts} +1 -1
- package/dist/interchange/index.cjs +34 -34
- package/dist/interchange/index.d.cts +7 -7
- package/dist/interchange/index.d.ts +7 -7
- package/dist/interchange/index.js +11 -11
- package/dist/{local-store-impl-DFKS7QTV.js → local-store-impl-ERPNYOCL.js} +18 -18
- package/dist/{local-store-impl-DFKS7QTV.js.map → local-store-impl-ERPNYOCL.js.map} +1 -1
- package/dist/{local-store-impl-3E4VLFCI.cjs → local-store-impl-OUINMCYI.cjs} +22 -22
- package/dist/{local-store-impl-3E4VLFCI.cjs.map → local-store-impl-OUINMCYI.cjs.map} +1 -1
- package/dist/{pglite-store-impl-N63GGBU2.js → pglite-store-impl-DUJBQZS5.js} +18 -18
- package/dist/{pglite-store-impl-N63GGBU2.js.map → pglite-store-impl-DUJBQZS5.js.map} +1 -1
- package/dist/{pglite-store-impl-T75O3LVQ.cjs → pglite-store-impl-Z3SOOP75.cjs} +22 -22
- package/dist/{pglite-store-impl-T75O3LVQ.cjs.map → pglite-store-impl-Z3SOOP75.cjs.map} +1 -1
- package/dist/{postgres-C9gitL71.d.ts → postgres-BbTYW3b_.d.ts} +3 -3
- package/dist/{postgres-BONrXHb4.d.cts → postgres-DOBXcZVg.d.cts} +1 -1
- package/dist/{postgres-DAFRdnTr.d.ts → postgres-DhZixg92.d.ts} +1 -1
- package/dist/{postgres-2FYdVYCm.d.cts → postgres-Dp3MpyJt.d.cts} +3 -3
- package/dist/{profile-CAD65CqS.d.ts → profile-Ch5SSewK.d.ts} +8 -8
- package/dist/{profile-Bmcg07Ki.d.cts → profile-DppApFgt.d.cts} +8 -8
- package/dist/profiler/index.d.cts +8 -8
- package/dist/profiler/index.d.ts +8 -8
- package/dist/provenance/index.cjs +22 -22
- package/dist/provenance/index.d.cts +6 -6
- package/dist/provenance/index.d.ts +6 -6
- package/dist/provenance/index.js +6 -6
- package/dist/{repair-validity-windows-CinP91t7.d.cts → repair-validity-windows-CpP_GpIx.d.cts} +1 -1
- package/dist/{repair-validity-windows-BJz4nffP.d.ts → repair-validity-windows-lfe275bY.d.ts} +1 -1
- package/dist/{resolve-DgOSlXx_.d.ts → resolve-CoYqHqno.d.cts} +7 -2
- package/dist/{resolve-DQXSEN_A.d.cts → resolve-DV0Iposp.d.ts} +7 -2
- package/dist/schema/index.cjs +37 -37
- package/dist/schema/index.d.cts +7 -7
- package/dist/schema/index.d.ts +7 -7
- package/dist/schema/index.js +7 -7
- package/dist/{searchable-DMdCwkXO.d.cts → searchable-C7Xt6g45.d.cts} +1 -1
- package/dist/{searchable-BPRF0Bah.d.ts → searchable-KKXrPet3.d.ts} +1 -1
- package/dist/{sqlite-DgbYa-1Y.d.cts → sqlite-BkQM9ZeI.d.cts} +1 -1
- package/dist/{sqlite-Co_uIpfs.d.cts → sqlite-BpRtjC36.d.cts} +3 -3
- package/dist/{sqlite-DcDAAYow.d.ts → sqlite-CH0Zq0Qv.d.ts} +3 -3
- package/dist/{sqlite-UlG5prJQ.d.ts → sqlite-CcCSeXGg.d.ts} +1 -1
- package/dist/{store-HxoFyQMu.d.cts → store-3nfPQK5j.d.cts} +30 -7
- package/dist/{store-C9T1c9Az.d.ts → store-C8ZPl7OW.d.ts} +30 -7
- package/dist/{types-CRCyg1fJ.d.cts → types-BynPp5kU.d.cts} +18 -2
- package/dist/{types-CRCyg1fJ.d.ts → types-BynPp5kU.d.ts} +18 -2
- package/dist/{types-Dg_prBqC.d.ts → types-C9YwrkSe.d.ts} +1 -1
- package/dist/{types-B5AUesS1.d.cts → types-JG-4CG6P.d.cts} +1 -1
- package/dist/{where-gRyc3jj_.d.cts → where-D1gBDqQ_.d.cts} +1 -1
- package/dist/{where-D-NDKMPw.d.ts → where-D2GqMFp-.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/chunk-337ONI2I.js.map +0 -1
- package/dist/chunk-3KWF25MF.cjs.map +0 -1
- package/dist/chunk-3RSFLZ7A.cjs.map +0 -1
- package/dist/chunk-AD3NLSV5.js.map +0 -1
- package/dist/chunk-BWQA3POT.cjs.map +0 -1
- package/dist/chunk-MIBWA6HX.js.map +0 -1
- package/dist/chunk-OC5ROP7V.cjs.map +0 -1
- package/dist/chunk-PFXNQFFY.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkQCD5JKU4_cjs = require('./chunk-QCD5JKU4.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkMN325MG4_cjs = require('./chunk-MN325MG4.cjs');
|
|
5
5
|
var chunkCBHZX3G5_cjs = require('./chunk-CBHZX3G5.cjs');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
6
|
+
var chunkI7SBZJI2_cjs = require('./chunk-I7SBZJI2.cjs');
|
|
7
|
+
var chunk6JRVV2SS_cjs = require('./chunk-6JRVV2SS.cjs');
|
|
8
8
|
var chunk7XYPLAPL_cjs = require('./chunk-7XYPLAPL.cjs');
|
|
9
9
|
var module$1 = require('module');
|
|
10
10
|
var Database = require('better-sqlite3');
|
|
@@ -16,26 +16,26 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
16
16
|
|
|
17
17
|
var Database__default = /*#__PURE__*/_interopDefault(Database);
|
|
18
18
|
|
|
19
|
-
var nodeRequire = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-
|
|
19
|
+
var nodeRequire = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunk-ANMCKLZQ.cjs', document.baseURI).href)));
|
|
20
20
|
function installLocalSqliteBaseSchema(sqlite, tables2, fulltextStrategy) {
|
|
21
|
-
if (
|
|
21
|
+
if (chunkMN325MG4_cjs.CURRENT_BASE_SCHEMA_VERSION !== 3) {
|
|
22
22
|
throw new chunk7XYPLAPL_cjs.CompilerInvariantError(
|
|
23
23
|
"The synchronous managed SQLite installation path only implements base-schema v1 through v3 adoption.",
|
|
24
|
-
{ currentVersion:
|
|
24
|
+
{ currentVersion: chunkMN325MG4_cjs.CURRENT_BASE_SCHEMA_VERSION }
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
|
-
const installationSql =
|
|
27
|
+
const installationSql = chunkMN325MG4_cjs.generateSqliteMigrationSQL(tables2, fulltextStrategy);
|
|
28
28
|
try {
|
|
29
29
|
sqlite.exec(installationSql);
|
|
30
30
|
} catch (error) {
|
|
31
|
-
if (!
|
|
31
|
+
if (!chunk6JRVV2SS_cjs.isSqliteMissingEdgeMatchIdentityColumnError(error)) throw error;
|
|
32
32
|
const edgeTableName = drizzleOrm.getTableName(tables2.edges);
|
|
33
33
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
34
|
-
const rows = sqlite.prepare(`PRAGMA table_info(${
|
|
34
|
+
const rows = sqlite.prepare(`PRAGMA table_info(${chunkMN325MG4_cjs.quoteDdlIdentifier(edgeTableName)})`).all();
|
|
35
35
|
const columns = new Set(
|
|
36
36
|
rows.flatMap((row) => typeof row.name === "string" ? [row.name] : [])
|
|
37
37
|
);
|
|
38
|
-
const adoptionSql =
|
|
38
|
+
const adoptionSql = chunkMN325MG4_cjs.planSqliteEdgeMatchIdentityAdoption(
|
|
39
39
|
edgeTableName,
|
|
40
40
|
columns
|
|
41
41
|
);
|
|
@@ -43,7 +43,7 @@ function installLocalSqliteBaseSchema(sqlite, tables2, fulltextStrategy) {
|
|
|
43
43
|
sqlite.exec([...adoptionSql, installationSql].join("\n"));
|
|
44
44
|
return;
|
|
45
45
|
} catch (repairError) {
|
|
46
|
-
if (attempt === 2 || !
|
|
46
|
+
if (attempt === 2 || !chunk6JRVV2SS_cjs.isSqliteDuplicateEdgeMatchIdentityColumnError(repairError)) {
|
|
47
47
|
throw repairError;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
@@ -162,16 +162,16 @@ function applyConnectionPragmas(sqlite, pragmas) {
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
function createLocalSqliteBackend(options = {}) {
|
|
165
|
-
|
|
165
|
+
chunkMN325MG4_cjs.assertNoLegacyTransactionCapability(options.capabilities);
|
|
166
166
|
const path = options.path ?? ":memory:";
|
|
167
|
-
const tables2 = options.tables ??
|
|
167
|
+
const tables2 = options.tables ?? chunkMN325MG4_cjs.tables2;
|
|
168
168
|
const sqlite = createDatabase(path);
|
|
169
169
|
try {
|
|
170
170
|
applyConnectionPragmas(sqlite, options.pragmas);
|
|
171
171
|
const hasSqliteVec = tryLoadSqliteVec(sqlite);
|
|
172
172
|
const db = betterSqlite3.drizzle(sqlite);
|
|
173
173
|
installLocalSqliteBaseSchema(sqlite, tables2, options.fulltext);
|
|
174
|
-
const backend =
|
|
174
|
+
const backend = chunkMN325MG4_cjs.createSqliteBackend(db, {
|
|
175
175
|
...options.schemaProvisioning === void 0 ? {} : { schemaProvisioning: options.schemaProvisioning },
|
|
176
176
|
executionProfile: {
|
|
177
177
|
isSync: true
|
|
@@ -187,10 +187,10 @@ function createLocalSqliteBackend(options = {}) {
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
});
|
|
190
|
-
const managedBackend =
|
|
190
|
+
const managedBackend = chunk6JRVV2SS_cjs.wrapWithManagedClose(backend, () => {
|
|
191
191
|
sqlite.close();
|
|
192
192
|
});
|
|
193
|
-
return { backend:
|
|
193
|
+
return { backend: chunkI7SBZJI2_cjs.markBundledRootAutocommitEligible(managedBackend), db };
|
|
194
194
|
} catch (error) {
|
|
195
195
|
try {
|
|
196
196
|
sqlite.close();
|
|
@@ -213,5 +213,5 @@ function tryLoadSqliteVec(sqlite) {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
exports.createLocalSqliteBackend = createLocalSqliteBackend;
|
|
216
|
-
//# sourceMappingURL=chunk-
|
|
217
|
-
//# sourceMappingURL=chunk-
|
|
216
|
+
//# sourceMappingURL=chunk-ANMCKLZQ.cjs.map
|
|
217
|
+
//# sourceMappingURL=chunk-ANMCKLZQ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend/sqlite/local.ts"],"names":["createRequire","tables","CURRENT_BASE_SCHEMA_VERSION","CompilerInvariantError","generateSqliteMigrationSQL","isSqliteMissingEdgeMatchIdentityColumnError","getTableName","quoteDdlIdentifier","planSqliteEdgeMatchIdentityAdoption","isSqliteDuplicateEdgeMatchIdentityColumnError","Database","ConfigurationError","DEFAULT_LOCAL_SQLITE_PRAGMAS","assertNoLegacyTransactionCapability","drizzle","createSqliteBackend","sqliteVecStrategy","wrapWithManagedClose","markBundledRootAutocommitEligible"],"mappings":"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","file":"chunk-JERQGJKG.cjs","sourcesContent":["/**\n * Local SQLite backend using better-sqlite3.\n *\n * This module depends on the `better-sqlite3` native addon and should only\n * be imported in Node.js environments. For bundler-friendly SQLite DDL\n * generation and Drizzle backend creation, import from `@nicia-ai/typegraph/adapters/drizzle/sqlite`.\n *\n * @example In-memory database (default)\n * ```typescript\n * import { createLocalSqliteBackend } from \"@nicia-ai/typegraph/adapters/drizzle/sqlite/local\";\n *\n * const { backend, db } = createLocalSqliteBackend();\n * const store = createStore(graph, backend);\n * ```\n *\n * @example File-based database for persistent local development\n * ```typescript\n * import { createLocalSqliteBackend } from \"@nicia-ai/typegraph/adapters/drizzle/sqlite/local\";\n *\n * const { backend, db } = createLocalSqliteBackend({ path: \"./dev.db\" });\n * const store = createStore(graph, backend);\n * ```\n */\nimport { createRequire } from \"node:module\";\n\nimport Database from \"better-sqlite3\";\nimport { getTableName } from \"drizzle-orm\";\nimport {\n type BetterSQLite3Database,\n drizzle,\n} from \"drizzle-orm/better-sqlite3\";\n\nimport { CompilerInvariantError, ConfigurationError } from \"../../errors\";\nimport { type FulltextStrategy } from \"../../query/dialect/fulltext-strategy\";\nimport { sqliteVecStrategy } from \"../../query/dialect/vector/sqlite-vec-strategy\";\nimport {\n isSqliteDuplicateEdgeMatchIdentityColumnError,\n isSqliteMissingEdgeMatchIdentityColumnError,\n} from \"../../utils/sql-errors\";\nimport { markBundledRootAutocommitEligible } from \"../capabilities/autocommit-single-statement\";\nimport { wrapWithManagedClose } from \"../derive-backend\";\nimport { CURRENT_BASE_SCHEMA_VERSION } from \"../drizzle/base-schema\";\nimport {\n generateSqliteMigrationSQL,\n planSqliteEdgeMatchIdentityAdoption,\n quoteDdlIdentifier,\n} from \"../drizzle/ddl\";\nimport { type AnySqliteDatabase } from \"../drizzle/execution\";\nexport type { AnySqliteDatabase } from \"../drizzle/execution\";\nimport { assertNoLegacyTransactionCapability } from \"../capabilities/declarations\";\nimport {\n createSqliteBackend,\n type SqliteTables,\n tables as defaultTables,\n} from \"../drizzle/sqlite\";\nimport {\n DEFAULT_LOCAL_SQLITE_PRAGMAS,\n type LocalSqliteJournalMode,\n type LocalSqlitePragmaOptions,\n type LocalSqliteSynchronousMode,\n} from \"./local-options\";\n\nexport {\n DEFAULT_LOCAL_SQLITE_PRAGMAS,\n type LocalSqliteJournalMode,\n type LocalSqlitePragmaOptions,\n type LocalSqliteSynchronousMode,\n} from \"./local-options\";\nimport {\n type AdapterBackend,\n type BundledBackendCapabilityOverrides,\n type SchemaProvisioning,\n} from \"../types\";\nexport type { BundledBackendCapabilityOverrides } from \"../types\";\nexport type {\n ContributionDiagnostic,\n ContributionDiagnosticState,\n ContributionRepairEntry,\n ContributionRepairResult,\n} from \"../types\";\n\nconst nodeRequire = createRequire(import.meta.url);\n\nfunction installLocalSqliteBaseSchema(\n sqlite: Database.Database,\n tables: SqliteTables,\n fulltextStrategy: FulltextStrategy | false | undefined,\n): void {\n // v2 (the fences relation) and v3 (the recorded-relations' and recorded\n // identity-assertions relation's `since_idx` indexes) need no adoption\n // logic beyond what `generateSqliteMigrationSQL` already emits: a\n // brand-new relation or index is fully covered by its own `CREATE TABLE\n // IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`, on both a fresh database\n // and one that already has every OTHER base table or index. Only v1's\n // edge-match-identity `ADD COLUMN` migration — handled by the catch block\n // below — needed runtime introspection this synchronous path writes by\n // hand instead of running `BaseSchemaLifecycle`'s async state machine.\n if (CURRENT_BASE_SCHEMA_VERSION !== 3) {\n throw new CompilerInvariantError(\n \"The synchronous managed SQLite installation path only implements base-schema v1 through v3 adoption.\",\n { currentVersion: CURRENT_BASE_SCHEMA_VERSION },\n );\n }\n const installationSql = generateSqliteMigrationSQL(tables, fulltextStrategy);\n try {\n sqlite.exec(installationSql);\n } catch (error) {\n if (!isSqliteMissingEdgeMatchIdentityColumnError(error)) throw error;\n const edgeTableName = getTableName(tables.edges);\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const rows = sqlite\n .prepare(`PRAGMA table_info(${quoteDdlIdentifier(edgeTableName)})`)\n .all() as readonly Readonly<{ name?: unknown }>[];\n const columns = new Set(\n rows.flatMap((row) => (typeof row.name === \"string\" ? [row.name] : [])),\n );\n const adoptionSql = planSqliteEdgeMatchIdentityAdoption(\n edgeTableName,\n columns,\n );\n try {\n sqlite.exec([...adoptionSql, installationSql].join(\"\\n\"));\n return;\n } catch (repairError) {\n if (\n attempt === 2 ||\n !isSqliteDuplicateEdgeMatchIdentityColumnError(repairError)\n ) {\n throw repairError;\n }\n }\n }\n throw new CompilerInvariantError(\n \"Local SQLite match-identity adoption exhausted its retry loop without returning or throwing.\",\n );\n }\n}\n\n// ============================================================\n// Native Addon Helpers\n// ============================================================\n\ntype NodeModuleVersionMismatch = Readonly<{\n compiled: number;\n required: number;\n}>;\n\nfunction getUnknownErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\nfunction parseNodeModuleVersionMismatchMessage(\n message: string,\n): NodeModuleVersionMismatch | undefined {\n const regexp =\n /NODE_MODULE_VERSION (?<compiled>\\d+)[\\s\\S]*?NODE_MODULE_VERSION (?<required>\\d+)/;\n const match = regexp.exec(message);\n if (!match?.groups) return undefined;\n\n const compiled = Number(match.groups[\"compiled\"]);\n const required = Number(match.groups[\"required\"]);\n\n if (!Number.isFinite(compiled) || !Number.isFinite(required))\n return undefined;\n\n return { compiled, required };\n}\n\nfunction createDatabase(path: string): Database.Database {\n try {\n return new Database(path);\n } catch (error) {\n const message = getUnknownErrorMessage(error);\n const mismatch = parseNodeModuleVersionMismatchMessage(message);\n if (!mismatch) throw error;\n\n throw new ConfigurationError(\n [\n \"Failed to load better-sqlite3 native addon.\",\n `It was compiled for NODE_MODULE_VERSION ${mismatch.compiled}, but this Node.js runtime requires ${mismatch.required}.`,\n \"This usually happens after switching Node versions without rebuilding native dependencies.\",\n \"Rebuild with: pnpm rebuild better-sqlite3 (or npm rebuild better-sqlite3).\",\n ].join(\" \"),\n {\n nodeVersion: process.version,\n nodeModuleVersion: process.versions.modules,\n compiledNodeModuleVersion: mismatch.compiled,\n requiredNodeModuleVersion: mismatch.required,\n },\n { cause: error },\n );\n }\n}\n\n// ============================================================\n// Types\n// ============================================================\n\nconst LOCAL_SQLITE_JOURNAL_MODES: readonly LocalSqliteJournalMode[] = [\n \"wal\",\n \"delete\",\n \"truncate\",\n \"persist\",\n \"memory\",\n \"off\",\n];\n\nconst LOCAL_SQLITE_SYNCHRONOUS_MODES: readonly LocalSqliteSynchronousMode[] = [\n \"off\",\n \"normal\",\n \"full\",\n \"extra\",\n];\n\nconst SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES = 2_147_483_647;\n\nfunction applyConnectionPragmas(\n sqlite: Database.Database,\n pragmas: LocalSqlitePragmaOptions | false | undefined,\n): void {\n if (pragmas === false) return;\n const resolved: Required<LocalSqlitePragmaOptions> = {\n ...DEFAULT_LOCAL_SQLITE_PRAGMAS,\n ...pragmas,\n };\n\n // Runtime guards mirror the compile-time unions: pragma values are spliced\n // into pragma statements, so reject anything outside the allowlists rather\n // than forwarding it to SQLite.\n if (!LOCAL_SQLITE_JOURNAL_MODES.includes(resolved.journalMode)) {\n throw new ConfigurationError(\n `Invalid journalMode pragma: ${resolved.journalMode}. ` +\n `Expected one of: ${LOCAL_SQLITE_JOURNAL_MODES.join(\", \")}.`,\n { journalMode: resolved.journalMode },\n );\n }\n if (!LOCAL_SQLITE_SYNCHRONOUS_MODES.includes(resolved.synchronous)) {\n throw new ConfigurationError(\n `Invalid synchronous pragma: ${resolved.synchronous}. ` +\n `Expected one of: ${LOCAL_SQLITE_SYNCHRONOUS_MODES.join(\", \")}.`,\n { synchronous: resolved.synchronous },\n );\n }\n if (\n !Number.isSafeInteger(resolved.busyTimeoutMs) ||\n resolved.busyTimeoutMs < 0\n ) {\n throw new ConfigurationError(\n `Invalid busyTimeoutMs pragma: ${String(resolved.busyTimeoutMs)}. ` +\n \"Expected a non-negative integer number of milliseconds.\",\n { busyTimeoutMs: resolved.busyTimeoutMs },\n );\n }\n if (\n resolved.cacheSizeKib !== undefined &&\n (!Number.isSafeInteger(resolved.cacheSizeKib) || resolved.cacheSizeKib >= 0)\n ) {\n throw new ConfigurationError(\n `Invalid cacheSizeKib pragma: ${String(resolved.cacheSizeKib)}. ` +\n \"Expected a negative safe integer — SQLite's own cache_size pragma \" +\n \"interprets a positive value as a page count, not KiB, so a caller \" +\n 'who passes e.g. 131072 meaning \"131072 KiB\" silently gets ' +\n \"131072 pages (~512MiB at the default 4KiB page size) instead.\",\n { cacheSizeKib: resolved.cacheSizeKib },\n );\n }\n if (\n resolved.mmapSizeBytes !== undefined &&\n (!Number.isSafeInteger(resolved.mmapSizeBytes) ||\n resolved.mmapSizeBytes < 0)\n ) {\n throw new ConfigurationError(\n `Invalid mmapSizeBytes pragma: ${String(resolved.mmapSizeBytes)}. ` +\n \"Expected a non-negative safe integer number of bytes.\",\n { mmapSizeBytes: resolved.mmapSizeBytes },\n );\n }\n if (\n resolved.walAutocheckpointPages !== undefined &&\n (!Number.isSafeInteger(resolved.walAutocheckpointPages) ||\n resolved.walAutocheckpointPages < 0 ||\n resolved.walAutocheckpointPages > SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES)\n ) {\n throw new ConfigurationError(\n `Invalid walAutocheckpointPages pragma: ${String(resolved.walAutocheckpointPages)}. ` +\n `Expected an integer between 0 and ${SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES} ` +\n \"WAL pages (0 disables automatic checkpointing entirely).\",\n { walAutocheckpointPages: resolved.walAutocheckpointPages },\n );\n }\n\n // \":memory:\" databases always journal in memory; SQLite answers the WAL\n // request with \"memory\" instead of erroring, so no special-casing needed.\n sqlite.pragma(`journal_mode = ${resolved.journalMode}`);\n sqlite.pragma(`synchronous = ${resolved.synchronous}`);\n sqlite.pragma(`busy_timeout = ${resolved.busyTimeoutMs}`);\n if (resolved.cacheSizeKib !== undefined) {\n sqlite.pragma(`cache_size = ${resolved.cacheSizeKib}`);\n }\n if (resolved.mmapSizeBytes !== undefined) {\n sqlite.pragma(`mmap_size = ${resolved.mmapSizeBytes}`);\n }\n if (resolved.walAutocheckpointPages !== undefined) {\n sqlite.pragma(`wal_autocheckpoint = ${resolved.walAutocheckpointPages}`);\n }\n}\n\n/**\n * Options for creating a local SQLite backend.\n */\nexport type LocalSqliteBackendOptions = Readonly<{\n schemaProvisioning?: SchemaProvisioning;\n /**\n * Path to the SQLite database file.\n * Defaults to \":memory:\" for an in-memory database.\n */\n path?: string;\n\n /**\n * Connection pragmas applied at open. Defaults to\n * {@link DEFAULT_LOCAL_SQLITE_PRAGMAS} (WAL, `synchronous=NORMAL`, 5s busy\n * timeout, and SQLite's own tiny built-in page cache / disabled mmap\n * left untouched). Individual values merge over the defaults; pass\n * `false` to skip pragma configuration entirely and keep the driver\n * defaults (rollback journal, `synchronous=FULL`, and better-sqlite3's\n * own 5s busy timeout from its `timeout` constructor option). Set\n * `cacheSizeKib`/`mmapSizeBytes` explicitly once a database's working\n * set is known to exceed SQLite's 2MiB default cache — otherwise every\n * query pays a fresh disk read per page past that tiny working set. Set\n * `walAutocheckpointPages` explicitly for a bulk-insert-heavy workload —\n * SQLite's own default checkpoints every ~4MiB of WAL growth, which gets\n * more expensive as the database file grows over a large load.\n */\n pragmas?: LocalSqlitePragmaOptions | false;\n\n /**\n * Custom table definitions.\n * Defaults to standard TypeGraph table names.\n */\n tables?: SqliteTables;\n\n /**\n * Override the fulltext strategy. Defaults to `fts5Strategy` (SQLite's\n * built-in FTS5 virtual table). Pass `false` to disable fulltext support\n * entirely — the backend then advertises no `capabilities.fulltext` and\n * omits the fulltext CRUD/search methods, and the managed installation\n * never creates the fulltext table. Forwarded to both the installation\n * DDL and `createSqliteBackend`.\n */\n fulltext?: FulltextStrategy | false;\n\n /**\n * Override specific backend capabilities — e.g. to simulate an engine-level\n * gap like missing SQL window functions in tests. Forwarded to\n * createSqliteBackend.\n */\n capabilities?: BundledBackendCapabilityOverrides;\n}>;\n\n/**\n * Result of creating a local SQLite backend.\n */\nexport type LocalSqliteBackendResult = Readonly<{\n /**\n * The GraphBackend instance for use with createStore.\n */\n backend: AdapterBackend<AnySqliteDatabase>;\n\n /**\n * The underlying Drizzle database instance.\n * Useful for direct SQL access or cleanup.\n */\n db: BetterSQLite3Database;\n}>;\n\n// ============================================================\n// Factory Function\n// ============================================================\n\n/**\n * Creates a SQLite backend with minimal configuration.\n *\n * This is a convenience function for local development and testing.\n * It handles database creation, schema migration, and backend setup.\n *\n * For production deployments or custom configurations, use createSqliteBackend\n * directly with your own Drizzle database instance.\n *\n * @param options - Configuration options\n * @returns Backend and database instances\n *\n * @example In-memory database (default)\n * ```typescript\n * const { backend } = createLocalSqliteBackend();\n * const store = createStore(graph, backend);\n * ```\n *\n * @example File-based database\n * ```typescript\n * const { backend, db } = createLocalSqliteBackend({ path: \"./data.db\" });\n * const store = createStore(graph, backend);\n * ```\n */\nexport function createLocalSqliteBackend(\n options: LocalSqliteBackendOptions = {},\n): LocalSqliteBackendResult {\n assertNoLegacyTransactionCapability(options.capabilities);\n const path = options.path ?? \":memory:\";\n const tables = options.tables ?? defaultTables;\n\n const sqlite = createDatabase(path);\n try {\n applyConnectionPragmas(sqlite, options.pragmas);\n\n // Best-effort: load sqlite-vec so embedding fields are persisted to\n // per-`(kind, field)` `vec0` storage. Without it, nodes with\n // `embedding()` fields validate and insert but their vectors are silently\n // dropped. When the user has installed sqlite-vec as a peer dep we load\n // it and wire the strategy; otherwise we proceed without vector support.\n const hasSqliteVec = tryLoadSqliteVec(sqlite);\n\n const db = drizzle(sqlite);\n\n // The managed factory owns a complete fresh installation, including the\n // deployment-wide base-schema marker consumed by verified/runtime-only\n // entrypoints. Raw generateSqliteDDL intentionally omits that marker.\n installLocalSqliteBaseSchema(sqlite, tables, options.fulltext);\n\n const backend = createSqliteBackend(db, {\n ...(options.schemaProvisioning === undefined ?\n {}\n : { schemaProvisioning: options.schemaProvisioning }),\n executionProfile: {\n isSync: true,\n },\n tables,\n ...(hasSqliteVec ? { vector: sqliteVecStrategy } : {}),\n ...(options.fulltext === undefined ? {} : { fulltext: options.fulltext }),\n capabilities: {\n ...options.capabilities,\n graphAnalytics: {\n supported:\n options.capabilities?.graphAnalytics?.supported ??\n options.capabilities?.execution?.interactiveTransactions !== false,\n mathFunctions:\n options.capabilities?.graphAnalytics?.mathFunctions ?? true,\n },\n },\n });\n const managedBackend = wrapWithManagedClose(backend, () => {\n sqlite.close();\n });\n\n return { backend: markBundledRootAutocommitEligible(managedBackend), db };\n } catch (error) {\n try {\n sqlite.close();\n } catch {\n // Preserve the provisioning error; a cleanup failure is secondary.\n }\n throw error;\n }\n}\n\nfunction tryLoadSqliteVec(sqlite: Database.Database): boolean {\n try {\n // `sqlite-vec` is an optional peer dep; resolved via createRequire so\n // bundlers don't mark it as a hard import. Node resolves the package\n // only when it's actually installed.\n const module_: unknown = nodeRequire(\"sqlite-vec\");\n if (\n typeof module_ === \"object\" &&\n module_ !== null &&\n \"load\" in module_ &&\n typeof module_.load === \"function\"\n ) {\n (module_ as { load: (db: Database.Database) => void }).load(sqlite);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\nexport type { GraphIdentityConfig } from \"../../core/define-graph\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/backend/sqlite/local.ts"],"names":["createRequire","tables","CURRENT_BASE_SCHEMA_VERSION","CompilerInvariantError","generateSqliteMigrationSQL","isSqliteMissingEdgeMatchIdentityColumnError","getTableName","quoteDdlIdentifier","planSqliteEdgeMatchIdentityAdoption","isSqliteDuplicateEdgeMatchIdentityColumnError","Database","ConfigurationError","DEFAULT_LOCAL_SQLITE_PRAGMAS","assertNoLegacyTransactionCapability","drizzle","createSqliteBackend","sqliteVecStrategy","wrapWithManagedClose","markBundledRootAutocommitEligible"],"mappings":"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","file":"chunk-ANMCKLZQ.cjs","sourcesContent":["/**\n * Local SQLite backend using better-sqlite3.\n *\n * This module depends on the `better-sqlite3` native addon and should only\n * be imported in Node.js environments. For bundler-friendly SQLite DDL\n * generation and Drizzle backend creation, import from `@nicia-ai/typegraph/adapters/drizzle/sqlite`.\n *\n * @example In-memory database (default)\n * ```typescript\n * import { createLocalSqliteBackend } from \"@nicia-ai/typegraph/adapters/drizzle/sqlite/local\";\n *\n * const { backend, db } = createLocalSqliteBackend();\n * const store = createStore(graph, backend);\n * ```\n *\n * @example File-based database for persistent local development\n * ```typescript\n * import { createLocalSqliteBackend } from \"@nicia-ai/typegraph/adapters/drizzle/sqlite/local\";\n *\n * const { backend, db } = createLocalSqliteBackend({ path: \"./dev.db\" });\n * const store = createStore(graph, backend);\n * ```\n */\nimport { createRequire } from \"node:module\";\n\nimport Database from \"better-sqlite3\";\nimport { getTableName } from \"drizzle-orm\";\nimport {\n type BetterSQLite3Database,\n drizzle,\n} from \"drizzle-orm/better-sqlite3\";\n\nimport { CompilerInvariantError, ConfigurationError } from \"../../errors\";\nimport { type FulltextStrategy } from \"../../query/dialect/fulltext-strategy\";\nimport { sqliteVecStrategy } from \"../../query/dialect/vector/sqlite-vec-strategy\";\nimport {\n isSqliteDuplicateEdgeMatchIdentityColumnError,\n isSqliteMissingEdgeMatchIdentityColumnError,\n} from \"../../utils/sql-errors\";\nimport { markBundledRootAutocommitEligible } from \"../capabilities/autocommit-single-statement\";\nimport { wrapWithManagedClose } from \"../derive-backend\";\nimport { CURRENT_BASE_SCHEMA_VERSION } from \"../drizzle/base-schema\";\nimport {\n generateSqliteMigrationSQL,\n planSqliteEdgeMatchIdentityAdoption,\n quoteDdlIdentifier,\n} from \"../drizzle/ddl\";\nimport { type AnySqliteDatabase } from \"../drizzle/execution\";\nexport type { AnySqliteDatabase } from \"../drizzle/execution\";\nimport { assertNoLegacyTransactionCapability } from \"../capabilities/declarations\";\nimport {\n createSqliteBackend,\n type SqliteTables,\n tables as defaultTables,\n} from \"../drizzle/sqlite\";\nimport {\n DEFAULT_LOCAL_SQLITE_PRAGMAS,\n type LocalSqliteJournalMode,\n type LocalSqlitePragmaOptions,\n type LocalSqliteSynchronousMode,\n} from \"./local-options\";\n\nexport {\n DEFAULT_LOCAL_SQLITE_PRAGMAS,\n type LocalSqliteJournalMode,\n type LocalSqlitePragmaOptions,\n type LocalSqliteSynchronousMode,\n} from \"./local-options\";\nimport {\n type AdapterBackend,\n type BundledBackendCapabilityOverrides,\n type SchemaProvisioning,\n} from \"../types\";\nexport type { BundledBackendCapabilityOverrides } from \"../types\";\nexport type {\n ContributionDiagnostic,\n ContributionDiagnosticState,\n ContributionRepairEntry,\n ContributionRepairResult,\n} from \"../types\";\n\nconst nodeRequire = createRequire(import.meta.url);\n\nfunction installLocalSqliteBaseSchema(\n sqlite: Database.Database,\n tables: SqliteTables,\n fulltextStrategy: FulltextStrategy | false | undefined,\n): void {\n // v2 (the fences relation) and v3 (the recorded-relations' and recorded\n // identity-assertions relation's `since_idx` indexes) need no adoption\n // logic beyond what `generateSqliteMigrationSQL` already emits: a\n // brand-new relation or index is fully covered by its own `CREATE TABLE\n // IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`, on both a fresh database\n // and one that already has every OTHER base table or index. Only v1's\n // edge-match-identity `ADD COLUMN` migration — handled by the catch block\n // below — needed runtime introspection this synchronous path writes by\n // hand instead of running `BaseSchemaLifecycle`'s async state machine.\n if (CURRENT_BASE_SCHEMA_VERSION !== 3) {\n throw new CompilerInvariantError(\n \"The synchronous managed SQLite installation path only implements base-schema v1 through v3 adoption.\",\n { currentVersion: CURRENT_BASE_SCHEMA_VERSION },\n );\n }\n const installationSql = generateSqliteMigrationSQL(tables, fulltextStrategy);\n try {\n sqlite.exec(installationSql);\n } catch (error) {\n if (!isSqliteMissingEdgeMatchIdentityColumnError(error)) throw error;\n const edgeTableName = getTableName(tables.edges);\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const rows = sqlite\n .prepare(`PRAGMA table_info(${quoteDdlIdentifier(edgeTableName)})`)\n .all() as readonly Readonly<{ name?: unknown }>[];\n const columns = new Set(\n rows.flatMap((row) => (typeof row.name === \"string\" ? [row.name] : [])),\n );\n const adoptionSql = planSqliteEdgeMatchIdentityAdoption(\n edgeTableName,\n columns,\n );\n try {\n sqlite.exec([...adoptionSql, installationSql].join(\"\\n\"));\n return;\n } catch (repairError) {\n if (\n attempt === 2 ||\n !isSqliteDuplicateEdgeMatchIdentityColumnError(repairError)\n ) {\n throw repairError;\n }\n }\n }\n throw new CompilerInvariantError(\n \"Local SQLite match-identity adoption exhausted its retry loop without returning or throwing.\",\n );\n }\n}\n\n// ============================================================\n// Native Addon Helpers\n// ============================================================\n\ntype NodeModuleVersionMismatch = Readonly<{\n compiled: number;\n required: number;\n}>;\n\nfunction getUnknownErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\nfunction parseNodeModuleVersionMismatchMessage(\n message: string,\n): NodeModuleVersionMismatch | undefined {\n const regexp =\n /NODE_MODULE_VERSION (?<compiled>\\d+)[\\s\\S]*?NODE_MODULE_VERSION (?<required>\\d+)/;\n const match = regexp.exec(message);\n if (!match?.groups) return undefined;\n\n const compiled = Number(match.groups[\"compiled\"]);\n const required = Number(match.groups[\"required\"]);\n\n if (!Number.isFinite(compiled) || !Number.isFinite(required))\n return undefined;\n\n return { compiled, required };\n}\n\nfunction createDatabase(path: string): Database.Database {\n try {\n return new Database(path);\n } catch (error) {\n const message = getUnknownErrorMessage(error);\n const mismatch = parseNodeModuleVersionMismatchMessage(message);\n if (!mismatch) throw error;\n\n throw new ConfigurationError(\n [\n \"Failed to load better-sqlite3 native addon.\",\n `It was compiled for NODE_MODULE_VERSION ${mismatch.compiled}, but this Node.js runtime requires ${mismatch.required}.`,\n \"This usually happens after switching Node versions without rebuilding native dependencies.\",\n \"Rebuild with: pnpm rebuild better-sqlite3 (or npm rebuild better-sqlite3).\",\n ].join(\" \"),\n {\n nodeVersion: process.version,\n nodeModuleVersion: process.versions.modules,\n compiledNodeModuleVersion: mismatch.compiled,\n requiredNodeModuleVersion: mismatch.required,\n },\n { cause: error },\n );\n }\n}\n\n// ============================================================\n// Types\n// ============================================================\n\nconst LOCAL_SQLITE_JOURNAL_MODES: readonly LocalSqliteJournalMode[] = [\n \"wal\",\n \"delete\",\n \"truncate\",\n \"persist\",\n \"memory\",\n \"off\",\n];\n\nconst LOCAL_SQLITE_SYNCHRONOUS_MODES: readonly LocalSqliteSynchronousMode[] = [\n \"off\",\n \"normal\",\n \"full\",\n \"extra\",\n];\n\nconst SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES = 2_147_483_647;\n\nfunction applyConnectionPragmas(\n sqlite: Database.Database,\n pragmas: LocalSqlitePragmaOptions | false | undefined,\n): void {\n if (pragmas === false) return;\n const resolved: Required<LocalSqlitePragmaOptions> = {\n ...DEFAULT_LOCAL_SQLITE_PRAGMAS,\n ...pragmas,\n };\n\n // Runtime guards mirror the compile-time unions: pragma values are spliced\n // into pragma statements, so reject anything outside the allowlists rather\n // than forwarding it to SQLite.\n if (!LOCAL_SQLITE_JOURNAL_MODES.includes(resolved.journalMode)) {\n throw new ConfigurationError(\n `Invalid journalMode pragma: ${resolved.journalMode}. ` +\n `Expected one of: ${LOCAL_SQLITE_JOURNAL_MODES.join(\", \")}.`,\n { journalMode: resolved.journalMode },\n );\n }\n if (!LOCAL_SQLITE_SYNCHRONOUS_MODES.includes(resolved.synchronous)) {\n throw new ConfigurationError(\n `Invalid synchronous pragma: ${resolved.synchronous}. ` +\n `Expected one of: ${LOCAL_SQLITE_SYNCHRONOUS_MODES.join(\", \")}.`,\n { synchronous: resolved.synchronous },\n );\n }\n if (\n !Number.isSafeInteger(resolved.busyTimeoutMs) ||\n resolved.busyTimeoutMs < 0\n ) {\n throw new ConfigurationError(\n `Invalid busyTimeoutMs pragma: ${String(resolved.busyTimeoutMs)}. ` +\n \"Expected a non-negative integer number of milliseconds.\",\n { busyTimeoutMs: resolved.busyTimeoutMs },\n );\n }\n if (\n resolved.cacheSizeKib !== undefined &&\n (!Number.isSafeInteger(resolved.cacheSizeKib) || resolved.cacheSizeKib >= 0)\n ) {\n throw new ConfigurationError(\n `Invalid cacheSizeKib pragma: ${String(resolved.cacheSizeKib)}. ` +\n \"Expected a negative safe integer — SQLite's own cache_size pragma \" +\n \"interprets a positive value as a page count, not KiB, so a caller \" +\n 'who passes e.g. 131072 meaning \"131072 KiB\" silently gets ' +\n \"131072 pages (~512MiB at the default 4KiB page size) instead.\",\n { cacheSizeKib: resolved.cacheSizeKib },\n );\n }\n if (\n resolved.mmapSizeBytes !== undefined &&\n (!Number.isSafeInteger(resolved.mmapSizeBytes) ||\n resolved.mmapSizeBytes < 0)\n ) {\n throw new ConfigurationError(\n `Invalid mmapSizeBytes pragma: ${String(resolved.mmapSizeBytes)}. ` +\n \"Expected a non-negative safe integer number of bytes.\",\n { mmapSizeBytes: resolved.mmapSizeBytes },\n );\n }\n if (\n resolved.walAutocheckpointPages !== undefined &&\n (!Number.isSafeInteger(resolved.walAutocheckpointPages) ||\n resolved.walAutocheckpointPages < 0 ||\n resolved.walAutocheckpointPages > SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES)\n ) {\n throw new ConfigurationError(\n `Invalid walAutocheckpointPages pragma: ${String(resolved.walAutocheckpointPages)}. ` +\n `Expected an integer between 0 and ${SQLITE_MAX_WAL_AUTOCHECKPOINT_PAGES} ` +\n \"WAL pages (0 disables automatic checkpointing entirely).\",\n { walAutocheckpointPages: resolved.walAutocheckpointPages },\n );\n }\n\n // \":memory:\" databases always journal in memory; SQLite answers the WAL\n // request with \"memory\" instead of erroring, so no special-casing needed.\n sqlite.pragma(`journal_mode = ${resolved.journalMode}`);\n sqlite.pragma(`synchronous = ${resolved.synchronous}`);\n sqlite.pragma(`busy_timeout = ${resolved.busyTimeoutMs}`);\n if (resolved.cacheSizeKib !== undefined) {\n sqlite.pragma(`cache_size = ${resolved.cacheSizeKib}`);\n }\n if (resolved.mmapSizeBytes !== undefined) {\n sqlite.pragma(`mmap_size = ${resolved.mmapSizeBytes}`);\n }\n if (resolved.walAutocheckpointPages !== undefined) {\n sqlite.pragma(`wal_autocheckpoint = ${resolved.walAutocheckpointPages}`);\n }\n}\n\n/**\n * Options for creating a local SQLite backend.\n */\nexport type LocalSqliteBackendOptions = Readonly<{\n schemaProvisioning?: SchemaProvisioning;\n /**\n * Path to the SQLite database file.\n * Defaults to \":memory:\" for an in-memory database.\n */\n path?: string;\n\n /**\n * Connection pragmas applied at open. Defaults to\n * {@link DEFAULT_LOCAL_SQLITE_PRAGMAS} (WAL, `synchronous=NORMAL`, 5s busy\n * timeout, and SQLite's own tiny built-in page cache / disabled mmap\n * left untouched). Individual values merge over the defaults; pass\n * `false` to skip pragma configuration entirely and keep the driver\n * defaults (rollback journal, `synchronous=FULL`, and better-sqlite3's\n * own 5s busy timeout from its `timeout` constructor option). Set\n * `cacheSizeKib`/`mmapSizeBytes` explicitly once a database's working\n * set is known to exceed SQLite's 2MiB default cache — otherwise every\n * query pays a fresh disk read per page past that tiny working set. Set\n * `walAutocheckpointPages` explicitly for a bulk-insert-heavy workload —\n * SQLite's own default checkpoints every ~4MiB of WAL growth, which gets\n * more expensive as the database file grows over a large load.\n */\n pragmas?: LocalSqlitePragmaOptions | false;\n\n /**\n * Custom table definitions.\n * Defaults to standard TypeGraph table names.\n */\n tables?: SqliteTables;\n\n /**\n * Override the fulltext strategy. Defaults to `fts5Strategy` (SQLite's\n * built-in FTS5 virtual table). Pass `false` to disable fulltext support\n * entirely — the backend then advertises no `capabilities.fulltext` and\n * omits the fulltext CRUD/search methods, and the managed installation\n * never creates the fulltext table. Forwarded to both the installation\n * DDL and `createSqliteBackend`.\n */\n fulltext?: FulltextStrategy | false;\n\n /**\n * Override specific backend capabilities — e.g. to simulate an engine-level\n * gap like missing SQL window functions in tests. Forwarded to\n * createSqliteBackend.\n */\n capabilities?: BundledBackendCapabilityOverrides;\n}>;\n\n/**\n * Result of creating a local SQLite backend.\n */\nexport type LocalSqliteBackendResult = Readonly<{\n /**\n * The GraphBackend instance for use with createStore.\n */\n backend: AdapterBackend<AnySqliteDatabase>;\n\n /**\n * The underlying Drizzle database instance.\n * Useful for direct SQL access or cleanup.\n */\n db: BetterSQLite3Database;\n}>;\n\n// ============================================================\n// Factory Function\n// ============================================================\n\n/**\n * Creates a SQLite backend with minimal configuration.\n *\n * This is a convenience function for local development and testing.\n * It handles database creation, schema migration, and backend setup.\n *\n * For production deployments or custom configurations, use createSqliteBackend\n * directly with your own Drizzle database instance.\n *\n * @param options - Configuration options\n * @returns Backend and database instances\n *\n * @example In-memory database (default)\n * ```typescript\n * const { backend } = createLocalSqliteBackend();\n * const store = createStore(graph, backend);\n * ```\n *\n * @example File-based database\n * ```typescript\n * const { backend, db } = createLocalSqliteBackend({ path: \"./data.db\" });\n * const store = createStore(graph, backend);\n * ```\n */\nexport function createLocalSqliteBackend(\n options: LocalSqliteBackendOptions = {},\n): LocalSqliteBackendResult {\n assertNoLegacyTransactionCapability(options.capabilities);\n const path = options.path ?? \":memory:\";\n const tables = options.tables ?? defaultTables;\n\n const sqlite = createDatabase(path);\n try {\n applyConnectionPragmas(sqlite, options.pragmas);\n\n // Best-effort: load sqlite-vec so embedding fields are persisted to\n // per-`(kind, field)` `vec0` storage. Without it, nodes with\n // `embedding()` fields validate and insert but their vectors are silently\n // dropped. When the user has installed sqlite-vec as a peer dep we load\n // it and wire the strategy; otherwise we proceed without vector support.\n const hasSqliteVec = tryLoadSqliteVec(sqlite);\n\n const db = drizzle(sqlite);\n\n // The managed factory owns a complete fresh installation, including the\n // deployment-wide base-schema marker consumed by verified/runtime-only\n // entrypoints. Raw generateSqliteDDL intentionally omits that marker.\n installLocalSqliteBaseSchema(sqlite, tables, options.fulltext);\n\n const backend = createSqliteBackend(db, {\n ...(options.schemaProvisioning === undefined ?\n {}\n : { schemaProvisioning: options.schemaProvisioning }),\n executionProfile: {\n isSync: true,\n },\n tables,\n ...(hasSqliteVec ? { vector: sqliteVecStrategy } : {}),\n ...(options.fulltext === undefined ? {} : { fulltext: options.fulltext }),\n capabilities: {\n ...options.capabilities,\n graphAnalytics: {\n supported:\n options.capabilities?.graphAnalytics?.supported ??\n options.capabilities?.execution?.interactiveTransactions !== false,\n mathFunctions:\n options.capabilities?.graphAnalytics?.mathFunctions ?? true,\n },\n },\n });\n const managedBackend = wrapWithManagedClose(backend, () => {\n sqlite.close();\n });\n\n return { backend: markBundledRootAutocommitEligible(managedBackend), db };\n } catch (error) {\n try {\n sqlite.close();\n } catch {\n // Preserve the provisioning error; a cleanup failure is secondary.\n }\n throw error;\n }\n}\n\nfunction tryLoadSqliteVec(sqlite: Database.Database): boolean {\n try {\n // `sqlite-vec` is an optional peer dep; resolved via createRequire so\n // bundlers don't mark it as a hard import. Node resolves the package\n // only when it's actually installed.\n const module_: unknown = nodeRequire(\"sqlite-vec\");\n if (\n typeof module_ === \"object\" &&\n module_ !== null &&\n \"load\" in module_ &&\n typeof module_.load === \"function\"\n ) {\n (module_ as { load: (db: Database.Database) => void }).load(sqlite);\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\nexport type { GraphIdentityConfig } from \"../../core/define-graph\";\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createSqlSchema } from './chunk-
|
|
1
|
+
import { createSqlSchema } from './chunk-TU22BFMP.js';
|
|
2
2
|
|
|
3
3
|
// src/backend/table-names.ts
|
|
4
4
|
var LEGACY_EMBEDDINGS_TABLE_NAME = "typegraph_node_embeddings";
|
|
@@ -16,5 +16,5 @@ function resolvedTableNames(backend, override) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export { LEGACY_EMBEDDINGS_TABLE_NAME, resolvedTableNames };
|
|
19
|
-
//# sourceMappingURL=chunk-
|
|
20
|
-
//# sourceMappingURL=chunk-
|
|
19
|
+
//# sourceMappingURL=chunk-BABP4D5B.js.map
|
|
20
|
+
//# sourceMappingURL=chunk-BABP4D5B.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend/table-names.ts"],"names":[],"mappings":";;;AAiBO,IAAM,4BAAA,GAA+B;AAE5C,SAAS,0BACP,QAAA,EACwB;AACxB,EAAA,IAAI,QAAA,KAAa,MAAA,EAAW,OAAO,EAAC;AACpC,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,SAAS,CAAA,KAAM,SAAA,KAAc,MAAS;AAAA,GAC5E;AACF;AAYO,SAAS,kBAAA,CACd,SACA,QAAA,EACuB;AACvB,EAAA,OAAO,eAAA,CAAgB;AAAA,IACrB,GAAG,OAAA,CAAQ,UAAA;AAAA,IACX,GAAG,0BAA0B,QAAQ;AAAA,GACtC,CAAA,CAAE,MAAA;AACL","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/backend/table-names.ts"],"names":[],"mappings":";;;AAiBO,IAAM,4BAAA,GAA+B;AAE5C,SAAS,0BACP,QAAA,EACwB;AACxB,EAAA,IAAI,QAAA,KAAa,MAAA,EAAW,OAAO,EAAC;AACpC,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,SAAS,CAAA,KAAM,SAAA,KAAc,MAAS;AAAA,GAC5E;AACF;AAYO,SAAS,kBAAA,CACd,SACA,QAAA,EACuB;AACvB,EAAA,OAAO,eAAA,CAAgB;AAAA,IACrB,GAAG,OAAA,CAAQ,UAAA;AAAA,IACX,GAAG,0BAA0B,QAAQ;AAAA,GACtC,CAAA,CAAE,MAAA;AACL","file":"chunk-BABP4D5B.js","sourcesContent":["/**\n * The one owner of \"which physical relations does this offline operation\n * touch?\" for the maintenance entrypoints that accept a `tableNames` override.\n */\nimport {\n createSqlSchema,\n type ResolvedSqlTableNames,\n type SqlTableNames,\n} from \"../query/compiler/schema\";\nimport type { GraphBackend } from \"./types\";\n\n/**\n * Physical name of the legacy single shared embeddings table, dropped in\n * the cross-backend vector cutover (the clean cut of #157). Strategies now\n * own per-`(nodeKind, fieldPath)` typed storage. Retained only so the\n * one-time migration utility can address and drain the old table.\n */\nexport const LEGACY_EMBEDDINGS_TABLE_NAME = \"typegraph_node_embeddings\";\n\nfunction definedTableNameOverrides(\n override: Partial<SqlTableNames> | undefined,\n): Partial<SqlTableNames> {\n if (override === undefined) return {};\n return Object.fromEntries(\n Object.entries(override).filter(([, tableName]) => tableName !== undefined),\n );\n}\n\n/**\n * Resolves the relations an offline maintenance call targets.\n *\n * An override is a PATCH over the backend's own names. This matches the\n * `Partial<SqlTableNames>` input contract: naming only `nodes`, for example,\n * must not silently retarget edges and recorded relations to the built-in\n * defaults. `migrateLegacyRecordedTime` and\n * `repairInvertedValidityWindows` share this owner so an offline write can never\n * resolve the same partial override two different ways.\n */\nexport function resolvedTableNames(\n backend: Pick<GraphBackend, \"tableNames\">,\n override: Partial<SqlTableNames> | undefined,\n): ResolvedSqlTableNames {\n return createSqlSchema({\n ...backend.tableNames,\n ...definedTableNameOverrides(override),\n }).tables;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CLAIMS, UNIQUE_SIDECAR_BATCH, BATCH_POINT_READ, ENDPOINT_SET_READ, STATEMENT_EXECUTION, CONTRIBUTION_HEALTH, RECORDED_REVISION_ORIGINS } from './chunk-
|
|
1
|
+
import { CLAIMS, UNIQUE_SIDECAR_BATCH, BATCH_POINT_READ, ENDPOINT_SET_READ, STATEMENT_EXECUTION, CONTRIBUTION_HEALTH, RECORDED_REVISION_ORIGINS } from './chunk-TU22BFMP.js';
|
|
2
2
|
import { requireDefined, createDataKeyedBag } from './chunk-QD2JFTSL.js';
|
|
3
3
|
import { ConfigurationError } from './chunk-GMKPIYHY.js';
|
|
4
4
|
|
|
@@ -187,5 +187,5 @@ function requireCatalog(backend, operation) {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
export { REVISION_COLUMN_KINDS, WALL_TIME_COLUMN_KINDS, batchPointReadVerdict, claimsVerdict, contributionHealthVerdict, createClaimsVerdictThunk, endpointSetReadVerdict, missingRequiredExtras, recordedRevisionOriginsVerdict, requireCatalog, requireExtras, resolveBundle, statementExecutionVerdict, uniqueSidecarBatchVerdict };
|
|
190
|
-
//# sourceMappingURL=chunk-
|
|
191
|
-
//# sourceMappingURL=chunk-
|
|
190
|
+
//# sourceMappingURL=chunk-BE75G3M5.js.map
|
|
191
|
+
//# sourceMappingURL=chunk-BE75G3M5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/backend/capabilities/resolve.ts","../src/backend/capabilities/catalog.ts"],"names":[],"mappings":"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","file":"chunk-EVGZ2TRQ.js","sourcesContent":["/**\n * The bundle verdict resolver — generalizing `claimSupport`\n * (`store/claims/backing.ts`).\n *\n * Resolution splits in two (ruling B1): the VERDICT — the support decision,\n * resolved once against `GraphBackend` and threaded — and the BINDING\n * (`bind.ts`) — the actual member functions, bound at the call site off\n * whichever port the site holds. A verdict carries names, never functions\n * (I19), so it crosses transaction boundaries safely.\n */\nimport { ConfigurationError } from \"../../errors\";\nimport { createDataKeyedBag } from \"../../utils/object\";\nimport { requireDefined } from \"../../utils/presence\";\nimport { type BackendCapabilities, type GraphBackend } from \"../types\";\nimport {\n BATCH_POINT_READ,\n type CapabilityBundleDefinition,\n type CapabilityBundleDisposition,\n type CapabilityBundleExtra,\n CLAIMS,\n CONTRIBUTION_HEALTH,\n ENDPOINT_SET_READ,\n type OptionalGraphBackendMember,\n RECORDED_REVISION_ORIGINS,\n STATEMENT_EXECUTION,\n UNIQUE_SIDECAR_BATCH,\n} from \"./bundle-registry\";\n\n/**\n * A bundle's extras, as a type-level map from extra id to the UNION of\n * member names that extra covers — derived from the definition's `extras`\n * array by `const` inference, never hand-written.\n */\nexport type CapabilityExtraSpec = Readonly<\n Record<string, OptionalGraphBackendMember>\n>;\n\n/**\n * One extra's verdict. `present: true` carries the member NAMES, not the\n * member functions (ruling B1) — the names are what the accessor binds\n * from, at the site, off the port.\n */\nexport type ExtraVerdict<M extends OptionalGraphBackendMember> =\n | Readonly<{ present: true; members: readonly M[] }>\n | Readonly<{\n present: false;\n missing: readonly M[];\n disposition: CapabilityBundleDisposition;\n }>;\n\n/** The verdict map: one entry per extra id, never a boolean. */\nexport type ExtraVerdicts<X extends CapabilityExtraSpec> = Readonly<{\n [K in keyof X]: ExtraVerdict<X[K]>;\n}>;\n\nexport type GatedBundleVerdict<\n MCore extends OptionalGraphBackendMember,\n X extends CapabilityExtraSpec,\n> =\n | Readonly<{\n supported: true;\n bundle: string;\n /** The core, guaranteed present. Names, not functions. */\n members: readonly MCore[];\n extras: ExtraVerdicts<X>;\n /** The `present: false` keys of `extras`. */\n missingExtras: readonly (keyof X)[];\n }>\n | Readonly<{\n supported: false;\n bundle: string;\n missing: readonly MCore[];\n /** Why it is unsupported: the bundle's own `disposition`, verbatim. */\n disposition: CapabilityBundleDisposition;\n }>;\n\n/** No `supported` field: a graduated bundle has no bundle-level verdict. */\nexport type GraduatedBundleVerdict<X extends CapabilityExtraSpec> = Readonly<{\n bundle: string;\n extras: ExtraVerdicts<X>;\n missingExtras: readonly (keyof X)[];\n}>;\n\n/**\n * Recovers the id→members map from a definition's `extras` TUPLE (not\n * `readonly CapabilityBundleExtra<XId, MExtra>[]` — over the array type the\n * id→members association is erased and `ExtraVerdicts<X>` degenerates to an\n * index signature).\n */\nexport type SpecOf<\n XS extends readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[],\n> = { [K in XS[number] as K[\"id\"]]: K[\"members\"][number] };\n\nexport type ExtrasOf<D extends CapabilityBundleDefinition> = SpecOf<\n NonNullable<D[\"extras\"]>\n>;\nexport type ExtraMember<\n D extends CapabilityBundleDefinition,\n X extends keyof ExtrasOf<D>,\n> = Extract<ExtrasOf<D>[X], OptionalGraphBackendMember>;\n\n/**\n * The definition union and the return-type mapping. Structural, matching\n * `bundle-registry.ts`'s `BundleMembers` helper's own lesson: reading `core`\n * off `D` directly (rather than re-matching `GatedBundleDefinition`) avoids\n * an unmatched `infer` silently widening to the member constraint.\n */\nexport type BundleVerdictOf<D extends CapabilityBundleDefinition> =\n D extends (\n {\n kind: \"graduated\";\n extras: infer XS extends readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[];\n }\n ) ?\n GraduatedBundleVerdict<SpecOf<XS>>\n : D extends (\n {\n kind: \"gated\";\n core: readonly (infer MCore extends OptionalGraphBackendMember)[];\n extras?: infer XS extends\n | readonly CapabilityBundleExtra<string, OptionalGraphBackendMember>[]\n | undefined;\n }\n ) ?\n GatedBundleVerdict<\n MCore,\n SpecOf<\n XS extends (\n readonly CapabilityBundleExtra<string, OptionalGraphBackendMember>[]\n ) ?\n XS\n : []\n >\n >\n : never;\n\nfunction resolveExtras<\n const XS extends readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[],\n>(\n backend: GraphBackend,\n extras: XS,\n): Readonly<{\n extras: ExtraVerdicts<SpecOf<XS>>;\n missingExtras: readonly (keyof SpecOf<XS>)[];\n}> {\n const verdicts =\n createDataKeyedBag<ExtraVerdict<OptionalGraphBackendMember>>();\n const missingExtras: string[] = [];\n for (const extra of extras) {\n const missing = extra.members.filter(\n (member) => backend[member] === undefined,\n );\n if (missing.length === 0) {\n verdicts[extra.id] = { present: true, members: extra.members };\n } else {\n verdicts[extra.id] = {\n present: false,\n missing,\n disposition: extra.disposition,\n };\n missingExtras.push(extra.id);\n }\n }\n return {\n extras: verdicts as ExtraVerdicts<SpecOf<XS>>,\n missingExtras: missingExtras,\n };\n}\n\n/**\n * The `claims` bidirectional cross-check (ruling F2), reproducing\n * `store/claims/backing.ts`'s pre-B7 message text, code and suggestion\n * BYTE-FOR-BYTE. B7 made `claimSupport` (`backing.ts`) delegate to\n * {@link resolveBundle}, so this is now the ONLY place the check runs — there\n * is no second copy left to keep in sync. `bidirectional` is `claims`-only by\n * design (§5.2.1): the two trailing sentences below name \"claim\"/\"fence\"\n * vocabulary that is specific to that one bundle, and a future bundle raising\n * `crossCheck` to `\"bidirectional\"` must carry its own justification row and,\n * with it, its own message pair here.\n *\n * @throws {ConfigurationError} when the declaration and the member surface\n * disagree in either direction.\n */\nfunction assertClaimsBidirectionalAgreement(\n backend: GraphBackend,\n definition: Readonly<{\n declaration?: keyof BackendCapabilities;\n core: readonly OptionalGraphBackendMember[];\n portSurfaceCode: string;\n }>,\n): void {\n if (definition.declaration === undefined) return;\n const declared = backend.capabilities[definition.declaration] === true;\n const present = definition.core.filter(\n (member) => backend[member] !== undefined,\n );\n if (declared && present.length === definition.core.length) return;\n if (!declared && present.length === 0) return;\n\n const missing = definition.core.filter(\n (member) => backend[member] === undefined,\n );\n const declarationName = definition.declaration;\n throw new ConfigurationError(\n declared ?\n `This backend declares \\`${declarationName}: true\\` but does not implement ${missing.join(\", \")}. ` +\n \"A declared constraint would then be written without the fence the declaration promises.\"\n : `This backend implements ${present.join(\", \")} but does not declare \\`${declarationName}: true\\`. ` +\n \"Claim support is read from the declaration, so these members would never be called.\",\n { code: definition.portSurfaceCode, missing, present },\n {\n suggestion:\n declared ?\n `Implement the missing members, or drop \\`${declarationName}\\` from the backend's capabilities.`\n : `Declare \\`${declarationName}: true\\` in the backend's capabilities, or drop the claim members.`,\n },\n );\n}\n\n/**\n * Resolved ONCE, at construction or entry, against the top-level backend —\n * never against a `TransactionBackend` (I15's `@ts-expect-error` row).\n *\n * Rules: the member surface is read always; the declaration is read only\n * when the definition names one AND `crossCheck !== \"none\"` (only `claims`\n * qualifies in the pilot registry); a gated bundle's core must be complete\n * or the bundle is unsupported with `missing`; a graduated bundle has no\n * bundle-level verdict, only per-extra verdicts. `missingExtras` is built by\n * the SAME fold that builds `extras` (one pass, one owner).\n */\nexport function resolveBundle<const D extends CapabilityBundleDefinition>(\n backend: GraphBackend,\n definition: D,\n): BundleVerdictOf<D> {\n const extras = (definition.extras ?? []) as readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[];\n const { extras: extraVerdicts, missingExtras } = resolveExtras(\n backend,\n extras,\n );\n\n // Rule 1: the declaration is read whenever `crossCheck !== \"none\"`,\n // regardless of kind — a graduated bundle's \"core\" for this purpose is the\n // union of every extra's members, since it has no core of its own. Only\n // `claims` (gated) exercises this in the pilot registry, but the check\n // itself must not silently no-op for a hypothetical graduated bidirectional\n // bundle (T11's mutation pins exactly this).\n if (definition.crossCheck === \"bidirectional\") {\n const memberSet =\n definition.kind === \"gated\" ?\n definition.core\n : extras.flatMap((extra) => extra.members);\n assertClaimsBidirectionalAgreement(backend, {\n ...(definition.declaration === undefined ?\n {}\n : { declaration: definition.declaration }),\n core: memberSet,\n portSurfaceCode: definition.portSurfaceCode,\n });\n }\n\n if (definition.kind === \"graduated\") {\n return {\n bundle: definition.id,\n extras: extraVerdicts,\n missingExtras,\n } as unknown as BundleVerdictOf<D>;\n }\n\n const missing = definition.core.filter(\n (member) => backend[member] === undefined,\n );\n if (missing.length > 0) {\n return {\n supported: false,\n bundle: definition.id,\n missing,\n disposition: definition.disposition,\n } as unknown as BundleVerdictOf<D>;\n }\n return {\n supported: true,\n bundle: definition.id,\n members: definition.core,\n extras: extraVerdicts,\n missingExtras,\n } as unknown as BundleVerdictOf<D>;\n}\n\n/** The literal operation names a bundle's `operations` table declares. */\nexport type OperationNames<D extends CapabilityBundleDefinition> =\n D[\"operations\"][number][\"operation\"];\n\n/** The extras a named operation `requires`, read from the ROW — never re-spelled at the call site. */\nexport type RequiredExtrasOf<\n D extends CapabilityBundleDefinition,\n Op extends OperationNames<D>,\n> =\n Extract<D[\"operations\"][number], { operation: Op }> extends (\n { requires: infer R extends readonly string[] }\n ) ?\n R[number]\n : never;\n\n/**\n * The registry's row lookup plus the presence fold, extracted verbatim from\n * {@link requireExtras}'s body (ruling B8 spec item 3): the ONE owner of\n * \"what this operation requires\" that both `requireExtras`'s default throw\n * and a call site's own `refuse` callback consult.\n *\n * `operation` is the literal key of the bundle's `operations` tuple, so the\n * required extras are looked up TYPE-LEVEL from the registry — no second\n * spelling of `requires` at the call site.\n *\n * @throws {ConfigurationError} naming the unknown operation when `operation`\n * is not a row of `definition.operations`.\n */\nexport function missingRequiredExtras<\n const D extends CapabilityBundleDefinition,\n Op extends OperationNames<D>,\n>(\n definition: D,\n verdict: BundleVerdictOf<D>,\n operation: Op,\n): readonly string[] {\n const row = definition.operations.find(\n (candidate) => candidate.operation === operation,\n );\n if (row === undefined) {\n throw new ConfigurationError(\n `Unknown operation \"${operation}\" for capability bundle \"${definition.id}\".`,\n { bundle: definition.id, operation },\n );\n }\n const required = row.requires ?? [];\n const extras:\n | Readonly<Record<string, ExtraVerdict<OptionalGraphBackendMember>>>\n | undefined = \"extras\" in verdict ? verdict.extras : undefined;\n return required.filter(\n (id) => extras === undefined || extras[id]?.present !== true,\n );\n}\n\n/**\n * The refusal for an operation whose `requires` extras are absent — how a\n * GRADUATED bundle refuses where the tree refuses today: the row names the\n * operation and the extras, this asserts they are present, and\n * {@link bindExtra} (`bind.ts`) binds them off the port.\n *\n * `refuse`, when supplied, is called instead of the registry-coded throw\n * below — this is how a call site keeps its OWN existing error text (message,\n * `details` shape, order relative to other refusals) while the registry\n * stays the one owner of \"what this operation requires\" (ruling B8 spec item\n * 3). Omitting it keeps the default behavior byte-identical to before this\n * parameter existed.\n *\n * @throws {ConfigurationError} naming the row's own `code` when one or more\n * required extras is absent from the verdict and no `refuse` callback is\n * supplied; otherwise calls `refuse(missing)`, which never returns.\n */\nexport function requireExtras<\n const D extends CapabilityBundleDefinition,\n Op extends OperationNames<D>,\n>(\n definition: D,\n verdict: BundleVerdictOf<D>,\n operation: Op,\n refuse?: (missing: readonly string[]) => never,\n): asserts verdict is BundleVerdictOf<D> & {\n extras: {\n [K in RequiredExtrasOf<D, Op> & keyof ExtrasOf<D>]: Extract<\n ExtraVerdict<ExtraMember<D, K>>,\n { present: true }\n >;\n };\n} {\n const missing = missingRequiredExtras(definition, verdict, operation);\n if (missing.length === 0) return;\n\n if (refuse !== undefined) refuse(missing);\n\n // `missingRequiredExtras` already threw the unknown-operation error above\n // when the row would be undefined, so `requireDefined` here is a redundant\n // (never-failing) narrowing, not a second lookup that could disagree.\n const { disposition } = requireDefined(\n definition.operations.find(\n (candidate) => candidate.operation === operation,\n ),\n );\n if (disposition.kind === \"refuse\") {\n throw new ConfigurationError(\n `Operation \"${operation}\" on capability bundle \"${definition.id}\" requires ${missing.join(\", \")}.`,\n { code: disposition.code, bundle: definition.id, operation, missing },\n );\n }\n // No pilot row reaches this: every row with a non-empty `requires` in the\n // registry disposes `refuse` (a graduated bundle's fallback rows never\n // name `requires` — the fallback IS the degrade path). Kept as a named,\n // typed refusal rather than a silent pass so a future `fallback` +\n // `requires` row cannot pass `requireExtras` unnoticed.\n throw new ConfigurationError(\n `Operation \"${operation}\" on capability bundle \"${definition.id}\" requires ${missing.join(\", \")}, and the registry names no refusal code for this fallback-dispositioned row.`,\n { bundle: definition.id, operation, missing },\n );\n}\n\n// ---------------------------------------------------------------------------\n// The seven named verdict accessors — GraphBackend-only, no exceptions (I15).\n// ---------------------------------------------------------------------------\n\nexport function claimsVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof CLAIMS> {\n return resolveBundle(backend, CLAIMS);\n}\n\nexport function uniqueSidecarBatchVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH> {\n return resolveBundle(backend, UNIQUE_SIDECAR_BATCH);\n}\n\nexport function batchPointReadVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof BATCH_POINT_READ> {\n return resolveBundle(backend, BATCH_POINT_READ);\n}\n\nexport function endpointSetReadVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof ENDPOINT_SET_READ> {\n return resolveBundle(backend, ENDPOINT_SET_READ);\n}\n\nexport function statementExecutionVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof STATEMENT_EXECUTION> {\n return resolveBundle(backend, STATEMENT_EXECUTION);\n}\n\nexport function contributionHealthVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof CONTRIBUTION_HEALTH> {\n return resolveBundle(backend, CONTRIBUTION_HEALTH);\n}\n\nexport function recordedRevisionOriginsVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof RECORDED_REVISION_ORIGINS> {\n return resolveBundle(backend, RECORDED_REVISION_ORIGINS);\n}\n\n// ---------------------------------------------------------------------------\n// The claims verdict THUNK — the reference implementation of §5.2.3's INTENT\n// (one owner, at-most-once resolution, no re-derivation) moved to WHEN it\n// resolves rather than IF (ruling B7 refinement 2).\n// ---------------------------------------------------------------------------\n\n/**\n * A memoized, at-most-once resolution of the `claims` bundle's verdict\n * against ONE backend.\n *\n * Eager resolution at store construction is forbidden: T14's\n * contradictory-declaration backends must still be able to construct a store\n * and create nodes — only a constrained edge write may legally reach the\n * bidirectional cross-check's throw, and it must do so lazily, at the first\n * write that needs the verdict.\n *\n * A cached verdict cannot go stale because `GraphBackend` is deep-frozen (B1):\n * nothing can flip `capabilities.constraintClaims` or add/remove a claim\n * member on a backend object after this thunk has already resolved it, so\n * \"resolve once and reuse forever\" is exactly as safe as \"resolve every\n * time\" — for one backend object, they observe the same immutable answer.\n */\nexport type ClaimsVerdictThunk = () => BundleVerdictOf<typeof CLAIMS>;\n\n/**\n * Interning: the same backend object always gets back the SAME thunk object.\n * This is what makes \"one shared thunk per backend\" structural rather than a\n * convention every population site has to honor — a second call to\n * {@link createClaimsVerdictThunk} for a backend already minted cannot produce\n * a second, independently-memoized verdict.\n */\nconst CLAIMS_VERDICT_THUNKS = new WeakMap<GraphBackend, ClaimsVerdictThunk>();\n\n/**\n * Mints — or returns the already-minted — {@link ClaimsVerdictThunk} for\n * `backend`.\n *\n * The thunk resolves {@link resolveBundle}`(backend, CLAIMS)` on its first\n * call and caches the outcome, INCLUDING a thrown `ConfigurationError`: a\n * refusal is cached and re-thrown on every subsequent call, never\n * re-resolved. Both layers — interning here, memoization inside the thunk —\n * are required: interning alone would still let two independently-memoized\n * thunks exist for one backend if a caller ignored the shared one; memoizing\n * alone would still let two different call sites mint two different thunks\n * that could disagree about whether they had already resolved.\n */\nexport function createClaimsVerdictThunk(\n backend: GraphBackend,\n): ClaimsVerdictThunk {\n const existing = CLAIMS_VERDICT_THUNKS.get(backend);\n if (existing !== undefined) return existing;\n\n type Memo =\n | Readonly<{ state: \"resolved\"; verdict: BundleVerdictOf<typeof CLAIMS> }>\n | Readonly<{ state: \"thrown\"; error: unknown }>;\n let memo: Memo | undefined;\n\n const thunk: ClaimsVerdictThunk = () => {\n if (memo === undefined) {\n try {\n memo = { state: \"resolved\", verdict: resolveBundle(backend, CLAIMS) };\n } catch (error) {\n memo = { state: \"thrown\", error };\n throw error;\n }\n }\n if (memo.state === \"thrown\") throw memo.error;\n return memo.verdict;\n };\n\n CLAIMS_VERDICT_THUNKS.set(backend, thunk);\n return thunk;\n}\n","/**\n * The backend's optional catalog-introspection surface: physical-schema\n * probes a store path consults directly, spelled once per dialect by the\n * two bundled profiles instead of a `dialect === \"postgres\"` branch at each\n * call site.\n *\n * Every member is a read-only probe except `dropInvalidIndex`, which issues\n * the one DDL statement that heals a crashed concurrent index build.\n * Nothing here writes a graph row, a sidecar row, or a status row.\n */\nimport { ConfigurationError } from \"../../errors\";\nimport { type GraphBackend } from \"../types\";\n\n/**\n * A physical index's presence and, on engines that can leave a build\n * half-finished, whether the leftover is usable.\n *\n * `invalid` is PostgreSQL's `pg_index.indisvalid = false` — an interrupted\n * `CREATE INDEX CONCURRENTLY` leaves a same-named index behind that a later\n * `IF NOT EXISTS` build would otherwise accept silently. SQLite has no such\n * state: `invalid` is always `false` there, and `exists` alone is the whole\n * answer.\n */\nexport type IndexState = Readonly<{\n /** The physical SQL index name that was probed. */\n name: string;\n /** Whether an index with this name exists in the engine catalog. */\n exists: boolean;\n /** PostgreSQL's invalid-build leftover flag; always `false` on SQLite. */\n invalid: boolean;\n}>;\n\n/**\n * A physical column's declared type, reduced to the family the two callers\n * that classify a recorded-time column actually distinguish: an integer\n * counter, text (SQLite's affinity for a wall-clock column stored as an\n * ISO-8601 string), PostgreSQL's exact `timestamp with time zone`, or\n * anything else. Kept this coarse on purpose — no caller needs a finer\n * classification, and each dialect's own probe decides which of these a\n * given declared type maps to, using that engine's own type rules (exact\n * match on PostgreSQL, affinity on SQLite).\n *\n * PostgreSQL's own normalizer never reports `\"text\"` — a declared `text`\n * column on that dialect falls through to `\"other\"`, since nothing\n * PostgreSQL-side stores a recorded-time column that way. That asymmetry is\n * why a revision or wall-time comparison must compare against\n * {@link REVISION_COLUMN_KINDS} / {@link WALL_TIME_COLUMN_KINDS} rather than\n * a single literal: the two dialects agree on the revision kind but not on\n * the wall-time one.\n */\nexport type NormalizedColumnKind =\n \"integer\" | \"text\" | \"timestamp-with-time-zone\" | \"other\";\n\n/**\n * The `columnTypes` kinds that count as a revision counter. Both dialects\n * normalize one to `\"integer\"`, so this is a single-member set today — named\n * and exported so a caller compares against ONE owned set instead of\n * re-spelling `=== \"integer\"` inline. Consumed by\n * `store/recorded-capture/schema-version.ts`'s `isCompatibleColumnKind`,\n * which replaced that file's dialect-branching `isCompatibleColumnType` and\n * its SQLite-affinity twin (`hasSqliteAffinity`) with this owned set.\n */\nexport const REVISION_COLUMN_KINDS: readonly NormalizedColumnKind[] = [\n \"integer\",\n];\n\n/**\n * The `columnTypes` kinds that count as a wall-clock timestamp. SQLite\n * stores one as an ISO-8601 string (`\"text\"`); PostgreSQL stores one as\n * `timestamp with time zone` (`\"timestamp-with-time-zone\"`) and never\n * normalizes a declared column to `\"text\"` at all — so this set stays exact\n * on both dialects without a caller ever branching on `dialect`. Consumed\n * by `store/recorded-capture/schema-version.ts`'s `isCompatibleColumnKind`,\n * alongside {@link REVISION_COLUMN_KINDS}.\n */\nexport const WALL_TIME_COLUMN_KINDS: readonly NormalizedColumnKind[] = [\n \"text\",\n \"timestamp-with-time-zone\",\n];\n\n/**\n * One physical column's name, normalized type family, and raw declared\n * type — trimmed and lower-cased, but otherwise exactly what the engine's\n * own catalog reports (`\"bigint\"`, `\"timestamp with time zone\"`, a SQLite\n * declared type such as `\"integer\"` or `\"text\"`, and so on). `kind` is what\n * a comparison should classify against; `declaredType` is what a\n * diagnostic should show a human, since `kind` discards the declared\n * spelling entirely.\n */\nexport type CatalogColumn = Readonly<{\n name: string;\n kind: NormalizedColumnKind;\n declaredType: string;\n}>;\n\n/** One physical table's catalog presence. See {@link BackendCatalogProbes.tablesExist}. */\nexport type TableState = Readonly<{\n /** The physical SQL table name that was probed. */\n name: string;\n /** Whether a table with this name exists in the engine catalog. */\n exists: boolean;\n}>;\n\n/**\n * The three facts index materialization used to keep in its own\n * dialect-keyed record: whether this engine can build an index\n * concurrently (without blocking readers/writers), whether a concurrent\n * build can be interrupted into a usable-but-invalid leftover, and whether\n * it offers the GIN index family fulltext/trigram indexing needs.\n */\nexport type CatalogIndexBehavior = Readonly<{\n concurrentBuilds: boolean;\n hasInvalidIndexState: boolean;\n supportsGinFamily: boolean;\n}>;\n\n/**\n * Physical-schema introspection a store path consults directly: table and\n * index presence, PostgreSQL's invalid-index leftover state and its\n * self-heal, normalized column types, and the per-dialect index-build\n * facts above.\n *\n * Optional: a custom backend that omits it loses the store paths that\n * consult it directly — index materialization (`store.materializeIndexes()`\n * refuses only once its empty-candidate short circuit and the status-table\n * ensure step have already run; `store.materializeSystemIndexes()`, which\n * has no candidate short circuit, refuses only once that same status-table\n * ensure step has run), the recorded-time schema check, and the\n * recorded-time migration's column read.\n */\nexport type BackendCatalogProbes = Readonly<{\n /**\n * Whether a table with this physical name exists in the engine catalog —\n * on PostgreSQL, anything an unqualified `DELETE`/`ANALYZE` against the\n * name could hit (ordinary and partitioned tables, views, materialized\n * views, foreign tables), matching the dialect operation strategy's own\n * DDL-target probe. A caller that means specifically \"is this a TABLE\",\n * as opposed to any relation an unqualified statement could resolve to,\n * wants {@link BackendCatalogProbes.tablesExist} instead — its narrower\n * predicate excludes views, materialized views, and foreign tables.\n */\n tableExists: (this: void, name: string) => Promise<boolean>;\n /**\n * The catalog state of each named physical TABLE, one entry per input\n * name (an absent name reports `exists: false`), resolved in one round\n * trip. On PostgreSQL this is ordinary and partitioned tables only\n * (`relkind IN ('r', 'p')`) — narrower than {@link tableExists}, which\n * also matches views, materialized views, and foreign tables. A caller\n * gating bulk, table-scoped work (a preload ahead of table DDL, say)\n * wants this member so it gets one round trip and the strict predicate,\n * rather than looping {@link tableExists} or accepting its wider match.\n */\n tablesExist: (\n this: void,\n names: readonly string[],\n ) => Promise<readonly TableState[]>;\n /**\n * The catalog state of each named physical index, one entry per input\n * name (an absent index reports `exists: false`), resolved in one\n * round trip.\n */\n indexStates: (\n this: void,\n names: readonly string[],\n ) => Promise<readonly IndexState[]>;\n /**\n * Drops the named index if — and only if — it is a PostgreSQL INVALID\n * leftover from an interrupted `CREATE INDEX CONCURRENTLY`. A no-op on\n * an engine whose `indexBehavior.hasInvalidIndexState` is `false`, and\n * a no-op for a valid or absent index on every engine.\n *\n * A ROOT-BACKEND operation on an engine with an invalid-index state:\n * PostgreSQL refuses `DROP INDEX CONCURRENTLY` inside a transaction\n * block, so there the `catalog` a `transaction()` handle exposes throws a\n * typed `ConfigurationError` from this member instead of attempting the\n * DDL. An engine whose `indexBehavior.hasInvalidIndexState` is `false`\n * (SQLite) has no invalid leftover to ever drop and stays a no-op in\n * both scopes — every other member here stays a plain read on that same\n * transaction-scoped bag regardless of engine.\n */\n dropInvalidIndex: (this: void, name: string) => Promise<void>;\n /** Every column's name and normalized type family for one physical table. */\n columnTypes: (this: void, table: string) => Promise<readonly CatalogColumn[]>;\n /** This engine's index-build facts. See {@link CatalogIndexBehavior}. */\n indexBehavior: CatalogIndexBehavior;\n}>;\n\n/**\n * THE refusal for a store path that needs the backend's catalog probes and\n * finds them absent, naming the missing port so a caller can add it — or\n * switch to a bundled backend — instead of chasing a `TypeError` two calls\n * deep into `materializeIndexes` or a recorded-time migration.\n */\nexport function requireCatalog(\n backend: Pick<GraphBackend, \"catalog\">,\n operation: string,\n): BackendCatalogProbes {\n const catalog = backend.catalog;\n if (catalog === undefined) {\n throw new ConfigurationError(\n `${operation} requires the backend's catalog probes, but this backend declares no \\`catalog\\`.`,\n { code: \"CATALOG_UNAVAILABLE\", operation },\n {\n suggestion:\n \"Implement `catalog` on this backend, or use a built-in SQLite or PostgreSQL backend.\",\n },\n );\n }\n return catalog;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/backend/capabilities/resolve.ts","../src/backend/capabilities/catalog.ts"],"names":[],"mappings":"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","file":"chunk-BE75G3M5.js","sourcesContent":["/**\n * The bundle verdict resolver — generalizing `claimSupport`\n * (`store/claims/backing.ts`).\n *\n * Resolution splits in two (ruling B1): the VERDICT — the support decision,\n * resolved once against `GraphBackend` and threaded — and the BINDING\n * (`bind.ts`) — the actual member functions, bound at the call site off\n * whichever port the site holds. A verdict carries names, never functions\n * (I19), so it crosses transaction boundaries safely.\n */\nimport { ConfigurationError } from \"../../errors\";\nimport { createDataKeyedBag } from \"../../utils/object\";\nimport { requireDefined } from \"../../utils/presence\";\nimport { type BackendCapabilities, type GraphBackend } from \"../types\";\nimport {\n BATCH_POINT_READ,\n type CapabilityBundleDefinition,\n type CapabilityBundleDisposition,\n type CapabilityBundleExtra,\n CLAIMS,\n CONTRIBUTION_HEALTH,\n ENDPOINT_SET_READ,\n type OptionalGraphBackendMember,\n RECORDED_REVISION_ORIGINS,\n STATEMENT_EXECUTION,\n UNIQUE_SIDECAR_BATCH,\n} from \"./bundle-registry\";\n\n/**\n * A bundle's extras, as a type-level map from extra id to the UNION of\n * member names that extra covers — derived from the definition's `extras`\n * array by `const` inference, never hand-written.\n */\nexport type CapabilityExtraSpec = Readonly<\n Record<string, OptionalGraphBackendMember>\n>;\n\n/**\n * One extra's verdict. `present: true` carries the member NAMES, not the\n * member functions (ruling B1) — the names are what the accessor binds\n * from, at the site, off the port.\n */\nexport type ExtraVerdict<M extends OptionalGraphBackendMember> =\n | Readonly<{ present: true; members: readonly M[] }>\n | Readonly<{\n present: false;\n missing: readonly M[];\n disposition: CapabilityBundleDisposition;\n }>;\n\n/** The verdict map: one entry per extra id, never a boolean. */\nexport type ExtraVerdicts<X extends CapabilityExtraSpec> = Readonly<{\n [K in keyof X]: ExtraVerdict<X[K]>;\n}>;\n\nexport type GatedBundleVerdict<\n MCore extends OptionalGraphBackendMember,\n X extends CapabilityExtraSpec,\n> =\n | Readonly<{\n supported: true;\n bundle: string;\n /** The core, guaranteed present. Names, not functions. */\n members: readonly MCore[];\n extras: ExtraVerdicts<X>;\n /** The `present: false` keys of `extras`. */\n missingExtras: readonly (keyof X)[];\n }>\n | Readonly<{\n supported: false;\n bundle: string;\n missing: readonly MCore[];\n /** Why it is unsupported: the bundle's own `disposition`, verbatim. */\n disposition: CapabilityBundleDisposition;\n }>;\n\n/** No `supported` field: a graduated bundle has no bundle-level verdict. */\nexport type GraduatedBundleVerdict<X extends CapabilityExtraSpec> = Readonly<{\n bundle: string;\n extras: ExtraVerdicts<X>;\n missingExtras: readonly (keyof X)[];\n}>;\n\n/**\n * Recovers the id→members map from a definition's `extras` TUPLE (not\n * `readonly CapabilityBundleExtra<XId, MExtra>[]` — over the array type the\n * id→members association is erased and `ExtraVerdicts<X>` degenerates to an\n * index signature).\n */\nexport type SpecOf<\n XS extends readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[],\n> = { [K in XS[number] as K[\"id\"]]: K[\"members\"][number] };\n\nexport type ExtrasOf<D extends CapabilityBundleDefinition> = SpecOf<\n NonNullable<D[\"extras\"]>\n>;\nexport type ExtraMember<\n D extends CapabilityBundleDefinition,\n X extends keyof ExtrasOf<D>,\n> = Extract<ExtrasOf<D>[X], OptionalGraphBackendMember>;\n\n/**\n * The definition union and the return-type mapping. Structural, matching\n * `bundle-registry.ts`'s `BundleMembers` helper's own lesson: reading `core`\n * off `D` directly (rather than re-matching `GatedBundleDefinition`) avoids\n * an unmatched `infer` silently widening to the member constraint.\n */\nexport type BundleVerdictOf<D extends CapabilityBundleDefinition> =\n D extends (\n {\n kind: \"graduated\";\n extras: infer XS extends readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[];\n }\n ) ?\n GraduatedBundleVerdict<SpecOf<XS>>\n : D extends (\n {\n kind: \"gated\";\n core: readonly (infer MCore extends OptionalGraphBackendMember)[];\n extras?: infer XS extends\n | readonly CapabilityBundleExtra<string, OptionalGraphBackendMember>[]\n | undefined;\n }\n ) ?\n GatedBundleVerdict<\n MCore,\n SpecOf<\n XS extends (\n readonly CapabilityBundleExtra<string, OptionalGraphBackendMember>[]\n ) ?\n XS\n : []\n >\n >\n : never;\n\nfunction resolveExtras<\n const XS extends readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[],\n>(\n backend: GraphBackend,\n extras: XS,\n): Readonly<{\n extras: ExtraVerdicts<SpecOf<XS>>;\n missingExtras: readonly (keyof SpecOf<XS>)[];\n}> {\n const verdicts =\n createDataKeyedBag<ExtraVerdict<OptionalGraphBackendMember>>();\n const missingExtras: string[] = [];\n for (const extra of extras) {\n const missing = extra.members.filter(\n (member) => backend[member] === undefined,\n );\n if (missing.length === 0) {\n verdicts[extra.id] = { present: true, members: extra.members };\n } else {\n verdicts[extra.id] = {\n present: false,\n missing,\n disposition: extra.disposition,\n };\n missingExtras.push(extra.id);\n }\n }\n return {\n extras: verdicts as ExtraVerdicts<SpecOf<XS>>,\n missingExtras: missingExtras,\n };\n}\n\n/**\n * The `claims` bidirectional cross-check (ruling F2), reproducing\n * `store/claims/backing.ts`'s pre-B7 message text, code and suggestion\n * BYTE-FOR-BYTE. B7 made `claimSupport` (`backing.ts`) delegate to\n * {@link resolveBundle}, so this is now the ONLY place the check runs — there\n * is no second copy left to keep in sync. `bidirectional` is `claims`-only by\n * design (§5.2.1): the two trailing sentences below name \"claim\"/\"fence\"\n * vocabulary that is specific to that one bundle, and a future bundle raising\n * `crossCheck` to `\"bidirectional\"` must carry its own justification row and,\n * with it, its own message pair here.\n *\n * @throws {ConfigurationError} when the declaration and the member surface\n * disagree in either direction.\n */\nfunction assertClaimsBidirectionalAgreement(\n backend: GraphBackend,\n definition: Readonly<{\n declaration?: keyof BackendCapabilities;\n core: readonly OptionalGraphBackendMember[];\n portSurfaceCode: string;\n }>,\n): void {\n if (definition.declaration === undefined) return;\n const declared = backend.capabilities[definition.declaration] === true;\n const present = definition.core.filter(\n (member) => backend[member] !== undefined,\n );\n if (declared && present.length === definition.core.length) return;\n if (!declared && present.length === 0) return;\n\n const missing = definition.core.filter(\n (member) => backend[member] === undefined,\n );\n const declarationName = definition.declaration;\n throw new ConfigurationError(\n declared ?\n `This backend declares \\`${declarationName}: true\\` but does not implement ${missing.join(\", \")}. ` +\n \"A declared constraint would then be written without the fence the declaration promises.\"\n : `This backend implements ${present.join(\", \")} but does not declare \\`${declarationName}: true\\`. ` +\n \"Claim support is read from the declaration, so these members would never be called.\",\n { code: definition.portSurfaceCode, missing, present },\n {\n suggestion:\n declared ?\n `Implement the missing members, or drop \\`${declarationName}\\` from the backend's capabilities.`\n : `Declare \\`${declarationName}: true\\` in the backend's capabilities, or drop the claim members.`,\n },\n );\n}\n\n/**\n * Resolved ONCE, at construction or entry, against the top-level backend —\n * never against a `TransactionBackend` (I15's `@ts-expect-error` row).\n *\n * Rules: the member surface is read always; the declaration is read only\n * when the definition names one AND `crossCheck !== \"none\"` (only `claims`\n * qualifies in the pilot registry); a gated bundle's core must be complete\n * or the bundle is unsupported with `missing`; a graduated bundle has no\n * bundle-level verdict, only per-extra verdicts. `missingExtras` is built by\n * the SAME fold that builds `extras` (one pass, one owner).\n */\nexport function resolveBundle<const D extends CapabilityBundleDefinition>(\n backend: GraphBackend,\n definition: D,\n): BundleVerdictOf<D> {\n const extras = (definition.extras ?? []) as readonly CapabilityBundleExtra<\n string,\n OptionalGraphBackendMember\n >[];\n const { extras: extraVerdicts, missingExtras } = resolveExtras(\n backend,\n extras,\n );\n\n // Rule 1: the declaration is read whenever `crossCheck !== \"none\"`,\n // regardless of kind — a graduated bundle's \"core\" for this purpose is the\n // union of every extra's members, since it has no core of its own. Only\n // `claims` (gated) exercises this in the pilot registry, but the check\n // itself must not silently no-op for a hypothetical graduated bidirectional\n // bundle (T11's mutation pins exactly this).\n if (definition.crossCheck === \"bidirectional\") {\n const memberSet =\n definition.kind === \"gated\" ?\n definition.core\n : extras.flatMap((extra) => extra.members);\n assertClaimsBidirectionalAgreement(backend, {\n ...(definition.declaration === undefined ?\n {}\n : { declaration: definition.declaration }),\n core: memberSet,\n portSurfaceCode: definition.portSurfaceCode,\n });\n }\n\n if (definition.kind === \"graduated\") {\n return {\n bundle: definition.id,\n extras: extraVerdicts,\n missingExtras,\n } as unknown as BundleVerdictOf<D>;\n }\n\n const missing = definition.core.filter(\n (member) => backend[member] === undefined,\n );\n if (missing.length > 0) {\n return {\n supported: false,\n bundle: definition.id,\n missing,\n disposition: definition.disposition,\n } as unknown as BundleVerdictOf<D>;\n }\n return {\n supported: true,\n bundle: definition.id,\n members: definition.core,\n extras: extraVerdicts,\n missingExtras,\n } as unknown as BundleVerdictOf<D>;\n}\n\n/** The literal operation names a bundle's `operations` table declares. */\nexport type OperationNames<D extends CapabilityBundleDefinition> =\n D[\"operations\"][number][\"operation\"];\n\n/** The extras a named operation `requires`, read from the ROW — never re-spelled at the call site. */\nexport type RequiredExtrasOf<\n D extends CapabilityBundleDefinition,\n Op extends OperationNames<D>,\n> =\n Extract<D[\"operations\"][number], { operation: Op }> extends (\n { requires: infer R extends readonly string[] }\n ) ?\n R[number]\n : never;\n\n/**\n * The registry's row lookup plus the presence fold, extracted verbatim from\n * {@link requireExtras}'s body (ruling B8 spec item 3): the ONE owner of\n * \"what this operation requires\" that both `requireExtras`'s default throw\n * and a call site's own `refuse` callback consult.\n *\n * `operation` is the literal key of the bundle's `operations` tuple, so the\n * required extras are looked up TYPE-LEVEL from the registry — no second\n * spelling of `requires` at the call site.\n *\n * @throws {ConfigurationError} naming the unknown operation when `operation`\n * is not a row of `definition.operations`.\n */\nexport function missingRequiredExtras<\n const D extends CapabilityBundleDefinition,\n Op extends OperationNames<D>,\n>(\n definition: D,\n verdict: BundleVerdictOf<D>,\n operation: Op,\n): readonly string[] {\n const row = definition.operations.find(\n (candidate) => candidate.operation === operation,\n );\n if (row === undefined) {\n throw new ConfigurationError(\n `Unknown operation \"${operation}\" for capability bundle \"${definition.id}\".`,\n { bundle: definition.id, operation },\n );\n }\n const required = row.requires ?? [];\n const extras:\n | Readonly<Record<string, ExtraVerdict<OptionalGraphBackendMember>>>\n | undefined = \"extras\" in verdict ? verdict.extras : undefined;\n return required.filter(\n (id) => extras === undefined || extras[id]?.present !== true,\n );\n}\n\n/**\n * The refusal for an operation whose `requires` extras are absent — how a\n * GRADUATED bundle refuses where the tree refuses today: the row names the\n * operation and the extras, this asserts they are present, and\n * {@link bindExtra} (`bind.ts`) binds them off the port.\n *\n * `refuse`, when supplied, is called instead of the registry-coded throw\n * below — this is how a call site keeps its OWN existing error text (message,\n * `details` shape, order relative to other refusals) while the registry\n * stays the one owner of \"what this operation requires\" (ruling B8 spec item\n * 3). Omitting it keeps the default behavior byte-identical to before this\n * parameter existed.\n *\n * @throws {ConfigurationError} naming the row's own `code` when one or more\n * required extras is absent from the verdict and no `refuse` callback is\n * supplied; otherwise calls `refuse(missing)`, which never returns.\n */\nexport function requireExtras<\n const D extends CapabilityBundleDefinition,\n Op extends OperationNames<D>,\n>(\n definition: D,\n verdict: BundleVerdictOf<D>,\n operation: Op,\n refuse?: (missing: readonly string[]) => never,\n): asserts verdict is BundleVerdictOf<D> & {\n extras: {\n [K in RequiredExtrasOf<D, Op> & keyof ExtrasOf<D>]: Extract<\n ExtraVerdict<ExtraMember<D, K>>,\n { present: true }\n >;\n };\n} {\n const missing = missingRequiredExtras(definition, verdict, operation);\n if (missing.length === 0) return;\n\n if (refuse !== undefined) refuse(missing);\n\n // `missingRequiredExtras` already threw the unknown-operation error above\n // when the row would be undefined, so `requireDefined` here is a redundant\n // (never-failing) narrowing, not a second lookup that could disagree.\n const { disposition } = requireDefined(\n definition.operations.find(\n (candidate) => candidate.operation === operation,\n ),\n );\n if (disposition.kind === \"refuse\") {\n throw new ConfigurationError(\n `Operation \"${operation}\" on capability bundle \"${definition.id}\" requires ${missing.join(\", \")}.`,\n { code: disposition.code, bundle: definition.id, operation, missing },\n );\n }\n // No pilot row reaches this: every row with a non-empty `requires` in the\n // registry disposes `refuse` (a graduated bundle's fallback rows never\n // name `requires` — the fallback IS the degrade path). Kept as a named,\n // typed refusal rather than a silent pass so a future `fallback` +\n // `requires` row cannot pass `requireExtras` unnoticed.\n throw new ConfigurationError(\n `Operation \"${operation}\" on capability bundle \"${definition.id}\" requires ${missing.join(\", \")}, and the registry names no refusal code for this fallback-dispositioned row.`,\n { bundle: definition.id, operation, missing },\n );\n}\n\n// ---------------------------------------------------------------------------\n// The seven named verdict accessors — GraphBackend-only, no exceptions (I15).\n// ---------------------------------------------------------------------------\n\nexport function claimsVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof CLAIMS> {\n return resolveBundle(backend, CLAIMS);\n}\n\nexport function uniqueSidecarBatchVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof UNIQUE_SIDECAR_BATCH> {\n return resolveBundle(backend, UNIQUE_SIDECAR_BATCH);\n}\n\nexport function batchPointReadVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof BATCH_POINT_READ> {\n return resolveBundle(backend, BATCH_POINT_READ);\n}\n\nexport function endpointSetReadVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof ENDPOINT_SET_READ> {\n return resolveBundle(backend, ENDPOINT_SET_READ);\n}\n\nexport function statementExecutionVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof STATEMENT_EXECUTION> {\n return resolveBundle(backend, STATEMENT_EXECUTION);\n}\n\nexport function contributionHealthVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof CONTRIBUTION_HEALTH> {\n return resolveBundle(backend, CONTRIBUTION_HEALTH);\n}\n\nexport function recordedRevisionOriginsVerdict(\n backend: GraphBackend,\n): BundleVerdictOf<typeof RECORDED_REVISION_ORIGINS> {\n return resolveBundle(backend, RECORDED_REVISION_ORIGINS);\n}\n\n// ---------------------------------------------------------------------------\n// The claims verdict THUNK — the reference implementation of §5.2.3's INTENT\n// (one owner, at-most-once resolution, no re-derivation) moved to WHEN it\n// resolves rather than IF (ruling B7 refinement 2).\n// ---------------------------------------------------------------------------\n\n/**\n * A memoized, at-most-once resolution of the `claims` bundle's verdict\n * against ONE backend.\n *\n * Eager resolution at store construction is forbidden: T14's\n * contradictory-declaration backends must still be able to construct a store\n * and create nodes — only a constrained edge write may legally reach the\n * bidirectional cross-check's throw, and it must do so lazily, at the first\n * write that needs the verdict.\n *\n * A cached verdict cannot go stale because `GraphBackend` is deep-frozen (B1):\n * nothing can flip `capabilities.constraintClaims` or add/remove a claim\n * member on a backend object after this thunk has already resolved it, so\n * \"resolve once and reuse forever\" is exactly as safe as \"resolve every\n * time\" — for one backend object, they observe the same immutable answer.\n */\nexport type ClaimsVerdictThunk = () => BundleVerdictOf<typeof CLAIMS>;\n\n/**\n * Interning: the same backend object always gets back the SAME thunk object.\n * This is what makes \"one shared thunk per backend\" structural rather than a\n * convention every population site has to honor — a second call to\n * {@link createClaimsVerdictThunk} for a backend already minted cannot produce\n * a second, independently-memoized verdict.\n */\nconst CLAIMS_VERDICT_THUNKS = new WeakMap<GraphBackend, ClaimsVerdictThunk>();\n\n/**\n * Mints — or returns the already-minted — {@link ClaimsVerdictThunk} for\n * `backend`.\n *\n * The thunk resolves {@link resolveBundle}`(backend, CLAIMS)` on its first\n * call and caches the outcome, INCLUDING a thrown `ConfigurationError`: a\n * refusal is cached and re-thrown on every subsequent call, never\n * re-resolved. Both layers — interning here, memoization inside the thunk —\n * are required: interning alone would still let two independently-memoized\n * thunks exist for one backend if a caller ignored the shared one; memoizing\n * alone would still let two different call sites mint two different thunks\n * that could disagree about whether they had already resolved.\n */\nexport function createClaimsVerdictThunk(\n backend: GraphBackend,\n): ClaimsVerdictThunk {\n const existing = CLAIMS_VERDICT_THUNKS.get(backend);\n if (existing !== undefined) return existing;\n\n type Memo =\n | Readonly<{ state: \"resolved\"; verdict: BundleVerdictOf<typeof CLAIMS> }>\n | Readonly<{ state: \"thrown\"; error: unknown }>;\n let memo: Memo | undefined;\n\n const thunk: ClaimsVerdictThunk = () => {\n if (memo === undefined) {\n try {\n memo = { state: \"resolved\", verdict: resolveBundle(backend, CLAIMS) };\n } catch (error) {\n memo = { state: \"thrown\", error };\n throw error;\n }\n }\n if (memo.state === \"thrown\") throw memo.error;\n return memo.verdict;\n };\n\n CLAIMS_VERDICT_THUNKS.set(backend, thunk);\n return thunk;\n}\n","/**\n * The backend's optional catalog-introspection surface: physical-schema\n * probes a store path consults directly, spelled once per dialect by the\n * two bundled profiles instead of a `dialect === \"postgres\"` branch at each\n * call site.\n *\n * Every member is a read-only probe except `dropInvalidIndex`, which issues\n * the one DDL statement that heals a crashed concurrent index build.\n * Nothing here writes a graph row, a sidecar row, or a status row.\n */\nimport { ConfigurationError } from \"../../errors\";\nimport { type GraphBackend } from \"../types\";\n\n/**\n * A physical index's presence and, on engines that can leave a build\n * half-finished, whether the leftover is usable.\n *\n * `invalid` is PostgreSQL's `pg_index.indisvalid = false` — an interrupted\n * `CREATE INDEX CONCURRENTLY` leaves a same-named index behind that a later\n * `IF NOT EXISTS` build would otherwise accept silently. SQLite has no such\n * state: `invalid` is always `false` there, and `exists` alone is the whole\n * answer.\n */\nexport type IndexState = Readonly<{\n /** The physical SQL index name that was probed. */\n name: string;\n /** Whether an index with this name exists in the engine catalog. */\n exists: boolean;\n /** PostgreSQL's invalid-build leftover flag; always `false` on SQLite. */\n invalid: boolean;\n}>;\n\n/**\n * A physical column's declared type, reduced to the family the two callers\n * that classify a recorded-time column actually distinguish: an integer\n * counter, text (SQLite's affinity for a wall-clock column stored as an\n * ISO-8601 string), PostgreSQL's exact `timestamp with time zone`, or\n * anything else. Kept this coarse on purpose — no caller needs a finer\n * classification, and each dialect's own probe decides which of these a\n * given declared type maps to, using that engine's own type rules (exact\n * match on PostgreSQL, affinity on SQLite).\n *\n * PostgreSQL's own normalizer never reports `\"text\"` — a declared `text`\n * column on that dialect falls through to `\"other\"`, since nothing\n * PostgreSQL-side stores a recorded-time column that way. That asymmetry is\n * why a revision or wall-time comparison must compare against\n * {@link REVISION_COLUMN_KINDS} / {@link WALL_TIME_COLUMN_KINDS} rather than\n * a single literal: the two dialects agree on the revision kind but not on\n * the wall-time one.\n */\nexport type NormalizedColumnKind =\n \"integer\" | \"text\" | \"timestamp-with-time-zone\" | \"other\";\n\n/**\n * The `columnTypes` kinds that count as a revision counter. Both dialects\n * normalize one to `\"integer\"`, so this is a single-member set today — named\n * and exported so a caller compares against ONE owned set instead of\n * re-spelling `=== \"integer\"` inline. Consumed by\n * `store/recorded-capture/schema-version.ts`'s `isCompatibleColumnKind`,\n * which replaced that file's dialect-branching `isCompatibleColumnType` and\n * its SQLite-affinity twin (`hasSqliteAffinity`) with this owned set.\n */\nexport const REVISION_COLUMN_KINDS: readonly NormalizedColumnKind[] = [\n \"integer\",\n];\n\n/**\n * The `columnTypes` kinds that count as a wall-clock timestamp. SQLite\n * stores one as an ISO-8601 string (`\"text\"`); PostgreSQL stores one as\n * `timestamp with time zone` (`\"timestamp-with-time-zone\"`) and never\n * normalizes a declared column to `\"text\"` at all — so this set stays exact\n * on both dialects without a caller ever branching on `dialect`. Consumed\n * by `store/recorded-capture/schema-version.ts`'s `isCompatibleColumnKind`,\n * alongside {@link REVISION_COLUMN_KINDS}.\n */\nexport const WALL_TIME_COLUMN_KINDS: readonly NormalizedColumnKind[] = [\n \"text\",\n \"timestamp-with-time-zone\",\n];\n\n/**\n * One physical column's name, normalized type family, and raw declared\n * type — trimmed and lower-cased, but otherwise exactly what the engine's\n * own catalog reports (`\"bigint\"`, `\"timestamp with time zone\"`, a SQLite\n * declared type such as `\"integer\"` or `\"text\"`, and so on). `kind` is what\n * a comparison should classify against; `declaredType` is what a\n * diagnostic should show a human, since `kind` discards the declared\n * spelling entirely.\n */\nexport type CatalogColumn = Readonly<{\n name: string;\n kind: NormalizedColumnKind;\n declaredType: string;\n}>;\n\n/** One physical table's catalog presence. See {@link BackendCatalogProbes.tablesExist}. */\nexport type TableState = Readonly<{\n /** The physical SQL table name that was probed. */\n name: string;\n /** Whether a table with this name exists in the engine catalog. */\n exists: boolean;\n}>;\n\n/**\n * The three facts index materialization used to keep in its own\n * dialect-keyed record: whether this engine can build an index\n * concurrently (without blocking readers/writers), whether a concurrent\n * build can be interrupted into a usable-but-invalid leftover, and whether\n * it offers the GIN index family fulltext/trigram indexing needs.\n */\nexport type CatalogIndexBehavior = Readonly<{\n concurrentBuilds: boolean;\n hasInvalidIndexState: boolean;\n supportsGinFamily: boolean;\n}>;\n\n/**\n * Physical-schema introspection a store path consults directly: table and\n * index presence, PostgreSQL's invalid-index leftover state and its\n * self-heal, normalized column types, and the per-dialect index-build\n * facts above.\n *\n * Optional: a custom backend that omits it loses the store paths that\n * consult it directly — index materialization (`store.materializeIndexes()`\n * refuses only once its empty-candidate short circuit and the status-table\n * ensure step have already run; `store.materializeSystemIndexes()`, which\n * has no candidate short circuit, refuses only once that same status-table\n * ensure step has run), the recorded-time schema check, and the\n * recorded-time migration's column read.\n */\nexport type BackendCatalogProbes = Readonly<{\n /**\n * Whether a table with this physical name exists in the engine catalog —\n * on PostgreSQL, anything an unqualified `DELETE`/`ANALYZE` against the\n * name could hit (ordinary and partitioned tables, views, materialized\n * views, foreign tables), matching the dialect operation strategy's own\n * DDL-target probe. A caller that means specifically \"is this a TABLE\",\n * as opposed to any relation an unqualified statement could resolve to,\n * wants {@link BackendCatalogProbes.tablesExist} instead — its narrower\n * predicate excludes views, materialized views, and foreign tables.\n */\n tableExists: (this: void, name: string) => Promise<boolean>;\n /**\n * The catalog state of each named physical TABLE, one entry per input\n * name (an absent name reports `exists: false`), resolved in one round\n * trip. On PostgreSQL this is ordinary and partitioned tables only\n * (`relkind IN ('r', 'p')`) — narrower than {@link tableExists}, which\n * also matches views, materialized views, and foreign tables. A caller\n * gating bulk, table-scoped work (a preload ahead of table DDL, say)\n * wants this member so it gets one round trip and the strict predicate,\n * rather than looping {@link tableExists} or accepting its wider match.\n */\n tablesExist: (\n this: void,\n names: readonly string[],\n ) => Promise<readonly TableState[]>;\n /**\n * The catalog state of each named physical index, one entry per input\n * name (an absent index reports `exists: false`), resolved in one\n * round trip.\n */\n indexStates: (\n this: void,\n names: readonly string[],\n ) => Promise<readonly IndexState[]>;\n /**\n * Drops the named index if — and only if — it is a PostgreSQL INVALID\n * leftover from an interrupted `CREATE INDEX CONCURRENTLY`. A no-op on\n * an engine whose `indexBehavior.hasInvalidIndexState` is `false`, and\n * a no-op for a valid or absent index on every engine.\n *\n * A ROOT-BACKEND operation on an engine with an invalid-index state:\n * PostgreSQL refuses `DROP INDEX CONCURRENTLY` inside a transaction\n * block, so there the `catalog` a `transaction()` handle exposes throws a\n * typed `ConfigurationError` from this member instead of attempting the\n * DDL. An engine whose `indexBehavior.hasInvalidIndexState` is `false`\n * (SQLite) has no invalid leftover to ever drop and stays a no-op in\n * both scopes — every other member here stays a plain read on that same\n * transaction-scoped bag regardless of engine.\n */\n dropInvalidIndex: (this: void, name: string) => Promise<void>;\n /** Every column's name and normalized type family for one physical table. */\n columnTypes: (this: void, table: string) => Promise<readonly CatalogColumn[]>;\n /** This engine's index-build facts. See {@link CatalogIndexBehavior}. */\n indexBehavior: CatalogIndexBehavior;\n}>;\n\n/**\n * THE refusal for a store path that needs the backend's catalog probes and\n * finds them absent, naming the missing port so a caller can add it — or\n * switch to a bundled backend — instead of chasing a `TypeError` two calls\n * deep into `materializeIndexes` or a recorded-time migration.\n */\nexport function requireCatalog(\n backend: Pick<GraphBackend, \"catalog\">,\n operation: string,\n): BackendCatalogProbes {\n const catalog = backend.catalog;\n if (catalog === undefined) {\n throw new ConfigurationError(\n `${operation} requires the backend's catalog probes, but this backend declares no \\`catalog\\`.`,\n { code: \"CATALOG_UNAVAILABLE\", operation },\n {\n suggestion:\n \"Implement `catalog` on this backend, or use a built-in SQLite or PostgreSQL backend.\",\n },\n );\n }\n return catalog;\n}\n"]}
|