create-better-t-stack 2.40.3 → 2.40.5
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-BOnnM-3r.js → src-jRwaAdo-.js} +40 -29
- package/package.json +1 -1
- package/templates/api/orpc/server/next/src/app/rpc/[...all]/route.ts.hbs +32 -3
- package/templates/backend/server/elysia/src/index.ts.hbs +31 -2
- package/templates/backend/server/express/src/index.ts.hbs +38 -4
- package/templates/backend/server/fastify/src/index.ts.hbs +33 -2
- package/templates/backend/server/hono/src/index.ts.hbs +40 -5
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -110,6 +110,8 @@ const dependencyVersionMap = {
|
|
|
110
110
|
streamdown: "^1.1.6",
|
|
111
111
|
"@orpc/server": "^1.8.6",
|
|
112
112
|
"@orpc/client": "^1.8.6",
|
|
113
|
+
"@orpc/openapi": "^1.8.6",
|
|
114
|
+
"@orpc/zod": "^1.8.6",
|
|
113
115
|
"@orpc/tanstack-query": "^1.8.6",
|
|
114
116
|
"@trpc/tanstack-react-query": "^11.5.0",
|
|
115
117
|
"@trpc/server": "^11.5.0",
|
|
@@ -3096,8 +3098,7 @@ async function setupNextAlchemyDeploy(projectDir, _packageManager, options) {
|
|
|
3096
3098
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3097
3099
|
...pkg.scripts,
|
|
3098
3100
|
deploy: "alchemy deploy",
|
|
3099
|
-
destroy: "alchemy destroy"
|
|
3100
|
-
dev: "alchemy dev"
|
|
3101
|
+
destroy: "alchemy destroy"
|
|
3101
3102
|
};
|
|
3102
3103
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3103
3104
|
}
|
|
@@ -3122,8 +3123,7 @@ async function setupNuxtAlchemyDeploy(projectDir, _packageManager, options) {
|
|
|
3122
3123
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3123
3124
|
...pkg.scripts,
|
|
3124
3125
|
deploy: "alchemy deploy",
|
|
3125
|
-
destroy: "alchemy destroy"
|
|
3126
|
-
dev: "alchemy dev"
|
|
3126
|
+
destroy: "alchemy destroy"
|
|
3127
3127
|
};
|
|
3128
3128
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3129
3129
|
}
|
|
@@ -3186,8 +3186,7 @@ async function setupReactRouterAlchemyDeploy(projectDir, _packageManager, option
|
|
|
3186
3186
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3187
3187
|
...pkg.scripts,
|
|
3188
3188
|
deploy: "alchemy deploy",
|
|
3189
|
-
destroy: "alchemy destroy"
|
|
3190
|
-
dev: "alchemy dev"
|
|
3189
|
+
destroy: "alchemy destroy"
|
|
3191
3190
|
};
|
|
3192
3191
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3193
3192
|
}
|
|
@@ -3208,8 +3207,7 @@ async function setupSolidAlchemyDeploy(projectDir, _packageManager, options) {
|
|
|
3208
3207
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3209
3208
|
...pkg.scripts,
|
|
3210
3209
|
deploy: "alchemy deploy",
|
|
3211
|
-
destroy: "alchemy destroy"
|
|
3212
|
-
dev: "alchemy dev"
|
|
3210
|
+
destroy: "alchemy destroy"
|
|
3213
3211
|
};
|
|
3214
3212
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3215
3213
|
}
|
|
@@ -3234,8 +3232,7 @@ async function setupSvelteAlchemyDeploy(projectDir, _packageManager, options) {
|
|
|
3234
3232
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3235
3233
|
...pkg.scripts,
|
|
3236
3234
|
deploy: "alchemy deploy",
|
|
3237
|
-
destroy: "alchemy destroy"
|
|
3238
|
-
dev: "alchemy dev"
|
|
3235
|
+
destroy: "alchemy destroy"
|
|
3239
3236
|
};
|
|
3240
3237
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3241
3238
|
}
|
|
@@ -3301,8 +3298,7 @@ async function setupTanStackRouterAlchemyDeploy(projectDir, _packageManager, opt
|
|
|
3301
3298
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3302
3299
|
...pkg.scripts,
|
|
3303
3300
|
deploy: "alchemy deploy",
|
|
3304
|
-
destroy: "alchemy destroy"
|
|
3305
|
-
dev: "alchemy dev"
|
|
3301
|
+
destroy: "alchemy destroy"
|
|
3306
3302
|
};
|
|
3307
3303
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3308
3304
|
}
|
|
@@ -3327,8 +3323,7 @@ async function setupTanStackStartAlchemyDeploy(projectDir, _packageManager, opti
|
|
|
3327
3323
|
if (!options?.skipAppScripts) pkg.scripts = {
|
|
3328
3324
|
...pkg.scripts,
|
|
3329
3325
|
deploy: "alchemy deploy",
|
|
3330
|
-
destroy: "alchemy destroy"
|
|
3331
|
-
dev: "alchemy dev"
|
|
3326
|
+
destroy: "alchemy destroy"
|
|
3332
3327
|
};
|
|
3333
3328
|
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
3334
3329
|
}
|
|
@@ -3892,7 +3887,12 @@ function getFrontendType(frontend) {
|
|
|
3892
3887
|
}
|
|
3893
3888
|
function getApiDependencies(api, frontendType) {
|
|
3894
3889
|
const deps = {};
|
|
3895
|
-
if (api === "orpc") deps.server = { dependencies: [
|
|
3890
|
+
if (api === "orpc") deps.server = { dependencies: [
|
|
3891
|
+
"@orpc/server",
|
|
3892
|
+
"@orpc/client",
|
|
3893
|
+
"@orpc/openapi",
|
|
3894
|
+
"@orpc/zod"
|
|
3895
|
+
] };
|
|
3896
3896
|
else if (api === "trpc") deps.server = { dependencies: ["@trpc/server", "@trpc/client"] };
|
|
3897
3897
|
if (frontendType.hasReactWeb) {
|
|
3898
3898
|
if (api === "orpc") deps.web = { dependencies: ["@orpc/tanstack-query", "@orpc/client"] };
|
|
@@ -5740,7 +5740,7 @@ async function getDockerStatus(database) {
|
|
|
5740
5740
|
//#endregion
|
|
5741
5741
|
//#region src/helpers/core/post-installation.ts
|
|
5742
5742
|
async function displayPostInstallInstructions(config) {
|
|
5743
|
-
const { database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy, serverDeploy } = config;
|
|
5743
|
+
const { api, database, relativePath, packageManager, depsInstalled, orm, addons, runtime, frontend, backend, dbSetup, webDeploy, serverDeploy } = config;
|
|
5744
5744
|
const isConvex = backend === "convex";
|
|
5745
5745
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager === "pnpm" ? "pnpm run" : "bun run";
|
|
5746
5746
|
const cdCmd = `cd ${relativePath}`;
|
|
@@ -5788,7 +5788,11 @@ async function displayPostInstallInstructions(config) {
|
|
|
5788
5788
|
output += `${pc.bold("Your project will be available at:")}\n`;
|
|
5789
5789
|
if (hasWeb) output += `${pc.cyan("•")} Frontend: http://localhost:${webPort}\n`;
|
|
5790
5790
|
else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
|
|
5791
|
-
if (!isConvex)
|
|
5791
|
+
if (!isConvex) {
|
|
5792
|
+
output += `${pc.cyan("•")} Backend API: http://localhost:3000\n`;
|
|
5793
|
+
if (api === "orpc") if (backend === "next") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/rpc/api\n`;
|
|
5794
|
+
else output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api\n`;
|
|
5795
|
+
}
|
|
5792
5796
|
if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
|
|
5793
5797
|
if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
|
|
5794
5798
|
if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
|
|
@@ -6365,7 +6369,7 @@ async function openUrl(url) {
|
|
|
6365
6369
|
|
|
6366
6370
|
//#endregion
|
|
6367
6371
|
//#region src/utils/sponsors.ts
|
|
6368
|
-
const SPONSORS_JSON_URL = "https://sponsors.
|
|
6372
|
+
const SPONSORS_JSON_URL = "https://sponsors.better-t-stack.dev/sponsors.json";
|
|
6369
6373
|
async function fetchSponsors(url = SPONSORS_JSON_URL) {
|
|
6370
6374
|
const s = spinner();
|
|
6371
6375
|
s.start("Fetching sponsors…");
|
|
@@ -6379,23 +6383,30 @@ async function fetchSponsors(url = SPONSORS_JSON_URL) {
|
|
|
6379
6383
|
return sponsors$1;
|
|
6380
6384
|
}
|
|
6381
6385
|
function displaySponsors(sponsors$1) {
|
|
6382
|
-
|
|
6386
|
+
const { total_sponsors } = sponsors$1.summary;
|
|
6387
|
+
if (total_sponsors === 0) {
|
|
6383
6388
|
log.info("No sponsors found. You can be the first one! ✨");
|
|
6384
6389
|
outro(pc.cyan("Visit https://github.com/sponsors/AmanVarshney01 to become a sponsor."));
|
|
6385
6390
|
return;
|
|
6386
6391
|
}
|
|
6387
|
-
sponsors$1
|
|
6388
|
-
|
|
6389
|
-
const displayName = sponsor.name ?? sponsor.login;
|
|
6390
|
-
const tier = entry.tierName ? ` (${entry.tierName})` : "";
|
|
6391
|
-
log.step(`${idx + 1}. ${pc.green(displayName)}${pc.yellow(tier)}`);
|
|
6392
|
-
log.message(` ${pc.dim("GitHub:")} https://github.com/${sponsor.login}`);
|
|
6393
|
-
const website = sponsor.websiteUrl ?? sponsor.linkUrl;
|
|
6394
|
-
if (website) log.message(` ${pc.dim("Website:")} ${website}`);
|
|
6395
|
-
});
|
|
6396
|
-
log.message("");
|
|
6392
|
+
displaySponsorsBox(sponsors$1);
|
|
6393
|
+
if (total_sponsors - sponsors$1.specialSponsors.length > 0) log.message(pc.blue(`+${total_sponsors - sponsors$1.specialSponsors.length} more amazing sponsors.\n`));
|
|
6397
6394
|
outro(pc.magenta("Visit https://github.com/sponsors/AmanVarshney01 to become a sponsor."));
|
|
6398
6395
|
}
|
|
6396
|
+
function displaySponsorsBox(sponsors$1) {
|
|
6397
|
+
if (sponsors$1.specialSponsors.length === 0) return;
|
|
6398
|
+
let output = `${pc.bold(pc.cyan("-> Special Sponsors"))}\n\n`;
|
|
6399
|
+
sponsors$1.specialSponsors.forEach((sponsor, idx) => {
|
|
6400
|
+
const displayName = sponsor.name ?? sponsor.githubId;
|
|
6401
|
+
const tier = sponsor.tierName ? ` ${pc.yellow(`(${sponsor.tierName})`)}` : "";
|
|
6402
|
+
output += `${pc.green(`• ${displayName}`)}${tier}\n`;
|
|
6403
|
+
output += ` ${pc.dim("GitHub:")} https://github.com/${sponsor.githubId}\n`;
|
|
6404
|
+
const website = sponsor.websiteUrl ?? sponsor.githubUrl;
|
|
6405
|
+
if (website) output += ` ${pc.dim("Website:")} ${website}\n`;
|
|
6406
|
+
if (idx < sponsors$1.specialSponsors.length - 1) output += "\n";
|
|
6407
|
+
});
|
|
6408
|
+
consola$1.box(output);
|
|
6409
|
+
}
|
|
6399
6410
|
|
|
6400
6411
|
//#endregion
|
|
6401
6412
|
//#region src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.40.
|
|
3
|
+
"version": "2.40.5",
|
|
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",
|
|
@@ -2,18 +2,47 @@
|
|
|
2
2
|
import { createContext } from '@/lib/context'
|
|
3
3
|
{{/if}}
|
|
4
4
|
import { appRouter } from '@/routers'
|
|
5
|
+
import { OpenAPIHandler } from '@orpc/openapi/fetch'
|
|
6
|
+
import { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'
|
|
7
|
+
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'
|
|
5
8
|
import { RPCHandler } from '@orpc/server/fetch'
|
|
9
|
+
import { onError } from '@orpc/server'
|
|
6
10
|
import { NextRequest } from 'next/server'
|
|
7
11
|
|
|
8
|
-
const
|
|
12
|
+
const rpcHandler = new RPCHandler(appRouter, {
|
|
13
|
+
interceptors: [
|
|
14
|
+
onError((error) => {
|
|
15
|
+
console.error(error)
|
|
16
|
+
}),
|
|
17
|
+
],
|
|
18
|
+
})
|
|
19
|
+
const apiHandler = new OpenAPIHandler(appRouter, {
|
|
20
|
+
plugins: [
|
|
21
|
+
new OpenAPIReferencePlugin({
|
|
22
|
+
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
23
|
+
}),
|
|
24
|
+
],
|
|
25
|
+
interceptors: [
|
|
26
|
+
onError((error) => {
|
|
27
|
+
console.error(error)
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
})
|
|
9
31
|
|
|
10
32
|
async function handleRequest(req: NextRequest) {
|
|
11
|
-
const
|
|
33
|
+
const rpcResult = await rpcHandler.handle(req, {
|
|
12
34
|
prefix: '/rpc',
|
|
13
35
|
context: {{#if (eq auth "better-auth")}}await createContext(req){{else}}{}{{/if}},
|
|
14
36
|
})
|
|
37
|
+
if (rpcResult.response) return rpcResult.response
|
|
15
38
|
|
|
16
|
-
|
|
39
|
+
const apiResult = await apiHandler.handle(req, {
|
|
40
|
+
prefix: '/rpc/api',
|
|
41
|
+
context: {{#if (eq auth "better-auth")}}await createContext(req){{else}}{}{{/if}},
|
|
42
|
+
})
|
|
43
|
+
if (apiResult.response) return apiResult.response
|
|
44
|
+
|
|
45
|
+
return new Response('Not found', { status: 404 })
|
|
17
46
|
}
|
|
18
47
|
|
|
19
48
|
export const GET = handleRequest
|
|
@@ -10,7 +10,11 @@ import { appRouter } from "./routers/index";
|
|
|
10
10
|
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
|
|
11
11
|
{{/if}}
|
|
12
12
|
{{#if (eq api "orpc")}}
|
|
13
|
+
import { OpenAPIHandler } from "@orpc/openapi/fetch";
|
|
14
|
+
import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins";
|
|
15
|
+
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
|
|
13
16
|
import { RPCHandler } from "@orpc/server/fetch";
|
|
17
|
+
import { onError } from "@orpc/server";
|
|
14
18
|
import { appRouter } from "./routers";
|
|
15
19
|
import { createContext } from "./lib/context";
|
|
16
20
|
{{/if}}
|
|
@@ -19,7 +23,25 @@ import { auth } from "./lib/auth";
|
|
|
19
23
|
{{/if}}
|
|
20
24
|
|
|
21
25
|
{{#if (eq api "orpc")}}
|
|
22
|
-
const
|
|
26
|
+
const rpcHandler = new RPCHandler(appRouter, {
|
|
27
|
+
interceptors: [
|
|
28
|
+
onError((error) => {
|
|
29
|
+
console.error(error);
|
|
30
|
+
}),
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
const apiHandler = new OpenAPIHandler(appRouter, {
|
|
34
|
+
plugins: [
|
|
35
|
+
new OpenAPIReferencePlugin({
|
|
36
|
+
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
interceptors: [
|
|
40
|
+
onError((error) => {
|
|
41
|
+
console.error(error);
|
|
42
|
+
}),
|
|
43
|
+
],
|
|
44
|
+
});
|
|
23
45
|
{{/if}}
|
|
24
46
|
|
|
25
47
|
{{#if (eq runtime "node")}}
|
|
@@ -48,12 +70,19 @@ const app = new Elysia()
|
|
|
48
70
|
{{/if}}
|
|
49
71
|
{{#if (eq api "orpc")}}
|
|
50
72
|
.all('/rpc*', async (context) => {
|
|
51
|
-
const { response } = await
|
|
73
|
+
const { response } = await rpcHandler.handle(context.request, {
|
|
52
74
|
prefix: '/rpc',
|
|
53
75
|
context: await createContext({ context })
|
|
54
76
|
})
|
|
55
77
|
return response ?? new Response('Not Found', { status: 404 })
|
|
56
78
|
})
|
|
79
|
+
.all('/api*', async (context) => {
|
|
80
|
+
const { response } = await apiHandler.handle(context.request, {
|
|
81
|
+
prefix: '/api',
|
|
82
|
+
context: await createContext({ context })
|
|
83
|
+
})
|
|
84
|
+
return response ?? new Response('Not Found', { status: 404 })
|
|
85
|
+
})
|
|
57
86
|
{{/if}}
|
|
58
87
|
{{#if (eq api "trpc")}}
|
|
59
88
|
.all("/trpc/*", async (context) => {
|
|
@@ -5,7 +5,11 @@ import { createContext } from "./lib/context";
|
|
|
5
5
|
import { appRouter } from "./routers/index";
|
|
6
6
|
{{/if}}
|
|
7
7
|
{{#if (eq api "orpc")}}
|
|
8
|
+
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
9
|
+
import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins";
|
|
10
|
+
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
|
|
8
11
|
import { RPCHandler } from "@orpc/server/node";
|
|
12
|
+
import { onError } from "@orpc/server";
|
|
9
13
|
import { appRouter } from "./routers";
|
|
10
14
|
{{#if (eq auth "better-auth")}}
|
|
11
15
|
import { createContext } from "./lib/context";
|
|
@@ -50,9 +54,28 @@ app.use(
|
|
|
50
54
|
{{/if}}
|
|
51
55
|
|
|
52
56
|
{{#if (eq api "orpc")}}
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
const rpcHandler = new RPCHandler(appRouter, {
|
|
58
|
+
interceptors: [
|
|
59
|
+
onError((error) => {
|
|
60
|
+
console.error(error);
|
|
61
|
+
}),
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
const apiHandler = new OpenAPIHandler(appRouter, {
|
|
65
|
+
plugins: [
|
|
66
|
+
new OpenAPIReferencePlugin({
|
|
67
|
+
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
interceptors: [
|
|
71
|
+
onError((error) => {
|
|
72
|
+
console.error(error);
|
|
73
|
+
}),
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
app.use(async (req, res, next) => {
|
|
78
|
+
const rpcResult = await rpcHandler.handle(req, res, {
|
|
56
79
|
prefix: "/rpc",
|
|
57
80
|
{{#if (eq auth "better-auth")}}
|
|
58
81
|
context: await createContext({ req }),
|
|
@@ -60,7 +83,18 @@ app.use("/rpc{*path}", async (req, res, next) => {
|
|
|
60
83
|
context: {},
|
|
61
84
|
{{/if}}
|
|
62
85
|
});
|
|
63
|
-
if (matched) return;
|
|
86
|
+
if (rpcResult.matched) return;
|
|
87
|
+
|
|
88
|
+
const apiResult = await apiHandler.handle(req, res, {
|
|
89
|
+
prefix: "/api",
|
|
90
|
+
{{#if (eq auth "better-auth")}}
|
|
91
|
+
context: await createContext({ req }),
|
|
92
|
+
{{else}}
|
|
93
|
+
context: {},
|
|
94
|
+
{{/if}}
|
|
95
|
+
});
|
|
96
|
+
if (apiResult.matched) return;
|
|
97
|
+
|
|
64
98
|
next();
|
|
65
99
|
});
|
|
66
100
|
{{/if}}
|
|
@@ -9,8 +9,12 @@ import { appRouter, type AppRouter } from "./routers/index";
|
|
|
9
9
|
{{/if}}
|
|
10
10
|
|
|
11
11
|
{{#if (eq api "orpc")}}
|
|
12
|
+
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
13
|
+
import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins";
|
|
14
|
+
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
|
|
12
15
|
import { RPCHandler } from "@orpc/server/node";
|
|
13
16
|
import { CORSPlugin } from "@orpc/server/plugins";
|
|
17
|
+
import { onError } from "@orpc/server";
|
|
14
18
|
import { appRouter } from "./routers/index";
|
|
15
19
|
import { createServer } from "node:http";
|
|
16
20
|
{{#if (eq auth "better-auth")}}
|
|
@@ -40,7 +44,7 @@ const baseCorsConfig = {
|
|
|
40
44
|
};
|
|
41
45
|
|
|
42
46
|
{{#if (eq api "orpc")}}
|
|
43
|
-
const
|
|
47
|
+
const rpcHandler = new RPCHandler(appRouter, {
|
|
44
48
|
plugins: [
|
|
45
49
|
new CORSPlugin({
|
|
46
50
|
origin: process.env.CORS_ORIGIN,
|
|
@@ -48,13 +52,31 @@ const handler = new RPCHandler(appRouter, {
|
|
|
48
52
|
allowHeaders: ["Content-Type", "Authorization"],
|
|
49
53
|
}),
|
|
50
54
|
],
|
|
55
|
+
interceptors: [
|
|
56
|
+
onError((error) => {
|
|
57
|
+
console.error(error);
|
|
58
|
+
}),
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const apiHandler = new OpenAPIHandler(appRouter, {
|
|
63
|
+
plugins: [
|
|
64
|
+
new OpenAPIReferencePlugin({
|
|
65
|
+
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
interceptors: [
|
|
69
|
+
onError((error) => {
|
|
70
|
+
console.error(error);
|
|
71
|
+
}),
|
|
72
|
+
],
|
|
51
73
|
});
|
|
52
74
|
|
|
53
75
|
const fastify = Fastify({
|
|
54
76
|
logger: true,
|
|
55
77
|
serverFactory: (fastifyHandler) => {
|
|
56
78
|
const server = createServer(async (req, res) => {
|
|
57
|
-
const { matched } = await
|
|
79
|
+
const { matched } = await rpcHandler.handle(req, res, {
|
|
58
80
|
context: await createContext(req.headers),
|
|
59
81
|
prefix: "/rpc",
|
|
60
82
|
});
|
|
@@ -63,6 +85,15 @@ const fastify = Fastify({
|
|
|
63
85
|
return;
|
|
64
86
|
}
|
|
65
87
|
|
|
88
|
+
const apiResult = await apiHandler.handle(req, res, {
|
|
89
|
+
context: await createContext(req.headers),
|
|
90
|
+
prefix: "/api",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (apiResult.matched) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
66
97
|
fastifyHandler(req, res);
|
|
67
98
|
});
|
|
68
99
|
|
|
@@ -5,7 +5,11 @@ import "dotenv/config";
|
|
|
5
5
|
import { env } from "cloudflare:workers";
|
|
6
6
|
{{/if}}
|
|
7
7
|
{{#if (eq api "orpc")}}
|
|
8
|
+
import { OpenAPIHandler } from "@orpc/openapi/fetch";
|
|
9
|
+
import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins";
|
|
10
|
+
import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4";
|
|
8
11
|
import { RPCHandler } from "@orpc/server/fetch";
|
|
12
|
+
import { onError } from "@orpc/server";
|
|
9
13
|
import { createContext } from "./lib/context";
|
|
10
14
|
import { appRouter } from "./routers/index";
|
|
11
15
|
{{/if}}
|
|
@@ -54,17 +58,48 @@ app.on(["POST", "GET"], "/api/auth/**", (c) => auth.handler(c.req.raw));
|
|
|
54
58
|
{{/if}}
|
|
55
59
|
|
|
56
60
|
{{#if (eq api "orpc")}}
|
|
57
|
-
const
|
|
58
|
-
|
|
61
|
+
export const apiHandler = new OpenAPIHandler(appRouter, {
|
|
62
|
+
plugins: [
|
|
63
|
+
new OpenAPIReferencePlugin({
|
|
64
|
+
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
65
|
+
}),
|
|
66
|
+
],
|
|
67
|
+
interceptors: [
|
|
68
|
+
onError((error) => {
|
|
69
|
+
console.error(error);
|
|
70
|
+
}),
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const rpcHandler = new RPCHandler(appRouter, {
|
|
75
|
+
interceptors: [
|
|
76
|
+
onError((error) => {
|
|
77
|
+
console.error(error);
|
|
78
|
+
}),
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
app.use("/*", async (c, next) => {
|
|
59
83
|
const context = await createContext({ context: c });
|
|
60
|
-
|
|
84
|
+
|
|
85
|
+
const rpcResult = await rpcHandler.handle(c.req.raw, {
|
|
61
86
|
prefix: "/rpc",
|
|
62
87
|
context: context,
|
|
63
88
|
});
|
|
64
89
|
|
|
65
|
-
if (matched) {
|
|
66
|
-
return c.newResponse(response.body, response);
|
|
90
|
+
if (rpcResult.matched) {
|
|
91
|
+
return c.newResponse(rpcResult.response.body, rpcResult.response);
|
|
67
92
|
}
|
|
93
|
+
|
|
94
|
+
const apiResult = await apiHandler.handle(c.req.raw, {
|
|
95
|
+
prefix: "/api",
|
|
96
|
+
context: context,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (apiResult.matched) {
|
|
100
|
+
return c.newResponse(apiResult.response.body, apiResult.response);
|
|
101
|
+
}
|
|
102
|
+
|
|
68
103
|
await next();
|
|
69
104
|
});
|
|
70
105
|
{{/if}}
|