@websolutespa/bom-next 3.0.2 → 4.0.0-next.1

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 (264) hide show
  1. package/CHANGELOG.md +37 -7
  2. package/README.md +28 -0
  3. package/dist/_virtual/{_rolldown/runtime.js → rolldown_runtime.js} +7 -4
  4. package/dist/client/client.d.ts.map +1 -1
  5. package/dist/client/client.js +17 -6
  6. package/dist/client/client.js.map +1 -1
  7. package/dist/client/extra.d.ts +3 -3
  8. package/dist/client/extra.d.ts.map +1 -1
  9. package/dist/client/extra.js +10 -5
  10. package/dist/client/extra.js.map +1 -1
  11. package/dist/client/label.d.ts +3 -3
  12. package/dist/client/label.d.ts.map +1 -1
  13. package/dist/client/label.js +10 -5
  14. package/dist/client/label.js.map +1 -1
  15. package/dist/client/layout.d.ts +3 -3
  16. package/dist/client/layout.d.ts.map +1 -1
  17. package/dist/client/layout.js +10 -5
  18. package/dist/client/layout.js.map +1 -1
  19. package/dist/client/local.collection.d.ts.map +1 -1
  20. package/dist/client/local.collection.js +4 -2
  21. package/dist/client/local.collection.js.map +1 -1
  22. package/dist/client/metadata.d.ts +3 -3
  23. package/dist/client/metadata.d.ts.map +1 -1
  24. package/dist/client/metadata.js +48 -40
  25. package/dist/client/metadata.js.map +1 -1
  26. package/dist/client/page.d.ts +3 -3
  27. package/dist/client/page.d.ts.map +1 -1
  28. package/dist/client/page.js +10 -5
  29. package/dist/client/page.js.map +1 -1
  30. package/dist/client/useApi.d.ts +7 -7
  31. package/dist/client/useApi.d.ts.map +1 -1
  32. package/dist/client/useApi.js +2 -1
  33. package/dist/client/useApi.js.map +1 -1
  34. package/dist/client/useCollectionApi.d.ts +6 -6
  35. package/dist/client/useCollectionApi.d.ts.map +1 -1
  36. package/dist/client/useCollectionApi.js +4 -2
  37. package/dist/client/useCollectionApi.js.map +1 -1
  38. package/dist/client/useExtra.d.ts.map +1 -1
  39. package/dist/client/useExtra.js +5 -2
  40. package/dist/client/useExtra.js.map +1 -1
  41. package/dist/client/useHttp.d.ts.map +1 -1
  42. package/dist/client/useHttp.js +9 -6
  43. package/dist/client/useHttp.js.map +1 -1
  44. package/dist/client/useLabel.d.ts.map +1 -1
  45. package/dist/client/useLabel.js +5 -2
  46. package/dist/client/useLabel.js.map +1 -1
  47. package/dist/client/useLayout.d.ts.map +1 -1
  48. package/dist/client/useLayout.js +5 -2
  49. package/dist/client/useLayout.js.map +1 -1
  50. package/dist/client/useLink.d.ts.map +1 -1
  51. package/dist/client/useLink.js +7 -3
  52. package/dist/client/useLink.js.map +1 -1
  53. package/dist/client/useMetaData.d.ts.map +1 -1
  54. package/dist/client/useMetaData.js +5 -2
  55. package/dist/client/useMetaData.js.map +1 -1
  56. package/dist/client/usePage.d.ts.map +1 -1
  57. package/dist/client/usePage.js +5 -2
  58. package/dist/client/usePage.js.map +1 -1
  59. package/dist/client/useUser.d.ts.map +1 -1
  60. package/dist/client/useUser.js +5 -2
  61. package/dist/client/useUser.js.map +1 -1
  62. package/dist/client/user.d.ts.map +1 -1
  63. package/dist/client/user.js +17 -11
  64. package/dist/client/user.js.map +1 -1
  65. package/dist/exports/client.js +2 -1
  66. package/dist/exports/instrumentation.js +2 -1
  67. package/dist/exports/proxy.js +2 -1
  68. package/dist/exports/server.d.ts +5 -4
  69. package/dist/exports/server.js +7 -5
  70. package/dist/index.d.ts +3 -3
  71. package/dist/index.js +3 -2
  72. package/dist/instrumentation/client.d.ts.map +1 -1
  73. package/dist/instrumentation/client.js +2 -1
  74. package/dist/instrumentation/client.js.map +1 -1
  75. package/dist/instrumentation/sentry/capture.requestError.js +4 -1
  76. package/dist/instrumentation/sentry/capture.requestError.js.map +1 -1
  77. package/dist/instrumentation/sentry/capture.routerTransitionStart.js +2 -1
  78. package/dist/instrumentation/sentry/capture.routerTransitionStart.js.map +1 -1
  79. package/dist/instrumentation/sentry/config.client.js +10 -2
  80. package/dist/instrumentation/sentry/config.client.js.map +1 -0
  81. package/dist/instrumentation/sentry/config.edge.js +10 -2
  82. package/dist/instrumentation/sentry/config.edge.js.map +1 -0
  83. package/dist/instrumentation/sentry/config.server.js +10 -2
  84. package/dist/instrumentation/sentry/config.server.js.map +1 -0
  85. package/dist/instrumentation/server.d.ts.map +1 -1
  86. package/dist/instrumentation/server.js +8 -5
  87. package/dist/instrumentation/server.js.map +1 -1
  88. package/dist/instrumentation/types.d.ts.map +1 -1
  89. package/dist/lib/breadcrumb.d.ts.map +1 -1
  90. package/dist/lib/breadcrumb.js +6 -1
  91. package/dist/lib/breadcrumb.js.map +1 -1
  92. package/dist/lib/const.d.ts +14 -2
  93. package/dist/lib/const.d.ts.map +1 -1
  94. package/dist/lib/const.js +24 -2
  95. package/dist/lib/const.js.map +1 -1
  96. package/dist/lib/http.d.ts +9 -0
  97. package/dist/lib/http.d.ts.map +1 -1
  98. package/dist/lib/http.js +27 -4
  99. package/dist/lib/http.js.map +1 -1
  100. package/dist/lib/label.d.ts.map +1 -1
  101. package/dist/lib/label.js +4 -3
  102. package/dist/lib/label.js.map +1 -1
  103. package/dist/lib/layout.defaults.d.ts.map +1 -1
  104. package/dist/lib/layout.defaults.js +1 -1
  105. package/dist/lib/layout.defaults.js.map +1 -1
  106. package/dist/lib/link.d.ts.map +1 -1
  107. package/dist/lib/link.js +2 -1
  108. package/dist/lib/link.js.map +1 -1
  109. package/dist/lib/meta-data.d.ts.map +1 -1
  110. package/dist/lib/open-graph.d.ts.map +1 -1
  111. package/dist/lib/pagination.d.ts.map +1 -1
  112. package/dist/lib/pagination.js +4 -2
  113. package/dist/lib/pagination.js.map +1 -1
  114. package/dist/lib/route.d.ts.map +1 -1
  115. package/dist/lib/route.js +9 -3
  116. package/dist/lib/route.js.map +1 -1
  117. package/dist/lib/store.d.ts.map +1 -1
  118. package/dist/lib/store.js +31 -31
  119. package/dist/lib/store.js.map +1 -1
  120. package/dist/lib/structured-data.d.ts.map +1 -1
  121. package/dist/lib/twitter-card.d.ts.map +1 -1
  122. package/dist/lib/utils.d.ts.map +1 -1
  123. package/dist/lib/utils.js +3 -2
  124. package/dist/lib/utils.js.map +1 -1
  125. package/dist/mock.d.ts.map +1 -1
  126. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js +3 -2
  127. package/dist/node_modules/@selderee/plugin-htmlparser2/lib/hp2-builder.js.map +1 -1
  128. package/dist/node_modules/deepmerge/dist/cjs.js +17 -9
  129. package/dist/node_modules/deepmerge/dist/cjs.js.map +1 -1
  130. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js +2 -2
  131. package/dist/node_modules/dom-serializer/lib/esm/foreignNames.js.map +1 -1
  132. package/dist/node_modules/dom-serializer/lib/esm/index.js +10 -15
  133. package/dist/node_modules/dom-serializer/lib/esm/index.js.map +1 -1
  134. package/dist/node_modules/domelementtype/lib/esm/index.js +12 -12
  135. package/dist/node_modules/domelementtype/lib/esm/index.js.map +1 -1
  136. package/dist/node_modules/domhandler/lib/esm/index.js +4 -3
  137. package/dist/node_modules/domhandler/lib/esm/index.js.map +1 -1
  138. package/dist/node_modules/domhandler/lib/esm/node.js +8 -7
  139. package/dist/node_modules/domhandler/lib/esm/node.js.map +1 -1
  140. package/dist/node_modules/entities/lib/esm/decode.js +33 -32
  141. package/dist/node_modules/entities/lib/esm/decode.js.map +1 -1
  142. package/dist/node_modules/entities/lib/esm/decode_codepoint.js +5 -5
  143. package/dist/node_modules/entities/lib/esm/decode_codepoint.js.map +1 -1
  144. package/dist/node_modules/entities/lib/esm/escape.js +14 -6
  145. package/dist/node_modules/entities/lib/esm/escape.js.map +1 -1
  146. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js +2 -2
  147. package/dist/node_modules/entities/lib/esm/generated/decode-data-html.js.map +1 -1
  148. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js +2 -2
  149. package/dist/node_modules/entities/lib/esm/generated/decode-data-xml.js.map +1 -1
  150. package/dist/node_modules/html-to-text/lib/html-to-text.js +45 -33
  151. package/dist/node_modules/html-to-text/lib/html-to-text.js.map +1 -1
  152. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js +25 -25
  153. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Parser.js.map +1 -1
  154. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js +76 -73
  155. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/Tokenizer.js.map +1 -1
  156. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js +4 -3
  157. package/dist/node_modules/html-to-text/node_modules/htmlparser2/lib/esm/index.js.map +1 -1
  158. package/dist/node_modules/leac/lib/leac.js +72 -72
  159. package/dist/node_modules/leac/lib/leac.js.map +1 -1
  160. package/dist/node_modules/parseley/lib/parseley.js +37 -33
  161. package/dist/node_modules/parseley/lib/parseley.js.map +1 -1
  162. package/dist/node_modules/peberminta/lib/core.js +4 -4
  163. package/dist/node_modules/peberminta/lib/core.js.map +1 -1
  164. package/dist/node_modules/selderee/lib/selderee.js +16 -10
  165. package/dist/node_modules/selderee/lib/selderee.js.map +1 -1
  166. package/dist/proxy/protected-route.d.ts.map +1 -1
  167. package/dist/proxy/protected-route.js +11 -6
  168. package/dist/proxy/protected-route.js.map +1 -1
  169. package/dist/proxy/proxy.d.ts +5 -4
  170. package/dist/proxy/proxy.d.ts.map +1 -1
  171. package/dist/proxy/proxy.js +26 -6
  172. package/dist/proxy/proxy.js.map +1 -1
  173. package/dist/proxy/route-auto-detection.d.ts.map +1 -1
  174. package/dist/proxy/route-auto-detection.js +26 -14
  175. package/dist/proxy/route-auto-detection.js.map +1 -1
  176. package/dist/proxy/route-proxy.d.ts.map +1 -1
  177. package/dist/proxy/route-proxy.js +22 -5
  178. package/dist/proxy/route-proxy.js.map +1 -1
  179. package/dist/server/context.d.ts +31 -15
  180. package/dist/server/context.d.ts.map +1 -1
  181. package/dist/server/context.js +156 -69
  182. package/dist/server/context.js.map +1 -1
  183. package/dist/server/handlers/auth.handler.d.ts.map +1 -1
  184. package/dist/server/handlers/auth.handler.js +4 -2
  185. package/dist/server/handlers/auth.handler.js.map +1 -1
  186. package/dist/server/handlers/captions.handler.d.ts.map +1 -1
  187. package/dist/server/handlers/captions.handler.js +4 -2
  188. package/dist/server/handlers/captions.handler.js.map +1 -1
  189. package/dist/server/handlers/collection.handler.d.ts.map +1 -1
  190. package/dist/server/handlers/collection.handler.js +2 -1
  191. package/dist/server/handlers/collection.handler.js.map +1 -1
  192. package/dist/server/handlers/error-response.js +6 -2
  193. package/dist/server/handlers/error-response.js.map +1 -1
  194. package/dist/server/handlers/index.handler.d.ts.map +1 -1
  195. package/dist/server/handlers/index.handler.js +2 -1
  196. package/dist/server/handlers/index.handler.js.map +1 -1
  197. package/dist/server/handlers/preview.handler.d.ts.map +1 -1
  198. package/dist/server/handlers/preview.handler.js +6 -3
  199. package/dist/server/handlers/preview.handler.js.map +1 -1
  200. package/dist/server/handlers/registry.handler.d.ts.map +1 -1
  201. package/dist/server/handlers/registry.handler.js +14 -9
  202. package/dist/server/handlers/registry.handler.js.map +1 -1
  203. package/dist/server/handlers/route.handler.d.ts.map +1 -1
  204. package/dist/server/handlers/route.handler.js +12 -3
  205. package/dist/server/handlers/route.handler.js.map +1 -1
  206. package/dist/server/handlers/sitemap.handler.d.ts.map +1 -1
  207. package/dist/server/handlers/sitemap.handler.js +12 -9
  208. package/dist/server/handlers/sitemap.handler.js.map +1 -1
  209. package/dist/server/handlers/static-params.handler.d.ts.map +1 -1
  210. package/dist/server/handlers/static-params.handler.js +13 -8
  211. package/dist/server/handlers/static-params.handler.js.map +1 -1
  212. package/dist/server/handlers/vars.handler.d.ts.map +1 -1
  213. package/dist/server/handlers/vars.handler.js +5 -4
  214. package/dist/server/handlers/vars.handler.js.map +1 -1
  215. package/dist/server/helpers.d.ts +50 -0
  216. package/dist/server/helpers.d.ts.map +1 -0
  217. package/dist/server/helpers.js +60 -0
  218. package/dist/server/helpers.js.map +1 -0
  219. package/dist/server/layout.js +69 -34
  220. package/dist/server/layout.js.map +1 -1
  221. package/dist/server/lazy.d.ts +1 -0
  222. package/dist/server/lazy.d.ts.map +1 -1
  223. package/dist/server/lazy.js +3 -2
  224. package/dist/server/lazy.js.map +1 -1
  225. package/dist/server/local-api.d.ts.map +1 -1
  226. package/dist/server/local-api.js +12 -6
  227. package/dist/server/local-api.js.map +1 -1
  228. package/dist/server/metadata.d.ts +8 -5
  229. package/dist/server/metadata.d.ts.map +1 -1
  230. package/dist/server/metadata.js +21 -7
  231. package/dist/server/metadata.js.map +1 -1
  232. package/dist/server/mixer-payload.d.ts +1 -1
  233. package/dist/server/mixer-payload.d.ts.map +1 -1
  234. package/dist/server/mixer.d.ts +48 -6
  235. package/dist/server/mixer.d.ts.map +1 -1
  236. package/dist/server/mixer.js +235 -68
  237. package/dist/server/mixer.js.map +1 -1
  238. package/dist/server/page.d.ts +21 -5
  239. package/dist/server/page.d.ts.map +1 -1
  240. package/dist/server/page.js +74 -15
  241. package/dist/server/page.js.map +1 -1
  242. package/dist/server/utils.d.ts.map +1 -1
  243. package/dist/server/utils.js +4 -2
  244. package/dist/server/utils.js.map +1 -1
  245. package/dist/server/utmz.d.ts.map +1 -1
  246. package/dist/server/utmz.js +1 -1
  247. package/dist/server/utmz.js.map +1 -1
  248. package/dist/types.d.ts +79 -8
  249. package/dist/types.d.ts.map +1 -1
  250. package/package.json +16 -15
  251. package/src/exports/server.ts +1 -0
  252. package/src/lib/const.ts +15 -0
  253. package/src/lib/http.ts +15 -4
  254. package/src/proxy/proxy.ts +11 -4
  255. package/src/server/context.test.ts +467 -0
  256. package/src/server/context.ts +237 -78
  257. package/src/server/context.type-test.ts +106 -0
  258. package/src/server/helpers.ts +58 -0
  259. package/src/server/layout.ts +45 -39
  260. package/src/server/lazy.ts +1 -1
  261. package/src/server/metadata.ts +15 -7
  262. package/src/server/mixer.ts +57 -9
  263. package/src/server/page.ts +62 -17
  264. package/src/types.ts +109 -7
