@akinon/next 2.0.0-beta.1 → 2.0.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/.eslintrc.js +12 -0
  2. package/CHANGELOG.md +56 -0
  3. package/__tests__/next-config.test.ts +83 -0
  4. package/__tests__/tsconfig.json +23 -0
  5. package/api/auth.ts +72 -5
  6. package/api/client.ts +18 -1
  7. package/babel.config.js +6 -0
  8. package/bin/pz-prebuild.js +1 -0
  9. package/bin/pz-run-tests.js +99 -0
  10. package/bin/run-prebuild-tests.js +46 -0
  11. package/components/accordion.tsx +1 -1
  12. package/components/button.tsx +51 -36
  13. package/components/client-root.tsx +20 -0
  14. package/components/input.tsx +1 -1
  15. package/components/modal.tsx +1 -1
  16. package/components/price.tsx +2 -2
  17. package/components/select.tsx +1 -1
  18. package/components/selected-payment-option-view.tsx +1 -1
  19. package/data/client/api.ts +2 -0
  20. package/data/client/basket.ts +27 -5
  21. package/data/client/checkout.ts +62 -7
  22. package/data/client/misc.ts +25 -1
  23. package/data/client/product.ts +19 -2
  24. package/data/client/user.ts +16 -8
  25. package/data/server/flatpage.ts +8 -4
  26. package/data/server/form.ts +12 -4
  27. package/data/server/landingpage.ts +8 -4
  28. package/data/server/menu.ts +7 -2
  29. package/data/server/product.ts +16 -5
  30. package/data/server/seo.ts +11 -4
  31. package/data/server/widget.ts +19 -4
  32. package/data/urls.ts +11 -3
  33. package/hooks/index.ts +1 -0
  34. package/hooks/use-localization.ts +24 -10
  35. package/hooks/use-router.ts +5 -2
  36. package/hooks/use-sentry-uncaught-errors.ts +24 -0
  37. package/instrumentation/index.ts +10 -0
  38. package/jest.config.js +19 -0
  39. package/lib/cache-handler.mjs +2 -2
  40. package/lib/cache.ts +4 -4
  41. package/localization/index.ts +2 -1
  42. package/middlewares/default.ts +31 -4
  43. package/middlewares/locale.ts +35 -11
  44. package/middlewares/url-redirection.ts +16 -0
  45. package/package.json +8 -4
  46. package/plugins.js +2 -1
  47. package/redux/middlewares/checkout.ts +30 -130
  48. package/redux/middlewares/index.ts +6 -2
  49. package/redux/middlewares/pre-order/address.ts +50 -0
  50. package/redux/middlewares/pre-order/attribute-based-shipping-option.ts +46 -0
  51. package/redux/middlewares/pre-order/data-source-shipping-option.ts +43 -0
  52. package/redux/middlewares/pre-order/delivery-option.ts +40 -0
  53. package/redux/middlewares/pre-order/index.ts +29 -0
  54. package/redux/middlewares/pre-order/installment-option.ts +42 -0
  55. package/redux/middlewares/pre-order/payment-option.ts +34 -0
  56. package/redux/middlewares/pre-order/pre-order-validation.ts +24 -0
  57. package/redux/middlewares/pre-order/redirection.ts +40 -0
  58. package/redux/middlewares/pre-order/set-pre-order.ts +22 -0
  59. package/redux/middlewares/pre-order/shipping-option.ts +44 -0
  60. package/redux/middlewares/pre-order/shipping-step.ts +38 -0
  61. package/redux/reducers/checkout.ts +8 -2
  62. package/redux/reducers/index.ts +5 -3
  63. package/redux/reducers/root.ts +7 -2
  64. package/sentry/index.ts +36 -17
  65. package/tailwind/content.js +16 -0
  66. package/types/commerce/account.ts +5 -1
  67. package/types/commerce/checkout.ts +23 -0
  68. package/types/index.ts +7 -2
  69. package/utils/get-root-hostname.ts +28 -0
  70. package/utils/index.ts +6 -2
  71. package/utils/localization.ts +4 -0
  72. package/utils/override-middleware.ts +25 -0
  73. package/views/error-page.tsx +93 -0
  74. package/with-pz-config.js +4 -3
@@ -4,6 +4,7 @@ import { RetailStore } from './misc';
4
4
  import { PaymentOption } from './order';
5
5
  import { Product } from './product';
6
6
  import { JSX } from 'react';
7
+ import { RootState, TypedDispatch } from 'redux/store';
7
8
 
