@opensip-cli/datastore 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/baseline-repo.test.d.ts +2 -0
- package/dist/__tests__/baseline-repo.test.d.ts.map +1 -0
- package/dist/__tests__/baseline-repo.test.js +85 -0
- package/dist/__tests__/baseline-repo.test.js.map +1 -0
- package/dist/__tests__/data-store.test.d.ts +10 -0
- package/dist/__tests__/data-store.test.d.ts.map +1 -0
- package/dist/__tests__/data-store.test.js +68 -0
- package/dist/__tests__/data-store.test.js.map +1 -0
- package/dist/__tests__/factory.test.d.ts +2 -0
- package/dist/__tests__/factory.test.d.ts.map +1 -0
- package/dist/__tests__/factory.test.js +168 -0
- package/dist/__tests__/factory.test.js.map +1 -0
- package/dist/__tests__/migration-integrity.test.d.ts +2 -0
- package/dist/__tests__/migration-integrity.test.d.ts.map +1 -0
- package/dist/__tests__/migration-integrity.test.js +78 -0
- package/dist/__tests__/migration-integrity.test.js.map +1 -0
- package/dist/__tests__/tool-state-repo.test.d.ts +7 -0
- package/dist/__tests__/tool-state-repo.test.d.ts.map +1 -0
- package/dist/__tests__/tool-state-repo.test.js +54 -0
- package/dist/__tests__/tool-state-repo.test.js.map +1 -0
- package/dist/__tests__/version-guard.test.d.ts +2 -0
- package/dist/__tests__/version-guard.test.d.ts.map +1 -0
- package/dist/__tests__/version-guard.test.js +110 -0
- package/dist/__tests__/version-guard.test.js.map +1 -0
- package/dist/backends/memory.d.ts +3 -0
- package/dist/backends/memory.d.ts.map +1 -0
- package/dist/backends/memory.js +5 -0
- package/dist/backends/memory.js.map +1 -0
- package/dist/backends/shared.d.ts +3 -0
- package/dist/backends/shared.d.ts.map +1 -0
- package/dist/backends/shared.js +31 -0
- package/dist/backends/shared.js.map +1 -0
- package/dist/backends/sqlite.d.ts +5 -0
- package/dist/backends/sqlite.d.ts.map +1 -0
- package/dist/backends/sqlite.js +8 -0
- package/dist/backends/sqlite.js.map +1 -0
- package/dist/baseline-repo.d.ts +50 -0
- package/dist/baseline-repo.d.ts.map +1 -0
- package/dist/baseline-repo.js +159 -0
- package/dist/baseline-repo.js.map +1 -0
- package/dist/data-store.d.ts +78 -0
- package/dist/data-store.d.ts.map +1 -0
- package/dist/data-store.js +71 -0
- package/dist/data-store.js.map +1 -0
- package/dist/factory.d.ts +47 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +151 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/schema/baseline.d.ts +178 -0
- package/dist/schema/baseline.d.ts.map +1 -0
- package/dist/schema/baseline.js +31 -0
- package/dist/schema/baseline.js.map +1 -0
- package/dist/schema/tool-state.d.ts +110 -0
- package/dist/schema/tool-state.d.ts.map +1 -0
- package/dist/schema/tool-state.js +20 -0
- package/dist/schema/tool-state.js.map +1 -0
- package/dist/schema-version.d.ts +23 -0
- package/dist/schema-version.d.ts.map +1 -0
- package/dist/schema-version.js +55 -0
- package/dist/schema-version.js.map +1 -0
- package/dist/tool-state-repo.d.ts +51 -0
- package/dist/tool-state-repo.d.ts.map +1 -0
- package/dist/tool-state-repo.js +110 -0
- package/dist/tool-state-repo.js.map +1 -0
- package/migrations/.gitkeep +0 -0
- package/migrations/0000_sticky_white_tiger.sql +39 -0
- package/migrations/0001_easy_harry_osborn.sql +18 -0
- package/migrations/0002_plain_amazoness.sql +5 -0
- package/migrations/0003_mysterious_khan.sql +6 -0
- package/migrations/0004_narrow_bloodscream.sql +3 -0
- package/migrations/0005_lying_luke_cage.sql +7 -0
- package/migrations/0006_mean_photon.sql +12 -0
- package/migrations/0007_parallel_chamber.sql +3 -0
- package/migrations/0008_flaky_victor_mancha.sql +7 -0
- package/migrations/0009_stable_tool_identity.sql +9 -0
- package/migrations/0010_add_timestamp_iso_and_payload_version.sql +11 -0
- package/migrations/0011_payload_version_safety_and_notes.sql +21 -0
- package/migrations/0012_overrated_talon.sql +21 -0
- package/migrations/0013_lovely_zarda.sql +1 -0
- package/migrations/meta/0000_snapshot.json +269 -0
- package/migrations/meta/0001_snapshot.json +369 -0
- package/migrations/meta/0002_snapshot.json +400 -0
- package/migrations/meta/0003_snapshot.json +441 -0
- package/migrations/meta/0004_snapshot.json +270 -0
- package/migrations/meta/0005_snapshot.json +315 -0
- package/migrations/meta/0006_snapshot.json +382 -0
- package/migrations/meta/0007_snapshot.json +303 -0
- package/migrations/meta/0008_snapshot.json +346 -0
- package/migrations/meta/0009_snapshot.json +367 -0
- package/migrations/meta/0010_snapshot.json +382 -0
- package/migrations/meta/0011_snapshot.json +382 -0
- package/migrations/meta/0012_snapshot.json +512 -0
- package/migrations/meta/0013_snapshot.json +458 -0
- package/migrations/meta/_journal.json +104 -0
- package/package.json +56 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
2
|
+
export type DrizzleHandle<TSchema extends Record<string, unknown> = Record<string, unknown>> = BetterSQLite3Database<TSchema>;
|
|
3
|
+
/** Public persistence handle: lifecycle plus transaction, but no raw query escape hatch. */
|
|
4
|
+
export interface DataStore<TSchema extends Record<string, unknown> = Record<string, unknown>> {
|
|
5
|
+
close(): void;
|
|
6
|
+
transaction<T>(fn: (tx: DrizzleHandle<TSchema>) => T): T;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Persistence-layer handle that exposes the raw Drizzle DB. Repository modules
|
|
10
|
+
* can narrow to this shape when they own the table boundary; general consumers
|
|
11
|
+
* should stay on {@link DataStore}.
|
|
12
|
+
*
|
|
13
|
+
* Direct query calls must stay inside `src/persistence/`, `session-store`, or
|
|
14
|
+
* `datastore`. Cross-module business code should go through the owning
|
|
15
|
+
* repository/API; `restrict-raw-db-access` guards that boundary.
|
|
16
|
+
*/
|
|
17
|
+
export interface DrizzleDataStore<TSchema extends Record<string, unknown> = Record<string, unknown>> extends DataStore<TSchema> {
|
|
18
|
+
readonly db: DrizzleHandle<TSchema>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A SQLite-backed {@link DrizzleDataStore} that also exposes its built-in
|
|
22
|
+
* `PRAGMA user_version` schema-stamp. Internal to the datastore package — the
|
|
23
|
+
* factory uses it to read/write the version guard before and after migrating.
|
|
24
|
+
* General consumers stay on {@link DataStore} / {@link DrizzleDataStore}.
|
|
25
|
+
*/
|
|
26
|
+
export interface SqliteBackendHandle<TSchema extends Record<string, unknown> = Record<string, unknown>> extends DrizzleDataStore<TSchema> {
|
|
27
|
+
/** Read SQLite's `PRAGMA user_version` (0 on a fresh or pre-guard database). */
|
|
28
|
+
readUserVersion(): number;
|
|
29
|
+
/** Write SQLite's `PRAGMA user_version` schema-stamp. */
|
|
30
|
+
writeUserVersion(version: number): void;
|
|
31
|
+
}
|
|
32
|
+
export declare function isDrizzleDataStore(value: unknown): value is DrizzleDataStore;
|
|
33
|
+
/**
|
|
34
|
+
* Narrow a {@link DataStore} to a {@link DrizzleDataStore}, requiring the raw
|
|
35
|
+
* Drizzle handle to be present.
|
|
36
|
+
*
|
|
37
|
+
* @throws {Error} when `datastore` is not Drizzle-backed (general callers should
|
|
38
|
+
* use repository APIs instead of the raw datastore handle).
|
|
39
|
+
*/
|
|
40
|
+
export declare function requireDrizzleDataStore(datastore: DataStore): DrizzleDataStore;
|
|
41
|
+
/** Options for opening a {@link DataStore}: backend choice and optional file path. */
|
|
42
|
+
export interface DataStoreOpenOptions {
|
|
43
|
+
backend: 'sqlite' | 'memory';
|
|
44
|
+
path?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Thrown when a Drizzle schema migration fails to apply; carries the offending file name. */
|
|
47
|
+
export declare class DataStoreMigrationError extends Error {
|
|
48
|
+
readonly migrationFile: string | undefined;
|
|
49
|
+
constructor(message: string, options?: {
|
|
50
|
+
migrationFile?: string;
|
|
51
|
+
cause?: unknown;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** Inputs describing an incompatible (future) on-disk database. */
|
|
55
|
+
export interface DataStoreVersionMismatch {
|
|
56
|
+
readonly path: string;
|
|
57
|
+
/** The `user_version` stamp found on disk. */
|
|
58
|
+
readonly dbVersion: number;
|
|
59
|
+
/** The highest schema version this CLI supports. */
|
|
60
|
+
readonly supportedVersion: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Thrown when the on-disk SQLite cache was written by a NEWER opensip-cli than
|
|
64
|
+
* the one now opening it (`dbVersion > supportedVersion`). Drizzle's migrator
|
|
65
|
+
* cannot detect this direction — the older CLI's migrations are all a prefix of
|
|
66
|
+
* what was applied, so `migrate()` would no-op and later queries would hit
|
|
67
|
+
* missing/renamed columns with a confusing error. This guard fails fast instead,
|
|
68
|
+
* with an actionable message symmetric to the config-schema "upgrade your CLI"
|
|
69
|
+
* bailout. The `.runtime/` cache is disposable, so deleting it is offered as the
|
|
70
|
+
* fallback for users who intend to stay on the older CLI.
|
|
71
|
+
*/
|
|
72
|
+
export declare class DataStoreVersionError extends Error {
|
|
73
|
+
readonly path: string;
|
|
74
|
+
readonly dbVersion: number;
|
|
75
|
+
readonly supportedVersion: number;
|
|
76
|
+
constructor(mismatch: DataStoreVersionMismatch);
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=data-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-store.d.ts","sourceRoot":"","sources":["../src/data-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IACzF,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAEjC,4FAA4F;AAC5F,MAAM,WAAW,SAAS,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1F,KAAK,IAAI,IAAI,CAAC;IACd,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;CAC1D;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB,CAC/B,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACjE,SAAQ,SAAS,CAAC,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB,CAClC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACjE,SAAQ,gBAAgB,CAAC,OAAO,CAAC;IACjC,gFAAgF;IAChF,eAAe,IAAI,MAAM,CAAC;IAC1B,yDAAyD;IACzD,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAU5E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAK9E;AAED,sFAAsF;AACtF,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,8FAA8F;AAC9F,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE/B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAQvF;AAED,mEAAmE;AACnE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;gBAEtB,QAAQ,EAAE,wBAAwB;CAO/C"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export function isDrizzleDataStore(value) {
|
|
2
|
+
return (typeof value === 'object' &&
|
|
3
|
+
value !== null &&
|
|
4
|
+
'db' in value &&
|
|
5
|
+
'transaction' in value &&
|
|
6
|
+
typeof value.transaction === 'function' &&
|
|
7
|
+
'close' in value &&
|
|
8
|
+
typeof value.close === 'function');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Narrow a {@link DataStore} to a {@link DrizzleDataStore}, requiring the raw
|
|
12
|
+
* Drizzle handle to be present.
|
|
13
|
+
*
|
|
14
|
+
* @throws {Error} when `datastore` is not Drizzle-backed (general callers should
|
|
15
|
+
* use repository APIs instead of the raw datastore handle).
|
|
16
|
+
*/
|
|
17
|
+
export function requireDrizzleDataStore(datastore) {
|
|
18
|
+
if (isDrizzleDataStore(datastore))
|
|
19
|
+
return datastore;
|
|
20
|
+
throw new Error('A Drizzle-backed DataStore is required for repository access. General callers should use repository APIs instead of the raw datastore handle.');
|
|
21
|
+
}
|
|
22
|
+
/** Thrown when a Drizzle schema migration fails to apply; carries the offending file name. */
|
|
23
|
+
export class DataStoreMigrationError extends Error {
|
|
24
|
+
migrationFile;
|
|
25
|
+
constructor(message, options = {}) {
|
|
26
|
+
// Pass cause to super so it lands on the standard Error.cause slot
|
|
27
|
+
// (ES2022). Don't redeclare the field — that would shadow it with a
|
|
28
|
+
// writable class-field property and bypass native engine handling.
|
|
29
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
30
|
+
this.name = 'DataStoreMigrationError';
|
|
31
|
+
this.migrationFile = options.migrationFile;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Thrown when the on-disk SQLite cache was written by a NEWER opensip-cli than
|
|
36
|
+
* the one now opening it (`dbVersion > supportedVersion`). Drizzle's migrator
|
|
37
|
+
* cannot detect this direction — the older CLI's migrations are all a prefix of
|
|
38
|
+
* what was applied, so `migrate()` would no-op and later queries would hit
|
|
39
|
+
* missing/renamed columns with a confusing error. This guard fails fast instead,
|
|
40
|
+
* with an actionable message symmetric to the config-schema "upgrade your CLI"
|
|
41
|
+
* bailout. The `.runtime/` cache is disposable, so deleting it is offered as the
|
|
42
|
+
* fallback for users who intend to stay on the older CLI.
|
|
43
|
+
*/
|
|
44
|
+
export class DataStoreVersionError extends Error {
|
|
45
|
+
path;
|
|
46
|
+
dbVersion;
|
|
47
|
+
supportedVersion;
|
|
48
|
+
constructor(mismatch) {
|
|
49
|
+
super(formatVersionErrorMessage(mismatch));
|
|
50
|
+
this.name = 'DataStoreVersionError';
|
|
51
|
+
this.path = mismatch.path;
|
|
52
|
+
this.dbVersion = mismatch.dbVersion;
|
|
53
|
+
this.supportedVersion = mismatch.supportedVersion;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function formatVersionErrorMessage(mismatch) {
|
|
57
|
+
return [
|
|
58
|
+
`This project's opensip-cli cache was written by a newer version of opensip-cli than this CLI supports.`,
|
|
59
|
+
``,
|
|
60
|
+
` Cache: ${mismatch.path}`,
|
|
61
|
+
` Cache schema: v${mismatch.dbVersion}`,
|
|
62
|
+
` CLI supports: v${mismatch.supportedVersion}`,
|
|
63
|
+
``,
|
|
64
|
+
` Update your CLI to continue:`,
|
|
65
|
+
` curl -fsSL https://opensip.ai/cli/install.sh | bash`,
|
|
66
|
+
``,
|
|
67
|
+
` (Or delete ${mismatch.path} to discard the local cache and continue with`,
|
|
68
|
+
` this older CLI — session history will be lost; the cache rebuilds on next run.)`,
|
|
69
|
+
].join('\n');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=data-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-store.js","sourceRoot":"","sources":["../src/data-store.ts"],"names":[],"mappings":"AAyCA,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,IAAI,IAAI,KAAK;QACb,aAAa,IAAI,KAAK;QACtB,OAAO,KAAK,CAAC,WAAW,KAAK,UAAU;QACvC,OAAO,IAAI,KAAK;QAChB,OAAO,KAAK,CAAC,KAAK,KAAK,UAAU,CAClC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAoB;IAC1D,IAAI,kBAAkB,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACpD,MAAM,IAAI,KAAK,CACb,+IAA+I,CAChJ,CAAC;AACJ,CAAC;AAQD,8FAA8F;AAC9F,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,aAAa,CAAqB;IAE3C,YAAY,OAAe,EAAE,UAAuD,EAAE;QACpF,mEAAmE;QACnE,oEAAoE;QACpE,mEAAmE;QACnE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC7C,CAAC;CACF;AAWD;;;;;;;;;GASG;AACH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,IAAI,CAAS;IACb,SAAS,CAAS;IAClB,gBAAgB,CAAS;IAElC,YAAY,QAAkC;QAC5C,KAAK,CAAC,yBAAyB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAC1B,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;QACpC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC;IACpD,CAAC;CACF;AAED,SAAS,yBAAyB,CAAC,QAAkC;IACnE,OAAO;QACL,wGAAwG;QACxG,EAAE;QACF,qBAAqB,QAAQ,CAAC,IAAI,EAAE;QACpC,sBAAsB,QAAQ,CAAC,SAAS,EAAE;QAC1C,sBAAsB,QAAQ,CAAC,gBAAgB,EAAE;QACjD,EAAE;QACF,gCAAgC;QAChC,yDAAyD;QACzD,EAAE;QACF,gBAAgB,QAAQ,CAAC,IAAI,+CAA+C;QAC5E,mFAAmF;KACpF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { DataStoreOpenOptions, DrizzleDataStore } from './data-store.js';
|
|
2
|
+
export declare const DataStoreFactory: {
|
|
3
|
+
/**
|
|
4
|
+
* Open a DataStore (SQLite or in-memory) and run pending migrations.
|
|
5
|
+
*
|
|
6
|
+
* For SQLite, a version guard runs first: if the file was stamped by a NEWER
|
|
7
|
+
* CLI than this one (`PRAGMA user_version` ahead of the bundled migration
|
|
8
|
+
* count), it throws {@link DataStoreVersionError} instead of letting Drizzle
|
|
9
|
+
* silently no-op into a runtime column error. After a successful migrate, the
|
|
10
|
+
* stamp is refreshed to this CLI's supported version.
|
|
11
|
+
*
|
|
12
|
+
* @throws {DataStoreVersionError} When the SQLite file was written by a newer
|
|
13
|
+
* opensip-cli than this CLI supports (the downgrade direction).
|
|
14
|
+
* @throws {DataStoreMigrationError} When the SQLite file cannot be opened
|
|
15
|
+
* (corrupt header, missing parent directory, permission errors), when the
|
|
16
|
+
* native `better-sqlite3` binding fails to load (an ABI mismatch — the file
|
|
17
|
+
* is fine, the addon was built for a different Node.js version), or when
|
|
18
|
+
* running the migrations folder fails. The original cause is preserved via
|
|
19
|
+
* the `cause` field; the message distinguishes the binding case so callers
|
|
20
|
+
* are not told to delete a healthy data store.
|
|
21
|
+
*/
|
|
22
|
+
open(opts: DataStoreOpenOptions & {
|
|
23
|
+
migrationsFolder?: string;
|
|
24
|
+
}): DrizzleDataStore;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Detect a native-binding load failure: `better-sqlite3`'s compiled addon was
|
|
28
|
+
* built for a different Node.js ABI than the one now running (e.g. the binding
|
|
29
|
+
* was compiled under Node 22 and the CLI is run under Node 24). This is NOT a
|
|
30
|
+
* data problem — the SQLite file is intact and must not be deleted; the fix is
|
|
31
|
+
* to rebuild the native module for the current Node.js.
|
|
32
|
+
*
|
|
33
|
+
* Identified by the Node loader's `ERR_DLOPEN_FAILED` code or the
|
|
34
|
+
* `NODE_MODULE_VERSION` / "compiled against a different Node.js version" text,
|
|
35
|
+
* scanned across the whole `cause` chain (the error may be wrapped).
|
|
36
|
+
*/
|
|
37
|
+
export declare function isNativeBindingError(error: unknown): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Build the user-facing message for a data-store open failure, choosing the
|
|
40
|
+
* remediation that matches the actual cause: a native-binding ABI mismatch
|
|
41
|
+
* (rebuild the addon — the data is fine) vs a genuine corrupt/permission/
|
|
42
|
+
* non-writable SQLite file (delete to start fresh) vs an in-memory programming
|
|
43
|
+
* error. Separated from the throw site so the cause→message mapping is unit
|
|
44
|
+
* testable without exercising the real binding.
|
|
45
|
+
*/
|
|
46
|
+
export declare function openFailureMessage(opts: DataStoreOpenOptions, error: unknown): string;
|
|
47
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAM9E,eAAO,MAAM,gBAAgB;IAC3B;;;;;;;;;;;;;;;;;;OAkBG;eACQ,oBAAoB,GAAG;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,gBAAgB;CAwCnF,CAAC;AA8BF;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAU5D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAWrF"}
|
package/dist/factory.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { ConfigurationError } from '@opensip-cli/core';
|
|
4
|
+
import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
|
|
5
|
+
import { openMemoryBackend } from './backends/memory.js';
|
|
6
|
+
import { openSqliteBackend } from './backends/sqlite.js';
|
|
7
|
+
import { DataStoreMigrationError, DataStoreVersionError } from './data-store.js';
|
|
8
|
+
import { isDbNewerThanCli, readSupportedDbVersion } from './schema-version.js';
|
|
9
|
+
function defaultMigrationsFolder() {
|
|
10
|
+
return join(fileURLToPath(new URL('.', import.meta.url)), '..', 'migrations');
|
|
11
|
+
}
|
|
12
|
+
export const DataStoreFactory = {
|
|
13
|
+
/**
|
|
14
|
+
* Open a DataStore (SQLite or in-memory) and run pending migrations.
|
|
15
|
+
*
|
|
16
|
+
* For SQLite, a version guard runs first: if the file was stamped by a NEWER
|
|
17
|
+
* CLI than this one (`PRAGMA user_version` ahead of the bundled migration
|
|
18
|
+
* count), it throws {@link DataStoreVersionError} instead of letting Drizzle
|
|
19
|
+
* silently no-op into a runtime column error. After a successful migrate, the
|
|
20
|
+
* stamp is refreshed to this CLI's supported version.
|
|
21
|
+
*
|
|
22
|
+
* @throws {DataStoreVersionError} When the SQLite file was written by a newer
|
|
23
|
+
* opensip-cli than this CLI supports (the downgrade direction).
|
|
24
|
+
* @throws {DataStoreMigrationError} When the SQLite file cannot be opened
|
|
25
|
+
* (corrupt header, missing parent directory, permission errors), when the
|
|
26
|
+
* native `better-sqlite3` binding fails to load (an ABI mismatch — the file
|
|
27
|
+
* is fine, the addon was built for a different Node.js version), or when
|
|
28
|
+
* running the migrations folder fails. The original cause is preserved via
|
|
29
|
+
* the `cause` field; the message distinguishes the binding case so callers
|
|
30
|
+
* are not told to delete a healthy data store.
|
|
31
|
+
*/
|
|
32
|
+
open(opts) {
|
|
33
|
+
const migrationsFolder = opts.migrationsFolder ?? defaultMigrationsFolder();
|
|
34
|
+
if (opts.backend === 'memory') {
|
|
35
|
+
return openAndMigrate(opts, migrationsFolder, () => openMemoryBackend());
|
|
36
|
+
}
|
|
37
|
+
const path = requireSqlitePath(opts);
|
|
38
|
+
let handle;
|
|
39
|
+
try {
|
|
40
|
+
handle = openSqliteBackend({ path });
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// Corrupted file (bad SQLite header), missing dir, permission errors, or a
|
|
44
|
+
// native-binding ABI mismatch (better-sqlite3 built for another Node.js).
|
|
45
|
+
throw new DataStoreMigrationError(openFailureMessage(opts, error), { cause: error });
|
|
46
|
+
}
|
|
47
|
+
// `undefined` (unreadable journal) means "skip the guard" — migrate() reads
|
|
48
|
+
// the same journal and will surface the canonical failure loudly.
|
|
49
|
+
const supportedVersion = readSupportedDbVersion(migrationsFolder);
|
|
50
|
+
if (supportedVersion !== undefined) {
|
|
51
|
+
const dbVersion = handle.readUserVersion();
|
|
52
|
+
if (isDbNewerThanCli(dbVersion, supportedVersion)) {
|
|
53
|
+
handle.close();
|
|
54
|
+
throw new DataStoreVersionError({ path, dbVersion, supportedVersion });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
migrate(handle.db, { migrationsFolder });
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
handle.close();
|
|
62
|
+
throw new DataStoreMigrationError(migrateFailureMessage(opts), { cause: error });
|
|
63
|
+
}
|
|
64
|
+
// Re-stamp on every successful open: a fresh (0) or pre-guard "legacy" DB
|
|
65
|
+
// gets adopted to the current version; an already-current DB is a no-op write.
|
|
66
|
+
if (supportedVersion !== undefined)
|
|
67
|
+
handle.writeUserVersion(supportedVersion);
|
|
68
|
+
return handle;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Open a backend and run migrations, mapping both failures to
|
|
73
|
+
* {@link DataStoreMigrationError}. Used for the in-memory path (which needs no
|
|
74
|
+
* version guard — it is ephemeral) and shared message handling.
|
|
75
|
+
*
|
|
76
|
+
* @throws {DataStoreMigrationError} When the backend cannot be opened or the
|
|
77
|
+
* migrations folder fails to apply; the original cause is preserved.
|
|
78
|
+
*/
|
|
79
|
+
function openAndMigrate(opts, migrationsFolder, openBackend) {
|
|
80
|
+
let datastore;
|
|
81
|
+
try {
|
|
82
|
+
datastore = openBackend();
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
throw new DataStoreMigrationError(openFailureMessage(opts, error), { cause: error });
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
migrate(datastore.db, { migrationsFolder });
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
datastore.close();
|
|
92
|
+
throw new DataStoreMigrationError(migrateFailureMessage(opts), { cause: error });
|
|
93
|
+
}
|
|
94
|
+
return datastore;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Detect a native-binding load failure: `better-sqlite3`'s compiled addon was
|
|
98
|
+
* built for a different Node.js ABI than the one now running (e.g. the binding
|
|
99
|
+
* was compiled under Node 22 and the CLI is run under Node 24). This is NOT a
|
|
100
|
+
* data problem — the SQLite file is intact and must not be deleted; the fix is
|
|
101
|
+
* to rebuild the native module for the current Node.js.
|
|
102
|
+
*
|
|
103
|
+
* Identified by the Node loader's `ERR_DLOPEN_FAILED` code or the
|
|
104
|
+
* `NODE_MODULE_VERSION` / "compiled against a different Node.js version" text,
|
|
105
|
+
* scanned across the whole `cause` chain (the error may be wrapped).
|
|
106
|
+
*/
|
|
107
|
+
export function isNativeBindingError(error) {
|
|
108
|
+
for (let current = error; current instanceof Error; current = current.cause) {
|
|
109
|
+
if (current.code === 'ERR_DLOPEN_FAILED')
|
|
110
|
+
return true;
|
|
111
|
+
if (/NODE_MODULE_VERSION|compiled against a different Node\.js version/i.test(current.message)) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Build the user-facing message for a data-store open failure, choosing the
|
|
119
|
+
* remediation that matches the actual cause: a native-binding ABI mismatch
|
|
120
|
+
* (rebuild the addon — the data is fine) vs a genuine corrupt/permission/
|
|
121
|
+
* non-writable SQLite file (delete to start fresh) vs an in-memory programming
|
|
122
|
+
* error. Separated from the throw site so the cause→message mapping is unit
|
|
123
|
+
* testable without exercising the real binding.
|
|
124
|
+
*/
|
|
125
|
+
export function openFailureMessage(opts, error) {
|
|
126
|
+
// A native-binding ABI mismatch is not a corrupt/missing file — telling the
|
|
127
|
+
// user to delete the data store would destroy healthy session history for no
|
|
128
|
+
// reason. Steer them to rebuild the addon instead, regardless of backend.
|
|
129
|
+
if (isNativeBindingError(error)) {
|
|
130
|
+
return `Failed to load the native SQLite module (better-sqlite3): its compiled binding was built for a different Node.js version than the one now running. Your data store is NOT corrupt — do not delete it. Rebuild the native module for your current Node.js with \`pnpm rebuild better-sqlite3\`, and run opensip on the Node.js version this project targets (see \`.nvmrc\` / the package.json \`engines\` field).`;
|
|
131
|
+
}
|
|
132
|
+
if (opts.backend === 'sqlite' && opts.path) {
|
|
133
|
+
return `Failed to open SQLite data store at \`${opts.path}\` — the file may be corrupted, missing permissions, or in a non-writable directory. Delete \`${opts.path}\` to start fresh (cache will rebuild on next run; session history will be lost).`;
|
|
134
|
+
}
|
|
135
|
+
return 'Failed to open in-memory data store; this is likely a programming error.';
|
|
136
|
+
}
|
|
137
|
+
function migrateFailureMessage(opts) {
|
|
138
|
+
if (opts.backend === 'sqlite' && opts.path) {
|
|
139
|
+
return `Schema migration failed against \`${opts.path}\`; the local cache may be from an incompatible version. Delete \`${opts.path}\` to start fresh (cache will rebuild on next run; session history will be lost).`;
|
|
140
|
+
}
|
|
141
|
+
return 'Schema migration failed against the in-memory backend; this is likely a programming error.';
|
|
142
|
+
}
|
|
143
|
+
function requireSqlitePath(opts) {
|
|
144
|
+
if (!opts.path) {
|
|
145
|
+
throw new ConfigurationError('DataStoreFactory.open: SQLite backend requires a `path` option', {
|
|
146
|
+
code: 'CONFIGURATION.DATASTORE.MISSING_PATH',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
return opts.path;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { DataStore, DataStoreOpenOptions, DataStoreVersionMismatch, DrizzleDataStore, DrizzleHandle, SqliteBackendHandle, } from './data-store.js';
|
|
2
|
+
export { DataStoreMigrationError, DataStoreVersionError, isDrizzleDataStore, requireDrizzleDataStore, } from './data-store.js';
|
|
3
|
+
export { DataStoreFactory } from './factory.js';
|
|
4
|
+
export { isDbNewerThanCli, readSupportedDbVersion } from './schema-version.js';
|
|
5
|
+
export { toolBaselineEntries, toolBaselineMeta } from './schema/baseline.js';
|
|
6
|
+
export { BaselineRepo } from './baseline-repo.js';
|
|
7
|
+
export { toolState } from './schema/tool-state.js';
|
|
8
|
+
export { ToolStateRepo, TOOL_STATE_MAX_PAYLOAD_BYTES } from './tool-state-repo.js';
|
|
9
|
+
export type { BaselineEntry, BaselineRow } from './baseline-repo.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,SAAS,EACT,oBAAoB,EACpB,wBAAwB,EACxB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAG/E,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACnF,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { DataStoreMigrationError, DataStoreVersionError, isDrizzleDataStore, requireDrizzleDataStore, } from './data-store.js';
|
|
2
|
+
export { DataStoreFactory } from './factory.js';
|
|
3
|
+
export { isDbNewerThanCli, readSupportedDbVersion } from './schema-version.js';
|
|
4
|
+
// Generic host-owned baseline/ratchet plane (ADR-0036): the shared table pair
|
|
5
|
+
// + the per-tool repo over them.
|
|
6
|
+
export { toolBaselineEntries, toolBaselineMeta } from './schema/baseline.js';
|
|
7
|
+
export { BaselineRepo } from './baseline-repo.js';
|
|
8
|
+
// ADR-0042: the generic keyed tool-state table + repo (the cli.toolState seams).
|
|
9
|
+
export { toolState } from './schema/tool-state.js';
|
|
10
|
+
export { ToolStateRepo, TOOL_STATE_MAX_PAYLOAD_BYTES } from './tool-state-repo.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,8EAA8E;AAC9E,iCAAiC;AACjC,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,iFAAiF;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic host-owned baseline entries (ADR-0036). ONE table pair replaces the
|
|
3
|
+
* per-tool baseline tables (`graph_baseline_signals`, `fit_baseline`, …): each
|
|
4
|
+
* row is one finding's fingerprint + its full `Signal` payload, scoped by the
|
|
5
|
+
* `tool` column so tools share the table but never see each other's rows.
|
|
6
|
+
*
|
|
7
|
+
* The composite primary key `(tool, fingerprint)` makes save a per-tool
|
|
8
|
+
* delete-all + bulk-insert (atomic replace), and the `payload` column supplies
|
|
9
|
+
* the full-object `resolved` diff bucket AND the SARIF re-render
|
|
10
|
+
* (synthetic envelope → `formatSignalSarif`).
|
|
11
|
+
*/
|
|
12
|
+
export declare const toolBaselineEntries: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
13
|
+
name: "tool_baseline_entries";
|
|
14
|
+
schema: undefined;
|
|
15
|
+
columns: {
|
|
16
|
+
tool: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
17
|
+
name: "tool";
|
|
18
|
+
tableName: "tool_baseline_entries";
|
|
19
|
+
dataType: "string";
|
|
20
|
+
columnType: "SQLiteText";
|
|
21
|
+
data: string;
|
|
22
|
+
driverParam: string;
|
|
23
|
+
notNull: true;
|
|
24
|
+
hasDefault: false;
|
|
25
|
+
isPrimaryKey: false;
|
|
26
|
+
isAutoincrement: false;
|
|
27
|
+
hasRuntimeDefault: false;
|
|
28
|
+
enumValues: [string, ...string[]];
|
|
29
|
+
baseColumn: never;
|
|
30
|
+
identity: undefined;
|
|
31
|
+
generated: undefined;
|
|
32
|
+
}, {}, {
|
|
33
|
+
length: number | undefined;
|
|
34
|
+
}>;
|
|
35
|
+
stableId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
36
|
+
name: "stable_id";
|
|
37
|
+
tableName: "tool_baseline_entries";
|
|
38
|
+
dataType: "string";
|
|
39
|
+
columnType: "SQLiteText";
|
|
40
|
+
data: string;
|
|
41
|
+
driverParam: string;
|
|
42
|
+
notNull: false;
|
|
43
|
+
hasDefault: false;
|
|
44
|
+
isPrimaryKey: false;
|
|
45
|
+
isAutoincrement: false;
|
|
46
|
+
hasRuntimeDefault: false;
|
|
47
|
+
enumValues: [string, ...string[]];
|
|
48
|
+
baseColumn: never;
|
|
49
|
+
identity: undefined;
|
|
50
|
+
generated: undefined;
|
|
51
|
+
}, {}, {
|
|
52
|
+
length: number | undefined;
|
|
53
|
+
}>;
|
|
54
|
+
fingerprint: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
55
|
+
name: "fingerprint";
|
|
56
|
+
tableName: "tool_baseline_entries";
|
|
57
|
+
dataType: "string";
|
|
58
|
+
columnType: "SQLiteText";
|
|
59
|
+
data: string;
|
|
60
|
+
driverParam: string;
|
|
61
|
+
notNull: true;
|
|
62
|
+
hasDefault: false;
|
|
63
|
+
isPrimaryKey: false;
|
|
64
|
+
isAutoincrement: false;
|
|
65
|
+
hasRuntimeDefault: false;
|
|
66
|
+
enumValues: [string, ...string[]];
|
|
67
|
+
baseColumn: never;
|
|
68
|
+
identity: undefined;
|
|
69
|
+
generated: undefined;
|
|
70
|
+
}, {}, {
|
|
71
|
+
length: number | undefined;
|
|
72
|
+
}>;
|
|
73
|
+
payload: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
74
|
+
name: "payload";
|
|
75
|
+
tableName: "tool_baseline_entries";
|
|
76
|
+
dataType: "json";
|
|
77
|
+
columnType: "SQLiteTextJson";
|
|
78
|
+
data: unknown;
|
|
79
|
+
driverParam: string;
|
|
80
|
+
notNull: false;
|
|
81
|
+
hasDefault: false;
|
|
82
|
+
isPrimaryKey: false;
|
|
83
|
+
isAutoincrement: false;
|
|
84
|
+
hasRuntimeDefault: false;
|
|
85
|
+
enumValues: undefined;
|
|
86
|
+
baseColumn: never;
|
|
87
|
+
identity: undefined;
|
|
88
|
+
generated: undefined;
|
|
89
|
+
}, {}, {}>;
|
|
90
|
+
capturedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
91
|
+
name: "captured_at";
|
|
92
|
+
tableName: "tool_baseline_entries";
|
|
93
|
+
dataType: "number";
|
|
94
|
+
columnType: "SQLiteInteger";
|
|
95
|
+
data: number;
|
|
96
|
+
driverParam: number;
|
|
97
|
+
notNull: true;
|
|
98
|
+
hasDefault: false;
|
|
99
|
+
isPrimaryKey: false;
|
|
100
|
+
isAutoincrement: false;
|
|
101
|
+
hasRuntimeDefault: false;
|
|
102
|
+
enumValues: undefined;
|
|
103
|
+
baseColumn: never;
|
|
104
|
+
identity: undefined;
|
|
105
|
+
generated: undefined;
|
|
106
|
+
}, {}, {}>;
|
|
107
|
+
};
|
|
108
|
+
dialect: "sqlite";
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Per-tool baseline existence marker + capture timestamp (ADR-0036). Keyed by
|
|
112
|
+
* `tool`, separate from the entries so an empty-but-saved baseline (a clean
|
|
113
|
+
* codebase) still reports `exists() === true` — distinguishing "saved, no
|
|
114
|
+
* findings" from "never saved". `capturedAt` feeds the JSON export's timestamp.
|
|
115
|
+
*/
|
|
116
|
+
export declare const toolBaselineMeta: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
117
|
+
name: "tool_baseline_meta";
|
|
118
|
+
schema: undefined;
|
|
119
|
+
columns: {
|
|
120
|
+
tool: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
121
|
+
name: "tool";
|
|
122
|
+
tableName: "tool_baseline_meta";
|
|
123
|
+
dataType: "string";
|
|
124
|
+
columnType: "SQLiteText";
|
|
125
|
+
data: string;
|
|
126
|
+
driverParam: string;
|
|
127
|
+
notNull: true;
|
|
128
|
+
hasDefault: false;
|
|
129
|
+
isPrimaryKey: true;
|
|
130
|
+
isAutoincrement: false;
|
|
131
|
+
hasRuntimeDefault: false;
|
|
132
|
+
enumValues: [string, ...string[]];
|
|
133
|
+
baseColumn: never;
|
|
134
|
+
identity: undefined;
|
|
135
|
+
generated: undefined;
|
|
136
|
+
}, {}, {
|
|
137
|
+
length: number | undefined;
|
|
138
|
+
}>;
|
|
139
|
+
stableId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
140
|
+
name: "stable_id";
|
|
141
|
+
tableName: "tool_baseline_meta";
|
|
142
|
+
dataType: "string";
|
|
143
|
+
columnType: "SQLiteText";
|
|
144
|
+
data: string;
|
|
145
|
+
driverParam: string;
|
|
146
|
+
notNull: false;
|
|
147
|
+
hasDefault: false;
|
|
148
|
+
isPrimaryKey: false;
|
|
149
|
+
isAutoincrement: false;
|
|
150
|
+
hasRuntimeDefault: false;
|
|
151
|
+
enumValues: [string, ...string[]];
|
|
152
|
+
baseColumn: never;
|
|
153
|
+
identity: undefined;
|
|
154
|
+
generated: undefined;
|
|
155
|
+
}, {}, {
|
|
156
|
+
length: number | undefined;
|
|
157
|
+
}>;
|
|
158
|
+
capturedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
159
|
+
name: "captured_at";
|
|
160
|
+
tableName: "tool_baseline_meta";
|
|
161
|
+
dataType: "number";
|
|
162
|
+
columnType: "SQLiteInteger";
|
|
163
|
+
data: number;
|
|
164
|
+
driverParam: number;
|
|
165
|
+
notNull: true;
|
|
166
|
+
hasDefault: false;
|
|
167
|
+
isPrimaryKey: false;
|
|
168
|
+
isAutoincrement: false;
|
|
169
|
+
hasRuntimeDefault: false;
|
|
170
|
+
enumValues: undefined;
|
|
171
|
+
baseColumn: never;
|
|
172
|
+
identity: undefined;
|
|
173
|
+
generated: undefined;
|
|
174
|
+
}, {}, {}>;
|
|
175
|
+
};
|
|
176
|
+
dialect: "sqlite";
|
|
177
|
+
}>;
|
|
178
|
+
//# sourceMappingURL=baseline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../../src/schema/baseline.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAI3B,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { integer, primaryKey, sqliteTable, text } from 'drizzle-orm/sqlite-core';
|
|
2
|
+
/**
|
|
3
|
+
* Generic host-owned baseline entries (ADR-0036). ONE table pair replaces the
|
|
4
|
+
* per-tool baseline tables (`graph_baseline_signals`, `fit_baseline`, …): each
|
|
5
|
+
* row is one finding's fingerprint + its full `Signal` payload, scoped by the
|
|
6
|
+
* `tool` column so tools share the table but never see each other's rows.
|
|
7
|
+
*
|
|
8
|
+
* The composite primary key `(tool, fingerprint)` makes save a per-tool
|
|
9
|
+
* delete-all + bulk-insert (atomic replace), and the `payload` column supplies
|
|
10
|
+
* the full-object `resolved` diff bucket AND the SARIF re-render
|
|
11
|
+
* (synthetic envelope → `formatSignalSarif`).
|
|
12
|
+
*/
|
|
13
|
+
export const toolBaselineEntries = sqliteTable('tool_baseline_entries', {
|
|
14
|
+
tool: text('tool').notNull(), // human `name` value (for compat + current queries)
|
|
15
|
+
stableId: text('stable_id'), // tool stable UUID (additive per ADR-0048; null for legacy rows)
|
|
16
|
+
fingerprint: text('fingerprint').notNull(),
|
|
17
|
+
payload: text('payload', { mode: 'json' }), // the Signal as JSON
|
|
18
|
+
capturedAt: integer('captured_at').notNull(),
|
|
19
|
+
}, (t) => [primaryKey({ columns: [t.tool, t.fingerprint] })]);
|
|
20
|
+
/**
|
|
21
|
+
* Per-tool baseline existence marker + capture timestamp (ADR-0036). Keyed by
|
|
22
|
+
* `tool`, separate from the entries so an empty-but-saved baseline (a clean
|
|
23
|
+
* codebase) still reports `exists() === true` — distinguishing "saved, no
|
|
24
|
+
* findings" from "never saved". `capturedAt` feeds the JSON export's timestamp.
|
|
25
|
+
*/
|
|
26
|
+
export const toolBaselineMeta = sqliteTable('tool_baseline_meta', {
|
|
27
|
+
tool: text('tool').primaryKey(), // human `name` value (for compat)
|
|
28
|
+
stableId: text('stable_id'), // tool stable UUID (additive)
|
|
29
|
+
capturedAt: integer('captured_at').notNull(),
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/schema/baseline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEjF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAC5C,uBAAuB,EACvB;IACE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,oDAAoD;IAClF,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,iEAAiE;IAC9F,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IAC1C,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,qBAAqB;IACjE,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;CAC7C,EACD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAC1D,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC,oBAAoB,EAAE;IAChE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,kCAAkC;IACnE,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,8BAA8B;IAC3D,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;CAC7C,CAAC,CAAC"}
|