@websolutespa/bom-next 3.0.0 → 3.0.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 (313) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/dist/_virtual/_rolldown/runtime.js +24 -0
  3. package/dist/client/client.d.ts +9 -0
  4. package/dist/client/client.d.ts.map +1 -0
  5. package/dist/client/client.js +18 -0
  6. package/dist/client/client.js.map +1 -0
  7. package/dist/client/extra.d.ts +17 -0
  8. package/dist/client/extra.d.ts.map +1 -0
  9. package/dist/client/extra.js +13 -0
  10. package/dist/client/extra.js.map +1 -0
  11. package/dist/client/label.d.ts +15 -0
  12. package/dist/client/label.d.ts.map +1 -0
  13. package/dist/client/label.js +20 -0
  14. package/dist/client/label.js.map +1 -0
  15. package/dist/client/layout.d.ts +18 -0
  16. package/dist/client/layout.d.ts.map +1 -0
  17. package/dist/client/layout.js +13 -0
  18. package/dist/client/layout.js.map +1 -0
  19. package/dist/client/local.collection.d.ts +32 -0
  20. package/dist/client/local.collection.d.ts.map +1 -0
  21. package/dist/client/local.collection.js +49 -0
  22. package/dist/client/local.collection.js.map +1 -0
  23. package/dist/client/metadata.d.ts +43 -0
  24. package/dist/client/metadata.d.ts.map +1 -0
  25. package/dist/client/metadata.js +146 -0
  26. package/dist/client/metadata.js.map +1 -0
  27. package/dist/client/page.d.ts +404 -0
  28. package/dist/client/page.d.ts.map +1 -0
  29. package/dist/client/page.js +13 -0
  30. package/dist/client/page.js.map +1 -0
  31. package/dist/client/useApi.d.ts +21 -0
  32. package/dist/client/useApi.d.ts.map +1 -0
  33. package/dist/client/useApi.js +65 -0
  34. package/dist/client/useApi.js.map +1 -0
  35. package/dist/client/useCollectionApi.d.ts +21 -0
  36. package/dist/client/useCollectionApi.d.ts.map +1 -0
  37. package/dist/client/useCollectionApi.js +65 -0
  38. package/dist/client/useCollectionApi.js.map +1 -0
  39. package/dist/client/useExtra.d.ts +9 -0
  40. package/dist/client/useExtra.d.ts.map +1 -0
  41. package/dist/client/useExtra.js +13 -0
  42. package/dist/client/useExtra.js.map +1 -0
  43. package/dist/client/useHttp.d.ts +15 -0
  44. package/dist/client/useHttp.d.ts.map +1 -0
  45. package/dist/client/useHttp.js +70 -0
  46. package/dist/client/useHttp.js.map +1 -0
  47. package/dist/client/useLabel.d.ts +9 -0
  48. package/dist/client/useLabel.d.ts.map +1 -0
  49. package/dist/client/useLabel.js +13 -0
  50. package/dist/client/useLabel.js.map +1 -0
  51. package/dist/client/useLayout.d.ts +9 -0
  52. package/dist/client/useLayout.d.ts.map +1 -0
  53. package/dist/client/useLayout.js +13 -0
  54. package/dist/client/useLayout.js.map +1 -0
  55. package/dist/client/useLink.d.ts +7 -0
  56. package/dist/client/useLink.d.ts.map +1 -0
  57. package/dist/client/useLink.js +15 -0
  58. package/dist/client/useLink.js.map +1 -0
  59. package/dist/client/useMetaData.d.ts +9 -0
  60. package/dist/client/useMetaData.d.ts.map +1 -0
  61. package/dist/client/useMetaData.js +13 -0
  62. package/dist/client/useMetaData.js.map +1 -0
  63. package/dist/client/usePage.d.ts +394 -0
  64. package/dist/client/usePage.d.ts.map +1 -0
  65. package/dist/client/usePage.js +13 -0
  66. package/dist/client/usePage.js.map +1 -0
  67. package/dist/client/useUser.d.ts +9 -0
  68. package/dist/client/useUser.d.ts.map +1 -0
  69. package/dist/client/useUser.js +13 -0
  70. package/dist/client/useUser.js.map +1 -0
  71. package/dist/client/user.d.ts +20 -0
  72. package/dist/client/user.d.ts.map +1 -0
  73. package/dist/client/user.js +33 -0
  74. package/dist/client/user.js.map +1 -0
  75. package/dist/exports/client.d.ts +20 -0
  76. package/dist/exports/client.js +19 -5734
  77. package/dist/exports/instrumentation.d.ts +2 -0
  78. package/dist/exports/instrumentation.js +1 -24
  79. package/dist/exports/proxy.d.ts +5 -0
  80. package/dist/exports/proxy.js +4 -253
  81. package/dist/exports/server.d.ts +19 -0
  82. package/dist/exports/server.js +18 -1973
  83. package/dist/index.d.ts +18 -0
  84. package/dist/index.js +10 -200
  85. package/dist/instrumentation/client.d.ts +8 -0
  86. package/dist/instrumentation/client.d.ts.map +1 -0
  87. package/dist/instrumentation/client.js +15 -0
  88. package/dist/instrumentation/client.js.map +1 -0
  89. package/dist/instrumentation/sentry/capture.requestError.js +10 -0
  90. package/dist/instrumentation/sentry/capture.requestError.js.map +1 -0
  91. package/dist/instrumentation/sentry/capture.routerTransitionStart.js +7 -0
  92. package/dist/instrumentation/sentry/capture.routerTransitionStart.js.map +1 -0
  93. package/dist/{exports/instrumentation-DBO6QH4d.d.ts → instrumentation/server.d.ts} +2 -2
  94. package/dist/instrumentation/server.d.ts.map +1 -0
  95. package/dist/instrumentation/server.js +19 -0
  96. package/dist/instrumentation/server.js.map +1 -0
  97. package/dist/{types-BatUTdbZ.d.ts → instrumentation/types.d.ts} +2 -2
  98. package/dist/instrumentation/types.d.ts.map +1 -0
  99. package/dist/lib/breadcrumb.d.ts +15 -0
  100. package/dist/lib/breadcrumb.d.ts.map +1 -0
  101. package/dist/lib/breadcrumb.js +20 -0
  102. package/dist/lib/breadcrumb.js.map +1 -0
  103. package/dist/lib/const.d.ts +9 -0
  104. package/dist/lib/const.d.ts.map +1 -0
  105. package/dist/lib/const.js +9 -0
  106. package/dist/lib/const.js.map +1 -0
  107. package/dist/lib/http.d.ts +36 -0
  108. package/dist/lib/http.d.ts.map +1 -0
  109. package/dist/{http-_2M-UFRx.js → lib/http.js} +2 -2
  110. package/dist/lib/http.js.map +1 -0
  111. package/dist/lib/label.d.ts +16 -0
  112. package/dist/lib/label.d.ts.map +1 -0
  113. package/dist/lib/label.js +33 -0
  114. package/dist/lib/label.js.map +1 -0
  115. package/dist/lib/layout.defaults.d.ts +9 -0
  116. package/dist/lib/layout.defaults.d.ts.map +1 -0
  117. package/dist/lib/layout.defaults.js +161 -0
  118. package/dist/lib/layout.defaults.js.map +1 -0
  119. package/dist/lib/link.d.ts +9 -0
  120. package/dist/lib/link.d.ts.map +1 -0
  121. package/dist/lib/link.js +16 -0
  122. package/dist/lib/link.js.map +1 -0
  123. package/dist/lib/meta-data.d.ts +56 -0
  124. package/dist/lib/meta-data.d.ts.map +1 -0
  125. package/dist/lib/open-graph.d.ts +143 -0
  126. package/dist/lib/open-graph.d.ts.map +1 -0
  127. package/dist/lib/pagination.d.ts +27 -0
  128. package/dist/lib/pagination.d.ts.map +1 -0
  129. package/dist/lib/pagination.js +39 -0
  130. package/dist/lib/pagination.js.map +1 -0
  131. package/dist/lib/route.d.ts +17 -0
  132. package/dist/lib/route.d.ts.map +1 -0
  133. package/dist/{route-DzFwERQP.js → lib/route.js} +2 -2
  134. package/dist/lib/route.js.map +1 -0
  135. package/dist/lib/store.d.ts +27 -0
  136. package/dist/lib/store.d.ts.map +1 -0
  137. package/dist/{store-CJzqrHsl.js → lib/store.js} +2 -25
  138. package/dist/lib/store.js.map +1 -0
  139. package/dist/lib/structured-data.d.ts +9 -0
  140. package/dist/lib/structured-data.d.ts.map +1 -0
  141. package/dist/lib/twitter-card.d.ts +43 -0
  142. package/dist/lib/twitter-card.d.ts.map +1 -0
  143. package/dist/lib/utils.d.ts +13 -0
  144. package/dist/lib/utils.d.ts.map +1 -0
  145. package/dist/lib/utils.js +35 -0
  146. package/dist/lib/utils.js.map +1 -0
  147. package/dist/mock.d.ts +127 -0
  148. package/dist/mock.d.ts.map +1 -0
  149. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js +75 -0
  150. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js.map +1 -0
  151. package/dist/node_modules/deepmerge/dist/cjs.js +86 -0
  152. package/dist/node_modules/deepmerge/dist/cjs.js.map +1 -0
  153. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js +105 -0
  154. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js.map +1 -0
  155. package/dist/node_modules/dom-serializer/lib/esm/index.js +146 -0
  156. package/dist/node_modules/dom-serializer/lib/esm/index.js.map +1 -0
  157. package/dist/node_modules/domelementtype/lib/esm/index.js +53 -0
  158. package/dist/node_modules/domelementtype/lib/esm/index.js.map +1 -0
  159. package/dist/node_modules/domhandler/lib/esm/index.js +130 -0
  160. package/dist/node_modules/domhandler/lib/esm/index.js.map +1 -0
  161. package/dist/node_modules/domhandler/lib/esm/node.js +307 -0
  162. package/dist/node_modules/domhandler/lib/esm/node.js.map +1 -0
  163. package/dist/node_modules/entities/lib/esm/decode.js +363 -0
  164. package/dist/node_modules/entities/lib/esm/decode.js.map +1 -0
  165. package/dist/node_modules/entities/lib/esm/decode_codepoint.js +59 -0
  166. package/dist/node_modules/entities/lib/esm/decode_codepoint.js.map +1 -0
  167. package/dist/node_modules/entities/lib/esm/escape.js +85 -0
  168. package/dist/node_modules/entities/lib/esm/escape.js.map +1 -0
  169. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js +6 -0
  170. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js.map +1 -0
  171. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js +6 -0
  172. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js.map +1 -0
  173. package/dist/node_modules/html-to-text/lib/html-to-text.js +1816 -0
  174. package/dist/node_modules/html-to-text/lib/html-to-text.js.map +1 -0
  175. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js +435 -0
  176. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js.map +1 -0
  177. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js +736 -0
  178. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js.map +1 -0
  179. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js +19 -0
  180. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js.map +1 -0
  181. package/dist/node_modules/leac/lib/leac.js +101 -0
  182. package/dist/node_modules/leac/lib/leac.js.map +1 -0
  183. package/dist/node_modules/parseley/lib/parseley.js +310 -0
  184. package/dist/node_modules/parseley/lib/parseley.js.map +1 -0
  185. package/dist/node_modules/peberminta/lib/core.js +149 -0
  186. package/dist/node_modules/peberminta/lib/core.js.map +1 -0
  187. package/dist/node_modules/selderee/lib/selderee.js +319 -0
  188. package/dist/node_modules/selderee/lib/selderee.js.map +1 -0
  189. package/dist/proxy/protected-route.d.ts +9 -0
  190. package/dist/proxy/protected-route.d.ts.map +1 -0
  191. package/dist/proxy/protected-route.js +40 -0
  192. package/dist/proxy/protected-route.js.map +1 -0
  193. package/dist/proxy/proxy.d.ts +31 -0
  194. package/dist/proxy/proxy.d.ts.map +1 -0
  195. package/dist/proxy/proxy.js +49 -0
  196. package/dist/proxy/proxy.js.map +1 -0
  197. package/dist/proxy/route-auto-detection.d.ts +12 -0
  198. package/dist/proxy/route-auto-detection.d.ts.map +1 -0
  199. package/dist/proxy/route-auto-detection.js +82 -0
  200. package/dist/proxy/route-auto-detection.js.map +1 -0
  201. package/dist/proxy/route-proxy.d.ts +36 -0
  202. package/dist/proxy/route-proxy.d.ts.map +1 -0
  203. package/dist/proxy/route-proxy.js +103 -0
  204. package/dist/proxy/route-proxy.js.map +1 -0
  205. package/dist/server/context.d.ts +30 -0
  206. package/dist/server/context.d.ts.map +1 -0
  207. package/dist/server/context.js +106 -0
  208. package/dist/server/context.js.map +1 -0
  209. package/dist/server/handlers/auth.handler.d.ts +10 -0
  210. package/dist/server/handlers/auth.handler.d.ts.map +1 -0
  211. package/dist/server/handlers/auth.handler.js +29 -0
  212. package/dist/server/handlers/auth.handler.js.map +1 -0
  213. package/dist/server/handlers/captions.handler.d.ts +10 -0
  214. package/dist/server/handlers/captions.handler.d.ts.map +1 -0
  215. package/dist/server/handlers/captions.handler.js +33 -0
  216. package/dist/server/handlers/captions.handler.js.map +1 -0
  217. package/dist/server/handlers/collection.handler.d.ts +36 -0
  218. package/dist/server/handlers/collection.handler.d.ts.map +1 -0
  219. package/dist/server/handlers/collection.handler.js +166 -0
  220. package/dist/server/handlers/collection.handler.js.map +1 -0
  221. package/dist/server/handlers/error-response.js +24 -0
  222. package/dist/server/handlers/error-response.js.map +1 -0
  223. package/dist/server/handlers/index.handler.d.ts +9 -0
  224. package/dist/server/handlers/index.handler.d.ts.map +1 -0
  225. package/dist/server/handlers/index.handler.js +145 -0
  226. package/dist/server/handlers/index.handler.js.map +1 -0
  227. package/dist/server/handlers/preview.handler.d.ts +9 -0
  228. package/dist/server/handlers/preview.handler.d.ts.map +1 -0
  229. package/dist/server/handlers/preview.handler.js +15 -0
  230. package/dist/server/handlers/preview.handler.js.map +1 -0
  231. package/dist/server/handlers/registry.handler.d.ts +16 -0
  232. package/dist/server/handlers/registry.handler.d.ts.map +1 -0
  233. package/dist/server/handlers/registry.handler.js +260 -0
  234. package/dist/server/handlers/registry.handler.js.map +1 -0
  235. package/dist/server/handlers/route.handler.d.ts +20 -0
  236. package/dist/server/handlers/route.handler.d.ts.map +1 -0
  237. package/dist/server/handlers/route.handler.js +122 -0
  238. package/dist/server/handlers/route.handler.js.map +1 -0
  239. package/dist/server/handlers/sitemap.handler.d.ts +30 -0
  240. package/dist/server/handlers/sitemap.handler.d.ts.map +1 -0
  241. package/dist/server/handlers/sitemap.handler.js +338 -0
  242. package/dist/server/handlers/sitemap.handler.js.map +1 -0
  243. package/dist/server/handlers/static-params.handler.d.ts +24 -0
  244. package/dist/server/handlers/static-params.handler.d.ts.map +1 -0
  245. package/dist/server/handlers/static-params.handler.js +56 -0
  246. package/dist/server/handlers/static-params.handler.js.map +1 -0
  247. package/dist/server/handlers/vars.handler.d.ts +10 -0
  248. package/dist/server/handlers/vars.handler.d.ts.map +1 -0
  249. package/dist/server/handlers/vars.handler.js +159 -0
  250. package/dist/server/handlers/vars.handler.js.map +1 -0
  251. package/dist/server/layout.js +88 -0
  252. package/dist/server/layout.js.map +1 -0
  253. package/dist/server/lazy.d.ts +11 -0
  254. package/dist/server/lazy.d.ts.map +1 -0
  255. package/dist/server/lazy.js +33 -0
  256. package/dist/server/lazy.js.map +1 -0
  257. package/dist/server/local-api.d.ts +9 -0
  258. package/dist/server/local-api.d.ts.map +1 -0
  259. package/dist/server/local-api.js +60 -0
  260. package/dist/server/local-api.js.map +1 -0
  261. package/dist/server/metadata.d.ts +21 -0
  262. package/dist/server/metadata.d.ts.map +1 -0
  263. package/dist/server/metadata.js +20 -0
  264. package/dist/server/metadata.js.map +1 -0
  265. package/dist/server/mixer-payload.d.ts +63 -0
  266. package/dist/server/mixer-payload.d.ts.map +1 -0
  267. package/dist/server/mixer.d.ts +214 -0
  268. package/dist/server/mixer.d.ts.map +1 -0
  269. package/dist/server/mixer.js +355 -0
  270. package/dist/server/mixer.js.map +1 -0
  271. package/dist/server/page.d.ts +22 -0
  272. package/dist/server/page.d.ts.map +1 -0
  273. package/dist/server/page.js +57 -0
  274. package/dist/server/page.js.map +1 -0
  275. package/dist/server/utils.d.ts +12 -0
  276. package/dist/server/utils.d.ts.map +1 -0
  277. package/dist/{utils-YwteTbk7.js → server/utils.js} +3 -3
  278. package/dist/server/utils.js.map +1 -0
  279. package/dist/server/utmz.d.ts +9 -0
  280. package/dist/server/utmz.d.ts.map +1 -0
  281. package/dist/server/utmz.js +14 -0
  282. package/dist/server/utmz.js.map +1 -0
  283. package/dist/types.d.ts +136 -0
  284. package/dist/types.d.ts.map +1 -0
  285. package/package.json +1 -1
  286. package/src/index.ts +0 -1
  287. package/dist/exports/client-xcFJNcG7.d.ts +0 -979
  288. package/dist/exports/client-xcFJNcG7.d.ts.map +0 -1
  289. package/dist/exports/client.js.map +0 -1
  290. package/dist/exports/instrumentation-DBO6QH4d.d.ts.map +0 -1
  291. package/dist/exports/instrumentation.js.map +0 -1
  292. package/dist/exports/proxy-Cv7QFVci.d.ts +0 -71
  293. package/dist/exports/proxy-Cv7QFVci.d.ts.map +0 -1
  294. package/dist/exports/proxy.js.map +0 -1
  295. package/dist/exports/server-BHObJHJ6.d.ts +0 -402
  296. package/dist/exports/server-BHObJHJ6.d.ts.map +0 -1
  297. package/dist/exports/server.js.map +0 -1
  298. package/dist/http-_2M-UFRx.js.map +0 -1
  299. package/dist/index-CdYcvudT.d.ts +0 -4
  300. package/dist/index-CtfAJ0y7.d.ts +0 -499
  301. package/dist/index-CtfAJ0y7.d.ts.map +0 -1
  302. package/dist/index.js.map +0 -1
  303. package/dist/route-DzFwERQP.js.map +0 -1
  304. package/dist/store-CJzqrHsl.js.map +0 -1
  305. package/dist/types-BatUTdbZ.d.ts.map +0 -1
  306. package/dist/types-D29_snYY.d.ts +0 -191
  307. package/dist/types-D29_snYY.d.ts.map +0 -1
  308. package/dist/utils-Ca7xh5mm.js +0 -78
  309. package/dist/utils-Ca7xh5mm.js.map +0 -1
  310. package/dist/utils-YwteTbk7.js.map +0 -1
  311. /package/dist/{config.client-B8As5DY0.js → instrumentation/sentry/config.client.js} +0 -0
  312. /package/dist/{config.edge-B8As5DY0.js → instrumentation/sentry/config.edge.js} +0 -0
  313. /package/dist/{config.server-B8As5DY0.js → instrumentation/sentry/config.server.js} +0 -0
