@bleedingdev/modern-js-runtime-extensions 3.9.0-ultramodern.9 → 3.9.3-ultramodern.2
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/{reactContext.js → localisedUrls/config.js} +14 -10
- package/dist/cjs/localisedUrls/index.js +95 -0
- package/dist/cjs/localisedUrls/normalise.js +87 -0
- package/dist/cjs/localisedUrls/pathname.js +68 -0
- package/dist/cjs/localisedUrls/patterns.js +214 -0
- package/dist/cjs/localisedUrls/redirect.js +104 -0
- package/dist/cjs/localisedUrls/resolve.js +78 -0
- package/dist/cjs/localisedUrls/routeIdentity.js +92 -0
- package/dist/cjs/localisedUrls/routes.js +217 -0
- package/dist/cjs/localisedUrls/types.js +18 -0
- package/dist/cjs/rendererHead.js +18 -5
- package/dist/cjs/request-policy/policyCore.js +1 -1
- package/dist/cjs/request-policy/transport.js +2 -2
- package/dist/cjs/routerState.js +85 -77
- package/dist/cjs/routerStatePlugin.js +63 -9
- package/dist/cjs/server-config/serverSource.js +18 -0
- package/dist/esm/localisedUrls/config.mjs +11 -0
- package/dist/esm/localisedUrls/index.mjs +8 -0
- package/dist/esm/localisedUrls/normalise.mjs +37 -0
- package/dist/esm/localisedUrls/pathname.mjs +24 -0
- package/dist/esm/localisedUrls/patterns.mjs +152 -0
- package/dist/esm/localisedUrls/redirect.mjs +57 -0
- package/dist/esm/localisedUrls/resolve.mjs +37 -0
- package/dist/esm/localisedUrls/routeIdentity.mjs +54 -0
- package/dist/esm/localisedUrls/routes.mjs +176 -0
- package/dist/esm/localisedUrls/types.mjs +0 -0
- package/dist/esm/rendererHead.mjs +14 -5
- package/dist/esm/request-policy/policyCore.mjs +1 -1
- package/dist/esm/request-policy/transport.mjs +2 -2
- package/dist/esm/routerState.mjs +81 -73
- package/dist/esm/routerStatePlugin.mjs +62 -11
- package/dist/esm/server-config/serverSource.mjs +0 -0
- package/dist/esm-node/localisedUrls/config.mjs +12 -0
- package/dist/esm-node/localisedUrls/index.mjs +9 -0
- package/dist/esm-node/localisedUrls/normalise.mjs +38 -0
- package/dist/esm-node/localisedUrls/pathname.mjs +25 -0
- package/dist/esm-node/localisedUrls/patterns.mjs +153 -0
- package/dist/esm-node/localisedUrls/redirect.mjs +58 -0
- package/dist/esm-node/localisedUrls/resolve.mjs +38 -0
- package/dist/esm-node/localisedUrls/routeIdentity.mjs +55 -0
- package/dist/esm-node/localisedUrls/routes.mjs +177 -0
- package/dist/esm-node/localisedUrls/types.mjs +1 -0
- package/dist/esm-node/rendererHead.mjs +14 -5
- package/dist/esm-node/request-policy/policyCore.mjs +1 -1
- package/dist/esm-node/request-policy/transport.mjs +2 -2
- package/dist/esm-node/routerState.mjs +81 -73
- package/dist/esm-node/routerStatePlugin.mjs +62 -11
- package/dist/esm-node/server-config/serverSource.mjs +1 -0
- package/dist/types/helmetCompat.d.ts +1 -1
- package/dist/types/localisedUrls/config.d.ts +9 -0
- package/dist/types/localisedUrls/index.d.ts +10 -0
- package/dist/types/localisedUrls/normalise.d.ts +10 -0
- package/dist/types/localisedUrls/pathname.d.ts +4 -0
- package/dist/types/localisedUrls/patterns.d.ts +11 -0
- package/dist/types/localisedUrls/redirect.d.ts +19 -0
- package/dist/types/localisedUrls/resolve.d.ts +7 -0
- package/dist/types/localisedUrls/routeIdentity.d.ts +22 -0
- package/dist/types/localisedUrls/routes.d.ts +3 -0
- package/dist/types/localisedUrls/types.d.ts +14 -0
- package/dist/types/rendererHead.d.ts +5 -3
- package/dist/types/request-policy/types.d.ts +1 -1
- package/dist/types/routeHydration.d.ts +2 -2
- package/dist/types/routerProvider.d.ts +1 -3
- package/dist/types/routerState.d.ts +11 -6
- package/dist/types/routerStatePlugin.d.ts +12 -0
- package/dist/types/routerStateTypes.d.ts +47 -17
- package/dist/types/server-config/index.d.ts +1 -0
- package/dist/types/server-config/serverSource.d.ts +16 -0
- package/package.json +42 -44
- package/src/helmetCompat.ts +1 -1
- package/src/localisedUrls/config.ts +18 -0
- package/src/localisedUrls/index.ts +25 -0
- package/src/localisedUrls/normalise.ts +62 -0
- package/src/localisedUrls/pathname.ts +60 -0
- package/src/localisedUrls/patterns.ts +283 -0
- package/src/localisedUrls/redirect.ts +110 -0
- package/src/localisedUrls/resolve.ts +106 -0
- package/src/localisedUrls/routeIdentity.ts +83 -0
- package/src/localisedUrls/routes.ts +451 -0
- package/src/localisedUrls/types.ts +18 -0
- package/src/rendererHead.ts +25 -8
- package/src/request-policy/policyCore.ts +1 -1
- package/src/request-policy/transport.ts +2 -2
- package/src/request-policy/types.ts +1 -1
- package/src/routeHydration.ts +2 -2
- package/src/routerProvider.ts +1 -1
- package/src/routerState.ts +127 -115
- package/src/routerStatePlugin.ts +106 -10
- package/src/routerStateTypes.ts +47 -17
- package/src/server-config/index.ts +1 -0
- package/src/server-config/serverSource.ts +23 -0
- package/dist/cjs/buildIdentity.js +0 -73
- package/dist/esm/buildIdentity.mjs +0 -35
- package/dist/esm/reactContext.mjs +0 -7
- package/dist/esm-node/buildIdentity.mjs +0 -36
- package/dist/esm-node/reactContext.mjs +0 -8
- package/dist/types/buildIdentity.d.ts +0 -37
- package/dist/types/reactContext.d.ts +0 -6
- package/rslib.config.mts +0 -19
- package/rstest.config.mts +0 -38
- package/src/buildIdentity.ts +0 -61
- package/src/reactContext.ts +0 -16
- package/tests/buildIdentity.test.ts +0 -51
- package/tests/contextExtensions.test.ts +0 -27
- package/tests/headRuntime.test.tsx +0 -229
- package/tests/rendererHead.test.ts +0 -187
- package/tests/request-policy/browser-policy.test.ts +0 -108
- package/tests/request-policy/client-isolation.test.ts +0 -109
- package/tests/request-policy/node-policy.test.ts +0 -447
- package/tests/request-policy/policyCore.test.ts +0 -129
- package/tests/request-policy/requestContext.test.ts +0 -66
- package/tests/request-policy/requestFactory.outbound-contract.test.ts +0 -290
- package/tests/request-policy/traceparent.test.ts +0 -52
- package/tests/request-policy/transport-retry.test.ts +0 -367
- package/tests/routeHydration.test.ts +0 -180
- package/tests/routerPrefetchPolicy.test.ts +0 -102
- package/tests/routerProvider.test.ts +0 -29
- package/tests/routerState.test.ts +0 -78
- package/tests/routerStatePlugin.test.ts +0 -63
- package/tests/runtimeContextProjection.test.ts +0 -83
- package/tests/safeFailure.test.ts +0 -136
- package/tests/shellStream.test.ts +0 -122
- package/tests/workspaceEvents.test.ts +0 -221
- package/tsconfig.json +0 -10
|
@@ -8,99 +8,107 @@ function getRouterRuntimeState(runtimeContext) {
|
|
|
8
8
|
function getRouterServerSnapshot(runtimeContext) {
|
|
9
9
|
return routerServerSnapshotExtension.get(runtimeContext);
|
|
10
10
|
}
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
hydrationScript: state.hydrationScript ?? hydrationScripts[0],
|
|
28
|
-
hydrationScripts
|
|
11
|
+
function createRouterServerSnapshot(snapshot) {
|
|
12
|
+
const matches = snapshot.matches?.map((match)=>Object.freeze({
|
|
13
|
+
...match,
|
|
14
|
+
...match.params ? {
|
|
15
|
+
params: Object.freeze({
|
|
16
|
+
...match.params
|
|
17
|
+
})
|
|
18
|
+
} : {}
|
|
19
|
+
}));
|
|
20
|
+
const matchedRouteIds = snapshot.matchedRouteIds ?? matches?.map((match)=>match.assetRouteId ?? match.routeId);
|
|
21
|
+
return Object.freeze({
|
|
22
|
+
...snapshot,
|
|
23
|
+
...snapshot.hydrationScripts ? {
|
|
24
|
+
hydrationScripts: Object.freeze([
|
|
25
|
+
...snapshot.hydrationScripts
|
|
26
|
+
])
|
|
29
27
|
} : {},
|
|
30
28
|
...matchedRouteIds ? {
|
|
31
|
-
matchedRouteIds
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
function createRouterRuntimeState(state) {
|
|
36
|
-
const hasSnapshotState = Boolean(state.serverSnapshot) || Boolean(state.hydrationScript) || Boolean(state.hydrationScripts?.length) || Boolean(state.matchedRouteIds?.length) || Boolean(state.matches?.length);
|
|
37
|
-
const serverSnapshot = state.serverSnapshot ? createRouterServerSnapshot({
|
|
38
|
-
...state.serverSnapshot,
|
|
39
|
-
framework: state.serverSnapshot.framework ?? state.framework,
|
|
40
|
-
basename: state.serverSnapshot.basename ?? state.basename,
|
|
41
|
-
hydrationScript: state.serverSnapshot.hydrationScript ?? state.hydrationScript,
|
|
42
|
-
hydrationScripts: state.serverSnapshot.hydrationScripts ?? state.hydrationScripts,
|
|
43
|
-
matchedRouteIds: state.serverSnapshot.matchedRouteIds ?? state.matchedRouteIds,
|
|
44
|
-
matches: state.serverSnapshot.matches ?? state.matches
|
|
45
|
-
}) : hasSnapshotState ? createRouterServerSnapshot({
|
|
46
|
-
framework: state.framework,
|
|
47
|
-
basename: state.basename,
|
|
48
|
-
hydrationScript: state.hydrationScript,
|
|
49
|
-
hydrationScripts: state.hydrationScripts,
|
|
50
|
-
matchedRouteIds: state.matchedRouteIds,
|
|
51
|
-
matches: state.matches
|
|
52
|
-
}) : void 0;
|
|
53
|
-
const hydrationScripts = toHydrationScripts({
|
|
54
|
-
hydrationScript: state.hydrationScript ?? serverSnapshot?.hydrationScript,
|
|
55
|
-
hydrationScripts: state.hydrationScripts ?? serverSnapshot?.hydrationScripts
|
|
56
|
-
});
|
|
57
|
-
const matchedRouteIds = state.matchedRouteIds ?? serverSnapshot?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(state.matches);
|
|
58
|
-
return {
|
|
59
|
-
...state,
|
|
60
|
-
...hydrationScripts?.length ? {
|
|
61
|
-
hydrationScript: state.hydrationScript ?? hydrationScripts[0],
|
|
62
|
-
hydrationScripts
|
|
29
|
+
matchedRouteIds: Object.freeze([
|
|
30
|
+
...matchedRouteIds
|
|
31
|
+
])
|
|
63
32
|
} : {},
|
|
64
|
-
...
|
|
65
|
-
|
|
33
|
+
...matches ? {
|
|
34
|
+
matches: Object.freeze(matches)
|
|
66
35
|
} : {},
|
|
67
|
-
...
|
|
68
|
-
|
|
36
|
+
...snapshot.errors ? {
|
|
37
|
+
errors: Object.freeze({
|
|
38
|
+
...snapshot.errors
|
|
39
|
+
})
|
|
40
|
+
} : {},
|
|
41
|
+
...snapshot.routerData ? {
|
|
42
|
+
routerData: Object.freeze({
|
|
43
|
+
...snapshot.routerData,
|
|
44
|
+
...snapshot.routerData.loaderData ? {
|
|
45
|
+
loaderData: Object.freeze({
|
|
46
|
+
...snapshot.routerData.loaderData
|
|
47
|
+
})
|
|
48
|
+
} : {},
|
|
49
|
+
...snapshot.routerData.errors ? {
|
|
50
|
+
errors: Object.freeze({
|
|
51
|
+
...snapshot.routerData.errors
|
|
52
|
+
})
|
|
53
|
+
} : {}
|
|
54
|
+
})
|
|
69
55
|
} : {}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const routerRuntimeStateListeners = new WeakMap();
|
|
59
|
+
function subscribeRouterRuntimeState(runtimeContext, listener) {
|
|
60
|
+
if (!runtimeContext || 'object' != typeof runtimeContext) return ()=>void 0;
|
|
61
|
+
let listeners = routerRuntimeStateListeners.get(runtimeContext);
|
|
62
|
+
if (!listeners) {
|
|
63
|
+
listeners = new Set();
|
|
64
|
+
routerRuntimeStateListeners.set(runtimeContext, listeners);
|
|
65
|
+
}
|
|
66
|
+
listeners.add(listener);
|
|
67
|
+
return ()=>{
|
|
68
|
+
listeners?.delete(listener);
|
|
70
69
|
};
|
|
71
70
|
}
|
|
71
|
+
const pendingRouterRuntimeStateNotifications = new WeakSet();
|
|
72
|
+
function notifyRouterRuntimeState(runtimeContext) {
|
|
73
|
+
const listeners = routerRuntimeStateListeners.get(runtimeContext);
|
|
74
|
+
if (!listeners?.size) return;
|
|
75
|
+
if (pendingRouterRuntimeStateNotifications.has(runtimeContext)) return;
|
|
76
|
+
pendingRouterRuntimeStateNotifications.add(runtimeContext);
|
|
77
|
+
const deliver = ()=>{
|
|
78
|
+
pendingRouterRuntimeStateNotifications.delete(runtimeContext);
|
|
79
|
+
const current = routerRuntimeStateListeners.get(runtimeContext);
|
|
80
|
+
if (!current?.size) return;
|
|
81
|
+
for (const listener of [
|
|
82
|
+
...current
|
|
83
|
+
])try {
|
|
84
|
+
listener();
|
|
85
|
+
} catch {}
|
|
86
|
+
};
|
|
87
|
+
if ('function' == typeof queueMicrotask) queueMicrotask(deliver);
|
|
88
|
+
else setTimeout(deliver, 0);
|
|
89
|
+
}
|
|
72
90
|
function applyRouterRuntimeState(runtimeContext, state) {
|
|
73
|
-
const
|
|
74
|
-
routerRuntimeStateExtension.set(runtimeContext,
|
|
75
|
-
if (
|
|
91
|
+
const previous = routerRuntimeStateExtension.get(runtimeContext);
|
|
92
|
+
routerRuntimeStateExtension.set(runtimeContext, state);
|
|
93
|
+
if (previous?.instance !== state.instance || previous?.framework !== state.framework || previous?.navigation !== state.navigation) notifyRouterRuntimeState(runtimeContext);
|
|
76
94
|
return runtimeContext;
|
|
77
95
|
}
|
|
78
96
|
function applyRouterServerPrepareResult(runtimeContext, result) {
|
|
79
|
-
|
|
97
|
+
if (result.snapshot) routerServerSnapshotExtension.set(runtimeContext, createRouterServerSnapshot(result.snapshot));
|
|
98
|
+
return applyRouterRuntimeState(runtimeContext, {
|
|
80
99
|
...result.state,
|
|
81
|
-
cleanup: result.cleanup ?? result.state.cleanup
|
|
82
|
-
serverSnapshot: result.snapshot ?? result.state.serverSnapshot
|
|
100
|
+
cleanup: result.cleanup ?? result.state.cleanup
|
|
83
101
|
});
|
|
84
|
-
applyRouterRuntimeState(runtimeContext, state);
|
|
85
|
-
return runtimeContext;
|
|
86
102
|
}
|
|
87
103
|
function getRouterHydrationScripts(runtimeContext) {
|
|
88
|
-
|
|
89
|
-
const runtimeState = getRouterRuntimeState(runtimeContext);
|
|
90
|
-
return serverSnapshot?.hydrationScripts ?? toHydrationScripts({
|
|
91
|
-
hydrationScript: serverSnapshot?.hydrationScript
|
|
92
|
-
}) ?? runtimeState?.hydrationScripts ?? toHydrationScripts({
|
|
93
|
-
hydrationScript: runtimeState?.hydrationScript
|
|
94
|
-
}) ?? [];
|
|
104
|
+
return getRouterServerSnapshot(runtimeContext)?.hydrationScripts ?? [];
|
|
95
105
|
}
|
|
96
106
|
function getRouterMatchedRouteIds(runtimeContext) {
|
|
97
|
-
|
|
98
|
-
const runtimeState = getRouterRuntimeState(runtimeContext);
|
|
99
|
-
return serverSnapshot?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(serverSnapshot?.matches) ?? runtimeState?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(runtimeState?.matches);
|
|
107
|
+
return getRouterServerSnapshot(runtimeContext)?.matchedRouteIds;
|
|
100
108
|
}
|
|
101
109
|
async function cleanupRouterRuntimeState(runtimeContext) {
|
|
102
110
|
try {
|
|
103
111
|
await getRouterRuntimeState(runtimeContext)?.cleanup?.();
|
|
104
112
|
} catch {}
|
|
105
113
|
}
|
|
106
|
-
export { applyRouterRuntimeState, applyRouterServerPrepareResult, cleanupRouterRuntimeState,
|
|
114
|
+
export { applyRouterRuntimeState, applyRouterServerPrepareResult, cleanupRouterRuntimeState, createRouterServerSnapshot, getRouterHydrationScripts, getRouterMatchedRouteIds, getRouterRuntimeState, getRouterServerSnapshot, subscribeRouterRuntimeState };
|
|
@@ -1,21 +1,64 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
import { createRouterPrefetchPolicy } from "./routerPrefetchPolicy.mjs";
|
|
3
|
-
import { applyRouterRuntimeState,
|
|
3
|
+
import { applyRouterRuntimeState, applyRouterServerPrepareResult, getRouterRuntimeState, getRouterServerSnapshot } from "./routerState.mjs";
|
|
4
|
+
const ROUTER_CLEANUP_ERROR = 'An error occurs during router runtime cleanup';
|
|
5
|
+
const installedRouterPolicies = new WeakSet();
|
|
6
|
+
function createReactRouterNavigation(router, Link) {
|
|
7
|
+
let state;
|
|
8
|
+
let snapshot;
|
|
9
|
+
return {
|
|
10
|
+
Link,
|
|
11
|
+
getSnapshot () {
|
|
12
|
+
if (state !== router.state) {
|
|
13
|
+
state = router.state;
|
|
14
|
+
snapshot = {
|
|
15
|
+
location: state.location,
|
|
16
|
+
params: Object.assign({}, ...state.matches.map((match)=>match.params))
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return snapshot;
|
|
20
|
+
},
|
|
21
|
+
subscribe: (listener)=>router.subscribe(listener),
|
|
22
|
+
navigate: (href, options)=>router.navigate(href, options)
|
|
23
|
+
};
|
|
24
|
+
}
|
|
4
25
|
function createRouterStatePlugin({ registryHooks }) {
|
|
5
26
|
return {
|
|
6
27
|
name: '@modern-js/router-runtime-policy',
|
|
7
28
|
registryHooks,
|
|
8
29
|
setup (api) {
|
|
30
|
+
if (installedRouterPolicies.has(api)) return;
|
|
31
|
+
installedRouterPolicies.add(api);
|
|
9
32
|
api.onBeforeRender((context)=>{
|
|
10
33
|
const runtimeContext = context;
|
|
11
34
|
runtimeContext.linkPrefetchPolicy ??= createRouterPrefetchPolicy();
|
|
12
35
|
});
|
|
36
|
+
api.onRenderPrepared((info)=>{
|
|
37
|
+
const snapshot = getRouterServerSnapshot(info.runtimeContext);
|
|
38
|
+
if (!snapshot) return info;
|
|
39
|
+
return {
|
|
40
|
+
...info,
|
|
41
|
+
routerResult: {
|
|
42
|
+
statusCode: snapshot.statusCode ?? info.routerResult?.statusCode,
|
|
43
|
+
errors: snapshot.errors ?? info.routerResult?.errors
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
api.onRequestEnd(async ({ runtimeContext })=>{
|
|
48
|
+
try {
|
|
49
|
+
await getRouterRuntimeState(runtimeContext)?.cleanup?.();
|
|
50
|
+
} catch (error) {
|
|
51
|
+
const { ssrContext } = runtimeContext;
|
|
52
|
+
if (!ssrContext) throw error;
|
|
53
|
+
ssrContext.onError(error, ROUTER_CLEANUP_ERROR);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
13
56
|
api.onAfterCreateRouter((event)=>{
|
|
14
57
|
if ('react-router' !== event.framework) return;
|
|
15
58
|
if ('ssr-prepare' === event.phase) {
|
|
16
59
|
const { routerContext } = event.runtimeContext;
|
|
17
60
|
if (!routerContext) return;
|
|
18
|
-
const
|
|
61
|
+
const snapshot = {
|
|
19
62
|
framework: event.framework,
|
|
20
63
|
basename: event.basename,
|
|
21
64
|
statusCode: routerContext.statusCode,
|
|
@@ -29,21 +72,29 @@ function createRouterStatePlugin({ registryHooks }) {
|
|
|
29
72
|
routeId: match.route.id
|
|
30
73
|
}
|
|
31
74
|
] : [])
|
|
75
|
+
};
|
|
76
|
+
applyRouterServerPrepareResult(event.runtimeContext, {
|
|
77
|
+
snapshot,
|
|
78
|
+
state: {
|
|
79
|
+
framework: event.framework,
|
|
80
|
+
basename: event.basename,
|
|
81
|
+
instance: event.router
|
|
82
|
+
}
|
|
32
83
|
});
|
|
84
|
+
} else if ('client-create' === event.phase) {
|
|
85
|
+
const router = event.router;
|
|
86
|
+
const { router: api } = event.runtimeContext;
|
|
33
87
|
applyRouterRuntimeState(event.runtimeContext, {
|
|
34
88
|
framework: event.framework,
|
|
35
89
|
basename: event.basename,
|
|
36
|
-
instance:
|
|
37
|
-
|
|
38
|
-
|
|
90
|
+
instance: router,
|
|
91
|
+
...api?.Link ? {
|
|
92
|
+
navigation: createReactRouterNavigation(router, api.Link)
|
|
93
|
+
} : {}
|
|
39
94
|
});
|
|
40
|
-
}
|
|
41
|
-
framework: event.framework,
|
|
42
|
-
basename: event.basename,
|
|
43
|
-
instance: event.router
|
|
44
|
-
});
|
|
95
|
+
}
|
|
45
96
|
});
|
|
46
97
|
}
|
|
47
98
|
};
|
|
48
99
|
}
|
|
49
|
-
export { createRouterStatePlugin };
|
|
100
|
+
export { ROUTER_CLEANUP_ERROR, createRouterStatePlugin };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "node:module";
|
|
@@ -63,7 +63,7 @@ export type HelmetCompatState<Element> = {
|
|
|
63
63
|
style: HeadDatum<Element>;
|
|
64
64
|
title: HeadDatum<Element>;
|
|
65
65
|
};
|
|
66
|
-
export declare const renderHeadMarker: <Element>(react: ElementFactory<Element>, marker: MarkerProps |
|
|
66
|
+
export declare const renderHeadMarker: <Element>(react: ElementFactory<Element>, marker: MarkerProps | undefined) => Element | null;
|
|
67
67
|
export declare const markPriorityHeadRecord: (record: object, prioritize: boolean | undefined) => void;
|
|
68
68
|
export declare const isPriorityHeadTag: (tag: object) => boolean;
|
|
69
69
|
export declare const headTagsToComponents: <Element>(react: ElementFactory<Element>, tagName: string, tags: HeadTag[]) => Element[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LocalisedUrlsOption, ResolvedLocalisedUrlsConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Localised URLs are strictly opt-in: only an explicit, non-empty map enables
|
|
4
|
+
* route expansion and validation. `true`, `false`, an empty map and absence
|
|
5
|
+
* all resolve to disabled, so upstream-style configs (`localePathRedirect` +
|
|
6
|
+
* `languages` without a map) keep plain locale-prefix behavior instead of
|
|
7
|
+
* failing the build for every route missing from a map they never wrote.
|
|
8
|
+
*/
|
|
9
|
+
export declare const resolveLocalisedUrlsConfig: (option: LocalisedUrlsOption | undefined) => ResolvedLocalisedUrlsConfig;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { resolveLocalisedUrlsConfig } from './config.js';
|
|
2
|
+
export { normalisePathname, normalisePathPattern } from './normalise.js';
|
|
3
|
+
export { canonicalTargetPathname, localiseTargetPathname, stripLanguagePrefix, } from './pathname.js';
|
|
4
|
+
export { buildPathFromPattern, matchPathPattern } from './patterns.js';
|
|
5
|
+
export type { LocaleRedirectSkipRule } from './redirect.js';
|
|
6
|
+
export { DEFAULT_LOCALE_REDIRECT_SKIP_RULES, isDefaultLocaleRedirectSkipPath, matchesPathPrefix, shouldSkipLocaleRedirect, } from './redirect.js';
|
|
7
|
+
export { resolveCanonicalLocalisedPath, resolveLocalisedPath } from './resolve.js';
|
|
8
|
+
export { createLocalisedRouteRewrite } from './routeIdentity.js';
|
|
9
|
+
export { applyLocalisedUrlsToRoutes, validateLocalisedUrls } from './routes.js';
|
|
10
|
+
export type { LocalisedRoute, LocalisedUrlPathMap, LocalisedUrlsMap, LocalisedUrlsOption, ResolvedLocalisedUrlsConfig, } from './types.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const normalisePathPattern: (path: string) => string;
|
|
2
|
+
/**
|
|
3
|
+
* Normalise a concrete request pathname: slash cleanup only. Unlike
|
|
4
|
+
* {@link normalisePathPattern} it must not rewrite literal `[x]` segments to
|
|
5
|
+
* `:x` params — pathnames are values, not patterns.
|
|
6
|
+
*/
|
|
7
|
+
export declare const normalisePathname: (pathname: string) => string;
|
|
8
|
+
export declare const normaliseRoutePath: (path: string) => string;
|
|
9
|
+
export declare const stripLeadingLocaleParam: (path?: string) => string | undefined;
|
|
10
|
+
export declare const getLeadingLocaleParam: (path?: string) => string | null;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { LocalisedUrlsOption } from './types.js';
|
|
2
|
+
export declare const stripLanguagePrefix: (pathname: string, languages: string[]) => string;
|
|
3
|
+
export declare const localiseTargetPathname: (pathname: string, language: string, languages: string[], localisedUrls?: LocalisedUrlsOption) => string;
|
|
4
|
+
export declare const canonicalTargetPathname: (pathname: string, languages: string[], localisedUrls?: LocalisedUrlsOption) => string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const getOrderedPathParamSignature: (pattern: string) => string[];
|
|
2
|
+
export declare const getPathParamSignature: (pattern: string) => string[];
|
|
3
|
+
export declare const getPathPatternValidationIssue: (pattern: string) => string | undefined;
|
|
4
|
+
export declare const getPhysicalPathPattern: (pattern: string) => string;
|
|
5
|
+
export declare const haveEqualPatternSpecificity: (left: string, right: string) => boolean;
|
|
6
|
+
export declare const doPathPatternsOverlap: (left: string, right: string) => boolean;
|
|
7
|
+
export declare const sortPatternsBySpecificity: <T extends {
|
|
8
|
+
pattern: string;
|
|
9
|
+
}>(patterns: T[]) => T[];
|
|
10
|
+
export declare const matchPathPattern: (pathname: string, pattern: string) => Record<string, string> | null;
|
|
11
|
+
export declare const buildPathFromPattern: (pattern: string, params: Record<string, string>) => string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type LocaleRedirectSkipRule = {
|
|
2
|
+
type: 'exact';
|
|
3
|
+
path: string;
|
|
4
|
+
} | {
|
|
5
|
+
type: 'prefix';
|
|
6
|
+
path: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'pattern';
|
|
9
|
+
path: RegExp;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Federation artifacts are never pages. The remote entries match the same
|
|
13
|
+
* shapes the federation layer itself recognises and serves (`mfCache.ts`):
|
|
14
|
+
* a manifest may name a root entry such as `remoteEntry.catalog.js`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const DEFAULT_LOCALE_REDIRECT_SKIP_RULES: readonly LocaleRedirectSkipRule[];
|
|
17
|
+
export declare const matchesPathPrefix: (pathname: string, prefix: string) => boolean;
|
|
18
|
+
export declare const isDefaultLocaleRedirectSkipPath: (pathname: string, languages?: string[]) => boolean;
|
|
19
|
+
export declare const shouldSkipLocaleRedirect: (pathname: string, languages?: string[], ignoreRedirectRoutes?: string[] | ((pathname: string) => boolean)) => boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LocalisedUrlsMap } from './types.js';
|
|
2
|
+
export declare const resolveLocalisedPath: (pathname: string, targetLanguage: string, languages: string[], localisedUrls: LocalisedUrlsMap) => string;
|
|
3
|
+
/**
|
|
4
|
+
* Reverse-map language-specific pathnames back to language-agnostic
|
|
5
|
+
* LocalisedUrlsMap keys.
|
|
6
|
+
*/
|
|
7
|
+
export declare const resolveCanonicalLocalisedPath: (pathname: string, languages: string[], localisedUrls: LocalisedUrlsMap) => string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface RouteIdentity {
|
|
2
|
+
id?: string;
|
|
3
|
+
path?: string;
|
|
4
|
+
canonicalPath: string;
|
|
5
|
+
paths?: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
interface RouteNode {
|
|
8
|
+
id?: string;
|
|
9
|
+
path?: string;
|
|
10
|
+
children?: RouteNode[];
|
|
11
|
+
modernLocalisedRoute?: RouteIdentity;
|
|
12
|
+
}
|
|
13
|
+
/** Use the router's URL rewrite seam; browser URLs retain their locale spelling. */
|
|
14
|
+
export declare function createLocalisedRouteRewrite(routes: RouteNode[]): {
|
|
15
|
+
input: ({ url }: {
|
|
16
|
+
url: URL;
|
|
17
|
+
}) => URL;
|
|
18
|
+
output: ({ url }: {
|
|
19
|
+
url: URL;
|
|
20
|
+
}) => URL;
|
|
21
|
+
} | undefined;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { LocalisedRoute, LocalisedUrlsMap } from './types.js';
|
|
2
|
+
export declare const validateLocalisedUrls: (routes: LocalisedRoute[], languages: string[], localisedUrls: LocalisedUrlsMap) => void;
|
|
3
|
+
export declare const applyLocalisedUrlsToRoutes: (routes: LocalisedRoute[], languages: string[], localisedUrls: LocalisedUrlsMap, projection?: 'physical' | 'canonical') => LocalisedRoute[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type LocalisedRoute = {
|
|
2
|
+
type: 'nested' | 'page';
|
|
3
|
+
path?: string;
|
|
4
|
+
id?: string;
|
|
5
|
+
children?: LocalisedRoute[];
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
};
|
|
8
|
+
export type LocalisedUrlPathMap = Record<string, string>;
|
|
9
|
+
export type LocalisedUrlsMap = Record<string, LocalisedUrlPathMap>;
|
|
10
|
+
export type LocalisedUrlsOption = boolean | LocalisedUrlsMap;
|
|
11
|
+
export interface ResolvedLocalisedUrlsConfig {
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
map: LocalisedUrlsMap;
|
|
14
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
declare const MARKER_ATTRIBUTE = "data-modern-helmet";
|
|
2
2
|
export type RendererHeadMarkerProps = Record<typeof MARKER_ATTRIBUTE, string>;
|
|
3
3
|
export * from './helmetCompat.js';
|
|
4
|
-
export
|
|
5
|
-
export declare const
|
|
4
|
+
export type ReportLateHead = (message: string) => void;
|
|
5
|
+
export declare const LATE_HEAD_MESSAGE = "<Helmet> rendered in a boundary that completed after the shell; head tags dropped. Move it above the Suspense boundary or set server.ssrByEntries[entry].mode to 'string'.";
|
|
6
|
+
export declare const beginHeadRender: (context: object, reportLateHead: ReportLateHead) => void;
|
|
7
|
+
export declare const collectHeadRecord: <RecordType>(context: object, createRecord: () => RecordType, publish: (records: RecordType[]) => void) => RendererHeadMarkerProps | undefined;
|
|
6
8
|
export declare const collectHeadState: <RecordType, StateType>(context: object, createRecord: () => RecordType, derive: (records: RecordType[]) => StateType, target: {
|
|
7
9
|
helmet?: StateType;
|
|
8
|
-
}) => RendererHeadMarkerProps |
|
|
10
|
+
}) => RendererHeadMarkerProps | undefined;
|
|
9
11
|
export declare const publishHeadRender: (context: object) => void;
|
|
10
12
|
export declare const finishHeadRender: (context: object) => void;
|
|
11
13
|
export declare const completeHeadRender: (context: object, html: string) => string;
|
|
@@ -106,7 +106,7 @@ export type OperationContractOptions = {
|
|
|
106
106
|
requireOperationVersion?: boolean;
|
|
107
107
|
onViolation?: (violation: OperationContractViolation) => void;
|
|
108
108
|
};
|
|
109
|
-
export type OperationContextSource = 'client' | 'server' | 'generated-client' | 'effect-
|
|
109
|
+
export type OperationContextSource = 'client' | 'server' | 'generated-client' | 'effect-server' | 'data-platform' | 'unknown';
|
|
110
110
|
export type OperationContext = {
|
|
111
111
|
requestId?: string;
|
|
112
112
|
operationId?: string;
|
|
@@ -8,7 +8,7 @@ export type ScriptChunkLike = {
|
|
|
8
8
|
filename?: string;
|
|
9
9
|
url?: string;
|
|
10
10
|
};
|
|
11
|
-
export declare function getMatchedRouteChunks<T>(routeManifest: RouteManifestLike | undefined, matchedRouteIds: string[], routeAssetToChunk: (asset: string) => T): T[];
|
|
11
|
+
export declare function getMatchedRouteChunks<T>(routeManifest: RouteManifestLike | undefined, matchedRouteIds: readonly string[], routeAssetToChunk: (asset: string) => T): T[];
|
|
12
12
|
export declare const orderHydrationScriptChunks: <T extends ScriptChunkLike>({ asyncEntryChunks, collectedChunks, matchedRouteChunks, entryName, }: {
|
|
13
13
|
asyncEntryChunks: T[];
|
|
14
14
|
collectedChunks: T[];
|
|
@@ -17,7 +17,7 @@ export declare const orderHydrationScriptChunks: <T extends ScriptChunkLike>({ a
|
|
|
17
17
|
}) => T[];
|
|
18
18
|
export declare function injectBeforeHydrationEntryScript(template: string, scripts: string, entryName?: string): string;
|
|
19
19
|
export declare function replaceChunkJsPlaceholder(template: string, scripts: string, entryName: string | undefined, placeholder: string): string;
|
|
20
|
-
export declare function createRouteHydrationScriptTags(routeManifest: RouteManifestLike | undefined, matchedRouteIds: string[], entryName: string, options?: {
|
|
20
|
+
export declare function createRouteHydrationScriptTags(routeManifest: RouteManifestLike | undefined, matchedRouteIds: readonly string[], entryName: string, options?: {
|
|
21
21
|
nonce?: string;
|
|
22
22
|
template?: string;
|
|
23
23
|
}): string;
|
|
@@ -47,9 +47,7 @@ export declare function createRouterPlugin<Hooks extends Record<string, unknown>
|
|
|
47
47
|
name: string;
|
|
48
48
|
registryHooks: Hooks;
|
|
49
49
|
setup(api: {
|
|
50
|
-
getRuntimeConfig: () =>
|
|
51
|
-
router?: Record<string, unknown>;
|
|
52
|
-
};
|
|
50
|
+
getRuntimeConfig: () => Record<string, unknown>;
|
|
53
51
|
[key: string]: any;
|
|
54
52
|
}): void;
|
|
55
53
|
};
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { InternalRouterRuntimeState, InternalRouterServerSnapshot, RouterServerPrepareResult } from './routerStateTypes.js';
|
|
2
|
-
export type { BuiltInRouterFramework, InternalRouterRuntimeState, InternalRouterServerSnapshot, RouterFramework, RouterLifecyclePhase, RouterRouteMatchSnapshot, RouterServerPrepareResult, } from './routerStateTypes.js';
|
|
2
|
+
export type { BuiltInRouterFramework, InternalRouterRuntimeState, InternalRouterServerSnapshot, RouterFramework, RouterLifecyclePhase, RouterLinkTarget, RouterNavigationCapability, RouterNavigationSnapshot, RouterRouteMatchSnapshot, RouterServerPrepareResult, } from './routerStateTypes.js';
|
|
3
3
|
export declare function getRouterRuntimeState(runtimeContext: object): InternalRouterRuntimeState | undefined;
|
|
4
4
|
export declare function getRouterServerSnapshot(runtimeContext: object): InternalRouterServerSnapshot | undefined;
|
|
5
|
-
|
|
6
|
-
export declare function createRouterServerSnapshot(
|
|
7
|
-
|
|
5
|
+
/** Capture prepared metadata once; live router updates cannot rewrite it. */
|
|
6
|
+
export declare function createRouterServerSnapshot(snapshot: InternalRouterServerSnapshot): InternalRouterServerSnapshot;
|
|
7
|
+
/**
|
|
8
|
+
* Observe the router runtime-state slot for the given runtime context.
|
|
9
|
+
* Returns an unsubscribe function; safe to call for a context that never
|
|
10
|
+
* receives a router.
|
|
11
|
+
*/
|
|
12
|
+
export declare function subscribeRouterRuntimeState(runtimeContext: object, listener: () => void): () => void;
|
|
8
13
|
export declare function applyRouterRuntimeState<Context extends object>(runtimeContext: Context, state: InternalRouterRuntimeState): Context;
|
|
9
14
|
export declare function applyRouterServerPrepareResult<Context extends object>(runtimeContext: Context, result: RouterServerPrepareResult): Context;
|
|
10
|
-
export declare function getRouterHydrationScripts(runtimeContext: object): string[];
|
|
11
|
-
export declare function getRouterMatchedRouteIds(runtimeContext: object): string[] | undefined;
|
|
15
|
+
export declare function getRouterHydrationScripts(runtimeContext: object): readonly string[];
|
|
16
|
+
export declare function getRouterMatchedRouteIds(runtimeContext: object): readonly string[] | undefined;
|
|
12
17
|
export declare function cleanupRouterRuntimeState(runtimeContext: object): Promise<void>;
|
|
@@ -5,6 +5,14 @@ type RouterLifecycleEvent = {
|
|
|
5
5
|
basename?: string;
|
|
6
6
|
router?: unknown;
|
|
7
7
|
};
|
|
8
|
+
type PreparedRequest<RuntimeContext extends object = object> = {
|
|
9
|
+
runtimeContext: RuntimeContext;
|
|
10
|
+
routerResult?: {
|
|
11
|
+
statusCode?: number;
|
|
12
|
+
errors?: Record<string, unknown> | null;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export declare const ROUTER_CLEANUP_ERROR = "An error occurs during router runtime cleanup";
|
|
8
16
|
/** Install fork policy through lifecycle hooks supplied by the native owner. */
|
|
9
17
|
export declare function createRouterStatePlugin<Hooks extends Record<string, unknown>>({ registryHooks, }: {
|
|
10
18
|
registryHooks: Hooks;
|
|
@@ -13,6 +21,10 @@ export declare function createRouterStatePlugin<Hooks extends Record<string, unk
|
|
|
13
21
|
registryHooks: Hooks;
|
|
14
22
|
setup(api: {
|
|
15
23
|
onBeforeRender: (callback: (context: object) => void) => unknown;
|
|
24
|
+
onRenderPrepared: (callback: <RuntimeContext extends object>(info: PreparedRequest<RuntimeContext>) => PreparedRequest<RuntimeContext>) => unknown;
|
|
25
|
+
onRequestEnd: (callback: (info: {
|
|
26
|
+
runtimeContext: object;
|
|
27
|
+
}) => Promise<void>) => unknown;
|
|
16
28
|
onAfterCreateRouter: (callback: (event: RouterLifecycleEvent) => void) => unknown;
|
|
17
29
|
}): void;
|
|
18
30
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type React from 'react';
|
|
1
2
|
export type BuiltInRouterFramework = 'react-router' | 'tanstack';
|
|
2
3
|
export type RouterFramework = BuiltInRouterFramework | (string & {});
|
|
3
4
|
export interface RouterRouteMatchSnapshot {
|
|
@@ -7,34 +8,63 @@ export interface RouterRouteMatchSnapshot {
|
|
|
7
8
|
params?: Record<string, string>;
|
|
8
9
|
}
|
|
9
10
|
export interface InternalRouterServerSnapshot {
|
|
10
|
-
framework?: RouterFramework;
|
|
11
|
-
basename?: string;
|
|
12
|
-
statusCode?: number;
|
|
13
|
-
errors?: Record<string, unknown>;
|
|
14
|
-
routerData?: {
|
|
15
|
-
loaderData?: Record<string, unknown>;
|
|
16
|
-
errors?: Record<string, unknown>;
|
|
11
|
+
readonly framework?: RouterFramework;
|
|
12
|
+
readonly basename?: string;
|
|
13
|
+
readonly statusCode?: number;
|
|
14
|
+
readonly errors?: Record<string, unknown>;
|
|
15
|
+
readonly routerData?: {
|
|
16
|
+
readonly loaderData?: Record<string, unknown>;
|
|
17
|
+
readonly errors?: Record<string, unknown>;
|
|
17
18
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
matches?: RouterRouteMatchSnapshot[];
|
|
19
|
+
readonly hydrationScripts?: readonly string[];
|
|
20
|
+
readonly matchedRouteIds?: readonly string[];
|
|
21
|
+
readonly matches?: readonly RouterRouteMatchSnapshot[];
|
|
22
22
|
}
|
|
23
23
|
export interface InternalRouterRuntimeState {
|
|
24
24
|
framework: RouterFramework;
|
|
25
25
|
basename?: string;
|
|
26
26
|
instance?: unknown;
|
|
27
|
-
|
|
28
|
-
hydrationScripts?: string[];
|
|
29
|
-
matchedRouteIds?: string[];
|
|
30
|
-
matches?: RouterRouteMatchSnapshot[];
|
|
31
|
-
serverSnapshot?: InternalRouterServerSnapshot;
|
|
27
|
+
navigation?: RouterNavigationCapability;
|
|
32
28
|
cleanup?: () => void | Promise<void>;
|
|
33
29
|
}
|
|
34
30
|
export interface RouterServerPrepareResult {
|
|
35
31
|
state: InternalRouterRuntimeState;
|
|
36
32
|
snapshot?: InternalRouterServerSnapshot;
|
|
37
|
-
redirect?: Response;
|
|
38
33
|
cleanup?: () => void | Promise<void>;
|
|
39
34
|
}
|
|
40
35
|
export type RouterLifecyclePhase = 'ssr-prepare' | 'client-create' | 'hydrate';
|
|
36
|
+
/** Provider-owned browser navigation. Consumers never inspect router internals. */
|
|
37
|
+
export interface RouterNavigationSnapshot {
|
|
38
|
+
location: {
|
|
39
|
+
pathname: string;
|
|
40
|
+
search: string;
|
|
41
|
+
hash: string;
|
|
42
|
+
};
|
|
43
|
+
params: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
export interface RouterLinkTarget {
|
|
46
|
+
pathname: string;
|
|
47
|
+
href: string;
|
|
48
|
+
search?: Record<string, unknown>;
|
|
49
|
+
hash?: string;
|
|
50
|
+
hashScrollIntoView?: boolean | ScrollIntoViewOptions;
|
|
51
|
+
prefetch?: 'intent' | 'render' | 'viewport' | 'none';
|
|
52
|
+
preload?: unknown;
|
|
53
|
+
}
|
|
54
|
+
export interface RouterNavigationCapability {
|
|
55
|
+
getSnapshot: () => RouterNavigationSnapshot;
|
|
56
|
+
subscribe: (listener: () => void) => () => void;
|
|
57
|
+
navigate: (href: string, options?: {
|
|
58
|
+
replace?: boolean;
|
|
59
|
+
state?: unknown;
|
|
60
|
+
}) => void | Promise<void>;
|
|
61
|
+
Link: React.ComponentType<{
|
|
62
|
+
to: string;
|
|
63
|
+
children?: React.ReactNode;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}>;
|
|
66
|
+
createLinkProps?: (target: RouterLinkTarget) => {
|
|
67
|
+
to: string;
|
|
68
|
+
[key: string]: unknown;
|
|
69
|
+
};
|
|
70
|
+
}
|