@bitcobblers/wod-wiki-storage 0.35.2129 → 0.36.2133

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.
@@ -1,5 +1,7 @@
1
- import { Client } from '@libsql/client';
1
+ import { S as SqlConnection, D as Database } from '../connection-DxuCLpRc.cjs';
2
+ export { L as LibsqlClient, a as SqlRow, b as SqlStatement, c as SqlValue, l as libsqlDatabase } from '../connection-DxuCLpRc.cjs';
2
3
  import { a as StoreDef, R as RangeDTO, K as KeyDTO, e as DomainQueryResult, T as TxOp, I as IStorage, S as StoreName, b as IReadOnlyStore, c as StoreType, d as IReadWriteStore, D as DomainQuery, f as IStorageTransaction } from '../wire-CiFcjo6_.cjs';
4
+ import '@libsql/client';
3
5
  import '@bitcobblers/wod-wiki-core';
4
6
  import '@bitcobblers/wod-wiki-lang';
5
7
 
@@ -15,41 +17,6 @@ declare class StorageError extends Error {
15
17
  constructor(status: number, message: string, code?: string | undefined);
16
18
  }
17
19
 
18
- /**
19
- * Connection contracts + a generic libsql adapter. The adapter takes a
20
- * *structural* client so the browser passes @libsql/client/web and the server
21
- * passes @libsql/client (node) — this module never imports either, keeping
22
- * the browser graph free of native drivers.
23
- *
24
- * All operations are serialized through one promise chain: the underlying
25
- * client shares a single connection, so concurrent transactions/reads could
26
- * otherwise interleave on it. Transactions run on a transaction-owned
27
- * connection (libsql interactive transaction), so writes inside a transaction
28
- * commit or roll back atomically and are not visible outside it.
29
- */
30
-
31
- type SqlValue = string | number | null;
32
- type SqlRow = Record<string, unknown>;
33
- interface SqlStatement {
34
- sql: string;
35
- params?: SqlValue[];
36
- }
37
- interface SqlConnection {
38
- query(sql: string, params?: SqlValue[]): Promise<SqlRow[]>;
39
- exec(sql: string, params?: SqlValue[]): Promise<void>;
40
- batch?(statements: SqlStatement[]): Promise<SqlRow[][]>;
41
- }
42
- interface Database extends SqlConnection {
43
- readonly dialect: 'sqlite' | 'postgres';
44
- transaction<T>(fn: (tx: SqlConnection) => Promise<T>): Promise<T>;
45
- close(): Promise<void>;
46
- }
47
- /** Minimal surface used from a libsql client (node or web build) — the real
48
- * @libsql/client types, type-only so the browser graph stays driver-free. */
49
- type LibsqlClient = Pick<Client, 'execute' | 'transaction' | 'close'>;
50
- /** Wrap a libsql client (node or web build) into the shared Database surface. */
51
- declare function libsqlDatabase(client: LibsqlClient): Database;
52
-
53
20
  /**
54
21
  * Row codec for the SQL `data` column. Plain JSON.stringify destroys
55
22
  * ArrayBuffer values ({}); attachment rows carry raw blobs, so encoding tags
@@ -116,6 +83,13 @@ declare function rebuildProjections(conn: SqlConnection): Promise<void>;
116
83
  /** Boot-time derived state: DDL + rebuild only when the guard is incompatible
117
84
  * (first run, projection version bump, or an interrupted prior rebuild). */
118
85
  declare function initializeDomain(db: Database): Promise<void>;
86
+ /** Read-only readiness check (no DDL, no writes): both real guards — the
87
+ * store schema version row and the domain projection version row — must be
88
+ * current, and every store/projection table must exist. Missing table →
89
+ * db_not_initialized; version drift or corrupt guards → schema_incompatible;
90
+ * auth/network errors propagate untouched. Used by
91
+ * openCliDb(…, { initialize: false }). */
92
+ declare function verifyReadiness(db: Database): Promise<void>;
119
93
  /** Clears derived tables after a data wipe (empty is a consistent state). */
