create-better-t-stack 3.2.4 → 3.2.6-canary.46b928a7
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-BcBhk2Os.js → src-D60cASJW.js} +120 -172
- package/package.json +12 -12
- package/templates/auth/clerk/convex/web/react/tanstack-start/src/start.ts.hbs +8 -0
- package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +4 -5
- package/templates/auth/clerk/convex/web/react/tanstack-start/src/server.ts.hbs +0 -19
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-D60cASJW.js";
|
|
3
3
|
|
|
4
4
|
export { builder, createBtsCli, docs, init, router, sponsors };
|
|
@@ -66,7 +66,7 @@ const dependencyVersionMap = {
|
|
|
66
66
|
"@better-auth/expo": "^1.3.13",
|
|
67
67
|
"@clerk/nextjs": "^6.31.5",
|
|
68
68
|
"@clerk/clerk-react": "^5.45.0",
|
|
69
|
-
"@clerk/tanstack-react-start": "^0.
|
|
69
|
+
"@clerk/tanstack-react-start": "^0.26.3",
|
|
70
70
|
"@clerk/clerk-expo": "^2.14.25",
|
|
71
71
|
"drizzle-orm": "^0.44.2",
|
|
72
72
|
"drizzle-kit": "^0.31.2",
|
|
@@ -334,11 +334,9 @@ function isWebFrontend(value) {
|
|
|
334
334
|
return WEB_FRAMEWORKS.includes(value);
|
|
335
335
|
}
|
|
336
336
|
function splitFrontends(values = []) {
|
|
337
|
-
const web = values.filter((f) => isWebFrontend(f));
|
|
338
|
-
const native = values.filter((f) => f === "native-nativewind" || f === "native-unistyles");
|
|
339
337
|
return {
|
|
340
|
-
web,
|
|
341
|
-
native
|
|
338
|
+
web: values.filter((f) => isWebFrontend(f)),
|
|
339
|
+
native: values.filter((f) => f === "native-nativewind" || f === "native-unistyles")
|
|
342
340
|
};
|
|
343
341
|
}
|
|
344
342
|
function ensureSingleWebAndNative(frontends) {
|
|
@@ -411,13 +409,10 @@ function validateServerDeployRequiresBackend(serverDeploy, backend) {
|
|
|
411
409
|
function validateAddonCompatibility(addon, frontend, _auth) {
|
|
412
410
|
const compatibleFrontends = ADDON_COMPATIBILITY[addon];
|
|
413
411
|
if (compatibleFrontends.length > 0) {
|
|
414
|
-
if (!frontend.some((f) => compatibleFrontends.includes(f))) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
reason: `${addon} addon requires one of these frontends: ${frontendList}`
|
|
419
|
-
};
|
|
420
|
-
}
|
|
412
|
+
if (!frontend.some((f) => compatibleFrontends.includes(f))) return {
|
|
413
|
+
isCompatible: false,
|
|
414
|
+
reason: `${addon} addon requires one of these frontends: ${compatibleFrontends.join(", ")}`
|
|
415
|
+
};
|
|
421
416
|
}
|
|
422
417
|
return { isCompatible: true };
|
|
423
418
|
}
|
|
@@ -546,11 +541,10 @@ async function getAddonsChoice(addons, frontends, auth) {
|
|
|
546
541
|
Object.keys(groupedOptions).forEach((group$1) => {
|
|
547
542
|
if (groupedOptions[group$1].length === 0) delete groupedOptions[group$1];
|
|
548
543
|
});
|
|
549
|
-
const initialValues = DEFAULT_CONFIG.addons.filter((addonValue) => Object.values(groupedOptions).some((options) => options.some((opt) => opt.value === addonValue)));
|
|
550
544
|
const response = await groupMultiselect({
|
|
551
545
|
message: "Select addons",
|
|
552
546
|
options: groupedOptions,
|
|
553
|
-
initialValues,
|
|
547
|
+
initialValues: DEFAULT_CONFIG.addons.filter((addonValue) => Object.values(groupedOptions).some((options) => options.some((opt) => opt.value === addonValue))),
|
|
554
548
|
required: false,
|
|
555
549
|
selectableGroups: false
|
|
556
550
|
});
|
|
@@ -924,46 +918,45 @@ async function getFrontendChoice(frontendOptions, backend, auth) {
|
|
|
924
918
|
if (isCancel(frontendTypes)) return exitCancelled("Operation cancelled");
|
|
925
919
|
const result = [];
|
|
926
920
|
if (frontendTypes.includes("web")) {
|
|
927
|
-
const webOptions = [
|
|
928
|
-
{
|
|
929
|
-
value: "tanstack-router",
|
|
930
|
-
label: "TanStack Router",
|
|
931
|
-
hint: "Modern and scalable routing for React Applications"
|
|
932
|
-
},
|
|
933
|
-
{
|
|
934
|
-
value: "react-router",
|
|
935
|
-
label: "React Router",
|
|
936
|
-
hint: "A user‑obsessed, standards‑focused, multi‑strategy router"
|
|
937
|
-
},
|
|
938
|
-
{
|
|
939
|
-
value: "next",
|
|
940
|
-
label: "Next.js",
|
|
941
|
-
hint: "The React Framework for the Web"
|
|
942
|
-
},
|
|
943
|
-
{
|
|
944
|
-
value: "nuxt",
|
|
945
|
-
label: "Nuxt",
|
|
946
|
-
hint: "The Progressive Web Framework for Vue.js"
|
|
947
|
-
},
|
|
948
|
-
{
|
|
949
|
-
value: "svelte",
|
|
950
|
-
label: "Svelte",
|
|
951
|
-
hint: "web development for the rest of us"
|
|
952
|
-
},
|
|
953
|
-
{
|
|
954
|
-
value: "solid",
|
|
955
|
-
label: "Solid",
|
|
956
|
-
hint: "Simple and performant reactivity for building user interfaces"
|
|
957
|
-
},
|
|
958
|
-
{
|
|
959
|
-
value: "tanstack-start",
|
|
960
|
-
label: "TanStack Start",
|
|
961
|
-
hint: "SSR, Server Functions, API Routes and more with TanStack Router"
|
|
962
|
-
}
|
|
963
|
-
].filter((option) => isFrontendAllowedWithBackend(option.value, backend, auth));
|
|
964
921
|
const webFramework = await select({
|
|
965
922
|
message: "Choose web",
|
|
966
|
-
options:
|
|
923
|
+
options: [
|
|
924
|
+
{
|
|
925
|
+
value: "tanstack-router",
|
|
926
|
+
label: "TanStack Router",
|
|
927
|
+
hint: "Modern and scalable routing for React Applications"
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
value: "react-router",
|
|
931
|
+
label: "React Router",
|
|
932
|
+
hint: "A user‑obsessed, standards‑focused, multi‑strategy router"
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
value: "next",
|
|
936
|
+
label: "Next.js",
|
|
937
|
+
hint: "The React Framework for the Web"
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
value: "nuxt",
|
|
941
|
+
label: "Nuxt",
|
|
942
|
+
hint: "The Progressive Web Framework for Vue.js"
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
value: "svelte",
|
|
946
|
+
label: "Svelte",
|
|
947
|
+
hint: "web development for the rest of us"
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
value: "solid",
|
|
951
|
+
label: "Solid",
|
|
952
|
+
hint: "Simple and performant reactivity for building user interfaces"
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
value: "tanstack-start",
|
|
956
|
+
label: "TanStack Start",
|
|
957
|
+
hint: "SSR, Server Functions, API Routes and more with TanStack Router"
|
|
958
|
+
}
|
|
959
|
+
].filter((option) => isFrontendAllowedWithBackend(option.value, backend, auth)),
|
|
967
960
|
initialValue: DEFAULT_CONFIG.frontend[0]
|
|
968
961
|
});
|
|
969
962
|
if (isCancel(webFramework)) return exitCancelled("Operation cancelled");
|
|
@@ -1036,10 +1029,9 @@ async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
|
1036
1029
|
if (backend === "convex") return "none";
|
|
1037
1030
|
if (!hasDatabase) return "none";
|
|
1038
1031
|
if (orm !== void 0) return orm;
|
|
1039
|
-
const options = [...database === "mongodb" ? [ormOptions.prisma, ormOptions.mongoose] : [ormOptions.drizzle, ormOptions.prisma]];
|
|
1040
1032
|
const response = await select({
|
|
1041
1033
|
message: "Select ORM",
|
|
1042
|
-
options,
|
|
1034
|
+
options: [...database === "mongodb" ? [ormOptions.prisma, ormOptions.mongoose] : [ormOptions.drizzle, ormOptions.prisma]],
|
|
1043
1035
|
initialValue: database === "mongodb" ? "prisma" : runtime === "workers" ? "drizzle" : DEFAULT_CONFIG.orm
|
|
1044
1036
|
});
|
|
1045
1037
|
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
@@ -1050,7 +1042,6 @@ async function getORMChoice(orm, hasDatabase, database, backend, runtime) {
|
|
|
1050
1042
|
//#region src/prompts/package-manager.ts
|
|
1051
1043
|
async function getPackageManagerChoice(packageManager) {
|
|
1052
1044
|
if (packageManager !== void 0) return packageManager;
|
|
1053
|
-
const detectedPackageManager = getUserPkgManager();
|
|
1054
1045
|
const response = await select({
|
|
1055
1046
|
message: "Choose package manager",
|
|
1056
1047
|
options: [
|
|
@@ -1070,7 +1061,7 @@ async function getPackageManagerChoice(packageManager) {
|
|
|
1070
1061
|
hint: "All-in-one JavaScript runtime & toolkit"
|
|
1071
1062
|
}
|
|
1072
1063
|
],
|
|
1073
|
-
initialValue:
|
|
1064
|
+
initialValue: getUserPkgManager()
|
|
1074
1065
|
});
|
|
1075
1066
|
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
1076
1067
|
return response;
|
|
@@ -1219,21 +1210,20 @@ function getDeploymentDisplay(deployment) {
|
|
|
1219
1210
|
async function getDeploymentChoice(deployment, _runtime, _backend, frontend = []) {
|
|
1220
1211
|
if (deployment !== void 0) return deployment;
|
|
1221
1212
|
if (!hasWebFrontend(frontend)) return "none";
|
|
1222
|
-
const options = [
|
|
1223
|
-
"wrangler",
|
|
1224
|
-
"alchemy",
|
|
1225
|
-
"none"
|
|
1226
|
-
].map((deploy) => {
|
|
1227
|
-
const { label, hint } = getDeploymentDisplay(deploy);
|
|
1228
|
-
return {
|
|
1229
|
-
value: deploy,
|
|
1230
|
-
label,
|
|
1231
|
-
hint
|
|
1232
|
-
};
|
|
1233
|
-
});
|
|
1234
1213
|
const response = await select({
|
|
1235
1214
|
message: "Select web deployment",
|
|
1236
|
-
options
|
|
1215
|
+
options: [
|
|
1216
|
+
"wrangler",
|
|
1217
|
+
"alchemy",
|
|
1218
|
+
"none"
|
|
1219
|
+
].map((deploy) => {
|
|
1220
|
+
const { label, hint } = getDeploymentDisplay(deploy);
|
|
1221
|
+
return {
|
|
1222
|
+
value: deploy,
|
|
1223
|
+
label,
|
|
1224
|
+
hint
|
|
1225
|
+
};
|
|
1226
|
+
}),
|
|
1237
1227
|
initialValue: DEFAULT_CONFIG.webDeploy
|
|
1238
1228
|
});
|
|
1239
1229
|
if (isCancel(response)) return exitCancelled("Operation cancelled");
|
|
@@ -1333,10 +1323,8 @@ function validateDirectoryName(name) {
|
|
|
1333
1323
|
async function getProjectName(initialName) {
|
|
1334
1324
|
if (initialName) {
|
|
1335
1325
|
if (initialName === ".") return initialName;
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
const projectDir = path.resolve(process.cwd(), initialName);
|
|
1339
|
-
if (isPathWithinCwd(projectDir)) return initialName;
|
|
1326
|
+
if (!validateDirectoryName(path.basename(initialName))) {
|
|
1327
|
+
if (isPathWithinCwd(path.resolve(process.cwd(), initialName))) return initialName;
|
|
1340
1328
|
consola.error(pc.red("Project path must be within current directory"));
|
|
1341
1329
|
}
|
|
1342
1330
|
}
|
|
@@ -1356,12 +1344,10 @@ async function getProjectName(initialName) {
|
|
|
1356
1344
|
defaultValue: defaultName,
|
|
1357
1345
|
validate: (value) => {
|
|
1358
1346
|
const nameToUse = String(value ?? "").trim() || defaultName;
|
|
1359
|
-
const
|
|
1360
|
-
const validationError = validateDirectoryName(finalDirName);
|
|
1347
|
+
const validationError = validateDirectoryName(path.basename(nameToUse));
|
|
1361
1348
|
if (validationError) return validationError;
|
|
1362
1349
|
if (nameToUse !== ".") {
|
|
1363
|
-
|
|
1364
|
-
if (!isPathWithinCwd(projectDir)) return "Project path must be within current directory";
|
|
1350
|
+
if (!isPathWithinCwd(path.resolve(process.cwd(), nameToUse))) return "Project path must be within current directory";
|
|
1365
1351
|
}
|
|
1366
1352
|
}
|
|
1367
1353
|
});
|
|
@@ -1389,7 +1375,7 @@ const getLatestCLIVersion = () => {
|
|
|
1389
1375
|
*/
|
|
1390
1376
|
function isTelemetryEnabled() {
|
|
1391
1377
|
const BTS_TELEMETRY_DISABLED = process.env.BTS_TELEMETRY_DISABLED;
|
|
1392
|
-
const BTS_TELEMETRY = "
|
|
1378
|
+
const BTS_TELEMETRY = "0";
|
|
1393
1379
|
if (BTS_TELEMETRY_DISABLED !== void 0) return BTS_TELEMETRY_DISABLED !== "1";
|
|
1394
1380
|
if (BTS_TELEMETRY !== void 0) return BTS_TELEMETRY === "1";
|
|
1395
1381
|
return true;
|
|
@@ -1397,8 +1383,8 @@ function isTelemetryEnabled() {
|
|
|
1397
1383
|
|
|
1398
1384
|
//#endregion
|
|
1399
1385
|
//#region src/utils/analytics.ts
|
|
1400
|
-
const POSTHOG_API_KEY = "
|
|
1401
|
-
const POSTHOG_HOST = "
|
|
1386
|
+
const POSTHOG_API_KEY = "random";
|
|
1387
|
+
const POSTHOG_HOST = "random";
|
|
1402
1388
|
function generateSessionId() {
|
|
1403
1389
|
const rand = Math.random().toString(36).slice(2);
|
|
1404
1390
|
return `cli_${Date.now().toString(36)}${rand}`;
|
|
@@ -1552,11 +1538,9 @@ async function handleDirectoryConflict(currentPathInput, silent = false) {
|
|
|
1552
1538
|
finalPathInput: currentPathInput,
|
|
1553
1539
|
shouldClearDirectory: false
|
|
1554
1540
|
};
|
|
1555
|
-
case "rename":
|
|
1541
|
+
case "rename":
|
|
1556
1542
|
log.info("Please choose a different project name or path.");
|
|
1557
|
-
|
|
1558
|
-
return await handleDirectoryConflict(newPathInput);
|
|
1559
|
-
}
|
|
1543
|
+
return await handleDirectoryConflict(await getProjectName(void 0));
|
|
1560
1544
|
case "cancel": return exitCancelled("Operation cancelled.");
|
|
1561
1545
|
}
|
|
1562
1546
|
}
|
|
@@ -1621,8 +1605,7 @@ const catppuccinTheme = {
|
|
|
1621
1605
|
const renderTitle = () => {
|
|
1622
1606
|
const terminalWidth = process.stdout.columns || 80;
|
|
1623
1607
|
const titleLines = TITLE_TEXT.split("\n");
|
|
1624
|
-
|
|
1625
|
-
if (terminalWidth < titleWidth) console.log(gradient(Object.values(catppuccinTheme)).multiline(`
|
|
1608
|
+
if (terminalWidth < Math.max(...titleLines.map((line) => line.length))) console.log(gradient(Object.values(catppuccinTheme)).multiline(`
|
|
1626
1609
|
╔══════════════════╗
|
|
1627
1610
|
║ Better T Stack ║
|
|
1628
1611
|
╚══════════════════╝
|
|
@@ -1904,10 +1887,7 @@ function processAndValidateFlags(options, providedFlags, projectName) {
|
|
|
1904
1887
|
return config;
|
|
1905
1888
|
}
|
|
1906
1889
|
function processProvidedFlagsWithoutValidation(options, projectName) {
|
|
1907
|
-
if (!options.yolo)
|
|
1908
|
-
const providedFlags = getProvidedFlags(options);
|
|
1909
|
-
validateYesFlagCombination(options, providedFlags);
|
|
1910
|
-
}
|
|
1890
|
+
if (!options.yolo) validateYesFlagCombination(options, getProvidedFlags(options));
|
|
1911
1891
|
const config = processFlags(options, projectName);
|
|
1912
1892
|
const validatedProjectName = extractAndValidateProjectName(projectName, options.projectDirectory, true);
|
|
1913
1893
|
if (validatedProjectName) config.projectName = validatedProjectName;
|
|
@@ -2088,8 +2068,7 @@ async function setupFumadocs(config) {
|
|
|
2088
2068
|
initialValue: "next-mdx"
|
|
2089
2069
|
});
|
|
2090
2070
|
if (isCancel(template)) return exitCancelled("Operation cancelled");
|
|
2091
|
-
const
|
|
2092
|
-
const fumadocsInitCommand = getPackageExecutionCommand(packageManager, commandWithArgs);
|
|
2071
|
+
const fumadocsInitCommand = getPackageExecutionCommand(packageManager, `create-fumadocs-app@latest fumadocs --template ${TEMPLATES[template].value} --src --no-install --pm ${packageManager} --no-eslint --no-git`);
|
|
2093
2072
|
const s = spinner();
|
|
2094
2073
|
s.start("Setting up Fumadocs...");
|
|
2095
2074
|
const appsDir = path.join(projectDir, "apps");
|
|
@@ -2176,8 +2155,7 @@ async function setupRuler(config) {
|
|
|
2176
2155
|
const s = spinner();
|
|
2177
2156
|
s.start("Applying rules with Ruler...");
|
|
2178
2157
|
try {
|
|
2179
|
-
|
|
2180
|
-
await execa(rulerApplyCmd, {
|
|
2158
|
+
await execa(getPackageExecutionCommand(packageManager, `@intellectronica/ruler@latest apply --agents ${selectedEditors.join(",")} --local-only`), {
|
|
2181
2159
|
cwd: projectDir,
|
|
2182
2160
|
env: { CI: "true" },
|
|
2183
2161
|
shell: true
|
|
@@ -2211,7 +2189,7 @@ async function setupStarlight(config) {
|
|
|
2211
2189
|
const s = spinner();
|
|
2212
2190
|
try {
|
|
2213
2191
|
s.start("Setting up Starlight docs...");
|
|
2214
|
-
const
|
|
2192
|
+
const starlightInitCommand = getPackageExecutionCommand(packageManager, `create-astro@latest ${[
|
|
2215
2193
|
"docs",
|
|
2216
2194
|
"--template",
|
|
2217
2195
|
"starlight",
|
|
@@ -2220,8 +2198,7 @@ async function setupStarlight(config) {
|
|
|
2220
2198
|
"tailwind",
|
|
2221
2199
|
"--no-git",
|
|
2222
2200
|
"--skip-houston"
|
|
2223
|
-
].join(" ")}
|
|
2224
|
-
const starlightInitCommand = getPackageExecutionCommand(packageManager, commandWithArgs);
|
|
2201
|
+
].join(" ")}`);
|
|
2225
2202
|
const appsDir = path.join(projectDir, "apps");
|
|
2226
2203
|
await fs.ensureDir(appsDir);
|
|
2227
2204
|
await execa(starlightInitCommand, {
|
|
@@ -2268,7 +2245,7 @@ async function setupTauri(config) {
|
|
|
2268
2245
|
const hasNext = frontend.includes("next");
|
|
2269
2246
|
const devUrl = hasReactRouter || hasSvelte ? "http://localhost:5173" : hasNext ? "http://localhost:3001" : "http://localhost:3001";
|
|
2270
2247
|
const frontendDist = hasNuxt ? "../.output/public" : hasSvelte ? "../build" : hasNext ? "../.next" : hasReactRouter ? "../build/client" : "../dist";
|
|
2271
|
-
|
|
2248
|
+
await execa(getPackageExecutionCommand(packageManager, `@tauri-apps/cli@latest ${[
|
|
2272
2249
|
"init",
|
|
2273
2250
|
`--app-name=${path.basename(projectDir)}`,
|
|
2274
2251
|
`--window-title=${path.basename(projectDir)}`,
|
|
@@ -2276,9 +2253,7 @@ async function setupTauri(config) {
|
|
|
2276
2253
|
`--dev-url=${devUrl}`,
|
|
2277
2254
|
`--before-dev-command="${packageManager} run dev"`,
|
|
2278
2255
|
`--before-build-command="${packageManager} run build"`
|
|
2279
|
-
].join(" ")}
|
|
2280
|
-
const tauriInitCommand = getPackageExecutionCommand(packageManager, commandWithArgs);
|
|
2281
|
-
await execa(tauriInitCommand, {
|
|
2256
|
+
].join(" ")}`), {
|
|
2282
2257
|
cwd: clientPackageDir,
|
|
2283
2258
|
env: { CI: "true" },
|
|
2284
2259
|
shell: true
|
|
@@ -2350,8 +2325,7 @@ async function setupUltracite(config, hasHusky) {
|
|
|
2350
2325
|
if (editors.length > 0) ultraciteArgs.push("--editors", ...editors);
|
|
2351
2326
|
if (rules.length > 0) ultraciteArgs.push("--rules", ...rules);
|
|
2352
2327
|
if (hasHusky) ultraciteArgs.push("--integrations", "husky", "lint-staged");
|
|
2353
|
-
const
|
|
2354
|
-
const ultraciteInitCommand = getPackageExecutionCommand(packageManager, commandWithArgs);
|
|
2328
|
+
const ultraciteInitCommand = getPackageExecutionCommand(packageManager, `ultracite@latest ${ultraciteArgs.join(" ")} --skip-install`);
|
|
2355
2329
|
const s = spinner();
|
|
2356
2330
|
s.start("Setting up Ultracite...");
|
|
2357
2331
|
await execa(ultraciteInitCommand, {
|
|
@@ -2738,8 +2712,7 @@ async function processAndCopyFiles(sourcePattern, baseSourceDir, destDir, contex
|
|
|
2738
2712
|
}
|
|
2739
2713
|
}
|
|
2740
2714
|
async function copyBaseTemplate(projectDir, context) {
|
|
2741
|
-
|
|
2742
|
-
await processAndCopyFiles(["**/*"], templateDir, projectDir, context);
|
|
2715
|
+
await processAndCopyFiles(["**/*"], path.join(PKG_ROOT, "templates/base"), projectDir, context);
|
|
2743
2716
|
}
|
|
2744
2717
|
async function setupFrontendTemplates(projectDir, context) {
|
|
2745
2718
|
const hasReactWeb = context.frontend.some((f) => [
|
|
@@ -3191,8 +3164,7 @@ async function setupDeploymentTemplates(projectDir, context) {
|
|
|
3191
3164
|
if (context.webDeploy === "alchemy" && (context.serverDeploy === "alchemy" || isBackendSelf)) {
|
|
3192
3165
|
if (await fs.pathExists(alchemyTemplateSrc)) {
|
|
3193
3166
|
const webAppDir = path.join(projectDir, "apps/web");
|
|
3194
|
-
|
|
3195
|
-
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, destDir, context);
|
|
3167
|
+
await processAndCopyFiles("alchemy.run.ts.hbs", alchemyTemplateSrc, isBackendSelf && await fs.pathExists(webAppDir) ? webAppDir : projectDir, context);
|
|
3196
3168
|
await addEnvDtsToPackages(projectDir, context, alchemyTemplateSrc);
|
|
3197
3169
|
}
|
|
3198
3170
|
} else {
|
|
@@ -3289,16 +3261,14 @@ async function addAddonsToProject(input) {
|
|
|
3289
3261
|
await setupAddonsTemplate(projectDir, config);
|
|
3290
3262
|
await setupAddons(config, true);
|
|
3291
3263
|
const currentAddons = detectedConfig.addons || [];
|
|
3292
|
-
|
|
3293
|
-
await updateBtsConfig(projectDir, { addons: mergedAddons });
|
|
3264
|
+
await updateBtsConfig(projectDir, { addons: [...new Set([...currentAddons, ...input.addons])] });
|
|
3294
3265
|
if (config.install) await installDependencies({
|
|
3295
3266
|
projectDir,
|
|
3296
3267
|
packageManager: config.packageManager
|
|
3297
3268
|
});
|
|
3298
3269
|
else if (!input.suppressInstallMessage) log.info(pc.yellow(`Run ${pc.bold(`${config.packageManager} install`)} to install dependencies`));
|
|
3299
3270
|
} catch (error) {
|
|
3300
|
-
|
|
3301
|
-
exitWithError(`Error adding addons: ${message}`);
|
|
3271
|
+
exitWithError(`Error adding addons: ${error instanceof Error ? error.message : String(error)}`);
|
|
3302
3272
|
}
|
|
3303
3273
|
}
|
|
3304
3274
|
|
|
@@ -3342,8 +3312,7 @@ async function generateCloudflareWorkerTypes({ serverDir, packageManager }) {
|
|
|
3342
3312
|
const s = spinner();
|
|
3343
3313
|
try {
|
|
3344
3314
|
s.start("Generating Cloudflare Workers types...");
|
|
3345
|
-
|
|
3346
|
-
await execa(runCmd, {
|
|
3315
|
+
await execa(getPackageExecutionCommand(packageManager, "wrangler types --env-interface CloudflareBindings"), {
|
|
3347
3316
|
cwd: serverDir,
|
|
3348
3317
|
shell: true
|
|
3349
3318
|
});
|
|
@@ -4017,8 +3986,7 @@ async function addDeploymentToProject(input) {
|
|
|
4017
3986
|
});
|
|
4018
3987
|
else if (!input.suppressInstallMessage) log.info(pc.yellow(`Run ${pc.bold(`${config.packageManager} install`)} to install dependencies`));
|
|
4019
3988
|
} catch (error) {
|
|
4020
|
-
|
|
4021
|
-
exitWithError(`Error adding deployment: ${message}`);
|
|
3989
|
+
exitWithError(`Error adding deployment: ${error instanceof Error ? error.message : String(error)}`);
|
|
4022
3990
|
}
|
|
4023
3991
|
}
|
|
4024
3992
|
|
|
@@ -4337,6 +4305,10 @@ async function setupApi(config) {
|
|
|
4337
4305
|
});
|
|
4338
4306
|
}
|
|
4339
4307
|
}
|
|
4308
|
+
if (config.auth === "better-auth" && (backend === "express" || backend === "fastify")) await addPackageDependency({
|
|
4309
|
+
dependencies: ["better-auth"],
|
|
4310
|
+
projectDir: apiPackageDir
|
|
4311
|
+
});
|
|
4340
4312
|
if (webDirExists && apiDeps.web) await addPackageDependency({
|
|
4341
4313
|
dependencies: apiDeps.web.dependencies,
|
|
4342
4314
|
devDependencies: apiDeps.web.devDependencies,
|
|
@@ -4442,8 +4414,7 @@ async function setupBetterAuthPlugins(projectDir, config) {
|
|
|
4442
4414
|
if (betterAuthCall) {
|
|
4443
4415
|
const configObject = betterAuthCall.getArguments()[0];
|
|
4444
4416
|
if (configObject && configObject.getKind() === SyntaxKind.ObjectLiteralExpression) {
|
|
4445
|
-
const
|
|
4446
|
-
const pluginsArray = ensureArrayProperty(objLiteral, "plugins");
|
|
4417
|
+
const pluginsArray = ensureArrayProperty(configObject.asKindOrThrow(SyntaxKind.ObjectLiteralExpression), "plugins");
|
|
4447
4418
|
pluginsToAdd.forEach((plugin) => {
|
|
4448
4419
|
pluginsArray.addElement(plugin);
|
|
4449
4420
|
});
|
|
@@ -4681,11 +4652,9 @@ async function setupEnvironmentVariables(config) {
|
|
|
4681
4652
|
const clientDir = path.join(projectDir, "apps/web");
|
|
4682
4653
|
if (await fs.pathExists(clientDir)) {
|
|
4683
4654
|
const baseVar = getClientServerVar(frontend, backend);
|
|
4684
|
-
const envVarName = backend === "convex" ? getConvexVar(frontend) : baseVar.key;
|
|
4685
|
-
const serverUrl = backend === "convex" ? "https://<YOUR_CONVEX_URL>" : baseVar.value;
|
|
4686
4655
|
const clientVars = [{
|
|
4687
|
-
key:
|
|
4688
|
-
value:
|
|
4656
|
+
key: backend === "convex" ? getConvexVar(frontend) : baseVar.key,
|
|
4657
|
+
value: backend === "convex" ? "https://<YOUR_CONVEX_URL>" : baseVar.value,
|
|
4689
4658
|
condition: backend === "convex" ? true : baseVar.write
|
|
4690
4659
|
}];
|
|
4691
4660
|
if (backend === "convex" && auth === "clerk") {
|
|
@@ -4860,14 +4829,12 @@ ${hasWeb ? "# npx convex env set SITE_URL http://localhost:3001\n" : ""}
|
|
|
4860
4829
|
} else if (await fs.pathExists(serverDir)) await addEnvVariablesToFile(path.join(serverDir, ".env"), serverVars);
|
|
4861
4830
|
const isUnifiedAlchemy = webDeploy === "alchemy" && serverDeploy === "alchemy";
|
|
4862
4831
|
const isIndividualAlchemy = webDeploy === "alchemy" || serverDeploy === "alchemy";
|
|
4863
|
-
if (isUnifiedAlchemy) {
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
}]);
|
|
4870
|
-
} else if (isIndividualAlchemy) {
|
|
4832
|
+
if (isUnifiedAlchemy) await addEnvVariablesToFile(path.join(projectDir, ".env"), [{
|
|
4833
|
+
key: "ALCHEMY_PASSWORD",
|
|
4834
|
+
value: "please-change-this",
|
|
4835
|
+
condition: true
|
|
4836
|
+
}]);
|
|
4837
|
+
else if (isIndividualAlchemy) {
|
|
4871
4838
|
if (webDeploy === "alchemy") {
|
|
4872
4839
|
const webDir = path.join(projectDir, "apps/web");
|
|
4873
4840
|
if (await fs.pathExists(webDir)) await addEnvVariablesToFile(path.join(webDir, ".env"), [{
|
|
@@ -4929,10 +4896,9 @@ async function setupCloudflareD1(config) {
|
|
|
4929
4896
|
try {
|
|
4930
4897
|
await addEnvVariablesToFile(envPath, variables);
|
|
4931
4898
|
} catch (_err) {}
|
|
4932
|
-
const serverDir = path.join(projectDir, backend === "self" ? "apps/web" : "apps/server");
|
|
4933
4899
|
await addPackageDependency({
|
|
4934
4900
|
dependencies: ["@prisma/adapter-d1"],
|
|
4935
|
-
projectDir:
|
|
4901
|
+
projectDir: path.join(projectDir, backend === "self" ? "apps/web" : "apps/server")
|
|
4936
4902
|
});
|
|
4937
4903
|
}
|
|
4938
4904
|
}
|
|
@@ -4950,13 +4916,11 @@ async function setupDockerCompose(config) {
|
|
|
4950
4916
|
}
|
|
4951
4917
|
async function writeEnvFile$4(projectDir, database, projectName, backend) {
|
|
4952
4918
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
4953
|
-
|
|
4954
|
-
const variables = [{
|
|
4919
|
+
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
4955
4920
|
key: "DATABASE_URL",
|
|
4956
4921
|
value: getDatabaseUrl(database, projectName),
|
|
4957
4922
|
condition: true
|
|
4958
|
-
}];
|
|
4959
|
-
await addEnvVariablesToFile(envPath, variables);
|
|
4923
|
+
}]);
|
|
4960
4924
|
}
|
|
4961
4925
|
function getDatabaseUrl(database, projectName) {
|
|
4962
4926
|
switch (database) {
|
|
@@ -5026,13 +4990,11 @@ async function initMongoDBAtlas(serverDir) {
|
|
|
5026
4990
|
async function writeEnvFile$3(projectDir, backend, config) {
|
|
5027
4991
|
try {
|
|
5028
4992
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5029
|
-
|
|
5030
|
-
const variables = [{
|
|
4993
|
+
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
5031
4994
|
key: "DATABASE_URL",
|
|
5032
4995
|
value: config?.connectionString ?? "mongodb://localhost:27017/mydb",
|
|
5033
4996
|
condition: true
|
|
5034
|
-
}];
|
|
5035
|
-
await addEnvVariablesToFile(envPath, variables);
|
|
4997
|
+
}]);
|
|
5036
4998
|
} catch (_error) {
|
|
5037
4999
|
consola.error("Failed to update environment configuration");
|
|
5038
5000
|
}
|
|
@@ -5155,8 +5117,7 @@ async function executeNeonCommand(packageManager, commandArgsString, spinnerText
|
|
|
5155
5117
|
}
|
|
5156
5118
|
async function createNeonProject(projectName, regionId, packageManager) {
|
|
5157
5119
|
try {
|
|
5158
|
-
const
|
|
5159
|
-
const { stdout } = await executeNeonCommand(packageManager, commandArgsString, `Creating Neon project "${projectName}"...`);
|
|
5120
|
+
const { stdout } = await executeNeonCommand(packageManager, `neonctl@latest projects create --name ${projectName} --region-id ${regionId} --output json`, `Creating Neon project "${projectName}"...`);
|
|
5160
5121
|
const response = JSON.parse(stdout);
|
|
5161
5122
|
if (response.project && response.connection_uris && response.connection_uris.length > 0) {
|
|
5162
5123
|
const projectId = response.project.id;
|
|
@@ -5177,13 +5138,11 @@ async function createNeonProject(projectName, regionId, packageManager) {
|
|
|
5177
5138
|
}
|
|
5178
5139
|
async function writeEnvFile$2(projectDir, backend, config) {
|
|
5179
5140
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5180
|
-
|
|
5181
|
-
const variables = [{
|
|
5141
|
+
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
5182
5142
|
key: "DATABASE_URL",
|
|
5183
5143
|
value: config?.connectionString ?? "postgresql://postgres:postgres@localhost:5432/mydb?schema=public",
|
|
5184
5144
|
condition: true
|
|
5185
|
-
}];
|
|
5186
|
-
await addEnvVariablesToFile(envPath, variables);
|
|
5145
|
+
}]);
|
|
5187
5146
|
return true;
|
|
5188
5147
|
}
|
|
5189
5148
|
async function setupWithNeonDb(projectDir, packageManager, backend) {
|
|
@@ -5193,8 +5152,7 @@ async function setupWithNeonDb(projectDir, packageManager, backend) {
|
|
|
5193
5152
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5194
5153
|
const targetDir = path.join(projectDir, targetApp);
|
|
5195
5154
|
await fs.ensureDir(targetDir);
|
|
5196
|
-
|
|
5197
|
-
await execa(packageCmd, {
|
|
5155
|
+
await execa(getPackageExecutionCommand(packageManager, "neondb@latest --yes"), {
|
|
5198
5156
|
shell: true,
|
|
5199
5157
|
cwd: targetDir
|
|
5200
5158
|
});
|
|
@@ -5412,8 +5370,7 @@ async function initPrismaDatabase(serverDir, packageManager) {
|
|
|
5412
5370
|
const prismaDir = path.join(serverDir, "prisma");
|
|
5413
5371
|
await fs.ensureDir(prismaDir);
|
|
5414
5372
|
log.info("Starting Prisma PostgreSQL setup.");
|
|
5415
|
-
|
|
5416
|
-
await execa(prismaInitCommand, {
|
|
5373
|
+
await execa(getPackageExecutionCommand(packageManager, "prisma init --db"), {
|
|
5417
5374
|
cwd: serverDir,
|
|
5418
5375
|
stdio: "inherit",
|
|
5419
5376
|
shell: true
|
|
@@ -5474,10 +5431,9 @@ DATABASE_URL="your_database_url"`);
|
|
|
5474
5431
|
}
|
|
5475
5432
|
async function addPrismaAccelerateExtension(projectDir) {
|
|
5476
5433
|
try {
|
|
5477
|
-
const dbPackageDir = path.join(projectDir, "packages/db");
|
|
5478
5434
|
await addPackageDependency({
|
|
5479
5435
|
dependencies: ["@prisma/extension-accelerate"],
|
|
5480
|
-
projectDir:
|
|
5436
|
+
projectDir: path.join(projectDir, "packages/db")
|
|
5481
5437
|
});
|
|
5482
5438
|
return true;
|
|
5483
5439
|
} catch (_error) {
|
|
@@ -5588,8 +5544,7 @@ function extractDbUrl(output) {
|
|
|
5588
5544
|
async function initializeSupabase(serverDir, packageManager) {
|
|
5589
5545
|
log.info("Initializing Supabase project...");
|
|
5590
5546
|
try {
|
|
5591
|
-
|
|
5592
|
-
await execa(supabaseInitCommand, {
|
|
5547
|
+
await execa(getPackageExecutionCommand(packageManager, "supabase init"), {
|
|
5593
5548
|
cwd: serverDir,
|
|
5594
5549
|
stdio: "inherit",
|
|
5595
5550
|
shell: true
|
|
@@ -5780,13 +5735,12 @@ async function selectTursoGroup() {
|
|
|
5780
5735
|
log.info(`Using the only available group: ${pc.blue(groups[0].name)}`);
|
|
5781
5736
|
return groups[0].name;
|
|
5782
5737
|
}
|
|
5783
|
-
const groupOptions = groups.map((group$1) => ({
|
|
5784
|
-
value: group$1.name,
|
|
5785
|
-
label: `${group$1.name} (${group$1.locations})`
|
|
5786
|
-
}));
|
|
5787
5738
|
const selectedGroup = await select({
|
|
5788
5739
|
message: "Select a Turso database group:",
|
|
5789
|
-
options:
|
|
5740
|
+
options: groups.map((group$1) => ({
|
|
5741
|
+
value: group$1.name,
|
|
5742
|
+
label: `${group$1.name} (${group$1.locations})`
|
|
5743
|
+
}))
|
|
5790
5744
|
});
|
|
5791
5745
|
if (isCancel(selectedGroup)) return exitCancelled("Operation cancelled");
|
|
5792
5746
|
return selectedGroup;
|
|
@@ -5817,8 +5771,7 @@ async function createTursoDatabase(dbName, groupName) {
|
|
|
5817
5771
|
}
|
|
5818
5772
|
async function writeEnvFile(projectDir, backend, config) {
|
|
5819
5773
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5820
|
-
|
|
5821
|
-
const variables = [{
|
|
5774
|
+
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
5822
5775
|
key: "DATABASE_URL",
|
|
5823
5776
|
value: config?.dbUrl ?? "",
|
|
5824
5777
|
condition: true
|
|
@@ -5826,8 +5779,7 @@ async function writeEnvFile(projectDir, backend, config) {
|
|
|
5826
5779
|
key: "DATABASE_AUTH_TOKEN",
|
|
5827
5780
|
value: config?.authToken ?? "",
|
|
5828
5781
|
condition: true
|
|
5829
|
-
}];
|
|
5830
|
-
await addEnvVariablesToFile(envPath, variables);
|
|
5782
|
+
}]);
|
|
5831
5783
|
}
|
|
5832
5784
|
function displayManualSetupInstructions() {
|
|
5833
5785
|
log.info(`Manual Turso Setup Instructions:
|
|
@@ -5908,8 +5860,7 @@ async function setupTurso(config, cliInput) {
|
|
|
5908
5860
|
if (isCancel(dbNameResponse)) return exitCancelled("Operation cancelled");
|
|
5909
5861
|
dbName = dbNameResponse;
|
|
5910
5862
|
try {
|
|
5911
|
-
|
|
5912
|
-
await writeEnvFile(projectDir, backend, config$1);
|
|
5863
|
+
await writeEnvFile(projectDir, backend, await createTursoDatabase(dbName, selectedGroup));
|
|
5913
5864
|
success = true;
|
|
5914
5865
|
} catch (error) {
|
|
5915
5866
|
if (error instanceof Error && error.message === "DATABASE_EXISTS") {
|
|
@@ -7079,7 +7030,6 @@ async function createProjectHandler(input) {
|
|
|
7079
7030
|
shouldClearDirectory = result.shouldClearDirectory;
|
|
7080
7031
|
}
|
|
7081
7032
|
} catch (error) {
|
|
7082
|
-
const elapsedTimeMs$1 = Date.now() - startTime;
|
|
7083
7033
|
return {
|
|
7084
7034
|
success: false,
|
|
7085
7035
|
projectConfig: {
|
|
@@ -7105,7 +7055,7 @@ async function createProjectHandler(input) {
|
|
|
7105
7055
|
},
|
|
7106
7056
|
reproducibleCommand: "",
|
|
7107
7057
|
timeScaffolded,
|
|
7108
|
-
elapsedTimeMs:
|
|
7058
|
+
elapsedTimeMs: Date.now() - startTime,
|
|
7109
7059
|
projectDirectory: "",
|
|
7110
7060
|
relativePath: "",
|
|
7111
7061
|
error: error instanceof Error ? error.message : String(error)
|
|
@@ -7357,11 +7307,10 @@ const router = os.router({
|
|
|
7357
7307
|
manualDb: z$1.boolean().optional().default(false).describe("Skip automatic/manual database setup prompt and use manual setup")
|
|
7358
7308
|
})])).handler(async ({ input }) => {
|
|
7359
7309
|
const [projectName, options] = input;
|
|
7360
|
-
const
|
|
7310
|
+
const result = await createProjectHandler({
|
|
7361
7311
|
projectName,
|
|
7362
7312
|
...options
|
|
7363
|
-
};
|
|
7364
|
-
const result = await createProjectHandler(combinedInput);
|
|
7313
|
+
});
|
|
7365
7314
|
if (options.verbose) return result;
|
|
7366
7315
|
}),
|
|
7367
7316
|
add: os.meta({ description: "Add addons or deployment configurations to an existing Better-T-Stack project" }).input(z$1.tuple([z$1.object({
|
|
@@ -7379,8 +7328,7 @@ const router = os.router({
|
|
|
7379
7328
|
try {
|
|
7380
7329
|
renderTitle();
|
|
7381
7330
|
intro(pc.magenta("Better-T-Stack Sponsors"));
|
|
7382
|
-
|
|
7383
|
-
displaySponsors(sponsors$1);
|
|
7331
|
+
displaySponsors(await fetchSponsors());
|
|
7384
7332
|
} catch (error) {
|
|
7385
7333
|
handleError(error, "Failed to display sponsors");
|
|
7386
7334
|
}
|
|
@@ -7468,4 +7416,4 @@ async function builder() {
|
|
|
7468
7416
|
}
|
|
7469
7417
|
|
|
7470
7418
|
//#endregion
|
|
7471
|
-
export {
|
|
7419
|
+
export { router as a, init as i, createBtsCli as n, sponsors as o, docs as r, builder as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.6-canary.46b928a7",
|
|
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",
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@biomejs/js-api": "^3.0.0",
|
|
70
|
-
"@biomejs/wasm-nodejs": "^2.2.
|
|
71
|
-
"@clack/prompts": "^1.0.0-alpha.
|
|
72
|
-
"@orpc/server": "^1.
|
|
70
|
+
"@biomejs/wasm-nodejs": "^2.2.6",
|
|
71
|
+
"@clack/prompts": "^1.0.0-alpha.6",
|
|
72
|
+
"@orpc/server": "^1.10.0",
|
|
73
73
|
"consola": "^3.4.2",
|
|
74
74
|
"execa": "^9.6.0",
|
|
75
75
|
"fs-extra": "^11.3.2",
|
|
@@ -78,18 +78,18 @@
|
|
|
78
78
|
"jsonc-parser": "^3.3.1",
|
|
79
79
|
"picocolors": "^1.1.1",
|
|
80
80
|
"tinyglobby": "^0.2.15",
|
|
81
|
-
"trpc-cli": "^0.
|
|
82
|
-
"ts-morph": "^27.0.
|
|
83
|
-
"yaml": "^2.
|
|
84
|
-
"zod": "^4.1.
|
|
81
|
+
"trpc-cli": "^0.12.0",
|
|
82
|
+
"ts-morph": "^27.0.2",
|
|
83
|
+
"yaml": "^2.8.1",
|
|
84
|
+
"zod": "^4.1.12"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@types/fs-extra": "^11.0.4",
|
|
88
|
-
"@types/node": "^24.
|
|
88
|
+
"@types/node": "^24.9.1",
|
|
89
89
|
"@vitest/ui": "^3.2.4",
|
|
90
|
-
"publint": "^0.3.
|
|
91
|
-
"tsdown": "^0.15.
|
|
92
|
-
"typescript": "^5.9.
|
|
90
|
+
"publint": "^0.3.15",
|
|
91
|
+
"tsdown": "^0.15.9",
|
|
92
|
+
"typescript": "^5.9.3",
|
|
93
93
|
"vitest": "^3.2.4"
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -28,15 +28,14 @@ import Loader from "@/components/loader";
|
|
|
28
28
|
|
|
29
29
|
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
30
30
|
import { ClerkProvider, useAuth } from "@clerk/tanstack-react-start";
|
|
31
|
-
import {
|
|
31
|
+
import { auth } from "@clerk/tanstack-react-start/server";
|
|
32
32
|
import { createServerFn } from "@tanstack/react-start";
|
|
33
|
-
import { getRequest } from "@tanstack/react-start/server";
|
|
34
33
|
import { ConvexProviderWithClerk } from "convex/react-clerk";
|
|
35
34
|
|
|
36
35
|
const fetchClerkAuth = createServerFn({ method: "GET" }).handler(async () => {
|
|
37
|
-
const
|
|
38
|
-
const token = await
|
|
39
|
-
return { userId:
|
|
36
|
+
const clerkAuth = await auth();
|
|
37
|
+
const token = await clerkAuth.getToken({ template: "convex" });
|
|
38
|
+
return { userId: clerkAuth.userId, token };
|
|
40
39
|
});
|
|
41
40
|
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
42
41
|
import { createServerFn } from "@tanstack/react-start";
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createClerkHandler } from "@clerk/tanstack-react-start/server";
|
|
2
|
-
import {
|
|
3
|
-
createStartHandler,
|
|
4
|
-
defaultStreamHandler,
|
|
5
|
-
defineHandlerCallback,
|
|
6
|
-
} from "@tanstack/react-start/server";
|
|
7
|
-
import { createRouter } from "./router";
|
|
8
|
-
|
|
9
|
-
// this is broken right now, waiting for a fix
|
|
10
|
-
const handlerFactory = createClerkHandler(
|
|
11
|
-
createStartHandler({
|
|
12
|
-
createRouter,
|
|
13
|
-
}),
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
export default defineHandlerCallback(async (event) => {
|
|
17
|
-
const startHandler = await handlerFactory(defaultStreamHandler);
|
|
18
|
-
return startHandler(event);
|
|
19
|
-
});
|