bun-query-builder 0.2.25 → 0.2.27

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/src/index.js CHANGED
@@ -3048,25 +3048,27 @@ var init_dynamodb = __esm(() => {
3048
3048
 
3049
3049
  // ../../node_modules/bunfig/dist/index.js
3050
3050
  import { existsSync, statSync } from "fs";
3051
+ import { resolve } from "path";
3052
+ import process2 from "process";
3051
3053
  import { existsSync as existsSync13, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readFileSync, writeFileSync as writeFileSync7 } from "fs";
3052
3054
  import { homedir as homedir3 } from "os";
3053
3055
  import { dirname as dirname4, resolve as resolve12 } from "path";
3054
3056
  import process20 from "process";
3055
- import { existsSync as existsSync2, statSync as statSync2 } from "fs";
3057
+ import { existsSync as existsSync3, statSync as statSync2 } from "fs";
3056
3058
  import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync5 } from "fs";
3057
3059
  import { homedir as homedir2 } from "os";
3058
3060
  import { dirname as dirname3, resolve as resolve7 } from "path";
3059
3061
  import process12 from "process";
3060
3062
  import { join as join3, relative as relative2, resolve as resolve4 } from "path";
3061
3063
  import process7 from "process";
3062
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
3064
+ import { existsSync as existsSync32, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
3063
3065
  import { homedir } from "os";
3064
3066
  import { dirname as dirname2, resolve as resolve3 } from "path";
3065
3067
  import process6 from "process";
3066
3068
  import { join, relative, resolve as resolve2 } from "path";
3067
- import process2 from "process";
3069
+ import process22 from "process";
3068
3070
  import { existsSync as existsSync22, mkdirSync, readdirSync, writeFileSync } from "fs";
3069
- import { dirname, resolve } from "path";
3071
+ import { dirname, resolve as resolve5 } from "path";
3070
3072
  import process3 from "process";
3071
3073
  import { Buffer as Buffer2 } from "buffer";
3072
3074
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
@@ -3090,7 +3092,7 @@ import process10 from "process";
3090
3092
  import process9 from "process";
3091
3093
  import process8 from "process";
3092
3094
  import { existsSync as existsSync5 } from "fs";
3093
- import { resolve as resolve5 } from "path";
3095
+ import { resolve as resolve52 } from "path";
3094
3096
  import { existsSync as existsSync7 } from "fs";
3095
3097
  import { existsSync as existsSync9, readdirSync as readdirSync5 } from "fs";
3096
3098
  import { extname, resolve as resolve8 } from "path";
@@ -3350,6 +3352,34 @@ class PerformanceMonitor {
3350
3352
  return this.metrics.filter((m) => m.duration > threshold);
3351
3353
  }
3352
3354
  }
3355
+ function getConfigNamePatterns(options = {}) {
3356
+ const { name = "", alias } = options;
3357
+ const patterns = ["config", ".config"];
3358
+ if (name)
3359
+ patterns.push(name, `.${name}.config`, `${name}.config`, `.${name}`);
3360
+ const aliases = alias === undefined ? [] : Array.isArray(alias) ? alias : [alias];
3361
+ for (const alternative of aliases) {
3362
+ if (!alternative)
3363
+ continue;
3364
+ patterns.push(alternative, `.${alternative}.config`, `${alternative}.config`, `.${alternative}`);
3365
+ if (name)
3366
+ patterns.push(`${name}.${alternative}.config`, `.${name}.${alternative}.config`);
3367
+ }
3368
+ return Array.from(new Set(patterns.filter(Boolean)));
3369
+ }
3370
+ function getConfigPaths(options) {
3371
+ const patterns = getConfigNamePatterns(options);
3372
+ return patterns.flatMap((pattern) => CONFIG_FILE_EXTENSIONS.map((extension) => resolve(options.directory, `${pattern}${extension}`)));
3373
+ }
3374
+ function getLocalConfigDirectories(options = {}) {
3375
+ const cwd = resolve(options.cwd || process2.cwd());
3376
+ return Array.from(new Set([
3377
+ cwd,
3378
+ resolve(cwd, "config"),
3379
+ resolve(cwd, ".config"),
3380
+ options.configDir ? resolve(cwd, options.configDir) : undefined
3381
+ ].filter((directory) => Boolean(directory))));
3382
+ }
3353
3383
  function __exportSetter2(name, newValue) {
3354
3384
  this[name] = __returnValue2.bind(null, newValue);
3355
3385
  }
@@ -3433,7 +3463,7 @@ class ConfigCache2 {
3433
3463
  }
3434
3464
  isFileModified(configPath, cachedTimestamp) {
3435
3465
  try {
3436
- if (!existsSync2(configPath)) {
3466
+ if (!existsSync3(configPath)) {
3437
3467
  return true;
3438
3468
  }
3439
3469
  const stats = statSync2(configPath);
@@ -3455,7 +3485,7 @@ class ConfigCache2 {
3455
3485
  }
3456
3486
  setWithFileCheck(configName, value, configPath, customTtl) {
3457
3487
  try {
3458
- const stats = existsSync2(configPath) ? statSync2(configPath) : null;
3488
+ const stats = existsSync3(configPath) ? statSync2(configPath) : null;
3459
3489
  const fileTimestamp = stats ? stats.mtime : new Date;
3460
3490
  this.set(configName, { value, fileTimestamp }, configPath, customTtl);
3461
3491
  } catch {
@@ -3765,7 +3795,7 @@ async function loadConfig({
3765
3795
  ];
3766
3796
  for (const configPath of configPaths) {
3767
3797
  for (const ext of extensions) {
3768
- const fullPath = resolve(baseDir, `${configPath}${ext}`);
3798
+ const fullPath = resolve5(baseDir, `${configPath}${ext}`);
3769
3799
  const config2 = await tryLoadConfig(fullPath, defaultConfig);
3770
3800
  if (config2 !== null) {
3771
3801
  return config2;
@@ -3773,7 +3803,7 @@ async function loadConfig({
3773
3803
  }
3774
3804
  }
3775
3805
  try {
3776
- const pkgPath = resolve(baseDir, "package.json");
3806
+ const pkgPath = resolve5(baseDir, "package.json");
3777
3807
  if (existsSync22(pkgPath)) {
3778
3808
  const pkg = await import(pkgPath);
3779
3809
  const pkgConfig = pkg[name];
@@ -3787,12 +3817,12 @@ async function loadConfig({
3787
3817
  return defaultConfig;
3788
3818
  }
3789
3819
  function getProjectRoot(filePath, options = {}) {
3790
- let path = process2.cwd();
3820
+ let path = process22.cwd();
3791
3821
  while (path.includes("storage"))
3792
3822
  path = resolve2(path, "..");
3793
3823
  const finalPath = resolve2(path, filePath || "");
3794
3824
  if (options?.relative)
3795
- return relative(process2.cwd(), finalPath);
3825
+ return relative(process22.cwd(), finalPath);
3796
3826
  return finalPath;
3797
3827
  }
3798
3828
  async function loadConfig2() {
@@ -3800,7 +3830,7 @@ async function loadConfig2() {
3800
3830
  const loadedConfig = await loadConfig({
3801
3831
  name: "clarity",
3802
3832
  defaultConfig,
3803
- cwd: process2.cwd(),
3833
+ cwd: process22.cwd(),
3804
3834
  endpoint: "",
3805
3835
  headers: {}
3806
3836
  });
@@ -5142,7 +5172,7 @@ function isObject2(item) {
5142
5172
  return Boolean(item && typeof item === "object" && !Array.isArray(item));
5143
5173
  }
5144
5174
  async function tryLoadConfig2(configPath, defaultConfig2, arrayStrategy = "replace") {
5145
- if (!existsSync3(configPath))
5175
+ if (!existsSync32(configPath))
5146
5176
  return null;
5147
5177
  try {
5148
5178
  const importedConfig = await import(configPath);
@@ -5313,7 +5343,7 @@ async function loadConfig3({
5313
5343
  }
5314
5344
  try {
5315
5345
  const pkgPath = resolve3(baseDir, "package.json");
5316
- if (existsSync3(pkgPath)) {
5346
+ if (existsSync32(pkgPath)) {
5317
5347
  const pkg = await import(pkgPath);
5318
5348
  let pkgConfig = pkg[name];
5319
5349
  if (!pkgConfig && alias) {
@@ -5604,7 +5634,7 @@ class Logger2 {
5604
5634
  const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
5605
5635
  console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
5606
5636
  const delay = backoffDelay * 2 ** retries;
5607
- await new Promise((resolve52) => setTimeout(resolve52, delay));
5637
+ await new Promise((resolve522) => setTimeout(resolve522, delay));
5608
5638
  retries++;
5609
5639
  continue;
5610
5640
  }
@@ -5632,7 +5662,7 @@ class Logger2 {
5632
5662
  }
5633
5663
  retries++;
5634
5664
  const delay = backoffDelay * 2 ** (retries - 1);
5635
- await new Promise((resolve52) => setTimeout(resolve52, delay));
5665
+ await new Promise((resolve522) => setTimeout(resolve522, delay));
5636
5666
  }
5637
5667
  }
5638
5668
  })();
@@ -5762,11 +5792,11 @@ class Logger2 {
5762
5792
  };
5763
5793
  }
5764
5794
  async compressData(data) {
5765
- return new Promise((resolve52, reject) => {
5795
+ return new Promise((resolve522, reject) => {
5766
5796
  const gzip = createGzip2();
5767
5797
  const chunks = [];
5768
5798
  gzip.on("data", (chunk2) => chunks.push(chunk2));
5769
- gzip.on("end", () => resolve52(Buffer22.from(Buffer22.concat(chunks))));
5799
+ gzip.on("end", () => resolve522(Buffer22.from(Buffer22.concat(chunks))));
5770
5800
  gzip.on("error", reject);
5771
5801
  gzip.write(data);
5772
5802
  gzip.end();
@@ -6455,7 +6485,7 @@ class Logger2 {
6455
6485
  if (isBrowserProcess2()) {
6456
6486
  return Promise.resolve(true);
6457
6487
  }
6458
- return new Promise((resolve52) => {
6488
+ return new Promise((resolve522) => {
6459
6489
  console.error(`${styles2.cyan("?")} ${message} (y/n) `);
6460
6490
  const onData = (data) => {
6461
6491
  const input = data.toString().trim().toLowerCase();
@@ -6467,7 +6497,7 @@ class Logger2 {
6467
6497
  } catch {}
6468
6498
  process11.stdin.pause();
6469
6499
  console.error("");
6470
- resolve52(input === "y" || input === "yes");
6500
+ resolve522(input === "y" || input === "yes");
6471
6501
  };
6472
6502
  try {
6473
6503
  if (typeof process11.stdin.setRawMode === "function") {
@@ -6633,7 +6663,7 @@ async function withErrorRecovery(fn, options = {}) {
6633
6663
  break;
6634
6664
  }
6635
6665
  if (retryDelay > 0) {
6636
- await new Promise((resolve52) => setTimeout(resolve52, retryDelay));
6666
+ await new Promise((resolve522) => setTimeout(resolve522, retryDelay));
6637
6667
  }
6638
6668
  }
6639
6669
  }
@@ -7161,7 +7191,7 @@ class ConfigFileLoader {
7161
7191
  const paths = [];
7162
7192
  for (const pattern of patterns) {
7163
7193
  for (const ext of this.extensions) {
7164
- paths.push(resolve5(directory, `${pattern}${ext}`));
7194
+ paths.push(resolve52(directory, `${pattern}${ext}`));
7165
7195
  }
7166
7196
  }
7167
7197
  return paths;
@@ -7198,7 +7228,7 @@ class ConfigFileLoader {
7198
7228
  const patterns = this.generateNamePatterns(configName || "", alias);
7199
7229
  for (const pattern of patterns) {
7200
7230
  for (const ext of this.extensions) {
7201
- const filePath = resolve5(directory, `${pattern}${ext}`);
7231
+ const filePath = resolve52(directory, `${pattern}${ext}`);
7202
7232
  if (await this.checkFileAccess(filePath)) {
7203
7233
  discoveredFiles.push(filePath);
7204
7234
  }
@@ -7210,7 +7240,7 @@ class ConfigFileLoader {
7210
7240
  const files = readdirSync32(directory);
7211
7241
  for (const file of files) {
7212
7242
  if (this.looksLikeConfigFile(file)) {
7213
- const filePath = resolve5(directory, file);
7243
+ const filePath = resolve52(directory, file);
7214
7244
  if (await this.checkFileAccess(filePath)) {
7215
7245
  discoveredFiles.push(filePath);
7216
7246
  }
@@ -9935,7 +9965,7 @@ function isObject4(item) {
9935
9965
  }
9936
9966
 
9937
9967
  class ConfigFileLoader2 {
9938
- extensions = [".ts", ".js", ".mjs", ".cjs", ".json", ".mts", ".cts"];
9968
+ extensions = CONFIG_FILE_EXTENSIONS;
9939
9969
  async loadFromPath(configPath, defaultConfig4, options = {}) {
9940
9970
  const {
9941
9971
  arrayStrategy = "replace",
@@ -10010,37 +10040,10 @@ class ConfigFileLoader2 {
10010
10040
  return null;
10011
10041
  }
10012
10042
  generateConfigPaths(configName, directory, alias) {
10013
- const patterns = this.generateNamePatterns(configName, alias);
10014
- const paths = [];
10015
- for (const pattern of patterns) {
10016
- for (const ext of this.extensions) {
10017
- paths.push(resolve10(directory, `${pattern}${ext}`));
10018
- }
10019
- }
10020
- return paths;
10043
+ return getConfigPaths({ name: configName, directory, alias });
10021
10044
  }
10022
10045
  generateNamePatterns(configName, alias) {
10023
- const patterns = [];
10024
- patterns.push("config", ".config");
10025
- if (configName) {
10026
- patterns.push(configName, `.${configName}.config`, `${configName}.config`, `.${configName}`);
10027
- }
10028
- const aliases = alias === undefined ? [] : Array.isArray(alias) ? alias : [alias];
10029
- for (const a of aliases) {
10030
- if (!a)
10031
- continue;
10032
- patterns.push(a, `.${a}.config`, `${a}.config`, `.${a}`);
10033
- if (configName) {
10034
- patterns.push(`${configName}.${a}.config`, `.${configName}.${a}.config`);
10035
- }
10036
- }
10037
- const seen = new Set;
10038
- return patterns.filter((p) => {
10039
- if (!p || seen.has(p))
10040
- return false;
10041
- seen.add(p);
10042
- return true;
10043
- });
10046
+ return getConfigNamePatterns({ name: configName, alias });
10044
10047
  }
10045
10048
  checkFileAccess(filePath) {
10046
10049
  return withErrorRecovery2(async () => {
@@ -10551,6 +10554,8 @@ class ConfigLoader2 {
10551
10554
  try {
10552
10555
  result = await this.loadConfigurationStrategies(baseOptions, true, cache);
10553
10556
  } catch (error) {
10557
+ if (baseOptions.configFile)
10558
+ throw error;
10554
10559
  const isStrictMode = baseOptions.__strictErrorHandling;
10555
10560
  if (error instanceof Error && error.name === "ConfigNotFoundError") {
10556
10561
  if (isStrictMode) {
@@ -10625,6 +10630,7 @@ class ConfigLoader2 {
10625
10630
  const {
10626
10631
  name = "",
10627
10632
  alias,
10633
+ configFile,
10628
10634
  cwd,
10629
10635
  configDir,
10630
10636
  defaultConfig: defaultConfig4,
@@ -10634,6 +10640,17 @@ class ConfigLoader2 {
10634
10640
  } = options;
10635
10641
  const baseDir = cwd || process20.cwd();
10636
10642
  const searchPaths = [];
10643
+ if (configFile) {
10644
+ const explicitPath = resolve12(baseDir, configFile);
10645
+ searchPaths.push(explicitPath);
10646
+ const envDefaults = checkEnv ? applyEnvVarsToConfig3(name, defaultConfig4, verbose) : defaultConfig4;
10647
+ const explicitResult = await this.fileLoader.tryLoadFromPaths([explicitPath], envDefaults, { arrayStrategy, verbose, cacheTtl: cacheOptions?.ttl, useCache: !cacheOptions?.ttl || cacheOptions.ttl > 100 });
10648
+ if (!explicitResult)
10649
+ throw ErrorFactory2.configNotFound(name || configFile, searchPaths, alias);
10650
+ if (verbose)
10651
+ log3.success(`Configuration loaded from explicit path: ${explicitPath}`);
10652
+ return this.finalizeResult(explicitResult, searchPaths, checkEnv, name, verbose);
10653
+ }
10637
10654
  const localResult = await this.loadLocalConfiguration(name, alias, baseDir, configDir, defaultConfig4, arrayStrategy, verbose, checkEnv, cacheOptions);
10638
10655
  if (localResult) {
10639
10656
  searchPaths.push(...this.getLocalSearchPaths(name, alias, baseDir, configDir));
@@ -10821,6 +10838,8 @@ class ConfigLoader2 {
10821
10838
  }
10822
10839
  if (options.cwd)
10823
10840
  keyParts.push(`cwd:${options.cwd}`);
10841
+ if (options.configFile)
10842
+ keyParts.push(`configFile:${options.configFile}`);
10824
10843
  if (options.configDir)
10825
10844
  keyParts.push(`configDir:${options.configDir}`);
10826
10845
  if ("checkEnv" in options)
@@ -10828,12 +10847,7 @@ class ConfigLoader2 {
10828
10847
  return keyParts.join("|");
10829
10848
  }
10830
10849
  getLocalDirectories(baseDir, configDir) {
10831
- return Array.from(new Set([
10832
- baseDir,
10833
- resolve12(baseDir, "config"),
10834
- resolve12(baseDir, ".config"),
10835
- configDir ? resolve12(baseDir, configDir) : undefined
10836
- ].filter(Boolean)));
10850
+ return getLocalConfigDirectories({ cwd: baseDir, configDir });
10837
10851
  }
10838
10852
  getAllSearchPaths(name, alias, baseDir, configDir) {
10839
10853
  const paths = [];
@@ -10885,6 +10899,8 @@ async function loadConfig6(options) {
10885
10899
  }
10886
10900
  return result?.config ?? defaultConfig4;
10887
10901
  } catch (error) {
10902
+ if (options.configFile)
10903
+ throw error;
10888
10904
  const errorName = error instanceof Error ? error.name : "UnknownError";
10889
10905
  const errorMessage = error instanceof Error ? error.message : String(error);
10890
10906
  const isConfigError = errorName === "ConfigNotFoundError" || errorName === "ConfigLoadError" || errorName === "ConfigValidationError" || errorMessage.includes("config");
@@ -10952,7 +10968,7 @@ function applyEnvVarsToConfig3(name, config6, verbose = false) {
10952
10968
  }
10953
10969
  return processConfigLevel(config6);
10954
10970
  }
10955
- var globalCache, globalPerformanceMonitor, __defProp2, __returnValue2 = (v) => v, __export2 = (target, all) => {
10971
+ var globalCache, globalPerformanceMonitor, CONFIG_FILE_EXTENSIONS, __defProp2, __returnValue2 = (v) => v, __export2 = (target, all) => {
10956
10972
  for (var name in all)
10957
10973
  __defProp2(target, name, {
10958
10974
  get: all[name],
@@ -10964,6 +10980,15 @@ var globalCache, globalPerformanceMonitor, __defProp2, __returnValue2 = (v) => v
10964
10980
  var init_dist = __esm(() => {
10965
10981
  globalCache = new ConfigCache;
10966
10982
  globalPerformanceMonitor = new PerformanceMonitor;
10983
+ CONFIG_FILE_EXTENSIONS = [
10984
+ ".ts",
10985
+ ".js",
10986
+ ".mjs",
10987
+ ".cjs",
10988
+ ".json",
10989
+ ".mts",
10990
+ ".cts"
10991
+ ];
10967
10992
  __defProp2 = Object.defineProperty;
10968
10993
  exports_dist = {};
10969
10994
  __export2(exports_dist, {
@@ -11016,9 +11041,9 @@ var init_dist = __esm(() => {
11016
11041
  isEquivalent: isEquivalent2,
11017
11042
  estimateMemoryUsage: estimateMemoryUsage2
11018
11043
  };
11019
- defaultConfigDir = resolve(process3.cwd(), "config");
11020
- defaultGeneratedDir = resolve(process3.cwd(), "src/generated");
11021
- defaultLogDirectory = process2.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
11044
+ defaultConfigDir = resolve5(process3.cwd(), "config");
11045
+ defaultGeneratedDir = resolve5(process3.cwd(), "src/generated");
11046
+ defaultLogDirectory = process22.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
11022
11047
  defaultConfig = {
11023
11048
  level: "info",
11024
11049
  defaultName: "clarity",
@@ -11635,8 +11660,8 @@ var init_dist = __esm(() => {
11635
11660
  showTags: true
11636
11661
  });
11637
11662
  globalConfigLoader2 = new ConfigLoader2;
11638
- defaultConfigDir4 = resolve12(process20.cwd(), "config");
11639
- defaultGeneratedDir4 = resolve12(process20.cwd(), "src/generated");
11663
+ defaultConfigDir4 = /* @__PURE__ */ resolve12(process20.cwd(), "config");
11664
+ defaultGeneratedDir4 = /* @__PURE__ */ resolve12(process20.cwd(), "src/generated");
11640
11665
  });
11641
11666
 
11642
11667
  // src/config.ts
@@ -11644,6 +11669,29 @@ import process19 from "process";
11644
11669
  function isMysqlLike(dialect = config5.dialect) {
11645
11670
  return dialect === "mysql" || dialect === "singlestore" || dialect === "vitess";
11646
11671
  }
11672
+ function isPlainObject(value) {
11673
+ if (value === null || typeof value !== "object" || Array.isArray(value))
11674
+ return false;
11675
+ const proto = Object.getPrototypeOf(value);
11676
+ return proto === Object.prototype || proto === null;
11677
+ }
11678
+ function mergeObject(target, source, seen = new Set) {
11679
+ const out = { ...target };
11680
+ seen.add(source);
11681
+ for (const key of Object.keys(source)) {
11682
+ if (FORBIDDEN_MERGE_KEYS.has(key))
11683
+ continue;
11684
+ const next = source[key];
11685
+ if (isPlainObject(next) && !seen.has(next)) {
11686
+ const prev = out[key];
11687
+ out[key] = mergeObject(isPlainObject(prev) ? prev : {}, next, seen);
11688
+ } else {
11689
+ out[key] = next;
11690
+ }
11691
+ }
11692
+ seen.delete(source);
11693
+ return out;
11694
+ }
11647
11695
  function resolveDialect(explicit) {
11648
11696
  if (explicit)
11649
11697
  return explicit;
@@ -11687,21 +11735,12 @@ async function getConfig() {
11687
11735
  return config5;
11688
11736
  }
11689
11737
  function applyConfig(userConfig) {
11690
- Object.assign(config5, userConfig);
11691
- if (userConfig.database) {
11692
- config5.database = { ...config5.database, ...userConfig.database };
11693
- }
11694
- if (userConfig.timestamps) {
11695
- config5.timestamps = { ...config5.timestamps, ...userConfig.timestamps };
11696
- }
11697
- if (userConfig.pagination) {
11698
- config5.pagination = { ...config5.pagination, ...userConfig.pagination };
11699
- }
11700
- if (userConfig.softDeletes) {
11701
- config5.softDeletes = { ...config5.softDeletes, ...userConfig.softDeletes };
11702
- }
11703
- if (userConfig.vitess) {
11704
- config5.vitess = { ...config5.vitess, ...userConfig.vitess };
11738
+ const merged = mergeObject(config5, userConfig);
11739
+ const target = config5;
11740
+ for (const key of Object.keys(merged)) {
11741
+ if (FORBIDDEN_MERGE_KEYS.has(key))
11742
+ continue;
11743
+ target[key] = merged[key];
11705
11744
  }
11706
11745
  }
11707
11746
  function setConfig(userConfig) {
@@ -11709,7 +11748,7 @@ function setConfig(userConfig) {
11709
11748
  const key = `${_lastConfiguredDialect}->${userConfig.dialect}`;
11710
11749
  if (!_warnedDialectConflicts.has(key)) {
11711
11750
  _warnedDialectConflicts.add(key);
11712
- console.warn(`[query-builder] setConfig({ dialect: '${userConfig.dialect}' }) overrides a previous ` + `setConfig({ dialect: '${_lastConfiguredDialect}' }). ` + `Config is process-wide; in-flight queries from the previous configuration may break. ` + `Run conflicting connections in separate processes \u2014 see stacksjs/stacks#1862 #18.`);
11751
+ console.warn(`[query-builder] Configuring dialect '${userConfig.dialect}' overrides the previously ` + `configured dialect '${_lastConfiguredDialect}'. ` + `Config is process-wide (setConfig, db.configure and query-builder.config.ts all write it); ` + `in-flight queries from the previous configuration may break. ` + `Run conflicting connections in separate processes \u2014 see stacksjs/stacks#1862 #18.`);
11713
11752
  }
11714
11753
  }
11715
11754
  if (userConfig.dialect)
@@ -11718,7 +11757,10 @@ function setConfig(userConfig) {
11718
11757
  configState.explicit.add(key);
11719
11758
  applyConfig(userConfig);
11720
11759
  }
11721
- var defaultConfig4, CONFIG_SINGLETON_KEY, config5, CONFIG_STATE_KEY, configState, _lastConfiguredDialect = null, _warnedDialectConflicts;
11760
+ function defineConfig(userConfig) {
11761
+ return userConfig;
11762
+ }
11763
+ var defaultConfig4, FORBIDDEN_MERGE_KEYS, CONFIG_SINGLETON_KEY, config5, CONFIG_STATE_KEY, configState, _lastConfiguredDialect = null, _warnedDialectConflicts;
11722
11764
  var init_config = __esm(() => {
11723
11765
  init_dist();
11724
11766
  defaultConfig4 = {
@@ -11783,8 +11825,9 @@ var init_config = __esm(() => {
11783
11825
  defaultFilter: true
11784
11826
  }
11785
11827
  };
11828
+ FORBIDDEN_MERGE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
11786
11829
  CONFIG_SINGLETON_KEY = Symbol.for("bun-query-builder.config");
11787
- config5 = globalThis[CONFIG_SINGLETON_KEY] ??= { ...defaultConfig4 };
11830
+ config5 = globalThis[CONFIG_SINGLETON_KEY] ??= mergeObject({}, defaultConfig4);
11788
11831
  CONFIG_STATE_KEY = Symbol.for("bun-query-builder.config-state");
11789
11832
  configState = globalThis[CONFIG_STATE_KEY] ??= { explicit: new Set, fileLoaded: false };
11790
11833
  _warnedDialectConflicts = new Set;
@@ -11942,12 +11985,12 @@ function createSQLiteSQL(filename) {
11942
11985
  const params = [];
11943
11986
  for (let i = 0;i < values.length; i++) {
11944
11987
  const value = values[i];
11945
- if (value && typeof value === "object" && (value.__raw || value.raw)) {
11946
- const rawValue = value.__raw ? value.value : typeof value.raw === "string" ? value.raw : value.raw();
11947
- sql += rawValue + (strings[i + 1] || "");
11948
- } else if (value && typeof value === "object" && "sql" in value && "values" in value) {
11988
+ if (value && typeof value === "object" && typeof value.sql === "string" && Array.isArray(value.values)) {
11949
11989
  sql += value.sql + (strings[i + 1] || "");
11950
11990
  params.push(...value.values);
11991
+ } else if (value && typeof value === "object" && (value.__raw || value.raw)) {
11992
+ const rawValue = value.__raw ? value.value : typeof value.raw === "string" ? value.raw : value.raw();
11993
+ sql += rawValue + (strings[i + 1] || "");
11951
11994
  } else if (Array.isArray(value)) {
11952
11995
  const placeholders = value.map(() => "?").join(", ");
11953
11996
  sql += placeholders + (strings[i + 1] || "");
@@ -12582,6 +12625,11 @@ function renderSelectColumn(col) {
12582
12625
  }
12583
12626
  throw new TypeError(`[query-builder] select(): unsupported column ${String(col)} \u2014 pass a column name, a string[], or a SQL fragment (e.g. sql\`count(*) as c\`)`);
12584
12627
  }
12628
+ function renderInPredicate(column, values, negated, placeholders) {
12629
+ if (values.length === 0)
12630
+ return negated ? TRUE_PREDICATE : FALSE_PREDICATE;
12631
+ return `${column} ${negated ? "NOT IN" : "IN"} (${placeholders})`;
12632
+ }
12585
12633
  function validateIdentifier(name, context) {
12586
12634
  if (!SQL_PATTERNS.IDENTIFIER.test(name)) {
12587
12635
  const contextMsg = context ? ` in ${context}` : "";
@@ -12827,6 +12875,20 @@ function createQueryBuilder(state) {
12827
12875
  const _sql = state?.sql ?? getOrCreateBunSql();
12828
12876
  const meta = state?.meta;
12829
12877
  const schema = state?.schema;
12878
+ function advisoryLockKey(key) {
12879
+ if (typeof key === "number")
12880
+ return key;
12881
+ const s = String(key);
12882
+ let hash = 7;
12883
+ for (let i = 0;i < s.length; i++)
12884
+ hash = hash * 31 + s.charCodeAt(i) | 0;
12885
+ return Math.abs(hash);
12886
+ }
12887
+ function activeHooks() {
12888
+ if (!state?.hooks)
12889
+ return config5.hooks;
12890
+ return { ...config5.hooks, ...state.hooks };
12891
+ }
12830
12892
  const dynamicWhereColumnCache = new Map;
12831
12893
  function applyCondition(expr) {
12832
12894
  if (Array.isArray(expr)) {
@@ -12918,7 +12980,7 @@ function createQueryBuilder(state) {
12918
12980
  return;
12919
12981
  }
12920
12982
  function runWithHooks(q, kind, opts) {
12921
- const hooks = config5.hooks;
12983
+ const hooks = activeHooks();
12922
12984
  const slowMs = hooks?.slowQueryThresholdMs;
12923
12985
  const slowEnabled = slowMs != null && slowMs >= 0;
12924
12986
  const hasSlowQuery = Boolean(hooks?.onSlowQuery || slowEnabled);
@@ -14285,8 +14347,12 @@ function createQueryBuilder(state) {
14285
14347
  return this;
14286
14348
  },
14287
14349
  whereAny(cols, op, value) {
14288
- if (cols.length === 0)
14350
+ if (cols.length === 0) {
14351
+ const kw = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14352
+ text += ` ${kw} (${FALSE_PREDICATE})`;
14353
+ built = null;
14289
14354
  return this;
14355
+ }
14290
14356
  const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14291
14357
  const idx = whereParams.length + 1;
14292
14358
  const conds = cols.map((c, i) => `${c} ${op} ${getPlaceholder(idx + i)}`);
@@ -14368,7 +14434,7 @@ function createQueryBuilder(state) {
14368
14434
  const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14369
14435
  if (Array.isArray(values)) {
14370
14436
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14371
- text += ` ${keyword} ${column} IN (${placeholders})`;
14437
+ text += ` ${keyword} ${renderInPredicate(column, values, false, placeholders)}`;
14372
14438
  whereParams.push(...values);
14373
14439
  } else {
14374
14440
  text += ` ${keyword} ${column} IN (${String(values.toSQL())})`;
@@ -14380,7 +14446,7 @@ function createQueryBuilder(state) {
14380
14446
  validateIdentifier(String(column), "orWhereIn(column)");
14381
14447
  if (Array.isArray(values)) {
14382
14448
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14383
- text += ` OR ${column} IN (${placeholders})`;
14449
+ text += ` OR ${renderInPredicate(column, values, false, placeholders)}`;
14384
14450
  whereParams.push(...values);
14385
14451
  } else {
14386
14452
  text += ` OR ${column} IN (${String(values.toSQL())})`;
@@ -14393,7 +14459,7 @@ function createQueryBuilder(state) {
14393
14459
  const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14394
14460
  if (Array.isArray(values)) {
14395
14461
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14396
- text += ` ${keyword} ${column} NOT IN (${placeholders})`;
14462
+ text += ` ${keyword} ${renderInPredicate(column, values, true, placeholders)}`;
14397
14463
  whereParams.push(...values);
14398
14464
  } else {
14399
14465
  text += ` ${keyword} ${column} NOT IN (${String(values.toSQL())})`;
@@ -14405,7 +14471,7 @@ function createQueryBuilder(state) {
14405
14471
  validateIdentifier(String(column), "orWhereNotIn(column)");
14406
14472
  if (Array.isArray(values)) {
14407
14473
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14408
- text += ` OR ${column} NOT IN (${placeholders})`;
14474
+ text += ` OR ${renderInPredicate(column, values, true, placeholders)}`;
14409
14475
  whereParams.push(...values);
14410
14476
  } else {
14411
14477
  text += ` OR ${column} NOT IN (${String(values.toSQL())})`;
@@ -15000,7 +15066,7 @@ function createQueryBuilder(state) {
15000
15066
  return text;
15001
15067
  },
15002
15068
  async get() {
15003
- const hooks = config5.hooks;
15069
+ const hooks = activeHooks();
15004
15070
  const hasQueryHooks = hooks && (hooks.onQueryStart || hooks.onQueryEnd || hooks.onQueryError || hooks.startSpan || hasSlowQueryHook(hooks));
15005
15071
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !hasQueryHooks) {
15006
15072
  const prepareFn = _sql._prepareStatement;
@@ -15053,7 +15119,7 @@ function createQueryBuilder(state) {
15053
15119
  return result;
15054
15120
  },
15055
15121
  async first() {
15056
- const fHooks = config5.hooks;
15122
+ const fHooks = activeHooks();
15057
15123
  const fHasQueryHooks = fHooks && (fHooks.onQueryStart || fHooks.onQueryEnd || fHooks.onQueryError || fHooks.startSpan || hasSlowQueryHook(fHooks));
15058
15124
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !fHasQueryHooks) {
15059
15125
  const prepareFn = _sql._prepareStatement;
@@ -15135,7 +15201,7 @@ function createQueryBuilder(state) {
15135
15201
  } else {
15136
15202
  countText = `SELECT COUNT(*) as c FROM ${table}`;
15137
15203
  }
15138
- const cHooks = config5.hooks;
15204
+ const cHooks = activeHooks();
15139
15205
  const cHasHooks = cHooks && (cHooks.onQueryStart || cHooks.onQueryEnd || cHooks.onQueryError || cHooks.startSpan || hasSlowQueryHook(cHooks));
15140
15206
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !cHasHooks) {
15141
15207
  const prepareFn = _sql._prepareStatement;
@@ -15153,7 +15219,7 @@ function createQueryBuilder(state) {
15153
15219
  async avg(column) {
15154
15220
  const fromIdx = text.indexOf(" FROM ");
15155
15221
  const avgText = fromIdx !== -1 ? `SELECT AVG(${column}) as a${text.substring(fromIdx)}` : `SELECT AVG(${column}) as a FROM ${table}`;
15156
- const aHooks = config5.hooks;
15222
+ const aHooks = activeHooks();
15157
15223
  const aHasHooks = aHooks && (aHooks.onQueryStart || aHooks.onQueryEnd || aHooks.onQueryError || aHooks.startSpan || hasSlowQueryHook(aHooks));
15158
15224
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !aHasHooks) {
15159
15225
  const prepareFn = _sql._prepareStatement;
@@ -15290,7 +15356,7 @@ function createQueryBuilder(state) {
15290
15356
  }
15291
15357
  return {
15292
15358
  configure(opts) {
15293
- Object.assign(config5, opts);
15359
+ setConfig(opts);
15294
15360
  return this;
15295
15361
  },
15296
15362
  id(name) {
@@ -15667,7 +15733,7 @@ function createQueryBuilder(state) {
15667
15733
  return makeExecutableQuery(built, sqlText);
15668
15734
  },
15669
15735
  execute() {
15670
- const hooks = config5.hooks;
15736
+ const hooks = activeHooks();
15671
15737
  const hasHooks = hooks && (hooks.onQueryStart || hooks.onQueryEnd || hooks.onQueryError || hooks.startSpan || hooks.beforeCreate || hooks.afterCreate || hasSlowQueryHook(hooks));
15672
15738
  if (!hasHooks) {
15673
15739
  const prepareFn = _sql._prepareStatement;
@@ -16021,13 +16087,13 @@ function createQueryBuilder(state) {
16021
16087
  },
16022
16088
  async execute() {
16023
16089
  try {
16024
- await config5.hooks?.beforeDelete?.({ table: String(table), where: whereCondition });
16090
+ await activeHooks()?.beforeDelete?.({ table: String(table), where: whereCondition });
16025
16091
  } catch (err) {
16026
16092
  throw err;
16027
16093
  }
16028
16094
  const result = mutationCount(await runWithHooks(ensureDelBuilt(), "delete"));
16029
16095
  try {
16030
- await config5.hooks?.afterDelete?.({ table: String(table), where: whereCondition, result });
16096
+ await activeHooks()?.afterDelete?.({ table: String(table), where: whereCondition, result });
16031
16097
  } catch {}
16032
16098
  return result;
16033
16099
  },
@@ -16091,18 +16157,14 @@ function createQueryBuilder(state) {
16091
16157
  },
16092
16158
  async advisoryLock(key) {
16093
16159
  if (config5.dialect === "postgres") {
16094
- const s = String(key);
16095
- let hash = 7;
16096
- for (let i = 0;i < s.length; i++)
16097
- hash = hash * 31 + s.charCodeAt(i) | 0;
16098
- const k = typeof key === "number" ? key : Math.abs(hash);
16099
- const q = bunSql`SELECT pg_advisory_lock(${k})`;
16160
+ const k = advisoryLockKey(key);
16161
+ const q = _sql`SELECT pg_advisory_lock(${k})`;
16100
16162
  await runWithHooks(q, "raw");
16101
16163
  return;
16102
16164
  }
16103
16165
  if (isMysqlLike(config5.dialect)) {
16104
16166
  const lockName = `bqb:${String(key)}`;
16105
- const q = bunSql`SELECT GET_LOCK(${lockName}, -1) AS ok`;
16167
+ const q = _sql`SELECT GET_LOCK(${lockName}, -1) AS ok`;
16106
16168
  await runWithHooks(q, "raw");
16107
16169
  return;
16108
16170
  }
@@ -16110,18 +16172,29 @@ function createQueryBuilder(state) {
16110
16172
  },
16111
16173
  async tryAdvisoryLock(key) {
16112
16174
  if (config5.dialect === "postgres") {
16113
- const s = String(key);
16114
- let hash = 7;
16115
- for (let i = 0;i < s.length; i++)
16116
- hash = hash * 31 + s.charCodeAt(i) | 0;
16117
- const k = typeof key === "number" ? key : Math.abs(hash);
16118
- const q = bunSql`SELECT pg_try_advisory_lock(${k}) as ok`;
16175
+ const k = advisoryLockKey(key);
16176
+ const q = _sql`SELECT pg_try_advisory_lock(${k}) as ok`;
16119
16177
  const rows = await runWithHooks(q, "raw");
16120
16178
  return Boolean(rows?.[0]?.ok);
16121
16179
  }
16122
16180
  if (isMysqlLike(config5.dialect)) {
16123
16181
  const lockName = `bqb:${String(key)}`;
16124
- const q = bunSql`SELECT GET_LOCK(${lockName}, 0) AS ok`;
16182
+ const q = _sql`SELECT GET_LOCK(${lockName}, 0) AS ok`;
16183
+ const rows = await runWithHooks(q, "raw");
16184
+ return Number(rows?.[0]?.ok) === 1;
16185
+ }
16186
+ return false;
16187
+ },
16188
+ async advisoryUnlock(key) {
16189
+ if (config5.dialect === "postgres") {
16190
+ const k = advisoryLockKey(key);
16191
+ const q = _sql`SELECT pg_advisory_unlock(${k}) as ok`;
16192
+ const rows = await runWithHooks(q, "raw");
16193
+ return Boolean(rows?.[0]?.ok);
16194
+ }
16195
+ if (isMysqlLike(config5.dialect)) {
16196
+ const lockName = `bqb:${String(key)}`;
16197
+ const q = _sql`SELECT RELEASE_LOCK(${lockName}) AS ok`;
16125
16198
  const rows = await runWithHooks(q, "raw");
16126
16199
  return Number(rows?.[0]?.ok) === 1;
16127
16200
  }
@@ -16131,11 +16204,11 @@ function createQueryBuilder(state) {
16131
16204
  return _sql.unsafe(query, params);
16132
16205
  },
16133
16206
  file(path, params) {
16134
- return bunSql.file(path, params);
16207
+ return _sql.file(path, params);
16135
16208
  },
16136
16209
  async reserve() {
16137
16210
  const reserved = await bunSql.reserve();
16138
- const qb = createQueryBuilder({ sql: reserved, meta, schema });
16211
+ const qb = createQueryBuilder({ sql: reserved, meta, schema, hooks: state?.hooks });
16139
16212
  qb.release = () => reserved.release();
16140
16213
  return qb;
16141
16214
  },
@@ -16155,7 +16228,7 @@ function createQueryBuilder(state) {
16155
16228
  },
16156
16229
  async ping() {
16157
16230
  try {
16158
- const q = bunSql`SELECT 1`;
16231
+ const q = _sql`SELECT 1`;
16159
16232
  await runWithHooks(q, "select");
16160
16233
  return true;
16161
16234
  } catch {
@@ -16182,7 +16255,7 @@ function createQueryBuilder(state) {
16182
16255
  opts.logger?.({ type: "start", attempt: attempt2 });
16183
16256
  const start = Date.now();
16184
16257
  return await txConn[txMethod](async (tx) => {
16185
- const qb = createQueryBuilder({ sql: tx, meta, schema, inTransaction: true });
16258
+ const qb = createQueryBuilder({ sql: tx, meta, schema, hooks: state?.hooks, inTransaction: true });
16186
16259
  if (opts?.isolation && !nested) {
16187
16260
  const level = opts.isolation;
16188
16261
  const upper = level === "read committed" ? "READ COMMITTED" : level === "repeatable read" ? "REPEATABLE READ" : "SERIALIZABLE";
@@ -16245,14 +16318,14 @@ function createQueryBuilder(state) {
16245
16318
  if (!s || typeof s.savepoint !== "function")
16246
16319
  throw new Error("savepoint() is not supported by the active connection");
16247
16320
  return await s.savepoint(async (sp) => {
16248
- const qb = createQueryBuilder({ sql: sp, meta, schema, inTransaction: true });
16321
+ const qb = createQueryBuilder({ sql: sp, meta, schema, hooks: state?.hooks, inTransaction: true });
16249
16322
  return await fn(qb);
16250
16323
  });
16251
16324
  },
16252
16325
  async beginDistributed(name, fn) {
16253
16326
  const txConn = state?.sql ?? bunSql;
16254
16327
  const res = await txConn.beginDistributed(name, async (tx) => {
16255
- const qb = createQueryBuilder({ sql: tx, meta, schema });
16328
+ const qb = createQueryBuilder({ sql: tx, meta, schema, hooks: state?.hooks });
16256
16329
  return await fn(qb);
16257
16330
  });
16258
16331
  return res;
@@ -16278,24 +16351,24 @@ function createQueryBuilder(state) {
16278
16351
  const { colsSql, valuesSql, params } = buildInsertClause(rows);
16279
16352
  const tbl = quoteInsertIdent(String(table));
16280
16353
  const sqlText = isMysqlLike(config5.dialect) ? `INSERT IGNORE INTO ${tbl} (${colsSql}) VALUES ${valuesSql}` : `INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql} ON CONFLICT DO NOTHING`;
16281
- return bunSql.unsafe(sqlText, params).execute();
16354
+ return _sql.unsafe(sqlText, params).execute();
16282
16355
  },
16283
16356
  async insertGetId(table, values, idColumn = "id") {
16284
16357
  const { colsSql, valuesSql, params } = buildInsertClause([values]);
16285
16358
  const tbl = quoteInsertIdent(String(table));
16286
16359
  if (isMysqlLike(config5.dialect)) {
16287
- await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16288
- const [row2] = await bunSql.unsafe(`SELECT LAST_INSERT_ID() as id`).execute();
16360
+ await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16361
+ const [row2] = await _sql.unsafe(`SELECT LAST_INSERT_ID() as id`).execute();
16289
16362
  return row2?.id;
16290
16363
  }
16291
16364
  if (config5.dialect === "sqlite") {
16292
- const res = await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16365
+ const res = await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16293
16366
  if (res?.lastInsertRowid != null)
16294
16367
  return res.lastInsertRowid;
16295
- const [row2] = await bunSql.unsafe(`SELECT last_insert_rowid() as id`).execute();
16368
+ const [row2] = await _sql.unsafe(`SELECT last_insert_rowid() as id`).execute();
16296
16369
  return row2?.id;
16297
16370
  }
16298
- const [row] = await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql} RETURNING ${quoteInsertIdent(String(idColumn))} as id`, params).execute();
16371
+ const [row] = await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql} RETURNING ${quoteInsertIdent(String(idColumn))} as id`, params).execute();
16299
16372
  return row?.id;
16300
16373
  },
16301
16374
  async updateOrInsert(table, match, values) {
@@ -16304,18 +16377,18 @@ function createQueryBuilder(state) {
16304
16377
  let idx = 1;
16305
16378
  const whereSql = matchKeys.map((k) => `${quoteInsertIdent(k)} = ${getPlaceholder(idx++)}`).join(" AND ");
16306
16379
  const whereParams = matchKeys.map((k) => match[k]);
16307
- const existsRows = await bunSql.unsafe(`SELECT 1 FROM ${tbl} WHERE ${whereSql} LIMIT 1`, whereParams).execute();
16380
+ const existsRows = await _sql.unsafe(`SELECT 1 FROM ${tbl} WHERE ${whereSql} LIMIT 1`, whereParams).execute();
16308
16381
  if (existsRows.length) {
16309
16382
  const setKeys = Object.keys(values);
16310
16383
  let i = 1;
16311
16384
  const setSql = setKeys.map((k) => `${quoteInsertIdent(k)} = ${getPlaceholder(i++)}`).join(", ");
16312
16385
  const whereSql2 = matchKeys.map((k) => `${quoteInsertIdent(k)} = ${getPlaceholder(i++)}`).join(" AND ");
16313
16386
  const params2 = [...setKeys.map((k) => values[k]), ...matchKeys.map((k) => match[k])];
16314
- await bunSql.unsafe(`UPDATE ${tbl} SET ${setSql} WHERE ${whereSql2}`, params2).execute();
16387
+ await _sql.unsafe(`UPDATE ${tbl} SET ${setSql} WHERE ${whereSql2}`, params2).execute();
16315
16388
  return true;
16316
16389
  }
16317
16390
  const { colsSql, valuesSql, params } = buildInsertClause([{ ...match, ...values }]);
16318
- await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16391
+ await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16319
16392
  return true;
16320
16393
  },
16321
16394
  async upsert(table, rows, conflictColumns, mergeColumns) {
@@ -16329,15 +16402,15 @@ function createQueryBuilder(state) {
16329
16402
  const insert = `INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`;
16330
16403
  if (isMysqlLike(config5.dialect)) {
16331
16404
  if (setCols.length === 0)
16332
- return bunSql.unsafe(`INSERT IGNORE INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16405
+ return _sql.unsafe(`INSERT IGNORE INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16333
16406
  const updateList2 = setCols.map((c) => `${quoteInsertIdent(c)} = VALUES(${quoteInsertIdent(c)})`).join(", ");
16334
- return bunSql.unsafe(`${insert} ON DUPLICATE KEY UPDATE ${updateList2}`, params).execute();
16407
+ return _sql.unsafe(`${insert} ON DUPLICATE KEY UPDATE ${updateList2}`, params).execute();
16335
16408
  }
16336
16409
  const targets = targetCols.map(quoteInsertIdent).join(", ");
16337
16410
  if (setCols.length === 0)
16338
- return bunSql.unsafe(`${insert} ON CONFLICT (${targets}) DO NOTHING`, params).execute();
16411
+ return _sql.unsafe(`${insert} ON CONFLICT (${targets}) DO NOTHING`, params).execute();
16339
16412
  const updateList = setCols.map((c) => `${quoteInsertIdent(c)} = EXCLUDED.${quoteInsertIdent(c)}`).join(", ");
16340
- return bunSql.unsafe(`${insert} ON CONFLICT (${targets}) DO UPDATE SET ${updateList}`, params).execute();
16413
+ return _sql.unsafe(`${insert} ON CONFLICT (${targets}) DO UPDATE SET ${updateList}`, params).execute();
16341
16414
  },
16342
16415
  async save(table, values) {
16343
16416
  const pk = meta?.primaryKeys[String(table)] ?? "id";
@@ -16380,26 +16453,25 @@ function createQueryBuilder(state) {
16380
16453
  async rawQuery(query) {
16381
16454
  const start = Date.now();
16382
16455
  try {
16383
- config5.hooks?.onQueryStart?.({ sql: query, kind: "raw" });
16384
- const res = await bunSql.unsafe(query);
16385
- config5.hooks?.onQueryEnd?.({ sql: query, durationMs: Date.now() - start, kind: "raw" });
16456
+ activeHooks()?.onQueryStart?.({ sql: query, kind: "raw" });
16457
+ const res = await _sql.unsafe(query);
16458
+ activeHooks()?.onQueryEnd?.({ sql: query, durationMs: Date.now() - start, kind: "raw" });
16386
16459
  return res;
16387
16460
  } catch (err) {
16388
- config5.hooks?.onQueryError?.({ sql: query, error: err, durationMs: Date.now() - start, kind: "raw" });
16461
+ activeHooks()?.onQueryError?.({ sql: query, error: err, durationMs: Date.now() - start, kind: "raw" });
16389
16462
  throw err;
16390
16463
  }
16391
16464
  },
16392
16465
  async create(table, values) {
16393
16466
  const pk = meta?.primaryKeys[String(table)] ?? "id";
16394
16467
  try {
16395
- await config5.hooks?.beforeCreate?.({ table: String(table), data: values });
16468
+ await activeHooks()?.beforeCreate?.({ table: String(table), data: values });
16396
16469
  } catch (err) {
16397
16470
  throw err;
16398
16471
  }
16399
16472
  if (config5.dialect === "postgres") {
16400
- const q = bunSql`INSERT INTO ${bunSql(String(table))} ${bunSql(values)} RETURNING ${bunSql(String(pk))} as id`;
16473
+ const q = _sql`INSERT INTO ${_sql(String(table))} ${_sql(values)} RETURNING ${_sql(String(pk))} as id`;
16401
16474
  const [result] = await q.execute();
16402
- console.log("resultId", result);
16403
16475
  if (!result?.id) {
16404
16476
  console.error(`create() failed to get insert ID for table ${String(table)}`);
16405
16477
  console.error("Inserted values:", values);
@@ -16412,7 +16484,7 @@ function createQueryBuilder(state) {
16412
16484
  throw new Error(`create() failed to retrieve inserted row for table ${String(table)} with id ${result.id}`);
16413
16485
  }
16414
16486
  try {
16415
- await config5.hooks?.afterCreate?.({ table: String(table), data: values, result: row });
16487
+ await activeHooks()?.afterCreate?.({ table: String(table), data: values, result: row });
16416
16488
  } catch {}
16417
16489
  return row;
16418
16490
  } else {
@@ -16427,7 +16499,7 @@ function createQueryBuilder(state) {
16427
16499
  throw new Error(`create() failed to retrieve inserted row for table ${String(table)} with id ${id}`);
16428
16500
  }
16429
16501
  try {
16430
- await config5.hooks?.afterCreate?.({ table: String(table), data: values, result: row });
16502
+ await activeHooks()?.afterCreate?.({ table: String(table), data: values, result: row });
16431
16503
  } catch {}
16432
16504
  return row;
16433
16505
  }
@@ -16567,28 +16639,28 @@ function createQueryBuilder(state) {
16567
16639
  return await this.create(table, { ...match, ...values });
16568
16640
  },
16569
16641
  async count(table, column) {
16570
- const col = column ? bunSql(String(column)) : bunSql`*`;
16571
- const q = bunSql`SELECT COUNT(${col}) as c FROM ${bunSql(String(table))}`;
16642
+ const col = column ? _sql(String(column)) : _sql`*`;
16643
+ const q = _sql`SELECT COUNT(${col}) as c FROM ${_sql(String(table))}`;
16572
16644
  const [row] = await q.execute();
16573
16645
  return Number(row?.c ?? 0);
16574
16646
  },
16575
16647
  async sum(table, column) {
16576
- const q = bunSql`SELECT SUM(${bunSql(String(column))}) as s FROM ${bunSql(String(table))}`;
16648
+ const q = _sql`SELECT SUM(${_sql(String(column))}) as s FROM ${_sql(String(table))}`;
16577
16649
  const [row] = await q.execute();
16578
16650
  return Number(row?.s ?? 0);
16579
16651
  },
16580
16652
  async avg(table, column) {
16581
- const q = bunSql`SELECT AVG(${bunSql(String(column))}) as a FROM ${bunSql(String(table))}`;
16653
+ const q = _sql`SELECT AVG(${_sql(String(column))}) as a FROM ${_sql(String(table))}`;
16582
16654
  const [row] = await q.execute();
16583
16655
  return Number(row?.a ?? 0);
16584
16656
  },
16585
16657
  async min(table, column) {
16586
- const q = bunSql`SELECT MIN(${bunSql(String(column))}) as m FROM ${bunSql(String(table))}`;
16658
+ const q = _sql`SELECT MIN(${_sql(String(column))}) as m FROM ${_sql(String(table))}`;
16587
16659
  const [row] = await q.execute();
16588
16660
  return row?.m;
16589
16661
  },
16590
16662
  async max(table, column) {
16591
- const q = bunSql`SELECT MAX(${bunSql(String(column))}) as m FROM ${bunSql(String(table))}`;
16663
+ const q = _sql`SELECT MAX(${_sql(String(column))}) as m FROM ${_sql(String(table))}`;
16592
16664
  const [row] = await q.execute();
16593
16665
  return row?.m;
16594
16666
  },
@@ -16658,7 +16730,7 @@ function clearQueryCache() {
16658
16730
  function setQueryCacheMaxSize(size) {
16659
16731
  queryCache.setMaxSize(size);
16660
16732
  }
16661
- var SQL_PATTERNS, SAFE_WHERE_OPERATORS, warnedSqlFragmentContexts, queryCache, reorderCache, REORDER_CACHE_MAX = 500;
16733
+ var FALSE_PREDICATE = "1 = 0", TRUE_PREDICATE = "1 = 1", SQL_PATTERNS, SAFE_WHERE_OPERATORS, warnedSqlFragmentContexts, queryCache, reorderCache, REORDER_CACHE_MAX = 500;
16662
16734
  var init_client = __esm(() => {
16663
16735
  init_config();
16664
16736
  init_db();
@@ -16751,7 +16823,7 @@ var init_cache = __esm(() => {
16751
16823
  });
16752
16824
 
16753
16825
  // src/actions/console.ts
16754
- import process22 from "process";
16826
+ import process23 from "process";
16755
16827
  import { createInterface } from "readline";
16756
16828
  async function startConsole() {
16757
16829
  console.log("-- Query Builder Interactive Console");
@@ -16760,8 +16832,8 @@ async function startConsole() {
16760
16832
  console.log();
16761
16833
  const qb = createQueryBuilder();
16762
16834
  const rl = createInterface({
16763
- input: process22.stdin,
16764
- output: process22.stdout,
16835
+ input: process23.stdin,
16836
+ output: process23.stdout,
16765
16837
  prompt: "qb> "
16766
16838
  });
16767
16839
  let multilineBuffer = "";
@@ -16812,7 +16884,7 @@ Tips:
16812
16884
  if (cmd === ".exit" || cmd === ".quit") {
16813
16885
  console.log("Goodbye!");
16814
16886
  rl.close();
16815
- process22.exit(0);
16887
+ process23.exit(0);
16816
16888
  } else if (cmd === ".help") {
16817
16889
  console.log(helpText);
16818
16890
  } else if (cmd === ".clear") {
@@ -16883,7 +16955,7 @@ Tips:
16883
16955
  rl.on("close", () => {
16884
16956
  console.log(`
16885
16957
  Goodbye!`);
16886
- process22.exit(0);
16958
+ process23.exit(0);
16887
16959
  });
16888
16960
  rl.prompt();
16889
16961
  }
@@ -16895,7 +16967,7 @@ var init_console = __esm(() => {
16895
16967
  });
16896
16968
 
16897
16969
  // src/actions/data.ts
16898
- import { existsSync as existsSync11, readFileSync as readFileSync2, writeFileSync as writeFileSync8 } from "fs";
16970
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync8 } from "fs";
16899
16971
  async function exportData(tableName, options = {}) {
16900
16972
  const format = options.format || "json";
16901
16973
  const output = options.output || `${tableName}.${format}`;
@@ -16970,7 +17042,7 @@ async function exportData(tableName, options = {}) {
16970
17042
  }
16971
17043
  }
16972
17044
  async function importData(tableName, filePath, options = {}) {
16973
- if (!existsSync11(filePath)) {
17045
+ if (!existsSync2(filePath)) {
16974
17046
  console.error(`-- File not found: ${filePath}`);
16975
17047
  throw new Error(`File not found: ${filePath}`);
16976
17048
  }
@@ -18116,23 +18188,23 @@ var init_introspect_db = __esm(() => {
18116
18188
  });
18117
18189
 
18118
18190
  // src/actions/make-model.ts
18119
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, writeFileSync as writeFileSync10 } from "fs";
18191
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, writeFileSync as writeFileSync10 } from "fs";
18120
18192
  import { dirname as dirname7, join as join7 } from "path";
18121
- import process23 from "process";
18193
+ import process25 from "process";
18122
18194
  function findWorkspaceRoot(startPath) {
18123
18195
  let currentPath = startPath;
18124
18196
  while (currentPath !== dirname7(currentPath)) {
18125
- if (existsSync14(join7(currentPath, "package.json"))) {
18197
+ if (existsSync11(join7(currentPath, "package.json"))) {
18126
18198
  return currentPath;
18127
18199
  }
18128
18200
  currentPath = dirname7(currentPath);
18129
18201
  }
18130
- return process23.cwd();
18202
+ return process25.cwd();
18131
18203
  }
18132
18204
  async function makeModel(name, options = {}) {
18133
- const workspaceRoot = findWorkspaceRoot(process23.cwd());
18205
+ const workspaceRoot = findWorkspaceRoot(process25.cwd());
18134
18206
  const modelsDir = options.dir || join7(workspaceRoot, "app/Models");
18135
- if (!existsSync14(modelsDir)) {
18207
+ if (!existsSync11(modelsDir)) {
18136
18208
  mkdirSync7(modelsDir, { recursive: true });
18137
18209
  console.log(`-- Created models directory: ${modelsDir}`);
18138
18210
  }
@@ -18140,7 +18212,7 @@ async function makeModel(name, options = {}) {
18140
18212
  const tableName = options.table || `${name.toLowerCase()}s`;
18141
18213
  const fileName = `${className}.ts`;
18142
18214
  const filePath = join7(modelsDir, fileName);
18143
- if (existsSync14(filePath)) {
18215
+ if (existsSync11(filePath)) {
18144
18216
  console.error(`-- Model already exists: ${filePath}`);
18145
18217
  throw new Error(`Model already exists: ${filePath}`);
18146
18218
  }
@@ -18900,17 +18972,17 @@ var init_drivers = __esm(() => {
18900
18972
  });
18901
18973
 
18902
18974
  // src/workspace.ts
18903
- import { existsSync as existsSync16 } from "fs";
18975
+ import { existsSync as existsSync14 } from "fs";
18904
18976
  import { dirname as dirname8, isAbsolute as isAbsolute3, join as join9 } from "path";
18905
- import process24 from "process";
18906
- function findWorkspaceRoot2(startPath = process24.cwd()) {
18977
+ import process26 from "process";
18978
+ function findWorkspaceRoot2(startPath = process26.cwd()) {
18907
18979
  let currentPath = startPath;
18908
18980
  while (currentPath !== dirname8(currentPath)) {
18909
- if (existsSync16(join9(currentPath, "package.json")))
18981
+ if (existsSync14(join9(currentPath, "package.json")))
18910
18982
  return currentPath;
18911
18983
  currentPath = dirname8(currentPath);
18912
18984
  }
18913
- return process24.cwd();
18985
+ return process26.cwd();
18914
18986
  }
18915
18987
  function getSqlDirectory(workspaceRoot, migrationDir = "database/migrations") {
18916
18988
  const configured = migrationDir || "database/migrations";
@@ -18929,10 +19001,10 @@ __export(exports_migrate, {
18929
19001
  copyModelsToGenerated: () => copyModelsToGenerated,
18930
19002
  clearGeneratedDirectory: () => clearGeneratedDirectory
18931
19003
  });
18932
- import { existsSync as existsSync17, mkdirSync as mkdirSync8, mkdtempSync, readdirSync as readdirSync6, readFileSync as readFileSync3, rmSync, unlinkSync, writeFileSync as writeFileSync11 } from "fs";
19004
+ import { existsSync as existsSync16, mkdirSync as mkdirSync8, mkdtempSync, readdirSync as readdirSync6, readFileSync as readFileSync3, rmSync, unlinkSync, writeFileSync as writeFileSync11 } from "fs";
18933
19005
  import { tmpdir } from "os";
18934
19006
  import { join as join10 } from "path";
18935
- import process25 from "process";
19007
+ import process27 from "process";
18936
19008
  async function settleAppliedFiles(qb, dialect, files) {
18937
19009
  if (files.length === 0)
18938
19010
  return;
@@ -18970,7 +19042,7 @@ function getSnapshotPath(workspaceRoot, dialect) {
18970
19042
  }
18971
19043
  function loadPlanSnapshot(workspaceRoot, dialect) {
18972
19044
  const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
18973
- if (!existsSync17(snapshotPath)) {
19045
+ if (!existsSync16(snapshotPath)) {
18974
19046
  return;
18975
19047
  }
18976
19048
  try {
@@ -18993,7 +19065,7 @@ function savePlanSnapshot(workspaceRoot, dialect, plan) {
18993
19065
  const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
18994
19066
  const snapshotDir = getSnapshotDir(workspaceRoot);
18995
19067
  const hash = hashMigrationPlan(plan);
18996
- if (existsSync17(snapshotPath)) {
19068
+ if (existsSync16(snapshotPath)) {
18997
19069
  try {
18998
19070
  const current = JSON.parse(readFileSync3(snapshotPath, "utf8"));
18999
19071
  if (current?.hash === hash && current?.dialect === dialect && current?.plan) {
@@ -19002,7 +19074,7 @@ function savePlanSnapshot(workspaceRoot, dialect, plan) {
19002
19074
  }
19003
19075
  } catch {}
19004
19076
  }
19005
- if (!existsSync17(snapshotDir)) {
19077
+ if (!existsSync16(snapshotDir)) {
19006
19078
  mkdirSync8(snapshotDir, { recursive: true });
19007
19079
  info(`-- Created snapshot directory: ${snapshotDir}`);
19008
19080
  }
@@ -19024,7 +19096,7 @@ function getWorkspaceRoot() {
19024
19096
  }
19025
19097
  function ensureSqlDirectory(workspaceRoot) {
19026
19098
  const sqlDir = getSqlDirectory(workspaceRoot, config5.migrationDir);
19027
- if (!existsSync17(sqlDir)) {
19099
+ if (!existsSync16(sqlDir)) {
19028
19100
  mkdirSync8(sqlDir, { recursive: true });
19029
19101
  info(`-- Created SQL directory: ${sqlDir}`);
19030
19102
  }
@@ -19033,7 +19105,7 @@ function ensureSqlDirectory(workspaceRoot) {
19033
19105
  async function generateMigration(dir, opts = {}) {
19034
19106
  await getConfig();
19035
19107
  if (!dir) {
19036
- dir = join10(process25.cwd(), "app/Models");
19108
+ dir = join10(process27.cwd(), "app/Models");
19037
19109
  }
19038
19110
  const dialect = opts.dialect || config5.dialect || "postgres";
19039
19111
  const workspaceRoot = getWorkspaceRoot();
@@ -19048,7 +19120,7 @@ async function generateMigration(dir, opts = {}) {
19048
19120
  } else {
19049
19121
  const defaultStatePath = join10(dir, `.qb-migrations.${dialect}.json`);
19050
19122
  const statePath = String(opts.state || defaultStatePath);
19051
- if (existsSync17(statePath)) {
19123
+ if (existsSync16(statePath)) {
19052
19124
  try {
19053
19125
  const raw2 = readFileSync3(statePath, "utf8");
19054
19126
  const parsed = JSON.parse(raw2);
@@ -19113,6 +19185,33 @@ async function generateMigration(dir, opts = {}) {
19113
19185
  savePlanSnapshot(workspaceRoot, dialect, plan);
19114
19186
  return { sql, sqlStatements, hasChanges, plan, operations };
19115
19187
  }
19188
+ function supportsTransactionalDdl(dialect) {
19189
+ return dialect === "postgres" || dialect === "sqlite";
19190
+ }
19191
+ async function withMigrationLock(dialect, fn) {
19192
+ if (dialect === "sqlite")
19193
+ return await fn();
19194
+ const qb = createQueryBuilder();
19195
+ let reserved;
19196
+ try {
19197
+ reserved = await qb.reserve();
19198
+ } catch {
19199
+ return await fn();
19200
+ }
19201
+ let held = false;
19202
+ try {
19203
+ await reserved.advisoryLock(MIGRATION_LOCK_KEY);
19204
+ held = true;
19205
+ return await fn();
19206
+ } finally {
19207
+ try {
19208
+ if (held)
19209
+ await reserved.advisoryUnlock(MIGRATION_LOCK_KEY);
19210
+ } finally {
19211
+ reserved.release?.();
19212
+ }
19213
+ }
19214
+ }
19116
19215
  async function executeMigration(dir) {
19117
19216
  await getConfig();
19118
19217
  const workspaceRoot = getWorkspaceRoot();
@@ -19127,32 +19226,47 @@ async function executeMigration(dir) {
19127
19226
  info(`-- Found ${scriptFiles.length} script files to execute`);
19128
19227
  try {
19129
19228
  const qb = createQueryBuilder();
19130
- await createMigrationsTable(qb, dialect);
19131
- const executedMigrations = await getExecutedMigrations(qb, dialect);
19132
- const pending = scriptFiles.filter((file2) => !executedMigrations.includes(file2));
19133
- if (pending.length === 0) {
19134
- info("-- No pending migrations to execute");
19135
- return true;
19136
- }
19137
- info(`-- Executing ${pending.length} migration${pending.length === 1 ? "" : "s"}`);
19138
- for (const file2 of pending) {
19139
- const filePath = join10(sqlDir, file2);
19140
- info(`-- Executing: ${file2}`);
19141
- try {
19142
- await qb.file(filePath);
19143
- await recordMigration(qb, file2, dialect);
19144
- info(`-- \u2713 Migration ${file2} executed and recorded`);
19145
- } catch (err) {
19146
- if (isGeneratedMigration(sqlDir, file2) && isAlreadyAppliedError(err)) {
19147
- await recordMigration(qb, file2, dialect);
19148
- info(`-- \u2713 Migration ${file2} was already applied; recorded it (${err instanceof Error ? err.message : String(err)})`);
19149
- continue;
19229
+ return await withMigrationLock(dialect, async () => {
19230
+ await createMigrationsTable(qb, dialect);
19231
+ const executedMigrations = await getExecutedMigrations(qb, dialect);
19232
+ const pending = scriptFiles.filter((file2) => !executedMigrations.includes(file2));
19233
+ if (pending.length === 0) {
19234
+ info("-- No pending migrations to execute");
19235
+ return true;
19236
+ }
19237
+ info(`-- Executing ${pending.length} migration${pending.length === 1 ? "" : "s"}`);
19238
+ for (const file2 of pending) {
19239
+ const filePath = join10(sqlDir, file2);
19240
+ info(`-- Executing: ${file2}`);
19241
+ try {
19242
+ const wrappable = supportsTransactionalDdl(dialect) && !NON_TRANSACTIONAL_SQL.test(readFileSync3(filePath, "utf-8"));
19243
+ if (wrappable) {
19244
+ await qb.transaction(async (tx) => {
19245
+ await tx.file(filePath);
19246
+ await recordMigration(tx, file2, dialect);
19247
+ });
19248
+ } else {
19249
+ await qb.file(filePath);
19250
+ await recordMigration(qb, file2, dialect);
19251
+ if (!supportsTransactionalDdl(dialect))
19252
+ info(`-- (${dialect} commits DDL implicitly, so ${file2} was not applied atomically)`);
19253
+ else
19254
+ info(`-- (${file2} contains a statement that cannot run in a transaction, so it was not applied atomically)`);
19255
+ }
19256
+ info(`-- \u2713 Migration ${file2} executed and recorded`);
19257
+ } catch (err) {
19258
+ if (isGeneratedMigration(sqlDir, file2) && isAlreadyAppliedError(err)) {
19259
+ await recordMigration(qb, file2, dialect);
19260
+ info(`-- \u2713 Migration ${file2} was already applied; recorded it (${err instanceof Error ? err.message : String(err)})`);
19261
+ continue;
19262
+ }
19263
+ console.error(`-- \u2717 Migration ${file2} failed:`, err);
19264
+ throw err;
19150
19265
  }
19151
- console.error(`-- \u2717 Migration ${file2} failed:`, err);
19152
- throw err;
19153
19266
  }
19154
- }
19155
- info("-- All migrations executed successfully");
19267
+ info("-- All migrations executed successfully");
19268
+ return true;
19269
+ });
19156
19270
  } catch (err) {
19157
19271
  console.error("-- Migration execution failed:", err);
19158
19272
  throw err;
@@ -19162,7 +19276,7 @@ async function executeMigration(dir) {
19162
19276
  async function resetDatabase(dir, opts = {}) {
19163
19277
  await getConfig();
19164
19278
  if (!dir) {
19165
- dir = join10(process25.cwd(), "app/Models");
19279
+ dir = join10(process27.cwd(), "app/Models");
19166
19280
  }
19167
19281
  const dialect = opts.dialect || config5.dialect || "postgres";
19168
19282
  const driver = getDialectDriver(dialect);
@@ -19259,27 +19373,27 @@ async function resetDatabase(dir, opts = {}) {
19259
19373
  }
19260
19374
  async function deleteMigrationFiles(dir, workspaceRoot, opts = {}) {
19261
19375
  if (!dir) {
19262
- dir = join10(process25.cwd(), "app/Models");
19376
+ dir = join10(process27.cwd(), "app/Models");
19263
19377
  }
19264
19378
  if (!workspaceRoot) {
19265
19379
  workspaceRoot = getWorkspaceRoot();
19266
19380
  }
19267
19381
  const dialect = String(opts.dialect || config5.dialect || "postgres");
19268
19382
  const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
19269
- if (existsSync17(snapshotPath)) {
19383
+ if (existsSync16(snapshotPath)) {
19270
19384
  unlinkSync(snapshotPath);
19271
19385
  info(`-- Removed model snapshot file: ${snapshotPath}`);
19272
19386
  }
19273
19387
  const defaultStatePath = join10(dir, `.qb-migrations.${dialect}.json`);
19274
19388
  const statePath = String(opts.state || defaultStatePath);
19275
- if (existsSync17(statePath)) {
19389
+ if (existsSync16(statePath)) {
19276
19390
  unlinkSync(statePath);
19277
19391
  info(`-- Removed legacy migration state file: ${statePath}`);
19278
19392
  }
19279
19393
  removeGeneratedMigrationFiles(getSqlDirectory(workspaceRoot, config5.migrationDir));
19280
19394
  }
19281
19395
  function removeGeneratedMigrationFiles(sqlDir) {
19282
- if (!existsSync17(sqlDir))
19396
+ if (!existsSync16(sqlDir))
19283
19397
  return;
19284
19398
  let removed = 0;
19285
19399
  const kept = [];
@@ -19302,7 +19416,7 @@ async function clearGeneratedDirectory(workspaceRoot) {
19302
19416
  workspaceRoot = getWorkspaceRoot();
19303
19417
  }
19304
19418
  const generatedDir = join10(workspaceRoot, "generated");
19305
- if (existsSync17(generatedDir)) {
19419
+ if (existsSync16(generatedDir)) {
19306
19420
  try {
19307
19421
  rmSync(generatedDir, { recursive: true, force: true });
19308
19422
  info("-- Cleared generated directory");
@@ -19343,6 +19457,7 @@ async function recordMigration(qb, migrationFile, dialect) {
19343
19457
  throw err;
19344
19458
  }
19345
19459
  }
19460
+ var MIGRATION_LOCK_KEY = "bun-query-builder:migrate", NON_TRANSACTIONAL_SQL;
19346
19461
  var init_migrate = __esm(() => {
19347
19462
  init_config();
19348
19463
  init_db();
@@ -19350,6 +19465,7 @@ var init_migrate = __esm(() => {
19350
19465
  init_src2();
19351
19466
  init_introspect_db();
19352
19467
  init_workspace();
19468
+ NON_TRANSACTIONAL_SQL = /\bCONCURRENTLY\b|^\s*VACUUM\b/im;
19353
19469
  });
19354
19470
 
19355
19471
  // src/actions/migrate-generate.ts
@@ -19361,7 +19477,7 @@ var init_migrate_generate = __esm(() => {
19361
19477
  });
19362
19478
 
19363
19479
  // src/actions/migrate-rollback.ts
19364
- import { existsSync as existsSync18, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
19480
+ import { existsSync as existsSync17, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
19365
19481
  import { join as join11 } from "path";
19366
19482
  function splitSqlStatements2(sql) {
19367
19483
  const out = [];
@@ -19476,7 +19592,7 @@ async function migrateRollback(options = {}) {
19476
19592
  for (const migration of migrationsToRollback) {
19477
19593
  try {
19478
19594
  const filePath = join11(sqlDir, migration.migration);
19479
- if (reverseSchema && existsSync18(filePath)) {
19595
+ if (reverseSchema && existsSync17(filePath)) {
19480
19596
  const forwardSql = readFileSync4(filePath, "utf8");
19481
19597
  const { down, skipped } = deriveDownStatements(forwardSql);
19482
19598
  for (const stmt of down) {
@@ -19490,7 +19606,7 @@ async function migrateRollback(options = {}) {
19490
19606
  const deleteSql = `DELETE FROM migrations WHERE migration = ${getPlaceholder(1)}`;
19491
19607
  await qb.unsafe(deleteSql, [migration.migration]);
19492
19608
  console.log(`-- \u2713 Removed migration record: ${migration.migration}`);
19493
- if (options.deleteFiles && existsSync18(filePath)) {
19609
+ if (options.deleteFiles && existsSync17(filePath)) {
19494
19610
  unlinkSync2(filePath);
19495
19611
  console.log(`-- \uD83D\uDDD1\uFE0F Deleted migration file: ${migration.migration}`);
19496
19612
  }
@@ -19517,7 +19633,7 @@ var init_migrate_rollback = __esm(() => {
19517
19633
  });
19518
19634
 
19519
19635
  // src/actions/migrate-status.ts
19520
- import { existsSync as existsSync19, readdirSync as readdirSync8 } from "fs";
19636
+ import { existsSync as existsSync18, readdirSync as readdirSync8 } from "fs";
19521
19637
  async function migrateStatus() {
19522
19638
  const dialect = config5.dialect || "postgres";
19523
19639
  const driver = getDialectDriver(dialect);
@@ -19526,7 +19642,7 @@ async function migrateStatus() {
19526
19642
  console.log(`-- Dialect: ${dialect}`);
19527
19643
  console.log(`-- SQL directory: ${sqlDir}`);
19528
19644
  console.log();
19529
- if (!existsSync19(sqlDir)) {
19645
+ if (!existsSync18(sqlDir)) {
19530
19646
  console.log("-- No SQL directory found. No migrations have been created yet.");
19531
19647
  return [];
19532
19648
  }
@@ -19591,9 +19707,9 @@ var init_migrate_status = __esm(() => {
19591
19707
  // src/actions/model-show.ts
19592
19708
  import { readdirSync as readdirSync9 } from "fs";
19593
19709
  import { extname as extname2, join as join12 } from "path";
19594
- import process26 from "process";
19710
+ import process28 from "process";
19595
19711
  async function modelShow(modelName, options = {}) {
19596
- const dir = options.dir || join12(process26.cwd(), "app/Models");
19712
+ const dir = options.dir || join12(process28.cwd(), "app/Models");
19597
19713
  try {
19598
19714
  const files = readdirSync9(dir);
19599
19715
  const modelFile = files.find((f) => {
@@ -19807,9 +19923,9 @@ var init_query_explain_all = __esm(() => {
19807
19923
  // src/actions/relation-diagram.ts
19808
19924
  import { writeFileSync as writeFileSync12 } from "fs";
19809
19925
  import { join as join14 } from "path";
19810
- import process27 from "process";
19926
+ import process29 from "process";
19811
19927
  async function relationDiagram(options = {}) {
19812
- const dir = options.dir || join14(process27.cwd(), "app/Models");
19928
+ const dir = options.dir || join14(process29.cwd(), "app/Models");
19813
19929
  const format = options.format || "mermaid";
19814
19930
  try {
19815
19931
  const models = await loadModels({ modelsDir: dir });
@@ -19929,21 +20045,21 @@ var init_relation_diagram = __esm(() => {
19929
20045
  });
19930
20046
 
19931
20047
  // src/actions/seed.ts
19932
- import { existsSync as existsSync20, mkdirSync as mkdirSync9, readdirSync as readdirSync11, writeFileSync as writeFileSync13 } from "fs";
20048
+ import { existsSync as existsSync19, mkdirSync as mkdirSync9, readdirSync as readdirSync11, writeFileSync as writeFileSync13 } from "fs";
19933
20049
  import { dirname as dirname10, join as join15 } from "path";
19934
- import process28 from "process";
20050
+ import process30 from "process";
19935
20051
  function findWorkspaceRoot3(startPath) {
19936
20052
  let currentPath = startPath;
19937
20053
  while (currentPath !== dirname10(currentPath)) {
19938
- if (existsSync20(join15(currentPath, "package.json"))) {
20054
+ if (existsSync19(join15(currentPath, "package.json"))) {
19939
20055
  return currentPath;
19940
20056
  }
19941
20057
  currentPath = dirname10(currentPath);
19942
20058
  }
19943
- return process28.cwd();
20059
+ return process30.cwd();
19944
20060
  }
19945
20061
  async function loadSeeders(seedersDir) {
19946
- if (!existsSync20(seedersDir)) {
20062
+ if (!existsSync19(seedersDir)) {
19947
20063
  console.log(`-- Seeders directory not found: ${seedersDir}`);
19948
20064
  return [];
19949
20065
  }
@@ -19973,7 +20089,7 @@ async function loadSeeders(seedersDir) {
19973
20089
  return seeders;
19974
20090
  }
19975
20091
  async function runSeeders(config6 = {}) {
19976
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20092
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
19977
20093
  const seedersDir = config6.seedersDir || join15(workspaceRoot, "database/seeders");
19978
20094
  const verbose = config6.verbose ?? true;
19979
20095
  if (verbose) {
@@ -20008,7 +20124,7 @@ async function runSeeders(config6 = {}) {
20008
20124
  }
20009
20125
  }
20010
20126
  async function runSeeder(className, options = {}) {
20011
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20127
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
20012
20128
  const seedersDir = join15(workspaceRoot, "database/seeders");
20013
20129
  const verbose = options.verbose ?? true;
20014
20130
  if (verbose) {
@@ -20033,9 +20149,9 @@ async function runSeeder(className, options = {}) {
20033
20149
  }
20034
20150
  }
20035
20151
  async function makeSeeder(name) {
20036
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20152
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
20037
20153
  const seedersDir = join15(workspaceRoot, "database/seeders");
20038
- if (!existsSync20(seedersDir)) {
20154
+ if (!existsSync19(seedersDir)) {
20039
20155
  mkdirSync9(seedersDir, { recursive: true });
20040
20156
  console.log(`-- Created seeders directory: ${seedersDir}`);
20041
20157
  }
@@ -20043,7 +20159,7 @@ async function makeSeeder(name) {
20043
20159
  const className = `${baseName}Seeder`;
20044
20160
  const fileName = `${className}.ts`;
20045
20161
  const filePath = join15(seedersDir, fileName);
20046
- if (existsSync20(filePath)) {
20162
+ if (existsSync19(filePath)) {
20047
20163
  console.error(`-- Seeder already exists: ${filePath}`);
20048
20164
  throw new Error(`Seeder already exists: ${filePath}`);
20049
20165
  }
@@ -20097,7 +20213,7 @@ export default class ${className} extends Seeder {
20097
20213
  console.log(`-- \u2713 Created seeder: ${filePath}`);
20098
20214
  }
20099
20215
  async function freshDatabase(options = {}) {
20100
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20216
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
20101
20217
  const modelsDir = options.modelsDir || join15(workspaceRoot, "app/Models");
20102
20218
  const seedersDir = options.seedersDir || join15(workspaceRoot, "database/seeders");
20103
20219
  const verbose = options.verbose ?? true;
@@ -20157,22 +20273,22 @@ var init_unsafe = __esm(() => {
20157
20273
  });
20158
20274
 
20159
20275
  // src/actions/validate.ts
20160
- import { existsSync as existsSync21 } from "fs";
20276
+ import { existsSync as existsSync20 } from "fs";
20161
20277
  import { dirname as dirname11, join as join16 } from "path";
20162
- import process29 from "process";
20278
+ import process31 from "process";
20163
20279
  function findWorkspaceRoot4(startPath) {
20164
20280
  let currentPath = startPath;
20165
20281
  while (currentPath !== dirname11(currentPath)) {
20166
- if (existsSync21(join16(currentPath, "package.json"))) {
20282
+ if (existsSync20(join16(currentPath, "package.json"))) {
20167
20283
  return currentPath;
20168
20284
  }
20169
20285
  currentPath = dirname11(currentPath);
20170
20286
  }
20171
- return process29.cwd();
20287
+ return process31.cwd();
20172
20288
  }
20173
20289
  async function validateSchema(dir) {
20174
20290
  if (!dir) {
20175
- dir = join16(findWorkspaceRoot4(process29.cwd()), "app/Models");
20291
+ dir = join16(findWorkspaceRoot4(process31.cwd()), "app/Models");
20176
20292
  }
20177
20293
  const dialect = config5.dialect || "postgres";
20178
20294
  console.log("-- Validating Schema");
@@ -25431,6 +25547,28 @@ function toTableName2(modelName) {
25431
25547
  tableNameCache.set(modelName, cached);
25432
25548
  return cached;
25433
25549
  }
25550
+ function relationNamesFor(definition, kind) {
25551
+ const rel = definition[kind];
25552
+ if (!rel)
25553
+ return [];
25554
+ if (Array.isArray(rel))
25555
+ return rel.map((item) => typeof item === "string" ? item : String(item?.model ?? "")).filter(Boolean);
25556
+ if (typeof rel === "object")
25557
+ return Object.keys(rel);
25558
+ if (typeof rel === "string")
25559
+ return [rel];
25560
+ return [];
25561
+ }
25562
+ function unresolvedRelationMessage(definition, relationName) {
25563
+ const model = definition.name ?? definition.table ?? "model";
25564
+ const declaredUnder = DECLARABLE_RELATION_KINDS.filter((kind) => relationNamesFor(definition, kind).some((n2) => n2.toLowerCase() === relationName.toLowerCase()));
25565
+ const unsupported = declaredUnder.filter((k2) => !RESOLVABLE_RELATION_KINDS.includes(k2));
25566
+ if (unsupported.length > 0) {
25567
+ return `[orm] '${model}' declares '${relationName}' as ${unsupported.join("/")}, which eager loading does not support yet. ` + `Supported kinds: ${RESOLVABLE_RELATION_KINDS.join(", ")}. ` + `Load it with a manual query for now \u2014 see stacksjs/bun-query-builder#1068.`;
25568
+ }
25569
+ const available = RESOLVABLE_RELATION_KINDS.flatMap((kind) => relationNamesFor(definition, kind));
25570
+ return available.length > 0 ? `[orm] '${model}' has no relation '${relationName}'. Available: ${available.join(", ")}.` : `[orm] '${model}' has no relation '${relationName}' \u2014 it declares no relations at all.`;
25571
+ }
25434
25572
  function resolveRelation(definition, relationName) {
25435
25573
  const parentName = definition.name;
25436
25574
  const parentTable = definition.table;
@@ -26165,7 +26303,7 @@ class ModelQueryBuilder {
26165
26303
  relationCache.set(cacheKey, rel);
26166
26304
  }
26167
26305
  if (!rel)
26168
- return;
26306
+ throw new Error(unresolvedRelationMessage(this._definition, relationName));
26169
26307
  if (rel.type === "hasMany" || rel.type === "hasOne") {
26170
26308
  const parentIds = distinctParentIds(instances, pk);
26171
26309
  if (parentIds.length === 0)
@@ -26757,7 +26895,7 @@ async function seedModel(definition, count, faker) {
26757
26895
  await exec.run(`INSERT INTO ${definition.table} (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`, Object.values(data));
26758
26896
  }
26759
26897
  }
26760
- var SAFE_SQL_IDENTIFIER, _getModel = null, pgPlaceholderCache, PG_PLACEHOLDER_CACHE_MAX = 500, globalDb = null, _executor = null, _executorForDb = null, _executorDialect = null, _executorDatabase = null, SOFT_DELETE_COLUMN = "deleted_at", BTM_RELATED_ALIAS = "__btm_rel__", btmKeysCache, snakeCaseCache, tableNameCache, relationCache, RELATION_CACHE_MAX = 1000;
26898
+ var SAFE_SQL_IDENTIFIER, _getModel = null, pgPlaceholderCache, PG_PLACEHOLDER_CACHE_MAX = 500, globalDb = null, _executor = null, _executorForDb = null, _executorDialect = null, _executorDatabase = null, SOFT_DELETE_COLUMN = "deleted_at", BTM_RELATED_ALIAS = "__btm_rel__", btmKeysCache, snakeCaseCache, tableNameCache, relationCache, RELATION_CACHE_MAX = 1000, RESOLVABLE_RELATION_KINDS, DECLARABLE_RELATION_KINDS;
26761
26899
  var init_orm = __esm(() => {
26762
26900
  init_config();
26763
26901
  init_db();
@@ -26768,6 +26906,17 @@ var init_orm = __esm(() => {
26768
26906
  snakeCaseCache = new Map;
26769
26907
  tableNameCache = new Map;
26770
26908
  relationCache = new Map;
26909
+ RESOLVABLE_RELATION_KINDS = ["hasMany", "hasOne", "belongsTo", "belongsToMany"];
26910
+ DECLARABLE_RELATION_KINDS = [
26911
+ ...RESOLVABLE_RELATION_KINDS,
26912
+ "hasOneThrough",
26913
+ "hasManyThrough",
26914
+ "morphOne",
26915
+ "morphMany",
26916
+ "morphTo",
26917
+ "morphToMany",
26918
+ "morphedByMany"
26919
+ ];
26771
26920
  });
26772
26921
 
26773
26922
  // src/model.ts
@@ -28217,7 +28366,7 @@ var init_factory = () => {};
28217
28366
  // src/loader.ts
28218
28367
  import { readdirSync as readdirSync12 } from "fs";
28219
28368
  import { basename, extname as extname4, isAbsolute as isAbsolute5, join as join17 } from "path";
28220
- import process30 from "process";
28369
+ import process33 from "process";
28221
28370
  function isModelFile(name) {
28222
28371
  const ext = extname4(name);
28223
28372
  if (!MODEL_EXTENSIONS.has(ext))
@@ -28248,7 +28397,7 @@ function collectModelFiles(dir) {
28248
28397
  return files;
28249
28398
  }
28250
28399
  async function loadModels(options) {
28251
- const cwd = options.cwd ?? process30.cwd();
28400
+ const cwd = options.cwd ?? process33.cwd();
28252
28401
  const dir = isAbsolute5(options.modelsDir) ? options.modelsDir : join17(cwd, options.modelsDir);
28253
28402
  const result = {};
28254
28403
  for (const full of collectModelFiles(dir)) {
@@ -28355,9 +28504,9 @@ function buildSchemaMeta(models) {
28355
28504
  var init_meta = () => {};
28356
28505
 
28357
28506
  // src/migrations.ts
28358
- import { existsSync as existsSync23, mkdirSync as mkdirSync10, readdirSync as readdirSync13, readFileSync as readFileSync6, writeFileSync as writeFileSync14 } from "fs";
28507
+ import { existsSync as existsSync21, mkdirSync as mkdirSync10, readdirSync as readdirSync13, readFileSync as readFileSync6, writeFileSync as writeFileSync14 } from "fs";
28359
28508
  import { dirname as dirname12, join as join18 } from "path";
28360
- import process31 from "process";
28509
+ import process35 from "process";
28361
28510
  function info2(message) {
28362
28511
  if (config5.verbose)
28363
28512
  console.log(message);
@@ -28374,17 +28523,17 @@ function lastCreatedMigrationFiles() {
28374
28523
  function findWorkspaceRoot5(startPath) {
28375
28524
  let currentPath = startPath;
28376
28525
  while (currentPath !== dirname12(currentPath)) {
28377
- if (existsSync23(join18(currentPath, "package.json"))) {
28526
+ if (existsSync21(join18(currentPath, "package.json"))) {
28378
28527
  return currentPath;
28379
28528
  }
28380
28529
  currentPath = dirname12(currentPath);
28381
28530
  }
28382
- return process31.cwd();
28531
+ return process35.cwd();
28383
28532
  }
28384
28533
  function ensureSqlDirectory2() {
28385
- const workspaceRoot = findWorkspaceRoot5(process31.cwd());
28534
+ const workspaceRoot = findWorkspaceRoot5(process35.cwd());
28386
28535
  const sqlDir = getSqlDirectory(workspaceRoot, config5.migrationDir);
28387
- if (!existsSync23(sqlDir)) {
28536
+ if (!existsSync21(sqlDir)) {
28388
28537
  mkdirSync10(sqlDir, { recursive: true });
28389
28538
  info2(`-- Created SQL directory: ${sqlDir}`);
28390
28539
  }
@@ -28429,7 +28578,7 @@ function createMigrationFile(statement, fileName) {
28429
28578
  let fullFileName = `${sequence}-${fileName}.sql`;
28430
28579
  if (!useDeterministicNames) {
28431
28580
  let next = Number(sequence);
28432
- while (existsSync23(join18(sqlDir, fullFileName))) {
28581
+ while (existsSync21(join18(sqlDir, fullFileName))) {
28433
28582
  next += 1;
28434
28583
  sequence = String(next);
28435
28584
  fullFileName = `${sequence}-${fileName}.sql`;
@@ -29751,6 +29900,7 @@ export {
29751
29900
  defineSeeder,
29752
29901
  defineModels,
29753
29902
  defineModel,
29903
+ defineConfig,
29754
29904
  defaultConfig4 as defaultConfig,
29755
29905
  dbWipe,
29756
29906
  dbStats,