@bleedingdev/modern-js-runtime-extensions 3.9.0-ultramodern.2 → 3.9.0-ultramodern.20

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 (251) hide show
  1. package/dist/cjs/buildIdentity.js +73 -0
  2. package/dist/cjs/contextExtensions.js +74 -0
  3. package/dist/cjs/headRuntime.js +91 -0
  4. package/dist/cjs/helmetContext.js +54 -0
  5. package/dist/cjs/index.js +18 -4
  6. package/dist/cjs/localisedLoaderIdentity.js +51 -0
  7. package/dist/cjs/localisedUrls/config.js +49 -0
  8. package/dist/cjs/localisedUrls/index.js +95 -0
  9. package/dist/cjs/localisedUrls/normalise.js +87 -0
  10. package/dist/cjs/localisedUrls/pathname.js +68 -0
  11. package/dist/cjs/localisedUrls/patterns.js +214 -0
  12. package/dist/cjs/localisedUrls/redirect.js +100 -0
  13. package/dist/cjs/localisedUrls/resolve.js +78 -0
  14. package/dist/cjs/localisedUrls/routeIdentity.js +92 -0
  15. package/dist/cjs/localisedUrls/routes.js +217 -0
  16. package/dist/cjs/localisedUrls/types.js +18 -0
  17. package/dist/cjs/prefetchPolicy.js +52 -0
  18. package/dist/cjs/rendererHead.js +18 -5
  19. package/dist/cjs/request-policy/browser.js +139 -0
  20. package/dist/cjs/request-policy/client.js +234 -0
  21. package/dist/cjs/request-policy/node.js +149 -0
  22. package/dist/cjs/request-policy/policyCore.js +266 -0
  23. package/dist/cjs/request-policy/requestContext.js +137 -0
  24. package/dist/cjs/request-policy/traceparent.js +56 -0
  25. package/dist/cjs/request-policy/transport.js +234 -0
  26. package/dist/cjs/request-policy/types.js +57 -0
  27. package/dist/cjs/routeHydration.js +127 -0
  28. package/dist/cjs/routerPrefetchPolicy.js +153 -0
  29. package/dist/cjs/routerProvider.js +105 -0
  30. package/dist/cjs/routerState.js +175 -0
  31. package/dist/cjs/routerStatePlugin.js +113 -0
  32. package/dist/cjs/routerStateTypes.js +18 -0
  33. package/dist/cjs/rsc-disabled/rscDisabledClientBrowserRuntime.js +69 -0
  34. package/dist/cjs/rsc-disabled/rscDisabledClientEdgeRuntime.js +61 -0
  35. package/dist/cjs/rsc-disabled/rscDisabledClientNodeRuntime.js +65 -0
  36. package/dist/cjs/rsc-disabled/rscDisabledRuntimeError.js +42 -0
  37. package/dist/cjs/rsc-disabled/rscDisabledServerEdgeRuntime.js +93 -0
  38. package/dist/cjs/rsc-disabled/rscDisabledServerNodeRuntime.js +101 -0
  39. package/dist/cjs/runtimeContextProjection.js +112 -0
  40. package/dist/cjs/server-config/bffRuntime.js +18 -0
  41. package/dist/cjs/server-config/index.js +18 -0
  42. package/dist/cjs/server-config/serverTelemetry.js +18 -0
  43. package/dist/cjs/shellStream.js +34 -2
  44. package/dist/cjs/workspaceEvents.js +159 -0
  45. package/dist/esm/buildIdentity.mjs +35 -0
  46. package/dist/esm/contextExtensions.mjs +33 -0
  47. package/dist/esm/headRuntime.mjs +43 -0
  48. package/dist/esm/helmetContext.mjs +13 -0
  49. package/dist/esm/index.mjs +2 -0
  50. package/dist/esm/localisedLoaderIdentity.mjs +13 -0
  51. package/dist/esm/localisedUrls/config.mjs +11 -0
  52. package/dist/esm/localisedUrls/index.mjs +8 -0
  53. package/dist/esm/localisedUrls/normalise.mjs +37 -0
  54. package/dist/esm/localisedUrls/pathname.mjs +24 -0
  55. package/dist/esm/localisedUrls/patterns.mjs +152 -0
  56. package/dist/esm/localisedUrls/redirect.mjs +53 -0
  57. package/dist/esm/localisedUrls/resolve.mjs +37 -0
  58. package/dist/esm/localisedUrls/routeIdentity.mjs +54 -0
  59. package/dist/esm/localisedUrls/routes.mjs +176 -0
  60. package/dist/esm/localisedUrls/types.mjs +0 -0
  61. package/dist/esm/prefetchPolicy.mjs +11 -0
  62. package/dist/esm/rendererHead.mjs +14 -5
  63. package/dist/esm/request-policy/browser.mjs +11 -0
  64. package/dist/esm/request-policy/client.mjs +195 -0
  65. package/dist/esm/request-policy/policyCore.mjs +171 -0
  66. package/dist/esm/request-policy/requestContext.mjs +75 -0
  67. package/dist/esm/request-policy/traceparent.mjs +18 -0
  68. package/dist/esm/request-policy/transport.mjs +196 -0
  69. package/dist/esm/request-policy/types.mjs +10 -0
  70. package/dist/esm/routeHydration.mjs +77 -0
  71. package/dist/esm/routerPrefetchPolicy.mjs +115 -0
  72. package/dist/esm/routerProvider.mjs +58 -0
  73. package/dist/esm/routerState.mjs +113 -0
  74. package/dist/esm/routerStatePlugin.mjs +75 -0
  75. package/dist/esm/routerStateTypes.mjs +0 -0
  76. package/dist/esm/rsc-disabled/rscDisabledClientBrowserRuntime.mjs +10 -0
  77. package/dist/esm/rsc-disabled/rscDisabledClientEdgeRuntime.mjs +8 -0
  78. package/dist/esm/rsc-disabled/rscDisabledClientNodeRuntime.mjs +9 -0
  79. package/dist/esm/rsc-disabled/rscDisabledRuntimeError.mjs +4 -0
  80. package/dist/esm/rsc-disabled/rscDisabledServerEdgeRuntime.mjs +16 -0
  81. package/dist/esm/rsc-disabled/rscDisabledServerNodeRuntime.mjs +18 -0
  82. package/dist/esm/runtimeContextProjection.mjs +74 -0
  83. package/dist/esm/server-config/bffRuntime.mjs +0 -0
  84. package/dist/esm/server-config/index.mjs +0 -0
  85. package/dist/esm/server-config/serverTelemetry.mjs +0 -0
  86. package/dist/esm/shellStream.mjs +34 -2
  87. package/dist/esm/workspaceEvents.mjs +66 -0
  88. package/dist/esm-node/buildIdentity.mjs +36 -0
  89. package/dist/esm-node/contextExtensions.mjs +34 -0
  90. package/dist/esm-node/headRuntime.mjs +44 -0
  91. package/dist/esm-node/helmetContext.mjs +14 -0
  92. package/dist/esm-node/index.mjs +2 -0
  93. package/dist/esm-node/localisedLoaderIdentity.mjs +14 -0
  94. package/dist/esm-node/localisedUrls/config.mjs +12 -0
  95. package/dist/esm-node/localisedUrls/index.mjs +9 -0
  96. package/dist/esm-node/localisedUrls/normalise.mjs +38 -0
  97. package/dist/esm-node/localisedUrls/pathname.mjs +25 -0
  98. package/dist/esm-node/localisedUrls/patterns.mjs +153 -0
  99. package/dist/esm-node/localisedUrls/redirect.mjs +54 -0
  100. package/dist/esm-node/localisedUrls/resolve.mjs +38 -0
  101. package/dist/esm-node/localisedUrls/routeIdentity.mjs +55 -0
  102. package/dist/esm-node/localisedUrls/routes.mjs +177 -0
  103. package/dist/esm-node/localisedUrls/types.mjs +1 -0
  104. package/dist/esm-node/prefetchPolicy.mjs +12 -0
  105. package/dist/esm-node/rendererHead.mjs +14 -5
  106. package/dist/esm-node/request-policy/browser.mjs +12 -0
  107. package/dist/esm-node/request-policy/client.mjs +196 -0
  108. package/dist/esm-node/request-policy/node.mjs +22 -0
  109. package/dist/esm-node/request-policy/policyCore.mjs +172 -0
  110. package/dist/esm-node/request-policy/requestContext.mjs +76 -0
  111. package/dist/esm-node/request-policy/traceparent.mjs +19 -0
  112. package/dist/esm-node/request-policy/transport.mjs +197 -0
  113. package/dist/esm-node/request-policy/types.mjs +11 -0
  114. package/dist/esm-node/routeHydration.mjs +78 -0
  115. package/dist/esm-node/routerPrefetchPolicy.mjs +116 -0
  116. package/dist/esm-node/routerProvider.mjs +59 -0
  117. package/dist/esm-node/routerState.mjs +114 -0
  118. package/dist/esm-node/routerStatePlugin.mjs +76 -0
  119. package/dist/esm-node/routerStateTypes.mjs +1 -0
  120. package/dist/esm-node/rsc-disabled/rscDisabledClientBrowserRuntime.mjs +11 -0
  121. package/dist/esm-node/rsc-disabled/rscDisabledClientEdgeRuntime.mjs +9 -0
  122. package/dist/esm-node/rsc-disabled/rscDisabledClientNodeRuntime.mjs +10 -0
  123. package/dist/esm-node/rsc-disabled/rscDisabledRuntimeError.mjs +5 -0
  124. package/dist/esm-node/rsc-disabled/rscDisabledServerEdgeRuntime.mjs +17 -0
  125. package/dist/esm-node/rsc-disabled/rscDisabledServerNodeRuntime.mjs +19 -0
  126. package/dist/esm-node/runtimeContextProjection.mjs +75 -0
  127. package/dist/esm-node/server-config/bffRuntime.mjs +1 -0
  128. package/dist/esm-node/server-config/index.mjs +1 -0
  129. package/dist/esm-node/server-config/serverTelemetry.mjs +1 -0
  130. package/dist/esm-node/shellStream.mjs +34 -2
  131. package/dist/esm-node/workspaceEvents.mjs +67 -0
  132. package/dist/types/buildIdentity.d.ts +37 -0
  133. package/dist/types/contextExtensions.d.ts +34 -0
  134. package/dist/types/headRuntime.d.ts +12 -0
  135. package/dist/types/helmetCompat.d.ts +1 -1
  136. package/dist/types/helmetContext.d.ts +10 -0
  137. package/dist/types/index.d.ts +2 -0
  138. package/dist/types/localisedLoaderIdentity.d.ts +10 -0
  139. package/dist/types/localisedUrls/config.d.ts +9 -0
  140. package/dist/types/localisedUrls/index.d.ts +10 -0
  141. package/dist/types/localisedUrls/normalise.d.ts +10 -0
  142. package/dist/types/localisedUrls/pathname.d.ts +4 -0
  143. package/dist/types/localisedUrls/patterns.d.ts +11 -0
  144. package/dist/types/localisedUrls/redirect.d.ts +19 -0
  145. package/dist/types/localisedUrls/resolve.d.ts +7 -0
  146. package/dist/types/localisedUrls/routeIdentity.d.ts +22 -0
  147. package/dist/types/localisedUrls/routes.d.ts +3 -0
  148. package/dist/types/localisedUrls/types.d.ts +14 -0
  149. package/dist/types/prefetchPolicy.d.ts +4 -0
  150. package/dist/types/rendererHead.d.ts +5 -3
  151. package/dist/types/request-policy/browser.d.ts +10 -0
  152. package/dist/types/request-policy/client.d.ts +14 -0
  153. package/dist/types/request-policy/node.d.ts +10 -0
  154. package/dist/types/request-policy/policyCore.d.ts +107 -0
  155. package/dist/types/request-policy/requestContext.d.ts +22 -0
  156. package/dist/types/request-policy/traceparent.d.ts +10 -0
  157. package/dist/types/request-policy/transport.d.ts +12 -0
  158. package/dist/types/request-policy/types.d.ts +144 -0
  159. package/dist/types/routeHydration.d.ts +24 -0
  160. package/dist/types/routerPrefetchPolicy.d.ts +28 -0
  161. package/dist/types/routerProvider.d.ts +55 -0
  162. package/dist/types/routerState.d.ts +17 -0
  163. package/dist/types/routerStatePlugin.d.ts +19 -0
  164. package/dist/types/routerStateTypes.d.ts +70 -0
  165. package/dist/types/rsc-disabled/rscDisabledClientBrowserRuntime.d.ts +9 -0
  166. package/dist/types/rsc-disabled/rscDisabledClientEdgeRuntime.d.ts +7 -0
  167. package/dist/types/rsc-disabled/rscDisabledClientNodeRuntime.d.ts +8 -0
  168. package/dist/types/rsc-disabled/rscDisabledRuntimeError.d.ts +1 -0
  169. package/dist/types/rsc-disabled/rscDisabledServerEdgeRuntime.d.ts +15 -0
  170. package/dist/types/rsc-disabled/rscDisabledServerNodeRuntime.d.ts +17 -0
  171. package/dist/types/runtimeContextProjection.d.ts +30 -0
  172. package/dist/types/server-config/bffRuntime.d.ts +122 -0
  173. package/dist/types/server-config/index.d.ts +2 -0
  174. package/dist/types/server-config/serverTelemetry.d.ts +322 -0
  175. package/dist/types/workspaceEvents.d.ts +62 -0
  176. package/package.json +240 -15
  177. package/rslib.config.mts +17 -2
  178. package/rstest.config.mts +33 -2
  179. package/src/buildIdentity.ts +61 -0
  180. package/src/contextExtensions.ts +81 -0
  181. package/src/headRuntime.tsx +77 -0
  182. package/src/helmetCompat.ts +1 -1
  183. package/src/helmetContext.ts +31 -0
  184. package/src/index.ts +2 -0
  185. package/src/localisedLoaderIdentity.ts +30 -0
  186. package/src/localisedUrls/config.ts +18 -0
  187. package/src/localisedUrls/index.ts +25 -0
  188. package/src/localisedUrls/normalise.ts +62 -0
  189. package/src/localisedUrls/pathname.ts +60 -0
  190. package/src/localisedUrls/patterns.ts +283 -0
  191. package/src/localisedUrls/redirect.ts +107 -0
  192. package/src/localisedUrls/resolve.ts +106 -0
  193. package/src/localisedUrls/routeIdentity.ts +83 -0
  194. package/src/localisedUrls/routes.ts +451 -0
  195. package/src/localisedUrls/types.ts +18 -0
  196. package/src/prefetchPolicy.ts +33 -0
  197. package/src/rendererHead.ts +25 -8
  198. package/src/request-policy/browser.ts +22 -0
  199. package/src/request-policy/client.ts +404 -0
  200. package/src/request-policy/node.ts +41 -0
  201. package/src/request-policy/policyCore.ts +424 -0
  202. package/src/request-policy/requestContext.ts +149 -0
  203. package/src/request-policy/traceparent.ts +43 -0
  204. package/src/request-policy/transport.ts +349 -0
  205. package/src/request-policy/types.ts +229 -0
  206. package/src/routeHydration.ts +208 -0
  207. package/src/routerPrefetchPolicy.ts +195 -0
  208. package/src/routerProvider.ts +160 -0
  209. package/src/routerState.ts +220 -0
  210. package/src/routerStatePlugin.ts +125 -0
  211. package/src/routerStateTypes.ts +76 -0
  212. package/src/rsc-disabled/rscDisabledClientBrowserRuntime.ts +10 -0
  213. package/src/rsc-disabled/rscDisabledClientEdgeRuntime.ts +8 -0
  214. package/src/rsc-disabled/rscDisabledClientNodeRuntime.ts +9 -0
  215. package/src/rsc-disabled/rscDisabledRuntimeError.ts +3 -0
  216. package/src/rsc-disabled/rscDisabledServerEdgeRuntime.ts +16 -0
  217. package/src/rsc-disabled/rscDisabledServerNodeRuntime.ts +18 -0
  218. package/src/runtimeContextProjection.ts +105 -0
  219. package/src/server-config/bffRuntime.ts +136 -0
  220. package/src/server-config/index.ts +2 -0
  221. package/src/server-config/serverTelemetry.ts +337 -0
  222. package/src/shellStream.ts +55 -25
  223. package/src/workspaceEvents.ts +324 -0
  224. package/tests/buildIdentity.test.ts +51 -0
  225. package/tests/contextExtensions.test.ts +27 -0
  226. package/tests/headRuntime.test.tsx +229 -0
  227. package/tests/localisedUrls.test.ts +560 -0
  228. package/tests/rendererHead.test.ts +52 -121
  229. package/tests/request-policy/browser-policy.test.ts +108 -0
  230. package/tests/request-policy/client-isolation.test.ts +109 -0
  231. package/tests/request-policy/node-policy.test.ts +447 -0
  232. package/tests/request-policy/policyCore.test.ts +129 -0
  233. package/tests/request-policy/requestContext.test.ts +66 -0
  234. package/tests/request-policy/requestFactory.outbound-contract.test.ts +290 -0
  235. package/tests/request-policy/traceparent.test.ts +52 -0
  236. package/tests/request-policy/transport-retry.test.ts +367 -0
  237. package/tests/routeHydration.test.ts +180 -0
  238. package/tests/routerPrefetchPolicy.test.ts +102 -0
  239. package/tests/routerProvider.test.ts +29 -0
  240. package/tests/routerState.test.ts +77 -0
  241. package/tests/routerStatePlugin.test.ts +63 -0
  242. package/tests/runtimeContextProjection.test.ts +83 -0
  243. package/tests/safeFailure.test.ts +10 -28
  244. package/tests/shellStream.test.ts +39 -2
  245. package/tests/workspaceEvents.test.ts +221 -0
  246. package/dist/cjs/rscHtmlStream.js +0 -128
  247. package/dist/esm/rscHtmlStream.mjs +0 -86
  248. package/dist/esm-node/rscHtmlStream.mjs +0 -87
  249. package/dist/types/rscHtmlStream.d.ts +0 -4
  250. package/src/rscHtmlStream.ts +0 -142
  251. package/tests/rscHtmlStream.test.ts +0 -153
