mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
add workers support for tanstack start (#369)
This commit is contained in:
5
.changeset/upset-pears-argue.md
Normal file
5
.changeset/upset-pears-argue.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"create-better-t-stack": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
add workers support for tanstack start
|
||||||
@@ -42,24 +42,6 @@ export async function addDeploymentToProject(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.webDeploy === "workers") {
|
|
||||||
const compatibleFrontends = [
|
|
||||||
"tanstack-router",
|
|
||||||
"react-router",
|
|
||||||
"solid",
|
|
||||||
"next",
|
|
||||||
"svelte",
|
|
||||||
];
|
|
||||||
const hasCompatible = detectedConfig.frontend?.some((f) =>
|
|
||||||
compatibleFrontends.includes(f),
|
|
||||||
);
|
|
||||||
if (!hasCompatible) {
|
|
||||||
exitWithError(
|
|
||||||
"Cloudflare Workers deployment requires a compatible web frontend (tanstack-router, react-router, solid, next, or svelte).",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const config: ProjectConfig = {
|
const config: ProjectConfig = {
|
||||||
projectName: detectedConfig.projectName || path.basename(projectDir),
|
projectName: detectedConfig.projectName || path.basename(projectDir),
|
||||||
projectDir,
|
projectDir,
|
||||||
|
|||||||
@@ -851,6 +851,7 @@ export async function setupDeploymentTemplates(
|
|||||||
|
|
||||||
const templateMap: Record<string, string> = {
|
const templateMap: Record<string, string> = {
|
||||||
"tanstack-router": "react/tanstack-router",
|
"tanstack-router": "react/tanstack-router",
|
||||||
|
"tanstack-start": "react/tanstack-start",
|
||||||
"react-router": "react/react-router",
|
"react-router": "react/react-router",
|
||||||
solid: "solid",
|
solid: "solid",
|
||||||
next: "react/next",
|
next: "react/next",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { PackageManager, ProjectConfig } from "../../types";
|
|||||||
import { addPackageDependency } from "../../utils/add-package-deps";
|
import { addPackageDependency } from "../../utils/add-package-deps";
|
||||||
import { setupNuxtWorkersDeploy } from "./workers-nuxt-setup";
|
import { setupNuxtWorkersDeploy } from "./workers-nuxt-setup";
|
||||||
import { setupSvelteWorkersDeploy } from "./workers-svelte-setup";
|
import { setupSvelteWorkersDeploy } from "./workers-svelte-setup";
|
||||||
|
import { setupTanstackStartWorkersDeploy } from "./workers-tanstack-start-setup";
|
||||||
import { setupWorkersVitePlugin } from "./workers-vite-setup";
|
import { setupWorkersVitePlugin } from "./workers-vite-setup";
|
||||||
|
|
||||||
export async function setupWebDeploy(config: ProjectConfig): Promise<void> {
|
export async function setupWebDeploy(config: ProjectConfig): Promise<void> {
|
||||||
@@ -18,6 +19,7 @@ export async function setupWebDeploy(config: ProjectConfig): Promise<void> {
|
|||||||
const isNuxt = frontend.includes("nuxt");
|
const isNuxt = frontend.includes("nuxt");
|
||||||
const isSvelte = frontend.includes("svelte");
|
const isSvelte = frontend.includes("svelte");
|
||||||
const isTanstackRouter = frontend.includes("tanstack-router");
|
const isTanstackRouter = frontend.includes("tanstack-router");
|
||||||
|
const isTanstackStart = frontend.includes("tanstack-start");
|
||||||
const isReactRouter = frontend.includes("react-router");
|
const isReactRouter = frontend.includes("react-router");
|
||||||
const isSolid = frontend.includes("solid");
|
const isSolid = frontend.includes("solid");
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ export async function setupWebDeploy(config: ProjectConfig): Promise<void> {
|
|||||||
await setupNuxtWorkersDeploy(projectDir, packageManager);
|
await setupNuxtWorkersDeploy(projectDir, packageManager);
|
||||||
} else if (isSvelte) {
|
} else if (isSvelte) {
|
||||||
await setupSvelteWorkersDeploy(projectDir, packageManager);
|
await setupSvelteWorkersDeploy(projectDir, packageManager);
|
||||||
|
} else if (isTanstackStart) {
|
||||||
|
await setupTanstackStartWorkersDeploy(projectDir, packageManager);
|
||||||
} else if (isTanstackRouter || isReactRouter || isSolid) {
|
} else if (isTanstackRouter || isReactRouter || isSolid) {
|
||||||
await setupWorkersWebDeploy(projectDir, packageManager);
|
await setupWorkersWebDeploy(projectDir, packageManager);
|
||||||
}
|
}
|
||||||
|
|||||||
75
apps/cli/src/helpers/setup/workers-tanstack-start-setup.ts
Normal file
75
apps/cli/src/helpers/setup/workers-tanstack-start-setup.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import path from "node:path";
|
||||||
|
import fs from "fs-extra";
|
||||||
|
import {
|
||||||
|
type CallExpression,
|
||||||
|
Node,
|
||||||
|
type ObjectLiteralExpression,
|
||||||
|
SyntaxKind,
|
||||||
|
} from "ts-morph";
|
||||||
|
import type { PackageManager } from "../../types";
|
||||||
|
import { addPackageDependency } from "../../utils/add-package-deps";
|
||||||
|
import { ensureArrayProperty, tsProject } from "../../utils/ts-morph";
|
||||||
|
|
||||||
|
export async function setupTanstackStartWorkersDeploy(
|
||||||
|
projectDir: string,
|
||||||
|
packageManager: PackageManager,
|
||||||
|
): Promise<void> {
|
||||||
|
const webAppDir = path.join(projectDir, "apps/web");
|
||||||
|
if (!(await fs.pathExists(webAppDir))) return;
|
||||||
|
|
||||||
|
await addPackageDependency({
|
||||||
|
devDependencies: ["wrangler"],
|
||||||
|
projectDir: webAppDir,
|
||||||
|
});
|
||||||
|
|
||||||
|
const pkgPath = path.join(webAppDir, "package.json");
|
||||||
|
if (await fs.pathExists(pkgPath)) {
|
||||||
|
const pkg = await fs.readJson(pkgPath);
|
||||||
|
pkg.scripts = {
|
||||||
|
...pkg.scripts,
|
||||||
|
deploy: `${packageManager} run build && wrangler deploy`,
|
||||||
|
"cf-typegen": "wrangler types --env-interface Env",
|
||||||
|
};
|
||||||
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const viteConfigPath = path.join(webAppDir, "vite.config.ts");
|
||||||
|
if (!(await fs.pathExists(viteConfigPath))) return;
|
||||||
|
|
||||||
|
const sourceFile = tsProject.addSourceFileAtPathIfExists(viteConfigPath);
|
||||||
|
if (!sourceFile) return;
|
||||||
|
|
||||||
|
const defineCall = sourceFile
|
||||||
|
.getDescendantsOfKind(SyntaxKind.CallExpression)
|
||||||
|
.find((expr) => {
|
||||||
|
const expression = expr.getExpression();
|
||||||
|
return (
|
||||||
|
Node.isIdentifier(expression) && expression.getText() === "defineConfig"
|
||||||
|
);
|
||||||
|
}) as CallExpression | undefined;
|
||||||
|
|
||||||
|
if (!defineCall) return;
|
||||||
|
|
||||||
|
const configObj = defineCall.getArguments()[0] as
|
||||||
|
| ObjectLiteralExpression
|
||||||
|
| undefined;
|
||||||
|
if (!configObj) return;
|
||||||
|
|
||||||
|
const pluginsArray = ensureArrayProperty(configObj, "plugins");
|
||||||
|
|
||||||
|
const tanstackPluginIndex = pluginsArray
|
||||||
|
.getElements()
|
||||||
|
.findIndex((el) => el.getText().includes("tanstackStart("));
|
||||||
|
|
||||||
|
const tanstackPluginText = 'tanstackStart({ target: "cloudflare-module" })';
|
||||||
|
|
||||||
|
if (tanstackPluginIndex === -1) {
|
||||||
|
pluginsArray.addElement(tanstackPluginText);
|
||||||
|
} else {
|
||||||
|
pluginsArray
|
||||||
|
.getElements()
|
||||||
|
[tanstackPluginIndex].replaceWithText(tanstackPluginText);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tsProject.save();
|
||||||
|
}
|
||||||
@@ -3,15 +3,6 @@ import pc from "picocolors";
|
|||||||
import { DEFAULT_CONFIG } from "../constants";
|
import { DEFAULT_CONFIG } from "../constants";
|
||||||
import type { Backend, Frontend, Runtime, WebDeploy } from "../types";
|
import type { Backend, Frontend, Runtime, WebDeploy } from "../types";
|
||||||
|
|
||||||
const WORKERS_COMPATIBLE_FRONTENDS: Frontend[] = [
|
|
||||||
"tanstack-router",
|
|
||||||
"react-router",
|
|
||||||
"solid",
|
|
||||||
"next",
|
|
||||||
"nuxt",
|
|
||||||
"svelte",
|
|
||||||
];
|
|
||||||
|
|
||||||
type DeploymentOption = {
|
type DeploymentOption = {
|
||||||
value: WebDeploy;
|
value: WebDeploy;
|
||||||
label: string;
|
label: string;
|
||||||
@@ -38,18 +29,10 @@ export async function getDeploymentChoice(
|
|||||||
deployment?: WebDeploy,
|
deployment?: WebDeploy,
|
||||||
_runtime?: Runtime,
|
_runtime?: Runtime,
|
||||||
_backend?: Backend,
|
_backend?: Backend,
|
||||||
frontend: Frontend[] = [],
|
_frontend: Frontend[] = [],
|
||||||
): Promise<WebDeploy> {
|
): Promise<WebDeploy> {
|
||||||
if (deployment !== undefined) return deployment;
|
if (deployment !== undefined) return deployment;
|
||||||
|
|
||||||
const hasCompatibleFrontend = frontend.some((f) =>
|
|
||||||
WORKERS_COMPATIBLE_FRONTENDS.includes(f),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasCompatibleFrontend) {
|
|
||||||
return "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
const options: DeploymentOption[] = [
|
const options: DeploymentOption[] = [
|
||||||
{
|
{
|
||||||
value: "workers",
|
value: "workers",
|
||||||
@@ -74,15 +57,12 @@ export async function getDeploymentChoice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getDeploymentToAdd(
|
export async function getDeploymentToAdd(
|
||||||
frontend: Frontend[],
|
_frontend: Frontend[],
|
||||||
existingDeployment?: WebDeploy,
|
existingDeployment?: WebDeploy,
|
||||||
): Promise<WebDeploy> {
|
): Promise<WebDeploy> {
|
||||||
const options: DeploymentOption[] = [];
|
const options: DeploymentOption[] = [];
|
||||||
|
|
||||||
if (
|
if (existingDeployment !== "workers") {
|
||||||
frontend.some((f) => WORKERS_COMPATIBLE_FRONTENDS.includes(f)) &&
|
|
||||||
existingDeployment !== "workers"
|
|
||||||
) {
|
|
||||||
const { label, hint } = getDeploymentDisplay("workers");
|
const { label, hint } = getDeploymentDisplay("workers");
|
||||||
options.push({
|
options.push({
|
||||||
value: "workers",
|
value: "workers",
|
||||||
|
|||||||
@@ -451,24 +451,6 @@ export function processAndValidateFlags(
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
config.webDeploy === "workers" &&
|
|
||||||
config.frontend &&
|
|
||||||
config.frontend.length > 0
|
|
||||||
) {
|
|
||||||
const incompatibleFrontends = config.frontend.filter(
|
|
||||||
(f) => f === "tanstack-start",
|
|
||||||
);
|
|
||||||
if (incompatibleFrontends.length > 0) {
|
|
||||||
consola.fatal(
|
|
||||||
`The following frontends are not compatible with '--web-deploy workers': ${incompatibleFrontends.join(
|
|
||||||
", ",
|
|
||||||
)}. Please choose a different frontend or remove '--web-deploy workers'.`,
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../node_modules/wrangler/config-schema.json",
|
||||||
|
"name": "{{projectName}}",
|
||||||
|
"main": ".output/server/index.mjs",
|
||||||
|
"compatibility_date": "2025-07-05",
|
||||||
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
|
"assets": {
|
||||||
|
"directory": ".output/public",
|
||||||
|
},
|
||||||
|
"observability": {
|
||||||
|
"enabled": true,
|
||||||
|
},
|
||||||
|
// "kv_namespaces": [
|
||||||
|
// {
|
||||||
|
// "binding": "CACHE",
|
||||||
|
// "id": "<Your KV ID>",
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
.vinxi
|
.vinxi
|
||||||
.output
|
.output
|
||||||
.react-router/
|
.react-router/
|
||||||
|
.tanstack/
|
||||||
|
.nitro/
|
||||||
|
|
||||||
# Deployment
|
# Deployment
|
||||||
.vercel
|
.vercel
|
||||||
|
|||||||
@@ -1,174 +1,143 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
"$id": "https://better-t-stack.dev/schema.json",
|
"$id": "https://better-t-stack.dev/schema.json",
|
||||||
"title": "Better-T-Stack Configuration",
|
"title": "Better-T-Stack Configuration",
|
||||||
"description": "Configuration file for Better-T-Stack projects",
|
"description": "Configuration file for Better-T-Stack projects",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"$schema": {
|
"$schema": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "JSON Schema reference for validation"
|
"description": "JSON Schema reference for validation"
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "CLI version used to create this project",
|
"description": "CLI version used to create this project",
|
||||||
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
||||||
},
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time",
|
"format": "date-time",
|
||||||
"description": "Timestamp when the project was created"
|
"description": "Timestamp when the project was created"
|
||||||
},
|
},
|
||||||
"database": {
|
"database": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": ["none", "sqlite", "postgres", "mysql", "mongodb"],
|
||||||
"none",
|
"description": "Database type"
|
||||||
"sqlite",
|
},
|
||||||
"postgres",
|
"orm": {
|
||||||
"mysql",
|
"type": "string",
|
||||||
"mongodb"
|
"enum": ["drizzle", "prisma", "mongoose", "none"],
|
||||||
],
|
"description": "ORM type"
|
||||||
"description": "Database type"
|
},
|
||||||
},
|
"backend": {
|
||||||
"orm": {
|
"type": "string",
|
||||||
"type": "string",
|
"enum": [
|
||||||
"enum": [
|
"hono",
|
||||||
"drizzle",
|
"express",
|
||||||
"prisma",
|
"fastify",
|
||||||
"mongoose",
|
"next",
|
||||||
"none"
|
"elysia",
|
||||||
],
|
"convex",
|
||||||
"description": "ORM type"
|
"none"
|
||||||
},
|
],
|
||||||
"backend": {
|
"description": "Backend framework"
|
||||||
"type": "string",
|
},
|
||||||
"enum": [
|
"runtime": {
|
||||||
"hono",
|
"type": "string",
|
||||||
"express",
|
"enum": ["bun", "node", "workers", "none"],
|
||||||
"fastify",
|
"description": "Runtime environment (workers only available with hono backend and drizzle orm)"
|
||||||
"next",
|
},
|
||||||
"elysia",
|
"frontend": {
|
||||||
"convex",
|
"type": "array",
|
||||||
"none"
|
"items": {
|
||||||
],
|
"type": "string",
|
||||||
"description": "Backend framework"
|
"enum": [
|
||||||
},
|
"tanstack-router",
|
||||||
"runtime": {
|
"react-router",
|
||||||
"type": "string",
|
"tanstack-start",
|
||||||
"enum": [
|
"next",
|
||||||
"bun",
|
"nuxt",
|
||||||
"node",
|
"native-nativewind",
|
||||||
"workers",
|
"native-unistyles",
|
||||||
"none"
|
"svelte",
|
||||||
],
|
"solid",
|
||||||
"description": "Runtime environment (workers only available with hono backend and drizzle orm)"
|
"none"
|
||||||
},
|
]
|
||||||
"frontend": {
|
},
|
||||||
"type": "array",
|
"description": "Frontend framework"
|
||||||
"items": {
|
},
|
||||||
"type": "string",
|
"addons": {
|
||||||
"enum": [
|
"type": "array",
|
||||||
"tanstack-router",
|
"items": {
|
||||||
"react-router",
|
"type": "string",
|
||||||
"tanstack-start",
|
"enum": [
|
||||||
"next",
|
"pwa",
|
||||||
"nuxt",
|
"tauri",
|
||||||
"native-nativewind",
|
"starlight",
|
||||||
"native-unistyles",
|
"biome",
|
||||||
"svelte",
|
"husky",
|
||||||
"solid",
|
"turborepo",
|
||||||
"none"
|
"none"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"description": "Frontend framework"
|
"description": "Additional addons"
|
||||||
},
|
},
|
||||||
"addons": {
|
"examples": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": ["todo", "ai", "none"]
|
||||||
"pwa",
|
},
|
||||||
"tauri",
|
"description": "Example templates to include"
|
||||||
"starlight",
|
},
|
||||||
"biome",
|
"auth": {
|
||||||
"husky",
|
"type": "boolean",
|
||||||
"turborepo",
|
"description": "Whether authentication is enabled"
|
||||||
"none"
|
},
|
||||||
]
|
"packageManager": {
|
||||||
},
|
"type": "string",
|
||||||
"description": "Additional addons"
|
"enum": ["npm", "pnpm", "bun"],
|
||||||
},
|
"description": "Package manager"
|
||||||
"examples": {
|
},
|
||||||
"type": "array",
|
"dbSetup": {
|
||||||
"items": {
|
"type": "string",
|
||||||
"type": "string",
|
"enum": [
|
||||||
"enum": [
|
"turso",
|
||||||
"todo",
|
"neon",
|
||||||
"ai",
|
"prisma-postgres",
|
||||||
"none"
|
"mongodb-atlas",
|
||||||
]
|
"supabase",
|
||||||
},
|
"d1",
|
||||||
"description": "Example templates to include"
|
"none"
|
||||||
},
|
],
|
||||||
"auth": {
|
"description": "Database hosting setup"
|
||||||
"type": "boolean",
|
},
|
||||||
"description": "Whether authentication is enabled"
|
"api": {
|
||||||
},
|
"type": "string",
|
||||||
"packageManager": {
|
"enum": ["trpc", "orpc", "none"],
|
||||||
"type": "string",
|
"description": "API type"
|
||||||
"enum": [
|
},
|
||||||
"npm",
|
"webDeploy": {
|
||||||
"pnpm",
|
"type": "string",
|
||||||
"bun"
|
"enum": ["workers", "none"],
|
||||||
],
|
"description": "Web deployment"
|
||||||
"description": "Package manager"
|
}
|
||||||
},
|
},
|
||||||
"dbSetup": {
|
"required": [
|
||||||
"type": "string",
|
"version",
|
||||||
"enum": [
|
"createdAt",
|
||||||
"turso",
|
"database",
|
||||||
"neon",
|
"orm",
|
||||||
"prisma-postgres",
|
"backend",
|
||||||
"mongodb-atlas",
|
"runtime",
|
||||||
"supabase",
|
"frontend",
|
||||||
"d1",
|
"addons",
|
||||||
"none"
|
"examples",
|
||||||
],
|
"auth",
|
||||||
"description": "Database hosting setup"
|
"packageManager",
|
||||||
},
|
"dbSetup",
|
||||||
"api": {
|
"api",
|
||||||
"type": "string",
|
"webDeploy"
|
||||||
"enum": [
|
],
|
||||||
"trpc",
|
"additionalProperties": false
|
||||||
"orpc",
|
}
|
||||||
"none"
|
|
||||||
],
|
|
||||||
"description": "API type"
|
|
||||||
},
|
|
||||||
"webDeploy": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"workers",
|
|
||||||
"none"
|
|
||||||
],
|
|
||||||
"description": "Web deployment"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"version",
|
|
||||||
"createdAt",
|
|
||||||
"database",
|
|
||||||
"orm",
|
|
||||||
"backend",
|
|
||||||
"runtime",
|
|
||||||
"frontend",
|
|
||||||
"addons",
|
|
||||||
"examples",
|
|
||||||
"auth",
|
|
||||||
"packageManager",
|
|
||||||
"dbSetup",
|
|
||||||
"api",
|
|
||||||
"webDeploy"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -802,28 +802,6 @@ const analyzeStackCompatibility = (stack: StackState): CompatibilityResult => {
|
|||||||
if (nextStack.examples.length !== originalExamplesLength)
|
if (nextStack.examples.length !== originalExamplesLength)
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Web deploy compatibility: Workers not supported with TanStack Start
|
|
||||||
if (
|
|
||||||
nextStack.webDeploy === "workers" &&
|
|
||||||
nextStack.webFrontend.includes("tanstack-start")
|
|
||||||
) {
|
|
||||||
notes.webDeploy.notes.push(
|
|
||||||
"Cloudflare Workers deployment is not supported with TanStack Start. It will be set to 'None'.",
|
|
||||||
);
|
|
||||||
notes.webFrontend.notes.push(
|
|
||||||
"TanStack Start is not compatible with Cloudflare Workers deployment.",
|
|
||||||
);
|
|
||||||
notes.webDeploy.hasIssue = true;
|
|
||||||
notes.webFrontend.hasIssue = true;
|
|
||||||
nextStack.webDeploy = "none";
|
|
||||||
changed = true;
|
|
||||||
changes.push({
|
|
||||||
category: "webDeploy",
|
|
||||||
message:
|
|
||||||
"Web deployment set to 'None' (Workers not compatible with TanStack Start)",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user