bun-query-builder 0.1.33 → 0.1.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/cli.js CHANGED
@@ -11664,8 +11664,9 @@ async function getConfig() {
11664
11664
  alias: "qb",
11665
11665
  defaultConfig: defaultConfig4
11666
11666
  });
11667
+ setConfig(_config);
11667
11668
  }
11668
- return _config;
11669
+ return config5;
11669
11670
  }
11670
11671
  function setConfig(userConfig) {
11671
11672
  if (userConfig.dialect && _lastConfiguredDialect && userConfig.dialect !== _lastConfiguredDialect) {
@@ -11972,6 +11973,43 @@ function createSQLiteSQL(filename) {
11972
11973
  return Promise.reject(error);
11973
11974
  }
11974
11975
  };
11976
+ let txDepth = 0;
11977
+ sqlFunction.begin = async (fnOrName, maybeFn) => {
11978
+ const fn = typeof fnOrName === "function" ? fnOrName : maybeFn;
11979
+ if (typeof fn !== "function")
11980
+ throw new TypeError("[query-builder] sqlite begin(): a transaction callback is required");
11981
+ const isSavepoint = txDepth > 0;
11982
+ const spName = `qb_sp_${txDepth}`;
11983
+ if (isSavepoint)
11984
+ wrapper.run(`SAVEPOINT ${spName}`);
11985
+ else
11986
+ wrapper.run("BEGIN");
11987
+ txDepth++;
11988
+ try {
11989
+ const result = await fn(sqlFunction);
11990
+ txDepth--;
11991
+ if (isSavepoint)
11992
+ wrapper.run(`RELEASE SAVEPOINT ${spName}`);
11993
+ else
11994
+ wrapper.run("COMMIT");
11995
+ return result;
11996
+ } catch (err) {
11997
+ txDepth--;
11998
+ try {
11999
+ if (isSavepoint) {
12000
+ wrapper.run(`ROLLBACK TO SAVEPOINT ${spName}`);
12001
+ wrapper.run(`RELEASE SAVEPOINT ${spName}`);
12002
+ } else {
12003
+ wrapper.run("ROLLBACK");
12004
+ }
12005
+ } catch {}
12006
+ throw err;
12007
+ }
12008
+ };
12009
+ sqlFunction.savepoint = sqlFunction.begin;
12010
+ sqlFunction.beginDistributed = async () => {
12011
+ throw new Error("[query-builder] beginDistributed() (two-phase commit) is not supported on SQLite. Use begin()/transaction().");
12012
+ };
11975
12013
  sqlFunction._wrapper = wrapper;
11976
12014
  return sqlFunction;
11977
12015
  }
