@putout/plugin-esm 6.5.0 → 6.6.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 +42 -1
- package/lib/apply-privately-imported-file/index.js +151 -0
- package/lib/index.js +9 -6
- package/package.json +1 -1
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
|
}
|
|
@@ -444,6 +446,45 @@ import a from './a.js';
|
|
|
444
446
|
import * as a from './a.js';
|
|
445
447
|
```
|
|
446
448
|
|
|
449
|
+
### apply-privately-imported-to-file
|
|
450
|
+
|
|
451
|
+
> Entries in the imports field must be strings starting with `#`.
|
|
452
|
+
> Package imports permit mapping to external packages.
|
|
453
|
+
> This field defines subpath imports for the current package.
|
|
454
|
+
>
|
|
455
|
+
> (c) [nodejs.org](https://nodejs.org/api/packages.html#imports)
|
|
456
|
+
|
|
457
|
+
Check out in 🐊**Putout Editor**:
|
|
458
|
+
|
|
459
|
+
- ✅ [`get-imports`](https://putout.cloudcmd.io/#/gist/5d7687215e9fbdf705935c444503dded/75a98d2db9d3847c73017e41637924b1cfd5a598);
|
|
460
|
+
- ✅ [`change-imports`](https://putout.cloudcmd.io/#/gist/23a6dc6741b772c03fbed95feda2b451/1fbecac6fc40282bcda0593aa666a8c213ef85b7);
|
|
461
|
+
|
|
462
|
+
Let's consider file structure:
|
|
463
|
+
|
|
464
|
+
```
|
|
465
|
+
/
|
|
466
|
+
|-- package.json {"imports": {"#is: {"default": "./lib/tokenize/is.js"}}}
|
|
467
|
+
|-- lib/
|
|
468
|
+
| `-- tokenize/
|
|
469
|
+
| `-- is.js "export const isPrev = () => {}"
|
|
470
|
+
| `-- expressions/
|
|
471
|
+
`-- spread-element.js "import {isPrev} from '../is.js"
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
In this case `spread-element.js` can be fixed:
|
|
475
|
+
|
|
476
|
+
#### ❌ Example of incorrect code
|
|
477
|
+
|
|
478
|
+
```js
|
|
479
|
+
import {isPrev} from '../is.js';
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
#### ✅ Example of correct code
|
|
483
|
+
|
|
484
|
+
```js
|
|
485
|
+
import {isPrev} from '#is';
|
|
486
|
+
```
|
|
487
|
+
|
|
447
488
|
### resolve-imported-file
|
|
448
489
|
|
|
449
490
|
Check out in 🐊**Putout Editor**:
|
|
@@ -488,7 +529,7 @@ Let's consider file structure:
|
|
|
488
529
|
/
|
|
489
530
|
|-- processors/
|
|
490
531
|
| `-- index.js
|
|
491
|
-
| `-- parse-
|
|
532
|
+
| `-- parse-processor-names.js
|
|
492
533
|
```
|
|
493
534
|
|
|
494
535
|
In this case `index.js` can be fixed:
|
|
@@ -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
|
};
|
package/package.json
CHANGED