@exadev/eslint-config 1.4.1 → 2.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 +45 -44
- package/dist/index.cjs +287 -2
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +259 -2
- package/package.json +1 -14
- package/dist/plugin-BscQLyGY.cjs +0 -46
- package/dist/plugin-DYny7gdb.js +0 -45
- package/dist/plugin.cjs +0 -2
- package/dist/plugin.d.cts +0 -4
- package/dist/plugin.d.ts +0 -5
- package/dist/plugin.js +0 -2
- package/dist/recommended-type-checked.cjs +0 -52
- package/dist/recommended-type-checked.d.cts +0 -5
- package/dist/recommended-type-checked.d.ts +0 -6
- package/dist/recommended-type-checked.js +0 -29
- package/dist/rules/no-non-barrel-index.cjs +0 -24
- package/dist/rules/no-non-barrel-index.d.cts +0 -4
- package/dist/rules/no-non-barrel-index.d.ts +0 -5
- package/dist/rules/no-non-barrel-index.js +0 -24
- package/dist/rules/no-non-barrel-reexport.cjs +0 -89
- package/dist/rules/no-non-barrel-reexport.d.cts +0 -4
- package/dist/rules/no-non-barrel-reexport.d.ts +0 -5
- package/dist/rules/no-non-barrel-reexport.js +0 -89
- package/dist/rules/no-pointless-reassignment.cjs +0 -57
- package/dist/rules/no-pointless-reassignment.d.cts +0 -4
- package/dist/rules/no-pointless-reassignment.d.ts +0 -5
- package/dist/rules/no-pointless-reassignment.js +0 -57
- package/dist/rules/no-side-effects-in-index.cjs +0 -24
- package/dist/rules/no-side-effects-in-index.d.cts +0 -4
- package/dist/rules/no-side-effects-in-index.d.ts +0 -5
- package/dist/rules/no-side-effects-in-index.js +0 -24
package/dist/index.js
CHANGED
|
@@ -1,2 +1,259 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import tseslint from "typescript-eslint";
|
|
2
|
+
//#region package.json
|
|
3
|
+
var version = "2.0.0";
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/rules/no-non-barrel-index.ts
|
|
6
|
+
const INDEX_BASENAME = /^index\.[cm]?[tj]s$/;
|
|
7
|
+
const noNonBarrelIndex = {
|
|
8
|
+
meta: {
|
|
9
|
+
type: "problem",
|
|
10
|
+
schema: [],
|
|
11
|
+
messages: { barrel: "Only src/index.ts may be named index.* (the public convenience barrel); give any other module a descriptive filename." }
|
|
12
|
+
},
|
|
13
|
+
create(context) {
|
|
14
|
+
const filename = context.filename;
|
|
15
|
+
const slash = filename.lastIndexOf("/");
|
|
16
|
+
const basename = slash === -1 ? filename : filename.slice(slash + 1);
|
|
17
|
+
if (!INDEX_BASENAME.test(basename)) return {};
|
|
18
|
+
if (filename.endsWith("/src/index.ts")) return {};
|
|
19
|
+
return { Program(node) {
|
|
20
|
+
context.report({
|
|
21
|
+
node,
|
|
22
|
+
messageId: "barrel"
|
|
23
|
+
});
|
|
24
|
+
} };
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/rules/no-non-barrel-reexport.ts
|
|
29
|
+
function removeListMember(fixer, sourceCode, declaration, members, target) {
|
|
30
|
+
if (members.length === 1) return fixer.remove(declaration);
|
|
31
|
+
const targetIndex = members.indexOf(target);
|
|
32
|
+
const isLast = targetIndex === members.length - 1;
|
|
33
|
+
const neighbor = members[isLast ? targetIndex - 1 : targetIndex + 1];
|
|
34
|
+
if (neighbor === void 0) throw new Error("Unreachable: a list with more than one member always has a neighbor either side of any member within it.");
|
|
35
|
+
return isLast ? fixer.removeRange([sourceCode.getRange(neighbor)[1], sourceCode.getRange(target)[1]]) : fixer.removeRange([sourceCode.getRange(target)[0], sourceCode.getRange(neighbor)[0]]);
|
|
36
|
+
}
|
|
37
|
+
function importIsOnlyUsedByThisExport(sourceCode, trackedImport, usageIdentifier) {
|
|
38
|
+
const variable = sourceCode.getDeclaredVariables(trackedImport.declaration).find((candidate) => candidate.defs.some((def) => def.node === trackedImport.specifier));
|
|
39
|
+
if (variable === void 0) return false;
|
|
40
|
+
if (variable.references.length !== 1) return false;
|
|
41
|
+
const [onlyReference] = variable.references;
|
|
42
|
+
if (onlyReference === void 0) throw new Error("Unreachable: the length check above guarantees exactly one element.");
|
|
43
|
+
return onlyReference.identifier === usageIdentifier;
|
|
44
|
+
}
|
|
45
|
+
const noNonBarrelReexport = {
|
|
46
|
+
meta: {
|
|
47
|
+
type: "problem",
|
|
48
|
+
fixable: "code",
|
|
49
|
+
schema: [],
|
|
50
|
+
messages: {
|
|
51
|
+
splitStatementReexport: "'{{ name }}' is imported here and handed straight back out via a bare export -- the identical re-export 'export { {{ name }} } from ...' would be, just split across two statements. Re-exports belong only in src/index.ts (the public barrel).",
|
|
52
|
+
splitStatementDefaultReexport: "'{{ name }}' is imported here and handed straight back out via `export default` -- the identical re-export 'export { {{ name }} as default } from ...' would be, just split across two statements. Re-exports belong only in src/index.ts (the public barrel)."
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
create(context) {
|
|
56
|
+
if (context.filename.endsWith("/src/index.ts")) return {};
|
|
57
|
+
const importsByName = /* @__PURE__ */ new Map();
|
|
58
|
+
const bareExportSpecifiers = [];
|
|
59
|
+
const defaultExportDeclarations = [];
|
|
60
|
+
return {
|
|
61
|
+
ImportDeclaration(node) {
|
|
62
|
+
for (const specifier of node.specifiers) importsByName.set(specifier.local.name, {
|
|
63
|
+
declaration: node,
|
|
64
|
+
specifier
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
ExportNamedDeclaration(node) {
|
|
68
|
+
if (node.source !== null && node.source !== void 0) return;
|
|
69
|
+
for (const specifier of node.specifiers) bareExportSpecifiers.push({
|
|
70
|
+
declaration: node,
|
|
71
|
+
specifier
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
ExportDefaultDeclaration(node) {
|
|
75
|
+
defaultExportDeclarations.push(node);
|
|
76
|
+
},
|
|
77
|
+
"Program:exit"() {
|
|
78
|
+
const { sourceCode } = context;
|
|
79
|
+
for (const { declaration, specifier } of bareExportSpecifiers) {
|
|
80
|
+
const name = specifier.local.type === "Identifier" ? specifier.local.name : void 0;
|
|
81
|
+
if (name === void 0) continue;
|
|
82
|
+
const trackedImport = importsByName.get(name);
|
|
83
|
+
if (trackedImport === void 0) continue;
|
|
84
|
+
context.report({
|
|
85
|
+
node: specifier,
|
|
86
|
+
messageId: "splitStatementReexport",
|
|
87
|
+
data: { name },
|
|
88
|
+
fix(fixer) {
|
|
89
|
+
const fixes = [removeListMember(fixer, sourceCode, declaration, declaration.specifiers, specifier)];
|
|
90
|
+
if (specifier.local.type === "Identifier" && importIsOnlyUsedByThisExport(sourceCode, trackedImport, specifier.local)) fixes.push(removeListMember(fixer, sourceCode, trackedImport.declaration, trackedImport.declaration.specifiers, trackedImport.specifier));
|
|
91
|
+
return fixes;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
for (const declarationNode of defaultExportDeclarations) {
|
|
96
|
+
const name = declarationNode.declaration.type === "Identifier" ? declarationNode.declaration.name : void 0;
|
|
97
|
+
if (name === void 0) continue;
|
|
98
|
+
const trackedImport = importsByName.get(name);
|
|
99
|
+
if (trackedImport === void 0) continue;
|
|
100
|
+
context.report({
|
|
101
|
+
node: declarationNode,
|
|
102
|
+
messageId: "splitStatementDefaultReexport",
|
|
103
|
+
data: { name },
|
|
104
|
+
fix(fixer) {
|
|
105
|
+
const fixes = [fixer.remove(declarationNode)];
|
|
106
|
+
if (declarationNode.declaration.type === "Identifier" && importIsOnlyUsedByThisExport(sourceCode, trackedImport, declarationNode.declaration)) fixes.push(removeListMember(fixer, sourceCode, trackedImport.declaration, trackedImport.declaration.specifiers, trackedImport.specifier));
|
|
107
|
+
return fixes;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/rules/no-pointless-reassignment.ts
|
|
117
|
+
function isIdentifierReference(reference) {
|
|
118
|
+
return reference.identifier.type === "Identifier";
|
|
119
|
+
}
|
|
120
|
+
const noPointlessReassignment = {
|
|
121
|
+
meta: {
|
|
122
|
+
type: "problem",
|
|
123
|
+
fixable: "code",
|
|
124
|
+
schema: [],
|
|
125
|
+
messages: { pointlessReassignment: "Pointless reassignment: '{{ name }}' is just an alias for '{{ value }}'. Use the original directly." }
|
|
126
|
+
},
|
|
127
|
+
create(context) {
|
|
128
|
+
return { VariableDeclarator(node) {
|
|
129
|
+
if (node.id.type !== "Identifier" || node.init?.type !== "Identifier" || node.id.name.startsWith("_")) return;
|
|
130
|
+
if (node.parent.type !== "VariableDeclaration" || node.parent.kind !== "const") return;
|
|
131
|
+
const scope = context.sourceCode.getScope(node);
|
|
132
|
+
const sourceVariable = scope.references.find((reference) => reference.identifier === node.init)?.resolved;
|
|
133
|
+
if (!sourceVariable || sourceVariable.references.some((reference) => reference.isWrite() && !reference.init)) return;
|
|
134
|
+
const aliasName = node.id.name;
|
|
135
|
+
const originalName = node.init.name;
|
|
136
|
+
context.report({
|
|
137
|
+
node,
|
|
138
|
+
messageId: "pointlessReassignment",
|
|
139
|
+
data: {
|
|
140
|
+
name: aliasName,
|
|
141
|
+
value: originalName
|
|
142
|
+
},
|
|
143
|
+
fix(fixer) {
|
|
144
|
+
const variable = scope.set.get(aliasName);
|
|
145
|
+
if (!variable) return null;
|
|
146
|
+
if (variable.references.filter((reference) => reference.isWrite() && reference.identifier !== node.id).length > 0) return null;
|
|
147
|
+
const readRefs = variable.references.filter((reference) => reference.isRead() && isIdentifierReference(reference));
|
|
148
|
+
if (readRefs.some((reference) => {
|
|
149
|
+
const afterToken = context.sourceCode.getTokenAfter(reference.identifier);
|
|
150
|
+
if (afterToken?.value === ":") return false;
|
|
151
|
+
if (afterToken?.value !== "}" && afterToken?.value !== ",") return false;
|
|
152
|
+
let token = context.sourceCode.getTokenBefore(reference.identifier);
|
|
153
|
+
while (token) {
|
|
154
|
+
if (token.value === "{") return true;
|
|
155
|
+
if (token.value === "[" || token.value === "(") return false;
|
|
156
|
+
if (token.value === ":") return false;
|
|
157
|
+
token = context.sourceCode.getTokenBefore(token);
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
})) return null;
|
|
161
|
+
const fixes = readRefs.map((reference) => fixer.replaceText(reference.identifier, originalName));
|
|
162
|
+
const declaration = node.parent;
|
|
163
|
+
if (declaration.type !== "VariableDeclaration" || declaration.declarations.length !== 1) return null;
|
|
164
|
+
fixes.push(fixer.remove(declaration));
|
|
165
|
+
return fixes;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
} };
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region src/rules/no-side-effects-in-index.ts
|
|
173
|
+
function isPureReexport(statement) {
|
|
174
|
+
if (statement.type === "ExportAllDeclaration") return true;
|
|
175
|
+
return statement.type === "ExportNamedDeclaration" && statement.source !== null && statement.source !== void 0;
|
|
176
|
+
}
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/plugin.ts
|
|
179
|
+
const plugin = {
|
|
180
|
+
meta: {
|
|
181
|
+
name: "@exadev/eslint-config",
|
|
182
|
+
version,
|
|
183
|
+
namespace: "exadev"
|
|
184
|
+
},
|
|
185
|
+
rules: {
|
|
186
|
+
"no-non-barrel-index": noNonBarrelIndex,
|
|
187
|
+
"no-non-barrel-reexport": noNonBarrelReexport,
|
|
188
|
+
"no-pointless-reassignment": noPointlessReassignment,
|
|
189
|
+
"no-side-effects-in-index": {
|
|
190
|
+
meta: {
|
|
191
|
+
type: "problem",
|
|
192
|
+
schema: [],
|
|
193
|
+
messages: { notAPureReexport: "The public barrel (src/index.ts) may contain only re-export statements ('export * from ...' / 'export { x } from ...' / 'export type { x } from ...') -- nothing else, so it can never have a side effect at import time by construction. Found: {{ description }}." }
|
|
194
|
+
},
|
|
195
|
+
create(context) {
|
|
196
|
+
if (!context.filename.endsWith("/src/index.ts")) return {};
|
|
197
|
+
return { Program(node) {
|
|
198
|
+
for (const statement of node.body) if (!isPureReexport(statement)) context.report({
|
|
199
|
+
node: statement,
|
|
200
|
+
messageId: "notAPureReexport",
|
|
201
|
+
data: { description: statement.type }
|
|
202
|
+
});
|
|
203
|
+
} };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
configs: {
|
|
208
|
+
get recommended() {
|
|
209
|
+
return {
|
|
210
|
+
plugins: { exadev: plugin },
|
|
211
|
+
linterOptions: { noInlineConfig: true },
|
|
212
|
+
rules: {
|
|
213
|
+
"exadev/no-non-barrel-index": "error",
|
|
214
|
+
"exadev/no-non-barrel-reexport": "error",
|
|
215
|
+
"exadev/no-pointless-reassignment": "error",
|
|
216
|
+
"exadev/no-side-effects-in-index": "error"
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
},
|
|
220
|
+
get barrel() {
|
|
221
|
+
return {
|
|
222
|
+
plugins: { exadev: plugin },
|
|
223
|
+
rules: {
|
|
224
|
+
"exadev/no-non-barrel-index": "error",
|
|
225
|
+
"exadev/no-non-barrel-reexport": "error",
|
|
226
|
+
"exadev/no-side-effects-in-index": "error"
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/recommended-type-checked.ts
|
|
234
|
+
const TEST_FILE_PATTERNS = "**/*.{test,spec}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
235
|
+
const recommendedTypeChecked = [
|
|
236
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
237
|
+
...tseslint.configs.stylisticTypeChecked,
|
|
238
|
+
{
|
|
239
|
+
plugins: { exadev: plugin },
|
|
240
|
+
linterOptions: { noInlineConfig: true },
|
|
241
|
+
rules: {
|
|
242
|
+
"exadev/no-non-barrel-index": "error",
|
|
243
|
+
"exadev/no-non-barrel-reexport": "error",
|
|
244
|
+
"exadev/no-pointless-reassignment": "error",
|
|
245
|
+
"exadev/no-side-effects-in-index": "error",
|
|
246
|
+
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "never" }],
|
|
247
|
+
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": true }]
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
files: [TEST_FILE_PATTERNS],
|
|
252
|
+
rules: {
|
|
253
|
+
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
|
|
254
|
+
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "as" }]
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
];
|
|
258
|
+
//#endregion
|
|
259
|
+
export { recommendedTypeChecked as default, plugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exadev/eslint-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Shared custom ESLint rules and plugin for ExaDev projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -23,14 +23,6 @@
|
|
|
23
23
|
},
|
|
24
24
|
"import": "./dist/index.js",
|
|
25
25
|
"require": "./dist/index.cjs"
|
|
26
|
-
},
|
|
27
|
-
"./*": {
|
|
28
|
-
"types": {
|
|
29
|
-
"import": "./dist/*.d.ts",
|
|
30
|
-
"require": "./dist/*.d.cts"
|
|
31
|
-
},
|
|
32
|
-
"import": "./dist/*.js",
|
|
33
|
-
"require": "./dist/*.cjs"
|
|
34
26
|
}
|
|
35
27
|
},
|
|
36
28
|
"files": [
|
|
@@ -49,11 +41,6 @@
|
|
|
49
41
|
"eslint": ">=10.0.0",
|
|
50
42
|
"typescript-eslint": ">=8.0.0"
|
|
51
43
|
},
|
|
52
|
-
"peerDependenciesMeta": {
|
|
53
|
-
"typescript-eslint": {
|
|
54
|
-
"optional": true
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
44
|
"devDependencies": {
|
|
58
45
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
59
46
|
"@commitlint/cli": "^21.2.1",
|
package/dist/plugin-BscQLyGY.cjs
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
//#endregion
|
|
2
|
-
//#region src/plugin.ts
|
|
3
|
-
const plugin = {
|
|
4
|
-
meta: {
|
|
5
|
-
name: "@exadev/eslint-config",
|
|
6
|
-
version: "1.4.1",
|
|
7
|
-
namespace: "exadev"
|
|
8
|
-
},
|
|
9
|
-
rules: {
|
|
10
|
-
"no-non-barrel-index": require("./rules/no-non-barrel-index.cjs"),
|
|
11
|
-
"no-non-barrel-reexport": require("./rules/no-non-barrel-reexport.cjs"),
|
|
12
|
-
"no-pointless-reassignment": require("./rules/no-pointless-reassignment.cjs"),
|
|
13
|
-
"no-side-effects-in-index": require("./rules/no-side-effects-in-index.cjs")
|
|
14
|
-
},
|
|
15
|
-
configs: {
|
|
16
|
-
get recommended() {
|
|
17
|
-
return {
|
|
18
|
-
plugins: { exadev: plugin },
|
|
19
|
-
linterOptions: { noInlineConfig: true },
|
|
20
|
-
rules: {
|
|
21
|
-
"exadev/no-non-barrel-index": "error",
|
|
22
|
-
"exadev/no-non-barrel-reexport": "error",
|
|
23
|
-
"exadev/no-pointless-reassignment": "error",
|
|
24
|
-
"exadev/no-side-effects-in-index": "error"
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
},
|
|
28
|
-
get barrel() {
|
|
29
|
-
return {
|
|
30
|
-
plugins: { exadev: plugin },
|
|
31
|
-
rules: {
|
|
32
|
-
"exadev/no-non-barrel-index": "error",
|
|
33
|
-
"exadev/no-non-barrel-reexport": "error",
|
|
34
|
-
"exadev/no-side-effects-in-index": "error"
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
//#endregion
|
|
41
|
-
Object.defineProperty(exports, "plugin", {
|
|
42
|
-
enumerable: true,
|
|
43
|
-
get: function() {
|
|
44
|
-
return plugin;
|
|
45
|
-
}
|
|
46
|
-
});
|
package/dist/plugin-DYny7gdb.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import noNonBarrelIndex from "./rules/no-non-barrel-index.js";
|
|
2
|
-
import noNonBarrelReexport from "./rules/no-non-barrel-reexport.js";
|
|
3
|
-
import noPointlessReassignment from "./rules/no-pointless-reassignment.js";
|
|
4
|
-
import noSideEffectsInIndex from "./rules/no-side-effects-in-index.js";
|
|
5
|
-
//#endregion
|
|
6
|
-
//#region src/plugin.ts
|
|
7
|
-
const plugin = {
|
|
8
|
-
meta: {
|
|
9
|
-
name: "@exadev/eslint-config",
|
|
10
|
-
version: "1.4.1",
|
|
11
|
-
namespace: "exadev"
|
|
12
|
-
},
|
|
13
|
-
rules: {
|
|
14
|
-
"no-non-barrel-index": noNonBarrelIndex,
|
|
15
|
-
"no-non-barrel-reexport": noNonBarrelReexport,
|
|
16
|
-
"no-pointless-reassignment": noPointlessReassignment,
|
|
17
|
-
"no-side-effects-in-index": noSideEffectsInIndex
|
|
18
|
-
},
|
|
19
|
-
configs: {
|
|
20
|
-
get recommended() {
|
|
21
|
-
return {
|
|
22
|
-
plugins: { exadev: plugin },
|
|
23
|
-
linterOptions: { noInlineConfig: true },
|
|
24
|
-
rules: {
|
|
25
|
-
"exadev/no-non-barrel-index": "error",
|
|
26
|
-
"exadev/no-non-barrel-reexport": "error",
|
|
27
|
-
"exadev/no-pointless-reassignment": "error",
|
|
28
|
-
"exadev/no-side-effects-in-index": "error"
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
},
|
|
32
|
-
get barrel() {
|
|
33
|
-
return {
|
|
34
|
-
plugins: { exadev: plugin },
|
|
35
|
-
rules: {
|
|
36
|
-
"exadev/no-non-barrel-index": "error",
|
|
37
|
-
"exadev/no-non-barrel-reexport": "error",
|
|
38
|
-
"exadev/no-side-effects-in-index": "error"
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
//#endregion
|
|
45
|
-
export { plugin as t };
|
package/dist/plugin.cjs
DELETED
package/dist/plugin.d.cts
DELETED
package/dist/plugin.d.ts
DELETED
package/dist/plugin.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
|
-
//#endregion
|
|
23
|
-
const require_plugin = require("./plugin-BscQLyGY.cjs");
|
|
24
|
-
let typescript_eslint = require("typescript-eslint");
|
|
25
|
-
typescript_eslint = __toESM(typescript_eslint, 1);
|
|
26
|
-
//#region src/recommended-type-checked.ts
|
|
27
|
-
const TEST_FILE_PATTERNS = "**/*.{test,spec}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
28
|
-
const recommendedTypeChecked = [
|
|
29
|
-
...typescript_eslint.default.configs.recommendedTypeChecked,
|
|
30
|
-
...typescript_eslint.default.configs.stylisticTypeChecked,
|
|
31
|
-
{
|
|
32
|
-
plugins: { exadev: require_plugin.plugin },
|
|
33
|
-
linterOptions: { noInlineConfig: true },
|
|
34
|
-
rules: {
|
|
35
|
-
"exadev/no-non-barrel-index": "error",
|
|
36
|
-
"exadev/no-non-barrel-reexport": "error",
|
|
37
|
-
"exadev/no-pointless-reassignment": "error",
|
|
38
|
-
"exadev/no-side-effects-in-index": "error",
|
|
39
|
-
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "never" }],
|
|
40
|
-
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": true }]
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
files: [TEST_FILE_PATTERNS],
|
|
45
|
-
rules: {
|
|
46
|
-
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
|
|
47
|
-
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "as" }]
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
];
|
|
51
|
-
//#endregion
|
|
52
|
-
module.exports = recommendedTypeChecked;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { t as plugin } from "./plugin-DYny7gdb.js";
|
|
2
|
-
import tseslint from "typescript-eslint";
|
|
3
|
-
//#region src/recommended-type-checked.ts
|
|
4
|
-
const TEST_FILE_PATTERNS = "**/*.{test,spec}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
5
|
-
const recommendedTypeChecked = [
|
|
6
|
-
...tseslint.configs.recommendedTypeChecked,
|
|
7
|
-
...tseslint.configs.stylisticTypeChecked,
|
|
8
|
-
{
|
|
9
|
-
plugins: { exadev: plugin },
|
|
10
|
-
linterOptions: { noInlineConfig: true },
|
|
11
|
-
rules: {
|
|
12
|
-
"exadev/no-non-barrel-index": "error",
|
|
13
|
-
"exadev/no-non-barrel-reexport": "error",
|
|
14
|
-
"exadev/no-pointless-reassignment": "error",
|
|
15
|
-
"exadev/no-side-effects-in-index": "error",
|
|
16
|
-
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "never" }],
|
|
17
|
-
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": true }]
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
files: [TEST_FILE_PATTERNS],
|
|
22
|
-
rules: {
|
|
23
|
-
"@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": "allow-with-description" }],
|
|
24
|
-
"@typescript-eslint/consistent-type-assertions": ["error", { assertionStyle: "as" }]
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
];
|
|
28
|
-
//#endregion
|
|
29
|
-
export { recommendedTypeChecked as default };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region src/rules/no-non-barrel-index.ts
|
|
2
|
-
const INDEX_BASENAME = /^index\.[cm]?[tj]s$/;
|
|
3
|
-
const noNonBarrelIndex = {
|
|
4
|
-
meta: {
|
|
5
|
-
type: "problem",
|
|
6
|
-
schema: [],
|
|
7
|
-
messages: { barrel: "Only src/index.ts may be named index.* (the public convenience barrel); give any other module a descriptive filename." }
|
|
8
|
-
},
|
|
9
|
-
create(context) {
|
|
10
|
-
const filename = context.filename;
|
|
11
|
-
const slash = filename.lastIndexOf("/");
|
|
12
|
-
const basename = slash === -1 ? filename : filename.slice(slash + 1);
|
|
13
|
-
if (!INDEX_BASENAME.test(basename)) return {};
|
|
14
|
-
if (filename.endsWith("/src/index.ts")) return {};
|
|
15
|
-
return { Program(node) {
|
|
16
|
-
context.report({
|
|
17
|
-
node,
|
|
18
|
-
messageId: "barrel"
|
|
19
|
-
});
|
|
20
|
-
} };
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
//#endregion
|
|
24
|
-
module.exports = noNonBarrelIndex;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region src/rules/no-non-barrel-index.ts
|
|
2
|
-
const INDEX_BASENAME = /^index\.[cm]?[tj]s$/;
|
|
3
|
-
const noNonBarrelIndex = {
|
|
4
|
-
meta: {
|
|
5
|
-
type: "problem",
|
|
6
|
-
schema: [],
|
|
7
|
-
messages: { barrel: "Only src/index.ts may be named index.* (the public convenience barrel); give any other module a descriptive filename." }
|
|
8
|
-
},
|
|
9
|
-
create(context) {
|
|
10
|
-
const filename = context.filename;
|
|
11
|
-
const slash = filename.lastIndexOf("/");
|
|
12
|
-
const basename = slash === -1 ? filename : filename.slice(slash + 1);
|
|
13
|
-
if (!INDEX_BASENAME.test(basename)) return {};
|
|
14
|
-
if (filename.endsWith("/src/index.ts")) return {};
|
|
15
|
-
return { Program(node) {
|
|
16
|
-
context.report({
|
|
17
|
-
node,
|
|
18
|
-
messageId: "barrel"
|
|
19
|
-
});
|
|
20
|
-
} };
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
//#endregion
|
|
24
|
-
export { noNonBarrelIndex as default };
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
//#region src/rules/no-non-barrel-reexport.ts
|
|
2
|
-
function removeListMember(fixer, sourceCode, declaration, members, target) {
|
|
3
|
-
if (members.length === 1) return fixer.remove(declaration);
|
|
4
|
-
const targetIndex = members.indexOf(target);
|
|
5
|
-
const isLast = targetIndex === members.length - 1;
|
|
6
|
-
const neighbor = members[isLast ? targetIndex - 1 : targetIndex + 1];
|
|
7
|
-
if (neighbor === void 0) throw new Error("Unreachable: a list with more than one member always has a neighbor either side of any member within it.");
|
|
8
|
-
return isLast ? fixer.removeRange([sourceCode.getRange(neighbor)[1], sourceCode.getRange(target)[1]]) : fixer.removeRange([sourceCode.getRange(target)[0], sourceCode.getRange(neighbor)[0]]);
|
|
9
|
-
}
|
|
10
|
-
function importIsOnlyUsedByThisExport(sourceCode, trackedImport, usageIdentifier) {
|
|
11
|
-
const variable = sourceCode.getDeclaredVariables(trackedImport.declaration).find((candidate) => candidate.defs.some((def) => def.node === trackedImport.specifier));
|
|
12
|
-
if (variable === void 0) return false;
|
|
13
|
-
if (variable.references.length !== 1) return false;
|
|
14
|
-
const [onlyReference] = variable.references;
|
|
15
|
-
if (onlyReference === void 0) throw new Error("Unreachable: the length check above guarantees exactly one element.");
|
|
16
|
-
return onlyReference.identifier === usageIdentifier;
|
|
17
|
-
}
|
|
18
|
-
const noNonBarrelReexport = {
|
|
19
|
-
meta: {
|
|
20
|
-
type: "problem",
|
|
21
|
-
fixable: "code",
|
|
22
|
-
schema: [],
|
|
23
|
-
messages: {
|
|
24
|
-
splitStatementReexport: "'{{ name }}' is imported here and handed straight back out via a bare export -- the identical re-export 'export { {{ name }} } from ...' would be, just split across two statements. Re-exports belong only in src/index.ts (the public barrel).",
|
|
25
|
-
splitStatementDefaultReexport: "'{{ name }}' is imported here and handed straight back out via `export default` -- the identical re-export 'export { {{ name }} as default } from ...' would be, just split across two statements. Re-exports belong only in src/index.ts (the public barrel)."
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
create(context) {
|
|
29
|
-
if (context.filename.endsWith("/src/index.ts")) return {};
|
|
30
|
-
const importsByName = /* @__PURE__ */ new Map();
|
|
31
|
-
const bareExportSpecifiers = [];
|
|
32
|
-
const defaultExportDeclarations = [];
|
|
33
|
-
return {
|
|
34
|
-
ImportDeclaration(node) {
|
|
35
|
-
for (const specifier of node.specifiers) importsByName.set(specifier.local.name, {
|
|
36
|
-
declaration: node,
|
|
37
|
-
specifier
|
|
38
|
-
});
|
|
39
|
-
},
|
|
40
|
-
ExportNamedDeclaration(node) {
|
|
41
|
-
if (node.source !== null && node.source !== void 0) return;
|
|
42
|
-
for (const specifier of node.specifiers) bareExportSpecifiers.push({
|
|
43
|
-
declaration: node,
|
|
44
|
-
specifier
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
ExportDefaultDeclaration(node) {
|
|
48
|
-
defaultExportDeclarations.push(node);
|
|
49
|
-
},
|
|
50
|
-
"Program:exit"() {
|
|
51
|
-
const { sourceCode } = context;
|
|
52
|
-
for (const { declaration, specifier } of bareExportSpecifiers) {
|
|
53
|
-
const name = specifier.local.type === "Identifier" ? specifier.local.name : void 0;
|
|
54
|
-
if (name === void 0) continue;
|
|
55
|
-
const trackedImport = importsByName.get(name);
|
|
56
|
-
if (trackedImport === void 0) continue;
|
|
57
|
-
context.report({
|
|
58
|
-
node: specifier,
|
|
59
|
-
messageId: "splitStatementReexport",
|
|
60
|
-
data: { name },
|
|
61
|
-
fix(fixer) {
|
|
62
|
-
const fixes = [removeListMember(fixer, sourceCode, declaration, declaration.specifiers, specifier)];
|
|
63
|
-
if (specifier.local.type === "Identifier" && importIsOnlyUsedByThisExport(sourceCode, trackedImport, specifier.local)) fixes.push(removeListMember(fixer, sourceCode, trackedImport.declaration, trackedImport.declaration.specifiers, trackedImport.specifier));
|
|
64
|
-
return fixes;
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
for (const declarationNode of defaultExportDeclarations) {
|
|
69
|
-
const name = declarationNode.declaration.type === "Identifier" ? declarationNode.declaration.name : void 0;
|
|
70
|
-
if (name === void 0) continue;
|
|
71
|
-
const trackedImport = importsByName.get(name);
|
|
72
|
-
if (trackedImport === void 0) continue;
|
|
73
|
-
context.report({
|
|
74
|
-
node: declarationNode,
|
|
75
|
-
messageId: "splitStatementDefaultReexport",
|
|
76
|
-
data: { name },
|
|
77
|
-
fix(fixer) {
|
|
78
|
-
const fixes = [fixer.remove(declarationNode)];
|
|
79
|
-
if (declarationNode.declaration.type === "Identifier" && importIsOnlyUsedByThisExport(sourceCode, trackedImport, declarationNode.declaration)) fixes.push(removeListMember(fixer, sourceCode, trackedImport.declaration, trackedImport.declaration.specifiers, trackedImport.specifier));
|
|
80
|
-
return fixes;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
//#endregion
|
|
89
|
-
module.exports = noNonBarrelReexport;
|