@chidchanun/bcp 0.1.8 → 0.1.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 +82 -0
- package/README.md +218 -7
- package/docs/application-modules.md +63 -3
- package/docs/releasing.md +34 -19
- package/docs/route-guards.md +240 -0
- package/docs/server-data-loaders.md +240 -0
- package/docs/updating.md +130 -0
- package/package.json +1 -1
- package/packages/bundler/src/server-production-guards.ts +497 -0
- package/packages/bundler/src/server-production-middleware.ts +33 -8
- package/packages/bundler/src/server-production.ts +25 -0
- package/packages/cli/src/args.ts +58 -0
- package/packages/cli/src/index.ts +41 -13
- package/packages/cli/src/update.ts +860 -0
- package/packages/client/src/index.tsx +5 -0
- package/packages/client/src/loader-data.tsx +229 -0
- package/packages/client/src/router-v2.tsx +254 -29
- package/packages/server/src/dev-navigation-target.ts +188 -0
- package/packages/server/src/index.ts +209 -119
- package/packages/server/src/navigation-payload.ts +24 -1
- package/packages/server/src/navigation-response.ts +284 -0
- package/packages/server/src/page-guard.ts +529 -0
- package/packages/server/src/page-loader.ts +643 -0
- package/packages/server/src/standalone-production-runtime-v2-guard.ts +815 -0
- package/packages/server/src/standalone-production-runtime-v2-navigation.ts +785 -0
- package/packages/server/src/standalone-production-runtime-v2.ts +131 -19
- package/packages/server/src/standalone-production-runtime-v3.ts +1 -1
- package/packages/server/src/standalone-production-runtime-v4.ts +42 -2
- package/packages/server/src/static-dev-server.ts +21 -17
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import * as http from "node:http";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
appendVary,
|
|
5
|
+
compressDynamicContent,
|
|
6
|
+
selectContentEncoding,
|
|
7
|
+
} from "./compression.js";
|
|
8
|
+
|
|
9
|
+
export interface NavigationRedirectPayload {
|
|
10
|
+
redirect: {
|
|
11
|
+
location: string;
|
|
12
|
+
status: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createNavigationJsonResponse(
|
|
17
|
+
value: unknown,
|
|
18
|
+
init: ResponseInit = {}
|
|
19
|
+
): Response {
|
|
20
|
+
const headers =
|
|
21
|
+
new Headers(
|
|
22
|
+
init.headers
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
if (
|
|
26
|
+
!headers.has(
|
|
27
|
+
"Cache-Control"
|
|
28
|
+
)
|
|
29
|
+
) {
|
|
30
|
+
headers.set(
|
|
31
|
+
"Cache-Control",
|
|
32
|
+
"no-store"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (
|
|
37
|
+
!headers.has(
|
|
38
|
+
"X-Content-Type-Options"
|
|
39
|
+
)
|
|
40
|
+
) {
|
|
41
|
+
headers.set(
|
|
42
|
+
"X-Content-Type-Options",
|
|
43
|
+
"nosniff"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return Response.json(
|
|
48
|
+
value,
|
|
49
|
+
{
|
|
50
|
+
...init,
|
|
51
|
+
headers,
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createNavigationRedirectResponse(
|
|
57
|
+
response: Response
|
|
58
|
+
): Response | null {
|
|
59
|
+
if (
|
|
60
|
+
!isRedirectStatus(
|
|
61
|
+
response.status
|
|
62
|
+
)
|
|
63
|
+
) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const location =
|
|
68
|
+
response.headers.get(
|
|
69
|
+
"location"
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
if (!location) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const headers =
|
|
77
|
+
new Headers();
|
|
78
|
+
|
|
79
|
+
copySetCookieHeaders(
|
|
80
|
+
response.headers,
|
|
81
|
+
headers
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return createNavigationJsonResponse(
|
|
85
|
+
{
|
|
86
|
+
redirect: {
|
|
87
|
+
location,
|
|
88
|
+
status:
|
|
89
|
+
response.status,
|
|
90
|
+
},
|
|
91
|
+
} satisfies NavigationRedirectPayload,
|
|
92
|
+
{
|
|
93
|
+
status:
|
|
94
|
+
200,
|
|
95
|
+
headers,
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function sendNavigationWebResponse(
|
|
101
|
+
req: http.IncomingMessage,
|
|
102
|
+
res: http.ServerResponse,
|
|
103
|
+
response: Response
|
|
104
|
+
): Promise<void> {
|
|
105
|
+
res.statusCode =
|
|
106
|
+
response.status;
|
|
107
|
+
|
|
108
|
+
response.headers.forEach(
|
|
109
|
+
(
|
|
110
|
+
value,
|
|
111
|
+
key
|
|
112
|
+
) => {
|
|
113
|
+
const normalized =
|
|
114
|
+
key.toLowerCase();
|
|
115
|
+
|
|
116
|
+
if (
|
|
117
|
+
normalized ===
|
|
118
|
+
"set-cookie" ||
|
|
119
|
+
normalized ===
|
|
120
|
+
"content-length" ||
|
|
121
|
+
normalized ===
|
|
122
|
+
"content-encoding"
|
|
123
|
+
) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
res.setHeader(
|
|
128
|
+
key,
|
|
129
|
+
value
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
const cookies =
|
|
135
|
+
getSetCookieHeaders(
|
|
136
|
+
response.headers
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
if (
|
|
140
|
+
cookies.length > 0
|
|
141
|
+
) {
|
|
142
|
+
res.setHeader(
|
|
143
|
+
"Set-Cookie",
|
|
144
|
+
cookies
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (
|
|
149
|
+
response.status === 204 ||
|
|
150
|
+
response.status === 304
|
|
151
|
+
) {
|
|
152
|
+
res.end();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const rawBody =
|
|
157
|
+
Buffer.from(
|
|
158
|
+
await response.arrayBuffer()
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const contentType =
|
|
162
|
+
response.headers.get(
|
|
163
|
+
"content-type"
|
|
164
|
+
) ??
|
|
165
|
+
"application/octet-stream";
|
|
166
|
+
|
|
167
|
+
const existingEncoding =
|
|
168
|
+
response.headers.get(
|
|
169
|
+
"content-encoding"
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const encoding =
|
|
173
|
+
existingEncoding
|
|
174
|
+
? null
|
|
175
|
+
: selectContentEncoding(
|
|
176
|
+
req,
|
|
177
|
+
contentType,
|
|
178
|
+
rawBody.length
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const body =
|
|
182
|
+
existingEncoding
|
|
183
|
+
? rawBody
|
|
184
|
+
: compressDynamicContent(
|
|
185
|
+
rawBody,
|
|
186
|
+
encoding
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
if (existingEncoding) {
|
|
190
|
+
res.setHeader(
|
|
191
|
+
"Content-Encoding",
|
|
192
|
+
existingEncoding
|
|
193
|
+
);
|
|
194
|
+
} else if (encoding) {
|
|
195
|
+
res.setHeader(
|
|
196
|
+
"Content-Encoding",
|
|
197
|
+
encoding
|
|
198
|
+
);
|
|
199
|
+
res.setHeader(
|
|
200
|
+
"Vary",
|
|
201
|
+
appendVary(
|
|
202
|
+
res.getHeader(
|
|
203
|
+
"Vary"
|
|
204
|
+
)?.toString(),
|
|
205
|
+
"Accept-Encoding"
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
res.setHeader(
|
|
211
|
+
"Content-Length",
|
|
212
|
+
body.length
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (
|
|
216
|
+
(
|
|
217
|
+
req.method ??
|
|
218
|
+
"GET"
|
|
219
|
+
).toUpperCase() ===
|
|
220
|
+
"HEAD"
|
|
221
|
+
) {
|
|
222
|
+
res.end();
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
res.end(
|
|
227
|
+
body
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function copySetCookieHeaders(
|
|
232
|
+
source: Headers,
|
|
233
|
+
target: Headers
|
|
234
|
+
): void {
|
|
235
|
+
for (
|
|
236
|
+
const cookie
|
|
237
|
+
of getSetCookieHeaders(
|
|
238
|
+
source
|
|
239
|
+
)
|
|
240
|
+
) {
|
|
241
|
+
target.append(
|
|
242
|
+
"Set-Cookie",
|
|
243
|
+
cookie
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function getSetCookieHeaders(
|
|
249
|
+
headers: Headers
|
|
250
|
+
): string[] {
|
|
251
|
+
const extended =
|
|
252
|
+
headers as Headers & {
|
|
253
|
+
getSetCookie?: () =>
|
|
254
|
+
string[];
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const values =
|
|
258
|
+
extended.getSetCookie?.();
|
|
259
|
+
|
|
260
|
+
if (values) {
|
|
261
|
+
return values;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const fallback =
|
|
265
|
+
headers.get(
|
|
266
|
+
"set-cookie"
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
return fallback
|
|
270
|
+
? [fallback]
|
|
271
|
+
: [];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function isRedirectStatus(
|
|
275
|
+
status: number
|
|
276
|
+
): boolean {
|
|
277
|
+
return (
|
|
278
|
+
status === 301 ||
|
|
279
|
+
status === 302 ||
|
|
280
|
+
status === 303 ||
|
|
281
|
+
status === 307 ||
|
|
282
|
+
status === 308
|
|
283
|
+
);
|
|
284
|
+
}
|