@putout/plugin-esm 4.0.0 → 4.1.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/README.md CHANGED
@@ -27,6 +27,7 @@ npm i putout @putout/plugin-esm -D
27
27
  - ✅ [remove-empty-import](#remove-empty-import);
28
28
  - ✅ [remove-empty-export](#remove-empty-export);
29
29
  - ✅ [sort-imports-by-specifiers](#sort-imports-by-specifiers);
30
+ - ✅ [resolve-imported-file](#resolve-imported-file);
30
31
 
31
32
  ## Config
32
33
 
@@ -43,7 +44,8 @@ npm i putout @putout/plugin-esm -D
43
44
  "esm/remove-empty-import": ["on", {
44
45
  "ignore": []
45
46
  }],
46
- "esm/sort-imports-by-specifiers": "on"
47
+ "esm/sort-imports-by-specifiers": "on",
48
+ "esm/resolve-imported-file": "on"
47
49
  }
48
50
  }
49
51
  ```
@@ -73,7 +75,6 @@ import addAction from './add-action/index.js';
73
75
  export const rules = {};
74
76
  ```
75
77
 
76
-
77
78
  ### apply-export-from
78
79
 
79
80
  > The `export` declaration is used to export values from a JavaScript module.
@@ -305,6 +306,37 @@ import('foo.json', {
305
306
  });
306
307
  ```
307
308
 
309
+ ### resolve-imported-file
310
+
311
+ Check out in 🐊**Putout Editor**:
312
+
313
+ - ✅ [`resolve-imported-file`](https://putout.cloudcmd.io/#/gist/241489cb2781dd37ec96baf0115cde4e/83c2f2e9f490850b7fda432f8d25ae6a64ed07e3);
314
+ - ✅ [`get-imports`](https://putout.cloudcmd.io/#/gist/ee10100fed86e4db926885dd54298668/7538bca7a9ae006d976f41261c0ed4c0e1902ace);
315
+ - ✅ [`change-imports`](https://putout.cloudcmd.io/#/gist/23a6dc6741b772c03fbed95feda2b451/1fbecac6fc40282bcda0593aa666a8c213ef85b7);
316
+
317
+ Let's consider file structure:
318
+
319
+ ```
320
+ /
321
+ |-- lib/
322
+ | `-- index.js
323
+ | `-- a.js
324
+ ```
325
+
326
+ In this case `index.js` can be fixed:
327
+
328
+ #### ❌ Example of incorrect code
329
+
330
+ ```js
331
+ import a from './a';
332
+ ```
333
+
334
+ #### ✅ Example of correct code
335
+
336
+ ```js
337
+ import a from './a.js';
338
+ ```
339
+
308
340
  ## License
309
341
 
310
342
  MIT
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import * as resolveImportedFile from './resolve-imported-file/index.js';
1
2
  import * as addIndexToImport from './add-index-to-import/index.js';
2
3
  import * as declareImportsFirst from './declare-imports-first/index.js';
3
4
  import * as groupImportsBySource from './group-imports-by-source/index.js';
@@ -10,7 +11,7 @@ import * as convertAssertToWith from './convert-assert-to-with/index.js';
10
11
  import * as applyExportFrom from './apply-export-from/index.js';
11
12
 
12
13
  export const rules = {
13
- 'add-index-to-import': addIndexToImport,
14
+ 'add-index-to-import': ['off', addIndexToImport],
14
15
  'apply-export-from': applyExportFrom,
15
16
  'convert-assert-to-with': convertAssertToWith,
16
17
  'declare-imports-first': declareImportsFirst,
@@ -20,4 +21,5 @@ export const rules = {
20
21
  'remove-empty-import': removeEmptyImport,
21
22
  'remove-empty-export': removeEmptyExport,
22
23
  'sort-imports-by-specifiers': sortImportsBySpecifiers,
24
+ 'resolve-imported-file': ['off', resolveImportedFile],
23
25
  };
@@ -0,0 +1,11 @@
1
+ export const report = () => '';
2
+ export const replace = ({options}) => {
3
+ const {from = '', to = ''} = options;
4
+
5
+ if (!from || !to)
6
+ return {};
7
+
8
+ return {
9
+ [`import __imports from '${from}'`]: `import __imports from '${to}'`,
10
+ };
11
+ };
@@ -0,0 +1,16 @@
1
+ export const report = (path) => path.node.source.value;
2
+
3
+ export const fix = () => {};
4
+
5
+ export const include = () => [
6
+ 'ImportDeclaration',
7
+ ];
8
+
9
+ export const filter = (path) => {
10
+ const {value} = path.node.source;
11
+
12
+ if (!value.startsWith('.'))
13
+ return false;
14
+
15
+ return !/\.[m|c]?js/.test(value);
16
+ };
@@ -0,0 +1,121 @@
1
+ import {join, dirname} from 'node:path';
2
+ import {
3
+ parse,
4
+ print,
5
+ transform,
6
+ operator,
7
+ } from 'putout';
8
+ import * as getImportsSource from './get-imports-source/index.js';
9
+ import * as changeImports from './change-imports/index.js';
10
+
11
+ const {
12
+ findFile,
13
+ getFilename,
14
+ readFileContent,
15
+ writeFileContent,
16
+ } = operator;
17
+
18
+ const getMessage = (a) => a.message;
19
+
20
+ export const report = (file, {from, to}) => `Resolve import source: '${from}' -> '${to}'`;
21
+ export const fix = (file, {content, ast, from, to}) => {
22
+ transform(ast, content, {
23
+ rules: {
24
+ 'change-imports': ['on', {
25
+ from,
26
+ to,
27
+ }],
28
+ },
29
+ plugins: [
30
+ ['change-imports', changeImports],
31
+ ],
32
+ });
33
+
34
+ const newContent = print(ast);
35
+
36
+ writeFileContent(file, newContent);
37
+ };
38
+
39
+ export const scan = (rootPath, {push, trackFile}) => {
40
+ const mask = [
41
+ '*.js',
42
+ '*.mjs',
43
+ ];
44
+
45
+ for (const file of trackFile(rootPath, mask)) {
46
+ const content = readFileContent(file);
47
+
48
+ if (!content.includes('import'))
49
+ continue;
50
+
51
+ const ast = parse(content);
52
+
53
+ const places = transform(ast, content, {
54
+ plugins: [
55
+ ['get-imports-source', getImportsSource],
56
+ ],
57
+ });
58
+
59
+ const imports = places.map(getMessage);
60
+ const filename = getFilename(file);
61
+ const dir = dirname(filename);
62
+ const importsTuples = buildImports(dir, imports);
63
+ const resolvedTuples = buildResolved(rootPath, importsTuples);
64
+
65
+ for (const [from, to] of resolvedTuples) {
66
+ push(file, {
67
+ from,
68
+ to,
69
+ content,
70
+ ast,
71
+ });
72
+ }
73
+ }
74
+ };
75
+
76
+ function buildImports(dir, imports) {
77
+ const list = [];
78
+
79
+ for (const current of imports) {
80
+ const full = join(dir, current);
81
+ list.push([current, full]);
82
+ }
83
+
84
+ return list;
85
+ }
86
+
87
+ function buildResolved(rootPath, importsTuples) {
88
+ const result = [];
89
+
90
+ for (const [relative, current] of importsTuples) {
91
+ const withIndex = join(current, 'index.js');
92
+ const withJs = `${current}.js`;
93
+
94
+ if (findFile(rootPath, withIndex).length) {
95
+ result.push([relative, `${relative}/index.js`]);
96
+ continue;
97
+ }
98
+
99
+ if (relative === '..') {
100
+ const withPackage = join(current, 'package.json');
101
+ const [packageJson] = findFile(rootPath, withPackage);
102
+
103
+ if (!packageJson)
104
+ continue;
105
+
106
+ const json = readFileContent(packageJson);
107
+ const {main} = JSON.parse(json);
108
+
109
+ result.push([relative, join(relative, main)]);
110
+
111
+ continue;
112
+ }
113
+
114
+ if (findFile(rootPath, withJs).length) {
115
+ result.push([relative, `${relative}.js`]);
116
+ continue;
117
+ }
118
+ }
119
+
120
+ return result;
121
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/plugin-esm",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "🐊Putout plugin improves ability to transform ESM code",