@putout/plugin-nodejs 19.1.0 → 19.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
@@ -33,12 +33,16 @@ npm i putout @putout/plugin-nodejs -D
33
33
  - ✅ [group-require-by-id](#group-require-by-id);
34
34
  - ✅ [remove-process-exit](#remove-process-exit);
35
35
  - ✅ [remove-useless-promisify](#remove-useless-promisify);
36
- - ✅ [rename-file-cjs-to-js](#rename-file-cjs-to-js);
37
- - ✅ [rename-file-mjs-to-js](#rename-file-mjs-to-js);
38
36
  - ✅ [remove-useless-strict-mode](#remove-useless-strict-mode);
39
37
  - ✅ [remove-illegal-strict-mode](#remove-useless-strict-mode);
38
+
39
+ ## File rules
40
+
41
+ - ✅ [apply-privately-imported-file](#apply-privately-imported-file);
40
42
  - ✅ [cjs-file](#cjs-file);
41
43
  - ✅ [mjs-file](#mjs-file);
44
+ - ✅ [rename-file-cjs-to-js](#rename-file-cjs-to-js);
45
+ - ✅ [rename-file-mjs-to-js](#rename-file-mjs-to-js);
42
46
 
43
47
  ## Config
44
48
 
@@ -587,6 +591,40 @@ export const readSize = promisify(async (dir, options, callback) => {});
587
591
  export const readSize = async (dir, options, callback) => {};
588
592
  ```
589
593
 
594
+ #### apply-privately-required-to-file
595
+
596
+ > Entries in the imports field must be strings starting with `#`.
597
+ > Package imports permit mapping to external packages.
598
+ > This field defines subpath imports for the current package.
599
+ >
600
+ > (c) [nodejs.org](https://nodejs.org/api/packages.html#imports)
601
+
602
+ Let's consider file structure:
603
+
604
+ ```
605
+ /
606
+ |-- package.json {"imports": {"#is: {"default": "./lib/tokenize/is.js"}}}
607
+ |-- lib/
608
+ | `-- tokenize/
609
+ | `-- is.js "export const isPrev = () => {}"
610
+ | `-- expressions/
611
+ `-- spread-element.js "const {isPrev} = require('../is.js')"
612
+ ```
613
+
614
+ In this case `spread-element.js` can be fixed:
615
+
616
+ #### ❌ Example of incorrect code
617
+
618
+ ```js
619
+ const {isPrev} = require('../is.js');
620
+ ```
621
+
622
+ #### ✅ Example of correct code
623
+
624
+ ```js
625
+ const {isPrev} = require('#is');
626
+ ```
627
+
590
628
  ## License
591
629
 
592
630
  MIT
@@ -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
+ [`require('${from}')`]: `require('${to}')`,
10
+ };
11
+ };
@@ -0,0 +1,28 @@
1
+ import {types} from 'putout';
2
+
3
+ const {isStringLiteral} = types;
4
+
5
+ export const report = (path) => {
6
+ const [arg] = path.node.arguments;
7
+ return arg.value;
8
+ };
9
+
10
+ export const fix = () => {};
11
+
12
+ export const include = () => [
13
+ 'require(__a)',
14
+ ];
15
+
16
+ export const filter = (path) => {
17
+ const [arg] = path.node.arguments;
18
+
19
+ if (!isStringLiteral(arg))
20
+ return false;
21
+
22
+ const {value} = arg;
23
+
24
+ if (!value.startsWith('.'))
25
+ return false;
26
+
27
+ return /\.[mc]?js/.test(value);
28
+ };
@@ -0,0 +1,148 @@
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 './get-require/index.js';
14
+ import * as changeImports from './change-require/index.js';
15
+
16
+ const isString = (a) => typeof a === 'string';
17
+
18
+ const {
19
+ getFilename,
20
+ readFileContent,
21
+ writeFileContent,
22
+ findFileUp,
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 required source: '${from}' -> '${to}'`;
31
+ export const fix = (file, {content, ast, from, to}) => {
32
+ transform(ast, content, {
33
+ rules: {
34
+ 'change-require': ['on', {
35
+ from,
36
+ to,
37
+ }],
38
+ },
39
+ plugins: [
40
+ ['change-require', 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
+ '*.cjs',
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('require'))
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-require', 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);
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 [dir, importsCache.get(dir)];
101
+
102
+ const [packageDirectory, packagePath] = findFileUp(file, 'package.json');
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, property] of entries(imports)) {
122
+ const filePath = parseProperty(property);
123
+
124
+ if (!filePath)
125
+ continue;
126
+
127
+ const resolvedPath = resolve(packageDirectory, filePath);
128
+
129
+ importsEntries.set(resolvedPath, alias);
130
+ }
131
+
132
+ importsCache.set(dir, [packageDirectory, importsEntries]);
133
+
134
+ return [packageDirectory, importsEntries];
135
+ };
136
+
137
+ function parseProperty(property) {
138
+ if (isString(property))
139
+ return property;
140
+
141
+ const {
142
+ default: filePath,
143
+ node,
144
+ browser,
145
+ } = property;
146
+
147
+ return filePath || node || browser;
148
+ }
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import * as applyPrivatelyRequiredFiles from './apply-privately-required-file/index.js';
1
2
  import * as convertBufferToBufferAlloc from './convert-buffer-to-buffer-alloc/index.js';
2
3
  import * as convertFsPromises from './convert-fs-promises/index.js';
3
4
  import * as convertPromisifyToFsPromises from './convert-promisify-to-fs-promises/index.js';
@@ -32,6 +33,7 @@ export const rules = {
32
33
  'add-node-prefix': addNodePrefix,
33
34
  'convert-exports-to-module-exports': convertExportsToModuleExports,
34
35
 
36
+ 'apply-privately-required-files': ['off', applyPrivatelyRequiredFiles],
35
37
  'convert-esm-to-commonjs': ['off', convertEsmToCommonjs],
36
38
  'convert-commonjs-to-esm/exports': ['off', convertCommonjsToEsm.rules.exports],
37
39
  'convert-commonjs-to-esm/common': ['off', convertCommonjsToEsm.rules.commons],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/plugin-nodejs",
3
- "version": "19.1.0",
3
+ "version": "19.2.0",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "🐊Putout plugin adds ability to transform code to new API of Node.js",
@@ -30,7 +30,8 @@
30
30
  "report": "madrun report"
31
31
  },
32
32
  "dependencies": {
33
- "just-camel-case": "^6.2.0"
33
+ "just-camel-case": "^6.2.0",
34
+ "try-catch": "^4.0.7"
34
35
  },
35
36
  "keywords": [
36
37
  "putout",
@@ -39,7 +40,7 @@
39
40
  "nodejs"
40
41
  ],
41
42
  "devDependencies": {
42
- "@putout/eslint-flat": "^3.0.0",
43
+ "@putout/eslint-flat": "^4.0.0",
43
44
  "@putout/plugin-declare": "*",
44
45
  "@putout/plugin-declare-before-reference": "*",
45
46
  "@putout/plugin-esm": "*",