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/bin/cli.js CHANGED
@@ -3049,25 +3049,27 @@ var init_dynamodb = __esm(() => {
3049
3049
 
3050
3050
  // ../../node_modules/bunfig/dist/index.js
3051
3051
  import { existsSync, statSync } from "fs";
3052
+ import { resolve } from "path";
3053
+ import process2 from "process";
3052
3054
  import { existsSync as existsSync13, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readFileSync, writeFileSync as writeFileSync7 } from "fs";
3053
3055
  import { homedir as homedir3 } from "os";
3054
3056
  import { dirname as dirname4, resolve as resolve12 } from "path";
3055
3057
  import process20 from "process";
3056
- import { existsSync as existsSync2, statSync as statSync2 } from "fs";
3058
+ import { existsSync as existsSync3, statSync as statSync2 } from "fs";
3057
3059
  import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync5 } from "fs";
3058
3060
  import { homedir as homedir2 } from "os";
3059
3061
  import { dirname as dirname3, resolve as resolve7 } from "path";
3060
3062
  import process12 from "process";
3061
3063
  import { join as join3, relative as relative2, resolve as resolve4 } from "path";
3062
3064
  import process7 from "process";
3063
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
3065
+ import { existsSync as existsSync32, mkdirSync as mkdirSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync3 } from "fs";
3064
3066
  import { homedir } from "os";
3065
3067
  import { dirname as dirname2, resolve as resolve3 } from "path";
3066
3068
  import process6 from "process";
3067
3069
  import { join, relative, resolve as resolve2 } from "path";
3068
- import process2 from "process";
3070
+ import process22 from "process";
3069
3071
  import { existsSync as existsSync22, mkdirSync, readdirSync, writeFileSync } from "fs";
3070
- import { dirname, resolve } from "path";
3072
+ import { dirname, resolve as resolve5 } from "path";
3071
3073
  import process3 from "process";
3072
3074
  import { Buffer as Buffer2 } from "buffer";
3073
3075
  import { createCipheriv, createDecipheriv, randomBytes } from "crypto";
@@ -3091,7 +3093,7 @@ import process10 from "process";
3091
3093
  import process9 from "process";
3092
3094
  import process8 from "process";
3093
3095
  import { existsSync as existsSync5 } from "fs";
3094
- import { resolve as resolve5 } from "path";
3096
+ import { resolve as resolve52 } from "path";
3095
3097
  import { existsSync as existsSync7 } from "fs";
3096
3098
  import { existsSync as existsSync9, readdirSync as readdirSync5 } from "fs";
3097
3099
  import { extname, resolve as resolve8 } from "path";
@@ -3351,6 +3353,34 @@ class PerformanceMonitor {
3351
3353
  return this.metrics.filter((m) => m.duration > threshold);
3352
3354
  }
3353
3355
  }
3356
+ function getConfigNamePatterns(options = {}) {
3357
+ const { name = "", alias } = options;
3358
+ const patterns = ["config", ".config"];
3359
+ if (name)
3360
+ patterns.push(name, `.${name}.config`, `${name}.config`, `.${name}`);
3361
+ const aliases = alias === undefined ? [] : Array.isArray(alias) ? alias : [alias];
3362
+ for (const alternative of aliases) {
3363
+ if (!alternative)
3364
+ continue;
3365
+ patterns.push(alternative, `.${alternative}.config`, `${alternative}.config`, `.${alternative}`);
3366
+ if (name)
3367
+ patterns.push(`${name}.${alternative}.config`, `.${name}.${alternative}.config`);
3368
+ }
3369
+ return Array.from(new Set(patterns.filter(Boolean)));
3370
+ }
3371
+ function getConfigPaths(options) {
3372
+ const patterns = getConfigNamePatterns(options);
3373
+ return patterns.flatMap((pattern) => CONFIG_FILE_EXTENSIONS.map((extension) => resolve(options.directory, `${pattern}${extension}`)));
3374
+ }
3375
+ function getLocalConfigDirectories(options = {}) {
3376
+ const cwd = resolve(options.cwd || process2.cwd());
3377
+ return Array.from(new Set([
3378
+ cwd,
3379
+ resolve(cwd, "config"),
3380
+ resolve(cwd, ".config"),
3381
+ options.configDir ? resolve(cwd, options.configDir) : undefined
3382
+ ].filter((directory) => Boolean(directory))));
3383
+ }
3354
3384
  function __exportSetter2(name, newValue) {
3355
3385
  this[name] = __returnValue2.bind(null, newValue);
3356
3386
  }
@@ -3434,7 +3464,7 @@ class ConfigCache2 {
3434
3464
  }
