@graphcommerce/next-config 5.2.0-canary.9 → 6.0.0-canary.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +4 -9
  2. package/dist/config/generateConfig.js +49 -0
  3. package/dist/config/index.js +18 -0
  4. package/dist/config/loadConfig.js +48 -0
  5. package/dist/config/utils/configToImportMeta.js +34 -0
  6. package/dist/config/utils/diff.js +33 -0
  7. package/dist/config/utils/mergeEnvIntoConfig.js +175 -0
  8. package/dist/config/utils/rewriteLegacyEnv.js +110 -0
  9. package/dist/generated/config.js +56 -0
  10. package/dist/index.js +2 -10
  11. package/dist/interceptors/InterceptorPlugin.js +4 -3
  12. package/dist/interceptors/findPlugins.js +64 -35
  13. package/dist/interceptors/generateInterceptors.js +2 -2
  14. package/dist/interceptors/writeInterceptors.js +1 -0
  15. package/dist/utils/resolveDependency.js +5 -1
  16. package/dist/withGraphCommerce.js +85 -19
  17. package/package.json +13 -6
  18. package/src/config/generateConfig.ts +52 -0
  19. package/src/config/index.ts +13 -0
  20. package/src/config/loadConfig.ts +40 -0
  21. package/src/config/utils/configToImportMeta.ts +36 -0
  22. package/src/config/utils/diff.ts +39 -0
  23. package/src/config/utils/mergeEnvIntoConfig.ts +228 -0
  24. package/src/config/utils/rewriteLegacyEnv.ts +121 -0
  25. package/src/generated/config.ts +255 -0
  26. package/src/index.ts +2 -10
  27. package/src/interceptors/InterceptorPlugin.ts +4 -3
  28. package/src/interceptors/findPlugins.ts +73 -36
  29. package/src/interceptors/generateInterceptors.ts +4 -3
  30. package/src/interceptors/writeInterceptors.ts +1 -0
  31. package/src/utils/resolveDependency.ts +5 -1
  32. package/src/withGraphCommerce.ts +102 -30
  33. package/dist/index.d.ts +0 -10
  34. package/dist/interceptors/InterceptorPlugin.d.ts +0 -8
  35. package/dist/interceptors/findPlugins.d.ts +0 -2
  36. package/dist/interceptors/generateInterceptors.d.ts +0 -19
  37. package/dist/interceptors/writeInterceptors.d.ts +0 -2
  38. package/dist/utils/PackagesSort.d.ts +0 -3
  39. package/dist/utils/TopologicalSort.d.ts +0 -16
  40. package/dist/utils/isMonorepo.d.ts +0 -1
  41. package/dist/utils/resolveDependenciesSync.d.ts +0 -22
  42. package/dist/utils/resolveDependency.d.ts +0 -9
  43. package/dist/withGraphCommerce.d.ts +0 -6
