@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.
Files changed (124) hide show
  1. package/dist/cjs/{reactContext.js → localisedUrls/config.js} +14 -10
  2. package/dist/cjs/localisedUrls/index.js +95 -0
  3. package/dist/cjs/localisedUrls/normalise.js +87 -0
  4. package/dist/cjs/localisedUrls/pathname.js +68 -0
  5. package/dist/cjs/localisedUrls/patterns.js +214 -0
  6. package/dist/cjs/localisedUrls/redirect.js +104 -0
  7. package/dist/cjs/localisedUrls/resolve.js +78 -0
  8. package/dist/cjs/localisedUrls/routeIdentity.js +92 -0
  9. package/dist/cjs/localisedUrls/routes.js +217 -0
  10. package/dist/cjs/localisedUrls/types.js +18 -0
  11. package/dist/cjs/rendererHead.js +18 -5
  12. package/dist/cjs/request-policy/policyCore.js +1 -1
  13. package/dist/cjs/request-policy/transport.js +2 -2
  14. package/dist/cjs/routerState.js +85 -77
  15. package/dist/cjs/routerStatePlugin.js +63 -9
  16. package/dist/cjs/server-config/serverSource.js +18 -0
  17. package/dist/esm/localisedUrls/config.mjs +11 -0
  18. package/dist/esm/localisedUrls/index.mjs +8 -0
  19. package/dist/esm/localisedUrls/normalise.mjs +37 -0
  20. package/dist/esm/localisedUrls/pathname.mjs +24 -0
  21. package/dist/esm/localisedUrls/patterns.mjs +152 -0
  22. package/dist/esm/localisedUrls/redirect.mjs +57 -0
  23. package/dist/esm/localisedUrls/resolve.mjs +37 -0
  24. package/dist/esm/localisedUrls/routeIdentity.mjs +54 -0
  25. package/dist/esm/localisedUrls/routes.mjs +176 -0
  26. package/dist/esm/localisedUrls/types.mjs +0 -0
  27. package/dist/esm/rendererHead.mjs +14 -5
  28. package/dist/esm/request-policy/policyCore.mjs +1 -1
  29. package/dist/esm/request-policy/transport.mjs +2 -2
  30. package/dist/esm/routerState.mjs +81 -73
  31. package/dist/esm/routerStatePlugin.mjs +62 -11
  32. package/dist/esm/server-config/serverSource.mjs +0 -0
  33. package/dist/esm-node/localisedUrls/config.mjs +12 -0
  34. package/dist/esm-node/localisedUrls/index.mjs +9 -0
  35. package/dist/esm-node/localisedUrls/normalise.mjs +38 -0
  36. package/dist/esm-node/localisedUrls/pathname.mjs +25 -0
  37. package/dist/esm-node/localisedUrls/patterns.mjs +153 -0
  38. package/dist/esm-node/localisedUrls/redirect.mjs +58 -0
  39. package/dist/esm-node/localisedUrls/resolve.mjs +38 -0
  40. package/dist/esm-node/localisedUrls/routeIdentity.mjs +55 -0
  41. package/dist/esm-node/localisedUrls/routes.mjs +177 -0
  42. package/dist/esm-node/localisedUrls/types.mjs +1 -0
  43. package/dist/esm-node/rendererHead.mjs +14 -5
  44. package/dist/esm-node/request-policy/policyCore.mjs +1 -1
  45. package/dist/esm-node/request-policy/transport.mjs +2 -2
  46. package/dist/esm-node/routerState.mjs +81 -73
  47. package/dist/esm-node/routerStatePlugin.mjs +62 -11
  48. package/dist/esm-node/server-config/serverSource.mjs +1 -0
  49. package/dist/types/helmetCompat.d.ts +1 -1
  50. package/dist/types/localisedUrls/config.d.ts +9 -0
  51. package/dist/types/localisedUrls/index.d.ts +10 -0
  52. package/dist/types/localisedUrls/normalise.d.ts +10 -0
  53. package/dist/types/localisedUrls/pathname.d.ts +4 -0
  54. package/dist/types/localisedUrls/patterns.d.ts +11 -0
  55. package/dist/types/localisedUrls/redirect.d.ts +19 -0
  56. package/dist/types/localisedUrls/resolve.d.ts +7 -0
  57. package/dist/types/localisedUrls/routeIdentity.d.ts +22 -0
  58. package/dist/types/localisedUrls/routes.d.ts +3 -0
  59. package/dist/types/localisedUrls/types.d.ts +14 -0
  60. package/dist/types/rendererHead.d.ts +5 -3
  61. package/dist/types/request-policy/types.d.ts +1 -1
  62. package/dist/types/routeHydration.d.ts +2 -2
  63. package/dist/types/routerProvider.d.ts +1 -3
  64. package/dist/types/routerState.d.ts +11 -6
  65. package/dist/types/routerStatePlugin.d.ts +12 -0
  66. package/dist/types/routerStateTypes.d.ts +47 -17
  67. package/dist/types/server-config/index.d.ts +1 -0
  68. package/dist/types/server-config/serverSource.d.ts +16 -0
  69. package/package.json +42 -44
  70. package/src/helmetCompat.ts +1 -1
  71. package/src/localisedUrls/config.ts +18 -0
  72. package/src/localisedUrls/index.ts +25 -0
  73. package/src/localisedUrls/normalise.ts +62 -0
  74. package/src/localisedUrls/pathname.ts +60 -0
  75. package/src/localisedUrls/patterns.ts +283 -0
  76. package/src/localisedUrls/redirect.ts +110 -0
  77. package/src/localisedUrls/resolve.ts +106 -0
  78. package/src/localisedUrls/routeIdentity.ts +83 -0
  79. package/src/localisedUrls/routes.ts +451 -0
  80. package/src/localisedUrls/types.ts +18 -0
  81. package/src/rendererHead.ts +25 -8
  82. package/src/request-policy/policyCore.ts +1 -1
  83. package/src/request-policy/transport.ts +2 -2
  84. package/src/request-policy/types.ts +1 -1
  85. package/src/routeHydration.ts +2 -2
  86. package/src/routerProvider.ts +1 -1
  87. package/src/routerState.ts +127 -115
  88. package/src/routerStatePlugin.ts +106 -10
  89. package/src/routerStateTypes.ts +47 -17
  90. package/src/server-config/index.ts +1 -0
  91. package/src/server-config/serverSource.ts +23 -0
  92. package/dist/cjs/buildIdentity.js +0 -73
  93. package/dist/esm/buildIdentity.mjs +0 -35
  94. package/dist/esm/reactContext.mjs +0 -7
  95. package/dist/esm-node/buildIdentity.mjs +0 -36
  96. package/dist/esm-node/reactContext.mjs +0 -8
  97. package/dist/types/buildIdentity.d.ts +0 -37
  98. package/dist/types/reactContext.d.ts +0 -6
  99. package/rslib.config.mts +0 -19
  100. package/rstest.config.mts +0 -38
  101. package/src/buildIdentity.ts +0 -61
  102. package/src/reactContext.ts +0 -16
  103. package/tests/buildIdentity.test.ts +0 -51
  104. package/tests/contextExtensions.test.ts +0 -27
  105. package/tests/headRuntime.test.tsx +0 -229
  106. package/tests/rendererHead.test.ts +0 -187
  107. package/tests/request-policy/browser-policy.test.ts +0 -108
  108. package/tests/request-policy/client-isolation.test.ts +0 -109
  109. package/tests/request-policy/node-policy.test.ts +0 -447
  110. package/tests/request-policy/policyCore.test.ts +0 -129
  111. package/tests/request-policy/requestContext.test.ts +0 -66
  112. package/tests/request-policy/requestFactory.outbound-contract.test.ts +0 -290
  113. package/tests/request-policy/traceparent.test.ts +0 -52
  114. package/tests/request-policy/transport-retry.test.ts +0 -367
  115. package/tests/routeHydration.test.ts +0 -180
  116. package/tests/routerPrefetchPolicy.test.ts +0 -102
  117. package/tests/routerProvider.test.ts +0 -29
  118. package/tests/routerState.test.ts +0 -78
  119. package/tests/routerStatePlugin.test.ts +0 -63
  120. package/tests/runtimeContextProjection.test.ts +0 -83
  121. package/tests/safeFailure.test.ts +0 -136
  122. package/tests/shellStream.test.ts +0 -122
  123. package/tests/workspaceEvents.test.ts +0 -221
  124. package/tsconfig.json +0 -10