@@ -1 +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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"}
1
+ {"version":3,"file":"route-proxy.js","names":["error: unknown"],"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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"}
@@ -1,30 +1,46 @@
1
- import { IPageContext, TypedPageContext } from "../types.js";
1
+ import { IPageContext, LayoutContextOptions, LayoutOption, LayoutOptions, PageContextOptions, PageSelect, ReadonlyHeaders, TypedPageContext } from "../types.js";
2
+ import "server-only";
2
3
  import { CollectionSlug, SanitizedConfig } from "payload";
3
- import { headers } from "next/headers";
4
4
 
5
5
  //#region src/server/context.d.ts
6
+ /** JSON serialization with sorted keys, so equivalent options produce the same key. */
7
+ declare function stableStringify(value: unknown): string;
6
8
  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>>;
9
+ declare function setPageContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(data: Partial<TypedPageContext<TSlug, TSelect, TLayout>>): Promise<void>;
13
10
  /**
14
11
  * Initialises the full page context using Payload local API.
15
12
  *
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.
13
+ * Page and layout are fetched in parallel and memoized per request, so
14
+ * `getMetadata` and the page component share the same reads. The mixer
15
+ * context (routes + categories) is passed to every payload read so that
16
+ * payload-plugin-bowl can enrich responses, including populated documents.
17
+ *
18
+ * @example
19
+ * const { page, label, link } = await createPageContext(market, locale, 'post_detail', id, {
20
+ * config,
21
+ * depth: 2,
22
+ * select: { title: true, abstract: true, media: true, components: true },
23
+ * populate: { media: { url: true, alt: true, width: true, height: true, type: true } },
24
+ * });
25
+ */
26
+ declare function createPageContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(market: string, locale: string, slug: TSlug, id: string, options: PageContextOptions<TSlug, TSelect, TLayout>): Promise<TypedPageContext<TSlug, TSelect, TLayout>>;
27
+ /** @deprecated Use `createPageContext(market, locale, slug, id, { config, headers })`. */
28
+ declare function createPageContext<TSlug extends CollectionSlug>(market: string, locale: string, slug: TSlug, id: string, config: Promise<SanitizedConfig>, headers?: ReadonlyHeaders): Promise<TypedPageContext<TSlug>>;
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.
20
32
  */
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>>;
33
+ declare function createNotFoundContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(market: string, locale: string, slug: TSlug, id: string, options: PageContextOptions<TSlug, TSelect, TLayout>): Promise<TypedPageContext<TSlug, TSelect, TLayout>>;
34
+ /** @deprecated Use `createNotFoundContext(market, locale, slug, id, { config, headers })`. */
35
+ declare function createNotFoundContext<TSlug extends CollectionSlug>(market: string, locale: string, slug: TSlug, id: string, config: Promise<SanitizedConfig>, headers?: ReadonlyHeaders): Promise<TypedPageContext<TSlug>>;
22
36
  /**
23
37
  * Layout-only context — no page fetch. Used by RootLayout server components.
24
38
  */