@@ -0,0 +1,228 @@
1
+ /* eslint-disable import/no-extraneous-dependencies */
2
+ import { mergeDeep, cloneDeep } from '@apollo/client/utilities'
3
+ import chalk from 'chalk'
4
+ import { get, set } from 'lodash'
5
+ import snakeCase from 'lodash/snakeCase'
6
+ import {
7
+ z,
8
+ ZodObject,
9
+ ZodBoolean,
10
+ ZodArray,
11
+ ZodString,
12
+ ZodNumber,
13
+ ZodNullable,
14
+ ZodOptional,
15
+ ZodEffects,
16
+ ZodRawShape,
17
+ ZodEnum,
18
+ } from 'zod'
19
+ import diff from './diff'
20
+
21
+ const fmt = (s: string) => s.split(/(\d+)/).map(snakeCase).join('')
22
+ const pathStr = (path: string[]) => ['GC', ...path].map(fmt).join('_').toUpperCase()
23
+ const dotNotation = (pathParts: string[]) =>
24
+ pathParts
25
+ .map((v) => {
26
+ const idx = Number(v)
27
+ return !Number.isNaN(idx) ? `[${idx}]` : v
28
+ })
29
+ .join('.')
30
+
31
+ function isJSON(str: string | undefined): boolean {
32
+ if (!str) return true
33
+ try {
34
+ JSON.parse(str)
35
+ } catch (e) {
36
+ return false
37
+ }
38
+ return true
39
+ }
40
+
41
+ export type ZodNode =
42
+ | ZodNullable<any>
43
+ | ZodOptional<any>
44
+ | ZodEffects<any>
45
+ | ZodObject<any>
46
+ | ZodArray<any>
47
+ | ZodString
48
+ | ZodNumber
49
+ | ZodBoolean
50
+
51
+ export function configToEnvSchema(schema: ZodNode) {
52
+ const envSchema: ZodRawShape = {}
53
+ const envToDot: Record<string, string> = {}
54
+
55
+ function walk(incomming: ZodNode, path: string[] = []) {
56
+ let node = incomming
57
+
58
+ if (node instanceof ZodEffects) node = node.innerType()
59
+ if (node instanceof ZodOptional) node = node.unwrap()
60
+ if (node instanceof ZodNullable) node = node.unwrap()
61
+
62
+ if (node instanceof ZodObject) {
63
+ if (path.length > 0) {
64
+ envSchema[pathStr(path)] = z
65
+ .string()
66
+ .optional()
67
+ .refine(isJSON, { message: `Invalid JSON` })
68
+ .transform((val) => (val ? JSON.parse(val) : val))
69
+ envToDot[pathStr(path)] = dotNotation(path)
70
+ }
71
+
72
+ const typeNode = node as unknown as ZodObject<ZodRawShape>
73
+
74
+ Object.keys(typeNode.shape).forEach((key) => {
75
+ walk(typeNode.shape[key], [...path, key])
76
+ })
77
+
78
+ return
79
+ }
80
+
81
+ if (node instanceof ZodArray) {
82
+ const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
83
+ if (path.length > 0) {
84
+ envSchema[pathStr(path)] = z
85
+ .string()
86
+ .optional()
87
+ .refine(isJSON, { message: `Invalid JSON` })
88
+ .transform((val) => (val ? JSON.parse(val) : val))
89
+ envToDot[pathStr(path)] = dotNotation(path)
90
+ }
91
+
92
+ arr.forEach((key) => {
93
+ walk((node as unknown as ZodArray<ZodNode>).element, [...path, String(key)])
94
+ })
95
+
96
+ return
97
+ }
98
+
99
+ if (node instanceof ZodString || node instanceof ZodNumber || node instanceof ZodEnum) {
100
+ envSchema[pathStr(path)] = node.optional()
101
+ envToDot[pathStr(path)] = dotNotation(path)
102
+ return
103
+ }
104
+
105
+ if (node instanceof ZodBoolean) {
106
+ envSchema[pathStr(path)] = z
107
+ .enum(['true', '1', 'false', '0'])
108
+ .optional()
109
+ .transform((v) => {
110
+ if (v === 'true' || v === '1') return true
111
+ if (v === 'false' || v === '0') return false
112
+ return v
113
+ })
114
+ envToDot[pathStr(path)] = dotNotation(path)
115
+ return
116
+ }
117
+
118
+ throw Error(
119
+ `[@graphcommerce/next-config] Unknown type in schema ${node.constructor.name}. This is probably a bug please create an issue.`,
120
+ )
121
+ }
122
+ walk(schema)
123
+
124
+ return [z.object(envSchema), envToDot] as const
125
+ }
126
+
127
+ export type ApplyResultItem = {
128
+ envVar: string
129
+ envValue: unknown
130
+ dotVar?: string | undefined
131
+ from?: unknown
132
+ to?: unknown
133
+ error?: string[]
134
+ warning?: string[]
135
+ }
136
+ export type ApplyResult = ApplyResultItem[]
137
+
138
+ export function mergeEnvIntoConfig(
139
+ schema: ZodNode,
140
+ config: Record<string, unknown>,
141
+ env: Record<string, string | undefined>,
142
+ ) {
143
+ const filterEnv = Object.fromEntries(Object.entries(env).filter(([key]) => key.startsWith('GC_')))
144
+
145
+ const newConfig = cloneDeep(config)
146
+ const [envSchema, envToDot] = configToEnvSchema(schema)
147
+ const result = envSchema.safeParse(filterEnv)
148
+
149
+ const applyResult: ApplyResult = []
150
+
151
+ if (!result.success) {
152
+ Object.entries(result.error.flatten().fieldErrors).forEach(([envVar, error]) => {
153
+ const dotVar = envToDot[envVar]
154
+ const envValue = filterEnv[envVar]
155
+ applyResult.push({ envVar, envValue, dotVar, error })
156
+ })
157
+ return [undefined, applyResult] as const
158
+ }
159
+
160
+ Object.entries(result.data).forEach(([envVar, value]) => {
161
+ const dotVar = envToDot[envVar]
162
+ const envValue = filterEnv[envVar]
163
+
164
+ if (!dotVar) {
165
+ applyResult.push({ envVar, envValue })
166
+ return
167
+ }
168
+
169
+ const dotValue = get(newConfig, dotVar)
170
+ const merged = mergeDeep(dotValue, value)
171
+
172
+ const from = diff(merged, dotValue)
173
+ const to = diff(dotValue, merged)
174
+
175
+ applyResult.push({ envVar, envValue, dotVar, from, to })
176
+ set(newConfig, dotVar, merged)
177
+ })
178
+
179
+ return [newConfig, applyResult] as const
180
+ }
181
+
182
+ /**
183
+ * Prints the applied env variables to the console
184
+ *
185
+ * The format is:
186
+ *
187
+ * - If from and to is empty, the value is unchanged: `=` (white)
188
+ * - If the from is empty, a new value is applied: `+` (green)
189
+ * - If the to is empty, a value is removed: `-` (red)
190
+ * - If both from and to is not empty, a value is changed: `~` (yellow)
191
+ */
192
+ export function formatAppliedEnv(applyResult: ApplyResult) {
193
+ let hasError = false
194
+ let hasWarning = false
195
+ const lines = applyResult.map(({ from, to, envValue, envVar, dotVar, error, warning }) => {
196
+ const fromFmt = chalk.red(JSON.stringify(from))
197
+ const toFmt = chalk.green(JSON.stringify(to))
198
+ const envVariableFmt = `${envVar}='${envValue}'`
199
+ const dotVariableFmt = chalk.bold.underline(`${dotVar}`)
200
+
201
+ const baseLog = `${envVariableFmt} => ${dotVariableFmt}`
202
+
203
+ if (error) {
204
+ hasError = true
205
+ return `${chalk.red(` ⨉ ${envVariableFmt}`)} => ${error.join(', ')}`
206
+ }
207
+ if (warning) {
208
+ hasWarning = true
209
+ return `${chalk.yellowBright(` ‼ ${envVariableFmt}`)} => ${warning.join(', ')}`
210
+ }
211
+
212
+ if (!dotVar) return chalk.red(`${envVariableFmt} => ignored (no matching config)`)
213
+
214
+ if (from === undefined && to === undefined)
215
+ return ` = ${baseLog}: (ignored, no change/wrong format)`
216
+ if (from === undefined && to !== undefined) return ` ${chalk.green('+')} ${baseLog}: ${toFmt}`
217
+ if (from !== undefined && to === undefined) return ` ${chalk.red('-')} ${baseLog}: ${fromFmt}`
218
+ return ` ${chalk.yellowBright('~')} ${baseLog}: ${fromFmt} => ${toFmt}`
219
+ })
220
+
221
+ let header = chalk.blueBright(`info`)
222
+ if (hasWarning) header = chalk.yellowBright(`warning`)
223
+ if (hasError) header = chalk.yellowBright(`error`)
224
+
225
+ header += ` - Loaded GraphCommerce env variables`
226
+
227
+ return [header, ...lines].join('\n')
228
+ }
@@ -0,0 +1,121 @@
1
+ import cloneDeep from 'lodash/cloneDeep'
2
+ import { GraphCommerceConfig } from '../../generated/config'
3
+ import { ApplyResult, mergeEnvIntoConfig, ZodNode } from './mergeEnvIntoConfig'
4
+
5
+ export function rewriteLegacyEnv(
6
+ schema: ZodNode,
7
+ config: GraphCommerceConfig,
8
+ env: Record<string, string | undefined>,
9
+ ) {
10
+ const clonedEnv: Record<string, string | undefined> = cloneDeep(env)
11
+ const applied: ApplyResult = []
12
+
13
+ function renamedTo(to: string) {
14
+ return (envVar: string, envValue: string) => {
15
+ applied.push({
16
+ warning: [`should be renamed to ${to}='${envValue}'`],
17
+ envVar,
18
+ envValue,
19
+ })
20
+ clonedEnv[to] = envValue
21
+ }
22
+ }
23
+
24
+ function notUsed() {
25
+ return (envVar: string, envValue: string) => {
26
+ applied.push({
27
+ warning: [`should be removed`],
28
+ envVar,
29
+ envValue,
30
+ })
31
+ }
32
+ }
33
+
34
+ const parsers: Record<string, (key: string, value: string) => void> = {
35
+ MAGENTO_ENDPPOINT: renamedTo('GC_MAGENTO_ENDPOINT'),
36
+ GRAPHCMS_URL: renamedTo('GC_HYGRAPH_ENDPOINT'),
37
+ NEXT_PUBLIC_GRAPHQL_ENDPOINT: notUsed(),
38
+ IMAGE_DOMAINS: (envVar: string, envValue: string) => {
39
+ applied.push({
40
+ warning: [
41
+ `should be removed: will automatically add the Magento/Hygraph URL. For more advanced configurations, see: https://nextjs.org/docs/api-reference/next/image#configuration-options`,
42
+ ],
43
+ envVar,
44
+ envValue,
45
+ })
46
+ },
47
+ NEXT_PUBLIC_LOCALE_STORES: (envVar: string, envValue: string) => {
48
+ const parsed = JSON.parse(envValue) as Record<string, string>
49
+
50
+ applied.push({
51
+ warning: ['env variable is is modified, rewritten to GC_I18N.'],
52
+ envVar,
53
+ envValue,
54
+ })
55
+
56
+ clonedEnv.GC_I18N = JSON.stringify(
57
+ Object.entries(parsed).map(([locale, magentoStoreCode], index) => {
58
+ config.i18n[index] = { ...config.i18n[index], locale, magentoStoreCode }
59
+ return { locale, magentoStoreCode }
60
+ }),
61
+ )
62
+ },
63
+ NEXT_PUBLIC_SITE_URL: renamedTo('GC_CANONICAL_BASE_URL'),
64
+ NEXT_PUBLIC_GTM_ID: renamedTo('GC_GOOGLE_TAGMANAGER_ID'),
65
+ NEXT_PUBLIC_GOOGLE_ANALYTICS: (envVar: string, envValue: string) => {
66
+ if (envValue.startsWith('{')) {
67
+ const parsed = JSON.parse(envValue) as Record<string, string>
68
+
69
+ clonedEnv.GC_GOOGLE_ANALYTICS_ID = 'enabled'
70
+ config.i18n.forEach((i18n, index) => {
71
+ if (parsed[i18n.locale]) {
72
+ clonedEnv[`GC_I18N_${index}_GOOGLE_ANALYTICS_ID`] = parsed[i18n.locale]
73
+ }
74
+ })
75
+
76
+ applied.push({
77
+ warning: ['should be rewritten to GC_I18N_*_GOOGLE_ANALYTICS_ID'],
78
+ envVar,
79
+ envValue,
80
+ })
81
+
82
+ return
83
+ }
84
+ renamedTo('GC_GOOGLE_ANALYTICS_ID')
85
+ },
86
+ NEXT_PUBLIC_GOOGLE_RECAPTCHA_V3_SITE_KEY: renamedTo('GC_GOOGLE_RECAPTCHA_KEY'),
87
+ NEXT_PUBLIC_DISPLAY_INCL_TAX: (envVar: string, envValue: string) => {
88
+ const inclTax = envValue.split(',').map((i) => i.trim())
89
+
90
+ config.i18n.forEach((i18n, index) => {
91
+ if (!inclTax.includes(i18n.locale)) return null
92
+ clonedEnv[`GC_I18N_${index}_CART_DISPLAY_PRICES_INCL_TAX`] = '1'
93
+ })
94
+
95
+ applied.push({
96
+ warning: ['env variable is renamed, move to configuration: cartDisplayPricesInclTax'],
97
+ envVar,
98
+ envValue,
99
+ })
100
+ clonedEnv.GC_DISPLAY_PRICES_INCL_TAX = envValue
101
+ },
102
+ PREVIEW_SECRET: renamedTo('GC_PREVIEW_SECRET'),
103
+ DEMO_MAGENTO_GRAPHCOMMERCE: renamedTo('GC_DEMO_MODE'),
104
+ }
105
+
106
+ if (env.SKIP_MIGRATION === '1' || env.SKIP_MIGRATION === 'true') {
107
+ return mergeEnvIntoConfig(schema, config, clonedEnv)
108
+ }
109
+
110
+ Object.entries(env).forEach(([key, value]) => {
111
+ if (value === undefined) return
112
+ try {
113
+ parsers[key]?.(key, value)
114
+ } catch (e) {
115
+ console.error(`Error parsing ${key}`, e)
116
+ }
117
+ })
118
+
119
+ const [newConfig, envApplied] = mergeEnvIntoConfig(schema, config, clonedEnv)
120
+ return [newConfig, [...applied, ...envApplied] as ApplyResult] as const
121
+ }
@@ -0,0 +1,255 @@
1
+ /* eslint-disable */
2
+ import { z } from 'zod'
3
+ export type Maybe<T> = T | null;
4
+ export type InputMaybe<T> = Maybe<T>;
5
+ export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
6
+ export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
7
+ export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
8
+ /** All built-in and custom scalars, mapped to their actual values */
9
+ export type Scalars = {
10
+ ID: string;
11
+ String: string;
12
+ Boolean: boolean;
13
+ Int: number;
14
+ Float: number;
15
+ };
16
+
17
+ export type DeployEnvironment =
18
+ /** The development environment */
19
+ | 'development'
20
+ /** The staging environment */
21
+ | 'preview'
22
+ /** The production environment */
23
+ | 'production';
24
+
25
+ /** Global GraphCommerce configuration can be configured in your `graphcommerce.config.js` file in the root of your project. */
26
+ export type GraphCommerceConfig = {
27
+ /**
28
+ * The canonical base URL is used for SEO purposes.
29
+ *
30
+ * Examples:
31
+ * - https://example.com
32
+ * - https://example.com/en
33
+ * - https://example.com/en-US
34
+ */
35
+ canonicalBaseUrl: Scalars['String'];
36
+ /**
37
+ * Due to a limitation of the GraphQL API it is not possible to determine if a cart should be displayed including or excluding tax.
38
+ *
39
+ * When Magento's StoreConfig adds this value, this can be replaced.
40
+ */
41
+ cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']>;
42
+ /**
43
+ * Due to a limitation in the GraphQL API of Magento 2, we need to know if the
44
+ * customer requires email confirmation.
45
+ *
46
+ * This value should match Magento 2's configuration value for
47
+ * `customer/create_account/confirm` and should be removed once we can query
48
+ */
49
+ customerRequireEmailConfirmation?: InputMaybe<Scalars['Boolean']>;
50
+ /** Debug configuration for GraphCommerce */
51
+ debug?: InputMaybe<GraphCommerceDebugConfig>;
52
+ /**
53
+ * Enables some demo specific code that is probably not useful for a project:
54
+ *
55
+ * - Adds the "BY GC" to the product list items.
56
+ * - Adds "dominant_color" attribute swatches to the product list items.
57
+ * - Creates a big list items in the product list.
58
+ */
59
+ demoMode?: InputMaybe<Scalars['Boolean']>;
60
+ /**
61
+ * Environment GraphCommerce is deployed to.
62
+ *
63
+ * Not to be confused with NODE_ENV: which will always be 'production' when running `next build`.
64
+ */
65
+ deployEnvironment?: InputMaybe<DeployEnvironment>;
66
+ /**
67
+ * See https://support.google.com/analytics/answer/9539598?hl=en
68
+ *
69
+ * Provide a value to enable Google Analytics for your store.
70
+ *
71
+ * To enable only for a specific locale, override the value in the i18n config.
72
+ */
73
+ googleAnalyticsId?: InputMaybe<Scalars['String']>;
74
+ /**
75
+ * Google reCAPTCHA key, get from https://developers.google.com/recaptcha/docs/v3
76
+ *
77
+ * This value is required even if you are configuring different values for each locale.
78
+ */
79
+ googleRecaptchaKey?: InputMaybe<Scalars['String']>;
80
+ /**
81
+ * The Google Tagmanager ID to be used on the site.
82
+ *
83
+ * This value is required even if you are configuring different values for each locale.
84
+ */
85
+ googleTagmanagerId?: InputMaybe<Scalars['String']>;
86
+ /**
87
+ * The HyGraph endpoint.
88
+ *
89
+ * Project settings -> API Access -> High Performance Read-only Content API
90
+ */
91
+ hygraphEndpoint: Scalars['String'];
92
+ /** All i18n configuration for the project */
93
+ i18n: Array<GraphCommerceI18nConfig>;
94
+ /**
95
+ * GraphQL Magento endpoint.
96
+ *
97
+ * Examples:
98
+ * - https://magento2.test/graphql
99
+ */
100
+ magentoEndpoint: Scalars['String'];
101
+ /** To enable next.js' preview mode, configure the secret you'd like to use. */
102
+ previewSecret?: InputMaybe<Scalars['String']>;
103
+ /**
104
+ * Product filters with better UI for mobile and desktop.
105
+ *
106
+ * @experimental This is an experimental feature and may change in the future.
107
+ */
108
+ productFiltersPro: Scalars['Boolean'];
109
+ /**
110
+ * Allow the site to be indexed by search engines.
111
+ * If false, the robots.txt file will be set to disallow all.
112
+ */
113
+ robotsAllow: Scalars['Boolean'];
114
+ /**
115
+ * On older versions of GraphCommerce products would use a product type specific route.
116
+ *
117
+ * This should only be set to false if you use the /product/[url] or /product/configurable/[url] routes.
118
+ */
119
+ singleProductRoute: Scalars['Boolean'];
120
+ /** Hide the wishlist functionality for guests. */
121
+ wishlistHideForGuests?: InputMaybe<Scalars['Boolean']>;
122
+ /** Ignores wether a product is already in the wishlist, makes the toggle an add only. */
123
+ wishlistIgnoreProductWishlistStatus?: InputMaybe<Scalars['Boolean']>;
124
+ };
125
+
126
+ /** Debug configuration for GraphCommerce */
127
+ export type GraphCommerceDebugConfig = {
128
+ /** Reports which plugins are enabled or disabled. */
129
+ pluginStatus?: InputMaybe<Scalars['Boolean']>;
130
+ /**
131
+ * Cyclic dependencies can cause memory issues and other strange bugs.
132
+ * This plugin will warn you when it detects a cyclic dependency.
133
+ *
134
+ * When running into memory issues, it can be useful to enable this plugin.
135
+ */
136
+ webpackCircularDependencyPlugin?: InputMaybe<Scalars['Boolean']>;
137
+ /**
138
+ * When updating packages it can happen that the same package is included with different versions in the same project.
139
+ *
140
+ * Issues that this can cause are:
141
+ * - The same package is included multiple times in the bundle, increasing the bundle size.
142
+ * - The Typescript types of the package are not compatible with each other, causing Typescript errors.
143
+ */
144
+ webpackDuplicatesPlugin?: InputMaybe<Scalars['Boolean']>;
145
+ };
146
+
147
+ /** All i18n configuration for the project */
148
+ export type GraphCommerceI18nConfig = {
149
+ /**
150
+ * The canonical base URL is used for SEO purposes.
151
+ *
152
+ * Examples:
153
+ * - https://example.com
154
+ * - https://example.com/en
155
+ * - https://example.com/en-US
156
+ */
157
+ canonicalBaseUrl?: InputMaybe<Scalars['String']>;
158
+ /** Due to a limitation of the GraphQL API it is not possible to determine if a cart should be displayed including or excluding tax. */
159
+ cartDisplayPricesInclTax?: InputMaybe<Scalars['Boolean']>;
160
+ /**
161
+ * There can only be one entry with defaultLocale set to true.
162
+ * - If there are more, the first one is used.
163
+ * - If there is none, the first entry is used.
164
+ */
165
+ defaultLocale?: InputMaybe<Scalars['Boolean']>;
166
+ /** Domain configuration, must be a domain https://tools.ietf.org/html/rfc3986 */
167
+ domain?: InputMaybe<Scalars['String']>;
168
+ /**
169
+ * Configure different Google Analytics IDs for different locales.
170
+ *
171
+ * To disable for a specific locale, set the value to null.
172
+ */
173
+ googleAnalyticsId?: InputMaybe<Scalars['String']>;
174
+ /** Locale specific google reCAPTCHA key. */
175
+ googleRecaptchaKey?: InputMaybe<Scalars['String']>;
176
+ /** The Google Tagmanager ID to be used per locale. */
177
+ googleTagmanagerId?: InputMaybe<Scalars['String']>;
178
+ /** Add a gcms-locales header to make sure queries return in a certain language, can be an array to define fallbacks. */
179
+ hygraphLocales?: InputMaybe<Array<Scalars['String']>>;
180
+ /** Specify a custom locale for to load translations. */
181
+ linguiLocale?: InputMaybe<Scalars['String']>;
182
+ /** Must be a locale string https://www.unicode.org/reports/tr35/tr35-59/tr35.html#Identifiers */
183
+ locale: Scalars['String'];
184
+ /**
185
+ * Magento store code.
186
+ *
187
+ * Stores => All Stores => [Store View] => Store View Code
188
+ *
189
+ * Examples:
190
+ * - default
191
+ * - en-us
192
+ * - b2b-us
193
+ */
194
+ magentoStoreCode: Scalars['String'];
195
+ };
196
+
197
+
198
+ type Properties<T> = Required<{
199
+ [K in keyof T]: z.ZodType<T[K], any, T[K]>;
200
+ }>;
201
+
202
+ type definedNonNullAny = {};
203
+
204
+ export const isDefinedNonNullAny = (v: any): v is definedNonNullAny => v !== undefined && v !== null;
205
+
206
+ export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny(v));
207
+
208
+ export const DeployEnvironmentSchema = z.enum(['development', 'preview', 'production']);
209
+
210
+ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerceConfig>> {
211
+ return z.object<Properties<GraphCommerceConfig>>({
212
+ canonicalBaseUrl: z.string().min(1),
213
+ cartDisplayPricesInclTax: z.boolean().nullish(),
214
+ customerRequireEmailConfirmation: z.boolean().nullish(),
215
+ debug: GraphCommerceDebugConfigSchema().nullish(),
216
+ demoMode: z.boolean().nullish(),
217
+ deployEnvironment: DeployEnvironmentSchema.nullish(),
218
+ googleAnalyticsId: z.string().nullish(),
219
+ googleRecaptchaKey: z.string().nullish(),
220
+ googleTagmanagerId: z.string().nullish(),
221
+ hygraphEndpoint: z.string().min(1),
222
+ i18n: z.array(GraphCommerceI18nConfigSchema()),
223
+ magentoEndpoint: z.string().min(1),
224
+ previewSecret: z.string().nullish(),
225
+ productFiltersPro: z.boolean(),
226
+ robotsAllow: z.boolean(),
227
+ singleProductRoute: z.boolean(),
228
+ wishlistHideForGuests: z.boolean().nullish(),
229
+ wishlistIgnoreProductWishlistStatus: z.boolean().nullish()
230
+ })
231
+ }
232
+
233
+ export function GraphCommerceDebugConfigSchema(): z.ZodObject<Properties<GraphCommerceDebugConfig>> {
234
+ return z.object<Properties<GraphCommerceDebugConfig>>({
235
+ pluginStatus: z.boolean().nullish(),
236
+ webpackCircularDependencyPlugin: z.boolean().nullish(),
237
+ webpackDuplicatesPlugin: z.boolean().nullish()
238
+ })
239
+ }
240
+
241
+ export function GraphCommerceI18nConfigSchema(): z.ZodObject<Properties<GraphCommerceI18nConfig>> {
242
+ return z.object<Properties<GraphCommerceI18nConfig>>({
243
+ canonicalBaseUrl: z.string().nullish(),
244
+ cartDisplayPricesInclTax: z.boolean().nullish(),
245
+ defaultLocale: z.boolean().nullish(),
246
+ domain: z.string().nullish(),
247
+ googleAnalyticsId: z.string().nullish(),
248
+ googleRecaptchaKey: z.string().nullish(),
249
+ googleTagmanagerId: z.string().nullish(),
250
+ hygraphLocales: z.array(z.string().min(1)).nullish(),
251
+ linguiLocale: z.string().nullish(),
252
+ locale: z.string().min(1),
253
+ magentoStoreCode: z.string().min(1)
254
+ })
255
+ }
package/src/index.ts CHANGED
@@ -1,18 +1,10 @@
1
- import { NextConfig } from 'next/dist/server/config-shared'
2
1
  import type React from 'react'
