@bleedingdev/modern-js-runtime 3.2.0-ultramodern.120 → 3.2.0-ultramodern.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/boundary-debugger/index.js +4 -0
- package/dist/cjs/cli/index.js +11 -0
- package/dist/cjs/{router/runtime/tanstack/rsc/ClientSlot.js → core/context/extensions.js} +33 -21
- package/dist/cjs/{router/runtime/tanstack/rsc/SlotContext.js → core/context/helmetContext.js} +16 -20
- package/dist/cjs/core/context/index.js +65 -0
- package/dist/cjs/core/react/wrapper.js +6 -4
- package/dist/cjs/core/server/helmet.js +2 -1
- package/dist/cjs/core/server/requestHandler.js +42 -29
- package/dist/cjs/core/server/routerCleanup.js +110 -0
- package/dist/cjs/core/server/scriptOrder.js +75 -4
- package/dist/cjs/core/server/stream/afterTemplate.js +6 -18
- package/dist/cjs/core/server/stream/deferredScript.js +4 -1
- package/dist/cjs/core/server/string/index.js +1 -7
- package/dist/cjs/core/server/string/loadable.js +13 -40
- package/dist/cjs/core/server/string/ssrData.js +1 -1
- package/dist/cjs/core/server/utils.js +31 -8
- package/dist/cjs/exports/head.js +135 -74
- package/dist/cjs/exports/tanstack-router.js +36 -305
- package/dist/cjs/module-federation/index.js +178 -0
- package/dist/cjs/router/cli/code/index.js +1 -47
- package/dist/cjs/router/cli/code/templates.js +1 -14
- package/dist/cjs/router/cli/handler.js +1 -1
- package/dist/cjs/router/cli/index.js +2 -23
- package/dist/cjs/router/runtime/DeferredDataScripts.node.js +16 -4
- package/dist/cjs/router/runtime/PrefetchLink.js +2 -3
- package/dist/cjs/router/runtime/internal.js +20 -13
- package/dist/cjs/router/runtime/lifecycle.js +37 -22
- package/dist/cjs/router/runtime/plugin.js +2 -9
- package/dist/cjs/router/runtime/plugin.node.js +2 -7
- package/dist/cjs/router/runtime/provider.js +107 -0
- package/dist/cjs/router/runtime/utils.js +35 -9
- package/dist/esm/boundary-debugger/index.mjs +4 -0
- package/dist/esm/cli/index.mjs +4 -2
- package/dist/esm/core/context/extensions.mjs +28 -0
- package/dist/esm/core/context/helmetContext.mjs +13 -0
- package/dist/esm/core/context/index.mjs +5 -0
- package/dist/esm/core/react/wrapper.mjs +6 -4
- package/dist/esm/core/server/helmet.mjs +2 -1
- package/dist/esm/core/server/requestHandler.mjs +43 -30
- package/dist/esm/core/server/routerCleanup.mjs +66 -0
- package/dist/esm/core/server/scriptOrder.mjs +60 -1
- package/dist/esm/core/server/stream/afterTemplate.mjs +8 -20
- package/dist/esm/core/server/stream/deferredScript.mjs +4 -1
- package/dist/esm/core/server/string/index.mjs +3 -9
- package/dist/esm/core/server/string/loadable.mjs +11 -38
- package/dist/esm/core/server/string/ssrData.mjs +2 -2
- package/dist/esm/core/server/utils.mjs +31 -8
- package/dist/esm/exports/head.mjs +135 -74
- package/dist/esm/exports/tanstack-router.mjs +30 -4
- package/dist/esm/module-federation/index.mjs +109 -0
- package/dist/esm/router/cli/code/index.mjs +1 -47
- package/dist/esm/router/cli/code/templates.mjs +1 -14
- package/dist/esm/router/cli/handler.mjs +1 -1
- package/dist/esm/router/cli/index.mjs +3 -24
- package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +16 -4
- package/dist/esm/router/runtime/PrefetchLink.mjs +2 -3
- package/dist/esm/router/runtime/internal.mjs +16 -15
- package/dist/esm/router/runtime/lifecycle.mjs +22 -13
- package/dist/esm/router/runtime/plugin.mjs +4 -11
- package/dist/esm/router/runtime/plugin.node.mjs +4 -9
- package/dist/esm/router/runtime/provider.mjs +57 -0
- package/dist/esm/router/runtime/utils.mjs +35 -9
- package/dist/esm-node/boundary-debugger/index.mjs +4 -0
- package/dist/esm-node/cli/index.mjs +4 -2
- package/dist/esm-node/core/context/extensions.mjs +29 -0
- package/dist/esm-node/core/context/helmetContext.mjs +14 -0
- package/dist/esm-node/core/context/index.mjs +5 -0
- package/dist/esm-node/core/react/wrapper.mjs +6 -4
- package/dist/esm-node/core/server/helmet.mjs +2 -1
- package/dist/esm-node/core/server/requestHandler.mjs +43 -30
- package/dist/esm-node/core/server/routerCleanup.mjs +67 -0
- package/dist/esm-node/core/server/scriptOrder.mjs +60 -1
- package/dist/esm-node/core/server/stream/afterTemplate.mjs +8 -20
- package/dist/esm-node/core/server/stream/deferredScript.mjs +4 -1
- package/dist/esm-node/core/server/string/index.mjs +3 -9
- package/dist/esm-node/core/server/string/loadable.mjs +11 -38
- package/dist/esm-node/core/server/string/ssrData.mjs +2 -2
- package/dist/esm-node/core/server/utils.mjs +31 -8
- package/dist/esm-node/exports/head.mjs +135 -74
- package/dist/esm-node/exports/tanstack-router.mjs +30 -4
- package/dist/esm-node/module-federation/index.mjs +110 -0
- package/dist/esm-node/router/cli/code/index.mjs +1 -47
- package/dist/esm-node/router/cli/code/templates.mjs +1 -14
- package/dist/esm-node/router/cli/handler.mjs +1 -1
- package/dist/esm-node/router/cli/index.mjs +3 -24
- package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +16 -4
- package/dist/esm-node/router/runtime/PrefetchLink.mjs +2 -3
- package/dist/esm-node/router/runtime/internal.mjs +16 -15
- package/dist/esm-node/router/runtime/lifecycle.mjs +22 -13
- package/dist/esm-node/router/runtime/plugin.mjs +4 -11
- package/dist/esm-node/router/runtime/plugin.node.mjs +4 -9
- package/dist/esm-node/router/runtime/provider.mjs +58 -0
- package/dist/esm-node/router/runtime/utils.mjs +35 -9
- package/dist/types/cli/index.d.ts +3 -1
- package/dist/types/core/context/extensions.d.ts +37 -0
- package/dist/types/core/context/helmetContext.d.ts +10 -0
- package/dist/types/core/context/index.d.ts +6 -0
- package/dist/types/core/context/runtime.d.ts +1 -11
- package/dist/types/core/server/routerCleanup.d.ts +28 -0
- package/dist/types/core/server/scriptOrder.d.ts +24 -0
- package/dist/types/core/server/string/loadable.d.ts +1 -7
- package/dist/types/core/server/utils.d.ts +1 -0
- package/dist/types/exports/tanstack-router.d.ts +88 -7
- package/dist/types/module-federation/index.d.ts +65 -0
- package/dist/types/router/cli/code/index.d.ts +1 -3
- package/dist/types/router/cli/handler.d.ts +0 -3
- package/dist/types/router/runtime/internal.d.ts +1 -0
- package/dist/types/router/runtime/lifecycle.d.ts +2 -0
- package/dist/types/router/runtime/plugin.d.ts +1 -1
- package/dist/types/router/runtime/plugin.node.d.ts +1 -1
- package/dist/types/router/runtime/provider.d.ts +61 -0
- package/package.json +16 -12
- package/rstest.config.mts +2 -4
- package/dist/cjs/router/cli/code/tanstackTypes.js +0 -447
- package/dist/cjs/router/runtime/tanstack/basepathRewrite.js +0 -66
- package/dist/cjs/router/runtime/tanstack/dataMutation.js +0 -349
- package/dist/cjs/router/runtime/tanstack/hydrationBoundary.js +0 -48
- package/dist/cjs/router/runtime/tanstack/outlet.js +0 -58
- package/dist/cjs/router/runtime/tanstack/plugin.js +0 -342
- package/dist/cjs/router/runtime/tanstack/plugin.node.js +0 -272
- package/dist/cjs/router/runtime/tanstack/prefetchLink.js +0 -59
- package/dist/cjs/router/runtime/tanstack/routeTree.js +0 -525
- package/dist/cjs/router/runtime/tanstack/rsc/CompositeComponent.js +0 -79
- package/dist/cjs/router/runtime/tanstack/rsc/ReplayableStream.js +0 -146
- package/dist/cjs/router/runtime/tanstack/rsc/RscNodeRenderer.js +0 -69
- package/dist/cjs/router/runtime/tanstack/rsc/client.js +0 -97
- package/dist/cjs/router/runtime/tanstack/rsc/createRscProxy.js +0 -145
- package/dist/cjs/router/runtime/tanstack/rsc/index.js +0 -46
- package/dist/cjs/router/runtime/tanstack/rsc/server.js +0 -250
- package/dist/cjs/router/runtime/tanstack/rsc/slotUsageSanitizer.js +0 -69
- package/dist/cjs/router/runtime/tanstack/rsc/symbols.js +0 -77
- package/dist/cjs/ssr/index.node.js +0 -125
- package/dist/cjs/ssr/serverRender/renderToStream/buildTemplate.after.js +0 -88
- package/dist/cjs/ssr/serverRender/renderToString/entry.js +0 -200
- package/dist/cjs/ssr/serverRender/types.js +0 -40
- package/dist/esm/router/cli/code/tanstackTypes.mjs +0 -396
- package/dist/esm/router/runtime/tanstack/basepathRewrite.mjs +0 -28
- package/dist/esm/router/runtime/tanstack/dataMutation.mjs +0 -305
- package/dist/esm/router/runtime/tanstack/hydrationBoundary.mjs +0 -10
- package/dist/esm/router/runtime/tanstack/outlet.mjs +0 -17
- package/dist/esm/router/runtime/tanstack/plugin.mjs +0 -304
- package/dist/esm/router/runtime/tanstack/plugin.node.mjs +0 -234
- package/dist/esm/router/runtime/tanstack/prefetchLink.mjs +0 -18
- package/dist/esm/router/runtime/tanstack/routeTree.mjs +0 -481
- package/dist/esm/router/runtime/tanstack/rsc/ClientSlot.mjs +0 -19
- package/dist/esm/router/runtime/tanstack/rsc/CompositeComponent.mjs +0 -41
- package/dist/esm/router/runtime/tanstack/rsc/ReplayableStream.mjs +0 -104
- package/dist/esm/router/runtime/tanstack/rsc/RscNodeRenderer.mjs +0 -31
- package/dist/esm/router/runtime/tanstack/rsc/SlotContext.mjs +0 -17
- package/dist/esm/router/runtime/tanstack/rsc/client.mjs +0 -53
- package/dist/esm/router/runtime/tanstack/rsc/createRscProxy.mjs +0 -107
- package/dist/esm/router/runtime/tanstack/rsc/index.mjs +0 -1
- package/dist/esm/router/runtime/tanstack/rsc/server.mjs +0 -200
- package/dist/esm/router/runtime/tanstack/rsc/slotUsageSanitizer.mjs +0 -31
- package/dist/esm/router/runtime/tanstack/rsc/symbols.mjs +0 -17
- package/dist/esm/ssr/index.node.mjs +0 -44
- package/dist/esm/ssr/serverRender/renderToStream/buildTemplate.after.mjs +0 -50
- package/dist/esm/ssr/serverRender/renderToString/entry.mjs +0 -151
- package/dist/esm/ssr/serverRender/types.mjs +0 -1
- package/dist/esm-node/router/cli/code/tanstackTypes.mjs +0 -397
- package/dist/esm-node/router/runtime/tanstack/basepathRewrite.mjs +0 -29
- package/dist/esm-node/router/runtime/tanstack/dataMutation.mjs +0 -306
- package/dist/esm-node/router/runtime/tanstack/hydrationBoundary.mjs +0 -11
- package/dist/esm-node/router/runtime/tanstack/outlet.mjs +0 -18
- package/dist/esm-node/router/runtime/tanstack/plugin.mjs +0 -305
- package/dist/esm-node/router/runtime/tanstack/plugin.node.mjs +0 -235
- package/dist/esm-node/router/runtime/tanstack/prefetchLink.mjs +0 -19
- package/dist/esm-node/router/runtime/tanstack/routeTree.mjs +0 -482
- package/dist/esm-node/router/runtime/tanstack/rsc/ClientSlot.mjs +0 -20
- package/dist/esm-node/router/runtime/tanstack/rsc/CompositeComponent.mjs +0 -42
- package/dist/esm-node/router/runtime/tanstack/rsc/ReplayableStream.mjs +0 -105
- package/dist/esm-node/router/runtime/tanstack/rsc/RscNodeRenderer.mjs +0 -32
- package/dist/esm-node/router/runtime/tanstack/rsc/SlotContext.mjs +0 -18
- package/dist/esm-node/router/runtime/tanstack/rsc/client.mjs +0 -54
- package/dist/esm-node/router/runtime/tanstack/rsc/createRscProxy.mjs +0 -108
- package/dist/esm-node/router/runtime/tanstack/rsc/index.mjs +0 -2
- package/dist/esm-node/router/runtime/tanstack/rsc/server.mjs +0 -201
- package/dist/esm-node/router/runtime/tanstack/rsc/slotUsageSanitizer.mjs +0 -32
- package/dist/esm-node/router/runtime/tanstack/rsc/symbols.mjs +0 -18
- package/dist/esm-node/ssr/index.node.mjs +0 -45
- package/dist/esm-node/ssr/serverRender/renderToStream/buildTemplate.after.mjs +0 -51
- package/dist/esm-node/ssr/serverRender/renderToString/entry.mjs +0 -152
- package/dist/esm-node/ssr/serverRender/types.mjs +0 -2
- package/dist/types/router/cli/code/tanstackTypes.d.ts +0 -10
- package/dist/types/router/runtime/tanstack/basepathRewrite.d.ts +0 -8
- package/dist/types/router/runtime/tanstack/dataMutation.d.ts +0 -29
- package/dist/types/router/runtime/tanstack/hydrationBoundary.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/outlet.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/plugin.d.ts +0 -6
- package/dist/types/router/runtime/tanstack/plugin.node.d.ts +0 -6
- package/dist/types/router/runtime/tanstack/prefetchLink.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/routeTree.d.ts +0 -8
- package/dist/types/router/runtime/tanstack/rsc/ClientSlot.d.ts +0 -5
- package/dist/types/router/runtime/tanstack/rsc/CompositeComponent.d.ts +0 -3
- package/dist/types/router/runtime/tanstack/rsc/ReplayableStream.d.ts +0 -24
- package/dist/types/router/runtime/tanstack/rsc/RscNodeRenderer.d.ts +0 -5
- package/dist/types/router/runtime/tanstack/rsc/SlotContext.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/rsc/client.d.ts +0 -11
- package/dist/types/router/runtime/tanstack/rsc/createRscProxy.d.ts +0 -7
- package/dist/types/router/runtime/tanstack/rsc/index.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/rsc/server.d.ts +0 -14
- package/dist/types/router/runtime/tanstack/rsc/slotUsageSanitizer.d.ts +0 -2
- package/dist/types/router/runtime/tanstack/rsc/symbols.d.ts +0 -46
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
const MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT = 'modernjs:mf-runtime-fallback';
|
|
3
|
+
const MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT = 'modernjs:mf-runtime-recovery';
|
|
4
|
+
const DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT = '/_modern/contract-gates/runtime-fallback';
|
|
5
|
+
const DEFAULT_RUNTIME_FALLBACK_SIGNAL_AUTH_HEADER = 'x-modernjs-runtime-signal-token';
|
|
6
|
+
class ModuleFederationRemoteLoadTimeoutError extends Error {
|
|
7
|
+
constructor(remote, timeoutMs){
|
|
8
|
+
super(`Loading remote "${remote}" timed out after ${timeoutMs}ms`);
|
|
9
|
+
this.name = 'ModuleFederationRemoteLoadTimeoutError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
class ModuleFederationRemoteLoadError extends Error {
|
|
13
|
+
constructor(remote, attempts, causeError){
|
|
14
|
+
super(`Unable to load remote "${remote}" after ${attempts} attempt${attempts > 1 ? 's' : ''}: ${causeError.message}`);
|
|
15
|
+
this.name = 'ModuleFederationRemoteLoadError';
|
|
16
|
+
this.remote = remote;
|
|
17
|
+
this.attempts = attempts;
|
|
18
|
+
this.causeError = causeError;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class ModuleFederationRemoteComponentContractError extends Error {
|
|
22
|
+
constructor(remote, exportName){
|
|
23
|
+
super(`Remote "${remote}" export "${exportName}" is not a valid React component`);
|
|
24
|
+
this.name = 'ModuleFederationRemoteComponentContractError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function toError(error) {
|
|
28
|
+
if (error instanceof Error) return error;
|
|
29
|
+
return new Error('string' == typeof error ? error : 'Unknown remote load error');
|
|
30
|
+
}
|
|
31
|
+
function classifyModuleFederationFallback(error) {
|
|
32
|
+
const normalizedError = toError(error);
|
|
33
|
+
if (normalizedError instanceof ModuleFederationRemoteLoadError) return classifyModuleFederationFallback(normalizedError.causeError);
|
|
34
|
+
if (normalizedError instanceof ModuleFederationRemoteLoadTimeoutError) return 'timeout';
|
|
35
|
+
if (normalizedError instanceof ModuleFederationRemoteComponentContractError) return 'contract';
|
|
36
|
+
const message = normalizedError.message;
|
|
37
|
+
if (/version|requiredVersion|singleton|share scope|shared module/i.test(message)) return 'version-skew';
|
|
38
|
+
if (/network|fetch|script|timeout|chunk|loading/i.test(message)) return 'network';
|
|
39
|
+
return 'remote-unavailable';
|
|
40
|
+
}
|
|
41
|
+
function createModuleFederationFallbackTelemetry(input) {
|
|
42
|
+
const error = void 0 !== input.error ? toError(input.error) : void 0;
|
|
43
|
+
const status = input.status ?? 'degraded';
|
|
44
|
+
const eventName = input.eventName ?? ('recovered' === status ? MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT : MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT);
|
|
45
|
+
const metadata = {
|
|
46
|
+
...input.metadata ?? {},
|
|
47
|
+
classification: input.classification,
|
|
48
|
+
remote: input.remote,
|
|
49
|
+
status
|
|
50
|
+
};
|
|
51
|
+
if (void 0 !== input.exportName) metadata.exportName = input.exportName;
|
|
52
|
+
if (void 0 !== input.runtimeDigest) metadata.runtimeDigest = input.runtimeDigest;
|
|
53
|
+
if (void 0 !== error) {
|
|
54
|
+
metadata.errorName = error.name;
|
|
55
|
+
metadata.errorMessage = error.message;
|
|
56
|
+
}
|
|
57
|
+
const payload = {
|
|
58
|
+
appName: input.appName,
|
|
59
|
+
eventName,
|
|
60
|
+
metadata,
|
|
61
|
+
phase: input.phase,
|
|
62
|
+
reason: input.classification,
|
|
63
|
+
schemaVersion: 1
|
|
64
|
+
};
|
|
65
|
+
if (void 0 !== input.entry) payload.entry = input.entry;
|
|
66
|
+
if (void 0 !== input.runtimeDigest) payload.runtimeDigest = input.runtimeDigest;
|
|
67
|
+
return payload;
|
|
68
|
+
}
|
|
69
|
+
function toModuleFederationFallbackAttributes(payload) {
|
|
70
|
+
return {
|
|
71
|
+
'data-mf-fallback-app': payload.appName,
|
|
72
|
+
'data-mf-fallback-classification': payload.reason,
|
|
73
|
+
'data-mf-fallback-phase': payload.phase,
|
|
74
|
+
'data-mf-fallback-remote': String(payload.metadata.remote),
|
|
75
|
+
'data-mf-fallback-status': String(payload.metadata.status),
|
|
76
|
+
'data-mf-telemetry-event': payload.eventName
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async function emitModuleFederationFallbackTelemetry(input, options = {}) {
|
|
80
|
+
const payload = createModuleFederationFallbackTelemetry(input);
|
|
81
|
+
if ("u" > typeof window && 'function' == typeof window.dispatchEvent && "u" > typeof CustomEvent) window.dispatchEvent(new CustomEvent(payload.eventName, {
|
|
82
|
+
detail: payload
|
|
83
|
+
}));
|
|
84
|
+
const shouldPost = true === options.postSignal || Boolean(options.endpoint);
|
|
85
|
+
if (!shouldPost) return {
|
|
86
|
+
dispatched: true,
|
|
87
|
+
posted: false
|
|
88
|
+
};
|
|
89
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
90
|
+
if ('function' != typeof fetchImpl) return {
|
|
91
|
+
dispatched: true,
|
|
92
|
+
posted: false
|
|
93
|
+
};
|
|
94
|
+
const headers = new Headers({
|
|
95
|
+
'content-type': 'application/json'
|
|
96
|
+
});
|
|
97
|
+
if (void 0 !== options.authToken && options.authToken.length > 0) headers.set(options.authHeaderName ?? DEFAULT_RUNTIME_FALLBACK_SIGNAL_AUTH_HEADER, options.authToken);
|
|
98
|
+
const response = await fetchImpl(options.endpoint ?? DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT, {
|
|
99
|
+
body: JSON.stringify(payload),
|
|
100
|
+
headers,
|
|
101
|
+
method: 'POST',
|
|
102
|
+
keepalive: true
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
dispatched: true,
|
|
106
|
+
posted: true,
|
|
107
|
+
postStatus: response.status
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export { DEFAULT_RUNTIME_FALLBACK_SIGNAL_AUTH_HEADER, DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT, MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT, MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT, ModuleFederationRemoteComponentContractError, ModuleFederationRemoteLoadError, ModuleFederationRemoteLoadTimeoutError, classifyModuleFederationFallback, createModuleFederationFallbackTelemetry, emitModuleFederationFallbackTelemetry, toModuleFederationFallbackAttributes };
|
|
@@ -6,7 +6,6 @@ import { ENTRY_POINT_RUNTIME_GLOBAL_CONTEXT_FILE_NAME } from "../../../cli/const
|
|
|
6
6
|
import { resolveSSRMode } from "../../../cli/ssr/mode.mjs";
|
|
7
7
|
import { FILE_SYSTEM_ROUTES_FILE_NAME } from "../constants.mjs";
|
|
8
8
|
import { walk } from "./nestedRoutes.mjs";
|
|
9
|
-
import { generateTanstackRouterTypesSourceForEntry, isTanstackRouterFrameworkEnabled } from "./tanstackTypes.mjs";
|
|
10
9
|
import { getServerCombinedModuleFile, getServerLoadersFile } from "./utils.mjs";
|
|
11
10
|
import * as __rspack_external__templates_mjs_4da4c6c8 from "./templates.mjs";
|
|
12
11
|
async function generateRoutesForEntry(entrypoint, appContext) {
|
|
@@ -41,42 +40,11 @@ async function generateRoutesForEntry(entrypoint, appContext) {
|
|
|
41
40
|
}
|
|
42
41
|
return routes;
|
|
43
42
|
}
|
|
44
|
-
const generateCode = async (appContext, config, entrypoints, api
|
|
43
|
+
const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
45
44
|
const { internalDirectory, srcDirectory, internalSrcAlias, packageName } = appContext;
|
|
46
45
|
const hooks = api.getHooks();
|
|
47
|
-
const enableTanstackTypes = options?.enableTanstackTypes ?? await isTanstackRouterFrameworkEnabled(appContext);
|
|
48
46
|
const generatedRoutesByEntry = {};
|
|
49
47
|
await Promise.all(entrypoints.map(generateEntryCode));
|
|
50
|
-
if (enableTanstackTypes) {
|
|
51
|
-
const allEntries = Array.from(new Set(entrypoints.map((e)=>e.entryName).filter(Boolean)));
|
|
52
|
-
const mainEntry = entrypoints.find((e)=>e.isMainEntry)?.entryName;
|
|
53
|
-
const registerEntries = allEntries.sort((a, b)=>{
|
|
54
|
-
if (mainEntry && a === mainEntry) return -1;
|
|
55
|
-
if (mainEntry && b === mainEntry) return 1;
|
|
56
|
-
return a.localeCompare(b);
|
|
57
|
-
});
|
|
58
|
-
if (registerEntries.length > 0) {
|
|
59
|
-
const registerDtsPath = path.join(srcDirectory, 'modern-tanstack', 'register.gen.d.ts');
|
|
60
|
-
const importStatements = registerEntries.map((entryName, index)=>`import type { router as router${index} } from './${entryName}/router.gen';`).join('\n');
|
|
61
|
-
const routerUnionType = registerEntries.map((_, index)=>`typeof router${index}`).join(' | ');
|
|
62
|
-
const registerContent = `// This file is auto-generated by Modern.js. Do not edit manually.
|
|
63
|
-
|
|
64
|
-
${importStatements}
|
|
65
|
-
|
|
66
|
-
declare module '@modern-js/runtime/tanstack-router' {
|
|
67
|
-
interface Register {
|
|
68
|
-
router: ${routerUnionType};
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
`;
|
|
72
|
-
try {
|
|
73
|
-
const prev = await fs.pathExists(registerDtsPath) ? await fs.readFile(registerDtsPath, 'utf-8') : null;
|
|
74
|
-
if (prev !== registerContent) await fs.outputFile(registerDtsPath, registerContent, 'utf-8');
|
|
75
|
-
} catch {
|
|
76
|
-
await fs.outputFile(registerDtsPath, registerContent, 'utf-8');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
48
|
async function generateEntryCode(entrypoint) {
|
|
81
49
|
const { entryName, isMainEntry, isAutoMount, pageRoutesEntry, nestedRoutesEntry } = entrypoint;
|
|
82
50
|
const { metaName } = api.getAppContext();
|
|
@@ -158,20 +126,6 @@ declare module '@modern-js/runtime/tanstack-router' {
|
|
|
158
126
|
await fs.outputFile(serverLoaderFile, serverLoaderCombined);
|
|
159
127
|
}
|
|
160
128
|
await fs.outputFile(path.resolve(internalDirectory, `./${entryName}/${FILE_SYSTEM_ROUTES_FILE_NAME}`), code, 'utf8');
|
|
161
|
-
if (enableTanstackTypes) {
|
|
162
|
-
const { routerGenTs } = await generateTanstackRouterTypesSourceForEntry({
|
|
163
|
-
appContext,
|
|
164
|
-
entryName,
|
|
165
|
-
routes: routes
|
|
166
|
-
});
|
|
167
|
-
const outPath = path.join(srcDirectory, 'modern-tanstack', entryName, 'router.gen.ts');
|
|
168
|
-
try {
|
|
169
|
-
const prev = await fs.pathExists(outPath) ? await fs.readFile(outPath, 'utf-8') : null;
|
|
170
|
-
if (prev !== routerGenTs) await fs.outputFile(outPath, routerGenTs, 'utf-8');
|
|
171
|
-
} catch {
|
|
172
|
-
await fs.outputFile(outPath, routerGenTs, 'utf-8');
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
129
|
}
|
|
176
130
|
}
|
|
177
131
|
}
|
|
@@ -102,20 +102,7 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
102
102
|
const loadersMapFile = path.join(internalDirectory, entryName, TEMP_LOADERS_DIR, 'map.json');
|
|
103
103
|
const importLazyCode = `
|
|
104
104
|
import { lazy } from "react";
|
|
105
|
-
import
|
|
106
|
-
|
|
107
|
-
const resolveLoadableExport = module => {
|
|
108
|
-
const candidates = [module, module.default, module.default?.default];
|
|
109
|
-
const loadable = candidates.find(candidate => typeof candidate === 'function');
|
|
110
|
-
|
|
111
|
-
if (!loadable) {
|
|
112
|
-
throw new TypeError('Modern.js runtime loadable export must resolve to a function');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return loadable;
|
|
116
|
-
};
|
|
117
|
-
const loadable = resolveLoadableExport(loadableModule);
|
|
118
|
-
const loadableLazy = loadableModule.lazy || loadableModule.default?.lazy || loadable.lazy;
|
|
105
|
+
import loadable, { lazy as loadableLazy } from "@${metaName}/runtime/loadable"
|
|
119
106
|
`;
|
|
120
107
|
let rootLayoutCode = "";
|
|
121
108
|
const getDataLoaderPath = ({ loaderId, clientData, action, inline, routeId, inValidSSRRoute })=>{
|
|
@@ -21,7 +21,7 @@ async function handleGeneratorEntryCode(api, entrypoints, options = {}) {
|
|
|
21
21
|
const { generatorRegisterCode, generateCode, generatorServerRegisterCode } = await import("./code/index.mjs");
|
|
22
22
|
originEntrypointsByKey.set(entrypointsKey, cloneDeep(entrypoints));
|
|
23
23
|
const enableRsc = resolvedConfig?.server?.rsc;
|
|
24
|
-
const routesByEntry = await generateCode(appContext, resolvedConfig, entrypoints, api
|
|
24
|
+
const routesByEntry = await generateCode(appContext, resolvedConfig, entrypoints, api);
|
|
25
25
|
await Promise.all(entrypoints.map(async (entrypoint)=>{
|
|
26
26
|
if (entrypoint.nestedRoutesEntry || entrypoint.pageRoutesEntry) {
|
|
27
27
|
const route = appContext.serverRoutes.find((r)=>r.entryName === entrypoint.entryName);
|
|
@@ -1,32 +1,12 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import node_path from "node:path";
|
|
3
|
-
import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer,
|
|
3
|
+
import { NESTED_ROUTE_SPEC_FILE, filterRoutesForServer, fs } from "@modern-js/utils";
|
|
4
4
|
import { NESTED_ROUTES_DIR } from "./constants.mjs";
|
|
5
5
|
import { BUILT_IN_ROUTES_OWNER, getEntrypointRoutesDir, getEntrypointRoutesOwner, isRouteEntry } from "./entry.mjs";
|
|
6
6
|
import { handleFileChange, handleGeneratorEntryCode, handleModifyEntrypoints } from "./handler.mjs";
|
|
7
7
|
import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
|
|
8
8
|
import { dirname as __rspack_dirname } from "node:path";
|
|
9
9
|
var cli_dirname = __rspack_dirname(__rspack_fileURLToPath(import.meta.url));
|
|
10
|
-
const JS_OR_TS_EXTS = [
|
|
11
|
-
'.js',
|
|
12
|
-
'.jsx',
|
|
13
|
-
'.ts',
|
|
14
|
-
'.tsx',
|
|
15
|
-
'.mjs',
|
|
16
|
-
'.mts',
|
|
17
|
-
'.cjs',
|
|
18
|
-
'.cts'
|
|
19
|
-
];
|
|
20
|
-
function hasRouterConfigInRuntimeFile(runtimeConfigBase) {
|
|
21
|
-
const runtimeConfigFile = findExists(JS_OR_TS_EXTS.map((ext)=>`${runtimeConfigBase}${ext}`));
|
|
22
|
-
if (!runtimeConfigFile) return false;
|
|
23
|
-
try {
|
|
24
|
-
const content = fs.readFileSync(runtimeConfigFile, 'utf-8');
|
|
25
|
-
return /router\s*:/.test(content);
|
|
26
|
-
} catch {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
10
|
function isBuiltInRouteEntrypoint(entrypoint) {
|
|
31
11
|
const entrypointRoutesOwner = getEntrypointRoutesOwner(entrypoint);
|
|
32
12
|
if (entrypointRoutesOwner) return entrypointRoutesOwner === BUILT_IN_ROUTES_OWNER;
|
|
@@ -56,12 +36,11 @@ const routerPlugin = ()=>({
|
|
|
56
36
|
});
|
|
57
37
|
});
|
|
58
38
|
api._internalRuntimePlugins(({ entrypoint, plugins })=>{
|
|
59
|
-
const { serverRoutes, metaName
|
|
39
|
+
const { serverRoutes, metaName } = api.getAppContext();
|
|
60
40
|
const normalizedConfig = api.getNormalizedConfig();
|
|
61
41
|
const hasUserRouterConfig = normalizedConfig.router && Object.keys(normalizedConfig.router).length > 0;
|
|
62
|
-
const hasRuntimeRouterConfig = hasRouterConfigInRuntimeFile(node_path.join(srcDirectory, runtimeConfigFile));
|
|
63
42
|
const serverBase = serverRoutes.filter((route)=>route.entryName === entrypoint.entryName).map((route)=>route.urlPath).sort((a, b)=>a.length - b.length > 0 ? -1 : 1);
|
|
64
|
-
const shouldInstallBuiltInRouter = isBuiltInRouteEntrypoint(entrypoint) || !isPluginOwnedRouteEntrypoint(entrypoint) &&
|
|
43
|
+
const shouldInstallBuiltInRouter = isBuiltInRouteEntrypoint(entrypoint) || !isPluginOwnedRouteEntrypoint(entrypoint) && hasUserRouterConfig;
|
|
65
44
|
if (shouldInstallBuiltInRouter) plugins.push({
|
|
66
45
|
name: 'router',
|
|
67
46
|
path: `@${metaName}/runtime/router/internal`,
|
|
@@ -5,6 +5,21 @@ import { useEffect, useMemo, useRef } from "react";
|
|
|
5
5
|
import { ROUTER_DATA_JSON_ID } from "../../core/constants.mjs";
|
|
6
6
|
import { modernInline, runWindowFnStr } from "./constants.mjs";
|
|
7
7
|
import { serializeErrors } from "./utils.mjs";
|
|
8
|
+
function toDeferredErrorInfo(error) {
|
|
9
|
+
if ('production' === process.env.NODE_ENV) return {
|
|
10
|
+
message: 'Unexpected Server Error'
|
|
11
|
+
};
|
|
12
|
+
if (error && 'object' == typeof error) {
|
|
13
|
+
const maybeMessage = error.message;
|
|
14
|
+
return {
|
|
15
|
+
message: 'string' == typeof maybeMessage ? maybeMessage : String(maybeMessage ?? error),
|
|
16
|
+
stack: error.stack
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
message: String(error)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
8
23
|
const DeferredDataScripts = (props)=>{
|
|
9
24
|
const staticContext = props?.context;
|
|
10
25
|
const useJsonScript = props?.useJsonScript;
|
|
@@ -40,10 +55,7 @@ const DeferredDataScripts = (props)=>{
|
|
|
40
55
|
{
|
|
41
56
|
const trackedPromise = deferredData.data[key];
|
|
42
57
|
if (void 0 !== trackedPromise._error) {
|
|
43
|
-
const error =
|
|
44
|
-
message: trackedPromise._error.message,
|
|
45
|
-
stack: 'production' !== process.env.NODE_ENV ? trackedPromise._error.stack : void 0
|
|
46
|
-
};
|
|
58
|
+
const error = toDeferredErrorInfo(trackedPromise._error);
|
|
47
59
|
return {
|
|
48
60
|
key,
|
|
49
61
|
routerDataFnName: 'p',
|
|
@@ -12,7 +12,6 @@ function composeEventHandlers(theirHandler, ourHandler) {
|
|
|
12
12
|
}
|
|
13
13
|
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
14
14
|
const DEFAULT_PREFETCH_BEHAVIOR = 'render';
|
|
15
|
-
const DEFAULT_PRELOAD_BEHAVIOR = 'viewport';
|
|
16
15
|
const INTENT_DELAY = 100;
|
|
17
16
|
const VIEWPORT_ROOT_MARGIN = '200px';
|
|
18
17
|
const MAX_CONCURRENT_WARMUPS = 4;
|
|
@@ -77,7 +76,7 @@ const setRef = (ref, value)=>{
|
|
|
77
76
|
};
|
|
78
77
|
const isDataWarmupEnabled = (route)=>{
|
|
79
78
|
const handle = route.handle;
|
|
80
|
-
return handle?.navigationWarmup?.data
|
|
79
|
+
return handle?.navigationWarmup?.data !== false;
|
|
81
80
|
};
|
|
82
81
|
function usePrefetchBehavior(prefetch, preload, theirElementProps) {
|
|
83
82
|
const [maybeWarmup, setMaybeWarmup] = react.useState(false);
|
|
@@ -251,7 +250,7 @@ const normalizePreloadBehavior = (preload, prefetch)=>{
|
|
|
251
250
|
if (false === preload || 'none' === preload) return 'none';
|
|
252
251
|
if (void 0 !== preload) return preload;
|
|
253
252
|
if ('none' === prefetch) return 'none';
|
|
254
|
-
return
|
|
253
|
+
return prefetch;
|
|
255
254
|
};
|
|
256
255
|
const createPrefetchLink = (Link)=>/*#__PURE__*/ react.forwardRef(({ to, prefetch = DEFAULT_PREFETCH_BEHAVIOR, preload, ...props }, forwardedRef)=>{
|
|
257
256
|
const isAbsolute = 'string' == typeof to && ABSOLUTE_URL_REGEX.test(to);
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { merge } from "@modern-js/runtime-utils/merge";
|
|
3
|
-
import { modifyRoutes,
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import { modifyRoutes, routerPlugin } from "./plugin.mjs";
|
|
4
|
+
import { registerRouterProvider, reportUnsupportedProviderRegistryHooks, resolveRouterProvider, routerProviderRegistryHooks } from "./provider.mjs";
|
|
5
|
+
registerRouterProvider('react-router', routerPlugin, {
|
|
6
|
+
isDefault: true
|
|
7
|
+
});
|
|
6
8
|
const internal_routerPlugin = (userConfig = {})=>({
|
|
7
9
|
name: '@modern-js/plugin-router',
|
|
8
|
-
registryHooks:
|
|
9
|
-
onAfterCreateRouter: onAfterCreateRouter,
|
|
10
|
-
onAfterHydrateRouter: onAfterHydrateRouter,
|
|
11
|
-
onBeforeCreateRouter: onBeforeCreateRouter,
|
|
12
|
-
modifyRoutes: modifyRoutes,
|
|
13
|
-
onBeforeCreateRoutes: onBeforeCreateRoutes,
|
|
14
|
-
onBeforeHydrateRouter: onBeforeHydrateRouter
|
|
15
|
-
},
|
|
10
|
+
registryHooks: routerProviderRegistryHooks,
|
|
16
11
|
setup: (api)=>{
|
|
17
12
|
const mergedConfig = merge(api.getRuntimeConfig().router || {}, userConfig);
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
const pluginFactory = resolveRouterProvider(mergedConfig.framework, {
|
|
14
|
+
localDefault: {
|
|
15
|
+
name: 'react-router',
|
|
16
|
+
factory: routerPlugin
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const providerPlugin = pluginFactory(userConfig);
|
|
20
|
+
reportUnsupportedProviderRegistryHooks(providerPlugin);
|
|
21
|
+
providerPlugin.setup?.(api);
|
|
21
22
|
}
|
|
22
23
|
});
|
|
23
24
|
const internal = internal_routerPlugin;
|
|
24
25
|
export { renderRoutes } from "./utils.mjs";
|
|
25
26
|
export default internal;
|
|
26
|
-
export {
|
|
27
|
+
export { internal_routerPlugin as routerPlugin, modifyRoutes, registerRouterProvider, resolveRouterProvider };
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
import { createRuntimeContextExtension } from "../../core/context/extensions.mjs";
|
|
3
|
+
const routerRuntimeStateExtension = createRuntimeContextExtension('@modern-js/runtime:router-runtime-state');
|
|
4
|
+
const routerServerSnapshotExtension = createRuntimeContextExtension('@modern-js/runtime:router-server-snapshot');
|
|
5
|
+
function getRouterRuntimeState(runtimeContext) {
|
|
6
|
+
return routerRuntimeStateExtension.get(runtimeContext);
|
|
7
|
+
}
|
|
8
|
+
function getRouterServerSnapshot(runtimeContext) {
|
|
9
|
+
return routerServerSnapshotExtension.get(runtimeContext);
|
|
10
|
+
}
|
|
2
11
|
function toHydrationScripts(state) {
|
|
3
12
|
if (state.hydrationScripts?.length) return state.hydrationScripts;
|
|
4
13
|
return state.hydrationScript ? [
|
|
@@ -62,12 +71,8 @@ function createRouterRuntimeState(state) {
|
|
|
62
71
|
}
|
|
63
72
|
function applyRouterRuntimeState(runtimeContext, state) {
|
|
64
73
|
const normalized = createRouterRuntimeState(state);
|
|
65
|
-
runtimeContext
|
|
66
|
-
|
|
67
|
-
runtimeContext.routerHydrationScript = normalized.hydrationScript;
|
|
68
|
-
runtimeContext.routerMatchedRouteIds = normalized.matchedRouteIds;
|
|
69
|
-
runtimeContext.routerRuntime = normalized;
|
|
70
|
-
if (normalized.serverSnapshot) runtimeContext.routerServerSnapshot = normalized.serverSnapshot;
|
|
74
|
+
routerRuntimeStateExtension.set(runtimeContext, normalized);
|
|
75
|
+
if (normalized.serverSnapshot) routerServerSnapshotExtension.set(runtimeContext, normalized.serverSnapshot);
|
|
71
76
|
return runtimeContext;
|
|
72
77
|
}
|
|
73
78
|
function applyRouterServerPrepareResult(runtimeContext, result) {
|
|
@@ -80,18 +85,22 @@ function applyRouterServerPrepareResult(runtimeContext, result) {
|
|
|
80
85
|
return runtimeContext;
|
|
81
86
|
}
|
|
82
87
|
function getRouterHydrationScripts(runtimeContext) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
hydrationScript:
|
|
88
|
+
const serverSnapshot = getRouterServerSnapshot(runtimeContext);
|
|
89
|
+
const runtimeState = getRouterRuntimeState(runtimeContext);
|
|
90
|
+
return serverSnapshot?.hydrationScripts ?? toHydrationScripts({
|
|
91
|
+
hydrationScript: serverSnapshot?.hydrationScript
|
|
92
|
+
}) ?? runtimeState?.hydrationScripts ?? toHydrationScripts({
|
|
93
|
+
hydrationScript: runtimeState?.hydrationScript
|
|
87
94
|
}) ?? [];
|
|
88
95
|
}
|
|
89
96
|
function getRouterMatchedRouteIds(runtimeContext) {
|
|
90
|
-
|
|
97
|
+
const serverSnapshot = getRouterServerSnapshot(runtimeContext);
|
|
98
|
+
const runtimeState = getRouterRuntimeState(runtimeContext);
|
|
99
|
+
return serverSnapshot?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(serverSnapshot?.matches) ?? runtimeState?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(runtimeState?.matches);
|
|
91
100
|
}
|
|
92
101
|
async function cleanupRouterRuntimeState(runtimeContext) {
|
|
93
102
|
try {
|
|
94
|
-
await runtimeContext
|
|
103
|
+
await getRouterRuntimeState(runtimeContext)?.cleanup?.();
|
|
95
104
|
} catch {}
|
|
96
105
|
}
|
|
97
|
-
export { applyRouterRuntimeState, applyRouterServerPrepareResult, cleanupRouterRuntimeState, createRouterRuntimeState, createRouterServerSnapshot, getRouterHydrationScripts, getRouterMatchedRouteIds };
|
|
106
|
+
export { applyRouterRuntimeState, applyRouterServerPrepareResult, cleanupRouterRuntimeState, createRouterRuntimeState, createRouterServerSnapshot, getRouterHydrationScripts, getRouterMatchedRouteIds, getRouterRuntimeState, getRouterServerSnapshot };
|
|
@@ -5,15 +5,15 @@ import { RouterProvider, createBrowserRouter, createHashRouter, createRoutesFrom
|
|
|
5
5
|
import { normalizePathname } from "@modern-js/runtime-utils/url";
|
|
6
6
|
import * as __rspack_external_react from "react";
|
|
7
7
|
import { InternalRuntimeContext, getGlobalIsRscClient, getGlobalLayoutApp, getGlobalRoutes } from "../../core/context/index.mjs";
|
|
8
|
-
import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
|
|
9
8
|
import { applyRouterRuntimeState } from "./lifecycle.mjs";
|
|
9
|
+
import { routerProviderRegistryHooks } from "./provider.mjs";
|
|
10
10
|
import { createClientRouterFromPayload } from "./rsc-router.mjs";
|
|
11
11
|
import { createRouteObjectsFromConfig, deserializeErrors, renderRoutes, urlJoin } from "./utils.mjs";
|
|
12
12
|
let finalRouteConfig = {
|
|
13
13
|
routes: []
|
|
14
14
|
};
|
|
15
15
|
let beforeCreateRouter = true;
|
|
16
|
-
function
|
|
16
|
+
function modifyRoutes(modifyFunction) {
|
|
17
17
|
if (beforeCreateRouter) {
|
|
18
18
|
const { routes: originRoutes } = finalRouteConfig;
|
|
19
19
|
const newRoutes = modifyFunction(originRoutes);
|
|
@@ -22,14 +22,7 @@ function plugin_modifyRoutes(modifyFunction) {
|
|
|
22
22
|
}
|
|
23
23
|
const routerPlugin = (userConfig = {})=>({
|
|
24
24
|
name: '@modern-js/plugin-router',
|
|
25
|
-
registryHooks:
|
|
26
|
-
onAfterCreateRouter: onAfterCreateRouter,
|
|
27
|
-
onAfterHydrateRouter: onAfterHydrateRouter,
|
|
28
|
-
onBeforeCreateRouter: onBeforeCreateRouter,
|
|
29
|
-
modifyRoutes: modifyRoutes,
|
|
30
|
-
onBeforeCreateRoutes: onBeforeCreateRoutes,
|
|
31
|
-
onBeforeHydrateRouter: onBeforeHydrateRouter
|
|
32
|
-
},
|
|
25
|
+
registryHooks: routerProviderRegistryHooks,
|
|
33
26
|
setup: (api)=>{
|
|
34
27
|
const routesContainer = {
|
|
35
28
|
current: []
|
|
@@ -217,4 +210,4 @@ function useRouterCreation(props, options) {
|
|
|
217
210
|
getBlockNavState
|
|
218
211
|
]);
|
|
219
212
|
}
|
|
220
|
-
export { beforeCreateRouter, finalRouteConfig,
|
|
213
|
+
export { beforeCreateRouter, finalRouteConfig, modifyRoutes, routerPlugin };
|
|
@@ -9,8 +9,8 @@ import { useContext } from "react";
|
|
|
9
9
|
import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "../../core/context/index.mjs";
|
|
10
10
|
import { setServerPayload } from "../../core/context/serverPayload/index.server.mjs";
|
|
11
11
|
import DeferredDataScripts_node from "./DeferredDataScripts.node.mjs";
|
|
12
|
-
import { modifyRoutes, onAfterCreateRouter, onBeforeCreateRouter, onBeforeCreateRoutes } from "./hooks.mjs";
|
|
13
12
|
import { applyRouterRuntimeState, createRouterServerSnapshot } from "./lifecycle.mjs";
|
|
13
|
+
import { routerProviderRegistryHooks } from "./provider.mjs";
|
|
14
14
|
import { RSCStaticRouter, createServerPayload, handleRSCRedirect, prepareRSCRoutes } from "./rsc-router.mjs";
|
|
15
15
|
import { createRouteObjectsFromConfig, renderRoutes, urlJoin } from "./utils.mjs";
|
|
16
16
|
function createRemixRequest(request) {
|
|
@@ -43,12 +43,7 @@ function createReactRouterServerSnapshot(routerContext, basename) {
|
|
|
43
43
|
}
|
|
44
44
|
const routerPlugin = (userConfig = {})=>({
|
|
45
45
|
name: '@modern-js/plugin-router',
|
|
46
|
-
registryHooks:
|
|
47
|
-
onAfterCreateRouter: onAfterCreateRouter,
|
|
48
|
-
onBeforeCreateRouter: onBeforeCreateRouter,
|
|
49
|
-
modifyRoutes: modifyRoutes,
|
|
50
|
-
onBeforeCreateRoutes: onBeforeCreateRoutes
|
|
51
|
-
},
|
|
46
|
+
registryHooks: routerProviderRegistryHooks,
|
|
52
47
|
setup: (api)=>{
|
|
53
48
|
let finalRouteConfig = {};
|
|
54
49
|
api.onBeforeRender(async (context, interrupt)=>{
|
|
@@ -176,5 +171,5 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
176
171
|
});
|
|
177
172
|
}
|
|
178
173
|
});
|
|
179
|
-
const
|
|
180
|
-
export {
|
|
174
|
+
const modifyRoutes = ()=>{};
|
|
175
|
+
export { modifyRoutes, routerPlugin };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter } from "./hooks.mjs";
|
|
3
|
+
const routerProviderRegistryHooks = {
|
|
4
|
+
modifyRoutes: modifyRoutes,
|
|
5
|
+
onBeforeCreateRoutes: onBeforeCreateRoutes,
|
|
6
|
+
onBeforeCreateRouter: onBeforeCreateRouter,
|
|
7
|
+
onAfterCreateRouter: onAfterCreateRouter,
|
|
8
|
+
onBeforeHydrateRouter: onBeforeHydrateRouter,
|
|
9
|
+
onAfterHydrateRouter: onAfterHydrateRouter
|
|
10
|
+
};
|
|
11
|
+
function reportUnsupportedProviderRegistryHooks(providerPlugin) {
|
|
12
|
+
const unsupportedHookNames = Object.keys(providerPlugin.registryHooks ?? {}).filter((hookName)=>!(hookName in routerProviderRegistryHooks));
|
|
13
|
+
if (unsupportedHookNames.length > 0) console.warn(`[@modern-js/runtime] The router provider "${providerPlugin.name}" declares registry hooks outside the router hook contract: ${unsupportedHookNames.join(', ')}. These hooks are not registered when the provider is resolved through \`runtime.router.framework\` — declare them on a separate runtime plugin instead.`);
|
|
14
|
+
return unsupportedHookNames;
|
|
15
|
+
}
|
|
16
|
+
const REGISTRY_SLOT = Symbol.for('@modern-js/runtime:router-providers:v2');
|
|
17
|
+
function getRegistry() {
|
|
18
|
+
const host = globalThis;
|
|
19
|
+
host[REGISTRY_SLOT] ??= {
|
|
20
|
+
providers: new Map(),
|
|
21
|
+
warnedDuplicates: new Set()
|
|
22
|
+
};
|
|
23
|
+
host[REGISTRY_SLOT].warnedDuplicates ??= new Set();
|
|
24
|
+
return host[REGISTRY_SLOT];
|
|
25
|
+
}
|
|
26
|
+
function registerRouterProvider(name, factory, options = {}) {
|
|
27
|
+
const registry = getRegistry();
|
|
28
|
+
const existing = registry.providers.get(name);
|
|
29
|
+
if (void 0 !== existing) {
|
|
30
|
+
if (existing !== factory && !registry.warnedDuplicates.has(name)) {
|
|
31
|
+
registry.warnedDuplicates.add(name);
|
|
32
|
+
console.warn(`[@modern-js/runtime] The router provider "${name}" was registered more than once with different module instances; keeping the first registration. This usually means two copies of the providing plugin were bundled — for Module Federation, add the provider runtime (e.g. '@modern-js/plugin-tanstack/runtime') to the shared modules of both the host and the remote to deduplicate it.`);
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (true !== options.isDefault) {
|
|
37
|
+
if (void 0 !== registry.nonDefaultProvider && registry.nonDefaultProvider !== name) throw new Error(`[@modern-js/runtime] Cannot register router provider "${name}": the competing router provider "${registry.nonDefaultProvider}" is already registered. Only one non-default router provider may be installed at a time — remove one of the router plugins.`);
|
|
38
|
+
registry.nonDefaultProvider = name;
|
|
39
|
+
} else registry.defaultProvider = name;
|
|
40
|
+
registry.providers.set(name, factory);
|
|
41
|
+
}
|
|
42
|
+
function resolveRouterProvider(framework, options = {}) {
|
|
43
|
+
const registry = getRegistry();
|
|
44
|
+
const name = framework || registry.defaultProvider || options.localDefault?.name;
|
|
45
|
+
if (void 0 === name) throw new Error('[@modern-js/runtime] No default router provider is registered. This is a bug in the runtime setup.');
|
|
46
|
+
if (void 0 !== options.localDefault && name === options.localDefault.name) return options.localDefault.factory;
|
|
47
|
+
const factory = registry.providers.get(name);
|
|
48
|
+
if (void 0 !== factory) return factory;
|
|
49
|
+
if ('tanstack' === name) throw new Error("[@modern-js/runtime] `runtime.router.framework` is set to \"tanstack\", but no TanStack router provider is registered. Install @modern-js/plugin-tanstack, add `tanstackRouterPlugin()` to the `plugins` array in modern.config.ts, and make sure '@modern-js/plugin-tanstack/runtime' is imported (e.g. in modern.runtime.ts).");
|
|
50
|
+
throw new Error(`[@modern-js/runtime] Unknown router framework "${name}". Registered providers: ${[
|
|
51
|
+
...registry.providers.keys()
|
|
52
|
+
].join(', ') || '(none)'}. Install and register the plugin that provides this router framework.`);
|
|
53
|
+
}
|
|
54
|
+
function unsafe_resetRouterProvidersForTesting() {
|
|
55
|
+
const host = globalThis;
|
|
56
|
+
delete host[REGISTRY_SLOT];
|
|
57
|
+
}
|
|
58
|
+
export { registerRouterProvider, reportUnsupportedProviderRegistryHooks, resolveRouterProvider, routerProviderRegistryHooks, unsafe_resetRouterProvidersForTesting };
|
|
@@ -99,7 +99,10 @@ function getRouteObjects(routes, { globalApp, ssrMode, props }) {
|
|
|
99
99
|
}
|
|
100
100
|
routeObjects.push({
|
|
101
101
|
path: '*',
|
|
102
|
-
element: /*#__PURE__*/ jsx(DefaultNotFound, {})
|
|
102
|
+
element: /*#__PURE__*/ jsx(DefaultNotFound, {}),
|
|
103
|
+
loader: ()=>new Response('404', {
|
|
104
|
+
status: 404
|
|
105
|
+
})
|
|
103
106
|
});
|
|
104
107
|
return routeObjects;
|
|
105
108
|
}
|
|
@@ -148,17 +151,40 @@ function serializeErrors(errors) {
|
|
|
148
151
|
if (!errors) return null;
|
|
149
152
|
const entries = Object.entries(errors);
|
|
150
153
|
const serialized = {};
|
|
151
|
-
for (const [key, val] of entries)if (isRouteErrorResponse(val)) serialized[key] =
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
for (const [key, val] of entries)if (isRouteErrorResponse(val)) serialized[key] = serializeRouteErrorResponse(val);
|
|
155
|
+
else if (val instanceof Error) serialized[key] = serializeError(val);
|
|
156
|
+
else serialized[key] = val;
|
|
157
|
+
return serialized;
|
|
158
|
+
}
|
|
159
|
+
function shouldRedactServerError() {
|
|
160
|
+
return 'development' !== process.env.NODE_ENV && 'test' !== process.env.NODE_ENV;
|
|
161
|
+
}
|
|
162
|
+
function serializeError(error) {
|
|
163
|
+
if (shouldRedactServerError()) return {
|
|
164
|
+
message: 'Unexpected Server Error',
|
|
165
|
+
stack: void 0,
|
|
166
|
+
__type: 'Error'
|
|
154
167
|
};
|
|
155
|
-
|
|
156
|
-
message:
|
|
157
|
-
stack:
|
|
168
|
+
return {
|
|
169
|
+
message: error.message,
|
|
170
|
+
stack: error.stack,
|
|
158
171
|
__type: 'Error'
|
|
159
172
|
};
|
|
160
|
-
|
|
161
|
-
|
|
173
|
+
}
|
|
174
|
+
function serializeRouteErrorResponse(error) {
|
|
175
|
+
if (!isRouteErrorResponse(error)) return error;
|
|
176
|
+
if (error.status >= 500 && shouldRedactServerError()) return {
|
|
177
|
+
status: error.status,
|
|
178
|
+
statusText: 'Internal Server Error',
|
|
179
|
+
data: 'Unexpected Server Error',
|
|
180
|
+
__type: 'RouteErrorResponse'
|
|
181
|
+
};
|
|
182
|
+
return {
|
|
183
|
+
status: error.status,
|
|
184
|
+
statusText: error.statusText,
|
|
185
|
+
data: error.data,
|
|
186
|
+
__type: 'RouteErrorResponse'
|
|
187
|
+
};
|
|
162
188
|
}
|
|
163
189
|
function deserializeErrors(errors) {
|
|
164
190
|
if (!errors) return null;
|
|
@@ -2,7 +2,9 @@ import type { AppTools, CliPlugin } from '@modern-js/app-tools';
|
|
|
2
2
|
import { documentPlugin } from '../document/cli';
|
|
3
3
|
import { routerPlugin } from '../router/cli';
|
|
4
4
|
import { ssrPlugin } from './ssr';
|
|
5
|
-
export { getEntrypointRoutesDir, handleFileChange, handleGeneratorEntryCode, handleModifyEntrypoints, isRouteEntry, } from '../router/cli';
|
|
5
|
+
export { getEntrypointRoutesDir, getEntrypointRoutesOwner, handleFileChange, handleGeneratorEntryCode, handleModifyEntrypoints, isRouteEntry, } from '../router/cli';
|
|
6
|
+
export { makeLegalIdentifier } from '../router/cli/code/makeLegalIdentifier';
|
|
7
|
+
export { getPathWithoutExt } from '../router/cli/code/utils';
|
|
6
8
|
export { isRuntimeEntry } from './entry';
|
|
7
9
|
export { documentPlugin, routerPlugin, ssrPlugin };
|
|
8
10
|
export declare const runtimePlugin: (params?: {
|