@databricks-solutions/lakebase-scm-utils 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +10 -4
  2. package/dist/scripts/index.cjs +2336 -2262
  3. package/dist/scripts/index.js +395 -321
  4. package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +26 -9
  5. package/dist/scripts/lakebase/ci-resolve-branch.cli.js +27 -10
  6. package/dist/scripts/lakebase/collapse-heads.cli.cjs +26 -9
  7. package/dist/scripts/lakebase/collapse-heads.cli.js +27 -10
  8. package/dist/scripts/lakebase/detect-language.cli.cjs +26 -9
  9. package/dist/scripts/lakebase/detect-language.cli.js +27 -10
  10. package/dist/scripts/lakebase/doctor.cli.cjs +26 -9
  11. package/dist/scripts/lakebase/doctor.cli.js +27 -10
  12. package/dist/scripts/lakebase/get-connection.cli.cjs +2 -2
  13. package/dist/scripts/lakebase/get-connection.cli.js +2 -2
  14. package/dist/scripts/lakebase/index.cjs +2333 -2223
  15. package/dist/scripts/lakebase/index.js +389 -279
  16. package/dist/scripts/lakebase/infra-runner.cli.cjs +26 -9
  17. package/dist/scripts/lakebase/infra-runner.cli.js +27 -10
  18. package/dist/scripts/lakebase/new-migration.cli.cjs +26 -9
  19. package/dist/scripts/lakebase/new-migration.cli.js +27 -10
  20. package/dist/scripts/lakebase/schema-diff.cli.cjs +2 -2
  21. package/dist/scripts/lakebase/schema-diff.cli.js +2 -2
  22. package/dist/scripts/lakebase/schema-migrate.cli.cjs +26 -9
  23. package/dist/scripts/lakebase/schema-migrate.cli.js +27 -10
  24. package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +26 -9
  25. package/dist/scripts/lakebase/scm-claim-feature.cli.js +27 -10
  26. package/dist/scripts/lakebase/scm-doctor.cli.cjs +26 -9
  27. package/dist/scripts/lakebase/scm-doctor.cli.js +27 -10
  28. package/dist/scripts/lakebase/scm-merge.cli.cjs +26 -9
  29. package/dist/scripts/lakebase/scm-merge.cli.js +27 -10
  30. package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +26 -9
  31. package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +28 -11
  32. package/dist/scripts/util/index.cjs +2 -2
  33. package/dist/scripts/util/index.js +2 -2
  34. package/package.json +1 -1
  35. package/scripts/lakebase/client-lockfile.ts +102 -0
  36. package/scripts/lakebase/create-project.ts +19 -0
  37. package/scripts/lakebase/schema-migrate-runners/alembic.ts +58 -14
  38. package/templates/project/client/playwright.config.ts +35 -10
@@ -1913,9 +1913,9 @@ function asBranchUid(s) {
1913
1913
  }
1914
1914
  return s;
1915
1915
  }
