@reckona/mreact-router 0.0.203 → 0.0.205
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 +53 -9
- package/dist/actions.d.ts +6 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +70 -10
- package/dist/actions.js.map +1 -1
- package/dist/adapters/aws-lambda.d.ts +15 -4
- package/dist/adapters/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +301 -63
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/adapters/cloudflare.d.ts +2 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +18 -10
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/edge.d.ts +1 -1
- package/dist/adapters/edge.d.ts.map +1 -1
- package/dist/adapters/edge.js.map +1 -1
- package/dist/adapters/node.d.ts +5 -3
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +2 -1
- package/dist/adapters/node.js.map +1 -1
- package/dist/adapters/static.d.ts.map +1 -1
- package/dist/adapters/static.js +24 -2
- package/dist/adapters/static.js.map +1 -1
- package/dist/build.d.ts +1 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +91 -5
- package/dist/build.js.map +1 -1
- package/dist/built-runtime.d.ts +2 -0
- package/dist/built-runtime.d.ts.map +1 -1
- package/dist/built-runtime.js +16 -0
- package/dist/built-runtime.js.map +1 -1
- package/dist/cache.d.ts +3 -1
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +211 -13
- package/dist/cache.js.map +1 -1
- package/dist/cli.js +12 -1
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +32 -1
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -2
- package/dist/config.js.map +1 -1
- package/dist/csp.d.ts +1 -0
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +11 -6
- package/dist/csp.js.map +1 -1
- package/dist/dehydrate-policy.d.ts +3 -0
- package/dist/dehydrate-policy.d.ts.map +1 -0
- package/dist/dehydrate-policy.js +16 -0
- package/dist/dehydrate-policy.js.map +1 -0
- package/dist/dev-server.d.ts +7 -2
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +120 -11
- package/dist/dev-server.js.map +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +147 -7
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +22 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +22 -8
- package/dist/logger.js.map +1 -1
- package/dist/metadata.d.ts +8 -0
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +60 -22
- package/dist/metadata.js.map +1 -1
- package/dist/navigation-marker.d.ts.map +1 -1
- package/dist/navigation-marker.js +72 -9
- package/dist/navigation-marker.js.map +1 -1
- package/dist/navigation.d.ts +1 -0
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +1 -1
- package/dist/navigation.js.map +1 -1
- package/dist/node-server.d.ts +5 -2
- package/dist/node-server.d.ts.map +1 -1
- package/dist/node-server.js +75 -6
- package/dist/node-server.js.map +1 -1
- package/dist/prerender-entry.d.ts +14 -0
- package/dist/prerender-entry.d.ts.map +1 -1
- package/dist/prerender-entry.js +40 -3
- package/dist/prerender-entry.js.map +1 -1
- package/dist/render.d.ts +9 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +102 -123
- package/dist/render.js.map +1 -1
- package/dist/serve.d.ts +8 -2
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +22 -20
- package/dist/serve.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +52 -19
- package/dist/session.js.map +1 -1
- package/dist/upgrade.d.ts +59 -2
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +282 -1
- package/dist/upgrade.js.map +1 -1
- package/dist/vite-config.d.ts +2 -0
- package/dist/vite-config.d.ts.map +1 -1
- package/dist/vite-config.js +2 -0
- package/dist/vite-config.js.map +1 -1
- package/dist/vite.d.ts +4 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +117 -6
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/actions.ts +81 -11
- package/src/adapters/aws-lambda.ts +426 -115
- package/src/adapters/cloudflare.ts +29 -13
- package/src/adapters/edge.ts +2 -0
- package/src/adapters/node.ts +8 -10
- package/src/adapters/static.ts +31 -2
- package/src/build.ts +117 -10
- package/src/built-runtime.ts +28 -0
- package/src/cache.ts +262 -15
- package/src/cli.ts +14 -1
- package/src/client.ts +32 -1
- package/src/config.ts +43 -6
- package/src/csp.ts +14 -11
- package/src/dehydrate-policy.ts +23 -0
- package/src/dev-server.ts +188 -15
- package/src/http.ts +172 -6
- package/src/index.ts +14 -1
- package/src/logger.ts +47 -10
- package/src/metadata.ts +125 -60
- package/src/navigation-marker.ts +79 -9
- package/src/navigation.ts +1 -1
- package/src/node-server.ts +128 -22
- package/src/prerender-entry.ts +52 -3
- package/src/render.ts +807 -753
- package/src/serve.ts +49 -56
- package/src/session.ts +56 -25
- package/src/upgrade.ts +402 -3
- package/src/vite-config.ts +6 -0
- package/src/vite.ts +157 -5
package/dist/adapters/node.js
CHANGED
|
@@ -29,13 +29,14 @@ export function createNodeRequestHandler(options) {
|
|
|
29
29
|
forwardedProto: incoming.headers["x-forwarded-proto"],
|
|
30
30
|
trustForwardedProto: options.trustForwardedProto,
|
|
31
31
|
});
|
|
32
|
-
const request = nodeRequestToWebRequest(incoming, `${protocol}://${host}
|
|
32
|
+
const request = nodeRequestToWebRequest(incoming, `${protocol}://${host}`, outgoing);
|
|
33
33
|
const logFields = requestLogFields(request, "node");
|
|
34
34
|
emitRouterLog(options.logger, "info", {
|
|
35
35
|
...logFields,
|
|
36
36
|
type: "router:request:start",
|
|
37
37
|
});
|
|
38
38
|
const response = await renderBuiltAppRequest({
|
|
39
|
+
dehydrateOptions: options.dehydrateOptions,
|
|
39
40
|
outDir: options.outDir,
|
|
40
41
|
importPolicy: options.importPolicy,
|
|
41
42
|
instrumentation: options.instrumentation,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AppRouterCache } from \"../cache.js\";\nimport { nodeRequestToWebRequest, sendResponse } from \"../http.js\";\nimport type { AppRouterServerActionOptions } from \"../actions.js\";\nimport type { AppRouterImportPolicy } from \"../import-policy.js\";\nimport {\n emitRouterLog,\n logDurationMs,\n logError,\n logNow,\n nodeRequestPath,\n requestLogFields,\n type AppRouterLogger,\n} from \"../logger.js\";\nimport type { AppRouterResponseHook } from \"../render.js\";\nimport type { RouterInstrumentation } from \"../trace.js\";\nimport { resolveNodeRequestProtocol } from \"../node-server.js\";\n\n/** Re-exports cache contracts used by Node handlers. */\nexport type { AppRouterCache, AppRouterCacheEntry } from \"../cache.js\";\n/** Re-exports server action contracts used by Node handlers. */\nexport type {\n AppRouterAllowedServerAction,\n AppRouterServerActionOptions,\n} from \"../actions.js\";\n/** Re-exports import policy contracts used by Node handlers. */\nexport type { AppRouterImportPolicy } from \"../import-policy.js\";\n/** Re-exports logger contracts used by Node handlers. */\nexport type {\n AppRouterCspInlineNonceWarningLogEvent,\n AppRouterLogger,\n AppRouterLogError,\n AppRouterLogEvent,\n AppRouterRenderTimingLogEvent,\n AppRouterRequestEndLogEvent,\n AppRouterRequestErrorLogEvent,\n AppRouterRequestStartLogEvent,\n AppRouterRequestTimingLogEvent,\n AppRouterRuntime,\n} from \"../logger.js\";\n/** Re-exports response hook contracts used by Node handlers. */\nexport type { AppRouterResponseHook, AppRouterResponseHookContext } from \"../render.js\";\n/** Re-exports build contracts referenced by Node handler options. */\nexport type { BuiltPrerenderedRoute } from \"../build.js\";\n/** Re-exports router instrumentation hooks and events for Node handlers. */\nexport type {\n RouterInstrumentation,\n RouterMiddlewareEndInstrumentationEvent,\n RouterMiddlewareInstrumentationEvent,\n RouterRequestEndInstrumentationEvent,\n RouterRequestInstrumentationEvent,\n RouterRouteEndInstrumentationEvent,\n RouterRouteInstrumentationEvent,\n RouterTraceContext,\n} from \"../trace.js\";\nimport {\n renderBuiltAppRequest,\n resolveRequestHost,\n warnIfImplicitHostTrust,\n type AppRouterPrerenderStore,\n type RequestHostPolicy,\n type ResponseSinkStrategy,\n} from \"../serve.js\";\n\n/** Re-exports request and rendering contracts used by Node handlers. */\nexport type {\n AppRouterPrerenderStore,\n RequestHostPolicy,\n ResponseSinkStrategy,\n} from \"../serve.js\";\n\n/**\n * Configures a Node request handler for built app-router output.\n */\nexport interface NodeRequestHandlerOptions {\n allowedHosts?: readonly string[] | undefined;\n errorHandler?:\n | ((error: unknown) => {\n body: string;\n headers?: Record<string, string>;\n status: number;\n })\n | undefined;\n hostPolicy?: RequestHostPolicy | undefined;\n hostname?: string | undefined;\n importPolicy?: AppRouterImportPolicy | undefined;\n instrumentation?: RouterInstrumentation | undefined;\n logger?: AppRouterLogger | undefined;\n onResponse?: AppRouterResponseHook | undefined;\n outDir: string;\n port?: number | undefined;\n prerenderStore?: AppRouterPrerenderStore | undefined;\n routeCache?: AppRouterCache | undefined;\n serverActions?: AppRouterServerActionOptions | undefined;\n sinkStrategy?: ResponseSinkStrategy | undefined;\n /**\n * Trusts the first `X-Forwarded-Proto` value when the socket is not TLS.\n *\n * Defaults to `false`. Enable only behind a proxy that overwrites the header\n * and prevents untrusted clients from reaching the Node listener directly.\n */\n trustForwardedProto?: boolean | undefined;\n}\n\n/**\n * Handles one Node HTTP request/response pair for built app-router output.\n */\nexport type NodeRequestHandler = (\n incoming: IncomingMessage,\n outgoing: ServerResponse,\n) => Promise<void>;\n\n/**\n * Creates a Node `IncomingMessage`/`ServerResponse` handler for built app-router output.\n *\n * The handler converts Node requests to Web `Request` objects, enforces configured host trust, applies the built renderer, and writes the Web `Response` back to the Node socket.\n */\nexport function createNodeRequestHandler(options: NodeRequestHandlerOptions): NodeRequestHandler {\n warnIfImplicitHostTrust(options);\n\n return async (incoming, outgoing) => {\n const startedAt = logNow();\n const fallbackRequestFields = {\n method: incoming.method ?? \"GET\",\n path: nodeRequestPath(incoming.url),\n runtime: \"node\" as const,\n };\n\n try {\n const fallbackHost = `${options.hostname ?? \"127.0.0.1\"}:${options.port ?? 80}`;\n const host = resolveRequestHost({\n allowedHosts: options.allowedHosts,\n fallbackHost,\n hostPolicy: options.hostPolicy,\n rawHost: incoming.headers.host,\n });\n const protocol = resolveNodeRequestProtocol({\n encrypted: (incoming.socket as { encrypted?: boolean }).encrypted === true,\n forwardedProto: incoming.headers[\"x-forwarded-proto\"],\n trustForwardedProto: options.trustForwardedProto,\n });\n const request = nodeRequestToWebRequest(incoming, `${protocol}://${host}`);\n const logFields = requestLogFields(request, \"node\");\n emitRouterLog(options.logger, \"info\", {\n ...logFields,\n type: \"router:request:start\",\n });\n const response = await renderBuiltAppRequest({\n outDir: options.outDir,\n importPolicy: options.importPolicy,\n instrumentation: options.instrumentation,\n logger: options.logger,\n onResponse: options.onResponse,\n prerenderStore: options.prerenderStore,\n request,\n routeCache: options.routeCache,\n serverActions: options.serverActions,\n ...(options.sinkStrategy === undefined ? {} : { sinkStrategy: options.sinkStrategy }),\n });\n emitRouterLog(options.logger, \"info\", {\n ...logFields,\n durationMs: logDurationMs(startedAt),\n status: response.status,\n type: \"router:request:end\",\n });\n\n await sendResponse(outgoing, response);\n } catch (error) {\n emitRouterLog(options.logger, \"error\", {\n ...fallbackRequestFields,\n durationMs: logDurationMs(startedAt),\n error: logError(error),\n type: \"router:request:error\",\n });\n const payload = options.errorHandler\n ? options.errorHandler(error)\n : { body: \"Internal Server Error\", status: 500 };\n outgoing.statusCode = payload.status;\n outgoing.setHeader(\n \"content-type\",\n payload.headers?.[\"content-type\"] ?? \"text/plain; charset=utf-8\",\n );\n\n for (const [name, value] of Object.entries(payload.headers ?? {})) {\n if (name.toLowerCase() !== \"content-type\") {\n outgoing.setHeader(name, value);\n }\n }\n\n outgoing.end(payload.body);\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGnE,OAAO,EACL,aAAa,EACb,aAAa,EACb,QAAQ,EACR,MAAM,EACN,eAAe,EACf,gBAAgB,GAEjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAsC/D,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,GAIxB,MAAM,aAAa,CAAC;AA+CrB;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAkC;IACzE,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEjC,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE;QAClC,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC;QAC3B,MAAM,qBAAqB,GAAG;YAC5B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,KAAK;YAChC,IAAI,EAAE,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC;YACnC,OAAO,EAAE,MAAe;SACzB,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,GAAG,OAAO,CAAC,QAAQ,IAAI,WAAW,IAAI,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YAChF,MAAM,IAAI,GAAG,kBAAkB,CAAC;gBAC9B,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,YAAY;gBACZ,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI;aAC/B,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,0BAA0B,CAAC;gBAC1C,SAAS,EAAG,QAAQ,CAAC,MAAkC,CAAC,SAAS,KAAK,IAAI;gBAC1E,cAAc,EAAE,QAAQ,CAAC,OAAO,CAAC,mBAAmB,CAAC;gBACrD,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;aACjD,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,EAAE,GAAG,QAAQ,MAAM,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC;YACrF,MAAM,SAAS,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACpD,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;gBACpC,GAAG,SAAS;gBACZ,IAAI,EAAE,sBAAsB;aAC7B,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC;gBAC3C,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;gBAC1C,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,eAAe,EAAE,OAAO,CAAC,eAAe;gBACxC,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,OAAO;gBACP,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;aACtF,CAAC,CAAC;YACH,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;gBACpC,GAAG,SAAS;gBACZ,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC;gBACpC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,IAAI,EAAE,oBAAoB;aAC3B,CAAC,CAAC;YAEH,MAAM,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;gBACrC,GAAG,qBAAqB;gBACxB,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC;gBACpC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;gBACtB,IAAI,EAAE,sBAAsB;aAC7B,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY;gBAClC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC;gBAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;YACnD,QAAQ,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;YACrC,QAAQ,CAAC,SAAS,CAChB,cAAc,EACd,OAAO,CAAC,OAAO,EAAE,CAAC,cAAc,CAAC,IAAI,2BAA2B,CACjE,CAAC;YAEF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;gBAClE,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc,EAAE,CAAC;oBAC1C,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;YAED,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { DehydrateOptions } from \"@reckona/mreact-query\";\nimport type { AppRouterCache } from \"../cache.js\";\nimport { nodeRequestToWebRequest, sendResponse } from \"../http.js\";\nimport type { AppRouterServerActionOptions } from \"../actions.js\";\nimport type { AppRouterImportPolicy } from \"../import-policy.js\";\nimport {\n emitRouterLog,\n logDurationMs,\n logError,\n logNow,\n nodeRequestPath,\n requestLogFields,\n type AppRouterLogger,\n} from \"../logger.js\";\nimport type { AppRouterResponseHook } from \"../render.js\";\nimport type { RouterInstrumentation } from \"../trace.js\";\nimport { resolveNodeRequestProtocol } from \"../node-server.js\";\n\n/** Re-exports cache contracts used by Node handlers. */\nexport type { AppRouterCache, AppRouterCacheEntry } from \"../cache.js\";\n/** Re-exports server action contracts used by Node handlers. */\nexport type { AppRouterAllowedServerAction, AppRouterServerActionOptions } from \"../actions.js\";\n/** Re-exports import policy contracts used by Node handlers. */\nexport type { AppRouterImportPolicy } from \"../import-policy.js\";\n/** Re-exports logger contracts used by Node handlers. */\nexport type {\n AppRouterCspInlineNonceWarningLogEvent,\n AppRouterLogger,\n AppRouterLogError,\n AppRouterLogEvent,\n AppRouterRenderTimingLogEvent,\n AppRouterRequestEndLogEvent,\n AppRouterRequestErrorLogEvent,\n AppRouterRequestStartLogEvent,\n AppRouterRequestTimingLogEvent,\n AppRouterRuntime,\n AppRouterUpgradeErrorLogEvent,\n AppRouterUpgradeRejectedLogEvent,\n} from \"../logger.js\";\n/** Re-exports response hook contracts used by Node handlers. */\nexport type { AppRouterResponseHook, AppRouterResponseHookContext } from \"../render.js\";\n/** Re-exports build contracts referenced by Node handler options. */\nexport type { BuiltPrerenderedRoute } from \"../build.js\";\n/** Re-exports router instrumentation hooks and events for Node handlers. */\nexport type {\n RouterInstrumentation,\n RouterMiddlewareEndInstrumentationEvent,\n RouterMiddlewareInstrumentationEvent,\n RouterRequestEndInstrumentationEvent,\n RouterRequestInstrumentationEvent,\n RouterRouteEndInstrumentationEvent,\n RouterRouteInstrumentationEvent,\n RouterTraceContext,\n} from \"../trace.js\";\nimport {\n renderBuiltAppRequest,\n resolveRequestHost,\n warnIfImplicitHostTrust,\n type AppRouterPrerenderStore,\n type RequestHostPolicy,\n type ResponseSinkStrategy,\n} from \"../serve.js\";\n\n/** Re-exports request and rendering contracts used by Node handlers. */\nexport type { AppRouterPrerenderStore, RequestHostPolicy, ResponseSinkStrategy } from \"../serve.js\";\n\n/**\n * Configures a Node request handler for built app-router output.\n */\nexport interface NodeRequestHandlerOptions {\n allowedHosts?: readonly string[] | undefined;\n dehydrateOptions?: DehydrateOptions | undefined;\n errorHandler?:\n | ((error: unknown) => {\n body: string;\n headers?: Record<string, string>;\n status: number;\n })\n | undefined;\n hostPolicy?: RequestHostPolicy | undefined;\n hostname?: string | undefined;\n importPolicy?: AppRouterImportPolicy | undefined;\n instrumentation?: RouterInstrumentation | undefined;\n logger?: AppRouterLogger | undefined;\n onResponse?: AppRouterResponseHook | undefined;\n outDir: string;\n port?: number | undefined;\n prerenderStore?: AppRouterPrerenderStore | undefined;\n routeCache?: AppRouterCache | undefined;\n serverActions?: AppRouterServerActionOptions | undefined;\n sinkStrategy?: ResponseSinkStrategy | undefined;\n /**\n * Trusts the first `X-Forwarded-Proto` value when the socket is not TLS.\n *\n * Defaults to `false`. Enable only behind a proxy that overwrites the header\n * and prevents untrusted clients from reaching the Node listener directly.\n */\n trustForwardedProto?: boolean | undefined;\n}\n\n/**\n * Handles one Node HTTP request/response pair for built app-router output.\n */\nexport type NodeRequestHandler = (\n incoming: IncomingMessage,\n outgoing: ServerResponse,\n) => Promise<void>;\n\n/**\n * Creates a Node `IncomingMessage`/`ServerResponse` handler for built app-router output.\n *\n * The handler converts Node requests to Web `Request` objects, enforces configured host trust, applies the built renderer, and writes the Web `Response` back to the Node socket.\n */\nexport function createNodeRequestHandler(options: NodeRequestHandlerOptions): NodeRequestHandler {\n warnIfImplicitHostTrust(options);\n\n return async (incoming, outgoing) => {\n const startedAt = logNow();\n const fallbackRequestFields = {\n method: incoming.method ?? \"GET\",\n path: nodeRequestPath(incoming.url),\n runtime: \"node\" as const,\n };\n\n try {\n const fallbackHost = `${options.hostname ?? \"127.0.0.1\"}:${options.port ?? 80}`;\n const host = resolveRequestHost({\n allowedHosts: options.allowedHosts,\n fallbackHost,\n hostPolicy: options.hostPolicy,\n rawHost: incoming.headers.host,\n });\n const protocol = resolveNodeRequestProtocol({\n encrypted: (incoming.socket as { encrypted?: boolean }).encrypted === true,\n forwardedProto: incoming.headers[\"x-forwarded-proto\"],\n trustForwardedProto: options.trustForwardedProto,\n });\n const request = nodeRequestToWebRequest(incoming, `${protocol}://${host}`, outgoing);\n const logFields = requestLogFields(request, \"node\");\n emitRouterLog(options.logger, \"info\", {\n ...logFields,\n type: \"router:request:start\",\n });\n const response = await renderBuiltAppRequest({\n dehydrateOptions: options.dehydrateOptions,\n outDir: options.outDir,\n importPolicy: options.importPolicy,\n instrumentation: options.instrumentation,\n logger: options.logger,\n onResponse: options.onResponse,\n prerenderStore: options.prerenderStore,\n request,\n routeCache: options.routeCache,\n serverActions: options.serverActions,\n ...(options.sinkStrategy === undefined ? {} : { sinkStrategy: options.sinkStrategy }),\n });\n emitRouterLog(options.logger, \"info\", {\n ...logFields,\n durationMs: logDurationMs(startedAt),\n status: response.status,\n type: \"router:request:end\",\n });\n\n await sendResponse(outgoing, response);\n } catch (error) {\n emitRouterLog(options.logger, \"error\", {\n ...fallbackRequestFields,\n durationMs: logDurationMs(startedAt),\n error: logError(error),\n type: \"router:request:error\",\n });\n const payload = options.errorHandler\n ? options.errorHandler(error)\n : { body: \"Internal Server Error\", status: 500 };\n outgoing.statusCode = payload.status;\n outgoing.setHeader(\n \"content-type\",\n payload.headers?.[\"content-type\"] ?? \"text/plain; charset=utf-8\",\n );\n\n for (const [name, value] of Object.entries(payload.headers ?? {})) {\n if (name.toLowerCase() !== \"content-type\") {\n outgoing.setHeader(name, value);\n }\n }\n\n outgoing.end(payload.body);\n }\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/adapters/static.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/adapters/static.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA6C/F"}
|
package/dist/adapters/static.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join, resolve, sep } from "node:path";
|
|
3
|
-
import { isCurrentPrerenderedRoute } from "../prerender-entry.js";
|
|
3
|
+
import { isCurrentPrerenderedRoute, validatedPrerenderedNavigationHtml, } from "../prerender-entry.js";
|
|
4
|
+
const staticNavigationBase = "/_mreact/navigation";
|
|
5
|
+
const staticNavigationMetadata = `<meta name="mreact-static-navigation" content="${staticNavigationBase}">`;
|
|
4
6
|
/**
|
|
5
7
|
* Exports prerendered app-router routes and client assets to a static filesystem directory.
|
|
6
8
|
*
|
|
@@ -56,8 +58,28 @@ async function writePrerenderedRoute(exportDir, route, entry) {
|
|
|
56
58
|
throw new Error(`Cannot export route ${route} with status ${entry.status}.`);
|
|
57
59
|
}
|
|
58
60
|
const file = routeToHtmlFile(exportDir, route);
|
|
61
|
+
const navigationHtml = validatedPrerenderedNavigationHtml(entry);
|
|
62
|
+
if (navigationHtml === undefined) {
|
|
63
|
+
throw new Error(`Cannot export route ${route} without a valid navigation variant.`);
|
|
64
|
+
}
|
|
65
|
+
const navigationFile = routeToHtmlFile(join(exportDir, staticNavigationBase), route);
|
|
59
66
|
await mkdir(dirname(file), { recursive: true });
|
|
60
|
-
await
|
|
67
|
+
await mkdir(dirname(navigationFile), { recursive: true });
|
|
68
|
+
await writeFile(file, withStaticNavigationMetadata(entry.html));
|
|
69
|
+
await writeFile(navigationFile, navigationHtml);
|
|
70
|
+
}
|
|
71
|
+
function withStaticNavigationMetadata(html) {
|
|
72
|
+
const head = /<head(?:\s[^>]*)?>/i.exec(html);
|
|
73
|
+
if (head?.index !== undefined) {
|
|
74
|
+
const insertion = head.index + head[0].length;
|
|
75
|
+
return `${html.slice(0, insertion)}${staticNavigationMetadata}${html.slice(insertion)}`;
|
|
76
|
+
}
|
|
77
|
+
const doctype = /^\s*<!doctype\s+html\s*>/i.exec(html);
|
|
78
|
+
if (doctype !== null) {
|
|
79
|
+
const insertion = doctype[0].length;
|
|
80
|
+
return `${html.slice(0, insertion)}${staticNavigationMetadata}${html.slice(insertion)}`;
|
|
81
|
+
}
|
|
82
|
+
return `${staticNavigationMetadata}${html}`;
|
|
61
83
|
}
|
|
62
84
|
function routeToHtmlFile(exportDir, route) {
|
|
63
85
|
const pathname = route.split("?")[0] ?? "/";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/adapters/static.ts"],"names":[],"mappings":"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","sourcesContent":["import { cp, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport type { BuiltPrerenderedRoute, BuiltServerManifest } from \"../build.js\";\nimport { isCurrentPrerenderedRoute } from \"../prerender-entry.js\";\n\n/**\n * Configures static export from a built app-router output directory.\n */\nexport interface StaticExportOptions {\n exportDir: string;\n outDir: string;\n paths?: readonly string[] | undefined;\n}\n\n/**\n * Lists the routes written by a static app-router export.\n */\nexport interface StaticExportResult {\n routes: string[];\n}\n\n/**\n * Exports prerendered app-router routes and client assets to a static filesystem directory.\n *\n * Only routes present in the built prerender manifest can be exported; the export directory is removed and recreated, and route paths are checked to prevent traversal outside it.\n */\nexport async function exportStaticApp(options: StaticExportOptions): Promise<StaticExportResult> {\n const manifest = JSON.parse(\n await readFile(join(options.outDir, \"server\", \"manifest.json\"), \"utf8\"),\n ) as BuiltServerManifest;\n const clientManifest = JSON.parse(\n await readFile(join(options.outDir, \"client\", \"manifest.json\"), \"utf8\"),\n ) as { publicAssets?: readonly string[] };\n const prerenderedRoutes = manifest.prerenderedRoutes ?? {};\n const routes = [...(options.paths ?? Object.keys(prerenderedRoutes))].sort();\n const entries = routes.map((route): readonly [string, BuiltPrerenderedRoute] => {\n routeToHtmlFile(options.exportDir, route);\n const entry = prerenderedRoutes[route];\n\n if (entry === undefined) {\n throw new Error(`Cannot export non-prerendered route: ${route}`);\n }\n\n if (!isCurrentPrerenderedRoute(entry)) {\n throw new Error(`Cannot export invalid prerendered route: ${route}`);\n }\n\n if (entry.status < 200 || entry.status >= 300) {\n throw new Error(`Cannot export route ${route} with status ${entry.status}.`);\n }\n\n return [route, entry];\n });\n\n await rm(options.exportDir, { force: true, recursive: true });\n await mkdir(options.exportDir, { recursive: true });\n\n for (const [route, entry] of entries) {\n await writePrerenderedRoute(options.exportDir, route, entry);\n }\n\n await cp(join(options.outDir, \"client\"), join(options.exportDir, \"_mreact\", \"client\"), {\n recursive: true,\n });\n await copyPublicAssetsToExportRoot(\n join(options.outDir, \"client\"),\n options.exportDir,\n clientManifest.publicAssets ?? [],\n );\n\n return { routes };\n}\n\nasync function copyPublicAssetsToExportRoot(\n clientDir: string,\n exportDir: string,\n publicAssets: readonly string[],\n): Promise<void> {\n for (const asset of publicAssets) {\n if (\n !asset.startsWith(\"/\") ||\n asset.startsWith(\"//\") ||\n asset.includes(\"..\") ||\n asset === \"/_mreact\" ||\n asset.startsWith(\"/_mreact/\")\n ) {\n continue;\n }\n\n const relativeAsset = asset.slice(1);\n const destination = join(exportDir, relativeAsset);\n await mkdir(dirname(destination), { recursive: true });\n await cp(join(clientDir, relativeAsset), destination, { recursive: true });\n }\n}\n\nasync function writePrerenderedRoute(\n exportDir: string,\n route: string,\n entry: BuiltPrerenderedRoute,\n): Promise<void> {\n if (entry.status < 200 || entry.status >= 300) {\n throw new Error(`Cannot export route ${route} with status ${entry.status}.`);\n }\n\n const file = routeToHtmlFile(exportDir, route);\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, entry.html);\n}\n\nfunction routeToHtmlFile(exportDir: string, route: string): string {\n const pathname = route.split(\"?\")[0] ?? \"/\";\n const normalized = pathname.startsWith(\"/\") ? pathname.slice(1) : pathname;\n const relativeFile = normalized === \"\" ? \"index.html\" : join(normalized, \"index.html\");\n const root = resolve(exportDir);\n const file = resolve(root, relativeFile);\n\n if (file !== root && !file.startsWith(`${root}${sep}`)) {\n throw new Error(`unsafe static export route: ${route}`);\n }\n\n return file;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/adapters/static.ts"],"names":[],"mappings":"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","sourcesContent":["import { cp, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport type { BuiltPrerenderedRoute, BuiltServerManifest } from \"../build.js\";\nimport {\n isCurrentPrerenderedRoute,\n validatedPrerenderedNavigationHtml,\n} from \"../prerender-entry.js\";\n\nconst staticNavigationBase = \"/_mreact/navigation\";\nconst staticNavigationMetadata = `<meta name=\"mreact-static-navigation\" content=\"${staticNavigationBase}\">`;\n\n/**\n * Configures static export from a built app-router output directory.\n */\nexport interface StaticExportOptions {\n exportDir: string;\n outDir: string;\n paths?: readonly string[] | undefined;\n}\n\n/**\n * Lists the routes written by a static app-router export.\n */\nexport interface StaticExportResult {\n routes: string[];\n}\n\n/**\n * Exports prerendered app-router routes and client assets to a static filesystem directory.\n *\n * Only routes present in the built prerender manifest can be exported; the export directory is removed and recreated, and route paths are checked to prevent traversal outside it.\n */\nexport async function exportStaticApp(options: StaticExportOptions): Promise<StaticExportResult> {\n const manifest = JSON.parse(\n await readFile(join(options.outDir, \"server\", \"manifest.json\"), \"utf8\"),\n ) as BuiltServerManifest;\n const clientManifest = JSON.parse(\n await readFile(join(options.outDir, \"client\", \"manifest.json\"), \"utf8\"),\n ) as { publicAssets?: readonly string[] };\n const prerenderedRoutes = manifest.prerenderedRoutes ?? {};\n const routes = [...(options.paths ?? Object.keys(prerenderedRoutes))].sort();\n const entries = routes.map((route): readonly [string, BuiltPrerenderedRoute] => {\n routeToHtmlFile(options.exportDir, route);\n const entry = prerenderedRoutes[route];\n\n if (entry === undefined) {\n throw new Error(`Cannot export non-prerendered route: ${route}`);\n }\n\n if (!isCurrentPrerenderedRoute(entry)) {\n throw new Error(`Cannot export invalid prerendered route: ${route}`);\n }\n\n if (entry.status < 200 || entry.status >= 300) {\n throw new Error(`Cannot export route ${route} with status ${entry.status}.`);\n }\n\n return [route, entry];\n });\n\n await rm(options.exportDir, { force: true, recursive: true });\n await mkdir(options.exportDir, { recursive: true });\n\n for (const [route, entry] of entries) {\n await writePrerenderedRoute(options.exportDir, route, entry);\n }\n\n await cp(join(options.outDir, \"client\"), join(options.exportDir, \"_mreact\", \"client\"), {\n recursive: true,\n });\n await copyPublicAssetsToExportRoot(\n join(options.outDir, \"client\"),\n options.exportDir,\n clientManifest.publicAssets ?? [],\n );\n\n return { routes };\n}\n\nasync function copyPublicAssetsToExportRoot(\n clientDir: string,\n exportDir: string,\n publicAssets: readonly string[],\n): Promise<void> {\n for (const asset of publicAssets) {\n if (\n !asset.startsWith(\"/\") ||\n asset.startsWith(\"//\") ||\n asset.includes(\"..\") ||\n asset === \"/_mreact\" ||\n asset.startsWith(\"/_mreact/\")\n ) {\n continue;\n }\n\n const relativeAsset = asset.slice(1);\n const destination = join(exportDir, relativeAsset);\n await mkdir(dirname(destination), { recursive: true });\n await cp(join(clientDir, relativeAsset), destination, { recursive: true });\n }\n}\n\nasync function writePrerenderedRoute(\n exportDir: string,\n route: string,\n entry: BuiltPrerenderedRoute,\n): Promise<void> {\n if (entry.status < 200 || entry.status >= 300) {\n throw new Error(`Cannot export route ${route} with status ${entry.status}.`);\n }\n\n const file = routeToHtmlFile(exportDir, route);\n const navigationHtml = validatedPrerenderedNavigationHtml(entry);\n if (navigationHtml === undefined) {\n throw new Error(`Cannot export route ${route} without a valid navigation variant.`);\n }\n const navigationFile = routeToHtmlFile(join(exportDir, staticNavigationBase), route);\n await mkdir(dirname(file), { recursive: true });\n await mkdir(dirname(navigationFile), { recursive: true });\n await writeFile(file, withStaticNavigationMetadata(entry.html));\n await writeFile(navigationFile, navigationHtml);\n}\n\nfunction withStaticNavigationMetadata(html: string): string {\n const head = /<head(?:\\s[^>]*)?>/i.exec(html);\n if (head?.index !== undefined) {\n const insertion = head.index + head[0].length;\n return `${html.slice(0, insertion)}${staticNavigationMetadata}${html.slice(insertion)}`;\n }\n\n const doctype = /^\\s*<!doctype\\s+html\\s*>/i.exec(html);\n if (doctype !== null) {\n const insertion = doctype[0].length;\n return `${html.slice(0, insertion)}${staticNavigationMetadata}${html.slice(insertion)}`;\n }\n\n return `${staticNavigationMetadata}${html}`;\n}\n\nfunction routeToHtmlFile(exportDir: string, route: string): string {\n const pathname = route.split(\"?\")[0] ?? \"/\";\n const normalized = pathname.startsWith(\"/\") ? pathname.slice(1) : pathname;\n const relativeFile = normalized === \"\" ? \"index.html\" : join(normalized, \"index.html\");\n const root = resolve(exportDir);\n const file = resolve(root, relativeFile);\n\n if (file !== root && !file.startsWith(`${root}${sep}`)) {\n throw new Error(`unsafe static export route: ${route}`);\n }\n\n return file;\n}\n"]}
|
package/dist/build.d.ts
CHANGED
|
@@ -109,6 +109,7 @@ export interface PackageCloudflarePagesArtifactOptions {
|
|
|
109
109
|
export interface BuiltServerManifest {
|
|
110
110
|
allowedSourceDirs?: readonly string[];
|
|
111
111
|
assetBaseUrl?: string;
|
|
112
|
+
dehydratePolicyModule?: string;
|
|
112
113
|
version: 1;
|
|
113
114
|
files: Record<string, string>;
|
|
114
115
|
prerenderedRoutes?: Record<string, BuiltPrerenderedRoute>;
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
CHANGED
|
@@ -11,6 +11,7 @@ import { compilerModuleContextForSource, collectClientRouteReferences, createCli
|
|
|
11
11
|
import { createBoundaryReport } from "./boundaries.js";
|
|
12
12
|
import { buildClientRouteBatchOutput, buildNavigationRuntimeBundle, clientScriptForPath, routeIdForPath, routeMarkerParts, } from "./navigation-runtime.js";
|
|
13
13
|
import { COMPAT_VENDOR_PLACEHOLDER_PREFIX, bundleAppRouterSourceModule, fileImportMetaUrlPlugin, importAppRouterSourceModule, resolveCompatVendorEntryFiles, sourceReferencesCompatVendorSpecifier, } from "./module-runner.js";
|
|
14
|
+
import { dehydrateOptionsFromModule } from "./dehydrate-policy.js";
|
|
14
15
|
import { compileRouteMatcherArtifact, scanAppRoutes } from "./routes.js";
|
|
15
16
|
import { appFileConventionForRootFilename } from "./file-conventions.js";
|
|
16
17
|
import { resolveAppRouterProjectOptions, resolveBuildTargets, } from "./config.js";
|
|
@@ -77,6 +78,9 @@ export async function buildApp(options) {
|
|
|
77
78
|
return await buildConcurrencyStorage.run(buildConcurrency, async () => await buildAppWithResolvedProject(options, project));
|
|
78
79
|
}
|
|
79
80
|
async function buildAppWithResolvedProject(options, project) {
|
|
81
|
+
if (options.dehydrateOptions !== undefined) {
|
|
82
|
+
throw new Error("buildApp dehydration policies must use dehydratePolicyModule so the same executable policy is available to prerendering and built runtimes.");
|
|
83
|
+
}
|
|
80
84
|
const timingSink = options.onBuildPhaseTiming;
|
|
81
85
|
const progressSink = options.onBuildProgress;
|
|
82
86
|
const shouldTrackBuildPhases = timingSink !== undefined || progressSink !== undefined;
|
|
@@ -178,6 +182,21 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
178
182
|
]);
|
|
179
183
|
});
|
|
180
184
|
}
|
|
185
|
+
const builtDehydratePolicy = project.dehydratePolicyModule === undefined
|
|
186
|
+
? undefined
|
|
187
|
+
: await buildDehydratePolicyModule({
|
|
188
|
+
define: viteDefine,
|
|
189
|
+
file: project.dehydratePolicyModule,
|
|
190
|
+
projectRoot: project.projectRoot,
|
|
191
|
+
vitePlugins,
|
|
192
|
+
});
|
|
193
|
+
const dehydratePolicyArtifact = builtDehydratePolicy === undefined
|
|
194
|
+
? undefined
|
|
195
|
+
: `dehydrate-policy.${hashText(builtDehydratePolicy.code).slice(0, 16)}.mjs`;
|
|
196
|
+
if (builtDehydratePolicy !== undefined && dehydratePolicyArtifact !== undefined) {
|
|
197
|
+
await writeFile(join(serverDir, dehydratePolicyArtifact), builtDehydratePolicy.code);
|
|
198
|
+
}
|
|
199
|
+
const dehydrateOptions = builtDehydratePolicy?.dehydrateOptions;
|
|
181
200
|
const publicAssets = shouldTrackBuildPhases === false
|
|
182
201
|
? await buildPublicAssetManifest(project, clientDir)
|
|
183
202
|
: await timeBuildPhase(timingSink, progressSink, "publicAssets", () => buildPublicAssetManifest(project, clientDir));
|
|
@@ -302,6 +321,7 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
302
321
|
assetBaseUrl: project.assetBaseUrl,
|
|
303
322
|
clientRoutes: clientManifestRoutes,
|
|
304
323
|
define: viteDefine,
|
|
324
|
+
dehydrateOptions,
|
|
305
325
|
project,
|
|
306
326
|
routes,
|
|
307
327
|
serverModules,
|
|
@@ -313,6 +333,7 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
313
333
|
assetBaseUrl: project.assetBaseUrl,
|
|
314
334
|
clientRoutes: clientManifestRoutes,
|
|
315
335
|
define: viteDefine,
|
|
336
|
+
dehydrateOptions,
|
|
316
337
|
project,
|
|
317
338
|
routes,
|
|
318
339
|
serverModules,
|
|
@@ -352,6 +373,9 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
352
373
|
const serverManifest = {
|
|
353
374
|
allowedSourceDirs: project.allowedSourceDirs.map((directory) => relative(project.projectRoot, directory)),
|
|
354
375
|
...(project.assetBaseUrl === undefined ? {} : { assetBaseUrl: project.assetBaseUrl }),
|
|
376
|
+
...(dehydratePolicyArtifact === undefined
|
|
377
|
+
? {}
|
|
378
|
+
: { dehydratePolicyModule: dehydratePolicyArtifact }),
|
|
355
379
|
version: 1,
|
|
356
380
|
routes: serverRoutes,
|
|
357
381
|
routeMatcher: compileRouteMatcherArtifact(serverRoutes),
|
|
@@ -446,7 +470,7 @@ async function buildAppWithResolvedProject(options, project) {
|
|
|
446
470
|
return { routes };
|
|
447
471
|
}
|
|
448
472
|
const incrementalBuildCacheFilename = "build-cache.json";
|
|
449
|
-
const incrementalBuildCacheVersion =
|
|
473
|
+
const incrementalBuildCacheVersion = 2;
|
|
450
474
|
async function createIncrementalBuildCacheFingerprint(options) {
|
|
451
475
|
if (options.vitePlugins !== undefined && options.vitePlugins.length > 0) {
|
|
452
476
|
return undefined;
|
|
@@ -481,6 +505,9 @@ async function createIncrementalBuildCacheFingerprint(options) {
|
|
|
481
505
|
assetBaseUrl: options.project.assetBaseUrl ?? null,
|
|
482
506
|
clientConsolePureFunctions: options.project.clientConsolePureFunctions ?? [],
|
|
483
507
|
clientSourceMaps: options.project.clientSourceMaps,
|
|
508
|
+
dehydratePolicyModule: options.project.dehydratePolicyModule === undefined
|
|
509
|
+
? null
|
|
510
|
+
: normalizeBuildInputPath(relative(options.project.projectRoot, options.project.dehydratePolicyModule)),
|
|
484
511
|
define,
|
|
485
512
|
nodeEnv: process.env.NODE_ENV ?? null,
|
|
486
513
|
publicAssetBaseUrl: options.project.publicAssetBaseUrl ?? null,
|
|
@@ -529,6 +556,9 @@ async function hasRequiredIncrementalBuildOutputs(outDir, buildTargets) {
|
|
|
529
556
|
return false;
|
|
530
557
|
}
|
|
531
558
|
for (const file of [
|
|
559
|
+
...(serverManifest.dehydratePolicyModule === undefined
|
|
560
|
+
? []
|
|
561
|
+
: [serverManifest.dehydratePolicyModule]),
|
|
532
562
|
...Object.values(serverManifest.serverModuleFiles ?? {}),
|
|
533
563
|
...Object.values(serverManifest.serverModuleRenderFiles ?? {}),
|
|
534
564
|
...Object.values(serverManifest.serverModuleRequestFiles ?? {}),
|
|
@@ -1570,6 +1600,28 @@ async function copyPublicAssetsInner(publicDir, relativeDir, outDir) {
|
|
|
1570
1600
|
function isReservedPublicAssetPath(pathname) {
|
|
1571
1601
|
return pathname === "/_mreact" || pathname.startsWith("/_mreact/");
|
|
1572
1602
|
}
|
|
1603
|
+
async function buildDehydratePolicyModule(options) {
|
|
1604
|
+
const source = await readFile(options.file, "utf8");
|
|
1605
|
+
const code = await bundleAppRouterSourceModule({
|
|
1606
|
+
code: source,
|
|
1607
|
+
define: options.define,
|
|
1608
|
+
label: `dehydrate-policy:${options.file}`,
|
|
1609
|
+
plugins: [fileImportMetaUrlPlugin()],
|
|
1610
|
+
resolveDir: dirname(options.file),
|
|
1611
|
+
root: options.projectRoot,
|
|
1612
|
+
sourcefile: options.file,
|
|
1613
|
+
vitePlugins: options.vitePlugins,
|
|
1614
|
+
});
|
|
1615
|
+
const policyModule = await importAppRouterSourceModule({
|
|
1616
|
+
code,
|
|
1617
|
+
label: `dehydrate-policy-runtime:${options.file}`,
|
|
1618
|
+
sourcefile: options.file,
|
|
1619
|
+
});
|
|
1620
|
+
return {
|
|
1621
|
+
code,
|
|
1622
|
+
dehydrateOptions: dehydrateOptionsFromModule(policyModule, `mreactRouter dehydratePolicyModule ${options.file}`),
|
|
1623
|
+
};
|
|
1624
|
+
}
|
|
1573
1625
|
function isNodeError(error) {
|
|
1574
1626
|
return error instanceof Error && "code" in error;
|
|
1575
1627
|
}
|
|
@@ -1613,11 +1665,11 @@ async function prerenderStaticRoutes(options) {
|
|
|
1613
1665
|
clientScripts,
|
|
1614
1666
|
clientStyles,
|
|
1615
1667
|
define: options.define,
|
|
1668
|
+
dehydrateOptions: options.dehydrateOptions,
|
|
1616
1669
|
importPolicy,
|
|
1617
1670
|
navigationScripts,
|
|
1618
|
-
request: new Request(`http://mreact.local${pathname}
|
|
1619
|
-
|
|
1620
|
-
: { headers: { "x-mreact-prerender-variant-capture": "1" } }),
|
|
1671
|
+
request: new Request(`http://mreact.local${pathname}`),
|
|
1672
|
+
prerenderVariantCapture: !analysis.clientRoute,
|
|
1621
1673
|
renderSignals,
|
|
1622
1674
|
serverModuleCacheVersion,
|
|
1623
1675
|
serverModules: serverModuleMap,
|
|
@@ -3399,7 +3451,41 @@ function validateOptionalHeadMetadata(value, path) {
|
|
|
3399
3451
|
}
|
|
3400
3452
|
}
|
|
3401
3453
|
}
|
|
3454
|
+
validateMetaRefreshHeadDescriptor(descriptor, descriptorPath);
|
|
3455
|
+
});
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
function validateMetaRefreshHeadDescriptor(descriptor, path) {
|
|
3459
|
+
if (descriptor.tag !== "meta" || descriptor.attrs === undefined) {
|
|
3460
|
+
return;
|
|
3461
|
+
}
|
|
3462
|
+
const attrs = Object.entries(descriptor.attrs);
|
|
3463
|
+
const hasRefresh = attrs.some(([name, value]) => {
|
|
3464
|
+
const canonicalName = name.toLowerCase();
|
|
3465
|
+
return (canonicalName === "http-equiv" || canonicalName === "httpequiv")
|
|
3466
|
+
&& typeof value === "string"
|
|
3467
|
+
&& value.toLowerCase() === "refresh";
|
|
3402
3468
|
});
|
|
3469
|
+
if (!hasRefresh) {
|
|
3470
|
+
return;
|
|
3471
|
+
}
|
|
3472
|
+
for (const [name, value] of attrs) {
|
|
3473
|
+
if (name.toLowerCase() !== "content" || typeof value !== "string") {
|
|
3474
|
+
continue;
|
|
3475
|
+
}
|
|
3476
|
+
const match = /^[^;]*;\\s*url\\s*=\\s*([\\s\\S]+)$/iu.exec(value);
|
|
3477
|
+
if (match === null || match[1] === undefined) {
|
|
3478
|
+
continue;
|
|
3479
|
+
}
|
|
3480
|
+
let target = match[1].trim();
|
|
3481
|
+
const quote = target[0];
|
|
3482
|
+
if ((quote === String.fromCharCode(34) || quote === "'") && target[target.length - 1] === quote) {
|
|
3483
|
+
target = target.slice(1, -1).trim();
|
|
3484
|
+
}
|
|
3485
|
+
if (isUnsafeUrlValueForName("href", target)) {
|
|
3486
|
+
throw new Error(\`Invalid metadata field \${path}.attrs.\${name}: unsafe refresh URL value.\`);
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3403
3489
|
}
|
|
3404
3490
|
|
|
3405
3491
|
function validateHeadAttribute(name, value, path) {
|
|
@@ -3463,7 +3549,7 @@ function isUnsafeUrlValueForName(name, value) {
|
|
|
3463
3549
|
}
|
|
3464
3550
|
const scheme = match[1].toLowerCase();
|
|
3465
3551
|
if (scheme === "data" && (name === "src" || name === "poster")) {
|
|
3466
|
-
return !/^data:image\\/(?!svg\\+xml(?:[;,]|$))/i.test(canonical);
|
|
3552
|
+
return !/^data:image\\/(?!svg\\+xml\\s*(?:[;,]|$))/i.test(canonical);
|
|
3467
3553
|
}
|
|
3468
3554
|
return scheme === "javascript" || scheme === "data" || scheme === "vbscript" || scheme === "livescript" || scheme === "mhtml" || scheme === "file";
|
|
3469
3555
|
}
|