@donotdev/cli 0.0.14 → 0.0.16
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 +372 -88
- package/dist/bin/commands/agent-setup.js +7 -1
- package/dist/bin/commands/build.js +141 -44
- package/dist/bin/commands/bump.js +81 -41
- package/dist/bin/commands/cacheout.js +37 -9
- package/dist/bin/commands/create-app.js +276 -121
- package/dist/bin/commands/create-project.js +506 -217
- package/dist/bin/commands/deploy.js +1785 -694
- package/dist/bin/commands/dev.js +177 -43
- 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} +1215 -156
- package/dist/bin/commands/doctor.js.map +1 -0
- package/dist/bin/commands/emu.js +451 -104
- package/dist/bin/commands/format.js +37 -9
- package/dist/bin/commands/make-admin.js +77499 -11
- package/dist/bin/commands/preview.js +181 -43
- 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 +11733 -0
- package/dist/bin/commands/setup.js.map +1 -0
- package/dist/bin/commands/supabase-setup.d.ts +6 -0
- package/dist/bin/commands/supabase-setup.d.ts.map +1 -0
- package/dist/bin/commands/supabase-setup.js +7 -0
- package/dist/bin/commands/supabase-setup.js.map +1 -0
- package/dist/bin/commands/sync-secrets.js +211 -34
- package/dist/bin/commands/type-check.d.ts +14 -0
- package/dist/bin/commands/type-check.d.ts.map +1 -0
- package/dist/bin/commands/type-check.js +2049 -0
- package/dist/bin/commands/type-check.js.map +1 -0
- package/dist/bin/commands/wai.js +3 -1
- package/dist/bin/dndev.js +73 -52
- package/dist/bin/donotdev.js +54 -45
- package/dist/index.js +4212 -3050
- package/package.json +3 -3
- package/templates/app-demo/src/App.tsx.example +1 -0
- package/templates/app-demo/src/pages/FullPage.tsx.example +2 -2
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +2 -2
- package/templates/app-demo/src/themes.css.example +5 -12
- package/templates/app-expo/.env.example +44 -0
- package/templates/app-expo/.expo/README.md.example +5 -0
- package/templates/app-expo/.gitignore.example +36 -0
- package/templates/app-expo/README.md.example +58 -0
- package/templates/app-expo/app/.gitkeep +2 -0
- package/templates/app-expo/app/_layout.tsx.example +41 -0
- package/templates/app-expo/app/form.tsx.example +52 -0
- package/templates/app-expo/app/index.tsx.example +89 -0
- package/templates/app-expo/app/list.tsx.example +32 -0
- package/templates/app-expo/app/profile.tsx.example +76 -0
- package/templates/app-expo/app/signin.tsx.example +53 -0
- package/templates/app-expo/app.json.example +39 -0
- 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/babel.config.js.example +10 -0
- package/templates/app-expo/eas.json.example +20 -0
- package/templates/app-expo/expo-env.d.ts.example +4 -0
- package/templates/app-expo/metro.config.js.example +20 -0
- package/templates/app-expo/service-account-key.json.example +12 -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-expo/tsconfig.json.example +19 -0
- package/templates/app-next/.env.example +4 -33
- package/templates/app-next/src/app/ClientLayout.tsx.example +2 -0
- package/templates/app-next/src/app/layout.tsx.example +7 -6
- package/templates/app-next/src/config/providers.ts.example +7 -0
- package/templates/app-next/src/globals.css.example +2 -11
- package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-next/src/themes.css.example +10 -13
- package/templates/app-vite/.env.example +3 -32
- package/templates/app-vite/index.html.example +2 -24
- package/templates/app-vite/src/App.tsx.example +2 -0
- package/templates/app-vite/src/config/providers.ts.example +7 -0
- package/templates/app-vite/src/globals.css.example +2 -12
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +1 -2
- package/templates/app-vite/src/pages/HomePage.tsx.example +2 -2
- package/templates/app-vite/src/themes.css.example +109 -79
- package/templates/app-vite/vercel.json.example +11 -0
- package/templates/functions-firebase/README.md.example +1 -1
- package/templates/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/.env.example.example +24 -26
- package/templates/functions-firebase/functions-firebase/README.md.example +1 -1
- package/templates/functions-firebase/functions-firebase/build.mjs.example +2 -72
- 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/cancel-subscription/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/change-plan/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/crud/index.ts.example +16 -0
- package/templates/functions-supabase/supabase/functions/delete-account/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/deno.json.example +8 -0
- package/templates/functions-supabase/supabase/functions/get-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-user-auth-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/remove-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/set-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/migrations/20250101000000_idempotency.sql +24 -0
- package/templates/functions-supabase/supabase/migrations/20250101000001_rate_limits.sql +22 -0
- package/templates/functions-supabase/supabase/migrations/20250101000002_cleanup_jobs.sql +28 -0
- package/templates/functions-supabase/supabase/migrations/20250101000003_operation_metrics.sql +28 -0
- package/templates/functions-vercel/functions-vercel/tsconfig.json.example +1 -1
- package/templates/functions-vercel/functions-vercel/vercel.json.example +1 -1
- package/templates/functions-vercel/vercel.json.example +1 -1
- package/templates/github/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/overlay-firebase/env.fragment.example +34 -0
- package/templates/overlay-firebase/env.fragment.expo.example +34 -0
- package/templates/overlay-firebase/env.fragment.nextjs.example +34 -0
- package/templates/overlay-firebase/src/config/providers.expo.ts.example +49 -0
- package/templates/overlay-firebase/src/config/providers.ts.example +23 -0
- package/templates/overlay-supabase/env.fragment.example +12 -0
- package/templates/overlay-supabase/env.fragment.expo.example +12 -0
- package/templates/overlay-supabase/env.fragment.nextjs.example +12 -0
- package/templates/overlay-supabase/src/config/providers.expo.ts.example +35 -0
- package/templates/overlay-supabase/src/config/providers.ts.example +33 -0
- package/templates/overlay-supabase/vercel.headers.example +23 -0
- package/templates/overlay-supabase/vercel.json.example +22 -0
- package/templates/overlay-vercel/env.fragment.example +34 -0
- package/templates/overlay-vercel/env.fragment.nextjs.example +34 -0
- package/templates/overlay-vercel/src/config/providers.ts.example +24 -0
- package/templates/root-consumer/.claude/agents/architect.md.example +2 -310
- package/templates/root-consumer/.claude/agents/builder.md.example +2 -326
- package/templates/root-consumer/.claude/agents/coder.md.example +2 -83
- package/templates/root-consumer/.claude/agents/extractor.md.example +2 -231
- package/templates/root-consumer/.claude/agents/polisher.md.example +2 -132
- package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +2 -81
- package/templates/root-consumer/.claude/commands/grill.md.example +30 -0
- package/templates/root-consumer/.claude/commands/techdebt.md.example +28 -0
- package/templates/root-consumer/.clinerules.example +1 -0
- package/templates/root-consumer/.cursor/rules/no-docs.mdc.example +15 -0
- package/templates/root-consumer/.cursorrules.example +1 -0
- package/templates/root-consumer/.github/copilot-instructions.md.example +1 -0
- package/templates/root-consumer/.windsurfrules.example +1 -0
- package/templates/root-consumer/AI.md.example +44 -123
- package/templates/root-consumer/CLAUDE.md.example +1 -134
- package/templates/root-consumer/CONVENTIONS.md.example +1 -0
- package/templates/root-consumer/GEMINI.md.example +1 -0
- package/templates/root-consumer/firebase.json.example +1 -1
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +22 -2
- package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +0 -18
- package/templates/root-consumer/guides/dndev/COMPONENTS_UI.md.example +1 -1
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +101 -32
- package/templates/root-consumer/guides/dndev/INDEX.md.example +4 -2
- package/templates/root-consumer/guides/dndev/SETUP_APP_CONFIG.md.example +3 -3
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +241 -12
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +13 -7
- package/templates/root-consumer/guides/dndev/SETUP_OAUTH_PROVIDERS.md.example +60 -0
- package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -0
- package/templates/root-consumer/guides/dndev/SETUP_STRIPE.md.example +62 -0
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -0
- package/templates/root-consumer/guides/dndev/SETUP_THEMES.md.example +6 -2
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +176 -0
- package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +5 -9
- package/templates/root-consumer/guides/dndev/essences_reference.css.example +174 -0
- package/templates/root-consumer/guides/wai-way/WAI_WAY_CLI.md.example +7 -8
- package/templates/root-consumer/guides/wai-way/agents/builder.md.example +10 -0
- package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +25 -5
- package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +13 -2
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +2 -2
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +55 -15
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +15 -4
- package/templates/root-consumer/guides/wai-way/spec_template.md.example +7 -6
- 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/templates/app-payload/.env.example +0 -28
- package/templates/app-payload/README.md.example +0 -233
- package/templates/app-payload/collections/Company.ts.example +0 -125
- package/templates/app-payload/collections/Hero.ts.example +0 -62
- package/templates/app-payload/collections/Media.ts.example +0 -41
- package/templates/app-payload/collections/Products.ts.example +0 -115
- package/templates/app-payload/collections/Services.ts.example +0 -104
- package/templates/app-payload/collections/Testimonials.ts.example +0 -92
- package/templates/app-payload/collections/Users.ts.example +0 -35
- package/templates/app-payload/src/server.ts.example +0 -79
- package/templates/app-payload/tsconfig.json.example +0 -24
package/dist/bin/commands/emu.js
CHANGED
|
@@ -7594,11 +7594,39 @@ var init_PathResolver = __esm({
|
|
|
7594
7594
|
});
|
|
7595
7595
|
|
|
7596
7596
|
// packages/tooling/src/utils/errors.ts
|
|
7597
|
-
var DoNotDevError;
|
|
7597
|
+
var DO_NOT_DEV_ERROR_CODES, DoNotDevError;
|
|
7598
7598
|
var init_errors = __esm({
|
|
7599
7599
|
"packages/tooling/src/utils/errors.ts"() {
|
|
7600
7600
|
"use strict";
|
|
7601
7601
|
init_utils();
|
|
7602
|
+
DO_NOT_DEV_ERROR_CODES = {
|
|
7603
|
+
CONFIGURATION_ERROR: "configuration-error",
|
|
7604
|
+
CONFIG_NOT_FOUND: "config-not-found",
|
|
7605
|
+
CONFIG_INVALID: "config-invalid",
|
|
7606
|
+
PATH_RESOLUTION_ERROR: "path-resolution-error",
|
|
7607
|
+
FILE_OPERATION_ERROR: "file-operation-error",
|
|
7608
|
+
FILE_NOT_FOUND: "file-not-found",
|
|
7609
|
+
PERMISSION_DENIED: "permission-denied",
|
|
7610
|
+
GENERATION_ERROR: "generation-error",
|
|
7611
|
+
TEMPLATE_ERROR: "template-error",
|
|
7612
|
+
TEMPLATE_NOT_FOUND: "template-not-found",
|
|
7613
|
+
CLI_EXECUTION_ERROR: "cli-execution-error",
|
|
7614
|
+
COMMAND_NOT_FOUND: "command-not-found",
|
|
7615
|
+
COMMAND_FAILED: "command-failed",
|
|
7616
|
+
VALIDATION_ERROR: "validation-error",
|
|
7617
|
+
SCHEMA_ERROR: "schema-error",
|
|
7618
|
+
DEPENDENCY_ERROR: "dependency-error",
|
|
7619
|
+
DEPENDENCY_NOT_FOUND: "dependency-not-found",
|
|
7620
|
+
DEPENDENCY_VERSION_ERROR: "dependency-version-error",
|
|
7621
|
+
INVALID_ARGUMENT: "invalid-argument",
|
|
7622
|
+
MISSING_ARGUMENT: "missing-argument",
|
|
7623
|
+
MISSING_PROJECT_ID: "missing-project-id",
|
|
7624
|
+
FIREBASE_CLI_ERROR: "firebase-cli-error",
|
|
7625
|
+
DEPLOYMENT_FAILED: "deployment-failed",
|
|
7626
|
+
OPERATION_CANCELLED: "operation-cancelled",
|
|
7627
|
+
TIMEOUT_ERROR: "timeout-error",
|
|
7628
|
+
UNKNOWN_ERROR: "unknown-error"
|
|
7629
|
+
};
|
|
7602
7630
|
DoNotDevError = class _DoNotDevError extends Error {
|
|
7603
7631
|
/** The error code categorizing this error */
|
|
7604
7632
|
code;
|
|
@@ -7618,7 +7646,7 @@ var init_errors = __esm({
|
|
|
7618
7646
|
* @param {Record<string, any>} [options.context] - Additional context data
|
|
7619
7647
|
* @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
|
|
7620
7648
|
*/
|
|
7621
|
-
constructor(message, code =
|
|
7649
|
+
constructor(message, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
|
|
7622
7650
|
super(message);
|
|
7623
7651
|
this.name = "DoNotDevError";
|
|
7624
7652
|
this.code = code;
|
|
@@ -7649,7 +7677,7 @@ var init_errors = __esm({
|
|
|
7649
7677
|
* @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
|
|
7650
7678
|
* @returns {DoNotDevError} New DoNotDev error wrapping the original
|
|
7651
7679
|
*/
|
|
7652
|
-
static from(error2, context, code =
|
|
7680
|
+
static from(error2, context, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
|
|
7653
7681
|
if (!(error2 instanceof Error)) {
|
|
7654
7682
|
return new _DoNotDevError(
|
|
7655
7683
|
`Unknown error: ${String(error2)}`,
|
|
@@ -7686,21 +7714,21 @@ var init_errors = __esm({
|
|
|
7686
7714
|
}
|
|
7687
7715
|
const message = error2.message.toLowerCase();
|
|
7688
7716
|
if (error2.name === "ValidationError" || message.includes("validation")) {
|
|
7689
|
-
return
|
|
7717
|
+
return DO_NOT_DEV_ERROR_CODES.VALIDATION_ERROR;
|
|
7690
7718
|
}
|
|
7691
7719
|
if (message.includes("not found") || message.includes("no such file")) {
|
|
7692
|
-
return
|
|
7720
|
+
return DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND;
|
|
7693
7721
|
}
|
|
7694
7722
|
if (message.includes("permission") || message.includes("access denied")) {
|
|
7695
|
-
return
|
|
7723
|
+
return DO_NOT_DEV_ERROR_CODES.PERMISSION_DENIED;
|
|
7696
7724
|
}
|
|
7697
7725
|
if (message.includes("timeout") || message.includes("timed out")) {
|
|
7698
|
-
return
|
|
7726
|
+
return DO_NOT_DEV_ERROR_CODES.TIMEOUT_ERROR;
|
|
7699
7727
|
}
|
|
7700
7728
|
if (message.includes("dependency") || message.includes("module not found")) {
|
|
7701
|
-
return
|
|
7729
|
+
return DO_NOT_DEV_ERROR_CODES.DEPENDENCY_ERROR;
|
|
7702
7730
|
}
|
|
7703
|
-
return
|
|
7731
|
+
return DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR;
|
|
7704
7732
|
}
|
|
7705
7733
|
};
|
|
7706
7734
|
}
|
|
@@ -7743,6 +7771,52 @@ var init_pathResolver = __esm({
|
|
|
7743
7771
|
}
|
|
7744
7772
|
});
|
|
7745
7773
|
|
|
7774
|
+
// packages/tooling/src/utils/typed-file-operations.ts
|
|
7775
|
+
function readFirebaseJson(filePath) {
|
|
7776
|
+
if (!pathExists(filePath)) {
|
|
7777
|
+
throw new DoNotDevError(
|
|
7778
|
+
`firebase.json not found: ${filePath}`,
|
|
7779
|
+
DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND,
|
|
7780
|
+
{ context: { filePath } }
|
|
7781
|
+
);
|
|
7782
|
+
}
|
|
7783
|
+
const content = readSync(filePath, { format: "json" });
|
|
7784
|
+
if (!content || typeof content !== "object") {
|
|
7785
|
+
throw new DoNotDevError(
|
|
7786
|
+
`Invalid firebase.json: ${filePath}`,
|
|
7787
|
+
DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
|
|
7788
|
+
{ context: { filePath } }
|
|
7789
|
+
);
|
|
7790
|
+
}
|
|
7791
|
+
return content;
|
|
7792
|
+
}
|
|
7793
|
+
function readPackageJson(filePath) {
|
|
7794
|
+
if (!pathExists(filePath)) {
|
|
7795
|
+
throw new DoNotDevError(
|
|
7796
|
+
`package.json not found: ${filePath}`,
|
|
7797
|
+
DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND,
|
|
7798
|
+
{ context: { filePath } }
|
|
7799
|
+
);
|
|
7800
|
+
}
|
|
7801
|
+
const content = readSync(filePath, { format: "json" });
|
|
7802
|
+
if (!content || typeof content !== "object" || !("name" in content)) {
|
|
7803
|
+
throw new DoNotDevError(
|
|
7804
|
+
`Invalid package.json: ${filePath}`,
|
|
7805
|
+
DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
|
|
7806
|
+
{ context: { filePath } }
|
|
7807
|
+
);
|
|
7808
|
+
}
|
|
7809
|
+
return content;
|
|
7810
|
+
}
|
|
7811
|
+
var init_typed_file_operations = __esm({
|
|
7812
|
+
"packages/tooling/src/utils/typed-file-operations.ts"() {
|
|
7813
|
+
"use strict";
|
|
7814
|
+
init_utils();
|
|
7815
|
+
init_pathResolver();
|
|
7816
|
+
init_errors();
|
|
7817
|
+
}
|
|
7818
|
+
});
|
|
7819
|
+
|
|
7746
7820
|
// packages/tooling/src/bundler/utils.ts
|
|
7747
7821
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
7748
7822
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
@@ -7770,22 +7844,7 @@ var init_utils = __esm({
|
|
|
7770
7844
|
}
|
|
7771
7845
|
});
|
|
7772
7846
|
|
|
7773
|
-
// packages/cli/src/bin/commands/emu.ts
|
|
7774
|
-
init_utils();
|
|
7775
|
-
|
|
7776
|
-
// packages/tooling/src/index.ts
|
|
7777
|
-
init_utils();
|
|
7778
|
-
|
|
7779
|
-
// packages/tooling/src/cli/index.ts
|
|
7780
|
-
init_utils();
|
|
7781
|
-
|
|
7782
|
-
// packages/tooling/src/utils/app-selector.ts
|
|
7783
|
-
init_utils();
|
|
7784
|
-
init_dist2();
|
|
7785
|
-
|
|
7786
7847
|
// packages/tooling/src/utils/app-detection.ts
|
|
7787
|
-
init_utils();
|
|
7788
|
-
init_pathResolver();
|
|
7789
7848
|
function detectApps(projectRoot) {
|
|
7790
7849
|
const apps = [];
|
|
7791
7850
|
const appsDir = joinPath(projectRoot, "apps");
|
|
@@ -7806,9 +7865,7 @@ function detectApps(projectRoot) {
|
|
|
7806
7865
|
const packageJsonPath = joinPath(projectRoot, "package.json");
|
|
7807
7866
|
if (pathExists(packageJsonPath)) {
|
|
7808
7867
|
try {
|
|
7809
|
-
const packageJson =
|
|
7810
|
-
format: "json"
|
|
7811
|
-
});
|
|
7868
|
+
const packageJson = readPackageJson(packageJsonPath);
|
|
7812
7869
|
if (packageJson && (packageJson.dependencies?.vite || packageJson.devDependencies?.vite || packageJson.dependencies?.next || packageJson.devDependencies?.next)) {
|
|
7813
7870
|
const pathParts = projectRoot.split(/[/\\]/);
|
|
7814
7871
|
const appName = pathParts[pathParts.length - 1] || "app";
|
|
@@ -7828,10 +7885,10 @@ function analyzeApp(appPath, appName) {
|
|
|
7828
7885
|
if (!pathExists(packageJsonPath)) {
|
|
7829
7886
|
return null;
|
|
7830
7887
|
}
|
|
7831
|
-
let packageJson;
|
|
7888
|
+
let packageJson = null;
|
|
7832
7889
|
try {
|
|
7833
|
-
packageJson =
|
|
7834
|
-
if (!packageJson) {
|
|
7890
|
+
packageJson = readPackageJson(packageJsonPath);
|
|
7891
|
+
if (!packageJson.name) {
|
|
7835
7892
|
return null;
|
|
7836
7893
|
}
|
|
7837
7894
|
} catch {
|
|
@@ -7846,14 +7903,23 @@ function analyzeApp(appPath, appName) {
|
|
|
7846
7903
|
const functionsPath = joinPath(appPath, "functions");
|
|
7847
7904
|
const functionsStat = statSync2(functionsPath);
|
|
7848
7905
|
const hasFunctions = pathExists(functionsPath) && (functionsStat?.isDirectory() ?? false);
|
|
7849
|
-
let
|
|
7850
|
-
|
|
7851
|
-
|
|
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) {
|
|
7852
7920
|
const vercelJsonPath = joinPath(appPath, "vercel.json");
|
|
7853
|
-
if (pathExists(
|
|
7854
|
-
|
|
7855
|
-
} else if (pathExists(vercelJsonPath)) {
|
|
7856
|
-
platform = "vercel";
|
|
7921
|
+
if (pathExists(vercelJsonPath)) {
|
|
7922
|
+
platform4 = "vercel";
|
|
7857
7923
|
}
|
|
7858
7924
|
}
|
|
7859
7925
|
return {
|
|
@@ -7864,12 +7930,19 @@ function analyzeApp(appPath, appName) {
|
|
|
7864
7930
|
framework,
|
|
7865
7931
|
hasFunctions,
|
|
7866
7932
|
functionsPath: hasFunctions ? functionsPath : void 0,
|
|
7867
|
-
platform
|
|
7933
|
+
platform: platform4
|
|
7868
7934
|
};
|
|
7869
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
|
+
});
|
|
7870
7944
|
|
|
7871
7945
|
// packages/tooling/src/utils/app-selector.ts
|
|
7872
|
-
init_cli_output();
|
|
7873
7946
|
async function selectApp(projectRoot, appName) {
|
|
7874
7947
|
const apps = detectApps(projectRoot);
|
|
7875
7948
|
if (apps.length === 0) {
|
|
@@ -7903,10 +7976,17 @@ async function selectApp(projectRoot, appName) {
|
|
|
7903
7976
|
}
|
|
7904
7977
|
return apps.find((a) => a.name === selected) || null;
|
|
7905
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
|
+
});
|
|
7906
7988
|
|
|
7907
7989
|
// packages/tooling/src/utils/cli-input.ts
|
|
7908
|
-
init_utils();
|
|
7909
|
-
init_dist2();
|
|
7910
7990
|
async function askForMultiSelection(message, choices, defaultIndices = []) {
|
|
7911
7991
|
const options = choices.map((choice) => ({
|
|
7912
7992
|
value: choice.value,
|
|
@@ -7925,6 +8005,22 @@ async function askForMultiSelection(message, choices, defaultIndices = []) {
|
|
|
7925
8005
|
}
|
|
7926
8006
|
return result;
|
|
7927
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();
|
|
7928
8024
|
|
|
7929
8025
|
// packages/tooling/src/utils/spawn-utils.ts
|
|
7930
8026
|
init_utils();
|
|
@@ -7970,16 +8066,29 @@ function createEmulatorEnv(appPath, framework = "vite", options) {
|
|
|
7970
8066
|
|
|
7971
8067
|
// packages/tooling/src/apps/emu.ts
|
|
7972
8068
|
init_utils();
|
|
7973
|
-
|
|
8069
|
+
init_app_selector();
|
|
7974
8070
|
init_cli_output();
|
|
7975
8071
|
init_errors();
|
|
7976
8072
|
init_pathResolver();
|
|
8073
|
+
|
|
8074
|
+
// packages/tooling/src/apps/emu-firebase.ts
|
|
8075
|
+
init_utils();
|
|
8076
|
+
init_cli_input();
|
|
8077
|
+
init_cli_output();
|
|
7977
8078
|
init_pathResolver();
|
|
8079
|
+
init_typed_file_operations();
|
|
8080
|
+
import {
|
|
8081
|
+
spawn,
|
|
8082
|
+
spawnSync as spawnSync2,
|
|
8083
|
+
execSync as execSync2
|
|
8084
|
+
} from "node:child_process";
|
|
8085
|
+
import { platform } from "node:os";
|
|
7978
8086
|
function discoverFirebaseProjectId(appPath) {
|
|
7979
8087
|
const firebasercPath = joinPath(appPath, ".firebaserc");
|
|
7980
8088
|
if (pathExists(firebasercPath)) {
|
|
7981
8089
|
try {
|
|
7982
|
-
const
|
|
8090
|
+
const firebasercRaw = readSync(firebasercPath, { format: "json" });
|
|
8091
|
+
const firebaserc = firebasercRaw && typeof firebasercRaw === "object" ? firebasercRaw : null;
|
|
7983
8092
|
if (firebaserc?.projects?.default) {
|
|
7984
8093
|
return firebaserc.projects.default;
|
|
7985
8094
|
}
|
|
@@ -8005,7 +8114,7 @@ function killPorts(ports) {
|
|
|
8005
8114
|
pids.add(match[1]);
|
|
8006
8115
|
}
|
|
8007
8116
|
}
|
|
8008
|
-
for (const pid of pids) {
|
|
8117
|
+
for (const pid of Array.from(pids)) {
|
|
8009
8118
|
try {
|
|
8010
8119
|
execSync2(`taskkill /F /PID ${pid}`, { stdio: "ignore" });
|
|
8011
8120
|
log.debug(`Killed process ${pid} on port ${port}`);
|
|
@@ -8014,12 +8123,18 @@ function killPorts(ports) {
|
|
|
8014
8123
|
}
|
|
8015
8124
|
} else {
|
|
8016
8125
|
try {
|
|
8017
|
-
const
|
|
8126
|
+
const output = execSync2(`lsof -ti:${port}`, {
|
|
8018
8127
|
encoding: "utf-8"
|
|
8019
8128
|
}).trim();
|
|
8020
|
-
if (
|
|
8021
|
-
|
|
8022
|
-
|
|
8129
|
+
if (output) {
|
|
8130
|
+
const pids = output.split("\n").filter(Boolean);
|
|
8131
|
+
for (const pid of pids) {
|
|
8132
|
+
try {
|
|
8133
|
+
execSync2(`kill -9 ${pid}`, { stdio: "ignore" });
|
|
8134
|
+
log.debug(`Killed process ${pid} on port ${port}`);
|
|
8135
|
+
} catch {
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8023
8138
|
}
|
|
8024
8139
|
} catch {
|
|
8025
8140
|
}
|
|
@@ -8061,9 +8176,9 @@ function loadEnvFile(filePath) {
|
|
|
8061
8176
|
} catch {
|
|
8062
8177
|
}
|
|
8063
8178
|
}
|
|
8064
|
-
async function
|
|
8065
|
-
const
|
|
8066
|
-
|
|
8179
|
+
async function startFirebase(app, projectRoot, options = {}) {
|
|
8180
|
+
const debug = options.debug ?? false;
|
|
8181
|
+
let selectedServices = options.selectedServices ?? [];
|
|
8067
8182
|
const serviceChoices = [
|
|
8068
8183
|
{
|
|
8069
8184
|
title: "Auth",
|
|
@@ -8086,47 +8201,6 @@ async function main(options) {
|
|
|
8086
8201
|
hint: "Stripe webhook forwarding (for payment testing)"
|
|
8087
8202
|
}
|
|
8088
8203
|
];
|
|
8089
|
-
let selectedServices = [];
|
|
8090
|
-
const appName = args.find(
|
|
8091
|
-
(arg) => arg !== "emu" && arg !== "--debug" && !arg.startsWith("--")
|
|
8092
|
-
);
|
|
8093
|
-
if (options?.services) {
|
|
8094
|
-
selectedServices = options.services.split(",").map((s) => s.trim());
|
|
8095
|
-
} else {
|
|
8096
|
-
const servicesArg = args.find((arg) => arg.startsWith("--services="));
|
|
8097
|
-
if (servicesArg) {
|
|
8098
|
-
const servicesList = servicesArg.split("=")[1];
|
|
8099
|
-
if (servicesList) {
|
|
8100
|
-
selectedServices = servicesList.split(",").map((s) => s.trim());
|
|
8101
|
-
}
|
|
8102
|
-
} else {
|
|
8103
|
-
if (options?.auth || args.includes("--auth"))
|
|
8104
|
-
selectedServices.push("auth");
|
|
8105
|
-
if (args.includes("--functions")) selectedServices.push("functions");
|
|
8106
|
-
if (options?.firestore || args.includes("--firestore"))
|
|
8107
|
-
selectedServices.push("firestore");
|
|
8108
|
-
if (options?.stripe || args.includes("--stripe"))
|
|
8109
|
-
selectedServices.push("stripe");
|
|
8110
|
-
}
|
|
8111
|
-
}
|
|
8112
|
-
const validServices = serviceChoices.map((c) => c.value);
|
|
8113
|
-
selectedServices = selectedServices.filter((s) => validServices.includes(s));
|
|
8114
|
-
const projectRoot = getRepoRoot();
|
|
8115
|
-
if (!projectRoot) {
|
|
8116
|
-
throw new DoNotDevError(
|
|
8117
|
-
"Could not determine repository root",
|
|
8118
|
-
"path-resolution-error"
|
|
8119
|
-
);
|
|
8120
|
-
}
|
|
8121
|
-
const app = await selectApp(projectRoot, appName);
|
|
8122
|
-
if (!app) {
|
|
8123
|
-
return 1;
|
|
8124
|
-
}
|
|
8125
|
-
if (!app.hasFunctions || app.platform !== "firebase") {
|
|
8126
|
-
log.error(`App "${app.name}" does not have Firebase functions.`);
|
|
8127
|
-
log.error('Use "dndev dev" for apps without functions.\n');
|
|
8128
|
-
return 1;
|
|
8129
|
-
}
|
|
8130
8204
|
log.info(`Starting Firebase emulators + dev server for ${app.name}...
|
|
8131
8205
|
`);
|
|
8132
8206
|
if (selectedServices.length === 0) {
|
|
@@ -8206,8 +8280,10 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
8206
8280
|
let emulatorConfig = null;
|
|
8207
8281
|
if (pathExists(appFirebaseJson)) {
|
|
8208
8282
|
try {
|
|
8209
|
-
const firebaseConfig =
|
|
8210
|
-
|
|
8283
|
+
const firebaseConfig = readFirebaseJson(appFirebaseJson);
|
|
8284
|
+
if (firebaseConfig.emulators) {
|
|
8285
|
+
emulatorConfig = firebaseConfig.emulators;
|
|
8286
|
+
}
|
|
8211
8287
|
} catch {
|
|
8212
8288
|
}
|
|
8213
8289
|
}
|
|
@@ -8244,7 +8320,7 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
8244
8320
|
const concurrentlyArgs = [
|
|
8245
8321
|
"--kill-others-on-fail",
|
|
8246
8322
|
"--prefix-colors",
|
|
8247
|
-
"cyan,green,yellow",
|
|
8323
|
+
useStripe ? "cyan,green,yellow" : "cyan,green",
|
|
8248
8324
|
"--prefix",
|
|
8249
8325
|
"[{name}]",
|
|
8250
8326
|
"--names",
|
|
@@ -8256,21 +8332,292 @@ FIREBASE_AUTH_EMULATOR_HOST=${authEmulatorHost}
|
|
|
8256
8332
|
const stripeWebhookUrl = `http://localhost:5001/${projectId}/${region}/stripeWebhook`;
|
|
8257
8333
|
concurrentlyArgs.push(`stripe listen --forward-to ${stripeWebhookUrl}`);
|
|
8258
8334
|
log.info("");
|
|
8259
|
-
log.info("
|
|
8335
|
+
log.info("Stripe webhook forwarding will start automatically");
|
|
8260
8336
|
log.info(` Webhook URL: ${stripeWebhookUrl}`);
|
|
8261
8337
|
log.info(" To trigger test events, run in another terminal:");
|
|
8262
8338
|
log.info(" stripe trigger checkout.session.completed");
|
|
8263
8339
|
log.info("");
|
|
8264
8340
|
}
|
|
8265
|
-
const
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8341
|
+
const isWindows = platform() === "win32";
|
|
8342
|
+
const childProcess = spawn(
|
|
8343
|
+
"bunx",
|
|
8344
|
+
["concurrently", ...concurrentlyArgs],
|
|
8345
|
+
{
|
|
8346
|
+
stdio: "inherit",
|
|
8347
|
+
env: createEmulatorEnv(app.path, app.framework, {
|
|
8348
|
+
useEmulatorAuth: useAuth,
|
|
8349
|
+
useEmulatorFirestore: useFirestore
|
|
8350
|
+
}),
|
|
8351
|
+
cwd: app.path,
|
|
8352
|
+
shell: isWindows
|
|
8353
|
+
}
|
|
8354
|
+
);
|
|
8355
|
+
const SIGNAL_EXIT_CODES = {
|
|
8356
|
+
SIGINT: 130,
|
|
8357
|
+
SIGTERM: 143
|
|
8358
|
+
};
|
|
8359
|
+
const cleanup = (signal) => {
|
|
8360
|
+
if (!childProcess.pid) return;
|
|
8361
|
+
log.debug(`Received ${signal}, cleaning up processes...`);
|
|
8362
|
+
if (isWindows) {
|
|
8363
|
+
try {
|
|
8364
|
+
execSync2(`taskkill /F /T /PID ${childProcess.pid}`, {
|
|
8365
|
+
stdio: "ignore",
|
|
8366
|
+
timeout: 2e3
|
|
8367
|
+
});
|
|
8368
|
+
} catch {
|
|
8369
|
+
}
|
|
8370
|
+
} else {
|
|
8371
|
+
try {
|
|
8372
|
+
process.kill(childProcess.pid, signal);
|
|
8373
|
+
} catch {
|
|
8374
|
+
}
|
|
8375
|
+
try {
|
|
8376
|
+
execSync2(`pkill -P ${childProcess.pid}`, {
|
|
8377
|
+
stdio: "ignore",
|
|
8378
|
+
timeout: 1e3
|
|
8379
|
+
});
|
|
8380
|
+
} catch {
|
|
8381
|
+
}
|
|
8382
|
+
}
|
|
8383
|
+
};
|
|
8384
|
+
const signals = ["SIGINT", "SIGTERM"];
|
|
8385
|
+
const handlers = [];
|
|
8386
|
+
for (const signal of signals) {
|
|
8387
|
+
const handler = () => {
|
|
8388
|
+
cleanup(signal);
|
|
8389
|
+
handlers.forEach((h2) => h2());
|
|
8390
|
+
process.exit(SIGNAL_EXIT_CODES[signal] ?? 130);
|
|
8391
|
+
};
|
|
8392
|
+
process.on(signal, handler);
|
|
8393
|
+
handlers.push(() => process.removeListener(signal, handler));
|
|
8394
|
+
}
|
|
8395
|
+
return new Promise((resolve4) => {
|
|
8396
|
+
childProcess.on("exit", (code, signal) => {
|
|
8397
|
+
handlers.forEach((h2) => h2());
|
|
8398
|
+
if (signal) {
|
|
8399
|
+
log.debug(`Process killed by signal: ${signal}`);
|
|
8400
|
+
resolve4(SIGNAL_EXIT_CODES[signal] ?? 130);
|
|
8401
|
+
} else {
|
|
8402
|
+
resolve4(code ?? 0);
|
|
8403
|
+
}
|
|
8404
|
+
});
|
|
8405
|
+
childProcess.on("error", (error2) => {
|
|
8406
|
+
handlers.forEach((h2) => h2());
|
|
8407
|
+
log.error(`Failed to start Firebase emulators: ${error2.message}`);
|
|
8408
|
+
resolve4(1);
|
|
8409
|
+
});
|
|
8410
|
+
});
|
|
8411
|
+
}
|
|
8412
|
+
|
|
8413
|
+
// packages/tooling/src/apps/emu-supabase.ts
|
|
8414
|
+
init_utils();
|
|
8415
|
+
init_cli_output();
|
|
8416
|
+
import {
|
|
8417
|
+
spawn as spawn2,
|
|
8418
|
+
execSync as execSync3
|
|
8419
|
+
} from "node:child_process";
|
|
8420
|
+
import { platform as platform2 } from "node:os";
|
|
8421
|
+
function isDockerRunning() {
|
|
8422
|
+
try {
|
|
8423
|
+
execSync3("docker info", { stdio: "pipe", timeout: 5e3 });
|
|
8424
|
+
return true;
|
|
8425
|
+
} catch {
|
|
8426
|
+
return false;
|
|
8427
|
+
}
|
|
8428
|
+
}
|
|
8429
|
+
async function startSupabase(app, _projectRoot) {
|
|
8430
|
+
log.info(`Starting Supabase local stack + dev server for ${app.name}...
|
|
8431
|
+
`);
|
|
8432
|
+
if (!isDockerRunning()) {
|
|
8433
|
+
log.error("Docker is not running. Supabase local dev requires Docker.");
|
|
8434
|
+
log.error("Start Docker Desktop and try again.\n");
|
|
8435
|
+
return 1;
|
|
8436
|
+
}
|
|
8437
|
+
try {
|
|
8438
|
+
execSync3("supabase --version", { stdio: "pipe" });
|
|
8439
|
+
} catch {
|
|
8440
|
+
log.error("Supabase CLI not found. Install it:");
|
|
8441
|
+
log.error(" npm install -g supabase\n");
|
|
8442
|
+
return 1;
|
|
8443
|
+
}
|
|
8444
|
+
const isWindows = platform2() === "win32";
|
|
8445
|
+
const concurrentlyArgs = [
|
|
8446
|
+
"--kill-others-on-fail",
|
|
8447
|
+
"--prefix-colors",
|
|
8448
|
+
"cyan,green",
|
|
8449
|
+
"--prefix",
|
|
8450
|
+
"[{name}]",
|
|
8451
|
+
"--names",
|
|
8452
|
+
"supabase,dev",
|
|
8453
|
+
"supabase start",
|
|
8454
|
+
`bunx turbo dev --filter=${app.packageName}`
|
|
8455
|
+
];
|
|
8456
|
+
const childProcess = spawn2(
|
|
8457
|
+
"bunx",
|
|
8458
|
+
["concurrently", ...concurrentlyArgs],
|
|
8459
|
+
{
|
|
8460
|
+
stdio: "inherit",
|
|
8461
|
+
cwd: app.path,
|
|
8462
|
+
shell: isWindows
|
|
8463
|
+
}
|
|
8464
|
+
);
|
|
8465
|
+
const cleanup = () => {
|
|
8466
|
+
if (!childProcess.pid) return;
|
|
8467
|
+
if (isWindows) {
|
|
8468
|
+
try {
|
|
8469
|
+
execSync3(`taskkill /F /T /PID ${childProcess.pid}`, { stdio: "ignore", timeout: 2e3 });
|
|
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);
|
|
8272
8486
|
});
|
|
8273
|
-
return
|
|
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 {
|
|
8500
|
+
spawn as spawn3,
|
|
8501
|
+
execSync as execSync4
|
|
8502
|
+
} from "node:child_process";
|
|
8503
|
+
import { platform as platform3 } from "node:os";
|
|
8504
|
+
async function startVercel(app, _projectRoot) {
|
|
8505
|
+
log.info(`Starting Vercel dev server for ${app.name}...
|
|
8506
|
+
`);
|
|
8507
|
+
try {
|
|
8508
|
+
execSync4("vercel --version", { stdio: "pipe" });
|
|
8509
|
+
} catch {
|
|
8510
|
+
log.error("Vercel CLI not found. Install it:");
|
|
8511
|
+
log.error(" npm install -g vercel\n");
|
|
8512
|
+
return 1;
|
|
8513
|
+
}
|
|
8514
|
+
const isWindows = platform3() === "win32";
|
|
8515
|
+
const childProcess = spawn3(
|
|
8516
|
+
"vercel",
|
|
8517
|
+
["dev"],
|
|
8518
|
+
{
|
|
8519
|
+
stdio: "inherit",
|
|
8520
|
+
cwd: app.path,
|
|
8521
|
+
shell: isWindows
|
|
8522
|
+
}
|
|
8523
|
+
);
|
|
8524
|
+
const cleanup = () => {
|
|
8525
|
+
if (!childProcess.pid) return;
|
|
8526
|
+
if (isWindows) {
|
|
8527
|
+
try {
|
|
8528
|
+
execSync4(`taskkill /F /T /PID ${childProcess.pid}`, { stdio: "ignore", timeout: 2e3 });
|
|
8529
|
+
} catch {
|
|
8530
|
+
}
|
|
8531
|
+
} else {
|
|
8532
|
+
try {
|
|
8533
|
+
process.kill(childProcess.pid, "SIGTERM");
|
|
8534
|
+
} catch {
|
|
8535
|
+
}
|
|
8536
|
+
}
|
|
8537
|
+
};
|
|
8538
|
+
process.on("SIGINT", () => {
|
|
8539
|
+
cleanup();
|
|
8540
|
+
process.exit(130);
|
|
8541
|
+
});
|
|
8542
|
+
process.on("SIGTERM", () => {
|
|
8543
|
+
cleanup();
|
|
8544
|
+
process.exit(143);
|
|
8545
|
+
});
|
|
8546
|
+
return new Promise((resolve4) => {
|
|
8547
|
+
childProcess.on("exit", (code) => resolve4(code ?? 0));
|
|
8548
|
+
childProcess.on("error", (error2) => {
|
|
8549
|
+
log.error(`Failed to start Vercel dev: ${error2.message}`);
|
|
8550
|
+
resolve4(1);
|
|
8551
|
+
});
|
|
8552
|
+
});
|
|
8553
|
+
}
|
|
8554
|
+
|
|
8555
|
+
// packages/tooling/src/apps/emu.ts
|
|
8556
|
+
async function main(options) {
|
|
8557
|
+
const args = process.argv.slice(2);
|
|
8558
|
+
const projectRoot = getRepoRoot();
|
|
8559
|
+
if (!projectRoot) {
|
|
8560
|
+
throw new DoNotDevError(
|
|
8561
|
+
"Could not determine repository root",
|
|
8562
|
+
"path-resolution-error"
|
|
8563
|
+
);
|
|
8564
|
+
}
|
|
8565
|
+
const appName = args.find(
|
|
8566
|
+
(arg) => arg !== "emu" && arg !== "--debug" && !arg.startsWith("--")
|
|
8567
|
+
);
|
|
8568
|
+
const app = await selectApp(projectRoot, appName);
|
|
8569
|
+
if (!app) {
|
|
8570
|
+
return 1;
|
|
8571
|
+
}
|
|
8572
|
+
switch (app.platform) {
|
|
8573
|
+
case "firebase": {
|
|
8574
|
+
if (!app.hasFunctions) {
|
|
8575
|
+
log.error(`App "${app.name}" has Firebase config but no functions directory.`);
|
|
8576
|
+
log.error('Use "dndev dev" for apps without backend functions.\n');
|
|
8577
|
+
return 1;
|
|
8578
|
+
}
|
|
8579
|
+
const selectedServices = parseFirebaseServices(args, options);
|
|
8580
|
+
return startFirebase(app, projectRoot, {
|
|
8581
|
+
debug: options?.debug ?? false,
|
|
8582
|
+
selectedServices
|
|
8583
|
+
});
|
|
8584
|
+
}
|
|
8585
|
+
case "supabase":
|
|
8586
|
+
return startSupabase(app, projectRoot);
|
|
8587
|
+
case "vercel":
|
|
8588
|
+
return startVercel(app, projectRoot);
|
|
8589
|
+
default:
|
|
8590
|
+
log.error(`App "${app.name}" does not have a detected backend platform.`);
|
|
8591
|
+
log.error(
|
|
8592
|
+
"Expected: firebase.json (Firebase), supabase/config.toml or @donotdev/supabase (Supabase), or vercel.json (Vercel)."
|
|
8593
|
+
);
|
|
8594
|
+
log.error('Use "dndev dev" for apps without a backend.\n');
|
|
8595
|
+
return 1;
|
|
8596
|
+
}
|
|
8597
|
+
}
|
|
8598
|
+
function parseFirebaseServices(args, options) {
|
|
8599
|
+
const validServices = ["auth", "functions", "firestore", "stripe"];
|
|
8600
|
+
let selectedServices = [];
|
|
8601
|
+
if (options?.services) {
|
|
8602
|
+
selectedServices = options.services.split(",").map((s) => s.trim());
|
|
8603
|
+
} else {
|
|
8604
|
+
const servicesArg = args.find((arg) => arg.startsWith("--services="));
|
|
8605
|
+
if (servicesArg) {
|
|
8606
|
+
const servicesList = servicesArg.split("=")[1];
|
|
8607
|
+
if (servicesList) {
|
|
8608
|
+
selectedServices = servicesList.split(",").map((s) => s.trim());
|
|
8609
|
+
}
|
|
8610
|
+
} else {
|
|
8611
|
+
if (options?.auth || args.includes("--auth"))
|
|
8612
|
+
selectedServices.push("auth");
|
|
8613
|
+
if (args.includes("--functions")) selectedServices.push("functions");
|
|
8614
|
+
if (options?.firestore || args.includes("--firestore"))
|
|
8615
|
+
selectedServices.push("firestore");
|
|
8616
|
+
if (options?.stripe || args.includes("--stripe"))
|
|
8617
|
+
selectedServices.push("stripe");
|
|
8618
|
+
}
|
|
8619
|
+
}
|
|
8620
|
+
return selectedServices.filter((s) => validServices.includes(s));
|
|
8274
8621
|
}
|
|
8275
8622
|
export {
|
|
8276
8623
|
main
|