25
- declare function createLayoutContext(market: string, locale: string, config: Promise<SanitizedConfig>, headers?: Awaited<ReturnType<typeof headers>>): Promise<IPageContext>;
39
+ declare function createLayoutContext(market: string, locale: string, options: LayoutContextOptions): Promise<IPageContext>;
40
+ /** @deprecated Use `createLayoutContext(market, locale, { config, headers })`. */
41
+ declare function createLayoutContext(market: string, locale: string, config: Promise<SanitizedConfig>, headers?: ReadonlyHeaders): Promise<IPageContext>;
26
42
  //# sourceMappingURL=context.d.ts.map
27
43
 
28
44
  //#endregion
29
- export { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext };
45
+ export { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext, stableStringify };
30
46
  //# sourceMappingURL=context.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"context.d.ts","names":[],"sources":["../../src/server/context.ts"],"sourcesContent":[],"mappings":";;;;;;iBA6DgB,eAAA;AAAA,iBAwEM,cAxES,CAAA,cAwEoB,cAxEpB,GAwEqC,cAxErC,CAAA,CAAA,CAAA,EAwEwD,OAxExD,CAwEgE,gBAxEhE,CAwEiF,KAxEjF,CAAA,CAAA;AAwET,iBAUA,cAVc,CAAA,cAUe,cAVf,EAAA,gBAU+C,UAV/C,CAU0D,KAV1D,CAAA,GAAA,SAAA,EAAA,gBAU8F,YAV9F,GAU6G,aAV7G,CAAA,CAAA,IAAA,EAW5B,OAX4B,CAWpB,gBAXoB,CAWH,KAXG,EAWI,OAXJ,EAWa,OAXb,CAAA,CAAA,CAAA,EAWsB,OAXtB,CAAA,IAAA,CAAA;;;;;;;AAA0D;AAU9F;;;;;;;;;AACiD,iBAwBjC,iBAxBiC,CAAA,cAwBD,cAxBC,EAAA,gBAwB+B,UAxB/B,CAwB0C,KAxB1C,CAAA,GAAA,SAAA,EAAA,gBAwB8E,YAxB9E,GAwB6F,aAxB7F,CAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EA2BzC,KA3ByC,EAAA,EAAA,EAAA,MAAA,EAAA,OAAA,EA6BtC,kBA7BsC,CA6BnB,KA7BmB,EA6BZ,OA7BY,EA6BH,OA7BG,CAAA,CAAA,EA8B9C,OA9B8C,CA8BtC,gBA9BsC,CA8BrB,KA9BqB,EA8Bd,OA9Bc,EA8BL,OA9BK,CAAA,CAAA;;AAAzC,iBAgCQ,iBAhCR,CAAA,cAgCwC,cAhCxC,CAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EAmCA,KAnCA,EAAA,EAAA,EAAA,MAAA,EAAA,MAAA,EAqCE,OArCF,CAqCU,eArCV,CAAA,EAAA,OAAA,CAAA,EAsCI,eAtCJ,CAAA,EAuCL,OAvCK,CAuCG,gBAvCH,CAuCoB,KAvCpB,CAAA,CAAA;;AAAkD;AAwB1D;;AAAgD,iBAoEhC,qBApEgC,CAAA,cAoEI,cApEJ,EAAA,gBAoEoC,UApEpC,CAoE+C,KApE/C,CAAA,GAAA,SAAA,EAAA,gBAoEmF,YApEnF,GAoEkG,aApElG,CAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EAuExC,KAvEwC,EAAA,EAAA,EAAA,MAAA,EAAA,OAAA,EAyErC,kBAzEqC,CAyElB,KAzEkB,EAyEX,OAzEW,EAyEF,OAzEE,CAAA,CAAA,EA0E7C,OA1E6C,CA0ErC,gBA1EqC,CA0EpB,KA1EoB,EA0Eb,OA1Ea,EA0EJ,OA1EI,CAAA,CAAA;;AAAgC,iBA4EhE,qBA5EgE,CAAA,cA4E5B,cA5E4B,CAAA,CAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,IAAA,EA+ExE,KA/EwE,EAAA,EAAA,EAAA,MAAA,EAAA,MAAA,EAiFtE,OAjFsE,CAiF9D,eAjF8D,CAAA,EAAA,OAAA,CAAA,EAkFpE,eAlFoE,CAAA,EAmF7E,OAnF6E,CAmFrE,gBAnFqE,CAmFpD,KAnFoD,CAAA,CAAA;;;;AAKlD,iBA+Fd,mBAAA,CA/Fc,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAkGnB,oBAlGmB,CAAA,EAmG3B,OAnG2B,CAmGnB,YAnGmB,CAAA;;AAAgB,iBAqG9B,mBAAA,CArG8B,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAwGpC,OAxGoC,CAwG5B,eAxG4B,CAAA,EAAA,OAAA,CAAA,EAyGlC,eAzGkC,CAAA,EA0G3C,OA1G2C,CA0GnC,YA1GmC,CAAA"}