120
94
  declare function wipeDomain(conn: SqlConnection): Promise<void>;
121
95
  declare const MAX_BODY: number;
@@ -327,4 +301,4 @@ declare function readRawSyncOps(db: Database): Promise<RawSyncOp[]>;
327
301
  */
328
302
  declare function readLegacyRows(db: Database, table: string): Promise<unknown[]>;
329
303
 
330
- export { type ApplySyncBatchOptions, BrowserTursoStorage, type Database, type LibsqlClient, MAX_BODY, type RawSyncOp, SCHEMA_TABLE, SYNC_ARCHIVE_TABLE, SYNC_OPS_TABLE, SYNC_STATE_TABLE, type SqlConnection, type SqlRow, type SqlStatement, SqlStorage, type SqlStorageOptions, type SqlValue, StorageError, type StoredSyncOp, type SyncEntry, type SyncMutation, type SyncTargetKind, type TursoSettings, applySyncBatch, clearRows, countRows, decodeRowJson, deleteRows, encodeRowJson, fetchSyncOps, getRow, getRows, handleDomainQuery, initSyncTarget, initializeDomain, initializeStore, libsqlDatabase, listRows, listRowsFromIndexMany, probeSyncTarget, putRow, putRows, readLegacyRows, readRawSyncOps, rebuildProjections, refreshDomain, replaceSyncLog, storeDefinition, validateTursoUrl, wipeDomain, wipeRows };
304
+ export { type ApplySyncBatchOptions, BrowserTursoStorage, Database, MAX_BODY, type RawSyncOp, SCHEMA_TABLE, SYNC_ARCHIVE_TABLE, SYNC_OPS_TABLE, SYNC_STATE_TABLE, SqlConnection, SqlStorage, type SqlStorageOptions, StorageError, type StoredSyncOp, type SyncEntry, type SyncMutation, type SyncTargetKind, type TursoSettings, applySyncBatch, clearRows, countRows, decodeRowJson, deleteRows, encodeRowJson, fetchSyncOps, getRow, getRows, handleDomainQuery, initSyncTarget, initializeDomain, initializeStore, listRows, listRowsFromIndexMany, probeSyncTarget, putRow, putRows, readLegacyRows, readRawSyncOps, rebuildProjections, refreshDomain, replaceSyncLog, storeDefinition, validateTursoUrl, verifyReadiness, wipeDomain, wipeRows };
@@ -1,5 +1,7 @@
1
- import { Client } from '@libsql/client';
1
+ import { S as SqlConnection, D as Database } from '../connection-DxuCLpRc.js';
2
+ export { L as LibsqlClient, a as SqlRow, b as SqlStatement, c as SqlValue, l as libsqlDatabase } from '../connection-DxuCLpRc.js';
2
3
  import { a as StoreDef, R as RangeDTO, K as KeyDTO, e as DomainQueryResult, T as TxOp, I as IStorage, S as StoreName, b as IReadOnlyStore, c as StoreType, d as IReadWriteStore, D as DomainQuery, f as IStorageTransaction } from '../wire-CiFcjo6_.js';
4
+ import '@libsql/client';
3
5
  import '@bitcobblers/wod-wiki-core';
4
6
  import '@bitcobblers/wod-wiki-lang';
5
7
 
@@ -15,41 +17,6 @@ declare class StorageError extends Error {
15
17
  constructor(status: number, message: string, code?: string | undefined);
16
18
  }
17
19
 
