@demiurgejs/core 0.1.0 → 0.2.0-beta.1
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 +3 -0
- package/bin/demiurge.mjs +51 -0
- package/dist/browser/file-router.d.ts +5 -0
- package/dist/browser/file-router.d.ts.map +1 -1
- package/dist/chunks/request-metadata-DwEO1EAS.js +477 -0
- package/dist/chunks/request-metadata-DwEO1EAS.js.map +1 -0
- package/dist/chunks/static-files-DUjHw-4H.js +11 -0
- package/dist/chunks/static-files-DUjHw-4H.js.map +1 -0
- package/dist/chunks/{streaming-27pwhjGC.js → streaming-Ci6vf3BB.js} +117 -107
- package/dist/chunks/streaming-Ci6vf3BB.js.map +1 -0
- package/dist/chunks/{testing-BBnJ5WUR.js → testing-DBjVCN5v.js} +2384 -1941
- package/dist/chunks/testing-DBjVCN5v.js.map +1 -0
- package/dist/cli.d.ts +42 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +164 -0
- package/dist/cli.js.map +1 -0
- package/dist/document/index.d.ts +2 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/document/render.d.ts +2 -1
- package/dist/document/render.d.ts.map +1 -1
- package/dist/document/scripts.d.ts +22 -0
- package/dist/document/scripts.d.ts.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +893 -1035
- package/dist/index.js.map +1 -1
- package/dist/internal/testing.js +15 -14
- package/dist/internal/testing.js.map +1 -1
- package/dist/node/index.js +86 -85
- package/dist/node/index.js.map +1 -1
- package/dist/node/static.d.ts.map +1 -1
- package/dist/node/streaming.d.ts +2 -0
- package/dist/node/streaming.d.ts.map +1 -1
- package/dist/route/action.d.ts +11 -11
- package/dist/route/action.d.ts.map +1 -1
- package/dist/route/index.d.ts +2 -1
- package/dist/route/index.d.ts.map +1 -1
- package/dist/route/middleware.d.ts +7 -0
- package/dist/route/middleware.d.ts.map +1 -0
- package/dist/route/page.d.ts +2 -2
- package/dist/route/page.d.ts.map +1 -1
- package/dist/route/response.d.ts +19 -19
- package/dist/route/response.d.ts.map +1 -1
- package/dist/route/types.d.ts +55 -31
- package/dist/route/types.d.ts.map +1 -1
- package/dist/route/webhook.d.ts +1 -1
- package/dist/router/manifest.d.ts +4 -1
- package/dist/router/manifest.d.ts.map +1 -1
- package/dist/routing/generate.d.ts +2 -0
- package/dist/routing/generate.d.ts.map +1 -1
- package/dist/routing/index.d.ts +1 -1
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/types.d.ts +2 -0
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/security/cors.d.ts.map +1 -1
- package/dist/security/index.d.ts +4 -2
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/policy.d.ts +31 -2
- package/dist/security/policy.d.ts.map +1 -1
- package/dist/security/types.d.ts +27 -13
- package/dist/security/types.d.ts.map +1 -1
- package/dist/security/verification.d.ts +8 -0
- package/dist/security/verification.d.ts.map +1 -0
- package/dist/server/errors.d.ts.map +1 -1
- package/dist/server/not-found.d.ts.map +1 -1
- package/dist/server/render-tree.d.ts +6 -1
- package/dist/server/render-tree.d.ts.map +1 -1
- package/dist/server/request-handler.d.ts +4 -1
- package/dist/server/request-handler.d.ts.map +1 -1
- package/dist/server/ssr.d.ts +1 -0
- package/dist/server/ssr.d.ts.map +1 -1
- package/dist/static/index.d.ts +15 -0
- package/dist/static/index.d.ts.map +1 -1
- package/dist/static/index.js +684 -123
- package/dist/static/index.js.map +1 -1
- package/dist/static/preview.d.ts +8 -0
- package/dist/static/preview.d.ts.map +1 -0
- package/dist/static/vercel.d.ts +31 -0
- package/dist/static/vercel.d.ts.map +1 -0
- package/dist/static-files.d.ts +5 -0
- package/dist/static-files.d.ts.map +1 -0
- package/dist/vite/index.d.ts +3 -2
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +882 -288
- package/dist/vite/index.js.map +1 -1
- package/dist/vite/plugin.d.ts +13 -0
- package/dist/vite/plugin.d.ts.map +1 -1
- package/dist/vite/policy-verification.d.ts +10 -0
- package/dist/vite/policy-verification.d.ts.map +1 -0
- package/package.json +9 -1
- package/dist/chunks/index-BnX9Qxbm.js +0 -44
- package/dist/chunks/index-BnX9Qxbm.js.map +0 -1
- package/dist/chunks/ssr-O3d7Q73U.js +0 -273
- package/dist/chunks/ssr-O3d7Q73U.js.map +0 -1
- package/dist/chunks/streaming-27pwhjGC.js.map +0 -1
- package/dist/chunks/testing-BBnJ5WUR.js.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { Readable as
|
|
2
|
-
import { pipeline as
|
|
3
|
-
import { isIP as
|
|
4
|
-
import { s as
|
|
5
|
-
import { renderToPipeableStream as
|
|
6
|
-
const
|
|
1
|
+
import { Readable as C, Transform as P } from "node:stream";
|
|
2
|
+
import { pipeline as A } from "node:stream/promises";
|
|
3
|
+
import { isIP as M } from "node:net";
|
|
4
|
+
import { s as R, r as I, c as v, a as $, b as U } from "./request-metadata-DwEO1EAS.js";
|
|
5
|
+
import { renderToPipeableStream as L } from "react-dom/server";
|
|
6
|
+
const g = {
|
|
7
7
|
for: "x-forwarded-for",
|
|
8
8
|
host: "x-forwarded-host",
|
|
9
9
|
protocol: "x-forwarded-proto"
|
|
10
|
-
},
|
|
11
|
-
class
|
|
10
|
+
}, N = !1, O = /* @__PURE__ */ new Set(["CONNECT", "TRACE", "TRACK"]);
|
|
11
|
+
class W extends Error {
|
|
12
12
|
method;
|
|
13
13
|
constructor(t) {
|
|
14
14
|
super(`HTTP method "${t}" is not supported.`), this.method = t, this.name = "UnsupportedMethodError";
|
|
@@ -20,13 +20,13 @@ class w extends Error {
|
|
|
20
20
|
super(`HTTP host "${t}" is not allowed.`), this.host = t, this.name = "UntrustedHostError";
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function _(e) {
|
|
24
24
|
if (e.allowedHosts.length === 0)
|
|
25
25
|
throw new Error("Demiurge Node allowedHosts must contain at least one host.");
|
|
26
26
|
for (const r of e.allowedHosts)
|
|
27
|
-
if (!
|
|
27
|
+
if (!E(r))
|
|
28
28
|
throw new Error(`Demiurge Node allowed host "${r}" is invalid.`);
|
|
29
|
-
const t = e.trustProxy ??
|
|
29
|
+
const t = e.trustProxy ?? N;
|
|
30
30
|
if (t !== !1) {
|
|
31
31
|
if ("hops" in t) {
|
|
32
32
|
if (!Number.isSafeInteger(t.hops) || t.hops < 0)
|
|
@@ -37,35 +37,35 @@ function O(e) {
|
|
|
37
37
|
}
|
|
38
38
|
for (const r of t.ranges) {
|
|
39
39
|
const n = r.split("/")[0];
|
|
40
|
-
|
|
40
|
+
k(n, r);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
function
|
|
45
|
-
|
|
44
|
+
function ne(e, t) {
|
|
45
|
+
_(t);
|
|
46
46
|
const r = e.method ?? "GET";
|
|
47
|
-
if (
|
|
48
|
-
throw new
|
|
49
|
-
const n =
|
|
47
|
+
if (O.has(r.toUpperCase()))
|
|
48
|
+
throw new W(r);
|
|
49
|
+
const n = y(e.socket?.remoteAddress), o = V(
|
|
50
50
|
n,
|
|
51
|
-
e.headers[
|
|
52
|
-
t.trustProxy ??
|
|
53
|
-
), s =
|
|
54
|
-
e.headers[
|
|
51
|
+
e.headers[g.for],
|
|
52
|
+
t.trustProxy ?? N
|
|
53
|
+
), s = b(
|
|
54
|
+
e.headers[g.protocol],
|
|
55
55
|
o.forwardedDepth
|
|
56
|
-
), c =
|
|
57
|
-
e.headers[
|
|
56
|
+
), c = B(e, s), i = b(
|
|
57
|
+
e.headers[g.host],
|
|
58
58
|
o.forwardedDepth
|
|
59
|
-
) ?? e.headers.host, a =
|
|
60
|
-
headers:
|
|
59
|
+
) ?? e.headers.host, a = G(i, t.allowedHosts), f = `${c}://${a}`, d = new URL(e.url ?? "/", f), u = {
|
|
60
|
+
headers: K(e.headers),
|
|
61
61
|
method: r,
|
|
62
62
|
signal: t.signal
|
|
63
63
|
};
|
|
64
|
-
r !== "GET" && r !== "HEAD" && (
|
|
65
|
-
const h = new Request(
|
|
66
|
-
return
|
|
64
|
+
r !== "GET" && r !== "HEAD" && (u.body = C.toWeb(e), u.duplex = "half");
|
|
65
|
+
const h = new Request(d, u);
|
|
66
|
+
return R(h, { clientIp: o.clientIp }), h;
|
|
67
67
|
}
|
|
68
|
-
function
|
|
68
|
+
function B(e, t) {
|
|
69
69
|
if (t) {
|
|
70
70
|
const r = t.toLowerCase();
|
|
71
71
|
if (r !== "http" && r !== "https")
|
|
@@ -74,16 +74,16 @@ function W(e, t) {
|
|
|
74
74
|
}
|
|
75
75
|
return e.socket?.encrypted ? "https" : "http";
|
|
76
76
|
}
|
|
77
|
-
function
|
|
77
|
+
function G(e, t) {
|
|
78
78
|
if (t.length === 0)
|
|
79
79
|
throw new Error("Demiurge Node allowedHosts must contain at least one host.");
|
|
80
80
|
if (!e)
|
|
81
81
|
throw new w("");
|
|
82
|
-
const r =
|
|
82
|
+
const r = E(e);
|
|
83
83
|
if (!r)
|
|
84
84
|
throw new w(e);
|
|
85
85
|
if (!t.some((o) => {
|
|
86
|
-
const s =
|
|
86
|
+
const s = E(o);
|
|
87
87
|
if (!s)
|
|
88
88
|
throw new Error(`Demiurge Node allowed host "${o}" is invalid.`);
|
|
89
89
|
return s.port ? s.host === r.host : s.hostname === r.hostname;
|
|
@@ -91,7 +91,7 @@ function _(e, t) {
|
|
|
91
91
|
throw new w(e);
|
|
92
92
|
return r.host;
|
|
93
93
|
}
|
|
94
|
-
function
|
|
94
|
+
function E(e) {
|
|
95
95
|
if (e.trim() !== e || e.includes("@"))
|
|
96
96
|
return null;
|
|
97
97
|
try {
|
|
@@ -101,8 +101,8 @@ function g(e) {
|
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
function
|
|
105
|
-
const n =
|
|
104
|
+
function V(e, t, r) {
|
|
105
|
+
const n = T(t), o = [...n, e];
|
|
106
106
|
if (r === !1)
|
|
107
107
|
return { clientIp: e, forwardedDepth: 0 };
|
|
108
108
|
if ("hops" in r) {
|
|
@@ -117,28 +117,28 @@ function B(e, t, r) {
|
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
let s = o.length - 1, c = 0;
|
|
120
|
-
for (; s > 0 &&
|
|
120
|
+
for (; s > 0 && S(o[s], r.ranges); )
|
|
121
121
|
s -= 1, c += 1;
|
|
122
122
|
return {
|
|
123
123
|
clientIp: o[s],
|
|
124
|
-
forwardedDepth: c || (
|
|
124
|
+
forwardedDepth: c || (S(e, r.ranges) ? 1 : 0)
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
-
function
|
|
127
|
+
function b(e, t) {
|
|
128
128
|
if (t === 0)
|
|
129
129
|
return;
|
|
130
|
-
const r =
|
|
130
|
+
const r = T(e);
|
|
131
131
|
if (r.length !== 0)
|
|
132
132
|
return r[Math.max(0, r.length - t)];
|
|
133
133
|
}
|
|
134
|
-
function
|
|
134
|
+
function T(e) {
|
|
135
135
|
return (Array.isArray(e) ? e : [e]).flatMap((t) => t?.split(",") ?? []).map((t) => t.trim()).filter(Boolean);
|
|
136
136
|
}
|
|
137
|
-
function
|
|
138
|
-
return t.some((r) =>
|
|
137
|
+
function S(e, t) {
|
|
138
|
+
return t.some((r) => k(e, r));
|
|
139
139
|
}
|
|
140
|
-
function
|
|
141
|
-
const [r, n] = t.split("/"), o =
|
|
140
|
+
function k(e, t) {
|
|
141
|
+
const [r, n] = t.split("/"), o = D(y(e)), s = D(y(r));
|
|
142
142
|
if (!o || !s || o.length !== s.length) {
|
|
143
143
|
if (!s)
|
|
144
144
|
throw new Error(`Demiurge Node trustProxy range "${t}" is invalid.`);
|
|
@@ -148,17 +148,17 @@ function T(e, t) {
|
|
|
148
148
|
if (!Number.isInteger(i) || i < 0 || i > c)
|
|
149
149
|
throw new Error(`Demiurge Node trustProxy range "${t}" is invalid.`);
|
|
150
150
|
for (let a = 0; a < i; a += 1) {
|
|
151
|
-
const
|
|
152
|
-
if ((o[Math.floor(a / 8)] &
|
|
151
|
+
const f = 1 << 7 - a % 8;
|
|
152
|
+
if ((o[Math.floor(a / 8)] & f) !== (s[Math.floor(a / 8)] & f))
|
|
153
153
|
return !1;
|
|
154
154
|
}
|
|
155
155
|
return !0;
|
|
156
156
|
}
|
|
157
|
-
function
|
|
157
|
+
function y(e) {
|
|
158
158
|
return e ? e.startsWith("::ffff:") ? e.slice(7) : e : "unknown";
|
|
159
159
|
}
|
|
160
|
-
function
|
|
161
|
-
const t =
|
|
160
|
+
function D(e) {
|
|
161
|
+
const t = M(e);
|
|
162
162
|
if (t === 4)
|
|
163
163
|
return e.split(".").map(Number);
|
|
164
164
|
if (t !== 6)
|
|
@@ -169,15 +169,15 @@ function S(e) {
|
|
|
169
169
|
...Array.from({ length: c }, () => "0"),
|
|
170
170
|
...s
|
|
171
171
|
].flatMap((a) => {
|
|
172
|
-
const
|
|
173
|
-
return [
|
|
172
|
+
const f = Number.parseInt(a, 16);
|
|
173
|
+
return [f >> 8, f & 255];
|
|
174
174
|
});
|
|
175
175
|
}
|
|
176
|
-
function
|
|
176
|
+
function oe(e) {
|
|
177
177
|
e.statusCode = 501, e.setHeader("content-type", "text/plain; charset=utf-8"), e.end("Not Implemented");
|
|
178
178
|
}
|
|
179
|
-
async function
|
|
180
|
-
const r =
|
|
179
|
+
async function se(e, t) {
|
|
180
|
+
const r = Y(t.headers);
|
|
181
181
|
if (t.headers.forEach((n, o) => {
|
|
182
182
|
o !== "set-cookie" && e.setHeader(o, n);
|
|
183
183
|
}), r.length > 0 && e.setHeader("set-cookie", r), e.statusCode = t.status, t.statusText && (e.statusMessage = t.statusText), !t.body) {
|
|
@@ -185,27 +185,27 @@ async function ne(e, t) {
|
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
187
187
|
try {
|
|
188
|
-
await
|
|
189
|
-
|
|
188
|
+
await A(
|
|
189
|
+
C.fromWeb(
|
|
190
190
|
t.body
|
|
191
191
|
),
|
|
192
192
|
e
|
|
193
193
|
);
|
|
194
194
|
} catch (n) {
|
|
195
|
-
if (!
|
|
195
|
+
if (!F(n))
|
|
196
196
|
throw n;
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
const
|
|
199
|
+
const z = /* @__PURE__ */ new Set([
|
|
200
200
|
"ECONNRESET",
|
|
201
201
|
"EPIPE",
|
|
202
202
|
"ERR_STREAM_DESTROYED",
|
|
203
203
|
"ERR_STREAM_PREMATURE_CLOSE"
|
|
204
204
|
]);
|
|
205
|
-
function
|
|
206
|
-
return e instanceof Error && "code" in e && typeof e.code == "string" &&
|
|
205
|
+
function F(e) {
|
|
206
|
+
return e instanceof Error && "code" in e && typeof e.code == "string" && z.has(e.code);
|
|
207
207
|
}
|
|
208
|
-
function
|
|
208
|
+
function K(e) {
|
|
209
209
|
const t = new Headers();
|
|
210
210
|
for (const [r, n] of Object.entries(e)) {
|
|
211
211
|
if (Array.isArray(n)) {
|
|
@@ -217,62 +217,72 @@ function z(e) {
|
|
|
217
217
|
}
|
|
218
218
|
return t;
|
|
219
219
|
}
|
|
220
|
-
function
|
|
220
|
+
function Y(e) {
|
|
221
221
|
const t = e.getSetCookie;
|
|
222
222
|
if (t)
|
|
223
223
|
return t.call(e);
|
|
224
224
|
const r = e.get("set-cookie");
|
|
225
|
-
return r ?
|
|
225
|
+
return r ? j(r) : [];
|
|
226
226
|
}
|
|
227
|
-
function
|
|
227
|
+
function j(e) {
|
|
228
228
|
return e.split(/,\s*(?=[^;,=\s]+\s*=)/);
|
|
229
229
|
}
|
|
230
230
|
const m = '<template data-demiurge-stream-root=""></template>';
|
|
231
|
-
function
|
|
232
|
-
return e.render.mode === "streaming" ?
|
|
231
|
+
function ie(e, t = {}) {
|
|
232
|
+
return e.render.mode === "streaming" ? J(e, t) : I(e, t);
|
|
233
233
|
}
|
|
234
|
-
async function
|
|
234
|
+
async function J(e, t = {}) {
|
|
235
235
|
if (t.signal?.aborted)
|
|
236
236
|
throw t.signal.reason;
|
|
237
|
-
const r =
|
|
237
|
+
const r = v(e, t), n = $(e, r);
|
|
238
238
|
return await new Promise((o, s) => {
|
|
239
|
-
let c = !1, i = !1, a = !1,
|
|
240
|
-
const u = new
|
|
241
|
-
destroy(
|
|
242
|
-
c || (i = !0),
|
|
239
|
+
let c = !1, i = !1, a = !1, f = "", d;
|
|
240
|
+
const u = new P({
|
|
241
|
+
destroy(l, x) {
|
|
242
|
+
c || (i = !0), x(l);
|
|
243
243
|
},
|
|
244
|
-
flush(
|
|
245
|
-
|
|
244
|
+
flush(l) {
|
|
245
|
+
l(null, f);
|
|
246
246
|
},
|
|
247
|
-
transform(
|
|
248
|
-
|
|
247
|
+
transform(l, x, H) {
|
|
248
|
+
H(null, l);
|
|
249
249
|
}
|
|
250
|
-
}),
|
|
251
|
-
i = !0,
|
|
252
|
-
},
|
|
250
|
+
}), h = () => {
|
|
251
|
+
i = !0, d?.abort(t.signal?.reason), u.destroy();
|
|
252
|
+
}, p = () => t.signal?.removeEventListener("abort", h);
|
|
253
253
|
u.once("finish", () => {
|
|
254
254
|
c = !0;
|
|
255
255
|
}), u.once("close", () => {
|
|
256
|
-
|
|
257
|
-
}), t.signal?.addEventListener("abort",
|
|
256
|
+
p(), c || (i = !0, d?.abort(new Error("Demiurge streaming response was cancelled.")));
|
|
257
|
+
}), t.signal?.addEventListener("abort", h, { once: !0 }), d = L(n, {
|
|
258
258
|
nonce: t.nonce,
|
|
259
|
-
onError(
|
|
260
|
-
a && !i && t.onStreamError?.(
|
|
259
|
+
onError(l) {
|
|
260
|
+
a && !i && t.onStreamError?.(l);
|
|
261
261
|
},
|
|
262
|
-
onShellError(
|
|
263
|
-
|
|
262
|
+
onShellError(l) {
|
|
263
|
+
p(), s(l);
|
|
264
264
|
},
|
|
265
265
|
onShellReady() {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
266
|
+
(async () => {
|
|
267
|
+
try {
|
|
268
|
+
const l = await X(e, {
|
|
269
|
+
...t,
|
|
270
|
+
scripts: r.scripts()
|
|
271
|
+
});
|
|
272
|
+
f = l.suffix, r.flushHead(), u.push(l.prefix), a = !0, d?.pipe(u), o(
|
|
273
|
+
new Response(Q(u), {
|
|
274
|
+
headers: { "content-type": "text/html; charset=utf-8" }
|
|
275
|
+
})
|
|
276
|
+
);
|
|
277
|
+
} catch (l) {
|
|
278
|
+
p(), d?.abort(l), u.destroy(), s(l);
|
|
279
|
+
}
|
|
280
|
+
})();
|
|
271
281
|
}
|
|
272
282
|
});
|
|
273
283
|
});
|
|
274
284
|
}
|
|
275
|
-
function
|
|
285
|
+
function Q(e) {
|
|
276
286
|
let t = !1, r = () => {
|
|
277
287
|
};
|
|
278
288
|
return new ReadableStream({
|
|
@@ -284,14 +294,14 @@ function Y(e) {
|
|
|
284
294
|
},
|
|
285
295
|
start(n) {
|
|
286
296
|
e.on("data", o), e.once("end", s), e.once("error", c), e.once("close", i);
|
|
287
|
-
function o(
|
|
288
|
-
t || (n.enqueue(Uint8Array.from(
|
|
297
|
+
function o(f) {
|
|
298
|
+
t || (n.enqueue(Uint8Array.from(f)), (n.desiredSize ?? 1) <= 0 && e.pause());
|
|
289
299
|
}
|
|
290
300
|
function s() {
|
|
291
301
|
t || (t = !0, a(), n.close());
|
|
292
302
|
}
|
|
293
|
-
function c(
|
|
294
|
-
t || (t = !0, a(), n.error(
|
|
303
|
+
function c(f) {
|
|
304
|
+
t || (t = !0, a(), n.error(f));
|
|
295
305
|
}
|
|
296
306
|
function i() {
|
|
297
307
|
t || (t = !0, a(), n.close());
|
|
@@ -303,15 +313,15 @@ function Y(e) {
|
|
|
303
313
|
}
|
|
304
314
|
});
|
|
305
315
|
}
|
|
306
|
-
async function
|
|
307
|
-
const r =
|
|
316
|
+
async function X(e, t) {
|
|
317
|
+
const r = U({
|
|
308
318
|
body: { data: e.data, navigation: t.navigation },
|
|
309
319
|
entrySrc: t.clientEntry,
|
|
310
320
|
lang: t.lang,
|
|
311
321
|
links: e.links,
|
|
312
322
|
metadata: e.metadata,
|
|
313
323
|
nonce: t.nonce,
|
|
314
|
-
scripts: e.scripts,
|
|
324
|
+
scripts: t.scripts ?? e.scripts,
|
|
315
325
|
styles: t.styles,
|
|
316
326
|
title: t.title
|
|
317
327
|
});
|
|
@@ -330,14 +340,14 @@ async function J(e, t) {
|
|
|
330
340
|
};
|
|
331
341
|
}
|
|
332
342
|
export {
|
|
333
|
-
|
|
343
|
+
W as U,
|
|
334
344
|
w as a,
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
345
|
+
se as b,
|
|
346
|
+
J as c,
|
|
347
|
+
K as d,
|
|
348
|
+
ie as r,
|
|
349
|
+
ne as t,
|
|
350
|
+
_ as v,
|
|
351
|
+
oe as w
|
|
342
352
|
};
|
|
343
|
-
//# sourceMappingURL=streaming-
|
|
353
|
+
//# sourceMappingURL=streaming-Ci6vf3BB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming-Ci6vf3BB.js","sources":["../../src/node/http.ts","../../src/node/streaming.ts"],"sourcesContent":["import { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { isIP } from \"node:net\";\nimport type {\n IncomingHttpHeaders,\n IncomingMessage,\n ServerResponse,\n} from \"node:http\";\nimport { setRequestConnectionMetadata } from \"../server/request-metadata\";\n\nexport type HttpScheme = \"http\" | \"https\";\n\nexport type NodeOriginPolicy = {\n allowedHosts: readonly string[];\n trustProxy?: TrustProxy;\n};\n\nexport type ToWebRequestOptions = NodeOriginPolicy & {\n signal?: AbortSignal;\n};\n\nexport type TrustProxy =\n | false\n | { hops: number }\n | { ranges: readonly string[] };\n\nconst forwardedHeaders = {\n for: \"x-forwarded-for\",\n host: \"x-forwarded-host\",\n protocol: \"x-forwarded-proto\",\n} as const satisfies Record<\"for\" | \"host\" | \"protocol\", string>;\nconst defaultTrustProxy = false satisfies TrustProxy;\n\n// The Fetch specification prohibits these methods in the `Request` constructor.\n// `new Request(...)` throws for them. Without this guard, an unauthenticated\n// client can make a generic 500 response and add stack traces to the server log.\nconst forbiddenMethods = new Set([\"CONNECT\", \"TRACE\", \"TRACK\"]);\n\nexport class UnsupportedMethodError extends Error {\n method: string;\n\n constructor(method: string) {\n super(`HTTP method \"${method}\" is not supported.`);\n this.method = method;\n this.name = \"UnsupportedMethodError\";\n }\n}\n\nexport class UntrustedHostError extends Error {\n host: string;\n\n constructor(host: string) {\n super(`HTTP host \"${host}\" is not allowed.`);\n this.host = host;\n this.name = \"UntrustedHostError\";\n }\n}\n\nexport function validateNodeOriginPolicy(policy: NodeOriginPolicy) {\n if (policy.allowedHosts.length === 0) {\n throw new Error(\"Demiurge Node allowedHosts must contain at least one host.\");\n }\n\n for (const host of policy.allowedHosts) {\n if (!parseAuthority(host)) {\n throw new Error(`Demiurge Node allowed host \"${host}\" is invalid.`);\n }\n }\n\n const trustProxy = policy.trustProxy ?? defaultTrustProxy;\n\n if (trustProxy === false) {\n return;\n }\n\n if (\"hops\" in trustProxy) {\n if (!Number.isSafeInteger(trustProxy.hops) || trustProxy.hops < 0) {\n throw new Error(\n \"Demiurge Node trustProxy hop count must be a non-negative integer.\",\n );\n }\n\n return;\n }\n\n for (const range of trustProxy.ranges) {\n const network = range.split(\"/\")[0];\n ipMatchesRange(network, range);\n }\n}\n\nexport function toWebRequest(\n request: IncomingMessage,\n options: ToWebRequestOptions,\n) {\n validateNodeOriginPolicy(options);\n const method = request.method ?? \"GET\";\n\n if (forbiddenMethods.has(method.toUpperCase())) {\n throw new UnsupportedMethodError(method);\n }\n\n const peerAddress = normalizeIpAddress(request.socket?.remoteAddress);\n const proxy = resolveProxyChain(\n peerAddress,\n request.headers[forwardedHeaders.for],\n options.trustProxy ?? defaultTrustProxy,\n );\n const forwardedProtocol = selectForwardedValue(\n request.headers[forwardedHeaders.protocol],\n proxy.forwardedDepth,\n );\n const protocol = resolveProtocol(request, forwardedProtocol);\n const host = selectForwardedValue(\n request.headers[forwardedHeaders.host],\n proxy.forwardedDepth,\n ) ?? request.headers.host;\n const authority = validateAllowedHost(host, options.allowedHosts);\n const origin = `${protocol}://${authority}`;\n const url = new URL(request.url ?? \"/\", origin);\n const init: RequestInit & { duplex?: \"half\" } = {\n headers: toHeaders(request.headers),\n method,\n signal: options.signal,\n };\n\n if (method !== \"GET\" && method !== \"HEAD\") {\n init.body = Readable.toWeb(request) as ReadableStream;\n init.duplex = \"half\";\n }\n\n const webRequest = new Request(url, init);\n setRequestConnectionMetadata(webRequest, { clientIp: proxy.clientIp });\n\n return webRequest;\n}\n\nfunction resolveProtocol(\n request: IncomingMessage,\n forwardedProtocol: string | undefined,\n) {\n if (forwardedProtocol) {\n const protocol = forwardedProtocol.toLowerCase();\n\n if (protocol !== \"http\" && protocol !== \"https\") {\n throw new Error(`Unsupported forwarded protocol \"${forwardedProtocol}\".`);\n }\n\n return protocol;\n }\n\n return (request.socket as { encrypted?: boolean } | undefined)?.encrypted\n ? \"https\"\n : \"http\";\n}\n\nfunction validateAllowedHost(\n host: string | undefined,\n allowedHosts: readonly string[],\n) {\n if (allowedHosts.length === 0) {\n throw new Error(\"Demiurge Node allowedHosts must contain at least one host.\");\n }\n\n if (!host) {\n throw new UntrustedHostError(\"\");\n }\n\n const authority = parseAuthority(host);\n\n if (!authority) {\n throw new UntrustedHostError(host);\n }\n\n const allowed = allowedHosts.some((candidate) => {\n const expected = parseAuthority(candidate);\n\n if (!expected) {\n throw new Error(`Demiurge Node allowed host \"${candidate}\" is invalid.`);\n }\n\n return expected.port\n ? expected.host === authority.host\n : expected.hostname === authority.hostname;\n });\n\n if (!allowed) {\n throw new UntrustedHostError(host);\n }\n\n return authority.host;\n}\n\nfunction parseAuthority(value: string) {\n if (value.trim() !== value || value.includes(\"@\")) {\n return null;\n }\n\n try {\n const parsed = new URL(`http://${value}`);\n\n if (\n !parsed.hostname ||\n parsed.pathname !== \"/\" ||\n parsed.search ||\n parsed.hash ||\n parsed.host.toLowerCase() !== value.toLowerCase()\n ) {\n return null;\n }\n\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction resolveProxyChain(\n peerAddress: string,\n forwardedFor: string | readonly string[] | undefined,\n trustProxy: TrustProxy,\n) {\n const forwarded = headerValues(forwardedFor);\n const chain = [...forwarded, peerAddress];\n\n if (trustProxy === false) {\n return { clientIp: peerAddress, forwardedDepth: 0 };\n }\n\n if (\"hops\" in trustProxy) {\n if (!Number.isSafeInteger(trustProxy.hops) || trustProxy.hops < 0) {\n throw new Error(\n \"Demiurge Node trustProxy hop count must be a non-negative integer.\",\n );\n }\n\n const clientHops = Math.min(trustProxy.hops, forwarded.length);\n\n return {\n clientIp: chain[chain.length - 1 - clientHops],\n forwardedDepth: trustProxy.hops,\n };\n }\n\n let index = chain.length - 1;\n let trustedHops = 0;\n\n while (\n index > 0 &&\n isAddressTrusted(chain[index], trustProxy.ranges)\n ) {\n index -= 1;\n trustedHops += 1;\n }\n\n return {\n clientIp: chain[index],\n forwardedDepth:\n trustedHops || (isAddressTrusted(peerAddress, trustProxy.ranges) ? 1 : 0),\n };\n}\n\nfunction selectForwardedValue(\n header: string | readonly string[] | undefined,\n trustedDepth: number,\n) {\n if (trustedDepth === 0) {\n return undefined;\n }\n\n const values = headerValues(header);\n\n if (values.length === 0) {\n return undefined;\n }\n\n return values[Math.max(0, values.length - trustedDepth)];\n}\n\nfunction headerValues(value: string | readonly string[] | undefined) {\n return (Array.isArray(value) ? value : [value])\n .flatMap((item) => item?.split(\",\") ?? [])\n .map((item) => item.trim())\n .filter(Boolean);\n}\n\nfunction isAddressTrusted(address: string, ranges: readonly string[]) {\n return ranges.some((range) => ipMatchesRange(address, range));\n}\n\nfunction ipMatchesRange(address: string, range: string) {\n const [networkValue, prefixValue] = range.split(\"/\");\n const addressBytes = ipBytes(normalizeIpAddress(address));\n const networkBytes = ipBytes(normalizeIpAddress(networkValue));\n\n if (!addressBytes || !networkBytes || addressBytes.length !== networkBytes.length) {\n if (!networkBytes) {\n throw new Error(`Demiurge Node trustProxy range \"${range}\" is invalid.`);\n }\n\n return false;\n }\n\n const maximumPrefix = addressBytes.length * 8;\n const prefix = prefixValue === undefined ? maximumPrefix : Number(prefixValue);\n\n if (!Number.isInteger(prefix) || prefix < 0 || prefix > maximumPrefix) {\n throw new Error(`Demiurge Node trustProxy range \"${range}\" is invalid.`);\n }\n\n for (let bit = 0; bit < prefix; bit += 1) {\n const mask = 1 << (7 - (bit % 8));\n\n if ((addressBytes[Math.floor(bit / 8)] & mask) !==\n (networkBytes[Math.floor(bit / 8)] & mask)) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction normalizeIpAddress(address: string | undefined) {\n if (!address) {\n return \"unknown\";\n }\n\n return address.startsWith(\"::ffff:\") ? address.slice(7) : address;\n}\n\nfunction ipBytes(address: string) {\n const version = isIP(address);\n\n if (version === 4) {\n return address.split(\".\").map(Number);\n }\n\n if (version !== 6) {\n return null;\n }\n\n const [left = \"\", right = \"\"] = address.split(\"::\");\n const leftGroups = left ? left.split(\":\") : [];\n const rightGroups = right ? right.split(\":\") : [];\n const missing = 8 - leftGroups.length - rightGroups.length;\n const groups = [\n ...leftGroups,\n ...Array.from({ length: missing }, () => \"0\"),\n ...rightGroups,\n ];\n\n return groups.flatMap((group) => {\n const value = Number.parseInt(group, 16);\n return [value >> 8, value & 255];\n });\n}\n\n// Shared by the Node adapter and the Vite dev middleware so a request the\n// Fetch layer cannot represent gets the same answer in both.\nexport function writeNotImplemented(serverResponse: ServerResponse) {\n serverResponse.statusCode = 501;\n serverResponse.setHeader(\"content-type\", \"text/plain; charset=utf-8\");\n serverResponse.end(\"Not Implemented\");\n}\n\nexport async function writeWebResponse(\n serverResponse: ServerResponse,\n webResponse: Response,\n) {\n // `Headers.forEach` joins repeated headers with a comma, which is wrong for\n // `set-cookie`: two cookies would arrive as one malformed header. Node's\n // `setHeader` takes an array for exactly this case.\n const cookies = getSetCookies(webResponse.headers);\n\n webResponse.headers.forEach((value, name) => {\n if (name === \"set-cookie\") {\n return;\n }\n\n serverResponse.setHeader(name, value);\n });\n\n if (cookies.length > 0) {\n serverResponse.setHeader(\"set-cookie\", cookies);\n }\n\n serverResponse.statusCode = webResponse.status;\n\n // An empty status text would otherwise overwrite Node's default reason\n // phrase with nothing at all.\n if (webResponse.statusText) {\n serverResponse.statusMessage = webResponse.statusText;\n }\n\n if (!webResponse.body) {\n serverResponse.end();\n return;\n }\n\n // `Readable.pipe()` does not destroy its source when the destination closes\n // or has an error. An aborted client can leave the source stream open. It can\n // also leave an associated file descriptor open. `pipeline` destroys the\n // source when either side closes.\n try {\n await pipeline(\n Readable.fromWeb(\n webResponse.body as unknown as import(\"node:stream/web\").ReadableStream,\n ),\n serverResponse,\n );\n } catch (error) {\n if (!isClientDisconnect(error)) {\n throw error;\n }\n }\n}\n\n// A client disconnect during a response is ordinary traffic, not a server\n// fault. A new throw would run the caller error path for each canceled download.\n// This path records a stack trace and creates an unused 500 response. An\n// unauthenticated client can cause this condition.\nconst clientDisconnectCodes = new Set([\n \"ECONNRESET\",\n \"EPIPE\",\n \"ERR_STREAM_DESTROYED\",\n \"ERR_STREAM_PREMATURE_CLOSE\",\n]);\n\nfunction isClientDisconnect(error: unknown) {\n return (\n error instanceof Error &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n clientDisconnectCodes.has(error.code)\n );\n}\n\nexport function toHeaders(headers: IncomingHttpHeaders) {\n const nextHeaders = new Headers();\n\n for (const [name, value] of Object.entries(headers)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n nextHeaders.append(name, item);\n }\n continue;\n }\n\n if (value) {\n nextHeaders.set(name, value);\n }\n }\n\n return nextHeaders;\n}\n\nfunction getSetCookies(headers: Headers) {\n const getSetCookie = (headers as Headers & {\n getSetCookie?: () => string[];\n }).getSetCookie;\n\n if (getSetCookie) {\n return getSetCookie.call(headers);\n }\n\n const combined = headers.get(\"set-cookie\");\n\n return combined ? splitSetCookies(combined) : [];\n}\n\nfunction splitSetCookies(value: string) {\n return value.split(/,\\s*(?=[^;,=\\s]+\\s*=)/);\n}\n","import { Transform } from \"node:stream\";\nimport { renderToPipeableStream } from \"react-dom/server\";\nimport { renderDocumentShell } from \"../document/render\";\nimport type { ScriptTag } from \"../document/scripts\";\nimport type { LoadedRouteMatch } from \"../router\";\nimport { createPageRenderTree } from \"../server/render-tree\";\nimport { createPageScriptContext } from \"../server/render-tree\";\nimport {\n renderPageResponse,\n type SsrRenderOptions,\n} from \"../server/ssr\";\n\nconst streamRootMarker = '<template data-demiurge-stream-root=\"\"></template>';\n\nexport function renderNodePageResponse(\n match: LoadedRouteMatch,\n options: SsrRenderOptions = {},\n) {\n return match.render.mode === \"streaming\"\n ? renderStreamingPageResponse(match, options)\n : renderPageResponse(match, options);\n}\n\nexport async function renderStreamingPageResponse(\n match: LoadedRouteMatch,\n options: SsrRenderOptions = {},\n) {\n if (options.signal?.aborted) {\n throw options.signal.reason;\n }\n\n const scripts = createPageScriptContext(match, options);\n const content = createPageRenderTree(match, scripts);\n\n return await new Promise<Response>((resolveResponse, rejectResponse) => {\n let completed = false;\n let cancelled = false;\n let responseCommitted = false;\n let documentSuffix = \"\";\n let stream = undefined as ReturnType<typeof renderToPipeableStream> | undefined;\n const documentStream = new Transform({\n destroy(error, callback) {\n if (!completed) {\n cancelled = true;\n }\n\n callback(error);\n },\n flush(callback) {\n callback(null, documentSuffix);\n },\n transform(chunk, _encoding, callback) {\n callback(null, chunk);\n },\n });\n const abort = () => {\n cancelled = true;\n stream?.abort(options.signal?.reason);\n documentStream.destroy();\n };\n const cleanup = () => options.signal?.removeEventListener(\"abort\", abort);\n\n documentStream.once(\"finish\", () => {\n completed = true;\n });\n documentStream.once(\"close\", () => {\n cleanup();\n\n if (!completed) {\n cancelled = true;\n stream?.abort(new Error(\"Demiurge streaming response was cancelled.\"));\n }\n });\n options.signal?.addEventListener(\"abort\", abort, { once: true });\n\n stream = renderToPipeableStream(content, {\n nonce: options.nonce,\n onError(error) {\n if (responseCommitted && !cancelled) {\n options.onStreamError?.(error);\n }\n },\n onShellError(error) {\n cleanup();\n rejectResponse(error);\n },\n onShellReady() {\n void (async () => {\n try {\n const shell = await createDocumentShell(match, {\n ...options,\n scripts: scripts.scripts(),\n });\n documentSuffix = shell.suffix;\n scripts.flushHead();\n documentStream.push(shell.prefix);\n responseCommitted = true;\n stream?.pipe(documentStream);\n resolveResponse(\n new Response(toWebReadableStream(documentStream), {\n headers: { \"content-type\": \"text/html; charset=utf-8\" },\n }),\n );\n } catch (error) {\n cleanup();\n stream?.abort(error);\n documentStream.destroy();\n rejectResponse(error);\n }\n })();\n },\n });\n });\n}\n\nexport function toWebReadableStream(stream: Transform) {\n let closed = false;\n let removeListeners = () => {};\n\n return new ReadableStream<Uint8Array>({\n cancel() {\n closed = true;\n removeListeners();\n stream.pause();\n stream.destroy();\n },\n pull() {\n stream.resume();\n },\n start(controller) {\n stream.on(\"data\", onData);\n stream.once(\"end\", onEnd);\n stream.once(\"error\", onError);\n stream.once(\"close\", onClose);\n\n function onData(chunk: Buffer) {\n if (closed) {\n return;\n }\n\n controller.enqueue(Uint8Array.from(chunk));\n\n if ((controller.desiredSize ?? 1) <= 0) {\n stream.pause();\n }\n }\n\n function onEnd() {\n if (!closed) {\n closed = true;\n cleanup();\n controller.close();\n }\n }\n\n function onError(error: Error) {\n if (!closed) {\n closed = true;\n cleanup();\n controller.error(error);\n }\n }\n\n function onClose() {\n if (!closed) {\n closed = true;\n cleanup();\n controller.close();\n }\n }\n\n function cleanup() {\n stream.off(\"data\", onData);\n stream.off(\"end\", onEnd);\n stream.off(\"error\", onError);\n stream.off(\"close\", onClose);\n }\n\n removeListeners = cleanup;\n },\n });\n}\n\nasync function createDocumentShell(\n match: LoadedRouteMatch,\n options: SsrRenderOptions & { scripts?: ScriptTag[] },\n) {\n const shell = renderDocumentShell({\n body: { data: match.data, navigation: options.navigation },\n entrySrc: options.clientEntry,\n lang: options.lang,\n links: match.links,\n metadata: match.metadata,\n nonce: options.nonce,\n scripts: options.scripts ?? match.scripts,\n styles: options.styles,\n title: options.title,\n });\n\n if (!options.transformDocument) {\n return shell;\n }\n\n const transformed = await options.transformDocument(\n `${shell.prefix}${streamRootMarker}${shell.suffix}`,\n );\n const markerIndex = transformed.indexOf(streamRootMarker);\n\n if (\n markerIndex === -1 ||\n transformed.indexOf(streamRootMarker, markerIndex + streamRootMarker.length) !== -1\n ) {\n throw new Error(\n \"Demiurge streaming document transform must preserve the root marker exactly once.\",\n );\n }\n\n return {\n prefix: transformed.slice(0, markerIndex),\n suffix: transformed.slice(markerIndex + streamRootMarker.length),\n };\n}\n"],"names":["forwardedHeaders","defaultTrustProxy","forbiddenMethods","UnsupportedMethodError","method","UntrustedHostError","host","validateNodeOriginPolicy","policy","parseAuthority","trustProxy","range","network","ipMatchesRange","toWebRequest","request","options","peerAddress","normalizeIpAddress","proxy","resolveProxyChain","forwardedProtocol","selectForwardedValue","protocol","resolveProtocol","authority","validateAllowedHost","origin","url","init","toHeaders","Readable","webRequest","setRequestConnectionMetadata","allowedHosts","candidate","expected","value","parsed","forwardedFor","forwarded","headerValues","chain","clientHops","index","trustedHops","isAddressTrusted","header","trustedDepth","values","item","address","ranges","networkValue","prefixValue","addressBytes","ipBytes","networkBytes","maximumPrefix","prefix","bit","mask","version","isIP","left","right","leftGroups","rightGroups","missing","group","writeNotImplemented","serverResponse","writeWebResponse","webResponse","cookies","getSetCookies","name","pipeline","error","isClientDisconnect","clientDisconnectCodes","headers","nextHeaders","getSetCookie","combined","splitSetCookies","streamRootMarker","renderNodePageResponse","match","renderStreamingPageResponse","renderPageResponse","scripts","createPageScriptContext","content","createPageRenderTree","resolveResponse","rejectResponse","completed","cancelled","responseCommitted","documentSuffix","stream","documentStream","Transform","callback","chunk","_encoding","abort","cleanup","renderToPipeableStream","shell","createDocumentShell","toWebReadableStream","closed","removeListeners","controller","onData","onEnd","onError","onClose","renderDocumentShell","transformed","markerIndex"],"mappings":"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"}
|