@databricks-solutions/lakebase-scm-utils 0.2.51 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/scripts/index.cjs +2632 -2120
- package/dist/scripts/index.d.cts +1 -1
- package/dist/scripts/index.d.ts +1 -1
- package/dist/scripts/index.js +676 -174
- 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 +2629 -2117
- package/dist/scripts/lakebase/index.d.cts +59 -10
- package/dist/scripts/lakebase/index.d.ts +59 -10
- package/dist/scripts/lakebase/index.js +670 -168
- 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/collapse-heads.cli.ts +1 -1
- package/scripts/lakebase/create-project.ts +6 -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
|
@@ -1913,9 +1913,9 @@ function asBranchUid(s) {
|
|
|
1913
1913
|
}
|
|
1914
1914
|
return s;
|
|
1915
1915
|
}
|
|
1916
|
-
function branchNameFromResourcePath(
|
|
1917
|
-
if (!
|
|
1918
|
-
const leaf =
|
|
1916
|
+
function branchNameFromResourcePath(path36) {
|
|
1917
|
+
if (!path36.includes("/branches/")) return null;
|
|
1918
|
+
const leaf = path36.split("/branches/").pop();
|
|
1919
1919
|
if (!leaf) return null;
|
|
1920
1920
|
try {
|
|
1921
1921
|
return asBranchName(leaf);
|
|
@@ -2521,8 +2521,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
2521
2521
|
var cached;
|
|
2522
2522
|
function substrateSelfVersion() {
|
|
2523
2523
|
if (cached !== void 0) return cached;
|
|
2524
|
-
if ("0.
|
|
2525
|
-
cached = "0.
|
|
2524
|
+
if ("0.3.0".length > 0) {
|
|
2525
|
+
cached = "0.3.0";
|
|
2526
2526
|
return cached;
|
|
2527
2527
|
}
|
|
2528
2528
|
cached = "unknown";
|
|
@@ -5062,7 +5062,7 @@ paginateRest.VERSION = VERSION5;
|
|
|
5062
5062
|
|
|
5063
5063
|
// node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
|
|
5064
5064
|
init_esm_shims();
|
|
5065
|
-
var generateMessage = (
|
|
5065
|
+
var generateMessage = (path36, cursorValue) => `The cursor at "${path36.join(
|
|
5066
5066
|
","
|
|
5067
5067
|
)}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
|
|
5068
5068
|
var MissingCursorChange = class extends Error {
|
|
@@ -5103,9 +5103,9 @@ function findPaginatedResourcePath(responseData) {
|
|
|
5103
5103
|
}
|
|
5104
5104
|
return paginatedResourcePath;
|
|
5105
5105
|
}
|
|
5106
|
-
var deepFindPathToProperty = (object, searchProp,
|
|
5106
|
+
var deepFindPathToProperty = (object, searchProp, path36 = []) => {
|
|
5107
5107
|
for (const key of Object.keys(object)) {
|
|
5108
|
-
const currentPath = [...
|
|
5108
|
+
const currentPath = [...path36, key];
|
|
5109
5109
|
const currentValue = object[key];
|
|
5110
5110
|
if (isObject(currentValue)) {
|
|
5111
5111
|
if (currentValue.hasOwnProperty(searchProp)) {
|
|
@@ -5123,12 +5123,12 @@ var deepFindPathToProperty = (object, searchProp, path33 = []) => {
|
|
|
5123
5123
|
}
|
|
5124
5124
|
return [];
|
|
5125
5125
|
};
|
|
5126
|
-
var get = (object,
|
|
5127
|
-
return
|
|
5126
|
+
var get = (object, path36) => {
|
|
5127
|
+
return path36.reduce((current, nextProperty) => current[nextProperty], object);
|
|
5128
5128
|
};
|
|
5129
|
-
var set = (object,
|
|
5130
|
-
const lastProperty =
|
|
5131
|
-
const parentPath = [...
|
|
5129
|
+
var set = (object, path36, mutator) => {
|
|
5130
|
+
const lastProperty = path36[path36.length - 1];
|
|
5131
|
+
const parentPath = [...path36].slice(0, -1);
|
|
5132
5132
|
const parent = get(object, parentPath);
|
|
5133
5133
|
if (typeof mutator === "function") {
|
|
5134
5134
|
parent[lastProperty] = mutator(parent[lastProperty]);
|
|
@@ -5180,22 +5180,22 @@ var mergeResponses = (response1, response2) => {
|
|
|
5180
5180
|
if (Object.keys(response1).length === 0) {
|
|
5181
5181
|
return Object.assign(response1, response2);
|
|
5182
5182
|
}
|
|
5183
|
-
const
|
|
5184
|
-
const nodesPath = [...
|
|
5183
|
+
const path36 = findPaginatedResourcePath(response1);
|
|
5184
|
+
const nodesPath = [...path36, "nodes"];
|
|
5185
5185
|
const newNodes = get(response2, nodesPath);
|
|
5186
5186
|
if (newNodes) {
|
|
5187
5187
|
set(response1, nodesPath, (values) => {
|
|
5188
5188
|
return [...values, ...newNodes];
|
|
5189
5189
|
});
|
|
5190
5190
|
}
|
|
5191
|
-
const edgesPath = [...
|
|
5191
|
+
const edgesPath = [...path36, "edges"];
|
|
5192
5192
|
const newEdges = get(response2, edgesPath);
|
|
5193
5193
|
if (newEdges) {
|
|
5194
5194
|
set(response1, edgesPath, (values) => {
|
|
5195
5195
|
return [...values, ...newEdges];
|
|
5196
5196
|
});
|
|
5197
5197
|
}
|
|
5198
|
-
const pageInfoPath = [...
|
|
5198
|
+
const pageInfoPath = [...path36, "pageInfo"];
|
|
5199
5199
|
set(response1, pageInfoPath, get(response2, pageInfoPath));
|
|
5200
5200
|
return response1;
|
|
5201
5201
|
};
|
|
@@ -7616,7 +7616,7 @@ var triggers_notification_paths_default = [
|
|
|
7616
7616
|
];
|
|
7617
7617
|
function routeMatcher(paths) {
|
|
7618
7618
|
const regexes = paths.map(
|
|
7619
|
-
(
|
|
7619
|
+
(path36) => path36.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
|
|
7620
7620
|
);
|
|
7621
7621
|
const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
|
|
7622
7622
|
return new RegExp(regex2, "i");
|
|
@@ -10944,16 +10944,16 @@ function isAllSchemas(schema) {
|
|
|
10944
10944
|
}
|
|
10945
10945
|
function buildSchemaQuery(schema) {
|
|
10946
10946
|
const cols = "c.table_schema, c.table_name, c.column_name, c.data_type";
|
|
10947
|
-
const
|
|
10947
|
+
const join35 = "FROM information_schema.columns c JOIN pg_tables t ON c.table_name = t.tablename AND c.table_schema = t.schemaname ";
|
|
10948
10948
|
if (isAllSchemas(schema)) {
|
|
10949
10949
|
return {
|
|
10950
|
-
text: `SELECT ${cols} ` +
|
|
10950
|
+
text: `SELECT ${cols} ` + join35 + `WHERE ${SYSTEM_SCHEMA_FILTER} ORDER BY c.table_schema, c.table_name, c.ordinal_position`,
|
|
10951
10951
|
values: []
|
|
10952
10952
|
};
|
|
10953
10953
|
}
|
|
10954
10954
|
const one = (schema ?? "").trim() || "public";
|
|
10955
10955
|
return {
|
|
10956
|
-
text: `SELECT ${cols} ` +
|
|
10956
|
+
text: `SELECT ${cols} ` + join35 + "WHERE c.table_schema = $1 ORDER BY c.table_name, c.ordinal_position",
|
|
10957
10957
|
values: [one]
|
|
10958
10958
|
};
|
|
10959
10959
|
}
|
|
@@ -11711,6 +11711,20 @@ async function deployLanguageProject(args) {
|
|
|
11711
11711
|
return;
|
|
11712
11712
|
}
|
|
11713
11713
|
const templatesDir = args.templatesDir ?? findTemplatesDir2();
|
|
11714
|
+
if (args.language === "dotnet") {
|
|
11715
|
+
const tool = args.migrationTool ?? "efcore";
|
|
11716
|
+
if (tool !== "efcore" && tool !== "flyway") {
|
|
11717
|
+
throw new Error(`Unsupported .NET migration tool: ${String(tool)} (expected efcore or flyway)`);
|
|
11718
|
+
}
|
|
11719
|
+
const base = path10.join(templatesDir, "dotnet");
|
|
11720
|
+
const overlay = path10.join(templatesDir, `dotnet-${tool}`);
|
|
11721
|
+
if (!fs11.existsSync(base) || !fs11.existsSync(overlay)) {
|
|
11722
|
+
throw new Error(`No template found for language: dotnet (${tool})`);
|
|
11723
|
+
}
|
|
11724
|
+
copyDirSubstituted(base, args.targetDir, { projectName: args.projectName });
|
|
11725
|
+
copyDirSubstituted(overlay, args.targetDir, { projectName: args.projectName });
|
|
11726
|
+
return;
|
|
11727
|
+
}
|
|
11714
11728
|
const langSrc = path10.join(templatesDir, args.language);
|
|
11715
11729
|
if (!fs11.existsSync(langSrc)) {
|
|
11716
11730
|
throw new Error(`No template found for language: ${args.language}`);
|
|
@@ -12130,6 +12144,7 @@ async function scaffoldAll(args) {
|
|
|
12130
12144
|
targetDir: args.targetDir,
|
|
12131
12145
|
language,
|
|
12132
12146
|
projectName,
|
|
12147
|
+
migrationTool: args.migrationTool,
|
|
12133
12148
|
templatesDir: args.templatesDir,
|
|
12134
12149
|
initializrClient: args.initializrClient,
|
|
12135
12150
|
report
|
|
@@ -13550,6 +13565,7 @@ Last probe error:
|
|
|
13550
13565
|
databricksHost: host,
|
|
13551
13566
|
lakebaseProjectId,
|
|
13552
13567
|
language,
|
|
13568
|
+
migrationTool: input.migrationTool,
|
|
13553
13569
|
runnerType,
|
|
13554
13570
|
skipCommands,
|
|
13555
13571
|
clientFramework,
|
|
@@ -13693,7 +13709,8 @@ Last probe error:
|
|
|
13693
13709
|
java: "Java/Spring Boot",
|
|
13694
13710
|
kotlin: "Kotlin/Spring Boot",
|
|
13695
13711
|
python: "Python/FastAPI",
|
|
13696
|
-
nodejs: "Node.js/Express"
|
|
13712
|
+
nodejs: "Node.js/Express",
|
|
13713
|
+
dotnet: `.NET/ASP.NET Core (${input.migrationTool === "flyway" ? "Flyway" : "EF Core"})`
|
|
13697
13714
|
};
|
|
13698
13715
|
const langLabel = langLabels[language] ?? language;
|
|
13699
13716
|
report("Creating initial commit...");
|
|
@@ -13874,8 +13891,8 @@ function _testMakeBrownfieldFixture(opts) {
|
|
|
13874
13891
|
|
|
13875
13892
|
// scripts/lakebase/infra-runner.ts
|
|
13876
13893
|
init_esm_shims();
|
|
13877
|
-
import * as
|
|
13878
|
-
import * as
|
|
13894
|
+
import * as fs29 from "fs";
|
|
13895
|
+
import * as path31 from "path";
|
|
13879
13896
|
|
|
13880
13897
|
// scripts/lakebase/schema-diff.ts
|
|
13881
13898
|
init_esm_shims();
|
|
@@ -14071,18 +14088,84 @@ function dbcli6(args) {
|
|
|
14071
14088
|
|
|
14072
14089
|
// scripts/lakebase/schema-migrate.ts
|
|
14073
14090
|
init_esm_shims();
|
|
14074
|
-
import * as
|
|
14075
|
-
import * as
|
|
14091
|
+
import * as fs28 from "fs";
|
|
14092
|
+
import * as path30 from "path";
|
|
14076
14093
|
|
|
14077
14094
|
// scripts/lakebase/migration-layout.ts
|
|
14078
14095
|
init_esm_shims();
|
|
14096
|
+
import * as fs21 from "fs";
|
|
14097
|
+
import * as path21 from "path";
|
|
14098
|
+
|
|
14099
|
+
// scripts/lakebase/dotnet-project.ts
|
|
14100
|
+
init_esm_shims();
|
|
14079
14101
|
import * as fs20 from "fs";
|
|
14080
14102
|
import * as path20 from "path";
|
|
14103
|
+
var EF_DESIGN_PACKAGE = "Microsoft.EntityFrameworkCore.Design";
|
|
14104
|
+
var DOTNET_FLYWAY_DIR = path20.join("db", "migrations");
|
|
14105
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["bin", "obj", "node_modules", ".git", "client", "tests", "test"]);
|
|
14106
|
+
function safeReaddir(dir) {
|
|
14107
|
+
try {
|
|
14108
|
+
return fs20.readdirSync(dir, { withFileTypes: true });
|
|
14109
|
+
} catch {
|
|
14110
|
+
return [];
|
|
14111
|
+
}
|
|
14112
|
+
}
|
|
14113
|
+
function hasDotnetMarker(dir) {
|
|
14114
|
+
return safeReaddir(dir).some(
|
|
14115
|
+
(e) => e.isFile() && /\.(sln|slnx|csproj)$/i.test(e.name)
|
|
14116
|
+
);
|
|
14117
|
+
}
|
|
14118
|
+
function findCsprojFiles(projectDir) {
|
|
14119
|
+
const found = [];
|
|
14120
|
+
const walk = (dir, depth) => {
|
|
14121
|
+
for (const e of safeReaddir(dir)) {
|
|
14122
|
+
const full = path20.join(dir, e.name);
|
|
14123
|
+
if (e.isFile() && e.name.toLowerCase().endsWith(".csproj")) {
|
|
14124
|
+
found.push(full);
|
|
14125
|
+
} else if (e.isDirectory() && depth < 2 && !SKIP_DIRS.has(e.name.toLowerCase()) && !e.name.startsWith(".")) {
|
|
14126
|
+
walk(full, depth + 1);
|
|
14127
|
+
}
|
|
14128
|
+
}
|
|
14129
|
+
};
|
|
14130
|
+
walk(projectDir, 0);
|
|
14131
|
+
return found.sort();
|
|
14132
|
+
}
|
|
14133
|
+
function findEfCoreProject(projectDir) {
|
|
14134
|
+
for (const csproj of findCsprojFiles(projectDir)) {
|
|
14135
|
+
let content = "";
|
|
14136
|
+
try {
|
|
14137
|
+
content = fs20.readFileSync(csproj, "utf-8");
|
|
14138
|
+
} catch {
|
|
14139
|
+
continue;
|
|
14140
|
+
}
|
|
14141
|
+
if (content.includes(EF_DESIGN_PACKAGE)) {
|
|
14142
|
+
const dir = path20.dirname(csproj);
|
|
14143
|
+
return { csproj, projectDir: dir, migrationsDir: path20.join(dir, "Migrations") };
|
|
14144
|
+
}
|
|
14145
|
+
}
|
|
14146
|
+
return null;
|
|
14147
|
+
}
|
|
14148
|
+
function isDotnetProject(projectDir) {
|
|
14149
|
+
return hasDotnetMarker(projectDir);
|
|
14150
|
+
}
|
|
14151
|
+
function isDotnetFlywayProject(projectDir) {
|
|
14152
|
+
return isDotnetProject(projectDir) && fs20.existsSync(path20.join(projectDir, DOTNET_FLYWAY_DIR));
|
|
14153
|
+
}
|
|
14154
|
+
var MAVEN_FLYWAY_DIR = path20.join("src", "main", "resources", "db", "migration");
|
|
14155
|
+
function flywayMigrationsDir(projectDir) {
|
|
14156
|
+
const maven = path20.join(projectDir, MAVEN_FLYWAY_DIR);
|
|
14157
|
+
if (fs20.existsSync(maven) || fs20.existsSync(path20.join(projectDir, "pom.xml"))) return maven;
|
|
14158
|
+
if (isDotnetFlywayProject(projectDir)) return path20.join(projectDir, DOTNET_FLYWAY_DIR);
|
|
14159
|
+
return maven;
|
|
14160
|
+
}
|
|
14161
|
+
|
|
14162
|
+
// scripts/lakebase/migration-layout.ts
|
|
14081
14163
|
var MIGRATION_LANGUAGES = [
|
|
14082
14164
|
"java",
|
|
14083
14165
|
"kotlin",
|
|
14084
14166
|
"python",
|
|
14085
14167
|
"nodejs",
|
|
14168
|
+
"dotnet",
|
|
14086
14169
|
"unknown"
|
|
14087
14170
|
];
|
|
14088
14171
|
var MIGRATION_DEFAULTS = {
|
|
@@ -14090,16 +14173,19 @@ var MIGRATION_DEFAULTS = {
|
|
|
14090
14173
|
kotlin: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" },
|
|
14091
14174
|
python: { path: "alembic/versions", pattern: /^[0-9a-f][\w]*.*\.py$/i, glob: "*.py" },
|
|
14092
14175
|
nodejs: { path: "migrations", pattern: /^\d+.*\.(js|ts)$/i, glob: "*.{js,ts}" },
|
|
14176
|
+
// .NET + Flyway; EF Core projects get their Migrations/ dir from
|
|
14177
|
+
// resolveMigrationLayout (see DOTNET_EFCORE_DEFAULTS).
|
|
14178
|
+
dotnet: { path: "db/migrations", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" },
|
|
14093
14179
|
unknown: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" }
|
|
14094
14180
|
};
|
|
14095
14181
|
function detectLanguageAt(dir) {
|
|
14096
|
-
if (
|
|
14097
|
-
const kotlinDir =
|
|
14098
|
-
if (
|
|
14182
|
+
if (fs21.existsSync(path21.join(dir, "pom.xml"))) {
|
|
14183
|
+
const kotlinDir = path21.join(dir, "src", "main", "kotlin");
|
|
14184
|
+
if (fs21.existsSync(kotlinDir)) {
|
|
14099
14185
|
return "kotlin";
|
|
14100
14186
|
}
|
|
14101
14187
|
try {
|
|
14102
|
-
const pom =
|
|
14188
|
+
const pom = fs21.readFileSync(path21.join(dir, "pom.xml"), "utf-8");
|
|
14103
14189
|
if (pom.includes("kotlin-maven-plugin")) {
|
|
14104
14190
|
return "kotlin";
|
|
14105
14191
|
}
|
|
@@ -14107,10 +14193,13 @@ function detectLanguageAt(dir) {
|
|
|
14107
14193
|
}
|
|
14108
14194
|
return "java";
|
|
14109
14195
|
}
|
|
14110
|
-
if (
|
|
14196
|
+
if (fs21.existsSync(path21.join(dir, "pyproject.toml")) || fs21.existsSync(path21.join(dir, "requirements.txt")) || fs21.existsSync(path21.join(dir, "alembic.ini"))) {
|
|
14111
14197
|
return "python";
|
|
14112
14198
|
}
|
|
14113
|
-
if (
|
|
14199
|
+
if (hasDotnetMarker(dir)) {
|
|
14200
|
+
return "dotnet";
|
|
14201
|
+
}
|
|
14202
|
+
if (fs21.existsSync(path21.join(dir, "package.json"))) {
|
|
14114
14203
|
return "nodejs";
|
|
14115
14204
|
}
|
|
14116
14205
|
return "unknown";
|
|
@@ -14131,14 +14220,14 @@ function resolveMigrationLanguage(projectDir, configuredMigrationPath, override)
|
|
|
14131
14220
|
if (!rel) {
|
|
14132
14221
|
return "unknown";
|
|
14133
14222
|
}
|
|
14134
|
-
const rootResolved =
|
|
14135
|
-
let dir =
|
|
14136
|
-
while (dir === rootResolved || dir.startsWith(rootResolved +
|
|
14223
|
+
const rootResolved = path21.resolve(projectDir);
|
|
14224
|
+
let dir = path21.resolve(projectDir, rel);
|
|
14225
|
+
while (dir === rootResolved || dir.startsWith(rootResolved + path21.sep)) {
|
|
14137
14226
|
const lang = detectLanguageAt(dir);
|
|
14138
14227
|
if (lang !== "unknown") {
|
|
14139
14228
|
return lang;
|
|
14140
14229
|
}
|
|
14141
|
-
const parent =
|
|
14230
|
+
const parent = path21.dirname(dir);
|
|
14142
14231
|
if (parent === dir) {
|
|
14143
14232
|
break;
|
|
14144
14233
|
}
|
|
@@ -14157,10 +14246,33 @@ function compileMigrationPattern(src) {
|
|
|
14157
14246
|
return void 0;
|
|
14158
14247
|
}
|
|
14159
14248
|
}
|
|
14249
|
+
var DOTNET_EFCORE_DEFAULTS = {
|
|
14250
|
+
path: "Migrations",
|
|
14251
|
+
pattern: /^\d{14}_(?!.*\.Designer\.cs$).+\.cs$/i,
|
|
14252
|
+
glob: "*.cs"
|
|
14253
|
+
};
|
|
14254
|
+
var DOTNET_LAYOUT_TTL_MS = 5e3;
|
|
14255
|
+
var dotnetLayoutCache = /* @__PURE__ */ new Map();
|
|
14256
|
+
function dotnetDefaults(projectDir) {
|
|
14257
|
+
if (!projectDir) return MIGRATION_DEFAULTS.dotnet;
|
|
14258
|
+
const key = path21.resolve(projectDir);
|
|
14259
|
+
const hit = dotnetLayoutCache.get(key);
|
|
14260
|
+
if (hit && Date.now() - hit.at < DOTNET_LAYOUT_TTL_MS) return hit.value;
|
|
14261
|
+
let value = MIGRATION_DEFAULTS.dotnet;
|
|
14262
|
+
if (!isDotnetFlywayProject(projectDir)) {
|
|
14263
|
+
const ef = findEfCoreProject(projectDir);
|
|
14264
|
+
if (ef) {
|
|
14265
|
+
const rel = path21.relative(projectDir, ef.migrationsDir).split(path21.sep).join("/");
|
|
14266
|
+
value = { ...DOTNET_EFCORE_DEFAULTS, path: rel };
|
|
14267
|
+
}
|
|
14268
|
+
}
|
|
14269
|
+
dotnetLayoutCache.set(key, { at: Date.now(), value });
|
|
14270
|
+
return value;
|
|
14271
|
+
}
|
|
14160
14272
|
function resolveMigrationLayout(args) {
|
|
14161
14273
|
const configuredMigrationPath = (args.migrationPath ?? "").trim();
|
|
14162
14274
|
const language = resolveMigrationLanguage(args.projectDir, configuredMigrationPath, args.language);
|
|
14163
|
-
const defaults = MIGRATION_DEFAULTS[language];
|
|
14275
|
+
const defaults = language === "dotnet" ? dotnetDefaults(args.projectDir) : MIGRATION_DEFAULTS[language];
|
|
14164
14276
|
return {
|
|
14165
14277
|
language,
|
|
14166
14278
|
migrationPath: configuredMigrationPath || defaults.path,
|
|
@@ -14171,22 +14283,22 @@ function resolveMigrationLayout(args) {
|
|
|
14171
14283
|
|
|
14172
14284
|
// scripts/lakebase/adapters/alembic-adapter.ts
|
|
14173
14285
|
init_esm_shims();
|
|
14174
|
-
import * as
|
|
14175
|
-
import * as
|
|
14286
|
+
import * as fs23 from "fs";
|
|
14287
|
+
import * as path23 from "path";
|
|
14176
14288
|
|
|
14177
14289
|
// scripts/lakebase/schema-migrate-runners/alembic.ts
|
|
14178
14290
|
init_esm_shims();
|
|
14179
14291
|
import { spawn as spawn5 } from "child_process";
|
|
14180
|
-
import * as
|
|
14181
|
-
import * as
|
|
14292
|
+
import * as fs22 from "fs";
|
|
14293
|
+
import * as path22 from "path";
|
|
14182
14294
|
function resolveAlembicBin(projectDir) {
|
|
14183
14295
|
const candidates = [
|
|
14184
|
-
|
|
14185
|
-
|
|
14296
|
+
path22.join(projectDir, ".venv", "bin", "alembic"),
|
|
14297
|
+
path22.join(projectDir, "venv", "bin", "alembic")
|
|
14186
14298
|
];
|
|
14187
14299
|
for (const candidate of candidates) {
|
|
14188
14300
|
try {
|
|
14189
|
-
if (
|
|
14301
|
+
if (fs22.existsSync(candidate)) return candidate;
|
|
14190
14302
|
} catch {
|
|
14191
14303
|
}
|
|
14192
14304
|
}
|
|
@@ -14196,7 +14308,7 @@ function spawnAlembic(projectDir, args, dsn) {
|
|
|
14196
14308
|
return new Promise((resolve2, reject) => {
|
|
14197
14309
|
const bin = resolveAlembicBin(projectDir);
|
|
14198
14310
|
const env = { ...process.env };
|
|
14199
|
-
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(
|
|
14311
|
+
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path22.delimiter);
|
|
14200
14312
|
if (dsn) env.DATABASE_URL = dsn;
|
|
14201
14313
|
const child = spawn5(bin, args, {
|
|
14202
14314
|
cwd: projectDir,
|
|
@@ -14244,10 +14356,10 @@ async function createAlembicRevision(opts) {
|
|
|
14244
14356
|
const m = stdout.match(/Generating\s+(\S+\.py)/);
|
|
14245
14357
|
if (m) return m[1].trim();
|
|
14246
14358
|
for (const rel of ["migrations/versions", "alembic/versions"]) {
|
|
14247
|
-
const dir =
|
|
14248
|
-
if (!
|
|
14249
|
-
const hit =
|
|
14250
|
-
if (hit) return
|
|
14359
|
+
const dir = path22.join(opts.projectDir, rel);
|
|
14360
|
+
if (!fs22.existsSync(dir)) continue;
|
|
14361
|
+
const hit = fs22.readdirSync(dir).find((f) => f.startsWith(`${opts.revId}_`) && f.endsWith(".py"));
|
|
14362
|
+
if (hit) return path22.join(dir, hit);
|
|
14251
14363
|
}
|
|
14252
14364
|
throw new SchemaMigrationError(
|
|
14253
14365
|
`alembic revision succeeded but the created file could not be located.
|
|
@@ -14382,15 +14494,15 @@ async function buildDsn2(args) {
|
|
|
14382
14494
|
}
|
|
14383
14495
|
function findVersionsDir(projectDir) {
|
|
14384
14496
|
const candidates = [
|
|
14385
|
-
|
|
14386
|
-
|
|
14497
|
+
path23.join(projectDir, "migrations", "versions"),
|
|
14498
|
+
path23.join(projectDir, "alembic", "versions")
|
|
14387
14499
|
];
|
|
14388
|
-
return candidates.find((p) =>
|
|
14500
|
+
return candidates.find((p) => fs23.existsSync(p));
|
|
14389
14501
|
}
|
|
14390
14502
|
function listAlembicFiles(projectDir) {
|
|
14391
14503
|
const dir = findVersionsDir(projectDir);
|
|
14392
14504
|
if (!dir) return [];
|
|
14393
|
-
const files =
|
|
14505
|
+
const files = fs23.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
|
|
14394
14506
|
return files.map((filename) => {
|
|
14395
14507
|
const stem = filename.replace(/\.py$/, "");
|
|
14396
14508
|
const sep4 = stem.indexOf("_");
|
|
@@ -14415,9 +14527,9 @@ var AlembicAdapter = {
|
|
|
14415
14527
|
* here. Callers can still force-select via project.yaml#migration_tool.
|
|
14416
14528
|
*/
|
|
14417
14529
|
detect(projectDir) {
|
|
14418
|
-
if (
|
|
14419
|
-
if (
|
|
14420
|
-
if (
|
|
14530
|
+
if (fs23.existsSync(path23.join(projectDir, "alembic.ini"))) return true;
|
|
14531
|
+
if (fs23.existsSync(path23.join(projectDir, "migrations", "env.py"))) return true;
|
|
14532
|
+
if (fs23.existsSync(path23.join(projectDir, "alembic", "env.py"))) return true;
|
|
14421
14533
|
return false;
|
|
14422
14534
|
},
|
|
14423
14535
|
async apply(args) {
|
|
@@ -14523,7 +14635,7 @@ var AlembicAdapter = {
|
|
|
14523
14635
|
autogenerate: !!args.autogenerate,
|
|
14524
14636
|
dsn
|
|
14525
14637
|
});
|
|
14526
|
-
return { status: "ok", version: revId, filename:
|
|
14638
|
+
return { status: "ok", version: revId, filename: path23.basename(created), path: created };
|
|
14527
14639
|
} catch (err) {
|
|
14528
14640
|
return {
|
|
14529
14641
|
status: "error",
|
|
@@ -14540,7 +14652,7 @@ var AlembicAdapter = {
|
|
|
14540
14652
|
if (heads.length <= 1) return { status: "noop", headsBefore: heads };
|
|
14541
14653
|
if (args.dryRun) return { status: "ok", headsBefore: heads };
|
|
14542
14654
|
const created = await mergeAlembicHeads(args.projectDir, args.message ?? "merge heads");
|
|
14543
|
-
const mergeRevision =
|
|
14655
|
+
const mergeRevision = path23.basename(created).replace(/\.py$/, "").split("_")[0];
|
|
14544
14656
|
return { status: "ok", headsBefore: heads, mergeRevision, path: created };
|
|
14545
14657
|
} catch (err) {
|
|
14546
14658
|
return {
|
|
@@ -14555,13 +14667,13 @@ registerSchemaMigrationAdapter(AlembicAdapter);
|
|
|
14555
14667
|
|
|
14556
14668
|
// scripts/lakebase/adapters/flyway-adapter.ts
|
|
14557
14669
|
init_esm_shims();
|
|
14558
|
-
import * as
|
|
14559
|
-
import * as
|
|
14670
|
+
import * as fs24 from "fs";
|
|
14671
|
+
import * as path25 from "path";
|
|
14560
14672
|
|
|
14561
14673
|
// scripts/lakebase/schema-migrate-runners/flyway.ts
|
|
14562
14674
|
init_esm_shims();
|
|
14563
14675
|
import { spawn as spawn6 } from "child_process";
|
|
14564
|
-
import * as
|
|
14676
|
+
import * as path24 from "path";
|
|
14565
14677
|
function dsnToFlywayEnv(dsn) {
|
|
14566
14678
|
const u = new URL(dsn);
|
|
14567
14679
|
const user = decodeURIComponent(u.username);
|
|
@@ -14571,7 +14683,7 @@ function dsnToFlywayEnv(dsn) {
|
|
|
14571
14683
|
return { url, user, password };
|
|
14572
14684
|
}
|
|
14573
14685
|
function migrationsLocation(projectDir) {
|
|
14574
|
-
return `filesystem:${
|
|
14686
|
+
return `filesystem:${flywayMigrationsDir(projectDir)}`;
|
|
14575
14687
|
}
|
|
14576
14688
|
function runFlyway(ctx, args) {
|
|
14577
14689
|
const { url, user, password } = dsnToFlywayEnv(ctx.dsn);
|
|
@@ -14672,7 +14784,7 @@ async function statusFlyway(ctx) {
|
|
|
14672
14784
|
if (state === "SUCCESS" || state === "BASELINE") {
|
|
14673
14785
|
current = m.version;
|
|
14674
14786
|
} else if (state === "PENDING") {
|
|
14675
|
-
const filename = m.filepath ?
|
|
14787
|
+
const filename = m.filepath ? path24.basename(m.filepath) : `V${m.version}__migration.sql`;
|
|
14676
14788
|
pending.push({
|
|
14677
14789
|
version: m.version,
|
|
14678
14790
|
filename,
|
|
@@ -14695,9 +14807,9 @@ async function buildDsn3(args) {
|
|
|
14695
14807
|
return result.url;
|
|
14696
14808
|
}
|
|
14697
14809
|
function listFlywayFiles(projectDir) {
|
|
14698
|
-
const dir =
|
|
14699
|
-
if (!
|
|
14700
|
-
const files =
|
|
14810
|
+
const dir = flywayMigrationsDir(projectDir);
|
|
14811
|
+
if (!fs24.existsSync(dir)) return [];
|
|
14812
|
+
const files = fs24.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
14701
14813
|
return files.map((filename) => {
|
|
14702
14814
|
const m = filename.match(/^V(\d+(?:\.\d+)*)__(.+)\.sql$/);
|
|
14703
14815
|
const version = m[1];
|
|
@@ -14718,9 +14830,9 @@ function versionCompare(a, b) {
|
|
|
14718
14830
|
}
|
|
14719
14831
|
var FlywayAdapter = {
|
|
14720
14832
|
id: "flyway",
|
|
14721
|
-
languages: ["java", "kotlin"],
|
|
14833
|
+
languages: ["java", "kotlin", "dotnet"],
|
|
14722
14834
|
detect(projectDir) {
|
|
14723
|
-
return
|
|
14835
|
+
return fs24.existsSync(path25.join(projectDir, "pom.xml")) || isDotnetFlywayProject(projectDir);
|
|
14724
14836
|
},
|
|
14725
14837
|
async apply(args) {
|
|
14726
14838
|
const dsn = await buildDsn3(args);
|
|
@@ -14778,14 +14890,14 @@ var FlywayAdapter = {
|
|
|
14778
14890
|
// optional-protocol shape makes this additive.
|
|
14779
14891
|
async newMigration(args) {
|
|
14780
14892
|
try {
|
|
14781
|
-
const dir =
|
|
14782
|
-
|
|
14893
|
+
const dir = flywayMigrationsDir(args.projectDir);
|
|
14894
|
+
fs24.mkdirSync(dir, { recursive: true });
|
|
14783
14895
|
const version = migrationTimestamp();
|
|
14784
14896
|
const slug = migrationSlug2(args.slug);
|
|
14785
14897
|
const filename = `V${version}__${slug}.sql`;
|
|
14786
|
-
const full =
|
|
14787
|
-
if (
|
|
14788
|
-
|
|
14898
|
+
const full = path25.join(dir, filename);
|
|
14899
|
+
if (fs24.existsSync(full)) throw new Error(`${filename} already exists`);
|
|
14900
|
+
fs24.writeFileSync(
|
|
14789
14901
|
full,
|
|
14790
14902
|
`-- V${version}: ${args.slug}
|
|
14791
14903
|
-- Flyway migration (write your DDL/DML below).
|
|
@@ -14808,19 +14920,19 @@ registerSchemaMigrationAdapter(FlywayAdapter);
|
|
|
14808
14920
|
|
|
14809
14921
|
// scripts/lakebase/adapters/knex-adapter.ts
|
|
14810
14922
|
init_esm_shims();
|
|
14811
|
-
import * as
|
|
14812
|
-
import * as
|
|
14923
|
+
import * as fs26 from "fs";
|
|
14924
|
+
import * as path27 from "path";
|
|
14813
14925
|
|
|
14814
14926
|
// scripts/lakebase/schema-migrate-runners/knex.ts
|
|
14815
14927
|
init_esm_shims();
|
|
14816
14928
|
import { spawn as spawn7 } from "child_process";
|
|
14817
|
-
import * as
|
|
14818
|
-
import * as
|
|
14929
|
+
import * as fs25 from "fs";
|
|
14930
|
+
import * as path26 from "path";
|
|
14819
14931
|
var KNEXFILE_VARIANTS = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14820
14932
|
function findKnexfile(projectDir) {
|
|
14821
14933
|
for (const name of KNEXFILE_VARIANTS) {
|
|
14822
|
-
const p =
|
|
14823
|
-
if (
|
|
14934
|
+
const p = path26.join(projectDir, name);
|
|
14935
|
+
if (fs25.existsSync(p)) return p;
|
|
14824
14936
|
}
|
|
14825
14937
|
return void 0;
|
|
14826
14938
|
}
|
|
@@ -14972,9 +15084,9 @@ async function buildDsn4(args) {
|
|
|
14972
15084
|
}
|
|
14973
15085
|
var KNEXFILE_VARIANTS2 = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14974
15086
|
function listKnexFiles(projectDir) {
|
|
14975
|
-
const dir =
|
|
14976
|
-
if (!
|
|
14977
|
-
const files =
|
|
15087
|
+
const dir = path27.join(projectDir, "migrations");
|
|
15088
|
+
if (!fs26.existsSync(dir)) return [];
|
|
15089
|
+
const files = fs26.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
14978
15090
|
return files.map((filename) => {
|
|
14979
15091
|
const stem = filename.replace(/\.(js|ts)$/, "");
|
|
14980
15092
|
const m = stem.match(/^(\d{14})_(.+)$/);
|
|
@@ -14994,7 +15106,7 @@ var KnexAdapter = {
|
|
|
14994
15106
|
* project.yaml#migration_tool.
|
|
14995
15107
|
*/
|
|
14996
15108
|
detect(projectDir) {
|
|
14997
|
-
return KNEXFILE_VARIANTS2.some((name) =>
|
|
15109
|
+
return KNEXFILE_VARIANTS2.some((name) => fs26.existsSync(path27.join(projectDir, name)));
|
|
14998
15110
|
},
|
|
14999
15111
|
async apply(args) {
|
|
15000
15112
|
const dsn = await buildDsn4(args);
|
|
@@ -15067,9 +15179,9 @@ var KnexAdapter = {
|
|
|
15067
15179
|
async newMigration(args) {
|
|
15068
15180
|
try {
|
|
15069
15181
|
const created = await createKnexMigration({ projectDir: args.projectDir, slug: migrationSlug2(args.slug) });
|
|
15070
|
-
const stem =
|
|
15182
|
+
const stem = path27.basename(created).replace(/\.(js|ts)$/, "");
|
|
15071
15183
|
const version = stem.match(/^(\d{14})_/)?.[1] ?? stem;
|
|
15072
|
-
return { status: "ok", version, filename:
|
|
15184
|
+
return { status: "ok", version, filename: path27.basename(created), path: created };
|
|
15073
15185
|
} catch (err) {
|
|
15074
15186
|
return {
|
|
15075
15187
|
status: "error",
|
|
@@ -15083,6 +15195,362 @@ var KnexAdapter = {
|
|
|
15083
15195
|
};
|
|
15084
15196
|
registerSchemaMigrationAdapter(KnexAdapter);
|
|
15085
15197
|
|
|
15198
|
+
// scripts/lakebase/adapters/efcore-adapter.ts
|
|
15199
|
+
init_esm_shims();
|
|
15200
|
+
import * as path29 from "path";
|
|
15201
|
+
|
|
15202
|
+
// scripts/lakebase/schema-migrate-runners/efcore.ts
|
|
15203
|
+
init_esm_shims();
|
|
15204
|
+
import { spawn as spawn8 } from "child_process";
|
|
15205
|
+
import * as fs27 from "fs";
|
|
15206
|
+
import * as path28 from "path";
|
|
15207
|
+
import { Client as Client3 } from "pg";
|
|
15208
|
+
var MIGRATION_ID = /^(\d{14})_(.+)$/;
|
|
15209
|
+
function efVersion(id) {
|
|
15210
|
+
return MIGRATION_ID.exec(id)?.[1] ?? id;
|
|
15211
|
+
}
|
|
15212
|
+
function efDescription(id) {
|
|
15213
|
+
const name = MIGRATION_ID.exec(id)?.[2] ?? id;
|
|
15214
|
+
return name.replace(/_/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2");
|
|
15215
|
+
}
|
|
15216
|
+
function dsnToNpgsql(dsn) {
|
|
15217
|
+
const u = new URL(dsn);
|
|
15218
|
+
const parts = [
|
|
15219
|
+
`Host=${u.hostname}`,
|
|
15220
|
+
`Port=${u.port || "5432"}`,
|
|
15221
|
+
`Database=${decodeURIComponent(u.pathname.replace(/^\//, "")) || "databricks_postgres"}`
|
|
15222
|
+
];
|
|
15223
|
+
if (u.username) parts.push(`Username=${decodeURIComponent(u.username)}`);
|
|
15224
|
+
if (u.password) parts.push(`Password=${decodeURIComponent(u.password)}`);
|
|
15225
|
+
const sslmode = (u.searchParams.get("sslmode") ?? "require").toLowerCase();
|
|
15226
|
+
const ssl = {
|
|
15227
|
+
disable: "Disable",
|
|
15228
|
+
allow: "Allow",
|
|
15229
|
+
prefer: "Prefer",
|
|
15230
|
+
require: "Require",
|
|
15231
|
+
"verify-ca": "VerifyCA",
|
|
15232
|
+
"verify-full": "VerifyFull"
|
|
15233
|
+
};
|
|
15234
|
+
parts.push(`SSL Mode=${ssl[sslmode] ?? "Require"}`);
|
|
15235
|
+
const app = u.searchParams.get("application_name");
|
|
15236
|
+
if (app) parts.push(`Application Name=${app}`);
|
|
15237
|
+
return parts.map((p) => p.replace(/;/g, "")).join(";");
|
|
15238
|
+
}
|
|
15239
|
+
function parseEfJson(stdout) {
|
|
15240
|
+
const body = stdout.split(/\r?\n/).filter((l) => l.startsWith("data:")).map((l) => l.slice("data:".length)).join("\n").trim();
|
|
15241
|
+
if (!body) {
|
|
15242
|
+
throw new SchemaMigrationError(`dotnet ef returned no JSON payload: ${stdout.slice(0, 400)}`);
|
|
15243
|
+
}
|
|
15244
|
+
try {
|
|
15245
|
+
return JSON.parse(body);
|
|
15246
|
+
} catch (err) {
|
|
15247
|
+
throw new SchemaMigrationError(
|
|
15248
|
+
`dotnet ef JSON parse failed: ${err instanceof Error ? err.message : String(err)}.
|
|
15249
|
+
Body (first 400 chars): ${body.slice(0, 400)}`
|
|
15250
|
+
);
|
|
15251
|
+
}
|
|
15252
|
+
}
|
|
15253
|
+
function requireProject(projectDir) {
|
|
15254
|
+
const project = findEfCoreProject(projectDir);
|
|
15255
|
+
if (!project) {
|
|
15256
|
+
throw new SchemaMigrationError(
|
|
15257
|
+
`No EF Core project found under ${projectDir}. Expected a *.csproj that references ${EF_DESIGN_PACKAGE}.`
|
|
15258
|
+
);
|
|
15259
|
+
}
|
|
15260
|
+
return project;
|
|
15261
|
+
}
|
|
15262
|
+
function spawnDotnet(projectDir, args, env) {
|
|
15263
|
+
return new Promise((resolve2, reject) => {
|
|
15264
|
+
const child = spawn8("dotnet", args, {
|
|
15265
|
+
cwd: projectDir,
|
|
15266
|
+
env: { ...process.env, DOTNET_NOLOGO: "1", DOTNET_CLI_TELEMETRY_OPTOUT: "1", ...env },
|
|
15267
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
15268
|
+
});
|
|
15269
|
+
let stdout = "";
|
|
15270
|
+
let stderr = "";
|
|
15271
|
+
child.stdout.on("data", (chunk) => {
|
|
15272
|
+
stdout += chunk.toString("utf8");
|
|
15273
|
+
});
|
|
15274
|
+
child.stderr.on("data", (chunk) => {
|
|
15275
|
+
stderr += chunk.toString("utf8");
|
|
15276
|
+
});
|
|
15277
|
+
child.on("error", (err) => {
|
|
15278
|
+
reject(
|
|
15279
|
+
new SchemaMigrationError(
|
|
15280
|
+
`Could not spawn dotnet. Is the .NET SDK installed and on PATH? ${err.message}`,
|
|
15281
|
+
err
|
|
15282
|
+
)
|
|
15283
|
+
);
|
|
15284
|
+
});
|
|
15285
|
+
child.on("close", (code) => {
|
|
15286
|
+
if (code === 0) {
|
|
15287
|
+
resolve2({ stdout, stderr });
|
|
15288
|
+
} else {
|
|
15289
|
+
reject(
|
|
15290
|
+
new SchemaMigrationError(
|
|
15291
|
+
`dotnet ${args.join(" ")} exited with code ${code}.
|
|
15292
|
+
stdout: ${stdout}
|
|
15293
|
+
stderr: ${stderr}`
|
|
15294
|
+
)
|
|
15295
|
+
);
|
|
15296
|
+
}
|
|
15297
|
+
});
|
|
15298
|
+
});
|
|
15299
|
+
}
|
|
15300
|
+
var restored = /* @__PURE__ */ new Set();
|
|
15301
|
+
async function ensureRestored(projectDir, csproj) {
|
|
15302
|
+
if (restored.has(projectDir)) return;
|
|
15303
|
+
if (fs27.existsSync(path28.join(projectDir, ".config", "dotnet-tools.json"))) {
|
|
15304
|
+
await spawnDotnet(projectDir, ["tool", "restore"], {});
|
|
15305
|
+
}
|
|
15306
|
+
await spawnDotnet(projectDir, ["restore", csproj], {});
|
|
15307
|
+
restored.add(projectDir);
|
|
15308
|
+
}
|
|
15309
|
+
async function runEf(projectDir, args, dsn, opts = {}) {
|
|
15310
|
+
const project = requireProject(projectDir);
|
|
15311
|
+
const csproj = path28.relative(projectDir, project.csproj) || project.csproj;
|
|
15312
|
+
await ensureRestored(projectDir, csproj);
|
|
15313
|
+
const full = ["ef", ...args, "--project", csproj, "--prefix-output"];
|
|
15314
|
+
if (opts.noBuild) full.push("--no-build");
|
|
15315
|
+
const env = {};
|
|
15316
|
+
if (dsn) {
|
|
15317
|
+
env.DATABASE_URL = dsn;
|
|
15318
|
+
if (process.env.LAKEBASE_EFCORE_CONNECTION_ARG === "1") full.push("--connection", dsnToNpgsql(dsn));
|
|
15319
|
+
}
|
|
15320
|
+
return spawnDotnet(projectDir, full, env);
|
|
15321
|
+
}
|
|
15322
|
+
async function listEfMigrations(ctx, opts = {}) {
|
|
15323
|
+
const { stdout, stderr } = await runEf(ctx.projectDir, ["migrations", "list", "--json"], ctx.dsn, opts);
|
|
15324
|
+
const entries = parseEfJson(stdout);
|
|
15325
|
+
if (ctx.dsn && entries.some((e) => e.applied === null)) {
|
|
15326
|
+
const warning = stdout.split(/\r?\n/).filter((l) => /^(warn|error):/.test(l)).join("\n");
|
|
15327
|
+
throw new SchemaMigrationError(
|
|
15328
|
+
`dotnet ef could not read migration state from the database (check connectivity and credentials).
|
|
15329
|
+
${warning || stderr}`.trim()
|
|
15330
|
+
);
|
|
15331
|
+
}
|
|
15332
|
+
return entries;
|
|
15333
|
+
}
|
|
15334
|
+
async function readEfHistory(dsn) {
|
|
15335
|
+
const client = new Client3({ connectionString: dsn, application_name: connectionApplicationName() });
|
|
15336
|
+
await client.connect();
|
|
15337
|
+
try {
|
|
15338
|
+
const exists = await client.query(`SELECT to_regclass('"__EFMigrationsHistory"') IS NOT NULL AS present`);
|
|
15339
|
+
if (!exists.rows[0]?.present) return null;
|
|
15340
|
+
const r = await client.query(`SELECT "MigrationId" FROM "__EFMigrationsHistory" ORDER BY "MigrationId"`);
|
|
15341
|
+
return r.rows.map((row) => row.MigrationId);
|
|
15342
|
+
} finally {
|
|
15343
|
+
await client.end();
|
|
15344
|
+
}
|
|
15345
|
+
}
|
|
15346
|
+
function toApplied(entries) {
|
|
15347
|
+
return entries.map((e) => ({ version: efVersion(e.id), description: efDescription(e.id) }));
|
|
15348
|
+
}
|
|
15349
|
+
async function statusEfcore(ctx) {
|
|
15350
|
+
const entries = await listEfMigrations(ctx);
|
|
15351
|
+
const history = await (ctx.readHistory ?? readEfHistory)(ctx.dsn);
|
|
15352
|
+
const current = history && history.length > 0 ? efVersion(history[history.length - 1]) : void 0;
|
|
15353
|
+
const pending = entries.filter((e) => e.applied !== true).map((e) => ({ version: efVersion(e.id), filename: `${e.id}.cs`, description: efDescription(e.id) }));
|
|
15354
|
+
return { current, pending, tool: "efcore" };
|
|
15355
|
+
}
|
|
15356
|
+
async function applyEfcore(ctx) {
|
|
15357
|
+
const before = new Set((await listEfMigrations(ctx)).filter((e) => e.applied).map((e) => e.id));
|
|
15358
|
+
await runEf(ctx.projectDir, ["database", "update"], ctx.dsn, { noBuild: true });
|
|
15359
|
+
const after = await listEfMigrations(ctx, { noBuild: true });
|
|
15360
|
+
const applied = toApplied(after.filter((e) => e.applied && !before.has(e.id)));
|
|
15361
|
+
return { applied, alreadyAtLatest: applied.length === 0, tool: "efcore" };
|
|
15362
|
+
}
|
|
15363
|
+
function resolveEfTarget(target, applied) {
|
|
15364
|
+
const t = target.trim();
|
|
15365
|
+
if (t === "0") return "0";
|
|
15366
|
+
const rel = /^-(\d+)$/.exec(t);
|
|
15367
|
+
if (rel) {
|
|
15368
|
+
const steps = Number(rel[1]);
|
|
15369
|
+
if (steps < 1) throw new SchemaMigrationError(`Invalid rollback step: ${target}`);
|
|
15370
|
+
const index = applied.length - 1 - steps;
|
|
15371
|
+
if (index < -1) {
|
|
15372
|
+
throw new SchemaMigrationError(`Cannot roll back ${steps} migration(s); only ${applied.length} applied.`);
|
|
15373
|
+
}
|
|
15374
|
+
return index === -1 ? "0" : applied[index].id;
|
|
15375
|
+
}
|
|
15376
|
+
const match = applied.find((e) => e.id === t || efVersion(e.id) === t || e.name === t);
|
|
15377
|
+
if (!match) throw new SchemaMigrationError(`Rollback target '${target}' is not an applied migration.`);
|
|
15378
|
+
return match.id;
|
|
15379
|
+
}
|
|
15380
|
+
async function rollbackEfcore(ctx) {
|
|
15381
|
+
const beforeEntries = (await listEfMigrations(ctx)).filter((e) => e.applied);
|
|
15382
|
+
const targetId = resolveEfTarget(ctx.target, beforeEntries);
|
|
15383
|
+
await runEf(ctx.projectDir, ["database", "update", targetId], ctx.dsn, { noBuild: true });
|
|
15384
|
+
const stillApplied = new Set((await listEfMigrations(ctx, { noBuild: true })).filter((e) => e.applied).map((e) => e.id));
|
|
15385
|
+
return { rolledBack: toApplied(beforeEntries.filter((e) => !stillApplied.has(e.id)).reverse()), tool: "efcore" };
|
|
15386
|
+
}
|
|
15387
|
+
function efMigrationName(slug) {
|
|
15388
|
+
const name = slug.split(/[^A-Za-z0-9]+/).filter(Boolean).map((w) => w[0].toUpperCase() + w.slice(1)).join("");
|
|
15389
|
+
if (!name) throw new SchemaMigrationError(`Cannot derive a migration name from '${slug}'.`);
|
|
15390
|
+
return /^[0-9]/.test(name) ? `M${name}` : name;
|
|
15391
|
+
}
|
|
15392
|
+
async function createEfcoreMigration(opts) {
|
|
15393
|
+
const project = requireProject(opts.projectDir);
|
|
15394
|
+
const name = efMigrationName(opts.slug);
|
|
15395
|
+
const existing = new Set(fs27.existsSync(project.migrationsDir) ? fs27.readdirSync(project.migrationsDir) : []);
|
|
15396
|
+
await runEf(opts.projectDir, ["migrations", "add", name]);
|
|
15397
|
+
const created = fs27.readdirSync(project.migrationsDir).filter((f) => !existing.has(f) && MIGRATION_ID.test(f.replace(/\.cs$/, "")) && !f.endsWith(".Designer.cs"));
|
|
15398
|
+
if (created.length !== 1) {
|
|
15399
|
+
throw new SchemaMigrationError(`Expected one new migration file for ${name}, found: ${created.join(", ") || "none"}`);
|
|
15400
|
+
}
|
|
15401
|
+
return { id: created[0].replace(/\.cs$/, ""), path: path28.join(project.migrationsDir, created[0]) };
|
|
15402
|
+
}
|
|
15403
|
+
function localEfMigrationIds(projectDir) {
|
|
15404
|
+
const project = findEfCoreProject(projectDir);
|
|
15405
|
+
if (!project || !fs27.existsSync(project.migrationsDir)) return [];
|
|
15406
|
+
return fs27.readdirSync(project.migrationsDir).filter((f) => f.endsWith(".cs") && !f.endsWith(".Designer.cs") && MIGRATION_ID.test(f.slice(0, -3))).map((f) => f.slice(0, -3)).sort();
|
|
15407
|
+
}
|
|
15408
|
+
function efProductVersion(project) {
|
|
15409
|
+
try {
|
|
15410
|
+
const csproj = fs27.readFileSync(project.csproj, "utf-8");
|
|
15411
|
+
const m = new RegExp(`${EF_DESIGN_PACKAGE.replace(/\./g, "\\.")}"\\s+Version="([^"]+)"`).exec(csproj);
|
|
15412
|
+
if (m) return m[1];
|
|
15413
|
+
} catch {
|
|
15414
|
+
}
|
|
15415
|
+
return "unknown";
|
|
15416
|
+
}
|
|
15417
|
+
async function stampEfcore(ctx) {
|
|
15418
|
+
const project = requireProject(ctx.projectDir);
|
|
15419
|
+
const ids = localEfMigrationIds(ctx.projectDir);
|
|
15420
|
+
if (ids.length === 0) throw new SchemaMigrationError("No local EF Core migrations to stamp.");
|
|
15421
|
+
const rev = ctx.revision.trim();
|
|
15422
|
+
const end = rev === "head" ? ids.length - 1 : ids.findIndex((id) => id === rev || efVersion(id) === rev);
|
|
15423
|
+
if (end < 0) throw new SchemaMigrationError(`Stamp revision '${ctx.revision}' is not a local migration.`);
|
|
15424
|
+
const toStamp = ids.slice(0, end + 1);
|
|
15425
|
+
const productVersion = efProductVersion(project);
|
|
15426
|
+
const client = new Client3({ connectionString: ctx.dsn, application_name: connectionApplicationName() });
|
|
15427
|
+
await client.connect();
|
|
15428
|
+
try {
|
|
15429
|
+
await client.query("BEGIN");
|
|
15430
|
+
await client.query(
|
|
15431
|
+
`CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
|
15432
|
+
"MigrationId" character varying(150) NOT NULL,
|
|
15433
|
+
"ProductVersion" character varying(32) NOT NULL,
|
|
15434
|
+
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId"))`
|
|
15435
|
+
);
|
|
15436
|
+
await client.query(`DELETE FROM "__EFMigrationsHistory" WHERE NOT ("MigrationId" = ANY($1::text[]))`, [toStamp]);
|
|
15437
|
+
for (const id of toStamp) {
|
|
15438
|
+
await client.query(
|
|
15439
|
+
`INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ($1, $2)
|
|
15440
|
+
ON CONFLICT ("MigrationId") DO NOTHING`,
|
|
15441
|
+
[id, productVersion]
|
|
15442
|
+
);
|
|
15443
|
+
}
|
|
15444
|
+
await client.query("COMMIT");
|
|
15445
|
+
} catch (err) {
|
|
15446
|
+
await client.query("ROLLBACK").catch(() => void 0);
|
|
15447
|
+
throw err;
|
|
15448
|
+
} finally {
|
|
15449
|
+
await client.end();
|
|
15450
|
+
}
|
|
15451
|
+
return efVersion(toStamp[toStamp.length - 1]);
|
|
15452
|
+
}
|
|
15453
|
+
|
|
15454
|
+
// scripts/lakebase/adapters/efcore-adapter.ts
|
|
15455
|
+
async function buildDsn5(args) {
|
|
15456
|
+
const result = await getConnection({
|
|
15457
|
+
output: "dsn",
|
|
15458
|
+
instance: args.instance,
|
|
15459
|
+
branch: args.branch,
|
|
15460
|
+
database: args.database,
|
|
15461
|
+
endpointName: args.endpointName
|
|
15462
|
+
});
|
|
15463
|
+
return result.url;
|
|
15464
|
+
}
|
|
15465
|
+
function errMsg(err) {
|
|
15466
|
+
return err instanceof Error ? err.message : String(err);
|
|
15467
|
+
}
|
|
15468
|
+
function listEfCoreFiles(projectDir) {
|
|
15469
|
+
return localEfMigrationIds(projectDir).map((id) => ({
|
|
15470
|
+
version: efVersion(id),
|
|
15471
|
+
filename: `${id}.cs`,
|
|
15472
|
+
description: efDescription(id),
|
|
15473
|
+
type: "CSharp",
|
|
15474
|
+
tool: "efcore"
|
|
15475
|
+
}));
|
|
15476
|
+
}
|
|
15477
|
+
var EfCoreAdapter = {
|
|
15478
|
+
id: "efcore",
|
|
15479
|
+
languages: ["dotnet"],
|
|
15480
|
+
/** A .NET project (root marker) with a *.csproj that references Microsoft.EntityFrameworkCore.Design. */
|
|
15481
|
+
detect(projectDir) {
|
|
15482
|
+
return isDotnetProject(projectDir) && findEfCoreProject(projectDir) !== null;
|
|
15483
|
+
},
|
|
15484
|
+
async apply(args) {
|
|
15485
|
+
try {
|
|
15486
|
+
const dsn = await buildDsn5(args);
|
|
15487
|
+
const r = await applyEfcore({ projectDir: args.projectDir, dsn });
|
|
15488
|
+
return {
|
|
15489
|
+
applied_migrations: r.applied,
|
|
15490
|
+
status: r.alreadyAtLatest ? "noop" : "ok",
|
|
15491
|
+
tool_specific: { alreadyAtLatest: r.alreadyAtLatest, tool: r.tool }
|
|
15492
|
+
};
|
|
15493
|
+
} catch (err) {
|
|
15494
|
+
return { applied_migrations: [], status: "error", error: errMsg(err) };
|
|
15495
|
+
}
|
|
15496
|
+
},
|
|
15497
|
+
async rollback(args) {
|
|
15498
|
+
try {
|
|
15499
|
+
const dsn = await buildDsn5(args);
|
|
15500
|
+
const r = await rollbackEfcore({ projectDir: args.projectDir, dsn, target: args.target });
|
|
15501
|
+
return {
|
|
15502
|
+
rolled_back: r.rolledBack,
|
|
15503
|
+
status: r.rolledBack.length === 0 ? "noop" : "ok",
|
|
15504
|
+
tool_specific: { tool: r.tool }
|
|
15505
|
+
};
|
|
15506
|
+
} catch (err) {
|
|
15507
|
+
return { rolled_back: [], status: "error", error: errMsg(err) };
|
|
15508
|
+
}
|
|
15509
|
+
},
|
|
15510
|
+
async stamp(args) {
|
|
15511
|
+
try {
|
|
15512
|
+
const dsn = await buildDsn5(args);
|
|
15513
|
+
const stamped = await stampEfcore({ projectDir: args.projectDir, dsn, revision: args.revision });
|
|
15514
|
+
return { status: "ok", stamped_revision: stamped, tool_specific: { tool: "efcore" } };
|
|
15515
|
+
} catch (err) {
|
|
15516
|
+
return { status: "error", stamped_revision: null, error: errMsg(err) };
|
|
15517
|
+
}
|
|
15518
|
+
},
|
|
15519
|
+
async status(args) {
|
|
15520
|
+
try {
|
|
15521
|
+
const dsn = await buildDsn5(args);
|
|
15522
|
+
const r = await statusEfcore({ projectDir: args.projectDir, dsn });
|
|
15523
|
+
return {
|
|
15524
|
+
applied_version: r.current ?? null,
|
|
15525
|
+
pending: r.pending,
|
|
15526
|
+
applied: [],
|
|
15527
|
+
status: "ok",
|
|
15528
|
+
tool_specific: { tool: r.tool }
|
|
15529
|
+
};
|
|
15530
|
+
} catch (err) {
|
|
15531
|
+
return { applied_version: null, pending: [], applied: [], status: "error", error: errMsg(err) };
|
|
15532
|
+
}
|
|
15533
|
+
},
|
|
15534
|
+
async list(args) {
|
|
15535
|
+
return { files: listEfCoreFiles(args.projectDir) };
|
|
15536
|
+
},
|
|
15537
|
+
// baseline: use stamp (EF has no separate baseline concept).
|
|
15538
|
+
async newMigration(args) {
|
|
15539
|
+
try {
|
|
15540
|
+
const created = await createEfcoreMigration({ projectDir: args.projectDir, slug: args.slug });
|
|
15541
|
+
return {
|
|
15542
|
+
status: "ok",
|
|
15543
|
+
version: efVersion(created.id),
|
|
15544
|
+
filename: path29.basename(created.path),
|
|
15545
|
+
path: created.path
|
|
15546
|
+
};
|
|
15547
|
+
} catch (err) {
|
|
15548
|
+
return { status: "error", version: "", filename: "", path: "", error: errMsg(err) };
|
|
15549
|
+
}
|
|
15550
|
+
}
|
|
15551
|
+
};
|
|
15552
|
+
registerSchemaMigrationAdapter(EfCoreAdapter);
|
|
15553
|
+
|
|
15086
15554
|
// scripts/lakebase/schema-migrate.ts
|
|
15087
15555
|
var SchemaMigrationError = class extends Error {
|
|
15088
15556
|
constructor(message, cause) {
|
|
@@ -15096,13 +15564,16 @@ function detectLanguage(projectDir) {
|
|
|
15096
15564
|
const lang = resolveMigrationLanguage(projectDir);
|
|
15097
15565
|
if (lang === "unknown") {
|
|
15098
15566
|
throw new SchemaMigrationError(
|
|
15099
|
-
`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.`
|
|
15567
|
+
`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.`
|
|
15100
15568
|
);
|
|
15101
15569
|
}
|
|
15102
15570
|
return lang;
|
|
15103
15571
|
}
|
|
15104
|
-
function toolForLanguage(language) {
|
|
15572
|
+
function toolForLanguage(language, projectDir) {
|
|
15105
15573
|
switch (language) {
|
|
15574
|
+
case "dotnet":
|
|
15575
|
+
if (projectDir && isDotnetFlywayProject(projectDir)) return "flyway";
|
|
15576
|
+
return "efcore";
|
|
15106
15577
|
case "java":
|
|
15107
15578
|
case "kotlin":
|
|
15108
15579
|
return "flyway";
|
|
@@ -15115,8 +15586,10 @@ function toolForLanguage(language) {
|
|
|
15115
15586
|
function listSchemaMigrations(args = {}) {
|
|
15116
15587
|
const projectDir = args.projectDir ?? process.cwd();
|
|
15117
15588
|
const language = args.language ?? detectLanguage(projectDir);
|
|
15118
|
-
const tool = toolForLanguage(language);
|
|
15589
|
+
const tool = toolForLanguage(language, projectDir);
|
|
15119
15590
|
switch (tool) {
|
|
15591
|
+
case "efcore":
|
|
15592
|
+
return listEfCoreFiles(projectDir);
|
|
15120
15593
|
case "flyway":
|
|
15121
15594
|
return listFlywayMigrations(projectDir);
|
|
15122
15595
|
case "alembic":
|
|
@@ -15126,9 +15599,9 @@ function listSchemaMigrations(args = {}) {
|
|
|
15126
15599
|
}
|
|
15127
15600
|
}
|
|
15128
15601
|
function listFlywayMigrations(projectDir) {
|
|
15129
|
-
const dir =
|
|
15130
|
-
if (!
|
|
15131
|
-
const files =
|
|
15602
|
+
const dir = flywayMigrationsDir(projectDir);
|
|
15603
|
+
if (!fs28.existsSync(dir)) return [];
|
|
15604
|
+
const files = fs28.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
15132
15605
|
return files.map((filename) => {
|
|
15133
15606
|
const m = filename.match(/^V(\d+(?:\.\d+)*)__(.+)\.sql$/);
|
|
15134
15607
|
const version = m[1];
|
|
@@ -15138,12 +15611,12 @@ function listFlywayMigrations(projectDir) {
|
|
|
15138
15611
|
}
|
|
15139
15612
|
function listAlembicMigrations(projectDir) {
|
|
15140
15613
|
const candidates = [
|
|
15141
|
-
|
|
15142
|
-
|
|
15614
|
+
path30.join(projectDir, "migrations", "versions"),
|
|
15615
|
+
path30.join(projectDir, "alembic", "versions")
|
|
15143
15616
|
];
|
|
15144
|
-
const dir = candidates.find((p) =>
|
|
15617
|
+
const dir = candidates.find((p) => fs28.existsSync(p));
|
|
15145
15618
|
if (!dir) return [];
|
|
15146
|
-
const files =
|
|
15619
|
+
const files = fs28.readdirSync(dir).filter((f) => f.endsWith(".py") && !f.startsWith("__"));
|
|
15147
15620
|
return files.map((filename) => {
|
|
15148
15621
|
const stem = filename.replace(/\.py$/, "");
|
|
15149
15622
|
const sep4 = stem.indexOf("_");
|
|
@@ -15153,9 +15626,9 @@ function listAlembicMigrations(projectDir) {
|
|
|
15153
15626
|
}).sort((a, b) => a.filename.localeCompare(b.filename));
|
|
15154
15627
|
}
|
|
15155
15628
|
function listKnexMigrations(projectDir) {
|
|
15156
|
-
const dir =
|
|
15157
|
-
if (!
|
|
15158
|
-
const files =
|
|
15629
|
+
const dir = path30.join(projectDir, "migrations");
|
|
15630
|
+
if (!fs28.existsSync(dir)) return [];
|
|
15631
|
+
const files = fs28.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
15159
15632
|
return files.map((filename) => {
|
|
15160
15633
|
const stem = filename.replace(/\.(js|ts)$/, "");
|
|
15161
15634
|
const m = stem.match(/^(\d{14})_(.+)$/);
|
|
@@ -15177,7 +15650,7 @@ function versionCompare2(a, b) {
|
|
|
15177
15650
|
return 0;
|
|
15178
15651
|
}
|
|
15179
15652
|
function adapterFor(projectDir, language) {
|
|
15180
|
-
const override = language ? toolForLanguage(language) : void 0;
|
|
15653
|
+
const override = language ? toolForLanguage(language, projectDir) : void 0;
|
|
15181
15654
|
return resolveSchemaMigrationAdapter(projectDir, override);
|
|
15182
15655
|
}
|
|
15183
15656
|
var TierMigrationRefusedError = class extends Error {
|
|
@@ -15331,8 +15804,8 @@ async function runInfraSuite(args) {
|
|
|
15331
15804
|
duration_ms: Date.now() - start
|
|
15332
15805
|
};
|
|
15333
15806
|
if (args.junitOutput) {
|
|
15334
|
-
|
|
15335
|
-
|
|
15807
|
+
fs29.mkdirSync(path31.dirname(args.junitOutput), { recursive: true });
|
|
15808
|
+
fs29.writeFileSync(args.junitOutput, formatJUnit(result), "utf8");
|
|
15336
15809
|
}
|
|
15337
15810
|
return result;
|
|
15338
15811
|
}
|
|
@@ -15378,8 +15851,8 @@ function escapeXml(s) {
|
|
|
15378
15851
|
|
|
15379
15852
|
// scripts/lakebase/scm-claim-feature.ts
|
|
15380
15853
|
init_esm_shims();
|
|
15381
|
-
import * as
|
|
15382
|
-
import * as
|
|
15854
|
+
import * as fs30 from "fs";
|
|
15855
|
+
import * as path32 from "path";
|
|
15383
15856
|
var ScmClaimError = class extends Error {
|
|
15384
15857
|
constructor(message, code) {
|
|
15385
15858
|
super(message);
|
|
@@ -15436,7 +15909,7 @@ async function claimFeatureBranch(args) {
|
|
|
15436
15909
|
const current = readWorkflowState(args.projectDir);
|
|
15437
15910
|
if (!current) {
|
|
15438
15911
|
throw new ScmClaimError(
|
|
15439
|
-
`No SCM workflow state found at ${
|
|
15912
|
+
`No SCM workflow state found at ${path32.join(args.projectDir, ".lakebase/workflow-state.json")}. Run lakebase-create-project to scaffold, or re-seed via the substrate.`,
|
|
15440
15913
|
"no-state-file"
|
|
15441
15914
|
);
|
|
15442
15915
|
}
|
|
@@ -15540,8 +16013,8 @@ function alreadyClaimedSentinel(state) {
|
|
|
15540
16013
|
};
|
|
15541
16014
|
}
|
|
15542
16015
|
function workflowStateFileExists(projectDir) {
|
|
15543
|
-
return
|
|
15544
|
-
|
|
16016
|
+
return fs30.existsSync(
|
|
16017
|
+
path32.join(projectDir, ".lakebase/workflow-state.json")
|
|
15545
16018
|
);
|
|
15546
16019
|
}
|
|
15547
16020
|
|
|
@@ -16029,12 +16502,12 @@ async function pushCurrentBranchForPr(args) {
|
|
|
16029
16502
|
|
|
16030
16503
|
// scripts/lakebase/workflow-drift.ts
|
|
16031
16504
|
init_esm_shims();
|
|
16032
|
-
import * as
|
|
16033
|
-
import * as
|
|
16505
|
+
import * as fs31 from "fs";
|
|
16506
|
+
import * as path33 from "path";
|
|
16034
16507
|
function findKitTemplatesDir(start) {
|
|
16035
16508
|
let dir = start;
|
|
16036
16509
|
for (let i = 0; i < 6; i++) {
|
|
16037
|
-
const candidate =
|
|
16510
|
+
const candidate = path33.join(
|
|
16038
16511
|
dir,
|
|
16039
16512
|
"templates",
|
|
16040
16513
|
"project",
|
|
@@ -16042,8 +16515,8 @@ function findKitTemplatesDir(start) {
|
|
|
16042
16515
|
".github",
|
|
16043
16516
|
"workflows"
|
|
16044
16517
|
);
|
|
16045
|
-
if (
|
|
16046
|
-
const parent =
|
|
16518
|
+
if (fs31.existsSync(candidate)) return candidate;
|
|
16519
|
+
const parent = path33.dirname(dir);
|
|
16047
16520
|
if (parent === dir) break;
|
|
16048
16521
|
dir = parent;
|
|
16049
16522
|
}
|
|
@@ -16067,13 +16540,13 @@ function unifiedDiff(name, projectContent, templateContent) {
|
|
|
16067
16540
|
return out.join("\n");
|
|
16068
16541
|
}
|
|
16069
16542
|
function detectWorkflowDrift(args) {
|
|
16070
|
-
const projectWorkflowsDir =
|
|
16543
|
+
const projectWorkflowsDir = path33.join(
|
|
16071
16544
|
args.projectDir,
|
|
16072
16545
|
".github",
|
|
16073
16546
|
"workflows"
|
|
16074
16547
|
);
|
|
16075
|
-
const here =
|
|
16076
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16548
|
+
const here = path33.dirname(new URL(import.meta.url).pathname);
|
|
16549
|
+
const kitWorkflowsDir = args.kitDir ? path33.join(
|
|
16077
16550
|
args.kitDir,
|
|
16078
16551
|
"templates",
|
|
16079
16552
|
"project",
|
|
@@ -16081,21 +16554,21 @@ function detectWorkflowDrift(args) {
|
|
|
16081
16554
|
".github",
|
|
16082
16555
|
"workflows"
|
|
16083
16556
|
) : findKitTemplatesDir(here);
|
|
16084
|
-
const templateFiles =
|
|
16085
|
-
const projectFiles =
|
|
16557
|
+
const templateFiles = fs31.existsSync(kitWorkflowsDir) ? fs31.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
16558
|
+
const projectFiles = fs31.existsSync(projectWorkflowsDir) ? fs31.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
16086
16559
|
const version = readKitVersion(kitWorkflowsDir);
|
|
16087
16560
|
const seen = /* @__PURE__ */ new Set();
|
|
16088
16561
|
const files = [];
|
|
16089
16562
|
for (const name of templateFiles) {
|
|
16090
16563
|
seen.add(name);
|
|
16091
|
-
const projectPath2 =
|
|
16092
|
-
const templatePath =
|
|
16093
|
-
if (!
|
|
16564
|
+
const projectPath2 = path33.join(projectWorkflowsDir, name);
|
|
16565
|
+
const templatePath = path33.join(kitWorkflowsDir, name);
|
|
16566
|
+
if (!fs31.existsSync(projectPath2)) {
|
|
16094
16567
|
files.push({ name, status: "missing" });
|
|
16095
16568
|
continue;
|
|
16096
16569
|
}
|
|
16097
|
-
const projectContent =
|
|
16098
|
-
const templateContent = applyPlaceholders(
|
|
16570
|
+
const projectContent = fs31.readFileSync(projectPath2, "utf8");
|
|
16571
|
+
const templateContent = applyPlaceholders(fs31.readFileSync(templatePath, "utf8"), version);
|
|
16099
16572
|
if (projectContent === templateContent) {
|
|
16100
16573
|
files.push({ name, status: "unchanged" });
|
|
16101
16574
|
} else {
|
|
@@ -16126,10 +16599,10 @@ function detectWorkflowDrift(args) {
|
|
|
16126
16599
|
function readKitVersion(kitWorkflowsDir) {
|
|
16127
16600
|
let dir = kitWorkflowsDir;
|
|
16128
16601
|
for (let i = 0; i < 5; i++) {
|
|
16129
|
-
dir =
|
|
16602
|
+
dir = path33.dirname(dir);
|
|
16130
16603
|
}
|
|
16131
16604
|
try {
|
|
16132
|
-
const raw =
|
|
16605
|
+
const raw = fs31.readFileSync(path33.join(dir, "package.json"), "utf-8");
|
|
16133
16606
|
const pkg = JSON.parse(raw);
|
|
16134
16607
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16135
16608
|
} catch {
|
|
@@ -16146,7 +16619,7 @@ var COMMAND_HOOK_FILE_PATTERN = /\.(pre|post)-hook\.md$/;
|
|
|
16146
16619
|
function findKitCommandsDir(start) {
|
|
16147
16620
|
let dir = start;
|
|
16148
16621
|
for (let i = 0; i < 6; i++) {
|
|
16149
|
-
const candidate =
|
|
16622
|
+
const candidate = path33.join(
|
|
16150
16623
|
dir,
|
|
16151
16624
|
"templates",
|
|
16152
16625
|
"project",
|
|
@@ -16154,8 +16627,8 @@ function findKitCommandsDir(start) {
|
|
|
16154
16627
|
".claude",
|
|
16155
16628
|
"commands"
|
|
16156
16629
|
);
|
|
16157
|
-
if (
|
|
16158
|
-
const parent =
|
|
16630
|
+
if (fs31.existsSync(candidate)) return candidate;
|
|
16631
|
+
const parent = path33.dirname(dir);
|
|
16159
16632
|
if (parent === dir) break;
|
|
16160
16633
|
dir = parent;
|
|
16161
16634
|
}
|
|
@@ -16168,24 +16641,24 @@ function parsePinnedVersion(content) {
|
|
|
16168
16641
|
return m ? m[1] : void 0;
|
|
16169
16642
|
}
|
|
16170
16643
|
function detectCommandDrift(args) {
|
|
16171
|
-
const projectCommandsDir =
|
|
16172
|
-
const here =
|
|
16173
|
-
const kitCommandsDir = args.kitDir ?
|
|
16644
|
+
const projectCommandsDir = path33.join(args.projectDir, ".claude", "commands");
|
|
16645
|
+
const here = path33.dirname(new URL(import.meta.url).pathname);
|
|
16646
|
+
const kitCommandsDir = args.kitDir ? path33.join(args.kitDir, "templates", "project", "common", ".claude", "commands") : findKitCommandsDir(here);
|
|
16174
16647
|
const kitVersion = readKitVersionFromCommandsDir(kitCommandsDir);
|
|
16175
|
-
const templateFiles =
|
|
16176
|
-
const projectFiles =
|
|
16648
|
+
const templateFiles = fs31.existsSync(kitCommandsDir) ? fs31.readdirSync(kitCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
16649
|
+
const projectFiles = fs31.existsSync(projectCommandsDir) ? fs31.readdirSync(projectCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
16177
16650
|
const seen = /* @__PURE__ */ new Set();
|
|
16178
16651
|
const files = [];
|
|
16179
16652
|
for (const name of templateFiles) {
|
|
16180
16653
|
seen.add(name);
|
|
16181
|
-
const projectPath2 =
|
|
16182
|
-
const templatePath =
|
|
16183
|
-
const templateRaw =
|
|
16184
|
-
if (!
|
|
16654
|
+
const projectPath2 = path33.join(projectCommandsDir, name);
|
|
16655
|
+
const templatePath = path33.join(kitCommandsDir, name);
|
|
16656
|
+
const templateRaw = fs31.readFileSync(templatePath, "utf8");
|
|
16657
|
+
if (!fs31.existsSync(projectPath2)) {
|
|
16185
16658
|
files.push({ name, status: "missing", kit_version: kitVersion });
|
|
16186
16659
|
continue;
|
|
16187
16660
|
}
|
|
16188
|
-
const projectContent =
|
|
16661
|
+
const projectContent = fs31.readFileSync(projectPath2, "utf8");
|
|
16189
16662
|
const pinned = parsePinnedVersion(projectContent);
|
|
16190
16663
|
const versionForCompare = pinned ?? kitVersion;
|
|
16191
16664
|
const templateContent = applyCommandPlaceholders(templateRaw, versionForCompare);
|
|
@@ -16223,10 +16696,10 @@ function detectCommandDrift(args) {
|
|
|
16223
16696
|
function readKitVersionFromCommandsDir(kitCommandsDir) {
|
|
16224
16697
|
let dir = kitCommandsDir;
|
|
16225
16698
|
for (let i = 0; i < 5; i++) {
|
|
16226
|
-
dir =
|
|
16699
|
+
dir = path33.dirname(dir);
|
|
16227
16700
|
}
|
|
16228
16701
|
try {
|
|
16229
|
-
const raw =
|
|
16702
|
+
const raw = fs31.readFileSync(path33.join(dir, "package.json"), "utf-8");
|
|
16230
16703
|
const pkg = JSON.parse(raw);
|
|
16231
16704
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16232
16705
|
} catch {
|
|
@@ -16243,13 +16716,13 @@ function detectScaffoldedDrift(args) {
|
|
|
16243
16716
|
};
|
|
16244
16717
|
}
|
|
16245
16718
|
function updateWorkflows(args) {
|
|
16246
|
-
const projectWorkflowsDir =
|
|
16719
|
+
const projectWorkflowsDir = path33.join(
|
|
16247
16720
|
args.projectDir,
|
|
16248
16721
|
".github",
|
|
16249
16722
|
"workflows"
|
|
16250
16723
|
);
|
|
16251
|
-
const here =
|
|
16252
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16724
|
+
const here = path33.dirname(new URL(import.meta.url).pathname);
|
|
16725
|
+
const kitWorkflowsDir = args.kitDir ? path33.join(
|
|
16253
16726
|
args.kitDir,
|
|
16254
16727
|
"templates",
|
|
16255
16728
|
"project",
|
|
@@ -16260,22 +16733,22 @@ function updateWorkflows(args) {
|
|
|
16260
16733
|
const substitute = args.substitute !== false;
|
|
16261
16734
|
const dryRun = args.dryRun === true;
|
|
16262
16735
|
const pruneExtras = args.pruneExtras === true;
|
|
16263
|
-
const templateFiles =
|
|
16264
|
-
const projectFiles =
|
|
16265
|
-
if (!dryRun && templateFiles.length > 0 && !
|
|
16266
|
-
|
|
16736
|
+
const templateFiles = fs31.existsSync(kitWorkflowsDir) ? fs31.readdirSync(kitWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
16737
|
+
const projectFiles = fs31.existsSync(projectWorkflowsDir) ? fs31.readdirSync(projectWorkflowsDir).filter((f) => f.endsWith(".yml")) : [];
|
|
16738
|
+
if (!dryRun && templateFiles.length > 0 && !fs31.existsSync(projectWorkflowsDir)) {
|
|
16739
|
+
fs31.mkdirSync(projectWorkflowsDir, { recursive: true });
|
|
16267
16740
|
}
|
|
16268
16741
|
const version = substitute ? readKitVersion(kitWorkflowsDir) : "";
|
|
16269
16742
|
const seen = /* @__PURE__ */ new Set();
|
|
16270
16743
|
const files = [];
|
|
16271
16744
|
for (const name of templateFiles) {
|
|
16272
16745
|
seen.add(name);
|
|
16273
|
-
const projectPath2 =
|
|
16274
|
-
const templatePath =
|
|
16275
|
-
const templateRaw =
|
|
16746
|
+
const projectPath2 = path33.join(projectWorkflowsDir, name);
|
|
16747
|
+
const templatePath = path33.join(kitWorkflowsDir, name);
|
|
16748
|
+
const templateRaw = fs31.readFileSync(templatePath, "utf-8");
|
|
16276
16749
|
const desired = substitute ? applyPlaceholders(templateRaw, version) : templateRaw;
|
|
16277
|
-
const existed =
|
|
16278
|
-
const current = existed ?
|
|
16750
|
+
const existed = fs31.existsSync(projectPath2);
|
|
16751
|
+
const current = existed ? fs31.readFileSync(projectPath2, "utf-8") : "";
|
|
16279
16752
|
let outcome;
|
|
16280
16753
|
if (!existed) {
|
|
16281
16754
|
outcome = "added";
|
|
@@ -16285,16 +16758,16 @@ function updateWorkflows(args) {
|
|
|
16285
16758
|
outcome = "updated";
|
|
16286
16759
|
}
|
|
16287
16760
|
if (!dryRun && outcome !== "unchanged") {
|
|
16288
|
-
|
|
16761
|
+
fs31.writeFileSync(projectPath2, desired);
|
|
16289
16762
|
}
|
|
16290
16763
|
files.push({ name, outcome });
|
|
16291
16764
|
}
|
|
16292
16765
|
if (pruneExtras) {
|
|
16293
16766
|
for (const name of projectFiles) {
|
|
16294
16767
|
if (seen.has(name)) continue;
|
|
16295
|
-
const projectPath2 =
|
|
16768
|
+
const projectPath2 = path33.join(projectWorkflowsDir, name);
|
|
16296
16769
|
if (!dryRun) {
|
|
16297
|
-
|
|
16770
|
+
fs31.unlinkSync(projectPath2);
|
|
16298
16771
|
}
|
|
16299
16772
|
files.push({ name, outcome: "removed" });
|
|
16300
16773
|
}
|
|
@@ -16892,15 +17365,15 @@ function parentForTopology(t, defaultLeaf) {
|
|
|
16892
17365
|
|
|
16893
17366
|
// scripts/lakebase/scm-doctor.ts
|
|
16894
17367
|
init_esm_shims();
|
|
16895
|
-
import * as
|
|
16896
|
-
import * as
|
|
17368
|
+
import * as fs32 from "fs";
|
|
17369
|
+
import * as path34 from "path";
|
|
16897
17370
|
var FEATURE_PREFIX = "feature/";
|
|
16898
17371
|
var TIER_LEAFS2 = DEFAULT_PROTECTED_TIER_NAMES;
|
|
16899
17372
|
function readEnv(projectDir) {
|
|
16900
|
-
const envPath =
|
|
17373
|
+
const envPath = path34.join(projectDir, ".env");
|
|
16901
17374
|
const out = /* @__PURE__ */ new Map();
|
|
16902
|
-
if (!
|
|
16903
|
-
const lines =
|
|
17375
|
+
if (!fs32.existsSync(envPath)) return out;
|
|
17376
|
+
const lines = fs32.readFileSync(envPath, "utf8").split("\n");
|
|
16904
17377
|
for (const line of lines) {
|
|
16905
17378
|
const m = line.match(/^\s*([A-Z0-9_]+)\s*=\s*(.+?)\s*$/);
|
|
16906
17379
|
if (m) out.set(m[1], m[2].replace(/^["']|["']$/g, ""));
|
|
@@ -16955,9 +17428,9 @@ async function runDoctor(args, deps = {}) {
|
|
|
16955
17428
|
}
|
|
16956
17429
|
for (const wf of ["pr.yml", "merge.yml"]) {
|
|
16957
17430
|
try {
|
|
16958
|
-
const p =
|
|
16959
|
-
if (!
|
|
16960
|
-
const body =
|
|
17431
|
+
const p = path34.join(projectDir, ".github", "workflows", wf);
|
|
17432
|
+
if (!fs32.existsSync(p)) continue;
|
|
17433
|
+
const body = fs32.readFileSync(p, "utf8");
|
|
16961
17434
|
if (/lakebase-scm-utils#v\d/.test(body)) {
|
|
16962
17435
|
findings.push({
|
|
16963
17436
|
id: "ci-workflow-substrate-pin",
|
|
@@ -17172,7 +17645,7 @@ async function fixFinding(args) {
|
|
|
17172
17645
|
);
|
|
17173
17646
|
}
|
|
17174
17647
|
const sanitized = sanitizeBranchName(branch);
|
|
17175
|
-
const envFile =
|
|
17648
|
+
const envFile = path34.join(args.projectDir, ".env");
|
|
17176
17649
|
updateEnvConnection({
|
|
17177
17650
|
envPath: envFile,
|
|
17178
17651
|
projectId: readEnvVar(envFile, "LAKEBASE_PROJECT_ID") ?? "",
|
|
@@ -17274,14 +17747,14 @@ function shellEscape3(s) {
|
|
|
17274
17747
|
|
|
17275
17748
|
// scripts/lakebase/doctor.ts
|
|
17276
17749
|
init_esm_shims();
|
|
17277
|
-
import * as
|
|
17278
|
-
import * as
|
|
17750
|
+
import * as fs33 from "fs";
|
|
17751
|
+
import * as path35 from "path";
|
|
17279
17752
|
import * as cp6 from "child_process";
|
|
17280
17753
|
function readEnvFile(projectDir) {
|
|
17281
|
-
const envPath =
|
|
17282
|
-
if (!
|
|
17754
|
+
const envPath = path35.join(projectDir, ".env");
|
|
17755
|
+
if (!fs33.existsSync(envPath)) return {};
|
|
17283
17756
|
const out = {};
|
|
17284
|
-
for (const line of
|
|
17757
|
+
for (const line of fs33.readFileSync(envPath, "utf8").split("\n")) {
|
|
17285
17758
|
const m = line.match(/^\s*([A-Z][A-Z0-9_]*)\s*=\s*(.*)\s*$/);
|
|
17286
17759
|
if (!m) continue;
|
|
17287
17760
|
let val = m[2];
|
|
@@ -17435,6 +17908,23 @@ async function checkPrereq(spec, run) {
|
|
|
17435
17908
|
detail: { version: trimmed }
|
|
17436
17909
|
};
|
|
17437
17910
|
}
|
|
17911
|
+
var DOTNET_PREREQ = {
|
|
17912
|
+
name: "dotnet-sdk",
|
|
17913
|
+
cmd: "dotnet",
|
|
17914
|
+
versionArgs: ["--version"],
|
|
17915
|
+
minMajor: 10,
|
|
17916
|
+
label: ".NET SDK",
|
|
17917
|
+
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."
|
|
17918
|
+
};
|
|
17919
|
+
async function checkLanguagePrerequisites(projectDir, run = defaultVersionRunner) {
|
|
17920
|
+
let lang;
|
|
17921
|
+
try {
|
|
17922
|
+
lang = detectLanguage(projectDir);
|
|
17923
|
+
} catch {
|
|
17924
|
+
return [];
|
|
17925
|
+
}
|
|
17926
|
+
return lang === "dotnet" ? [await checkPrereq(DOTNET_PREREQ, run)] : [];
|
|
17927
|
+
}
|
|
17438
17928
|
async function checkPrerequisites(run = defaultVersionRunner) {
|
|
17439
17929
|
return Promise.all(PREREQS.map((spec) => checkPrereq(spec, run)));
|
|
17440
17930
|
}
|
|
@@ -17536,7 +18026,7 @@ function checkEnv(projectDir) {
|
|
|
17536
18026
|
name: "env-file",
|
|
17537
18027
|
status: "warn",
|
|
17538
18028
|
message: ".env not found",
|
|
17539
|
-
detail: { projectDir, envPath:
|
|
18029
|
+
detail: { projectDir, envPath: path35.join(projectDir, ".env") },
|
|
17540
18030
|
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)."
|
|
17541
18031
|
};
|
|
17542
18032
|
}
|
|
@@ -17766,6 +18256,7 @@ async function runDoctor2(args = {}) {
|
|
|
17766
18256
|
const hooks = checkHooks(projectDir);
|
|
17767
18257
|
const workflowDrift = checkWorkflowDrift(projectDir);
|
|
17768
18258
|
const prereqs = await checkPrerequisites();
|
|
18259
|
+
const languagePrereqs = await checkLanguagePrerequisites(projectDir);
|
|
17769
18260
|
const lakebaseEnabled = auth7.status === "ok" ? await checkLakebaseEnabled(profile) : {
|
|
17770
18261
|
name: "lakebase-enabled",
|
|
17771
18262
|
status: "skip",
|
|
@@ -17774,6 +18265,7 @@ async function runDoctor2(args = {}) {
|
|
|
17774
18265
|
const checks = [
|
|
17775
18266
|
cli,
|
|
17776
18267
|
...prereqs,
|
|
18268
|
+
...languagePrereqs,
|
|
17777
18269
|
auth7,
|
|
17778
18270
|
identity,
|
|
17779
18271
|
lakebaseEnabled,
|
|
@@ -17956,12 +18448,16 @@ function isUcMissingError(msg) {
|
|
|
17956
18448
|
export {
|
|
17957
18449
|
CONVENTION_TIER_DEFAULTS,
|
|
17958
18450
|
DEFAULT_PROTECTED_TIER_NAMES,
|
|
18451
|
+
DOTNET_EFCORE_DEFAULTS,
|
|
18452
|
+
DOTNET_FLYWAY_DIR,
|
|
18453
|
+
EF_DESIGN_PACKAGE,
|
|
17959
18454
|
FIXABLE_FINDING_IDS,
|
|
17960
18455
|
InitializrNetworkError,
|
|
17961
18456
|
InitializrParseError,
|
|
17962
18457
|
LakebaseBranchError,
|
|
17963
18458
|
LakebaseBranchTtlTooLongError,
|
|
17964
18459
|
LakebaseProjectError,
|
|
18460
|
+
MAVEN_FLYWAY_DIR,
|
|
17965
18461
|
MIGRATION_DEFAULTS,
|
|
17966
18462
|
NODE_E2E_TEMPLATE_FILES,
|
|
17967
18463
|
PLAYWRIGHT_TEMPLATE_FILES,
|
|
@@ -18058,9 +18554,12 @@ export {
|
|
|
18058
18554
|
ensureSchemaAndVolume,
|
|
18059
18555
|
extractPullNumber,
|
|
18060
18556
|
featureBranchName,
|
|
18557
|
+
findCsprojFiles,
|
|
18061
18558
|
findDefaultBranchName,
|
|
18559
|
+
findEfCoreProject,
|
|
18062
18560
|
findHistoryRetentionDuration,
|
|
18063
18561
|
fixFinding,
|
|
18562
|
+
flywayMigrationsDir,
|
|
18064
18563
|
formatJUnit,
|
|
18065
18564
|
formatSchemaDiffAsMarkdown,
|
|
18066
18565
|
generateAppYaml,
|
|
@@ -18082,11 +18581,14 @@ export {
|
|
|
18082
18581
|
getTargetNames,
|
|
18083
18582
|
grantLakebasePermission,
|
|
18084
18583
|
grantUcCatalogPermission,
|
|
18584
|
+
hasDotnetMarker,
|
|
18085
18585
|
inferTierTopology,
|
|
18086
18586
|
initWorkflowState,
|
|
18087
18587
|
installHooks,
|
|
18088
18588
|
installPlaywright,
|
|
18089
18589
|
isAllSchemas,
|
|
18590
|
+
isDotnetFlywayProject,
|
|
18591
|
+
isDotnetProject,
|
|
18090
18592
|
isForeignFeatureClaim,
|
|
18091
18593
|
isGitTracked,
|
|
18092
18594
|
isLongRunningTierBranch,
|