@akinon/next 1.34.0-rc.2 → 1.34.0-rc.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,16 +1,22 @@
1
1
  # @akinon/next
2
2
 
3
- ## 1.34.0-rc.2
3
+ ## 1.34.0-rc.20
4
4
 
5
5
  ### Minor Changes
6
6
 
7
+ - a4c8d6a: ZERO-2663: Fix the image url for gif and svgs and return them without options
7
8
  - d09b677: ZERO-2577: Fix pagination bug and update usePagination hook and ensure pagination controls rendering correctly
8
9
  - 6d4aadb: ZERO-2476: Auto install recommendenent extension
10
+ - 8e6e8cf: ZERO-2524: Removed cli from projectzero so that build works as expected
11
+ - c53ef7b: ZERO-2668: The Link component has been updated to improve the logic for handling href values. Previously, if the href was not a string or started with 'http', it would return the href as is. Now, if the href is not provided, it will default to '#' to prevent any potential errors. Additionally, if the href is a string and does not start with 'http', it will be formatted with the locale and pathname, based on the localeUrlStrategy and defaultLocaleValue. This ensures that the correct href is generated based on the localization settings.
9
12
  - ebb63ce: ZERO-2525: Fix category facet removal bug and add close icon to active filters
10
13
  - 7cebe87: ZERO-2524: Add check monorepo utility function
14
+ - 91265bb: ZERO-2551: Improve pretty url and caching performance
15
+ - bbe18b9: ZERO-2575: Fix build error
11
16
  - f0c23bc: ZERO-2135: add custom not found page
12
17
  - 3420416: ZERO-2533: extend eslint config from @akinon/next
13
18
  - 495d155: ZERO-2505: findBaseDir function is united and move on to the utils
19
+ - beb499e: ZERO-2551: Add new tsconfig paths
14
20
  - 40ad73e: ZERO-2504: add cookie filter to api client request
15
21
  - 495d155: ZERO-2524: Zero-cli dist checks for changes and renders it to the terminal.
16
22
  - f046f8e: ZERO-2575: update version for react-number-format
@@ -19,15 +25,88 @@
19
25
 
20
26
  ### Patch Changes
21
27
 
22
- - 10123f9: ZERO-2632: rename projectzero-cli to projectzero
28
+ - 616690d: ZERO-2635: remove maxRetries from redux
29
+ - 59fb7c3: ZERO-2504: get set-cookie headers from commerce request
30
+
31
+ ## 1.34.0-rc.19
32
+
33
+ ### Minor Changes
34
+
35
+ - c53ef7b: ZERO-2668: The Link component has been updated to improve the logic for handling href values. Previously, if the href was not a string or started with 'http', it would return the href as is. Now, if the href is not provided, it will default to '#' to prevent any potential errors. Additionally, if the href is a string and does not start with 'http', it will be formatted with the locale and pathname, based on the localeUrlStrategy and defaultLocaleValue. This ensures that the correct href is generated based on the localization settings.
36
+
37
+ ## 1.34.0-rc.18
38
+
39
+ ### Minor Changes
23
40
 
24
- ## 1.34.0-rc.1
41
+ - a4c8d6a: ZERO-2663: Fix the image url for gif and svgs and return them without options
42
+
43
+ ## 1.34.0-rc.17
44
+
45
+ ### Minor Changes
46
+
47
+ - d09b677: ZERO-2577: Fix pagination bug and update usePagination hook and ensure pagination controls rendering correctly
48
+ - 6d4aadb: ZERO-2476: Auto install recommendenent extension
49
+ - 8e6e8cf: ZERO-2524: Removed cli from projectzero so that build works as expected
50
+ - ebb63ce: ZERO-2525: Fix category facet removal bug and add close icon to active filters
51
+ - 7cebe87: ZERO-2524: Add check monorepo utility function
52
+ - 91265bb: ZERO-2551: Improve pretty url and caching performance
53
+ - bbe18b9: ZERO-2575: Fix build error
54
+ - f0c23bc: ZERO-2135: add custom not found page
55
+ - 3420416: ZERO-2533: extend eslint config from @akinon/next
56
+ - 495d155: ZERO-2505: findBaseDir function is united and move on to the utils
57
+ - beb499e: ZERO-2551: Add new tsconfig paths
58
+ - 40ad73e: ZERO-2504: add cookie filter to api client request
59
+ - 495d155: ZERO-2524: Zero-cli dist checks for changes and renders it to the terminal.
60
+ - f046f8e: ZERO-2575: update version for react-number-format
61
+ - 6b2972b: ZERO-2514: Fix handling of status 204 and return Commerce status code in client proxy API.
62
+ - 3e68768: ZERO-2578: Add osessionid check in middleware
25
63
 
