@websolutespa/bom-next 4.0.0-next.0 → 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 (65) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +28 -0
  3. package/dist/client/extra.d.ts +3 -3
  4. package/dist/client/label.d.ts +3 -3
  5. package/dist/client/metadata.d.ts +3 -3
  6. package/dist/client/page.d.ts +3 -3
  7. package/dist/exports/server.d.ts +5 -4
  8. package/dist/exports/server.js +6 -5
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +2 -2
  11. package/dist/lib/const.d.ts +14 -2
  12. package/dist/lib/const.d.ts.map +1 -1
  13. package/dist/lib/const.js +23 -1
  14. package/dist/lib/const.js.map +1 -1
  15. package/dist/lib/http.d.ts +9 -0
  16. package/dist/lib/http.d.ts.map +1 -1
  17. package/dist/lib/http.js +21 -1
  18. package/dist/lib/http.js.map +1 -1
  19. package/dist/proxy/proxy.d.ts +5 -4
  20. package/dist/proxy/proxy.d.ts.map +1 -1
  21. package/dist/proxy/proxy.js +9 -4
  22. package/dist/proxy/proxy.js.map +1 -1
  23. package/dist/server/context.d.ts +31 -15
  24. package/dist/server/context.d.ts.map +1 -1
  25. package/dist/server/context.js +151 -82
  26. package/dist/server/context.js.map +1 -1
  27. package/dist/server/helpers.d.ts +50 -0
  28. package/dist/server/helpers.d.ts.map +1 -0
  29. package/dist/server/helpers.js +60 -0
  30. package/dist/server/helpers.js.map +1 -0
  31. package/dist/server/layout.js +44 -31
  32. package/dist/server/layout.js.map +1 -1
  33. package/dist/server/lazy.d.ts +1 -0
  34. package/dist/server/lazy.d.ts.map +1 -1
  35. package/dist/server/lazy.js +1 -3
  36. package/dist/server/lazy.js.map +1 -1
  37. package/dist/server/metadata.d.ts +8 -5
  38. package/dist/server/metadata.d.ts.map +1 -1
  39. package/dist/server/metadata.js +16 -6
  40. package/dist/server/metadata.js.map +1 -1
  41. package/dist/server/mixer.d.ts +48 -6
  42. package/dist/server/mixer.d.ts.map +1 -1
  43. package/dist/server/mixer.js +52 -11
  44. package/dist/server/mixer.js.map +1 -1
  45. package/dist/server/page.d.ts +21 -5
  46. package/dist/server/page.d.ts.map +1 -1
  47. package/dist/server/page.js +63 -15
  48. package/dist/server/page.js.map +1 -1
  49. package/dist/types.d.ts +79 -8
  50. package/dist/types.d.ts.map +1 -1
  51. package/package.json +6 -5
  52. package/src/exports/server.ts +1 -0
  53. package/src/lib/const.ts +15 -0
  54. package/src/lib/http.ts +15 -4
  55. package/src/proxy/proxy.ts +11 -4
  56. package/src/server/context.test.ts +467 -0
  57. package/src/server/context.ts +237 -78
  58. package/src/server/context.type-test.ts +106 -0
  59. package/src/server/helpers.ts +58 -0
  60. package/src/server/layout.ts +45 -39
  61. package/src/server/lazy.ts +1 -1
  62. package/src/server/metadata.ts +15 -7
  63. package/src/server/mixer.ts +57 -9
  64. package/src/server/page.ts +62 -17
  65. package/src/types.ts +109 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @websolutespa/bom-next
2
2
 
3
+ ## 4.0.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - Next: options signature for `createPageContext`, `createLayoutContext`, `createNotFoundContext` and `getMetadata`.
8
+ - New form: `createPageContext(market, locale, slug, id, { config, headers, depth, select, populate, joins, draft, layout })` and `createLayoutContext(market, locale, { config, headers, depth, draft })`. The positional `(config, headers)` form still works, logs a one-time deprecation warning in development.
9
+ - **Behaviour change:** pages are now read at `DEFAULT_PAGE_DEPTH` (2) and the layout at `DEFAULT_LAYOUT_DEPTH` (1), including through the legacy signature. Relationships and uploads (page media, media inside blocks, category, template, markets) are populated objects instead of ids; pass `depth: 0` to keep the previous shape.
10
+ - `select` narrows the page type; envelope fields (`id`, `slug`, `title`, `category`, `markets`, `meta`, `template`) are always read so `href`, alternates and breadcrumb keep working.
11
+ - Draft mode works: `draft: 'auto'` (default) reads Next `draftMode()`, draft reads use the draft mixer/route cache key and the authenticated user. `createNotFoundContext` always reads published content.
12
+ - Page and layout are loaded once per request (React `cache`, serialized key) and in parallel, so `getMetadata` and the page share the same reads. `getLayout` runs its reads in parallel.
13
+ - `getPage` returns `undefined` only for not found / not accessible documents and rethrows other errors.
14
+ - `buildBaseOptions` is deprecated in favour of `buildReadOptions({ user, locale, draft, depth, select, populate, joins })`.
15
+ - `context`, `page`, `layout` and `lazy` modules use `import 'server-only'` instead of `'use server'`, so their exports are no longer exposed as Server Actions. `server-only` is now a dependency; outside Next (scripts, Payload CLI, Vitest) `@websolutespa/bom-next/server` needs the `react-server` condition (`node --conditions=react-server`, Vitest `resolve.conditions`) or a `server-only` mock.
16
+ - `TypedPageContext.layout` follows the `layout` option: `undefined` with `layout: false`.
17
+ - New `createContextHelpers({ config, defaults })` factory and `Populated<T>` type helper.
18
+
19
+ ### Patch Changes
20
+
21
+ - feat: enhance page context options and helpers
22
+
3
23
  ## 4.0.0-next.0
4
24
 
5
25
  ### Major Changes
package/README.md CHANGED
@@ -9,3 +9,31 @@ Next module of the [BOM Repository](https://github.com/websolutespa/bom) by [web
9
9
  ---
10
10
 
11
11
  ##### *this library is for internal usage and not production ready*
12
+
13
+ ## Page context
14
+
15
+ ```ts
16
+ import { createPageContext, getMetadata } from '@websolutespa/bom-next/server';
17
+
18
+ export const generateMetadata = getMetadata('post_detail', config);
19
+
20
+ const { page, layout, label, link } = await createPageContext(market, locale, 'post_detail', id, {
21
+ config,
22
+ depth: 2, // default DEFAULT_PAGE_DEPTH
23
+ select: { title: true, abstract: true, media: true, components: true },
24
+ populate: { media: { url: true, alt: true, width: true, height: true, type: true } },
25
+ });
26
+
27
+ const { layout } = await createLayoutContext(market, locale, { config }); // depth: DEFAULT_LAYOUT_DEPTH (1)
28
+ ```
29
+
30
+ | option | default | |
31
+ |---|---|---|
32
+ | `depth` | `2` | `0` ids only, `1` direct relations/uploads (including those inside blocks), `2` relations of relations |
33
+ | `select` | – | Payload select; envelope fields (`id`, `slug`, `title`, `category`, `markets`, `meta`, `template`) are always read |
34
+ | `populate` | – | per-collection select for populated documents |
35
+ | `draft` | `'auto'` | `true` / `false`, or `'auto'` to read Next `draftMode()` |
36
+ | `layout` | `{ depth: 1 }` | layout options, or `false` to skip the layout |
37
+
38
+ Page and layout reads are memoized per request, so `getMetadata` and the page component share them when called with the same options.
39
+ To bind `config` once: `export const { createPageContext, createLayoutContext, getMetadata } = createContextHelpers({ config, defaults: { depth: 2 } });`
@@ -1,15 +1,15 @@
1
- import * as react0 from "react";
1
+ import * as react4 from "react";
2
2
 
3
3
  //#region src/client/extra.d.ts
4
4
  type IExtraContext = Record<string, any>;
5
- declare const ExtraContext: react0.Context<IExtraContext | undefined>;
5
+ declare const ExtraContext: react4.Context<IExtraContext | undefined>;
6
6
  declare function ExtraProvider({
7
7
  extra,
8
8
  children
9
9
  }: {
10
10
  extra?: Record<string, any>;
11
11
  children?: React.ReactNode;
12
- }): react0.JSX.Element;
12
+ }): react4.JSX.Element;
13
13
  //# sourceMappingURL=extra.d.ts.map
14
14
 
15
15
  //#endregion
@@ -1,13 +1,13 @@
1
- import * as react4 from "react";
1
+ import * as react0 from "react";
2
2
 