@@ -15891,12 +15929,15 @@ function createQueryBuilder(state) {
15891
15929
  async transaction(fn, options) {
15892
15930
  const defaults = state?.txDefaults;
15893
15931
  const opts = { ...defaults, ...options };
15932
+ const txConn = state?.sql ?? bunSql;
15933
+ const nested = state?.inTransaction === true;
15934
+ const txMethod = nested && typeof txConn?.savepoint === "function" ? "savepoint" : "begin";
15894
15935
  const runWith = async (attempt2) => {
15895
15936
  opts.logger?.({ type: "start", attempt: attempt2 });
15896
15937
  const start = Date.now();
15897
- return await bunSql.begin(async (tx) => {
15898
- const qb = createQueryBuilder({ sql: tx, meta, schema });
15899
- if (opts?.isolation) {
15938
+ return await txConn[txMethod](async (tx) => {
15939
+ const qb = createQueryBuilder({ sql: tx, meta, schema, inTransaction: true });
15940
+ if (opts?.isolation && !nested) {
15900
15941
  const level = opts.isolation;
15901
15942
  const upper = level === "read committed" ? "READ COMMITTED" : level === "repeatable read" ? "REPEATABLE READ" : "SERIALIZABLE";
15902
15943
  if (config5.dialect === "postgres") {
@@ -15961,7 +16002,8 @@ function createQueryBuilder(state) {
15961
16002
  });
15962
16003
  },
15963
16004
  async beginDistributed(name, fn) {
15964
- const res = await bunSql.beginDistributed(name, async (tx) => {
16005
+ const txConn = state?.sql ?? bunSql;
16006
+ const res = await txConn.beginDistributed(name, async (tx) => {
15965
16007
  const qb = createQueryBuilder({ sql: tx, meta, schema });
15966
16008
  return await fn(qb);
15967
16009
  });
@@ -30111,7 +30153,7 @@ function getPrefix() {
30111
30153
  }
30112
30154
  var prefix = getPrefix();
30113
30155
  // package.json
30114
- var version2 = "0.1.33";
30156
+ var version2 = "0.1.35";
30115
30157
 
30116
30158
  // bin/cli.ts
30117
30159
  init_actions();
package/dist/client.d.ts CHANGED
@@ -386,6 +386,7 @@ declare interface InternalState {
386
386
  meta?: SchemaMeta
387
387
  schema?: any
388
388
  txDefaults?: TransactionOptions
389
+ inTransaction?: boolean
389
390
  }
390
391
  declare interface TxBackoff { baseMs?: number, maxMs?: number, factor?: number, jitter?: boolean }
391
392
  declare interface TxLoggerEvent { type: 'start' | 'retry' | 'commit' | 'rollback' | 'error', attempt: number, error?: any, durationMs?: number }
package/dist/config.d.ts CHANGED
@@ -10,6 +10,26 @@ export declare function getPlaceholder(index: number): string;
10
10
  * MySQL/SQLite: ?, ?, ?
11
11
  */
12
12
  export declare function getPlaceholders(count: number, startIndex?: number): string;
13
+ /**
14
+ * Load the query-builder config from a config file (`query-builder.config.ts`,
15
+ * `.config/query-builder.ts`, etc.) and environment variables via bunfig, then
16
+ * MERGE it into the live, process-wide `config` singleton so every reader
17
+ * (dialect dispatch, placeholders, soft-deletes, the model layer, …) sees it.
18
+ *
19
+ * Call this once at application boot if you keep configuration in a file:
20
+ *
21
+ * ```ts
22
+ * import { getConfig } from 'bun-query-builder'
23
+ * await getConfig() // applies query-builder.config.ts + env to the runtime
24
+ * ```
25
+ *
26
+ * It is intentionally explicit/async: the builder otherwise runs purely off the
27
+ * synchronous `config` singleton (defaults + any `setConfig`), which keeps
28
+ * `bun --compile` and test behavior deterministic — auto-loading a file in the
29
+ * background would make early queries race the load. Previously this wrote the
30
+ * loaded config to a private `_config` variable that nothing else read, so a
31
+ * config file silently never took effect; it now routes through `setConfig`.
32
+ */
13
33
  export declare function getConfig(): Promise<QueryBuilderConfig>;
14
34
  export declare function setConfig(userConfig: Partial<QueryBuilderConfig>): void;
15
35
  export declare const defaultConfig: QueryBuilderConfig;
package/dist/src/index.js CHANGED
@@ -11664,8 +11664,9 @@ async function getConfig() {
11664
11664
  alias: "qb",
11665
11665
  defaultConfig: defaultConfig4
11666
11666
  });
11667
+ setConfig(_config);
11667
11668
  }
11668
- return _config;
11669
+ return config5;
11669
11670
  }
11670
11671
  function setConfig(userConfig) {
11671
11672
  if (userConfig.dialect && _lastConfiguredDialect && userConfig.dialect !== _lastConfiguredDialect) {
@@ -11972,6 +11973,43 @@ function createSQLiteSQL(filename) {
11972
11973
  return Promise.reject(error);
11973
11974
  }
11974
11975
  };
11976
+ let txDepth = 0;
11977
+ sqlFunction.begin = async (fnOrName, maybeFn) => {
11978
+ const fn = typeof fnOrName === "function" ? fnOrName : maybeFn;
11979
+ if (typeof fn !== "function")
11980
+ throw new TypeError("[query-builder] sqlite begin(): a transaction callback is required");
11981
+ const isSavepoint = txDepth > 0;
11982
+ const spName = `qb_sp_${txDepth}`;
11983
+ if (isSavepoint)
11984
+ wrapper.run(`SAVEPOINT ${spName}`);
11985
+ else
11986
+ wrapper.run("BEGIN");
11987
+ txDepth++;
11988
+ try {
11989
+ const result = await fn(sqlFunction);
11990
+ txDepth--;
11991
+ if (isSavepoint)
11992
+ wrapper.run(`RELEASE SAVEPOINT ${spName}`);
11993
+ else
11994
+ wrapper.run("COMMIT");
11995
+ return result;
11996
+ } catch (err) {
11997
+ txDepth--;
11998
+ try {
11999
+ if (isSavepoint) {
12000
+ wrapper.run(`ROLLBACK TO SAVEPOINT ${spName}`);
12001
+ wrapper.run(`RELEASE SAVEPOINT ${spName}`);
12002
+ } else {
12003
+ wrapper.run("ROLLBACK");
12004
+ }
12005
+ } catch {}
12006
+ throw err;
12007
+ }
12008
+ };
12009
+ sqlFunction.savepoint = sqlFunction.begin;
12010
+ sqlFunction.beginDistributed = async () => {
12011
+ throw new Error("[query-builder] beginDistributed() (two-phase commit) is not supported on SQLite. Use begin()/transaction().");
12012
+ };
11975
12013
  sqlFunction._wrapper = wrapper;
11976
12014
  return sqlFunction;
11977
12015
  }
@@ -15891,12 +15929,15 @@ function createQueryBuilder(state) {
15891
15929
  async transaction(fn, options) {
15892
15930
  const defaults = state?.txDefaults;
15893
15931
  const opts = { ...defaults, ...options };
15932
+ const txConn = state?.sql ?? bunSql;
15933
+ const nested = state?.inTransaction === true;
15934
+ const txMethod = nested && typeof txConn?.savepoint === "function" ? "savepoint" : "begin";
15894
15935
  const runWith = async (attempt2) => {
15895
15936
  opts.logger?.({ type: "start", attempt: attempt2 });
15896
15937
  const start = Date.now();
15897
- return await bunSql.begin(async (tx) => {
15898
- const qb = createQueryBuilder({ sql: tx, meta, schema });
15899
- if (opts?.isolation) {
15938
+ return await txConn[txMethod](async (tx) => {
15939
+ const qb = createQueryBuilder({ sql: tx, meta, schema, inTransaction: true });
15940
+ if (opts?.isolation && !nested) {
15900
15941
  const level = opts.isolation;
15901
15942
  const upper = level === "read committed" ? "READ COMMITTED" : level === "repeatable read" ? "REPEATABLE READ" : "SERIALIZABLE";
15902
15943
  if (config5.dialect === "postgres") {
@@ -15961,7 +16002,8 @@ function createQueryBuilder(state) {
15961
16002
  });
15962
16003
  },
15963
16004
  async beginDistributed(name, fn) {
15964
- const res = await bunSql.beginDistributed(name, async (tx) => {
16005
+ const txConn = state?.sql ?? bunSql;
16006
+ const res = await txConn.beginDistributed(name, async (tx) => {
15965
16007
  const qb = createQueryBuilder({ sql: tx, meta, schema });
15966
16008
  return await fn(qb);
15967
16009
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-query-builder",
3
3
  "type": "module",
4
- "version": "0.1.33",
4
+ "version": "0.1.35",
5
5
  "description": "A simple yet performant query builder for TypeScript. Built with Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",