@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.js
CHANGED
|
@@ -12,25 +12,41 @@ var createRule = ESLintUtils.RuleCreator(evidenceUrl);
|
|
|
12
12
|
// src/rules/_paths.ts
|
|
13
13
|
var SCRIPT_FILE_RE = /([\\/]scripts[\\/])|(\.mjs$)/;
|
|
14
14
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
15
|
-
var
|
|
16
|
-
var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types|vendor|vendored|
|
|
17
|
-
var
|
|
18
|
-
|
|
15
|
+
var STORY_TREE_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
|
|
16
|
+
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$)/;
|
|
17
|
+
var EXTERNAL_TREE_RE = /[\\/]external[\\/]/;
|
|
18
|
+
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;
|
|
19
|
+
var TEST_BASENAME_RE = /[.\-_](test|spec|e2e)\.[cm]?[jt]sx?$/;
|
|
20
|
+
var TEST_INTEGRATION_BASENAME_RE = /\.integration\.[cm]?[jt]sx?$/;
|
|
21
|
+
var TEST_DIR_RE = /(^|\/)(tests?|__tests__|__mocks__|fixtures|__fixtures__|__testfixtures__|e2e|integration)\//;
|
|
22
|
+
var FIXTURE_TREE_RE = /(^|\/)fixture\//;
|
|
23
|
+
function isTestFile(filename, gates = []) {
|
|
19
24
|
const normalized = filename.replaceAll("\\", "/");
|
|
20
25
|
const base = normalized.slice(normalized.lastIndexOf("/") + 1);
|
|
21
|
-
if (
|
|
26
|
+
if (TEST_BASENAME_RE.test(base) || TEST_INTEGRATION_BASENAME_RE.test(base)) {
|
|
22
27
|
return true;
|
|
23
28
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
if (TEST_DIR_RE.test(normalized)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return gates.includes("fixtureTree") && FIXTURE_TREE_RE.test(normalized);
|
|
27
33
|
}
|
|
28
|
-
function isStoryFile(filename) {
|
|
34
|
+
function isStoryFile(filename, gates = []) {
|
|
29
35
|
const normalized = filename.replaceAll("\\", "/");
|
|
30
|
-
|
|
36
|
+
if (STORY_FILE_RE.test(normalized)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return gates.includes("storyTree") && STORY_TREE_RE.test(normalized);
|
|
31
40
|
}
|
|
32
|
-
function isGeneratedFile(filename, sourceText = "") {
|
|
33
|
-
|
|
41
|
+
function isGeneratedFile(filename, sourceText = "", gates = []) {
|
|
42
|
+
const normalized = filename.replaceAll("\\", "/");
|
|
43
|
+
if (GENERATED_FILE_RE.test(normalized)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (gates.includes("externalTree") && EXTERNAL_TREE_RE.test(normalized)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return GENERATED_MARKER_RE.test(sourceText.slice(0, 2048));
|
|
34
50
|
}
|
|
35
51
|
function isScriptFile(filename) {
|
|
36
52
|
return SCRIPT_FILE_RE.test(filename);
|
|
@@ -115,6 +131,10 @@ var enforce_file_structure_default = createRule({
|
|
|
115
131
|
|
|
116
132
|
// src/rules/no-async-callback-in-wait-for.ts
|
|
117
133
|
import { AST_NODE_TYPES as AST_NODE_TYPES2 } from "@typescript-eslint/utils";
|
|
134
|
+
var isWaitForCallee = (callee) => {
|
|
135
|
+
if (callee.type === AST_NODE_TYPES2.Identifier) return callee.name === "waitFor";
|
|
136
|
+
return callee.type === AST_NODE_TYPES2.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES2.Identifier && callee.property.name === "waitFor";
|
|
137
|
+
};
|
|
118
138
|
var no_async_callback_in_wait_for_default = createRule({
|
|
119
139
|
name: "no-async-callback-in-wait-for",
|
|
120
140
|
meta: {
|
|
@@ -134,14 +154,13 @@ var no_async_callback_in_wait_for_default = createRule({
|
|
|
134
154
|
}
|
|
135
155
|
return {
|
|
136
156
|
CallExpression(node) {
|
|
137
|
-
if (node.callee
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
157
|
+
if (!isWaitForCallee(node.callee)) return;
|
|
158
|
+
const callback = node.arguments[0];
|
|
159
|
+
if (callback && (callback.type === AST_NODE_TYPES2.ArrowFunctionExpression || callback.type === AST_NODE_TYPES2.FunctionExpression) && callback.async) {
|
|
160
|
+
context.report({
|
|
161
|
+
node: callback,
|
|
162
|
+
messageId: "noAsyncCallbackInWaitFor"
|
|
163
|
+
});
|
|
145
164
|
}
|
|
146
165
|
}
|
|
147
166
|
};
|
|
@@ -769,6 +788,12 @@ var no_comment_cruft_default = createRule({
|
|
|
769
788
|
// src/rules/no-conditional-in-test.ts
|
|
770
789
|
import { AST_NODE_TYPES as AST_NODE_TYPES6 } from "@typescript-eslint/utils";
|
|
771
790
|
var TEST_CALLERS = /* @__PURE__ */ new Set(["it", "test"]);
|
|
791
|
+
var HOOK_MEMBERS = /* @__PURE__ */ new Set([
|
|
792
|
+
"afterAll",
|
|
793
|
+
"afterEach",
|
|
794
|
+
"beforeAll",
|
|
795
|
+
"beforeEach"
|
|
796
|
+
]);
|
|
772
797
|
var FUNCTION_TYPES = /* @__PURE__ */ new Set([
|
|
773
798
|
AST_NODE_TYPES6.FunctionDeclaration,
|
|
774
799
|
AST_NODE_TYPES6.FunctionExpression,
|
|
@@ -812,6 +837,9 @@ function isTestBody(fn) {
|
|
|
812
837
|
if (call?.type !== AST_NODE_TYPES6.CallExpression || !call.arguments.some((argument) => argument === fn)) {
|
|
813
838
|
return false;
|
|
814
839
|
}
|
|
840
|
+
if (call.callee.type === AST_NODE_TYPES6.MemberExpression && !call.callee.computed && call.callee.property.type === AST_NODE_TYPES6.Identifier && HOOK_MEMBERS.has(call.callee.property.name)) {
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
815
843
|
const name = testCallerName(call.callee);
|
|
816
844
|
return name !== null && TEST_CALLERS.has(name);
|
|
817
845
|
}
|
|
@@ -966,8 +994,26 @@ function isTypeLevelNarrowing(node) {
|
|
|
966
994
|
return isTypeAssertionBranch(node.consequent) && (node.alternate === null || isTypeAssertionBranch(node.alternate));
|
|
967
995
|
}
|
|
968
996
|
var isInertBranch = (branch) => !containsAssertion(branch) && !containsEscape(branch) && !containsSkipCall(branch);
|
|
997
|
+
function isNormalizationStatement(statement) {
|
|
998
|
+
if (statement.type === AST_NODE_TYPES6.VariableDeclaration) {
|
|
999
|
+
return true;
|
|
1000
|
+
}
|
|
1001
|
+
if (statement.type === AST_NODE_TYPES6.BlockStatement) {
|
|
1002
|
+
return statement.body.every(isNormalizationStatement);
|
|
1003
|
+
}
|
|
1004
|
+
if (statement.type !== AST_NODE_TYPES6.ExpressionStatement) {
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
const { expression } = statement;
|
|
1008
|
+
return expression.type === AST_NODE_TYPES6.AssignmentExpression || expression.type === AST_NODE_TYPES6.UpdateExpression || expression.type === AST_NODE_TYPES6.UnaryExpression && expression.operator === "delete";
|
|
1009
|
+
}
|
|
969
1010
|
function isInertNormalization(node) {
|
|
970
|
-
|
|
1011
|
+
const branches = [node.consequent, node.alternate].filter(
|
|
1012
|
+
(branch) => branch !== null
|
|
1013
|
+
);
|
|
1014
|
+
return branches.every(
|
|
1015
|
+
(branch) => isInertBranch(branch) && isNormalizationStatement(branch)
|
|
1016
|
+
);
|
|
971
1017
|
}
|
|
972
1018
|
function isExemptIfStatement(node) {
|
|
973
1019
|
return isPinnedNarrowingGuard(node) || isThrowingGuard(node) || isTypeLevelNarrowing(node) || isInertNormalization(node);
|
|
@@ -1575,7 +1621,6 @@ var PURE_METHODS = /* @__PURE__ */ new Set([
|
|
|
1575
1621
|
"forEach",
|
|
1576
1622
|
"reduce",
|
|
1577
1623
|
"reduceRight",
|
|
1578
|
-
"find",
|
|
1579
1624
|
"findIndex",
|
|
1580
1625
|
"findLast",
|
|
1581
1626
|
"findLastIndex",
|
|
@@ -1598,15 +1643,6 @@ var PURE_METHODS = /* @__PURE__ */ new Set([
|
|
|
1598
1643
|
"indexOf",
|
|
1599
1644
|
"lastIndexOf",
|
|
1600
1645
|
"at",
|
|
1601
|
-
"keys",
|
|
1602
|
-
"values",
|
|
1603
|
-
"entries",
|
|
1604
|
-
"has",
|
|
1605
|
-
"get",
|
|
1606
|
-
"set",
|
|
1607
|
-
"add",
|
|
1608
|
-
"delete",
|
|
1609
|
-
"clear",
|
|
1610
1646
|
"toString",
|
|
1611
1647
|
"toLocaleString",
|
|
1612
1648
|
"valueOf",
|
|
@@ -1637,6 +1673,7 @@ var PURE_NAMESPACES = /* @__PURE__ */ new Set([
|
|
|
1637
1673
|
"Boolean",
|
|
1638
1674
|
"console"
|
|
1639
1675
|
]);
|
|
1676
|
+
var IMPURE_NAMESPACE_METHODS = /* @__PURE__ */ new Set(["JSON.parse"]);
|
|
1640
1677
|
var PURE_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
1641
1678
|
"Map",
|
|
1642
1679
|
"Set",
|
|
@@ -1673,7 +1710,7 @@ function isPureCall(node) {
|
|
|
1673
1710
|
return false;
|
|
1674
1711
|
}
|
|
1675
1712
|
if (callee.object.type === AST_NODE_TYPES9.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
|
|
1676
|
-
return
|
|
1713
|
+
return !IMPURE_NAMESPACE_METHODS.has(`${callee.object.name}.${property.name}`);
|
|
1677
1714
|
}
|
|
1678
1715
|
return PURE_METHODS.has(property.name);
|
|
1679
1716
|
}
|
|
@@ -5247,7 +5284,7 @@ var no_type_member_comment_wall_default = createRule({
|
|
|
5247
5284
|
create(context, [provided]) {
|
|
5248
5285
|
const options = { ...WALL_DEFAULTS, ...provided };
|
|
5249
5286
|
const sourceCode = context.sourceCode;
|
|
5250
|
-
if (isGeneratedFile(context.filename, sourceCode.text) || isTestFile(context.filename) || isStoryFile(context.filename)) {
|
|
5287
|
+
if (isGeneratedFile(context.filename, sourceCode.text, ["externalTree"]) || isTestFile(context.filename, ["fixtureTree"]) || isStoryFile(context.filename, ["storyTree"])) {
|
|
5251
5288
|
return {};
|
|
5252
5289
|
}
|
|
5253
5290
|
const endingOn = /* @__PURE__ */ new Map();
|
|
@@ -6230,7 +6267,7 @@ var DEFAULT_FACTORIES = [
|
|
|
6230
6267
|
"tuple",
|
|
6231
6268
|
"union"
|
|
6232
6269
|
];
|
|
6233
|
-
var DEFAULT_MIN_PROPERTIES =
|
|
6270
|
+
var DEFAULT_MIN_PROPERTIES = 2;
|
|
6234
6271
|
var MEMO_CALLEES = /* @__PURE__ */ new Set([
|
|
6235
6272
|
"lazy",
|
|
6236
6273
|
"memo",
|
|
@@ -6246,6 +6283,34 @@ var TERMINAL_METHODS = /* @__PURE__ */ new Set([
|
|
|
6246
6283
|
"safeParseAsync",
|
|
6247
6284
|
"spa"
|
|
6248
6285
|
]);
|
|
6286
|
+
var ZOD_COMBINATOR_METHODS = /* @__PURE__ */ new Set([
|
|
6287
|
+
"and",
|
|
6288
|
+
"array",
|
|
6289
|
+
"catch",
|
|
6290
|
+
"catchall",
|
|
6291
|
+
"default",
|
|
6292
|
+
"extend",
|
|
6293
|
+
"merge",
|
|
6294
|
+
"or",
|
|
6295
|
+
"pipe",
|
|
6296
|
+
"refine",
|
|
6297
|
+
"superRefine",
|
|
6298
|
+
"transform"
|
|
6299
|
+
]);
|
|
6300
|
+
var I18N_CALLEE_NAMES = /* @__PURE__ */ new Set([
|
|
6301
|
+
"$t",
|
|
6302
|
+
"defineMessage",
|
|
6303
|
+
"gettext",
|
|
6304
|
+
"msg",
|
|
6305
|
+
"ngettext",
|
|
6306
|
+
"t",
|
|
6307
|
+
"translate"
|
|
6308
|
+
]);
|
|
6309
|
+
var I18N_RECEIVER_NAMES = /* @__PURE__ */ new Set([
|
|
6310
|
+
"$i18n",
|
|
6311
|
+
"i18n",
|
|
6312
|
+
"intl"
|
|
6313
|
+
]);
|
|
6249
6314
|
var FUNCTION_TYPES6 = /* @__PURE__ */ new Set([
|
|
6250
6315
|
AST_NODE_TYPES31.ArrowFunctionExpression,
|
|
6251
6316
|
AST_NODE_TYPES31.FunctionDeclaration,
|
|
@@ -6279,7 +6344,7 @@ function outermostEnclosingFunction(node) {
|
|
|
6279
6344
|
}
|
|
6280
6345
|
return outermost;
|
|
6281
6346
|
}
|
|
6282
|
-
function
|
|
6347
|
+
function subtreeSome(root, predicate) {
|
|
6283
6348
|
let found = false;
|
|
6284
6349
|
const visit = (value) => {
|
|
6285
6350
|
if (found || value === null || typeof value !== "object") {
|
|
@@ -6295,7 +6360,7 @@ function readsReceiver(node) {
|
|
|
6295
6360
|
if (typeof candidate.type !== "string") {
|
|
6296
6361
|
return;
|
|
6297
6362
|
}
|
|
6298
|
-
if (candidate
|
|
6363
|
+
if (predicate(candidate)) {
|
|
6299
6364
|
found = true;
|
|
6300
6365
|
return;
|
|
6301
6366
|
}
|
|
@@ -6306,9 +6371,30 @@ function readsReceiver(node) {
|
|
|
6306
6371
|
visit(candidate[key]);
|
|
6307
6372
|
}
|
|
6308
6373
|
};
|
|
6309
|
-
visit(
|
|
6374
|
+
visit(root);
|
|
6310
6375
|
return found;
|
|
6311
6376
|
}
|
|
6377
|
+
function readsReceiver(node) {
|
|
6378
|
+
return subtreeSome(
|
|
6379
|
+
node,
|
|
6380
|
+
(inner) => inner.type === AST_NODE_TYPES31.ThisExpression || inner.type === AST_NODE_TYPES31.Super || inner.type === AST_NODE_TYPES31.Identifier && inner.name === "arguments"
|
|
6381
|
+
);
|
|
6382
|
+
}
|
|
6383
|
+
function buildsLocalizedText(node) {
|
|
6384
|
+
return subtreeSome(node, (inner) => {
|
|
6385
|
+
if (inner.type === AST_NODE_TYPES31.TaggedTemplateExpression) {
|
|
6386
|
+
return true;
|
|
6387
|
+
}
|
|
6388
|
+
if (inner.type !== AST_NODE_TYPES31.CallExpression) {
|
|
6389
|
+
return false;
|
|
6390
|
+
}
|
|
6391
|
+
const { callee } = inner;
|
|
6392
|
+
if (callee.type === AST_NODE_TYPES31.Identifier) {
|
|
6393
|
+
return I18N_CALLEE_NAMES.has(callee.name);
|
|
6394
|
+
}
|
|
6395
|
+
return callee.type === AST_NODE_TYPES31.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES31.Identifier && I18N_RECEIVER_NAMES.has(callee.object.name);
|
|
6396
|
+
});
|
|
6397
|
+
}
|
|
6312
6398
|
function collectReferences(scope, out) {
|
|
6313
6399
|
out.push(...scope.references);
|
|
6314
6400
|
for (const child of scope.childScopes) {
|
|
@@ -6378,6 +6464,31 @@ var prefer_module_level_schema_default = createRule({
|
|
|
6378
6464
|
}
|
|
6379
6465
|
return false;
|
|
6380
6466
|
}
|
|
6467
|
+
function outermostSchemaExpression(expression) {
|
|
6468
|
+
let confirmed = expression;
|
|
6469
|
+
let current = expression;
|
|
6470
|
+
for (; ; ) {
|
|
6471
|
+
const parent = current.parent ?? void 0;
|
|
6472
|
+
if (parent === void 0) {
|
|
6473
|
+
return confirmed;
|
|
6474
|
+
}
|
|
6475
|
+
if (parent.type === AST_NODE_TYPES31.Property && parent.value === current || parent.type === AST_NODE_TYPES31.ObjectExpression || parent.type === AST_NODE_TYPES31.ArrayExpression) {
|
|
6476
|
+
current = parent;
|
|
6477
|
+
continue;
|
|
6478
|
+
}
|
|
6479
|
+
if (parent.type === AST_NODE_TYPES31.CallExpression && parent.arguments.includes(current) && isSchemaComposition(parent)) {
|
|
6480
|
+
current = schemaExpression(parent);
|
|
6481
|
+
confirmed = current;
|
|
6482
|
+
continue;
|
|
6483
|
+
}
|
|
6484
|
+
return confirmed;
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6487
|
+
function isSchemaComposition(node) {
|
|
6488
|
+
const { callee } = node;
|
|
6489
|
+
const isCombinator = callee.type === AST_NODE_TYPES31.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES31.Identifier && ZOD_COMBINATOR_METHODS.has(callee.property.name);
|
|
6490
|
+
return isCombinator || isZodCall(node);
|
|
6491
|
+
}
|
|
6381
6492
|
function closesOverNothing(node, enclosing) {
|
|
6382
6493
|
const references = [];
|
|
6383
6494
|
collectReferences(sourceCode.getScope(node), references);
|
|
@@ -6397,6 +6508,9 @@ var prefer_module_level_schema_default = createRule({
|
|
|
6397
6508
|
continue;
|
|
6398
6509
|
}
|
|
6399
6510
|
const [defStart, defEnd] = definition.node.range;
|
|
6511
|
+
if (defStart >= schemaStart && defEnd <= schemaEnd) {
|
|
6512
|
+
continue;
|
|
6513
|
+
}
|
|
6400
6514
|
if (defStart >= functionStart && defEnd <= functionEnd) {
|
|
6401
6515
|
return false;
|
|
6402
6516
|
}
|
|
@@ -6455,6 +6569,13 @@ var prefer_module_level_schema_default = createRule({
|
|
|
6455
6569
|
if (readsReceiver(expression)) {
|
|
6456
6570
|
return;
|
|
6457
6571
|
}
|
|
6572
|
+
if (buildsLocalizedText(expression)) {
|
|
6573
|
+
return;
|
|
6574
|
+
}
|
|
6575
|
+
const outermost = outermostSchemaExpression(expression);
|
|
6576
|
+
if (outermost !== expression && (readsReceiver(outermost) || buildsLocalizedText(outermost) || !closesOverNothing(outermost, enclosing))) {
|
|
6577
|
+
return;
|
|
6578
|
+
}
|
|
6458
6579
|
if (!closesOverNothing(expression, enclosing)) {
|
|
6459
6580
|
return;
|
|
6460
6581
|
}
|
|
@@ -6813,7 +6934,7 @@ var prefer_schema_for_api_payload_default = createRule({
|
|
|
6813
6934
|
|
|
6814
6935
|
// src/rules/prefer-semantic-colors.ts
|
|
6815
6936
|
import { AST_NODE_TYPES as AST_NODE_TYPES34 } from "@typescript-eslint/utils";
|
|
6816
|
-
import { existsSync, readFileSync } from "fs";
|
|
6937
|
+
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
6817
6938
|
import { dirname, join, parse } from "path";
|
|
6818
6939
|
|
|
6819
6940
|
// src/rules/_tailwind.ts
|
|
@@ -6854,7 +6975,14 @@ var STYLE_COLOR_PROPS = /* @__PURE__ */ new Set([
|
|
|
6854
6975
|
var RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\b|\\b(?:${COLOR_FN})\\s*\\(`, "i");
|
|
6855
6976
|
var CSS_VAR_REFERENCE_RE = /var\(\s*--/;
|
|
6856
6977
|
var STORIES_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
6857
|
-
var SEMANTIC_TOKEN_RE =
|
|
6978
|
+
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/;
|
|
6979
|
+
var CONFIG_IS_SUFFICIENT = /* @__PURE__ */ new Set([
|
|
6980
|
+
"components.json",
|
|
6981
|
+
"tailwind.config.cjs",
|
|
6982
|
+
"tailwind.config.js",
|
|
6983
|
+
"tailwind.config.mjs",
|
|
6984
|
+
"tailwind.config.ts"
|
|
6985
|
+
]);
|
|
6858
6986
|
var DETECTION_FILES = [
|
|
6859
6987
|
"components.json",
|
|
6860
6988
|
"tailwind.config.js",
|
|
@@ -6867,8 +6995,17 @@ var DETECTION_FILES = [
|
|
|
6867
6995
|
"src/styles/globals.css",
|
|
6868
6996
|
"styles/globals.css"
|
|
6869
6997
|
];
|
|
6870
|
-
var
|
|
6871
|
-
|
|
6998
|
+
var WORKSPACE_ROOT_FILES = [
|
|
6999
|
+
"pnpm-workspace.yaml",
|
|
7000
|
+
"pnpm-workspace.yml",
|
|
7001
|
+
"turbo.json",
|
|
7002
|
+
"lerna.json"
|
|
7003
|
+
];
|
|
7004
|
+
var DEFAULT_WORKSPACE_GLOBS = ["packages/*", "apps/*"];
|
|
7005
|
+
var MAX_WORKSPACE_PACKAGES = 512;
|
|
7006
|
+
var ancestryCache = /* @__PURE__ */ new Map();
|
|
7007
|
+
var workspaceScanCache = /* @__PURE__ */ new Map();
|
|
7008
|
+
var workspaceRootCache = /* @__PURE__ */ new Map();
|
|
6872
7009
|
var SVG_DEFS_CONTAINERS = /* @__PURE__ */ new Set([
|
|
6873
7010
|
"mask",
|
|
6874
7011
|
"clipPath",
|
|
@@ -6934,48 +7071,134 @@ var isInsideIconFactoryPath = (node) => {
|
|
|
6934
7071
|
}
|
|
6935
7072
|
return false;
|
|
6936
7073
|
};
|
|
6937
|
-
var
|
|
6938
|
-
|
|
7074
|
+
var hasMarkerAt = (dir) => {
|
|
7075
|
+
for (const rel of DETECTION_FILES) {
|
|
7076
|
+
const candidate = join(dir, rel);
|
|
7077
|
+
if (!existsSync(candidate)) continue;
|
|
7078
|
+
if (CONFIG_IS_SUFFICIENT.has(rel)) return true;
|
|
7079
|
+
try {
|
|
7080
|
+
if (SEMANTIC_TOKEN_RE.test(readFileSync(candidate, "utf8"))) return true;
|
|
7081
|
+
} catch {
|
|
7082
|
+
}
|
|
7083
|
+
}
|
|
7084
|
+
return false;
|
|
7085
|
+
};
|
|
7086
|
+
var hasMarkerAtOrAbove = (startDir) => {
|
|
7087
|
+
let dir = startDir;
|
|
6939
7088
|
const root = parse(dir).root;
|
|
6940
7089
|
const visited = [];
|
|
6941
7090
|
let answer;
|
|
6942
|
-
for (
|
|
6943
|
-
const cached =
|
|
7091
|
+
for (; ; ) {
|
|
7092
|
+
const cached = ancestryCache.get(dir);
|
|
6944
7093
|
if (cached !== void 0) {
|
|
6945
7094
|
answer = cached;
|
|
6946
7095
|
break;
|
|
6947
7096
|
}
|
|
6948
7097
|
visited.push(dir);
|
|
6949
|
-
|
|
6950
|
-
for (const rel of DETECTION_FILES) {
|
|
6951
|
-
const candidate = join(dir, rel);
|
|
6952
|
-
if (!existsSync(candidate)) continue;
|
|
6953
|
-
if (rel === "components.json") {
|
|
6954
|
-
found = true;
|
|
6955
|
-
break;
|
|
6956
|
-
}
|
|
6957
|
-
try {
|
|
6958
|
-
if (SEMANTIC_TOKEN_RE.test(readFileSync(candidate, "utf8"))) {
|
|
6959
|
-
found = true;
|
|
6960
|
-
break;
|
|
6961
|
-
}
|
|
6962
|
-
} catch {
|
|
6963
|
-
}
|
|
6964
|
-
}
|
|
6965
|
-
if (found) {
|
|
7098
|
+
if (hasMarkerAt(dir)) {
|
|
6966
7099
|
answer = true;
|
|
6967
7100
|
break;
|
|
6968
7101
|
}
|
|
6969
|
-
|
|
7102
|
+
const parent = dirname(dir);
|
|
7103
|
+
if (dir === root || parent === dir) {
|
|
6970
7104
|
answer = false;
|
|
6971
7105
|
break;
|
|
6972
7106
|
}
|
|
6973
|
-
dir =
|
|
7107
|
+
dir = parent;
|
|
7108
|
+
}
|
|
7109
|
+
for (const seen of visited) ancestryCache.set(seen, answer);
|
|
7110
|
+
return answer;
|
|
7111
|
+
};
|
|
7112
|
+
var readWorkspaceGlobs = (dir) => {
|
|
7113
|
+
const globs = [];
|
|
7114
|
+
const packageJson = join(dir, "package.json");
|
|
7115
|
+
if (existsSync(packageJson)) {
|
|
7116
|
+
try {
|
|
7117
|
+
const parsed = JSON.parse(readFileSync(packageJson, "utf8"));
|
|
7118
|
+
const declared = typeof parsed === "object" && parsed !== null && "workspaces" in parsed ? parsed.workspaces : void 0;
|
|
7119
|
+
const list = Array.isArray(declared) ? declared : typeof declared === "object" && declared !== null && Array.isArray(declared.packages) ? declared.packages : [];
|
|
7120
|
+
for (const entry of list) if (typeof entry === "string") globs.push(entry);
|
|
7121
|
+
} catch {
|
|
7122
|
+
}
|
|
7123
|
+
}
|
|
7124
|
+
for (const name of ["pnpm-workspace.yaml", "pnpm-workspace.yml"]) {
|
|
7125
|
+
const yaml = join(dir, name);
|
|
7126
|
+
if (!existsSync(yaml)) continue;
|
|
7127
|
+
try {
|
|
7128
|
+
for (const line of readFileSync(yaml, "utf8").split("\n")) {
|
|
7129
|
+
const match = /^\s*-\s*["']?([^"'#\s]+)["']?\s*$/u.exec(line);
|
|
7130
|
+
if (match?.[1] !== void 0) globs.push(match[1]);
|
|
7131
|
+
}
|
|
7132
|
+
} catch {
|
|
7133
|
+
}
|
|
7134
|
+
}
|
|
7135
|
+
return globs;
|
|
7136
|
+
};
|
|
7137
|
+
var expandWorkspaceGlob = (root, glob) => {
|
|
7138
|
+
const star = glob.indexOf("*");
|
|
7139
|
+
if (star === -1) return [join(root, glob)];
|
|
7140
|
+
const prefix = glob.slice(0, star).replace(/\/$/u, "");
|
|
7141
|
+
const parent = prefix === "" ? root : join(root, prefix);
|
|
7142
|
+
try {
|
|
7143
|
+
return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => join(parent, entry.name));
|
|
7144
|
+
} catch {
|
|
7145
|
+
return [];
|
|
7146
|
+
}
|
|
7147
|
+
};
|
|
7148
|
+
var findWorkspaceRoot = (startDir) => {
|
|
7149
|
+
let dir = startDir;
|
|
7150
|
+
const root = parse(dir).root;
|
|
7151
|
+
const visited = [];
|
|
7152
|
+
let answer;
|
|
7153
|
+
for (; ; ) {
|
|
7154
|
+
const cached = workspaceRootCache.get(dir);
|
|
7155
|
+
if (cached !== void 0) {
|
|
7156
|
+
answer = cached;
|
|
7157
|
+
break;
|
|
7158
|
+
}
|
|
7159
|
+
visited.push(dir);
|
|
7160
|
+
if (WORKSPACE_ROOT_FILES.some((name) => existsSync(join(dir, name))) || readWorkspaceGlobs(dir).length > 0) {
|
|
7161
|
+
answer = dir;
|
|
7162
|
+
break;
|
|
7163
|
+
}
|
|
7164
|
+
const parent = dirname(dir);
|
|
7165
|
+
if (dir === root || parent === dir) {
|
|
7166
|
+
answer = null;
|
|
7167
|
+
break;
|
|
7168
|
+
}
|
|
7169
|
+
dir = parent;
|
|
6974
7170
|
}
|
|
6975
|
-
|
|
6976
|
-
for (const seen of visited) semanticTokenCache.set(seen, answer);
|
|
7171
|
+
for (const seen of visited) workspaceRootCache.set(seen, answer);
|
|
6977
7172
|
return answer;
|
|
6978
7173
|
};
|
|
7174
|
+
var workspaceHasMarker = (root) => {
|
|
7175
|
+
const cached = workspaceScanCache.get(root);
|
|
7176
|
+
if (cached !== void 0) return cached;
|
|
7177
|
+
const globs = readWorkspaceGlobs(root);
|
|
7178
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
7179
|
+
for (const glob of globs.length > 0 ? globs : DEFAULT_WORKSPACE_GLOBS) {
|
|
7180
|
+
for (const dir of expandWorkspaceGlob(root, glob)) {
|
|
7181
|
+
candidates.add(dir);
|
|
7182
|
+
if (candidates.size >= MAX_WORKSPACE_PACKAGES) break;
|
|
7183
|
+
}
|
|
7184
|
+
if (candidates.size >= MAX_WORKSPACE_PACKAGES) break;
|
|
7185
|
+
}
|
|
7186
|
+
let found = false;
|
|
7187
|
+
for (const dir of candidates) {
|
|
7188
|
+
if (hasMarkerAt(dir)) {
|
|
7189
|
+
found = true;
|
|
7190
|
+
break;
|
|
7191
|
+
}
|
|
7192
|
+
}
|
|
7193
|
+
workspaceScanCache.set(root, found);
|
|
7194
|
+
return found;
|
|
7195
|
+
};
|
|
7196
|
+
var hasSemanticTokenSystem = (filename) => {
|
|
7197
|
+
const dir = dirname(filename);
|
|
7198
|
+
if (hasMarkerAtOrAbove(dir)) return true;
|
|
7199
|
+
const root = findWorkspaceRoot(dir);
|
|
7200
|
+
return root !== null && workspaceHasMarker(root);
|
|
7201
|
+
};
|
|
6979
7202
|
var propName = (key) => {
|
|
6980
7203
|
if (key.type === AST_NODE_TYPES34.Identifier) return key.name;
|
|
6981
7204
|
if (key.type === AST_NODE_TYPES34.Literal && typeof key.value === "string") return key.value;
|
|
@@ -7615,6 +7838,7 @@ import { AST_NODE_TYPES as AST_NODE_TYPES36 } from "@typescript-eslint/utils";
|
|
|
7615
7838
|
var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
7616
7839
|
var ARRAY_MATCHERS = /* @__PURE__ */ new Set(["toEqual", "toStrictEqual"]);
|
|
7617
7840
|
var COLLECTION_PROPERTIES = /* @__PURE__ */ new Set(["length", "size"]);
|
|
7841
|
+
var LITERAL_KEY_HAZARDS = /* @__PURE__ */ new Set(["__proto__"]);
|
|
7618
7842
|
var NUMERIC_SIGNS2 = /* @__PURE__ */ new Set(["-", "+"]);
|
|
7619
7843
|
var MIN_RUN_LENGTH = 2;
|
|
7620
7844
|
function literalText(node, getText) {
|
|
@@ -7704,7 +7928,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
7704
7928
|
}
|
|
7705
7929
|
key = { kind: "index", index };
|
|
7706
7930
|
} else {
|
|
7707
|
-
if (actual.property.type !== AST_NODE_TYPES36.Identifier || COLLECTION_PROPERTIES.has(actual.property.name)) {
|
|
7931
|
+
if (actual.property.type !== AST_NODE_TYPES36.Identifier || COLLECTION_PROPERTIES.has(actual.property.name) || LITERAL_KEY_HAZARDS.has(actual.property.name)) {
|
|
7708
7932
|
return null;
|
|
7709
7933
|
}
|
|
7710
7934
|
key = { kind: "property", name: actual.property.name };
|
|
@@ -7729,6 +7953,11 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
7729
7953
|
expectedIsLiteral: literal !== null
|
|
7730
7954
|
};
|
|
7731
7955
|
}
|
|
7956
|
+
function hasInterveningComment(run) {
|
|
7957
|
+
return run.some(
|
|
7958
|
+
(assertion, index) => sourceCode.getCommentsInside(assertion.statement).length > 0 || index > 0 && sourceCode.getCommentsBefore(assertion.statement).length > 0
|
|
7959
|
+
);
|
|
7960
|
+
}
|
|
7732
7961
|
function reportPropertyRun(run) {
|
|
7733
7962
|
const names = /* @__PURE__ */ new Set();
|
|
7734
7963
|
for (const assertion of run) {
|
|
@@ -7755,7 +7984,7 @@ var prefer_whole_object_assertion_default = createRule({
|
|
|
7755
7984
|
node: first.statement,
|
|
7756
7985
|
messageId: "combineAssertions",
|
|
7757
7986
|
data: { count: String(run.length), receiver: receiverText },
|
|
7758
|
-
fix: (fixer) => [
|
|
7987
|
+
fix: hasInterveningComment(run) ? null : (fixer) => [
|
|
7759
7988
|
fixer.replaceText(first.statement, `expect(${receiverText}).toMatchObject({ ${properties} });`),
|
|
7760
7989
|
...run.slice(1).map((assertion) => fixer.remove(assertion.statement))
|
|
7761
7990
|
]
|
|
@@ -8920,6 +9149,54 @@ var renamedRules = {
|
|
|
8920
9149
|
"trailing-value-narration": "no-trailing-value-narration"
|
|
8921
9150
|
};
|
|
8922
9151
|
|
|
9152
|
+
// src/rules/_retired.ts
|
|
9153
|
+
var retiredRules = {
|
|
9154
|
+
"ban-loose-type-guards-in-tests": {
|
|
9155
|
+
removedIn: "5.0.0",
|
|
9156
|
+
reason: "Read at 39 findings with 0 true positives in the #183 corpus audit. Delete the config entry; no replacement."
|
|
9157
|
+
},
|
|
9158
|
+
"no-implicit-attribute-access": {
|
|
9159
|
+
removedIn: "5.0.0",
|
|
9160
|
+
reason: "Read at 50 findings with 0 true positives in the #183 corpus audit. Delete the config entry; no replacement."
|
|
9161
|
+
},
|
|
9162
|
+
"no-sequential-await": {
|
|
9163
|
+
removedIn: "3.0.0",
|
|
9164
|
+
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."
|
|
9165
|
+
},
|
|
9166
|
+
"no-template-literal-in-log": {
|
|
9167
|
+
removedIn: "2.3.1",
|
|
9168
|
+
reason: "Withdrawn. Delete the config entry; no replacement."
|
|
9169
|
+
},
|
|
9170
|
+
"no-unsafe-cast": {
|
|
9171
|
+
removedIn: "3.0.0",
|
|
9172
|
+
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.'
|
|
9173
|
+
},
|
|
9174
|
+
"prefer-setup-file-mocks": {
|
|
9175
|
+
removedIn: "5.0.0",
|
|
9176
|
+
reason: "Read at 50 findings with 0 true positives in the #183 corpus audit. Delete the config entry; no replacement."
|
|
9177
|
+
},
|
|
9178
|
+
"prefer-shadcn": {
|
|
9179
|
+
removedIn: "3.0.0",
|
|
9180
|
+
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."
|
|
9181
|
+
},
|
|
9182
|
+
"primary-export-file-name": {
|
|
9183
|
+
removedIn: "4.0.0",
|
|
9184
|
+
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."
|
|
9185
|
+
},
|
|
9186
|
+
"require-parameterized-tests": {
|
|
9187
|
+
removedIn: "4.0.0",
|
|
9188
|
+
reason: "Landed in #153 and never wired up: absent from the `rules` record, every preset, and eslint.strict.mjs. Nothing to migrate."
|
|
9189
|
+
},
|
|
9190
|
+
"require-schema-validate-search": {
|
|
9191
|
+
removedIn: "3.0.0",
|
|
9192
|
+
reason: "14 findings, all matched line-and-column by `@typescript-eslint/consistent-type-assertions`. Delete the entry."
|
|
9193
|
+
},
|
|
9194
|
+
"single-public-export": {
|
|
9195
|
+
removedIn: "3.0.0",
|
|
9196
|
+
reason: "3 findings, all also reported by the then-live `primary-export-file-name` (itself withdrawn in 4.0.0). Delete the entry."
|
|
9197
|
+
}
|
|
9198
|
+
};
|
|
9199
|
+
|
|
8923
9200
|
// src/index.ts
|
|
8924
9201
|
var rules = {
|
|
8925
9202
|
"enforce-file-structure": enforce_file_structure_default,
|
|
@@ -8977,7 +9254,7 @@ var rules = {
|
|
|
8977
9254
|
};
|
|
8978
9255
|
var meta = {
|
|
8979
9256
|
name: "@sarj/eslint-plugin",
|
|
8980
|
-
version: "
|
|
9257
|
+
version: "8.0.0"
|
|
8981
9258
|
};
|
|
8982
9259
|
var renames = renamedRules;
|
|
8983
9260
|
var deprecatedAliases = Object.fromEntries(
|
|
@@ -9107,6 +9384,9 @@ var strictRules = {
|
|
|
9107
9384
|
var plugin = {
|
|
9108
9385
|
meta,
|
|
9109
9386
|
rules: allRules,
|
|
9387
|
+
// Withdrawn names travel WITH the plugin so a consumer's migration script and
|
|
9388
|
+
// this repo's gates read one map, not two. See src/rules/_retired.ts.
|
|
9389
|
+
retiredRules,
|
|
9110
9390
|
configs: {
|
|
9111
9391
|
recommended: {},
|
|
9112
9392
|
strict: {}
|
|
@@ -9127,6 +9407,7 @@ export {
|
|
|
9127
9407
|
index_default as default,
|
|
9128
9408
|
recommendedRules,
|
|
9129
9409
|
renamedRules,
|
|
9410
|
+
retiredRules,
|
|
9130
9411
|
rules,
|
|
9131
9412
|
strictRules
|
|
9132
9413
|
};
|