1916
- function branchNameFromResourcePath(path36) {
1917
- if (!path36.includes("/branches/")) return null;
1918
- const leaf = path36.split("/branches/").pop();
1916
+ function branchNameFromResourcePath(path37) {
1917
+ if (!path37.includes("/branches/")) return null;
1918
+ const leaf = path37.split("/branches/").pop();
1919
1919
  if (!leaf) return null;
1920
1920
  try {
1921
1921
  return asBranchName(leaf);
@@ -2521,8 +2521,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
2521
2521
  var cached;
2522
2522
  function substrateSelfVersion() {
2523
2523
  if (cached !== void 0) return cached;
2524
- if ("0.3.0".length > 0) {
2525
- cached = "0.3.0";
2524
+ if ("0.3.2".length > 0) {
2525
+ cached = "0.3.2";
2526
2526
  return cached;
2527
2527
  }
2528
2528
  cached = "unknown";
@@ -5062,7 +5062,7 @@ paginateRest.VERSION = VERSION5;
5062
5062
 
5063
5063
  // node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
5064
5064
  init_esm_shims();
5065
- var generateMessage = (path36, cursorValue) => `The cursor at "${path36.join(
5065
+ var generateMessage = (path37, cursorValue) => `The cursor at "${path37.join(
5066
5066
  ","
5067
5067
  )}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
5068
5068
  var MissingCursorChange = class extends Error {
@@ -5103,9 +5103,9 @@ function findPaginatedResourcePath(responseData) {
5103
5103
  }
5104
5104
  return paginatedResourcePath;
5105
5105
  }
5106
- var deepFindPathToProperty = (object, searchProp, path36 = []) => {
5106
+ var deepFindPathToProperty = (object, searchProp, path37 = []) => {
5107
5107
  for (const key of Object.keys(object)) {
5108
- const currentPath = [...path36, key];
5108
+ const currentPath = [...path37, key];
5109
5109
  const currentValue = object[key];
5110
5110
  if (isObject(currentValue)) {
5111
5111
  if (currentValue.hasOwnProperty(searchProp)) {
@@ -5123,12 +5123,12 @@ var deepFindPathToProperty = (object, searchProp, path36 = []) => {
5123
5123
  }
5124
5124
  return [];
5125
5125
  };
5126
- var get = (object, path36) => {
5127
- return path36.reduce((current, nextProperty) => current[nextProperty], object);
5126
+ var get = (object, path37) => {
5127
+ return path37.reduce((current, nextProperty) => current[nextProperty], object);
5128
5128
  };
5129
- var set = (object, path36, mutator) => {
5130
- const lastProperty = path36[path36.length - 1];
5131
- const parentPath = [...path36].slice(0, -1);
5129
+ var set = (object, path37, mutator) => {
5130
+ const lastProperty = path37[path37.length - 1];
5131
+ const parentPath = [...path37].slice(0, -1);
5132
5132
  const parent = get(object, parentPath);
5133
5133
  if (typeof mutator === "function") {
5134
5134
  parent[lastProperty] = mutator(parent[lastProperty]);
@@ -5180,22 +5180,22 @@ var mergeResponses = (response1, response2) => {
5180
5180
  if (Object.keys(response1).length === 0) {
5181
5181
  return Object.assign(response1, response2);
5182
5182
  }
5183
- const path36 = findPaginatedResourcePath(response1);
5184
- const nodesPath = [...path36, "nodes"];
5183
+ const path37 = findPaginatedResourcePath(response1);
5184
+ const nodesPath = [...path37, "nodes"];
5185
5185
  const newNodes = get(response2, nodesPath);
5186
5186
  if (newNodes) {
5187
5187
  set(response1, nodesPath, (values) => {
5188
5188
  return [...values, ...newNodes];
5189
5189
  });
5190
5190
  }
5191
- const edgesPath = [...path36, "edges"];
5191
+ const edgesPath = [...path37, "edges"];
5192
5192
  const newEdges = get(response2, edgesPath);
5193
5193
  if (newEdges) {
5194
5194
  set(response1, edgesPath, (values) => {
5195
5195
  return [...values, ...newEdges];
5196
5196
  });
5197
5197
  }
5198
- const pageInfoPath = [...path36, "pageInfo"];
5198
+ const pageInfoPath = [...path37, "pageInfo"];
5199
5199
  set(response1, pageInfoPath, get(response2, pageInfoPath));
5200
5200
  return response1;
5201
5201
  };
@@ -7616,7 +7616,7 @@ var triggers_notification_paths_default = [
7616
7616
  ];
7617
7617
  function routeMatcher(paths) {
7618
7618
  const regexes = paths.map(
7619
- (path36) => path36.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
7619
+ (path37) => path37.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
7620
7620
  );
7621
7621
  const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
7622
7622
  return new RegExp(regex2, "i");
@@ -10944,16 +10944,16 @@ function isAllSchemas(schema) {
10944
10944
  }
10945
10945
  function buildSchemaQuery(schema) {
10946
10946
  const cols = "c.table_schema, c.table_name, c.column_name, c.data_type";
10947
- const join35 = "FROM information_schema.columns c JOIN pg_tables t ON c.table_name = t.tablename AND c.table_schema = t.schemaname ";
10947
+ const join36 = "FROM information_schema.columns c JOIN pg_tables t ON c.table_name = t.tablename AND c.table_schema = t.schemaname ";
10948
10948
  if (isAllSchemas(schema)) {
10949
10949
  return {
10950
- text: `SELECT ${cols} ` + join35 + `WHERE ${SYSTEM_SCHEMA_FILTER} ORDER BY c.table_schema, c.table_name, c.ordinal_position`,
10950
+ text: `SELECT ${cols} ` + join36 + `WHERE ${SYSTEM_SCHEMA_FILTER} ORDER BY c.table_schema, c.table_name, c.ordinal_position`,
10951
10951
  values: []
10952
10952
  };
10953
10953
  }
10954
10954
  const one = (schema ?? "").trim() || "public";
10955
10955
  return {
10956
- text: `SELECT ${cols} ` + join35 + "WHERE c.table_schema = $1 ORDER BY c.table_name, c.ordinal_position",
10956
+ text: `SELECT ${cols} ` + join36 + "WHERE c.table_schema = $1 ORDER BY c.table_name, c.ordinal_position",
10957
10957
  values: [one]
10958
10958
  };
10959
10959
  }
@@ -11113,8 +11113,8 @@ async function withLakebaseRollback(opts, fn) {
11113
11113
 
11114
11114
  // scripts/lakebase/create-project.ts
11115
11115
  init_esm_shims();
11116
- import * as fs18 from "fs";
11117
- import * as path18 from "path";
11116
+ import * as fs19 from "fs";
11117
+ import * as path19 from "path";
11118
11118
 
11119
11119
  // scripts/lakebase/project-verify.ts
11120
11120
  init_esm_shims();
@@ -12477,18 +12477,100 @@ function enableE2eForProject(args) {
12477
12477
  };
12478
12478
  }
12479
12479
 
12480
- // scripts/lakebase/enable-infra.ts
12480
+ // scripts/lakebase/client-lockfile.ts
12481
12481
  init_esm_shims();
12482
12482
  import * as fs15 from "fs";
12483
12483
  import * as path14 from "path";
12484
+
12485
+ // scripts/util/proxy-env.ts
12486
+ init_esm_shims();
12487
+ var PROXY_ENV_KEYS = [
12488
+ "HTTP_PROXY",
12489
+ "HTTPS_PROXY",
12490
+ "NO_PROXY",
12491
+ "http_proxy",
12492
+ "https_proxy",
12493
+ "no_proxy",
12494
+ "npm_config_proxy",
12495
+ "npm_config_https_proxy",
12496
+ "npm_config_no_proxy",
12497
+ "npm_config_registry"
12498
+ ];
12499
+ function proxyEnvSubset(source = process.env) {
12500
+ const out = {};
12501
+ for (const key of PROXY_ENV_KEYS) {
12502
+ const v = source[key];
12503
+ if (v !== void 0 && v !== "") {
12504
+ out[key] = v;
12505
+ }
12506
+ }
12507
+ return out;
12508
+ }
12509
+ function withProxyEnv(base = {}) {
12510
+ const out = {};
12511
+ const inherited = proxyEnvSubset();
12512
+ for (const [k, v] of Object.entries(inherited)) {
12513
+ out[k] = v;
12514
+ }
12515
+ for (const [k, v] of Object.entries(base)) {
12516
+ if (v !== void 0) out[k] = v;
12517
+ }
12518
+ return out;
12519
+ }
12520
+
12521
+ // scripts/lakebase/client-lockfile.ts
12522
+ var PROXY_HOST = "npm-proxy.cloud.databricks.com";
12523
+ var PUBLIC_HOST = "registry.npmjs.org";
12524
+ function normalizeLockfileRegistry(lockText) {
12525
+ let swaps = 0;
12526
+ const text = lockText.replace(new RegExp(PROXY_HOST.replace(/\./g, "\\."), "g"), () => {
12527
+ swaps++;
12528
+ return PUBLIC_HOST;
12529
+ });
12530
+ return { text, swaps };
12531
+ }
12532
+ async function ensureClientLockfile(args) {
12533
+ const clientDir = path14.join(args.projectDir, args.clientDir ?? "client");
12534
+ const pkg = path14.join(clientDir, "package.json");
12535
+ if (!fs15.existsSync(pkg)) {
12536
+ return { generated: false, swaps: 0, reason: "no client package.json" };
12537
+ }
12538
+ const lockPath = path14.join(clientDir, "package-lock.json");
12539
+ try {
12540
+ await exec2("npm install --package-lock-only", {
12541
+ cwd: clientDir,
12542
+ env: withProxyEnv(),
12543
+ timeout: 18e4
12544
+ });
12545
+ } catch (err) {
12546
+ const msg = err instanceof Error ? err.message : String(err);
12547
+ return { generated: fs15.existsSync(lockPath), swaps: 0, reason: `npm resolve failed: ${msg}` };
12548
+ }
12549
+ if (!fs15.existsSync(lockPath)) {
12550
+ return { generated: false, swaps: 0, reason: "npm wrote no package-lock.json" };
12551
+ }
12552
+ try {
12553
+ const { text, swaps } = normalizeLockfileRegistry(fs15.readFileSync(lockPath, "utf8"));
12554
+ if (swaps > 0) fs15.writeFileSync(lockPath, text);
12555
+ return { generated: true, swaps };
12556
+ } catch (err) {
12557
+ const msg = err instanceof Error ? err.message : String(err);
12558
+ return { generated: true, swaps: 0, reason: `lock normalize failed: ${msg}` };
12559
+ }
12560
+ }
12561
+
12562
+ // scripts/lakebase/enable-infra.ts
12563
+ init_esm_shims();
12564
+ import * as fs16 from "fs";
12565
+ import * as path15 from "path";
12484
12566
  var RUN_TESTS_INFRA_MARKER = "# Run Lakebase [Infra]-tag suite when wired";
12485
12567
  function addInfraToPackageJson(args) {
12486
- const pkgPath = path14.join(args.projectDir, "package.json");
12487
- if (!fs15.existsSync(pkgPath)) {
12568
+ const pkgPath = path15.join(args.projectDir, "package.json");
12569
+ if (!fs16.existsSync(pkgPath)) {
12488
12570
  return { patched: false, scriptAdded: false };
12489
12571
  }
12490
12572
  const scriptValue = args.scriptValue ?? "npx --yes lakebase-infra-runner";
12491
- const raw = fs15.readFileSync(pkgPath, "utf8");
12573
+ const raw = fs16.readFileSync(pkgPath, "utf8");
12492
12574
  const pkg = JSON.parse(raw);
12493
12575
  const scripts = pkg.scripts ?? {};
12494
12576
  let scriptAdded = false;
@@ -12499,16 +12581,16 @@ function addInfraToPackageJson(args) {
12499
12581
  pkg.scripts = scripts;
12500
12582
  if (scriptAdded) {
12501
12583
  const trailing = raw.endsWith("\n") ? "\n" : "";
12502
- fs15.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + trailing, "utf8");
12584
+ fs16.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + trailing, "utf8");
12503
12585
  }
12504
12586
  return { patched: true, scriptAdded };
12505
12587
  }
12506
12588
  function addInfraToRunTestsScript(args) {
12507
- const scriptPath = path14.join(args.projectDir, "scripts", "run-tests.sh");
12508
- if (!fs15.existsSync(scriptPath)) {
12589
+ const scriptPath = path15.join(args.projectDir, "scripts", "run-tests.sh");
12590
+ if (!fs16.existsSync(scriptPath)) {
12509
12591
  return { patched: false, inserted: false };
12510
12592
  }
12511
- const original = fs15.readFileSync(scriptPath, "utf8");
12593
+ const original = fs16.readFileSync(scriptPath, "utf8");
12512
12594
  if (original.includes(RUN_TESTS_INFRA_MARKER)) {
12513
12595
  return { patched: true, inserted: false };
12514
12596
  }
@@ -12524,7 +12606,7 @@ function addInfraToRunTestsScript(args) {
12524
12606
  "fi",
12525
12607
  ""
12526
12608
  ].join("\n");
12527
- fs15.writeFileSync(scriptPath, trimmed + block, "utf8");
12609
+ fs16.writeFileSync(scriptPath, trimmed + block, "utf8");
12528
12610
  return { patched: true, inserted: true };
12529
12611
  }
12530
12612
  function enableInfraForProject(args) {
@@ -12538,9 +12620,9 @@ function enableInfraForProject(args) {
12538
12620
 
12539
12621
  // scripts/lakebase/runner-setup.ts
12540
12622
  init_esm_shims();
12541
- import * as fs16 from "fs";
12623
+ import * as fs17 from "fs";
12542
12624
  import * as os from "os";
12543
- import * as path15 from "path";
12625
+ import * as path16 from "path";
12544
12626
  import * as cp4 from "child_process";
12545
12627
  import * as tar from "tar";
12546
12628
  import findJavaHome from "find-java-home";
@@ -12627,28 +12709,28 @@ var RUNNER_OS = process.platform === "darwin" ? "osx" : "linux";
12627
12709
  var RUNNER_ARCHIVE = `actions-runner-${RUNNER_OS}-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz`;
12628
12710
  var RUNNER_URL = `https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/${RUNNER_ARCHIVE}`;
12629
12711
  function cacheDir() {
12630
- return path15.join(os.homedir(), ".cache", "github-actions-runner");
12712
+ return path16.join(os.homedir(), ".cache", "github-actions-runner");
12631
12713
  }
12632
12714
  function runnersDir() {
12633
- return path15.join(os.homedir(), ".lakebase", "runners");
12715
+ return path16.join(os.homedir(), ".lakebase", "runners");
12634
12716
  }
12635
12717
  function runnerDir(projectName) {
12636
- return path15.join(runnersDir(), projectName);
12718
+ return path16.join(runnersDir(), projectName);
12637
12719
  }
12638
12720
  function runnerName(projectName) {
12639
12721
  return `lakebase-${projectName}`;
12640
12722
  }
12641
12723
  async function ensureCachedArchive() {
12642
12724
  const dir = cacheDir();
12643
- fs16.mkdirSync(dir, { recursive: true });
12644
- const cachedPath = path15.join(dir, RUNNER_ARCHIVE);
12645
- if (fs16.existsSync(cachedPath)) return cachedPath;
12725
+ fs17.mkdirSync(dir, { recursive: true });
12726
+ const cachedPath = path16.join(dir, RUNNER_ARCHIVE);
12727
+ if (fs17.existsSync(cachedPath)) return cachedPath;
12646
12728
  const response = await fetch(RUNNER_URL);
12647
12729
  if (!response.ok) {
12648
12730
  throw new Error(`Failed to download runner: HTTP ${response.status}`);
12649
12731
  }
12650
12732
  const buffer = Buffer.from(await response.arrayBuffer());
12651
- fs16.writeFileSync(cachedPath, buffer);
12733
+ fs17.writeFileSync(cachedPath, buffer);
12652
12734
  return cachedPath;
12653
12735
  }
12654
12736
  async function resolveJavaHome() {
@@ -12658,9 +12740,9 @@ async function resolveJavaHome() {
12658
12740
  });
12659
12741
  }
12660
12742
  function isRunning(projectName) {
12661
- const pidFile = path15.join(runnerDir(projectName), ".pid");
12662
- if (!fs16.existsSync(pidFile)) return false;
12663
- const pid = parseInt(fs16.readFileSync(pidFile, "utf-8").trim(), 10);
12743
+ const pidFile = path16.join(runnerDir(projectName), ".pid");
12744
+ if (!fs17.existsSync(pidFile)) return false;
12745
+ const pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim(), 10);
12664
12746
  if (!pid) return false;
12665
12747
  try {
12666
12748
  process.kill(pid, 0);
@@ -12671,23 +12753,23 @@ function isRunning(projectName) {
12671
12753
  }
12672
12754
  function getRunnerInfo(projectName) {
12673
12755
  const dir = runnerDir(projectName);
12674
- if (!fs16.existsSync(dir)) return void 0;
12675
- const pidFile = path15.join(dir, ".pid");
12756
+ if (!fs17.existsSync(dir)) return void 0;
12757
+ const pidFile = path16.join(dir, ".pid");
12676
12758
  let pid;
12677
- if (fs16.existsSync(pidFile)) {
12678
- pid = parseInt(fs16.readFileSync(pidFile, "utf-8").trim(), 10);
12759
+ if (fs17.existsSync(pidFile)) {
12760
+ pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim(), 10);
12679
12761
  }
12680
12762
  return { name: runnerName(projectName), dir, pid, online: isRunning(projectName) };
12681
12763
  }
12682
12764
  var lastRunnerPid;
12683
12765
  function stopRunner(projectName) {
12684
12766
  const dir = runnerDir(projectName);
12685
- const pidFile = path15.join(dir, ".pid");
12767
+ const pidFile = path16.join(dir, ".pid");
12686
12768
  let pid = lastRunnerPid;
12687
- if (fs16.existsSync(pidFile)) {
12688
- pid = parseInt(fs16.readFileSync(pidFile, "utf-8").trim(), 10);
12769
+ if (fs17.existsSync(pidFile)) {
12770
+ pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim(), 10);
12689
12771
  try {
12690
- fs16.unlinkSync(pidFile);
12772
+ fs17.unlinkSync(pidFile);
12691
12773
  } catch {
12692
12774
  }
12693
12775
  }
@@ -12700,7 +12782,7 @@ function stopRunner(projectName) {
12700
12782
  } catch {
12701
12783
  }
12702
12784
  }
12703
- } else if (fs16.existsSync(dir)) {
12785
+ } else if (fs17.existsSync(dir)) {
12704
12786
  try {
12705
12787
  cp4.execSync(`pkill -9 -f "${dir.replace(/\//g, "\\/")}.*Runner" 2>/dev/null || true`, {
12706
12788
  timeout: KIT_TIMEOUTS.cmdShort
@@ -12710,16 +12792,16 @@ function stopRunner(projectName) {
12710
12792
  }
12711
12793
  lastRunnerPid = void 0;
12712
12794
  for (const stale of ["_diag/pages", "_work/_temp", "_work/_actions"]) {
12713
- const full = path15.join(dir, stale);
12714
- if (fs16.existsSync(full)) {
12795
+ const full = path16.join(dir, stale);
12796
+ if (fs17.existsSync(full)) {
12715
12797
  try {
12716
- fs16.rmSync(full, { recursive: true, force: true });
12798
+ fs17.rmSync(full, { recursive: true, force: true });
12717
12799
  } catch {
12718
12800
  }
12719
12801
  }
12720
12802
  }
12721
12803
  try {
12722
- fs16.mkdirSync(path15.join(dir, "_diag", "pages"), { recursive: true });
12804
+ fs17.mkdirSync(path16.join(dir, "_diag", "pages"), { recursive: true });
12723
12805
  } catch {
12724
12806
  }
12725
12807
  }
@@ -12735,24 +12817,24 @@ function resetRunnerConfig(dir, projectName) {
12735
12817
  ];
12736
12818
  for (const f of stateFiles) {
12737
12819
  try {
12738
- fs16.unlinkSync(path15.join(dir, f));
12820
+ fs17.unlinkSync(path16.join(dir, f));
12739
12821
  } catch {
12740
12822
  }
12741
12823
  }
12742
12824
  if (process.platform === "darwin") {
12743
- const plist = path15.join(
12825
+ const plist = path16.join(
12744
12826
  os.homedir(),
12745
12827
  "Library",
12746
12828
  "LaunchAgents",
12747
12829
  `actions.runner.${projectName}.plist`
12748
12830
  );
12749
- if (fs16.existsSync(plist)) {
12831
+ if (fs17.existsSync(plist)) {
12750
12832
  try {
12751
12833
  cp4.execFileSync("launchctl", ["unload", plist], { stdio: "ignore" });
12752
12834
  } catch {
12753
12835
  }
12754
12836
  try {
12755
- fs16.unlinkSync(plist);
12837
+ fs17.unlinkSync(plist);
12756
12838
  } catch {
12757
12839
  }
12758
12840
  }
@@ -12766,24 +12848,24 @@ async function setupRunner(args) {
12766
12848
  stopRunner(args.projectName);
12767
12849
  report("Downloading runner binary...");
12768
12850
  const archive = await ensureCachedArchive();
12769
- fs16.mkdirSync(dir, { recursive: true });
12770
- if (!fs16.existsSync(path15.join(dir, "config.sh"))) {
12851
+ fs17.mkdirSync(dir, { recursive: true });
12852
+ if (!fs17.existsSync(path16.join(dir, "config.sh"))) {
12771
12853
  report("Extracting runner...");
12772
12854
  await tar.extract({ file: archive, cwd: dir });
12773
12855
  }
12774
- const diagPages = path15.join(dir, "_diag", "pages");
12775
- if (fs16.existsSync(diagPages)) {
12776
- fs16.rmSync(diagPages, { recursive: true, force: true });
12777
- fs16.mkdirSync(diagPages, { recursive: true });
12856
+ const diagPages = path16.join(dir, "_diag", "pages");
12857
+ if (fs17.existsSync(diagPages)) {
12858
+ fs17.rmSync(diagPages, { recursive: true, force: true });
12859
+ fs17.mkdirSync(diagPages, { recursive: true });
12778
12860
  }
12779
- const runnerFile = path15.join(dir, ".runner");
12780
- let needsConfig = !fs16.existsSync(runnerFile);
12861
+ const runnerFile = path16.join(dir, ".runner");
12862
+ let needsConfig = !fs17.existsSync(runnerFile);
12781
12863
  if (needsConfig) {
12782
12864
  resetRunnerConfig(dir, args.projectName);
12783
12865
  } else {
12784
12866
  let urlMismatch = false;
12785
12867
  try {
12786
- const runnerJson = JSON.parse(fs16.readFileSync(runnerFile, "utf-8"));
12868
+ const runnerJson = JSON.parse(fs17.readFileSync(runnerFile, "utf-8"));
12787
12869
  const configuredUrl = runnerJson.gitHubUrl || runnerJson.serverUrl || runnerJson.agentUrl || "";
12788
12870
  const expectedUrl = `https://github.com/${args.fullRepoName}`;
12789
12871
  urlMismatch = !!configuredUrl && !configuredUrl.startsWith(expectedUrl);
@@ -12844,7 +12926,7 @@ async function setupRunner(args) {
12844
12926
  child.unref();
12845
12927
  lastRunnerPid = child.pid;
12846
12928
  if (child.pid) {
12847
- fs16.writeFileSync(path15.join(dir, ".pid"), String(child.pid));
12929
+ fs17.writeFileSync(path16.join(dir, ".pid"), String(child.pid));
12848
12930
  }
12849
12931
  report("Waiting for runner to come online...");
12850
12932
  let online = false;
@@ -12876,14 +12958,14 @@ async function removeRunner(args) {
12876
12958
  } catch {
12877
12959
  }
12878
12960
  try {
12879
- fs16.rmSync(dir, { recursive: true, force: true });
12961
+ fs17.rmSync(dir, { recursive: true, force: true });
12880
12962
  } catch {
12881
12963
  }
12882
12964
  }
12883
12965
 
12884
12966
  // scripts/util/ci-secrets.ts
12885
12967
  init_esm_shims();
12886
- import * as path16 from "path";
12968
+ import * as path17 from "path";
12887
12969
 
12888
12970
  // scripts/github/secrets.ts
12889
12971
  init_esm_shims();
@@ -13106,7 +13188,7 @@ async function ensureCiSecretsFresh(args) {
13106
13188
  return { action: "ok", reason: "CI token is current." };
13107
13189
  }
13108
13190
  async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
13109
- const envPath = path16.join(projectDir, ".env");
13191
+ const envPath = path17.join(projectDir, ".env");
13110
13192
  const databricksHost = readEnvVar(envPath, "DATABRICKS_HOST");
13111
13193
  const lakebaseProjectId = readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
13112
13194
  if (!databricksHost || !lakebaseProjectId) {
@@ -13133,8 +13215,8 @@ async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
13133
13215
 
13134
13216
  // scripts/lakebase/scm-workflow-state.ts
13135
13217
  init_esm_shims();
13136
- import * as fs17 from "fs";
13137
- import * as path17 from "path";
13218
+ import * as fs18 from "fs";
13219
+ import * as path18 from "path";
13138
13220
  import { execFileSync as execFileSync6 } from "child_process";
13139
13221
  function isGitTracked(projectDir, rel) {
13140
13222
  try {
@@ -13153,11 +13235,11 @@ function ensureWorkflowStateUntracked(projectDir) {
13153
13235
  } catch {
13154
13236
  }
13155
13237
  try {
13156
- const gitignore = path17.join(projectDir, ".gitignore");
13157
- const existing = fs17.existsSync(gitignore) ? fs17.readFileSync(gitignore, "utf8") : "";
13238
+ const gitignore = path18.join(projectDir, ".gitignore");
13239
+ const existing = fs18.existsSync(gitignore) ? fs18.readFileSync(gitignore, "utf8") : "";
13158
13240
  if (!existing.split("\n").some((l) => l.trim() === rel)) {
13159
13241
  const sep4 = existing === "" || existing.endsWith("\n") ? "" : "\n";
13160
- fs17.appendFileSync(
13242
+ fs18.appendFileSync(
13161
13243
  gitignore,
13162
13244
  `${sep4}# Runtime SCM claim state (per working tree): a branch checkout must never restore
13163
13245
  # a stale committed claim over the live one (issue #203 / Finding 28).
@@ -13181,12 +13263,12 @@ var STATE_INDEX = SCM_STATES.reduce(
13181
13263
  );
13182
13264
  var STATE_FILE_REL = ".lakebase/workflow-state.json";
13183
13265
  function stateFilePath(projectDir) {
13184
- return path17.join(projectDir, STATE_FILE_REL);
13266
+ return path18.join(projectDir, STATE_FILE_REL);
13185
13267
  }
13186
13268
  function readWorkflowState(projectDir) {
13187
13269
  const p = stateFilePath(projectDir);
13188
- if (!fs17.existsSync(p)) return null;
13189
- const raw = fs17.readFileSync(p, "utf8");
13270
+ if (!fs18.existsSync(p)) return null;
13271
+ const raw = fs18.readFileSync(p, "utf8");
13190
13272
  let parsed;
13191
13273
  try {
13192
13274
  parsed = JSON.parse(raw);
@@ -13221,14 +13303,14 @@ function writeWorkflowState(projectDir, state) {
13221
13303
  ${summary}`);
13222
13304
  }
13223
13305
  ensureWorkflowStateUntracked(projectDir);
13224
- const dir = path17.join(projectDir, ".lakebase");
13225
- fs17.mkdirSync(dir, { recursive: true });
13306
+ const dir = path18.join(projectDir, ".lakebase");
13307
+ fs18.mkdirSync(dir, { recursive: true });
13226
13308
  const target = stateFilePath(projectDir);
13227
13309
  const tmp = `${target}.tmp`;
13228
13310
  const ordered = orderForOutput(result.value);
13229
- fs17.writeFileSync(tmp, `${JSON.stringify(ordered, null, 2)}
13311
+ fs18.writeFileSync(tmp, `${JSON.stringify(ordered, null, 2)}
13230
13312
  `, "utf8");
13231
- fs17.renameSync(tmp, target);
13313
+ fs18.renameSync(tmp, target);
13232
13314
  }
13233
13315
  function initWorkflowState(args) {
13234
13316
  return {
@@ -13452,7 +13534,7 @@ function orderForOutput(state) {
13452
13534
  async function createProject(input, progress) {
13453
13535
  const report = progress ?? (() => {
13454
13536
  });
13455
- const projectDir = path18.join(input.parentDir, input.projectName);
13537
+ const projectDir = path19.join(input.parentDir, input.projectName);
13456
13538
  const lakebaseProjectId = input.projectName;
13457
13539
  const host = input.databricksHost.replace(/\/+$/, "");
13458
13540
  const useGithub = input.createGithubRepo !== false;
@@ -13477,7 +13559,7 @@ async function createProject(input, progress) {
13477
13559
  useGithub,
13478
13560
  githubOwner: input.githubOwner,
13479
13561
  tiers,
13480
- dirExists: (p) => fs18.existsSync(p),
13562
+ dirExists: (p) => fs19.existsSync(p),
13481
13563
  dirIsEmpty
13482
13564
  });
13483
13565
  if (!v.ok) throw new Error(v.reason);
@@ -13546,7 +13628,7 @@ Last probe error:
13546
13628
  });
13547
13629
  } else {
13548
13630
  report("Creating local project directory...", projectDir);
13549
- fs18.mkdirSync(projectDir, { recursive: true });
13631
+ fs19.mkdirSync(projectDir, { recursive: true });
13550
13632
  await gitInit(projectDir);
13551
13633
  }
13552
13634
  report("Creating Lakebase database (provisioning Postgres)...", lakebaseProjectId);
@@ -13680,9 +13762,9 @@ Last probe error:
13680
13762
  const scmRef = envRef || (ver !== "unknown" ? `v${ver}` : "");
13681
13763
  if (scmRef) {
13682
13764
  try {
13683
- const dir = path18.join(projectDir, ".lakebase");
13684
- fs18.mkdirSync(dir, { recursive: true });
13685
- fs18.writeFileSync(path18.join(dir, "scm-utils-ref"), `${scmRef}
13765
+ const dir = path19.join(projectDir, ".lakebase");
13766
+ fs19.mkdirSync(dir, { recursive: true });
13767
+ fs19.writeFileSync(path19.join(dir, "scm-utils-ref"), `${scmRef}
13686
13768
  `, "utf8");
13687
13769
  } catch (err) {
13688
13770
  warnings.push(`Substrate ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
@@ -13693,9 +13775,9 @@ Last probe error:
13693
13775
  const kitRef = process.env.LAKEBASE_KIT_REF?.trim();
13694
13776
  if (kitRef) {
13695
13777
  try {
13696
- const dir = path18.join(projectDir, ".lakebase");
13697
- fs18.mkdirSync(dir, { recursive: true });
13698
- fs18.writeFileSync(path18.join(dir, "kit-ref"), `${kitRef}
13778
+ const dir = path19.join(projectDir, ".lakebase");
13779
+ fs19.mkdirSync(dir, { recursive: true });
13780
+ fs19.writeFileSync(path19.join(dir, "kit-ref"), `${kitRef}
13699
13781
  `, "utf8");
13700
13782
  } catch (err) {
13701
13783
  warnings.push(`Kit ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
@@ -13713,6 +13795,17 @@ Last probe error:
13713
13795
  dotnet: `.NET/ASP.NET Core (${input.migrationTool === "flyway" ? "Flyway" : "EF Core"})`
13714
13796
  };
13715
13797
  const langLabel = langLabels[language] ?? language;
13798
+ if (clientFramework !== "none") {
13799
+ report("Generating client package-lock.json (registry-normalized)...");
13800
+ const lock = await ensureClientLockfile({ projectDir });
13801
+ if (lock.generated) {
13802
+ report(` wrote client/package-lock.json${lock.swaps > 0 ? ` (normalized ${lock.swaps} proxy URL(s) to the public registry)` : ""}`);
13803
+ } else {
13804
+ const m = `Could not generate client/package-lock.json (${lock.reason ?? "unknown"}). Generate it with: (cd client && npm install) \u2014 the lock is committed on first push.`;
13805
+ warnings.push(m);
13806
+ report(`WARNING: ${m}`);
13807
+ }
13808
+ }
13716
13809
  report("Creating initial commit...");
13717
13810
  await commitAndPush({
13718
13811
  projectDir,
@@ -13777,17 +13870,17 @@ Last probe error:
13777
13870
  // scripts/lakebase/adopt-lakebase-project.ts
13778
13871
  init_esm_shims();
13779
13872
  import * as cp5 from "child_process";
13780
- import * as fs19 from "fs";
13781
- import * as path19 from "path";
13873
+ import * as fs20 from "fs";
13874
+ import * as path20 from "path";
13782
13875
  async function adoptLakebaseProject(args) {
13783
13876
  const warnings = [];
13784
13877
  const filesWritten = [];
13785
13878
  const dryRun = args.dryRun === true;
13786
13879
  const preserveExistingEnv = args.preserveExistingEnv !== false;
13787
- if (!fs19.existsSync(args.projectDir)) {
13880
+ if (!fs20.existsSync(args.projectDir)) {
13788
13881
  throw new Error(`adoptLakebaseProject: project directory does not exist: ${args.projectDir}`);
13789
13882
  }
13790
- if (!fs19.existsSync(path19.join(args.projectDir, ".git"))) {
13883
+ if (!fs20.existsSync(path20.join(args.projectDir, ".git"))) {
13791
13884
  throw new Error(
13792
13885
  `adoptLakebaseProject: ${args.projectDir} is not a git repo. Run \`git init\` first, or pass an existing repo path.`
13793
13886
  );
@@ -13853,9 +13946,9 @@ async function adoptLakebaseProject(args) {
13853
13946
  };
13854
13947
  }
13855
13948
  function assertEnvCompatibility(projectDir, expectedProjectId) {
13856
- const envPath = path19.join(projectDir, ".env");
13857
- if (!fs19.existsSync(envPath)) return;
13858
- const content = fs19.readFileSync(envPath, "utf8");
13949
+ const envPath = path20.join(projectDir, ".env");
13950
+ if (!fs20.existsSync(envPath)) return;
13951
+ const content = fs20.readFileSync(envPath, "utf8");
13859
13952
  const match = content.match(/^LAKEBASE_PROJECT_ID\s*=\s*(.+?)\s*$/m);
13860
13953
  if (!match) return;
13861
13954
  const existing = match[1].trim().replace(/^['"]|['"]$/g, "");
@@ -13866,10 +13959,10 @@ function assertEnvCompatibility(projectDir, expectedProjectId) {
13866
13959
  }
13867
13960
  }
13868
13961
  function assertAdoptionPreflight(args) {
13869
- if (!fs19.existsSync(args.projectDir)) {
13962
+ if (!fs20.existsSync(args.projectDir)) {
13870
13963
  throw new Error(`assertAdoptionPreflight: project directory does not exist: ${args.projectDir}`);
13871
13964
  }
13872
- if (!fs19.existsSync(path19.join(args.projectDir, ".git"))) {
13965
+ if (!fs20.existsSync(path20.join(args.projectDir, ".git"))) {
13873
13966
  throw new Error(
13874
13967
  `assertAdoptionPreflight: ${args.projectDir} is not a git repo.`
13875
13968
  );
@@ -13879,11 +13972,11 @@ function assertAdoptionPreflight(args) {
13879
13972
  }
13880
13973
  }
13881
13974
  function _testMakeBrownfieldFixture(opts) {
13882
- fs19.mkdirSync(opts.dir, { recursive: true });
13975
+ fs20.mkdirSync(opts.dir, { recursive: true });
13883
13976
  cp5.execSync("git init --quiet", { cwd: opts.dir, stdio: "pipe" });
13884
13977
  if (opts.packageJson) {
13885
- fs19.writeFileSync(
13886
- path19.join(opts.dir, "package.json"),
13978
+ fs20.writeFileSync(
13979
+ path20.join(opts.dir, "package.json"),
13887
13980
  JSON.stringify(opts.packageJson, null, 2) + "\n"
13888
13981
  );
13889
13982
  }
@@ -13891,8 +13984,8 @@ function _testMakeBrownfieldFixture(opts) {
13891
13984
 
13892
13985
  // scripts/lakebase/infra-runner.ts
13893
13986
  init_esm_shims();
13894
- import * as fs29 from "fs";
13895
- import * as path31 from "path";
13987
+ import * as fs30 from "fs";
13988
+ import * as path32 from "path";
13896
13989
 
13897
13990
  // scripts/lakebase/schema-diff.ts
13898
13991
  init_esm_shims();
@@ -14088,24 +14181,24 @@ function dbcli6(args) {
14088
14181
 
14089
14182
  // scripts/lakebase/schema-migrate.ts
14090
14183
  init_esm_shims();
14091
- import * as fs28 from "fs";
14092
- import * as path30 from "path";
14184
+ import * as fs29 from "fs";
14185
+ import * as path31 from "path";
14093
14186
 
14094
14187
  // scripts/lakebase/migration-layout.ts
14095
14188
  init_esm_shims();
14096
- import * as fs21 from "fs";
14097
- import * as path21 from "path";
14189
+ import * as fs22 from "fs";
14190
+ import * as path22 from "path";
14098
14191
 
14099
14192
  // scripts/lakebase/dotnet-project.ts
14100
14193
  init_esm_shims();
14101
- import * as fs20 from "fs";
14102
- import * as path20 from "path";
14194
+ import * as fs21 from "fs";
14195
+ import * as path21 from "path";
14103
14196
  var EF_DESIGN_PACKAGE = "Microsoft.EntityFrameworkCore.Design";
14104
- var DOTNET_FLYWAY_DIR = path20.join("db", "migrations");
14197
+ var DOTNET_FLYWAY_DIR = path21.join("db", "migrations");
14105
14198
  var SKIP_DIRS = /* @__PURE__ */ new Set(["bin", "obj", "node_modules", ".git", "client", "tests", "test"]);
14106
14199
  function safeReaddir(dir) {
14107
14200
  try {
14108
- return fs20.readdirSync(dir, { withFileTypes: true });
14201
+ return fs21.readdirSync(dir, { withFileTypes: true });
14109
14202
  } catch {
14110
14203
  return [];
14111
14204
  }
@@ -14119,7 +14212,7 @@ function findCsprojFiles(projectDir) {
14119
14212
  const found = [];
14120
14213
  const walk = (dir, depth) => {
14121
14214
  for (const e of safeReaddir(dir)) {
14122
- const full = path20.join(dir, e.name);
14215
+ const full = path21.join(dir, e.name);
14123
14216
  if (e.isFile() && e.name.toLowerCase().endsWith(".csproj")) {
14124
14217
  found.push(full);
14125
14218
  } else if (e.isDirectory() && depth < 2 && !SKIP_DIRS.has(e.name.toLowerCase()) && !e.name.startsWith(".")) {
@@ -14134,13 +14227,13 @@ function findEfCoreProject(projectDir) {
14134
14227
  for (const csproj of findCsprojFiles(projectDir)) {
14135
14228
  let content = "";
14136
14229
  try {
14137
- content = fs20.readFileSync(csproj, "utf-8");
14230
+ content = fs21.readFileSync(csproj, "utf-8");
14138
14231
  } catch {
14139
14232
  continue;
14140
14233
  }
14141
14234
  if (content.includes(EF_DESIGN_PACKAGE)) {
14142
- const dir = path20.dirname(csproj);
14143
- return { csproj, projectDir: dir, migrationsDir: path20.join(dir, "Migrations") };
14235
+ const dir = path21.dirname(csproj);
14236
+ return { csproj, projectDir: dir, migrationsDir: path21.join(dir, "Migrations") };
14144
14237
  }
14145
14238
  }
14146
14239
  return null;
@@ -14149,13 +14242,13 @@ function isDotnetProject(projectDir) {
14149
14242
  return hasDotnetMarker(projectDir);
14150
14243
  }
14151
14244
  function isDotnetFlywayProject(projectDir) {
14152
- return isDotnetProject(projectDir) && fs20.existsSync(path20.join(projectDir, DOTNET_FLYWAY_DIR));
14245
+ return isDotnetProject(projectDir) && fs21.existsSync(path21.join(projectDir, DOTNET_FLYWAY_DIR));
14153
14246
  }
14154
- var MAVEN_FLYWAY_DIR = path20.join("src", "main", "resources", "db", "migration");
14247
+ var MAVEN_FLYWAY_DIR = path21.join("src", "main", "resources", "db", "migration");
14155
14248
  function flywayMigrationsDir(projectDir) {
14156
- const maven = path20.join(projectDir, MAVEN_FLYWAY_DIR);
14157
- if (fs20.existsSync(maven) || fs20.existsSync(path20.join(projectDir, "pom.xml"))) return maven;
14158
- if (isDotnetFlywayProject(projectDir)) return path20.join(projectDir, DOTNET_FLYWAY_DIR);
14249
+ const maven = path21.join(projectDir, MAVEN_FLYWAY_DIR);
14250
+ if (fs21.existsSync(maven) || fs21.existsSync(path21.join(projectDir, "pom.xml"))) return maven;
14251
+ if (isDotnetFlywayProject(projectDir)) return path21.join(projectDir, DOTNET_FLYWAY_DIR);
14159
14252
  return maven;
14160
14253
  }
14161
14254
 
@@ -14179,13 +14272,13 @@ var MIGRATION_DEFAULTS = {
14179
14272
  unknown: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" }
14180
14273
  };
14181
14274
  function detectLanguageAt(dir) {
14182
- if (fs21.existsSync(path21.join(dir, "pom.xml"))) {
14183
- const kotlinDir = path21.join(dir, "src", "main", "kotlin");
14184
- if (fs21.existsSync(kotlinDir)) {
14275
+ if (fs22.existsSync(path22.join(dir, "pom.xml"))) {
14276
+ const kotlinDir = path22.join(dir, "src", "main", "kotlin");
14277
+ if (fs22.existsSync(kotlinDir)) {
14185
14278
  return "kotlin";
14186
14279
  }
14187
14280
  try {
14188
- const pom = fs21.readFileSync(path21.join(dir, "pom.xml"), "utf-8");
14281
+ const pom = fs22.readFileSync(path22.join(dir, "pom.xml"), "utf-8");
14189
14282
  if (pom.includes("kotlin-maven-plugin")) {
14190
14283
  return "kotlin";
14191
14284
  }
@@ -14193,13 +14286,13 @@ function detectLanguageAt(dir) {
14193
14286
  }
14194
14287
  return "java";
14195
14288
  }
14196
- if (fs21.existsSync(path21.join(dir, "pyproject.toml")) || fs21.existsSync(path21.join(dir, "requirements.txt")) || fs21.existsSync(path21.join(dir, "alembic.ini"))) {
14289
+ if (fs22.existsSync(path22.join(dir, "pyproject.toml")) || fs22.existsSync(path22.join(dir, "requirements.txt")) || fs22.existsSync(path22.join(dir, "alembic.ini"))) {
14197
14290
  return "python";
14198
14291
  }
14199
14292
  if (hasDotnetMarker(dir)) {
14200
14293
  return "dotnet";
14201
14294
  }
14202
- if (fs21.existsSync(path21.join(dir, "package.json"))) {
14295
+ if (fs22.existsSync(path22.join(dir, "package.json"))) {
14203
14296
  return "nodejs";
14204
14297
  }
14205
14298
  return "unknown";
@@ -14220,14 +14313,14 @@ function resolveMigrationLanguage(projectDir, configuredMigrationPath, override)
14220
14313
  if (!rel) {
14221
14314
  return "unknown";
14222
14315
  }
14223
- const rootResolved = path21.resolve(projectDir);
14224
- let dir = path21.resolve(projectDir, rel);
14225
- while (dir === rootResolved || dir.startsWith(rootResolved + path21.sep)) {
14316
+ const rootResolved = path22.resolve(projectDir);
14317
+ let dir = path22.resolve(projectDir, rel);
14318
+ while (dir === rootResolved || dir.startsWith(rootResolved + path22.sep)) {
14226
14319
  const lang = detectLanguageAt(dir);
14227
14320
  if (lang !== "unknown") {
14228
14321
  return lang;
14229
14322
  }
14230
- const parent = path21.dirname(dir);
14323
+ const parent = path22.dirname(dir);
14231
14324
  if (parent === dir) {
14232
14325
  break;
14233
14326
  }
@@ -14255,14 +14348,14 @@ var DOTNET_LAYOUT_TTL_MS = 5e3;
14255
14348
  var dotnetLayoutCache = /* @__PURE__ */ new Map();
14256
14349
  function dotnetDefaults(projectDir) {
14257
14350
  if (!projectDir) return MIGRATION_DEFAULTS.dotnet;
14258
- const key = path21.resolve(projectDir);
14351
+ const key = path22.resolve(projectDir);
14259
14352
  const hit = dotnetLayoutCache.get(key);
14260
14353
  if (hit && Date.now() - hit.at < DOTNET_LAYOUT_TTL_MS) return hit.value;
14261
14354
  let value = MIGRATION_DEFAULTS.dotnet;
14262
14355
  if (!isDotnetFlywayProject(projectDir)) {
14263
14356
  const ef = findEfCoreProject(projectDir);
14264
14357
  if (ef) {
14265
- const rel = path21.relative(projectDir, ef.migrationsDir).split(path21.sep).join("/");
14358
+ const rel = path22.relative(projectDir, ef.migrationsDir).split(path22.sep).join("/");
14266
14359
  value = { ...DOTNET_EFCORE_DEFAULTS, path: rel };
14267
14360
  }
14268
14361
  }
@@ -14283,34 +14376,51 @@ function resolveMigrationLayout(args) {
14283
14376
 
14284
14377
  // scripts/lakebase/adapters/alembic-adapter.ts
14285
14378
  init_esm_shims();
14286
- import * as fs23 from "fs";
14287
- import * as path23 from "path";
14379
+ import * as fs24 from "fs";
14380
+ import * as path24 from "path";
14288
14381
 
14289
14382
  // scripts/lakebase/schema-migrate-runners/alembic.ts
14290
14383
  init_esm_shims();
14291
- import { spawn as spawn5 } from "child_process";
14292
- import * as fs22 from "fs";
14293
- import * as path22 from "path";
14294
- function resolveAlembicBin(projectDir) {
14295
- const candidates = [
14296
- path22.join(projectDir, ".venv", "bin", "alembic"),
14297
- path22.join(projectDir, "venv", "bin", "alembic")
14384
+ import { spawn as spawn5, execFileSync as execFileSync7 } from "child_process";
14385
+ import * as fs23 from "fs";
14386
+ import * as path23 from "path";
14387
+ var uvOnPath;
14388
+ function hasUv() {
14389
+ if (uvOnPath !== void 0) return uvOnPath;
14390
+ try {
14391
+ execFileSync7("uv", ["--version"], { stdio: "ignore" });
14392
+ uvOnPath = true;
14393
+ } catch {
14394
+ uvOnPath = false;
14395
+ }
14396
+ return uvOnPath;
14397
+ }
14398
+ function resolveAlembicInvocation(projectDir, uvAvailable = hasUv()) {
14399
+ const venvCandidates = [
14400
+ path23.join(projectDir, ".venv", "bin", "alembic"),
14401
+ path23.join(projectDir, "venv", "bin", "alembic")
14298
14402
  ];
14299
- for (const candidate of candidates) {
14403
+ for (const candidate of venvCandidates) {
14300
14404
  try {
14301
- if (fs22.existsSync(candidate)) return candidate;
14405
+ if (fs23.existsSync(candidate)) return { bin: candidate, prefixArgs: [] };
14302
14406
  } catch {
14303
14407
  }
14304
14408
  }
14305
- return "alembic";
14409
+ try {
14410
+ if (uvAvailable && fs23.existsSync(path23.join(projectDir, "pyproject.toml"))) {
14411
+ return { bin: "uv", prefixArgs: ["run", "alembic"] };
14412
+ }
14413
+ } catch {
14414
+ }
14415
+ return { bin: "alembic", prefixArgs: [] };
14306
14416
  }
14307
14417
  function spawnAlembic(projectDir, args, dsn) {
14308
14418
  return new Promise((resolve2, reject) => {
14309
- const bin = resolveAlembicBin(projectDir);
14419
+ const { bin, prefixArgs } = resolveAlembicInvocation(projectDir);
14310
14420
  const env = { ...process.env };
14311
- env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path22.delimiter);
14421
+ env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path23.delimiter);
14312
14422
  if (dsn) env.DATABASE_URL = dsn;
14313
- const child = spawn5(bin, args, {
14423
+ const child = spawn5(bin, [...prefixArgs, ...args], {
14314
14424
  cwd: projectDir,
14315
14425
  env,
14316
14426
  stdio: ["ignore", "pipe", "pipe"]
@@ -14356,10 +14466,10 @@ async function createAlembicRevision(opts) {
14356
14466
  const m = stdout.match(/Generating\s+(\S+\.py)/);
14357
14467
  if (m) return m[1].trim();
14358
14468
  for (const rel of ["migrations/versions", "alembic/versions"]) {
14359
- const dir = path22.join(opts.projectDir, rel);
14360
- if (!fs22.existsSync(dir)) continue;
14361
- const hit = fs22.readdirSync(dir).find((f) => f.startsWith(`${opts.revId}_`) && f.endsWith(".py"));
14362
- if (hit) return path22.join(dir, hit);
14469
+ const dir = path23.join(opts.projectDir, rel);
14470
+ if (!fs23.existsSync(dir)) continue;
14471
+ const hit = fs23.readdirSync(dir).find((f) => f.startsWith(`${opts.revId}_`) && f.endsWith(".py"));
14472
+ if (hit) return path23.join(dir, hit);
14363
14473
  }
14364
14474
  throw new SchemaMigrationError(
14365
14475
  `alembic revision succeeded but the created file could not be located.
@@ -14494,15 +14604,15 @@ async function buildDsn2(args) {
14494
14604
  }
14495
14605
  function findVersionsDir(projectDir) {
14496
14606
  const candidates = [
14497
- path23.join(projectDir, "migrations", "versions"),
14498
- path23.join(projectDir, "alembic", "versions")
14607
+ path24.join(projectDir, "migrations", "versions"),
14608
+ path24.join(projectDir, "alembic", "versions")
14499
14609
  ];
14500
- return candidates.find((p) => fs23.existsSync(p));
14610
+ return candidates.find((p) => fs24.existsSync(p));
14501
14611
  }
14502
14612
  function listAlembicFiles(projectDir) {
14503
14613
  const dir = findVersionsDir(projectDir);
14504
14614
  if (!dir) return [];
14505
- const files = fs23.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
14615
+ const files = fs24.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
14506
14616
  return files.map((filename) => {
14507
14617
  const stem = filename.replace(/\.py$/, "");
14508
14618
  const sep4 = stem.indexOf("_");
@@ -14527,9 +14637,9 @@ var AlembicAdapter = {
14527
14637
  * here. Callers can still force-select via project.yaml#migration_tool.
14528
14638
  */
14529
14639
  detect(projectDir) {
14530
- if (fs23.existsSync(path23.join(projectDir, "alembic.ini"))) return true;
14531
- if (fs23.existsSync(path23.join(projectDir, "migrations", "env.py"))) return true;
14532
- if (fs23.existsSync(path23.join(projectDir, "alembic", "env.py"))) return true;
14640
+ if (fs24.existsSync(path24.join(projectDir, "alembic.ini"))) return true;
14641
+ if (fs24.existsSync(path24.join(projectDir, "migrations", "env.py"))) return true;
14642
+ if (fs24.existsSync(path24.join(projectDir, "alembic", "env.py"))) return true;
14533
14643
  return false;
14534
14644
  },
14535
14645
  async apply(args) {
@@ -14635,7 +14745,7 @@ var AlembicAdapter = {
14635
14745
  autogenerate: !!args.autogenerate,
14636
14746
  dsn
14637
14747
  });
14638
- return { status: "ok", version: revId, filename: path23.basename(created), path: created };
14748
+ return { status: "ok", version: revId, filename: path24.basename(created), path: created };
14639
14749
  } catch (err) {
14640
14750
  return {
14641
14751
  status: "error",
@@ -14652,7 +14762,7 @@ var AlembicAdapter = {
14652
14762
  if (heads.length <= 1) return { status: "noop", headsBefore: heads };
14653
14763
  if (args.dryRun) return { status: "ok", headsBefore: heads };
14654
14764
  const created = await mergeAlembicHeads(args.projectDir, args.message ?? "merge heads");
14655
- const mergeRevision = path23.basename(created).replace(/\.py$/, "").split("_")[0];
14765
+ const mergeRevision = path24.basename(created).replace(/\.py$/, "").split("_")[0];
14656
14766
  return { status: "ok", headsBefore: heads, mergeRevision, path: created };
14657
14767
  } catch (err) {
14658
14768
  return {
@@ -14667,13 +14777,13 @@ registerSchemaMigrationAdapter(AlembicAdapter);
14667
14777
 
14668
14778
  // scripts/lakebase/adapters/flyway-adapter.ts
14669
14779
  init_esm_shims();
14670
- import * as fs24 from "fs";
14671
- import * as path25 from "path";
14780
+ import * as fs25 from "fs";
14781
+ import * as path26 from "path";
14672
14782
 
14673
14783
  // scripts/lakebase/schema-migrate-runners/flyway.ts
14674
14784
  init_esm_shims();
14675
14785
  import { spawn as spawn6 } from "child_process";
14676
- import * as path24 from "path";
14786
+ import * as path25 from "path";
14677
14787
  function dsnToFlywayEnv(dsn) {
14678
14788
  const u = new URL(dsn);
14679
14789
  const user = decodeURIComponent(u.username);
@@ -14784,7 +14894,7 @@ async function statusFlyway(ctx) {
14784
14894
  if (state === "SUCCESS" || state === "BASELINE") {
14785
14895
  current = m.version;
14786
14896
  } else if (state === "PENDING") {
14787
- const filename = m.filepath ? path24.basename(m.filepath) : `V${m.version}__migration.sql`;
14897
+ const filename = m.filepath ? path25.basename(m.filepath) : `V${m.version}__migration.sql`;
14788
14898
  pending.push({
14789
14899
  version: m.version,
14790
14900
  filename,
@@ -14808,8 +14918,8 @@ async function buildDsn3(args) {
14808
14918
  }
14809
14919
  function listFlywayFiles(projectDir) {
14810
14920
  const dir = flywayMigrationsDir(projectDir);
14811
- if (!fs24.existsSync(dir)) return [];
14812
- const files = fs24.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
14921
+ if (!fs25.existsSync(dir)) return [];
14922
+ const files = fs25.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
14813
14923
  return files.map((filename) => {
14814
14924
  const m = filename.match(/^V(\d+(?:\.\d+)*)__(.+)\.sql$/);
14815
14925
  const version = m[1];
@@ -14832,7 +14942,7 @@ var FlywayAdapter = {
14832
14942
  id: "flyway",
14833
14943
  languages: ["java", "kotlin", "dotnet"],
14834
14944
  detect(projectDir) {
14835
- return fs24.existsSync(path25.join(projectDir, "pom.xml")) || isDotnetFlywayProject(projectDir);
14945
+ return fs25.existsSync(path26.join(projectDir, "pom.xml")) || isDotnetFlywayProject(projectDir);
14836
14946
  },
14837
14947
  async apply(args) {
14838
14948
  const dsn = await buildDsn3(args);
@@ -14891,13 +15001,13 @@ var FlywayAdapter = {
14891
15001
  async newMigration(args) {
14892
15002
  try {
14893
15003
  const dir = flywayMigrationsDir(args.projectDir);
14894
- fs24.mkdirSync(dir, { recursive: true });
15004
+ fs25.mkdirSync(dir, { recursive: true });
14895
15005
  const version = migrationTimestamp();
14896
15006
  const slug = migrationSlug2(args.slug);
14897
15007
  const filename = `V${version}__${slug}.sql`;
14898
- const full = path25.join(dir, filename);
14899
- if (fs24.existsSync(full)) throw new Error(`${filename} already exists`);
14900
- fs24.writeFileSync(
15008
+ const full = path26.join(dir, filename);
15009
+ if (fs25.existsSync(full)) throw new Error(`${filename} already exists`);
15010
+ fs25.writeFileSync(
14901
15011
  full,
14902
15012
  `-- V${version}: ${args.slug}
14903
15013
  -- Flyway migration (write your DDL/DML below).
@@ -14920,19 +15030,19 @@ registerSchemaMigrationAdapter(FlywayAdapter);
14920
15030
 
14921
15031
  // scripts/lakebase/adapters/knex-adapter.ts
14922
15032
  init_esm_shims();
14923
- import * as fs26 from "fs";
14924
- import * as path27 from "path";
15033
+ import * as fs27 from "fs";
15034
+ import * as path28 from "path";
14925
15035
 
14926
15036
  // scripts/lakebase/schema-migrate-runners/knex.ts
14927
15037
  init_esm_shims();
14928
15038
  import { spawn as spawn7 } from "child_process";
14929
- import * as fs25 from "fs";
14930
- import * as path26 from "path";
15039
+ import * as fs26 from "fs";
15040
+ import * as path27 from "path";
14931
15041
  var KNEXFILE_VARIANTS = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
14932
15042
  function findKnexfile(projectDir) {
14933
15043
  for (const name of KNEXFILE_VARIANTS) {
14934
- const p = path26.join(projectDir, name);
14935
- if (fs25.existsSync(p)) return p;
15044
+ const p = path27.join(projectDir, name);
15045
+ if (fs26.existsSync(p)) return p;
14936
15046
  }
14937
15047
  return void 0;
14938
15048
  }
@@ -15084,9 +15194,9 @@ async function buildDsn4(args) {
15084
15194
  }
15085
15195
  var KNEXFILE_VARIANTS2 = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
15086
15196
  function listKnexFiles(projectDir) {
15087
- const dir = path27.join(projectDir, "migrations");
15088
- if (!fs26.existsSync(dir)) return [];
15089
- const files = fs26.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
15197
+ const dir = path28.join(projectDir, "migrations");
15198
+ if (!fs27.existsSync(dir)) return [];
15199
+ const files = fs27.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
15090
15200
  return files.map((filename) => {
15091
15201
  const stem = filename.replace(/\.(js|ts)$/, "");
15092
15202
  const m = stem.match(/^(\d{14})_(.+)$/);
@@ -15106,7 +15216,7 @@ var KnexAdapter = {
15106
15216
  * project.yaml#migration_tool.
15107
15217
  */
15108
15218
  detect(projectDir) {
15109
- return KNEXFILE_VARIANTS2.some((name) => fs26.existsSync(path27.join(projectDir, name)));
15219
+ return KNEXFILE_VARIANTS2.some((name) => fs27.existsSync(path28.join(projectDir, name)));
15110
15220
  },
15111
15221
  async apply(args) {
15112
15222
  const dsn = await buildDsn4(args);
@@ -15179,9 +15289,9 @@ var KnexAdapter = {
15179
15289
  async newMigration(args) {
15180
15290
  try {
15181
15291
  const created = await createKnexMigration({ projectDir: args.projectDir, slug: migrationSlug2(args.slug) });
15182
- const stem = path27.basename(created).replace(/\.(js|ts)$/, "");
15292
+ const stem = path28.basename(created).replace(/\.(js|ts)$/, "");
15183
15293
  const version = stem.match(/^(\d{14})_/)?.[1] ?? stem;
15184
- return { status: "ok", version, filename: path27.basename(created), path: created };
15294
+ return { status: "ok", version, filename: path28.basename(created), path: created };
15185
15295
  } catch (err) {
15186
15296
  return {
15187
15297
  status: "error",
@@ -15197,13 +15307,13 @@ registerSchemaMigrationAdapter(KnexAdapter);
15197
15307
 
15198
15308
  // scripts/lakebase/adapters/efcore-adapter.ts
15199
15309
  init_esm_shims();
15200
- import * as path29 from "path";
15310
+ import * as path30 from "path";
15201
15311
 
15202
15312
  // scripts/lakebase/schema-migrate-runners/efcore.ts
15203
15313
  init_esm_shims();
15204
15314
  import { spawn as spawn8 } from "child_process";
15205
- import * as fs27 from "fs";
15206
- import * as path28 from "path";
15315
+ import * as fs28 from "fs";
15316
+ import * as path29 from "path";
15207
15317
  import { Client as Client3 } from "pg";
15208
15318
  var MIGRATION_ID = /^(\d{14})_(.+)$/;
15209
15319
  function efVersion(id) {
@@ -15300,7 +15410,7 @@ stderr: ${stderr}`
15300
15410
  var restored = /* @__PURE__ */ new Set();
15301
15411
  async function ensureRestored(projectDir, csproj) {
15302
15412
  if (restored.has(projectDir)) return;
15303
- if (fs27.existsSync(path28.join(projectDir, ".config", "dotnet-tools.json"))) {
15413
+ if (fs28.existsSync(path29.join(projectDir, ".config", "dotnet-tools.json"))) {
15304
15414
  await spawnDotnet(projectDir, ["tool", "restore"], {});
15305
15415
  }
15306
15416
  await spawnDotnet(projectDir, ["restore", csproj], {});
@@ -15308,7 +15418,7 @@ async function ensureRestored(projectDir, csproj) {
15308
15418
  }
15309
15419
  async function runEf(projectDir, args, dsn, opts = {}) {
15310
15420
  const project = requireProject(projectDir);
15311
- const csproj = path28.relative(projectDir, project.csproj) || project.csproj;
15421
+ const csproj = path29.relative(projectDir, project.csproj) || project.csproj;
15312
15422
  await ensureRestored(projectDir, csproj);
15313
15423
  const full = ["ef", ...args, "--project", csproj, "--prefix-output"];
15314
15424
  if (opts.noBuild) full.push("--no-build");
@@ -15392,22 +15502,22 @@ function efMigrationName(slug) {
15392
15502
  async function createEfcoreMigration(opts) {
15393
15503
  const project = requireProject(opts.projectDir);
15394
15504
  const name = efMigrationName(opts.slug);
15395
- const existing = new Set(fs27.existsSync(project.migrationsDir) ? fs27.readdirSync(project.migrationsDir) : []);
15505
+ const existing = new Set(fs28.existsSync(project.migrationsDir) ? fs28.readdirSync(project.migrationsDir) : []);
15396
15506
  await runEf(opts.projectDir, ["migrations", "add", name]);
15397
- const created = fs27.readdirSync(project.migrationsDir).filter((f) => !existing.has(f) && MIGRATION_ID.test(f.replace(/\.cs$/, "")) && !f.endsWith(".Designer.cs"));
15507
+ const created = fs28.readdirSync(project.migrationsDir).filter((f) => !existing.has(f) && MIGRATION_ID.test(f.replace(/\.cs$/, "")) && !f.endsWith(".Designer.cs"));
15398
15508
  if (created.length !== 1) {
15399
15509
  throw new SchemaMigrationError(`Expected one new migration file for ${name}, found: ${created.join(", ") || "none"}`);
15400
15510
  }
15401
- return { id: created[0].replace(/\.cs$/, ""), path: path28.join(project.migrationsDir, created[0]) };
15511
+ return { id: created[0].replace(/\.cs$/, ""), path: path29.join(project.migrationsDir, created[0]) };
15402
15512
  }
15403
15513
  function localEfMigrationIds(projectDir) {
15404
15514
  const project = findEfCoreProject(projectDir);
15405
- if (!project || !fs27.existsSync(project.migrationsDir)) return [];
15406
- return fs27.readdirSync(project.migrationsDir).filter((f) => f.endsWith(".cs") && !f.endsWith(".Designer.cs") && MIGRATION_ID.test(f.slice(0, -3))).map((f) => f.slice(0, -3)).sort();
15515
+ if (!project || !fs28.existsSync(project.migrationsDir)) return [];
15516
+ return fs28.readdirSync(project.migrationsDir).filter((f) => f.endsWith(".cs") && !f.endsWith(".Designer.cs") && MIGRATION_ID.test(f.slice(0, -3))).map((f) => f.slice(0, -3)).sort();
15407
15517
  }
15408
15518
  function efProductVersion(project) {
15409
15519
  try {
15410
- const csproj = fs27.readFileSync(project.csproj, "utf-8");
15520
+ const csproj = fs28.readFileSync(project.csproj, "utf-8");
15411
15521
  const m = new RegExp(`${EF_DESIGN_PACKAGE.replace(/\./g, "\\.")}"\\s+Version="([^"]+)"`).exec(csproj);
15412
15522
  if (m) return m[1];
15413
15523
  } catch {
@@ -15541,7 +15651,7 @@ var EfCoreAdapter = {
15541
15651
  return {
15542
15652
  status: "ok",
15543
15653
  version: efVersion(created.id),
15544
- filename: path29.basename(created.path),
15654
+ filename: path30.basename(created.path),
15545
15655
  path: created.path
15546
15656
  };
15547
15657
  } catch (err) {
@@ -15600,8 +15710,8 @@ function listSchemaMigrations(args = {}) {
15600
15710
  }
15601
15711
  function listFlywayMigrations(projectDir) {
15602
15712
  const dir = flywayMigrationsDir(projectDir);
15603
- if (!fs28.existsSync(dir)) return [];
15604
- const files = fs28.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
15713
+ if (!fs29.existsSync(dir)) return [];
15714
+ const files = fs29.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
15605
15715
  return files.map((filename) => {
15606
15716
  const m = filename.match(/^V(\d+(?:\.\d+)*)__(.+)\.sql$/);
15607
15717
  const version = m[1];
@@ -15611,12 +15721,12 @@ function listFlywayMigrations(projectDir) {
15611
15721
  }
15612
15722
  function listAlembicMigrations(projectDir) {
15613
15723
  const candidates = [
15614
- path30.join(projectDir, "migrations", "versions"),
15615
- path30.join(projectDir, "alembic", "versions")
15724
+ path31.join(projectDir, "migrations", "versions"),
15725
+ path31.join(projectDir, "alembic", "versions")
15616
15726
  ];
15617
- const dir = candidates.find((p) => fs28.existsSync(p));
15727
+ const dir = candidates.find((p) => fs29.existsSync(p));
15618
15728
  if (!dir) return [];
15619
- const files = fs28.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
15729
+ const files = fs29.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
15620
15730
  return files.map((filename) => {
15621
15731
  const stem = filename.replace(/\.py$/, "");
15622
15732
  const sep4 = stem.indexOf("_");
@@ -15626,9 +15736,9 @@ function listAlembicMigrations(projectDir) {
15626
15736
  }).sort((a, b) => a.filename.localeCompare(b.filename));
15627
15737
  }
15628
15738
  function listKnexMigrations(projectDir) {
15629
- const dir = path30.join(projectDir, "migrations");
15630
- if (!fs28.existsSync(dir)) return [];
15631
- const files = fs28.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
15739
+ const dir = path31.join(projectDir, "migrations");
15740
+ if (!fs29.existsSync(dir)) return [];
15741
+ const files = fs29.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
15632
15742
  return files.map((filename) => {
15633
15743
  const stem = filename.replace(/\.(js|ts)$/, "");
15634
15744
  const m = stem.match(/^(\d{14})_(.+)$/);
@@ -15804,8 +15914,8 @@ async function runInfraSuite(args) {
15804
15914
  duration_ms: Date.now() - start
15805
15915
  };
15806
15916
  if (args.junitOutput) {
15807
- fs29.mkdirSync(path31.dirname(args.junitOutput), { recursive: true });
15808
- fs29.writeFileSync(args.junitOutput, formatJUnit(result), "utf8");
15917
+ fs30.mkdirSync(path32.dirname(args.junitOutput), { recursive: true });
15918
+ fs30.writeFileSync(args.junitOutput, formatJUnit(result), "utf8");
15809
15919
  }
15810
15920
  return result;
15811
15921
  }
@@ -15851,8 +15961,8 @@ function escapeXml(s) {
15851
15961
 
15852
15962
  // scripts/lakebase/scm-claim-feature.ts
15853
15963
  init_esm_shims();
15854
- import * as fs30 from "fs";
15855
- import * as path32 from "path";
15964
+ import * as fs31 from "fs";
15965
+ import * as path33 from "path";
15856
15966
  var ScmClaimError = class extends Error {
15857
15967
  constructor(message, code) {
15858
15968
  super(message);
@@ -15909,7 +16019,7 @@ async function claimFeatureBranch(args) {
15909
16019
  const current = readWorkflowState(args.projectDir);
15910
16020
  if (!current) {
15911
16021
  throw new ScmClaimError(
15912
- `No SCM workflow state found at ${path32.join(args.projectDir, ".lakebase/workflow-state.json")}. Run lakebase-create-project to scaffold, or re-seed via the substrate.`,
16022
+ `No SCM workflow state found at ${path33.join(args.projectDir, ".lakebase/workflow-state.json")}. Run lakebase-create-project to scaffold, or re-seed via the substrate.`,
15913
16023
  "no-state-file"
15914
16024
  );
15915
16025
  }
@@ -16013,8 +16123,8 @@ function alreadyClaimedSentinel(state) {
16013
16123
  };
16014
16124
  }
16015
16125
  function workflowStateFileExists(projectDir) {
16016
- return fs30.existsSync(
16017
- path32.join(projectDir, ".lakebase/workflow-state.json")
16126
+ return fs31.existsSync(
16127
+ path33.join(projectDir, ".lakebase/workflow-state.json")
16018
16128
  );
16019
16129
  }
16020
16130
 
@@ -16502,12 +16612,12 @@ async function pushCurrentBranchForPr(args) {
16502
16612
 
16503
16613
  // scripts/lakebase/workflow-drift.ts
16504
16614
  init_esm_shims();
16505
- import * as fs31 from "fs";
16506
- import * as path33 from "path";
16615
+ import * as fs32 from "fs";
16616
+ import * as path34 from "path";
16507
16617
  function findKitTemplatesDir(start) {
16508
16618
  let dir = start;
16509
16619
  for (let i = 0; i < 6; i++) {
16510
- const candidate = path33.join(
16620
+ const candidate = path34.join(
16511
16621
  dir,
16512
16622
  "templates",
16513
16623
  "project",
@@ -16515,8 +16625,8 @@ function findKitTemplatesDir(start) {
16515
16625
  ".github",
16516
16626
  "workflows"
16517
16627
  );
16518
- if (fs31.existsSync(candidate)) return candidate;
16519
- const parent = path33.dirname(dir);
16628
+ if (fs32.existsSync(candidate)) return candidate;
16629
+ const parent = path34.dirname(dir);
16520
16630
  if (parent === dir) break;
16521
16631
  dir = parent;
16522
16632
  }
@@ -16540,13 +16650,13 @@ function unifiedDiff(name, projectContent, templateContent) {
16540
16650
  return out.join("\n");
16541
16651
  }
16542
16652
  function detectWorkflowDrift(args) {
16543
- const projectWorkflowsDir = path33.join(
16653
+ const projectWorkflowsDir = path34.join(
16544
16654
  args.projectDir,
16545
16655
  ".github",
16546
16656
  "workflows"
16547
16657
  );
16548
- const here = path33.dirname(new URL(import.meta.url).pathname);
16549
- const kitWorkflowsDir = args.kitDir ? path33.join(
16658
+ const here = path34.dirname(new URL(import.meta.url).pathname);
16659
+ const kitWorkflowsDir = args.kitDir ? path34.join(
16550
16660
  args.kitDir,
16551
16661
  "templates",
16552
16662
  "project",
@@ -16554,21 +16664,21 @@ function detectWorkflowDrift(args) {
16554
16664
  ".github",
16555
16665
  "workflows"
16556
16666
  ) : findKitTemplatesDir(here);
16557
- const templateFiles = fs31.existsSync(kitWorkflowsDir) ? fs31.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16558
- const projectFiles = fs31.existsSync(projectWorkflowsDir) ? fs31.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16667
+ const templateFiles = fs32.existsSync(kitWorkflowsDir) ? fs32.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16668
+ const projectFiles = fs32.existsSync(projectWorkflowsDir) ? fs32.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16559
16669
  const version = readKitVersion(kitWorkflowsDir);
16560
16670
  const seen = /* @__PURE__ */ new Set();
16561
16671
  const files = [];
16562
16672
  for (const name of templateFiles) {
16563
16673
  seen.add(name);
16564
- const projectPath2 = path33.join(projectWorkflowsDir, name);
16565
- const templatePath = path33.join(kitWorkflowsDir, name);
16566
- if (!fs31.existsSync(projectPath2)) {
16674
+ const projectPath2 = path34.join(projectWorkflowsDir, name);
16675
+ const templatePath = path34.join(kitWorkflowsDir, name);
16676
+ if (!fs32.existsSync(projectPath2)) {
16567
16677
  files.push({ name, status: "missing" });
16568
16678
  continue;
16569
16679
  }
16570
- const projectContent = fs31.readFileSync(projectPath2, "utf8");
16571
- const templateContent = applyPlaceholders(fs31.readFileSync(templatePath, "utf8"), version);
16680
+ const projectContent = fs32.readFileSync(projectPath2, "utf8");
16681
+ const templateContent = applyPlaceholders(fs32.readFileSync(templatePath, "utf8"), version);
16572
16682
  if (projectContent === templateContent) {
16573
16683
  files.push({ name, status: "unchanged" });
16574
16684
  } else {
@@ -16599,10 +16709,10 @@ function detectWorkflowDrift(args) {
16599
16709
  function readKitVersion(kitWorkflowsDir) {
16600
16710
  let dir = kitWorkflowsDir;
16601
16711
  for (let i = 0; i < 5; i++) {
16602
- dir = path33.dirname(dir);
16712
+ dir = path34.dirname(dir);
16603
16713
  }
16604
16714
  try {
16605
- const raw = fs31.readFileSync(path33.join(dir, "package.json"), "utf-8");
16715
+ const raw = fs32.readFileSync(path34.join(dir, "package.json"), "utf-8");
16606
16716
  const pkg = JSON.parse(raw);
16607
16717
  return typeof pkg.version === "string" ? pkg.version : "unknown";
16608
16718
  } catch {
@@ -16619,7 +16729,7 @@ var COMMAND_HOOK_FILE_PATTERN = /\.(pre|post)-hook\.md$/;
16619
16729
  function findKitCommandsDir(start) {
16620
16730
  let dir = start;
16621
16731
  for (let i = 0; i < 6; i++) {
16622
- const candidate = path33.join(
16732
+ const candidate = path34.join(
16623
16733
  dir,
16624
16734
  "templates",
16625
16735
  "project",
@@ -16627,8 +16737,8 @@ function findKitCommandsDir(start) {
16627
16737
  ".claude",
16628
16738
  "commands"
16629
16739
  );
16630
- if (fs31.existsSync(candidate)) return candidate;
16631
- const parent = path33.dirname(dir);
16740
+ if (fs32.existsSync(candidate)) return candidate;
16741
+ const parent = path34.dirname(dir);
16632
16742
  if (parent === dir) break;
16633
16743
  dir = parent;
16634
16744
  }
@@ -16641,24 +16751,24 @@ function parsePinnedVersion(content) {
16641
16751
  return m ? m[1] : void 0;
16642
16752
  }
16643
16753
  function detectCommandDrift(args) {
16644
- const projectCommandsDir = path33.join(args.projectDir, ".claude", "commands");
16645
- const here = path33.dirname(new URL(import.meta.url).pathname);
16646
- const kitCommandsDir = args.kitDir ? path33.join(args.kitDir, "templates", "project", "common", ".claude", "commands") : findKitCommandsDir(here);
16754
+ const projectCommandsDir = path34.join(args.projectDir, ".claude", "commands");
16755
+ const here = path34.dirname(new URL(import.meta.url).pathname);
16756
+ const kitCommandsDir = args.kitDir ? path34.join(args.kitDir, "templates", "project", "common", ".claude", "commands") : findKitCommandsDir(here);
16647
16757
  const kitVersion = readKitVersionFromCommandsDir(kitCommandsDir);
16648
- const templateFiles = fs31.existsSync(kitCommandsDir) ? fs31.readdirSync(kitCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
16649
- const projectFiles = fs31.existsSync(projectCommandsDir) ? fs31.readdirSync(projectCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
16758
+ const templateFiles = fs32.existsSync(kitCommandsDir) ? fs32.readdirSync(kitCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
16759
+ const projectFiles = fs32.existsSync(projectCommandsDir) ? fs32.readdirSync(projectCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
16650
16760
  const seen = /* @__PURE__ */ new Set();
16651
16761
  const files = [];
16652
16762
  for (const name of templateFiles) {
16653
16763
  seen.add(name);
16654
- const projectPath2 = path33.join(projectCommandsDir, name);
16655
- const templatePath = path33.join(kitCommandsDir, name);
16656
- const templateRaw = fs31.readFileSync(templatePath, "utf8");
16657
- if (!fs31.existsSync(projectPath2)) {
16764
+ const projectPath2 = path34.join(projectCommandsDir, name);
16765
+ const templatePath = path34.join(kitCommandsDir, name);
16766
+ const templateRaw = fs32.readFileSync(templatePath, "utf8");
16767
+ if (!fs32.existsSync(projectPath2)) {
16658
16768
  files.push({ name, status: "missing", kit_version: kitVersion });
16659
16769
  continue;
16660
16770
  }
16661
- const projectContent = fs31.readFileSync(projectPath2, "utf8");
16771
+ const projectContent = fs32.readFileSync(projectPath2, "utf8");
16662
16772
  const pinned = parsePinnedVersion(projectContent);
16663
16773
  const versionForCompare = pinned ?? kitVersion;
16664
16774
  const templateContent = applyCommandPlaceholders(templateRaw, versionForCompare);
@@ -16696,10 +16806,10 @@ function detectCommandDrift(args) {
16696
16806
  function readKitVersionFromCommandsDir(kitCommandsDir) {
16697
16807
  let dir = kitCommandsDir;
16698
16808
  for (let i = 0; i < 5; i++) {
16699
- dir = path33.dirname(dir);
16809
+ dir = path34.dirname(dir);
16700
16810
  }
16701
16811
  try {
16702
- const raw = fs31.readFileSync(path33.join(dir, "package.json"), "utf-8");
16812
+ const raw = fs32.readFileSync(path34.join(dir, "package.json"), "utf-8");
16703
16813
  const pkg = JSON.parse(raw);
16704
16814
  return typeof pkg.version === "string" ? pkg.version : "unknown";
16705
16815
  } catch {
@@ -16716,13 +16826,13 @@ function detectScaffoldedDrift(args) {
16716
16826
  };
16717
16827
  }
16718
16828
  function updateWorkflows(args) {
16719
- const projectWorkflowsDir = path33.join(
16829
+ const projectWorkflowsDir = path34.join(
16720
16830
  args.projectDir,
16721
16831
  ".github",
16722
16832
  "workflows"
16723
16833
  );
16724
- const here = path33.dirname(new URL(import.meta.url).pathname);
16725
- const kitWorkflowsDir = args.kitDir ? path33.join(
16834
+ const here = path34.dirname(new URL(import.meta.url).pathname);
16835
+ const kitWorkflowsDir = args.kitDir ? path34.join(
16726
16836
  args.kitDir,
16727
16837
  "templates",
16728
16838
  "project",
@@ -16733,22 +16843,22 @@ function updateWorkflows(args) {
16733
16843
  const substitute = args.substitute !== false;
16734
16844
  const dryRun = args.dryRun === true;
16735
16845
  const pruneExtras = args.pruneExtras === true;
16736
- const templateFiles = fs31.existsSync(kitWorkflowsDir) ? fs31.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16737
- const projectFiles = fs31.existsSync(projectWorkflowsDir) ? fs31.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16738
- if (!dryRun && templateFiles.length > 0 && !fs31.existsSync(projectWorkflowsDir)) {
16739
- fs31.mkdirSync(projectWorkflowsDir, { recursive: true });
16846
+ const templateFiles = fs32.existsSync(kitWorkflowsDir) ? fs32.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16847
+ const projectFiles = fs32.existsSync(projectWorkflowsDir) ? fs32.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
16848
+ if (!dryRun && templateFiles.length > 0 && !fs32.existsSync(projectWorkflowsDir)) {
16849
+ fs32.mkdirSync(projectWorkflowsDir, { recursive: true });
16740
16850
  }
16741
16851
  const version = substitute ? readKitVersion(kitWorkflowsDir) : "";
16742
16852
  const seen = /* @__PURE__ */ new Set();
16743
16853
  const files = [];
16744
16854
  for (const name of templateFiles) {
16745
16855
  seen.add(name);
16746
- const projectPath2 = path33.join(projectWorkflowsDir, name);
16747
- const templatePath = path33.join(kitWorkflowsDir, name);
16748
- const templateRaw = fs31.readFileSync(templatePath, "utf-8");
16856
+ const projectPath2 = path34.join(projectWorkflowsDir, name);
16857
+ const templatePath = path34.join(kitWorkflowsDir, name);
16858
+ const templateRaw = fs32.readFileSync(templatePath, "utf-8");
16749
16859
  const desired = substitute ? applyPlaceholders(templateRaw, version) : templateRaw;
16750
- const existed = fs31.existsSync(projectPath2);
16751
- const current = existed ? fs31.readFileSync(projectPath2, "utf-8") : "";
16860
+ const existed = fs32.existsSync(projectPath2);
16861
+ const current = existed ? fs32.readFileSync(projectPath2, "utf-8") : "";
16752
16862
  let outcome;
16753
16863
  if (!existed) {
16754
16864
  outcome = "added";
@@ -16758,16 +16868,16 @@ function updateWorkflows(args) {
16758
16868
  outcome = "updated";
16759
16869
  }
16760
16870
  if (!dryRun && outcome !== "unchanged") {
16761
- fs31.writeFileSync(projectPath2, desired);
16871
+ fs32.writeFileSync(projectPath2, desired);
16762
16872
  }
16763
16873
  files.push({ name, outcome });
16764
16874
  }
16765
16875
  if (pruneExtras) {
16766
16876
  for (const name of projectFiles) {
16767
16877
  if (seen.has(name)) continue;
16768
- const projectPath2 = path33.join(projectWorkflowsDir, name);
16878
+ const projectPath2 = path34.join(projectWorkflowsDir, name);
16769
16879
  if (!dryRun) {
16770
- fs31.unlinkSync(projectPath2);
16880
+ fs32.unlinkSync(projectPath2);
16771
16881
  }
16772
16882
  files.push({ name, outcome: "removed" });
16773
16883
  }
@@ -17365,15 +17475,15 @@ function parentForTopology(t, defaultLeaf) {
17365
17475
 
17366
17476
  // scripts/lakebase/scm-doctor.ts
17367
17477
  init_esm_shims();
17368
- import * as fs32 from "fs";
17369
- import * as path34 from "path";
17478
+ import * as fs33 from "fs";
17479
+ import * as path35 from "path";
17370
17480
  var FEATURE_PREFIX = "feature/";
17371
17481
  var TIER_LEAFS2 = DEFAULT_PROTECTED_TIER_NAMES;
17372
17482
  function readEnv(projectDir) {
17373
- const envPath = path34.join(projectDir, ".env");
17483
+ const envPath = path35.join(projectDir, ".env");
17374
17484
  const out = /* @__PURE__ */ new Map();
17375
- if (!fs32.existsSync(envPath)) return out;
17376
- const lines = fs32.readFileSync(envPath, "utf8").split("\n");
17485
+ if (!fs33.existsSync(envPath)) return out;
17486
+ const lines = fs33.readFileSync(envPath, "utf8").split("\n");
17377
17487
  for (const line of lines) {
17378
17488
  const m = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.+?)\s*$/);
17379
17489
  if (m) out.set(m[1], m[2].replace(/^["']|["']$/g, ""));
@@ -17428,9 +17538,9 @@ async function runDoctor(args, deps = {}) {
17428
17538
  }
17429
17539
  for (const wf of ["pr.yml", "merge.yml"]) {
17430
17540
  try {
17431
- const p = path34.join(projectDir, ".github", "workflows", wf);
17432
- if (!fs32.existsSync(p)) continue;
17433
- const body = fs32.readFileSync(p, "utf8");
17541
+ const p = path35.join(projectDir, ".github", "workflows", wf);
17542
+ if (!fs33.existsSync(p)) continue;
17543
+ const body = fs33.readFileSync(p, "utf8");
17434
17544
  if (/lakebase-scm-utils#v\d/.test(body)) {
17435
17545
  findings.push({
17436
17546
  id: "ci-workflow-substrate-pin",
@@ -17645,7 +17755,7 @@ async function fixFinding(args) {
17645
17755
  );
17646
17756
  }
17647
17757
  const sanitized = sanitizeBranchName(branch);
17648
- const envFile = path34.join(args.projectDir, ".env");
17758
+ const envFile = path35.join(args.projectDir, ".env");
17649
17759
  updateEnvConnection({
17650
17760
  envPath: envFile,
17651
17761
  projectId: readEnvVar(envFile, "LAKEBASE_PROJECT_ID") ?? "",
@@ -17747,14 +17857,14 @@ function shellEscape3(s) {
17747
17857
 
17748
17858
  // scripts/lakebase/doctor.ts
17749
17859
  init_esm_shims();
17750
- import * as fs33 from "fs";
17751
- import * as path35 from "path";
17860
+ import * as fs34 from "fs";
17861
+ import * as path36 from "path";
17752
17862
  import * as cp6 from "child_process";
17753
17863
  function readEnvFile(projectDir) {
17754
- const envPath = path35.join(projectDir, ".env");
17755
- if (!fs33.existsSync(envPath)) return {};
17864
+ const envPath = path36.join(projectDir, ".env");
17865
+ if (!fs34.existsSync(envPath)) return {};
17756
17866
  const out = {};
17757
- for (const line of fs33.readFileSync(envPath, "utf8").split("\n")) {
17867
+ for (const line of fs34.readFileSync(envPath, "utf8").split("\n")) {
17758
17868
  const m = line.match(/^\s*([A-Z][A-Z0-9_]*)\s*=\s*(.*)\s*$/);
17759
17869
  if (!m) continue;
17760
17870
  let val = m[2];
@@ -18026,7 +18136,7 @@ function checkEnv(projectDir) {
18026
18136
  name: "env-file",
18027
18137
  status: "warn",
18028
18138
  message: ".env not found",
18029
- detail: { projectDir, envPath: path35.join(projectDir, ".env") },
18139
+ detail: { projectDir, envPath: path36.join(projectDir, ".env") },
18030
18140
  hint: "Run `lakebase-branch sync-env`, or `git checkout <branch>` so the post-checkout hook writes .env (or copy .env.example). The kit stores connection METADATA only , no DB token (the app mints a short-lived credential at runtime)."
18031
18141
  };
18032
18142
  }