@donotdev/cli 0.0.15 → 0.0.17
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/dependencies-matrix.json +67 -147
- package/dist/bin/commands/build.js +69 -52
- package/dist/bin/commands/bump.js +15 -14
- package/dist/bin/commands/create-app.js +258 -55
- package/dist/bin/commands/create-project.js +290 -161
- package/dist/bin/commands/deploy.js +146 -63
- package/dist/bin/commands/dev.js +43 -24
- package/dist/bin/commands/doctor.d.ts +6 -0
- package/dist/bin/commands/doctor.d.ts.map +1 -0
- package/dist/bin/commands/{lint.js → doctor.js} +1370 -146
- package/dist/bin/commands/doctor.js.map +1 -0
- package/dist/bin/commands/emu.js +295 -107
- package/dist/bin/commands/make-admin.js +77519 -11
- package/dist/bin/commands/preview.js +44 -25
- package/dist/bin/commands/setup.d.ts +6 -0
- package/dist/bin/commands/setup.d.ts.map +1 -0
- package/dist/bin/commands/setup.js +12123 -0
- package/dist/bin/commands/setup.js.map +1 -0
- package/dist/bin/commands/type-check.d.ts.map +1 -1
- package/dist/bin/commands/type-check.js +2022 -283
- package/dist/bin/commands/type-check.js.map +1 -1
- package/dist/bin/dndev.js +54 -58
- package/dist/bin/donotdev.js +54 -58
- package/dist/index.js +860 -459
- package/package.json +2 -2
- package/templates/app-expo/.env.example +2 -22
- package/templates/app-expo/README.md.example +1 -1
- package/templates/app-expo/assets/adaptive-icon.png +0 -0
- package/templates/app-expo/assets/favicon.png +0 -0
- package/templates/app-expo/assets/icon.png +0 -0
- package/templates/app-expo/assets/splash.png +0 -0
- package/templates/app-expo/src/config/app.ts.example +46 -0
- package/templates/app-expo/src/config/providers.ts.example +7 -0
- package/templates/app-next/src/config/providers.ts.example +7 -0
- package/templates/app-vite/src/config/providers.ts.example +7 -0
- package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
- package/templates/functions-firebase/README.md.example +1 -1
- package/templates/functions-firebase/functions-firebase/.env.example.example +1 -1
- package/templates/functions-firebase/functions-firebase/README.md.example +1 -1
- package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
- package/templates/functions-firebase/functions.config.js.example +1 -1
- package/templates/functions-supabase/supabase/config.toml.example +59 -0
- package/templates/functions-supabase/supabase/functions/.env.example +13 -0
- package/templates/functions-supabase/supabase/functions/deno.json.example +8 -0
- package/templates/overlay-firebase/env.fragment.example +1 -1
- package/templates/overlay-firebase/env.fragment.expo.example +1 -1
- package/templates/overlay-firebase/env.fragment.nextjs.example +1 -1
- package/templates/overlay-supabase/env.fragment.example +8 -3
- package/templates/overlay-supabase/env.fragment.expo.example +8 -3
- package/templates/overlay-supabase/env.fragment.nextjs.example +8 -3
- package/templates/overlay-vercel/env.fragment.example +1 -1
- package/templates/overlay-vercel/env.fragment.nextjs.example +1 -1
- package/templates/root-consumer/AI.md.example +15 -0
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +2 -2
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +12 -12
- package/templates/root-consumer/guides/dndev/INDEX.md.example +3 -3
- package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
- package/templates/root-consumer/guides/dndev/SETUP_AUTH.md.example +13 -6
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +149 -988
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +72 -20
- package/templates/root-consumer/guides/dndev/SETUP_FUNCTIONS.md.example +6 -111
- package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +60 -0
- package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +62 -0
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -33
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +108 -91
- package/templates/root-consumer/guides/dndev/advanced/EMULATORS.md.example +2 -2
- package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +7 -8
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +9 -5
- package/dist/bin/commands/firebase-setup.d.ts +0 -6
- package/dist/bin/commands/firebase-setup.d.ts.map +0 -1
- package/dist/bin/commands/firebase-setup.js +0 -7
- package/dist/bin/commands/firebase-setup.js.map +0 -1
- package/dist/bin/commands/lint.d.ts +0 -11
- package/dist/bin/commands/lint.d.ts.map +0 -1
- package/dist/bin/commands/lint.js.map +0 -1
- package/dist/bin/commands/staging.d.ts +0 -11
- package/dist/bin/commands/staging.d.ts.map +0 -1
- package/dist/bin/commands/staging.js +0 -12
- package/dist/bin/commands/staging.js.map +0 -1
- package/dist/bin/commands/supabase-setup.d.ts +0 -6
- package/dist/bin/commands/supabase-setup.d.ts.map +0 -1
- package/dist/bin/commands/supabase-setup.js +0 -7
- package/dist/bin/commands/supabase-setup.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -8469,7 +8469,14 @@ function readServiceAccountKey(filePath) {
|
|
|
8469
8469
|
throw new DoNotDevError(
|
|
8470
8470
|
`Invalid service account key: missing required fields`,
|
|
8471
8471
|
DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
|
|
8472
|
-
{
|
|
8472
|
+
{
|
|
8473
|
+
context: {
|
|
8474
|
+
filePath,
|
|
8475
|
+
missingFields: ["project_id", "private_key", "client_email"].filter(
|
|
8476
|
+
(f) => !key[f]
|
|
8477
|
+
)
|
|
8478
|
+
}
|
|
8479
|
+
}
|
|
8473
8480
|
);
|
|
8474
8481
|
}
|
|
8475
8482
|
return content;
|
|
@@ -8510,6 +8517,148 @@ var init_utils = __esm({
|
|
|
8510
8517
|
}
|
|
8511
8518
|
});
|
|
8512
8519
|
|
|
8520
|
+
// packages/tooling/src/utils/app-detection.ts
|
|
8521
|
+
function detectApps(projectRoot) {
|
|
8522
|
+
const apps = [];
|
|
8523
|
+
const appsDir = joinPath(projectRoot, "apps");
|
|
8524
|
+
const appsDirStat = statSync2(appsDir);
|
|
8525
|
+
if (pathExists(appsDir) && appsDirStat?.isDirectory()) {
|
|
8526
|
+
const appDirs = readdirSync2(appsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
|
|
8527
|
+
for (const appDir of appDirs) {
|
|
8528
|
+
const appPath = joinPath(appsDir, appDir);
|
|
8529
|
+
const packageJsonPath = joinPath(appPath, "package.json");
|
|
8530
|
+
if (pathExists(packageJsonPath)) {
|
|
8531
|
+
const appInfo = analyzeApp(appPath, appDir);
|
|
8532
|
+
if (appInfo) {
|
|
8533
|
+
apps.push(appInfo);
|
|
8534
|
+
}
|
|
8535
|
+
}
|
|
8536
|
+
}
|
|
8537
|
+
} else {
|
|
8538
|
+
const packageJsonPath = joinPath(projectRoot, "package.json");
|
|
8539
|
+
if (pathExists(packageJsonPath)) {
|
|
8540
|
+
try {
|
|
8541
|
+
const packageJson = readPackageJson(packageJsonPath);
|
|
8542
|
+
if (packageJson && (packageJson.dependencies?.vite || packageJson.devDependencies?.vite || packageJson.dependencies?.next || packageJson.devDependencies?.next)) {
|
|
8543
|
+
const pathParts = projectRoot.split(/[/\\]/);
|
|
8544
|
+
const appName = pathParts[pathParts.length - 1] || "app";
|
|
8545
|
+
const appInfo = analyzeApp(projectRoot, appName);
|
|
8546
|
+
if (appInfo) {
|
|
8547
|
+
apps.push(appInfo);
|
|
8548
|
+
}
|
|
8549
|
+
}
|
|
8550
|
+
} catch {
|
|
8551
|
+
}
|
|
8552
|
+
}
|
|
8553
|
+
}
|
|
8554
|
+
return apps;
|
|
8555
|
+
}
|
|
8556
|
+
function analyzeApp(appPath, appName) {
|
|
8557
|
+
const packageJsonPath = joinPath(appPath, "package.json");
|
|
8558
|
+
if (!pathExists(packageJsonPath)) {
|
|
8559
|
+
return null;
|
|
8560
|
+
}
|
|
8561
|
+
let packageJson = null;
|
|
8562
|
+
try {
|
|
8563
|
+
packageJson = readPackageJson(packageJsonPath);
|
|
8564
|
+
if (!packageJson.name) {
|
|
8565
|
+
return null;
|
|
8566
|
+
}
|
|
8567
|
+
} catch {
|
|
8568
|
+
return null;
|
|
8569
|
+
}
|
|
8570
|
+
let framework = "unknown";
|
|
8571
|
+
if (pathExists(joinPath(appPath, "next.config.js")) || pathExists(joinPath(appPath, "next.config.ts")) || pathExists(joinPath(appPath, "next.config.mjs")) || packageJson.dependencies?.next || packageJson.devDependencies?.next) {
|
|
8572
|
+
framework = "nextjs";
|
|
8573
|
+
} else if (pathExists(joinPath(appPath, "vite.config.ts")) || pathExists(joinPath(appPath, "vite.config.js")) || pathExists(joinPath(appPath, "vite.config.mjs")) || packageJson.dependencies?.vite || packageJson.devDependencies?.vite) {
|
|
8574
|
+
framework = "vite";
|
|
8575
|
+
}
|
|
8576
|
+
const functionsPath = joinPath(appPath, "functions");
|
|
8577
|
+
const functionsStat = statSync2(functionsPath);
|
|
8578
|
+
const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
|
|
8579
|
+
let platform6;
|
|
8580
|
+
const firebaseJsonInFunctions = hasFunctions && pathExists(joinPath(functionsPath, "firebase.json"));
|
|
8581
|
+
const firebaseJsonInApp = pathExists(joinPath(appPath, "firebase.json"));
|
|
8582
|
+
if (firebaseJsonInFunctions || firebaseJsonInApp) {
|
|
8583
|
+
platform6 = "firebase";
|
|
8584
|
+
}
|
|
8585
|
+
if (!platform6) {
|
|
8586
|
+
const supabaseConfigPath = joinPath(appPath, "supabase", "config.toml");
|
|
8587
|
+
const hasSupabaseDep = !!(packageJson.dependencies?.["@donotdev/supabase"] || packageJson.dependencies?.["@supabase/supabase-js"]);
|
|
8588
|
+
if (pathExists(supabaseConfigPath) || hasSupabaseDep) {
|
|
8589
|
+
platform6 = "supabase";
|
|
8590
|
+
}
|
|
8591
|
+
}
|
|
8592
|
+
if (!platform6) {
|
|
8593
|
+
const vercelJsonPath = joinPath(appPath, "vercel.json");
|
|
8594
|
+
if (pathExists(vercelJsonPath)) {
|
|
8595
|
+
platform6 = "vercel";
|
|
8596
|
+
}
|
|
8597
|
+
}
|
|
8598
|
+
return {
|
|
8599
|
+
name: appName,
|
|
8600
|
+
packageName: packageJson.name || appName,
|
|
8601
|
+
path: appPath,
|
|
8602
|
+
packageJsonPath,
|
|
8603
|
+
framework,
|
|
8604
|
+
hasFunctions,
|
|
8605
|
+
functionsPath: hasFunctions ? functionsPath : void 0,
|
|
8606
|
+
platform: platform6
|
|
8607
|
+
};
|
|
8608
|
+
}
|
|
8609
|
+
var init_app_detection = __esm({
|
|
8610
|
+
"packages/tooling/src/utils/app-detection.ts"() {
|
|
8611
|
+
"use strict";
|
|
8612
|
+
init_utils();
|
|
8613
|
+
init_pathResolver();
|
|
8614
|
+
init_typed_file_operations();
|
|
8615
|
+
}
|
|
8616
|
+
});
|
|
8617
|
+
|
|
8618
|
+
// packages/tooling/src/utils/app-selector.ts
|
|
8619
|
+
async function selectApp(projectRoot, appName) {
|
|
8620
|
+
const apps = detectApps(projectRoot);
|
|
8621
|
+
if (apps.length === 0) {
|
|
8622
|
+
log.error("No apps found in this project.");
|
|
8623
|
+
log.info('Run "dndev init" to create a new project.');
|
|
8624
|
+
return null;
|
|
8625
|
+
}
|
|
8626
|
+
if (appName) {
|
|
8627
|
+
const app = apps.find((a) => a.name === appName);
|
|
8628
|
+
if (!app) {
|
|
8629
|
+
log.warn(`App "${appName}" not found.`);
|
|
8630
|
+
log.info("Available apps:");
|
|
8631
|
+
apps.forEach((a) => log.info(` - ${a.name}`));
|
|
8632
|
+
log.info("Please select from the list:");
|
|
8633
|
+
} else {
|
|
8634
|
+
return app;
|
|
8635
|
+
}
|
|
8636
|
+
}
|
|
8637
|
+
if (apps.length === 1) {
|
|
8638
|
+
return apps[0] || null;
|
|
8639
|
+
}
|
|
8640
|
+
const selected = await ve({
|
|
8641
|
+
message: "Select app:",
|
|
8642
|
+
options: apps.map((app) => ({
|
|
8643
|
+
value: app.name,
|
|
8644
|
+
label: `${app.name} (${app.framework === "nextjs" ? "Next.js" : "Vite"}${app.hasFunctions ? ` + ${app.platform || "functions"}` : ""})`
|
|
8645
|
+
}))
|
|
8646
|
+
});
|
|
8647
|
+
if (typeof selected !== "string") {
|
|
8648
|
+
return null;
|
|
8649
|
+
}
|
|
8650
|
+
return apps.find((a) => a.name === selected) || null;
|
|
8651
|
+
}
|
|
8652
|
+
var init_app_selector = __esm({
|
|
8653
|
+
"packages/tooling/src/utils/app-selector.ts"() {
|
|
8654
|
+
"use strict";
|
|
8655
|
+
init_utils();
|
|
8656
|
+
init_dist2();
|
|
8657
|
+
init_app_detection();
|
|
8658
|
+
init_cli_output();
|
|
8659
|
+
}
|
|
8660
|
+
});
|
|
8661
|
+
|
|
8513
8662
|
// packages/tooling/src/utils/cli-input.ts
|
|
8514
8663
|
async function askForInput(message, defaultValue = "") {
|
|
8515
8664
|
const result = await he({
|
|
@@ -8677,7 +8826,7 @@ function checkTsx() {
|
|
|
8677
8826
|
return checkCLI("tsx");
|
|
8678
8827
|
}
|
|
8679
8828
|
function getCLIInstallInstructions(tool) {
|
|
8680
|
-
const
|
|
8829
|
+
const platform6 = process.platform;
|
|
8681
8830
|
const instructions = {
|
|
8682
8831
|
[CLI_TOOLS.BUN]: {
|
|
8683
8832
|
win32: [
|
|
@@ -8730,21 +8879,23 @@ function getCLIInstallInstructions(tool) {
|
|
|
8730
8879
|
},
|
|
8731
8880
|
[CLI_TOOLS.SUPABASE]: {
|
|
8732
8881
|
win32: [
|
|
8733
|
-
"
|
|
8882
|
+
"scoop install supabase",
|
|
8883
|
+
"Or: winget install Supabase.CLI",
|
|
8734
8884
|
"Or download from: https://github.com/supabase/cli/releases"
|
|
8735
8885
|
],
|
|
8736
|
-
darwin: [
|
|
8737
|
-
"brew install supabase/tap/supabase",
|
|
8738
|
-
"Or: npm install -g supabase"
|
|
8739
|
-
],
|
|
8886
|
+
darwin: ["brew install supabase/tap/supabase"],
|
|
8740
8887
|
linux: [
|
|
8741
|
-
"
|
|
8888
|
+
"brew install supabase/tap/supabase",
|
|
8742
8889
|
"Or see: https://supabase.com/docs/guides/cli"
|
|
8743
8890
|
]
|
|
8744
8891
|
},
|
|
8745
8892
|
[CLI_TOOLS.VERCEL]: {
|
|
8746
8893
|
win32: ["npm install -g vercel", "Or: npx vercel (no install)"],
|
|
8747
|
-
darwin: [
|
|
8894
|
+
darwin: [
|
|
8895
|
+
"npm install -g vercel",
|
|
8896
|
+
"Or: brew install vercel",
|
|
8897
|
+
"Or: npx vercel"
|
|
8898
|
+
],
|
|
8748
8899
|
linux: ["npm install -g vercel", "Or: npx vercel"]
|
|
8749
8900
|
},
|
|
8750
8901
|
[CLI_TOOLS.SENTRY_CLI]: {
|
|
@@ -8791,7 +8942,7 @@ function getCLIInstallInstructions(tool) {
|
|
|
8791
8942
|
linux: ["npm install -g tsx"]
|
|
8792
8943
|
}
|
|
8793
8944
|
};
|
|
8794
|
-
const platformInstructions = instructions[tool]?.[
|
|
8945
|
+
const platformInstructions = instructions[tool]?.[platform6] || instructions[tool]?.linux || [];
|
|
8795
8946
|
return platformInstructions.join("\n \u2022 ");
|
|
8796
8947
|
}
|
|
8797
8948
|
function formatCLIMissingError(tool, additionalContext) {
|
|
@@ -8806,9 +8957,9 @@ function formatCLIMissingError(tool, additionalContext) {
|
|
|
8806
8957
|
M2.info(`
|
|
8807
8958
|
${additionalContext}`);
|
|
8808
8959
|
}
|
|
8809
|
-
const
|
|
8960
|
+
const platform6 = process.platform;
|
|
8810
8961
|
M2.info("\nIf already installed, ensure it's in your PATH:");
|
|
8811
|
-
if (
|
|
8962
|
+
if (platform6 === "win32") {
|
|
8812
8963
|
M2.message(" \u2022 Check with: where " + tool);
|
|
8813
8964
|
M2.message(
|
|
8814
8965
|
" \u2022 Common location: C:\\Users\\<username>\\AppData\\Roaming\\npm\\"
|
|
@@ -8865,6 +9016,40 @@ var init_cli_tools = __esm({
|
|
|
8865
9016
|
}
|
|
8866
9017
|
});
|
|
8867
9018
|
|
|
9019
|
+
// packages/tooling/src/cli/setup/vercel-token.ts
|
|
9020
|
+
function readEnvVar(filePath, varName) {
|
|
9021
|
+
if (!pathExists(filePath)) return null;
|
|
9022
|
+
const content = readSync(filePath, { format: "text" });
|
|
9023
|
+
if (typeof content !== "string") return null;
|
|
9024
|
+
for (const line of content.split(/\r?\n/)) {
|
|
9025
|
+
const trimmed = line.trim();
|
|
9026
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
9027
|
+
if (trimmed.startsWith(`${varName}=`)) {
|
|
9028
|
+
const val = trimmed.substring(`${varName}=`.length).trim();
|
|
9029
|
+
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
|
|
9030
|
+
return val.slice(1, -1);
|
|
9031
|
+
}
|
|
9032
|
+
return val || null;
|
|
9033
|
+
}
|
|
9034
|
+
}
|
|
9035
|
+
return null;
|
|
9036
|
+
}
|
|
9037
|
+
function resolveVercelToken(appDir) {
|
|
9038
|
+
if (process.env.VERCEL_TOKEN) return process.env.VERCEL_TOKEN;
|
|
9039
|
+
const fromEnv = readEnvVar(joinPath(appDir, ".env"), "VERCEL_TOKEN");
|
|
9040
|
+
if (fromEnv) return fromEnv;
|
|
9041
|
+
const fromLocal = readEnvVar(joinPath(appDir, ".env.local"), "VERCEL_TOKEN");
|
|
9042
|
+
if (fromLocal) return fromLocal;
|
|
9043
|
+
return null;
|
|
9044
|
+
}
|
|
9045
|
+
var init_vercel_token = __esm({
|
|
9046
|
+
"packages/tooling/src/cli/setup/vercel-token.ts"() {
|
|
9047
|
+
"use strict";
|
|
9048
|
+
init_utils();
|
|
9049
|
+
init_pathResolver();
|
|
9050
|
+
}
|
|
9051
|
+
});
|
|
9052
|
+
|
|
8868
9053
|
// node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js
|
|
8869
9054
|
var require_identity = __commonJS({
|
|
8870
9055
|
"node_modules/.bun/yaml@2.8.2/node_modules/yaml/dist/nodes/identity.js"(exports) {
|
|
@@ -16226,13 +16411,36 @@ var require_dist = __commonJS({
|
|
|
16226
16411
|
}
|
|
16227
16412
|
});
|
|
16228
16413
|
|
|
16414
|
+
// packages/tooling/src/utils/error-handling.ts
|
|
16415
|
+
function isError(error2) {
|
|
16416
|
+
return error2 instanceof Error;
|
|
16417
|
+
}
|
|
16418
|
+
function getErrorMessage(error2) {
|
|
16419
|
+
if (isError(error2)) {
|
|
16420
|
+
return error2.message;
|
|
16421
|
+
}
|
|
16422
|
+
if (typeof error2 === "string") {
|
|
16423
|
+
return error2;
|
|
16424
|
+
}
|
|
16425
|
+
if (error2 && typeof error2 === "object" && "message" in error2) {
|
|
16426
|
+
return String(error2.message);
|
|
16427
|
+
}
|
|
16428
|
+
return String(error2);
|
|
16429
|
+
}
|
|
16430
|
+
var init_error_handling = __esm({
|
|
16431
|
+
"packages/tooling/src/utils/error-handling.ts"() {
|
|
16432
|
+
"use strict";
|
|
16433
|
+
init_utils();
|
|
16434
|
+
}
|
|
16435
|
+
});
|
|
16436
|
+
|
|
16229
16437
|
// packages/tooling/src/apps/sync-secrets.ts
|
|
16230
16438
|
var sync_secrets_exports = {};
|
|
16231
16439
|
__export(sync_secrets_exports, {
|
|
16232
16440
|
default: () => sync_secrets_default,
|
|
16233
16441
|
main: () => main5
|
|
16234
16442
|
});
|
|
16235
|
-
import { spawnSync as
|
|
16443
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
16236
16444
|
function parseEnvFile(filePath) {
|
|
16237
16445
|
if (!pathExists(filePath)) {
|
|
16238
16446
|
throw new DoNotDevError(
|
|
@@ -16425,7 +16633,7 @@ async function setFirebaseSecret(key, value, projectId, dryRun = false, cwd) {
|
|
|
16425
16633
|
NODE_OPTIONS: ""
|
|
16426
16634
|
// Clear to avoid conflicts
|
|
16427
16635
|
};
|
|
16428
|
-
const result =
|
|
16636
|
+
const result = spawnSync9(firebaseCmd, args, {
|
|
16429
16637
|
input: value,
|
|
16430
16638
|
encoding: "utf8",
|
|
16431
16639
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -16521,7 +16729,7 @@ function setVercelSecret(key, value, projectId, dryRun = false) {
|
|
|
16521
16729
|
if (projectId) {
|
|
16522
16730
|
args.push("--project", projectId);
|
|
16523
16731
|
}
|
|
16524
|
-
const result =
|
|
16732
|
+
const result = spawnSync9("vercel", args, {
|
|
16525
16733
|
input: value,
|
|
16526
16734
|
encoding: "utf8",
|
|
16527
16735
|
stdio: ["pipe", "inherit", "inherit"]
|
|
@@ -16550,7 +16758,7 @@ function setVercelSecret(key, value, projectId, dryRun = false) {
|
|
|
16550
16758
|
}
|
|
16551
16759
|
function detectGitHubRepo() {
|
|
16552
16760
|
try {
|
|
16553
|
-
const result =
|
|
16761
|
+
const result = spawnSync9("git", ["remote", "get-url", "origin"], {
|
|
16554
16762
|
encoding: "utf8",
|
|
16555
16763
|
stdio: ["pipe", "pipe", "pipe"]
|
|
16556
16764
|
});
|
|
@@ -16578,7 +16786,7 @@ function setGitHubSecret(key, value, repo, dryRun = false) {
|
|
|
16578
16786
|
if (repo) {
|
|
16579
16787
|
args.push("--repo", repo);
|
|
16580
16788
|
}
|
|
16581
|
-
const result =
|
|
16789
|
+
const result = spawnSync9("gh", args, {
|
|
16582
16790
|
input: value,
|
|
16583
16791
|
encoding: "utf8",
|
|
16584
16792
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -16752,12 +16960,12 @@ Examples:
|
|
|
16752
16960
|
}
|
|
16753
16961
|
return 0;
|
|
16754
16962
|
}
|
|
16755
|
-
const
|
|
16963
|
+
const platform6 = config.platform || detectPlatform();
|
|
16756
16964
|
log.info(`Reading secrets from: ${envFilePath}`);
|
|
16757
16965
|
if (config.verbose) {
|
|
16758
16966
|
log.debug(`Working directory: ${currentDir}`);
|
|
16759
16967
|
log.debug(`Environment file: ${envFilePath}`);
|
|
16760
|
-
log.debug(`Platform: ${
|
|
16968
|
+
log.debug(`Platform: ${platform6}`);
|
|
16761
16969
|
log.debug(`Dry run mode: ${config.dryRun}`);
|
|
16762
16970
|
}
|
|
16763
16971
|
const secrets = parseEnvFile(envFilePath);
|
|
@@ -16766,7 +16974,7 @@ Examples:
|
|
|
16766
16974
|
log.info("No secrets found in .env file");
|
|
16767
16975
|
return 0;
|
|
16768
16976
|
}
|
|
16769
|
-
log.info(`Found ${secretKeys.length} secrets to sync to ${
|
|
16977
|
+
log.info(`Found ${secretKeys.length} secrets to sync to ${platform6}:`);
|
|
16770
16978
|
secretKeys.forEach((key) => {
|
|
16771
16979
|
if (config.verbose) {
|
|
16772
16980
|
const value = secrets[key];
|
|
@@ -16777,12 +16985,12 @@ Examples:
|
|
|
16777
16985
|
log.info(` ${key}`);
|
|
16778
16986
|
}
|
|
16779
16987
|
});
|
|
16780
|
-
const finalFirebaseProjectDir =
|
|
16988
|
+
const finalFirebaseProjectDir = platform6 === "firebase" ? firebaseProjectDir || findFirebaseProjectDir(config.envFile) : void 0;
|
|
16781
16989
|
if (config.verbose && finalFirebaseProjectDir) {
|
|
16782
16990
|
log.debug(`Firebase project directory: ${finalFirebaseProjectDir}`);
|
|
16783
16991
|
}
|
|
16784
16992
|
for (const [key, value] of Object.entries(secrets)) {
|
|
16785
|
-
if (
|
|
16993
|
+
if (platform6 === "firebase") {
|
|
16786
16994
|
await setFirebaseSecret(
|
|
16787
16995
|
key,
|
|
16788
16996
|
value,
|
|
@@ -16790,18 +16998,18 @@ Examples:
|
|
|
16790
16998
|
config.dryRun,
|
|
16791
16999
|
finalFirebaseProjectDir
|
|
16792
17000
|
);
|
|
16793
|
-
} else if (
|
|
17001
|
+
} else if (platform6 === "vercel") {
|
|
16794
17002
|
setVercelSecret(key, value, config.vercelProjectId, config.dryRun);
|
|
16795
17003
|
}
|
|
16796
17004
|
}
|
|
16797
17005
|
if (config.dryRun) {
|
|
16798
17006
|
log.success(
|
|
16799
17007
|
`
|
|
16800
|
-
Dry run completed. No secrets were actually set to ${
|
|
17008
|
+
Dry run completed. No secrets were actually set to ${platform6}.`
|
|
16801
17009
|
);
|
|
16802
17010
|
} else {
|
|
16803
17011
|
log.success(`
|
|
16804
|
-
All secrets synced successfully to ${
|
|
17012
|
+
All secrets synced successfully to ${platform6}!`);
|
|
16805
17013
|
}
|
|
16806
17014
|
return 0;
|
|
16807
17015
|
} catch (err) {
|
|
@@ -16830,12 +17038,14 @@ var deploy_supabase_functions_exports = {};
|
|
|
16830
17038
|
__export(deploy_supabase_functions_exports, {
|
|
16831
17039
|
deploySupabaseFunctions: () => deploySupabaseFunctions
|
|
16832
17040
|
});
|
|
16833
|
-
import { execSync as
|
|
17041
|
+
import { execSync as execSync9 } from "node:child_process";
|
|
16834
17042
|
async function deploySupabaseFunctions(appDir, config) {
|
|
16835
17043
|
const supabaseDir = joinPath(appDir, "supabase");
|
|
16836
17044
|
const functionsDir = joinPath(supabaseDir, "functions");
|
|
16837
17045
|
if (!pathExists(functionsDir)) {
|
|
16838
|
-
log.warn(
|
|
17046
|
+
log.warn(
|
|
17047
|
+
"No supabase/functions/ directory found. Skipping Supabase functions deployment."
|
|
17048
|
+
);
|
|
16839
17049
|
return;
|
|
16840
17050
|
}
|
|
16841
17051
|
requireCLI(
|
|
@@ -16851,15 +17061,19 @@ async function deploySupabaseFunctions(appDir, config) {
|
|
|
16851
17061
|
return pathExists(indexPath);
|
|
16852
17062
|
});
|
|
16853
17063
|
if (functionDirs.length === 0) {
|
|
16854
|
-
log.warn(
|
|
17064
|
+
log.warn(
|
|
17065
|
+
"No Edge Functions found in supabase/functions/. Skipping deployment."
|
|
17066
|
+
);
|
|
16855
17067
|
return;
|
|
16856
17068
|
}
|
|
16857
|
-
log.info(
|
|
17069
|
+
log.info(
|
|
17070
|
+
`Found ${functionDirs.length} Edge Function(s): ${functionDirs.join(", ")}`
|
|
17071
|
+
);
|
|
16858
17072
|
const s = Y2();
|
|
16859
17073
|
for (const functionName of functionDirs) {
|
|
16860
17074
|
s.start(`Deploying Edge Function: ${functionName}...`);
|
|
16861
17075
|
try {
|
|
16862
|
-
|
|
17076
|
+
execSync9(`supabase functions deploy ${functionName}`, {
|
|
16863
17077
|
cwd: supabaseDir,
|
|
16864
17078
|
stdio: config.verbose ? "inherit" : "pipe",
|
|
16865
17079
|
env: {
|
|
@@ -16873,7 +17087,12 @@ async function deploySupabaseFunctions(appDir, config) {
|
|
|
16873
17087
|
throw new DoNotDevError(
|
|
16874
17088
|
`Failed to deploy Supabase Edge Function: ${functionName}`,
|
|
16875
17089
|
"deployment-failed",
|
|
16876
|
-
{
|
|
17090
|
+
{
|
|
17091
|
+
context: {
|
|
17092
|
+
functionName,
|
|
17093
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
17094
|
+
}
|
|
17095
|
+
}
|
|
16877
17096
|
);
|
|
16878
17097
|
}
|
|
16879
17098
|
}
|
|
@@ -16898,161 +17117,36 @@ init_utils();
|
|
|
16898
17117
|
|
|
16899
17118
|
// packages/tooling/src/apps/build.ts
|
|
16900
17119
|
init_utils();
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16905
|
-
init_dist2();
|
|
16906
|
-
|
|
16907
|
-
// packages/tooling/src/utils/app-detection.ts
|
|
16908
|
-
init_utils();
|
|
17120
|
+
init_app_selector();
|
|
17121
|
+
init_cli_input();
|
|
17122
|
+
init_cli_output();
|
|
17123
|
+
init_errors();
|
|
16909
17124
|
init_pathResolver();
|
|
16910
17125
|
init_typed_file_operations();
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
const
|
|
16914
|
-
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
16920
|
-
if (pathExists(packageJsonPath)) {
|
|
16921
|
-
const appInfo = analyzeApp(appPath, appDir);
|
|
16922
|
-
if (appInfo) {
|
|
16923
|
-
apps.push(appInfo);
|
|
16924
|
-
}
|
|
16925
|
-
}
|
|
16926
|
-
}
|
|
16927
|
-
} else {
|
|
16928
|
-
const packageJsonPath = joinPath(projectRoot, "package.json");
|
|
16929
|
-
if (pathExists(packageJsonPath)) {
|
|
16930
|
-
try {
|
|
16931
|
-
const packageJson = readPackageJson(packageJsonPath);
|
|
16932
|
-
if (packageJson && (packageJson.dependencies?.vite || packageJson.devDependencies?.vite || packageJson.dependencies?.next || packageJson.devDependencies?.next)) {
|
|
16933
|
-
const pathParts = projectRoot.split(/[/\\]/);
|
|
16934
|
-
const appName = pathParts[pathParts.length - 1] || "app";
|
|
16935
|
-
const appInfo = analyzeApp(projectRoot, appName);
|
|
16936
|
-
if (appInfo) {
|
|
16937
|
-
apps.push(appInfo);
|
|
16938
|
-
}
|
|
16939
|
-
}
|
|
16940
|
-
} catch {
|
|
16941
|
-
}
|
|
16942
|
-
}
|
|
16943
|
-
}
|
|
16944
|
-
return apps;
|
|
16945
|
-
}
|
|
16946
|
-
function analyzeApp(appPath, appName) {
|
|
16947
|
-
const packageJsonPath = joinPath(appPath, "package.json");
|
|
16948
|
-
if (!pathExists(packageJsonPath)) {
|
|
16949
|
-
return null;
|
|
17126
|
+
import { spawnSync, execSync } from "node:child_process";
|
|
17127
|
+
function validateFirebaseJson(appDir) {
|
|
17128
|
+
const firebaseJsonPath = joinPath(appDir, "firebase.json");
|
|
17129
|
+
if (!pathExists(firebaseJsonPath)) {
|
|
17130
|
+
return {
|
|
17131
|
+
valid: false,
|
|
17132
|
+
hasHosting: false,
|
|
17133
|
+
hasFunctions: false
|
|
17134
|
+
};
|
|
16950
17135
|
}
|
|
16951
|
-
let packageJson = null;
|
|
16952
17136
|
try {
|
|
16953
|
-
|
|
16954
|
-
if (!
|
|
16955
|
-
return
|
|
17137
|
+
const config = readFirebaseJson(firebaseJsonPath);
|
|
17138
|
+
if (!config.projectId) {
|
|
17139
|
+
return {
|
|
17140
|
+
valid: false,
|
|
17141
|
+
hasHosting: false,
|
|
17142
|
+
hasFunctions: false
|
|
17143
|
+
};
|
|
16956
17144
|
}
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
framework = "nextjs";
|
|
16963
|
-
} else if (pathExists(joinPath(appPath, "vite.config.ts")) || pathExists(joinPath(appPath, "vite.config.js")) || pathExists(joinPath(appPath, "vite.config.mjs")) || packageJson.dependencies?.vite || packageJson.devDependencies?.vite) {
|
|
16964
|
-
framework = "vite";
|
|
16965
|
-
}
|
|
16966
|
-
const functionsPath = joinPath(appPath, "functions");
|
|
16967
|
-
const functionsStat = statSync2(functionsPath);
|
|
16968
|
-
const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
|
|
16969
|
-
let platform4;
|
|
16970
|
-
if (hasFunctions) {
|
|
16971
|
-
const firebaseJsonPath = joinPath(functionsPath, "firebase.json");
|
|
16972
|
-
const vercelJsonPath = joinPath(appPath, "vercel.json");
|
|
16973
|
-
if (pathExists(firebaseJsonPath)) {
|
|
16974
|
-
platform4 = "firebase";
|
|
16975
|
-
} else if (pathExists(vercelJsonPath)) {
|
|
16976
|
-
platform4 = "vercel";
|
|
16977
|
-
}
|
|
16978
|
-
}
|
|
16979
|
-
return {
|
|
16980
|
-
name: appName,
|
|
16981
|
-
packageName: packageJson.name || appName,
|
|
16982
|
-
path: appPath,
|
|
16983
|
-
packageJsonPath,
|
|
16984
|
-
framework,
|
|
16985
|
-
hasFunctions,
|
|
16986
|
-
functionsPath: hasFunctions ? functionsPath : void 0,
|
|
16987
|
-
platform: platform4
|
|
16988
|
-
};
|
|
16989
|
-
}
|
|
16990
|
-
|
|
16991
|
-
// packages/tooling/src/utils/app-selector.ts
|
|
16992
|
-
init_cli_output();
|
|
16993
|
-
async function selectApp(projectRoot, appName) {
|
|
16994
|
-
const apps = detectApps(projectRoot);
|
|
16995
|
-
if (apps.length === 0) {
|
|
16996
|
-
log.error("No apps found in this project.");
|
|
16997
|
-
log.info('Run "dndev init" to create a new project.');
|
|
16998
|
-
return null;
|
|
16999
|
-
}
|
|
17000
|
-
if (appName) {
|
|
17001
|
-
const app = apps.find((a) => a.name === appName);
|
|
17002
|
-
if (!app) {
|
|
17003
|
-
log.warn(`App "${appName}" not found.`);
|
|
17004
|
-
log.info("Available apps:");
|
|
17005
|
-
apps.forEach((a) => log.info(` - ${a.name}`));
|
|
17006
|
-
log.info("Please select from the list:");
|
|
17007
|
-
} else {
|
|
17008
|
-
return app;
|
|
17009
|
-
}
|
|
17010
|
-
}
|
|
17011
|
-
if (apps.length === 1) {
|
|
17012
|
-
return apps[0] || null;
|
|
17013
|
-
}
|
|
17014
|
-
const selected = await ve({
|
|
17015
|
-
message: "Select app:",
|
|
17016
|
-
options: apps.map((app) => ({
|
|
17017
|
-
value: app.name,
|
|
17018
|
-
label: `${app.name} (${app.framework === "nextjs" ? "Next.js" : "Vite"}${app.hasFunctions ? ` + ${app.platform || "functions"}` : ""})`
|
|
17019
|
-
}))
|
|
17020
|
-
});
|
|
17021
|
-
if (typeof selected !== "string") {
|
|
17022
|
-
return null;
|
|
17023
|
-
}
|
|
17024
|
-
return apps.find((a) => a.name === selected) || null;
|
|
17025
|
-
}
|
|
17026
|
-
|
|
17027
|
-
// packages/tooling/src/apps/build.ts
|
|
17028
|
-
init_cli_input();
|
|
17029
|
-
init_cli_output();
|
|
17030
|
-
init_errors();
|
|
17031
|
-
init_pathResolver();
|
|
17032
|
-
init_typed_file_operations();
|
|
17033
|
-
function validateFirebaseJson(appDir) {
|
|
17034
|
-
const firebaseJsonPath = joinPath(appDir, "firebase.json");
|
|
17035
|
-
if (!pathExists(firebaseJsonPath)) {
|
|
17036
|
-
return {
|
|
17037
|
-
valid: false,
|
|
17038
|
-
hasHosting: false,
|
|
17039
|
-
hasFunctions: false
|
|
17040
|
-
};
|
|
17041
|
-
}
|
|
17042
|
-
try {
|
|
17043
|
-
const config = readFirebaseJson(firebaseJsonPath);
|
|
17044
|
-
if (!config.projectId) {
|
|
17045
|
-
return {
|
|
17046
|
-
valid: false,
|
|
17047
|
-
hasHosting: false,
|
|
17048
|
-
hasFunctions: false
|
|
17049
|
-
};
|
|
17050
|
-
}
|
|
17051
|
-
return {
|
|
17052
|
-
valid: true,
|
|
17053
|
-
hasHosting: !!config.hosting,
|
|
17054
|
-
hasFunctions: !!config.functions && Array.isArray(config.functions)
|
|
17055
|
-
};
|
|
17145
|
+
return {
|
|
17146
|
+
valid: true,
|
|
17147
|
+
hasHosting: !!config.hosting,
|
|
17148
|
+
hasFunctions: !!config.functions && Array.isArray(config.functions)
|
|
17149
|
+
};
|
|
17056
17150
|
} catch {
|
|
17057
17151
|
return {
|
|
17058
17152
|
valid: false,
|
|
@@ -17220,11 +17314,12 @@ async function main() {
|
|
|
17220
17314
|
|
|
17221
17315
|
// packages/tooling/src/apps/dev.ts
|
|
17222
17316
|
init_utils();
|
|
17223
|
-
|
|
17224
|
-
import { platform } from "node:os";
|
|
17317
|
+
init_app_selector();
|
|
17225
17318
|
init_cli_output();
|
|
17226
17319
|
init_errors();
|
|
17227
17320
|
init_pathResolver();
|
|
17321
|
+
import { spawn, execSync as execSync3 } from "node:child_process";
|
|
17322
|
+
import { platform } from "node:os";
|
|
17228
17323
|
|
|
17229
17324
|
// packages/tooling/src/utils/spawn-utils.ts
|
|
17230
17325
|
init_utils();
|
|
@@ -17470,18 +17565,23 @@ async function main2() {
|
|
|
17470
17565
|
|
|
17471
17566
|
// packages/tooling/src/apps/emu.ts
|
|
17472
17567
|
init_utils();
|
|
17568
|
+
init_app_selector();
|
|
17569
|
+
init_cli_output();
|
|
17570
|
+
init_errors();
|
|
17571
|
+
init_pathResolver();
|
|
17572
|
+
|
|
17573
|
+
// packages/tooling/src/apps/emu-firebase.ts
|
|
17574
|
+
init_utils();
|
|
17575
|
+
init_cli_input();
|
|
17576
|
+
init_cli_output();
|
|
17577
|
+
init_pathResolver();
|
|
17578
|
+
init_typed_file_operations();
|
|
17473
17579
|
import {
|
|
17474
17580
|
spawn as spawn2,
|
|
17475
17581
|
spawnSync as spawnSync3,
|
|
17476
17582
|
execSync as execSync4
|
|
17477
17583
|
} from "node:child_process";
|
|
17478
17584
|
import { platform as platform2 } from "node:os";
|
|
17479
|
-
init_cli_input();
|
|
17480
|
-
init_cli_output();
|
|
17481
|
-
init_errors();
|
|
17482
|
-
init_pathResolver();
|
|
17483
|
-
init_pathResolver();
|
|
17484
|
-
init_typed_file_operations();
|
|
17485
17585
|
function discoverFirebaseProjectId(appPath) {
|
|
17486
17586
|
const firebasercPath = joinPath(appPath, ".firebaserc");
|
|
17487
17587
|
if (pathExists(firebasercPath)) {
|
|
@@ -17513,7 +17613,7 @@ function killPorts(ports) {
|
|
|
17513
17613
|
pids.add(match[1]);
|
|
17514
17614
|
}
|
|
17515
17615
|
}
|
|
17516
|
-
for (const pid of pids) {
|
|
17616
|
+
for (const pid of Array.from(pids)) {
|
|
17517
17617
|
try {
|
|
17518
17618
|
execSync4(`taskkill /F /PID ${pid}`, { stdio: "ignore" });
|
|
17519
17619
|
log.debug(`Killed process ${pid} on port ${port}`);
|
|
@@ -17575,9 +17675,9 @@ function loadEnvFile(filePath) {
|
|
|
17575
17675
|
} catch {
|
|
17576
17676
|
}
|
|
17577
17677
|
}
|
|
17578
|
-
async function
|
|
17579
|
-
const
|
|
17580
|
-
|
|
17678
|
+
async function startFirebase(app, projectRoot, options = {}) {
|
|
17679
|
+
const debug = options.debug ?? false;
|
|
17680
|
+
let selectedServices = options.selectedServices ?? [];
|
|
17581
17681
|
const serviceChoices = [
|
|
17582
17682
|
{
|
|
17583
17683
|
title: "Auth",
|
|
@@ -17600,47 +17700,6 @@ async function main3(options) {
|
|
|
17600
17700
|
hint: "Stripe webhook forwarding (for payment testing)"
|
|
17601
17701
|
}
|
|
17602
17702
|
];
|
|
17603
|
-
let selectedServices = [];
|
|
17604
|
-
const appName = args.find(
|
|
17605
|
-
(arg) => arg !== "emu" && arg !== "--debug" && !arg.startsWith("--")
|
|
17606
|
-
);
|
|
17607
|
-
if (options?.services) {
|
|
17608
|
-
selectedServices = options.services.split(",").map((s) => s.trim());
|
|
17609
|
-
} else {
|
|
17610
|
-
const servicesArg = args.find((arg) => arg.startsWith("--services="));
|
|
17611
|
-
if (servicesArg) {
|
|
17612
|
-
const servicesList = servicesArg.split("=")[1];
|
|
17613
|
-
if (servicesList) {
|
|
17614
|
-
selectedServices = servicesList.split(",").map((s) => s.trim());
|
|
17615
|
-
}
|
|
17616
|
-
} else {
|
|
17617
|
-
if (options?.auth || args.includes("--auth"))
|
|
17618
|
-
selectedServices.push("auth");
|
|
17619
|
-
if (args.includes("--functions")) selectedServices.push("functions");
|
|
17620
|
-
if (options?.firestore || args.includes("--firestore"))
|
|
17621
|
-
selectedServices.push("firestore");
|
|
17622
|
-
if (options?.stripe || args.includes("--stripe"))
|
|
17623
|
-
selectedServices.push("stripe");
|
|
17624
|
-
}
|
|
17625
|
-
}
|
|
17626
|
-
const validServices = serviceChoices.map((c) => c.value);
|
|
17627
|
-
selectedServices = selectedServices.filter((s) => validServices.includes(s));
|
|
17628
|
-
const projectRoot = getRepoRoot();
|
|
17629
|
-
if (!projectRoot) {
|
|
17630
|
-
throw new DoNotDevError(
|
|
17631
|
-
"Could not determine repository root",
|
|
17632
|
-
"path-resolution-error"
|
|
17633
|
-
);
|
|
17634
|
-
}
|
|
17635
|
-
const app = await selectApp(projectRoot, appName);
|
|
17636
|
-
if (!app) {
|
|
17637
|
-
return 1;
|
|
17638
|
-
}
|
|
17639
|
-
if (!app.hasFunctions || app.platform !== "firebase") {
|
|
17640
|
-
log.error(`App "${app.name}" does not have Firebase functions.`);
|
|
17641
|
-
log.error('Use "dndev dev" for apps without functions.\n');
|
|
17642
|
-
return 1;
|
|
17643
|
-
}
|
|
17644
17703
|
log.info(`Starting Firebase emulators + dev server for ${app.name}...
|
|
17645
17704
|
`);
|
|
17646
17705
|
if (selectedServices.length === 0) {
|
|
@@ -17772,7 +17831,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
17772
17831
|
const stripeWebhookUrl = `http://localhost:5001/${projectId}/${region}/stripeWebhook`;
|
|
17773
17832
|
concurrentlyArgs.push(`stripe listen --forward-to ${stripeWebhookUrl}`);
|
|
17774
17833
|
log.info("");
|
|
17775
|
-
log.info("
|
|
17834
|
+
log.info("Stripe webhook forwarding will start automatically");
|
|
17776
17835
|
log.info(` Webhook URL: ${stripeWebhookUrl}`);
|
|
17777
17836
|
log.info(" To trigger test events, run in another terminal:");
|
|
17778
17837
|
log.info(" stripe trigger checkout.session.completed");
|
|
@@ -17794,9 +17853,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
17794
17853
|
);
|
|
17795
17854
|
const SIGNAL_EXIT_CODES3 = {
|
|
17796
17855
|
SIGINT: 130,
|
|
17797
|
-
// 128 + 2
|
|
17798
17856
|
SIGTERM: 143
|
|
17799
|
-
// 128 + 15
|
|
17800
17857
|
};
|
|
17801
17858
|
const cleanup = (signal) => {
|
|
17802
17859
|
if (!childProcess.pid) return;
|
|
@@ -17846,23 +17903,232 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
17846
17903
|
});
|
|
17847
17904
|
childProcess.on("error", (error2) => {
|
|
17848
17905
|
handlers.forEach((h2) => h2());
|
|
17849
|
-
log.error(`Failed to start emulators: ${error2.message}`);
|
|
17906
|
+
log.error(`Failed to start Firebase emulators: ${error2.message}`);
|
|
17850
17907
|
resolve4(1);
|
|
17851
17908
|
});
|
|
17852
17909
|
});
|
|
17853
17910
|
}
|
|
17854
17911
|
|
|
17855
|
-
// packages/tooling/src/apps/
|
|
17912
|
+
// packages/tooling/src/apps/emu-supabase.ts
|
|
17856
17913
|
init_utils();
|
|
17857
|
-
|
|
17858
|
-
|
|
17859
|
-
spawnSync as spawnSync4,
|
|
17860
|
-
execSync as execSync5
|
|
17861
|
-
} from "node:child_process";
|
|
17914
|
+
init_cli_output();
|
|
17915
|
+
import { spawn as spawn3, execSync as execSync5 } from "node:child_process";
|
|
17862
17916
|
import { platform as platform3 } from "node:os";
|
|
17917
|
+
function isDockerRunning() {
|
|
17918
|
+
try {
|
|
17919
|
+
execSync5("docker info", { stdio: "pipe", timeout: 5e3 });
|
|
17920
|
+
return true;
|
|
17921
|
+
} catch {
|
|
17922
|
+
return false;
|
|
17923
|
+
}
|
|
17924
|
+
}
|
|
17925
|
+
async function startSupabase(app, _projectRoot) {
|
|
17926
|
+
log.info(`Starting Supabase local stack + dev server for ${app.name}...
|
|
17927
|
+
`);
|
|
17928
|
+
if (!isDockerRunning()) {
|
|
17929
|
+
log.error("Docker is not running. Supabase local dev requires Docker.");
|
|
17930
|
+
log.error("Start Docker Desktop and try again.\n");
|
|
17931
|
+
return 1;
|
|
17932
|
+
}
|
|
17933
|
+
try {
|
|
17934
|
+
execSync5("supabase --version", { stdio: "pipe" });
|
|
17935
|
+
} catch {
|
|
17936
|
+
log.error("Supabase CLI not found. Install it:");
|
|
17937
|
+
log.error(" npm install -g supabase\n");
|
|
17938
|
+
return 1;
|
|
17939
|
+
}
|
|
17940
|
+
const isWindows = platform3() === "win32";
|
|
17941
|
+
const concurrentlyArgs = [
|
|
17942
|
+
"--kill-others-on-fail",
|
|
17943
|
+
"--prefix-colors",
|
|
17944
|
+
"cyan,green",
|
|
17945
|
+
"--prefix",
|
|
17946
|
+
"[{name}]",
|
|
17947
|
+
"--names",
|
|
17948
|
+
"supabase,dev",
|
|
17949
|
+
"supabase start",
|
|
17950
|
+
`bunx turbo dev --filter=${app.packageName}`
|
|
17951
|
+
];
|
|
17952
|
+
const childProcess = spawn3(
|
|
17953
|
+
"bunx",
|
|
17954
|
+
["concurrently", ...concurrentlyArgs],
|
|
17955
|
+
{
|
|
17956
|
+
stdio: "inherit",
|
|
17957
|
+
cwd: app.path,
|
|
17958
|
+
shell: isWindows
|
|
17959
|
+
}
|
|
17960
|
+
);
|
|
17961
|
+
const cleanup = () => {
|
|
17962
|
+
if (!childProcess.pid) return;
|
|
17963
|
+
if (isWindows) {
|
|
17964
|
+
try {
|
|
17965
|
+
execSync5(`taskkill /F /T /PID ${childProcess.pid}`, {
|
|
17966
|
+
stdio: "ignore",
|
|
17967
|
+
timeout: 2e3
|
|
17968
|
+
});
|
|
17969
|
+
} catch {
|
|
17970
|
+
}
|
|
17971
|
+
} else {
|
|
17972
|
+
try {
|
|
17973
|
+
process.kill(childProcess.pid, "SIGTERM");
|
|
17974
|
+
} catch {
|
|
17975
|
+
}
|
|
17976
|
+
}
|
|
17977
|
+
};
|
|
17978
|
+
process.on("SIGINT", () => {
|
|
17979
|
+
cleanup();
|
|
17980
|
+
process.exit(130);
|
|
17981
|
+
});
|
|
17982
|
+
process.on("SIGTERM", () => {
|
|
17983
|
+
cleanup();
|
|
17984
|
+
process.exit(143);
|
|
17985
|
+
});
|
|
17986
|
+
return new Promise((resolve4) => {
|
|
17987
|
+
childProcess.on("exit", (code) => resolve4(code ?? 0));
|
|
17988
|
+
childProcess.on("error", (error2) => {
|
|
17989
|
+
log.error(`Failed to start Supabase local dev: ${error2.message}`);
|
|
17990
|
+
resolve4(1);
|
|
17991
|
+
});
|
|
17992
|
+
});
|
|
17993
|
+
}
|
|
17994
|
+
|
|
17995
|
+
// packages/tooling/src/apps/emu-vercel.ts
|
|
17996
|
+
init_utils();
|
|
17997
|
+
init_cli_output();
|
|
17998
|
+
import { spawn as spawn4, execSync as execSync6 } from "node:child_process";
|
|
17999
|
+
import { platform as platform4 } from "node:os";
|
|
18000
|
+
async function startVercel(app, _projectRoot) {
|
|
18001
|
+
log.info(`Starting Vercel dev server for ${app.name}...
|
|
18002
|
+
`);
|
|
18003
|
+
try {
|
|
18004
|
+
execSync6("vercel --version", { stdio: "pipe" });
|
|
18005
|
+
} catch {
|
|
18006
|
+
log.error("Vercel CLI not found. Install it:");
|
|
18007
|
+
log.error(" npm install -g vercel\n");
|
|
18008
|
+
return 1;
|
|
18009
|
+
}
|
|
18010
|
+
const isWindows = platform4() === "win32";
|
|
18011
|
+
const childProcess = spawn4("vercel", ["dev"], {
|
|
18012
|
+
stdio: "inherit",
|
|
18013
|
+
cwd: app.path,
|
|
18014
|
+
shell: isWindows
|
|
18015
|
+
});
|
|
18016
|
+
const cleanup = () => {
|
|
18017
|
+
if (!childProcess.pid) return;
|
|
18018
|
+
if (isWindows) {
|
|
18019
|
+
try {
|
|
18020
|
+
execSync6(`taskkill /F /T /PID ${childProcess.pid}`, {
|
|
18021
|
+
stdio: "ignore",
|
|
18022
|
+
timeout: 2e3
|
|
18023
|
+
});
|
|
18024
|
+
} catch {
|
|
18025
|
+
}
|
|
18026
|
+
} else {
|
|
18027
|
+
try {
|
|
18028
|
+
process.kill(childProcess.pid, "SIGTERM");
|
|
18029
|
+
} catch {
|
|
18030
|
+
}
|
|
18031
|
+
}
|
|
18032
|
+
};
|
|
18033
|
+
process.on("SIGINT", () => {
|
|
18034
|
+
cleanup();
|
|
18035
|
+
process.exit(130);
|
|
18036
|
+
});
|
|
18037
|
+
process.on("SIGTERM", () => {
|
|
18038
|
+
cleanup();
|
|
18039
|
+
process.exit(143);
|
|
18040
|
+
});
|
|
18041
|
+
return new Promise((resolve4) => {
|
|
18042
|
+
childProcess.on("exit", (code) => resolve4(code ?? 0));
|
|
18043
|
+
childProcess.on("error", (error2) => {
|
|
18044
|
+
log.error(`Failed to start Vercel dev: ${error2.message}`);
|
|
18045
|
+
resolve4(1);
|
|
18046
|
+
});
|
|
18047
|
+
});
|
|
18048
|
+
}
|
|
18049
|
+
|
|
18050
|
+
// packages/tooling/src/apps/emu.ts
|
|
18051
|
+
async function main3(options) {
|
|
18052
|
+
const args = process.argv.slice(2);
|
|
18053
|
+
const projectRoot = getRepoRoot();
|
|
18054
|
+
if (!projectRoot) {
|
|
18055
|
+
throw new DoNotDevError(
|
|
18056
|
+
"Could not determine repository root",
|
|
18057
|
+
"path-resolution-error"
|
|
18058
|
+
);
|
|
18059
|
+
}
|
|
18060
|
+
const appName = args.find(
|
|
18061
|
+
(arg) => arg !== "emu" && arg !== "--debug" && !arg.startsWith("--")
|
|
18062
|
+
);
|
|
18063
|
+
const app = await selectApp(projectRoot, appName);
|
|
18064
|
+
if (!app) {
|
|
18065
|
+
return 1;
|
|
18066
|
+
}
|
|
18067
|
+
switch (app.platform) {
|
|
18068
|
+
case "firebase": {
|
|
18069
|
+
if (!app.hasFunctions) {
|
|
18070
|
+
log.error(
|
|
18071
|
+
`App "${app.name}" has Firebase config but no functions directory.`
|
|
18072
|
+
);
|
|
18073
|
+
log.error('Use "dndev dev" for apps without backend functions.\n');
|
|
18074
|
+
return 1;
|
|
18075
|
+
}
|
|
18076
|
+
const selectedServices = parseFirebaseServices(args, options);
|
|
18077
|
+
return startFirebase(app, projectRoot, {
|
|
18078
|
+
debug: options?.debug ?? false,
|
|
18079
|
+
selectedServices
|
|
18080
|
+
});
|
|
18081
|
+
}
|
|
18082
|
+
case "supabase":
|
|
18083
|
+
return startSupabase(app, projectRoot);
|
|
18084
|
+
case "vercel":
|
|
18085
|
+
return startVercel(app, projectRoot);
|
|
18086
|
+
default:
|
|
18087
|
+
log.error(`App "${app.name}" does not have a detected backend platform.`);
|
|
18088
|
+
log.error(
|
|
18089
|
+
"Expected: firebase.json (Firebase), supabase/config.toml or @donotdev/supabase (Supabase), or vercel.json (Vercel)."
|
|
18090
|
+
);
|
|
18091
|
+
log.error('Use "dndev dev" for apps without a backend.\n');
|
|
18092
|
+
return 1;
|
|
18093
|
+
}
|
|
18094
|
+
}
|
|
18095
|
+
function parseFirebaseServices(args, options) {
|
|
18096
|
+
const validServices = ["auth", "functions", "firestore", "stripe"];
|
|
18097
|
+
let selectedServices = [];
|
|
18098
|
+
if (options?.services) {
|
|
18099
|
+
selectedServices = options.services.split(",").map((s) => s.trim());
|
|
18100
|
+
} else {
|
|
18101
|
+
const servicesArg = args.find((arg) => arg.startsWith("--services="));
|
|
18102
|
+
if (servicesArg) {
|
|
18103
|
+
const servicesList = servicesArg.split("=")[1];
|
|
18104
|
+
if (servicesList) {
|
|
18105
|
+
selectedServices = servicesList.split(",").map((s) => s.trim());
|
|
18106
|
+
}
|
|
18107
|
+
} else {
|
|
18108
|
+
if (options?.auth || args.includes("--auth"))
|
|
18109
|
+
selectedServices.push("auth");
|
|
18110
|
+
if (args.includes("--functions")) selectedServices.push("functions");
|
|
18111
|
+
if (options?.firestore || args.includes("--firestore"))
|
|
18112
|
+
selectedServices.push("firestore");
|
|
18113
|
+
if (options?.stripe || args.includes("--stripe"))
|
|
18114
|
+
selectedServices.push("stripe");
|
|
18115
|
+
}
|
|
18116
|
+
}
|
|
18117
|
+
return selectedServices.filter((s) => validServices.includes(s));
|
|
18118
|
+
}
|
|
18119
|
+
|
|
18120
|
+
// packages/tooling/src/apps/preview.ts
|
|
18121
|
+
init_utils();
|
|
18122
|
+
init_app_selector();
|
|
17863
18123
|
init_cli_output();
|
|
17864
18124
|
init_errors();
|
|
17865
18125
|
init_pathResolver();
|
|
18126
|
+
import {
|
|
18127
|
+
spawn as spawn5,
|
|
18128
|
+
spawnSync as spawnSync4,
|
|
18129
|
+
execSync as execSync7
|
|
18130
|
+
} from "node:child_process";
|
|
18131
|
+
import { platform as platform5 } from "node:os";
|
|
17866
18132
|
var SIGNAL_EXIT_CODES2 = {
|
|
17867
18133
|
SIGINT: 130,
|
|
17868
18134
|
// 128 + 2
|
|
@@ -17905,8 +18171,8 @@ async function main4() {
|
|
|
17905
18171
|
log.info(`Previewing ${app.name}...
|
|
17906
18172
|
`);
|
|
17907
18173
|
const turboArgs = ["preview", "--filter", app.packageName];
|
|
17908
|
-
const isWindows =
|
|
17909
|
-
const childProcess =
|
|
18174
|
+
const isWindows = platform5() === "win32";
|
|
18175
|
+
const childProcess = spawn5("bunx", ["turbo", ...turboArgs], {
|
|
17910
18176
|
stdio: "inherit",
|
|
17911
18177
|
env: createAppEnv(app.path),
|
|
17912
18178
|
cwd: projectRoot,
|
|
@@ -17917,7 +18183,7 @@ async function main4() {
|
|
|
17917
18183
|
log.debug(`Received ${signal}, cleaning up processes...`);
|
|
17918
18184
|
if (isWindows) {
|
|
17919
18185
|
try {
|
|
17920
|
-
|
|
18186
|
+
execSync7(`taskkill /F /T /PID ${childProcess.pid}`, {
|
|
17921
18187
|
stdio: "ignore",
|
|
17922
18188
|
timeout: 2e3
|
|
17923
18189
|
});
|
|
@@ -17929,7 +18195,7 @@ async function main4() {
|
|
|
17929
18195
|
} catch {
|
|
17930
18196
|
}
|
|
17931
18197
|
try {
|
|
17932
|
-
|
|
18198
|
+
execSync7(`pkill -P ${childProcess.pid}`, {
|
|
17933
18199
|
stdio: "ignore",
|
|
17934
18200
|
timeout: 1e3
|
|
17935
18201
|
});
|
|
@@ -17968,7 +18234,7 @@ async function main4() {
|
|
|
17968
18234
|
|
|
17969
18235
|
// packages/tooling/src/apps/deploy.ts
|
|
17970
18236
|
init_utils();
|
|
17971
|
-
import { execSync as
|
|
18237
|
+
import { execSync as execSync10 } from "node:child_process";
|
|
17972
18238
|
|
|
17973
18239
|
// packages/tooling/src/apps/deploy-frontend.ts
|
|
17974
18240
|
init_utils();
|
|
@@ -18269,15 +18535,14 @@ function getMatrixPath(mode) {
|
|
|
18269
18535
|
}
|
|
18270
18536
|
const executionMode = mode || detectExecutionMode();
|
|
18271
18537
|
if (executionMode === "development") {
|
|
18272
|
-
const
|
|
18273
|
-
|
|
18274
|
-
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18279
|
-
|
|
18280
|
-
}
|
|
18538
|
+
const templatesRoot = getTemplatesRoot();
|
|
18539
|
+
const devPath = normalizePath(
|
|
18540
|
+
templatesRoot,
|
|
18541
|
+
"..",
|
|
18542
|
+
"dependencies-matrix.json"
|
|
18543
|
+
);
|
|
18544
|
+
if (pathExists(devPath)) {
|
|
18545
|
+
return devPath;
|
|
18281
18546
|
}
|
|
18282
18547
|
}
|
|
18283
18548
|
return null;
|
|
@@ -18292,8 +18557,8 @@ function getCliVersion(mode) {
|
|
|
18292
18557
|
}
|
|
18293
18558
|
const executionMode = mode || detectExecutionMode();
|
|
18294
18559
|
if (executionMode === "development") {
|
|
18295
|
-
const
|
|
18296
|
-
const cliPackageJson =
|
|
18560
|
+
const templatesRoot = getTemplatesRoot();
|
|
18561
|
+
const cliPackageJson = normalizePath(templatesRoot, "..", "package.json");
|
|
18297
18562
|
if (pathExists(cliPackageJson)) {
|
|
18298
18563
|
const pkg = readSync(cliPackageJson, { format: "json" });
|
|
18299
18564
|
return String(pkg?.version || "0.0.0");
|
|
@@ -18446,7 +18711,12 @@ async function runQuestionnaire(questions, initialAnswers, showWIP, askFor) {
|
|
|
18446
18711
|
async function deployFrontend(appDir, serviceAccountPath, projectId, config) {
|
|
18447
18712
|
const s = Y2();
|
|
18448
18713
|
s.start("Deploying frontend to Firebase Hosting...");
|
|
18449
|
-
const args = buildFirebaseDeployArgs(
|
|
18714
|
+
const args = buildFirebaseDeployArgs(
|
|
18715
|
+
"hosting",
|
|
18716
|
+
projectId,
|
|
18717
|
+
config.debug,
|
|
18718
|
+
config.force ?? true
|
|
18719
|
+
);
|
|
18450
18720
|
const result = executeFirebaseCommand(args, {
|
|
18451
18721
|
cwd: appDir,
|
|
18452
18722
|
serviceAccountPath,
|
|
@@ -18470,15 +18740,33 @@ async function deployFrontend(appDir, serviceAccountPath, projectId, config) {
|
|
|
18470
18740
|
|
|
18471
18741
|
// packages/tooling/src/apps/deploy-vercel-frontend.ts
|
|
18472
18742
|
init_utils();
|
|
18473
|
-
|
|
18743
|
+
init_cli_output();
|
|
18744
|
+
init_vercel_token();
|
|
18745
|
+
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
18474
18746
|
async function deployVercelFrontend(appDir, _config) {
|
|
18475
18747
|
const s = Y2();
|
|
18476
18748
|
s.start("Deploying frontend to Vercel...");
|
|
18749
|
+
const token = resolveVercelToken(appDir);
|
|
18750
|
+
if (token) {
|
|
18751
|
+
log.debug("Using VERCEL_TOKEN from .env (token-based auth)");
|
|
18752
|
+
}
|
|
18753
|
+
const args = ["vercel", "--prod", "--yes"];
|
|
18754
|
+
if (token) {
|
|
18755
|
+
args.push("--token", token);
|
|
18756
|
+
}
|
|
18477
18757
|
try {
|
|
18478
|
-
|
|
18758
|
+
const result = spawnSync6("bunx", args, {
|
|
18479
18759
|
cwd: appDir,
|
|
18480
|
-
stdio: "
|
|
18760
|
+
stdio: "pipe",
|
|
18761
|
+
encoding: "utf-8"
|
|
18481
18762
|
});
|
|
18763
|
+
if (result.status !== 0) {
|
|
18764
|
+
s.stop("Vercel deployment failed");
|
|
18765
|
+
const errOutput = result.stderr?.trim();
|
|
18766
|
+
throw new Error(
|
|
18767
|
+
errOutput || `Vercel deploy exited with code ${result.status}`
|
|
18768
|
+
);
|
|
18769
|
+
}
|
|
18482
18770
|
s.stop("Frontend deployed to Vercel");
|
|
18483
18771
|
} catch (err) {
|
|
18484
18772
|
s.stop("Vercel deployment failed");
|
|
@@ -18489,7 +18777,7 @@ async function deployVercelFrontend(appDir, _config) {
|
|
|
18489
18777
|
// packages/tooling/src/apps/deploy-functions.ts
|
|
18490
18778
|
init_utils();
|
|
18491
18779
|
var import_yaml = __toESM(require_dist(), 1);
|
|
18492
|
-
import { execSync as
|
|
18780
|
+
import { execSync as execSync8, spawnSync as spawnSync7 } from "node:child_process";
|
|
18493
18781
|
init_pathResolver();
|
|
18494
18782
|
init_cli_tools();
|
|
18495
18783
|
init_typed_file_operations();
|
|
@@ -18658,7 +18946,7 @@ function updateCloudRunIAM(functionNames, projectId, region, serviceAccountPath,
|
|
|
18658
18946
|
let failCount = 0;
|
|
18659
18947
|
for (const funcName of functionNames) {
|
|
18660
18948
|
try {
|
|
18661
|
-
const result =
|
|
18949
|
+
const result = spawnSync7(
|
|
18662
18950
|
"gcloud",
|
|
18663
18951
|
[
|
|
18664
18952
|
"run",
|
|
@@ -18776,7 +19064,7 @@ async function autoSyncSecrets(functionsDir, projectId, config) {
|
|
|
18776
19064
|
let failCount = 0;
|
|
18777
19065
|
for (const { key, value } of secrets) {
|
|
18778
19066
|
try {
|
|
18779
|
-
const result =
|
|
19067
|
+
const result = spawnSync7(
|
|
18780
19068
|
firebaseCmd,
|
|
18781
19069
|
["functions:secrets:set", key, "--project", projectId],
|
|
18782
19070
|
{
|
|
@@ -18858,7 +19146,7 @@ To fix this, run:
|
|
|
18858
19146
|
const s2 = Y2();
|
|
18859
19147
|
s2.start("Building functions...");
|
|
18860
19148
|
try {
|
|
18861
|
-
|
|
19149
|
+
execSync8("bun run build", {
|
|
18862
19150
|
cwd: functionsDir,
|
|
18863
19151
|
stdio: config.verbose ? "inherit" : "pipe"
|
|
18864
19152
|
});
|
|
@@ -18934,7 +19222,12 @@ async function deployRules(appDir, serviceAccountPath, projectId, config, option
|
|
|
18934
19222
|
const targetNames = targets.join(", ");
|
|
18935
19223
|
const s = Y2();
|
|
18936
19224
|
s.start(`Deploying ${targetNames}...`);
|
|
18937
|
-
const args = buildFirebaseDeployArgs(
|
|
19225
|
+
const args = buildFirebaseDeployArgs(
|
|
19226
|
+
targets,
|
|
19227
|
+
projectId,
|
|
19228
|
+
config.debug,
|
|
19229
|
+
config.force ?? true
|
|
19230
|
+
);
|
|
18938
19231
|
const result = executeFirebaseCommand(args, {
|
|
18939
19232
|
cwd: appDir,
|
|
18940
19233
|
serviceAccountPath,
|
|
@@ -18958,29 +19251,10 @@ async function deployRules(appDir, serviceAccountPath, projectId, config, option
|
|
|
18958
19251
|
|
|
18959
19252
|
// packages/tooling/src/apps/deploy-utils.ts
|
|
18960
19253
|
init_utils();
|
|
18961
|
-
import { spawnSync as
|
|
19254
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
18962
19255
|
init_pathResolver();
|
|
18963
19256
|
init_typed_file_operations();
|
|
18964
|
-
|
|
18965
|
-
// packages/tooling/src/utils/error-handling.ts
|
|
18966
|
-
init_utils();
|
|
18967
|
-
function isError(error2) {
|
|
18968
|
-
return error2 instanceof Error;
|
|
18969
|
-
}
|
|
18970
|
-
function getErrorMessage(error2) {
|
|
18971
|
-
if (isError(error2)) {
|
|
18972
|
-
return error2.message;
|
|
18973
|
-
}
|
|
18974
|
-
if (typeof error2 === "string") {
|
|
18975
|
-
return error2;
|
|
18976
|
-
}
|
|
18977
|
-
if (error2 && typeof error2 === "object" && "message" in error2) {
|
|
18978
|
-
return String(error2.message);
|
|
18979
|
-
}
|
|
18980
|
-
return String(error2);
|
|
18981
|
-
}
|
|
18982
|
-
|
|
18983
|
-
// packages/tooling/src/apps/deploy-utils.ts
|
|
19257
|
+
init_error_handling();
|
|
18984
19258
|
function detectAvailableApps() {
|
|
18985
19259
|
const currentDir = process.cwd();
|
|
18986
19260
|
const appsDir = joinPath(currentDir, "apps");
|
|
@@ -19165,7 +19439,7 @@ How to fix:
|
|
|
19165
19439
|
if (shouldOpen) {
|
|
19166
19440
|
try {
|
|
19167
19441
|
const openCommand = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
|
|
19168
|
-
|
|
19442
|
+
spawnSync8(openCommand, [consoleUrl], { shell: true });
|
|
19169
19443
|
log.success("Opening Firebase Console...");
|
|
19170
19444
|
} catch {
|
|
19171
19445
|
log.warn("Could not open browser. Please open the URL manually.");
|
|
@@ -19236,7 +19510,7 @@ function detectProvider(appDir) {
|
|
|
19236
19510
|
if (hasFirebase) {
|
|
19237
19511
|
try {
|
|
19238
19512
|
const config = readSync(firebaseJsonPath, { format: "json" });
|
|
19239
|
-
if (config && typeof config === "object"
|
|
19513
|
+
if (config && typeof config === "object") {
|
|
19240
19514
|
const firebaseConfigObj = config;
|
|
19241
19515
|
firebaseConfig = {
|
|
19242
19516
|
projectId: firebaseConfigObj.projectId,
|
|
@@ -19245,8 +19519,6 @@ function detectProvider(appDir) {
|
|
|
19245
19519
|
hasFirestoreRules: !!firebaseConfigObj.firestore?.rules,
|
|
19246
19520
|
hasStorageRules: !!firebaseConfigObj.storage?.rules
|
|
19247
19521
|
};
|
|
19248
|
-
} else {
|
|
19249
|
-
throw new Error("Invalid firebase.json structure");
|
|
19250
19522
|
}
|
|
19251
19523
|
} catch {
|
|
19252
19524
|
firebaseConfig = {
|
|
@@ -19329,13 +19601,17 @@ async function main6(options = {}) {
|
|
|
19329
19601
|
const availableApps = detectAvailableApps();
|
|
19330
19602
|
if (availableApps.length === 0) {
|
|
19331
19603
|
if (providerInfo.hasSupabase && !providerInfo.hasFirebase) {
|
|
19332
|
-
log.info(
|
|
19604
|
+
log.info(
|
|
19605
|
+
"Supabase project detected. Deploying Supabase resources..."
|
|
19606
|
+
);
|
|
19333
19607
|
} else {
|
|
19334
19608
|
log.info("No apps with firebase.json or supabase/ directory found.");
|
|
19335
19609
|
log.info(
|
|
19336
19610
|
"To deploy, ensure your app has a firebase.json or supabase/ configuration."
|
|
19337
19611
|
);
|
|
19338
|
-
log.info(
|
|
19612
|
+
log.info(
|
|
19613
|
+
"Run from a DoNotDev project, or create one with: dndev init"
|
|
19614
|
+
);
|
|
19339
19615
|
return;
|
|
19340
19616
|
}
|
|
19341
19617
|
}
|
|
@@ -19554,7 +19830,7 @@ async function main6(options = {}) {
|
|
|
19554
19830
|
isStaging ? "Building (staging mode)..." : "Building application..."
|
|
19555
19831
|
);
|
|
19556
19832
|
try {
|
|
19557
|
-
|
|
19833
|
+
execSync10(buildCmd, {
|
|
19558
19834
|
cwd: appDir,
|
|
19559
19835
|
stdio: "inherit",
|
|
19560
19836
|
env: {
|
|
@@ -19615,12 +19891,7 @@ async function main6(options = {}) {
|
|
|
19615
19891
|
}
|
|
19616
19892
|
}
|
|
19617
19893
|
}
|
|
19618
|
-
await deployFunctions(
|
|
19619
|
-
appDir,
|
|
19620
|
-
serviceAccountPath,
|
|
19621
|
-
config.project,
|
|
19622
|
-
config
|
|
19623
|
-
);
|
|
19894
|
+
await deployFunctions(appDir, serviceAccountPath, config.project, config);
|
|
19624
19895
|
}
|
|
19625
19896
|
if (shouldDeployFirebaseRules && serviceAccountPath && config.project && appProviderInfo.firebaseConfig) {
|
|
19626
19897
|
await deployRules(appDir, serviceAccountPath, config.project, config, {
|
|
@@ -19799,10 +20070,10 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
19799
20070
|
}
|
|
19800
20071
|
if (templateName.includes("functions")) {
|
|
19801
20072
|
result.main = "lib/index.js";
|
|
19802
|
-
result.engines = { node: "
|
|
20073
|
+
result.engines = { node: "22" };
|
|
19803
20074
|
if (options.appName) {
|
|
19804
|
-
const
|
|
19805
|
-
result.description = `${options.appName} ${
|
|
20075
|
+
const platform6 = templateName.includes("vercel") ? "Vercel" : "Firebase";
|
|
20076
|
+
result.description = `${options.appName} ${platform6} Functions`;
|
|
19806
20077
|
}
|
|
19807
20078
|
if (mode === "development") {
|
|
19808
20079
|
const workspacePkgs = [
|
|
@@ -19844,18 +20115,102 @@ init_pathResolver();
|
|
|
19844
20115
|
// packages/tooling/src/scaffolding/scaffold-matrix.ts
|
|
19845
20116
|
init_utils();
|
|
19846
20117
|
var MATRIX = [
|
|
19847
|
-
{
|
|
19848
|
-
|
|
19849
|
-
|
|
19850
|
-
|
|
19851
|
-
|
|
19852
|
-
|
|
19853
|
-
|
|
19854
|
-
|
|
19855
|
-
{
|
|
19856
|
-
|
|
19857
|
-
|
|
19858
|
-
|
|
20118
|
+
{
|
|
20119
|
+
builder: "vite",
|
|
20120
|
+
backend: "none",
|
|
20121
|
+
baseTemplate: "app-vite",
|
|
20122
|
+
overlay: null,
|
|
20123
|
+
deployConfig: null,
|
|
20124
|
+
functionsTemplate: null
|
|
20125
|
+
},
|
|
20126
|
+
{
|
|
20127
|
+
builder: "vite",
|
|
20128
|
+
backend: "firebase",
|
|
20129
|
+
baseTemplate: "app-vite",
|
|
20130
|
+
overlay: "overlay-firebase",
|
|
20131
|
+
deployConfig: "firebase",
|
|
20132
|
+
functionsTemplate: "functions-firebase"
|
|
20133
|
+
},
|
|
20134
|
+
{
|
|
20135
|
+
builder: "vite",
|
|
20136
|
+
backend: "supabase",
|
|
20137
|
+
baseTemplate: "app-vite",
|
|
20138
|
+
overlay: "overlay-supabase",
|
|
20139
|
+
deployConfig: "vercel-supabase",
|
|
20140
|
+
functionsTemplate: "functions-supabase"
|
|
20141
|
+
},
|
|
20142
|
+
{
|
|
20143
|
+
builder: "vite",
|
|
20144
|
+
backend: "vercel",
|
|
20145
|
+
baseTemplate: "app-vite",
|
|
20146
|
+
overlay: "overlay-vercel",
|
|
20147
|
+
deployConfig: "vercel-vercel",
|
|
20148
|
+
functionsTemplate: "functions-vercel"
|
|
20149
|
+
},
|
|
20150
|
+
{
|
|
20151
|
+
builder: "nextjs",
|
|
20152
|
+
backend: "none",
|
|
20153
|
+
baseTemplate: "app-next",
|
|
20154
|
+
overlay: null,
|
|
20155
|
+
deployConfig: null,
|
|
20156
|
+
functionsTemplate: null
|
|
20157
|
+
},
|
|
20158
|
+
{
|
|
20159
|
+
builder: "nextjs",
|
|
20160
|
+
backend: "firebase",
|
|
20161
|
+
baseTemplate: "app-next",
|
|
20162
|
+
overlay: "overlay-firebase",
|
|
20163
|
+
deployConfig: "firebase",
|
|
20164
|
+
functionsTemplate: "functions-firebase"
|
|
20165
|
+
},
|
|
20166
|
+
{
|
|
20167
|
+
builder: "nextjs",
|
|
20168
|
+
backend: "supabase",
|
|
20169
|
+
baseTemplate: "app-next",
|
|
20170
|
+
overlay: "overlay-supabase",
|
|
20171
|
+
deployConfig: "vercel-supabase",
|
|
20172
|
+
functionsTemplate: "functions-supabase"
|
|
20173
|
+
},
|
|
20174
|
+
{
|
|
20175
|
+
builder: "nextjs",
|
|
20176
|
+
backend: "vercel",
|
|
20177
|
+
baseTemplate: "app-next",
|
|
20178
|
+
overlay: "overlay-vercel",
|
|
20179
|
+
deployConfig: "vercel-vercel",
|
|
20180
|
+
functionsTemplate: "functions-vercel"
|
|
20181
|
+
},
|
|
20182
|
+
{
|
|
20183
|
+
builder: "expo",
|
|
20184
|
+
backend: "none",
|
|
20185
|
+
baseTemplate: "app-expo",
|
|
20186
|
+
overlay: null,
|
|
20187
|
+
deployConfig: null,
|
|
20188
|
+
functionsTemplate: null
|
|
20189
|
+
},
|
|
20190
|
+
{
|
|
20191
|
+
builder: "expo",
|
|
20192
|
+
backend: "firebase",
|
|
20193
|
+
baseTemplate: "app-expo",
|
|
20194
|
+
overlay: "overlay-firebase",
|
|
20195
|
+
deployConfig: null,
|
|
20196
|
+
functionsTemplate: "functions-firebase"
|
|
20197
|
+
},
|
|
20198
|
+
{
|
|
20199
|
+
builder: "expo",
|
|
20200
|
+
backend: "supabase",
|
|
20201
|
+
baseTemplate: "app-expo",
|
|
20202
|
+
overlay: "overlay-supabase",
|
|
20203
|
+
deployConfig: null,
|
|
20204
|
+
functionsTemplate: "functions-supabase"
|
|
20205
|
+
},
|
|
20206
|
+
{
|
|
20207
|
+
builder: "demo",
|
|
20208
|
+
backend: "none",
|
|
20209
|
+
baseTemplate: "app-demo",
|
|
20210
|
+
overlay: null,
|
|
20211
|
+
deployConfig: null,
|
|
20212
|
+
functionsTemplate: null
|
|
20213
|
+
}
|
|
19859
20214
|
];
|
|
19860
20215
|
function comboKey(builder, backend) {
|
|
19861
20216
|
return `${builder}-${backend}`;
|
|
@@ -19868,7 +20223,9 @@ function getScaffoldRow(builder, backend) {
|
|
|
19868
20223
|
const key = comboKey(builder, backend);
|
|
19869
20224
|
const row = ROWS_BY_KEY.get(key);
|
|
19870
20225
|
if (!row) {
|
|
19871
|
-
throw new Error(
|
|
20226
|
+
throw new Error(
|
|
20227
|
+
`Unsupported scaffold combo: ${key}. Supported: ${[...ROWS_BY_KEY.keys()].join(", ")}`
|
|
20228
|
+
);
|
|
19872
20229
|
}
|
|
19873
20230
|
return row;
|
|
19874
20231
|
}
|
|
@@ -20024,13 +20381,16 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20024
20381
|
const variantFile = `src/config/providers.${appTemplate}.ts.example`;
|
|
20025
20382
|
if (overlayFiles.includes(variantFile)) continue;
|
|
20026
20383
|
}
|
|
20027
|
-
const providersVariant = file.match(
|
|
20384
|
+
const providersVariant = file.match(
|
|
20385
|
+
/^src\/config\/providers\.(\w+)\.ts\.example$/
|
|
20386
|
+
);
|
|
20028
20387
|
if (providersVariant) {
|
|
20029
20388
|
if (providersVariant[1] !== appTemplate) continue;
|
|
20030
20389
|
const destPath2 = joinPath(appDir, "src/config/providers.ts");
|
|
20031
20390
|
await ensureDir(getDirname(destPath2));
|
|
20032
|
-
await copy(joinPath(overlayDir, file), destPath2);
|
|
20033
|
-
if (await isTextFile(destPath2))
|
|
20391
|
+
await copy(joinPath(overlayDir, file), destPath2, { overwrite: true });
|
|
20392
|
+
if (await isTextFile(destPath2))
|
|
20393
|
+
await replacePlaceholders(destPath2, replacements);
|
|
20034
20394
|
continue;
|
|
20035
20395
|
}
|
|
20036
20396
|
const sourcePath = joinPath(overlayDir, file);
|
|
@@ -20040,7 +20400,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20040
20400
|
}
|
|
20041
20401
|
const destPath = joinPath(appDir, destFileName);
|
|
20042
20402
|
await ensureDir(getDirname(destPath));
|
|
20043
|
-
await copy(sourcePath, destPath);
|
|
20403
|
+
await copy(sourcePath, destPath, { overwrite: true });
|
|
20044
20404
|
if (await isTextFile(destPath)) {
|
|
20045
20405
|
await replacePlaceholders(destPath, replacements);
|
|
20046
20406
|
}
|
|
@@ -20055,16 +20415,28 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20055
20415
|
}
|
|
20056
20416
|
if (deployConfig === "vercel-supabase") {
|
|
20057
20417
|
const vercelPath = joinPath(appDir, "vercel.json");
|
|
20058
|
-
const headersFragmentPath = joinPath(
|
|
20418
|
+
const headersFragmentPath = joinPath(
|
|
20419
|
+
overlayDir,
|
|
20420
|
+
"vercel.headers.example"
|
|
20421
|
+
);
|
|
20059
20422
|
const fullVercelPath = joinPath(overlayDir, "vercel.json.example");
|
|
20060
20423
|
if (pathExists(vercelPath) && pathExists(headersFragmentPath)) {
|
|
20061
20424
|
const vercelJson = readSync(vercelPath, { format: "json" });
|
|
20062
|
-
const headersFragment = readSync(headersFragmentPath, {
|
|
20063
|
-
|
|
20064
|
-
|
|
20425
|
+
const headersFragment = readSync(headersFragmentPath, {
|
|
20426
|
+
format: "json"
|
|
20427
|
+
});
|
|
20428
|
+
vercelJson.headers = [
|
|
20429
|
+
...vercelJson.headers ?? [],
|
|
20430
|
+
...headersFragment
|
|
20431
|
+
];
|
|
20432
|
+
await write(vercelPath, vercelJson, {
|
|
20433
|
+
format: "json",
|
|
20434
|
+
overwrite: true
|
|
20435
|
+
});
|
|
20065
20436
|
} else if (pathExists(fullVercelPath)) {
|
|
20066
20437
|
await copy(fullVercelPath, vercelPath);
|
|
20067
|
-
if (await isTextFile(vercelPath))
|
|
20438
|
+
if (await isTextFile(vercelPath))
|
|
20439
|
+
await replacePlaceholders(vercelPath, replacements);
|
|
20068
20440
|
}
|
|
20069
20441
|
}
|
|
20070
20442
|
}
|
|
@@ -20083,23 +20455,33 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20083
20455
|
overwrite: true
|
|
20084
20456
|
});
|
|
20085
20457
|
if (row.functionsTemplate) {
|
|
20086
|
-
const functionsRootDir = joinPath(appDir, "functions");
|
|
20087
20458
|
const functionsTemplateName = row.functionsTemplate;
|
|
20088
|
-
const functionsTemplateExists = pathExists(
|
|
20459
|
+
const functionsTemplateExists = pathExists(
|
|
20460
|
+
joinPath(templatesRoot, functionsTemplateName)
|
|
20461
|
+
);
|
|
20089
20462
|
if (!functionsTemplateExists) {
|
|
20090
|
-
log.warn(
|
|
20091
|
-
|
|
20092
|
-
const functionsPackageJson = generatePackageJson(
|
|
20093
|
-
functionsTemplateName,
|
|
20094
|
-
executionMode,
|
|
20095
|
-
{ appName, platform: row.functionsTemplate.replace("functions-", "") }
|
|
20463
|
+
log.warn(
|
|
20464
|
+
`Functions template "${functionsTemplateName}" not found \u2014 skipping functions scaffolding.`
|
|
20096
20465
|
);
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20100
|
-
|
|
20101
|
-
|
|
20102
|
-
|
|
20466
|
+
} else {
|
|
20467
|
+
const isSupabaseFunctions = functionsTemplateName === "functions-supabase";
|
|
20468
|
+
const functionsRootDir = isSupabaseFunctions ? appDir : joinPath(appDir, "functions");
|
|
20469
|
+
if (!isSupabaseFunctions) {
|
|
20470
|
+
const functionsPackageJson = generatePackageJson(
|
|
20471
|
+
functionsTemplateName,
|
|
20472
|
+
executionMode,
|
|
20473
|
+
{
|
|
20474
|
+
appName,
|
|
20475
|
+
platform: row.functionsTemplate.replace("functions-", "")
|
|
20476
|
+
}
|
|
20477
|
+
);
|
|
20478
|
+
const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
|
|
20479
|
+
await ensureDir(functionsRootDir);
|
|
20480
|
+
await write(packageJsonPath2, functionsPackageJson, {
|
|
20481
|
+
format: "json",
|
|
20482
|
+
overwrite: true
|
|
20483
|
+
});
|
|
20484
|
+
}
|
|
20103
20485
|
const templateDir2 = joinPath(templatesRoot, functionsTemplateName);
|
|
20104
20486
|
const templateFiles2 = await glob("**/*", {
|
|
20105
20487
|
cwd: templateDir2,
|
|
@@ -20127,20 +20509,49 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20127
20509
|
}
|
|
20128
20510
|
const deploymentTemplateDir = joinPath(templatesRoot, "root-consumer");
|
|
20129
20511
|
if (deployConfig === "firebase") {
|
|
20130
|
-
const firebaseJsonSource = joinPath(
|
|
20512
|
+
const firebaseJsonSource = joinPath(
|
|
20513
|
+
deploymentTemplateDir,
|
|
20514
|
+
"firebase.json.example"
|
|
20515
|
+
);
|
|
20131
20516
|
if (pathExists(firebaseJsonSource)) {
|
|
20132
20517
|
await copy(firebaseJsonSource, joinPath(appDir, "firebase.json"));
|
|
20133
20518
|
const firebaseJsonDest = joinPath(appDir, "firebase.json");
|
|
20134
|
-
if (await isTextFile(firebaseJsonDest))
|
|
20519
|
+
if (await isTextFile(firebaseJsonDest))
|
|
20520
|
+
await replacePlaceholders(firebaseJsonDest, replacements);
|
|
20521
|
+
if (appTemplate === "nextjs") {
|
|
20522
|
+
const firebaseJson = readSync(firebaseJsonDest, {
|
|
20523
|
+
format: "json"
|
|
20524
|
+
});
|
|
20525
|
+
if (firebaseJson.hosting?.rewrites) {
|
|
20526
|
+
firebaseJson.hosting.rewrites = firebaseJson.hosting.rewrites.filter(
|
|
20527
|
+
(r2) => r2.destination !== "/index.html"
|
|
20528
|
+
);
|
|
20529
|
+
}
|
|
20530
|
+
if (firebaseJson.hosting) {
|
|
20531
|
+
firebaseJson.hosting.public = "out";
|
|
20532
|
+
}
|
|
20533
|
+
await write(firebaseJsonDest, firebaseJson, {
|
|
20534
|
+
format: "json",
|
|
20535
|
+
overwrite: true
|
|
20536
|
+
});
|
|
20537
|
+
}
|
|
20135
20538
|
}
|
|
20136
|
-
const firebasercSource = joinPath(
|
|
20539
|
+
const firebasercSource = joinPath(
|
|
20540
|
+
deploymentTemplateDir,
|
|
20541
|
+
".firebaserc.example"
|
|
20542
|
+
);
|
|
20137
20543
|
if (pathExists(firebasercSource)) {
|
|
20138
20544
|
await copy(firebasercSource, joinPath(appDir, ".firebaserc"));
|
|
20139
20545
|
const firebasercDest = joinPath(appDir, ".firebaserc");
|
|
20140
|
-
if (await isTextFile(firebasercDest))
|
|
20546
|
+
if (await isTextFile(firebasercDest))
|
|
20547
|
+
await replacePlaceholders(firebasercDest, replacements);
|
|
20141
20548
|
}
|
|
20142
20549
|
if (row.functionsTemplate === "functions-firebase") {
|
|
20143
|
-
for (const example of [
|
|
20550
|
+
for (const example of [
|
|
20551
|
+
"firestore.rules.example",
|
|
20552
|
+
"firestore.indexes.json.example",
|
|
20553
|
+
"storage.rules.example"
|
|
20554
|
+
]) {
|
|
20144
20555
|
const src = joinPath(deploymentTemplateDir, example);
|
|
20145
20556
|
if (pathExists(src)) {
|
|
20146
20557
|
await copy(src, joinPath(appDir, example.replace(".example", "")));
|
|
@@ -20148,12 +20559,76 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
20148
20559
|
}
|
|
20149
20560
|
}
|
|
20150
20561
|
}
|
|
20562
|
+
if (!deployConfig && backend === "firebase" && row.functionsTemplate) {
|
|
20563
|
+
const firebaseJsonPath = joinPath(appDir, "firebase.json");
|
|
20564
|
+
if (!pathExists(firebaseJsonPath)) {
|
|
20565
|
+
const expoFirebaseJson = {
|
|
20566
|
+
functions: [
|
|
20567
|
+
{
|
|
20568
|
+
source: "functions",
|
|
20569
|
+
codebase: "default",
|
|
20570
|
+
ignore: [
|
|
20571
|
+
"node_modules",
|
|
20572
|
+
".git",
|
|
20573
|
+
"firebase-debug.log",
|
|
20574
|
+
"firebase-debug.*.log",
|
|
20575
|
+
"**/.*",
|
|
20576
|
+
"**/*.test.ts",
|
|
20577
|
+
"**/__tests__/**"
|
|
20578
|
+
],
|
|
20579
|
+
runtime: "nodejs22"
|
|
20580
|
+
}
|
|
20581
|
+
],
|
|
20582
|
+
firestore: {
|
|
20583
|
+
rules: "firestore.rules",
|
|
20584
|
+
indexes: "firestore.indexes.json"
|
|
20585
|
+
},
|
|
20586
|
+
storage: { rules: "storage.rules" },
|
|
20587
|
+
emulators: {
|
|
20588
|
+
auth: { port: 9099 },
|
|
20589
|
+
functions: { port: 5001 },
|
|
20590
|
+
firestore: { port: 8080 },
|
|
20591
|
+
storage: { port: 9199 },
|
|
20592
|
+
ui: { enabled: true, port: 4e3 }
|
|
20593
|
+
}
|
|
20594
|
+
};
|
|
20595
|
+
await write(firebaseJsonPath, expoFirebaseJson, {
|
|
20596
|
+
format: "json",
|
|
20597
|
+
overwrite: true
|
|
20598
|
+
});
|
|
20599
|
+
}
|
|
20600
|
+
const firebasercSource = joinPath(
|
|
20601
|
+
deploymentTemplateDir,
|
|
20602
|
+
".firebaserc.example"
|
|
20603
|
+
);
|
|
20604
|
+
const firebasercDest = joinPath(appDir, ".firebaserc");
|
|
20605
|
+
if (pathExists(firebasercSource) && !pathExists(firebasercDest)) {
|
|
20606
|
+
await copy(firebasercSource, firebasercDest);
|
|
20607
|
+
if (await isTextFile(firebasercDest))
|
|
20608
|
+
await replacePlaceholders(firebasercDest, replacements);
|
|
20609
|
+
}
|
|
20610
|
+
for (const example of [
|
|
20611
|
+
"firestore.rules.example",
|
|
20612
|
+
"firestore.indexes.json.example",
|
|
20613
|
+
"storage.rules.example"
|
|
20614
|
+
]) {
|
|
20615
|
+
const src = joinPath(deploymentTemplateDir, example);
|
|
20616
|
+
const dest = joinPath(appDir, example.replace(".example", ""));
|
|
20617
|
+
if (pathExists(src) && !pathExists(dest)) {
|
|
20618
|
+
await copy(src, dest);
|
|
20619
|
+
}
|
|
20620
|
+
}
|
|
20621
|
+
}
|
|
20151
20622
|
if (deployConfig === "vercel-vercel") {
|
|
20152
|
-
const vercelJsonSource = joinPath(
|
|
20623
|
+
const vercelJsonSource = joinPath(
|
|
20624
|
+
deploymentTemplateDir,
|
|
20625
|
+
"vercel.json.example"
|
|
20626
|
+
);
|
|
20153
20627
|
if (pathExists(vercelJsonSource)) {
|
|
20154
20628
|
await copy(vercelJsonSource, joinPath(appDir, "vercel.json"));
|
|
20155
20629
|
const vercelJsonDest = joinPath(appDir, "vercel.json");
|
|
20156
|
-
if (await isTextFile(vercelJsonDest))
|
|
20630
|
+
if (await isTextFile(vercelJsonDest))
|
|
20631
|
+
await replacePlaceholders(vercelJsonDest, replacements);
|
|
20157
20632
|
}
|
|
20158
20633
|
}
|
|
20159
20634
|
const backendInfo = row.functionsTemplate ? ` with ${row.functionsTemplate.replace("functions-", "")} functions` : "";
|
|
@@ -20228,23 +20703,25 @@ init_cli_input();
|
|
|
20228
20703
|
init_cli_output();
|
|
20229
20704
|
init_pathResolver();
|
|
20230
20705
|
var SHOW_WIP2 = process.env.SHOW_WIP === "true" || process.argv.includes("--wip");
|
|
20231
|
-
|
|
20232
|
-
|
|
20233
|
-
|
|
20234
|
-
|
|
20235
|
-
|
|
20236
|
-
}
|
|
20237
|
-
|
|
20238
|
-
|
|
20239
|
-
|
|
20240
|
-
|
|
20241
|
-
|
|
20242
|
-
|
|
20243
|
-
|
|
20244
|
-
|
|
20245
|
-
]
|
|
20246
|
-
|
|
20247
|
-
|
|
20706
|
+
async function collectAppConfig(appName) {
|
|
20707
|
+
const answers = await runQuestionnaire(APP_QUESTIONNAIRE, {}, SHOW_WIP2, {
|
|
20708
|
+
selection: askForSelection,
|
|
20709
|
+
confirmation: askForConfirmation,
|
|
20710
|
+
input: askForInput
|
|
20711
|
+
});
|
|
20712
|
+
const framework = answers.framework || "vite";
|
|
20713
|
+
const needsBackend = answers.needsBackend || false;
|
|
20714
|
+
const defaultPlatform = framework === "nextjs" ? "vercel" : "firebase";
|
|
20715
|
+
return {
|
|
20716
|
+
template: framework,
|
|
20717
|
+
needsBackend,
|
|
20718
|
+
backendPlatform: needsBackend ? answers.backendPlatform || defaultPlatform : void 0,
|
|
20719
|
+
needsCRUD: false,
|
|
20720
|
+
selectedEntities: [],
|
|
20721
|
+
userAuth: "none",
|
|
20722
|
+
billing: false,
|
|
20723
|
+
features: []
|
|
20724
|
+
};
|
|
20248
20725
|
}
|
|
20249
20726
|
function calculateRelativePath(from, to) {
|
|
20250
20727
|
try {
|
|
@@ -20286,8 +20763,8 @@ async function main9(options) {
|
|
|
20286
20763
|
try {
|
|
20287
20764
|
Ie("\u{1F680} DoNotDev Project Creator");
|
|
20288
20765
|
try {
|
|
20289
|
-
const { execSync:
|
|
20290
|
-
|
|
20766
|
+
const { execSync: execSync11 } = await import("node:child_process");
|
|
20767
|
+
execSync11("bun --version", { stdio: "ignore" });
|
|
20291
20768
|
} catch {
|
|
20292
20769
|
log.error("bun is required but not installed.");
|
|
20293
20770
|
Me(
|
|
@@ -20357,71 +20834,22 @@ async function main9(options) {
|
|
|
20357
20834
|
let appNames = [];
|
|
20358
20835
|
const appConfigs = {};
|
|
20359
20836
|
let anyAppNeedsBackend = false;
|
|
20360
|
-
|
|
20361
|
-
|
|
20362
|
-
""
|
|
20363
|
-
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
if (isReservedAppName(trimmedName)) {
|
|
20367
|
-
log.warn(`'${trimmedName}' is reserved for framework demos.`);
|
|
20368
|
-
} else if (!isValidFileName(trimmedName)) {
|
|
20369
|
-
log.warn(
|
|
20370
|
-
`Invalid app name. Use only letters, numbers, dashes (-), and underscores (_).`
|
|
20371
|
-
);
|
|
20372
|
-
} else {
|
|
20373
|
-
appNames.push(trimmedName);
|
|
20374
|
-
const framework = await askForSelection(
|
|
20375
|
-
`Builder for "${trimmedName}"?`,
|
|
20376
|
-
[
|
|
20377
|
-
{
|
|
20378
|
-
title: "Vite \u2014 SPA/SaaS (client-side rendering, fast dev)",
|
|
20379
|
-
value: "vite"
|
|
20380
|
-
},
|
|
20381
|
-
{
|
|
20382
|
-
title: "Next.js \u2014 Static content/SEO (SSR, SSG) \u2014 DoNotDev support: BETA",
|
|
20383
|
-
value: "nextjs"
|
|
20384
|
-
},
|
|
20385
|
-
{
|
|
20386
|
-
title: "Expo \u2014 Mobile app (iOS + Android, single codebase)",
|
|
20387
|
-
value: "expo"
|
|
20388
|
-
}
|
|
20389
|
-
],
|
|
20390
|
-
0
|
|
20391
|
-
);
|
|
20392
|
-
const backendValue = await askForSelection(
|
|
20393
|
-
`Backend for "${trimmedName}"?`,
|
|
20394
|
-
[...BACKEND_CHOICES],
|
|
20395
|
-
getDefaultBackendIndex(framework)
|
|
20396
|
-
);
|
|
20397
|
-
const needsBackend = backendValue !== "none";
|
|
20398
|
-
if (needsBackend) anyAppNeedsBackend = true;
|
|
20399
|
-
appConfigs[trimmedName] = {
|
|
20400
|
-
template: framework,
|
|
20401
|
-
needsBackend,
|
|
20402
|
-
backendPlatform: needsBackend ? backendValue : void 0,
|
|
20403
|
-
needsCRUD: false,
|
|
20404
|
-
selectedEntities: [],
|
|
20405
|
-
userAuth: "none",
|
|
20406
|
-
billing: false,
|
|
20407
|
-
features: []
|
|
20408
|
-
};
|
|
20409
|
-
}
|
|
20410
|
-
}
|
|
20411
|
-
while (appNames.length > 0) {
|
|
20412
|
-
const appName = await askForInput("App name (press Enter to finish)", "");
|
|
20413
|
-
if (!appName || appName.trim() === "") {
|
|
20837
|
+
let isFirstApp = true;
|
|
20838
|
+
while (true) {
|
|
20839
|
+
const prompt = isFirstApp ? "What's your first app name? (press Enter to skip)" : "App name (press Enter to finish)";
|
|
20840
|
+
const appNameInput = await askForInput(prompt, "");
|
|
20841
|
+
if (!appNameInput || appNameInput.trim() === "") {
|
|
20842
|
+
if (isFirstApp) break;
|
|
20414
20843
|
break;
|
|
20415
20844
|
}
|
|
20416
|
-
const trimmedName =
|
|
20845
|
+
const trimmedName = appNameInput.trim();
|
|
20846
|
+
isFirstApp = false;
|
|
20417
20847
|
if (appNames.includes(trimmedName)) {
|
|
20418
20848
|
log.warn(`'${trimmedName}' already exists. Choose a different name.`);
|
|
20419
20849
|
continue;
|
|
20420
20850
|
}
|
|
20421
20851
|
if (isReservedAppName(trimmedName)) {
|
|
20422
|
-
log.warn(
|
|
20423
|
-
`'${trimmedName}' is reserved for framework demos. Choose a different name.`
|
|
20424
|
-
);
|
|
20852
|
+
log.warn(`'${trimmedName}' is reserved for framework demos.`);
|
|
20425
20853
|
continue;
|
|
20426
20854
|
}
|
|
20427
20855
|
if (!isValidFileName(trimmedName)) {
|
|
@@ -20431,37 +20859,10 @@ async function main9(options) {
|
|
|
20431
20859
|
continue;
|
|
20432
20860
|
}
|
|
20433
20861
|
appNames.push(trimmedName);
|
|
20434
|
-
|
|
20435
|
-
|
|
20436
|
-
|
|
20437
|
-
|
|
20438
|
-
title: "Vite \u2014 SPA/SaaS (client-side rendering, fast dev)",
|
|
20439
|
-
value: "vite"
|
|
20440
|
-
},
|
|
20441
|
-
{
|
|
20442
|
-
title: "Next.js \u2014 Static content/SEO (SSR, SSG) \u2014 DoNotDev support: BETA",
|
|
20443
|
-
value: "nextjs"
|
|
20444
|
-
}
|
|
20445
|
-
],
|
|
20446
|
-
0
|
|
20447
|
-
);
|
|
20448
|
-
const backendValue = await askForSelection(
|
|
20449
|
-
`Backend for "${trimmedName}"?`,
|
|
20450
|
-
[...BACKEND_CHOICES],
|
|
20451
|
-
getDefaultBackendIndex(framework)
|
|
20452
|
-
);
|
|
20453
|
-
const needsBackend = backendValue !== "none";
|
|
20454
|
-
if (needsBackend) anyAppNeedsBackend = true;
|
|
20455
|
-
appConfigs[trimmedName] = {
|
|
20456
|
-
template: framework,
|
|
20457
|
-
needsBackend,
|
|
20458
|
-
backendPlatform: needsBackend ? backendValue : void 0,
|
|
20459
|
-
needsCRUD: false,
|
|
20460
|
-
selectedEntities: [],
|
|
20461
|
-
userAuth: "none",
|
|
20462
|
-
billing: false,
|
|
20463
|
-
features: []
|
|
20464
|
-
};
|
|
20862
|
+
Me(`Configuring "${trimmedName}"...`, "\u2699\uFE0F");
|
|
20863
|
+
const config = await collectAppConfig(trimmedName);
|
|
20864
|
+
appConfigs[trimmedName] = config;
|
|
20865
|
+
if (config.needsBackend) anyAppNeedsBackend = true;
|
|
20465
20866
|
}
|
|
20466
20867
|
let installDemoApp = await askForConfirmation(
|
|
20467
20868
|
"Would you like to install the demo app? (component showcase)",
|
|
@@ -20793,7 +21194,7 @@ init_utils();
|
|
|
20793
21194
|
init_cli_output();
|
|
20794
21195
|
init_errors();
|
|
20795
21196
|
init_pathResolver();
|
|
20796
|
-
import { spawnSync as
|
|
21197
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
20797
21198
|
import { EOL as EOL2 } from "node:os";
|
|
20798
21199
|
async function main10(options = {}) {
|
|
20799
21200
|
const dryRun = options.dryRun ?? false;
|
|
@@ -21270,7 +21671,7 @@ async function runPrettier(rootDir, dryRun, verbose) {
|
|
|
21270
21671
|
log.info("DRY RUN: Would run Prettier");
|
|
21271
21672
|
return stats;
|
|
21272
21673
|
}
|
|
21273
|
-
const result =
|
|
21674
|
+
const result = spawnSync10("bunx", prettierArgs, {
|
|
21274
21675
|
cwd: rootDir,
|
|
21275
21676
|
stdio: "pipe",
|
|
21276
21677
|
shell: true,
|