@torpor/adapter-node 0.0.8 → 0.0.10
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/CHANGELOG.md +13 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +11 -6
- package/src/adapter.ts +1 -1
- package/src/constants.ts +1 -1
- package/src/createFetchHandler.ts +1 -1
- package/src/createNodeServer.ts +4 -1
- package/src/flattenHeaders.ts +44 -0
- package/src/nodeMessageToRequest.ts +1 -1
- package/src/responseToNodeResponse.ts +1 -1
- package/tsup.config.ts +7 -2
- package/vitest.config.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @torpor/adapter-node
|
|
2
2
|
|
|
3
|
+
## 0.0.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3ed8a23: Chore: specify exports in packages
|
|
8
|
+
|
|
9
|
+
## 0.0.9
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [8de094b]
|
|
14
|
+
- @torpor/build@0.1.12
|
|
15
|
+
|
|
3
16
|
## 0.0.8
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,7 @@ var INTERNAL_BODY = Symbol("internal_body");
|
|
|
33
33
|
// src/nodeMessageToRequest.ts
|
|
34
34
|
var import_node_stream = require("stream");
|
|
35
35
|
|
|
36
|
-
//
|
|
36
|
+
// src/flattenHeaders.ts
|
|
37
37
|
function flattenHeaders(headers) {
|
|
38
38
|
const flatHeaders = new Headers();
|
|
39
39
|
for (const [key, value] of Object.entries(headers)) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/createNodeServer.ts","../src/constants.ts","../src/nodeMessageToRequest.ts","
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/createNodeServer.ts","../src/constants.ts","../src/nodeMessageToRequest.ts","../src/flattenHeaders.ts","../src/responseToNodeResponse.ts","../src/createFetchHandler.ts","../src/adapter.ts"],"sourcesContent":["import node from \"./adapter\";\n\nexport { node };\n","import { IncomingMessage, Server, ServerResponse } from \"http\";\nimport { createServer } from \"node:http\";\nimport { createFetchHandler } from \"./createFetchHandler\";\n\nexport default function createNodeServer(\n\thandler: (req: Request) => Response | Promise<Response>,\n): Server<typeof IncomingMessage, typeof ServerResponse> {\n\t// Create a server, polyfill it so that it can handle standard fetch methods,\n\t// and pass our app fetch method to the handler\n\treturn createServer(createFetchHandler(handler));\n}\n","export const INTERNAL_BODY: unique symbol = Symbol(\"internal_body\");\n","import { type IncomingMessage } from \"node:http\";\nimport { Http2ServerRequest } from \"node:http2\";\nimport { Readable } from \"node:stream\";\nimport flattenHeaders from \"./flattenHeaders\";\n\n// From https://stackoverflow.com/a/78849544\n// and https://gist.github.com/marvinhagemeister/cc236ec97235ce0305ae9d48a24a607d\n\nexport default async function nodeMessageToRequest(\n\treq: IncomingMessage | Http2ServerRequest,\n): Promise<Request> {\n\t// Build the full url\n\tlet path = req.url;\n\tif (path === undefined) {\n\t\tthrow new Error(`Empty request URL`);\n\t}\n\tif (!path.startsWith(\"/\")) {\n\t\tpath = \"/\" + path;\n\t}\n\tconst { host } = req.headers;\n\tif (host == undefined) {\n\t\tthrow new Error(`Missing \"Host\" header`);\n\t}\n\tconst protocol = \"encrypted\" in req.socket && req.socket.encrypted ? \"https\" : \"http\";\n\tconst url = `${protocol}://${host}${path}`;\n\n\t// Flatten the headers\n\tconst headers = flattenHeaders(req.headers);\n\n\t// Convert body to Buffer if applicable\n\tconst body =\n\t\treq.method !== \"GET\" && req.method !== \"HEAD\"\n\t\t\t? (Readable.toWeb(req) as ReadableStream) // await readableToBuffer(req)\n\t\t\t: null;\n\n\treturn new Request(url, {\n\t\tmethod: req.method,\n\t\theaders: headers,\n\t\tbody: body,\n\t\t// @ts-ignore this is needed for using a Readable for some reason\n\t\tduplex: \"half\",\n\t});\n}\n","import { IncomingHttpHeaders } from \"node:http\";\nimport { OutgoingHttpHeaders } from \"node:http2\";\n\nexport default function flattenHeaders(\n\theaders: IncomingHttpHeaders | OutgoingHttpHeaders,\n): HeadersInit {\n\tconst flatHeaders = new Headers();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t} else if (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v !== undefined && v !== null) {\n\t\t\t\t\tvalue.forEach((v) => flatHeaders.append(key, v));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.set(key, String(value));\n\t\t}\n\t}\n\treturn flatHeaders;\n\n\t/*\n const flatHeaders: [string, string][] = [];\n\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v != null) {\n\t\t\t\t\tflatHeaders.push([key, String(v)]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.push([key, String(value)]);\n\t\t}\n\t}\n\n\treturn flatHeaders;\n */\n}\n","import { ServerResponse } from \"node:http\";\nimport { Http2ServerResponse } from \"node:http2\";\nimport { isArrayBufferView } from \"node:util/types\";\nimport { INTERNAL_BODY } from \"./constants\";\n\nexport default async function responseToNodeResponse(\n\tres: Response,\n\toutgoing: ServerResponse | Http2ServerResponse,\n): Promise<void> {\n\toutgoing.statusCode = res.status;\n\toutgoing.statusMessage = res.statusText;\n\n\tres.headers.forEach((value, key) => {\n\t\toutgoing.setHeader(key, value);\n\t});\n\n\tconst body = (res as any)[INTERNAL_BODY];\n\n\tif (body === null || body === undefined) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end();\n\t} else if (typeof body === \"string\" || body instanceof Uint8Array) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(body);\n\t} else if (body instanceof Blob) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(new Uint8Array(await body.arrayBuffer()));\n\t} else if (body instanceof ArrayBuffer) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(new Uint8Array(body));\n\t} else if (isArrayBufferView(body)) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(new Uint8Array(body.buffer));\n\t} else if (body instanceof FormData) {\n\t\t// TODO\n\t\toutgoing.setHeader(\"Content-Type\", \"application/x-www-form-urlencoded;charset=UTF-8\");\n\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end();\n\t} else {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end();\n\t}\n}\n","import { type IncomingMessage, ServerResponse } from \"node:http\";\nimport { Http2ServerRequest, Http2ServerResponse } from \"node:http2\";\nimport { INTERNAL_BODY } from \"./constants\";\nimport nodeMessageToRequest from \"./nodeMessageToRequest\";\nimport responseToNodeResponse from \"./responseToNodeResponse\";\n\n// From https://gist.github.com/marvinhagemeister/cc236ec97235ce0305ae9d48a24a607d\n// Referenced from https://marvinh.dev/blog/modern-way-to-write-javascript-servers/\n\nconst GlobalResponse = Response;\nglobalThis.Response = class Response extends GlobalResponse {\n\t[INTERNAL_BODY]: BodyInit | null | undefined = null;\n\n\tconstructor(body?: BodyInit | null, init?: ResponseInit) {\n\t\tsuper(body, init);\n\t\tthis[INTERNAL_BODY] = body;\n\t}\n};\n\nexport function createFetchHandler(handler: (req: Request) => Response | Promise<Response>) {\n\treturn async (\n\t\tincoming: IncomingMessage | Http2ServerRequest,\n\t\toutgoing: ServerResponse | Http2ServerResponse,\n\t): Promise<void> => {\n\t\tconst req = await nodeMessageToRequest(incoming);\n\t\tconst res = await handler(req);\n\t\treturn await responseToNodeResponse(res, outgoing);\n\t};\n}\n","import { type Adapter } from \"@torpor/build\";\nimport { Server } from \"@torpor/build/server\";\nimport createNodeServer from \"./createNodeServer\";\n\nexport default {\n\tserve: (server: Server) => {\n\t\tprocess.env.PROTOCOL ??= \"http:\";\n\t\tprocess.env.HOST ??= \"localhost\";\n\t\tprocess.env.PORT ??= \"7059\";\n\n\t\t// Create the Node server and start listening\n\t\tconst url = `${process.env.PROTOCOL}//${process.env.HOST}:${process.env.PORT}`;\n\t\tconsole.log(`\\nConnecting to ${url}`);\n\t\tconst devServer = createNodeServer(server.fetch);\n\t\tdevServer.listen(parseInt(process.env.PORT), process.env.HOST, () => {\n\t\t\tconsole.log(`Listening on ${url}\\n`);\n\t\t});\n\t},\n} satisfies Adapter as Adapter;\n"],"mappings":"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","names":["v","Response"]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var INTERNAL_BODY = Symbol("internal_body");
|
|
|
7
7
|
// src/nodeMessageToRequest.ts
|
|
8
8
|
import { Readable } from "node:stream";
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// src/flattenHeaders.ts
|
|
11
11
|
function flattenHeaders(headers) {
|
|
12
12
|
const flatHeaders = new Headers();
|
|
13
13
|
for (const [key, value] of Object.entries(headers)) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createNodeServer.ts","../src/constants.ts","../src/nodeMessageToRequest.ts","
|
|
1
|
+
{"version":3,"sources":["../src/createNodeServer.ts","../src/constants.ts","../src/nodeMessageToRequest.ts","../src/flattenHeaders.ts","../src/responseToNodeResponse.ts","../src/createFetchHandler.ts","../src/adapter.ts"],"sourcesContent":["import { IncomingMessage, Server, ServerResponse } from \"http\";\nimport { createServer } from \"node:http\";\nimport { createFetchHandler } from \"./createFetchHandler\";\n\nexport default function createNodeServer(\n\thandler: (req: Request) => Response | Promise<Response>,\n): Server<typeof IncomingMessage, typeof ServerResponse> {\n\t// Create a server, polyfill it so that it can handle standard fetch methods,\n\t// and pass our app fetch method to the handler\n\treturn createServer(createFetchHandler(handler));\n}\n","export const INTERNAL_BODY: unique symbol = Symbol(\"internal_body\");\n","import { type IncomingMessage } from \"node:http\";\nimport { Http2ServerRequest } from \"node:http2\";\nimport { Readable } from \"node:stream\";\nimport flattenHeaders from \"./flattenHeaders\";\n\n// From https://stackoverflow.com/a/78849544\n// and https://gist.github.com/marvinhagemeister/cc236ec97235ce0305ae9d48a24a607d\n\nexport default async function nodeMessageToRequest(\n\treq: IncomingMessage | Http2ServerRequest,\n): Promise<Request> {\n\t// Build the full url\n\tlet path = req.url;\n\tif (path === undefined) {\n\t\tthrow new Error(`Empty request URL`);\n\t}\n\tif (!path.startsWith(\"/\")) {\n\t\tpath = \"/\" + path;\n\t}\n\tconst { host } = req.headers;\n\tif (host == undefined) {\n\t\tthrow new Error(`Missing \"Host\" header`);\n\t}\n\tconst protocol = \"encrypted\" in req.socket && req.socket.encrypted ? \"https\" : \"http\";\n\tconst url = `${protocol}://${host}${path}`;\n\n\t// Flatten the headers\n\tconst headers = flattenHeaders(req.headers);\n\n\t// Convert body to Buffer if applicable\n\tconst body =\n\t\treq.method !== \"GET\" && req.method !== \"HEAD\"\n\t\t\t? (Readable.toWeb(req) as ReadableStream) // await readableToBuffer(req)\n\t\t\t: null;\n\n\treturn new Request(url, {\n\t\tmethod: req.method,\n\t\theaders: headers,\n\t\tbody: body,\n\t\t// @ts-ignore this is needed for using a Readable for some reason\n\t\tduplex: \"half\",\n\t});\n}\n","import { IncomingHttpHeaders } from \"node:http\";\nimport { OutgoingHttpHeaders } from \"node:http2\";\n\nexport default function flattenHeaders(\n\theaders: IncomingHttpHeaders | OutgoingHttpHeaders,\n): HeadersInit {\n\tconst flatHeaders = new Headers();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t} else if (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v !== undefined && v !== null) {\n\t\t\t\t\tvalue.forEach((v) => flatHeaders.append(key, v));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.set(key, String(value));\n\t\t}\n\t}\n\treturn flatHeaders;\n\n\t/*\n const flatHeaders: [string, string][] = [];\n\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v != null) {\n\t\t\t\t\tflatHeaders.push([key, String(v)]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.push([key, String(value)]);\n\t\t}\n\t}\n\n\treturn flatHeaders;\n */\n}\n","import { ServerResponse } from \"node:http\";\nimport { Http2ServerResponse } from \"node:http2\";\nimport { isArrayBufferView } from \"node:util/types\";\nimport { INTERNAL_BODY } from \"./constants\";\n\nexport default async function responseToNodeResponse(\n\tres: Response,\n\toutgoing: ServerResponse | Http2ServerResponse,\n): Promise<void> {\n\toutgoing.statusCode = res.status;\n\toutgoing.statusMessage = res.statusText;\n\n\tres.headers.forEach((value, key) => {\n\t\toutgoing.setHeader(key, value);\n\t});\n\n\tconst body = (res as any)[INTERNAL_BODY];\n\n\tif (body === null || body === undefined) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end();\n\t} else if (typeof body === \"string\" || body instanceof Uint8Array) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(body);\n\t} else if (body instanceof Blob) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(new Uint8Array(await body.arrayBuffer()));\n\t} else if (body instanceof ArrayBuffer) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(new Uint8Array(body));\n\t} else if (isArrayBufferView(body)) {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end(new Uint8Array(body.buffer));\n\t} else if (body instanceof FormData) {\n\t\t// TODO\n\t\toutgoing.setHeader(\"Content-Type\", \"application/x-www-form-urlencoded;charset=UTF-8\");\n\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end();\n\t} else {\n\t\toutgoing.writeHead(res.status, res.statusText);\n\t\toutgoing.end();\n\t}\n}\n","import { type IncomingMessage, ServerResponse } from \"node:http\";\nimport { Http2ServerRequest, Http2ServerResponse } from \"node:http2\";\nimport { INTERNAL_BODY } from \"./constants\";\nimport nodeMessageToRequest from \"./nodeMessageToRequest\";\nimport responseToNodeResponse from \"./responseToNodeResponse\";\n\n// From https://gist.github.com/marvinhagemeister/cc236ec97235ce0305ae9d48a24a607d\n// Referenced from https://marvinh.dev/blog/modern-way-to-write-javascript-servers/\n\nconst GlobalResponse = Response;\nglobalThis.Response = class Response extends GlobalResponse {\n\t[INTERNAL_BODY]: BodyInit | null | undefined = null;\n\n\tconstructor(body?: BodyInit | null, init?: ResponseInit) {\n\t\tsuper(body, init);\n\t\tthis[INTERNAL_BODY] = body;\n\t}\n};\n\nexport function createFetchHandler(handler: (req: Request) => Response | Promise<Response>) {\n\treturn async (\n\t\tincoming: IncomingMessage | Http2ServerRequest,\n\t\toutgoing: ServerResponse | Http2ServerResponse,\n\t): Promise<void> => {\n\t\tconst req = await nodeMessageToRequest(incoming);\n\t\tconst res = await handler(req);\n\t\treturn await responseToNodeResponse(res, outgoing);\n\t};\n}\n","import { type Adapter } from \"@torpor/build\";\nimport { Server } from \"@torpor/build/server\";\nimport createNodeServer from \"./createNodeServer\";\n\nexport default {\n\tserve: (server: Server) => {\n\t\tprocess.env.PROTOCOL ??= \"http:\";\n\t\tprocess.env.HOST ??= \"localhost\";\n\t\tprocess.env.PORT ??= \"7059\";\n\n\t\t// Create the Node server and start listening\n\t\tconst url = `${process.env.PROTOCOL}//${process.env.HOST}:${process.env.PORT}`;\n\t\tconsole.log(`\\nConnecting to ${url}`);\n\t\tconst devServer = createNodeServer(server.fetch);\n\t\tdevServer.listen(parseInt(process.env.PORT), process.env.HOST, () => {\n\t\t\tconsole.log(`Listening on ${url}\\n`);\n\t\t});\n\t},\n} satisfies Adapter as Adapter;\n"],"mappings":"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","names":["v","Response"]}
|
package/dist/metafile-cjs.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/constants.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/constants.ts":{"bytes":69,"imports":[],"format":"esm"},"src/flattenHeaders.ts":{"bytes":1017,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true}],"format":"esm"},"src/nodeMessageToRequest.ts":{"bytes":1277,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true},{"path":"stream","kind":"import-statement","external":true},{"path":"src/flattenHeaders.ts","kind":"import-statement","original":"./flattenHeaders"}],"format":"esm"},"src/responseToNodeResponse.ts":{"bytes":1486,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true},{"path":"util/types","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"}],"format":"esm"},"src/createFetchHandler.ts":{"bytes":1119,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"src/nodeMessageToRequest.ts","kind":"import-statement","original":"./nodeMessageToRequest"},{"path":"src/responseToNodeResponse.ts","kind":"import-statement","original":"./responseToNodeResponse"}],"format":"esm"},"src/createNodeServer.ts":{"bytes":506,"imports":[{"path":"http","kind":"import-statement","external":true},{"path":"http","kind":"import-statement","external":true},{"path":"src/createFetchHandler.ts","kind":"import-statement","original":"./createFetchHandler"}],"format":"esm"},"src/adapter.ts":{"bytes":675,"imports":[{"path":"@torpor/build","kind":"import-statement","external":true},{"path":"@torpor/build/server","kind":"import-statement","external":true},{"path":"src/createNodeServer.ts","kind":"import-statement","original":"./createNodeServer"}],"format":"esm"},"src/index.ts":{"bytes":48,"imports":[{"path":"src/adapter.ts","kind":"import-statement","original":"./adapter"}],"format":"esm"}},"outputs":{"dist/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":9758},"dist/index.cjs":{"imports":[{"path":"http","kind":"require-call","external":true},{"path":"stream","kind":"require-call","external":true},{"path":"util/types","kind":"require-call","external":true}],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":130},"src/createNodeServer.ts":{"bytesInOutput":153},"src/constants.ts":{"bytesInOutput":45},"src/nodeMessageToRequest.ts":{"bytesInOutput":808},"src/flattenHeaders.ts":{"bytesInOutput":472},"src/responseToNodeResponse.ts":{"bytesInOutput":1289},"src/createFetchHandler.ts":{"bytesInOutput":443},"src/adapter.ts":{"bytesInOutput":469}},"bytes":4973}}}
|
package/dist/metafile-esm.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"src/constants.ts":{"bytes":
|
|
1
|
+
{"inputs":{"src/constants.ts":{"bytes":69,"imports":[],"format":"esm"},"src/flattenHeaders.ts":{"bytes":1017,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true}],"format":"esm"},"src/nodeMessageToRequest.ts":{"bytes":1277,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true},{"path":"node:stream","kind":"import-statement","external":true},{"path":"src/flattenHeaders.ts","kind":"import-statement","original":"./flattenHeaders"}],"format":"esm"},"src/responseToNodeResponse.ts":{"bytes":1486,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true},{"path":"node:util/types","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"}],"format":"esm"},"src/createFetchHandler.ts":{"bytes":1119,"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:http2","kind":"import-statement","external":true},{"path":"src/constants.ts","kind":"import-statement","original":"./constants"},{"path":"src/nodeMessageToRequest.ts","kind":"import-statement","original":"./nodeMessageToRequest"},{"path":"src/responseToNodeResponse.ts","kind":"import-statement","original":"./responseToNodeResponse"}],"format":"esm"},"src/createNodeServer.ts":{"bytes":506,"imports":[{"path":"http","kind":"import-statement","external":true},{"path":"node:http","kind":"import-statement","external":true},{"path":"src/createFetchHandler.ts","kind":"import-statement","original":"./createFetchHandler"}],"format":"esm"},"src/adapter.ts":{"bytes":675,"imports":[{"path":"@torpor/build","kind":"import-statement","external":true},{"path":"@torpor/build/server","kind":"import-statement","external":true},{"path":"src/createNodeServer.ts","kind":"import-statement","original":"./createNodeServer"}],"format":"esm"},"src/index.ts":{"bytes":48,"imports":[{"path":"src/adapter.ts","kind":"import-statement","original":"./adapter"}],"format":"esm"}},"outputs":{"dist/index.js.map":{"imports":[],"exports":[],"inputs":{},"bytes":9649},"dist/index.js":{"imports":[{"path":"node:http","kind":"import-statement","external":true},{"path":"node:stream","kind":"import-statement","external":true},{"path":"node:util/types","kind":"import-statement","external":true}],"exports":["node"],"entryPoint":"src/index.ts","inputs":{"src/createNodeServer.ts":{"bytesInOutput":133},"src/constants.ts":{"bytesInOutput":45},"src/nodeMessageToRequest.ts":{"bytesInOutput":785},"src/flattenHeaders.ts":{"bytesInOutput":472},"src/responseToNodeResponse.ts":{"bytesInOutput":1282},"src/createFetchHandler.ts":{"bytesInOutput":443},"src/adapter.ts":{"bytesInOutput":469},"src/index.ts":{"bytesInOutput":0}},"bytes":3916}}}
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@torpor/adapter-node",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "A @torpor/build adapter for running on Node",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
},
|
|
9
14
|
"publishConfig": {
|
|
10
15
|
"access": "public"
|
|
11
16
|
},
|
|
@@ -13,18 +18,18 @@
|
|
|
13
18
|
"author": "",
|
|
14
19
|
"license": "ISC",
|
|
15
20
|
"dependencies": {
|
|
16
|
-
"vite": "^6.
|
|
17
|
-
"@torpor/build": "^0.1.
|
|
21
|
+
"vite": "^6.3.3",
|
|
22
|
+
"@torpor/build": "^0.1.12"
|
|
18
23
|
},
|
|
19
24
|
"devDependencies": {
|
|
20
25
|
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
21
26
|
"tsup": "^8.4.0",
|
|
22
|
-
"tsx": "^4.19.
|
|
27
|
+
"tsx": "^4.19.4",
|
|
23
28
|
"typescript": "^5.8.3",
|
|
24
|
-
"vitest": "^3.1.
|
|
29
|
+
"vitest": "^3.1.2"
|
|
25
30
|
},
|
|
26
31
|
"scripts": {
|
|
27
|
-
"build": "tsup",
|
|
32
|
+
"build": "tsc --noEmit && tsup",
|
|
28
33
|
"build:watch": "tsup --watch",
|
|
29
34
|
"check": "tsc --noEmit",
|
|
30
35
|
"test": "vitest"
|
package/src/adapter.ts
CHANGED
package/src/constants.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const INTERNAL_BODY = Symbol("internal_body");
|
|
1
|
+
export const INTERNAL_BODY: unique symbol = Symbol("internal_body");
|
|
@@ -21,7 +21,7 @@ export function createFetchHandler(handler: (req: Request) => Response | Promise
|
|
|
21
21
|
return async (
|
|
22
22
|
incoming: IncomingMessage | Http2ServerRequest,
|
|
23
23
|
outgoing: ServerResponse | Http2ServerResponse,
|
|
24
|
-
) => {
|
|
24
|
+
): Promise<void> => {
|
|
25
25
|
const req = await nodeMessageToRequest(incoming);
|
|
26
26
|
const res = await handler(req);
|
|
27
27
|
return await responseToNodeResponse(res, outgoing);
|
package/src/createNodeServer.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { IncomingMessage, Server, ServerResponse } from "http";
|
|
1
2
|
import { createServer } from "node:http";
|
|
2
3
|
import { createFetchHandler } from "./createFetchHandler";
|
|
3
4
|
|
|
4
|
-
export default function createNodeServer(
|
|
5
|
+
export default function createNodeServer(
|
|
6
|
+
handler: (req: Request) => Response | Promise<Response>,
|
|
7
|
+
): Server<typeof IncomingMessage, typeof ServerResponse> {
|
|
5
8
|
// Create a server, polyfill it so that it can handle standard fetch methods,
|
|
6
9
|
// and pass our app fetch method to the handler
|
|
7
10
|
return createServer(createFetchHandler(handler));
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { IncomingHttpHeaders } from "node:http";
|
|
2
|
+
import { OutgoingHttpHeaders } from "node:http2";
|
|
3
|
+
|
|
4
|
+
export default function flattenHeaders(
|
|
5
|
+
headers: IncomingHttpHeaders | OutgoingHttpHeaders,
|
|
6
|
+
): HeadersInit {
|
|
7
|
+
const flatHeaders = new Headers();
|
|
8
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
9
|
+
if (value === undefined || value === null) {
|
|
10
|
+
continue;
|
|
11
|
+
} else if (Array.isArray(value)) {
|
|
12
|
+
for (const v of value) {
|
|
13
|
+
if (v !== undefined && v !== null) {
|
|
14
|
+
value.forEach((v) => flatHeaders.append(key, v));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
flatHeaders.set(key, String(value));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return flatHeaders;
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
const flatHeaders: [string, string][] = [];
|
|
25
|
+
|
|
26
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
27
|
+
if (value === undefined || value === null) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
for (const v of value) {
|
|
33
|
+
if (v != null) {
|
|
34
|
+
flatHeaders.push([key, String(v)]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
flatHeaders.push([key, String(value)]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return flatHeaders;
|
|
43
|
+
*/
|
|
44
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type IncomingMessage } from "node:http";
|
|
2
2
|
import { Http2ServerRequest } from "node:http2";
|
|
3
3
|
import { Readable } from "node:stream";
|
|
4
|
-
import flattenHeaders from "
|
|
4
|
+
import flattenHeaders from "./flattenHeaders";
|
|
5
5
|
|
|
6
6
|
// From https://stackoverflow.com/a/78849544
|
|
7
7
|
// and https://gist.github.com/marvinhagemeister/cc236ec97235ce0305ae9d48a24a607d
|
|
@@ -6,7 +6,7 @@ import { INTERNAL_BODY } from "./constants";
|
|
|
6
6
|
export default async function responseToNodeResponse(
|
|
7
7
|
res: Response,
|
|
8
8
|
outgoing: ServerResponse | Http2ServerResponse,
|
|
9
|
-
) {
|
|
9
|
+
): Promise<void> {
|
|
10
10
|
outgoing.statusCode = res.status;
|
|
11
11
|
outgoing.statusMessage = res.statusText;
|
|
12
12
|
|
package/tsup.config.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import { defineConfig } from "tsup";
|
|
1
|
+
import { type Options, defineConfig } from "tsup";
|
|
2
|
+
|
|
3
|
+
type Config =
|
|
4
|
+
| Options
|
|
5
|
+
| Options[]
|
|
6
|
+
| ((overrideOptions: Options) => Options | Options[] | Promise<Options | Options[]>);
|
|
2
7
|
|
|
3
8
|
export default defineConfig({
|
|
4
9
|
entry: ["src/index.ts"],
|
|
@@ -7,4 +12,4 @@ export default defineConfig({
|
|
|
7
12
|
clean: true,
|
|
8
13
|
metafile: true,
|
|
9
14
|
sourcemap: true,
|
|
10
|
-
});
|
|
15
|
+
}) satisfies Config as Config;
|
package/vitest.config.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
1
|
+
import { type UserConfigFnObject, defineConfig } from "vitest/config";
|
|
2
2
|
|
|
3
|
-
export default defineConfig(() => ({}));
|
|
3
|
+
export default defineConfig(() => ({})) satisfies UserConfigFnObject as UserConfigFnObject;
|