@graphcommerce/next-config 9.0.4-canary.1 → 9.0.4-canary.10
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 +30 -0
- package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +0 -905
- package/__tests__/config/utils/mergeEnvIntoConfig.ts +19 -2
- package/__tests__/config/utils/replaceConfigInString.ts +0 -1
- package/__tests__/interceptors/findPlugins.ts +270 -273
- package/__tests__/utils/resolveDependenciesSync.ts +44 -44
- package/dist/generated/config.js +109 -119
- package/dist/index.js +3359 -26
- package/package.json +33 -8
- package/src/config/commands/generateConfig.ts +16 -4
- package/src/config/demoConfig.ts +0 -1
- package/src/config/loadConfig.ts +3 -9
- package/src/config/utils/mergeEnvIntoConfig.ts +8 -6
- package/src/generated/config.ts +17 -5
- package/src/interceptors/generateInterceptor.ts +0 -2
- package/src/interceptors/parseStructure.ts +3 -3
- package/src/utils/resolveDependenciesSync.ts +43 -6
- package/src/withGraphCommerce.ts +30 -42
- package/tsconfig.json +1 -1
- package/__tests__/config/utils/rewriteLegancyEnv.ts +0 -79
- package/dist/commands/codegen.js +0 -18
- package/dist/commands/copyFiles.js +0 -297
- package/dist/config/commands/exportConfig.js +0 -16
- package/dist/config/commands/generateConfig.js +0 -56
- package/dist/config/demoConfig.js +0 -52
- package/dist/config/index.js +0 -19
- package/dist/config/loadConfig.js +0 -62
- package/dist/config/utils/configToImportMeta.js +0 -39
- package/dist/config/utils/diff.js +0 -33
- package/dist/config/utils/exportConfigToEnv.js +0 -31
- package/dist/config/utils/mergeEnvIntoConfig.js +0 -182
- package/dist/config/utils/replaceConfigInString.js +0 -12
- package/dist/config/utils/rewriteLegacyEnv.js +0 -115
- package/dist/interceptors/InterceptorPlugin.js +0 -108
- package/dist/interceptors/RenameVisitor.js +0 -19
- package/dist/interceptors/Visitor.js +0 -1414
- package/dist/interceptors/commands/codegenInterceptors.js +0 -22
- package/dist/interceptors/extractExports.js +0 -159
- package/dist/interceptors/findOriginalSource.js +0 -103
- package/dist/interceptors/findPlugins.js +0 -68
- package/dist/interceptors/generateInterceptor.js +0 -219
- package/dist/interceptors/generateInterceptors.js +0 -56
- package/dist/interceptors/parseStructure.js +0 -84
- package/dist/interceptors/swc.js +0 -15
- package/dist/interceptors/writeInterceptors.js +0 -44
- package/dist/utils/PackagesSort.js +0 -7
- package/dist/utils/TopologicalSort.js +0 -87
- package/dist/utils/isMonorepo.js +0 -47
- package/dist/utils/packageRoots.js +0 -31
- package/dist/utils/resolveDependenciesSync.js +0 -78
- package/dist/utils/resolveDependency.js +0 -70
- package/dist/utils/sig.js +0 -34
- package/dist/withGraphCommerce.js +0 -162
- package/src/config/utils/rewriteLegacyEnv.ts +0 -125
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.codegenInterceptors = codegenInterceptors;
|
|
7
|
-
const dotenv_1 = __importDefault(require("dotenv"));
|
|
8
|
-
const loadConfig_1 = require("../../config/loadConfig");
|
|
9
|
-
const resolveDependency_1 = require("../../utils/resolveDependency");
|
|
10
|
-
const findPlugins_1 = require("../findPlugins");
|
|
11
|
-
const generateInterceptors_1 = require("../generateInterceptors");
|
|
12
|
-
const writeInterceptors_1 = require("../writeInterceptors");
|
|
13
|
-
dotenv_1.default.config();
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
15
|
-
async function codegenInterceptors() {
|
|
16
|
-
const conf = (0, loadConfig_1.loadConfig)(process.cwd());
|
|
17
|
-
const [plugins] = (0, findPlugins_1.findPlugins)(conf);
|
|
18
|
-
const generatedInterceptors = await (0, generateInterceptors_1.generateInterceptors)(plugins, (0, resolveDependency_1.resolveDependency)(), conf.debug, true);
|
|
19
|
-
// const generated = Date.now()
|
|
20
|
-
// console.log('Generated interceptors in', generated - found, 'ms')
|
|
21
|
-
await (0, writeInterceptors_1.writeInterceptors)(generatedInterceptors);
|
|
22
|
-
}
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.extractExports = extractExports;
|
|
5
|
-
function isIdentifier(node) {
|
|
6
|
-
return node.type === 'Identifier';
|
|
7
|
-
}
|
|
8
|
-
function isBooleanLiteral(node) {
|
|
9
|
-
return node.type === 'BooleanLiteral';
|
|
10
|
-
}
|
|
11
|
-
function isNullLiteral(node) {
|
|
12
|
-
return node.type === 'NullLiteral';
|
|
13
|
-
}
|
|
14
|
-
function isStringLiteral(node) {
|
|
15
|
-
return node.type === 'StringLiteral';
|
|
16
|
-
}
|
|
17
|
-
function isNumericLiteral(node) {
|
|
18
|
-
return node.type === 'NumericLiteral';
|
|
19
|
-
}
|
|
20
|
-
function isArrayExpression(node) {
|
|
21
|
-
return node.type === 'ArrayExpression';
|
|
22
|
-
}
|
|
23
|
-
function isObjectExpression(node) {
|
|
24
|
-
return node.type === 'ObjectExpression';
|
|
25
|
-
}
|
|
26
|
-
function isKeyValueProperty(node) {
|
|
27
|
-
return node.type === 'KeyValueProperty';
|
|
28
|
-
}
|
|
29
|
-
function isRegExpLiteral(node) {
|
|
30
|
-
return node.type === 'RegExpLiteral';
|
|
31
|
-
}
|
|
32
|
-
function isTemplateLiteral(node) {
|
|
33
|
-
return node.type === 'TemplateLiteral';
|
|
34
|
-
}
|
|
35
|
-
const RUNTIME_VALUE = Symbol('RUNTIME_VALUE');
|
|
36
|
-
function extractValue(node, path, optional = false) {
|
|
37
|
-
if (isNullLiteral(node)) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
if (isBooleanLiteral(node)) {
|
|
41
|
-
// e.g. true / false
|
|
42
|
-
return node.value;
|
|
43
|
-
}
|
|
44
|
-
if (isStringLiteral(node)) {
|
|
45
|
-
// e.g. "abc"
|
|
46
|
-
return node.value;
|
|
47
|
-
}
|
|
48
|
-
if (isNumericLiteral(node)) {
|
|
49
|
-
// e.g. 123
|
|
50
|
-
return node.value;
|
|
51
|
-
}
|
|
52
|
-
if (isRegExpLiteral(node)) {
|
|
53
|
-
// e.g. /abc/i
|
|
54
|
-
return new RegExp(node.pattern, node.flags);
|
|
55
|
-
}
|
|
56
|
-
if (isIdentifier(node)) {
|
|
57
|
-
switch (node.value) {
|
|
58
|
-
case 'undefined':
|
|
59
|
-
return undefined;
|
|
60
|
-
default:
|
|
61
|
-
return RUNTIME_VALUE;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
else if (isArrayExpression(node)) {
|
|
65
|
-
// e.g. [1, 2, 3]
|
|
66
|
-
const arr = [];
|
|
67
|
-
for (let i = 0, len = node.elements.length; i < len; i++) {
|
|
68
|
-
const elem = node.elements[i];
|
|
69
|
-
if (elem) {
|
|
70
|
-
if (elem.spread) {
|
|
71
|
-
// e.g. [ ...a ]
|
|
72
|
-
return RUNTIME_VALUE;
|
|
73
|
-
}
|
|
74
|
-
arr.push(extractValue(elem.expression, path && [...path, `[${i}]`], optional));
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
// e.g. [1, , 2]
|
|
78
|
-
// ^^
|
|
79
|
-
arr.push(undefined);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return arr;
|
|
83
|
-
}
|
|
84
|
-
else if (isObjectExpression(node)) {
|
|
85
|
-
// e.g. { a: 1, b: 2 }
|
|
86
|
-
const obj = {};
|
|
87
|
-
for (const prop of node.properties) {
|
|
88
|
-
if (!isKeyValueProperty(prop)) {
|
|
89
|
-
// e.g. { ...a }
|
|
90
|
-
return RUNTIME_VALUE;
|
|
91
|
-
}
|
|
92
|
-
let key;
|
|
93
|
-
if (isIdentifier(prop.key)) {
|
|
94
|
-
// e.g. { a: 1, b: 2 }
|
|
95
|
-
key = prop.key.value;
|
|
96
|
-
}
|
|
97
|
-
else if (isStringLiteral(prop.key)) {
|
|
98
|
-
// e.g. { "a": 1, "b": 2 }
|
|
99
|
-
key = prop.key.value;
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
return RUNTIME_VALUE;
|
|
103
|
-
}
|
|
104
|
-
obj[key] = extractValue(prop.value, path && [...path, key]);
|
|
105
|
-
}
|
|
106
|
-
return obj;
|
|
107
|
-
}
|
|
108
|
-
else if (isTemplateLiteral(node)) {
|
|
109
|
-
// e.g. `abc`
|
|
110
|
-
if (node.expressions.length !== 0) {
|
|
111
|
-
// TODO: should we add support for `${'e'}d${'g'}'e'`?
|
|
112
|
-
return RUNTIME_VALUE;
|
|
113
|
-
}
|
|
114
|
-
// When TemplateLiteral has 0 expressions, the length of quasis is always 1.
|
|
115
|
-
// Because when parsing TemplateLiteral, the parser yields the first quasi,
|
|
116
|
-
// then the first expression, then the next quasi, then the next expression, etc.,
|
|
117
|
-
// until the last quasi.
|
|
118
|
-
// Thus if there is no expression, the parser ends at the frst and also last quasis
|
|
119
|
-
//
|
|
120
|
-
// A "cooked" interpretation where backslashes have special meaning, while a
|
|
121
|
-
// "raw" interpretation where backslashes do not have special meaning
|
|
122
|
-
// https://exploringjs.com/impatient-js/ch_template-literals.html#template-strings-cooked-vs-raw
|
|
123
|
-
const [{ cooked, raw }] = node.quasis;
|
|
124
|
-
return cooked ?? raw;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
return RUNTIME_VALUE;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function extractExports(module) {
|
|
131
|
-
const exports = {};
|
|
132
|
-
const errors = [];
|
|
133
|
-
for (const moduleItem of module.body) {
|
|
134
|
-
switch (moduleItem.type) {
|
|
135
|
-
case 'ExportAllDeclaration':
|
|
136
|
-
errors.push('You can not use export * from a plugin, exports must be explicit');
|
|
137
|
-
break;
|
|
138
|
-
case 'ExportDefaultDeclaration':
|
|
139
|
-
errors.push('You can not use default exports from a plugin, exports must be explicit');
|
|
140
|
-
break;
|
|
141
|
-
case 'ExportDeclaration':
|
|
142
|
-
switch (moduleItem.declaration.type) {
|
|
143
|
-
case 'ClassDeclaration':
|
|
144
|
-
case 'FunctionDeclaration':
|
|
145
|
-
exports[moduleItem.declaration.identifier.value] = RUNTIME_VALUE;
|
|
146
|
-
// node.identifier.value
|
|
147
|
-
break;
|
|
148
|
-
case 'VariableDeclaration':
|
|
149
|
-
moduleItem.declaration.declarations.forEach((decl) => {
|
|
150
|
-
if (isIdentifier(decl.id) && decl.init) {
|
|
151
|
-
exports[decl.id.value] = extractValue(decl.init, undefined, true);
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return [exports, errors];
|
|
159
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.findOriginalSource = findOriginalSource;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const swc_1 = require("./swc");
|
|
9
|
-
function parseAndFindExport(resolved, findExport, resolve) {
|
|
10
|
-
if (!resolved?.source)
|
|
11
|
-
return undefined;
|
|
12
|
-
const ast = (0, swc_1.parseSync)(resolved.source);
|
|
13
|
-
for (const node of ast.body) {
|
|
14
|
-
if (node.type === 'ExportDeclaration') {
|
|
15
|
-
switch (node.declaration.type) {
|
|
16
|
-
case 'ClassDeclaration':
|
|
17
|
-
case 'FunctionDeclaration':
|
|
18
|
-
if (node.declaration.identifier.value === findExport)
|
|
19
|
-
return resolved;
|
|
20
|
-
break;
|
|
21
|
-
case 'VariableDeclaration':
|
|
22
|
-
for (const declaration of node.declaration.declarations) {
|
|
23
|
-
if (declaration.type === 'VariableDeclarator') {
|
|
24
|
-
if (declaration.id.type === 'Identifier') {
|
|
25
|
-
if (declaration.id.value === findExport)
|
|
26
|
-
return resolved;
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
// eslint-disable-next-line no-console
|
|
30
|
-
console.log(declaration);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (node.type === 'ExportNamedDeclaration') {
|
|
38
|
-
for (const specifier of node.specifiers) {
|
|
39
|
-
if (specifier.type === 'ExportSpecifier') {
|
|
40
|
-
if (specifier.exported?.value === findExport)
|
|
41
|
-
return resolved;
|
|
42
|
-
}
|
|
43
|
-
else if (specifier.type === 'ExportDefaultSpecifier') {
|
|
44
|
-
// todo
|
|
45
|
-
}
|
|
46
|
-
else if (specifier.type === 'ExportNamespaceSpecifier') {
|
|
47
|
-
// todo
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// todo: if (node.type === 'ExportDefaultDeclaration') {}
|
|
52
|
-
// todo: if (node.type === 'ExportDefaultExpression') {}
|
|
53
|
-
}
|
|
54
|
-
const exports = ast.body
|
|
55
|
-
.filter((node) => node.type === 'ExportAllDeclaration')
|
|
56
|
-
.sort((a, b) => {
|
|
57
|
-
const probablyA = a.source.value.includes(findExport);
|
|
58
|
-
const probablyB = b.source.value.includes(findExport);
|
|
59
|
-
// eslint-disable-next-line no-nested-ternary
|
|
60
|
-
return probablyA === probablyB ? 0 : probablyA ? -1 : 1;
|
|
61
|
-
});
|
|
62
|
-
for (const node of exports) {
|
|
63
|
-
const isRelative = node.source.value.startsWith('.');
|
|
64
|
-
if (isRelative) {
|
|
65
|
-
const d = resolved.dependency === resolved.denormalized
|
|
66
|
-
? resolved.dependency.substring(0, resolved.dependency.lastIndexOf('/'))
|
|
67
|
-
: resolved.dependency;
|
|
68
|
-
const newPath = path_1.default.join(d, node.source.value);
|
|
69
|
-
const resolveResult = resolve(newPath, { includeSources: true });
|
|
70
|
-
// eslint-disable-next-line no-continue
|
|
71
|
-
if (!resolveResult)
|
|
72
|
-
continue;
|
|
73
|
-
const newResolved = parseAndFindExport(resolveResult, findExport, resolve);
|
|
74
|
-
if (newResolved && resolved.dependency !== newResolved.dependency)
|
|
75
|
-
return newResolved;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
// const cachedResults = new Map<string, ResolveDependencyReturn>()
|
|
81
|
-
function findOriginalSource(plug, resolved, resolve) {
|
|
82
|
-
if (!resolved?.source)
|
|
83
|
-
return {
|
|
84
|
-
resolved: undefined,
|
|
85
|
-
error: new Error(`Plugin: Can not find module ${plug.targetModule} for ${plug.sourceModule}`),
|
|
86
|
-
};
|
|
87
|
-
// const cacheKey = `${plug.targetModule}#${plug.targetExport}`
|
|
88
|
-
// if (cachedResults.has(cacheKey)) {
|
|
89
|
-
// return {
|
|
90
|
-
// resolved: cachedResults.get(cacheKey) as NonNullable<ResolveDependencyReturn>,
|
|
91
|
-
// error: undefined,
|
|
92
|
-
// }
|
|
93
|
-
// }
|
|
94
|
-
const newResolved = parseAndFindExport(resolved, plug.targetExport, resolve);
|
|
95
|
-
if (!newResolved) {
|
|
96
|
-
return {
|
|
97
|
-
resolved: undefined,
|
|
98
|
-
error: new Error(`Plugin target not found ${plug.targetModule}#${plug.sourceExport} for plugin ${plug.sourceModule}#${plug.sourceExport}`),
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
// cachedResults.set(cacheKey, newResolved)
|
|
102
|
-
return { resolved: newResolved, error: undefined };
|
|
103
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findPlugins = findPlugins;
|
|
4
|
-
const core_1 = require("@swc/core");
|
|
5
|
-
const glob_1 = require("glob");
|
|
6
|
-
const resolveDependenciesSync_1 = require("../utils/resolveDependenciesSync");
|
|
7
|
-
const parseStructure_1 = require("./parseStructure");
|
|
8
|
-
const pluginLogs = {};
|
|
9
|
-
// ANSI escape codes for console colors
|
|
10
|
-
const GREEN = '\x1b[32m';
|
|
11
|
-
const RESET = '\x1b[0m';
|
|
12
|
-
function findPlugins(config, cwd = process.cwd()) {
|
|
13
|
-
const dependencies = (0, resolveDependenciesSync_1.resolveDependenciesSync)(cwd);
|
|
14
|
-
const debug = Boolean(config.debug?.pluginStatus);
|
|
15
|
-
const errors = [];
|
|
16
|
-
const plugins = [];
|
|
17
|
-
dependencies.forEach((filePath, packageName) => {
|
|
18
|
-
const files = (0, glob_1.sync)(`${filePath}/plugins/**/*.{ts,tsx}`);
|
|
19
|
-
files.forEach((file) => {
|
|
20
|
-
let sourceModule = file.replace('.tsx', '').replace('.ts', '');
|
|
21
|
-
if (file.startsWith(filePath))
|
|
22
|
-
sourceModule = `${packageName}/${sourceModule.slice(filePath.length + 1)}`;
|
|
23
|
-
if (packageName === '.' && !sourceModule.startsWith('.'))
|
|
24
|
-
sourceModule = `./${sourceModule}`;
|
|
25
|
-
try {
|
|
26
|
-
const ast = (0, core_1.parseFileSync)(file, { syntax: 'typescript', tsx: true });
|
|
27
|
-
(0, parseStructure_1.parseStructure)(ast, config, sourceModule).forEach((result) => {
|
|
28
|
-
plugins.push(result);
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
catch (e) {
|
|
32
|
-
console.error(`Error parsing ${file}`, e);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
if (process.env.NODE_ENV === 'development' && debug) {
|
|
37
|
-
const byExported = plugins.reduce((acc, plugin) => {
|
|
38
|
-
const key = `🔌 ${GREEN}Plugins loaded for ${plugin.targetModule}#${plugin.targetExport}${RESET}`;
|
|
39
|
-
if (!acc[key])
|
|
40
|
-
acc[key] = [];
|
|
41
|
-
acc[key].push(plugin);
|
|
42
|
-
return acc;
|
|
43
|
-
}, {});
|
|
44
|
-
const toLog = [];
|
|
45
|
-
Object.entries(byExported).forEach(([key, p]) => {
|
|
46
|
-
const logStr = p
|
|
47
|
-
.filter((c) => debug || c.enabled)
|
|
48
|
-
.map((c) => {
|
|
49
|
-
// eslint-disable-next-line no-nested-ternary
|
|
50
|
-
const ifConfigStr = c.ifConfig
|
|
51
|
-
? Array.isArray(c.ifConfig)
|
|
52
|
-
? `${c.ifConfig[0]}=${c.ifConfig[1]}`
|
|
53
|
-
: `${c.ifConfig}`
|
|
54
|
-
: '';
|
|
55
|
-
return `${c.enabled ? '🟢' : '⚪️'} ${c.sourceModule} ${ifConfigStr}`;
|
|
56
|
-
})
|
|
57
|
-
.join('\n');
|
|
58
|
-
if (logStr && pluginLogs[key] !== logStr) {
|
|
59
|
-
toLog.push(`${key}\n${logStr}`);
|
|
60
|
-
pluginLogs[key] = logStr;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
// eslint-disable-next-line no-console
|
|
64
|
-
if (toLog.length)
|
|
65
|
-
console.log(toLog.join('\n\n'));
|
|
66
|
-
}
|
|
67
|
-
return [plugins, errors];
|
|
68
|
-
}
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SOURCE_END = exports.SOURCE_START = void 0;
|
|
7
|
-
exports.isPluginBaseConfig = isPluginBaseConfig;
|
|
8
|
-
exports.isReactPluginConfig = isReactPluginConfig;
|
|
9
|
-
exports.isMethodPluginConfig = isMethodPluginConfig;
|
|
10
|
-
exports.isReplacePluginConfig = isReplacePluginConfig;
|
|
11
|
-
exports.isPluginConfig = isPluginConfig;
|
|
12
|
-
exports.moveRelativeDown = moveRelativeDown;
|
|
13
|
-
exports.generateInterceptor = generateInterceptor;
|
|
14
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
15
|
-
const prettier_config_pwa_1 = __importDefault(require("@graphcommerce/prettier-config-pwa"));
|
|
16
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
17
|
-
const prettier_1 = __importDefault(require("prettier"));
|
|
18
|
-
const RenameVisitor_1 = require("./RenameVisitor");
|
|
19
|
-
const swc_1 = require("./swc");
|
|
20
|
-
/** @public */
|
|
21
|
-
function isPluginBaseConfig(plugin) {
|
|
22
|
-
return (typeof plugin.type === 'string' &&
|
|
23
|
-
typeof plugin.sourceModule === 'string' &&
|
|
24
|
-
typeof plugin.enabled === 'boolean' &&
|
|
25
|
-
typeof plugin.targetExport === 'string');
|
|
26
|
-
}
|
|
27
|
-
/** @public */
|
|
28
|
-
function isReactPluginConfig(plugin) {
|
|
29
|
-
if (!isPluginBaseConfig(plugin))
|
|
30
|
-
return false;
|
|
31
|
-
return plugin.type === 'component';
|
|
32
|
-
}
|
|
33
|
-
/** @public */
|
|
34
|
-
function isMethodPluginConfig(plugin) {
|
|
35
|
-
if (!isPluginBaseConfig(plugin))
|
|
36
|
-
return false;
|
|
37
|
-
return plugin.type === 'function';
|
|
38
|
-
}
|
|
39
|
-
/** @public */
|
|
40
|
-
function isReplacePluginConfig(plugin) {
|
|
41
|
-
if (!isPluginBaseConfig(plugin))
|
|
42
|
-
return false;
|
|
43
|
-
return plugin.type === 'replace';
|
|
44
|
-
}
|
|
45
|
-
function isPluginConfig(plugin) {
|
|
46
|
-
return isPluginBaseConfig(plugin);
|
|
47
|
-
}
|
|
48
|
-
exports.SOURCE_START = '/** SOURCE_START */';
|
|
49
|
-
exports.SOURCE_END = '/** SOURCE_END */';
|
|
50
|
-
const originalSuffix = 'Original';
|
|
51
|
-
const interceptorSuffix = 'Interceptor';
|
|
52
|
-
const disabledSuffix = 'Disabled';
|
|
53
|
-
const name = (plugin) => `${plugin.sourceExport}${plugin.sourceModule
|
|
54
|
-
.split('/')[plugin.sourceModule.split('/').length - 1].replace(/[^a-zA-Z0-9]/g, '')}`;
|
|
55
|
-
const fileName = (plugin) => `${plugin.sourceModule}#${plugin.sourceExport}`;
|
|
56
|
-
const originalName = (n) => `${n}${originalSuffix}`;
|
|
57
|
-
const sourceName = (n) => `${n}`;
|
|
58
|
-
const interceptorName = (n) => `${n}${interceptorSuffix}`;
|
|
59
|
-
const interceptorPropsName = (n) => `${n}Props`;
|
|
60
|
-
function moveRelativeDown(plugins) {
|
|
61
|
-
return [...plugins].sort((a, b) => {
|
|
62
|
-
if (a.sourceModule.startsWith('.') && !b.sourceModule.startsWith('.'))
|
|
63
|
-
return 1;
|
|
64
|
-
if (!a.sourceModule.startsWith('.') && b.sourceModule.startsWith('.'))
|
|
65
|
-
return -1;
|
|
66
|
-
return 0;
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
const generateIdentifyer = (s) => Math.abs(s.split('').reduce((a, b) => {
|
|
70
|
-
// eslint-disable-next-line no-param-reassign, no-bitwise
|
|
71
|
-
a = (a << 5) - a + b.charCodeAt(0);
|
|
72
|
-
// eslint-disable-next-line no-bitwise
|
|
73
|
-
return a & a;
|
|
74
|
-
}, 0)).toString();
|
|
75
|
-
/** The is on the first line, with the format: /* hash:${identifer} */
|
|
76
|
-
function extractIdentifier(source) {
|
|
77
|
-
if (!source)
|
|
78
|
-
return null;
|
|
79
|
-
const match = source.match(/\/\* hash:(\d+) \*\//);
|
|
80
|
-
if (!match)
|
|
81
|
-
return null;
|
|
82
|
-
return match[1];
|
|
83
|
-
}
|
|
84
|
-
async function generateInterceptor(interceptor, config, oldInterceptorSource) {
|
|
85
|
-
const identifer = generateIdentifyer(JSON.stringify(interceptor) + JSON.stringify(config));
|
|
86
|
-
const { dependency, targetExports, source } = interceptor;
|
|
87
|
-
if (oldInterceptorSource && identifer === extractIdentifier(oldInterceptorSource))
|
|
88
|
-
return { ...interceptor, template: oldInterceptorSource };
|
|
89
|
-
const pluginConfigs = [...Object.entries(targetExports)].map(([, plugins]) => plugins).flat();
|
|
90
|
-
// console.log('pluginConfigs', pluginConfigs)
|
|
91
|
-
const duplicateImports = new Set();
|
|
92
|
-
const pluginImports = moveRelativeDown([...pluginConfigs].sort((a, b) => a.sourceModule.localeCompare(b.sourceModule)))
|
|
93
|
-
.map((plugin) => `import { ${plugin.sourceExport} as ${sourceName(name(plugin))} } from '${plugin.sourceModule}'`)
|
|
94
|
-
.filter((str) => {
|
|
95
|
-
if (duplicateImports.has(str))
|
|
96
|
-
return false;
|
|
97
|
-
duplicateImports.add(str);
|
|
98
|
-
return true;
|
|
99
|
-
})
|
|
100
|
-
.join('\n');
|
|
101
|
-
const ast = (0, swc_1.parseSync)(source);
|
|
102
|
-
new RenameVisitor_1.RenameVisitor(Object.keys(targetExports), (s) => originalName(s)).visitModule(ast);
|
|
103
|
-
const pluginExports = Object.entries(targetExports)
|
|
104
|
-
.map(([base, plugins]) => {
|
|
105
|
-
const duplicateInterceptors = new Set();
|
|
106
|
-
let carry = originalName(base);
|
|
107
|
-
let carryProps = [];
|
|
108
|
-
const pluginSee = [];
|
|
109
|
-
pluginSee.push(`@see {@link file://${interceptor.sourcePathRelative}} for original source file`);
|
|
110
|
-
const pluginStr = plugins
|
|
111
|
-
.reverse()
|
|
112
|
-
.filter((p) => {
|
|
113
|
-
if (duplicateInterceptors.has(name(p)))
|
|
114
|
-
return false;
|
|
115
|
-
duplicateInterceptors.add(name(p));
|
|
116
|
-
return true;
|
|
117
|
-
})
|
|
118
|
-
.map((p) => {
|
|
119
|
-
let result;
|
|
120
|
-
const wrapChain = plugins
|
|
121
|
-
.reverse()
|
|
122
|
-
.map((pl) => name(pl))
|
|
123
|
-
.join(' wrapping ');
|
|
124
|
-
if (isReplacePluginConfig(p)) {
|
|
125
|
-
new RenameVisitor_1.RenameVisitor([originalName(p.targetExport)], (s) => s.replace(originalSuffix, disabledSuffix)).visitModule(ast);
|
|
126
|
-
carryProps.push(`React.ComponentProps<typeof ${sourceName(name(p))}>`);
|
|
127
|
-
pluginSee.push(`@see {${sourceName(name(p))}} for replacement of the original source (original source not used)`);
|
|
128
|
-
}
|
|
129
|
-
if (isReactPluginConfig(p)) {
|
|
130
|
-
const withBraces = config.pluginStatus || process.env.NODE_ENV === 'development';
|
|
131
|
-
result = `
|
|
132
|
-
type ${interceptorPropsName(name(p))} = ${carryProps.join(' & ')} & OmitPrev<React.ComponentProps<typeof ${sourceName(name(p))}>, 'Prev'>
|
|
133
|
-
|
|
134
|
-
const ${interceptorName(name(p))} = (props: ${interceptorPropsName(name(p))}) => ${withBraces ? '{' : '('}
|
|
135
|
-
${config.pluginStatus ? `logOnce(\`🔌 Rendering ${base} with plugin(s): ${wrapChain} wrapping <${base}/>\`)` : ''}
|
|
136
|
-
|
|
137
|
-
${process.env.NODE_ENV === 'development'
|
|
138
|
-
? `if(!props['data-plugin'])
|
|
139
|
-
logOnce('${fileName(p)} does not spread props to prev: <Prev {...props}/>. This will cause issues if multiple plugins are applied to this component.')`
|
|
140
|
-
: ''}
|
|
141
|
-
${withBraces ? 'return' : ''} <${sourceName(name(p))} {...props} Prev={${carry}} />
|
|
142
|
-
${withBraces ? '}' : ')'}`;
|
|
143
|
-
carryProps = [interceptorPropsName(name(p))];
|
|
144
|
-
pluginSee.push(`@see {${sourceName(name(p))}} for source of applied plugin`);
|
|
145
|
-
}
|
|
146
|
-
if (isMethodPluginConfig(p)) {
|
|
147
|
-
result = `const ${interceptorName(name(p))}: typeof ${carry} = (...args) => {
|
|
148
|
-
${config.pluginStatus ? `logOnce(\`🔌 Calling ${base} with plugin(s): ${wrapChain} wrapping ${base}()\`)` : ''}
|
|
149
|
-
return ${sourceName(name(p))}(${carry}, ...args)
|
|
150
|
-
}`;
|
|
151
|
-
pluginSee.push(`@see {${sourceName(name(p))}} for source of applied plugin`);
|
|
152
|
-
}
|
|
153
|
-
carry = p.type === 'replace' ? sourceName(name(p)) : interceptorName(name(p));
|
|
154
|
-
return result;
|
|
155
|
-
})
|
|
156
|
-
.filter((v) => !!v)
|
|
157
|
-
.join('\n');
|
|
158
|
-
const isComponent = plugins.every((p) => isReactPluginConfig(p));
|
|
159
|
-
if (isComponent && plugins.some((p) => isMethodPluginConfig(p))) {
|
|
160
|
-
throw new Error(`Cannot mix React and Method plugins for ${base} in ${dependency}.`);
|
|
161
|
-
}
|
|
162
|
-
const seeString = `
|
|
163
|
-
/**
|
|
164
|
-
* Here you see the 'interceptor' that is applying all the configured plugins.
|
|
165
|
-
*
|
|
166
|
-
* This file is NOT meant to be modified directly and is auto-generated if the plugins or the original source changes.
|
|
167
|
-
*
|
|
168
|
-
${pluginSee.map((s) => `* ${s}`).join('\n')}
|
|
169
|
-
*/`;
|
|
170
|
-
if (process.env.NODE_ENV === 'development' && isComponent) {
|
|
171
|
-
return `${pluginStr}
|
|
172
|
-
${seeString}
|
|
173
|
-
export const ${base}: typeof ${carry} = (props) => {
|
|
174
|
-
return <${carry} {...props} data-plugin />
|
|
175
|
-
}`;
|
|
176
|
-
}
|
|
177
|
-
return `
|
|
178
|
-
${pluginStr}
|
|
179
|
-
${seeString}
|
|
180
|
-
export const ${base} = ${carry}
|
|
181
|
-
`;
|
|
182
|
-
})
|
|
183
|
-
.join('\n');
|
|
184
|
-
const logOnce = config.pluginStatus || process.env.NODE_ENV === 'development'
|
|
185
|
-
? `
|
|
186
|
-
const logged: Set<string> = new Set();
|
|
187
|
-
const logOnce = (log: string, ...additional: unknown[]) => {
|
|
188
|
-
if (logged.has(log)) return
|
|
189
|
-
logged.add(log)
|
|
190
|
-
console.warn(log, ...additional)
|
|
191
|
-
}
|
|
192
|
-
`
|
|
193
|
-
: '';
|
|
194
|
-
const template = `/* hash:${identifer} */
|
|
195
|
-
/* eslint-disable */
|
|
196
|
-
/* This file is automatically generated for ${dependency} */
|
|
197
|
-
${Object.values(targetExports).some((t) => t.some((p) => p.type === 'component'))
|
|
198
|
-
? "import type { DistributedOmit as OmitPrev } from 'type-fest'"
|
|
199
|
-
: ''}
|
|
200
|
-
|
|
201
|
-
${pluginImports}
|
|
202
|
-
|
|
203
|
-
/** @see {@link file://${interceptor.sourcePathRelative}} for source of original */
|
|
204
|
-
${exports.SOURCE_START}
|
|
205
|
-
${(0, swc_1.printSync)(ast).code}
|
|
206
|
-
${exports.SOURCE_END}
|
|
207
|
-
${logOnce}${pluginExports}
|
|
208
|
-
`;
|
|
209
|
-
let templateFormatted;
|
|
210
|
-
try {
|
|
211
|
-
templateFormatted = await prettier_1.default.format(template, { ...prettier_config_pwa_1.default, parser: 'typescript' });
|
|
212
|
-
}
|
|
213
|
-
catch (e) {
|
|
214
|
-
// eslint-disable-next-line no-console
|
|
215
|
-
console.log('Error formatting interceptor: ', e, 'using raw template.');
|
|
216
|
-
templateFormatted = template;
|
|
217
|
-
}
|
|
218
|
-
return { ...interceptor, template: templateFormatted };
|
|
219
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateInterceptors = generateInterceptors;
|
|
7
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
8
|
-
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
9
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
const findOriginalSource_1 = require("./findOriginalSource");
|
|
11
|
-
const generateInterceptor_1 = require("./generateInterceptor");
|
|
12
|
-
async function generateInterceptors(plugins, resolve, config, force) {
|
|
13
|
-
const byTargetModuleAndExport = (0, generateInterceptor_1.moveRelativeDown)(plugins).reduce((acc, plug) => {
|
|
14
|
-
let { sourceModule: pluginPath } = plug;
|
|
15
|
-
if (!(0, generateInterceptor_1.isPluginConfig)(plug) || !plug.enabled)
|
|
16
|
-
return acc;
|
|
17
|
-
const result = resolve(plug.targetModule, { includeSources: true });
|
|
18
|
-
const { error, resolved } = (0, findOriginalSource_1.findOriginalSource)(plug, result, resolve);
|
|
19
|
-
if (error) {
|
|
20
|
-
console.error(error.message);
|
|
21
|
-
return acc;
|
|
22
|
-
}
|
|
23
|
-
const { fromRoot } = resolved;
|
|
24
|
-
if (pluginPath.startsWith('.')) {
|
|
25
|
-
const resolvedPlugin = resolve(pluginPath);
|
|
26
|
-
if (resolvedPlugin) {
|
|
27
|
-
pluginPath = node_path_1.default.relative(resolved.fromRoot.split('/').slice(0, -1).join('/'), resolvedPlugin.fromRoot);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (!acc[resolved.fromRoot]) {
|
|
31
|
-
acc[resolved.fromRoot] = {
|
|
32
|
-
...resolved,
|
|
33
|
-
target: `${resolved.fromRoot}.interceptor`,
|
|
34
|
-
targetExports: {},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
if (!acc[fromRoot].targetExports[plug.targetExport])
|
|
38
|
-
acc[fromRoot].targetExports[plug.targetExport] = [];
|
|
39
|
-
acc[fromRoot].targetExports[plug.targetExport].push({ ...plug, sourceModule: pluginPath });
|
|
40
|
-
return acc;
|
|
41
|
-
}, {});
|
|
42
|
-
return Object.fromEntries(await Promise.all(Object.entries(byTargetModuleAndExport).map(async ([target, interceptor]) => {
|
|
43
|
-
const file = `${interceptor.fromRoot}.interceptor.tsx`;
|
|
44
|
-
const originalSource = !force &&
|
|
45
|
-
(await promises_1.default
|
|
46
|
-
.access(file, promises_1.default.constants.F_OK)
|
|
47
|
-
.then(() => true)
|
|
48
|
-
.catch(() => false))
|
|
49
|
-
? (await promises_1.default.readFile(file)).toString()
|
|
50
|
-
: undefined;
|
|
51
|
-
return [
|
|
52
|
-
target,
|
|
53
|
-
await (0, generateInterceptor_1.generateInterceptor)(interceptor, config ?? {}, originalSource),
|
|
54
|
-
];
|
|
55
|
-
})));
|
|
56
|
-
}
|