@graphcommerce/next-config 8.1.0-canary.5 → 8.1.0-canary.50
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 +159 -0
- package/Config.graphqls +5 -5
- 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 +144 -194
- package/__tests__/interceptors/generateInterceptors.ts +174 -91
- package/__tests__/interceptors/parseStructure.ts +50 -0
- package/__tests__/utils/resolveDependenciesSync.ts +4 -0
- package/dist/config/commands/exportConfig.js +5 -0
- package/dist/config/commands/generateConfig.js +5 -0
- package/dist/config/commands/generateIntercetors.js +9 -0
- package/dist/config/demoConfig.js +5 -0
- package/dist/config/utils/mergeEnvIntoConfig.js +8 -1
- package/dist/generated/config.js +17 -9
- package/dist/index.js +1 -0
- package/dist/interceptors/commands/codegenInterceptors.js +23 -0
- package/dist/interceptors/commands/generateIntercetors.js +9 -0
- package/dist/interceptors/extractExports.js +21 -18
- package/dist/interceptors/findOriginalSource.js +17 -1
- package/dist/interceptors/findPlugins.js +7 -3
- package/dist/interceptors/generateInterceptor.js +32 -15
- package/dist/interceptors/generateInterceptors.js +6 -5
- package/dist/interceptors/parseStructure.js +9 -1
- package/dist/interceptors/writeInterceptors.js +7 -7
- package/dist/utils/resolveDependenciesSync.js +5 -4
- package/dist/utils/resolveDependency.js +5 -0
- package/dist/withGraphCommerce.js +14 -5
- package/package.json +1 -1
- package/src/config/commands/exportConfig.ts +3 -0
- package/src/config/commands/generateConfig.ts +3 -0
- package/src/config/demoConfig.ts +5 -0
- package/src/config/utils/mergeEnvIntoConfig.ts +9 -1
- package/src/generated/config.ts +57 -19
- package/src/index.ts +1 -0
- package/src/interceptors/commands/codegenInterceptors.ts +27 -0
- package/src/interceptors/extractExports.ts +21 -21
- package/src/interceptors/findOriginalSource.ts +16 -1
- package/src/interceptors/findPlugins.ts +7 -3
- package/src/interceptors/generateInterceptor.ts +39 -15
- package/src/interceptors/generateInterceptors.ts +9 -6
- package/src/interceptors/parseStructure.ts +14 -1
- package/src/interceptors/writeInterceptors.ts +7 -7
- package/src/utils/resolveDependenciesSync.ts +11 -3
- package/src/utils/resolveDependency.ts +7 -0
- 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
|
-
|
|
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)
|
|
@@ -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((
|
|
21
|
-
const files = (0, glob_1.sync)(`${
|
|
20
|
+
dependencies.forEach((filePath, packageName) => {
|
|
21
|
+
const files = (0, glob_1.sync)(`${filePath}/plugins/**/*.{ts,tsx}`);
|
|
22
22
|
files.forEach((file) => {
|
|
23
|
-
|
|
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 = '/**
|
|
43
|
-
exports.SOURCE_END = '/**
|
|
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 = '
|
|
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}
|
|
52
|
+
const sourceName = (n) => `${n}`;
|
|
53
53
|
const interceptorName = (n) => `${n}${interceptorSuffix}`;
|
|
54
|
-
const interceptorPropsName = (n) => `${
|
|
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
|
-
|
|
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(
|
|
123
|
-
|
|
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
|
-
|
|
128
|
+
const withBraces = config.pluginStatus || process.env.NODE_ENV === 'development';
|
|
127
129
|
result = `
|
|
128
|
-
type ${interceptorPropsName(name(p))} =
|
|
129
|
-
|
|
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}
|
|
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) =>
|
|
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 =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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.
|
|
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
|
+
"version": "8.1.0-canary.50",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "src/index.ts",
|
|
@@ -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()
|
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
|