3
3
  //#region src/client/label.d.ts
4
4
  type ILabelContext = (key: string, params?: Record<string, any>) => string;
5
- declare const LabelContext: react4.Context<ILabelContext | undefined>;
5
+ declare const LabelContext: react0.Context<ILabelContext | undefined>;
6
6
  declare function LabelProvider({
7
7
  children
8
8
  }: {
9
9
  children?: React.ReactNode;
10
- }): react4.JSX.Element;
10
+ }): react0.JSX.Element;
11
11
  //# sourceMappingURL=label.d.ts.map
12
12
 
13
13
  //#endregion
@@ -2,7 +2,7 @@ import { OpenGraphType } from "../lib/open-graph.js";
2
2
  import { StructuredDataType } from "../lib/structured-data.js";
3
3
  import { TwitterCardType } from "../lib/twitter-card.js";
4
4
  import { IMetaData } from "../lib/meta-data.js";
5
- import * as react6 from "react";
5
+ import * as react8 from "react";
6
6
  import { ReactNode } from "react";
7
7
 
8
8
  //#region src/client/metadata.d.ts
@@ -29,14 +29,14 @@ type IMetaDataOptions = {
29
29
  twitterCard?: TwitterCardType;
30
30
  };
31
31
  type IMetaDataContext = IMetaData;
32
- declare const MetaDataContext: react6.Context<IMetaData | undefined>;
32
+ declare const MetaDataContext: react8.Context<IMetaData | undefined>;
33
33
  declare function MetaDataProvider({
34
34
  metaData,
35
35
  children
36
36
  }: {
37
37
  metaData: IMetaDataOptions;
38
38
  children?: ReactNode;
39
- }): react6.JSX.Element;
39
+ }): react8.JSX.Element;
40
40
  //# sourceMappingURL=metadata.d.ts.map
41
41
  //#endregion
42
42
  export { IMetaDataContext, IMetaDataOptions, MetaDataContext, MetaDataProvider };
@@ -1,10 +1,10 @@
1
1
  import * as _websolutespa_bom_core0 from "@websolutespa/bom-core";
2
2
  import { ILocalized, IPage } from "@websolutespa/bom-core";
3
- import * as react8 from "react";
3
+ import * as react6 from "react";
4
4
 
5
5
  //#region src/client/page.d.ts
6
6
  type IPageContext = ILocalized<IPage>;
7
- declare const PageContext: react8.Context<{
7
+ declare const PageContext: react6.Context<{
8
8
  [x: string]: unknown;
9
9
  id: _websolutespa_bom_core0.IEquatable;
10
10
  schema: string;
@@ -397,7 +397,7 @@ declare function PageProvider({
397
397
  }: {
398
398
  page: ILocalized<IPage>;
399
399
  children?: React.ReactNode;
400
- }): react8.JSX.Element;
400
+ }): react6.JSX.Element;
401
401
  //# sourceMappingURL=page.d.ts.map
402
402
  //#endregion
403
403
  export { IPageContext, PageContext, PageProvider };
@@ -1,4 +1,4 @@
1
- import { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext } from "../server/context.js";
1
+ import { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext, stableStringify } from "../server/context.js";
2
2
  import { getAuthMeHandler } from "../server/handlers/auth.handler.js";
3
3
  import { getCaptionsVTT } from "../server/handlers/captions.handler.js";
4
4
  import { collectionDeleteHandler, collectionGetHandler, collectionPatchHandler, collectionPostHandler } from "../server/handlers/collection.handler.js";
@@ -9,11 +9,12 @@ import { getRouteHandler } from "../server/handlers/route.handler.js";
9
9
  import { ISiteMap, getSiteMapIndex, getSiteMapXML, getSiteMapXSL } from "../server/handlers/sitemap.handler.js";
10
10
  import { getStaticParams, getStaticParamsFromPayload, getStaticParams_ } from "../server/handlers/static-params.handler.js";
11
11
  import { getVarsHandler } from "../server/handlers/vars.handler.js";
12
+ import { createContextHelpers } from "../server/helpers.js";
12
13
  import { decorateLazyComponents, withLazyProps } from "../server/lazy.js";
13
14
  import { getLocalApi } from "../server/local-api.js";
14
15
  import { getMetadata } from "../server/metadata.js";
15
- import { buildBaseOptions, filterRoutes, getAuthHeaders, getCacheKey, getContext, getMixerContext, getOptions, getPayload, getPayloadInstance, getRoutes, getSearchParams, setContext } from "../server/mixer.js";
16
- import { getPage } from "../server/page.js";
16
+ import { buildBaseOptions, buildReadOptions, filterRoutes, getAuthHeaders, getCacheKey, getContext, getMixerContext, getOptions, getPayload, getPayloadInstance, getRoutes, getSearchParams, resolveDraft, setContext } from "../server/mixer.js";
17
+ import { PAGE_ENVELOPE_FIELDS, getPage, withEnvelopeSelect } from "../server/page.js";
17
18
  import { getHrefBeforeRedirect, getNextUrl } from "../server/utils.js";
18
19
  import { getUtmz } from "../server/utmz.js";
19
- export { ISiteMap, buildBaseOptions, collectionDeleteHandler, collectionGetHandler, collectionPatchHandler, collectionPostHandler, createLayoutContext, createNotFoundContext, createPageContext, decorateLazyComponents, filterRoutes, getAuthHeaders, getAuthMeHandler, getCacheKey, getCaptionsVTT, getContext, getHrefBeforeRedirect, getLocalApi, getMetadata, getMixerContext, getNextUrl, getOptions, getPage, getPageContext, getPayload, getPayloadInstance, getRegistry, getRegistryItem, getRouteHandler, getRoutes, getSearchParams, getSiteMapIndex, getSiteMapXML, getSiteMapXSL, getStaticParams, getStaticParamsFromPayload, getStaticParams_, getUtmz, getVarsHandler, indexGetHandler, previewHandler, setContext, setPageContext, withLazyProps };
20
+ export { ISiteMap, PAGE_ENVELOPE_FIELDS, buildBaseOptions, buildReadOptions, collectionDeleteHandler, collectionGetHandler, collectionPatchHandler, collectionPostHandler, createContextHelpers, createLayoutContext, createNotFoundContext, createPageContext, decorateLazyComponents, filterRoutes, getAuthHeaders, getAuthMeHandler, getCacheKey, getCaptionsVTT, getContext, getHrefBeforeRedirect, getLocalApi, getMetadata, getMixerContext, getNextUrl, getOptions, getPage, getPageContext, getPayload, getPayloadInstance, getRegistry, getRegistryItem, getRouteHandler, getRoutes, getSearchParams, getSiteMapIndex, getSiteMapXML, getSiteMapXSL, getStaticParams, getStaticParamsFromPayload, getStaticParams_, getUtmz, getVarsHandler, indexGetHandler, previewHandler, resolveDraft, setContext, setPageContext, stableStringify, withEnvelopeSelect, withLazyProps };
@@ -1,7 +1,7 @@
1
1
  import { getHrefBeforeRedirect, getNextUrl } from "../server/utils.js";
2
- import { buildBaseOptions, filterRoutes, getAuthHeaders, getCacheKey, getContext, getMixerContext, getOptions, getPayload, getPayloadInstance, getRoutes, getSearchParams, setContext } from "../server/mixer.js";
3
- import { getPage } from "../server/page.js";
4
- import { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext } from "../server/context.js";
2
+ import { buildBaseOptions, buildReadOptions, filterRoutes, getAuthHeaders, getCacheKey, getContext, getMixerContext, getOptions, getPayload, getPayloadInstance, getRoutes, getSearchParams, resolveDraft, setContext } from "../server/mixer.js";
3
+ import { PAGE_ENVELOPE_FIELDS, getPage, withEnvelopeSelect } from "../server/page.js";
4
+ import { createLayoutContext, createNotFoundContext, createPageContext, getPageContext, setPageContext, stableStringify } from "../server/context.js";
5
5
  import { getAuthMeHandler } from "../server/handlers/auth.handler.js";
6
6
  import { getCaptionsVTT } from "../server/handlers/captions.handler.js";
7
7
  import { getLocalApi } from "../server/local-api.js";
@@ -13,8 +13,9 @@ import { getRouteHandler } from "../server/handlers/route.handler.js";
13
13
  import { getSiteMapIndex, getSiteMapXML, getSiteMapXSL } from "../server/handlers/sitemap.handler.js";
14
14
  import { getStaticParams, getStaticParamsFromPayload, getStaticParams_ } from "../server/handlers/static-params.handler.js";
