@graphcommerce/next-config 6.2.0-canary.7 → 6.2.0-canary.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,165 @@
1
1
  # Change Log
2
2
 
3
+ ## 6.2.0-canary.71
4
+
5
+ ## 6.2.0-canary.70
6
+
7
+ ## 6.2.0-canary.69
8
+
9
+ ## 6.2.0-canary.68
10
+
11
+ ## 6.2.0-canary.67
12
+
13
+ ### Patch Changes
14
+
15
+ - [#2002](https://github.com/graphcommerce-org/graphcommerce/pull/2002) [`1234bb61f`](https://github.com/graphcommerce-org/graphcommerce/commit/1234bb61f8332da8a9e4dd7262b0c70beaed8c91) - Updated next and apollo/client ([@paales](https://github.com/paales))
16
+
17
+ ## 6.2.0-canary.66
18
+
19
+ ## 6.2.0-canary.65
20
+
21
+ ## 6.2.0-canary.64
22
+
23
+ ## 6.2.0-canary.63
24
+
25
+ ## 6.2.0-canary.62
26
+
27
+ ## 6.2.0-canary.61
28
+
29
+ ## 6.2.0-canary.60
30
+
31
+ ## 6.2.0-canary.59
32
+
33
+ ## 6.2.0-canary.58
34
+
35
+ ## 6.2.0-canary.57
36
+
37
+ ### Patch Changes
38
+
39
+ - [#1982](https://github.com/graphcommerce-org/graphcommerce/pull/1982) [`e1fab2f6d`](https://github.com/graphcommerce-org/graphcommerce/commit/e1fab2f6d8f57d0488d8a915596d5c19cb7718e6) - Better detection what the package roots are when a custom node_modules directory is used ([@paales](https://github.com/paales))
40
+
41
+ ## 6.2.0-canary.56
42
+
43
+ ## 6.2.0-canary.55
44
+
45
+ ## 6.2.0-canary.54
46
+
47
+ ## 6.2.0-canary.53
48
+
49
+ ## 6.2.0-canary.52
50
+
51
+ ## 6.2.0-canary.51
52
+
53
+ ## 6.2.0-canary.50
54
+
55
+ ### Minor Changes
56
+
57
+ - [`e55d8c390`](https://github.com/graphcommerce-org/graphcommerce/commit/e55d8c390d90b4bb7bab11c6a99027ac72bd7e3e) - Created a new sidebar layout system, can be configured with productFiltersLayout in the graphcommerce.config.js ([@paales](https://github.com/paales))
58
+
59
+ ## 6.2.0-canary.49
60
+
61
+ ### Patch Changes
62
+
63
+ - [#1959](https://github.com/graphcommerce-org/graphcommerce/pull/1959) [`d0809b132`](https://github.com/graphcommerce-org/graphcommerce/commit/d0809b132a0e4cbdfeb86164f6c16a89ebecd987) - Added support for default values in the Config.graphqls files for the documentation ([@JoshuaS98](https://github.com/JoshuaS98))
64
+
65
+ ## 6.2.0-canary.48
66
+
67
+ ## 6.2.0-canary.47
68
+
69
+ ## 6.2.0-canary.46
70
+
71
+ ## 6.2.0-canary.45
72
+
73
+ ## 6.2.0-canary.44
74
+
75
+ ## 6.2.0-canary.43
76
+
77
+ ## 6.2.0-canary.42
78
+
79
+ ## 6.2.0-canary.41
80
+
81
+ ### Patch Changes
82
+
83
+ - [#1960](https://github.com/graphcommerce-org/graphcommerce/pull/1960) [`86e14569b`](https://github.com/graphcommerce-org/graphcommerce/commit/86e14569b1f68f73be7f93b614e36b382c5debff) - Updated to the latest release of GraphQL codegen and solve compatibility issues with our own generator ([@paales](https://github.com/paales))
84
+
85
+ ## 6.2.0-canary.40
86
+
87
+ ## 6.2.0-canary.39
88
+
89
+ ## 6.2.0-canary.38
90
+
91
+ ## 6.2.0-canary.37
92
+
93
+ ## 6.2.0-canary.36
94
+
95
+ ## 6.2.0-canary.35
96
+
97
+ ## 6.2.0-canary.34
98
+
99
+ ## 6.2.0-canary.33
100
+
101
+ ## 6.2.0-canary.32
102
+
103
+ ## 6.2.0-canary.31
104
+
105
+ ## 6.2.0-canary.30
106
+
107
+ ## 6.2.0-canary.29
108
+
109
+ ## 6.2.0-canary.28
110
+
111
+ ## 6.2.0-canary.27
112
+
113
+ ## 6.2.0-canary.26
114
+
115
+ ## 6.2.0-canary.25
116
+
117
+ ## 6.2.0-canary.24
118
+
119
+ ## 6.2.0-canary.23
120
+
121
+ ## 6.2.0-canary.22
122
+
123
+ ## 6.2.0-canary.21
124
+
125
+ ## 6.2.0-canary.20
126
+
127
+ ### Patch Changes
128
+
129
+ - [#1928](https://github.com/graphcommerce-org/graphcommerce/pull/1928) [`09d6a7abd`](https://github.com/graphcommerce-org/graphcommerce/commit/09d6a7abdf44c04a37f59432e9fc0c0722e6df76) - Added number to config value formatter, so Graphcommerce config accepts number values. ([@mikekeehnen](https://github.com/mikekeehnen))
130
+
131
+ ## 6.2.0-canary.19
132
+
133
+ ## 6.2.0-canary.18
134
+
135
+ ## 6.2.0-canary.17
136
+
137
+ ## 6.2.0-canary.16
138
+
139
+ ## 6.2.0-canary.15
140
+
141
+ ## 6.2.0-canary.14
142
+
143
+ ### Patch Changes
144
+
145
+ - [#1925](https://github.com/graphcommerce-org/graphcommerce/pull/1925) [`2b595bf13`](https://github.com/graphcommerce-org/graphcommerce/commit/2b595bf13f3725a77661586cce021ce8d4791558) - Fixed bug for type error in `demoConfig.ts`. All storefront config values in the demo config are now optional. ([@mikekeehnen](https://github.com/mikekeehnen))
146
+
147
+ ## 6.2.0-canary.13
148
+
149
+ ### Patch Changes
150
+
151
+ - [#1924](https://github.com/graphcommerce-org/graphcommerce/pull/1924) [`04581f619`](https://github.com/graphcommerce-org/graphcommerce/commit/04581f619c609f2f6ca5268ee5effb6a1db3f0eb) - Use the latest branch from graphql-mesh so that all versions are in sync ([@paales](https://github.com/paales))
152
+
153
+ ## 6.2.0-canary.12
154
+
155
+ ## 6.2.0-canary.11
156
+
157
+ ## 6.2.0-canary.10
158
+
159
+ ## 6.2.0-canary.9
160
+
161
+ ## 6.2.0-canary.8
162
+
3
163
  ## 6.2.0-canary.7
4
164
 
5
165
  ## 6.2.0-canary.6
@@ -28,6 +28,8 @@ exports[`traverses a schema and returns a list of env variables that match 1`] =
28
28
  [
29
29
  "GC_CANONICAL_BASE_URL",
30
30
  "GC_CART_DISPLAY_PRICES_INCL_TAX",
31
+ "GC_COMPARE",
32
+ "GC_COMPARE_VARIANT",
31
33
  "GC_CUSTOMER_REQUIRE_EMAIL_CONFIRMATION",
32
34
  "GC_DEBUG",
33
35
  "GC_DEBUG_PLUGIN_STATUS",
@@ -38,6 +40,8 @@ exports[`traverses a schema and returns a list of env variables that match 1`] =
38
40
  "GC_GOOGLE_RECAPTCHA_KEY",
39
41
  "GC_GOOGLE_TAGMANAGER_ID",
40
42
  "GC_HYGRAPH_ENDPOINT",
43
+ "GC_HYGRAPH_WRITE_ACCESS_ENDPOINT",
44
+ "GC_HYGRAPH_WRITE_ACCESS_TOKEN",
41
45
  "GC_LEGACY_PRODUCT_ROUTE",
42
46
  "GC_LIMIT_SSG",
43
47
  "GC_MAGENTO_ENDPOINT",
@@ -165,6 +165,12 @@ it('finds plugins', () => {
165
165
  "func": "graphqlConfig",
166
166
  "plugin": "@graphcommerce/magento-store/plugins/magentoStoreGraphqlConfig",
167
167
  },
168
+ {
169
+ "enabled": true,
170
+ "exported": "@graphcommerce/graphql/config",
171
+ "func": "graphqlConfig",
172
+ "plugin": "@graphcommerce/magento-graphql/plugins/magentoGraphqlConfig",
173
+ },
168
174
  ]
169
175
  `)
170
176
  expect(disabled).toMatchInlineSnapshot(`
@@ -211,6 +217,34 @@ it('finds plugins', () => {
211
217
  "ifConfig": "googleTagmanagerId",
212
218
  "plugin": "@graphcommerce/googletagmanager/plugins/GtagFramerNextPages",
213
219
  },
220
+ {
221
+ "component": "CartFab",
222
+ "enabled": false,
223
+ "exported": "@graphcommerce/magento-cart",
224
+ "ifConfig": "compare",
225
+ "plugin": "@graphcommerce/magento-compare/plugins/AddCompareFabNextToCart",
226
+ },
227
+ {
228
+ "component": "ProductPageAddToCartActionsRow",
229
+ "enabled": false,
230
+ "exported": "@graphcommerce/magento-product",
231
+ "ifConfig": "compare",
232
+ "plugin": "@graphcommerce/magento-compare/plugins/AddCompareToProductPage",
233
+ },
234
+ {
235
+ "component": "GraphQLProvider",
236
+ "enabled": false,
237
+ "exported": "@graphcommerce/graphql",
238
+ "ifConfig": "compare",
239
+ "plugin": "@graphcommerce/magento-compare/plugins/AddCompareTypePolicies",
240
+ },
241
+ {
242
+ "component": "ProductListItem",
243
+ "enabled": false,
244
+ "exported": "@graphcommerce/magento-product",
245
+ "ifConfig": "compare",
246
+ "plugin": "@graphcommerce/magento-compare/plugins/CompareAbleProductListItem",
247
+ },
214
248
  ]
215
249
  `)
216
250
  })
@@ -0,0 +1,35 @@
1
+ import { packageRoots } from '../../src/utils/packageRoots'
2
+
3
+ describe('packageRoots', () => {
4
+ it('should simplify all common paths', () => {
5
+ const paths = [
6
+ '../../packages/cli',
7
+ '../../packages/hygraph-cli',
8
+ '../../packagesDev/next-config',
9
+ '../../packagesDev/next-la',
10
+ '../../../layers/paketo-buildpacks_yarn-install/build-modules/node_modules/@graphcommerce/magento-cart-items',
11
+ '../../../layers/paketo-buildpacks_yarn-install/build-modules/node_modules/@graphcommerce/magento-product',
12
+ // ... (rest of your paths)
13
+ ]
14
+
15
+ const expectedRoots = [
16
+ '../../packages',
17
+ '../../packagesDev',
18
+ '../../../layers/paketo-buildpacks_yarn-install/build-modules/node_modules/@graphcommerce',
19
+ ]
20
+
21
+ const roots = packageRoots(paths)
22
+
23
+ // Expect roots to be an array
24
+ expect(Array.isArray(roots)).toBe(true)
25
+
26
+ // Expect the roots array to be equal to expectedRoots
27
+ expect(expectedRoots).toEqual(roots)
28
+ })
29
+
30
+ it('should return an empty array for no common roots', () => {
31
+ const paths = ['../a/b', '../c/d']
32
+ const roots = packageRoots(paths)
33
+ expect(roots).toEqual([])
34
+ })
35
+ })
@@ -9,12 +9,13 @@ it('resolves dependences', () => {
9
9
  Map {
10
10
  "." => "examples/magento-graphcms",
11
11
  "@graphcommerce/cli" => "packages/cli",
12
+ "@graphcommerce/hygraph-cli" => "packages/hygraph-cli",
12
13
  "@graphcommerce/demo-magento-graphcommerce" => "packages/demo-magento-graphcommerce",
13
14
  "@graphcommerce/googleanalytics" => "packages/googleanalytics",
14
15
  "@graphcommerce/magento-cart-shipping-method" => "packages/magento-cart-shipping-method",
15
16
  "@graphcommerce/googlerecaptcha" => "packages/googlerecaptcha",
16
17
  "@graphcommerce/googletagmanager" => "packages/googletagmanager",
17
- "@graphcommerce/graphcms-ui" => "packages/graphcms-ui",
18
+ "@graphcommerce/graphcms-ui" => "packages/hygraph-ui",
18
19
  "@graphcommerce/lingui-next" => "packages/lingui-next",
19
20
  "@graphcommerce/next-config" => "packagesDev/next-config",
20
21
  "@graphcommerce/magento-cart-billing-address" => "packages/magento-cart-billing-address",
@@ -22,6 +23,7 @@ it('resolves dependences', () => {
22
23
  "@graphcommerce/magento-cart-coupon" => "packages/magento-cart-coupon",
23
24
  "@graphcommerce/magento-cart-email" => "packages/magento-cart-email",
24
25
  "@graphcommerce/magento-cms" => "packages/magento-cms",
26
+ "@graphcommerce/magento-compare" => "packages/magento-compare",
25
27
  "@graphcommerce/magento-newsletter" => "packages/magento-newsletter",
26
28
  "@graphcommerce/magento-payment-included" => "packages/magento-payment-included",
27
29
  "@graphcommerce/magento-cart-payment-method" => "packages/magento-cart-payment-method",
@@ -25,6 +25,7 @@ async function generateConfig() {
25
25
  content: '/* eslint-disable */',
26
26
  schema: 'zod',
27
27
  notAllowEmptyString: true,
28
+ strictScalars: true,
28
29
  enumsAsTypes: true,
29
30
  scalarSchemas: {
30
31
  Domain: 'z.string()',
@@ -19,7 +19,11 @@ exports.demoConfig = {
19
19
  { locale: 'en-ca', magentoStoreCode: 'en_CA' },
20
20
  ],
21
21
  productFiltersPro: true,
22
+ productFiltersLayout: 'DEFAULT',
23
+ compareVariant: 'ICON',
22
24
  robotsAllow: false,
23
25
  demoMode: true,
24
26
  limitSsg: true,
27
+ compare: true,
28
+ configurableVariantForSimple: true,
25
29
  };
@@ -10,6 +10,9 @@ const fmt = (value) => {
10
10
  if (typeof formattedValue === 'object') {
11
11
  formattedValue = JSON.stringify(formattedValue);
12
12
  }
13
+ if (typeof formattedValue === 'number') {
14
+ formattedValue = String(formattedValue);
15
+ }
13
16
  return formattedValue;
14
17
  };
15
18
  function exportConfigToEnv(config) {
@@ -1,15 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GraphCommerceStorefrontConfigSchema = exports.GraphCommerceDebugConfigSchema = exports.GraphCommerceConfigSchema = exports.definedNonNullAnySchema = exports.isDefinedNonNullAny = void 0;
3
+ exports.GraphCommerceStorefrontConfigSchema = exports.GraphCommerceDebugConfigSchema = exports.GraphCommerceConfigSchema = exports.ProductFiltersLayoutSchema = exports.CompareVariantSchema = exports.definedNonNullAnySchema = exports.isDefinedNonNullAny = void 0;
4
4
  /* eslint-disable */
5
5
  const zod_1 = require("zod");
6
6
  const isDefinedNonNullAny = (v) => v !== undefined && v !== null;
7
7
  exports.isDefinedNonNullAny = isDefinedNonNullAny;
8
8
  exports.definedNonNullAnySchema = zod_1.z.any().refine((v) => (0, exports.isDefinedNonNullAny)(v));
9
+ exports.CompareVariantSchema = zod_1.z.enum(['CHECKBOX', 'ICON']);
10
+ exports.ProductFiltersLayoutSchema = zod_1.z.enum(['DEFAULT', 'SIDEBAR']);
9
11
  function GraphCommerceConfigSchema() {
10
12
  return zod_1.z.object({
11
13
  canonicalBaseUrl: zod_1.z.string().min(1),
12
14
  cartDisplayPricesInclTax: zod_1.z.boolean().nullish(),
15
+ compare: zod_1.z.boolean().nullish(),
16
+ compareVariant: exports.CompareVariantSchema.nullish(),
17
+ configurableVariantForSimple: zod_1.z.boolean().nullish(),
13
18
  customerRequireEmailConfirmation: zod_1.z.boolean().nullish(),
14
19
  debug: GraphCommerceDebugConfigSchema().nullish(),
15
20
  demoMode: zod_1.z.boolean().nullish(),
@@ -17,10 +22,13 @@ function GraphCommerceConfigSchema() {
17
22
  googleRecaptchaKey: zod_1.z.string().nullish(),
18
23
  googleTagmanagerId: zod_1.z.string().nullish(),
19
24
  hygraphEndpoint: zod_1.z.string().min(1),
25
+ hygraphWriteAccessEndpoint: zod_1.z.string().nullish(),
26
+ hygraphWriteAccessToken: zod_1.z.string().nullish(),
20
27
  legacyProductRoute: zod_1.z.boolean().nullish(),
21
28
  limitSsg: zod_1.z.boolean().nullish(),
22
29
  magentoEndpoint: zod_1.z.string().min(1),
23
30
  previewSecret: zod_1.z.string().nullish(),
31
+ productFiltersLayout: exports.ProductFiltersLayoutSchema.nullish(),
24
32
  productFiltersPro: zod_1.z.boolean().nullish(),
25
33
  productRoute: zod_1.z.string().nullish(),
26
34
  robotsAllow: zod_1.z.boolean().nullish(),
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./utils/isMonorepo"), exports);
18
18
  __exportStar(require("./utils/resolveDependenciesSync"), exports);
19
+ __exportStar(require("./utils/packageRoots"), exports);
19
20
  __exportStar(require("./withGraphCommerce"), exports);
20
21
  __exportStar(require("./generated/config"), exports);
21
22
  __exportStar(require("./config"), exports);
@@ -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;
@@ -53,8 +53,9 @@ function withGraphCommerce(nextConfig, cwd) {
53
53
  return {
54
54
  ...nextConfig,
55
55
  experimental: {
56
- enableUndici: true,
57
56
  ...nextConfig.experimental,
57
+ scrollRestoration: true,
58
+ swcPlugins: [...(nextConfig.experimental?.swcPlugins ?? []), ['@lingui/swc-plugin', {}]],
58
59
  },
59
60
  i18n: {
60
61
  defaultLocale: storefront.find((locale) => locale.defaultLocale)?.locale ?? storefront[0].locale,
@@ -79,6 +80,7 @@ function withGraphCommerce(nextConfig, cwd) {
79
80
  { source: '/product/downloadable/:url*', destination, permanent: true },
80
81
  { source: '/product/grouped/:url*', destination, permanent: true },
81
82
  { source: '/product/virtual/:url*', destination, permanent: true },
83
+ { source: '/customer/account', destination: '/account', permanent: true },
82
84
  ]);
83
85
  if (destination !== '/product/:url*')
84
86
  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": "6.2.0-canary.7",
5
+ "version": "6.2.0-canary.71",
6
6
  "type": "commonjs",
7
7
  "main": "dist/index.js",
8
8
  "types": "src/index.ts",
@@ -12,9 +12,10 @@
12
12
  "prepack": "tsc"
13
13
  },
14
14
  "dependencies": {
15
- "@graphql-mesh/cli": "0.82.25",
16
- "@lingui/loader": "3.17.2",
17
- "@swc/core": "1.3.39",
15
+ "@graphql-mesh/cli": "latest",
16
+ "@lingui/loader": "4.3.0",
17
+ "@lingui/swc-plugin": "^4.0.3",
18
+ "@swc/core": "1.3.62",
18
19
  "circular-dependency-plugin": "^5.2.2",
19
20
  "inspectpack": "^4.7.1",
20
21
  "js-yaml-loader": "^1.2.2",
@@ -26,7 +27,7 @@
26
27
  "@types/circular-dependency-plugin": "^5.0.5",
27
28
  "@types/cli-table": "^0.3.1",
28
29
  "@types/lodash": "^4.14.191",
29
- "typescript": "4.9.5"
30
+ "typescript": "5.1.3"
30
31
  },
31
32
  "peerDependencies": {
32
33
  "next": "^13.2.0",
@@ -27,6 +27,7 @@ export async function generateConfig() {
27
27
  content: '/* eslint-disable */',
28
28
  schema: 'zod',
29
29
  notAllowEmptyString: true,
30
+ strictScalars: true,
30
31
  enumsAsTypes: true,
31
32
  scalarSchemas: {
32
33
  Domain: 'z.string()',
@@ -1,6 +1,9 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+ import { PartialDeep } from 'type-fest'
1
3
  import { GraphCommerceConfig } from '../generated/config'
2
4
 
3
- export const demoConfig: Partial<GraphCommerceConfig> & Record<string, unknown> = {
5
+ export const demoConfig: PartialDeep<GraphCommerceConfig, { recurseIntoArrays: true }> &
6
+ Record<string, unknown> = {
4
7
  canonicalBaseUrl: 'https://graphcommerce.vercel.app',
5
8
  hygraphEndpoint: 'https://eu-central-1.cdn.hygraph.com/content/ckhx7xadya6xs01yxdujt8i80/master',
6
9
  magentoEndpoint: 'https://backend.reachdigital.dev/graphql',
@@ -18,7 +21,11 @@ export const demoConfig: Partial<GraphCommerceConfig> & Record<string, unknown>
18
21
  { locale: 'en-ca', magentoStoreCode: 'en_CA' },
19
22
  ],
20
23
  productFiltersPro: true,
24
+ productFiltersLayout: 'DEFAULT',
25
+ compareVariant: 'ICON',
21
26
  robotsAllow: false,
22
27
  demoMode: true,
23
28
  limitSsg: true,
29
+ compare: true,
30
+ configurableVariantForSimple: true,
24
31
  }
@@ -1,7 +1,7 @@
1
1
  import { GraphCommerceConfig } from '../../generated/config'
2
2
  import { toEnvStr } from './mergeEnvIntoConfig'
3
3
 
4
- const fmt = (value: string | boolean | object | null) => {
4
+ const fmt = (value: string | number | boolean | object | null) => {
5
5
  let formattedValue = value
6
6
 
7
7
  if (typeof formattedValue === 'boolean') {
@@ -11,6 +11,10 @@ const fmt = (value: string | boolean | object | null) => {
11
11
  formattedValue = JSON.stringify(formattedValue)
12
12
  }
13
13
 
14
+ if (typeof formattedValue === 'number') {
15
+ formattedValue = String(formattedValue)
16
+ }
17
+
14
18
  return formattedValue
15
19
  }
16
20
 
@@ -5,15 +5,21 @@ 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 | number; 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
 
19
+ export type CompareVariant =
20
+ | 'CHECKBOX'
21
+ | 'ICON';
22
+
17
23
  /**
18
24
  * # GraphCommerce configuration system
19
25
  *
@@ -100,13 +106,33 @@ export type GraphCommerceConfig = {
100
106
  * - https://example.com/en
101
107
  * - https://example.com/en-US
102
108
  */
103
- canonicalBaseUrl: Scalars['String'];
109
+ canonicalBaseUrl: Scalars['String']['input'];
104
110
  /**
105
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.
106
112
  *
107
113
  * When Magento's StoreConfig adds this value, this can be replaced.
108
114
  */
109
- cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']>;
115
+ cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']['input']>;
116
+ /** Use compare functionality */
117
+ compare?: InputMaybe<Scalars['Boolean']['input']>;
118
+ /**
119
+ * By default the compare feature is denoted with a 'compare ICON' (2 arrows facing one another).
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
121
+ */
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']>;
110
136
  /**
111
137
  * Due to a limitation in the GraphQL API of Magento 2, we need to know if the
112
138
  * customer requires email confirmation.
@@ -114,7 +140,7 @@ export type GraphCommerceConfig = {
114
140
  * This value should match Magento 2's configuration value for
115
141
  * `customer/create_account/confirm` and should be removed once we can query
116
142
  */
117
- customerRequireEmailConfirmation?: InputMaybe<Scalars['Boolean']>;
143
+ customerRequireEmailConfirmation?: InputMaybe<Scalars['Boolean']['input']>;
118
144
  /** Debug configuration for GraphCommerce */
119
145
  debug?: InputMaybe<GraphCommerceDebugConfig>;
120
146
  /**
@@ -124,7 +150,7 @@ export type GraphCommerceConfig = {
124
150
  * - Adds "dominant_color" attribute swatches to the product list items.
125
151
  * - Creates a big list items in the product list.
126
152
  */
127
- demoMode?: InputMaybe<Scalars['Boolean']>;
153
+ demoMode?: InputMaybe<Scalars['Boolean']['input']>;
128
154
  /**
129
155
  * See https://support.google.com/analytics/answer/9539598?hl=en
130
156
  *
@@ -132,25 +158,65 @@ export type GraphCommerceConfig = {
132
158
  *
133
159
  * To override the value for a specific locale, configure in i18n config.
134
160
  */
135
- googleAnalyticsId?: InputMaybe<Scalars['String']>;
161
+ googleAnalyticsId?: InputMaybe<Scalars['String']['input']>;
136
162
  /**
137
- * Google reCAPTCHA key, get from https://developers.google.com/recaptcha/docs/v3
163
+ * Google reCAPTCHA site key.
164
+ * When using reCAPTCHA, this value is required, even if you are configuring different values for each locale.
138
165
  *
139
- * This value is required even if you are configuring different values for each locale.
166
+ * Get a site key and a secret key from https://developers.google.com/recaptcha/docs/v3
167
+ *
168
+ * The secret key should be added in the Magento admin panel (Stores > Configuration > Security > Google ReCAPTCHA Storefront > reCAPTCHA v3 Invisible)
169
+ * ReCAPTCHA can then be enabled/disabled for the different forms, separately (Stores > Configuration > Security > Google ReCAPTCHA Storefront > Storefront)
140
170
  */
141
- googleRecaptchaKey?: InputMaybe<Scalars['String']>;
171
+ googleRecaptchaKey?: InputMaybe<Scalars['String']['input']>;
142
172
  /**
143
173
  * The Google Tagmanager ID to be used on the site.
144
174
  *
145
175
  * This value is required even if you are configuring different values for each locale.
146
176
  */
147
- googleTagmanagerId?: InputMaybe<Scalars['String']>;
177
+ googleTagmanagerId?: InputMaybe<Scalars['String']['input']>;
148
178
  /**
149
179
  * The HyGraph endpoint.
150
180
  *
181
+ * > Read-only endpoint that allows low latency and high read-throughput content delivery.
182
+ *
151
183
  * Project settings -> API Access -> High Performance Read-only Content API
152
184
  */
153
- hygraphEndpoint: Scalars['String'];
185
+ hygraphEndpoint: Scalars['String']['input'];
186
+ /**
187
+ * Content API. **Only used for migrations.**
188
+ *
189
+ * > Regular read & write endpoint that allows querying and mutating data in your project.
190
+ *
191
+ * Project settings -> API Access -> Content API
192
+ */
193
+ hygraphWriteAccessEndpoint?: InputMaybe<Scalars['String']['input']>;
194
+ /**
195
+ * Hygraph Management SDK Authorization Token. **Only used for migrations.**
196
+ *
197
+ * Project settings -> API Access -> Permanent Auth Tokens
198
+ *
199
+ * 1. Click 'Add token' and give it a name, something like 'GraphCommerce Write Access Token' and keep stage on 'Published'.
200
+ * 2. Under 'Management API', click 'Yes, Initialize defaults'
201
+ * 3. Click 'Edit Permissions' and enable: 'Update' and 'Delete' permissions for 'models', 'enumerations', 'fields', 'components' and 'sources'
202
+ * - Update existing models
203
+ * - Delete existing models
204
+ * - Update existing fields
205
+ * - Delete existing fields
206
+ * - Update existing enumerations
207
+ * - Delete existing enumerations
208
+ * - Update existing components
209
+ * - Delete existing components
210
+ * - Update remote sources
211
+ * - Delete remote sources
212
+ *
213
+ * ```
214
+ * GC_HYGRAPH_WRITE_ACCESS_ENDPOINT="https://...hygraph.com/v2/..."
215
+ * GC_HYGRAPH_WRITE_ACCESS_TOKEN="AccessTokenFromHygraph"
216
+ * yarn graphcommerce hygraph-migrate
217
+ * ```
218
+ */
219
+ hygraphWriteAccessToken?: InputMaybe<Scalars['String']['input']>;
154
220
  /**
155
221
  * On older versions of GraphCommerce products would use a product type specific route.
156
222
  *
@@ -158,57 +224,63 @@ export type GraphCommerceConfig = {
158
224
  *
159
225
  * @deprecated Will be removed in a future version. [migration](../upgrading/graphcommerce-5-to-6.md#product-routing-changes)
160
226
  */
161
- legacyProductRoute?: InputMaybe<Scalars['Boolean']>;
227
+ legacyProductRoute?: InputMaybe<Scalars['Boolean']['input']>;
162
228
  /** Limit the static generation of SSG when building */
163
- limitSsg?: InputMaybe<Scalars['Boolean']>;
229
+ limitSsg?: InputMaybe<Scalars['Boolean']['input']>;
164
230
  /**
165
231
  * GraphQL Magento endpoint.
166
232
  *
167
233
  * Examples:
168
234
  * - https://magento2.test/graphql
169
235
  */
170
- magentoEndpoint: Scalars['String'];
236
+ magentoEndpoint: Scalars['String']['input'];
171
237
  /** To enable next.js' preview mode, configure the secret you'd like to use. */
172
- previewSecret?: InputMaybe<Scalars['String']>;
238
+ previewSecret?: InputMaybe<Scalars['String']['input']>;
239
+ /**
240
+ * Layout how the filters are rendered.
241
+ * DEFAULT: Will be rendered as horzontal chips on desktop and mobile
242
+ * SIDEBAR: Will be rendered as a sidebar on desktop and horizontal chips on mobile
243
+ */
244
+ productFiltersLayout?: InputMaybe<ProductFiltersLayout>;
173
245
  /**
174
246
  * Product filters with better UI for mobile and desktop.
175
247
  *
176
248
  * @experimental This is an experimental feature and may change in the future.
177
249
  */
178
- productFiltersPro?: InputMaybe<Scalars['Boolean']>;
250
+ productFiltersPro?: InputMaybe<Scalars['Boolean']['input']>;
179
251
  /**
180
252
  * By default we route products to /p/[url] but you can change this to /product/[url] if you wish.
181
253
  *
182
254
  * Default: '/p/'
183
255
  * Example: '/product/'
184
256
  */
185
- productRoute?: InputMaybe<Scalars['String']>;
257
+ productRoute?: InputMaybe<Scalars['String']['input']>;
186
258
  /**
187
259
  * Allow the site to be indexed by search engines.
188
260
  * If false, the robots.txt file will be set to disallow all.
189
261
  */
190
- robotsAllow?: InputMaybe<Scalars['Boolean']>;
262
+ robotsAllow?: InputMaybe<Scalars['Boolean']['input']>;
191
263
  /** All storefront configuration for the project */
192
264
  storefront: Array<GraphCommerceStorefrontConfig>;
193
265
  /** Hide the wishlist functionality for guests. */
194
- wishlistHideForGuests?: InputMaybe<Scalars['Boolean']>;
266
+ wishlistHideForGuests?: InputMaybe<Scalars['Boolean']['input']>;
195
267
  /** Ignores whether a product is already in the wishlist, makes the toggle an add only. */
196
- wishlistIgnoreProductWishlistStatus?: InputMaybe<Scalars['Boolean']>;
268
+ wishlistIgnoreProductWishlistStatus?: InputMaybe<Scalars['Boolean']['input']>;
197
269
  /** Show a message when the product is added to the wishlist. */
198
- wishlistShowFeedbackMessage?: InputMaybe<Scalars['Boolean']>;
270
+ wishlistShowFeedbackMessage?: InputMaybe<Scalars['Boolean']['input']>;
199
271
  };
200
272
 
201
273
  /** Debug configuration for GraphCommerce */
202
274
  export type GraphCommerceDebugConfig = {
203
275
  /** Reports which plugins are enabled or disabled. */
204
- pluginStatus?: InputMaybe<Scalars['Boolean']>;
276
+ pluginStatus?: InputMaybe<Scalars['Boolean']['input']>;
205
277
  /**
206
278
  * Cyclic dependencies can cause memory issues and other strange bugs.
207
279
  * This plugin will warn you when it detects a cyclic dependency.
208
280
  *
209
281
  * When running into memory issues, it can be useful to enable this plugin.
210
282
  */
211
- webpackCircularDependencyPlugin?: InputMaybe<Scalars['Boolean']>;
283
+ webpackCircularDependencyPlugin?: InputMaybe<Scalars['Boolean']['input']>;
212
284
  /**
213
285
  * When updating packages it can happen that the same package is included with different versions in the same project.
214
286
  *
@@ -216,7 +288,7 @@ export type GraphCommerceDebugConfig = {
216
288
  * - The same package is included multiple times in the bundle, increasing the bundle size.
217
289
  * - The Typescript types of the package are not compatible with each other, causing Typescript errors.
218
290
  */
219
- webpackDuplicatesPlugin?: InputMaybe<Scalars['Boolean']>;
291
+ webpackDuplicatesPlugin?: InputMaybe<Scalars['Boolean']['input']>;
220
292
  };
221
293
 
222
294
  /** All storefront configuration for the project */
@@ -229,33 +301,33 @@ export type GraphCommerceStorefrontConfig = {
229
301
  * - https://example.com/en
230
302
  * - https://example.com/en-US
231
303
  */
232
- canonicalBaseUrl?: InputMaybe<Scalars['String']>;
304
+ canonicalBaseUrl?: InputMaybe<Scalars['String']['input']>;
233
305
  /** Due to a limitation of the GraphQL API it is not possible to determine if a cart should be displayed including or excluding tax. */
234
- cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']>;
306
+ cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']['input']>;
235
307
  /**
236
308
  * There can only be one entry with defaultLocale set to true.
237
309
  * - If there are more, the first one is used.
238
310
  * - If there is none, the first entry is used.
239
311
  */
240
- defaultLocale?: InputMaybe<Scalars['Boolean']>;
312
+ defaultLocale?: InputMaybe<Scalars['Boolean']['input']>;
241
313
  /** Domain configuration, must be a domain https://tools.ietf.org/html/rfc3986 */
242
- domain?: InputMaybe<Scalars['String']>;
314
+ domain?: InputMaybe<Scalars['String']['input']>;
243
315
  /**
244
316
  * Configure different Google Analytics IDs for different locales.
245
317
  *
246
318
  * To disable for a specific locale, set the value to null.
247
319
  */
248
- googleAnalyticsId?: InputMaybe<Scalars['String']>;
320
+ googleAnalyticsId?: InputMaybe<Scalars['String']['input']>;
249
321
  /** Locale specific google reCAPTCHA key. */
250
- googleRecaptchaKey?: InputMaybe<Scalars['String']>;
322
+ googleRecaptchaKey?: InputMaybe<Scalars['String']['input']>;
251
323
  /** The Google Tagmanager ID to be used per locale. */
252
- googleTagmanagerId?: InputMaybe<Scalars['String']>;
324
+ googleTagmanagerId?: InputMaybe<Scalars['String']['input']>;
253
325
  /** Add a gcms-locales header to make sure queries return in a certain language, can be an array to define fallbacks. */
254
- hygraphLocales?: InputMaybe<Array<Scalars['String']>>;
326
+ hygraphLocales?: InputMaybe<Array<Scalars['String']['input']>>;
255
327
  /** Specify a custom locale for to load translations. */
256
- linguiLocale?: InputMaybe<Scalars['String']>;
328
+ linguiLocale?: InputMaybe<Scalars['String']['input']>;
257
329
  /** Must be a locale string https://www.unicode.org/reports/tr35/tr35-59/tr35.html#Identifiers */
258
- locale: Scalars['String'];
330
+ locale: Scalars['String']['input'];
259
331
  /**
260
332
  * Magento store code.
261
333
  *
@@ -266,9 +338,13 @@ export type GraphCommerceStorefrontConfig = {
266
338
  * - en-us
267
339
  * - b2b-us
268
340
  */
269
- magentoStoreCode: Scalars['String'];
341
+ magentoStoreCode: Scalars['String']['input'];
270
342
  };
271
343
 
344
+ export type ProductFiltersLayout =
345
+ | 'DEFAULT'
346
+ | 'SIDEBAR';
347
+
272
348
 
273
349
  type Properties<T> = Required<{
274
350
  [K in keyof T]: z.ZodType<T[K], any, T[K]>;
@@ -280,10 +356,17 @@ export const isDefinedNonNullAny = (v: any): v is definedNonNullAny => v !== und
280
356
 
281
357
  export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny(v));
282
358
 
359
+ export const CompareVariantSchema = z.enum(['CHECKBOX', 'ICON']);
360
+
361
+ export const ProductFiltersLayoutSchema = z.enum(['DEFAULT', 'SIDEBAR']);
362
+
283
363
  export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerceConfig>> {
284
- return z.object<Properties<GraphCommerceConfig>>({
364
+ return z.object({
285
365
  canonicalBaseUrl: z.string().min(1),
286
366
  cartDisplayPricesInclTax: z.boolean().nullish(),
367
+ compare: z.boolean().nullish(),
368
+ compareVariant: CompareVariantSchema.nullish(),
369
+ configurableVariantForSimple: z.boolean().nullish(),
287
370
  customerRequireEmailConfirmation: z.boolean().nullish(),
288
371
  debug: GraphCommerceDebugConfigSchema().nullish(),
289
372
  demoMode: z.boolean().nullish(),
@@ -291,10 +374,13 @@ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerc
291
374
  googleRecaptchaKey: z.string().nullish(),
292
375
  googleTagmanagerId: z.string().nullish(),
293
376
  hygraphEndpoint: z.string().min(1),
377
+ hygraphWriteAccessEndpoint: z.string().nullish(),
378
+ hygraphWriteAccessToken: z.string().nullish(),
294
379
  legacyProductRoute: z.boolean().nullish(),
295
380
  limitSsg: z.boolean().nullish(),
296
381
  magentoEndpoint: z.string().min(1),
297
382
  previewSecret: z.string().nullish(),
383
+ productFiltersLayout: ProductFiltersLayoutSchema.nullish(),
298
384
  productFiltersPro: z.boolean().nullish(),
299
385
  productRoute: z.string().nullish(),
300
386
  robotsAllow: z.boolean().nullish(),
@@ -306,7 +392,7 @@ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerc
306
392
  }
307
393
 
308
394
  export function GraphCommerceDebugConfigSchema(): z.ZodObject<Properties<GraphCommerceDebugConfig>> {
309
- return z.object<Properties<GraphCommerceDebugConfig>>({
395
+ return z.object({
310
396
  pluginStatus: z.boolean().nullish(),
311
397
  webpackCircularDependencyPlugin: z.boolean().nullish(),
312
398
  webpackDuplicatesPlugin: z.boolean().nullish()
@@ -314,7 +400,7 @@ export function GraphCommerceDebugConfigSchema(): z.ZodObject<Properties<GraphCo
314
400
  }
315
401
 
316
402
  export function GraphCommerceStorefrontConfigSchema(): z.ZodObject<Properties<GraphCommerceStorefrontConfig>> {
317
- return z.object<Properties<GraphCommerceStorefrontConfig>>({
403
+ return z.object({
318
404
  canonicalBaseUrl: z.string().nullish(),
319
405
  cartDisplayPricesInclTax: z.boolean().nullish(),
320
406
  defaultLocale: z.boolean().nullish(),
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ import type React from 'react'
2
2
 
3
3
  export * from './utils/isMonorepo'
4
4
  export * from './utils/resolveDependenciesSync'
5
+ export * from './utils/packageRoots'
5
6
  export * from './withGraphCommerce'
6
7
  export * from './generated/config'
7
8
  export * from './config'
@@ -0,0 +1,35 @@
1
+ type PathCount = { path: string; count: number }
2
+
3
+ export const packageRoots = (packagePaths: string[]): string[] => {
4
+ const pathMap: { [key: string]: PathCount } = {}
5
+
6
+ // Iterate over each path in the array
7
+ packagePaths.forEach((singlePath) => {
8
+ const parts = singlePath.split('/')
9
+
10
+ // Iterate through each part of the path
11
+ for (let i = 1; i < parts.length; i++) {
12
+ const subPath = parts.slice(0, i + 1).join('/')
13
+
14
+ // Increment the count of this subPath
15
+ if (pathMap[subPath]) {
16
+ pathMap[subPath].count += 1
17
+ } else {
18
+ pathMap[subPath] = { path: subPath, count: 1 }
19
+ }
20
+ }
21
+ })
22
+
23
+ // Filter the paths that appear more than once
24
+ const roots: string[] = []
25
+ Object.values(pathMap).forEach(({ path, count }) => {
26
+ if (count > 1) {
27
+ roots.push(path)
28
+ }
29
+ })
30
+
31
+ // Filter out the sub-paths which are part of another longer sub-path
32
+ return roots.filter(
33
+ (root, index, self) => self.findIndex((r) => r !== root && r.startsWith(root + '/')) === -1,
34
+ )
35
+ }
@@ -61,8 +61,9 @@ export function withGraphCommerce(nextConfig: NextConfig, cwd: string): NextConf
61
61
  return {
62
62
  ...nextConfig,
63
63
  experimental: {
64
- enableUndici: true,
65
64
  ...nextConfig.experimental,
65
+ scrollRestoration: true,
66
+ swcPlugins: [...(nextConfig.experimental?.swcPlugins ?? []), ['@lingui/swc-plugin', {}]],
66
67
  },
67
68
  i18n: {
68
69
  defaultLocale:
@@ -91,6 +92,7 @@ export function withGraphCommerce(nextConfig: NextConfig, cwd: string): NextConf
91
92
  { source: '/product/downloadable/:url*', destination, permanent: true },
92
93
  { source: '/product/grouped/:url*', destination, permanent: true },
93
94
  { source: '/product/virtual/:url*', destination, permanent: true },
95
+ { source: '/customer/account', destination: '/account', permanent: true },
94
96
  ],
95
97
  )
96
98