@tanstack/start-server-core 1.120.4-alpha.8 → 1.120.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/README.md +27 -6
- package/dist/cjs/createRequestHandler.cjs +3 -1
- package/dist/cjs/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/createStartHandler.cjs +30 -235
- package/dist/cjs/createStartHandler.cjs.map +1 -1
- package/dist/cjs/createStartHandler.d.cts +6 -8
- package/dist/cjs/h3.cjs +73 -30
- package/dist/cjs/h3.cjs.map +1 -1
- package/dist/cjs/h3.d.cts +7 -11
- package/dist/cjs/handlerCallback.cjs.map +1 -1
- package/dist/cjs/handlerCallback.d.cts +4 -3
- package/dist/cjs/index.cjs +14 -20
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -7
- package/dist/esm/createRequestHandler.js +3 -1
- package/dist/esm/createRequestHandler.js.map +1 -1
- package/dist/esm/createStartHandler.d.ts +6 -8
- package/dist/esm/createStartHandler.js +32 -215
- package/dist/esm/createStartHandler.js.map +1 -1
- package/dist/esm/h3.d.ts +7 -11
- package/dist/esm/h3.js +63 -26
- package/dist/esm/h3.js.map +1 -1
- package/dist/esm/handlerCallback.d.ts +4 -3
- package/dist/esm/handlerCallback.js.map +1 -1
- package/dist/esm/index.d.ts +1 -7
- package/dist/esm/index.js +5 -17
- package/dist/esm/index.js.map +1 -1
- package/package.json +6 -9
- package/src/createRequestHandler.ts +3 -1
- package/src/createStartHandler.ts +48 -325
- package/src/h3.ts +78 -71
- package/src/handlerCallback.ts +12 -5
- package/src/index.tsx +1 -13
- package/dist/cjs/router-manifest.cjs +0 -44
- package/dist/cjs/router-manifest.cjs.map +0 -1
- package/dist/cjs/router-manifest.d.cts +0 -17
- package/dist/cjs/server-functions-handler.cjs +0 -154
- package/dist/cjs/server-functions-handler.cjs.map +0 -1
- package/dist/cjs/server-functions-handler.d.cts +0 -4
- package/dist/cjs/serverRoute.cjs +0 -100
- package/dist/cjs/serverRoute.cjs.map +0 -1
- package/dist/cjs/serverRoute.d.cts +0 -115
- package/dist/cjs/undici.cjs +0 -14
- package/dist/cjs/undici.cjs.map +0 -1
- package/dist/cjs/undici.d.cts +0 -43
- package/dist/esm/router-manifest.d.ts +0 -17
- package/dist/esm/router-manifest.js +0 -44
- package/dist/esm/router-manifest.js.map +0 -1
- package/dist/esm/server-functions-handler.d.ts +0 -4
- package/dist/esm/server-functions-handler.js +0 -154
- package/dist/esm/server-functions-handler.js.map +0 -1
- package/dist/esm/serverRoute.d.ts +0 -115
- package/dist/esm/serverRoute.js +0 -100
- package/dist/esm/serverRoute.js.map +0 -1
- package/dist/esm/undici.d.ts +0 -43
- package/dist/esm/undici.js +0 -14
- package/dist/esm/undici.js.map +0 -1
- package/src/router-manifest.ts +0 -79
- package/src/server-functions-handler.ts +0 -273
- package/src/serverRoute.ts +0 -661
- package/src/tanstack-start.d.ts +0 -5
- package/src/undici.ts +0 -60
package/README.md
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
|
+
> 🤫 we're cooking up something special!
|
|
2
|
+
|
|
1
3
|
<img src="https://static.scarf.sh/a.png?x-pxid=d988eb79-b0fc-4a2b-8514-6a1ab932d188" />
|
|
2
4
|
|
|
3
|
-
# TanStack Start
|
|
5
|
+
# TanStack Start
|
|
6
|
+
|
|
7
|
+