15
15
  import { getVarsHandler } from "../server/handlers/vars.handler.js";
16
- import { decorateLazyComponents, withLazyProps } from "../server/lazy.js";
17
16
  import { getMetadata } from "../server/metadata.js";
17
+ import { createContextHelpers } from "../server/helpers.js";
18
+ import { decorateLazyComponents, withLazyProps } from "../server/lazy.js";
18
19
  import { getUtmz } from "../server/utmz.js";
19
20
 
20
- export { buildBaseOptions, collectionDeleteHandler, collectionGetHandler, collectionPatchHandler, collectionPostHandler, createLayoutContext, createNotFoundContext, createPageContext, decorateLazyComponents, filterRoutes, getAuthHeaders, getAuthMeHandler, getCacheKey, getCaptionsVTT, getContext, getHrefBeforeRedirect, getLocalApi, getMetadata, getMixerContext, getNextUrl, getOptions, getPage, getPageContext, getPayload, getPayloadInstance, getRegistry, getRegistryItem, getRouteHandler, getRoutes, getSearchParams, getSiteMapIndex, getSiteMapXML, getSiteMapXSL, getStaticParams, getStaticParamsFromPayload, getStaticParams_, getUtmz, getVarsHandler, indexGetHandler, previewHandler, setContext, setPageContext, withLazyProps };
21
+ export { PAGE_ENVELOPE_FIELDS, buildBaseOptions, buildReadOptions, collectionDeleteHandler, collectionGetHandler, collectionPatchHandler, collectionPostHandler, createContextHelpers, createLayoutContext, createNotFoundContext, createPageContext, decorateLazyComponents, filterRoutes, getAuthHeaders, getAuthMeHandler, getCacheKey, getCaptionsVTT, getContext, getHrefBeforeRedirect, getLocalApi, getMetadata, getMixerContext, getNextUrl, getOptions, getPage, getPageContext, getPayload, getPayloadInstance, getRegistry, getRegistryItem, getRouteHandler, getRoutes, getSearchParams, getSiteMapIndex, getSiteMapXML, getSiteMapXSL, getStaticParams, getStaticParamsFromPayload, getStaticParams_, getUtmz, getVarsHandler, indexGetHandler, previewHandler, resolveDraft, setContext, setPageContext, stableStringify, withEnvelopeSelect, withLazyProps };
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { StructuredDataType } from "./lib/structured-data.js";
4
4
  import { TwitterCardApp, TwitterCardBase, TwitterCardPlayer, TwitterCardSummary, TwitterCardSummaryLargeImage, TwitterCardType } from "./lib/twitter-card.js";
5
5
  import { IAlternate, IBrand, IMeta, IMetaData } from "./lib/meta-data.js";
6
6
  import { buildBreadcrumb } from "./lib/breadcrumb.js";
7
- import { guest } from "./lib/const.js";
7
+ import { DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH, guest } from "./lib/const.js";
8
8
  import { LabelService, getLabelFromLabels, interpolateText } from "./lib/label.js";
9
9
  import { LayoutDefaults } from "./lib/layout.defaults.js";
10
10
  import { getLink } from "./lib/link.js";
@@ -14,5 +14,5 @@ import { BuildStrategy, NextPhase, StoreStrategy, buildStrategy, nextPhase, stor
14
14
  import { getPublicUrl, resolveHref, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, trimTerminalSlash } from "./lib/utils.js";
15
15
  import { IMockCollection, IMockDocument, IMockGlobal, IMockLocale, IMockLocalized, IMockMedia, IMockMenu, IMockMenuItem, IMockPage, IMockStore } from "./mock.js";
16
16
  import { ErrorContext, RequestInfo } from "./instrumentation/types.js";
17
- import { BaseOptions, ComponentContext, ComponentProps, IContext, IEndUser, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, INullableLazyableProps, IPageContext, IUser, LayoutContext, LocalProvider, MarketLocaleParams, MixerContext, NotFoundContext, NotFoundParams, PageContext, PageDocument, PageLayoutContext, PageParams, PartialPageProps, ReadonlyHeaders, SearchParams, TypedPage, TypedPageContext } from "./types.js";
18
- export { ApiRequestOptions, BaseOptions, BuildStrategy, ComponentContext, ComponentProps, ErrorContext, IAlternate, IBrand, IContext, IEndUser, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, IMeta, IMetaData, IMockCollection, IMockDocument, IMockGlobal, IMockLocale, IMockLocalized, IMockMedia, IMockMenu, IMockMenuItem, IMockPage, IMockStore, INullableLazyableProps, IPageContext, IPaginationInfo, IPaginationItem, IPaginationOptions, IUser, LabelService, LayoutContext, LayoutDefaults, LocalProvider, MarketLocaleParams, MixerContext, NextPhase, NotFoundContext, NotFoundParams, OpenGraphArticle, OpenGraphAudio, OpenGraphBase, OpenGraphBook, OpenGraphBusiness, OpenGraphImage, OpenGraphMusic, OpenGraphPlace, OpenGraphProduct, OpenGraphProductGroup, OpenGraphProfile, OpenGraphRestaurant, OpenGraphType, OpenGraphVideo, OpenGraphWebsite, PageContext, PageDocument, PageLayoutContext, PageParams, PartialPageProps, ReadonlyHeaders, RequestInfo, SearchParams, StoreStrategy, StructuredDataType, TwitterCardApp, TwitterCardBase, TwitterCardPlayer, TwitterCardSummary, TwitterCardSummaryLargeImage, TwitterCardType, TypedPage, TypedPageContext, buildBreadcrumb, buildStrategy, getLabelFromLabels, getLink, getLocalApiRequestOptions, getLocalApiUrl, getMoreItems, getPagedItems, getPaginationInfo, getPublicUrl, getRemoteApiRequestOptions, getRouteLinkCategory, guest, interpolateText, isPaginationInfo, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, newRouteLink, nextPhase, resolveHref, resolveRoute, routeToLink, routeToRouteLink, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, storeCacheDuration, storeStrategy, trimTerminalSlash };
17
+ import { BaseOptions, ComponentContext, ComponentProps, DraftOption, IContext, IEndUser, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, INullableLazyableProps, IPageContext, IUser, LayoutContext, LayoutContextOptions, LayoutFor, LayoutOption, LayoutOptions, LocalProvider, MarketLocaleParams, MixerContext, NotFoundContext, NotFoundParams, PageContext, PageContextOptions, PageDocument, PageEnvelope, PageEnvelopeField, PageLayoutContext, PageParams, PageSelect, PartialPageProps, Populated, ReadOptions, ReadonlyHeaders, SearchParams, TypedPage, TypedPageContext, WithEnvelopeSelect } from "./types.js";
18
+ export { ApiRequestOptions, BaseOptions, BuildStrategy, ComponentContext, ComponentProps, DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH, DraftOption, ErrorContext, IAlternate, IBrand, IContext, IEndUser, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, IMeta, IMetaData, IMockCollection, IMockDocument, IMockGlobal, IMockLocale, IMockLocalized, IMockMedia, IMockMenu, IMockMenuItem, IMockPage, IMockStore, INullableLazyableProps, IPageContext, IPaginationInfo, IPaginationItem, IPaginationOptions, IUser, LabelService, LayoutContext, LayoutContextOptions, LayoutDefaults, LayoutFor, LayoutOption, LayoutOptions, LocalProvider, MarketLocaleParams, MixerContext, NextPhase, NotFoundContext, NotFoundParams, OpenGraphArticle, OpenGraphAudio, OpenGraphBase, OpenGraphBook, OpenGraphBusiness, OpenGraphImage, OpenGraphMusic, OpenGraphPlace, OpenGraphProduct, OpenGraphProductGroup, OpenGraphProfile, OpenGraphRestaurant, OpenGraphType, OpenGraphVideo, OpenGraphWebsite, PageContext, PageContextOptions, PageDocument, PageEnvelope, PageEnvelopeField, PageLayoutContext, PageParams, PageSelect, PartialPageProps, Populated, ReadOptions, ReadonlyHeaders, RequestInfo, SearchParams, StoreStrategy, StructuredDataType, TwitterCardApp, TwitterCardBase, TwitterCardPlayer, TwitterCardSummary, TwitterCardSummaryLargeImage, TwitterCardType, TypedPage, TypedPageContext, WithEnvelopeSelect, buildBreadcrumb, buildStrategy, getLabelFromLabels, getLink, getLocalApiRequestOptions, getLocalApiUrl, getMoreItems, getPagedItems, getPaginationInfo, getPublicUrl, getRemoteApiRequestOptions, getRouteLinkCategory, guest, interpolateText, isPaginationInfo, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, newRouteLink, nextPhase, resolveHref, resolveRoute, routeToLink, routeToRouteLink, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, storeCacheDuration, storeStrategy, trimTerminalSlash };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getRouteLinkCategory, newRouteLink, resolveRoute, routeToLink, routeToRouteLink } from "./lib/route.js";
2
2
  import { buildBreadcrumb } from "./lib/breadcrumb.js";
