@rocicorp/zero 1.6.0-canary.5 → 1.6.0-canary.6

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.
Files changed (55) hide show
  1. package/out/replicache/src/kv/expo-sqlite/store.d.ts +1 -1
  2. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  3. package/out/replicache/src/kv/expo-sqlite/store.js +6 -7
  4. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  5. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  6. package/out/replicache/src/kv/op-sqlite/store.js +6 -6
  7. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  8. package/out/replicache/src/kv/sqlite-store.d.ts +6 -6
  9. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  10. package/out/replicache/src/kv/sqlite-store.js +104 -22
  11. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  12. package/out/replicache/src/kv/throw-if-closed.d.ts +1 -0
  13. package/out/replicache/src/kv/throw-if-closed.d.ts.map +1 -1
  14. package/out/replicache/src/kv/throw-if-closed.js +1 -4
  15. package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
  16. package/out/zero/package.js +1 -1
  17. package/out/zero/package.js.map +1 -1
  18. package/out/zero-cache/src/server/change-streamer.js +6 -3
  19. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  20. package/out/zero-cache/src/server/reaper.js +2 -2
  21. package/out/zero-cache/src/server/reaper.js.map +1 -1
  22. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  23. package/out/zero-cache/src/server/syncer.js +4 -4
  24. package/out/zero-cache/src/server/syncer.js.map +1 -1
  25. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +2 -2
  26. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  27. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  28. package/out/zero-cache/src/services/change-source/pg/change-source.js +2 -2
  29. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  30. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  31. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +4 -4
  32. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  33. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +1 -1
  34. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  35. package/out/zero-cache/src/services/life-cycle.js +5 -0
  36. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  37. package/out/zero-cache/src/services/view-syncer/client-handler.js +1 -1
  38. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  39. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +1 -1
  40. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  41. package/out/zero-cache/src/services/view-syncer/view-syncer.js +1 -1
  42. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  43. package/out/zero-cache/src/types/configuration-error.d.ts +4 -0
  44. package/out/zero-cache/src/types/configuration-error.d.ts.map +1 -0
  45. package/out/zero-cache/src/types/configuration-error.js +11 -0
  46. package/out/zero-cache/src/types/configuration-error.js.map +1 -0
  47. package/out/zero-cache/src/types/pg.d.ts +2 -0
  48. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  49. package/out/zero-cache/src/types/pg.js +34 -1
  50. package/out/zero-cache/src/types/pg.js.map +1 -1
  51. package/out/zero-client/src/client/version.js +1 -1
  52. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  53. package/out/zql/src/ivm/union-fan-in.js +3 -1
  54. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  55. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import type { SQLiteStoreOptions } from '../sqlite-store.ts';
2
2
  import type { StoreProvider } from '../store.ts';
3
3
  export type ExpoSQLiteStoreOptions = SQLiteStoreOptions;
4
- export declare function dropExpoSQLiteStore(name: string): Promise<void>;
4
+ export declare function dropExpoSQLiteStore(name: string, opts?: ExpoSQLiteStoreOptions): Promise<void>;
5
5
  /**
6
6
  * Creates a StoreProvider for SQLite-based stores using expo-sqlite.
7
7
  * Supports shared connections between multiple store instances with the same name,
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../../../replicache/src/kv/expo-sqlite/store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAExD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,CAAC,EAAE,sBAAsB,GAC5B,aAAa,CAMf"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../../../replicache/src/kv/expo-sqlite/store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAE/C,MAAM,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAExD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,sBAAsB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,CAAC,EAAE,sBAAsB,GAC5B,aAAa,CAMf"}
@@ -1,8 +1,8 @@
1
1
  import { SQLiteStore, dropStore } from "../sqlite-store.js";
2
2
  import { deleteDatabaseSync, openDatabaseSync } from "expo-sqlite";
3
3
  //#region ../replicache/src/kv/expo-sqlite/store.ts
4
- function dropExpoSQLiteStore(name) {
5
- return dropStore(name, (filename) => new ExpoSQLiteDatabase(filename));
4
+ function dropExpoSQLiteStore(name, opts) {
5
+ return dropStore(name, (filename) => new ExpoSQLiteDatabase(filename), opts);
6
6
  }
7
7
  /**
8
8
  * Creates a StoreProvider for SQLite-based stores using expo-sqlite.
@@ -12,7 +12,7 @@ function dropExpoSQLiteStore(name) {
12
12
  function expoSQLiteStoreProvider(opts) {
13
13
  return {
14
14
  create: (name) => new SQLiteStore(name, (name) => new ExpoSQLiteDatabase(name), opts),
15
- drop: dropExpoSQLiteStore
15
+ drop: (name) => dropExpoSQLiteStore(name, opts)
16
16
  };
17
17
  }
18
18
  var ExpoSQLitePreparedStatement = class {
@@ -20,13 +20,12 @@ var ExpoSQLitePreparedStatement = class {
20
20
  constructor(statement) {
21
21
  this.#statement = statement;
22
22
  }
23
- async firstValue(params) {
24
- const row = await (await this.#statement.executeForRawResultAsync(params)).getFirstAsync();
25
- return row === null ? void 0 : row[0];
26
- }
27
23
  async exec(params) {
28
24
  await this.#statement.executeForRawResultAsync(params);
29
25
  }
26
+ async all(params) {
27
+ return (await this.#statement.executeForRawResultAsync(params)).getAllAsync();
28
+ }
30
29
  };
31
30
  var ExpoSQLiteDatabase = class {
32
31
  #db;
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","names":["#statement","#db","#filename","#statements"],"sources":["../../../../../../replicache/src/kv/expo-sqlite/store.ts"],"sourcesContent":["import {\n deleteDatabaseSync,\n openDatabaseSync,\n type SQLiteDatabase as DB,\n type SQLiteStatement,\n} from 'expo-sqlite';\nimport type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\n\nexport type ExpoSQLiteStoreOptions = SQLiteStoreOptions;\n\nexport function dropExpoSQLiteStore(name: string): Promise<void> {\n return dropStore(name, filename => new ExpoSQLiteDatabase(filename));\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using expo-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n */\nexport function expoSQLiteStoreProvider(\n opts?: ExpoSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(name, name => new ExpoSQLiteDatabase(name), opts),\n drop: dropExpoSQLiteStore,\n };\n}\n\nclass ExpoSQLitePreparedStatement implements PreparedStatement {\n readonly #statement: SQLiteStatement;\n\n constructor(statement: SQLiteStatement) {\n this.#statement = statement;\n }\n\n async firstValue(params: string[]): Promise<string | undefined> {\n const result = await this.#statement.executeForRawResultAsync(params);\n const row = await result.getFirstAsync();\n return row === null ? undefined : row[0];\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#statement.executeForRawResultAsync(params);\n }\n}\n\nclass ExpoSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n readonly #statements: Set<SQLiteStatement> = new Set();\n\n constructor(filename: string) {\n this.#filename = filename;\n this.#db = openDatabaseSync(filename);\n }\n\n close(): void {\n for (const stmt of this.#statements) {\n stmt.finalizeSync();\n }\n this.#db.closeSync();\n }\n\n destroy(): void {\n deleteDatabaseSync(this.#filename);\n }\n\n prepare(sql: string): PreparedStatement {\n const statement = this.#db.prepareSync(sql);\n this.#statements.add(statement);\n return new ExpoSQLitePreparedStatement(statement);\n }\n\n execSync(sql: string): void {\n this.#db.execSync(sql);\n }\n}\n"],"mappings":";;;AAgBA,SAAgB,oBAAoB,MAA6B;AAC/D,QAAO,UAAU,OAAM,aAAY,IAAI,mBAAmB,SAAS,CAAC;;;;;;;AAQtE,SAAgB,wBACd,MACe;AACf,QAAO;EACL,SAAQ,SACN,IAAI,YAAY,OAAM,SAAQ,IAAI,mBAAmB,KAAK,EAAE,KAAK;EACnE,MAAM;EACP;;AAGH,IAAM,8BAAN,MAA+D;CAC7D;CAEA,YAAY,WAA4B;AACtC,QAAA,YAAkB;;CAGpB,MAAM,WAAW,QAA+C;EAE9D,MAAM,MAAM,OADG,MAAM,MAAA,UAAgB,yBAAyB,OAAO,EAC5C,eAAe;AACxC,SAAO,QAAQ,OAAO,KAAA,IAAY,IAAI;;CAGxC,MAAM,KAAK,QAAiC;AAC1C,QAAM,MAAA,UAAgB,yBAAyB,OAAO;;;AAI1D,IAAM,qBAAN,MAAmD;CACjD;CACA;CACA,8BAA6C,IAAI,KAAK;CAEtD,YAAY,UAAkB;AAC5B,QAAA,WAAiB;AACjB,QAAA,KAAW,iBAAiB,SAAS;;CAGvC,QAAc;AACZ,OAAK,MAAM,QAAQ,MAAA,WACjB,MAAK,cAAc;AAErB,QAAA,GAAS,WAAW;;CAGtB,UAAgB;AACd,qBAAmB,MAAA,SAAe;;CAGpC,QAAQ,KAAgC;EACtC,MAAM,YAAY,MAAA,GAAS,YAAY,IAAI;AAC3C,QAAA,WAAiB,IAAI,UAAU;AAC/B,SAAO,IAAI,4BAA4B,UAAU;;CAGnD,SAAS,KAAmB;AAC1B,QAAA,GAAS,SAAS,IAAI"}
1
+ {"version":3,"file":"store.js","names":["#statement","#db","#filename","#statements"],"sources":["../../../../../../replicache/src/kv/expo-sqlite/store.ts"],"sourcesContent":["import {\n deleteDatabaseSync,\n openDatabaseSync,\n type SQLiteDatabase as DB,\n type SQLiteStatement,\n} from 'expo-sqlite';\nimport type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\n\nexport type ExpoSQLiteStoreOptions = SQLiteStoreOptions;\n\nexport function dropExpoSQLiteStore(\n name: string,\n opts?: ExpoSQLiteStoreOptions,\n): Promise<void> {\n return dropStore(name, filename => new ExpoSQLiteDatabase(filename), opts);\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using expo-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n */\nexport function expoSQLiteStoreProvider(\n opts?: ExpoSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(name, name => new ExpoSQLiteDatabase(name), opts),\n drop: name => dropExpoSQLiteStore(name, opts),\n };\n}\n\nclass ExpoSQLitePreparedStatement implements PreparedStatement {\n readonly #statement: SQLiteStatement;\n\n constructor(statement: SQLiteStatement) {\n this.#statement = statement;\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#statement.executeForRawResultAsync(params);\n }\n\n async all(params: string[]): Promise<unknown[][]> {\n const result = await this.#statement.executeForRawResultAsync(params);\n return result.getAllAsync() as Promise<unknown[][]>;\n }\n}\n\nclass ExpoSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n readonly #statements: Set<SQLiteStatement> = new Set();\n\n constructor(filename: string) {\n this.#filename = filename;\n this.#db = openDatabaseSync(filename);\n }\n\n close(): void {\n for (const stmt of this.#statements) {\n stmt.finalizeSync();\n }\n this.#db.closeSync();\n }\n\n destroy(): void {\n deleteDatabaseSync(this.#filename);\n }\n\n prepare(sql: string): PreparedStatement {\n const statement = this.#db.prepareSync(sql);\n this.#statements.add(statement);\n return new ExpoSQLitePreparedStatement(statement);\n }\n\n execSync(sql: string): void {\n this.#db.execSync(sql);\n }\n}\n"],"mappings":";;;AAgBA,SAAgB,oBACd,MACA,MACe;AACf,QAAO,UAAU,OAAM,aAAY,IAAI,mBAAmB,SAAS,EAAE,KAAK;;;;;;;AAQ5E,SAAgB,wBACd,MACe;AACf,QAAO;EACL,SAAQ,SACN,IAAI,YAAY,OAAM,SAAQ,IAAI,mBAAmB,KAAK,EAAE,KAAK;EACnE,OAAM,SAAQ,oBAAoB,MAAM,KAAK;EAC9C;;AAGH,IAAM,8BAAN,MAA+D;CAC7D;CAEA,YAAY,WAA4B;AACtC,QAAA,YAAkB;;CAGpB,MAAM,KAAK,QAAiC;AAC1C,QAAM,MAAA,UAAgB,yBAAyB,OAAO;;CAGxD,MAAM,IAAI,QAAwC;AAEhD,UADe,MAAM,MAAA,UAAgB,yBAAyB,OAAO,EACvD,aAAa;;;AAI/B,IAAM,qBAAN,MAAmD;CACjD;CACA;CACA,8BAA6C,IAAI,KAAK;CAEtD,YAAY,UAAkB;AAC5B,QAAA,WAAiB;AACjB,QAAA,KAAW,iBAAiB,SAAS;;CAGvC,QAAc;AACZ,OAAK,MAAM,QAAQ,MAAA,WACjB,MAAK,cAAc;AAErB,QAAA,GAAS,WAAW;;CAGtB,UAAgB;AACd,qBAAmB,MAAA,SAAe;;CAGpC,QAAQ,KAAgC;EACtC,MAAM,YAAY,MAAA,GAAS,YAAY,IAAI;AAC3C,QAAA,WAAiB,IAAI,UAAU;AAC/B,SAAO,IAAI,4BAA4B,UAAU;;CAGnD,SAAS,KAAmB;AAC1B,QAAA,GAAS,SAAS,IAAI"}
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../../../replicache/src/kv/op-sqlite/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAG/C,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,GAAG;IAEtD,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,oBAAoB,GAC1B,aAAa,CAUf"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../../../../replicache/src/kv/op-sqlite/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAG/C,MAAM,MAAM,oBAAoB,GAAG,kBAAkB,GAAG;IAEtD,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAaF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,CAAC,EAAE,oBAAoB,GAC1B,aAAa,CAUf"}
@@ -1,8 +1,8 @@
1
1
  import { SQLiteStore, dropStore } from "../sqlite-store.js";