8
9
  export enum CheckoutStep {
9
10
  Shipping = 'shipping',
@@ -107,6 +108,7 @@ export interface PreOrder {
107
108
  context_extras?: ExtraField;
108
109
  token?: string;
109
110
  agreement_confirmed?: boolean;
111
+ phone_number?: string;
110
112
  }
111
113
 
112
114
  export type ExtraField = Record<string, any>;
@@ -186,3 +188,24 @@ export interface AttributeBasedShippingOption {
186
188
  attribute_key: string;
187
189
  [key: string]: any;
188
190
  }
191
+
192
+ export interface CheckoutResult {
193
+ payload: {
194
+ errors?: Record<string, string[]>;
195
+ pre_order?: PreOrder;
196
+ context_list?: CheckoutContext[];
197
+ };
198
+ }
199
+
200
+ export interface MiddlewareParams {
201
+ getState: () => RootState;
202
+ dispatch: TypedDispatch;
203
+ }
204
+
205
+ export type SendSmsType = {
206
+ phone_number: string;
207
+ };
208
+
209
+ export type VerifySmsType = {
210
+ verify_code: string;
211
+ };
package/types/index.ts CHANGED
@@ -199,15 +199,17 @@ export interface Settings {
199
199
  extraPaymentTypes?: string[];
200
200
  masterpassJsUrl?: string;
201
201
  };
202
- customNotFoundEnabled: boolean;
203
202
  useOptimizedTranslations?: boolean;
204
203
  plugins?: Record<string, Record<string, any>>;
205
204
  includedProxyHeaders?: string[];
205
+ commerceRedirectionIgnoreList?: string[];
206
206
  /**
207
207
  * By default, the currency will be reset when the currency is changed.
208
208
  * If you want to keep the basket when the currency is changed, you can set this option to `false`.
209
209
  */
210
210
  resetBasketOnCurrencyChange?: boolean;
211
+ frontendIds?: Record<string, number>;
212
+ customNotFoundEnabled: boolean;
211
213
  }
212
214
 
