rev-dep 0.3.0 → 1.0.0-alpha.2

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/README.md CHANGED
@@ -81,14 +81,14 @@ Available options are
81
81
  #### `find` Function
82
82
 
83
83
  ```js
84
- import { find } from 'rev-dep'
84
+ import { find } from "rev-dep";
85
85
 
86
86
  const path = find({
87
- entryPoints: ['index.js'],
88
- filePath: 'utils.js'
89
- })
87
+ entryPoints: ["index.js"],
88
+ filePath: "utils.js",
89
+ });
90
90
 
91
- console.log(path)
91
+ console.log(path);
92
92
  ```
93
93
 
94
94
  #### `find` Options
@@ -111,6 +111,94 @@ If you installed `rev-dep` **globally**, you will have appropriate compiler inst
111
111
 
112
112
  For example, to support `*.ts` and `*.tsx` implicit extensions in globally installed `rev-dep`, you have to also install globally `typescript` package (see [source](https://github.com/sverweij/dependency-cruiser/blob/96e34d0cf158034f2b7c8cafe9cec72dd74d8c45/src/extract/transpile/typescript-wrap.js))
113
113
 
114
+ ## CLI reference
115
+
116
+ <!-- cli-docs-start -->
117
+
118
+ ### Command `resolve`
119
+
120
+ Checks if a filePath is required from entryPoint(s) and prints the resolution path
121
+
122
+ #### Usage
123
+
124
+ ```sh
125
+ rev-dep resolve <filePath> [entryPoints...] [options]
126
+ ```
127
+
128
+ #### Arguments
129
+
130
+ - `filePath` - Path to a file that should be resolved in entry points (**required**),\* `entryPoints...` - List of entry points to look for file (_optional_)
131
+
132
+ #### Options
133
+
134
+ - `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support (_optional_)
135
+ - `--cwd <path>` - path to a directory that should be used as a resolution root (_optional_)
136
+ - `--rr reexportRewire <value>` - resolve actual dependencies for "export \* from" statements (_optional_)
137
+ - `-i include <globs...>` - A list of globs to determine files included in entry points search (_optional_)
138
+ - `-e exclude <globs...>` - A list of globs to determine files excluded in entry points search (_optional_)
139
+ - `-cs, --compactSummary` - print a compact summary of reverse resolution with a count of found paths (_optional_)
140
+ - `-a, --all` - finds all paths combination of a given dependency. Might work very slow or crash for some projects due to heavy usage of RAM (_optional_)
141
+
142
+ ### Command `entry-points`
143
+
144
+ Print list of entry points in current directory
145
+
146
+ #### Usage
147
+
148
+ ```sh
149
+ rev-dep entry-points [options]
150
+ ```
151
+
152
+ #### Options
153
+
154
+ - `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support (_optional_)
155
+ - `--cwd <path>` - path to a directory that should be used as a resolution root (_optional_)
156
+ - `--rr reexportRewire <value>` - resolve actual dependencies for "export \* from" statements (_optional_)
157
+ - `-i include <globs...>` - A list of globs to determine files included in entry points search (_optional_)
158
+ - `-e exclude <globs...>` - A list of globs to determine files excluded in entry points search (_optional_)
159
+ - `-pdc, --printDependenciesCount` - print count of entry point dependencies (_optional_)
160
+ - `-c, --count` - print just count of found entry points (_optional_)
161
+
162
+ ### Command `files`
163
+
164
+ Get list of files required by entry point
165
+
166
+ #### Usage
167
+
168
+ ```sh
169
+ rev-dep files <entryPoint> [options]
170
+ ```
171
+
172
+ #### Arguments
173
+
174
+ - `entryPoint` - Path to entry point (**required**)
175
+
176
+ #### Options
177
+
178
+ - `-wc, --webpackConfig <path>` - path to webpack config to enable webpack aliases support (_optional_)
179
+ - `--cwd <path>` - path to a directory that should be used as a resolution root (_optional_)
180
+ - `--rr reexportRewire <value>` - resolve actual dependencies for "export \* from" statements (_optional_)
181
+ - `-c, --count` - print only count of entry point dependencies (_optional_)
182
+
183
+ ### Command `docs`
184
+
185
+ Generate documentation of available commands into md file.
186
+
187
+ #### Usage
188
+
189
+ ```sh
190
+ rev-dep docs <outputPath> [options]
191
+ ```
192
+
193
+ #### Arguments
194
+
195
+ - `outputPath` - path to output \*.md file (**required**)
196
+
197
+ #### Options
198
+
199
+ - `-hl, --headerLevel <value>` - Initial header level (_optional_)
200
+ <!-- cli-docs-end -->
201
+
114
202
  ## Contributing
115
203
 
116
204
  Project is open to contributions, just rise an issue if you have some ideas about features or you noticed a bug. After discussion we can approach implementation :)
package/babel.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/babel/index.js')
package/bin.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('./dist/cli');
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ /*eslint-disable @typescript-eslint/no-var-requires */
3
+ const node_path = require('path');
4
+ const fs = require('fs');
5
+ const parser = require('@babel/parser');
6
+ const template = require('@babel/template').default;
7
+ const SKIP = Symbol('SKIP');
8
+ module.exports = function plugin({ types }, { tsConfigPath }) {
9
+ const tsConfig = require(tsConfigPath);
10
+ const aliases = tsConfig.compilerOptions.paths;
11
+ const aliasesKeys = Object.keys(aliases);
12
+ const aliasesRegexes = Object.keys(aliases).map((alias) => {
13
+ return new RegExp(`^${alias.replace('*', '(.)+')}$`);
14
+ });
15
+ const cache = new Map();
16
+ const getFile = (original, paths) => {
17
+ if (paths.length === 0) {
18
+ throw new Error('Cannot resolve import ' + original);
19
+ }
20
+ const path = paths[0];
21
+ try {
22
+ return [path, fs.readFileSync(path).toString()];
23
+ }
24
+ catch (e) {
25
+ return getFile(original, paths.slice(1));
26
+ }
27
+ };
28
+ const isPathRelativeOrAliased = (path) => {
29
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(path));
30
+ const isRelative = path.startsWith('./') || path.startsWith('../');
31
+ return aliasRegexIdx > -1 || isRelative;
32
+ };
33
+ const cacheKey = (identifier, filePath) => `${identifier}-${filePath}`;
34
+ const lookup = (identifier, filePath, cwd) => {
35
+ const cached = cache.get(cacheKey(identifier, filePath));
36
+ if (cached) {
37
+ return cached;
38
+ }
39
+ const withExtension = /(\.ts|\.tsx)$/.test(filePath)
40
+ ? [filePath]
41
+ : [
42
+ `${filePath}.ts`,
43
+ `${filePath}.tsx`,
44
+ `${filePath}/index.ts`,
45
+ `${filePath}/index.tsx`,
46
+ `${filePath}.js`,
47
+ `${filePath}.jsx`,
48
+ `${filePath}/index.js`,
49
+ `${filePath}/index.jsx`
50
+ ];
51
+ const [resolvedFilePath, file] = getFile(filePath, withExtension);
52
+ const ast = parser.parse(file, {
53
+ sourceType: 'module',
54
+ plugins: [
55
+ 'jsx',
56
+ 'typescript',
57
+ 'objectRestSpread',
58
+ 'classProperties',
59
+ 'asyncGenerators',
60
+ 'decorators-legacy'
61
+ ]
62
+ });
63
+ /**
64
+ * {
65
+ * identifier?: string,
66
+ * source: string
67
+ * }
68
+ */
69
+ const toLookup = [];
70
+ let resolvedAs = null;
71
+ ast.program.body.forEach((declaration) => {
72
+ var _a;
73
+ if (resolvedAs === null) {
74
+ if (types.isExportNamedDeclaration(declaration)) {
75
+ if (types.isVariableDeclaration(declaration.declaration)) {
76
+ const hasIdentifier = declaration.declaration.declarations.find((declarator) => {
77
+ return declarator.id.name === identifier;
78
+ });
79
+ if (hasIdentifier) {
80
+ resolvedAs = {
81
+ type: 'named',
82
+ identifier,
83
+ source: filePath
84
+ };
85
+ }
86
+ }
87
+ else if (types.isFunctionDeclaration(declaration.declaration) ||
88
+ types.isClassDeclaration(declaration.declaration)) {
89
+ if (declaration.declaration.id.name === identifier) {
90
+ resolvedAs = {
91
+ type: 'named',
92
+ identifier,
93
+ source: filePath
94
+ };
95
+ }
96
+ }
97
+ else {
98
+ const source = (_a = declaration.source) === null || _a === void 0 ? void 0 : _a.value;
99
+ declaration.specifiers.forEach((specifier) => {
100
+ if (types.isExportSpecifier(specifier)) {
101
+ if (specifier.exported.name === identifier) {
102
+ if (specifier.local.name === 'default' && source) {
103
+ resolvedAs = {
104
+ type: 'default',
105
+ identifier,
106
+ source: getModulePath(source, resolvedFilePath, cwd)
107
+ };
108
+ }
109
+ else if (source === undefined) {
110
+ resolvedAs = {
111
+ type: 'named',
112
+ identifier,
113
+ source: filePath
114
+ };
115
+ }
116
+ else if (isPathRelativeOrAliased(source)) {
117
+ toLookup.push({
118
+ identifier: specifier.exported.local,
119
+ source: getModulePath(source, resolvedFilePath, cwd)
120
+ });
121
+ }
122
+ }
123
+ }
124
+ });
125
+ }
126
+ }
127
+ else if (types.isExportAllDeclaration(declaration) &&
128
+ isPathRelativeOrAliased(declaration.source.value)) {
129
+ toLookup.push({
130
+ identifier,
131
+ source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
132
+ });
133
+ }
134
+ }
135
+ });
136
+ if (resolvedAs) {
137
+ return resolvedAs;
138
+ }
139
+ const nestedResult = toLookup
140
+ .map(({ identifier, source }) => lookup(identifier, source, cwd))
141
+ .filter(Boolean);
142
+ return nestedResult[0];
143
+ };
144
+ const getModulePath = (sourcePath, fileName, cwd) => {
145
+ var _a;
146
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
147
+ const relativeFileName = node_path.relative(cwd, fileName);
148
+ const aliasKey = aliasesKeys[aliasRegexIdx];
149
+ const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0];
150
+ let modulePath = '';
151
+ if (alias) {
152
+ let relative = alias;
153
+ if (aliasKey.endsWith('*')) {
154
+ const aliasKeyPrefix = aliasKey.replace('*', '');
155
+ relative = alias.replace('*', sourcePath.replace(aliasKeyPrefix, ''));
156
+ }
157
+ modulePath = node_path.resolve(cwd, relative);
158
+ }
159
+ else {
160
+ // we need ../ to skip current file name
161
+ modulePath = node_path.resolve(relativeFileName, '../' + sourcePath);
162
+ }
163
+ return modulePath;
164
+ };
165
+ return {
166
+ visitor: {
167
+ Program: {
168
+ enter(_, { filename }) {
169
+ //console.log(filename);
170
+ }
171
+ },
172
+ ImportDeclaration(path, { filename, cwd }) {
173
+ const sourceRelative = (source) => {
174
+ const rel = node_path.relative(node_path.dirname(filename), source);
175
+ return rel.startsWith('.') ? rel : './' + rel;
176
+ };
177
+ const node = path.node;
178
+ const source = node.source;
179
+ if (source.type !== 'StringLiteral') {
180
+ return;
181
+ }
182
+ const shouldSkip = node[SKIP] || !isPathRelativeOrAliased(source.value);
183
+ if (shouldSkip) {
184
+ return;
185
+ }
186
+ const modulePath = getModulePath(source.value, filename, cwd);
187
+ const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
188
+ const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier');
189
+ const specifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier');
190
+ const results = specifiers.map((specifier) => {
191
+ const importedName = specifier.imported.name;
192
+ const result = lookup(importedName, modulePath, cwd);
193
+ if (!result) {
194
+ return {
195
+ identifier: importedName,
196
+ local: specifier.local.name,
197
+ source: source.value
198
+ };
199
+ }
200
+ cache.set(cacheKey(importedName, modulePath), result);
201
+ return {
202
+ ...result,
203
+ source: sourceRelative(result.source),
204
+ local: specifier.local.name
205
+ };
206
+ });
207
+ const defaultResult = defaultSpecifier
208
+ ? lookup('default', modulePath, cwd)
209
+ : null;
210
+ if (defaultResult) {
211
+ cache.set(cacheKey('default', modulePath), defaultResult);
212
+ }
213
+ const buildNamed = template(`
214
+ import { %%IMPORT_NAME%% } from %%SOURCE%%;
215
+ `);
216
+ const buildNamedWithAlias = template(`
217
+ import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from %%SOURCE%%;
218
+ `);
219
+ const buildDefault = template(`
220
+ import %%IMPORT_NAME%% from %%SOURCE%%;
221
+ `);
222
+ const buildNamespace = template(`
223
+ import * as %%IMPORT_NAME%% from %%SOURCE%%;
224
+ `);
225
+ const defaultImport = defaultResult
226
+ ? [
227
+ buildDefault({
228
+ IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
229
+ SOURCE: types.stringLiteral(sourceRelative(defaultResult.source))
230
+ })
231
+ ]
232
+ : defaultSpecifier
233
+ ? [
234
+ buildDefault({
235
+ IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
236
+ SOURCE: types.stringLiteral(source.value)
237
+ })
238
+ ]
239
+ : [];
240
+ const namespaceImport = namespaceSpecifier
241
+ ? [
242
+ buildNamespace({
243
+ IMPORT_NAME: types.identifier(namespaceSpecifier.local.name),
244
+ SOURCE: types.stringLiteral(source.value)
245
+ })
246
+ ]
247
+ : [];
248
+ const named = results.map(({ type, identifier, local, source }) => {
249
+ if (type === 'default') {
250
+ return buildDefault({
251
+ IMPORT_NAME: types.identifier(identifier),
252
+ SOURCE: types.stringLiteral(source)
253
+ });
254
+ }
255
+ else if (identifier !== local) {
256
+ return buildNamedWithAlias({
257
+ IMPORTED_NAME: types.identifier(identifier),
258
+ LOCAL_NAME: types.identifier(local),
259
+ SOURCE: types.stringLiteral(source)
260
+ });
261
+ }
262
+ else {
263
+ return buildNamed({
264
+ IMPORT_NAME: types.identifier(identifier),
265
+ SOURCE: types.stringLiteral(source)
266
+ });
267
+ }
268
+ });
269
+ const newImports = [...namespaceImport, ...defaultImport, ...named].map((node) => {
270
+ node[SKIP] = true;
271
+ return node;
272
+ });
273
+ path.replaceWithMultiple(newImports);
274
+ }
275
+ }
276
+ };
277
+ };
@@ -0,0 +1,277 @@
1
+ "use strict";
2
+ /*eslint-disable @typescript-eslint/no-var-requires */
3
+ const node_path = require('path');
4
+ const fs = require('fs');
5
+ const parser = require('@babel/parser');
6
+ const template = require('@babel/template').default;
7
+ const SKIP = Symbol('SKIP');
8
+ module.exports = function plugin({ types }, { tsConfigPath }) {
9
+ const tsConfig = require(tsConfigPath);
10
+ const aliases = tsConfig.compilerOptions.paths;
11
+ const aliasesKeys = Object.keys(aliases);
12
+ const aliasesRegexes = Object.keys(aliases).map((alias) => {
13
+ return new RegExp(`^${alias.replace('*', '(.)+')}$`);
14
+ });
15
+ const cache = new Map();
16
+ const getFile = (original, paths) => {
17
+ if (paths.length === 0) {
18
+ throw new Error('Cannot resolve import ' + original);
19
+ }
20
+ const path = paths[0];
21
+ try {
22
+ return [path, fs.readFileSync(path).toString()];
23
+ }
24
+ catch (e) {
25
+ return getFile(original, paths.slice(1));
26
+ }
27
+ };
28
+ const isPathRelativeOrAliased = (path) => {
29
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(path));
30
+ const isRelative = path.startsWith('./') || path.startsWith('../');
31
+ return aliasRegexIdx > -1 || isRelative;
32
+ };
33
+ const cacheKey = (identifier, filePath) => `${identifier}-${filePath}`;
34
+ const lookup = (identifier, filePath, cwd) => {
35
+ const cached = cache.get(cacheKey(identifier, filePath));
36
+ if (cached) {
37
+ return cached;
38
+ }
39
+ const withExtension = /(\.ts|\.tsx)$/.test(filePath)
40
+ ? [filePath]
41
+ : [
42
+ `${filePath}.ts`,
43
+ `${filePath}.tsx`,
44
+ `${filePath}/index.ts`,
45
+ `${filePath}/index.tsx`,
46
+ `${filePath}.js`,
47
+ `${filePath}.jsx`,
48
+ `${filePath}/index.js`,
49
+ `${filePath}/index.jsx`
50
+ ];
51
+ const [resolvedFilePath, file] = getFile(filePath, withExtension);
52
+ const ast = parser.parse(file, {
53
+ sourceType: 'module',
54
+ plugins: [
55
+ 'jsx',
56
+ 'typescript',
57
+ 'objectRestSpread',
58
+ 'classProperties',
59
+ 'asyncGenerators',
60
+ 'decorators-legacy'
61
+ ]
62
+ });
63
+ /**
64
+ * {
65
+ * identifier?: string,
66
+ * source: string
67
+ * }
68
+ */
69
+ const toLookup = [];
70
+ let resolvedAs = null;
71
+ ast.program.body.forEach((declaration) => {
72
+ var _a;
73
+ if (resolvedAs === null) {
74
+ if (types.isExportNamedDeclaration(declaration)) {
75
+ if (types.isVariableDeclaration(declaration.declaration)) {
76
+ const hasIdentifier = declaration.declaration.declarations.find((declarator) => {
77
+ return declarator.id.name === identifier;
78
+ });
79
+ if (hasIdentifier) {
80
+ resolvedAs = {
81
+ type: 'named',
82
+ identifier,
83
+ source: filePath
84
+ };
85
+ }
86
+ }
87
+ else if (types.isFunctionDeclaration(declaration.declaration) ||
88
+ types.isClassDeclaration(declaration.declaration)) {
89
+ if (declaration.declaration.id.name === identifier) {
90
+ resolvedAs = {
91
+ type: 'named',
92
+ identifier,
93
+ source: filePath
94
+ };
95
+ }
96
+ }
97
+ else {
98
+ const source = (_a = declaration.source) === null || _a === void 0 ? void 0 : _a.value;
99
+ declaration.specifiers.forEach((specifier) => {
100
+ if (types.isExportSpecifier(specifier)) {
101
+ if (specifier.exported.name === identifier) {
102
+ if (specifier.local.name === 'default' && source) {
103
+ resolvedAs = {
104
+ type: 'default',
105
+ identifier,
106
+ source: getModulePath(source, resolvedFilePath, cwd)
107
+ };
108
+ }
109
+ else if (source === undefined) {
110
+ resolvedAs = {
111
+ type: 'named',
112
+ identifier,
113
+ source: filePath
114
+ };
115
+ }
116
+ else if (isPathRelativeOrAliased(source)) {
117
+ toLookup.push({
118
+ identifier: specifier.exported.local,
119
+ source: getModulePath(source, resolvedFilePath, cwd)
120
+ });
121
+ }
122
+ }
123
+ }
124
+ });
125
+ }
126
+ }
127
+ else if (types.isExportAllDeclaration(declaration) &&
128
+ isPathRelativeOrAliased(declaration.source.value)) {
129
+ toLookup.push({
130
+ identifier,
131
+ source: getModulePath(declaration.source.value, resolvedFilePath, cwd)
132
+ });
133
+ }
134
+ }
135
+ });
136
+ if (resolvedAs) {
137
+ return resolvedAs;
138
+ }
139
+ const nestedResult = toLookup
140
+ .map(({ identifier, source }) => lookup(identifier, source, cwd))
141
+ .filter(Boolean);
142
+ return nestedResult[0];
143
+ };
144
+ const getModulePath = (sourcePath, fileName, cwd) => {
145
+ var _a;
146
+ const aliasRegexIdx = aliasesRegexes.findIndex((aliasRegex) => aliasRegex.test(sourcePath));
147
+ const relativeFileName = node_path.relative(cwd, fileName);
148
+ const aliasKey = aliasesKeys[aliasRegexIdx];
149
+ const alias = (_a = aliases[aliasKey]) === null || _a === void 0 ? void 0 : _a[0];
150
+ let modulePath = '';
151
+ if (alias) {
152
+ let relative = alias;
153
+ if (aliasKey.endsWith('*')) {
154
+ const aliasKeyPrefix = aliasKey.replace('*', '');
155
+ relative = alias.replace('*', sourcePath.replace(aliasKeyPrefix, ''));
156
+ }
157
+ modulePath = node_path.resolve(cwd, relative);
158
+ }
159
+ else {
160
+ // we need ../ to skip current file name
161
+ modulePath = node_path.resolve(relativeFileName, '../' + sourcePath);
162
+ }
163
+ return modulePath;
164
+ };
165
+ return {
166
+ visitor: {
167
+ Program: {
168
+ enter(_, { filename }) {
169
+ //console.log(filename);
170
+ }
171
+ },
172
+ ImportDeclaration(path, { filename, cwd }) {
173
+ const sourceRelative = (source) => {
174
+ const rel = node_path.relative(node_path.dirname(filename), source);
175
+ return rel.startsWith('.') ? rel : './' + rel;
176
+ };
177
+ const node = path.node;
178
+ const source = node.source;
179
+ if (source.type !== 'StringLiteral') {
180
+ return;
181
+ }
182
+ const shouldSkip = node[SKIP] || !isPathRelativeOrAliased(source.value);
183
+ if (shouldSkip) {
184
+ return;
185
+ }
186
+ const modulePath = getModulePath(source.value, filename, cwd);
187
+ const defaultSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
188
+ const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === 'ImportNamespaceSpecifier');
189
+ const specifiers = node.specifiers.filter((specifier) => specifier.type === 'ImportSpecifier');
190
+ const results = specifiers.map((specifier) => {
191
+ const importedName = specifier.imported.name;
192
+ const result = lookup(importedName, modulePath, cwd);
193
+ if (!result) {
194
+ return {
195
+ identifier: importedName,
196
+ local: specifier.local.name,
197
+ source: source.value
198
+ };
199
+ }
200
+ cache.set(cacheKey(importedName, modulePath), result);
201
+ return {
202
+ ...result,
203
+ source: sourceRelative(result.source),
204
+ local: specifier.local.name
205
+ };
206
+ });
207
+ const defaultResult = defaultSpecifier
208
+ ? lookup('default', modulePath, cwd)
209
+ : null;
210
+ if (defaultResult) {
211
+ cache.set(cacheKey('default', modulePath), defaultResult);
212
+ }
213
+ const buildNamed = template(`
214
+ import { %%IMPORT_NAME%% } from %%SOURCE%%;
215
+ `);
216
+ const buildNamedWithAlias = template(`
217
+ import { %%IMPORTED_NAME%% as %%LOCAL_NAME%% } from %%SOURCE%%;
218
+ `);
219
+ const buildDefault = template(`
220
+ import %%IMPORT_NAME%% from %%SOURCE%%;
221
+ `);
222
+ const buildNamespace = template(`
223
+ import * as %%IMPORT_NAME%% from %%SOURCE%%;
224
+ `);
225
+ const defaultImport = defaultResult
226
+ ? [
227
+ buildDefault({
228
+ IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
229
+ SOURCE: types.stringLiteral(sourceRelative(defaultResult.source))
230
+ })
231
+ ]
232
+ : defaultSpecifier
233
+ ? [
234
+ buildDefault({
235
+ IMPORT_NAME: types.identifier(defaultSpecifier.local.name),
236
+ SOURCE: types.stringLiteral(source.value)
237
+ })
238
+ ]
239
+ : [];
240
+ const namespaceImport = namespaceSpecifier
241
+ ? [
242
+ buildNamespace({
243
+ IMPORT_NAME: types.identifier(namespaceSpecifier.local.name),
244
+ SOURCE: types.stringLiteral(source.value)
245
+ })
246
+ ]
247
+ : [];
248
+ const named = results.map(({ type, identifier, local, source }) => {
249
+ if (type === 'default') {
250
+ return buildDefault({
251
+ IMPORT_NAME: types.identifier(identifier),
252
+ SOURCE: types.stringLiteral(source)
253
+ });
254
+ }
255
+ else if (identifier !== local) {
256
+ return buildNamedWithAlias({
257
+ IMPORTED_NAME: types.identifier(identifier),
258
+ LOCAL_NAME: types.identifier(local),
259
+ SOURCE: types.stringLiteral(source)
260
+ });
261
+ }
262
+ else {
263
+ return buildNamed({
264
+ IMPORT_NAME: types.identifier(identifier),
265
+ SOURCE: types.stringLiteral(source)
266
+ });
267
+ }
268
+ });
269
+ const newImports = [...namespaceImport, ...defaultImport, ...named].map((node) => {
270
+ node[SKIP] = true;
271
+ return node;
272
+ });
273
+ path.replaceWithMultiple(newImports);
274
+ }
275
+ }
276
+ };
277
+ };