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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @websolutespa/bom-next
2
2
 
3
+ ## 4.0.0-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: add route template handling and tests for static parameters
8
+
3
9
  ## 4.0.0-next.1
4
10
 
5
11
  ### Minor Changes
@@ -1,7 +1,7 @@
1
- import * as react0 from "react";
1
+ import * as react8 from "react";
2
2
 
3
3
  //#region src/client/client.d.ts
4
- declare function Client(): react0.JSX.Element;
4
+ declare function Client(): react8.JSX.Element;
5
5
  //# sourceMappingURL=client.d.ts.map
6
6
 
7
7
  //#endregion
@@ -1,13 +1,13 @@
1
- import * as react0 from "react";
1
+ import * as react9 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: react0.Context<ILabelContext | undefined>;
5
+ declare const LabelContext: react9.Context<ILabelContext | undefined>;
6
6
  declare function LabelProvider({
7
7
  children
8
8
  }: {
9
9
  children?: React.ReactNode;
10
- }): react0.JSX.Element;
10
+ }): react9.JSX.Element;
11
11
  //# sourceMappingURL=label.d.ts.map
12
12
 
13
13
  //#endregion
@@ -1,16 +1,16 @@
1
1
  import { ILayout } from "@websolutespa/bom-core";
2
- import * as react2 from "react";
2
+ import * as react13 from "react";
3
3
 
4
4
  //#region src/client/layout.d.ts
5
5
  type ILayoutContext = ILayout;
6
- declare const LayoutContext: react2.Context<ILayoutContext | undefined>;
6
+ declare const LayoutContext: react13.Context<ILayoutContext | undefined>;
7
7
  declare function LayoutProvider({
8
8
  layout,
9
9
  children
10
10
  }: {
11
11
  layout: ILayout;
12
12
  children?: React.ReactNode;
13
- }): react2.JSX.Element;
13
+ }): react13.JSX.Element;
14
14
  //# sourceMappingURL=layout.d.ts.map
15
15
 
16
16
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","names":[],"sources":["../../src/client/layout.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,cAAA,GAAiB;cAEhB,eAAa,MAAA,CAAA,QAAA;iBAEV,cAAA;;;;EAJJ,MAAA,EAQF,OARE;EAEC,QAAA,CAAA,EAOA,KAAA,CAAM,SAP8D;CAAA,CAAA,EAQhF,MAAA,CAAA,GAAA,CAAA,OARgF"}
1
+ {"version":3,"file":"layout.d.ts","names":[],"sources":["../../src/client/layout.tsx"],"sourcesContent":[],"mappings":";;;;KAKY,cAAA,GAAiB;cAEhB,eAAa,OAAA,CAAA,QAAA;iBAEV,cAAA;;;;EAJJ,MAAA,EAQF,OARE;EAEC,QAAA,CAAA,EAOA,KAAA,CAAM,SAP8D;CAAA,CAAA,EAQhF,OAAA,CAAA,GAAA,CAAA,OARgF"}
@@ -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 react8 from "react";
5
+ import * as react6 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: react8.Context<IMetaData | undefined>;
32
+ declare const MetaDataContext: react6.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
- }): react8.JSX.Element;
39
+ }): react6.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 react6 from "react";
3
+ import * as react11 from "react";
4
4
 
5
5
  //#region src/client/page.d.ts
6
6
  type IPageContext = ILocalized<IPage>;
7
- declare const PageContext: react6.Context<{
7
+ declare const PageContext: react11.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
- }): react6.JSX.Element;
400
+ }): react11.JSX.Element;
401
401
  //# sourceMappingURL=page.d.ts.map
402
402
  //#endregion
403
403
  export { IPageContext, PageContext, PageProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","names":[],"sources":["../../src/client/page.tsx"],"sourcesContent":[],"mappings":";;;;;KAKY,YAAA,GAAe,WAAW;cAEzB,oBAAW;;MAAqD,uBAAA,CAAA;EAFjE,MAAA,EAAA,MAAA;EAAY,QAAA,EAAA;IAAc,UAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;IAAX,CAAA,CAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IAAU,QAAA,EAAA,GAAA,GAAA,MAAA;IAExB,MAAA,EAAA,CAAA,GAAgE,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,UAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,GAAA,OAAA,EAAA,MAAA,EAAA,EAAA,GAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAArD,GAAA,MAAA;IAAA,GAAA,EAAA,GAAA,GAAA,MAAA;IAER,QAAA,EAAA,CAAY,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAC1B,OAAA,EAAA,GAAA,GAAA,MAAA;IACA,SAAA,EAAA,GAAA,GAAA,MAAA;IAEiB,QAAA,EAAA,GAAA,GAAA,MAAA;IAAX,SAAA,EAAA,GAAA,GAAA,MAAA;IACK,QAAM,EAAA,CAAA,MAAA,QAAA,EAAA,uBAAA,gBAAA,CAAA;IAClB,UAAA,EAAA;MAAA,CAAA,WAAA,EAAA,MAAA,SAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBANe,YAAA;;;;QAIR,WAAW;aACN,KAAA,CAAM;IAClB,MAAA,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"page.d.ts","names":[],"sources":["../../src/client/page.tsx"],"sourcesContent":[],"mappings":";;;;;KAKY,YAAA,GAAe,WAAW;cAEzB,qBAAW;;MAAqD,uBAAA,CAAA;EAFjE,MAAA,EAAA,MAAA;EAAY,QAAA,EAAA;IAAc,UAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;IAAX,CAAA,CAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IAAU,QAAA,EAAA,GAAA,GAAA,MAAA;IAExB,MAAA,EAAA,CAAA,GAAgE,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,UAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,GAAA,OAAA,EAAA,MAAA,EAAA,EAAA,GAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAArD,GAAA,MAAA;IAAA,GAAA,EAAA,GAAA,GAAA,MAAA;IAER,QAAA,EAAA,CAAY,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAAA,MAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,EAAA,GAAA,MAAA;IAC1B,OAAA,EAAA,GAAA,GAAA,MAAA;IACA,SAAA,EAAA,GAAA,GAAA,MAAA;IAEiB,QAAA,EAAA,GAAA,GAAA,MAAA;IAAX,SAAA,EAAA,GAAA,GAAA,MAAA;IACK,QAAM,EAAA,CAAA,MAAA,QAAA,EAAA,uBAAA,gBAAA,CAAA;IAClB,UAAA,EAAA;MAAA,CAAA,WAAA,EAAA,MAAA,SAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBANe,YAAA;;;;QAIR,WAAW;aACN,KAAA,CAAM;IAClB,OAAA,CAAA,GAAA,CAAA"}
@@ -1,13 +1,13 @@
1
1
  import { ApiRequestOptions } from "../lib/http.js";
2
- import * as react10 from "react";
2
+ import * as react17 from "react";
3
3
 
4
4
  //#region src/client/useApi.d.ts
5
- declare function useApiFetch<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react10.Dispatch<any>];
6
- declare function useApiGet<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react10.Dispatch<any>];
7
- declare function useApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react10.Dispatch<any>];
8
- declare function useApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react10.Dispatch<any>];
9
- declare function useApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react10.Dispatch<any>];
10
- declare function useApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react10.Dispatch<any>];
5
+ declare function useApiFetch<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
6
+ declare function useApiGet<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
7
+ declare function useApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
8
+ declare function useApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
9
+ declare function useApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
10
+ declare function useApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react17.Dispatch<any>];
11
11
  type Api = {
12
12
  get: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
13
13
  post: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
@@ -1,6 +1,6 @@
1
1
  import { ApiRequestOptions } from "../lib/http.js";
2
2
  import { QueryParams } from "@websolutespa/bom-core";
3
- import * as react16 from "react";
3
+ import * as react0 from "react";
4
4
 
5
5
  //#region src/client/useCollectionApi.d.ts
6
6
  type CollectionApi = {
@@ -11,11 +11,11 @@ type CollectionApi = {
11
11
  delete: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
12
12
  };
13
13
  declare function useCollectionApi(): CollectionApi;
14
- declare function useCollectionApiGet<T = unknown>(pathname: string, params?: QueryParams, options?: ApiRequestOptions): [T | undefined, boolean, any, react16.Dispatch<any>];
15
- declare function useCollectionApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react16.Dispatch<any>];
16
- declare function useCollectionApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react16.Dispatch<any>];
17
- declare function useCollectionApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react16.Dispatch<any>];
18
- declare function useCollectionApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react16.Dispatch<any>];
14
+ declare function useCollectionApiGet<T = unknown>(pathname: string, params?: QueryParams, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
15
+ declare function useCollectionApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
16
+ declare function useCollectionApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
17
+ declare function useCollectionApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
18
+ declare function useCollectionApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, react0.Dispatch<any>];
19
19
  //#endregion
20
20
  export { useCollectionApi, useCollectionApiDelete, useCollectionApiGet, useCollectionApiPatch, useCollectionApiPost, useCollectionApiPut };
