rev-dep 1.4.0 → 1.5.1
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/dist/babel/babelParsingOptions.d.ts +5 -0
- package/dist/babel/babelParsingOptions.js +15 -0
- package/dist/babel/groupBy.d.ts +1 -0
- package/dist/babel/groupBy.js +14 -0
- package/dist/babel/index.js +286 -163
- package/dist/babel/processCodeTextModificationsArray.d.ts +30 -0
- package/dist/babel/processCodeTextModificationsArray.js +55 -0
- package/dist/babel/template.d.ts +1 -0
- package/dist/babel/template.js +13 -0
- package/dist/babel/transform.d.ts +6 -1
- package/dist/babel/transform.js +28 -14
- package/dist/babel/transformCli.d.ts +1 -0
- package/dist/babel/transformCli.js +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.babelParsingOptions = void 0;
|
|
4
|
+
exports.babelParsingOptions = {
|
|
5
|
+
errorRecovery: true,
|
|
6
|
+
sourceType: 'module',
|
|
7
|
+
plugins: [
|
|
8
|
+
'jsx',
|
|
9
|
+
'typescript',
|
|
10
|
+
'objectRestSpread',
|
|
11
|
+
'classProperties',
|
|
12
|
+
'asyncGenerators',
|
|
13
|
+
'decorators-legacy'
|
|
14
|
+
]
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function groupBy(arr: any, property: any): any;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.groupBy = void 0;
|
|
4
|
+
function groupBy(arr, property) {
|
|
5
|
+
return arr.reduce((result, obj) => {
|
|
6
|
+
const key = obj[property];
|
|
7
|
+
if (!result[key]) {
|
|
8
|
+
result[key] = [];
|
|
9
|
+
}
|
|
10
|
+
result[key].push(obj);
|
|
11
|
+
return result;
|
|
12
|
+
}, {});
|
|
13
|
+
}
|
|
14
|
+
exports.groupBy = groupBy;
|
package/dist/babel/index.js
CHANGED
|
@@ -4,19 +4,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
const node_path = require('path');
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const parser = require('@babel/parser');
|
|
7
|
-
const template = require('@babel/template').default;
|
|
8
7
|
const utils_1 = require("../lib/utils");
|
|
8
|
+
const template_1 = require("./template");
|
|
9
9
|
const SKIP = Symbol('SKIP');
|
|
10
|
+
const babelParsingOptions_1 = require("./babelParsingOptions");
|
|
11
|
+
const groupBy_1 = require("./groupBy");
|
|
10
12
|
/**
|
|
11
13
|
*
|
|
12
14
|
* TODO
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* + If that has to be used as a codemod, we have to refactor to make sure we don't change structure of other parts of the code and we preserve imports order
|
|
16
|
+
* +- group named imports from the same file
|
|
17
|
+
* + support imports from baseUrl from TS config -> relative | baseUrl | alias
|
|
18
|
+
* + persist the original import alias
|
|
19
|
+
* + allow for a list of files to rewire
|
|
20
|
+
* + use cache for not resolved modules as well
|
|
21
|
+
* + handle type imports properly - we don't preserve the import was a type import
|
|
22
|
+
* + do not touch imports that don't need changes
|
|
18
23
|
*/
|
|
19
|
-
module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsConfig)() }) {
|
|
24
|
+
module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsConfig)(), cache = new Map(), includeBarrelExportFiles, excludeBarrelExportFiles = [] }) {
|
|
20
25
|
const root = tsConfigPath.replace('/tsconfig.json', '');
|
|
21
26
|
const tsConfigContent = fs.readFileSync(tsConfigPath).toString();
|
|
22
27
|
const tsConfigContentCleaned = tsConfigContent
|
|
@@ -26,9 +31,21 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
|
|
|
26
31
|
const tsConfig = JSON.parse(tsConfigContentCleaned);
|
|
27
32
|
const aliases = tsConfig.compilerOptions.paths;
|
|
28
33
|
const aliasesKeys = Object.keys(aliases);
|
|
29
|
-
const
|
|
30
|
-
return new RegExp(`^${
|
|
31
|
-
}
|
|
34
|
+
const makeRegExpFromAliasExpression = (aliasExpression) => {
|
|
35
|
+
return new RegExp(`^${aliasExpression.replace('*', '(.+)')}$`);
|
|
36
|
+
};
|
|
37
|
+
const aliasesRegexes = Object.keys(aliases).map(makeRegExpFromAliasExpression);
|
|
38
|
+
// TODO we assume that only one aliased path can exist
|
|
39
|
+
const aliasedPathRegExps = Object.values(aliases).map(([fistAliasedPath]) => makeRegExpFromAliasExpression(fistAliasedPath));
|
|
40
|
+
const interpolateAliasWithPath = (aliasKey, aliasedPathRegExp, resolvedSourcePathRelativeToBaseUrl) => {
|
|
41
|
+
const [_, ...groups] = aliasedPathRegExp.exec(resolvedSourcePathRelativeToBaseUrl);
|
|
42
|
+
const aliasParts = aliasKey.split('*');
|
|
43
|
+
const interpolatedAlias = aliasParts.reduce((mergedPath, aliasPart, idx) => {
|
|
44
|
+
var _a;
|
|
45
|
+
return `${mergedPath}${aliasPart}${(_a = groups[idx]) !== null && _a !== void 0 ? _a : ''}`;
|
|
46
|
+
}, '');
|
|
47
|
+
return interpolatedAlias;
|
|
48
|
+
};
|
|
32
49
|
let baseUrlDirs = [];
|
|
33
50
|
const baseUrl = tsConfig.compilerOptions.baseUrl;
|
|
34
51
|
if (baseUrl) {
|
|
@@ -39,10 +56,10 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
|
|
|
39
56
|
.map((dirent) => dirent.name + '/');
|
|
40
57
|
baseUrlDirs = dirNames;
|
|
41
58
|
}
|
|
42
|
-
const cache = new Map();
|
|
43
59
|
const getFile = (original, paths) => {
|
|
44
60
|
if (paths.length === 0) {
|
|
45
|
-
|
|
61
|
+
console.warn('Cannot resolve import ' + original);
|
|
62
|
+
return null;
|
|
46
63
|
}
|
|
47
64
|
const path = paths[0];
|
|
48
65
|
try {
|
|
@@ -52,18 +69,18 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
|
|
|
52
69
|
return getFile(original, paths.slice(1));
|
|
53
70
|
}
|
|
54
71
|
};
|
|
55
|
-
const
|
|
72
|
+
const shouldPathBeAnalyzed = (path) => {
|
|
56
73
|
const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(path));
|
|
57
74
|
const isRelative = path.startsWith('./') || path.startsWith('../');
|
|
58
75
|
const isAbsolute = path.startsWith('/');
|
|
59
76
|
const isBaseUrlPath = baseUrlDirs.some((dir) => path.startsWith(dir));
|
|
60
77
|
return aliasRegexIdx > -1 || isRelative || isAbsolute || isBaseUrlPath;
|
|
61
78
|
};
|
|
62
|
-
const
|
|
79
|
+
const getCacheKey = (identifier, filePath) => `${identifier}-${filePath}`;
|
|
63
80
|
const lookup = (identifier, filePath, cwd) => {
|
|
64
|
-
const cached = cache.get(
|
|
81
|
+
const cached = cache.get(getCacheKey(identifier, filePath));
|
|
65
82
|
if (cached) {
|
|
66
|
-
return cached;
|
|
83
|
+
return { ...cached, isCached: true };
|
|
67
84
|
}
|
|
68
85
|
const withExtension = /(\.ts|\.tsx)$/.test(filePath)
|
|
69
86
|
? [filePath]
|
|
@@ -77,117 +94,124 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
|
|
|
77
94
|
`${filePath}/index.js`,
|
|
78
95
|
`${filePath}/index.jsx`
|
|
79
96
|
];
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
type: 'named',
|
|
111
|
-
identifier,
|
|
112
|
-
source: filePath
|
|
113
|
-
};
|
|
97
|
+
const fileInfo = getFile(filePath, withExtension);
|
|
98
|
+
if (!fileInfo) {
|
|
99
|
+
return { resolvedAs: null, visitedFiles: [] };
|
|
100
|
+
}
|
|
101
|
+
const [resolvedFilePath, file] = fileInfo;
|
|
102
|
+
try {
|
|
103
|
+
const ast = parser.parse(file, babelParsingOptions_1.babelParsingOptions);
|
|
104
|
+
/**
|
|
105
|
+
* {
|
|
106
|
+
* identifier?: string,
|
|
107
|
+
* source: string
|
|
108
|
+
* }
|
|
109
|
+
*/
|
|
110
|
+
const toLookup = [];
|
|
111
|
+
let resolvedAs = null;
|
|
112
|
+
ast.program.body.forEach((declaration) => {
|
|
113
|
+
var _a, _b, _c;
|
|
114
|
+
if (resolvedAs === null) {
|
|
115
|
+
if (types.isExportNamedDeclaration(declaration)) {
|
|
116
|
+
if (((_a = declaration.declaration) === null || _a === void 0 ? void 0 : _a.type.startsWith('TS')) &&
|
|
117
|
+
((_b = declaration.declaration) === null || _b === void 0 ? void 0 : _b.type.endsWith('Declaration'))) {
|
|
118
|
+
const typeName = declaration.declaration.id.name;
|
|
119
|
+
if (typeName === identifier) {
|
|
120
|
+
resolvedAs = {
|
|
121
|
+
// This should be 'type' of something else, but ESLint would handle that
|
|
122
|
+
type: 'named',
|
|
123
|
+
identifier,
|
|
124
|
+
source: filePath
|
|
125
|
+
};
|
|
126
|
+
}
|
|
114
127
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
128
|
+
else if (types.isVariableDeclaration(declaration.declaration)) {
|
|
129
|
+
const hasIdentifier = declaration.declaration.declarations.find((declarator) => {
|
|
130
|
+
return declarator.id.name === identifier;
|
|
131
|
+
});
|
|
132
|
+
if (hasIdentifier) {
|
|
133
|
+
resolvedAs = {
|
|
134
|
+
type: 'named',
|
|
135
|
+
identifier,
|
|
136
|
+
source: filePath
|
|
137
|
+
};
|
|
138
|
+
}
|
|
126
139
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
140
|
+
else if (types.isFunctionDeclaration(declaration.declaration) ||
|
|
141
|
+
types.isClassDeclaration(declaration.declaration)) {
|
|
142
|
+
if (declaration.declaration.id.name === identifier) {
|
|
143
|
+
resolvedAs = {
|
|
144
|
+
type: 'named',
|
|
145
|
+
identifier,
|
|
146
|
+
source: filePath
|
|
147
|
+
};
|
|
148
|
+
}
|
|
136
149
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
150
|
+
else {
|
|
151
|
+
const source = (_c = declaration.source) === null || _c === void 0 ? void 0 : _c.value;
|
|
152
|
+
declaration.specifiers.forEach((specifier) => {
|
|
153
|
+
if (types.isExportSpecifier(specifier)) {
|
|
154
|
+
if (specifier.exported.name === identifier) {
|
|
155
|
+
if (specifier.local.name === 'default' && source) {
|
|
156
|
+
resolvedAs = {
|
|
157
|
+
type: 'default',
|
|
158
|
+
identifier,
|
|
159
|
+
source: getModulePath(source, resolvedFilePath, cwd)
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
else if (source === undefined) {
|
|
163
|
+
// Here we could check if identifier comes from import statement, and if so, lookup deeper
|
|
164
|
+
resolvedAs = {
|
|
165
|
+
type: 'named',
|
|
166
|
+
identifier,
|
|
167
|
+
source: filePath
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
else if (shouldPathBeAnalyzed(source)) {
|
|
171
|
+
toLookup.push({
|
|
172
|
+
identifier: specifier.local.name,
|
|
173
|
+
source: getModulePath(source, resolvedFilePath, cwd)
|
|
174
|
+
});
|
|
175
|
+
}
|
|
162
176
|
}
|
|
163
177
|
}
|
|
164
|
-
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (types.isExportAllDeclaration(declaration) &&
|
|
182
|
+
shouldPathBeAnalyzed(declaration.source.value)) {
|
|
183
|
+
toLookup.push({
|
|
184
|
+
identifier,
|
|
185
|
+
source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
|
|
165
186
|
});
|
|
166
187
|
}
|
|
167
188
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
identifier,
|
|
172
|
-
source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
|
|
173
|
-
});
|
|
174
|
-
}
|
|
189
|
+
});
|
|
190
|
+
if (resolvedAs) {
|
|
191
|
+
return { resolvedAs, visitedFiles: [resolvedAs.source] };
|
|
175
192
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
193
|
+
const nestedResult = toLookup
|
|
194
|
+
.map(({ identifier, source }) => lookup(identifier, source, cwd))
|
|
195
|
+
.filter((lookUpResult) => lookUpResult.resolvedAs !== null);
|
|
196
|
+
if (nestedResult[0]) {
|
|
197
|
+
return {
|
|
198
|
+
resolvedAs: nestedResult[0].resolvedAs,
|
|
199
|
+
visitedFiles: [resolvedFilePath, ...nestedResult[0].visitedFiles]
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return { resolvedAs: null, visitedFiles: [] };
|
|
203
|
+
}
|
|
204
|
+
catch (e) {
|
|
205
|
+
console.log('Lookup parse error', filePath, e);
|
|
206
|
+
process.exit(0);
|
|
179
207
|
}
|
|
180
|
-
const nestedResult = toLookup
|
|
181
|
-
.map(({ identifier, source }) => lookup(identifier, source, cwd))
|
|
182
|
-
.filter(Boolean);
|
|
183
|
-
return nestedResult[0];
|
|
184
208
|
};
|
|
185
209
|
const getModulePath = (sourcePath, fileName, cwd) => {
|
|
186
210
|
var _a;
|
|
187
211
|
const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
|
|
188
212
|
const relativeFileName = node_path.relative(cwd, fileName);
|
|
189
213
|
const aliasKey = aliasesKeys[aliasRegexIdx];
|
|
190
|
-
const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0];
|
|
214
|
+
const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0]; // TODO we assume that only one aliased path can exist in config
|
|
191
215
|
const isAbsoluteToBaseDir = baseUrlDirs.some((baseUrlDir) => sourcePath.startsWith(baseUrlDir));
|
|
192
216
|
let modulePath = '';
|
|
193
217
|
if (alias) {
|
|
@@ -207,115 +231,214 @@ module.exports = function plugin({ types }, { tsConfigPath = (0, utils_1.findTsC
|
|
|
207
231
|
}
|
|
208
232
|
return modulePath;
|
|
209
233
|
};
|
|
234
|
+
const getImportKind = (sourcePath) => {
|
|
235
|
+
const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
|
|
236
|
+
const isRelative = sourcePath.startsWith('./') || sourcePath.startsWith('../');
|
|
237
|
+
const isBaseUrlPath = baseUrlDirs.some((dir) => sourcePath.startsWith(dir));
|
|
238
|
+
if (aliasRegexIdx > -1) {
|
|
239
|
+
return 'aliased';
|
|
240
|
+
}
|
|
241
|
+
if (isRelative) {
|
|
242
|
+
return 'relative';
|
|
243
|
+
}
|
|
244
|
+
if (isBaseUrlPath) {
|
|
245
|
+
return 'baseUrl';
|
|
246
|
+
}
|
|
247
|
+
throw new Error('Could not determine import kind');
|
|
248
|
+
};
|
|
210
249
|
return {
|
|
211
250
|
visitor: {
|
|
212
251
|
Program() {
|
|
213
252
|
// console.log('Cache size', cache.size)
|
|
214
253
|
},
|
|
215
|
-
ImportDeclaration(path,
|
|
216
|
-
const
|
|
217
|
-
|
|
254
|
+
ImportDeclaration(path, state) {
|
|
255
|
+
const filename = state.filename;
|
|
256
|
+
const getImportSourceFormatted = (resolvedSourcePath, importKind) => {
|
|
257
|
+
const baseDirPath = node_path.join(root, baseUrl);
|
|
258
|
+
if (importKind === 'baseUrl') {
|
|
259
|
+
const relativeToBaseUrl = node_path.relative(baseDirPath, resolvedSourcePath);
|
|
260
|
+
return relativeToBaseUrl;
|
|
261
|
+
}
|
|
262
|
+
if (importKind === 'aliased') {
|
|
263
|
+
const originalSource = path.node.source.value;
|
|
264
|
+
const currentAliasIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(originalSource));
|
|
265
|
+
const resolvedSourcePathRelativeToBaseUrl = resolvedSourcePath
|
|
266
|
+
.replace(baseDirPath, '')
|
|
267
|
+
.replace(/^\//, '');
|
|
268
|
+
// Try to use current alias if it matches new path
|
|
269
|
+
if (currentAliasIdx > -1) {
|
|
270
|
+
const aliasKey = aliasesKeys[currentAliasIdx];
|
|
271
|
+
const aliasedPathRegExp = aliasedPathRegExps[currentAliasIdx];
|
|
272
|
+
if (aliasedPathRegExp.test(resolvedSourcePathRelativeToBaseUrl)) {
|
|
273
|
+
return interpolateAliasWithPath(aliasKey, aliasedPathRegExp, resolvedSourcePathRelativeToBaseUrl);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
// Try finding matching alias
|
|
277
|
+
const newMatchingAliasIndex = aliasedPathRegExps.findIndex((aliasedPathRegexp) => aliasedPathRegexp.test(resolvedSourcePathRelativeToBaseUrl));
|
|
278
|
+
if (newMatchingAliasIndex > -1) {
|
|
279
|
+
const aliasKey = aliasesKeys[newMatchingAliasIndex];
|
|
280
|
+
const aliasedPathRegExp = aliasedPathRegExps[newMatchingAliasIndex];
|
|
281
|
+
return interpolateAliasWithPath(aliasKey, aliasedPathRegExp, resolvedSourcePathRelativeToBaseUrl);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const rel = node_path.relative(node_path.dirname(filename), resolvedSourcePath);
|
|
218
285
|
const whatever = rel.startsWith('.') ? rel : './' + rel;
|
|
219
286
|
// remove file extension
|
|
220
287
|
return whatever.replace(/\.(ts|js|tsx|jsx|cjs|mjs)$/, '');
|
|
221
288
|
};
|
|
222
289
|
const node = path.node;
|
|
290
|
+
const isTypeImport = node.importKind === 'type';
|
|
223
291
|
const source = node.source;
|
|
224
292
|
if (source.type !== 'StringLiteral') {
|
|
225
293
|
return;
|
|
226
294
|
}
|
|
227
|
-
const shouldSkip = node[SKIP] || !
|
|
295
|
+
const shouldSkip = node[SKIP] || !shouldPathBeAnalyzed(source.value);
|
|
228
296
|
if (shouldSkip) {
|
|
229
297
|
return;
|
|
230
298
|
}
|
|
299
|
+
const importKind = getImportKind(source.value);
|
|
231
300
|
const modulePath = getModulePath(source.value, filename, root);
|
|
232
|
-
const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier'
|
|
233
|
-
|
|
234
|
-
const
|
|
301
|
+
const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier' // import $$ from '$$'
|
|
302
|
+
);
|
|
303
|
+
const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier' // import * as $$ from '$$'
|
|
304
|
+
);
|
|
305
|
+
const specifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier' // import { $$ } from '$$'
|
|
306
|
+
);
|
|
235
307
|
const results = specifiers.map((specifier) => {
|
|
236
308
|
const importedName = specifier.imported.name;
|
|
237
309
|
const result = lookup(importedName, modulePath, root);
|
|
238
|
-
if (!result) {
|
|
239
|
-
|
|
310
|
+
if (!(result === null || result === void 0 ? void 0 : result.isCached)) {
|
|
311
|
+
const cacheKey = getCacheKey(importedName, modulePath);
|
|
312
|
+
// console.log('resolved not cached', cacheKey, result)
|
|
313
|
+
const originalImport = {
|
|
314
|
+
identifier: importedName,
|
|
315
|
+
local: specifier.local.name,
|
|
316
|
+
source: source.value // cannot cache non absolute path
|
|
317
|
+
};
|
|
318
|
+
const originalImportToCache = {
|
|
240
319
|
identifier: importedName,
|
|
241
320
|
local: specifier.local.name,
|
|
242
|
-
source:
|
|
321
|
+
source: modulePath
|
|
243
322
|
};
|
|
323
|
+
const originalResolution = {
|
|
324
|
+
resolvedAs: originalImportToCache,
|
|
325
|
+
visitedFiles: []
|
|
326
|
+
};
|
|
327
|
+
if (!result.resolvedAs) {
|
|
328
|
+
cache.set(cacheKey, originalResolution);
|
|
329
|
+
return originalImport;
|
|
330
|
+
}
|
|
331
|
+
if (includeBarrelExportFiles &&
|
|
332
|
+
!includeBarrelExportFiles.some((fileThatHasToBeVisited) => result.visitedFiles.includes(fileThatHasToBeVisited))) {
|
|
333
|
+
cache.set(cacheKey, originalResolution);
|
|
334
|
+
return originalImport;
|
|
335
|
+
}
|
|
336
|
+
if (excludeBarrelExportFiles.some((fileThatCannotBeVisited) => result.visitedFiles.includes(fileThatCannotBeVisited))) {
|
|
337
|
+
cache.set(cacheKey, originalResolution);
|
|
338
|
+
return originalImport;
|
|
339
|
+
}
|
|
340
|
+
cache.set(cacheKey, result);
|
|
244
341
|
}
|
|
245
|
-
cache.set(cacheKey(importedName, modulePath), result);
|
|
246
342
|
return {
|
|
247
|
-
...result,
|
|
248
|
-
source:
|
|
343
|
+
...result.resolvedAs,
|
|
344
|
+
source: getImportSourceFormatted(result.resolvedAs.source, importKind),
|
|
249
345
|
local: specifier.local.name
|
|
250
346
|
};
|
|
251
347
|
});
|
|
252
348
|
const defaultResult = defaultSpecifier
|
|
253
349
|
? lookup('default', modulePath, root)
|
|
254
350
|
: null;
|
|
255
|
-
if (defaultResult) {
|
|
256
|
-
|
|
351
|
+
if (defaultResult && !defaultResult.isCached) {
|
|
352
|
+
const cacheKey = getCacheKey('default', modulePath);
|
|
353
|
+
const originalImportToCache = {
|
|
354
|
+
source: modulePath
|
|
355
|
+
};
|
|
356
|
+
const originalResolution = {
|
|
357
|
+
resolvedAs: originalImportToCache,
|
|
358
|
+
visitedFiles: []
|
|
359
|
+
};
|
|
360
|
+
if (!defaultResult.resolvedAs) {
|
|
361
|
+
cache.set(cacheKey, originalResolution);
|
|
362
|
+
}
|
|
363
|
+
else if (includeBarrelExportFiles &&
|
|
364
|
+
!includeBarrelExportFiles.some((fileThatHasToBeVisited) => defaultResult.visitedFiles.includes(fileThatHasToBeVisited))) {
|
|
365
|
+
cache.set(cacheKey, originalResolution);
|
|
366
|
+
}
|
|
367
|
+
else if (excludeBarrelExportFiles.some((fileThatCannotBeVisited) => defaultResult.visitedFiles.includes(fileThatCannotBeVisited))) {
|
|
368
|
+
cache.set(cacheKey, originalResolution);
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
cache.set(cacheKey, defaultResult);
|
|
372
|
+
}
|
|
257
373
|
}
|
|
258
|
-
const buildNamed = template(`
|
|
259
|
-
import { %%IMPORT_NAME%% } from %%SOURCE
|
|
374
|
+
const buildNamed = (0, template_1.template)(`
|
|
375
|
+
import { %%IMPORT_NAME%% } from '%%SOURCE%%';
|
|
260
376
|
`);
|
|
261
|
-
const buildNamedWithAlias = template(`
|
|
262
|
-
import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from %%SOURCE
|
|
377
|
+
const buildNamedWithAlias = (0, template_1.template)(`
|
|
378
|
+
import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from '%%SOURCE%%';
|
|
263
379
|
`);
|
|
264
|
-
const buildDefault = template(`
|
|
265
|
-
import %%IMPORT_NAME%% from %%SOURCE
|
|
380
|
+
const buildDefault = (0, template_1.template)(`
|
|
381
|
+
import %%IMPORT_NAME%% from '%%SOURCE%%';
|
|
266
382
|
`);
|
|
267
|
-
const buildNamespace = template(`
|
|
268
|
-
import * as %%IMPORT_NAME%% from %%SOURCE
|
|
383
|
+
const buildNamespace = (0, template_1.template)(`
|
|
384
|
+
import * as %%IMPORT_NAME%% from '%%SOURCE%%';
|
|
269
385
|
`);
|
|
270
|
-
const defaultImport = defaultResult
|
|
386
|
+
const defaultImport = (defaultResult === null || defaultResult === void 0 ? void 0 : defaultResult.resolvedAs)
|
|
271
387
|
? [
|
|
272
388
|
buildDefault({
|
|
273
|
-
IMPORT_NAME:
|
|
274
|
-
SOURCE:
|
|
389
|
+
IMPORT_NAME: defaultSpecifier.local.name,
|
|
390
|
+
SOURCE: getImportSourceFormatted(defaultResult.resolvedAs.source, importKind)
|
|
275
391
|
})
|
|
276
392
|
]
|
|
277
393
|
: defaultSpecifier
|
|
278
394
|
? [
|
|
279
395
|
buildDefault({
|
|
280
|
-
IMPORT_NAME:
|
|
281
|
-
SOURCE:
|
|
396
|
+
IMPORT_NAME: defaultSpecifier.local.name,
|
|
397
|
+
SOURCE: source.value
|
|
282
398
|
})
|
|
283
399
|
]
|
|
284
400
|
: [];
|
|
285
401
|
const namespaceImport = namespaceSpecifier
|
|
286
402
|
? [
|
|
287
403
|
buildNamespace({
|
|
288
|
-
IMPORT_NAME:
|
|
289
|
-
SOURCE:
|
|
404
|
+
IMPORT_NAME: namespaceSpecifier.local.name,
|
|
405
|
+
SOURCE: source.value
|
|
290
406
|
})
|
|
291
407
|
]
|
|
292
408
|
: [];
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
IMPORT_NAME: types.identifier(identifier),
|
|
310
|
-
SOURCE: types.stringLiteral(source)
|
|
311
|
-
});
|
|
312
|
-
}
|
|
409
|
+
const importsFromNamedGroupedBySource = Object.values((0, groupBy_1.groupBy)(results, 'source'));
|
|
410
|
+
const named = importsFromNamedGroupedBySource.map((imports) => {
|
|
411
|
+
const source = imports[0].source;
|
|
412
|
+
const defaultImport = imports.find(({ type }) => type === 'default');
|
|
413
|
+
const nonDefault = imports.filter(({ type }) => type !== 'default');
|
|
414
|
+
const defaultPart = defaultImport
|
|
415
|
+
? `${defaultImport.identifier}`
|
|
416
|
+
: null;
|
|
417
|
+
const nonDefaultPart = nonDefault.length > 0
|
|
418
|
+
? nonDefault
|
|
419
|
+
.map(({ identifier, local }) => identifier !== local
|
|
420
|
+
? `${identifier} as ${local}`
|
|
421
|
+
: identifier)
|
|
422
|
+
.join(', ')
|
|
423
|
+
: null;
|
|
424
|
+
return `import ${isTypeImport ? 'type ' : ''}${defaultPart ? `${defaultPart}${nonDefaultPart ? ', ' : ''}` : ''}${nonDefaultPart ? `{ ${nonDefaultPart} }` : ''} from '${source}';`;
|
|
313
425
|
});
|
|
314
426
|
const newImports = [...namespaceImport, ...defaultImport, ...named].map((node) => {
|
|
315
|
-
node[SKIP] = true;
|
|
316
427
|
return node;
|
|
317
428
|
});
|
|
318
|
-
|
|
429
|
+
if (!state.file.metadata) {
|
|
430
|
+
state.file.metadata = {};
|
|
431
|
+
}
|
|
432
|
+
if (!state.file.metadata[filename]) {
|
|
433
|
+
state.file.metadata[filename] = [];
|
|
434
|
+
}
|
|
435
|
+
const modification = {
|
|
436
|
+
modificationCode: newImports.join('\n'),
|
|
437
|
+
start: path.node.start,
|
|
438
|
+
end: path.node.end,
|
|
439
|
+
loc: path.node.loc
|
|
440
|
+
};
|
|
441
|
+
state.file.metadata[filename].push(modification);
|
|
319
442
|
}
|
|
320
443
|
}
|
|
321
444
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare type CodeModification = {
|
|
2
|
+
modificationCode: string;
|
|
3
|
+
};
|
|
4
|
+
export declare type CodeChange = CodeModification;
|
|
5
|
+
export declare type CodeChangeWithLocation = CodeModification & MatchPosition;
|
|
6
|
+
export declare type MatchPosition = {
|
|
7
|
+
start: number;
|
|
8
|
+
end: number;
|
|
9
|
+
loc: Location;
|
|
10
|
+
};
|
|
11
|
+
declare type ModifyCodeAsTextParams = {
|
|
12
|
+
code: string;
|
|
13
|
+
modificationCode?: string;
|
|
14
|
+
alreadyChangedCodes?: string[];
|
|
15
|
+
location: Pick<MatchPosition, 'start' | 'end'>;
|
|
16
|
+
};
|
|
17
|
+
declare type ProcessCodeModificationsArrayParams = {
|
|
18
|
+
code: string;
|
|
19
|
+
changes: CodeChangeWithLocation[];
|
|
20
|
+
};
|
|
21
|
+
export declare const regExpTest: (regExp: RegExp, text: string) => boolean;
|
|
22
|
+
export declare function modifyCodeAsText({ code, modificationCode, location }: ModifyCodeAsTextParams): {
|
|
23
|
+
fileCode: string;
|
|
24
|
+
locationsChange: {
|
|
25
|
+
from: number;
|
|
26
|
+
to: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export declare function processTextCodeModificationsArray({ code, changes }: ProcessCodeModificationsArrayParams): string;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processTextCodeModificationsArray = exports.modifyCodeAsText = exports.regExpTest = void 0;
|
|
4
|
+
const regExpTest = (regExp, text) => {
|
|
5
|
+
if (!text) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const matches = text.match(regExp);
|
|
9
|
+
return matches !== null && matches.length > 0;
|
|
10
|
+
};
|
|
11
|
+
exports.regExpTest = regExpTest;
|
|
12
|
+
function modifyCodeAsText({ code, modificationCode, location }) {
|
|
13
|
+
let fileCode = code;
|
|
14
|
+
const codeBeforeMatch = fileCode.slice(0, location.start);
|
|
15
|
+
const codeAfterMatch = fileCode.slice(location.end);
|
|
16
|
+
const replacedCodeLength = location.end - location.start;
|
|
17
|
+
const replacementCodeLength = modificationCode.length;
|
|
18
|
+
const locationsChange = {
|
|
19
|
+
from: location.end,
|
|
20
|
+
to: location.end + replacementCodeLength - replacedCodeLength
|
|
21
|
+
};
|
|
22
|
+
fileCode = `${codeBeforeMatch}${modificationCode}${codeAfterMatch}`;
|
|
23
|
+
return { fileCode, locationsChange };
|
|
24
|
+
}
|
|
25
|
+
exports.modifyCodeAsText = modifyCodeAsText;
|
|
26
|
+
function processTextCodeModificationsArray({ code, changes }) {
|
|
27
|
+
let modifiedCode = code;
|
|
28
|
+
/**
|
|
29
|
+
* Include only changes that are unique by it's location.
|
|
30
|
+
* Remove changes that are inside range of other changes
|
|
31
|
+
*/
|
|
32
|
+
const pendingChanges = changes.filter((change, changeIdx) => !changes.some((otherChange, otherChangeIdx) => otherChangeIdx !== changeIdx &&
|
|
33
|
+
otherChange.start <= change.start &&
|
|
34
|
+
otherChange.end >= change.end &&
|
|
35
|
+
// insert changes has the same start and end to distinguish them from anchor node, that might have other changes attached
|
|
36
|
+
change.start !== change.end));
|
|
37
|
+
while (pendingChanges.length > 0) {
|
|
38
|
+
const change = pendingChanges.shift();
|
|
39
|
+
const { locationsChange, fileCode } = modifyCodeAsText({
|
|
40
|
+
code: modifiedCode,
|
|
41
|
+
modificationCode: change.modificationCode,
|
|
42
|
+
location: { start: change.start, end: change.end }
|
|
43
|
+
});
|
|
44
|
+
modifiedCode = fileCode;
|
|
45
|
+
pendingChanges.forEach((pendingChange) => {
|
|
46
|
+
if (pendingChange.start >= locationsChange.from) {
|
|
47
|
+
const diff = locationsChange.to - locationsChange.from;
|
|
48
|
+
pendingChange.end += diff;
|
|
49
|
+
pendingChange.start += diff;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return modifiedCode;
|
|
54
|
+
}
|
|
55
|
+
exports.processTextCodeModificationsArray = processTextCodeModificationsArray;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function template(template: string): (params: Record<string, string>) => string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.template = void 0;
|
|
4
|
+
function template(template) {
|
|
5
|
+
return (params) => {
|
|
6
|
+
let code = template.trim();
|
|
7
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
8
|
+
code = code.replace(new RegExp(`%%${key}%%`, 'g'), value);
|
|
9
|
+
});
|
|
10
|
+
return code;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
exports.template = template;
|
package/dist/babel/transform.js
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transform = void 0;
|
|
2
4
|
/*eslint-disable @typescript-eslint/no-var-requires */
|
|
3
5
|
const { getFilesList } = require('@codeque/core');
|
|
4
6
|
const babelCore = require('@babel/core');
|
|
7
|
+
const parser = require('@babel/parser');
|
|
5
8
|
const fs = require('fs');
|
|
6
9
|
const path = require('path');
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
console.error('Please provide correct transformation root');
|
|
11
|
-
process.exit(1);
|
|
12
|
-
}
|
|
13
|
-
;
|
|
14
|
-
(async () => {
|
|
10
|
+
const babelParsingOptions_1 = require("./babelParsingOptions");
|
|
11
|
+
const processCodeTextModificationsArray_1 = require("./processCodeTextModificationsArray");
|
|
12
|
+
const transform = async ({ rootPath, inputFilePath, includeBarrelExportFiles, excludeBarrelExportFiles }) => {
|
|
15
13
|
const root = path.resolve(rootPath);
|
|
16
14
|
const resolvedInputFilePath = inputFilePath
|
|
17
15
|
? path.join(root, inputFilePath)
|
|
@@ -25,19 +23,34 @@ if (!rootPath) {
|
|
|
25
23
|
});
|
|
26
24
|
const errors = [];
|
|
27
25
|
let progressCount = 0;
|
|
26
|
+
let cache = new Map();
|
|
28
27
|
for (const filePath of filesList) {
|
|
29
28
|
try {
|
|
30
29
|
const fileName = path.parse(filePath).name;
|
|
30
|
+
const fileContent = fs.readFileSync(filePath).toString();
|
|
31
31
|
const result = babelCore.transformFileSync(filePath, {
|
|
32
32
|
plugins: [
|
|
33
|
-
[
|
|
33
|
+
[
|
|
34
|
+
__dirname + '/index.js',
|
|
35
|
+
{
|
|
36
|
+
tsConfigPath: path.join(root, 'tsconfig.json'),
|
|
37
|
+
cache,
|
|
38
|
+
includeBarrelExportFiles,
|
|
39
|
+
excludeBarrelExportFiles
|
|
40
|
+
}
|
|
41
|
+
]
|
|
34
42
|
],
|
|
35
|
-
parserOpts:
|
|
36
|
-
plugins: ['typescript', 'jsx']
|
|
37
|
-
},
|
|
43
|
+
parserOpts: babelParsingOptions_1.babelParsingOptions,
|
|
38
44
|
filename: fileName
|
|
39
45
|
});
|
|
40
|
-
|
|
46
|
+
const changes = result.metadata[filePath];
|
|
47
|
+
if ((changes === null || changes === void 0 ? void 0 : changes.length) > 0) {
|
|
48
|
+
const resultCode = (0, processCodeTextModificationsArray_1.processTextCodeModificationsArray)({
|
|
49
|
+
code: fileContent,
|
|
50
|
+
changes
|
|
51
|
+
});
|
|
52
|
+
fs.writeFileSync(filePath, resultCode);
|
|
53
|
+
}
|
|
41
54
|
progressCount++;
|
|
42
55
|
if (progressCount % 100 === 0) {
|
|
43
56
|
console.log(`${progressCount}+${errors.length}/${filesList.length}`);
|
|
@@ -49,4 +62,5 @@ if (!rootPath) {
|
|
|
49
62
|
}
|
|
50
63
|
console.log(errors);
|
|
51
64
|
console.log(`Done: ${progressCount}/${filesList.length}; Failed: ${errors.length}`);
|
|
52
|
-
}
|
|
65
|
+
};
|
|
66
|
+
exports.transform = transform;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const rootPath = process.argv[2];
|
|
4
|
+
const inputFilePath = process.argv[3];
|
|
5
|
+
const transform_1 = require("./transform");
|
|
6
|
+
if (!rootPath) {
|
|
7
|
+
console.error('Please provide correct transformation root');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const run = async () => {
|
|
11
|
+
const startTime = new Date().getTime();
|
|
12
|
+
await (0, transform_1.transform)({
|
|
13
|
+
rootPath,
|
|
14
|
+
inputFilePath
|
|
15
|
+
});
|
|
16
|
+
console.log('Operation time: ', (new Date().getTime() - startTime) / 1000);
|
|
17
|
+
};
|
|
18
|
+
run();
|