3
- import { guest } from "./lib/const.js";
3
+ import { DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH, guest } from "./lib/const.js";
4
4
  import { getLocalApiRequestOptions, getLocalApiUrl, getRemoteApiRequestOptions, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut } from "./lib/http.js";
5
5
  import { LabelService, getLabelFromLabels, interpolateText } from "./lib/label.js";
6
6
  import { LayoutDefaults } from "./lib/layout.defaults.js";
@@ -9,4 +9,4 @@ import { getMoreItems, getPagedItems, getPaginationInfo, isPaginationInfo } from
9
9
  import { BuildStrategy, NextPhase, StoreStrategy, buildStrategy, nextPhase, storeCacheDuration, storeStrategy } from "./lib/store.js";
10
10
  import { getPublicUrl, resolveHref, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, trimTerminalSlash } from "./lib/utils.js";
11
11
 
12
- export { BuildStrategy, LabelService, LayoutDefaults, NextPhase, StoreStrategy, buildBreadcrumb, buildStrategy, getLabelFromLabels, getLink, getLocalApiRequestOptions, getLocalApiUrl, getMoreItems, getPagedItems, getPaginationInfo, getPublicUrl, getRemoteApiRequestOptions, getRouteLinkCategory, guest, interpolateText, isPaginationInfo, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, newRouteLink, nextPhase, resolveHref, resolveRoute, routeToLink, routeToRouteLink, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, storeCacheDuration, storeStrategy, trimTerminalSlash };
12
+ export { BuildStrategy, DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH, LabelService, LayoutDefaults, NextPhase, StoreStrategy, buildBreadcrumb, buildStrategy, getLabelFromLabels, getLink, getLocalApiRequestOptions, getLocalApiUrl, getMoreItems, getPagedItems, getPaginationInfo, getPublicUrl, getRemoteApiRequestOptions, getRouteLinkCategory, guest, interpolateText, isPaginationInfo, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, newRouteLink, nextPhase, resolveHref, resolveRoute, routeToLink, routeToRouteLink, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, storeCacheDuration, storeStrategy, trimTerminalSlash };
@@ -2,8 +2,20 @@ import { Config, User } from "@websolutespa/payload-plugin-bowl";
2
2
 
3
3
  //#region src/lib/const.d.ts
4
4
  declare const guest: (User & Config["user"]);
5
+ /**
6
+ * Default population depth for page documents read by `createPageContext`.
7
+ *
8
+ * - `0`: relationships and uploads are returned as ids.
9
+ * - `1`: direct relationships and uploads are populated, including those inside blocks.
10
+ * - `2`: relationships of relationships are populated too (e.g. the cover of a related card).
11
+ */
12
+ declare const DEFAULT_PAGE_DEPTH = 2;
13
+ /**
14
+ * Default population depth for the layout reads (app global, menus, labels, markets).
15
+ * `1` populates the app logo and menu media.
16
+ */
17
+ declare const DEFAULT_LAYOUT_DEPTH = 1;
5
18
  //# sourceMappingURL=const.d.ts.map
6
-
7
19
  //#endregion
8
- export { guest };
20
+ export { DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH, guest };
9
21
  //# sourceMappingURL=const.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"const.d.ts","names":[],"sources":["../../src/lib/const.ts"],"sourcesContent":[],"mappings":";;;cAEa,QAAsD,OAAO"}
1
+ {"version":3,"file":"const.d.ts","names":[],"sources":["../../src/lib/const.ts"],"sourcesContent":[],"mappings":";;;cAEa,QAAsD,OAAO;;AAA1E;;;;AAAgF;AAShF;AAMa,cANA,kBAAA,GAMoB,CAAA;;;;;cAApB,oBAAA"}
package/dist/lib/const.js CHANGED
@@ -3,7 +3,29 @@ const guest = {
3
3
  collection: "users",
4
4
  roles: ["guest"]
5
5
  };
6
+ /**
7
+
8
+ * Default population depth for page documents read by `createPageContext`.
9
+
10
+ *
11
+
12
+ * - `0`: relationships and uploads are returned as ids.
13
+
14
+ * - `1`: direct relationships and uploads are populated, including those inside blocks.
15
+
16
+ * - `2`: relationships of relationships are populated too (e.g. the cover of a related card).
17
+
18
+ */
19
+ const DEFAULT_PAGE_DEPTH = 2;
20
+ /**
21
+
22
+ * Default population depth for the layout reads (app global, menus, labels, markets).
23
+
24
+ * `1` populates the app logo and menu media.
25
+
26
+ */
27
+ const DEFAULT_LAYOUT_DEPTH = 1;
6
28
 
7
29
  //#endregion
8
- export { guest };
30
+ export { DEFAULT_LAYOUT_DEPTH, DEFAULT_PAGE_DEPTH, guest };
9
31
  //# sourceMappingURL=const.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"const.js","names":[],"sources":["../../src/lib/const.ts"],"sourcesContent":["import type { Config, User } from '@websolutespa/payload-plugin-bowl';\r\n\r\nexport const guest = { collection: 'users', roles: ['guest'] } as (User & Config['user']);\r\n"],"mappings":";AAEA,MAAa,QAAQ;CAAE,YAAY;CAAS,OAAO,CAAC,OAAQ;AAAE"}
1
+ {"version":3,"file":"const.js","names":[],"sources":["../../src/lib/const.ts"],"sourcesContent":["import type { Config, User } from '@websolutespa/payload-plugin-bowl';\r\n\r\nexport const guest = { collection: 'users', roles: ['guest'] } as (User & Config['user']);\r\n\r\n/**\r\n * Default population depth for page documents read by `createPageContext`.\r\n *\r\n * - `0`: relationships and uploads are returned as ids.\r\n * - `1`: direct relationships and uploads are populated, including those inside blocks.\r\n * - `2`: relationships of relationships are populated too (e.g. the cover of a related card).\r\n */\r\nexport const DEFAULT_PAGE_DEPTH = 2;\r\n\r\n/**\r\n * Default population depth for the layout reads (app global, menus, labels, markets).\r\n * `1` populates the app logo and menu media.\r\n */\r\nexport const DEFAULT_LAYOUT_DEPTH = 1;\r\n"],"mappings":";AAEA,MAAa,QAAQ;CAAE,YAAY;CAAS,OAAO,CAAC,OAAQ;AAAE;;;;;;;;;;;;;;AAS9D,MAAa,qBAAqB;;;;;;;;AAMlC,MAAa,uBAAuB"}
@@ -2,6 +2,15 @@ import { FetchRequestOptions } from "@websolutespa/bom-core";
2
2
 
3
3
  //#region src/lib/http.d.ts
4
4
  type ApiRequestOptions = FetchRequestOptions;
5
+ /**
6
+ * Default options for requests to this app's own API.
7
+ *
8
+ * Server-side calls (proxy, handlers) target the request's deployment URL,
9
+ * which Vercel Deployment Protection answers with 401. When "Protection Bypass
10
+ * for Automation" is enabled, Vercel exposes VERCEL_AUTOMATION_BYPASS_SECRET;
11
+ * sending it as `x-vercel-protection-bypass` lets these calls through. The
12
+ * secret is never sent from the browser.
13
+ */
5
14
  declare function getLocalApiRequestOptions(): ApiRequestOptions;
6
15
  declare function getRemoteApiRequestOptions(token?: string): ApiRequestOptions;
