@putout/plugin-esm 6.5.1 → 7.0.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
@@ -35,6 +35,7 @@ npm i putout @putout/plugin-esm -D
35
35
  ## File rules
36
36
 
37
37
  - ✅ [apply-namespace-import-file](#resolve-imported-file);
38
+ - ✅ [apply-privately-imported-file](#apply-privately-imported-file);
38
39
  - ✅ [resolve-imported-file](#resolve-imported-file);
39
40
  - ✅ [shorten-imported-file](#shorten-imported-file);
40
41
 
@@ -59,6 +60,7 @@ npm i putout @putout/plugin-esm -D
59
60
  "esm/resolve-imported-file": "off",
60
61
  "esm/shorten-imported-file": "off",
61
62
  "esm/apply-namespace-of-file": "off",
63
+ "esm/apply-privately-imported-file": "off",
62
64
  "esm/remove-useless-export-specifiers": "off"
63
65
  }
64
66
  }
@@ -249,34 +251,22 @@ import ss from '../../bb/ss.js';
249
251
  const c = 5;
250
252
  ```
251
253
 
252
- ### merge-duplicate-imports
254
+ ### merge-duplicate-imports/join
253
255
 
254
- #### join
255
-
256
- To disable use:
257
-
258
- ```json
259
- {
260
- "rules": {
261
- "esm/merge-duplicate-imports-join": "off"
262
- }
263
- }
264
- ```
265
-
266
- ##### ❌ Example of incorrect code
256
+ #### ❌ Example of incorrect code
267
257
 
268
258
  ```js
269
259
  import test from 'supertape';
270
260
  import {stub} from 'supertape';
271
261
  ```
272
262
 
273
- ##### ✅ Example of correct code
263
+ #### ✅ Example of correct code
274
264
 
275
265
  ```js
276
266
  import test, {stub} from 'supertape';
277
267
  ```
278
268
 
279
- #### rename
269
+ ### merge-duplicate-imports/rename
280
270
 
281
271
  Checkout in 🐊[**Putout Editor**](https://putout.cloudcmd.io/#/gist/6604936dec6b1eed8ce0d143f2962f15/17b310a6e4d85b0b8615a8b91d0e27414e8af291).
282
272
  To disable use:
@@ -289,7 +279,7 @@ To disable use:
289
279
  }
290
280
  ```
291
281
 
292
- ##### ❌ Example of incorrect code
282
+ #### ❌ Example of incorrect code
293
283
 
294
284
  ```js
295
285
  import putout from './putout.js';
@@ -300,7 +290,7 @@ console.log(all);
300
290
  console.log(x);
301
291
  ```
302
292
 
303
- ##### ✅ Example of correct code
293
+ #### ✅ Example of correct code
304
294
 
305
295
  ```js
306
296
  import putout from './putout.js';
@@ -444,6 +434,45 @@ import a from './a.js';
444
434
  import * as a from './a.js';
445
435
  ```
446
436
 
437
+ ### apply-privately-imported-to-file
438
+
439
+ > Entries in the imports field must be strings starting with `#`.
440
+ > Package imports permit mapping to external packages.
441
+ > This field defines subpath imports for the current package.
442
+ >
443
+ > (c) [nodejs.org](https://nodejs.org/api/packages.html#imports)
444
+
445
+ Check out in 🐊**Putout Editor**:
446
+
447
+ - ✅ [`get-imports`](https://putout.cloudcmd.io/#/gist/5d7687215e9fbdf705935c444503dded/75a98d2db9d3847c73017e41637924b1cfd5a598);
448
+ - ✅ [`change-imports`](https://putout.cloudcmd.io/#/gist/23a6dc6741b772c03fbed95feda2b451/1fbecac6fc40282bcda0593aa666a8c213ef85b7);
449
+
450
+ Let's consider file structure:
451
+
452
+ ```
453
+ /
454
+ |-- package.json {"imports": {"#is: {"default": "./lib/tokenize/is.js"}}}
455
+ |-- lib/
456
+ | `-- tokenize/
457
+ | `-- is.js "export const isPrev = () => {}"
458
+ | `-- expressions/
459
+ `-- spread-element.js "import {isPrev} from '../is.js"
460
+ ```
461
+
462
+ In this case `spread-element.js` can be fixed:
463
+
464
+ #### ❌ Example of incorrect code
465
+
466
+ ```js
467
+ import {isPrev} from '../is.js';
468
+ ```
469
+
470
+ #### ✅ Example of correct code
471
+
472
+ ```js
473
+ import {isPrev} from '#is';
474
+ ```
475
+
447
476
  ### resolve-imported-file
448
477
 
449
478
  Check out in 🐊**Putout Editor**:
@@ -0,0 +1,151 @@
1
+ import {
2
+ join,
3
+ dirname,
4
+ resolve,
5
+ } from 'node:path';
6
+ import {tryCatch} from 'try-catch';
7
+ import {
8
+ parse,
9
+ print,
10
+ transform,
11
+ operator,
12
+ } from 'putout';
13
+ import * as getImports from '../shorten-imported-file/get-imports/index.js';
14
+ import * as changeImports from '../resolve-imported-file/change-imports/index.js';
15
+
16
+ const {
17
+ getFilename,
18
+ getFileType,
19
+ getParentDirectory,
20
+ readFileContent,
21
+ writeFileContent,
22
+ readDirectory,
23
+ } = operator;
24
+
25
+ const {entries} = Object;
26
+ const {parse: parseJson} = JSON;
27
+
28
+ const getMessage = (a) => a.message;
29
+
30
+ export const report = (file, {from, to}) => `Apply privately imported source: '${from}' -> '${to}'`;
31
+ export const fix = (file, {content, ast, from, to}) => {
32
+ transform(ast, content, {
33
+ rules: {
34
+ 'change-imports': ['on', {
35
+ from,
36
+ to,
37
+ }],
38
+ },
39
+ plugins: [
40
+ ['change-imports', changeImports],
41
+ ],
42
+ });
43
+
44
+ const newContent = print(ast);
45
+
46
+ writeFileContent(file, newContent);
47
+ };
48
+
49
+ export const scan = (rootPath, {push, trackFile}) => {
50
+ const mask = [
51
+ '*.js',
52
+ '*.mjs',
53
+ ];
54
+
55
+ const getPrivateImports = createGetPrivateImports();
56
+
57
+ for (const file of trackFile(rootPath, mask)) {
58
+ const content = readFileContent(file);
59
+
60
+ if (!content.includes('import'))
61
+ continue;
62
+
63
+ const [, privateImports] = getPrivateImports(file);
64
+
65
+ if (!privateImports.size)
66
+ continue;
67
+
68
+ const ast = parse(content);
69
+
70
+ const places = transform(ast, content, {
71
+ plugins: [
72
+ ['get-imports', getImports],
73
+ ],
74
+ });
75
+
76
+ const imports = places.map(getMessage);
77
+
78
+ const filename = getFilename(file);
79
+ const dir = dirname(filename);
80
+
81
+ for (const from of imports) {
82
+ const to = join(dir, from).replace(dir, '.');
83
+
84
+ if (privateImports.has(to))
85
+ push(file, {
86
+ from,
87
+ to: privateImports.get(to),
88
+ content,
89
+ ast,
90
+ });
91
+ }
92
+ }
93
+ };
94
+
95
+ const createGetPrivateImports = (importsCache = new Map(), emptyMap = new Map()) => (file) => {
96
+ const filename = getFilename(file);
97
+ const dir = dirname(filename);
98
+
99
+ if (importsCache.has(dir))
100
+ return importsCache.get(dir);
101
+
102
+ const [packageDirectory, packagePath] = findPackage(file);
103
+
104
+ if (!packagePath) {
105
+ importsCache.set(dir, {});
106
+ return ['', emptyMap];
107
+ }
108
+
109
+ const packageContent = readFileContent(packagePath);
110
+ const [error, packageJson] = tryCatch(parseJson, packageContent);
111
+
112
+ if (error) {
113
+ importsCache.set(dir, emptyMap);
114
+
115
+ return ['', emptyMap];
116
+ }
117
+
118
+ const {imports = {}} = packageJson;
119
+ const importsEntries = new Map();
120
+
121
+ for (const [alias, {default: filePath}] of entries(imports)) {
122
+ const resolvedPath = resolve(packageDirectory, filePath);
123
+ importsEntries.set(resolvedPath, alias);
124
+ }
125
+
126
+ importsCache.set(dir, [packageDirectory, importsEntries]);
127
+
128
+ return [packageDirectory, importsEntries];
129
+ };
130
+
131
+ function findPackage(file) {
132
+ const parentDirectory = getParentDirectory(file);
133
+ const directoryName = getFilename(parentDirectory);
134
+
135
+ for (const currentFile of readDirectory(parentDirectory)) {
136
+ const type = getFileType(currentFile);
137
+
138
+ if (type === 'directory')
139
+ continue;
140
+
141
+ const currentName = getFilename(currentFile);
142
+
143
+ if (currentName.endsWith('package.json'))
144
+ return [directoryName, currentFile];
145
+ }
146
+
147
+ if (directoryName === '/')
148
+ return [];
149
+
150
+ return findPackage(parentDirectory);
151
+ }
package/lib/index.js CHANGED
@@ -2,9 +2,6 @@ import * as applyExportFrom from './apply-export-from/index.js';
2
2
  import * as mergeExportDeclarations from './merge-export-declarations/index.js';
3
3
  import * as removeUselessExportSpecifiers from './remove-useless-export-specifiers/index.js';
4
4
  import * as mergeDeclarationWithExport from './merge-declaration-with-export/index.js';
5
- import * as applyNamespaceImportToFile from './apply-namespace-import-to-file/index.js';
6
- import * as resolveImportedFile from './resolve-imported-file/index.js';
7
- import * as shortenImportedFile from './shorten-imported-file/index.js';
8
5
  import * as addIndexToImport from './add-index-to-import/index.js';
9
6
  import * as declareImportsFirst from './declare-imports-first/index.js';
10
7
  import * as groupImportsBySource from './group-imports-by-source/index.js';
@@ -14,6 +11,10 @@ import * as removeEmptyImport from './remove-empty-import/index.js';
14
11
  import * as removeEmptyExport from './remove-empty-export/index.js';
15
12
  import * as mergeDuplicateImports from './merge-duplicate-imports/index.js';
16
13
  import * as convertAssertToWith from './convert-assert-to-with/index.js';
14
+ import * as applyNamespaceImportToFile from './apply-namespace-import-to-file/index.js';
15
+ import * as applyPrivatelyImportedFile from './apply-privately-imported-file/index.js';
16
+ import * as resolveImportedFile from './resolve-imported-file/index.js';
17
+ import * as shortenImportedFile from './shorten-imported-file/index.js';
17
18
 
18
19
  export const rules = {
19
20
  'add-index-to-import': ['off', addIndexToImport],
@@ -26,10 +27,12 @@ export const rules = {
26
27
  'remove-empty-import': removeEmptyImport,
27
28
  'remove-empty-export': removeEmptyExport,
28
29
  'sort-imports-by-specifiers': sortImportsBySpecifiers,
29
- 'resolve-imported-file': ['off', resolveImportedFile],
30
- 'shorten-imported-file': ['off', shortenImportedFile],
31
- 'apply-namespace-import-to-file': ['off', applyNamespaceImportToFile],
32
30
  'merge-declaration-with-export': mergeDeclarationWithExport,
33
31
  'remove-useless-export-specifiers': removeUselessExportSpecifiers,
34
32
  'merge-export-declarations': mergeExportDeclarations,
33
+
34
+ 'resolve-imported-file': ['off', resolveImportedFile],
35
+ 'shorten-imported-file': ['off', shortenImportedFile],
36
+ 'apply-namespace-import-to-file': ['off', applyNamespaceImportToFile],
37
+ 'apply-privately-imported-file': ['off', applyPrivatelyImportedFile],
35
38
  };
@@ -2,6 +2,6 @@ import * as mergeDuplicateImportsJoin from './join/index.js';
2
2
  import * as mergeDuplicateImportsRename from './rename/index.js';
3
3
 
4
4
  export const rules = {
5
- 'merge-duplicate-imports-join': mergeDuplicateImportsJoin,
6
- 'merge-duplicate-imports-rename': mergeDuplicateImportsRename,
5
+ 'merge-duplicate-imports/join': mergeDuplicateImportsJoin,
6
+ 'merge-duplicate-imports/rename': mergeDuplicateImportsRename,
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/plugin-esm",
3
- "version": "6.5.1",
3
+ "version": "7.0.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",