@reckona/mreact-router 0.0.188 → 0.0.190
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 +16 -3
- package/bin/mreact-router.js +23 -0
- package/dist/adapters/aws-lambda.d.ts +33 -13
- package/dist/adapters/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +128 -20
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/adapters/cloudflare.d.ts +18 -0
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/edge.d.ts +2 -0
- package/dist/adapters/edge.d.ts.map +1 -1
- package/dist/adapters/edge.js.map +1 -1
- package/dist/adapters/node.d.ts +16 -2
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js.map +1 -1
- package/dist/cache.d.ts +8 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +34 -13
- package/dist/cache.js.map +1 -1
- package/dist/cli-options.d.ts +1 -1
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +21 -3
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +19 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/link.d.ts +22 -1
- package/dist/link.d.ts.map +1 -1
- package/dist/link.js +130 -5
- package/dist/link.js.map +1 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +514 -517
- package/dist/render.js.map +1 -1
- package/dist/request.d.ts +10 -0
- package/dist/request.d.ts.map +1 -0
- package/dist/request.js +6 -0
- package/dist/request.js.map +1 -0
- package/dist/typed-routes.d.ts +4 -5
- package/dist/typed-routes.d.ts.map +1 -1
- package/dist/typed-routes.js.map +1 -1
- package/dist/vite.d.ts +6 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +4 -1
- package/dist/vite.js.map +1 -1
- package/package.json +19 -13
- package/src/adapters/aws-lambda.ts +227 -56
- package/src/adapters/cloudflare.ts +59 -0
- package/src/adapters/edge.ts +14 -0
- package/src/adapters/node.ts +44 -2
- package/src/cache.ts +39 -17
- package/src/cli-options.ts +28 -6
- package/src/client.ts +2 -1
- package/src/config.ts +10 -2
- package/src/index.ts +56 -10
- package/src/link.ts +205 -10
- package/src/render.ts +5 -7
- package/src/request.ts +35 -0
- package/src/typed-routes.ts +4 -4
- package/src/vite.ts +30 -1
|
@@ -22,8 +22,41 @@ import {
|
|
|
22
22
|
import type { AppRouterResponseHook } from "../render.js";
|
|
23
23
|
import type { RouterInstrumentation } from "../trace.js";
|
|
24
24
|
|
|
25
|
-
/** Re-exports
|
|
26
|
-
export type {
|
|
25
|
+
/** Re-exports cache contracts used by AWS Lambda handlers. */
|
|
26
|
+
export type { AppRouterCache, AppRouterCacheEntry } from "../cache.js";
|
|
27
|
+
/** Re-exports server action contracts used by AWS Lambda handlers. */
|
|
28
|
+
export type {
|
|
29
|
+
AppRouterAllowedServerAction,
|
|
30
|
+
AppRouterServerActionOptions,
|
|
31
|
+
} from "../actions.js";
|
|
32
|
+
/** Re-exports logger contracts used by AWS Lambda handlers. */
|
|
33
|
+
export type {
|
|
34
|
+
AppRouterCspInlineNonceWarningLogEvent,
|
|
35
|
+
AppRouterLogger,
|
|
36
|
+
AppRouterLogError,
|
|
37
|
+
AppRouterLogEvent,
|
|
38
|
+
AppRouterRenderTimingLogEvent,
|
|
39
|
+
AppRouterRequestEndLogEvent,
|
|
40
|
+
AppRouterRequestErrorLogEvent,
|
|
41
|
+
AppRouterRequestStartLogEvent,
|
|
42
|
+
AppRouterRequestTimingLogEvent,
|
|
43
|
+
AppRouterRuntime,
|
|
44
|
+
} from "../logger.js";
|
|
45
|
+
/** Re-exports response hook contracts used by AWS Lambda handlers. */
|
|
46
|
+
export type { AppRouterResponseHook, AppRouterResponseHookContext } from "../render.js";
|
|
47
|
+
/** Re-exports build contracts referenced by AWS Lambda handler options. */
|
|
48
|
+
export type { BuiltPrerenderedRoute } from "../build.js";
|
|
49
|
+
/** Re-exports router instrumentation hooks and events for AWS Lambda handlers. */
|
|
50
|
+
export type {
|
|
51
|
+
RouterInstrumentation,
|
|
52
|
+
RouterMiddlewareEndInstrumentationEvent,
|
|
53
|
+
RouterMiddlewareInstrumentationEvent,
|
|
54
|
+
RouterRequestEndInstrumentationEvent,
|
|
55
|
+
RouterRequestInstrumentationEvent,
|
|
56
|
+
RouterRouteEndInstrumentationEvent,
|
|
57
|
+
RouterRouteInstrumentationEvent,
|
|
58
|
+
RouterTraceContext,
|
|
59
|
+
} from "../trace.js";
|
|
27
60
|
/** Re-exports app-router import policy controls for AWS Lambda handlers. */
|
|
28
61
|
export type { AppRouterImportPolicy } from "../import-policy.js";
|
|
29
62
|
import {
|
|
@@ -36,6 +69,13 @@ import {
|
|
|
36
69
|
type ResponseSinkStrategy,
|
|
37
70
|
} from "../serve.js";
|
|
38
71
|
|
|
72
|
+
/** Re-exports request and rendering contracts used by AWS Lambda handlers. */
|
|
73
|
+
export type {
|
|
74
|
+
AppRouterPrerenderStore,
|
|
75
|
+
RequestHostPolicy,
|
|
76
|
+
ResponseSinkStrategy,
|
|
77
|
+
} from "../serve.js";
|
|
78
|
+
|
|
39
79
|
/**
|
|
40
80
|
* Represents the AWS API Gateway HTTP API v2 event consumed by buffered handlers.
|
|
41
81
|
*/
|
|
@@ -44,15 +84,15 @@ export interface AwsLambdaHttpEventV2 {
|
|
|
44
84
|
cookies?: string[] | undefined;
|
|
45
85
|
headers?: Record<string, string | undefined> | undefined;
|
|
46
86
|
isBase64Encoded?: boolean | undefined;
|
|
47
|
-
rawPath
|
|
48
|
-
rawQueryString
|
|
49
|
-
requestContext
|
|
50
|
-
http
|
|
51
|
-
method
|
|
87
|
+
rawPath: string;
|
|
88
|
+
rawQueryString: string;
|
|
89
|
+
requestContext: {
|
|
90
|
+
http: {
|
|
91
|
+
method: string;
|
|
52
92
|
protocol?: string | undefined;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
version
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
version: "2.0";
|
|
56
96
|
}
|
|
57
97
|
|
|
58
98
|
/**
|
|
@@ -156,6 +196,25 @@ export type AwsLambdaStreamingRequestHandler<TContext = unknown> = (
|
|
|
156
196
|
context: TContext,
|
|
157
197
|
) => Promise<void>;
|
|
158
198
|
|
|
199
|
+
const invalidAwsLambdaHttpEventV2Diagnostic =
|
|
200
|
+
'Expected an AWS Lambda HTTP API payload format 2.0 event with rawPath and requestContext.http.method.';
|
|
201
|
+
|
|
202
|
+
function invalidAwsLambdaHttpEventV2Result(): AwsLambdaHttpResultV2 {
|
|
203
|
+
return {
|
|
204
|
+
body: invalidAwsLambdaHttpEventV2Diagnostic,
|
|
205
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
206
|
+
isBase64Encoded: false,
|
|
207
|
+
statusCode: 400,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function invalidAwsLambdaHttpEventV2Response(): Response {
|
|
212
|
+
return new Response(invalidAwsLambdaHttpEventV2Diagnostic, {
|
|
213
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
214
|
+
status: 400,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
159
218
|
/**
|
|
160
219
|
* Creates a buffered AWS Lambda HTTP API v2 handler for built app-router output.
|
|
161
220
|
*
|
|
@@ -165,35 +224,75 @@ export function createAwsLambdaRequestHandler(
|
|
|
165
224
|
options: AwsLambdaRequestHandlerOptions,
|
|
166
225
|
): AwsLambdaRequestHandler {
|
|
167
226
|
warnIfImplicitHostTrust(options);
|
|
168
|
-
|
|
169
|
-
const runtimePreloadPromise = startAwsLambdaRuntimePreload(
|
|
170
|
-
options,
|
|
171
|
-
runtimeDirPromise,
|
|
172
|
-
"middleware",
|
|
173
|
-
);
|
|
174
|
-
void runtimePreloadPromise?.catch(() => {});
|
|
227
|
+
let handler: AwsLambdaRequestHandler | undefined;
|
|
175
228
|
|
|
176
|
-
return
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
229
|
+
return async (event) => {
|
|
230
|
+
try {
|
|
231
|
+
validateAwsLambdaHttpEventV2(event);
|
|
232
|
+
} catch {
|
|
233
|
+
return invalidAwsLambdaHttpEventV2Result();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
handler ??= (() => {
|
|
237
|
+
const runtimeDirPromise = prepareAwsLambdaRuntimeDir(options);
|
|
238
|
+
const runtimePreloadPromise = startAwsLambdaRuntimePreload(options, runtimeDirPromise, "middleware");
|
|
239
|
+
void runtimePreloadPromise?.catch(() => {});
|
|
240
|
+
return createAwsLambdaRequestHandlerFromRuntime(
|
|
241
|
+
options,
|
|
242
|
+
runtimeDirPromise,
|
|
243
|
+
runtimePreloadPromise,
|
|
244
|
+
"middleware",
|
|
245
|
+
);
|
|
246
|
+
})();
|
|
247
|
+
|
|
248
|
+
return await handler(event);
|
|
249
|
+
};
|
|
182
250
|
}
|
|
183
251
|
|
|
184
252
|
/**
|
|
185
|
-
* Creates a buffered AWS Lambda handler
|
|
253
|
+
* Creates a buffered AWS Lambda handler that starts full runtime preparation after the first valid event.
|
|
186
254
|
*
|
|
187
|
-
*
|
|
255
|
+
* Invalid events are rejected before runtime materialization or preload work begins.
|
|
188
256
|
*/
|
|
189
257
|
export async function createPreloadedAwsLambdaRequestHandler(
|
|
190
258
|
options: AwsLambdaRequestHandlerOptions,
|
|
191
259
|
): Promise<AwsLambdaRequestHandler> {
|
|
260
|
+
warnIfImplicitHostTrust(options);
|
|
261
|
+
let handler: AwsLambdaRequestHandler | undefined;
|
|
262
|
+
|
|
263
|
+
return async (event) => {
|
|
264
|
+
try {
|
|
265
|
+
validateAwsLambdaHttpEventV2(event);
|
|
266
|
+
} catch {
|
|
267
|
+
return invalidAwsLambdaHttpEventV2Result();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
handler ??= (() => {
|
|
271
|
+
const runtimeDirPromise = prepareAwsLambdaRuntimeDir(options);
|
|
272
|
+
const runtimePreloadPromise = startAwsLambdaRuntimePreload(options, runtimeDirPromise, "all");
|
|
273
|
+
void runtimePreloadPromise?.catch(() => {});
|
|
274
|
+
return createAwsLambdaRequestHandlerFromRuntime(
|
|
275
|
+
options,
|
|
276
|
+
runtimeDirPromise,
|
|
277
|
+
runtimePreloadPromise,
|
|
278
|
+
);
|
|
279
|
+
})();
|
|
280
|
+
|
|
281
|
+
return await handler(event);
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Explicitly materializes and preloads a built Lambda runtime before request handling.
|
|
287
|
+
*
|
|
288
|
+
* Call this during controlled Lambda initialization only when the extra startup work is preferable to first-valid-request latency. Request handlers always validate events before they start runtime work.
|
|
289
|
+
*/
|
|
290
|
+
export async function warmAwsLambdaRuntime(
|
|
291
|
+
options: AwsLambdaRequestHandlerOptions,
|
|
292
|
+
): Promise<void> {
|
|
192
293
|
warnIfImplicitHostTrust(options);
|
|
193
294
|
const runtimeDir = await prepareAwsLambdaRuntimeDir(options);
|
|
194
295
|
await preloadAwsLambdaRuntime(options, runtimeDir);
|
|
195
|
-
|
|
196
|
-
return createAwsLambdaRequestHandlerFromRuntime(options, Promise.resolve(runtimeDir));
|
|
197
296
|
}
|
|
198
297
|
|
|
199
298
|
function createAwsLambdaRequestHandlerFromRuntime(
|
|
@@ -203,6 +302,12 @@ function createAwsLambdaRequestHandlerFromRuntime(
|
|
|
203
302
|
defaultPreloadMode: AwsLambdaDefaultPreloadMode = "all",
|
|
204
303
|
): AwsLambdaRequestHandler {
|
|
205
304
|
return async (event) => {
|
|
305
|
+
try {
|
|
306
|
+
validateAwsLambdaHttpEventV2(event);
|
|
307
|
+
} catch {
|
|
308
|
+
return invalidAwsLambdaHttpEventV2Result();
|
|
309
|
+
}
|
|
310
|
+
|
|
206
311
|
const startedAt = logNow();
|
|
207
312
|
const phases = createAwsLambdaTimingPhases(options);
|
|
208
313
|
const eventToRequestStartedAt = phaseStartedAt(phases);
|
|
@@ -298,39 +403,75 @@ export function createAwsLambdaStreamingRequestHandler<TContext = unknown>(
|
|
|
298
403
|
): AwsLambdaStreamingRequestHandler<TContext> {
|
|
299
404
|
warnIfImplicitHostTrust(options);
|
|
300
405
|
const runtime = awsLambdaRuntime();
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
406
|
+
let handler: AwsLambdaStreamingRequestHandler<TContext> | undefined;
|
|
407
|
+
|
|
408
|
+
return runtime.streamifyResponse(async (event, responseStream, context) => {
|
|
409
|
+
try {
|
|
410
|
+
validateAwsLambdaHttpEventV2(event);
|
|
411
|
+
} catch {
|
|
412
|
+
await streamResponseToLambda(
|
|
413
|
+
invalidAwsLambdaHttpEventV2Response(),
|
|
414
|
+
responseStream,
|
|
415
|
+
runtime,
|
|
416
|
+
);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
handler ??= (() => {
|
|
421
|
+
const runtimeDirPromise = prepareAwsLambdaRuntimeDir(options);
|
|
422
|
+
const runtimePreloadPromise = startAwsLambdaRuntimePreload(options, runtimeDirPromise, "middleware");
|
|
423
|
+
void runtimePreloadPromise?.catch(() => {});
|
|
424
|
+
return createAwsLambdaStreamingRequestHandlerFromRuntime(
|
|
425
|
+
options,
|
|
426
|
+
runtime,
|
|
427
|
+
runtimeDirPromise,
|
|
428
|
+
runtimePreloadPromise,
|
|
429
|
+
"middleware",
|
|
430
|
+
);
|
|
431
|
+
})();
|
|
432
|
+
|
|
433
|
+
await handler(event, responseStream, context);
|
|
434
|
+
});
|
|
316
435
|
}
|
|
317
436
|
|
|
318
437
|
/**
|
|
319
|
-
* Creates a streaming AWS Lambda handler
|
|
438
|
+
* Creates a streaming AWS Lambda handler that starts full runtime preparation after the first valid event.
|
|
439
|
+
*
|
|
440
|
+
* Invalid events are rejected before runtime materialization or preload work begins.
|
|
320
441
|
*/
|
|
321
442
|
export async function createPreloadedAwsLambdaStreamingRequestHandler<TContext = unknown>(
|
|
322
443
|
options: AwsLambdaRequestHandlerOptions,
|
|
323
444
|
): Promise<AwsLambdaStreamingRequestHandler<TContext>> {
|
|
324
445
|
warnIfImplicitHostTrust(options);
|
|
325
446
|
const runtime = awsLambdaRuntime();
|
|
326
|
-
|
|
327
|
-
await preloadAwsLambdaRuntime(options, runtimeDir);
|
|
447
|
+
let handler: AwsLambdaStreamingRequestHandler<TContext> | undefined;
|
|
328
448
|
|
|
329
|
-
return
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
449
|
+
return runtime.streamifyResponse(async (event, responseStream, context) => {
|
|
450
|
+
try {
|
|
451
|
+
validateAwsLambdaHttpEventV2(event);
|
|
452
|
+
} catch {
|
|
453
|
+
await streamResponseToLambda(
|
|
454
|
+
invalidAwsLambdaHttpEventV2Response(),
|
|
455
|
+
responseStream,
|
|
456
|
+
runtime,
|
|
457
|
+
);
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
handler ??= (() => {
|
|
462
|
+
const runtimeDirPromise = prepareAwsLambdaRuntimeDir(options);
|
|
463
|
+
const runtimePreloadPromise = startAwsLambdaRuntimePreload(options, runtimeDirPromise, "all");
|
|
464
|
+
void runtimePreloadPromise?.catch(() => {});
|
|
465
|
+
return createAwsLambdaStreamingRequestHandlerFromRuntime<TContext>(
|
|
466
|
+
options,
|
|
467
|
+
runtime,
|
|
468
|
+
runtimeDirPromise,
|
|
469
|
+
runtimePreloadPromise,
|
|
470
|
+
);
|
|
471
|
+
})();
|
|
472
|
+
|
|
473
|
+
await handler(event, responseStream, context);
|
|
474
|
+
});
|
|
334
475
|
}
|
|
335
476
|
|
|
336
477
|
function startAwsLambdaRuntimePreload(
|
|
@@ -480,6 +621,17 @@ function createAwsLambdaStreamingRequestHandlerFromRuntime<TContext = unknown>(
|
|
|
480
621
|
defaultPreloadMode: AwsLambdaDefaultPreloadMode = "all",
|
|
481
622
|
): AwsLambdaStreamingRequestHandler<TContext> {
|
|
482
623
|
return runtime.streamifyResponse(async (event, responseStream, _context) => {
|
|
624
|
+
try {
|
|
625
|
+
validateAwsLambdaHttpEventV2(event);
|
|
626
|
+
} catch {
|
|
627
|
+
await streamResponseToLambda(
|
|
628
|
+
invalidAwsLambdaHttpEventV2Response(),
|
|
629
|
+
responseStream,
|
|
630
|
+
runtime,
|
|
631
|
+
);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
|
|
483
635
|
const startedAt = logNow();
|
|
484
636
|
const phases = createAwsLambdaTimingPhases(options);
|
|
485
637
|
const eventToRequestStartedAt = phaseStartedAt(phases);
|
|
@@ -647,6 +799,7 @@ function eventToRequest(
|
|
|
647
799
|
event: AwsLambdaHttpEventV2,
|
|
648
800
|
options: AwsLambdaRequestHandlerOptions,
|
|
649
801
|
): Request {
|
|
802
|
+
validateAwsLambdaHttpEventV2(event);
|
|
650
803
|
const headers = eventHeaders(event);
|
|
651
804
|
const rawHost = lambdaRequestHost(headers, options);
|
|
652
805
|
const host = resolveRequestHost({
|
|
@@ -656,12 +809,9 @@ function eventToRequest(
|
|
|
656
809
|
rawHost: rawHost ?? undefined,
|
|
657
810
|
});
|
|
658
811
|
const protocol = lambdaRequestProtocol(event, headers, options);
|
|
659
|
-
const rawPath = event.rawPath
|
|
660
|
-
const rawQueryString =
|
|
661
|
-
|
|
662
|
-
? ""
|
|
663
|
-
: `?${event.rawQueryString}`;
|
|
664
|
-
const method = event.requestContext?.http?.method ?? "GET";
|
|
812
|
+
const rawPath = event.rawPath;
|
|
813
|
+
const rawQueryString = event.rawQueryString === "" ? "" : `?${event.rawQueryString}`;
|
|
814
|
+
const method = event.requestContext.http.method;
|
|
665
815
|
const init: RequestInit = {
|
|
666
816
|
headers,
|
|
667
817
|
method,
|
|
@@ -675,6 +825,27 @@ function eventToRequest(
|
|
|
675
825
|
return new Request(`${protocol}://${host}${rawPath}${rawQueryString}`, init);
|
|
676
826
|
}
|
|
677
827
|
|
|
828
|
+
function validateAwsLambdaHttpEventV2(event: AwsLambdaHttpEventV2): void {
|
|
829
|
+
const candidate = event as unknown;
|
|
830
|
+
|
|
831
|
+
if (
|
|
832
|
+
typeof candidate !== "object" ||
|
|
833
|
+
candidate === null ||
|
|
834
|
+
(candidate as { version?: unknown }).version !== "2.0" ||
|
|
835
|
+
typeof (candidate as { rawPath?: unknown }).rawPath !== "string" ||
|
|
836
|
+
!(candidate as { rawPath: string }).rawPath.startsWith("/") ||
|
|
837
|
+
typeof (candidate as { rawQueryString?: unknown }).rawQueryString !== "string" ||
|
|
838
|
+
typeof (candidate as { requestContext?: unknown }).requestContext !== "object" ||
|
|
839
|
+
(candidate as { requestContext?: unknown }).requestContext === null ||
|
|
840
|
+
typeof ((candidate as { requestContext: { http?: unknown } }).requestContext.http) !== "object" ||
|
|
841
|
+
(candidate as { requestContext: { http?: unknown } }).requestContext.http === null ||
|
|
842
|
+
typeof ((candidate as { requestContext: { http: { method?: unknown } } }).requestContext.http.method) !== "string" ||
|
|
843
|
+
(candidate as { requestContext: { http: { method: string } } }).requestContext.http.method === ""
|
|
844
|
+
) {
|
|
845
|
+
throw new Error(invalidAwsLambdaHttpEventV2Diagnostic);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
678
849
|
function lambdaRequestHost(
|
|
679
850
|
headers: Headers,
|
|
680
851
|
options: AwsLambdaRequestHandlerOptions,
|
|
@@ -39,6 +39,65 @@ import type { AppRouterPrerenderStore } from "../serve.js";
|
|
|
39
39
|
import { emitRouterDevtoolsEvent } from "./devtools.js";
|
|
40
40
|
import { escapeHtmlAttribute, escapeHtmlText } from "@reckona/mreact-shared/html-escape";
|
|
41
41
|
|
|
42
|
+
/** Re-exports build manifest contracts used by Cloudflare handlers. */
|
|
43
|
+
export type {
|
|
44
|
+
BuiltPrerenderedRoute,
|
|
45
|
+
BuiltRouteSourceAnalysisSummary,
|
|
46
|
+
BuiltServerActionExpressionReference,
|
|
47
|
+
BuiltServerActionReference,
|
|
48
|
+
BuiltServerManifest,
|
|
49
|
+
BuiltServerModuleArtifact,
|
|
50
|
+
BuiltServerModuleOutput,
|
|
51
|
+
} from "../build.js";
|
|
52
|
+
/** Re-exports client manifest contracts used by Cloudflare handlers. */
|
|
53
|
+
export type { ClientRouteManifestEntry } from "../client.js";
|
|
54
|
+
/** Re-exports route cache policy contracts used by route manifests. */
|
|
55
|
+
export type { RouteCachePolicy } from "../cache.js";
|
|
56
|
+
/** Re-exports logger contracts used by Cloudflare handlers. */
|
|
57
|
+
export type {
|
|
58
|
+
AppRouterCspInlineNonceWarningLogEvent,
|
|
59
|
+
AppRouterLogger,
|
|
60
|
+
AppRouterLogError,
|
|
61
|
+
AppRouterLogEvent,
|
|
62
|
+
AppRouterRenderTimingLogEvent,
|
|
63
|
+
AppRouterRequestEndLogEvent,
|
|
64
|
+
AppRouterRequestErrorLogEvent,
|
|
65
|
+
AppRouterRequestStartLogEvent,
|
|
66
|
+
AppRouterRequestTimingLogEvent,
|
|
67
|
+
AppRouterRuntime,
|
|
68
|
+
} from "../logger.js";
|
|
69
|
+
/** Re-exports response hook contracts used by Cloudflare handlers. */
|
|
70
|
+
export type { AppRouterResponseHook, AppRouterResponseHookContext } from "../render.js";
|
|
71
|
+
/** Re-exports route contracts used by Cloudflare handlers. */
|
|
72
|
+
export type {
|
|
73
|
+
AppAssetRoute,
|
|
74
|
+
AppMetadataRoute,
|
|
75
|
+
AppRoute,
|
|
76
|
+
CompiledRouteMatcherEntry,
|
|
77
|
+
CompiledRouteMatcherArtifact,
|
|
78
|
+
CompiledRouteMatcherSegment,
|
|
79
|
+
PageRoute,
|
|
80
|
+
ServerRoute,
|
|
81
|
+
RouteSegment,
|
|
82
|
+
} from "../routes.js";
|
|
83
|
+
/** Re-exports prerender store contracts used by Cloudflare handlers. */
|
|
84
|
+
export type { AppRouterPrerenderStore } from "../serve.js";
|
|
85
|
+
/** Re-exports metadata contracts used by Cloudflare route modules. */
|
|
86
|
+
export type {
|
|
87
|
+
GenerateMetadataContext,
|
|
88
|
+
MetadataImage,
|
|
89
|
+
MetadataScalar,
|
|
90
|
+
MetadataThemeColor,
|
|
91
|
+
MetadataViewport,
|
|
92
|
+
RouteHeadDescriptor,
|
|
93
|
+
RouteMetadata,
|
|
94
|
+
RouteParams,
|
|
95
|
+
RouteSecurityHeaders,
|
|
96
|
+
RouteStrictTransportSecurity,
|
|
97
|
+
} from "../types.js";
|
|
98
|
+
/** Re-exports file convention contracts used by Cloudflare route manifests. */
|
|
99
|
+
export type { AppFileConvention } from "../file-conventions.js";
|
|
100
|
+
|
|
42
101
|
/**
|
|
43
102
|
* Represents the Cloudflare Worker execution context used by router handlers.
|
|
44
103
|
*/
|
package/src/adapters/edge.ts
CHANGED
|
@@ -8,6 +8,20 @@ import {
|
|
|
8
8
|
type AppRouterLogger,
|
|
9
9
|
} from "../logger.js";
|
|
10
10
|
|
|
11
|
+
/** Re-exports the logger contract used by edge handlers. */
|
|
12
|
+
export type {
|
|
13
|
+
AppRouterCspInlineNonceWarningLogEvent,
|
|
14
|
+
AppRouterLogger,
|
|
15
|
+
AppRouterLogError,
|
|
16
|
+
AppRouterLogEvent,
|
|
17
|
+
AppRouterRenderTimingLogEvent,
|
|
18
|
+
AppRouterRequestEndLogEvent,
|
|
19
|
+
AppRouterRequestErrorLogEvent,
|
|
20
|
+
AppRouterRequestStartLogEvent,
|
|
21
|
+
AppRouterRequestTimingLogEvent,
|
|
22
|
+
AppRouterRuntime,
|
|
23
|
+
} from "../logger.js";
|
|
24
|
+
|
|
11
25
|
/**
|
|
12
26
|
* Handles one standard Web `Request` in an edge runtime.
|
|
13
27
|
*/
|
package/src/adapters/node.ts
CHANGED
|
@@ -15,8 +15,43 @@ import {
|
|
|
15
15
|
import type { AppRouterResponseHook } from "../render.js";
|
|
16
16
|
import type { RouterInstrumentation } from "../trace.js";
|
|
17
17
|
|
|
18
|
-
/** Re-exports
|
|
19
|
-
export type {
|
|
18
|
+
/** Re-exports cache contracts used by Node handlers. */
|
|
19
|
+
export type { AppRouterCache, AppRouterCacheEntry } from "../cache.js";
|
|
20
|
+
/** Re-exports server action contracts used by Node handlers. */
|
|
21
|
+
export type {
|
|
22
|
+
AppRouterAllowedServerAction,
|
|
23
|
+
AppRouterServerActionOptions,
|
|
24
|
+
} from "../actions.js";
|
|
25
|
+
/** Re-exports import policy contracts used by Node handlers. */
|
|
26
|
+
export type { AppRouterImportPolicy } from "../import-policy.js";
|
|
27
|
+
/** Re-exports logger contracts used by Node handlers. */
|
|
28
|
+
export type {
|
|
29
|
+
AppRouterCspInlineNonceWarningLogEvent,
|
|
30
|
+
AppRouterLogger,
|
|
31
|
+
AppRouterLogError,
|
|
32
|
+
AppRouterLogEvent,
|
|
33
|
+
AppRouterRenderTimingLogEvent,
|
|
34
|
+
AppRouterRequestEndLogEvent,
|
|
35
|
+
AppRouterRequestErrorLogEvent,
|
|
36
|
+
AppRouterRequestStartLogEvent,
|
|
37
|
+
AppRouterRequestTimingLogEvent,
|
|
38
|
+
AppRouterRuntime,
|
|
39
|
+
} from "../logger.js";
|
|
40
|
+
/** Re-exports response hook contracts used by Node handlers. */
|
|
41
|
+
export type { AppRouterResponseHook, AppRouterResponseHookContext } from "../render.js";
|
|
42
|
+
/** Re-exports build contracts referenced by Node handler options. */
|
|
43
|
+
export type { BuiltPrerenderedRoute } from "../build.js";
|
|
44
|
+
/** Re-exports router instrumentation hooks and events for Node handlers. */
|
|
45
|
+
export type {
|
|
46
|
+
RouterInstrumentation,
|
|
47
|
+
RouterMiddlewareEndInstrumentationEvent,
|
|
48
|
+
RouterMiddlewareInstrumentationEvent,
|
|
49
|
+
RouterRequestEndInstrumentationEvent,
|
|
50
|
+
RouterRequestInstrumentationEvent,
|
|
51
|
+
RouterRouteEndInstrumentationEvent,
|
|
52
|
+
RouterRouteInstrumentationEvent,
|
|
53
|
+
RouterTraceContext,
|
|
54
|
+
} from "../trace.js";
|
|
20
55
|
import {
|
|
21
56
|
renderBuiltAppRequest,
|
|
22
57
|
resolveRequestHost,
|
|
@@ -26,6 +61,13 @@ import {
|
|
|
26
61
|
type ResponseSinkStrategy,
|
|
27
62
|
} from "../serve.js";
|
|
28
63
|
|
|
64
|
+
/** Re-exports request and rendering contracts used by Node handlers. */
|
|
65
|
+
export type {
|
|
66
|
+
AppRouterPrerenderStore,
|
|
67
|
+
RequestHostPolicy,
|
|
68
|
+
ResponseSinkStrategy,
|
|
69
|
+
} from "../serve.js";
|
|
70
|
+
|
|
29
71
|
/**
|
|
30
72
|
* Configures a Node request handler for built app-router output.
|
|
31
73
|
*/
|
package/src/cache.ts
CHANGED
|
@@ -58,6 +58,7 @@ interface AppRouterCacheState {
|
|
|
58
58
|
interface RouteCacheContext {
|
|
59
59
|
cache: AppRouterCache;
|
|
60
60
|
cachePolicy?: RouteCachePolicy | undefined;
|
|
61
|
+
closed?: boolean | undefined;
|
|
61
62
|
revalidatedPaths: Set<string>;
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -472,15 +473,20 @@ export async function withRouteCacheContext<T>(
|
|
|
472
473
|
};
|
|
473
474
|
|
|
474
475
|
return cacheState.storage.run(context, async () => {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
476
|
+
try {
|
|
477
|
+
const value = await fn();
|
|
478
|
+
context.closed = true;
|
|
479
|
+
const cachePolicy = context.cachePolicy;
|
|
480
|
+
const revalidatedPaths = Array.from(context.revalidatedPaths);
|
|
478
481
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
+
for (const path of revalidatedPaths) {
|
|
483
|
+
await context.cache.deleteByPath(path);
|
|
484
|
+
}
|
|
482
485
|
|
|
483
|
-
|
|
486
|
+
return { cachePolicy, revalidatedPaths, value };
|
|
487
|
+
} finally {
|
|
488
|
+
context.closed = true;
|
|
489
|
+
}
|
|
484
490
|
});
|
|
485
491
|
}
|
|
486
492
|
|
|
@@ -500,15 +506,17 @@ export function beginRouteCacheContext(cache: AppRouterCache | undefined): {
|
|
|
500
506
|
return context.cachePolicy;
|
|
501
507
|
},
|
|
502
508
|
async dispose() {
|
|
509
|
+
context.closed = true;
|
|
503
510
|
const revalidatedPaths = Array.from(context.revalidatedPaths);
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
511
|
+
try {
|
|
512
|
+
for (const path of revalidatedPaths) {
|
|
513
|
+
await context.cache.deleteByPath(path);
|
|
514
|
+
}
|
|
515
|
+
} finally {
|
|
516
|
+
const index = cacheState.activeContexts.lastIndexOf(context);
|
|
517
|
+
if (index !== -1) {
|
|
518
|
+
cacheState.activeContexts.splice(index, 1);
|
|
519
|
+
}
|
|
512
520
|
}
|
|
513
521
|
|
|
514
522
|
return { revalidatedPaths };
|
|
@@ -516,8 +524,22 @@ export function beginRouteCacheContext(cache: AppRouterCache | undefined): {
|
|
|
516
524
|
};
|
|
517
525
|
}
|
|
518
526
|
|
|
519
|
-
function activeRouteCacheContext(): RouteCacheContext | undefined {
|
|
520
|
-
|
|
527
|
+
export function activeRouteCacheContext(): RouteCacheContext | undefined {
|
|
528
|
+
const asyncContext = cacheState.storage.getStore();
|
|
529
|
+
|
|
530
|
+
if (asyncContext !== undefined) {
|
|
531
|
+
return asyncContext.closed === true ? undefined : asyncContext;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
for (let index = cacheState.activeContexts.length - 1; index >= 0; index -= 1) {
|
|
535
|
+
const context = cacheState.activeContexts[index];
|
|
536
|
+
|
|
537
|
+
if (context?.closed !== true) {
|
|
538
|
+
return context;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return undefined;
|
|
521
543
|
}
|
|
522
544
|
|
|
523
545
|
// Host is excluded from the cache key to prevent attacker-supplied Host
|