create-better-t-stack 2.50.1-canary.7ebd503f → 2.50.1-canary.9643d88e
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 +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-DG05Vcnx.js → src-B0pvu6Z-.js} +186 -133
- package/package.json +1 -1
- package/templates/addons/ruler/.ruler/bts.md.hbs +24 -14
- package/templates/api/orpc/native/utils/orpc.ts.hbs +5 -1
- package/templates/api/orpc/server/package.json.hbs +1 -3
- package/templates/api/orpc/server/tsconfig.json.hbs +8 -8
- package/templates/api/trpc/native/utils/trpc.ts.hbs +5 -1
- package/templates/api/trpc/server/package.json.hbs +1 -3
- package/templates/api/trpc/server/tsconfig.json.hbs +8 -11
- package/templates/auth/better-auth/server/base/package.json.hbs +1 -4
- package/templates/auth/better-auth/server/base/tsconfig.json.hbs +8 -11
- package/templates/backend/server/base/tsconfig.json.hbs +1 -15
- package/templates/base/tsconfig.base.json.hbs +31 -21
- package/templates/db/base/package.json.hbs +1 -3
- package/templates/db/base/tsconfig.json.hbs +8 -11
- package/templates/extras/bunfig.toml.hbs +1 -1
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -347,21 +347,17 @@ function ensureSingleWebAndNative(frontends) {
|
|
|
347
347
|
if (web.length > 1) exitWithError("Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt, svelte, solid");
|
|
348
348
|
if (native.length > 1) exitWithError("Cannot select multiple native frameworks. Choose only one of: native-nativewind, native-unistyles");
|
|
349
349
|
}
|
|
350
|
-
const FULLSTACK_FRONTENDS$1 = [
|
|
351
|
-
"next",
|
|
352
|
-
"nuxt",
|
|
353
|
-
"svelte",
|
|
354
|
-
"tanstack-start"
|
|
355
|
-
];
|
|
350
|
+
const FULLSTACK_FRONTENDS$1 = ["next"];
|
|
356
351
|
function validateSelfBackendCompatibility(providedFlags, options, config) {
|
|
357
352
|
const backend = config.backend || options.backend;
|
|
358
353
|
const frontends = config.frontend || options.frontend || [];
|
|
359
354
|
if (backend === "self") {
|
|
360
|
-
|
|
361
|
-
if (
|
|
355
|
+
const { web, native } = splitFrontends(frontends);
|
|
356
|
+
if (!(web.length === 1 && FULLSTACK_FRONTENDS$1.includes(web[0]))) exitWithError("Backend 'self' (fullstack) currently only supports Next.js frontend. Please use --frontend next. Support for Nuxt, SvelteKit, and TanStack Start will be added in a future update.");
|
|
357
|
+
if (native.length > 1) exitWithError("Cannot select multiple native frameworks. Choose only one of: native-nativewind, native-unistyles");
|
|
362
358
|
}
|
|
363
359
|
const hasFullstackFrontend = frontends.some((f) => FULLSTACK_FRONTENDS$1.includes(f));
|
|
364
|
-
if (providedFlags.has("backend") && !hasFullstackFrontend && backend === "self") exitWithError("Backend 'self' (fullstack)
|
|
360
|
+
if (providedFlags.has("backend") && !hasFullstackFrontend && backend === "self") exitWithError("Backend 'self' (fullstack) currently only supports Next.js frontend. Please use --frontend next or choose a different backend. Support for Nuxt, SvelteKit, and TanStack Start will be added in a future update.");
|
|
365
361
|
}
|
|
366
362
|
function validateWorkersCompatibility(providedFlags, options, config) {
|
|
367
363
|
if (providedFlags.has("runtime") && options.runtime === "workers" && config.backend && config.backend !== "hono") exitWithError(`Cloudflare Workers runtime (--runtime workers) is only supported with Hono backend (--backend hono). Current backend: ${config.backend}. Please use '--backend hono' or choose a different runtime.`);
|
|
@@ -684,12 +680,7 @@ async function getAuthChoice(auth, hasDatabase, backend, frontend) {
|
|
|
684
680
|
|
|
685
681
|
//#endregion
|
|
686
682
|
//#region src/prompts/backend.ts
|
|
687
|
-
const FULLSTACK_FRONTENDS = [
|
|
688
|
-
"next",
|
|
689
|
-
"nuxt",
|
|
690
|
-
"svelte",
|
|
691
|
-
"tanstack-start"
|
|
692
|
-
];
|
|
683
|
+
const FULLSTACK_FRONTENDS = ["next"];
|
|
693
684
|
async function getBackendFrameworkChoice(backendFramework, frontends) {
|
|
694
685
|
if (backendFramework !== void 0) return backendFramework;
|
|
695
686
|
const hasIncompatibleFrontend = frontends?.some((f) => f === "solid");
|
|
@@ -1776,6 +1767,12 @@ function validateBackendNoneConstraints(config, providedFlags) {
|
|
|
1776
1767
|
if (has("dbSetup") && config.dbSetup !== "none") exitWithError("Backend 'none' requires '--db-setup none'. Please remove the --db-setup flag or set it to 'none'.");
|
|
1777
1768
|
if (has("serverDeploy") && config.serverDeploy !== "none") exitWithError("Backend 'none' requires '--server-deploy none'. Please remove the --server-deploy flag or set it to 'none'.");
|
|
1778
1769
|
}
|
|
1770
|
+
function validateSelfBackendConstraints(config, providedFlags) {
|
|
1771
|
+
const { backend } = config;
|
|
1772
|
+
if (backend !== "self") return;
|
|
1773
|
+
const has = (k) => providedFlags.has(k);
|
|
1774
|
+
if (has("runtime") && config.runtime !== "none") exitWithError("Backend 'self' (fullstack) requires '--runtime none'. Please remove the --runtime flag or set it to 'none'.");
|
|
1775
|
+
}
|
|
1779
1776
|
function validateBackendConstraints(config, providedFlags, options) {
|
|
1780
1777
|
const { backend } = config;
|
|
1781
1778
|
if (config.auth === "clerk" && backend !== "convex") exitWithError("Clerk authentication is only supported with the Convex backend. Please use '--backend convex' or choose a different auth provider.");
|
|
@@ -1814,6 +1811,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
1814
1811
|
validateDatabaseSetup(config, providedFlags);
|
|
1815
1812
|
validateConvexConstraints(config, providedFlags);
|
|
1816
1813
|
validateBackendNoneConstraints(config, providedFlags);
|
|
1814
|
+
validateSelfBackendConstraints(config, providedFlags);
|
|
1817
1815
|
validateBackendConstraints(config, providedFlags, options);
|
|
1818
1816
|
validateFrontendConstraints(config, providedFlags);
|
|
1819
1817
|
validateApiConstraints(config, options);
|
|
@@ -3155,25 +3153,29 @@ async function setupDockerComposeTemplates(projectDir, context) {
|
|
|
3155
3153
|
if (await fs.pathExists(dockerSrcDir)) await processAndCopyFiles("**/*", dockerSrcDir, dbPackageDir, context);
|
|
3156
3154
|
}
|
|
3157
3155
|
async function setupDeploymentTemplates(projectDir, context) {
|
|
3158
|
-
|
|
3156
|
+
const isBackendSelf = context.backend === "self";
|
|
3157
|
+
if (context.webDeploy === "alchemy" || context.serverDeploy === "alchemy") {
|
|
3159
3158
|
const alchemyTemplateSrc = path.join(PKG_ROOT, "templates/deploy/alchemy");
|
|
3160
|
-
if (
|
|
3161
|
-
await
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
await
|
|
3176
|
-
|
|
3159
|
+
if (context.webDeploy === "alchemy" && (context.serverDeploy === "alchemy" || isBackendSelf)) {
|
|
3160
|
+
if (await fs.pathExists(alchemyTemplateSrc)) {
|
|
3161
|
+
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, projectDir, context);
|
|
3162
|
+
await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
|
|
3163
|
+
}
|
|
3164
|
+
} else {
|
|
3165
|
+
if (context.webDeploy === "alchemy") {
|
|
3166
|
+
const webAppDir = path.join(projectDir, "apps/web");
|
|
3167
|
+
if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(webAppDir)) {
|
|
3168
|
+
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, webAppDir, context);
|
|
3169
|
+
await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
if (context.serverDeploy === "alchemy" && !isBackendSelf) {
|
|
3173
|
+
const serverAppDir = path.join(projectDir, "apps/server");
|
|
3174
|
+
if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(serverAppDir)) {
|
|
3175
|
+
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
3176
|
+
await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
3177
|
+
await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
|
|
3178
|
+
}
|
|
3177
3179
|
}
|
|
3178
3180
|
}
|
|
3179
3181
|
}
|
|
@@ -3196,7 +3198,7 @@ async function setupDeploymentTemplates(projectDir, context) {
|
|
|
3196
3198
|
}
|
|
3197
3199
|
}
|
|
3198
3200
|
}
|
|
3199
|
-
if (context.serverDeploy !== "none" && context.serverDeploy !== "alchemy") {
|
|
3201
|
+
if (context.serverDeploy !== "none" && context.serverDeploy !== "alchemy" && !isBackendSelf) {
|
|
3200
3202
|
const serverAppDir = path.join(projectDir, "apps/server");
|
|
3201
3203
|
if (await fs.pathExists(serverAppDir)) {
|
|
3202
3204
|
const deployTemplateSrc = path.join(PKG_ROOT, `templates/deploy/${context.serverDeploy}/server`);
|
|
@@ -3204,6 +3206,18 @@ async function setupDeploymentTemplates(projectDir, context) {
|
|
|
3204
3206
|
}
|
|
3205
3207
|
}
|
|
3206
3208
|
}
|
|
3209
|
+
async function addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc) {
|
|
3210
|
+
for (const packageName of [
|
|
3211
|
+
"packages/api",
|
|
3212
|
+
"packages/auth",
|
|
3213
|
+
"packages/db"
|
|
3214
|
+
]) {
|
|
3215
|
+
const packageDir = path.join(projectDir, packageName);
|
|
3216
|
+
if (await fs.pathExists(packageDir)) await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, packageDir, context);
|
|
3217
|
+
}
|
|
3218
|
+
const serverAppDir = path.join(projectDir, "apps/server");
|
|
3219
|
+
if (await fs.pathExists(serverAppDir)) await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
3220
|
+
}
|
|
3207
3221
|
|
|
3208
3222
|
//#endregion
|
|
3209
3223
|
//#region src/helpers/core/add-addons.ts
|
|
@@ -3269,7 +3283,7 @@ async function setupServerDeploy(config) {
|
|
|
3269
3283
|
serverDir,
|
|
3270
3284
|
packageManager
|
|
3271
3285
|
});
|
|
3272
|
-
} else if (serverDeploy === "alchemy") await setupAlchemyServerDeploy(serverDir, packageManager);
|
|
3286
|
+
} else if (serverDeploy === "alchemy") await setupAlchemyServerDeploy(serverDir, packageManager, projectDir);
|
|
3273
3287
|
}
|
|
3274
3288
|
async function setupWorkersServerDeploy(serverDir, _packageManager) {
|
|
3275
3289
|
const packageJsonPath = path.join(serverDir, "package.json");
|
|
@@ -3306,7 +3320,7 @@ async function generateCloudflareWorkerTypes({ serverDir, packageManager }) {
|
|
|
3306
3320
|
log.warn(`Note: You can manually run 'cd apps/server && ${managerCmd} cf-typegen' in the project directory later`);
|
|
3307
3321
|
}
|
|
3308
3322
|
}
|
|
3309
|
-
async function setupAlchemyServerDeploy(serverDir, _packageManager) {
|
|
3323
|
+
async function setupAlchemyServerDeploy(serverDir, _packageManager, projectDir) {
|
|
3310
3324
|
if (!await fs.pathExists(serverDir)) return;
|
|
3311
3325
|
await addPackageDependency({
|
|
3312
3326
|
devDependencies: [
|
|
@@ -3317,6 +3331,7 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
|
|
|
3317
3331
|
],
|
|
3318
3332
|
projectDir: serverDir
|
|
3319
3333
|
});
|
|
3334
|
+
if (projectDir) await addAlchemyPackagesDependencies$1(projectDir);
|
|
3320
3335
|
const packageJsonPath = path.join(serverDir, "package.json");
|
|
3321
3336
|
if (await fs.pathExists(packageJsonPath)) {
|
|
3322
3337
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
@@ -3329,6 +3344,19 @@ async function setupAlchemyServerDeploy(serverDir, _packageManager) {
|
|
|
3329
3344
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
3330
3345
|
}
|
|
3331
3346
|
}
|
|
3347
|
+
async function addAlchemyPackagesDependencies$1(projectDir) {
|
|
3348
|
+
for (const packageName of [
|
|
3349
|
+
"packages/api",
|
|
3350
|
+
"packages/auth",
|
|
3351
|
+
"packages/db"
|
|
3352
|
+
]) {
|
|
3353
|
+
const packageDir = path.join(projectDir, packageName);
|
|
3354
|
+
if (await fs.pathExists(packageDir)) await addPackageDependency({
|
|
3355
|
+
devDependencies: ["@cloudflare/workers-types"],
|
|
3356
|
+
projectDir: packageDir
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3332
3360
|
|
|
3333
3361
|
//#endregion
|
|
3334
3362
|
//#region src/helpers/deployment/alchemy/alchemy-next-setup.ts
|
|
@@ -3634,7 +3662,7 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
|
|
|
3634
3662
|
await fs.writeJson(rootPkgPath, pkg, { spaces: 2 });
|
|
3635
3663
|
}
|
|
3636
3664
|
const serverDir = path.join(projectDir, "apps/server");
|
|
3637
|
-
if (await fs.pathExists(serverDir)) await setupAlchemyServerDeploy(serverDir, packageManager);
|
|
3665
|
+
if (await fs.pathExists(serverDir)) await setupAlchemyServerDeploy(serverDir, packageManager, projectDir);
|
|
3638
3666
|
const frontend = config.frontend;
|
|
3639
3667
|
const isNext = frontend.includes("next");
|
|
3640
3668
|
const isNuxt = frontend.includes("nuxt");
|
|
@@ -3867,6 +3895,7 @@ async function setupWebDeploy(config) {
|
|
|
3867
3895
|
if (webDeploy !== "wrangler" && webDeploy !== "alchemy") return;
|
|
3868
3896
|
if (webDeploy === "alchemy" && serverDeploy === "alchemy") {
|
|
3869
3897
|
await setupCombinedAlchemyDeploy(projectDir, packageManager, config);
|
|
3898
|
+
await addAlchemyPackagesDependencies(projectDir);
|
|
3870
3899
|
return;
|
|
3871
3900
|
}
|
|
3872
3901
|
const isNext = frontend.includes("next");
|
|
@@ -3890,6 +3919,7 @@ async function setupWebDeploy(config) {
|
|
|
3890
3919
|
else if (isTanstackRouter) await setupTanStackRouterAlchemyDeploy(projectDir, packageManager);
|
|
3891
3920
|
else if (isReactRouter) await setupReactRouterAlchemyDeploy(projectDir, packageManager);
|
|
3892
3921
|
else if (isSolid) await setupSolidAlchemyDeploy(projectDir, packageManager);
|
|
3922
|
+
await addAlchemyPackagesDependencies(projectDir);
|
|
3893
3923
|
}
|
|
3894
3924
|
}
|
|
3895
3925
|
async function setupWorkersWebDeploy(projectDir, pkgManager) {
|
|
@@ -3907,6 +3937,19 @@ async function setupWorkersWebDeploy(projectDir, pkgManager) {
|
|
|
3907
3937
|
}
|
|
3908
3938
|
await setupWorkersVitePlugin(projectDir);
|
|
3909
3939
|
}
|
|
3940
|
+
async function addAlchemyPackagesDependencies(projectDir) {
|
|
3941
|
+
for (const packageName of [
|
|
3942
|
+
"packages/api",
|
|
3943
|
+
"packages/auth",
|
|
3944
|
+
"packages/db"
|
|
3945
|
+
]) {
|
|
3946
|
+
const packageDir = path.join(projectDir, packageName);
|
|
3947
|
+
if (await fs.pathExists(packageDir)) await addPackageDependency({
|
|
3948
|
+
devDependencies: ["@cloudflare/workers-types"],
|
|
3949
|
+
projectDir: packageDir
|
|
3950
|
+
});
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3910
3953
|
|
|
3911
3954
|
//#endregion
|
|
3912
3955
|
//#region src/helpers/core/add-deployment.ts
|
|
@@ -3966,6 +4009,7 @@ async function setupCatalogs(projectDir, options) {
|
|
|
3966
4009
|
const packagePaths = [
|
|
3967
4010
|
"apps/server",
|
|
3968
4011
|
"apps/web",
|
|
4012
|
+
"apps/native",
|
|
3969
4013
|
"packages/api",
|
|
3970
4014
|
"packages/db",
|
|
3971
4015
|
"packages/auth",
|
|
@@ -4232,7 +4276,7 @@ function getConvexDependencies(frontend) {
|
|
|
4232
4276
|
return deps;
|
|
4233
4277
|
}
|
|
4234
4278
|
async function setupApi(config) {
|
|
4235
|
-
const { api, projectName, frontend, backend, packageManager, projectDir
|
|
4279
|
+
const { api, projectName, frontend, backend, packageManager, projectDir } = config;
|
|
4236
4280
|
const isConvex = backend === "convex";
|
|
4237
4281
|
const webDir = path.join(projectDir, "apps/web");
|
|
4238
4282
|
const nativeDir = path.join(projectDir, "apps/native");
|
|
@@ -4253,40 +4297,14 @@ async function setupApi(config) {
|
|
|
4253
4297
|
dependencies: apiDeps.server.dependencies,
|
|
4254
4298
|
projectDir: webDir
|
|
4255
4299
|
});
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
else if (backend === "elysia") frameworkDeps.push("elysia");
|
|
4259
|
-
else if (backend === "express") frameworkDeps.push("express", "@types/express");
|
|
4260
|
-
else if (backend === "fastify") frameworkDeps.push("fastify");
|
|
4261
|
-
else if (backend === "self") {
|
|
4300
|
+
if (backend === "self") {
|
|
4301
|
+
const frameworkDeps = [];
|
|
4262
4302
|
if (frontend.includes("next")) frameworkDeps.push("next");
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
dependencies: frameworkDeps,
|
|
4266
|
-
projectDir: apiPackageDir
|
|
4267
|
-
});
|
|
4268
|
-
if (api === "trpc") {
|
|
4269
|
-
if (backend === "hono") await addPackageDependency({
|
|
4270
|
-
dependencies: ["@hono/trpc-server"],
|
|
4271
|
-
projectDir: apiPackageDir
|
|
4272
|
-
});
|
|
4273
|
-
else if (backend === "elysia") await addPackageDependency({
|
|
4274
|
-
dependencies: ["@elysiajs/trpc"],
|
|
4275
|
-
projectDir: apiPackageDir
|
|
4276
|
-
});
|
|
4277
|
-
else if (backend === "express") await addPackageDependency({
|
|
4278
|
-
dependencies: ["@trpc/server"],
|
|
4279
|
-
projectDir: apiPackageDir
|
|
4280
|
-
});
|
|
4281
|
-
else if (backend === "fastify") await addPackageDependency({
|
|
4282
|
-
dependencies: ["@trpc/server"],
|
|
4303
|
+
if (frameworkDeps.length > 0) await addPackageDependency({
|
|
4304
|
+
dependencies: frameworkDeps,
|
|
4283
4305
|
projectDir: apiPackageDir
|
|
4284
4306
|
});
|
|
4285
4307
|
}
|
|
4286
|
-
if (auth === "better-auth") await addPackageDependency({
|
|
4287
|
-
dependencies: ["better-auth"],
|
|
4288
|
-
projectDir: apiPackageDir
|
|
4289
|
-
});
|
|
4290
4308
|
}
|
|
4291
4309
|
if (webDirExists && apiDeps.web) await addPackageDependency({
|
|
4292
4310
|
dependencies: apiDeps.web.dependencies,
|
|
@@ -4338,34 +4356,23 @@ async function setupBackendDependencies(config) {
|
|
|
4338
4356
|
const devDependencies = [];
|
|
4339
4357
|
if (framework === "hono") {
|
|
4340
4358
|
dependencies.push("hono");
|
|
4341
|
-
if (
|
|
4342
|
-
if (runtime === "node") {
|
|
4343
|
-
dependencies.push("@hono/node-server");
|
|
4344
|
-
devDependencies.push("tsx", "@types/node");
|
|
4345
|
-
}
|
|
4359
|
+
if (runtime === "node") dependencies.push("@hono/node-server");
|
|
4346
4360
|
} else if (framework === "elysia") {
|
|
4347
4361
|
dependencies.push("elysia", "@elysiajs/cors");
|
|
4348
|
-
if (
|
|
4349
|
-
if (runtime === "node") {
|
|
4350
|
-
dependencies.push("@elysiajs/node");
|
|
4351
|
-
devDependencies.push("tsx", "@types/node");
|
|
4352
|
-
}
|
|
4362
|
+
if (runtime === "node") dependencies.push("@elysiajs/node");
|
|
4353
4363
|
} else if (framework === "express") {
|
|
4354
4364
|
dependencies.push("express", "cors");
|
|
4355
4365
|
devDependencies.push("@types/express", "@types/cors");
|
|
4356
|
-
|
|
4357
|
-
} else if (framework === "fastify") {
|
|
4358
|
-
dependencies.push("fastify", "@fastify/cors");
|
|
4359
|
-
if (runtime === "node") devDependencies.push("tsx", "@types/node");
|
|
4360
|
-
}
|
|
4366
|
+
} else if (framework === "fastify") dependencies.push("fastify", "@fastify/cors");
|
|
4361
4367
|
if (api === "trpc") {
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
else if (
|
|
4368
|
+
dependencies.push("@trpc/server");
|
|
4369
|
+
if (framework === "hono") dependencies.push("@hono/trpc-server");
|
|
4370
|
+
else if (framework === "elysia") dependencies.push("@elysiajs/trpc");
|
|
4365
4371
|
} else if (api === "orpc") dependencies.push("@orpc/server", "@orpc/openapi", "@orpc/zod");
|
|
4366
4372
|
if (auth === "better-auth") dependencies.push("better-auth");
|
|
4367
4373
|
if (examples.includes("ai")) dependencies.push("ai", "@ai-sdk/google");
|
|
4368
|
-
if (runtime === "
|
|
4374
|
+
if (runtime === "node") devDependencies.push("tsx", "@types/node");
|
|
4375
|
+
else if (runtime === "bun") devDependencies.push("@types/bun");
|
|
4369
4376
|
if (dependencies.length > 0 || devDependencies.length > 0) await addPackageDependency({
|
|
4370
4377
|
dependencies,
|
|
4371
4378
|
devDependencies,
|
|
@@ -4626,7 +4633,7 @@ async function setupEnvironmentVariables(config) {
|
|
|
4626
4633
|
const nativeDir = path.join(projectDir, "apps/native");
|
|
4627
4634
|
if (await fs.pathExists(nativeDir)) {
|
|
4628
4635
|
let envVarName = "EXPO_PUBLIC_SERVER_URL";
|
|
4629
|
-
let serverUrl = "http://localhost:3000";
|
|
4636
|
+
let serverUrl = backend === "self" ? "http://localhost:3001" : "http://localhost:3000";
|
|
4630
4637
|
if (backend === "convex") {
|
|
4631
4638
|
envVarName = "EXPO_PUBLIC_CONVEX_URL";
|
|
4632
4639
|
serverUrl = "https://<YOUR_CONVEX_URL>";
|
|
@@ -5995,7 +6002,7 @@ This project uses Convex as a backend. You'll need to set up Convex before runni
|
|
|
5995
6002
|
${packageManagerRunCmd} dev:setup
|
|
5996
6003
|
\`\`\`
|
|
5997
6004
|
|
|
5998
|
-
Follow the prompts to create a new Convex project and connect it to your application.${auth === "clerk" ? " See [Convex + Clerk guide](https://docs.convex.dev/auth/clerk) for auth setup." : ""}` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup, options.serverDeploy)}
|
|
6005
|
+
Follow the prompts to create a new Convex project and connect it to your application.${auth === "clerk" ? " See [Convex + Clerk guide](https://docs.convex.dev/auth/clerk) for auth setup." : ""}` : generateDatabaseSetup(database, auth, packageManagerRunCmd, orm, options.dbSetup, options.serverDeploy, options.backend)}
|
|
5999
6006
|
|
|
6000
6007
|
Then, run the development server:
|
|
6001
6008
|
|
|
@@ -6048,6 +6055,7 @@ function generateRunningInstructions(frontend, backend, webPort, hasNative, isCo
|
|
|
6048
6055
|
const instructions = [];
|
|
6049
6056
|
const hasFrontendNone = frontend.length === 0 || frontend.includes("none");
|
|
6050
6057
|
const isBackendNone = backend === "none";
|
|
6058
|
+
const isBackendSelf = backend === "self";
|
|
6051
6059
|
if (!hasFrontendNone) {
|
|
6052
6060
|
const hasTanstackRouter = frontend.includes("tanstack-router");
|
|
6053
6061
|
const hasReactRouter = frontend.includes("react-router");
|
|
@@ -6056,17 +6064,19 @@ function generateRunningInstructions(frontend, backend, webPort, hasNative, isCo
|
|
|
6056
6064
|
const hasSvelte = frontend.includes("svelte");
|
|
6057
6065
|
const hasNuxt = frontend.includes("nuxt");
|
|
6058
6066
|
const hasSolid = frontend.includes("solid");
|
|
6059
|
-
if (hasTanstackRouter || hasReactRouter || hasNext || hasTanstackStart || hasSvelte || hasNuxt || hasSolid) instructions.push(`Open [http://localhost:${webPort}](http://localhost:${webPort}) in your browser to see
|
|
6067
|
+
if (hasTanstackRouter || hasReactRouter || hasNext || hasTanstackStart || hasSvelte || hasNuxt || hasSolid) if (isBackendSelf) instructions.push(`Open [http://localhost:${webPort}](http://localhost:${webPort}) in your browser to see your fullstack application.`);
|
|
6068
|
+
else instructions.push(`Open [http://localhost:${webPort}](http://localhost:${webPort}) in your browser to see the web application.`);
|
|
6060
6069
|
}
|
|
6061
6070
|
if (hasNative) instructions.push("Use the Expo Go app to run the mobile application.");
|
|
6062
6071
|
if (isConvex) instructions.push("Your app will connect to the Convex cloud backend automatically.");
|
|
6063
|
-
else if (!isBackendNone) instructions.push("The API is running at [http://localhost:3000](http://localhost:3000).");
|
|
6072
|
+
else if (!isBackendNone && !isBackendSelf) instructions.push("The API is running at [http://localhost:3000](http://localhost:3000).");
|
|
6064
6073
|
return instructions.join("\n");
|
|
6065
6074
|
}
|
|
6066
6075
|
function generateProjectStructure(projectName, frontend, backend, addons, isConvex, api, auth) {
|
|
6067
6076
|
const structure = [`${projectName}/`, "├── apps/"];
|
|
6068
6077
|
const hasFrontendNone = frontend.length === 0 || frontend.includes("none");
|
|
6069
6078
|
const isBackendNone = backend === "none";
|
|
6079
|
+
const isBackendSelf = backend === "self";
|
|
6070
6080
|
if (!hasFrontendNone) {
|
|
6071
6081
|
const hasTanstackRouter = frontend.includes("tanstack-router");
|
|
6072
6082
|
const hasReactRouter = frontend.includes("react-router");
|
|
@@ -6084,21 +6094,32 @@ function generateProjectStructure(projectName, frontend, backend, addons, isConv
|
|
|
6084
6094
|
else if (hasSvelte) frontendType = "SvelteKit";
|
|
6085
6095
|
else if (hasNuxt) frontendType = "Nuxt";
|
|
6086
6096
|
else if (hasSolid) frontendType = "SolidJS";
|
|
6087
|
-
structure.push(`│
|
|
6097
|
+
if (isBackendSelf) structure.push(`│ └── web/ # Fullstack application (${frontendType})`);
|
|
6098
|
+
else structure.push(`│ ├── web/ # Frontend application (${frontendType})`);
|
|
6088
6099
|
}
|
|
6089
6100
|
}
|
|
6090
|
-
if (frontend.includes("native-nativewind") || frontend.includes("native-unistyles")) structure.push("│ ├── native/ # Mobile application (React Native, Expo)");
|
|
6091
|
-
|
|
6092
|
-
if (
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
if (auth === "clerk") structure.push("│ ├── convex/ # Convex functions and schema", "│ └── .env.local # Convex environment variables");
|
|
6096
|
-
} else if (!isBackendNone) {
|
|
6101
|
+
if (frontend.includes("native-nativewind") || frontend.includes("native-unistyles")) if (isBackendSelf) structure.push("│ ├── native/ # Mobile application (React Native, Expo)");
|
|
6102
|
+
else structure.push("│ ├── native/ # Mobile application (React Native, Expo)");
|
|
6103
|
+
if (addons.includes("starlight")) if (isBackendSelf) structure.push("│ ├── docs/ # Documentation site (Astro Starlight)");
|
|
6104
|
+
else structure.push("│ ├── docs/ # Documentation site (Astro Starlight)");
|
|
6105
|
+
if (!isBackendSelf && !isBackendNone && !isConvex) {
|
|
6097
6106
|
const backendName = backend[0].toUpperCase() + backend.slice(1);
|
|
6098
6107
|
const apiName = api !== "none" ? api.toUpperCase() : "";
|
|
6099
6108
|
const backendDesc = apiName ? `${backendName}, ${apiName}` : backendName;
|
|
6100
6109
|
structure.push(`│ └── server/ # Backend API (${backendDesc})`);
|
|
6101
6110
|
}
|
|
6111
|
+
if (isConvex || !isBackendNone) {
|
|
6112
|
+
structure.push("├── packages/");
|
|
6113
|
+
if (isConvex) {
|
|
6114
|
+
structure.push("│ ├── backend/ # Convex backend functions and schema");
|
|
6115
|
+
if (auth === "clerk") structure.push("│ │ ├── convex/ # Convex functions and schema", "│ │ └── .env.local # Convex environment variables");
|
|
6116
|
+
}
|
|
6117
|
+
if (!isConvex) {
|
|
6118
|
+
structure.push("│ ├── api/ # API layer / business logic");
|
|
6119
|
+
if (auth !== "none") structure.push("│ ├── auth/ # Authentication configuration & logic");
|
|
6120
|
+
if (api !== "none" || auth !== "none") structure.push("│ └── db/ # Database schema & queries");
|
|
6121
|
+
}
|
|
6122
|
+
}
|
|
6102
6123
|
return structure.join("\n");
|
|
6103
6124
|
}
|
|
6104
6125
|
function generateFeaturesList(database, auth, addons, orm, runtime, frontend, backend, api) {
|
|
@@ -6134,7 +6155,6 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
|
|
|
6134
6155
|
else if (backend === "express") addonsList.push("- **Express** - Fast, unopinionated web framework");
|
|
6135
6156
|
else if (backend === "fastify") addonsList.push("- **Fastify** - Fast, low-overhead web framework");
|
|
6136
6157
|
else if (backend === "elysia") addonsList.push("- **Elysia** - Type-safe, high-performance framework");
|
|
6137
|
-
else if (backend === "next") addonsList.push("- **Next.js** - Full-stack React framework");
|
|
6138
6158
|
if (api === "trpc") addonsList.push("- **tRPC** - End-to-end type-safe APIs");
|
|
6139
6159
|
else if (api === "orpc") addonsList.push("- **oRPC** - End-to-end type-safe APIs with OpenAPI integration");
|
|
6140
6160
|
if (runtime !== "none") addonsList.push(`- **${runtime === "bun" ? "Bun" : runtime === "node" ? "Node.js" : runtime}** - Runtime environment`);
|
|
@@ -6156,33 +6176,36 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
|
|
|
6156
6176
|
else if (addon === "turborepo") addonsList.push("- **Turborepo** - Optimized monorepo build system");
|
|
6157
6177
|
return addonsList.join("\n");
|
|
6158
6178
|
}
|
|
6159
|
-
function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup, serverDeploy) {
|
|
6179
|
+
function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSetup, serverDeploy, backend) {
|
|
6160
6180
|
if (database === "none") return "";
|
|
6181
|
+
const isBackendSelf = backend === "self";
|
|
6182
|
+
const envPath = isBackendSelf ? "apps/web/.env" : "apps/server/.env";
|
|
6183
|
+
const dbLocalPath = isBackendSelf ? "apps/web" : "apps/server";
|
|
6161
6184
|
let setup = "## Database Setup\n\n";
|
|
6162
6185
|
if (database === "sqlite") setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
|
|
6163
6186
|
|
|
6164
6187
|
1. Start the local SQLite database:
|
|
6165
6188
|
${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
|
|
6166
|
-
cd
|
|
6189
|
+
cd ${dbLocalPath} && ${packageManagerRunCmd} db:local
|
|
6167
6190
|
\`\`\`
|
|
6168
6191
|
`}
|
|
6169
6192
|
|
|
6170
|
-
2. Update your \`.env\` file in the
|
|
6193
|
+
2. Update your \`.env\` file in the \`${isBackendSelf ? "apps/web" : "apps/server"}\` directory with the appropriate connection details if needed.
|
|
6171
6194
|
`;
|
|
6172
6195
|
else if (database === "postgres") setup += `This project uses PostgreSQL${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
|
|
6173
6196
|
|
|
6174
6197
|
1. Make sure you have a PostgreSQL database set up.
|
|
6175
|
-
2. Update your \`
|
|
6198
|
+
2. Update your \`${envPath}\` file with your PostgreSQL connection details.
|
|
6176
6199
|
`;
|
|
6177
6200
|
else if (database === "mysql") setup += `This project uses MySQL${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
|
|
6178
6201
|
|
|
6179
6202
|
1. Make sure you have a MySQL database set up.
|
|
6180
|
-
2. Update your \`
|
|
6203
|
+
2. Update your \`${envPath}\` file with your MySQL connection details.
|
|
6181
6204
|
`;
|
|
6182
6205
|
else if (database === "mongodb") setup += `This project uses MongoDB ${orm === "mongoose" ? "with Mongoose" : orm === "prisma" ? "with Prisma ORM" : `with ${orm}`}.
|
|
6183
6206
|
|
|
6184
6207
|
1. Make sure you have MongoDB set up.
|
|
6185
|
-
2. Update your \`
|
|
6208
|
+
2. Update your \`${envPath}\` file with your MongoDB connection URI.
|
|
6186
6209
|
`;
|
|
6187
6210
|
setup += `
|
|
6188
6211
|
3. ${orm === "prisma" ? `Generate the Prisma client and push the schema:
|
|
@@ -6201,13 +6224,14 @@ ${packageManagerRunCmd} db:push
|
|
|
6201
6224
|
function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNative, addons, backend) {
|
|
6202
6225
|
const isConvex = backend === "convex";
|
|
6203
6226
|
const isBackendNone = backend === "none";
|
|
6227
|
+
const isBackendSelf = backend === "self";
|
|
6204
6228
|
let scripts = `- \`${packageManagerRunCmd} dev\`: Start all applications in development mode
|
|
6205
6229
|
- \`${packageManagerRunCmd} build\`: Build all applications`;
|
|
6206
|
-
scripts += `
|
|
6230
|
+
if (!isBackendSelf) scripts += `
|
|
6207
6231
|
- \`${packageManagerRunCmd} dev:web\`: Start only the web application`;
|
|
6208
6232
|
if (isConvex) scripts += `
|
|
6209
6233
|
- \`${packageManagerRunCmd} dev:setup\`: Setup and configure your Convex project`;
|
|
6210
|
-
else if (!isBackendNone) scripts += `
|
|
6234
|
+
else if (!isBackendNone && !isBackendSelf) scripts += `
|
|
6211
6235
|
- \`${packageManagerRunCmd} dev:server\`: Start only the server`;
|
|
6212
6236
|
scripts += `
|
|
6213
6237
|
- \`${packageManagerRunCmd} check-types\`: Check TypeScript types across all apps`;
|
|
@@ -6218,7 +6242,7 @@ function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNati
|
|
|
6218
6242
|
- \`${packageManagerRunCmd} db:push\`: Push schema changes to database
|
|
6219
6243
|
- \`${packageManagerRunCmd} db:studio\`: Open database studio UI`;
|
|
6220
6244
|
if (database === "sqlite" && orm === "drizzle") scripts += `
|
|
6221
|
-
- \`cd apps/server && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
|
|
6245
|
+
- \`cd ${isBackendSelf ? "apps/web" : "apps/server"} && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
|
|
6222
6246
|
}
|
|
6223
6247
|
if (addons.includes("biome")) scripts += `
|
|
6224
6248
|
- \`${packageManagerRunCmd} check\`: Run Biome formatting and linting`;
|
|
@@ -6375,19 +6399,20 @@ async function getDockerStatus(database) {
|
|
|
6375
6399
|
async function displayPostInstallInstructions(config) {
|
|
6376
6400
|
const { api, database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy, serverDeploy } = config;
|
|
6377
6401
|
const isConvex = backend === "convex";
|
|
6402
|
+
const isBackendSelf = backend === "self";
|
|
6378
6403
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager === "pnpm" ? "pnpm run" : "bun run";
|
|
6379
6404
|
const cdCmd = `cd ${relativePath}`;
|
|
6380
6405
|
const hasHuskyOrBiome = addons?.includes("husky") || addons?.includes("biome");
|
|
6381
|
-
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy) : "";
|
|
6406
|
+
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
|
|
6382
6407
|
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
|
|
6383
6408
|
const lintingInstructions = hasHuskyOrBiome ? getLintingInstructions(runCmd) : "";
|
|
6384
|
-
const nativeInstructions = frontend?.includes("native-nativewind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex) : "";
|
|
6409
|
+
const nativeInstructions = frontend?.includes("native-nativewind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex, isBackendSelf) : "";
|
|
6385
6410
|
const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
|
|
6386
6411
|
const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
|
|
6387
6412
|
const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
|
|
6388
|
-
const polarInstructions = config.payments === "polar" && config.auth === "better-auth" ? getPolarInstructions() : "";
|
|
6389
|
-
const wranglerDeployInstructions = getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy);
|
|
6390
|
-
const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy);
|
|
6413
|
+
const polarInstructions = config.payments === "polar" && config.auth === "better-auth" ? getPolarInstructions(backend) : "";
|
|
6414
|
+
const wranglerDeployInstructions = getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
|
|
6415
|
+
const alchemyDeployInstructions = getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend);
|
|
6391
6416
|
const hasWeb = frontend?.some((f) => [
|
|
6392
6417
|
"tanstack-router",
|
|
6393
6418
|
"react-router",
|
|
@@ -6411,7 +6436,8 @@ async function displayPostInstallInstructions(config) {
|
|
|
6411
6436
|
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
|
|
6412
6437
|
output += `${pc.cyan(`${stepCounter++}.`)} Copy environment variables from\n${pc.white(" packages/backend/.env.local")} to ${pc.white("apps/*/.env")}\n`;
|
|
6413
6438
|
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n\n`;
|
|
6414
|
-
} else {
|
|
6439
|
+
} else if (isBackendSelf) output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
|
|
6440
|
+
else {
|
|
6415
6441
|
if (runtime !== "workers") output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
|
|
6416
6442
|
if (runtime === "workers") {
|
|
6417
6443
|
if (dbSetup === "d1") output += `${pc.yellow("IMPORTANT:")} Complete D1 database setup first\n (see Database commands below)\n`;
|
|
@@ -6422,11 +6448,11 @@ async function displayPostInstallInstructions(config) {
|
|
|
6422
6448
|
output += `${pc.bold("Your project will be available at:")}\n`;
|
|
6423
6449
|
if (hasWeb) output += `${pc.cyan("•")} Frontend: http://localhost:${webPort}\n`;
|
|
6424
6450
|
else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
|
|
6425
|
-
if (!isConvex) {
|
|
6451
|
+
if (!isConvex && !isBackendSelf) {
|
|
6426
6452
|
output += `${pc.cyan("•")} Backend API: http://localhost:3000\n`;
|
|
6427
|
-
if (api === "orpc")
|
|
6428
|
-
else output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api\n`;
|
|
6453
|
+
if (api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api\n`;
|
|
6429
6454
|
}
|
|
6455
|
+
if (isBackendSelf && api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:${webPort}/rpc/api\n`;
|
|
6430
6456
|
if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
|
|
6431
6457
|
if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
|
|
6432
6458
|
if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
|
|
@@ -6446,9 +6472,9 @@ async function displayPostInstallInstructions(config) {
|
|
|
6446
6472
|
output += pc.cyan("https://github.com/AmanVarshney01/create-better-t-stack");
|
|
6447
6473
|
consola$1.box(output);
|
|
6448
6474
|
}
|
|
6449
|
-
function getNativeInstructions(isConvex) {
|
|
6475
|
+
function getNativeInstructions(isConvex, isBackendSelf) {
|
|
6450
6476
|
const envVar = isConvex ? "EXPO_PUBLIC_CONVEX_URL" : "EXPO_PUBLIC_SERVER_URL";
|
|
6451
|
-
const exampleUrl = isConvex ? "https://<YOUR_CONVEX_URL>" : "http://<YOUR_LOCAL_IP>:3000";
|
|
6477
|
+
const exampleUrl = isConvex ? "https://<YOUR_CONVEX_URL>" : isBackendSelf ? "http://<YOUR_LOCAL_IP>:3001" : "http://<YOUR_LOCAL_IP>:3000";
|
|
6452
6478
|
const envFileName = ".env";
|
|
6453
6479
|
const ipNote = isConvex ? "your Convex deployment URL (find after running 'dev:setup')" : "your local IP address";
|
|
6454
6480
|
let instructions = `${pc.yellow("NOTE:")} For Expo connectivity issues, update\n apps/native/${envFileName} with ${ipNote}:\n ${`${envVar}=${exampleUrl}`}\n`;
|
|
@@ -6458,7 +6484,7 @@ function getNativeInstructions(isConvex) {
|
|
|
6458
6484
|
function getLintingInstructions(runCmd) {
|
|
6459
6485
|
return `${pc.bold("Linting and formatting:")}\n${pc.cyan("•")} Format and lint fix: ${`${runCmd} check`}\n`;
|
|
6460
6486
|
}
|
|
6461
|
-
async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy) {
|
|
6487
|
+
async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) {
|
|
6462
6488
|
const instructions = [];
|
|
6463
6489
|
if (dbSetup === "docker") {
|
|
6464
6490
|
const dockerStatus = await getDockerStatus(database);
|
|
@@ -6472,8 +6498,9 @@ async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup,
|
|
|
6472
6498
|
const packageManager = runCmd === "npm run" ? "npm" : runCmd || "npm";
|
|
6473
6499
|
instructions.push(`${pc.cyan("1.")} Login to Cloudflare: ${pc.white(`${packageManager} wrangler login`)}`);
|
|
6474
6500
|
instructions.push(`${pc.cyan("2.")} Create D1 database: ${pc.white(`${packageManager} wrangler d1 create your-database-name`)}`);
|
|
6475
|
-
|
|
6476
|
-
instructions.push(`${pc.cyan("
|
|
6501
|
+
const wranglerPath = backend === "self" ? "apps/web" : "apps/server";
|
|
6502
|
+
instructions.push(`${pc.cyan("3.")} Update ${wranglerPath}/wrangler.jsonc with database_id and database_name`);
|
|
6503
|
+
instructions.push(`${pc.cyan("4.")} Generate migrations: ${pc.white(`cd ${wranglerPath} && ${runCmd} db:generate`)}`);
|
|
6477
6504
|
instructions.push(`${pc.cyan("5.")} Apply migrations locally: ${pc.white(`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME --local`)}`);
|
|
6478
6505
|
instructions.push(`${pc.cyan("6.")} Apply migrations to production: ${pc.white(`${packageManager} wrangler d1 migrations apply YOUR_DB_NAME`)}`);
|
|
6479
6506
|
}
|
|
@@ -6497,7 +6524,10 @@ async function getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup,
|
|
|
6497
6524
|
if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
|
|
6498
6525
|
if (dbSetup !== "d1") instructions.push(`${pc.cyan("•")} Apply schema: ${`${runCmd} db:push`}`);
|
|
6499
6526
|
if (!(dbSetup === "d1" && serverDeploy === "alchemy")) instructions.push(`${pc.cyan("•")} Database UI: ${`${runCmd} db:studio`}`);
|
|
6500
|
-
if (database === "sqlite" && dbSetup !== "d1")
|
|
6527
|
+
if (database === "sqlite" && dbSetup !== "d1") {
|
|
6528
|
+
const dbLocalPath = backend === "self" ? "apps/web" : "apps/server";
|
|
6529
|
+
instructions.push(`${pc.cyan("•")} Start local DB (if needed): ${`cd ${dbLocalPath} && ${runCmd} db:local`}`);
|
|
6530
|
+
}
|
|
6501
6531
|
} else if (orm === "mongoose") {
|
|
6502
6532
|
if (dbSetup === "docker") instructions.push(`${pc.cyan("•")} Start docker container: ${`${runCmd} db:start`}`);
|
|
6503
6533
|
} else if (orm === "none") instructions.push(`${pc.yellow("NOTE:")} Manual database schema setup\n required.`);
|
|
@@ -6518,23 +6548,28 @@ function getNoOrmWarning() {
|
|
|
6518
6548
|
function getBunWebNativeWarning() {
|
|
6519
6549
|
return `\n${pc.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo.\n Use 'pnpm' if problems arise.`;
|
|
6520
6550
|
}
|
|
6521
|
-
function getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy) {
|
|
6551
|
+
function getWranglerDeployInstructions(runCmd, webDeploy, serverDeploy, backend) {
|
|
6522
6552
|
const instructions = [];
|
|
6523
|
-
if (webDeploy === "wrangler")
|
|
6524
|
-
|
|
6553
|
+
if (webDeploy === "wrangler") {
|
|
6554
|
+
const deployPath = backend === "self" ? "apps/web" : "apps/web";
|
|
6555
|
+
instructions.push(`${pc.bold("Deploy web to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd ${deployPath} && ${runCmd} run deploy`}`);
|
|
6556
|
+
}
|
|
6557
|
+
if (serverDeploy === "wrangler" && backend !== "self") instructions.push(`${pc.bold("Deploy server to Cloudflare Workers:")}\n${pc.cyan("•")} Deploy: ${`cd apps/server && ${runCmd} run deploy`}`);
|
|
6525
6558
|
return instructions.length ? `\n${instructions.join("\n")}` : "";
|
|
6526
6559
|
}
|
|
6527
6560
|
function getClerkInstructions() {
|
|
6528
6561
|
return `${pc.bold("Clerk Authentication Setup:")}\n${pc.cyan("•")} Follow the guide: ${pc.underline("https://docs.convex.dev/auth/clerk")}\n${pc.cyan("•")} Set CLERK_JWT_ISSUER_DOMAIN in Convex Dashboard\n${pc.cyan("•")} Set CLERK_PUBLISHABLE_KEY in apps/*/.env`;
|
|
6529
6562
|
}
|
|
6530
|
-
function getPolarInstructions() {
|
|
6531
|
-
|
|
6563
|
+
function getPolarInstructions(backend) {
|
|
6564
|
+
const envPath = backend === "self" ? "apps/web/.env" : "apps/server/.env";
|
|
6565
|
+
return `${pc.bold("Polar Payments Setup:")}\n${pc.cyan("•")} Get access token & product ID from ${pc.underline("https://sandbox.polar.sh/")}\n${pc.cyan("•")} Set POLAR_ACCESS_TOKEN in ${envPath}`;
|
|
6532
6566
|
}
|
|
6533
|
-
function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy) {
|
|
6567
|
+
function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend) {
|
|
6534
6568
|
const instructions = [];
|
|
6569
|
+
const isBackendSelf = backend === "self";
|
|
6535
6570
|
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`}`);
|
|
6536
|
-
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`}`);
|
|
6537
|
-
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`}`);
|
|
6571
|
+
else if (serverDeploy === "alchemy" && webDeploy !== "alchemy" && !isBackendSelf) 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`}`);
|
|
6572
|
+
else if (webDeploy === "alchemy" && (serverDeploy === "alchemy" || isBackendSelf)) 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`}`);
|
|
6538
6573
|
return instructions.length ? `\n${instructions.join("\n")}` : "";
|
|
6539
6574
|
}
|
|
6540
6575
|
|
|
@@ -6590,12 +6625,30 @@ async function setupWorkspaceDependencies(projectDir, options) {
|
|
|
6590
6625
|
projectDir: webPackageDir
|
|
6591
6626
|
});
|
|
6592
6627
|
}
|
|
6628
|
+
const nativePackageDir = path.join(projectDir, "apps/native");
|
|
6629
|
+
if (await fs.pathExists(nativePackageDir)) {
|
|
6630
|
+
const nativeDeps = {};
|
|
6631
|
+
nativeDeps[`@${projectName}/api`] = workspaceVersion;
|
|
6632
|
+
if (Object.keys(nativeDeps).length > 0) await addPackageDependency({
|
|
6633
|
+
customDependencies: nativeDeps,
|
|
6634
|
+
projectDir: nativePackageDir
|
|
6635
|
+
});
|
|
6636
|
+
}
|
|
6637
|
+
const runtimeDevDeps = getRuntimeDevDeps(options);
|
|
6593
6638
|
await addPackageDependency({
|
|
6594
6639
|
dependencies: commonDeps,
|
|
6595
|
-
devDependencies: commonDevDeps,
|
|
6640
|
+
devDependencies: [...commonDevDeps, ...runtimeDevDeps],
|
|
6596
6641
|
projectDir
|
|
6597
6642
|
});
|
|
6598
6643
|
}
|
|
6644
|
+
function getRuntimeDevDeps(options) {
|
|
6645
|
+
const { runtime, backend } = options;
|
|
6646
|
+
if (runtime === "none" && backend === "self") return ["@types/node"];
|
|
6647
|
+
if (runtime === "node") return ["@types/node"];
|
|
6648
|
+
if (runtime === "bun") return ["@types/bun"];
|
|
6649
|
+
if (runtime === "workers") return ["@types/node"];
|
|
6650
|
+
return [];
|
|
6651
|
+
}
|
|
6599
6652
|
|
|
6600
6653
|
//#endregion
|
|
6601
6654
|
//#region src/helpers/core/project-config.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.50.1-canary.
|
|
3
|
+
"version": "2.50.1-canary.9643d88e",
|
|
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",
|
|
@@ -8,14 +8,14 @@ This is a monorepo with the following structure:
|
|
|
8
8
|
|
|
9
9
|
{{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
|
|
10
10
|
(includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
|
|
11
|
-
- **`apps/web/`** - Frontend application{{#if (includes frontend "tanstack-router")}} (React with TanStack Router){{else
|
|
11
|
+
- **`apps/web/`** - {{#if (eq backend "self")}}Fullstack application{{else}}Frontend application{{/if}}{{#if (includes frontend "tanstack-router")}} (React with TanStack Router){{else
|
|
12
12
|
if (includes frontend "react-router")}} (React with React Router){{else if (includes frontend "next")}} (Next.js){{else
|
|
13
13
|
if (includes frontend "nuxt")}} (Nuxt.js){{else if (includes frontend "svelte")}} (SvelteKit){{else if (includes
|
|
14
14
|
frontend "solid")}} (SolidStart){{/if}}
|
|
15
15
|
{{/if}}
|
|
16
16
|
|
|
17
17
|
{{#if (ne backend "convex")}}
|
|
18
|
-
{{#if (ne backend "none")}}
|
|
18
|
+
{{#if (and (ne backend "none") (ne backend "self"))}}
|
|
19
19
|
- **`apps/server/`** - Backend server{{#if (eq backend "hono")}} (Hono){{else if (eq backend "express")}}
|
|
20
20
|
(Express){{else if (eq backend "fastify")}} (Fastify){{else if (eq backend "elysia")}} (Elysia){{else if (eq backend
|
|
21
21
|
"next")}} (Next.js API){{/if}}
|
|
@@ -24,6 +24,18 @@ frontend "solid")}} (SolidStart){{/if}}
|
|
|
24
24
|
- **`packages/backend/`** - Convex backend functions
|
|
25
25
|
{{/if}}
|
|
26
26
|
|
|
27
|
+
{{#if (or (ne backend "none") (ne backend "convex"))}}
|
|
28
|
+
{{#if (ne api "none")}}
|
|
29
|
+
- **`packages/api/`** - Shared API logic and types
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if (and (ne auth "none") (ne backend "convex"))}}
|
|
32
|
+
- **`packages/auth/`** - Authentication logic and utilities
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{#if (and (ne database "none") (ne orm "none") (ne backend "convex"))}}
|
|
35
|
+
- **`packages/db/`** - Database schema and utilities
|
|
36
|
+
{{/if}}
|
|
37
|
+
{{/if}}
|
|
38
|
+
|
|
27
39
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
28
40
|
- **`apps/native/`** - React Native mobile app{{#if (includes frontend "native-nativewind")}} (with NativeWind){{else if
|
|
29
41
|
(includes frontend "native-unistyles")}} (with Unistyles){{/if}}
|
|
@@ -32,15 +44,13 @@ frontend "solid")}} (SolidStart){{/if}}
|
|
|
32
44
|
## Available Scripts
|
|
33
45
|
|
|
34
46
|
- `{{packageManager}} run dev` - Start all apps in development mode
|
|
35
|
-
{{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
|
|
36
|
-
(includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
|
|
47
|
+
{{#if (and (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
|
|
48
|
+
(includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid")) (ne backend "self"))}}
|
|
37
49
|
- `{{packageManager}} run dev:web` - Start only the web app
|
|
38
50
|
{{/if}}
|
|
39
|
-
{{#if (ne backend "none")}}
|
|
40
|
-
{{#if (ne backend "convex")}}
|
|
51
|
+
{{#if (and (ne backend "none") (ne backend "convex") (ne backend "self"))}}
|
|
41
52
|
- `{{packageManager}} run dev:server` - Start only the server
|
|
42
53
|
{{/if}}
|
|
43
|
-
{{/if}}
|
|
44
54
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
45
55
|
- `{{packageManager}} run dev:native` - Start only the native app
|
|
46
56
|
{{/if}}
|
|
@@ -48,7 +58,7 @@ frontend "solid")}} (SolidStart){{/if}}
|
|
|
48
58
|
{{#if (and (ne database "none") (ne orm "none") (ne backend "convex"))}}
|
|
49
59
|
## Database Commands
|
|
50
60
|
|
|
51
|
-
All database operations should be run from the server workspace:
|
|
61
|
+
All database operations should be run from the {{#if (eq backend "self")}}web{{else}}server{{/if}} workspace:
|
|
52
62
|
|
|
53
63
|
- `{{packageManager}} run db:push` - Push schema changes to database
|
|
54
64
|
- `{{packageManager}} run db:studio` - Open database studio
|
|
@@ -57,11 +67,11 @@ All database operations should be run from the server workspace:
|
|
|
57
67
|
- `{{packageManager}} run db:migrate` - Run database migrations
|
|
58
68
|
|
|
59
69
|
{{#if (eq orm "drizzle")}}
|
|
60
|
-
Database schema files are located in `apps/server/src/db/schema/`
|
|
70
|
+
Database schema files are located in {{#if (eq backend "self")}}`apps/web/src/db/schema/`{{else}}`apps/server/src/db/schema/`{{/if}}
|
|
61
71
|
{{else if (eq orm "prisma")}}
|
|
62
|
-
Database schema is located in `apps/server/prisma/schema.prisma`
|
|
72
|
+
Database schema is located in {{#if (eq backend "self")}}`apps/web/prisma/schema.prisma`{{else}}`apps/server/prisma/schema.prisma`{{/if}}
|
|
63
73
|
{{else if (eq orm "mongoose")}}
|
|
64
|
-
Database models are located in `apps/server/src/db/models/`
|
|
74
|
+
Database models are located in {{#if (eq backend "self")}}`apps/web/src/db/models/`{{else}}`apps/server/src/db/models/`{{/if}}
|
|
65
75
|
{{/if}}
|
|
66
76
|
{{/if}}
|
|
67
77
|
|
|
@@ -69,10 +79,10 @@ Database models are located in `apps/server/src/db/models/`
|
|
|
69
79
|
## API Structure
|
|
70
80
|
|
|
71
81
|
{{#if (eq api "trpc")}}
|
|
72
|
-
- tRPC routers are in `apps/server/src/routers/`
|
|
82
|
+
- tRPC routers are in {{#if (eq backend "self")}}`packages/api/src/routers/`{{else}}`apps/server/src/routers/`{{/if}}
|
|
73
83
|
- Client-side tRPC utils are in `apps/web/src/utils/trpc.ts`
|
|
74
84
|
{{else if (eq api "orpc")}}
|
|
75
|
-
- oRPC endpoints are in `apps/server/src/api/`
|
|
85
|
+
- oRPC endpoints are in {{#if (eq backend "self")}}`packages/api/src/api/`{{else}}`apps/server/src/api/`{{/if}}
|
|
76
86
|
- Client-side API utils are in `apps/web/src/utils/api.ts`
|
|
77
87
|
{{/if}}
|
|
78
88
|
{{/if}}
|
|
@@ -82,7 +92,7 @@ Database models are located in `apps/server/src/db/models/`
|
|
|
82
92
|
|
|
83
93
|
Authentication is enabled in this project:
|
|
84
94
|
{{#if (ne backend "convex")}}
|
|
85
|
-
- Server auth logic is in `apps/server/src/lib/auth.ts`
|
|
95
|
+
- Server auth logic is in {{#if (eq backend "self")}}`packages/auth/src/lib/auth.ts`{{else}}`apps/server/src/lib/auth.ts`{{/if}}
|
|
86
96
|
{{#if (or (includes frontend "tanstack-router") (includes frontend "react-router") (includes frontend "tanstack-start")
|
|
87
97
|
(includes frontend "next") (includes frontend "nuxt") (includes frontend "svelte") (includes frontend "solid"))}}
|
|
88
98
|
- Web app auth client is in `apps/web/src/lib/auth-client.ts`
|
|
@@ -2,7 +2,7 @@ import { createORPCClient } from "@orpc/client";
|
|
|
2
2
|
import { RPCLink } from "@orpc/client/fetch";
|
|
3
3
|
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
|
|
4
4
|
import { QueryCache, QueryClient } from "@tanstack/react-query";
|
|
5
|
-
import type { AppRouterClient } from "
|
|
5
|
+
import type { AppRouterClient } from "@{{projectName}}/api/routers/index";
|
|
6
6
|
{{#if (eq auth "better-auth")}}
|
|
7
7
|
import { authClient } from "@/lib/auth-client";
|
|
8
8
|
{{/if}}
|
|
@@ -16,7 +16,11 @@ export const queryClient = new QueryClient({
|
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
export const link = new RPCLink({
|
|
19
|
+
{{#if (eq backend "self")}}
|
|
20
|
+
url: `${process.env.EXPO_PUBLIC_SERVER_URL}/api/rpc`,
|
|
21
|
+
{{else}}
|
|
19
22
|
url: `${process.env.EXPO_PUBLIC_SERVER_URL}/rpc`,
|
|
23
|
+
{{/if}}
|
|
20
24
|
{{#if (eq auth "better-auth")}}
|
|
21
25
|
headers() {
|
|
22
26
|
const headers = new Map<string, string>();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"composite": true
|
|
9
|
+
}
|
|
10
10
|
}
|
|
@@ -4,14 +4,18 @@ import { authClient } from "@/lib/auth-client";
|
|
|
4
4
|
import { QueryClient } from "@tanstack/react-query";
|
|
5
5
|
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
|
6
6
|
import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query";
|
|
7
|
-
import type { AppRouter } from "
|
|
7
|
+
import type { AppRouter } from "@{{projectName}}/api/routers/index";
|
|
8
8
|
|
|
9
9
|
export const queryClient = new QueryClient();
|
|
10
10
|
|
|
11
11
|
const trpcClient = createTRPCClient<AppRouter>({
|
|
12
12
|
links: [
|
|
13
13
|
httpBatchLink({
|
|
14
|
+
{{#if (eq backend "self")}}
|
|
15
|
+
url: `${process.env.EXPO_PUBLIC_SERVER_URL}/api/trpc`,
|
|
16
|
+
{{else}}
|
|
14
17
|
url: `${process.env.EXPO_PUBLIC_SERVER_URL}/trpc`,
|
|
18
|
+
{{/if}}
|
|
15
19
|
{{#if (eq auth "better-auth")}}
|
|
16
20
|
headers() {
|
|
17
21
|
const headers = new Map<string, string>();
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"bun"
|
|
11
|
-
]
|
|
12
|
-
}
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"composite": true
|
|
9
|
+
}
|
|
13
10
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"bun"
|
|
11
|
-
]
|
|
12
|
-
}
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"composite": true
|
|
9
|
+
}
|
|
13
10
|
}
|
|
@@ -5,22 +5,8 @@
|
|
|
5
5
|
"outDir": "dist",
|
|
6
6
|
"baseUrl": ".",
|
|
7
7
|
"paths": {
|
|
8
|
-
"@/*": ["./src/*"]
|
|
9
|
-
"prisma": ["node_modules/prisma"]{{/if}}
|
|
8
|
+
"@/*": ["./src/*"]
|
|
10
9
|
},
|
|
11
|
-
"types": [
|
|
12
|
-
{{#if (eq runtime "node")}}
|
|
13
|
-
"node"
|
|
14
|
-
{{else if (eq runtime "bun")}}
|
|
15
|
-
"bun"
|
|
16
|
-
{{else if (eq runtime "workers")}}
|
|
17
|
-
"node"
|
|
18
|
-
{{else}}
|
|
19
|
-
"node",
|
|
20
|
-
"bun"
|
|
21
|
-
{{/if}}{{#if (eq serverDeploy "alchemy")}},
|
|
22
|
-
"@cloudflare/workers-types"{{/if}}
|
|
23
|
-
],
|
|
24
10
|
"jsx": "react-jsx"{{#if (eq backend "hono")}},
|
|
25
11
|
"jsxImportSource": "hono/jsx"{{/if}}
|
|
26
12
|
}
|
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"lib": ["ESNext"],
|
|
8
|
+
"verbatimModuleSyntax": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"allowSyntheticDefaultImports": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noUncheckedIndexedAccess": true,
|
|
17
|
+
"noUnusedLocals": true,
|
|
18
|
+
"noUnusedParameters": true,
|
|
19
|
+
"noFallthroughCasesInSwitch": true,
|
|
20
|
+
"types": [
|
|
21
|
+
{{#if (eq runtime "node")}}
|
|
22
|
+
"node"
|
|
23
|
+
{{else if (eq runtime "bun")}}
|
|
24
|
+
"bun"
|
|
25
|
+
{{else if (eq runtime "workers")}}
|
|
26
|
+
"node"
|
|
27
|
+
{{else}}
|
|
28
|
+
"node"
|
|
29
|
+
{{/if}}{{#if (eq serverDeploy "alchemy")}},
|
|
30
|
+
"@cloudflare/workers-types"{{/if}}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
23
33
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"bun"
|
|
11
|
-
]
|
|
12
|
-
}
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"sourceMap": true,
|
|
7
|
+
"outDir": "dist",
|
|
8
|
+
"composite": true
|
|
9
|
+
}
|
|
13
10
|
}
|