@sarj/eslint-plugin 7.1.0 → 8.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/dist/index.cjs +350 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +350 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
default: () => index_default,
|
|
34
34
|
recommendedRules: () => recommendedRules,
|
|
35
35
|
renamedRules: () => renamedRules,
|
|
36
|
+
retiredRules: () => retiredRules,
|
|
36
37
|
rules: () => rules,
|
|
37
38
|
strictRules: () => strictRules
|
|
38
39
|
});
|
|
@@ -52,25 +53,41 @@ var createRule = import_utils.ESLintUtils.RuleCreator(evidenceUrl);
|
|
|
52
53
|
// src/rules/_paths.ts
|
|
53
54
|
var SCRIPT_FILE_RE = /([\\/]scripts[\\/])|(\.mjs$)/;
|
|
54
55
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
55
|
-
var
|
|
56
|
-
var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types|vendor|vendored|
|
|
57
|
-
var
|
|
58
|
-
|
|
56
|
+
var STORY_TREE_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
|
|
57
|
+
var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types|vendor|vendored|third[-_]?party)[\\/])|(\.gen\.[cm]?[jt]sx?$)|(\.generated\.[cm]?[jt]sx?$)|(\.d\.[cm]?ts$)|(\.types\.[cm]?ts$)/;
|
|
58
|
+
var EXTERNAL_TREE_RE = /[\\/]external[\\/]/;
|
|
59
|
+
var GENERATED_MARKER_RE = /(?:@generated\b|this file (?:is|was|has been)[\w\s,'-]{0,40}?generated|auto-?generated file\b|generated (?:with|by)|generated (?:graphql )?types|do not edit(?: directly| manually)?|do not (?:modify|change) this file)/i;
|
|
60
|
+
var TEST_BASENAME_RE = /[.\-_](test|spec|e2e)\.[cm]?[jt]sx?$/;
|
|
61
|
+
var TEST_INTEGRATION_BASENAME_RE = /\.integration\.[cm]?[jt]sx?$/;
|
|
62
|
+
var TEST_DIR_RE = /(^|\/)(tests?|__tests__|__mocks__|fixtures|__fixtures__|__testfixtures__|e2e|integration)\//;
|
|
63
|
+
var FIXTURE_TREE_RE = /(^|\/)fixture\//;
|
|
64
|
+
function isTestFile(filename, gates = []) {
|
|
59
65
|
const normalized = filename.replaceAll("\\", "/");
|
|
60
66
|
const base = normalized.slice(normalized.lastIndexOf("/") + 1);
|
|
61
|
-
if (
|
|
67
|
+
if (TEST_BASENAME_RE.test(base) || TEST_INTEGRATION_BASENAME_RE.test(base)) {
|
|
62
68
|
return true;
|
|
63
69
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
if (TEST_DIR_RE.test(normalized)) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
return gates.includes("fixtureTree") && FIXTURE_TREE_RE.test(normalized);
|
|
67
74
|
}
|
|
68
|
-
function isStoryFile(filename) {
|
|
75
|
+
function isStoryFile(filename, gates = []) {
|
|
69
76
|
const normalized = filename.replaceAll("\\", "/");
|
|
70
|
-
|
|
77
|
+
if (STORY_FILE_RE.test(normalized)) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
return gates.includes("storyTree") && STORY_TREE_RE.test(normalized);
|
|
71
81
|
}
|
|
72
|
-
function isGeneratedFile(filename, sourceText = "") {
|
|
73
|
-
|
|
82
|
+
function isGeneratedFile(filename, sourceText = "", gates = []) {
|
|
83
|
+
const normalized = filename.replaceAll("\\", "/");
|
|
84
|
+
if (GENERATED_FILE_RE.test(normalized)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (gates.includes("externalTree") && EXTERNAL_TREE_RE.test(normalized)) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
return GENERATED_MARKER_RE.test(sourceText.slice(0, 2048));
|
|
74
91
|
}
|
|
75
92
|
function isScriptFile(filename) {
|
|
76
93
|
return SCRIPT_FILE_RE.test(filename);
|
|
@@ -155,6 +172,10 @@ var enforce_file_structure_default = createRule({
|
|
|
155
172
|
|
|
156
173
|
// src/rules/no-async-callback-in-wait-for.ts
|
|
157
174
|
var import_utils3 = require("@typescript-eslint/utils");
|
|
175
|
+
var isWaitForCallee = (callee) => {
|
|
176
|
+
if (callee.type === import_utils3.AST_NODE_TYPES.Identifier) return callee.name === "waitFor";
|
|
177
|
+
return callee.type === import_utils3.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils3.AST_NODE_TYPES.Identifier && callee.property.name === "waitFor";
|
|
178
|
+
};
|
|
158
179
|
var no_async_callback_in_wait_for_default = createRule({
|
|
159
180
|
name: "no-async-callback-in-wait-for",
|
|
160
181
|
meta: {
|
|
@@ -174,14 +195,13 @@ var no_async_callback_in_wait_for_default = createRule({
|
|
|
174
195
|
}
|
|
175
196
|
return {
|
|
176
197
|
CallExpression(node) {
|
|
177
|
-
if (node.callee
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
198
|
+
if (!isWaitForCallee(node.callee)) return;
|
|
199
|
+
const callback = node.arguments[0];
|
|
200
|
+
if (callback && (callback.type === import_utils3.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils3.AST_NODE_TYPES.FunctionExpression) && callback.async) {
|
|
201
|
+
context.report({
|
|
202
|
+
node: callback,
|
|
203
|
+
messageId: "noAsyncCallbackInWaitFor"
|
|
204
|
+
});
|
|
185
205
|
}
|
|
186
206
|
}
|
|
187
207
|
};
|
|
@@ -809,6 +829,12 @@ var no_comment_cruft_default = createRule({
|
|
|
809
829
|
// src/rules/no-conditional-in-test.ts
|
|
810
830
|
var import_utils7 = require("@typescript-eslint/utils");
|
|
811
831
|
var TEST_CALLERS = /* @__PURE__ */ new Set(["it", "test"]);
|
|
832
|
+
var HOOK_MEMBERS = /* @__PURE__ */ new Set([
|
|
833
|
+
"afterAll",
|
|
834
|
+
"afterEach",
|
|
835
|
+
"beforeAll",
|
|
836
|
+
"beforeEach"
|
|
837
|
+
]);
|
|
812
838
|
var FUNCTION_TYPES = /* @__PURE__ */ new Set([
|
|
813
839
|
import_utils7.AST_NODE_TYPES.FunctionDeclaration,
|
|
814
840
|
import_utils7.AST_NODE_TYPES.FunctionExpression,
|
|
@@ -852,6 +878,9 @@ function isTestBody(fn) {
|
|
|
852
878
|
if (call?.type !== import_utils7.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
|
|
853
879
|
return false;
|
|
854
880
|
}
|
|
881
|
+
if (call.callee.type === import_utils7.AST_NODE_TYPES.MemberExpression && !call.callee.computed && call.callee.property.type === import_utils7.AST_NODE_TYPES.Identifier && HOOK_MEMBERS.has(call.callee.property.name)) {
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
855
884
|
const name = testCallerName(call.callee);
|
|
856
885
|
return name !== null && TEST_CALLERS.has(name);
|
|
857
886
|
}
|
|
@@ -1006,8 +1035,26 @@ function isTypeLevelNarrowing(node) {
|
|
|
1006
1035
|
return isTypeAssertionBranch(node.consequent) && (node.alternate === null || isTypeAssertionBranch(node.alternate));
|
|
1007
1036
|
}
|
|
1008
1037
|
var isInertBranch = (branch) => !containsAssertion(branch) && !containsEscape(branch) && !containsSkipCall(branch);
|
|
1038
|
+
function isNormalizationStatement(statement) {
|
|
1039
|
+
if (statement.type === import_utils7.AST_NODE_TYPES.VariableDeclaration) {
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
if (statement.type === import_utils7.AST_NODE_TYPES.BlockStatement) {
|
|
1043
|
+
return statement.body.every(isNormalizationStatement);
|
|
1044
|
+
}
|
|
1045
|
+
if (statement.type !== import_utils7.AST_NODE_TYPES.ExpressionStatement) {
|
|
1046
|
+
return false;
|
|
1047
|
+
}
|
|
1048
|
+
const { expression } = statement;
|
|
1049
|
+
return expression.type === import_utils7.AST_NODE_TYPES.AssignmentExpression || expression.type === import_utils7.AST_NODE_TYPES.UpdateExpression || expression.type === import_utils7.AST_NODE_TYPES.UnaryExpression && expression.operator === "delete";
|
|
1050
|
+
}
|
|
1009
1051
|
function isInertNormalization(node) {
|
|
1010
|
-
|
|
1052
|
+
const branches = [node.consequent, node.alternate].filter(
|
|
1053
|
+
(branch) => branch !== null
|
|
1054
|
+
);
|
|
1055
|
+
return branches.every(
|
|
1056
|
+
(branch) => isInertBranch(branch) && isNormalizationStatement(branch)
|
|
1057
|
+
);
|
|
1011
1058
|
}
|
|
1012
1059
|
function isExemptIfStatement(node) {
|
|
1013
1060
|
return isPinnedNarrowingGuard(node) || isThrowingGuard(node) || isTypeLevelNarrowing(node) || isInertNormalization(node);
|
|
@@ -1615,7 +1662,6 @@ var PURE_METHODS = /* @__PURE__ */ new Set([
|
|
|
1615
1662
|
"forEach",
|
|
1616
1663
|
"reduce",
|
|
1617
1664
|
"reduceRight",
|
|
1618
|
-
"find",
|
|
1619
1665
|
"findIndex",
|
|
1620
1666
|
"findLast",
|
|
1621
1667
|
"findLastIndex",
|
|
@@ -1638,15 +1684,6 @@ var PURE_METHODS = /* @__PURE__ */ new Set([
|
|
|
1638
1684
|
"indexOf",
|
|
1639
1685
|
"lastIndexOf",
|
|
1640
1686
|
"at",
|
|
1641
|
-
"keys",
|
|
1642
|
-
"values",
|
|
1643
|
-
"entries",
|
|
1644
|
-
"has",
|
|
1645
|
-
"get",
|
|
1646
|
-
"set",
|
|
1647
|
-
"add",
|
|
1648
|
-
"delete",
|
|
1649
|
-
"clear",
|
|
1650
1687
|
"toString",
|
|
1651
1688
|
"toLocaleString",
|
|
1652
1689
|
"valueOf",
|
|
@@ -1677,6 +1714,7 @@ var PURE_NAMESPACES = /* @__PURE__ */ new Set([
|
|
|
1677
1714
|
"Boolean",
|
|
1678
1715
|
"console"
|
|
1679
1716
|
]);
|
|
1717
|
+
var IMPURE_NAMESPACE_METHODS = /* @__PURE__ */ new Set(["JSON.parse"]);
|
|
1680
1718
|
var PURE_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
1681
1719
|
"Map",
|
|
1682
1720
|
"Set",
|
|
@@ -1713,7 +1751,7 @@ function isPureCall(node) {
|
|
|
1713
1751
|
return false;
|
|
1714
1752
|
}
|
|
1715
1753
|
if (callee.object.type === import_utils12.AST_NODE_TYPES.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
|
|
1716
|
-
return
|
|
1754
|
+
return !IMPURE_NAMESPACE_METHODS.has(`${callee.object.name}.${property.name}`);
|
|
1717
1755
|
}
|
|
1718
1756
|
return PURE_METHODS.has(property.name);
|
|
1719
1757
|
}
|
|
@@ -5287,7 +5325,7 @@ var no_type_member_comment_wall_default = createRule({
|
|
|
5287
5325
|
create(context, [provided]) {
|
|
5288
5326
|
const options = { ...WALL_DEFAULTS, ...provided };
|
|
5289
5327
|
const sourceCode = context.sourceCode;
|
|
5290
|
-
if (isGeneratedFile(context.filename, sourceCode.text) || isTestFile(context.filename) || isStoryFile(context.filename)) {
|
|
5328
|
+
if (isGeneratedFile(context.filename, sourceCode.text, ["externalTree"]) || isTestFile(context.filename, ["fixtureTree"]) || isStoryFile(context.filename, ["storyTree"])) {
|
|
5291
5329
|
return {};
|
|
5292
5330
|
}
|
|
5293
5331
|
const endingOn = /* @__PURE__ */ new Map();
|
|
@@ -6267,7 +6305,7 @@ var DEFAULT_FACTORIES = [
|
|
|
6267
6305
|
"tuple",
|
|
6268
6306
|
"union"
|
|
6269
6307
|
];
|
|
6270
|
-
var DEFAULT_MIN_PROPERTIES =
|
|
6308
|
+
var DEFAULT_MIN_PROPERTIES = 2;
|
|
6271
6309
|
var MEMO_CALLEES = /* @__PURE__ */ new Set([
|
|
6272
6310
|
"lazy",
|
|
6273
6311
|
"memo",
|
|
@@ -6283,6 +6321,34 @@ var TERMINAL_METHODS = /* @__PURE__ */ new Set([
|
|
|
6283
6321
|
"safeParseAsync",
|
|
6284
6322
|
"spa"
|
|
6285
6323
|
]);
|
|
6324
|
+
var ZOD_COMBINATOR_METHODS = /* @__PURE__ */ new Set([
|
|
6325
|
+
"and",
|
|
6326
|
+
"array",
|
|
6327
|
+
"catch",
|
|
6328
|
+
"catchall",
|
|
6329
|
+
"default",
|
|
6330
|
+
"extend",
|
|
6331
|
+
"merge",
|
|
6332
|
+
"or",
|
|
6333
|
+
"pipe",
|
|
6334
|
+
"refine",
|
|
6335
|
+
"superRefine",
|
|
6336
|
+
"transform"
|
|
6337
|
+
]);
|
|
6338
|
+
var I18N_CALLEE_NAMES = /* @__PURE__ */ new Set([
|
|
6339
|
+
"$t",
|
|
6340
|
+
"defineMessage",
|
|
6341
|
+
"gettext",
|
|
6342
|
+
"msg",
|
|
6343
|
+
"ngettext",
|
|
6344
|
+
"t",
|
|
6345
|
+
"translate"
|
|
6346
|
+
]);
|
|
6347
|
+
var I18N_RECEIVER_NAMES = /* @__PURE__ */ new Set([
|
|
6348
|
+
"$i18n",
|
|
6349
|
+
"i18n",
|
|
6350
|
+
"intl"
|
|
6351
|
+
]);
|
|
6286
6352
|
var FUNCTION_TYPES6 = /* @__PURE__ */ new Set([
|
|
6287
6353
|
import_utils45.AST_NODE_TYPES.ArrowFunctionExpression,
|
|
6288
6354
|
import_utils45.AST_NODE_TYPES.FunctionDeclaration,
|
|
@@ -6316,7 +6382,7 @@ function outermostEnclosingFunction(node) {
|
|
|
6316
6382
|
}
|
|
6317
6383
|
return outermost;
|
|
6318
6384
|
}
|
|
6319
|
-
function
|
|
6385
|
+
function subtreeSome(root, predicate) {
|
|
6320
6386
|
let found = false;
|
|
6321
6387
|
const visit = (value) => {
|
|
6322
6388
|
if (found || value === null || typeof value !== "object") {
|
|
@@ -6332,7 +6398,7 @@ function readsReceiver(node) {
|
|
|
6332
6398
|
if (typeof candidate.type !== "string") {
|
|
6333
6399
|
return;
|
|
6334
6400
|
}
|
|
6335
|
-
if (candidate
|
|
6401
|
+
if (predicate(candidate)) {
|
|
6336
6402
|
found = true;
|
|
6337
6403
|
return;
|
|
6338
6404
|
}
|
|
@@ -6343,9 +6409,30 @@ function readsReceiver(node) {
|
|
|
6343
6409
|
visit(candidate[key]);
|
|
6344
6410
|
}
|
|
6345
6411
|
};
|
|
6346
|
-
visit(
|
|
6412
|
+
visit(root);
|
|
6347
6413
|
return found;
|
|
6348
6414
|
}
|
|
6415
|
+
function readsReceiver(node) {
|
|
6416
|
+
return subtreeSome(
|
|
6417
|
+
node,
|
|
6418
|
+
(inner) => inner.type === import_utils45.AST_NODE_TYPES.ThisExpression || inner.type === import_utils45.AST_NODE_TYPES.Super || inner.type === import_utils45.AST_NODE_TYPES.Identifier && inner.name === "arguments"
|
|
6419
|
+
);
|
|
6420
|
+
}
|
|
6421
|
+
function buildsLocalizedText(node) {
|
|
6422
|
+
return subtreeSome(node, (inner) => {
|
|
6423
|
+
if (inner.type === import_utils45.AST_NODE_TYPES.TaggedTemplateExpression) {
|
|
6424
|
+
return true;
|
|
6425
|
+
}
|
|
6426
|
+
if (inner.type !== import_utils45.AST_NODE_TYPES.CallExpression) {
|
|
6427
|
+
return false;
|
|
6428
|
+
}
|
|
6429
|
+
const { callee } = inner;
|
|
6430
|
+
if (callee.type === import_utils45.AST_NODE_TYPES.Identifier) {
|
|
6431
|
+
return I18N_CALLEE_NAMES.has(callee.name);
|
|
6432
|
+
}
|
|
6433
|
+
return callee.type === import_utils45.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils45.AST_NODE_TYPES.Identifier && I18N_RECEIVER_NAMES.has(callee.object.name);
|
|
6434
|
+
});
|
|
6435
|
+
}
|
|
6349
6436
|
function collectReferences(scope, out) {
|
|
6350
6437
|
out.push(...scope.references);
|
|
6351
6438
|
for (const child of scope.childScopes) {
|
|
@@ -6415,6 +6502,31 @@ var prefer_module_level_schema_default = createRule({
|
|
|
6415
6502
|
}
|
|
6416
6503
|
return false;
|
|
6417
6504
|
}
|
|
6505
|
+
function outermostSchemaExpression(expression) {
|
|
6506
|
+
let confirmed = expression;
|
|
6507
|
+
let current = expression;
|
|
6508
|
+
for (; ; ) {
|
|
6509
|
+
const parent = current.parent ?? void 0;
|
|
6510
|
+
if (parent === void 0) {
|
|
6511
|
+
return confirmed;
|
|
6512
|
+
}
|
|
6513
|
+
if (parent.type === import_utils45.AST_NODE_TYPES.Property && parent.value === current || parent.type === import_utils45.AST_NODE_TYPES.ObjectExpression || parent.type === import_utils45.AST_NODE_TYPES.ArrayExpression) {
|
|
6514
|
+
current = parent;
|
|
6515
|
+
continue;
|
|
6516
|
+
}
|
|
6517
|
+
if (parent.type === import_utils45.AST_NODE_TYPES.CallExpression && parent.arguments.includes(current) && isSchemaComposition(parent)) {
|
|
6518
|
+
current = schemaExpression(parent);
|
|
6519
|
+
confirmed = current;
|
|
6520
|
+
continue;
|
|
6521
|
+
}
|
|
6522
|
+
return confirmed;
|
|
6523
|
+
}
|
|
6524
|
+
}
|
|
6525
|
+
function isSchemaComposition(node) {
|
|
6526
|
+
const { callee } = node;
|
|
6527
|
+
const isCombinator = callee.type === import_utils45.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils45.AST_NODE_TYPES.Identifier && ZOD_COMBINATOR_METHODS.has(callee.property.name);
|
|
6528
|
+
return isCombinator || isZodCall(node);
|
|
6529
|
+
}
|
|
6418
6530
|
function closesOverNothing(node, enclosing) {
|
|
6419
6531
|
const references = [];
|
|
6420
6532
|
collectReferences(sourceCode.getScope(node), references);
|
|
@@ -6434,6 +6546,9 @@ var prefer_module_level_schema_default = createRule({
|
|
|
6434
6546
|
continue;
|
|
6435
6547
|
}
|
|
6436
6548
|
const [defStart, defEnd] = definition.node.range;
|
|
6549
|
+
if (defStart >= schemaStart && defEnd <= schemaEnd) {
|
|
6550
|
+
continue;
|
|
6551
|
+
}
|
|
6437
6552
|
if (defStart >= functionStart && defEnd <= functionEnd) {
|
|
6438
6553
|
return false;
|
|
6439
6554
|
}
|
|
@@ -6492,6 +6607,13 @@ var prefer_module_level_schema_default = createRule({
|
|
|
6492
6607
|
if (readsReceiver(expression)) {
|
|
6493
6608
|
return;
|
|
6494
6609
|
}
|
|
6610
|
+
if (buildsLocalizedText(expression)) {
|
|
6611
|
+
return;
|
|
6612
|
+
}
|
|
6613
|
+
const outermost = outermostSchemaExpression(expression);
|
|
6614
|
+
if (outermost !== expression && (readsReceiver(outermost) || buildsLocalizedText(outermost) || !closesOverNothing(outermost, enclosing))) {
|
|
6615
|
+
return;
|
|
6616
|
+
}
|
|
6495
6617
|
if (!closesOverNothing(expression, enclosing)) {
|
|
6496
6618
|
return;
|
|
6497
6619
|
}
|
|
@@ -6891,7 +7013,14 @@ var STYLE_COLOR_PROPS = /* @__PURE__ */ new Set([
|
|
|
6891
7013
|
var RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\b|\\b(?:${COLOR_FN})\\s*\\(`, "i");
|
|
6892
7014
|
var CSS_VAR_REFERENCE_RE = /var\(\s*--/;
|
|
6893
7015
|
var STORIES_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
6894
|
-
var SEMANTIC_TOKEN_RE =
|
|
7016
|
+
var SEMANTIC_TOKEN_RE = /@theme\b|--(?:background|foreground|primary|secondary|muted|accent|destructive|border|card|popover)\b|(?:bg|text|border)-(?:background|foreground|primary|secondary|muted|accent|destructive|border|card|popover)\b/;
|
|
7017
|
+
var CONFIG_IS_SUFFICIENT = /* @__PURE__ */ new Set([
|
|
7018
|
+
"components.json",
|
|
7019
|
+
"tailwind.config.cjs",
|
|
7020
|
+
"tailwind.config.js",
|
|
7021
|
+
"tailwind.config.mjs",
|
|
7022
|
+
"tailwind.config.ts"
|
|
7023
|
+
]);
|
|
6895
7024
|
var DETECTION_FILES = [
|
|
6896
7025
|
"components.json",
|
|
6897
7026
|
"tailwind.config.js",
|
|
@@ -6904,8 +7033,17 @@ var DETECTION_FILES = [
|
|
|
6904
7033
|
"src/styles/globals.css",
|
|
6905
7034
|
"styles/globals.css"
|
|
6906
7035
|
];
|
|
6907
|
-
var
|
|
6908
|
-
|
|
7036
|
+
var WORKSPACE_ROOT_FILES = [
|
|
7037
|
+
"pnpm-workspace.yaml",
|
|
7038
|
+
"pnpm-workspace.yml",
|
|
7039
|
+
"turbo.json",
|
|
7040
|
+
"lerna.json"
|
|
7041
|
+
];
|
|
7042
|
+
var DEFAULT_WORKSPACE_GLOBS = ["packages/*", "apps/*"];
|
|
7043
|
+
var MAX_WORKSPACE_PACKAGES = 512;
|
|
7044
|
+
var ancestryCache = /* @__PURE__ */ new Map();
|
|
7045
|
+
var workspaceScanCache = /* @__PURE__ */ new Map();
|
|
7046
|
+
var workspaceRootCache = /* @__PURE__ */ new Map();
|
|
6909
7047
|
var SVG_DEFS_CONTAINERS = /* @__PURE__ */ new Set([
|
|
6910
7048
|
"mask",
|
|
6911
7049
|
"clipPath",
|
|
@@ -6971,48 +7109,134 @@ var isInsideIconFactoryPath = (node) => {
|
|
|
6971
7109
|
}
|
|
6972
7110
|
return false;
|
|
6973
7111
|
};
|
|
6974
|
-
var
|
|
6975
|
-
|
|
7112
|
+
var hasMarkerAt = (dir) => {
|
|
7113
|
+
for (const rel of DETECTION_FILES) {
|
|
7114
|
+
const candidate = (0, import_path.join)(dir, rel);
|
|
7115
|
+
if (!(0, import_fs.existsSync)(candidate)) continue;
|
|
7116
|
+
if (CONFIG_IS_SUFFICIENT.has(rel)) return true;
|
|
7117
|
+
try {
|
|
7118
|
+
if (SEMANTIC_TOKEN_RE.test((0, import_fs.readFileSync)(candidate, "utf8"))) return true;
|
|
7119
|
+
} catch {
|
|
7120
|
+
}
|
|
7121
|
+
}
|
|
7122
|
+
return false;
|
|
7123
|
+
};
|
|
7124
|
+
var hasMarkerAtOrAbove = (startDir) => {
|
|
7125
|
+
let dir = startDir;
|
|
6976
7126
|
const root = (0, import_path.parse)(dir).root;
|
|
6977
7127
|
const visited = [];
|
|
6978
7128
|
let answer;
|
|
6979
|
-
for (
|
|
6980
|
-
const cached =
|
|
7129
|
+
for (; ; ) {
|
|
7130
|
+
const cached = ancestryCache.get(dir);
|
|
6981
7131
|
if (cached !== void 0) {
|
|
6982
7132
|
answer = cached;
|
|
6983
7133
|
break;
|
|
6984
7134
|
}
|
|
6985
7135
|
visited.push(dir);
|
|
6986
|
-
|
|
6987
|
-
for (const rel of DETECTION_FILES) {
|
|
6988
|
-
const candidate = (0, import_path.join)(dir, rel);
|
|
6989
|
-
if (!(0, import_fs.existsSync)(candidate)) continue;
|
|
6990
|
-
if (rel === "components.json") {
|
|
6991
|
-
found = true;
|
|
6992
|
-
break;
|
|
6993
|
-
}
|
|
6994
|
-
try {
|
|
6995
|
-
if (SEMANTIC_TOKEN_RE.test((0, import_fs.readFileSync)(candidate, "utf8"))) {
|
|
6996
|
-
found = true;
|
|
6997
|
-
break;
|
|
6998
|
-
}
|
|
6999
|
-
} catch {
|
|
7000
|
-
}
|
|
7001
|
-
}
|
|
7002
|
-
if (found) {
|
|
7136
|
+
if (hasMarkerAt(dir)) {
|
|
7003
7137
|
answer = true;
|
|
7004
7138
|
break;
|
|
7005
7139
|
}
|
|
7006
|
-
|
|
7140
|
+
const parent = (0, import_path.dirname)(dir);
|
|
7141
|
+
if (dir === root || parent === dir) {
|
|
7007
7142
|
answer = false;
|
|
7008
7143
|
break;
|
|
7009
7144
|
}
|
|
7010
|
-
dir =
|
|
7145
|
+
dir = parent;
|
|
7146
|
+
}
|
|
7147
|
+
for (const seen of visited) ancestryCache.set(seen, answer);
|
|
7148
|
+
return answer;
|
|
7149
|
+
};
|
|
7150
|
+
var readWorkspaceGlobs = (dir) => {
|
|
7151
|
+
const globs = [];
|
|
7152
|
+
const packageJson = (0, import_path.join)(dir, "package.json");
|
|
7153
|
+
if ((0, import_fs.existsSync)(packageJson)) {
|
|
7154
|
+
try {
|
|
7155
|
+
const parsed = JSON.parse((0, import_fs.readFileSync)(packageJson, "utf8"));
|
|
7156
|
+
const declared = typeof parsed === "object" && parsed !== null && "workspaces" in parsed ? parsed.workspaces : void 0;
|
|
7157
|
+
const list = Array.isArray(declared) ? declared : typeof declared === "object" && declared !== null && Array.isArray(declared.packages) ? declared.packages : [];
|
|
7158
|
+
for (const entry of list) if (typeof entry === "string") globs.push(entry);
|
|
7159
|
+
} catch {
|
|
7160
|
+
}
|
|
7161
|
+
}
|
|
7162
|
+
for (const name of ["pnpm-workspace.yaml", "pnpm-workspace.yml"]) {
|
|
7163
|
+
const yaml = (0, import_path.join)(dir, name);
|
|
7164
|
+
if (!(0, import_fs.existsSync)(yaml)) continue;
|
|
7165
|
+
try {
|
|
7166
|
+
for (const line of (0, import_fs.readFileSync)(yaml, "utf8").split("\n")) {
|
|
7167
|
+
const match = /^\s*-\s*["']?([^"'#\s]+)["']?\s*$/u.exec(line);
|
|
7168
|
+
if (match?.[1] !== void 0) globs.push(match[1]);
|
|
7169
|
+
}
|
|
7170
|
+
} catch {
|
|
7171
|
+
}
|
|
7172
|
+
}
|
|
7173
|
+
return globs;
|
|
7174
|
+
};
|
|
7175
|
+
var expandWorkspaceGlob = (root, glob) => {
|
|
7176
|
+
const star = glob.indexOf("*");
|
|
7177
|
+
if (star === -1) return [(0, import_path.join)(root, glob)];
|
|
7178
|
+
const prefix = glob.slice(0, star).replace(/\/$/u, "");
|
|
7179
|
+
const parent = prefix === "" ? root : (0, import_path.join)(root, prefix);
|
|
7180
|
+
try {
|
|
7181
|
+
return (0, import_fs.readdirSync)(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => (0, import_path.join)(parent, entry.name));
|
|
7182
|
+
} catch {
|
|
7183
|
+
return [];
|
|
7184
|
+
}
|
|
7185
|
+
};
|
|
7186
|
+
var findWorkspaceRoot = (startDir) => {
|
|
7187
|
+
let dir = startDir;
|
|
7188
|
+
const root = (0, import_path.parse)(dir).root;
|
|
7189
|
+
const visited = [];
|
|
7190
|
+
let answer;
|
|
7191
|
+
for (; ; ) {
|
|
7192
|
+
const cached = workspaceRootCache.get(dir);
|
|
7193
|
+
if (cached !== void 0) {
|
|
7194
|
+
answer = cached;
|
|
7195
|
+
break;
|
|
7196
|
+
}
|
|
7197
|
+
visited.push(dir);
|
|
7198
|
+
if (WORKSPACE_ROOT_FILES.some((name) => (0, import_fs.existsSync)((0, import_path.join)(dir, name))) || readWorkspaceGlobs(dir).length > 0) {
|
|
7199
|
+
answer = dir;
|
|
7200
|
+
break;
|
|
7201
|
+
}
|
|
7202
|
+
const parent = (0, import_path.dirname)(dir);
|
|
7203
|
+
if (dir === root || parent === dir) {
|
|
7204
|
+
answer = null;
|
|
7205
|
+
break;
|
|
7206
|
+
}
|
|
7207
|
+
dir = parent;
|
|
7011
7208
|
}
|
|
7012
|
-
|
|
7013
|
-
for (const seen of visited) semanticTokenCache.set(seen, answer);
|
|
7209
|
+
for (const seen of visited) workspaceRootCache.set(seen, answer);
|
|
7014
7210
|
return answer;
|
|
7015
7211
|
};
|
|
7212
|
+
var workspaceHasMarker = (root) => {
|
|
7213
|
+
const cached = workspaceScanCache.get(root);
|
|
7214
|
+
if (cached !== void 0) return cached;
|
|
7215
|
+
const globs = readWorkspaceGlobs(root);
|
|
7216
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
7217
|
+
for (const glob of globs.length > 0 ? globs : DEFAULT_WORKSPACE_GLOBS) {
|
|
7218
|
+
for (const dir of expandWorkspaceGlob(root, glob)) {
|
|
7219
|
+
candidates.add(dir);
|
|
7220
|
+
if (candidates.size >= MAX_WORKSPACE_PACKAGES) break;
|
|
7221
|
+
}
|
|
7222
|
+
if (candidates.size >= MAX_WORKSPACE_PACKAGES) break;
|
|
7223
|
+
}
|
|
7224
|
+
let found = false;
|
|
7225
|
+
for (const dir of candidates) {
|
|
7226
|
+
if (hasMarkerAt(dir)) {
|
|
7227
|
+
found = true;
|
|
7228
|
+
break;
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
workspaceScanCache.set(root, found);
|
|
7232
|
+
return found;
|
|
7233
|
+
};
|
|
7234
|
+
var hasSemanticTokenSystem = (filename) => {
|
|
7235
|
+
const dir = (0, import_path.dirname)(filename);
|
|
7236
|
+
if (hasMarkerAtOrAbove(dir)) return true;
|
|
7237
|
+
const root = findWorkspaceRoot(dir);
|
|
7238
|
+
return root !== null && workspaceHasMarker(root);
|
|
7239
|
+
};
|
|
7016
7240
|
var propName = (key) => {
|
|
7017
7241
|
if (key.type === import_utils48.AST_NODE_TYPES.Identifier) return key.name;
|
|
7018
7242
|
if (key.type === import_utils48.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
|
|
@@ -7649,6 +7873,7 @@ var import_utils51 = require("@typescript-eslint/utils");
|
|
|
7649
7873
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
7650
7874
|
var ARRAY_MATCHERS = /* @__PURE__ */ new Set(["toEqual", "toStrictEqual"]);
|
|
7651
7875
|
var COLLECTION_PROPERTIES = /* @__PURE__ */ new Set(["length", "size"]);
|
|
7876
|
+
var LITERAL_KEY_HAZARDS = /* @__PURE__ */ new Set(["__proto__"]);
|
|
7652
7877
|
var NUMERIC_SIGNS2 = /* @__PURE__ */ new Set(["-", "+"]);
|
|
7653
7878
|
var MIN_RUN_LENGTH = 2;
|
|
7654
7879
|
function literalText(node, getText) {
|
|
@@ -7738,7 +7963,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
7738
7963
|
}
|
|
7739
7964
|
key = { kind: "index", index };
|
|
7740
7965
|
} else {
|
|
7741
|
-
if (actual.property.type !== import_utils51.AST_NODE_TYPES.Identifier || COLLECTION_PROPERTIES.has(actual.property.name)) {
|
|
7966
|
+
if (actual.property.type !== import_utils51.AST_NODE_TYPES.Identifier || COLLECTION_PROPERTIES.has(actual.property.name) || LITERAL_KEY_HAZARDS.has(actual.property.name)) {
|
|
7742
7967
|
return null;
|
|
7743
7968
|
}
|
|
7744
7969
|
key = { kind: "property", name: actual.property.name };
|
|
@@ -7763,6 +7988,11 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
7763
7988
|
expectedIsLiteral: literal !== null
|
|
7764
7989
|
};
|
|
7765
7990
|
}
|
|
7991
|
+
function hasInterveningComment(run) {
|
|
7992
|
+
return run.some(
|
|
7993
|
+
(assertion, index) => sourceCode.getCommentsInside(assertion.statement).length > 0 || index > 0 && sourceCode.getCommentsBefore(assertion.statement).length > 0
|
|
7994
|
+
);
|
|
7995
|
+
}
|
|
7766
7996
|
function reportPropertyRun(run) {
|
|
7767
7997
|
const names = /* @__PURE__ */ new Set();
|
|
7768
7998
|
for (const assertion of run) {
|
|
@@ -7789,7 +8019,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
7789
8019
|
node: first.statement,
|
|
7790
8020
|
messageId: "combineAssertions",
|
|
7791
8021
|
data: { count: String(run.length), receiver: receiverText },
|
|
7792
|
-
fix: (fixer) => [
|
|
8022
|
+
fix: hasInterveningComment(run) ? null : (fixer) => [
|
|
7793
8023
|
fixer.replaceText(first.statement, `expect(${receiverText}).toMatchObject({ ${properties} });`),
|
|
7794
8024
|
...run.slice(1).map((assertion) => fixer.remove(assertion.statement))
|
|
7795
8025
|
]
|
|
@@ -8954,6 +9184,54 @@ var renamedRules = {
|
|
|
8954
9184
|
"trailing-value-narration": "no-trailing-value-narration"
|
|
8955
9185
|
};
|
|
8956
9186
|
|
|
9187
|
+
// src/rules/_retired.ts
|
|
9188
|
+
var retiredRules = {
|
|
9189
|
+
"ban-loose-type-guards-in-tests": {
|
|
9190
|
+
removedIn: "5.0.0",
|
|
9191
|
+
reason: "Read at 39 findings with 0 true positives in the #183 corpus audit. Delete the config entry; no replacement."
|
|
9192
|
+
},
|
|
9193
|
+
"no-implicit-attribute-access": {
|
|
9194
|
+
removedIn: "5.0.0",
|
|
9195
|
+
reason: "Read at 50 findings with 0 true positives in the #183 corpus audit. Delete the config entry; no replacement."
|
|
9196
|
+
},
|
|
9197
|
+
"no-sequential-await": {
|
|
9198
|
+
removedIn: "3.0.0",
|
|
9199
|
+
reason: "218 findings, 100% range-contained in core `no-await-in-loop`, which the shipped config already enables. Delete the entry; `no-await-in-loop` covers it."
|
|
9200
|
+
},
|
|
9201
|
+
"no-template-literal-in-log": {
|
|
9202
|
+
removedIn: "2.3.1",
|
|
9203
|
+
reason: "Withdrawn. Delete the config entry; no replacement."
|
|
9204
|
+
},
|
|
9205
|
+
"no-unsafe-cast": {
|
|
9206
|
+
removedIn: "3.0.0",
|
|
9207
|
+
reason: '1,089 findings, matching `@typescript-eslint/consistent-type-assertions` ("never") at the identical line and column with zero residue. Delete the entry; keep that rule enabled.'
|
|
9208
|
+
},
|
|
9209
|
+
"prefer-setup-file-mocks": {
|
|
9210
|
+
removedIn: "5.0.0",
|
|
9211
|
+
reason: "Read at 50 findings with 0 true positives in the #183 corpus audit. Delete the config entry; no replacement."
|
|
9212
|
+
},
|
|
9213
|
+
"prefer-shadcn": {
|
|
9214
|
+
removedIn: "3.0.0",
|
|
9215
|
+
reason: "645 findings, a subset of `react/forbid-elements`; its 24-position residue was all design-system primitives being told not to be the design system. Delete the entry."
|
|
9216
|
+
},
|
|
9217
|
+
"primary-export-file-name": {
|
|
9218
|
+
removedIn: "4.0.0",
|
|
9219
|
+
reason: "Renamed files after one of their exports \u2014 316 findings over 1,966 files sampled 11 harmful / 15 useless / 4 valuable, including telling `next.config.ts` to become `next-config.ts`. Delete the config entry."
|
|
9220
|
+
},
|
|
9221
|
+
"require-parameterized-tests": {
|
|
9222
|
+
removedIn: "4.0.0",
|
|
9223
|
+
reason: "Landed in #153 and never wired up: absent from the `rules` record, every preset, and eslint.strict.mjs. Nothing to migrate."
|
|
9224
|
+
},
|
|
9225
|
+
"require-schema-validate-search": {
|
|
9226
|
+
removedIn: "3.0.0",
|
|
9227
|
+
reason: "14 findings, all matched line-and-column by `@typescript-eslint/consistent-type-assertions`. Delete the entry."
|
|
9228
|
+
},
|
|
9229
|
+
"single-public-export": {
|
|
9230
|
+
removedIn: "3.0.0",
|
|
9231
|
+
reason: "3 findings, all also reported by the then-live `primary-export-file-name` (itself withdrawn in 4.0.0). Delete the entry."
|
|
9232
|
+
}
|
|
9233
|
+
};
|
|
9234
|
+
|
|
8957
9235
|
// src/index.ts
|
|
8958
9236
|
var rules = {
|
|
8959
9237
|
"enforce-file-structure": enforce_file_structure_default,
|
|
@@ -9011,7 +9289,7 @@ var rules = {
|
|
|
9011
9289
|
};
|
|
9012
9290
|
var meta = {
|
|
9013
9291
|
name: "@sarj/eslint-plugin",
|
|
9014
|
-
version: "
|
|
9292
|
+
version: "8.0.0"
|
|
9015
9293
|
};
|
|
9016
9294
|
var renames = renamedRules;
|
|
9017
9295
|
var deprecatedAliases = Object.fromEntries(
|
|
@@ -9141,6 +9419,9 @@ var strictRules = {
|
|
|
9141
9419
|
var plugin = {
|
|
9142
9420
|
meta,
|
|
9143
9421
|
rules: allRules,
|
|
9422
|
+
// Withdrawn names travel WITH the plugin so a consumer's migration script and
|
|
9423
|
+
// this repo's gates read one map, not two. See src/rules/_retired.ts.
|
|
9424
|
+
retiredRules,
|
|
9144
9425
|
configs: {
|
|
9145
9426
|
recommended: {},
|
|
9146
9427
|
strict: {}
|
|
@@ -9161,6 +9442,7 @@ var index_default = plugin;
|
|
|
9161
9442
|
0 && (module.exports = {
|
|
9162
9443
|
recommendedRules,
|
|
9163
9444
|
renamedRules,
|
|
9445
|
+
retiredRules,
|
|
9164
9446
|
rules,
|
|
9165
9447
|
strictRules
|
|
9166
9448
|
});
|