@donotdev/cli 0.0.14 → 0.0.15
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 +356 -88
- package/dist/bin/commands/agent-setup.js +7 -1
- package/dist/bin/commands/build.js +118 -38
- package/dist/bin/commands/bump.js +74 -28
- package/dist/bin/commands/cacheout.js +37 -9
- package/dist/bin/commands/create-app.js +222 -115
- package/dist/bin/commands/create-project.js +455 -140
- package/dist/bin/commands/deploy.js +1736 -697
- package/dist/bin/commands/dev.js +138 -23
- package/dist/bin/commands/emu.js +215 -58
- package/dist/bin/commands/format.js +37 -9
- package/dist/bin/commands/lint.js +37 -9
- package/dist/bin/commands/preview.js +142 -23
- 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 +314 -0
- package/dist/bin/commands/type-check.js.map +1 -0
- package/dist/bin/commands/wai.js +3 -1
- package/dist/bin/dndev.js +27 -2
- package/dist/bin/donotdev.js +27 -2
- package/dist/index.js +3960 -3015
- package/package.json +2 -2
- 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 +64 -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/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/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/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/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 +1 -1
- package/templates/app-vite/src/themes.css.example +109 -79
- package/templates/app-vite/vercel.json.example +11 -0
- package/templates/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/.env.example.example +23 -25
- 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-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/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 +7 -0
- package/templates/overlay-supabase/env.fragment.expo.example +7 -0
- package/templates/overlay-supabase/env.fragment.nextjs.example +7 -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 +29 -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 +20 -0
- 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 +99 -30
- package/templates/root-consumer/guides/dndev/INDEX.md.example +3 -1
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +143 -12
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +9 -3
- package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -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/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 +47 -11
- 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/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
|
@@ -7757,6 +7757,147 @@ var init_PathResolver = __esm({
|
|
|
7757
7757
|
}
|
|
7758
7758
|
});
|
|
7759
7759
|
|
|
7760
|
+
// packages/tooling/src/utils/errors.ts
|
|
7761
|
+
var DO_NOT_DEV_ERROR_CODES, DoNotDevError;
|
|
7762
|
+
var init_errors = __esm({
|
|
7763
|
+
"packages/tooling/src/utils/errors.ts"() {
|
|
7764
|
+
"use strict";
|
|
7765
|
+
init_utils();
|
|
7766
|
+
DO_NOT_DEV_ERROR_CODES = {
|
|
7767
|
+
CONFIGURATION_ERROR: "configuration-error",
|
|
7768
|
+
CONFIG_NOT_FOUND: "config-not-found",
|
|
7769
|
+
CONFIG_INVALID: "config-invalid",
|
|
7770
|
+
PATH_RESOLUTION_ERROR: "path-resolution-error",
|
|
7771
|
+
FILE_OPERATION_ERROR: "file-operation-error",
|
|
7772
|
+
FILE_NOT_FOUND: "file-not-found",
|
|
7773
|
+
PERMISSION_DENIED: "permission-denied",
|
|
7774
|
+
GENERATION_ERROR: "generation-error",
|
|
7775
|
+
TEMPLATE_ERROR: "template-error",
|
|
7776
|
+
TEMPLATE_NOT_FOUND: "template-not-found",
|
|
7777
|
+
CLI_EXECUTION_ERROR: "cli-execution-error",
|
|
7778
|
+
COMMAND_NOT_FOUND: "command-not-found",
|
|
7779
|
+
COMMAND_FAILED: "command-failed",
|
|
7780
|
+
VALIDATION_ERROR: "validation-error",
|
|
7781
|
+
SCHEMA_ERROR: "schema-error",
|
|
7782
|
+
DEPENDENCY_ERROR: "dependency-error",
|
|
7783
|
+
DEPENDENCY_NOT_FOUND: "dependency-not-found",
|
|
7784
|
+
DEPENDENCY_VERSION_ERROR: "dependency-version-error",
|
|
7785
|
+
INVALID_ARGUMENT: "invalid-argument",
|
|
7786
|
+
MISSING_ARGUMENT: "missing-argument",
|
|
7787
|
+
MISSING_PROJECT_ID: "missing-project-id",
|
|
7788
|
+
FIREBASE_CLI_ERROR: "firebase-cli-error",
|
|
7789
|
+
DEPLOYMENT_FAILED: "deployment-failed",
|
|
7790
|
+
OPERATION_CANCELLED: "operation-cancelled",
|
|
7791
|
+
TIMEOUT_ERROR: "timeout-error",
|
|
7792
|
+
UNKNOWN_ERROR: "unknown-error"
|
|
7793
|
+
};
|
|
7794
|
+
DoNotDevError = class _DoNotDevError extends Error {
|
|
7795
|
+
/** The error code categorizing this error */
|
|
7796
|
+
code;
|
|
7797
|
+
/** Original error if this is wrapping another error */
|
|
7798
|
+
originalError;
|
|
7799
|
+
/** Additional context for the error */
|
|
7800
|
+
context;
|
|
7801
|
+
/** Whether this error should be displayed to the user */
|
|
7802
|
+
displayable;
|
|
7803
|
+
/**
|
|
7804
|
+
* Creates a new DoNotDev error
|
|
7805
|
+
*
|
|
7806
|
+
* @param {string} message - Error message
|
|
7807
|
+
* @param {DoNotDevErrorCode} code - Error code
|
|
7808
|
+
* @param {object} [options] - Additional error options
|
|
7809
|
+
* @param {Error} [options.originalError] - Original error if wrapping
|
|
7810
|
+
* @param {Record<string, any>} [options.context] - Additional context data
|
|
7811
|
+
* @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
|
|
7812
|
+
*/
|
|
7813
|
+
constructor(message, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
|
|
7814
|
+
super(message);
|
|
7815
|
+
this.name = "DoNotDevError";
|
|
7816
|
+
this.code = code;
|
|
7817
|
+
this.originalError = options?.originalError;
|
|
7818
|
+
this.context = options?.context;
|
|
7819
|
+
this.displayable = options?.displayable !== false;
|
|
7820
|
+
Object.setPrototypeOf(this, _DoNotDevError.prototype);
|
|
7821
|
+
if (Error.captureStackTrace) {
|
|
7822
|
+
Error.captureStackTrace(this, _DoNotDevError);
|
|
7823
|
+
}
|
|
7824
|
+
}
|
|
7825
|
+
/**
|
|
7826
|
+
* Formats the error for logging or display
|
|
7827
|
+
*
|
|
7828
|
+
* @returns {string} Formatted error message with code
|
|
7829
|
+
*/
|
|
7830
|
+
format() {
|
|
7831
|
+
return `[${this.code}] ${this.message}`;
|
|
7832
|
+
}
|
|
7833
|
+
/**
|
|
7834
|
+
* Creates a wrapped error from another error
|
|
7835
|
+
*
|
|
7836
|
+
* @param {Error} error - Original error to wrap
|
|
7837
|
+
* @param {string} [context] - Additional context for the error
|
|
7838
|
+
* @param {DoNotDevErrorCode} [code='unknown-error'] - Error code
|
|
7839
|
+
* @param {object} [options] - Additional error options
|
|
7840
|
+
* @param {Record<string, any>} [options.context] - Additional context data
|
|
7841
|
+
* @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
|
|
7842
|
+
* @returns {DoNotDevError} New DoNotDev error wrapping the original
|
|
7843
|
+
*/
|
|
7844
|
+
static from(error2, context, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
|
|
7845
|
+
if (!(error2 instanceof Error)) {
|
|
7846
|
+
return new _DoNotDevError(
|
|
7847
|
+
`Unknown error: ${String(error2)}`,
|
|
7848
|
+
code,
|
|
7849
|
+
options
|
|
7850
|
+
);
|
|
7851
|
+
}
|
|
7852
|
+
if (error2 instanceof _DoNotDevError) {
|
|
7853
|
+
if (!context) {
|
|
7854
|
+
return error2;
|
|
7855
|
+
}
|
|
7856
|
+
return new _DoNotDevError(`${context}: ${error2.message}`, error2.code, {
|
|
7857
|
+
originalError: error2.originalError || error2,
|
|
7858
|
+
context: { ...error2.context, ...options?.context || {} },
|
|
7859
|
+
displayable: options?.displayable ?? error2.displayable
|
|
7860
|
+
});
|
|
7861
|
+
}
|
|
7862
|
+
const message = context ? `${context}: ${error2.message}` : error2.message;
|
|
7863
|
+
return new _DoNotDevError(message, code, {
|
|
7864
|
+
originalError: error2,
|
|
7865
|
+
context: options?.context,
|
|
7866
|
+
displayable: options?.displayable
|
|
7867
|
+
});
|
|
7868
|
+
}
|
|
7869
|
+
/**
|
|
7870
|
+
* Maps common error types to DoNotDevErrorCode
|
|
7871
|
+
*
|
|
7872
|
+
* @param {Error} error - Error to analyze
|
|
7873
|
+
* @returns {DoNotDevErrorCode} Mapped error code
|
|
7874
|
+
*/
|
|
7875
|
+
static getErrorCodeFromError(error2) {
|
|
7876
|
+
if (error2 instanceof _DoNotDevError) {
|
|
7877
|
+
return error2.code;
|
|
7878
|
+
}
|
|
7879
|
+
const message = error2.message.toLowerCase();
|
|
7880
|
+
if (error2.name === "ValidationError" || message.includes("validation")) {
|
|
7881
|
+
return DO_NOT_DEV_ERROR_CODES.VALIDATION_ERROR;
|
|
7882
|
+
}
|
|
7883
|
+
if (message.includes("not found") || message.includes("no such file")) {
|
|
7884
|
+
return DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND;
|
|
7885
|
+
}
|
|
7886
|
+
if (message.includes("permission") || message.includes("access denied")) {
|
|
7887
|
+
return DO_NOT_DEV_ERROR_CODES.PERMISSION_DENIED;
|
|
7888
|
+
}
|
|
7889
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
7890
|
+
return DO_NOT_DEV_ERROR_CODES.TIMEOUT_ERROR;
|
|
7891
|
+
}
|
|
7892
|
+
if (message.includes("dependency") || message.includes("module not found")) {
|
|
7893
|
+
return DO_NOT_DEV_ERROR_CODES.DEPENDENCY_ERROR;
|
|
7894
|
+
}
|
|
7895
|
+
return DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR;
|
|
7896
|
+
}
|
|
7897
|
+
};
|
|
7898
|
+
}
|
|
7899
|
+
});
|
|
7900
|
+
|
|
7760
7901
|
// packages/tooling/src/utils/pathResolver.ts
|
|
7761
7902
|
var pathResolver_exports = {};
|
|
7762
7903
|
__export(pathResolver_exports, {
|
|
@@ -7884,16 +8025,19 @@ function getBinPath(binaryName) {
|
|
|
7884
8025
|
return binaryName;
|
|
7885
8026
|
}
|
|
7886
8027
|
function detectExecutionMode() {
|
|
7887
|
-
const fileUrlPath =
|
|
7888
|
-
if (
|
|
7889
|
-
return "
|
|
8028
|
+
const fileUrlPath = fileURLToPath2(import.meta.url);
|
|
8029
|
+
if (fileUrlPath.includes("node_modules")) {
|
|
8030
|
+
return "published";
|
|
7890
8031
|
}
|
|
7891
|
-
|
|
8032
|
+
if (fileUrlPath.includes("/dist/")) {
|
|
8033
|
+
return "published";
|
|
8034
|
+
}
|
|
8035
|
+
return "development";
|
|
7892
8036
|
}
|
|
7893
8037
|
function getTemplatesRoot() {
|
|
7894
8038
|
const mode = detectExecutionMode();
|
|
7895
8039
|
if (mode === "development") {
|
|
7896
|
-
const fileUrlPath =
|
|
8040
|
+
const fileUrlPath = fileURLToPath2(import.meta.url);
|
|
7897
8041
|
const frameworkRoot = normalizePath(dirname2(fileUrlPath), "../../../..");
|
|
7898
8042
|
return normalizePath(frameworkRoot, PACKAGE_PATHS.CLI, "templates");
|
|
7899
8043
|
} else {
|
|
@@ -8146,6 +8290,48 @@ var init_pathResolver = __esm({
|
|
|
8146
8290
|
}
|
|
8147
8291
|
});
|
|
8148
8292
|
|
|
8293
|
+
// packages/tooling/src/utils/typed-file-operations.ts
|
|
8294
|
+
function readTurboJson(filePath) {
|
|
8295
|
+
if (!pathExists(filePath)) {
|
|
8296
|
+
return null;
|
|
8297
|
+
}
|
|
8298
|
+
const content = readSync(filePath, { format: "json" });
|
|
8299
|
+
if (!content || typeof content !== "object") {
|
|
8300
|
+
throw new DoNotDevError(
|
|
8301
|
+
`Invalid turbo.json: ${filePath}`,
|
|
8302
|
+
DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
|
|
8303
|
+
{ context: { filePath } }
|
|
8304
|
+
);
|
|
8305
|
+
}
|
|
8306
|
+
return content;
|
|
8307
|
+
}
|
|
8308
|
+
function readTsConfigJson(filePath) {
|
|
8309
|
+
if (!pathExists(filePath)) {
|
|
8310
|
+
throw new DoNotDevError(
|
|
8311
|
+
`tsconfig.json not found: ${filePath}`,
|
|
8312
|
+
DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND,
|
|
8313
|
+
{ context: { filePath } }
|
|
8314
|
+
);
|
|
8315
|
+
}
|
|
8316
|
+
const content = readSync(filePath, { format: "json" });
|
|
8317
|
+
if (!content || typeof content !== "object") {
|
|
8318
|
+
throw new DoNotDevError(
|
|
8319
|
+
`Invalid tsconfig.json: ${filePath}`,
|
|
8320
|
+
DO_NOT_DEV_ERROR_CODES.CONFIG_INVALID,
|
|
8321
|
+
{ context: { filePath } }
|
|
8322
|
+
);
|
|
8323
|
+
}
|
|
8324
|
+
return content;
|
|
8325
|
+
}
|
|
8326
|
+
var init_typed_file_operations = __esm({
|
|
8327
|
+
"packages/tooling/src/utils/typed-file-operations.ts"() {
|
|
8328
|
+
"use strict";
|
|
8329
|
+
init_utils();
|
|
8330
|
+
init_pathResolver();
|
|
8331
|
+
init_errors();
|
|
8332
|
+
}
|
|
8333
|
+
});
|
|
8334
|
+
|
|
8149
8335
|
// packages/tooling/src/bundler/utils.ts
|
|
8150
8336
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
8151
8337
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
@@ -8173,18 +8359,7 @@ var init_utils = __esm({
|
|
|
8173
8359
|
}
|
|
8174
8360
|
});
|
|
8175
8361
|
|
|
8176
|
-
// packages/cli/src/bin/commands/create-project.ts
|
|
8177
|
-
init_utils();
|
|
8178
|
-
|
|
8179
|
-
// packages/tooling/src/index.ts
|
|
8180
|
-
init_utils();
|
|
8181
|
-
|
|
8182
|
-
// packages/tooling/src/cli/index.ts
|
|
8183
|
-
init_utils();
|
|
8184
|
-
|
|
8185
8362
|
// packages/tooling/src/utils/cli-input.ts
|
|
8186
|
-
init_utils();
|
|
8187
|
-
init_dist2();
|
|
8188
8363
|
async function askForInput(message, defaultValue = "") {
|
|
8189
8364
|
const result = await he({
|
|
8190
8365
|
message,
|
|
@@ -8225,11 +8400,28 @@ async function askForSelection(message, choices, defaultValue = 0) {
|
|
|
8225
8400
|
}
|
|
8226
8401
|
return result;
|
|
8227
8402
|
}
|
|
8403
|
+
var init_cli_input = __esm({
|
|
8404
|
+
"packages/tooling/src/utils/cli-input.ts"() {
|
|
8405
|
+
"use strict";
|
|
8406
|
+
init_utils();
|
|
8407
|
+
init_dist2();
|
|
8408
|
+
}
|
|
8409
|
+
});
|
|
8410
|
+
|
|
8411
|
+
// packages/cli/src/bin/commands/create-project.ts
|
|
8412
|
+
init_utils();
|
|
8413
|
+
|
|
8414
|
+
// packages/tooling/src/index.ts
|
|
8415
|
+
init_utils();
|
|
8416
|
+
|
|
8417
|
+
// packages/tooling/src/cli/index.ts
|
|
8418
|
+
init_utils();
|
|
8228
8419
|
|
|
8229
8420
|
// packages/tooling/src/utils/create-utils.ts
|
|
8230
8421
|
init_utils();
|
|
8231
8422
|
init_cli_output();
|
|
8232
8423
|
init_pathResolver();
|
|
8424
|
+
init_typed_file_operations();
|
|
8233
8425
|
async function copyTemplateFiles(sourceDir, destDir, replacements) {
|
|
8234
8426
|
if (!pathExists(sourceDir)) {
|
|
8235
8427
|
log.warn(`Warning: Template directory does not exist: ${sourceDir}`);
|
|
@@ -8414,12 +8606,7 @@ async function mergeRootTsConfig(rootDir, allAppNames, includeFunctions = false)
|
|
|
8414
8606
|
return;
|
|
8415
8607
|
}
|
|
8416
8608
|
try {
|
|
8417
|
-
const tsconfig =
|
|
8418
|
-
if (!tsconfig) {
|
|
8419
|
-
throw new Error(
|
|
8420
|
-
`tsconfig.json is empty or invalid JSON at ${tsconfigPath}`
|
|
8421
|
-
);
|
|
8422
|
-
}
|
|
8609
|
+
const tsconfig = readTsConfigJson(tsconfigPath);
|
|
8423
8610
|
tsconfig.references = tsconfig.references || [];
|
|
8424
8611
|
const existingPaths = new Set(
|
|
8425
8612
|
tsconfig.references.map((ref) => ref.path)
|
|
@@ -8453,7 +8640,7 @@ async function mergeRootTurboJson(rootDir) {
|
|
|
8453
8640
|
return;
|
|
8454
8641
|
}
|
|
8455
8642
|
try {
|
|
8456
|
-
const turboJson =
|
|
8643
|
+
const turboJson = readTurboJson(turboJsonPath);
|
|
8457
8644
|
if (!turboJson) {
|
|
8458
8645
|
throw new Error(
|
|
8459
8646
|
`turbo.json is empty or invalid JSON at ${turboJsonPath}`
|
|
@@ -8505,7 +8692,7 @@ async function mergeRootTurboJson(rootDir) {
|
|
|
8505
8692
|
}
|
|
8506
8693
|
} catch (error2) {
|
|
8507
8694
|
log.warn(
|
|
8508
|
-
`Warning: Could not merge root turbo.json: ${error2.message
|
|
8695
|
+
`Warning: Could not merge root turbo.json: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
8509
8696
|
);
|
|
8510
8697
|
}
|
|
8511
8698
|
}
|
|
@@ -8601,6 +8788,10 @@ var APP_QUESTIONNAIRE = [
|
|
|
8601
8788
|
{
|
|
8602
8789
|
title: "Next.js \u2014 Static content/SEO (SSR, SSG) \u2014 BETA",
|
|
8603
8790
|
value: "nextjs"
|
|
8791
|
+
},
|
|
8792
|
+
{
|
|
8793
|
+
title: "Expo \u2014 Mobile app (iOS + Android)",
|
|
8794
|
+
value: "expo"
|
|
8604
8795
|
}
|
|
8605
8796
|
]
|
|
8606
8797
|
},
|
|
@@ -8627,6 +8818,10 @@ var APP_QUESTIONNAIRE = [
|
|
|
8627
8818
|
{
|
|
8628
8819
|
title: "Vercel \u2014 Serverless functions (edge + node.js)",
|
|
8629
8820
|
value: "vercel"
|
|
8821
|
+
},
|
|
8822
|
+
{
|
|
8823
|
+
title: "Supabase \u2014 Postgres + Auth + Storage",
|
|
8824
|
+
value: "supabase"
|
|
8630
8825
|
}
|
|
8631
8826
|
]
|
|
8632
8827
|
}
|
|
@@ -8693,6 +8888,7 @@ async function runQuestionnaire(questions, initialAnswers, showWIP, askFor) {
|
|
|
8693
8888
|
|
|
8694
8889
|
// packages/tooling/src/scaffolding/create-app.ts
|
|
8695
8890
|
init_utils();
|
|
8891
|
+
init_cli_input();
|
|
8696
8892
|
init_cli_output();
|
|
8697
8893
|
|
|
8698
8894
|
// packages/tooling/src/utils/dependency-resolver.ts
|
|
@@ -8726,6 +8922,15 @@ function generateScripts(templateName, options) {
|
|
|
8726
8922
|
scripts.preview = "next start";
|
|
8727
8923
|
scripts.lint = "eslint src/";
|
|
8728
8924
|
scripts["type-check"] = "tsc --noEmit";
|
|
8925
|
+
} else if (templateName.includes("expo")) {
|
|
8926
|
+
scripts.dev = "expo start";
|
|
8927
|
+
scripts.start = "expo start";
|
|
8928
|
+
scripts.android = "expo start --android";
|
|
8929
|
+
scripts.ios = "expo start --ios";
|
|
8930
|
+
scripts.web = "expo start --web";
|
|
8931
|
+
scripts.build = "expo export";
|
|
8932
|
+
scripts.lint = "eslint .";
|
|
8933
|
+
scripts["type-check"] = "tsc --noEmit";
|
|
8729
8934
|
} else if (templateName === "consumer-root") {
|
|
8730
8935
|
scripts.dev = "turbo run dev";
|
|
8731
8936
|
scripts.build = "turbo run build";
|
|
@@ -8814,7 +9019,7 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
8814
9019
|
result.main = "./index.ts";
|
|
8815
9020
|
result.types = "./index.ts";
|
|
8816
9021
|
}
|
|
8817
|
-
if (templateName.includes("vite") || templateName.includes("nextjs") || templateName.includes("functions")) {
|
|
9022
|
+
if (templateName.includes("vite") || templateName.includes("nextjs") || templateName.includes("expo") || templateName.includes("functions")) {
|
|
8818
9023
|
if (!dependencies.entities) {
|
|
8819
9024
|
dependencies.entities = "workspace:*";
|
|
8820
9025
|
}
|
|
@@ -8862,6 +9067,40 @@ function generatePackageJson(templateName, mode, options = {}) {
|
|
|
8862
9067
|
// packages/tooling/src/scaffolding/create-app.ts
|
|
8863
9068
|
init_pathResolver();
|
|
8864
9069
|
init_pathResolver();
|
|
9070
|
+
|
|
9071
|
+
// packages/tooling/src/scaffolding/scaffold-matrix.ts
|
|
9072
|
+
init_utils();
|
|
9073
|
+
var MATRIX = [
|
|
9074
|
+
{ builder: "vite", backend: "none", baseTemplate: "app-vite", overlay: null, deployConfig: null, functionsTemplate: null },
|
|
9075
|
+
{ builder: "vite", backend: "firebase", baseTemplate: "app-vite", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
|
|
9076
|
+
{ builder: "vite", backend: "supabase", baseTemplate: "app-vite", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: null },
|
|
9077
|
+
{ builder: "vite", backend: "vercel", baseTemplate: "app-vite", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
|
|
9078
|
+
{ builder: "nextjs", backend: "none", baseTemplate: "app-next", overlay: null, deployConfig: null, functionsTemplate: null },
|
|
9079
|
+
{ builder: "nextjs", backend: "firebase", baseTemplate: "app-next", overlay: "overlay-firebase", deployConfig: "firebase", functionsTemplate: "functions-firebase" },
|
|
9080
|
+
{ builder: "nextjs", backend: "supabase", baseTemplate: "app-next", overlay: "overlay-supabase", deployConfig: "vercel-supabase", functionsTemplate: null },
|
|
9081
|
+
{ builder: "nextjs", backend: "vercel", baseTemplate: "app-next", overlay: "overlay-vercel", deployConfig: "vercel-vercel", functionsTemplate: "functions-vercel" },
|
|
9082
|
+
{ builder: "expo", backend: "none", baseTemplate: "app-expo", overlay: null, deployConfig: null, functionsTemplate: null },
|
|
9083
|
+
{ builder: "expo", backend: "firebase", baseTemplate: "app-expo", overlay: "overlay-firebase", deployConfig: null, functionsTemplate: "functions-firebase" },
|
|
9084
|
+
{ builder: "expo", backend: "supabase", baseTemplate: "app-expo", overlay: "overlay-supabase", deployConfig: null, functionsTemplate: null },
|
|
9085
|
+
{ builder: "demo", backend: "none", baseTemplate: "app-demo", overlay: null, deployConfig: null, functionsTemplate: null }
|
|
9086
|
+
];
|
|
9087
|
+
function comboKey(builder, backend) {
|
|
9088
|
+
return `${builder}-${backend}`;
|
|
9089
|
+
}
|
|
9090
|
+
var ROWS_BY_KEY = /* @__PURE__ */ new Map();
|
|
9091
|
+
for (const row of MATRIX) {
|
|
9092
|
+
ROWS_BY_KEY.set(comboKey(row.builder, row.backend), row);
|
|
9093
|
+
}
|
|
9094
|
+
function getScaffoldRow(builder, backend) {
|
|
9095
|
+
const key = comboKey(builder, backend);
|
|
9096
|
+
const row = ROWS_BY_KEY.get(key);
|
|
9097
|
+
if (!row) {
|
|
9098
|
+
throw new Error(`Unsupported scaffold combo: ${key}. Supported: ${[...ROWS_BY_KEY.keys()].join(", ")}`);
|
|
9099
|
+
}
|
|
9100
|
+
return row;
|
|
9101
|
+
}
|
|
9102
|
+
|
|
9103
|
+
// packages/tooling/src/scaffolding/create-app.ts
|
|
8865
9104
|
var SHOW_WIP = process.env.SHOW_WIP === "true" || process.argv.includes("--wip");
|
|
8866
9105
|
async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
8867
9106
|
const isInteractive = !appName || !appConfig;
|
|
@@ -8947,14 +9186,19 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
8947
9186
|
const s = Y2();
|
|
8948
9187
|
s.start(`Creating app: ${appName}`);
|
|
8949
9188
|
await ensureDir(appDir);
|
|
8950
|
-
const
|
|
9189
|
+
const builder = appTemplate;
|
|
9190
|
+
const backend = appConfig.needsBackend && appConfig.backendPlatform ? appConfig.backendPlatform : "none";
|
|
9191
|
+
const row = getScaffoldRow(builder, backend);
|
|
9192
|
+
const templateDir = row.baseTemplate;
|
|
8951
9193
|
const firebaseProjectId = (appConfig?.firebaseProjectId ?? "").trim() || appName.toLowerCase().replace(/\s+/g, "-");
|
|
8952
9194
|
const firebaseRegion = appConfig?.firebaseRegion ?? "europe-west1";
|
|
9195
|
+
const backendPlatform = appConfig.backendPlatform ?? "firebase";
|
|
9196
|
+
const deployConfig = row.deployConfig;
|
|
8953
9197
|
const replacements = {
|
|
8954
9198
|
projectName: appName,
|
|
8955
9199
|
appName,
|
|
8956
9200
|
appShortName: appName.toUpperCase().replace(/-/g, " "),
|
|
8957
|
-
includeFunctions: Boolean(
|
|
9201
|
+
includeFunctions: Boolean(row.functionsTemplate),
|
|
8958
9202
|
needsCRUD: Boolean(appConfig.needsCRUD),
|
|
8959
9203
|
setupGithubActions: false,
|
|
8960
9204
|
appNames: [appName],
|
|
@@ -8964,8 +9208,13 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
8964
9208
|
monorepoRelativePath: "../../packages/tooling",
|
|
8965
9209
|
appTemplate,
|
|
8966
9210
|
isNextjs: appTemplate === "nextjs",
|
|
9211
|
+
isExpo: appTemplate === "expo",
|
|
8967
9212
|
YOUR_FIREBASE_PROJECT_ID: firebaseProjectId,
|
|
8968
|
-
YOUR_REGION: firebaseRegion
|
|
9213
|
+
YOUR_REGION: firebaseRegion,
|
|
9214
|
+
backendPlatform,
|
|
9215
|
+
isFirebase: backendPlatform === "firebase",
|
|
9216
|
+
isSupabase: backendPlatform === "supabase",
|
|
9217
|
+
isVercel: backendPlatform === "vercel"
|
|
8969
9218
|
};
|
|
8970
9219
|
const templateSourceDir = joinPath(templatesRoot, templateDir);
|
|
8971
9220
|
const templateFiles = await glob("**/*", {
|
|
@@ -8986,118 +9235,155 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
8986
9235
|
await replacePlaceholders(destPath, replacements);
|
|
8987
9236
|
}
|
|
8988
9237
|
}
|
|
9238
|
+
if (row.overlay) {
|
|
9239
|
+
const overlayDir = joinPath(templatesRoot, row.overlay);
|
|
9240
|
+
if (pathExists(overlayDir)) {
|
|
9241
|
+
const overlayFiles = await glob("**/*", {
|
|
9242
|
+
cwd: overlayDir,
|
|
9243
|
+
dot: true,
|
|
9244
|
+
onlyFiles: true
|
|
9245
|
+
});
|
|
9246
|
+
for (const file of overlayFiles) {
|
|
9247
|
+
if (file.startsWith("env.fragment")) continue;
|
|
9248
|
+
if (file === "vercel.headers.example") continue;
|
|
9249
|
+
if (file === "vercel.json.example") continue;
|
|
9250
|
+
if (file === "src/config/providers.ts.example") {
|
|
9251
|
+
const variantFile = `src/config/providers.${appTemplate}.ts.example`;
|
|
9252
|
+
if (overlayFiles.includes(variantFile)) continue;
|
|
9253
|
+
}
|
|
9254
|
+
const providersVariant = file.match(/^src\/config\/providers\.(\w+)\.ts\.example$/);
|
|
9255
|
+
if (providersVariant) {
|
|
9256
|
+
if (providersVariant[1] !== appTemplate) continue;
|
|
9257
|
+
const destPath2 = joinPath(appDir, "src/config/providers.ts");
|
|
9258
|
+
await ensureDir(getDirname(destPath2));
|
|
9259
|
+
await copy(joinPath(overlayDir, file), destPath2);
|
|
9260
|
+
if (await isTextFile(destPath2)) await replacePlaceholders(destPath2, replacements);
|
|
9261
|
+
continue;
|
|
9262
|
+
}
|
|
9263
|
+
const sourcePath = joinPath(overlayDir, file);
|
|
9264
|
+
let destFileName = file;
|
|
9265
|
+
if (destFileName.endsWith(".example")) {
|
|
9266
|
+
destFileName = destFileName.slice(0, -8);
|
|
9267
|
+
}
|
|
9268
|
+
const destPath = joinPath(appDir, destFileName);
|
|
9269
|
+
await ensureDir(getDirname(destPath));
|
|
9270
|
+
await copy(sourcePath, destPath);
|
|
9271
|
+
if (await isTextFile(destPath)) {
|
|
9272
|
+
await replacePlaceholders(destPath, replacements);
|
|
9273
|
+
}
|
|
9274
|
+
}
|
|
9275
|
+
const fragmentName = appTemplate === "nextjs" ? "env.fragment.nextjs.example" : appTemplate === "expo" ? "env.fragment.expo.example" : "env.fragment.example";
|
|
9276
|
+
const fragmentPath = joinPath(overlayDir, fragmentName);
|
|
9277
|
+
const envPath = joinPath(appDir, ".env");
|
|
9278
|
+
if (pathExists(fragmentPath) && pathExists(envPath)) {
|
|
9279
|
+
const baseEnv = readSync(envPath);
|
|
9280
|
+
const fragment = readSync(fragmentPath);
|
|
9281
|
+
await write(envPath, baseEnv + "\n" + fragment, { overwrite: true });
|
|
9282
|
+
}
|
|
9283
|
+
if (deployConfig === "vercel-supabase") {
|
|
9284
|
+
const vercelPath = joinPath(appDir, "vercel.json");
|
|
9285
|
+
const headersFragmentPath = joinPath(overlayDir, "vercel.headers.example");
|
|
9286
|
+
const fullVercelPath = joinPath(overlayDir, "vercel.json.example");
|
|
9287
|
+
if (pathExists(vercelPath) && pathExists(headersFragmentPath)) {
|
|
9288
|
+
const vercelJson = readSync(vercelPath, { format: "json" });
|
|
9289
|
+
const headersFragment = readSync(headersFragmentPath, { format: "json" });
|
|
9290
|
+
vercelJson.headers = [...vercelJson.headers ?? [], ...headersFragment];
|
|
9291
|
+
await write(vercelPath, vercelJson, { format: "json", overwrite: true });
|
|
9292
|
+
} else if (pathExists(fullVercelPath)) {
|
|
9293
|
+
await copy(fullVercelPath, vercelPath);
|
|
9294
|
+
if (await isTextFile(vercelPath)) await replacePlaceholders(vercelPath, replacements);
|
|
9295
|
+
}
|
|
9296
|
+
}
|
|
9297
|
+
}
|
|
9298
|
+
}
|
|
8989
9299
|
const executionMode = detectExecutionMode();
|
|
8990
9300
|
const templateName = appTemplate === "demo" ? "demo" : executionMode === "development" ? `dev-${appTemplate}` : `consumer-${appTemplate}`;
|
|
8991
9301
|
const packageJson = generatePackageJson(templateName, executionMode, {
|
|
8992
9302
|
appName,
|
|
8993
9303
|
template: appTemplate === "demo" ? "vite" : appTemplate,
|
|
8994
|
-
includeFunctions: Boolean(
|
|
9304
|
+
includeFunctions: Boolean(row.functionsTemplate),
|
|
9305
|
+
platform: appTemplate === "demo" ? void 0 : backendPlatform
|
|
8995
9306
|
});
|
|
8996
9307
|
const packageJsonPath = joinPath(appDir, "package.json");
|
|
8997
9308
|
await write(packageJsonPath, packageJson, {
|
|
8998
9309
|
format: "json",
|
|
8999
9310
|
overwrite: true
|
|
9000
9311
|
});
|
|
9001
|
-
if (
|
|
9002
|
-
const platform = appConfig.backendPlatform;
|
|
9312
|
+
if (row.functionsTemplate) {
|
|
9003
9313
|
const functionsRootDir = joinPath(appDir, "functions");
|
|
9004
|
-
const functionsTemplateName =
|
|
9005
|
-
const
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
templatesRoot,
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
await replacePlaceholders(destPath, {
|
|
9043
|
-
...replacements,
|
|
9044
|
-
APP_NAME: appName
|
|
9045
|
-
});
|
|
9314
|
+
const functionsTemplateName = row.functionsTemplate;
|
|
9315
|
+
const functionsTemplateExists = pathExists(joinPath(templatesRoot, functionsTemplateName));
|
|
9316
|
+
if (!functionsTemplateExists) {
|
|
9317
|
+
log.warn(`Functions template "${functionsTemplateName}" not found \u2014 skipping functions scaffolding.`);
|
|
9318
|
+
} else {
|
|
9319
|
+
const functionsPackageJson = generatePackageJson(
|
|
9320
|
+
functionsTemplateName,
|
|
9321
|
+
executionMode,
|
|
9322
|
+
{ appName, platform: row.functionsTemplate.replace("functions-", "") }
|
|
9323
|
+
);
|
|
9324
|
+
const packageJsonPath2 = joinPath(functionsRootDir, "package.json");
|
|
9325
|
+
await ensureDir(functionsRootDir);
|
|
9326
|
+
await write(packageJsonPath2, functionsPackageJson, {
|
|
9327
|
+
format: "json",
|
|
9328
|
+
overwrite: true
|
|
9329
|
+
});
|
|
9330
|
+
const templateDir2 = joinPath(templatesRoot, functionsTemplateName);
|
|
9331
|
+
const templateFiles2 = await glob("**/*", {
|
|
9332
|
+
cwd: templateDir2,
|
|
9333
|
+
dot: true,
|
|
9334
|
+
onlyFiles: true
|
|
9335
|
+
});
|
|
9336
|
+
for (const file of templateFiles2) {
|
|
9337
|
+
if (file === "package.json.example") continue;
|
|
9338
|
+
const sourcePath = joinPath(templateDir2, file);
|
|
9339
|
+
let destFileName = file;
|
|
9340
|
+
if (destFileName.endsWith(".example")) {
|
|
9341
|
+
destFileName = destFileName.slice(0, -8);
|
|
9342
|
+
}
|
|
9343
|
+
const destPath = joinPath(functionsRootDir, destFileName);
|
|
9344
|
+
await ensureDir(getDirname(destPath));
|
|
9345
|
+
await copy(sourcePath, destPath);
|
|
9346
|
+
if (await isTextFile(destPath)) {
|
|
9347
|
+
await replacePlaceholders(destPath, {
|
|
9348
|
+
...replacements,
|
|
9349
|
+
APP_NAME: appName
|
|
9350
|
+
});
|
|
9351
|
+
}
|
|
9046
9352
|
}
|
|
9047
9353
|
}
|
|
9048
9354
|
}
|
|
9049
9355
|
const deploymentTemplateDir = joinPath(templatesRoot, "root-consumer");
|
|
9050
|
-
|
|
9051
|
-
deploymentTemplateDir,
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9356
|
+
if (deployConfig === "firebase") {
|
|
9357
|
+
const firebaseJsonSource = joinPath(deploymentTemplateDir, "firebase.json.example");
|
|
9358
|
+
if (pathExists(firebaseJsonSource)) {
|
|
9359
|
+
await copy(firebaseJsonSource, joinPath(appDir, "firebase.json"));
|
|
9360
|
+
const firebaseJsonDest = joinPath(appDir, "firebase.json");
|
|
9361
|
+
if (await isTextFile(firebaseJsonDest)) await replacePlaceholders(firebaseJsonDest, replacements);
|
|
9362
|
+
}
|
|
9363
|
+
const firebasercSource = joinPath(deploymentTemplateDir, ".firebaserc.example");
|
|
9364
|
+
if (pathExists(firebasercSource)) {
|
|
9365
|
+
await copy(firebasercSource, joinPath(appDir, ".firebaserc"));
|
|
9366
|
+
const firebasercDest = joinPath(appDir, ".firebaserc");
|
|
9367
|
+
if (await isTextFile(firebasercDest)) await replacePlaceholders(firebasercDest, replacements);
|
|
9368
|
+
}
|
|
9369
|
+
if (row.functionsTemplate === "functions-firebase") {
|
|
9370
|
+
for (const example of ["firestore.rules.example", "firestore.indexes.json.example", "storage.rules.example"]) {
|
|
9371
|
+
const src = joinPath(deploymentTemplateDir, example);
|
|
9372
|
+
if (pathExists(src)) {
|
|
9373
|
+
await copy(src, joinPath(appDir, example.replace(".example", "")));
|
|
9374
|
+
}
|
|
9375
|
+
}
|
|
9059
9376
|
}
|
|
9060
9377
|
}
|
|
9061
|
-
|
|
9062
|
-
deploymentTemplateDir,
|
|
9063
|
-
".firebaserc.example"
|
|
9064
|
-
);
|
|
9065
|
-
if (pathExists(firebasercSource)) {
|
|
9066
|
-
const firebasercDest = joinPath(appDir, ".firebaserc");
|
|
9067
|
-
await copy(firebasercSource, firebasercDest);
|
|
9068
|
-
if (await isTextFile(firebasercDest)) {
|
|
9069
|
-
await replacePlaceholders(firebasercDest, replacements);
|
|
9070
|
-
}
|
|
9071
|
-
}
|
|
9072
|
-
if (appConfig.needsBackend && appConfig.backendPlatform === "firebase") {
|
|
9073
|
-
const rulesFiles = [
|
|
9074
|
-
"firestore.rules.example",
|
|
9075
|
-
"firestore.indexes.json.example",
|
|
9076
|
-
"storage.rules.example"
|
|
9077
|
-
];
|
|
9078
|
-
for (const example of rulesFiles) {
|
|
9079
|
-
const src = joinPath(deploymentTemplateDir, example);
|
|
9080
|
-
if (pathExists(src)) {
|
|
9081
|
-
const destName = example.replace(".example", "");
|
|
9082
|
-
const dest = joinPath(appDir, destName);
|
|
9083
|
-
await copy(src, dest);
|
|
9084
|
-
}
|
|
9085
|
-
}
|
|
9086
|
-
}
|
|
9087
|
-
if (appTemplate === "nextjs" || appConfig.needsBackend && appConfig.backendPlatform === "vercel") {
|
|
9088
|
-
const vercelJsonSource = joinPath(
|
|
9089
|
-
deploymentTemplateDir,
|
|
9090
|
-
"vercel.json.example"
|
|
9091
|
-
);
|
|
9378
|
+
if (deployConfig === "vercel-vercel") {
|
|
9379
|
+
const vercelJsonSource = joinPath(deploymentTemplateDir, "vercel.json.example");
|
|
9092
9380
|
if (pathExists(vercelJsonSource)) {
|
|
9381
|
+
await copy(vercelJsonSource, joinPath(appDir, "vercel.json"));
|
|
9093
9382
|
const vercelJsonDest = joinPath(appDir, "vercel.json");
|
|
9094
|
-
await
|
|
9095
|
-
if (await isTextFile(vercelJsonDest)) {
|
|
9096
|
-
await replacePlaceholders(vercelJsonDest, replacements);
|
|
9097
|
-
}
|
|
9383
|
+
if (await isTextFile(vercelJsonDest)) await replacePlaceholders(vercelJsonDest, replacements);
|
|
9098
9384
|
}
|
|
9099
9385
|
}
|
|
9100
|
-
const backendInfo =
|
|
9386
|
+
const backendInfo = row.functionsTemplate ? ` with ${row.functionsTemplate.replace("functions-", "")} functions` : "";
|
|
9101
9387
|
s.stop(`Created ${appName}${backendInfo}`);
|
|
9102
9388
|
const rootPackageJsonPath = joinPath(workspaceRoot, "package.json");
|
|
9103
9389
|
if (pathExists(rootPackageJsonPath)) {
|
|
@@ -9109,7 +9395,7 @@ async function createApp(appName, appConfig, workspaceRoot, templatesRoot) {
|
|
|
9109
9395
|
}
|
|
9110
9396
|
if (isInteractive) {
|
|
9111
9397
|
Se("\u{1F389} App created successfully!");
|
|
9112
|
-
const firebaseStep =
|
|
9398
|
+
const firebaseStep = row.functionsTemplate === "functions-firebase" ? `2. Set Firebase project: cd apps/${appName} && firebase use --add (or edit .firebaserc)
|
|
9113
9399
|
3. bun install
|
|
9114
9400
|
4. bun run dev` : `2. bun install
|
|
9115
9401
|
3. bun run dev`;
|
|
@@ -9127,9 +9413,28 @@ Happy coding!`,
|
|
|
9127
9413
|
|
|
9128
9414
|
// packages/tooling/src/scaffolding/create-project.ts
|
|
9129
9415
|
init_utils();
|
|
9416
|
+
init_cli_input();
|
|
9130
9417
|
init_cli_output();
|
|
9131
9418
|
init_pathResolver();
|
|
9132
9419
|
var SHOW_WIP2 = process.env.SHOW_WIP === "true" || process.argv.includes("--wip");
|
|
9420
|
+
var BACKEND_CHOICES = [
|
|
9421
|
+
{ title: "None", value: "none" },
|
|
9422
|
+
{
|
|
9423
|
+
title: "Firebase \u2014 Full platform (Auth, Firestore, Storage, Functions, Hosting)",
|
|
9424
|
+
value: "firebase"
|
|
9425
|
+
},
|
|
9426
|
+
{
|
|
9427
|
+
title: "Supabase \u2014 Auth, Postgres, Storage, Functions",
|
|
9428
|
+
value: "supabase"
|
|
9429
|
+
},
|
|
9430
|
+
{
|
|
9431
|
+
title: "Vercel \u2014 Serverless functions + Hosting (e.g. Next.js API routes)",
|
|
9432
|
+
value: "vercel"
|
|
9433
|
+
}
|
|
9434
|
+
];
|
|
9435
|
+
function getDefaultBackendIndex(framework) {
|
|
9436
|
+
return framework === "nextjs" ? 3 : 1;
|
|
9437
|
+
}
|
|
9133
9438
|
function calculateRelativePath(from, to) {
|
|
9134
9439
|
try {
|
|
9135
9440
|
return getRelativePathBetween(from, to).replace(/\\/g, "/");
|
|
@@ -9238,10 +9543,6 @@ async function main(options) {
|
|
|
9238
9543
|
Me("Merge mode: Merging root files, creating new apps", "\u{1F527} Mode");
|
|
9239
9544
|
}
|
|
9240
9545
|
}
|
|
9241
|
-
let installDemoApp = await askForConfirmation(
|
|
9242
|
-
"Would you like to install the demo app? (component showcase)",
|
|
9243
|
-
false
|
|
9244
|
-
);
|
|
9245
9546
|
let appNames = [];
|
|
9246
9547
|
const appConfigs = {};
|
|
9247
9548
|
let anyAppNeedsBackend = false;
|
|
@@ -9269,21 +9570,25 @@ async function main(options) {
|
|
|
9269
9570
|
{
|
|
9270
9571
|
title: "Next.js \u2014 Static content/SEO (SSR, SSG) \u2014 DoNotDev support: BETA",
|
|
9271
9572
|
value: "nextjs"
|
|
9573
|
+
},
|
|
9574
|
+
{
|
|
9575
|
+
title: "Expo \u2014 Mobile app (iOS + Android, single codebase)",
|
|
9576
|
+
value: "expo"
|
|
9272
9577
|
}
|
|
9273
9578
|
],
|
|
9274
9579
|
0
|
|
9275
9580
|
);
|
|
9276
|
-
const
|
|
9277
|
-
`
|
|
9278
|
-
|
|
9581
|
+
const backendValue = await askForSelection(
|
|
9582
|
+
`Backend for "${trimmedName}"?`,
|
|
9583
|
+
[...BACKEND_CHOICES],
|
|
9584
|
+
getDefaultBackendIndex(framework)
|
|
9279
9585
|
);
|
|
9280
|
-
|
|
9281
|
-
|
|
9282
|
-
}
|
|
9586
|
+
const needsBackend = backendValue !== "none";
|
|
9587
|
+
if (needsBackend) anyAppNeedsBackend = true;
|
|
9283
9588
|
appConfigs[trimmedName] = {
|
|
9284
9589
|
template: framework,
|
|
9285
9590
|
needsBackend,
|
|
9286
|
-
backendPlatform: needsBackend ?
|
|
9591
|
+
backendPlatform: needsBackend ? backendValue : void 0,
|
|
9287
9592
|
needsCRUD: false,
|
|
9288
9593
|
selectedEntities: [],
|
|
9289
9594
|
userAuth: "none",
|
|
@@ -9329,17 +9634,17 @@ async function main(options) {
|
|
|
9329
9634
|
],
|
|
9330
9635
|
0
|
|
9331
9636
|
);
|
|
9332
|
-
const
|
|
9333
|
-
`
|
|
9334
|
-
|
|
9637
|
+
const backendValue = await askForSelection(
|
|
9638
|
+
`Backend for "${trimmedName}"?`,
|
|
9639
|
+
[...BACKEND_CHOICES],
|
|
9640
|
+
getDefaultBackendIndex(framework)
|
|
9335
9641
|
);
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
}
|
|
9642
|
+
const needsBackend = backendValue !== "none";
|
|
9643
|
+
if (needsBackend) anyAppNeedsBackend = true;
|
|
9339
9644
|
appConfigs[trimmedName] = {
|
|
9340
9645
|
template: framework,
|
|
9341
9646
|
needsBackend,
|
|
9342
|
-
backendPlatform: needsBackend ?
|
|
9647
|
+
backendPlatform: needsBackend ? backendValue : void 0,
|
|
9343
9648
|
needsCRUD: false,
|
|
9344
9649
|
selectedEntities: [],
|
|
9345
9650
|
userAuth: "none",
|
|
@@ -9347,6 +9652,10 @@ async function main(options) {
|
|
|
9347
9652
|
features: []
|
|
9348
9653
|
};
|
|
9349
9654
|
}
|
|
9655
|
+
let installDemoApp = await askForConfirmation(
|
|
9656
|
+
"Would you like to install the demo app? (component showcase)",
|
|
9657
|
+
false
|
|
9658
|
+
);
|
|
9350
9659
|
let allAppNames = [...appNames];
|
|
9351
9660
|
let appsToCreate = [];
|
|
9352
9661
|
let appsToSkip = [];
|
|
@@ -9466,12 +9775,14 @@ async function main(options) {
|
|
|
9466
9775
|
overwrite: true
|
|
9467
9776
|
});
|
|
9468
9777
|
const relativeMonorepoPath = executionMode === "development" ? calculateRelativePath(projectDirNormalized, monorepoRoot) : "";
|
|
9778
|
+
const primaryPlatform = Object.values(appConfigs).find((c) => c.backendPlatform)?.backendPlatform ?? "firebase";
|
|
9469
9779
|
const rootPackageJson = generatePackageJson(
|
|
9470
9780
|
"consumer-root",
|
|
9471
9781
|
executionMode,
|
|
9472
9782
|
{
|
|
9473
9783
|
projectName,
|
|
9474
|
-
includeFunctions: anyAppNeedsBackend
|
|
9784
|
+
includeFunctions: anyAppNeedsBackend,
|
|
9785
|
+
platform: primaryPlatform
|
|
9475
9786
|
}
|
|
9476
9787
|
);
|
|
9477
9788
|
const packageJsonPath = joinPath(projectDirNormalized, "package.json");
|
|
@@ -9530,8 +9841,12 @@ async function main(options) {
|
|
|
9530
9841
|
}
|
|
9531
9842
|
}
|
|
9532
9843
|
if (setupGithubActions) {
|
|
9533
|
-
const ciTemplateDir = joinPath(templatesRoot, "github
|
|
9534
|
-
await copyTemplateFiles(
|
|
9844
|
+
const ciTemplateDir = joinPath(templatesRoot, "github");
|
|
9845
|
+
await copyTemplateFiles(
|
|
9846
|
+
ciTemplateDir,
|
|
9847
|
+
projectDirNormalized,
|
|
9848
|
+
rootReplacements
|
|
9849
|
+
);
|
|
9535
9850
|
}
|
|
9536
9851
|
s.stop("Project structure created");
|
|
9537
9852
|
} else {
|