@putout/plugin-esm 8.0.2 → 8.2.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
@@ -34,7 +34,7 @@ npm i putout @putout/plugin-esm -D
34
34
 
35
35
  ## File rules
36
36
 
37
- - ✅ [apply-namespace-import-file](#resolve-imported-file);
37
+ - ✅ [apply-import-by-type-to-file](#apply-import-by-type-to-file]);
38
38
  - ✅ [apply-privately-imported-file](#apply-privately-imported-file);
39
39
  - ✅ [apply-js-imported-file](#apply-js-imported-file);
40
40
  - ✅ [resolve-imported-file](#resolve-imported-file);
@@ -61,7 +61,7 @@ npm i putout @putout/plugin-esm -D
61
61
  "esm/apply-js-imported-file": "off",
62
62
  "esm/resolve-imported-file": "off",
63
63
  "esm/shorten-imported-file": "off",
64
- "esm/apply-namespace-of-file": "off",
64
+ "esm/apply-import-by-type-to-file": "off",
65
65
  "esm/apply-privately-imported-file": "off",
66
66
  "esm/remove-useless-export-specifiers": "off"
67
67
  }
@@ -399,7 +399,7 @@ import('foo.json', {
399
399
 
400
400
  ## File Rules
401
401
 
402
- ### apply-namespace-import-to-file
402
+ ### apply-import-by-type-to-file
403
403
 
404
404
  The rule fixes:
405
405
 
@@ -413,6 +413,33 @@ Check out in 🐊**Putout Editor**:
413
413
  - ✅ [`apply-namespace-import`](https://putout.cloudcmd.io/#/gist/23a6dc6741b772c03fbed95feda2b451/1fbecac6fc40282bcda0593aa666a8c213ef85b7);
414
414
  - ✅ [`is-esm`](https://putout.cloudcmd.io/#/gist/fa080be2bf3a6560e289d84b5873c2bc/2601091f6bf97148843767968c3afcb36dde31de);
415
415
 
416
+ #### named import
417
+
418
+ Let's consider file structure:
419
+
420
+ ```
421
+ /
422
+ |-- lib/
423
+ | `-- index.js "import a from './a.js';"
424
+ | `-- a.js "export const a = 2;"
425
+ ```
426
+
427
+ In this case `index.js` can be fixed:
428
+
429
+ ##### ❌ Example of incorrect code
430
+
431
+ ```js
432
+ import a from './a.js';
433
+ ```
434
+
435
+ ##### ✅ Example of correct code
436
+
437
+ ```js
438
+ import {a} from './a.js';
439
+ ```
440
+
441
+ #### namespace import
442
+
416
443
  Let's consider file structure:
417
444
 
418
445
  ```
@@ -424,13 +451,13 @@ Let's consider file structure:
424
451
 
425
452
  In this case `index.js` can be fixed:
426
453
 
427
- #### ❌ Example of incorrect code
454
+ ##### ❌ Example of incorrect code
428
455
 
429
456
  ```js
430
457
  import a from './a.js';
431
458
  ```
432
459
 
433
- #### ✅ Example of correct code
460
+ ##### ✅ Example of correct code
434
461
 
435
462
  ```js
436
463
  import * as a from './a.js';
@@ -0,0 +1,16 @@
1
+ export const report = (path) => {
2
+ const source = path.node.source.value;
3
+ const {specifiers} = path.node;
4
+ const [{local}] = specifiers;
5
+ const {name} = local;
6
+
7
+ return `'import ${name} from "${source}"' -> 'import {${name}} from "${source}"'`;
8
+ };
9
+
10
+ export const replace = ({options}) => {
11
+ const {name, source} = options;
12
+
13
+ return {
14
+ [`import ${name} from "${source}"`]: `import {${name}} from "${source}"`,
15
+ };
16
+ };
@@ -0,0 +1,59 @@
1
+ import {putout, operator} from 'putout';
2
+ import * as hasExportDefaultPlugin from '#has-export-default';
3
+ import * as isESMPlugin from '#is-esm';
4
+
5
+ const isESM = (a) => a.rule === 'is-esm';
6
+ const hasExportDefault = (a) => a.rule === 'has-export-default';
7
+
8
+ const {
9
+ findFile,
10
+ readFileContent,
11
+ } = operator;
12
+
13
+ export const determineImportType = ({name, rootPath, importedFilename, privateImports}) => {
14
+ const parsedName = parseImportedFilename({
15
+ importedFilename,
16
+ privateImports,
17
+ });
18
+
19
+ const [importedFile] = findFile(rootPath, parsedName);
20
+
21
+ if (!importedFile)
22
+ return '';
23
+
24
+ const importedContent = readFileContent(importedFile);
25
+
26
+ const {places} = putout(importedContent, {
27
+ fix: false,
28
+ plugins: [
29
+ ['has-export-default', hasExportDefaultPlugin],
30
+ ['is-esm', isESMPlugin],
31
+ ],
32
+ });
33
+
34
+ const esm = places.filter(isESM);
35
+
36
+ if (!esm.length)
37
+ return '';
38
+
39
+ const defaultExport = places.filter(hasExportDefault);
40
+
41
+ if (defaultExport.length)
42
+ return '';
43
+
44
+ for (const {message} of esm) {
45
+ const [, exportName] = message.split(':');
46
+
47
+ if (name === exportName)
48
+ return 'equal';
49
+ }
50
+
51
+ return 'named';
52
+ };
53
+
54
+ function parseImportedFilename({importedFilename, privateImports}) {
55
+ if (privateImports.has(importedFilename))
56
+ return privateImports.get(importedFilename);
57
+
58
+ return importedFilename;
59
+ }
@@ -1,45 +1,48 @@
1
1
  import {join, dirname} from 'node:path';
2
2
  import {tryCatch} from 'try-catch';
3
- import putout, {
3
+ import {
4
4
  parse,
5
5
  print,
6
6
  transform,
7
7
  operator,
8
8
  } from 'putout';
9
9
  import {createGetPrivateImports} from '#private-imports';
10
- import * as isESMPlugin from './is-esm/index.js';
11
- import * as hasExportDefaultPlugin from './has-export-default/index.js';
12
- import * as applyNamespaceImportPlugin from './apply-namespace-import/index.js';
13
- import * as getImportsPlugin from './get-imports/index.js';
10
+ import * as getImportsPlugin from '#get-default-imports';
11
+ import {determineImportType} from '#determine-import-type';
12
+ import {transformNamedImport} from './transform-named-import.js';
13
+ import {transformNamespaceImport} from './transform-namespace-import.js';
14
14
 
15
15
  const {
16
- findFile,
17
16
  getFilename,
18
17
  readFileContent,
19
18
  writeFileContent,
20
19
  } = operator;
21
20
 
22
21
  const getMessage = (a) => a.message;
23
- const isESM = (a) => a.rule === 'is-esm';
24
- const hasExportDefault = (a) => a.rule === 'has-export-default';
25
22
 
26
- export const report = (file, {name, source}) => {
23
+ export const report = (file, {importType, name, source}) => {
27
24
  const filename = getFilename(file);
28
- return `Use 'import * as ${name} from '${source}' in '${filename}'`;
25
+
26
+ if (importType === 'equal')
27
+ return `Use \`import {${name}} from '${source}'\` in '${filename}'`;
28
+
29
+ return `Use \`import * as ${name} from '${source}'\` in '${filename}'`;
29
30
  };
30
31
 
31
- export const fix = (file, {name, source, content, ast}) => {
32
- transform(ast, content, {
33
- rules: {
34
- 'apply-namespace-import': ['on', {
35
- name,
36
- source,
37
- }],
38
- },
39
- plugins: [
40
- ['apply-namespace-import', applyNamespaceImportPlugin],
41
- ],
42
- });
32
+ export const fix = (file, {name, source, content, ast, importType}) => {
33
+ if (importType === 'equal')
34
+ transformNamedImport(ast, {
35
+ name,
36
+ source,
37
+ content,
38
+ });
39
+
40
+ if (importType === 'named')
41
+ transformNamespaceImport(ast, {
42
+ name,
43
+ source,
44
+ content,
45
+ });
43
46
 
44
47
  const newContent = print(ast);
45
48
 
@@ -68,17 +71,18 @@ export const scan = (rootPath, {push, trackFile}) => {
68
71
  });
69
72
 
70
73
  for (const [name, source, importedFilename] of importsTuples) {
71
- const is = hasImportDefault({
74
+ const importType = determineImportType({
72
75
  name,
73
76
  rootPath,
74
77
  importedFilename,
75
78
  privateImports,
76
79
  });
77
80
 
78
- if (is)
81
+ if (!importType)
79
82
  continue;
80
83
 
81
84
  push(file, {
85
+ importType,
82
86
  name,
83
87
  source,
84
88
  ast,
@@ -107,50 +111,6 @@ function getImports(file, content, ast) {
107
111
  return buildImports(dir, imports);
108
112
  }
109
113
 
110
- function parseImportedFilename({importedFilename, privateImports}) {
111
- if (privateImports.has(importedFilename))
112
- return privateImports.get(importedFilename);
113
-
114
- return importedFilename;
115
- }
116
-
117
- function hasImportDefault({name, rootPath, importedFilename, privateImports}) {
118
- const parsedName = parseImportedFilename({
119
- importedFilename,
120
- privateImports,
121
- });
122
-
123
- const [importedFile] = findFile(rootPath, parsedName);
124
-
125
- if (!importedFile)
126
- return true;
127
-
128
- const importedContent = readFileContent(importedFile);
129
-
130
- const {places} = putout(importedContent, {
131
- fix: false,
132
- plugins: [
133
- ['has-export-default', hasExportDefaultPlugin],
134
- ['is-esm', isESMPlugin],
135
- ],
136
- });
137
-
138
- const esm = places.filter(isESM);
139
- const defaultExport = places.filter(hasExportDefault);
140
-
141
- if (defaultExport.length)
142
- return true;
143
-
144
- for (const {message} of esm) {
145
- const [, exportName] = message.split(':');
146
-
147
- if (name === exportName)
148
- return true;
149
- }
150
-
151
- return !esm.length;
152
- }
153
-
154
114
  function parseFull(dir, source) {
155
115
  if (source.startsWith('#'))
156
116
  return source;
@@ -0,0 +1,16 @@
1
+ import {transform} from 'putout';
2
+ import * as applyNamedImportPlugin from './apply-named-import/index.js';
3
+
4
+ export const transformNamedImport = (ast, {name, source, content}) => {
5
+ transform(ast, content, {
6
+ rules: {
7
+ 'apply-named-import': ['on', {
8
+ name,
9
+ source,
10
+ }],
11
+ },
12
+ plugins: [
13
+ ['apply-named-import', applyNamedImportPlugin],
14
+ ],
15
+ });
16
+ };
@@ -0,0 +1,16 @@
1
+ import {transform} from 'putout';
2
+ import * as applyNamespaceImportPlugin from './apply-namespace-import/index.js';
3
+
4
+ export const transformNamespaceImport = (ast, {source, content, name}) => {
5
+ transform(ast, content, {
6
+ rules: {
7
+ 'apply-namespace-import': ['on', {
8
+ name,
9
+ source,
10
+ }],
11
+ },
12
+ plugins: [
13
+ ['apply-namespace-import', applyNamespaceImportPlugin],
14
+ ],
15
+ });
16
+ };
package/lib/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as applyExportFrom from './apply-export-from/index.js';
2
2
  import * as applyJsImportedFile from './apply-js-imported-file/index.js';
3
+ import * as applyImportByTypeToFile from './apply-import-by-type-to-file/index.js';
3
4
  import * as mergeExportDeclarations from './merge-export-declarations/index.js';
4
5
  import * as removeUselessExportSpecifiers from './remove-useless-export-specifiers/index.js';
5
6
  import * as mergeDeclarationWithExport from './merge-declaration-with-export/index.js';
@@ -12,7 +13,6 @@ import * as removeEmptyImport from './remove-empty-import/index.js';
12
13
  import * as removeEmptyExport from './remove-empty-export/index.js';
13
14
  import * as mergeDuplicateImports from './merge-duplicate-imports/index.js';
14
15
  import * as convertAssertToWith from './convert-assert-to-with/index.js';
15
- import * as applyNamespaceImportToFile from './apply-namespace-import-to-file/index.js';
16
16
  import * as applyPrivatelyImportedFile from './apply-privately-imported-file/index.js';
17
17
  import * as resolveImportedFile from './resolve-imported-file/index.js';
18
18
  import * as shortenImportedFile from './shorten-imported-file/index.js';
@@ -34,7 +34,7 @@ export const rules = {
34
34
 
35
35
  'resolve-imported-file': ['off', resolveImportedFile],
36
36
  'shorten-imported-file': ['off', shortenImportedFile],
37
- 'apply-namespace-import-to-file': ['off', applyNamespaceImportToFile],
37
+ 'apply-import-by-type-to-file': ['off', applyImportByTypeToFile],
38
38
  'apply-privately-imported-file': ['off', applyPrivatelyImportedFile],
39
39
  'apply-js-imported-file': ['off', applyJsImportedFile],
40
40
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/plugin-esm",
3
- "version": "8.0.2",
3
+ "version": "8.2.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",
@@ -12,8 +12,12 @@
12
12
  },
13
13
  "imports": {
14
14
  "#get-imports": "./lib/shorten-imported-file/get-imports/index.js",
15
+ "#get-default-imports": "./lib/apply-import-by-type-to-file/get-imports/index.js",
15
16
  "#change-imports": "./lib/resolve-imported-file/change-imports/index.js",
16
- "#private-imports": "./lib/apply-privately-imported-file/private-imports.js"
17
+ "#private-imports": "./lib/apply-privately-imported-file/private-imports.js",
18
+ "#is-esm": "./lib/apply-import-by-type-to-file/is-esm/index.js",
19
+ "#has-export-default": "./lib/apply-import-by-type-to-file/has-export-default/index.js",
20
+ "#determine-import-type": "./lib/apply-import-by-type-to-file/determine-import-type.js"
17
21
  },
18
22
  "release": false,
19
23
  "tag": false,