7
16
  declare function getLocalApiUrl(pathname: string, origin?: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","names":[],"sources":["../../src/lib/http.ts"],"sourcesContent":[],"mappings":";;;KAKY,iBAAA,GAAoB;iBAEhB,yBAAA,CAAA,GAA6B;AAFjC,iBASI,0BAAA,CATgB,KAAmB,CAAA,EAAA,MAAA,CAAA,EASS,iBATT;AAEnC,iBA4BA,cAAA,CA5ByB,QAAI,EAAA,MAAA,EAAA,MAAiB,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAO9C,iBA2BM,aA3BoB,CAAA,IAAA,OAAkB,CAAA,CAAA,QAAA,EAAiB,MAAA,EAAA,OAAA,CAAA,EA2BD,iBA3BC,EAAA,cA2B1C,CA3B0C,EAAA;EAqB7D,MAAA,EAAA,MAAA;EAMM,MAAA,EAAA,MAAA;CAAa,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAwI,OAAxI,CAAgJ,CAAhJ,CAAA;AAAyC,iBActD,WAdsD,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAcP,iBAdO,EAAA,cAAsG,CAAtG,EAAA;EAAsB,MAAiF,EAAA,MAAA;EAAC,MAAT,EAAA,MAAA;AAAO,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAcd,OAdc,CAcN,CAdM,CAAA;AAc5J,iBAIA,YAJW,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAIwD,iBAJxD,EAAA,cAA0D,CAA1D,EAAA;EAAA,MAAA,EAAA,MAAA;EAAA,MAAoC,EAAA,MAAA;CAAsB,CAAA,EAI4E,OAJK,CAIG,CAJH,CAAA;AAAR,iBAQ9I,WAR8I,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAQ5E,iBAR4E,EAAA,cAIlI,CAJkI,EAAA;EAAO,MAAA,EAAA,MAAA;EAIrJ,MAAA,EAAA,MAAA;CAAY,CAAA,EAIoI,OAJpI,CAI4I,CAJ5I,CAAA;AAAuD,iBAQnE,aARmE,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAQC,iBARD,EAAA,cAAqF,CAArF,EAAA;EAAsB,MAAgE,EAAA,MAAA;EAAC,MAAT,EAAA,MAAA;AAAO,CAAA,CAAA,EAQN,OARM,CAQE,CARF,CAAA;AAIxJ,iBAQA,cARW,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAQuC,iBARvC,EAAA,cAA6E,CAA7E,EAAA;EAAA,MAAA,EAAA,MAAA;EAAA,MAAuD,EAAA,MAAA;CAAsB,CAAA,EAQwC,OARwB,CAQhB,CARgB,CAAA"}
1
+ {"version":3,"file":"http.d.ts","names":[],"sources":["../../src/lib/http.ts"],"sourcesContent":[],"mappings":";;;KAKY,iBAAA,GAAoB;;AAAhC;AAWA;AASA;AAqBA;AAMA;;;;AAA2K,iBApC3J,yBAAA,CAAA,CAoC2J,EApC9H,iBAoC8H;AAAO,iBA3BlK,0BAAA,CA2BkK,KAAA,CAAA,EAAA,MAAA,CAAA,EA3BtH,iBA2BsH;AAc5J,iBApBN,cAAA,CAoBiB,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAAA,iBAdX,aAcW,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAd2C,iBAc3C,EAAA,cAA4I,CAA5I,EAAA;EAAA,MAAoC,EAAA,MAAA;EAAsB,MAAiF,EAAA,MAAA;CAAC,EAAA,MAAT,CAAA,EAAA,MAAA,CAAA,EAdO,OAcP,CAde,CAcf,CAAA;AAAO,iBAArJ,WAAqJ,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAtG,iBAAsG,EAAA,cAIzI,CAJyI,EAAA;EAIrJ,MAAA,EAAA,MAAA;EAAY,MAAA,EAAA,MAAA;CAAA,EAAA,MAAuD,CAAA,EAAA,MAAA,CAAA,EAJ2E,OAI3E,CAJmF,CAInF,CAAA;AAAsF,iBAAzJ,YAAyJ,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAtF,iBAAsF,EAAA,cAI/K,CAJ+K,EAAA;EAAC,MAAT,EAAA,MAAA;EAAO,MAAA,EAAA,MAAA;AAI9K,CAAA,CAAA,EAJuK,OAIjJ,CAJyJ,CAIzJ,CAAA;AAAW,iBAAX,WAAW,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAuD,iBAAvD,EAAA,cAA8I,CAA9I,EAAA;EAAA,MAAuD,EAAA,MAAA;EAAsB,MAAgE,EAAA,MAAA;CAAC,CAAA,EAAT,OAAA,CAAQ,CAAR,CAAA;AAAO,iBAIvJ,aAJuJ,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAInF,iBAJmF,EAAA,cAI1I,CAJ0I,EAAA;EAIvJ,MAAA,EAAA,MAAA;EAAa,MAAA,EAAA,MAAA;CAAA,CAAA,EAAqI,OAA9E,CAAsF,CAAtF,CAAA;AAAsF,iBAI1J,cAJ0J,CAAA,IAAA,OAAA,CAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAIxG,iBAJwG,EAAA,cAIhL,CAJgL,EAAA;EAAC,MAAT,EAAA,MAAA;EAAO,MAAA,EAAA,MAAA;AAI/K,CAAA,CAAA,EAAsJ,OAAhI,CAAwI,CAAxI,CAAA"}
package/dist/lib/http.js CHANGED
@@ -3,8 +3,28 @@ import { httpFetch, isBrowser, merge } from "@websolutespa/bom-core";
3
3
  //#region src/lib/http.ts
4
4
  const API_URL = process.env.NEXT_PUBLIC_URL || "http://localhost:3000";
5
5
  const API_BASE = process.env.NEXT_PUBLIC_API || "/api";
6
+ /**
7
+
8
+ * Default options for requests to this app's own API.
9
+
10
+ *
11
+
12
+ * Server-side calls (proxy, handlers) target the request's deployment URL,
13
+
14
+ * which Vercel Deployment Protection answers with 401. When "Protection Bypass
15
+
16
+ * for Automation" is enabled, Vercel exposes VERCEL_AUTOMATION_BYPASS_SECRET;
17
+
18
+ * sending it as `x-vercel-protection-bypass` lets these calls through. The
19
+
20
+ * secret is never sent from the browser.
21
+
22
+ */
6
23
  function getLocalApiRequestOptions() {
7
- return { headers: {} };
24
+ const headers = {};
25
+ const bypassSecret = !isBrowser ? process.env.VERCEL_AUTOMATION_BYPASS_SECRET : void 0;
26
+ if (bypassSecret) headers["x-vercel-protection-bypass"] = bypassSecret;
27
+ return { headers };
8
28
  }
9
29
  function getRemoteApiRequestOptions(token) {
10
30
  if (token) return { headers: { Authorization: `JWT ${token}` } };
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","names":["token?: string","pathname: string","origin?: string","options: ApiRequestOptions","serviceOptions?: { locale: string, market: string }","url: string","payload?: unknown"],"sources":["../../src/lib/http.ts"],"sourcesContent":["import { FetchRequestOptions, httpFetch, isBrowser, merge } from '@websolutespa/bom-core';\r\n\r\nconst API_URL = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';\r\nconst API_BASE = process.env.NEXT_PUBLIC_API || '/api';\r\n\r\nexport type ApiRequestOptions = FetchRequestOptions;\r\n\r\nexport function getLocalApiRequestOptions(): ApiRequestOptions {\r\n return {\r\n headers: {\r\n },\r\n };\r\n}\r\n\r\nexport function getRemoteApiRequestOptions(token?: string): ApiRequestOptions {\r\n if (token) {\r\n // authenticated end user JWT token bearer (end_users)\r\n return {\r\n // mode: 'cors',\r\n headers: {\r\n Authorization: `JWT ${token}`,\r\n // Authorization: `Bearer ${token}`,\r\n },\r\n };\r\n } else {\r\n // guest user api key (users)\r\n return {\r\n // mode: 'cors',\r\n headers: {\r\n Authorization: `users API-Key ${process.env.STORE_API_KEY}`,\r\n },\r\n };\r\n }\r\n}\r\n\r\nexport function getLocalApiUrl(pathname: string, origin?: string): string {\r\n const url = `${isBrowser ? window.location.origin : (origin || API_URL)}${API_BASE}${pathname}`;\r\n // console.log('getLocalApiUrl', url);\r\n return url;\r\n}\r\n\r\nexport async function localApiFetch<T = unknown>(pathname: string, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }, origin?: string): Promise<T> {\r\n // console.log('localApiFetch', pathname, options, serviceOptions);\r\n const url = new URL(getLocalApiUrl(pathname, origin));\r\n if (serviceOptions) {\r\n url.searchParams.append('locale', serviceOptions.locale);\r\n url.searchParams.append('market', serviceOptions.market);\r\n }\r\n const apiOptions = merge({ ...getLocalApiRequestOptions() }, options);\r\n console.log('📡 localApiFetch', apiOptions.method, url.href);\r\n const apiResponse = await httpFetch(url.href, apiOptions);\r\n // console.log('localApiFetch', pathname, apiResponse);\r\n return apiResponse;\r\n}\r\n\r\nexport async function localApiGet<T = unknown>(url: string, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }, origin?: string): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'GET' }, serviceOptions, origin);\r\n}\r\n\r\nexport async function localApiPost<T = unknown>(url: string, payload?: unknown, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'POST', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);\r\n}\r\n\r\nexport async function localApiPut<T = unknown>(url: string, payload?: unknown, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'PUT', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);\r\n}\r\n\r\nexport async function localApiPatch<T = unknown>(url: string, payload?: unknown, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'PATCH', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);\r\n}\r\n\r\nexport async function localApiDelete<T = unknown>(url: string, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'DELETE' }, serviceOptions);\r\n}\r\n"],"mappings":";;;AAEA,MAAM,UAAU,QAAQ,IAAI,mBAAmB;AAC/C,MAAM,WAAW,QAAQ,IAAI,mBAAmB;AAIhD,SAAgB,4BAA+C;AAC7D,QAAO,EACL,SAAS,CACR,EACF;AACF;AAED,SAAgB,2BAA2BA,OAAmC;AAC5E,KAAI,MAEF,QAAO,EAEL,SAAS,EACP,eAAe,CAAC,IAAI,EAAE,OAAO,CAE9B,EACF;KAGD,QAAO,EAEL,SAAS,EACP,eAAe,CAAC,cAAc,EAAE,QAAQ,IAAI,eAAe,CAC5D,EACF;AAEJ;AAED,SAAgB,eAAeC,UAAkBC,QAAyB;CACxE,MAAM,MAAM,GAAG,YAAY,OAAO,SAAS,SAAU,UAAU,UAAW,WAAW,UAAU;AAE/F,QAAO;AACR;AAED,eAAsB,cAA2BD,UAAkBE,UAA6B,CAAE,GAAEC,gBAAqDF,QAA6B;CAEpL,MAAM,MAAM,IAAI,IAAI,eAAe,UAAU,OAAO;AACpD,KAAI,gBAAgB;EAClB,IAAI,aAAa,OAAO,UAAU,eAAe,OAAO;EACxD,IAAI,aAAa,OAAO,UAAU,eAAe,OAAO;CACzD;CACD,MAAM,aAAa,MAAM,EAAE,GAAG,2BAA2B,CAAE,GAAE,QAAQ;CACrE,QAAQ,IAAI,oBAAoB,WAAW,QAAQ,IAAI,KAAK;CAC5D,MAAM,cAAc,MAAM,UAAU,IAAI,MAAM,WAAW;AAEzD,QAAO;AACR;AAED,eAAsB,YAAyBG,KAAaF,UAA6B,CAAE,GAAEC,gBAAqDF,QAA6B;AAC7K,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;CAAO,GAAE,gBAAgB,OAAO;AAC1F;AAED,eAAsB,aAA0BG,KAAaC,SAAmBH,UAA6B,CAAE,GAAEC,gBAAiE;AAChL,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;EAAQ,MAAM,UAAU,KAAK,UAAU,QAAQ,GAAG;CAAW,GAAE,eAAe;AACxI;AAED,eAAsB,YAAyBC,KAAaC,SAAmBH,UAA6B,CAAE,GAAEC,gBAAiE;AAC/K,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;EAAO,MAAM,UAAU,KAAK,UAAU,QAAQ,GAAG;CAAW,GAAE,eAAe;AACvI;AAED,eAAsB,cAA2BC,KAAaC,SAAmBH,UAA6B,CAAE,GAAEC,gBAAiE;AACjL,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;EAAS,MAAM,UAAU,KAAK,UAAU,QAAQ,GAAG;CAAW,GAAE,eAAe;AACzI;AAED,eAAsB,eAA4BC,KAAaF,UAA6B,CAAE,GAAEC,gBAAiE;AAC/J,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;CAAU,GAAE,eAAe;AACrF"}
1
+ {"version":3,"file":"http.js","names":["headers: Record<string, string>","token?: string","pathname: string","origin?: string","options: ApiRequestOptions","serviceOptions?: { locale: string, market: string }","url: string","payload?: unknown"],"sources":["../../src/lib/http.ts"],"sourcesContent":["import { FetchRequestOptions, httpFetch, isBrowser, merge } from '@websolutespa/bom-core';\r\n\r\nconst API_URL = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';\r\nconst API_BASE = process.env.NEXT_PUBLIC_API || '/api';\r\n\r\nexport type ApiRequestOptions = FetchRequestOptions;\r\n\r\n/**\r\n * Default options for requests to this app's own API.\r\n *\r\n * Server-side calls (proxy, handlers) target the request's deployment URL,\r\n * which Vercel Deployment Protection answers with 401. When \"Protection Bypass\r\n * for Automation\" is enabled, Vercel exposes VERCEL_AUTOMATION_BYPASS_SECRET;\r\n * sending it as `x-vercel-protection-bypass` lets these calls through. The\r\n * secret is never sent from the browser.\r\n */\r\nexport function getLocalApiRequestOptions(): ApiRequestOptions {\r\n const headers: Record<string, string> = {};\r\n const bypassSecret = !isBrowser ? process.env.VERCEL_AUTOMATION_BYPASS_SECRET : undefined;\r\n if (bypassSecret) {\r\n headers['x-vercel-protection-bypass'] = bypassSecret;\r\n }\r\n return { headers };\r\n}\r\n\r\nexport function getRemoteApiRequestOptions(token?: string): ApiRequestOptions {\r\n if (token) {\r\n // authenticated end user JWT token bearer (end_users)\r\n return {\r\n // mode: 'cors',\r\n headers: {\r\n Authorization: `JWT ${token}`,\r\n // Authorization: `Bearer ${token}`,\r\n },\r\n };\r\n } else {\r\n // guest user api key (users)\r\n return {\r\n // mode: 'cors',\r\n headers: {\r\n Authorization: `users API-Key ${process.env.STORE_API_KEY}`,\r\n },\r\n };\r\n }\r\n}\r\n\r\nexport function getLocalApiUrl(pathname: string, origin?: string): string {\r\n const url = `${isBrowser ? window.location.origin : (origin || API_URL)}${API_BASE}${pathname}`;\r\n // console.log('getLocalApiUrl', url);\r\n return url;\r\n}\r\n\r\nexport async function localApiFetch<T = unknown>(pathname: string, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }, origin?: string): Promise<T> {\r\n // console.log('localApiFetch', pathname, options, serviceOptions);\r\n const url = new URL(getLocalApiUrl(pathname, origin));\r\n if (serviceOptions) {\r\n url.searchParams.append('locale', serviceOptions.locale);\r\n url.searchParams.append('market', serviceOptions.market);\r\n }\r\n const apiOptions = merge({ ...getLocalApiRequestOptions() }, options);\r\n console.log('📡 localApiFetch', apiOptions.method, url.href);\r\n const apiResponse = await httpFetch(url.href, apiOptions);\r\n // console.log('localApiFetch', pathname, apiResponse);\r\n return apiResponse;\r\n}\r\n\r\nexport async function localApiGet<T = unknown>(url: string, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }, origin?: string): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'GET' }, serviceOptions, origin);\r\n}\r\n\r\nexport async function localApiPost<T = unknown>(url: string, payload?: unknown, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'POST', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);\r\n}\r\n\r\nexport async function localApiPut<T = unknown>(url: string, payload?: unknown, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'PUT', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);\r\n}\r\n\r\nexport async function localApiPatch<T = unknown>(url: string, payload?: unknown, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'PATCH', body: payload ? JSON.stringify(payload) : undefined }, serviceOptions);\r\n}\r\n\r\nexport async function localApiDelete<T = unknown>(url: string, options: ApiRequestOptions = {}, serviceOptions?: { locale: string, market: string }): Promise<T> {\r\n return await localApiFetch<T>(url, { ...options, method: 'DELETE' }, serviceOptions);\r\n}\r\n"],"mappings":";;;AAEA,MAAM,UAAU,QAAQ,IAAI,mBAAmB;AAC/C,MAAM,WAAW,QAAQ,IAAI,mBAAmB;;;;;;;;;;;;;;;;;;AAahD,SAAgB,4BAA+C;CAC7D,MAAMA,UAAkC,CAAE;CAC1C,MAAM,eAAe,CAAC,YAAY,QAAQ,IAAI,kCAAkC;AAChF,KAAI,cACF,QAAQ,gCAAgC;AAE1C,QAAO,EAAE,QAAS;AACnB;AAED,SAAgB,2BAA2BC,OAAmC;AAC5E,KAAI,MAEF,QAAO,EAEL,SAAS,EACP,eAAe,CAAC,IAAI,EAAE,OAAO,CAE9B,EACF;KAGD,QAAO,EAEL,SAAS,EACP,eAAe,CAAC,cAAc,EAAE,QAAQ,IAAI,eAAe,CAC5D,EACF;AAEJ;AAED,SAAgB,eAAeC,UAAkBC,QAAyB;CACxE,MAAM,MAAM,GAAG,YAAY,OAAO,SAAS,SAAU,UAAU,UAAW,WAAW,UAAU;AAE/F,QAAO;AACR;AAED,eAAsB,cAA2BD,UAAkBE,UAA6B,CAAE,GAAEC,gBAAqDF,QAA6B;CAEpL,MAAM,MAAM,IAAI,IAAI,eAAe,UAAU,OAAO;AACpD,KAAI,gBAAgB;EAClB,IAAI,aAAa,OAAO,UAAU,eAAe,OAAO;EACxD,IAAI,aAAa,OAAO,UAAU,eAAe,OAAO;CACzD;CACD,MAAM,aAAa,MAAM,EAAE,GAAG,2BAA2B,CAAE,GAAE,QAAQ;CACrE,QAAQ,IAAI,oBAAoB,WAAW,QAAQ,IAAI,KAAK;CAC5D,MAAM,cAAc,MAAM,UAAU,IAAI,MAAM,WAAW;AAEzD,QAAO;AACR;AAED,eAAsB,YAAyBG,KAAaF,UAA6B,CAAE,GAAEC,gBAAqDF,QAA6B;AAC7K,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;CAAO,GAAE,gBAAgB,OAAO;AAC1F;AAED,eAAsB,aAA0BG,KAAaC,SAAmBH,UAA6B,CAAE,GAAEC,gBAAiE;AAChL,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;EAAQ,MAAM,UAAU,KAAK,UAAU,QAAQ,GAAG;CAAW,GAAE,eAAe;AACxI;AAED,eAAsB,YAAyBC,KAAaC,SAAmBH,UAA6B,CAAE,GAAEC,gBAAiE;AAC/K,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;EAAO,MAAM,UAAU,KAAK,UAAU,QAAQ,GAAG;CAAW,GAAE,eAAe;AACvI;AAED,eAAsB,cAA2BC,KAAaC,SAAmBH,UAA6B,CAAE,GAAEC,gBAAiE;AACjL,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;EAAS,MAAM,UAAU,KAAK,UAAU,QAAQ,GAAG;CAAW,GAAE,eAAe;AACzI;AAED,eAAsB,eAA4BC,KAAaF,UAA6B,CAAE,GAAEC,gBAAiE;AAC/J,QAAO,MAAM,cAAiB,KAAK;EAAE,GAAG;EAAS,QAAQ;CAAU,GAAE,eAAe;AACrF"}
@@ -11,10 +11,11 @@ type Middleware = (props: MiddlewareOptions) => NextMiddlewareResult | Promise<N
11
11
  /**
12
12
  * Returns the externally visible origin for an internal middleware request.
13
13
  *
14
- * Deployments commonly terminate TLS or change ports before forwarding to
15
- * Next.js. Honoring valid forwarded headers keeps resolver requests on the
16
- * public host and prevents an avoidable proxy redirect; direct-origin fallback
17
- * keeps local development and untrusted/invalid header values deterministic.
14
+ * BOM_INTERNAL_ORIGIN wins when set, for hosts whose public or deployment URL
15
+ * is unreachable from the server (protected previews, private networks,
16
+ * containers behind a gateway). Otherwise valid forwarded headers keep resolver
17
+ * requests on the public host; direct-origin fallback keeps local development
18
+ * and untrusted/invalid header values deterministic.
18
19
  */
19
20
  declare function getRequestOrigin(request: NextRequest): string;
20
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","names":[],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":[],"mappings":";;;;KAKY,iBAAA;WACD;EADC,IAAA,EAEJ,cAFqB;EAAA,QAAA,CAAA,EAAA,OAAA;CAAA;AAErB,KAGI,UAAA,GAHJ,CAAA,KAAA,EAGyB,iBAHzB,EAAA,GAG+C,oBAH/C,GAGsE,OAHtE,CAG8E,oBAH9E,CAAA;AAAc;AAGtB;;;;;;AAAqF;AAUrE,iBAAA,gBAAA,CAA0B,OAAW,EAAX,WAAW,CAAA,EAAA,MAAA;AAwBrD;;;;AAAiE;;;iBAAjD,WAAA,aAAwB,eAAe"}
1
+ {"version":3,"file":"proxy.d.ts","names":[],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":[],"mappings":";;;;KAKY,iBAAA;WACD;EADC,IAAA,EAEJ,cAFqB;EAAA,QAAA,CAAA,EAAA,OAAA;CAAA;AAErB,KAGI,UAAA,GAHJ,CAAA,KAAA,EAGyB,iBAHzB,EAAA,GAG+C,oBAH/C,GAGsE,OAHtE,CAG8E,oBAH9E,CAAA;AAAc;AAGtB;;;;;;AAAqF;AAcrF;AA2BgB,iBA3BA,gBAAA,CA2BW,OAAA,EA3Be,WA2Bf,CAAA,EAAA,MAAA;;;;AAAsC;;;;iBAAjD,WAAA,aAAwB,eAAe"}
@@ -1,22 +1,27 @@
1
1
  import { NextResponse } from "next/server";
2
2
 
3
3
  //#region src/proxy/proxy.ts
4
+ /** Optional fixed origin for internal resolver requests, e.g. `http://127.0.0.1:3000`. */
5
+ const INTERNAL_ORIGIN = process.env.BOM_INTERNAL_ORIGIN?.replace(/\/$/, "");
4
6
  /**
5
7
 
6
8
  * Returns the externally visible origin for an internal middleware request.
7
9
 
8
10
  *
9
11
 
10
- * Deployments commonly terminate TLS or change ports before forwarding to
12
+ * BOM_INTERNAL_ORIGIN wins when set, for hosts whose public or deployment URL
11
13
 
12
- * Next.js. Honoring valid forwarded headers keeps resolver requests on the
14
+ * is unreachable from the server (protected previews, private networks,
13
15
 
14
- * public host and prevents an avoidable proxy redirect; direct-origin fallback
16
+ * containers behind a gateway). Otherwise valid forwarded headers keep resolver
15
17
 
16
- * keeps local development and untrusted/invalid header values deterministic.
18
+ * requests on the public host; direct-origin fallback keeps local development
19
+
20
+ * and untrusted/invalid header values deterministic.
17
21
 
18
22
  */
19
23
  function getRequestOrigin(request) {
24
+ if (INTERNAL_ORIGIN) return INTERNAL_ORIGIN;
20
25
  const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
21
26
  const forwardedProtocol = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
22
27
  const forwardedPort = request.headers.get("x-forwarded-port")?.split(",")[0]?.trim();
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","names":["request: NextRequest"],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":["import { NextMiddlewareResult } from 'next/dist/server/web/types';\r\nimport { NextFetchEvent, NextRequest, NextResponse } from 'next/server';\r\n\r\n// export type Middleware = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type MiddlewareOptions = {\r\n request: NextRequest,\r\n next: NextFetchEvent,\r\n disabled?: boolean,\r\n};\r\nexport type Middleware = (props: MiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\r\n\r\n/**\r\n * Returns the externally visible origin for an internal middleware request.\r\n *\r\n * Deployments commonly terminate TLS or change ports before forwarding to\r\n * Next.js. Honoring valid forwarded headers keeps resolver requests on the\r\n * public host and prevents an avoidable proxy redirect; direct-origin fallback\r\n * keeps local development and untrusted/invalid header values deterministic.\r\n */\r\nexport function getRequestOrigin(request: NextRequest): string {\r\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\r\n const forwardedProtocol = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\r\n const forwardedPort = request.headers.get('x-forwarded-port')?.split(',')[0]?.trim();\r\n\r\n if (!forwardedHost || !['http', 'https'].includes(forwardedProtocol || '')) {\r\n return request.nextUrl.origin;\r\n }\r\n\r\n const protocol = forwardedProtocol!;\r\n const defaultPort = protocol === 'https' ? '443' : '80';\r\n const includesPort = forwardedHost.startsWith('[') ? forwardedHost.includes(']:') : forwardedHost.includes(':');\r\n const authority = forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost;\r\n\r\n return `${protocol}://${authority}`;\r\n}\r\n\r\n/**\r\n * Composes middleware into an ordered, short-circuiting proxy pipeline.\r\n *\r\n * A disabled proxy returns immediately, avoiding all downstream request work.\r\n * Otherwise each middleware can claim the response; stopping at its first\r\n * result prevents duplicate rewrites, redirects, and expensive policy checks.\r\n */\r\nexport function createProxy(...proxies: Middleware[]): Middleware {\r\n return async function ({ request, next, disabled }: MiddlewareOptions) {\r\n if (disabled) {\r\n return NextResponse.next();\r\n }\r\n let proxyResponse, i = 0;\r\n while (i < proxies.length && !proxyResponse) {\r\n const proxy = proxies[i] as Middleware;\r\n // console.log('createProxy.proxies', proxies.length, typeof proxy === 'function');\r\n if (typeof proxy === 'function') {\r\n proxyResponse = await proxy({ request, next });\r\n if (proxyResponse) {\r\n return proxyResponse;\r\n }\r\n }\r\n i++;\r\n }\r\n return NextResponse.next();\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,SAAgB,iBAAiBA,SAA8B;CAC7D,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;CACpF,MAAM,oBAAoB,QAAQ,QAAQ,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;CACzF,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;AAEpF,KAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,OAAQ,EAAC,SAAS,qBAAqB,GAAG,CACxE,QAAO,QAAQ,QAAQ;CAGzB,MAAM,WAAW;CACjB,MAAM,cAAc,aAAa,UAAU,QAAQ;CACnD,MAAM,eAAe,cAAc,WAAW,IAAI,GAAG,cAAc,SAAS,KAAK,GAAG,cAAc,SAAS,IAAI;CAC/G,MAAM,YAAY,iBAAiB,kBAAkB,eAAe,CAAC,eAAe,GAAG,cAAc,CAAC,EAAE,eAAe,GAAG;AAE1H,QAAO,GAAG,SAAS,GAAG,EAAE,WAAW;AACpC;;;;;;;;;;;;;;AASD,SAAgB,YAAY,GAAG,SAAmC;AAChE,QAAO,eAAgB,EAAE,SAAS,MAAM,UAA6B,EAAE;AACrE,MAAI,SACF,QAAO,aAAa,MAAM;EAE5B,IAAI,eAAe,IAAI;AACvB,SAAO,IAAI,QAAQ,UAAU,CAAC,eAAe;GAC3C,MAAM,QAAQ,QAAQ;AAEtB,OAAI,OAAO,UAAU,YAAY;IAC/B,gBAAgB,MAAM,MAAM;KAAE;KAAS;IAAM,EAAC;AAC9C,QAAI,cACF,QAAO;GAEV;GACD;EACD;AACD,SAAO,aAAa,MAAM;CAC3B;AACF"}
1
+ {"version":3,"file":"proxy.js","names":["request: NextRequest"],"sources":["../../src/proxy/proxy.ts"],"sourcesContent":["import { NextMiddlewareResult } from 'next/dist/server/web/types';\r\nimport { NextFetchEvent, NextRequest, NextResponse } from 'next/server';\r\n\r\n// export type Middleware = (request: NextRequest, next: NextFetchEvent) => Promise<NextMiddlewareResult>;\r\n\r\nexport type MiddlewareOptions = {\r\n request: NextRequest,\r\n next: NextFetchEvent,\r\n disabled?: boolean,\r\n};\r\nexport type Middleware = (props: MiddlewareOptions) => NextMiddlewareResult | Promise<NextMiddlewareResult>;\r\n\r\n/** Optional fixed origin for internal resolver requests, e.g. `http://127.0.0.1:3000`. */\r\nconst INTERNAL_ORIGIN = process.env.BOM_INTERNAL_ORIGIN?.replace(/\\/$/, '');\r\n\r\n/**\r\n * Returns the externally visible origin for an internal middleware request.\r\n *\r\n * BOM_INTERNAL_ORIGIN wins when set, for hosts whose public or deployment URL\r\n * is unreachable from the server (protected previews, private networks,\r\n * containers behind a gateway). Otherwise valid forwarded headers keep resolver\r\n * requests on the public host; direct-origin fallback keeps local development\r\n * and untrusted/invalid header values deterministic.\r\n */\r\nexport function getRequestOrigin(request: NextRequest): string {\r\n if (INTERNAL_ORIGIN) {\r\n return INTERNAL_ORIGIN;\r\n }\r\n const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\r\n const forwardedProtocol = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\r\n const forwardedPort = request.headers.get('x-forwarded-port')?.split(',')[0]?.trim();\r\n\r\n if (!forwardedHost || !['http', 'https'].includes(forwardedProtocol || '')) {\r\n return request.nextUrl.origin;\r\n }\r\n\r\n const protocol = forwardedProtocol!;\r\n const defaultPort = protocol === 'https' ? '443' : '80';\r\n const includesPort = forwardedHost.startsWith('[') ? forwardedHost.includes(']:') : forwardedHost.includes(':');\r\n const authority = forwardedPort && forwardedPort !== defaultPort && !includesPort ? `${forwardedHost}:${forwardedPort}` : forwardedHost;\r\n\r\n return `${protocol}://${authority}`;\r\n}\r\n\r\n/**\r\n * Composes middleware into an ordered, short-circuiting proxy pipeline.\r\n *\r\n * A disabled proxy returns immediately, avoiding all downstream request work.\r\n * Otherwise each middleware can claim the response; stopping at its first\r\n * result prevents duplicate rewrites, redirects, and expensive policy checks.\r\n */\r\nexport function createProxy(...proxies: Middleware[]): Middleware {\r\n return async function ({ request, next, disabled }: MiddlewareOptions) {\r\n if (disabled) {\r\n return NextResponse.next();\r\n }\r\n let proxyResponse, i = 0;\r\n while (i < proxies.length && !proxyResponse) {\r\n const proxy = proxies[i] as Middleware;\r\n // console.log('createProxy.proxies', proxies.length, typeof proxy === 'function');\r\n if (typeof proxy === 'function') {\r\n proxyResponse = await proxy({ request, next });\r\n if (proxyResponse) {\r\n return proxyResponse;\r\n }\r\n }\r\n i++;\r\n }\r\n return NextResponse.next();\r\n };\r\n}\r\n"],"mappings":";;;;AAaA,MAAM,kBAAkB,QAAQ,IAAI,qBAAqB,QAAQ,OAAO,GAAG;;;;;;;;;;;;;;;;;;AAW3E,SAAgB,iBAAiBA,SAA8B;AAC7D,KAAI,gBACF,QAAO;CAET,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;CACpF,MAAM,oBAAoB,QAAQ,QAAQ,IAAI,oBAAoB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;CACzF,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,mBAAmB,EAAE,MAAM,IAAI,CAAC,IAAI,MAAM;AAEpF,KAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,OAAQ,EAAC,SAAS,qBAAqB,GAAG,CACxE,QAAO,QAAQ,QAAQ;CAGzB,MAAM,WAAW;CACjB,MAAM,cAAc,aAAa,UAAU,QAAQ;CACnD,MAAM,eAAe,cAAc,WAAW,IAAI,GAAG,cAAc,SAAS,KAAK,GAAG,cAAc,SAAS,IAAI;CAC/G,MAAM,YAAY,iBAAiB,kBAAkB,eAAe,CAAC,eAAe,GAAG,cAAc,CAAC,EAAE,eAAe,GAAG;AAE1H,QAAO,GAAG,SAAS,GAAG,EAAE,WAAW;AACpC;;;;;;;;;;;;;;AASD,SAAgB,YAAY,GAAG,SAAmC;AAChE,QAAO,eAAgB,EAAE,SAAS,MAAM,UAA6B,EAAE;AACrE,MAAI,SACF,QAAO,aAAa,MAAM;EAE5B,IAAI,eAAe,IAAI;AACvB,SAAO,IAAI,QAAQ,UAAU,CAAC,eAAe;GAC3C,MAAM,QAAQ,QAAQ;AAEtB,OAAI,OAAO,UAAU,YAAY;IAC/B,gBAAgB,MAAM,MAAM;KAAE;KAAS;IAAM,EAAC;AAC9C,QAAI,cACF,QAAO;GAEV;GACD;EACD;AACD,SAAO,aAAa,MAAM;CAC3B;AACF"}
@@ -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"],"sourcesContent":[],"mappings":";;;;;iBAoBsB,6BAA6B,iBAAiB,mBAAmB,QAAQ,iBAAiB;iBAU1F,6BAA6B,sBAAsB,iBAAiB,SAAM;AAVhG;;;;AAAgH,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;;;AAAlB;AAU9F;;;;;AAAgG,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;;AAA0D,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"}
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"}