create-better-t-stack 3.32.0 → 3.33.1-pr1075.e991845
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/README.md +8 -2
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +1 -1
- package/dist/{src-BZV4gWGl.mjs → src-DTXDyOdP.mjs} +207 -132
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -68,8 +68,8 @@ Options:
|
|
|
68
68
|
--install Install dependencies
|
|
69
69
|
--no-install Skip installing dependencies
|
|
70
70
|
--db-setup <setup> Database setup (turso, d1, neon, supabase, prisma-postgres, planetscale, mongodb-atlas, docker, none)
|
|
71
|
-
--web-deploy <setup> Web deployment (cloudflare, none)
|
|
72
|
-
--server-deploy <setup> Server deployment (cloudflare, none)
|
|
71
|
+
--web-deploy <setup> Web deployment (cloudflare, docker, none)
|
|
72
|
+
--server-deploy <setup> Server deployment (cloudflare, docker, none)
|
|
73
73
|
--backend <framework> Backend framework (hono, express, fastify, elysia, convex, self, none)
|
|
74
74
|
--runtime <runtime> Runtime (bun, node, workers, none)
|
|
75
75
|
--api <type> API type (trpc, orpc, none)
|
|
@@ -223,6 +223,12 @@ Create a self-hosted fullstack project on Cloudflare with D1:
|
|
|
223
223
|
npx create-better-t-stack --backend self --frontend next --api trpc --database sqlite --orm drizzle --db-setup d1 --web-deploy cloudflare
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
+
Create a self-hosted project that ships as Docker containers (web + server + database via Docker Compose):
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
npx create-better-t-stack --frontend tanstack-router --backend hono --runtime bun --database postgres --orm drizzle --db-setup docker --web-deploy docker --server-deploy docker
|
|
230
|
+
```
|
|
231
|
+
|
|
226
232
|
Create a minimal API-only project:
|
|
227
233
|
|
|
228
234
|
```bash
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-
|
|
2
|
+
import { _ as types_exports, i as SchemaNameSchema, l as create, m as getSchemaResult, s as add, u as createBtsCli, v as getLatestCLIVersion } from "./src-DTXDyOdP.mjs";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
5
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/dist/index.d.mts
CHANGED
|
@@ -184,8 +184,8 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
184
184
|
backend?: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self" | undefined;
|
|
185
185
|
runtime?: "none" | "bun" | "node" | "workers" | undefined;
|
|
186
186
|
api?: "none" | "trpc" | "orpc" | undefined;
|
|
187
|
-
webDeploy?: "none" | "cloudflare" | undefined;
|
|
188
|
-
serverDeploy?: "none" | "cloudflare" | undefined;
|
|
187
|
+
webDeploy?: "none" | "docker" | "cloudflare" | undefined;
|
|
188
|
+
serverDeploy?: "none" | "docker" | "cloudflare" | undefined;
|
|
189
189
|
directoryConflict?: "merge" | "overwrite" | "increment" | "error" | undefined;
|
|
190
190
|
renderTitle?: boolean | undefined;
|
|
191
191
|
disableAnalytics?: boolean | undefined;
|
|
@@ -283,8 +283,8 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
283
283
|
backend?: "none" | "hono" | "express" | "fastify" | "elysia" | "convex" | "self" | undefined;
|
|
284
284
|
runtime?: "none" | "bun" | "node" | "workers" | undefined;
|
|
285
285
|
api?: "none" | "trpc" | "orpc" | undefined;
|
|
286
|
-
webDeploy?: "none" | "cloudflare" | undefined;
|
|
287
|
-
serverDeploy?: "none" | "cloudflare" | undefined;
|
|
286
|
+
webDeploy?: "none" | "docker" | "cloudflare" | undefined;
|
|
287
|
+
serverDeploy?: "none" | "docker" | "cloudflare" | undefined;
|
|
288
288
|
directoryConflict?: "merge" | "overwrite" | "increment" | "error" | undefined;
|
|
289
289
|
renderTitle?: boolean | undefined;
|
|
290
290
|
disableAnalytics?: boolean | undefined;
|
|
@@ -363,8 +363,8 @@ declare const router: _$_trpc_server0.TRPCBuiltRouter<{
|
|
|
363
363
|
hooks?: ("cursor" | "windsurf" | "codebuddy" | "claude" | "copilot")[] | undefined;
|
|
364
364
|
} | undefined;
|
|
365
365
|
} | undefined;
|
|
366
|
-
webDeploy?: "none" | "cloudflare" | undefined;
|
|
367
|
-
serverDeploy?: "none" | "cloudflare" | undefined;
|
|
366
|
+
webDeploy?: "none" | "docker" | "cloudflare" | undefined;
|
|
367
|
+
serverDeploy?: "none" | "docker" | "cloudflare" | undefined;
|
|
368
368
|
projectDir?: string | undefined;
|
|
369
369
|
install?: boolean | undefined;
|
|
370
370
|
packageManager?: "bun" | "npm" | "pnpm" | undefined;
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-
|
|
2
|
+
import { C as ProjectCreationError, S as DirectoryConflictError, T as ValidationError, a as TEMPLATE_COUNT, b as CompatibilityError, c as builder, d as createVirtual, f as docs, g as sponsors, h as router, i as SchemaNameSchema, l as create, m as getSchemaResult, n as GeneratorError, o as VirtualFileSystem, p as generate, r as Result, s as add, t as EMBEDDED_TEMPLATES, u as createBtsCli, w as UserCancelledError, x as DatabaseSetupError, y as CLIError } from "./src-DTXDyOdP.mjs";
|
|
3
3
|
export { CLIError, CompatibilityError, DatabaseSetupError, DirectoryConflictError, EMBEDDED_TEMPLATES, GeneratorError, ProjectCreationError, Result, SchemaNameSchema, TEMPLATE_COUNT, UserCancelledError, ValidationError, VirtualFileSystem, add, builder, create, createBtsCli, createVirtual, docs, generate, getSchemaResult, router, sponsors };
|
|
@@ -875,6 +875,12 @@ function validateServerDeployRequiresBackend(serverDeploy, backend) {
|
|
|
875
875
|
if (serverDeploy && serverDeploy !== "none" && (!backend || backend === "none")) return validationErr$1("'--server-deploy' requires a backend. Please select a backend or set '--server-deploy none'.");
|
|
876
876
|
return Result.ok(void 0);
|
|
877
877
|
}
|
|
878
|
+
function validateDockerServerDeploy(serverDeploy, backend, runtime) {
|
|
879
|
+
if (serverDeploy !== "docker") return Result.ok(void 0);
|
|
880
|
+
if (backend === "convex" || backend === "self") return validationErr$1("'--server-deploy docker' requires a separate server backend (hono, express, fastify, elysia). For a fullstack 'self' backend, use '--web-deploy docker' instead.");
|
|
881
|
+
if (runtime === "workers") return validationErr$1("'--server-deploy docker' is not compatible with '--runtime workers'. Use '--runtime bun' or '--runtime node', or choose '--server-deploy cloudflare'.");
|
|
882
|
+
return Result.ok(void 0);
|
|
883
|
+
}
|
|
878
884
|
function validateAddonCompatibility(addon, frontend, _auth, backend, runtime) {
|
|
879
885
|
if (addon === "evlog" && !supportsEvlogAddon(frontend, backend, runtime)) return {
|
|
880
886
|
isCompatible: false,
|
|
@@ -985,7 +991,7 @@ function normalizeValidationMessage(validationMessage) {
|
|
|
985
991
|
async function runWithNavigation(prompt) {
|
|
986
992
|
let goBack = false;
|
|
987
993
|
prompt.on("key", (char) => {
|
|
988
|
-
if (char === "b" && !isFirstPrompt()) {
|
|
994
|
+
if ((char === "b" || char === "B") && !isFirstPrompt()) {
|
|
989
995
|
goBack = true;
|
|
990
996
|
prompt.state = "cancel";
|
|
991
997
|
}
|
|
@@ -1171,6 +1177,10 @@ async function navigableGroupMultiselect(opts) {
|
|
|
1171
1177
|
}
|
|
1172
1178
|
}));
|
|
1173
1179
|
}
|
|
1180
|
+
/** Use the remembered answer as the initial value only while it is still selectable. */
|
|
1181
|
+
function preferValidInitial(options, previous, fallback) {
|
|
1182
|
+
return previous !== void 0 && options.some((o) => o.value === previous) ? previous : fallback;
|
|
1183
|
+
}
|
|
1174
1184
|
//#endregion
|
|
1175
1185
|
//#region src/prompts/addons.ts
|
|
1176
1186
|
function getAddonDisplay(addon) {
|
|
@@ -1310,7 +1320,7 @@ function validateAddonSelection(selected) {
|
|
|
1310
1320
|
"vite-plus"
|
|
1311
1321
|
].includes(addon)) ?? []).length > 1) return "Choose Turborepo, Nx, or Vite+ as your task runner, not more than one.";
|
|
1312
1322
|
}
|
|
1313
|
-
async function getAddonsChoice(addons, frontends, auth, backend, runtime) {
|
|
1323
|
+
async function getAddonsChoice(addons, frontends, auth, backend, runtime, previousValue) {
|
|
1314
1324
|
if (addons !== void 0) return addons;
|
|
1315
1325
|
const allAddons = types_exports.AddonsSchema.options.filter((addon) => addon !== "none");
|
|
1316
1326
|
const groupedOptions = createGroupedOptions();
|
|
@@ -1329,7 +1339,7 @@ async function getAddonsChoice(addons, frontends, auth, backend, runtime) {
|
|
|
1329
1339
|
const response = await navigableGroupMultiselect({
|
|
1330
1340
|
message: "Select addons",
|
|
1331
1341
|
options: groupedOptions,
|
|
1332
|
-
initialValues: DEFAULT_CONFIG.addons.filter((addonValue) => Object.values(groupedOptions).some((options) => options.some((opt) => opt.value === addonValue))),
|
|
1342
|
+
initialValues: (previousValue ?? DEFAULT_CONFIG.addons).filter((addonValue) => Object.values(groupedOptions).some((options) => options.some((opt) => opt.value === addonValue))),
|
|
1333
1343
|
required: false,
|
|
1334
1344
|
validate: validateAddonSelection
|
|
1335
1345
|
});
|
|
@@ -1974,26 +1984,36 @@ async function setupEvlog(config) {
|
|
|
1974
1984
|
/**
|
|
1975
1985
|
* Define a group of prompts that supports going back to previous prompts.
|
|
1976
1986
|
* Returns a result object with all the values, or handles cancel/go-back navigation.
|
|
1987
|
+
* When navigating back, the discarded answers are replayed to the prompts as
|
|
1988
|
+
* `previousAnswer` so they can preselect what the user chose before.
|
|
1977
1989
|
*/
|
|
1978
1990
|
async function navigableGroup(prompts, opts) {
|
|
1979
1991
|
const results = {};
|
|
1992
|
+
const previousAnswers = {};
|
|
1980
1993
|
const promptNames = Object.keys(prompts);
|
|
1981
1994
|
let currentIndex = 0;
|
|
1982
1995
|
let goingBack = false;
|
|
1996
|
+
const stepBack = () => {
|
|
1997
|
+
const prevName = promptNames[currentIndex - 1];
|
|
1998
|
+
previousAnswers[prevName] = results[prevName];
|
|
1999
|
+
delete results[prevName];
|
|
2000
|
+
currentIndex--;
|
|
2001
|
+
};
|
|
1983
2002
|
while (currentIndex < promptNames.length) {
|
|
1984
2003
|
const name = promptNames[currentIndex];
|
|
1985
2004
|
const prompt = prompts[name];
|
|
1986
2005
|
setIsFirstPrompt$1(currentIndex === 0);
|
|
1987
2006
|
setLastPromptShownUI(false);
|
|
1988
|
-
const result = await prompt({
|
|
2007
|
+
const result = await prompt({
|
|
2008
|
+
results,
|
|
2009
|
+
previousAnswer: previousAnswers[name]
|
|
2010
|
+
})?.catch((e) => {
|
|
1989
2011
|
throw e;
|
|
1990
2012
|
});
|
|
1991
2013
|
if (isGoBack(result)) {
|
|
1992
2014
|
goingBack = true;
|
|
1993
2015
|
if (currentIndex > 0) {
|
|
1994
|
-
|
|
1995
|
-
delete results[prevName];
|
|
1996
|
-
currentIndex--;
|
|
2016
|
+
stepBack();
|
|
1997
2017
|
continue;
|
|
1998
2018
|
}
|
|
1999
2019
|
goingBack = false;
|
|
@@ -2009,9 +2029,7 @@ async function navigableGroup(prompts, opts) {
|
|
|
2009
2029
|
}
|
|
2010
2030
|
if (goingBack && !didLastPromptShowUI()) {
|
|
2011
2031
|
if (currentIndex > 0) {
|
|
2012
|
-
|
|
2013
|
-
delete results[prevName];
|
|
2014
|
-
currentIndex--;
|
|
2032
|
+
stepBack();
|
|
2015
2033
|
continue;
|
|
2016
2034
|
}
|
|
2017
2035
|
}
|
|
@@ -4045,7 +4063,7 @@ async function addHandlerInternal(input) {
|
|
|
4045
4063
|
}
|
|
4046
4064
|
//#endregion
|
|
4047
4065
|
//#region src/prompts/api.ts
|
|
4048
|
-
async function getApiChoice(Api, frontend, backend) {
|
|
4066
|
+
async function getApiChoice(Api, frontend, backend, previousValue) {
|
|
4049
4067
|
if (backend === "convex" || backend === "none") return "none";
|
|
4050
4068
|
const allowed = allowedApisForFrontends(frontend ?? []);
|
|
4051
4069
|
if (Api) {
|
|
@@ -4069,7 +4087,7 @@ async function getApiChoice(Api, frontend, backend) {
|
|
|
4069
4087
|
const apiType = await navigableSelect({
|
|
4070
4088
|
message: "Select API type",
|
|
4071
4089
|
options: apiOptions,
|
|
4072
|
-
initialValue: apiOptions[0].value
|
|
4090
|
+
initialValue: preferValidInitial(apiOptions, previousValue, apiOptions[0].value)
|
|
4073
4091
|
});
|
|
4074
4092
|
if (isCancel$1(apiType)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4075
4093
|
return apiType;
|
|
@@ -4095,7 +4113,7 @@ function getAvailableAuthProviders(backend, frontend = []) {
|
|
|
4095
4113
|
if (options.length === 0) return ["none"];
|
|
4096
4114
|
return [...options, "none"];
|
|
4097
4115
|
}
|
|
4098
|
-
async function getAuthChoice(auth, backend, frontend = []) {
|
|
4116
|
+
async function getAuthChoice(auth, backend, frontend = [], previousValue) {
|
|
4099
4117
|
if (auth !== void 0) return auth;
|
|
4100
4118
|
const availableProviders = getAvailableAuthProviders(backend, frontend);
|
|
4101
4119
|
if (availableProviders.length === 1 && availableProviders[0] === "none") return "none";
|
|
@@ -4121,7 +4139,7 @@ async function getAuthChoice(auth, backend, frontend = []) {
|
|
|
4121
4139
|
const response = await navigableSelect({
|
|
4122
4140
|
message: "Select authentication provider",
|
|
4123
4141
|
options,
|
|
4124
|
-
initialValue: options.some((option) => option.value === DEFAULT_CONFIG.auth) ? DEFAULT_CONFIG.auth : "none"
|
|
4142
|
+
initialValue: preferValidInitial(options, previousValue, options.some((option) => option.value === DEFAULT_CONFIG.auth) ? DEFAULT_CONFIG.auth : "none")
|
|
4125
4143
|
});
|
|
4126
4144
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4127
4145
|
return response;
|
|
@@ -4135,7 +4153,7 @@ const FULLSTACK_FRONTENDS = [
|
|
|
4135
4153
|
"svelte",
|
|
4136
4154
|
"astro"
|
|
4137
4155
|
];
|
|
4138
|
-
async function getBackendFrameworkChoice(backendFramework, frontends) {
|
|
4156
|
+
async function getBackendFrameworkChoice(backendFramework, frontends, previousValue) {
|
|
4139
4157
|
if (backendFramework !== void 0) return backendFramework;
|
|
4140
4158
|
const hasIncompatibleFrontend = frontends?.some((f) => f === "solid" || f === "astro");
|
|
4141
4159
|
const hasFullstackFrontend = frontends?.some((f) => FULLSTACK_FRONTENDS.includes(f));
|
|
@@ -4175,14 +4193,14 @@ async function getBackendFrameworkChoice(backendFramework, frontends) {
|
|
|
4175
4193
|
const response = await navigableSelect({
|
|
4176
4194
|
message: "Select backend",
|
|
4177
4195
|
options: backendOptions,
|
|
4178
|
-
initialValue: hasFullstackFrontend ? "self" : DEFAULT_CONFIG.backend
|
|
4196
|
+
initialValue: preferValidInitial(backendOptions, previousValue, hasFullstackFrontend ? "self" : DEFAULT_CONFIG.backend)
|
|
4179
4197
|
});
|
|
4180
4198
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4181
4199
|
return response;
|
|
4182
4200
|
}
|
|
4183
4201
|
//#endregion
|
|
4184
4202
|
//#region src/prompts/database.ts
|
|
4185
|
-
async function getDatabaseChoice(database, backend, runtime) {
|
|
4203
|
+
async function getDatabaseChoice(database, backend, runtime, previousValue) {
|
|
4186
4204
|
if (backend === "convex" || backend === "none") return "none";
|
|
4187
4205
|
if (database !== void 0) return database;
|
|
4188
4206
|
const databaseOptions = [
|
|
@@ -4215,14 +4233,14 @@ async function getDatabaseChoice(database, backend, runtime) {
|
|
|
4215
4233
|
const response = await navigableSelect({
|
|
4216
4234
|
message: "Select database",
|
|
4217
4235
|
options: databaseOptions,
|
|
4218
|
-
initialValue: DEFAULT_CONFIG.database
|
|
4236
|
+
initialValue: preferValidInitial(databaseOptions, previousValue, DEFAULT_CONFIG.database)
|
|
4219
4237
|
});
|
|
4220
4238
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4221
4239
|
return response;
|
|
4222
4240
|
}
|
|
4223
4241
|
//#endregion
|
|
4224
4242
|
//#region src/prompts/database-setup.ts
|
|
4225
|
-
async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
4243
|
+
async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime, previousValue) {
|
|
4226
4244
|
if (backend === "convex") return "none";
|
|
4227
4245
|
if (dbSetup !== void 0) return dbSetup;
|
|
4228
4246
|
if (databaseType === "none") return "none";
|
|
@@ -4314,14 +4332,14 @@ async function getDBSetupChoice(databaseType, dbSetup, _orm, backend, runtime) {
|
|
|
4314
4332
|
const response = await navigableSelect({
|
|
4315
4333
|
message: `Select ${databaseType} setup option`,
|
|
4316
4334
|
options,
|
|
4317
|
-
initialValue: "none"
|
|
4335
|
+
initialValue: preferValidInitial(options, previousValue, "none")
|
|
4318
4336
|
});
|
|
4319
4337
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4320
4338
|
return response;
|
|
4321
4339
|
}
|
|
4322
4340
|
//#endregion
|
|
4323
4341
|
//#region src/prompts/examples.ts
|
|
4324
|
-
async function getExamplesChoice(examples, database, frontends, backend, api) {
|
|
4342
|
+
async function getExamplesChoice(examples, database, frontends, backend, api, previousValue) {
|
|
4325
4343
|
if (examples !== void 0) return examples;
|
|
4326
4344
|
if (backend === "none") return [];
|
|
4327
4345
|
let response = [];
|
|
@@ -4341,15 +4359,27 @@ async function getExamplesChoice(examples, database, frontends, backend, api) {
|
|
|
4341
4359
|
message: "Include examples",
|
|
4342
4360
|
options,
|
|
4343
4361
|
required: false,
|
|
4344
|
-
initialValues: DEFAULT_CONFIG.examples?.filter((ex) => options.some((o) => o.value === ex))
|
|
4362
|
+
initialValues: (previousValue ?? DEFAULT_CONFIG.examples)?.filter((ex) => options.some((o) => o.value === ex))
|
|
4345
4363
|
});
|
|
4346
4364
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4347
4365
|
return response;
|
|
4348
4366
|
}
|
|
4349
4367
|
//#endregion
|
|
4350
4368
|
//#region src/prompts/frontend.ts
|
|
4351
|
-
|
|
4369
|
+
const WEB_FRONTEND_VALUES = [
|
|
4370
|
+
"tanstack-router",
|
|
4371
|
+
"react-router",
|
|
4372
|
+
"next",
|
|
4373
|
+
"nuxt",
|
|
4374
|
+
"svelte",
|
|
4375
|
+
"solid",
|
|
4376
|
+
"astro",
|
|
4377
|
+
"tanstack-start"
|
|
4378
|
+
];
|
|
4379
|
+
async function getFrontendChoice(frontendOptions, backend, auth, previousValue) {
|
|
4352
4380
|
if (frontendOptions !== void 0) return frontendOptions;
|
|
4381
|
+
const previousWeb = previousValue?.find((f) => WEB_FRONTEND_VALUES.includes(f));
|
|
4382
|
+
const previousNative = previousValue?.find((f) => f.startsWith("native-"));
|
|
4353
4383
|
while (true) {
|
|
4354
4384
|
const wasFirstPrompt = isFirstPrompt();
|
|
4355
4385
|
const frontendTypes = await navigableMultiselect({
|
|
@@ -4364,7 +4394,7 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
4364
4394
|
hint: "Create a React Native/Expo app"
|
|
4365
4395
|
}],
|
|
4366
4396
|
required: false,
|
|
4367
|
-
initialValues: ["web"]
|
|
4397
|
+
initialValues: previousValue ? [...previousWeb ? ["web"] : [], ...previousNative ? ["native"] : []] : ["web"]
|
|
4368
4398
|
});
|
|
4369
4399
|
if (isGoBack(frontendTypes)) return GO_BACK_SYMBOL;
|
|
4370
4400
|
if (isCancel$1(frontendTypes)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
@@ -4372,51 +4402,52 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
4372
4402
|
const result = [];
|
|
4373
4403
|
let shouldRestart = false;
|
|
4374
4404
|
if (frontendTypes.includes("web")) {
|
|
4405
|
+
const webOptions = [
|
|
4406
|
+
{
|
|
4407
|
+
value: "tanstack-router",
|
|
4408
|
+
label: "TanStack Router",
|
|
4409
|
+
hint: "Modern and scalable routing for React Applications"
|
|
4410
|
+
},
|
|
4411
|
+
{
|
|
4412
|
+
value: "react-router",
|
|
4413
|
+
label: "React Router",
|
|
4414
|
+
hint: "A user‑obsessed, standards‑focused, multi‑strategy router"
|
|
4415
|
+
},
|
|
4416
|
+
{
|
|
4417
|
+
value: "next",
|
|
4418
|
+
label: "Next.js",
|
|
4419
|
+
hint: "The React Framework for the Web"
|
|
4420
|
+
},
|
|
4421
|
+
{
|
|
4422
|
+
value: "nuxt",
|
|
4423
|
+
label: "Nuxt",
|
|
4424
|
+
hint: "The Progressive Web Framework for Vue.js"
|
|
4425
|
+
},
|
|
4426
|
+
{
|
|
4427
|
+
value: "svelte",
|
|
4428
|
+
label: "Svelte",
|
|
4429
|
+
hint: "web development for the rest of us"
|
|
4430
|
+
},
|
|
4431
|
+
{
|
|
4432
|
+
value: "solid",
|
|
4433
|
+
label: "Solid",
|
|
4434
|
+
hint: "Simple and performant reactivity for building user interfaces"
|
|
4435
|
+
},
|
|
4436
|
+
{
|
|
4437
|
+
value: "astro",
|
|
4438
|
+
label: "Astro",
|
|
4439
|
+
hint: "The web framework for content-driven websites"
|
|
4440
|
+
},
|
|
4441
|
+
{
|
|
4442
|
+
value: "tanstack-start",
|
|
4443
|
+
label: "TanStack Start",
|
|
4444
|
+
hint: "SSR, Server Functions, API Routes and more with TanStack Router"
|
|
4445
|
+
}
|
|
4446
|
+
].filter((option) => isFrontendAllowedWithBackend(option.value, backend, auth));
|
|
4375
4447
|
const webFramework = await navigableSelect({
|
|
4376
4448
|
message: "Choose web",
|
|
4377
|
-
options:
|
|
4378
|
-
|
|
4379
|
-
value: "tanstack-router",
|
|
4380
|
-
label: "TanStack Router",
|
|
4381
|
-
hint: "Modern and scalable routing for React Applications"
|
|
4382
|
-
},
|
|
4383
|
-
{
|
|
4384
|
-
value: "react-router",
|
|
4385
|
-
label: "React Router",
|
|
4386
|
-
hint: "A user‑obsessed, standards‑focused, multi‑strategy router"
|
|
4387
|
-
},
|
|
4388
|
-
{
|
|
4389
|
-
value: "next",
|
|
4390
|
-
label: "Next.js",
|
|
4391
|
-
hint: "The React Framework for the Web"
|
|
4392
|
-
},
|
|
4393
|
-
{
|
|
4394
|
-
value: "nuxt",
|
|
4395
|
-
label: "Nuxt",
|
|
4396
|
-
hint: "The Progressive Web Framework for Vue.js"
|
|
4397
|
-
},
|
|
4398
|
-
{
|
|
4399
|
-
value: "svelte",
|
|
4400
|
-
label: "Svelte",
|
|
4401
|
-
hint: "web development for the rest of us"
|
|
4402
|
-
},
|
|
4403
|
-
{
|
|
4404
|
-
value: "solid",
|
|
4405
|
-
label: "Solid",
|
|
4406
|
-
hint: "Simple and performant reactivity for building user interfaces"
|
|
4407
|
-
},
|
|
4408
|
-
{
|
|
4409
|
-
value: "astro",
|
|
4410
|
-
label: "Astro",
|
|
4411
|
-
hint: "The web framework for content-driven websites"
|
|
4412
|
-
},
|
|
4413
|
-
{
|
|
4414
|
-
value: "tanstack-start",
|
|
4415
|
-
label: "TanStack Start",
|
|
4416
|
-
hint: "SSR, Server Functions, API Routes and more with TanStack Router"
|
|
4417
|
-
}
|
|
4418
|
-
].filter((option) => isFrontendAllowedWithBackend(option.value, backend, auth)),
|
|
4419
|
-
initialValue: DEFAULT_CONFIG.frontend[0]
|
|
4449
|
+
options: webOptions,
|
|
4450
|
+
initialValue: preferValidInitial(webOptions, previousWeb, DEFAULT_CONFIG.frontend[0])
|
|
4420
4451
|
});
|
|
4421
4452
|
if (isGoBack(webFramework)) shouldRestart = true;
|
|
4422
4453
|
else if (isCancel$1(webFramework)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
@@ -4446,7 +4477,7 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
4446
4477
|
hint: "Consistent styling for React Native"
|
|
4447
4478
|
}
|
|
4448
4479
|
],
|
|
4449
|
-
initialValue: "native-bare"
|
|
4480
|
+
initialValue: previousNative ?? "native-bare"
|
|
4450
4481
|
});
|
|
4451
4482
|
if (isGoBack(nativeFramework)) if (frontendTypes.includes("web")) shouldRestart = true;
|
|
4452
4483
|
else {
|
|
@@ -4465,22 +4496,22 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
4465
4496
|
}
|
|
4466
4497
|
//#endregion
|
|
4467
4498
|
//#region src/prompts/git.ts
|
|
4468
|
-
async function getGitChoice(git) {
|
|
4499
|
+
async function getGitChoice(git, previousValue) {
|
|
4469
4500
|
if (git !== void 0) return git;
|
|
4470
4501
|
const response = await navigableConfirm({
|
|
4471
4502
|
message: "Initialize git repository?",
|
|
4472
|
-
initialValue: DEFAULT_CONFIG.git
|
|
4503
|
+
initialValue: previousValue ?? DEFAULT_CONFIG.git
|
|
4473
4504
|
});
|
|
4474
4505
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4475
4506
|
return response;
|
|
4476
4507
|
}
|
|
4477
4508
|
//#endregion
|
|
4478
4509
|
//#region src/prompts/install.ts
|
|
4479
|
-
async function getinstallChoice(install) {
|
|
4510
|
+
async function getinstallChoice(install, previousValue) {
|
|
4480
4511
|
if (install !== void 0) return install;
|
|
4481
4512
|
const response = await navigableConfirm({
|
|
4482
4513
|
message: "Install dependencies?",
|
|
4483
|
-
initialValue: DEFAULT_CONFIG.install
|
|
4514
|
+
initialValue: previousValue ?? DEFAULT_CONFIG.install
|
|
4484
4515
|
});
|
|
4485
4516
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4486
4517
|
return response;
|
|
@@ -4664,6 +4695,7 @@ function validateFullConfig(config, providedFlags, options) {
|
|
|
4664
4695
|
yield* validateFrontendConstraints(config, providedFlags);
|
|
4665
4696
|
yield* validateApiConstraints(config, options);
|
|
4666
4697
|
yield* validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
|
|
4698
|
+
yield* validateDockerServerDeploy(config.serverDeploy, config.backend, config.runtime);
|
|
4667
4699
|
yield* validateSelfBackendCompatibility(providedFlags, options, config);
|
|
4668
4700
|
yield* validateWorkersCompatibility(providedFlags, options, config);
|
|
4669
4701
|
if (config.runtime === "workers" && config.serverDeploy === "none") yield* validationErr("Cloudflare Workers runtime requires a server deployment. Please choose 'cloudflare' for --server-deploy.");
|
|
@@ -4707,7 +4739,7 @@ const ormOptions = {
|
|
|
4707
4739
|
hint: "Lightweight and performant TypeScript ORM"
|
|
4708
4740
|
}
|
|
4709
4741
|
};
|
|
4710
|
-
async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
4742
|
+
async function getORMChoice(orm, hasDatabase, database, backend, runtime, previousValue) {
|
|
4711
4743
|
if (backend === "convex") return "none";
|
|
4712
4744
|
if (!hasDatabase) return "none";
|
|
4713
4745
|
if (orm !== void 0) {
|
|
@@ -4715,18 +4747,20 @@ async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
|
4715
4747
|
if (compat.isErr()) throw compat.error;
|
|
4716
4748
|
return orm;
|
|
4717
4749
|
}
|
|
4750
|
+
const options = database === "mongodb" ? [ormOptions.prisma, ormOptions.mongoose] : [ormOptions.drizzle, ormOptions.prisma];
|
|
4718
4751
|
const response = await navigableSelect({
|
|
4719
4752
|
message: "Select ORM",
|
|
4720
|
-
options
|
|
4721
|
-
initialValue: database === "mongodb" ? "prisma" : runtime === "workers" ? "drizzle" : DEFAULT_CONFIG.orm
|
|
4753
|
+
options,
|
|
4754
|
+
initialValue: preferValidInitial(options, previousValue, database === "mongodb" ? "prisma" : runtime === "workers" ? "drizzle" : DEFAULT_CONFIG.orm)
|
|
4722
4755
|
});
|
|
4723
4756
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4724
4757
|
return response;
|
|
4725
4758
|
}
|
|
4726
4759
|
//#endregion
|
|
4727
4760
|
//#region src/prompts/package-manager.ts
|
|
4728
|
-
async function getPackageManagerChoice(packageManager) {
|
|
4761
|
+
async function getPackageManagerChoice(packageManager, previousValue) {
|
|
4729
4762
|
if (packageManager !== void 0) return packageManager;
|
|
4763
|
+
const detectedPackageManager = getUserPkgManager();
|
|
4730
4764
|
const response = await navigableSelect({
|
|
4731
4765
|
message: "Choose package manager",
|
|
4732
4766
|
options: [
|
|
@@ -4746,36 +4780,37 @@ async function getPackageManagerChoice(packageManager) {
|
|
|
4746
4780
|
hint: "All-in-one JavaScript runtime & toolkit"
|
|
4747
4781
|
}
|
|
4748
4782
|
],
|
|
4749
|
-
initialValue:
|
|
4783
|
+
initialValue: previousValue ?? detectedPackageManager
|
|
4750
4784
|
});
|
|
4751
4785
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4752
4786
|
return response;
|
|
4753
4787
|
}
|
|
4754
4788
|
//#endregion
|
|
4755
4789
|
//#region src/prompts/payments.ts
|
|
4756
|
-
async function getPaymentsChoice(payments, auth, backend, _frontends) {
|
|
4790
|
+
async function getPaymentsChoice(payments, auth, backend, _frontends, previousValue) {
|
|
4757
4791
|
if (payments !== void 0) return payments;
|
|
4758
4792
|
if (backend === "none") return "none";
|
|
4759
4793
|
if (!(auth === "better-auth")) return "none";
|
|
4794
|
+
const options = [{
|
|
4795
|
+
value: "polar",
|
|
4796
|
+
label: "Polar",
|
|
4797
|
+
hint: "Turn your software into a business. 6 lines of code."
|
|
4798
|
+
}, {
|
|
4799
|
+
value: "none",
|
|
4800
|
+
label: "None",
|
|
4801
|
+
hint: "No payments integration"
|
|
4802
|
+
}];
|
|
4760
4803
|
const response = await navigableSelect({
|
|
4761
4804
|
message: "Select payments provider",
|
|
4762
|
-
options
|
|
4763
|
-
|
|
4764
|
-
label: "Polar",
|
|
4765
|
-
hint: "Turn your software into a business. 6 lines of code."
|
|
4766
|
-
}, {
|
|
4767
|
-
value: "none",
|
|
4768
|
-
label: "None",
|
|
4769
|
-
hint: "No payments integration"
|
|
4770
|
-
}],
|
|
4771
|
-
initialValue: DEFAULT_CONFIG.payments
|
|
4805
|
+
options,
|
|
4806
|
+
initialValue: preferValidInitial(options, previousValue, DEFAULT_CONFIG.payments)
|
|
4772
4807
|
});
|
|
4773
4808
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4774
4809
|
return response;
|
|
4775
4810
|
}
|
|
4776
4811
|
//#endregion
|
|
4777
4812
|
//#region src/prompts/runtime.ts
|
|
4778
|
-
async function getRuntimeChoice(runtime, backend) {
|
|
4813
|
+
async function getRuntimeChoice(runtime, backend, previousValue) {
|
|
4779
4814
|
if (backend === "convex" || backend === "none" || backend === "self") return "none";
|
|
4780
4815
|
if (runtime !== void 0) return runtime;
|
|
4781
4816
|
const runtimeOptions = [{
|
|
@@ -4795,19 +4830,56 @@ async function getRuntimeChoice(runtime, backend) {
|
|
|
4795
4830
|
const response = await navigableSelect({
|
|
4796
4831
|
message: "Select runtime",
|
|
4797
4832
|
options: runtimeOptions,
|
|
4798
|
-
initialValue: DEFAULT_CONFIG.runtime
|
|
4833
|
+
initialValue: preferValidInitial(runtimeOptions, previousValue, DEFAULT_CONFIG.runtime)
|
|
4799
4834
|
});
|
|
4800
4835
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4801
4836
|
return response;
|
|
4802
4837
|
}
|
|
4803
4838
|
//#endregion
|
|
4804
4839
|
//#region src/prompts/server-deploy.ts
|
|
4805
|
-
|
|
4840
|
+
const SERVER_APP_BACKENDS = [
|
|
4841
|
+
"hono",
|
|
4842
|
+
"express",
|
|
4843
|
+
"fastify",
|
|
4844
|
+
"elysia"
|
|
4845
|
+
];
|
|
4846
|
+
function getDeploymentDisplay$1(deployment) {
|
|
4847
|
+
if (deployment === "cloudflare") return {
|
|
4848
|
+
label: "Cloudflare",
|
|
4849
|
+
hint: "Deploy to Cloudflare Workers using Alchemy"
|
|
4850
|
+
};
|
|
4851
|
+
if (deployment === "docker") return {
|
|
4852
|
+
label: "Docker",
|
|
4853
|
+
hint: "Self-host with a Dockerfile and docker-compose.yml"
|
|
4854
|
+
};
|
|
4855
|
+
return {
|
|
4856
|
+
label: deployment,
|
|
4857
|
+
hint: `Add ${deployment} deployment`
|
|
4858
|
+
};
|
|
4859
|
+
}
|
|
4860
|
+
async function getServerDeploymentChoice(deployment, runtime, backend, _webDeploy, previousValue) {
|
|
4806
4861
|
if (deployment !== void 0) return deployment;
|
|
4807
|
-
if (backend
|
|
4808
|
-
if (backend !== "hono") return "none";
|
|
4862
|
+
if (!backend || !SERVER_APP_BACKENDS.includes(backend)) return "none";
|
|
4809
4863
|
if (runtime === "workers") return "cloudflare";
|
|
4810
|
-
return "none";
|
|
4864
|
+
if (runtime !== "bun" && runtime !== "node") return "none";
|
|
4865
|
+
const options = ["docker", "none"].map((deploy) => {
|
|
4866
|
+
const { label, hint } = deploy === "none" ? {
|
|
4867
|
+
label: "None",
|
|
4868
|
+
hint: "Skip deployment setup"
|
|
4869
|
+
} : getDeploymentDisplay$1(deploy);
|
|
4870
|
+
return {
|
|
4871
|
+
value: deploy,
|
|
4872
|
+
label,
|
|
4873
|
+
hint
|
|
4874
|
+
};
|
|
4875
|
+
});
|
|
4876
|
+
const response = await navigableSelect({
|
|
4877
|
+
message: "Select server deployment",
|
|
4878
|
+
options,
|
|
4879
|
+
initialValue: preferValidInitial(options, previousValue, DEFAULT_CONFIG.serverDeploy)
|
|
4880
|
+
});
|
|
4881
|
+
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4882
|
+
return response;
|
|
4811
4883
|
}
|
|
4812
4884
|
//#endregion
|
|
4813
4885
|
//#region src/prompts/web-deploy.ts
|
|
@@ -4819,26 +4891,35 @@ function getDeploymentDisplay(deployment) {
|
|
|
4819
4891
|
label: "Cloudflare",
|
|
4820
4892
|
hint: "Deploy to Cloudflare Workers using Alchemy"
|
|
4821
4893
|
};
|
|
4894
|
+
if (deployment === "docker") return {
|
|
4895
|
+
label: "Docker",
|
|
4896
|
+
hint: "Self-host with a Dockerfile and docker-compose.yml"
|
|
4897
|
+
};
|
|
4822
4898
|
return {
|
|
4823
4899
|
label: deployment,
|
|
4824
4900
|
hint: `Add ${deployment} deployment`
|
|
4825
4901
|
};
|
|
4826
4902
|
}
|
|
4827
|
-
async function getDeploymentChoice(deployment, _runtime, backend, frontend = [], dbSetup) {
|
|
4903
|
+
async function getDeploymentChoice(deployment, _runtime, backend, frontend = [], dbSetup, previousValue) {
|
|
4828
4904
|
if (deployment !== void 0) return deployment;
|
|
4829
4905
|
if (!hasWebFrontend(frontend)) return "none";
|
|
4830
4906
|
if (backend === "self" && dbSetup === "d1") return "cloudflare";
|
|
4907
|
+
const options = [
|
|
4908
|
+
"cloudflare",
|
|
4909
|
+
"docker",
|
|
4910
|
+
"none"
|
|
4911
|
+
].map((deploy) => {
|
|
4912
|
+
const { label, hint } = getDeploymentDisplay(deploy);
|
|
4913
|
+
return {
|
|
4914
|
+
value: deploy,
|
|
4915
|
+
label,
|
|
4916
|
+
hint
|
|
4917
|
+
};
|
|
4918
|
+
});
|
|
4831
4919
|
const response = await navigableSelect({
|
|
4832
4920
|
message: "Select web deployment",
|
|
4833
|
-
options
|
|
4834
|
-
|
|
4835
|
-
return {
|
|
4836
|
-
value: deploy,
|
|
4837
|
-
label,
|
|
4838
|
-
hint
|
|
4839
|
-
};
|
|
4840
|
-
}),
|
|
4841
|
-
initialValue: DEFAULT_CONFIG.webDeploy
|
|
4921
|
+
options,
|
|
4922
|
+
initialValue: preferValidInitial(options, previousValue, DEFAULT_CONFIG.webDeploy)
|
|
4842
4923
|
});
|
|
4843
4924
|
if (isCancel$1(response)) throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4844
4925
|
return response;
|
|
@@ -4870,22 +4951,22 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
4870
4951
|
serverDeploy: flags.serverDeploy ?? DEFAULT_CONFIG.serverDeploy
|
|
4871
4952
|
};
|
|
4872
4953
|
const result = await navigableGroup({
|
|
4873
|
-
frontend: () => getFrontendChoice(flags.frontend, flags.backend, flags.auth),
|
|
4874
|
-
backend: ({ results }) => getBackendFrameworkChoice(flags.backend, results.frontend),
|
|
4875
|
-
runtime: ({ results }) => getRuntimeChoice(flags.runtime, results.backend),
|
|
4876
|
-
database: ({ results }) => getDatabaseChoice(flags.database, results.backend, results.runtime),
|
|
4877
|
-
orm: ({ results }) => getORMChoice(flags.orm, results.database !== "none", results.database, results.backend, results.runtime),
|
|
4878
|
-
api: ({ results }) => getApiChoice(flags.api, results.frontend, results.backend),
|
|
4879
|
-
auth: ({ results }) => getAuthChoice(flags.auth, results.backend, results.frontend),
|
|
4880
|
-
payments: ({ results }) => getPaymentsChoice(flags.payments, results.auth, results.backend, results.frontend),
|
|
4881
|
-
addons: ({ results }) => getAddonsChoice(flags.addons, results.frontend, results.auth, results.backend, results.runtime),
|
|
4882
|
-
examples: ({ results }) => getExamplesChoice(flags.examples, results.database, results.frontend, results.backend, results.api),
|
|
4883
|
-
dbSetup: ({ results }) => getDBSetupChoice(results.database ?? "none", flags.dbSetup, results.orm, results.backend, results.runtime),
|
|
4884
|
-
webDeploy: ({ results }) => getDeploymentChoice(flags.webDeploy, results.runtime, results.backend, results.frontend, results.dbSetup),
|
|
4885
|
-
serverDeploy: ({ results }) => getServerDeploymentChoice(flags.serverDeploy, results.runtime, results.backend, results.webDeploy),
|
|
4886
|
-
git: () => getGitChoice(flags.git),
|
|
4887
|
-
packageManager: () => getPackageManagerChoice(flags.packageManager),
|
|
4888
|
-
install: () => getinstallChoice(flags.install)
|
|
4954
|
+
frontend: ({ previousAnswer }) => getFrontendChoice(flags.frontend, flags.backend, flags.auth, previousAnswer),
|
|
4955
|
+
backend: ({ results, previousAnswer }) => getBackendFrameworkChoice(flags.backend, results.frontend, previousAnswer),
|
|
4956
|
+
runtime: ({ results, previousAnswer }) => getRuntimeChoice(flags.runtime, results.backend, previousAnswer),
|
|
4957
|
+
database: ({ results, previousAnswer }) => getDatabaseChoice(flags.database, results.backend, results.runtime, previousAnswer),
|
|
4958
|
+
orm: ({ results, previousAnswer }) => getORMChoice(flags.orm, results.database !== "none", results.database, results.backend, results.runtime, previousAnswer),
|
|
4959
|
+
api: ({ results, previousAnswer }) => getApiChoice(flags.api, results.frontend, results.backend, previousAnswer),
|
|
4960
|
+
auth: ({ results, previousAnswer }) => getAuthChoice(flags.auth, results.backend, results.frontend, previousAnswer),
|
|
4961
|
+
payments: ({ results, previousAnswer }) => getPaymentsChoice(flags.payments, results.auth, results.backend, results.frontend, previousAnswer),
|
|
4962
|
+
addons: ({ results, previousAnswer }) => getAddonsChoice(flags.addons, results.frontend, results.auth, results.backend, results.runtime, previousAnswer),
|
|
4963
|
+
examples: ({ results, previousAnswer }) => getExamplesChoice(flags.examples, results.database, results.frontend, results.backend, results.api, previousAnswer),
|
|
4964
|
+
dbSetup: ({ results, previousAnswer }) => getDBSetupChoice(results.database ?? "none", flags.dbSetup, results.orm, results.backend, results.runtime, previousAnswer),
|
|
4965
|
+
webDeploy: ({ results, previousAnswer }) => getDeploymentChoice(flags.webDeploy, results.runtime, results.backend, results.frontend, results.dbSetup, previousAnswer),
|
|
4966
|
+
serverDeploy: ({ results, previousAnswer }) => getServerDeploymentChoice(flags.serverDeploy, results.runtime, results.backend, results.webDeploy, previousAnswer),
|
|
4967
|
+
git: ({ previousAnswer }) => getGitChoice(flags.git, previousAnswer),
|
|
4968
|
+
packageManager: ({ previousAnswer }) => getPackageManagerChoice(flags.packageManager, previousAnswer),
|
|
4969
|
+
install: ({ previousAnswer }) => getinstallChoice(flags.install, previousAnswer)
|
|
4889
4970
|
}, { onCancel: () => {
|
|
4890
4971
|
throw new UserCancelledError({ message: "Operation cancelled" });
|
|
4891
4972
|
} });
|
|
@@ -4972,24 +5053,14 @@ async function getProjectName(initialName) {
|
|
|
4972
5053
|
*/
|
|
4973
5054
|
function isTelemetryEnabled() {
|
|
4974
5055
|
const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
|
|
4975
|
-
const BTS_TELEMETRY = "
|
|
5056
|
+
const BTS_TELEMETRY = "0";
|
|
4976
5057
|
if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
|
|
4977
5058
|
if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
|
|
4978
5059
|
return true;
|
|
4979
5060
|
}
|
|
4980
5061
|
//#endregion
|
|
4981
5062
|
//#region src/utils/analytics.ts
|
|
4982
|
-
|
|
4983
|
-
async function sendConvexEvent(payload) {
|
|
4984
|
-
await Result.tryPromise({
|
|
4985
|
-
try: () => fetch(CONVEX_INGEST_URL, {
|
|
4986
|
-
method: "POST",
|
|
4987
|
-
headers: { "Content-Type": "application/json" },
|
|
4988
|
-
body: JSON.stringify(payload)
|
|
4989
|
-
}),
|
|
4990
|
-
catch: () => void 0
|
|
4991
|
-
});
|
|
4992
|
-
}
|
|
5063
|
+
async function sendConvexEvent(payload) {}
|
|
4993
5064
|
async function trackProjectCreation(config, disableAnalytics = false) {
|
|
4994
5065
|
if (!isTelemetryEnabled() || disableAnalytics) return;
|
|
4995
5066
|
const { projectName: _projectName, projectDir: _projectDir, relativePath: _relativePath, ...safeConfig } = config;
|
|
@@ -7057,6 +7128,10 @@ function getAlchemyDeployInstructions(runCmd, webDeploy, serverDeploy, backend)
|
|
|
7057
7128
|
if (webDeploy === "cloudflare" && serverDeploy !== "cloudflare" && !isBackendSelf) instructions.push(`${pc.bold("Deploy web with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
|
|
7058
7129
|
else if (serverDeploy === "cloudflare" && webDeploy !== "cloudflare" && !isBackendSelf) instructions.push(`${pc.bold("Deploy server with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
|
|
7059
7130
|
else if (webDeploy === "cloudflare" && (serverDeploy === "cloudflare" || isBackendSelf)) instructions.push(`${pc.bold("Deploy with Cloudflare (Alchemy):")}\n${pc.cyan("•")} Dev: ${`${runCmd} dev`}\n${pc.cyan("•")} Deploy: ${`${runCmd} deploy`}\n${pc.cyan("•")} Destroy: ${`${runCmd} destroy`}`);
|
|
7131
|
+
if (webDeploy === "docker" || serverDeploy === "docker") {
|
|
7132
|
+
const dockerTargets = webDeploy === "docker" && serverDeploy === "docker" ? "web + server" : webDeploy === "docker" ? "web" : "server";
|
|
7133
|
+
instructions.push(`${pc.bold(`Deploy ${dockerTargets} with Docker Compose:`)}\n${pc.cyan("•")} Start: ${`${runCmd} docker:up`}\n${pc.cyan("•")} Logs: ${`${runCmd} docker:logs`}\n${pc.cyan("•")} Stop: ${`${runCmd} docker:down`}\n${pc.cyan("•")} Config: docker-compose.yml`);
|
|
7134
|
+
}
|
|
7060
7135
|
return instructions.length ? `\n${instructions.join("\n")}` : "";
|
|
7061
7136
|
}
|
|
7062
7137
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.33.1-pr1075.e991845",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
"prepublishOnly": "npm run build"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@better-t-stack/template-generator": "
|
|
73
|
-
"@better-t-stack/types": "
|
|
74
|
-
"@clack/core": "^1.
|
|
75
|
-
"@clack/prompts": "^1.
|
|
72
|
+
"@better-t-stack/template-generator": "3.33.1-pr1075.e991845",
|
|
73
|
+
"@better-t-stack/types": "3.33.1-pr1075.e991845",
|
|
74
|
+
"@clack/core": "^1.4.1",
|
|
75
|
+
"@clack/prompts": "^1.5.1",
|
|
76
76
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
77
77
|
"@trpc/server": "^11.17.0",
|
|
78
78
|
"better-result": "^2.9.2",
|