18
- /**
19
- * Connection contracts + a generic libsql adapter. The adapter takes a
20
- * *structural* client so the browser passes @libsql/client/web and the server
21
- * passes @libsql/client (node) — this module never imports either, keeping
22
- * the browser graph free of native drivers.
23
- *
24
- * All operations are serialized through one promise chain: the underlying
25
- * client shares a single connection, so concurrent transactions/reads could
26
- * otherwise interleave on it. Transactions run on a transaction-owned
27
- * connection (libsql interactive transaction), so writes inside a transaction
28
- * commit or roll back atomically and are not visible outside it.
29
- */
30
-
31
- type SqlValue = string | number | null;
32
- type SqlRow = Record<string, unknown>;
33
- interface SqlStatement {
34
- sql: string;
35
- params?: SqlValue[];
36
- }
37
- interface SqlConnection {
38
- query(sql: string, params?: SqlValue[]): Promise<SqlRow[]>;
39
- exec(sql: string, params?: SqlValue[]): Promise<void>;
40
- batch?(statements: SqlStatement[]): Promise<SqlRow[][]>;
41
- }
42
- interface Database extends SqlConnection {
43
- readonly dialect: 'sqlite' | 'postgres';
44
- transaction<T>(fn: (tx: SqlConnection) => Promise<T>): Promise<T>;
45
- close(): Promise<void>;
46
- }
47
- /** Minimal surface used from a libsql client (node or web build) — the real
48
- * @libsql/client types, type-only so the browser graph stays driver-free. */
49
- type LibsqlClient = Pick<Client, 'execute' | 'transaction' | 'close'>;
50
- /** Wrap a libsql client (node or web build) into the shared Database surface. */
51
- declare function libsqlDatabase(client: LibsqlClient): Database;
52
-
53
20
  /**
54
21
  * Row codec for the SQL `data` column. Plain JSON.stringify destroys
55
22
  * ArrayBuffer values ({}); attachment rows carry raw blobs, so encoding tags
@@ -116,6 +83,13 @@ declare function rebuildProjections(conn: SqlConnection): Promise<void>;
116
83
  /** Boot-time derived state: DDL + rebuild only when the guard is incompatible
117
84
  * (first run, projection version bump, or an interrupted prior rebuild). */
118
85
  declare function initializeDomain(db: Database): Promise<void>;
86
+ /** Read-only readiness check (no DDL, no writes): both real guards — the
87
+ * store schema version row and the domain projection version row — must be
88
+ * current, and every store/projection table must exist. Missing table →
89
+ * db_not_initialized; version drift or corrupt guards → schema_incompatible;
90
+ * auth/network errors propagate untouched. Used by
91
+ * openCliDb(…, { initialize: false }). */
92
+ declare function verifyReadiness(db: Database): Promise<void>;
119
93
  /** Clears derived tables after a data wipe (empty is a consistent state). */
120
94
  declare function wipeDomain(conn: SqlConnection): Promise<void>;
121
95
  declare const MAX_BODY: number;
@@ -327,4 +301,4 @@ declare function readRawSyncOps(db: Database): Promise<RawSyncOp[]>;
327
301
  */
328
302
  declare function readLegacyRows(db: Database, table: string): Promise<unknown[]>;
329
303
 
