create-better-t-stack 2.36.3-canary.5fe7a73e → 2.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1345,7 +1345,7 @@ const getLatestCLIVersion = () => {
|
|
|
1345
1345
|
*/
|
|
1346
1346
|
function isTelemetryEnabled() {
|
|
1347
1347
|
const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
|
|
1348
|
-
const BTS_TELEMETRY = "
|
|
1348
|
+
const BTS_TELEMETRY = "1";
|
|
1349
1349
|
if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
|
|
1350
1350
|
if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
|
|
1351
1351
|
return true;
|
|
@@ -1353,8 +1353,8 @@ function isTelemetryEnabled() {
|
|
|
1353
1353
|
|
|
1354
1354
|
//#endregion
|
|
1355
1355
|
//#region src/utils/analytics.ts
|
|
1356
|
-
const POSTHOG_API_KEY = "
|
|
1357
|
-
const POSTHOG_HOST = "
|
|
1356
|
+
const POSTHOG_API_KEY = "phc_8ZUxEwwfKMajJLvxz1daGd931dYbQrwKNficBmsdIrs";
|
|
1357
|
+
const POSTHOG_HOST = "https://us.i.posthog.com";
|
|
1358
1358
|
function generateSessionId() {
|
|
1359
1359
|
const rand = Math.random().toString(36).slice(2);
|
|
1360
1360
|
const now = Date.now().toString(36);
|
|
@@ -2350,10 +2350,7 @@ async function setupDeploymentTemplates(projectDir, context) {
|
|
|
2350
2350
|
if (await fs.pathExists(alchemyTemplateSrc)) {
|
|
2351
2351
|
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, projectDir, context);
|
|
2352
2352
|
const serverAppDir = path.join(projectDir, "apps/server");
|
|
2353
|
-
if (await fs.pathExists(serverAppDir))
|
|
2354
|
-
await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2355
|
-
await processAndCopyFiles("wrangler.jsonc.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2356
|
-
}
|
|
2353
|
+
if (await fs.pathExists(serverAppDir)) await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2357
2354
|
}
|
|
2358
2355
|
} else {
|
|
2359
2356
|
if (context.webDeploy === "alchemy") {
|
|
@@ -2367,7 +2364,6 @@ async function setupDeploymentTemplates(projectDir, context) {
|
|
|
2367
2364
|
if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(serverAppDir)) {
|
|
2368
2365
|
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2369
2366
|
await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2370
|
-
await processAndCopyFiles("wrangler.jsonc.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2371
2367
|
}
|
|
2372
2368
|
}
|
|
2373
2369
|
}
|
|
@@ -3000,11 +2996,9 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
|
|
|
3000
2996
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
3001
2997
|
packageJson.scripts = {
|
|
3002
2998
|
...packageJson.scripts,
|
|
3003
|
-
dev: "
|
|
3004
|
-
build: "wrangler deploy --dry-run",
|
|
2999
|
+
dev: "alchemy dev",
|
|
3005
3000
|
deploy: "alchemy deploy",
|
|
3006
|
-
destroy: "alchemy destroy"
|
|
3007
|
-
"alchemy:dev": "alchemy dev"
|
|
3001
|
+
destroy: "alchemy destroy"
|
|
3008
3002
|
};
|
|
3009
3003
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
3010
3004
|
}
|
|
@@ -3012,7 +3006,7 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
|
|
|
3012
3006
|
|
|
3013
3007
|
//#endregion
|
|
3014
3008
|
//#region src/helpers/deployment/alchemy/alchemy-next-setup.ts
|
|
3015
|
-
async function setupNextAlchemyDeploy(projectDir, _packageManager) {
|
|
3009
|
+
async function setupNextAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3016
3010
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3017
3011
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3018
3012
|
await addPackageDependency({
|
|
@@ -3022,11 +3016,11 @@ async function setupNextAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3022
3016
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3023
3017
|
if (await fs.pathExists(pkgPath)) {
|
|
3024
3018
|
const pkg = await fs.readJson(pkgPath);
|
|
3025
|
-
pkg.scripts = {
|
|
3019
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3026
3020
|
...pkg.scripts,
|
|
3027
3021
|
deploy: "alchemy deploy",
|
|
3028
3022
|
destroy: "alchemy destroy",
|
|
3029
|
-
|
|
3023
|
+
dev: "alchemy dev"
|
|
3030
3024
|
};
|
|
3031
3025
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3032
3026
|
}
|
|
@@ -3034,7 +3028,7 @@ async function setupNextAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3034
3028
|
|
|
3035
3029
|
//#endregion
|
|
3036
3030
|
//#region src/helpers/deployment/alchemy/alchemy-nuxt-setup.ts
|
|
3037
|
-
async function setupNuxtAlchemyDeploy(projectDir, _packageManager) {
|
|
3031
|
+
async function setupNuxtAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3038
3032
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3039
3033
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3040
3034
|
await addPackageDependency({
|
|
@@ -3048,11 +3042,11 @@ async function setupNuxtAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3048
3042
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3049
3043
|
if (await fs.pathExists(pkgPath)) {
|
|
3050
3044
|
const pkg = await fs.readJson(pkgPath);
|
|
3051
|
-
pkg.scripts = {
|
|
3045
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3052
3046
|
...pkg.scripts,
|
|
3053
3047
|
deploy: "alchemy deploy",
|
|
3054
3048
|
destroy: "alchemy destroy",
|
|
3055
|
-
|
|
3049
|
+
dev: "alchemy dev"
|
|
3056
3050
|
};
|
|
3057
3051
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3058
3052
|
}
|
|
@@ -3102,112 +3096,29 @@ async function setupNuxtAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3102
3096
|
|
|
3103
3097
|
//#endregion
|
|
3104
3098
|
//#region src/helpers/deployment/alchemy/alchemy-react-router-setup.ts
|
|
3105
|
-
async function setupReactRouterAlchemyDeploy(projectDir, _packageManager) {
|
|
3099
|
+
async function setupReactRouterAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3106
3100
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3107
3101
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3108
3102
|
await addPackageDependency({
|
|
3109
|
-
devDependencies: [
|
|
3110
|
-
"alchemy",
|
|
3111
|
-
"@cloudflare/vite-plugin",
|
|
3112
|
-
"dotenv"
|
|
3113
|
-
],
|
|
3103
|
+
devDependencies: ["alchemy", "dotenv"],
|
|
3114
3104
|
projectDir: webAppDir
|
|
3115
3105
|
});
|
|
3116
3106
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3117
3107
|
if (await fs.pathExists(pkgPath)) {
|
|
3118
3108
|
const pkg = await fs.readJson(pkgPath);
|
|
3119
|
-
pkg.scripts = {
|
|
3109
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3120
3110
|
...pkg.scripts,
|
|
3121
3111
|
deploy: "alchemy deploy",
|
|
3122
3112
|
destroy: "alchemy destroy",
|
|
3123
|
-
|
|
3113
|
+
dev: "alchemy dev"
|
|
3124
3114
|
};
|
|
3125
3115
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3126
3116
|
}
|
|
3127
|
-
const viteConfigPath = path.join(webAppDir, "vite.config.ts");
|
|
3128
|
-
if (await fs.pathExists(viteConfigPath)) try {
|
|
3129
|
-
const project = new Project({ manipulationSettings: {
|
|
3130
|
-
indentationText: IndentationText.TwoSpaces,
|
|
3131
|
-
quoteKind: QuoteKind.Double
|
|
3132
|
-
} });
|
|
3133
|
-
project.addSourceFileAtPath(viteConfigPath);
|
|
3134
|
-
const sourceFile = project.getSourceFileOrThrow(viteConfigPath);
|
|
3135
|
-
const alchemyImport = sourceFile.getImportDeclaration("alchemy/cloudflare/react-router");
|
|
3136
|
-
if (!alchemyImport) sourceFile.addImportDeclaration({
|
|
3137
|
-
moduleSpecifier: "alchemy/cloudflare/react-router",
|
|
3138
|
-
defaultImport: "alchemy"
|
|
3139
|
-
});
|
|
3140
|
-
const exportAssignment = sourceFile.getExportAssignment((d) => !d.isExportEquals());
|
|
3141
|
-
if (!exportAssignment) return;
|
|
3142
|
-
const defineConfigCall = exportAssignment.getExpression();
|
|
3143
|
-
if (!Node.isCallExpression(defineConfigCall) || defineConfigCall.getExpression().getText() !== "defineConfig") return;
|
|
3144
|
-
let configObject = defineConfigCall.getArguments()[0];
|
|
3145
|
-
if (!configObject) configObject = defineConfigCall.addArgument("{}");
|
|
3146
|
-
if (Node.isObjectLiteralExpression(configObject)) {
|
|
3147
|
-
const pluginsProperty = configObject.getProperty("plugins");
|
|
3148
|
-
if (pluginsProperty && Node.isPropertyAssignment(pluginsProperty)) {
|
|
3149
|
-
const initializer = pluginsProperty.getInitializer();
|
|
3150
|
-
if (Node.isArrayLiteralExpression(initializer)) {
|
|
3151
|
-
const hasCloudflarePlugin = initializer.getElements().some((el) => el.getText().includes("cloudflare("));
|
|
3152
|
-
if (!hasCloudflarePlugin) initializer.addElement("alchemy()");
|
|
3153
|
-
}
|
|
3154
|
-
} else if (!pluginsProperty) configObject.addPropertyAssignment({
|
|
3155
|
-
name: "plugins",
|
|
3156
|
-
initializer: "[alchemy()]"
|
|
3157
|
-
});
|
|
3158
|
-
}
|
|
3159
|
-
await project.save();
|
|
3160
|
-
} catch (error) {
|
|
3161
|
-
console.warn("Failed to update vite.config.ts:", error);
|
|
3162
|
-
}
|
|
3163
|
-
const reactRouterConfigPath = path.join(webAppDir, "react-router.config.ts");
|
|
3164
|
-
if (await fs.pathExists(reactRouterConfigPath)) try {
|
|
3165
|
-
const project = new Project({ manipulationSettings: {
|
|
3166
|
-
indentationText: IndentationText.TwoSpaces,
|
|
3167
|
-
quoteKind: QuoteKind.Double
|
|
3168
|
-
} });
|
|
3169
|
-
project.addSourceFileAtPath(reactRouterConfigPath);
|
|
3170
|
-
const sourceFile = project.getSourceFileOrThrow(reactRouterConfigPath);
|
|
3171
|
-
const exportAssignment = sourceFile.getExportAssignment((d) => !d.isExportEquals());
|
|
3172
|
-
if (!exportAssignment) return;
|
|
3173
|
-
const configExpression = exportAssignment.getExpression();
|
|
3174
|
-
let configObject;
|
|
3175
|
-
if (Node.isObjectLiteralExpression(configExpression)) configObject = configExpression;
|
|
3176
|
-
else if (Node.isSatisfiesExpression(configExpression)) {
|
|
3177
|
-
const expression = configExpression.getExpression();
|
|
3178
|
-
if (Node.isObjectLiteralExpression(expression)) configObject = expression;
|
|
3179
|
-
}
|
|
3180
|
-
if (!configObject || !Node.isObjectLiteralExpression(configObject)) return;
|
|
3181
|
-
const futureProperty = configObject.getProperty("future");
|
|
3182
|
-
if (!futureProperty) configObject.addPropertyAssignment({
|
|
3183
|
-
name: "future",
|
|
3184
|
-
initializer: `{
|
|
3185
|
-
unstable_viteEnvironmentApi: true,
|
|
3186
|
-
}`
|
|
3187
|
-
});
|
|
3188
|
-
else if (Node.isPropertyAssignment(futureProperty)) {
|
|
3189
|
-
const futureInitializer = futureProperty.getInitializer();
|
|
3190
|
-
if (Node.isObjectLiteralExpression(futureInitializer)) {
|
|
3191
|
-
const viteEnvApiProp = futureInitializer.getProperty("unstable_viteEnvironmentApi");
|
|
3192
|
-
if (!viteEnvApiProp) futureInitializer.addPropertyAssignment({
|
|
3193
|
-
name: "unstable_viteEnvironmentApi",
|
|
3194
|
-
initializer: "true"
|
|
3195
|
-
});
|
|
3196
|
-
else if (Node.isPropertyAssignment(viteEnvApiProp)) {
|
|
3197
|
-
const value = viteEnvApiProp.getInitializer()?.getText();
|
|
3198
|
-
if (value === "false") viteEnvApiProp.setInitializer("true");
|
|
3199
|
-
}
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
await project.save();
|
|
3203
|
-
} catch (error) {
|
|
3204
|
-
console.warn("Failed to update react-router.config.ts:", error);
|
|
3205
|
-
}
|
|
3206
3117
|
}
|
|
3207
3118
|
|
|
3208
3119
|
//#endregion
|
|
3209
3120
|
//#region src/helpers/deployment/alchemy/alchemy-solid-setup.ts
|
|
3210
|
-
async function setupSolidAlchemyDeploy(projectDir, _packageManager) {
|
|
3121
|
+
async function setupSolidAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3211
3122
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3212
3123
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3213
3124
|
await addPackageDependency({
|
|
@@ -3217,11 +3128,11 @@ async function setupSolidAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3217
3128
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3218
3129
|
if (await fs.pathExists(pkgPath)) {
|
|
3219
3130
|
const pkg = await fs.readJson(pkgPath);
|
|
3220
|
-
pkg.scripts = {
|
|
3131
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3221
3132
|
...pkg.scripts,
|
|
3222
3133
|
deploy: "alchemy deploy",
|
|
3223
3134
|
destroy: "alchemy destroy",
|
|
3224
|
-
|
|
3135
|
+
dev: "alchemy dev"
|
|
3225
3136
|
};
|
|
3226
3137
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3227
3138
|
}
|
|
@@ -3229,7 +3140,7 @@ async function setupSolidAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3229
3140
|
|
|
3230
3141
|
//#endregion
|
|
3231
3142
|
//#region src/helpers/deployment/alchemy/alchemy-svelte-setup.ts
|
|
3232
|
-
async function setupSvelteAlchemyDeploy(projectDir, _packageManager) {
|
|
3143
|
+
async function setupSvelteAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3233
3144
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3234
3145
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3235
3146
|
await addPackageDependency({
|
|
@@ -3243,11 +3154,11 @@ async function setupSvelteAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3243
3154
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3244
3155
|
if (await fs.pathExists(pkgPath)) {
|
|
3245
3156
|
const pkg = await fs.readJson(pkgPath);
|
|
3246
|
-
pkg.scripts = {
|
|
3157
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3247
3158
|
...pkg.scripts,
|
|
3248
3159
|
deploy: "alchemy deploy",
|
|
3249
3160
|
destroy: "alchemy destroy",
|
|
3250
|
-
|
|
3161
|
+
dev: "alchemy dev"
|
|
3251
3162
|
};
|
|
3252
3163
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3253
3164
|
}
|
|
@@ -3300,7 +3211,7 @@ function updateAdapterInConfig(configObject) {
|
|
|
3300
3211
|
|
|
3301
3212
|
//#endregion
|
|
3302
3213
|
//#region src/helpers/deployment/alchemy/alchemy-tanstack-router-setup.ts
|
|
3303
|
-
async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager) {
|
|
3214
|
+
async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3304
3215
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3305
3216
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3306
3217
|
await addPackageDependency({
|
|
@@ -3310,11 +3221,11 @@ async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3310
3221
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3311
3222
|
if (await fs.pathExists(pkgPath)) {
|
|
3312
3223
|
const pkg = await fs.readJson(pkgPath);
|
|
3313
|
-
pkg.scripts = {
|
|
3224
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3314
3225
|
...pkg.scripts,
|
|
3315
3226
|
deploy: "alchemy deploy",
|
|
3316
3227
|
destroy: "alchemy destroy",
|
|
3317
|
-
|
|
3228
|
+
dev: "alchemy dev"
|
|
3318
3229
|
};
|
|
3319
3230
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3320
3231
|
}
|
|
@@ -3322,7 +3233,7 @@ async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3322
3233
|
|
|
3323
3234
|
//#endregion
|
|
3324
3235
|
//#region src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts
|
|
3325
|
-
async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager) {
|
|
3236
|
+
async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, options) {
|
|
3326
3237
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3327
3238
|
if (!await fs.pathExists(webAppDir)) return;
|
|
3328
3239
|
await addPackageDependency({
|
|
@@ -3336,11 +3247,11 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager) {
|
|
|
3336
3247
|
const pkgPath = path.join(webAppDir, "package.json");
|
|
3337
3248
|
if (await fs.pathExists(pkgPath)) {
|
|
3338
3249
|
const pkg = await fs.readJson(pkgPath);
|
|
3339
|
-
pkg.scripts = {
|
|
3250
|
+
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3340
3251
|
...pkg.scripts,
|
|
3341
3252
|
deploy: "alchemy deploy",
|
|
3342
3253
|
destroy: "alchemy destroy",
|
|
3343
|
-
|
|
3254
|
+
dev: "alchemy dev"
|
|
3344
3255
|
};
|
|
3345
3256
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3346
3257
|
}
|
|
@@ -3456,7 +3367,7 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
|
|
|
3456
3367
|
...pkg.scripts,
|
|
3457
3368
|
deploy: "alchemy deploy",
|
|
3458
3369
|
destroy: "alchemy destroy",
|
|
3459
|
-
|
|
3370
|
+
dev: "alchemy dev"
|
|
3460
3371
|
};
|
|
3461
3372
|
await fs.writeJson(rootPkgPath, pkg, { spaces: 2 });
|
|
3462
3373
|
}
|
|
@@ -3470,13 +3381,13 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
|
|
|
3470
3381
|
const isTanstackStart = frontend.includes("tanstack-start");
|
|
3471
3382
|
const isReactRouter = frontend.includes("react-router");
|
|
3472
3383
|
const isSolid = frontend.includes("solid");
|
|
3473
|
-
if (isNext) await setupNextAlchemyDeploy(projectDir, packageManager);
|
|
3474
|
-
else if (isNuxt) await setupNuxtAlchemyDeploy(projectDir, packageManager);
|
|
3475
|
-
else if (isSvelte) await setupSvelteAlchemyDeploy(projectDir, packageManager);
|
|
3476
|
-
else if (isTanstackStart) await setupTanStackStartAlchemyDeploy(projectDir, packageManager);
|
|
3477
|
-
else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager);
|
|
3478
|
-
else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager);
|
|
3479
|
-
else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager);
|
|
3384
|
+
if (isNext) await setupNextAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3385
|
+
else if (isNuxt) await setupNuxtAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3386
|
+
else if (isSvelte) await setupSvelteAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3387
|
+
else if (isTanstackStart) await setupTanStackStartAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3388
|
+
else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3389
|
+
else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3390
|
+
else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager, { skipAppScripts: true });
|
|
3480
3391
|
}
|
|
3481
3392
|
|
|
3482
3393
|
//#endregion
|
|
@@ -5282,7 +5193,7 @@ async function createReadme(projectDir, options) {
|
|
|
5282
5193
|
}
|
|
5283
5194
|
}
|
|
5284
5195
|
function generateReadmeContent(options) {
|
|
5285
|
-
const { projectName, packageManager, database, auth, addons = [], orm = "drizzle", runtime = "bun", frontend = ["tanstack-router"], backend = "hono", api = "trpc" } = options;
|
|
5196
|
+
const { projectName, packageManager, database, auth, addons = [], orm = "drizzle", runtime = "bun", frontend = ["tanstack-router"], backend = "hono", api = "trpc", webDeploy, serverDeploy } = options;
|
|
5286
5197
|
const isConvex = backend === "convex";
|
|
5287
5198
|
const hasReactRouter = frontend.includes("react-router");
|
|
5288
5199
|
const hasNative = frontend.includes("native-nativewind") || frontend.includes("native-unistyles");
|
|
@@ -5315,7 +5226,7 @@ This project uses Convex as a backend. You'll need to set up Convex before runni
|
|
|
5315
5226
|
${packageManagerRunCmd} dev:setup
|
|
5316
5227
|
\`\`\`
|
|
5317
5228
|
|
|
5318
|
-
Follow the prompts to create a new Convex project and connect it to your application.` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup)}
|
|
5229
|
+
Follow the prompts to create a new Convex project and connect it to your application.` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup, options.serverDeploy)}
|
|
5319
5230
|
|
|
5320
5231
|
Then, run the development server:
|
|
5321
5232
|
|
|
@@ -5327,6 +5238,8 @@ ${generateRunningInstructions(frontend, backend, webPort, hasNative, isConvex)}
|
|
|
5327
5238
|
|
|
5328
5239
|
${addons.includes("pwa") && hasReactRouter ? "\n## PWA Support with React Router v7\n\nThere is a known compatibility issue between VitePWA and React Router v7.\nSee: https://github.com/vite-pwa/vite-plugin-pwa/issues/809\n" : ""}
|
|
5329
5240
|
|
|
5241
|
+
${generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy)}
|
|
5242
|
+
|
|
5330
5243
|
## Project Structure
|
|
5331
5244
|
|
|
5332
5245
|
\`\`\`
|
|
@@ -5470,13 +5383,13 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
|
|
|
5470
5383
|
else if (addon === "turborepo") addonsList.push("- **Turborepo** - Optimized monorepo build system");
|
|
5471
5384
|
return addonsList.join("\n");
|
|
5472
5385
|
}
|
|
5473
|
-
function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup) {
|
|
5386
|
+
function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup, serverDeploy) {
|
|
5474
5387
|
if (database === "none") return "";
|
|
5475
5388
|
let setup = "## Database Setup\n\n";
|
|
5476
5389
|
if (database === "sqlite") setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
|
|
5477
5390
|
|
|
5478
5391
|
1. Start the local SQLite database:
|
|
5479
|
-
${dbSetup === "d1" ? "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command." : `\`\`\`bash
|
|
5392
|
+
${dbSetup === "d1" ? serverDeploy === "alchemy" ? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy." : "Local development for a Cloudflare D1 database will already be running as part of the `wrangler dev` command." : `\`\`\`bash
|
|
5480
5393
|
cd apps/server && ${packageManagerRunCmd} db:local
|
|
5481
5394
|
\`\`\`
|
|
5482
5395
|
`}
|
|
@@ -5546,6 +5459,21 @@ function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNati
|
|
|
5546
5459
|
- \`cd apps/docs && ${packageManagerRunCmd} build\`: Build documentation site`;
|
|
5547
5460
|
return scripts;
|
|
5548
5461
|
}
|
|
5462
|
+
function generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy) {
|
|
5463
|
+
const lines = [];
|
|
5464
|
+
if (webDeploy === "alchemy" || serverDeploy === "alchemy") {
|
|
5465
|
+
lines.push("## Deployment (Alchemy)");
|
|
5466
|
+
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") lines.push(`- Web dev: cd apps/web && ${packageManagerRunCmd} dev`, `- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`, `- Web destroy: cd apps/web && ${packageManagerRunCmd} destroy`);
|
|
5467
|
+
if (serverDeploy === "alchemy" && webDeploy !== "alchemy") lines.push(`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`, `- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`, `- Server destroy: cd apps/server && ${packageManagerRunCmd} destroy`);
|
|
5468
|
+
if (webDeploy === "alchemy" && serverDeploy === "alchemy") lines.push(`- Dev: ${packageManagerRunCmd} dev`, `- Deploy: ${packageManagerRunCmd} deploy`, `- Destroy: ${packageManagerRunCmd} destroy`);
|
|
5469
|
+
}
|
|
5470
|
+
if (webDeploy === "wrangler" || serverDeploy === "wrangler") {
|
|
5471
|
+
lines.push("\n## Deployment (Cloudflare Wrangler)");
|
|
5472
|
+
if (webDeploy === "wrangler") lines.push(`- Web deploy: cd apps/web && ${packageManagerRunCmd} deploy`);
|
|
5473
|
+
if (serverDeploy === "wrangler") lines.push(`- Server dev: cd apps/server && ${packageManagerRunCmd} dev`, `- Server deploy: cd apps/server && ${packageManagerRunCmd} deploy`);
|
|
5474
|
+
}
|
|
5475
|
+
return lines.length ? `\n${lines.join("\n")}\n` : "";
|
|
5476
|
+
}
|
|
5549
5477
|
|
|
5550
5478
|
//#endregion
|
|
5551
5479
|
//#region src/helpers/core/git.ts
|
|
@@ -5761,9 +5689,9 @@ function getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy) {
|
|
|
5761
5689
|
}
|
|
5762
5690
|
function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy) {
|
|
5763
5691
|
const instructions = [];
|
|
5764
|
-
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd}
|
|
5765
|
-
else if (serverDeploy === "alchemy" && webDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd}
|
|
5766
|
-
else if (webDeploy === "alchemy" && serverDeploy === "alchemy") instructions.push(`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd}
|
|
5692
|
+
if (webDeploy === "alchemy" && serverDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy web with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/web && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/web && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/web && ${runCmd} destroy`}`);
|
|
5693
|
+
else if (serverDeploy === "alchemy" && webDeploy !== "alchemy") instructions.push(`${pc.bold("Deploy server with Alchemy:")}\n${pc.cyan("•")} Dev: ${`cd apps/server && ${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`cd apps/server && ${runCmd} destroy`}`);
|
|
5694
|
+
else if (webDeploy === "alchemy" && serverDeploy === "alchemy") instructions.push(`${pc.bold("Deploy with Alchemy:")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
|
|
5767
5695
|
return instructions.length ? `\n${instructions.join("\n")}` : "";
|
|
5768
5696
|
}
|
|
5769
5697
|
|
|
@@ -5976,10 +5904,10 @@ async function createProject(options) {
|
|
|
5976
5904
|
if (options.addons.length > 0 && options.addons[0] !== "none") await setupAddons(options);
|
|
5977
5905
|
if (!isConvex && options.auth) await setupAuth(options);
|
|
5978
5906
|
await handleExtras(projectDir, options);
|
|
5979
|
-
await setupWebDeploy(options);
|
|
5980
|
-
await setupServerDeploy(options);
|
|
5981
5907
|
await setupEnvironmentVariables(options);
|
|
5982
5908
|
await updatePackageConfigurations(projectDir, options);
|
|
5909
|
+
await setupWebDeploy(options);
|
|
5910
|
+
await setupServerDeploy(options);
|
|
5983
5911
|
await createReadme(projectDir, options);
|
|
5984
5912
|
await writeBtsConfig(options);
|
|
5985
5913
|
await formatProjectWithBiome(projectDir);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.37.0",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,7 +17,7 @@ import { Vite } from "alchemy/cloudflare";
|
|
|
17
17
|
{{/if}}
|
|
18
18
|
{{/if}}
|
|
19
19
|
{{#if (eq serverDeploy "alchemy")}}
|
|
20
|
-
import { Worker
|
|
20
|
+
import { Worker } from "alchemy/cloudflare";
|
|
21
21
|
{{#if (eq dbSetup "d1")}}
|
|
22
22
|
import { D1Database } from "alchemy/cloudflare";
|
|
23
23
|
{{/if}}
|
|
@@ -44,7 +44,6 @@ await Exec("db-generate", {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
const db = await D1Database("database", {
|
|
47
|
-
name: `${app.name}-${app.stage}-db`,
|
|
48
47
|
migrationsDir: "apps/server/src/db/migrations",
|
|
49
48
|
});
|
|
50
49
|
{{/if}}
|
|
@@ -53,7 +52,6 @@ const db = await D1Database("database", {
|
|
|
53
52
|
{{#if (includes frontend "next")}}
|
|
54
53
|
export const web = await Next("web", {
|
|
55
54
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
56
|
-
name: `${app.name}-${app.stage}-web`,
|
|
57
55
|
bindings: {
|
|
58
56
|
{{#if (eq backend "convex")}}
|
|
59
57
|
NEXT_PUBLIC_CONVEX_URL: process.env.NEXT_PUBLIC_CONVEX_URL || "",
|
|
@@ -68,7 +66,6 @@ export const web = await Next("web", {
|
|
|
68
66
|
{{else if (includes frontend "nuxt")}}
|
|
69
67
|
export const web = await Nuxt("web", {
|
|
70
68
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
71
|
-
name: `${app.name}-${app.stage}-web`,
|
|
72
69
|
bindings: {
|
|
73
70
|
{{#if (eq backend "convex")}}
|
|
74
71
|
NUXT_PUBLIC_CONVEX_URL: process.env.NUXT_PUBLIC_CONVEX_URL || "",
|
|
@@ -83,7 +80,6 @@ export const web = await Nuxt("web", {
|
|
|
83
80
|
{{else if (includes frontend "svelte")}}
|
|
84
81
|
export const web = await SvelteKit("web", {
|
|
85
82
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
86
|
-
name: `${app.name}-${app.stage}-web`,
|
|
87
83
|
bindings: {
|
|
88
84
|
{{#if (eq backend "convex")}}
|
|
89
85
|
PUBLIC_CONVEX_URL: process.env.PUBLIC_CONVEX_URL || "",
|
|
@@ -98,7 +94,6 @@ export const web = await SvelteKit("web", {
|
|
|
98
94
|
{{else if (includes frontend "tanstack-start")}}
|
|
99
95
|
export const web = await TanStackStart("web", {
|
|
100
96
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
101
|
-
name: `${app.name}-${app.stage}-web`,
|
|
102
97
|
bindings: {
|
|
103
98
|
{{#if (eq backend "convex")}}
|
|
104
99
|
VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
|
|
@@ -113,7 +108,6 @@ export const web = await TanStackStart("web", {
|
|
|
113
108
|
{{else if (includes frontend "tanstack-router")}}
|
|
114
109
|
export const web = await Vite("web", {
|
|
115
110
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
116
|
-
name: `${app.name}-${app.stage}-web`,
|
|
117
111
|
assets: "dist",
|
|
118
112
|
bindings: {
|
|
119
113
|
{{#if (eq backend "convex")}}
|
|
@@ -129,7 +123,6 @@ export const web = await Vite("web", {
|
|
|
129
123
|
{{else if (includes frontend "react-router")}}
|
|
130
124
|
export const web = await ReactRouter("web", {
|
|
131
125
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
132
|
-
name: `${app.name}-${app.stage}-web`,
|
|
133
126
|
bindings: {
|
|
134
127
|
{{#if (eq backend "convex")}}
|
|
135
128
|
VITE_CONVEX_URL: process.env.VITE_CONVEX_URL || "",
|
|
@@ -144,7 +137,6 @@ export const web = await ReactRouter("web", {
|
|
|
144
137
|
{{else if (includes frontend "solid")}}
|
|
145
138
|
export const web = await Vite("web", {
|
|
146
139
|
{{#if (eq serverDeploy "alchemy")}}cwd: "apps/web",{{/if}}
|
|
147
|
-
name: `${app.name}-${app.stage}-web`,
|
|
148
140
|
assets: "dist",
|
|
149
141
|
bindings: {
|
|
150
142
|
{{#if (eq backend "convex")}}
|
|
@@ -163,7 +155,6 @@ export const web = await Vite("web", {
|
|
|
163
155
|
{{#if (eq serverDeploy "alchemy")}}
|
|
164
156
|
export const server = await Worker("server", {
|
|
165
157
|
{{#if (eq webDeploy "alchemy")}}cwd: "apps/server",{{/if}}
|
|
166
|
-
name: `${app.name}-${app.stage}`,
|
|
167
158
|
entrypoint: "src/index.ts",
|
|
168
159
|
compatibility: "node",
|
|
169
160
|
bindings: {
|
|
@@ -188,14 +179,8 @@ export const server = await Worker("server", {
|
|
|
188
179
|
port: 3000,
|
|
189
180
|
},
|
|
190
181
|
});
|
|
191
|
-
|
|
192
|
-
await WranglerJson("wrangler", {
|
|
193
|
-
worker: server,
|
|
194
|
-
});
|
|
195
182
|
{{/if}}
|
|
196
183
|
|
|
197
|
-
|
|
198
|
-
|
|
199
184
|
{{#if (and (eq webDeploy "alchemy") (eq serverDeploy "alchemy"))}}
|
|
200
185
|
console.log(`Web -> ${web.url}`);
|
|
201
186
|
console.log(`Server -> ${server.url}`);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// This is a temporary wrangler.jsonc file that will be overwritten by alchemy
|
|
2
|
-
// It's only here so that `wrangler dev` can work or use alchemy dev instead
|
|
3
|
-
{
|
|
4
|
-
"name": "{{projectName}}",
|
|
5
|
-
"main": "src/index.ts",
|
|
6
|
-
"compatibility_date": "2025-08-16",
|
|
7
|
-
"compatibility_flags": [
|
|
8
|
-
"nodejs_compat",
|
|
9
|
-
"nodejs_compat_populate_process_env"
|
|
10
|
-
]
|
|
11
|
-
}
|