vinext 0.0.37 → 0.0.38

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.
Files changed (86) hide show
  1. package/dist/cache.d.ts +2 -0
  2. package/dist/cache.js +2 -0
  3. package/dist/cli.js +6 -22
  4. package/dist/cli.js.map +1 -1
  5. package/dist/client/empty-module.d.ts +1 -0
  6. package/dist/client/empty-module.js +1 -0
  7. package/dist/client/entry.js +2 -0
  8. package/dist/client/entry.js.map +1 -1
  9. package/dist/client/instrumentation-client-state.d.ts +10 -0
  10. package/dist/client/instrumentation-client-state.js +19 -0
  11. package/dist/client/instrumentation-client-state.js.map +1 -0
  12. package/dist/client/instrumentation-client.d.ts +8 -0
  13. package/dist/client/instrumentation-client.js +8 -0
  14. package/dist/client/instrumentation-client.js.map +1 -0
  15. package/dist/cloudflare/tpr.js +1 -3
  16. package/dist/cloudflare/tpr.js.map +1 -1
  17. package/dist/deploy.js +9 -3
  18. package/dist/deploy.js.map +1 -1
  19. package/dist/entries/app-rsc-entry.js +27 -22
  20. package/dist/entries/app-rsc-entry.js.map +1 -1
  21. package/dist/entries/pages-client-entry.js +2 -0
  22. package/dist/entries/pages-client-entry.js.map +1 -1
  23. package/dist/entries/pages-server-entry.js +41 -260
  24. package/dist/entries/pages-server-entry.js.map +1 -1
  25. package/dist/entries/runtime-entry-module.d.ts +13 -1
  26. package/dist/entries/runtime-entry-module.js +18 -4
  27. package/dist/entries/runtime-entry-module.js.map +1 -1
  28. package/dist/index.d.ts +13 -11
  29. package/dist/index.js +101 -696
  30. package/dist/index.js.map +1 -1
  31. package/dist/plugins/fix-use-server-closure-collision.d.ts +29 -0
  32. package/dist/plugins/fix-use-server-closure-collision.js +204 -0
  33. package/dist/plugins/fix-use-server-closure-collision.js.map +1 -0
  34. package/dist/plugins/fonts.d.ts +39 -0
  35. package/dist/plugins/fonts.js +432 -0
  36. package/dist/plugins/fonts.js.map +1 -0
  37. package/dist/plugins/instrumentation-client.d.ts +7 -0
  38. package/dist/plugins/instrumentation-client.js +29 -0
  39. package/dist/plugins/instrumentation-client.js.map +1 -0
  40. package/dist/plugins/og-assets.d.ts +26 -0
  41. package/dist/plugins/og-assets.js +118 -0
  42. package/dist/plugins/og-assets.js.map +1 -0
  43. package/dist/server/api-handler.js +6 -23
  44. package/dist/server/api-handler.js.map +1 -1
  45. package/dist/server/app-browser-entry.js +4 -0
  46. package/dist/server/app-browser-entry.js.map +1 -1
  47. package/dist/server/dev-server.js +3 -1
  48. package/dist/server/dev-server.js.map +1 -1
  49. package/dist/server/instrumentation.d.ts +5 -1
  50. package/dist/server/instrumentation.js +15 -6
  51. package/dist/server/instrumentation.js.map +1 -1
  52. package/dist/server/middleware.d.ts +2 -0
  53. package/dist/server/middleware.js +14 -7
  54. package/dist/server/middleware.js.map +1 -1
  55. package/dist/server/pages-api-route.d.ts +23 -0
  56. package/dist/server/pages-api-route.js +40 -0
  57. package/dist/server/pages-api-route.js.map +1 -0
  58. package/dist/server/pages-media-type.d.ts +16 -0
  59. package/dist/server/pages-media-type.js +25 -0
  60. package/dist/server/pages-media-type.js.map +1 -0
  61. package/dist/server/pages-node-compat.d.ts +45 -0
  62. package/dist/server/pages-node-compat.js +148 -0
  63. package/dist/server/pages-node-compat.js.map +1 -0
  64. package/dist/server/prod-server.js +1 -0
  65. package/dist/server/prod-server.js.map +1 -1
  66. package/dist/shims/cache-for-request.d.ts +58 -0
  67. package/dist/shims/cache-for-request.js +74 -0
  68. package/dist/shims/cache-for-request.js.map +1 -0
  69. package/dist/shims/dynamic.js +25 -10
  70. package/dist/shims/dynamic.js.map +1 -1
  71. package/dist/shims/headers.js +1 -1
  72. package/dist/shims/image.js +24 -8
  73. package/dist/shims/image.js.map +1 -1
  74. package/dist/shims/layout-segment-context.js +9 -3
  75. package/dist/shims/layout-segment-context.js.map +1 -1
  76. package/dist/shims/link.js +2 -0
  77. package/dist/shims/link.js.map +1 -1
  78. package/dist/shims/navigation.js +2 -0
  79. package/dist/shims/navigation.js.map +1 -1
  80. package/dist/shims/server.d.ts +1 -0
  81. package/dist/shims/server.js +3 -0
  82. package/dist/shims/server.js.map +1 -1
  83. package/dist/shims/unified-request-context.d.ts +2 -0
  84. package/dist/shims/unified-request-context.js +1 -0
  85. package/dist/shims/unified-request-context.js.map +1 -1
  86. package/package.json +8 -4
