@graphcommerce/next-config 7.0.0-canary.21 → 7.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.
- package/CHANGELOG.md +229 -1
- package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +1 -22
- package/__tests__/interceptors/writeInterceptors.ts +5 -2
- package/__tests__/utils/packageRoots.ts +35 -0
- package/dist/config/commands/exportConfig.js +1 -0
- package/dist/config/commands/generateConfig.js +1 -0
- package/dist/config/demoConfig.js +4 -0
- package/dist/config/loadConfig.js +1 -0
- package/dist/config/utils/rewriteLegacyEnv.js +1 -1
- package/dist/generated/config.js +14 -1
- package/dist/index.js +2 -0
- package/dist/interceptors/InterceptorPlugin.js +2 -0
- package/dist/interceptors/findPlugins.js +1 -0
- package/dist/runtimeCachingOptimizations.js +28 -0
- package/dist/utils/packageRoots.js +31 -0
- package/dist/withGraphCommerce.js +6 -11
- package/package.json +7 -5
- package/src/config/commands/exportConfig.ts +1 -0
- package/src/config/commands/generateConfig.ts +1 -0
- package/src/config/demoConfig.ts +5 -0
- package/src/config/loadConfig.ts +2 -1
- package/src/config/utils/mergeEnvIntoConfig.ts +8 -5
- package/src/config/utils/rewriteLegacyEnv.ts +1 -1
- package/src/generated/config.ts +119 -45
- package/src/index.ts +8 -2
- package/src/interceptors/InterceptorPlugin.ts +2 -0
- package/src/interceptors/findPlugins.ts +1 -0
- package/src/interceptors/generateInterceptors.ts +1 -1
- package/src/runtimeCachingOptimizations.ts +27 -0
- package/src/utils/packageRoots.ts +35 -0
- package/src/withGraphCommerce.ts +6 -13
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.packageRoots = void 0;
|
|
4
|
+
const packageRoots = (packagePaths) => {
|
|
5
|
+
const pathMap = {};
|
|
6
|
+
// Iterate over each path in the array
|
|
7
|
+
packagePaths.forEach((singlePath) => {
|
|
8
|
+
const parts = singlePath.split('/');
|
|
9
|
+
// Iterate through each part of the path
|
|
10
|
+
for (let i = 1; i < parts.length; i++) {
|
|
11
|
+
const subPath = parts.slice(0, i + 1).join('/');
|
|
12
|
+
// Increment the count of this subPath
|
|
13
|
+
if (pathMap[subPath]) {
|
|
14
|
+
pathMap[subPath].count += 1;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
pathMap[subPath] = { path: subPath, count: 1 };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
// Filter the paths that appear more than once
|
|
22
|
+
const roots = [];
|
|
23
|
+
Object.values(pathMap).forEach(({ path, count }) => {
|
|
24
|
+
if (count > 1) {
|
|
25
|
+
roots.push(path);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// Filter out the sub-paths which are part of another longer sub-path
|
|
29
|
+
return roots.filter((root, index, self) => self.findIndex((r) => r !== root && r.startsWith(`${root}/`)) === -1);
|
|
30
|
+
};
|
|
31
|
+
exports.packageRoots = packageRoots;
|
|
@@ -17,22 +17,14 @@ function domains(config) {
|
|
|
17
17
|
if (!loc.domain)
|
|
18
18
|
return acc;
|
|
19
19
|
acc[loc.domain] = {
|
|
20
|
-
defaultLocale: loc.
|
|
20
|
+
defaultLocale: loc.locale,
|
|
21
21
|
locales: [...(acc[loc.domain]?.locales ?? []), loc.locale],
|
|
22
22
|
domain: loc.domain,
|
|
23
|
-
http:
|
|
23
|
+
http: process.env.NODE_ENV === 'development' || undefined,
|
|
24
24
|
};
|
|
25
25
|
return acc;
|
|
26
26
|
}, {}));
|
|
27
27
|
}
|
|
28
|
-
function remotePatterns(url) {
|
|
29
|
-
const urlObj = new URL(url);
|
|
30
|
-
return {
|
|
31
|
-
hostname: urlObj.hostname,
|
|
32
|
-
protocol: urlObj.protocol,
|
|
33
|
-
port: urlObj.port,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
28
|
/**
|
|
37
29
|
* GraphCommerce configuration: .
|
|
38
30
|
*
|
|
@@ -53,10 +45,12 @@ function withGraphCommerce(nextConfig, cwd) {
|
|
|
53
45
|
return {
|
|
54
46
|
...nextConfig,
|
|
55
47
|
experimental: {
|
|
56
|
-
enableUndici: true,
|
|
57
48
|
...nextConfig.experimental,
|
|
49
|
+
scrollRestoration: true,
|
|
50
|
+
swcPlugins: [...(nextConfig.experimental?.swcPlugins ?? []), ['@lingui/swc-plugin', {}]],
|
|
58
51
|
},
|
|
59
52
|
i18n: {
|
|
53
|
+
...nextConfig.i18n,
|
|
60
54
|
defaultLocale: storefront.find((locale) => locale.defaultLocale)?.locale ?? storefront[0].locale,
|
|
61
55
|
locales: storefront.map((locale) => locale.locale),
|
|
62
56
|
domains: [...domains(graphcommerceConfig), ...(nextConfig.i18n?.domains ?? [])],
|
|
@@ -79,6 +73,7 @@ function withGraphCommerce(nextConfig, cwd) {
|
|
|
79
73
|
{ source: '/product/downloadable/:url*', destination, permanent: true },
|
|
80
74
|
{ source: '/product/grouped/:url*', destination, permanent: true },
|
|
81
75
|
{ source: '/product/virtual/:url*', destination, permanent: true },
|
|
76
|
+
{ source: '/customer/account', destination: '/account', permanent: true },
|
|
82
77
|
]);
|
|
83
78
|
if (destination !== '/product/:url*')
|
|
84
79
|
redirects.push({ source: '/product/:url*', destination, permanent: true });
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/next-config",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "7.0.0
|
|
5
|
+
"version": "7.0.0",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "src/index.ts",
|
|
@@ -13,20 +13,22 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@graphql-mesh/cli": "latest",
|
|
16
|
-
"@lingui/loader": "
|
|
17
|
-
"@swc
|
|
16
|
+
"@lingui/loader": "4.4.0",
|
|
17
|
+
"@lingui/swc-plugin": "4.0.3",
|
|
18
|
+
"@swc/core": "1.3.77",
|
|
18
19
|
"circular-dependency-plugin": "^5.2.2",
|
|
19
20
|
"inspectpack": "^4.7.1",
|
|
20
21
|
"js-yaml-loader": "^1.2.2",
|
|
21
22
|
"lodash": "^4.17.21",
|
|
22
23
|
"znv": "^0.3.2",
|
|
23
|
-
"zod": "^3.21.4"
|
|
24
|
+
"zod": "^3.21.4",
|
|
25
|
+
"workbox-build": "^7.0.0"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
26
28
|
"@types/circular-dependency-plugin": "^5.0.5",
|
|
27
29
|
"@types/cli-table": "^0.3.1",
|
|
28
30
|
"@types/lodash": "^4.14.191",
|
|
29
|
-
"typescript": "
|
|
31
|
+
"typescript": "5.1.3"
|
|
30
32
|
},
|
|
31
33
|
"peerDependencies": {
|
|
32
34
|
"next": "^13.2.0",
|
|
@@ -4,5 +4,6 @@ import { exportConfigToEnv } from '../utils/exportConfigToEnv'
|
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
5
5
|
export async function exportConfig() {
|
|
6
6
|
const conf = loadConfig(process.cwd())
|
|
7
|
+
// eslint-disable-next-line no-console
|
|
7
8
|
console.log(exportConfigToEnv(conf))
|
|
8
9
|
}
|
package/src/config/demoConfig.ts
CHANGED
|
@@ -21,8 +21,13 @@ export const demoConfig: PartialDeep<GraphCommerceConfig, { recurseIntoArrays: t
|
|
|
21
21
|
{ locale: 'en-ca', magentoStoreCode: 'en_CA' },
|
|
22
22
|
],
|
|
23
23
|
productFiltersPro: true,
|
|
24
|
+
productFiltersLayout: 'DEFAULT',
|
|
25
|
+
compareVariant: 'ICON',
|
|
24
26
|
robotsAllow: false,
|
|
25
27
|
demoMode: true,
|
|
26
28
|
limitSsg: true,
|
|
27
29
|
compare: true,
|
|
30
|
+
|
|
31
|
+
configurableVariantForSimple: true,
|
|
32
|
+
configurableVariantValues: { url: true, content: true, gallery: true },
|
|
28
33
|
}
|
package/src/config/loadConfig.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
3
|
import { cosmiconfigSync } from 'cosmiconfig'
|
|
3
4
|
import type { GraphCommerceConfig } from '../generated/config'
|
|
4
5
|
import { GraphCommerceConfigSchema } from '../generated/config'
|
|
5
6
|
import { demoConfig } from './demoConfig'
|
|
6
|
-
import {
|
|
7
|
+
import { formatAppliedEnv } from './utils/mergeEnvIntoConfig'
|
|
7
8
|
import { rewriteLegacyEnv } from './utils/rewriteLegacyEnv'
|
|
8
9
|
|
|
9
10
|
export * from './utils/configToImportMeta'
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
ZodEffects,
|
|
16
16
|
ZodRawShape,
|
|
17
17
|
ZodEnum,
|
|
18
|
+
ZodTypeAny,
|
|
19
|
+
ZodAny,
|
|
18
20
|
} from 'zod'
|
|
19
21
|
import diff from './diff'
|
|
20
22
|
|
|
@@ -39,14 +41,15 @@ function isJSON(str: string | undefined): boolean {
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
export type ZodNode =
|
|
42
|
-
| ZodNullable<
|
|
43
|
-
| ZodOptional<
|
|
44
|
-
| ZodEffects<
|
|
45
|
-
| ZodObject<
|
|
46
|
-
| ZodArray<
|
|
44
|
+
| ZodNullable<ZodTypeAny>
|
|
45
|
+
| ZodOptional<ZodTypeAny>
|
|
46
|
+
| ZodEffects<ZodTypeAny>
|
|
47
|
+
| ZodObject<ZodRawShape>
|
|
48
|
+
| ZodArray<ZodTypeAny>
|
|
47
49
|
| ZodString
|
|
48
50
|
| ZodNumber
|
|
49
51
|
| ZodBoolean
|
|
52
|
+
| ZodAny
|
|
50
53
|
|
|
51
54
|
export function configToEnvSchema(schema: ZodNode) {
|
|
52
55
|
const envSchema: ZodRawShape = {}
|
|
@@ -91,7 +91,7 @@ export function rewriteLegacyEnv(
|
|
|
91
91
|
|
|
92
92
|
if (!config.storefront) config.storefront = []
|
|
93
93
|
config.storefront.forEach((storefront, index) => {
|
|
94
|
-
if (!inclTax.includes(storefront.locale)) return
|
|
94
|
+
if (!inclTax.includes(storefront.locale)) return
|
|
95
95
|
clonedEnv[`GC_STOREFRONT_${index}_CART_DISPLAY_PRICES_INCL_TAX`] = '1'
|
|
96
96
|
})
|
|
97
97
|
|
package/src/generated/config.ts
CHANGED
|
@@ -5,13 +5,15 @@ export type InputMaybe<T> = Maybe<T>;
|
|
|
5
5
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
|
6
6
|
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
|
|
7
7
|
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
|
|
8
|
+
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
|
|
9
|
+
export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
|
|
8
10
|
/** All built-in and custom scalars, mapped to their actual values */
|
|
9
11
|
export type Scalars = {
|
|
10
|
-
ID: string;
|
|
11
|
-
String: string;
|
|
12
|
-
Boolean: boolean;
|
|
13
|
-
Int: number;
|
|
14
|
-
Float: number;
|
|
12
|
+
ID: { input: string; output: string; }
|
|
13
|
+
String: { input: string; output: string; }
|
|
14
|
+
Boolean: { input: boolean; output: boolean; }
|
|
15
|
+
Int: { input: number; output: number; }
|
|
16
|
+
Float: { input: number; output: number; }
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
export type CompareVariant =
|
|
@@ -104,20 +106,39 @@ export type GraphCommerceConfig = {
|
|
|
104
106
|
* - https://example.com/en
|
|
105
107
|
* - https://example.com/en-US
|
|
106
108
|
*/
|
|
107
|
-
canonicalBaseUrl: Scalars['String'];
|
|
109
|
+
canonicalBaseUrl: Scalars['String']['input'];
|
|
108
110
|
/**
|
|
109
111
|
* Due to a limitation of the GraphQL API it is not possible to determine if a cart should be displayed including or excluding tax.
|
|
110
112
|
*
|
|
111
113
|
* When Magento's StoreConfig adds this value, this can be replaced.
|
|
112
114
|
*/
|
|
113
|
-
cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']>;
|
|
115
|
+
cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']['input']>;
|
|
114
116
|
/** Use compare functionality */
|
|
115
|
-
compare?: InputMaybe<Scalars['Boolean']>;
|
|
117
|
+
compare?: InputMaybe<Scalars['Boolean']['input']>;
|
|
116
118
|
/**
|
|
117
119
|
* By default the compare feature is denoted with a 'compare ICON' (2 arrows facing one another).
|
|
118
120
|
* This may be fine for experienced users, but for more clarity it's also possible to present the compare feature as a CHECKBOX accompanied by the 'Compare' label
|
|
119
121
|
*/
|
|
120
122
|
compareVariant?: InputMaybe<CompareVariant>;
|
|
123
|
+
/**
|
|
124
|
+
* If a simple product is part of a Configurable product page, should the simple product be
|
|
125
|
+
* rendered as a configured option of the configurable product page?
|
|
126
|
+
*
|
|
127
|
+
* How does this work:
|
|
128
|
+
*
|
|
129
|
+
* When the `products(filters: { url_key: { eq: 'simple-product' } }) { ... }` query is ran,
|
|
130
|
+
* Magento also returns the Simple product and the Configurable product the simple belongs to.
|
|
131
|
+
*
|
|
132
|
+
* If that is the case we render the configurable product page instead of the simple product page but
|
|
133
|
+
* the options to select the simple product are pre-selected.
|
|
134
|
+
*/
|
|
135
|
+
configurableVariantForSimple?: InputMaybe<Scalars['Boolean']['input']>;
|
|
136
|
+
/**
|
|
137
|
+
* When a user selects a variant, it will switch the values on the configurable page with the values of the configured variant.
|
|
138
|
+
*
|
|
139
|
+
* Enabling options here will allow switching of those variants.
|
|
140
|
+
*/
|
|
141
|
+
configurableVariantValues?: InputMaybe<MagentoConfigurableVariantValues>;
|
|
121
142
|
/**
|
|
122
143
|
* Due to a limitation in the GraphQL API of Magento 2, we need to know if the
|
|
123
144
|
* customer requires email confirmation.
|
|
@@ -125,7 +146,7 @@ export type GraphCommerceConfig = {
|
|
|
125
146
|
* This value should match Magento 2's configuration value for
|
|
126
147
|
* `customer/create_account/confirm` and should be removed once we can query
|
|
127
148
|
*/
|
|
128
|
-
customerRequireEmailConfirmation?: InputMaybe<Scalars['Boolean']>;
|
|
149
|
+
customerRequireEmailConfirmation?: InputMaybe<Scalars['Boolean']['input']>;
|
|
129
150
|
/** Debug configuration for GraphCommerce */
|
|
130
151
|
debug?: InputMaybe<GraphCommerceDebugConfig>;
|
|
131
152
|
/**
|
|
@@ -135,7 +156,7 @@ export type GraphCommerceConfig = {
|
|
|
135
156
|
* - Adds "dominant_color" attribute swatches to the product list items.
|
|
136
157
|
* - Creates a big list items in the product list.
|
|
137
158
|
*/
|
|
138
|
-
demoMode?: InputMaybe<Scalars['Boolean']>;
|
|
159
|
+
demoMode?: InputMaybe<Scalars['Boolean']['input']>;
|
|
139
160
|
/**
|
|
140
161
|
* See https://support.google.com/analytics/answer/9539598?hl=en
|
|
141
162
|
*
|
|
@@ -143,19 +164,23 @@ export type GraphCommerceConfig = {
|
|
|
143
164
|
*
|
|
144
165
|
* To override the value for a specific locale, configure in i18n config.
|
|
145
166
|
*/
|
|
146
|
-
googleAnalyticsId?: InputMaybe<Scalars['String']>;
|
|
167
|
+
googleAnalyticsId?: InputMaybe<Scalars['String']['input']>;
|
|
147
168
|
/**
|
|
148
|
-
* Google reCAPTCHA key
|
|
169
|
+
* Google reCAPTCHA site key.
|
|
170
|
+
* When using reCAPTCHA, this value is required, even if you are configuring different values for each locale.
|
|
149
171
|
*
|
|
150
|
-
*
|
|
172
|
+
* Get a site key and a secret key from https://developers.google.com/recaptcha/docs/v3
|
|
173
|
+
*
|
|
174
|
+
* The secret key should be added in the Magento admin panel (Stores > Configuration > Security > Google ReCAPTCHA Storefront > reCAPTCHA v3 Invisible)
|
|
175
|
+
* ReCAPTCHA can then be enabled/disabled for the different forms, separately (Stores > Configuration > Security > Google ReCAPTCHA Storefront > Storefront)
|
|
151
176
|
*/
|
|
152
|
-
googleRecaptchaKey?: InputMaybe<Scalars['String']>;
|
|
177
|
+
googleRecaptchaKey?: InputMaybe<Scalars['String']['input']>;
|
|
153
178
|
/**
|
|
154
179
|
* The Google Tagmanager ID to be used on the site.
|
|
155
180
|
*
|
|
156
181
|
* This value is required even if you are configuring different values for each locale.
|
|
157
182
|
*/
|
|
158
|
-
googleTagmanagerId?: InputMaybe<Scalars['String']>;
|
|
183
|
+
googleTagmanagerId?: InputMaybe<Scalars['String']['input']>;
|
|
159
184
|
/**
|
|
160
185
|
* The HyGraph endpoint.
|
|
161
186
|
*
|
|
@@ -163,7 +188,9 @@ export type GraphCommerceConfig = {
|
|
|
163
188
|
*
|
|
164
189
|
* Project settings -> API Access -> High Performance Read-only Content API
|
|
165
190
|
*/
|
|
166
|
-
hygraphEndpoint: Scalars['String'];
|
|
191
|
+
hygraphEndpoint: Scalars['String']['input'];
|
|
192
|
+
/** Hygraph Project ID. **Only used for migrations.** */
|
|
193
|
+
hygraphProjectId?: InputMaybe<Scalars['String']['input']>;
|
|
167
194
|
/**
|
|
168
195
|
* Content API. **Only used for migrations.**
|
|
169
196
|
*
|
|
@@ -171,7 +198,7 @@ export type GraphCommerceConfig = {
|
|
|
171
198
|
*
|
|
172
199
|
* Project settings -> API Access -> Content API
|
|
173
200
|
*/
|
|
174
|
-
hygraphWriteAccessEndpoint?: InputMaybe<Scalars['String']>;
|
|
201
|
+
hygraphWriteAccessEndpoint?: InputMaybe<Scalars['String']['input']>;
|
|
175
202
|
/**
|
|
176
203
|
* Hygraph Management SDK Authorization Token. **Only used for migrations.**
|
|
177
204
|
*
|
|
@@ -190,6 +217,12 @@ export type GraphCommerceConfig = {
|
|
|
190
217
|
* - Delete existing components
|
|
191
218
|
* - Update remote sources
|
|
192
219
|
* - Delete remote sources
|
|
220
|
+
* - Read existing environments
|
|
221
|
+
* - Read public content views
|
|
222
|
+
* - Create public content views
|
|
223
|
+
* - Update public content views
|
|
224
|
+
* - Delete public content views
|
|
225
|
+
* - Can see schema view
|
|
193
226
|
*
|
|
194
227
|
* ```
|
|
195
228
|
* GC_HYGRAPH_WRITE_ACCESS_ENDPOINT="https://...hygraph.com/v2/..."
|
|
@@ -197,7 +230,7 @@ export type GraphCommerceConfig = {
|
|
|
197
230
|
* yarn graphcommerce hygraph-migrate
|
|
198
231
|
* ```
|
|
199
232
|
*/
|
|
200
|
-
hygraphWriteAccessToken?: InputMaybe<Scalars['String']>;
|
|
233
|
+
hygraphWriteAccessToken?: InputMaybe<Scalars['String']['input']>;
|
|
201
234
|
/**
|
|
202
235
|
* On older versions of GraphCommerce products would use a product type specific route.
|
|
203
236
|
*
|
|
@@ -205,57 +238,63 @@ export type GraphCommerceConfig = {
|
|
|
205
238
|
*
|
|
206
239
|
* @deprecated Will be removed in a future version. [migration](../upgrading/graphcommerce-5-to-6.md#product-routing-changes)
|
|
207
240
|
*/
|
|
208
|
-
legacyProductRoute?: InputMaybe<Scalars['Boolean']>;
|
|
241
|
+
legacyProductRoute?: InputMaybe<Scalars['Boolean']['input']>;
|
|
209
242
|
/** Limit the static generation of SSG when building */
|
|
210
|
-
limitSsg?: InputMaybe<Scalars['Boolean']>;
|
|
243
|
+
limitSsg?: InputMaybe<Scalars['Boolean']['input']>;
|
|
211
244
|
/**
|
|
212
245
|
* GraphQL Magento endpoint.
|
|
213
246
|
*
|
|
214
247
|
* Examples:
|
|
215
248
|
* - https://magento2.test/graphql
|
|
216
249
|
*/
|
|
217
|
-
magentoEndpoint: Scalars['String'];
|
|
250
|
+
magentoEndpoint: Scalars['String']['input'];
|
|
218
251
|
/** To enable next.js' preview mode, configure the secret you'd like to use. */
|
|
219
|
-
previewSecret?: InputMaybe<Scalars['String']>;
|
|
252
|
+
previewSecret?: InputMaybe<Scalars['String']['input']>;
|
|
253
|
+
/**
|
|
254
|
+
* Layout how the filters are rendered.
|
|
255
|
+
* DEFAULT: Will be rendered as horzontal chips on desktop and mobile
|
|
256
|
+
* SIDEBAR: Will be rendered as a sidebar on desktop and horizontal chips on mobile
|
|
257
|
+
*/
|
|
258
|
+
productFiltersLayout?: InputMaybe<ProductFiltersLayout>;
|
|
220
259
|
/**
|
|
221
260
|
* Product filters with better UI for mobile and desktop.
|
|
222
261
|
*
|
|
223
262
|
* @experimental This is an experimental feature and may change in the future.
|
|
224
263
|
*/
|
|
225
|
-
productFiltersPro?: InputMaybe<Scalars['Boolean']>;
|
|
264
|
+
productFiltersPro?: InputMaybe<Scalars['Boolean']['input']>;
|
|
226
265
|
/**
|
|
227
266
|
* By default we route products to /p/[url] but you can change this to /product/[url] if you wish.
|
|
228
267
|
*
|
|
229
268
|
* Default: '/p/'
|
|
230
269
|
* Example: '/product/'
|
|
231
270
|
*/
|
|
232
|
-
productRoute?: InputMaybe<Scalars['String']>;
|
|
271
|
+
productRoute?: InputMaybe<Scalars['String']['input']>;
|
|
233
272
|
/**
|
|
234
273
|
* Allow the site to be indexed by search engines.
|
|
235
274
|
* If false, the robots.txt file will be set to disallow all.
|
|
236
275
|
*/
|
|
237
|
-
robotsAllow?: InputMaybe<Scalars['Boolean']>;
|
|
276
|
+
robotsAllow?: InputMaybe<Scalars['Boolean']['input']>;
|
|
238
277
|
/** All storefront configuration for the project */
|
|
239
278
|
storefront: Array<GraphCommerceStorefrontConfig>;
|
|
240
279
|
/** Hide the wishlist functionality for guests. */
|
|
241
|
-
wishlistHideForGuests?: InputMaybe<Scalars['Boolean']>;
|
|
280
|
+
wishlistHideForGuests?: InputMaybe<Scalars['Boolean']['input']>;
|
|
242
281
|
/** Ignores whether a product is already in the wishlist, makes the toggle an add only. */
|
|
243
|
-
wishlistIgnoreProductWishlistStatus?: InputMaybe<Scalars['Boolean']>;
|
|
282
|
+
wishlistIgnoreProductWishlistStatus?: InputMaybe<Scalars['Boolean']['input']>;
|
|
244
283
|
/** Show a message when the product is added to the wishlist. */
|
|
245
|
-
wishlistShowFeedbackMessage?: InputMaybe<Scalars['Boolean']>;
|
|
284
|
+
wishlistShowFeedbackMessage?: InputMaybe<Scalars['Boolean']['input']>;
|
|
246
285
|
};
|
|
247
286
|
|
|
248
287
|
/** Debug configuration for GraphCommerce */
|
|
249
288
|
export type GraphCommerceDebugConfig = {
|
|
250
289
|
/** Reports which plugins are enabled or disabled. */
|
|
251
|
-
pluginStatus?: InputMaybe<Scalars['Boolean']>;
|
|
290
|
+
pluginStatus?: InputMaybe<Scalars['Boolean']['input']>;
|
|
252
291
|
/**
|
|
253
292
|
* Cyclic dependencies can cause memory issues and other strange bugs.
|
|
254
293
|
* This plugin will warn you when it detects a cyclic dependency.
|
|
255
294
|
*
|
|
256
295
|
* When running into memory issues, it can be useful to enable this plugin.
|
|
257
296
|
*/
|
|
258
|
-
webpackCircularDependencyPlugin?: InputMaybe<Scalars['Boolean']>;
|
|
297
|
+
webpackCircularDependencyPlugin?: InputMaybe<Scalars['Boolean']['input']>;
|
|
259
298
|
/**
|
|
260
299
|
* When updating packages it can happen that the same package is included with different versions in the same project.
|
|
261
300
|
*
|
|
@@ -263,7 +302,7 @@ export type GraphCommerceDebugConfig = {
|
|
|
263
302
|
* - The same package is included multiple times in the bundle, increasing the bundle size.
|
|
264
303
|
* - The Typescript types of the package are not compatible with each other, causing Typescript errors.
|
|
265
304
|
*/
|
|
266
|
-
webpackDuplicatesPlugin?: InputMaybe<Scalars['Boolean']>;
|
|
305
|
+
webpackDuplicatesPlugin?: InputMaybe<Scalars['Boolean']['input']>;
|
|
267
306
|
};
|
|
268
307
|
|
|
269
308
|
/** All storefront configuration for the project */
|
|
@@ -276,33 +315,33 @@ export type GraphCommerceStorefrontConfig = {
|
|
|
276
315
|
* - https://example.com/en
|
|
277
316
|
* - https://example.com/en-US
|
|
278
317
|
*/
|
|
279
|
-
canonicalBaseUrl?: InputMaybe<Scalars['String']>;
|
|
318
|
+
canonicalBaseUrl?: InputMaybe<Scalars['String']['input']>;
|
|
280
319
|
/** Due to a limitation of the GraphQL API it is not possible to determine if a cart should be displayed including or excluding tax. */
|
|
281
|
-
cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']>;
|
|
320
|
+
cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']['input']>;
|
|
282
321
|
/**
|
|
283
322
|
* There can only be one entry with defaultLocale set to true.
|
|
284
323
|
* - If there are more, the first one is used.
|
|
285
324
|
* - If there is none, the first entry is used.
|
|
286
325
|
*/
|
|
287
|
-
defaultLocale?: InputMaybe<Scalars['Boolean']>;
|
|
326
|
+
defaultLocale?: InputMaybe<Scalars['Boolean']['input']>;
|
|
288
327
|
/** Domain configuration, must be a domain https://tools.ietf.org/html/rfc3986 */
|
|
289
|
-
domain?: InputMaybe<Scalars['String']>;
|
|
328
|
+
domain?: InputMaybe<Scalars['String']['input']>;
|
|
290
329
|
/**
|
|
291
330
|
* Configure different Google Analytics IDs for different locales.
|
|
292
331
|
*
|
|
293
332
|
* To disable for a specific locale, set the value to null.
|
|
294
333
|
*/
|
|
295
|
-
googleAnalyticsId?: InputMaybe<Scalars['String']>;
|
|
334
|
+
googleAnalyticsId?: InputMaybe<Scalars['String']['input']>;
|
|
296
335
|
/** Locale specific google reCAPTCHA key. */
|
|
297
|
-
googleRecaptchaKey?: InputMaybe<Scalars['String']>;
|
|
336
|
+
googleRecaptchaKey?: InputMaybe<Scalars['String']['input']>;
|
|
298
337
|
/** The Google Tagmanager ID to be used per locale. */
|
|
299
|
-
googleTagmanagerId?: InputMaybe<Scalars['String']>;
|
|
338
|
+
googleTagmanagerId?: InputMaybe<Scalars['String']['input']>;
|
|
300
339
|
/** Add a gcms-locales header to make sure queries return in a certain language, can be an array to define fallbacks. */
|
|
301
|
-
hygraphLocales?: InputMaybe<Array<Scalars['String']>>;
|
|
340
|
+
hygraphLocales?: InputMaybe<Array<Scalars['String']['input']>>;
|
|
302
341
|
/** Specify a custom locale for to load translations. */
|
|
303
|
-
linguiLocale?: InputMaybe<Scalars['String']>;
|
|
342
|
+
linguiLocale?: InputMaybe<Scalars['String']['input']>;
|
|
304
343
|
/** Must be a locale string https://www.unicode.org/reports/tr35/tr35-59/tr35.html#Identifiers */
|
|
305
|
-
locale: Scalars['String'];
|
|
344
|
+
locale: Scalars['String']['input'];
|
|
306
345
|
/**
|
|
307
346
|
* Magento store code.
|
|
308
347
|
*
|
|
@@ -313,9 +352,30 @@ export type GraphCommerceStorefrontConfig = {
|
|
|
313
352
|
* - en-us
|
|
314
353
|
* - b2b-us
|
|
315
354
|
*/
|
|
316
|
-
magentoStoreCode: Scalars['String'];
|
|
355
|
+
magentoStoreCode: Scalars['String']['input'];
|
|
317
356
|
};
|
|
318
357
|
|
|
358
|
+
/** Options to configure which values will be replaced when a variant is selected on the product page. */
|
|
359
|
+
export type MagentoConfigurableVariantValues = {
|
|
360
|
+
/** Use the name, description, short description and meta data from the configured variant */
|
|
361
|
+
content?: InputMaybe<Scalars['Boolean']['input']>;
|
|
362
|
+
/**
|
|
363
|
+
* This option enables the automatic update of product gallery images on the product page when a variant is selected,
|
|
364
|
+
* provided that the gallery images for the selected variant differ from the currently displayed images.
|
|
365
|
+
*/
|
|
366
|
+
gallery?: InputMaybe<Scalars['Boolean']['input']>;
|
|
367
|
+
/**
|
|
368
|
+
* When a variant is selected the URL of the product will be changed in the address bar.
|
|
369
|
+
*
|
|
370
|
+
* This only happens when the actual variant is can be accessed by the URL.
|
|
371
|
+
*/
|
|
372
|
+
url?: InputMaybe<Scalars['Boolean']['input']>;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
export type ProductFiltersLayout =
|
|
376
|
+
| 'DEFAULT'
|
|
377
|
+
| 'SIDEBAR';
|
|
378
|
+
|
|
319
379
|
|
|
320
380
|
type Properties<T> = Required<{
|
|
321
381
|
[K in keyof T]: z.ZodType<T[K], any, T[K]>;
|
|
@@ -329,12 +389,16 @@ export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny
|
|
|
329
389
|
|
|
330
390
|
export const CompareVariantSchema = z.enum(['CHECKBOX', 'ICON']);
|
|
331
391
|
|
|
392
|
+
export const ProductFiltersLayoutSchema = z.enum(['DEFAULT', 'SIDEBAR']);
|
|
393
|
+
|
|
332
394
|
export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerceConfig>> {
|
|
333
|
-
return z.object
|
|
395
|
+
return z.object({
|
|
334
396
|
canonicalBaseUrl: z.string().min(1),
|
|
335
397
|
cartDisplayPricesInclTax: z.boolean().nullish(),
|
|
336
398
|
compare: z.boolean().nullish(),
|
|
337
399
|
compareVariant: CompareVariantSchema.nullish(),
|
|
400
|
+
configurableVariantForSimple: z.boolean().nullish(),
|
|
401
|
+
configurableVariantValues: MagentoConfigurableVariantValuesSchema().nullish(),
|
|
338
402
|
customerRequireEmailConfirmation: z.boolean().nullish(),
|
|
339
403
|
debug: GraphCommerceDebugConfigSchema().nullish(),
|
|
340
404
|
demoMode: z.boolean().nullish(),
|
|
@@ -342,12 +406,14 @@ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerc
|
|
|
342
406
|
googleRecaptchaKey: z.string().nullish(),
|
|
343
407
|
googleTagmanagerId: z.string().nullish(),
|
|
344
408
|
hygraphEndpoint: z.string().min(1),
|
|
409
|
+
hygraphProjectId: z.string().nullish(),
|
|
345
410
|
hygraphWriteAccessEndpoint: z.string().nullish(),
|
|
346
411
|
hygraphWriteAccessToken: z.string().nullish(),
|
|
347
412
|
legacyProductRoute: z.boolean().nullish(),
|
|
348
413
|
limitSsg: z.boolean().nullish(),
|
|
349
414
|
magentoEndpoint: z.string().min(1),
|
|
350
415
|
previewSecret: z.string().nullish(),
|
|
416
|
+
productFiltersLayout: ProductFiltersLayoutSchema.nullish(),
|
|
351
417
|
productFiltersPro: z.boolean().nullish(),
|
|
352
418
|
productRoute: z.string().nullish(),
|
|
353
419
|
robotsAllow: z.boolean().nullish(),
|
|
@@ -359,7 +425,7 @@ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerc
|
|
|
359
425
|
}
|
|
360
426
|
|
|
361
427
|
export function GraphCommerceDebugConfigSchema(): z.ZodObject<Properties<GraphCommerceDebugConfig>> {
|
|
362
|
-
return z.object
|
|
428
|
+
return z.object({
|
|
363
429
|
pluginStatus: z.boolean().nullish(),
|
|
364
430
|
webpackCircularDependencyPlugin: z.boolean().nullish(),
|
|
365
431
|
webpackDuplicatesPlugin: z.boolean().nullish()
|
|
@@ -367,7 +433,7 @@ export function GraphCommerceDebugConfigSchema(): z.ZodObject<Properties<GraphCo
|
|
|
367
433
|
}
|
|
368
434
|
|
|
369
435
|
export function GraphCommerceStorefrontConfigSchema(): z.ZodObject<Properties<GraphCommerceStorefrontConfig>> {
|
|
370
|
-
return z.object
|
|
436
|
+
return z.object({
|
|
371
437
|
canonicalBaseUrl: z.string().nullish(),
|
|
372
438
|
cartDisplayPricesInclTax: z.boolean().nullish(),
|
|
373
439
|
defaultLocale: z.boolean().nullish(),
|
|
@@ -381,3 +447,11 @@ export function GraphCommerceStorefrontConfigSchema(): z.ZodObject<Properties<Gr
|
|
|
381
447
|
magentoStoreCode: z.string().min(1)
|
|
382
448
|
})
|
|
383
449
|
}
|
|
450
|
+
|
|
451
|
+
export function MagentoConfigurableVariantValuesSchema(): z.ZodObject<Properties<MagentoConfigurableVariantValues>> {
|
|
452
|
+
return z.object({
|
|
453
|
+
content: z.boolean().nullish(),
|
|
454
|
+
gallery: z.boolean().nullish(),
|
|
455
|
+
url: z.boolean().nullish()
|
|
456
|
+
})
|
|
457
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import type React from 'react'
|
|
2
3
|
|
|
3
4
|
export * from './utils/isMonorepo'
|
|
4
5
|
export * from './utils/resolveDependenciesSync'
|
|
6
|
+
export * from './utils/packageRoots'
|
|
5
7
|
export * from './withGraphCommerce'
|
|
6
8
|
export * from './generated/config'
|
|
7
9
|
export * from './config'
|
|
10
|
+
export * from './runtimeCachingOptimizations'
|
|
8
11
|
|
|
9
12
|
export type PluginProps<P extends Record<string, unknown> = Record<string, unknown>> = P & {
|
|
10
13
|
Prev: React.FC<P>
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
export type ReactPlugin<
|
|
14
|
-
|
|
16
|
+
export type ReactPlugin<
|
|
17
|
+
T extends React.FC<any>,
|
|
18
|
+
AdditionalOptionalProps extends Record<string, unknown> = Record<string, unknown>,
|
|
19
|
+
> = (
|
|
20
|
+
props: Parameters<T>[0] & AdditionalOptionalProps & { Prev: React.FC<Parameters<T>[0]> },
|
|
15
21
|
) => ReturnType<T>
|
|
16
22
|
|
|
17
23
|
export type MethodPlugin<T extends (...args: any[]) => any> = (
|
|
@@ -16,6 +16,7 @@ export class InterceptorPlugin {
|
|
|
16
16
|
constructor(private config: GraphCommerceConfig) {
|
|
17
17
|
this.resolveDependency = resolveDependency()
|
|
18
18
|
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
20
|
const [plugins, errors] = findPlugins(this.config)
|
|
20
21
|
this.interceptors = generateInterceptors(plugins, this.resolveDependency, this.config.debug)
|
|
21
22
|
this.interceptorByDepependency = Object.fromEntries(
|
|
@@ -30,6 +31,7 @@ export class InterceptorPlugin {
|
|
|
30
31
|
|
|
31
32
|
// After the compilation has succeeded we watch all possible plugin locations.
|
|
32
33
|
compiler.hooks.afterCompile.tap('InterceptorPlugin', (compilation) => {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
35
|
const [plugins, errors] = findPlugins(this.config)
|
|
34
36
|
|
|
35
37
|
plugins.forEach((p) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import {
|
|
2
|
+
import { GraphCommerceDebugConfig } from '../generated/config'
|
|
3
3
|
import { ResolveDependency, ResolveDependencyReturn } from '../utils/resolveDependency'
|
|
4
4
|
|
|
5
5
|
type PluginBaseConfig = {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RuntimeCaching } from 'workbox-build'
|
|
2
|
+
|
|
3
|
+
export const runtimeCachingOptimizations: RuntimeCaching[] = [
|
|
4
|
+
{
|
|
5
|
+
urlPattern: /\/_next\/image\?url=.+$/i,
|
|
6
|
+
handler: 'StaleWhileRevalidate',
|
|
7
|
+
options: {
|
|
8
|
+
cacheName: 'next-image',
|
|
9
|
+
expiration: {
|
|
10
|
+
maxEntries: 1000, // 1000 images
|
|
11
|
+
maxAgeSeconds: 168 * 60 * 60, // 1 week
|
|
12
|
+
matchOptions: { ignoreVary: true },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
urlPattern: /\/_next\/data\/.+\/.+\.json$/i,
|
|
18
|
+
handler: 'NetworkFirst',
|
|
19
|
+
options: {
|
|
20
|
+
cacheName: 'next-data',
|
|
21
|
+
expiration: {
|
|
22
|
+
maxEntries: 32,
|
|
23
|
+
maxAgeSeconds: 24 * 60 * 60, // 24 hours
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
]
|