21
21
  //# sourceMappingURL=useCollectionApi.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCollectionApi.d.ts","names":[],"sources":["../../src/client/useCollectionApi.ts"],"sourcesContent":[],"mappings":";;;;;KAMK,aAAA;gDAC2C,uBAAuB,sBAAsB,QAAQ;qEAChC,sBAAsB,QAAQ;EAF9F,GAAA,EAAA,CAAA,IAAA,OAAa,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAGkD,iBAHlD,EAAA,GAGwE,OAHxE,CAGgF,CAHhF,CAAA;EAAA,KAAA,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAIoD,iBAJpD,EAAA,GAI0E,OAJ1E,CAIkF,CAJlF,CAAA;EAAA,MAC8B,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAII,iBAJJ,EAAA,GAI0B,OAJ1B,CAIkC,CAJlC,CAAA;CAAW;AAA0C,iBAOrF,gBAAA,CAAA,CAPqF,EAOjE,aAPiE;AAAR,iBAuC7E,mBAvC6E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAuCjB,WAvCiB,EAAA,OAAA,CAAA,EAuCK,iBAvCL,CAAA,EAAA,CAuC2B,CAvC3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAuC2B,OAAA,CAAA,QAvC3B,CAAA,GAAA,CAAA,CAAA;AACxB,iBA2CrD,oBA3CqD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA2C0B,iBA3C1B,CAAA,EAAA,CA2CgD,CA3ChD,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA2CgD,OAAA,CAAA,QA3ChD,CAAA,GAAA,CAAA,CAAA;AAA8B,iBA+CnF,mBA/CmF,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA+CL,iBA/CK,CAAA,EAAA,CA+CiB,CA/CjB,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA+CiB,OAAA,CAAA,QA/CjB,CAAA,GAAA,CAAA,CAAA;AAAR,iBAmD3E,qBAnD2E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAmDK,iBAnDL,CAAA,EAAA,CAmD2B,CAnD3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAmD2B,OAAA,CAAA,QAnD3B,CAAA,GAAA,CAAA,CAAA;AACvB,iBAsDpD,sBAtDoD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAsDW,iBAtDX,CAAA,EAAA,CAsDiC,CAtDjC,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAsDiC,OAAA,CAAA,QAtDjC,CAAA,GAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"useCollectionApi.d.ts","names":[],"sources":["../../src/client/useCollectionApi.ts"],"sourcesContent":[],"mappings":";;;;;KAMK,aAAA;gDAC2C,uBAAuB,sBAAsB,QAAQ;qEAChC,sBAAsB,QAAQ;EAF9F,GAAA,EAAA,CAAA,IAAA,OAAa,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAGkD,iBAHlD,EAAA,GAGwE,OAHxE,CAGgF,CAHhF,CAAA;EAAA,KAAA,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAIoD,iBAJpD,EAAA,GAI0E,OAJ1E,CAIkF,CAJlF,CAAA;EAAA,MAC8B,EAAA,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAII,iBAJJ,EAAA,GAI0B,OAJ1B,CAIkC,CAJlC,CAAA;CAAW;AAA0C,iBAOrF,gBAAA,CAAA,CAPqF,EAOjE,aAPiE;AAAR,iBAuC7E,mBAvC6E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,MAAA,CAAA,EAuCjB,WAvCiB,EAAA,OAAA,CAAA,EAuCK,iBAvCL,CAAA,EAAA,CAuC2B,CAvC3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAuC2B,MAAA,CAAA,QAvC3B,CAAA,GAAA,CAAA,CAAA;AACxB,iBA2CrD,oBA3CqD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA2C0B,iBA3C1B,CAAA,EAAA,CA2CgD,CA3ChD,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA2CgD,MAAA,CAAA,QA3ChD,CAAA,GAAA,CAAA,CAAA;AAA8B,iBA+CnF,mBA/CmF,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EA+CL,iBA/CK,CAAA,EAAA,CA+CiB,CA/CjB,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EA+CiB,MAAA,CAAA,QA/CjB,CAAA,GAAA,CAAA,CAAA;AAAR,iBAmD3E,qBAnD2E,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAmDK,iBAnDL,CAAA,EAAA,CAmD2B,CAnD3B,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAmD2B,MAAA,CAAA,QAnD3B,CAAA,GAAA,CAAA,CAAA;AACvB,iBAsDpD,sBAtDoD,CAAA,IAAA,OAAA,CAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAsDW,iBAtDX,CAAA,EAAA,CAsDiC,CAtDjC,GAAA,SAAA,EAAA,OAAA,EAAA,GAAA,EAsDiC,MAAA,CAAA,QAtDjC,CAAA,GAAA,CAAA,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { IEndUser, IUser } from "../types.js";
2
- import * as react21 from "react";
2
+ import * as react15 from "react";
3
3
  import { ReactNode } from "react";
4
4
 
5
5
  //#region src/client/user.d.ts
@@ -7,12 +7,12 @@ type UserContextType = {
7
7
  user?: IEndUser | IUser | null;
8
8
  setUser: (user?: IEndUser | IUser | null) => void;
9
9
  };
10
- declare const UserContext: react21.Context<UserContextType>;
10
+ declare const UserContext: react15.Context<UserContextType>;
11
11
  declare function UserProvider({
12
12
  children
13
13
  }: {
14
14
  children: ReactNode;
15
- }): react21.JSX.Element;
15
+ }): react15.JSX.Element;
16
16
  //# sourceMappingURL=user.d.ts.map
17
17
 
18
18
  //#endregion
package/dist/index.d.ts CHANGED
@@ -9,10 +9,10 @@ import { LabelService, getLabelFromLabels, interpolateText } from "./lib/label.j
9
9
  import { LayoutDefaults } from "./lib/layout.defaults.js";
10
10
  import { getLink } from "./lib/link.js";
11
11
  import { IPaginationInfo, IPaginationItem, IPaginationOptions, getMoreItems, getPagedItems, getPaginationInfo, isPaginationInfo } from "./lib/pagination.js";
12
- import { getRouteLinkCategory, newRouteLink, resolveRoute, routeToLink, routeToRouteLink } from "./lib/route.js";
12
+ import { getRouteLinkCategory, getRouteTemplate, newRouteLink, resolveRoute, routeToLink, routeToRouteLink } from "./lib/route.js";
13
13
  import { BuildStrategy, NextPhase, StoreStrategy, buildStrategy, nextPhase, storeCacheDuration, storeStrategy } from "./lib/store.js";
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
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 };
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, getRouteTemplate, 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,4 +1,4 @@
1
- import { getRouteLinkCategory, newRouteLink, resolveRoute, routeToLink, routeToRouteLink } from "./lib/route.js";
1
+ import { getRouteLinkCategory, getRouteTemplate, newRouteLink, resolveRoute, routeToLink, routeToRouteLink } from "./lib/route.js";
2
2
  import { buildBreadcrumb } from "./lib/breadcrumb.js";
3
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";
@@ -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, 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 };
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, getRouteTemplate, guest, interpolateText, isPaginationInfo, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut, newRouteLink, nextPhase, resolveHref, resolveRoute, routeToLink, routeToRouteLink, sanitizeHref, sanitizeRedirectFrom, sanitizeRedirectTo, sanitizeRedirectUrl, storeCacheDuration, storeStrategy, trimTerminalSlash };
@@ -1 +1 @@
1
- {"version":3,"file":"meta-data.d.ts","names":[],"sources":["../../src/lib/meta-data.ts"],"sourcesContent":[],"mappings":";;;;;;;KAMY,MAAA;;EAAA,YAAM,EAAA,MAgBP;EAGC,OAAA,EAAA,MAAU;EAMV,IAAA,EAAA,MAAK;EAAA,GAAA,EAAA,MAAA;EAAA,KAOH,CAAA,EAAA,MAAA;EAAU,SACX,CAAA,EAAA,MAAA;EAAU,OAAA,CAAA,EAAA,MAAA;EASX,IAAA,CAAA,EAAA,MAAS;EAAA,OAAA,CAAA,EAAA,MAAA;EAAA,YACX,CAAA,EAAA,MAAA;EAAO,WACE,CAAA,EAAA,MAAA;EAAK,WAAhB,CAAA,EAAA,MAAA;EAAU,MACT,CAAA,EA7BE,MA6BF,CAAA,MAAA,EAAA,MAAA,CAAA;CAAM;AAEP,KA5BI,UAAA,GA4BJ;EAAK,EAAA,EACA,MAAA;EAAa,IACV,EAAA,MAAA;EAAY,QACX,EAAA,MAAA;CAAa;AAEd,KA3BJ,KAAA,GA2BI;EAAe,KAAA,EAAA,MAAA;;;;;;cApBjB;aACD;;;;KASD,SAAA;UACF;QACF,WAAW;SACV;gBACO;QACR;aACK;gBACG;iBACC;kBACC;gBACF"}
1
+ {"version":3,"file":"meta-data.d.ts","names":[],"sources":["../../src/lib/meta-data.ts"],"sourcesContent":[],"mappings":";;;;;;;KAMY,MAAA;;EAAA,YAAM,EAAA,MAAA;EAmBN,OAAA,EAAA,MAAU;EAMV,IAAA,EAAA,MAAK;EAAA,GAAA,EAAA,MAAA;EAAA,KAOH,CAAA,EAAA,MAAA;EAAU,SACX,CAAA,EAAA,MAAA;EAAU,OAAA,CAAA,EAAA,MAAA;EASX,IAAA,CAAA,EAAA,MAAS;EAAA,OAAA,CAAA,EAAA,MAAA;EAAA,YACX,CAAA,EAAA,MAAA;EAAO,WACE,CAAA,EAAA,MAAA;EAAK,WAAhB,CAAA,EAAA,MAAA;EAAU,MACT,CAAA,EA7BE,MA6BF,CAAA,MAAA,EAAA,MAAA,CAAA;CAAM;AAEP,KA5BI,UAAA,GA4BJ;EAAK,EAAA,EACA,MAAA;EAAa,IACV,EAAA,MAAA;EAAY,QACX,EAAA,MAAA;CAAa;AAEd,KA3BJ,KAAA,GA2BI;EAAe,KAAA,EAAA,MAAA;;;;;;cApBjB;aACD;;;;KASD,SAAA;UACF;QACF,WAAW;SACV;gBACO;QACR;aACK;gBACG;iBACC;kBACC;gBACF"}
@@ -3,6 +3,11 @@ import { ICategory, IRoute, IRouteLink } from "@websolutespa/bom-core";
3
3
  //#region src/lib/route.d.ts
4
4
  declare function getRouteLinkCategory(locale: string, routes: IRoute[], categories: ICategory[], rootCategory: ICategory, category: ICategory): IRouteLink | IRouteLink[] | undefined;
5
5
  declare function newRouteLink(category: ICategory, route: IRoute | undefined, locale: string): IRouteLink;
6
+ /**
7
+ * Returns the template id of a route, normalizing a string id or a populated `{ id }`.
8
+ * Returns `undefined` when empty or equal to the route schema.
9
+ */
10
+ declare function getRouteTemplate(route: Pick<IRoute, 'schema' | 'template'>): string | undefined;
6
11
  declare function resolveRoute(route: IRoute): string;
7
12
  declare function routeToRouteLink(route: IRoute): IRouteLink;
