create-better-t-stack 3.7.3 → 3.8.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 → cli.mjs} +1 -1
- package/dist/{index.d.ts → index.d.mts} +112 -254
- package/dist/index.mjs +4 -0
- package/dist/{src-b1TtTCMt.js → src-BDXa8gsB.mjs} +221 -371
- package/package.json +18 -17
- package/templates/api/orpc/server/package.json.hbs +0 -3
- package/templates/api/trpc/server/package.json.hbs +1 -4
- package/templates/auth/better-auth/server/base/package.json.hbs +1 -4
- package/templates/backend/convex/packages/backend/convex/README.md +1 -1
- package/templates/backend/convex/packages/backend/convex/{schema.ts → schema.ts.hbs} +2 -0
- package/templates/backend/convex/packages/backend/package.json.hbs +1 -2
- package/templates/backend/server/base/package.json.hbs +1 -3
- package/templates/db/base/package.json.hbs +1 -4
- package/templates/db/drizzle/base/src/schema/index.ts.hbs +7 -0
- package/templates/db/drizzle/mysql/src/index.ts.hbs +8 -0
- package/templates/db/drizzle/postgres/src/index.ts.hbs +8 -4
- package/templates/db/drizzle/sqlite/src/index.ts.hbs +6 -3
- package/templates/examples/todo/convex/packages/backend/convex/todos.ts.hbs +42 -0
- package/templates/frontend/native/bare/package.json.hbs +1 -2
- package/templates/frontend/native/unistyles/package.json.hbs +1 -2
- package/templates/frontend/native/uniwind/package.json.hbs +1 -2
- package/templates/frontend/nuxt/package.json.hbs +0 -1
- package/templates/frontend/react/next/package.json.hbs +6 -6
- package/templates/frontend/react/react-router/package.json.hbs +13 -13
- package/templates/frontend/react/tanstack-router/package.json.hbs +7 -8
- package/templates/frontend/react/tanstack-start/package.json.hbs +8 -9
- package/templates/frontend/solid/package.json.hbs +0 -1
- package/templates/frontend/svelte/package.json.hbs +0 -1
- package/dist/index.js +0 -4
- package/templates/backend/convex/packages/backend/convex/todos.ts +0 -42
- /package/dist/{cli.d.ts → cli.d.mts} +0 -0
- /package/templates/backend/convex/packages/backend/convex/{healthCheck.ts → healthCheck.ts.hbs} +0 -0
- /package/templates/backend/convex/packages/backend/convex/{tsconfig.json → tsconfig.json.hbs} +0 -0
|
@@ -3,11 +3,12 @@ import { autocompleteMultiselect, cancel, confirm, group, groupMultiselect, intr
|
|
|
3
3
|
import { createRouterClient, os } from "@orpc/server";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import { createCli } from "trpc-cli";
|
|
6
|
-
import z
|
|
6
|
+
import z from "zod";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import consola, { consola as consola$1 } from "consola";
|
|
9
9
|
import fs from "fs-extra";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { APISchema, AddonsSchema, AuthSchema, BackendSchema, DatabaseSchema, DatabaseSetupSchema, DirectoryConflictSchema, ExamplesSchema, FrontendSchema, ORMSchema, PackageManagerSchema, PaymentsSchema, ProjectNameSchema, RuntimeSchema, ServerDeploySchema, TemplateSchema, WebDeploySchema } from "@better-t-stack/types";
|
|
11
12
|
import gradient from "gradient-string";
|
|
12
13
|
import * as JSONC from "jsonc-parser";
|
|
13
14
|
import { $, execa } from "execa";
|
|
@@ -62,43 +63,44 @@ function getDefaultConfig() {
|
|
|
62
63
|
}
|
|
63
64
|
const DEFAULT_CONFIG = getDefaultConfig();
|
|
64
65
|
const dependencyVersionMap = {
|
|
65
|
-
|
|
66
|
-
"
|
|
66
|
+
typescript: "^5",
|
|
67
|
+
"better-auth": "1.4.5",
|
|
68
|
+
"@better-auth/expo": "1.4.5",
|
|
67
69
|
"@clerk/nextjs": "^6.31.5",
|
|
68
70
|
"@clerk/clerk-react": "^5.45.0",
|
|
69
71
|
"@clerk/tanstack-react-start": "^0.26.3",
|
|
70
72
|
"@clerk/clerk-expo": "^2.14.25",
|
|
71
|
-
"drizzle-orm": "^0.45.
|
|
73
|
+
"drizzle-orm": "^0.45.1",
|
|
72
74
|
"drizzle-kit": "^0.31.8",
|
|
73
75
|
"@planetscale/database": "^1.19.0",
|
|
74
|
-
"@libsql/client": "
|
|
75
|
-
libsql: "
|
|
76
|
+
"@libsql/client": "0.15.15",
|
|
77
|
+
libsql: "0.5.22",
|
|
76
78
|
"@neondatabase/serverless": "^1.0.2",
|
|
77
79
|
pg: "^8.16.3",
|
|
78
80
|
"@types/pg": "^8.15.6",
|
|
79
81
|
"@types/ws": "^8.18.1",
|
|
80
82
|
ws: "^8.18.3",
|
|
81
83
|
mysql2: "^3.14.0",
|
|
82
|
-
"@prisma/client": "^7.0
|
|
83
|
-
prisma: "^7.0
|
|
84
|
-
"@prisma/adapter-d1": "^7.0
|
|
85
|
-
"@prisma/adapter-neon": "^7.0
|
|
86
|
-
"@prisma/adapter-mariadb": "^7.0
|
|
87
|
-
"@prisma/adapter-libsql": "^7.0
|
|
88
|
-
"@prisma/adapter-better-sqlite3": "^7.0
|
|
89
|
-
"@prisma/adapter-pg": "^7.0
|
|
90
|
-
"@prisma/adapter-planetscale": "^7.0
|
|
84
|
+
"@prisma/client": "^7.1.0",
|
|
85
|
+
prisma: "^7.1.0",
|
|
86
|
+
"@prisma/adapter-d1": "^7.1.0",
|
|
87
|
+
"@prisma/adapter-neon": "^7.1.0",
|
|
88
|
+
"@prisma/adapter-mariadb": "^7.1.0",
|
|
89
|
+
"@prisma/adapter-libsql": "^7.1.0",
|
|
90
|
+
"@prisma/adapter-better-sqlite3": "^7.1.0",
|
|
91
|
+
"@prisma/adapter-pg": "^7.1.0",
|
|
92
|
+
"@prisma/adapter-planetscale": "^7.1.0",
|
|
91
93
|
mongoose: "^8.14.0",
|
|
92
94
|
"vite-plugin-pwa": "^1.0.1",
|
|
93
95
|
"@vite-pwa/assets-generator": "^1.0.0",
|
|
94
96
|
"@tauri-apps/cli": "^2.4.0",
|
|
95
97
|
"@biomejs/biome": "^2.2.0",
|
|
96
|
-
oxlint: "^1.
|
|
98
|
+
oxlint: "^1.32.0",
|
|
97
99
|
husky: "^9.1.7",
|
|
98
100
|
"lint-staged": "^16.1.2",
|
|
99
101
|
tsx: "^4.19.2",
|
|
100
102
|
"@types/node": "^22.13.11",
|
|
101
|
-
"@types/bun": "^1.
|
|
103
|
+
"@types/bun": "^1.3.4",
|
|
102
104
|
"@elysiajs/node": "^1.3.1",
|
|
103
105
|
"@elysiajs/cors": "^1.3.3",
|
|
104
106
|
"@elysiajs/trpc": "^1.1.0",
|
|
@@ -118,17 +120,17 @@ const dependencyVersionMap = {
|
|
|
118
120
|
"@ai-sdk/vue": "^2.0.49",
|
|
119
121
|
"@ai-sdk/svelte": "^3.0.39",
|
|
120
122
|
"@ai-sdk/react": "^2.0.39",
|
|
121
|
-
streamdown: "^1.
|
|
123
|
+
streamdown: "^1.6.10",
|
|
122
124
|
shiki: "^3.12.2",
|
|
123
|
-
"@orpc/server": "^1.
|
|
124
|
-
"@orpc/client": "^1.
|
|
125
|
-
"@orpc/openapi": "^1.
|
|
126
|
-
"@orpc/zod": "^1.
|
|
127
|
-
"@orpc/tanstack-query": "^1.
|
|
128
|
-
"@trpc/tanstack-react-query": "^11.
|
|
129
|
-
"@trpc/server": "^11.
|
|
130
|
-
"@trpc/client": "^11.
|
|
131
|
-
next: "^16.0.
|
|
125
|
+
"@orpc/server": "^1.12.2",
|
|
126
|
+
"@orpc/client": "^1.12.2",
|
|
127
|
+
"@orpc/openapi": "^1.12.2",
|
|
128
|
+
"@orpc/zod": "^1.12.2",
|
|
129
|
+
"@orpc/tanstack-query": "^1.12.2",
|
|
130
|
+
"@trpc/tanstack-react-query": "^11.7.2",
|
|
131
|
+
"@trpc/server": "^11.7.2",
|
|
132
|
+
"@trpc/client": "^11.7.2",
|
|
133
|
+
next: "^16.0.10",
|
|
132
134
|
convex: "^1.29.3",
|
|
133
135
|
"@convex-dev/react-query": "^0.1.0",
|
|
134
136
|
"convex-svelte": "^0.0.12",
|
|
@@ -139,8 +141,8 @@ const dependencyVersionMap = {
|
|
|
139
141
|
"@tanstack/svelte-query-devtools": "^5.85.3",
|
|
140
142
|
"@tanstack/vue-query-devtools": "^5.90.2",
|
|
141
143
|
"@tanstack/vue-query": "^5.90.2",
|
|
142
|
-
"@tanstack/react-query-devtools": "^5.
|
|
143
|
-
"@tanstack/react-query": "^5.
|
|
144
|
+
"@tanstack/react-query-devtools": "^5.91.1",
|
|
145
|
+
"@tanstack/react-query": "^5.90.12",
|
|
144
146
|
"@tanstack/solid-query": "^5.87.4",
|
|
145
147
|
"@tanstack/solid-query-devtools": "^5.87.4",
|
|
146
148
|
"@tanstack/solid-router-devtools": "^1.131.44",
|
|
@@ -150,7 +152,7 @@ const dependencyVersionMap = {
|
|
|
150
152
|
"nitro-cloudflare-dev": "^0.2.2",
|
|
151
153
|
"@sveltejs/adapter-cloudflare": "^7.2.1",
|
|
152
154
|
"@cloudflare/workers-types": "^4.20250822.0",
|
|
153
|
-
alchemy: "^0.
|
|
155
|
+
alchemy: "^0.81.1",
|
|
154
156
|
dotenv: "^17.2.2",
|
|
155
157
|
tsdown: "^0.16.5",
|
|
156
158
|
zod: "^4.1.13",
|
|
@@ -184,121 +186,6 @@ const ADDON_COMPATIBILITY = {
|
|
|
184
186
|
none: []
|
|
185
187
|
};
|
|
186
188
|
|
|
187
|
-
//#endregion
|
|
188
|
-
//#region src/types.ts
|
|
189
|
-
const DatabaseSchema = z.enum([
|
|
190
|
-
"none",
|
|
191
|
-
"sqlite",
|
|
192
|
-
"postgres",
|
|
193
|
-
"mysql",
|
|
194
|
-
"mongodb"
|
|
195
|
-
]).describe("Database type");
|
|
196
|
-
const ORMSchema = z.enum([
|
|
197
|
-
"drizzle",
|
|
198
|
-
"prisma",
|
|
199
|
-
"mongoose",
|
|
200
|
-
"none"
|
|
201
|
-
]).describe("ORM type");
|
|
202
|
-
const BackendSchema = z.enum([
|
|
203
|
-
"hono",
|
|
204
|
-
"express",
|
|
205
|
-
"fastify",
|
|
206
|
-
"elysia",
|
|
207
|
-
"convex",
|
|
208
|
-
"self",
|
|
209
|
-
"none"
|
|
210
|
-
]).describe("Backend framework");
|
|
211
|
-
const RuntimeSchema = z.enum([
|
|
212
|
-
"bun",
|
|
213
|
-
"node",
|
|
214
|
-
"workers",
|
|
215
|
-
"none"
|
|
216
|
-
]).describe("Runtime environment");
|
|
217
|
-
const FrontendSchema = z.enum([
|
|
218
|
-
"tanstack-router",
|
|
219
|
-
"react-router",
|
|
220
|
-
"tanstack-start",
|
|
221
|
-
"next",
|
|
222
|
-
"nuxt",
|
|
223
|
-
"native-bare",
|
|
224
|
-
"native-uniwind",
|
|
225
|
-
"native-unistyles",
|
|
226
|
-
"svelte",
|
|
227
|
-
"solid",
|
|
228
|
-
"none"
|
|
229
|
-
]).describe("Frontend framework");
|
|
230
|
-
const AddonsSchema = z.enum([
|
|
231
|
-
"pwa",
|
|
232
|
-
"tauri",
|
|
233
|
-
"starlight",
|
|
234
|
-
"biome",
|
|
235
|
-
"husky",
|
|
236
|
-
"ruler",
|
|
237
|
-
"turborepo",
|
|
238
|
-
"fumadocs",
|
|
239
|
-
"ultracite",
|
|
240
|
-
"oxlint",
|
|
241
|
-
"none"
|
|
242
|
-
]).describe("Additional addons");
|
|
243
|
-
const ExamplesSchema = z.enum([
|
|
244
|
-
"todo",
|
|
245
|
-
"ai",
|
|
246
|
-
"none"
|
|
247
|
-
]).describe("Example templates to include");
|
|
248
|
-
const PackageManagerSchema = z.enum([
|
|
249
|
-
"npm",
|
|
250
|
-
"pnpm",
|
|
251
|
-
"bun"
|
|
252
|
-
]).describe("Package manager");
|
|
253
|
-
const DatabaseSetupSchema = z.enum([
|
|
254
|
-
"turso",
|
|
255
|
-
"neon",
|
|
256
|
-
"prisma-postgres",
|
|
257
|
-
"planetscale",
|
|
258
|
-
"mongodb-atlas",
|
|
259
|
-
"supabase",
|
|
260
|
-
"d1",
|
|
261
|
-
"docker",
|
|
262
|
-
"none"
|
|
263
|
-
]).describe("Database hosting setup");
|
|
264
|
-
const APISchema = z.enum([
|
|
265
|
-
"trpc",
|
|
266
|
-
"orpc",
|
|
267
|
-
"none"
|
|
268
|
-
]).describe("API type");
|
|
269
|
-
const AuthSchema = z.enum([
|
|
270
|
-
"better-auth",
|
|
271
|
-
"clerk",
|
|
272
|
-
"none"
|
|
273
|
-
]).describe("Authentication provider");
|
|
274
|
-
const PaymentsSchema = z.enum(["polar", "none"]).describe("Payments provider");
|
|
275
|
-
const ProjectNameSchema = z.string().min(1, "Project name cannot be empty").max(255, "Project name must be less than 255 characters").refine((name) => name === "." || !name.startsWith("."), "Project name cannot start with a dot (except for '.')").refine((name) => name === "." || !name.startsWith("-"), "Project name cannot start with a dash").refine((name) => {
|
|
276
|
-
return ![
|
|
277
|
-
"<",
|
|
278
|
-
">",
|
|
279
|
-
":",
|
|
280
|
-
"\"",
|
|
281
|
-
"|",
|
|
282
|
-
"?",
|
|
283
|
-
"*"
|
|
284
|
-
].some((char) => name.includes(char));
|
|
285
|
-
}, "Project name contains invalid characters").refine((name) => name.toLowerCase() !== "node_modules", "Project name is reserved").describe("Project name or path");
|
|
286
|
-
const WebDeploySchema = z.enum(["alchemy", "none"]).describe("Web deployment");
|
|
287
|
-
const ServerDeploySchema = z.enum(["alchemy", "none"]).describe("Server deployment");
|
|
288
|
-
const DirectoryConflictSchema = z.enum([
|
|
289
|
-
"merge",
|
|
290
|
-
"overwrite",
|
|
291
|
-
"increment",
|
|
292
|
-
"error"
|
|
293
|
-
]).describe("How to handle existing directory conflicts");
|
|
294
|
-
const TemplateSchema = z.enum([
|
|
295
|
-
"mern",
|
|
296
|
-
"pern",
|
|
297
|
-
"t3",
|
|
298
|
-
"uniwind",
|
|
299
|
-
"none"
|
|
300
|
-
]).describe("Predefined project template");
|
|
301
|
-
|
|
302
189
|
//#endregion
|
|
303
190
|
//#region src/utils/compatibility.ts
|
|
304
191
|
const WEB_FRAMEWORKS = [
|
|
@@ -400,7 +287,8 @@ function allowedApisForFrontends(frontends = []) {
|
|
|
400
287
|
function isExampleTodoAllowed(backend, database) {
|
|
401
288
|
return !(backend !== "convex" && backend !== "none" && database === "none");
|
|
402
289
|
}
|
|
403
|
-
function isExampleAIAllowed(
|
|
290
|
+
function isExampleAIAllowed(backend, frontends = []) {
|
|
291
|
+
if (backend === "convex") return false;
|
|
404
292
|
if (frontends.includes("solid")) return false;
|
|
405
293
|
return true;
|
|
406
294
|
}
|
|
@@ -447,6 +335,7 @@ function validateExamplesCompatibility(examples, backend, database, frontend) {
|
|
|
447
335
|
const examplesArr = examples ?? [];
|
|
448
336
|
if (examplesArr.length === 0 || examplesArr.includes("none")) return;
|
|
449
337
|
if (examplesArr.includes("todo") && backend !== "convex" && backend !== "none" && database === "none") exitWithError("The 'todo' example requires a database if a backend (other than Convex) is present. Cannot use --examples todo when database is 'none' and a backend is selected.");
|
|
338
|
+
if (examplesArr.includes("ai") && backend === "convex") exitWithError("The 'ai' example is not yet available with Convex backend.");
|
|
450
339
|
if (examplesArr.includes("ai") && (frontend ?? []).includes("solid")) exitWithError("The 'ai' example is not compatible with the Solid frontend.");
|
|
451
340
|
}
|
|
452
341
|
|
|
@@ -873,13 +762,11 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
873
762
|
//#region src/prompts/examples.ts
|
|
874
763
|
async function getExamplesChoice(examples, database, frontends, backend, api) {
|
|
875
764
|
if (examples !== void 0) return examples;
|
|
876
|
-
if (api === "none") {
|
|
877
|
-
if (backend === "convex") return ["todo"];
|
|
878
|
-
return [];
|
|
879
|
-
}
|
|
880
|
-
if (backend === "convex") return ["todo"];
|
|
881
765
|
if (backend === "none") return [];
|
|
882
|
-
if (
|
|
766
|
+
if (backend !== "convex") {
|
|
767
|
+
if (api === "none") return [];
|
|
768
|
+
if (database === "none") return [];
|
|
769
|
+
}
|
|
883
770
|
let response = [];
|
|
884
771
|
const options = [];
|
|
885
772
|
if (isExampleTodoAllowed(backend, database)) options.push({
|
|
@@ -1366,7 +1253,7 @@ async function sendConvexEvent(payload) {
|
|
|
1366
1253
|
}
|
|
1367
1254
|
async function trackProjectCreation(config, disableAnalytics = false) {
|
|
1368
1255
|
if (!isTelemetryEnabled() || disableAnalytics) return;
|
|
1369
|
-
const { projectName: _projectName, projectDir: _projectDir, relativePath: _relativePath
|
|
1256
|
+
const { projectName: _projectName, projectDir: _projectDir, relativePath: _relativePath, ...safeConfig } = config;
|
|
1370
1257
|
try {
|
|
1371
1258
|
await sendConvexEvent({
|
|
1372
1259
|
...safeConfig,
|
|
@@ -2925,6 +2812,8 @@ async function setupDbPackage(projectDir, context) {
|
|
|
2925
2812
|
await fs.ensureDir(dbPackageDir);
|
|
2926
2813
|
const dbBaseDir = path.join(PKG_ROOT, "templates/db/base");
|
|
2927
2814
|
if (await fs.pathExists(dbBaseDir)) await processAndCopyFiles("**/*", dbBaseDir, dbPackageDir, context);
|
|
2815
|
+
const dbOrmBaseDir = path.join(PKG_ROOT, `templates/db/${context.orm}/base`);
|
|
2816
|
+
if (await fs.pathExists(dbOrmBaseDir)) await processAndCopyFiles("**/*", dbOrmBaseDir, dbPackageDir, context);
|
|
2928
2817
|
const dbOrmSrcDir = path.join(PKG_ROOT, `templates/db/${context.orm}/${context.database}`);
|
|
2929
2818
|
if (await fs.pathExists(dbOrmSrcDir)) await processAndCopyFiles("**/*", dbOrmSrcDir, dbPackageDir, context);
|
|
2930
2819
|
}
|
|
@@ -3195,7 +3084,11 @@ async function setupExamplesTemplate(projectDir, context) {
|
|
|
3195
3084
|
for (const example of context.examples) {
|
|
3196
3085
|
if (example === "none") continue;
|
|
3197
3086
|
const exampleBaseDir = path.join(PKG_ROOT, `templates/examples/${example}`);
|
|
3198
|
-
if (
|
|
3087
|
+
if (context.backend === "convex") {
|
|
3088
|
+
const convexBackendDestDir = path.join(projectDir, "packages/backend");
|
|
3089
|
+
const convexExampleSrc = path.join(exampleBaseDir, "convex/packages/backend");
|
|
3090
|
+
if (await fs.pathExists(convexExampleSrc)) await processAndCopyFiles("**/*", convexExampleSrc, convexBackendDestDir, context, false);
|
|
3091
|
+
} else if ((serverAppDirExists || context.backend === "self") && context.backend !== "none") {
|
|
3199
3092
|
const exampleServerSrc = path.join(exampleBaseDir, "server");
|
|
3200
3093
|
if (context.api !== "none") {
|
|
3201
3094
|
const apiPackageDir = path.join(projectDir, "packages/api");
|
|
@@ -3863,6 +3756,7 @@ async function addDeploymentToProject(input) {
|
|
|
3863
3756
|
async function setupCatalogs(projectDir, options) {
|
|
3864
3757
|
if (options.packageManager === "npm") return;
|
|
3865
3758
|
const packagePaths = [
|
|
3759
|
+
".",
|
|
3866
3760
|
"apps/server",
|
|
3867
3761
|
"apps/web",
|
|
3868
3762
|
"apps/native",
|
|
@@ -3871,7 +3765,8 @@ async function setupCatalogs(projectDir, options) {
|
|
|
3871
3765
|
"packages/api",
|
|
3872
3766
|
"packages/db",
|
|
3873
3767
|
"packages/auth",
|
|
3874
|
-
"packages/backend"
|
|
3768
|
+
"packages/backend",
|
|
3769
|
+
"packages/config"
|
|
3875
3770
|
];
|
|
3876
3771
|
const packagesInfo = [];
|
|
3877
3772
|
for (const pkgPath of packagePaths) {
|
|
@@ -3970,15 +3865,18 @@ async function updatePackageJsonsWithCatalogs(packagesInfo, catalog) {
|
|
|
3970
3865
|
//#endregion
|
|
3971
3866
|
//#region src/helpers/addons/examples-setup.ts
|
|
3972
3867
|
async function setupExamples(config) {
|
|
3973
|
-
const { examples, frontend, backend, projectDir, orm } = config;
|
|
3868
|
+
const { examples, frontend, backend, projectDir, orm, database } = config;
|
|
3974
3869
|
if (backend === "convex" || !examples || examples.length === 0 || examples[0] === "none") return;
|
|
3975
3870
|
const apiDir = path.join(projectDir, "packages/api");
|
|
3976
3871
|
if (await fs.pathExists(apiDir) && backend !== "none") {
|
|
3977
|
-
if (orm === "drizzle")
|
|
3978
|
-
dependencies
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3872
|
+
if (orm === "drizzle") {
|
|
3873
|
+
const dependencies = ["drizzle-orm"];
|
|
3874
|
+
if (database === "postgres") dependencies.push("@types/pg");
|
|
3875
|
+
await addPackageDependency({
|
|
3876
|
+
dependencies,
|
|
3877
|
+
projectDir: apiDir
|
|
3878
|
+
});
|
|
3879
|
+
} else if (orm === "prisma") await addPackageDependency({
|
|
3982
3880
|
dependencies: ["@prisma/client"],
|
|
3983
3881
|
projectDir: apiDir
|
|
3984
3882
|
});
|
|
@@ -4027,15 +3925,6 @@ async function setupExamples(config) {
|
|
|
4027
3925
|
|
|
4028
3926
|
//#endregion
|
|
4029
3927
|
//#region src/helpers/core/api-setup.ts
|
|
4030
|
-
async function addBackendWorkspaceDependency(projectDir, backendPackageName, workspaceVersion) {
|
|
4031
|
-
const pkgJsonPath = path.join(projectDir, "package.json");
|
|
4032
|
-
try {
|
|
4033
|
-
const pkgJson = await fs.readJson(pkgJsonPath);
|
|
4034
|
-
if (!pkgJson.dependencies) pkgJson.dependencies = {};
|
|
4035
|
-
pkgJson.dependencies[backendPackageName] = workspaceVersion;
|
|
4036
|
-
await fs.writeJson(pkgJsonPath, pkgJson, { spaces: 2 });
|
|
4037
|
-
} catch {}
|
|
4038
|
-
}
|
|
4039
3928
|
function getFrontendType(frontend) {
|
|
4040
3929
|
const reactBasedFrontends = [
|
|
4041
3930
|
"tanstack-router",
|
|
@@ -4153,7 +4042,7 @@ function getConvexDependencies(frontend) {
|
|
|
4153
4042
|
return deps;
|
|
4154
4043
|
}
|
|
4155
4044
|
async function setupApi(config) {
|
|
4156
|
-
const { api,
|
|
4045
|
+
const { api, frontend, backend, projectDir } = config;
|
|
4157
4046
|
const isConvex = backend === "convex";
|
|
4158
4047
|
const webDir = path.join(projectDir, "apps/web");
|
|
4159
4048
|
const nativeDir = path.join(projectDir, "apps/native");
|
|
@@ -4223,10 +4112,6 @@ async function setupApi(config) {
|
|
|
4223
4112
|
dependencies: convexDeps.native.dependencies,
|
|
4224
4113
|
projectDir: nativeDir
|
|
4225
4114
|
});
|
|
4226
|
-
const backendPackageName = `@${projectName}/backend`;
|
|
4227
|
-
const backendWorkspaceVersion = packageManager === "npm" ? "*" : "workspace:*";
|
|
4228
|
-
if (webDirExists) await addBackendWorkspaceDependency(webDir, backendPackageName, backendWorkspaceVersion);
|
|
4229
|
-
if (nativeDirExists) await addBackendWorkspaceDependency(nativeDir, backendPackageName, backendWorkspaceVersion);
|
|
4230
4115
|
}
|
|
4231
4116
|
}
|
|
4232
4117
|
|
|
@@ -6431,93 +6316,113 @@ function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend)
|
|
|
6431
6316
|
//#endregion
|
|
6432
6317
|
//#region src/helpers/core/workspace-setup.ts
|
|
6433
6318
|
async function setupWorkspaceDependencies(projectDir, options) {
|
|
6434
|
-
const projectName = options
|
|
6435
|
-
const workspaceVersion =
|
|
6319
|
+
const { projectName, packageManager, database, auth, api, runtime, backend } = options;
|
|
6320
|
+
const workspaceVersion = packageManager === "npm" ? "*" : "workspace:*";
|
|
6436
6321
|
const commonDeps = ["dotenv", "zod"];
|
|
6437
|
-
const commonDevDeps = [];
|
|
6438
|
-
const
|
|
6439
|
-
const
|
|
6440
|
-
|
|
6441
|
-
const
|
|
6442
|
-
|
|
6322
|
+
const commonDevDeps = ["typescript"];
|
|
6323
|
+
const configDir = path.join(projectDir, "packages/config");
|
|
6324
|
+
const dbDir = path.join(projectDir, "packages/db");
|
|
6325
|
+
const authDir = path.join(projectDir, "packages/auth");
|
|
6326
|
+
const apiDir = path.join(projectDir, "packages/api");
|
|
6327
|
+
const backendDir = path.join(projectDir, "packages/backend");
|
|
6328
|
+
const serverDir = path.join(projectDir, "apps/server");
|
|
6329
|
+
const webDir = path.join(projectDir, "apps/web");
|
|
6330
|
+
const nativeDir = path.join(projectDir, "apps/native");
|
|
6331
|
+
const [configExists, dbExists, authExists, apiExists, backendExists, serverExists, webExists, nativeExists] = await Promise.all([
|
|
6332
|
+
fs.pathExists(configDir),
|
|
6333
|
+
fs.pathExists(dbDir),
|
|
6334
|
+
fs.pathExists(authDir),
|
|
6335
|
+
fs.pathExists(apiDir),
|
|
6336
|
+
fs.pathExists(backendDir),
|
|
6337
|
+
fs.pathExists(serverDir),
|
|
6338
|
+
fs.pathExists(webDir),
|
|
6339
|
+
fs.pathExists(nativeDir)
|
|
6340
|
+
]);
|
|
6341
|
+
const configDep = configExists ? { [`@${projectName}/config`]: workspaceVersion } : {};
|
|
6342
|
+
if (dbExists) await addPackageDependency({
|
|
6443
6343
|
dependencies: commonDeps,
|
|
6444
6344
|
devDependencies: commonDevDeps,
|
|
6445
6345
|
customDevDependencies: configDep,
|
|
6446
|
-
projectDir:
|
|
6346
|
+
projectDir: dbDir
|
|
6447
6347
|
});
|
|
6448
|
-
|
|
6449
|
-
if (await fs.pathExists(authPackageDir)) {
|
|
6348
|
+
if (authExists) {
|
|
6450
6349
|
const authDeps = {};
|
|
6451
|
-
if (
|
|
6350
|
+
if (database !== "none" && dbExists) authDeps[`@${projectName}/db`] = workspaceVersion;
|
|
6452
6351
|
await addPackageDependency({
|
|
6453
6352
|
dependencies: commonDeps,
|
|
6454
6353
|
devDependencies: commonDevDeps,
|
|
6455
6354
|
customDependencies: authDeps,
|
|
6456
6355
|
customDevDependencies: configDep,
|
|
6457
|
-
projectDir:
|
|
6356
|
+
projectDir: authDir
|
|
6458
6357
|
});
|
|
6459
6358
|
}
|
|
6460
|
-
|
|
6461
|
-
if (await fs.pathExists(apiPackageDir)) {
|
|
6359
|
+
if (apiExists) {
|
|
6462
6360
|
const apiDeps = {};
|
|
6463
|
-
if (
|
|
6464
|
-
if (
|
|
6361
|
+
if (auth !== "none" && authExists) apiDeps[`@${projectName}/auth`] = workspaceVersion;
|
|
6362
|
+
if (database !== "none" && dbExists) apiDeps[`@${projectName}/db`] = workspaceVersion;
|
|
6465
6363
|
await addPackageDependency({
|
|
6466
6364
|
dependencies: commonDeps,
|
|
6467
6365
|
devDependencies: commonDevDeps,
|
|
6468
6366
|
customDependencies: apiDeps,
|
|
6469
6367
|
customDevDependencies: configDep,
|
|
6470
|
-
projectDir:
|
|
6368
|
+
projectDir: apiDir
|
|
6471
6369
|
});
|
|
6472
6370
|
}
|
|
6473
|
-
|
|
6474
|
-
|
|
6371
|
+
if (backendExists) await addPackageDependency({
|
|
6372
|
+
dependencies: commonDeps,
|
|
6373
|
+
devDependencies: commonDevDeps,
|
|
6374
|
+
customDevDependencies: configDep,
|
|
6375
|
+
projectDir: backendDir
|
|
6376
|
+
});
|
|
6377
|
+
if (serverExists) {
|
|
6475
6378
|
const serverDeps = {};
|
|
6476
|
-
if (
|
|
6477
|
-
if (
|
|
6478
|
-
if (
|
|
6379
|
+
if (api !== "none" && apiExists) serverDeps[`@${projectName}/api`] = workspaceVersion;
|
|
6380
|
+
if (auth !== "none" && authExists) serverDeps[`@${projectName}/auth`] = workspaceVersion;
|
|
6381
|
+
if (database !== "none" && dbExists) serverDeps[`@${projectName}/db`] = workspaceVersion;
|
|
6479
6382
|
await addPackageDependency({
|
|
6480
6383
|
dependencies: commonDeps,
|
|
6481
6384
|
devDependencies: [...commonDevDeps, "tsdown"],
|
|
6482
6385
|
customDependencies: serverDeps,
|
|
6483
6386
|
customDevDependencies: configDep,
|
|
6484
|
-
projectDir:
|
|
6387
|
+
projectDir: serverDir
|
|
6485
6388
|
});
|
|
6486
6389
|
}
|
|
6487
|
-
|
|
6488
|
-
if (await fs.pathExists(webPackageDir)) {
|
|
6390
|
+
if (webExists) {
|
|
6489
6391
|
const webDeps = {};
|
|
6490
|
-
if (
|
|
6491
|
-
if (
|
|
6492
|
-
if (
|
|
6392
|
+
if (api !== "none" && apiExists) webDeps[`@${projectName}/api`] = workspaceVersion;
|
|
6393
|
+
if (auth !== "none" && authExists) webDeps[`@${projectName}/auth`] = workspaceVersion;
|
|
6394
|
+
if (backend === "convex" && backendExists) webDeps[`@${projectName}/backend`] = workspaceVersion;
|
|
6395
|
+
await addPackageDependency({
|
|
6396
|
+
dependencies: commonDeps,
|
|
6397
|
+
devDependencies: commonDevDeps,
|
|
6493
6398
|
customDependencies: webDeps,
|
|
6494
6399
|
customDevDependencies: configDep,
|
|
6495
|
-
projectDir:
|
|
6400
|
+
projectDir: webDir
|
|
6496
6401
|
});
|
|
6497
6402
|
}
|
|
6498
|
-
|
|
6499
|
-
if (await fs.pathExists(nativePackageDir)) {
|
|
6403
|
+
if (nativeExists) {
|
|
6500
6404
|
const nativeDeps = {};
|
|
6501
|
-
if (
|
|
6502
|
-
if (
|
|
6405
|
+
if (api !== "none" && apiExists) nativeDeps[`@${projectName}/api`] = workspaceVersion;
|
|
6406
|
+
if (backend === "convex" && backendExists) nativeDeps[`@${projectName}/backend`] = workspaceVersion;
|
|
6407
|
+
await addPackageDependency({
|
|
6408
|
+
dependencies: commonDeps,
|
|
6409
|
+
devDependencies: commonDevDeps,
|
|
6503
6410
|
customDependencies: nativeDeps,
|
|
6504
6411
|
customDevDependencies: configDep,
|
|
6505
|
-
projectDir:
|
|
6412
|
+
projectDir: nativeDir
|
|
6506
6413
|
});
|
|
6507
6414
|
}
|
|
6508
|
-
const runtimeDevDeps = getRuntimeDevDeps(
|
|
6415
|
+
const runtimeDevDeps = getRuntimeDevDeps(runtime, backend);
|
|
6509
6416
|
await addPackageDependency({
|
|
6510
6417
|
dependencies: commonDeps,
|
|
6511
6418
|
devDependencies: [...commonDevDeps, ...runtimeDevDeps],
|
|
6512
6419
|
projectDir
|
|
6513
6420
|
});
|
|
6514
6421
|
}
|
|
6515
|
-
function getRuntimeDevDeps(
|
|
6516
|
-
const { runtime, backend } = options;
|
|
6422
|
+
function getRuntimeDevDeps(runtime, backend) {
|
|
6517
6423
|
if (runtime === "none" && backend === "self") return ["@types/node"];
|
|
6518
|
-
if (runtime === "node") return ["@types/node"];
|
|
6424
|
+
if (runtime === "node" || runtime === "workers") return ["@types/node"];
|
|
6519
6425
|
if (runtime === "bun") return ["@types/bun"];
|
|
6520
|
-
if (runtime === "workers") return ["@types/node"];
|
|
6521
6426
|
return [];
|
|
6522
6427
|
}
|
|
6523
6428
|
|
|
@@ -6526,185 +6431,130 @@ function getRuntimeDevDeps(options) {
|
|
|
6526
6431
|
async function updatePackageConfigurations(projectDir, options) {
|
|
6527
6432
|
await updateRootPackageJson(projectDir, options);
|
|
6528
6433
|
if (options.backend === "convex") await updateConvexPackageJson(projectDir, options);
|
|
6529
|
-
else if (options.backend
|
|
6434
|
+
else if (options.backend !== "none") {
|
|
6530
6435
|
await updateDbPackageJson(projectDir, options);
|
|
6531
6436
|
await updateAuthPackageJson(projectDir, options);
|
|
6532
6437
|
await updateApiPackageJson(projectDir, options);
|
|
6533
|
-
await
|
|
6534
|
-
} else if (options.backend !== "none") {
|
|
6535
|
-
await updateServerPackageJson(projectDir, options);
|
|
6536
|
-
await updateAuthPackageJson(projectDir, options);
|
|
6537
|
-
await updateApiPackageJson(projectDir, options);
|
|
6538
|
-
await setupWorkspaceDependencies(projectDir, options);
|
|
6438
|
+
if (options.backend !== "self") await updateServerPackageJson(projectDir, options);
|
|
6539
6439
|
}
|
|
6440
|
+
await setupWorkspaceDependencies(projectDir, options);
|
|
6540
6441
|
}
|
|
6541
6442
|
async function updateRootPackageJson(projectDir, options) {
|
|
6542
6443
|
const rootPackageJsonPath = path.join(projectDir, "package.json");
|
|
6543
6444
|
if (!await fs.pathExists(rootPackageJsonPath)) return;
|
|
6544
6445
|
const packageJson = await fs.readJson(rootPackageJsonPath);
|
|
6545
6446
|
packageJson.name = options.projectName;
|
|
6546
|
-
|
|
6447
|
+
packageJson.scripts = packageJson.scripts || {};
|
|
6448
|
+
packageJson.workspaces = packageJson.workspaces || [];
|
|
6547
6449
|
const scripts = packageJson.scripts;
|
|
6548
|
-
const
|
|
6549
|
-
const
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
scripts["
|
|
6565
|
-
scripts["
|
|
6566
|
-
if (
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
if (
|
|
6572
|
-
scripts["db:generate"] = `turbo -F ${dbPackageName} db:generate`;
|
|
6573
|
-
scripts["db:migrate"] = `turbo -F ${dbPackageName} db:migrate`;
|
|
6574
|
-
} else if (options.orm === "drizzle") {
|
|
6575
|
-
scripts["db:generate"] = `turbo -F ${dbPackageName} db:generate`;
|
|
6576
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:migrate"] = `turbo -F ${dbPackageName} db:migrate`;
|
|
6577
|
-
}
|
|
6578
|
-
}
|
|
6579
|
-
if (options.dbSetup === "docker") {
|
|
6580
|
-
scripts["db:start"] = `turbo -F ${dbPackageName} db:start`;
|
|
6581
|
-
scripts["db:watch"] = `turbo -F ${dbPackageName} db:watch`;
|
|
6582
|
-
scripts["db:stop"] = `turbo -F ${dbPackageName} db:stop`;
|
|
6583
|
-
scripts["db:down"] = `turbo -F ${dbPackageName} db:down`;
|
|
6584
|
-
}
|
|
6585
|
-
} else if (options.packageManager === "pnpm") {
|
|
6586
|
-
scripts.dev = devScript;
|
|
6587
|
-
scripts.build = "pnpm -r build";
|
|
6588
|
-
scripts["check-types"] = "pnpm -r check-types";
|
|
6589
|
-
scripts["dev:native"] = "pnpm --filter native dev";
|
|
6590
|
-
scripts["dev:web"] = "pnpm --filter web dev";
|
|
6591
|
-
if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
|
|
6592
|
-
if (options.backend === "convex") scripts["dev:setup"] = `pnpm --filter ${backendPackageName} dev:setup`;
|
|
6593
|
-
if (needsDbScripts) {
|
|
6594
|
-
scripts["db:push"] = `pnpm --filter ${dbPackageName} db:push`;
|
|
6595
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:studio"] = `pnpm --filter ${dbPackageName} db:studio`;
|
|
6596
|
-
if (options.orm === "prisma") {
|
|
6597
|
-
scripts["db:generate"] = `pnpm --filter ${dbPackageName} db:generate`;
|
|
6598
|
-
scripts["db:migrate"] = `pnpm --filter ${dbPackageName} db:migrate`;
|
|
6599
|
-
} else if (options.orm === "drizzle") {
|
|
6600
|
-
scripts["db:generate"] = `pnpm --filter ${dbPackageName} db:generate`;
|
|
6601
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:migrate"] = `pnpm --filter ${dbPackageName} db:migrate`;
|
|
6602
|
-
}
|
|
6603
|
-
}
|
|
6604
|
-
if (options.dbSetup === "docker") {
|
|
6605
|
-
scripts["db:start"] = `pnpm --filter ${dbPackageName} db:start`;
|
|
6606
|
-
scripts["db:watch"] = `pnpm --filter ${dbPackageName} db:watch`;
|
|
6607
|
-
scripts["db:stop"] = `pnpm --filter ${dbPackageName} db:stop`;
|
|
6608
|
-
scripts["db:down"] = `pnpm --filter ${dbPackageName} db:down`;
|
|
6609
|
-
}
|
|
6610
|
-
} else if (options.packageManager === "npm") {
|
|
6611
|
-
scripts.dev = devScript;
|
|
6612
|
-
scripts.build = "npm run build --workspaces";
|
|
6613
|
-
scripts["check-types"] = "npm run check-types --workspaces";
|
|
6614
|
-
scripts["dev:native"] = "npm run dev --workspace native";
|
|
6615
|
-
scripts["dev:web"] = "npm run dev --workspace web";
|
|
6616
|
-
if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
|
|
6617
|
-
if (options.backend === "convex") scripts["dev:setup"] = `npm run dev:setup --workspace ${backendPackageName}`;
|
|
6618
|
-
if (needsDbScripts) {
|
|
6619
|
-
scripts["db:push"] = `npm run db:push --workspace ${dbPackageName}`;
|
|
6620
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:studio"] = `npm run db:studio --workspace ${dbPackageName}`;
|
|
6621
|
-
if (options.orm === "prisma") {
|
|
6622
|
-
scripts["db:generate"] = `npm run db:generate --workspace ${dbPackageName}`;
|
|
6623
|
-
scripts["db:migrate"] = `npm run db:migrate --workspace ${dbPackageName}`;
|
|
6624
|
-
} else if (options.orm === "drizzle") {
|
|
6625
|
-
scripts["db:generate"] = `npm run db:generate --workspace ${dbPackageName}`;
|
|
6626
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:migrate"] = `npm run db:migrate --workspace ${dbPackageName}`;
|
|
6627
|
-
}
|
|
6628
|
-
}
|
|
6629
|
-
if (options.dbSetup === "docker") {
|
|
6630
|
-
scripts["db:start"] = `npm run db:start --workspace ${dbPackageName}`;
|
|
6631
|
-
scripts["db:watch"] = `npm run db:watch --workspace ${dbPackageName}`;
|
|
6632
|
-
scripts["db:stop"] = `npm run db:stop --workspace ${dbPackageName}`;
|
|
6633
|
-
scripts["db:down"] = `npm run db:down --workspace ${dbPackageName}`;
|
|
6634
|
-
}
|
|
6635
|
-
} else if (options.packageManager === "bun") {
|
|
6636
|
-
scripts.dev = devScript;
|
|
6637
|
-
scripts.build = "bun run --filter '*' build";
|
|
6638
|
-
scripts["check-types"] = "bun run --filter '*' check-types";
|
|
6639
|
-
scripts["dev:native"] = "bun run --filter native dev";
|
|
6640
|
-
scripts["dev:web"] = "bun run --filter web dev";
|
|
6641
|
-
if (options.backend !== "self" && options.backend !== "none") scripts["dev:server"] = serverDevScript;
|
|
6642
|
-
if (options.backend === "convex") scripts["dev:setup"] = `bun run --filter ${backendPackageName} dev:setup`;
|
|
6643
|
-
if (needsDbScripts) {
|
|
6644
|
-
scripts["db:push"] = `bun run --filter ${dbPackageName} db:push`;
|
|
6645
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:studio"] = `bun run --filter ${dbPackageName} db:studio`;
|
|
6646
|
-
if (options.orm === "prisma") {
|
|
6647
|
-
scripts["db:generate"] = `bun run --filter ${dbPackageName} db:generate`;
|
|
6648
|
-
scripts["db:migrate"] = `bun run --filter ${dbPackageName} db:migrate`;
|
|
6649
|
-
} else if (options.orm === "drizzle") {
|
|
6650
|
-
scripts["db:generate"] = `bun run --filter ${dbPackageName} db:generate`;
|
|
6651
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:migrate"] = `bun run --filter ${dbPackageName} db:migrate`;
|
|
6652
|
-
}
|
|
6653
|
-
}
|
|
6654
|
-
if (options.dbSetup === "docker") {
|
|
6655
|
-
scripts["db:start"] = `bun run --filter ${dbPackageName} db:start`;
|
|
6656
|
-
scripts["db:watch"] = `bun run --filter ${dbPackageName} db:watch`;
|
|
6657
|
-
scripts["db:stop"] = `bun run --filter ${dbPackageName} db:stop`;
|
|
6658
|
-
scripts["db:down"] = `bun run --filter ${dbPackageName} db:down`;
|
|
6450
|
+
const workspaces = packageJson.workspaces;
|
|
6451
|
+
const { projectName, packageManager, backend, database, orm, dbSetup, serverDeploy, addons } = options;
|
|
6452
|
+
const backendPackageName = backend === "convex" ? `@${projectName}/backend` : "server";
|
|
6453
|
+
const dbPackageName = `@${projectName}/db`;
|
|
6454
|
+
const hasTurborepo = addons.includes("turborepo");
|
|
6455
|
+
const needsDbScripts = backend !== "convex" && database !== "none" && orm !== "none" && orm !== "mongoose";
|
|
6456
|
+
const isD1Alchemy = dbSetup === "d1" && serverDeploy === "alchemy";
|
|
6457
|
+
const pmConfig = getPackageManagerConfig(packageManager, hasTurborepo);
|
|
6458
|
+
scripts.dev = pmConfig.dev;
|
|
6459
|
+
scripts.build = pmConfig.build;
|
|
6460
|
+
scripts["check-types"] = pmConfig.checkTypes;
|
|
6461
|
+
scripts["dev:native"] = pmConfig.filter("native", "dev");
|
|
6462
|
+
scripts["dev:web"] = pmConfig.filter("web", "dev");
|
|
6463
|
+
if (backend !== "self" && backend !== "none") scripts["dev:server"] = pmConfig.filter(backendPackageName, "dev");
|
|
6464
|
+
if (backend === "convex") scripts["dev:setup"] = pmConfig.filter(backendPackageName, "dev:setup");
|
|
6465
|
+
if (needsDbScripts) {
|
|
6466
|
+
scripts["db:push"] = pmConfig.filter(dbPackageName, "db:push");
|
|
6467
|
+
if (!isD1Alchemy) scripts["db:studio"] = pmConfig.filter(dbPackageName, "db:studio");
|
|
6468
|
+
if (orm === "prisma") {
|
|
6469
|
+
scripts["db:generate"] = pmConfig.filter(dbPackageName, "db:generate");
|
|
6470
|
+
scripts["db:migrate"] = pmConfig.filter(dbPackageName, "db:migrate");
|
|
6471
|
+
} else if (orm === "drizzle") {
|
|
6472
|
+
scripts["db:generate"] = pmConfig.filter(dbPackageName, "db:generate");
|
|
6473
|
+
if (!isD1Alchemy) scripts["db:migrate"] = pmConfig.filter(dbPackageName, "db:migrate");
|
|
6659
6474
|
}
|
|
6660
6475
|
}
|
|
6476
|
+
if (dbSetup === "docker") {
|
|
6477
|
+
scripts["db:start"] = pmConfig.filter(dbPackageName, "db:start");
|
|
6478
|
+
scripts["db:watch"] = pmConfig.filter(dbPackageName, "db:watch");
|
|
6479
|
+
scripts["db:stop"] = pmConfig.filter(dbPackageName, "db:stop");
|
|
6480
|
+
scripts["db:down"] = pmConfig.filter(dbPackageName, "db:down");
|
|
6481
|
+
}
|
|
6661
6482
|
try {
|
|
6662
|
-
const { stdout } = await execa(
|
|
6663
|
-
packageJson.packageManager = `${
|
|
6483
|
+
const { stdout } = await execa(packageManager, ["-v"], { cwd: projectDir });
|
|
6484
|
+
packageJson.packageManager = `${packageManager}@${stdout.trim()}`;
|
|
6664
6485
|
} catch {
|
|
6665
|
-
log.warn(`Could not determine ${
|
|
6486
|
+
log.warn(`Could not determine ${packageManager} version.`);
|
|
6666
6487
|
}
|
|
6667
|
-
if (
|
|
6668
|
-
const workspaces = packageJson.workspaces;
|
|
6669
|
-
if (options.backend === "convex") {
|
|
6488
|
+
if (backend === "convex") {
|
|
6670
6489
|
if (!workspaces.includes("packages/*")) workspaces.push("packages/*");
|
|
6671
|
-
if ((options.frontend.length > 0 ||
|
|
6490
|
+
if ((options.frontend.length > 0 || addons.includes("starlight")) && !workspaces.includes("apps/*")) workspaces.push("apps/*");
|
|
6672
6491
|
} else {
|
|
6673
6492
|
if (!workspaces.includes("apps/*")) workspaces.push("apps/*");
|
|
6674
6493
|
if (!workspaces.includes("packages/*")) workspaces.push("packages/*");
|
|
6675
6494
|
}
|
|
6676
6495
|
await fs.writeJson(rootPackageJsonPath, packageJson, { spaces: 2 });
|
|
6677
6496
|
}
|
|
6678
|
-
|
|
6497
|
+
function getPackageManagerConfig(packageManager, hasTurborepo) {
|
|
6498
|
+
if (hasTurborepo) return {
|
|
6499
|
+
dev: "turbo dev",
|
|
6500
|
+
build: "turbo build",
|
|
6501
|
+
checkTypes: "turbo check-types",
|
|
6502
|
+
filter: (workspace, script) => `turbo -F ${workspace} ${script}`
|
|
6503
|
+
};
|
|
6504
|
+
switch (packageManager) {
|
|
6505
|
+
case "pnpm": return {
|
|
6506
|
+
dev: "pnpm -r dev",
|
|
6507
|
+
build: "pnpm -r build",
|
|
6508
|
+
checkTypes: "pnpm -r check-types",
|
|
6509
|
+
filter: (workspace, script) => `pnpm --filter ${workspace} ${script}`
|
|
6510
|
+
};
|
|
6511
|
+
case "npm": return {
|
|
6512
|
+
dev: "npm run dev --workspaces",
|
|
6513
|
+
build: "npm run build --workspaces",
|
|
6514
|
+
checkTypes: "npm run check-types --workspaces",
|
|
6515
|
+
filter: (workspace, script) => `npm run ${script} --workspace ${workspace}`
|
|
6516
|
+
};
|
|
6517
|
+
case "bun": return {
|
|
6518
|
+
dev: "bun run --filter '*' dev",
|
|
6519
|
+
build: "bun run --filter '*' build",
|
|
6520
|
+
checkTypes: "bun run --filter '*' check-types",
|
|
6521
|
+
filter: (workspace, script) => `bun run --filter ${workspace} ${script}`
|
|
6522
|
+
};
|
|
6523
|
+
}
|
|
6524
|
+
}
|
|
6525
|
+
async function updateServerPackageJson(projectDir, _options) {
|
|
6679
6526
|
const serverPackageJsonPath = path.join(projectDir, "apps/server/package.json");
|
|
6680
6527
|
if (!await fs.pathExists(serverPackageJsonPath)) return;
|
|
6681
6528
|
const serverPackageJson = await fs.readJson(serverPackageJsonPath);
|
|
6682
|
-
|
|
6529
|
+
serverPackageJson.scripts = serverPackageJson.scripts || {};
|
|
6683
6530
|
await fs.writeJson(serverPackageJsonPath, serverPackageJson, { spaces: 2 });
|
|
6684
|
-
await updateDbPackageJson(projectDir, options);
|
|
6685
6531
|
}
|
|
6686
6532
|
async function updateDbPackageJson(projectDir, options) {
|
|
6687
6533
|
const dbPackageJsonPath = path.join(projectDir, "packages/db/package.json");
|
|
6688
6534
|
if (!await fs.pathExists(dbPackageJsonPath)) return;
|
|
6689
6535
|
const dbPackageJson = await fs.readJson(dbPackageJsonPath);
|
|
6690
6536
|
dbPackageJson.name = `@${options.projectName}/db`;
|
|
6691
|
-
|
|
6537
|
+
dbPackageJson.scripts = dbPackageJson.scripts || {};
|
|
6692
6538
|
const scripts = dbPackageJson.scripts;
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6539
|
+
const { database, orm, dbSetup, serverDeploy } = options;
|
|
6540
|
+
const isD1Alchemy = dbSetup === "d1" && serverDeploy === "alchemy";
|
|
6541
|
+
if (database !== "none") {
|
|
6542
|
+
if (database === "sqlite" && orm === "drizzle" && dbSetup !== "d1") scripts["db:local"] = "turso dev --db-file local.db";
|
|
6543
|
+
if (orm === "prisma") {
|
|
6696
6544
|
scripts["db:push"] = "prisma db push";
|
|
6697
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:studio"] = "prisma studio";
|
|
6698
6545
|
scripts["db:generate"] = "prisma generate";
|
|
6699
6546
|
scripts["db:migrate"] = "prisma migrate dev";
|
|
6700
|
-
|
|
6547
|
+
if (!isD1Alchemy) scripts["db:studio"] = "prisma studio";
|
|
6548
|
+
} else if (orm === "drizzle") {
|
|
6701
6549
|
scripts["db:push"] = "drizzle-kit push";
|
|
6702
|
-
if (!(options.dbSetup === "d1" && options.serverDeploy === "alchemy")) scripts["db:studio"] = "drizzle-kit studio";
|
|
6703
6550
|
scripts["db:generate"] = "drizzle-kit generate";
|
|
6704
|
-
if (!
|
|
6551
|
+
if (!isD1Alchemy) {
|
|
6552
|
+
scripts["db:studio"] = "drizzle-kit studio";
|
|
6553
|
+
scripts["db:migrate"] = "drizzle-kit migrate";
|
|
6554
|
+
}
|
|
6705
6555
|
}
|
|
6706
6556
|
}
|
|
6707
|
-
if (
|
|
6557
|
+
if (dbSetup === "docker") {
|
|
6708
6558
|
scripts["db:start"] = "docker compose up -d";
|
|
6709
6559
|
scripts["db:watch"] = "docker compose up";
|
|
6710
6560
|
scripts["db:stop"] = "docker compose stop";
|
|
@@ -6731,7 +6581,7 @@ async function updateConvexPackageJson(projectDir, options) {
|
|
|
6731
6581
|
if (!await fs.pathExists(convexPackageJsonPath)) return;
|
|
6732
6582
|
const convexPackageJson = await fs.readJson(convexPackageJsonPath);
|
|
6733
6583
|
convexPackageJson.name = `@${options.projectName}/backend`;
|
|
6734
|
-
|
|
6584
|
+
convexPackageJson.scripts = convexPackageJson.scripts || {};
|
|
6735
6585
|
await fs.writeJson(convexPackageJsonPath, convexPackageJson, { spaces: 2 });
|
|
6736
6586
|
}
|
|
6737
6587
|
|
|
@@ -6896,7 +6746,7 @@ async function createProjectHandler(input) {
|
|
|
6896
6746
|
log.message(displayConfig(config));
|
|
6897
6747
|
} else {
|
|
6898
6748
|
const flagConfig = processAndValidateFlags(cliInput, providedFlags, finalBaseName);
|
|
6899
|
-
const { projectName: _projectNameFromFlags
|
|
6749
|
+
const { projectName: _projectNameFromFlags, ...otherFlags } = flagConfig;
|
|
6900
6750
|
if (Object.keys(otherFlags).length > 0) {
|
|
6901
6751
|
log.info(pc.yellow("Using these pre-selected options:"));
|
|
6902
6752
|
log.message(displayConfig(otherFlags));
|
|
@@ -7094,21 +6944,21 @@ const router = os.router({
|
|
|
7094
6944
|
description: "Create a new Better-T-Stack project",
|
|
7095
6945
|
default: true,
|
|
7096
6946
|
negateBooleans: true
|
|
7097
|
-
}).input(z
|
|
6947
|
+
}).input(z.tuple([ProjectNameSchema.optional(), z.object({
|
|
7098
6948
|
template: TemplateSchema.optional().describe("Use a predefined template"),
|
|
7099
|
-
yes: z
|
|
7100
|
-
yolo: z
|
|
7101
|
-
verbose: z
|
|
6949
|
+
yes: z.boolean().optional().default(false).describe("Use default configuration"),
|
|
6950
|
+
yolo: z.boolean().optional().default(false).describe("(WARNING - NOT RECOMMENDED) Bypass validations and compatibility checks"),
|
|
6951
|
+
verbose: z.boolean().optional().default(false).describe("Show detailed result information"),
|
|
7102
6952
|
database: DatabaseSchema.optional(),
|
|
7103
6953
|
orm: ORMSchema.optional(),
|
|
7104
6954
|
auth: AuthSchema.optional(),
|
|
7105
6955
|
payments: PaymentsSchema.optional(),
|
|
7106
|
-
frontend: z
|
|
7107
|
-
addons: z
|
|
7108
|
-
examples: z
|
|
7109
|
-
git: z
|
|
6956
|
+
frontend: z.array(FrontendSchema).optional(),
|
|
6957
|
+
addons: z.array(AddonsSchema).optional(),
|
|
6958
|
+
examples: z.array(ExamplesSchema).optional(),
|
|
6959
|
+
git: z.boolean().optional(),
|
|
7110
6960
|
packageManager: PackageManagerSchema.optional(),
|
|
7111
|
-
install: z
|
|
6961
|
+
install: z.boolean().optional(),
|
|
7112
6962
|
dbSetup: DatabaseSetupSchema.optional(),
|
|
7113
6963
|
backend: BackendSchema.optional(),
|
|
7114
6964
|
runtime: RuntimeSchema.optional(),
|
|
@@ -7116,9 +6966,9 @@ const router = os.router({
|
|
|
7116
6966
|
webDeploy: WebDeploySchema.optional(),
|
|
7117
6967
|
serverDeploy: ServerDeploySchema.optional(),
|
|
7118
6968
|
directoryConflict: DirectoryConflictSchema.optional(),
|
|
7119
|
-
renderTitle: z
|
|
7120
|
-
disableAnalytics: z
|
|
7121
|
-
manualDb: z
|
|
6969
|
+
renderTitle: z.boolean().optional(),
|
|
6970
|
+
disableAnalytics: z.boolean().optional().default(false).describe("Disable analytics"),
|
|
6971
|
+
manualDb: z.boolean().optional().default(false).describe("Skip automatic/manual database setup prompt and use manual setup")
|
|
7122
6972
|
})])).handler(async ({ input }) => {
|
|
7123
6973
|
const [projectName, options] = input;
|
|
7124
6974
|
const result = await createProjectHandler({
|
|
@@ -7127,12 +6977,12 @@ const router = os.router({
|
|
|
7127
6977
|
});
|
|
7128
6978
|
if (options.verbose) return result;
|
|
7129
6979
|
}),
|
|
7130
|
-
add: os.meta({ description: "Add addons or deployment configurations to an existing Better-T-Stack project" }).input(z
|
|
7131
|
-
addons: z
|
|
6980
|
+
add: os.meta({ description: "Add addons or deployment configurations to an existing Better-T-Stack project" }).input(z.tuple([z.object({
|
|
6981
|
+
addons: z.array(AddonsSchema).optional().default([]),
|
|
7132
6982
|
webDeploy: WebDeploySchema.optional(),
|
|
7133
6983
|
serverDeploy: ServerDeploySchema.optional(),
|
|
7134
|
-
projectDir: z
|
|
7135
|
-
install: z
|
|
6984
|
+
projectDir: z.string().optional(),
|
|
6985
|
+
install: z.boolean().optional().default(false).describe("Install dependencies after adding addons or deployment"),
|
|
7136
6986
|
packageManager: PackageManagerSchema.optional()
|
|
7137
6987
|
})])).handler(async ({ input }) => {
|
|
7138
6988
|
const [options] = input;
|