betterstart-cli 0.0.72 → 0.0.74
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/cli.js +72 -76
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -115,7 +115,7 @@ function createInitCommand(runtime) {
|
|
|
115
115
|
).option("--database-provider <provider>", "Database provider: vercel, railway, or manual").option(
|
|
116
116
|
"--storage-provider <provider>",
|
|
117
117
|
"Storage provider: vercel-blob, railway-bucket, r2, or local"
|
|
118
|
-
).option("--deploy-provider <provider>", "Deploy provider: vercel, railway, or none").option("--database-plan <id>", "Neon plan id for a Vercel-provisioned database").option("--railway-workspace <id-or-name>", "Railway workspace for a new project").option("--railway-project <id-or-name>", "Railway project to reuse").option("--railway-environment <id-or-name>", "Railway environment (default: production)").option("--railway-service <id-or-name>", "Railway app service (default: web)").option(
|
|
118
|
+
).option("--deploy-provider <provider>", "Deploy provider: vercel, railway, or none").option("--database-plan <id>", "Neon plan id for a Vercel-provisioned database").option("--railway-workspace <id-or-name>", "Railway workspace for a new project").option("--railway-project <id-or-name>", "Existing Railway project to intentionally reuse").option("--railway-environment <id-or-name>", "Railway environment (default: production)").option("--railway-service <id-or-name>", "Railway app service (default: web)").option(
|
|
119
119
|
"--railway-bucket-region <region>",
|
|
120
120
|
"Railway bucket region: sjc, iad, ams, or sin (default: iad)"
|
|
121
121
|
).option("--force", "Overwrite all existing Admin files (nuclear option)").action(
|
|
@@ -22971,6 +22971,16 @@ function parseProjectSummary(value) {
|
|
|
22971
22971
|
}
|
|
22972
22972
|
return { id: project2.id, name: project2.name, workspace };
|
|
22973
22973
|
}
|
|
22974
|
+
var MAX_PROJECT_NAME_ATTEMPTS = 10;
|
|
22975
|
+
function versionedRailwayProjectName(base, attempt) {
|
|
22976
|
+
return attempt <= 1 ? base : `${base}-v${attempt}`;
|
|
22977
|
+
}
|
|
22978
|
+
function railwayProjectNameIsTaken(projects, candidate) {
|
|
22979
|
+
return projects.some((project2) => project2.name.toLowerCase() === candidate.toLowerCase());
|
|
22980
|
+
}
|
|
22981
|
+
function isRailwayProjectNameConflict(detail) {
|
|
22982
|
+
return /already exists|name.*taken|duplicate.*name/i.test(detail);
|
|
22983
|
+
}
|
|
22974
22984
|
async function readRailwayProjectContext(runner, cwd, environment, env) {
|
|
22975
22985
|
const result = await runRailway(runner, ["status", "--environment", environment, "--json"], {
|
|
22976
22986
|
cwd,
|
|
@@ -23039,18 +23049,26 @@ ${result.stderr}`) ?? `Could not link Railway project ${project2}.`
|
|
|
23039
23049
|
);
|
|
23040
23050
|
}
|
|
23041
23051
|
}
|
|
23042
|
-
async function createRailwayProject(runner, cwd, projectName, options) {
|
|
23043
|
-
const
|
|
23044
|
-
|
|
23045
|
-
|
|
23046
|
-
|
|
23047
|
-
|
|
23048
|
-
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
);
|
|
23052
|
+
async function createRailwayProject(runner, cwd, projectName, existingProjects, options) {
|
|
23053
|
+
const knownProjects = [...existingProjects];
|
|
23054
|
+
for (let attempt = 1; attempt <= MAX_PROJECT_NAME_ATTEMPTS; attempt++) {
|
|
23055
|
+
const candidate = versionedRailwayProjectName(projectName, attempt);
|
|
23056
|
+
if (railwayProjectNameIsTaken(knownProjects, candidate)) continue;
|
|
23057
|
+
const args = ["init", "--name", candidate, "--json"];
|
|
23058
|
+
if (options.workspace) args.push("--workspace", options.workspace);
|
|
23059
|
+
const result = await runRailway(runner, args, { cwd, mode: "capture", env: options.env });
|
|
23060
|
+
const project2 = result.success ? parseProjectSummary(parseRailwayJson(result.stdout)) : void 0;
|
|
23061
|
+
if (project2) return project2;
|
|
23062
|
+
const detail = railwayOutputTail(`${result.stdout}
|
|
23063
|
+
${result.stderr}`);
|
|
23064
|
+
if (!detail || !isRailwayProjectNameConflict(detail)) {
|
|
23065
|
+
throw new Error(detail ?? `Could not create Railway project ${candidate}.`);
|
|
23066
|
+
}
|
|
23067
|
+
knownProjects.push({ id: candidate, name: candidate });
|
|
23052
23068
|
}
|
|
23053
|
-
|
|
23069
|
+
throw new Error(
|
|
23070
|
+
`Could not create a unique Railway project name after ${MAX_PROJECT_NAME_ATTEMPTS} attempts.`
|
|
23071
|
+
);
|
|
23054
23072
|
}
|
|
23055
23073
|
async function ensureRailwayProject(runner, options) {
|
|
23056
23074
|
const environment = options.environment?.trim() || "production";
|
|
@@ -23063,77 +23081,47 @@ async function ensureRailwayProject(runner, options) {
|
|
|
23063
23081
|
env: options.env
|
|
23064
23082
|
});
|
|
23065
23083
|
} else {
|
|
23066
|
-
|
|
23067
|
-
if (
|
|
23084
|
+
let createWorkspace = options.workspace;
|
|
23085
|
+
if (!createWorkspace && options.workspaces?.length === 1) {
|
|
23086
|
+
createWorkspace = options.workspaces[0]?.id;
|
|
23087
|
+
} else if (!createWorkspace && options.interactive && options.workspaces?.length) {
|
|
23068
23088
|
projectSpinner.clear();
|
|
23069
|
-
|
|
23070
|
-
|
|
23071
|
-
|
|
23072
|
-
|
|
23073
|
-
|
|
23074
|
-
|
|
23075
|
-
const createValue = "__betterstart_create_railway_project__";
|
|
23076
|
-
const choice = await p15.select({
|
|
23077
|
-
message: "Choose a Railway project",
|
|
23078
|
-
options: [
|
|
23079
|
-
{
|
|
23080
|
-
value: createValue,
|
|
23081
|
-
label: `Create ${options.projectName}`,
|
|
23082
|
-
hint: "new project"
|
|
23083
|
-
},
|
|
23084
|
-
...projects.map((project2) => ({
|
|
23085
|
-
value: project2.id,
|
|
23086
|
-
label: project2.name,
|
|
23087
|
-
hint: project2.workspace?.name
|
|
23088
|
-
}))
|
|
23089
|
-
],
|
|
23090
|
-
initialValue: createValue
|
|
23089
|
+
const workspace = await p15.select({
|
|
23090
|
+
message: "Choose a Railway workspace",
|
|
23091
|
+
options: options.workspaces.map((candidate) => ({
|
|
23092
|
+
value: candidate.id,
|
|
23093
|
+
label: candidate.name
|
|
23094
|
+
}))
|
|
23091
23095
|
});
|
|
23092
|
-
if (p15.isCancel(
|
|
23096
|
+
if (p15.isCancel(workspace)) {
|
|
23093
23097
|
p15.cancel("Setup cancelled.");
|
|
23094
23098
|
process.exit(0);
|
|
23095
23099
|
}
|
|
23096
|
-
|
|
23097
|
-
|
|
23098
|
-
|
|
23099
|
-
|
|
23100
|
-
);
|
|
23101
|
-
|
|
23102
|
-
|
|
23103
|
-
|
|
23104
|
-
|
|
23105
|
-
|
|
23106
|
-
|
|
23107
|
-
let createWorkspace = options.workspace;
|
|
23108
|
-
if (!createWorkspace && options.workspaces?.length === 1) {
|
|
23109
|
-
createWorkspace = options.workspaces[0]?.id;
|
|
23110
|
-
} else if (!createWorkspace && options.interactive && options.workspaces?.length) {
|
|
23111
|
-
projectSpinner.clear();
|
|
23112
|
-
const workspace = await p15.select({
|
|
23113
|
-
message: "Choose a Railway workspace",
|
|
23114
|
-
options: options.workspaces.map((candidate) => ({
|
|
23115
|
-
value: candidate.id,
|
|
23116
|
-
label: candidate.name
|
|
23117
|
-
}))
|
|
23118
|
-
});
|
|
23119
|
-
if (p15.isCancel(workspace)) {
|
|
23120
|
-
p15.cancel("Setup cancelled.");
|
|
23121
|
-
process.exit(0);
|
|
23122
|
-
}
|
|
23123
|
-
createWorkspace = workspace;
|
|
23124
|
-
projectSpinner.start(`Creating Railway project ${pc2.cyan(options.projectName)}`);
|
|
23125
|
-
}
|
|
23126
|
-
const created = await createRailwayProject(runner, options.cwd, options.projectName, {
|
|
23100
|
+
createWorkspace = workspace;
|
|
23101
|
+
projectSpinner.start("Checking Railway project names");
|
|
23102
|
+
}
|
|
23103
|
+
const projects = await listRailwayProjects(runner, options.cwd, options.env);
|
|
23104
|
+
projectSpinner.start(`Creating Railway project ${pc2.cyan(options.projectName)}`);
|
|
23105
|
+
const created = await createRailwayProject(
|
|
23106
|
+
runner,
|
|
23107
|
+
options.cwd,
|
|
23108
|
+
options.projectName,
|
|
23109
|
+
projects,
|
|
23110
|
+
{
|
|
23127
23111
|
workspace: createWorkspace,
|
|
23128
23112
|
env: options.env
|
|
23129
|
-
});
|
|
23130
|
-
if (environment.toLowerCase() !== "production") {
|
|
23131
|
-
await linkRailwayProject(runner, options.cwd, created.id, environment, {
|
|
23132
|
-
workspace: created.workspace?.id ?? options.workspace,
|
|
23133
|
-
env: options.env
|
|
23134
|
-
});
|
|
23135
23113
|
}
|
|
23114
|
+
);
|
|
23115
|
+
await linkRailwayProject(runner, options.cwd, created.id, environment, {
|
|
23116
|
+
workspace: created.workspace?.id ?? createWorkspace,
|
|
23117
|
+
env: options.env
|
|
23118
|
+
});
|
|
23119
|
+
const context2 = await readRailwayProjectContext(runner, options.cwd, environment, options.env);
|
|
23120
|
+
if (!context2 || context2.id !== created.id) {
|
|
23121
|
+
throw new Error("Railway did not link the newly created project.");
|
|
23136
23122
|
}
|
|
23123
|
+
projectSpinner.clear();
|
|
23124
|
+
return context2;
|
|
23137
23125
|
}
|
|
23138
23126
|
const context = await readRailwayProjectContext(runner, options.cwd, environment, options.env);
|
|
23139
23127
|
projectSpinner.clear();
|
|
@@ -23587,13 +23575,22 @@ async function runRailwayDeployFlow(options) {
|
|
|
23587
23575
|
service,
|
|
23588
23576
|
options.session.env
|
|
23589
23577
|
);
|
|
23578
|
+
const url = await ensureRailwayDomain(options.session, options.cwd, service);
|
|
23579
|
+
if (!url) {
|
|
23580
|
+
throw new Error("Railway could not create a public domain required for Better Auth.");
|
|
23581
|
+
}
|
|
23582
|
+
const providerOverrides = {
|
|
23583
|
+
...options.providerOverrides,
|
|
23584
|
+
BETTERSTART_AUTH_URL: url,
|
|
23585
|
+
NEXT_PUBLIC_BETTERSTART_AUTH_URL: url
|
|
23586
|
+
};
|
|
23590
23587
|
const envSpinner = spinner2();
|
|
23591
23588
|
envSpinner.start("Syncing environment variables to Railway");
|
|
23592
23589
|
const sync = await syncRailwayServiceEnv(
|
|
23593
23590
|
options.session,
|
|
23594
23591
|
options.cwd,
|
|
23595
23592
|
service,
|
|
23596
|
-
|
|
23593
|
+
providerOverrides
|
|
23597
23594
|
);
|
|
23598
23595
|
envSpinner.clear();
|
|
23599
23596
|
for (const key of sync.failed) {
|
|
@@ -23662,7 +23659,6 @@ async function runRailwayDeployFlow(options) {
|
|
|
23662
23659
|
${deploy.stderr}`) ?? deploy.errorMessage
|
|
23663
23660
|
};
|
|
23664
23661
|
}
|
|
23665
|
-
const url = await ensureRailwayDomain(options.session, options.cwd, service);
|
|
23666
23662
|
deploySpinner.stop(url ? `Deployed ${pc3.cyan(url)}` : "Deployed to Railway");
|
|
23667
23663
|
return { ok: true, url, service, syncedEnvKeys: sync.synced };
|
|
23668
23664
|
} catch (error) {
|