8
13
  /**
@@ -13,5 +18,5 @@ declare function routeToLink(route: IRoute, title?: string): IRouteLink;
13
18
  //# sourceMappingURL=route.d.ts.map
14
19
 
15
20
  //#endregion
16
- export { getRouteLinkCategory, newRouteLink, resolveRoute, routeToLink, routeToRouteLink };
21
+ export { getRouteLinkCategory, getRouteTemplate, newRouteLink, resolveRoute, routeToLink, routeToRouteLink };
17
22
  //# sourceMappingURL=route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","names":[],"sources":["../../src/lib/route.ts"],"sourcesContent":[],"mappings":";;;iBAEgB,oBAAA,yBAEN,sBACI,2BACE,qBACJ,YACT,aAAa;iBA0BA,YAAA,WAAuB,kBAAkB,qCAAqC;AAhC9E,iBAkDA,YAAA,CAlDoB,KAAA,EAkDA,MAlDA,CAAA,EAAA,MAAA;AAAA,iBAsDpB,gBAAA,CAtDoB,KAAA,EAsDI,MAtDJ,CAAA,EAsDa,UAtDb;;;;;AAMjC,iBAiEa,WAAA,CAjEb,KAAA,EAiEgC,MAjEhC,EAAA,KAAA,CAAA,EAAA,MAAA,CAAA,EAiEyD,UAjEzD"}
1
+ {"version":3,"file":"route.d.ts","names":[],"sources":["../../src/lib/route.ts"],"sourcesContent":[],"mappings":";;;iBAEgB,oBAAA,yBAEN,sBACI,2BACE,qBACJ,YACT,aAAa;iBA0BA,YAAA,WAAuB,kBAAkB,qCAAqC;AAhC9F;;;;AAIgB,iBAkDA,gBAAA,CAlDA,KAAA,EAkDwB,IAlDxB,CAkD6B,MAlD7B,EAAA,QAAA,GAAA,UAAA,CAAA,CAAA,EAAA,MAAA,GAAA,SAAA;AACJ,iBAyDI,YAAA,CAzDJ,KAAA,EAyDwB,MAzDxB,CAAA,EAAA,MAAA;AACT,iBA4Da,gBAAA,CA5Db,KAAA,EA4DqC,MA5DrC,CAAA,EA4D8C,UA5D9C;;AAAuB;AA0B1B;;AAAuC,iBAmDvB,WAAA,CAnDuB,KAAA,EAmDJ,MAnDI,EAAA,KAAA,CAAA,EAAA,MAAA,CAAA,EAmDqB,UAnDrB"}
package/dist/lib/route.js CHANGED
@@ -1,4 +1,4 @@
1
- import { asCategoryId, findRouteOfCategory, localize } from "@websolutespa/bom-core";
1
+ import { asCategoryId, asEquatableString, findRouteOfCategory, localize } from "@websolutespa/bom-core";
2
2
 
3
3
  //#region src/lib/route.ts
4
4
  function getRouteLinkCategory(locale, routes, categories, rootCategory, category) {
@@ -20,7 +20,7 @@ function newRouteLink(category, route, locale) {
20
20
  const href = route && route.id ? route.id.toString() : "/";
21
21
  const id = route?.page || category.id;
22
22
  const media = category.media || route?.media;
23
- const schema = route?.template || route?.schema || category?.schema || "unknown";
23
+ const schema = route && getRouteTemplate(route) || route?.schema || category?.schema || "unknown";
24
24
  const title = localize(category.title || route?.title || "untitled", locale);
25
25
  const routeLink = {
26
26
  category: category.id,
@@ -33,8 +33,20 @@ function newRouteLink(category, route, locale) {
33
33
  };
34
34
  return routeLink;
35
35
  }
36
+ /**
37
+
38
+ * Returns the template id of a route, normalizing a string id or a populated `{ id }`.
39
+
40
+ * Returns `undefined` when empty or equal to the route schema.
41
+
42
+ */
43
+ function getRouteTemplate(route) {
44
+ const id = route.template ? asEquatableString(route.template) : void 0;
45
+ if (!id) return void 0;
46
+ return id === route.schema ? void 0 : id;
47
+ }
36
48
  function resolveRoute(route) {
37
- return `/${route.market}/${route.locale}/${route.schema}/${route.page}`;
49
+ return `/${route.market}/${route.locale}/${getRouteTemplate(route) ?? route.schema}/${route.page}`;
38
50
  }