330
- export { type ApplySyncBatchOptions, BrowserTursoStorage, type Database, type LibsqlClient, MAX_BODY, type RawSyncOp, SCHEMA_TABLE, SYNC_ARCHIVE_TABLE, SYNC_OPS_TABLE, SYNC_STATE_TABLE, type SqlConnection, type SqlRow, type SqlStatement, SqlStorage, type SqlStorageOptions, type SqlValue, StorageError, type StoredSyncOp, type SyncEntry, type SyncMutation, type SyncTargetKind, type TursoSettings, applySyncBatch, clearRows, countRows, decodeRowJson, deleteRows, encodeRowJson, fetchSyncOps, getRow, getRows, handleDomainQuery, initSyncTarget, initializeDomain, initializeStore, libsqlDatabase, listRows, listRowsFromIndexMany, probeSyncTarget, putRow, putRows, readLegacyRows, readRawSyncOps, rebuildProjections, refreshDomain, replaceSyncLog, storeDefinition, validateTursoUrl, wipeDomain, wipeRows };
304
+ export { type ApplySyncBatchOptions, BrowserTursoStorage, Database, MAX_BODY, type RawSyncOp, SCHEMA_TABLE, SYNC_ARCHIVE_TABLE, SYNC_OPS_TABLE, SYNC_STATE_TABLE, SqlConnection, SqlStorage, type SqlStorageOptions, StorageError, type StoredSyncOp, type SyncEntry, type SyncMutation, type SyncTargetKind, type TursoSettings, applySyncBatch, clearRows, countRows, decodeRowJson, deleteRows, encodeRowJson, fetchSyncOps, getRow, getRows, handleDomainQuery, initSyncTarget, initializeDomain, initializeStore, listRows, listRowsFromIndexMany, probeSyncTarget, putRow, putRows, readLegacyRows, readRawSyncOps, rebuildProjections, refreshDomain, replaceSyncLog, storeDefinition, validateTursoUrl, verifyReadiness, wipeDomain, wipeRows };
@@ -1,61 +1,11 @@
1
- import { STORE_DEFS, StorageError, extractKeyPart, validateStorageRow, isRange, DB_VERSION, rowsEqual, validateStoredPins, DOMAIN_PROJECTION_VERSION, bufferToOps, stampUserOwned, bufferedGet, overlayRows, rangeFromIDB, isDirty, keyFromValue, bufferSlot, COLUMN_TYPES, keyInRange, compareKeys } from '../chunk-7ZCBM5NS.mjs';
2
- export { StorageError } from '../chunk-7ZCBM5NS.mjs';
1
+ import { STORE_DEFS, extractKeyPart, validateStorageRow, isRange, DB_VERSION, rowsEqual, validateStoredPins, DOMAIN_PROJECTION_VERSION, bufferToOps, stampUserOwned, bufferedGet, overlayRows, rangeFromIDB, isDirty, keyFromValue, bufferSlot, COLUMN_TYPES, keyInRange, compareKeys } from '../chunk-YESCCCRF.mjs';
2
+ import { libsqlDatabase } from '../chunk-6ZTAWTAP.mjs';
3
+ export { libsqlDatabase } from '../chunk-6ZTAWTAP.mjs';
4
+ import { StorageError } from '../chunk-XRQKLSOT.mjs';
5
+ export { StorageError } from '../chunk-XRQKLSOT.mjs';
3
6
  import { catalogOfItem, sourceMatches } from '@bitcobblers/wod-wiki-wql';
4
7
  import { createClient } from '@libsql/client/web';
5
8
 
6
- // src/sql/connection.ts
7
- function libsqlRows(result) {
8
- return result.rows;
9
- }
10
- function libsqlDatabase(client) {
11
- let chain = Promise.resolve();
12
- const serialize = (fn) => {
13
- const next = chain.then(fn, fn);
14
- chain = next.then(() => void 0, () => void 0);
15
- return next;
16
- };
17
- return {
18
- dialect: "sqlite",
19
- query: (sql, params = []) => serialize(() => client.execute({ sql, args: params }).then(libsqlRows)),
20
- exec: async (sql, params = []) => {
21
- await serialize(() => client.execute({ sql, args: params }));
22
- },
23
- transaction(fn) {
24
- return serialize(async () => {
25
- const tx = await client.transaction("write");
26
- try {
27
- const txConn = {
28
- query: (sql, params = []) => tx.execute({ sql, args: params }).then(libsqlRows),
29
- exec: async (sql, params = []) => {
30
- await tx.execute({ sql, args: params });
31
- },
32
- batch: async (statements) => (await tx.batch(statements.map(({ sql, params = [] }) => ({ sql, args: params })))).map(libsqlRows)
33
- };
34
- const result = await fn(txConn);
35
- await tx.commit();
36
- return result;
37
- } catch (err) {
38
- try {
39
- await tx.rollback();
40
- } catch {
41
- }
42
- const message = err instanceof Error ? err.message : String(err);
43
- for (const code of ["revision_conflict", "transaction_conflict", "invalid_session_pin"]) {
44
- if (message.includes(code)) throw new StorageError(409, message, code);
45
- }
46
- throw err;
47
- } finally {
48
- tx.close();
49
- }
50
- });
51
- },
52
- close: async () => {
53
- await chain;
54
- client.close();
55
- }
56
- };
57
- }
58
-
59
9
  // src/sql/codec.ts
