@prowise/eslint-config-linting-rules 1.2.2 → 1.2.4

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/backend.js CHANGED
@@ -8,8 +8,8 @@ module.exports = {
8
8
 
9
9
  // For Node, we require that you add extensions (.js) to every Javascript/Typescript file.
10
10
  plugins: [
11
- "eslint-plugin-node",
12
- "require-extensions",
11
+ "node",
12
+ "esm-extensions",
13
13
  "vitest",
14
14
  ],
15
15
 
@@ -0,0 +1,153 @@
1
+ /* eslint-disable prefer-arrow/prefer-arrow-functions */
2
+ const { default: moduleVisitor } = require("eslint-module-utils/moduleVisitor");
3
+ const { default: resolve } = require("eslint-module-utils/resolve");
4
+ const { isBuiltIn } = require("eslint-plugin-import/lib/core/importType");
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+
8
+ /**
9
+ * Map correct extension
10
+ *
11
+ * @param extension Extension to map.
12
+ * @returns Correct extension.
13
+ */
14
+ function mapExtension(extension) {
15
+ switch (extension) {
16
+ case ".ts":
17
+ return ".js";
18
+ case ".tsx":
19
+ return ".jsx";
20
+ case ".cts":
21
+ return ".cjs";
22
+ default:
23
+ return extension;
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Return the root path.
29
+ *
30
+ * @param context Context
31
+ * @returns Root path.
32
+ */
33
+ function getRootCwd(context) {
34
+ const cwd = context.cwd || process.cwd();
35
+ if (
36
+ !context.parserOptions.project ||
37
+ !fs.existsSync(context.parserOptions.project)
38
+ ) {
39
+ return cwd;
40
+ }
41
+ const data = JSON.parse(fs.readFileSync(context.parserOptions.project));
42
+ if (!data?.compilerOptions?.baseUrl) {
43
+ return cwd;
44
+ }
45
+ return path.join(path.dirname(context.parserOptions.project), data.compilerOptions.baseUrl);
46
+ }
47
+
48
+ module.exports = {
49
+ rules: {
50
+ "force-extensions": {
51
+ meta: {
52
+ type: "suggestion",
53
+ docs: {
54
+ category: "Style guide",
55
+ description: "Ensure consistent use of file extension within the import path.",
56
+ },
57
+ fixable: "code",
58
+ },
59
+ schema: [],
60
+
61
+ // eslint-disable-next-line jsdoc/require-jsdoc
62
+ create(context) {
63
+ const cwd = getRootCwd(context);
64
+ const nodeModulesTypesPath = path.join(cwd, "node_modules", "@types");
65
+ const nodeModulesPath = path.join(cwd, "node_modules");
66
+
67
+ // eslint-disable-next-line jsdoc/require-jsdoc
68
+ function isExternalType(resolvedPath) {
69
+ return !path.relative(nodeModulesTypesPath, resolvedPath).startsWith("..");
70
+ }
71
+
72
+ // eslint-disable-next-line jsdoc/require-jsdoc
73
+ function isExternal(resolvedPath) {
74
+ return !path.relative(nodeModulesPath, resolvedPath).startsWith("..");
75
+ }
76
+
77
+ // eslint-disable-next-line jsdoc/require-jsdoc
78
+ function isIndex(checkPath) {
79
+ return path.parse(checkPath).name === "index";
80
+ }
81
+
82
+ // eslint-disable-next-line jsdoc/require-jsdoc
83
+ function resolveAndMap(importPath) {
84
+ const resolvedPath = resolve(importPath, context) || importPath;
85
+ if (!resolvedPath) {
86
+ return undefined;
87
+ }
88
+ const parsed = path.parse(resolvedPath);
89
+ return path.join(parsed.dir, `${parsed.name.replace(/\.d/, "")}${mapExtension(parsed.ext)}`);
90
+ }
91
+
92
+ // eslint-disable-next-line jsdoc/require-jsdoc
93
+ function checkFileExtension(source, node) {
94
+ // bail if the declaration doesn't have a source, e.g. "export { foo };",
95
+ // or if it's only partially typed like in an editor
96
+ if (!source || !source.value) { return; }
97
+ // don't enforce anything on builtins
98
+ if (isBuiltIn(source.value, context.settings)) {
99
+ return;
100
+ }
101
+
102
+ const importPath = source.value.replace(/\?(.*)$/, "");
103
+ const resolvedPath = resolveAndMap(source.value, context);
104
+
105
+ const resolvedExtension = path.extname(resolvedPath).substring(1);
106
+ const importExtension = path.extname(node.source.value).substring(1);
107
+
108
+ if (resolvedExtension === importExtension) {
109
+ return;
110
+ }
111
+
112
+ if (isExternal(resolvedPath)) {
113
+ if (!importPath.startsWith("@prowise/")) {
114
+ // TODO figure out all te import rules for packages
115
+ // We need to read exports in package.json
116
+ // There might be a better way?
117
+ return;
118
+ }
119
+ if (fs.existsSync(path.join(
120
+ isExternalType(resolvedPath) ? nodeModulesTypesPath : nodeModulesPath,
121
+ importPath,
122
+ "package.json",
123
+ ))) {
124
+ return;
125
+ }
126
+ }
127
+
128
+ if (isIndex(resolvedPath) && !isIndex(path.basename(importPath))) {
129
+ context.report({
130
+ node: source,
131
+ message: `Missing index.${resolvedExtension} for import "${importPath}"`,
132
+ fix: (fixer) => {
133
+ const fixValue = `${importPath}/index.${resolvedExtension}`;
134
+ return fixer.replaceText(node.source, `"${node.source.value.replace(importPath, fixValue)}"`);
135
+ },
136
+ });
137
+ return;
138
+ }
139
+
140
+ context.report({
141
+ node: source,
142
+ message: `${importExtension ? `Incorrect extension "${importExtension}"` : "Missing extension"} for import: "${node.source.value}"`,
143
+ fix: (fixer) => {
144
+ const fixValue = `${importPath.substring(0, importPath.length - (importExtension.length ? importExtension.length + 1 : 0))}.${resolvedExtension}`;
145
+ return fixer.replaceText(node.source, `"${node.source.value.replace(importPath, fixValue)}"`);
146
+ },
147
+ });
148
+ }
149
+ return moduleVisitor(checkFileExtension, { commonjs: true });
150
+ },
151
+ },
152
+ },
153
+ };
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "eslint-plugin-esm-extensions",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ },
6
+ "main": "./index.js",
7
+ "type": "commonjs",
8
+ "exports": {
9
+ "require": "./index.js"
10
+ },
11
+ "files": [
12
+ "index.js"
13
+ ],
14
+ "dependencies": {
15
+ "eslint-module-utils": "^2.8.0",
16
+ "eslint-plugin-import": "^2.29.1"
17
+ },
18
+ "peerDependencies": {
19
+ "eslint": "*"
20
+ },
21
+ "devDependencies": {
22
+ }
23
+ }
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@prowise/eslint-config-linting-rules","version":"1.2.2","description":"Default Prowise linting rules for npm packages.","main":"index.js","exports":{"./default":"./index.js","./typescript":"./typescript.js","./backend":"./backend.js","./frontend":"./frontend.js","./solid":"./solid.js"},"scripts":{"lint":"eslint **/*.js"},"repository":{"type":"git","url":"git+ssh://git@bitbucket.org/prowise/npm-linting-rules.git"},"author":"Prowise B.V.","license":"UNLICENSED","homepage":"https://bitbucket.org/prowise/npm-linting-rules#readme","dependencies":{"@typescript-eslint/eslint-plugin":"^6.19.0","@typescript-eslint/parser":"^6.19.0","confusing-browser-globals":"^1.0.11","eslint":"^8.56.0","eslint-import-resolver-typescript":"^3.6.1","eslint-plugin-import":"^2.29.1","eslint-plugin-jest":"^27.6.3","eslint-plugin-jsdoc":"^48.0.2","eslint-plugin-node":"^11.1.0","eslint-plugin-prefer-arrow":"^1.2.3","eslint-plugin-react":"^7.33.2","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-require-extensions":"^0.1.3","eslint-plugin-solid":"^0.13.1","eslint-plugin-vitest":"^0.3.20","object.assign":"^4.1.5"},"overrides":{"semver":"^7.5.3"}}
1
+ {"name":"@prowise/eslint-config-linting-rules","version":"1.2.4","description":"Default Prowise linting rules for npm packages.","main":"index.js","exports":{"./default":"./index.js","./typescript":"./typescript.js","./backend":"./backend.js","./frontend":"./frontend.js","./solid":"./solid.js"},"scripts":{"lint":"eslint **/*.js"},"repository":{"type":"git","url":"git+ssh://git@bitbucket.org/prowise/npm-linting-rules.git"},"author":"Prowise B.V.","license":"UNLICENSED","homepage":"https://bitbucket.org/prowise/npm-linting-rules#readme","dependencies":{"@typescript-eslint/eslint-plugin":"^7.0.2","@typescript-eslint/parser":"^7.0.2","confusing-browser-globals":"^1.0.11","eslint":"^8.56.0","eslint-import-resolver-typescript":"^3.6.1","eslint-plugin-esm-extensions":"file:eslint-plugin-esm-extensions","eslint-plugin-import":"^2.29.1","eslint-plugin-jest":"^27.9.0","eslint-plugin-jsdoc":"^48.1.0","eslint-plugin-node":"^11.1.0","eslint-plugin-prefer-arrow":"^1.2.3","eslint-plugin-react":"^7.33.2","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-solid":"^0.13.1","eslint-plugin-vitest":"^0.3.22","object.assign":"^4.1.5"},"overrides":{"semver":"^7.5.3"}}
@@ -1559,7 +1559,7 @@ module.exports = {
1559
1559
  * This option sets a specific tab width for your code 🔧
1560
1560
  * https://eslint.org/docs/latest/rules/indent.
1561
1561
  */
1562
- indent: "error",
1562
+ indent: ["error", 4, { SwitchCase: 1 }],
1563
1563
 
1564
1564
  /**
1565
1565
  * Specify whether double or single quotes should be used in JSX attributes 🔧
@@ -64,10 +64,9 @@ module.exports = {
64
64
  * Therefore all backend Node.js projects should always include .js as an extension.
65
65
  *
66
66
  * This does not effect projects that use CJS exports, but it doesn't hurt either.
67
- * Https://github.com/solana-labs/eslint-plugin-require-extensions.
68
67
  */
68
+ // In favour of the force-extensions rule, the default eslint rule is disabled.
69
69
  "import/extensions": "off",
70
- "require-extensions/require-extensions": "error",
71
- "require-extensions/require-index": "error",
70
+ "esm-extensions/force-extensions": "error",
72
71
  },
73
72
  };