@@ -31,12 +31,12 @@ __webpack_require__.d(__webpack_exports__, {
31
31
  applyRouterRuntimeState: ()=>applyRouterRuntimeState,
32
32
  applyRouterServerPrepareResult: ()=>applyRouterServerPrepareResult,
33
33
  cleanupRouterRuntimeState: ()=>cleanupRouterRuntimeState,
34
- createRouterRuntimeState: ()=>createRouterRuntimeState,
35
34
  createRouterServerSnapshot: ()=>createRouterServerSnapshot,
36
35
  getRouterHydrationScripts: ()=>getRouterHydrationScripts,
37
36
  getRouterMatchedRouteIds: ()=>getRouterMatchedRouteIds,
38
37
  getRouterRuntimeState: ()=>getRouterRuntimeState,
39
- getRouterServerSnapshot: ()=>getRouterServerSnapshot
38
+ getRouterServerSnapshot: ()=>getRouterServerSnapshot,
39
+ subscribeRouterRuntimeState: ()=>subscribeRouterRuntimeState
40
40
  });
41
41
  const external_contextExtensions_js_namespaceObject = require("./contextExtensions.js");
42
42
  const routerRuntimeStateExtension = (0, external_contextExtensions_js_namespaceObject.createRuntimeContextExtension)('@modern-js/runtime:router-runtime-state');