60
10
  var TAG = "$binary";
61
11
  var LEN = "$bytes";
@@ -581,7 +531,7 @@ async function ensureStoreTables(conn, dialect, def) {
581
531
  BEGIN SELECT RAISE(ABORT, 'invalid_session_pin: Session pin is immutable'); END`);
582
532
  }
583
533
  if (dialect === "postgres" && ["notes", "block_revisions", "sessions"].includes(def.name)) {
584
- const condition = def.name === "block_revisions" ? `EXISTS (SELECT 1 FROM "block_revisions" old WHERE old."k0" = NEW."k0" AND old."k1" = NEW."k1" AND old."k2" = NEW."k2" AND old."data" <> NEW."data")` : def.name === "notes" ? `(NEW."data"::jsonb->>'sourceRevision')::bigint < (OLD."data"::jsonb->>'sourceRevision')::bigint OR ((NEW."data"::jsonb->'rawContent' IS DISTINCT FROM OLD."data"::jsonb->'rawContent' OR NEW."data"::jsonb->'blocks' IS DISTINCT FROM OLD."data"::jsonb->'blocks') AND (NEW."data"::jsonb->>'sourceRevision')::bigint <= (OLD."data"::jsonb->>'sourceRevision')::bigint)` : `NEW."data"::jsonb->'noteId' IS DISTINCT FROM OLD."data"::jsonb->'noteId' OR NEW."data"::jsonb->'blockId' IS DISTINCT FROM OLD."data"::jsonb->'blockId' OR NEW."data"::jsonb->'blockVersion' IS DISTINCT FROM OLD."data"::jsonb->'blockVersion'`;
534
+ const condition = def.name === "block_revisions" ? `EXISTS (SELECT 1 FROM "block_revisions" saved WHERE saved."k0" = NEW."k0" AND saved."k1" = NEW."k1" AND saved."k2" = NEW."k2" AND saved."data" <> NEW."data")` : def.name === "notes" ? `(NEW."data"::jsonb->>'sourceRevision')::bigint < (OLD."data"::jsonb->>'sourceRevision')::bigint OR ((NEW."data"::jsonb->'rawContent' IS DISTINCT FROM OLD."data"::jsonb->'rawContent' OR NEW."data"::jsonb->'blocks' IS DISTINCT FROM OLD."data"::jsonb->'blocks') AND (NEW."data"::jsonb->>'sourceRevision')::bigint <= (OLD."data"::jsonb->>'sourceRevision')::bigint)` : `NEW."data"::jsonb->'noteId' IS DISTINCT FROM OLD."data"::jsonb->'noteId' OR NEW."data"::jsonb->'blockId' IS DISTINCT FROM OLD."data"::jsonb->'blockId' OR NEW."data"::jsonb->'blockVersion' IS DISTINCT FROM OLD."data"::jsonb->'blockVersion'`;
585
535
  const code = def.name === "block_revisions" ? "revision_conflict" : def.name === "notes" ? "transaction_conflict" : "invalid_session_pin";
586
536
  const guard = `${def.name}_guard`;
587
537
  await conn.exec(`CREATE OR REPLACE FUNCTION "${guard}"() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN IF ${condition} THEN RAISE EXCEPTION '${code}'; END IF; RETURN NEW; END; $$`);
@@ -681,7 +631,7 @@ function ensureDdl(db) {
681
631
  }
682
632
  var DOMAIN_NOTE_COLS = ["note_id", "note_type", "catalog", "source_id", "source_path", "title", "title_search", "created_at", "date", "text_search", "journal", "payload"];
683
633
  var QUERY_BLOCK_COLS = ["occurrence_id", "source_note_id", "parent_note_id", "content_id", "section_key", "ordinal", "data_type", "source_id", "source_path", "catalog", "effective_date", "created_at", "note_title", "normalized_text", "journal", "payload"];
684
- var conflictUpdate = (cols, keys) => `ON CONFLICT (${keys.map((k) => `"${k}"`).join(", ")}) DO UPDATE SET ` + cols.filter((c) => !keys.includes(c)).map((c) => `"${c}" = excluded."${c}"`).join(",") + ` WHERE ` + cols.filter((col) => !keys.includes(col)).map((col) => `"${col}" IS DISTINCT FROM excluded."${col}"`).join(" OR ");
634
+ var conflictUpdate = (table, cols, keys) => `ON CONFLICT (${keys.map((k) => `"${k}"`).join(", ")}) DO UPDATE SET ` + cols.filter((c) => !keys.includes(c)).map((c) => `"${c}" = excluded."${c}"`).join(",") + ` WHERE ` + cols.filter((col) => !keys.includes(col)).map((col) => `"${table}"."${col}" IS DISTINCT FROM excluded."${col}"`).join(" OR ");
685
635
  function domainNoteRow(note) {
686
636
  const id = text(note.id);
687
637
  if (!id) return void 0;
@@ -703,7 +653,7 @@ function domainNoteRow(note) {
703
653
  }
704
654
  async function upsertDomainNotes(conn, notes) {
705
655
  const rows = notes.map(domainNoteRow).filter((r) => r !== void 0);
706
- await batchInsert(conn, "domain_note", [...DOMAIN_NOTE_COLS], rows, conflictUpdate(DOMAIN_NOTE_COLS, ["note_id"]));
656
+ await batchInsert(conn, "domain_note", [...DOMAIN_NOTE_COLS], rows, conflictUpdate("domain_note", DOMAIN_NOTE_COLS, ["note_id"]));
707
657
  }
708
658
  function queryBlockRow(block, parent) {
709
659
  const id = text(block.id);
@@ -732,7 +682,7 @@ function queryBlockRow(block, parent) {
732
682
  }
733
683
  async function upsertQueryBlocks(conn, blocks) {
734
684
  const rows = blocks.map(([b, p]) => queryBlockRow(b, p)).filter((r) => r !== void 0);
735
- await batchInsert(conn, "query_block", [...QUERY_BLOCK_COLS], rows, conflictUpdate(QUERY_BLOCK_COLS, ["occurrence_id"]));
685
+ await batchInsert(conn, "query_block", [...QUERY_BLOCK_COLS], rows, conflictUpdate("query_block", QUERY_BLOCK_COLS, ["occurrence_id"]));
736
686
  }
737
687
  function indexNoteIdentities(notes) {
738
688
  const byNoteId = /* @__PURE__ */ new Map();
@@ -932,6 +882,73 @@ async function initializeDomain(db) {
932
882
  await rebuildProjections(tx);
933
883
  });
934
884
  }
885
+ async function verifyReadiness(db) {
886
+ const isMissingRelation = (error) => {
887
+ if (typeof error !== "object" || error === null) return false;
888
+ if ("errno" in error && error.errno === "42P01") return true;
889
+ if ("code" in error && error.code === "42P01") return true;
890
+ return "code" in error && error.code === "SQLITE_ERROR" && /no such table/i.test(error instanceof Error ? error.message : String(error));
891
+ };
892
+ const readGuard = async (key) => {
893
+ const rows = await db.query(`SELECT "value" FROM "${SCHEMA_TABLE}" WHERE "key" = ?`, [key]);
894
+ if (!rows.length || typeof rows[0].value !== "string") return void 0;
895
+ try {
896
+ return JSON.parse(rows[0].value);
897
+ } catch {
898
+ throw new StorageError(500, `database guard "${key}" is corrupt; re-run initialization`, "schema_incompatible");
899
+ }
900
+ };
901
+ let schemaGuard;
902
+ let projectionGuard;
903
+ try {
904
+ schemaGuard = await readGuard("schema");
905
+ projectionGuard = await readGuard(PROJECTION_GUARD_KEY);
906
+ } catch (error) {
907
+ if (isMissingRelation(error)) {
908
+ throw new StorageError(500, "database is not initialized (schema guard table missing)", "db_not_initialized");
909
+ }
910
+ throw error;
911
+ }
912
+ const schemaVersion = schemaGuard?.version;
913
+ const projectionVersion = projectionGuard?.version;
914
+ if (typeof schemaVersion !== "number") {
915
+ throw new StorageError(500, "database is not initialized (no schema guard row)", "db_not_initialized");
916
+ }
917
+ if (typeof projectionVersion !== "number") {
918
+ throw new StorageError(500, "database is not initialized (projections never built)", "db_not_initialized");
919
+ }
920
+ if (schemaVersion > DB_VERSION) {
921
+ throw new StorageError(
922
+ 500,
923
+ `database schema v${schemaVersion} is newer than this server supports (v${DB_VERSION}); refusing to downgrade`,
924
+ "schema_incompatible"
925
+ );
926
+ }
927
+ if (schemaVersion !== DB_VERSION) {
928
+ throw new StorageError(
929
+ 500,
930
+ `database schema v${schemaVersion} is incompatible with v${DB_VERSION}; re-run initialization`,
931
+ "schema_incompatible"
932
+ );
933
+ }
934
+ if (projectionVersion !== DOMAIN_PROJECTION_VERSION) {
935
+ throw new StorageError(
936
+ 500,
937
+ `database projections v${projectionVersion} are incompatible with v${DOMAIN_PROJECTION_VERSION}; re-run initialization`,
938
+ "schema_incompatible"
939
+ );
940
+ }
941
+ for (const table of [...STORE_DEFS.map((def) => def.name), ...TABLES]) {
942
+ try {
943
+ await db.query(`SELECT * FROM "${table}" LIMIT 0`);
944
+ } catch (error) {
945
+ if (isMissingRelation(error)) {
946
+ throw new StorageError(500, `database is not initialized (missing table: ${table})`, "db_not_initialized");
947
+ }
948
+ throw error;
949
+ }
950
+ }
951
+ }
935
952
  async function wipeDomain(conn) {
936
953
  for (const t of TABLES) await conn.exec(`DELETE FROM "${t}"`);
937
954
  }
@@ -1857,6 +1874,6 @@ async function readLegacyRows(db, table) {
1857
1874
  return rows.map((row) => decodeRowJson(String(row.data), BINARY_FIELD2[table]));
1858
1875
  }
1859
1876
 
1860
- export { BrowserTursoStorage, MAX_BODY, SCHEMA_TABLE, SYNC_ARCHIVE_TABLE, SYNC_OPS_TABLE, SYNC_STATE_TABLE, SqlStorage, applySyncBatch, clearRows, countRows, decodeRowJson, deleteRows, encodeRowJson, fetchSyncOps, getRow, getRows, handleDomainQuery, initSyncTarget, initializeDomain, initializeStore, libsqlDatabase, listRows, listRowsFromIndexMany, probeSyncTarget, putRow, putRows, readLegacyRows, readRawSyncOps, rebuildProjections, refreshDomain, replaceSyncLog, storeDefinition, validateTursoUrl, wipeDomain, wipeRows };
1877
+ export { BrowserTursoStorage, MAX_BODY, SCHEMA_TABLE, SYNC_ARCHIVE_TABLE, SYNC_OPS_TABLE, SYNC_STATE_TABLE, SqlStorage, applySyncBatch, clearRows, countRows, decodeRowJson, deleteRows, encodeRowJson, fetchSyncOps, getRow, getRows, handleDomainQuery, initSyncTarget, initializeDomain, initializeStore, listRows, listRowsFromIndexMany, probeSyncTarget, putRow, putRows, readLegacyRows, readRawSyncOps, rebuildProjections, refreshDomain, replaceSyncLog, storeDefinition, validateTursoUrl, verifyReadiness, wipeDomain, wipeRows };
1861
1878
  //# sourceMappingURL=index.mjs.map
1862
1879
  //# sourceMappingURL=index.mjs.map