@@ -0,0 +1,54 @@
1
+ import { normalisePathPattern } from "./normalise.mjs";
2
+ import { buildPathFromPattern, matchPathPattern } from "./patterns.mjs";
3
+ function rewritePath(url, mappings) {
4
+ for (const { from, to } of mappings){
5
+ const params = matchPathPattern(url.pathname, from);
6
+ if (params) {
7
+ url.pathname = buildPathFromPattern(to, params);
8
+ break;
9
+ }
10
+ }
11
+ return url;
12
+ }
13
+ function createLocalisedRouteRewrite(routes) {
14
+ const input = [];
15
+ const output = [];
16
+ const visit = (nodes, parent)=>{
17
+ for (const route of nodes){
18
+ const fullPath = normalisePathPattern(`${parent}/${route.path ?? ''}`);
19
+ const identity = route.modernLocalisedRoute;
20
+ if (identity?.paths && fullPath.endsWith(identity.canonicalPath)) {
21
+ const prefix = fullPath.slice(0, -identity.canonicalPath.length);
22
+ const hasLocale = prefix.split('/').some((segment)=>/^:(?:lang|locale|language)\??$/.test(segment));
23
+ for (const [language, localisedPath] of Object.entries(identity.paths)){
24
+ const localePrefix = prefix.split('/').map((segment)=>/^:(?:lang|locale|language)\??$/.test(segment) ? language : segment).join('/');
25
+ const canonical = normalisePathPattern(`${localePrefix}/${identity.canonicalPath}`);
26
+ const localised = normalisePathPattern(`${localePrefix}/${localisedPath}`);
27
+ if (canonical !== localised) {
28
+ input.push({
29
+ from: localised,
30
+ to: canonical
31
+ });
32
+ if (hasLocale) output.push({
33
+ from: canonical,
34
+ to: localised
35
+ });
36
+ }
37
+ }
38
+ }
39
+ if (route.children) visit(route.children, fullPath);
40
+ }
41
+ };
42
+ visit(routes, '');
43
+ if (0 === input.length) return;
44
+ const specificity = (pattern)=>pattern.split('/').filter((segment)=>segment && !segment.startsWith(':') && '*' !== segment).length;
45
+ for (const mappings of [
46
+ input,
47
+ output
48
+ ])mappings.sort((a, b)=>specificity(b.from) - specificity(a.from));
49
+ return {
50
+ input: ({ url })=>rewritePath(url, input),
51
+ output: ({ url })=>rewritePath(url, output)
52
+ };
53
+ }
54
+ export { createLocalisedRouteRewrite };
@@ -0,0 +1,176 @@
1
+ import { getLeadingLocaleParam, normalisePathPattern, normaliseRoutePath, stripLeadingLocaleParam } from "./normalise.mjs";
2
+ import { doPathPatternsOverlap, getOrderedPathParamSignature, getPathParamSignature, getPathPatternValidationIssue, getPhysicalPathPattern, haveEqualPatternSpecificity } from "./patterns.mjs";
3
+ const isLocalisableRoutePath = (path)=>{
4
+ const pathWithoutLocale = stripLeadingLocaleParam(path);
5
+ if (!pathWithoutLocale || '/' === pathWithoutLocale || '*' === pathWithoutLocale) return false;
6
+ return true;
7
+ };
8
+ const joinPath = (parentPath, routePath)=>{
9
+ if (!isLocalisableRoutePath(routePath)) return parentPath;
10
+ const segment = normaliseRoutePath(stripLeadingLocaleParam(routePath) || '');
11
+ return normalisePathPattern(`${parentPath}/${segment}`);
12
+ };
13
+ const isFrameworkInternalRoutePath = (canonicalPath)=>'/_mf' === canonicalPath || canonicalPath.startsWith('/_mf/');
14
+ const legalRouteIdPart = (value)=>value.replace(/[^a-zA-Z0-9_$-]+/g, '_').replace(/^_+|_+$/g, '') || 'index';
15
+ const formatParamSignature = (signature)=>signature.length > 0 ? signature.join(', ') : '(none)';
16
+ const validateLocalisedUrlPatterns = (languages, localisedUrls)=>{
17
+ const physicalPatterns = new Map();
18
+ const claimedPatterns = [];
19
+ const claimPhysicalPattern = (sourcePattern, canonicalPath, source)=>{
20
+ const physicalPattern = getPhysicalPathPattern(sourcePattern);
21
+ const existing = physicalPatterns.get(physicalPattern);
22
+ if (existing && existing.canonicalPath !== canonicalPath) throw new Error(`localisedUrls["${existing.canonicalPath}"] ${existing.source} and localisedUrls["${canonicalPath}"] ${source} generate the same physical route pattern "${physicalPattern}". Localised route patterns must identify exactly one canonical route.`);
23
+ const overlapping = claimedPatterns.find((claimed)=>claimed.canonicalPath !== canonicalPath && haveEqualPatternSpecificity(claimed.pattern, sourcePattern) && doPathPatternsOverlap(claimed.pattern, sourcePattern));
24
+ if (overlapping) throw new Error(`localisedUrls["${overlapping.canonicalPath}"] ${overlapping.source} pattern "${overlapping.pattern}" and localisedUrls["${canonicalPath}"] ${source} pattern "${sourcePattern}" are equal-specificity overlapping route patterns. Localised route patterns must identify exactly one canonical route.`);
25
+ physicalPatterns.set(physicalPattern, {
26
+ canonicalPath,
27
+ source
28
+ });
29
+ claimedPatterns.push({
30
+ canonicalPath,
31
+ pattern: sourcePattern,
32
+ source
33
+ });
34
+ };
35
+ for (const [canonicalPath, entry] of Object.entries(localisedUrls).sort(([left], [right])=>left < right ? -1 : left > right ? 1 : 0)){
36
+ const canonicalIssue = getPathPatternValidationIssue(canonicalPath);
37
+ if (canonicalIssue) throw new Error(`localisedUrls["${canonicalPath}"] canonical pattern has ${canonicalIssue}.`);
38
+ const expectedSignature = getPathParamSignature(canonicalPath);
39
+ const expectedOrderedSignature = getOrderedPathParamSignature(canonicalPath);
40
+ claimPhysicalPattern(canonicalPath, canonicalPath, 'canonical pattern');
41
+ for (const language of languages){
42
+ const localisedPattern = entry[language];
43
+ if (!localisedPattern) continue;
44
+ const localisedIssue = getPathPatternValidationIssue(localisedPattern);
45
+ if (localisedIssue) throw new Error(`localisedUrls["${canonicalPath}"].${language} has ${localisedIssue}.`);
46
+ const actualSignature = getPathParamSignature(localisedPattern);
47
+ if (actualSignature.length !== expectedSignature.length || actualSignature.some((parameter, index)=>parameter !== expectedSignature[index])) throw new Error(`localisedUrls["${canonicalPath}"].${language} must use the same parameter signature as "${canonicalPath}": expected ${formatParamSignature(expectedSignature)}; received ${formatParamSignature(actualSignature)}.`);
48
+ const actualOrderedSignature = getOrderedPathParamSignature(localisedPattern);
49
+ if (expectedOrderedSignature.some((parameter)=>'*' === parameter || parameter.endsWith('?')) && actualOrderedSignature.some((parameter, index)=>parameter !== expectedOrderedSignature[index])) throw new Error(`localisedUrls["${canonicalPath}"].${language} must keep optional and splat parameters in canonical order: expected ${formatParamSignature(expectedOrderedSignature)}; received ${formatParamSignature(actualOrderedSignature)}.`);
50
+ claimPhysicalPattern(localisedPattern, canonicalPath, `.${language}`);
51
+ }
52
+ }
53
+ };
54
+ const ensureLocalisedUrlsForPath = (canonicalPath, languages, localisedUrls)=>{
55
+ const entry = localisedUrls[canonicalPath];
56
+ if (!entry) throw new Error(`localisedUrls is enabled, but route "${canonicalPath}" does not define localised URLs for languages: ${languages.join(', ')}. Add localisedUrls["${canonicalPath}"] or set localeDetection.localisedUrls to false.`);
57
+ const missingLanguages = languages.filter((language)=>!entry[language]);
58
+ if (missingLanguages.length > 0) throw new Error(`localisedUrls["${canonicalPath}"] is missing languages: ${missingLanguages.join(', ')}. Every configured language must have a localised URL.`);
59
+ return entry;
60
+ };
61
+ const validateLocalisedUrls = (routes, languages, localisedUrls)=>{
62
+ validateLocalisedUrlPatterns(languages, localisedUrls);
63
+ const visit = (route, parentPath)=>{
64
+ const canonicalPath = joinPath(parentPath, route.path);
65
+ if (isLocalisableRoutePath(route.path) && !isFrameworkInternalRoutePath(canonicalPath)) ensureLocalisedUrlsForPath(canonicalPath, languages, localisedUrls);
66
+ if ('children' in route && route.children) route.children.forEach((child)=>visit(child, canonicalPath));
67
+ };
68
+ routes.forEach((route)=>visit(route, ''));
69
+ };
70
+ const getLocalisedRouteIdSuffixes = (paths)=>{
71
+ const usedSuffixes = new Set();
72
+ return paths.map((path, index)=>{
73
+ if (0 === index) return;
74
+ const baseSuffix = legalRouteIdPart(path);
75
+ let suffix = baseSuffix;
76
+ let disambiguator = 2;
77
+ while(usedSuffixes.has(suffix))suffix = `${baseSuffix}_${disambiguator++}`;
78
+ usedSuffixes.add(suffix);
79
+ return suffix;
80
+ });
81
+ };
82
+ const getLocalisedRoutePaths = (canonicalPath, parentLocalisedPaths, languages, entry)=>{
83
+ const paths = languages.map((language)=>{
84
+ const fullPath = normalisePathPattern(entry[language]);
85
+ const parentPath = normalisePathPattern(parentLocalisedPaths[language] || '/');
86
+ if ('/' === parentPath) return normaliseRoutePath(fullPath) || void 0;
87
+ const parentPrefix = `${parentPath}/`;
88
+ if (!fullPath.startsWith(parentPrefix)) throw new Error(`localisedUrls["${canonicalPath}"].${language} must be nested under "${parentPath}" because its parent route is localised there.`);
89
+ return normaliseRoutePath(fullPath.slice(parentPath.length));
90
+ });
91
+ const uniquePaths = Array.from(new Set(paths.filter(Boolean)));
92
+ return uniquePaths;
93
+ };
94
+ const transformLocalisedRoute = (route, parentCanonicalPath, parentLocalisedPaths, languages, localisedUrls, projection)=>{
95
+ const isSplat = '*' === stripLeadingLocaleParam(route.path);
96
+ const canonicalPath = isSplat ? normalisePathPattern(`${parentCanonicalPath}/*`) : joinPath(parentCanonicalPath, route.path);
97
+ const localisedUrlEntry = isLocalisableRoutePath(route.path) && !isFrameworkInternalRoutePath(canonicalPath) ? ensureLocalisedUrlsForPath(canonicalPath, languages, localisedUrls) : void 0;
98
+ const routeLocalisedPaths = localisedUrlEntry ? languages.reduce((acc, language)=>{
99
+ acc[language] = normalisePathPattern(localisedUrlEntry[language]);
100
+ return acc;
101
+ }, {}) : isSplat ? Object.fromEntries(Object.entries(parentLocalisedPaths).map(([language, path])=>[
102
+ language,
103
+ normalisePathPattern(`${path}/*`)
104
+ ])) : parentLocalisedPaths;
105
+ const children = 'children' in route && route.children ? route.children.flatMap((child)=>transformLocalisedRoute(child, canonicalPath, routeLocalisedPaths, languages, localisedUrls, projection)) : void 0;
106
+ const baseRoute = {
107
+ ...route,
108
+ ...!isFrameworkInternalRoutePath(canonicalPath) ? {
109
+ modernLocalisedRoute: {
110
+ id: route.id,
111
+ path: route.path,
112
+ canonicalPath,
113
+ paths: localisedUrlEntry ?? (isSplat ? routeLocalisedPaths : void 0)
114
+ }
115
+ } : {},
116
+ ...children ? {
117
+ children
118
+ } : {}
119
+ };
120
+ if (!localisedUrlEntry) return [
121
+ baseRoute
122
+ ];
123
+ const localisedPaths = getLocalisedRoutePaths(canonicalPath, parentLocalisedPaths, languages, localisedUrlEntry);
124
+ if ('canonical' === projection) return [
125
+ baseRoute
126
+ ];
127
+ const leadingLocaleParam = getLeadingLocaleParam(route.path);
128
+ const routeIdPaths = leadingLocaleParam ? localisedPaths.map((path)=>normaliseRoutePath(`${leadingLocaleParam}/${path}`)) : localisedPaths;
129
+ const routeIdSuffixes = getLocalisedRouteIdSuffixes(routeIdPaths);
130
+ return localisedPaths.map((localisedPath, index)=>cloneRouteWithLocalisedPath(baseRoute, localisedPath, routeIdSuffixes[index], canonicalPath));
131
+ };
132
+ const suffixRouteIds = (route, suffix)=>{
133
+ const children = 'children' in route && route.children ? route.children.map((child)=>suffixRouteIds(child, suffix)) : void 0;
134
+ return {
135
+ ...route,
136
+ ...route.id ? {
137
+ id: `${route.id}__localised_${suffix}`
138
+ } : {},
139
+ ...children ? {
140
+ children
141
+ } : {}
142
+ };
143
+ };
144
+ const collectRouteIdCounts = (routes, counts = new Map())=>{
145
+ for (const route of routes){
146
+ if (route.id) counts.set(route.id, (counts.get(route.id) ?? 0) + 1);
147
+ if ('children' in route && route.children) collectRouteIdCounts(route.children, counts);
148
+ }
149
+ return counts;
150
+ };
151
+ const validateNoNewRouteIdCollisions = (sourceRoutes, localisedRoutes)=>{
152
+ const sourceCounts = collectRouteIdCounts(sourceRoutes);
153
+ const localisedCounts = collectRouteIdCounts(localisedRoutes);
154
+ for (const [routeId, count] of localisedCounts)if (count > 1 && count > (sourceCounts.get(routeId) ?? 0)) throw new Error(`Localised route expansion generated duplicate route ID "${routeId}". Change the source route ID or localised path so every generated route remains identifiable.`);
155
+ };
156
+ const cloneRouteWithLocalisedPath = (route, path, routeIdSuffix, canonicalPath)=>{
157
+ const leadingLocaleParam = getLeadingLocaleParam(route.path);
158
+ const localisedPath = leadingLocaleParam ? normaliseRoutePath(`${leadingLocaleParam}/${path}`) : path;
159
+ const routeWithPath = {
160
+ ...route,
161
+ path: localisedPath
162
+ };
163
+ routeWithPath.modernCanonicalPath = canonicalPath;
164
+ return routeIdSuffix ? suffixRouteIds(routeWithPath, routeIdSuffix) : routeWithPath;
165
+ };
166
+ const applyLocalisedUrlsToRoutes = (routes, languages, localisedUrls, projection = 'physical')=>{
167
+ const rootLocalisedPaths = languages.reduce((acc, language)=>{
168
+ acc[language] = '/';
169
+ return acc;
170
+ }, {});
171
+ validateLocalisedUrls(routes, languages, localisedUrls);
172
+ const localisedRoutes = routes.flatMap((route)=>transformLocalisedRoute(route, '', rootLocalisedPaths, languages, localisedUrls, projection));
173
+ validateNoNewRouteIdCollisions(routes, localisedRoutes);
174
+ return localisedRoutes;
175
+ };
176
+ export { applyLocalisedUrlsToRoutes, validateLocalisedUrls };
File without changes
@@ -0,0 +1,11 @@
1
+ function resolvePreloadFromPrefetch(prefetch, preload) {
2
+ if (void 0 !== preload) return preload;
3
+ if ('none' === prefetch) return false;
4
+ if ('intent' === prefetch || 'render' === prefetch || 'viewport' === prefetch) return prefetch;
5
+ return 'viewport';
6
+ }
7
+ function normalizePreloadBehavior(preload, prefetch) {
8
+ const resolved = resolvePreloadFromPrefetch(prefetch, preload);
9
+ return false === resolved ? 'none' : resolved;
10
+ }
11
+ export { normalizePreloadBehavior, resolvePreloadFromPrefetch };
@@ -4,6 +4,7 @@ const MARKER_PREFIX = `<template ${MARKER_ATTRIBUTE}="`;
4
4
  const MARKER_SUFFIX = '"></template>';
