@sarj/eslint-plugin 5.0.0 → 6.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.js CHANGED
@@ -4,7 +4,8 @@ import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
4
4
  // src/rules/_paths.ts
5
5
  var SCRIPT_FILE_RE = /([\\/]scripts[\\/])|(\.mjs$)/;
6
6
  var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
7
- var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types)[\\/])|(\.gen\.[cm]?[jt]sx?$)|(\.generated\.[cm]?[jt]sx?$)|(\.d\.[cm]?ts$)|(\.types\.[cm]?ts$)/;
7
+ var STORY_DIR_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
8
+ var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types|vendor|vendored|external|third[-_]?party)[\\/])|(\.gen\.[cm]?[jt]sx?$)|(\.generated\.[cm]?[jt]sx?$)|(\.d\.[cm]?ts$)|(\.types\.[cm]?ts$)/;
8
9
  var GENERATED_MARKER_RE = /(?:@generated\b|generated (?:with|by)|generated (?:graphql )?types|do not edit(?: directly| manually)?)/i;
9
10
  function isTestFile(filename) {
10
11
  const normalized = filename.replaceAll("\\", "/");
@@ -12,10 +13,13 @@ function isTestFile(filename) {
12
13
  if (/[.\-_](test|spec|e2e)\.[cm]?[jt]sx?$/.test(base) || /\.integration\.[cm]?[jt]sx?$/.test(base)) {
13
14
  return true;
14
15
  }
15
- return /(^|\/)(tests?|__tests__|__mocks__|fixtures|e2e|integration)\//.test(normalized);
16
+ return /(^|\/)(tests?|__tests__|__mocks__|__fixtures__|__testfixtures__|fixtures?|e2e|integration)\//.test(
17
+ normalized
18
+ );
16
19
  }
17
20
  function isStoryFile(filename) {
18
- return STORY_FILE_RE.test(filename);
21
+ const normalized = filename.replaceAll("\\", "/");
22
+ return STORY_FILE_RE.test(normalized) || STORY_DIR_RE.test(normalized);
19
23
  }
20
24
  function isGeneratedFile(filename, sourceText = "") {
21
25
  return GENERATED_FILE_RE.test(filename.replaceAll("\\", "/")) || GENERATED_MARKER_RE.test(sourceText.slice(0, 2048));
@@ -7689,8 +7693,190 @@ var trailing_value_narration_default = ESLintUtils43.RuleCreator(
7689
7693
  }
7690
7694
  });
7691
7695
 
7692
- // src/rules/no-tautological-expect.ts
7696
+ // src/rules/no-type-member-comment-wall.ts
7693
7697
  import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils44 } from "@typescript-eslint/utils";
