@better-t-stack/template-generator 3.35.3 → 3.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +537 -92
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -189,6 +189,33 @@ Handlebars.registerHelper("and", (...args) => args.slice(0, -1).every(Boolean));
|
|
|
189
189
|
Handlebars.registerHelper("or", (...args) => args.slice(0, -1).some(Boolean));
|
|
190
190
|
Handlebars.registerHelper("not", (a) => !a);
|
|
191
191
|
Handlebars.registerHelper("includes", (arr, val) => Array.isArray(arr) && arr.includes(val));
|
|
192
|
+
const getServerUrlSource = `function getServerUrl(url: string) {
|
|
193
|
+
const normalized = url.endsWith("/") ? url.slice(0, -1) : url;
|
|
194
|
+
|
|
195
|
+
if (!normalized.startsWith("/")) {
|
|
196
|
+
return normalized;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (typeof window !== "undefined") {
|
|
200
|
+
return \`\${window.location.origin}\${normalized}\`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const processEnv = (globalThis as {
|
|
204
|
+
process?: { env?: Record<string, string | undefined> };
|
|
205
|
+
}).process?.env;
|
|
206
|
+
const vercelUrl =
|
|
207
|
+
processEnv?.VERCEL_ENV === "production"
|
|
208
|
+
? (processEnv?.VERCEL_PROJECT_PRODUCTION_URL ?? processEnv?.VERCEL_URL)
|
|
209
|
+
: (processEnv?.VERCEL_URL ?? processEnv?.VERCEL_PROJECT_PRODUCTION_URL);
|
|
210
|
+
if (vercelUrl) {
|
|
211
|
+
const origin = vercelUrl.startsWith("http") ? vercelUrl : \`https://\${vercelUrl}\`;
|
|
212
|
+
return \`\${origin}\${normalized}\`;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return \`http://localhost:3000\${normalized}\`;
|
|
216
|
+
}`;
|
|
217
|
+
Handlebars.registerPartial("getServerUrl", getServerUrlSource);
|
|
218
|
+
Handlebars.registerPartial("getServerUrlSpaces", getServerUrlSource.replaceAll(" ", " "));
|
|
192
219
|
function processTemplateString(content, context) {
|
|
193
220
|
return Handlebars.compile(content)(context);
|
|
194
221
|
}
|
|
@@ -201,6 +228,7 @@ function transformFilename(filename) {
|
|
|
201
228
|
if (basename === "_gitignore") result = result.replace(/_gitignore$/, ".gitignore");
|
|
202
229
|
else if (basename === "_npmrc") result = result.replace(/_npmrc$/, ".npmrc");
|
|
203
230
|
else if (basename === "_dockerignore") result = result.replace(/_dockerignore$/, ".dockerignore");
|
|
231
|
+
else if (basename === "_vercelignore") result = result.replace(/_vercelignore$/, ".vercelignore");
|
|
204
232
|
return result;
|
|
205
233
|
}
|
|
206
234
|
function processFileContent(filePath, content, context) {
|
|
@@ -492,10 +520,13 @@ const dependencyVersionMap = {
|
|
|
492
520
|
"nitro-cloudflare-dev": "^0.2.2",
|
|
493
521
|
"@sveltejs/adapter-cloudflare": "^7.2.9",
|
|
494
522
|
"@sveltejs/adapter-node": "^5.5.7",
|
|
523
|
+
"@sveltejs/adapter-vercel": "^6.3.4",
|
|
495
524
|
"@cloudflare/workers-types": "^4.20260702.1",
|
|
496
525
|
"@astrojs/cloudflare": "^14.1.0",
|
|
497
526
|
"@astrojs/node": "^11.0.1",
|
|
527
|
+
"@astrojs/vercel": "^11.0.1",
|
|
498
528
|
alchemy: "^0.93.12",
|
|
529
|
+
vercel: "^54.18.6",
|
|
499
530
|
dotenv: "^17.4.2",
|
|
500
531
|
tsdown: "^0.22.3",
|
|
501
532
|
zod: "^4.4.3",
|
|
@@ -522,8 +553,9 @@ function addPackageDependency(options) {
|
|
|
522
553
|
const version = dependencyVersionMap[dep];
|
|
523
554
|
if (!version) throw new Error(`Missing version for dependency: ${dep}. Add it to dependencyVersionMap in add-deps.ts`);
|
|
524
555
|
pkgJson.dependencies[dep] = version;
|
|
556
|
+
delete pkgJson.devDependencies[dep];
|
|
525
557
|
}
|
|
526
|
-
for (const dep of devDependencies) if (!pkgJson.devDependencies[dep]) {
|
|
558
|
+
for (const dep of devDependencies) if (!pkgJson.devDependencies[dep] && !pkgJson.dependencies[dep]) {
|
|
527
559
|
const version = dependencyVersionMap[dep];
|
|
528
560
|
if (!version) throw new Error(`Missing version for devDependency: ${dep}. Add it to dependencyVersionMap in add-deps.ts`);
|
|
529
561
|
pkgJson.devDependencies[dep] = version;
|
|
@@ -659,10 +691,25 @@ function updateRootPackageJson(vfs, config) {
|
|
|
659
691
|
scripts["db:down"] = pmConfig.filter(dbPackageName, "db:down");
|
|
660
692
|
}
|
|
661
693
|
const infraPackageName = `@${projectName}/infra`;
|
|
662
|
-
|
|
663
|
-
|
|
694
|
+
const hasCloudflareDeploy = config.webDeploy === "cloudflare" || config.serverDeploy === "cloudflare";
|
|
695
|
+
const hasVercelDeploy = config.webDeploy === "vercel" || config.serverDeploy === "vercel";
|
|
696
|
+
const isMixedCloud = hasCloudflareDeploy && hasVercelDeploy;
|
|
697
|
+
if (hasCloudflareDeploy) {
|
|
698
|
+
const cfDeployScript = isMixedCloud ? config.webDeploy === "cloudflare" ? "deploy:web" : "deploy:server" : "deploy";
|
|
699
|
+
scripts[cfDeployScript] = pmConfig.filter(infraPackageName, "deploy");
|
|
664
700
|
scripts.destroy = pmConfig.filter(infraPackageName, "destroy");
|
|
665
701
|
}
|
|
702
|
+
if (hasVercelDeploy) {
|
|
703
|
+
const vercelTarget = config.webDeploy === "vercel" ? "web" : "server";
|
|
704
|
+
const vercelDeploy = isMixedCloud ? `deploy:${vercelTarget}` : "deploy";
|
|
705
|
+
scripts["deploy:setup"] = "vercel link";
|
|
706
|
+
scripts["dev:vercel"] = "vercel dev -L";
|
|
707
|
+
scripts["env:preview"] = "tsx scripts/sync-vercel-env.ts preview";
|
|
708
|
+
scripts["env:production"] = "tsx scripts/sync-vercel-env.ts production";
|
|
709
|
+
scripts[vercelDeploy] = "vercel deploy";
|
|
710
|
+
scripts[`${vercelDeploy}:prod`] = "vercel deploy --prod";
|
|
711
|
+
scripts["deploy:check"] = "vercel deploy --dry";
|
|
712
|
+
}
|
|
666
713
|
if (config.webDeploy === "docker" || config.serverDeploy === "docker") {
|
|
667
714
|
scripts["docker:build"] = "docker compose build";
|
|
668
715
|
scripts["docker:up"] = "docker compose up -d --build";
|
|
@@ -941,6 +988,86 @@ function updateVitePlusPackageScripts(vfs, config) {
|
|
|
941
988
|
vfs.writeJson(webPkgPath, webPkg);
|
|
942
989
|
}
|
|
943
990
|
//#endregion
|
|
991
|
+
//#region src/post-process/vercel-config.ts
|
|
992
|
+
function getWebFramework(frontend, isDesktop) {
|
|
993
|
+
if (frontend.includes("next")) return "nextjs";
|
|
994
|
+
if (frontend.includes("nuxt")) return "nuxtjs";
|
|
995
|
+
if (frontend.includes("svelte")) return "sveltekit";
|
|
996
|
+
if (frontend.includes("astro")) return "astro";
|
|
997
|
+
if (frontend.includes("tanstack-start")) return "tanstack-start";
|
|
998
|
+
if (frontend.includes("react-router") && !isDesktop) return "react-router";
|
|
999
|
+
return "vite";
|
|
1000
|
+
}
|
|
1001
|
+
function getPublicServerUrlVar(frontend) {
|
|
1002
|
+
if (frontend.includes("next")) return "NEXT_PUBLIC_SERVER_URL";
|
|
1003
|
+
if (frontend.includes("nuxt")) return "NUXT_PUBLIC_SERVER_URL";
|
|
1004
|
+
if (frontend.includes("svelte") || frontend.includes("astro")) return "PUBLIC_SERVER_URL";
|
|
1005
|
+
return "VITE_SERVER_URL";
|
|
1006
|
+
}
|
|
1007
|
+
function processVercelConfig(vfs, config) {
|
|
1008
|
+
const { webDeploy, serverDeploy, backend, runtime, frontend, addons, packageManager } = config;
|
|
1009
|
+
if (webDeploy !== "vercel" && serverDeploy !== "vercel") return;
|
|
1010
|
+
const hasWeb = webDeploy === "vercel";
|
|
1011
|
+
const hasServer = serverDeploy === "vercel" && backend !== "self";
|
|
1012
|
+
const isDesktop = addons.includes("tauri") || addons.includes("electrobun");
|
|
1013
|
+
const isStaticSpa = frontend.includes("tanstack-router") || frontend.includes("solid") || frontend.includes("react-router") && isDesktop;
|
|
1014
|
+
const installCommand = `cd ../.. && ${packageManager} install`;
|
|
1015
|
+
const services = {};
|
|
1016
|
+
if (hasWeb) {
|
|
1017
|
+
const web = {
|
|
1018
|
+
root: "apps/web",
|
|
1019
|
+
framework: getWebFramework(frontend, isDesktop),
|
|
1020
|
+
installCommand
|
|
1021
|
+
};
|
|
1022
|
+
if (hasServer) web.buildCommand = `${getPublicServerUrlVar(frontend)}=/api ${packageManager} run build`;
|
|
1023
|
+
if (frontend.includes("react-router") && isDesktop) web.outputDirectory = "build/client";
|
|
1024
|
+
if (isStaticSpa) web.rewrites = [{
|
|
1025
|
+
source: "/(.*)",
|
|
1026
|
+
destination: "/index.html"
|
|
1027
|
+
}];
|
|
1028
|
+
services.web = web;
|
|
1029
|
+
}
|
|
1030
|
+
if (hasServer) {
|
|
1031
|
+
const server = {
|
|
1032
|
+
root: "apps/server",
|
|
1033
|
+
framework: backend,
|
|
1034
|
+
entrypoint: "src/index.ts",
|
|
1035
|
+
installCommand
|
|
1036
|
+
};
|
|
1037
|
+
if (hasWeb) server.routes = [{
|
|
1038
|
+
src: "/api/((?!auth(?:/|$)).*)",
|
|
1039
|
+
transforms: [{
|
|
1040
|
+
type: "request.path",
|
|
1041
|
+
op: "set",
|
|
1042
|
+
args: "/$1"
|
|
1043
|
+
}]
|
|
1044
|
+
}];
|
|
1045
|
+
services.server = server;
|
|
1046
|
+
}
|
|
1047
|
+
const rewrites = [];
|
|
1048
|
+
if (hasWeb && hasServer) rewrites.push({
|
|
1049
|
+
source: "/api/(.*)",
|
|
1050
|
+
destination: { service: "server" }
|
|
1051
|
+
}, {
|
|
1052
|
+
source: "/(.*)",
|
|
1053
|
+
destination: { service: "web" }
|
|
1054
|
+
});
|
|
1055
|
+
else if (hasWeb) rewrites.push({
|
|
1056
|
+
source: "/(.*)",
|
|
1057
|
+
destination: { service: "web" }
|
|
1058
|
+
});
|
|
1059
|
+
else if (hasServer) rewrites.push({
|
|
1060
|
+
source: "/(.*)",
|
|
1061
|
+
destination: { service: "server" }
|
|
1062
|
+
});
|
|
1063
|
+
vfs.writeJson("vercel.json", {
|
|
1064
|
+
$schema: "https://openapi.vercel.sh/vercel.json",
|
|
1065
|
+
...hasServer && runtime === "bun" ? { bunVersion: "1.x" } : {},
|
|
1066
|
+
services,
|
|
1067
|
+
rewrites
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
//#endregion
|
|
944
1071
|
//#region src/processors/addons-deps.ts
|
|
945
1072
|
function processAddonsDeps(vfs, config) {
|
|
946
1073
|
if (!config.addons || config.addons.length === 0) return;
|
|
@@ -2062,12 +2189,47 @@ function processDrizzleDeps(vfs, config, dbPkgPath, webPkgPath, webExists) {
|
|
|
2062
2189
|
//#endregion
|
|
2063
2190
|
//#region src/processors/deploy-deps.ts
|
|
2064
2191
|
function processDeployDeps(vfs, config) {
|
|
2065
|
-
const { webDeploy, serverDeploy, frontend, backend } = config;
|
|
2192
|
+
const { webDeploy, serverDeploy, frontend, backend, addons } = config;
|
|
2066
2193
|
const isCloudflareWeb = webDeploy === "cloudflare";
|
|
2067
2194
|
const isCloudflareServer = serverDeploy === "cloudflare";
|
|
2068
2195
|
const isDockerWeb = webDeploy === "docker";
|
|
2196
|
+
const isVercelWeb = webDeploy === "vercel";
|
|
2197
|
+
const isVercelServer = serverDeploy === "vercel";
|
|
2069
2198
|
const isBackendSelf = backend === "self";
|
|
2070
|
-
if (!isCloudflareWeb && !isCloudflareServer && !isDockerWeb) return;
|
|
2199
|
+
if (!isCloudflareWeb && !isCloudflareServer && !isDockerWeb && !isVercelWeb && !isVercelServer) return;
|
|
2200
|
+
if (isVercelWeb || isVercelServer) addPackageDependency({
|
|
2201
|
+
vfs,
|
|
2202
|
+
packagePath: "package.json",
|
|
2203
|
+
devDependencies: [
|
|
2204
|
+
"@types/node",
|
|
2205
|
+
"tsx",
|
|
2206
|
+
"vercel"
|
|
2207
|
+
]
|
|
2208
|
+
});
|
|
2209
|
+
if (isVercelWeb && frontend.includes("tanstack-start")) {
|
|
2210
|
+
const webPkgPath = "apps/web/package.json";
|
|
2211
|
+
if (vfs.exists(webPkgPath)) addPackageDependency({
|
|
2212
|
+
vfs,
|
|
2213
|
+
packagePath: webPkgPath,
|
|
2214
|
+
dependencies: ["nitro"]
|
|
2215
|
+
});
|
|
2216
|
+
}
|
|
2217
|
+
if (isVercelWeb && frontend.includes("astro") && !addons.includes("electrobun") && !addons.includes("tauri")) {
|
|
2218
|
+
const webPkgPath = "apps/web/package.json";
|
|
2219
|
+
if (vfs.exists(webPkgPath)) addPackageDependency({
|
|
2220
|
+
vfs,
|
|
2221
|
+
packagePath: webPkgPath,
|
|
2222
|
+
dependencies: ["@astrojs/vercel"]
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
if (isVercelWeb && frontend.includes("svelte") && !addons.includes("electrobun") && !addons.includes("tauri")) {
|
|
2226
|
+
const webPkgPath = "apps/web/package.json";
|
|
2227
|
+
if (vfs.exists(webPkgPath)) addPackageDependency({
|
|
2228
|
+
vfs,
|
|
2229
|
+
packagePath: webPkgPath,
|
|
2230
|
+
devDependencies: ["@sveltejs/adapter-vercel"]
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2071
2233
|
if (isDockerWeb) {
|
|
2072
2234
|
const webPkgPath = "apps/web/package.json";
|
|
2073
2235
|
if (vfs.exists(webPkgPath)) {
|
|
@@ -2686,7 +2848,7 @@ function setupAIDependencies(vfs, config) {
|
|
|
2686
2848
|
//#region src/processors/frontend-deps.ts
|
|
2687
2849
|
function processFrontendDeps(vfs, config) {
|
|
2688
2850
|
const { addons, frontend, webDeploy } = config;
|
|
2689
|
-
if (!frontend.includes("astro") || addons.includes("electrobun") || addons.includes("tauri") || webDeploy === "cloudflare") return;
|
|
2851
|
+
if (!frontend.includes("astro") || addons.includes("electrobun") || addons.includes("tauri") || webDeploy === "cloudflare" || webDeploy === "vercel") return;
|
|
2690
2852
|
const webPackagePath = "apps/web/package.json";
|
|
2691
2853
|
if (!vfs.exists(webPackagePath)) return;
|
|
2692
2854
|
addPackageDependency({
|
|
@@ -2786,6 +2948,7 @@ function getStackGeneratedIgnorePatterns(config) {
|
|
|
2786
2948
|
patterns.add("**/.wrangler/**");
|
|
2787
2949
|
if (config.frontend.includes("next")) patterns.add("apps/web/.open-next/**");
|
|
2788
2950
|
}
|
|
2951
|
+
if (config.webDeploy === "vercel" || config.serverDeploy === "vercel") patterns.add(".vercel/**");
|
|
2789
2952
|
return [...patterns];
|
|
2790
2953
|
}
|
|
2791
2954
|
//#endregion
|
|
@@ -3456,20 +3619,39 @@ function generateScriptsList(packageManagerRunCmd, config, hasNative) {
|
|
|
3456
3619
|
- \`${packageManagerRunCmd} docker:up\`: Build and start the Docker Compose stack
|
|
3457
3620
|
- \`${packageManagerRunCmd} docker:logs\`: Tail logs from the Docker Compose stack
|
|
3458
3621
|
- \`${packageManagerRunCmd} docker:down\`: Stop the Docker Compose stack`;
|
|
3622
|
+
if (webDeploy === "vercel" || serverDeploy === "vercel") {
|
|
3623
|
+
const v = getVercelScriptNames(webDeploy, serverDeploy);
|
|
3624
|
+
scripts += `\n- \`${packageManagerRunCmd} ${v.setup}\`: Link this repo to a Vercel project (first-time setup)
|
|
3625
|
+
- \`${packageManagerRunCmd} dev:vercel\`: Run the Vercel Services dev environment locally
|
|
3626
|
+
- \`${packageManagerRunCmd} ${v.envPreview}\`: Sync local env files to the Vercel preview environment
|
|
3627
|
+
- \`${packageManagerRunCmd} ${v.envProduction}\`: Sync local env files to the Vercel production environment
|
|
3628
|
+
- \`${packageManagerRunCmd} ${v.deploy}\`: Create a Vercel preview deployment
|
|
3629
|
+
- \`${packageManagerRunCmd} ${v.deployProd}\`: Deploy to Vercel production
|
|
3630
|
+
- \`${packageManagerRunCmd} ${v.deployCheck}\`: Dry-run a deploy to preview framework detection and included files without uploading`;
|
|
3631
|
+
}
|
|
3459
3632
|
return scripts;
|
|
3460
3633
|
}
|
|
3461
3634
|
function generateDeploymentCommands(packageManagerRunCmd, webDeploy, serverDeploy, backend) {
|
|
3462
3635
|
const hasCloudflare = webDeploy === "cloudflare" || serverDeploy === "cloudflare";
|
|
3463
3636
|
const hasDocker = webDeploy === "docker" || serverDeploy === "docker";
|
|
3464
|
-
|
|
3637
|
+
const hasVercel = webDeploy === "vercel" || serverDeploy === "vercel";
|
|
3638
|
+
if (!hasCloudflare && !hasDocker && !hasVercel) return "";
|
|
3465
3639
|
const lines = ["## Deployment"];
|
|
3466
3640
|
if (hasCloudflare) {
|
|
3467
3641
|
const targetLabel = webDeploy === "cloudflare" && (serverDeploy === "cloudflare" || backend === "self") ? "web + server" : webDeploy === "cloudflare" ? "web" : "server";
|
|
3468
|
-
|
|
3642
|
+
const cfDeployScript = hasVercel ? webDeploy === "cloudflare" ? "deploy:web" : "deploy:server" : "deploy";
|
|
3643
|
+
lines.push("", "### Cloudflare via Alchemy", "", `- Target: ${targetLabel}`, `- Dev: ${packageManagerRunCmd} dev`, `- Deploy: ${packageManagerRunCmd} ${cfDeployScript}`, `- Destroy: ${packageManagerRunCmd} destroy`, "", "For more details, see the guide on [Deploying to Cloudflare with Alchemy](https://www.better-t-stack.dev/docs/guides/cloudflare-alchemy).");
|
|
3469
3644
|
}
|
|
3470
3645
|
if (hasDocker) {
|
|
3471
3646
|
const targetLabel = webDeploy === "docker" && (serverDeploy === "docker" || backend === "self") ? "web + server" : webDeploy === "docker" ? "web" : "server";
|
|
3472
|
-
lines.push("", "### Docker Compose", "", `- Target: ${targetLabel}`, "- Config: `docker-compose.yml` (app Dockerfiles live in `apps/*/Dockerfile`)", `- Build images: ${packageManagerRunCmd} docker:build`, `- Start: ${packageManagerRunCmd} docker:up`, `- Logs: ${packageManagerRunCmd} docker:logs`, `- Stop: ${packageManagerRunCmd} docker:down`, "", "Environment variables are read from each app's `.env` file (baked into web builds for public variables) and overridden in `docker-compose.yml` for container networking.");
|
|
3647
|
+
lines.push("", "### Docker Compose", "", `- Target: ${targetLabel}`, "- Config: `docker-compose.yml` (app Dockerfiles live in `apps/*/Dockerfile`)", `- Build images: ${packageManagerRunCmd} docker:build`, `- Start: ${packageManagerRunCmd} docker:up`, `- Logs: ${packageManagerRunCmd} docker:logs`, `- Stop: ${packageManagerRunCmd} docker:down`, "", "Environment variables are read from each app's `.env` file (baked into web builds for public variables) and overridden in `docker-compose.yml` for container networking.", "", "For more details, see the guide on [Deploying with Docker Compose](https://www.better-t-stack.dev/docs/guides/docker).");
|
|
3648
|
+
}
|
|
3649
|
+
if (hasVercel) {
|
|
3650
|
+
const vercelNames = getVercelScriptNames(webDeploy, serverDeploy);
|
|
3651
|
+
const targetLabel = webDeploy === "vercel" && (serverDeploy === "vercel" || backend === "self") ? "web + server" : webDeploy === "vercel" ? "web" : "server";
|
|
3652
|
+
lines.push("", "### Vercel Services", "", `- Target: ${targetLabel}`, "- Config: `vercel.json`", `- Link the project first: ${packageManagerRunCmd} ${vercelNames.setup}`, `- Local Vercel dev: ${packageManagerRunCmd} dev:vercel`, `- Sync preview env: ${packageManagerRunCmd} ${vercelNames.envPreview}`, `- Sync production env: ${packageManagerRunCmd} ${vercelNames.envProduction}`, `- Dry-run check (no upload): ${packageManagerRunCmd} ${vercelNames.deployCheck}`, `- Preview deploy: ${packageManagerRunCmd} ${vercelNames.deploy}`, `- Production deploy: ${packageManagerRunCmd} ${vercelNames.deployProd}`);
|
|
3653
|
+
if (webDeploy === "vercel" && serverDeploy === "vercel" && backend !== "self") lines.push("- Web requests under `/api/*` route to the server service and are rewritten before reaching the backend.");
|
|
3654
|
+
lines.push("Vercel Services share project environment variables, but deploys do not upload local `.env` files automatically. Link the project with `vercel link`, then run the env sync command before your first deploy (otherwise the deployment starts with no env vars), or pass one-off envs with `vercel deploy -e KEY=value`.", `Pass Vercel CLI flags to the env sync command directly, for example: \`${packageManagerRunCmd} ${vercelNames.envProduction} --scope your-team\`.`, "", "For more details, see the guide on [Deploying to Vercel](https://www.better-t-stack.dev/docs/guides/vercel).");
|
|
3473
3655
|
}
|
|
3474
3656
|
return `${lines.join("\n")}\n`;
|
|
3475
3657
|
}
|
|
@@ -3486,6 +3668,17 @@ function generateGitHooksSection(packageManagerRunCmd, addons) {
|
|
|
3486
3668
|
if (hasLinting) lines.push(`- Run checks: \`${packageManagerRunCmd} check\``);
|
|
3487
3669
|
return `${lines.join("\n")}\n\n`;
|
|
3488
3670
|
}
|
|
3671
|
+
function getVercelScriptNames(webDeploy, serverDeploy) {
|
|
3672
|
+
const deploy = webDeploy === "cloudflare" || serverDeploy === "cloudflare" ? `deploy:${webDeploy === "vercel" ? "web" : "server"}` : "deploy";
|
|
3673
|
+
return {
|
|
3674
|
+
setup: "deploy:setup",
|
|
3675
|
+
envPreview: "env:preview",
|
|
3676
|
+
envProduction: "env:production",
|
|
3677
|
+
deploy,
|
|
3678
|
+
deployProd: `${deploy}:prod`,
|
|
3679
|
+
deployCheck: "deploy:check"
|
|
3680
|
+
};
|
|
3681
|
+
}
|
|
3489
3682
|
//#endregion
|
|
3490
3683
|
//#region src/processors/runtime-deps.ts
|
|
3491
3684
|
function processRuntimeDeps(vfs, config) {
|
|
@@ -4233,7 +4426,7 @@ async function processExtrasTemplates(vfs, templates, config) {
|
|
|
4233
4426
|
].includes(f));
|
|
4234
4427
|
const hasNuxt = config.frontend.includes("nuxt");
|
|
4235
4428
|
if (config.packageManager === "pnpm") processSingleTemplate(vfs, templates, "extras/pnpm-workspace.yaml", "pnpm-workspace.yaml", config);
|
|
4236
|
-
if (config.packageManager === "bun") processSingleTemplate(vfs, templates, "extras/bunfig.toml", "bunfig.toml", config);
|
|
4429
|
+
if (config.packageManager === "bun" && hasNative) processSingleTemplate(vfs, templates, "extras/bunfig.toml", "bunfig.toml", config);
|
|
4237
4430
|
if (config.packageManager === "pnpm" && (hasNative || hasNuxt)) processSingleTemplate(vfs, templates, "extras/_npmrc", ".npmrc", config);
|
|
4238
4431
|
if (config.serverDeploy === "cloudflare" || config.backend === "self" && config.webDeploy === "cloudflare") processSingleTemplate(vfs, templates, "extras/env.d.ts", "packages/env/env.d.ts", config);
|
|
4239
4432
|
}
|
|
@@ -4243,7 +4436,8 @@ async function processDeployTemplates(vfs, templates, config) {
|
|
|
4243
4436
|
const isBackendSelf = config.backend === "self";
|
|
4244
4437
|
if (config.webDeploy === "cloudflare" || config.serverDeploy === "cloudflare") processTemplatesFromPrefix(vfs, templates, "packages/infra", "packages/infra", config);
|
|
4245
4438
|
if (config.webDeploy === "docker" || config.serverDeploy === "docker") processTemplatesFromPrefix(vfs, templates, "deploy/docker/compose", "", config);
|
|
4246
|
-
if (config.webDeploy
|
|
4439
|
+
if (config.webDeploy === "vercel" || config.serverDeploy === "vercel") processTemplatesFromPrefix(vfs, templates, "deploy/vercel", "", config);
|
|
4440
|
+
if (config.webDeploy !== "none" && config.webDeploy !== "cloudflare" && config.webDeploy !== "vercel") {
|
|
4247
4441
|
const templateMap = {
|
|
4248
4442
|
"tanstack-router": "react/tanstack-router",
|
|
4249
4443
|
"tanstack-start": "react/tanstack-start",
|
|
@@ -4256,7 +4450,7 @@ async function processDeployTemplates(vfs, templates, config) {
|
|
|
4256
4450
|
};
|
|
4257
4451
|
for (const f of config.frontend) if (templateMap[f]) processTemplatesFromPrefix(vfs, templates, `deploy/${config.webDeploy}/web/${templateMap[f]}`, "apps/web", config);
|
|
4258
4452
|
}
|
|
4259
|
-
if (config.serverDeploy !== "none" && config.serverDeploy !== "cloudflare" && !isBackendSelf) processTemplatesFromPrefix(vfs, templates, `deploy/${config.serverDeploy}/server`, "apps/server", config);
|
|
4453
|
+
if (config.serverDeploy !== "none" && config.serverDeploy !== "cloudflare" && config.serverDeploy !== "vercel" && !isBackendSelf) processTemplatesFromPrefix(vfs, templates, `deploy/${config.serverDeploy}/server`, "apps/server", config);
|
|
4260
4454
|
}
|
|
4261
4455
|
//#endregion
|
|
4262
4456
|
//#region src/utils/reproducible-command.ts
|
|
@@ -4344,6 +4538,7 @@ async function generate(options) {
|
|
|
4344
4538
|
processAlchemyPlugins(vfs, config);
|
|
4345
4539
|
processPwaPlugins(vfs, config);
|
|
4346
4540
|
processCatalogs(vfs, config);
|
|
4541
|
+
processVercelConfig(vfs, config);
|
|
4347
4542
|
processReadme(vfs, config);
|
|
4348
4543
|
if (options.version) {
|
|
4349
4544
|
const reproducibleCommand = generateReproducibleCommand(config);
|
|
@@ -5625,13 +5820,16 @@ import { RPCLink } from "@orpc/client/fetch";
|
|
|
5625
5820
|
|
|
5626
5821
|
{{#if (eq backend "self")}}
|
|
5627
5822
|
export const link = new RPCLink({
|
|
5628
|
-
|
|
5823
|
+
// Lazy: this module is imported during SSR where window does not exist
|
|
5824
|
+
url: () => \`\${window.location.origin}/rpc\`,
|
|
5629
5825
|
});
|
|
5630
5826
|
{{else}}
|
|
5631
5827
|
import { PUBLIC_SERVER_URL } from "astro:env/client";
|
|
5632
5828
|
|
|
5829
|
+
{{> getServerUrlSpaces}}
|
|
5830
|
+
|
|
5633
5831
|
export const link = new RPCLink({
|
|
5634
|
-
url: \`\${PUBLIC_SERVER_URL}/rpc\`,
|
|
5832
|
+
url: \`\${getServerUrl(PUBLIC_SERVER_URL)}/rpc\`,
|
|
5635
5833
|
{{#if (eq auth "better-auth")}}
|
|
5636
5834
|
fetch(url, options) {
|
|
5637
5835
|
return fetch(url, {
|
|
@@ -5651,11 +5849,25 @@ import { createORPCClient } from '@orpc/client'
|
|
|
5651
5849
|
import { RPCLink } from '@orpc/client/fetch'
|
|
5652
5850
|
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
|
|
5653
5851
|
|
|
5852
|
+
function getServerUrl(url: string) {
|
|
5853
|
+
const normalized = url.endsWith("/") ? url.slice(0, -1) : url;
|
|
5854
|
+
|
|
5855
|
+
if (!normalized.startsWith("/")) {
|
|
5856
|
+
return normalized;
|
|
5857
|
+
}
|
|
5858
|
+
|
|
5859
|
+
if (import.meta.server) {
|
|
5860
|
+
return \`\${useRequestURL().origin}\${normalized}\`;
|
|
5861
|
+
}
|
|
5862
|
+
|
|
5863
|
+
return \`\${window.location.origin}\${normalized}\`;
|
|
5864
|
+
}
|
|
5865
|
+
|
|
5654
5866
|
export default defineNuxtPlugin(() => {
|
|
5655
5867
|
const config = useRuntimeConfig();
|
|
5656
5868
|
const serverUrl =
|
|
5657
5869
|
(import.meta.server && config.serverUrl) || config.public.serverUrl;
|
|
5658
|
-
const rpcUrl = \`\${serverUrl}/rpc\`;
|
|
5870
|
+
const rpcUrl = \`\${getServerUrl(serverUrl)}/rpc\`;
|
|
5659
5871
|
|
|
5660
5872
|
const rpcLink = new RPCLink({
|
|
5661
5873
|
url: rpcUrl,
|
|
@@ -5783,6 +5995,10 @@ export function createQueryClient() {
|
|
|
5783
5995
|
export const queryClient = createQueryClient();
|
|
5784
5996
|
{{/unless}}
|
|
5785
5997
|
|
|
5998
|
+
{{#unless (eq backend "self")}}
|
|
5999
|
+
{{> getServerUrl}}
|
|
6000
|
+
|
|
6001
|
+
{{/unless}}
|
|
5786
6002
|
{{#if (and (includes frontend "tanstack-start") (eq backend "self"))}}
|
|
5787
6003
|
const getORPCClient = createIsomorphicFn()
|
|
5788
6004
|
.server(() =>
|
|
@@ -5811,7 +6027,7 @@ const getORPCClient = createIsomorphicFn()
|
|
|
5811
6027
|
export const client: RouterClient<typeof appRouter> = getORPCClient();
|
|
5812
6028
|
{{else if (includes frontend "tanstack-start")}}
|
|
5813
6029
|
const link = new RPCLink({
|
|
5814
|
-
url: \`\${env.VITE_SERVER_URL}/rpc\`,
|
|
6030
|
+
url: \`\${getServerUrl(env.VITE_SERVER_URL)}/rpc\`,
|
|
5815
6031
|
{{#if (eq auth "clerk")}}
|
|
5816
6032
|
headers: async () => {
|
|
5817
6033
|
const token = await getClerkAuthToken();
|
|
@@ -5838,9 +6054,9 @@ export const link = new RPCLink({
|
|
|
5838
6054
|
{{#if (and (eq backend "self") (includes frontend "next"))}}
|
|
5839
6055
|
url: \`\${typeof window !== "undefined" ? window.location.origin : "http://localhost:3001"}/api/rpc\`,
|
|
5840
6056
|
{{else if (includes frontend "next")}}
|
|
5841
|
-
url: \`\${env.NEXT_PUBLIC_SERVER_URL}/rpc\`,
|
|
6057
|
+
url: \`\${getServerUrl(env.NEXT_PUBLIC_SERVER_URL)}/rpc\`,
|
|
5842
6058
|
{{else}}
|
|
5843
|
-
url: \`\${env.VITE_SERVER_URL}/rpc\`,
|
|
6059
|
+
url: \`\${getServerUrl(env.VITE_SERVER_URL)}/rpc\`,
|
|
5844
6060
|
{{/if}}
|
|
5845
6061
|
{{#if (eq auth "clerk")}}
|
|
5846
6062
|
headers: async () => {
|
|
@@ -5901,8 +6117,10 @@ export const queryClient = new QueryClient({
|
|
|
5901
6117
|
}),
|
|
5902
6118
|
});
|
|
5903
6119
|
|
|
6120
|
+
{{> getServerUrl}}
|
|
6121
|
+
|
|
5904
6122
|
export const link = new RPCLink({
|
|
5905
|
-
url: \`\${env.VITE_SERVER_URL}/rpc\`,
|
|
6123
|
+
url: \`\${getServerUrl(env.VITE_SERVER_URL)}/rpc\`,
|
|
5906
6124
|
{{#if (eq auth "better-auth")}}
|
|
5907
6125
|
fetch(url, options) {
|
|
5908
6126
|
return fetch(url, {
|
|
@@ -5934,6 +6152,10 @@ export const queryClient = new QueryClient({
|
|
|
5934
6152
|
}),
|
|
5935
6153
|
});
|
|
5936
6154
|
|
|
6155
|
+
{{#unless (eq backend "self")}}
|
|
6156
|
+
{{> getServerUrl}}
|
|
6157
|
+
|
|
6158
|
+
{{/unless}}
|
|
5937
6159
|
export const link = new RPCLink({
|
|
5938
6160
|
{{#if (eq backend "self")}}
|
|
5939
6161
|
url: () => {
|
|
@@ -5944,7 +6166,7 @@ export const link = new RPCLink({
|
|
|
5944
6166
|
return \`\${window.location.origin}/rpc\`;
|
|
5945
6167
|
},
|
|
5946
6168
|
{{else}}
|
|
5947
|
-
url: \`\${PUBLIC_SERVER_URL}/rpc\`,
|
|
6169
|
+
url: \`\${getServerUrl(PUBLIC_SERVER_URL)}/rpc\`,
|
|
5948
6170
|
{{/if}}
|
|
5949
6171
|
{{#if (eq auth "better-auth")}}
|
|
5950
6172
|
fetch(url, options) {
|
|
@@ -6470,6 +6692,8 @@ import type { AppRouter } from "@{{projectName}}/api/routers/index";
|
|
|
6470
6692
|
import { toast } from 'sonner';
|
|
6471
6693
|
{{#unless (eq backend "self")}}
|
|
6472
6694
|
import { env } from "@{{projectName}}/env/web";
|
|
6695
|
+
|
|
6696
|
+
{{> getServerUrl}}
|
|
6473
6697
|
{{/unless}}
|
|
6474
6698
|
{{#if (eq auth "clerk")}}
|
|
6475
6699
|
import { getClerkAuthToken } from "@/utils/clerk-auth";
|
|
@@ -6496,7 +6720,7 @@ const trpcClient = createTRPCClient<AppRouter>({
|
|
|
6496
6720
|
{{#if (eq backend "self")}}
|
|
6497
6721
|
url: "/api/trpc",
|
|
6498
6722
|
{{else}}
|
|
6499
|
-
url: \`\${env.NEXT_PUBLIC_SERVER_URL}/trpc\`,
|
|
6723
|
+
url: \`\${getServerUrl(env.NEXT_PUBLIC_SERVER_URL)}/trpc\`,
|
|
6500
6724
|
{{/if}}
|
|
6501
6725
|
{{#if (eq auth "clerk")}}
|
|
6502
6726
|
headers: async () => {
|
|
@@ -6547,6 +6771,8 @@ import { env } from "@{{projectName}}/env/web";
|
|
|
6547
6771
|
import { getClerkAuthToken } from "@/utils/clerk-auth";
|
|
6548
6772
|
{{/if}}
|
|
6549
6773
|
|
|
6774
|
+
{{> getServerUrl}}
|
|
6775
|
+
|
|
6550
6776
|
export const queryClient = new QueryClient({
|
|
6551
6777
|
queryCache: new QueryCache({
|
|
6552
6778
|
onError: (error, query) => {
|
|
@@ -6565,7 +6791,7 @@ export const queryClient = new QueryClient({
|
|
|
6565
6791
|
export const trpcClient = createTRPCClient<AppRouter>({
|
|
6566
6792
|
links: [
|
|
6567
6793
|
httpBatchLink({
|
|
6568
|
-
url: \`\${env.VITE_SERVER_URL}/trpc\`,
|
|
6794
|
+
url: \`\${getServerUrl(env.VITE_SERVER_URL)}/trpc\`,
|
|
6569
6795
|
{{#if (eq auth "clerk")}}
|
|
6570
6796
|
headers: async () => {
|
|
6571
6797
|
const token = await getClerkAuthToken();
|
|
@@ -13361,9 +13587,15 @@ import { polarClient } from "@polar-sh/better-auth/client";
|
|
|
13361
13587
|
import { PUBLIC_SERVER_URL } from "astro:env/client";
|
|
13362
13588
|
{{/if}}
|
|
13363
13589
|
|
|
13590
|
+
{{#if (ne backend "self")}}
|
|
13591
|
+
{{> getServerUrlSpaces}}
|
|
13592
|
+
|
|
13593
|
+
{{/if}}
|
|
13364
13594
|
export const authClient = createAuthClient({
|
|
13365
13595
|
{{#if (ne backend "self")}}
|
|
13366
|
-
|
|
13596
|
+
// better-auth derives its route-matching base from this URL's path, so the
|
|
13597
|
+
// public auth path must equal the server-side mount (/api/auth everywhere)
|
|
13598
|
+
baseURL: new URL("/api/auth", getServerUrl(PUBLIC_SERVER_URL)).toString(),
|
|
13367
13599
|
{{/if}}
|
|
13368
13600
|
{{#if (eq payments "polar")}}
|
|
13369
13601
|
plugins: [polarClient()],
|
|
@@ -13897,11 +14129,17 @@ import { polarClient } from "@polar-sh/better-auth/client";
|
|
|
13897
14129
|
export default defineNuxtPlugin(() => {
|
|
13898
14130
|
{{#if (ne backend "self")}}
|
|
13899
14131
|
const config = useRuntimeConfig();
|
|
14132
|
+
const rawServerUrl = (import.meta.server && config.serverUrl) || config.public.serverUrl;
|
|
14133
|
+
// Same-origin paths like /api need an absolute base, and better-auth derives
|
|
14134
|
+
// its route matching from this URL's path, so it must be exactly /api/auth
|
|
14135
|
+
const serverOrigin = rawServerUrl.startsWith("/")
|
|
14136
|
+
? (import.meta.server ? useRequestURL() : window.location).origin + rawServerUrl
|
|
14137
|
+
: rawServerUrl;
|
|
13900
14138
|
{{/if}}
|
|
13901
14139
|
|
|
13902
14140
|
const authClient = createAuthClient({
|
|
13903
14141
|
{{#if (ne backend "self")}}
|
|
13904
|
-
baseURL: (
|
|
14142
|
+
baseURL: new URL("/api/auth", serverOrigin).toString(),
|
|
13905
14143
|
{{/if}}
|
|
13906
14144
|
{{#if (eq payments "polar")}}
|
|
13907
14145
|
plugins: [polarClient()],
|
|
@@ -13921,11 +14159,15 @@ import { polarClient } from "@polar-sh/better-auth/client";
|
|
|
13921
14159
|
{{/if}}
|
|
13922
14160
|
{{#unless (eq backend "self")}}
|
|
13923
14161
|
import { env } from "@{{projectName}}/env/web";
|
|
14162
|
+
|
|
14163
|
+
{{> getServerUrl}}
|
|
13924
14164
|
{{/unless}}
|
|
13925
14165
|
|
|
13926
14166
|
export const authClient = createAuthClient({
|
|
13927
14167
|
{{#unless (eq backend "self")}}
|
|
13928
|
-
|
|
14168
|
+
// better-auth derives its route-matching base from this URL's path, so the
|
|
14169
|
+
// public auth path must equal the server-side mount (/api/auth everywhere)
|
|
14170
|
+
baseURL: new URL("/api/auth", getServerUrl(env.{{#if (includes frontend "next")}}NEXT_PUBLIC_SERVER_URL{{else}}VITE_SERVER_URL{{/if}})).toString(),
|
|
13929
14171
|
{{/unless}}
|
|
13930
14172
|
{{#if (eq payments "polar")}}
|
|
13931
14173
|
plugins: [polarClient()]
|
|
@@ -16219,8 +16461,12 @@ import { polarClient } from "@polar-sh/better-auth/client";
|
|
|
16219
16461
|
{{/if}}
|
|
16220
16462
|
import { env } from "@{{projectName}}/env/web";
|
|
16221
16463
|
|
|
16464
|
+
{{> getServerUrl}}
|
|
16465
|
+
|
|
16222
16466
|
export const authClient = createAuthClient({
|
|
16223
|
-
|
|
16467
|
+
// better-auth derives its route-matching base from this URL's path, so the
|
|
16468
|
+
// public auth path must equal the server-side mount (/api/auth everywhere)
|
|
16469
|
+
baseURL: new URL("/api/auth", getServerUrl(env.VITE_SERVER_URL)).toString(),
|
|
16224
16470
|
{{#if (eq payments "polar")}}
|
|
16225
16471
|
plugins: [polarClient()]
|
|
16226
16472
|
{{/if}}
|
|
@@ -16636,9 +16882,15 @@ import { createAuthClient } from "better-auth/svelte";
|
|
|
16636
16882
|
import { polarClient } from "@polar-sh/better-auth/client";
|
|
16637
16883
|
{{/if}}
|
|
16638
16884
|
|
|
16885
|
+
{{#unless (eq backend "self")}}
|
|
16886
|
+
{{> getServerUrl}}
|
|
16887
|
+
|
|
16888
|
+
{{/unless}}
|
|
16639
16889
|
export const authClient = createAuthClient({
|
|
16640
16890
|
{{#unless (eq backend "self")}}
|
|
16641
|
-
|
|
16891
|
+
// better-auth derives its route-matching base from this URL's path, so the
|
|
16892
|
+
// public auth path must equal the server-side mount (/api/auth everywhere)
|
|
16893
|
+
baseURL: new URL("/api/auth", getServerUrl(PUBLIC_SERVER_URL)).toString(),
|
|
16642
16894
|
{{/unless}}
|
|
16643
16895
|
{{#if (eq payments "polar")}}
|
|
16644
16896
|
plugins: [polarClient()]
|
|
@@ -18664,11 +18916,7 @@ const apiHandler = new OpenAPIHandler(appRouter, {
|
|
|
18664
18916
|
});
|
|
18665
18917
|
{{/if}}
|
|
18666
18918
|
|
|
18667
|
-
{{#if (eq runtime "node")}}
|
|
18668
|
-
new Elysia({ adapter: node() })
|
|
18669
|
-
{{else}}
|
|
18670
|
-
new Elysia()
|
|
18671
|
-
{{/if}}
|
|
18919
|
+
const app = {{#if (eq runtime "node")}}new Elysia({ adapter: node() }){{else}}new Elysia(){{/if}}
|
|
18672
18920
|
.use(
|
|
18673
18921
|
cors({
|
|
18674
18922
|
origin: env.CORS_ORIGIN,
|
|
@@ -18774,9 +19022,22 @@ new Elysia()
|
|
|
18774
19022
|
})
|
|
18775
19023
|
{{/if}}
|
|
18776
19024
|
.get("/", () => "OK")
|
|
19025
|
+
{{#if (eq serverDeploy "vercel")}};
|
|
19026
|
+
|
|
19027
|
+
export default app;
|
|
19028
|
+
|
|
19029
|
+
// Elysia's default export is not auto-served by Bun or Node, so start a local
|
|
19030
|
+
// server outside Vercel while still exporting the app for Vercel functions.
|
|
19031
|
+
if (!process.env.VERCEL) {
|
|
19032
|
+
app.listen(3000, () => {
|
|
19033
|
+
console.log("Server is running on http://localhost:3000");
|
|
19034
|
+
});
|
|
19035
|
+
}
|
|
19036
|
+
{{else}}
|
|
18777
19037
|
.listen(3000, () => {
|
|
18778
19038
|
console.log("Server is running on http://localhost:3000");
|
|
18779
19039
|
});
|
|
19040
|
+
{{/if}}
|
|
18780
19041
|
`],
|
|
18781
19042
|
["backend/server/express/src/index.ts.hbs", `import { env } from "@{{projectName}}/env/server";
|
|
18782
19043
|
{{#if (eq api "trpc")}}
|
|
@@ -19347,15 +19608,23 @@ app.get("/", (c) => {
|
|
|
19347
19608
|
{{#if (eq runtime "node")}}
|
|
19348
19609
|
import { serve } from "@hono/node-server";
|
|
19349
19610
|
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
|
|
19354
|
-
|
|
19355
|
-
(
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19611
|
+
{{#if (eq serverDeploy "vercel")}}
|
|
19612
|
+
export default app;
|
|
19613
|
+
|
|
19614
|
+
if (!process.env.VERCEL) {
|
|
19615
|
+
{{/if}}
|
|
19616
|
+
serve(
|
|
19617
|
+
{
|
|
19618
|
+
fetch: app.fetch,
|
|
19619
|
+
port: 3000,
|
|
19620
|
+
},
|
|
19621
|
+
(info) => {
|
|
19622
|
+
console.log(\`Server is running on http://localhost:\${info.port}\`);
|
|
19623
|
+
}
|
|
19624
|
+
);
|
|
19625
|
+
{{#if (eq serverDeploy "vercel")}}
|
|
19626
|
+
}
|
|
19627
|
+
{{/if}}
|
|
19359
19628
|
{{else}}
|
|
19360
19629
|
{{#if (eq runtime "bun")}}
|
|
19361
19630
|
export default app;
|
|
@@ -19409,6 +19678,7 @@ lerna-debug.log*
|
|
|
19409
19678
|
|
|
19410
19679
|
# Better-T-Stack
|
|
19411
19680
|
.alchemy
|
|
19681
|
+
.vercel
|
|
19412
19682
|
|
|
19413
19683
|
# Testing
|
|
19414
19684
|
coverage
|
|
@@ -20278,7 +20548,7 @@ services:
|
|
|
20278
20548
|
{{/if}}
|
|
20279
20549
|
init: true
|
|
20280
20550
|
ports:
|
|
20281
|
-
{{#if (or (includes frontend "tanstack-router") (includes frontend "
|
|
20551
|
+
{{#if (or (includes frontend "tanstack-router") (includes frontend "solid"))}}
|
|
20282
20552
|
- "3001:80"
|
|
20283
20553
|
{{else}}
|
|
20284
20554
|
- "3001:3001"
|
|
@@ -20325,7 +20595,7 @@ services:
|
|
|
20325
20595
|
{{/if}}
|
|
20326
20596
|
{{/if}}
|
|
20327
20597
|
healthcheck:
|
|
20328
|
-
{{#if (or (includes frontend "tanstack-router") (includes frontend "
|
|
20598
|
+
{{#if (or (includes frontend "tanstack-router") (includes frontend "solid"))}}
|
|
20329
20599
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/"]
|
|
20330
20600
|
{{else}}
|
|
20331
20601
|
test:
|
|
@@ -20686,30 +20956,14 @@ ENV VITE_CLERK_PUBLISHABLE_KEY=\${VITE_CLERK_PUBLISHABLE_KEY}
|
|
|
20686
20956
|
ENV NODE_ENV=production
|
|
20687
20957
|
RUN cd apps/web && {{packageManager}} run build
|
|
20688
20958
|
|
|
20689
|
-
FROM
|
|
20690
|
-
|
|
20691
|
-
COPY
|
|
20692
|
-
|
|
20693
|
-
|
|
20694
|
-
|
|
20695
|
-
|
|
20696
|
-
|
|
20697
|
-
server_name _;
|
|
20698
|
-
root /usr/share/nginx/html;
|
|
20699
|
-
index index.html;
|
|
20700
|
-
|
|
20701
|
-
gzip on;
|
|
20702
|
-
gzip_types text/plain text/css application/json application/javascript image/svg+xml;
|
|
20703
|
-
|
|
20704
|
-
location /assets/ {
|
|
20705
|
-
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
20706
|
-
}
|
|
20707
|
-
|
|
20708
|
-
# SPA fallback
|
|
20709
|
-
location / {
|
|
20710
|
-
try_files $uri $uri/ /index.html;
|
|
20711
|
-
}
|
|
20712
|
-
}
|
|
20959
|
+
FROM node:24-slim AS runner
|
|
20960
|
+
WORKDIR /app
|
|
20961
|
+
COPY --from=builder /app .
|
|
20962
|
+
ENV NODE_ENV=production
|
|
20963
|
+
ENV PORT=3001
|
|
20964
|
+
ENV HOST=0.0.0.0
|
|
20965
|
+
EXPOSE 3001
|
|
20966
|
+
CMD ["sh", "-c", "cd apps/web && npm run start"]
|
|
20713
20967
|
`],
|
|
20714
20968
|
["deploy/docker/web/react/tanstack-router/Dockerfile.hbs", `FROM node:24{{#unless (includes addons "vite-plus")}}-slim{{/unless}} AS builder
|
|
20715
20969
|
{{#if (eq packageManager "bun")}}
|
|
@@ -20949,6 +21203,143 @@ EXPOSE 3001
|
|
|
20949
21203
|
|
|
20950
21204
|
WORKDIR /app/apps/web
|
|
20951
21205
|
CMD ["node", "build/index.js"]
|
|
21206
|
+
`],
|
|
21207
|
+
["deploy/vercel/_vercelignore", `# Local env files must never ship in deployments: Vercel project env vars are
|
|
21208
|
+
# the source of truth (bun env:vercel:*), and frameworks like Next.js would
|
|
21209
|
+
# otherwise load these localhost values at runtime.
|
|
21210
|
+
.env
|
|
21211
|
+
.env.*
|
|
21212
|
+
**/.env
|
|
21213
|
+
**/.env.*
|
|
21214
|
+
!**/.env.example
|
|
21215
|
+
local.db
|
|
21216
|
+
local.db-*
|
|
21217
|
+
.alchemy/
|
|
21218
|
+
`],
|
|
21219
|
+
["deploy/vercel/scripts/sync-vercel-env.ts.hbs", `import { spawnSync } from "node:child_process";
|
|
21220
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
21221
|
+
import dotenv from "dotenv";
|
|
21222
|
+
|
|
21223
|
+
const DEFAULT_ENVIRONMENT = "preview";
|
|
21224
|
+
const VALID_ENVIRONMENTS = new Set(["development", "preview", "production"]);
|
|
21225
|
+
const VERCEL_COMMAND = [{{#if (eq packageManager "npm")}}"npx", "vercel"{{else if (eq packageManager "pnpm")}}"pnpm", "exec", "vercel"{{else}}"bunx", "vercel"{{/if}}] as const;
|
|
21226
|
+
const DEFAULT_FILES = [
|
|
21227
|
+
{{#if (eq webDeploy "vercel")}}
|
|
21228
|
+
"apps/web/.env",
|
|
21229
|
+
{{/if}}
|
|
21230
|
+
{{#if (and (eq serverDeploy "vercel") (ne backend "self") (ne backend "none") (ne backend "convex"))}}
|
|
21231
|
+
"apps/server/.env",
|
|
21232
|
+
{{/if}}
|
|
21233
|
+
];
|
|
21234
|
+
const SKIP_KEYS = new Set([
|
|
21235
|
+
{{#if (or (and (eq webDeploy "vercel") (eq serverDeploy "vercel") (ne backend "self") (ne backend "none") (ne backend "convex")) (and (eq webDeploy "vercel") (eq backend "self")))}}
|
|
21236
|
+
"BETTER_AUTH_URL",
|
|
21237
|
+
"CORS_ORIGIN",
|
|
21238
|
+
"NODE_ENV",
|
|
21239
|
+
{{/if}}
|
|
21240
|
+
]);
|
|
21241
|
+
const OVERRIDE_KEYS = new Map([
|
|
21242
|
+
{{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel") (ne backend "self") (ne backend "none") (ne backend "convex"))}}
|
|
21243
|
+
["NEXT_PUBLIC_SERVER_URL", "/api"],
|
|
21244
|
+
["NUXT_PUBLIC_SERVER_URL", "/api"],
|
|
21245
|
+
["PUBLIC_SERVER_URL", "/api"],
|
|
21246
|
+
["VITE_SERVER_URL", "/api"],
|
|
21247
|
+
{{/if}}
|
|
21248
|
+
]);
|
|
21249
|
+
|
|
21250
|
+
const args = process.argv.slice(2);
|
|
21251
|
+
const separatorIndex = args.indexOf("--");
|
|
21252
|
+
const scriptArgs = separatorIndex === -1 ? args : args.slice(0, separatorIndex);
|
|
21253
|
+
const forwardedArgs = separatorIndex === -1 ? [] : args.slice(separatorIndex + 1);
|
|
21254
|
+
|
|
21255
|
+
const environment =
|
|
21256
|
+
scriptArgs[0] && VALID_ENVIRONMENTS.has(scriptArgs[0]) ? scriptArgs[0] : DEFAULT_ENVIRONMENT;
|
|
21257
|
+
const remainingArgs = scriptArgs.slice(VALID_ENVIRONMENTS.has(scriptArgs[0] ?? "") ? 1 : 0);
|
|
21258
|
+
// Split remaining args into env-file paths and passthrough Vercel CLI flags.
|
|
21259
|
+
// A bare token counts as a file only when it exists on disk, so flags and their
|
|
21260
|
+
// values (e.g. \`--scope my-team\`) forward correctly regardless of argument order.
|
|
21261
|
+
const files: string[] = [];
|
|
21262
|
+
const passthroughArgs: string[] = [];
|
|
21263
|
+
for (const arg of remainingArgs) {
|
|
21264
|
+
if (!arg.startsWith("-") && existsSync(arg)) {
|
|
21265
|
+
files.push(arg);
|
|
21266
|
+
} else {
|
|
21267
|
+
passthroughArgs.push(arg);
|
|
21268
|
+
}
|
|
21269
|
+
}
|
|
21270
|
+
const vercelArgs = [...passthroughArgs, ...forwardedArgs];
|
|
21271
|
+
const envFiles = files.length > 0 ? files : DEFAULT_FILES;
|
|
21272
|
+
|
|
21273
|
+
if (envFiles.length === 0) {
|
|
21274
|
+
console.log("No env files configured for this Vercel stack.");
|
|
21275
|
+
process.exit(0);
|
|
21276
|
+
}
|
|
21277
|
+
|
|
21278
|
+
const env = new Map<string, string>();
|
|
21279
|
+
|
|
21280
|
+
for (const file of envFiles) {
|
|
21281
|
+
if (!existsSync(file)) {
|
|
21282
|
+
console.warn(\`Skipping missing env file: \${file}\`);
|
|
21283
|
+
continue;
|
|
21284
|
+
}
|
|
21285
|
+
|
|
21286
|
+
for (const [key, value] of Object.entries(dotenv.parse(readFileSync(file, "utf8")))) {
|
|
21287
|
+
if (SKIP_KEYS.has(key)) continue;
|
|
21288
|
+
env.set(key, OVERRIDE_KEYS.get(key) ?? value);
|
|
21289
|
+
}
|
|
21290
|
+
}
|
|
21291
|
+
|
|
21292
|
+
if (env.size === 0) {
|
|
21293
|
+
console.log("No Vercel env vars found to sync.");
|
|
21294
|
+
process.exit(0);
|
|
21295
|
+
}
|
|
21296
|
+
|
|
21297
|
+
const LOCAL_VALUE_PATTERN = /localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|^file:/i;
|
|
21298
|
+
const localKeys = [...env.entries()]
|
|
21299
|
+
.filter(([, value]) => LOCAL_VALUE_PATTERN.test(value))
|
|
21300
|
+
.map(([key]) => key);
|
|
21301
|
+
if (localKeys.length > 0) {
|
|
21302
|
+
console.warn(
|
|
21303
|
+
\`Warning: \${localKeys.join(", ")} look\${localKeys.length === 1 ? "s" : ""} like local-only value(s). Update them in your .env file(s) and re-run this sync if your deployed app should not point at local endpoints.\`,
|
|
21304
|
+
);
|
|
21305
|
+
}
|
|
21306
|
+
|
|
21307
|
+
console.log(\`Syncing \${env.size} env var(s) to Vercel \${environment}.\`);
|
|
21308
|
+
for (const [key, value] of env.entries()) {
|
|
21309
|
+
const result = spawnSync(
|
|
21310
|
+
VERCEL_COMMAND[0],
|
|
21311
|
+
[
|
|
21312
|
+
...VERCEL_COMMAND.slice(1),
|
|
21313
|
+
"env",
|
|
21314
|
+
"add",
|
|
21315
|
+
key,
|
|
21316
|
+
environment,
|
|
21317
|
+
"--force",
|
|
21318
|
+
"--yes",
|
|
21319
|
+
"--non-interactive",
|
|
21320
|
+
...vercelArgs,
|
|
21321
|
+
],
|
|
21322
|
+
{
|
|
21323
|
+
input: \`\${value}\\n\`,
|
|
21324
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
21325
|
+
encoding: "utf8",
|
|
21326
|
+
// Windows resolves bunx/npx/pnpm via .cmd shims, which need a shell
|
|
21327
|
+
shell: process.platform === "win32",
|
|
21328
|
+
},
|
|
21329
|
+
);
|
|
21330
|
+
|
|
21331
|
+
if (result.error) {
|
|
21332
|
+
console.error(\`Failed to sync \${key}: \${result.error.message}\`);
|
|
21333
|
+
process.exit(1);
|
|
21334
|
+
}
|
|
21335
|
+
|
|
21336
|
+
if (result.status !== 0) {
|
|
21337
|
+
console.error(\`Failed to sync \${key}\`);
|
|
21338
|
+
process.exit(result.status ?? 1);
|
|
21339
|
+
}
|
|
21340
|
+
}
|
|
21341
|
+
|
|
21342
|
+
console.log("Vercel env sync complete. Redeploy for changes to take effect.");
|
|
20952
21343
|
`],
|
|
20953
21344
|
["examples/ai/convex/packages/backend/convex/agent.ts.hbs", `import { Agent } from "@convex-dev/agent";
|
|
20954
21345
|
import { google } from "@ai-sdk/google";
|
|
@@ -29645,14 +30036,7 @@ shamefully-hoist=true
|
|
|
29645
30036
|
strict-peer-dependencies=false
|
|
29646
30037
|
{{/if}}`],
|
|
29647
30038
|
["extras/bunfig.toml.hbs", `[install]
|
|
29648
|
-
{{#if (includes frontend "nuxt")}}
|
|
29649
|
-
linker = "hoisted" # Nuxt needs hoisting for its dependency resolver
|
|
29650
|
-
{{else}}
|
|
29651
|
-
linker = "isolated"
|
|
29652
|
-
{{#if (or (includes frontend "native-bare") (includes frontend "native-uniwind") (includes frontend "native-unistyles"))}}
|
|
29653
30039
|
peer = false # Expo native projects declare SDK peers explicitly; this keeps Bun isolated installs deduped for native modules
|
|
29654
|
-
{{/if}}
|
|
29655
|
-
{{/if}}
|
|
29656
30040
|
`],
|
|
29657
30041
|
["extras/env.d.ts.hbs", `{{#if (eq serverDeploy "cloudflare")}}
|
|
29658
30042
|
import { type server } from "@{{projectName}}/infra/alchemy.run";
|
|
@@ -29678,19 +30062,19 @@ declare module "cloudflare:workers" {
|
|
|
29678
30062
|
["extras/pnpm-workspace.yaml.hbs", `packages:
|
|
29679
30063
|
- "apps/*"
|
|
29680
30064
|
- "packages/*"
|
|
29681
|
-
{{#if (or (eq runtime "node") (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare") (eq webDeploy "docker") (eq serverDeploy "docker") (eq orm "prisma") (includes addons "lefthook") (includes addons "nx") (includes addons "pwa") (includes addons "turborepo") (includes addons "vite-plus") (includes frontend "react-router") (includes frontend "next") (includes frontend "nuxt"))}}
|
|
30065
|
+
{{#if (or (eq runtime "node") (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare") (eq webDeploy "docker") (eq serverDeploy "docker") (eq webDeploy "vercel") (eq serverDeploy "vercel") (eq orm "prisma") (includes addons "lefthook") (includes addons "nx") (includes addons "pwa") (includes addons "turborepo") (includes addons "vite-plus") (includes frontend "react-router") (includes frontend "next") (includes frontend "nuxt"))}}
|
|
29682
30066
|
|
|
29683
30067
|
# pnpm 11 blocks dependency lifecycle scripts unless they are approved here.
|
|
29684
30068
|
# Entries are scoped to packages this generated stack can pull in.
|
|
29685
30069
|
allowBuilds:
|
|
29686
|
-
{{#if (or (eq runtime "node") (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare") (eq webDeploy "docker") (eq serverDeploy "docker") (includes addons "turborepo") (includes addons "vite-plus") (includes frontend "react-router") (includes frontend "nuxt"))}}
|
|
30070
|
+
{{#if (or (eq runtime "node") (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare") (eq webDeploy "docker") (eq serverDeploy "docker") (eq webDeploy "vercel") (eq serverDeploy "vercel") (includes addons "turborepo") (includes addons "vite-plus") (includes frontend "react-router") (includes frontend "nuxt"))}}
|
|
29687
30071
|
esbuild: true
|
|
29688
30072
|
{{/if}}
|
|
29689
30073
|
{{#if (includes frontend "nuxt")}}
|
|
29690
30074
|
"@parcel/watcher": true
|
|
29691
30075
|
vue-demi: true
|
|
29692
30076
|
{{/if}}
|
|
29693
|
-
{{#if (or (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare") (eq webDeploy "docker") (includes addons "pwa") (includes frontend "next"))}}
|
|
30077
|
+
{{#if (or (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare") (eq webDeploy "docker") (eq webDeploy "vercel") (includes addons "pwa") (includes frontend "next"))}}
|
|
29694
30078
|
sharp: true
|
|
29695
30079
|
{{/if}}
|
|
29696
30080
|
{{#if (or (eq webDeploy "cloudflare") (eq serverDeploy "cloudflare"))}}
|
|
@@ -29737,6 +30121,8 @@ pnpm-debug.log*
|
|
|
29737
30121
|
import tailwindcss from "@tailwindcss/vite";
|
|
29738
30122
|
import { defineConfig, envField } from "astro/config";
|
|
29739
30123
|
{{#if (or (includes addons "electrobun") (includes addons "tauri"))}}
|
|
30124
|
+
{{else if (eq webDeploy "vercel")}}
|
|
30125
|
+
import vercel from "@astrojs/vercel";
|
|
29740
30126
|
{{else}}
|
|
29741
30127
|
import node from "@astrojs/node";
|
|
29742
30128
|
{{/if}}
|
|
@@ -29745,6 +30131,9 @@ import node from "@astrojs/node";
|
|
|
29745
30131
|
export default defineConfig({
|
|
29746
30132
|
{{#if (or (includes addons "electrobun") (includes addons "tauri"))}}
|
|
29747
30133
|
output: "static",
|
|
30134
|
+
{{else if (eq webDeploy "vercel")}}
|
|
30135
|
+
output: "server",
|
|
30136
|
+
adapter: vercel(),
|
|
29748
30137
|
{{else}}
|
|
29749
30138
|
output: "server",
|
|
29750
30139
|
adapter: node({ mode: "standalone" }),
|
|
@@ -29905,9 +30294,6 @@ const { title = "{{projectName}}" } = Astro.props;
|
|
|
29905
30294
|
`],
|
|
29906
30295
|
["frontend/astro/src/pages/index.astro.hbs", `---
|
|
29907
30296
|
import Layout from "../layouts/Layout.astro";
|
|
29908
|
-
{{#if (eq api "orpc")}}
|
|
29909
|
-
import { orpc } from "../lib/orpc";
|
|
29910
|
-
{{/if}}
|
|
29911
30297
|
|
|
29912
30298
|
const TITLE_TEXT = \`
|
|
29913
30299
|
██████╗ ███████╗████████╗████████╗███████╗██████╗
|
|
@@ -34429,10 +34815,16 @@ export function ThemeProvider({
|
|
|
34429
34815
|
}
|
|
34430
34816
|
`],
|
|
34431
34817
|
["frontend/react/react-router/public/favicon.ico", `[Binary file]`],
|
|
34432
|
-
["frontend/react/react-router/react-router.config.ts", `import type { Config } from "@react-router/dev/config";
|
|
34818
|
+
["frontend/react/react-router/react-router.config.ts.hbs", `import type { Config } from "@react-router/dev/config";
|
|
34433
34819
|
|
|
34434
34820
|
export default {
|
|
34821
|
+
{{#if (and (eq webDeploy "vercel") (not (or (includes addons "tauri") (includes addons "electrobun"))))}}
|
|
34822
|
+
// Adopt vercelPreset() once @vercel/react-router supports RR8 (vercel/vercel#16730)
|
|
34823
|
+
{{/if}}
|
|
34824
|
+
{{#if (or (includes addons "tauri") (includes addons "electrobun"))}}
|
|
34825
|
+
// Desktop addons package static web assets; SSR output cannot be bundled
|
|
34435
34826
|
ssr: false,
|
|
34827
|
+
{{/if}}
|
|
34436
34828
|
appDirectory: "src",
|
|
34437
34829
|
} satisfies Config;
|
|
34438
34830
|
`],
|
|
@@ -34910,6 +35302,12 @@ export default defineConfig({
|
|
|
34910
35302
|
reactRouter(),
|
|
34911
35303
|
tsconfigPaths(),
|
|
34912
35304
|
],
|
|
35305
|
+
{{#if (and (eq webDeploy "vercel") (not (or (includes addons "tauri") (includes addons "electrobun"))))}}
|
|
35306
|
+
ssr: {
|
|
35307
|
+
// Vercel functions have no node_modules; bundle all deps into the server build
|
|
35308
|
+
noExternal: true,
|
|
35309
|
+
},
|
|
35310
|
+
{{/if}}
|
|
34913
35311
|
});
|
|
34914
35312
|
`],
|
|
34915
35313
|
["frontend/react/tanstack-router/index.html.hbs", `<!DOCTYPE html>
|
|
@@ -35480,6 +35878,10 @@ export function getRouter() {
|
|
|
35480
35878
|
}
|
|
35481
35879
|
{{else}}
|
|
35482
35880
|
{{#if (eq api "trpc")}}
|
|
35881
|
+
{{#unless (eq backend "self")}}
|
|
35882
|
+
{{> getServerUrl}}
|
|
35883
|
+
|
|
35884
|
+
{{/unless}}
|
|
35483
35885
|
function createQueryClient() {
|
|
35484
35886
|
return new QueryClient({
|
|
35485
35887
|
queryCache: new QueryCache({
|
|
@@ -35501,7 +35903,7 @@ function createQueryClient() {
|
|
|
35501
35903
|
const trpcClient = createTRPCClient<AppRouter>({
|
|
35502
35904
|
links: [
|
|
35503
35905
|
httpBatchLink({
|
|
35504
|
-
url: {{#if (eq backend "self")}}"/api/trpc"{{else}}\`\${env.VITE_SERVER_URL}/trpc\`{{/if}},
|
|
35906
|
+
url: {{#if (eq backend "self")}}"/api/trpc"{{else}}\`\${getServerUrl(env.VITE_SERVER_URL)}/trpc\`{{/if}},
|
|
35505
35907
|
{{#if (eq auth "clerk")}}
|
|
35506
35908
|
headers: async () => {
|
|
35507
35909
|
const token = await getClerkAuthToken();
|
|
@@ -35944,7 +36346,7 @@ function HomeComponent() {
|
|
|
35944
36346
|
`],
|
|
35945
36347
|
["frontend/react/tanstack-start/vite.config.ts.hbs", `import { defineConfig } from "{{#if (includes addons "vite-plus")}}vite-plus{{else}}vite{{/if}}";
|
|
35946
36348
|
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
|
|
35947
|
-
{{#if (eq webDeploy "docker")}}
|
|
36349
|
+
{{#if (or (eq webDeploy "docker") (eq webDeploy "vercel"))}}
|
|
35948
36350
|
import { nitro } from "nitro/vite";
|
|
35949
36351
|
{{/if}}
|
|
35950
36352
|
import tailwindcss from "@tailwindcss/vite";
|
|
@@ -35966,12 +36368,17 @@ export default defineConfig({
|
|
|
35966
36368
|
},
|
|
35967
36369
|
},
|
|
35968
36370
|
{{/if}}),
|
|
35969
|
-
{{#if (eq webDeploy "docker")}}
|
|
36371
|
+
{{#if (or (eq webDeploy "docker") (eq webDeploy "vercel"))}}
|
|
35970
36372
|
nitro(),
|
|
35971
36373
|
{{/if}}
|
|
35972
36374
|
viteReact(),
|
|
35973
36375
|
],
|
|
35974
|
-
{{#if (
|
|
36376
|
+
{{#if (eq webDeploy "vercel")}}
|
|
36377
|
+
// Bundle all SSR deps: Vercel functions have no node_modules at runtime
|
|
36378
|
+
ssr: {
|
|
36379
|
+
noExternal: true,
|
|
36380
|
+
},
|
|
36381
|
+
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
35975
36382
|
ssr: {
|
|
35976
36383
|
noExternal: ["@convex-dev/better-auth"],
|
|
35977
36384
|
},
|
|
@@ -36767,6 +37174,8 @@ import adapter from '@sveltejs/adapter-static';
|
|
|
36767
37174
|
import alchemy from 'alchemy/cloudflare/sveltekit';
|
|
36768
37175
|
{{else if (eq webDeploy "docker")}}
|
|
36769
37176
|
import adapter from '@sveltejs/adapter-node';
|
|
37177
|
+
{{else if (eq webDeploy "vercel")}}
|
|
37178
|
+
import adapter from '@sveltejs/adapter-vercel';
|
|
36770
37179
|
{{else}}
|
|
36771
37180
|
import adapter from '@sveltejs/adapter-auto';
|
|
36772
37181
|
{{/if}}
|
|
@@ -36792,6 +37201,8 @@ const config = {
|
|
|
36792
37201
|
{{else if (eq webDeploy "docker")}}
|
|
36793
37202
|
// adapter-node builds a standalone Node server (run with \`node build/index.js\`).
|
|
36794
37203
|
adapter: adapter()
|
|
37204
|
+
{{else if (eq webDeploy "vercel")}}
|
|
37205
|
+
adapter: adapter()
|
|
36795
37206
|
{{else}}
|
|
36796
37207
|
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
|
36797
37208
|
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
|
@@ -37022,6 +37433,33 @@ import "dotenv/config";
|
|
|
37022
37433
|
import { createEnv } from "@t3-oss/env-core";
|
|
37023
37434
|
import { z } from "zod";
|
|
37024
37435
|
|
|
37436
|
+
{{#if (or (eq webDeploy "vercel") (eq serverDeploy "vercel"))}}
|
|
37437
|
+
function getVercelOrigin() {
|
|
37438
|
+
const vercelUrl =
|
|
37439
|
+
process.env.VERCEL_ENV === "production"
|
|
37440
|
+
? (process.env.VERCEL_PROJECT_PRODUCTION_URL ?? process.env.VERCEL_URL)
|
|
37441
|
+
: (process.env.VERCEL_URL ?? process.env.VERCEL_PROJECT_PRODUCTION_URL);
|
|
37442
|
+
if (!vercelUrl) return undefined;
|
|
37443
|
+
return vercelUrl.startsWith("http") ? vercelUrl : \`https://\${vercelUrl}\`;
|
|
37444
|
+
}
|
|
37445
|
+
|
|
37446
|
+
const vercelOrigin = getVercelOrigin();
|
|
37447
|
+
|
|
37448
|
+
const runtimeEnv = {
|
|
37449
|
+
...process.env,
|
|
37450
|
+
{{#if (eq auth "better-auth")}}
|
|
37451
|
+
{{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel") (ne backend "self"))}}
|
|
37452
|
+
// Public auth base: /api/auth bypasses the rewrite's path strip, so the
|
|
37453
|
+
// same URL works for incoming matching and generated callbacks
|
|
37454
|
+
BETTER_AUTH_URL: process.env.BETTER_AUTH_URL ?? (vercelOrigin ? \`\${vercelOrigin}/api/auth\` : undefined),
|
|
37455
|
+
{{else}}
|
|
37456
|
+
BETTER_AUTH_URL: process.env.BETTER_AUTH_URL ?? vercelOrigin,
|
|
37457
|
+
{{/if}}
|
|
37458
|
+
{{/if}}
|
|
37459
|
+
CORS_ORIGIN: process.env.CORS_ORIGIN ?? vercelOrigin,
|
|
37460
|
+
};
|
|
37461
|
+
|
|
37462
|
+
{{/if}}
|
|
37025
37463
|
export const env = createEnv({
|
|
37026
37464
|
server: {
|
|
37027
37465
|
{{#if (ne database "none")}}
|
|
@@ -37053,7 +37491,7 @@ export const env = createEnv({
|
|
|
37053
37491
|
CORS_ORIGIN: z.url(),
|
|
37054
37492
|
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
|
37055
37493
|
},
|
|
37056
|
-
runtimeEnv: process.env,
|
|
37494
|
+
runtimeEnv: {{#if (or (eq webDeploy "vercel") (eq serverDeploy "vercel"))}}runtimeEnv{{else}}process.env{{/if}},
|
|
37057
37495
|
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
|
|
37058
37496
|
emptyStringAsUndefined: true,
|
|
37059
37497
|
});
|
|
@@ -37070,6 +37508,13 @@ import { createEnv } from "@t3-oss/env-core";
|
|
|
37070
37508
|
{{/if}}
|
|
37071
37509
|
import { z } from "zod";
|
|
37072
37510
|
|
|
37511
|
+
{{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel") (ne backend "self") (ne backend "none") (ne backend "convex"))}}
|
|
37512
|
+
const serverUrlSchema = z.union([
|
|
37513
|
+
z.url(),
|
|
37514
|
+
z.string().regex(/^\\/(?!\\/)/, "Use an absolute URL or a same-origin path like /api"),
|
|
37515
|
+
]);
|
|
37516
|
+
|
|
37517
|
+
{{/if}}
|
|
37073
37518
|
{{#if (eq backend "convex")}}
|
|
37074
37519
|
const convexUrlSchema = (exampleHost: string) =>
|
|
37075
37520
|
z.url().refine((url) => new URL(url).hostname !== exampleHost, {
|
|
@@ -37155,7 +37600,7 @@ export const env = createEnv({
|
|
|
37155
37600
|
{{else if (ne backend "none")}}
|
|
37156
37601
|
{{#if (includes frontend "next")}}
|
|
37157
37602
|
client: {
|
|
37158
|
-
NEXT_PUBLIC_SERVER_URL: z.url(),
|
|
37603
|
+
NEXT_PUBLIC_SERVER_URL: {{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel"))}}serverUrlSchema{{else}}z.url(){{/if}},
|
|
37159
37604
|
{{#if (eq auth "clerk")}}
|
|
37160
37605
|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
|
|
37161
37606
|
{{/if}}
|
|
@@ -37168,18 +37613,18 @@ export const env = createEnv({
|
|
|
37168
37613
|
},
|
|
37169
37614
|
{{else if (includes frontend "nuxt")}}
|
|
37170
37615
|
client: {
|
|
37171
|
-
NUXT_PUBLIC_SERVER_URL: z.url(),
|
|
37616
|
+
NUXT_PUBLIC_SERVER_URL: {{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel"))}}serverUrlSchema{{else}}z.url(){{/if}},
|
|
37172
37617
|
},
|
|
37173
37618
|
{{else if (or (includes frontend "svelte") (includes frontend "astro"))}}
|
|
37174
37619
|
clientPrefix: "PUBLIC_",
|
|
37175
37620
|
client: {
|
|
37176
|
-
PUBLIC_SERVER_URL: z.url(),
|
|
37621
|
+
PUBLIC_SERVER_URL: {{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel"))}}serverUrlSchema{{else}}z.url(){{/if}},
|
|
37177
37622
|
},
|
|
37178
37623
|
runtimeEnv: (import.meta as any).env,
|
|
37179
37624
|
{{else}}
|
|
37180
37625
|
clientPrefix: "VITE_",
|
|
37181
37626
|
client: {
|
|
37182
|
-
VITE_SERVER_URL: z.url(),
|
|
37627
|
+
VITE_SERVER_URL: {{#if (and (eq webDeploy "vercel") (eq serverDeploy "vercel"))}}serverUrlSchema{{else}}z.url(){{/if}},
|
|
37183
37628
|
{{#if (eq auth "clerk")}}
|
|
37184
37629
|
VITE_CLERK_PUBLISHABLE_KEY: z.string().min(1),
|
|
37185
37630
|
{{/if}}
|
|
@@ -39642,8 +40087,8 @@ function SuccessPage() {
|
|
|
39642
40087
|
</div>
|
|
39643
40088
|
`]
|
|
39644
40089
|
]);
|
|
39645
|
-
const TEMPLATE_COUNT =
|
|
40090
|
+
const TEMPLATE_COUNT = 507;
|
|
39646
40091
|
//#endregion
|
|
39647
|
-
export { EMBEDDED_TEMPLATES, GeneratorError, Handlebars, TEMPLATE_COUNT, VirtualFileSystem, dependencyVersionMap, generate, generateReproducibleCommand, isBinaryFile, processAddonTemplates, processAddonsDeps, processFileContent, processNxConfig, processPackageConfigs, processTemplateString, processTurboConfig, processVitePlusConfig, transformFilename, writeBtsConfigToVfs };
|
|
40092
|
+
export { EMBEDDED_TEMPLATES, GeneratorError, Handlebars, TEMPLATE_COUNT, VirtualFileSystem, dependencyVersionMap, generate, generateReproducibleCommand, isBinaryFile, processAddonTemplates, processAddonsDeps, processFileContent, processNxConfig, processPackageConfigs, processTemplateString, processTurboConfig, processVercelConfig, processVitePlusConfig, transformFilename, writeBtsConfigToVfs };
|
|
39648
40093
|
|
|
39649
40094
|
//# sourceMappingURL=index.mjs.map
|