3435
3465
  isFileModified(configPath, cachedTimestamp) {
3436
3466
  try {
3437
- if (!existsSync2(configPath)) {
3467
+ if (!existsSync3(configPath)) {
3438
3468
  return true;
3439
3469
  }
3440
3470
  const stats = statSync2(configPath);
@@ -3456,7 +3486,7 @@ class ConfigCache2 {
3456
3486
  }
3457
3487
  setWithFileCheck(configName, value, configPath, customTtl) {
3458
3488
  try {
3459
- const stats = existsSync2(configPath) ? statSync2(configPath) : null;
3489
+ const stats = existsSync3(configPath) ? statSync2(configPath) : null;
3460
3490
  const fileTimestamp = stats ? stats.mtime : new Date;
3461
3491
  this.set(configName, { value, fileTimestamp }, configPath, customTtl);
3462
3492
  } catch {
@@ -3766,7 +3796,7 @@ async function loadConfig({
3766
3796
  ];
3767
3797
  for (const configPath of configPaths) {
3768
3798
  for (const ext of extensions) {
3769
- const fullPath = resolve(baseDir, `${configPath}${ext}`);
3799
+ const fullPath = resolve5(baseDir, `${configPath}${ext}`);
3770
3800
  const config2 = await tryLoadConfig(fullPath, defaultConfig);
3771
3801
  if (config2 !== null) {
3772
3802
  return config2;
@@ -3774,7 +3804,7 @@ async function loadConfig({
3774
3804
  }
3775
3805
  }
3776
3806
  try {
3777
- const pkgPath = resolve(baseDir, "package.json");
3807
+ const pkgPath = resolve5(baseDir, "package.json");
3778
3808
  if (existsSync22(pkgPath)) {
3779
3809
  const pkg = await import(pkgPath);
3780
3810
  const pkgConfig = pkg[name];
@@ -3788,12 +3818,12 @@ async function loadConfig({
3788
3818
  return defaultConfig;
3789
3819
  }
3790
3820
  function getProjectRoot(filePath, options = {}) {
3791
- let path = process2.cwd();
3821
+ let path = process22.cwd();
3792
3822
  while (path.includes("storage"))
3793
3823
  path = resolve2(path, "..");
3794
3824
  const finalPath = resolve2(path, filePath || "");
3795
3825
  if (options?.relative)
3796
- return relative(process2.cwd(), finalPath);
3826
+ return relative(process22.cwd(), finalPath);
3797
3827
  return finalPath;
3798
3828
  }
3799
3829
  async function loadConfig2() {
@@ -3801,7 +3831,7 @@ async function loadConfig2() {
3801
3831
  const loadedConfig = await loadConfig({
3802
3832
  name: "clarity",
3803
3833
  defaultConfig,
3804
- cwd: process2.cwd(),
3834
+ cwd: process22.cwd(),
3805
3835
  endpoint: "",
3806
3836
  headers: {}
3807
3837
  });
@@ -5143,7 +5173,7 @@ function isObject2(item) {
5143
5173
  return Boolean(item && typeof item === "object" && !Array.isArray(item));
5144
5174
  }
5145
5175
  async function tryLoadConfig2(configPath, defaultConfig2, arrayStrategy = "replace") {
5146
- if (!existsSync3(configPath))
5176
+ if (!existsSync32(configPath))
5147
5177
  return null;
5148
5178
  try {
5149
5179
  const importedConfig = await import(configPath);
@@ -5314,7 +5344,7 @@ async function loadConfig3({
5314
5344
  }
5315
5345
  try {
5316
5346
  const pkgPath = resolve3(baseDir, "package.json");
5317
- if (existsSync3(pkgPath)) {
5347
+ if (existsSync32(pkgPath)) {
5318
5348
  const pkg = await import(pkgPath);
5319
5349
  let pkgConfig = pkg[name];
5320
5350
  if (!pkgConfig && alias) {
@@ -5605,7 +5635,7 @@ class Logger2 {
5605
5635
  const errorMessage = typeof error.message === "string" ? error.message : "Unknown error";
5606
5636
  console.error(`Network error during write attempt ${retries + 1}/${maxRetries}:`, errorMessage);
5607
5637
  const delay = backoffDelay * 2 ** retries;
5608
- await new Promise((resolve52) => setTimeout(resolve52, delay));
5638
+ await new Promise((resolve522) => setTimeout(resolve522, delay));
5609
5639
  retries++;
5610
5640
  continue;
5611
5641
  }
@@ -5633,7 +5663,7 @@ class Logger2 {
5633
5663
  }
5634
5664
  retries++;
5635
5665
  const delay = backoffDelay * 2 ** (retries - 1);
5636
- await new Promise((resolve52) => setTimeout(resolve52, delay));
5666
+ await new Promise((resolve522) => setTimeout(resolve522, delay));
5637
5667
  }
5638
5668
  }
5639
5669
  })();
@@ -5763,11 +5793,11 @@ class Logger2 {
5763
5793
  };
5764
5794
  }
5765
5795
  async compressData(data) {
5766
- return new Promise((resolve52, reject) => {
5796
+ return new Promise((resolve522, reject) => {
5767
5797
  const gzip = createGzip2();
5768
5798
  const chunks = [];
5769
5799
  gzip.on("data", (chunk2) => chunks.push(chunk2));
5770
- gzip.on("end", () => resolve52(Buffer22.from(Buffer22.concat(chunks))));
5800
+ gzip.on("end", () => resolve522(Buffer22.from(Buffer22.concat(chunks))));
5771
5801
  gzip.on("error", reject);
5772
5802
  gzip.write(data);
5773
5803
  gzip.end();
@@ -6456,7 +6486,7 @@ class Logger2 {
6456
6486
  if (isBrowserProcess2()) {
6457
6487
  return Promise.resolve(true);
6458
6488
  }
6459
- return new Promise((resolve52) => {
6489
+ return new Promise((resolve522) => {
6460
6490
  console.error(`${styles2.cyan("?")} ${message} (y/n) `);
6461
6491
  const onData = (data) => {
6462
6492
  const input = data.toString().trim().toLowerCase();
@@ -6468,7 +6498,7 @@ class Logger2 {
6468
6498
  } catch {}
6469
6499
  process11.stdin.pause();
6470
6500
  console.error("");
6471
- resolve52(input === "y" || input === "yes");
6501
+ resolve522(input === "y" || input === "yes");
6472
6502
  };
6473
6503
  try {
6474
6504
  if (typeof process11.stdin.setRawMode === "function") {
@@ -6634,7 +6664,7 @@ async function withErrorRecovery(fn, options = {}) {
6634
6664
  break;
6635
6665
  }
6636
6666
  if (retryDelay > 0) {
6637
- await new Promise((resolve52) => setTimeout(resolve52, retryDelay));
6667
+ await new Promise((resolve522) => setTimeout(resolve522, retryDelay));
6638
6668
  }
6639
6669
  }
6640
6670
  }
@@ -7162,7 +7192,7 @@ class ConfigFileLoader {
7162
7192
  const paths = [];
7163
7193
  for (const pattern of patterns) {
7164
7194
  for (const ext of this.extensions) {
7165
- paths.push(resolve5(directory, `${pattern}${ext}`));
7195
+ paths.push(resolve52(directory, `${pattern}${ext}`));
7166
7196
  }
7167
7197
  }
7168
7198
  return paths;
@@ -7199,7 +7229,7 @@ class ConfigFileLoader {
7199
7229
  const patterns = this.generateNamePatterns(configName || "", alias);
7200
7230
  for (const pattern of patterns) {
7201
7231
  for (const ext of this.extensions) {
7202
- const filePath = resolve5(directory, `${pattern}${ext}`);
7232
+ const filePath = resolve52(directory, `${pattern}${ext}`);
7203
7233
  if (await this.checkFileAccess(filePath)) {
7204
7234
  discoveredFiles.push(filePath);
7205
7235
  }
@@ -7211,7 +7241,7 @@ class ConfigFileLoader {
7211
7241
  const files = readdirSync32(directory);
7212
7242
  for (const file of files) {
7213
7243
  if (this.looksLikeConfigFile(file)) {
7214
- const filePath = resolve5(directory, file);
7244
+ const filePath = resolve52(directory, file);
7215
7245
  if (await this.checkFileAccess(filePath)) {
7216
7246
  discoveredFiles.push(filePath);
7217
7247
  }
@@ -9936,7 +9966,7 @@ function isObject4(item) {
9936
9966
  }
9937
9967
 
9938
9968
  class ConfigFileLoader2 {
9939
- extensions = [".ts", ".js", ".mjs", ".cjs", ".json", ".mts", ".cts"];
9969
+ extensions = CONFIG_FILE_EXTENSIONS;
9940
9970
  async loadFromPath(configPath, defaultConfig4, options = {}) {
9941
9971
  const {
9942
9972
  arrayStrategy = "replace",
@@ -10011,37 +10041,10 @@ class ConfigFileLoader2 {
10011
10041
  return null;
10012
10042
  }
10013
10043
  generateConfigPaths(configName, directory, alias) {
10014
- const patterns = this.generateNamePatterns(configName, alias);
10015
- const paths = [];
10016
- for (const pattern of patterns) {
10017
- for (const ext of this.extensions) {
10018
- paths.push(resolve10(directory, `${pattern}${ext}`));
10019
- }
10020
- }
10021
- return paths;
10044
+ return getConfigPaths({ name: configName, directory, alias });
10022
10045
  }
10023
10046
  generateNamePatterns(configName, alias) {
10024
- const patterns = [];
10025
- patterns.push("config", ".config");
10026
- if (configName) {
10027
- patterns.push(configName, `.${configName}.config`, `${configName}.config`, `.${configName}`);
10028
- }
10029
- const aliases = alias === undefined ? [] : Array.isArray(alias) ? alias : [alias];
10030
- for (const a of aliases) {
10031
- if (!a)
10032
- continue;
10033
- patterns.push(a, `.${a}.config`, `${a}.config`, `.${a}`);
10034
- if (configName) {
10035
- patterns.push(`${configName}.${a}.config`, `.${configName}.${a}.config`);
10036
- }
10037
- }
10038
- const seen = new Set;
10039
- return patterns.filter((p) => {
10040
- if (!p || seen.has(p))
10041
- return false;
10042
- seen.add(p);
10043
- return true;
10044
- });
10047
+ return getConfigNamePatterns({ name: configName, alias });
10045
10048
  }
10046
10049
  checkFileAccess(filePath) {
10047
10050
  return withErrorRecovery2(async () => {
@@ -10552,6 +10555,8 @@ class ConfigLoader2 {
10552
10555
  try {
10553
10556
  result = await this.loadConfigurationStrategies(baseOptions, true, cache);
10554
10557
  } catch (error) {
10558
+ if (baseOptions.configFile)
10559
+ throw error;
10555
10560
  const isStrictMode = baseOptions.__strictErrorHandling;
10556
10561
  if (error instanceof Error && error.name === "ConfigNotFoundError") {
10557
10562
  if (isStrictMode) {
@@ -10626,6 +10631,7 @@ class ConfigLoader2 {
10626
10631
  const {
10627
10632
  name = "",
10628
10633
  alias,
10634
+ configFile,
10629
10635
  cwd,
10630
10636
  configDir,
10631
10637
  defaultConfig: defaultConfig4,
@@ -10635,6 +10641,17 @@ class ConfigLoader2 {
10635
10641
  } = options;
10636
10642
  const baseDir = cwd || process20.cwd();
10637
10643
  const searchPaths = [];
10644
+ if (configFile) {
10645
+ const explicitPath = resolve12(baseDir, configFile);
10646
+ searchPaths.push(explicitPath);
10647
+ const envDefaults = checkEnv ? applyEnvVarsToConfig3(name, defaultConfig4, verbose) : defaultConfig4;
10648
+ const explicitResult = await this.fileLoader.tryLoadFromPaths([explicitPath], envDefaults, { arrayStrategy, verbose, cacheTtl: cacheOptions?.ttl, useCache: !cacheOptions?.ttl || cacheOptions.ttl > 100 });
10649
+ if (!explicitResult)
10650
+ throw ErrorFactory2.configNotFound(name || configFile, searchPaths, alias);
10651
+ if (verbose)
10652
+ log3.success(`Configuration loaded from explicit path: ${explicitPath}`);
10653
+ return this.finalizeResult(explicitResult, searchPaths, checkEnv, name, verbose);
10654
+ }
10638
10655
  const localResult = await this.loadLocalConfiguration(name, alias, baseDir, configDir, defaultConfig4, arrayStrategy, verbose, checkEnv, cacheOptions);
10639
10656
  if (localResult) {
10640
10657
  searchPaths.push(...this.getLocalSearchPaths(name, alias, baseDir, configDir));
@@ -10822,6 +10839,8 @@ class ConfigLoader2 {
10822
10839
  }
10823
10840
  if (options.cwd)
10824
10841
  keyParts.push(`cwd:${options.cwd}`);
10842
+ if (options.configFile)
10843
+ keyParts.push(`configFile:${options.configFile}`);
10825
10844
  if (options.configDir)
10826
10845
  keyParts.push(`configDir:${options.configDir}`);
10827
10846
  if ("checkEnv" in options)
@@ -10829,12 +10848,7 @@ class ConfigLoader2 {
10829
10848
  return keyParts.join("|");
10830
10849
  }
10831
10850
  getLocalDirectories(baseDir, configDir) {
10832
- return Array.from(new Set([
10833
- baseDir,
10834
- resolve12(baseDir, "config"),
10835
- resolve12(baseDir, ".config"),
10836
- configDir ? resolve12(baseDir, configDir) : undefined
10837
- ].filter(Boolean)));
10851
+ return getLocalConfigDirectories({ cwd: baseDir, configDir });
10838
10852
  }
10839
10853
  getAllSearchPaths(name, alias, baseDir, configDir) {
10840
10854
  const paths = [];
@@ -10886,6 +10900,8 @@ async function loadConfig6(options) {
10886
10900
  }
10887
10901
  return result?.config ?? defaultConfig4;
10888
10902
  } catch (error) {
10903
+ if (options.configFile)
10904
+ throw error;
10889
10905
  const errorName = error instanceof Error ? error.name : "UnknownError";
10890
10906
  const errorMessage = error instanceof Error ? error.message : String(error);
10891
10907
  const isConfigError = errorName === "ConfigNotFoundError" || errorName === "ConfigLoadError" || errorName === "ConfigValidationError" || errorMessage.includes("config");
@@ -10953,7 +10969,7 @@ function applyEnvVarsToConfig3(name, config6, verbose = false) {
10953
10969
  }
10954
10970
  return processConfigLevel(config6);
10955
10971
  }
10956
- var globalCache, globalPerformanceMonitor, __defProp2, __returnValue2 = (v) => v, __export2 = (target, all) => {
10972
+ var globalCache, globalPerformanceMonitor, CONFIG_FILE_EXTENSIONS, __defProp2, __returnValue2 = (v) => v, __export2 = (target, all) => {
10957
10973
  for (var name in all)
10958
10974
  __defProp2(target, name, {
10959
10975
  get: all[name],
@@ -10965,6 +10981,15 @@ var globalCache, globalPerformanceMonitor, __defProp2, __returnValue2 = (v) => v
10965
10981
  var init_dist = __esm(() => {
10966
10982
  globalCache = new ConfigCache;
10967
10983
  globalPerformanceMonitor = new PerformanceMonitor;
10984
+ CONFIG_FILE_EXTENSIONS = [
10985
+ ".ts",
10986
+ ".js",
10987
+ ".mjs",
10988
+ ".cjs",
10989
+ ".json",
10990
+ ".mts",
10991
+ ".cts"
10992
+ ];
10968
10993
  __defProp2 = Object.defineProperty;
10969
10994
  exports_dist = {};
10970
10995
  __export2(exports_dist, {
@@ -11017,9 +11042,9 @@ var init_dist = __esm(() => {
11017
11042
  isEquivalent: isEquivalent2,
11018
11043
  estimateMemoryUsage: estimateMemoryUsage2
11019
11044
  };
11020
- defaultConfigDir = resolve(process3.cwd(), "config");
11021
- defaultGeneratedDir = resolve(process3.cwd(), "src/generated");
11022
- defaultLogDirectory = process2.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
11045
+ defaultConfigDir = resolve5(process3.cwd(), "config");
11046
+ defaultGeneratedDir = resolve5(process3.cwd(), "src/generated");
11047
+ defaultLogDirectory = process22.env.CLARITY_LOG_DIR || join(getProjectRoot(), "logs");
11023
11048
  defaultConfig = {
11024
11049
  level: "info",
11025
11050
  defaultName: "clarity",
@@ -11636,8 +11661,8 @@ var init_dist = __esm(() => {
11636
11661
  showTags: true
11637
11662
  });
11638
11663
  globalConfigLoader2 = new ConfigLoader2;
11639
- defaultConfigDir4 = resolve12(process20.cwd(), "config");
11640
- defaultGeneratedDir4 = resolve12(process20.cwd(), "src/generated");
11664
+ defaultConfigDir4 = /* @__PURE__ */ resolve12(process20.cwd(), "config");
11665
+ defaultGeneratedDir4 = /* @__PURE__ */ resolve12(process20.cwd(), "src/generated");
11641
11666
  });
11642
11667
 
11643
11668
  // src/config.ts
@@ -11645,6 +11670,29 @@ import process19 from "process";
11645
11670
  function isMysqlLike(dialect = config5.dialect) {
11646
11671
  return dialect === "mysql" || dialect === "singlestore" || dialect === "vitess";
11647
11672
  }
11673
+ function isPlainObject(value) {
11674
+ if (value === null || typeof value !== "object" || Array.isArray(value))
11675
+ return false;
11676
+ const proto = Object.getPrototypeOf(value);
11677
+ return proto === Object.prototype || proto === null;
11678
+ }
11679
+ function mergeObject(target, source, seen = new Set) {
11680
+ const out = { ...target };
11681
+ seen.add(source);
11682
+ for (const key of Object.keys(source)) {
11683
+ if (FORBIDDEN_MERGE_KEYS.has(key))
11684
+ continue;
11685
+ const next = source[key];
11686
+ if (isPlainObject(next) && !seen.has(next)) {
11687
+ const prev = out[key];
11688
+ out[key] = mergeObject(isPlainObject(prev) ? prev : {}, next, seen);
11689
+ } else {
11690
+ out[key] = next;
11691
+ }
11692
+ }
11693
+ seen.delete(source);
11694
+ return out;
11695
+ }
11648
11696
  function resolveDialect(explicit) {
11649
11697
  if (explicit)
11650
11698
  return explicit;
@@ -11688,21 +11736,12 @@ async function getConfig() {
11688
11736
  return config5;
11689
11737
  }
11690
11738
  function applyConfig(userConfig) {
11691
- Object.assign(config5, userConfig);
11692
- if (userConfig.database) {
11693
- config5.database = { ...config5.database, ...userConfig.database };
11694
- }
11695
- if (userConfig.timestamps) {
11696
- config5.timestamps = { ...config5.timestamps, ...userConfig.timestamps };
11697
- }
11698
- if (userConfig.pagination) {
11699
- config5.pagination = { ...config5.pagination, ...userConfig.pagination };
11700
- }
11701
- if (userConfig.softDeletes) {
11702
- config5.softDeletes = { ...config5.softDeletes, ...userConfig.softDeletes };
11703
- }
11704
- if (userConfig.vitess) {
11705
- config5.vitess = { ...config5.vitess, ...userConfig.vitess };
11739
+ const merged = mergeObject(config5, userConfig);
11740
+ const target = config5;
11741
+ for (const key of Object.keys(merged)) {
11742
+ if (FORBIDDEN_MERGE_KEYS.has(key))
11743
+ continue;
11744
+ target[key] = merged[key];
11706
11745
  }
11707
11746
  }
11708
11747
  function setConfig(userConfig) {
@@ -11710,7 +11749,7 @@ function setConfig(userConfig) {
11710
11749
  const key = `${_lastConfiguredDialect}->${userConfig.dialect}`;
11711
11750
  if (!_warnedDialectConflicts.has(key)) {
11712
11751
  _warnedDialectConflicts.add(key);
11713
- 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.`);
11752
+ 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.`);
11714
11753
  }
11715
11754
  }
11716
11755
  if (userConfig.dialect)
@@ -11719,7 +11758,10 @@ function setConfig(userConfig) {
11719
11758
  configState.explicit.add(key);
11720
11759
  applyConfig(userConfig);
11721
11760
  }
11722
- var defaultConfig4, CONFIG_SINGLETON_KEY, config5, CONFIG_STATE_KEY, configState, _lastConfiguredDialect = null, _warnedDialectConflicts;
11761
+ function defineConfig(userConfig) {
11762
+ return userConfig;
11763
+ }
11764
+ var defaultConfig4, FORBIDDEN_MERGE_KEYS, CONFIG_SINGLETON_KEY, config5, CONFIG_STATE_KEY, configState, _lastConfiguredDialect = null, _warnedDialectConflicts;
11723
11765
  var init_config = __esm(() => {
11724
11766
  init_dist();
11725
11767
  defaultConfig4 = {
@@ -11784,8 +11826,9 @@ var init_config = __esm(() => {
11784
11826
  defaultFilter: true
11785
11827
  }
11786
11828
  };
11829
+ FORBIDDEN_MERGE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
11787
11830
  CONFIG_SINGLETON_KEY = Symbol.for("bun-query-builder.config");
11788
- config5 = globalThis[CONFIG_SINGLETON_KEY] ??= { ...defaultConfig4 };
11831
+ config5 = globalThis[CONFIG_SINGLETON_KEY] ??= mergeObject({}, defaultConfig4);
11789
11832
  CONFIG_STATE_KEY = Symbol.for("bun-query-builder.config-state");
11790
11833
  configState = globalThis[CONFIG_STATE_KEY] ??= { explicit: new Set, fileLoaded: false };
11791
11834
  _warnedDialectConflicts = new Set;
@@ -11943,12 +11986,12 @@ function createSQLiteSQL(filename) {
11943
11986
  const params = [];
11944
11987
  for (let i = 0;i < values.length; i++) {
11945
11988
  const value = values[i];
11946
- if (value && typeof value === "object" && (value.__raw || value.raw)) {
11947
- const rawValue = value.__raw ? value.value : typeof value.raw === "string" ? value.raw : value.raw();
11948
- sql += rawValue + (strings[i + 1] || "");
11949
- } else if (value && typeof value === "object" && "sql" in value && "values" in value) {
11989
+ if (value && typeof value === "object" && typeof value.sql === "string" && Array.isArray(value.values)) {
11950
11990
  sql += value.sql + (strings[i + 1] || "");
11951
11991
  params.push(...value.values);
11992
+ } else if (value && typeof value === "object" && (value.__raw || value.raw)) {
11993
+ const rawValue = value.__raw ? value.value : typeof value.raw === "string" ? value.raw : value.raw();
11994
+ sql += rawValue + (strings[i + 1] || "");
11952
11995
  } else if (Array.isArray(value)) {
11953
11996
  const placeholders = value.map(() => "?").join(", ");
11954
11997
  sql += placeholders + (strings[i + 1] || "");
@@ -12583,6 +12626,11 @@ function renderSelectColumn(col) {
12583
12626
  }
12584
12627
  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\`)`);
12585
12628
  }
12629
+ function renderInPredicate(column, values, negated, placeholders) {
12630
+ if (values.length === 0)
12631
+ return negated ? TRUE_PREDICATE : FALSE_PREDICATE;
12632
+ return `${column} ${negated ? "NOT IN" : "IN"} (${placeholders})`;
12633
+ }
12586
12634
  function validateIdentifier(name, context) {
12587
12635
  if (!SQL_PATTERNS.IDENTIFIER.test(name)) {
12588
12636
  const contextMsg = context ? ` in ${context}` : "";
@@ -12828,6 +12876,20 @@ function createQueryBuilder(state) {
12828
12876
  const _sql = state?.sql ?? getOrCreateBunSql();
12829
12877
  const meta = state?.meta;
12830
12878
  const schema = state?.schema;
12879
+ function advisoryLockKey(key) {
12880
+ if (typeof key === "number")
12881
+ return key;
12882
+ const s = String(key);
12883
+ let hash = 7;
12884
+ for (let i = 0;i < s.length; i++)
12885
+ hash = hash * 31 + s.charCodeAt(i) | 0;
12886
+ return Math.abs(hash);
12887
+ }
12888
+ function activeHooks() {
12889
+ if (!state?.hooks)
12890
+ return config5.hooks;
12891
+ return { ...config5.hooks, ...state.hooks };
12892
+ }
12831
12893
  const dynamicWhereColumnCache = new Map;
12832
12894
  function applyCondition(expr) {
12833
12895
  if (Array.isArray(expr)) {
@@ -12919,7 +12981,7 @@ function createQueryBuilder(state) {
12919
12981
  return;
12920
12982
  }
12921
12983
  function runWithHooks(q, kind, opts) {
12922
- const hooks = config5.hooks;
12984
+ const hooks = activeHooks();
12923
12985
  const slowMs = hooks?.slowQueryThresholdMs;
12924
12986
  const slowEnabled = slowMs != null && slowMs >= 0;
12925
12987
  const hasSlowQuery = Boolean(hooks?.onSlowQuery || slowEnabled);
@@ -14286,8 +14348,12 @@ function createQueryBuilder(state) {
14286
14348
  return this;
14287
14349
  },
14288
14350
  whereAny(cols, op, value) {
14289
- if (cols.length === 0)
14351
+ if (cols.length === 0) {
14352
+ const kw = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14353
+ text += ` ${kw} (${FALSE_PREDICATE})`;
14354
+ built = null;
14290
14355
  return this;
14356
+ }
14291
14357
  const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14292
14358
  const idx = whereParams.length + 1;
14293
14359
  const conds = cols.map((c, i) => `${c} ${op} ${getPlaceholder(idx + i)}`);
@@ -14369,7 +14435,7 @@ function createQueryBuilder(state) {
14369
14435
  const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14370
14436
  if (Array.isArray(values)) {
14371
14437
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14372
- text += ` ${keyword} ${column} IN (${placeholders})`;
14438
+ text += ` ${keyword} ${renderInPredicate(column, values, false, placeholders)}`;
14373
14439
  whereParams.push(...values);
14374
14440
  } else {
14375
14441
  text += ` ${keyword} ${column} IN (${String(values.toSQL())})`;
@@ -14381,7 +14447,7 @@ function createQueryBuilder(state) {
14381
14447
  validateIdentifier(String(column), "orWhereIn(column)");
14382
14448
  if (Array.isArray(values)) {
14383
14449
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14384
- text += ` OR ${column} IN (${placeholders})`;
14450
+ text += ` OR ${renderInPredicate(column, values, false, placeholders)}`;
14385
14451
  whereParams.push(...values);
14386
14452
  } else {
14387
14453
  text += ` OR ${column} IN (${String(values.toSQL())})`;
@@ -14394,7 +14460,7 @@ function createQueryBuilder(state) {
14394
14460
  const keyword = SQL_PATTERNS.WHERE.test(text) ? "AND" : "WHERE";
14395
14461
  if (Array.isArray(values)) {
14396
14462
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14397
- text += ` ${keyword} ${column} NOT IN (${placeholders})`;
14463
+ text += ` ${keyword} ${renderInPredicate(column, values, true, placeholders)}`;
14398
14464
  whereParams.push(...values);
14399
14465
  } else {
14400
14466
  text += ` ${keyword} ${column} NOT IN (${String(values.toSQL())})`;
@@ -14406,7 +14472,7 @@ function createQueryBuilder(state) {
14406
14472
  validateIdentifier(String(column), "orWhereNotIn(column)");
14407
14473
  if (Array.isArray(values)) {
14408
14474
  const placeholders = getPlaceholders(values.length, whereParams.length + 1);
14409
- text += ` OR ${column} NOT IN (${placeholders})`;
14475
+ text += ` OR ${renderInPredicate(column, values, true, placeholders)}`;
14410
14476
  whereParams.push(...values);
14411
14477
  } else {
14412
14478
  text += ` OR ${column} NOT IN (${String(values.toSQL())})`;
@@ -15001,7 +15067,7 @@ function createQueryBuilder(state) {
15001
15067
  return text;
15002
15068
  },
15003
15069
  async get() {
15004
- const hooks = config5.hooks;
15070
+ const hooks = activeHooks();
15005
15071
  const hasQueryHooks = hooks && (hooks.onQueryStart || hooks.onQueryEnd || hooks.onQueryError || hooks.startSpan || hasSlowQueryHook(hooks));
15006
15072
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !hasQueryHooks) {
15007
15073
  const prepareFn = _sql._prepareStatement;
@@ -15054,7 +15120,7 @@ function createQueryBuilder(state) {
15054
15120
  return result;
15055
15121
  },
15056
15122
  async first() {
15057
- const fHooks = config5.hooks;
15123
+ const fHooks = activeHooks();
15058
15124
  const fHasQueryHooks = fHooks && (fHooks.onQueryStart || fHooks.onQueryEnd || fHooks.onQueryError || fHooks.startSpan || hasSlowQueryHook(fHooks));
15059
15125
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !fHasQueryHooks) {
15060
15126
  const prepareFn = _sql._prepareStatement;
@@ -15136,7 +15202,7 @@ function createQueryBuilder(state) {
15136
15202
  } else {
15137
15203
  countText = `SELECT COUNT(*) as c FROM ${table}`;
15138
15204
  }
15139
- const cHooks = config5.hooks;
15205
+ const cHooks = activeHooks();
15140
15206
  const cHasHooks = cHooks && (cHooks.onQueryStart || cHooks.onQueryEnd || cHooks.onQueryError || cHooks.startSpan || hasSlowQueryHook(cHooks));
15141
15207
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !cHasHooks) {
15142
15208
  const prepareFn = _sql._prepareStatement;
@@ -15154,7 +15220,7 @@ function createQueryBuilder(state) {
15154
15220
  async avg(column) {
15155
15221
  const fromIdx = text.indexOf(" FROM ");
15156
15222
  const avgText = fromIdx !== -1 ? `SELECT AVG(${column}) as a${text.substring(fromIdx)}` : `SELECT AVG(${column}) as a FROM ${table}`;
15157
- const aHooks = config5.hooks;
15223
+ const aHooks = activeHooks();
15158
15224
  const aHasHooks = aHooks && (aHooks.onQueryStart || aHooks.onQueryEnd || aHooks.onQueryError || aHooks.startSpan || hasSlowQueryHook(aHooks));
15159
15225
  if (!config5.softDeletes?.enabled && !useCache && !timeoutMs && !abortSignal && !aHasHooks) {
15160
15226
  const prepareFn = _sql._prepareStatement;
@@ -15291,7 +15357,7 @@ function createQueryBuilder(state) {
15291
15357
  }
15292
15358
  return {
15293
15359
  configure(opts) {
15294
- Object.assign(config5, opts);
15360
+ setConfig(opts);
15295
15361
  return this;
15296
15362
  },
15297
15363
  id(name) {
@@ -15668,7 +15734,7 @@ function createQueryBuilder(state) {
15668
15734
  return makeExecutableQuery(built, sqlText);
15669
15735
  },
15670
15736
  execute() {
15671
- const hooks = config5.hooks;
15737
+ const hooks = activeHooks();
15672
15738
  const hasHooks = hooks && (hooks.onQueryStart || hooks.onQueryEnd || hooks.onQueryError || hooks.startSpan || hooks.beforeCreate || hooks.afterCreate || hasSlowQueryHook(hooks));
15673
15739
  if (!hasHooks) {
15674
15740
  const prepareFn = _sql._prepareStatement;
@@ -16022,13 +16088,13 @@ function createQueryBuilder(state) {
16022
16088
  },
16023
16089
  async execute() {
16024
16090
  try {
16025
- await config5.hooks?.beforeDelete?.({ table: String(table), where: whereCondition });
16091
+ await activeHooks()?.beforeDelete?.({ table: String(table), where: whereCondition });
16026
16092
  } catch (err) {
16027
16093
  throw err;
16028
16094
  }
16029
16095
  const result = mutationCount(await runWithHooks(ensureDelBuilt(), "delete"));
16030
16096
  try {
16031
- await config5.hooks?.afterDelete?.({ table: String(table), where: whereCondition, result });
16097
+ await activeHooks()?.afterDelete?.({ table: String(table), where: whereCondition, result });
16032
16098
  } catch {}
16033
16099
  return result;
16034
16100
  },
@@ -16092,18 +16158,14 @@ function createQueryBuilder(state) {
16092
16158
  },
16093
16159
  async advisoryLock(key) {
16094
16160
  if (config5.dialect === "postgres") {
16095
- const s = String(key);
16096
- let hash = 7;
16097
- for (let i = 0;i < s.length; i++)
16098
- hash = hash * 31 + s.charCodeAt(i) | 0;
16099
- const k = typeof key === "number" ? key : Math.abs(hash);
16100
- const q = bunSql`SELECT pg_advisory_lock(${k})`;
16161
+ const k = advisoryLockKey(key);
16162
+ const q = _sql`SELECT pg_advisory_lock(${k})`;
16101
16163
  await runWithHooks(q, "raw");
16102
16164
  return;
16103
16165
  }
16104
16166
  if (isMysqlLike(config5.dialect)) {
16105
16167
  const lockName = `bqb:${String(key)}`;
16106
- const q = bunSql`SELECT GET_LOCK(${lockName}, -1) AS ok`;
16168
+ const q = _sql`SELECT GET_LOCK(${lockName}, -1) AS ok`;
16107
16169
  await runWithHooks(q, "raw");
16108
16170
  return;
16109
16171
  }
@@ -16111,18 +16173,29 @@ function createQueryBuilder(state) {
16111
16173
  },
16112
16174
  async tryAdvisoryLock(key) {
16113
16175
  if (config5.dialect === "postgres") {
16114
- const s = String(key);
16115
- let hash = 7;
16116
- for (let i = 0;i < s.length; i++)
16117
- hash = hash * 31 + s.charCodeAt(i) | 0;
16118
- const k = typeof key === "number" ? key : Math.abs(hash);
16119
- const q = bunSql`SELECT pg_try_advisory_lock(${k}) as ok`;
16176
+ const k = advisoryLockKey(key);
16177
+ const q = _sql`SELECT pg_try_advisory_lock(${k}) as ok`;
16120
16178
  const rows = await runWithHooks(q, "raw");
16121
16179
  return Boolean(rows?.[0]?.ok);
16122
16180
  }
16123
16181
  if (isMysqlLike(config5.dialect)) {
16124
16182
  const lockName = `bqb:${String(key)}`;
16125
- const q = bunSql`SELECT GET_LOCK(${lockName}, 0) AS ok`;
16183
+ const q = _sql`SELECT GET_LOCK(${lockName}, 0) AS ok`;
16184
+ const rows = await runWithHooks(q, "raw");
16185
+ return Number(rows?.[0]?.ok) === 1;
16186
+ }
16187
+ return false;
16188
+ },
16189
+ async advisoryUnlock(key) {
16190
+ if (config5.dialect === "postgres") {
16191
+ const k = advisoryLockKey(key);
16192
+ const q = _sql`SELECT pg_advisory_unlock(${k}) as ok`;
16193
+ const rows = await runWithHooks(q, "raw");
16194
+ return Boolean(rows?.[0]?.ok);
16195
+ }
16196
+ if (isMysqlLike(config5.dialect)) {
16197
+ const lockName = `bqb:${String(key)}`;
16198
+ const q = _sql`SELECT RELEASE_LOCK(${lockName}) AS ok`;
16126
16199
  const rows = await runWithHooks(q, "raw");
16127
16200
  return Number(rows?.[0]?.ok) === 1;
16128
16201
  }
@@ -16132,11 +16205,11 @@ function createQueryBuilder(state) {
16132
16205
  return _sql.unsafe(query, params);
16133
16206
  },
16134
16207
  file(path, params) {
16135
- return bunSql.file(path, params);
16208
+ return _sql.file(path, params);
16136
16209
  },
16137
16210
  async reserve() {
16138
16211
  const reserved = await bunSql.reserve();
16139
- const qb = createQueryBuilder({ sql: reserved, meta, schema });
16212
+ const qb = createQueryBuilder({ sql: reserved, meta, schema, hooks: state?.hooks });
16140
16213
  qb.release = () => reserved.release();
16141
16214
  return qb;
16142
16215
  },
@@ -16156,7 +16229,7 @@ function createQueryBuilder(state) {
16156
16229
  },
16157
16230
  async ping() {
16158
16231
  try {
16159
- const q = bunSql`SELECT 1`;
16232
+ const q = _sql`SELECT 1`;
16160
16233
  await runWithHooks(q, "select");
16161
16234
  return true;
16162
16235
  } catch {
@@ -16183,7 +16256,7 @@ function createQueryBuilder(state) {
16183
16256
  opts.logger?.({ type: "start", attempt: attempt2 });
16184
16257
  const start = Date.now();
16185
16258
  return await txConn[txMethod](async (tx) => {
16186
- const qb = createQueryBuilder({ sql: tx, meta, schema, inTransaction: true });
16259
+ const qb = createQueryBuilder({ sql: tx, meta, schema, hooks: state?.hooks, inTransaction: true });
16187
16260
  if (opts?.isolation && !nested) {
16188
16261
  const level = opts.isolation;
16189
16262
  const upper = level === "read committed" ? "READ COMMITTED" : level === "repeatable read" ? "REPEATABLE READ" : "SERIALIZABLE";
@@ -16246,14 +16319,14 @@ function createQueryBuilder(state) {
16246
16319
  if (!s || typeof s.savepoint !== "function")
16247
16320
  throw new Error("savepoint() is not supported by the active connection");
16248
16321
  return await s.savepoint(async (sp) => {
16249
- const qb = createQueryBuilder({ sql: sp, meta, schema, inTransaction: true });
16322
+ const qb = createQueryBuilder({ sql: sp, meta, schema, hooks: state?.hooks, inTransaction: true });
16250
16323
  return await fn(qb);
16251
16324
  });
16252
16325
  },
16253
16326
  async beginDistributed(name, fn) {
16254
16327
  const txConn = state?.sql ?? bunSql;
16255
16328
  const res = await txConn.beginDistributed(name, async (tx) => {
16256
- const qb = createQueryBuilder({ sql: tx, meta, schema });
16329
+ const qb = createQueryBuilder({ sql: tx, meta, schema, hooks: state?.hooks });
16257
16330
  return await fn(qb);
16258
16331
  });
16259
16332
  return res;
@@ -16279,24 +16352,24 @@ function createQueryBuilder(state) {
16279
16352
  const { colsSql, valuesSql, params } = buildInsertClause(rows);
16280
16353
  const tbl = quoteInsertIdent(String(table));
16281
16354
  const sqlText = isMysqlLike(config5.dialect) ? `INSERT IGNORE INTO ${tbl} (${colsSql}) VALUES ${valuesSql}` : `INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql} ON CONFLICT DO NOTHING`;
16282
- return bunSql.unsafe(sqlText, params).execute();
16355
+ return _sql.unsafe(sqlText, params).execute();
16283
16356
  },
16284
16357
  async insertGetId(table, values, idColumn = "id") {
16285
16358
  const { colsSql, valuesSql, params } = buildInsertClause([values]);
16286
16359
  const tbl = quoteInsertIdent(String(table));
16287
16360
  if (isMysqlLike(config5.dialect)) {
16288
- await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16289
- const [row2] = await bunSql.unsafe(`SELECT LAST_INSERT_ID() as id`).execute();
16361
+ await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16362
+ const [row2] = await _sql.unsafe(`SELECT LAST_INSERT_ID() as id`).execute();
16290
16363
  return row2?.id;
16291
16364
  }
16292
16365
  if (config5.dialect === "sqlite") {
16293
- const res = await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16366
+ const res = await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16294
16367
  if (res?.lastInsertRowid != null)
16295
16368
  return res.lastInsertRowid;
16296
- const [row2] = await bunSql.unsafe(`SELECT last_insert_rowid() as id`).execute();
16369
+ const [row2] = await _sql.unsafe(`SELECT last_insert_rowid() as id`).execute();
16297
16370
  return row2?.id;
16298
16371
  }
16299
- const [row] = await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql} RETURNING ${quoteInsertIdent(String(idColumn))} as id`, params).execute();
16372
+ const [row] = await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql} RETURNING ${quoteInsertIdent(String(idColumn))} as id`, params).execute();
16300
16373
  return row?.id;
16301
16374
  },
16302
16375
  async updateOrInsert(table, match, values) {
@@ -16305,18 +16378,18 @@ function createQueryBuilder(state) {
16305
16378
  let idx = 1;
16306
16379
  const whereSql = matchKeys.map((k) => `${quoteInsertIdent(k)} = ${getPlaceholder(idx++)}`).join(" AND ");
16307
16380
  const whereParams = matchKeys.map((k) => match[k]);
16308
- const existsRows = await bunSql.unsafe(`SELECT 1 FROM ${tbl} WHERE ${whereSql} LIMIT 1`, whereParams).execute();
16381
+ const existsRows = await _sql.unsafe(`SELECT 1 FROM ${tbl} WHERE ${whereSql} LIMIT 1`, whereParams).execute();
16309
16382
  if (existsRows.length) {
16310
16383
  const setKeys = Object.keys(values);
16311
16384
  let i = 1;
16312
16385
  const setSql = setKeys.map((k) => `${quoteInsertIdent(k)} = ${getPlaceholder(i++)}`).join(", ");
16313
16386
  const whereSql2 = matchKeys.map((k) => `${quoteInsertIdent(k)} = ${getPlaceholder(i++)}`).join(" AND ");
16314
16387
  const params2 = [...setKeys.map((k) => values[k]), ...matchKeys.map((k) => match[k])];
16315
- await bunSql.unsafe(`UPDATE ${tbl} SET ${setSql} WHERE ${whereSql2}`, params2).execute();
16388
+ await _sql.unsafe(`UPDATE ${tbl} SET ${setSql} WHERE ${whereSql2}`, params2).execute();
16316
16389
  return true;
16317
16390
  }
16318
16391
  const { colsSql, valuesSql, params } = buildInsertClause([{ ...match, ...values }]);
16319
- await bunSql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16392
+ await _sql.unsafe(`INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16320
16393
  return true;
16321
16394
  },
16322
16395
  async upsert(table, rows, conflictColumns, mergeColumns) {
@@ -16330,15 +16403,15 @@ function createQueryBuilder(state) {
16330
16403
  const insert = `INSERT INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`;
16331
16404
  if (isMysqlLike(config5.dialect)) {
16332
16405
  if (setCols.length === 0)
16333
- return bunSql.unsafe(`INSERT IGNORE INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16406
+ return _sql.unsafe(`INSERT IGNORE INTO ${tbl} (${colsSql}) VALUES ${valuesSql}`, params).execute();
16334
16407
  const updateList2 = setCols.map((c) => `${quoteInsertIdent(c)} = VALUES(${quoteInsertIdent(c)})`).join(", ");
16335
- return bunSql.unsafe(`${insert} ON DUPLICATE KEY UPDATE ${updateList2}`, params).execute();
16408
+ return _sql.unsafe(`${insert} ON DUPLICATE KEY UPDATE ${updateList2}`, params).execute();
16336
16409
  }
16337
16410
  const targets = targetCols.map(quoteInsertIdent).join(", ");
16338
16411
  if (setCols.length === 0)
16339
- return bunSql.unsafe(`${insert} ON CONFLICT (${targets}) DO NOTHING`, params).execute();
16412
+ return _sql.unsafe(`${insert} ON CONFLICT (${targets}) DO NOTHING`, params).execute();
16340
16413
  const updateList = setCols.map((c) => `${quoteInsertIdent(c)} = EXCLUDED.${quoteInsertIdent(c)}`).join(", ");
16341
- return bunSql.unsafe(`${insert} ON CONFLICT (${targets}) DO UPDATE SET ${updateList}`, params).execute();
16414
+ return _sql.unsafe(`${insert} ON CONFLICT (${targets}) DO UPDATE SET ${updateList}`, params).execute();
16342
16415
  },
16343
16416
  async save(table, values) {
16344
16417
  const pk = meta?.primaryKeys[String(table)] ?? "id";
@@ -16381,26 +16454,25 @@ function createQueryBuilder(state) {
16381
16454
  async rawQuery(query) {
16382
16455
  const start = Date.now();
16383
16456
  try {
16384
- config5.hooks?.onQueryStart?.({ sql: query, kind: "raw" });
16385
- const res = await bunSql.unsafe(query);
16386
- config5.hooks?.onQueryEnd?.({ sql: query, durationMs: Date.now() - start, kind: "raw" });
16457
+ activeHooks()?.onQueryStart?.({ sql: query, kind: "raw" });
16458
+ const res = await _sql.unsafe(query);
16459
+ activeHooks()?.onQueryEnd?.({ sql: query, durationMs: Date.now() - start, kind: "raw" });
16387
16460
  return res;
16388
16461
  } catch (err) {
16389
- config5.hooks?.onQueryError?.({ sql: query, error: err, durationMs: Date.now() - start, kind: "raw" });
16462
+ activeHooks()?.onQueryError?.({ sql: query, error: err, durationMs: Date.now() - start, kind: "raw" });
16390
16463
  throw err;
16391
16464
  }
16392
16465
  },
16393
16466
  async create(table, values) {
16394
16467
  const pk = meta?.primaryKeys[String(table)] ?? "id";
16395
16468
  try {
16396
- await config5.hooks?.beforeCreate?.({ table: String(table), data: values });
16469
+ await activeHooks()?.beforeCreate?.({ table: String(table), data: values });
16397
16470
  } catch (err) {
16398
16471
  throw err;
16399
16472
  }
16400
16473
  if (config5.dialect === "postgres") {
16401
- const q = bunSql`INSERT INTO ${bunSql(String(table))} ${bunSql(values)} RETURNING ${bunSql(String(pk))} as id`;
16474
+ const q = _sql`INSERT INTO ${_sql(String(table))} ${_sql(values)} RETURNING ${_sql(String(pk))} as id`;
16402
16475
  const [result] = await q.execute();
16403
- console.log("resultId", result);
16404
16476
  if (!result?.id) {
16405
16477
  console.error(`create() failed to get insert ID for table ${String(table)}`);
16406
16478
  console.error("Inserted values:", values);
@@ -16413,7 +16485,7 @@ function createQueryBuilder(state) {
16413
16485
  throw new Error(`create() failed to retrieve inserted row for table ${String(table)} with id ${result.id}`);
16414
16486
  }
16415
16487
  try {
16416
- await config5.hooks?.afterCreate?.({ table: String(table), data: values, result: row });
16488
+ await activeHooks()?.afterCreate?.({ table: String(table), data: values, result: row });
16417
16489
  } catch {}
16418
16490
  return row;
16419
16491
  } else {
@@ -16428,7 +16500,7 @@ function createQueryBuilder(state) {
16428
16500
  throw new Error(`create() failed to retrieve inserted row for table ${String(table)} with id ${id}`);
16429
16501
  }
16430
16502
  try {
16431
- await config5.hooks?.afterCreate?.({ table: String(table), data: values, result: row });
16503
+ await activeHooks()?.afterCreate?.({ table: String(table), data: values, result: row });
16432
16504
  } catch {}
16433
16505
  return row;
16434
16506
  }
@@ -16568,28 +16640,28 @@ function createQueryBuilder(state) {
16568
16640
  return await this.create(table, { ...match, ...values });
16569
16641
  },
16570
16642
  async count(table, column) {
16571
- const col = column ? bunSql(String(column)) : bunSql`*`;
16572
- const q = bunSql`SELECT COUNT(${col}) as c FROM ${bunSql(String(table))}`;
16643
+ const col = column ? _sql(String(column)) : _sql`*`;
16644
+ const q = _sql`SELECT COUNT(${col}) as c FROM ${_sql(String(table))}`;
16573
16645
  const [row] = await q.execute();
16574
16646
  return Number(row?.c ?? 0);
16575
16647
  },
16576
16648
  async sum(table, column) {
16577
- const q = bunSql`SELECT SUM(${bunSql(String(column))}) as s FROM ${bunSql(String(table))}`;
16649
+ const q = _sql`SELECT SUM(${_sql(String(column))}) as s FROM ${_sql(String(table))}`;
16578
16650
  const [row] = await q.execute();
16579
16651
  return Number(row?.s ?? 0);
16580
16652
  },
16581
16653
  async avg(table, column) {
16582
- const q = bunSql`SELECT AVG(${bunSql(String(column))}) as a FROM ${bunSql(String(table))}`;
16654
+ const q = _sql`SELECT AVG(${_sql(String(column))}) as a FROM ${_sql(String(table))}`;
16583
16655
  const [row] = await q.execute();
16584
16656
  return Number(row?.a ?? 0);
16585
16657
  },
16586
16658
  async min(table, column) {
16587
- const q = bunSql`SELECT MIN(${bunSql(String(column))}) as m FROM ${bunSql(String(table))}`;
16659
+ const q = _sql`SELECT MIN(${_sql(String(column))}) as m FROM ${_sql(String(table))}`;
16588
16660
  const [row] = await q.execute();
16589
16661
  return row?.m;
16590
16662
  },
16591
16663
  async max(table, column) {
16592
- const q = bunSql`SELECT MAX(${bunSql(String(column))}) as m FROM ${bunSql(String(table))}`;
16664
+ const q = _sql`SELECT MAX(${_sql(String(column))}) as m FROM ${_sql(String(table))}`;
16593
16665
  const [row] = await q.execute();
16594
16666
  return row?.m;
16595
16667
  },
@@ -16659,7 +16731,7 @@ function clearQueryCache() {
16659
16731
  function setQueryCacheMaxSize(size) {
16660
16732
  queryCache.setMaxSize(size);
16661
16733
  }
16662
- var SQL_PATTERNS, SAFE_WHERE_OPERATORS, warnedSqlFragmentContexts, queryCache, reorderCache, REORDER_CACHE_MAX = 500;
16734
+ var FALSE_PREDICATE = "1 = 0", TRUE_PREDICATE = "1 = 1", SQL_PATTERNS, SAFE_WHERE_OPERATORS, warnedSqlFragmentContexts, queryCache, reorderCache, REORDER_CACHE_MAX = 500;
16663
16735
  var init_client = __esm(() => {
16664
16736
  init_config();
16665
16737
  init_db();
@@ -16752,7 +16824,7 @@ var init_cache = __esm(() => {
16752
16824
  });
16753
16825
 
16754
16826
  // src/actions/console.ts
16755
- import process22 from "process";
16827
+ import process23 from "process";
16756
16828
  import { createInterface } from "readline";
16757
16829
  async function startConsole() {
16758
16830
  console.log("-- Query Builder Interactive Console");
@@ -16761,8 +16833,8 @@ async function startConsole() {
16761
16833
  console.log();
16762
16834
  const qb = createQueryBuilder();
16763
16835
  const rl = createInterface({
16764
- input: process22.stdin,
16765
- output: process22.stdout,
16836
+ input: process23.stdin,
16837
+ output: process23.stdout,
16766
16838
  prompt: "qb> "
16767
16839
  });
16768
16840
  let multilineBuffer = "";
@@ -16813,7 +16885,7 @@ Tips:
16813
16885
  if (cmd === ".exit" || cmd === ".quit") {
16814
16886
  console.log("Goodbye!");
16815
16887
  rl.close();
16816
- process22.exit(0);
16888
+ process23.exit(0);
16817
16889
  } else if (cmd === ".help") {
16818
16890
  console.log(helpText);
16819
16891
  } else if (cmd === ".clear") {
@@ -16884,7 +16956,7 @@ Tips:
16884
16956
  rl.on("close", () => {
16885
16957
  console.log(`
16886
16958
  Goodbye!`);
16887
- process22.exit(0);
16959
+ process23.exit(0);
16888
16960
  });
16889
16961
  rl.prompt();
16890
16962
  }
@@ -16896,7 +16968,7 @@ var init_console = __esm(() => {
16896
16968
  });
16897
16969
 
16898
16970
  // src/actions/data.ts
16899
- import { existsSync as existsSync11, readFileSync as readFileSync2, writeFileSync as writeFileSync8 } from "fs";
16971
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync8 } from "fs";
16900
16972
  async function exportData(tableName, options = {}) {
16901
16973
  const format = options.format || "json";
16902
16974
  const output = options.output || `${tableName}.${format}`;
@@ -16971,7 +17043,7 @@ async function exportData(tableName, options = {}) {
16971
17043
  }
16972
17044
  }
16973
17045
  async function importData(tableName, filePath, options = {}) {
16974
- if (!existsSync11(filePath)) {
17046
+ if (!existsSync2(filePath)) {
16975
17047
  console.error(`-- File not found: ${filePath}`);
16976
17048
  throw new Error(`File not found: ${filePath}`);
16977
17049
  }
@@ -18117,23 +18189,23 @@ var init_introspect_db = __esm(() => {
18117
18189
  });
18118
18190
 
18119
18191
  // src/actions/make-model.ts
18120
- import { existsSync as existsSync14, mkdirSync as mkdirSync7, writeFileSync as writeFileSync10 } from "fs";
18192
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, writeFileSync as writeFileSync10 } from "fs";
18121
18193
  import { dirname as dirname7, join as join7 } from "path";
18122
- import process23 from "process";
18194
+ import process25 from "process";
18123
18195
  function findWorkspaceRoot(startPath) {
18124
18196
  let currentPath = startPath;
18125
18197
  while (currentPath !== dirname7(currentPath)) {
18126
- if (existsSync14(join7(currentPath, "package.json"))) {
18198
+ if (existsSync11(join7(currentPath, "package.json"))) {
18127
18199
  return currentPath;
18128
18200
  }
18129
18201
  currentPath = dirname7(currentPath);
18130
18202
  }
18131
- return process23.cwd();
18203
+ return process25.cwd();
18132
18204
  }
18133
18205
  async function makeModel(name, options = {}) {
18134
- const workspaceRoot = findWorkspaceRoot(process23.cwd());
18206
+ const workspaceRoot = findWorkspaceRoot(process25.cwd());
18135
18207
  const modelsDir = options.dir || join7(workspaceRoot, "app/Models");
18136
- if (!existsSync14(modelsDir)) {
18208
+ if (!existsSync11(modelsDir)) {
18137
18209
  mkdirSync7(modelsDir, { recursive: true });
18138
18210
  console.log(`-- Created models directory: ${modelsDir}`);
18139
18211
  }
@@ -18141,7 +18213,7 @@ async function makeModel(name, options = {}) {
18141
18213
  const tableName = options.table || `${name.toLowerCase()}s`;
18142
18214
  const fileName = `${className}.ts`;
18143
18215
  const filePath = join7(modelsDir, fileName);
18144
- if (existsSync14(filePath)) {
18216
+ if (existsSync11(filePath)) {
18145
18217
  console.error(`-- Model already exists: ${filePath}`);
18146
18218
  throw new Error(`Model already exists: ${filePath}`);
18147
18219
  }
@@ -18901,17 +18973,17 @@ var init_drivers = __esm(() => {
18901
18973
  });
18902
18974
 
18903
18975
  // src/workspace.ts
18904
- import { existsSync as existsSync16 } from "fs";
18976
+ import { existsSync as existsSync14 } from "fs";
18905
18977
  import { dirname as dirname8, isAbsolute as isAbsolute3, join as join9 } from "path";
18906
- import process24 from "process";
18907
- function findWorkspaceRoot2(startPath = process24.cwd()) {
18978
+ import process26 from "process";
18979
+ function findWorkspaceRoot2(startPath = process26.cwd()) {
18908
18980
  let currentPath = startPath;
18909
18981
  while (currentPath !== dirname8(currentPath)) {
18910
- if (existsSync16(join9(currentPath, "package.json")))
18982
+ if (existsSync14(join9(currentPath, "package.json")))
18911
18983
  return currentPath;
18912
18984
  currentPath = dirname8(currentPath);
18913
18985
  }
18914
- return process24.cwd();
18986
+ return process26.cwd();
18915
18987
  }
18916
18988
  function getSqlDirectory(workspaceRoot, migrationDir = "database/migrations") {
18917
18989
  const configured = migrationDir || "database/migrations";
@@ -18930,10 +19002,10 @@ __export(exports_migrate, {
18930
19002
  copyModelsToGenerated: () => copyModelsToGenerated,
18931
19003
  clearGeneratedDirectory: () => clearGeneratedDirectory
18932
19004
  });
18933
- import { existsSync as existsSync17, mkdirSync as mkdirSync8, mkdtempSync, readdirSync as readdirSync6, readFileSync as readFileSync3, rmSync, unlinkSync, writeFileSync as writeFileSync11 } from "fs";
19005
+ import { existsSync as existsSync16, mkdirSync as mkdirSync8, mkdtempSync, readdirSync as readdirSync6, readFileSync as readFileSync3, rmSync, unlinkSync, writeFileSync as writeFileSync11 } from "fs";
18934
19006
  import { tmpdir } from "os";
18935
19007
  import { join as join10 } from "path";
18936
- import process25 from "process";
19008
+ import process27 from "process";
18937
19009
  async function settleAppliedFiles(qb, dialect, files) {
18938
19010
  if (files.length === 0)
18939
19011
  return;
@@ -18971,7 +19043,7 @@ function getSnapshotPath(workspaceRoot, dialect) {
18971
19043
  }
18972
19044
  function loadPlanSnapshot(workspaceRoot, dialect) {
18973
19045
  const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
18974
- if (!existsSync17(snapshotPath)) {
19046
+ if (!existsSync16(snapshotPath)) {
18975
19047
  return;
18976
19048
  }
18977
19049
  try {
@@ -18994,7 +19066,7 @@ function savePlanSnapshot(workspaceRoot, dialect, plan) {
18994
19066
  const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
18995
19067
  const snapshotDir = getSnapshotDir(workspaceRoot);
18996
19068
  const hash = hashMigrationPlan(plan);
18997
- if (existsSync17(snapshotPath)) {
19069
+ if (existsSync16(snapshotPath)) {
18998
19070
  try {
18999
19071
  const current = JSON.parse(readFileSync3(snapshotPath, "utf8"));
19000
19072
  if (current?.hash === hash && current?.dialect === dialect && current?.plan) {
@@ -19003,7 +19075,7 @@ function savePlanSnapshot(workspaceRoot, dialect, plan) {
19003
19075
  }
19004
19076
  } catch {}
19005
19077
  }
19006
- if (!existsSync17(snapshotDir)) {
19078
+ if (!existsSync16(snapshotDir)) {
19007
19079
  mkdirSync8(snapshotDir, { recursive: true });
19008
19080
  info(`-- Created snapshot directory: ${snapshotDir}`);
19009
19081
  }
@@ -19025,7 +19097,7 @@ function getWorkspaceRoot() {
19025
19097
  }
19026
19098
  function ensureSqlDirectory(workspaceRoot) {
19027
19099
  const sqlDir = getSqlDirectory(workspaceRoot, config5.migrationDir);
19028
- if (!existsSync17(sqlDir)) {
19100
+ if (!existsSync16(sqlDir)) {
19029
19101
  mkdirSync8(sqlDir, { recursive: true });
19030
19102
  info(`-- Created SQL directory: ${sqlDir}`);
19031
19103
  }
@@ -19034,7 +19106,7 @@ function ensureSqlDirectory(workspaceRoot) {
19034
19106
  async function generateMigration(dir, opts = {}) {
19035
19107
  await getConfig();
19036
19108
  if (!dir) {
19037
- dir = join10(process25.cwd(), "app/Models");
19109
+ dir = join10(process27.cwd(), "app/Models");
19038
19110
  }
19039
19111
  const dialect = opts.dialect || config5.dialect || "postgres";
19040
19112
  const workspaceRoot = getWorkspaceRoot();
@@ -19049,7 +19121,7 @@ async function generateMigration(dir, opts = {}) {
19049
19121
  } else {
19050
19122
  const defaultStatePath = join10(dir, `.qb-migrations.${dialect}.json`);
19051
19123
  const statePath = String(opts.state || defaultStatePath);
19052
- if (existsSync17(statePath)) {
19124
+ if (existsSync16(statePath)) {
19053
19125
  try {
19054
19126
  const raw2 = readFileSync3(statePath, "utf8");
19055
19127
  const parsed = JSON.parse(raw2);
@@ -19114,6 +19186,33 @@ async function generateMigration(dir, opts = {}) {
19114
19186
  savePlanSnapshot(workspaceRoot, dialect, plan);
19115
19187
  return { sql, sqlStatements, hasChanges, plan, operations };
19116
19188
  }
19189
+ function supportsTransactionalDdl(dialect) {
19190
+ return dialect === "postgres" || dialect === "sqlite";
19191
+ }
19192
+ async function withMigrationLock(dialect, fn) {
19193
+ if (dialect === "sqlite")
19194
+ return await fn();
19195
+ const qb = createQueryBuilder();
19196
+ let reserved;
19197
+ try {
19198
+ reserved = await qb.reserve();
19199
+ } catch {
19200
+ return await fn();
19201
+ }
19202
+ let held = false;
19203
+ try {
19204
+ await reserved.advisoryLock(MIGRATION_LOCK_KEY);
19205
+ held = true;
19206
+ return await fn();
19207
+ } finally {
19208
+ try {
19209
+ if (held)
19210
+ await reserved.advisoryUnlock(MIGRATION_LOCK_KEY);
19211
+ } finally {
19212
+ reserved.release?.();
19213
+ }
19214
+ }
19215
+ }
19117
19216
  async function executeMigration(dir) {
19118
19217
  await getConfig();
19119
19218
  const workspaceRoot = getWorkspaceRoot();
@@ -19128,32 +19227,47 @@ async function executeMigration(dir) {
19128
19227
  info(`-- Found ${scriptFiles.length} script files to execute`);
19129
19228
  try {
19130
19229
  const qb = createQueryBuilder();
19131
- await createMigrationsTable(qb, dialect);
19132
- const executedMigrations = await getExecutedMigrations(qb, dialect);
19133
- const pending = scriptFiles.filter((file2) => !executedMigrations.includes(file2));
19134
- if (pending.length === 0) {
19135
- info("-- No pending migrations to execute");
19136
- return true;
19137
- }
19138
- info(`-- Executing ${pending.length} migration${pending.length === 1 ? "" : "s"}`);
19139
- for (const file2 of pending) {
19140
- const filePath = join10(sqlDir, file2);
19141
- info(`-- Executing: ${file2}`);
19142
- try {
19143
- await qb.file(filePath);
19144
- await recordMigration(qb, file2, dialect);
19145
- info(`-- \u2713 Migration ${file2} executed and recorded`);
19146
- } catch (err) {
19147
- if (isGeneratedMigration(sqlDir, file2) && isAlreadyAppliedError(err)) {
19148
- await recordMigration(qb, file2, dialect);
19149
- info(`-- \u2713 Migration ${file2} was already applied; recorded it (${err instanceof Error ? err.message : String(err)})`);
19150
- continue;
19230
+ return await withMigrationLock(dialect, async () => {
19231
+ await createMigrationsTable(qb, dialect);
19232
+ const executedMigrations = await getExecutedMigrations(qb, dialect);
19233
+ const pending = scriptFiles.filter((file2) => !executedMigrations.includes(file2));
19234
+ if (pending.length === 0) {
19235
+ info("-- No pending migrations to execute");
19236
+ return true;
19237
+ }
19238
+ info(`-- Executing ${pending.length} migration${pending.length === 1 ? "" : "s"}`);
19239
+ for (const file2 of pending) {
19240
+ const filePath = join10(sqlDir, file2);
19241
+ info(`-- Executing: ${file2}`);
19242
+ try {
19243
+ const wrappable = supportsTransactionalDdl(dialect) && !NON_TRANSACTIONAL_SQL.test(readFileSync3(filePath, "utf-8"));
19244
+ if (wrappable) {
19245
+ await qb.transaction(async (tx) => {
19246
+ await tx.file(filePath);
19247
+ await recordMigration(tx, file2, dialect);
19248
+ });
19249
+ } else {
19250
+ await qb.file(filePath);
19251
+ await recordMigration(qb, file2, dialect);
19252
+ if (!supportsTransactionalDdl(dialect))
19253
+ info(`-- (${dialect} commits DDL implicitly, so ${file2} was not applied atomically)`);
19254
+ else
19255
+ info(`-- (${file2} contains a statement that cannot run in a transaction, so it was not applied atomically)`);
19256
+ }
19257
+ info(`-- \u2713 Migration ${file2} executed and recorded`);
19258
+ } catch (err) {
19259
+ if (isGeneratedMigration(sqlDir, file2) && isAlreadyAppliedError(err)) {
19260
+ await recordMigration(qb, file2, dialect);
19261
+ info(`-- \u2713 Migration ${file2} was already applied; recorded it (${err instanceof Error ? err.message : String(err)})`);
19262
+ continue;
19263
+ }
19264
+ console.error(`-- \u2717 Migration ${file2} failed:`, err);
19265
+ throw err;
19151
19266
  }
19152
- console.error(`-- \u2717 Migration ${file2} failed:`, err);
19153
- throw err;
19154
19267
  }
19155
- }
19156
- info("-- All migrations executed successfully");
19268
+ info("-- All migrations executed successfully");
19269
+ return true;
19270
+ });
19157
19271
  } catch (err) {
19158
19272
  console.error("-- Migration execution failed:", err);
19159
19273
  throw err;
@@ -19163,7 +19277,7 @@ async function executeMigration(dir) {
19163
19277
  async function resetDatabase(dir, opts = {}) {
19164
19278
  await getConfig();
19165
19279
  if (!dir) {
19166
- dir = join10(process25.cwd(), "app/Models");
19280
+ dir = join10(process27.cwd(), "app/Models");
19167
19281
  }
19168
19282
  const dialect = opts.dialect || config5.dialect || "postgres";
19169
19283
  const driver = getDialectDriver(dialect);
@@ -19260,27 +19374,27 @@ async function resetDatabase(dir, opts = {}) {
19260
19374
  }
19261
19375
  async function deleteMigrationFiles(dir, workspaceRoot, opts = {}) {
19262
19376
  if (!dir) {
19263
- dir = join10(process25.cwd(), "app/Models");
19377
+ dir = join10(process27.cwd(), "app/Models");
19264
19378
  }
19265
19379
  if (!workspaceRoot) {
19266
19380
  workspaceRoot = getWorkspaceRoot();
19267
19381
  }
19268
19382
  const dialect = String(opts.dialect || config5.dialect || "postgres");
19269
19383
  const snapshotPath = getSnapshotPath(workspaceRoot, dialect);
19270
- if (existsSync17(snapshotPath)) {
19384
+ if (existsSync16(snapshotPath)) {
19271
19385
  unlinkSync(snapshotPath);
19272
19386
  info(`-- Removed model snapshot file: ${snapshotPath}`);
19273
19387
  }
19274
19388
  const defaultStatePath = join10(dir, `.qb-migrations.${dialect}.json`);
19275
19389
  const statePath = String(opts.state || defaultStatePath);
19276
- if (existsSync17(statePath)) {
19390
+ if (existsSync16(statePath)) {
19277
19391
  unlinkSync(statePath);
19278
19392
  info(`-- Removed legacy migration state file: ${statePath}`);
19279
19393
  }
19280
19394
  removeGeneratedMigrationFiles(getSqlDirectory(workspaceRoot, config5.migrationDir));
19281
19395
  }
19282
19396
  function removeGeneratedMigrationFiles(sqlDir) {
19283
- if (!existsSync17(sqlDir))
19397
+ if (!existsSync16(sqlDir))
19284
19398
  return;
19285
19399
  let removed = 0;
19286
19400
  const kept = [];
@@ -19303,7 +19417,7 @@ async function clearGeneratedDirectory(workspaceRoot) {
19303
19417
  workspaceRoot = getWorkspaceRoot();
19304
19418
  }
19305
19419
  const generatedDir = join10(workspaceRoot, "generated");
19306
- if (existsSync17(generatedDir)) {
19420
+ if (existsSync16(generatedDir)) {
19307
19421
  try {
19308
19422
  rmSync(generatedDir, { recursive: true, force: true });
19309
19423
  info("-- Cleared generated directory");
@@ -19344,6 +19458,7 @@ async function recordMigration(qb, migrationFile, dialect) {
19344
19458
  throw err;
19345
19459
  }
19346
19460
  }
19461
+ var MIGRATION_LOCK_KEY = "bun-query-builder:migrate", NON_TRANSACTIONAL_SQL;
19347
19462
  var init_migrate = __esm(() => {
19348
19463
  init_config();
19349
19464
  init_db();
@@ -19351,6 +19466,7 @@ var init_migrate = __esm(() => {
19351
19466
  init_src2();
19352
19467
  init_introspect_db();
19353
19468
  init_workspace();
19469
+ NON_TRANSACTIONAL_SQL = /\bCONCURRENTLY\b|^\s*VACUUM\b/im;
19354
19470
  });
19355
19471
 
19356
19472
  // src/actions/migrate-generate.ts
@@ -19362,7 +19478,7 @@ var init_migrate_generate = __esm(() => {
19362
19478
  });
19363
19479
 
19364
19480
  // src/actions/migrate-rollback.ts
19365
- import { existsSync as existsSync18, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
19481
+ import { existsSync as existsSync17, readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
19366
19482
  import { join as join11 } from "path";
19367
19483
  function splitSqlStatements2(sql) {
19368
19484
  const out = [];
@@ -19477,7 +19593,7 @@ async function migrateRollback(options = {}) {
19477
19593
  for (const migration of migrationsToRollback) {
19478
19594
  try {
19479
19595
  const filePath = join11(sqlDir, migration.migration);
19480
- if (reverseSchema && existsSync18(filePath)) {
19596
+ if (reverseSchema && existsSync17(filePath)) {
19481
19597
  const forwardSql = readFileSync4(filePath, "utf8");
19482
19598
  const { down, skipped } = deriveDownStatements(forwardSql);
19483
19599
  for (const stmt of down) {
@@ -19491,7 +19607,7 @@ async function migrateRollback(options = {}) {
19491
19607
  const deleteSql = `DELETE FROM migrations WHERE migration = ${getPlaceholder(1)}`;
19492
19608
  await qb.unsafe(deleteSql, [migration.migration]);
19493
19609
  console.log(`-- \u2713 Removed migration record: ${migration.migration}`);
19494
- if (options.deleteFiles && existsSync18(filePath)) {
19610
+ if (options.deleteFiles && existsSync17(filePath)) {
19495
19611
  unlinkSync2(filePath);
19496
19612
  console.log(`-- \uD83D\uDDD1\uFE0F Deleted migration file: ${migration.migration}`);
19497
19613
  }
@@ -19518,7 +19634,7 @@ var init_migrate_rollback = __esm(() => {
19518
19634
  });
19519
19635
 
19520
19636
  // src/actions/migrate-status.ts
19521
- import { existsSync as existsSync19, readdirSync as readdirSync8 } from "fs";
19637
+ import { existsSync as existsSync18, readdirSync as readdirSync8 } from "fs";
19522
19638
  async function migrateStatus() {
19523
19639
  const dialect = config5.dialect || "postgres";
19524
19640
  const driver = getDialectDriver(dialect);
@@ -19527,7 +19643,7 @@ async function migrateStatus() {
19527
19643
  console.log(`-- Dialect: ${dialect}`);
19528
19644
  console.log(`-- SQL directory: ${sqlDir}`);
19529
19645
  console.log();
19530
- if (!existsSync19(sqlDir)) {
19646
+ if (!existsSync18(sqlDir)) {
19531
19647
  console.log("-- No SQL directory found. No migrations have been created yet.");
19532
19648
  return [];
19533
19649
  }
@@ -19592,9 +19708,9 @@ var init_migrate_status = __esm(() => {
19592
19708
  // src/actions/model-show.ts
19593
19709
  import { readdirSync as readdirSync9 } from "fs";
19594
19710
  import { extname as extname2, join as join12 } from "path";
19595
- import process26 from "process";
19711
+ import process28 from "process";
19596
19712
  async function modelShow(modelName, options = {}) {
19597
- const dir = options.dir || join12(process26.cwd(), "app/Models");
19713
+ const dir = options.dir || join12(process28.cwd(), "app/Models");
19598
19714
  try {
19599
19715
  const files = readdirSync9(dir);
19600
19716
  const modelFile = files.find((f) => {
@@ -19808,9 +19924,9 @@ var init_query_explain_all = __esm(() => {
19808
19924
  // src/actions/relation-diagram.ts
19809
19925
  import { writeFileSync as writeFileSync12 } from "fs";
19810
19926
  import { join as join14 } from "path";
19811
- import process27 from "process";
19927
+ import process29 from "process";
19812
19928
  async function relationDiagram(options = {}) {
19813
- const dir = options.dir || join14(process27.cwd(), "app/Models");
19929
+ const dir = options.dir || join14(process29.cwd(), "app/Models");
19814
19930
  const format = options.format || "mermaid";
19815
19931
  try {
19816
19932
  const models = await loadModels({ modelsDir: dir });
@@ -19930,21 +20046,21 @@ var init_relation_diagram = __esm(() => {
19930
20046
  });
19931
20047
 
19932
20048
  // src/actions/seed.ts
19933
- import { existsSync as existsSync20, mkdirSync as mkdirSync9, readdirSync as readdirSync11, writeFileSync as writeFileSync13 } from "fs";
20049
+ import { existsSync as existsSync19, mkdirSync as mkdirSync9, readdirSync as readdirSync11, writeFileSync as writeFileSync13 } from "fs";
19934
20050
  import { dirname as dirname10, join as join15 } from "path";
19935
- import process28 from "process";
20051
+ import process30 from "process";
19936
20052
  function findWorkspaceRoot3(startPath) {
19937
20053
  let currentPath = startPath;
19938
20054
  while (currentPath !== dirname10(currentPath)) {
19939
- if (existsSync20(join15(currentPath, "package.json"))) {
20055
+ if (existsSync19(join15(currentPath, "package.json"))) {
19940
20056
  return currentPath;
19941
20057
  }
19942
20058
  currentPath = dirname10(currentPath);
19943
20059
  }
19944
- return process28.cwd();
20060
+ return process30.cwd();
19945
20061
  }
19946
20062
  async function loadSeeders(seedersDir) {
19947
- if (!existsSync20(seedersDir)) {
20063
+ if (!existsSync19(seedersDir)) {
19948
20064
  console.log(`-- Seeders directory not found: ${seedersDir}`);
19949
20065
  return [];
19950
20066
  }
@@ -19974,7 +20090,7 @@ async function loadSeeders(seedersDir) {
19974
20090
  return seeders;
19975
20091
  }
19976
20092
  async function runSeeders(config6 = {}) {
19977
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20093
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
19978
20094
  const seedersDir = config6.seedersDir || join15(workspaceRoot, "database/seeders");
19979
20095
  const verbose = config6.verbose ?? true;
19980
20096
  if (verbose) {
@@ -20009,7 +20125,7 @@ async function runSeeders(config6 = {}) {
20009
20125
  }
20010
20126
  }
20011
20127
  async function runSeeder(className, options = {}) {
20012
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20128
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
20013
20129
  const seedersDir = join15(workspaceRoot, "database/seeders");
20014
20130
  const verbose = options.verbose ?? true;
20015
20131
  if (verbose) {
@@ -20034,9 +20150,9 @@ async function runSeeder(className, options = {}) {
20034
20150
  }
20035
20151
  }
20036
20152
  async function makeSeeder(name) {
20037
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20153
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
20038
20154
  const seedersDir = join15(workspaceRoot, "database/seeders");
20039
- if (!existsSync20(seedersDir)) {
20155
+ if (!existsSync19(seedersDir)) {
20040
20156
  mkdirSync9(seedersDir, { recursive: true });
20041
20157
  console.log(`-- Created seeders directory: ${seedersDir}`);
20042
20158
  }
@@ -20044,7 +20160,7 @@ async function makeSeeder(name) {
20044
20160
  const className = `${baseName}Seeder`;
20045
20161
  const fileName = `${className}.ts`;
20046
20162
  const filePath = join15(seedersDir, fileName);
20047
- if (existsSync20(filePath)) {
20163
+ if (existsSync19(filePath)) {
20048
20164
  console.error(`-- Seeder already exists: ${filePath}`);
20049
20165
  throw new Error(`Seeder already exists: ${filePath}`);
20050
20166
  }
@@ -20098,7 +20214,7 @@ export default class ${className} extends Seeder {
20098
20214
  console.log(`-- \u2713 Created seeder: ${filePath}`);
20099
20215
  }
20100
20216
  async function freshDatabase(options = {}) {
20101
- const workspaceRoot = findWorkspaceRoot3(process28.cwd());
20217
+ const workspaceRoot = findWorkspaceRoot3(process30.cwd());
20102
20218
  const modelsDir = options.modelsDir || join15(workspaceRoot, "app/Models");
20103
20219
  const seedersDir = options.seedersDir || join15(workspaceRoot, "database/seeders");
20104
20220
  const verbose = options.verbose ?? true;
@@ -20158,22 +20274,22 @@ var init_unsafe = __esm(() => {
20158
20274
  });
20159
20275
 
20160
20276
  // src/actions/validate.ts
20161
- import { existsSync as existsSync21 } from "fs";
20277
+ import { existsSync as existsSync20 } from "fs";
20162
20278
  import { dirname as dirname11, join as join16 } from "path";
20163
- import process29 from "process";
20279
+ import process31 from "process";
20164
20280
  function findWorkspaceRoot4(startPath) {
20165
20281
  let currentPath = startPath;
20166
20282
  while (currentPath !== dirname11(currentPath)) {
20167
- if (existsSync21(join16(currentPath, "package.json"))) {
20283
+ if (existsSync20(join16(currentPath, "package.json"))) {
20168
20284
  return currentPath;
20169
20285
  }
20170
20286
  currentPath = dirname11(currentPath);
20171
20287
  }
20172
- return process29.cwd();
20288
+ return process31.cwd();
20173
20289
  }
20174
20290
  async function validateSchema(dir) {
20175
20291
  if (!dir) {
20176
- dir = join16(findWorkspaceRoot4(process29.cwd()), "app/Models");
20292
+ dir = join16(findWorkspaceRoot4(process31.cwd()), "app/Models");
20177
20293
  }
20178
20294
  const dialect = config5.dialect || "postgres";
20179
20295
  console.log("-- Validating Schema");
@@ -25432,6 +25548,28 @@ function toTableName2(modelName) {
25432
25548
  tableNameCache.set(modelName, cached);
25433
25549
  return cached;
25434
25550
  }
25551
+ function relationNamesFor(definition, kind) {
25552
+ const rel = definition[kind];
25553
+ if (!rel)
25554
+ return [];
25555
+ if (Array.isArray(rel))
25556
+ return rel.map((item) => typeof item === "string" ? item : String(item?.model ?? "")).filter(Boolean);
25557
+ if (typeof rel === "object")
25558
+ return Object.keys(rel);
25559
+ if (typeof rel === "string")
25560
+ return [rel];
25561
+ return [];
25562
+ }
25563
+ function unresolvedRelationMessage(definition, relationName) {
25564
+ const model = definition.name ?? definition.table ?? "model";
25565
+ const declaredUnder = DECLARABLE_RELATION_KINDS.filter((kind) => relationNamesFor(definition, kind).some((n2) => n2.toLowerCase() === relationName.toLowerCase()));
25566
+ const unsupported = declaredUnder.filter((k2) => !RESOLVABLE_RELATION_KINDS.includes(k2));
25567
+ if (unsupported.length > 0) {
25568
+ 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.`;
25569
+ }
25570
+ const available = RESOLVABLE_RELATION_KINDS.flatMap((kind) => relationNamesFor(definition, kind));
25571
+ 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.`;
25572
+ }
25435
25573
  function resolveRelation(definition, relationName) {
25436
25574
  const parentName = definition.name;
25437
25575
  const parentTable = definition.table;
@@ -26166,7 +26304,7 @@ class ModelQueryBuilder {
26166
26304
  relationCache.set(cacheKey, rel);
26167
26305
  }
26168
26306
  if (!rel)
26169
- return;
26307
+ throw new Error(unresolvedRelationMessage(this._definition, relationName));
26170
26308
  if (rel.type === "hasMany" || rel.type === "hasOne") {
26171
26309
  const parentIds = distinctParentIds(instances, pk);
26172
26310
  if (parentIds.length === 0)
@@ -26758,7 +26896,7 @@ async function seedModel(definition, count, faker) {
26758
26896
  await exec.run(`INSERT INTO ${definition.table} (${columns.join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`, Object.values(data));
26759
26897
  }
26760
26898
  }
26761
- 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;
26899
+ 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;
26762
26900
  var init_orm = __esm(() => {
26763
26901
  init_config();
26764
26902
  init_db();
@@ -26769,6 +26907,17 @@ var init_orm = __esm(() => {
26769
26907
  snakeCaseCache = new Map;
26770
26908
  tableNameCache = new Map;
26771
26909
  relationCache = new Map;
26910
+ RESOLVABLE_RELATION_KINDS = ["hasMany", "hasOne", "belongsTo", "belongsToMany"];
26911
+ DECLARABLE_RELATION_KINDS = [
26912
+ ...RESOLVABLE_RELATION_KINDS,
26913
+ "hasOneThrough",
26914
+ "hasManyThrough",
26915
+ "morphOne",
26916
+ "morphMany",
26917
+ "morphTo",
26918
+ "morphToMany",
26919
+ "morphedByMany"
26920
+ ];
26772
26921
  });
26773
26922
 
26774
26923
  // src/model.ts
@@ -28218,7 +28367,7 @@ var init_factory = () => {};
28218
28367
  // src/loader.ts
28219
28368
  import { readdirSync as readdirSync12 } from "fs";
28220
28369
  import { basename, extname as extname4, isAbsolute as isAbsolute5, join as join17 } from "path";
28221
- import process30 from "process";
28370
+ import process33 from "process";
28222
28371
  function isModelFile(name) {
28223
28372
  const ext = extname4(name);
28224
28373
  if (!MODEL_EXTENSIONS.has(ext))
@@ -28249,7 +28398,7 @@ function collectModelFiles(dir) {
28249
28398
  return files;
28250
28399
  }
28251
28400
  async function loadModels(options) {
28252
- const cwd = options.cwd ?? process30.cwd();
28401
+ const cwd = options.cwd ?? process33.cwd();
28253
28402
  const dir = isAbsolute5(options.modelsDir) ? options.modelsDir : join17(cwd, options.modelsDir);
28254
28403
  const result = {};
28255
28404
  for (const full of collectModelFiles(dir)) {
@@ -28356,9 +28505,9 @@ function buildSchemaMeta(models) {
28356
28505
  var init_meta = () => {};
28357
28506
 
28358
28507
  // src/migrations.ts
28359
- import { existsSync as existsSync23, mkdirSync as mkdirSync10, readdirSync as readdirSync13, readFileSync as readFileSync6, writeFileSync as writeFileSync14 } from "fs";
28508
+ import { existsSync as existsSync21, mkdirSync as mkdirSync10, readdirSync as readdirSync13, readFileSync as readFileSync6, writeFileSync as writeFileSync14 } from "fs";
28360
28509
  import { dirname as dirname12, join as join18 } from "path";
28361
- import process31 from "process";
28510
+ import process35 from "process";
28362
28511
  function info2(message) {
28363
28512
  if (config5.verbose)
28364
28513
  console.log(message);
@@ -28375,17 +28524,17 @@ function lastCreatedMigrationFiles() {
28375
28524
  function findWorkspaceRoot5(startPath) {
28376
28525
  let currentPath = startPath;
28377
28526
  while (currentPath !== dirname12(currentPath)) {
28378
- if (existsSync23(join18(currentPath, "package.json"))) {
28527
+ if (existsSync21(join18(currentPath, "package.json"))) {
28379
28528
  return currentPath;
28380
28529
  }
28381
28530
  currentPath = dirname12(currentPath);
28382
28531
  }
28383
- return process31.cwd();
28532
+ return process35.cwd();
28384
28533
  }
28385
28534
  function ensureSqlDirectory2() {
28386
- const workspaceRoot = findWorkspaceRoot5(process31.cwd());
28535
+ const workspaceRoot = findWorkspaceRoot5(process35.cwd());
28387
28536
  const sqlDir = getSqlDirectory(workspaceRoot, config5.migrationDir);
28388
- if (!existsSync23(sqlDir)) {
28537
+ if (!existsSync21(sqlDir)) {
28389
28538
  mkdirSync10(sqlDir, { recursive: true });
28390
28539
  info2(`-- Created SQL directory: ${sqlDir}`);
28391
28540
  }
@@ -28430,7 +28579,7 @@ function createMigrationFile(statement, fileName) {
28430
28579
  let fullFileName = `${sequence}-${fileName}.sql`;
28431
28580
  if (!useDeterministicNames) {
28432
28581
  let next = Number(sequence);
28433
- while (existsSync23(join18(sqlDir, fullFileName))) {
28582
+ while (existsSync21(join18(sqlDir, fullFileName))) {
28434
28583
  next += 1;
28435
28584
  sequence = String(next);
28436
28585
  fullFileName = `${sequence}-${fileName}.sql`;
@@ -29652,14 +29801,14 @@ var init_src2 = __esm(() => {
29652
29801
  });
29653
29802
 
29654
29803
  // ../../node_modules/@stacksjs/clapp/dist/index.js
29655
- import { existsSync as existsSync25 } from "fs";
29804
+ import { existsSync as existsSync23 } from "fs";
29656
29805
  import fs from "fs/promises";
29657
29806
  import os from "os";
29658
29807
  import path from "path";
29659
- import process33 from "process";
29808
+ import process36 from "process";
29660
29809
  import { EventEmitter } from "events";
29661
29810
  import process52 from "process";
29662
- import process210 from "process";
29811
+ import process24 from "process";
29663
29812
  import process34 from "process";
29664
29813
  import process42 from "process";
29665
29814
  import process72 from "process";
@@ -29680,10 +29829,10 @@ class Telemetry {
29680
29829
  this.configPath = path.join(configDir, "telemetry.json");
29681
29830
  }
29682
29831
  async isEnabled() {
29683
- if (process33.env.DO_NOT_TRACK === "1" || process33.env.DO_NOT_TRACK === "true") {
29832
+ if (process36.env.DO_NOT_TRACK === "1" || process36.env.DO_NOT_TRACK === "true") {
29684
29833
  return false;
29685
29834
  }
29686
- if (process33.env.NO_TELEMETRY === "1" || process33.env.NO_TELEMETRY === "true") {
29835
+ if (process36.env.NO_TELEMETRY === "1" || process36.env.NO_TELEMETRY === "true") {
29687
29836
  return false;
29688
29837
  }
29689
29838
  const config6 = await this.loadConfig();
@@ -29712,7 +29861,7 @@ class Telemetry {
29712
29861
  ...data,
29713
29862
  timestamp: Date.now(),
29714
29863
  platform: os.platform(),
29715
- nodeVersion: process33.version
29864
+ nodeVersion: process36.version
29716
29865
  };
29717
29866
  this.events.push(telemetryEvent);
29718
29867
  if (this.events.length >= 10) {
@@ -29768,7 +29917,7 @@ class Telemetry {
29768
29917
  const config6 = await this.loadConfig();
29769
29918
  return {
29770
29919
  enabled: config6.enabled,
29771
- doNotTrack: process33.env.DO_NOT_TRACK === "1" || process33.env.DO_NOT_TRACK === "true",
29920
+ doNotTrack: process36.env.DO_NOT_TRACK === "1" || process36.env.DO_NOT_TRACK === "true",
29772
29921
  eventsQueued: this.events.length,
29773
29922
  lastSent: config6.lastSent
29774
29923
  };
@@ -29778,7 +29927,7 @@ class Telemetry {
29778
29927
  return this.config;
29779
29928
  }
29780
29929
  try {
29781
- if (existsSync25(this.configPath)) {
29930
+ if (existsSync23(this.configPath)) {
29782
29931
  const data = await fs.readFile(this.configPath, "utf-8");
29783
29932
  this.config = JSON.parse(data);
29784
29933
  return this.config;
@@ -29804,90 +29953,6 @@ class Telemetry {
29804
29953
  }
29805
29954
  }
29806
29955
  var telemetry = new Telemetry;
29807
- function parseArgv(argv, opts = {}) {
29808
- const result = { _: [] };
29809
- const alias = opts.alias || {};
29810
- const booleans = new Set(opts.boolean || []);
29811
- const aliasOf = {};
29812
- for (const key of Object.keys(alias)) {
29813
- for (const a2 of alias[key]) {
29814
- aliasOf[a2] = key;
29815
- }
29816
- }
29817
- for (const b2 of booleans) {
29818
- if (alias[b2]) {
29819
- for (const a2 of alias[b2])
29820
- booleans.add(a2);
29821
- }
29822
- }
29823
- function setKey(key, value) {
29824
- const canonical = aliasOf[key] || key;
29825
- result[canonical] = value;
29826
- if (alias[canonical]) {
29827
- for (const a2 of alias[canonical])
29828
- result[a2] = value;
29829
- }
29830
- if (aliasOf[key] && alias[aliasOf[key]]) {
29831
- for (const a2 of alias[aliasOf[key]])
29832
- result[a2] = value;
29833
- }
29834
- result[key] = value;
29835
- }
29836
- for (let i2 = 0;i2 < argv.length; i2++) {
29837
- const arg = argv[i2];
29838
- if (arg === "--") {
29839
- result._.push(...argv.slice(i2 + 1));
29840
- break;
29841
- }
29842
- if (arg.startsWith("--")) {
29843
- const eqIdx = arg.indexOf("=");
29844
- if (eqIdx !== -1) {
29845
- const key = arg.slice(2, eqIdx);
29846
- const value = arg.slice(eqIdx + 1);
29847
- setKey(key, value);
29848
- } else {
29849
- const key = arg.slice(2);
29850
- if (key.startsWith("no-")) {
29851
- const actualKey = key.slice(3);
29852
- setKey(actualKey, false);
29853
- continue;
29854
- }
29855
- const canonical = aliasOf[key] || key;
29856
- if (booleans.has(canonical) || booleans.has(key)) {
29857
- setKey(key, true);
29858
- } else {
29859
- const next = argv[i2 + 1];
29860
- if (next !== undefined && !next.startsWith("-")) {
29861
- setKey(key, next);
29862
- i2++;
29863
- } else {
29864
- setKey(key, true);
29865
- }
29866
- }
29867
- }
29868
- } else if (arg.startsWith("-") && arg.length > 1) {
29869
- const chars = arg.slice(1);
29870
- for (let j = 0;j < chars.length; j++) {
29871
- const ch = chars[j];
29872
- const canonical = aliasOf[ch] || ch;
29873
- if (j === chars.length - 1 && !booleans.has(canonical) && !booleans.has(ch)) {
29874
- const next = argv[i2 + 1];
29875
- if (next !== undefined && !next.startsWith("-")) {
29876
- setKey(ch, next);
29877
- i2++;
29878
- } else {
29879
- setKey(ch, true);
29880
- }
29881
- } else {
29882
- setKey(ch, true);
29883
- }
29884
- }
29885
- } else {
29886
- result._.push(arg);
29887
- }
29888
- }
29889
- return result;
29890
- }
29891
29956
  function removeBrackets(v2) {
29892
29957
  return v2.replace(/[<[].+/, "").trim();
29893
29958
  }
@@ -29984,9 +30049,13 @@ function camelcaseOptionName(name) {
29984
30049
  class ClappError extends Error {
29985
30050
  exitCode = 2;
29986
30051
  isUsageError = true;
29987
- constructor(message) {
30052
+ usage;
30053
+ constructor(message, usage) {
29988
30054
  super(message);
29989
30055
  this.name = this.constructor.name;
30056
+ if (usage !== undefined) {
30057
+ this.usage = usage;
30058
+ }
29990
30059
  if (typeof Error.captureStackTrace === "function") {
29991
30060
  Error.captureStackTrace(this, this.constructor);
29992
30061
  } else {
@@ -30003,10 +30072,16 @@ ${this.stack}`;
30003
30072
  return this.message;
30004
30073
  }
30005
30074
  }
30075
+ function isClappError(err) {
30076
+ if (err instanceof ClappError) {
30077
+ return true;
30078
+ }
30079
+ return !!err && typeof err === "object" && err.name === "ClappError" && typeof err.message === "string";
30080
+ }
30006
30081
  function isUnicodeSupported() {
30007
- const { env } = process210;
30082
+ const { env } = process24;
30008
30083
  const { TERM, TERM_PROGRAM } = env;
30009
- if (process210.platform !== "win32") {
30084
+ if (process24.platform !== "win32") {
30010
30085
  return TERM !== "linux";
30011
30086
  }
30012
30087
  return Boolean(env.WT_SESSION) || Boolean(env.TERMINUS_SUBLIME) || env.ConEmuTask === "{cmd::Cmder}" || TERM_PROGRAM === "Terminus-Sublime" || TERM_PROGRAM === "vscode" || TERM === "xterm-256color" || TERM === "alacritty" || TERM === "rxvt-unicode" || TERM === "rxvt-unicode-256color" || env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
@@ -30084,6 +30159,91 @@ function levenshteinDistance(a2, b2) {
30084
30159
  function findSimilarCommands(input, commands, maxDistance = 2, maxSuggestions = 3) {
30085
30160
  return commands.map((cmd) => ({ cmd, distance: levenshteinDistance(input, cmd) })).filter(({ distance }) => distance <= maxDistance).sort((a2, b2) => a2.distance - b2.distance).slice(0, maxSuggestions).map(({ cmd }) => cmd);
30086
30161
  }
30162
+ function parseArgv(argv, opts = {}) {
30163
+ const result = { _: [] };
30164
+ const alias = opts.alias || {};
30165
+ const booleans = new Set(opts.boolean || []);
30166
+ const aliasOf = {};
30167
+ for (const key of Object.keys(alias)) {
30168
+ for (const a2 of alias[key]) {
30169
+ aliasOf[a2] = key;
30170
+ }
30171
+ }
30172
+ for (const b2 of booleans) {
30173
+ if (alias[b2]) {
30174
+ for (const a2 of alias[b2])
30175
+ booleans.add(a2);
30176
+ }
30177
+ }
30178
+ function setKey(key, value) {
30179
+ const canonical = aliasOf[key] || key;
30180
+ result[canonical] = value;
30181
+ if (alias[canonical]) {
30182
+ for (const a2 of alias[canonical])
30183
+ result[a2] = value;
30184
+ }
30185
+ if (aliasOf[key] && alias[aliasOf[key]]) {
30186
+ for (const a2 of alias[aliasOf[key]])
30187
+ result[a2] = value;
30188
+ }
30189
+ result[key] = value;
30190
+ }
30191
+ for (let i2 = 0;i2 < argv.length; i2++) {
30192
+ const arg = argv[i2];
30193
+ if (arg === "--") {
30194
+ result._.push(...argv.slice(i2 + 1));
30195
+ break;
30196
+ }
30197
+ if (arg.startsWith("--")) {
30198
+ const eqIdx = arg.indexOf("=");
30199
+ if (eqIdx !== -1) {
30200
+ const key = camelcase(arg.slice(2, eqIdx));
30201
+ const value = arg.slice(eqIdx + 1);
30202
+ setKey(key, value);
30203
+ } else {
30204
+ const rawKey = arg.slice(2);
30205
+ if (rawKey.startsWith("no-")) {
30206
+ const actualKey = camelcase(rawKey.slice(3));
30207
+ setKey(actualKey, false);
30208
+ continue;
30209
+ }
30210
+ const key = camelcase(rawKey);
30211
+ const canonical = aliasOf[key] || key;
30212
+ if (booleans.has(canonical) || booleans.has(key)) {
30213
+ setKey(key, true);
30214
+ } else {
30215
+ const next = argv[i2 + 1];
30216
+ if (next !== undefined && !next.startsWith("-")) {
30217
+ setKey(key, next);
30218
+ i2++;
30219
+ } else {
30220
+ setKey(key, true);
30221
+ }
30222
+ }
30223
+ }
30224
+ } else if (arg.startsWith("-") && arg.length > 1) {
30225
+ const chars = arg.slice(1);
30226
+ for (let j = 0;j < chars.length; j++) {
30227
+ const ch = chars[j];
30228
+ const canonical = aliasOf[ch] || ch;
30229
+ if (j === chars.length - 1 && !booleans.has(canonical) && !booleans.has(ch)) {
30230
+ const next = argv[i2 + 1];
30231
+ if (next !== undefined && !next.startsWith("-")) {
30232
+ setKey(ch, next);
30233
+ i2++;
30234
+ } else {
30235
+ setKey(ch, true);
30236
+ }
30237
+ } else {
30238
+ setKey(ch, true);
30239
+ }
30240
+ }
30241
+ } else {
30242
+ result._.push(arg);
30243
+ }
30244
+ }
30245
+ return result;
30246
+ }
30087
30247
 
30088
30248
  class Option {
30089
30249
  rawName;
@@ -30231,9 +30391,9 @@ class Command {
30231
30391
  return this.namespace ? `${this.namespace}:${this.name}` : this.name;
30232
30392
  }
30233
30393
  hasOption(name) {
30234
- name = name.split(".")[0];
30394
+ const normalized = camelcaseOptionName(name.split(".")[0]);
30235
30395
  return !!this.options.find((option) => {
30236
- return option.names.includes(name);
30396
+ return option.names.some((optionName) => camelcaseOptionName(optionName) === normalized);
30237
30397
  });
30238
30398
  }
30239
30399
  outputHelp() {
@@ -30268,6 +30428,7 @@ class Command {
30268
30428
  }
30269
30429
  }
30270
30430
  let commandBody = "";
30431
+ noNamespaceCommands.sort((a2, b2) => a2.rawName < b2.rawName ? -1 : a2.rawName > b2.rawName ? 1 : 0);
30271
30432
  if (noNamespaceCommands.length > 0) {
30272
30433
  commandBody += noNamespaceCommands.map((command) => {
30273
30434
  return ` ${padRight(command.rawName, longestCommandName.length)} ${command.description}`;
@@ -30294,12 +30455,14 @@ class Command {
30294
30455
  body: commandBody
30295
30456
  });
30296
30457
  sections.push({
30297
- title: `For more info, run any command with the \`--help\` flag`,
30298
- body: commands.map((command) => ` $ ${name}${command.displayName === "" ? "" : ` ${command.displayName}`} --help`).join(`
30299
- `)
30458
+ body: `Run \`${name} <command> --help\` for command details.`
30300
30459
  });
30301
30460
  }
30302
- let options = this.isGlobalCommand ? globalOptions : [...this.options, ...globalOptions || []];
30461
+ const localOptionNames = new Set(this.options.flatMap((option) => option.names));
30462
+ let options = this.isGlobalCommand ? globalOptions : [
30463
+ ...this.options,
30464
+ ...(globalOptions || []).filter((option) => !option.names.some((name2) => localOptionNames.has(name2)))
30465
+ ];
30303
30466
  if (!this.isGlobalCommand && !this.isDefaultCommand) {
30304
30467
  options = options.filter((option) => option.name !== "version");
30305
30468
  }
@@ -30343,6 +30506,9 @@ ${section.body}` : section.body;
30343
30506
  console.log(`${name}/${versionNumber} ${platformInfo3}`);
30344
30507
  }
30345
30508
  }
30509
+ get usageLine() {
30510
+ return `$ ${this.cli.name} ${this.usageText || this.rawName}`;
30511
+ }
30346
30512
  checkRequiredArgs() {
30347
30513
  const minimalArgsCount = this.args.filter((arg) => arg.required).length;
30348
30514
  if (this.cli.args.length < minimalArgsCount) {
@@ -30351,7 +30517,7 @@ ${section.body}` : section.body;
30351
30517
  const argNames = missingArgs.map((arg) => `<${arg.value}>`).join(" ");
30352
30518
  throw new ClappError(`Missing required argument${missingArgs.length > 1 ? "s" : ""}: ${argNames}
30353
30519
 
30354
- ` + `Run \`${this.cli.name} ${this.rawName} --help\` for usage information.`);
30520
+ ` + `Run \`${this.cli.name} ${this.rawName} --help\` for usage information.`, this.usageLine);
30355
30521
  }
30356
30522
  }
30357
30523
  checkUnknownOptions() {
@@ -30361,8 +30527,9 @@ ${section.body}` : section.body;
30361
30527
  if (name !== "--" && !this.hasOption(name) && !globalCommand.hasOption(name)) {
30362
30528
  const allOptions = [...globalCommand.options, ...this.options];
30363
30529
  const allOptionNames = allOptions.flatMap((opt) => opt.names);
30530
+ const normalizedName = camelcaseOptionName(name.split(".")[0]);
30364
30531
  const optionFlag = name.length > 1 ? `--${name}` : `-${name}`;
30365
- const suggestions = findSimilarCommands(name, allOptionNames);
30532
+ const suggestions = findSimilarCommands(normalizedName, allOptionNames);
30366
30533
  let errorMsg = `Unknown option \`${optionFlag}\``;
30367
30534
  if (suggestions.length > 0) {
30368
30535
  errorMsg += `
@@ -30377,7 +30544,7 @@ Did you mean one of these?`;
30377
30544
  errorMsg += `
30378
30545
 
30379
30546
  Run \`${this.cli.name} ${this.rawName} --help\` to see available options.`;
30380
- throw new ClappError(errorMsg);
30547
+ throw new ClappError(errorMsg, this.usageLine);
30381
30548
  }
30382
30549
  }
30383
30550
  }
@@ -30392,7 +30559,7 @@ Run \`${this.cli.name} ${this.rawName} --help\` to see available options.`;
30392
30559
  if (value === true || value === false && !hasNegated) {
30393
30560
  throw new ClappError(`Option \`${option.rawName}\` requires a value.
30394
30561
 
30395
- ` + `Example: ${this.cli.name} ${this.rawName} ${option.rawName} <value>`);
30562
+ ` + `Example: ${this.cli.name} ${this.rawName} ${option.rawName} <value>`, this.usageLine);
30396
30563
  }
30397
30564
  }
30398
30565
  }
@@ -30698,6 +30865,25 @@ Received ${signal}, cleaning up...`);
30698
30865
  break;
30699
30866
  }
30700
30867
  }
30868
+ if (shouldParse) {
30869
+ const nextToken = slicedArgv[1];
30870
+ if (nextToken && !nextToken.startsWith("-")) {
30871
+ const joinedName = `${candidateName}:${nextToken}`;
30872
+ for (const command of this.commands) {
30873
+ if (command.isMatched(joinedName)) {
30874
+ const parsed = this.mri(slicedArgv, command);
30875
+ shouldParse = false;
30876
+ const parsedInfo = {
30877
+ ...parsed,
30878
+ args: parsed.args.slice(2)
30879
+ };
30880
+ this.setParsedInfo(parsedInfo, command, joinedName);
30881
+ this.emit(`command:${joinedName}`, command);
30882
+ break;
30883
+ }
30884
+ }
30885
+ }
30886
+ }
30701
30887
  }
30702
30888
  if (shouldParse) {
30703
30889
  for (const command of this.commands) {
@@ -30723,7 +30909,7 @@ Received ${signal}, cleaning up...`);
30723
30909
  if (this.options.debug) {
30724
30910
  this.isDebug = true;
30725
30911
  }
30726
- if (this.options.noInteraction) {
30912
+ if (this.options.noInteraction || this.options.interaction === false) {
30727
30913
  this.isNoInteraction = true;
30728
30914
  }
30729
30915
  if (this.options.env) {
@@ -30735,14 +30921,14 @@ Received ${signal}, cleaning up...`);
30735
30921
  if (this.options.force) {
30736
30922
  this.isForce = true;
30737
30923
  }
30738
- if (this.options.noEmoji !== undefined) {
30739
- this.useEmoji = !this.options.noEmoji;
30924
+ if (this.options.noEmoji || this.options.emoji === false) {
30925
+ this.useEmoji = false;
30740
30926
  }
30741
30927
  if (this.options.theme) {
30742
30928
  this.theme = String(this.options.theme);
30743
30929
  }
30744
- if (this.options.noCache !== undefined) {
30745
- this.isNoCache = Boolean(this.options.noCache);
30930
+ if (this.options.noCache || this.options.cache === false) {
30931
+ this.isNoCache = true;
30746
30932
  }
30747
30933
  if (this.options.help && this.showHelpOnExit) {
30748
30934
  this.outputHelp();
@@ -30823,18 +31009,16 @@ Received ${signal}, cleaning up...`);
30823
31009
  return this.parse(argv, { run: true, exitOnError: true });
30824
31010
  }
30825
31011
  handleUsageError(err) {
30826
- const isClappError = !!err && typeof err === "object" && err.name === "ClappError";
30827
- const isUsage = isClappError && err.isUsageError !== false;
30828
- if (!isUsage)
31012
+ if (!isClappError(err) || err.isUsageError === false)
30829
31013
  return;
30830
- const e2 = err;
30831
- const raw2 = e2.message ?? "command-line error";
31014
+ const raw2 = err.message || "command-line error";
30832
31015
  const label = this.name ? `${this.name}: ` : "";
30833
- const suffix = /--help/.test(raw2) ? "" : `
31016
+ const suffix = /--help/.test(raw2) ? "" : err.usage ? `
31017
+ Usage: ${err.usage}` : `
30834
31018
  Run \`${this.name ?? "cli"} --help\` for usage.`;
30835
31019
  process52.stderr.write(`${label}${raw2}${suffix}
30836
31020
  `);
30837
- process52.exit(e2.exitCode ?? 2);
31021
+ process52.exit(err.exitCode ?? 2);
30838
31022
  }
30839
31023
  async runMatchedCommand() {
30840
31024
  const { args, options, matchedCommand: command } = this;
@@ -31690,7 +31874,7 @@ function getPrefix() {
31690
31874
  }
31691
31875
  var prefix = getPrefix();
31692
31876
  // package.json
31693
- var version2 = "0.2.25";
31877
+ var version2 = "0.2.27";
31694
31878
 
31695
31879
  // bin/cli.ts
31696
31880
  init_actions();