@graphcommerce/next-config 8.1.0-canary.9 → 9.0.0-canary.55
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 +133 -0
- package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +48 -2
- package/__tests__/config/utils/configToImportMeta.ts +0 -4
- package/__tests__/config/utils/mergeEnvIntoConfig.ts +15 -2
- package/__tests__/config/utils/rewriteLegancyEnv.ts +1 -1
- package/__tests__/interceptors/findPlugins.ts +60 -126
- package/__tests__/interceptors/generateInterceptors.ts +136 -57
- package/__tests__/interceptors/parseStructure.ts +50 -0
- package/dist/config/demoConfig.js +5 -0
- package/dist/config/utils/mergeEnvIntoConfig.js +8 -1
- package/dist/generated/config.js +15 -8
- package/dist/interceptors/extractExports.js +21 -18
- package/dist/interceptors/findOriginalSource.js +17 -1
- package/dist/interceptors/generateInterceptor.js +3 -4
- package/dist/interceptors/parseStructure.js +9 -1
- package/dist/interceptors/writeInterceptors.js +7 -7
- package/dist/withGraphCommerce.js +13 -4
- package/package.json +1 -1
- package/src/config/demoConfig.ts +5 -0
- package/src/config/utils/mergeEnvIntoConfig.ts +9 -1
- package/src/generated/config.ts +49 -13
- package/src/interceptors/extractExports.ts +21 -21
- package/src/interceptors/findOriginalSource.ts +16 -1
- package/src/interceptors/generateInterceptor.ts +3 -5
- package/src/interceptors/parseStructure.ts +14 -1
- package/src/interceptors/writeInterceptors.ts +7 -7
- package/src/withGraphCommerce.ts +13 -5
|
@@ -156,3 +156,53 @@ export const AddProductsToCartForm = EnableCrossselsPlugin
|
|
|
156
156
|
}
|
|
157
157
|
`)
|
|
158
158
|
})
|
|
159
|
+
|
|
160
|
+
it('parses', () => {
|
|
161
|
+
const src = `
|
|
162
|
+
import {
|
|
163
|
+
PaymentMethodContextProviderProps,
|
|
164
|
+
PaymentModule,
|
|
165
|
+
} from '@graphcommerce/magento-cart-payment-method'
|
|
166
|
+
import type { PluginProps } from '@graphcommerce/next-config'
|
|
167
|
+
import { AdyenPaymentActionCard } from '../components/AdyenPaymentActionCard/AdyenPaymentActionCard'
|
|
168
|
+
import { AdyenPaymentHandler } from '../components/AdyenPaymentHandler/AdyenPaymentHandler'
|
|
169
|
+
import { HppOptions } from '../components/AdyenPaymentOptionsAndPlaceOrder/AdyenPaymentOptionsAndPlaceOrder'
|
|
170
|
+
import { adyenHppExpandMethods } from '../hooks/adyenHppExpandMethods'
|
|
171
|
+
|
|
172
|
+
export const adyen_hpp: PaymentModule = {
|
|
173
|
+
PaymentOptions: HppOptions,
|
|
174
|
+
PaymentPlaceOrder: () => null,
|
|
175
|
+
PaymentHandler: AdyenPaymentHandler,
|
|
176
|
+
PaymentActionCard: AdyenPaymentActionCard,
|
|
177
|
+
expandMethods: adyenHppExpandMethods,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export const component = 'PaymentMethodContextProvider'
|
|
181
|
+
export const exported = '@graphcommerce/magento-cart-payment-method'
|
|
182
|
+
|
|
183
|
+
function AddAdyenMethods(props: PluginProps<PaymentMethodContextProviderProps>) {
|
|
184
|
+
const { modules, Prev, ...rest } = props
|
|
185
|
+
return <Prev {...rest} modules={{ ...modules, adyen_hpp }} />
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export const Plugin = AddAdyenMethods
|
|
189
|
+
`
|
|
190
|
+
|
|
191
|
+
const plugins = parseStructure(
|
|
192
|
+
parseSync(src),
|
|
193
|
+
fakeconfig,
|
|
194
|
+
'@graphcommerce/magento-payment-adyen/plugins/AddAdyenMethods.tsx',
|
|
195
|
+
)
|
|
196
|
+
expect(plugins).toHaveLength(1)
|
|
197
|
+
expect(plugins[0]).toMatchInlineSnapshot(`
|
|
198
|
+
{
|
|
199
|
+
"enabled": true,
|
|
200
|
+
"sourceExport": "Plugin",
|
|
201
|
+
"sourceModule": "@graphcommerce/magento-payment-adyen/plugins/AddAdyenMethods.tsx",
|
|
202
|
+
"targetExport": "PaymentMethodContextProvider",
|
|
203
|
+
"targetModule": "@graphcommerce/magento-cart-payment-method",
|
|
204
|
+
"type": "component",
|
|
205
|
+
}
|
|
206
|
+
`)
|
|
207
|
+
expect(plugins[1]).toMatchInlineSnapshot(`undefined`)
|
|
208
|
+
})
|
|
@@ -5,6 +5,7 @@ exports.demoConfig = {
|
|
|
5
5
|
canonicalBaseUrl: 'https://graphcommerce.vercel.app',
|
|
6
6
|
hygraphEndpoint: 'https://eu-central-1.cdn.hygraph.com/content/ckhx7xadya6xs01yxdujt8i80/master',
|
|
7
7
|
magentoEndpoint: 'https://backend.reachdigital.dev/graphql',
|
|
8
|
+
magentoVersion: 246,
|
|
8
9
|
storefront: [
|
|
9
10
|
{ locale: 'en', magentoStoreCode: 'en_US', defaultLocale: true },
|
|
10
11
|
{
|
|
@@ -35,6 +36,7 @@ exports.demoConfig = {
|
|
|
35
36
|
],
|
|
36
37
|
productFiltersPro: true,
|
|
37
38
|
productFiltersLayout: 'DEFAULT',
|
|
39
|
+
productListPaginationVariant: 'COMPACT',
|
|
38
40
|
compareVariant: 'ICON',
|
|
39
41
|
robotsAllow: false,
|
|
40
42
|
demoMode: true,
|
|
@@ -44,4 +46,7 @@ exports.demoConfig = {
|
|
|
44
46
|
configurableVariantForSimple: true,
|
|
45
47
|
configurableVariantValues: { url: true, content: true, gallery: true },
|
|
46
48
|
recentlyViewedProducts: { enabled: true, maxCount: 20 },
|
|
49
|
+
breadcrumbs: false,
|
|
50
|
+
customerDeleteEnabled: true,
|
|
51
|
+
previewSecret: 'SECRET',
|
|
47
52
|
};
|
|
@@ -43,6 +43,8 @@ function configToEnvSchema(schema) {
|
|
|
43
43
|
node = node.unwrap();
|
|
44
44
|
if (node instanceof zod_1.ZodNullable)
|
|
45
45
|
node = node.unwrap();
|
|
46
|
+
if (node instanceof zod_1.ZodDefault)
|
|
47
|
+
node = node.removeDefault();
|
|
46
48
|
if (node instanceof zod_1.ZodObject) {
|
|
47
49
|
if (path.length > 0) {
|
|
48
50
|
envSchema[(0, exports.toEnvStr)(path)] = zod_1.z
|
|
@@ -73,7 +75,12 @@ function configToEnvSchema(schema) {
|
|
|
73
75
|
});
|
|
74
76
|
return;
|
|
75
77
|
}
|
|
76
|
-
if (node instanceof zod_1.
|
|
78
|
+
if (node instanceof zod_1.ZodNumber) {
|
|
79
|
+
envSchema[(0, exports.toEnvStr)(path)] = zod_1.z.coerce.number().optional();
|
|
80
|
+
envToDot[(0, exports.toEnvStr)(path)] = (0, exports.dotNotation)(path);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (node instanceof zod_1.ZodString || node instanceof zod_1.ZodEnum) {
|
|
77
84
|
envSchema[(0, exports.toEnvStr)(path)] = node.optional();
|
|
78
85
|
envToDot[(0, exports.toEnvStr)(path)] = (0, exports.dotNotation)(path);
|
|
79
86
|
return;
|
package/dist/generated/config.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SidebarGalleryConfigSchema = exports.RecentlyViewedProductsConfigSchema = exports.MagentoConfigurableVariantValuesSchema = exports.GraphCommerceStorefrontConfigSchema = exports.GraphCommerceDebugConfigSchema = exports.GraphCommerceConfigSchema = exports.DatalayerConfigSchema = exports.SidebarGalleryPaginationVariantSchema = exports.ProductFiltersLayoutSchema = exports.CompareVariantSchema = exports.definedNonNullAnySchema = exports.isDefinedNonNullAny = void 0;
|
|
3
|
+
exports.SidebarGalleryConfigSchema = exports.RecentlyViewedProductsConfigSchema = exports.MagentoConfigurableVariantValuesSchema = exports.GraphCommerceStorefrontConfigSchema = exports.GraphCommerceDebugConfigSchema = exports.GraphCommerceConfigSchema = exports.DatalayerConfigSchema = exports.SidebarGalleryPaginationVariantSchema = exports.ProductFiltersLayoutSchema = exports.PaginationVariantSchema = 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
9
|
exports.CompareVariantSchema = zod_1.z.enum(['CHECKBOX', 'ICON']);
|
|
10
|
+
exports.PaginationVariantSchema = zod_1.z.enum(['COMPACT', 'EXTENDED']);
|
|
10
11
|
exports.ProductFiltersLayoutSchema = zod_1.z.enum(['DEFAULT', 'SIDEBAR']);
|
|
11
12
|
exports.SidebarGalleryPaginationVariantSchema = zod_1.z.enum(['DOTS', 'THUMBNAILS_BOTTOM']);
|
|
12
13
|
function DatalayerConfigSchema() {
|
|
@@ -17,18 +18,21 @@ function DatalayerConfigSchema() {
|
|
|
17
18
|
exports.DatalayerConfigSchema = DatalayerConfigSchema;
|
|
18
19
|
function GraphCommerceConfigSchema() {
|
|
19
20
|
return zod_1.z.object({
|
|
21
|
+
breadcrumbs: zod_1.z.boolean().default(false).nullish(),
|
|
20
22
|
canonicalBaseUrl: zod_1.z.string().min(1),
|
|
21
23
|
cartDisplayPricesInclTax: zod_1.z.boolean().nullish(),
|
|
22
24
|
compare: zod_1.z.boolean().nullish(),
|
|
23
|
-
compareVariant: exports.CompareVariantSchema.nullish(),
|
|
24
|
-
configurableVariantForSimple: zod_1.z.boolean().nullish(),
|
|
25
|
+
compareVariant: exports.CompareVariantSchema.default("ICON").nullish(),
|
|
26
|
+
configurableVariantForSimple: zod_1.z.boolean().default(false).nullish(),
|
|
25
27
|
configurableVariantValues: MagentoConfigurableVariantValuesSchema().nullish(),
|
|
26
|
-
crossSellsHideCartItems: zod_1.z.boolean().nullish(),
|
|
27
|
-
crossSellsRedirectItems: zod_1.z.boolean().nullish(),
|
|
28
|
-
|
|
28
|
+
crossSellsHideCartItems: zod_1.z.boolean().default(false).nullish(),
|
|
29
|
+
crossSellsRedirectItems: zod_1.z.boolean().default(false).nullish(),
|
|
30
|
+
customerAddressNoteEnable: zod_1.z.boolean().nullish(),
|
|
31
|
+
customerCompanyFieldsEnable: zod_1.z.boolean().nullish(),
|
|
32
|
+
customerDeleteEnabled: zod_1.z.boolean().nullish(),
|
|
29
33
|
dataLayer: DatalayerConfigSchema().nullish(),
|
|
30
34
|
debug: GraphCommerceDebugConfigSchema().nullish(),
|
|
31
|
-
demoMode: zod_1.z.boolean().nullish(),
|
|
35
|
+
demoMode: zod_1.z.boolean().default(true).nullish(),
|
|
32
36
|
enableGuestCheckoutLogin: zod_1.z.boolean().nullish(),
|
|
33
37
|
googleAnalyticsId: zod_1.z.string().nullish(),
|
|
34
38
|
googleRecaptchaKey: zod_1.z.string().nullish(),
|
|
@@ -40,9 +44,11 @@ function GraphCommerceConfigSchema() {
|
|
|
40
44
|
hygraphWriteAccessToken: zod_1.z.string().nullish(),
|
|
41
45
|
limitSsg: zod_1.z.boolean().nullish(),
|
|
42
46
|
magentoEndpoint: zod_1.z.string().min(1),
|
|
47
|
+
magentoVersion: zod_1.z.number(),
|
|
43
48
|
previewSecret: zod_1.z.string().nullish(),
|
|
44
|
-
productFiltersLayout: exports.ProductFiltersLayoutSchema.nullish(),
|
|
49
|
+
productFiltersLayout: exports.ProductFiltersLayoutSchema.default("DEFAULT").nullish(),
|
|
45
50
|
productFiltersPro: zod_1.z.boolean().nullish(),
|
|
51
|
+
productListPaginationVariant: exports.PaginationVariantSchema.default("COMPACT").nullish(),
|
|
46
52
|
productRoute: zod_1.z.string().nullish(),
|
|
47
53
|
recentlyViewedProducts: RecentlyViewedProductsConfigSchema().nullish(),
|
|
48
54
|
robotsAllow: zod_1.z.boolean().nullish(),
|
|
@@ -66,6 +72,7 @@ function GraphCommerceStorefrontConfigSchema() {
|
|
|
66
72
|
return zod_1.z.object({
|
|
67
73
|
canonicalBaseUrl: zod_1.z.string().nullish(),
|
|
68
74
|
cartDisplayPricesInclTax: zod_1.z.boolean().nullish(),
|
|
75
|
+
customerCompanyFieldsEnable: zod_1.z.boolean().nullish(),
|
|
69
76
|
defaultLocale: zod_1.z.boolean().nullish(),
|
|
70
77
|
domain: zod_1.z.string().nullish(),
|
|
71
78
|
googleAnalyticsId: zod_1.z.string().nullish(),
|
|
@@ -87,9 +87,8 @@ function extractValue(node, path, optional = false) {
|
|
|
87
87
|
case 'undefined':
|
|
88
88
|
return undefined;
|
|
89
89
|
default:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
throw new UnsupportedValueError(`Unknown identifier "${node.value}"`, path);
|
|
90
|
+
return exports.RUNTIME_VALUE;
|
|
91
|
+
// throw new UnsupportedValueError(`Unknown identifier "${node.value}"`, path)
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
else if (isArrayExpression(node)) {
|
|
@@ -100,9 +99,11 @@ function extractValue(node, path, optional = false) {
|
|
|
100
99
|
if (elem) {
|
|
101
100
|
if (elem.spread) {
|
|
102
101
|
// e.g. [ ...a ]
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
return exports.RUNTIME_VALUE;
|
|
103
|
+
// throw new UnsupportedValueError(
|
|
104
|
+
// 'Unsupported spread operator in the Array Expression',
|
|
105
|
+
// path,
|
|
106
|
+
// )
|
|
106
107
|
}
|
|
107
108
|
arr.push(extractValue(elem.expression, path && [...path, `[${i}]`], optional));
|
|
108
109
|
}
|
|
@@ -120,9 +121,11 @@ function extractValue(node, path, optional = false) {
|
|
|
120
121
|
for (const prop of node.properties) {
|
|
121
122
|
if (!isKeyValueProperty(prop)) {
|
|
122
123
|
// e.g. { ...a }
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
return exports.RUNTIME_VALUE;
|
|
125
|
+
// throw new UnsupportedValueError(
|
|
126
|
+
// 'Unsupported spread operator in the Object Expression',
|
|
127
|
+
// path,
|
|
128
|
+
// )
|
|
126
129
|
}
|
|
127
130
|
let key;
|
|
128
131
|
if (isIdentifier(prop.key)) {
|
|
@@ -134,9 +137,11 @@ function extractValue(node, path, optional = false) {
|
|
|
134
137
|
key = prop.key.value;
|
|
135
138
|
}
|
|
136
139
|
else {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
return exports.RUNTIME_VALUE;
|
|
141
|
+
// throw new UnsupportedValueError(
|
|
142
|
+
// `Unsupported key type "${prop.key.type}" in the Object Expression`,
|
|
143
|
+
// path,
|
|
144
|
+
// )
|
|
140
145
|
}
|
|
141
146
|
obj[key] = extractValue(prop.value, path && [...path, key]);
|
|
142
147
|
}
|
|
@@ -146,9 +151,8 @@ function extractValue(node, path, optional = false) {
|
|
|
146
151
|
// e.g. `abc`
|
|
147
152
|
if (node.expressions.length !== 0) {
|
|
148
153
|
// TODO: should we add support for `${'e'}d${'g'}'e'`?
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
throw new UnsupportedValueError('Unsupported template literal with expressions', path);
|
|
154
|
+
return exports.RUNTIME_VALUE;
|
|
155
|
+
// throw new UnsupportedValueError('Unsupported template literal with expressions', path)
|
|
152
156
|
}
|
|
153
157
|
// When TemplateLiteral has 0 expressions, the length of quasis is always 1.
|
|
154
158
|
// Because when parsing TemplateLiteral, the parser yields the first quasi,
|
|
@@ -163,9 +167,8 @@ function extractValue(node, path, optional = false) {
|
|
|
163
167
|
return cooked ?? raw;
|
|
164
168
|
}
|
|
165
169
|
else {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
throw new UnsupportedValueError(`Unsupported node type "${node.type}"`, path);
|
|
170
|
+
return exports.RUNTIME_VALUE;
|
|
171
|
+
// throw new UnsupportedValueError(`Unsupported node type "${node.type}"`, path)
|
|
169
172
|
}
|
|
170
173
|
}
|
|
171
174
|
function extractExports(module) {
|
|
@@ -33,6 +33,22 @@ function parseAndFindExport(resolved, findExport, resolve) {
|
|
|
33
33
|
break;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
if (node.type === 'ExportNamedDeclaration') {
|
|
37
|
+
for (const specifier of node.specifiers) {
|
|
38
|
+
if (specifier.type === 'ExportSpecifier') {
|
|
39
|
+
if (specifier.exported?.value === findExport)
|
|
40
|
+
return resolved;
|
|
41
|
+
}
|
|
42
|
+
else if (specifier.type === 'ExportDefaultSpecifier') {
|
|
43
|
+
// todo
|
|
44
|
+
}
|
|
45
|
+
else if (specifier.type === 'ExportNamespaceSpecifier') {
|
|
46
|
+
// todo
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// todo: if (node.type === 'ExportDefaultDeclaration') {}
|
|
51
|
+
// todo: if (node.type === 'ExportDefaultExpression') {}
|
|
36
52
|
}
|
|
37
53
|
const exports = ast.body
|
|
38
54
|
.filter((node) => node.type === 'ExportAllDeclaration')
|
|
@@ -78,7 +94,7 @@ function findOriginalSource(plug, resolved, resolve) {
|
|
|
78
94
|
if (!newResolved) {
|
|
79
95
|
return {
|
|
80
96
|
resolved: undefined,
|
|
81
|
-
error: new Error(`
|
|
97
|
+
error: new Error(`Plugin target not found ${plug.targetModule}#${plug.sourceExport} for plugin ${plug.sourceModule}#${plug.sourceExport}`),
|
|
82
98
|
};
|
|
83
99
|
}
|
|
84
100
|
// cachedResults.set(cacheKey, newResolved)
|
|
@@ -45,7 +45,7 @@ const originalSuffix = 'Original';
|
|
|
45
45
|
const sourceSuffix = 'Plugin';
|
|
46
46
|
const interceptorSuffix = 'Interceptor';
|
|
47
47
|
const disabledSuffix = 'Disabled';
|
|
48
|
-
const name = (plugin) => `${plugin.sourceModule
|
|
48
|
+
const name = (plugin) => `${plugin.sourceExport}${plugin.sourceModule
|
|
49
49
|
.split('/')[plugin.sourceModule.split('/').length - 1].replace(/[^a-zA-Z0-9]/g, '')}`;
|
|
50
50
|
const fileName = (plugin) => `${plugin.sourceModule}#${plugin.sourceExport}`;
|
|
51
51
|
const originalName = (n) => `${n}${originalSuffix}`;
|
|
@@ -121,8 +121,7 @@ async function generateInterceptor(interceptor, config, oldInterceptorSource) {
|
|
|
121
121
|
.join(' wrapping ');
|
|
122
122
|
if (isReplacePluginConfig(p)) {
|
|
123
123
|
new RenameVisitor_1.RenameVisitor([originalName(p.targetExport)], (s) => s.replace(originalSuffix, disabledSuffix)).visitModule(ast);
|
|
124
|
-
carryProps.push(
|
|
125
|
-
result = `type ${interceptorPropsName(name(p))} = React.ComponentProps<typeof ${sourceName(name(p))}>`;
|
|
124
|
+
carryProps.push(`React.ComponentProps<typeof ${sourceName(name(p))}>`);
|
|
126
125
|
pluginSee.push(`@see {${sourceName(name(p))}} for replacement of the original source (original source not used)`);
|
|
127
126
|
}
|
|
128
127
|
if (isReactPluginConfig(p)) {
|
|
@@ -154,7 +153,7 @@ async function generateInterceptor(interceptor, config, oldInterceptorSource) {
|
|
|
154
153
|
})
|
|
155
154
|
.filter((v) => !!v)
|
|
156
155
|
.join('\n');
|
|
157
|
-
const isComponent = plugins.every((p) =>
|
|
156
|
+
const isComponent = plugins.every((p) => isReactPluginConfig(p));
|
|
158
157
|
if (isComponent && plugins.some((p) => isMethodPluginConfig(p))) {
|
|
159
158
|
throw new Error(`Cannot mix React and Method plugins for ${base} in ${dependency}.`);
|
|
160
159
|
}
|
|
@@ -27,7 +27,7 @@ function parseStructure(ast, gcConfig, sourceModule) {
|
|
|
27
27
|
exportVals.push('Plugin');
|
|
28
28
|
if (func && !moduleConfig)
|
|
29
29
|
exportVals.push('plugin');
|
|
30
|
-
|
|
30
|
+
const pluginConfigs = exportVals
|
|
31
31
|
.map((exportVal) => {
|
|
32
32
|
let config = isObject(moduleConfig) ? moduleConfig : {};
|
|
33
33
|
if (!moduleConfig && component) {
|
|
@@ -41,6 +41,7 @@ function parseStructure(ast, gcConfig, sourceModule) {
|
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
43
|
console.error(`Plugin configuration invalid! See ${sourceModule}`);
|
|
44
|
+
return null;
|
|
44
45
|
}
|
|
45
46
|
const parsed = pluginConfigParsed.safeParse(config);
|
|
46
47
|
if (!parsed.success) {
|
|
@@ -67,5 +68,12 @@ function parseStructure(ast, gcConfig, sourceModule) {
|
|
|
67
68
|
return val;
|
|
68
69
|
})
|
|
69
70
|
.filter(nonNullable);
|
|
71
|
+
const newPluginConfigs = pluginConfigs.reduce((acc, pluginConfig) => {
|
|
72
|
+
if (!acc.find((accPluginConfig) => accPluginConfig.sourceExport === pluginConfig.sourceExport)) {
|
|
73
|
+
acc.push(pluginConfig);
|
|
74
|
+
}
|
|
75
|
+
return acc;
|
|
76
|
+
}, []);
|
|
77
|
+
return newPluginConfigs;
|
|
70
78
|
}
|
|
71
79
|
exports.parseStructure = parseStructure;
|
|
@@ -17,19 +17,19 @@ function checkFileExists(file) {
|
|
|
17
17
|
}
|
|
18
18
|
async function writeInterceptors(interceptors, cwd = process.cwd()) {
|
|
19
19
|
const dependencies = (0, resolveDependenciesSync_1.resolveDependenciesSync)(cwd);
|
|
20
|
-
const existing =
|
|
20
|
+
const existing = new Set();
|
|
21
21
|
dependencies.forEach((dependency) => {
|
|
22
22
|
const files = (0, glob_1.sync)([`${dependency}/**/*.interceptor.tsx`, `${dependency}/**/*.interceptor.ts`], { cwd });
|
|
23
|
-
existing.
|
|
23
|
+
files.forEach((file) => existing.add(file));
|
|
24
24
|
});
|
|
25
25
|
const written = Object.entries(interceptors).map(async ([, plugin]) => {
|
|
26
26
|
const extension = plugin.sourcePath.endsWith('.tsx') ? '.tsx' : '.ts';
|
|
27
27
|
const relativeFile = `${plugin.fromRoot}.interceptor${extension}`;
|
|
28
|
-
if (existing.
|
|
29
|
-
|
|
28
|
+
if (existing.has(relativeFile)) {
|
|
29
|
+
existing.delete(relativeFile);
|
|
30
30
|
}
|
|
31
|
-
if (existing.
|
|
32
|
-
|
|
31
|
+
if (existing.has(`./${relativeFile}`)) {
|
|
32
|
+
existing.delete(`./${relativeFile}`);
|
|
33
33
|
}
|
|
34
34
|
const fileToWrite = path_1.default.join(cwd, relativeFile);
|
|
35
35
|
const isSame = (await checkFileExists(fileToWrite)) &&
|
|
@@ -38,7 +38,7 @@ async function writeInterceptors(interceptors, cwd = process.cwd()) {
|
|
|
38
38
|
await promises_1.default.writeFile(fileToWrite, plugin.template);
|
|
39
39
|
});
|
|
40
40
|
// Cleanup unused interceptors
|
|
41
|
-
const cleaned = existing.map(async (file) => (await checkFileExists(file)) && (await promises_1.default.unlink(file)));
|
|
41
|
+
const cleaned = [...existing].map(async (file) => (await checkFileExists(file)) && (await promises_1.default.unlink(file)));
|
|
42
42
|
await Promise.all(written);
|
|
43
43
|
await Promise.all(cleaned);
|
|
44
44
|
}
|
|
@@ -94,8 +94,19 @@ function withGraphCommerce(nextConfig, cwd) {
|
|
|
94
94
|
},
|
|
95
95
|
transpilePackages,
|
|
96
96
|
webpack: (config, options) => {
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
if (!config.module)
|
|
98
|
+
config.module = { rules: [] };
|
|
99
|
+
config.module = {
|
|
100
|
+
...config.module,
|
|
101
|
+
rules: [
|
|
102
|
+
...(config.module.rules ?? []),
|
|
103
|
+
// Allow importing yml/yaml files for graphql-mesh
|
|
104
|
+
{ test: /\.ya?ml$/, use: 'js-yaml-loader' },
|
|
105
|
+
// @lingui .po file support
|
|
106
|
+
{ test: /\.po/, use: '@lingui/loader' },
|
|
107
|
+
],
|
|
108
|
+
exprContextCritical: false,
|
|
109
|
+
};
|
|
99
110
|
if (!config.plugins)
|
|
100
111
|
config.plugins = [];
|
|
101
112
|
// Make import.meta.graphCommerce available for usage.
|
|
@@ -122,8 +133,6 @@ function withGraphCommerce(nextConfig, cwd) {
|
|
|
122
133
|
}));
|
|
123
134
|
}
|
|
124
135
|
}
|
|
125
|
-
// @lingui .po file support
|
|
126
|
-
config.module?.rules?.push({ test: /\.po/, use: '@lingui/loader' });
|
|
127
136
|
config.snapshot = {
|
|
128
137
|
...(config.snapshot ?? {}),
|
|
129
138
|
managedPaths: [
|
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": "
|
|
5
|
+
"version": "9.0.0-canary.55",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "src/index.ts",
|
package/src/config/demoConfig.ts
CHANGED
|
@@ -7,6 +7,7 @@ export const demoConfig: PartialDeep<GraphCommerceConfig, { recurseIntoArrays: t
|
|
|
7
7
|
canonicalBaseUrl: 'https://graphcommerce.vercel.app',
|
|
8
8
|
hygraphEndpoint: 'https://eu-central-1.cdn.hygraph.com/content/ckhx7xadya6xs01yxdujt8i80/master',
|
|
9
9
|
magentoEndpoint: 'https://backend.reachdigital.dev/graphql',
|
|
10
|
+
magentoVersion: 246,
|
|
10
11
|
storefront: [
|
|
11
12
|
{ locale: 'en', magentoStoreCode: 'en_US', defaultLocale: true },
|
|
12
13
|
{
|
|
@@ -37,6 +38,7 @@ export const demoConfig: PartialDeep<GraphCommerceConfig, { recurseIntoArrays: t
|
|
|
37
38
|
],
|
|
38
39
|
productFiltersPro: true,
|
|
39
40
|
productFiltersLayout: 'DEFAULT',
|
|
41
|
+
productListPaginationVariant: 'COMPACT',
|
|
40
42
|
compareVariant: 'ICON',
|
|
41
43
|
robotsAllow: false,
|
|
42
44
|
|
|
@@ -47,4 +49,7 @@ export const demoConfig: PartialDeep<GraphCommerceConfig, { recurseIntoArrays: t
|
|
|
47
49
|
configurableVariantForSimple: true,
|
|
48
50
|
configurableVariantValues: { url: true, content: true, gallery: true },
|
|
49
51
|
recentlyViewedProducts: { enabled: true, maxCount: 20 },
|
|
52
|
+
breadcrumbs: false,
|
|
53
|
+
customerDeleteEnabled: true,
|
|
54
|
+
previewSecret: 'SECRET',
|
|
50
55
|
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
ZodEnum,
|
|
18
18
|
ZodTypeAny,
|
|
19
19
|
ZodAny,
|
|
20
|
+
ZodDefault,
|
|
20
21
|
} from 'zod'
|
|
21
22
|
import diff from './diff'
|
|
22
23
|
|
|
@@ -61,6 +62,7 @@ export function configToEnvSchema(schema: ZodNode) {
|
|
|
61
62
|
if (node instanceof ZodEffects) node = node.innerType()
|
|
62
63
|
if (node instanceof ZodOptional) node = node.unwrap()
|
|
63
64
|
if (node instanceof ZodNullable) node = node.unwrap()
|
|
65
|
+
if (node instanceof ZodDefault) node = node.removeDefault()
|
|
64
66
|
|
|
65
67
|
if (node instanceof ZodObject) {
|
|
66
68
|
if (path.length > 0) {
|
|
@@ -99,7 +101,13 @@ export function configToEnvSchema(schema: ZodNode) {
|
|
|
99
101
|
return
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
if (node instanceof
|
|
104
|
+
if (node instanceof ZodNumber) {
|
|
105
|
+
envSchema[toEnvStr(path)] = z.coerce.number().optional()
|
|
106
|
+
envToDot[toEnvStr(path)] = dotNotation(path)
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (node instanceof ZodString || node instanceof ZodEnum) {
|
|
103
111
|
envSchema[toEnvStr(path)] = node.optional()
|
|
104
112
|
envToDot[toEnvStr(path)] = dotNotation(path)
|
|
105
113
|
return
|
package/src/generated/config.ts
CHANGED
|
@@ -104,6 +104,8 @@ export type DatalayerConfig = {
|
|
|
104
104
|
* Below is a list of all possible configurations that can be set by GraphCommerce.
|
|
105
105
|
*/
|
|
106
106
|
export type GraphCommerceConfig = {
|
|
107
|
+
/** Configuration for the SidebarGallery component */
|
|
108
|
+
breadcrumbs?: InputMaybe<Scalars['Boolean']['input']>;
|
|
107
109
|
/**
|
|
108
110
|
* The canonical base URL is used for SEO purposes.
|
|
109
111
|
*
|
|
@@ -157,14 +159,17 @@ export type GraphCommerceConfig = {
|
|
|
157
159
|
* Default: 'false'
|
|
158
160
|
*/
|
|
159
161
|
crossSellsRedirectItems?: InputMaybe<Scalars['Boolean']['input']>;
|
|
162
|
+
/** Enables the shipping notes field in the checkout */
|
|
163
|
+
customerAddressNoteEnable?: InputMaybe<Scalars['Boolean']['input']>;
|
|
160
164
|
/**
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* This value should match Magento 2's configuration value for
|
|
165
|
-
* `customer/create_account/confirm` and should be removed once we can query
|
|
165
|
+
* Enables company fields inside the checkout:
|
|
166
|
+
* - Company name
|
|
167
|
+
* - VAT ID
|
|
166
168
|
*/
|
|
167
|
-
|
|
169
|
+
customerCompanyFieldsEnable?: InputMaybe<Scalars['Boolean']['input']>;
|
|
170
|
+
/** Enable customer account deletion through the account section */
|
|
171
|
+
customerDeleteEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
|
172
|
+
/** Datalayer config */
|
|
168
173
|
dataLayer?: InputMaybe<DatalayerConfig>;
|
|
169
174
|
/** Debug configuration for GraphCommerce */
|
|
170
175
|
debug?: InputMaybe<GraphCommerceDebugConfig>;
|
|
@@ -275,6 +280,12 @@ export type GraphCommerceConfig = {
|
|
|
275
280
|
* - https://magento2.test/graphql
|
|
276
281
|
*/
|
|
277
282
|
magentoEndpoint: Scalars['String']['input'];
|
|
283
|
+
/**
|
|
284
|
+
* Version of the Magento backend.
|
|
285
|
+
*
|
|
286
|
+
* Values: 245, 246, 247 for Magento 2.4.5, 2.4.6, 2.4.7 respectively.
|
|
287
|
+
*/
|
|
288
|
+
magentoVersion: Scalars['Int']['input'];
|
|
278
289
|
/** To enable next.js' preview mode, configure the secret you'd like to use. */
|
|
279
290
|
previewSecret?: InputMaybe<Scalars['String']['input']>;
|
|
280
291
|
/**
|
|
@@ -285,6 +296,13 @@ export type GraphCommerceConfig = {
|
|
|
285
296
|
productFiltersLayout?: InputMaybe<ProductFiltersLayout>;
|
|
286
297
|
/** Product filters with better UI for mobile and desktop. */
|
|
287
298
|
productFiltersPro?: InputMaybe<Scalars['Boolean']['input']>;
|
|
299
|
+
/**
|
|
300
|
+
* Pagination variant for the product listings.
|
|
301
|
+
*
|
|
302
|
+
* COMPACT means: "< Page X of Y >"
|
|
303
|
+
* EXTENDED means: "< 1 2 ... 4 [5] 6 ... 10 11 >"
|
|
304
|
+
*/
|
|
305
|
+
productListPaginationVariant?: InputMaybe<PaginationVariant>;
|
|
288
306
|
/**
|
|
289
307
|
* By default we route products to /p/[url] but you can change this to /product/[url] if you wish.
|
|
290
308
|
*
|
|
@@ -345,6 +363,12 @@ export type GraphCommerceStorefrontConfig = {
|
|
|
345
363
|
canonicalBaseUrl?: InputMaybe<Scalars['String']['input']>;
|
|
346
364
|
/** Due to a limitation of the GraphQL API it is not possible to determine if a cart should be displayed including or excluding tax. */
|
|
347
365
|
cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']['input']>;
|
|
366
|
+
/**
|
|
367
|
+
* Enables company fields inside the checkout:
|
|
368
|
+
* - Company name
|
|
369
|
+
* - VAT ID
|
|
370
|
+
*/
|
|
371
|
+
customerCompanyFieldsEnable?: InputMaybe<Scalars['Boolean']['input']>;
|
|
348
372
|
/**
|
|
349
373
|
* There can only be one entry with defaultLocale set to true.
|
|
350
374
|
* - If there are more, the first one is used.
|
|
@@ -408,6 +432,10 @@ export type MagentoConfigurableVariantValues = {
|
|
|
408
432
|
url?: InputMaybe<Scalars['Boolean']['input']>;
|
|
409
433
|
};
|
|
410
434
|
|
|
435
|
+
export type PaginationVariant =
|
|
436
|
+
| 'COMPACT'
|
|
437
|
+
| 'EXTENDED';
|
|
438
|
+
|
|
411
439
|
export type ProductFiltersLayout =
|
|
412
440
|
| 'DEFAULT'
|
|
413
441
|
| 'SIDEBAR';
|
|
@@ -444,6 +472,8 @@ export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny
|
|
|
444
472
|
|
|
445
473
|
export const CompareVariantSchema = z.enum(['CHECKBOX', 'ICON']);
|
|
446
474
|
|
|
475
|
+
export const PaginationVariantSchema = z.enum(['COMPACT', 'EXTENDED']);
|
|
476
|
+
|
|
447
477
|
export const ProductFiltersLayoutSchema = z.enum(['DEFAULT', 'SIDEBAR']);
|
|
448
478
|
|
|
449
479
|
export const SidebarGalleryPaginationVariantSchema = z.enum(['DOTS', 'THUMBNAILS_BOTTOM']);
|
|
@@ -456,18 +486,21 @@ export function DatalayerConfigSchema(): z.ZodObject<Properties<DatalayerConfig>
|
|
|
456
486
|
|
|
457
487
|
export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerceConfig>> {
|
|
458
488
|
return z.object({
|
|
489
|
+
breadcrumbs: z.boolean().default(false).nullish(),
|
|
459
490
|
canonicalBaseUrl: z.string().min(1),
|
|
460
491
|
cartDisplayPricesInclTax: z.boolean().nullish(),
|
|
461
492
|
compare: z.boolean().nullish(),
|
|
462
|
-
compareVariant: CompareVariantSchema.nullish(),
|
|
463
|
-
configurableVariantForSimple: z.boolean().nullish(),
|
|
493
|
+
compareVariant: CompareVariantSchema.default("ICON").nullish(),
|
|
494
|
+
configurableVariantForSimple: z.boolean().default(false).nullish(),
|
|
464
495
|
configurableVariantValues: MagentoConfigurableVariantValuesSchema().nullish(),
|
|
465
|
-
crossSellsHideCartItems: z.boolean().nullish(),
|
|
466
|
-
crossSellsRedirectItems: z.boolean().nullish(),
|
|
467
|
-
|
|
496
|
+
crossSellsHideCartItems: z.boolean().default(false).nullish(),
|
|
497
|
+
crossSellsRedirectItems: z.boolean().default(false).nullish(),
|
|
498
|
+
customerAddressNoteEnable: z.boolean().nullish(),
|
|
499
|
+
customerCompanyFieldsEnable: z.boolean().nullish(),
|
|
500
|
+
customerDeleteEnabled: z.boolean().nullish(),
|
|
468
501
|
dataLayer: DatalayerConfigSchema().nullish(),
|
|
469
502
|
debug: GraphCommerceDebugConfigSchema().nullish(),
|
|
470
|
-
demoMode: z.boolean().nullish(),
|
|
503
|
+
demoMode: z.boolean().default(true).nullish(),
|
|
471
504
|
enableGuestCheckoutLogin: z.boolean().nullish(),
|
|
472
505
|
googleAnalyticsId: z.string().nullish(),
|
|
473
506
|
googleRecaptchaKey: z.string().nullish(),
|
|
@@ -479,9 +512,11 @@ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerc
|
|
|
479
512
|
hygraphWriteAccessToken: z.string().nullish(),
|
|
480
513
|
limitSsg: z.boolean().nullish(),
|
|
481
514
|
magentoEndpoint: z.string().min(1),
|
|
515
|
+
magentoVersion: z.number(),
|
|
482
516
|
previewSecret: z.string().nullish(),
|
|
483
|
-
productFiltersLayout: ProductFiltersLayoutSchema.nullish(),
|
|
517
|
+
productFiltersLayout: ProductFiltersLayoutSchema.default("DEFAULT").nullish(),
|
|
484
518
|
productFiltersPro: z.boolean().nullish(),
|
|
519
|
+
productListPaginationVariant: PaginationVariantSchema.default("COMPACT").nullish(),
|
|
485
520
|
productRoute: z.string().nullish(),
|
|
486
521
|
recentlyViewedProducts: RecentlyViewedProductsConfigSchema().nullish(),
|
|
487
522
|
robotsAllow: z.boolean().nullish(),
|
|
@@ -505,6 +540,7 @@ export function GraphCommerceStorefrontConfigSchema(): z.ZodObject<Properties<Gr
|
|
|
505
540
|
return z.object({
|
|
506
541
|
canonicalBaseUrl: z.string().nullish(),
|
|
507
542
|
cartDisplayPricesInclTax: z.boolean().nullish(),
|
|
543
|
+
customerCompanyFieldsEnable: z.boolean().nullish(),
|
|
508
544
|
defaultLocale: z.boolean().nullish(),
|
|
509
545
|
domain: z.string().nullish(),
|
|
510
546
|
googleAnalyticsId: z.string().nullish(),
|