@putout/plugin-esm 3.0.0 → 4.1.0

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
@@ -18,6 +18,7 @@ npm i putout @putout/plugin-esm -D
18
18
 
19
19
  ## Rules
20
20
 
21
+ - ✅ [add-index-to-import](#add-index-to-import);
21
22
  - ✅ [apply-export-from](#apply-export-from);
22
23
  - ✅ [declare-imports-first](#declare-imports-first);
23
24
  - ✅ [group-imports-by-source](#group-imports-by-source);
@@ -26,12 +27,14 @@ npm i putout @putout/plugin-esm -D
26
27
  - ✅ [remove-empty-import](#remove-empty-import);
27
28
  - ✅ [remove-empty-export](#remove-empty-export);
28
29
  - ✅ [sort-imports-by-specifiers](#sort-imports-by-specifiers);
30
+ - ✅ [resolve-imported-file](#resolve-imported-file);
29
31
 
30
32
  ## Config
31
33
 
32
34
  ```json
33
35
  {
34
36
  "rules": {
37
+ "esm/add-index-to-import": "on",
35
38
  "esm/apply-export-from": "on",
36
39
  "esm/declare-imports-first": "on",
37
40
  "esm/group-imports-by-source": "on",
@@ -41,20 +44,46 @@ npm i putout @putout/plugin-esm -D
41
44
  "esm/remove-empty-import": ["on", {
42
45
  "ignore": []
43
46
  }],
44
- "esm/sort-imports-by-specifiers": "on"
47
+ "esm/sort-imports-by-specifiers": "on",
48
+ "esm/resolve-imported-file": "on"
45
49
  }
46
50
  }
47
51
  ```
48
52
 
49
- ## apply-export-from
53
+ ## Rules
54
+
55
+ ### add-index-to-import
56
+
57
+ ESM doesn't add `index.js`, so it can be left after [`@putout/plugin-convert-esm-to-commonjs`](https://github.com/coderaiser/putout/blob/master/packages/plugin-convert-esm-to-commonjs#readme).
58
+ Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/b7c489710767efee95ecf3dd16e232a2/9f974f0a345ef4d0cb39b011097dff82e6c32b75).
59
+
60
+ #### ❌ Example of incorrect code
61
+
62
+ ```js
63
+ import insertRust from './insert-rust.js';
64
+ import addAction from './add-action.js';
65
+
66
+ export const rules = {};
67
+ ```
68
+
69
+ #### ✅ Example of correct code
70
+
71
+ ```js
72
+ import insertRust from './insert-rust/index.js';
73
+ import addAction from './add-action/index.js';
74
+
75
+ export const rules = {};
76
+ ```
77
+
78
+ ### apply-export-from
50
79
 
51
80
  > The `export` declaration is used to export values from a JavaScript module.
52
81
  >
53
82
  > (c) [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)
54
83
 
55
- Check out in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/c9a3983d269745da89c1c7560f3b7fac/3ecb9aa6b910ce3816605bae11c8dd86bdc457e5).
84
+ Check out in 🐊[**Putout Editor**](https://putout.cloudcmd.io/##/gist/c9a3983d269745da89c1c7560f3b7fac/3ecb9aa6b910ce3816605bae11c8dd86bdc457e5).
56
85
 
57
- ## ❌ Example of incorrect code
86
+ #### ❌ Example of incorrect code
58
87
 
59
88
  ```js
60
89
  import * as ns_1 from 'x';
@@ -64,24 +93,24 @@ export {
64
93
  };
65
94
  ```
66
95
 
67
- ## ✅ Example of correct code
96
+ #### ✅ Example of correct code
68
97
 
69
98
  ```js
70
99
  export * as ns from 'x';
71
100
  ```
72
101
 
73
- ## declare-imports-first
102
+ ### declare-imports-first
74
103
 
75
104
  Check out in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/b1c18e5d726afe4ebb69d6b7a7dda82b/8189590815a1b8adb35bb8a846e28228e3c7fadf). For **CommonJS** use [nodejs/declare-after-require](https://github.com/coderaiser/putout/tree/master/packages/plugin-nodejs#declare-after-require).
76
105
 
77
- ## ❌ Example of incorrect code
106
+ #### ❌ Example of incorrect code
78
107
 
79
108
  ```js
80
109
  const [arg] = process.argv;
81
110
  import esbuild from 'esbuild';
82
111
  ```
83
112
 
84
- ## ✅ Example of correct code
113
+ #### ✅ Example of correct code
85
114
 
86
115
  ```js
87
116
  import esbuild from 'esbuild';
@@ -89,7 +118,7 @@ import esbuild from 'esbuild';
89
118
  const [arg] = process.argv;
90
119
  ```
91
120
 
92
- ## group-imports-by-source
121
+ ### group-imports-by-source
93
122
 
94
123
  Group order:
95
124
 
@@ -100,7 +129,7 @@ Group order:
100
129
 
101
130
  Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/3cc782acf95211f9d456d63a99032ee1/0674223d050bba572f5271ffdccf8616cb441af5).
102
131
 
103
- ## ❌ Example of incorrect code
132
+ #### ❌ Example of incorrect code
104
133
 
105
134
  ```js
106
135
  import fs from 'node:fs';
@@ -114,7 +143,7 @@ import parse from '#parser';
114
143
  const c = 5;
115
144
  ```
116
145
 
117
- ## ✅ Example of correct code
146
+ #### ✅ Example of correct code
118
147
 
119
148
  ```js
120
149
  import fs from 'node:fs';
@@ -128,9 +157,9 @@ import ss from '../../bb/ss.js';
128
157
  const c = 5;
129
158
  ```
130
159
 
131
- ## merge-duplicate-imports
160
+ ### merge-duplicate-imports
132
161
 
133
- ### join
162
+ #### join
134
163
 
135
164
  To disable use:
136
165
 
@@ -142,20 +171,20 @@ To disable use:
142
171
  }
143
172
  ```
144
173
 
145
- #### ❌ Example of incorrect code
174
+ ##### ❌ Example of incorrect code
146
175
 
147
176
  ```js
148
177
  import test from 'supertape';
149
178
  import {stub} from 'supertape';
150
179
  ```
151
180
 
152
- #### ✅ Example of correct code
181
+ ##### ✅ Example of correct code
153
182
 
154
183
  ```js
155
184
  import test, {stub} from 'supertape';
156
185
  ```
157
186
 
158
- ### rename
187
+ #### rename
159
188
 
160
189
  Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/6604936dec6b1eed8ce0d143f2962f15/17b310a6e4d85b0b8615a8b91d0e27414e8af291).
161
190
 
@@ -169,7 +198,7 @@ To disable use:
169
198
  }
170
199
  ```
171
200
 
172
- #### ❌ Example of incorrect code
201
+ ##### ❌ Example of incorrect code
173
202
 
174
203
  ```js
175
204
  import putout from './putout.js';
@@ -180,7 +209,7 @@ console.log(all);
180
209
  console.log(x);
181
210
  ```
182
211
 
183
- #### ✅ Example of correct code
212
+ ##### ✅ Example of correct code
184
213
 
185
214
  ```js
186
215
  import putout from './putout.js';
@@ -189,39 +218,39 @@ console.log(putout);
189
218
  console.log(putout);
190
219
  ```
191
220
 
192
- ## remove-empty-export
221
+ ### remove-empty-export
193
222
 
194
223
  ```diff
195
224
  -export {};
196
225
  ```
197
226
 
198
- ## remove-empty-import
227
+ ### remove-empty-import
199
228
 
200
229
  ```diff
201
230
  -import 'abc';
202
231
  ```
203
232
 
204
- ## remove-quotes-from-import-assertions
233
+ ### remove-quotes-from-import-assertions
205
234
 
206
235
  Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/f9f34acddbefba0ded53225ca10fa44e/7b4dba44602b9b2d28fe3a98989474a4b0d8d73d).
207
236
 
208
- ### ❌ Example of incorrect code
237
+ #### ❌ Example of incorrect code
209
238
 
210
239
  ```js
211
240
  import json from './mod.json' with { type: 'json' };
212
241
  ```
213
242
 
214
- ## ✅ Example of correct code
243
+ #### ✅ Example of correct code
215
244
 
216
245
  ```js
217
246
  import json from './mod.json' with { type: 'json' };
218
247
  ```
219
248
 
220
- ## sort-imports-by-specifiers
249
+ ### sort-imports-by-specifiers
221
250
 
222
251
  Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/521e2ff199243a7ce1f65db7140c272e/28c0588281286f8a6765b8aa2ecabbfcde2973a7).
223
252
 
224
- ### ❌ Example of incorrect code
253
+ #### ❌ Example of incorrect code
225
254
 
226
255
  ```js
227
256
  import {
@@ -233,7 +262,7 @@ import {
233
262
  import a1 from 'a1';
234
263
  ```
235
264
 
236
- ### ✅ Example of correct code
265
+ #### ✅ Example of correct code
237
266
 
238
267
  ```js
239
268
  import a1 from 'a1';
@@ -245,7 +274,7 @@ import {
245
274
  } from 'd';
246
275
  ```
247
276
 
248
- ## convert-assert-to-with
277
+ ### convert-assert-to-with
249
278
 
250
279
  > This feature would ideally use the `with` keyword to denote attributes, but there are existing implementations based on a previous version of the proposal using the `assert` keyword. Due to potential web compatibility risks, the proposal still includes `assert` marked as deprecated. Usage of the old syntax is discouraged, and its removal is being investigated.
251
280
  >
@@ -253,7 +282,7 @@ import {
253
282
 
254
283
  Check out in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/9f85897b998c6458efc19db6a5414b79/57ef7cdd113c7a0087e0f7a6e70522f60baa04f4).
255
284
 
256
- ## ❌ Example of incorrect code
285
+ #### ❌ Example of incorrect code
257
286
 
258
287
  ```js
259
288
  import json from './foo.json' assert { type: 'json' };
@@ -265,7 +294,7 @@ import('foo.json', {
265
294
  });
266
295
  ```
267
296
 
268
- ## ✅ Example of correct code
297
+ #### ✅ Example of correct code
269
298
 
270
299
  ```js
271
300
  import json from './foo.json' with { type: 'json' };
@@ -277,6 +306,37 @@ import('foo.json', {
277
306
  });
278
307
  ```
279
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
+
280
340
  ## License
281
341
 
282
342
  MIT
@@ -0,0 +1,31 @@
1
+ import {extname} from 'node:path';
2
+ import {operator} from 'putout';
3
+
4
+ const {setLiteralValue} = operator;
5
+
6
+ export const report = (path) => {
7
+ const {value} = path.node.source;
8
+ return `Add 'index.js' to import: '${value}' -> '${value}/index.js'`;
9
+ };
10
+
11
+ export const fix = (path) => {
12
+ const {source} = path.node;
13
+ const {value} = source;
14
+
15
+ setLiteralValue(source, `${value}/index.js`);
16
+ };
17
+
18
+ export const traverse = ({push}) => ({
19
+ ImportDeclaration: (path) => {
20
+ const {value} = path.node.source;
21
+ const ext = extname(value);
22
+
23
+ if (ext)
24
+ return;
25
+
26
+ if (!value.startsWith('.'))
27
+ return;
28
+
29
+ push(path);
30
+ },
31
+ });
package/lib/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import * as resolveImportedFile from './resolve-imported-file/index.js';
2
+ import * as addIndexToImport from './add-index-to-import/index.js';
1
3
  import * as declareImportsFirst from './declare-imports-first/index.js';
2
4
  import * as groupImportsBySource from './group-imports-by-source/index.js';
3
5
  import * as removeQuotesFromImportAssertions from './remove-quotes-from-import-assertions/index.js';
@@ -9,13 +11,15 @@ import * as convertAssertToWith from './convert-assert-to-with/index.js';
9
11
  import * as applyExportFrom from './apply-export-from/index.js';
10
12
 
11
13
  export const rules = {
12
- ...mergeDuplicateImports.rules,
14
+ 'add-index-to-import': addIndexToImport,
15
+ 'apply-export-from': applyExportFrom,
16
+ 'convert-assert-to-with': convertAssertToWith,
13
17
  'declare-imports-first': declareImportsFirst,
14
18
  'group-imports-by-source': groupImportsBySource,
19
+ ...mergeDuplicateImports.rules,
15
20
  'remove-quotes-from-import-assertions': removeQuotesFromImportAssertions,
16
21
  'remove-empty-import': removeEmptyImport,
17
22
  'remove-empty-export': removeEmptyExport,
18
23
  'sort-imports-by-specifiers': sortImportsBySpecifiers,
19
- 'convert-assert-to-with': convertAssertToWith,
20
- 'apply-export-from': applyExportFrom,
24
+ 'resolve-imported-file': ['off', resolveImportedFile],
21
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": "3.0.0",
3
+ "version": "4.1.0",
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",
@@ -56,7 +56,7 @@
56
56
  "supertape": "^11.0.3"
57
57
  },
58
58
  "peerDependencies": {
59
- "putout": ">=39"
59
+ "putout": ">=40"
60
60
  },
61
61
  "license": "MIT",
62
62
  "engines": {