3
- import { withGraphCommerce } from './withGraphCommerce'
4
2
 
5
3
  export * from './utils/isMonorepo'
6
4
  export * from './utils/resolveDependenciesSync'
7
5
  export * from './withGraphCommerce'
8
-
9
- export function withYarn1Workspaces(packages: string[] = []): (config: NextConfig) => NextConfig {
10
- return withGraphCommerce({ packages })
11
- }
12
-
13
- export function withYarn1Scopes(packages?: string[]): (config: NextConfig) => NextConfig {
14
- return withGraphCommerce({ packages })
15
- }
6
+ export * from './generated/config'
7
+ export * from './config'
16
8
 
17
9
  export type PluginProps<P extends Record<string, unknown> = Record<string, unknown>> = P & {
18
10
  Prev: React.FC<P>
@@ -1,5 +1,6 @@
1
1
  import path from 'path'
2
2
  import { Compiler } from 'webpack'
3
+ import { GraphCommerceConfig } from '../generated/config'
3
4
  import { ResolveDependency, resolveDependency } from '../utils/resolveDependency'
4
5
  import { findPlugins } from './findPlugins'
5
6
  import { generateInterceptors, GenerateInterceptorsReturn } from './generateInterceptors'
@@ -12,10 +13,10 @@ export class InterceptorPlugin {
12
13
 
13
14
  private resolveDependency: ResolveDependency
14
15
 
15
- constructor() {
16
+ constructor(private config: GraphCommerceConfig) {
16
17
  this.resolveDependency = resolveDependency()
17
18
 
18
- this.interceptors = generateInterceptors(findPlugins(), this.resolveDependency)
19
+ this.interceptors = generateInterceptors(findPlugins(this.config), this.resolveDependency)
19
20
  this.interceptorByDepependency = Object.fromEntries(
20
21
  Object.values(this.interceptors).map((i) => [i.dependency, i]),
21
22
  )
@@ -28,7 +29,7 @@ export class InterceptorPlugin {
28
29
 
29
30
  // After the compilation has succeeded we watch all possible plugin locations.
30
31
  compiler.hooks.afterCompile.tap('InterceptorPlugin', (compilation) => {
31
- const plugins = findPlugins()
32
+ const plugins = findPlugins(this.config)
32
33
 
33
34
  plugins.forEach((p) => {
34
35
  const absoluteFilePath = `${path.join(