26
64
  ### Patch Changes
27
65
 
28
- - 10123f9: ZERO-2632: rename projectzero-cli to projectzero
66
+ - 616690d: ZERO-2635: remove maxRetries from redux
67
+ - 59fb7c3: ZERO-2504: get set-cookie headers from commerce request
68
+
69
+ ## 1.34.0-rc.16
70
+
71
+ ## 1.34.0-rc.15
29
72
 
30
- ## 1.34.0-rc.0
73
+ ## 1.34.0-rc.14
74
+
75
+ ## 1.34.0-rc.13
76
+
77
+ ## 1.34.0-rc.12
78
+
79
+ ### Patch Changes
80
+
81
+ - 616690d: ZERO-2635: remove maxRetries from redux
82
+
83
+ ## 1.34.0-rc.11
84
+
85
+ ### Minor Changes
86
+
87
+ - 8e6e8cf: ZERO-2524: Removed cli from projectzero so that build works as expected
88
+
89
+ ## 1.34.0-rc.10
90
+
91
+ ### Minor Changes
92
+
93
+ - bbe18b9: ZERO-2575: Fix build error
94
+
95
+ ## 1.34.0-rc.9
96
+
97
+ ### Minor Changes
98
+
99
+ - beb499e: ZERO-2551: Add new tsconfig paths
100
+
101
+ ## 1.34.0-rc.8
102
+
103
+ ### Minor Changes
104
+
105
+ - 91265bb: ZERO-2551: Improve pretty url and caching performance
106
+
107
+ ## 1.34.0-rc.7
108
+
109
+ ## 1.34.0-rc.6
31
110
 
32
111
  ### Minor Changes
33
112
 
@@ -44,6 +123,18 @@
44
123
  - 6b2972b: ZERO-2514: Fix handling of status 204 and return Commerce status code in client proxy API.
45
124
  - 3e68768: ZERO-2578: Add osessionid check in middleware
46
125
 
126
+ ### Patch Changes
127
+
128
+ - 59fb7c3: ZERO-2504: get set-cookie headers from commerce request
129
+
130
+ ## 1.33.2
131
+
132
+ ## 1.33.1
133
+
134
+ ### Patch Changes
135
+
136
+ - 10123f9: ZERO-2632: rename projectzero-cli to projectzero
137
+
47
138
  ## 1.33.0
48
139
 
49
140
  ## 1.32.0
package/api/client.ts CHANGED
@@ -141,7 +141,7 @@ async function proxyRequest(...args) {
141
141
  );
142
142
  }
143
143
 
144
- const setCookieHeaders = req.headers.getSetCookie();
144
+ const setCookieHeaders = request.headers.getSetCookie();
145
145
  const exceptCookieKeys = ['pz-locale', 'pz-currency'];
146
146
 
147
147
  const isExcludedCookie = (name: string) => exceptCookieKeys.includes(name);
