create-better-t-stack 2.33.8-canary.98a850ad → 2.33.9-canary.88769d6d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-D0MPVT22.js → src-Bm5FOLMd.js} +78 -27
- package/package.json +1 -1
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { createCli, trpcServer } from "trpc-cli";
|
|
|
5
5
|
import z from "zod";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import consola, { consola as consola$1 } from "consola";
|
|
8
|
-
import * as fs$1 from "fs-extra";
|
|
9
8
|
import fs from "fs-extra";
|
|
10
9
|
import { fileURLToPath } from "node:url";
|
|
11
10
|
import gradient from "gradient-string";
|
|
@@ -137,7 +136,8 @@ const ADDON_COMPATIBILITY = {
|
|
|
137
136
|
"react-router",
|
|
138
137
|
"nuxt",
|
|
139
138
|
"svelte",
|
|
140
|
-
"solid"
|
|
139
|
+
"solid",
|
|
140
|
+
"next"
|
|
141
141
|
],
|
|
142
142
|
biome: [],
|
|
143
143
|
husky: [],
|
|
@@ -565,6 +565,20 @@ function validateWebDeployRequiresWebFrontend(webDeploy, hasWebFrontendFlag) {
|
|
|
565
565
|
function validateServerDeployRequiresBackend(serverDeploy, backend) {
|
|
566
566
|
if (serverDeploy && serverDeploy !== "none" && (!backend || backend === "none")) exitWithError("'--server-deploy' requires a backend. Please select a backend or set '--server-deploy none'.");
|
|
567
567
|
}
|
|
568
|
+
function validateAddonsAgainstFrontends(addons = [], frontends = []) {
|
|
569
|
+
for (const addon of addons) {
|
|
570
|
+
if (addon === "none") continue;
|
|
571
|
+
const { isCompatible, reason } = validateAddonCompatibility(addon, frontends);
|
|
572
|
+
if (!isCompatible) exitWithError(`Incompatible addon/frontend combination: ${reason}`);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function validateExamplesCompatibility(examples, backend, database, frontend) {
|
|
576
|
+
const examplesArr = examples ?? [];
|
|
577
|
+
if (examplesArr.length === 0 || examplesArr.includes("none")) return;
|
|
578
|
+
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.");
|
|
579
|
+
if (examplesArr.includes("ai") && backend === "elysia") exitWithError("The 'ai' example is not compatible with the Elysia backend.");
|
|
580
|
+
if (examplesArr.includes("ai") && (frontend ?? []).includes("solid")) exitWithError("The 'ai' example is not compatible with the Solid frontend.");
|
|
581
|
+
}
|
|
568
582
|
|
|
569
583
|
//#endregion
|
|
570
584
|
//#region src/prompts/api.ts
|
|
@@ -1298,9 +1312,9 @@ async function getProjectName(initialName) {
|
|
|
1298
1312
|
|
|
1299
1313
|
//#endregion
|
|
1300
1314
|
//#region src/utils/get-latest-cli-version.ts
|
|
1301
|
-
const getLatestCLIVersion =
|
|
1315
|
+
const getLatestCLIVersion = () => {
|
|
1302
1316
|
const packageJsonPath = path.join(PKG_ROOT, "package.json");
|
|
1303
|
-
const packageJsonContent =
|
|
1317
|
+
const packageJsonContent = fs.readJSONSync(packageJsonPath);
|
|
1304
1318
|
return packageJsonContent.version ?? "1.0.0";
|
|
1305
1319
|
};
|
|
1306
1320
|
|
|
@@ -1662,6 +1676,43 @@ function processAndValidateFlags(options, providedFlags, projectName) {
|
|
|
1662
1676
|
validateServerDeployRequiresBackend(config.serverDeploy, config.backend);
|
|
1663
1677
|
return config;
|
|
1664
1678
|
}
|
|
1679
|
+
function validateConfigCompatibility(config) {
|
|
1680
|
+
const effectiveDatabase = config.database;
|
|
1681
|
+
const effectiveBackend = config.backend;
|
|
1682
|
+
const effectiveFrontend = config.frontend;
|
|
1683
|
+
const effectiveApi = config.api;
|
|
1684
|
+
validateApiFrontendCompatibility(effectiveApi, effectiveFrontend);
|
|
1685
|
+
if (config.addons && config.addons.length > 0) {
|
|
1686
|
+
validateAddonsAgainstFrontends(config.addons, effectiveFrontend);
|
|
1687
|
+
config.addons = [...new Set(config.addons)];
|
|
1688
|
+
}
|
|
1689
|
+
validateExamplesCompatibility(config.examples ?? [], effectiveBackend, effectiveDatabase, effectiveFrontend ?? []);
|
|
1690
|
+
}
|
|
1691
|
+
function processProvidedFlagsWithoutValidation(options, projectName) {
|
|
1692
|
+
const config = {};
|
|
1693
|
+
if (options.api) config.api = options.api;
|
|
1694
|
+
if (options.backend) config.backend = options.backend;
|
|
1695
|
+
if (options.database) config.database = options.database;
|
|
1696
|
+
if (options.orm) config.orm = options.orm;
|
|
1697
|
+
if (options.auth !== void 0) config.auth = options.auth;
|
|
1698
|
+
if (options.git !== void 0) config.git = options.git;
|
|
1699
|
+
if (options.install !== void 0) config.install = options.install;
|
|
1700
|
+
if (options.runtime) config.runtime = options.runtime;
|
|
1701
|
+
if (options.dbSetup) config.dbSetup = options.dbSetup;
|
|
1702
|
+
if (options.packageManager) config.packageManager = options.packageManager;
|
|
1703
|
+
if (options.webDeploy) config.webDeploy = options.webDeploy;
|
|
1704
|
+
const derivedName = deriveProjectName(projectName, options.projectDirectory);
|
|
1705
|
+
if (derivedName) {
|
|
1706
|
+
const nameToValidate = projectName ? path.basename(projectName) : derivedName;
|
|
1707
|
+
const result = ProjectNameSchema.safeParse(nameToValidate);
|
|
1708
|
+
if (!result.success) throw new Error(`Invalid project name: ${result.error.issues[0]?.message}`);
|
|
1709
|
+
config.projectName = projectName || derivedName;
|
|
1710
|
+
}
|
|
1711
|
+
if (options.frontend && options.frontend.length > 0) config.frontend = processArrayOption(options.frontend);
|
|
1712
|
+
if (options.addons && options.addons.length > 0) config.addons = processArrayOption(options.addons);
|
|
1713
|
+
if (options.examples && options.examples.length > 0) config.examples = processArrayOption(options.examples);
|
|
1714
|
+
return config;
|
|
1715
|
+
}
|
|
1665
1716
|
function getProvidedFlags(options) {
|
|
1666
1717
|
return new Set(Object.keys(options).filter((key) => options[key] !== void 0));
|
|
1667
1718
|
}
|
|
@@ -2216,20 +2267,16 @@ async function setupDeploymentTemplates(projectDir, context) {
|
|
|
2216
2267
|
}
|
|
2217
2268
|
} else {
|
|
2218
2269
|
if (context.webDeploy === "alchemy") {
|
|
2270
|
+
const alchemyTemplateSrc = path.join(PKG_ROOT, "templates/deploy/alchemy");
|
|
2219
2271
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
2220
|
-
if (await fs.pathExists(webAppDir))
|
|
2221
|
-
const alchemyTemplateSrc = path.join(PKG_ROOT, "templates/deploy/alchemy");
|
|
2222
|
-
if (await fs.pathExists(alchemyTemplateSrc)) await processAndCopyFiles("**/*", alchemyTemplateSrc, webAppDir, context);
|
|
2223
|
-
}
|
|
2272
|
+
if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(webAppDir)) await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, webAppDir, context);
|
|
2224
2273
|
}
|
|
2225
2274
|
if (context.serverDeploy === "alchemy") {
|
|
2275
|
+
const alchemyTemplateSrc = path.join(PKG_ROOT, "templates/deploy/alchemy");
|
|
2226
2276
|
const serverAppDir = path.join(projectDir, "apps/server");
|
|
2227
|
-
if (await fs.pathExists(serverAppDir)) {
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2231
|
-
await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2232
|
-
}
|
|
2277
|
+
if (await fs.pathExists(alchemyTemplateSrc) && await fs.pathExists(serverAppDir)) {
|
|
2278
|
+
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2279
|
+
await processAndCopyFiles("env.d.ts.hbs", alchemyTemplateSrc, serverAppDir, context);
|
|
2233
2280
|
}
|
|
2234
2281
|
}
|
|
2235
2282
|
}
|
|
@@ -2501,7 +2548,7 @@ async function setupUltracite(config, hasHusky) {
|
|
|
2501
2548
|
];
|
|
2502
2549
|
if (editors.length > 0) ultraciteArgs.push("--editors", ...editors);
|
|
2503
2550
|
if (rules.length > 0) ultraciteArgs.push("--rules", ...rules);
|
|
2504
|
-
if (hasHusky) ultraciteArgs.push("--
|
|
2551
|
+
if (hasHusky) ultraciteArgs.push("--integrations", "husky", "lint-staged");
|
|
2505
2552
|
const ultraciteArgsString = ultraciteArgs.join(" ");
|
|
2506
2553
|
const commandWithArgs = `ultracite@latest ${ultraciteArgsString} --skip-install`;
|
|
2507
2554
|
const ultraciteInitCommand = getPackageExecutionCommand(packageManager, commandWithArgs);
|
|
@@ -3342,15 +3389,15 @@ async function setupCombinedAlchemyDeploy(projectDir, packageManager, config) {
|
|
|
3342
3389
|
//#region src/helpers/deployment/workers/workers-next-setup.ts
|
|
3343
3390
|
async function setupNextWorkersDeploy(projectDir, _packageManager) {
|
|
3344
3391
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3345
|
-
if (!await fs
|
|
3392
|
+
if (!await fs.pathExists(webAppDir)) return;
|
|
3346
3393
|
await addPackageDependency({
|
|
3347
3394
|
dependencies: ["@opennextjs/cloudflare"],
|
|
3348
3395
|
devDependencies: ["wrangler"],
|
|
3349
3396
|
projectDir: webAppDir
|
|
3350
3397
|
});
|
|
3351
3398
|
const packageJsonPath = path.join(webAppDir, "package.json");
|
|
3352
|
-
if (await fs
|
|
3353
|
-
const pkg = await fs
|
|
3399
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
3400
|
+
const pkg = await fs.readJson(packageJsonPath);
|
|
3354
3401
|
pkg.scripts = {
|
|
3355
3402
|
...pkg.scripts,
|
|
3356
3403
|
preview: "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
|
@@ -3358,7 +3405,7 @@ async function setupNextWorkersDeploy(projectDir, _packageManager) {
|
|
|
3358
3405
|
upload: "opennextjs-cloudflare build && opennextjs-cloudflare upload",
|
|
3359
3406
|
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
|
|
3360
3407
|
};
|
|
3361
|
-
await fs
|
|
3408
|
+
await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
|
|
3362
3409
|
}
|
|
3363
3410
|
}
|
|
3364
3411
|
|
|
@@ -5902,15 +5949,9 @@ async function createProjectHandler(input) {
|
|
|
5902
5949
|
projectDirectory: input.projectName
|
|
5903
5950
|
};
|
|
5904
5951
|
const providedFlags = getProvidedFlags(cliInput);
|
|
5905
|
-
const flagConfig = processAndValidateFlags(cliInput, providedFlags, finalBaseName);
|
|
5906
|
-
const { projectName: _projectNameFromFlags,...otherFlags } = flagConfig;
|
|
5907
|
-
if (!input.yes && Object.keys(otherFlags).length > 0) {
|
|
5908
|
-
log.info(pc.yellow("Using these pre-selected options:"));
|
|
5909
|
-
log.message(displayConfig(otherFlags));
|
|
5910
|
-
log.message("");
|
|
5911
|
-
}
|
|
5912
5952
|
let config;
|
|
5913
5953
|
if (input.yes) {
|
|
5954
|
+
const flagConfig = processProvidedFlagsWithoutValidation(cliInput, finalBaseName);
|
|
5914
5955
|
config = {
|
|
5915
5956
|
...DEFAULT_CONFIG,
|
|
5916
5957
|
...flagConfig,
|
|
@@ -5918,12 +5959,22 @@ async function createProjectHandler(input) {
|
|
|
5918
5959
|
projectDir: finalResolvedPath,
|
|
5919
5960
|
relativePath: finalPathInput
|
|
5920
5961
|
};
|
|
5962
|
+
validateConfigCompatibility(config);
|
|
5921
5963
|
if (config.backend === "convex") log.info("Due to '--backend convex' flag, the following options have been automatically set: auth=false, database=none, orm=none, api=none, runtime=none, dbSetup=none, examples=todo");
|
|
5922
5964
|
else if (config.backend === "none") log.info("Due to '--backend none', the following options have been automatically set: --auth=false, --database=none, --orm=none, --api=none, --runtime=none, --db-setup=none, --examples=none");
|
|
5923
5965
|
log.info(pc.yellow("Using default/flag options (config prompts skipped):"));
|
|
5924
5966
|
log.message(displayConfig(config));
|
|
5925
5967
|
log.message("");
|
|
5926
|
-
} else
|
|
5968
|
+
} else {
|
|
5969
|
+
const flagConfig = processAndValidateFlags(cliInput, providedFlags, finalBaseName);
|
|
5970
|
+
const { projectName: _projectNameFromFlags,...otherFlags } = flagConfig;
|
|
5971
|
+
if (Object.keys(otherFlags).length > 0) {
|
|
5972
|
+
log.info(pc.yellow("Using these pre-selected options:"));
|
|
5973
|
+
log.message(displayConfig(otherFlags));
|
|
5974
|
+
log.message("");
|
|
5975
|
+
}
|
|
5976
|
+
config = await gatherConfig(flagConfig, finalBaseName, finalResolvedPath, finalPathInput);
|
|
5977
|
+
}
|
|
5927
5978
|
await createProject(config);
|
|
5928
5979
|
const reproducibleCommand = generateReproducibleCommand(config);
|
|
5929
5980
|
log.success(pc.blue(`You can reproduce this setup with the following command:\n${reproducibleCommand}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.33.
|
|
3
|
+
"version": "2.33.9-canary.88769d6d",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|