@akinon/next 1.0.0

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 (98) hide show
  1. package/.prettierrc +13 -0
  2. package/api/auth.ts +217 -0
  3. package/api/cache.ts +44 -0
  4. package/api/client.ts +157 -0
  5. package/api/logout.ts +42 -0
  6. package/assets/styles/index.scss +24 -0
  7. package/bin/pz-install-plugins.js +33 -0
  8. package/components/client-root.tsx +69 -0
  9. package/components/image.tsx +133 -0
  10. package/components/mobile-app-toggler.tsx +15 -0
  11. package/components/oauth-login.tsx +24 -0
  12. package/components/plugin-module.tsx +78 -0
  13. package/components/pz-providers.tsx +24 -0
  14. package/components/pz-root.tsx +21 -0
  15. package/components/redirect-three-d/content/index.tsx +64 -0
  16. package/components/redirect-three-d/index.tsx +17 -0
  17. package/components/selected-payment-option-view.tsx +66 -0
  18. package/components/trans.tsx +39 -0
  19. package/data/client/account.ts +188 -0
  20. package/data/client/address.ts +107 -0
  21. package/data/client/api.ts +42 -0
  22. package/data/client/basket.ts +85 -0
  23. package/data/client/checkout.ts +477 -0
  24. package/data/client/misc.ts +101 -0
  25. package/data/client/product.ts +90 -0
  26. package/data/client/user.ts +83 -0
  27. package/data/client/wishlist.ts +79 -0
  28. package/data/server/category.ts +121 -0
  29. package/data/server/flatpage.ts +21 -0
  30. package/data/server/index.ts +8 -0
  31. package/data/server/list.ts +56 -0
  32. package/data/server/menu.ts +35 -0
  33. package/data/server/product.ts +86 -0
  34. package/data/server/seo.ts +48 -0
  35. package/data/server/special-page.ts +42 -0
  36. package/data/server/widget.ts +27 -0
  37. package/data/urls.ts +184 -0
  38. package/hocs/client/index.ts +1 -0
  39. package/hocs/client/with-segment-defaults.tsx +26 -0
  40. package/hocs/server/index.ts +1 -0
  41. package/hocs/server/with-segment-defaults.tsx +83 -0
  42. package/hooks/index.ts +8 -0
  43. package/hooks/use-captcha.tsx +76 -0
  44. package/hooks/use-common-product-attributes.ts +36 -0
  45. package/hooks/use-debounce.ts +20 -0
  46. package/hooks/use-localization.ts +63 -0
  47. package/hooks/use-media-query.ts +36 -0
  48. package/hooks/use-on-click-outside.tsx +28 -0
  49. package/hooks/use-router.ts +45 -0
  50. package/hooks/use-translation.ts +14 -0
  51. package/lib/cache.ts +185 -0
  52. package/localization/index.ts +5 -0
  53. package/localization/provider.tsx +58 -0
  54. package/middlewares/currency.ts +55 -0
  55. package/middlewares/default.ts +224 -0
  56. package/middlewares/index.ts +29 -0
  57. package/middlewares/locale.ts +61 -0
  58. package/middlewares/oauth-login.ts +78 -0
  59. package/middlewares/pretty-url.ts +94 -0
  60. package/middlewares/redirection-payment.ts +117 -0
  61. package/middlewares/three-d-redirection.ts +122 -0
  62. package/middlewares/url-redirection.ts +61 -0
  63. package/package.json +20 -0
  64. package/plugins.js +7 -0
  65. package/redux/hooks.ts +7 -0
  66. package/redux/middlewares/checkout.ts +231 -0
  67. package/redux/middlewares/index.ts +50 -0
  68. package/redux/reducers/checkout.ts +164 -0
  69. package/redux/reducers/config.ts +28 -0
  70. package/redux/reducers/header.ts +59 -0
  71. package/redux/reducers/index.ts +15 -0
  72. package/redux/reducers/root.ts +61 -0
  73. package/tailwind/rtl.js +137 -0
  74. package/types/commerce/account.ts +68 -0
  75. package/types/commerce/address.ts +94 -0
  76. package/types/commerce/basket.ts +43 -0
  77. package/types/commerce/category.ts +114 -0
  78. package/types/commerce/checkout.ts +132 -0
  79. package/types/commerce/flatpage.ts +7 -0
  80. package/types/commerce/index.ts +10 -0
  81. package/types/commerce/misc.ts +127 -0
  82. package/types/commerce/order.ts +108 -0
  83. package/types/commerce/product.ts +110 -0
  84. package/types/commerce/widget.ts +28 -0
  85. package/types/gtm.ts +16 -0
  86. package/types/index.ts +207 -0
  87. package/types/next-auth.d.ts +24 -0
  88. package/utils/app-fetch.ts +62 -0
  89. package/utils/generate-commerce-search-params.ts +22 -0
  90. package/utils/get-currency.ts +29 -0
  91. package/utils/image-loader.ts +31 -0
  92. package/utils/index.ts +132 -0
  93. package/utils/localization.ts +29 -0
  94. package/utils/log.ts +138 -0
  95. package/utils/menu-generator.ts +27 -0
  96. package/utils/mobile-3d-iframe.ts +58 -0
  97. package/utils/server-translation.ts +57 -0
  98. package/utils/server-variables.ts +9 -0