@@ -1,18 +1,111 @@
1
- "use server";
1
+ import { DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH } from "../lib/const.js";
2
2
  import { getLabelFromLabels } from "../lib/label.js";
3
3
  import { getLink } from "../lib/link.js";
4
- import { getPayload } from "./mixer.js";
4
+ import { getPayload, resolveDraft } from "./mixer.js";
5
5
  import { getLayout } from "./layout.js";
6
6
  import { getPage } from "./page.js";
7
+ import { getIsDevelopment } from "@websolutespa/bom-core";
7
8
  import { cache } from "react";
9
+ import "server-only";
10
+
8
11
  //#region src/server/context.ts
9
12
  /**
13
+
10
14
  * Per-request context store (React.cache ensures a fresh Map per RSC render).
15
+
11
16
  * Safe to use inside Next.js server components — do NOT call this at build time.
17
+
12
18
  */
13
19
  const PageContext = cache(() => {
14
20
  return /* @__PURE__ */ new Map();
15
21
  });
22
+ /**
23
+
24
+ * Per-request memo of page and layout loads, keyed by a serialized string.
25
+
26
+ * React `cache` compares object arguments by identity, so options objects
27
+
28
+ * built inline by each caller would never hit: the key is serialized instead.
29
+
30
+ */
31
+ const RequestMemo = cache(() => {
32
+ return /* @__PURE__ */ new Map();
33
+ });
34
+ /** Payload instance + authenticated user, resolved once per request. */
35
+ const getRequestPayload = cache((config, headers, draft) => {
36
+ return getPayload({
37
+ config,
38
+ headers,
39
+ draft
40
+ });
41
+ });
42
+ function memoize(key, factory) {
43
+ const memo = RequestMemo();
44
+ let promise = memo.get(key);
45
+ if (!promise) {
46
+ promise = factory();
47
+ memo.set(key, promise);
48
+ promise.catch(() => memo.delete(key));
49
+ }
50
+ return promise;
51
+ }
52
+ /** JSON serialization with sorted keys, so equivalent options produce the same key. */
53
+ function stableStringify(value) {
54
+ return JSON.stringify(value, (_, item) => {
55
+ if (item && typeof item === "object" && !Array.isArray(item)) return Object.keys(item).sort().reduce((sorted, key) => {
56
+ sorted[key] = item[key];
57
+ return sorted;
58
+ }, {});
59
+ return item;
60
+ });
61
+ }
62
+ function getUserKey(user) {
63
+ if (user && "id" in user && user.id !== void 0 && user.id !== null) return `${user.collection || "user"}:${user.id}`;
64
+ return "guest";
65
+ }
66
+ function isPromiseLike(value) {
67
+ return !!value && typeof value.then === "function";
68
+ }
69
+ const warnedLegacySignatures = /* @__PURE__ */ new Set();
70
+ function warnLegacySignature(name, signature) {
71
+ if (getIsDevelopment() && !warnedLegacySignatures.has(name)) {
72
+ warnedLegacySignatures.add(name);
73
+ console.warn(`[bom-next] ${name}(..., config, headers) is deprecated. Use ${name}(${signature}, { config, headers }) instead.`);
74
+ }
75
+ }
76
+ function toPageOptions(name, optionsOrConfig, headers) {
77
+ if (isPromiseLike(optionsOrConfig)) {
78
+ warnLegacySignature(name, "market, locale, slug, id");
79
+ return {
80
+ config: optionsOrConfig,
81
+ headers
82
+ };
83
+ }
84
+ return optionsOrConfig;
85
+ }
86
+ function loadLayout(market, locale, payload, user, mixerContext, readOptions) {
87
+ const read = {
88
+ depth: readOptions.depth ?? DEFAULT_LAYOUT_DEPTH,
89
+ draft: readOptions.draft
90
+ };
91
+ const key = stableStringify([
92
+ "layout",
93
+ market,
94
+ locale,
95
+ getUserKey(user),
96
+ read
97
+ ]);
98
+ return memoize(key, () => getLayout(market, locale, payload, user, mixerContext, read));
99
+ }
100
+ function toPageContext(layout, page, user) {
101
+ return {
102
+ layout,
103
+ page: page ? { ...page } : void 0,
104
+ user,
105
+ label: getLabelFromLabels(layout?.labels ?? []),
106
+ link: (category) => layout ? getLink(category, layout) : void 0
107
+ };
108
+ }
16
109
  async function getPageContext() {
17
110
  return {
18
111
  layout: PageContext().get("layout"),
@@ -26,81 +119,75 @@ async function setPageContext(data) {
26
119
  const context = PageContext();
27
120
  for (const key in data) context.set(key, data[key]);
28
121
  }
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
- });
122
+ async function createPageContext(market, locale, slug, id, optionsOrConfig, headers) {
123
+ const options = toPageOptions("createPageContext", optionsOrConfig, headers);
124
+ const draft = await resolveDraft(options.draft);
125
+ const { payload, user, getContext } = await getRequestPayload(options.config, options.headers, draft);
38
126
  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
127
+ const pageRead = {
128
+ draft,
129
+ depth: options.depth ?? DEFAULT_PAGE_DEPTH,
130
+ select: options.select,
131
+ populate: options.populate,
132
+ joins: options.joins
49
133
  };
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
134
+ const pageKey = stableStringify([
135
+ "page",
136
+ market,
137
+ locale,
138
+ slug,
139
+ id,
140
+ getUserKey(user),
141
+ pageRead
142
+ ]);
143
+ const pagePromise = memoize(pageKey, () => getPage(slug, id, market, locale, payload, user, context, pageRead));
144
+ const layoutOptions = options.layout;
145
+ const layoutPromise = layoutOptions === false ? Promise.resolve(void 0) : (async () => loadLayout(market, locale, payload, user, context, {
146
+ depth: layoutOptions?.depth,
147
+ draft: layoutOptions?.draft === void 0 ? draft : await resolveDraft(layoutOptions.draft)
148
+ }))();
149
+ const [layout, page] = await Promise.all([layoutPromise, pagePromise]);
150
+ const pageContext = toPageContext(layout, page, user);
151
+ if (layout) await setPageContext(pageContext);
152
+ else await setPageContext({
153
+ page: pageContext.page,
154
+ user: pageContext.user
66
155
  });
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
156
  return pageContext;
81
157
  }
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
158
+ async function createNotFoundContext(market, locale, slug, id, optionsOrConfig, headers) {
159
+ const options = toPageOptions("createNotFoundContext", optionsOrConfig, headers);
160
+ const layout = options.layout === false ? false : {
161
+ ...options.layout,
162
+ draft: false
163
+ };
164
+ return createPageContext(market, locale, slug, id, {
165
+ ...options,
166
+ draft: false,
167
+ layout
89
168
  });
169
+ }
170
+ async function createLayoutContext(market, locale, optionsOrConfig, headers) {
171
+ let options;
172
+ if (isPromiseLike(optionsOrConfig)) {
173
+ warnLegacySignature("createLayoutContext", "market, locale");
174
+ options = {
175
+ config: optionsOrConfig,
176
+ headers
177
+ };
178
+ } else options = optionsOrConfig;
179
+ const draft = await resolveDraft(options.draft);
180
+ const { payload, user, getContext } = await getRequestPayload(options.config, options.headers, draft);
90
181
  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);