@@ -11,11 +11,11 @@ if (!BASE_DIR) {
11
11
 
12
12
  const packageDistPath = path.join(
13
13
  __dirname,
14
- '../../../packages/projectzero-cli/dist/commands'
14
+ '../../../packages/projectzero/dist/commands'
15
15
  );
16
16
 
17
17
  const hash = hashDirectory(packageDistPath);
18
18
  fs.writeFileSync(
19
- path.join(__dirname, '../../../packages/projectzero-cli/dist/dist-hash.txt'),
19
+ path.join(__dirname, '../../../packages/projectzero/dist/dist-hash.txt'),
20
20
  hash
21
21
  );
@@ -1,6 +1,7 @@
1
1
  import clsx from 'clsx';
2
2
  import { forwardRef, FocusEvent, useState, Ref } from 'react';
3
3
  import { Controller } from 'react-hook-form';
4
+ // @ts-ignore
4
5
  import { PatternFormat, PatternFormatProps } from 'react-number-format';
5
6
  import { InputProps } from '../types';
6
7
  import { twMerge } from 'tailwind-merge';
@@ -10,28 +10,32 @@ type LinkProps = Omit<
10
10
  React.AnchorHTMLAttributes<HTMLAnchorElement>,
11
11
  keyof NextLinkProps
12
12
  > &
13
- NextLinkProps;
13
+ NextLinkProps & {
14
+ href: string;
15
+ };
14
16
 
15
17
  export const Link = ({ children, href, ...rest }: LinkProps) => {
16
18
  const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
17
19
  const formattedHref = useMemo(() => {
18
- if (typeof href !== 'string' || href.startsWith('http')) {
19
- return href;
20
+ if (!href) {
21
+ return '#';
20
22
  }
21
23
 
22
- const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
23
- const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
24
+ if (typeof href === 'string' && !href.startsWith('http')) {
25
+ const pathnameWithoutLocale = href.replace(urlLocaleMatcherRegex, '');
26
+ const hrefWithLocale = `/${locale}${pathnameWithoutLocale}`;
24
27
 
25
- if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
26
- return hrefWithLocale;
27
- } else if (
28
- localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
29
- locale !== defaultLocaleValue
30
- ) {
31
- return hrefWithLocale;
28
+ if (localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales) {
29
+ return hrefWithLocale;
30
+ } else if (
31
+ localeUrlStrategy === LocaleUrlStrategy.HideDefaultLocale &&
32
+ locale !== defaultLocaleValue
33
+ ) {
34
+ return hrefWithLocale;
35
+ }
32
36
  }
33
37
 
34
- return href || '#';
38
+ return href;
35
39
  }, [href, defaultLocaleValue, locale, localeUrlStrategy]);
36
40
 
37
41
  return (
@@ -1,4 +1,5 @@
1
1
  import { useMemo } from 'react';
2
+ // @ts-ignore
2
3
  import { NumericFormat, NumericFormatProps } from 'react-number-format';
3
4
  import { getCurrency } from '@akinon/next/utils';
4
5
 
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  createApi,
3
3
  fetchBaseQuery,
4
- retry,
5
4
  BaseQueryFn,
6
5
  FetchBaseQueryError,
7
6
  FetchBaseQueryMeta,
@@ -65,7 +64,7 @@ const customBaseQuery: BaseQueryFn<
65
64
 
66
65
  export const api = createApi({
67
66
  reducerPath: 'api',
68
- baseQuery: retry(customBaseQuery, { maxRetries: 3 }),
67
+ baseQuery: customBaseQuery,
69
68
  tagTypes: [
70
69
  'Basket',
71
70
  'BasketB2b',
@@ -8,7 +8,7 @@ import logger from '../../utils/log';
8
8
 
9
9
  function getCategoryDataHandler(
10
10
  pk: number,
11
- searchParams?: URLSearchParams,
11
+ searchParams?: { [key: string]: string | string[] | undefined },
12
12
  headers?: Record<string, string>
13
13
  ) {
14
14
  return async function () {
@@ -78,7 +78,7 @@ export const getCategoryData = ({
78
78
  headers
79
79
  }: {
80
80
  pk: number;
81
- searchParams?: URLSearchParams;
81
+ searchParams?: { [key: string]: string | string[] | undefined };
82
82
  headers?: Record<string, string>;
83
83
  }) => {
84
84
  return Cache.wrap(
@@ -7,7 +7,7 @@ import { parse } from 'lossless-json';
7
7
  import logger from '../../utils/log';
8
8
 
9
9
  const getListDataHandler = (
10
- searchParams: URLSearchParams,
10
+ searchParams: { [key: string]: string | string[] | undefined },
11
11
  headers?: Record<string, string>
12
12
  ) => {
13
13
  return async function () {
@@ -54,7 +54,7 @@ export const getListData = async ({
54
54
  searchParams,
55
55
  headers
56
56
  }: {
57
- searchParams: URLSearchParams;
57
+ searchParams: { [key: string]: string | string[] | undefined };
58
58
  headers?: Record<string, string>;
59
59
  }) => {
60
60
  return Cache.wrap(
@@ -9,7 +9,7 @@ import appFetch from '../../utils/app-fetch';
9
9
 
10
10
  type GetProduct = {
11
11
  pk: number;
12
- searchParams?: URLSearchParams;
12
+ searchParams?: { [key: string]: string | string[] | undefined };
13
13
  groupProduct?: boolean;
14
14
  };
15
15
 
@@ -74,10 +74,7 @@ export const getProductData = async ({
74
74
  groupProduct
75
75
  }: GetProduct) => {
76
76
  return Cache.wrap(
77
- CacheKey[groupProduct ? 'GroupProduct' : 'Product'](
78
- pk,
79
- searchParams ?? new URLSearchParams()
80
- ),
77
+ CacheKey[groupProduct ? 'GroupProduct' : 'Product'](pk, searchParams ?? {}),
81
78
  getProductDataHandler({ pk, searchParams, groupProduct }),
82
79
  {
83
80
  expire: 300
@@ -7,7 +7,7 @@ import header from '../../redux/reducers/header';
7
7
 
8
8
  const getSpecialPageDataHandler = (
9
9
  pk: number,
10
- searchParams: URLSearchParams,
10
+ searchParams: { [key: string]: string | string[] | undefined },
11
11
  headers?: Record<string, string>
12
12
  ) => {
13
13
  return async function () {
@@ -34,7 +34,7 @@ export const getSpecialPageData = async ({
34
34
  headers
35
35
  }: {
36
36
  pk: number;
37
- searchParams: URLSearchParams;
37
+ searchParams: { [key: string]: string | string[] | undefined };
38
38
  headers?: Record<string, string>;
39
39
  }) => {
40
40
  return Cache.wrap(
@@ -0,0 +1,33 @@
1
+ import { CacheHandler } from '@neshca/cache-handler';
2
+ import createLruHandler from '@neshca/cache-handler/local-lru';
3
+ import createRedisHandler from '@neshca/cache-handler/redis-stack';
4
+ import { createClient } from 'redis';
5
+
6
+ CacheHandler.onCreation(async () => {
7
+ const redisUrl = `redis://${process.env.CACHE_HOST}:${
8
+ process.env.CACHE_PORT
9
+ }/${process.env.CACHE_BUCKET ?? '0'}`;
10
+
11
+ const client = createClient({
12
+ url: redisUrl
13
+ });
14
+
15
+ client.on('error', (error) => {
16
+ console.error('Redis client error', { redisUrl, error });
17
+ });
18
+
19
+ await client.connect();
20
+
21
+ const redisHandler = await createRedisHandler({
22
+ client,
23
+ timeoutMs: 5000
24
+ });
25
+
26
+ const localHandler = createLruHandler();
27
+
28
+ return {
29
+ handlers: [redisHandler, localHandler]
30
+ };
31
+ });
32
+
33
+ export default CacheHandler;
package/lib/cache.ts CHANGED
@@ -20,13 +20,16 @@ const hashCacheKey = (object?: Record<string, string>) => {
20
20
  return `_${encodeURIComponent(cacheKey)}`;
21
21
  };
22
22
  export const CacheKey = {
23
- List: (searchParams: URLSearchParams, headers?: Record<string, string>) =>
23
+ List: (
24
+ searchParams: { [key: string]: string | string[] | undefined },
25
+ headers?: Record<string, string>
26
+ ) =>
24
27
  `list_${encodeURIComponent(JSON.stringify(searchParams))}${hashCacheKey(
25
28
  headers
26
29
  )}`,
27
30
  Category: (
28
31
  pk: number,
29
- searchParams?: URLSearchParams,
32
+ searchParams?: { [key: string]: string | string[] | undefined },
30
33
  headers?: Record<string, string>
31
34
  ) =>
32
35
  `category_${pk}_${encodeURIComponent(
@@ -35,15 +38,20 @@ export const CacheKey = {
35
38
  CategorySlug: (slug: string) => `category_${slug}`,
36
39
  SpecialPage: (
37
40
  pk: number,
38
- searchParams: URLSearchParams,
41
+ searchParams: { [key: string]: string | string[] | undefined },
39
42
  headers?: Record<string, string>
40
43
  ) =>
41
44
  `special_page_${pk}_${encodeURIComponent(
42
45
  JSON.stringify(searchParams)
43
46
  )}${hashCacheKey(headers)}`,
44
- Product: (pk: number, searchParams: URLSearchParams) =>
45
- `product_${pk}_${encodeURIComponent(JSON.stringify(searchParams))}`,
46
- GroupProduct: (pk: number, searchParams: URLSearchParams) =>
47
+ Product: (
48
+ pk: number,
49
+ searchParams: { [key: string]: string | string[] | undefined }
50
+ ) => `product_${pk}_${encodeURIComponent(JSON.stringify(searchParams))}`,
51
+ GroupProduct: (
52
+ pk: number,
53
+ searchParams: { [key: string]: string | string[] | undefined }
54
+ ) =>
47
55
  `group_product_${pk}_${encodeURIComponent(JSON.stringify(searchParams))}`,
48
56
  FlatPage: (pk: number) => `flat_page_${pk}`,
49
57
  LandingPage: (pk: number) => `landing_page_${pk}`,
@@ -158,6 +166,10 @@ export class Cache {
158
166
  handler: () => Promise<T>,
159
167
  options?: CacheOptions
160
168
  ): Promise<T> {
169
+ if (Settings.usePrettyUrlRoute) {
170
+ return await handler();
171
+ }
172
+
161
173
  const requiredVariables = [
162
174
  process.env.CACHE_HOST,
163
175
  process.env.CACHE_PORT,
@@ -200,6 +200,15 @@ const withPzDefault =
200
200
  );
201
201
  }
202
202
 
203
+ if (
204
+ Settings.usePrettyUrlRoute &&
205
+ url.searchParams.toString().length > 0
206
+ ) {
207
+ url.pathname =
208
+ url.pathname +
209
+ `searchparams|${url.searchParams.toString()}`;
210
+ }
211
+
203
212
  Settings.rewrites.forEach((rewrite) => {
204
213
  url.pathname = url.pathname.replace(
205
214
  rewrite.source,
@@ -56,6 +56,10 @@ const resolvePrettyUrl = async (pathname: string, ip: string | null) => {
56
56
  const withPrettyUrl =
57
57
  (middleware: NextMiddleware) =>
58
58
  async (req: PzNextRequest, event: NextFetchEvent) => {
59
+ if (Settings.usePrettyUrlRoute) {
60
+ return middleware(req, event);
61
+ }
62
+
59
63
  const url = req.nextUrl.clone();
60
64
  const matchedLanguagePrefix = url.pathname.match(
61
65
  urlLocaleMatcherRegex
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@akinon/next",
3
3
  "description": "Core package for Project Zero Next",
4
- "version": "1.34.0-rc.2",
4
+ "version": "1.34.0-rc.20",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -20,11 +20,12 @@
20
20
  "@opentelemetry/sdk-trace-node": "1.19.0",
21
21
  "@opentelemetry/semantic-conventions": "1.19.0",
22
22
  "@reduxjs/toolkit": "1.9.7",
23
+ "@neshca/cache-handler": "1.0.7",
23
24
  "cross-spawn": "7.0.3",
24
25
  "generic-pool": "3.9.0",
25
26
  "react-redux": "8.1.3",
26
27
  "react-string-replace": "1.1.1",
27
- "redis": "4.5.1",
28
+ "redis": "4.6.13",
28
29
  "semver": "7.5.4",
29
30
  "set-cookie-parser": "2.6.0"
30
31
  },
@@ -34,7 +35,7 @@
34
35
  "@typescript-eslint/eslint-plugin": "6.7.4",
35
36
  "@typescript-eslint/parser": "6.7.4",
36
37
  "eslint": "^8.14.0",
37
- "@akinon/eslint-plugin-projectzero": "1.34.0-rc.2",
38
+ "@akinon/eslint-plugin-projectzero": "1.34.0-rc.20",
38
39
  "eslint-config-prettier": "8.5.0"
39
40
  }
40
41
  }
@@ -0,0 +1,194 @@
1
+ import { URLS } from '@akinon/next/data/urls';
2
+ import { Metadata, PageProps } from '@akinon/next/types';
3
+ import logger from '@akinon/next/utils/log';
4
+ import { notFound } from 'next/navigation';
5
+
6
+ type PrettyUrlResult = {
7
+ matched: boolean;
8
+ path?: string;
9
+ pk?: number;
10
+ };
11
+
12
+ const resolvePrettyUrlHandler =
13
+ (pathname: string, ip: string | null) => async () => {
14
+ let results = [] as { old_path: string }[];
15
+ let prettyUrlResult: PrettyUrlResult = {
16
+ matched: false
17
+ };
18
+
19
+ try {
20
+ const requestUrl = URLS.misc.prettyUrls(`/${pathname}/`);
21
+
22
+ logger.debug(`Resolving pretty url`, { pathname, requestUrl, ip });
23
+
24
+ const start = Date.now();
25
+ const apiResponse = await fetch(requestUrl, {
26
+ next: {
27
+ revalidate: 0
28
+ }
29
+ });
30
+ const data = await apiResponse.json();
31
+ ({ results } = data);
32
+ const end = Date.now();
33
+ console.warn('Pretty url response time', end - start, requestUrl);
34
+
35
+ const matched = results.length > 0;
36
+ const [{ old_path: path } = { old_path: '' }] = results;
37
+ let pk;
38
+
39
+ if (matched) {
40
+ const pkRegex = /\/(\d+)\/$/;
41
+ const match = path.match(pkRegex);
42
+ pk = match ? parseInt(match[1]) : undefined;
43
+ }
44
+
45
+ prettyUrlResult = {
46
+ matched,
47
+ path,
48
+ pk
49
+ };
50
+
51
+ logger.trace('Pretty url result', { prettyUrlResult, ip });
52
+ } catch (error) {
53
+ logger.error('Error resolving pretty url', { error, pathname, ip });
54
+ }
55
+
56
+ return prettyUrlResult;
57
+ };
58
+
59
+ export async function generateMetadata({ params }: PageProps) {
60
+ let result: Metadata = {};
61
+ const { prettyurl } = params;
62
+ const pageSlug = prettyurl
63
+ .filter((x) => !x.startsWith('searchparams'))
64
+ .join('/');
65
+
66
+ const searchParams = Object.fromEntries(
67
+ new URLSearchParams(
68
+ decodeURIComponent(
69
+ prettyurl
70
+ .find((x) => x.startsWith('searchparams'))
71
+ ?.replace('searchparams%7C', '')
72
+ ) ?? {}
73
+ ).entries()
74
+ );
75
+
76
+ const prettyUrlResult = await resolvePrettyUrlHandler(pageSlug, null)();
77
+
78
+ if (!prettyUrlResult.matched) {
79
+ return notFound();
80
+ }
81
+
82
+ const commonProps = {
83
+ params: {
84
+ ...params,
85
+ pk: prettyUrlResult.pk
86
+ },
87
+ searchParams
88
+ };
89
+
90
+ try {
91
+ if (prettyUrlResult.path.startsWith('/product/')) {
92
+ await import('@product/[pk]/page').then(async (module) => {
93
+ result = await module['generateMetadata']?.(commonProps);
94
+ });
95
+ }
96
+
97
+ if (prettyUrlResult.path.startsWith('/group-product/')) {
98
+ await import('@group-product/[pk]/page').then(async (module) => {
99
+ result = await module['generateMetadata']?.(commonProps);
100
+ });
101
+ }
102
+
103
+ if (prettyUrlResult.path.startsWith('/category/')) {
104
+ await import('@category/[pk]/page').then(async (module) => {
105
+ result = await module['generateMetadata']?.(commonProps);
106
+ });
107
+ }
108
+
109
+ if (prettyUrlResult.path.startsWith('/special-page/')) {
110
+ await import('@special-page/[pk]/page').then(async (module) => {
111
+ result = await module['generateMetadata']?.(commonProps);
112
+ });
113
+ }
114
+
115
+ if (prettyUrlResult.path.startsWith('/flat-page/')) {
116
+ await import('@flat-page/[pk]/page').then(async (module) => {
117
+ result = await module['generateMetadata']?.(commonProps);
118
+ });
119
+ }
120
+ // eslint-disable-next-line no-empty
121
+ } catch (error) {}
122
+
123
+ return result;
124
+ }
125
+
126
+ export const dynamic = 'force-static';
127
+ export const revalidate = 300;
128
+
129
+ export default async function Page({ params }) {
130
+ const { prettyurl } = params;
131
+ const pageSlug = prettyurl
132
+ .filter((x) => !x.startsWith('searchparams'))
133
+ .join('/');
134
+
135
+ const urlSearchParams = new URLSearchParams(
136
+ decodeURIComponent(
137
+ prettyurl
138
+ .find((x) => x.startsWith('searchparams'))
139
+ ?.replace('searchparams%7C', '')
140
+ ) ?? {}
141
+ );
142
+
143
+ const searchParams = {};
144
+
145
+ for (const [key, value] of urlSearchParams.entries() as unknown as Array<
146
+ [string, string]
147
+ >) {
148
+ if (!searchParams[key]) {
149
+ searchParams[key] = [];
150
+ }
151
+ searchParams[key].push(value);
152
+ }
153
+
154
+ const result = await resolvePrettyUrlHandler(pageSlug, null)();
155
+
156
+ if (!result.matched) {
157
+ return notFound();
158
+ }
159
+
160
+ const commonProps = {
161
+ params: {
162
+ ...params,
163
+ pk: result.pk
164
+ },
165
+ searchParams
166
+ };
167
+
168
+ if (result.path.startsWith('/category/')) {
169
+ const CategoryPage = (await import('@category/[pk]/page')).default;
170
+ return <CategoryPage {...commonProps} />;
171
+ }
172
+
173
+ if (result.path.startsWith('/product/')) {
174
+ const ProductPage = (await import('@product/[pk]/page')).default;
175
+ return <ProductPage {...commonProps} />;
176
+ }
177
+
178
+ if (result.path.startsWith('/group-product/')) {
179
+ const GroupProduct = (await import('@group-product/[pk]/page')).default;
180
+ return <GroupProduct {...commonProps} />;
181
+ }
182
+
183
+ if (result.path.startsWith('/special-page/')) {
184
+ const SpecialPage = (await import('@special-page/[pk]/page')).default;
185
+ return <SpecialPage {...commonProps} />;
186
+ }
187
+
188
+ if (result.path.startsWith('/flat-page/')) {
189
+ const FlatPage = (await import('@flat-page/[pk]/page')).default;
190
+ return <FlatPage {...commonProps} />;
191
+ }
192
+
193
+ return null;
194
+ }
package/types/index.ts CHANGED
@@ -70,6 +70,7 @@ export interface Currency {
70
70
  }
71
71
 
72
72
  export interface Settings {
73
+ usePrettyUrlRoute?: boolean;
73
74
  commerceUrl: string;
74
75
  redis: {
75
76
  defaultExpirationTime: number;
@@ -214,7 +215,7 @@ export type Translations = { [key: string]: object };
214
215
 
215
216
  export interface PageProps<T = any> {
216
217
  params: T;
217
- searchParams: URLSearchParams;
218
+ searchParams: { [key: string]: string | string[] | undefined };
218
219
  }
219
220
 
220
221
  export interface LayoutProps<T = any> extends PageProps<T> {
@@ -41,7 +41,7 @@ const appFetch = async <T>(
41
41
  };
42
42
 
43
43
  init.next = {
44
- revalidate: 60
44
+ revalidate: Settings.usePrettyUrlRoute ? 0 : 60
45
45
  };
46
46
 
47
47
  logger.debug(`FETCH START ${url}`, { requestURL, init, ip });
@@ -1,11 +1,15 @@
1
1
  import logger from './log';
2
2
 
3
- export const generateCommerceSearchParams = (searchParams?: URLSearchParams) => {
3
+ export const generateCommerceSearchParams = (searchParams?: {
4
+ [key: string]: string | string[] | undefined;
5
+ }) => {
4
6
  if (!searchParams) {
5
7
  return null;
6
8
  }
7
9
 
8
- const urlSerchParams = new URLSearchParams(searchParams);
10
+ const urlSerchParams = new URLSearchParams(
11
+ searchParams as Record<string, string>
12
+ );
9
13
 
10
14
  Object.entries(searchParams).forEach(([key, value]) => {
11
15
  if (typeof value === 'object') {
package/utils/index.ts CHANGED
@@ -102,6 +102,12 @@ export function buildCDNUrl(url: string, config?: CDNOptions) {
102
102
  ''
103
103
  );
104
104
 
105
+ const noOptionFileExtension = url?.split('.').pop()?.toLowerCase() ?? '';
106
+
107
+ if (noOptionFileExtension === 'svg' || noOptionFileExtension === 'gif') {
108
+ return url;
109
+ }
110
+
105
111
  let options = '';
106
112
 
107
113
  if (config) {
package/with-pz-config.js CHANGED
@@ -8,6 +8,7 @@ const defaultConfig = {
8
8
  transpilePackages: ['@akinon/next', ...pzPlugins.map((p) => `@akinon/${p}`)],
9
9
  skipTrailingSlashRedirect: true,
10
10
  poweredByHeader: false,
11
+ cacheMaxMemorySize: 0,
11
12
  env: {
12
13
  NEXT_PUBLIC_SENTRY_DSN: process.env.SENTRY_DSN
13
14
  },
@@ -65,7 +66,12 @@ const defaultConfig = {
65
66
  }
66
67
  };
67
68
 
68
- const withPzConfig = (myNextConfig = {}) => {
69
+ const withPzConfig = (
70
+ myNextConfig = {},
71
+ options = {
72
+ useCacheHandler: false
73
+ }
74
+ ) => {
69
75
  let extendedConfig = deepMerge({}, defaultConfig, myNextConfig);
70
76
 
71
77
  const originalPzHeadersFunction = defaultConfig.headers;
@@ -91,6 +97,10 @@ const withPzConfig = (myNextConfig = {}) => {
91
97
  return [...pzRewrites, ...myRewrites];
92
98
  };
93
99
 
100
+ if (options.useCacheHandler) {
101
+ extendedConfig.cacheHandler = require.resolve('./lib/cache-handler.mjs');
102
+ }
103
+
94
104
  return extendedConfig;
95
105
  };
96
106