5
5
  const RECORD_ID_WIDTH = 12;
6
6
  const MARKER_LENGTH = MARKER_PREFIX.length + 1 + 36 + RECORD_ID_WIDTH + MARKER_SUFFIX.length;
7
+ 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'.";
7
8
  const HEAD_STATE = Symbol('modern.rendererHead');
8
9
  const getState = (context)=>{
9
10
  const headContext = context;
@@ -24,7 +25,12 @@ const createToken = (transaction)=>{
24
25
  transaction.nextRecordId += 1;
25
26
  return token;
26
27
  };
27
- const beginHeadRender = (context)=>{
28
+ const dropLateHead = (transaction)=>{
29
+ if (transaction.lateHeadReported) return;
30
+ transaction.lateHeadReported = true;
31
+ transaction.reportLateHead(LATE_HEAD_MESSAGE);
32
+ };
33
+ const beginHeadRender = (context, reportLateHead)=>{
28
34
  const state = getState(context);
29
35
  state.transaction = {
30
36
  recordsByToken: new Map(),
@@ -33,7 +39,9 @@ const beginHeadRender = (context)=>{
33
39
  nextRecordId: 0,
34
40
  nonce: globalThis.crypto.randomUUID(),
35
41
  previousRecords: state.publishedRecords,
36
- sealed: false
42
+ sealed: false,
43
+ reportLateHead,
44
+ lateHeadReported: false
37
45
  };
38
46
  state.publish?.([]);
39
47
  };
@@ -44,7 +52,6 @@ const collectHeadRecord = (context, createRecord, publish)=>{
44
52
  const hadPublisher = void 0 !== state.publish;
45
53
  state.publish = (records)=>publish(records);
46
54
  if (!hadPublisher) state.publish([]);
47
- if (transaction.sealed) return null;
48
55
  const token = createToken(transaction);
49
56
  transaction.recordsByToken.set(token, createRecord());
50
57
  return {
@@ -74,7 +81,9 @@ const consumeMarkers = (context, html)=>{
74
81
  const token = html.slice(tokenStart, end);
75
82
  if (transaction.recordsByToken.has(token)) {
76
83
  stripped += html.slice(cursor, start);
77
- if (!transaction.sealed && !transaction.committedTokens.has(token)) {
84
+ if (transaction.sealed) {
85
+ if (!transaction.committedTokens.has(token)) dropLateHead(transaction);
86
+ } else if (!transaction.committedTokens.has(token)) {
78
87
  transaction.committedTokens.add(token);
79
88
  transaction.committedRecords.push(transaction.recordsByToken.get(token));
80
89
  }
@@ -159,4 +168,4 @@ const createWebHeadMarkerStripper = (context)=>{
159
168
  }
160
169
  });
161
170
  };
162
- export { abortHeadRender, beginHeadRender, collectHeadRecord, collectHeadState, completeHeadRender, createHeadChunkProcessor, createWebHeadMarkerStripper, finishHeadRender, publishHeadRender };
171
+ export { LATE_HEAD_MESSAGE, abortHeadRender, beginHeadRender, collectHeadRecord, collectHeadState, completeHeadRender, createHeadChunkProcessor, createWebHeadMarkerStripper, finishHeadRender, publishHeadRender };
@@ -0,0 +1,11 @@
1
+ import { createClient } from "@modern-js/create-request/client";
2
+ import { createPolicyClient } from "./client.mjs";
3
+ export * from "./requestContext.mjs";
4
+ export * from "./types.mjs";
5
+ const browser_createClient = ()=>createPolicyClient(createClient(), {
6
+ target: 'browser',
7
+ resolveSourceOrigin: ()=>"u" > typeof window ? window.location.origin : void 0
8
+ });
9
+ const { configure: configure, createRequest: createRequest, createUploader: createUploader } = browser_createClient();
10
+ export { CrossOriginEnvelopePolicyError, IdentityBindingViolationError, OperationContractViolationError, ProducerClientNotInitializedError, ProducerDomainNotConfiguredError } from "./policyCore.mjs";
11
+ export { browser_createClient as createClient, configure, createRequest, createUploader };
@@ -0,0 +1,195 @@
1
+ import { IdentityBindingViolationError, ProducerDomainNotConfiguredError, TRACEPARENT_HEADER, attachOperationContextHeaders, buildEnvelopeHeaderValue, deleteHeader, firstHeaderValue, isEmptyDomain, isSecuredRequestId, parseTraceparentValue, readHeader, resolveConfiguredRequest, toOrigin, writeHeader } from "./policyCore.mjs";
2
+ import { executeWithResilience } from "./transport.mjs";
3
+ import { BFF_DEFAULT_PROTECTED_IDENTITY_HEADERS, BFF_ENVELOPE_HEADER, BFF_OPERATION_CONTEXT_DETAIL_HEADER, BFF_OPERATION_CONTEXT_HEADER } from "./types.mjs";
4
+ const createPolicyClient = (nativeClient, environment)=>{
5
+ const isServerTarget = 'server' === environment.target;
6
+ const configuredRequests = new Map();
7
+ const realResolveHeaders = new Map();
8
+ const realRequireEnvelope = new Map();
9
+ const realAllowCrossOriginEnvelope = new Map();
10
+ const realTransportResilience = new Map();
11
+ const realIdentityBinding = new Map();
12
+ const realOperationContract = new Map();
13
+ const domainMap = new Map();
14
+ const attachEnvelopeHeaderIfRequired = (headers, requestId, url, incomingHeaders)=>{
15
+ const shouldRequireEnvelope = realRequireEnvelope.get(requestId) ?? isSecuredRequestId(requestId);
16
+ if (!shouldRequireEnvelope) return;
17
+ headers[BFF_ENVELOPE_HEADER] = buildEnvelopeHeaderValue({
18
+ requestId,
19
+ target: environment.target,
20
+ sourceOrigin: environment.resolveSourceOrigin(incomingHeaders),
21
+ targetOrigin: toOrigin(url),
22
+ traceContext: parseTraceparentValue(readHeader(headers, TRACEPARENT_HEADER)),
23
+ allowCrossOriginEnvelope: realAllowCrossOriginEnvelope.get(requestId)
24
+ });
25
+ };
26
+ const attachSecuredOperationHeaders = (headers, requestId, method, path, operationContext)=>{
27
+ if (!isSecuredRequestId(requestId)) return;
28
+ attachOperationContextHeaders({
29
+ headers,
30
+ requestId,
31
+ target: environment.target,
32
+ method,
33
+ path,
34
+ operationContext,
35
+ operationContract: realOperationContract.get(requestId),
36
+ operationContextHeader: BFF_OPERATION_CONTEXT_HEADER,
37
+ operationContextDetailHeader: BFF_OPERATION_CONTEXT_DETAIL_HEADER
38
+ });
39
+ };
40
+ const applyIdentityAndForwardedHeaders = ({ headers, requestId, incomingHeaders, forwardedHeaders, allowedHeaders: targetAllowedHeaders })=>{
41
+ const identityBinding = realIdentityBinding.get(requestId);
42
+ const identityBindingEnabled = identityBinding?.enabled ?? isSecuredRequestId(requestId);
43
+ const identityBindingStrict = identityBinding?.strict ?? isSecuredRequestId(requestId);
44
+ const protectedIdentityHeaders = (identityBinding?.protectedHeaders || BFF_DEFAULT_PROTECTED_IDENTITY_HEADERS).map((header)=>header.toLowerCase());
45
+ if (identityBindingEnabled) {
46
+ const derivedIdentityHeaders = {};
47
+ if (isServerTarget) for (const header of protectedIdentityHeaders){
48
+ const incomingHeaderValue = readHeader(incomingHeaders, header);
49
+ if (void 0 !== incomingHeaderValue) writeHeader(derivedIdentityHeaders, header, incomingHeaderValue);
50
+ }
51
+ const customDerivedHeaders = identityBinding?.deriveHeaders?.({
52
+ requestId,
53
+ target: environment.target,
54
+ incomingHeaders: isServerTarget ? {
55
+ ...incomingHeaders
56
+ } : {},
57
+ protectedHeaders: [
58
+ ...protectedIdentityHeaders
59
+ ]
60
+ });
61
+ if (customDerivedHeaders && 'object' == typeof customDerivedHeaders) for (const header of protectedIdentityHeaders){
62
+ const customValue = readHeader(customDerivedHeaders, header);
63
+ if (void 0 !== customValue) writeHeader(derivedIdentityHeaders, header, customValue);
64
+ }
65
+ for (const header of protectedIdentityHeaders){
66
+ const attemptedValue = readHeader(headers, header);
67
+ if (void 0 === attemptedValue) continue;
68
+ const violation = {
69
+ requestId,
70
+ target: environment.target,
71
+ header,
72
+ attemptedValue,
73
+ derivedValue: readHeader(derivedIdentityHeaders, header),
74
+ reason: 'client_override_blocked'
75
+ };
76
+ identityBinding?.onViolation?.(violation);
77
+ if (identityBindingStrict) throw new IdentityBindingViolationError(violation);
78
+ deleteHeader(headers, header);
79
+ }
80
+ Object.keys(derivedIdentityHeaders).forEach((header)=>{
81
+ isServerTarget ? writeHeader(forwardedHeaders, header, derivedIdentityHeaders[header]) : writeHeader(headers, header, derivedIdentityHeaders[header]);
82
+ });
83
+ }
84
+ if (isServerTarget) {
85
+ const resolveHeaders = realResolveHeaders.get(requestId);
86
+ if (resolveHeaders) {
87
+ const resolvedHeaders = resolveHeaders({
88
+ requestId,
89
+ allowedHeaders: targetAllowedHeaders,
90
+ incomingHeaders: {
91
+ ...forwardedHeaders
92
+ }
93
+ });
94
+ if (resolvedHeaders && 'object' == typeof resolvedHeaders) for (const key of targetAllowedHeaders){
95
+ const resolvedValue = readHeader(resolvedHeaders, key);
96
+ if (void 0 !== resolvedValue) {
97
+ if (identityBindingEnabled && protectedIdentityHeaders.includes(key.toLowerCase())) {
98
+ writeHeader(forwardedHeaders, key.toLowerCase(), resolvedValue);
99
+ continue;
100
+ }
101
+ writeHeader(forwardedHeaders, key, resolvedValue);
102
+ }
103
+ }
104
+ }
105
+ }
106
+ return headers;
107
+ };
108
+ const configure = (options)=>{
109
+ const { request, interceptor, allowedHeaders, resolveHeaders, transport, requireEnvelope, allowCrossOriginEnvelope, identityBinding, operationContract, setDomain, requestId = 'default' } = options;
110
+ const hasExistingDomain = domainMap.has(requestId);
111
+ if ('default' !== requestId && !setDomain && !hasExistingDomain) throw new ProducerDomainNotConfiguredError(requestId);
112
+ let resolvedDomain;
113
+ nativeClient.configure({
114
+ request,
115
+ interceptor,
116
+ allowedHeaders,
117
+ requestId,
118
+ setDomain: setDomain ? (options)=>{
119
+ resolvedDomain = setDomain(options);
120
+ if ('default' !== requestId && isEmptyDomain(resolvedDomain)) throw new ProducerDomainNotConfiguredError(requestId);
121
+ return resolvedDomain;
122
+ } : void 0
123
+ });
124
+ realResolveHeaders.delete(requestId);
125
+ realTransportResilience.delete(requestId);
126
+ realIdentityBinding.delete(requestId);
127
+ realOperationContract.delete(requestId);
128
+ realRequireEnvelope.delete(requestId);
129
+ realAllowCrossOriginEnvelope.delete(requestId);
130
+ if (isServerTarget && 'function' == typeof resolveHeaders) realResolveHeaders.set(requestId, resolveHeaders);
131
+ if (transport && 'object' == typeof transport) realTransportResilience.set(requestId, transport);
132
+ if (identityBinding && 'object' == typeof identityBinding) realIdentityBinding.set(requestId, identityBinding);
133
+ if (operationContract && 'object' == typeof operationContract) realOperationContract.set(requestId, operationContract);
134
+ if ('boolean' == typeof requireEnvelope) realRequireEnvelope.set(requestId, requireEnvelope);
135
+ if ('boolean' == typeof allowCrossOriginEnvelope || 'function' == typeof allowCrossOriginEnvelope) realAllowCrossOriginEnvelope.set(requestId, allowCrossOriginEnvelope);
136
+ if ('string' == typeof resolvedDomain) domainMap.set(requestId, resolvedDomain);
137
+ configuredRequests.set(requestId, true);
138
+ };
139
+ const createHooks = (path, method, requestId, operationContext, upload = false)=>({
140
+ onStart: ({ configuredDomain })=>{
141
+ resolveConfiguredRequest(configuredRequests, requestId, false);
142
+ if (!upload && 'default' !== requestId && isEmptyDomain(configuredDomain)) throw new ProducerDomainNotConfiguredError(requestId);
143
+ },
144
+ prepareHeaders: applyIdentityAndForwardedHeaders,
145
+ dispatch: (context)=>{
146
+ const { incomingHeaders, url, init: { headers } } = context;
147
+ if (isServerTarget && !upload) {
148
+ if (void 0 === readHeader(headers, TRACEPARENT_HEADER)) {
149
+ const incomingTraceparent = firstHeaderValue(readHeader(incomingHeaders, TRACEPARENT_HEADER));
150
+ if ('string' == typeof incomingTraceparent) writeHeader(headers, TRACEPARENT_HEADER, incomingTraceparent);
151
+ }
152
+ if (void 0 === readHeader(headers, TRACEPARENT_HEADER) && operationContext?.traceparent) writeHeader(headers, TRACEPARENT_HEADER, operationContext.traceparent);
153
+ }
154
+ attachEnvelopeHeaderIfRequired(headers, requestId, url, incomingHeaders);
155
+ attachSecuredOperationHeaders(headers, requestId, method, path, operationContext);
156
+ return executeWithResilience({
157
+ requestId,
158
+ target: environment.target,
159
+ method,
160
+ url,
161
+ init: context.init,
162
+ fetcher: context.fetcher,
163
+ transport: realTransportResilience.get(requestId)
164
+ });
165
+ }
166
+ });
167
+ const createRequest = (...args)=>{
168
+ const options = 'object' == typeof args[0] && null !== args[0] ? args[0] : {
169
+ path: args[0],
170
+ method: args[1],
171
+ port: args[2],
172
+ httpMethodDecider: args[3],
173
+ fetch: args[4],
174
+ requestId: args[5],
175
+ operationContext: args[6]
176
+ };
177
+ const { operationContext, requestId = 'default', ...nativeOptions } = options;
178
+ return nativeClient.createRequest({
179
+ ...nativeOptions,
180
+ requestId,
181
+ hooks: createHooks(options.path, options.method, requestId, operationContext)
182
+ });
183
+ };
184
+ const createUploader = ({ operationContext, requestId = 'default', ...options })=>nativeClient.createUploader({
185
+ ...options,
186
+ requestId,
187
+ hooks: createHooks(options.path, 'POST', requestId, operationContext, true)
188
+ });
189
+ return {
190
+ configure,
191
+ createRequest,
192
+ createUploader
193
+ };
194
+ };
195
+ export { createPolicyClient };