@@ -0,0 +1,49 @@
1
+ import { NextResponse } from "next/server";
2
+ //#region src/proxy/proxy.ts
3
+ /**
4
+ * Returns the externally visible origin for an internal middleware request.
5
+ *
6
+ * Deployments commonly terminate TLS or change ports before forwarding to
7
+ * Next.js. Honoring valid forwarded headers keeps resolver requests on the
8
+ * public host and prevents an avoidable proxy redirect; direct-origin fallback
9
+ * keeps local development and untrusted/invalid header values deterministic.
10
+ */
11
+ function getRequestOrigin(request) {
12
+ const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
13
+ const forwardedProtocol = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
14
+ const forwardedPort = request.headers.get("x-forwarded-port")?.split(",")[0]?.trim();
15
+ if (!forwardedHost || !["http", "https"].includes(forwardedProtocol || "")) return request.nextUrl.origin;
16
+ const protocol = forwardedProtocol;
17
+ const defaultPort = protocol === "https" ? "443" : "80";
18
+ const includesPort = forwardedHost.startsWith("[") ? forwardedHost.includes("]:") : forwardedHost.includes(":");
19
+ return `${protocol}://${forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost}`;
20
+ }
21
+ /**
22
+ * Composes middleware into an ordered, short-circuiting proxy pipeline.
23
+ *
24
+ * A disabled proxy returns immediately, avoiding all downstream request work.
25
+ * Otherwise each middleware can claim the response; stopping at its first
26
+ * result prevents duplicate rewrites, redirects, and expensive policy checks.
27
+ */
28
+ function createProxy(...proxies) {
29
+ return async function({ request, next, disabled }) {
30
+ if (disabled) return NextResponse.next();
31
+ let proxyResponse, i = 0;
32
+ while (i < proxies.length && !proxyResponse) {
33
+ const proxy = proxies[i];
34
+ if (typeof proxy === "function") {
35
+ proxyResponse = await proxy({
36
+ request,
37
+ next
38
+ });
39
+ if (proxyResponse) return proxyResponse;
40
+ }
41
+ i++;
42
+ }
43
+ return NextResponse.next();
44
+ };
45
+ }
46
+ //#endregion
47
+ export { createProxy, getRequestOrigin };
48
+
49
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","names":[],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":["import { NextMiddlewareResult } from 'next/dist/server/web/types';\r\nimport { NextFetchEvent, NextRequest, NextResponse } from 'next/server';\r\n\r\n// export type Middleware = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type MiddlewareOptions = {\r\n request: NextRequest,\r\n next: NextFetchEvent,\r\n disabled?: boolean,\r\n};\r\nexport type Middleware = (props: MiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\r\n\r\n/**\r\n * Returns the externally visible origin for an internal middleware request.\r\n *\r\n * Deployments commonly terminate TLS or change ports before forwarding to\r\n * Next.js. Honoring valid forwarded headers keeps resolver requests on the\r\n * public host and prevents an avoidable proxy redirect; direct-origin fallback\r\n * keeps local development and untrusted/invalid header values deterministic.\r\n */\r\nexport function getRequestOrigin(request: NextRequest): string {\r\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\r\n const forwardedProtocol = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\r\n const forwardedPort = request.headers.get('x-forwarded-port')?.split(',')[0]?.trim();\r\n\r\n if (!forwardedHost || !['http', 'https'].includes(forwardedProtocol || '')) {\r\n return request.nextUrl.origin;\r\n }\r\n\r\n const protocol = forwardedProtocol!;\r\n const defaultPort = protocol === 'https' ? '443' : '80';\r\n const includesPort = forwardedHost.startsWith('[') ? forwardedHost.includes(']:') : forwardedHost.includes(':');\r\n const authority = forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost;\r\n\r\n return `${protocol}://${authority}`;\r\n}\r\n\r\n/**\r\n * Composes middleware into an ordered, short-circuiting proxy pipeline.\r\n *\r\n * A disabled proxy returns immediately, avoiding all downstream request work.\r\n * Otherwise each middleware can claim the response; stopping at its first\r\n * result prevents duplicate rewrites, redirects, and expensive policy checks.\r\n */\r\nexport function createProxy(...proxies: Middleware[]): Middleware {\r\n return async function ({ request, next, disabled }: MiddlewareOptions) {\r\n if (disabled) {\r\n return NextResponse.next();\r\n }\r\n let proxyResponse, i = 0;\r\n while (i < proxies.length && !proxyResponse) {\r\n const proxy = proxies[i] as Middleware;\r\n // console.log('createProxy.proxies', proxies.length, typeof proxy === 'function');\r\n if (typeof proxy === 'function') {\r\n proxyResponse = await proxy({ request, next });\r\n if (proxyResponse) {\r\n return proxyResponse;\r\n }\r\n }\r\n i++;\r\n }\r\n return NextResponse.next();\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;AAoBA,SAAgB,iBAAiB,SAA8B;CAC7D,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,kBAAkB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK;CACnF,MAAM,oBAAoB,QAAQ,QAAQ,IAAI,mBAAmB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK;CACxF,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,kBAAkB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK;CAEnF,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,OAAO,CAAC,CAAC,SAAS,qBAAqB,EAAE,GACvE,OAAO,QAAQ,QAAQ;CAGzB,MAAM,WAAW;CACjB,MAAM,cAAc,aAAa,UAAU,QAAQ;CACnD,MAAM,eAAe,cAAc,WAAW,GAAG,IAAI,cAAc,SAAS,IAAI,IAAI,cAAc,SAAS,GAAG;CAG9G,OAAO,GAAG,SAAS,KAFD,iBAAiB,kBAAkB,eAAe,CAAC,eAAe,GAAG,cAAc,GAAG,kBAAkB;AAG5H;;;;;;;;AASA,SAAgB,YAAY,GAAG,SAAmC;CAChE,OAAO,eAAgB,EAAE,SAAS,MAAM,YAA+B;EACrE,IAAI,UACF,OAAO,aAAa,KAAK;EAE3B,IAAI,eAAe,IAAI;EACvB,OAAO,IAAI,QAAQ,UAAU,CAAC,eAAe;GAC3C,MAAM,QAAQ,QAAQ;GAEtB,IAAI,OAAO,UAAU,YAAY;IAC/B,gBAAgB,MAAM,MAAM;KAAE;KAAS;IAAK,CAAC;IAC7C,IAAI,eACF,OAAO;GAEX;GACA;EACF;EACA,OAAO,aAAa,KAAK;CAC3B;AACF"}
@@ -0,0 +1,12 @@
1
+ import { Middleware } from "./proxy.js";
2
+ import { NextRequest } from "next/server";
3
+
4
+ //#region src/proxy/route-auto-detection.d.ts
5
+ declare function detectLocale(request: NextRequest, defaultLocale?: string): Promise<string>;
6
+ declare function detectCountry(request: NextRequest, defaultMarket?: string): Promise<string | undefined>;
7
+ declare const routeAutoDetection: Middleware;
8
+ //# sourceMappingURL=route-auto-detection.d.ts.map
9
+
10
+ //#endregion
11
+ export { detectCountry, detectLocale, routeAutoDetection };
12
+ //# sourceMappingURL=route-auto-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-auto-detection.d.ts","names":[],"sources":["../../src/proxy/route-auto-detection.ts"],"mappings":";;;;iBAOsB,YAAA,UAAsB,sCAAmC;iBAMzD,aAAA,UAAuB,sCAAmC;AAN1D,cA2CT,kBA3CqB,EA2CD,UA3CC;AAAA"}
@@ -0,0 +1,82 @@
1
+ "use server";
2
+ import { localApiGet } from "../lib/http.js";
3
+ import { getRequestOrigin } from "./proxy.js";
4
+ import { asEquatable, defaultLocale, defaultMarket } from "@websolutespa/bom-core";
5
+ import { NextResponse } from "next/server";
6
+ //#region src/proxy/route-auto-detection.ts
7
+ async function detectLocale(request, defaultLocale) {
8
+ const acceptLanguage = request.headers.get("accept-language")?.split(",")[0];
9
+ return request.cookies.get("NEXT_LOCALE")?.value || acceptLanguage || defaultLocale || process.env.DEFAULT_LOCALE;
10
+ }
11
+ async function detectCountry(request, defaultMarket) {
12
+ let ip = request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip");
13
+ if (ip) ip = ip.split(",")[0];
14
+ const isValidIp = ip?.match(/^(\d+?)\.(\d+?)\.(\d+?)\.(\d+?)$/);
15
+ let detectedCountry = "";
16
+ try {
17
+ const token = process.env.IPINFO_TOKEN;
18
+ if (token) {
19
+ const url = isValidIp ? `https://api.ipinfo.io/lite/${ip}/country_code?token=${token}` : `https://api.ipinfo.io/lite/me/country_code?token=${token}`;
20
+ const response = await fetch(url);
21
+ if (response.ok) detectedCountry = (await response.text()).toLowerCase();
22
+ } else {
23
+ const url = `https://geoip.websolute.it/Ip2Location/get_info.aspx?ipaddress=${isValidIp ? ip : ""}`;
24
+ const response = await fetch(url);
25
+ if (response.ok) detectedCountry = (((await response.text()).split("<CountryCode><![CDATA[")[1] || "").split("]]></CountryCode>")[0] || "").replace("-", "").toLowerCase();
26
+ }
27
+ return detectedCountry || defaultMarket || process.env.DEFAULT_MARKET;
28
+ } catch (error) {
29
+ console.log("routeInterceptor.detectCountry.error", error);
30
+ }
31
+ return defaultMarket || process.env.DEFAULT_MARKET;
32
+ }
33
+ const routeAutoDetection = async ({ request }) => {
34
+ let redirectUrl = void 0;
35
+ const url = request.nextUrl;
36
+ const origin = getRequestOrigin(request);
37
+ if (url.pathname === "/") {
38
+ const cookie = request.cookies.get("detectedRoute");
39
+ if (cookie?.value) redirectUrl = cookie.value;
40
+ const rootRoutes = await localApiGet("/-route?where[isRoot][equals]=true", {}, void 0, origin);
41
+ if (rootRoutes.find((x) => x.id === "/")) return;
42
+ const markets = await localApiGet("/market?pagination=false", {}, void 0, origin);
43
+ const market = markets.find((x) => x.isDefault) || markets.find((x) => x.id === defaultMarket) || markets[0];
44
+ const detectedCountry = await detectCountry(request, market.id);
45
+ const detectedMarket = detectedCountry ? markets.filter((x) => Array.isArray(x.countries)).find((x) => {
46
+ return (x.countries || []).map((x) => typeof x === "string" ? x : x.id).includes(detectedCountry);
47
+ }) || markets.find((x) => !Array.isArray(x.countries)) : void 0;
48
+ let detectedMarketRoutes = rootRoutes.filter((x) => x.market === detectedMarket?.id);
49
+ if (detectedMarketRoutes.length === 0) detectedMarketRoutes = rootRoutes.filter((x) => x.market === market.id);
50
+ const defaultMarketLocale = market.defaultLanguage ? typeof market.defaultLanguage === "string" ? market.defaultLanguage : market.defaultLanguage.id : defaultLocale;
51
+ const detectedLocale = await detectLocale(request, defaultMarketLocale);
52
+ const detectedLocaleRoutes = detectedMarketRoutes.filter((x) => x.locale === detectedLocale);
53
+ const detectedRoute = detectedLocaleRoutes.length > 0 ? detectedLocaleRoutes[0] : detectedMarketRoutes.find((x) => {
54
+ const market = markets.find((m) => m.id === x.market);
55
+ const marketLocale = market.defaultLanguage ? asEquatable(market.defaultLanguage) : defaultMarketLocale;
56
+ return x.locale === marketLocale;
57
+ });
58
+ if (detectedRoute && detectedRoute.id !== url.pathname) {
59
+ console.log("routeInterceptor.routeAutoDetection", detectedLocale, detectedCountry, detectedRoute.id);
60
+ redirectUrl = detectedRoute.id;
61
+ }
62
+ }
63
+ if (redirectUrl) {
64
+ const resolvedUrl = new URL(redirectUrl, origin).href;
65
+ const search = request.nextUrl.search;
66
+ const response = NextResponse.redirect(resolvedUrl + search, { status: 307 });
67
+ response.cookies.set({
68
+ expires: new Date(Date.now() + 864e5),
69
+ httpOnly: true,
70
+ name: "detectedRoute",
71
+ path: "/",
72
+ sameSite: "lax",
73
+ secure: true,
74
+ value: redirectUrl
75
+ });
76
+ return response;
77
+ }
78
+ };
79
+ //#endregion
80
+ export { detectCountry, detectLocale, routeAutoDetection };
81
+
82
+ //# sourceMappingURL=route-auto-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-auto-detection.js","names":[],"sources":["../../src/proxy/route-auto-detection.ts"],"sourcesContent":["'use server';\r\n\r\nimport { asEquatable, defaultLocale, defaultMarket, IMarket, IRoute } from '@websolutespa/bom-core';\r\nimport { NextRequest, NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getRequestOrigin, Middleware, MiddlewareOptions } from './proxy';\r\n\r\nexport async function detectLocale(request: NextRequest, defaultLocale?: string) {\r\n const acceptLanguage = request.headers.get('accept-language')?.split(',')[0];\r\n const detectedLocale = request.cookies.get('NEXT_LOCALE')?.value || acceptLanguage || defaultLocale || process.env.DEFAULT_LOCALE;\r\n return detectedLocale as string;\r\n}\r\n\r\nexport async function detectCountry(request: NextRequest, defaultMarket?: string) {\r\n let ip = request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip');\r\n if (ip) {\r\n ip = ip.split(',')[0];\r\n }\r\n const isValidIp = ip?.match(/^(\\d+?)\\.(\\d+?)\\.(\\d+?)\\.(\\d+?)$/);\r\n let detectedCountry = '';\r\n try {\r\n const token = process.env.IPINFO_TOKEN;\r\n if (token) {\r\n const url = isValidIp ?\r\n `https://api.ipinfo.io/lite/${ip}/country_code?token=${token}` :\r\n `https://api.ipinfo.io/lite/me/country_code?token=${token}`;\r\n const response = await fetch(url);\r\n if (response.ok) {\r\n const data = await response.text();\r\n detectedCountry = data.toLowerCase();\r\n }\r\n } else {\r\n const url = `https://geoip.websolute.it/Ip2Location/get_info.aspx?ipaddress=${isValidIp ? ip : ''}`;\r\n const response = await fetch(url);\r\n if (response.ok) {\r\n const xml = await response.text();\r\n detectedCountry = (\r\n ((xml.split('<CountryCode><![CDATA[')[1] || '').split(']]></CountryCode>')[0] || '')\r\n ).replace('-', '').toLowerCase();\r\n // console.log('detectedCountry', detectedCountry);\r\n }\r\n }\r\n // console.log('routeInterceptor.detectCountry', detectedCountry);\r\n return detectedCountry || defaultMarket || process.env.DEFAULT_MARKET;\r\n } catch (error) {\r\n console.log('routeInterceptor.detectCountry.error', error);\r\n }\r\n return (defaultMarket || process.env.DEFAULT_MARKET) as string;\r\n}\r\n\r\nexport const routeAutoDetection: Middleware = async ({ request }: MiddlewareOptions) => {\r\n let redirectUrl: string | undefined = undefined;\r\n const url = request.nextUrl;\r\n const origin = getRequestOrigin(request);\r\n if (url.pathname === '/') {\r\n const cookie = request.cookies.get('detectedRoute');\r\n if (cookie?.value) {\r\n redirectUrl = cookie.value;\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection', url.pathname);\r\n const rootRoutes: IRoute[] = await localApiGet('/-route?where[isRoot][equals]=true', {}, undefined, origin);\r\n // console.log('routeInterceptor.routeAutoDetection.rootRoutes', rootRoutes);\r\n const defaultRoute = rootRoutes.find(x => x.id === '/');\r\n // console.log('routeInterceptor.routeAutoDetection.defaultRoute', defaultRoute);\r\n if (defaultRoute) {\r\n return;\r\n }\r\n const markets: IMarket[] = await localApiGet('/market?pagination=false', {}, undefined, origin);\r\n // console.log('routeInterceptor.routeAutoDetection.markets', markets);\r\n const market = markets.find(x => x.isDefault) || markets.find(x => x.id === defaultMarket) || markets[0];\r\n // console.log('routeInterceptor.routeAutoDetection.market', market);\r\n const detectedCountry = await detectCountry(request, market.id);\r\n // console.log('routeInterceptor.routeAutoDetection.detectedCountry', detectedCountry);\r\n const detectedMarket = detectedCountry ? (\r\n markets.filter(x => Array.isArray(x.countries)).find(x => {\r\n const countries: string[] = (x.countries || []).map(x => typeof x === 'string' ? x : x.id as string);\r\n return countries.includes(detectedCountry);\r\n }) ||\r\n markets.find(x => !Array.isArray(x.countries))\r\n ) : undefined;\r\n // console.log('routeInterceptor.routeAutoDetection.detectedMarket', detectedMarket);\r\n let detectedMarketRoutes = rootRoutes.filter(x => x.market === detectedMarket?.id);\r\n if (detectedMarketRoutes.length === 0) {\r\n detectedMarketRoutes = rootRoutes.filter(x => x.market === market.id);\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection.detectedMarketRoutes', detectedMarketRoutes);\r\n const defaultMarketLocale = market.defaultLanguage ? (\r\n typeof market.defaultLanguage === 'string' ? market.defaultLanguage : market.defaultLanguage.id\r\n ) as string : defaultLocale;\r\n // console.log('routeInterceptor.routeAutoDetection.defaultMarketLocale', defaultMarketLocale);\r\n const detectedLocale = await detectLocale(request, defaultMarketLocale);\r\n // console.log('routeInterceptor.routeAutoDetection.detectedLocale', detectedLocale);\r\n const detectedLocaleRoutes = detectedMarketRoutes.filter(x => x.locale === detectedLocale);\r\n const detectedRoute =\r\n detectedLocaleRoutes.length > 0 ?\r\n detectedLocaleRoutes[0]! :\r\n detectedMarketRoutes.find(x => {\r\n const market = markets.find(m => m.id === x.market)!;\r\n const marketLocale = (market.defaultLanguage ? asEquatable(market.defaultLanguage as string) : defaultMarketLocale);\r\n return x.locale === marketLocale;\r\n })!;\r\n // console.log('routeInterceptor.routeAutoDetection.detectedRoute', detectedRoute);\r\n if (detectedRoute && detectedRoute.id !== url.pathname) {\r\n console.log('routeInterceptor.routeAutoDetection', detectedLocale, detectedCountry, detectedRoute.id);\r\n redirectUrl = detectedRoute.id;\r\n }\r\n // console.log('routeInterceptor.routeAutoDetection', locale, detectedCountry, rootRoutes);\r\n }\r\n if (redirectUrl) {\r\n // console.log('routeInterceptor', 'redirectUrl', redirectUrl);\r\n const resolvedUrl = new URL(redirectUrl, origin).href;\r\n // console.log('routeInterceptor', 'resolvedUrl', resolvedUrl);\r\n const search = request.nextUrl.search;\r\n const response = NextResponse.redirect(resolvedUrl + search, { status: 307 });\r\n response.cookies.set({\r\n expires: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000),\r\n httpOnly: true,\r\n name: 'detectedRoute',\r\n path: '/',\r\n sameSite: 'lax',\r\n secure: true,\r\n value: redirectUrl,\r\n });\r\n return response;\r\n }\r\n};\r\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { Middleware } from "./proxy.js";
2
+ import { IRoute } from "@websolutespa/bom-core";
3
+ import { NextFetchEvent, NextRequest } from "next/server";
4
+ import { NextMiddlewareResult } from "next/dist/server/web/types";
5
+
6
+ //#region src/proxy/route-proxy.d.ts
7
+ type Proxy = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;
8
+ type RouteMiddlewareOptions = {
9
+ request: NextRequest;
10
+ next: NextFetchEvent;
11
+ route: IRoute;
12
+ disabled?: boolean;
13
+ };
14
+ type RouteMiddleware = (props: RouteMiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;
15
+ type RouteInterceptorProxy = (route: IRoute, request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;
16
+ type ResolvedRoute = IRoute & {
17
+ splat?: string;
18
+ };
19
+ type RouteResolverResponse = {
20
+ parent?: IRoute;
21
+ route?: ResolvedRoute;
22
+ };
23
+ /**
24
+ * Resolves a public request to a CMS route, then rewrites it to the internal
25
+ * Next.js page while preserving the original browser URL.
26
+ *
27
+ * The resolver call is deliberately made to this request's public origin so it
28
+ * works behind reverse proxies and deployment hosts. A rewrite keeps routing
29
+ * server-side, avoiding an extra browser round trip that a redirect would add.
30
+ */
31
+ declare function createRouteProxy(...middlewares: RouteMiddleware[]): Middleware;
32
+ //# sourceMappingURL=route-proxy.d.ts.map
33
+
34
+ //#endregion
35
+ export { Proxy, ResolvedRoute, RouteInterceptorProxy, RouteMiddleware, RouteMiddlewareOptions, RouteResolverResponse, createRouteProxy };
36
+ //# sourceMappingURL=route-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-proxy.d.ts","names":[],"sources":["../../src/proxy/route-proxy.ts"],"mappings":";;;;;;KAOY,KAAA,aAAkB,mBAAmB,mBAAmB,QAAQ;KAEhE,sBAAA;EAFA,OAAA,EAGD,WAHM;EAAA,IAAA,EAIT,cAJS;EAAa,KAAA,EAKrB,MALqB;EAAmB,QAAA,CAAA,EAAA,OAAA;AAA2B,CAAA;AAAR,KAQxD,eAAA,GARwD,CAAA,KAAA,EAQ9B,sBAR8B,EAAA,GAQH,oBARG,GAQoB,OARpB,CAQ4B,oBAR5B,CAAA;AAAO,KAU/D,qBAAA,GAV+D,CAAA,KAAA,EAU/B,MAV+B,EAAA,OAAA,EAUd,WAVc,EAAA,IAAA,EAUK,cAVL,EAAA,GAUwB,OAVxB,CAUgC,oBAVhC,CAAA;AAE/D,KAUA,aAAA,GAAgB,MAVM,GAAA;EAAA,KAAA,CAAA,EAAA,MAAA;AACvB,CAAA;AACH,KASI,qBAAA,GATJ;EACC,MAAA,CAAA,EASE,MATF;EAAM,KAAA,CAAA,EAUL,aAVK;AAGf,CAAA;AAA2B;AAAW;AAA2B;AAA+B;AAAR;AAAO;AAE/F;AAAiC;AAAW,iBAgB5B,gBAAA,CAhB4B,GAAA,WAAA,EAgBK,eAhBL,EAAA,CAAA,EAgByB,UAhBzB;AAAiB"}
@@ -0,0 +1,103 @@
1
+ import { localApiGet } from "../lib/http.js";
2
+ import { getHrefBeforeRedirect, getNextUrl } from "../server/utils.js";
3
+ import { getRequestOrigin } from "./proxy.js";
4
+ import { defaultLocale, defaultMarket } from "@websolutespa/bom-core";
5
+ import { NextResponse } from "next/server";
6
+ //#region src/proxy/route-proxy.ts
7
+ /**
8
+ * Resolves a public request to a CMS route, then rewrites it to the internal
9
+ * Next.js page while preserving the original browser URL.
10
+ *
11
+ * The resolver call is deliberately made to this request's public origin so it
12
+ * works behind reverse proxies and deployment hosts. A rewrite keeps routing
13
+ * server-side, avoiding an extra browser round trip that a redirect would add.
14
+ */
15
+ function createRouteProxy(...middlewares) {
16
+ return async function({ request, next }) {
17
+ const url = request.nextUrl;
18
+ const origin = getRequestOrigin(request);
19
+ const hrefBeforeRedirect = getHrefBeforeRedirect(request);
20
+ const { pathname } = url;
21
+ const headers = new Headers(request.headers);
22
+ headers.set("x-pathname", pathname);
23
+ try {
24
+ const draftMode = request.cookies.has("__prerender_bypass");
25
+ console.log("draftMode", draftMode);
26
+ if (draftMode) return;
27
+ const resolution = await localApiGet(`/-route?pathname=${url.pathname}&href=${url.href}&hrefBeforeRedirect=${hrefBeforeRedirect}`, {}, void 0, origin);
28
+ const route = resolution?.route;
29
+ if (route) {
30
+ let middlewareResponse, i = 0;
31
+ while (i < middlewares.length && !middlewareResponse) {
32
+ const middleware = middlewares[i];
33
+ if (typeof middleware === "function") {
34
+ middlewareResponse = await middleware({
35
+ request,
36
+ next,
37
+ route
38
+ });
39
+ if (middlewareResponse) return middlewareResponse;
40
+ }
41
+ i++;
42
+ }
43
+ const nextUrl = getNextUrl(request, route);
44
+ console.log("createRouteProxy.Found", pathname, ">", nextUrl.pathname);
45
+ headers.set("x-market", route.market);
46
+ headers.set("x-locale", route.locale);
47
+ headers.set("x-schema", route.schema);
48
+ headers.set("x-id", String(route.page));
49
+ headers.set("x-forwarded-pathname", nextUrl.pathname);
50
+ return NextResponse.rewrite(nextUrl, { request: { headers } });
51
+ } else {
52
+ const parentRoute = resolution?.parent;
53
+ const market = parentRoute?.market || defaultMarket;
54
+ const locale = parentRoute?.locale || defaultLocale;
55
+ const nextUrl = request.nextUrl.clone();
56
+ nextUrl.pathname = `/${market}/${locale}/404`;
57
+ headers.set("x-market", market);
58
+ headers.set("x-locale", locale);
59
+ headers.set("x-schema", "not_found");
60
+ headers.set("x-id", "404");
61
+ headers.set("x-forwarded-pathname", nextUrl.pathname);
62
+ console.log("createRouteProxy.NotFound", pathname);
63
+ return NextResponse.rewrite(nextUrl, { request: { headers } });
64
+ }
65
+ } catch (error) {
66
+ const routeError = error && typeof error === "object" ? error : {};
67
+ if (routeError.status && routeError.status >= 300 && routeError.status < 400) {
68
+ console.log("createRouteProxy.3xx", url.pathname, routeError.status, routeError.statusText);
69
+ const nextUrl = request.nextUrl.clone();
70
+ nextUrl.pathname = "/";
71
+ headers.set("x-forwarded-pathname", nextUrl.pathname);
72
+ return NextResponse.redirect(nextUrl, 307);
73
+ } else if (routeError.status && routeError.status >= 400 && routeError.status < 500) {
74
+ if (routeError.status === 404)
75
+ /**
76
+ * A resolver miss is not necessarily a CMS 404: it may be a Next.js
77
+ * file-system route such as an API endpoint or static asset. Letting
78
+ * Next continue avoids routing those requests through a fallback
79
+ * render and keeps their fast native handling intact.
80
+ */
81
+ return;
82
+ console.log("createRouteProxy.4xx", url.pathname, routeError.status, routeError.statusText);
83
+ const market = defaultMarket;
84
+ const locale = defaultLocale;
85
+ const nextUrl = request.nextUrl.clone();
86
+ nextUrl.pathname = `/${market}/${locale}/404`;
87
+ headers.set("x-market", market);
88
+ headers.set("x-locale", locale);
89
+ headers.set("x-schema", "not_found");
90
+ headers.set("x-id", "404");
91
+ headers.set("x-forwarded-pathname", nextUrl.pathname);
92
+ console.log("createRouteProxy.NotFound", pathname);
93
+ return NextResponse.rewrite(nextUrl, { request: { headers } });
94
+ }
95
+ console.log("createRouteProxy.error.5xx", url.pathname, routeError.url, routeError.status, routeError.statusText || error);
96
+ return;
97
+ }
98
+ };
99
+ }
100
+ //#endregion
101
+ export { createRouteProxy };
102
+
103
+ //# sourceMappingURL=route-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-proxy.js","names":[],"sources":["../../src/proxy/route-proxy.ts"],"sourcesContent":["import { defaultLocale, defaultMarket, IRoute } from '@websolutespa/bom-core';\r\nimport { NextMiddlewareResult } from 'next/dist/server/web/types';\r\nimport { NextFetchEvent, NextRequest, NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getHrefBeforeRedirect, getNextUrl } from '../server/utils';\r\nimport { getRequestOrigin, Middleware, MiddlewareOptions } from './proxy';\r\n\r\nexport type Proxy = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type RouteMiddlewareOptions = {\r\n request: NextRequest,\r\n next: NextFetchEvent,\r\n route: IRoute,\r\n disabled?: boolean,\r\n};\r\nexport type RouteMiddleware = (props: RouteMiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\r\n\r\nexport type RouteInterceptorProxy = (route: IRoute, request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type ResolvedRoute = IRoute & { splat?: string };\r\nexport type RouteResolverResponse = {\r\n parent?: IRoute;\r\n route?: ResolvedRoute;\r\n};\r\n\r\n/**\r\n * Resolves a public request to a CMS route, then rewrites it to the internal\r\n * Next.js page while preserving the original browser URL.\r\n *\r\n * The resolver call is deliberately made to this request's public origin so it\r\n * works behind reverse proxies and deployment hosts. A rewrite keeps routing\r\n * server-side, avoiding an extra browser round trip that a redirect would add.\r\n */\r\nexport function createRouteProxy(...middlewares: RouteMiddleware[]): Middleware {\r\n return async function ({ request, next }: MiddlewareOptions) {\r\n const url = request.nextUrl;\r\n const origin = getRequestOrigin(request);\r\n const hrefBeforeRedirect = getHrefBeforeRedirect(request);\r\n const { pathname } = url;\r\n const headers = new Headers(request.headers);\r\n headers.set('x-pathname', pathname);\r\n try {\r\n const draftMode = request.cookies.has('__prerender_bypass');\r\n console.log('draftMode', draftMode);\r\n if (draftMode) {\r\n // Draft requests need Payload's native preview behavior, so skip the\r\n // route lookup and its database/cache work entirely.\r\n return;\r\n }\r\n // Resolve once before invoking route middleware. This shares the route\r\n // snapshot result across all middleware rather than letting each one\r\n // repeat the internal API request.\r\n const resolution = await localApiGet<RouteResolverResponse>(\r\n `/-route?pathname=${url.pathname}&href=${url.href}&hrefBeforeRedirect=${hrefBeforeRedirect}`,\r\n {},\r\n undefined,\r\n origin\r\n );\r\n const route = resolution?.route;\r\n // console.log('createRouteProxy', route);\r\n if (route) {\r\n let middlewareResponse, i = 0;\r\n // Run in registration order and stop at the first response. Later\r\n // middleware cannot affect a committed rewrite, so short-circuiting\r\n // avoids unnecessary authentication or policy checks.\r\n while (i < middlewares.length && !middlewareResponse) {\r\n const middleware = middlewares[i] as RouteMiddleware;\r\n // console.log('createRouteProxy.middlewares', middlewares.length, typeof middleware === 'function');\r\n if (typeof middleware === 'function') {\r\n middlewareResponse = await middleware({ request, next, route });\r\n if (middlewareResponse) {\r\n return middlewareResponse;\r\n }\r\n }\r\n i++;\r\n }\r\n const nextUrl = getNextUrl(request, route);\r\n console.log('createRouteProxy.Found', pathname, '>', nextUrl.pathname);\r\n // Pass the resolved route as request headers so the internal page can\r\n // render without performing a second route-resolution lookup.\r\n headers.set('x-market', route.market);\r\n headers.set('x-locale', route.locale);\r\n headers.set('x-schema', route.schema);\r\n headers.set('x-id', String(route.page));\r\n headers.set('x-forwarded-pathname', nextUrl.pathname);\r\n const response = NextResponse.rewrite(nextUrl, {\r\n request: {\r\n headers,\r\n },\r\n });\r\n // const response = NextResponse.redirect(url);\r\n return response;\r\n } else {\r\n const parentRoute = resolution?.parent;\r\n // The resolver returns the nearest parent even when no leaf route\r\n // matches. Reusing its market and locale makes the 404 contextual\r\n // without another lookup; defaults cover an entirely unknown path.\r\n const market = parentRoute?.market || defaultMarket;\r\n const locale = parentRoute?.locale || defaultLocale;\r\n const nextUrl = request.nextUrl.clone();\r\n nextUrl.pathname = `/${market}/${locale}/404`;\r\n headers.set('x-market', market);\r\n headers.set('x-locale', locale);\r\n headers.set('x-schema', 'not_found');\r\n headers.set('x-id', '404');\r\n headers.set('x-forwarded-pathname', nextUrl.pathname);\r\n console.log('createRouteProxy.NotFound', pathname);\r\n const response = NextResponse\r\n .rewrite(nextUrl, {\r\n request: {\r\n headers,\r\n },\r\n });\r\n return response;\r\n }\r\n } catch (error: unknown) {\r\n const routeError = error && typeof error === 'object'\r\n ? error as { status?: number; statusText?: string; url?: string }\r\n : {};\r\n\r\n if (routeError.status && routeError.status >= 300 && routeError.status < 400) {\r\n console.log('createRouteProxy.3xx', url.pathname, routeError.status, routeError.statusText);\r\n const nextUrl = request.nextUrl.clone();\r\n // The handler has already validated the redirect target. Redirect the\r\n // browser once so its address bar changes, rather than rewriting a\r\n // route whose canonical URL is different.\r\n nextUrl.pathname = '/';\r\n headers.set('x-forwarded-pathname', nextUrl.pathname);\r\n const response = NextResponse.redirect(nextUrl, 307);\r\n return response;\r\n } else if (routeError.status && routeError.status >= 400 && routeError.status < 500) {\r\n if (routeError.status === 404) {\r\n /**\r\n * A resolver miss is not necessarily a CMS 404: it may be a Next.js\r\n * file-system route such as an API endpoint or static asset. Letting\r\n * Next continue avoids routing those requests through a fallback\r\n * render and keeps their fast native handling intact.\r\n */\r\n // console.log('createRouteProxy.route.notfound', url.pathname);\r\n return;\r\n }\r\n console.log('createRouteProxy.4xx', url.pathname, routeError.status, routeError.statusText);\r\n // Other client errors are terminal CMS outcomes, so render the shared\r\n // 404 page directly instead of issuing a separate client navigation.\r\n const market = defaultMarket;\r\n const locale = defaultLocale;\r\n const nextUrl = request.nextUrl.clone();\r\n nextUrl.pathname = `/${market}/${locale}/404`;\r\n headers.set('x-market', market);\r\n headers.set('x-locale', locale);\r\n headers.set('x-schema', 'not_found');\r\n headers.set('x-id', '404');\r\n headers.set('x-forwarded-pathname', nextUrl.pathname);\r\n console.log('createRouteProxy.NotFound', pathname);\r\n const response = NextResponse\r\n .rewrite(nextUrl, {\r\n request: {\r\n headers,\r\n },\r\n });\r\n return response;\r\n /*\r\n const response = NextResponse.next({\r\n status: routeError.status,\r\n statusText: routeError.statusText,\r\n headers,\r\n });\r\n return response;\r\n */\r\n }\r\n // A resolver failure must not block unrelated Next.js routes. Returning\r\n // undefined delegates to the normal pipeline and avoids masking a\r\n // transient upstream failure with a misleading synthetic response.\r\n console.log('createRouteProxy.error.5xx', url.pathname, routeError.url, routeError.status, routeError.statusText || error);\r\n return;\r\n }\r\n };\r\n}\r\n\r\n/*\r\n\r\nexport const routeInterceptor: Proxy = async function (request: NextRequest, next: NextFetchEvent) {\r\n const middleware = await createRouteProxy();\r\n return await middleware(request, next);\r\n};\r\n\r\n*/\r\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { IPageContext, TypedPageContext } from "../types.js";
2
+ import { CollectionSlug, SanitizedConfig } from "payload";
3
+ import { headers } from "next/headers";
4
+
5
+ //#region src/server/context.d.ts
6
+ declare function getPageContext<TSlug extends CollectionSlug = CollectionSlug>(): Promise<TypedPageContext<TSlug>>;
7
+ declare function setPageContext<TSlug extends CollectionSlug>(data: TypedPageContext<TSlug>): Promise<void>;
8
+ /**
9
+ * Same as createPageContext but without draft mode — used for error/not-found pages
10
+ * that should always show published content regardless of draft mode state.
11
+ */
12
+ declare function createNotFoundContext<TSlug extends CollectionSlug>(market: string, locale: string, slug: TSlug, id: string, config: Promise<SanitizedConfig>, headers?: Awaited<ReturnType<typeof headers>>): Promise<TypedPageContext<TSlug>>;
13
+ /**
14
+ * Initialises the full page context using Payload local API.
15
+ *
16
+ * Replaces the @websolutespa/bom-next/server createPageContext that goes through the store
17
+ * abstraction. All data is fetched directly from Payload; the mixer context
18
+ * (routes + categories) is passed to every payload.find call so that
19
+ * payload-plugin-bowl can enrich responses.
20
+ */
21
+ declare function createPageContext<TSlug extends CollectionSlug>(market: string, locale: string, slug: TSlug, id: string, config: Promise<SanitizedConfig>, headers?: Awaited<ReturnType<typeof headers>>): Promise<TypedPageContext<TSlug>>;
22
+ /**
23
+ * Layout-only context — no page fetch. Used by RootLayout server components.
24
+ */
25
+ declare function createLayoutContext(market: string, locale: string, config: Promise<SanitizedConfig>, headers?: Awaited<ReturnType<typeof headers>>): Promise<IPageContext>;
26
+ //# sourceMappingURL=context.d.ts.map
27
+
28
+ //#endregion
29
+ export { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext };
30
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","names":[],"sources":["../../src/server/context.ts"],"mappings":";;;;;iBAoBsB,6BAA6B,iBAAiB,mBAAmB,QAAQ,iBAAiB;iBAU1F,6BAA6B,sBAAsB,iBAAiB,SAAM;AAVhG;AAAoC;AAAe;AAAiB;AAA4C,iBAqB1F,qBArB0F,CAAA,cAqBtD,cArBsD,CAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EAwBxG,KAxBwG,EAAA,EAAA,EAAA,MAAA,EAAA,MAAA,EA0BtG,OA1BsG,CA0B9F,eA1B8F,CAAA,EAAA,OAAA,CAAA,EA2BpG,OA3BoG,CA2B5F,UA3B4F,CAAA,OA2B1E,OA3B0E,CAAA,CAAA,CAAA,EA4B7G,OA5B6G,CA4BrG,gBA5BqG,CA4BpF,KA5BoF,CAAA,CAAA;AAAjB;AAAR;AAAO;AAU9F;AAAoC;AAAe;AAAuC;AAAjB;AAAuB,iBAiD1E,iBAjD0E,CAAA,cAiD1C,cAjD0C,CAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EAoDxF,KApDwF,EAAA,EAAA,EAAA,MAAA,EAAA,MAAA,EAsDtF,OAtDsF,CAsD9E,eAtD8E,CAAA,EAAA,OAAA,CAAA,EAuDpF,OAvDoF,CAuD5E,UAvD4E,CAAA,OAuD1D,OAvD0D,CAAA,CAAA,CAAA,EAwD7F,OAxD6F,CAwDrF,gBAxDqF,CAwDpE,KAxDoE,CAAA,CAAA;AAAA;AAWhG;AAA2C;AAAe,iBAiFpC,mBAAA,CAjFoC,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAoFhD,OApFgD,CAoFxC,eApFwC,CAAA,EAAA,OAAA,CAAA,EAqF9C,OArF8C,CAqFtC,UArFsC,CAAA,OAqFpB,OArFoB,CAAA,CAAA,CAAA,EAqFR,OArFQ,CAqFR,YArFQ,CAAA;AAGlD"}
@@ -0,0 +1,106 @@
1
+ "use server";
2
+ import { getLabelFromLabels } from "../lib/label.js";
3
+ import { getLink } from "../lib/link.js";
4
+ import { getPayload } from "./mixer.js";
5
+ import { getLayout } from "./layout.js";
6
+ import { getPage } from "./page.js";
7
+ import { cache } from "react";
8
+ //#region src/server/context.ts
9
+ /**
10
+ * Per-request context store (React.cache ensures a fresh Map per RSC render).
11
+ * Safe to use inside Next.js server components — do NOT call this at build time.
12
+ */
13
+ const PageContext = cache(() => {
14
+ return /* @__PURE__ */ new Map();
15
+ });
16
+ async function getPageContext() {
17
+ return {
18
+ layout: PageContext().get("layout"),
19
+ page: PageContext().get("page"),
20
+ user: PageContext().get("user") || null,
21
+ label: PageContext().get("label"),
22
+ link: PageContext().get("link")
23
+ };
24
+ }
25
+ async function setPageContext(data) {
26
+ const context = PageContext();
27
+ for (const key in data) context.set(key, data[key]);
28
+ }
29
+ /**
30
+ * Same as createPageContext but without draft mode — used for error/not-found pages
31
+ * that should always show published content regardless of draft mode state.
32
+ */
33
+ async function createNotFoundContext(market, locale, slug, id, config, headers) {
34
+ const { payload, user, getContext } = await getPayload({
35
+ config,
36
+ headers
37
+ });
38
+ const context = await getContext(market, locale);
39
+ const layout = await getLayout(market, locale, payload, user, context);
40
+ const page = await getPage(slug, id, market, locale, payload, user, context);
41
+ const label = getLabelFromLabels(layout.labels);
42
+ const link = (category) => getLink(category, layout);
43
+ const pageContext = {
44
+ layout,
45
+ page,
46
+ user,
47
+ label,
48
+ link
49
+ };
50
+ setPageContext(pageContext);
51
+ return pageContext;
52
+ }
53
+ /**
54
+ * Initialises the full page context using Payload local API.
55
+ *
56
+ * Replaces the @websolutespa/bom-next/server createPageContext that goes through the store
57
+ * abstraction. All data is fetched directly from Payload; the mixer context
58
+ * (routes + categories) is passed to every payload.find call so that
59
+ * payload-plugin-bowl can enrich responses.
60
+ */
61
+ async function createPageContext(market, locale, slug, id, config, headers) {
62
+ const draft = { isEnabled: false };
63
+ const { payload, user, getContext } = await getPayload({
64
+ config,
65
+ headers
66
+ });
67
+ const context = await getContext(market, locale);
68
+ const layout = await getLayout(market, locale, payload, user, context, draft.isEnabled);
69
+ const page = await getPage(slug, id, market, locale, payload, user, context, draft.isEnabled);
70
+ const label = getLabelFromLabels(layout.labels);
71
+ const link = (category) => getLink(category, layout);
72
+ const pageContext = {
73
+ layout,
74
+ page,
75
+ user,
76
+ label,
77
+ link
78
+ };
79
+ setPageContext(pageContext);
80
+ return pageContext;
81
+ }
82
+ /**
83
+ * Layout-only context — no page fetch. Used by RootLayout server components.
84
+ */
85
+ async function createLayoutContext(market, locale, config, headers) {
86
+ const { payload, user, getContext } = await getPayload({
87
+ config,
88
+ headers
89
+ });
90
+ const context = await getContext(market, locale);
91
+ const layout = await getLayout(market, locale, payload, user, context);
92
+ const label = getLabelFromLabels(layout.labels);
93
+ const link = (category) => getLink(category, layout);
94
+ const pageContext = {
95
+ layout,
96
+ user,
97
+ label,
98
+ link
99
+ };
100
+ setPageContext(pageContext);
101
+ return pageContext;
102
+ }
103
+ //#endregion
104
+ export { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext };
105
+
106
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/server/context.ts"],"sourcesContent":["'use server';\r\n\r\nimport { headers as getHeaders } from 'next/headers';\r\nimport type { CollectionSlug, SanitizedConfig } from 'payload';\r\nimport { cache } from 'react';\r\nimport { getLabelFromLabels } from '../lib/label';\r\nimport { getLink } from '../lib/link';\r\nimport type { IPageContext, TypedPageContext } from '../types';\r\nimport { getLayout } from './layout';\r\nimport { getPayload } from './mixer';\r\nimport { getPage } from './page';\r\n\r\n/**\r\n * Per-request context store (React.cache ensures a fresh Map per RSC render).\r\n * Safe to use inside Next.js server components — do NOT call this at build time.\r\n */\r\nconst PageContext = cache(() => {\r\n return new Map<string, any>();\r\n});\r\n\r\nexport async function getPageContext<TSlug extends CollectionSlug = CollectionSlug>(): Promise<TypedPageContext<TSlug>> {\r\n return {\r\n layout: PageContext().get('layout'),\r\n page: PageContext().get('page'),\r\n user: PageContext().get('user') || null,\r\n label: PageContext().get('label'),\r\n link: PageContext().get('link'),\r\n } as TypedPageContext<TSlug>;\r\n}\r\n\r\nexport async function setPageContext<TSlug extends CollectionSlug>(data: TypedPageContext<TSlug>) {\r\n const context = PageContext();\r\n for (const key in data) {\r\n context.set(key, data[key as keyof IPageContext]);\r\n }\r\n}\r\n\r\n/**\r\n * Same as createPageContext but without draft mode — used for error/not-found pages\r\n * that should always show published content regardless of draft mode state.\r\n */\r\nexport async function createNotFoundContext<TSlug extends CollectionSlug>(\r\n market: string,\r\n locale: string,\r\n slug: TSlug,\r\n id: string,\r\n config: Promise<SanitizedConfig>,\r\n headers?: Awaited<ReturnType<typeof getHeaders>>\r\n): Promise<TypedPageContext<TSlug>> {\r\n const { payload, user, getContext } = await getPayload({ config, headers });\r\n const context = await getContext(market, locale);\r\n\r\n const layout = await getLayout(market, locale, payload, user, context);\r\n const page = await getPage(slug, id, market, locale, payload, user, context);\r\n\r\n const label = getLabelFromLabels(layout.labels);\r\n const link = (category: string) => getLink(category, layout);\r\n\r\n const pageContext = {\r\n layout,\r\n page,\r\n user,\r\n label,\r\n link,\r\n } as TypedPageContext<TSlug>;\r\n\r\n setPageContext(pageContext);\r\n\r\n return pageContext;\r\n}\r\n\r\n/**\r\n * Initialises the full page context using Payload local API.\r\n *\r\n * Replaces the @websolutespa/bom-next/server createPageContext that goes through the store\r\n * abstraction. All data is fetched directly from Payload; the mixer context\r\n * (routes + categories) is passed to every payload.find call so that\r\n * payload-plugin-bowl can enrich responses.\r\n */\r\nexport async function createPageContext<TSlug extends CollectionSlug>(\r\n market: string,\r\n locale: string,\r\n slug: TSlug,\r\n id: string,\r\n config: Promise<SanitizedConfig>,\r\n headers?: Awaited<ReturnType<typeof getHeaders>>\r\n): Promise<TypedPageContext<TSlug>> {\r\n\r\n // const draft = await draftMode();\r\n const draft = { isEnabled: false };\r\n\r\n const { payload, user, getContext } = await getPayload({ config, headers });\r\n const context = await getContext(market, locale);\r\n\r\n const layout = await getLayout(market, locale, payload, user, context, draft.isEnabled);\r\n const page = await getPage(slug, id, market, locale, payload, user, context, draft.isEnabled);\r\n\r\n const label = getLabelFromLabels(layout.labels);\r\n const link = (category: string) => getLink(category, layout);\r\n\r\n const pageContext = {\r\n layout,\r\n page,\r\n user,\r\n label,\r\n link,\r\n } as TypedPageContext<TSlug>;\r\n\r\n setPageContext(pageContext);\r\n\r\n /*\r\n if (draft.isEnabled) {\r\n draft.disable();\r\n }\r\n */\r\n\r\n return pageContext;\r\n}\r\n\r\n/**\r\n * Layout-only context — no page fetch. Used by RootLayout server components.\r\n */\r\nexport async function createLayoutContext(\r\n market: string,\r\n locale: string,\r\n config: Promise<SanitizedConfig>,\r\n headers?: Awaited<ReturnType<typeof getHeaders>>\r\n) {\r\n const { payload, user, getContext } = await getPayload({ config, headers });\r\n const context = await getContext(market, locale);\r\n\r\n const layout = await getLayout(market, locale, payload, user, context);\r\n\r\n const label = getLabelFromLabels(layout.labels);\r\n const link = (category: string) => getLink(category, layout);\r\n\r\n const pageContext = {\r\n layout,\r\n user,\r\n label,\r\n link,\r\n } as unknown as IPageContext;\r\n\r\n setPageContext(pageContext);\r\n\r\n return pageContext;\r\n}\r\n"],"mappings":";;;;;;;;;;;;AAgBA,MAAM,cAAc,YAAY;CAC9B,uBAAO,IAAI,IAAiB;AAC9B,CAAC;AAED,eAAsB,iBAAkG;CACtH,OAAO;EACL,QAAQ,YAAY,CAAC,CAAC,IAAI,QAAQ;EAClC,MAAM,YAAY,CAAC,CAAC,IAAI,MAAM;EAC9B,MAAM,YAAY,CAAC,CAAC,IAAI,MAAM,KAAK;EACnC,OAAO,YAAY,CAAC,CAAC,IAAI,OAAO;EAChC,MAAM,YAAY,CAAC,CAAC,IAAI,MAAM;CAChC;AACF;AAEA,eAAsB,eAA6C,MAA+B;CAChG,MAAM,UAAU,YAAY;CAC5B,KAAK,MAAM,OAAO,MAChB,QAAQ,IAAI,KAAK,KAAK,IAA0B;AAEpD;;;;;AAMA,eAAsB,sBACpB,QACA,QACA,MACA,IACA,QACA,SACkC;CAClC,MAAM,EAAE,SAAS,MAAM,eAAe,MAAM,WAAW;EAAE;EAAQ;CAAQ,CAAC;CAC1E,MAAM,UAAU,MAAM,WAAW,QAAQ,MAAM;CAE/C,MAAM,SAAS,MAAM,UAAU,QAAQ,QAAQ,SAAS,MAAM,OAAO;CACrE,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,QAAQ,QAAQ,SAAS,MAAM,OAAO;CAE3E,MAAM,QAAQ,mBAAmB,OAAO,MAAM;CAC9C,MAAM,QAAQ,aAAqB,QAAQ,UAAU,MAAM;CAE3D,MAAM,cAAc;EAClB;EACA;EACA;EACA;EACA;CACF;CAEA,eAAe,WAAW;CAE1B,OAAO;AACT;;;;;;;;;AAUA,eAAsB,kBACpB,QACA,QACA,MACA,IACA,QACA,SACkC;CAGlC,MAAM,QAAQ,EAAE,WAAW,MAAM;CAEjC,MAAM,EAAE,SAAS,MAAM,eAAe,MAAM,WAAW;EAAE;EAAQ;CAAQ,CAAC;CAC1E,MAAM,UAAU,MAAM,WAAW,QAAQ,MAAM;CAE/C,MAAM,SAAS,MAAM,UAAU,QAAQ,QAAQ,SAAS,MAAM,SAAS,MAAM,SAAS;CACtF,MAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,QAAQ,QAAQ,SAAS,MAAM,SAAS,MAAM,SAAS;CAE5F,MAAM,QAAQ,mBAAmB,OAAO,MAAM;CAC9C,MAAM,QAAQ,aAAqB,QAAQ,UAAU,MAAM;CAE3D,MAAM,cAAc;EAClB;EACA;EACA;EACA;EACA;CACF;CAEA,eAAe,WAAW;CAQ1B,OAAO;AACT;;;;AAKA,eAAsB,oBACpB,QACA,QACA,QACA,SACA;CACA,MAAM,EAAE,SAAS,MAAM,eAAe,MAAM,WAAW;EAAE;EAAQ;CAAQ,CAAC;CAC1E,MAAM,UAAU,MAAM,WAAW,QAAQ,MAAM;CAE/C,MAAM,SAAS,MAAM,UAAU,QAAQ,QAAQ,SAAS,MAAM,OAAO;CAErE,MAAM,QAAQ,mBAAmB,OAAO,MAAM;CAC9C,MAAM,QAAQ,aAAqB,QAAQ,UAAU,MAAM;CAE3D,MAAM,cAAc;EAClB;EACA;EACA;EACA;CACF;CAEA,eAAe,WAAW;CAE1B,OAAO;AACT"}
@@ -0,0 +1,10 @@
1
+ import { NextRequest } from "next/server";
2
+ import { SanitizedConfig } from "payload";
3
+
4
+ //#region src/server/handlers/auth.handler.d.ts
5
+ declare function getAuthMeHandler(config: Promise<SanitizedConfig>): (request: NextRequest) => Promise<Response>;
6
+ //# sourceMappingURL=auth.handler.d.ts.map
7
+
8
+ //#endregion
9
+ export { getAuthMeHandler };
10
+ //# sourceMappingURL=auth.handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.handler.d.ts","names":[],"sources":["../../../src/server/handlers/auth.handler.ts"],"mappings":";;;;iBAMgB,gBAAA,SAAyB,QAAQ,6BACf,gBAAW,QAAA"}
@@ -0,0 +1,29 @@
1
+ import { getPayload } from "../mixer.js";
2
+ import { getHandlerErrorResponse } from "./error-response.js";
3
+ import { headers } from "next/headers";
4
+ //#region src/server/handlers/auth.handler.ts
5
+ function getAuthMeHandler(config) {
6
+ return async function(request) {
7
+ try {
8
+ const headers$1 = await headers();
9
+ const { user } = await getPayload({
10
+ config,
11
+ headers: headers$1
12
+ });
13
+ if ((user?.roles || []).includes("user") && "firstName" in user) return Response.json({
14
+ id: user.id,
15
+ email: user.email,
16
+ firstName: user.firstName,
17
+ lastName: user.lastName
18
+ }, { status: 200 });
19
+ return Response.json(null, { status: 200 });
20
+ } catch (error) {
21
+ console.log("getAuthMeHandler.error", error);
22
+ return getHandlerErrorResponse(error);
23
+ }
24
+ };
25
+ }
26
+ //#endregion
27
+ export { getAuthMeHandler };
28
+
29
+ //# sourceMappingURL=auth.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.handler.js","names":["headers","getHeaders"],"sources":["../../../src/server/handlers/auth.handler.ts"],"sourcesContent":["import { headers as getHeaders } from 'next/headers';\r\nimport { NextRequest } from 'next/server';\r\nimport { SanitizedConfig } from 'payload';\r\nimport { getPayload } from '../mixer';\r\nimport { getHandlerErrorResponse } from './error-response';\r\n\r\nexport function getAuthMeHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: NextRequest) {\r\n try {\r\n const headers = await getHeaders();\r\n const { user } = await getPayload({ config, headers });\r\n const roles = (user?.roles || []);\r\n if (roles.includes('user') && 'firstName' in user) {\r\n return Response.json({\r\n id: user.id,\r\n email: user.email,\r\n firstName: user.firstName,\r\n lastName: user.lastName,\r\n }, { status: 200 });\r\n }\r\n return Response.json(null, { status: 200 });\r\n } catch (error) {\r\n console.log('getAuthMeHandler.error', error);\r\n return getHandlerErrorResponse(error);\r\n }\r\n };\r\n}\r\n"],"mappings":";;;;AAMA,SAAgB,iBAAiB,QAAkC;CACjE,OAAO,eAAgB,SAAsB;EAC3C,IAAI;GACF,MAAMA,YAAU,MAAMC,QAAW;GACjC,MAAM,EAAE,SAAS,MAAM,WAAW;IAAE;IAAQ,SAAA;GAAQ,CAAC;GAErD,KADe,MAAM,SAAS,CAAC,EAAA,CACrB,SAAS,MAAM,KAAK,eAAe,MAC3C,OAAO,SAAS,KAAK;IACnB,IAAI,KAAK;IACT,OAAO,KAAK;IACZ,WAAW,KAAK;IAChB,UAAU,KAAK;GACjB,GAAG,EAAE,QAAQ,IAAI,CAAC;GAEpB,OAAO,SAAS,KAAK,MAAM,EAAE,QAAQ,IAAI,CAAC;EAC5C,SAAS,OAAO;GACd,QAAQ,IAAI,0BAA0B,KAAK;GAC3C,OAAO,wBAAwB,KAAK;EACtC;CACF;AACF"}
@@ -0,0 +1,10 @@
1
+ import { NextRequest } from "next/server";
2
+ import { SanitizedConfig } from "payload";
3
+
4
+ //#region src/server/handlers/captions.handler.d.ts
5
+ declare function getCaptionsVTT(config: Promise<SanitizedConfig>): (request: NextRequest) => Promise<Response>;
6
+ //# sourceMappingURL=captions.handler.d.ts.map
7
+
8
+ //#endregion
9
+ export { getCaptionsVTT };
10
+ //# sourceMappingURL=captions.handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captions.handler.d.ts","names":[],"sources":["../../../src/server/handlers/captions.handler.ts"],"mappings":";;;;iBAIgB,cAAA,SAAuB,QAAQ,6BACb,gBAAW,QAAA"}
@@ -0,0 +1,33 @@
1
+ import { getHandlerErrorResponse } from "./error-response.js";
2
+ //#region src/server/handlers/captions.handler.ts
3
+ function getCaptionsVTT(config) {
4
+ return async function(request) {
5
+ try {
6
+ const title = request.nextUrl.searchParams.get("title") || "Untitled";
7
+ const body = `WEBVTT
8
+
9
+ 00:00:01.000 --> 00:00:03.000
10
+ - This video has no audio.
11
+
12
+ ${title ? `
13
+ 00:00:04.000 --> 00:00:06.000
14
+ - The title of the video is "${title}".
15
+ ` : ""}`;
16
+ return new Response(body, {
17
+ status: 200,
18
+ headers: {
19
+ "Content-Type": "text/plain; charset=UTF-8",
20
+ "X-Frame-Options": "SAMEORIGIN",
21
+ "X-Robots-Tag": "noindex, follow"
22
+ }
23
+ });
24
+ } catch (error) {
25
+ console.error("getCaptionsVTT.error", error);
26
+ return getHandlerErrorResponse(error);
27
+ }
28
+ };
29
+ }
30
+ //#endregion
31
+ export { getCaptionsVTT };
32
+
33
+ //# sourceMappingURL=captions.handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captions.handler.js","names":[],"sources":["../../../src/server/handlers/captions.handler.ts"],"sourcesContent":["import { NextRequest } from 'next/server';\r\nimport { SanitizedConfig } from 'payload';\r\nimport { getHandlerErrorResponse } from './error-response';\r\n\r\nexport function getCaptionsVTT(config: Promise<SanitizedConfig>) {\r\n return async function (request: NextRequest) {\r\n try {\r\n const searchParams = request.nextUrl.searchParams;\r\n const title = searchParams.get('title') || 'Untitled';\r\n const body = /* html */`WEBVTT\r\n\r\n00:00:01.000 --> 00:00:03.000\r\n- This video has no audio.\r\n\r\n${title ? `\r\n00:00:04.000 --> 00:00:06.000\r\n- The title of the video is \"${title}\".\r\n` : ''}`;\r\n return new Response(body, {\r\n status: 200,\r\n headers: {\r\n 'Content-Type': 'text/plain; charset=UTF-8',\r\n 'X-Frame-Options': 'SAMEORIGIN',\r\n 'X-Robots-Tag': 'noindex, follow',\r\n },\r\n });\r\n } catch (error: unknown) {\r\n console.error('getCaptionsVTT.error', error);\r\n return getHandlerErrorResponse(error);\r\n }\r\n };\r\n}\r\n"],"mappings":";;AAIA,SAAgB,eAAe,QAAkC;CAC/D,OAAO,eAAgB,SAAsB;EAC3C,IAAI;GAEF,MAAM,QADe,QAAQ,QAAQ,aACV,IAAI,OAAO,KAAK;GAC3C,MAAM,OAAiB;;;;;EAK3B,QAAQ;;+BAEqB,MAAM;IACjC;GACE,OAAO,IAAI,SAAS,MAAM;IACxB,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,mBAAmB;KACnB,gBAAgB;IAClB;GACF,CAAC;EACH,SAAS,OAAgB;GACvB,QAAQ,MAAM,wBAAwB,KAAK;GAC3C,OAAO,wBAAwB,KAAK;EACtC;CACF;AACF"}