@marko/run 0.0.1-beta1 → 0.0.1-beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/default-entry.mjs +9 -3
- package/dist/adapter/dev-server.d.ts +1 -1
- package/dist/adapter/index.cjs +23 -8
- package/dist/adapter/index.js +22 -7
- package/dist/adapter/middleware.cjs +200 -0
- package/dist/adapter/middleware.d.ts +59 -0
- package/dist/adapter/middleware.js +169 -0
- package/dist/cli/default.config.mjs +1 -1
- package/dist/cli/index.mjs +45 -24
- package/dist/runtime/index.cjs +0 -16
- package/dist/runtime/index.d.ts +10 -2
- package/dist/runtime/index.js +0 -7
- package/dist/runtime/internal.cjs +148 -0
- package/dist/runtime/internal.d.ts +10 -0
- package/dist/runtime/internal.js +115 -0
- package/dist/runtime/router.cjs +6 -6
- package/dist/runtime/router.d.ts +4 -4
- package/dist/runtime/router.js +4 -4
- package/dist/runtime/types.d.ts +31 -16
- package/dist/runtime/utils.d.ts +3 -0
- package/dist/vite/codegen/index.d.ts +4 -3
- package/dist/vite/codegen/writer.d.ts +1 -1
- package/dist/vite/constants.d.ts +3 -2
- package/dist/vite/index.cjs +542 -275
- package/dist/vite/index.d.ts +4 -3
- package/dist/vite/index.js +539 -275
- package/dist/vite/types.d.ts +9 -7
- package/dist/vite/utils/config.d.ts +2 -2
- package/dist/vite/utils/server.d.ts +3 -1
- package/package.json +18 -6
- package/dist/adapter/server-old.d.ts +0 -3
- package/dist/adapter/server.d.ts +0 -6
- package/dist/adapters/node/index.d.ts +0 -5
- package/dist/adapters/node/server.d.ts +0 -3
- package/dist/adapters/static/crawler.d.ts +0 -9
- package/dist/adapters/static/default-entry.mjs +0 -1
- package/dist/adapters/static/index.cjs +0 -371
- package/dist/adapters/static/index.d.ts +0 -5
- package/dist/adapters/static/index.js +0 -341
- package/dist/adapters/static/server.d.ts +0 -3
- package/dist/runtime/request.d.ts +0 -4
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import createStaticServe from "serve-static";
|
|
2
|
+
import compression from "compression";
|
|
2
3
|
import { createServer } from "http";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
4
|
+
import createMiddleware from "@marko/run/adapter/middleware";
|
|
5
|
+
import { router } from "@marko/run/router";
|
|
5
6
|
|
|
6
7
|
const { PORT = 3456 } = process.env;
|
|
7
8
|
|
|
8
9
|
const dir = process.cwd();
|
|
9
|
-
const middleware = createMiddleware(
|
|
10
|
+
const middleware = createMiddleware(router);
|
|
11
|
+
const compress = compression({
|
|
12
|
+
threshold: 500,
|
|
13
|
+
});
|
|
10
14
|
const staticServe = createStaticServe(dir, {
|
|
11
15
|
index: false,
|
|
12
16
|
immutable: true,
|
|
@@ -14,5 +18,7 @@ const staticServe = createStaticServe(dir, {
|
|
|
14
18
|
});
|
|
15
19
|
|
|
16
20
|
createServer((req, res) =>
|
|
21
|
+
compress(req, res, () =>
|
|
17
22
|
staticServe(req, res, () => middleware(req, res))
|
|
23
|
+
)
|
|
18
24
|
).listen(PORT);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ViteDevServer } from "vite";
|
|
2
|
-
import { type NodeMiddleware } from "@
|
|
2
|
+
import { type NodeMiddleware } from "@marko/run/adapter/middleware";
|
|
3
3
|
export declare function createViteDevMiddleware<T>(devServer: ViteDevServer, load: (prev: T | undefined) => Promise<T>, factory: (value: T) => NodeMiddleware): NodeMiddleware;
|
|
4
4
|
export declare function createDevServer(configFile?: string): Promise<import("vite").Connect.Server>;
|
package/dist/adapter/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ var import_url = require("url");
|
|
|
36
36
|
|
|
37
37
|
// src/adapter/dev-server.ts
|
|
38
38
|
var import_vite = require("vite");
|
|
39
|
-
var
|
|
39
|
+
var import_middleware = __toESM(require("@marko/run/adapter/middleware"), 1);
|
|
40
40
|
function createViteDevMiddleware(devServer, load, factory) {
|
|
41
41
|
let value;
|
|
42
42
|
let middleware;
|
|
@@ -64,8 +64,8 @@ async function createDevServer(configFile) {
|
|
|
64
64
|
});
|
|
65
65
|
const middleware = createViteDevMiddleware(
|
|
66
66
|
devServer,
|
|
67
|
-
async () => (await devServer.ssrLoadModule("@marko/run")).
|
|
68
|
-
|
|
67
|
+
async () => (await devServer.ssrLoadModule("@marko/run/router")).router,
|
|
68
|
+
import_middleware.default
|
|
69
69
|
);
|
|
70
70
|
return devServer.middlewares.use(middleware);
|
|
71
71
|
}
|
|
@@ -73,16 +73,30 @@ async function createDevServer(configFile) {
|
|
|
73
73
|
// src/vite/utils/server.ts
|
|
74
74
|
var import_net = __toESM(require("net"), 1);
|
|
75
75
|
var import_child_process = __toESM(require("child_process"), 1);
|
|
76
|
-
|
|
76
|
+
var import_dotenv = require("dotenv");
|
|
77
|
+
var import_fs = __toESM(require("fs"), 1);
|
|
78
|
+
async function parseEnv(envFile) {
|
|
79
|
+
if (import_fs.default.existsSync(envFile)) {
|
|
80
|
+
const content = await import_fs.default.promises.readFile(envFile, "utf8");
|
|
81
|
+
return (0, import_dotenv.parse)(content);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function loadEnv(envFile) {
|
|
85
|
+
(0, import_dotenv.config)({ path: envFile });
|
|
86
|
+
}
|
|
87
|
+
async function spawnServer(cmd, port = 0, env, cwd = process.cwd(), wait = 3e4) {
|
|
77
88
|
if (port <= 0) {
|
|
78
89
|
port = await getAvailablePort();
|
|
79
90
|
}
|
|
91
|
+
if (typeof env === "string") {
|
|
92
|
+
env = await parseEnv(env);
|
|
93
|
+
}
|
|
80
94
|
const proc = import_child_process.default.spawn(cmd, {
|
|
81
95
|
cwd,
|
|
82
96
|
shell: true,
|
|
83
97
|
stdio: "inherit",
|
|
84
98
|
windowsHide: true,
|
|
85
|
-
env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
99
|
+
env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
86
100
|
});
|
|
87
101
|
const close = () => {
|
|
88
102
|
proc.unref();
|
|
@@ -136,7 +150,8 @@ function adapter() {
|
|
|
136
150
|
const entry = import_path.default.join(__dirname, "default-entry");
|
|
137
151
|
return entry;
|
|
138
152
|
},
|
|
139
|
-
async startDev(configFile, port) {
|
|
153
|
+
async startDev(configFile, port, envFile) {
|
|
154
|
+
envFile && await loadEnv(envFile);
|
|
140
155
|
const server = await createDevServer(configFile);
|
|
141
156
|
return new Promise((resolve) => {
|
|
142
157
|
const listener = server.listen(port, () => {
|
|
@@ -146,8 +161,8 @@ function adapter() {
|
|
|
146
161
|
});
|
|
147
162
|
});
|
|
148
163
|
},
|
|
149
|
-
async startPreview(dir, entry, port) {
|
|
150
|
-
const server = await spawnServer(`node ${entry}`, port, dir);
|
|
164
|
+
async startPreview(dir, entry, port, envFile) {
|
|
165
|
+
const server = await spawnServer(`node ${entry}`, port, envFile, dir);
|
|
151
166
|
console.log(`Preview server started: http://localhost:${server.port}`);
|
|
152
167
|
}
|
|
153
168
|
};
|
package/dist/adapter/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from "url";
|
|
|
4
4
|
|
|
5
5
|
// src/adapter/dev-server.ts
|
|
6
6
|
import { createServer } from "vite";
|
|
7
|
-
import
|
|
7
|
+
import createMiddleware from "@marko/run/adapter/middleware";
|
|
8
8
|
function createViteDevMiddleware(devServer, load, factory) {
|
|
9
9
|
let value;
|
|
10
10
|
let middleware;
|
|
@@ -32,7 +32,7 @@ async function createDevServer(configFile) {
|
|
|
32
32
|
});
|
|
33
33
|
const middleware = createViteDevMiddleware(
|
|
34
34
|
devServer,
|
|
35
|
-
async () => (await devServer.ssrLoadModule("@marko/run")).
|
|
35
|
+
async () => (await devServer.ssrLoadModule("@marko/run/router")).router,
|
|
36
36
|
createMiddleware
|
|
37
37
|
);
|
|
38
38
|
return devServer.middlewares.use(middleware);
|
|
@@ -41,16 +41,30 @@ async function createDevServer(configFile) {
|
|
|
41
41
|
// src/vite/utils/server.ts
|
|
42
42
|
import net from "net";
|
|
43
43
|
import cp from "child_process";
|
|
44
|
-
|
|
44
|
+
import { parse, config } from "dotenv";
|
|
45
|
+
import fs from "fs";
|
|
46
|
+
async function parseEnv(envFile) {
|
|
47
|
+
if (fs.existsSync(envFile)) {
|
|
48
|
+
const content = await fs.promises.readFile(envFile, "utf8");
|
|
49
|
+
return parse(content);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function loadEnv(envFile) {
|
|
53
|
+
config({ path: envFile });
|
|
54
|
+
}
|
|
55
|
+
async function spawnServer(cmd, port = 0, env, cwd = process.cwd(), wait = 3e4) {
|
|
45
56
|
if (port <= 0) {
|
|
46
57
|
port = await getAvailablePort();
|
|
47
58
|
}
|
|
59
|
+
if (typeof env === "string") {
|
|
60
|
+
env = await parseEnv(env);
|
|
61
|
+
}
|
|
48
62
|
const proc = cp.spawn(cmd, {
|
|
49
63
|
cwd,
|
|
50
64
|
shell: true,
|
|
51
65
|
stdio: "inherit",
|
|
52
66
|
windowsHide: true,
|
|
53
|
-
env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
67
|
+
env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
54
68
|
});
|
|
55
69
|
const close = () => {
|
|
56
70
|
proc.unref();
|
|
@@ -103,7 +117,8 @@ function adapter() {
|
|
|
103
117
|
const entry = path.join(__dirname, "default-entry");
|
|
104
118
|
return entry;
|
|
105
119
|
},
|
|
106
|
-
async startDev(configFile, port) {
|
|
120
|
+
async startDev(configFile, port, envFile) {
|
|
121
|
+
envFile && await loadEnv(envFile);
|
|
107
122
|
const server = await createDevServer(configFile);
|
|
108
123
|
return new Promise((resolve) => {
|
|
109
124
|
const listener = server.listen(port, () => {
|
|
@@ -113,8 +128,8 @@ function adapter() {
|
|
|
113
128
|
});
|
|
114
129
|
});
|
|
115
130
|
},
|
|
116
|
-
async startPreview(dir, entry, port) {
|
|
117
|
-
const server = await spawnServer(`node ${entry}`, port, dir);
|
|
131
|
+
async startPreview(dir, entry, port, envFile) {
|
|
132
|
+
const server = await spawnServer(`node ${entry}`, port, envFile, dir);
|
|
118
133
|
console.log(`Preview server started: http://localhost:${server.port}`);
|
|
119
134
|
}
|
|
120
135
|
};
|
|
@@ -0,0 +1,200 @@
|
|
|
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 __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
|
|
26
|
+
// src/adapter/middleware.ts
|
|
27
|
+
var middleware_exports = {};
|
|
28
|
+
__export(middleware_exports, {
|
|
29
|
+
default: () => createMiddleware,
|
|
30
|
+
getOrigin: () => getOrigin
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(middleware_exports);
|
|
33
|
+
var webStream = __toESM(require("stream/web"), 1);
|
|
34
|
+
var import_crypto = __toESM(require("@hattip/polyfills/crypto"), 1);
|
|
35
|
+
(0, import_crypto.default)();
|
|
36
|
+
for (const key of Object.keys(webStream)) {
|
|
37
|
+
if (!(key in global)) {
|
|
38
|
+
global[key] = webStream[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function getForwardedHeader(req, name) {
|
|
42
|
+
const value = req.headers["x-forwarded-" + name];
|
|
43
|
+
if (value) {
|
|
44
|
+
if (typeof value === "string") {
|
|
45
|
+
const index = value.indexOf(",");
|
|
46
|
+
return index < 0 ? value : value.slice(0, index);
|
|
47
|
+
}
|
|
48
|
+
return value[0];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function getOrigin(req, protocol, host, trustProxy) {
|
|
52
|
+
var _a;
|
|
53
|
+
protocol ?? (protocol = req.protocol || trustProxy && getForwardedHeader(req, "proto") || ((_a = req.socket) == null ? void 0 : _a.encrypted) && "https" || "http");
|
|
54
|
+
host ?? (host = trustProxy && getForwardedHeader(req, "host") || req.headers.host);
|
|
55
|
+
if (!host) {
|
|
56
|
+
if (process.env.NODE_ENV !== "production") {
|
|
57
|
+
host = "localhost";
|
|
58
|
+
console.warn(
|
|
59
|
+
`Could not automatically determine the origin host, using 'localhost'. Use the 'origin' option or the 'ORIGIN' environment variable to set the origin explicitly.`
|
|
60
|
+
);
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Could not automatically determine the origin host. Use the 'origin' option or the 'ORIGIN' environment variable to set the origin explicitly.`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return `${protocol}://${host}`;
|
|
68
|
+
}
|
|
69
|
+
function createMiddleware(router, options = {}) {
|
|
70
|
+
const { trustProxy = process.env.TRUST_PROXY === "1" } = options;
|
|
71
|
+
let { origin = process.env.ORIGIN } = options;
|
|
72
|
+
let protocol;
|
|
73
|
+
let host;
|
|
74
|
+
if (origin) {
|
|
75
|
+
({ protocol, host } = new URL(origin));
|
|
76
|
+
protocol = protocol.slice(0, -1);
|
|
77
|
+
}
|
|
78
|
+
return async (req, res, next) => {
|
|
79
|
+
origin ?? (origin = getOrigin(req, protocol, host, trustProxy));
|
|
80
|
+
const url = new URL(req.url, origin);
|
|
81
|
+
const ip = req.ip || trustProxy && getForwardedHeader(req, "for") || req.socket.remoteAddress || "";
|
|
82
|
+
const platform = {
|
|
83
|
+
ip,
|
|
84
|
+
request: req,
|
|
85
|
+
response: res,
|
|
86
|
+
setCookie(cookie) {
|
|
87
|
+
res.appendHeader("set-cookie", cookie);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const context = {
|
|
91
|
+
method: req.method,
|
|
92
|
+
url,
|
|
93
|
+
platform
|
|
94
|
+
};
|
|
95
|
+
Object.defineProperty(context, "request", {
|
|
96
|
+
get() {
|
|
97
|
+
const headers = req.headers;
|
|
98
|
+
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : req.socket ? req : new ReadableStream({
|
|
99
|
+
start(controller) {
|
|
100
|
+
req.on("data", (chunk) => controller.enqueue(chunk));
|
|
101
|
+
req.on("end", () => controller.close());
|
|
102
|
+
req.on("error", (err) => controller.error(err));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const request = new Request(url, {
|
|
106
|
+
method: req.method,
|
|
107
|
+
headers,
|
|
108
|
+
body,
|
|
109
|
+
duplex: "half"
|
|
110
|
+
});
|
|
111
|
+
Object.defineProperty(this, "request", {
|
|
112
|
+
value: request,
|
|
113
|
+
enumerable: true,
|
|
114
|
+
configurable: true
|
|
115
|
+
});
|
|
116
|
+
return request;
|
|
117
|
+
},
|
|
118
|
+
enumerable: true,
|
|
119
|
+
configurable: true
|
|
120
|
+
});
|
|
121
|
+
const response = await router(context);
|
|
122
|
+
if (!response) {
|
|
123
|
+
if (next) {
|
|
124
|
+
next();
|
|
125
|
+
} else {
|
|
126
|
+
res.statusCode = 404;
|
|
127
|
+
res.setHeader("content-length", "0");
|
|
128
|
+
res.end();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
res.statusCode = response.status;
|
|
134
|
+
for (const [key, value] of response.headers) {
|
|
135
|
+
if (key === "set-cookie") {
|
|
136
|
+
let sepIndex = value.indexOf(",") + 1;
|
|
137
|
+
if (!sepIndex) {
|
|
138
|
+
res.setHeader(key, value);
|
|
139
|
+
} else {
|
|
140
|
+
let index = 0;
|
|
141
|
+
do {
|
|
142
|
+
res.appendHeader(key, value.slice(index, sepIndex - 1));
|
|
143
|
+
index = sepIndex;
|
|
144
|
+
sepIndex = value.indexOf(",", sepIndex) + 1;
|
|
145
|
+
} while (sepIndex);
|
|
146
|
+
res.appendHeader(key, value.slice(index));
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
res.setHeader(key, value);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (!response.body) {
|
|
153
|
+
if (!response.headers.has("content-length")) {
|
|
154
|
+
res.setHeader("content-length", "0");
|
|
155
|
+
}
|
|
156
|
+
res.end();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const reader = response.body.getReader();
|
|
160
|
+
if (res.destroyed) {
|
|
161
|
+
reader.cancel();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
res.on("close", cancel);
|
|
165
|
+
res.on("error", cancel);
|
|
166
|
+
write();
|
|
167
|
+
function cancel(error) {
|
|
168
|
+
res.off("close", cancel);
|
|
169
|
+
res.off("error", cancel);
|
|
170
|
+
reader.cancel(error).catch(() => {
|
|
171
|
+
});
|
|
172
|
+
error && res.destroy(error);
|
|
173
|
+
}
|
|
174
|
+
async function write() {
|
|
175
|
+
try {
|
|
176
|
+
while (true) {
|
|
177
|
+
const { done, value } = await reader.read();
|
|
178
|
+
if (done) {
|
|
179
|
+
res.end();
|
|
180
|
+
return;
|
|
181
|
+
} else if (!res.write(value)) {
|
|
182
|
+
res.once("drain", write);
|
|
183
|
+
return;
|
|
184
|
+
} else if (res.flush) {
|
|
185
|
+
res.flush();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch (err) {
|
|
189
|
+
const error = err instanceof Error ? err : new Error("Error while writing to node response", {
|
|
190
|
+
cause: err
|
|
191
|
+
});
|
|
192
|
+
cancel(error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
198
|
+
0 && (module.exports = {
|
|
199
|
+
getOrigin
|
|
200
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Router } from "@marko/run";
|
|
2
|
+
import type { IncomingMessage, ServerResponse } from "http";
|
|
3
|
+
declare module "net" {
|
|
4
|
+
interface Socket {
|
|
5
|
+
encrypted?: boolean;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
declare module "http" {
|
|
9
|
+
interface IncomingMessage {
|
|
10
|
+
ip?: string;
|
|
11
|
+
protocol?: string;
|
|
12
|
+
}
|
|
13
|
+
interface ServerResponse {
|
|
14
|
+
appendHeader(key: string, value: string | string[]): this;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
declare module "@marko/run" {
|
|
18
|
+
interface Platform extends NodePlatformInfo {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export interface NodePlatformInfo {
|
|
22
|
+
ip: string;
|
|
23
|
+
request: IncomingMessage;
|
|
24
|
+
response: ServerResponse;
|
|
25
|
+
setCookie(cookie: string): void;
|
|
26
|
+
}
|
|
27
|
+
/** Connect/Express style request listener/middleware */
|
|
28
|
+
export declare type NodeMiddleware = (req: IncomingMessage, res: ServerResponse & {
|
|
29
|
+
flush?: () => void;
|
|
30
|
+
}, next?: () => void) => void;
|
|
31
|
+
/** Adapter options */
|
|
32
|
+
export interface NodeAdapterOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Set the origin part of the URL to a constant value.
|
|
35
|
+
* It defaults to `process.env.ORIGIN`. If neither is set,
|
|
36
|
+
* the origin is computed from the protocol and hostname.
|
|
37
|
+
* To determine the protocol, `req.protocol` is tried first.
|
|
38
|
+
* If `trustProxy` is set, `X-Forwarded-Proto` header is used.
|
|
39
|
+
* Otherwise, `req.socket.encrypted` is used.
|
|
40
|
+
* To determine the hostname, `X-Forwarded-Host`
|
|
41
|
+
* (if `trustProxy` is set) or `Host` header is used.
|
|
42
|
+
*/
|
|
43
|
+
origin?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Whether to trust `X-Forwarded-*` headers. `X-Forwarded-Proto`
|
|
46
|
+
* and `X-Forwarded-Host` are used to determine the origin when
|
|
47
|
+
* `origin` and `process.env.ORIGIN` are not set. `X-Forwarded-For`
|
|
48
|
+
* is used to determine the IP address. The leftmost values are used
|
|
49
|
+
* if multiple values are set. Defaults to true if `process.env.TRUST_PROXY`
|
|
50
|
+
* is set to `1`, otherwise false.
|
|
51
|
+
*/
|
|
52
|
+
trustProxy?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export declare function getOrigin(req: IncomingMessage, protocol?: string, host?: string, trustProxy?: boolean): string;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a request handler to be passed to http.createServer() or used as a
|
|
57
|
+
* middleware in Connect-style frameworks like Express.
|
|
58
|
+
*/
|
|
59
|
+
export default function createMiddleware(router: Router<NodePlatformInfo>, options?: NodeAdapterOptions): NodeMiddleware;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// src/adapter/middleware.ts
|
|
2
|
+
import * as webStream from "stream/web";
|
|
3
|
+
import installCrypto from "@hattip/polyfills/crypto";
|
|
4
|
+
installCrypto();
|
|
5
|
+
for (const key of Object.keys(webStream)) {
|
|
6
|
+
if (!(key in global)) {
|
|
7
|
+
global[key] = webStream[key];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function getForwardedHeader(req, name) {
|
|
11
|
+
const value = req.headers["x-forwarded-" + name];
|
|
12
|
+
if (value) {
|
|
13
|
+
if (typeof value === "string") {
|
|
14
|
+
const index = value.indexOf(",");
|
|
15
|
+
return index < 0 ? value : value.slice(0, index);
|
|
16
|
+
}
|
|
17
|
+
return value[0];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function getOrigin(req, protocol, host, trustProxy) {
|
|
21
|
+
var _a;
|
|
22
|
+
protocol ?? (protocol = req.protocol || trustProxy && getForwardedHeader(req, "proto") || ((_a = req.socket) == null ? void 0 : _a.encrypted) && "https" || "http");
|
|
23
|
+
host ?? (host = trustProxy && getForwardedHeader(req, "host") || req.headers.host);
|
|
24
|
+
if (!host) {
|
|
25
|
+
if (process.env.NODE_ENV !== "production") {
|
|
26
|
+
host = "localhost";
|
|
27
|
+
console.warn(
|
|
28
|
+
`Could not automatically determine the origin host, using 'localhost'. Use the 'origin' option or the 'ORIGIN' environment variable to set the origin explicitly.`
|
|
29
|
+
);
|
|
30
|
+
} else {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Could not automatically determine the origin host. Use the 'origin' option or the 'ORIGIN' environment variable to set the origin explicitly.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return `${protocol}://${host}`;
|
|
37
|
+
}
|
|
38
|
+
function createMiddleware(router, options = {}) {
|
|
39
|
+
const { trustProxy = process.env.TRUST_PROXY === "1" } = options;
|
|
40
|
+
let { origin = process.env.ORIGIN } = options;
|
|
41
|
+
let protocol;
|
|
42
|
+
let host;
|
|
43
|
+
if (origin) {
|
|
44
|
+
({ protocol, host } = new URL(origin));
|
|
45
|
+
protocol = protocol.slice(0, -1);
|
|
46
|
+
}
|
|
47
|
+
return async (req, res, next) => {
|
|
48
|
+
origin ?? (origin = getOrigin(req, protocol, host, trustProxy));
|
|
49
|
+
const url = new URL(req.url, origin);
|
|
50
|
+
const ip = req.ip || trustProxy && getForwardedHeader(req, "for") || req.socket.remoteAddress || "";
|
|
51
|
+
const platform = {
|
|
52
|
+
ip,
|
|
53
|
+
request: req,
|
|
54
|
+
response: res,
|
|
55
|
+
setCookie(cookie) {
|
|
56
|
+
res.appendHeader("set-cookie", cookie);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const context = {
|
|
60
|
+
method: req.method,
|
|
61
|
+
url,
|
|
62
|
+
platform
|
|
63
|
+
};
|
|
64
|
+
Object.defineProperty(context, "request", {
|
|
65
|
+
get() {
|
|
66
|
+
const headers = req.headers;
|
|
67
|
+
const body = req.method === "GET" || req.method === "HEAD" ? void 0 : req.socket ? req : new ReadableStream({
|
|
68
|
+
start(controller) {
|
|
69
|
+
req.on("data", (chunk) => controller.enqueue(chunk));
|
|
70
|
+
req.on("end", () => controller.close());
|
|
71
|
+
req.on("error", (err) => controller.error(err));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const request = new Request(url, {
|
|
75
|
+
method: req.method,
|
|
76
|
+
headers,
|
|
77
|
+
body,
|
|
78
|
+
duplex: "half"
|
|
79
|
+
});
|
|
80
|
+
Object.defineProperty(this, "request", {
|
|
81
|
+
value: request,
|
|
82
|
+
enumerable: true,
|
|
83
|
+
configurable: true
|
|
84
|
+
});
|
|
85
|
+
return request;
|
|
86
|
+
},
|
|
87
|
+
enumerable: true,
|
|
88
|
+
configurable: true
|
|
89
|
+
});
|
|
90
|
+
const response = await router(context);
|
|
91
|
+
if (!response) {
|
|
92
|
+
if (next) {
|
|
93
|
+
next();
|
|
94
|
+
} else {
|
|
95
|
+
res.statusCode = 404;
|
|
96
|
+
res.setHeader("content-length", "0");
|
|
97
|
+
res.end();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
res.statusCode = response.status;
|
|
103
|
+
for (const [key, value] of response.headers) {
|
|
104
|
+
if (key === "set-cookie") {
|
|
105
|
+
let sepIndex = value.indexOf(",") + 1;
|
|
106
|
+
if (!sepIndex) {
|
|
107
|
+
res.setHeader(key, value);
|
|
108
|
+
} else {
|
|
109
|
+
let index = 0;
|
|
110
|
+
do {
|
|
111
|
+
res.appendHeader(key, value.slice(index, sepIndex - 1));
|
|
112
|
+
index = sepIndex;
|
|
113
|
+
sepIndex = value.indexOf(",", sepIndex) + 1;
|
|
114
|
+
} while (sepIndex);
|
|
115
|
+
res.appendHeader(key, value.slice(index));
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
res.setHeader(key, value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!response.body) {
|
|
122
|
+
if (!response.headers.has("content-length")) {
|
|
123
|
+
res.setHeader("content-length", "0");
|
|
124
|
+
}
|
|
125
|
+
res.end();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const reader = response.body.getReader();
|
|
129
|
+
if (res.destroyed) {
|
|
130
|
+
reader.cancel();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
res.on("close", cancel);
|
|
134
|
+
res.on("error", cancel);
|
|
135
|
+
write();
|
|
136
|
+
function cancel(error) {
|
|
137
|
+
res.off("close", cancel);
|
|
138
|
+
res.off("error", cancel);
|
|
139
|
+
reader.cancel(error).catch(() => {
|
|
140
|
+
});
|
|
141
|
+
error && res.destroy(error);
|
|
142
|
+
}
|
|
143
|
+
async function write() {
|
|
144
|
+
try {
|
|
145
|
+
while (true) {
|
|
146
|
+
const { done, value } = await reader.read();
|
|
147
|
+
if (done) {
|
|
148
|
+
res.end();
|
|
149
|
+
return;
|
|
150
|
+
} else if (!res.write(value)) {
|
|
151
|
+
res.once("drain", write);
|
|
152
|
+
return;
|
|
153
|
+
} else if (res.flush) {
|
|
154
|
+
res.flush();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
const error = err instanceof Error ? err : new Error("Error while writing to node response", {
|
|
159
|
+
cause: err
|
|
160
|
+
});
|
|
161
|
+
cancel(error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
export {
|
|
167
|
+
createMiddleware as default,
|
|
168
|
+
getOrigin
|
|
169
|
+
};
|