@@ -0,0 +1,127 @@
1
+ import { District } from './address';
2
+ export interface Config {
3
+ user_phone_regex: string;
4
+ user_phone_format: string;
5
+ country: {
6
+ pk: number;
7
+ name: string;
8
+ code: string;
9
+ };
10
+ }
11
+
12
+ export interface RetailStore {
13
+ address: string;
14
+ name: string;
15
+ pk: number;
16
+ district: District;
17
+ township: {
18
+ name: string;
19
+ pk: number;
20
+ city: {
21
+ country: number;
22
+ name: string;
23
+ pk: number;
24
+ };
25
+ };
26
+ }
27
+
28
+ export type Pagination = {
29
+ current_page: number;
30
+ num_pages: number;
31
+ page_size: number;
32
+ total_count: number;
33
+ };
34
+
35
+ export type EmailSubscriptionType = {
36
+ email: string;
37
+ subscribe_contract: boolean;
38
+ };
39
+
40
+ export type ImageType = {
41
+ data_type?: 'image';
42
+ url?: string;
43
+ value?: string;
44
+ };
45
+
46
+ export interface Error {
47
+ status: number;
48
+ data: {
49
+ error_code: string;
50
+ non_field_errors: string;
51
+ };
52
+ }
53
+
54
+ export type Discount = {
55
+ description: string;
56
+ discount: string;
57
+ };
58
+
59
+ export type MenuItemExtraContentImageType = {
60
+ kwargs: {
61
+ value: {
62
+ image: {
63
+ url: string;
64
+ value: string;
65
+ };
66
+ };
67
+ };
68
+ value: {
69
+ image: string;
70
+ link_text: string;
71
+ title: string;
72
+ url: string;
73
+ };
74
+ };
75
+
76
+ export type MenuItemExtraContentStoryType = {
77
+ value: {
78
+ url: string;
79
+ alt: string;
80
+ image: string;
81
+ };
82
+ kwargs: {
83
+ data_type: 'nested';
84
+ value: {
85
+ image: ImageType;
86
+ };
87
+ };
88
+ };
89
+
90
+ export type MenuItemExtraContentType = {
91
+ attributes: {
92
+ category_id: number;
93
+ images: Array<MenuItemExtraContentImageType>;
94
+ [key: string]: any;
95
+ };
96
+ include_parent: boolean;
97
+ numchild: number;
98
+ [key: string]: any;
99
+ };
100
+
101
+ export type MenuItemType = {
102
+ extra_context: MenuItemExtraContentType;
103
+ generator_name: 'menu_item';
104
+ label: string;
105
+ level: number;
106
+ parent: null | MenuItemType;
107
+ parent_pk: null | string;
108
+ children: null | MenuItemType[];
109
+ path: string;
110
+ pk: string;
111
+ sort_order: number;
112
+ url: string;
113
+ };
114
+
115
+ export type ForgotPasswordFormType = {
116
+ email: string;
117
+ };
118
+
119
+ export interface UpsellDetail {
120
+ message: string;
121
+ params: {
122
+ partial_percentage: number;
123
+ required: number;
124
+ partial: number;
125
+ remaining: number;
126
+ };
127
+ }
@@ -0,0 +1,108 @@
1
+ import { Product } from './product';
2
+ import { Address } from './address';
3
+
4
+ export interface OrderStatus {
5
+ value: string;
6
+ label: string;
7
+ }
8
+
9
+ export interface Currency {
10
+ value: string;
11
+ label: string;
12
+ }
13
+
14
+ export interface PaymentOption {
15
+ name: string;
16
+ payment_type: string;
17
+ payment_type_label: string;
18
+ pk: number;
19
+ slug: string;
20
+ }
21
+
22
+ export interface OrderItem {
23
+ id: number;
24
+ status: OrderStatus;
25
+ price_currency: Currency;
26
+ product: Product;
27
+ is_cancelled: boolean;
28
+ is_cancellable: boolean;
29
+ is_refundable: boolean;
30
+ is_tradable: boolean;
31
+ available_easy_return_shipping_companies: {
32
+ pk: number;
33
+ shipping_company: {
34
+ value: string;
35
+ label: string;
36
+ };
37
+ }[];
38
+ active_cancellation_request: [
39
+ {
40
+ easy_return: {
41
+ code: string;
42
+ };
43
+ }
44
+ ];
45
+ created_date: string;
46
+ modified_date: string;
47
+ price: string;
48
+ tax_rate: string;
49
+ retail_price: string;
50
+ order: number;
51
+ length: number;
52
+ quantity: string;
53
+ unit_price: string;
54
+ total_amount: string;
55
+ }
56
+
57
+ export interface Order {
58
+ id: number;
59
+ status: OrderStatus;
60
+ currency: Currency;
61
+ orderitem_set: OrderItem[];
62
+ discountitem_set: [
63
+ {
64
+ amount: string;
65
+ cancel_amount: string;
66
+ code: null;
67
+ created_date: string;
68
+ modified_date: string;
69
+ name: string;
70
+ offer_type: string;
71
+ order: number;
72
+ pk: number;
73
+ promotion: number;
74
+ session_offer_type: null;
75
+ }
76
+ ];
77
+ is_cancelled: boolean;
78
+ is_cancellable: boolean;
79
+ is_refundable: boolean;
80
+ shipping_address: Address;
81
+ billing_address: Address;
82
+ client_type: string;
83
+ payment_option: PaymentOption;
84
+ amount_without_discount: string;
85
+ is_payable: boolean;
86
+ created_date: string;
87
+ modified_date: string;
88
+ number: string;
89
+ amount: string;
90
+ discount_amount: string;
91
+ shipping_amount: string;
92
+ refund_amount: string;
93
+ discount_refund_amount: string;
94
+ shipping_refund_amount: string;
95
+ remote_addr: string;
96
+ has_gift_box: boolean;
97
+ language_code: string;
98
+ user_email: string;
99
+ shipping_option_slug: string;
100
+ payment_option_slug: string;
101
+ installment_count: 1;
102
+ installment_interest_amount: string;
103
+ user: number;
104
+ basket: number;
105
+ shipping_option: number;
106
+ tracking_number: string;
107
+ tracking_url: string;
108
+ }
@@ -0,0 +1,110 @@
1
+ import { Category } from './category';
2
+
3
+ type Values<T> = T[keyof T];
4
+
5
+ export interface Product {
6
+ absolute_url: string;
7
+ attribute_set: number;
8
+ attributes: {
9
+ [key: string]: any;
10
+ };
11
+ attributes_kwargs: any;
12
+ base_code: string;
13
+ basket_offers: {
14
+ kwargs: { show_benefit_products: boolean };
15
+ label: string;
16
+ listing_kwargs: {
17
+ [key: string]: any;
18
+ };
19
+ pk: number;
20
+ };
21
+ currency_type: string;
22
+ data_source: null;
23
+ extra_attributes: {
24
+ [key: string]: any;
25
+ };
26
+ form_schema: null;
27
+ image?: string;
28
+ in_stock: boolean;
29
+ is_ready_to_basket: boolean;
30
+ name: string;
31
+ pk: number;
32
+ price: string;
33
+ price_type: string;
34
+ product_type: string;
35
+ productimage_set: Array<{
36
+ created_date: Date;
37
+ image: string;
38
+ order: number;
39
+ pk: number;
40
+ specialimage_set: Array<{
41
+ [key: string]: any;
42
+ }>;
43
+ status: string;
44
+ }>;
45
+ productvideo_set: Array<{
46
+ [key: string]: any;
47
+ }>;
48
+ retail_price: string;
49
+ sku: string;
50
+ stock: number;
51
+ unit_type: string;
52
+ created_date: string;
53
+ modified_date: string;
54
+ description?: string;
55
+ quantity: string;
56
+ }
57
+
58
+ export interface FavoriteItem {
59
+ pk: number;
60
+ product: Product;
61
+ }
62
+
63
+ export type VariantOption = {
64
+ in_stock: boolean;
65
+ is_selectable: boolean;
66
+ is_selectable_without_stock: boolean;
67
+ is_selected: boolean;
68
+ label: string;
69
+ order: string;
70
+ product: Product;
71
+ value: string;
72
+ };
73
+
74
+ export type StockResultType = [
75
+ {
76
+ address: string;
77
+ latitude: string;
78
+ longitude: string;
79
+ name: string;
80
+ stock: string;
81
+ store_hours: Array<any>;
82
+ }
83
+ ];
84
+
85
+ export type FindInStoreFormType = {
86
+ store: string;
87
+ variant: string;
88
+ productPk: string;
89
+ };
90
+
91
+ export interface ProductCategoryResult {
92
+ count: number;
93
+ next: string;
94
+ previous: null | string;
95
+ results: Category[];
96
+ }
97
+
98
+ export type VariantType = {
99
+ attribute_key: Values<any>;
100
+ attribute_name: string;
101
+ options: Array<VariantOption>;
102
+ };
103
+
104
+ export type ProductResult = {
105
+ in_stock: boolean;
106
+ product: Product;
107
+ group_products?: Array<Product>;
108
+ selected_variant?: Product | null;
109
+ variants?: Array<VariantType>;
110
+ };
@@ -0,0 +1,28 @@
1
+ import { ImageType } from './misc';
2
+ import { Product } from './product';
3
+
4
+ export type WidgetType = {
5
+ kwargs?: {
6
+ data_type?: 'nested';
7
+ value?: {
8
+ image?: ImageType;
9
+ mobile_image?: ImageType;
10
+ };
11
+ };
12
+ value?: {
13
+ alt?: string;
14
+ image?: string;
15
+ mobile_image?: string;
16
+ url?: string;
17
+ item_slug?: string;
18
+ title?: string;
19
+ };
20
+ };
21
+
22
+ export type WidgetResultType<T> = {
23
+ attributes?: T;
24
+ products?: Array<Product>;
25
+ name?: string;
26
+ slug?: string;
27
+ template?: string;
28
+ };
package/types/gtm.ts ADDED
@@ -0,0 +1,16 @@
1
+ export interface GTMEvent {
2
+ Action: string;
3
+ Category?: string;
4
+ Label: string;
5
+ Value?: number;
6
+ ecommerce: Record<string, any>;
7
+ event: `ee${string}`;
8
+ }
9
+
10
+ export interface GTMUserType {
11
+ pk: number;
12
+ hashedEmail: string;
13
+ dateJoined: string;
14
+ gender: string;
15
+ emailAllowed: boolean;
16
+ }
package/types/index.ts ADDED
@@ -0,0 +1,207 @@
1
+ import { LocaleUrlStrategy } from '../localization';
2
+ import { PzNextRequest } from '../middlewares';
3
+
4
+ declare global {
5
+ export interface Window {
6
+ dataLayer: Record<string, any>[];
7
+ }
8
+ }
9
+
10
+ export * from './commerce';
11
+ export * from './gtm';
12
+
13
+ export interface Locale {
14
+ label: string;
15
+ /**
16
+ * Lowercased locale value in `ISO 639-1` format or including country code in `ISO 3166-1 alpha-2` format.
17
+ *
18
+ * -- If you use uppercase characters, it will be considered as lowercase.
19
+ *
20
+ * ***
21
+ * @example
22
+ * value: 'en'
23
+ * value: 'en-us'
24
+ * value: 'tr'
25
+ *
26
+ * @see https://en.wikipedia.org/wiki/ISO_639-1
27
+ * @see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
28
+ */
29
+ value: string;
30
+ localePath?: string;
31
+ /**
32
+ * Corresponding Commerce API value for fetching data. It will be used in `Accept-Language` header.
33
+ */
34
+ apiValue: string;
35
+ rtl?: boolean;
36
+ }
37
+
38
+ export interface Currency {
39
+ /**
40
+ * It will be used for displaying currency in currency switcher.
41
+ * Can be symbol, code, etc.
42
+ *
43
+ * @example
44
+ * label: '$'
45
+ * label: '€'
46
+ * label: 'USD'
47
+ * label: 'US Dollar'
48
+ * label: '$ - USD'
49
+ */
50
+ label: string;
51
+ /**
52
+ * Lowercased currency code in `ISO 4217` format.
53
+ *
54
+ * It should match with one of the values returned from Commerce API.
55
+ *
56
+ * @example
57
+ * code: 'usd'
58
+ * code: 'eur'
59
+ * code: 'try'
60
+ *
61
+ * @see https://en.wikipedia.org/wiki/ISO_4217
62
+ */
63
+ code: string;
64
+ }
65
+
66
+ export interface Settings {
67
+ commerceUrl: string;
68
+ redis: {
69
+ defaultExpirationTime: number;
70
+ };
71
+ commonProductAttributes: Array<{
72
+ translationKey: string;
73
+ key: string;
74
+ }>;
75
+ localization: {
76
+ locales: Locale[];
77
+ currencies: Array<Currency>;
78
+ /**
79
+ * Default locale value in `ISO 639-1` format or including country code in `ISO 3166-1 alpha-2` format.
80
+ *
81
+ * It will be used for redirections and fallbacks.
82
+ *
83
+ * It should be one of the values in `locales` array.
84
+ */
85
+ defaultLocaleValue: string;
86
+ /**
87
+ * Determines url behavior according to locale.
88
+ *
89
+ * Available options:
90
+ * - LocaleUrlStrategy.HideDefaultLocale
91
+ * - LocaleUrlStrategy.HideAllLocales
92
+ * - LocaleUrlStrategy.ShowAllLocales
93
+ *
94
+ * @default LocaleUrlStrategy.HideDefaultLocale
95
+ *
96
+ * @example
97
+ * // Example configuration
98
+ * locales: [{ value: 'en'}, { value: 'tr' }]
99
+ * defaultLocaleValue: 'en'
100
+ * // -------------------------------
101
+ *
102
+ * LocaleUrlStrategy.HideDefaultLocale:
103
+ * en -> "/women"
104
+ * tr -> "/tr/women"
105
+ *
106
+ * LocaleUrlStrategy.ShowAllLocales:
107
+ * en -> "/en/women"
108
+ * tr -> "/tr/women"
109
+ *
110
+ * LocaleUrlStrategy.HideAllLocales:
111
+ * en -> "/women"
112
+ * tr -> "/women"
113
+ */
114
+ localeUrlStrategy?: LocaleUrlStrategy;
115
+ redirectToDefaultLocale?: boolean;
116
+ defaultCurrencyCode: string;
117
+ /**
118
+ * The default behavior of `getActiveCurrencyCode` function is to get active currency code from cookie named `pz-currency`.
119
+ *
120
+ * You can use this function to override existing and get currency code from cookie, header, url, etc.
121
+ *
122
+ * If return value does not match with any currency code in `currencies` array, default currency code will be used.
123
+ *
124
+ * @param req - Incoming request. You can use this to get cookie, header, url, etc.
125
+ * @param locale - Active locale value. E.g. 'en', 'tr', 'en-us', 'tr-tr'
126
+ * @param defaultCurrencyCode - Default currency code in `ISO 4217` format. E.g. 'usd', 'eur', 'try'
127
+ * @returns Currency code in `ISO 4217` format. E.g. 'usd', 'eur', 'try'
128
+ *
129
+ * @example
130
+ * getActiveCurrencyCode: ({ req, locale, defaultCurrencyCode }) => {
131
+ * const [, countryCode] = locale.split('-');
132
+ *
133
+ * if (countryCode === 'ae') {
134
+ * return 'aed';
135
+ * } else if (countryCode === 'qa') {
136
+ * return 'qar';
137
+ * }
138
+ *
139
+ * return defaultCurrencyCode;
140
+ * }
141
+ */
142
+ getActiveCurrencyCode?: ({
143
+ req,
144
+ locale,
145
+ defaultCurrencyCode
146
+ }: {
147
+ req: PzNextRequest;
148
+ locale: string;
149
+ defaultCurrencyCode: string;
150
+ }) => string;
151
+ };
152
+ rewrites?: Array<{
153
+ source: string;
154
+ destination: string;
155
+ }>;
156
+ }
157
+
158
+ export interface CacheOptions {
159
+ cache?: boolean;
160
+ expire?: number;
161
+ useProxy?: boolean;
162
+ }
163
+
164
+ export interface ClientRequestOptions {
165
+ useTrailingSlash?: boolean;
166
+ useFormData?: boolean;
167
+ accept?: string;
168
+ contentType?: string;
169
+ responseType?: 'json' | 'text';
170
+ }
171
+
172
+ export type CDNOptions = {
173
+ width?: number;
174
+ height?: number;
175
+ quality?: number;
176
+ crop?: 'center' | 'top' | 'bottom' | 'left' | 'right';
177
+ upscale?: boolean;
178
+ };
179
+
180
+ export type ImageOptions = CDNOptions & {
181
+ sources?: Array<{ media: string; options: CDNOptions }>;
182
+ };
183
+
184
+ export type Translations = { [key: string]: object };
185
+
186
+ export interface PageProps<T = any> {
187
+ params: T;
188
+ searchParams: URLSearchParams;
189
+ }
190
+
191
+ export interface LayoutProps<T = any> extends PageProps<T> {
192
+ children: React.ReactNode;
193
+ }
194
+
195
+ export interface RootLayoutProps<
196
+ T = { commerce: string; locale: string; currency: string }
197
+ > extends LayoutProps<T> {
198
+ translations: Translations;
199
+ locale: Locale & {
200
+ isoCode: string;
201
+ };
202
+ }
203
+
204
+ export interface AuthError {
205
+ type: string;
206
+ data?: any;
207
+ }
@@ -0,0 +1,24 @@
1
+ import NextAuth from 'next-auth';
2
+
3
+ declare module 'next-auth' {
4
+ interface User {
5
+ id?: number;
6
+ pk: number;
7
+ firstName: string;
8
+ lastName: string;
9
+ email: string;
10
+ phone: string;
11
+ emailAllowed: boolean;
12
+ smsAllowed: boolean;
13
+ dateJoined: string;
14
+ lastLogin: string;
15
+ dateOfBirth: string;
16
+ token: string;
17
+ hashedEmail: string;
18
+ gender: string;
19
+ }
20
+
21
+ interface Session {
22
+ user: User;
23
+ }
24
+ }
@@ -0,0 +1,62 @@
1
+ import Settings from 'settings';
2
+ import { ServerVariables } from './server-variables';
3
+ import logger from '../utils/log';
4
+
5
+ export enum FetchResponseType {
6
+ JSON = 'json',
7
+ TEXT = 'text'
8
+ }
9
+
10
+ const appFetch = async <T>(
11
+ url: RequestInfo,
12
+ init: RequestInit = {},
13
+ responseType = FetchResponseType.JSON
14
+ ) => {
15
+ let response: T;
16
+ let status: number;
17
+
18
+ try {
19
+ const commerceUrl = Settings.commerceUrl;
20
+ const currentLocale = Settings.localization.locales.find(
21
+ (locale) => locale.value === ServerVariables.locale
22
+ );
23
+
24
+ if (commerceUrl === 'default') {
25
+ logger.error('Commerce URL is not set. Current value is "default"');
26
+ return undefined;
27
+ }
28
+
29
+ const requestURL = `${decodeURIComponent(commerceUrl)}${url}`;
30
+
31
+ init.headers = {
32
+ ...(init.headers ?? {}),
33
+ 'Accept-Language': currentLocale.apiValue,
34
+ 'x-currency': ServerVariables.currency
35
+ };
36
+
37
+ init.next = {
38
+ revalidate: 60
39
+ };
40
+
41
+ logger.debug(`FETCH START ${url}`, { requestURL, init });
42
+ const req = await fetch(requestURL, init);
43
+ status = req.status;
44
+ logger.debug(`FETCH END ${url}`, { status: req.status });
45
+
46
+ const rawData = await req.text();
47
+
48
+ if (responseType === FetchResponseType.JSON) {
49
+ response = JSON.parse(rawData);
50
+ } else {
51
+ response = rawData as unknown as T;
52
+ }
53
+
54
+ logger.trace(`FETCH RESPONSE`, { url, response });
55
+ } catch (error) {
56
+ logger.error(`FETCH FAILED`, { url, status, error });
57
+ }
58
+
59
+ return response;
60
+ };
61
+
62
+ export default appFetch;
@@ -0,0 +1,22 @@
1
+ import logger from './log';
2
+
3
+ export const generateCommerceSearchParams = (searchParams?: URLSearchParams) => {
4
+ if (!searchParams) {
5
+ return null;
6
+ }
7
+
8
+ const urlSerchParams = new URLSearchParams(searchParams);
9
+
10
+ Object.entries(searchParams).forEach(([key, value]) => {
11
+ if (typeof value === 'object') {
12
+ urlSerchParams.delete(key);
13
+ value.forEach((val) => {
14
+ urlSerchParams.append(key, val);
15
+ });
16
+ }
17
+ });
18
+
19
+ logger.debug(`generateCommerceSearchParams: ${urlSerchParams.toString()}`);
20
+
21
+ return `?${urlSerchParams.toString()}`;
22
+ };