betterstart-cli 0.0.30 → 0.0.32
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 +261 -304
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -21900,6 +21900,155 @@ function openBrowser(url) {
|
|
|
21900
21900
|
// adapters/next/init/prompts/plugins.ts
|
|
21901
21901
|
import { styleText } from "util";
|
|
21902
21902
|
import * as p11 from "@clack/prompts";
|
|
21903
|
+
|
|
21904
|
+
// adapters/next/init/scaffolders/env.ts
|
|
21905
|
+
import crypto2 from "crypto";
|
|
21906
|
+
|
|
21907
|
+
// adapters/next/init/scaffolders/dev-server.ts
|
|
21908
|
+
import fs26 from "fs";
|
|
21909
|
+
import path32 from "path";
|
|
21910
|
+
var DEFAULT_DEV_PORT = 4242;
|
|
21911
|
+
var DEV_PORT_FLAG_PATTERN = /(?:^|\s)(?:--port(?:=|\s+)|-p(?:=|\s+)?)(\d+)(?=\s|$)/;
|
|
21912
|
+
var DEV_PORT_ENV_PATTERN = /(?:^|\s)PORT=(\d+)(?=\s|$)/;
|
|
21913
|
+
function detectDevPort(cwd) {
|
|
21914
|
+
const pkg = readPackageJson2(cwd);
|
|
21915
|
+
if (!pkg) return DEFAULT_DEV_PORT;
|
|
21916
|
+
return detectDevPortFromScript(pkg.scripts?.dev) ?? DEFAULT_DEV_PORT;
|
|
21917
|
+
}
|
|
21918
|
+
function detectDevPortFromScript(devScript) {
|
|
21919
|
+
if (typeof devScript !== "string") return void 0;
|
|
21920
|
+
const trimmed = devScript.trim();
|
|
21921
|
+
if (trimmed.length === 0) return void 0;
|
|
21922
|
+
const flagMatch = trimmed.match(DEV_PORT_FLAG_PATTERN);
|
|
21923
|
+
const envMatch = trimmed.match(DEV_PORT_ENV_PATTERN);
|
|
21924
|
+
const rawPort = flagMatch?.[1] ?? envMatch?.[1];
|
|
21925
|
+
if (!rawPort) return void 0;
|
|
21926
|
+
const port = Number.parseInt(rawPort, 10);
|
|
21927
|
+
return isValidPort(port) ? port : void 0;
|
|
21928
|
+
}
|
|
21929
|
+
function ensureDefaultDevScriptPort(cwd) {
|
|
21930
|
+
const pkgPath = path32.join(cwd, "package.json");
|
|
21931
|
+
if (!fs26.existsSync(pkgPath)) {
|
|
21932
|
+
return { status: "missing-package", port: DEFAULT_DEV_PORT };
|
|
21933
|
+
}
|
|
21934
|
+
const raw = fs26.readFileSync(pkgPath, "utf-8");
|
|
21935
|
+
let pkg;
|
|
21936
|
+
try {
|
|
21937
|
+
pkg = JSON.parse(raw);
|
|
21938
|
+
} catch {
|
|
21939
|
+
return { status: "missing-package", port: DEFAULT_DEV_PORT };
|
|
21940
|
+
}
|
|
21941
|
+
const devScript = pkg.scripts?.dev;
|
|
21942
|
+
if (typeof devScript !== "string" || devScript.trim().length === 0) {
|
|
21943
|
+
return { status: "missing-script", port: DEFAULT_DEV_PORT };
|
|
21944
|
+
}
|
|
21945
|
+
const explicitPort = detectDevPortFromScript(devScript);
|
|
21946
|
+
if (explicitPort) {
|
|
21947
|
+
return { status: "preserved", port: explicitPort };
|
|
21948
|
+
}
|
|
21949
|
+
if (!isPlainNextDevScript(devScript)) {
|
|
21950
|
+
return { status: "skipped", port: DEFAULT_DEV_PORT };
|
|
21951
|
+
}
|
|
21952
|
+
const normalizedScript = `${normalizeWhitespace(devScript)} --port ${DEFAULT_DEV_PORT}`;
|
|
21953
|
+
pkg.scripts = {
|
|
21954
|
+
...pkg.scripts,
|
|
21955
|
+
dev: normalizedScript
|
|
21956
|
+
};
|
|
21957
|
+
const newline = raw.includes("\r\n") ? "\r\n" : "\n";
|
|
21958
|
+
const indent = detectIndent(raw);
|
|
21959
|
+
fs26.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, indent)}${newline}`, "utf-8");
|
|
21960
|
+
return { status: "updated", port: DEFAULT_DEV_PORT };
|
|
21961
|
+
}
|
|
21962
|
+
function readPackageJson2(cwd) {
|
|
21963
|
+
const pkgPath = path32.join(cwd, "package.json");
|
|
21964
|
+
if (!fs26.existsSync(pkgPath)) return void 0;
|
|
21965
|
+
try {
|
|
21966
|
+
return JSON.parse(fs26.readFileSync(pkgPath, "utf-8"));
|
|
21967
|
+
} catch {
|
|
21968
|
+
return void 0;
|
|
21969
|
+
}
|
|
21970
|
+
}
|
|
21971
|
+
function isPlainNextDevScript(devScript) {
|
|
21972
|
+
const normalized = normalizeWhitespace(devScript);
|
|
21973
|
+
return normalized === "next dev" || normalized === "next dev --turbopack" || normalized === "next dev --turbo";
|
|
21974
|
+
}
|
|
21975
|
+
function normalizeWhitespace(value) {
|
|
21976
|
+
return value.trim().replace(/\s+/g, " ");
|
|
21977
|
+
}
|
|
21978
|
+
function detectIndent(raw) {
|
|
21979
|
+
const indentMatch = raw.match(/^[ \t]+(?=")/m);
|
|
21980
|
+
return indentMatch?.[0] ?? 2;
|
|
21981
|
+
}
|
|
21982
|
+
function isValidPort(port) {
|
|
21983
|
+
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
21984
|
+
}
|
|
21985
|
+
|
|
21986
|
+
// adapters/next/init/scaffolders/env.ts
|
|
21987
|
+
var LEGACY_DEFAULT_AUTH_URL = "http://localhost:3000";
|
|
21988
|
+
function getCoreEnvSections(databaseUrl, devPort, namespace) {
|
|
21989
|
+
const authSecret = crypto2.randomBytes(32).toString("base64");
|
|
21990
|
+
return [
|
|
21991
|
+
{
|
|
21992
|
+
header: "Database (PostgreSQL)",
|
|
21993
|
+
vars: [{ key: "DATABASE_URL", value: databaseUrl ?? "postgresql://..." }]
|
|
21994
|
+
},
|
|
21995
|
+
{
|
|
21996
|
+
header: "Authentication",
|
|
21997
|
+
vars: [
|
|
21998
|
+
{ key: "BETTERSTART_AUTH_SECRET", value: authSecret },
|
|
21999
|
+
{ key: "BETTERSTART_AUTH_URL", value: `http://localhost:${devPort}` },
|
|
22000
|
+
{ key: "BETTERSTART_AUTH_BASE_PATH", value: `/api/${namespace}/auth` }
|
|
22001
|
+
]
|
|
22002
|
+
}
|
|
22003
|
+
];
|
|
22004
|
+
}
|
|
22005
|
+
function shouldOverwriteAuthUrl(cwd, devPort) {
|
|
22006
|
+
const existingAuthUrl = readEnvVar(cwd, "BETTERSTART_AUTH_URL");
|
|
22007
|
+
if (!existingAuthUrl) return false;
|
|
22008
|
+
return existingAuthUrl === LEGACY_DEFAULT_AUTH_URL && existingAuthUrl !== `http://localhost:${devPort}`;
|
|
22009
|
+
}
|
|
22010
|
+
function persistDatabaseUrl(cwd, databaseUrl) {
|
|
22011
|
+
appendEnvVars(
|
|
22012
|
+
cwd,
|
|
22013
|
+
[
|
|
22014
|
+
{
|
|
22015
|
+
header: "Database (PostgreSQL)",
|
|
22016
|
+
vars: [{ key: "DATABASE_URL", value: databaseUrl }]
|
|
22017
|
+
}
|
|
22018
|
+
],
|
|
22019
|
+
/* @__PURE__ */ new Set(["DATABASE_URL"])
|
|
22020
|
+
);
|
|
22021
|
+
}
|
|
22022
|
+
function persistBlobReadWriteToken(cwd, token) {
|
|
22023
|
+
appendEnvVars(
|
|
22024
|
+
cwd,
|
|
22025
|
+
[
|
|
22026
|
+
{
|
|
22027
|
+
header: "Storage (Vercel Blob)",
|
|
22028
|
+
vars: [{ key: "BLOB_READ_WRITE_TOKEN", value: token }]
|
|
22029
|
+
}
|
|
22030
|
+
],
|
|
22031
|
+
/* @__PURE__ */ new Set(["BLOB_READ_WRITE_TOKEN"])
|
|
22032
|
+
);
|
|
22033
|
+
}
|
|
22034
|
+
function scaffoldEnv(cwd, options) {
|
|
22035
|
+
const devPort = detectDevPort(cwd);
|
|
22036
|
+
const sections = getCoreEnvSections(options.databaseUrl, devPort, options.namespace ?? "admin");
|
|
22037
|
+
const authBasePath = `/api/${options.namespace ?? "admin"}/auth`;
|
|
22038
|
+
const overwrite = /* @__PURE__ */ new Set();
|
|
22039
|
+
if (options.databaseUrl) {
|
|
22040
|
+
overwrite.add("DATABASE_URL");
|
|
22041
|
+
}
|
|
22042
|
+
if (shouldOverwriteAuthUrl(cwd, devPort)) {
|
|
22043
|
+
overwrite.add("BETTERSTART_AUTH_URL");
|
|
22044
|
+
}
|
|
22045
|
+
if (readEnvVar(cwd, "BETTERSTART_AUTH_BASE_PATH") !== authBasePath) {
|
|
22046
|
+
overwrite.add("BETTERSTART_AUTH_BASE_PATH");
|
|
22047
|
+
}
|
|
22048
|
+
return appendEnvVars(cwd, sections, overwrite);
|
|
22049
|
+
}
|
|
22050
|
+
|
|
22051
|
+
// adapters/next/init/prompts/plugins.ts
|
|
21903
22052
|
async function promptPlugins(cwd, options = {}) {
|
|
21904
22053
|
const sections = [];
|
|
21905
22054
|
const overwriteKeys = /* @__PURE__ */ new Set();
|
|
@@ -21938,6 +22087,8 @@ async function promptPlugins(cwd, options = {}) {
|
|
|
21938
22087
|
const existingToken = readEnvVar(cwd, "BLOB_READ_WRITE_TOKEN")?.trim();
|
|
21939
22088
|
const flow = !existingToken && options.provisionVercelBlob ? await options.provisionVercelBlob() : void 0;
|
|
21940
22089
|
if (flow?.ok && flow.token) {
|
|
22090
|
+
persistBlobReadWriteToken(cwd, flow.token);
|
|
22091
|
+
p11.log.success("Saved BLOB_READ_WRITE_TOKEN to .env.local");
|
|
21941
22092
|
sections.push({
|
|
21942
22093
|
header: "Storage (Vercel Blob)",
|
|
21943
22094
|
vars: [{ key: "BLOB_READ_WRITE_TOKEN", value: flow.token }]
|
|
@@ -22045,53 +22196,53 @@ async function promptProject(defaultName) {
|
|
|
22045
22196
|
}
|
|
22046
22197
|
|
|
22047
22198
|
// adapters/next/init/scaffolders/api-routes.ts
|
|
22048
|
-
import
|
|
22199
|
+
import path34 from "path";
|
|
22049
22200
|
|
|
22050
22201
|
// core-engine/utils/fs.ts
|
|
22051
|
-
import
|
|
22052
|
-
import
|
|
22202
|
+
import fs27 from "fs";
|
|
22203
|
+
import path33 from "path";
|
|
22053
22204
|
import fse from "fs-extra";
|
|
22054
22205
|
function ensureDir(dirPath) {
|
|
22055
22206
|
fse.ensureDirSync(dirPath);
|
|
22056
22207
|
}
|
|
22057
22208
|
function safeWriteFile(filePath, content, force = false) {
|
|
22058
|
-
if (!force &&
|
|
22209
|
+
if (!force && fs27.existsSync(filePath)) {
|
|
22059
22210
|
return false;
|
|
22060
22211
|
}
|
|
22061
|
-
ensureDir(
|
|
22062
|
-
|
|
22212
|
+
ensureDir(path33.dirname(filePath));
|
|
22213
|
+
fs27.writeFileSync(filePath, content, "utf-8");
|
|
22063
22214
|
return true;
|
|
22064
22215
|
}
|
|
22065
22216
|
|
|
22066
22217
|
// adapters/next/init/scaffolders/api-routes.ts
|
|
22067
22218
|
function scaffoldApiRoutes({ cwd, config }) {
|
|
22068
22219
|
const created = [];
|
|
22069
|
-
const apiDir =
|
|
22220
|
+
const apiDir = path34.resolve(cwd, config.paths.api);
|
|
22070
22221
|
const namespace = config.frameworkConfig.next.namespace;
|
|
22071
22222
|
function write(relPath, content) {
|
|
22072
|
-
const fullPath =
|
|
22073
|
-
ensureDir(
|
|
22223
|
+
const fullPath = path34.join(apiDir, relPath);
|
|
22224
|
+
ensureDir(path34.dirname(fullPath));
|
|
22074
22225
|
const versionedContent = applyNextCacheApiForVersion(content, config.nextMajorVersion);
|
|
22075
22226
|
if (safeWriteFile(fullPath, applyAdminNamespaceToContent(versionedContent, namespace))) {
|
|
22076
|
-
created.push(
|
|
22227
|
+
created.push(path34.join(config.paths.api, relPath));
|
|
22077
22228
|
}
|
|
22078
22229
|
}
|
|
22079
|
-
write(
|
|
22080
|
-
write(
|
|
22230
|
+
write(path34.join("auth", "[...all]", "route.ts"), readTemplate("api/auth-route.ts"));
|
|
22231
|
+
write(path34.join("upload", "route.ts"), readTemplate("api/upload-route.ts"));
|
|
22081
22232
|
return created;
|
|
22082
22233
|
}
|
|
22083
22234
|
|
|
22084
22235
|
// adapters/next/init/scaffolders/auth.ts
|
|
22085
|
-
import
|
|
22236
|
+
import path35 from "path";
|
|
22086
22237
|
function scaffoldAuth({ cwd, config }) {
|
|
22087
22238
|
const created = [];
|
|
22088
|
-
const authDir =
|
|
22239
|
+
const authDir = path35.resolve(cwd, config.paths.admin, "lib", "actions", "auth");
|
|
22089
22240
|
const namespace = config.frameworkConfig.next.namespace;
|
|
22090
22241
|
function write(filename, content) {
|
|
22091
22242
|
const outputFile = applyAdminNamespaceToPath(filename, namespace);
|
|
22092
|
-
const fullPath =
|
|
22243
|
+
const fullPath = path35.join(authDir, outputFile);
|
|
22093
22244
|
if (safeWriteFile(fullPath, applyAdminNamespaceToContent(content, namespace))) {
|
|
22094
|
-
created.push(
|
|
22245
|
+
created.push(path35.join(config.paths.admin, "lib", "actions", "auth", outputFile));
|
|
22095
22246
|
}
|
|
22096
22247
|
}
|
|
22097
22248
|
write("server.ts", readTemplate("lib/actions/auth/auth.ts"));
|
|
@@ -22101,7 +22252,7 @@ function scaffoldAuth({ cwd, config }) {
|
|
|
22101
22252
|
}
|
|
22102
22253
|
|
|
22103
22254
|
// adapters/next/init/scaffolders/base.ts
|
|
22104
|
-
import
|
|
22255
|
+
import path36 from "path";
|
|
22105
22256
|
function scaffoldBase({
|
|
22106
22257
|
cwd,
|
|
22107
22258
|
config,
|
|
@@ -22111,58 +22262,58 @@ function scaffoldBase({
|
|
|
22111
22262
|
const adminDirs = [
|
|
22112
22263
|
config.paths.admin,
|
|
22113
22264
|
config.paths.schemas,
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
|
|
22129
|
-
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
|
|
22136
|
-
|
|
22137
|
-
|
|
22138
|
-
|
|
22265
|
+
path36.join(config.paths.admin, "lib"),
|
|
22266
|
+
path36.join(config.paths.admin, "lib", "db"),
|
|
22267
|
+
path36.join(config.paths.admin, "lib", "db", "core"),
|
|
22268
|
+
path36.join(config.paths.admin, "lib", "db", "migrations"),
|
|
22269
|
+
path36.join(config.paths.admin, "lib", "actions"),
|
|
22270
|
+
path36.join(config.paths.admin, "lib", "actions", "auth"),
|
|
22271
|
+
path36.join(config.paths.admin, "lib", "actions", "email"),
|
|
22272
|
+
path36.join(config.paths.admin, "lib", "actions", "forms"),
|
|
22273
|
+
path36.join(config.paths.admin, "lib", "actions", "media"),
|
|
22274
|
+
path36.join(config.paths.admin, "lib", "actions", "profile"),
|
|
22275
|
+
path36.join(config.paths.admin, "lib", "actions", "storage"),
|
|
22276
|
+
path36.join(config.paths.admin, "lib", "actions", "upload"),
|
|
22277
|
+
path36.join(config.paths.admin, "lib", "actions", "users"),
|
|
22278
|
+
path36.join(config.paths.admin, "hooks"),
|
|
22279
|
+
path36.join(config.paths.admin, "components", "ui"),
|
|
22280
|
+
path36.join(config.paths.admin, "components", "custom"),
|
|
22281
|
+
path36.join(config.paths.admin, "components", "layouts"),
|
|
22282
|
+
path36.join(config.paths.admin, "components", "shared"),
|
|
22283
|
+
path36.join(config.paths.admin, "components", "shared", "data-table"),
|
|
22284
|
+
path36.join(config.paths.admin, "components", "shared", "media"),
|
|
22285
|
+
path36.join(config.paths.admin, "data"),
|
|
22286
|
+
path36.join(config.paths.admin, "data", "navigation"),
|
|
22287
|
+
path36.join(config.paths.admin, "types"),
|
|
22288
|
+
path36.join(config.paths.admin, "utils"),
|
|
22289
|
+
path36.join(config.paths.admin, "utils", "core")
|
|
22139
22290
|
];
|
|
22140
22291
|
if (includeEmailTemplatesDir) {
|
|
22141
|
-
adminDirs.push(
|
|
22292
|
+
adminDirs.push(path36.join(config.paths.admin, "components", "email-templates"));
|
|
22142
22293
|
}
|
|
22143
22294
|
for (const dir of adminDirs) {
|
|
22144
|
-
ensureDir(
|
|
22295
|
+
ensureDir(path36.resolve(cwd, dir));
|
|
22145
22296
|
}
|
|
22146
|
-
const adminDir =
|
|
22297
|
+
const adminDir = path36.dirname(config.paths.pages);
|
|
22147
22298
|
const appDirs = [
|
|
22148
22299
|
config.paths.pages,
|
|
22149
22300
|
config.paths.login,
|
|
22150
22301
|
config.paths.api,
|
|
22151
|
-
|
|
22302
|
+
path36.join(adminDir, "(account)", "profile")
|
|
22152
22303
|
];
|
|
22153
22304
|
for (const dir of appDirs) {
|
|
22154
|
-
ensureDir(
|
|
22305
|
+
ensureDir(path36.resolve(cwd, dir));
|
|
22155
22306
|
}
|
|
22156
22307
|
const configContent = serializeConfig(config);
|
|
22157
|
-
if (safeWriteFile(
|
|
22308
|
+
if (safeWriteFile(path36.resolve(cwd, "admin.config.ts"), configContent)) {
|
|
22158
22309
|
created.push("admin.config.ts");
|
|
22159
22310
|
}
|
|
22160
22311
|
return created;
|
|
22161
22312
|
}
|
|
22162
22313
|
|
|
22163
22314
|
// adapters/next/init/scaffolders/biome.ts
|
|
22164
|
-
import
|
|
22165
|
-
import
|
|
22315
|
+
import fs28 from "fs";
|
|
22316
|
+
import path37 from "path";
|
|
22166
22317
|
function scaffoldBiome(cwd, linter) {
|
|
22167
22318
|
if (linter.type !== "none") {
|
|
22168
22319
|
return {
|
|
@@ -22170,8 +22321,8 @@ function scaffoldBiome(cwd, linter) {
|
|
|
22170
22321
|
skippedReason: `${linter.type} already configured (${linter.configFile})`
|
|
22171
22322
|
};
|
|
22172
22323
|
}
|
|
22173
|
-
const configPath =
|
|
22174
|
-
if (
|
|
22324
|
+
const configPath = path37.join(cwd, "biome.json");
|
|
22325
|
+
if (fs28.existsSync(configPath)) {
|
|
22175
22326
|
return { installed: false, skippedReason: "biome.json already exists" };
|
|
22176
22327
|
}
|
|
22177
22328
|
const config = {
|
|
@@ -22234,13 +22385,13 @@ function scaffoldBiome(cwd, linter) {
|
|
|
22234
22385
|
]
|
|
22235
22386
|
}
|
|
22236
22387
|
};
|
|
22237
|
-
|
|
22388
|
+
fs28.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}
|
|
22238
22389
|
`, "utf-8");
|
|
22239
22390
|
return { installed: true, skippedReason: null };
|
|
22240
22391
|
}
|
|
22241
22392
|
|
|
22242
22393
|
// adapters/next/init/scaffolders/components.ts
|
|
22243
|
-
import
|
|
22394
|
+
import path38 from "path";
|
|
22244
22395
|
|
|
22245
22396
|
// adapters/next/init/templates/app/admin.ts
|
|
22246
22397
|
function adminDataTemplate(projectName, namespaceValue = DEFAULT_ADMIN_NAMESPACE) {
|
|
@@ -22252,17 +22403,17 @@ function adminDataTemplate(projectName, namespaceValue = DEFAULT_ADMIN_NAMESPACE
|
|
|
22252
22403
|
}
|
|
22253
22404
|
|
|
22254
22405
|
// adapters/next/init/scaffolders/components.ts
|
|
22255
|
-
import
|
|
22406
|
+
import fs29 from "fs-extra";
|
|
22256
22407
|
function scaffoldComponents({ cwd, config }) {
|
|
22257
|
-
const admin =
|
|
22408
|
+
const admin = path38.resolve(cwd, config.paths.admin);
|
|
22258
22409
|
const created = [];
|
|
22259
22410
|
const namespace = config.frameworkConfig.next.namespace;
|
|
22260
22411
|
function write(relPath, content) {
|
|
22261
22412
|
const namespacedRelPath = applyAdminNamespaceToPath(relPath, namespace);
|
|
22262
|
-
const fullPath =
|
|
22413
|
+
const fullPath = path38.join(admin, namespacedRelPath);
|
|
22263
22414
|
const versionedContent = applyNextCacheApiForVersion(content, config.nextMajorVersion);
|
|
22264
22415
|
if (safeWriteFile(fullPath, applyAdminNamespaceToContent(versionedContent, namespace))) {
|
|
22265
|
-
created.push(
|
|
22416
|
+
created.push(path38.join(config.paths.admin, namespacedRelPath));
|
|
22266
22417
|
}
|
|
22267
22418
|
}
|
|
22268
22419
|
write("admin-globals.css", readTemplate("admin-globals.css"));
|
|
@@ -22695,49 +22846,49 @@ function copyCustomTemplates(cwd, config) {
|
|
|
22695
22846
|
}
|
|
22696
22847
|
function copyStaticComponentTemplates(cwd, config, sourceDirectory, targetDirectory) {
|
|
22697
22848
|
const created = [];
|
|
22698
|
-
const destDir =
|
|
22849
|
+
const destDir = path38.resolve(cwd, config.paths.admin, "components", targetDirectory);
|
|
22699
22850
|
const srcDir = resolveCliAssetPath("shared-assets", "react-admin", sourceDirectory);
|
|
22700
|
-
if (!
|
|
22851
|
+
if (!fs29.existsSync(srcDir)) {
|
|
22701
22852
|
return created;
|
|
22702
22853
|
}
|
|
22703
|
-
|
|
22854
|
+
fs29.ensureDirSync(destDir);
|
|
22704
22855
|
if (sourceDirectory === "custom") {
|
|
22705
22856
|
copyStaticComponentTemplatesRecursive(
|
|
22706
22857
|
srcDir,
|
|
22707
22858
|
destDir,
|
|
22708
22859
|
"",
|
|
22709
|
-
|
|
22860
|
+
path38.join(config.paths.admin, "components", targetDirectory),
|
|
22710
22861
|
config.frameworkConfig.next.namespace,
|
|
22711
22862
|
created
|
|
22712
22863
|
);
|
|
22713
22864
|
return created;
|
|
22714
22865
|
}
|
|
22715
|
-
const files =
|
|
22866
|
+
const files = fs29.readdirSync(srcDir, { withFileTypes: true }).filter(
|
|
22716
22867
|
(entry) => entry.isFile() && (entry.name.endsWith(".tsx") || entry.name.endsWith(".ts"))
|
|
22717
22868
|
).map((entry) => entry.name);
|
|
22718
22869
|
for (const file of files) {
|
|
22719
22870
|
const namespacedFile = applyAdminNamespaceToPath(file, config.frameworkConfig.next.namespace);
|
|
22720
|
-
const destPath =
|
|
22721
|
-
if (!
|
|
22722
|
-
const content =
|
|
22723
|
-
|
|
22871
|
+
const destPath = path38.join(destDir, namespacedFile);
|
|
22872
|
+
if (!fs29.existsSync(destPath)) {
|
|
22873
|
+
const content = fs29.readFileSync(path38.join(srcDir, file), "utf-8");
|
|
22874
|
+
fs29.writeFileSync(
|
|
22724
22875
|
destPath,
|
|
22725
22876
|
applyAdminNamespaceToContent(content, config.frameworkConfig.next.namespace),
|
|
22726
22877
|
"utf-8"
|
|
22727
22878
|
);
|
|
22728
|
-
created.push(
|
|
22879
|
+
created.push(path38.join(config.paths.admin, "components", targetDirectory, namespacedFile));
|
|
22729
22880
|
}
|
|
22730
22881
|
}
|
|
22731
22882
|
return created;
|
|
22732
22883
|
}
|
|
22733
22884
|
function copyStaticComponentTemplatesRecursive(srcDir, destDir, relBase, createdPrefix, namespace, created) {
|
|
22734
|
-
const entries =
|
|
22885
|
+
const entries = fs29.readdirSync(srcDir, { withFileTypes: true });
|
|
22735
22886
|
for (const entry of entries) {
|
|
22736
|
-
const rel =
|
|
22737
|
-
const srcPath =
|
|
22738
|
-
const destPath =
|
|
22887
|
+
const rel = path38.join(relBase, entry.name);
|
|
22888
|
+
const srcPath = path38.join(srcDir, entry.name);
|
|
22889
|
+
const destPath = path38.join(destDir, entry.name);
|
|
22739
22890
|
if (entry.isDirectory()) {
|
|
22740
|
-
const namespacedDestPath2 =
|
|
22891
|
+
const namespacedDestPath2 = path38.join(
|
|
22741
22892
|
destDir,
|
|
22742
22893
|
applyAdminNamespaceToPath(entry.name, namespace)
|
|
22743
22894
|
);
|
|
@@ -22755,37 +22906,37 @@ function copyStaticComponentTemplatesRecursive(srcDir, destDir, relBase, created
|
|
|
22755
22906
|
continue;
|
|
22756
22907
|
}
|
|
22757
22908
|
const namespacedRel = applyAdminNamespaceToPath(rel, namespace);
|
|
22758
|
-
const namespacedDestPath =
|
|
22759
|
-
|
|
22909
|
+
const namespacedDestPath = path38.join(
|
|
22910
|
+
path38.dirname(destPath),
|
|
22760
22911
|
applyAdminNamespaceToPath(entry.name, namespace)
|
|
22761
22912
|
);
|
|
22762
|
-
if (!
|
|
22763
|
-
|
|
22764
|
-
const content =
|
|
22765
|
-
|
|
22913
|
+
if (!fs29.existsSync(namespacedDestPath)) {
|
|
22914
|
+
fs29.ensureDirSync(path38.dirname(namespacedDestPath));
|
|
22915
|
+
const content = fs29.readFileSync(srcPath, "utf-8");
|
|
22916
|
+
fs29.writeFileSync(
|
|
22766
22917
|
namespacedDestPath,
|
|
22767
22918
|
applyAdminNamespaceToContent(content, namespace),
|
|
22768
22919
|
"utf-8"
|
|
22769
22920
|
);
|
|
22770
|
-
created.push(
|
|
22921
|
+
created.push(path38.join(createdPrefix, namespacedRel));
|
|
22771
22922
|
}
|
|
22772
22923
|
}
|
|
22773
22924
|
}
|
|
22774
22925
|
function copySchemaMetaschema(cwd, config) {
|
|
22775
22926
|
const created = [];
|
|
22776
22927
|
const srcPath = resolveCliAssetPath("shared-assets", "react-admin", "schema.json");
|
|
22777
|
-
const destPath =
|
|
22778
|
-
if (
|
|
22779
|
-
|
|
22780
|
-
|
|
22781
|
-
created.push(
|
|
22928
|
+
const destPath = path38.resolve(cwd, config.paths.schemas, "schema.json");
|
|
22929
|
+
if (fs29.existsSync(srcPath) && !fs29.existsSync(destPath)) {
|
|
22930
|
+
fs29.ensureDirSync(path38.dirname(destPath));
|
|
22931
|
+
fs29.copyFileSync(srcPath, destPath);
|
|
22932
|
+
created.push(path38.join(config.paths.schemas, "schema.json"));
|
|
22782
22933
|
}
|
|
22783
22934
|
return created;
|
|
22784
22935
|
}
|
|
22785
22936
|
|
|
22786
22937
|
// adapters/next/init/scaffolders/core-schemas.ts
|
|
22787
|
-
import
|
|
22788
|
-
import
|
|
22938
|
+
import fs30 from "fs";
|
|
22939
|
+
import path39 from "path";
|
|
22789
22940
|
|
|
22790
22941
|
// adapters/next/init/templates/core/default-settings.ts
|
|
22791
22942
|
function defaultSettingsSchema() {
|
|
@@ -22865,9 +23016,9 @@ function scaffoldCoreSchemas({
|
|
|
22865
23016
|
};
|
|
22866
23017
|
const schemaContent = defaultSettingsSchema();
|
|
22867
23018
|
const schemaName = "settings";
|
|
22868
|
-
const schemaPath =
|
|
22869
|
-
|
|
22870
|
-
|
|
23019
|
+
const schemaPath = path39.join(cwd, config.paths.schemas, `${schemaName}.json`);
|
|
23020
|
+
fs30.mkdirSync(path39.dirname(schemaPath), { recursive: true });
|
|
23021
|
+
fs30.writeFileSync(schemaPath, schemaContent, "utf-8");
|
|
22871
23022
|
result.schemas.push(`${schemaName}.json`);
|
|
22872
23023
|
ensureSnapshotGitFiles(cwd);
|
|
22873
23024
|
try {
|
|
@@ -22912,21 +23063,21 @@ function scaffoldCoreSchemas({
|
|
|
22912
23063
|
}
|
|
22913
23064
|
|
|
22914
23065
|
// adapters/next/init/scaffolders/database.ts
|
|
22915
|
-
import
|
|
23066
|
+
import path40 from "path";
|
|
22916
23067
|
function scaffoldDatabase({ cwd, config }) {
|
|
22917
23068
|
const created = [];
|
|
22918
|
-
const dbDir =
|
|
23069
|
+
const dbDir = path40.resolve(cwd, config.paths.admin, "lib", "db");
|
|
22919
23070
|
const namespace = config.frameworkConfig.next.namespace;
|
|
22920
23071
|
function write(filename, content) {
|
|
22921
|
-
const fullPath =
|
|
23072
|
+
const fullPath = path40.join(dbDir, filename);
|
|
22922
23073
|
if (safeWriteFile(fullPath, applyAdminNamespaceToContent(content, namespace))) {
|
|
22923
|
-
created.push(
|
|
23074
|
+
created.push(path40.join(config.paths.admin, "lib", "db", filename));
|
|
22924
23075
|
}
|
|
22925
23076
|
}
|
|
22926
23077
|
write("client.ts", readTemplate("lib/db/client.ts"));
|
|
22927
23078
|
write("core/schema.ts", readTemplate("lib/db/core/schema.ts"));
|
|
22928
23079
|
write("schema.ts", readTemplate("lib/db/schema.ts"));
|
|
22929
|
-
const drizzleConfigPath =
|
|
23080
|
+
const drizzleConfigPath = path40.resolve(cwd, "drizzle.config.ts");
|
|
22930
23081
|
if (safeWriteFile(
|
|
22931
23082
|
drizzleConfigPath,
|
|
22932
23083
|
applyAdminNamespaceToContent(readTemplate("drizzle.config.ts"), namespace)
|
|
@@ -22936,139 +23087,6 @@ function scaffoldDatabase({ cwd, config }) {
|
|
|
22936
23087
|
return created;
|
|
22937
23088
|
}
|
|
22938
23089
|
|
|
22939
|
-
// adapters/next/init/scaffolders/dev-server.ts
|
|
22940
|
-
import fs30 from "fs";
|
|
22941
|
-
import path40 from "path";
|
|
22942
|
-
var DEFAULT_DEV_PORT = 4242;
|
|
22943
|
-
var DEV_PORT_FLAG_PATTERN = /(?:^|\s)(?:--port(?:=|\s+)|-p(?:=|\s+)?)(\d+)(?=\s|$)/;
|
|
22944
|
-
var DEV_PORT_ENV_PATTERN = /(?:^|\s)PORT=(\d+)(?=\s|$)/;
|
|
22945
|
-
function detectDevPort(cwd) {
|
|
22946
|
-
const pkg = readPackageJson2(cwd);
|
|
22947
|
-
if (!pkg) return DEFAULT_DEV_PORT;
|
|
22948
|
-
return detectDevPortFromScript(pkg.scripts?.dev) ?? DEFAULT_DEV_PORT;
|
|
22949
|
-
}
|
|
22950
|
-
function detectDevPortFromScript(devScript) {
|
|
22951
|
-
if (typeof devScript !== "string") return void 0;
|
|
22952
|
-
const trimmed = devScript.trim();
|
|
22953
|
-
if (trimmed.length === 0) return void 0;
|
|
22954
|
-
const flagMatch = trimmed.match(DEV_PORT_FLAG_PATTERN);
|
|
22955
|
-
const envMatch = trimmed.match(DEV_PORT_ENV_PATTERN);
|
|
22956
|
-
const rawPort = flagMatch?.[1] ?? envMatch?.[1];
|
|
22957
|
-
if (!rawPort) return void 0;
|
|
22958
|
-
const port = Number.parseInt(rawPort, 10);
|
|
22959
|
-
return isValidPort(port) ? port : void 0;
|
|
22960
|
-
}
|
|
22961
|
-
function ensureDefaultDevScriptPort(cwd) {
|
|
22962
|
-
const pkgPath = path40.join(cwd, "package.json");
|
|
22963
|
-
if (!fs30.existsSync(pkgPath)) {
|
|
22964
|
-
return { status: "missing-package", port: DEFAULT_DEV_PORT };
|
|
22965
|
-
}
|
|
22966
|
-
const raw = fs30.readFileSync(pkgPath, "utf-8");
|
|
22967
|
-
let pkg;
|
|
22968
|
-
try {
|
|
22969
|
-
pkg = JSON.parse(raw);
|
|
22970
|
-
} catch {
|
|
22971
|
-
return { status: "missing-package", port: DEFAULT_DEV_PORT };
|
|
22972
|
-
}
|
|
22973
|
-
const devScript = pkg.scripts?.dev;
|
|
22974
|
-
if (typeof devScript !== "string" || devScript.trim().length === 0) {
|
|
22975
|
-
return { status: "missing-script", port: DEFAULT_DEV_PORT };
|
|
22976
|
-
}
|
|
22977
|
-
const explicitPort = detectDevPortFromScript(devScript);
|
|
22978
|
-
if (explicitPort) {
|
|
22979
|
-
return { status: "preserved", port: explicitPort };
|
|
22980
|
-
}
|
|
22981
|
-
if (!isPlainNextDevScript(devScript)) {
|
|
22982
|
-
return { status: "skipped", port: DEFAULT_DEV_PORT };
|
|
22983
|
-
}
|
|
22984
|
-
const normalizedScript = `${normalizeWhitespace(devScript)} --port ${DEFAULT_DEV_PORT}`;
|
|
22985
|
-
pkg.scripts = {
|
|
22986
|
-
...pkg.scripts,
|
|
22987
|
-
dev: normalizedScript
|
|
22988
|
-
};
|
|
22989
|
-
const newline = raw.includes("\r\n") ? "\r\n" : "\n";
|
|
22990
|
-
const indent = detectIndent(raw);
|
|
22991
|
-
fs30.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, indent)}${newline}`, "utf-8");
|
|
22992
|
-
return { status: "updated", port: DEFAULT_DEV_PORT };
|
|
22993
|
-
}
|
|
22994
|
-
function readPackageJson2(cwd) {
|
|
22995
|
-
const pkgPath = path40.join(cwd, "package.json");
|
|
22996
|
-
if (!fs30.existsSync(pkgPath)) return void 0;
|
|
22997
|
-
try {
|
|
22998
|
-
return JSON.parse(fs30.readFileSync(pkgPath, "utf-8"));
|
|
22999
|
-
} catch {
|
|
23000
|
-
return void 0;
|
|
23001
|
-
}
|
|
23002
|
-
}
|
|
23003
|
-
function isPlainNextDevScript(devScript) {
|
|
23004
|
-
const normalized = normalizeWhitespace(devScript);
|
|
23005
|
-
return normalized === "next dev" || normalized === "next dev --turbopack" || normalized === "next dev --turbo";
|
|
23006
|
-
}
|
|
23007
|
-
function normalizeWhitespace(value) {
|
|
23008
|
-
return value.trim().replace(/\s+/g, " ");
|
|
23009
|
-
}
|
|
23010
|
-
function detectIndent(raw) {
|
|
23011
|
-
const indentMatch = raw.match(/^[ \t]+(?=")/m);
|
|
23012
|
-
return indentMatch?.[0] ?? 2;
|
|
23013
|
-
}
|
|
23014
|
-
function isValidPort(port) {
|
|
23015
|
-
return Number.isInteger(port) && port > 0 && port <= 65535;
|
|
23016
|
-
}
|
|
23017
|
-
|
|
23018
|
-
// adapters/next/init/scaffolders/env.ts
|
|
23019
|
-
import crypto2 from "crypto";
|
|
23020
|
-
var LEGACY_DEFAULT_AUTH_URL = "http://localhost:3000";
|
|
23021
|
-
function getCoreEnvSections(databaseUrl, devPort, namespace) {
|
|
23022
|
-
const authSecret = crypto2.randomBytes(32).toString("base64");
|
|
23023
|
-
return [
|
|
23024
|
-
{
|
|
23025
|
-
header: "Database (PostgreSQL)",
|
|
23026
|
-
vars: [{ key: "DATABASE_URL", value: databaseUrl ?? "postgresql://..." }]
|
|
23027
|
-
},
|
|
23028
|
-
{
|
|
23029
|
-
header: "Authentication",
|
|
23030
|
-
vars: [
|
|
23031
|
-
{ key: "BETTERSTART_AUTH_SECRET", value: authSecret },
|
|
23032
|
-
{ key: "BETTERSTART_AUTH_URL", value: `http://localhost:${devPort}` },
|
|
23033
|
-
{ key: "BETTERSTART_AUTH_BASE_PATH", value: `/api/${namespace}/auth` }
|
|
23034
|
-
]
|
|
23035
|
-
}
|
|
23036
|
-
];
|
|
23037
|
-
}
|
|
23038
|
-
function shouldOverwriteAuthUrl(cwd, devPort) {
|
|
23039
|
-
const existingAuthUrl = readEnvVar(cwd, "BETTERSTART_AUTH_URL");
|
|
23040
|
-
if (!existingAuthUrl) return false;
|
|
23041
|
-
return existingAuthUrl === LEGACY_DEFAULT_AUTH_URL && existingAuthUrl !== `http://localhost:${devPort}`;
|
|
23042
|
-
}
|
|
23043
|
-
function persistDatabaseUrl(cwd, databaseUrl) {
|
|
23044
|
-
appendEnvVars(
|
|
23045
|
-
cwd,
|
|
23046
|
-
[
|
|
23047
|
-
{
|
|
23048
|
-
header: "Database (PostgreSQL)",
|
|
23049
|
-
vars: [{ key: "DATABASE_URL", value: databaseUrl }]
|
|
23050
|
-
}
|
|
23051
|
-
],
|
|
23052
|
-
/* @__PURE__ */ new Set(["DATABASE_URL"])
|
|
23053
|
-
);
|
|
23054
|
-
}
|
|
23055
|
-
function scaffoldEnv(cwd, options) {
|
|
23056
|
-
const devPort = detectDevPort(cwd);
|
|
23057
|
-
const sections = getCoreEnvSections(options.databaseUrl, devPort, options.namespace ?? "admin");
|
|
23058
|
-
const authBasePath = `/api/${options.namespace ?? "admin"}/auth`;
|
|
23059
|
-
const overwrite = /* @__PURE__ */ new Set();
|
|
23060
|
-
if (options.databaseUrl) {
|
|
23061
|
-
overwrite.add("DATABASE_URL");
|
|
23062
|
-
}
|
|
23063
|
-
if (shouldOverwriteAuthUrl(cwd, devPort)) {
|
|
23064
|
-
overwrite.add("BETTERSTART_AUTH_URL");
|
|
23065
|
-
}
|
|
23066
|
-
if (readEnvVar(cwd, "BETTERSTART_AUTH_BASE_PATH") !== authBasePath) {
|
|
23067
|
-
overwrite.add("BETTERSTART_AUTH_BASE_PATH");
|
|
23068
|
-
}
|
|
23069
|
-
return appendEnvVars(cwd, sections, overwrite);
|
|
23070
|
-
}
|
|
23071
|
-
|
|
23072
23090
|
// adapters/next/init/scaffolders/layout.ts
|
|
23073
23091
|
import path41 from "path";
|
|
23074
23092
|
function scaffoldLayout({ cwd, config }) {
|
|
@@ -24692,15 +24710,7 @@ async function provisionNeonInteractive(runner, cwd, options) {
|
|
|
24692
24710
|
if (!add.success) {
|
|
24693
24711
|
return { failure: add.timedOut ? "timeout" : "provision-failed" };
|
|
24694
24712
|
}
|
|
24695
|
-
|
|
24696
|
-
pullSpinner.start("Retrieving DATABASE_URL from Vercel");
|
|
24697
|
-
const databaseUrl = await pullVercelEnvValue(runner, cwd, readDbUrlFromDotenv, options.env);
|
|
24698
|
-
if (!databaseUrl) {
|
|
24699
|
-
pullSpinner.stop(`${pc5.yellow("\u25B2")} No DATABASE_URL came back from Vercel`);
|
|
24700
|
-
return {};
|
|
24701
|
-
}
|
|
24702
|
-
pullSpinner.clear();
|
|
24703
|
-
return { databaseUrl };
|
|
24713
|
+
return {};
|
|
24704
24714
|
}
|
|
24705
24715
|
async function provisionNeon(runner, cwd, options) {
|
|
24706
24716
|
const provisionSpinner = spinner2();
|
|
@@ -24723,20 +24733,6 @@ ${add.stderr}`.trim();
|
|
|
24723
24733
|
provisionSpinner.clear();
|
|
24724
24734
|
return readNeonProvisionInfo(add.stdout);
|
|
24725
24735
|
}
|
|
24726
|
-
async function connectNeonResourceToProject(runner, cwd, resourceName, env) {
|
|
24727
|
-
const connect = await runVercel(
|
|
24728
|
-
runner,
|
|
24729
|
-
["integration", "resource", "connect", resourceName, "--yes", "--format", "json"],
|
|
24730
|
-
{ cwd, mode: "capture", timeoutMs: PROVISION_TIMEOUT_MS2, env }
|
|
24731
|
-
);
|
|
24732
|
-
if (connect.success) return { ok: true };
|
|
24733
|
-
const detail = `${connect.stdout}
|
|
24734
|
-
${connect.stderr}`.trim();
|
|
24735
|
-
if (/already connected/i.test(detail)) {
|
|
24736
|
-
return { ok: true, alreadyConnected: true, detail: detail || void 0 };
|
|
24737
|
-
}
|
|
24738
|
-
return { ok: false, detail: detail || void 0 };
|
|
24739
|
-
}
|
|
24740
24736
|
function readDbUrlFromDotenv(filePath) {
|
|
24741
24737
|
const vars = parseDotenvFile(filePath);
|
|
24742
24738
|
const isPg = (v) => !!v && (v.startsWith("postgres://") || v.startsWith("postgresql://"));
|
|
@@ -24747,14 +24743,13 @@ function readDbUrlFromDotenv(filePath) {
|
|
|
24747
24743
|
function readNeonProvisionInfo(stdout) {
|
|
24748
24744
|
const meta = parseVercelJson(stdout);
|
|
24749
24745
|
if (!meta) return {};
|
|
24750
|
-
|
|
24751
|
-
|
|
24752
|
-
|
|
24753
|
-
|
|
24754
|
-
};
|
|
24746
|
+
const info = {};
|
|
24747
|
+
if (meta.dashboardUrl) info.dashboardUrl = meta.dashboardUrl;
|
|
24748
|
+
if (meta.ssoUrl?.resource) info.resourceUrl = meta.ssoUrl.resource;
|
|
24749
|
+
return info;
|
|
24755
24750
|
}
|
|
24756
24751
|
function neonAddArgs(options) {
|
|
24757
|
-
const addArgs = ["integration", "add", "neon", "--
|
|
24752
|
+
const addArgs = ["integration", "add", "neon", "--format", "json"];
|
|
24758
24753
|
if (options.plan) addArgs.push("--plan", options.plan);
|
|
24759
24754
|
return addArgs;
|
|
24760
24755
|
}
|
|
@@ -24785,20 +24780,10 @@ async function runVercelNeonFlow(options) {
|
|
|
24785
24780
|
if (neon.detail) p16.log.message(pc6.dim(neon.detail));
|
|
24786
24781
|
return { ok: false };
|
|
24787
24782
|
}
|
|
24788
|
-
|
|
24789
|
-
if (neon.resourceName) {
|
|
24790
|
-
const pulledDatabaseUrl = await connectNeonAndPullDatabaseUrl(
|
|
24791
|
-
runner,
|
|
24792
|
-
options.cwd,
|
|
24793
|
-
neon.resourceName,
|
|
24794
|
-
env
|
|
24795
|
-
);
|
|
24796
|
-
databaseUrl = pulledDatabaseUrl ?? databaseUrl;
|
|
24797
|
-
}
|
|
24783
|
+
const databaseUrl = await pullNeonDatabaseUrl(runner, options.cwd, env);
|
|
24798
24784
|
return {
|
|
24799
24785
|
ok: true,
|
|
24800
24786
|
databaseUrl,
|
|
24801
|
-
neonResourceName: neon.resourceName,
|
|
24802
24787
|
dashboardUrl: neon.dashboardUrl,
|
|
24803
24788
|
resourceUrl: neon.resourceUrl
|
|
24804
24789
|
};
|
|
@@ -24860,24 +24845,6 @@ async function runVercelDeployFlow(options) {
|
|
|
24860
24845
|
return { ok: false };
|
|
24861
24846
|
}
|
|
24862
24847
|
await ensureLinkedProject(runner, options.cwd, options.projectName, env);
|
|
24863
|
-
if (options.neonResourceName) {
|
|
24864
|
-
const neonSpinner = spinner2();
|
|
24865
|
-
neonSpinner.start("Connecting Neon database to Vercel project");
|
|
24866
|
-
const connect = await connectNeonResourceToProject(
|
|
24867
|
-
runner,
|
|
24868
|
-
options.cwd,
|
|
24869
|
-
options.neonResourceName,
|
|
24870
|
-
env
|
|
24871
|
-
);
|
|
24872
|
-
if (connect.ok) {
|
|
24873
|
-
neonSpinner.stop(
|
|
24874
|
-
connect.alreadyConnected ? "Neon database already connected to Vercel project" : "Connected Neon database to Vercel project"
|
|
24875
|
-
);
|
|
24876
|
-
} else {
|
|
24877
|
-
neonSpinner.stop(`${pc6.yellow("\u25B2")} Could not connect Neon database to Vercel project`);
|
|
24878
|
-
if (connect.detail) p16.log.message(pc6.dim(connect.detail));
|
|
24879
|
-
}
|
|
24880
|
-
}
|
|
24881
24848
|
const envSpinner = spinner2();
|
|
24882
24849
|
envSpinner.start("Syncing environment variables to Vercel");
|
|
24883
24850
|
const sync = await syncVercelProductionEnv(runner, options.cwd, env);
|
|
@@ -24940,16 +24907,9 @@ async function ensureLinkedProject(runner, cwd, projectName, env) {
|
|
|
24940
24907
|
project2.linked ? `Linked Vercel project ${pc6.cyan(project2.name)}` : `Using Vercel project ${pc6.cyan(project2.name)}`
|
|
24941
24908
|
);
|
|
24942
24909
|
}
|
|
24943
|
-
async function
|
|
24910
|
+
async function pullNeonDatabaseUrl(runner, cwd, env) {
|
|
24944
24911
|
const neonSpinner = spinner2();
|
|
24945
|
-
neonSpinner.start("
|
|
24946
|
-
const connect = await connectNeonResourceToProject(runner, cwd, resourceName, env);
|
|
24947
|
-
if (!connect.ok) {
|
|
24948
|
-
neonSpinner.stop(`${pc6.yellow("\u25B2")} Could not connect Neon database to Vercel project`);
|
|
24949
|
-
if (connect.detail) p16.log.message(pc6.dim(connect.detail));
|
|
24950
|
-
return void 0;
|
|
24951
|
-
}
|
|
24952
|
-
neonSpinner.message("Retrieving DATABASE_URL from Vercel");
|
|
24912
|
+
neonSpinner.start("Retrieving DATABASE_URL from Vercel");
|
|
24953
24913
|
const databaseUrl = await pullVercelEnvValue(runner, cwd, readDbUrlFromDotenv, env);
|
|
24954
24914
|
if (!databaseUrl) {
|
|
24955
24915
|
neonSpinner.stop(`${pc6.yellow("\u25B2")} No DATABASE_URL came back from Vercel`);
|
|
@@ -25581,7 +25541,6 @@ async function runInitCommand(name, options) {
|
|
|
25581
25541
|
isFreshProject = true;
|
|
25582
25542
|
}
|
|
25583
25543
|
let databaseUrl;
|
|
25584
|
-
let neonResourceName;
|
|
25585
25544
|
const existingDbUrl = readExistingDbUrl(cwd);
|
|
25586
25545
|
if (options.yes) {
|
|
25587
25546
|
if (options.databaseUrl) {
|
|
@@ -25603,12 +25562,10 @@ async function runInitCommand(name, options) {
|
|
|
25603
25562
|
env: process.env
|
|
25604
25563
|
});
|
|
25605
25564
|
if (flow.ok && flow.databaseUrl) {
|
|
25606
|
-
neonResourceName = flow.neonResourceName;
|
|
25607
25565
|
databaseUrl = flow.databaseUrl;
|
|
25608
25566
|
persistDatabaseUrl(cwd, databaseUrl);
|
|
25609
25567
|
p17.log.success(`Saved DATABASE_URL to ${pc7.cyan(".env.local")}`);
|
|
25610
25568
|
} else if (flow.ok) {
|
|
25611
|
-
neonResourceName = flow.neonResourceName;
|
|
25612
25569
|
p17.log.warn("Created a Neon database, but DATABASE_URL could not be retrieved from Vercel.");
|
|
25613
25570
|
const resourceUrl = flow.resourceUrl ?? flow.dashboardUrl;
|
|
25614
25571
|
if (resourceUrl) {
|
|
@@ -25639,12 +25596,10 @@ async function runInitCommand(name, options) {
|
|
|
25639
25596
|
env: process.env
|
|
25640
25597
|
});
|
|
25641
25598
|
if (flow.ok && flow.databaseUrl) {
|
|
25642
|
-
neonResourceName = flow.neonResourceName;
|
|
25643
25599
|
databaseUrl = flow.databaseUrl;
|
|
25644
25600
|
persistDatabaseUrl(cwd, databaseUrl);
|
|
25645
25601
|
p17.log.success(`Saved DATABASE_URL to ${pc7.cyan(".env.local")}`);
|
|
25646
25602
|
} else if (flow.ok) {
|
|
25647
|
-
neonResourceName = flow.neonResourceName;
|
|
25648
25603
|
openBrowserVercelNeonResource(flow.resourceUrl ?? flow.dashboardUrl);
|
|
25649
25604
|
databaseUrl = await promptConnectionString();
|
|
25650
25605
|
persistDatabaseUrl(cwd, databaseUrl);
|
|
@@ -25690,6 +25645,8 @@ async function runInitCommand(name, options) {
|
|
|
25690
25645
|
env: process.env
|
|
25691
25646
|
});
|
|
25692
25647
|
if (flow.ok && flow.token) {
|
|
25648
|
+
persistBlobReadWriteToken(cwd, flow.token);
|
|
25649
|
+
p17.log.success(`Saved BLOB_READ_WRITE_TOKEN to ${pc7.cyan(".env.local")}`);
|
|
25693
25650
|
collectedIntegrationConfig.sections.push({
|
|
25694
25651
|
header: "Storage (Vercel Blob)",
|
|
25695
25652
|
vars: [{ key: "BLOB_READ_WRITE_TOKEN", value: flow.token }]
|
|
@@ -25891,8 +25848,9 @@ async function runInitCommand(name, options) {
|
|
|
25891
25848
|
config: resolvedPluginInstallResult.config,
|
|
25892
25849
|
pm,
|
|
25893
25850
|
integrationIds: pluginSelection.integrations,
|
|
25894
|
-
// Secrets were already collected up front and written to
|
|
25895
|
-
// so the install runs without prompting (rule: no
|
|
25851
|
+
// Secrets were already collected up front and persisted/written to
|
|
25852
|
+
// .env.local, so the install runs without prompting (rule: no
|
|
25853
|
+
// mid-scaffold input).
|
|
25896
25854
|
interactive: false,
|
|
25897
25855
|
includeBiome: project2.linter.type === "none"
|
|
25898
25856
|
});
|
|
@@ -26172,13 +26130,12 @@ Run manually: ${pc7.cyan(betterstartExecCommand(pm, "seed"))}`,
|
|
|
26172
26130
|
initialValue: linkedVercelProject
|
|
26173
26131
|
});
|
|
26174
26132
|
if (!p17.isCancel(deployNow) && deployNow) {
|
|
26175
|
-
await runVercelDeployFlow({ cwd, projectName,
|
|
26133
|
+
await runVercelDeployFlow({ cwd, projectName, env: process.env });
|
|
26176
26134
|
}
|
|
26177
26135
|
} else if (linkedVercelProject && process.env.VERCEL_TOKEN) {
|
|
26178
26136
|
const deployFlow = await runVercelDeployFlow({
|
|
26179
26137
|
cwd,
|
|
26180
26138
|
projectName,
|
|
26181
|
-
neonResourceName,
|
|
26182
26139
|
env: process.env
|
|
26183
26140
|
});
|
|
26184
26141
|
if (!deployFlow.ok) {
|