create-better-t-stack 3.7.3-canary.8e4d5716 → 3.7.3-canary.98ba1e7a
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.d.ts +1 -0
- package/dist/cli.js +8 -0
- package/dist/index.d.ts +347 -0
- package/dist/index.js +4 -0
- package/dist/src-yXf02Wox.js +7077 -0
- package/package.json +11 -7
- package/src/cli.ts +0 -3
- package/src/constants.ts +0 -188
- package/src/helpers/addons/addons-setup.ts +0 -226
- package/src/helpers/addons/examples-setup.ts +0 -104
- package/src/helpers/addons/fumadocs-setup.ts +0 -103
- package/src/helpers/addons/ruler-setup.ts +0 -139
- package/src/helpers/addons/starlight-setup.ts +0 -51
- package/src/helpers/addons/tauri-setup.ts +0 -96
- package/src/helpers/addons/ultracite-setup.ts +0 -232
- package/src/helpers/addons/vite-pwa-setup.ts +0 -59
- package/src/helpers/core/add-addons.ts +0 -85
- package/src/helpers/core/add-deployment.ts +0 -102
- package/src/helpers/core/api-setup.ts +0 -280
- package/src/helpers/core/auth-setup.ts +0 -203
- package/src/helpers/core/backend-setup.ts +0 -73
- package/src/helpers/core/command-handlers.ts +0 -354
- package/src/helpers/core/convex-codegen.ts +0 -14
- package/src/helpers/core/create-project.ts +0 -133
- package/src/helpers/core/create-readme.ts +0 -687
- package/src/helpers/core/db-setup.ts +0 -184
- package/src/helpers/core/detect-project-config.ts +0 -41
- package/src/helpers/core/env-setup.ts +0 -449
- package/src/helpers/core/git.ts +0 -31
- package/src/helpers/core/install-dependencies.ts +0 -32
- package/src/helpers/core/payments-setup.ts +0 -48
- package/src/helpers/core/post-installation.ts +0 -383
- package/src/helpers/core/project-config.ts +0 -246
- package/src/helpers/core/runtime-setup.ts +0 -76
- package/src/helpers/core/template-manager.ts +0 -917
- package/src/helpers/core/workspace-setup.ts +0 -184
- package/src/helpers/database-providers/d1-setup.ts +0 -28
- package/src/helpers/database-providers/docker-compose-setup.ts +0 -50
- package/src/helpers/database-providers/mongodb-atlas-setup.ts +0 -186
- package/src/helpers/database-providers/neon-setup.ts +0 -243
- package/src/helpers/database-providers/planetscale-setup.ts +0 -78
- package/src/helpers/database-providers/prisma-postgres-setup.ts +0 -196
- package/src/helpers/database-providers/supabase-setup.ts +0 -218
- package/src/helpers/database-providers/turso-setup.ts +0 -309
- package/src/helpers/deployment/alchemy/alchemy-combined-setup.ts +0 -80
- package/src/helpers/deployment/alchemy/alchemy-next-setup.ts +0 -51
- package/src/helpers/deployment/alchemy/alchemy-nuxt-setup.ts +0 -104
- package/src/helpers/deployment/alchemy/alchemy-react-router-setup.ts +0 -32
- package/src/helpers/deployment/alchemy/alchemy-solid-setup.ts +0 -32
- package/src/helpers/deployment/alchemy/alchemy-svelte-setup.ts +0 -98
- package/src/helpers/deployment/alchemy/alchemy-tanstack-router-setup.ts +0 -33
- package/src/helpers/deployment/alchemy/alchemy-tanstack-start-setup.ts +0 -98
- package/src/helpers/deployment/alchemy/env-dts-setup.ts +0 -76
- package/src/helpers/deployment/alchemy/index.ts +0 -7
- package/src/helpers/deployment/server-deploy-setup.ts +0 -55
- package/src/helpers/deployment/web-deploy-setup.ts +0 -58
- package/src/index.ts +0 -253
- package/src/prompts/addons.ts +0 -178
- package/src/prompts/api.ts +0 -49
- package/src/prompts/auth.ts +0 -84
- package/src/prompts/backend.ts +0 -83
- package/src/prompts/config-prompts.ts +0 -138
- package/src/prompts/database-setup.ts +0 -112
- package/src/prompts/database.ts +0 -57
- package/src/prompts/examples.ts +0 -64
- package/src/prompts/frontend.ts +0 -118
- package/src/prompts/git.ts +0 -16
- package/src/prompts/install.ts +0 -16
- package/src/prompts/orm.ts +0 -53
- package/src/prompts/package-manager.ts +0 -32
- package/src/prompts/payments.ts +0 -50
- package/src/prompts/project-name.ts +0 -86
- package/src/prompts/runtime.ts +0 -47
- package/src/prompts/server-deploy.ts +0 -91
- package/src/prompts/web-deploy.ts +0 -107
- package/src/types.ts +0 -2
- package/src/utils/add-package-deps.ts +0 -57
- package/src/utils/analytics.ts +0 -39
- package/src/utils/better-auth-plugin-setup.ts +0 -71
- package/src/utils/biome-formatter.ts +0 -82
- package/src/utils/bts-config.ts +0 -122
- package/src/utils/command-exists.ts +0 -16
- package/src/utils/compatibility-rules.ts +0 -319
- package/src/utils/compatibility.ts +0 -11
- package/src/utils/config-processing.ts +0 -130
- package/src/utils/config-validation.ts +0 -470
- package/src/utils/display-config.ts +0 -96
- package/src/utils/docker-utils.ts +0 -70
- package/src/utils/errors.ts +0 -32
- package/src/utils/generate-reproducible-command.ts +0 -53
- package/src/utils/get-latest-cli-version.ts +0 -11
- package/src/utils/get-package-manager.ts +0 -13
- package/src/utils/open-url.ts +0 -25
- package/src/utils/package-runner.ts +0 -23
- package/src/utils/project-directory.ts +0 -102
- package/src/utils/project-name-validation.ts +0 -43
- package/src/utils/render-title.ts +0 -48
- package/src/utils/setup-catalogs.ts +0 -192
- package/src/utils/sponsors.ts +0 -101
- package/src/utils/telemetry.ts +0 -19
- package/src/utils/template-processor.ts +0 -64
- package/src/utils/templates.ts +0 -94
- package/src/utils/ts-morph.ts +0 -26
- package/src/validation.ts +0 -117
|
@@ -1,470 +0,0 @@
|
|
|
1
|
-
import type { CLIInput, Database, DatabaseSetup, ProjectConfig, Runtime } from "../types";
|
|
2
|
-
import {
|
|
3
|
-
ensureSingleWebAndNative,
|
|
4
|
-
isWebFrontend,
|
|
5
|
-
validateAddonsAgainstFrontends,
|
|
6
|
-
validateApiFrontendCompatibility,
|
|
7
|
-
validateExamplesCompatibility,
|
|
8
|
-
validatePaymentsCompatibility,
|
|
9
|
-
validateSelfBackendCompatibility,
|
|
10
|
-
validateServerDeployRequiresBackend,
|
|
11
|
-
validateWebDeployRequiresWebFrontend,
|
|
12
|
-
validateWorkersCompatibility,
|
|
13
|
-
} from "./compatibility-rules";
|
|
14
|
-
import { exitWithError } from "./errors";
|
|
15
|
-
|
|
16
|
-
export function validateDatabaseOrmAuth(cfg: Partial<ProjectConfig>, flags?: Set<string>) {
|
|
17
|
-
const db = cfg.database;
|
|
18
|
-
const orm = cfg.orm;
|
|
19
|
-
const has = (k: string) => (flags ? flags.has(k) : true);
|
|
20
|
-
|
|
21
|
-
if (has("orm") && has("database") && orm === "mongoose" && db !== "mongodb") {
|
|
22
|
-
exitWithError(
|
|
23
|
-
"Mongoose ORM requires MongoDB database. Please use '--database mongodb' or choose a different ORM.",
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (has("orm") && has("database") && orm === "drizzle" && db === "mongodb") {
|
|
28
|
-
exitWithError(
|
|
29
|
-
"Drizzle ORM does not support MongoDB. Please use '--orm mongoose' or '--orm prisma' or choose a different database.",
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (
|
|
34
|
-
has("database") &&
|
|
35
|
-
has("orm") &&
|
|
36
|
-
db === "mongodb" &&
|
|
37
|
-
orm &&
|
|
38
|
-
orm !== "mongoose" &&
|
|
39
|
-
orm !== "prisma" &&
|
|
40
|
-
orm !== "none"
|
|
41
|
-
) {
|
|
42
|
-
exitWithError(
|
|
43
|
-
"MongoDB database requires Mongoose or Prisma ORM. Please use '--orm mongoose' or '--orm prisma' or choose a different database.",
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (has("database") && has("orm") && db && db !== "none" && orm === "none") {
|
|
48
|
-
exitWithError(
|
|
49
|
-
"Database selection requires an ORM. Please choose '--orm drizzle', '--orm prisma', or '--orm mongoose'.",
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (has("orm") && has("database") && orm && orm !== "none" && db === "none") {
|
|
54
|
-
exitWithError(
|
|
55
|
-
"ORM selection requires a database. Please choose a database or set '--orm none'.",
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function validateDatabaseSetup(config: Partial<ProjectConfig>, providedFlags: Set<string>) {
|
|
61
|
-
const { dbSetup, database, runtime } = config;
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
providedFlags.has("dbSetup") &&
|
|
65
|
-
providedFlags.has("database") &&
|
|
66
|
-
dbSetup &&
|
|
67
|
-
dbSetup !== "none" &&
|
|
68
|
-
database === "none"
|
|
69
|
-
) {
|
|
70
|
-
exitWithError(
|
|
71
|
-
"Database setup requires a database. Please choose a database or set '--db-setup none'.",
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const setupValidations: Record<
|
|
76
|
-
DatabaseSetup,
|
|
77
|
-
{ database?: Database; runtime?: Runtime; errorMessage: string }
|
|
78
|
-
> = {
|
|
79
|
-
turso: {
|
|
80
|
-
database: "sqlite",
|
|
81
|
-
errorMessage:
|
|
82
|
-
"Turso setup requires SQLite database. Please use '--database sqlite' or choose a different setup.",
|
|
83
|
-
},
|
|
84
|
-
neon: {
|
|
85
|
-
database: "postgres",
|
|
86
|
-
errorMessage:
|
|
87
|
-
"Neon setup requires PostgreSQL database. Please use '--database postgres' or choose a different setup.",
|
|
88
|
-
},
|
|
89
|
-
"prisma-postgres": {
|
|
90
|
-
database: "postgres",
|
|
91
|
-
errorMessage:
|
|
92
|
-
"Prisma PostgreSQL setup requires PostgreSQL database. Please use '--database postgres' or choose a different setup.",
|
|
93
|
-
},
|
|
94
|
-
planetscale: {
|
|
95
|
-
errorMessage:
|
|
96
|
-
"PlanetScale setup requires PostgreSQL or MySQL database. Please use '--database postgres' or '--database mysql' or choose a different setup.",
|
|
97
|
-
},
|
|
98
|
-
"mongodb-atlas": {
|
|
99
|
-
database: "mongodb",
|
|
100
|
-
errorMessage:
|
|
101
|
-
"MongoDB Atlas setup requires MongoDB database. Please use '--database mongodb' or choose a different setup.",
|
|
102
|
-
},
|
|
103
|
-
supabase: {
|
|
104
|
-
database: "postgres",
|
|
105
|
-
errorMessage:
|
|
106
|
-
"Supabase setup requires PostgreSQL database. Please use '--database postgres' or choose a different setup.",
|
|
107
|
-
},
|
|
108
|
-
d1: {
|
|
109
|
-
database: "sqlite",
|
|
110
|
-
runtime: "workers",
|
|
111
|
-
errorMessage: "Cloudflare D1 setup requires SQLite database and Cloudflare Workers runtime.",
|
|
112
|
-
},
|
|
113
|
-
docker: {
|
|
114
|
-
errorMessage:
|
|
115
|
-
"Docker setup is not compatible with SQLite database or Cloudflare Workers runtime.",
|
|
116
|
-
},
|
|
117
|
-
none: { errorMessage: "" },
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
if (dbSetup && dbSetup !== "none") {
|
|
121
|
-
const validation = setupValidations[dbSetup];
|
|
122
|
-
|
|
123
|
-
if (dbSetup === "planetscale") {
|
|
124
|
-
if (database !== "postgres" && database !== "mysql") {
|
|
125
|
-
exitWithError(validation.errorMessage);
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
if (validation.database && database !== validation.database) {
|
|
129
|
-
exitWithError(validation.errorMessage);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (validation.runtime && runtime !== validation.runtime) {
|
|
134
|
-
exitWithError(validation.errorMessage);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (dbSetup === "docker") {
|
|
138
|
-
if (database === "sqlite") {
|
|
139
|
-
exitWithError(
|
|
140
|
-
"Docker setup is not compatible with SQLite database. SQLite is file-based and doesn't require Docker. Please use '--database postgres', '--database mysql', '--database mongodb', or choose a different setup.",
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
if (runtime === "workers") {
|
|
144
|
-
exitWithError(
|
|
145
|
-
"Docker setup is not compatible with Cloudflare Workers runtime. Workers runtime uses serverless databases (D1) and doesn't support local Docker containers. Please use '--db-setup d1' for SQLite or choose a different runtime.",
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function validateConvexConstraints(
|
|
153
|
-
config: Partial<ProjectConfig>,
|
|
154
|
-
providedFlags: Set<string>,
|
|
155
|
-
) {
|
|
156
|
-
const { backend } = config;
|
|
157
|
-
|
|
158
|
-
if (backend !== "convex") {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const has = (k: string) => providedFlags.has(k);
|
|
163
|
-
|
|
164
|
-
if (has("runtime") && config.runtime !== "none") {
|
|
165
|
-
exitWithError(
|
|
166
|
-
"Convex backend requires '--runtime none'. Please remove the --runtime flag or set it to 'none'.",
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (has("database") && config.database !== "none") {
|
|
171
|
-
exitWithError(
|
|
172
|
-
"Convex backend requires '--database none'. Please remove the --database flag or set it to 'none'.",
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (has("orm") && config.orm !== "none") {
|
|
177
|
-
exitWithError(
|
|
178
|
-
"Convex backend requires '--orm none'. Please remove the --orm flag or set it to 'none'.",
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (has("api") && config.api !== "none") {
|
|
183
|
-
exitWithError(
|
|
184
|
-
"Convex backend requires '--api none'. Please remove the --api flag or set it to 'none'.",
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (has("dbSetup") && config.dbSetup !== "none") {
|
|
189
|
-
exitWithError(
|
|
190
|
-
"Convex backend requires '--db-setup none'. Please remove the --db-setup flag or set it to 'none'.",
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (has("serverDeploy") && config.serverDeploy !== "none") {
|
|
195
|
-
exitWithError(
|
|
196
|
-
"Convex backend requires '--server-deploy none'. Please remove the --server-deploy flag or set it to 'none'.",
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (has("auth") && config.auth === "better-auth") {
|
|
201
|
-
const supportedFrontends = [
|
|
202
|
-
"tanstack-router",
|
|
203
|
-
"tanstack-start",
|
|
204
|
-
"next",
|
|
205
|
-
"native-bare",
|
|
206
|
-
"native-uniwind",
|
|
207
|
-
"native-unistyles",
|
|
208
|
-
];
|
|
209
|
-
const hasSupportedFrontend = config.frontend?.some((f) => supportedFrontends.includes(f));
|
|
210
|
-
|
|
211
|
-
if (!hasSupportedFrontend) {
|
|
212
|
-
exitWithError(
|
|
213
|
-
"Better-Auth with Convex backend requires a supported frontend (TanStack Router, TanStack Start, Next.js, or Native).",
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export function validateBackendNoneConstraints(
|
|
220
|
-
config: Partial<ProjectConfig>,
|
|
221
|
-
providedFlags: Set<string>,
|
|
222
|
-
) {
|
|
223
|
-
const { backend } = config;
|
|
224
|
-
|
|
225
|
-
if (backend !== "none") {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const has = (k: string) => providedFlags.has(k);
|
|
230
|
-
|
|
231
|
-
if (has("runtime") && config.runtime !== "none") {
|
|
232
|
-
exitWithError(
|
|
233
|
-
"Backend 'none' requires '--runtime none'. Please remove the --runtime flag or set it to 'none'.",
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (has("database") && config.database !== "none") {
|
|
238
|
-
exitWithError(
|
|
239
|
-
"Backend 'none' requires '--database none'. Please remove the --database flag or set it to 'none'.",
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (has("orm") && config.orm !== "none") {
|
|
244
|
-
exitWithError(
|
|
245
|
-
"Backend 'none' requires '--orm none'. Please remove the --orm flag or set it to 'none'.",
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (has("api") && config.api !== "none") {
|
|
250
|
-
exitWithError(
|
|
251
|
-
"Backend 'none' requires '--api none'. Please remove the --api flag or set it to 'none'.",
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (has("auth") && config.auth !== "none") {
|
|
256
|
-
exitWithError(
|
|
257
|
-
"Backend 'none' requires '--auth none'. Please remove the --auth flag or set it to 'none'.",
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (has("payments") && config.payments !== "none") {
|
|
262
|
-
exitWithError(
|
|
263
|
-
"Backend 'none' requires '--payments none'. Please remove the --payments flag or set it to 'none'.",
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (has("dbSetup") && config.dbSetup !== "none") {
|
|
268
|
-
exitWithError(
|
|
269
|
-
"Backend 'none' requires '--db-setup none'. Please remove the --db-setup flag or set it to 'none'.",
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (has("serverDeploy") && config.serverDeploy !== "none") {
|
|
274
|
-
exitWithError(
|
|
275
|
-
"Backend 'none' requires '--server-deploy none'. Please remove the --server-deploy flag or set it to 'none'.",
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export function validateSelfBackendConstraints(
|
|
281
|
-
config: Partial<ProjectConfig>,
|
|
282
|
-
providedFlags: Set<string>,
|
|
283
|
-
) {
|
|
284
|
-
const { backend } = config;
|
|
285
|
-
|
|
286
|
-
if (backend !== "self") {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const has = (k: string) => providedFlags.has(k);
|
|
291
|
-
|
|
292
|
-
if (has("runtime") && config.runtime !== "none") {
|
|
293
|
-
exitWithError(
|
|
294
|
-
"Backend 'self' (fullstack) requires '--runtime none'. Please remove the --runtime flag or set it to 'none'.",
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export function validateBackendConstraints(
|
|
300
|
-
config: Partial<ProjectConfig>,
|
|
301
|
-
providedFlags: Set<string>,
|
|
302
|
-
options: CLIInput,
|
|
303
|
-
) {
|
|
304
|
-
const { backend } = config;
|
|
305
|
-
|
|
306
|
-
if (config.auth === "clerk" && backend !== "convex") {
|
|
307
|
-
exitWithError(
|
|
308
|
-
"Clerk authentication is only supported with the Convex backend. Please use '--backend convex' or choose a different auth provider.",
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (backend === "convex" && config.auth === "clerk" && config.frontend) {
|
|
313
|
-
const incompatibleFrontends = config.frontend.filter((f) =>
|
|
314
|
-
["nuxt", "svelte", "solid"].includes(f),
|
|
315
|
-
);
|
|
316
|
-
if (incompatibleFrontends.length > 0) {
|
|
317
|
-
exitWithError(
|
|
318
|
-
`Clerk authentication is not compatible with the following frontends: ${incompatibleFrontends.join(
|
|
319
|
-
", ",
|
|
320
|
-
)}. Please choose a different frontend or auth provider.`,
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (
|
|
326
|
-
providedFlags.has("backend") &&
|
|
327
|
-
backend &&
|
|
328
|
-
backend !== "convex" &&
|
|
329
|
-
backend !== "none" &&
|
|
330
|
-
backend !== "self"
|
|
331
|
-
) {
|
|
332
|
-
if (providedFlags.has("runtime") && options.runtime === "none") {
|
|
333
|
-
exitWithError(
|
|
334
|
-
"'--runtime none' is only supported with '--backend convex', '--backend none', or '--backend self'. Please choose 'bun', 'node', or remove the --runtime flag.",
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (backend === "convex" && providedFlags.has("frontend") && options.frontend) {
|
|
340
|
-
const incompatibleFrontends = options.frontend.filter((f) => f === "solid");
|
|
341
|
-
if (incompatibleFrontends.length > 0) {
|
|
342
|
-
exitWithError(
|
|
343
|
-
`The following frontends are not compatible with '--backend convex': ${incompatibleFrontends.join(
|
|
344
|
-
", ",
|
|
345
|
-
)}. Please choose a different frontend or backend.`,
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export function validateFrontendConstraints(
|
|
352
|
-
config: Partial<ProjectConfig>,
|
|
353
|
-
providedFlags: Set<string>,
|
|
354
|
-
) {
|
|
355
|
-
const { frontend } = config;
|
|
356
|
-
|
|
357
|
-
if (frontend && frontend.length > 0) {
|
|
358
|
-
ensureSingleWebAndNative(frontend);
|
|
359
|
-
|
|
360
|
-
if (providedFlags.has("api") && providedFlags.has("frontend") && config.api) {
|
|
361
|
-
validateApiFrontendCompatibility(config.api, frontend);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const hasWebFrontendFlag = (frontend ?? []).some((f) => isWebFrontend(f));
|
|
366
|
-
validateWebDeployRequiresWebFrontend(config.webDeploy, hasWebFrontendFlag);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
export function validateApiConstraints(config: Partial<ProjectConfig>, options: CLIInput) {
|
|
370
|
-
if (config.api === "none") {
|
|
371
|
-
if (
|
|
372
|
-
options.examples &&
|
|
373
|
-
!(options.examples.length === 1 && options.examples[0] === "none") &&
|
|
374
|
-
options.backend !== "convex" &&
|
|
375
|
-
options.backend !== "none"
|
|
376
|
-
) {
|
|
377
|
-
exitWithError(
|
|
378
|
-
"Cannot use '--examples' when '--api' is set to 'none'. Please remove the --examples flag or choose an API type.",
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
export function validateFullConfig(
|
|
385
|
-
config: Partial<ProjectConfig>,
|
|
386
|
-
providedFlags: Set<string>,
|
|
387
|
-
options: CLIInput,
|
|
388
|
-
) {
|
|
389
|
-
validateDatabaseOrmAuth(config, providedFlags);
|
|
390
|
-
validateDatabaseSetup(config, providedFlags);
|
|
391
|
-
|
|
392
|
-
validateConvexConstraints(config, providedFlags);
|
|
393
|
-
validateBackendNoneConstraints(config, providedFlags);
|
|
394
|
-
validateSelfBackendConstraints(config, providedFlags);
|
|
395
|
-
validateBackendConstraints(config, providedFlags, options);
|
|
396
|
-
|
|
397
|
-
validateFrontendConstraints(config, providedFlags);
|
|
398
|
-
|
|
399
|
-
validateApiConstraints(config, options);
|
|
400
|
-
|
|
401
|
-
validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
|
|
402
|
-
|
|
403
|
-
validateSelfBackendCompatibility(providedFlags, options, config);
|
|
404
|
-
validateWorkersCompatibility(providedFlags, options, config);
|
|
405
|
-
|
|
406
|
-
if (config.runtime === "workers" && config.serverDeploy === "none") {
|
|
407
|
-
exitWithError(
|
|
408
|
-
"Cloudflare Workers runtime requires a server deployment. Please choose 'alchemy' for --server-deploy.",
|
|
409
|
-
);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (
|
|
413
|
-
providedFlags.has("serverDeploy") &&
|
|
414
|
-
config.serverDeploy === "alchemy" &&
|
|
415
|
-
config.runtime !== "workers"
|
|
416
|
-
) {
|
|
417
|
-
exitWithError(
|
|
418
|
-
`Server deployment '${config.serverDeploy}' requires '--runtime workers'. Please use '--runtime workers' or choose a different server deployment.`,
|
|
419
|
-
);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
if (config.addons && config.addons.length > 0) {
|
|
423
|
-
validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
424
|
-
config.addons = [...new Set(config.addons)];
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
validateExamplesCompatibility(
|
|
428
|
-
config.examples ?? [],
|
|
429
|
-
config.backend,
|
|
430
|
-
config.database,
|
|
431
|
-
config.frontend ?? [],
|
|
432
|
-
);
|
|
433
|
-
|
|
434
|
-
validatePaymentsCompatibility(
|
|
435
|
-
config.payments,
|
|
436
|
-
config.auth,
|
|
437
|
-
config.backend,
|
|
438
|
-
config.frontend ?? [],
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
export function validateConfigForProgrammaticUse(config: Partial<ProjectConfig>) {
|
|
443
|
-
try {
|
|
444
|
-
validateDatabaseOrmAuth(config);
|
|
445
|
-
|
|
446
|
-
if (config.frontend && config.frontend.length > 0) {
|
|
447
|
-
ensureSingleWebAndNative(config.frontend);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
validateApiFrontendCompatibility(config.api, config.frontend);
|
|
451
|
-
|
|
452
|
-
validatePaymentsCompatibility(config.payments, config.auth, config.backend, config.frontend);
|
|
453
|
-
|
|
454
|
-
if (config.addons && config.addons.length > 0) {
|
|
455
|
-
validateAddonsAgainstFrontends(config.addons, config.frontend, config.auth);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
validateExamplesCompatibility(
|
|
459
|
-
config.examples ?? [],
|
|
460
|
-
config.backend,
|
|
461
|
-
config.database,
|
|
462
|
-
config.frontend ?? [],
|
|
463
|
-
);
|
|
464
|
-
} catch (error) {
|
|
465
|
-
if (error instanceof Error) {
|
|
466
|
-
throw error;
|
|
467
|
-
}
|
|
468
|
-
throw new Error(String(error));
|
|
469
|
-
}
|
|
470
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import pc from "picocolors";
|
|
2
|
-
import type { ProjectConfig } from "../types";
|
|
3
|
-
|
|
4
|
-
export function displayConfig(config: Partial<ProjectConfig>) {
|
|
5
|
-
const configDisplay: string[] = [];
|
|
6
|
-
|
|
7
|
-
if (config.projectName) {
|
|
8
|
-
configDisplay.push(`${pc.blue("Project Name:")} ${config.projectName}`);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
if (config.frontend !== undefined) {
|
|
12
|
-
const frontend = Array.isArray(config.frontend) ? config.frontend : [config.frontend];
|
|
13
|
-
const frontendText =
|
|
14
|
-
frontend.length > 0 && frontend[0] !== undefined ? frontend.join(", ") : "none";
|
|
15
|
-
configDisplay.push(`${pc.blue("Frontend:")} ${frontendText}`);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (config.backend !== undefined) {
|
|
19
|
-
configDisplay.push(`${pc.blue("Backend:")} ${String(config.backend)}`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (config.runtime !== undefined) {
|
|
23
|
-
configDisplay.push(`${pc.blue("Runtime:")} ${String(config.runtime)}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (config.api !== undefined) {
|
|
27
|
-
configDisplay.push(`${pc.blue("API:")} ${String(config.api)}`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (config.database !== undefined) {
|
|
31
|
-
configDisplay.push(`${pc.blue("Database:")} ${String(config.database)}`);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (config.orm !== undefined) {
|
|
35
|
-
configDisplay.push(`${pc.blue("ORM:")} ${String(config.orm)}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (config.auth !== undefined) {
|
|
39
|
-
configDisplay.push(`${pc.blue("Auth:")} ${String(config.auth)}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (config.payments !== undefined) {
|
|
43
|
-
configDisplay.push(`${pc.blue("Payments:")} ${String(config.payments)}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (config.addons !== undefined) {
|
|
47
|
-
const addons = Array.isArray(config.addons) ? config.addons : [config.addons];
|
|
48
|
-
const addonsText = addons.length > 0 && addons[0] !== undefined ? addons.join(", ") : "none";
|
|
49
|
-
configDisplay.push(`${pc.blue("Addons:")} ${addonsText}`);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (config.examples !== undefined) {
|
|
53
|
-
const examples = Array.isArray(config.examples) ? config.examples : [config.examples];
|
|
54
|
-
const examplesText =
|
|
55
|
-
examples.length > 0 && examples[0] !== undefined ? examples.join(", ") : "none";
|
|
56
|
-
configDisplay.push(`${pc.blue("Examples:")} ${examplesText}`);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (config.git !== undefined) {
|
|
60
|
-
const gitText =
|
|
61
|
-
typeof config.git === "boolean" ? (config.git ? "Yes" : "No") : String(config.git);
|
|
62
|
-
configDisplay.push(`${pc.blue("Git Init:")} ${gitText}`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (config.packageManager !== undefined) {
|
|
66
|
-
configDisplay.push(`${pc.blue("Package Manager:")} ${String(config.packageManager)}`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (config.install !== undefined) {
|
|
70
|
-
const installText =
|
|
71
|
-
typeof config.install === "boolean"
|
|
72
|
-
? config.install
|
|
73
|
-
? "Yes"
|
|
74
|
-
: "No"
|
|
75
|
-
: String(config.install);
|
|
76
|
-
configDisplay.push(`${pc.blue("Install Dependencies:")} ${installText}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (config.dbSetup !== undefined) {
|
|
80
|
-
configDisplay.push(`${pc.blue("Database Setup:")} ${String(config.dbSetup)}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (config.webDeploy !== undefined) {
|
|
84
|
-
configDisplay.push(`${pc.blue("Web Deployment:")} ${String(config.webDeploy)}`);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (config.serverDeploy !== undefined) {
|
|
88
|
-
configDisplay.push(`${pc.blue("Server Deployment:")} ${String(config.serverDeploy)}`);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (configDisplay.length === 0) {
|
|
92
|
-
return pc.yellow("No configuration selected.");
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return configDisplay.join("\n");
|
|
96
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import os from "node:os";
|
|
2
|
-
import { $ } from "execa";
|
|
3
|
-
import pc from "picocolors";
|
|
4
|
-
import type { Database } from "../types";
|
|
5
|
-
import { commandExists } from "./command-exists";
|
|
6
|
-
|
|
7
|
-
export async function isDockerInstalled() {
|
|
8
|
-
return commandExists("docker");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function isDockerRunning() {
|
|
12
|
-
try {
|
|
13
|
-
await $`docker info`;
|
|
14
|
-
return true;
|
|
15
|
-
} catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function getDockerInstallInstructions(platform: string, database: Database) {
|
|
21
|
-
const isMac = platform === "darwin";
|
|
22
|
-
const isWindows = platform === "win32";
|
|
23
|
-
const isLinux = platform === "linux";
|
|
24
|
-
|
|
25
|
-
let installUrl = "";
|
|
26
|
-
let platformName = "";
|
|
27
|
-
|
|
28
|
-
if (isMac) {
|
|
29
|
-
installUrl = "https://docs.docker.com/desktop/setup/install/mac-install/";
|
|
30
|
-
platformName = "macOS";
|
|
31
|
-
} else if (isWindows) {
|
|
32
|
-
installUrl = "https://docs.docker.com/desktop/setup/install/windows-install/";
|
|
33
|
-
platformName = "Windows";
|
|
34
|
-
} else if (isLinux) {
|
|
35
|
-
installUrl = "https://docs.docker.com/desktop/setup/install/linux/";
|
|
36
|
-
platformName = "Linux";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const databaseName =
|
|
40
|
-
database === "mongodb" ? "MongoDB" : database === "mysql" ? "MySQL" : "PostgreSQL";
|
|
41
|
-
|
|
42
|
-
return `${pc.yellow("IMPORTANT:")} Docker required for ${databaseName}. Install for ${platformName}:\n${pc.blue(installUrl)}`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function getDockerStatus(database: Database) {
|
|
46
|
-
const platform = os.platform();
|
|
47
|
-
const installed = await isDockerInstalled();
|
|
48
|
-
|
|
49
|
-
if (!installed) {
|
|
50
|
-
return {
|
|
51
|
-
installed: false,
|
|
52
|
-
running: false,
|
|
53
|
-
message: getDockerInstallInstructions(platform, database),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const running = await isDockerRunning();
|
|
58
|
-
if (!running) {
|
|
59
|
-
return {
|
|
60
|
-
installed: true,
|
|
61
|
-
running: false,
|
|
62
|
-
message: `${pc.yellow("IMPORTANT:")} Docker is installed but not running.`,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
installed: true,
|
|
68
|
-
running: true,
|
|
69
|
-
};
|
|
70
|
-
}
|
package/src/utils/errors.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { cancel } from "@clack/prompts";
|
|
2
|
-
import consola from "consola";
|
|
3
|
-
import pc from "picocolors";
|
|
4
|
-
|
|
5
|
-
function isProgrammatic() {
|
|
6
|
-
return process.env.BTS_PROGRAMMATIC === "1";
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function exitWithError(message: string): never {
|
|
10
|
-
consola.error(pc.red(message));
|
|
11
|
-
if (isProgrammatic()) {
|
|
12
|
-
throw new Error(message);
|
|
13
|
-
}
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function exitCancelled(message = "Operation cancelled"): never {
|
|
18
|
-
cancel(pc.red(message));
|
|
19
|
-
if (isProgrammatic()) {
|
|
20
|
-
throw new Error(message);
|
|
21
|
-
}
|
|
22
|
-
process.exit(0);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function handleError(error: unknown, fallbackMessage?: string): never {
|
|
26
|
-
const message = error instanceof Error ? error.message : fallbackMessage || String(error);
|
|
27
|
-
consola.error(pc.red(message));
|
|
28
|
-
if (isProgrammatic()) {
|
|
29
|
-
throw new Error(message);
|
|
30
|
-
}
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|