182
+ const layout = await loadLayout(market, locale, payload, user, context, {
183
+ depth: options.depth,
184
+ draft
185
+ });
186
+ const { page: _page,...pageContext } = toPageContext(layout, void 0, user);
187
+ await setPageContext(pageContext);
101
188
  return pageContext;
102
189
  }
103
- //#endregion
104
- export { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext };
105
190
 
191
+ //#endregion
192
+ export { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext, stableStringify };
106
193
  //# sourceMappingURL=context.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"context.js","names":["config: Promise<SanitizedConfig>","headers: ReadonlyHeaders | undefined","draft: boolean","key: string","factory: () => Promise<T>","value: unknown","user: User | null | undefined","name: string","signature: string","optionsOrConfig: PageContextOptions<TSlug, TSelect, TLayout> | Promise<SanitizedConfig>","headers?: ReadonlyHeaders","market: string","locale: string","payload: MixerPayload","user: User","mixerContext: MixerContext","readOptions: { depth?: number; draft: boolean }","layout: ILayout | undefined","page: TypedPage<TSlug, TSelect> | undefined","category: string","data: Partial<TypedPageContext<TSlug, TSelect, TLayout>>","slug: TSlug","id: string","pageRead: ReadOptions","optionsOrConfig: LayoutContextOptions | Promise<SanitizedConfig>","options: LayoutContextOptions"],"sources":["../../src/server/context.ts"],"sourcesContent":["import 'server-only';\r\n\r\nimport { getIsDevelopment, type ILayout } from '@websolutespa/bom-core';\r\nimport type { User } from '@websolutespa/payload-plugin-bowl';\r\nimport type { CollectionSlug, SanitizedConfig } from 'payload';\r\nimport { cache } from 'react';\r\nimport { DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH } from '../lib/const';\r\nimport { getLabelFromLabels } from '../lib/label';\r\nimport { getLink } from '../lib/link';\r\nimport type {\r\n IPageContext,\r\n LayoutContextOptions,\r\n LayoutOption,\r\n LayoutOptions,\r\n MixerContext,\r\n PageContextOptions,\r\n PageSelect,\r\n ReadOptions,\r\n ReadonlyHeaders,\r\n TypedPage,\r\n TypedPageContext\r\n} from '../types';\r\nimport { getLayout } from './layout';\r\nimport { getPayload, resolveDraft } from './mixer';\r\nimport type { MixerPayload } from './mixer-payload';\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\n/**\r\n * Per-request memo of page and layout loads, keyed by a serialized string.\r\n * React `cache` compares object arguments by identity, so options objects\r\n * built inline by each caller would never hit: the key is serialized instead.\r\n */\r\nconst RequestMemo = cache(() => {\r\n return new Map<string, Promise<unknown>>();\r\n});\r\n\r\n/** Payload instance + authenticated user, resolved once per request. */\r\nconst getRequestPayload = cache((config: Promise<SanitizedConfig>, headers: ReadonlyHeaders | undefined, draft: boolean) => {\r\n return getPayload({ config, headers, draft });\r\n});\r\n\r\nfunction memoize<T>(key: string, factory: () => Promise<T>): Promise<T> {\r\n const memo = RequestMemo();\r\n let promise = memo.get(key) as Promise<T> | undefined;\r\n if (!promise) {\r\n promise = factory();\r\n memo.set(key, promise);\r\n promise.catch(() => memo.delete(key));\r\n }\r\n return promise;\r\n}\r\n\r\n/** JSON serialization with sorted keys, so equivalent options produce the same key. */\r\nexport function stableStringify(value: unknown): string {\r\n return JSON.stringify(value, (_, item) => {\r\n if (item && typeof item === 'object' && !Array.isArray(item)) {\r\n return Object.keys(item).sort().reduce((sorted, key) => {\r\n sorted[key] = item[key];\r\n return sorted;\r\n }, {} as Record<string, unknown>);\r\n }\r\n return item;\r\n });\r\n}\r\n\r\nfunction getUserKey(user: User | null | undefined): string {\r\n if (user && 'id' in user && user.id !== undefined && user.id !== null) {\r\n return `${(user as { collection?: string }).collection || 'user'}:${user.id}`;\r\n }\r\n return 'guest';\r\n}\r\n\r\nfunction isPromiseLike(value: unknown): value is Promise<SanitizedConfig> {\r\n return !!value && typeof (value as PromiseLike<unknown>).then === 'function';\r\n}\r\n\r\nconst warnedLegacySignatures = new Set<string>();\r\n\r\nfunction warnLegacySignature(name: string, signature: string) {\r\n if (getIsDevelopment() && !warnedLegacySignatures.has(name)) {\r\n warnedLegacySignatures.add(name);\r\n console.warn(`[bom-next] ${name}(..., config, headers) is deprecated. Use ${name}(${signature}, { config, headers }) instead.`);\r\n }\r\n}\r\n\r\nfunction toPageOptions<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug>, TLayout extends LayoutOption>(\r\n name: string,\r\n optionsOrConfig: PageContextOptions<TSlug, TSelect, TLayout> | Promise<SanitizedConfig>,\r\n headers?: ReadonlyHeaders\r\n): PageContextOptions<TSlug, TSelect, TLayout> {\r\n if (isPromiseLike(optionsOrConfig)) {\r\n warnLegacySignature(name, 'market, locale, slug, id');\r\n return { config: optionsOrConfig, headers };\r\n }\r\n return optionsOrConfig;\r\n}\r\n\r\nfunction loadLayout(\r\n market: string,\r\n locale: string,\r\n payload: MixerPayload,\r\n user: User,\r\n mixerContext: MixerContext,\r\n readOptions: { depth?: number; draft: boolean }\r\n): Promise<ILayout> {\r\n const read = { depth: readOptions.depth ?? DEFAULT_LAYOUT_DEPTH, draft: readOptions.draft };\r\n const key = stableStringify(['layout', market, locale, getUserKey(user), read]);\r\n return memoize(key, () => getLayout(market, locale, payload, user, mixerContext, read));\r\n}\r\n\r\nfunction toPageContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug>, TLayout extends LayoutOption>(\r\n layout: ILayout | undefined,\r\n page: TypedPage<TSlug, TSelect> | undefined,\r\n user: User\r\n): TypedPageContext<TSlug, TSelect, TLayout> {\r\n return {\r\n layout,\r\n // shallow copy: the memoized document is shared by every caller in the request\r\n page: page ? { ...page } : undefined,\r\n user,\r\n label: getLabelFromLabels(layout?.labels ?? []),\r\n link: (category: string) => layout ? getLink(category, layout) : undefined,\r\n } as TypedPageContext<TSlug, TSelect, TLayout>;\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, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(\r\n data: Partial<TypedPageContext<TSlug, TSelect, TLayout>>\r\n) {\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 * Initialises the full page context using Payload local API.\r\n *\r\n * Page and layout are fetched in parallel and memoized per request, so\r\n * `getMetadata` and the page component share the same reads. The mixer\r\n * context (routes + categories) is passed to every payload read so that\r\n * payload-plugin-bowl can enrich responses, including populated documents.\r\n *\r\n * @example\r\n * const { page, label, link } = await createPageContext(market, locale, 'post_detail', id, {\r\n * config,\r\n * depth: 2,\r\n * select: { title: true, abstract: true, media: true, components: true },\r\n * populate: { media: { url: true, alt: true, width: true, height: true, type: true } },\r\n * });\r\n */\r\nexport function createPageContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(\r\n market: string,\r\n locale: string,\r\n slug: TSlug,\r\n id: string,\r\n options: PageContextOptions<TSlug, TSelect, TLayout>\r\n): Promise<TypedPageContext<TSlug, TSelect, TLayout>>;\r\n/** @deprecated Use `createPageContext(market, locale, slug, id, { config, headers })`. */\r\nexport 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?: ReadonlyHeaders\r\n): Promise<TypedPageContext<TSlug>>;\r\nexport async function createPageContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(\r\n market: string,\r\n locale: string,\r\n slug: TSlug,\r\n id: string,\r\n optionsOrConfig: PageContextOptions<TSlug, TSelect, TLayout> | Promise<SanitizedConfig>,\r\n headers?: ReadonlyHeaders\r\n): Promise<TypedPageContext<TSlug, TSelect, TLayout>> {\r\n const options = toPageOptions<TSlug, TSelect, TLayout>('createPageContext', optionsOrConfig, headers);\r\n\r\n const draft = await resolveDraft(options.draft);\r\n const { payload, user, getContext } = await getRequestPayload(options.config, options.headers, draft);\r\n const context = await getContext(market, locale);\r\n\r\n const pageRead: ReadOptions = {\r\n draft,\r\n depth: options.depth ?? DEFAULT_PAGE_DEPTH,\r\n select: options.select as ReadOptions['select'],\r\n populate: options.populate,\r\n joins: options.joins as ReadOptions['joins'],\r\n };\r\n const pageKey = stableStringify(['page', market, locale, slug, id, getUserKey(user), pageRead]);\r\n const pagePromise = memoize(pageKey, () =>\r\n getPage<TSlug, TSelect>(slug, id, market, locale, payload, user, context, pageRead)\r\n );\r\n\r\n const layoutOptions = options.layout;\r\n const layoutPromise = layoutOptions === false\r\n ? Promise.resolve(undefined)\r\n : (async () => loadLayout(market, locale, payload, user, context, {\r\n depth: layoutOptions?.depth,\r\n draft: layoutOptions?.draft === undefined ? draft : await resolveDraft(layoutOptions.draft),\r\n }))();\r\n\r\n const [layout, page] = await Promise.all([layoutPromise, pagePromise]);\r\n\r\n const pageContext = toPageContext<TSlug, TSelect, TLayout>(layout, page, user);\r\n\r\n if (layout) {\r\n await setPageContext(pageContext);\r\n } else {\r\n // layout skipped: keep any layout already stored for this request\r\n await setPageContext({ page: pageContext.page, user: pageContext.user });\r\n }\r\n\r\n return pageContext;\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 function createNotFoundContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(\r\n market: string,\r\n locale: string,\r\n slug: TSlug,\r\n id: string,\r\n options: PageContextOptions<TSlug, TSelect, TLayout>\r\n): Promise<TypedPageContext<TSlug, TSelect, TLayout>>;\r\n/** @deprecated Use `createNotFoundContext(market, locale, slug, id, { config, headers })`. */\r\nexport 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?: ReadonlyHeaders\r\n): Promise<TypedPageContext<TSlug>>;\r\nexport async function createNotFoundContext<TSlug extends CollectionSlug, TSelect extends PageSelect<TSlug> = undefined, TLayout extends LayoutOption = LayoutOptions>(\r\n market: string,\r\n locale: string,\r\n slug: TSlug,\r\n id: string,\r\n optionsOrConfig: PageContextOptions<TSlug, TSelect, TLayout> | Promise<SanitizedConfig>,\r\n headers?: ReadonlyHeaders\r\n): Promise<TypedPageContext<TSlug, TSelect, TLayout>> {\r\n const options = toPageOptions<TSlug, TSelect, TLayout>('createNotFoundContext', optionsOrConfig, headers);\r\n const layout = (options.layout === false ? false : { ...options.layout, draft: false }) as TLayout;\r\n return createPageContext<TSlug, TSelect, TLayout>(market, locale, slug, id, { ...options, draft: false, layout });\r\n}\r\n\r\n/**\r\n * Layout-only context — no page fetch. Used by RootLayout server components.\r\n */\r\nexport function createLayoutContext(\r\n market: string,\r\n locale: string,\r\n options: LayoutContextOptions\r\n): Promise<IPageContext>;\r\n/** @deprecated Use `createLayoutContext(market, locale, { config, headers })`. */\r\nexport function createLayoutContext(\r\n market: string,\r\n locale: string,\r\n config: Promise<SanitizedConfig>,\r\n headers?: ReadonlyHeaders\r\n): Promise<IPageContext>;\r\nexport async function createLayoutContext(\r\n market: string,\r\n locale: string,\r\n optionsOrConfig: LayoutContextOptions | Promise<SanitizedConfig>,\r\n headers?: ReadonlyHeaders\r\n): Promise<IPageContext> {\r\n let options: LayoutContextOptions;\r\n if (isPromiseLike(optionsOrConfig)) {\r\n warnLegacySignature('createLayoutContext', 'market, locale');\r\n options = { config: optionsOrConfig, headers };\r\n } else {\r\n options = optionsOrConfig;\r\n }\r\n\r\n const draft = await resolveDraft(options.draft);\r\n const { payload, user, getContext } = await getRequestPayload(options.config, options.headers, draft);\r\n const context = await getContext(market, locale);\r\n\r\n const layout = await loadLayout(market, locale, payload, user, context, { depth: options.depth, draft });\r\n\r\n const { page: _page, ...pageContext } = toPageContext<CollectionSlug, undefined, LayoutOptions>(layout, undefined, user);\r\n\r\n await setPageContext(pageContext);\r\n\r\n return pageContext as IPageContext;\r\n}\r\n"],"mappings":"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"}