2
2
  import { open } from "./types.js";
3
3
  //#region ../replicache/src/kv/op-sqlite/store.ts
4
- function dropOpSQLiteStore(name) {
5
- return dropStore(name, (filename, opts) => new OpSQLiteDatabase(filename, opts));
4
+ function dropOpSQLiteStore(name, opts) {
5
+ return dropStore(name, (filename, options) => new OpSQLiteDatabase(filename, options), opts);
6
6
  }
7
7
  /**
8
8
  * Creates a StoreProvider for SQLite-based stores using @op-engineering/op-sqlite.
@@ -13,7 +13,7 @@ function dropOpSQLiteStore(name) {
13
13
  function opSQLiteStoreProvider(opts) {
14
14
  return {
15
15
  create: (name) => new SQLiteStore(name, (name, options) => new OpSQLiteDatabase(name, options), opts),
16
- drop: dropOpSQLiteStore
16
+ drop: (name) => dropOpSQLiteStore(name, opts)
17
17
  };
18
18
  }
19
19
  var OpSQLitePreparedStatement = class {
@@ -23,12 +23,12 @@ var OpSQLitePreparedStatement = class {
23
23
  this.#db = db;
24
24
  this.#sql = sql;
25
25
  }
26
- async firstValue(params) {
27
- return (await this.#db.executeRaw(this.#sql, params))[0]?.[0];
28
- }
29
26
  async exec(params) {
30
27
  await this.#db.executeRaw(this.#sql, params);
31
28
  }
29
+ all(params) {
30
+ return this.#db.executeRaw(this.#sql, params);
31
+ }
32
32
  };
33
33
  var OpSQLiteDatabase = class {
34
34
  #db;
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","names":["#db","#sql","#filename"],"sources":["../../../../../../replicache/src/kv/op-sqlite/store.ts"],"sourcesContent":["import type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\nimport {open, type DB} from './types.ts';\n\nexport type OpSQLiteStoreOptions = SQLiteStoreOptions & {\n // OpSQLite-specific options\n location?: 'default' | 'Library' | 'Documents' | 'Temporary';\n encryptionKey?: string;\n};\n\nfunction dropOpSQLiteStore(name: string): Promise<void> {\n return dropStore(\n name,\n (filename, opts) => new OpSQLiteDatabase(filename, opts),\n );\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using @op-engineering/op-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport function opSQLiteStoreProvider(\n opts?: OpSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(\n name,\n (name, options) => new OpSQLiteDatabase(name, options),\n opts,\n ),\n drop: dropOpSQLiteStore,\n };\n}\n\nclass OpSQLitePreparedStatement implements PreparedStatement {\n readonly #db: DB;\n readonly #sql: string;\n\n constructor(db: DB, sql: string) {\n this.#db = db;\n this.#sql = sql;\n }\n\n async firstValue(params: string[]): Promise<string | undefined> {\n const rows = await this.#db.executeRaw(this.#sql, params);\n return rows[0]?.[0];\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#db.executeRaw(this.#sql, params);\n }\n}\n\nclass OpSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n\n constructor(filename: string, opts?: OpSQLiteStoreOptions) {\n this.#filename = filename;\n const openOpts: {\n name: string;\n location?: string;\n encryptionKey?: string;\n } = {name: filename};\n\n if (opts?.location) {\n openOpts.location = opts.location;\n }\n if (opts?.encryptionKey) {\n openOpts.encryptionKey = opts.encryptionKey;\n }\n\n this.#db = open(openOpts);\n }\n\n close(): void {\n this.#db.close();\n }\n\n destroy(): void {\n // OpSQLite uses delete method on the database instance\n // We need to create a temporary connection to delete the database\n try {\n const tempDb = open({name: this.#filename});\n tempDb.delete();\n tempDb.close();\n } catch (_error) {\n // Database might not exist, which is fine\n }\n }\n\n prepare(sql: string): PreparedStatement {\n return new OpSQLitePreparedStatement(this.#db, sql);\n }\n\n execSync(sql: string): void {\n this.#db.executeRawSync(sql, []);\n }\n}\n"],"mappings":";;;AAeA,SAAS,kBAAkB,MAA6B;AACtD,QAAO,UACL,OACC,UAAU,SAAS,IAAI,iBAAiB,UAAU,KAAK,CACzD;;;;;;;;AASH,SAAgB,sBACd,MACe;AACf,QAAO;EACL,SAAQ,SACN,IAAI,YACF,OACC,MAAM,YAAY,IAAI,iBAAiB,MAAM,QAAQ,EACtD,KACD;EACH,MAAM;EACP;;AAGH,IAAM,4BAAN,MAA6D;CAC3D;CACA;CAEA,YAAY,IAAQ,KAAa;AAC/B,QAAA,KAAW;AACX,QAAA,MAAY;;CAGd,MAAM,WAAW,QAA+C;AAE9D,UADa,MAAM,MAAA,GAAS,WAAW,MAAA,KAAW,OAAO,EAC7C,KAAK;;CAGnB,MAAM,KAAK,QAAiC;AAC1C,QAAM,MAAA,GAAS,WAAW,MAAA,KAAW,OAAO;;;AAIhD,IAAM,mBAAN,MAAiD;CAC/C;CACA;CAEA,YAAY,UAAkB,MAA6B;AACzD,QAAA,WAAiB;EACjB,MAAM,WAIF,EAAC,MAAM,UAAS;AAEpB,MAAI,MAAM,SACR,UAAS,WAAW,KAAK;AAE3B,MAAI,MAAM,cACR,UAAS,gBAAgB,KAAK;AAGhC,QAAA,KAAW,KAAK,SAAS;;CAG3B,QAAc;AACZ,QAAA,GAAS,OAAO;;CAGlB,UAAgB;AAGd,MAAI;GACF,MAAM,SAAS,KAAK,EAAC,MAAM,MAAA,UAAe,CAAC;AAC3C,UAAO,QAAQ;AACf,UAAO,OAAO;WACP,QAAQ;;CAKnB,QAAQ,KAAgC;AACtC,SAAO,IAAI,0BAA0B,MAAA,IAAU,IAAI;;CAGrD,SAAS,KAAmB;AAC1B,QAAA,GAAS,eAAe,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"store.js","names":["#db","#sql","#filename"],"sources":["../../../../../../replicache/src/kv/op-sqlite/store.ts"],"sourcesContent":["import type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\nimport {open, type DB} from './types.ts';\n\nexport type OpSQLiteStoreOptions = SQLiteStoreOptions & {\n // OpSQLite-specific options\n location?: 'default' | 'Library' | 'Documents' | 'Temporary';\n encryptionKey?: string;\n};\n\nfunction dropOpSQLiteStore(\n name: string,\n opts?: OpSQLiteStoreOptions,\n): Promise<void> {\n return dropStore(\n name,\n (filename, options) => new OpSQLiteDatabase(filename, options),\n opts,\n );\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using @op-engineering/op-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport function opSQLiteStoreProvider(\n opts?: OpSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(\n name,\n (name, options) => new OpSQLiteDatabase(name, options),\n opts,\n ),\n drop: name => dropOpSQLiteStore(name, opts),\n };\n}\n\nclass OpSQLitePreparedStatement implements PreparedStatement {\n readonly #db: DB;\n readonly #sql: string;\n\n constructor(db: DB, sql: string) {\n this.#db = db;\n this.#sql = sql;\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#db.executeRaw(this.#sql, params);\n }\n\n all(params: string[]): Promise<unknown[][]> {\n return this.#db.executeRaw(this.#sql, params);\n }\n}\n\nclass OpSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n\n constructor(filename: string, opts?: OpSQLiteStoreOptions) {\n this.#filename = filename;\n const openOpts: {\n name: string;\n location?: string;\n encryptionKey?: string;\n } = {name: filename};\n\n if (opts?.location) {\n openOpts.location = opts.location;\n }\n if (opts?.encryptionKey) {\n openOpts.encryptionKey = opts.encryptionKey;\n }\n\n this.#db = open(openOpts);\n }\n\n close(): void {\n this.#db.close();\n }\n\n destroy(): void {\n // OpSQLite uses delete method on the database instance\n // We need to create a temporary connection to delete the database\n try {\n const tempDb = open({name: this.#filename});\n tempDb.delete();\n tempDb.close();\n } catch (_error) {\n // Database might not exist, which is fine\n }\n }\n\n prepare(sql: string): PreparedStatement {\n return new OpSQLitePreparedStatement(this.#db, sql);\n }\n\n execSync(sql: string): void {\n this.#db.executeRawSync(sql, []);\n }\n}\n"],"mappings":";;;AAeA,SAAS,kBACP,MACA,MACe;AACf,QAAO,UACL,OACC,UAAU,YAAY,IAAI,iBAAiB,UAAU,QAAQ,EAC9D,KACD;;;;;;;;AASH,SAAgB,sBACd,MACe;AACf,QAAO;EACL,SAAQ,SACN,IAAI,YACF,OACC,MAAM,YAAY,IAAI,iBAAiB,MAAM,QAAQ,EACtD,KACD;EACH,OAAM,SAAQ,kBAAkB,MAAM,KAAK;EAC5C;;AAGH,IAAM,4BAAN,MAA6D;CAC3D;CACA;CAEA,YAAY,IAAQ,KAAa;AAC/B,QAAA,KAAW;AACX,QAAA,MAAY;;CAGd,MAAM,KAAK,QAAiC;AAC1C,QAAM,MAAA,GAAS,WAAW,MAAA,KAAW,OAAO;;CAG9C,IAAI,QAAwC;AAC1C,SAAO,MAAA,GAAS,WAAW,MAAA,KAAW,OAAO;;;AAIjD,IAAM,mBAAN,MAAiD;CAC/C;CACA;CAEA,YAAY,UAAkB,MAA6B;AACzD,QAAA,WAAiB;EACjB,MAAM,WAIF,EAAC,MAAM,UAAS;AAEpB,MAAI,MAAM,SACR,UAAS,WAAW,KAAK;AAE3B,MAAI,MAAM,cACR,UAAS,gBAAgB,KAAK;AAGhC,QAAA,KAAW,KAAK,SAAS;;CAG3B,QAAc;AACZ,QAAA,GAAS,OAAO;;CAGlB,UAAgB;AAGd,MAAI;GACF,MAAM,SAAS,KAAK,EAAC,MAAM,MAAA,UAAe,CAAC;AAC3C,UAAO,QAAQ;AACf,UAAO,OAAO;WACP,QAAQ;;CAKnB,QAAQ,KAAgC;AACtC,SAAO,IAAI,0BAA0B,MAAA,IAAU,IAAI;;CAGrD,SAAS,KAAmB;AAC1B,QAAA,GAAS,eAAe,KAAK,EAAE,CAAC"}
@@ -3,14 +3,10 @@ import type { Read, Store, Write } from './store.ts';
3
3
  import { WriteImplBase } from './write-impl-base.ts';
4
4
  /**
5
5
  * A SQLite prepared statement.
6
- *
7
- * `run` executes the statement with optional parameters.
8
- * `all` executes the statement and returns the result rows.
9
- * `finalize` releases the statement.
10
6
  */
11
7
  export interface PreparedStatement {
12
- firstValue(params: string[]): Promise<unknown>;
13
8
  exec(params: string[]): Promise<void>;
9
+ all(params: string[]): Promise<unknown[][]>;
14
10
  }
15
11
  export interface SQLiteDatabase {
16
12
  /**
@@ -47,6 +43,8 @@ export declare function safeFilename(name: string): string;
47
43
  export type PreparedStatements = {
48
44
  has: PreparedStatement;
49
45
  get: PreparedStatement;
46
+ hasMany: PreparedStatement;
47
+ getMany: PreparedStatement;
50
48
  put: PreparedStatement;
51
49
  del: PreparedStatement;
52
50
  };
@@ -55,6 +53,8 @@ export interface SQLiteStoreOptions {
55
53
  journalMode?: 'WAL' | 'DELETE';
56
54
  synchronous?: 'NORMAL' | 'FULL';
57
55
  readUncommitted?: boolean;
56
+ /** Directory in which to create the SQLite file. Defaults to the process CWD. */
57
+ directory?: string | undefined;
58
58
  }
59
59
  /**
60
60
  * Common database setup logic shared between expo-sqlite and op-sqlite implementations.
@@ -77,5 +77,5 @@ export declare class SQLiteWrite extends WriteImplBase implements Write {
77
77
  get closed(): boolean;
78
78
  }
79
79
  export declare function clearAllNamedStoresForTesting(): void;
80
- export declare function dropStore(name: string, createDelegate: (filename: string, opts?: SQLiteStoreOptions) => SQLiteDatabase): Promise<void>;
80
+ export declare function dropStore(name: string, createDelegate: (filename: string, opts?: SQLiteStoreOptions) => SQLiteDatabase, opts?: SQLiteStoreOptions): Promise<void>;
81
81
  //# sourceMappingURL=sqlite-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { deepFreeze } from "../frozen-json.js";
2
- import { throwIfStoreClosed, throwIfTransactionClosed, transactionIsClosedRejection } from "./throw-if-closed.js";
2
+ import { maybeTransactionIsClosedRejection, throwIfStoreClosed, transactionError } from "./throw-if-closed.js";
3
3
  import { WriteImplBase, deleteSentinel } from "./write-impl-base.js";
4
4
  import { RWLock } from "@rocicorp/lock";
5
5
  //#region ../replicache/src/kv/sqlite-store.ts
@@ -14,8 +14,8 @@ var SQLiteStore = class {
14
14
  #entry;
15
15
  #closed = false;
16
16
  constructor(name, create, opts) {
17
- this.#filename = safeFilename(name);
18
- this.#entry = getOrCreateEntry(name, create, opts);
17
+ this.#filename = resolveFilename(name, opts);
18
+ this.#entry = getOrCreateEntry(this.#filename, create, opts);
19
19
  }
20
20
  async read() {
21
21
  throwIfStoreClosed(this);
@@ -52,6 +52,11 @@ var SQLiteStore = class {
52
52
  function safeFilename(name) {
53
53
  return name.replace(/[^a-zA-Z0-9]/g, "_");
54
54
  }
55
+ function resolveFilename(name, opts) {
56
+ const safe = safeFilename(name);
57
+ const dir = opts?.directory;
58
+ return dir ? `${dir}/${safe}` : safe;
59
+ }
55
60
  /**
56
61
  * Common database setup logic shared between expo-sqlite and op-sqlite implementations.
57
62
  * Configures SQLite pragmas, creates the entry table, and prepares common statements.
@@ -70,28 +75,107 @@ function setupDatabase(delegate, opts) {
70
75
  return {
71
76
  has: delegate.prepare(`SELECT 1 FROM entry WHERE key = ? LIMIT 1`),
72
77
  get: delegate.prepare("SELECT value FROM entry WHERE key = ?"),
78
+ hasMany: delegate.prepare(`SELECT key FROM entry WHERE key IN (SELECT value FROM json_each(?))`),
79
+ getMany: delegate.prepare(`SELECT key, value FROM entry WHERE key IN (SELECT value FROM json_each(?))`),
73
80
  put: delegate.prepare(`INSERT OR REPLACE INTO entry (key, value)
74
81
  SELECT e.value->>0, e.value->1 FROM json_each(?) e`),
75
82
  del: delegate.prepare(`DELETE FROM entry WHERE key IN (SELECT value FROM json_each(?))`)
76
83
  };
77
84
  }
85
+ var CB_STRIDE = 2;
86
+ var CB_RESOLVE = 0;
87
+ var CB_REJECT = 1;
88
+ function rejectAll(callbacks, e) {
89
+ for (let i = CB_REJECT; i < callbacks.length; i += CB_STRIDE) callbacks[i](e);
90
+ }
91
+ function resolveGet(resolve, reject, raw) {
92
+ try {
93
+ resolve(raw === void 0 ? void 0 : deepFreeze(JSON.parse(raw)));
94
+ } catch (e) {
95
+ reject(e);
96
+ }
97
+ }
98
+ async function flushGets(keys, callbacks, ps) {
99
+ let rows;
100
+ try {
101
+ rows = keys.length === 1 ? await ps.get.all([keys[0]]) : await ps.getMany.all([JSON.stringify(keys)]);
102
+ } catch (e) {
103
+ rejectAll(callbacks, e);
104
+ return;
105
+ }
106
+ if (keys.length === 1) {
107
+ resolveGet(callbacks[CB_RESOLVE], callbacks[CB_REJECT], rows[0]?.[0]);
108
+ return;
109
+ }
110
+ const resultMap = new Map(rows);
111
+ for (let i = 0; i < keys.length; i++) resolveGet(callbacks[i * CB_STRIDE + CB_RESOLVE], callbacks[i * CB_STRIDE + CB_REJECT], resultMap.get(keys[i]));
112
+ }
113
+ async function flushHas(keys, callbacks, ps) {
114
+ let rows;
115
+ try {
116
+ rows = keys.length === 1 ? await ps.has.all([keys[0]]) : await ps.hasMany.all([JSON.stringify(keys)]);
117
+ } catch (e) {
118
+ rejectAll(callbacks, e);
119
+ return;
120
+ }
121
+ if (keys.length === 1) {
122
+ callbacks[CB_RESOLVE](rows.length > 0);
123
+ return;
124
+ }
125
+ const existingKeys = new Set(rows.map((row) => row[0]));
126
+ for (let i = 0; i < keys.length; i++) callbacks[i * CB_STRIDE + CB_RESOLVE](existingKeys.has(keys[i]));
127
+ }
78
128
  var SQLiteStoreRead = class {
79
129
  #release;
80
- #closed = false;
81
130
  #preparedStatements;
131
+ #closed = false;
132
+ #pendingGetKeys = [];
133
+ #pendingGetCallbacks = [];
134
+ #pendingHasKeys = [];
135
+ #pendingHasCallbacks = [];
136
+ #scheduled = false;
82
137
  constructor(release, preparedStatements) {
83
138
  this.#release = release;
84
139
  this.#preparedStatements = preparedStatements;
85
140
  }
86
- async has(key) {
87
- throwIfTransactionClosed(this);
88
- return await this.#preparedStatements.has.firstValue([key]) !== void 0;
141
+ has(key) {
142
+ return maybeTransactionIsClosedRejection(this) ?? new Promise((resolve, reject) => {
143
+ this.#pendingHasKeys.push(key);
144
+ this.#pendingHasCallbacks.push(resolve, reject);
145
+ this.#scheduleLookup();
146
+ });
89
147
  }
90
- async get(key) {
91
- throwIfTransactionClosed(this);
92
- const value = await this.#preparedStatements.get.firstValue([key]);
93
- if (!value) return;
94
- return deepFreeze(JSON.parse(value));
148
+ get(key) {
149
+ return maybeTransactionIsClosedRejection(this) ?? new Promise((resolve, reject) => {
150
+ this.#pendingGetKeys.push(key);
151
+ this.#pendingGetCallbacks.push(resolve, reject);
152
+ this.#scheduleLookup();
153
+ });
154
+ }
155
+ #scheduleLookup() {
156
+ if (!this.#scheduled) {
157
+ this.#scheduled = true;
158
+ queueMicrotask(() => {
159
+ this.#scheduled = false;
160
+ const ps = this.#preparedStatements;
161
+ const getKeys = this.#pendingGetKeys;
162
+ this.#pendingGetKeys = [];
163
+ const getCallbacks = this.#pendingGetCallbacks;
164
+ this.#pendingGetCallbacks = [];
165
+ const hasKeys = this.#pendingHasKeys;
166
+ this.#pendingHasKeys = [];
167
+ const hasCallbacks = this.#pendingHasCallbacks;
168
+ this.#pendingHasCallbacks = [];
169
+ if (this.#closed) {
170
+ const e = transactionError();
171
+ rejectAll(getCallbacks, e);
172
+ rejectAll(hasCallbacks, e);
173
+ return;
174
+ }
175
+ if (getKeys.length > 0) flushGets(getKeys, getCallbacks, ps);
176
+ if (hasKeys.length > 0) flushHas(hasKeys, hasCallbacks, ps);
177
+ });
178
+ }
95
179
  }
96
180
  release() {
97
181
  if (!this.#closed) {
@@ -116,17 +200,16 @@ var SQLiteWrite = class extends WriteImplBase {
116
200
  this.#preparedStatements = preparedStatements;
117
201
  }
118
202
  async commit() {
119
- if (this.#closed) return transactionIsClosedRejection();
203
+ if (this.#closed) throw transactionError();
120
204
  const deleteKeys = [];
121
205
  for (const entry of this._pending) if (entry[1] === deleteSentinel) {
122
206
  deleteKeys.push(entry[0]);
123
207
  this._pending.delete(entry[0]);
124
208
  }
125
209
  const delP = deleteKeys.length > 0 ? this.#preparedStatements.del.exec([JSON.stringify(deleteKeys)]) : void 0;
126
- const upP = this._pending.size > 0 ? this.#preparedStatements.put.exec([JSON.stringify([...this._pending])]) : void 0;
127
- if (delP && upP) await Promise.all([delP, upP]);
128
- else if (delP) await delP;
129
- else if (upP) await upP;
210
+ const putP = this._pending.size > 0 ? this.#preparedStatements.put.exec([JSON.stringify([...this._pending])]) : void 0;
211
+ if (putP) await putP;
212
+ if (delP) await delP;
130
213
  this.#dbDelegate.execSync("COMMIT");
131
214
  this._pending.clear();
132
215
  this.#committed = true;
@@ -155,8 +238,7 @@ var stores = /* @__PURE__ */ new Map();
155
238
  * This implements the shared connection pattern where multiple stores with the same
156
239
  * name share the same database connection, lock, and delegate.
157
240
  */
158
- function getOrCreateEntry(name, create, opts) {
159
- const filename = safeFilename(name);
241
+ function getOrCreateEntry(filename, create, opts) {
160
242
  const entry = stores.get(filename);
161
243
  if (entry) {
162
244
  entry.refCount++;
@@ -192,8 +274,8 @@ function clearAllNamedStoresForTesting() {
192
274
  for (const entry of stores.values()) entry.db.close();
193
275
  stores.clear();
194
276
  }
195
- function dropStore(name, createDelegate) {
196
- const filename = safeFilename(name);
277
+ function dropStore(name, createDelegate, opts) {
278
+ const filename = resolveFilename(name, opts);
197
279
  const entry = stores.get(filename);
198
280
  if (entry) {
199
281
  try {
@@ -201,7 +283,7 @@ function dropStore(name, createDelegate) {
201
283
  } catch {}
202
284
  stores.delete(filename);
203
285
  }
204
- const tempDelegate = createDelegate(filename);
286
+ const tempDelegate = createDelegate(filename, opts);
205
287
  try {
206
288
  tempDelegate.close();
207
289
  } catch {}
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-store.js","names":["#filename","#entry","#closed","#release","#preparedStatements","#dbDelegate","#committed"],"sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"sourcesContent":["import {RWLock} from '@rocicorp/lock';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {deepFreeze} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n throwIfStoreClosed,\n throwIfTransactionClosed,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\n/**\n * A SQLite prepared statement.\n *\n * `run` executes the statement with optional parameters.\n * `all` executes the statement and returns the result rows.\n * `finalize` releases the statement.\n */\nexport interface PreparedStatement {\n firstValue(params: string[]): Promise<unknown>;\n exec(params: string[]): Promise<void>;\n}\n\nexport interface SQLiteDatabase {\n /**\n * Close the database connection.\n */\n close(): void;\n\n /**\n * Destroy or delete the database (e.g. delete file).\n */\n destroy(): void;\n\n /**\n * Prepare a SQL string, returning a statement you can execute.\n * E.g. `const stmt = db.prepare(\"SELECT * FROM todos WHERE id=?\");`\n */\n prepare(sql: string): PreparedStatement;\n\n // for PRAGMA statements, schema creation and transaction control.\n execSync(sql: string): void;\n}\n\nexport type CreateSQLiteDatabase = (\n filename: string,\n opts?: SQLiteStoreOptions,\n) => SQLiteDatabase;\n\n/**\n * SQLite-based implementation of the Store interface using a configurable delegate.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport class SQLiteStore implements Store {\n readonly #filename: string;\n readonly #entry: StoreEntry;\n\n #closed = false;\n\n constructor(\n name: string,\n create: CreateSQLiteDatabase,\n opts?: SQLiteStoreOptions,\n ) {\n this.#filename = safeFilename(name);\n this.#entry = getOrCreateEntry(name, create, opts);\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n\n const entry = this.#entry;\n const {db, lock, preparedStatements} = entry;\n const release = await lock.read();\n\n // Start shared read transaction if this is the first reader\n // This ensures consistent reads across all concurrent readers\n if (entry.activeReaders === 0) {\n db.execSync('BEGIN');\n }\n entry.activeReaders++;\n\n return new SQLiteStoreRead(() => {\n entry.activeReaders--;\n // Commit shared read transaction when last reader finishes\n if (entry.activeReaders === 0) {\n db.execSync('COMMIT');\n }\n release();\n }, preparedStatements);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n\n const {lock, db, preparedStatements} = this.#entry;\n const release = await lock.write();\n\n // At this point, RWLock guarantees no active readers\n // The last reader would have already committed the shared transaction\n\n db.execSync('BEGIN IMMEDIATE');\n\n return new SQLiteWrite(release, db, preparedStatements);\n }\n\n async close(): Promise<void> {\n if (this.#closed) {\n return;\n }\n\n const {lock, db} = this.#entry;\n // Wait for all readers and writers to finish.\n const writeRelease = await lock.write();\n\n // Handle reference counting for shared stores - only close database\n // when this is the last store instance using it\n decrementStoreRefCount(this.#filename, db);\n\n this.#closed = true;\n writeRelease();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport function safeFilename(name: string): string {\n return name.replace(/[^a-zA-Z0-9]/g, '_');\n}\n\nexport type PreparedStatements = {\n has: PreparedStatement;\n get: PreparedStatement;\n put: PreparedStatement;\n del: PreparedStatement;\n};\n\nexport interface SQLiteStoreOptions {\n // Common options\n busyTimeout?: number;\n journalMode?: 'WAL' | 'DELETE';\n synchronous?: 'NORMAL' | 'FULL';\n readUncommitted?: boolean;\n}\n\n/**\n * Common database setup logic shared between expo-sqlite and op-sqlite implementations.\n * Configures SQLite pragmas, creates the entry table, and prepares common statements.\n */\n\nexport function setupDatabase(\n delegate: SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): PreparedStatements {\n // Configure SQLite pragmas for optimal performance\n delegate.execSync(`PRAGMA busy_timeout = ${opts?.busyTimeout ?? 200}`);\n delegate.execSync(`PRAGMA journal_mode = '${opts?.journalMode ?? 'WAL'}'`);\n delegate.execSync(`PRAGMA synchronous = '${opts?.synchronous ?? 'NORMAL'}'`);\n delegate.execSync(\n `PRAGMA read_uncommitted = ${Boolean(opts?.readUncommitted)}`,\n );\n\n // Create the entry table\n delegate.execSync(`\n CREATE TABLE IF NOT EXISTS entry (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n ) WITHOUT ROWID\n `);\n\n // Prepare common statements\n return {\n has: delegate.prepare(`SELECT 1 FROM entry WHERE key = ? LIMIT 1`),\n get: delegate.prepare('SELECT value FROM entry WHERE key = ?'),\n put: delegate.prepare(\n `INSERT OR REPLACE INTO entry (key, value)\n SELECT e.value->>0, e.value->1 FROM json_each(?) e`,\n ),\n del: delegate.prepare(\n `DELETE FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n };\n}\n\nexport class SQLiteStoreRead implements Read {\n #release: () => void;\n #closed = false;\n #preparedStatements: PreparedStatements;\n\n constructor(release: () => void, preparedStatements: PreparedStatements) {\n this.#release = release;\n this.#preparedStatements = preparedStatements;\n }\n\n async has(key: string): Promise<boolean> {\n throwIfTransactionClosed(this);\n const value = await this.#preparedStatements.has.firstValue([key]);\n return value !== undefined;\n }\n\n async get(key: string): Promise<ReadonlyJSONValue | undefined> {\n throwIfTransactionClosed(this);\n const value = await this.#preparedStatements.get.firstValue([key]);\n if (!value) {\n return undefined;\n }\n\n const parsedValue = JSON.parse(value as string) as ReadonlyJSONValue;\n return deepFreeze(parsedValue);\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n this.#release();\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport class SQLiteWrite extends WriteImplBase implements Write {\n readonly #release: () => void;\n readonly #dbDelegate: SQLiteDatabase;\n readonly #preparedStatements: PreparedStatements;\n #committed = false;\n #closed = false;\n\n constructor(\n release: () => void,\n dbDelegate: SQLiteDatabase,\n preparedStatements: PreparedStatements,\n ) {\n super(new SQLiteStoreRead(() => undefined, preparedStatements));\n this.#release = release;\n this.#dbDelegate = dbDelegate;\n this.#preparedStatements = preparedStatements;\n }\n\n async commit(): Promise<void> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n\n const deleteKeys: string[] = [];\n for (const entry of this._pending) {\n if (entry[1] === deleteSentinel) {\n deleteKeys.push(entry[0]);\n this._pending.delete(entry[0]);\n }\n }\n\n const delP =\n deleteKeys.length > 0\n ? this.#preparedStatements.del.exec([JSON.stringify(deleteKeys)])\n : undefined;\n const upP =\n this._pending.size > 0\n ? this.#preparedStatements.put.exec([\n JSON.stringify([...this._pending]),\n ])\n : undefined;\n\n if (delP && upP) {\n await Promise.all([delP, upP]);\n } else if (delP) {\n await delP;\n } else if (upP) {\n await upP;\n }\n\n this.#dbDelegate.execSync('COMMIT');\n this._pending.clear();\n this.#committed = true;\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n super.release();\n let rollbackError: unknown;\n if (!this.#committed) {\n try {\n this.#dbDelegate.execSync('ROLLBACK');\n } catch (e) {\n rollbackError = e;\n }\n }\n\n this.#release();\n if (rollbackError !== undefined) {\n throw rollbackError;\n }\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\ntype StoreEntry = {\n readonly lock: RWLock;\n readonly db: SQLiteDatabase;\n refCount: number;\n activeReaders: number;\n preparedStatements: PreparedStatements;\n};\n\n// Global map to share database connections between multiple store instances with the same name\nconst stores = new Map<string, StoreEntry>();\n\n/**\n * Gets an existing store entry or creates a new one if it doesn't exist.\n * This implements the shared connection pattern where multiple stores with the same\n * name share the same database connection, lock, and delegate.\n */\nfunction getOrCreateEntry(\n name: string,\n create: (filename: string, opts?: SQLiteStoreOptions) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): StoreEntry {\n const filename = safeFilename(name);\n const entry = stores.get(filename);\n\n if (entry) {\n entry.refCount++;\n return entry;\n }\n\n const dbDelegate = create(filename, opts);\n const preparedStatements = setupDatabase(dbDelegate, opts);\n\n const lock = new RWLock();\n\n const newEntry: StoreEntry = {\n lock,\n db: dbDelegate,\n refCount: 1,\n activeReaders: 0,\n preparedStatements,\n };\n stores.set(filename, newEntry);\n return newEntry;\n}\n\n/**\n * Decrements the reference count for a shared store and cleans up resources\n * when the last reference is released.\n */\n\nfunction decrementStoreRefCount(\n filename: string,\n dbDelegate: SQLiteDatabase,\n): void {\n const entry = stores.get(filename);\n if (entry) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n dbDelegate.close();\n stores.delete(filename);\n }\n }\n}\nexport function clearAllNamedStoresForTesting(): void {\n for (const entry of stores.values()) {\n entry.db.close();\n }\n stores.clear();\n}\n\nexport function dropStore(\n name: string,\n createDelegate: (\n filename: string,\n opts?: SQLiteStoreOptions,\n ) => SQLiteDatabase,\n): Promise<void> {\n const filename = safeFilename(name);\n const entry = stores.get(filename);\n if (entry) {\n try {\n entry.db.close();\n } catch {\n // Ignore close errors\n }\n stores.delete(filename);\n }\n\n // Create a temporary delegate to handle database deletion\n const tempDelegate = createDelegate(filename);\n try {\n // we close the db before destroying it - this\n // caused an issue with expo-sqlite since it requires this\n tempDelegate.close();\n } catch {\n // Ignore close errors\n }\n try {\n tempDelegate.destroy();\n } catch {\n // Destroy errors shouldn't be fatal; the file may already be gone or locked\n }\n\n return Promise.resolve();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-store.js","names":["#filename","#entry","#closed","#release","#preparedStatements","#pendingHasKeys","#pendingHasCallbacks","#scheduleLookup","#pendingGetKeys","#pendingGetCallbacks","#scheduled","#dbDelegate","#committed"],"sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"sourcesContent":["import {RWLock} from '@rocicorp/lock';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {deepFreeze} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n maybeTransactionIsClosedRejection,\n throwIfStoreClosed,\n transactionError,\n} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\n/**\n * A SQLite prepared statement.\n */\nexport interface PreparedStatement {\n exec(params: string[]): Promise<void>;\n all(params: string[]): Promise<unknown[][]>;\n}\n\nexport interface SQLiteDatabase {\n /**\n * Close the database connection.\n */\n close(): void;\n\n /**\n * Destroy or delete the database (e.g. delete file).\n */\n destroy(): void;\n\n /**\n * Prepare a SQL string, returning a statement you can execute.\n * E.g. `const stmt = db.prepare(\"SELECT * FROM todos WHERE id=?\");`\n */\n prepare(sql: string): PreparedStatement;\n\n // for PRAGMA statements, schema creation and transaction control.\n execSync(sql: string): void;\n}\n\nexport type CreateSQLiteDatabase = (\n filename: string,\n opts?: SQLiteStoreOptions,\n) => SQLiteDatabase;\n\n/**\n * SQLite-based implementation of the Store interface using a configurable delegate.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport class SQLiteStore implements Store {\n readonly #filename: string;\n readonly #entry: StoreEntry;\n\n #closed = false;\n\n constructor(\n name: string,\n create: CreateSQLiteDatabase,\n opts?: SQLiteStoreOptions,\n ) {\n this.#filename = resolveFilename(name, opts);\n this.#entry = getOrCreateEntry(this.#filename, create, opts);\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n\n const entry = this.#entry;\n const {db, lock, preparedStatements} = entry;\n const release = await lock.read();\n\n // Start shared read transaction if this is the first reader\n // This ensures consistent reads across all concurrent readers\n if (entry.activeReaders === 0) {\n db.execSync('BEGIN');\n }\n entry.activeReaders++;\n\n return new SQLiteStoreRead(() => {\n entry.activeReaders--;\n // Commit shared read transaction when last reader finishes\n if (entry.activeReaders === 0) {\n db.execSync('COMMIT');\n }\n release();\n }, preparedStatements);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n\n const {lock, db, preparedStatements} = this.#entry;\n const release = await lock.write();\n\n // At this point, RWLock guarantees no active readers\n // The last reader would have already committed the shared transaction\n\n db.execSync('BEGIN IMMEDIATE');\n\n return new SQLiteWrite(release, db, preparedStatements);\n }\n\n async close(): Promise<void> {\n if (this.#closed) {\n return;\n }\n\n const {lock, db} = this.#entry;\n // Wait for all readers and writers to finish.\n const writeRelease = await lock.write();\n\n // Handle reference counting for shared stores - only close database\n // when this is the last store instance using it\n decrementStoreRefCount(this.#filename, db);\n\n this.#closed = true;\n writeRelease();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport function safeFilename(name: string): string {\n return name.replace(/[^a-zA-Z0-9]/g, '_');\n}\n\nfunction resolveFilename(name: string, opts?: SQLiteStoreOptions): string {\n const safe = safeFilename(name);\n const dir = opts?.directory;\n return dir ? `${dir}/${safe}` : safe;\n}\n\nexport type PreparedStatements = {\n has: PreparedStatement;\n get: PreparedStatement;\n hasMany: PreparedStatement;\n getMany: PreparedStatement;\n put: PreparedStatement;\n del: PreparedStatement;\n};\n\nexport interface SQLiteStoreOptions {\n // Common options\n busyTimeout?: number;\n journalMode?: 'WAL' | 'DELETE';\n synchronous?: 'NORMAL' | 'FULL';\n readUncommitted?: boolean;\n /** Directory in which to create the SQLite file. Defaults to the process CWD. */\n directory?: string | undefined;\n}\n\n/**\n * Common database setup logic shared between expo-sqlite and op-sqlite implementations.\n * Configures SQLite pragmas, creates the entry table, and prepares common statements.\n */\n\nexport function setupDatabase(\n delegate: SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): PreparedStatements {\n // Configure SQLite pragmas for optimal performance\n delegate.execSync(`PRAGMA busy_timeout = ${opts?.busyTimeout ?? 200}`);\n delegate.execSync(`PRAGMA journal_mode = '${opts?.journalMode ?? 'WAL'}'`);\n delegate.execSync(`PRAGMA synchronous = '${opts?.synchronous ?? 'NORMAL'}'`);\n delegate.execSync(\n `PRAGMA read_uncommitted = ${Boolean(opts?.readUncommitted)}`,\n );\n\n // Create the entry table\n delegate.execSync(`\n CREATE TABLE IF NOT EXISTS entry (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n ) WITHOUT ROWID\n `);\n\n // Prepare common statements\n return {\n has: delegate.prepare(`SELECT 1 FROM entry WHERE key = ? LIMIT 1`),\n get: delegate.prepare('SELECT value FROM entry WHERE key = ?'),\n hasMany: delegate.prepare(\n `SELECT key FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n getMany: delegate.prepare(\n `SELECT key, value FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n put: delegate.prepare(\n `INSERT OR REPLACE INTO entry (key, value)\n SELECT e.value->>0, e.value->1 FROM json_each(?) e`,\n ),\n del: delegate.prepare(\n `DELETE FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n };\n}\n\n// Callbacks are stored as striped pairs: [resolve, reject, resolve, reject, ...]\nconst CB_STRIDE = 2;\nconst CB_RESOLVE = 0;\nconst CB_REJECT = 1;\n\ntype GetResolve = (v: ReadonlyJSONValue | undefined) => void;\ntype HasResolve = (v: boolean) => void;\ntype Reject = (e: unknown) => void;\n\nfunction rejectAll(callbacks: unknown[], e: unknown): void {\n for (let i = CB_REJECT; i < callbacks.length; i += CB_STRIDE) {\n (callbacks[i] as Reject)(e);\n }\n}\n\nfunction resolveGet(\n resolve: GetResolve,\n reject: Reject,\n raw: string | undefined,\n): void {\n try {\n resolve(\n raw === undefined\n ? undefined\n : deepFreeze(JSON.parse(raw) as ReadonlyJSONValue),\n );\n } catch (e) {\n reject(e);\n }\n}\n\nasync function flushGets(\n keys: string[],\n callbacks: unknown[],\n ps: PreparedStatements,\n): Promise<void> {\n let rows: unknown[][];\n try {\n rows =\n keys.length === 1\n ? await ps.get.all([keys[0]])\n : await ps.getMany.all([JSON.stringify(keys)]);\n } catch (e) {\n rejectAll(callbacks, e);\n return;\n }\n if (keys.length === 1) {\n resolveGet(\n callbacks[CB_RESOLVE] as GetResolve,\n callbacks[CB_REJECT] as Reject,\n rows[0]?.[0] as string | undefined,\n );\n return;\n }\n const resultMap = new Map(rows as [string, string][]);\n for (let i = 0; i < keys.length; i++) {\n resolveGet(\n callbacks[i * CB_STRIDE + CB_RESOLVE] as GetResolve,\n callbacks[i * CB_STRIDE + CB_REJECT] as Reject,\n resultMap.get(keys[i]),\n );\n }\n}\n\nasync function flushHas(\n keys: string[],\n callbacks: unknown[],\n ps: PreparedStatements,\n): Promise<void> {\n let rows: unknown[][];\n try {\n rows =\n keys.length === 1\n ? await ps.has.all([keys[0]])\n : await ps.hasMany.all([JSON.stringify(keys)]);\n } catch (e) {\n rejectAll(callbacks, e);\n return;\n }\n if (keys.length === 1) {\n (callbacks[CB_RESOLVE] as HasResolve)(rows.length > 0);\n return;\n }\n const existingKeys = new Set(rows.map(row => row[0] as string));\n for (let i = 0; i < keys.length; i++) {\n (callbacks[i * CB_STRIDE + CB_RESOLVE] as HasResolve)(\n existingKeys.has(keys[i]),\n );\n }\n}\n\nexport class SQLiteStoreRead implements Read {\n readonly #release: () => void;\n readonly #preparedStatements: PreparedStatements;\n #closed = false;\n #pendingGetKeys: string[] = [];\n #pendingGetCallbacks: unknown[] = [];\n #pendingHasKeys: string[] = [];\n #pendingHasCallbacks: unknown[] = [];\n #scheduled = false;\n\n constructor(release: () => void, preparedStatements: PreparedStatements) {\n this.#release = release;\n this.#preparedStatements = preparedStatements;\n }\n\n has(key: string): Promise<boolean> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n new Promise((resolve, reject) => {\n this.#pendingHasKeys.push(key);\n this.#pendingHasCallbacks.push(resolve, reject);\n this.#scheduleLookup();\n })\n );\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n new Promise((resolve, reject) => {\n this.#pendingGetKeys.push(key);\n this.#pendingGetCallbacks.push(resolve, reject);\n this.#scheduleLookup();\n })\n );\n }\n\n #scheduleLookup(): void {\n if (!this.#scheduled) {\n this.#scheduled = true;\n queueMicrotask(() => {\n this.#scheduled = false;\n\n const ps = this.#preparedStatements;\n const getKeys = this.#pendingGetKeys;\n this.#pendingGetKeys = [];\n const getCallbacks = this.#pendingGetCallbacks;\n this.#pendingGetCallbacks = [];\n const hasKeys = this.#pendingHasKeys;\n this.#pendingHasKeys = [];\n const hasCallbacks = this.#pendingHasCallbacks;\n this.#pendingHasCallbacks = [];\n\n if (this.#closed) {\n const e = transactionError();\n rejectAll(getCallbacks, e);\n rejectAll(hasCallbacks, e);\n return;\n }\n\n if (getKeys.length > 0) {\n void flushGets(getKeys, getCallbacks, ps);\n }\n if (hasKeys.length > 0) {\n void flushHas(hasKeys, hasCallbacks, ps);\n }\n });\n }\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n this.#release();\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport class SQLiteWrite extends WriteImplBase implements Write {\n readonly #release: () => void;\n readonly #dbDelegate: SQLiteDatabase;\n readonly #preparedStatements: PreparedStatements;\n #committed = false;\n #closed = false;\n\n constructor(\n release: () => void,\n dbDelegate: SQLiteDatabase,\n preparedStatements: PreparedStatements,\n ) {\n super(new SQLiteStoreRead(() => undefined, preparedStatements));\n this.#release = release;\n this.#dbDelegate = dbDelegate;\n this.#preparedStatements = preparedStatements;\n }\n\n async commit(): Promise<void> {\n if (this.#closed) {\n throw transactionError();\n }\n\n const deleteKeys: string[] = [];\n for (const entry of this._pending) {\n if (entry[1] === deleteSentinel) {\n deleteKeys.push(entry[0]);\n this._pending.delete(entry[0]);\n }\n }\n\n const delP =\n deleteKeys.length > 0\n ? this.#preparedStatements.del.exec([JSON.stringify(deleteKeys)])\n : undefined;\n const putP =\n this._pending.size > 0\n ? this.#preparedStatements.put.exec([\n JSON.stringify([...this._pending]),\n ])\n : undefined;\n\n if (putP) await putP;\n if (delP) await delP;\n\n this.#dbDelegate.execSync('COMMIT');\n this._pending.clear();\n this.#committed = true;\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n super.release();\n let rollbackError: unknown;\n if (!this.#committed) {\n try {\n this.#dbDelegate.execSync('ROLLBACK');\n } catch (e) {\n rollbackError = e;\n }\n }\n this.#release();\n if (rollbackError !== undefined) {\n throw rollbackError;\n }\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\ntype StoreEntry = {\n readonly lock: RWLock;\n readonly db: SQLiteDatabase;\n refCount: number;\n activeReaders: number;\n preparedStatements: PreparedStatements;\n};\n\n// Global map to share database connections between multiple store instances with the same name\nconst stores = new Map<string, StoreEntry>();\n\n/**\n * Gets an existing store entry or creates a new one if it doesn't exist.\n * This implements the shared connection pattern where multiple stores with the same\n * name share the same database connection, lock, and delegate.\n */\nfunction getOrCreateEntry(\n filename: string,\n create: (filename: string, opts?: SQLiteStoreOptions) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): StoreEntry {\n const entry = stores.get(filename);\n\n if (entry) {\n entry.refCount++;\n return entry;\n }\n\n const dbDelegate = create(filename, opts);\n const preparedStatements = setupDatabase(dbDelegate, opts);\n\n const lock = new RWLock();\n\n const newEntry: StoreEntry = {\n lock,\n db: dbDelegate,\n refCount: 1,\n activeReaders: 0,\n preparedStatements,\n };\n stores.set(filename, newEntry);\n return newEntry;\n}\n\n/**\n * Decrements the reference count for a shared store and cleans up resources\n * when the last reference is released.\n */\n\nfunction decrementStoreRefCount(\n filename: string,\n dbDelegate: SQLiteDatabase,\n): void {\n const entry = stores.get(filename);\n if (entry) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n dbDelegate.close();\n stores.delete(filename);\n }\n }\n}\nexport function clearAllNamedStoresForTesting(): void {\n for (const entry of stores.values()) {\n entry.db.close();\n }\n stores.clear();\n}\n\nexport function dropStore(\n name: string,\n createDelegate: (\n filename: string,\n opts?: SQLiteStoreOptions,\n ) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): Promise<void> {\n const filename = resolveFilename(name, opts);\n const entry = stores.get(filename);\n if (entry) {\n try {\n entry.db.close();\n } catch {\n // Ignore close errors\n }\n stores.delete(filename);\n }\n\n // Create a temporary delegate to handle database deletion\n const tempDelegate = createDelegate(filename, opts);\n try {\n // we close the db before destroying it - this\n // caused an issue with expo-sqlite since it requires this\n tempDelegate.close();\n } catch {\n // Ignore close errors\n }\n try {\n tempDelegate.destroy();\n } catch {\n // Destroy errors shouldn't be fatal; the file may already be gone or locked\n }\n\n return Promise.resolve();\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export declare function transactionError(): Error;
1
2
  export declare function throwIfStoreClosed(store: {
2
3
  readonly closed: boolean;
3
4
  }): void;
@@ -1 +1 @@
1
- {"version":3,"file":"throw-if-closed.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/throw-if-closed.ts"],"names":[],"mappings":"AAQA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAC,GAAG,IAAI,CAI1E;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,GAAG,IAAI,CAIP;AAED,wBAAgB,4BAA4B,mBAE3C;AAED,wBAAgB,iCAAiC,CAAC,WAAW,EAAE;IAC7D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,SAAS,CAE7B;AAED,wBAAgB,sBAAsB,mBAErC"}
1
+ {"version":3,"file":"throw-if-closed.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/throw-if-closed.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,IAAI,KAAK,CAExC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CAAC,GAAG,IAAI,CAI1E;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,GAAG,IAAI,CAIP;AAED,wBAAgB,4BAA4B,mBAE3C;AAED,wBAAgB,iCAAiC,CAAC,WAAW,EAAE;IAC7D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,SAAS,CAE7B;AAED,wBAAgB,sBAAsB,mBAErC"}
@@ -8,9 +8,6 @@ function transactionError() {
8
8
  function throwIfStoreClosed(store) {
9
9
  if (store.closed) throw storeError();
10
10
  }
11
- function throwIfTransactionClosed(transaction) {
12
- if (transaction.closed) throw transactionError();
13
- }
14
11
  function transactionIsClosedRejection() {
15
12
  return Promise.reject(transactionError());
16
13
  }
@@ -21,6 +18,6 @@ function storeIsClosedRejection() {
21
18
  return Promise.reject(storeError());
22
19
  }
23
20
  //#endregion
24
- export { maybeTransactionIsClosedRejection, storeIsClosedRejection, throwIfStoreClosed, throwIfTransactionClosed, transactionIsClosedRejection };
21
+ export { maybeTransactionIsClosedRejection, storeIsClosedRejection, throwIfStoreClosed, transactionError, transactionIsClosedRejection };
25
22
 
26
23
  //# sourceMappingURL=throw-if-closed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"throw-if-closed.js","names":[],"sources":["../../../../../replicache/src/kv/throw-if-closed.ts"],"sourcesContent":["function storeError(): Error {\n return new Error('Store is closed');\n}\n\nfunction transactionError(): Error {\n return new Error('Transaction is closed');\n}\n\nexport function throwIfStoreClosed(store: {readonly closed: boolean}): void {\n if (store.closed) {\n throw storeError();\n }\n}\n\nexport function throwIfTransactionClosed(transaction: {\n readonly closed: boolean;\n}): void {\n if (transaction.closed) {\n throw transactionError();\n }\n}\n\nexport function transactionIsClosedRejection() {\n return Promise.reject(transactionError());\n}\n\nexport function maybeTransactionIsClosedRejection(transaction: {\n readonly closed: boolean;\n}): Promise<never> | undefined {\n return transaction.closed ? transactionIsClosedRejection() : undefined;\n}\n\nexport function storeIsClosedRejection() {\n return Promise.reject(storeError());\n}\n"],"mappings":";AAAA,SAAS,aAAoB;AAC3B,wBAAO,IAAI,MAAM,kBAAkB;;AAGrC,SAAS,mBAA0B;AACjC,wBAAO,IAAI,MAAM,wBAAwB;;AAG3C,SAAgB,mBAAmB,OAAyC;AAC1E,KAAI,MAAM,OACR,OAAM,YAAY;;AAItB,SAAgB,yBAAyB,aAEhC;AACP,KAAI,YAAY,OACd,OAAM,kBAAkB;;AAI5B,SAAgB,+BAA+B;AAC7C,QAAO,QAAQ,OAAO,kBAAkB,CAAC;;AAG3C,SAAgB,kCAAkC,aAEnB;AAC7B,QAAO,YAAY,SAAS,8BAA8B,GAAG,KAAA;;AAG/D,SAAgB,yBAAyB;AACvC,QAAO,QAAQ,OAAO,YAAY,CAAC"}
1
+ {"version":3,"file":"throw-if-closed.js","names":[],"sources":["../../../../../replicache/src/kv/throw-if-closed.ts"],"sourcesContent":["function storeError(): Error {\n return new Error('Store is closed');\n}\n\nexport function transactionError(): Error {\n return new Error('Transaction is closed');\n}\n\nexport function throwIfStoreClosed(store: {readonly closed: boolean}): void {\n if (store.closed) {\n throw storeError();\n }\n}\n\nexport function throwIfTransactionClosed(transaction: {\n readonly closed: boolean;\n}): void {\n if (transaction.closed) {\n throw transactionError();\n }\n}\n\nexport function transactionIsClosedRejection() {\n return Promise.reject(transactionError());\n}\n\nexport function maybeTransactionIsClosedRejection(transaction: {\n readonly closed: boolean;\n}): Promise<never> | undefined {\n return transaction.closed ? transactionIsClosedRejection() : undefined;\n}\n\nexport function storeIsClosedRejection() {\n return Promise.reject(storeError());\n}\n"],"mappings":";AAAA,SAAS,aAAoB;AAC3B,wBAAO,IAAI,MAAM,kBAAkB;;AAGrC,SAAgB,mBAA0B;AACxC,wBAAO,IAAI,MAAM,wBAAwB;;AAG3C,SAAgB,mBAAmB,OAAyC;AAC1E,KAAI,MAAM,OACR,OAAM,YAAY;;AAYtB,SAAgB,+BAA+B;AAC7C,QAAO,QAAQ,OAAO,kBAAkB,CAAC;;AAG3C,SAAgB,kCAAkC,aAEnB;AAC7B,QAAO,YAAY,SAAS,8BAA8B,GAAG,KAAA;;AAG/D,SAAgB,yBAAyB;AACvC,QAAO,QAAQ,OAAO,YAAY,CAAC"}
@@ -1,6 +1,6 @@
1
1
  var package_default = {
2
2
  name: "@rocicorp/zero",
3
- version: "1.6.0-canary.5",
3
+ version: "1.6.0-canary.6",
4
4
  description: "Zero is a web framework for serverless web development.",
5
5
  homepage: "https://zero.rocicorp.dev",
6
6
  bugs: { "url": "https://bugs.rocicorp.dev" },
@@ -1 +1 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.6.0-canary.5\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.203.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.62.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.203.0\",\n \"@opentelemetry/resources\": \"^2.0.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.0.1\",\n \"@opentelemetry/sdk-node\": \"^0.203.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.0.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^5.4.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.0.18\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.0\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"js-xxhash\": \"^4.0.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.45.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"tsx\": \"^4.21.0\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"^4.1.5\",\n \"analyze-query\": \"0.0.0\",\n \"ast-to-zql\": \"0.0.0\",\n \"expo-sqlite\": \">=15\",\n \"replicache\": \"15.2.1\",\n \"shared\": \"0.0.0\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"8.0.3\",\n \"vitest\": \"^4.1.5\",\n \"zero-cache\": \"0.0.0\",\n \"zero-client\": \"0.0.0\",\n \"zero-pg\": \"0.0.0\",\n \"zero-react\": \"0.0.0\",\n \"zero-server\": \"0.0.0\",\n \"zero-solid\": \"0.0.0\",\n \"zqlite\": \"0.0.0\"\n },\n \"peerDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"expo-sqlite\": \">=15\",\n \"kysely\": \"^0.28.16\"\n },\n \"peerDependenciesMeta\": {\n \"kysely\": {\n \"optional\": true\n },\n \"expo-sqlite\": {\n \"optional\": true\n },\n \"@op-engineering/op-sqlite\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \">=22\"\n }\n}"],"mappings":""}
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.6.0-canary.6\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.203.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.62.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.203.0\",\n \"@opentelemetry/resources\": \"^2.0.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.0.1\",\n \"@opentelemetry/sdk-node\": \"^0.203.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.0.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^5.4.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.0.18\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.0\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"js-xxhash\": \"^4.0.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.45.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"tsx\": \"^4.21.0\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"^4.1.5\",\n \"analyze-query\": \"0.0.0\",\n \"ast-to-zql\": \"0.0.0\",\n \"expo-sqlite\": \">=15\",\n \"replicache\": \"15.2.1\",\n \"shared\": \"0.0.0\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"8.0.3\",\n \"vitest\": \"^4.1.5\",\n \"zero-cache\": \"0.0.0\",\n \"zero-client\": \"0.0.0\",\n \"zero-pg\": \"0.0.0\",\n \"zero-react\": \"0.0.0\",\n \"zero-server\": \"0.0.0\",\n \"zero-solid\": \"0.0.0\",\n \"zqlite\": \"0.0.0\"\n },\n \"peerDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"expo-sqlite\": \">=15\",\n \"kysely\": \"^0.28.16\"\n },\n \"peerDependenciesMeta\": {\n \"kysely\": {\n \"optional\": true\n },\n \"expo-sqlite\": {\n \"optional\": true\n },\n \"@op-engineering/op-sqlite\": {\n \"optional\": true\n }\n },\n \"engines\": {\n \"node\": \">=22\"\n }\n}"],"mappings":""}
@@ -4,7 +4,7 @@ import { parentWorker, singleProcessMode } from "../types/processes.js";
4
4
  import { getShardConfig } from "../types/shards.js";
5
5
  import { getNormalizedZeroConfig } from "../config/zero-config.js";
6
6
  import { DatabaseInitError } from "../../../zqlite/src/db.js";
7
- import { pgClient } from "../types/pg.js";
7
+ import { connectPgClient } from "../types/pg.js";
8
8
  import { exitAfter, runUntilKilled } from "../services/life-cycle.js";
9
9
  import { createLogContext } from "./logging.js";
10
10
  import { getServerContext } from "../config/server-context.js";
@@ -37,7 +37,7 @@ async function runWorker(parent, env, ...argv) {
37
37
  startOtelAuto(createLogContext(config, "change-streamer", 0, false), "change-streamer", 0);
38
38
  lc = createLogContext(config, "change-streamer");
39
39
  initEventSink(lc, config);
40
- const changeDB = pgClient(lc, change.db, "change-streamer", { max: change.maxConns }, { sendStringAsJson: true });
40
+ const changeDB = await connectPgClient(lc, change.db, "change-streamer", { max: change.maxConns }, { sendStringAsJson: true });
41
41
  warmupConnections(lc, changeDB, "change").catch(() => {});
42
42
  const { autoReset, replicationLag } = config;
43
43
  const shard = getShardConfig(config);
@@ -88,7 +88,10 @@ async function runWorker(parent, env, ...argv) {
88
88
  parent.send(["ready", { ready: true }]);
89
89
  return runUntilKilled(lc, parent, changeStreamerWebServer, monitor);
90
90
  }
91
- if (!singleProcessMode()) exitAfter(lc, () => runWorker(must(parentWorker), process.env, ...process.argv.slice(2)).catch((e) => publishCriticalEvent(lc, replicationStatusError(lc, "Initializing", e))));
91
+ if (!singleProcessMode()) exitAfter(lc, () => runWorker(must(parentWorker), process.env, ...process.argv.slice(2)).catch(async (e) => {
92
+ await publishCriticalEvent(lc, replicationStatusError(lc, "Initializing", e));
93
+ throw e;
94
+ }));
92
95
  //#endregion
93
96
  export { runWorker as default };
94
97