|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
🤖 Type-safe router w/ built-in caching & URL state management for React!
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
<a href="https://twitter.com/intent/tweet?button_hashtag=TanStack" target="\_parent">
|
|
12
|
+
<img alt="#TanStack" src="https://img.shields.io/twitter/url?color=%2308a0e9&label=%23TanStack&style=social&url=https%3A%2F%2Ftwitter.com%2Fintent%2Ftweet%3Fbutton_hashtag%3DTanStack">
|
|
13
|
+
</a><a href="https://discord.com/invite/WrRKjPJ" target="\_parent">
|
|
14
|
+
<img alt="" src="https://img.shields.io/badge/Discord-TanStack-%235865F2" />
|
|
15
|
+
</a><a href="https://npmjs.com/package/@tanstack/react-router" target="\_parent">
|
|
16
|
+
<img alt="" src="https://img.shields.io/npm/dm/@tanstack/router.svg" />
|
|
17
|
+
</a><a href="https://bundlephobia.com/result?p=@tanstack/react-router" target="\_parent">
|
|
18
|
+
<img alt="" src="https://badgen.net/bundlephobia/minzip/@tanstack/react-router" />
|
|
19
|
+
</a><a href="#badge">
|
|
20
|
+
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
|
21
|
+
</a><a href="https://github.com/tanstack/router/discussions">
|
|
22
|
+
<img alt="Join the discussion on Github" src="https://img.shields.io/badge/Github%20Discussions%20%26%20Support-Chat%20now!-blue" />
|
|
23
|
+
</a><a href="https://bestofjs.org/projects/router"><img alt="Best of JS" src="https://img.shields.io/endpoint?url=https://bestofjs-serverless.now.sh/api/project-badge?fullName=tanstack%2Frouter%26since=daily" /></a><a href="https://github.com/tanstack/router" target="\_parent">
|
|
24
|
+
<img alt="" src="https://img.shields.io/github/stars/tanstack/router.svg?style=social&label=Star" />
|
|
25
|
+
</a><a href="https://twitter.com/tan_stack" target="\_parent">
|
|
26
|
+
<img alt="" src="https://img.shields.io/twitter/follow/tan_stack.svg?style=social&label=Follow @TanStack" />
|
|
27
|
+
</a><a href="https://twitter.com/tannerlinsley" target="\_parent">
|
|
28
|
+
<img alt="" src="https://img.shields.io/twitter/follow/tannerlinsley.svg?style=social&label=Follow @TannerLinsley" />
|
|
29
|
+
</a>
|
|
9
30
|
|
|
10
|
-
|
|
31
|
+
Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual)
|
|
11
32
|
|
|
12
|
-
|
|
33
|
+
## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more!
|
|
@@ -42,7 +42,9 @@ function getRequestHeaders(opts) {
|
|
|
42
42
|
);
|
|
43
43
|
const { redirect } = opts.router.state;
|
|
44
44
|
if (redirect) {
|
|
45
|
-
headers = startClientCore.mergeHeaders(headers, redirect.headers
|
|
45
|
+
headers = startClientCore.mergeHeaders(headers, redirect.headers, {
|
|
46
|
+
Location: redirect.href
|
|
47
|
+
});
|
|
46
48
|
}
|
|
47
49
|
return headers;
|
|
48
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createRequestHandler.cjs","sources":["../../src/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from '@tanstack/start-client-core'\nimport { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyRouter, Manifest } from '@tanstack/router-core'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n\n attachRouterServerSsrUtils(router, await getRouterManifest?.())\n\n const url = new URL(request.url, 'http://localhost')\n\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n })\n\n await router.load()\n\n dehydrateRouter(router)\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n return cb({\n request,\n router,\n responseHeaders,\n } as any)\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n let headers = mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers)\n }\n\n return headers\n}\n"],"names":["attachRouterServerSsrUtils","history","createMemoryHistory","dehydrateRouter","mergeHeaders"],"mappings":";;;;;AAUO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;AACnB,UAAM,SAAS,aAAa;AAEDA,yCAAA,QAAQ,OAAM,yDAAqB;AAE9D,UAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,kBAAkB;AAEnD,UAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,UAAMC,YAAUC,QAAAA,oBAAoB;AAAA,MAClC,gBAAgB,CAAC,IAAI;AAAA,IAAA,CACtB;AAGD,WAAO,OAAO;AAAA,MACZD,SAAAA;AAAAA,IAAA,CACD;AAED,UAAM,OAAO,KAAK;AAElBE,cAAAA,gBAAgB,MAAM;AAEtB,UAAM,kBAAkB,kBAAkB;AAAA,MACxC;AAAA,IAAA,CACD;AAED,WAAO,GAAG;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACM;AAAA,EACV;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,MAAI,UAAUC,gBAAA;AAAA,IACZ;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA,GAAG,KAAK,OAAO,MAAM,QAAQ,IAAI,CAAC,UAAU;AAC1C,aAAO,MAAM;AAAA,IACd,CAAA;AAAA,EACH;AAGA,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AAEjC,MAAI,UAAU;AACF,cAAAA,gBAAA,aAAa,SAAS,SAAS,
|
|
1
|
+
{"version":3,"file":"createRequestHandler.cjs","sources":["../../src/createRequestHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from '@tanstack/start-client-core'\nimport { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { AnyRouter, Manifest } from '@tanstack/router-core'\n\nexport type RequestHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => Promise<Response>\n\nexport function createRequestHandler<TRouter extends AnyRouter>({\n createRouter,\n request,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n request: Request\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): RequestHandler<TRouter> {\n return async (cb) => {\n const router = createRouter()\n\n attachRouterServerSsrUtils(router, await getRouterManifest?.())\n\n const url = new URL(request.url, 'http://localhost')\n\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Update the router with the history and context\n router.update({\n history,\n })\n\n await router.load()\n\n dehydrateRouter(router)\n\n const responseHeaders = getRequestHeaders({\n router,\n })\n\n return cb({\n request,\n router,\n responseHeaders,\n } as any)\n }\n}\n\nfunction getRequestHeaders(opts: { router: AnyRouter }): Headers {\n let headers = mergeHeaders(\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers, {\n Location: redirect.href,\n })\n }\n\n return headers\n}\n"],"names":["attachRouterServerSsrUtils","history","createMemoryHistory","dehydrateRouter","mergeHeaders"],"mappings":";;;;;AAUO,SAAS,qBAAgD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AACF,GAI4B;AAC1B,SAAO,OAAO,OAAO;AACnB,UAAM,SAAS,aAAa;AAEDA,yCAAA,QAAQ,OAAM,yDAAqB;AAE9D,UAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,kBAAkB;AAEnD,UAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,UAAMC,YAAUC,QAAAA,oBAAoB;AAAA,MAClC,gBAAgB,CAAC,IAAI;AAAA,IAAA,CACtB;AAGD,WAAO,OAAO;AAAA,MACZD,SAAAA;AAAAA,IAAA,CACD;AAED,UAAM,OAAO,KAAK;AAElBE,cAAAA,gBAAgB,MAAM;AAEtB,UAAM,kBAAkB,kBAAkB;AAAA,MACxC;AAAA,IAAA,CACD;AAED,WAAO,GAAG;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACM;AAAA,EACV;AACF;AAEA,SAAS,kBAAkB,MAAsC;AAC/D,MAAI,UAAUC,gBAAA;AAAA,IACZ;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA,GAAG,KAAK,OAAO,MAAM,QAAQ,IAAI,CAAC,UAAU;AAC1C,aAAO,MAAM;AAAA,IACd,CAAA;AAAA,EACH;AAGA,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AAEjC,MAAI,UAAU;AACF,cAAAA,gBAAA,aAAa,SAAS,SAAS,SAAS;AAAA,MAChD,UAAU,SAAS;AAAA,IAAA,CACpB;AAAA,EAAA;AAGI,SAAA;AACT;;"}
|
|
@@ -1,261 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
for (let key of __getOwnPropNames(from))
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
-
}
|
|
14
|
-
return to;
|
|
15
|
-
};
|
|
16
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
-
mod
|
|
23
|
-
));
|
|
24
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
25
3
|
const history = require("@tanstack/history");
|
|
26
4
|
const startClientCore = require("@tanstack/start-client-core");
|
|
27
|
-
const
|
|
28
|
-
const h3 = require("./h3.cjs");
|
|
5
|
+
const h3 = require("h3");
|
|
29
6
|
const ssrServer = require("./ssr-server.cjs");
|
|
30
|
-
const routerManifest = require("./router-manifest.cjs");
|
|
31
|
-
const serverFunctionsHandler = require("./server-functions-handler.cjs");
|
|
32
|
-
function getStartResponseHeaders(opts) {
|
|
33
|
-
let headers = startClientCore.mergeHeaders(
|
|
34
|
-
h3.getResponseHeaders(),
|
|
35
|
-
{
|
|
36
|
-
"Content-Type": "text/html; charset=UTF-8"
|
|
37
|
-
},
|
|
38
|
-
...opts.router.state.matches.map((match) => {
|
|
39
|
-
return match.headers;
|
|
40
|
-
})
|
|
41
|
-
);
|
|
42
|
-
const { redirect } = opts.router.state;
|
|
43
|
-
if (redirect) {
|
|
44
|
-
headers = startClientCore.mergeHeaders(headers, redirect.headers);
|
|
45
|
-
}
|
|
46
|
-
return headers;
|
|
47
|
-
}
|
|
48
7
|
function createStartHandler({
|
|
49
|
-
createRouter
|
|
8
|
+
createRouter,
|
|
9
|
+
getRouterManifest
|
|
50
10
|
}) {
|
|
51
11
|
return (cb) => {
|
|
52
|
-
return h3.
|
|
12
|
+
return h3.eventHandler(async (event) => {
|
|
13
|
+
const request = h3.toWebRequest(event);
|
|
53
14
|
const url = new URL(request.url);
|
|
54
15
|
const href = url.href.replace(url.origin, "");
|
|
55
16
|
const history$1 = history.createMemoryHistory({
|
|
56
17
|
initialEntries: [href]
|
|
57
18
|
});
|
|
58
19
|
const router = createRouter();
|
|
59
|
-
ssrServer.attachRouterServerSsrUtils(router,
|
|
20
|
+
ssrServer.attachRouterServerSsrUtils(router, await (getRouterManifest == null ? void 0 : getRouterManifest()));
|
|
60
21
|
router.update({
|
|
61
22
|
history: history$1
|
|
62
23
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const serverFnBase = routerCore.joinPaths([
|
|
71
|
-
"/",
|
|
72
|
-
routerCore.trimPath(process.env.TSS_SERVER_FN_BASE),
|
|
73
|
-
"/"
|
|
74
|
-
]);
|
|
75
|
-
if (href.startsWith(serverFnBase)) {
|
|
76
|
-
return await serverFunctionsHandler.handleServerAction({ request });
|
|
77
|
-
}
|
|
78
|
-
const serverRouteTreeModule = await (async () => {
|
|
79
|
-
try {
|
|
80
|
-
return await import("tanstack:server-routes");
|
|
81
|
-
} catch (e) {
|
|
82
|
-
console.log(e);
|
|
83
|
-
return void 0;
|
|
84
|
-
}
|
|
85
|
-
})();
|
|
86
|
-
if (serverRouteTreeModule) {
|
|
87
|
-
const [_matchedRoutes, response3] = await handleServerRoutes({
|
|
88
|
-
routeTree: serverRouteTreeModule.routeTree,
|
|
89
|
-
request
|
|
90
|
-
});
|
|
91
|
-
if (response3) return response3;
|
|
92
|
-
}
|
|
93
|
-
const requestAcceptHeader = request.headers.get("Accept") || "*/*";
|
|
94
|
-
const splitRequestAcceptHeader = requestAcceptHeader.split(",");
|
|
95
|
-
const supportedMimeTypes = ["*/*", "text/html"];
|
|
96
|
-
const isRouterAcceptSupported = supportedMimeTypes.some(
|
|
97
|
-
(mimeType) => splitRequestAcceptHeader.some(
|
|
98
|
-
(acceptedMimeType) => acceptedMimeType.trim().startsWith(mimeType)
|
|
99
|
-
)
|
|
100
|
-
);
|
|
101
|
-
if (!isRouterAcceptSupported) {
|
|
102
|
-
return startClientCore.json(
|
|
103
|
-
{
|
|
104
|
-
error: "Only HTML requests are supported here"
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
status: 500
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
await router.load();
|
|
112
|
-
if (router.state.redirect) return router.state.redirect;
|
|
113
|
-
ssrServer.dehydrateRouter(router);
|
|
114
|
-
const responseHeaders = getStartResponseHeaders({ router });
|
|
115
|
-
const response2 = await cb({
|
|
116
|
-
request,
|
|
117
|
-
router,
|
|
118
|
-
responseHeaders
|
|
119
|
-
});
|
|
120
|
-
return response2;
|
|
121
|
-
} catch (err) {
|
|
122
|
-
if (err instanceof Response) {
|
|
123
|
-
return err;
|
|
124
|
-
}
|
|
125
|
-
throw err;
|
|
126
|
-
}
|
|
127
|
-
})();
|
|
128
|
-
if (routerCore.isRedirect(response)) {
|
|
129
|
-
if (response.options.to && typeof response.options.to === "string" && !response.options.to.startsWith("/")) {
|
|
130
|
-
throw new Error(
|
|
131
|
-
`Server side redirects must use absolute paths via the 'href' or 'to' options. Received: ${JSON.stringify(response.options)}`
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
if (["params", "search", "hash"].some(
|
|
135
|
-
(d) => typeof response.options[d] === "function"
|
|
136
|
-
)) {
|
|
137
|
-
throw new Error(
|
|
138
|
-
`Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys(
|
|
139
|
-
response.options
|
|
140
|
-
).filter((d) => typeof response.options[d] === "function").map((d) => `"${d}"`).join(", ")}`
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
const redirect = router.resolveRedirect(response);
|
|
144
|
-
if (request.headers.get("x-tsr-redirect") === "manual") {
|
|
145
|
-
return startClientCore.json(
|
|
146
|
-
{
|
|
147
|
-
...response.options,
|
|
148
|
-
isSerializedRedirect: true
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
headers: redirect.headers
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
return redirect;
|
|
156
|
-
}
|
|
157
|
-
const body = response.status === 204 ? null : await response.clone().blob();
|
|
158
|
-
const headers = new Headers(response.headers);
|
|
159
|
-
headers.append("Access-Control-Expose-Headers", routerCore.tsrRedirectHeaderKey);
|
|
160
|
-
return new Response(body, {
|
|
161
|
-
status: response.status,
|
|
162
|
-
statusText: response.statusText,
|
|
163
|
-
headers
|
|
24
|
+
await router.load();
|
|
25
|
+
ssrServer.dehydrateRouter(router);
|
|
26
|
+
const responseHeaders = getStartResponseHeaders({ event, router });
|
|
27
|
+
const response = await cb({
|
|
28
|
+
request,
|
|
29
|
+
router,
|
|
30
|
+
responseHeaders
|
|
164
31
|
});
|
|
32
|
+
return response;
|
|
165
33
|
});
|
|
166
34
|
};
|
|
167
35
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
initialEntries: [pathname]
|
|
184
|
-
});
|
|
185
|
-
const { matchedRoutes, foundRoute, routeParams } = routerCore.getMatchedRoutes({
|
|
186
|
-
pathname: history$1.location.pathname,
|
|
187
|
-
basepath: "/",
|
|
188
|
-
caseSensitive: true,
|
|
189
|
-
routesByPath,
|
|
190
|
-
routesById,
|
|
191
|
-
flatRoutes
|
|
192
|
-
});
|
|
193
|
-
let response;
|
|
194
|
-
if (foundRoute && foundRoute.id !== routerCore.rootRouteId) {
|
|
195
|
-
const method = Object.keys(foundRoute.options.methods).find(
|
|
196
|
-
(method2) => method2.toLowerCase() === request.method.toLowerCase()
|
|
197
|
-
);
|
|
198
|
-
if (method) {
|
|
199
|
-
const handler = foundRoute.options.methods[method];
|
|
200
|
-
if (handler) {
|
|
201
|
-
const middlewares = startClientCore.flattenMiddlewares(
|
|
202
|
-
matchedRoutes.flatMap((r) => r.options.middleware).filter(Boolean)
|
|
203
|
-
).map((d) => d.options.server);
|
|
204
|
-
middlewares.push(handlerToMiddleware(handler));
|
|
205
|
-
const ctx = await executeMiddleware(middlewares, {
|
|
206
|
-
request,
|
|
207
|
-
context: {},
|
|
208
|
-
params: routeParams,
|
|
209
|
-
pathname: history$1.location.pathname
|
|
210
|
-
});
|
|
211
|
-
response = ctx.response;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return [matchedRoutes, response];
|
|
216
|
-
}
|
|
217
|
-
function handlerToMiddleware(handler) {
|
|
218
|
-
return async ({ next, ...rest }) => ({
|
|
219
|
-
response: await handler(rest)
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
function executeMiddleware(middlewares, ctx) {
|
|
223
|
-
let index = -1;
|
|
224
|
-
const next = async (ctx2) => {
|
|
225
|
-
index++;
|
|
226
|
-
const middleware = middlewares[index];
|
|
227
|
-
if (!middleware) return ctx2;
|
|
228
|
-
const result = await middleware({
|
|
229
|
-
...ctx2,
|
|
230
|
-
// Allow the middleware to call the next middleware in the chain
|
|
231
|
-
next: async (nextCtx) => {
|
|
232
|
-
const nextResult = await next({ ...ctx2, ...nextCtx });
|
|
233
|
-
return Object.assign(ctx2, handleCtxResult(nextResult));
|
|
234
|
-
}
|
|
235
|
-
// Allow the middleware result to extend the return context
|
|
236
|
-
}).catch((err) => {
|
|
237
|
-
if (isSpecialResponse(err)) {
|
|
238
|
-
return {
|
|
239
|
-
response: err
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
throw err;
|
|
36
|
+
function getStartResponseHeaders(opts) {
|
|
37
|
+
let headers = startClientCore.mergeHeaders(
|
|
38
|
+
h3.getResponseHeaders(opts.event),
|
|
39
|
+
opts.event.___ssrRpcResponseHeaders,
|
|
40
|
+
{
|
|
41
|
+
"Content-Type": "text/html; charset=UTF-8"
|
|
42
|
+
},
|
|
43
|
+
...opts.router.state.matches.map((match) => {
|
|
44
|
+
return match.headers;
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
const { redirect } = opts.router.state;
|
|
48
|
+
if (redirect) {
|
|
49
|
+
headers = startClientCore.mergeHeaders(headers, redirect.headers, {
|
|
50
|
+
Location: redirect.href
|
|
243
51
|
});
|
|
244
|
-
return Object.assign(ctx2, handleCtxResult(result));
|
|
245
|
-
};
|
|
246
|
-
return handleCtxResult(next(ctx));
|
|
247
|
-
}
|
|
248
|
-
function handleCtxResult(result) {
|
|
249
|
-
if (isSpecialResponse(result)) {
|
|
250
|
-
return {
|
|
251
|
-
response: result
|
|
252
|
-
};
|
|
253
52
|
}
|
|
254
|
-
return
|
|
255
|
-
}
|
|
256
|
-
function isSpecialResponse(err) {
|
|
257
|
-
return err instanceof Response || routerCore.isRedirect(err);
|
|
53
|
+
return headers;
|
|
258
54
|
}
|
|
259
55
|
exports.createStartHandler = createStartHandler;
|
|
260
|
-
exports.getStartResponseHeaders = getStartResponseHeaders;
|
|
261
56
|
//# sourceMappingURL=createStartHandler.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createStartHandler.cjs","sources":["../../src/createStartHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport {\n flattenMiddlewares,\n json,\n mergeHeaders,\n} from '@tanstack/start-client-core'\nimport {\n getMatchedRoutes,\n isRedirect,\n joinPaths,\n processRouteTree,\n rootRouteId,\n trimPath,\n tsrRedirectHeaderKey,\n} from '@tanstack/router-core'\nimport { getResponseHeaders, requestHandler } from './h3'\nimport { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'\nimport { getStartManifest } from './router-manifest'\nimport { handleServerAction } from './server-functions-handler'\nimport type { AnyServerRoute, AnyServerRouteWithTypes } from './serverRoute'\nimport type { RequestHandler } from './h3'\nimport type { AnyRouter } from '@tanstack/router-core'\nimport type { HandlerCallback } from './handlerCallback'\n\ntype TODO = any\n\nexport type CustomizeStartHandler<TRouter extends AnyRouter> = (\n cb: HandlerCallback<TRouter>,\n) => RequestHandler\n\nexport function getStartResponseHeaders(opts: { router: AnyRouter }) {\n let headers = mergeHeaders(\n getResponseHeaders(),\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers)\n }\n return headers\n}\n\nexport function createStartHandler<TRouter extends AnyRouter>({\n createRouter,\n}: {\n createRouter: () => TRouter\n}): CustomizeStartHandler<TRouter> {\n return (cb) => {\n return requestHandler(async ({ request }) => {\n const url = new URL(request.url)\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the client-side router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n // Create the client-side router\n const router = createRouter()\n\n // Attach the server-side SSR utils to the client-side router\n attachRouterServerSsrUtils(router, getStartManifest())\n\n // Update the client-side router with the history and context\n router.update({\n history,\n })\n\n const response = await (async () => {\n try {\n if (!process.env.TSS_SERVER_FN_BASE) {\n throw new Error(\n 'tanstack/start-server-core: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()',\n )\n }\n\n // First, let's attempt to handle server functions\n // Add trailing slash to sanitise user defined TSS_SERVER_FN_BASE\n const serverFnBase = joinPaths([\n '/',\n trimPath(process.env.TSS_SERVER_FN_BASE),\n '/',\n ])\n if (href.startsWith(serverFnBase)) {\n return await handleServerAction({ request })\n }\n\n // Then move on to attempting to load server routes\n const serverRouteTreeModule = await (async () => {\n try {\n // @ts-expect-error\n return (await import('tanstack:server-routes')) as {\n routeTree: AnyServerRoute\n }\n } catch (e) {\n console.log(e)\n return undefined\n }\n })()\n\n // If we have a server route tree, then we try matching to see if we have a\n // server route that matches the request.\n if (serverRouteTreeModule) {\n const [_matchedRoutes, response] = await handleServerRoutes({\n routeTree: serverRouteTreeModule.routeTree,\n request,\n })\n\n if (response) return response\n }\n\n const requestAcceptHeader = request.headers.get('Accept') || '*/*'\n const splitRequestAcceptHeader = requestAcceptHeader.split(',')\n\n const supportedMimeTypes = ['*/*', 'text/html']\n const isRouterAcceptSupported = supportedMimeTypes.some((mimeType) =>\n splitRequestAcceptHeader.some((acceptedMimeType) =>\n acceptedMimeType.trim().startsWith(mimeType),\n ),\n )\n\n if (!isRouterAcceptSupported) {\n return json(\n {\n error: 'Only HTML requests are supported here',\n },\n {\n status: 500,\n },\n )\n }\n\n // If no Server Routes were found, so fallback to normal SSR matching using\n // the router\n\n await router.load()\n\n // If there was a redirect, skip rendering the page at all\n if (router.state.redirect) return router.state.redirect\n\n dehydrateRouter(router)\n\n const responseHeaders = getStartResponseHeaders({ router })\n const response = await cb({\n request,\n router,\n responseHeaders,\n })\n\n return response\n } catch (err) {\n if (err instanceof Response) {\n return err\n }\n\n throw err\n }\n })()\n\n if (isRedirect(response)) {\n if (\n response.options.to &&\n typeof response.options.to === 'string' &&\n !response.options.to.startsWith('/')\n ) {\n throw new Error(\n `Server side redirects must use absolute paths via the 'href' or 'to' options. Received: ${JSON.stringify(response.options)}`,\n )\n }\n\n if (\n ['params', 'search', 'hash'].some(\n (d) => typeof (response.options as any)[d] === 'function',\n )\n ) {\n throw new Error(\n `Server side redirects must use static search, params, and hash values and do not support functional values. Received functional values for: ${Object.keys(\n response.options,\n )\n .filter((d) => typeof (response.options as any)[d] === 'function')\n .map((d) => `\"${d}\"`)\n .join(', ')}`,\n )\n }\n\n const redirect = router.resolveRedirect(response)\n\n if (request.headers.get('x-tsr-redirect') === 'manual') {\n return json(\n {\n ...response.options,\n isSerializedRedirect: true,\n },\n {\n headers: redirect.headers,\n },\n )\n }\n\n return redirect\n }\n\n // Add Access-Control-Expose-Headers\n // With HTTPs the response/header objects are immutable, therefore we must clone them\n const body =\n response.status === 204 ? null : await response.clone().blob()\n const headers = new Headers(response.headers)\n headers.append('Access-Control-Expose-Headers', tsrRedirectHeaderKey)\n\n return new Response(body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n })\n })\n }\n}\n\nasync function handleServerRoutes({\n routeTree,\n request,\n}: {\n routeTree: AnyServerRouteWithTypes\n request: Request\n}) {\n const { flatRoutes, routesById, routesByPath } = processRouteTree({\n routeTree,\n initRoute: (route, i) => {\n route.init({\n originalIndex: i,\n })\n },\n })\n\n const url = new URL(request.url)\n const pathname = url.pathname\n\n const history = createMemoryHistory({\n initialEntries: [pathname],\n })\n\n const { matchedRoutes, foundRoute, routeParams } =\n getMatchedRoutes<AnyServerRouteWithTypes>({\n pathname: history.location.pathname,\n basepath: '/',\n caseSensitive: true,\n routesByPath,\n routesById,\n flatRoutes,\n })\n\n let response: Response | undefined\n\n if (foundRoute && foundRoute.id !== rootRouteId) {\n // We've found a server route that matches the request, so we can call it.\n // TODO: Get the input type-signature correct\n // TODO: Perform the middlewares?\n // TODO: Error handling? What happens when its `throw redirect()` vs `throw new Error()`?\n\n const method = Object.keys(foundRoute.options.methods).find(\n (method) => method.toLowerCase() === request.method.toLowerCase(),\n )\n\n if (method) {\n const handler = foundRoute.options.methods[method]\n\n if (handler) {\n const middlewares = flattenMiddlewares(\n matchedRoutes.flatMap((r) => r.options.middleware).filter(Boolean),\n ).map((d) => d.options.server)\n\n middlewares.push(handlerToMiddleware(handler) as TODO)\n\n // TODO: This is starting to feel too much like a server function\n // Do generalize the existing middleware execution? Or do we need to\n // build a new middleware execution system for server routes?\n const ctx = await executeMiddleware(middlewares, {\n request,\n context: {},\n params: routeParams,\n pathname: history.location.pathname,\n })\n\n response = ctx.response\n }\n }\n }\n\n // We return the matched routes too so if\n // the app router happens to match the same path,\n // it can use any request middleware from server routes\n return [matchedRoutes, response] as const\n}\n\nfunction handlerToMiddleware(\n handler: AnyServerRouteWithTypes['options']['methods'][string],\n) {\n return async ({ next, ...rest }: TODO) => ({\n response: await handler(rest),\n })\n}\n\nfunction executeMiddleware(middlewares: TODO, ctx: TODO) {\n let index = -1\n\n const next = async (ctx: TODO) => {\n index++\n const middleware = middlewares[index]\n if (!middleware) return ctx\n\n const result = await middleware({\n ...ctx,\n // Allow the middleware to call the next middleware in the chain\n next: async (nextCtx: TODO) => {\n // Allow the caller to extend the context for the next middleware\n const nextResult = await next({ ...ctx, ...nextCtx })\n\n // Merge the result into the context\\\n return Object.assign(ctx, handleCtxResult(nextResult))\n },\n // Allow the middleware result to extend the return context\n }).catch((err: TODO) => {\n if (isSpecialResponse(err)) {\n return {\n response: err,\n }\n }\n\n throw err\n })\n\n // Merge the middleware result into the context, just in case it\n // returns a partial context\n return Object.assign(ctx, handleCtxResult(result))\n }\n\n return handleCtxResult(next(ctx))\n}\n\nfunction handleCtxResult(result: TODO) {\n if (isSpecialResponse(result)) {\n return {\n response: result,\n }\n }\n\n return result\n}\n\nfunction isSpecialResponse(err: TODO) {\n return err instanceof Response || isRedirect(err)\n}\n"],"names":["mergeHeaders","getResponseHeaders","requestHandler","history","createMemoryHistory","attachRouterServerSsrUtils","getStartManifest","joinPaths","trimPath","handleServerAction","response","json","dehydrateRouter","isRedirect","tsrRedirectHeaderKey","processRouteTree","getMatchedRoutes","rootRouteId","method","flattenMiddlewares","ctx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createStartHandler.cjs","sources":["../../src/createStartHandler.ts"],"sourcesContent":["import { createMemoryHistory } from '@tanstack/history'\nimport { mergeHeaders } from '@tanstack/start-client-core'\nimport { eventHandler, getResponseHeaders, toWebRequest } from 'h3'\nimport { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server'\nimport type { HandlerCallback } from './handlerCallback'\nimport type { EventHandlerResponse, H3Event } from 'h3'\nimport type { AnyRouter, Manifest } from '@tanstack/router-core'\n\nexport type CustomizeStartHandler<\n TRouter extends AnyRouter,\n TResponse extends EventHandlerResponse = EventHandlerResponse,\n> = (cb: HandlerCallback<TRouter, TResponse>) => ReturnType<typeof eventHandler>\n\nexport function createStartHandler<\n TRouter extends AnyRouter,\n TResponse extends EventHandlerResponse = EventHandlerResponse,\n>({\n createRouter,\n getRouterManifest,\n}: {\n createRouter: () => TRouter\n getRouterManifest?: () => Manifest | Promise<Manifest>\n}): CustomizeStartHandler<TRouter, TResponse> {\n return (cb) => {\n return eventHandler(async (event) => {\n const request = toWebRequest(event)\n\n const url = new URL(request.url)\n const href = url.href.replace(url.origin, '')\n\n // Create a history for the router\n const history = createMemoryHistory({\n initialEntries: [href],\n })\n\n const router = createRouter()\n\n attachRouterServerSsrUtils(router, await getRouterManifest?.())\n\n // Update the router with the history and context\n router.update({\n history,\n })\n\n await router.load()\n\n dehydrateRouter(router)\n\n const responseHeaders = getStartResponseHeaders({ event, router })\n const response = await cb({\n request,\n router,\n responseHeaders,\n })\n\n return response\n })\n }\n}\n\nfunction getStartResponseHeaders(opts: { event: H3Event; router: AnyRouter }) {\n let headers = mergeHeaders(\n getResponseHeaders(opts.event),\n (opts.event as any).___ssrRpcResponseHeaders,\n {\n 'Content-Type': 'text/html; charset=UTF-8',\n },\n ...opts.router.state.matches.map((match) => {\n return match.headers\n }),\n )\n\n // Handle Redirects\n const { redirect } = opts.router.state\n\n if (redirect) {\n headers = mergeHeaders(headers, redirect.headers, {\n Location: redirect.href,\n })\n }\n return headers\n}\n"],"names":["eventHandler","toWebRequest","history","createMemoryHistory","attachRouterServerSsrUtils","dehydrateRouter","mergeHeaders","getResponseHeaders"],"mappings":";;;;;;AAaO,SAAS,mBAGd;AAAA,EACA;AAAA,EACA;AACF,GAG8C;AAC5C,SAAO,CAAC,OAAO;AACN,WAAAA,GAAAA,aAAa,OAAO,UAAU;AAC7B,YAAA,UAAUC,gBAAa,KAAK;AAElC,YAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,YAAM,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,EAAE;AAG5C,YAAMC,YAAUC,QAAAA,oBAAoB;AAAA,QAClC,gBAAgB,CAAC,IAAI;AAAA,MAAA,CACtB;AAED,YAAM,SAAS,aAAa;AAEDC,2CAAA,QAAQ,OAAM,yDAAqB;AAG9D,aAAO,OAAO;AAAA,QACZF,SAAAA;AAAAA,MAAA,CACD;AAED,YAAM,OAAO,KAAK;AAElBG,gBAAAA,gBAAgB,MAAM;AAEtB,YAAM,kBAAkB,wBAAwB,EAAE,OAAO,QAAQ;AAC3D,YAAA,WAAW,MAAM,GAAG;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAEM,aAAA;AAAA,IAAA,CACR;AAAA,EACH;AACF;AAEA,SAAS,wBAAwB,MAA6C;AAC5E,MAAI,UAAUC,gBAAA;AAAA,IACZC,GAAA,mBAAmB,KAAK,KAAK;AAAA,IAC5B,KAAK,MAAc;AAAA,IACpB;AAAA,MACE,gBAAgB;AAAA,IAClB;AAAA,IACA,GAAG,KAAK,OAAO,MAAM,QAAQ,IAAI,CAAC,UAAU;AAC1C,aAAO,MAAM;AAAA,IACd,CAAA;AAAA,EACH;AAGA,QAAM,EAAE,SAAA,IAAa,KAAK,OAAO;AAEjC,MAAI,UAAU;AACF,cAAAD,gBAAA,aAAa,SAAS,SAAS,SAAS;AAAA,MAChD,UAAU,SAAS;AAAA,IAAA,CACpB;AAAA,EAAA;AAEI,SAAA;AACT;;"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AnyRouter } from '@tanstack/router-core';
|
|
1
|
+
import { eventHandler, EventHandlerResponse } from 'h3';
|
|
3
2
|
import { HandlerCallback } from './handlerCallback.cjs';
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
}): Headers;
|
|
8
|
-
export declare function createStartHandler<TRouter extends AnyRouter>({ createRouter, }: {
|
|
3
|
+
import { AnyRouter, Manifest } from '@tanstack/router-core';
|
|
4
|
+
export type CustomizeStartHandler<TRouter extends AnyRouter, TResponse extends EventHandlerResponse = EventHandlerResponse> = (cb: HandlerCallback<TRouter, TResponse>) => ReturnType<typeof eventHandler>;
|
|
5
|
+
export declare function createStartHandler<TRouter extends AnyRouter, TResponse extends EventHandlerResponse = EventHandlerResponse>({ createRouter, getRouterManifest, }: {
|
|
9
6
|
createRouter: () => TRouter;
|
|
10
|
-
|
|
7
|
+
getRouterManifest?: () => Manifest | Promise<Manifest>;
|
|
8
|
+
}): CustomizeStartHandler<TRouter, TResponse>;
|
package/dist/cjs/h3.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const node_async_hooks = require("node:async_hooks");
|
|
4
4
|
const h3 = require("h3");
|
|
5
|
-
const
|
|
5
|
+
const unctx = require("unctx");
|
|
6
6
|
function _setContext(event, key, value) {
|
|
7
7
|
event.context[key] = value;
|
|
8
8
|
}
|
|
@@ -12,27 +12,41 @@ function _getContext(event, key) {
|
|
|
12
12
|
function defineMiddleware(options) {
|
|
13
13
|
return options;
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
function toWebRequestH3(event) {
|
|
16
|
+
let readableStream;
|
|
17
|
+
const url = getRequestURL(event);
|
|
18
|
+
const base = {
|
|
19
|
+
// @ts-ignore Undici option
|
|
20
|
+
duplex: "half",
|
|
21
|
+
method: event.method,
|
|
22
|
+
headers: event.headers
|
|
23
|
+
};
|
|
24
|
+
if (event.node.req.body instanceof ArrayBuffer) {
|
|
25
|
+
return new Request(url, {
|
|
26
|
+
...base,
|
|
27
|
+
body: event.node.req.body
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return new Request(url, {
|
|
31
|
+
...base,
|
|
32
|
+
get body() {
|
|
33
|
+
if (readableStream) {
|
|
34
|
+
return readableStream;
|
|
35
|
+
}
|
|
36
|
+
readableStream = getRequestWebStream(event);
|
|
37
|
+
return readableStream;
|
|
38
|
+
}
|
|
18
39
|
});
|
|
19
40
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
41
|
+
function toWebRequest(event) {
|
|
42
|
+
event.web ?? (event.web = {
|
|
43
|
+
request: toWebRequestH3(event),
|
|
44
|
+
url: getRequestURL(event)
|
|
23
45
|
});
|
|
46
|
+
return event.web.request;
|
|
24
47
|
}
|
|
25
|
-
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
function getEvent() {
|
|
29
|
-
const event = eventStorage.getStore();
|
|
30
|
-
if (!event) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
return event;
|
|
48
|
+
function getHTTPEvent() {
|
|
49
|
+
return getEvent();
|
|
36
50
|
}
|
|
37
51
|
const HTTPEventSymbol = Symbol("$HTTPEvent");
|
|
38
52
|
function isEvent(obj) {
|
|
@@ -40,9 +54,15 @@ function isEvent(obj) {
|
|
|
40
54
|
}
|
|
41
55
|
function createWrapperFunction(h3Function) {
|
|
42
56
|
return function(...args) {
|
|
57
|
+
var _a;
|
|
43
58
|
const event = args[0];
|
|
44
59
|
if (!isEvent(event)) {
|
|
45
|
-
|
|
60
|
+
if (!((_a = globalThis.app.config.server.experimental) == null ? void 0 : _a.asyncContext)) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"AsyncLocalStorage was not enabled. Use the `server.experimental.asyncContext: true` option in your app configuration to enable it. Or, pass the instance of HTTPEvent that you have as the first argument to the function."
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
args.unshift(getHTTPEvent());
|
|
46
66
|
} else {
|
|
47
67
|
args[0] = event instanceof h3.H3Event || event.__is_event__ ? event : event[HTTPEventSymbol];
|
|
48
68
|
}
|
|
@@ -129,9 +149,26 @@ const removeResponseHeader = createWrapperFunction(h3.removeResponseHeader);
|
|
|
129
149
|
const getContext = createWrapperFunction(_getContext);
|
|
130
150
|
const setContext = createWrapperFunction(_setContext);
|
|
131
151
|
const clearResponseHeaders = createWrapperFunction(h3.clearResponseHeaders);
|
|
132
|
-
const getWebRequest = createWrapperFunction(
|
|
133
|
-
function
|
|
134
|
-
|
|
152
|
+
const getWebRequest = createWrapperFunction(toWebRequest);
|
|
153
|
+
function getNitroAsyncContext() {
|
|
154
|
+
var _a;
|
|
155
|
+
const nitroAsyncContext = unctx.getContext("nitro-app", {
|
|
156
|
+
asyncContext: ((_a = globalThis.app.config.server.experimental) == null ? void 0 : _a.asyncContext) ? true : false,
|
|
157
|
+
AsyncLocalStorage: node_async_hooks.AsyncLocalStorage
|
|
158
|
+
});
|
|
159
|
+
return nitroAsyncContext;
|
|
160
|
+
}
|
|
161
|
+
function getEvent() {
|
|
162
|
+
const event = getNitroAsyncContext().use().event;
|
|
163
|
+
if (!event) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
return event;
|
|
169
|
+
}
|
|
170
|
+
async function handleHTTPEvent(event) {
|
|
171
|
+
return await globalThis.$handle(event);
|
|
135
172
|
}
|
|
136
173
|
Object.defineProperty(exports, "H3Error", {
|
|
137
174
|
enumerable: true,
|
|
@@ -169,6 +206,14 @@ Object.defineProperty(exports, "createRouter", {
|
|
|
169
206
|
enumerable: true,
|
|
170
207
|
get: () => h3.createRouter
|
|
171
208
|
});
|
|
209
|
+
Object.defineProperty(exports, "createServer", {
|
|
210
|
+
enumerable: true,
|
|
211
|
+
get: () => h3.createApp
|
|
212
|
+
});
|
|
213
|
+
Object.defineProperty(exports, "defineEventHandler", {
|
|
214
|
+
enumerable: true,
|
|
215
|
+
get: () => h3.defineEventHandler
|
|
216
|
+
});
|
|
172
217
|
Object.defineProperty(exports, "defineLazyEventHandler", {
|
|
173
218
|
enumerable: true,
|
|
174
219
|
get: () => h3.defineLazyEventHandler
|
|
@@ -197,6 +242,10 @@ Object.defineProperty(exports, "dynamicEventHandler", {
|
|
|
197
242
|
enumerable: true,
|
|
198
243
|
get: () => h3.dynamicEventHandler
|
|
199
244
|
});
|
|
245
|
+
Object.defineProperty(exports, "eventHandler", {
|
|
246
|
+
enumerable: true,
|
|
247
|
+
get: () => h3.eventHandler
|
|
248
|
+
});
|
|
200
249
|
Object.defineProperty(exports, "fromNodeMiddleware", {
|
|
201
250
|
enumerable: true,
|
|
202
251
|
get: () => h3.fromNodeMiddleware
|
|
@@ -269,10 +318,6 @@ Object.defineProperty(exports, "toWebHandler", {
|
|
|
269
318
|
enumerable: true,
|
|
270
319
|
get: () => h3.toWebHandler
|
|
271
320
|
});
|
|
272
|
-
Object.defineProperty(exports, "toWebRequest", {
|
|
273
|
-
enumerable: true,
|
|
274
|
-
get: () => h3.toWebRequest
|
|
275
|
-
});
|
|
276
321
|
Object.defineProperty(exports, "useBase", {
|
|
277
322
|
enumerable: true,
|
|
278
323
|
get: () => h3.useBase
|
|
@@ -288,10 +333,8 @@ exports.assertMethod = assertMethod;
|
|
|
288
333
|
exports.clearResponseHeaders = clearResponseHeaders;
|
|
289
334
|
exports.clearSession = clearSession;
|
|
290
335
|
exports.defaultContentType = defaultContentType;
|
|
291
|
-
exports.defineEventHandler = defineEventHandler;
|
|
292
336
|
exports.defineMiddleware = defineMiddleware;
|
|
293
337
|
exports.deleteCookie = deleteCookie;
|
|
294
|
-
exports.eventHandler = eventHandler;
|
|
295
338
|
exports.fetchWithEvent = fetchWithEvent;
|
|
296
339
|
exports.getContext = getContext;
|
|
297
340
|
exports.getCookie = getCookie;
|
|
@@ -320,6 +363,7 @@ exports.getValidatedRouterParams = getValidatedRouterParams;
|
|
|
320
363
|
exports.getWebRequest = getWebRequest;
|
|
321
364
|
exports.handleCacheHeaders = handleCacheHeaders;
|
|
322
365
|
exports.handleCors = handleCors;
|
|
366
|
+
exports.handleHTTPEvent = handleHTTPEvent;
|
|
323
367
|
exports.isEvent = isEvent;
|
|
324
368
|
exports.isMethod = isMethod;
|
|
325
369
|
exports.isPreflightRequest = isPreflightRequest;
|
|
@@ -331,8 +375,6 @@ exports.readMultipartFormData = readMultipartFormData;
|
|
|
331
375
|
exports.readRawBody = readRawBody;
|
|
332
376
|
exports.readValidatedBody = readValidatedBody;
|
|
333
377
|
exports.removeResponseHeader = removeResponseHeader;
|
|
334
|
-
exports.requestHandler = requestHandler;
|
|
335
|
-
exports.runWithEvent = runWithEvent;
|
|
336
378
|
exports.sealSession = sealSession;
|
|
337
379
|
exports.send = send;
|
|
338
380
|
exports.sendError = sendError;
|
|
@@ -348,6 +390,7 @@ exports.setHeaders = setHeaders;
|
|
|
348
390
|
exports.setResponseHeader = setResponseHeader;
|
|
349
391
|
exports.setResponseHeaders = setResponseHeaders;
|
|
350
392
|
exports.setResponseStatus = setResponseStatus;
|
|
393
|
+
exports.toWebRequest = toWebRequest;
|
|
351
394
|
exports.unsealSession = unsealSession;
|
|
352
395
|
exports.updateSession = updateSession;
|
|
353
396
|
exports.useSession = useSession;
|