@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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/bin/commands/doctor.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,IAAI,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/bin/commands/emu.js
CHANGED
|
@@ -7844,50 +7844,7 @@ var init_utils = __esm({
|
|
|
7844
7844
|
}
|
|
7845
7845
|
});
|
|
7846
7846
|
|
|
7847
|
-
// packages/tooling/src/utils/cli-input.ts
|
|
7848
|
-
async function askForMultiSelection(message, choices, defaultIndices = []) {
|
|
7849
|
-
const options = choices.map((choice) => ({
|
|
7850
|
-
value: choice.value,
|
|
7851
|
-
label: choice.title,
|
|
7852
|
-
hint: choice.hint
|
|
7853
|
-
}));
|
|
7854
|
-
const initialValues = defaultIndices.map((i) => choices[i]?.value).filter(Boolean);
|
|
7855
|
-
const result = await fe({
|
|
7856
|
-
message,
|
|
7857
|
-
options,
|
|
7858
|
-
initialValues: initialValues.length > 0 ? initialValues : void 0
|
|
7859
|
-
});
|
|
7860
|
-
if (pD(result)) {
|
|
7861
|
-
xe("Operation cancelled.");
|
|
7862
|
-
process.exit(0);
|
|
7863
|
-
}
|
|
7864
|
-
return result;
|
|
7865
|
-
}
|
|
7866
|
-
var init_cli_input = __esm({
|
|
7867
|
-
"packages/tooling/src/utils/cli-input.ts"() {
|
|
7868
|
-
"use strict";
|
|
7869
|
-
init_utils();
|
|
7870
|
-
init_dist2();
|
|
7871
|
-
}
|
|
7872
|
-
});
|
|
7873
|
-
|
|
7874
|
-
// packages/cli/src/bin/commands/emu.ts
|
|
7875
|
-
init_utils();
|
|
7876
|
-
|
|
7877
|
-
// packages/tooling/src/index.ts
|
|
7878
|
-
init_utils();
|
|
7879
|
-
|
|
7880
|
-
// packages/tooling/src/cli/index.ts
|
|
7881
|
-
init_utils();
|
|
7882
|
-
|
|
7883
|
-
// packages/tooling/src/utils/app-selector.ts
|
|
7884
|
-
init_utils();
|
|
7885
|
-
init_dist2();
|
|
7886
|
-
|
|
7887
7847
|
// packages/tooling/src/utils/app-detection.ts
|
|
7888
|
-
init_utils();
|
|
7889
|
-
init_pathResolver();
|
|
7890
|
-
init_typed_file_operations();
|
|
7891
7848
|
function detectApps(projectRoot) {
|
|
7892
7849
|
const apps = [];
|
|
7893
7850
|
const appsDir = joinPath(projectRoot, "apps");
|
|
@@ -7946,14 +7903,23 @@ function analyzeApp(appPath, appName) {
|
|
|
7946
7903
|
const functionsPath = joinPath(appPath, "functions");
|
|
7947
7904
|
const functionsStat = statSync2(functionsPath);
|
|
7948
7905
|
const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
|
|
7949
|
-
let
|
|
7950
|
-
|
|
7951
|
-
|
|
7906
|
+
let platform4;
|
|
7907
|
+
const firebaseJsonInFunctions = hasFunctions && pathExists(joinPath(functionsPath, "firebase.json"));
|
|
7908
|
+
const firebaseJsonInApp = pathExists(joinPath(appPath, "firebase.json"));
|
|
7909
|
+
if (firebaseJsonInFunctions || firebaseJsonInApp) {
|
|
7910
|
+
platform4 = "firebase";
|
|
7911
|
+
}
|
|
7912
|
+
if (!platform4) {
|
|
7913
|
+
const supabaseConfigPath = joinPath(appPath, "supabase", "config.toml");
|
|
7914
|
+
const hasSupabaseDep = !!(packageJson.dependencies?.["@donotdev/supabase"] || packageJson.dependencies?.["@supabase/supabase-js"]);
|
|
7915
|
+
if (pathExists(supabaseConfigPath) || hasSupabaseDep) {
|
|
7916
|
+
platform4 = "supabase";
|
|
7917
|
+
}
|
|
7918
|
+
}
|
|
7919
|
+
if (!platform4) {
|
|
7952
7920
|
const vercelJsonPath = joinPath(appPath, "vercel.json");
|
|
7953
|
-
if (pathExists(
|
|
7954
|
-
|
|
7955
|
-
} else if (pathExists(vercelJsonPath)) {
|
|
7956
|
-
platform2 = "vercel";
|
|
7921
|
+
if (pathExists(vercelJsonPath)) {
|
|
7922
|
+
platform4 = "vercel";
|
|
7957
7923
|
}
|
|
7958
7924
|
}
|
|
7959
7925
|
return {
|
|
@@ -7964,12 +7930,19 @@ function analyzeApp(appPath, appName) {
|
|
|
7964
7930
|
framework,
|
|
7965
7931
|
hasFunctions,
|
|
7966
7932
|
functionsPath: hasFunctions ? functionsPath : void 0,
|
|
7967
|
-
platform:
|
|
7933
|
+
platform: platform4
|
|
7968
7934
|
};
|
|
7969
7935
|
}
|
|
7936
|
+
var init_app_detection = __esm({
|
|
7937
|
+
"packages/tooling/src/utils/app-detection.ts"() {
|
|
7938
|
+
"use strict";
|
|
7939
|
+
init_utils();
|
|
7940
|
+
init_pathResolver();
|
|
7941
|
+
init_typed_file_operations();
|
|
7942
|
+
}
|
|
7943
|
+
});
|
|
7970
7944
|
|
|
7971
7945
|
// packages/tooling/src/utils/app-selector.ts
|
|
7972
|
-
init_cli_output();
|
|
7973
7946
|
async function selectApp(projectRoot, appName) {
|
|
7974
7947
|
const apps = detectApps(projectRoot);
|
|
7975
7948
|
if (apps.length === 0) {
|
|
@@ -8003,6 +7976,51 @@ async function selectApp(projectRoot, appName) {
|
|
|
8003
7976
|
}
|
|
8004
7977
|
return apps.find((a) => a.name === selected) || null;
|
|
8005
7978
|
}
|
|
7979
|
+
var init_app_selector = __esm({
|
|
7980
|
+
"packages/tooling/src/utils/app-selector.ts"() {
|
|
7981
|
+
"use strict";
|
|
7982
|
+
init_utils();
|
|
7983
|
+
init_dist2();
|
|
7984
|
+
init_app_detection();
|
|
7985
|
+
init_cli_output();
|
|
7986
|
+
}
|
|
7987
|
+
});
|
|
7988
|
+
|
|
7989
|
+
// packages/tooling/src/utils/cli-input.ts
|
|
7990
|
+
async function askForMultiSelection(message, choices, defaultIndices = []) {
|
|
7991
|
+
const options = choices.map((choice) => ({
|
|
7992
|
+
value: choice.value,
|
|
7993
|
+
label: choice.title,
|
|
7994
|
+
hint: choice.hint
|
|
7995
|
+
}));
|
|
7996
|
+
const initialValues = defaultIndices.map((i) => choices[i]?.value).filter(Boolean);
|
|
7997
|
+
const result = await fe({
|
|
7998
|
+
message,
|
|
7999
|
+
options,
|
|
8000
|
+
initialValues: initialValues.length > 0 ? initialValues : void 0
|
|
8001
|
+
});
|
|
8002
|
+
if (pD(result)) {
|
|
8003
|
+
xe("Operation cancelled.");
|
|
8004
|
+
process.exit(0);
|
|
8005
|
+
}
|
|
8006
|
+
return result;
|
|
8007
|
+
}
|
|
8008
|
+
var init_cli_input = __esm({
|
|
8009
|
+
"packages/tooling/src/utils/cli-input.ts"() {
|
|
8010
|
+
"use strict";
|
|
8011
|
+
init_utils();
|
|
8012
|
+
init_dist2();
|
|
8013
|
+
}
|
|
8014
|
+
});
|
|
8015
|
+
|
|
8016
|
+
// packages/cli/src/bin/commands/emu.ts
|
|
8017
|
+
init_utils();
|
|
8018
|
+
|
|
8019
|
+
// packages/tooling/src/index.ts
|
|
8020
|
+
init_utils();
|
|
8021
|
+
|
|
8022
|
+
// packages/tooling/src/cli/index.ts
|
|
8023
|
+
init_utils();
|
|
8006
8024
|
|
|
8007
8025
|
// packages/tooling/src/utils/spawn-utils.ts
|
|
8008
8026
|
init_utils();
|
|
@@ -8048,18 +8066,23 @@ function createEmulatorEnv(appPath, framework = "vite", options) {
|
|
|
8048
8066
|
|
|
8049
8067
|
// packages/tooling/src/apps/emu.ts
|
|
8050
8068
|
init_utils();
|
|
8069
|
+
init_app_selector();
|
|
8070
|
+
init_cli_output();
|
|
8071
|
+
init_errors();
|
|
8072
|
+
init_pathResolver();
|
|
8073
|
+
|
|
8074
|
+
// packages/tooling/src/apps/emu-firebase.ts
|
|
8075
|
+
init_utils();
|
|
8076
|
+
init_cli_input();
|
|
8077
|
+
init_cli_output();
|
|
8078
|
+
init_pathResolver();
|
|
8079
|
+
init_typed_file_operations();
|
|
8051
8080
|
import {
|
|
8052
8081
|
spawn,
|
|
8053
8082
|
spawnSync as spawnSync2,
|
|
8054
8083
|
execSync as execSync2
|
|
8055
8084
|
} from "node:child_process";
|
|
8056
8085
|
import { platform } from "node:os";
|
|
8057
|
-
init_cli_input();
|
|
8058
|
-
init_cli_output();
|
|
8059
|
-
init_errors();
|
|
8060
|
-
init_pathResolver();
|
|
8061
|
-
init_pathResolver();
|
|
8062
|
-
init_typed_file_operations();
|
|
8063
8086
|
function discoverFirebaseProjectId(appPath) {
|
|
8064
8087
|
const firebasercPath = joinPath(appPath, ".firebaserc");
|
|
8065
8088
|
if (pathExists(firebasercPath)) {
|
|
@@ -8091,7 +8114,7 @@ function killPorts(ports) {
|
|
|
8091
8114
|
pids.add(match[1]);
|
|
8092
8115
|
}
|
|
8093
8116
|
}
|
|
8094
|
-
for (const pid of pids) {
|
|
8117
|
+
for (const pid of Array.from(pids)) {
|
|
8095
8118
|
try {
|
|
8096
8119
|
execSync2(`taskkill /F /PID ${pid}`, { stdio: "ignore" });
|
|
8097
8120
|
log.debug(`Killed process ${pid} on port ${port}`);
|
|
@@ -8153,9 +8176,9 @@ function loadEnvFile(filePath) {
|
|
|
8153
8176
|
} catch {
|
|
8154
8177
|
}
|
|
8155
8178
|
}
|
|
8156
|
-
async function
|
|
8157
|
-
const
|
|
8158
|
-
|
|
8179
|
+
async function startFirebase(app, projectRoot, options = {}) {
|
|
8180
|
+
const debug = options.debug ?? false;
|
|
8181
|
+
let selectedServices = options.selectedServices ?? [];
|
|
8159
8182
|
const serviceChoices = [
|
|
8160
8183
|
{
|
|
8161
8184
|
title: "Auth",
|
|
@@ -8178,47 +8201,6 @@ async function main(options) {
|
|
|
8178
8201
|
hint: "Stripe webhook forwarding (for payment testing)"
|
|
8179
8202
|
}
|
|
8180
8203
|
];
|
|
8181
|
-
let selectedServices = [];
|
|
8182
|
-
const appName = args.find(
|
|
8183
|
-
(arg) => arg !== "emu" && arg !== "--debug" && !arg.startsWith("--")
|
|
8184
|
-
);
|
|
8185
|
-
if (options?.services) {
|
|
8186
|
-
selectedServices = options.services.split(",").map((s) => s.trim());
|
|
8187
|
-
} else {
|
|
8188
|
-
const servicesArg = args.find((arg) => arg.startsWith("--services="));
|
|
8189
|
-
if (servicesArg) {
|
|
8190
|
-
const servicesList = servicesArg.split("=")[1];
|
|
8191
|
-
if (servicesList) {
|
|
8192
|
-
selectedServices = servicesList.split(",").map((s) => s.trim());
|
|
8193
|
-
}
|
|
8194
|
-
} else {
|
|
8195
|
-
if (options?.auth || args.includes("--auth"))
|
|
8196
|
-
selectedServices.push("auth");
|
|
8197
|
-
if (args.includes("--functions")) selectedServices.push("functions");
|
|
8198
|
-
if (options?.firestore || args.includes("--firestore"))
|
|
8199
|
-
selectedServices.push("firestore");
|
|
8200
|
-
if (options?.stripe || args.includes("--stripe"))
|
|
8201
|
-
selectedServices.push("stripe");
|
|
8202
|
-
}
|
|
8203
|
-
}
|
|
8204
|
-
const validServices = serviceChoices.map((c) => c.value);
|
|
8205
|
-
selectedServices = selectedServices.filter((s) => validServices.includes(s));
|
|
8206
|
-
const projectRoot = getRepoRoot();
|
|
8207
|
-
if (!projectRoot) {
|
|
8208
|
-
throw new DoNotDevError(
|
|
8209
|
-
"Could not determine repository root",
|
|
8210
|
-
"path-resolution-error"
|
|
8211
|
-
);
|
|
8212
|
-
}
|
|
8213
|
-
const app = await selectApp(projectRoot, appName);
|
|
8214
|
-
if (!app) {
|
|
8215
|
-
return 1;
|
|
8216
|
-
}
|
|
8217
|
-
if (!app.hasFunctions || app.platform !== "firebase") {
|
|
8218
|
-
log.error(`App "${app.name}" does not have Firebase functions.`);
|
|
8219
|
-
log.error('Use "dndev dev" for apps without functions.\n');
|
|
8220
|
-
return 1;
|
|
8221
|
-
}
|
|
8222
8204
|
log.info(`Starting Firebase emulators + dev server for ${app.name}...
|
|
8223
8205
|
`);
|
|
8224
8206
|
if (selectedServices.length === 0) {
|
|
@@ -8350,7 +8332,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
8350
8332
|
const stripeWebhookUrl = `http://localhost:5001/${projectId}/${region}/stripeWebhook`;
|
|
8351
8333
|
concurrentlyArgs.push(`stripe listen --forward-to ${stripeWebhookUrl}`);
|
|
8352
8334
|
log.info("");
|
|
8353
|
-
log.info("
|
|
8335
|
+
log.info("Stripe webhook forwarding will start automatically");
|
|
8354
8336
|
log.info(` Webhook URL: ${stripeWebhookUrl}`);
|
|
8355
8337
|
log.info(" To trigger test events, run in another terminal:");
|
|
8356
8338
|
log.info(" stripe trigger checkout.session.completed");
|
|
@@ -8372,9 +8354,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
8372
8354
|
);
|
|
8373
8355
|
const SIGNAL_EXIT_CODES = {
|
|
8374
8356
|
SIGINT: 130,
|
|
8375
|
-
// 128 + 2
|
|
8376
8357
|
SIGTERM: 143
|
|
8377
|
-
// 128 + 15
|
|
8378
8358
|
};
|
|
8379
8359
|
const cleanup = (signal) => {
|
|
8380
8360
|
if (!childProcess.pid) return;
|
|
@@ -8424,11 +8404,219 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
8424
8404
|
});
|
|
8425
8405
|
childProcess.on("error", (error2) => {
|
|
8426
8406
|
handlers.forEach((h2) => h2());
|
|
8427
|
-
log.error(`Failed to start emulators: ${error2.message}`);
|
|
8407
|
+
log.error(`Failed to start Firebase emulators: ${error2.message}`);
|
|
8428
8408
|
resolve4(1);
|
|
8429
8409
|
});
|
|
8430
8410
|
});
|
|
8431
8411
|
}
|
|
8412
|
+
|
|
8413
|
+
// packages/tooling/src/apps/emu-supabase.ts
|
|
8414
|
+
init_utils();
|
|
8415
|
+
init_cli_output();
|
|
8416
|
+
import { spawn as spawn2, execSync as execSync3 } from "node:child_process";
|
|
8417
|
+
import { platform as platform2 } from "node:os";
|
|
8418
|
+
function isDockerRunning() {
|
|
8419
|
+
try {
|
|
8420
|
+
execSync3("docker info", { stdio: "pipe", timeout: 5e3 });
|
|
8421
|
+
return true;
|
|
8422
|
+
} catch {
|
|
8423
|
+
return false;
|
|
8424
|
+
}
|
|
8425
|
+
}
|
|
8426
|
+
async function startSupabase(app, _projectRoot) {
|
|
8427
|
+
log.info(`Starting Supabase local stack + dev server for ${app.name}...
|
|
8428
|
+
`);
|
|
8429
|
+
if (!isDockerRunning()) {
|
|
8430
|
+
log.error("Docker is not running. Supabase local dev requires Docker.");
|
|
8431
|
+
log.error("Start Docker Desktop and try again.\n");
|
|
8432
|
+
return 1;
|
|
8433
|
+
}
|
|
8434
|
+
try {
|
|
8435
|
+
execSync3("supabase --version", { stdio: "pipe" });
|
|
8436
|
+
} catch {
|
|
8437
|
+
log.error("Supabase CLI not found. Install it:");
|
|
8438
|
+
log.error(" npm install -g supabase\n");
|
|
8439
|
+
return 1;
|
|
8440
|
+
}
|
|
8441
|
+
const isWindows = platform2() === "win32";
|
|
8442
|
+
const concurrentlyArgs = [
|
|
8443
|
+
"--kill-others-on-fail",
|
|
8444
|
+
"--prefix-colors",
|
|
8445
|
+
"cyan,green",
|
|
8446
|
+
"--prefix",
|
|
8447
|
+
"[{name}]",
|
|
8448
|
+
"--names",
|
|
8449
|
+
"supabase,dev",
|
|
8450
|
+
"supabase start",
|
|
8451
|
+
`bunx turbo dev --filter=${app.packageName}`
|
|
8452
|
+
];
|
|
8453
|
+
const childProcess = spawn2(
|
|
8454
|
+
"bunx",
|
|
8455
|
+
["concurrently", ...concurrentlyArgs],
|
|
8456
|
+
{
|
|
8457
|
+
stdio: "inherit",
|
|
8458
|
+
cwd: app.path,
|
|
8459
|
+
shell: isWindows
|
|
8460
|
+
}
|
|
8461
|
+
);
|
|
8462
|
+
const cleanup = () => {
|
|
8463
|
+
if (!childProcess.pid) return;
|
|
8464
|
+
if (isWindows) {
|
|
8465
|
+
try {
|
|
8466
|
+
execSync3(`taskkill /F /T /PID ${childProcess.pid}`, {
|
|
8467
|
+
stdio: "ignore",
|
|
8468
|
+
timeout: 2e3
|
|
8469
|
+
});
|
|
8470
|
+
} catch {
|
|
8471
|
+
}
|
|
8472
|
+
} else {
|
|
8473
|
+
try {
|
|
8474
|
+
process.kill(childProcess.pid, "SIGTERM");
|
|
8475
|
+
} catch {
|
|
8476
|
+
}
|
|
8477
|
+
}
|
|
8478
|
+
};
|
|
8479
|
+
process.on("SIGINT", () => {
|
|
8480
|
+
cleanup();
|
|
8481
|
+
process.exit(130);
|
|
8482
|
+
});
|
|
8483
|
+
process.on("SIGTERM", () => {
|
|
8484
|
+
cleanup();
|
|
8485
|
+
process.exit(143);
|
|
8486
|
+
});
|
|
8487
|
+
return new Promise((resolve4) => {
|
|
8488
|
+
childProcess.on("exit", (code) => resolve4(code ?? 0));
|
|
8489
|
+
childProcess.on("error", (error2) => {
|
|
8490
|
+
log.error(`Failed to start Supabase local dev: ${error2.message}`);
|
|
8491
|
+
resolve4(1);
|
|
8492
|
+
});
|
|
8493
|
+
});
|
|
8494
|
+
}
|
|
8495
|
+
|
|
8496
|
+
// packages/tooling/src/apps/emu-vercel.ts
|
|
8497
|
+
init_utils();
|
|
8498
|
+
init_cli_output();
|
|
8499
|
+
import { spawn as spawn3, execSync as execSync4 } from "node:child_process";
|
|
8500
|
+
import { platform as platform3 } from "node:os";
|
|
8501
|
+
async function startVercel(app, _projectRoot) {
|
|
8502
|
+
log.info(`Starting Vercel dev server for ${app.name}...
|
|
8503
|
+
`);
|
|
8504
|
+
try {
|
|
8505
|
+
execSync4("vercel --version", { stdio: "pipe" });
|
|
8506
|
+
} catch {
|
|
8507
|
+
log.error("Vercel CLI not found. Install it:");
|
|
8508
|
+
log.error(" npm install -g vercel\n");
|
|
8509
|
+
return 1;
|
|
8510
|
+
}
|
|
8511
|
+
const isWindows = platform3() === "win32";
|
|
8512
|
+
const childProcess = spawn3("vercel", ["dev"], {
|
|
8513
|
+
stdio: "inherit",
|
|
8514
|
+
cwd: app.path,
|
|
8515
|
+
shell: isWindows
|
|
8516
|
+
});
|
|
8517
|
+
const cleanup = () => {
|
|
8518
|
+
if (!childProcess.pid) return;
|
|
8519
|
+
if (isWindows) {
|
|
8520
|
+
try {
|
|
8521
|
+
execSync4(`taskkill /F /T /PID ${childProcess.pid}`, {
|
|
8522
|
+
stdio: "ignore",
|
|
8523
|
+
timeout: 2e3
|
|
8524
|
+
});
|
|
8525
|
+
} catch {
|
|
8526
|
+
}
|
|
8527
|
+
} else {
|
|
8528
|
+
try {
|
|
8529
|
+
process.kill(childProcess.pid, "SIGTERM");
|
|
8530
|
+
} catch {
|
|
8531
|
+
}
|
|
8532
|
+
}
|
|
8533
|
+
};
|
|
8534
|
+
process.on("SIGINT", () => {
|
|
8535
|
+
cleanup();
|
|
8536
|
+
process.exit(130);
|
|
8537
|
+
});
|
|
8538
|
+
process.on("SIGTERM", () => {
|
|
8539
|
+
cleanup();
|
|
8540
|
+
process.exit(143);
|
|
8541
|
+
});
|
|
8542
|
+
return new Promise((resolve4) => {
|
|
8543
|
+
childProcess.on("exit", (code) => resolve4(code ?? 0));
|
|
8544
|
+
childProcess.on("error", (error2) => {
|
|
8545
|
+
log.error(`Failed to start Vercel dev: ${error2.message}`);
|
|
8546
|
+
resolve4(1);
|
|
8547
|
+
});
|
|
8548
|
+
});
|
|
8549
|
+
}
|
|
8550
|
+
|
|
8551
|
+
// packages/tooling/src/apps/emu.ts
|
|
8552
|
+
async function main(options) {
|
|
8553
|
+
const args = process.argv.slice(2);
|
|
8554
|
+
const projectRoot = getRepoRoot();
|
|
8555
|
+
if (!projectRoot) {
|
|
8556
|
+
throw new DoNotDevError(
|
|
8557
|
+
"Could not determine repository root",
|
|
8558
|
+
"path-resolution-error"
|
|
8559
|
+
);
|
|
8560
|
+
}
|
|
8561
|
+
const appName = args.find(
|
|
8562
|
+
(arg) => arg !== "emu" && arg !== "--debug" && !arg.startsWith("--")
|
|
8563
|
+
);
|
|
8564
|
+
const app = await selectApp(projectRoot, appName);
|
|
8565
|
+
if (!app) {
|
|
8566
|
+
return 1;
|
|
8567
|
+
}
|
|
8568
|
+
switch (app.platform) {
|
|
8569
|
+
case "firebase": {
|
|
8570
|
+
if (!app.hasFunctions) {
|
|
8571
|
+
log.error(
|
|
8572
|
+
`App "${app.name}" has Firebase config but no functions directory.`
|
|
8573
|
+
);
|
|
8574
|
+
log.error('Use "dndev dev" for apps without backend functions.\n');
|
|
8575
|
+
return 1;
|
|
8576
|
+
}
|
|
8577
|
+
const selectedServices = parseFirebaseServices(args, options);
|
|
8578
|
+
return startFirebase(app, projectRoot, {
|
|
8579
|
+
debug: options?.debug ?? false,
|
|
8580
|
+
selectedServices
|
|
8581
|
+
});
|
|
8582
|
+
}
|
|
8583
|
+
case "supabase":
|
|
8584
|
+
return startSupabase(app, projectRoot);
|
|
8585
|
+
case "vercel":
|
|
8586
|
+
return startVercel(app, projectRoot);
|
|
8587
|
+
default:
|
|
8588
|
+
log.error(`App "${app.name}" does not have a detected backend platform.`);
|
|
8589
|
+
log.error(
|
|
8590
|
+
"Expected: firebase.json (Firebase), supabase/config.toml or @donotdev/supabase (Supabase), or vercel.json (Vercel)."
|
|
8591
|
+
);
|
|
8592
|
+
log.error('Use "dndev dev" for apps without a backend.\n');
|
|
8593
|
+
return 1;
|
|
8594
|
+
}
|
|
8595
|
+
}
|
|
8596
|
+
function parseFirebaseServices(args, options) {
|
|
8597
|
+
const validServices = ["auth", "functions", "firestore", "stripe"];
|
|
8598
|
+
let selectedServices = [];
|
|
8599
|
+
if (options?.services) {
|
|
8600
|
+
selectedServices = options.services.split(",").map((s) => s.trim());
|
|
8601
|
+
} else {
|
|
8602
|
+
const servicesArg = args.find((arg) => arg.startsWith("--services="));
|
|
8603
|
+
if (servicesArg) {
|
|
8604
|
+
const servicesList = servicesArg.split("=")[1];
|
|
8605
|
+
if (servicesList) {
|
|
8606
|
+
selectedServices = servicesList.split(",").map((s) => s.trim());
|
|
8607
|
+
}
|
|
8608
|
+
} else {
|
|
8609
|
+
if (options?.auth || args.includes("--auth"))
|
|
8610
|
+
selectedServices.push("auth");
|
|
8611
|
+
if (args.includes("--functions")) selectedServices.push("functions");
|
|
8612
|
+
if (options?.firestore || args.includes("--firestore"))
|
|
8613
|
+
selectedServices.push("firestore");
|
|
8614
|
+
if (options?.stripe || args.includes("--stripe"))
|
|
8615
|
+
selectedServices.push("stripe");
|
|
8616
|
+
}
|
|
8617
|
+
}
|
|
8618
|
+
return selectedServices.filter((s) => validServices.includes(s));
|
|
8619
|
+
}
|
|
8432
8620
|
export {
|
|
8433
8621
|
main
|
|
8434
8622
|
};
|