@@ -1 +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"}
1
+ {"version":3,"file":"auth.handler.d.ts","names":[],"sources":["../../../src/server/handlers/auth.handler.ts"],"sourcesContent":[],"mappings":";;;;iBAMgB,gBAAA,SAAyB,QAAQ,6BACf,gBAAW,QAAA"}
@@ -1,6 +1,7 @@
1
1
  import { getPayload } from "../mixer.js";
2
2
  import { getHandlerErrorResponse } from "./error-response.js";
3
3
  import { headers } from "next/headers";
4
+
4
5
  //#region src/server/handlers/auth.handler.ts
5
6
  function getAuthMeHandler(config) {
6
7
  return async function(request) {
@@ -10,7 +11,8 @@ function getAuthMeHandler(config) {
10
11
  config,
11
12
  headers: headers$1
12
13
  });
13
- if ((user?.roles || []).includes("user") && "firstName" in user) return Response.json({
14
+ const roles = user?.roles || [];
15
+ if (roles.includes("user") && "firstName" in user) return Response.json({
14
16
  id: user.id,
15
17
  email: user.email,
16
18
  firstName: user.firstName,
@@ -23,7 +25,7 @@ function getAuthMeHandler(config) {
23
25
  }
24
26
  };
25
27
  }
28
+
26
29
  //#endregion
27
30
  export { getAuthMeHandler };
28
-
29
31
  //# sourceMappingURL=auth.handler.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"auth.handler.js","names":["config: Promise<SanitizedConfig>","request: NextRequest","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,iBAAiBA,QAAkC;AACjE,QAAO,eAAgBC,SAAsB;AAC3C,MAAI;GACF,MAAMC,YAAU,MAAMC,SAAY;GAClC,MAAM,EAAE,MAAM,GAAG,MAAM,WAAW;IAAE;IAAQ;GAAS,EAAC;GACtD,MAAM,QAAS,MAAM,SAAS,CAAE;AAChC,OAAI,MAAM,SAAS,OAAO,IAAI,eAAe,KAC3C,QAAO,SAAS,KAAK;IACnB,IAAI,KAAK;IACT,OAAO,KAAK;IACZ,WAAW,KAAK;IAChB,UAAU,KAAK;GAChB,GAAE,EAAE,QAAQ,IAAK,EAAC;AAErB,UAAO,SAAS,KAAK,MAAM,EAAE,QAAQ,IAAK,EAAC;EAC5C,SAAQ,OAAO;GACd,QAAQ,IAAI,0BAA0B,MAAM;AAC5C,UAAO,wBAAwB,MAAM;EACtC;CACF;AACF"}
@@ -1 +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"}
1
+ {"version":3,"file":"captions.handler.d.ts","names":[],"sources":["../../../src/server/handlers/captions.handler.ts"],"sourcesContent":[],"mappings":";;;;iBAIgB,cAAA,SAAuB,QAAQ,6BACb,gBAAW,QAAA"}
@@ -1,9 +1,11 @@
1
1
  import { getHandlerErrorResponse } from "./error-response.js";
2
+
2
3
  //#region src/server/handlers/captions.handler.ts
3
4
  function getCaptionsVTT(config) {
4
5
  return async function(request) {
5
6
  try {
6
- const title = request.nextUrl.searchParams.get("title") || "Untitled";
7
+ const searchParams = request.nextUrl.searchParams;
8
+ const title = searchParams.get("title") || "Untitled";
7
9
  const body = `WEBVTT
8
10
 
9
11
  00:00:01.000 --> 00:00:03.000
@@ -27,7 +29,7 @@ ${title ? `
27
29
  }
28
30
  };
29
31
  }
32
+
30
33
  //#endregion
31
34
  export { getCaptionsVTT };
32
-
33
35
  //# sourceMappingURL=captions.handler.js.map
@@ -1 +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"}
1
+ {"version":3,"file":"captions.handler.js","names":["config: Promise<SanitizedConfig>","request: NextRequest","error: unknown"],"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,eAAeA,QAAkC;AAC/D,QAAO,eAAgBC,SAAsB;AAC3C,MAAI;GACF,MAAM,eAAe,QAAQ,QAAQ;GACrC,MAAM,QAAQ,aAAa,IAAI,QAAQ,IAAI;GAC3C,MAAM,OAAiB,CAAC;;;;;AAK9B,EAAE,QAAQ,CAAC;;6BAEkB,EAAE,MAAM;AACrC,CAAC,GAAG,IAAI;AACF,UAAO,IAAI,SAAS,MAAM;IACxB,QAAQ;IACR,SAAS;KACP,gBAAgB;KAChB,mBAAmB;KACnB,gBAAgB;IACjB;GACF;EACF,SAAQC,OAAgB;GACvB,QAAQ,MAAM,wBAAwB,MAAM;AAC5C,UAAO,wBAAwB,MAAM;EACtC;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"collection.handler.d.ts","names":[],"sources":["../../../src/server/handlers/collection.handler.ts"],"mappings":";;;iBAUgB,oBAAA,SAA6B,QAAQ,6BACnB;UAAS;AADU;UAIzC;IAJI,WAAA,EAAA,MAAoB,EAAA;EAAA,CAAA,CAAA;AAAiB,CAAA,EAAA,GAKlD,OALkD,CAKlD,QALkD,CAAA;AAAR,iBAgF7B,qBAAA,CAhF6B,MAAA,EAgFC,OAhFD,CAgFS,eAhFT,CAAA,CAAA,EAAA,CAAA,OAAA,EAiFX,OAjFW,EAAA;EAAA,MAAA,EAiFF;AA5ExC,CAL0C,EAAA;EACX,MAAA,EAmFtB,OAnFsB,CAAA;IAAS,WAAA,EAAA,MAAA,EAAA;EAG/B,CAAA,CAAA;AACT,CAAA,EAAA,GAgFA,OAhFA,CAgFA,QAhFA,GAAA,SAAA,CAAA;AAAA,iBAwHa,sBAAA,CAxHb,MAAA,EAwH4C,OAxH5C,CAwHoD,eAxHpD,CAAA,CAAA,EAAA,CAAA,OAAA,EAyH+B,OAzH/B,EAAA;EAAA,MAAA,EAyHwC;AA9CW,CA3EnD,EAAA;EAAA,MAAA,EA4HS,OA5HT,CAAA;IA2Ea,WAAA,EAAA,MAAA,EAAqB;EAAA,CAAA,CAAA;AAAiB,CAAA,EAAA,GAkDnD,OAlDmD,CAkDnD,QAlDmD,GAAA,SAAA,CAAA;AAAR,iBAoF9B,uBAAA,CApF8B,MAAA,EAoFE,OApFF,CAoFU,eApFV,CAAA,CAAA,EAAA,CAAA,OAAA,EAqFZ,OArFY,EAAA;EAAA,MAAA,EAqFH;AAhFxC,CAL2C,EAAA;EACZ,MAAA,EAuFtB,OAvFsB,CAAA;IAAS,WAAA,EAAA,MAAA,EAAA;EAG/B,CAAA,CAAA;AACT,CAAA,EAAA,GAoFA,OApFA,CAoFA,QApFA,GAAA,SAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"collection.handler.d.ts","names":[],"sources":["../../../src/server/handlers/collection.handler.ts"],"sourcesContent":[],"mappings":";;;iBAUgB,oBAAA,SAA6B,QAAQ,6BACnB;UAAS;;UAG/B;IAJI,WAAA,EAAA,MAAoB,EAAA;EAAA,CAAA,CAAA;CAAA,EAAA,GAKjC,OALkD,CAKlD,QALkD,CAAA;AAAR,iBAgF7B,qBAAA,CAhF6B,MAAA,EAgFC,OAhFD,CAgFS,eAhFT,CAAA,CAAA,EAAA,CAAA,OAAA,EAiFX,OAjFW,EAAA;EAAA,MAAA,EAiFF;CAjFE,EAAA;EAAO,MAClB,EAmFtB,OAnFsB,CAAA;IAAS,WAAA,EAAA,MAAA,EAAA;EAAA,CAAA,CAAA;CAGxB,EAAA,GAiFhB,OAhFA,CAgFA,QAhFA,GAAA,SAAA,CAAA;AAAA,iBAwHa,sBAAA,CAxHb,MAAA,EAwH4C,OAxH5C,CAwHoD,eAxHpD,CAAA,CAAA,EAAA,CAAA,OAAA,EAyH+B,OAzH/B,EAAA;EAAA,MAAA,EAyHwC;CAzHxC,EAAA;EAAA,MAAA,EA4HS,OA5HT,CAAA;IA2Ea,WAAA,EAAA,MAAA,EAAqB;EAAA,CAAA,CAAA;CAAA,EAAA,GAkDlC,OAlDmD,CAkDnD,QAlDmD,GAAA,SAAA,CAAA;AAAR,iBAoF9B,uBAAA,CApF8B,MAAA,EAoFE,OApFF,CAoFU,eApFV,CAAA,CAAA,EAAA,CAAA,OAAA,EAqFZ,OArFY,EAAA;EAAA,MAAA,EAqFH;CArFG,EAAA;EAAO,MACnB,EAuFtB,OAvFsB,CAAA;IAAS,WAAA,EAAA,MAAA,EAAA;EAAA,CAAA,CAAA;CAGxB,EAAA,GAqFhB,OApFA,CAoFA,QApFA,GAAA,SAAA,CAAA"}
@@ -3,6 +3,7 @@ import { getHandlerErrorResponse } from "./error-response.js";
3
3
  import { getLocalApi } from "../local-api.js";
4
4
  import { qsDeserialize } from "@websolutespa/bom-core";
5
5
  import { headers } from "next/headers";
6
+
6
7
  //#region src/server/handlers/collection.handler.ts
7
8
  function collectionGetHandler(config) {
8
9
  return async function(request, { params: getParams }) {
@@ -160,7 +161,7 @@ function collectionDeleteHandler(config) {
160
161
  }
161
162
  };
162
163
  }
164
+
163
165
  //#endregion
164
166
  export { collectionDeleteHandler, collectionGetHandler, collectionPatchHandler, collectionPostHandler };
165
-
166
167
  //# sourceMappingURL=collection.handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collection.handler.js","names":["headers","getHeaders"],"sources":["../../../src/server/handlers/collection.handler.ts"],"sourcesContent":["\r\nimport { qsDeserialize } from '@websolutespa/bom-core';\r\nimport { headers as getHeaders } from 'next/headers';\r\nimport { CollectionSlug, GlobalSlug, SanitizedConfig } from 'payload';\r\nimport { getLocalApi } from '../local-api';\r\nimport { getPayload } from '../mixer';\r\nimport { getHandlerErrorResponse } from './error-response';\r\n\r\n// find a specific document by id or\r\n// find paginated documents\r\nexport function collectionGetHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const headers = await getHeaders();\r\n const { payload, user, getContext } = await getPayload({ config, headers });\r\n const collectionSlugs = payload.config.collections.map(x => x.slug);\r\n const globalSlugs = payload.config.globals.map(x => x.slug);\r\n const keys = [\r\n ...collectionSlugs,\r\n ...globalSlugs,\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections?.length === 0) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n const id: string = collections[1];\r\n const search = new URL(request.url).search;\r\n const params = qsDeserialize(search);\r\n const context = params.market && params.locale ? await getContext(params.market, params.locale) : undefined;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'keys', slug);\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const localApi = await getLocalApi(config, slug);\r\n if (id) {\r\n // find by id\r\n const item = await localApi.findOne({\r\n ...params,\r\n id,\r\n context,\r\n user,\r\n });\r\n if (item) {\r\n return Response.json(item);\r\n } else {\r\n return new Response('not found', {\r\n status: 404,\r\n statusText: 'not found',\r\n });\r\n }\r\n } else if (String(params.pagination) === 'true') {\r\n // find paginated documents\r\n const items = await localApi.findPaged({\r\n ...params,\r\n context,\r\n user,\r\n });\r\n return Response.json(items);\r\n } else {\r\n // find many\r\n const items = await localApi.findMany({\r\n ...params,\r\n context,\r\n user,\r\n });\r\n return Response.json(items);\r\n }\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionGet.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n// create a new document + post route\r\nexport function collectionPostHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const { payload } = await getPayload({ config });\r\n const keys = [\r\n ...payload.config.collections.map(x => x.slug),\r\n ...payload.config.globals.map(x => x.slug),\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections.length !== 1) {\r\n console.error('method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n // api post route pathname\r\n /*\r\n if (slug === 'route') {\r\n return routePost(store, request);\r\n }\r\n */\r\n // !!! todo post create\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionPost.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n// update a document by id\r\nexport function collectionPatchHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const { payload } = await getPayload({ config });\r\n const keys = [\r\n ...payload.config.collections.map(x => x.slug),\r\n ...payload.config.globals.map(x => x.slug),\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections.length !== 2) {\r\n console.error('method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n // !!! todo patch update\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionPatch.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n// delete an existing document by id\r\nexport function collectionDeleteHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const { payload } = await getPayload({ config });\r\n const keys = [\r\n ...payload.config.collections.map(x => x.slug),\r\n ...payload.config.globals.map(x => x.slug),\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections.length !== 2) {\r\n console.error('method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const id: string = collections[1];\r\n // !!! todo delete\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionDelete.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"collection.handler.js","names":["config: Promise<SanitizedConfig>","request: Request","headers","getHeaders","id: string","error: unknown"],"sources":["../../../src/server/handlers/collection.handler.ts"],"sourcesContent":["\r\nimport { qsDeserialize } from '@websolutespa/bom-core';\r\nimport { headers as getHeaders } from 'next/headers';\r\nimport { CollectionSlug, GlobalSlug, SanitizedConfig } from 'payload';\r\nimport { getLocalApi } from '../local-api';\r\nimport { getPayload } from '../mixer';\r\nimport { getHandlerErrorResponse } from './error-response';\r\n\r\n// find a specific document by id or\r\n// find paginated documents\r\nexport function collectionGetHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const headers = await getHeaders();\r\n const { payload, user, getContext } = await getPayload({ config, headers });\r\n const collectionSlugs = payload.config.collections.map(x => x.slug);\r\n const globalSlugs = payload.config.globals.map(x => x.slug);\r\n const keys = [\r\n ...collectionSlugs,\r\n ...globalSlugs,\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections?.length === 0) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n const id: string = collections[1];\r\n const search = new URL(request.url).search;\r\n const params = qsDeserialize(search);\r\n const context = params.market && params.locale ? await getContext(params.market, params.locale) : undefined;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'keys', slug);\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const localApi = await getLocalApi(config, slug);\r\n if (id) {\r\n // find by id\r\n const item = await localApi.findOne({\r\n ...params,\r\n id,\r\n context,\r\n user,\r\n });\r\n if (item) {\r\n return Response.json(item);\r\n } else {\r\n return new Response('not found', {\r\n status: 404,\r\n statusText: 'not found',\r\n });\r\n }\r\n } else if (String(params.pagination) === 'true') {\r\n // find paginated documents\r\n const items = await localApi.findPaged({\r\n ...params,\r\n context,\r\n user,\r\n });\r\n return Response.json(items);\r\n } else {\r\n // find many\r\n const items = await localApi.findMany({\r\n ...params,\r\n context,\r\n user,\r\n });\r\n return Response.json(items);\r\n }\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionGet.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n// create a new document + post route\r\nexport function collectionPostHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const { payload } = await getPayload({ config });\r\n const keys = [\r\n ...payload.config.collections.map(x => x.slug),\r\n ...payload.config.globals.map(x => x.slug),\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections.length !== 1) {\r\n console.error('method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n // api post route pathname\r\n /*\r\n if (slug === 'route') {\r\n return routePost(store, request);\r\n }\r\n */\r\n // !!! todo post create\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionPost.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n// update a document by id\r\nexport function collectionPatchHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const { payload } = await getPayload({ config });\r\n const keys = [\r\n ...payload.config.collections.map(x => x.slug),\r\n ...payload.config.globals.map(x => x.slug),\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections.length !== 2) {\r\n console.error('method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n // !!! todo patch update\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionPatch.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n// delete an existing document by id\r\nexport function collectionDeleteHandler(config: Promise<SanitizedConfig>) {\r\n return async function (request: Request, {\r\n params: getParams,\r\n }: {\r\n params: Promise<{ collections: string[]; }>;\r\n }) {\r\n try {\r\n const { payload } = await getPayload({ config });\r\n const keys = [\r\n ...payload.config.collections.map(x => x.slug),\r\n ...payload.config.globals.map(x => x.slug),\r\n ];\r\n keys.sort();\r\n const { collections } = await getParams;\r\n if (!Array.isArray(collections) || collections.length !== 2) {\r\n console.error('method not allowed', collections);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const slug = collections[0] as CollectionSlug | GlobalSlug;\r\n if (!keys.includes(slug)) {\r\n console.error('storeHandler.collectionGet', 'method not allowed', slug);\r\n return new Response('method not allowed', {\r\n status: 405,\r\n statusText: 'method not allowed',\r\n });\r\n }\r\n const id: string = collections[1];\r\n // !!! todo delete\r\n } catch (error: unknown) {\r\n const response = getHandlerErrorResponse(error);\r\n console.error('storeHandler.collectionDelete.error', response.status, error);\r\n return response;\r\n }\r\n };\r\n}\r\n"],"mappings":"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"}