@sarj/eslint-plugin 2.15.0 → 2.16.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 +232 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +232 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -203,7 +203,7 @@ declare const rules: {
|
|
|
203
203
|
"no-client-side-data-fetching": _typescript_eslint_utils_ts_eslint.RuleModule<"noClientFetch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
204
204
|
name: string;
|
|
205
205
|
};
|
|
206
|
-
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
206
|
+
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration" | "untrackedTodo", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
207
207
|
name: string;
|
|
208
208
|
};
|
|
209
209
|
"no-enum": _typescript_eslint_utils_ts_eslint.RuleModule<"noEnum", readonly [{
|
|
@@ -283,6 +283,9 @@ declare const rules: {
|
|
|
283
283
|
"single-public-export": _typescript_eslint_utils_ts_eslint.RuleModule<"renameJunkDrawer", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
284
284
|
name: string;
|
|
285
285
|
};
|
|
286
|
+
"primary-export-file-name": _typescript_eslint_utils_ts_eslint.RuleModule<"primaryExportMismatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
287
|
+
name: string;
|
|
288
|
+
};
|
|
286
289
|
"no-silent-promise-catch": _typescript_eslint_utils_ts_eslint.RuleModule<"silentCatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
287
290
|
name: string;
|
|
288
291
|
};
|
|
@@ -352,6 +355,9 @@ declare const rules: {
|
|
|
352
355
|
"prefer-non-nullable-collection": _typescript_eslint_utils_ts_eslint.RuleModule<"preferNonNullableCollection", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
353
356
|
name: string;
|
|
354
357
|
};
|
|
358
|
+
"no-implicit-attribute-access": _typescript_eslint_utils_ts_eslint.RuleModule<"noImplicitAttributeAccess", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
359
|
+
name: string;
|
|
360
|
+
};
|
|
355
361
|
};
|
|
356
362
|
declare const plugin: {
|
|
357
363
|
meta: {
|
|
@@ -365,7 +371,7 @@ declare const plugin: {
|
|
|
365
371
|
"no-client-side-data-fetching": _typescript_eslint_utils_ts_eslint.RuleModule<"noClientFetch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
366
372
|
name: string;
|
|
367
373
|
};
|
|
368
|
-
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
374
|
+
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration" | "untrackedTodo", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
369
375
|
name: string;
|
|
370
376
|
};
|
|
371
377
|
"no-enum": _typescript_eslint_utils_ts_eslint.RuleModule<"noEnum", readonly [{
|
|
@@ -445,6 +451,9 @@ declare const plugin: {
|
|
|
445
451
|
"single-public-export": _typescript_eslint_utils_ts_eslint.RuleModule<"renameJunkDrawer", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
446
452
|
name: string;
|
|
447
453
|
};
|
|
454
|
+
"primary-export-file-name": _typescript_eslint_utils_ts_eslint.RuleModule<"primaryExportMismatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
455
|
+
name: string;
|
|
456
|
+
};
|
|
448
457
|
"no-silent-promise-catch": _typescript_eslint_utils_ts_eslint.RuleModule<"silentCatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
449
458
|
name: string;
|
|
450
459
|
};
|
|
@@ -514,6 +523,9 @@ declare const plugin: {
|
|
|
514
523
|
"prefer-non-nullable-collection": _typescript_eslint_utils_ts_eslint.RuleModule<"preferNonNullableCollection", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
515
524
|
name: string;
|
|
516
525
|
};
|
|
526
|
+
"no-implicit-attribute-access": _typescript_eslint_utils_ts_eslint.RuleModule<"noImplicitAttributeAccess", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
527
|
+
name: string;
|
|
528
|
+
};
|
|
517
529
|
};
|
|
518
530
|
configs: {
|
|
519
531
|
recommended: {
|
|
@@ -543,6 +555,7 @@ declare const plugin: {
|
|
|
543
555
|
"@sarj/no-secret-in-log": string;
|
|
544
556
|
"@sarj/no-unsafe-cast": string;
|
|
545
557
|
"@sarj/single-public-export": string;
|
|
558
|
+
"@sarj/primary-export-file-name": string;
|
|
546
559
|
"@sarj/prefer-string-literal-union": string;
|
|
547
560
|
"@sarj/require-fetch-timeout": string;
|
|
548
561
|
"@sarj/no-silent-promise-catch": string;
|
|
@@ -563,6 +576,7 @@ declare const plugin: {
|
|
|
563
576
|
"@sarj/no-tautological-expect": string;
|
|
564
577
|
"@sarj/require-interface-for-injected-service": string;
|
|
565
578
|
"@sarj/prefer-non-nullable-collection": string;
|
|
579
|
+
"@sarj/no-implicit-attribute-access": string;
|
|
566
580
|
};
|
|
567
581
|
};
|
|
568
582
|
strict: {
|
|
@@ -595,6 +609,7 @@ declare const plugin: {
|
|
|
595
609
|
"@sarj/no-secret-in-log": string;
|
|
596
610
|
"@sarj/no-unsafe-cast": string;
|
|
597
611
|
"@sarj/single-public-export": string;
|
|
612
|
+
"@sarj/primary-export-file-name": string;
|
|
598
613
|
"@sarj/prefer-string-literal-union": string;
|
|
599
614
|
"@sarj/require-fetch-timeout": string;
|
|
600
615
|
"@sarj/no-silent-promise-catch": string;
|
|
@@ -617,6 +632,7 @@ declare const plugin: {
|
|
|
617
632
|
"@sarj/no-tautological-expect": string;
|
|
618
633
|
"@sarj/require-interface-for-injected-service": string;
|
|
619
634
|
"@sarj/prefer-non-nullable-collection": string;
|
|
635
|
+
"@sarj/no-implicit-attribute-access": string;
|
|
620
636
|
};
|
|
621
637
|
};
|
|
622
638
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -203,7 +203,7 @@ declare const rules: {
|
|
|
203
203
|
"no-client-side-data-fetching": _typescript_eslint_utils_ts_eslint.RuleModule<"noClientFetch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
204
204
|
name: string;
|
|
205
205
|
};
|
|
206
|
-
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
206
|
+
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration" | "untrackedTodo", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
207
207
|
name: string;
|
|
208
208
|
};
|
|
209
209
|
"no-enum": _typescript_eslint_utils_ts_eslint.RuleModule<"noEnum", readonly [{
|
|
@@ -283,6 +283,9 @@ declare const rules: {
|
|
|
283
283
|
"single-public-export": _typescript_eslint_utils_ts_eslint.RuleModule<"renameJunkDrawer", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
284
284
|
name: string;
|
|
285
285
|
};
|
|
286
|
+
"primary-export-file-name": _typescript_eslint_utils_ts_eslint.RuleModule<"primaryExportMismatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
287
|
+
name: string;
|
|
288
|
+
};
|
|
286
289
|
"no-silent-promise-catch": _typescript_eslint_utils_ts_eslint.RuleModule<"silentCatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
287
290
|
name: string;
|
|
288
291
|
};
|
|
@@ -352,6 +355,9 @@ declare const rules: {
|
|
|
352
355
|
"prefer-non-nullable-collection": _typescript_eslint_utils_ts_eslint.RuleModule<"preferNonNullableCollection", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
353
356
|
name: string;
|
|
354
357
|
};
|
|
358
|
+
"no-implicit-attribute-access": _typescript_eslint_utils_ts_eslint.RuleModule<"noImplicitAttributeAccess", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
359
|
+
name: string;
|
|
360
|
+
};
|
|
355
361
|
};
|
|
356
362
|
declare const plugin: {
|
|
357
363
|
meta: {
|
|
@@ -365,7 +371,7 @@ declare const plugin: {
|
|
|
365
371
|
"no-client-side-data-fetching": _typescript_eslint_utils_ts_eslint.RuleModule<"noClientFetch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
366
372
|
name: string;
|
|
367
373
|
};
|
|
368
|
-
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
374
|
+
"no-comment-cruft": _typescript_eslint_utils_ts_eslint.RuleModule<"commentedOutCode" | "sectionBanner" | "fileHeaderPreamble" | "redundantNarration" | "untrackedTodo", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
369
375
|
name: string;
|
|
370
376
|
};
|
|
371
377
|
"no-enum": _typescript_eslint_utils_ts_eslint.RuleModule<"noEnum", readonly [{
|
|
@@ -445,6 +451,9 @@ declare const plugin: {
|
|
|
445
451
|
"single-public-export": _typescript_eslint_utils_ts_eslint.RuleModule<"renameJunkDrawer", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
446
452
|
name: string;
|
|
447
453
|
};
|
|
454
|
+
"primary-export-file-name": _typescript_eslint_utils_ts_eslint.RuleModule<"primaryExportMismatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
455
|
+
name: string;
|
|
456
|
+
};
|
|
448
457
|
"no-silent-promise-catch": _typescript_eslint_utils_ts_eslint.RuleModule<"silentCatch", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
449
458
|
name: string;
|
|
450
459
|
};
|
|
@@ -514,6 +523,9 @@ declare const plugin: {
|
|
|
514
523
|
"prefer-non-nullable-collection": _typescript_eslint_utils_ts_eslint.RuleModule<"preferNonNullableCollection", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
515
524
|
name: string;
|
|
516
525
|
};
|
|
526
|
+
"no-implicit-attribute-access": _typescript_eslint_utils_ts_eslint.RuleModule<"noImplicitAttributeAccess", [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
|
527
|
+
name: string;
|
|
528
|
+
};
|
|
517
529
|
};
|
|
518
530
|
configs: {
|
|
519
531
|
recommended: {
|
|
@@ -543,6 +555,7 @@ declare const plugin: {
|
|
|
543
555
|
"@sarj/no-secret-in-log": string;
|
|
544
556
|
"@sarj/no-unsafe-cast": string;
|
|
545
557
|
"@sarj/single-public-export": string;
|
|
558
|
+
"@sarj/primary-export-file-name": string;
|
|
546
559
|
"@sarj/prefer-string-literal-union": string;
|
|
547
560
|
"@sarj/require-fetch-timeout": string;
|
|
548
561
|
"@sarj/no-silent-promise-catch": string;
|
|
@@ -563,6 +576,7 @@ declare const plugin: {
|
|
|
563
576
|
"@sarj/no-tautological-expect": string;
|
|
564
577
|
"@sarj/require-interface-for-injected-service": string;
|
|
565
578
|
"@sarj/prefer-non-nullable-collection": string;
|
|
579
|
+
"@sarj/no-implicit-attribute-access": string;
|
|
566
580
|
};
|
|
567
581
|
};
|
|
568
582
|
strict: {
|
|
@@ -595,6 +609,7 @@ declare const plugin: {
|
|
|
595
609
|
"@sarj/no-secret-in-log": string;
|
|
596
610
|
"@sarj/no-unsafe-cast": string;
|
|
597
611
|
"@sarj/single-public-export": string;
|
|
612
|
+
"@sarj/primary-export-file-name": string;
|
|
598
613
|
"@sarj/prefer-string-literal-union": string;
|
|
599
614
|
"@sarj/require-fetch-timeout": string;
|
|
600
615
|
"@sarj/no-silent-promise-catch": string;
|
|
@@ -617,6 +632,7 @@ declare const plugin: {
|
|
|
617
632
|
"@sarj/no-tautological-expect": string;
|
|
618
633
|
"@sarj/require-interface-for-injected-service": string;
|
|
619
634
|
"@sarj/prefer-non-nullable-collection": string;
|
|
635
|
+
"@sarj/no-implicit-attribute-access": string;
|
|
620
636
|
};
|
|
621
637
|
};
|
|
622
638
|
};
|
package/dist/index.js
CHANGED
|
@@ -433,9 +433,9 @@ function restatesStatementHead(body, statement) {
|
|
|
433
433
|
|
|
434
434
|
// src/rules/no-comment-cruft.ts
|
|
435
435
|
var LEADING_PREAMBLE_MIN = 4;
|
|
436
|
-
var STEP_NARRATION_RE = /^(?:first(?:ly)?|second(?:ly)?|third(?:ly)?|then|next|after(?:wards| that)?|finally|lastly|now)\s*[,:]\s*\S
|
|
436
|
+
var STEP_NARRATION_RE = /^(?:first(?:ly)?|second(?:ly)?|third(?:ly)?|then|next|after(?:wards| that)?|finally|lastly|now)\s*[,:]\s*\S/i;
|
|
437
437
|
var META_COMMENTARY_RE = /\b(?:for now|keeping (?:it|this) simple|could be (?:refactored|improved|cleaned up|simplified)|refactor(?:ed|ing)? (?:later|this)|not sure (?:if|whether|why|how)|quick[- ](?:and[- ]dirty|fix)|(?:a |bit of a )?hacky|is a hack|temporary (?:solution|workaround|fix|hack)|revisit (?:this|later|below)|clean (?:this|it) up|not ideal|placeholder for now)\b/i;
|
|
438
|
-
var DIRECTIVE_RE = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|
|
|
438
|
+
var DIRECTIVE_RE = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|hack\b|xxx\b)/i;
|
|
439
439
|
var LICENSE_RE = /copyright|licen[cs]ed?|spdx|permission is hereby granted|all rights reserved/i;
|
|
440
440
|
var ENUMERATED_ITEM_RE = /^(?:\d+[.):]|[-*•])\s+\S/;
|
|
441
441
|
var ENUMERATED_ITEM_MIN_WORDS = 3;
|
|
@@ -501,7 +501,8 @@ function isSectionLabel(text) {
|
|
|
501
501
|
}
|
|
502
502
|
var HELPER_OPENER_RE = /^(?:a\s+)?helper\s+(?:function|method|component|hook|class|type|util(?:ity)?)\b/i;
|
|
503
503
|
var LETS_RE = /^let'?s\s+(?:not\s+|just\s+|now\s+|first\s+)?(?:add|append|assign|await|build|calculate|call|check|clear|close|compute|convert|copy|count|create|declare|decrement|define|delete|extract|fetch|filter|find|format|generate|get|handle|increment|init|initialise|initialize|insert|iterate|join|load|log|loop|map|merge|open|parse|print|process|push|read|remove|render|reset|return|save|send|set|setup|sort|split|start|stop|store|update|validate|wrap|write)(?:s|es|ed|ing)?\b/i;
|
|
504
|
-
var ENUMERATION_RE = /^(?:\d+[.)]\s+\S|phase\s+\d+\b)/i;
|
|
504
|
+
var ENUMERATION_RE = /^(?:\d+[.)]\s+\S|(?:phase|step)\s+\d+\b)/i;
|
|
505
|
+
var DUMMY_TRANSLATION_RE = /^(?:increment|return|returns|get|gets|set\b(?! up\b)|sets\b(?! up\b)|function to|method to)\b/i;
|
|
505
506
|
var DIAGRAM_ARROW_RE = /[-=~]{2,}>|<[-=~]{2,}/;
|
|
506
507
|
var CODE_KEYWORD_RE = /^(import |export |const |let |var |function\b|class |interface |type \w|enum |return\b|throw |await |async |if\s*\(|for\s*\(|while\s*\(|switch\s*\(|new |console\.)/;
|
|
507
508
|
var CODE_TAIL_RE = /[;{}()]\s*$|=>\s*$|,\s*$/;
|
|
@@ -549,6 +550,14 @@ function isRedundantNarration(body, statementBelow, standalone, isolatedEnumerat
|
|
|
549
550
|
if (STEP_NARRATION_RE.test(t)) return true;
|
|
550
551
|
if (META_COMMENTARY_RE.test(t) && !JUSTIFICATION_RE.test(t)) return true;
|
|
551
552
|
if (HELPER_OPENER_RE.test(t) || LETS_RE.test(t)) return true;
|
|
553
|
+
const words = t.split(/\s+/);
|
|
554
|
+
if (words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
|
|
555
|
+
const lowerT = t.toLowerCase();
|
|
556
|
+
const rationaleWords = ["when", "because", "if", "so that", "due to", "for", "instead of", "to prevent", "to avoid", "only"];
|
|
557
|
+
if (!rationaleWords.some((w) => lowerT.includes(w))) {
|
|
558
|
+
if (words.length > 1) return true;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
552
561
|
if (!nested && isSectionLabel(t)) return true;
|
|
553
562
|
if (isolatedEnumeration && ENUMERATION_RE.test(t)) return true;
|
|
554
563
|
}
|
|
@@ -616,7 +625,8 @@ var no_comment_cruft_default = ESLintUtils3.RuleCreator(
|
|
|
616
625
|
commentedOutCode: "Commented-out code \u2014 delete it; git history remembers.",
|
|
617
626
|
sectionBanner: "Section-banner / region comment \u2014 structure code with functions, not ASCII rules.",
|
|
618
627
|
fileHeaderPreamble: "File-header comment preamble \u2014 use a brief doc comment for the why, not a block of `//` lines.",
|
|
619
|
-
redundantNarration: "Comment narrates the code \u2014 delete it or say *why*, not *what*. Code is self-documenting."
|
|
628
|
+
redundantNarration: "Comment narrates the code \u2014 delete it or say *why*, not *what*. Code is self-documenting.",
|
|
629
|
+
untrackedTodo: "Untracked TODO/FIXME marker \u2014 add an issue ticket or context link."
|
|
620
630
|
}
|
|
621
631
|
},
|
|
622
632
|
defaultOptions: [],
|
|
@@ -670,6 +680,16 @@ var no_comment_cruft_default = ESLintUtils3.RuleCreator(
|
|
|
670
680
|
if (isJsDoc(comment) || !isStandalone(comment)) continue;
|
|
671
681
|
if (LICENSE_RE.test(comment.value)) continue;
|
|
672
682
|
const texts = comment.value.split("\n").map(stripCommentMarker).filter((l) => l.length > 0 && !isDirective(l));
|
|
683
|
+
const firstText = texts[0];
|
|
684
|
+
if (firstText !== void 0 && /^(?:todo|fixme)\b/i.test(firstText)) {
|
|
685
|
+
if (!runCitesAReference(comments, i)) {
|
|
686
|
+
context.report({
|
|
687
|
+
node: comment,
|
|
688
|
+
messageId: "untrackedTodo"
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
673
693
|
if (texts.some(isBanner)) {
|
|
674
694
|
context.report({ node: comment, messageId: "sectionBanner" });
|
|
675
695
|
continue;
|
|
@@ -7492,6 +7512,204 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
|
|
|
7492
7512
|
}
|
|
7493
7513
|
});
|
|
7494
7514
|
|
|
7515
|
+
// src/rules/primary-export-file-name.ts
|
|
7516
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
|
|
7517
|
+
var CONVENTIONAL_BUCKET_EXPORTS2 = /* @__PURE__ */ new Set(["cn"]);
|
|
7518
|
+
var GENERIC_ENTRYPOINTS = /* @__PURE__ */ new Set(["main", "run", "cli", "setup", "teardown", "execute"]);
|
|
7519
|
+
var ACRONYM_OVERRIDES2 = [
|
|
7520
|
+
[/OAuth/g, "Oauth"],
|
|
7521
|
+
[/GraphQL/g, "Graphql"],
|
|
7522
|
+
[/gRPC/g, "Grpc"]
|
|
7523
|
+
];
|
|
7524
|
+
var CAMEL_BOUNDARY_RE2 = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;
|
|
7525
|
+
var basename2 = (filename) => filename.split(/[/\\]/).pop() ?? filename;
|
|
7526
|
+
var stemOf2 = (base) => base.replace(/\.(test|spec|config|d|stories)\.[cm]?[jt]sx?$/i, "").replace(/\.[cm]?[jt]sx?$/i, "");
|
|
7527
|
+
var kebabCase3 = (name) => {
|
|
7528
|
+
let normalized = name;
|
|
7529
|
+
for (const [pattern, replacement] of ACRONYM_OVERRIDES2) {
|
|
7530
|
+
normalized = normalized.replace(pattern, replacement);
|
|
7531
|
+
}
|
|
7532
|
+
return normalized.replace(CAMEL_BOUNDARY_RE2, "-").toLowerCase();
|
|
7533
|
+
};
|
|
7534
|
+
var isFunctionOrClass = (node) => node.type === AST_NODE_TYPES35.ArrowFunctionExpression || node.type === AST_NODE_TYPES35.FunctionExpression;
|
|
7535
|
+
var findPrimaryExport = (body) => {
|
|
7536
|
+
let exportCount = 0;
|
|
7537
|
+
let primaryCandidate = null;
|
|
7538
|
+
for (const statement of body) {
|
|
7539
|
+
if (statement.type === AST_NODE_TYPES35.ExportAllDeclaration) {
|
|
7540
|
+
return null;
|
|
7541
|
+
}
|
|
7542
|
+
if (statement.type === AST_NODE_TYPES35.ExportDefaultDeclaration) {
|
|
7543
|
+
exportCount += 1;
|
|
7544
|
+
const decl = statement.declaration;
|
|
7545
|
+
if ((decl.type === AST_NODE_TYPES35.FunctionDeclaration || decl.type === AST_NODE_TYPES35.ClassDeclaration) && decl.id !== null) {
|
|
7546
|
+
primaryCandidate = { name: decl.id.name, node: statement, isDefault: true };
|
|
7547
|
+
} else if (decl.type === AST_NODE_TYPES35.Identifier) {
|
|
7548
|
+
primaryCandidate = { name: decl.name, node: statement, isDefault: true };
|
|
7549
|
+
}
|
|
7550
|
+
} else if (statement.type === AST_NODE_TYPES35.ExportNamedDeclaration) {
|
|
7551
|
+
if (statement.source !== null) {
|
|
7552
|
+
return null;
|
|
7553
|
+
}
|
|
7554
|
+
const decl = statement.declaration;
|
|
7555
|
+
if (decl === null) {
|
|
7556
|
+
exportCount += statement.specifiers.length;
|
|
7557
|
+
if (statement.specifiers.length === 1 && primaryCandidate === null) {
|
|
7558
|
+
const spec = statement.specifiers[0];
|
|
7559
|
+
if (spec && spec.exported.type === AST_NODE_TYPES35.Identifier) {
|
|
7560
|
+
primaryCandidate = { name: spec.exported.name, node: statement, isDefault: false };
|
|
7561
|
+
}
|
|
7562
|
+
}
|
|
7563
|
+
} else if (decl.type === AST_NODE_TYPES35.FunctionDeclaration || decl.type === AST_NODE_TYPES35.ClassDeclaration) {
|
|
7564
|
+
if (decl.id !== null) {
|
|
7565
|
+
exportCount += 1;
|
|
7566
|
+
if (primaryCandidate === null) {
|
|
7567
|
+
primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
} else if (decl.type === AST_NODE_TYPES35.VariableDeclaration) {
|
|
7571
|
+
for (const declarator of decl.declarations) {
|
|
7572
|
+
if (declarator.id.type === AST_NODE_TYPES35.Identifier) {
|
|
7573
|
+
exportCount += 1;
|
|
7574
|
+
if (primaryCandidate === null && declarator.init && isFunctionOrClass(declarator.init)) {
|
|
7575
|
+
primaryCandidate = { name: declarator.id.name, node: statement, isDefault: false };
|
|
7576
|
+
}
|
|
7577
|
+
}
|
|
7578
|
+
}
|
|
7579
|
+
} else if (decl.type === AST_NODE_TYPES35.TSTypeAliasDeclaration || decl.type === AST_NODE_TYPES35.TSInterfaceDeclaration) {
|
|
7580
|
+
exportCount += 1;
|
|
7581
|
+
if (primaryCandidate === null) {
|
|
7582
|
+
primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
|
|
7583
|
+
}
|
|
7584
|
+
}
|
|
7585
|
+
}
|
|
7586
|
+
}
|
|
7587
|
+
if (primaryCandidate === null || exportCount > 2) {
|
|
7588
|
+
return null;
|
|
7589
|
+
}
|
|
7590
|
+
return { ...primaryCandidate, count: exportCount };
|
|
7591
|
+
};
|
|
7592
|
+
var primary_export_file_name_default = ESLintUtils48.RuleCreator(
|
|
7593
|
+
(name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
|
|
7594
|
+
)({
|
|
7595
|
+
name: "primary-export-file-name",
|
|
7596
|
+
meta: {
|
|
7597
|
+
type: "suggestion",
|
|
7598
|
+
docs: {
|
|
7599
|
+
description: "Enforce semantic naming alignment: a file with a single primary export must be named after that export."
|
|
7600
|
+
},
|
|
7601
|
+
schema: [],
|
|
7602
|
+
messages: {
|
|
7603
|
+
primaryExportMismatch: "Module stem '{{stem}}' does not match its primary export '{{name}}' \u2014 rename the file to '{{expected}}{{ext}}' to describe its responsibility."
|
|
7604
|
+
}
|
|
7605
|
+
},
|
|
7606
|
+
defaultOptions: [],
|
|
7607
|
+
create(context) {
|
|
7608
|
+
const base = basename2(context.filename);
|
|
7609
|
+
if (base.endsWith(".d.ts") || base.startsWith("index.") || base.startsWith("_")) return {};
|
|
7610
|
+
if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
|
|
7611
|
+
const stem3 = stemOf2(base);
|
|
7612
|
+
if (stem3 === "page" || stem3 === "layout" || stem3 === "loading" || stem3 === "error" || stem3 === "not-found" || stem3 === "route" || stem3 === "__root" || stem3 === "config" || stem3 === "constants" || stem3 === "types" || stem3.startsWith("$") || stem3.startsWith("[")) {
|
|
7613
|
+
return {};
|
|
7614
|
+
}
|
|
7615
|
+
return {
|
|
7616
|
+
Program(node) {
|
|
7617
|
+
const primary = findPrimaryExport(node.body);
|
|
7618
|
+
if (primary === null) return;
|
|
7619
|
+
if (CONVENTIONAL_BUCKET_EXPORTS2.has(primary.name) || GENERIC_ENTRYPOINTS.has(primary.name)) return;
|
|
7620
|
+
const expectedStem = kebabCase3(primary.name);
|
|
7621
|
+
if (stem3 === expectedStem) return;
|
|
7622
|
+
const ext = base.endsWith(".tsx") ? ".tsx" : ".ts";
|
|
7623
|
+
context.report({
|
|
7624
|
+
node: primary.node,
|
|
7625
|
+
messageId: "primaryExportMismatch",
|
|
7626
|
+
data: { stem: stem3, name: primary.name, expected: expectedStem, ext }
|
|
7627
|
+
});
|
|
7628
|
+
}
|
|
7629
|
+
};
|
|
7630
|
+
}
|
|
7631
|
+
});
|
|
7632
|
+
|
|
7633
|
+
// src/rules/no-implicit-attribute-access.ts
|
|
7634
|
+
import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
|
|
7635
|
+
var EXCLUDED_BASES = /* @__PURE__ */ new Set([
|
|
7636
|
+
"environ",
|
|
7637
|
+
"headers",
|
|
7638
|
+
"cookies",
|
|
7639
|
+
"session",
|
|
7640
|
+
"redis",
|
|
7641
|
+
"cache",
|
|
7642
|
+
"state",
|
|
7643
|
+
"config",
|
|
7644
|
+
"env",
|
|
7645
|
+
"process",
|
|
7646
|
+
"localStorage",
|
|
7647
|
+
"sessionStorage"
|
|
7648
|
+
]);
|
|
7649
|
+
function getBaseName(node) {
|
|
7650
|
+
if (node.type === AST_NODE_TYPES36.Identifier) {
|
|
7651
|
+
return node.name;
|
|
7652
|
+
}
|
|
7653
|
+
if (node.type === AST_NODE_TYPES36.MemberExpression && node.property.type === AST_NODE_TYPES36.Identifier) {
|
|
7654
|
+
return node.property.name;
|
|
7655
|
+
}
|
|
7656
|
+
return null;
|
|
7657
|
+
}
|
|
7658
|
+
var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
|
|
7659
|
+
(name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
|
|
7660
|
+
)({
|
|
7661
|
+
name: "no-implicit-attribute-access",
|
|
7662
|
+
meta: {
|
|
7663
|
+
type: "problem",
|
|
7664
|
+
docs: {
|
|
7665
|
+
description: "Disallow imperative dictionary access with string literals; use declarative Zod schemas."
|
|
7666
|
+
},
|
|
7667
|
+
schema: [],
|
|
7668
|
+
messages: {
|
|
7669
|
+
noImplicitAttributeAccess: "Imperative lookup for '{{key}}' \u2014 if the key is known, parse the object declaratively with a Zod schema instead."
|
|
7670
|
+
}
|
|
7671
|
+
},
|
|
7672
|
+
defaultOptions: [],
|
|
7673
|
+
create(context) {
|
|
7674
|
+
return {
|
|
7675
|
+
MemberExpression(node) {
|
|
7676
|
+
if (!node.computed) {
|
|
7677
|
+
return;
|
|
7678
|
+
}
|
|
7679
|
+
if (node.property.type === AST_NODE_TYPES36.Literal && typeof node.property.value === "string") {
|
|
7680
|
+
const baseName = getBaseName(node.object);
|
|
7681
|
+
if (!baseName || !EXCLUDED_BASES.has(baseName)) {
|
|
7682
|
+
context.report({
|
|
7683
|
+
node,
|
|
7684
|
+
messageId: "noImplicitAttributeAccess",
|
|
7685
|
+
data: { key: node.property.value }
|
|
7686
|
+
});
|
|
7687
|
+
}
|
|
7688
|
+
}
|
|
7689
|
+
},
|
|
7690
|
+
CallExpression(node) {
|
|
7691
|
+
const callee = node.callee;
|
|
7692
|
+
if (callee.type === AST_NODE_TYPES36.MemberExpression) {
|
|
7693
|
+
const method = callee.property.type === AST_NODE_TYPES36.Identifier ? callee.property.name : null;
|
|
7694
|
+
if (method === "get") {
|
|
7695
|
+
const arg = node.arguments[0];
|
|
7696
|
+
if (arg && arg.type === AST_NODE_TYPES36.Literal && typeof arg.value === "string") {
|
|
7697
|
+
const baseName = getBaseName(callee.object);
|
|
7698
|
+
if (!baseName || !EXCLUDED_BASES.has(baseName)) {
|
|
7699
|
+
context.report({
|
|
7700
|
+
node,
|
|
7701
|
+
messageId: "noImplicitAttributeAccess",
|
|
7702
|
+
data: { key: arg.value }
|
|
7703
|
+
});
|
|
7704
|
+
}
|
|
7705
|
+
}
|
|
7706
|
+
}
|
|
7707
|
+
}
|
|
7708
|
+
}
|
|
7709
|
+
};
|
|
7710
|
+
}
|
|
7711
|
+
});
|
|
7712
|
+
|
|
7495
7713
|
// src/index.ts
|
|
7496
7714
|
var rules = {
|
|
7497
7715
|
"enforce-file-structure": enforce_file_structure_default,
|
|
@@ -7520,6 +7738,7 @@ var rules = {
|
|
|
7520
7738
|
"no-unsafe-cast": no_unsafe_cast_default,
|
|
7521
7739
|
"prefer-string-literal-union": prefer_string_literal_union_default,
|
|
7522
7740
|
"single-public-export": single_public_export_default,
|
|
7741
|
+
"primary-export-file-name": primary_export_file_name_default,
|
|
7523
7742
|
"no-silent-promise-catch": no_silent_promise_catch_default,
|
|
7524
7743
|
"require-fetch-timeout": require_fetch_timeout_default,
|
|
7525
7744
|
"require-schema-validate-search": require_schema_validate_search_default,
|
|
@@ -7540,12 +7759,13 @@ var rules = {
|
|
|
7540
7759
|
"trailing-value-narration": trailing_value_narration_default,
|
|
7541
7760
|
"no-tautological-expect": no_tautological_expect_default,
|
|
7542
7761
|
"require-interface-for-injected-service": require_interface_for_injected_service_default,
|
|
7543
|
-
"prefer-non-nullable-collection": prefer_non_nullable_collection_default
|
|
7762
|
+
"prefer-non-nullable-collection": prefer_non_nullable_collection_default,
|
|
7763
|
+
"no-implicit-attribute-access": no_implicit_attribute_access_default
|
|
7544
7764
|
};
|
|
7545
7765
|
var plugin = {
|
|
7546
7766
|
meta: {
|
|
7547
7767
|
name: "@sarj/eslint-plugin",
|
|
7548
|
-
version: "2.
|
|
7768
|
+
version: "2.16.0"
|
|
7549
7769
|
},
|
|
7550
7770
|
rules,
|
|
7551
7771
|
configs: {
|
|
@@ -7580,6 +7800,7 @@ var plugin = {
|
|
|
7580
7800
|
"@sarj/no-secret-in-log": "warn",
|
|
7581
7801
|
"@sarj/no-unsafe-cast": "warn",
|
|
7582
7802
|
"@sarj/single-public-export": "warn",
|
|
7803
|
+
"@sarj/primary-export-file-name": "warn",
|
|
7583
7804
|
"@sarj/prefer-string-literal-union": "warn",
|
|
7584
7805
|
// Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
|
|
7585
7806
|
"@sarj/require-fetch-timeout": "warn",
|
|
@@ -7629,7 +7850,8 @@ var plugin = {
|
|
|
7629
7850
|
// mocking. 11-repo sweep: 229 exported classes, 82% already carry a
|
|
7630
7851
|
// port, 29 fire, 28 of them true positives.
|
|
7631
7852
|
"@sarj/require-interface-for-injected-service": "warn",
|
|
7632
|
-
"@sarj/prefer-non-nullable-collection": "warn"
|
|
7853
|
+
"@sarj/prefer-non-nullable-collection": "warn",
|
|
7854
|
+
"@sarj/no-implicit-attribute-access": "warn"
|
|
7633
7855
|
}
|
|
7634
7856
|
},
|
|
7635
7857
|
strict: {
|
|
@@ -7667,6 +7889,7 @@ var plugin = {
|
|
|
7667
7889
|
"@sarj/no-secret-in-log": "error",
|
|
7668
7890
|
"@sarj/no-unsafe-cast": "error",
|
|
7669
7891
|
"@sarj/single-public-export": "error",
|
|
7892
|
+
"@sarj/primary-export-file-name": "error",
|
|
7670
7893
|
// Promoted to error 2026-07-25 — strict means strict (user directive).
|
|
7671
7894
|
"@sarj/prefer-string-literal-union": "error",
|
|
7672
7895
|
// Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
|
|
@@ -7707,7 +7930,8 @@ var plugin = {
|
|
|
7707
7930
|
// / `prefer-library-fake` wave. The convention already exists in the
|
|
7708
7931
|
// corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
|
|
7709
7932
|
"@sarj/require-interface-for-injected-service": "error",
|
|
7710
|
-
"@sarj/prefer-non-nullable-collection": "error"
|
|
7933
|
+
"@sarj/prefer-non-nullable-collection": "error",
|
|
7934
|
+
"@sarj/no-implicit-attribute-access": "error"
|
|
7711
7935
|
}
|
|
7712
7936
|
}
|
|
7713
7937
|
}
|