7698
+ var DEFAULTS = {
7699
+ // Below three rows "a wall" is not a fair description of what the reader sees.
7700
+ minCommentedMembers: 3,
7701
+ // A minority of commented members is a GROUP LABEL, not a wall.
7702
+ minCommentedRatio: 0.6,
7703
+ // Room for one substantive row in four; a type where a quarter of the comments
7704
+ // say something real is a type someone was documenting, not decorating.
7705
+ minRestatedRatio: 0.75,
7706
+ // One word beyond the member's own text. Zero is `jsdoc-restates-signature`'s
7707
+ // test and is already covered there; two admits definitions ("Partial match"
7708
+ // beside "Exact match"), which the evidence file counts.
7709
+ maxNovelWords: 1
7710
+ };
7711
+ var VALUE_TAG_RE = /@(?:deprecated|see|example|throws|remarks|since|default|defaultvalue|link|internal|alpha|beta|experimental|template|typeparam|inheritdoc|todo|fixme|override)\b/i;
7712
+ var DEFAULT_RE = /^\s*@?default\b|\bdefaults? (?:to|:)/i;
7713
+ var DIGIT_RE = /\d/;
7714
+ var UNIT_WORD_RE = /\b(?:ms|milliseconds?|seconds?|minutes?|hours?|days?|weeks?|months?|years?|bytes?|kb|mb|gb|percent|pixels?|px|utc|epoch)\b/i;
7715
+ var EXAMPLE_RE = /["'`]|\be\.g\.|\bi\.e\./;
7716
+ var BANNER_RE = /[=\-─-╿*#~_.]{3,}/;
7717
+ var NON_ASCII_LETTER_RE2 = /[^\p{ASCII}\p{N}\p{P}\p{Z}]/u;
7718
+ var STOPWORDS4 = new Set(
7719
+ `the a an of to for in on with and or as at by is are was be been being
7720
+ this that it its if whether when where which what will would can could should
7721
+ must may into from over about not no does do done has have had used use uses
7722
+ using given provided specified current new existing all any each per via
7723
+ instance object value values data item
7724
+ items element callback handler prop props param arg return
7725
+ returns returning result optional required true false null undefined
7726
+ string number boolean array list promise set map record type name`.split(/\s+/)
7727
+ );
7728
+ var WORD_RE4 = /[A-Za-z][A-Za-z0-9]*/g;
7729
+ var BARE_LABEL_RE = /^[A-Za-z][A-Za-z0-9]*$/;
7730
+ function labelStems(body) {
7731
+ return splitIdentifier(body).map(stem).join(" ");
7732
+ }
7733
+ function isNamedMember(node) {
7734
+ return (node.type === AST_NODE_TYPES34.TSPropertySignature || node.type === AST_NODE_TYPES34.TSMethodSignature) && !node.computed;
7735
+ }
7736
+ function commentBody(comment) {
7737
+ return comment.value.replace(/^\*+/, "").replace(/^[ \t]*\*[ \t]?/gm, "").trim();
7738
+ }
7739
+ function carriesValue(body) {
7740
+ return isProtected(body) || VALUE_TAG_RE.test(body) || DEFAULT_RE.test(body) || DIGIT_RE.test(body) || UNIT_WORD_RE.test(body) || EXAMPLE_RE.test(body) || BANNER_RE.test(body) || NON_ASCII_LETTER_RE2.test(body);
7741
+ }
7742
+ function knownTokens(source) {
7743
+ const tokens = /* @__PURE__ */ new Set();
7744
+ for (const identifier of source.match(/[A-Za-z_$][\w$]*/g) ?? []) {
7745
+ for (const part of splitIdentifier(identifier)) {
7746
+ tokens.add(part);
7747
+ tokens.add(stem(part));
7748
+ }
7749
+ }
7750
+ return tokens;
7751
+ }
7752
+ function novelWords(body, known) {
7753
+ let novel = 0;
7754
+ for (const word of body.match(WORD_RE4) ?? []) {
7755
+ const lower = word.toLowerCase();
7756
+ if (lower.length < 2 || STOPWORDS4.has(lower)) continue;
7757
+ if (!known.has(lower) && !known.has(stem(lower))) novel += 1;
7758
+ }
7759
+ return novel;
7760
+ }
7761
+ var no_type_member_comment_wall_default = ESLintUtils44.RuleCreator(
7762
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7763
+ )({
7764
+ name: "no-type-member-comment-wall",
7765
+ meta: {
7766
+ type: "suggestion",
7767
+ docs: {
7768
+ description: "Flag an object type whose member comments mostly re-spell the members' own names and types."
7769
+ },
7770
+ schema: [
7771
+ {
7772
+ type: "object",
7773
+ additionalProperties: false,
7774
+ properties: {
7775
+ minCommentedMembers: {
7776
+ type: "integer",
7777
+ minimum: 2,
7778
+ description: "Fewest commented members that can count as a wall."
7779
+ },
7780
+ minCommentedRatio: {
7781
+ type: "number",
7782
+ minimum: 0,
7783
+ maximum: 1,
7784
+ description: "Least share of the type's members that must be commented; below it the comments are group labels."
7785
+ },
7786
+ minRestatedRatio: {
7787
+ type: "number",
7788
+ minimum: 0,
7789
+ maximum: 1,
7790
+ description: "Least share of the member comments that must be restatements."
7791
+ },
7792
+ maxNovelWords: {
7793
+ type: "integer",
7794
+ minimum: 0,
7795
+ description: "Most content words a comment may add beyond its member's own source and still count as a restatement."
7796
+ }
7797
+ }
7798
+ }
7799
+ ],
7800
+ messages: {
7801
+ commentWall: "{{restated}} of this type's {{commented}} member comments only re-spell the member's own name and type \u2014 delete them, and keep the rows that say what the name cannot."
7802
+ }
7803
+ },
7804
+ defaultOptions: [DEFAULTS],
7805
+ create(context, [provided]) {
7806
+ const options = { ...DEFAULTS, ...provided };
7807
+ const sourceCode = context.sourceCode;
7808
+ if (isGeneratedFile(context.filename, sourceCode.text) || isTestFile(context.filename) || isStoryFile(context.filename)) {
7809
+ return {};
7810
+ }
7811
+ const endingOn = /* @__PURE__ */ new Map();
7812
+ const startingOn = /* @__PURE__ */ new Map();
7813
+ for (const comment of sourceCode.getAllComments()) {
7814
+ endingOn.set(comment.loc.end.line, comment);
7815
+ if (!startingOn.has(comment.loc.start.line)) startingOn.set(comment.loc.start.line, comment);
7816
+ }
7817
+ function documentingComment(member) {
7818
+ const beforeMember = sourceCode.getTokenBefore(member, { includeComments: false });
7819
+ const ownsItsLine = beforeMember === null || beforeMember.loc.end.line < member.loc.start.line;
7820
+ const lead = ownsItsLine ? endingOn.get(member.loc.start.line - 1) : void 0;
7821
+ if (lead !== void 0) {
7822
+ const before = sourceCode.getTokenBefore(lead, { includeComments: false });
7823
+ if (before === null || before.loc.end.line < lead.loc.start.line) return lead;
7824
+ }
7825
+ const trail = startingOn.get(member.loc.end.line);
7826
+ return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
7827
+ }
7828
+ function isGroupLabel(comment, member, headsRun) {
7829
+ if (comment.loc.end.line >= member.loc.start.line) return false;
7830
+ const body = commentBody(comment);
7831
+ if (!BARE_LABEL_RE.test(body)) return false;
7832
+ if (labelStems(body) === labelStems(sourceCode.getText(member.key))) return false;
7833
+ const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
7834
+ return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
7835
+ }
7836
+ function check(node) {
7837
+ const members = node.type === AST_NODE_TYPES34.TSInterfaceBody ? node.body : node.members;
7838
+ const named = members.filter(isNamedMember);
7839
+ if (named.length === 0) return;
7840
+ const documented = named.map((member) => ({ member, comment: documentingComment(member) }));
7841
+ let commented = 0;
7842
+ let restated = 0;
7843
+ const claimed = /* @__PURE__ */ new Set();
7844
+ for (const [index, { member, comment }] of documented.entries()) {
7845
+ if (comment === void 0 || claimed.has(comment)) continue;
7846
+ const next = documented[index + 1];
7847
+ if (isGroupLabel(comment, member, next !== void 0 && next.comment === void 0)) {
7848
+ continue;
7849
+ }
7850
+ claimed.add(comment);
7851
+ commented += 1;
7852
+ const body = commentBody(comment);
7853
+ if (body.length === 0 || carriesValue(body)) continue;
7854
+ if (novelWords(body, knownTokens(sourceCode.getText(member))) <= options.maxNovelWords) {
7855
+ restated += 1;
7856
+ }
7857
+ }
7858
+ if (commented < options.minCommentedMembers || commented / named.length < options.minCommentedRatio || restated / commented < options.minRestatedRatio) {
7859
+ return;
7860
+ }
7861
+ context.report({
7862
+ node,
7863
+ loc: {
7864
+ start: node.loc.start,
7865
+ end: { line: node.loc.start.line, column: node.loc.start.column + 1 }
7866
+ },
7867
+ messageId: "commentWall",
7868
+ data: { restated: String(restated), commented: String(commented) }
7869
+ });
7870
+ }
7871
+ return {
7872
+ TSInterfaceBody: check,
7873
+ TSTypeLiteral: check
7874
+ };
7875
+ }
7876
+ });
7877
+
7878
+ // src/rules/no-tautological-expect.ts
7879
+ import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
7694
7880
  var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
7695
7881
  var ZERO_ARG_MATCHERS = /* @__PURE__ */ new Set([
7696
7882
  "toBeDefined",
@@ -7704,17 +7890,17 @@ var OPERAND_PREVIEW_CHARS = 40;
7704
7890
  var NUMERIC_SIGNS = /* @__PURE__ */ new Set(["-", "+"]);
7705
7891
  function isLiteral(node) {
7706
7892
  switch (node.type) {
7707
- case AST_NODE_TYPES34.Literal:
7893
+ case AST_NODE_TYPES35.Literal:
7708
7894
  return true;
7709
- case AST_NODE_TYPES34.TemplateLiteral:
7895
+ case AST_NODE_TYPES35.TemplateLiteral:
7710
7896
  return node.expressions.length === 0;
7711
- case AST_NODE_TYPES34.UnaryExpression:
7897
+ case AST_NODE_TYPES35.UnaryExpression:
7712
7898
  return NUMERIC_SIGNS.has(node.operator) && isLiteral(node.argument);
7713
- case AST_NODE_TYPES34.ArrayExpression:
7899
+ case AST_NODE_TYPES35.ArrayExpression:
7714
7900
  return node.elements.every((element) => element !== null && isLiteral(element));
7715
- case AST_NODE_TYPES34.ObjectExpression:
7901
+ case AST_NODE_TYPES35.ObjectExpression:
7716
7902
  return node.properties.every(
7717
- (property) => property.type === AST_NODE_TYPES34.Property && !property.computed && isLiteral(property.value)
7903
+ (property) => property.type === AST_NODE_TYPES35.Property && !property.computed && isLiteral(property.value)
7718
7904
  );
7719
7905
  default:
7720
7906
  return false;
@@ -7722,12 +7908,12 @@ function isLiteral(node) {
7722
7908
  }
7723
7909
  function expectOperand(callee) {
7724
7910
  const receiver = callee.object;
7725
- if (receiver.type !== AST_NODE_TYPES34.CallExpression || receiver.callee.type !== AST_NODE_TYPES34.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7911
+ if (receiver.type !== AST_NODE_TYPES35.CallExpression || receiver.callee.type !== AST_NODE_TYPES35.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7726
7912
  return null;
7727
7913
  }
7728
7914
  return receiver.arguments[0] ?? null;
7729
7915
  }
7730
- var no_tautological_expect_default = ESLintUtils44.RuleCreator(
7916
+ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7731
7917
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7732
7918
  )({
7733
7919
  name: "no-tautological-expect",
@@ -7754,10 +7940,10 @@ var no_tautological_expect_default = ESLintUtils44.RuleCreator(
7754
7940
  return {
7755
7941
  CallExpression(node) {
7756
7942
  const callee = node.callee;
7757
- if (callee.type !== AST_NODE_TYPES34.MemberExpression || callee.computed) {
7943
+ if (callee.type !== AST_NODE_TYPES35.MemberExpression || callee.computed) {
7758
7944
  return;
7759
7945
  }
7760
- if (callee.property.type !== AST_NODE_TYPES34.Identifier) {
7946
+ if (callee.property.type !== AST_NODE_TYPES35.Identifier) {
7761
7947
  return;
7762
7948
  }
7763
7949
  const matcher = callee.property.name;
@@ -7791,26 +7977,26 @@ var no_tautological_expect_default = ESLintUtils44.RuleCreator(
7791
7977
  });
7792
7978
 
7793
7979
  // src/rules/require-interface-for-injected-service.ts
7794
- import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
7980
+ import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
7795
7981
  var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Props|Args|Env|Environment|Callbacks|Flags)$/;
7796
7982
  var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
7797
7983
  var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
7798
7984
  var TRANSPORT_WRAPPER_NAME_RE = /Client$/;
7799
7985
  var ROUTER_FACTORY_NAME = "Router";
7800
7986
  var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
7801
- var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES35.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES35.ExportDefaultDeclaration;
7802
- var qualifiedName = (name) => name.type === AST_NODE_TYPES35.Identifier ? name.name : name.type === AST_NODE_TYPES35.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7987
+ var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES36.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES36.ExportDefaultDeclaration;
7988
+ var qualifiedName = (name) => name.type === AST_NODE_TYPES36.Identifier ? name.name : name.type === AST_NODE_TYPES36.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7803
7989
  var typeReferenceName = (annotated) => {
7804
7990
  let target = annotated;
7805
- if (target.type === AST_NODE_TYPES35.TSParameterProperty) target = target.parameter;
7806
- if (target.type === AST_NODE_TYPES35.AssignmentPattern) target = target.left;
7807
- if (target.type !== AST_NODE_TYPES35.Identifier) return null;
7991
+ if (target.type === AST_NODE_TYPES36.TSParameterProperty) target = target.parameter;
7992
+ if (target.type === AST_NODE_TYPES36.AssignmentPattern) target = target.left;
7993
+ if (target.type !== AST_NODE_TYPES36.Identifier) return null;
7808
7994
  const annotation = target.typeAnnotation?.typeAnnotation;
7809
- if (annotation === void 0 || annotation.type !== AST_NODE_TYPES35.TSTypeReference) {
7995
+ if (annotation === void 0 || annotation.type !== AST_NODE_TYPES36.TSTypeReference) {
7810
7996
  return null;
7811
7997
  }
7812
7998
  const { typeName } = annotation;
7813
- const rightmost = typeName.type === AST_NODE_TYPES35.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES35.TSQualifiedName ? typeName.right.name : null;
7999
+ const rightmost = typeName.type === AST_NODE_TYPES36.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES36.TSQualifiedName ? typeName.right.name : null;
7814
8000
  if (rightmost === null) return null;
7815
8001
  return { name: target.name, typeName: rightmost, display: qualifiedName(typeName) };
7816
8002
  };
@@ -7820,17 +8006,17 @@ var readConstructor = (ctor) => {
7820
8006
  let constructedFields = 0;
7821
8007
  if (body !== null && body !== void 0) {
7822
8008
  for (const statement of body.body) {
7823
- if (statement.type !== AST_NODE_TYPES35.ExpressionStatement) continue;
8009
+ if (statement.type !== AST_NODE_TYPES36.ExpressionStatement) continue;
7824
8010
  const expression = statement.expression;
7825
- if (expression.type !== AST_NODE_TYPES35.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES35.MemberExpression || expression.left.object.type !== AST_NODE_TYPES35.ThisExpression) {
8011
+ if (expression.type !== AST_NODE_TYPES36.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES36.MemberExpression || expression.left.object.type !== AST_NODE_TYPES36.ThisExpression) {
7826
8012
  continue;
7827
8013
  }
7828
8014
  const source = expression.right;
7829
- if (source.type === AST_NODE_TYPES35.NewExpression) {
8015
+ if (source.type === AST_NODE_TYPES36.NewExpression) {
7830
8016
  constructedFields += 1;
7831
- } else if (source.type === AST_NODE_TYPES35.Identifier) {
8017
+ } else if (source.type === AST_NODE_TYPES36.Identifier) {
7832
8018
  storedFrom.add(source.name);
7833
- } else if (source.type === AST_NODE_TYPES35.MemberExpression && source.object.type === AST_NODE_TYPES35.Identifier) {
8019
+ } else if (source.type === AST_NODE_TYPES36.MemberExpression && source.object.type === AST_NODE_TYPES36.Identifier) {
7834
8020
  storedFrom.add(source.object.name);
7835
8021
  }
7836
8022
  }
@@ -7839,7 +8025,7 @@ var readConstructor = (ctor) => {
7839
8025
  for (const parameter of ctor.value.params) {
7840
8026
  const reference = typeReferenceName(parameter);
7841
8027
  if (reference === null) continue;
7842
- const stored = parameter.type === AST_NODE_TYPES35.TSParameterProperty || storedFrom.has(reference.name);
8028
+ const stored = parameter.type === AST_NODE_TYPES36.TSParameterProperty || storedFrom.has(reference.name);
7843
8029
  if (!stored) continue;
7844
8030
  if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
7845
8031
  if (CONFIGISH_NAME_RE.test(reference.name)) continue;
@@ -7869,19 +8055,19 @@ var subtreeHas = (root, found) => {
7869
8055
  return hit;
7870
8056
  };
7871
8057
  var isFrameworkWiring = (body) => subtreeHas(body, (node) => {
7872
- if (node.type === AST_NODE_TYPES35.CallExpression) {
8058
+ if (node.type === AST_NODE_TYPES36.CallExpression) {
7873
8059
  const { callee } = node;
7874
- if (callee.type === AST_NODE_TYPES35.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7875
- return callee.type === AST_NODE_TYPES35.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES35.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
8060
+ if (callee.type === AST_NODE_TYPES36.Identifier) return callee.name === ROUTER_FACTORY_NAME;
8061
+ return callee.type === AST_NODE_TYPES36.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES36.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7876
8062
  }
7877
- return node.type === AST_NODE_TYPES35.TSTypeReference && node.typeName.type === AST_NODE_TYPES35.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
8063
+ return node.type === AST_NODE_TYPES36.TSTypeReference && node.typeName.type === AST_NODE_TYPES36.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7878
8064
  });
7879
8065
  var stem2 = (name) => name.replace(/^I(?=[A-Z])/, "").replace(/Impl$/, "");
7880
8066
  var fileInterfaceNames = (program) => {
7881
8067
  const names = [];
7882
8068
  for (const statement of program.body) {
7883
- const declaration = statement.type === AST_NODE_TYPES35.ExportNamedDeclaration ? statement.declaration : statement;
7884
- if (declaration?.type === AST_NODE_TYPES35.TSInterfaceDeclaration) names.push(declaration.id.name);
8069
+ const declaration = statement.type === AST_NODE_TYPES36.ExportNamedDeclaration ? statement.declaration : statement;
8070
+ if (declaration?.type === AST_NODE_TYPES36.TSInterfaceDeclaration) names.push(declaration.id.name);
7885
8071
  }
7886
8072
  return names;
7887
8073
  };
@@ -7899,16 +8085,16 @@ var isTransportWrapper = (className, collaborators, program) => {
7899
8085
  var publicMethodNames = (body) => {
7900
8086
  const names = [];
7901
8087
  for (const member of body.body) {
7902
- if (member.type !== AST_NODE_TYPES35.MethodDefinition) continue;
8088
+ if (member.type !== AST_NODE_TYPES36.MethodDefinition) continue;
7903
8089
  if (member.kind !== "method" || member.static) continue;
7904
8090
  if (member.accessibility === "private" || member.accessibility === "protected") continue;
7905
- if (member.key.type === AST_NODE_TYPES35.PrivateIdentifier) continue;
7906
- if (member.key.type === AST_NODE_TYPES35.Identifier) names.push(member.key.name);
8091
+ if (member.key.type === AST_NODE_TYPES36.PrivateIdentifier) continue;
8092
+ if (member.key.type === AST_NODE_TYPES36.Identifier) names.push(member.key.name);
7907
8093
  else names.push("\u2026");
7908
8094
  }
7909
8095
  return names;
7910
8096
  };
7911
- var require_interface_for_injected_service_default = ESLintUtils45.RuleCreator(
8097
+ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7912
8098
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7913
8099
  )({
7914
8100
  name: "require-interface-for-injected-service",
@@ -7936,7 +8122,7 @@ var require_interface_for_injected_service_default = ESLintUtils45.RuleCreator(
7936
8122
  if (node.implements.length > 0) return;
7937
8123
  if (node.decorators.length > 0) return;
7938
8124
  const ctor = node.body.body.find(
7939
- (member) => member.type === AST_NODE_TYPES35.MethodDefinition && member.kind === "constructor"
8125
+ (member) => member.type === AST_NODE_TYPES36.MethodDefinition && member.kind === "constructor"
7940
8126
  );
7941
8127
  if (ctor === void 0) return;
7942
8128
  const { collaborators, constructedFields } = readConstructor(ctor);
@@ -7961,26 +8147,26 @@ var require_interface_for_injected_service_default = ESLintUtils45.RuleCreator(
7961
8147
  });
7962
8148
 
7963
8149
  // src/rules/prefer-non-nullable-collection.ts
7964
- import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
8150
+ import { AST_NODE_TYPES as AST_NODE_TYPES37, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
7965
8151
  var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
7966
8152
  function propertyName(node) {
7967
8153
  const key = node.key;
7968
- if (key.type === AST_NODE_TYPES36.Identifier) return key.name;
7969
- if (key.type === AST_NODE_TYPES36.Literal) return String(key.value);
8154
+ if (key.type === AST_NODE_TYPES37.Identifier) return key.name;
8155
+ if (key.type === AST_NODE_TYPES37.Literal) return String(key.value);
7970
8156
  return "collection";
7971
8157
  }
7972
8158
  function isArrayType(node) {
7973
- if (node.type === AST_NODE_TYPES36.TSArrayType) return true;
7974
- return node.type === AST_NODE_TYPES36.TSTypeReference && node.typeName.type === AST_NODE_TYPES36.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
8159
+ if (node.type === AST_NODE_TYPES37.TSArrayType) return true;
8160
+ return node.type === AST_NODE_TYPES37.TSTypeReference && node.typeName.type === AST_NODE_TYPES37.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7975
8161
  }
7976
8162
  function isNullishType(node) {
7977
- return node.type === AST_NODE_TYPES36.TSNullKeyword || node.type === AST_NODE_TYPES36.TSUndefinedKeyword;
8163
+ return node.type === AST_NODE_TYPES37.TSNullKeyword || node.type === AST_NODE_TYPES37.TSUndefinedKeyword;
7978
8164
  }
7979
8165
  function isNullableArrayOnly(node) {
7980
8166
  const values = node.types.filter((member) => !isNullishType(member));
7981
8167
  return values.length > 0 && values.length < node.types.length && values.every(isArrayType);
7982
8168
  }
7983
- var prefer_non_nullable_collection_default = ESLintUtils46.RuleCreator(
8169
+ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7984
8170
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
7985
8171
  )({
7986
8172
  name: "prefer-non-nullable-collection",
@@ -8003,7 +8189,7 @@ var prefer_non_nullable_collection_default = ESLintUtils46.RuleCreator(
8003
8189
  function checkOptionalProperty(node) {
8004
8190
  const annotation = node.typeAnnotation?.typeAnnotation;
8005
8191
  if (annotation === void 0) return;
8006
- if (annotation.type !== AST_NODE_TYPES36.TSUnionType || !isNullableArrayOnly(annotation)) {
8192
+ if (annotation.type !== AST_NODE_TYPES37.TSUnionType || !isNullableArrayOnly(annotation)) {
8007
8193
  return;
8008
8194
  }
8009
8195
  context.report({
@@ -8016,7 +8202,7 @@ var prefer_non_nullable_collection_default = ESLintUtils46.RuleCreator(
8016
8202
  TSPropertySignature: checkOptionalProperty,
8017
8203
  PropertyDefinition: checkOptionalProperty,
8018
8204
  TSTypeAliasDeclaration(node) {
8019
- if (node.typeAnnotation.type !== AST_NODE_TYPES36.TSUnionType) return;
8205
+ if (node.typeAnnotation.type !== AST_NODE_TYPES37.TSUnionType) return;
8020
8206
  if (!isNullableArrayOnly(node.typeAnnotation)) return;
8021
8207
  context.report({
8022
8208
  node,
@@ -8029,7 +8215,7 @@ var prefer_non_nullable_collection_default = ESLintUtils46.RuleCreator(
8029
8215
  });
8030
8216
 
8031
8217
  // src/rules/strict-test-assertions.ts
8032
- import { AST_NODE_TYPES as AST_NODE_TYPES37, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
8218
+ import { AST_NODE_TYPES as AST_NODE_TYPES38, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
8033
8219
  var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
8034
8220
  var ARRAY_MATCHERS = /* @__PURE__ */ new Set(["toEqual", "toStrictEqual"]);
8035
8221
  var COLLECTION_PROPERTIES = /* @__PURE__ */ new Set(["length", "size"]);
@@ -8037,11 +8223,11 @@ var NUMERIC_SIGNS2 = /* @__PURE__ */ new Set(["-", "+"]);
8037
8223
  var MIN_RUN_LENGTH = 2;
8038
8224
  function literalText(node, getText) {
8039
8225
  switch (node.type) {
8040
- case AST_NODE_TYPES37.Literal:
8226
+ case AST_NODE_TYPES38.Literal:
8041
8227
  return "regex" in node ? null : getText(node);
8042
- case AST_NODE_TYPES37.TemplateLiteral:
8228
+ case AST_NODE_TYPES38.TemplateLiteral:
8043
8229
  return node.expressions.length === 0 ? getText(node) : null;
8044
- case AST_NODE_TYPES37.UnaryExpression:
8230
+ case AST_NODE_TYPES38.UnaryExpression:
8045
8231
  return NUMERIC_SIGNS2.has(node.operator) && literalText(node.argument, getText) !== null ? getText(node) : null;
8046
8232
  default:
8047
8233
  return null;
@@ -8049,15 +8235,15 @@ function literalText(node, getText) {
8049
8235
  }
8050
8236
  function isPureReceiver(node) {
8051
8237
  switch (node.type) {
8052
- case AST_NODE_TYPES37.Identifier:
8053
- case AST_NODE_TYPES37.ThisExpression:
8238
+ case AST_NODE_TYPES38.Identifier:
8239
+ case AST_NODE_TYPES38.ThisExpression:
8054
8240
  return true;
8055
- case AST_NODE_TYPES37.MemberExpression:
8241
+ case AST_NODE_TYPES38.MemberExpression:
8056
8242
  if (node.optional) {
8057
8243
  return false;
8058
8244
  }
8059
8245
  if (node.computed) {
8060
- return node.property.type === AST_NODE_TYPES37.Literal && isPureReceiver(node.object);
8246
+ return node.property.type === AST_NODE_TYPES38.Literal && isPureReceiver(node.object);
8061
8247
  }
8062
8248
  return isPureReceiver(node.object);
8063
8249
  default:
@@ -8065,12 +8251,12 @@ function isPureReceiver(node) {
8065
8251
  }
8066
8252
  }
8067
8253
  function literalIndex(node) {
8068
- if (node.type !== AST_NODE_TYPES37.Literal || typeof node.value !== "number") {
8254
+ if (node.type !== AST_NODE_TYPES38.Literal || typeof node.value !== "number") {
8069
8255
  return null;
8070
8256
  }
8071
8257
  return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
8072
8258
  }
8073
- var strict_test_assertions_default = ESLintUtils47.RuleCreator(
8259
+ var strict_test_assertions_default = ESLintUtils48.RuleCreator(
8074
8260
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8075
8261
  )({
8076
8262
  name: "strict-test-assertions",
@@ -8093,24 +8279,24 @@ var strict_test_assertions_default = ESLintUtils47.RuleCreator(
8093
8279
  }
8094
8280
  const { sourceCode } = context;
8095
8281
  function parseAssertion(statement) {
8096
- if (statement.type !== AST_NODE_TYPES37.ExpressionStatement) {
8282
+ if (statement.type !== AST_NODE_TYPES38.ExpressionStatement) {
8097
8283
  return null;
8098
8284
  }
8099
8285
  const call = statement.expression;
8100
- if (call.type !== AST_NODE_TYPES37.CallExpression) {
8286
+ if (call.type !== AST_NODE_TYPES38.CallExpression) {
8101
8287
  return null;
8102
8288
  }
8103
8289
  const callee = call.callee;
8104
- if (callee.type !== AST_NODE_TYPES37.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES37.Identifier) {
8290
+ if (callee.type !== AST_NODE_TYPES38.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES38.Identifier) {
8105
8291
  return null;
8106
8292
  }
8107
8293
  const matcher = callee.property.name;
8108
8294
  const expectCall = callee.object;
8109
- if (expectCall.type !== AST_NODE_TYPES37.CallExpression || expectCall.callee.type !== AST_NODE_TYPES37.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
8295
+ if (expectCall.type !== AST_NODE_TYPES38.CallExpression || expectCall.callee.type !== AST_NODE_TYPES38.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
8110
8296
  return null;
8111
8297
  }
8112
8298
  const actual = expectCall.arguments[0];
8113
- if (actual === void 0 || actual.type !== AST_NODE_TYPES37.MemberExpression || actual.optional) {
8299
+ if (actual === void 0 || actual.type !== AST_NODE_TYPES38.MemberExpression || actual.optional) {
8114
8300
  return null;
8115
8301
  }
8116
8302
  if (!isPureReceiver(actual.object)) {
@@ -8124,7 +8310,7 @@ var strict_test_assertions_default = ESLintUtils47.RuleCreator(
8124
8310
  }
8125
8311
  key = { kind: "index", index };
8126
8312
  } else {
8127
- if (actual.property.type !== AST_NODE_TYPES37.Identifier || COLLECTION_PROPERTIES.has(actual.property.name)) {
8313
+ if (actual.property.type !== AST_NODE_TYPES38.Identifier || COLLECTION_PROPERTIES.has(actual.property.name)) {
8128
8314
  return null;
8129
8315
  }
8130
8316
  key = { kind: "property", name: actual.property.name };
@@ -8136,7 +8322,7 @@ var strict_test_assertions_default = ESLintUtils47.RuleCreator(
8136
8322
  return null;
8137
8323
  }
8138
8324
  const expected = call.arguments[0];
8139
- if (call.arguments.length !== 1 || expected === void 0 || expected.type === AST_NODE_TYPES37.SpreadElement) {
8325
+ if (call.arguments.length !== 1 || expected === void 0 || expected.type === AST_NODE_TYPES38.SpreadElement) {
8140
8326
  return null;
8141
8327
  }
8142
8328
  const literal = literalText(expected, (node) => sourceCode.getText(node));
@@ -8246,8 +8432,8 @@ var strict_test_assertions_default = ESLintUtils47.RuleCreator(
8246
8432
  });
8247
8433
 
8248
8434
  // src/rules/no-async-callback-in-waitfor.ts
8249
- import { AST_NODE_TYPES as AST_NODE_TYPES38, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
8250
- var no_async_callback_in_waitfor_default = ESLintUtils48.RuleCreator(
8435
+ import { AST_NODE_TYPES as AST_NODE_TYPES39, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
8436
+ var no_async_callback_in_waitfor_default = ESLintUtils49.RuleCreator(
8251
8437
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8252
8438
  )({
8253
8439
  name: "no-async-callback-in-waitfor",
@@ -8268,9 +8454,9 @@ var no_async_callback_in_waitfor_default = ESLintUtils48.RuleCreator(
8268
8454
  }
8269
8455
  return {
8270
8456
  CallExpression(node) {
8271
- if (node.callee.type === AST_NODE_TYPES38.Identifier && node.callee.name === "waitFor") {
8457
+ if (node.callee.type === AST_NODE_TYPES39.Identifier && node.callee.name === "waitFor") {
8272
8458
  const callback = node.arguments[0];
8273
- if (callback && (callback.type === AST_NODE_TYPES38.ArrowFunctionExpression || callback.type === AST_NODE_TYPES38.FunctionExpression) && callback.async) {
8459
+ if (callback && (callback.type === AST_NODE_TYPES39.ArrowFunctionExpression || callback.type === AST_NODE_TYPES39.FunctionExpression) && callback.async) {
8274
8460
  context.report({
8275
8461
  node: callback,
8276
8462
  messageId: "noAsyncCallbackInWaitFor"
@@ -8283,7 +8469,7 @@ var no_async_callback_in_waitfor_default = ESLintUtils48.RuleCreator(
8283
8469
  });
8284
8470
 
8285
8471
  // src/rules/no-hand-rolled-sleep.ts
8286
- import { AST_NODE_TYPES as AST_NODE_TYPES39, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
8472
+ import { AST_NODE_TYPES as AST_NODE_TYPES40, ESLintUtils as ESLintUtils50 } from "@typescript-eslint/utils";
8287
8473
  var GLOBAL_OBJECTS2 = /* @__PURE__ */ new Set([
8288
8474
  "globalThis",
8289
8475
  "window",
@@ -8302,66 +8488,66 @@ function matchesAnyPattern3(filename, patterns) {
8302
8488
  return false;
8303
8489
  }
8304
8490
  function isSetTimeoutCallee(callee) {
8305
- if (callee.type === AST_NODE_TYPES39.Identifier) {
8491
+ if (callee.type === AST_NODE_TYPES40.Identifier) {
8306
8492
  return callee.name === "setTimeout";
8307
8493
  }
8308
- return callee.type === AST_NODE_TYPES39.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES39.Identifier && callee.property.name === "setTimeout" && callee.object.type === AST_NODE_TYPES39.Identifier && GLOBAL_OBJECTS2.has(callee.object.name);
8494
+ return callee.type === AST_NODE_TYPES40.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES40.Identifier && callee.property.name === "setTimeout" && callee.object.type === AST_NODE_TYPES40.Identifier && GLOBAL_OBJECTS2.has(callee.object.name);
8309
8495
  }
8310
8496
  function soleCall(fn) {
8311
- if (fn.body.type !== AST_NODE_TYPES39.BlockStatement) {
8312
- return fn.body.type === AST_NODE_TYPES39.CallExpression ? fn.body : null;
8497
+ if (fn.body.type !== AST_NODE_TYPES40.BlockStatement) {
8498
+ return fn.body.type === AST_NODE_TYPES40.CallExpression ? fn.body : null;
8313
8499
  }
8314
8500
  if (fn.body.body.length !== 1) {
8315
8501
  return null;
8316
8502
  }
8317
8503
  const [only] = fn.body.body;
8318
- if (only?.type !== AST_NODE_TYPES39.ExpressionStatement) {
8504
+ if (only?.type !== AST_NODE_TYPES40.ExpressionStatement) {
8319
8505
  return null;
8320
8506
  }
8321
- return only.expression.type === AST_NODE_TYPES39.CallExpression ? only.expression : null;
8507
+ return only.expression.type === AST_NODE_TYPES40.CallExpression ? only.expression : null;
8322
8508
  }
8323
8509
  function isTimedDelay(delay) {
8324
8510
  if (delay === void 0) {
8325
8511
  return false;
8326
8512
  }
8327
- if (delay.type === AST_NODE_TYPES39.Literal && typeof delay.value === "number") {
8513
+ if (delay.type === AST_NODE_TYPES40.Literal && typeof delay.value === "number") {
8328
8514
  return delay.value !== 0;
8329
8515
  }
8330
8516
  return true;
8331
8517
  }
8332
8518
  function settlesWithoutValue(callback, name) {
8333
- if (callback.type === AST_NODE_TYPES39.Identifier) {
8519
+ if (callback.type === AST_NODE_TYPES40.Identifier) {
8334
8520
  return callback.name === name;
8335
8521
  }
8336
- if (callback.type !== AST_NODE_TYPES39.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES39.FunctionExpression) {
8522
+ if (callback.type !== AST_NODE_TYPES40.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES40.FunctionExpression) {
8337
8523
  return false;
8338
8524
  }
8339
8525
  const call = soleCall(callback);
8340
- return call !== null && call.arguments.length === 0 && call.callee.type === AST_NODE_TYPES39.Identifier && call.callee.name === name;
8526
+ return call !== null && call.arguments.length === 0 && call.callee.type === AST_NODE_TYPES40.Identifier && call.callee.name === name;
8341
8527
  }
8342
8528
  function rejectsInCallback(callback, name) {
8343
- if (callback.type === AST_NODE_TYPES39.Identifier) {
8529
+ if (callback.type === AST_NODE_TYPES40.Identifier) {
8344
8530
  return callback.name === name;
8345
8531
  }
8346
- if (callback.type !== AST_NODE_TYPES39.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES39.FunctionExpression) {
8532
+ if (callback.type !== AST_NODE_TYPES40.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES40.FunctionExpression) {
8347
8533
  return false;
8348
8534
  }
8349
8535
  const call = soleCall(callback);
8350
- return call !== null && call.callee.type === AST_NODE_TYPES39.Identifier && call.callee.name === name;
8536
+ return call !== null && call.callee.type === AST_NODE_TYPES40.Identifier && call.callee.name === name;
8351
8537
  }
8352
8538
  function parameterName(fn, index) {
8353
8539
  const parameter = fn.params[index];
8354
- return parameter?.type === AST_NODE_TYPES39.Identifier ? parameter.name : null;
8540
+ return parameter?.type === AST_NODE_TYPES40.Identifier ? parameter.name : null;
8355
8541
  }
8356
8542
  function isRaceArm(node) {
8357
8543
  const array = node.parent;
8358
- if (array?.type !== AST_NODE_TYPES39.ArrayExpression) {
8544
+ if (array?.type !== AST_NODE_TYPES40.ArrayExpression) {
8359
8545
  return false;
8360
8546
  }
8361
8547
  const call = array.parent;
8362
- return call?.type === AST_NODE_TYPES39.CallExpression && call.arguments[0] === array && call.callee.type === AST_NODE_TYPES39.MemberExpression && !call.callee.computed && call.callee.object.type === AST_NODE_TYPES39.Identifier && call.callee.object.name === "Promise" && call.callee.property.type === AST_NODE_TYPES39.Identifier && RACE_METHODS.has(call.callee.property.name);
8548
+ return call?.type === AST_NODE_TYPES40.CallExpression && call.arguments[0] === array && call.callee.type === AST_NODE_TYPES40.MemberExpression && !call.callee.computed && call.callee.object.type === AST_NODE_TYPES40.Identifier && call.callee.object.name === "Promise" && call.callee.property.type === AST_NODE_TYPES40.Identifier && RACE_METHODS.has(call.callee.property.name);
8363
8549
  }
8364
- var no_hand_rolled_sleep_default = ESLintUtils49.RuleCreator(
8550
+ var no_hand_rolled_sleep_default = ESLintUtils50.RuleCreator(
8365
8551
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8366
8552
  )({
8367
8553
  name: "no-hand-rolled-sleep",
@@ -8409,10 +8595,10 @@ var no_hand_rolled_sleep_default = ESLintUtils49.RuleCreator(
8409
8595
  }
8410
8596
  const program = sourceCode.ast;
8411
8597
  for (const statement of program.body) {
8412
- if (statement.type === AST_NODE_TYPES39.ExpressionStatement && statement.expression.type === AST_NODE_TYPES39.Literal && statement.expression.value === "use client") {
8598
+ if (statement.type === AST_NODE_TYPES40.ExpressionStatement && statement.expression.type === AST_NODE_TYPES40.Literal && statement.expression.value === "use client") {
8413
8599
  return true;
8414
8600
  }
8415
- if (statement.type === AST_NODE_TYPES39.ImportDeclaration && typeof statement.source.value === "string" && CLIENT_ONLY_MODULES.test(statement.source.value)) {
8601
+ if (statement.type === AST_NODE_TYPES40.ImportDeclaration && typeof statement.source.value === "string" && CLIENT_ONLY_MODULES.test(statement.source.value)) {
8416
8602
  return true;
8417
8603
  }
8418
8604
  }
@@ -8428,11 +8614,11 @@ var no_hand_rolled_sleep_default = ESLintUtils49.RuleCreator(
8428
8614
  };
8429
8615
  return {
8430
8616
  NewExpression(node) {
8431
- if (node.callee.type !== AST_NODE_TYPES39.Identifier || node.callee.name !== "Promise") {
8617
+ if (node.callee.type !== AST_NODE_TYPES40.Identifier || node.callee.name !== "Promise") {
8432
8618
  return;
8433
8619
  }
8434
8620
  const executor = node.arguments[0];
8435
- if (executor?.type !== AST_NODE_TYPES39.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES39.FunctionExpression) {
8621
+ if (executor?.type !== AST_NODE_TYPES40.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES40.FunctionExpression) {
8436
8622
  return;
8437
8623
  }
8438
8624
  const call = soleCall(executor);
@@ -8505,200 +8691,226 @@ var rules = {
8505
8691
  "jsdoc-restates-signature": jsdoc_restates_signature_default,
8506
8692
  "no-restated-comment": no_restated_comment_default,
8507
8693
  "trailing-value-narration": trailing_value_narration_default,
8694
+ "no-type-member-comment-wall": no_type_member_comment_wall_default,
8508
8695
  "no-tautological-expect": no_tautological_expect_default,
8509
8696
  "require-interface-for-injected-service": require_interface_for_injected_service_default,
8510
8697
  "strict-test-assertions": strict_test_assertions_default,
8511
8698
  "prefer-non-nullable-collection": prefer_non_nullable_collection_default,
8512
8699
  "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default
8513
8700
  };
8701
+ var meta = {
8702
+ name: "@sarj/eslint-plugin",
8703
+ version: "6.0.0"
8704
+ };
8705
+ var recommendedRules = {
8706
+ "@sarj/zod-naming-convention": "warn",
8707
+ "@sarj/require-assert-never": "error",
8708
+ "@sarj/require-zod-form-validation": "error",
8709
+ "@sarj/enforce-file-structure": "warn",
8710
+ "@sarj/no-client-side-data-fetching": "warn",
8711
+ "@sarj/prefer-server-actions": "warn",
8712
+ "@sarj/no-unnecessary-use-client": "warn",
8713
+ "@sarj/prefer-schema-for-api-payload": "warn",
8714
+ // Distilled from sarj-audit skills — warn in recommended, error in strict.
8715
+ "@sarj/no-sentinel-return-on-catch": "warn",
8716
+ "@sarj/no-log-only-catch": "warn",
8717
+ "@sarj/no-insecure-random-id": "warn",
8718
+ "@sarj/no-json-stringify-error": "warn",
8719
+ "@sarj/no-string-concat-in-loop": "warn",
8720
+ "@sarj/prefer-discriminated-union": "warn",
8721
+ "@sarj/no-comment-cruft": "warn",
8722
+ // Frontend / styling — distilled from frontend PR-review mining.
8723
+ "@sarj/prefer-semantic-colors": [
8724
+ "warn",
8725
+ { requireSemanticTokens: true }
8726
+ ],
8727
+ // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.
8728
+ "@sarj/no-fat-try-blocks": "warn",
8729
+ "@sarj/no-cors-wildcard-with-credentials": "warn",
8730
+ "@sarj/no-secret-in-log": "warn",
8731
+ "@sarj/no-unsafe-mock-casting": "warn",
8732
+ "@sarj/prefer-string-literal-union": "warn",
8733
+ "@sarj/prefer-zod-enum": "warn",
8734
+ // A type hand-written beside the Zod schema it restates drifts the
8735
+ // moment the schema gains a field. 30,759-file, 17-repo sweep
8736
+ // (2026-07): 5 reports, 5 true positives, all in public repos.
8737
+ // `requireIdenticalShape: false` widens it to 8 reports, 1 of them noise.
8738
+ "@sarj/prefer-zod-infer": "warn",
8739
+ // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
8740
+ "@sarj/require-fetch-timeout": "warn",
8741
+ "@sarj/no-silent-promise-catch": "warn",
8742
+ // Second SARJ port wave — the TS/Python parity gap. Each targets a
8743
+ // defect class seen in production Workers code: timing-leaky secret
8744
+ // compares, non-idempotent store writes under queue redelivery,
8745
+ // O(N) pagination, implicit row contracts, flaky timed tests.
8746
+ "@sarj/prefer-constant-time-secret-compare": "error",
8747
+ "@sarj/store-insert-requires-on-conflict": "warn",
8748
+ "@sarj/no-offset-pagination": "warn",
8749
+ "@sarj/no-select-star": "warn",
8750
+ // Uncancellable hand-rolled timers. Verified against the shipped
8751
+ // strict config (205 enabled rules) that nothing already reports this
8752
+ // position; `unicorn` 72 has no promisified-timer rule at all.
8753
+ "@sarj/no-hand-rolled-sleep": "warn",
8754
+ "@sarj/no-sleep-in-test-body": "warn",
8755
+ "@sarj/no-conditional-in-test": "warn",
8756
+ "@sarj/no-repeated-string-literal": "warn",
8757
+ "@sarj/no-positional-tuple-return": "warn",
8758
+ // Injection guard — low FP, applies to any repo touching SQL.
8759
+ "@sarj/no-dynamic-sql": "warn",
8760
+ // Mined from two years of PR review (SARJ-928). Schema-layer sibling of
8761
+ // `no-enum`; autofixable for inline string-literal objects.
8762
+ "@sarj/no-zod-native-enum": "warn",
8763
+ // Mined from two years of PR review — the single most frequent uncovered
8764
+ // theme (~37 PRs). Measured 17 hits / 1085 real TS files, all true
8765
+ // positives, so it is safe to run everywhere.
8766
+ "@sarj/prefer-module-level-constant": "warn",
8767
+ // Anti-comment-verbosity family (2026-07), from a 37,918-comment,
8768
+ // nine-repo measurement study. Each is a deletion-class finding, so each
8769
+ // was validated against pydantic / trio / attrs as well as the maintained
8770
+ // repos: `no-restated-comment` 0 hits in the flagship first-party
8771
+ // repo and 4 in the three famous
8772
+ // corpora combined; `trailing-value-narration` 18 hits, 18 true
8773
+ // positives; `jsdoc-restates-signature` 36 hits, 0 measured false
8774
+ // positives, and it offers a suggestion rather than a `--fix` because a
8775
+ // wrong deletion is silent information loss.
8776
+ "@sarj/no-restated-comment": "warn",
8777
+ "@sarj/jsdoc-restates-signature": "warn",
8778
+ "@sarj/trailing-value-narration": "warn",
8779
+ // The VOLUME arm of the same family (2026-07). Its siblings judge one
8780
+ // comment at a time and can only condemn one that adds nothing; this
8781
+ // one judges a TYPE, so it can report ten rows that each add a word.
8782
+ // 33 OSS TS repos / 46,861 files: 22 findings, all read, 0 false; zero
8783
+ // across ten first-party repos, where the generated-file sniff alone
8784
+ // removed 321 of the 407 raw hits. Measurements and the six false
8785
+ // positives that shaped the guards: docs/rules/no-type-member-comment-wall.md
8786
+ "@sarj/no-type-member-comment-wall": "warn",
8787
+ // The TS half of SARJ057 (2026-07). Python has caught the
8788
+ // assertion-FREE test since 0.15.0 (SARJ043) and had no TS
8789
+ // counterpart, which is how `expect(true).toBe(true); // placeholder`
8790
+ // survived in a first-party repo: the file HAS an assertion.
8791
+ // Measured across 5,819 .ts/.tsx files (1,003 of them test files) in
8792
+ // six internal repos plus got / hono / swr / trpc: 3 hits, 3 true
8793
+ // positives, 0 false positives.
8794
+ "@sarj/no-tautological-expect": "warn",
8795
+ // Substitutability: an exported service class with injected
8796
+ // collaborators and no interface above it can only be tested by
8797
+ // mocking. 11-repo sweep: 229 exported classes, 82% already carry a
8798
+ // port, 29 fire, 28 of them true positives.
8799
+ "@sarj/require-interface-for-injected-service": "warn",
8800
+ "@sarj/prefer-non-nullable-collection": "warn",
8801
+ "@sarj/no-async-callback-in-waitfor": "warn",
8802
+ // `strict-test-assertions` shipped in `rules` but in NEITHER preset, so a
8803
+ // consumer using `configs.recommended`/`configs.strict` instead of the shared
8804
+ // `eslint.strict.mjs` had silently never run it. `flat-presets.test.ts`
8805
+ // asserts strict wires every rule the plugin ships, so it cannot recur.
8806
+ "@sarj/strict-test-assertions": "warn"
8807
+ };
8808
+ var strictRules = {
8809
+ "@sarj/zod-naming-convention": "error",
8810
+ "@sarj/require-assert-never": "error",
8811
+ "@sarj/require-zod-form-validation": "error",
8812
+ "@sarj/enforce-file-structure": "error",
8813
+ "@sarj/no-raw-env": "error",
8814
+ "@sarj/no-enum": "error",
8815
+ "@sarj/no-client-side-data-fetching": "error",
8816
+ "@sarj/prefer-server-actions": "error",
8817
+ "@sarj/no-unnecessary-use-client": "error",
8818
+ "@sarj/prefer-schema-for-api-payload": "error",
8819
+ // Distilled from sarj-audit skills.
8820
+ "@sarj/no-sentinel-return-on-catch": "error",
8821
+ "@sarj/no-log-only-catch": "error",
8822
+ "@sarj/no-insecure-random-id": "error",
8823
+ "@sarj/no-json-stringify-error": "error",
8824
+ "@sarj/no-string-concat-in-loop": "error",
8825
+ "@sarj/prefer-discriminated-union": "error",
8826
+ "@sarj/no-comment-cruft": "error",
8827
+ // Frontend / styling — distilled from frontend PR-review mining. Stylistic,
8828
+ // no autofix → warn (rollout should prove the FP rate before raising it).
8829
+ "@sarj/prefer-semantic-colors": [
8830
+ "error",
8831
+ { requireSemanticTokens: true }
8832
+ ],
8833
+ // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.
8834
+ "@sarj/no-fat-try-blocks": "error",
8835
+ "@sarj/no-cors-wildcard-with-credentials": "error",
8836
+ "@sarj/no-secret-in-log": "error",
8837
+ "@sarj/no-unsafe-mock-casting": "error",
8838
+ // Promoted to error 2026-07-25 — strict means strict (user directive).
8839
+ "@sarj/prefer-string-literal-union": "error",
8840
+ "@sarj/prefer-zod-enum": "error",
8841
+ // See the `recommended` block for the measured counts.
8842
+ "@sarj/prefer-zod-infer": "error",
8843
+ // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
8844
+ "@sarj/require-fetch-timeout": "error",
8845
+ "@sarj/no-silent-promise-catch": "error",
8846
+ // Second SARJ port wave — the TS/Python parity gap.
8847
+ "@sarj/prefer-constant-time-secret-compare": "error",
8848
+ "@sarj/store-insert-requires-on-conflict": "error",
8849
+ "@sarj/no-offset-pagination": "error",
8850
+ "@sarj/no-select-star": "error",
8851
+ // Uncancellable hand-rolled timers. Verified against the shipped
8852
+ // strict config (205 enabled rules) that nothing already reports this
8853
+ // position; `unicorn` 72 has no promisified-timer rule at all.
8854
+ "@sarj/no-hand-rolled-sleep": "error",
8855
+ "@sarj/no-sleep-in-test-body": "error",
8856
+ "@sarj/no-conditional-in-test": "error",
8857
+ "@sarj/no-repeated-string-literal": "error",
8858
+ // API-shape advice rather than a runtime defect — a corpus sweep found its
8859
+ // only hits are parser `[value, cursor]` returns, which are conventional.
8860
+ // Warn even in strict until a rollout justifies more.
8861
+ "@sarj/no-positional-tuple-return": "error",
8862
+ "@sarj/no-dynamic-sql": "error",
8863
+ // Architectural: both need per-repo config to be meaningful, so they
8864
+ // are strict-only. `no-storage-in-stateless-modules` is a no-op until
8865
+ // its `modules` option names the directories a team declared stateless;
8866
+ // `no-raw-fetch-outside-clients` defaults to the `clients/` convention
8867
+ // and takes an `allow` list for repos that lay their client layer out
8868
+ // differently.
8869
+ "@sarj/no-raw-fetch-outside-clients": "error",
8870
+ "@sarj/no-storage-in-stateless-modules": "error",
8871
+ // Mined from two years of PR review (SARJ-928).
8872
+ "@sarj/no-zod-native-enum": "error",
8873
+ "@sarj/prefer-module-level-constant": "error",
8874
+ // Anti-comment-verbosity family (2026-07) — see the `recommended` block
8875
+ // for the measured hit counts and false-positive rates.
8876
+ "@sarj/no-restated-comment": "error",
8877
+ "@sarj/jsdoc-restates-signature": "error",
8878
+ "@sarj/trailing-value-narration": "error",
8879
+ "@sarj/no-type-member-comment-wall": "error",
8880
+ // TS half of SARJ057 — see the `recommended` block for the measurement.
8881
+ "@sarj/no-tautological-expect": "error",
8882
+ // Substitutability: the TS sibling of the Python `prefer-real-store-in-tests`
8883
+ // / `prefer-library-fake` wave. The convention already exists in the
8884
+ // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
8885
+ "@sarj/require-interface-for-injected-service": "error",
8886
+ "@sarj/prefer-non-nullable-collection": "error",
8887
+ "@sarj/no-async-callback-in-waitfor": "error",
8888
+ // See the `recommended` block.
8889
+ "@sarj/strict-test-assertions": "error"
8890
+ };
8514
8891
  var plugin = {
8515
- meta: {
8516
- name: "@sarj/eslint-plugin",
8517
- version: "5.0.0"
8518
- },
8892
+ meta,
8519
8893
  rules,
8520
8894
  configs: {
8521
- recommended: {
8522
- plugins: ["@sarj"],
8523
- rules: {
8524
- "@sarj/zod-naming-convention": "warn",
8525
- "@sarj/require-assert-never": "error",
8526
- "@sarj/require-zod-form-validation": "error",
8527
- "@sarj/enforce-file-structure": "warn",
8528
- "@sarj/no-client-side-data-fetching": "warn",
8529
- "@sarj/prefer-server-actions": "warn",
8530
- "@sarj/no-unnecessary-use-client": "warn",
8531
- "@sarj/prefer-schema-for-api-payload": "warn",
8532
- // Distilled from sarj-audit skills — warn in recommended, error in strict.
8533
- "@sarj/no-sentinel-return-on-catch": "warn",
8534
- "@sarj/no-log-only-catch": "warn",
8535
- "@sarj/no-insecure-random-id": "warn",
8536
- "@sarj/no-json-stringify-error": "warn",
8537
- "@sarj/no-string-concat-in-loop": "warn",
8538
- "@sarj/prefer-discriminated-union": "warn",
8539
- "@sarj/no-comment-cruft": "warn",
8540
- // Frontend / styling — distilled from frontend PR-review mining.
8541
- "@sarj/prefer-semantic-colors": [
8542
- "warn",
8543
- { requireSemanticTokens: true }
8544
- ],
8545
- // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.
8546
- "@sarj/no-fat-try-blocks": "warn",
8547
- "@sarj/no-cors-wildcard-with-credentials": "warn",
8548
- "@sarj/no-secret-in-log": "warn",
8549
- "@sarj/no-unsafe-mock-casting": "warn",
8550
- "@sarj/prefer-string-literal-union": "warn",
8551
- "@sarj/prefer-zod-enum": "warn",
8552
- // A type hand-written beside the Zod schema it restates drifts the
8553
- // moment the schema gains a field. 30,759-file, 17-repo sweep
8554
- // (2026-07): 5 reports, 5 true positives, all in public repos.
8555
- // `requireIdenticalShape: false` widens it to 8 reports, 1 of them noise.
8556
- "@sarj/prefer-zod-infer": "warn",
8557
- // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
8558
- "@sarj/require-fetch-timeout": "warn",
8559
- "@sarj/no-silent-promise-catch": "warn",
8560
- // Second SARJ port wave — the TS/Python parity gap. Each targets a
8561
- // defect class seen in production Workers code: timing-leaky secret
8562
- // compares, non-idempotent store writes under queue redelivery,
8563
- // O(N) pagination, implicit row contracts, flaky timed tests.
8564
- "@sarj/prefer-constant-time-secret-compare": "error",
8565
- "@sarj/store-insert-requires-on-conflict": "warn",
8566
- "@sarj/no-offset-pagination": "warn",
8567
- "@sarj/no-select-star": "warn",
8568
- // Uncancellable hand-rolled timers. Verified against the shipped
8569
- // strict config (205 enabled rules) that nothing already reports this
8570
- // position; `unicorn` 72 has no promisified-timer rule at all.
8571
- "@sarj/no-hand-rolled-sleep": "warn",
8572
- "@sarj/no-sleep-in-test-body": "warn",
8573
- "@sarj/no-conditional-in-test": "warn",
8574
- "@sarj/no-repeated-string-literal": "warn",
8575
- "@sarj/no-positional-tuple-return": "warn",
8576
- // Injection guard — low FP, applies to any repo touching SQL.
8577
- "@sarj/no-dynamic-sql": "warn",
8578
- // Mined from two years of PR review (SARJ-928). Schema-layer sibling of
8579
- // `no-enum`; autofixable for inline string-literal objects.
8580
- "@sarj/no-zod-native-enum": "warn",
8581
- // Mined from two years of PR review — the single most frequent uncovered
8582
- // theme (~37 PRs). Measured 17 hits / 1085 real TS files, all true
8583
- // positives, so it is safe to run everywhere.
8584
- "@sarj/prefer-module-level-constant": "warn",
8585
- // Anti-comment-verbosity family (2026-07), from a 37,918-comment,
8586
- // nine-repo measurement study. Each is a deletion-class finding, so each
8587
- // was validated against pydantic / trio / attrs as well as the maintained
8588
- // repos: `no-restated-comment` 0 hits in the flagship first-party
8589
- // repo and 4 in the three famous
8590
- // corpora combined; `trailing-value-narration` 18 hits, 18 true
8591
- // positives; `jsdoc-restates-signature` 36 hits, 0 measured false
8592
- // positives, and it offers a suggestion rather than a `--fix` because a
8593
- // wrong deletion is silent information loss.
8594
- "@sarj/no-restated-comment": "warn",
8595
- "@sarj/jsdoc-restates-signature": "warn",
8596
- "@sarj/trailing-value-narration": "warn",
8597
- // The TS half of SARJ057 (2026-07). Python has caught the
8598
- // assertion-FREE test since 0.15.0 (SARJ043) and had no TS
8599
- // counterpart, which is how `expect(true).toBe(true); // placeholder`
8600
- // survived in a first-party repo: the file HAS an assertion.
8601
- // Measured across 5,819 .ts/.tsx files (1,003 of them test files) in
8602
- // six internal repos plus got / hono / swr / trpc: 3 hits, 3 true
8603
- // positives, 0 false positives.
8604
- "@sarj/no-tautological-expect": "warn",
8605
- // Substitutability: an exported service class with injected
8606
- // collaborators and no interface above it can only be tested by
8607
- // mocking. 11-repo sweep: 229 exported classes, 82% already carry a
8608
- // port, 29 fire, 28 of them true positives.
8609
- "@sarj/require-interface-for-injected-service": "warn",
8610
- "@sarj/prefer-non-nullable-collection": "warn",
8611
- "@sarj/no-async-callback-in-waitfor": "warn"
8612
- }
8613
- },
8614
- strict: {
8615
- plugins: ["@sarj"],
8616
- rules: {
8617
- "@sarj/zod-naming-convention": "error",
8618
- "@sarj/require-assert-never": "error",
8619
- "@sarj/require-zod-form-validation": "error",
8620
- "@sarj/enforce-file-structure": "error",
8621
- "@sarj/no-raw-env": "error",
8622
- "@sarj/no-enum": "error",
8623
- "@sarj/no-client-side-data-fetching": "error",
8624
- "@sarj/prefer-server-actions": "error",
8625
- "@sarj/no-unnecessary-use-client": "error",
8626
- "@sarj/prefer-schema-for-api-payload": "error",
8627
- // Distilled from sarj-audit skills.
8628
- "@sarj/no-sentinel-return-on-catch": "error",
8629
- "@sarj/no-log-only-catch": "error",
8630
- "@sarj/no-insecure-random-id": "error",
8631
- "@sarj/no-json-stringify-error": "error",
8632
- "@sarj/no-string-concat-in-loop": "error",
8633
- "@sarj/prefer-discriminated-union": "error",
8634
- "@sarj/no-comment-cruft": "error",
8635
- // Frontend / styling — distilled from frontend PR-review mining. Stylistic,
8636
- // no autofix → warn (rollout should prove the FP rate before raising it).
8637
- "@sarj/prefer-semantic-colors": [
8638
- "error",
8639
- { requireSemanticTokens: true }
8640
- ],
8641
- // Ported from sarj-python-lint (SARJ), corpus-validated FP~0.
8642
- "@sarj/no-fat-try-blocks": "error",
8643
- "@sarj/no-cors-wildcard-with-credentials": "error",
8644
- "@sarj/no-secret-in-log": "error",
8645
- "@sarj/no-unsafe-mock-casting": "error",
8646
- // Promoted to error 2026-07-25 — strict means strict (user directive).
8647
- "@sarj/prefer-string-literal-union": "error",
8648
- "@sarj/prefer-zod-enum": "error",
8649
- // See the `recommended` block for the measured counts.
8650
- "@sarj/prefer-zod-infer": "error",
8651
- // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
8652
- "@sarj/require-fetch-timeout": "error",
8653
- "@sarj/no-silent-promise-catch": "error",
8654
- // Second SARJ port wave — the TS/Python parity gap.
8655
- "@sarj/prefer-constant-time-secret-compare": "error",
8656
- "@sarj/store-insert-requires-on-conflict": "error",
8657
- "@sarj/no-offset-pagination": "error",
8658
- "@sarj/no-select-star": "error",
8659
- // Uncancellable hand-rolled timers. Verified against the shipped
8660
- // strict config (205 enabled rules) that nothing already reports this
8661
- // position; `unicorn` 72 has no promisified-timer rule at all.
8662
- "@sarj/no-hand-rolled-sleep": "error",
8663
- "@sarj/no-sleep-in-test-body": "error",
8664
- "@sarj/no-conditional-in-test": "error",
8665
- "@sarj/no-repeated-string-literal": "error",
8666
- // API-shape advice rather than a runtime defect — a corpus sweep found its
8667
- // only hits are parser `[value, cursor]` returns, which are conventional.
8668
- // Warn even in strict until a rollout justifies more.
8669
- "@sarj/no-positional-tuple-return": "error",
8670
- "@sarj/no-dynamic-sql": "error",
8671
- // Architectural: both need per-repo config to be meaningful, so they
8672
- // are strict-only. `no-storage-in-stateless-modules` is a no-op until
8673
- // its `modules` option names the directories a team declared stateless;
8674
- // `no-raw-fetch-outside-clients` defaults to the `clients/` convention
8675
- // and takes an `allow` list for repos that lay their client layer out
8676
- // differently.
8677
- "@sarj/no-raw-fetch-outside-clients": "error",
8678
- "@sarj/no-storage-in-stateless-modules": "error",
8679
- // Mined from two years of PR review (SARJ-928).
8680
- "@sarj/no-zod-native-enum": "error",
8681
- "@sarj/prefer-module-level-constant": "error",
8682
- // Anti-comment-verbosity family (2026-07) — see the `recommended` block
8683
- // for the measured hit counts and false-positive rates.
8684
- "@sarj/no-restated-comment": "error",
8685
- "@sarj/jsdoc-restates-signature": "error",
8686
- "@sarj/trailing-value-narration": "error",
8687
- // TS half of SARJ057 — see the `recommended` block for the measurement.
8688
- "@sarj/no-tautological-expect": "error",
8689
- // Substitutability: the TS sibling of the Python `prefer-real-store-in-tests`
8690
- // / `prefer-library-fake` wave. The convention already exists in the
8691
- // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
8692
- "@sarj/require-interface-for-injected-service": "error",
8693
- "@sarj/prefer-non-nullable-collection": "error",
8694
- "@sarj/no-async-callback-in-waitfor": "error"
8695
- }
8696
- }
8895
+ recommended: {},
8896
+ strict: {}
8697
8897
  }
8698
8898
  };
8899
+ plugin.configs.recommended = {
8900
+ name: "@sarj/recommended",
8901
+ plugins: { "@sarj": plugin },
8902
+ rules: recommendedRules
8903
+ };
8904
+ plugin.configs.strict = {
8905
+ name: "@sarj/strict",
8906
+ plugins: { "@sarj": plugin },
8907
+ rules: strictRules
8908
+ };
8699
8909
  var index_default = plugin;
8700
8910
  export {
8701
8911
  index_default as default,
8702
- rules
8912
+ recommendedRules,
8913
+ rules,
8914
+ strictRules
8703
8915
  };
8704
8916
  //# sourceMappingURL=index.js.map