@databricks-solutions/lakebase-scm-utils 0.2.51 → 0.3.1
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/README.md +10 -4
- package/dist/scripts/index.cjs +2813 -2244
- package/dist/scripts/index.d.cts +1 -1
- package/dist/scripts/index.d.ts +1 -1
- package/dist/scripts/index.js +857 -298
- package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +2460 -2030
- package/dist/scripts/lakebase/ci-resolve-branch.cli.js +508 -81
- package/dist/scripts/lakebase/collapse-heads.cli.cjs +2429 -2007
- package/dist/scripts/lakebase/collapse-heads.cli.js +477 -58
- package/dist/scripts/lakebase/detect-language.cli.cjs +2441 -2016
- package/dist/scripts/lakebase/detect-language.cli.js +489 -67
- package/dist/scripts/lakebase/doctor.cli.cjs +2484 -2040
- package/dist/scripts/lakebase/doctor.cli.js +532 -91
- package/dist/scripts/lakebase/get-connection.cli.cjs +2 -2
- package/dist/scripts/lakebase/get-connection.cli.js +2 -2
- package/dist/scripts/lakebase/index.cjs +2810 -2205
- package/dist/scripts/lakebase/index.d.cts +59 -10
- package/dist/scripts/lakebase/index.d.ts +59 -10
- package/dist/scripts/lakebase/index.js +851 -256
- package/dist/scripts/lakebase/infra-runner.cli.cjs +2435 -2013
- package/dist/scripts/lakebase/infra-runner.cli.js +483 -64
- package/dist/scripts/lakebase/new-migration.cli.cjs +2429 -2007
- package/dist/scripts/lakebase/new-migration.cli.js +477 -58
- package/dist/scripts/lakebase/schema-diff.cli.cjs +2 -2
- package/dist/scripts/lakebase/schema-diff.cli.js +2 -2
- package/dist/scripts/lakebase/schema-migrate.cli.cjs +2461 -2029
- package/dist/scripts/lakebase/schema-migrate.cli.js +509 -80
- package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +2460 -2030
- package/dist/scripts/lakebase/scm-claim-feature.cli.js +508 -81
- package/dist/scripts/lakebase/scm-doctor.cli.cjs +2486 -2056
- package/dist/scripts/lakebase/scm-doctor.cli.js +537 -107
- package/dist/scripts/lakebase/scm-merge.cli.cjs +2443 -2021
- package/dist/scripts/lakebase/scm-merge.cli.js +494 -72
- package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +2464 -2034
- package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +511 -84
- package/dist/scripts/util/index.cjs +2 -2
- package/dist/scripts/util/index.js +2 -2
- package/package.json +1 -1
- package/scripts/lakebase/adapters/efcore-adapter.ts +158 -0
- package/scripts/lakebase/adapters/flyway-adapter.ts +8 -5
- package/scripts/lakebase/client-lockfile.ts +102 -0
- package/scripts/lakebase/collapse-heads.cli.ts +1 -1
- package/scripts/lakebase/create-project.ts +25 -2
- package/scripts/lakebase/detect-language.cli.ts +2 -2
- package/scripts/lakebase/doctor.ts +29 -0
- package/scripts/lakebase/dotnet-project.ts +112 -0
- package/scripts/lakebase/index.ts +1 -0
- package/scripts/lakebase/migration-layout.ts +43 -2
- package/scripts/lakebase/new-migration.cli.ts +1 -1
- package/scripts/lakebase/scaffold-language.ts +23 -2
- package/scripts/lakebase/scaffold.ts +4 -1
- package/scripts/lakebase/schema-migrate-runners/efcore.ts +399 -0
- package/scripts/lakebase/schema-migrate-runners/flyway.ts +6 -4
- package/scripts/lakebase/schema-migrate.cli.ts +3 -1
- package/scripts/lakebase/schema-migrate.ts +24 -10
- package/templates/project/common/.github/workflows/merge.yml +13 -1
- package/templates/project/common/.github/workflows/pr.yml +25 -5
- package/templates/project/common/scripts/flyway-migrate.sh +54 -1
- package/templates/project/common/scripts/prepare-schema-diff.sh +5 -0
- package/templates/project/common/scripts/run-dev.sh +10 -1
- package/templates/project/common/scripts/run-tests.sh +6 -1
- package/templates/project/dotnet/.gitignore.extra +8 -0
- package/templates/project/dotnet/App.sln +56 -0
- package/templates/project/dotnet/Makefile +13 -0
- package/templates/project/dotnet/global.json +6 -0
- package/templates/project/dotnet/src/App/Data/AppDbContext.cs +12 -0
- package/templates/project/dotnet/src/App/Lakebase/DotEnv.cs +48 -0
- package/templates/project/dotnet/src/App/Lakebase/LakebaseConnection.cs +225 -0
- package/templates/project/dotnet/src/App/Program.cs +34 -0
- package/templates/project/dotnet/src/App/appsettings.json +9 -0
- package/templates/project/dotnet/tests/App.Tests/App.Tests.csproj +25 -0
- package/templates/project/dotnet/tests/App.Tests/HealthTests.cs +18 -0
- package/templates/project/dotnet/tests/App.Tests/OpenApiTests.cs +23 -0
- package/templates/project/dotnet-efcore/.config/dotnet-tools.json +13 -0
- package/templates/project/dotnet-efcore/src/App/App.csproj +22 -0
- package/templates/project/dotnet-efcore/src/App/Data/DesignTimeDbContextFactory.cs +24 -0
- package/templates/project/dotnet-efcore/src/App/Migrations/README.md +23 -0
- package/templates/project/dotnet-flyway/db/migrations/README.md +23 -0
- package/templates/project/dotnet-flyway/src/App/App.csproj +17 -0
package/dist/scripts/index.js
CHANGED
|
@@ -2581,7 +2581,7 @@ paginateRest.VERSION = VERSION5;
|
|
|
2581
2581
|
|
|
2582
2582
|
// node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
|
|
2583
2583
|
init_esm_shims();
|
|
2584
|
-
var generateMessage = (
|
|
2584
|
+
var generateMessage = (path38, cursorValue) => `The cursor at "${path38.join(
|
|
2585
2585
|
","
|
|
2586
2586
|
)}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
|
|
2587
2587
|
var MissingCursorChange = class extends Error {
|
|
@@ -2622,9 +2622,9 @@ function findPaginatedResourcePath(responseData) {
|
|
|
2622
2622
|
}
|
|
2623
2623
|
return paginatedResourcePath;
|
|
2624
2624
|
}
|
|
2625
|
-
var deepFindPathToProperty = (object, searchProp,
|
|
2625
|
+
var deepFindPathToProperty = (object, searchProp, path38 = []) => {
|
|
2626
2626
|
for (const key of Object.keys(object)) {
|
|
2627
|
-
const currentPath = [...
|
|
2627
|
+
const currentPath = [...path38, key];
|
|
2628
2628
|
const currentValue = object[key];
|
|
2629
2629
|
if (isObject(currentValue)) {
|
|
2630
2630
|
if (currentValue.hasOwnProperty(searchProp)) {
|
|
@@ -2642,12 +2642,12 @@ var deepFindPathToProperty = (object, searchProp, path34 = []) => {
|
|
|
2642
2642
|
}
|
|
2643
2643
|
return [];
|
|
2644
2644
|
};
|
|
2645
|
-
var get = (object,
|
|
2646
|
-
return
|
|
2645
|
+
var get = (object, path38) => {
|
|
2646
|
+
return path38.reduce((current, nextProperty) => current[nextProperty], object);
|
|
2647
2647
|
};
|
|
2648
|
-
var set = (object,
|
|
2649
|
-
const lastProperty =
|
|
2650
|
-
const parentPath = [...
|
|
2648
|
+
var set = (object, path38, mutator) => {
|
|
2649
|
+
const lastProperty = path38[path38.length - 1];
|
|
2650
|
+
const parentPath = [...path38].slice(0, -1);
|
|
2651
2651
|
const parent = get(object, parentPath);
|
|
2652
2652
|
if (typeof mutator === "function") {
|
|
2653
2653
|
parent[lastProperty] = mutator(parent[lastProperty]);
|
|
@@ -2699,22 +2699,22 @@ var mergeResponses = (response1, response2) => {
|
|
|
2699
2699
|
if (Object.keys(response1).length === 0) {
|
|
2700
2700
|
return Object.assign(response1, response2);
|
|
2701
2701
|
}
|
|
2702
|
-
const
|
|
2703
|
-
const nodesPath = [...
|
|
2702
|
+
const path38 = findPaginatedResourcePath(response1);
|
|
2703
|
+
const nodesPath = [...path38, "nodes"];
|
|
2704
2704
|
const newNodes = get(response2, nodesPath);
|
|
2705
2705
|
if (newNodes) {
|
|
2706
2706
|
set(response1, nodesPath, (values) => {
|
|
2707
2707
|
return [...values, ...newNodes];
|
|
2708
2708
|
});
|
|
2709
2709
|
}
|
|
2710
|
-
const edgesPath = [...
|
|
2710
|
+
const edgesPath = [...path38, "edges"];
|
|
2711
2711
|
const newEdges = get(response2, edgesPath);
|
|
2712
2712
|
if (newEdges) {
|
|
2713
2713
|
set(response1, edgesPath, (values) => {
|
|
2714
2714
|
return [...values, ...newEdges];
|
|
2715
2715
|
});
|
|
2716
2716
|
}
|
|
2717
|
-
const pageInfoPath = [...
|
|
2717
|
+
const pageInfoPath = [...path38, "pageInfo"];
|
|
2718
2718
|
set(response1, pageInfoPath, get(response2, pageInfoPath));
|
|
2719
2719
|
return response1;
|
|
2720
2720
|
};
|
|
@@ -5135,7 +5135,7 @@ var triggers_notification_paths_default = [
|
|
|
5135
5135
|
];
|
|
5136
5136
|
function routeMatcher(paths) {
|
|
5137
5137
|
const regexes = paths.map(
|
|
5138
|
-
(
|
|
5138
|
+
(path38) => path38.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
|
|
5139
5139
|
);
|
|
5140
5140
|
const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
|
|
5141
5141
|
return new RegExp(regex2, "i");
|
|
@@ -8715,9 +8715,9 @@ function asBranchUid(s) {
|
|
|
8715
8715
|
}
|
|
8716
8716
|
return s;
|
|
8717
8717
|
}
|
|
8718
|
-
function branchNameFromResourcePath(
|
|
8719
|
-
if (!
|
|
8720
|
-
const leaf =
|
|
8718
|
+
function branchNameFromResourcePath(path38) {
|
|
8719
|
+
if (!path38.includes("/branches/")) return null;
|
|
8720
|
+
const leaf = path38.split("/branches/").pop();
|
|
8721
8721
|
if (!leaf) return null;
|
|
8722
8722
|
try {
|
|
8723
8723
|
return asBranchName(leaf);
|
|
@@ -9725,8 +9725,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
9725
9725
|
var cached;
|
|
9726
9726
|
function substrateSelfVersion() {
|
|
9727
9727
|
if (cached !== void 0) return cached;
|
|
9728
|
-
if ("0.
|
|
9729
|
-
cached = "0.
|
|
9728
|
+
if ("0.3.1".length > 0) {
|
|
9729
|
+
cached = "0.3.1";
|
|
9730
9730
|
return cached;
|
|
9731
9731
|
}
|
|
9732
9732
|
cached = "unknown";
|
|
@@ -11314,16 +11314,16 @@ function isAllSchemas(schema) {
|
|
|
11314
11314
|
}
|
|
11315
11315
|
function buildSchemaQuery(schema) {
|
|
11316
11316
|
const cols = "c.table_schema, c.table_name, c.column_name, c.data_type";
|
|
11317
|
-
const
|
|
11317
|
+
const join38 = "FROM information_schema.columns c JOIN pg_tables t ON c.table_name = t.tablename AND c.table_schema = t.schemaname ";
|
|
11318
11318
|
if (isAllSchemas(schema)) {
|
|
11319
11319
|
return {
|
|
11320
|
-
text: `SELECT ${cols} ` +
|
|
11320
|
+
text: `SELECT ${cols} ` + join38 + `WHERE ${SYSTEM_SCHEMA_FILTER} ORDER BY c.table_schema, c.table_name, c.ordinal_position`,
|
|
11321
11321
|
values: []
|
|
11322
11322
|
};
|
|
11323
11323
|
}
|
|
11324
11324
|
const one = (schema ?? "").trim() || "public";
|
|
11325
11325
|
return {
|
|
11326
|
-
text: `SELECT ${cols} ` +
|
|
11326
|
+
text: `SELECT ${cols} ` + join38 + "WHERE c.table_schema = $1 ORDER BY c.table_name, c.ordinal_position",
|
|
11327
11327
|
values: [one]
|
|
11328
11328
|
};
|
|
11329
11329
|
}
|
|
@@ -11483,8 +11483,8 @@ async function withLakebaseRollback(opts, fn) {
|
|
|
11483
11483
|
|
|
11484
11484
|
// scripts/lakebase/create-project.ts
|
|
11485
11485
|
init_esm_shims();
|
|
11486
|
-
import * as
|
|
11487
|
-
import * as
|
|
11486
|
+
import * as fs19 from "fs";
|
|
11487
|
+
import * as path19 from "path";
|
|
11488
11488
|
|
|
11489
11489
|
// scripts/lakebase/project-verify.ts
|
|
11490
11490
|
init_esm_shims();
|
|
@@ -11988,6 +11988,20 @@ async function deployLanguageProject(args) {
|
|
|
11988
11988
|
return;
|
|
11989
11989
|
}
|
|
11990
11990
|
const templatesDir = args.templatesDir ?? findTemplatesDir2();
|
|
11991
|
+
if (args.language === "dotnet") {
|
|
11992
|
+
const tool = args.migrationTool ?? "efcore";
|
|
11993
|
+
if (tool !== "efcore" && tool !== "flyway") {
|
|
11994
|
+
throw new Error(`Unsupported .NET migration tool: ${String(tool)} (expected efcore or flyway)`);
|
|
11995
|
+
}
|
|
11996
|
+
const base = path10.join(templatesDir, "dotnet");
|
|
11997
|
+
const overlay = path10.join(templatesDir, `dotnet-${tool}`);
|
|
11998
|
+
if (!fs11.existsSync(base) || !fs11.existsSync(overlay)) {
|
|
11999
|
+
throw new Error(`No template found for language: dotnet (${tool})`);
|
|
12000
|
+
}
|
|
12001
|
+
copyDirSubstituted(base, args.targetDir, { projectName: args.projectName });
|
|
12002
|
+
copyDirSubstituted(overlay, args.targetDir, { projectName: args.projectName });
|
|
12003
|
+
return;
|
|
12004
|
+
}
|
|
11991
12005
|
const langSrc = path10.join(templatesDir, args.language);
|
|
11992
12006
|
if (!fs11.existsSync(langSrc)) {
|
|
11993
12007
|
throw new Error(`No template found for language: ${args.language}`);
|
|
@@ -12407,6 +12421,7 @@ async function scaffoldAll(args) {
|
|
|
12407
12421
|
targetDir: args.targetDir,
|
|
12408
12422
|
language,
|
|
12409
12423
|
projectName,
|
|
12424
|
+
migrationTool: args.migrationTool,
|
|
12410
12425
|
templatesDir: args.templatesDir,
|
|
12411
12426
|
initializrClient: args.initializrClient,
|
|
12412
12427
|
report
|
|
@@ -12739,18 +12754,100 @@ function enableE2eForProject(args) {
|
|
|
12739
12754
|
};
|
|
12740
12755
|
}
|
|
12741
12756
|
|
|
12742
|
-
// scripts/lakebase/
|
|
12757
|
+
// scripts/lakebase/client-lockfile.ts
|
|
12743
12758
|
init_esm_shims();
|
|
12744
12759
|
import * as fs15 from "fs";
|
|
12745
12760
|
import * as path14 from "path";
|
|
12761
|
+
|
|
12762
|
+
// scripts/util/proxy-env.ts
|
|
12763
|
+
init_esm_shims();
|
|
12764
|
+
var PROXY_ENV_KEYS = [
|
|
12765
|
+
"HTTP_PROXY",
|
|
12766
|
+
"HTTPS_PROXY",
|
|
12767
|
+
"NO_PROXY",
|
|
12768
|
+
"http_proxy",
|
|
12769
|
+
"https_proxy",
|
|
12770
|
+
"no_proxy",
|
|
12771
|
+
"npm_config_proxy",
|
|
12772
|
+
"npm_config_https_proxy",
|
|
12773
|
+
"npm_config_no_proxy",
|
|
12774
|
+
"npm_config_registry"
|
|
12775
|
+
];
|
|
12776
|
+
function proxyEnvSubset(source = process.env) {
|
|
12777
|
+
const out = {};
|
|
12778
|
+
for (const key of PROXY_ENV_KEYS) {
|
|
12779
|
+
const v = source[key];
|
|
12780
|
+
if (v !== void 0 && v !== "") {
|
|
12781
|
+
out[key] = v;
|
|
12782
|
+
}
|
|
12783
|
+
}
|
|
12784
|
+
return out;
|
|
12785
|
+
}
|
|
12786
|
+
function withProxyEnv(base = {}) {
|
|
12787
|
+
const out = {};
|
|
12788
|
+
const inherited = proxyEnvSubset();
|
|
12789
|
+
for (const [k, v] of Object.entries(inherited)) {
|
|
12790
|
+
out[k] = v;
|
|
12791
|
+
}
|
|
12792
|
+
for (const [k, v] of Object.entries(base)) {
|
|
12793
|
+
if (v !== void 0) out[k] = v;
|
|
12794
|
+
}
|
|
12795
|
+
return out;
|
|
12796
|
+
}
|
|
12797
|
+
|
|
12798
|
+
// scripts/lakebase/client-lockfile.ts
|
|
12799
|
+
var PROXY_HOST = "npm-proxy.cloud.databricks.com";
|
|
12800
|
+
var PUBLIC_HOST = "registry.npmjs.org";
|
|
12801
|
+
function normalizeLockfileRegistry(lockText) {
|
|
12802
|
+
let swaps = 0;
|
|
12803
|
+
const text = lockText.replace(new RegExp(PROXY_HOST.replace(/\./g, "\\."), "g"), () => {
|
|
12804
|
+
swaps++;
|
|
12805
|
+
return PUBLIC_HOST;
|
|
12806
|
+
});
|
|
12807
|
+
return { text, swaps };
|
|
12808
|
+
}
|
|
12809
|
+
async function ensureClientLockfile(args) {
|
|
12810
|
+
const clientDir = path14.join(args.projectDir, args.clientDir ?? "client");
|
|
12811
|
+
const pkg = path14.join(clientDir, "package.json");
|
|
12812
|
+
if (!fs15.existsSync(pkg)) {
|
|
12813
|
+
return { generated: false, swaps: 0, reason: "no client package.json" };
|
|
12814
|
+
}
|
|
12815
|
+
const lockPath = path14.join(clientDir, "package-lock.json");
|
|
12816
|
+
try {
|
|
12817
|
+
await exec2("npm install --package-lock-only", {
|
|
12818
|
+
cwd: clientDir,
|
|
12819
|
+
env: withProxyEnv(),
|
|
12820
|
+
timeout: 18e4
|
|
12821
|
+
});
|
|
12822
|
+
} catch (err) {
|
|
12823
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
12824
|
+
return { generated: fs15.existsSync(lockPath), swaps: 0, reason: `npm resolve failed: ${msg}` };
|
|
12825
|
+
}
|
|
12826
|
+
if (!fs15.existsSync(lockPath)) {
|
|
12827
|
+
return { generated: false, swaps: 0, reason: "npm wrote no package-lock.json" };
|
|
12828
|
+
}
|
|
12829
|
+
try {
|
|
12830
|
+
const { text, swaps } = normalizeLockfileRegistry(fs15.readFileSync(lockPath, "utf8"));
|
|
12831
|
+
if (swaps > 0) fs15.writeFileSync(lockPath, text);
|
|
12832
|
+
return { generated: true, swaps };
|
|
12833
|
+
} catch (err) {
|
|
12834
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
12835
|
+
return { generated: true, swaps: 0, reason: `lock normalize failed: ${msg}` };
|
|
12836
|
+
}
|
|
12837
|
+
}
|
|
12838
|
+
|
|
12839
|
+
// scripts/lakebase/enable-infra.ts
|
|
12840
|
+
init_esm_shims();
|
|
12841
|
+
import * as fs16 from "fs";
|
|
12842
|
+
import * as path15 from "path";
|
|
12746
12843
|
var RUN_TESTS_INFRA_MARKER = "# Run Lakebase [Infra]-tag suite when wired";
|
|
12747
12844
|
function addInfraToPackageJson(args) {
|
|
12748
|
-
const pkgPath =
|
|
12749
|
-
if (!
|
|
12845
|
+
const pkgPath = path15.join(args.projectDir, "package.json");
|
|
12846
|
+
if (!fs16.existsSync(pkgPath)) {
|
|
12750
12847
|
return { patched: false, scriptAdded: false };
|
|
12751
12848
|
}
|
|
12752
12849
|
const scriptValue = args.scriptValue ?? "npx --yes lakebase-infra-runner";
|
|
12753
|
-
const raw =
|
|
12850
|
+
const raw = fs16.readFileSync(pkgPath, "utf8");
|
|
12754
12851
|
const pkg = JSON.parse(raw);
|
|
12755
12852
|
const scripts = pkg.scripts ?? {};
|
|
12756
12853
|
let scriptAdded = false;
|
|
@@ -12761,16 +12858,16 @@ function addInfraToPackageJson(args) {
|
|
|
12761
12858
|
pkg.scripts = scripts;
|
|
12762
12859
|
if (scriptAdded) {
|
|
12763
12860
|
const trailing = raw.endsWith("\n") ? "\n" : "";
|
|
12764
|
-
|
|
12861
|
+
fs16.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + trailing, "utf8");
|
|
12765
12862
|
}
|
|
12766
12863
|
return { patched: true, scriptAdded };
|
|
12767
12864
|
}
|
|
12768
12865
|
function addInfraToRunTestsScript(args) {
|
|
12769
|
-
const scriptPath =
|
|
12770
|
-
if (!
|
|
12866
|
+
const scriptPath = path15.join(args.projectDir, "scripts", "run-tests.sh");
|
|
12867
|
+
if (!fs16.existsSync(scriptPath)) {
|
|
12771
12868
|
return { patched: false, inserted: false };
|
|
12772
12869
|
}
|
|
12773
|
-
const original =
|
|
12870
|
+
const original = fs16.readFileSync(scriptPath, "utf8");
|
|
12774
12871
|
if (original.includes(RUN_TESTS_INFRA_MARKER)) {
|
|
12775
12872
|
return { patched: true, inserted: false };
|
|
12776
12873
|
}
|
|
@@ -12786,7 +12883,7 @@ function addInfraToRunTestsScript(args) {
|
|
|
12786
12883
|
"fi",
|
|
12787
12884
|
""
|
|
12788
12885
|
].join("\n");
|
|
12789
|
-
|
|
12886
|
+
fs16.writeFileSync(scriptPath, trimmed + block, "utf8");
|
|
12790
12887
|
return { patched: true, inserted: true };
|
|
12791
12888
|
}
|
|
12792
12889
|
function enableInfraForProject(args) {
|
|
@@ -12800,9 +12897,9 @@ function enableInfraForProject(args) {
|
|
|
12800
12897
|
|
|
12801
12898
|
// scripts/lakebase/runner-setup.ts
|
|
12802
12899
|
init_esm_shims();
|
|
12803
|
-
import * as
|
|
12900
|
+
import * as fs17 from "fs";
|
|
12804
12901
|
import * as os from "os";
|
|
12805
|
-
import * as
|
|
12902
|
+
import * as path16 from "path";
|
|
12806
12903
|
import * as cp4 from "child_process";
|
|
12807
12904
|
import * as tar from "tar";
|
|
12808
12905
|
import findJavaHome from "find-java-home";
|
|
@@ -12813,28 +12910,28 @@ var RUNNER_OS = process.platform === "darwin" ? "osx" : "linux";
|
|
|
12813
12910
|
var RUNNER_ARCHIVE = `actions-runner-${RUNNER_OS}-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz`;
|
|
12814
12911
|
var RUNNER_URL = `https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/${RUNNER_ARCHIVE}`;
|
|
12815
12912
|
function cacheDir() {
|
|
12816
|
-
return
|
|
12913
|
+
return path16.join(os.homedir(), ".cache", "github-actions-runner");
|
|
12817
12914
|
}
|
|
12818
12915
|
function runnersDir() {
|
|
12819
|
-
return
|
|
12916
|
+
return path16.join(os.homedir(), ".lakebase", "runners");
|
|
12820
12917
|
}
|
|
12821
12918
|
function runnerDir(projectName) {
|
|
12822
|
-
return
|
|
12919
|
+
return path16.join(runnersDir(), projectName);
|
|
12823
12920
|
}
|
|
12824
12921
|
function runnerName(projectName) {
|
|
12825
12922
|
return `lakebase-${projectName}`;
|
|
12826
12923
|
}
|
|
12827
12924
|
async function ensureCachedArchive() {
|
|
12828
12925
|
const dir = cacheDir();
|
|
12829
|
-
|
|
12830
|
-
const cachedPath =
|
|
12831
|
-
if (
|
|
12926
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
12927
|
+
const cachedPath = path16.join(dir, RUNNER_ARCHIVE);
|
|
12928
|
+
if (fs17.existsSync(cachedPath)) return cachedPath;
|
|
12832
12929
|
const response = await fetch(RUNNER_URL);
|
|
12833
12930
|
if (!response.ok) {
|
|
12834
12931
|
throw new Error(`Failed to download runner: HTTP ${response.status}`);
|
|
12835
12932
|
}
|
|
12836
12933
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
12837
|
-
|
|
12934
|
+
fs17.writeFileSync(cachedPath, buffer);
|
|
12838
12935
|
return cachedPath;
|
|
12839
12936
|
}
|
|
12840
12937
|
async function resolveJavaHome() {
|
|
@@ -12844,9 +12941,9 @@ async function resolveJavaHome() {
|
|
|
12844
12941
|
});
|
|
12845
12942
|
}
|
|
12846
12943
|
function isRunning(projectName) {
|
|
12847
|
-
const pidFile =
|
|
12848
|
-
if (!
|
|
12849
|
-
const pid = parseInt(
|
|
12944
|
+
const pidFile = path16.join(runnerDir(projectName), ".pid");
|
|
12945
|
+
if (!fs17.existsSync(pidFile)) return false;
|
|
12946
|
+
const pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
12850
12947
|
if (!pid) return false;
|
|
12851
12948
|
try {
|
|
12852
12949
|
process.kill(pid, 0);
|
|
@@ -12857,23 +12954,23 @@ function isRunning(projectName) {
|
|
|
12857
12954
|
}
|
|
12858
12955
|
function getRunnerInfo(projectName) {
|
|
12859
12956
|
const dir = runnerDir(projectName);
|
|
12860
|
-
if (!
|
|
12861
|
-
const pidFile =
|
|
12957
|
+
if (!fs17.existsSync(dir)) return void 0;
|
|
12958
|
+
const pidFile = path16.join(dir, ".pid");
|
|
12862
12959
|
let pid;
|
|
12863
|
-
if (
|
|
12864
|
-
pid = parseInt(
|
|
12960
|
+
if (fs17.existsSync(pidFile)) {
|
|
12961
|
+
pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
12865
12962
|
}
|
|
12866
12963
|
return { name: runnerName(projectName), dir, pid, online: isRunning(projectName) };
|
|
12867
12964
|
}
|
|
12868
12965
|
var lastRunnerPid;
|
|
12869
12966
|
function stopRunner(projectName) {
|
|
12870
12967
|
const dir = runnerDir(projectName);
|
|
12871
|
-
const pidFile =
|
|
12968
|
+
const pidFile = path16.join(dir, ".pid");
|
|
12872
12969
|
let pid = lastRunnerPid;
|
|
12873
|
-
if (
|
|
12874
|
-
pid = parseInt(
|
|
12970
|
+
if (fs17.existsSync(pidFile)) {
|
|
12971
|
+
pid = parseInt(fs17.readFileSync(pidFile, "utf-8").trim(), 10);
|
|
12875
12972
|
try {
|
|
12876
|
-
|
|
12973
|
+
fs17.unlinkSync(pidFile);
|
|
12877
12974
|
} catch {
|
|
12878
12975
|
}
|
|
12879
12976
|
}
|
|
@@ -12886,7 +12983,7 @@ function stopRunner(projectName) {
|
|
|
12886
12983
|
} catch {
|
|
12887
12984
|
}
|
|
12888
12985
|
}
|
|
12889
|
-
} else if (
|
|
12986
|
+
} else if (fs17.existsSync(dir)) {
|
|
12890
12987
|
try {
|
|
12891
12988
|
cp4.execSync(`pkill -9 -f "${dir.replace(/\//g, "\\/")}.*Runner" 2>/dev/null || true`, {
|
|
12892
12989
|
timeout: KIT_TIMEOUTS.cmdShort
|
|
@@ -12896,16 +12993,16 @@ function stopRunner(projectName) {
|
|
|
12896
12993
|
}
|
|
12897
12994
|
lastRunnerPid = void 0;
|
|
12898
12995
|
for (const stale of ["_diag/pages", "_work/_temp", "_work/_actions"]) {
|
|
12899
|
-
const full =
|
|
12900
|
-
if (
|
|
12996
|
+
const full = path16.join(dir, stale);
|
|
12997
|
+
if (fs17.existsSync(full)) {
|
|
12901
12998
|
try {
|
|
12902
|
-
|
|
12999
|
+
fs17.rmSync(full, { recursive: true, force: true });
|
|
12903
13000
|
} catch {
|
|
12904
13001
|
}
|
|
12905
13002
|
}
|
|
12906
13003
|
}
|
|
12907
13004
|
try {
|
|
12908
|
-
|
|
13005
|
+
fs17.mkdirSync(path16.join(dir, "_diag", "pages"), { recursive: true });
|
|
12909
13006
|
} catch {
|
|
12910
13007
|
}
|
|
12911
13008
|
}
|
|
@@ -12921,24 +13018,24 @@ function resetRunnerConfig(dir, projectName) {
|
|
|
12921
13018
|
];
|
|
12922
13019
|
for (const f of stateFiles) {
|
|
12923
13020
|
try {
|
|
12924
|
-
|
|
13021
|
+
fs17.unlinkSync(path16.join(dir, f));
|
|
12925
13022
|
} catch {
|
|
12926
13023
|
}
|
|
12927
13024
|
}
|
|
12928
13025
|
if (process.platform === "darwin") {
|
|
12929
|
-
const plist =
|
|
13026
|
+
const plist = path16.join(
|
|
12930
13027
|
os.homedir(),
|
|
12931
13028
|
"Library",
|
|
12932
13029
|
"LaunchAgents",
|
|
12933
13030
|
`actions.runner.${projectName}.plist`
|
|
12934
13031
|
);
|
|
12935
|
-
if (
|
|
13032
|
+
if (fs17.existsSync(plist)) {
|
|
12936
13033
|
try {
|
|
12937
13034
|
cp4.execFileSync("launchctl", ["unload", plist], { stdio: "ignore" });
|
|
12938
13035
|
} catch {
|
|
12939
13036
|
}
|
|
12940
13037
|
try {
|
|
12941
|
-
|
|
13038
|
+
fs17.unlinkSync(plist);
|
|
12942
13039
|
} catch {
|
|
12943
13040
|
}
|
|
12944
13041
|
}
|
|
@@ -12952,24 +13049,24 @@ async function setupRunner(args) {
|
|
|
12952
13049
|
stopRunner(args.projectName);
|
|
12953
13050
|
report("Downloading runner binary...");
|
|
12954
13051
|
const archive = await ensureCachedArchive();
|
|
12955
|
-
|
|
12956
|
-
if (!
|
|
13052
|
+
fs17.mkdirSync(dir, { recursive: true });
|
|
13053
|
+
if (!fs17.existsSync(path16.join(dir, "config.sh"))) {
|
|
12957
13054
|
report("Extracting runner...");
|
|
12958
13055
|
await tar.extract({ file: archive, cwd: dir });
|
|
12959
13056
|
}
|
|
12960
|
-
const diagPages =
|
|
12961
|
-
if (
|
|
12962
|
-
|
|
12963
|
-
|
|
13057
|
+
const diagPages = path16.join(dir, "_diag", "pages");
|
|
13058
|
+
if (fs17.existsSync(diagPages)) {
|
|
13059
|
+
fs17.rmSync(diagPages, { recursive: true, force: true });
|
|
13060
|
+
fs17.mkdirSync(diagPages, { recursive: true });
|
|
12964
13061
|
}
|
|
12965
|
-
const runnerFile =
|
|
12966
|
-
let needsConfig = !
|
|
13062
|
+
const runnerFile = path16.join(dir, ".runner");
|
|
13063
|
+
let needsConfig = !fs17.existsSync(runnerFile);
|
|
12967
13064
|
if (needsConfig) {
|
|
12968
13065
|
resetRunnerConfig(dir, args.projectName);
|
|
12969
13066
|
} else {
|
|
12970
13067
|
let urlMismatch = false;
|
|
12971
13068
|
try {
|
|
12972
|
-
const runnerJson = JSON.parse(
|
|
13069
|
+
const runnerJson = JSON.parse(fs17.readFileSync(runnerFile, "utf-8"));
|
|
12973
13070
|
const configuredUrl = runnerJson.gitHubUrl || runnerJson.serverUrl || runnerJson.agentUrl || "";
|
|
12974
13071
|
const expectedUrl = `https://github.com/${args.fullRepoName}`;
|
|
12975
13072
|
urlMismatch = !!configuredUrl && !configuredUrl.startsWith(expectedUrl);
|
|
@@ -13030,7 +13127,7 @@ async function setupRunner(args) {
|
|
|
13030
13127
|
child.unref();
|
|
13031
13128
|
lastRunnerPid = child.pid;
|
|
13032
13129
|
if (child.pid) {
|
|
13033
|
-
|
|
13130
|
+
fs17.writeFileSync(path16.join(dir, ".pid"), String(child.pid));
|
|
13034
13131
|
}
|
|
13035
13132
|
report("Waiting for runner to come online...");
|
|
13036
13133
|
let online = false;
|
|
@@ -13062,14 +13159,14 @@ async function removeRunner(args) {
|
|
|
13062
13159
|
} catch {
|
|
13063
13160
|
}
|
|
13064
13161
|
try {
|
|
13065
|
-
|
|
13162
|
+
fs17.rmSync(dir, { recursive: true, force: true });
|
|
13066
13163
|
} catch {
|
|
13067
13164
|
}
|
|
13068
13165
|
}
|
|
13069
13166
|
|
|
13070
13167
|
// scripts/util/ci-secrets.ts
|
|
13071
13168
|
init_esm_shims();
|
|
13072
|
-
import * as
|
|
13169
|
+
import * as path17 from "path";
|
|
13073
13170
|
|
|
13074
13171
|
// scripts/git/remote.ts
|
|
13075
13172
|
init_esm_shims();
|
|
@@ -13245,7 +13342,7 @@ async function ensureCiSecretsFresh(args) {
|
|
|
13245
13342
|
return { action: "ok", reason: "CI token is current." };
|
|
13246
13343
|
}
|
|
13247
13344
|
async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
|
|
13248
|
-
const envPath =
|
|
13345
|
+
const envPath = path17.join(projectDir, ".env");
|
|
13249
13346
|
const databricksHost = readEnvVar(envPath, "DATABRICKS_HOST");
|
|
13250
13347
|
const lakebaseProjectId = readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
|
|
13251
13348
|
if (!databricksHost || !lakebaseProjectId) {
|
|
@@ -13272,8 +13369,8 @@ async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
|
|
|
13272
13369
|
|
|
13273
13370
|
// scripts/lakebase/scm-workflow-state.ts
|
|
13274
13371
|
init_esm_shims();
|
|
13275
|
-
import * as
|
|
13276
|
-
import * as
|
|
13372
|
+
import * as fs18 from "fs";
|
|
13373
|
+
import * as path18 from "path";
|
|
13277
13374
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
13278
13375
|
function isGitTracked(projectDir, rel) {
|
|
13279
13376
|
try {
|
|
@@ -13292,11 +13389,11 @@ function ensureWorkflowStateUntracked(projectDir) {
|
|
|
13292
13389
|
} catch {
|
|
13293
13390
|
}
|
|
13294
13391
|
try {
|
|
13295
|
-
const gitignore =
|
|
13296
|
-
const existing =
|
|
13392
|
+
const gitignore = path18.join(projectDir, ".gitignore");
|
|
13393
|
+
const existing = fs18.existsSync(gitignore) ? fs18.readFileSync(gitignore, "utf8") : "";
|
|
13297
13394
|
if (!existing.split("\n").some((l) => l.trim() === rel)) {
|
|
13298
13395
|
const sep4 = existing === "" || existing.endsWith("\n") ? "" : "\n";
|
|
13299
|
-
|
|
13396
|
+
fs18.appendFileSync(
|
|
13300
13397
|
gitignore,
|
|
13301
13398
|
`${sep4}# Runtime SCM claim state (per working tree): a branch checkout must never restore
|
|
13302
13399
|
# a stale committed claim over the live one (issue #203 / Finding 28).
|
|
@@ -13320,12 +13417,12 @@ var STATE_INDEX = SCM_STATES.reduce(
|
|
|
13320
13417
|
);
|
|
13321
13418
|
var STATE_FILE_REL = ".lakebase/workflow-state.json";
|
|
13322
13419
|
function stateFilePath(projectDir) {
|
|
13323
|
-
return
|
|
13420
|
+
return path18.join(projectDir, STATE_FILE_REL);
|
|
13324
13421
|
}
|
|
13325
13422
|
function readWorkflowState(projectDir) {
|
|
13326
13423
|
const p = stateFilePath(projectDir);
|
|
13327
|
-
if (!
|
|
13328
|
-
const raw =
|
|
13424
|
+
if (!fs18.existsSync(p)) return null;
|
|
13425
|
+
const raw = fs18.readFileSync(p, "utf8");
|
|
13329
13426
|
let parsed;
|
|
13330
13427
|
try {
|
|
13331
13428
|
parsed = JSON.parse(raw);
|
|
@@ -13360,14 +13457,14 @@ function writeWorkflowState(projectDir, state) {
|
|
|
13360
13457
|
${summary}`);
|
|
13361
13458
|
}
|
|
13362
13459
|
ensureWorkflowStateUntracked(projectDir);
|
|
13363
|
-
const dir =
|
|
13364
|
-
|
|
13460
|
+
const dir = path18.join(projectDir, ".lakebase");
|
|
13461
|
+
fs18.mkdirSync(dir, { recursive: true });
|
|
13365
13462
|
const target = stateFilePath(projectDir);
|
|
13366
13463
|
const tmp = `${target}.tmp`;
|
|
13367
13464
|
const ordered = orderForOutput(result.value);
|
|
13368
|
-
|
|
13465
|
+
fs18.writeFileSync(tmp, `${JSON.stringify(ordered, null, 2)}
|
|
13369
13466
|
`, "utf8");
|
|
13370
|
-
|
|
13467
|
+
fs18.renameSync(tmp, target);
|
|
13371
13468
|
}
|
|
13372
13469
|
function initWorkflowState(args) {
|
|
13373
13470
|
return {
|
|
@@ -13591,7 +13688,7 @@ function orderForOutput(state) {
|
|
|
13591
13688
|
async function createProject(input, progress) {
|
|
13592
13689
|
const report = progress ?? (() => {
|
|
13593
13690
|
});
|
|
13594
|
-
const projectDir =
|
|
13691
|
+
const projectDir = path19.join(input.parentDir, input.projectName);
|
|
13595
13692
|
const lakebaseProjectId = input.projectName;
|
|
13596
13693
|
const host = input.databricksHost.replace(/\/+$/, "");
|
|
13597
13694
|
const useGithub = input.createGithubRepo !== false;
|
|
@@ -13616,7 +13713,7 @@ async function createProject(input, progress) {
|
|
|
13616
13713
|
useGithub,
|
|
13617
13714
|
githubOwner: input.githubOwner,
|
|
13618
13715
|
tiers,
|
|
13619
|
-
dirExists: (p) =>
|
|
13716
|
+
dirExists: (p) => fs19.existsSync(p),
|
|
13620
13717
|
dirIsEmpty
|
|
13621
13718
|
});
|
|
13622
13719
|
if (!v.ok) throw new Error(v.reason);
|
|
@@ -13685,7 +13782,7 @@ Last probe error:
|
|
|
13685
13782
|
});
|
|
13686
13783
|
} else {
|
|
13687
13784
|
report("Creating local project directory...", projectDir);
|
|
13688
|
-
|
|
13785
|
+
fs19.mkdirSync(projectDir, { recursive: true });
|
|
13689
13786
|
await gitInit(projectDir);
|
|
13690
13787
|
}
|
|
13691
13788
|
report("Creating Lakebase database (provisioning Postgres)...", lakebaseProjectId);
|
|
@@ -13704,6 +13801,7 @@ Last probe error:
|
|
|
13704
13801
|
databricksHost: host,
|
|
13705
13802
|
lakebaseProjectId,
|
|
13706
13803
|
language,
|
|
13804
|
+
migrationTool: input.migrationTool,
|
|
13707
13805
|
runnerType,
|
|
13708
13806
|
skipCommands,
|
|
13709
13807
|
clientFramework,
|
|
@@ -13818,9 +13916,9 @@ Last probe error:
|
|
|
13818
13916
|
const scmRef = envRef || (ver !== "unknown" ? `v${ver}` : "");
|
|
13819
13917
|
if (scmRef) {
|
|
13820
13918
|
try {
|
|
13821
|
-
const dir =
|
|
13822
|
-
|
|
13823
|
-
|
|
13919
|
+
const dir = path19.join(projectDir, ".lakebase");
|
|
13920
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
13921
|
+
fs19.writeFileSync(path19.join(dir, "scm-utils-ref"), `${scmRef}
|
|
13824
13922
|
`, "utf8");
|
|
13825
13923
|
} catch (err) {
|
|
13826
13924
|
warnings.push(`Substrate ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
|
|
@@ -13831,9 +13929,9 @@ Last probe error:
|
|
|
13831
13929
|
const kitRef = process.env.LAKEBASE_KIT_REF?.trim();
|
|
13832
13930
|
if (kitRef) {
|
|
13833
13931
|
try {
|
|
13834
|
-
const dir =
|
|
13835
|
-
|
|
13836
|
-
|
|
13932
|
+
const dir = path19.join(projectDir, ".lakebase");
|
|
13933
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
13934
|
+
fs19.writeFileSync(path19.join(dir, "kit-ref"), `${kitRef}
|
|
13837
13935
|
`, "utf8");
|
|
13838
13936
|
} catch (err) {
|
|
13839
13937
|
warnings.push(`Kit ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
|
|
@@ -13847,9 +13945,21 @@ Last probe error:
|
|
|
13847
13945
|
java: "Java/Spring Boot",
|
|
13848
13946
|
kotlin: "Kotlin/Spring Boot",
|
|
13849
13947
|
python: "Python/FastAPI",
|
|
13850
|
-
nodejs: "Node.js/Express"
|
|
13948
|
+
nodejs: "Node.js/Express",
|
|
13949
|
+
dotnet: `.NET/ASP.NET Core (${input.migrationTool === "flyway" ? "Flyway" : "EF Core"})`
|
|
13851
13950
|
};
|
|
13852
13951
|
const langLabel = langLabels[language] ?? language;
|
|
13952
|
+
if (clientFramework !== "none") {
|
|
13953
|
+
report("Generating client package-lock.json (registry-normalized)...");
|
|
13954
|
+
const lock = await ensureClientLockfile({ projectDir });
|
|
13955
|
+
if (lock.generated) {
|
|
13956
|
+
report(` wrote client/package-lock.json${lock.swaps > 0 ? ` (normalized ${lock.swaps} proxy URL(s) to the public registry)` : ""}`);
|
|
13957
|
+
} else {
|
|
13958
|
+
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.`;
|
|
13959
|
+
warnings.push(m);
|
|
13960
|
+
report(`WARNING: ${m}`);
|
|
13961
|
+
}
|
|
13962
|
+
}
|
|
13853
13963
|
report("Creating initial commit...");
|
|
13854
13964
|
await commitAndPush({
|
|
13855
13965
|
projectDir,
|
|
@@ -13914,17 +14024,17 @@ Last probe error:
|
|
|
13914
14024
|
// scripts/lakebase/adopt-lakebase-project.ts
|
|
13915
14025
|
init_esm_shims();
|
|
13916
14026
|
import * as cp5 from "child_process";
|
|
13917
|
-
import * as
|
|
13918
|
-
import * as
|
|
14027
|
+
import * as fs20 from "fs";
|
|
14028
|
+
import * as path20 from "path";
|
|
13919
14029
|
async function adoptLakebaseProject(args) {
|
|
13920
14030
|
const warnings = [];
|
|
13921
14031
|
const filesWritten = [];
|
|
13922
14032
|
const dryRun = args.dryRun === true;
|
|
13923
14033
|
const preserveExistingEnv = args.preserveExistingEnv !== false;
|
|
13924
|
-
if (!
|
|
14034
|
+
if (!fs20.existsSync(args.projectDir)) {
|
|
13925
14035
|
throw new Error(`adoptLakebaseProject: project directory does not exist: ${args.projectDir}`);
|
|
13926
14036
|
}
|
|
13927
|
-
if (!
|
|
14037
|
+
if (!fs20.existsSync(path20.join(args.projectDir, ".git"))) {
|
|
13928
14038
|
throw new Error(
|
|
13929
14039
|
`adoptLakebaseProject: ${args.projectDir} is not a git repo. Run \`git init\` first, or pass an existing repo path.`
|
|
13930
14040
|
);
|
|
@@ -13990,9 +14100,9 @@ async function adoptLakebaseProject(args) {
|
|
|
13990
14100
|
};
|
|
13991
14101
|
}
|
|
13992
14102
|
function assertEnvCompatibility(projectDir, expectedProjectId) {
|
|
13993
|
-
const envPath =
|
|
13994
|
-
if (!
|
|
13995
|
-
const content =
|
|
14103
|
+
const envPath = path20.join(projectDir, ".env");
|
|
14104
|
+
if (!fs20.existsSync(envPath)) return;
|
|
14105
|
+
const content = fs20.readFileSync(envPath, "utf8");
|
|
13996
14106
|
const match = content.match(/^LAKEBASE_PROJECT_ID\s*=\s*(.+?)\s*$/m);
|
|
13997
14107
|
if (!match) return;
|
|
13998
14108
|
const existing = match[1].trim().replace(/^['"]|['"]$/g, "");
|
|
@@ -14003,10 +14113,10 @@ function assertEnvCompatibility(projectDir, expectedProjectId) {
|
|
|
14003
14113
|
}
|
|
14004
14114
|
}
|
|
14005
14115
|
function assertAdoptionPreflight(args) {
|
|
14006
|
-
if (!
|
|
14116
|
+
if (!fs20.existsSync(args.projectDir)) {
|
|
14007
14117
|
throw new Error(`assertAdoptionPreflight: project directory does not exist: ${args.projectDir}`);
|
|
14008
14118
|
}
|
|
14009
|
-
if (!
|
|
14119
|
+
if (!fs20.existsSync(path20.join(args.projectDir, ".git"))) {
|
|
14010
14120
|
throw new Error(
|
|
14011
14121
|
`assertAdoptionPreflight: ${args.projectDir} is not a git repo.`
|
|
14012
14122
|
);
|
|
@@ -14016,11 +14126,11 @@ function assertAdoptionPreflight(args) {
|
|
|
14016
14126
|
}
|
|
14017
14127
|
}
|
|
14018
14128
|
function _testMakeBrownfieldFixture(opts) {
|
|
14019
|
-
|
|
14129
|
+
fs20.mkdirSync(opts.dir, { recursive: true });
|
|
14020
14130
|
cp5.execSync("git init --quiet", { cwd: opts.dir, stdio: "pipe" });
|
|
14021
14131
|
if (opts.packageJson) {
|
|
14022
|
-
|
|
14023
|
-
|
|
14132
|
+
fs20.writeFileSync(
|
|
14133
|
+
path20.join(opts.dir, "package.json"),
|
|
14024
14134
|
JSON.stringify(opts.packageJson, null, 2) + "\n"
|
|
14025
14135
|
);
|
|
14026
14136
|
}
|
|
@@ -14028,8 +14138,8 @@ function _testMakeBrownfieldFixture(opts) {
|
|
|
14028
14138
|
|
|
14029
14139
|
// scripts/lakebase/infra-runner.ts
|
|
14030
14140
|
init_esm_shims();
|
|
14031
|
-
import * as
|
|
14032
|
-
import * as
|
|
14141
|
+
import * as fs30 from "fs";
|
|
14142
|
+
import * as path32 from "path";
|
|
14033
14143
|
|
|
14034
14144
|
// scripts/lakebase/schema-diff.ts
|
|
14035
14145
|
init_esm_shims();
|
|
@@ -14225,18 +14335,84 @@ function dbcli6(args) {
|
|
|
14225
14335
|
|
|
14226
14336
|
// scripts/lakebase/schema-migrate.ts
|
|
14227
14337
|
init_esm_shims();
|
|
14228
|
-
import * as
|
|
14229
|
-
import * as
|
|
14338
|
+
import * as fs29 from "fs";
|
|
14339
|
+
import * as path31 from "path";
|
|
14230
14340
|
|
|
14231
14341
|
// scripts/lakebase/migration-layout.ts
|
|
14232
14342
|
init_esm_shims();
|
|
14233
|
-
import * as
|
|
14234
|
-
import * as
|
|
14343
|
+
import * as fs22 from "fs";
|
|
14344
|
+
import * as path22 from "path";
|
|
14345
|
+
|
|
14346
|
+
// scripts/lakebase/dotnet-project.ts
|
|
14347
|
+
init_esm_shims();
|
|
14348
|
+
import * as fs21 from "fs";
|
|
14349
|
+
import * as path21 from "path";
|
|
14350
|
+
var EF_DESIGN_PACKAGE = "Microsoft.EntityFrameworkCore.Design";
|
|
14351
|
+
var DOTNET_FLYWAY_DIR = path21.join("db", "migrations");
|
|
14352
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["bin", "obj", "node_modules", ".git", "client", "tests", "test"]);
|
|
14353
|
+
function safeReaddir(dir) {
|
|
14354
|
+
try {
|
|
14355
|
+
return fs21.readdirSync(dir, { withFileTypes: true });
|
|
14356
|
+
} catch {
|
|
14357
|
+
return [];
|
|
14358
|
+
}
|
|
14359
|
+
}
|
|
14360
|
+
function hasDotnetMarker(dir) {
|
|
14361
|
+
return safeReaddir(dir).some(
|
|
14362
|
+
(e) => e.isFile() && /\.(sln|slnx|csproj)$/i.test(e.name)
|
|
14363
|
+
);
|
|
14364
|
+
}
|
|
14365
|
+
function findCsprojFiles(projectDir) {
|
|
14366
|
+
const found = [];
|
|
14367
|
+
const walk = (dir, depth) => {
|
|
14368
|
+
for (const e of safeReaddir(dir)) {
|
|
14369
|
+
const full = path21.join(dir, e.name);
|
|
14370
|
+
if (e.isFile() && e.name.toLowerCase().endsWith(".csproj")) {
|
|
14371
|
+
found.push(full);
|
|
14372
|
+
} else if (e.isDirectory() && depth < 2 && !SKIP_DIRS.has(e.name.toLowerCase()) && !e.name.startsWith(".")) {
|
|
14373
|
+
walk(full, depth + 1);
|
|
14374
|
+
}
|
|
14375
|
+
}
|
|
14376
|
+
};
|
|
14377
|
+
walk(projectDir, 0);
|
|
14378
|
+
return found.sort();
|
|
14379
|
+
}
|
|
14380
|
+
function findEfCoreProject(projectDir) {
|
|
14381
|
+
for (const csproj of findCsprojFiles(projectDir)) {
|
|
14382
|
+
let content = "";
|
|
14383
|
+
try {
|
|
14384
|
+
content = fs21.readFileSync(csproj, "utf-8");
|
|
14385
|
+
} catch {
|
|
14386
|
+
continue;
|
|
14387
|
+
}
|
|
14388
|
+
if (content.includes(EF_DESIGN_PACKAGE)) {
|
|
14389
|
+
const dir = path21.dirname(csproj);
|
|
14390
|
+
return { csproj, projectDir: dir, migrationsDir: path21.join(dir, "Migrations") };
|
|
14391
|
+
}
|
|
14392
|
+
}
|
|
14393
|
+
return null;
|
|
14394
|
+
}
|
|
14395
|
+
function isDotnetProject(projectDir) {
|
|
14396
|
+
return hasDotnetMarker(projectDir);
|
|
14397
|
+
}
|
|
14398
|
+
function isDotnetFlywayProject(projectDir) {
|
|
14399
|
+
return isDotnetProject(projectDir) && fs21.existsSync(path21.join(projectDir, DOTNET_FLYWAY_DIR));
|
|
14400
|
+
}
|
|
14401
|
+
var MAVEN_FLYWAY_DIR = path21.join("src", "main", "resources", "db", "migration");
|
|
14402
|
+
function flywayMigrationsDir(projectDir) {
|
|
14403
|
+
const maven = path21.join(projectDir, MAVEN_FLYWAY_DIR);
|
|
14404
|
+
if (fs21.existsSync(maven) || fs21.existsSync(path21.join(projectDir, "pom.xml"))) return maven;
|
|
14405
|
+
if (isDotnetFlywayProject(projectDir)) return path21.join(projectDir, DOTNET_FLYWAY_DIR);
|
|
14406
|
+
return maven;
|
|
14407
|
+
}
|
|
14408
|
+
|
|
14409
|
+
// scripts/lakebase/migration-layout.ts
|
|
14235
14410
|
var MIGRATION_LANGUAGES = [
|
|
14236
14411
|
"java",
|
|
14237
14412
|
"kotlin",
|
|
14238
14413
|
"python",
|
|
14239
14414
|
"nodejs",
|
|
14415
|
+
"dotnet",
|
|
14240
14416
|
"unknown"
|
|
14241
14417
|
];
|
|
14242
14418
|
var MIGRATION_DEFAULTS = {
|
|
@@ -14244,16 +14420,19 @@ var MIGRATION_DEFAULTS = {
|
|
|
14244
14420
|
kotlin: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" },
|
|
14245
14421
|
python: { path: "alembic/versions", pattern: /^[0-9a-f][\w]*.*\.py$/i, glob: "*.py" },
|
|
14246
14422
|
nodejs: { path: "migrations", pattern: /^\d+.*\.(js|ts)$/i, glob: "*.{js,ts}" },
|
|
14423
|
+
// .NET + Flyway; EF Core projects get their Migrations/ dir from
|
|
14424
|
+
// resolveMigrationLayout (see DOTNET_EFCORE_DEFAULTS).
|
|
14425
|
+
dotnet: { path: "db/migrations", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" },
|
|
14247
14426
|
unknown: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" }
|
|
14248
14427
|
};
|
|
14249
14428
|
function detectLanguageAt(dir) {
|
|
14250
|
-
if (
|
|
14251
|
-
const kotlinDir =
|
|
14252
|
-
if (
|
|
14429
|
+
if (fs22.existsSync(path22.join(dir, "pom.xml"))) {
|
|
14430
|
+
const kotlinDir = path22.join(dir, "src", "main", "kotlin");
|
|
14431
|
+
if (fs22.existsSync(kotlinDir)) {
|
|
14253
14432
|
return "kotlin";
|
|
14254
14433
|
}
|
|
14255
14434
|
try {
|
|
14256
|
-
const pom =
|
|
14435
|
+
const pom = fs22.readFileSync(path22.join(dir, "pom.xml"), "utf-8");
|
|
14257
14436
|
if (pom.includes("kotlin-maven-plugin")) {
|
|
14258
14437
|
return "kotlin";
|
|
14259
14438
|
}
|
|
@@ -14261,10 +14440,13 @@ function detectLanguageAt(dir) {
|
|
|
14261
14440
|
}
|
|
14262
14441
|
return "java";
|
|
14263
14442
|
}
|
|
14264
|
-
if (
|
|
14443
|
+
if (fs22.existsSync(path22.join(dir, "pyproject.toml")) || fs22.existsSync(path22.join(dir, "requirements.txt")) || fs22.existsSync(path22.join(dir, "alembic.ini"))) {
|
|
14265
14444
|
return "python";
|
|
14266
14445
|
}
|
|
14267
|
-
if (
|
|
14446
|
+
if (hasDotnetMarker(dir)) {
|
|
14447
|
+
return "dotnet";
|
|
14448
|
+
}
|
|
14449
|
+
if (fs22.existsSync(path22.join(dir, "package.json"))) {
|
|
14268
14450
|
return "nodejs";
|
|
14269
14451
|
}
|
|
14270
14452
|
return "unknown";
|
|
@@ -14285,14 +14467,14 @@ function resolveMigrationLanguage(projectDir, configuredMigrationPath, override)
|
|
|
14285
14467
|
if (!rel) {
|
|
14286
14468
|
return "unknown";
|
|
14287
14469
|
}
|
|
14288
|
-
const rootResolved =
|
|
14289
|
-
let dir =
|
|
14290
|
-
while (dir === rootResolved || dir.startsWith(rootResolved +
|
|
14470
|
+
const rootResolved = path22.resolve(projectDir);
|
|
14471
|
+
let dir = path22.resolve(projectDir, rel);
|
|
14472
|
+
while (dir === rootResolved || dir.startsWith(rootResolved + path22.sep)) {
|
|
14291
14473
|
const lang = detectLanguageAt(dir);
|
|
14292
14474
|
if (lang !== "unknown") {
|
|
14293
14475
|
return lang;
|
|
14294
14476
|
}
|
|
14295
|
-
const parent =
|
|
14477
|
+
const parent = path22.dirname(dir);
|
|
14296
14478
|
if (parent === dir) {
|
|
14297
14479
|
break;
|
|
14298
14480
|
}
|
|
@@ -14311,10 +14493,33 @@ function compileMigrationPattern(src) {
|
|
|
14311
14493
|
return void 0;
|
|
14312
14494
|
}
|
|
14313
14495
|
}
|
|
14496
|
+
var DOTNET_EFCORE_DEFAULTS = {
|
|
14497
|
+
path: "Migrations",
|
|
14498
|
+
pattern: /^\d{14}_(?!.*\.Designer\.cs$).+\.cs$/i,
|
|
14499
|
+
glob: "*.cs"
|
|
14500
|
+
};
|
|
14501
|
+
var DOTNET_LAYOUT_TTL_MS = 5e3;
|
|
14502
|
+
var dotnetLayoutCache = /* @__PURE__ */ new Map();
|
|
14503
|
+
function dotnetDefaults(projectDir) {
|
|
14504
|
+
if (!projectDir) return MIGRATION_DEFAULTS.dotnet;
|
|
14505
|
+
const key = path22.resolve(projectDir);
|
|
14506
|
+
const hit = dotnetLayoutCache.get(key);
|
|
14507
|
+
if (hit && Date.now() - hit.at < DOTNET_LAYOUT_TTL_MS) return hit.value;
|
|
14508
|
+
let value = MIGRATION_DEFAULTS.dotnet;
|
|
14509
|
+
if (!isDotnetFlywayProject(projectDir)) {
|
|
14510
|
+
const ef = findEfCoreProject(projectDir);
|
|
14511
|
+
if (ef) {
|
|
14512
|
+
const rel = path22.relative(projectDir, ef.migrationsDir).split(path22.sep).join("/");
|
|
14513
|
+
value = { ...DOTNET_EFCORE_DEFAULTS, path: rel };
|
|
14514
|
+
}
|
|
14515
|
+
}
|
|
14516
|
+
dotnetLayoutCache.set(key, { at: Date.now(), value });
|
|
14517
|
+
return value;
|
|
14518
|
+
}
|
|
14314
14519
|
function resolveMigrationLayout(args) {
|
|
14315
14520
|
const configuredMigrationPath = (args.migrationPath ?? "").trim();
|
|
14316
14521
|
const language = resolveMigrationLanguage(args.projectDir, configuredMigrationPath, args.language);
|
|
14317
|
-
const defaults = MIGRATION_DEFAULTS[language];
|
|
14522
|
+
const defaults = language === "dotnet" ? dotnetDefaults(args.projectDir) : MIGRATION_DEFAULTS[language];
|
|
14318
14523
|
return {
|
|
14319
14524
|
language,
|
|
14320
14525
|
migrationPath: configuredMigrationPath || defaults.path,
|
|
@@ -14325,22 +14530,22 @@ function resolveMigrationLayout(args) {
|
|
|
14325
14530
|
|
|
14326
14531
|
// scripts/lakebase/adapters/alembic-adapter.ts
|
|
14327
14532
|
init_esm_shims();
|
|
14328
|
-
import * as
|
|
14329
|
-
import * as
|
|
14533
|
+
import * as fs24 from "fs";
|
|
14534
|
+
import * as path24 from "path";
|
|
14330
14535
|
|
|
14331
14536
|
// scripts/lakebase/schema-migrate-runners/alembic.ts
|
|
14332
14537
|
init_esm_shims();
|
|
14333
14538
|
import { spawn as spawn5 } from "child_process";
|
|
14334
|
-
import * as
|
|
14335
|
-
import * as
|
|
14539
|
+
import * as fs23 from "fs";
|
|
14540
|
+
import * as path23 from "path";
|
|
14336
14541
|
function resolveAlembicBin(projectDir) {
|
|
14337
14542
|
const candidates = [
|
|
14338
|
-
|
|
14339
|
-
|
|
14543
|
+
path23.join(projectDir, ".venv", "bin", "alembic"),
|
|
14544
|
+
path23.join(projectDir, "venv", "bin", "alembic")
|
|
14340
14545
|
];
|
|
14341
14546
|
for (const candidate of candidates) {
|
|
14342
14547
|
try {
|
|
14343
|
-
if (
|
|
14548
|
+
if (fs23.existsSync(candidate)) return candidate;
|
|
14344
14549
|
} catch {
|
|
14345
14550
|
}
|
|
14346
14551
|
}
|
|
@@ -14350,7 +14555,7 @@ function spawnAlembic(projectDir, args, dsn) {
|
|
|
14350
14555
|
return new Promise((resolve2, reject) => {
|
|
14351
14556
|
const bin = resolveAlembicBin(projectDir);
|
|
14352
14557
|
const env = { ...process.env };
|
|
14353
|
-
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(
|
|
14558
|
+
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path23.delimiter);
|
|
14354
14559
|
if (dsn) env.DATABASE_URL = dsn;
|
|
14355
14560
|
const child = spawn5(bin, args, {
|
|
14356
14561
|
cwd: projectDir,
|
|
@@ -14398,10 +14603,10 @@ async function createAlembicRevision(opts) {
|
|
|
14398
14603
|
const m = stdout.match(/Generating\s+(\S+\.py)/);
|
|
14399
14604
|
if (m) return m[1].trim();
|
|
14400
14605
|
for (const rel of ["migrations/versions", "alembic/versions"]) {
|
|
14401
|
-
const dir =
|
|
14402
|
-
if (!
|
|
14403
|
-
const hit =
|
|
14404
|
-
if (hit) return
|
|
14606
|
+
const dir = path23.join(opts.projectDir, rel);
|
|
14607
|
+
if (!fs23.existsSync(dir)) continue;
|
|
14608
|
+
const hit = fs23.readdirSync(dir).find((f) => f.startsWith(`${opts.revId}_`) && f.endsWith(".py"));
|
|
14609
|
+
if (hit) return path23.join(dir, hit);
|
|
14405
14610
|
}
|
|
14406
14611
|
throw new SchemaMigrationError(
|
|
14407
14612
|
`alembic revision succeeded but the created file could not be located.
|
|
@@ -14536,15 +14741,15 @@ async function buildDsn2(args) {
|
|
|
14536
14741
|
}
|
|
14537
14742
|
function findVersionsDir(projectDir) {
|
|
14538
14743
|
const candidates = [
|
|
14539
|
-
|
|
14540
|
-
|
|
14744
|
+
path24.join(projectDir, "migrations", "versions"),
|
|
14745
|
+
path24.join(projectDir, "alembic", "versions")
|
|
14541
14746
|
];
|
|
14542
|
-
return candidates.find((p) =>
|
|
14747
|
+
return candidates.find((p) => fs24.existsSync(p));
|
|
14543
14748
|
}
|
|
14544
14749
|
function listAlembicFiles(projectDir) {
|
|
14545
14750
|
const dir = findVersionsDir(projectDir);
|
|
14546
14751
|
if (!dir) return [];
|
|
14547
|
-
const files =
|
|
14752
|
+
const files = fs24.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
|
|
14548
14753
|
return files.map((filename) => {
|
|
14549
14754
|
const stem = filename.replace(/\.py$/, "");
|
|
14550
14755
|
const sep4 = stem.indexOf("_");
|
|
@@ -14569,9 +14774,9 @@ var AlembicAdapter = {
|
|
|
14569
14774
|
* here. Callers can still force-select via project.yaml#migration_tool.
|
|
14570
14775
|
*/
|
|
14571
14776
|
detect(projectDir) {
|
|
14572
|
-
if (
|
|
14573
|
-
if (
|
|
14574
|
-
if (
|
|
14777
|
+
if (fs24.existsSync(path24.join(projectDir, "alembic.ini"))) return true;
|
|
14778
|
+
if (fs24.existsSync(path24.join(projectDir, "migrations", "env.py"))) return true;
|
|
14779
|
+
if (fs24.existsSync(path24.join(projectDir, "alembic", "env.py"))) return true;
|
|
14575
14780
|
return false;
|
|
14576
14781
|
},
|
|
14577
14782
|
async apply(args) {
|
|
@@ -14677,7 +14882,7 @@ var AlembicAdapter = {
|
|
|
14677
14882
|
autogenerate: !!args.autogenerate,
|
|
14678
14883
|
dsn
|
|
14679
14884
|
});
|
|
14680
|
-
return { status: "ok", version: revId, filename:
|
|
14885
|
+
return { status: "ok", version: revId, filename: path24.basename(created), path: created };
|
|
14681
14886
|
} catch (err) {
|
|
14682
14887
|
return {
|
|
14683
14888
|
status: "error",
|
|
@@ -14694,7 +14899,7 @@ var AlembicAdapter = {
|
|
|
14694
14899
|
if (heads.length <= 1) return { status: "noop", headsBefore: heads };
|
|
14695
14900
|
if (args.dryRun) return { status: "ok", headsBefore: heads };
|
|
14696
14901
|
const created = await mergeAlembicHeads(args.projectDir, args.message ?? "merge heads");
|
|
14697
|
-
const mergeRevision =
|
|
14902
|
+
const mergeRevision = path24.basename(created).replace(/\.py$/, "").split("_")[0];
|
|
14698
14903
|
return { status: "ok", headsBefore: heads, mergeRevision, path: created };
|
|
14699
14904
|
} catch (err) {
|
|
14700
14905
|
return {
|
|
@@ -14709,13 +14914,13 @@ registerSchemaMigrationAdapter(AlembicAdapter);
|
|
|
14709
14914
|
|
|
14710
14915
|
// scripts/lakebase/adapters/flyway-adapter.ts
|
|
14711
14916
|
init_esm_shims();
|
|
14712
|
-
import * as
|
|
14713
|
-
import * as
|
|
14917
|
+
import * as fs25 from "fs";
|
|
14918
|
+
import * as path26 from "path";
|
|
14714
14919
|
|
|
14715
14920
|
// scripts/lakebase/schema-migrate-runners/flyway.ts
|
|
14716
14921
|
init_esm_shims();
|
|
14717
14922
|
import { spawn as spawn6 } from "child_process";
|
|
14718
|
-
import * as
|
|
14923
|
+
import * as path25 from "path";
|
|
14719
14924
|
function dsnToFlywayEnv(dsn) {
|
|
14720
14925
|
const u = new URL(dsn);
|
|
14721
14926
|
const user = decodeURIComponent(u.username);
|
|
@@ -14725,7 +14930,7 @@ function dsnToFlywayEnv(dsn) {
|
|
|
14725
14930
|
return { url, user, password };
|
|
14726
14931
|
}
|
|
14727
14932
|
function migrationsLocation(projectDir) {
|
|
14728
|
-
return `filesystem:${
|
|
14933
|
+
return `filesystem:${flywayMigrationsDir(projectDir)}`;
|
|
14729
14934
|
}
|
|
14730
14935
|
function runFlyway(ctx, args) {
|
|
14731
14936
|
const { url, user, password } = dsnToFlywayEnv(ctx.dsn);
|
|
@@ -14826,7 +15031,7 @@ async function statusFlyway(ctx) {
|
|
|
14826
15031
|
if (state === "SUCCESS" || state === "BASELINE") {
|
|
14827
15032
|
current = m.version;
|
|
14828
15033
|
} else if (state === "PENDING") {
|
|
14829
|
-
const filename = m.filepath ?
|
|
15034
|
+
const filename = m.filepath ? path25.basename(m.filepath) : `V${m.version}__migration.sql`;
|
|
14830
15035
|
pending.push({
|
|
14831
15036
|
version: m.version,
|
|
14832
15037
|
filename,
|
|
@@ -14849,9 +15054,9 @@ async function buildDsn3(args) {
|
|
|
14849
15054
|
return result.url;
|
|
14850
15055
|
}
|
|
14851
15056
|
function listFlywayFiles(projectDir) {
|
|
14852
|
-
const dir =
|
|
14853
|
-
if (!
|
|
14854
|
-
const files =
|
|
15057
|
+
const dir = flywayMigrationsDir(projectDir);
|
|
15058
|
+
if (!fs25.existsSync(dir)) return [];
|
|
15059
|
+
const files = fs25.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
14855
15060
|
return files.map((filename) => {
|
|
14856
15061
|
const m = filename.match(/^V(\d+(?:\.\d+)*)__(.+)\.sql$/);
|
|
14857
15062
|
const version = m[1];
|
|
@@ -14872,9 +15077,9 @@ function versionCompare(a, b) {
|
|
|
14872
15077
|
}
|
|
14873
15078
|
var FlywayAdapter = {
|
|
14874
15079
|
id: "flyway",
|
|
14875
|
-
languages: ["java", "kotlin"],
|
|
15080
|
+
languages: ["java", "kotlin", "dotnet"],
|
|
14876
15081
|
detect(projectDir) {
|
|
14877
|
-
return
|
|
15082
|
+
return fs25.existsSync(path26.join(projectDir, "pom.xml")) || isDotnetFlywayProject(projectDir);
|
|
14878
15083
|
},
|
|
14879
15084
|
async apply(args) {
|
|
14880
15085
|
const dsn = await buildDsn3(args);
|
|
@@ -14932,14 +15137,14 @@ var FlywayAdapter = {
|
|
|
14932
15137
|
// optional-protocol shape makes this additive.
|
|
14933
15138
|
async newMigration(args) {
|
|
14934
15139
|
try {
|
|
14935
|
-
const dir =
|
|
14936
|
-
|
|
15140
|
+
const dir = flywayMigrationsDir(args.projectDir);
|
|
15141
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
14937
15142
|
const version = migrationTimestamp();
|
|
14938
15143
|
const slug = migrationSlug2(args.slug);
|
|
14939
15144
|
const filename = `V${version}__${slug}.sql`;
|
|
14940
|
-
const full =
|
|
14941
|
-
if (
|
|
14942
|
-
|
|
15145
|
+
const full = path26.join(dir, filename);
|
|
15146
|
+
if (fs25.existsSync(full)) throw new Error(`${filename} already exists`);
|
|
15147
|
+
fs25.writeFileSync(
|
|
14943
15148
|
full,
|
|
14944
15149
|
`-- V${version}: ${args.slug}
|
|
14945
15150
|
-- Flyway migration (write your DDL/DML below).
|
|
@@ -14962,19 +15167,19 @@ registerSchemaMigrationAdapter(FlywayAdapter);
|
|
|
14962
15167
|
|
|
14963
15168
|
// scripts/lakebase/adapters/knex-adapter.ts
|
|
14964
15169
|
init_esm_shims();
|
|
14965
|
-
import * as
|
|
14966
|
-
import * as
|
|
15170
|
+
import * as fs27 from "fs";
|
|
15171
|
+
import * as path28 from "path";
|
|
14967
15172
|
|
|
14968
15173
|
// scripts/lakebase/schema-migrate-runners/knex.ts
|
|
14969
15174
|
init_esm_shims();
|
|
14970
15175
|
import { spawn as spawn7 } from "child_process";
|
|
14971
|
-
import * as
|
|
14972
|
-
import * as
|
|
15176
|
+
import * as fs26 from "fs";
|
|
15177
|
+
import * as path27 from "path";
|
|
14973
15178
|
var KNEXFILE_VARIANTS = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14974
15179
|
function findKnexfile(projectDir) {
|
|
14975
15180
|
for (const name of KNEXFILE_VARIANTS) {
|
|
14976
|
-
const p =
|
|
14977
|
-
if (
|
|
15181
|
+
const p = path27.join(projectDir, name);
|
|
15182
|
+
if (fs26.existsSync(p)) return p;
|
|
14978
15183
|
}
|
|
14979
15184
|
return void 0;
|
|
14980
15185
|
}
|
|
@@ -15126,9 +15331,9 @@ async function buildDsn4(args) {
|
|
|
15126
15331
|
}
|
|
15127
15332
|
var KNEXFILE_VARIANTS2 = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
15128
15333
|
function listKnexFiles(projectDir) {
|
|
15129
|
-
const dir =
|
|
15130
|
-
if (!
|
|
15131
|
-
const files =
|
|
15334
|
+
const dir = path28.join(projectDir, "migrations");
|
|
15335
|
+
if (!fs27.existsSync(dir)) return [];
|
|
15336
|
+
const files = fs27.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
15132
15337
|
return files.map((filename) => {
|
|
15133
15338
|
const stem = filename.replace(/\.(js|ts)$/, "");
|
|
15134
15339
|
const m = stem.match(/^(\d{14})_(.+)$/);
|
|
@@ -15148,7 +15353,7 @@ var KnexAdapter = {
|
|
|
15148
15353
|
* project.yaml#migration_tool.
|
|
15149
15354
|
*/
|
|
15150
15355
|
detect(projectDir) {
|
|
15151
|
-
return KNEXFILE_VARIANTS2.some((name) =>
|
|
15356
|
+
return KNEXFILE_VARIANTS2.some((name) => fs27.existsSync(path28.join(projectDir, name)));
|
|
15152
15357
|
},
|
|
15153
15358
|
async apply(args) {
|
|
15154
15359
|
const dsn = await buildDsn4(args);
|
|
@@ -15221,9 +15426,9 @@ var KnexAdapter = {
|
|
|
15221
15426
|
async newMigration(args) {
|
|
15222
15427
|
try {
|
|
15223
15428
|
const created = await createKnexMigration({ projectDir: args.projectDir, slug: migrationSlug2(args.slug) });
|
|
15224
|
-
const stem =
|
|
15429
|
+
const stem = path28.basename(created).replace(/\.(js|ts)$/, "");
|
|
15225
15430
|
const version = stem.match(/^(\d{14})_/)?.[1] ?? stem;
|
|
15226
|
-
return { status: "ok", version, filename:
|
|
15431
|
+
return { status: "ok", version, filename: path28.basename(created), path: created };
|
|
15227
15432
|
} catch (err) {
|
|
15228
15433
|
return {
|
|
15229
15434
|
status: "error",
|
|
@@ -15237,6 +15442,362 @@ var KnexAdapter = {
|
|
|
15237
15442
|
};
|
|
15238
15443
|
registerSchemaMigrationAdapter(KnexAdapter);
|
|
15239
15444
|
|
|
15445
|
+
// scripts/lakebase/adapters/efcore-adapter.ts
|
|
15446
|
+
init_esm_shims();
|
|
15447
|
+
import * as path30 from "path";
|
|
15448
|
+
|
|
15449
|
+
// scripts/lakebase/schema-migrate-runners/efcore.ts
|
|
15450
|
+
init_esm_shims();
|
|
15451
|
+
import { spawn as spawn8 } from "child_process";
|
|
15452
|
+
import * as fs28 from "fs";
|
|
15453
|
+
import * as path29 from "path";
|
|
15454
|
+
import { Client as Client3 } from "pg";
|
|
15455
|
+
var MIGRATION_ID = /^(\d{14})_(.+)$/;
|
|
15456
|
+
function efVersion(id) {
|
|
15457
|
+
return MIGRATION_ID.exec(id)?.[1] ?? id;
|
|
15458
|
+
}
|
|
15459
|
+
function efDescription(id) {
|
|
15460
|
+
const name = MIGRATION_ID.exec(id)?.[2] ?? id;
|
|
15461
|
+
return name.replace(/_/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2");
|
|
15462
|
+
}
|
|
15463
|
+
function dsnToNpgsql(dsn) {
|
|
15464
|
+
const u = new URL(dsn);
|
|
15465
|
+
const parts = [
|
|
15466
|
+
`Host=${u.hostname}`,
|
|
15467
|
+
`Port=${u.port || "5432"}`,
|
|
15468
|
+
`Database=${decodeURIComponent(u.pathname.replace(/^\//, "")) || "databricks_postgres"}`
|
|
15469
|
+
];
|
|
15470
|
+
if (u.username) parts.push(`Username=${decodeURIComponent(u.username)}`);
|
|
15471
|
+
if (u.password) parts.push(`Password=${decodeURIComponent(u.password)}`);
|
|
15472
|
+
const sslmode = (u.searchParams.get("sslmode") ?? "require").toLowerCase();
|
|
15473
|
+
const ssl = {
|
|
15474
|
+
disable: "Disable",
|
|
15475
|
+
allow: "Allow",
|
|
15476
|
+
prefer: "Prefer",
|
|
15477
|
+
require: "Require",
|
|
15478
|
+
"verify-ca": "VerifyCA",
|
|
15479
|
+
"verify-full": "VerifyFull"
|
|
15480
|
+
};
|
|
15481
|
+
parts.push(`SSL Mode=${ssl[sslmode] ?? "Require"}`);
|
|
15482
|
+
const app = u.searchParams.get("application_name");
|
|
15483
|
+
if (app) parts.push(`Application Name=${app}`);
|
|
15484
|
+
return parts.map((p) => p.replace(/;/g, "")).join(";");
|
|
15485
|
+
}
|
|
15486
|
+
function parseEfJson(stdout) {
|
|
15487
|
+
const body = stdout.split(/\r?\n/).filter((l) => l.startsWith("data:")).map((l) => l.slice("data:".length)).join("\n").trim();
|
|
15488
|
+
if (!body) {
|
|
15489
|
+
throw new SchemaMigrationError(`dotnet ef returned no JSON payload: ${stdout.slice(0, 400)}`);
|
|
15490
|
+
}
|
|
15491
|
+
try {
|
|
15492
|
+
return JSON.parse(body);
|
|
15493
|
+
} catch (err) {
|
|
15494
|
+
throw new SchemaMigrationError(
|
|
15495
|
+
`dotnet ef JSON parse failed: ${err instanceof Error ? err.message : String(err)}.
|
|
15496
|
+
Body (first 400 chars): ${body.slice(0, 400)}`
|
|
15497
|
+
);
|
|
15498
|
+
}
|
|
15499
|
+
}
|
|
15500
|
+
function requireProject(projectDir) {
|
|
15501
|
+
const project = findEfCoreProject(projectDir);
|
|
15502
|
+
if (!project) {
|
|
15503
|
+
throw new SchemaMigrationError(
|
|
15504
|
+
`No EF Core project found under ${projectDir}. Expected a *.csproj that references ${EF_DESIGN_PACKAGE}.`
|
|
15505
|
+
);
|
|
15506
|
+
}
|
|
15507
|
+
return project;
|
|
15508
|
+
}
|
|
15509
|
+
function spawnDotnet(projectDir, args, env) {
|
|
15510
|
+
return new Promise((resolve2, reject) => {
|
|
15511
|
+
const child = spawn8("dotnet", args, {
|
|
15512
|
+
cwd: projectDir,
|
|
15513
|
+
env: { ...process.env, DOTNET_NOLOGO: "1", DOTNET_CLI_TELEMETRY_OPTOUT: "1", ...env },
|
|
15514
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
15515
|
+
});
|
|
15516
|
+
let stdout = "";
|
|
15517
|
+
let stderr = "";
|
|
15518
|
+
child.stdout.on("data", (chunk) => {
|
|
15519
|
+
stdout += chunk.toString("utf8");
|
|
15520
|
+
});
|
|
15521
|
+
child.stderr.on("data", (chunk) => {
|
|
15522
|
+
stderr += chunk.toString("utf8");
|
|
15523
|
+
});
|
|
15524
|
+
child.on("error", (err) => {
|
|
15525
|
+
reject(
|
|
15526
|
+
new SchemaMigrationError(
|
|
15527
|
+
`Could not spawn dotnet. Is the .NET SDK installed and on PATH? ${err.message}`,
|
|
15528
|
+
err
|
|
15529
|
+
)
|
|
15530
|
+
);
|
|
15531
|
+
});
|
|
15532
|
+
child.on("close", (code) => {
|
|
15533
|
+
if (code === 0) {
|
|
15534
|
+
resolve2({ stdout, stderr });
|
|
15535
|
+
} else {
|
|
15536
|
+
reject(
|
|
15537
|
+
new SchemaMigrationError(
|
|
15538
|
+
`dotnet ${args.join(" ")} exited with code ${code}.
|
|
15539
|
+
stdout: ${stdout}
|
|
15540
|
+
stderr: ${stderr}`
|
|
15541
|
+
)
|
|
15542
|
+
);
|
|
15543
|
+
}
|
|
15544
|
+
});
|
|
15545
|
+
});
|
|
15546
|
+
}
|
|
15547
|
+
var restored = /* @__PURE__ */ new Set();
|
|
15548
|
+
async function ensureRestored(projectDir, csproj) {
|
|
15549
|
+
if (restored.has(projectDir)) return;
|
|
15550
|
+
if (fs28.existsSync(path29.join(projectDir, ".config", "dotnet-tools.json"))) {
|
|
15551
|
+
await spawnDotnet(projectDir, ["tool", "restore"], {});
|
|
15552
|
+
}
|
|
15553
|
+
await spawnDotnet(projectDir, ["restore", csproj], {});
|
|
15554
|
+
restored.add(projectDir);
|
|
15555
|
+
}
|
|
15556
|
+
async function runEf(projectDir, args, dsn, opts = {}) {
|
|
15557
|
+
const project = requireProject(projectDir);
|
|
15558
|
+
const csproj = path29.relative(projectDir, project.csproj) || project.csproj;
|
|
15559
|
+
await ensureRestored(projectDir, csproj);
|
|
15560
|
+
const full = ["ef", ...args, "--project", csproj, "--prefix-output"];
|
|
15561
|
+
if (opts.noBuild) full.push("--no-build");
|
|
15562
|
+
const env = {};
|
|
15563
|
+
if (dsn) {
|
|
15564
|
+
env.DATABASE_URL = dsn;
|
|
15565
|
+
if (process.env.LAKEBASE_EFCORE_CONNECTION_ARG === "1") full.push("--connection", dsnToNpgsql(dsn));
|
|
15566
|
+
}
|
|
15567
|
+
return spawnDotnet(projectDir, full, env);
|
|
15568
|
+
}
|
|
15569
|
+
async function listEfMigrations(ctx, opts = {}) {
|
|
15570
|
+
const { stdout, stderr } = await runEf(ctx.projectDir, ["migrations", "list", "--json"], ctx.dsn, opts);
|
|
15571
|
+
const entries = parseEfJson(stdout);
|
|
15572
|
+
if (ctx.dsn && entries.some((e) => e.applied === null)) {
|
|
15573
|
+
const warning = stdout.split(/\r?\n/).filter((l) => /^(warn|error):/.test(l)).join("\n");
|
|
15574
|
+
throw new SchemaMigrationError(
|
|
15575
|
+
`dotnet ef could not read migration state from the database (check connectivity and credentials).
|
|
15576
|
+
${warning || stderr}`.trim()
|
|
15577
|
+
);
|
|
15578
|
+
}
|
|
15579
|
+
return entries;
|
|
15580
|
+
}
|
|
15581
|
+
async function readEfHistory(dsn) {
|
|
15582
|
+
const client = new Client3({ connectionString: dsn, application_name: connectionApplicationName() });
|
|
15583
|
+
await client.connect();
|
|
15584
|
+
try {
|
|
15585
|
+
const exists = await client.query(`SELECT to_regclass('"__EFMigrationsHistory"') IS NOT NULL AS present`);
|
|
15586
|
+
if (!exists.rows[0]?.present) return null;
|
|
15587
|
+
const r = await client.query(`SELECT "MigrationId" FROM "__EFMigrationsHistory" ORDER BY "MigrationId"`);
|
|
15588
|
+
return r.rows.map((row) => row.MigrationId);
|
|
15589
|
+
} finally {
|
|
15590
|
+
await client.end();
|
|
15591
|
+
}
|
|
15592
|
+
}
|
|
15593
|
+
function toApplied(entries) {
|
|
15594
|
+
return entries.map((e) => ({ version: efVersion(e.id), description: efDescription(e.id) }));
|
|
15595
|
+
}
|
|
15596
|
+
async function statusEfcore(ctx) {
|
|
15597
|
+
const entries = await listEfMigrations(ctx);
|
|
15598
|
+
const history = await (ctx.readHistory ?? readEfHistory)(ctx.dsn);
|
|
15599
|
+
const current = history && history.length > 0 ? efVersion(history[history.length - 1]) : void 0;
|
|
15600
|
+
const pending = entries.filter((e) => e.applied !== true).map((e) => ({ version: efVersion(e.id), filename: `${e.id}.cs`, description: efDescription(e.id) }));
|
|
15601
|
+
return { current, pending, tool: "efcore" };
|
|
15602
|
+
}
|
|
15603
|
+
async function applyEfcore(ctx) {
|
|
15604
|
+
const before = new Set((await listEfMigrations(ctx)).filter((e) => e.applied).map((e) => e.id));
|
|
15605
|
+
await runEf(ctx.projectDir, ["database", "update"], ctx.dsn, { noBuild: true });
|
|
15606
|
+
const after = await listEfMigrations(ctx, { noBuild: true });
|
|
15607
|
+
const applied = toApplied(after.filter((e) => e.applied && !before.has(e.id)));
|
|
15608
|
+
return { applied, alreadyAtLatest: applied.length === 0, tool: "efcore" };
|
|
15609
|
+
}
|
|
15610
|
+
function resolveEfTarget(target, applied) {
|
|
15611
|
+
const t = target.trim();
|
|
15612
|
+
if (t === "0") return "0";
|
|
15613
|
+
const rel = /^-(\d+)$/.exec(t);
|
|
15614
|
+
if (rel) {
|
|
15615
|
+
const steps = Number(rel[1]);
|
|
15616
|
+
if (steps < 1) throw new SchemaMigrationError(`Invalid rollback step: ${target}`);
|
|
15617
|
+
const index = applied.length - 1 - steps;
|
|
15618
|
+
if (index < -1) {
|
|
15619
|
+
throw new SchemaMigrationError(`Cannot roll back ${steps} migration(s); only ${applied.length} applied.`);
|
|
15620
|
+
}
|
|
15621
|
+
return index === -1 ? "0" : applied[index].id;
|
|
15622
|
+
}
|
|
15623
|
+
const match = applied.find((e) => e.id === t || efVersion(e.id) === t || e.name === t);
|
|
15624
|
+
if (!match) throw new SchemaMigrationError(`Rollback target '${target}' is not an applied migration.`);
|
|
15625
|
+
return match.id;
|
|
15626
|
+
}
|
|
15627
|
+
async function rollbackEfcore(ctx) {
|
|
15628
|
+
const beforeEntries = (await listEfMigrations(ctx)).filter((e) => e.applied);
|
|
15629
|
+
const targetId = resolveEfTarget(ctx.target, beforeEntries);
|
|
15630
|
+
await runEf(ctx.projectDir, ["database", "update", targetId], ctx.dsn, { noBuild: true });
|
|
15631
|
+
const stillApplied = new Set((await listEfMigrations(ctx, { noBuild: true })).filter((e) => e.applied).map((e) => e.id));
|
|
15632
|
+
return { rolledBack: toApplied(beforeEntries.filter((e) => !stillApplied.has(e.id)).reverse()), tool: "efcore" };
|
|
15633
|
+
}
|
|
15634
|
+
function efMigrationName(slug) {
|
|
15635
|
+
const name = slug.split(/[^A-Za-z0-9]+/).filter(Boolean).map((w) => w[0].toUpperCase() + w.slice(1)).join("");
|
|
15636
|
+
if (!name) throw new SchemaMigrationError(`Cannot derive a migration name from '${slug}'.`);
|
|
15637
|
+
return /^[0-9]/.test(name) ? `M${name}` : name;
|
|
15638
|
+
}
|
|
15639
|
+
async function createEfcoreMigration(opts) {
|
|
15640
|
+
const project = requireProject(opts.projectDir);
|
|
15641
|
+
const name = efMigrationName(opts.slug);
|
|
15642
|
+
const existing = new Set(fs28.existsSync(project.migrationsDir) ? fs28.readdirSync(project.migrationsDir) : []);
|
|
15643
|
+
await runEf(opts.projectDir, ["migrations", "add", name]);
|
|
15644
|
+
const created = fs28.readdirSync(project.migrationsDir).filter((f) => !existing.has(f) && MIGRATION_ID.test(f.replace(/\.cs$/, "")) && !f.endsWith(".Designer.cs"));
|
|
15645
|
+
if (created.length !== 1) {
|
|
15646
|
+
throw new SchemaMigrationError(`Expected one new migration file for ${name}, found: ${created.join(", ") || "none"}`);
|
|
15647
|
+
}
|
|
15648
|
+
return { id: created[0].replace(/\.cs$/, ""), path: path29.join(project.migrationsDir, created[0]) };
|
|
15649
|
+
}
|
|
15650
|
+
function localEfMigrationIds(projectDir) {
|
|
15651
|
+
const project = findEfCoreProject(projectDir);
|
|
15652
|
+
if (!project || !fs28.existsSync(project.migrationsDir)) return [];
|
|
15653
|
+
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();
|
|
15654
|
+
}
|
|
15655
|
+
function efProductVersion(project) {
|
|
15656
|
+
try {
|
|
15657
|
+
const csproj = fs28.readFileSync(project.csproj, "utf-8");
|
|
15658
|
+
const m = new RegExp(`${EF_DESIGN_PACKAGE.replace(/\./g, "\\.")}"\\s+Version="([^"]+)"`).exec(csproj);
|
|
15659
|
+
if (m) return m[1];
|
|
15660
|
+
} catch {
|
|
15661
|
+
}
|
|
15662
|
+
return "unknown";
|
|
15663
|
+
}
|
|
15664
|
+
async function stampEfcore(ctx) {
|
|
15665
|
+
const project = requireProject(ctx.projectDir);
|
|
15666
|
+
const ids = localEfMigrationIds(ctx.projectDir);
|
|
15667
|
+
if (ids.length === 0) throw new SchemaMigrationError("No local EF Core migrations to stamp.");
|
|
15668
|
+
const rev = ctx.revision.trim();
|
|
15669
|
+
const end = rev === "head" ? ids.length - 1 : ids.findIndex((id) => id === rev || efVersion(id) === rev);
|
|
15670
|
+
if (end < 0) throw new SchemaMigrationError(`Stamp revision '${ctx.revision}' is not a local migration.`);
|
|
15671
|
+
const toStamp = ids.slice(0, end + 1);
|
|
15672
|
+
const productVersion = efProductVersion(project);
|
|
15673
|
+
const client = new Client3({ connectionString: ctx.dsn, application_name: connectionApplicationName() });
|
|
15674
|
+
await client.connect();
|
|
15675
|
+
try {
|
|
15676
|
+
await client.query("BEGIN");
|
|
15677
|
+
await client.query(
|
|
15678
|
+
`CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
|
15679
|
+
"MigrationId" character varying(150) NOT NULL,
|
|
15680
|
+
"ProductVersion" character varying(32) NOT NULL,
|
|
15681
|
+
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId"))`
|
|
15682
|
+
);
|
|
15683
|
+
await client.query(`DELETE FROM "__EFMigrationsHistory" WHERE NOT ("MigrationId" = ANY($1::text[]))`, [toStamp]);
|
|
15684
|
+
for (const id of toStamp) {
|
|
15685
|
+
await client.query(
|
|
15686
|
+
`INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ($1, $2)
|
|
15687
|
+
ON CONFLICT ("MigrationId") DO NOTHING`,
|
|
15688
|
+
[id, productVersion]
|
|
15689
|
+
);
|
|
15690
|
+
}
|
|
15691
|
+
await client.query("COMMIT");
|
|
15692
|
+
} catch (err) {
|
|
15693
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
15694
|
+
throw err;
|
|
15695
|
+
} finally {
|
|
15696
|
+
await client.end();
|
|
15697
|
+
}
|
|
15698
|
+
return efVersion(toStamp[toStamp.length - 1]);
|
|
15699
|
+
}
|
|
15700
|
+
|
|
15701
|
+
// scripts/lakebase/adapters/efcore-adapter.ts
|
|
15702
|
+
async function buildDsn5(args) {
|
|
15703
|
+
const result = await getConnection({
|
|
15704
|
+
output: "dsn",
|
|
15705
|
+
instance: args.instance,
|
|
15706
|
+
branch: args.branch,
|
|
15707
|
+
database: args.database,
|
|
15708
|
+
endpointName: args.endpointName
|
|
15709
|
+
});
|
|
15710
|
+
return result.url;
|
|
15711
|
+
}
|
|
15712
|
+
function errMsg(err) {
|
|
15713
|
+
return err instanceof Error ? err.message : String(err);
|
|
15714
|
+
}
|
|
15715
|
+
function listEfCoreFiles(projectDir) {
|
|
15716
|
+
return localEfMigrationIds(projectDir).map((id) => ({
|
|
15717
|
+
version: efVersion(id),
|
|
15718
|
+
filename: `${id}.cs`,
|
|
15719
|
+
description: efDescription(id),
|
|
15720
|
+
type: "CSharp",
|
|
15721
|
+
tool: "efcore"
|
|
15722
|
+
}));
|
|
15723
|
+
}
|
|
15724
|
+
var EfCoreAdapter = {
|
|
15725
|
+
id: "efcore",
|
|
15726
|
+
languages: ["dotnet"],
|
|
15727
|
+
/** A .NET project (root marker) with a *.csproj that references Microsoft.EntityFrameworkCore.Design. */
|
|
15728
|
+
detect(projectDir) {
|
|
15729
|
+
return isDotnetProject(projectDir) && findEfCoreProject(projectDir) !== null;
|
|
15730
|
+
},
|
|
15731
|
+
async apply(args) {
|
|
15732
|
+
try {
|
|
15733
|
+
const dsn = await buildDsn5(args);
|
|
15734
|
+
const r = await applyEfcore({ projectDir: args.projectDir, dsn });
|
|
15735
|
+
return {
|
|
15736
|
+
applied_migrations: r.applied,
|
|
15737
|
+
status: r.alreadyAtLatest ? "noop" : "ok",
|
|
15738
|
+
tool_specific: { alreadyAtLatest: r.alreadyAtLatest, tool: r.tool }
|
|
15739
|
+
};
|
|
15740
|
+
} catch (err) {
|
|
15741
|
+
return { applied_migrations: [], status: "error", error: errMsg(err) };
|
|
15742
|
+
}
|
|
15743
|
+
},
|
|
15744
|
+
async rollback(args) {
|
|
15745
|
+
try {
|
|
15746
|
+
const dsn = await buildDsn5(args);
|
|
15747
|
+
const r = await rollbackEfcore({ projectDir: args.projectDir, dsn, target: args.target });
|
|
15748
|
+
return {
|
|
15749
|
+
rolled_back: r.rolledBack,
|
|
15750
|
+
status: r.rolledBack.length === 0 ? "noop" : "ok",
|
|
15751
|
+
tool_specific: { tool: r.tool }
|
|
15752
|
+
};
|
|
15753
|
+
} catch (err) {
|
|
15754
|
+
return { rolled_back: [], status: "error", error: errMsg(err) };
|
|
15755
|
+
}
|
|
15756
|
+
},
|
|
15757
|
+
async stamp(args) {
|
|
15758
|
+
try {
|
|
15759
|
+
const dsn = await buildDsn5(args);
|
|
15760
|
+
const stamped = await stampEfcore({ projectDir: args.projectDir, dsn, revision: args.revision });
|
|
15761
|
+
return { status: "ok", stamped_revision: stamped, tool_specific: { tool: "efcore" } };
|
|
15762
|
+
} catch (err) {
|
|
15763
|
+
return { status: "error", stamped_revision: null, error: errMsg(err) };
|
|
15764
|
+
}
|
|
15765
|
+
},
|
|
15766
|
+
async status(args) {
|
|
15767
|
+
try {
|
|
15768
|
+
const dsn = await buildDsn5(args);
|
|
15769
|
+
const r = await statusEfcore({ projectDir: args.projectDir, dsn });
|
|
15770
|
+
return {
|
|
15771
|
+
applied_version: r.current ?? null,
|
|
15772
|
+
pending: r.pending,
|
|
15773
|
+
applied: [],
|
|
15774
|
+
status: "ok",
|
|
15775
|
+
tool_specific: { tool: r.tool }
|
|
15776
|
+
};
|
|
15777
|
+
} catch (err) {
|
|
15778
|
+
return { applied_version: null, pending: [], applied: [], status: "error", error: errMsg(err) };
|
|
15779
|
+
}
|
|
15780
|
+
},
|
|
15781
|
+
async list(args) {
|
|
15782
|
+
return { files: listEfCoreFiles(args.projectDir) };
|
|
15783
|
+
},
|
|
15784
|
+
// baseline: use stamp (EF has no separate baseline concept).
|
|
15785
|
+
async newMigration(args) {
|
|
15786
|
+
try {
|
|
15787
|
+
const created = await createEfcoreMigration({ projectDir: args.projectDir, slug: args.slug });
|
|
15788
|
+
return {
|
|
15789
|
+
status: "ok",
|
|
15790
|
+
version: efVersion(created.id),
|
|
15791
|
+
filename: path30.basename(created.path),
|
|
15792
|
+
path: created.path
|
|
15793
|
+
};
|
|
15794
|
+
} catch (err) {
|
|
15795
|
+
return { status: "error", version: "", filename: "", path: "", error: errMsg(err) };
|
|
15796
|
+
}
|
|
15797
|
+
}
|
|
15798
|
+
};
|
|
15799
|
+
registerSchemaMigrationAdapter(EfCoreAdapter);
|
|
15800
|
+
|
|
15240
15801
|
// scripts/lakebase/schema-migrate.ts
|
|
15241
15802
|
var SchemaMigrationError = class extends Error {
|
|
15242
15803
|
constructor(message, cause) {
|
|
@@ -15250,13 +15811,16 @@ function detectLanguage(projectDir) {
|
|
|
15250
15811
|
const lang = resolveMigrationLanguage(projectDir);
|
|
15251
15812
|
if (lang === "unknown") {
|
|
15252
15813
|
throw new SchemaMigrationError(
|
|
15253
|
-
`Could not detect project language in ${projectDir}. Expected one of: pom.xml (java/kotlin), pyproject.toml or alembic.ini (python), package.json (nodejs). Pass {language} explicitly to override.`
|
|
15814
|
+
`Could not detect project language in ${projectDir}. Expected one of: pom.xml (java/kotlin), pyproject.toml or alembic.ini (python), package.json (nodejs), *.sln or *.csproj (dotnet). Pass {language} explicitly to override.`
|
|
15254
15815
|
);
|
|
15255
15816
|
}
|
|
15256
15817
|
return lang;
|
|
15257
15818
|
}
|
|
15258
|
-
function toolForLanguage(language) {
|
|
15819
|
+
function toolForLanguage(language, projectDir) {
|
|
15259
15820
|
switch (language) {
|
|
15821
|
+
case "dotnet":
|
|
15822
|
+
if (projectDir && isDotnetFlywayProject(projectDir)) return "flyway";
|
|
15823
|
+
return "efcore";
|
|
15260
15824
|
case "java":
|
|
15261
15825
|
case "kotlin":
|
|
15262
15826
|
return "flyway";
|
|
@@ -15269,8 +15833,10 @@ function toolForLanguage(language) {
|
|
|
15269
15833
|
function listSchemaMigrations(args = {}) {
|
|
15270
15834
|
const projectDir = args.projectDir ?? process.cwd();
|
|
15271
15835
|
const language = args.language ?? detectLanguage(projectDir);
|
|
15272
|
-
const tool = toolForLanguage(language);
|
|
15836
|
+
const tool = toolForLanguage(language, projectDir);
|
|
15273
15837
|
switch (tool) {
|
|
15838
|
+
case "efcore":
|
|
15839
|
+
return listEfCoreFiles(projectDir);
|
|
15274
15840
|
case "flyway":
|
|
15275
15841
|
return listFlywayMigrations(projectDir);
|
|
15276
15842
|
case "alembic":
|
|
@@ -15280,9 +15846,9 @@ function listSchemaMigrations(args = {}) {
|
|
|
15280
15846
|
}
|
|
15281
15847
|
}
|
|
15282
15848
|
function listFlywayMigrations(projectDir) {
|
|
15283
|
-
const dir =
|
|
15284
|
-
if (!
|
|
15285
|
-
const files =
|
|
15849
|
+
const dir = flywayMigrationsDir(projectDir);
|
|
15850
|
+
if (!fs29.existsSync(dir)) return [];
|
|
15851
|
+
const files = fs29.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
15286
15852
|
return files.map((filename) => {
|
|
15287
15853
|
const m = filename.match(/^V(\d+(?:\.\d+)*)__(.+)\.sql$/);
|
|
15288
15854
|
const version = m[1];
|
|
@@ -15292,12 +15858,12 @@ function listFlywayMigrations(projectDir) {
|
|
|
15292
15858
|
}
|
|
15293
15859
|
function listAlembicMigrations(projectDir) {
|
|
15294
15860
|
const candidates = [
|
|
15295
|
-
|
|
15296
|
-
|
|
15861
|
+
path31.join(projectDir, "migrations", "versions"),
|
|
15862
|
+
path31.join(projectDir, "alembic", "versions")
|
|
15297
15863
|
];
|
|
15298
|
-
const dir = candidates.find((p) =>
|
|
15864
|
+
const dir = candidates.find((p) => fs29.existsSync(p));
|
|
15299
15865
|
if (!dir) return [];
|
|
15300
|
-
const files =
|
|
15866
|
+
const files = fs29.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
|
|
15301
15867
|
return files.map((filename) => {
|
|
15302
15868
|
const stem = filename.replace(/\.py$/, "");
|
|
15303
15869
|
const sep4 = stem.indexOf("_");
|
|
@@ -15307,9 +15873,9 @@ function listAlembicMigrations(projectDir) {
|
|
|
15307
15873
|
}).sort((a, b) => a.filename.localeCompare(b.filename));
|
|
15308
15874
|
}
|
|
15309
15875
|
function listKnexMigrations(projectDir) {
|
|
15310
|
-
const dir =
|
|
15311
|
-
if (!
|
|
15312
|
-
const files =
|
|
15876
|
+
const dir = path31.join(projectDir, "migrations");
|
|
15877
|
+
if (!fs29.existsSync(dir)) return [];
|
|
15878
|
+
const files = fs29.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
15313
15879
|
return files.map((filename) => {
|
|
15314
15880
|
const stem = filename.replace(/\.(js|ts)$/, "");
|
|
15315
15881
|
const m = stem.match(/^(\d{14})_(.+)$/);
|
|
@@ -15331,7 +15897,7 @@ function versionCompare2(a, b) {
|
|
|
15331
15897
|
return 0;
|
|
15332
15898
|
}
|
|
15333
15899
|
function adapterFor(projectDir, language) {
|
|
15334
|
-
const override = language ? toolForLanguage(language) : void 0;
|
|
15900
|
+
const override = language ? toolForLanguage(language, projectDir) : void 0;
|
|
15335
15901
|
return resolveSchemaMigrationAdapter(projectDir, override);
|
|
15336
15902
|
}
|
|
15337
15903
|
var TierMigrationRefusedError = class extends Error {
|
|
@@ -15485,8 +16051,8 @@ async function runInfraSuite(args) {
|
|
|
15485
16051
|
duration_ms: Date.now() - start
|
|
15486
16052
|
};
|
|
15487
16053
|
if (args.junitOutput) {
|
|
15488
|
-
|
|
15489
|
-
|
|
16054
|
+
fs30.mkdirSync(path32.dirname(args.junitOutput), { recursive: true });
|
|
16055
|
+
fs30.writeFileSync(args.junitOutput, formatJUnit(result), "utf8");
|
|
15490
16056
|
}
|
|
15491
16057
|
return result;
|
|
15492
16058
|
}
|
|
@@ -15532,8 +16098,8 @@ function escapeXml(s) {
|
|
|
15532
16098
|
|
|
15533
16099
|
// scripts/lakebase/scm-claim-feature.ts
|
|
15534
16100
|
init_esm_shims();
|
|
15535
|
-
import * as
|
|
15536
|
-
import * as
|
|
16101
|
+
import * as fs31 from "fs";
|
|
16102
|
+
import * as path33 from "path";
|
|
15537
16103
|
var ScmClaimError = class extends Error {
|
|
15538
16104
|
constructor(message, code) {
|
|
15539
16105
|
super(message);
|
|
@@ -15590,7 +16156,7 @@ async function claimFeatureBranch(args) {
|
|
|
15590
16156
|
const current = readWorkflowState(args.projectDir);
|
|
15591
16157
|
if (!current) {
|
|
15592
16158
|
throw new ScmClaimError(
|
|
15593
|
-
`No SCM workflow state found at ${
|
|
16159
|
+
`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.`,
|
|
15594
16160
|
"no-state-file"
|
|
15595
16161
|
);
|
|
15596
16162
|
}
|
|
@@ -15694,8 +16260,8 @@ function alreadyClaimedSentinel(state) {
|
|
|
15694
16260
|
};
|
|
15695
16261
|
}
|
|
15696
16262
|
function workflowStateFileExists(projectDir) {
|
|
15697
|
-
return
|
|
15698
|
-
|
|
16263
|
+
return fs31.existsSync(
|
|
16264
|
+
path33.join(projectDir, ".lakebase/workflow-state.json")
|
|
15699
16265
|
);
|
|
15700
16266
|
}
|
|
15701
16267
|
|
|
@@ -16217,12 +16783,12 @@ async function sync(args) {
|
|
|
16217
16783
|
|
|
16218
16784
|
// scripts/lakebase/workflow-drift.ts
|
|
16219
16785
|
init_esm_shims();
|
|
16220
|
-
import * as
|
|
16221
|
-
import * as
|
|
16786
|
+
import * as fs32 from "fs";
|
|
16787
|
+
import * as path34 from "path";
|
|
16222
16788
|
function findKitTemplatesDir(start) {
|
|
16223
16789
|
let dir = start;
|
|
16224
16790
|
for (let i = 0; i < 6; i++) {
|
|
16225
|
-
const candidate =
|
|
16791
|
+
const candidate = path34.join(
|
|
16226
16792
|
dir,
|
|
16227
16793
|
"templates",
|
|
16228
16794
|
"project",
|
|
@@ -16230,8 +16796,8 @@ function findKitTemplatesDir(start) {
|
|
|
16230
16796
|
".github",
|
|
16231
16797
|
"workflows"
|
|
16232
16798
|
);
|
|
16233
|
-
if (
|
|
16234
|
-
const parent =
|
|
16799
|
+
if (fs32.existsSync(candidate)) return candidate;
|
|
16800
|
+
const parent = path34.dirname(dir);
|
|
16235
16801
|
if (parent === dir) break;
|
|
16236
16802
|
dir = parent;
|
|
16237
16803
|
}
|
|
@@ -16255,13 +16821,13 @@ function unifiedDiff(name, projectContent, templateContent) {
|
|
|
16255
16821
|
return out.join("\n");
|
|
16256
16822
|
}
|
|
16257
16823
|
function detectWorkflowDrift(args) {
|
|
16258
|
-
const projectWorkflowsDir =
|
|
16824
|
+
const projectWorkflowsDir = path34.join(
|
|
16259
16825
|
args.projectDir,
|
|
16260
16826
|
".github",
|
|
16261
16827
|
"workflows"
|
|
16262
16828
|
);
|
|
16263
|
-
const here =
|
|
16264
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16829
|
+
const here = path34.dirname(new URL(import.meta.url).pathname);
|
|
16830
|
+
const kitWorkflowsDir = args.kitDir ? path34.join(
|
|
16265
16831
|
args.kitDir,
|
|
16266
16832
|
"templates",
|
|
16267
16833
|
"project",
|
|
@@ -16269,21 +16835,21 @@ function detectWorkflowDrift(args) {
|
|
|
16269
16835
|
".github",
|
|
16270
16836
|
"workflows"
|
|
16271
16837
|
) : findKitTemplatesDir(here);
|
|
16272
|
-
const templateFiles =
|
|
16273
|
-
const projectFiles =
|
|
16838
|
+
const templateFiles = fs32.existsSync(kitWorkflowsDir) ? fs32.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
16839
|
+
const projectFiles = fs32.existsSync(projectWorkflowsDir) ? fs32.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
16274
16840
|
const version = readKitVersion(kitWorkflowsDir);
|
|
16275
16841
|
const seen = /* @__PURE__ */ new Set();
|
|
16276
16842
|
const files = [];
|
|
16277
16843
|
for (const name of templateFiles) {
|
|
16278
16844
|
seen.add(name);
|
|
16279
|
-
const projectPath2 =
|
|
16280
|
-
const templatePath =
|
|
16281
|
-
if (!
|
|
16845
|
+
const projectPath2 = path34.join(projectWorkflowsDir, name);
|
|
16846
|
+
const templatePath = path34.join(kitWorkflowsDir, name);
|
|
16847
|
+
if (!fs32.existsSync(projectPath2)) {
|
|
16282
16848
|
files.push({ name, status: "missing" });
|
|
16283
16849
|
continue;
|
|
16284
16850
|
}
|
|
16285
|
-
const projectContent =
|
|
16286
|
-
const templateContent = applyPlaceholders(
|
|
16851
|
+
const projectContent = fs32.readFileSync(projectPath2, "utf8");
|
|
16852
|
+
const templateContent = applyPlaceholders(fs32.readFileSync(templatePath, "utf8"), version);
|
|
16287
16853
|
if (projectContent === templateContent) {
|
|
16288
16854
|
files.push({ name, status: "unchanged" });
|
|
16289
16855
|
} else {
|
|
@@ -16314,10 +16880,10 @@ function detectWorkflowDrift(args) {
|
|
|
16314
16880
|
function readKitVersion(kitWorkflowsDir) {
|
|
16315
16881
|
let dir = kitWorkflowsDir;
|
|
16316
16882
|
for (let i = 0; i < 5; i++) {
|
|
16317
|
-
dir =
|
|
16883
|
+
dir = path34.dirname(dir);
|
|
16318
16884
|
}
|
|
16319
16885
|
try {
|
|
16320
|
-
const raw =
|
|
16886
|
+
const raw = fs32.readFileSync(path34.join(dir, "package.json"), "utf-8");
|
|
16321
16887
|
const pkg = JSON.parse(raw);
|
|
16322
16888
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16323
16889
|
} catch {
|
|
@@ -16334,7 +16900,7 @@ var COMMAND_HOOK_FILE_PATTERN = /\.(pre|post)-hook\.md$/;
|
|
|
16334
16900
|
function findKitCommandsDir(start) {
|
|
16335
16901
|
let dir = start;
|
|
16336
16902
|
for (let i = 0; i < 6; i++) {
|
|
16337
|
-
const candidate =
|
|
16903
|
+
const candidate = path34.join(
|
|
16338
16904
|
dir,
|
|
16339
16905
|
"templates",
|
|
16340
16906
|
"project",
|
|
@@ -16342,8 +16908,8 @@ function findKitCommandsDir(start) {
|
|
|
16342
16908
|
".claude",
|
|
16343
16909
|
"commands"
|
|
16344
16910
|
);
|
|
16345
|
-
if (
|
|
16346
|
-
const parent =
|
|
16911
|
+
if (fs32.existsSync(candidate)) return candidate;
|
|
16912
|
+
const parent = path34.dirname(dir);
|
|
16347
16913
|
if (parent === dir) break;
|
|
16348
16914
|
dir = parent;
|
|
16349
16915
|
}
|
|
@@ -16356,24 +16922,24 @@ function parsePinnedVersion(content) {
|
|
|
16356
16922
|
return m ? m[1] : void 0;
|
|
16357
16923
|
}
|
|
16358
16924
|
function detectCommandDrift(args) {
|
|
16359
|
-
const projectCommandsDir =
|
|
16360
|
-
const here =
|
|
16361
|
-
const kitCommandsDir = args.kitDir ?
|
|
16925
|
+
const projectCommandsDir = path34.join(args.projectDir, ".claude", "commands");
|
|
16926
|
+
const here = path34.dirname(new URL(import.meta.url).pathname);
|
|
16927
|
+
const kitCommandsDir = args.kitDir ? path34.join(args.kitDir, "templates", "project", "common", ".claude", "commands") : findKitCommandsDir(here);
|
|
16362
16928
|
const kitVersion = readKitVersionFromCommandsDir(kitCommandsDir);
|
|
16363
|
-
const templateFiles =
|
|
16364
|
-
const projectFiles =
|
|
16929
|
+
const templateFiles = fs32.existsSync(kitCommandsDir) ? fs32.readdirSync(kitCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
16930
|
+
const projectFiles = fs32.existsSync(projectCommandsDir) ? fs32.readdirSync(projectCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
16365
16931
|
const seen = /* @__PURE__ */ new Set();
|
|
16366
16932
|
const files = [];
|
|
16367
16933
|
for (const name of templateFiles) {
|
|
16368
16934
|
seen.add(name);
|
|
16369
|
-
const projectPath2 =
|
|
16370
|
-
const templatePath =
|
|
16371
|
-
const templateRaw =
|
|
16372
|
-
if (!
|
|
16935
|
+
const projectPath2 = path34.join(projectCommandsDir, name);
|
|
16936
|
+
const templatePath = path34.join(kitCommandsDir, name);
|
|
16937
|
+
const templateRaw = fs32.readFileSync(templatePath, "utf8");
|
|
16938
|
+
if (!fs32.existsSync(projectPath2)) {
|
|
16373
16939
|
files.push({ name, status: "missing", kit_version: kitVersion });
|
|
16374
16940
|
continue;
|
|
16375
16941
|
}
|
|
16376
|
-
const projectContent =
|
|
16942
|
+
const projectContent = fs32.readFileSync(projectPath2, "utf8");
|
|
16377
16943
|
const pinned = parsePinnedVersion(projectContent);
|
|
16378
16944
|
const versionForCompare = pinned ?? kitVersion;
|
|
16379
16945
|
const templateContent = applyCommandPlaceholders(templateRaw, versionForCompare);
|
|
@@ -16411,10 +16977,10 @@ function detectCommandDrift(args) {
|
|
|
16411
16977
|
function readKitVersionFromCommandsDir(kitCommandsDir) {
|
|
16412
16978
|
let dir = kitCommandsDir;
|
|
16413
16979
|
for (let i = 0; i < 5; i++) {
|
|
16414
|
-
dir =
|
|
16980
|
+
dir = path34.dirname(dir);
|
|
16415
16981
|
}
|
|
16416
16982
|
try {
|
|
16417
|
-
const raw =
|
|
16983
|
+
const raw = fs32.readFileSync(path34.join(dir, "package.json"), "utf-8");
|
|
16418
16984
|
const pkg = JSON.parse(raw);
|
|
16419
16985
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16420
16986
|
} catch {
|
|
@@ -16431,13 +16997,13 @@ function detectScaffoldedDrift(args) {
|
|
|
16431
16997
|
};
|
|
16432
16998
|
}
|
|
16433
16999
|
function updateWorkflows(args) {
|
|
16434
|
-
const projectWorkflowsDir =
|
|
17000
|
+
const projectWorkflowsDir = path34.join(
|
|
16435
17001
|
args.projectDir,
|
|
16436
17002
|
".github",
|
|
16437
17003
|
"workflows"
|
|
16438
17004
|
);
|
|
16439
|
-
const here =
|
|
16440
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
17005
|
+
const here = path34.dirname(new URL(import.meta.url).pathname);
|
|
17006
|
+
const kitWorkflowsDir = args.kitDir ? path34.join(
|
|
16441
17007
|
args.kitDir,
|
|
16442
17008
|
"templates",
|
|
16443
17009
|
"project",
|
|
@@ -16448,22 +17014,22 @@ function updateWorkflows(args) {
|
|
|
16448
17014
|
const substitute = args.substitute !== false;
|
|
16449
17015
|
const dryRun = args.dryRun === true;
|
|
16450
17016
|
const pruneExtras = args.pruneExtras === true;
|
|
16451
|
-
const templateFiles =
|
|
16452
|
-
const projectFiles =
|
|
16453
|
-
if (!dryRun && templateFiles.length > 0 && !
|
|
16454
|
-
|
|
17017
|
+
const templateFiles = fs32.existsSync(kitWorkflowsDir) ? fs32.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
17018
|
+
const projectFiles = fs32.existsSync(projectWorkflowsDir) ? fs32.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
17019
|
+
if (!dryRun && templateFiles.length > 0 && !fs32.existsSync(projectWorkflowsDir)) {
|
|
17020
|
+
fs32.mkdirSync(projectWorkflowsDir, { recursive: true });
|
|
16455
17021
|
}
|
|
16456
17022
|
const version = substitute ? readKitVersion(kitWorkflowsDir) : "";
|
|
16457
17023
|
const seen = /* @__PURE__ */ new Set();
|
|
16458
17024
|
const files = [];
|
|
16459
17025
|
for (const name of templateFiles) {
|
|
16460
17026
|
seen.add(name);
|
|
16461
|
-
const projectPath2 =
|
|
16462
|
-
const templatePath =
|
|
16463
|
-
const templateRaw =
|
|
17027
|
+
const projectPath2 = path34.join(projectWorkflowsDir, name);
|
|
17028
|
+
const templatePath = path34.join(kitWorkflowsDir, name);
|
|
17029
|
+
const templateRaw = fs32.readFileSync(templatePath, "utf-8");
|
|
16464
17030
|
const desired = substitute ? applyPlaceholders(templateRaw, version) : templateRaw;
|
|
16465
|
-
const existed =
|
|
16466
|
-
const current = existed ?
|
|
17031
|
+
const existed = fs32.existsSync(projectPath2);
|
|
17032
|
+
const current = existed ? fs32.readFileSync(projectPath2, "utf-8") : "";
|
|
16467
17033
|
let outcome;
|
|
16468
17034
|
if (!existed) {
|
|
16469
17035
|
outcome = "added";
|
|
@@ -16473,16 +17039,16 @@ function updateWorkflows(args) {
|
|
|
16473
17039
|
outcome = "updated";
|
|
16474
17040
|
}
|
|
16475
17041
|
if (!dryRun && outcome !== "unchanged") {
|
|
16476
|
-
|
|
17042
|
+
fs32.writeFileSync(projectPath2, desired);
|
|
16477
17043
|
}
|
|
16478
17044
|
files.push({ name, outcome });
|
|
16479
17045
|
}
|
|
16480
17046
|
if (pruneExtras) {
|
|
16481
17047
|
for (const name of projectFiles) {
|
|
16482
17048
|
if (seen.has(name)) continue;
|
|
16483
|
-
const projectPath2 =
|
|
17049
|
+
const projectPath2 = path34.join(projectWorkflowsDir, name);
|
|
16484
17050
|
if (!dryRun) {
|
|
16485
|
-
|
|
17051
|
+
fs32.unlinkSync(projectPath2);
|
|
16486
17052
|
}
|
|
16487
17053
|
files.push({ name, outcome: "removed" });
|
|
16488
17054
|
}
|
|
@@ -17115,15 +17681,15 @@ function parentForTopology(t, defaultLeaf) {
|
|
|
17115
17681
|
|
|
17116
17682
|
// scripts/lakebase/scm-doctor.ts
|
|
17117
17683
|
init_esm_shims();
|
|
17118
|
-
import * as
|
|
17119
|
-
import * as
|
|
17684
|
+
import * as fs33 from "fs";
|
|
17685
|
+
import * as path35 from "path";
|
|
17120
17686
|
var FEATURE_PREFIX = "feature/";
|
|
17121
17687
|
var TIER_LEAFS2 = DEFAULT_PROTECTED_TIER_NAMES;
|
|
17122
17688
|
function readEnv(projectDir) {
|
|
17123
|
-
const envPath =
|
|
17689
|
+
const envPath = path35.join(projectDir, ".env");
|
|
17124
17690
|
const out = /* @__PURE__ */ new Map();
|
|
17125
|
-
if (!
|
|
17126
|
-
const lines =
|
|
17691
|
+
if (!fs33.existsSync(envPath)) return out;
|
|
17692
|
+
const lines = fs33.readFileSync(envPath, "utf8").split("\n");
|
|
17127
17693
|
for (const line of lines) {
|
|
17128
17694
|
const m = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.+?)\s*$/);
|
|
17129
17695
|
if (m) out.set(m[1], m[2].replace(/^["']|["']$/g, ""));
|
|
@@ -17178,9 +17744,9 @@ async function runDoctor(args, deps = {}) {
|
|
|
17178
17744
|
}
|
|
17179
17745
|
for (const wf of ["pr.yml", "merge.yml"]) {
|
|
17180
17746
|
try {
|
|
17181
|
-
const p =
|
|
17182
|
-
if (!
|
|
17183
|
-
const body =
|
|
17747
|
+
const p = path35.join(projectDir, ".github", "workflows", wf);
|
|
17748
|
+
if (!fs33.existsSync(p)) continue;
|
|
17749
|
+
const body = fs33.readFileSync(p, "utf8");
|
|
17184
17750
|
if (/lakebase-scm-utils#v\d/.test(body)) {
|
|
17185
17751
|
findings.push({
|
|
17186
17752
|
id: "ci-workflow-substrate-pin",
|
|
@@ -17395,7 +17961,7 @@ async function fixFinding(args) {
|
|
|
17395
17961
|
);
|
|
17396
17962
|
}
|
|
17397
17963
|
const sanitized = sanitizeBranchName(branch);
|
|
17398
|
-
const envFile =
|
|
17964
|
+
const envFile = path35.join(args.projectDir, ".env");
|
|
17399
17965
|
updateEnvConnection({
|
|
17400
17966
|
envPath: envFile,
|
|
17401
17967
|
projectId: readEnvVar(envFile, "LAKEBASE_PROJECT_ID") ?? "",
|
|
@@ -17497,14 +18063,14 @@ function shellEscape3(s) {
|
|
|
17497
18063
|
|
|
17498
18064
|
// scripts/lakebase/doctor.ts
|
|
17499
18065
|
init_esm_shims();
|
|
17500
|
-
import * as
|
|
17501
|
-
import * as
|
|
18066
|
+
import * as fs34 from "fs";
|
|
18067
|
+
import * as path36 from "path";
|
|
17502
18068
|
import * as cp6 from "child_process";
|
|
17503
18069
|
function readEnvFile(projectDir) {
|
|
17504
|
-
const envPath =
|
|
17505
|
-
if (!
|
|
18070
|
+
const envPath = path36.join(projectDir, ".env");
|
|
18071
|
+
if (!fs34.existsSync(envPath)) return {};
|
|
17506
18072
|
const out = {};
|
|
17507
|
-
for (const line of
|
|
18073
|
+
for (const line of fs34.readFileSync(envPath, "utf8").split("\n")) {
|
|
17508
18074
|
const m = line.match(/^\s*([A-Z][A-Z0-9_]*)\s*=\s*(.*)\s*$/);
|
|
17509
18075
|
if (!m) continue;
|
|
17510
18076
|
let val = m[2];
|
|
@@ -17658,6 +18224,23 @@ async function checkPrereq(spec, run) {
|
|
|
17658
18224
|
detail: { version: trimmed }
|
|
17659
18225
|
};
|
|
17660
18226
|
}
|
|
18227
|
+
var DOTNET_PREREQ = {
|
|
18228
|
+
name: "dotnet-sdk",
|
|
18229
|
+
cmd: "dotnet",
|
|
18230
|
+
versionArgs: ["--version"],
|
|
18231
|
+
minMajor: 10,
|
|
18232
|
+
label: ".NET SDK",
|
|
18233
|
+
hint: "Install the .NET 10 SDK (e.g. `brew install --cask dotnet-sdk` or https://dot.net). EF Core's dotnet-ef is restored per project from .config/dotnet-tools.json."
|
|
18234
|
+
};
|
|
18235
|
+
async function checkLanguagePrerequisites(projectDir, run = defaultVersionRunner) {
|
|
18236
|
+
let lang;
|
|
18237
|
+
try {
|
|
18238
|
+
lang = detectLanguage(projectDir);
|
|
18239
|
+
} catch {
|
|
18240
|
+
return [];
|
|
18241
|
+
}
|
|
18242
|
+
return lang === "dotnet" ? [await checkPrereq(DOTNET_PREREQ, run)] : [];
|
|
18243
|
+
}
|
|
17661
18244
|
async function checkPrerequisites(run = defaultVersionRunner) {
|
|
17662
18245
|
return Promise.all(PREREQS.map((spec) => checkPrereq(spec, run)));
|
|
17663
18246
|
}
|
|
@@ -17759,7 +18342,7 @@ function checkEnv(projectDir) {
|
|
|
17759
18342
|
name: "env-file",
|
|
17760
18343
|
status: "warn",
|
|
17761
18344
|
message: ".env not found",
|
|
17762
|
-
detail: { projectDir, envPath:
|
|
18345
|
+
detail: { projectDir, envPath: path36.join(projectDir, ".env") },
|
|
17763
18346
|
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)."
|
|
17764
18347
|
};
|
|
17765
18348
|
}
|
|
@@ -17989,6 +18572,7 @@ async function runDoctor2(args = {}) {
|
|
|
17989
18572
|
const hooks = checkHooks(projectDir);
|
|
17990
18573
|
const workflowDrift = checkWorkflowDrift(projectDir);
|
|
17991
18574
|
const prereqs = await checkPrerequisites();
|
|
18575
|
+
const languagePrereqs = await checkLanguagePrerequisites(projectDir);
|
|
17992
18576
|
const lakebaseEnabled = auth7.status === "ok" ? await checkLakebaseEnabled(profile) : {
|
|
17993
18577
|
name: "lakebase-enabled",
|
|
17994
18578
|
status: "skip",
|
|
@@ -17997,6 +18581,7 @@ async function runDoctor2(args = {}) {
|
|
|
17997
18581
|
const checks = [
|
|
17998
18582
|
cli,
|
|
17999
18583
|
...prereqs,
|
|
18584
|
+
...languagePrereqs,
|
|
18000
18585
|
auth7,
|
|
18001
18586
|
identity,
|
|
18002
18587
|
lakebaseEnabled,
|
|
@@ -18252,8 +18837,8 @@ async function listMigrationsOnBranch(args) {
|
|
|
18252
18837
|
|
|
18253
18838
|
// scripts/git/commits.ts
|
|
18254
18839
|
init_esm_shims();
|
|
18255
|
-
import { existsSync as
|
|
18256
|
-
import { join as
|
|
18840
|
+
import { existsSync as existsSync33 } from "fs";
|
|
18841
|
+
import { join as join36 } from "path";
|
|
18257
18842
|
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
18258
18843
|
".py",
|
|
18259
18844
|
".ts",
|
|
@@ -18356,7 +18941,7 @@ async function commitAllIfChanged(args) {
|
|
|
18356
18941
|
await exec2("git add -A", { cwd: args.cwd });
|
|
18357
18942
|
}
|
|
18358
18943
|
for (const inc of args.include ?? []) {
|
|
18359
|
-
if (
|
|
18944
|
+
if (existsSync33(join36(args.cwd, inc))) {
|
|
18360
18945
|
await exec2(`git add -f -- ${shq(inc)}`, { cwd: args.cwd });
|
|
18361
18946
|
}
|
|
18362
18947
|
}
|
|
@@ -18498,14 +19083,14 @@ async function stashDropAll(args) {
|
|
|
18498
19083
|
|
|
18499
19084
|
// scripts/git/rebase.ts
|
|
18500
19085
|
init_esm_shims();
|
|
18501
|
-
import * as
|
|
18502
|
-
import * as
|
|
19086
|
+
import * as fs35 from "fs";
|
|
19087
|
+
import * as path37 from "path";
|
|
18503
19088
|
async function abortRebase(args) {
|
|
18504
19089
|
await exec2("git rebase --abort", { cwd: args.cwd });
|
|
18505
19090
|
}
|
|
18506
19091
|
async function isRebasing(args) {
|
|
18507
19092
|
try {
|
|
18508
|
-
return
|
|
19093
|
+
return fs35.existsSync(path37.join(args.cwd, ".git/rebase-merge")) || fs35.existsSync(path37.join(args.cwd, ".git/rebase-apply"));
|
|
18509
19094
|
} catch {
|
|
18510
19095
|
return false;
|
|
18511
19096
|
}
|
|
@@ -18684,47 +19269,14 @@ function isCliEntry(importMetaUrl) {
|
|
|
18684
19269
|
}
|
|
18685
19270
|
return invokedResolved === moduleResolved;
|
|
18686
19271
|
}
|
|
18687
|
-
|
|
18688
|
-
// scripts/util/proxy-env.ts
|
|
18689
|
-
init_esm_shims();
|
|
18690
|
-
var PROXY_ENV_KEYS = [
|
|
18691
|
-
"HTTP_PROXY",
|
|
18692
|
-
"HTTPS_PROXY",
|
|
18693
|
-
"NO_PROXY",
|
|
18694
|
-
"http_proxy",
|
|
18695
|
-
"https_proxy",
|
|
18696
|
-
"no_proxy",
|
|
18697
|
-
"npm_config_proxy",
|
|
18698
|
-
"npm_config_https_proxy",
|
|
18699
|
-
"npm_config_no_proxy",
|
|
18700
|
-
"npm_config_registry"
|
|
18701
|
-
];
|
|
18702
|
-
function proxyEnvSubset(source = process.env) {
|
|
18703
|
-
const out = {};
|
|
18704
|
-
for (const key of PROXY_ENV_KEYS) {
|
|
18705
|
-
const v = source[key];
|
|
18706
|
-
if (v !== void 0 && v !== "") {
|
|
18707
|
-
out[key] = v;
|
|
18708
|
-
}
|
|
18709
|
-
}
|
|
18710
|
-
return out;
|
|
18711
|
-
}
|
|
18712
|
-
function withProxyEnv(base = {}) {
|
|
18713
|
-
const out = {};
|
|
18714
|
-
const inherited = proxyEnvSubset();
|
|
18715
|
-
for (const [k, v] of Object.entries(inherited)) {
|
|
18716
|
-
out[k] = v;
|
|
18717
|
-
}
|
|
18718
|
-
for (const [k, v] of Object.entries(base)) {
|
|
18719
|
-
if (v !== void 0) out[k] = v;
|
|
18720
|
-
}
|
|
18721
|
-
return out;
|
|
18722
|
-
}
|
|
18723
19272
|
export {
|
|
18724
19273
|
CI_TOKEN_LIFETIME_SECONDS,
|
|
18725
19274
|
CI_TOKEN_REMINT_MARGIN_SECONDS,
|
|
18726
19275
|
CONVENTION_TIER_DEFAULTS,
|
|
18727
19276
|
DEFAULT_PROTECTED_TIER_NAMES,
|
|
19277
|
+
DOTNET_EFCORE_DEFAULTS,
|
|
19278
|
+
DOTNET_FLYWAY_DIR,
|
|
19279
|
+
EF_DESIGN_PACKAGE,
|
|
18728
19280
|
FIXABLE_FINDING_IDS,
|
|
18729
19281
|
GITHUB_SCOPES,
|
|
18730
19282
|
GitHubPullRequestError,
|
|
@@ -18737,6 +19289,7 @@ export {
|
|
|
18737
19289
|
LakebaseBranchError,
|
|
18738
19290
|
LakebaseBranchTtlTooLongError,
|
|
18739
19291
|
LakebaseProjectError,
|
|
19292
|
+
MAVEN_FLYWAY_DIR,
|
|
18740
19293
|
MIGRATION_DEFAULTS,
|
|
18741
19294
|
NODE_E2E_TEMPLATE_FILES,
|
|
18742
19295
|
PLAYWRIGHT_TEMPLATE_FILES,
|
|
@@ -18873,9 +19426,12 @@ export {
|
|
|
18873
19426
|
fastForwardBranch,
|
|
18874
19427
|
featureBranchName,
|
|
18875
19428
|
fetch2 as fetch,
|
|
19429
|
+
findCsprojFiles,
|
|
18876
19430
|
findDefaultBranchName,
|
|
19431
|
+
findEfCoreProject,
|
|
18877
19432
|
findHistoryRetentionDuration,
|
|
18878
19433
|
fixFinding,
|
|
19434
|
+
flywayMigrationsDir,
|
|
18879
19435
|
formatJUnit,
|
|
18880
19436
|
formatOwnerRepo,
|
|
18881
19437
|
formatSchemaDiffAsMarkdown,
|
|
@@ -18925,6 +19481,7 @@ export {
|
|
|
18925
19481
|
gitInit,
|
|
18926
19482
|
grantLakebasePermission,
|
|
18927
19483
|
grantUcCatalogPermission,
|
|
19484
|
+
hasDotnetMarker,
|
|
18928
19485
|
hasRemoteBranch,
|
|
18929
19486
|
hasUpstream,
|
|
18930
19487
|
inferTierTopology,
|
|
@@ -18934,6 +19491,8 @@ export {
|
|
|
18934
19491
|
isAllSchemas,
|
|
18935
19492
|
isCliEntry,
|
|
18936
19493
|
isDirty,
|
|
19494
|
+
isDotnetFlywayProject,
|
|
19495
|
+
isDotnetProject,
|
|
18937
19496
|
isForeignFeatureClaim,
|
|
18938
19497
|
isGitTracked,
|
|
18939
19498
|
isLongRunningTierBranch,
|