39
51
  function routeToRouteLink(route) {
40
52
  const routeLink = {
@@ -67,5 +79,5 @@ function routeToLink(route, title) {
67
79
  }
68
80
 
69
81
  //#endregion
70
- export { getRouteLinkCategory, newRouteLink, resolveRoute, routeToLink, routeToRouteLink };
82
+ export { getRouteLinkCategory, getRouteTemplate, newRouteLink, resolveRoute, routeToLink, routeToRouteLink };
71
83
  //# sourceMappingURL=route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.js","names":["locale: string","routes: IRoute[]","categories: ICategory[]","rootCategory: ICategory","category: ICategory","items: IRouteLink[]","route: IRoute | undefined","route: IRoute","routeLink: IRouteLink","title?: string"],"sources":["../../src/lib/route.ts"],"sourcesContent":["import { asCategoryId, findRouteOfCategory, ICategory, IRoute, IRouteLink, localize } from '@websolutespa/bom-core';\r\n\r\nexport function getRouteLinkCategory(\r\n locale: string,\r\n routes: IRoute[],\r\n categories: ICategory[],\r\n rootCategory: ICategory,\r\n category: ICategory\r\n): IRouteLink | IRouteLink[] | undefined {\r\n const route = findRouteOfCategory(routes, category.id);\r\n const otherCategories = categories.filter(x => x.id !== category.id);\r\n const childCategories = otherCategories.filter(x => asCategoryId(x.category) === category.id);\r\n // console.log('childCategories', category.id, childCategories.map(x => x.id));\r\n const routeLink = newRouteLink(category, route, locale);\r\n // console.log('getRouteLinkCategory', href, category.id, route);\r\n const items: IRouteLink[] = [];\r\n for (const childCategory of childCategories) {\r\n const itemOrItems = getRouteLinkCategory(locale, routes, otherCategories, rootCategory, childCategory);\r\n if (Array.isArray(itemOrItems)) {\r\n items.push(...itemOrItems);\r\n } else if (itemOrItems) {\r\n items.push(itemOrItems);\r\n }\r\n }\r\n if (\r\n !route ||\r\n (category.isHidden && category.id !== rootCategory.id)\r\n ) {\r\n return items;\r\n }\r\n routeLink.items = items;\r\n return routeLink;\r\n}\r\n\r\nexport function newRouteLink(category: ICategory, route: IRoute | undefined, locale: string): IRouteLink {\r\n const href = (route && route.id) ? route.id.toString() : '/';\r\n const id = route?.page || category.id;\r\n const media = category.media || route?.media;\r\n const schema = route?.template || route?.schema || category?.schema || 'unknown';\r\n const title = localize(category.title || route?.title || 'untitled', locale);\r\n const routeLink = {\r\n category: category.id,\r\n href,\r\n id,\r\n items: [],\r\n media,\r\n schema,\r\n title,\r\n };\r\n return routeLink;\r\n}\r\n\r\nexport function resolveRoute(route: IRoute) {\r\n return `/${route.market}/${route.locale}/${route.schema}/${route.page}`;\r\n}\r\n\r\nexport function routeToRouteLink(route: IRoute): IRouteLink {\r\n const routeLink: IRouteLink = {\r\n category: asCategoryId(route.category),\r\n href: route.id,\r\n id: route.page,\r\n items: [],\r\n media: route.media,\r\n schema: route.schema,\r\n title: route.title,\r\n };\r\n return routeLink;\r\n}\r\n\r\n/**\r\n * Converts a route (and optional override title) into an IRouteLink.\r\n * route.id is the pathname (href), route.page is the document ID.\r\n */\r\nexport function routeToLink(route: IRoute, title?: string): IRouteLink {\r\n return {\r\n category: route.category,\r\n href: route.id,\r\n id: route.page,\r\n schema: route.schema,\r\n title: title ?? route.title,\r\n media: route.media,\r\n };\r\n}\r\n"],"mappings":";;;AAEA,SAAgB,qBACdA,QACAC,QACAC,YACAC,cACAC,UACuC;CACvC,MAAM,QAAQ,oBAAoB,QAAQ,SAAS,GAAG;CACtD,MAAM,kBAAkB,WAAW,OAAO,OAAK,EAAE,OAAO,SAAS,GAAG;CACpE,MAAM,kBAAkB,gBAAgB,OAAO,OAAK,aAAa,EAAE,SAAS,KAAK,SAAS,GAAG;CAE7F,MAAM,YAAY,aAAa,UAAU,OAAO,OAAO;CAEvD,MAAMC,QAAsB,CAAE;AAC9B,MAAK,MAAM,iBAAiB,iBAAiB;EAC3C,MAAM,cAAc,qBAAqB,QAAQ,QAAQ,iBAAiB,cAAc,cAAc;AACtG,MAAI,MAAM,QAAQ,YAAY,EAC5B,MAAM,KAAK,GAAG,YAAY;WACjB,aACT,MAAM,KAAK,YAAY;CAE1B;AACD,KACE,CAAC,SACA,SAAS,YAAY,SAAS,OAAO,aAAa,GAEnD,QAAO;CAET,UAAU,QAAQ;AAClB,QAAO;AACR;AAED,SAAgB,aAAaD,UAAqBE,OAA2BN,QAA4B;CACvG,MAAM,OAAQ,SAAS,MAAM,KAAM,MAAM,GAAG,UAAU,GAAG;CACzD,MAAM,KAAK,OAAO,QAAQ,SAAS;CACnC,MAAM,QAAQ,SAAS,SAAS,OAAO;CACvC,MAAM,SAAS,OAAO,YAAY,OAAO,UAAU,UAAU,UAAU;CACvE,MAAM,QAAQ,SAAS,SAAS,SAAS,OAAO,SAAS,YAAY,OAAO;CAC5E,MAAM,YAAY;EAChB,UAAU,SAAS;EACnB;EACA;EACA,OAAO,CAAE;EACT;EACA;EACA;CACD;AACD,QAAO;AACR;AAED,SAAgB,aAAaO,OAAe;AAC1C,QAAO,CAAC,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,MAAM,MAAM;AACxE;AAED,SAAgB,iBAAiBA,OAA2B;CAC1D,MAAMC,YAAwB;EAC5B,UAAU,aAAa,MAAM,SAAS;EACtC,MAAM,MAAM;EACZ,IAAI,MAAM;EACV,OAAO,CAAE;EACT,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,OAAO,MAAM;CACd;AACD,QAAO;AACR;;;;;;;;AAMD,SAAgB,YAAYD,OAAeE,OAA4B;AACrE,QAAO;EACL,UAAU,MAAM;EAChB,MAAM,MAAM;EACZ,IAAI,MAAM;EACV,QAAQ,MAAM;EACd,OAAO,SAAS,MAAM;EACtB,OAAO,MAAM;CACd;AACF"}
1
+ {"version":3,"file":"route.js","names":["locale: string","routes: IRoute[]","categories: ICategory[]","rootCategory: ICategory","category: ICategory","items: IRouteLink[]","route: IRoute | undefined","route: Pick<IRoute, 'schema' | 'template'>","route: IRoute","routeLink: IRouteLink","title?: string"],"sources":["../../src/lib/route.ts"],"sourcesContent":["import { asCategoryId, asEquatableString, findRouteOfCategory, ICategory, IRoute, IRouteLink, localize } from '@websolutespa/bom-core';\r\n\r\nexport function getRouteLinkCategory(\r\n locale: string,\r\n routes: IRoute[],\r\n categories: ICategory[],\r\n rootCategory: ICategory,\r\n category: ICategory\r\n): IRouteLink | IRouteLink[] | undefined {\r\n const route = findRouteOfCategory(routes, category.id);\r\n const otherCategories = categories.filter(x => x.id !== category.id);\r\n const childCategories = otherCategories.filter(x => asCategoryId(x.category) === category.id);\r\n // console.log('childCategories', category.id, childCategories.map(x => x.id));\r\n const routeLink = newRouteLink(category, route, locale);\r\n // console.log('getRouteLinkCategory', href, category.id, route);\r\n const items: IRouteLink[] = [];\r\n for (const childCategory of childCategories) {\r\n const itemOrItems = getRouteLinkCategory(locale, routes, otherCategories, rootCategory, childCategory);\r\n if (Array.isArray(itemOrItems)) {\r\n items.push(...itemOrItems);\r\n } else if (itemOrItems) {\r\n items.push(itemOrItems);\r\n }\r\n }\r\n if (\r\n !route ||\r\n (category.isHidden && category.id !== rootCategory.id)\r\n ) {\r\n return items;\r\n }\r\n routeLink.items = items;\r\n return routeLink;\r\n}\r\n\r\nexport function newRouteLink(category: ICategory, route: IRoute | undefined, locale: string): IRouteLink {\r\n const href = (route && route.id) ? route.id.toString() : '/';\r\n const id = route?.page || category.id;\r\n const media = category.media || route?.media;\r\n const schema = (route && getRouteTemplate(route)) || route?.schema || category?.schema || 'unknown';\r\n const title = localize(category.title || route?.title || 'untitled', locale);\r\n const routeLink = {\r\n category: category.id,\r\n href,\r\n id,\r\n items: [],\r\n media,\r\n schema,\r\n title,\r\n };\r\n return routeLink;\r\n}\r\n\r\n/**\r\n * Returns the template id of a route, normalizing a string id or a populated `{ id }`.\r\n * Returns `undefined` when empty or equal to the route schema.\r\n */\r\nexport function getRouteTemplate(route: Pick<IRoute, 'schema' | 'template'>): string | undefined {\r\n const id = route.template ? asEquatableString(route.template) : undefined;\r\n if (!id) {\r\n return undefined;\r\n }\r\n return id === route.schema ? undefined : id;\r\n}\r\n\r\nexport function resolveRoute(route: IRoute) {\r\n return `/${route.market}/${route.locale}/${getRouteTemplate(route) ?? route.schema}/${route.page}`;\r\n}\r\n\r\nexport function routeToRouteLink(route: IRoute): IRouteLink {\r\n const routeLink: IRouteLink = {\r\n category: asCategoryId(route.category),\r\n href: route.id,\r\n id: route.page,\r\n items: [],\r\n media: route.media,\r\n schema: route.schema,\r\n title: route.title,\r\n };\r\n return routeLink;\r\n}\r\n\r\n/**\r\n * Converts a route (and optional override title) into an IRouteLink.\r\n * route.id is the pathname (href), route.page is the document ID.\r\n */\r\nexport function routeToLink(route: IRoute, title?: string): IRouteLink {\r\n return {\r\n category: route.category,\r\n href: route.id,\r\n id: route.page,\r\n schema: route.schema,\r\n title: title ?? route.title,\r\n media: route.media,\r\n };\r\n}\r\n"],"mappings":";;;AAEA,SAAgB,qBACdA,QACAC,QACAC,YACAC,cACAC,UACuC;CACvC,MAAM,QAAQ,oBAAoB,QAAQ,SAAS,GAAG;CACtD,MAAM,kBAAkB,WAAW,OAAO,OAAK,EAAE,OAAO,SAAS,GAAG;CACpE,MAAM,kBAAkB,gBAAgB,OAAO,OAAK,aAAa,EAAE,SAAS,KAAK,SAAS,GAAG;CAE7F,MAAM,YAAY,aAAa,UAAU,OAAO,OAAO;CAEvD,MAAMC,QAAsB,CAAE;AAC9B,MAAK,MAAM,iBAAiB,iBAAiB;EAC3C,MAAM,cAAc,qBAAqB,QAAQ,QAAQ,iBAAiB,cAAc,cAAc;AACtG,MAAI,MAAM,QAAQ,YAAY,EAC5B,MAAM,KAAK,GAAG,YAAY;WACjB,aACT,MAAM,KAAK,YAAY;CAE1B;AACD,KACE,CAAC,SACA,SAAS,YAAY,SAAS,OAAO,aAAa,GAEnD,QAAO;CAET,UAAU,QAAQ;AAClB,QAAO;AACR;AAED,SAAgB,aAAaD,UAAqBE,OAA2BN,QAA4B;CACvG,MAAM,OAAQ,SAAS,MAAM,KAAM,MAAM,GAAG,UAAU,GAAG;CACzD,MAAM,KAAK,OAAO,QAAQ,SAAS;CACnC,MAAM,QAAQ,SAAS,SAAS,OAAO;CACvC,MAAM,SAAU,SAAS,iBAAiB,MAAM,IAAK,OAAO,UAAU,UAAU,UAAU;CAC1F,MAAM,QAAQ,SAAS,SAAS,SAAS,OAAO,SAAS,YAAY,OAAO;CAC5E,MAAM,YAAY;EAChB,UAAU,SAAS;EACnB;EACA;EACA,OAAO,CAAE;EACT;EACA;EACA;CACD;AACD,QAAO;AACR;;;;;;;;AAMD,SAAgB,iBAAiBO,OAAgE;CAC/F,MAAM,KAAK,MAAM,WAAW,kBAAkB,MAAM,SAAS,GAAG;AAChE,KAAI,CAAC,GACH,QAAO;AAET,QAAO,OAAO,MAAM,SAAS,SAAY;AAC1C;AAED,SAAgB,aAAaC,OAAe;AAC1C,QAAO,CAAC,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,iBAAiB,MAAM,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,MAAM;AACnG;AAED,SAAgB,iBAAiBA,OAA2B;CAC1D,MAAMC,YAAwB;EAC5B,UAAU,aAAa,MAAM,SAAS;EACtC,MAAM,MAAM;EACZ,IAAI,MAAM;EACV,OAAO,CAAE;EACT,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,OAAO,MAAM;CACd;AACD,QAAO;AACR;;;;;;;;AAMD,SAAgB,YAAYD,OAAeE,OAA4B;AACrE,QAAO;EACL,UAAU,MAAM;EAChB,MAAM,MAAM;EACZ,IAAI,MAAM;EACV,QAAQ,MAAM;EACd,OAAO,SAAS,MAAM;EACtB,OAAO,MAAM;CACd;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"protected-route.d.ts","names":[],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":[],"mappings":";;;cAca,qBAAqB"}
1
+ {"version":3,"file":"protected-route.d.ts","names":[],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":[],"mappings":";;;cAea,qBAAqB"}
@@ -1,3 +1,4 @@
1
+ import { getRouteTemplate } from "../lib/route.js";
1
2
  import { localApiGet } from "../lib/http.js";
2
3
  import { getNextUrl } from "../server/utils.js";
3
4
  import { getRequestOrigin } from "./proxy.js";
@@ -30,6 +31,8 @@ const protectedRouteProxy = async ({ request, route }) => {
30
31
  reqHeaders.set("x-market", nextRoute.market);
31
32
  reqHeaders.set("x-locale", nextRoute.locale);
32
33
  reqHeaders.set("x-schema", nextRoute.schema);
34
+ const template = getRouteTemplate(nextRoute);
35
+ if (template) reqHeaders.set("x-template", template);
33
36
  reqHeaders.set("x-id", String(nextRoute.page));
34
37
  reqHeaders.set("x-forwarded-pathname", nextUrl.pathname);
35
38
  console.log("protectedRouteProxy.Protected", pathname, ">", nextUrl.pathname);
@@ -1 +1 @@
1
- {"version":3,"file":"protected-route.js","names":["request: RouteMiddlewareOptions['request']","href: string","protectedRouteProxy: RouteMiddleware"],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getNextUrl } from '../server/utils';\r\nimport { getRequestOrigin } from './proxy';\r\nimport type { RouteMiddleware, RouteMiddlewareOptions, RouteResolverResponse } from './route-proxy';\r\n\r\nfunction getPublicRedirectUrl(request: RouteMiddlewareOptions['request'], href: string): URL | undefined {\r\n if (!href.startsWith('/') || href.startsWith('//')) {\r\n return undefined;\r\n }\r\n const url = new URL(href, getRequestOrigin(request));\r\n return url.pathname === request.nextUrl.pathname ? undefined : url;\r\n}\r\n\r\nexport const protectedRouteProxy: RouteMiddleware = async ({ request, route }: RouteMiddlewareOptions) => {\r\n // console.log('protectedRouteProxy', 'token', token);\r\n if (route.isProtected) {\r\n const token = request.cookies.get('payload-token');\r\n const isAuthenticated = token; // await hasValidSession();\r\n console.log('protectedRouteProxy.isAuthenticated', isAuthenticated);\r\n if (!isAuthenticated) {\r\n if (route.publicRedirect) {\r\n const redirectUrl = getPublicRedirectUrl(request, route.publicRedirect);\r\n if (redirectUrl) {\r\n return NextResponse.redirect(redirectUrl);\r\n }\r\n }\r\n const url = request.nextUrl;\r\n const { pathname } = url;\r\n const reqHeaders = new Headers(request.headers);\r\n reqHeaders.set('x-pathname', pathname);\r\n const resolution = await localApiGet<RouteResolverResponse>(\r\n `/-route?schema=login&market=${encodeURIComponent(route.market)}&locale=${encodeURIComponent(route.locale)}`,\r\n {},\r\n undefined,\r\n getRequestOrigin(request)\r\n );\r\n const nextRoute = resolution?.route;\r\n if (nextRoute) {\r\n const nextUrl = getNextUrl(request, nextRoute);\r\n reqHeaders.set('x-market', nextRoute.market);\r\n reqHeaders.set('x-locale', nextRoute.locale);\r\n reqHeaders.set('x-schema', nextRoute.schema);\r\n reqHeaders.set('x-id', String(nextRoute.page));\r\n reqHeaders.set('x-forwarded-pathname', nextUrl.pathname);\r\n console.log('protectedRouteProxy.Protected', pathname, '>', nextUrl.pathname);\r\n const response = NextResponse\r\n .rewrite(nextUrl, {\r\n request: {\r\n headers: reqHeaders,\r\n },\r\n });\r\n return response;\r\n }\r\n }\r\n }\r\n};\r\n"],"mappings":";;;;;;AAMA,SAAS,qBAAqBA,SAA4CC,MAA+B;AACvG,KAAI,CAAC,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,KAAK,CAChD,QAAO;CAET,MAAM,MAAM,IAAI,IAAI,MAAM,iBAAiB,QAAQ;AACnD,QAAO,IAAI,aAAa,QAAQ,QAAQ,WAAW,SAAY;AAChE;AAED,MAAaC,sBAAuC,OAAO,EAAE,SAAS,OAA+B,KAAK;AAExG,KAAI,MAAM,aAAa;EACrB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,gBAAgB;EAClD,MAAM,kBAAkB;EACxB,QAAQ,IAAI,uCAAuC,gBAAgB;AACnE,MAAI,CAAC,iBAAiB;AACpB,OAAI,MAAM,gBAAgB;IACxB,MAAM,cAAc,qBAAqB,SAAS,MAAM,eAAe;AACvE,QAAI,YACF,QAAO,aAAa,SAAS,YAAY;GAE5C;GACD,MAAM,MAAM,QAAQ;GACpB,MAAM,EAAE,UAAU,GAAG;GACrB,MAAM,aAAa,IAAI,QAAQ,QAAQ;GACvC,WAAW,IAAI,cAAc,SAAS;GACtC,MAAM,aAAa,MAAM,YACvB,CAAC,4BAA4B,EAAE,mBAAmB,MAAM,OAAO,CAAC,QAAQ,EAAE,mBAAmB,MAAM,OAAO,EAAE,EAC5G,CAAE,GACF,QACA,iBAAiB,QAAQ,CAC1B;GACD,MAAM,YAAY,YAAY;AAC9B,OAAI,WAAW;IACb,MAAM,UAAU,WAAW,SAAS,UAAU;IAC9C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,QAAQ,OAAO,UAAU,KAAK,CAAC;IAC9C,WAAW,IAAI,wBAAwB,QAAQ,SAAS;IACxD,QAAQ,IAAI,iCAAiC,UAAU,KAAK,QAAQ,SAAS;IAC7E,MAAM,WAAW,aACd,QAAQ,SAAS,EAChB,SAAS,EACP,SAAS,WACV,EACF,EAAC;AACJ,WAAO;GACR;EACF;CACF;AACF"}
1
+ {"version":3,"file":"protected-route.js","names":["request: RouteMiddlewareOptions['request']","href: string","protectedRouteProxy: RouteMiddleware"],"sources":["../../src/proxy/protected-route.ts"],"sourcesContent":["import { NextResponse } from 'next/server';\r\nimport { localApiGet } from '../lib/http';\r\nimport { getRouteTemplate } from '../lib/route';\r\nimport { getNextUrl } from '../server/utils';\r\nimport { getRequestOrigin } from './proxy';\r\nimport type { RouteMiddleware, RouteMiddlewareOptions, RouteResolverResponse } from './route-proxy';\r\n\r\nfunction getPublicRedirectUrl(request: RouteMiddlewareOptions['request'], href: string): URL | undefined {\r\n if (!href.startsWith('/') || href.startsWith('//')) {\r\n return undefined;\r\n }\r\n const url = new URL(href, getRequestOrigin(request));\r\n return url.pathname === request.nextUrl.pathname ? undefined : url;\r\n}\r\n\r\nexport const protectedRouteProxy: RouteMiddleware = async ({ request, route }: RouteMiddlewareOptions) => {\r\n // console.log('protectedRouteProxy', 'token', token);\r\n if (route.isProtected) {\r\n const token = request.cookies.get('payload-token');\r\n const isAuthenticated = token; // await hasValidSession();\r\n console.log('protectedRouteProxy.isAuthenticated', isAuthenticated);\r\n if (!isAuthenticated) {\r\n if (route.publicRedirect) {\r\n const redirectUrl = getPublicRedirectUrl(request, route.publicRedirect);\r\n if (redirectUrl) {\r\n return NextResponse.redirect(redirectUrl);\r\n }\r\n }\r\n const url = request.nextUrl;\r\n const { pathname } = url;\r\n const reqHeaders = new Headers(request.headers);\r\n reqHeaders.set('x-pathname', pathname);\r\n const resolution = await localApiGet<RouteResolverResponse>(\r\n `/-route?schema=login&market=${encodeURIComponent(route.market)}&locale=${encodeURIComponent(route.locale)}`,\r\n {},\r\n undefined,\r\n getRequestOrigin(request)\r\n );\r\n const nextRoute = resolution?.route;\r\n if (nextRoute) {\r\n const nextUrl = getNextUrl(request, nextRoute);\r\n reqHeaders.set('x-market', nextRoute.market);\r\n reqHeaders.set('x-locale', nextRoute.locale);\r\n reqHeaders.set('x-schema', nextRoute.schema);\r\n const template = getRouteTemplate(nextRoute);\r\n if (template) {\r\n reqHeaders.set('x-template', template);\r\n }\r\n reqHeaders.set('x-id', String(nextRoute.page));\r\n reqHeaders.set('x-forwarded-pathname', nextUrl.pathname);\r\n console.log('protectedRouteProxy.Protected', pathname, '>', nextUrl.pathname);\r\n const response = NextResponse\r\n .rewrite(nextUrl, {\r\n request: {\r\n headers: reqHeaders,\r\n },\r\n });\r\n return response;\r\n }\r\n }\r\n }\r\n};\r\n"],"mappings":";;;;;;;AAOA,SAAS,qBAAqBA,SAA4CC,MAA+B;AACvG,KAAI,CAAC,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,KAAK,CAChD,QAAO;CAET,MAAM,MAAM,IAAI,IAAI,MAAM,iBAAiB,QAAQ;AACnD,QAAO,IAAI,aAAa,QAAQ,QAAQ,WAAW,SAAY;AAChE;AAED,MAAaC,sBAAuC,OAAO,EAAE,SAAS,OAA+B,KAAK;AAExG,KAAI,MAAM,aAAa;EACrB,MAAM,QAAQ,QAAQ,QAAQ,IAAI,gBAAgB;EAClD,MAAM,kBAAkB;EACxB,QAAQ,IAAI,uCAAuC,gBAAgB;AACnE,MAAI,CAAC,iBAAiB;AACpB,OAAI,MAAM,gBAAgB;IACxB,MAAM,cAAc,qBAAqB,SAAS,MAAM,eAAe;AACvE,QAAI,YACF,QAAO,aAAa,SAAS,YAAY;GAE5C;GACD,MAAM,MAAM,QAAQ;GACpB,MAAM,EAAE,UAAU,GAAG;GACrB,MAAM,aAAa,IAAI,QAAQ,QAAQ;GACvC,WAAW,IAAI,cAAc,SAAS;GACtC,MAAM,aAAa,MAAM,YACvB,CAAC,4BAA4B,EAAE,mBAAmB,MAAM,OAAO,CAAC,QAAQ,EAAE,mBAAmB,MAAM,OAAO,EAAE,EAC5G,CAAE,GACF,QACA,iBAAiB,QAAQ,CAC1B;GACD,MAAM,YAAY,YAAY;AAC9B,OAAI,WAAW;IACb,MAAM,UAAU,WAAW,SAAS,UAAU;IAC9C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,WAAW,IAAI,YAAY,UAAU,OAAO;IAC5C,MAAM,WAAW,iBAAiB,UAAU;AAC5C,QAAI,UACF,WAAW,IAAI,cAAc,SAAS;IAExC,WAAW,IAAI,QAAQ,OAAO,UAAU,KAAK,CAAC;IAC9C,WAAW,IAAI,wBAAwB,QAAQ,SAAS;IACxD,QAAQ,IAAI,iCAAiC,UAAU,KAAK,QAAQ,SAAS;IAC7E,MAAM,WAAW,aACd,QAAQ,SAAS,EAChB,SAAS,EACP,SAAS,WACV,EACF,EAAC;AACJ,WAAO;GACR;EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"route-proxy.d.ts","names":[],"sources":["../../src/proxy/route-proxy.ts"],"sourcesContent":[],"mappings":";;;;;;KAOY,KAAA,aAAkB,mBAAmB,mBAAmB,QAAQ;KAEhE,sBAAA;EAFA,OAAA,EAGD,WAHM;EAAA,IAAA,EAIT,cAJS;EAAA,KAAa,EAKrB,MALqB;EAAW,QAAQ,CAAA,EAAA,OAAA;CAAc;AAAK,KAQxD,eAAA,GARwD,CAAA,KAAA,EAQ9B,sBAR8B,EAAA,GAQH,oBARG,GAQoB,OARpB,CAQ4B,oBAR5B,CAAA;AAAO,KAU/D,qBAAA,GAV+D,CAAA,KAAA,EAU/B,MAV+B,EAAA,OAAA,EAUd,WAVc,EAAA,IAAA,EAUK,cAVL,EAAA,GAUwB,OAVxB,CAUgC,oBAVhC,CAAA;AAE/D,KAUA,aAAA,GAAgB,MAVM,GAAA;EAAA,KAAA,CAAA,EAAA,MAAA;CAAA;AAE1B,KASI,qBAAA,GATJ;EAAc,MACb,CAAA,EASE,MATF;EAAM,KAAA,CAAA,EAUL,aAVK;AAGf,CAAA;;;;;;AAA+F;AAE/F;;AAA4C,iBAgB5B,gBAAA,CAhB4B,GAAA,WAAA,EAgBK,eAhBL,EAAA,CAAA,EAgByB,UAhBzB"}
1
+ {"version":3,"file":"route-proxy.d.ts","names":[],"sources":["../../src/proxy/route-proxy.ts"],"sourcesContent":[],"mappings":";;;;;;KAQY,KAAA,aAAkB,mBAAmB,mBAAmB,QAAQ;KAEhE,sBAAA;EAFA,OAAA,EAGD,WAHM;EAAA,IAAA,EAIT,cAJS;EAAA,KAAa,EAKrB,MALqB;EAAW,QAAQ,CAAA,EAAA,OAAA;CAAc;AAAK,KAQxD,eAAA,GARwD,CAAA,KAAA,EAQ9B,sBAR8B,EAAA,GAQH,oBARG,GAQoB,OARpB,CAQ4B,oBAR5B,CAAA;AAAO,KAU/D,qBAAA,GAV+D,CAAA,KAAA,EAU/B,MAV+B,EAAA,OAAA,EAUd,WAVc,EAAA,IAAA,EAUK,cAVL,EAAA,GAUwB,OAVxB,CAUgC,oBAVhC,CAAA;AAE/D,KAUA,aAAA,GAAgB,MAVM,GAAA;EAAA,KAAA,CAAA,EAAA,MAAA;CAAA;AAE1B,KASI,qBAAA,GATJ;EAAc,MACb,CAAA,EASE,MATF;EAAM,KAAA,CAAA,EAUL,aAVK;AAGf,CAAA;;;;;;AAA+F;AAE/F;;AAA4C,iBAgB5B,gBAAA,CAhB4B,GAAA,WAAA,EAgBK,eAhBL,EAAA,CAAA,EAgByB,UAhBzB"}
@@ -1,3 +1,4 @@
1
+ import { getRouteTemplate } from "../lib/route.js";
1
2
  import { localApiGet } from "../lib/http.js";
2
3
  import { getHrefBeforeRedirect, getNextUrl } from "../server/utils.js";
3
4
  import { getRequestOrigin } from "./proxy.js";
@@ -53,6 +54,8 @@ function createRouteProxy(...middlewares) {
53
54
  headers.set("x-market", route.market);
54
55
  headers.set("x-locale", route.locale);
55
56
  headers.set("x-schema", route.schema);
57
+ const template = getRouteTemplate(route);
58
+ if (template) headers.set("x-template", template);
56
59
  headers.set("x-id", String(route.page));
57
60
  headers.set("x-forwarded-pathname", nextUrl.pathname);
58
61
  const response = NextResponse.rewrite(nextUrl, { request: { headers } });
@@ -1 +1 @@
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":";;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,iBAAiB,GAAG,aAA4C;AAC9E,QAAO,eAAgB,EAAE,SAAS,MAAyB,EAAE;EAC3D,MAAM,MAAM,QAAQ;EACpB,MAAM,SAAS,iBAAiB,QAAQ;EACxC,MAAM,qBAAqB,sBAAsB,QAAQ;EACzD,MAAM,EAAE,UAAU,GAAG;EACrB,MAAM,UAAU,IAAI,QAAQ,QAAQ;EACpC,QAAQ,IAAI,cAAc,SAAS;AACnC,MAAI;GACF,MAAM,YAAY,QAAQ,QAAQ,IAAI,qBAAqB;GAC3D,QAAQ,IAAI,aAAa,UAAU;AACnC,OAAI,UAGF;GAKF,MAAM,aAAa,MAAM,YACvB,CAAC,iBAAiB,EAAE,IAAI,SAAS,MAAM,EAAE,IAAI,KAAK,oBAAoB,EAAE,oBAAoB,EAC5F,CAAE,GACF,QACA,OACD;GACD,MAAM,QAAQ,YAAY;AAE1B,OAAI,OAAO;IACT,IAAI,oBAAoB,IAAI;AAI5B,WAAO,IAAI,YAAY,UAAU,CAAC,oBAAoB;KACpD,MAAM,aAAa,YAAY;AAE/B,SAAI,OAAO,eAAe,YAAY;MACpC,qBAAqB,MAAM,WAAW;OAAE;OAAS;OAAM;MAAO,EAAC;AAC/D,UAAI,mBACF,QAAO;KAEV;KACD;IACD;IACD,MAAM,UAAU,WAAW,SAAS,MAAM;IAC1C,QAAQ,IAAI,0BAA0B,UAAU,KAAK,QAAQ,SAAS;IAGtE,QAAQ,IAAI,YAAY,MAAM,OAAO;IACrC,QAAQ,IAAI,YAAY,MAAM,OAAO;IACrC,QAAQ,IAAI,YAAY,MAAM,OAAO;IACrC,QAAQ,IAAI,QAAQ,OAAO,MAAM,KAAK,CAAC;IACvC,QAAQ,IAAI,wBAAwB,QAAQ,SAAS;IACrD,MAAM,WAAW,aAAa,QAAQ,SAAS,EAC7C,SAAS,EACP,QACD,EACF,EAAC;AAEF,WAAO;GACR,OAAM;IACL,MAAM,cAAc,YAAY;IAIhC,MAAM,SAAS,aAAa,UAAU;IACtC,MAAM,SAAS,aAAa,UAAU;IACtC,MAAM,UAAU,QAAQ,QAAQ,OAAO;IACvC,QAAQ,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,IAAI,CAAC;IAC7C,QAAQ,IAAI,YAAY,OAAO;IAC/B,QAAQ,IAAI,YAAY,OAAO;IAC/B,QAAQ,IAAI,YAAY,YAAY;IACpC,QAAQ,IAAI,QAAQ,MAAM;IAC1B,QAAQ,IAAI,wBAAwB,QAAQ,SAAS;IACrD,QAAQ,IAAI,6BAA6B,SAAS;IAClD,MAAM,WAAW,aACd,QAAQ,SAAS,EAChB,SAAS,EACP,QACD,EACF,EAAC;AACJ,WAAO;GACR;EACF,SAAQA,OAAgB;GACvB,MAAM,aAAa,SAAS,OAAO,UAAU,WACzC,QACA,CAAE;AAEN,OAAI,WAAW,UAAU,WAAW,UAAU,OAAO,WAAW,SAAS,KAAK;IAC5E,QAAQ,IAAI,wBAAwB,IAAI,UAAU,WAAW,QAAQ,WAAW,WAAW;IAC3F,MAAM,UAAU,QAAQ,QAAQ,OAAO;IAIvC,QAAQ,WAAW;IACnB,QAAQ,IAAI,wBAAwB,QAAQ,SAAS;IACrD,MAAM,WAAW,aAAa,SAAS,SAAS,IAAI;AACpD,WAAO;GACR,WAAU,WAAW,UAAU,WAAW,UAAU,OAAO,WAAW,SAAS,KAAK;AACnF,QAAI,WAAW,WAAW;;;;;;;;;;;;AAQxB;IAEF,QAAQ,IAAI,wBAAwB,IAAI,UAAU,WAAW,QAAQ,WAAW,WAAW;IAG3F,MAAM,SAAS;IACf,MAAM,SAAS;IACf,MAAM,UAAU,QAAQ,QAAQ,OAAO;IACvC,QAAQ,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,IAAI,CAAC;IAC7C,QAAQ,IAAI,YAAY,OAAO;IAC/B,QAAQ,IAAI,YAAY,OAAO;IAC/B,QAAQ,IAAI,YAAY,YAAY;IACpC,QAAQ,IAAI,QAAQ,MAAM;IAC1B,QAAQ,IAAI,wBAAwB,QAAQ,SAAS;IACrD,QAAQ,IAAI,6BAA6B,SAAS;IAClD,MAAM,WAAW,aACd,QAAQ,SAAS,EAChB,SAAS,EACP,QACD,EACF,EAAC;AACJ,WAAO;GASR;GAID,QAAQ,IAAI,8BAA8B,IAAI,UAAU,WAAW,KAAK,WAAW,QAAQ,WAAW,cAAc,MAAM;AAC1H;EACD;CACF;AACF"}
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 { getRouteTemplate } from '../lib/route';\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 const template = getRouteTemplate(route);\r\n if (template) {\r\n headers.set('x-template', template);\r\n }\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 +1 @@
1
- {"version":3,"file":"static-params.handler.d.ts","names":[],"sources":["../../../src/server/handlers/static-params.handler.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;AAA+B,iBAAf,eAAe,CAAA,cAAe,cAAf,CAAA,CAAA,IAAA,EAAqC,KAArC,EAAA,MAAA,EAAoD,OAApD,CAA4D,eAA5D,CAAA,CAAA,EAAA,GAAA,GACiB,OADjB,CACyB,UADzB,EAAA,CAAA;AAAe,iBAqB9B,gBAAA,CArB8B,MAAA,EAAA,MAAA,CAAA,EAAA,GAAA,GAsBE,OAtBF,CAAA;EAAc,MAAQ,EAAA,MAAA;EAAK,MAAkB,EAAA,MAAA;EAAe,EAAA,EAAvB,MAAA;CAAO,EAAA,CAAA;AAC1C,iBAuDhC,0BAAA,CAvDgC,MAAA,EAAA,MAAA,EAAA,MAAA,EAuDmB,OAvDnB,CAuD2B,eAvD3B,CAAA,CAAA,EAAA,GAAA,GAwDA,OAxDA,CAAA;EAAO,MAAA,EAAA,MAAA;EAoBvC,MAAA,EAAA,MAAA;EAmCA,EAAA,EAAA,MAAA;CAA0B,EAAA,CAAA"}
1
+ {"version":3,"file":"static-params.handler.d.ts","names":[],"sources":["../../../src/server/handlers/static-params.handler.ts"],"sourcesContent":[],"mappings":";;;;;;;AAYA;AAA+B,iBAAf,eAAe,CAAA,cAAe,cAAf,CAAA,CAAA,IAAA,EAAqC,KAArC,EAAA,MAAA,EAAoD,OAApD,CAA4D,eAA5D,CAAA,CAAA,EAAA,GAAA,GACiB,OADjB,CACyB,UADzB,EAAA,CAAA;AAAe,iBAqB9B,gBAAA,CArB8B,MAAA,EAAA,MAAA,CAAA,EAAA,GAAA,GAsBE,OAtBF,CAAA;EAAc,MAAQ,EAAA,MAAA;EAAK,MAAkB,EAAA,MAAA;EAAe,EAAA,EAAvB,MAAA;CAAO,EAAA,CAAA;AAC1C,iBAuDhC,0BAAA,CAvDgC,MAAA,EAAA,MAAA,EAAA,MAAA,EAuDmB,OAvDnB,CAuD2B,eAvD3B,CAAA,CAAA,EAAA,GAAA,GAwDA,OAxDA,CAAA;EAAO,MAAA,EAAA,MAAA;EAoBvC,MAAA,EAAA,MAAA;EAmCA,EAAA,EAAA,MAAA;CAA0B,EAAA,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { getRouteTemplate } from "../../lib/route.js";
1
2
  import { guest } from "../../lib/const.js";
2
3
  import { localApiGet } from "../../lib/http.js";
3
4
  import { BuildStrategy, buildStrategy } from "../../lib/store.js";
@@ -15,7 +16,7 @@ function getStaticParams(slug, config) {
15
16
  if (isDevelopment || buildStrategy === BuildStrategy.Runtime) return [];
16
17
  const { getContext } = await getPayload({ config });
17
18
  const { routes } = await getContext("all", "all");
18
- return routes.filter((r) => r.schema === slug).map((route) => ({
19
+ return routes.filter((r) => (getRouteTemplate(r) ?? r.schema) === slug).map((route) => ({
19
20
  market: route.market,
20
21
  locale: route.locale,
21
22
  id: String(route.page)
@@ -48,7 +49,7 @@ function getStaticParamsFromPayload(schema, config) {
48
49
  user: guest,
49
50
  draft: false
50
51
  });
51
- return routes.filter((route) => route.schema === schema || route.template === schema).map((route) => ({
52
+ return routes.filter((route) => (getRouteTemplate(route) ?? route.schema) === schema).map((route) => ({
52
53
  market: route.market,
53
54
  locale: route.locale,
54
55
  id: String(route.page)
@@ -1 +1 @@
1
- {"version":3,"file":"static-params.handler.js","names":["slug: TSlug","config: Promise<SanitizedConfig>","schema: string","routes: IRoute[]"],"sources":["../../../src/server/handlers/static-params.handler.ts"],"sourcesContent":["import { isDevelopment, qsSerialize, type IRoute } from '@websolutespa/bom-core';\r\nimport type { CollectionSlug, SanitizedConfig } from 'payload';\r\nimport { guest } from '../../lib/const';\r\nimport { localApiGet } from '../../lib/http';\r\nimport { BuildStrategy, buildStrategy } from '../../lib/store';\r\nimport { PageParams } from '../../types';\r\nimport { getPayload, getPayloadInstance, getRoutes } from '../mixer';\r\n\r\n/**\r\n * Returns a generateStaticParams function for a given page collection slug.\r\n */\r\nexport function getStaticParams<TSlug extends CollectionSlug>(slug: TSlug, config: Promise<SanitizedConfig>) {\r\n return async function generateStaticParams(): Promise<PageParams[]> {\r\n if (\r\n isDevelopment ||\r\n buildStrategy === BuildStrategy.Runtime\r\n ) {\r\n return [];\r\n }\r\n const { getContext } = await getPayload({ config });\r\n const { routes } = await getContext('all', 'all');\r\n return (routes)\r\n .filter(r => r.schema === slug)\r\n .map(route => ({\r\n market: route.market,\r\n locale: route.locale,\r\n id: String(route.page),\r\n }));\r\n };\r\n}\r\n\r\n// unused\r\nexport function getStaticParams_(schema: string) {\r\n return async function generateStaticParams(): Promise<{\r\n market: string;\r\n locale: string;\r\n id: string;\r\n }[]> {\r\n if (\r\n isDevelopment ||\r\n buildStrategy === BuildStrategy.Runtime\r\n ) {\r\n return [];\r\n }\r\n const query = qsSerialize({\r\n where: {\r\n or: [{\r\n schema: {\r\n equals: schema,\r\n },\r\n template: {\r\n equals: schema,\r\n },\r\n }],\r\n },\r\n });\r\n const routes: IRoute[] = await localApiGet(`/-route?${query}`);\r\n return (routes)\r\n .map(route => ({\r\n market: route.market,\r\n locale: route.locale,\r\n id: String(route.page),\r\n }));\r\n };\r\n}\r\n\r\n// unused\r\nexport function getStaticParamsFromPayload(schema: string, config: Promise<SanitizedConfig>) {\r\n return async function generateStaticParams(): Promise<{\r\n market: string;\r\n locale: string;\r\n id: string;\r\n }[]> {\r\n if (\r\n isDevelopment ||\r\n buildStrategy === BuildStrategy.Runtime\r\n ) {\r\n return [];\r\n }\r\n\r\n const payload = await getPayloadInstance({ config });\r\n const routes = await getRoutes({\r\n payload,\r\n market: 'all',\r\n locale: 'all',\r\n user: guest,\r\n draft: false,\r\n });\r\n\r\n return routes\r\n .filter(route => (\r\n route.schema === schema ||\r\n route.template === schema\r\n ))\r\n .map(route => ({\r\n market: route.market,\r\n locale: route.locale,\r\n id: String(route.page),\r\n }));\r\n };\r\n}\r\n\r\n/*\r\nGood to know:\r\nYou can use the dynamicParams segment config option to control what happens when a dynamic segment is visited that was not generated with generateStaticParams.\r\nYou must return an empty array from generateStaticParams or utilize export const dynamic = 'force-static' in order to revalidate (ISR) paths at runtime.\r\nDuring next dev, generateStaticParams will be called when you navigate to a route.\r\nDuring next build, generateStaticParams runs before the corresponding Layouts or Pages are generated.\r\nDuring revalidation (ISR), generateStaticParams will not be called again.\r\ngenerateStaticParams replaces the getStaticPaths function in the Pages Router.\r\n*/\r\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,gBAA8CA,MAAaC,QAAkC;AAC3G,QAAO,eAAe,uBAA8C;AAClE,MACE,iBACA,kBAAkB,cAAc,QAEhC,QAAO,CAAE;EAEX,MAAM,EAAE,YAAY,GAAG,MAAM,WAAW,EAAE,OAAQ,EAAC;EACnD,MAAM,EAAE,QAAQ,GAAG,MAAM,WAAW,OAAO,MAAM;AACjD,SAAQ,OACL,OAAO,OAAK,EAAE,WAAW,KAAK,CAC9B,IAAI,YAAU;GACb,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,IAAI,OAAO,MAAM,KAAK;EACvB,GAAE;CACN;AACF;AAGD,SAAgB,iBAAiBC,QAAgB;AAC/C,QAAO,eAAe,uBAIjB;AACH,MACE,iBACA,kBAAkB,cAAc,QAEhC,QAAO,CAAE;EAEX,MAAM,QAAQ,YAAY,EACxB,OAAO,EACL,IAAI,CAAC;GACH,QAAQ,EACN,QAAQ,OACT;GACD,UAAU,EACR,QAAQ,OACT;EACF,CAAC,EACH,EACF,EAAC;EACF,MAAMC,SAAmB,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;AAC9D,SAAQ,OACL,IAAI,YAAU;GACb,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,IAAI,OAAO,MAAM,KAAK;EACvB,GAAE;CACN;AACF;AAGD,SAAgB,2BAA2BD,QAAgBD,QAAkC;AAC3F,QAAO,eAAe,uBAIjB;AACH,MACE,iBACA,kBAAkB,cAAc,QAEhC,QAAO,CAAE;EAGX,MAAM,UAAU,MAAM,mBAAmB,EAAE,OAAQ,EAAC;EACpD,MAAM,SAAS,MAAM,UAAU;GAC7B;GACA,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;EACR,EAAC;AAEF,SAAO,OACJ,OAAO,WACN,MAAM,WAAW,UACjB,MAAM,aAAa,OACnB,CACD,IAAI,YAAU;GACb,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,IAAI,OAAO,MAAM,KAAK;EACvB,GAAE;CACN;AACF"}
1
+ {"version":3,"file":"static-params.handler.js","names":["slug: TSlug","config: Promise<SanitizedConfig>","schema: string","routes: IRoute[]"],"sources":["../../../src/server/handlers/static-params.handler.ts"],"sourcesContent":["import { isDevelopment, qsSerialize, type IRoute } from '@websolutespa/bom-core';\r\nimport type { CollectionSlug, SanitizedConfig } from 'payload';\r\nimport { guest } from '../../lib/const';\r\nimport { localApiGet } from '../../lib/http';\r\nimport { getRouteTemplate } from '../../lib/route';\r\nimport { BuildStrategy, buildStrategy } from '../../lib/store';\r\nimport { PageParams } from '../../types';\r\nimport { getPayload, getPayloadInstance, getRoutes } from '../mixer';\r\n\r\n/**\r\n * Returns a generateStaticParams function for a given page collection slug.\r\n */\r\nexport function getStaticParams<TSlug extends CollectionSlug>(slug: TSlug, config: Promise<SanitizedConfig>) {\r\n return async function generateStaticParams(): Promise<PageParams[]> {\r\n if (\r\n isDevelopment ||\r\n buildStrategy === BuildStrategy.Runtime\r\n ) {\r\n return [];\r\n }\r\n const { getContext } = await getPayload({ config });\r\n const { routes } = await getContext('all', 'all');\r\n return (routes)\r\n .filter(r => (getRouteTemplate(r) ?? r.schema) === slug)\r\n .map(route => ({\r\n market: route.market,\r\n locale: route.locale,\r\n id: String(route.page),\r\n }));\r\n };\r\n}\r\n\r\n// unused\r\nexport function getStaticParams_(schema: string) {\r\n return async function generateStaticParams(): Promise<{\r\n market: string;\r\n locale: string;\r\n id: string;\r\n }[]> {\r\n if (\r\n isDevelopment ||\r\n buildStrategy === BuildStrategy.Runtime\r\n ) {\r\n return [];\r\n }\r\n const query = qsSerialize({\r\n where: {\r\n or: [{\r\n schema: {\r\n equals: schema,\r\n },\r\n template: {\r\n equals: schema,\r\n },\r\n }],\r\n },\r\n });\r\n const routes: IRoute[] = await localApiGet(`/-route?${query}`);\r\n return (routes)\r\n .map(route => ({\r\n market: route.market,\r\n locale: route.locale,\r\n id: String(route.page),\r\n }));\r\n };\r\n}\r\n\r\n// unused\r\nexport function getStaticParamsFromPayload(schema: string, config: Promise<SanitizedConfig>) {\r\n return async function generateStaticParams(): Promise<{\r\n market: string;\r\n locale: string;\r\n id: string;\r\n }[]> {\r\n if (\r\n isDevelopment ||\r\n buildStrategy === BuildStrategy.Runtime\r\n ) {\r\n return [];\r\n }\r\n\r\n const payload = await getPayloadInstance({ config });\r\n const routes = await getRoutes({\r\n payload,\r\n market: 'all',\r\n locale: 'all',\r\n user: guest,\r\n draft: false,\r\n });\r\n\r\n return routes\r\n .filter(route => (getRouteTemplate(route) ?? route.schema) === schema)\r\n .map(route => ({\r\n market: route.market,\r\n locale: route.locale,\r\n id: String(route.page),\r\n }));\r\n };\r\n}\r\n\r\n/*\r\nGood to know:\r\nYou can use the dynamicParams segment config option to control what happens when a dynamic segment is visited that was not generated with generateStaticParams.\r\nYou must return an empty array from generateStaticParams or utilize export const dynamic = 'force-static' in order to revalidate (ISR) paths at runtime.\r\nDuring next dev, generateStaticParams will be called when you navigate to a route.\r\nDuring next build, generateStaticParams runs before the corresponding Layouts or Pages are generated.\r\nDuring revalidation (ISR), generateStaticParams will not be called again.\r\ngenerateStaticParams replaces the getStaticPaths function in the Pages Router.\r\n*/\r\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,gBAA8CA,MAAaC,QAAkC;AAC3G,QAAO,eAAe,uBAA8C;AAClE,MACE,iBACA,kBAAkB,cAAc,QAEhC,QAAO,CAAE;EAEX,MAAM,EAAE,YAAY,GAAG,MAAM,WAAW,EAAE,OAAQ,EAAC;EACnD,MAAM,EAAE,QAAQ,GAAG,MAAM,WAAW,OAAO,MAAM;AACjD,SAAQ,OACL,OAAO,QAAM,iBAAiB,EAAE,IAAI,EAAE,YAAY,KAAK,CACvD,IAAI,YAAU;GACb,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,IAAI,OAAO,MAAM,KAAK;EACvB,GAAE;CACN;AACF;AAGD,SAAgB,iBAAiBC,QAAgB;AAC/C,QAAO,eAAe,uBAIjB;AACH,MACE,iBACA,kBAAkB,cAAc,QAEhC,QAAO,CAAE;EAEX,MAAM,QAAQ,YAAY,EACxB,OAAO,EACL,IAAI,CAAC;GACH,QAAQ,EACN,QAAQ,OACT;GACD,UAAU,EACR,QAAQ,OACT;EACF,CAAC,EACH,EACF,EAAC;EACF,MAAMC,SAAmB,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;AAC9D,SAAQ,OACL,IAAI,YAAU;GACb,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,IAAI,OAAO,MAAM,KAAK;EACvB,GAAE;CACN;AACF;AAGD,SAAgB,2BAA2BD,QAAgBD,QAAkC;AAC3F,QAAO,eAAe,uBAIjB;AACH,MACE,iBACA,kBAAkB,cAAc,QAEhC,QAAO,CAAE;EAGX,MAAM,UAAU,MAAM,mBAAmB,EAAE,OAAQ,EAAC;EACpD,MAAM,SAAS,MAAM,UAAU;GAC7B;GACA,QAAQ;GACR,QAAQ;GACR,MAAM;GACN,OAAO;EACR,EAAC;AAEF,SAAO,OACJ,OAAO,YAAU,iBAAiB,MAAM,IAAI,MAAM,YAAY,OAAO,CACrE,IAAI,YAAU;GACb,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,IAAI,OAAO,MAAM,KAAK;EACvB,GAAE;CACN;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-next",
3
- "version": "4.0.0-next.1",
3
+ "version": "4.0.0-next.2",
4
4
  "description": "Next module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
@@ -0,0 +1,53 @@
1
+ // @vitest-environment node
2
+
3
+ import type { IRoute } from '@websolutespa/bom-core';
4
+ import { beforeEach, describe, expect, test, vi } from 'vitest';
5
+ import { getRouteTemplate, resolveRoute } from './route';
6
+
7
+ const getContext = vi.hoisted(() => vi.fn());
8
+
9
+ vi.mock('server-only', () => ({}));
10
+ vi.mock('../server/mixer', () => ({
11
+ getPayload: vi.fn(async () => ({ getContext })),
12
+ getPayloadInstance: vi.fn(),
13
+ getRoutes: vi.fn(),
14
+ }));
15
+ vi.mock('../lib/store', () => ({
16
+ BuildStrategy: { Runtime: 'runtime', Static: 'static' },
17
+ buildStrategy: 'static',
18
+ }));
19
+
20
+ const route = (extra: Partial<IRoute> = {}): IRoute => ({
21
+ id: '/components',
22
+ market: 'ww',
23
+ locale: 'en',
24
+ schema: 'homepage',
25
+ page: 'abc',
26
+ ...extra,
27
+ } as IRoute);
28
+
29
+ describe('route template', () => {
30
+ test('template selects the route folder', () => {
31
+ expect(resolveRoute(route({ template: 'components' }))).toBe('/ww/en/components/abc');
32
+ expect(resolveRoute(route({ template: { id: 'components' } as unknown as string }))).toBe('/ww/en/components/abc');
33
+ });
34
+
35
+ test('no template or template equal to schema uses the schema', () => {
36
+ expect(resolveRoute(route())).toBe('/ww/en/homepage/abc');
37
+ expect(resolveRoute(route({ template: 'homepage' }))).toBe('/ww/en/homepage/abc');
38
+ expect(getRouteTemplate(route({ template: '' }))).toBeUndefined();
39
+ });
40
+ });
41
+
42
+ describe('getStaticParams', () => {
43
+ beforeEach(() => {
44
+ getContext.mockResolvedValue({ routes: [route({ template: 'components' }), route({ page: 'plain' })] });
45
+ });
46
+
47
+ test('template folder gets the page, collection folder does not', async () => {
48
+ const { getStaticParams } = await import('../server/handlers/static-params.handler');
49
+ const config = Promise.resolve({}) as never;
50
+ expect(await getStaticParams('components' as never, config)()).toEqual([{ market: 'ww', locale: 'en', id: 'abc' }]);
51
+ expect(await getStaticParams('homepage' as never, config)()).toEqual([{ market: 'ww', locale: 'en', id: 'plain' }]);
52
+ });
53
+ });
package/src/lib/route.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { asCategoryId, findRouteOfCategory, ICategory, IRoute, IRouteLink, localize } from '@websolutespa/bom-core';
1
+ import { asCategoryId, asEquatableString, findRouteOfCategory, ICategory, IRoute, IRouteLink, localize } from '@websolutespa/bom-core';
2
2
 
3
3
  export function getRouteLinkCategory(
4
4
  locale: string,
@@ -36,7 +36,7 @@ export function newRouteLink(category: ICategory, route: IRoute | undefined, loc
36
36
  const href = (route && route.id) ? route.id.toString() : '/';
37
37
  const id = route?.page || category.id;
38
38
  const media = category.media || route?.media;
39
- const schema = route?.template || route?.schema || category?.schema || 'unknown';
39
+ const schema = (route && getRouteTemplate(route)) || route?.schema || category?.schema || 'unknown';
40
40
  const title = localize(category.title || route?.title || 'untitled', locale);
41
41
  const routeLink = {
42
42
  category: category.id,
@@ -50,8 +50,20 @@ export function newRouteLink(category: ICategory, route: IRoute | undefined, loc
50
50
  return routeLink;
51
51
  }
52
52
 
53
+ /**
54
+ * Returns the template id of a route, normalizing a string id or a populated `{ id }`.
55
+ * Returns `undefined` when empty or equal to the route schema.
56
+ */
57
+ export function getRouteTemplate(route: Pick<IRoute, 'schema' | 'template'>): string | undefined {
58
+ const id = route.template ? asEquatableString(route.template) : undefined;
59
+ if (!id) {
60
+ return undefined;
61
+ }
62
+ return id === route.schema ? undefined : id;
63
+ }
64
+
53
65
  export function resolveRoute(route: IRoute) {
54
- return `/${route.market}/${route.locale}/${route.schema}/${route.page}`;
66
+ return `/${route.market}/${route.locale}/${getRouteTemplate(route) ?? route.schema}/${route.page}`;
55
67
  }
56
68
 
57
69
  export function routeToRouteLink(route: IRoute): IRouteLink {
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server';
2
2
  import { localApiGet } from '../lib/http';
3
+ import { getRouteTemplate } from '../lib/route';
3
4
  import { getNextUrl } from '../server/utils';
4
5
  import { getRequestOrigin } from './proxy';
5
6
  import type { RouteMiddleware, RouteMiddlewareOptions, RouteResolverResponse } from './route-proxy';
@@ -41,6 +42,10 @@ export const protectedRouteProxy: RouteMiddleware = async ({ request, route }: R
41
42
  reqHeaders.set('x-market', nextRoute.market);
42
43
  reqHeaders.set('x-locale', nextRoute.locale);
43
44
  reqHeaders.set('x-schema', nextRoute.schema);
45
+ const template = getRouteTemplate(nextRoute);
46
+ if (template) {
47
+ reqHeaders.set('x-template', template);
48
+ }
44
49
  reqHeaders.set('x-id', String(nextRoute.page));
45
50
  reqHeaders.set('x-forwarded-pathname', nextUrl.pathname);
46
51
  console.log('protectedRouteProxy.Protected', pathname, '>', nextUrl.pathname);
@@ -2,6 +2,7 @@ import { defaultLocale, defaultMarket, IRoute } from '@websolutespa/bom-core';
2
2
  import { NextMiddlewareResult } from 'next/dist/server/web/types';
3
3
  import { NextFetchEvent, NextRequest, NextResponse } from 'next/server';
4
4
  import { localApiGet } from '../lib/http';
5
+ import { getRouteTemplate } from '../lib/route';
5
6
  import { getHrefBeforeRedirect, getNextUrl } from '../server/utils';
6
7
  import { getRequestOrigin, Middleware, MiddlewareOptions } from './proxy';
7
8
 
@@ -81,6 +82,10 @@ export function createRouteProxy(...middlewares: RouteMiddleware[]): Middleware
81
82
  headers.set('x-market', route.market);
82
83
  headers.set('x-locale', route.locale);
83
84
  headers.set('x-schema', route.schema);
85
+ const template = getRouteTemplate(route);
86
+ if (template) {
87
+ headers.set('x-template', template);
88
+ }
84
89
  headers.set('x-id', String(route.page));
85
90
  headers.set('x-forwarded-pathname', nextUrl.pathname);
86
91
  const response = NextResponse.rewrite(nextUrl, {
@@ -2,6 +2,7 @@ import { isDevelopment, qsSerialize, type IRoute } from '@websolutespa/bom-core'
2
2
  import type { CollectionSlug, SanitizedConfig } from 'payload';
3
3
  import { guest } from '../../lib/const';
4
4
  import { localApiGet } from '../../lib/http';
5
+ import { getRouteTemplate } from '../../lib/route';
5
6
  import { BuildStrategy, buildStrategy } from '../../lib/store';
6
7
  import { PageParams } from '../../types';
7
8
  import { getPayload, getPayloadInstance, getRoutes } from '../mixer';
@@ -20,7 +21,7 @@ export function getStaticParams<TSlug extends CollectionSlug>(slug: TSlug, confi
20
21
  const { getContext } = await getPayload({ config });
21
22
  const { routes } = await getContext('all', 'all');
22
23
  return (routes)
23
- .filter(r => r.schema === slug)
24
+ .filter(r => (getRouteTemplate(r) ?? r.schema) === slug)
24
25
  .map(route => ({
25
26
  market: route.market,
26
27
  locale: route.locale,
@@ -88,10 +89,7 @@ export function getStaticParamsFromPayload(schema: string, config: Promise<Sanit
88
89
  });
89
90
 
90
91
  return routes
91
- .filter(route => (
92
- route.schema === schema ||
93
- route.template === schema
94
- ))
92
+ .filter(route => (getRouteTemplate(route) ?? route.schema) === schema)
95
93
  .map(route => ({
96
94
  market: route.market,
97
95
  locale: route.locale,