@sarj/eslint-plugin 16.14.2 → 16.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +45 -54
- package/dist/index.js +146 -155
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
52
52
|
// package.json
|
|
53
53
|
var package_default = {
|
|
54
54
|
name: "@sarj/eslint-plugin",
|
|
55
|
-
version: "16.14.
|
|
55
|
+
version: "16.14.4",
|
|
56
56
|
packageManager: "npm@12.2.0",
|
|
57
57
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
58
58
|
type: "module",
|
|
@@ -382,6 +382,7 @@ function deepFreeze(value) {
|
|
|
382
382
|
}
|
|
383
383
|
|
|
384
384
|
// src/rules/_paths.ts
|
|
385
|
+
var import_node_path = require("path");
|
|
385
386
|
var LINE_TERMINATOR_RE = /[\n\r\u2028\u2029]/u;
|
|
386
387
|
var SCRIPT_FILE_RE = /(?:^|[\\/])scripts[\\/]|\.mjs$/;
|
|
387
388
|
var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
|
|
@@ -465,6 +466,10 @@ function leadingCommentBodies(sourceText) {
|
|
|
465
466
|
function isScriptFile(filename) {
|
|
466
467
|
return SCRIPT_FILE_RE.test(filename);
|
|
467
468
|
}
|
|
469
|
+
function matchesAnyPattern(filename, patterns) {
|
|
470
|
+
const normalized = filename.replaceAll("\\", "/");
|
|
471
|
+
return patterns.some((pattern) => import_node_path.posix.matchesGlob(normalized, pattern.replaceAll("\\", "/")));
|
|
472
|
+
}
|
|
468
473
|
function commentLineEnd(sourceText, start) {
|
|
469
474
|
const end = sourceText.slice(start).search(LINE_TERMINATOR_RE);
|
|
470
475
|
return end === -1 ? sourceText.length : start + end;
|
|
@@ -5842,15 +5847,6 @@ var NO_ENUM_DOCUMENTATION = {
|
|
|
5842
5847
|
{ id: "generated-header", scenarioId: "native-header-boundary", title: "Respect a native generated banner", outcome: "no-match", files: [{ path: "src/status.ts", source: '// auto-generated file\u2028const marker="auto-generated file"; enum Mode {Start} console.log(Mode.Start, marker);' }], focusPath: "src/status.ts", expectedCount: 0, public: true }
|
|
5843
5848
|
]
|
|
5844
5849
|
};
|
|
5845
|
-
function matchesAnyPattern(filename, patterns) {
|
|
5846
|
-
for (const pattern of patterns) {
|
|
5847
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
5848
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
5849
|
-
return true;
|
|
5850
|
-
}
|
|
5851
|
-
}
|
|
5852
|
-
return false;
|
|
5853
|
-
}
|
|
5854
5850
|
var no_enum_default = createRule({
|
|
5855
5851
|
name: "no-enum",
|
|
5856
5852
|
documentation: NO_ENUM_DOCUMENTATION,
|
|
@@ -6515,15 +6511,6 @@ var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
|
|
|
6515
6511
|
]);
|
|
6516
6512
|
var CLIENT_ONLY_MODULES = /^(react|react-dom|react-native|svelte|vue|preact|solid-js)(\/|$)|^next\/(navigation|router|link|image)$/;
|
|
6517
6513
|
var RACE_METHODS = /* @__PURE__ */ new Set(["race", "any"]);
|
|
6518
|
-
function matchesAnyPattern2(filename, patterns) {
|
|
6519
|
-
for (const pattern of patterns) {
|
|
6520
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
6521
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
6522
|
-
return true;
|
|
6523
|
-
}
|
|
6524
|
-
}
|
|
6525
|
-
return false;
|
|
6526
|
-
}
|
|
6527
6514
|
function isSetTimeoutCallee(callee) {
|
|
6528
6515
|
callee = unwrapExpression(callee);
|
|
6529
6516
|
if (callee.type === import_utils37.AST_NODE_TYPES.Identifier) {
|
|
@@ -6629,7 +6616,7 @@ var no_hand_rolled_sleep_default = createRule({
|
|
|
6629
6616
|
return {};
|
|
6630
6617
|
}
|
|
6631
6618
|
const allowIn = optionsArg?.allowIn ?? [];
|
|
6632
|
-
if (allowIn.length > 0 &&
|
|
6619
|
+
if (allowIn.length > 0 && matchesAnyPattern(filename, allowIn)) {
|
|
6633
6620
|
return {};
|
|
6634
6621
|
}
|
|
6635
6622
|
const checkClientModules = optionsArg?.checkClientModules ?? false;
|
|
@@ -16398,7 +16385,7 @@ function unwrapTransparentExport(node) {
|
|
|
16398
16385
|
var import_utils95 = require("@typescript-eslint/utils");
|
|
16399
16386
|
var import_typescript_estree = require("@typescript-eslint/typescript-estree");
|
|
16400
16387
|
var import_node_fs = require("fs");
|
|
16401
|
-
var
|
|
16388
|
+
var import_node_path2 = require("path");
|
|
16402
16389
|
var import_jsonc_parser = require("jsonc-parser");
|
|
16403
16390
|
var PREFER_SHADCN_PRIMITIVES_DOCUMENTATION = {
|
|
16404
16391
|
summary: "Require visible raw JSX controls to use the corresponding shared shadcn primitive.",
|
|
@@ -16460,9 +16447,9 @@ var AMBIGUOUS_INPUT_TYPES = /* @__PURE__ */ new Set([
|
|
|
16460
16447
|
var MAX_PROJECT_FILE_BYTES = 1048576;
|
|
16461
16448
|
var PROJECT_PRIMITIVES_CACHE = /* @__PURE__ */ new Map();
|
|
16462
16449
|
function detectProjectPrimitives(filename, requested) {
|
|
16463
|
-
const packageRoot = findPackageRoot((0,
|
|
16450
|
+
const packageRoot = findPackageRoot((0, import_node_path2.dirname)(filename));
|
|
16464
16451
|
if (packageRoot === null) return { available: /* @__PURE__ */ new Set(), uiRoot: null };
|
|
16465
|
-
const manifest = readJsonc((0,
|
|
16452
|
+
const manifest = readJsonc((0, import_node_path2.join)(packageRoot, "components.json"));
|
|
16466
16453
|
const alias = stringProperty(manifest, "aliases", "ui");
|
|
16467
16454
|
const unresolvedUiRoot = alias === null ? null : resolveAlias(packageRoot, alias);
|
|
16468
16455
|
if (unresolvedUiRoot === null) return { available: /* @__PURE__ */ new Set(), uiRoot: null };
|
|
@@ -16474,14 +16461,14 @@ function detectProjectPrimitives(filename, requested) {
|
|
|
16474
16461
|
for (const [capability, moduleName] of Object.entries(CAPABILITIES)) {
|
|
16475
16462
|
if (!requested.has(capability)) continue;
|
|
16476
16463
|
moduleCandidates.set(capability, ["tsx", "ts", "jsx", "js"].flatMap((extension) => [
|
|
16477
|
-
(0,
|
|
16478
|
-
(0,
|
|
16464
|
+
(0, import_node_path2.join)(uiRoot, `${moduleName}.${extension}`),
|
|
16465
|
+
(0, import_node_path2.join)(uiRoot, moduleName, `index.${extension}`)
|
|
16479
16466
|
]));
|
|
16480
16467
|
}
|
|
16481
16468
|
const fingerprint = [
|
|
16482
|
-
(0,
|
|
16483
|
-
(0,
|
|
16484
|
-
(0,
|
|
16469
|
+
(0, import_node_path2.join)(packageRoot, "components.json"),
|
|
16470
|
+
(0, import_node_path2.join)(packageRoot, "tsconfig.json"),
|
|
16471
|
+
(0, import_node_path2.join)(packageRoot, "jsconfig.json"),
|
|
16485
16472
|
...[...moduleCandidates.values()].flat()
|
|
16486
16473
|
].map(fileFingerprint).join("|");
|
|
16487
16474
|
const cacheKey = `${packageRoot}:${[...requested].sort().join(",")}`;
|
|
@@ -16508,8 +16495,8 @@ function fileFingerprint(path) {
|
|
|
16508
16495
|
}
|
|
16509
16496
|
}
|
|
16510
16497
|
function isWithin2(root, candidate2) {
|
|
16511
|
-
const path = (0,
|
|
16512
|
-
return path === "" || !path.startsWith(`..${
|
|
16498
|
+
const path = (0, import_node_path2.relative)(root, candidate2);
|
|
16499
|
+
return path === "" || !path.startsWith(`..${import_node_path2.sep}`) && path !== ".." && !(0, import_node_path2.isAbsolute)(path);
|
|
16513
16500
|
}
|
|
16514
16501
|
function safeContainedDirectory(root, candidate2) {
|
|
16515
16502
|
try {
|
|
@@ -16523,10 +16510,10 @@ function safeContainedDirectory(root, candidate2) {
|
|
|
16523
16510
|
}
|
|
16524
16511
|
function findPackageRoot(startDir) {
|
|
16525
16512
|
let dir = startDir;
|
|
16526
|
-
const filesystemRoot = (0,
|
|
16513
|
+
const filesystemRoot = (0, import_node_path2.parse)(dir).root;
|
|
16527
16514
|
for (; ; ) {
|
|
16528
|
-
if ((0, import_node_fs.existsSync)((0,
|
|
16529
|
-
const parent = (0,
|
|
16515
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path2.join)(dir, "package.json"))) return dir;
|
|
16516
|
+
const parent = (0, import_node_path2.dirname)(dir);
|
|
16530
16517
|
if (dir === filesystemRoot || parent === dir) return null;
|
|
16531
16518
|
dir = parent;
|
|
16532
16519
|
}
|
|
@@ -16563,9 +16550,9 @@ function stringProperty(value, ...keys) {
|
|
|
16563
16550
|
return typeof current === "string" && current.trim() !== "" ? current : null;
|
|
16564
16551
|
}
|
|
16565
16552
|
function resolveAlias(packageRoot, alias) {
|
|
16566
|
-
if ((0,
|
|
16567
|
-
if (alias.startsWith(".")) return (0,
|
|
16568
|
-
const configPath = ["tsconfig.json", "jsconfig.json"].map((name) => (0,
|
|
16553
|
+
if ((0, import_node_path2.isAbsolute)(alias)) return null;
|
|
16554
|
+
if (alias.startsWith(".")) return (0, import_node_path2.resolve)(packageRoot, alias);
|
|
16555
|
+
const configPath = ["tsconfig.json", "jsconfig.json"].map((name) => (0, import_node_path2.join)(packageRoot, name)).find(import_node_fs.existsSync);
|
|
16569
16556
|
if (configPath === void 0) return null;
|
|
16570
16557
|
const config = readJsonc(configPath);
|
|
16571
16558
|
if (typeof config !== "object" || config === null) return null;
|
|
@@ -16578,7 +16565,7 @@ function resolveAlias(packageRoot, alias) {
|
|
|
16578
16565
|
const matches = matchingAliasTargets(paths, alias);
|
|
16579
16566
|
const [match] = matches;
|
|
16580
16567
|
if (matches.length !== 1 || match === void 0) return null;
|
|
16581
|
-
return (0,
|
|
16568
|
+
return (0, import_node_path2.resolve)(packageRoot, baseUrl, match);
|
|
16582
16569
|
}
|
|
16583
16570
|
function exportsPrimitive(path, exportName) {
|
|
16584
16571
|
try {
|
|
@@ -18119,8 +18106,7 @@ function isNullish(node) {
|
|
|
18119
18106
|
}
|
|
18120
18107
|
function referenceCarrier(node, context, depth) {
|
|
18121
18108
|
if (node.typeName.type !== import_utils100.AST_NODE_TYPES.Identifier) return void 0;
|
|
18122
|
-
const
|
|
18123
|
-
const definitions = variable?.defs ?? [];
|
|
18109
|
+
const definitions = typeDefinitions(node, context);
|
|
18124
18110
|
const args = node.typeArguments?.params;
|
|
18125
18111
|
if (definitions.length === 0 && ["Array", "ReadonlyArray"].includes(node.typeName.name) && args?.length === 1) {
|
|
18126
18112
|
return arrayCarrier(rawCarrier(args[0], context, depth + 1));
|
|
@@ -18130,6 +18116,17 @@ function referenceCarrier(node, context, depth) {
|
|
|
18130
18116
|
if (declaration?.type !== import_utils100.AST_NODE_TYPES.TSTypeAliasDeclaration || declaration.typeParameters !== void 0) return void 0;
|
|
18131
18117
|
return rawCarrier(declaration.typeAnnotation, context, depth + 1);
|
|
18132
18118
|
}
|
|
18119
|
+
function typeDefinitions(node, context) {
|
|
18120
|
+
if (node.typeName.type !== import_utils100.AST_NODE_TYPES.Identifier) return [];
|
|
18121
|
+
let scope = context.sourceCode.getScope(node);
|
|
18122
|
+
while (scope !== null) {
|
|
18123
|
+
const variable = scope.set.get(node.typeName.name);
|
|
18124
|
+
const definitions = variable?.defs.filter((definition) => definition.isTypeDefinition) ?? [];
|
|
18125
|
+
if (definitions.length > 0 || variable?.isTypeVariable === true) return definitions;
|
|
18126
|
+
scope = scope.upper;
|
|
18127
|
+
}
|
|
18128
|
+
return [];
|
|
18129
|
+
}
|
|
18133
18130
|
function rawCarrier(node, context, depth = 0) {
|
|
18134
18131
|
if (node === void 0 || depth >= MAX_ALIAS_DEPTH) return void 0;
|
|
18135
18132
|
switch (node.type) {
|
|
@@ -18200,6 +18197,9 @@ var prefer_nominal_id_types_default = createRule({
|
|
|
18200
18197
|
FunctionExpression: (node) => checkBoundary(node, context),
|
|
18201
18198
|
TSDeclareFunction: (node) => checkBoundary(node, context),
|
|
18202
18199
|
TSEmptyBodyFunctionExpression: (node) => checkBoundary(node, context),
|
|
18200
|
+
TSCallSignatureDeclaration: (node) => checkBoundary(node, context),
|
|
18201
|
+
TSConstructSignatureDeclaration: (node) => checkBoundary(node, context),
|
|
18202
|
+
TSConstructorType: (node) => checkBoundary(node, context),
|
|
18203
18203
|
TSFunctionType: (node) => checkBoundary(node, context),
|
|
18204
18204
|
TSMethodSignature: (node) => checkBoundary(node, context)
|
|
18205
18205
|
};
|
|
@@ -22666,15 +22666,6 @@ var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
|
|
|
22666
22666
|
}
|
|
22667
22667
|
]
|
|
22668
22668
|
};
|
|
22669
|
-
function matchesAnyPattern3(filename, patterns) {
|
|
22670
|
-
for (const pattern of patterns) {
|
|
22671
|
-
const regexSource = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "::DOUBLESTAR::").replace(/\*/g, "[^/\\\\]*").replace(/::DOUBLESTAR::/g, ".*");
|
|
22672
|
-
if (new RegExp(`^${regexSource}$`).test(filename)) {
|
|
22673
|
-
return true;
|
|
22674
|
-
}
|
|
22675
|
-
}
|
|
22676
|
-
return false;
|
|
22677
|
-
}
|
|
22678
22669
|
function emptySignal(expression, resolvesToGlobal) {
|
|
22679
22670
|
const value = unwrapExpression(expression);
|
|
22680
22671
|
if (value.type === import_utils121.AST_NODE_TYPES.Literal && value.value === null)
|
|
@@ -22755,7 +22746,7 @@ var require_fetch_timeout_default = createRule({
|
|
|
22755
22746
|
return {};
|
|
22756
22747
|
}
|
|
22757
22748
|
const allowIn = optionsArg?.allowIn ?? [];
|
|
22758
|
-
if (allowIn.length > 0 &&
|
|
22749
|
+
if (allowIn.length > 0 && matchesAnyPattern(context.filename, allowIn)) {
|
|
22759
22750
|
return {};
|
|
22760
22751
|
}
|
|
22761
22752
|
function resolvesToGlobal(identifier) {
|
|
@@ -24871,7 +24862,7 @@ var import_utils131 = require("@typescript-eslint/utils");
|
|
|
24871
24862
|
|
|
24872
24863
|
// src/rules/_is-framework-entrypoint.ts
|
|
24873
24864
|
var import_node_fs2 = require("fs");
|
|
24874
|
-
var
|
|
24865
|
+
var import_node_path3 = require("path");
|
|
24875
24866
|
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]);
|
|
24876
24867
|
var NEXT_COMPONENT = /^(?:src\/)?app\/(?:.*\/)?(?:page|layout|loading|not-found|template|error|global-error|default|forbidden|unauthorized)\.[jt]sx?$/u;
|
|
24877
24868
|
var NEXT_METADATA = /^(?:src\/)?app\/(?:.*\/)?(?:(?:opengraph-image|twitter-image|icon|apple-icon)\.[jt]sx?|(?:robots|sitemap|manifest)\.[jt]s)$/u;
|
|
@@ -24881,7 +24872,7 @@ function isFrameworkEntrypoint(filename, exportKey) {
|
|
|
24881
24872
|
if (!/(?:^|\/)(?:app|pages)\/|(?:^|\/)(?:middleware|proxy|instrumentation)\.[jt]s$/u.test(normalized)) return false;
|
|
24882
24873
|
const owner = packageOwner(normalized);
|
|
24883
24874
|
if (owner === null) return false;
|
|
24884
|
-
const path = (0,
|
|
24875
|
+
const path = (0, import_node_path3.relative)(owner.root, normalized).replaceAll("\\", "/");
|
|
24885
24876
|
if (declaresFramework(owner.metadata, "next") && isNextEntrypoint(path, exportKey)) return true;
|
|
24886
24877
|
return declaresFramework(owner.metadata, "astro") && isAstroEntrypoint(path, exportKey);
|
|
24887
24878
|
}
|
|
@@ -24903,14 +24894,14 @@ function isAstroEntrypoint(path, exportKey) {
|
|
|
24903
24894
|
);
|
|
24904
24895
|
}
|
|
24905
24896
|
function packageOwner(filename) {
|
|
24906
|
-
let root = (0,
|
|
24897
|
+
let root = (0, import_node_path3.dirname)(filename);
|
|
24907
24898
|
while (true) {
|
|
24908
24899
|
try {
|
|
24909
|
-
return { root, metadata: JSON.parse((0, import_node_fs2.readFileSync)((0,
|
|
24900
|
+
return { root, metadata: JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path3.join)(root, "package.json"), "utf8")) };
|
|
24910
24901
|
} catch (error) {
|
|
24911
24902
|
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "ENOENT") return null;
|
|
24912
24903
|
}
|
|
24913
|
-
const parent = (0,
|
|
24904
|
+
const parent = (0, import_node_path3.dirname)(root);
|
|
24914
24905
|
if (parent === root) return null;
|
|
24915
24906
|
root = parent;
|
|
24916
24907
|
}
|