@graphcommerce/next-config 8.1.0-canary.5 → 8.1.0-canary.52

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 (47) hide show
  1. package/CHANGELOG.md +163 -0
  2. package/Config.graphqls +5 -5
  3. package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +48 -2
  4. package/__tests__/config/utils/configToImportMeta.ts +0 -4
  5. package/__tests__/config/utils/mergeEnvIntoConfig.ts +15 -2
  6. package/__tests__/config/utils/rewriteLegancyEnv.ts +1 -1
  7. package/__tests__/interceptors/findPlugins.ts +144 -194
  8. package/__tests__/interceptors/generateInterceptors.ts +174 -91
  9. package/__tests__/interceptors/parseStructure.ts +50 -0
  10. package/__tests__/utils/resolveDependenciesSync.ts +4 -0
  11. package/dist/config/commands/exportConfig.js +5 -0
  12. package/dist/config/commands/generateConfig.js +5 -0
  13. package/dist/config/commands/generateIntercetors.js +9 -0
  14. package/dist/config/demoConfig.js +5 -0
  15. package/dist/config/utils/mergeEnvIntoConfig.js +8 -1
  16. package/dist/generated/config.js +17 -9
  17. package/dist/index.js +1 -0
  18. package/dist/interceptors/commands/codegenInterceptors.js +23 -0
  19. package/dist/interceptors/commands/generateIntercetors.js +9 -0
  20. package/dist/interceptors/extractExports.js +21 -18
  21. package/dist/interceptors/findOriginalSource.js +17 -1
  22. package/dist/interceptors/findPlugins.js +7 -3
  23. package/dist/interceptors/generateInterceptor.js +32 -15
  24. package/dist/interceptors/generateInterceptors.js +6 -5
  25. package/dist/interceptors/parseStructure.js +9 -1
  26. package/dist/interceptors/writeInterceptors.js +7 -7
  27. package/dist/utils/resolveDependenciesSync.js +5 -4
  28. package/dist/utils/resolveDependency.js +5 -0
  29. package/dist/withGraphCommerce.js +14 -5
  30. package/package.json +1 -1
  31. package/src/config/commands/exportConfig.ts +3 -0
  32. package/src/config/commands/generateConfig.ts +3 -0
  33. package/src/config/demoConfig.ts +5 -0
  34. package/src/config/utils/mergeEnvIntoConfig.ts +9 -1
  35. package/src/generated/config.ts +57 -19
  36. package/src/index.ts +1 -0
  37. package/src/interceptors/commands/codegenInterceptors.ts +27 -0
  38. package/src/interceptors/extractExports.ts +21 -21
  39. package/src/interceptors/findOriginalSource.ts +16 -1
  40. package/src/interceptors/findPlugins.ts +7 -3
  41. package/src/interceptors/generateInterceptor.ts +39 -15
  42. package/src/interceptors/generateInterceptors.ts +9 -6
  43. package/src/interceptors/parseStructure.ts +14 -1
  44. package/src/interceptors/writeInterceptors.ts +7 -7
  45. package/src/utils/resolveDependenciesSync.ts +11 -3
  46. package/src/utils/resolveDependency.ts +7 -0
  47. package/src/withGraphCommerce.ts +15 -6
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exportConfig = void 0;
4
+ const loadConfig_1 = require("../../config/loadConfig");
5
+ // eslint-disable-next-line @typescript-eslint/require-await
6
+ async function exportConfig() {
7
+ const conf = (0, loadConfig_1.loadConfig)(process.cwd());
8
+ }
9
+ exports.exportConfig = exportConfig;
@@ -87,9 +87,8 @@ function extractValue(node, path, optional = false) {
87
87
  case 'undefined':
88
88
  return undefined;
89
89
  default:
90
- if (optional)
91
- return exports.RUNTIME_VALUE;
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
- if (optional)
104
- return exports.RUNTIME_VALUE;
105
- throw new UnsupportedValueError('Unsupported spread operator in the Array Expression', path);
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
- if (optional)
124
- return exports.RUNTIME_VALUE;
125
- throw new UnsupportedValueError('Unsupported spread operator in the Object Expression', path);
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
- if (optional)
138
- return exports.RUNTIME_VALUE;
139
- throw new UnsupportedValueError(`Unsupported key type "${prop.key.type}" in the Object Expression`, path);
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
- if (optional)
150
- return exports.RUNTIME_VALUE;
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
- if (optional)
167
- return exports.RUNTIME_VALUE;
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(`Can not find ${plug.targetModule}#${plug.sourceExport} for plugin ${plug.sourceModule}`),
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)
@@ -17,10 +17,14 @@ function findPlugins(config, cwd = process.cwd()) {
17
17
  const debug = Boolean(config.debug?.pluginStatus);
18
18
  const errors = [];
19
19
  const plugins = [];
20
- dependencies.forEach((dependency, path) => {
21
- const files = (0, glob_1.sync)(`${dependency}/plugins/**/*.{ts,tsx}`, { dotRelative: true });
20
+ dependencies.forEach((filePath, packageName) => {
21
+ const files = (0, glob_1.sync)(`${filePath}/plugins/**/*.{ts,tsx}`);
22
22
  files.forEach((file) => {
23
- const sourceModule = file.replace(dependency, path).replace('.tsx', '').replace('.ts', '');
23
+ let sourceModule = file.replace('.tsx', '').replace('.ts', '');
24
+ if (file.startsWith(filePath))
25
+ sourceModule = `${packageName}/${sourceModule.slice(filePath.length + 1)}`;
26
+ if (packageName === '.' && !sourceModule.startsWith('.'))
27
+ sourceModule = `./${sourceModule}`;
24
28
  try {
25
29
  const ast = (0, core_1.parseFileSync)(file, { syntax: 'typescript', tsx: true });
26
30
  (0, parseStructure_1.parseStructure)(ast, config, sourceModule).forEach((result) => {
@@ -39,19 +39,19 @@ function isPluginConfig(plugin) {
39
39
  return isPluginBaseConfig(plugin);
40
40
  }
41
41
  exports.isPluginConfig = isPluginConfig;
42
- exports.SOURCE_START = '/** ❗️ Original (modified) source starts here **/';
43
- exports.SOURCE_END = '/** ❗️ Original (modified) source ends here **/';
42
+ exports.SOURCE_START = '/** Original source starts here (do not modify!): **/';
43
+ exports.SOURCE_END = '/** Original source ends here (do not modify!) **/';
44
44
  const originalSuffix = 'Original';
45
- const sourceSuffix = 'Source';
45
+ const sourceSuffix = 'Plugin';
46
46
  const interceptorSuffix = 'Interceptor';
47
47
  const disabledSuffix = 'Disabled';
48
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}`;
52
- const sourceName = (n) => `${n}${sourceSuffix}`;
52
+ const sourceName = (n) => `${n}`;
53
53
  const interceptorName = (n) => `${n}${interceptorSuffix}`;
54
- const interceptorPropsName = (n) => `${interceptorName(n)}Props`;
54
+ const interceptorPropsName = (n) => `${n}Props`;
55
55
  function moveRelativeDown(plugins) {
56
56
  return [...plugins].sort((a, b) => {
57
57
  if (a.sourceModule.startsWith('.') && !b.sourceModule.startsWith('.'))
@@ -102,7 +102,9 @@ async function generateInterceptor(interceptor, config, oldInterceptorSource) {
102
102
  .map(([base, plugins]) => {
103
103
  const duplicateInterceptors = new Set();
104
104
  let carry = originalName(base);
105
- const carryProps = [];
105
+ let carryProps = [];
106
+ const pluginSee = [];
107
+ pluginSee.push(`@see {@link file://${interceptor.sourcePathRelative}} for original source file`);
106
108
  const pluginStr = plugins
107
109
  .reverse()
108
110
  .filter((p) => {
@@ -119,46 +121,60 @@ async function generateInterceptor(interceptor, config, oldInterceptorSource) {
119
121
  .join(' wrapping ');
120
122
  if (isReplacePluginConfig(p)) {
121
123
  new RenameVisitor_1.RenameVisitor([originalName(p.targetExport)], (s) => s.replace(originalSuffix, disabledSuffix)).visitModule(ast);
122
- carryProps.push(interceptorPropsName(name(p)));
123
- result = `type ${interceptorPropsName(name(p))} = React.ComponentProps<typeof ${sourceName(name(p))}>`;
124
+ carryProps.push(`React.ComponentProps<typeof ${sourceName(name(p))}>`);
125
+ pluginSee.push(`@see {${sourceName(name(p))}} for replacement of the original source (original source not used)`);
124
126
  }
125
127
  if (isReactPluginConfig(p)) {
126
- carryProps.push(interceptorPropsName(name(p)));
128
+ const withBraces = config.pluginStatus || process.env.NODE_ENV === 'development';
127
129
  result = `
128
- type ${interceptorPropsName(name(p))} = DistributedOmit<React.ComponentProps<typeof ${sourceName(name(p))}>, 'Prev'>
129
- const ${interceptorName(name(p))} = (props: ${carryProps.join(' & ')}) => {
130
+ type ${interceptorPropsName(name(p))} = ${carryProps.join(' & ')} & OmitPrev<React.ComponentProps<typeof ${sourceName(name(p))}>, 'Prev'>
131
+
132
+ const ${interceptorName(name(p))} = (props: ${interceptorPropsName(name(p))}) => ${withBraces ? `{` : '('}
130
133
  ${config.pluginStatus ? `logOnce(\`🔌 Rendering ${base} with plugin(s): ${wrapChain} wrapping <${base}/>\`)` : ''}
131
134
 
132
135
  ${process.env.NODE_ENV === 'development'
133
136
  ? `if(!props['data-plugin'])
134
137
  logOnce('${fileName(p)} does not spread props to prev: <Prev {...props}/>. This will cause issues if multiple plugins are applied to this component.')`
135
138
  : ''}
136
- return <${sourceName(name(p))} {...props} Prev={${carry} as React.FC} />
137
- }`;
139
+ ${withBraces ? `return` : ''} <${sourceName(name(p))} {...props} Prev={${carry}} />
140
+ ${withBraces ? `}` : ')'}`;
141
+ carryProps = [interceptorPropsName(name(p))];
142
+ pluginSee.push(`@see {${sourceName(name(p))}} for source of applied plugin`);
138
143
  }
139
144
  if (isMethodPluginConfig(p)) {
140
145
  result = `const ${interceptorName(name(p))}: typeof ${carry} = (...args) => {
141
146
  ${config.pluginStatus ? `logOnce(\`🔌 Calling ${base} with plugin(s): ${wrapChain} wrapping ${base}()\`)` : ''}
142
147
  return ${sourceName(name(p))}(${carry}, ...args)
143
148
  }`;
149
+ pluginSee.push(`@see {${sourceName(name(p))}} for source of applied plugin`);
144
150
  }
145
151
  carry = p.type === 'replace' ? sourceName(name(p)) : interceptorName(name(p));
146
152
  return result;
147
153
  })
148
154
  .filter((v) => !!v)
149
155
  .join('\n');
150
- const isComponent = plugins.every((p) => isReplacePluginConfig(p) || isReactPluginConfig(p));
156
+ const isComponent = plugins.every((p) => isReactPluginConfig(p));
151
157
  if (isComponent && plugins.some((p) => isMethodPluginConfig(p))) {
152
158
  throw new Error(`Cannot mix React and Method plugins for ${base} in ${dependency}.`);
153
159
  }
160
+ const seeString = `
161
+ /**
162
+ * Here you see the 'interceptor' that is applying all the configured plugins.
163
+ *
164
+ * This file is NOT meant to be modified directly and is auto-generated if the plugins or the original source changes.
165
+ *
166
+ ${pluginSee.map((s) => `* ${s}`).join('\n')}
167
+ */`;
154
168
  if (process.env.NODE_ENV === 'development' && isComponent) {
155
169
  return `${pluginStr}
170
+ ${seeString}
156
171
  export const ${base}: typeof ${carry} = (props) => {
157
172
  return <${carry} {...props} data-plugin />
158
173
  }`;
159
174
  }
160
175
  return `
161
176
  ${pluginStr}
177
+ ${seeString}
162
178
  export const ${base} = ${carry}
163
179
  `;
164
180
  })
@@ -177,11 +193,12 @@ async function generateInterceptor(interceptor, config, oldInterceptorSource) {
177
193
  /* eslint-disable */
178
194
  /* This file is automatically generated for ${dependency} */
179
195
  ${Object.values(targetExports).some((t) => t.some((p) => p.type === 'component'))
180
- ? `import type { DistributedOmit } from 'type-fest'`
196
+ ? `import type { DistributedOmit as OmitPrev } from 'type-fest'`
181
197
  : ''}
182
198
 
183
199
  ${pluginImports}
184
200
 
201
+ /** @see {@link file://${interceptor.sourcePathRelative}} for source of original */
185
202
  ${exports.SOURCE_START}
186
203
  ${(0, swc_1.printSync)(ast).code}
187
204
  ${exports.SOURCE_END}
@@ -8,7 +8,7 @@ const node_path_1 = __importDefault(require("node:path"));
8
8
  const promises_1 = __importDefault(require("node:fs/promises"));
9
9
  const findOriginalSource_1 = require("./findOriginalSource");
10
10
  const generateInterceptor_1 = require("./generateInterceptor");
11
- async function generateInterceptors(plugins, resolve, config) {
11
+ async function generateInterceptors(plugins, resolve, config, force) {
12
12
  const byTargetModuleAndExport = (0, generateInterceptor_1.moveRelativeDown)(plugins).reduce((acc, plug) => {
13
13
  let { sourceModule: pluginPath } = plug;
14
14
  if (!(0, generateInterceptor_1.isPluginConfig)(plug) || !plug.enabled)
@@ -40,10 +40,11 @@ async function generateInterceptors(plugins, resolve, config) {
40
40
  }, {});
41
41
  return Object.fromEntries(await Promise.all(Object.entries(byTargetModuleAndExport).map(async ([target, interceptor]) => {
42
42
  const file = `${interceptor.fromRoot}.interceptor.tsx`;
43
- const originalSource = (await promises_1.default
44
- .access(file, promises_1.default.constants.F_OK)
45
- .then(() => true)
46
- .catch(() => false))
43
+ const originalSource = !force &&
44
+ (await promises_1.default
45
+ .access(file, promises_1.default.constants.F_OK)
46
+ .then(() => true)
47
+ .catch(() => false))
47
48
  ? (await promises_1.default.readFile(file)).toString()
48
49
  : undefined;
49
50
  return [
@@ -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
- return exportVals
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.push(...files);
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.includes(relativeFile)) {
29
- delete existing[existing.indexOf(relativeFile)];
28
+ if (existing.has(relativeFile)) {
29
+ existing.delete(relativeFile);
30
30
  }
31
- if (existing.includes(`./${relativeFile}`)) {
32
- delete existing[existing.indexOf(`./${relativeFile}`)];
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
  }
@@ -8,7 +8,7 @@ const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const PackagesSort_1 = require("./PackagesSort");
10
10
  const resolveCache = new Map();
11
- function resolveRecursivePackageJson(dependencyPath, dependencyStructure, root) {
11
+ function resolveRecursivePackageJson(dependencyPath, dependencyStructure, root, additionalDependencies = []) {
12
12
  const isRoot = dependencyPath === root;
13
13
  const fileName = require.resolve(node_path_1.default.join(dependencyPath, 'package.json'));
14
14
  const packageJsonFile = node_fs_1.default.readFileSync(fileName, 'utf-8').toString();
@@ -22,8 +22,9 @@ function resolveRecursivePackageJson(dependencyPath, dependencyStructure, root)
22
22
  return dependencyStructure;
23
23
  const dependencies = [
24
24
  ...new Set([
25
- ...Object.keys(packageJson.dependencies ?? {}),
26
- ...Object.keys(packageJson.devDependencies ?? {}),
25
+ ...Object.keys(packageJson.dependencies ?? []),
26
+ ...Object.keys(packageJson.devDependencies ?? []),
27
+ ...additionalDependencies,
27
28
  // ...Object.keys(packageJson.peerDependencies ?? {}),
28
29
  ].filter((name) => name.includes('graphcommerce'))),
29
30
  ];
@@ -63,7 +64,7 @@ function resolveDependenciesSync(root = process.cwd()) {
63
64
  const cached = resolveCache.get(root);
64
65
  if (cached)
65
66
  return cached;
66
- const dependencyStructure = resolveRecursivePackageJson(root, {}, root);
67
+ const dependencyStructure = resolveRecursivePackageJson(root, {}, root, process.env.PRIVATE_ADDITIONAL_DEPENDENCIES?.split(',') ?? []);
67
68
  const sorted = sortDependencies(dependencyStructure);
68
69
  resolveCache.set(root, sorted);
69
70
  return sorted;
@@ -14,6 +14,7 @@ const resolveDependency = (cwd = process.cwd()) => {
14
14
  root: '.',
15
15
  source: '',
16
16
  sourcePath: '',
17
+ sourcePathRelative: '',
17
18
  dependency,
18
19
  fromRoot: dependency,
19
20
  fromModule: dependency,
@@ -45,6 +46,9 @@ const resolveDependency = (cwd = process.cwd()) => {
45
46
  let fromModule = !relative
46
47
  ? '.'
47
48
  : `./${relative.split('/')[relative.split('/').length - 1]}`;
49
+ const sourcePathRelative = !sourcePath
50
+ ? '.'
51
+ : `./${sourcePath.split('/')[sourcePath.split('/').length - 1]}`;
48
52
  if (dependency.startsWith('./'))
49
53
  fromModule = `.${relative}`;
50
54
  dependencyPaths = {
@@ -55,6 +59,7 @@ const resolveDependency = (cwd = process.cwd()) => {
55
59
  fromModule,
56
60
  source,
57
61
  sourcePath,
62
+ sourcePathRelative,
58
63
  };
59
64
  }
60
65
  });
@@ -94,15 +94,26 @@ function withGraphCommerce(nextConfig, cwd) {
94
94
  },
95
95
  transpilePackages,
96
96
  webpack: (config, options) => {
97
- // Allow importing yml/yaml files for graphql-mesh
98
- config.module?.rules?.push({ test: /\.ya?ml$/, use: 'js-yaml-loader' });
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.
102
113
  config.plugins.push(new webpack_1.DefinePlugin(importMetaPaths));
103
114
  // To properly properly treeshake @apollo/client we need to define the __DEV__ property
115
+ config.plugins.push(new webpack_1.DefinePlugin({ 'globalThis.__DEV__': options.dev }));
104
116
  if (!options.isServer) {
105
- config.plugins.push(new webpack_1.DefinePlugin({ __DEV__: options.dev }));
106
117
  if (graphcommerceConfig.debug?.webpackCircularDependencyPlugin) {
107
118
  config.plugins.push(new circular_dependency_plugin_1.default({
108
119
  exclude: /readable-stream|duplexer2|node_modules\/next/,
@@ -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": "8.1.0-canary.5",
5
+ "version": "8.1.0-canary.52",
6
6
  "type": "commonjs",
7
7
  "main": "dist/index.js",
8
8
  "types": "src/index.ts",
@@ -1,5 +1,8 @@
1
1
  import { loadConfig } from '../loadConfig'
2
2
  import { exportConfigToEnv } from '../utils/exportConfigToEnv'
3
+ import dotenv from 'dotenv'
4
+
5
+ dotenv.config()
3
6
 
4
7
  // eslint-disable-next-line @typescript-eslint/require-await
5
8
  export async function exportConfig() {
@@ -2,10 +2,13 @@ import { writeFileSync } from 'fs'
2
2
  // eslint-disable-next-line import/no-extraneous-dependencies
3
3
  import { generate } from '@graphql-codegen/cli'
4
4
  import { transformFileSync } from '@swc/core'
5
+ import dotenv from 'dotenv'
5
6
  import { isMonorepo } from '../../utils/isMonorepo'
6
7
  import { resolveDependenciesSync } from '../../utils/resolveDependenciesSync'
7
8
  import { resolveDependency } from '../../utils/resolveDependency'
8
9
 
10
+ dotenv.config()
11
+
9
12
  const packages = [...resolveDependenciesSync().values()].filter((p) => p !== '.')
10
13
 
11
14
  const resolve = resolveDependency()
@@ -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 ZodString || node instanceof ZodNumber || node instanceof ZodEnum) {
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