213
215
  export interface CacheOptions {
@@ -275,7 +277,10 @@ export interface IconProps extends React.ComponentPropsWithRef<'i'> {
275
277
 
276
278
  export interface ButtonProps
277
279
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
278
- appearance?: 'filled' | 'outlined' | 'ghost';
280
+ appearance?: 'filled' | 'outlined' | 'ghost' | 'link' | string;
281
+ size?: 'sm' | 'md' | 'lg' | 'xl';
282
+ href?: string;
283
+ target?: '_blank' | '_self' | '_parent' | '_top';
279
284
  }
280
285
 
281
286
  export type FileInputProps = React.HTMLProps<HTMLInputElement>;
@@ -0,0 +1,28 @@
1
+ import Settings from 'settings';
2
+
3
+ export default function getRootHostname(
4
+ url: string | undefined
5
+ ): string | null {
6
+ if (!url) return null;
7
+
8
+ try {
9
+ const urlObj = new URL(url);
10
+ const hostname = urlObj.hostname;
11
+ const parts = hostname.split('.');
12
+
13
+ const firstPart = parts[0];
14
+
15
+ const isLocale = Settings.localization.locales.some(
16
+ (locale) => locale.value === firstPart
17
+ );
18
+
19
+ if (isLocale) {
20
+ const hostnameAfterLocale = parts.slice(1).join('.');
21
+ return `.${hostnameAfterLocale}`;
22
+ }
23
+
24
+ return `.${hostname}`;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
package/utils/index.ts CHANGED
@@ -152,11 +152,15 @@ export function buildCDNUrl(url: string, config?: CDNOptions) {
152
152
  return `${rootWithoutOptions}${options}${fileExtension}`;
153
153
  }
154
154
 
155
+ const { locales, localeUrlStrategy, defaultLocaleValue } =
156
+ settings.localization;
157
+
155
158
  export const urlLocaleMatcherRegex = new RegExp(
156
159
  `^/(${settings.localization.locales
157
160
  .filter((l) =>
158
- settings.localization.localeUrlStrategy !==
159
- LocaleUrlStrategy.ShowAllLocales
161
+ ![LocaleUrlStrategy.ShowAllLocales, LocaleUrlStrategy.Subdomain].includes(
162
+ settings.localization.localeUrlStrategy
163
+ )
160
164
  ? l.value !== settings.localization.defaultLocaleValue
161
165
  : l
162
166
  )
@@ -11,6 +11,10 @@ export const getUrlPathWithLocale = (
11
11
  currentLocale = defaultLocaleValue;
12
12
  }
13
13
 
14
+ if (localeUrlStrategy === LocaleUrlStrategy.Subdomain) {
15
+ return pathname;
16
+ }
17
+
14
18
  if (localeUrlStrategy === LocaleUrlStrategy.HideAllLocales) {
15
19
  return pathname;
16
20
  }
@@ -0,0 +1,25 @@
1
+ import { Middleware } from '@reduxjs/toolkit';
2
+
3
+ export enum MiddlewareNames {
4
+ PreOrderValidationMiddleware = 'preOrderValidationMiddleware',
5
+ RedirectionMiddleware = 'redirectionMiddleware',
6
+ SetPreOrderMiddleware = 'setPreOrderMiddleware',
7
+ DeliveryOptionMiddleware = 'deliveryOptionMiddleware',
8
+ SetAddressMiddleware = 'setAddressMiddleware',
9
+ ShippingOptionMiddleware = 'shippingOptionMiddleware',
10
+ DataSourceShippingOptionMiddleware = 'dataSourceShippingOptionMiddleware',
11
+ AttributeBasedShippingOptionMiddleware = 'attributeBasedShippingOptionMiddleware',
12
+ PaymentOptionMiddleware = 'paymentOptionMiddleware',
13
+ InstallmentOptionMiddleware = 'installmentOptionMiddleware',
14
+ ShippingStepMiddleware = 'shippingStepMiddleware'
15
+ }
16
+
17
+ export const overrideMiddleware = (
18
+ originalMiddlewares: Middleware[],
19
+ overrides: Record<string, Middleware>
20
+ ): Middleware[] => {
21
+ return originalMiddlewares.map((middleware) => {
22
+ const middlewareKey = middleware.name || middleware.toString();
23
+ return overrides[middlewareKey] || middleware;
24
+ });
25
+ };
@@ -0,0 +1,93 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useLocalization } from '../hooks';
3
+ import { Button, Link } from '../components';
4
+ import { ROUTES } from 'routes';
5
+
6
+ export default function PzErrorPage({
7
+ error,
8
+ reset
9
+ }: {
10
+ error: Error & { digest?: string; isServerError?: boolean };
11
+ reset: () => void;
12
+ }) {
13
+ const [isServerError, setIsServerError] = useState(false);
14
+
15
+ useEffect(() => {
16
+ if ('isServerError' in error) {
17
+ setIsServerError(true);
18
+ return;
19
+ }
20
+
21
+ setIsServerError(!!error.digest);
22
+ }, [error]);
23
+
24
+ return isServerError ? (
25
+ <ServerErrorUI />
26
+ ) : (
27
+ <ClientErrorUI error={error} reset={reset} />
28
+ );
29
+ }
30
+
31
+ function ClientErrorUI({
32
+ error,
33
+ reset
34
+ }: {
35
+ error: Error & { digest?: string };
36
+ reset: () => void;
37
+ }) {
38
+ const { t } = useLocalization();
39
+
40
+ const errorMessage = error?.message || 'Unknown error';
41
+
42
+ return (
43
+ <section className="text-center px-6 py-6 my-14 md:px-0 md:m-14">
44
+ <div className="text-4xl font-bold md:text-6xl text-red-500">500</div>
45
+ <h1 className="text-lg md:text-xl mt-4">
46
+ {t('common.client_error.title')}
47
+ </h1>
48
+ <p className="text-lg md:text-xl mt-2">
49
+ {t('common.client_error.description')}
50
+ </p>
51
+
52
+ <div className="mt-4 mx-auto max-w-lg">
53
+ <p className="text-xs text-gray-600 font-mono bg-gray-100 p-3 rounded overflow-auto text-left">
54
+ <span className="font-semibold">Error:</span> {errorMessage}
55
+ </p>
56
+ </div>
57
+
58
+ <div className="mt-6 flex flex-col gap-4 items-center justify-center">
59
+ <Link href={ROUTES.HOME} className="text-lg underline">
60
+ {t('common.client_error.link_text')}
61
+ </Link>
62
+ <Button onClick={reset} className="text-lg">
63
+ {t('common.try_again')}
64
+ </Button>
65
+ </div>
66
+ </section>
67
+ );
68
+ }
69
+
70
+ function ServerErrorUI() {
71
+ const { t } = useLocalization();
72
+
73
+ const reloadPage = () => {
74
+ window.location.reload();
75
+ };
76
+
77
+ return (
78
+ <section className="text-center px-6 my-14 md:px-0 md:m-14">
79
+ <div className="text-7xl font-bold md:text-8xl">500</div>
80
+ <h1 className="text-lg md:text-xl"> {t('common.page_500.title')} </h1>
81
+ <p className="text-lg md:text-xl"> {t('common.page_500.description')} </p>
82
+
83
+ <div className="mt-6 flex flex-col gap-4 items-center justify-center">
84
+ <Link href={ROUTES.HOME} className="text-lg underline">
85
+ {t('common.page_500.link_text')}
86
+ </Link>
87
+ <Button onClick={reloadPage} className="text-lg">
88
+ {t('common.try_again')}
89
+ </Button>
90
+ </div>
91
+ </section>
92
+ );
93
+ }
package/with-pz-config.js CHANGED
@@ -44,8 +44,9 @@ const defaultConfig = {
44
44
  value: 'max-age=63072000; includeSubDomains; preload'
45
45
  },
46
46
  {
47
- key: 'X-Frame-Options',
48
- value: 'SAMEORIGIN'
47
+ key: 'Content-Security-Policy',
48
+ value:
49
+ "frame-ancestors 'self' https://*.akifast.com akifast.com https://*.akinoncloud.com akinoncloud.com"
49
50
  }
50
51
  ]
51
52
  }
@@ -64,7 +65,7 @@ const defaultConfig = {
64
65
  },
65
66
  sentry: {
66
67
  hideSourceMaps: true
67
- }
68
+ } // TODO: This section will be reviewed again in the Sentry 8 update.
68
69
  };
69
70
 
70
71
  const withPzConfig = (