@@ -47,95 +47,103 @@ function getRouterRuntimeState(runtimeContext) {
47
47
  function getRouterServerSnapshot(runtimeContext) {
48
48
  return routerServerSnapshotExtension.get(runtimeContext);
49
49
  }
50
- function toHydrationScripts(state) {
51
- if (state.hydrationScripts?.length) return state.hydrationScripts;
52
- return state.hydrationScript ? [
53
- state.hydrationScript
54
- ] : void 0;
55
- }
56
- function getMatchedRouteIdsFromMatches(matches) {
57
- const routeIds = matches?.map((match)=>match.assetRouteId ?? match.routeId).filter((routeId)=>'string' == typeof routeId);
58
- return routeIds?.length ? routeIds : void 0;
59
- }
60
- function createRouterServerSnapshot(state) {
61
- const hydrationScripts = toHydrationScripts(state);
62
- const matchedRouteIds = state.matchedRouteIds ?? getMatchedRouteIdsFromMatches(state.matches);
63
- return {
64
- ...state,
65
- ...hydrationScripts?.length ? {
66
- hydrationScript: state.hydrationScript ?? hydrationScripts[0],
67
- hydrationScripts
50
+ function createRouterServerSnapshot(snapshot) {
51
+ const matches = snapshot.matches?.map((match)=>Object.freeze({
52
+ ...match,
53
+ ...match.params ? {
54
+ params: Object.freeze({
55
+ ...match.params
56
+ })
57
+ } : {}
58
+ }));
59
+ const matchedRouteIds = snapshot.matchedRouteIds ?? matches?.map((match)=>match.assetRouteId ?? match.routeId);
60
+ return Object.freeze({
61
+ ...snapshot,
62
+ ...snapshot.hydrationScripts ? {
63
+ hydrationScripts: Object.freeze([
64
+ ...snapshot.hydrationScripts
65
+ ])
68
66
  } : {},
69
67
  ...matchedRouteIds ? {
70
- matchedRouteIds
71
- } : {}
72
- };
73
- }
74
- function createRouterRuntimeState(state) {
75
- const hasSnapshotState = Boolean(state.serverSnapshot) || Boolean(state.hydrationScript) || Boolean(state.hydrationScripts?.length) || Boolean(state.matchedRouteIds?.length) || Boolean(state.matches?.length);
76
- const serverSnapshot = state.serverSnapshot ? createRouterServerSnapshot({
77
- ...state.serverSnapshot,
78
- framework: state.serverSnapshot.framework ?? state.framework,
79
- basename: state.serverSnapshot.basename ?? state.basename,
80
- hydrationScript: state.serverSnapshot.hydrationScript ?? state.hydrationScript,
81
- hydrationScripts: state.serverSnapshot.hydrationScripts ?? state.hydrationScripts,
82
- matchedRouteIds: state.serverSnapshot.matchedRouteIds ?? state.matchedRouteIds,
83
- matches: state.serverSnapshot.matches ?? state.matches
84
- }) : hasSnapshotState ? createRouterServerSnapshot({
85
- framework: state.framework,
86
- basename: state.basename,
87
- hydrationScript: state.hydrationScript,
88
- hydrationScripts: state.hydrationScripts,
89
- matchedRouteIds: state.matchedRouteIds,
90
- matches: state.matches
91
- }) : void 0;
92
- const hydrationScripts = toHydrationScripts({
93
- hydrationScript: state.hydrationScript ?? serverSnapshot?.hydrationScript,
94
- hydrationScripts: state.hydrationScripts ?? serverSnapshot?.hydrationScripts
95
- });
96
- const matchedRouteIds = state.matchedRouteIds ?? serverSnapshot?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(state.matches);
97
- return {
98
- ...state,
99
- ...hydrationScripts?.length ? {
100
- hydrationScript: state.hydrationScript ?? hydrationScripts[0],
101
- hydrationScripts
68
+ matchedRouteIds: Object.freeze([
69
+ ...matchedRouteIds
70
+ ])
102
71
  } : {},
103
- ...matchedRouteIds ? {
104
- matchedRouteIds
72
+ ...matches ? {
73
+ matches: Object.freeze(matches)
105
74
  } : {},
106
- ...serverSnapshot ? {
107
- serverSnapshot
75
+ ...snapshot.errors ? {
76
+ errors: Object.freeze({
77
+ ...snapshot.errors
78
+ })
79
+ } : {},
80
+ ...snapshot.routerData ? {
81
+ routerData: Object.freeze({
82
+ ...snapshot.routerData,
83
+ ...snapshot.routerData.loaderData ? {
84
+ loaderData: Object.freeze({
85
+ ...snapshot.routerData.loaderData
86
+ })
87
+ } : {},
88
+ ...snapshot.routerData.errors ? {
89
+ errors: Object.freeze({
90
+ ...snapshot.routerData.errors
91
+ })
92
+ } : {}
93
+ })
108
94
  } : {}
95
+ });
96
+ }
97
+ const routerRuntimeStateListeners = new WeakMap();
98
+ function subscribeRouterRuntimeState(runtimeContext, listener) {
99
+ if (!runtimeContext || 'object' != typeof runtimeContext) return ()=>void 0;
100
+ let listeners = routerRuntimeStateListeners.get(runtimeContext);
101
+ if (!listeners) {
102
+ listeners = new Set();
103
+ routerRuntimeStateListeners.set(runtimeContext, listeners);
104
+ }
105
+ listeners.add(listener);
106
+ return ()=>{
107
+ listeners?.delete(listener);
109
108
  };
110
109
  }
110
+ const pendingRouterRuntimeStateNotifications = new WeakSet();
111
+ function notifyRouterRuntimeState(runtimeContext) {
112
+ const listeners = routerRuntimeStateListeners.get(runtimeContext);
113
+ if (!listeners?.size) return;
114
+ if (pendingRouterRuntimeStateNotifications.has(runtimeContext)) return;
115
+ pendingRouterRuntimeStateNotifications.add(runtimeContext);
116
+ const deliver = ()=>{
117
+ pendingRouterRuntimeStateNotifications.delete(runtimeContext);
118
+ const current = routerRuntimeStateListeners.get(runtimeContext);
119
+ if (!current?.size) return;
120
+ for (const listener of [
121
+ ...current
122
+ ])try {
123
+ listener();
124
+ } catch {}
125
+ };
126
+ if ('function' == typeof queueMicrotask) queueMicrotask(deliver);
127
+ else setTimeout(deliver, 0);
128
+ }
111
129
  function applyRouterRuntimeState(runtimeContext, state) {
112
- const normalized = createRouterRuntimeState(state);
113
- routerRuntimeStateExtension.set(runtimeContext, normalized);
114
- if (normalized.serverSnapshot) routerServerSnapshotExtension.set(runtimeContext, normalized.serverSnapshot);
130
+ const previous = routerRuntimeStateExtension.get(runtimeContext);
131
+ routerRuntimeStateExtension.set(runtimeContext, state);
132
+ if (previous?.instance !== state.instance || previous?.framework !== state.framework || previous?.navigation !== state.navigation) notifyRouterRuntimeState(runtimeContext);
115
133
  return runtimeContext;
116
134
  }
117
135
  function applyRouterServerPrepareResult(runtimeContext, result) {
118
- const state = createRouterRuntimeState({
136
+ if (result.snapshot) routerServerSnapshotExtension.set(runtimeContext, createRouterServerSnapshot(result.snapshot));
137
+ return applyRouterRuntimeState(runtimeContext, {
119
138
  ...result.state,
120
- cleanup: result.cleanup ?? result.state.cleanup,
121
- serverSnapshot: result.snapshot ?? result.state.serverSnapshot
139
+ cleanup: result.cleanup ?? result.state.cleanup
122
140
  });
123
- applyRouterRuntimeState(runtimeContext, state);
124
- return runtimeContext;
125
141
  }
126
142
  function getRouterHydrationScripts(runtimeContext) {
127
- const serverSnapshot = getRouterServerSnapshot(runtimeContext);
128
- const runtimeState = getRouterRuntimeState(runtimeContext);
129
- return serverSnapshot?.hydrationScripts ?? toHydrationScripts({
130
- hydrationScript: serverSnapshot?.hydrationScript
131
- }) ?? runtimeState?.hydrationScripts ?? toHydrationScripts({
132
- hydrationScript: runtimeState?.hydrationScript
133
- }) ?? [];
143
+ return getRouterServerSnapshot(runtimeContext)?.hydrationScripts ?? [];
134
144
  }
135
145
  function getRouterMatchedRouteIds(runtimeContext) {
136
- const serverSnapshot = getRouterServerSnapshot(runtimeContext);
137
- const runtimeState = getRouterRuntimeState(runtimeContext);
138
- return serverSnapshot?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(serverSnapshot?.matches) ?? runtimeState?.matchedRouteIds ?? getMatchedRouteIdsFromMatches(runtimeState?.matches);
146
+ return getRouterServerSnapshot(runtimeContext)?.matchedRouteIds;
139
147
  }
140
148
  async function cleanupRouterRuntimeState(runtimeContext) {
141
149
  try {
@@ -145,22 +153,22 @@ async function cleanupRouterRuntimeState(runtimeContext) {
145
153
  exports.applyRouterRuntimeState = __webpack_exports__.applyRouterRuntimeState;
146
154
  exports.applyRouterServerPrepareResult = __webpack_exports__.applyRouterServerPrepareResult;
147
155
  exports.cleanupRouterRuntimeState = __webpack_exports__.cleanupRouterRuntimeState;
148
- exports.createRouterRuntimeState = __webpack_exports__.createRouterRuntimeState;
149
156
  exports.createRouterServerSnapshot = __webpack_exports__.createRouterServerSnapshot;
150
157
  exports.getRouterHydrationScripts = __webpack_exports__.getRouterHydrationScripts;
151
158
  exports.getRouterMatchedRouteIds = __webpack_exports__.getRouterMatchedRouteIds;
152
159
  exports.getRouterRuntimeState = __webpack_exports__.getRouterRuntimeState;
153
160
  exports.getRouterServerSnapshot = __webpack_exports__.getRouterServerSnapshot;
161
+ exports.subscribeRouterRuntimeState = __webpack_exports__.subscribeRouterRuntimeState;
154
162
  for(var __rspack_i in __webpack_exports__)if (-1 === [
155
163
  "applyRouterRuntimeState",
156
164
  "applyRouterServerPrepareResult",
157
165
  "cleanupRouterRuntimeState",
158
- "createRouterRuntimeState",
159
166
  "createRouterServerSnapshot",
160
167
  "getRouterHydrationScripts",
161
168
  "getRouterMatchedRouteIds",
162
169
  "getRouterRuntimeState",
163
- "getRouterServerSnapshot"
170
+ "getRouterServerSnapshot",
171
+ "subscribeRouterRuntimeState"
164
172
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
165
173
  Object.defineProperty(exports, '__esModule', {
166
174
  value: true
@@ -28,25 +28,69 @@ var __webpack_require__ = {};
28
28
  var __webpack_exports__ = {};
29
29
  __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
+ ROUTER_CLEANUP_ERROR: ()=>ROUTER_CLEANUP_ERROR,
31
32
  createRouterStatePlugin: ()=>createRouterStatePlugin
32
33
  });
33
34
  const external_routerPrefetchPolicy_js_namespaceObject = require("./routerPrefetchPolicy.js");
34
35
  const external_routerState_js_namespaceObject = require("./routerState.js");
36
+ const ROUTER_CLEANUP_ERROR = 'An error occurs during router runtime cleanup';
37
+ const installedRouterPolicies = new WeakSet();
38
+ function createReactRouterNavigation(router, Link) {
39
+ let state;
40
+ let snapshot;
41
+ return {
42
+ Link,
43
+ getSnapshot () {
44
+ if (state !== router.state) {
45
+ state = router.state;
46
+ snapshot = {
47
+ location: state.location,
48
+ params: Object.assign({}, ...state.matches.map((match)=>match.params))
49
+ };
50
+ }
51
+ return snapshot;
52
+ },
53
+ subscribe: (listener)=>router.subscribe(listener),
54
+ navigate: (href, options)=>router.navigate(href, options)
55
+ };
56
+ }
35
57
  function createRouterStatePlugin({ registryHooks }) {
36
58
  return {
37
59
  name: '@modern-js/router-runtime-policy',
38
60
  registryHooks,
39
61
  setup (api) {
62
+ if (installedRouterPolicies.has(api)) return;
63
+ installedRouterPolicies.add(api);
40
64
  api.onBeforeRender((context)=>{
41
65
  const runtimeContext = context;
42
66
  runtimeContext.linkPrefetchPolicy ??= (0, external_routerPrefetchPolicy_js_namespaceObject.createRouterPrefetchPolicy)();
43
67
  });
68
+ api.onRenderPrepared((info)=>{
69
+ const snapshot = (0, external_routerState_js_namespaceObject.getRouterServerSnapshot)(info.runtimeContext);
70
+ if (!snapshot) return info;
71
+ return {
72
+ ...info,
73
+ routerResult: {
74
+ statusCode: snapshot.statusCode ?? info.routerResult?.statusCode,
75
+ errors: snapshot.errors ?? info.routerResult?.errors
76
+ }
77
+ };
78
+ });
79
+ api.onRequestEnd(async ({ runtimeContext })=>{
80
+ try {
81
+ await (0, external_routerState_js_namespaceObject.getRouterRuntimeState)(runtimeContext)?.cleanup?.();
82
+ } catch (error) {
83
+ const { ssrContext } = runtimeContext;
84
+ if (!ssrContext) throw error;
85
+ ssrContext.onError(error, ROUTER_CLEANUP_ERROR);
86
+ }
87
+ });
44
88
  api.onAfterCreateRouter((event)=>{
45
89
  if ('react-router' !== event.framework) return;
46
90
  if ('ssr-prepare' === event.phase) {
47
91
  const { routerContext } = event.runtimeContext;
48
92
  if (!routerContext) return;
49
- const serverSnapshot = (0, external_routerState_js_namespaceObject.createRouterServerSnapshot)({
93
+ const snapshot = {
50
94
  framework: event.framework,
51
95
  basename: event.basename,
52
96
  statusCode: routerContext.statusCode,
@@ -60,25 +104,35 @@ function createRouterStatePlugin({ registryHooks }) {
60
104
  routeId: match.route.id
61
105
  }
62
106
  ] : [])
107
+ };
108
+ (0, external_routerState_js_namespaceObject.applyRouterServerPrepareResult)(event.runtimeContext, {
109
+ snapshot,
110
+ state: {
111
+ framework: event.framework,
112
+ basename: event.basename,
113
+ instance: event.router
114
+ }
63
115
  });
116
+ } else if ('client-create' === event.phase) {
117
+ const router = event.router;
118
+ const { router: api } = event.runtimeContext;
64
119
  (0, external_routerState_js_namespaceObject.applyRouterRuntimeState)(event.runtimeContext, {
65
120
  framework: event.framework,
66
121
  basename: event.basename,
67
- instance: event.router,
68
- matchedRouteIds: serverSnapshot.matchedRouteIds,
69
- serverSnapshot
122
+ instance: router,
123
+ ...api?.Link ? {
124
+ navigation: createReactRouterNavigation(router, api.Link)
125
+ } : {}
70
126
  });
71
- } else if ('client-create' === event.phase) (0, external_routerState_js_namespaceObject.applyRouterRuntimeState)(event.runtimeContext, {
72
- framework: event.framework,
73
- basename: event.basename,
74
- instance: event.router
75
- });
127
+ }
76
128
  });
77
129
  }
78
130
  };
79
131
  }
132
+ exports.ROUTER_CLEANUP_ERROR = __webpack_exports__.ROUTER_CLEANUP_ERROR;
80
133
  exports.createRouterStatePlugin = __webpack_exports__.createRouterStatePlugin;
81
134
  for(var __rspack_i in __webpack_exports__)if (-1 === [
135
+ "ROUTER_CLEANUP_ERROR",
82
136
  "createRouterStatePlugin"
83
137
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
84
138
  Object.defineProperty(exports, '__esModule', {
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.r = (exports1)=>{
5
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
6
+ value: 'Module'
7
+ });
8
+ Object.defineProperty(exports1, '__esModule', {
9
+ value: true
10
+ });
11
+ };
12
+ })();
13
+ var __webpack_exports__ = {};
14
+ __webpack_require__.r(__webpack_exports__);
15
+ for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
16
+ Object.defineProperty(exports, '__esModule', {
17
+ value: true
18
+ });
@@ -0,0 +1,11 @@
1
+ const resolveLocalisedUrlsConfig = (option)=>{
2
+ if (option && 'object' == typeof option && Object.keys(option).length > 0) return {
3
+ enabled: true,
4
+ map: option
5
+ };
6
+ return {
7
+ enabled: false,
8
+ map: {}
9
+ };
10
+ };
11
+ export { resolveLocalisedUrlsConfig };
@@ -0,0 +1,8 @@
1
+ export { resolveLocalisedUrlsConfig } from "./config.mjs";
2
+ export { normalisePathPattern, normalisePathname } from "./normalise.mjs";
3
+ export { canonicalTargetPathname, localiseTargetPathname, stripLanguagePrefix } from "./pathname.mjs";
4
+ export { buildPathFromPattern, matchPathPattern } from "./patterns.mjs";
5
+ export { DEFAULT_LOCALE_REDIRECT_SKIP_RULES, isDefaultLocaleRedirectSkipPath, matchesPathPrefix, shouldSkipLocaleRedirect } from "./redirect.mjs";
6
+ export { resolveCanonicalLocalisedPath, resolveLocalisedPath } from "./resolve.mjs";
7
+ export { createLocalisedRouteRewrite } from "./routeIdentity.mjs";
8
+ export { applyLocalisedUrlsToRoutes, validateLocalisedUrls } from "./routes.mjs";
@@ -0,0 +1,37 @@
1
+ const LOCALE_PARAM_NAMES = new Set([
2
+ 'lang',
3
+ 'locale',
4
+ 'language'
5
+ ]);
6
+ const normaliseSlashes = (path)=>{
7
+ const withoutDuplicateSlashes = path.replace(/\/+/g, '/');
8
+ const withLeadingSlash = withoutDuplicateSlashes.startsWith('/') ? withoutDuplicateSlashes : `/${withoutDuplicateSlashes}`;
9
+ return withLeadingSlash.length > 1 ? withLeadingSlash.replace(/\/+$/, '') : withLeadingSlash;
10
+ };
11
+ const normalisePathPattern = (path)=>normaliseSlashes(path).replace(/\[(.+?)\]/g, ':$1');
12
+ const normalisePathname = (pathname)=>normaliseSlashes(pathname);
13
+ const normaliseRoutePath = (path)=>{
14
+ const normalized = normalisePathPattern(path);
15
+ return '/' === normalized ? '' : normalized.slice(1);
16
+ };
17
+ const getLocaleParamSegment = (segment)=>{
18
+ if (!segment.startsWith(':')) return null;
19
+ const paramName = segment.slice(1).replace(/\?$/, '');
20
+ return LOCALE_PARAM_NAMES.has(paramName) ? segment : null;
21
+ };
22
+ const splitPathSegments = (path)=>{
23
+ if (!path) return [];
24
+ return normalisePathPattern(path).split('/').filter(Boolean);
25
+ };
26
+ const stripLeadingLocaleParam = (path)=>{
27
+ const segments = splitPathSegments(path);
28
+ const leadingLocaleParam = getLocaleParamSegment(segments[0] || '');
29
+ if (!leadingLocaleParam) return path;
30
+ const remainingPath = segments.slice(1).join('/');
31
+ return remainingPath ? `/${remainingPath}` : void 0;
32
+ };
33
+ const getLeadingLocaleParam = (path)=>{
34
+ const segments = splitPathSegments(path);
35
+ return getLocaleParamSegment(segments[0] || '');
36
+ };
37
+ export { getLeadingLocaleParam, normalisePathPattern, normalisePathname, normaliseRoutePath, stripLeadingLocaleParam };
@@ -0,0 +1,24 @@
1
+ import { resolveLocalisedUrlsConfig } from "./config.mjs";
2
+ import { resolveCanonicalLocalisedPath, resolveLocalisedPath } from "./resolve.mjs";
3
+ const stripLanguagePrefix = (pathname, languages)=>{
4
+ const segments = pathname.split('/').filter(Boolean);
5
+ const firstSegment = segments[0]?.toLowerCase();
6
+ if (firstSegment && languages.some((language)=>language.toLowerCase() === firstSegment)) return `/${segments.slice(1).join('/')}`;
7
+ return pathname || '/';
8
+ };
9
+ const localiseTargetPathname = (pathname, language, languages, localisedUrls)=>{
10
+ const pathWithoutLanguage = stripLanguagePrefix(pathname, languages);
11
+ const localisedUrlsConfig = resolveLocalisedUrlsConfig(localisedUrls);
12
+ const resolvedPath = localisedUrlsConfig.enabled ? resolveLocalisedPath(pathWithoutLanguage, language, languages, localisedUrlsConfig.map) : pathWithoutLanguage;
13
+ const resolvedSegments = resolvedPath.split('/').filter(Boolean);
14
+ return `/${[
15
+ language,
16
+ ...resolvedSegments
17
+ ].join('/')}`;
18
+ };
19
+ const canonicalTargetPathname = (pathname, languages, localisedUrls)=>{
20
+ const pathWithoutLanguage = stripLanguagePrefix(pathname, languages);
21
+ const localisedUrlsConfig = resolveLocalisedUrlsConfig(localisedUrls);
22
+ return localisedUrlsConfig.enabled ? resolveCanonicalLocalisedPath(pathWithoutLanguage, languages, localisedUrlsConfig.map) : pathWithoutLanguage;
23
+ };
24
+ export { canonicalTargetPathname, localiseTargetPathname, stripLanguagePrefix };
@@ -0,0 +1,152 @@
1
+ import { normalisePathPattern, normalisePathname } from "./normalise.mjs";
2
+ const escapeRegExp = (value)=>value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3
+ const getParamName = (segment)=>segment.slice(1).replace(/\?$/, '');
4
+ const getOrderedPathParamSignature = (pattern)=>normalisePathPattern(pattern).split('/').filter(Boolean).flatMap((segment)=>{
5
+ if ('*' === segment) return [
6
+ '*'
7
+ ];
8
+ if (!segment.startsWith(':')) return [];
9
+ return [
10
+ `:${getParamName(segment)}${segment.endsWith('?') ? '?' : ''}`
11
+ ];
12
+ });
13
+ const getPathParamSignature = (pattern)=>getOrderedPathParamSignature(pattern).sort((left, right)=>left < right ? -1 : left > right ? 1 : 0);
14
+ const getPathPatternValidationIssue = (pattern)=>{
15
+ const segments = normalisePathPattern(pattern).split('/').filter(Boolean);
16
+ const seenParams = new Set();
17
+ for (const [index, segment] of segments.entries()){
18
+ if ('*' === segment) {
19
+ if (index !== segments.length - 1) return 'splat parameter "*" must be the final segment';
20
+ if (seenParams.has('*')) return 'duplicate splat parameter "*"';
21
+ seenParams.add('*');
22
+ continue;
23
+ }
24
+ if (!segment.startsWith(':')) continue;
25
+ const paramName = getParamName(segment);
26
+ if (seenParams.has(paramName)) return `duplicate path parameter ":${paramName}"`;
27
+ seenParams.add(paramName);
28
+ }
29
+ };
30
+ const getPhysicalPathPattern = (pattern)=>{
31
+ const segments = normalisePathPattern(pattern).split('/').filter(Boolean);
32
+ const physicalSegments = segments.map((segment)=>{
33
+ if ('*' === segment) return '*';
34
+ if (segment.startsWith(':')) return segment.endsWith('?') ? ':param?' : ':param';
35
+ return segment;
36
+ });
37
+ return `/${physicalSegments.join('/')}`;
38
+ };
39
+ const compiledPathPatternCache = new Map();
40
+ const compilePathPattern = (pattern)=>{
41
+ const normalizedPattern = normalisePathPattern(pattern);
42
+ const cached = compiledPathPatternCache.get(normalizedPattern);
43
+ if (cached) return cached;
44
+ const names = [];
45
+ const segments = normalizedPattern.split('/').filter(Boolean);
46
+ const source = segments.map((segment)=>{
47
+ if (segment.startsWith(':')) {
48
+ names.push(getParamName(segment));
49
+ const paramPattern = '([^/]+)';
50
+ return segment.endsWith('?') ? `(?:/${paramPattern})?` : `/${paramPattern}`;
51
+ }
52
+ if ('*' === segment) {
53
+ names.push('*');
54
+ return '(?:/(.*))?';
55
+ }
56
+ return `/${escapeRegExp(segment)}`;
57
+ }).join('');
58
+ const compiled = {
59
+ names,
60
+ regexp: new RegExp(`^${source || '/'}$`)
61
+ };
62
+ compiledPathPatternCache.set(normalizedPattern, compiled);
63
+ return compiled;
64
+ };
65
+ const getPatternSpecificity = (pattern)=>{
66
+ const segments = normalisePathPattern(pattern).split('/').filter(Boolean);
67
+ let staticSegments = 0;
68
+ let dynamicSegments = 0;
69
+ let optionalSegments = 0;
70
+ let splatSegments = 0;
71
+ for (const segment of segments)if ('*' === segment) splatSegments++;
72
+ else if (segment.startsWith(':')) {
73
+ dynamicSegments++;
74
+ if (segment.endsWith('?')) optionalSegments++;
75
+ } else staticSegments++;
76
+ return {
77
+ staticSegments,
78
+ dynamicSegments,
79
+ optionalSegments,
80
+ splatSegments,
81
+ totalSegments: segments.length
82
+ };
83
+ };
84
+ const comparePatternSpecificity = (left, right)=>{
85
+ const a = getPatternSpecificity(left);
86
+ const b = getPatternSpecificity(right);
87
+ return b.staticSegments - a.staticSegments || a.splatSegments - b.splatSegments || a.optionalSegments - b.optionalSegments || b.totalSegments - a.totalSegments || a.dynamicSegments - b.dynamicSegments;
88
+ };
89
+ const haveEqualPatternSpecificity = (left, right)=>0 === comparePatternSpecificity(left, right);
90
+ const doPathPatternsOverlap = (left, right)=>{
91
+ const leftSegments = normalisePathPattern(left).split('/').filter(Boolean);
92
+ const rightSegments = normalisePathPattern(right).split('/').filter(Boolean);
93
+ if (leftSegments.length !== rightSegments.length) return false;
94
+ return leftSegments.every((leftSegment, index)=>{
95
+ const rightSegment = rightSegments[index];
96
+ const leftIsDynamic = '*' === leftSegment || leftSegment.startsWith(':');
97
+ const rightIsDynamic = '*' === rightSegment || rightSegment.startsWith(':');
98
+ return leftIsDynamic || rightIsDynamic || leftSegment === rightSegment;
99
+ });
100
+ };
101
+ const comparePatternNames = (left, right)=>{
102
+ const normalizedLeft = normalisePathPattern(left);
103
+ const normalizedRight = normalisePathPattern(right);
104
+ return normalizedLeft < normalizedRight ? -1 : normalizedLeft > normalizedRight ? 1 : 0;
105
+ };
106
+ const sortPatternsBySpecificity = (patterns)=>patterns.map((pattern, index)=>({
107
+ pattern,
108
+ index
109
+ })).sort((left, right)=>comparePatternSpecificity(left.pattern.pattern, right.pattern.pattern) || comparePatternNames(left.pattern.pattern, right.pattern.pattern) || left.index - right.index).map(({ pattern })=>pattern);
110
+ const decodePathParam = (value)=>{
111
+ try {
112
+ return decodeURIComponent(value);
113
+ } catch {
114
+ return null;
115
+ }
116
+ };
117
+ const encodeSplatParam = (value)=>value.split('/').map(encodeURIComponent).join('/');
118
+ const matchPathPattern = (pathname, pattern)=>{
119
+ const { names, regexp } = compilePathPattern(pattern);
120
+ const match = regexp.exec(normalisePathname(pathname));
121
+ if (!match) return null;
122
+ const params = {};
123
+ for(let index = 0; index < names.length; index++){
124
+ const decoded = decodePathParam(match[index + 1] || '');
125
+ if (null === decoded) return null;
126
+ Object.defineProperty(params, names[index], {
127
+ configurable: true,
128
+ enumerable: true,
129
+ value: decoded,
130
+ writable: true
131
+ });
132
+ }
133
+ return params;
134
+ };
135
+ const buildPathFromPattern = (pattern, params)=>{
136
+ const segments = normalisePathPattern(pattern).split('/').filter(Boolean);
137
+ const path = segments.map((segment)=>{
138
+ if (segment.startsWith(':')) {
139
+ const paramName = getParamName(segment);
140
+ const param = Object.hasOwn(params, paramName) ? params[paramName] : void 0;
141
+ if (void 0 === param || '' === param) {
142
+ if (segment.endsWith('?')) return '';
143
+ throw new Error(`Missing required path parameter "${paramName}" for pattern "${normalisePathPattern(pattern)}".`);
144
+ }
145
+ return encodeURIComponent(param);
146
+ }
147
+ if ('*' === segment) return encodeSplatParam(params['*'] || '');
148
+ return segment;
149
+ }).filter(Boolean).join('/');
150
+ return `/${path}`;
151
+ };
152
+ export { buildPathFromPattern, doPathPatternsOverlap, getOrderedPathParamSignature, getPathParamSignature, getPathPatternValidationIssue, getPhysicalPathPattern, haveEqualPatternSpecificity, matchPathPattern, sortPatternsBySpecificity };
@@ -0,0 +1,57 @@
1
+ import { normalisePathname } from "./normalise.mjs";
2
+ import { stripLanguagePrefix } from "./pathname.mjs";
3
+ const DEFAULT_LOCALE_REDIRECT_SKIP_RULES = [
4
+ {
5
+ type: 'exact',
6
+ path: '/backend-mf-manifest.json'
7
+ },
8
+ {
9
+ type: 'exact',
10
+ path: '/mf-manifest.json'
11
+ },
12
+ {
13
+ type: 'exact',
14
+ path: '/mf-stats.json'
15
+ },
16
+ {
17
+ type: 'pattern',
18
+ path: /^\/(?:backendRemoteEntry(?:\.[a-zA-Z0-9_-]+)?\.cjs|remoteEntry(?:\.[a-zA-Z0-9_-]+)?\.js)$/
19
+ },
20
+ {
21
+ type: 'pattern',
22
+ path: /^\/bundles\/(?:[^/]+\/)*[^/]+\.(?:js|cjs|mjs)$/
23
+ },
24
+ {
25
+ type: 'prefix',
26
+ path: '/static/'
27
+ },
28
+ {
29
+ type: 'prefix',
30
+ path: '/upload/'
31
+ }
32
+ ];
33
+ const stripTrailingSlash = (pathname)=>pathname.length > 1 ? pathname.replace(/\/+$/, '') : pathname;
34
+ const matchesPathPrefix = (pathname, prefix)=>{
35
+ const normalizedPathname = normalisePathname(pathname);
36
+ const normalizedPrefix = stripTrailingSlash(normalisePathname(prefix));
37
+ return normalizedPathname === normalizedPrefix || normalizedPathname.startsWith(`${normalizedPrefix}/`);
38
+ };
39
+ const matchesSkipRule = (pathname, rule)=>{
40
+ if ('exact' === rule.type) return normalisePathname(pathname) === normalisePathname(rule.path);
41
+ if ('pattern' === rule.type) return rule.path.test(normalisePathname(pathname));
42
+ return matchesPathPrefix(pathname, rule.path);
43
+ };
44
+ const isDefaultLocaleRedirectSkipPath = (pathname, languages = [])=>{
45
+ const normalizedPathname = normalisePathname(pathname);
46
+ const pathWithoutLanguage = stripLanguagePrefix(normalizedPathname, languages);
47
+ return DEFAULT_LOCALE_REDIRECT_SKIP_RULES.some((rule)=>matchesSkipRule(pathWithoutLanguage, rule));
48
+ };
49
+ const shouldSkipLocaleRedirect = (pathname, languages = [], ignoreRedirectRoutes)=>{
50
+ const normalizedPathname = normalisePathname(pathname);
51
+ const pathWithoutLanguage = stripLanguagePrefix(normalizedPathname, languages);
52
+ if (isDefaultLocaleRedirectSkipPath(pathWithoutLanguage)) return true;
53
+ if (!ignoreRedirectRoutes) return false;
54
+ if ('function' == typeof ignoreRedirectRoutes) return ignoreRedirectRoutes(pathWithoutLanguage);
55
+ return ignoreRedirectRoutes.some((pattern)=>matchesPathPrefix(pathWithoutLanguage, pattern));
56
+ };
57
+ export { DEFAULT_LOCALE_REDIRECT_SKIP_RULES, isDefaultLocaleRedirectSkipPath, matchesPathPrefix, shouldSkipLocaleRedirect };