@@ -0,0 +1,23 @@
1
+ import { Route } from "../routing/pages-router.js";
2
+ import { PagesReqResRequest, PagesReqResResponse, PagesRequestQuery } from "./pages-node-compat.js";
3
+
4
+ //#region src/server/pages-api-route.d.ts
5
+ interface PagesApiRouteModule {
6
+ default?: (req: PagesReqResRequest, res: PagesReqResResponse) => void | Promise<void>;
7
+ }
8
+ interface PagesApiRouteMatch {
9
+ params: PagesRequestQuery;
10
+ route: Pick<Route, "pattern"> & {
11
+ module: PagesApiRouteModule;
12
+ };
13
+ }
14
+ interface HandlePagesApiRouteOptions {
15
+ match: PagesApiRouteMatch | null;
16
+ reportRequestError?: (error: Error, routePattern: string) => void | Promise<void>;
17
+ request: Request;
18
+ url: string;
19
+ }
20
+ declare function handlePagesApiRoute(options: HandlePagesApiRouteOptions): Promise<Response>;
21
+ //#endregion
22
+ export { HandlePagesApiRouteOptions, PagesApiRouteMatch, handlePagesApiRoute };
23
+ //# sourceMappingURL=pages-api-route.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { addQueryParam } from "../utils/query.js";
2
+ import { PagesBodyParseError } from "./pages-media-type.js";
3
+ import { createPagesReqRes, parsePagesApiBody } from "./pages-node-compat.js";
4
+ //#region src/server/pages-api-route.ts
5
+ function buildPagesApiQuery(url, params) {
6
+ const query = { ...params };
7
+ const search = url.split("?")[1];
8
+ if (!search) return query;
9
+ for (const [key, value] of new URLSearchParams(search)) addQueryParam(query, key, value);
10
+ return query;
11
+ }
12
+ async function handlePagesApiRoute(options) {
13
+ if (!options.match) return new Response("404 - API route not found", { status: 404 });
14
+ const { route, params } = options.match;
15
+ const handler = route.module.default;
16
+ if (typeof handler !== "function") return new Response("API route does not export a default function", { status: 500 });
17
+ try {
18
+ const query = buildPagesApiQuery(options.url, params);
19
+ const { req, res, responsePromise } = createPagesReqRes({
20
+ body: await parsePagesApiBody(options.request),
21
+ query,
22
+ request: options.request,
23
+ url: options.url
24
+ });
25
+ await handler(req, res);
26
+ res.end();
27
+ return await responsePromise;
28
+ } catch (error) {
29
+ if (error instanceof PagesBodyParseError) return new Response(error.message, {
30
+ status: error.statusCode,
31
+ statusText: error.message
32
+ });
33
+ options.reportRequestError?.(error instanceof Error ? error : new Error(String(error)), route.pattern);
34
+ return new Response("Internal Server Error", { status: 500 });
35
+ }
36
+ }
37
+ //#endregion
38
+ export { handlePagesApiRoute };
39
+
40
+ //# sourceMappingURL=pages-api-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages-api-route.js","names":["PagesApiBodyParseError"],"sources":["../../src/server/pages-api-route.ts"],"sourcesContent":["import type { Route } from \"../routing/pages-router.js\";\nimport { addQueryParam } from \"../utils/query.js\";\nimport {\n createPagesReqRes,\n parsePagesApiBody,\n type PagesRequestQuery,\n type PagesReqResRequest,\n type PagesReqResResponse,\n PagesApiBodyParseError,\n} from \"./pages-node-compat.js\";\n\ninterface PagesApiRouteModule {\n default?: (req: PagesReqResRequest, res: PagesReqResResponse) => void | Promise<void>;\n}\n\nexport interface PagesApiRouteMatch {\n params: PagesRequestQuery;\n route: Pick<Route, \"pattern\"> & {\n module: PagesApiRouteModule;\n };\n}\n\nexport interface HandlePagesApiRouteOptions {\n match: PagesApiRouteMatch | null;\n reportRequestError?: (error: Error, routePattern: string) => void | Promise<void>;\n request: Request;\n url: string;\n}\n\nfunction buildPagesApiQuery(url: string, params: PagesRequestQuery): PagesRequestQuery {\n const query: PagesRequestQuery = { ...params };\n const search = url.split(\"?\")[1];\n if (!search) {\n return query;\n }\n\n for (const [key, value] of new URLSearchParams(search)) {\n addQueryParam(query, key, value);\n }\n\n return query;\n}\n\nexport async function handlePagesApiRoute(options: HandlePagesApiRouteOptions): Promise<Response> {\n if (!options.match) {\n return new Response(\"404 - API route not found\", { status: 404 });\n }\n\n const { route, params } = options.match;\n const handler = route.module.default;\n if (typeof handler !== \"function\") {\n return new Response(\"API route does not export a default function\", { status: 500 });\n }\n\n try {\n const query = buildPagesApiQuery(options.url, params);\n const body = await parsePagesApiBody(options.request);\n const { req, res, responsePromise } = createPagesReqRes({\n body,\n query,\n request: options.request,\n url: options.url,\n });\n\n await handler(req, res);\n res.end();\n return await responsePromise;\n } catch (error) {\n if (error instanceof PagesApiBodyParseError) {\n return new Response(error.message, {\n status: error.statusCode,\n statusText: error.message,\n });\n }\n\n void options.reportRequestError?.(\n error instanceof Error ? error : new Error(String(error)),\n route.pattern,\n );\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n}\n"],"mappings":";;;;AA6BA,SAAS,mBAAmB,KAAa,QAA8C;CACrF,MAAM,QAA2B,EAAE,GAAG,QAAQ;CAC9C,MAAM,SAAS,IAAI,MAAM,IAAI,CAAC;AAC9B,KAAI,CAAC,OACH,QAAO;AAGT,MAAK,MAAM,CAAC,KAAK,UAAU,IAAI,gBAAgB,OAAO,CACpD,eAAc,OAAO,KAAK,MAAM;AAGlC,QAAO;;AAGT,eAAsB,oBAAoB,SAAwD;AAChG,KAAI,CAAC,QAAQ,MACX,QAAO,IAAI,SAAS,6BAA6B,EAAE,QAAQ,KAAK,CAAC;CAGnE,MAAM,EAAE,OAAO,WAAW,QAAQ;CAClC,MAAM,UAAU,MAAM,OAAO;AAC7B,KAAI,OAAO,YAAY,WACrB,QAAO,IAAI,SAAS,gDAAgD,EAAE,QAAQ,KAAK,CAAC;AAGtF,KAAI;EACF,MAAM,QAAQ,mBAAmB,QAAQ,KAAK,OAAO;EAErD,MAAM,EAAE,KAAK,KAAK,oBAAoB,kBAAkB;GACtD,MAFW,MAAM,kBAAkB,QAAQ,QAAQ;GAGnD;GACA,SAAS,QAAQ;GACjB,KAAK,QAAQ;GACd,CAAC;AAEF,QAAM,QAAQ,KAAK,IAAI;AACvB,MAAI,KAAK;AACT,SAAO,MAAM;UACN,OAAO;AACd,MAAI,iBAAiBA,oBACnB,QAAO,IAAI,SAAS,MAAM,SAAS;GACjC,QAAQ,MAAM;GACd,YAAY,MAAM;GACnB,CAAC;AAGC,UAAQ,qBACX,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC,EACzD,MAAM,QACP;AACD,SAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,KAAK,CAAC"}
@@ -0,0 +1,16 @@
1
+ //#region src/server/pages-media-type.d.ts
2
+ /**
3
+ * Shared media-type helpers and body-parse error for Pages API routes.
4
+ *
5
+ * Used by both api-handler.ts (Pages Router dev/prod with Node.js req/res) and
6
+ * pages-node-compat.ts (Pages Router fetch-based facade for Cloudflare Workers).
7
+ */
8
+ declare class PagesBodyParseError extends Error {
9
+ readonly statusCode: number;
10
+ constructor(message: string, statusCode: number);
11
+ }
12
+ declare function getMediaType(contentType: string | null | undefined): string;
13
+ declare function isJsonMediaType(mediaType: string): boolean;
14
+ //#endregion
15
+ export { PagesBodyParseError, getMediaType, isJsonMediaType };
16
+ //# sourceMappingURL=pages-media-type.d.ts.map
@@ -0,0 +1,25 @@
1
+ //#region src/server/pages-media-type.ts
2
+ /**
3
+ * Shared media-type helpers and body-parse error for Pages API routes.
4
+ *
5
+ * Used by both api-handler.ts (Pages Router dev/prod with Node.js req/res) and
6
+ * pages-node-compat.ts (Pages Router fetch-based facade for Cloudflare Workers).
7
+ */
8
+ var PagesBodyParseError = class extends Error {
9
+ constructor(message, statusCode) {
10
+ super(message);
11
+ this.statusCode = statusCode;
12
+ this.name = "PagesBodyParseError";
13
+ }
14
+ };
15
+ function getMediaType(contentType) {
16
+ const [type] = (contentType ?? "text/plain").split(";");
17
+ return type?.trim().toLowerCase() || "text/plain";
18
+ }
19
+ function isJsonMediaType(mediaType) {
20
+ return mediaType === "application/json" || mediaType === "application/ld+json";
21
+ }
22
+ //#endregion
23
+ export { PagesBodyParseError, getMediaType, isJsonMediaType };
24
+
25
+ //# sourceMappingURL=pages-media-type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages-media-type.js","names":[],"sources":["../../src/server/pages-media-type.ts"],"sourcesContent":["/**\n * Shared media-type helpers and body-parse error for Pages API routes.\n *\n * Used by both api-handler.ts (Pages Router dev/prod with Node.js req/res) and\n * pages-node-compat.ts (Pages Router fetch-based facade for Cloudflare Workers).\n */\n\nexport class PagesBodyParseError extends Error {\n constructor(\n message: string,\n readonly statusCode: number,\n ) {\n super(message);\n this.name = \"PagesBodyParseError\";\n }\n}\n\nexport function getMediaType(contentType: string | null | undefined): string {\n const [type] = (contentType ?? \"text/plain\").split(\";\");\n return type?.trim().toLowerCase() || \"text/plain\";\n}\n\nexport function isJsonMediaType(mediaType: string): boolean {\n return mediaType === \"application/json\" || mediaType === \"application/ld+json\";\n}\n"],"mappings":";;;;;;;AAOA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,YACE,SACA,YACA;AACA,QAAM,QAAQ;AAFL,OAAA,aAAA;AAGT,OAAK,OAAO;;;AAIhB,SAAgB,aAAa,aAAgD;CAC3E,MAAM,CAAC,SAAS,eAAe,cAAc,MAAM,IAAI;AACvD,QAAO,MAAM,MAAM,CAAC,aAAa,IAAI;;AAGvC,SAAgB,gBAAgB,WAA4B;AAC1D,QAAO,cAAc,sBAAsB,cAAc"}
@@ -0,0 +1,45 @@
1
+ import { PagesBodyParseError } from "./pages-media-type.js";
2
+
3
+ //#region src/server/pages-node-compat.d.ts
4
+ declare const MAX_PAGES_API_BODY_SIZE: number;
5
+ type PagesRequestQuery = Record<string, string | string[]>;
6
+ interface PagesReqResRequest {
7
+ method: string;
8
+ url: string;
9
+ headers: Record<string, string>;
10
+ query: PagesRequestQuery;
11
+ body: unknown;
12
+ cookies: Record<string, string>;
13
+ }
14
+ interface PagesReqResHeaders {
15
+ [key: string]: string | number | boolean | string[];
16
+ }
17
+ interface PagesReqResResponse {
18
+ statusCode: number;
19
+ readonly headersSent: boolean;
20
+ writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;
21
+ setHeader: (name: string, value: string | number | boolean | string[]) => PagesReqResResponse;
22
+ getHeader: (name: string) => string | number | boolean | string[] | undefined;
23
+ end: (data?: BodyInit | null) => void;
24
+ status: (code: number) => PagesReqResResponse;
25
+ json: (data: unknown) => void;
26
+ send: (data: unknown) => void;
27
+ redirect: (statusOrUrl: number | string, url?: string) => void;
28
+ getHeaders: () => PagesReqResHeaders;
29
+ }
30
+ interface CreatePagesReqResOptions {
31
+ body: unknown;
32
+ query: PagesRequestQuery;
33
+ request: Request;
34
+ url: string;
35
+ }
36
+ interface CreatePagesReqResResult {
37
+ req: PagesReqResRequest;
38
+ res: PagesReqResResponse;
39
+ responsePromise: Promise<Response>;
40
+ }
41
+ declare function parsePagesApiBody(request: Request, maxBytes?: number): Promise<unknown>;
42
+ declare function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult;
43
+ //#endregion
44
+ export { CreatePagesReqResOptions, CreatePagesReqResResult, MAX_PAGES_API_BODY_SIZE, PagesBodyParseError as PagesApiBodyParseError, PagesReqResHeaders, PagesReqResRequest, PagesReqResResponse, PagesRequestQuery, createPagesReqRes, parsePagesApiBody };
45
+ //# sourceMappingURL=pages-node-compat.d.ts.map
@@ -0,0 +1,148 @@
1
+ import { parseCookies } from "../config/config-matchers.js";
2
+ import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
3
+ import { decode } from "node:querystring";
4
+ //#region src/server/pages-node-compat.ts
5
+ const MAX_PAGES_API_BODY_SIZE = 1 * 1024 * 1024;
6
+ async function readPagesRequestBodyWithLimit(request, maxBytes) {
7
+ if (!request.body) return "";
8
+ const reader = request.body.getReader();
9
+ const decoder = new TextDecoder();
10
+ const chunks = [];
11
+ let totalSize = 0;
12
+ for (;;) {
13
+ const result = await reader.read();
14
+ if (result.done) break;
15
+ totalSize += result.value.byteLength;
16
+ if (totalSize > maxBytes) {
17
+ await reader.cancel();
18
+ throw new PagesBodyParseError("Request body too large", 413);
19
+ }
20
+ chunks.push(decoder.decode(result.value, { stream: true }));
21
+ }
22
+ chunks.push(decoder.decode());
23
+ return chunks.join("");
24
+ }
25
+ async function parsePagesApiBody(request, maxBytes = MAX_PAGES_API_BODY_SIZE) {
26
+ if (Number.parseInt(request.headers.get("content-length") || "0", 10) > maxBytes) throw new PagesBodyParseError("Request body too large", 413);
27
+ let rawBody = "";
28
+ try {
29
+ rawBody = await readPagesRequestBodyWithLimit(request, maxBytes);
30
+ } catch (err) {
31
+ if (err instanceof PagesBodyParseError) throw err;
32
+ throw new PagesBodyParseError("Request body too large", 413);
33
+ }
34
+ const mediaType = getMediaType(request.headers.get("content-type"));
35
+ if (!rawBody) return isJsonMediaType(mediaType) ? {} : mediaType === "application/x-www-form-urlencoded" ? decode(rawBody) : void 0;
36
+ if (isJsonMediaType(mediaType)) try {
37
+ return JSON.parse(rawBody);
38
+ } catch {
39
+ throw new PagesBodyParseError("Invalid JSON", 400);
40
+ }
41
+ if (mediaType === "application/x-www-form-urlencoded") return decode(rawBody);
42
+ return rawBody;
43
+ }
44
+ function createPagesReqRes(options) {
45
+ const headersObj = {};
46
+ for (const [key, value] of options.request.headers) headersObj[key.toLowerCase()] = value;
47
+ const req = {
48
+ method: options.request.method,
49
+ url: options.url,
50
+ headers: headersObj,
51
+ query: options.query,
52
+ body: options.body,
53
+ cookies: parseCookies(options.request.headers.get("cookie"))
54
+ };
55
+ let resStatusCode = 200;
56
+ const resHeaders = {};
57
+ const setCookieHeaders = [];
58
+ let resBody = null;
59
+ let ended = false;
60
+ let resolveResponse;
61
+ const responsePromise = new Promise((resolve) => {
62
+ resolveResponse = resolve;
63
+ });
64
+ const res = {
65
+ get statusCode() {
66
+ return resStatusCode;
67
+ },
68
+ set statusCode(code) {
69
+ resStatusCode = code;
70
+ },
71
+ get headersSent() {
72
+ return ended;
73
+ },
74
+ writeHead(code, headers) {
75
+ resStatusCode = code;
76
+ if (headers) for (const [key, value] of Object.entries(headers)) if (key.toLowerCase() === "set-cookie") if (Array.isArray(value)) setCookieHeaders.push(...value.map(String));
77
+ else setCookieHeaders.push(String(value));
78
+ else resHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
79
+ return res;
80
+ },
81
+ setHeader(name, value) {
82
+ if (name.toLowerCase() === "set-cookie") {
83
+ setCookieHeaders.length = 0;
84
+ if (Array.isArray(value)) setCookieHeaders.push(...value.map(String));
85
+ else setCookieHeaders.push(String(value));
86
+ } else resHeaders[name.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
87
+ return res;
88
+ },
89
+ getHeader(name) {
90
+ if (name.toLowerCase() === "set-cookie") return setCookieHeaders.length > 0 ? setCookieHeaders : void 0;
91
+ return resHeaders[name.toLowerCase()];
92
+ },
93
+ end(data) {
94
+ if (ended) return;
95
+ ended = true;
96
+ if (data !== void 0 && data !== null) resBody = data;
97
+ const headers = new Headers();
98
+ for (const [key, value] of Object.entries(resHeaders)) headers.set(key, String(value));
99
+ for (const cookie of setCookieHeaders) headers.append("set-cookie", cookie);
100
+ resolveResponse(new Response(resBody, {
101
+ status: resStatusCode,
102
+ headers
103
+ }));
104
+ },
105
+ status(code) {
106
+ resStatusCode = code;
107
+ return res;
108
+ },
109
+ json(data) {
110
+ resHeaders["content-type"] = "application/json";
111
+ res.end(JSON.stringify(data));
112
+ },
113
+ send(data) {
114
+ if (Buffer.isBuffer(data)) {
115
+ if (!resHeaders["content-type"]) resHeaders["content-type"] = "application/octet-stream";
116
+ resHeaders["content-length"] = String(data.length);
117
+ res.end(new Uint8Array(data));
118
+ return;
119
+ }
120
+ if (typeof data === "object" && data !== null) {
121
+ resHeaders["content-type"] = "application/json";
122
+ res.end(JSON.stringify(data));
123
+ return;
124
+ }
125
+ if (!resHeaders["content-type"]) resHeaders["content-type"] = "text/plain";
126
+ res.end(String(data));
127
+ },
128
+ redirect(statusOrUrl, url) {
129
+ if (typeof statusOrUrl === "string") res.writeHead(307, { Location: statusOrUrl });
130
+ else res.writeHead(statusOrUrl, { Location: url ?? "" });
131
+ res.end();
132
+ },
133
+ getHeaders() {
134
+ const headers = { ...resHeaders };
135
+ if (setCookieHeaders.length > 0) headers["set-cookie"] = setCookieHeaders;
136
+ return headers;
137
+ }
138
+ };
139
+ return {
140
+ req,
141
+ res,
142
+ responsePromise
143
+ };
144
+ }
145
+ //#endregion
146
+ export { MAX_PAGES_API_BODY_SIZE, PagesBodyParseError as PagesApiBodyParseError, createPagesReqRes, parsePagesApiBody };
147
+
148
+ //# sourceMappingURL=pages-node-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages-node-compat.js","names":["decodeQueryString"],"sources":["../../src/server/pages-node-compat.ts"],"sourcesContent":["import { decode as decodeQueryString } from \"node:querystring\";\nimport { parseCookies } from \"../config/config-matchers.js\";\nimport { PagesBodyParseError, getMediaType, isJsonMediaType } from \"./pages-media-type.js\";\n\nexport const MAX_PAGES_API_BODY_SIZE = 1 * 1024 * 1024;\n\n/**\n * @deprecated Use PagesBodyParseError from pages-media-type.ts instead.\n * Kept for backwards compatibility.\n */\nexport { PagesBodyParseError as PagesApiBodyParseError };\n\nexport type PagesRequestQuery = Record<string, string | string[]>;\n\nexport interface PagesReqResRequest {\n method: string;\n url: string;\n headers: Record<string, string>;\n query: PagesRequestQuery;\n body: unknown;\n cookies: Record<string, string>;\n}\n\nexport interface PagesReqResHeaders {\n [key: string]: string | number | boolean | string[];\n}\n\nexport interface PagesReqResResponse {\n statusCode: number;\n readonly headersSent: boolean;\n writeHead: (code: number, headers?: PagesReqResHeaders) => PagesReqResResponse;\n setHeader: (name: string, value: string | number | boolean | string[]) => PagesReqResResponse;\n getHeader: (name: string) => string | number | boolean | string[] | undefined;\n end: (data?: BodyInit | null) => void;\n status: (code: number) => PagesReqResResponse;\n json: (data: unknown) => void;\n send: (data: unknown) => void;\n redirect: (statusOrUrl: number | string, url?: string) => void;\n getHeaders: () => PagesReqResHeaders;\n}\n\nexport interface CreatePagesReqResOptions {\n body: unknown;\n query: PagesRequestQuery;\n request: Request;\n url: string;\n}\n\nexport interface CreatePagesReqResResult {\n req: PagesReqResRequest;\n res: PagesReqResResponse;\n responsePromise: Promise<Response>;\n}\n\nasync function readPagesRequestBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) {\n return \"\";\n }\n\n const reader = request.body.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\n let totalSize = 0;\n\n for (;;) {\n const result = await reader.read();\n if (result.done) {\n break;\n }\n\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n await reader.cancel();\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n chunks.push(decoder.decode(result.value, { stream: true }));\n }\n\n chunks.push(decoder.decode());\n return chunks.join(\"\");\n}\n\nexport async function parsePagesApiBody(\n request: Request,\n maxBytes = MAX_PAGES_API_BODY_SIZE,\n): Promise<unknown> {\n const contentLength = Number.parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > maxBytes) {\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n let rawBody = \"\";\n try {\n rawBody = await readPagesRequestBodyWithLimit(request, maxBytes);\n } catch (err) {\n if (err instanceof PagesBodyParseError) {\n throw err;\n }\n throw new PagesBodyParseError(\"Request body too large\", 413);\n }\n\n const mediaType = getMediaType(request.headers.get(\"content-type\"));\n if (!rawBody) {\n return isJsonMediaType(mediaType)\n ? {}\n : mediaType === \"application/x-www-form-urlencoded\"\n ? decodeQueryString(rawBody)\n : undefined;\n }\n\n if (isJsonMediaType(mediaType)) {\n try {\n return JSON.parse(rawBody);\n } catch {\n throw new PagesBodyParseError(\"Invalid JSON\", 400);\n }\n }\n\n if (mediaType === \"application/x-www-form-urlencoded\") {\n return decodeQueryString(rawBody);\n }\n\n return rawBody;\n}\n\nexport function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult {\n const headersObj: Record<string, string> = {};\n for (const [key, value] of options.request.headers) {\n headersObj[key.toLowerCase()] = value;\n }\n\n const req: PagesReqResRequest = {\n method: options.request.method,\n url: options.url,\n headers: headersObj,\n query: options.query,\n body: options.body,\n cookies: parseCookies(options.request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders: Record<string, string | number | boolean> = {};\n const setCookieHeaders: string[] = [];\n let resBody: BodyInit | null = null;\n let ended = false;\n let resolveResponse!: (value: Response) => void;\n const responsePromise = new Promise<Response>((resolve) => {\n resolveResponse = resolve;\n });\n\n const res: PagesReqResResponse = {\n get statusCode() {\n return resStatusCode;\n },\n set statusCode(code) {\n resStatusCode = code;\n },\n get headersSent() {\n return ended;\n },\n writeHead(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[key.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n }\n }\n return res;\n },\n setHeader(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n // Node.js res.setHeader() replaces the existing value entirely.\n setCookieHeaders.length = 0;\n if (Array.isArray(value)) {\n setCookieHeaders.push(...value.map(String));\n } else {\n setCookieHeaders.push(String(value));\n }\n } else {\n resHeaders[name.toLowerCase()] = Array.isArray(value) ? value.join(\", \") : value;\n }\n return res;\n },\n getHeader(name) {\n if (name.toLowerCase() === \"set-cookie\") {\n return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n }\n return resHeaders[name.toLowerCase()];\n },\n end(data) {\n if (ended) {\n return;\n }\n ended = true;\n if (data !== undefined && data !== null) {\n resBody = data;\n }\n const headers = new Headers();\n for (const [key, value] of Object.entries(resHeaders)) {\n headers.set(key, String(value));\n }\n for (const cookie of setCookieHeaders) {\n headers.append(\"set-cookie\", cookie);\n }\n resolveResponse(new Response(resBody, { status: resStatusCode, headers }));\n },\n status(code) {\n resStatusCode = code;\n return res;\n },\n json(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send(data) {\n if (Buffer.isBuffer(data)) {\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"application/octet-stream\";\n }\n resHeaders[\"content-length\"] = String(data.length);\n res.end(new Uint8Array(data));\n return;\n }\n\n if (typeof data === \"object\" && data !== null) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n return;\n }\n\n if (!resHeaders[\"content-type\"]) {\n resHeaders[\"content-type\"] = \"text/plain\";\n }\n res.end(String(data));\n },\n redirect(statusOrUrl, url) {\n if (typeof statusOrUrl === \"string\") {\n res.writeHead(307, { Location: statusOrUrl });\n } else {\n res.writeHead(statusOrUrl, { Location: url ?? \"\" });\n }\n res.end();\n },\n getHeaders() {\n const headers: PagesReqResHeaders = { ...resHeaders };\n if (setCookieHeaders.length > 0) {\n headers[\"set-cookie\"] = setCookieHeaders;\n }\n return headers;\n },\n };\n\n return { req, res, responsePromise };\n}\n"],"mappings":"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"}
@@ -715,6 +715,7 @@ async function startPagesRouterServer(options) {
715
715
  let middlewareRewriteStatus;
716
716
  if (typeof runMiddleware === "function") {
717
717
  const result = await runMiddleware(webRequest, void 0);
718
+ if (result.waitUntilPromises && result.waitUntilPromises.length > 0) Promise.allSettled(result.waitUntilPromises);
718
719
  if (!result.continue) {
719
720
  if (result.redirectUrl) {
720
721
  const redirectHeaders = { Location: result.redirectUrl };