@bleedingdev/modern-js-runtime 3.5.0-ultramodern.10 → 3.5.0-ultramodern.100
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 +13 -3
- package/dist/cjs/cli/index.js +1 -11
- package/dist/cjs/cli/registry.js +18 -0
- package/dist/cjs/cli/ssr/index.js +3 -2
- package/dist/cjs/cli/ssr/loadable-bundler-plugin.js +8 -4
- package/dist/cjs/core/browser/hydrate.js +16 -2
- package/dist/cjs/core/browser/index.js +19 -18
- package/dist/cjs/core/context/index.js +3 -0
- package/dist/cjs/core/context/public.js +49 -0
- package/dist/cjs/core/context/runtime.js +6 -8
- package/dist/cjs/core/react/wrapper.js +57 -0
- package/dist/cjs/core/server/federatedCss.js +7 -3
- package/dist/cjs/core/server/requestHandler.js +15 -45
- package/dist/cjs/core/server/requestResponse.js +83 -0
- package/dist/cjs/core/server/routerCleanup.js +16 -6
- package/dist/cjs/core/server/scriptOrder.js +13 -10
- package/dist/cjs/core/server/stream/afterTemplate.js +9 -5
- package/dist/cjs/core/server/stream/template.js +3 -3
- package/dist/cjs/core/server/string/index.js +3 -3
- package/dist/cjs/core/server/string/loadable.js +3 -11
- package/dist/cjs/index.js +7 -6
- package/dist/cjs/module-federation/consume-surface.js +199 -0
- package/dist/cjs/module-federation/distributed-ssr.js +134 -0
- package/dist/cjs/module-federation/index.js +258 -120
- package/dist/cjs/module-federation/last-known-good.js +124 -0
- package/dist/cjs/module-federation/manifest-recovery-runtime-plugin.js +140 -0
- package/dist/cjs/module-federation/surface-resolution-types.js +61 -0
- package/dist/cjs/router/cli/code/nestedRoutes.js +3 -0
- package/dist/cjs/router/cli/code/templates.js +3 -2
- package/dist/cjs/router/cli/constants.js +1 -0
- package/dist/cjs/router/cli/nestedRoutesSpec.js +3 -1
- package/dist/cjs/router/runtime/hooks.js +7 -6
- package/dist/cjs/router/runtime/internal.js +30 -16
- package/dist/cjs/router/runtime/plugin.js +6 -7
- package/dist/cjs/router/runtime/provider.js +58 -12
- package/dist/esm/boundary-debugger/index.mjs +13 -3
- package/dist/esm/cli/code.mjs +12 -12
- package/dist/esm/cli/index.mjs +2 -12
- package/dist/esm/cli/registry.mjs +0 -0
- package/dist/esm/cli/ssr/index.mjs +3 -2
- package/dist/esm/cli/ssr/loadable-bundler-plugin.mjs +8 -4
- package/dist/esm/core/browser/hydrate.mjs +15 -4
- package/dist/esm/core/browser/index.mjs +15 -17
- package/dist/esm/core/context/index.mjs +1 -1
- package/dist/esm/core/context/public.mjs +5 -0
- package/dist/esm/core/context/runtime.mjs +4 -6
- package/dist/esm/core/react/wrapper.mjs +58 -1
- package/dist/esm/core/server/federatedCss.mjs +7 -3
- package/dist/esm/core/server/requestHandler.mjs +15 -45
- package/dist/esm/core/server/requestResponse.mjs +39 -0
- package/dist/esm/core/server/routerCleanup.mjs +11 -4
- package/dist/esm/core/server/scriptOrder.mjs +11 -8
- package/dist/esm/core/server/stream/afterTemplate.mjs +10 -6
- package/dist/esm/core/server/stream/template.mjs +3 -3
- package/dist/esm/core/server/string/index.mjs +3 -3
- package/dist/esm/core/server/string/loadable.mjs +3 -8
- package/dist/esm/exports/loadable.mjs +3 -3
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/module-federation/consume-surface.mjs +158 -0
- package/dist/esm/module-federation/distributed-ssr.mjs +81 -0
- package/dist/esm/module-federation/index.mjs +6 -0
- package/dist/esm/module-federation/last-known-good.mjs +80 -0
- package/dist/esm/module-federation/manifest-recovery-runtime-plugin.mjs +100 -0
- package/dist/esm/module-federation/surface-resolution-types.mjs +8 -0
- package/dist/esm/router/cli/code/index.mjs +5 -5
- package/dist/esm/router/cli/code/nestedRoutes.mjs +3 -0
- package/dist/esm/router/cli/code/templates.mjs +3 -2
- package/dist/esm/router/cli/constants.mjs +1 -0
- package/dist/esm/router/cli/handler.mjs +3 -3
- package/dist/esm/router/cli/nestedRoutesSpec.mjs +3 -1
- package/dist/esm/router/runtime/hooks.mjs +7 -6
- package/dist/esm/router/runtime/internal.mjs +26 -18
- package/dist/esm/router/runtime/plugin.mjs +6 -7
- package/dist/esm/router/runtime/provider.mjs +56 -13
- package/dist/esm-node/boundary-debugger/index.mjs +13 -3
- package/dist/esm-node/cli/code.mjs +12 -12
- package/dist/esm-node/cli/index.mjs +2 -12
- package/dist/esm-node/cli/registry.mjs +1 -0
- package/dist/esm-node/cli/ssr/index.mjs +3 -2
- package/dist/esm-node/cli/ssr/loadable-bundler-plugin.mjs +8 -4
- package/dist/esm-node/core/browser/hydrate.mjs +15 -4
- package/dist/esm-node/core/browser/index.mjs +15 -17
- package/dist/esm-node/core/context/index.mjs +1 -1
- package/dist/esm-node/core/context/public.mjs +6 -0
- package/dist/esm-node/core/context/runtime.mjs +4 -6
- package/dist/esm-node/core/react/wrapper.mjs +58 -1
- package/dist/esm-node/core/server/federatedCss.mjs +7 -3
- package/dist/esm-node/core/server/requestHandler.mjs +15 -45
- package/dist/esm-node/core/server/requestResponse.mjs +40 -0
- package/dist/esm-node/core/server/routerCleanup.mjs +11 -4
- package/dist/esm-node/core/server/scriptOrder.mjs +11 -8
- package/dist/esm-node/core/server/stream/afterTemplate.mjs +10 -6
- package/dist/esm-node/core/server/stream/template.mjs +3 -3
- package/dist/esm-node/core/server/string/index.mjs +3 -3
- package/dist/esm-node/core/server/string/loadable.mjs +3 -8
- package/dist/esm-node/exports/loadable.mjs +3 -3
- package/dist/esm-node/index.mjs +2 -1
- package/dist/esm-node/module-federation/consume-surface.mjs +159 -0
- package/dist/esm-node/module-federation/distributed-ssr.mjs +82 -0
- package/dist/esm-node/module-federation/index.mjs +6 -0
- package/dist/esm-node/module-federation/last-known-good.mjs +81 -0
- package/dist/esm-node/module-federation/manifest-recovery-runtime-plugin.mjs +101 -0
- package/dist/esm-node/module-federation/surface-resolution-types.mjs +9 -0
- package/dist/esm-node/router/cli/code/index.mjs +5 -5
- package/dist/esm-node/router/cli/code/nestedRoutes.mjs +3 -0
- package/dist/esm-node/router/cli/code/templates.mjs +3 -2
- package/dist/esm-node/router/cli/constants.mjs +1 -0
- package/dist/esm-node/router/cli/handler.mjs +3 -3
- package/dist/esm-node/router/cli/nestedRoutesSpec.mjs +3 -1
- package/dist/esm-node/router/runtime/hooks.mjs +7 -6
- package/dist/esm-node/router/runtime/internal.mjs +26 -18
- package/dist/esm-node/router/runtime/plugin.mjs +6 -7
- package/dist/esm-node/router/runtime/provider.mjs +56 -13
- package/dist/types/boundary-debugger/index.d.ts +1 -1
- package/dist/types/cli/registry.d.ts +2 -0
- package/dist/types/common.d.ts +8 -1
- package/dist/types/core/browser/hydrate.d.ts +2 -1
- package/dist/types/core/browser/index.d.ts +4 -1
- package/dist/types/core/context/index.d.ts +26 -10
- package/dist/types/core/context/monitors/default.d.ts +10 -2
- package/dist/types/core/context/monitors/index.d.ts +1 -1
- package/dist/types/core/context/monitors/index.server.d.ts +2 -2
- package/dist/types/core/context/public.d.ts +27 -0
- package/dist/types/core/context/runtime.d.ts +12 -22
- package/dist/types/core/react/index.d.ts +1 -1
- package/dist/types/core/server/requestResponse.d.ts +15 -0
- package/dist/types/core/server/routerCleanup.d.ts +2 -1
- package/dist/types/core/server/scriptOrder.d.ts +1 -1
- package/dist/types/core/server/stream/shared.d.ts +2 -2
- package/dist/types/core/server/string/loadable.d.ts +0 -2
- package/dist/types/exports/head.d.ts +1 -1
- package/dist/types/index.d.ts +5 -5
- package/dist/types/internal.d.ts +0 -1
- package/dist/types/module-federation/consume-surface.d.ts +104 -0
- package/dist/types/module-federation/distributed-ssr.d.ts +61 -0
- package/dist/types/module-federation/index.d.ts +6 -0
- package/dist/types/module-federation/last-known-good.d.ts +72 -0
- package/dist/types/module-federation/manifest-recovery-runtime-plugin.d.ts +25 -0
- package/dist/types/module-federation/surface-resolution-types.d.ts +23 -0
- package/dist/types/router/cli/constants.d.ts +1 -0
- package/dist/types/router/runtime/hooks.d.ts +10 -6
- package/dist/types/router/runtime/internal.d.ts +13 -3
- 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 +28 -11
- package/dist/types/router/runtime/types.d.ts +27 -5
- package/package.json +47 -27
- package/dist/cjs/exports/tanstack-router.js +0 -83
- package/dist/esm/exports/tanstack-router.mjs +0 -30
- package/dist/esm-node/exports/tanstack-router.mjs +0 -31
- package/dist/types/exports/tanstack-router.d.ts +0 -88
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useRuntimeContext } from "../core/context/runtime.mjs";
|
|
4
|
+
const DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY = '__modernDistributedSsrFragments';
|
|
5
|
+
const DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY = '__modernDistributedSsrFragmentRequest';
|
|
6
|
+
function distributedSsrFragmentKey(remote, expose) {
|
|
7
|
+
return `${remote}::${expose}`;
|
|
8
|
+
}
|
|
9
|
+
function getDistributedSsrFragmentContext(response) {
|
|
10
|
+
const locals = response?.locals;
|
|
11
|
+
if (!locals || 'object' != typeof locals) return;
|
|
12
|
+
const context = locals[DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY];
|
|
13
|
+
if (!context || 'object' != typeof context) return;
|
|
14
|
+
return context;
|
|
15
|
+
}
|
|
16
|
+
function useDistributedSsrFragmentProps({ boundaryId, expose }) {
|
|
17
|
+
const runtimeContext = useRuntimeContext();
|
|
18
|
+
const locals = runtimeContext.requestContext?.response?.locals;
|
|
19
|
+
const request = locals && 'object' == typeof locals ? locals[DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY] : void 0;
|
|
20
|
+
if (!request || 'object' != typeof request || request.boundaryId !== boundaryId || request.expose !== expose) throw new Error(`Distributed SSR fragment request contract mismatch for ${boundaryId} ${expose}.`);
|
|
21
|
+
const props = request.props;
|
|
22
|
+
if (!props || 'object' != typeof props || Array.isArray(props)) throw new Error(`Distributed SSR fragment request props must be an object for ${boundaryId} ${expose}.`);
|
|
23
|
+
return props;
|
|
24
|
+
}
|
|
25
|
+
function isThenable(value) {
|
|
26
|
+
return 'function' == typeof value.then;
|
|
27
|
+
}
|
|
28
|
+
function DistributedSsrBoundary({ children, expose, fallback, fragmentProps = {}, remote }) {
|
|
29
|
+
const runtimeContext = useRuntimeContext();
|
|
30
|
+
const key = distributedSsrFragmentKey(remote, expose);
|
|
31
|
+
const attributes = {
|
|
32
|
+
'data-modern-distributed-ssr-boundary': key
|
|
33
|
+
};
|
|
34
|
+
if (runtimeContext.isBrowser) return /*#__PURE__*/ jsx("div", {
|
|
35
|
+
...attributes,
|
|
36
|
+
children: children
|
|
37
|
+
});
|
|
38
|
+
const fragmentContext = getDistributedSsrFragmentContext(runtimeContext.requestContext?.response);
|
|
39
|
+
if (!fragmentContext) return /*#__PURE__*/ jsx("div", {
|
|
40
|
+
...attributes,
|
|
41
|
+
children: children
|
|
42
|
+
});
|
|
43
|
+
const fragmentOrPromise = fragmentContext.resolve?.(remote, expose, fragmentProps) ?? fragmentContext.fragments?.[key];
|
|
44
|
+
if (fragmentOrPromise && isThenable(fragmentOrPromise)) throw fragmentOrPromise;
|
|
45
|
+
const fragment = fragmentOrPromise;
|
|
46
|
+
if (fragment?.status === 'ready') return /*#__PURE__*/ jsx("div", {
|
|
47
|
+
...attributes,
|
|
48
|
+
"data-modern-distributed-ssr-build": fragment.buildMarker,
|
|
49
|
+
"data-modern-distributed-ssr-digest": fragment.digest,
|
|
50
|
+
"data-modern-distributed-ssr-status": "ready",
|
|
51
|
+
dangerouslySetInnerHTML: {
|
|
52
|
+
__html: fragment.html
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return /*#__PURE__*/ jsx("div", {
|
|
56
|
+
...attributes,
|
|
57
|
+
"data-modern-distributed-ssr-reason": fragment?.reason ?? 'missing',
|
|
58
|
+
"data-modern-distributed-ssr-status": "degraded",
|
|
59
|
+
children: fallback
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function createDistributedSsrComponent({ createComponent, expose, fallback, remote }) {
|
|
63
|
+
let RemoteComponent;
|
|
64
|
+
function DeferredRemoteComponent(props) {
|
|
65
|
+
RemoteComponent ??= createComponent();
|
|
66
|
+
return /*#__PURE__*/ jsx(RemoteComponent, {
|
|
67
|
+
...props
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return function(props) {
|
|
71
|
+
return /*#__PURE__*/ jsx(DistributedSsrBoundary, {
|
|
72
|
+
expose: expose,
|
|
73
|
+
fallback: fallback,
|
|
74
|
+
fragmentProps: props,
|
|
75
|
+
remote: remote,
|
|
76
|
+
children: /*#__PURE__*/ jsx(DeferredRemoteComponent, {
|
|
77
|
+
...props
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export { DISTRIBUTED_SSR_FRAGMENTS_LOCALS_KEY, DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY, DistributedSsrBoundary, createDistributedSsrComponent, distributedSsrFragmentKey, useDistributedSsrFragmentProps };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
+
export * from "./consume-surface.mjs";
|
|
3
|
+
export * from "./distributed-ssr.mjs";
|
|
4
|
+
export * from "./last-known-good.mjs";
|
|
5
|
+
export * from "./manifest-recovery-runtime-plugin.mjs";
|
|
6
|
+
export * from "./surface-resolution-types.mjs";
|
|
2
7
|
const MODULE_FEDERATION_FALLBACK_SIGNAL_EVENT = 'modernjs:mf-runtime-fallback';
|
|
3
8
|
const MODULE_FEDERATION_RECOVERY_SIGNAL_EVENT = 'modernjs:mf-runtime-recovery';
|
|
4
9
|
const DEFAULT_RUNTIME_FALLBACK_SIGNAL_ENDPOINT = '/_modern/contract-gates/runtime-fallback';
|
|
@@ -107,4 +112,5 @@ async function emitModuleFederationFallbackTelemetry(input, options = {}) {
|
|
|
107
112
|
postStatus: response.status
|
|
108
113
|
};
|
|
109
114
|
}
|
|
115
|
+
export { DISTRIBUTED_SSR_FRAGMENT_REQUEST_LOCALS_KEY, useDistributedSsrFragmentProps } from "./distributed-ssr.mjs";
|
|
110
116
|
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 };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { createDiscoveryError, deliveryUnitResolutionKey } from "./surface-resolution-types.mjs";
|
|
3
|
+
const LAST_KNOWN_GOOD_PROVIDER_NAME = 'last-known-good';
|
|
4
|
+
function createInMemoryLkgStorage() {
|
|
5
|
+
const map = new Map();
|
|
6
|
+
return {
|
|
7
|
+
read (key) {
|
|
8
|
+
return map.get(key);
|
|
9
|
+
},
|
|
10
|
+
write (key, record) {
|
|
11
|
+
map.set(key, record);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function markDegraded(resolved, reason) {
|
|
16
|
+
return {
|
|
17
|
+
...resolved,
|
|
18
|
+
compatibility: {
|
|
19
|
+
...resolved.compatibility,
|
|
20
|
+
status: 'degraded',
|
|
21
|
+
reason
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function staleRecordResult(ref, env, ageMs, maxStaleMs) {
|
|
26
|
+
return {
|
|
27
|
+
ok: false,
|
|
28
|
+
error: createDiscoveryError('stale-record', ref, `Last-known-good record for surface is stale: age ${ageMs}ms exceeds maxStaleMs ${maxStaleMs}ms`, {
|
|
29
|
+
env,
|
|
30
|
+
ageMs,
|
|
31
|
+
maxStaleMs
|
|
32
|
+
})
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createLastKnownGoodProvider(options) {
|
|
36
|
+
const storage = options.storage ?? createInMemoryLkgStorage();
|
|
37
|
+
const now = options.now ?? (()=>Date.now());
|
|
38
|
+
const maxStaleMs = options.freshness?.maxStaleMs;
|
|
39
|
+
async function serveFromCache(ref, env, fallback) {
|
|
40
|
+
const key = deliveryUnitResolutionKey(ref.unitId, env);
|
|
41
|
+
const cached = await storage.read(key);
|
|
42
|
+
if (!cached) return fallback();
|
|
43
|
+
if (cached.major !== ref.major) return fallback();
|
|
44
|
+
if ('incompatible' === cached.resolved.compatibility.status) return fallback();
|
|
45
|
+
const ageMs = now() - cached.storedAt;
|
|
46
|
+
if (void 0 !== maxStaleMs && ageMs > maxStaleMs) return staleRecordResult(ref, env, ageMs, maxStaleMs);
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
unit: markDegraded(cached.resolved, `served last-known-good record (age ${ageMs}ms) after provider failure`)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
name: LAST_KNOWN_GOOD_PROVIDER_NAME,
|
|
54
|
+
async resolve (ref, env) {
|
|
55
|
+
const key = deliveryUnitResolutionKey(ref.unitId, env);
|
|
56
|
+
let resolution;
|
|
57
|
+
try {
|
|
58
|
+
resolution = await options.provider.resolve(ref, env);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
return serveFromCache(ref, env, ()=>({
|
|
61
|
+
ok: false,
|
|
62
|
+
error: createDiscoveryError('provider-unavailable', ref, error instanceof Error ? error.message : 'provider threw a non-error value', {
|
|
63
|
+
env,
|
|
64
|
+
provider: options.provider.name
|
|
65
|
+
})
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
if (!resolution.ok) {
|
|
69
|
+
const failure = resolution;
|
|
70
|
+
return serveFromCache(ref, env, ()=>failure);
|
|
71
|
+
}
|
|
72
|
+
if ('incompatible' !== resolution.unit.compatibility.status) await storage.write(key, {
|
|
73
|
+
resolved: resolution.unit,
|
|
74
|
+
storedAt: now(),
|
|
75
|
+
major: ref.major
|
|
76
|
+
});
|
|
77
|
+
return resolution;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export { LAST_KNOWN_GOOD_PROVIDER_NAME, createInMemoryLkgStorage, createLastKnownGoodProvider };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
const DEFAULT_ATTEMPTS = 3;
|
|
3
|
+
const DEFAULT_RETRY_DELAY_MS = 100;
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 1000;
|
|
5
|
+
const MAX_ATTEMPTS = 5;
|
|
6
|
+
const MAX_RETRY_DELAY_MS = 1000;
|
|
7
|
+
const MAX_TIMEOUT_MS = 5000;
|
|
8
|
+
const RETRYABLE_HTTP_STATUSES = new Set([
|
|
9
|
+
408,
|
|
10
|
+
425,
|
|
11
|
+
429,
|
|
12
|
+
500,
|
|
13
|
+
502,
|
|
14
|
+
503,
|
|
15
|
+
504
|
|
16
|
+
]);
|
|
17
|
+
const NON_RETRYABLE_ERROR_PATTERNS = [
|
|
18
|
+
/RUNTIME-013/i,
|
|
19
|
+
/invalid manifest/i,
|
|
20
|
+
/manifest (?:schema|contract|version|identity)/i,
|
|
21
|
+
/(?:incompatible|mismatch).*(?:manifest|remote)/i
|
|
22
|
+
];
|
|
23
|
+
const clampInteger = (value, fallback, minimum, maximum)=>{
|
|
24
|
+
if (void 0 === value || !Number.isFinite(value)) return fallback;
|
|
25
|
+
return Math.min(maximum, Math.max(minimum, Math.floor(value)));
|
|
26
|
+
};
|
|
27
|
+
const getErrorMessage = (error)=>{
|
|
28
|
+
if (error instanceof Error) return error.message;
|
|
29
|
+
return 'string' == typeof error ? error : '';
|
|
30
|
+
};
|
|
31
|
+
const getErrorStatus = (error)=>{
|
|
32
|
+
if ('object' == typeof error && null !== error && 'status' in error && 'number' == typeof error.status) return error.status;
|
|
33
|
+
};
|
|
34
|
+
const isRetryableError = (error)=>{
|
|
35
|
+
if (error instanceof SyntaxError) return false;
|
|
36
|
+
const message = getErrorMessage(error);
|
|
37
|
+
if (NON_RETRYABLE_ERROR_PATTERNS.some((pattern)=>pattern.test(message))) return false;
|
|
38
|
+
const status = getErrorStatus(error);
|
|
39
|
+
if (void 0 !== status) return RETRYABLE_HTTP_STATUSES.has(status);
|
|
40
|
+
if (error instanceof Error && [
|
|
41
|
+
'AbortError',
|
|
42
|
+
'TimeoutError'
|
|
43
|
+
].includes(error.name)) return true;
|
|
44
|
+
return error instanceof TypeError || /(?:fetch failed|network|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN)/i.test(message);
|
|
45
|
+
};
|
|
46
|
+
const isHttpManifestUrl = (id)=>{
|
|
47
|
+
if (!id) return false;
|
|
48
|
+
try {
|
|
49
|
+
const url = new URL(id);
|
|
50
|
+
return ('http:' === url.protocol || 'https:' === url.protocol) && url.pathname.endsWith('.json');
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const defaultWait = (milliseconds)=>new Promise((resolve)=>{
|
|
56
|
+
setTimeout(resolve, milliseconds);
|
|
57
|
+
});
|
|
58
|
+
const fetchWithTimeout = async (fetchImpl, url, timeoutMs)=>{
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
const timeout = setTimeout(()=>controller.abort(), timeoutMs);
|
|
61
|
+
try {
|
|
62
|
+
return await fetchImpl(url, {
|
|
63
|
+
signal: controller.signal
|
|
64
|
+
});
|
|
65
|
+
} finally{
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const createModuleFederationManifestRecoveryPlugin = (options = {})=>{
|
|
70
|
+
const attempts = clampInteger(options.attempts, DEFAULT_ATTEMPTS, 1, MAX_ATTEMPTS);
|
|
71
|
+
const retryDelayMs = clampInteger(options.retryDelayMs, DEFAULT_RETRY_DELAY_MS, 0, MAX_RETRY_DELAY_MS);
|
|
72
|
+
const timeoutMs = clampInteger(options.timeoutMs, DEFAULT_TIMEOUT_MS, 1, MAX_TIMEOUT_MS);
|
|
73
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
74
|
+
const waitImpl = options.waitImpl ?? defaultWait;
|
|
75
|
+
return {
|
|
76
|
+
name: 'modern-js-manifest-recovery-plugin',
|
|
77
|
+
async errorLoadRemote (args) {
|
|
78
|
+
if ('afterResolve' !== args.lifecycle || !isHttpManifestUrl(args.id) || !isRetryableError(args.error) || 'function' != typeof fetchImpl) return;
|
|
79
|
+
for(let attempt = 0; attempt < attempts; attempt++){
|
|
80
|
+
if (attempt > 0 && retryDelayMs > 0) await waitImpl(retryDelayMs);
|
|
81
|
+
try {
|
|
82
|
+
const response = await fetchWithTimeout(fetchImpl, args.id, timeoutMs);
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
if (!RETRYABLE_HTTP_STATUSES.has(response.status) || attempt === attempts - 1) return;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
return await response.json();
|
|
89
|
+
} catch {
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (!isRetryableError(error) || attempt === attempts - 1) break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
const manifest_recovery_runtime_plugin = createModuleFederationManifestRecoveryPlugin;
|
|
100
|
+
export default manifest_recovery_runtime_plugin;
|
|
101
|
+
export { createModuleFederationManifestRecoveryPlugin };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "node:module";
|
|
2
|
+
import { createDiscoveryError, formatSurfaceRef, parseSurfaceRef, validateSurfaceRef } from "@modern-js/utils/universal";
|
|
3
|
+
function surfaceResolutionKey(ref, env) {
|
|
4
|
+
return `${env}::${formatSurfaceRef(ref)}`;
|
|
5
|
+
}
|
|
6
|
+
function deliveryUnitResolutionKey(unitId, env) {
|
|
7
|
+
return `${env}::${unitId}`;
|
|
8
|
+
}
|
|
9
|
+
export { createDiscoveryError, deliveryUnitResolutionKey, formatSurfaceRef, parseSurfaceRef, surfaceResolutionKey, validateSurfaceRef };
|
|
@@ -7,7 +7,7 @@ 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
9
|
import { getServerCombinedModuleFile, getServerLoadersFile } from "./utils.mjs";
|
|
10
|
-
import * as
|
|
10
|
+
import * as __rspack_external__templates_mjs_ab577925 from "./templates.mjs";
|
|
11
11
|
async function generateRoutesForEntry(entrypoint, appContext) {
|
|
12
12
|
const routes = [];
|
|
13
13
|
if (entrypoint.nestedRoutesEntry) {
|
|
@@ -90,7 +90,7 @@ const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
|
90
90
|
}
|
|
91
91
|
const { code } = await hooks.onBeforeGenerateRoutes.call({
|
|
92
92
|
entrypoint,
|
|
93
|
-
code: await
|
|
93
|
+
code: await __rspack_external__templates_mjs_ab577925.fileSystemRoutes({
|
|
94
94
|
metaName,
|
|
95
95
|
routes: routes,
|
|
96
96
|
ssrMode: isUseRsc(config) ? 'stream' : ssrMode,
|
|
@@ -107,12 +107,12 @@ const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
|
107
107
|
const routesServerFile = getServerLoadersFile(internalDirectory, entryName);
|
|
108
108
|
const filtedRoutesForServer = filterRoutesForServer(routes);
|
|
109
109
|
const routesForServerLoaderMatches = filterRoutesLoader(routes);
|
|
110
|
-
const code =
|
|
110
|
+
const code = __rspack_external__templates_mjs_ab577925.routesForServer({
|
|
111
111
|
routesForServerLoaderMatches
|
|
112
112
|
});
|
|
113
113
|
await fs.ensureFile(routesServerFile);
|
|
114
114
|
await fs.writeFile(routesServerFile, code);
|
|
115
|
-
const serverRoutesCode = await
|
|
115
|
+
const serverRoutesCode = await __rspack_external__templates_mjs_ab577925.fileSystemRoutes({
|
|
116
116
|
metaName,
|
|
117
117
|
routes: filtedRoutesForServer,
|
|
118
118
|
ssrMode,
|
|
@@ -126,7 +126,7 @@ const generateCode = async (appContext, config, entrypoints, api)=>{
|
|
|
126
126
|
});
|
|
127
127
|
await fs.outputFile(path.resolve(internalDirectory, `./${entryName}/routes.server.js`), serverRoutesCode, 'utf8');
|
|
128
128
|
}
|
|
129
|
-
const serverLoaderCombined =
|
|
129
|
+
const serverLoaderCombined = __rspack_external__templates_mjs_ab577925.ssrLoaderCombinedModule(entrypoints, entrypoint, config, appContext);
|
|
130
130
|
if (serverLoaderCombined) {
|
|
131
131
|
const serverLoaderFile = getServerCombinedModuleFile(internalDirectory, entryName);
|
|
132
132
|
await fs.outputFile(serverLoaderFile, serverLoaderCombined);
|
|
@@ -83,6 +83,7 @@ const walk = async (options)=>{
|
|
|
83
83
|
let pageLoaderFile = '';
|
|
84
84
|
let pageRoute = null;
|
|
85
85
|
let pageConfigFile = '';
|
|
86
|
+
let pageSearchFile = '';
|
|
86
87
|
let pageClientData = '';
|
|
87
88
|
let pageData = '';
|
|
88
89
|
let pageAction = '';
|
|
@@ -129,12 +130,14 @@ const walk = async (options)=>{
|
|
|
129
130
|
if (await hasAction(itemPath)) pageAction = itemPathWithAlias;
|
|
130
131
|
}
|
|
131
132
|
if (itemWithoutExt === NESTED_ROUTE.PAGE_CONFIG_FILE) pageConfigFile = itemPathWithAlias;
|
|
133
|
+
if (itemWithoutExt === NESTED_ROUTE.PAGE_SEARCH_FILE) pageSearchFile = itemPathWithAlias;
|
|
132
134
|
if (itemWithoutExt === NESTED_ROUTE.PAGE_FILE) {
|
|
133
135
|
pageRoute = createIndexRoute({
|
|
134
136
|
_component: itemPathWithAlias
|
|
135
137
|
}, rootDir, itemPath, entryName, isMainEntry);
|
|
136
138
|
if (pageLoaderFile) pageRoute.loader = pageLoaderFile;
|
|
137
139
|
if (pageConfigFile) pageRoute.config = pageConfigFile;
|
|
140
|
+
if (pageSearchFile) pageRoute.validateSearch = pageSearchFile;
|
|
138
141
|
if (pageData) pageRoute.data = pageData;
|
|
139
142
|
if (pageClientData) pageRoute.clientData = pageClientData;
|
|
140
143
|
if (pageAction) pageRoute.action = pageAction;
|
|
@@ -184,7 +184,8 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
184
184
|
component = `component_${components.length - 1}`;
|
|
185
185
|
}
|
|
186
186
|
const isClientComponent = 'nested' === route.type && Boolean(route._component) && Boolean(srcDirectory) && Boolean(internalSrcAlias) && await hasUseClientDirective(route._component, srcDirectory, internalSrcAlias);
|
|
187
|
-
const
|
|
187
|
+
const shouldHydrateRscRoute = isRscClientBundle && !isClientComponent && !route.loader && !route.data;
|
|
188
|
+
const shouldIncludeClientBundle = !isRscClientBundle || isClientComponent || shouldHydrateRscRoute;
|
|
188
189
|
const finalRoute = {
|
|
189
190
|
...route,
|
|
190
191
|
loading,
|
|
@@ -287,7 +288,7 @@ const fileSystemRoutes = async ({ metaName, routes, ssrMode, nestedRoutesEntry,
|
|
|
287
288
|
${importLazyCode}
|
|
288
289
|
${!isRscClientBundle ? importComponentsCode : ''}
|
|
289
290
|
${importRuntimeRouterCode}
|
|
290
|
-
${
|
|
291
|
+
${rootLayoutCode}
|
|
291
292
|
${importLoadingCode}
|
|
292
293
|
${importErrorComponentsCode}
|
|
293
294
|
${importLoadersCode}
|
|
@@ -4,7 +4,7 @@ import { cloneDeep } from "@modern-js/utils/lodash";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { isPageComponentFile } from "./code/utils.mjs";
|
|
6
6
|
import { modifyEntrypoints } from "./entry.mjs";
|
|
7
|
-
import * as
|
|
7
|
+
import * as __rspack_external__code_templates_mjs_f6c22489 from "./code/templates.mjs";
|
|
8
8
|
const DEFAULT_ENTRYPOINTS_KEY = '__default_router_entries__';
|
|
9
9
|
const originEntrypointsByKey = new Map();
|
|
10
10
|
async function handleModifyEntrypoints(entrypoints, routesDir, options = {}) {
|
|
@@ -26,7 +26,7 @@ async function handleGeneratorEntryCode(api, entrypoints, options = {}) {
|
|
|
26
26
|
if (entrypoint.nestedRoutesEntry || entrypoint.pageRoutesEntry) {
|
|
27
27
|
const route = appContext.serverRoutes.find((r)=>r.entryName === entrypoint.entryName);
|
|
28
28
|
const basename = route?.urlPath || '/';
|
|
29
|
-
generatorRegisterCode(internalDirectory, entrypoint.entryName, await
|
|
29
|
+
generatorRegisterCode(internalDirectory, entrypoint.entryName, await __rspack_external__code_templates_mjs_f6c22489.runtimeGlobalContext({
|
|
30
30
|
entryName: entrypoint.entryName,
|
|
31
31
|
metaName: appContext.metaName,
|
|
32
32
|
srcDirectory: appContext.srcDirectory,
|
|
@@ -36,7 +36,7 @@ async function handleGeneratorEntryCode(api, entrypoints, options = {}) {
|
|
|
36
36
|
rscType: enableRsc ? 'client' : void 0,
|
|
37
37
|
basename
|
|
38
38
|
}));
|
|
39
|
-
if (enableRsc) generatorServerRegisterCode(internalDirectory, entrypoint.entryName, await
|
|
39
|
+
if (enableRsc) generatorServerRegisterCode(internalDirectory, entrypoint.entryName, await __rspack_external__code_templates_mjs_f6c22489.runtimeGlobalContext({
|
|
40
40
|
entryName: entrypoint.entryName,
|
|
41
41
|
metaName: appContext.metaName,
|
|
42
42
|
srcDirectory: appContext.srcDirectory,
|
|
@@ -2,6 +2,7 @@ import "node:module";
|
|
|
2
2
|
import node_path from "node:path";
|
|
3
3
|
import { setTimeout as promises_setTimeout } from "node:timers/promises";
|
|
4
4
|
import { fs } from "@modern-js/utils";
|
|
5
|
+
import { cloneDeep } from "@modern-js/utils/lodash";
|
|
5
6
|
const lockPollIntervalMs = 25;
|
|
6
7
|
const staleLockAgeMs = 120000;
|
|
7
8
|
const pendingUpdates = new Map();
|
|
@@ -44,6 +45,7 @@ async function writeJSONAtomically(filePath, value) {
|
|
|
44
45
|
}
|
|
45
46
|
async function updateNestedRoutesSpec(specPath, nextRoutes) {
|
|
46
47
|
const resolvedSpecPath = node_path.resolve(specPath);
|
|
48
|
+
const nextRoutesSnapshot = cloneDeep(nextRoutes);
|
|
47
49
|
const previousUpdate = pendingUpdates.get(resolvedSpecPath) ?? Promise.resolve();
|
|
48
50
|
const currentUpdate = previousUpdate.catch(()=>void 0).then(async ()=>{
|
|
49
51
|
const releaseLock = await acquireSpecLock(resolvedSpecPath);
|
|
@@ -51,7 +53,7 @@ async function updateNestedRoutesSpec(specPath, nextRoutes) {
|
|
|
51
53
|
const existingRoutes = await fs.pathExists(resolvedSpecPath) ? await fs.readJSON(resolvedSpecPath) : {};
|
|
52
54
|
await writeJSONAtomically(resolvedSpecPath, {
|
|
53
55
|
...existingRoutes,
|
|
54
|
-
...
|
|
56
|
+
...nextRoutesSnapshot
|
|
55
57
|
});
|
|
56
58
|
} finally{
|
|
57
59
|
await releaseLock();
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { createSyncHook } from "@modern-js/plugin";
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
3
|
+
const createRouterSyncHook = ()=>createSyncHook();
|
|
4
|
+
const modifyRoutes = createRouterSyncHook();
|
|
5
|
+
const onBeforeCreateRoutes = createRouterSyncHook();
|
|
6
|
+
const onBeforeCreateRouter = createRouterSyncHook();
|
|
7
|
+
const onAfterCreateRouter = createRouterSyncHook();
|
|
8
|
+
const onBeforeHydrateRouter = createRouterSyncHook();
|
|
9
|
+
const onAfterHydrateRouter = createRouterSyncHook();
|
|
9
10
|
export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter };
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { merge } from "@modern-js/runtime-utils/merge";
|
|
3
3
|
import { modifyRoutes, routerPlugin } from "./plugin.mjs";
|
|
4
|
-
import { registerRouterProvider, reportUnsupportedProviderRegistryHooks, resolveRouterProvider, routerProviderRegistryHooks } from "./provider.mjs";
|
|
4
|
+
import { createRouterProviderRealm, registerRouterProvider, reportUnsupportedProviderRegistryHooks, resolveRouterProvider, routerProviderRegistryHooks } from "./provider.mjs";
|
|
5
5
|
registerRouterProvider('react-router', routerPlugin, {
|
|
6
6
|
isDefault: true
|
|
7
7
|
});
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
8
|
+
const createRouterPlugin = (localProviders = [])=>{
|
|
9
|
+
const providerRealm = createRouterProviderRealm([
|
|
10
|
+
{
|
|
11
|
+
name: 'react-router',
|
|
12
|
+
factory: routerPlugin,
|
|
13
|
+
isDefault: true
|
|
14
|
+
},
|
|
15
|
+
...localProviders
|
|
16
|
+
]);
|
|
17
|
+
return (userConfig = {})=>({
|
|
18
|
+
name: '@modern-js/plugin-router',
|
|
19
|
+
registryHooks: routerProviderRegistryHooks,
|
|
20
|
+
setup: (api)=>{
|
|
21
|
+
const mergedConfig = merge(api.getRuntimeConfig().router || {}, userConfig);
|
|
22
|
+
const pluginFactory = resolveRouterProvider(mergedConfig.framework, {
|
|
23
|
+
realm: providerRealm
|
|
24
|
+
});
|
|
25
|
+
const providerPlugin = pluginFactory(userConfig);
|
|
26
|
+
reportUnsupportedProviderRegistryHooks(providerPlugin);
|
|
27
|
+
providerPlugin.setup?.(api);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
const internal_routerPlugin = createRouterPlugin();
|
|
24
32
|
const internal = internal_routerPlugin;
|
|
25
33
|
export { renderRoutes } from "./utils.mjs";
|
|
26
34
|
export default internal;
|
|
27
|
-
export { internal_routerPlugin as routerPlugin, modifyRoutes, registerRouterProvider, resolveRouterProvider };
|
|
35
|
+
export { createRouterPlugin, createRouterProviderRealm, internal_routerPlugin as routerPlugin, modifyRoutes, registerRouterProvider, resolveRouterProvider };
|
|
@@ -65,10 +65,10 @@ const routerPlugin = (userConfig = {})=>({
|
|
|
65
65
|
};
|
|
66
66
|
let cachedRouter = null;
|
|
67
67
|
const RouterWrapper = (props)=>{
|
|
68
|
-
const routerResult = useRouterCreation({
|
|
68
|
+
const routerResult = useRouterCreation(process.env.MODERN_ENABLE_RSC ? {
|
|
69
69
|
...props,
|
|
70
70
|
rscPayload: props?.rscPayload
|
|
71
|
-
}, {
|
|
71
|
+
} : props, {
|
|
72
72
|
api: api,
|
|
73
73
|
createRoutes,
|
|
74
74
|
supportHtml5History,
|
|
@@ -122,16 +122,15 @@ function useRouterCreation(props, options) {
|
|
|
122
122
|
const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
|
|
123
123
|
const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
|
|
124
124
|
const { unstable_getBlockNavState: getBlockNavState } = runtimeContext;
|
|
125
|
-
const rscPayload = props?.rscPayload ? safeUse(props.rscPayload) : null;
|
|
126
|
-
let hydrationData = window._ROUTER_DATA || rscPayload;
|
|
125
|
+
const rscPayload = process.env.MODERN_ENABLE_RSC && props?.rscPayload ? safeUse(props.rscPayload) : null;
|
|
126
|
+
let hydrationData = process.env.MODERN_ENABLE_RSC ? window._ROUTER_DATA || rscPayload : window._ROUTER_DATA;
|
|
127
127
|
return (0, __rspack_external_react.useMemo)(()=>{
|
|
128
128
|
if (hydrationData?.errors) hydrationData = {
|
|
129
129
|
...hydrationData,
|
|
130
130
|
errors: deserializeErrors(hydrationData.errors)
|
|
131
131
|
};
|
|
132
|
-
const isRscClient = getGlobalIsRscClient();
|
|
133
132
|
let routes = null;
|
|
134
|
-
routes =
|
|
133
|
+
routes = process.env.MODERN_ENABLE_RSC && getGlobalIsRscClient() ? createRoutes ? createRoutes() : createRouteObjectsFromConfig({
|
|
135
134
|
routesConfig: finalRouteConfig
|
|
136
135
|
}) : createRoutes ? createRoutes() : createRoutesFromElements(renderRoutes({
|
|
137
136
|
routesConfig: finalRouteConfig,
|
|
@@ -139,7 +138,7 @@ function useRouterCreation(props, options) {
|
|
|
139
138
|
}));
|
|
140
139
|
if (!routes) routes = [];
|
|
141
140
|
const hooks = api.getHooks();
|
|
142
|
-
if (rscPayload) try {
|
|
141
|
+
if (process.env.MODERN_ENABLE_RSC && rscPayload) try {
|
|
143
142
|
const router = createClientRouterFromPayload(rscPayload, routes, _basename);
|
|
144
143
|
return {
|
|
145
144
|
router,
|