@sarj/eslint-plugin 2.15.0 → 2.17.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 CHANGED
@@ -35,7 +35,7 @@ __export(index_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
- // src/rules/enforce-file-structure.ts
38
+ // src/rules/ban-loose-type-guards-in-tests.ts
39
39
  var import_utils = require("@typescript-eslint/utils");
40
40
 
41
41
  // src/rules/_paths.ts
@@ -61,27 +61,63 @@ function isScriptFile(filename) {
61
61
  return SCRIPT_FILE_RE.test(filename);
62
62
  }
63
63
 
64
+ // src/rules/ban-loose-type-guards-in-tests.ts
65
+ var ban_loose_type_guards_in_tests_default = import_utils.ESLintUtils.RuleCreator(
66
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
67
+ )({
68
+ name: "ban-loose-type-guards-in-tests",
69
+ meta: {
70
+ type: "problem",
71
+ docs: {
72
+ description: "Disallow loose type guards (`typeof` and `in`) in test files. Enforce Zod schemas or strict matchers for type validation."
73
+ },
74
+ schema: [],
75
+ messages: {
76
+ banLooseTypeGuardsInTests: "Do not use `typeof` or `in` for type validation in tests. Use Zod schemas or strict assertion matchers instead."
77
+ }
78
+ },
79
+ defaultOptions: [],
80
+ create(context) {
81
+ if (!isTestFile(context.filename)) {
82
+ return {};
83
+ }
84
+ return {
85
+ UnaryExpression(node) {
86
+ if (node.operator === "typeof") {
87
+ context.report({ node, messageId: "banLooseTypeGuardsInTests" });
88
+ }
89
+ },
90
+ BinaryExpression(node) {
91
+ if (node.operator === "in") {
92
+ context.report({ node, messageId: "banLooseTypeGuardsInTests" });
93
+ }
94
+ }
95
+ };
96
+ }
97
+ });
98
+
64
99
  // src/rules/enforce-file-structure.ts
100
+ var import_utils2 = require("@typescript-eslint/utils");
65
101
  var classifyStatement = (statement) => {
66
102
  switch (statement.type) {
67
- case import_utils.AST_NODE_TYPES.ImportDeclaration:
103
+ case import_utils2.AST_NODE_TYPES.ImportDeclaration:
68
104
  return "import";
69
- case import_utils.AST_NODE_TYPES.ExportAllDeclaration:
105
+ case import_utils2.AST_NODE_TYPES.ExportAllDeclaration:
70
106
  return "reexport";
71
- case import_utils.AST_NODE_TYPES.ExportNamedDeclaration:
107
+ case import_utils2.AST_NODE_TYPES.ExportNamedDeclaration:
72
108
  return statement.declaration === null ? "reexport" : "body";
73
109
  default:
74
110
  return "body";
75
111
  }
76
112
  };
77
- var isStringDirective = (statement) => statement.type === import_utils.AST_NODE_TYPES.ExpressionStatement && statement.expression.type === import_utils.AST_NODE_TYPES.Literal && typeof statement.expression.value === "string" && statement.expression.value.startsWith("use ");
113
+ var isStringDirective = (statement) => statement.type === import_utils2.AST_NODE_TYPES.ExpressionStatement && statement.expression.type === import_utils2.AST_NODE_TYPES.Literal && typeof statement.expression.value === "string" && statement.expression.value.startsWith("use ");
78
114
  var isUseServerDirective = (statement) => {
79
- if (statement.type !== import_utils.AST_NODE_TYPES.ExpressionStatement) return false;
115
+ if (statement.type !== import_utils2.AST_NODE_TYPES.ExpressionStatement) return false;
80
116
  const expr = statement.expression;
81
- if (expr.type !== import_utils.AST_NODE_TYPES.Literal) return false;
117
+ if (expr.type !== import_utils2.AST_NODE_TYPES.Literal) return false;
82
118
  return expr.value === "use server";
83
119
  };
84
- var enforce_file_structure_default = import_utils.ESLintUtils.RuleCreator(
120
+ var enforce_file_structure_default = import_utils2.ESLintUtils.RuleCreator(
85
121
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
86
122
  )({
87
123
  name: "enforce-file-structure",
@@ -141,7 +177,7 @@ var enforce_file_structure_default = import_utils.ESLintUtils.RuleCreator(
141
177
  });
142
178
 
143
179
  // src/rules/no-client-side-data-fetching.ts
144
- var import_utils2 = require("@typescript-eslint/utils");
180
+ var import_utils3 = require("@typescript-eslint/utils");
145
181
  var FETCH_LIBS = /* @__PURE__ */ new Set(["axios", "ky", "superagent"]);
146
182
  var HTTP_METHOD_NAMES = /* @__PURE__ */ new Set([
147
183
  "get",
@@ -165,25 +201,25 @@ var ANALYTICS_SEGMENTS = /* @__PURE__ */ new Set([
165
201
  ]);
166
202
  function isEffectHookCall(node) {
167
203
  const callee = node.callee;
168
- if (callee.type === import_utils2.AST_NODE_TYPES.Identifier) {
204
+ if (callee.type === import_utils3.AST_NODE_TYPES.Identifier) {
169
205
  return callee.name === "useEffect" || callee.name === "useLayoutEffect";
170
206
  }
171
- if (callee.type === import_utils2.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils2.AST_NODE_TYPES.Identifier && callee.object.name === "React" && callee.property.type === import_utils2.AST_NODE_TYPES.Identifier) {
207
+ if (callee.type === import_utils3.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils3.AST_NODE_TYPES.Identifier && callee.object.name === "React" && callee.property.type === import_utils3.AST_NODE_TYPES.Identifier) {
172
208
  return callee.property.name === "useEffect" || callee.property.name === "useLayoutEffect";
173
209
  }
174
210
  return false;
175
211
  }
176
212
  function readMethodProperty(optionsArg) {
177
- if (!optionsArg || optionsArg.type !== import_utils2.AST_NODE_TYPES.ObjectExpression) {
213
+ if (!optionsArg || optionsArg.type !== import_utils3.AST_NODE_TYPES.ObjectExpression) {
178
214
  return null;
179
215
  }
180
216
  for (const prop of optionsArg.properties) {
181
- if (prop.type !== import_utils2.AST_NODE_TYPES.Property) continue;
217
+ if (prop.type !== import_utils3.AST_NODE_TYPES.Property) continue;
182
218
  if (prop.computed) continue;
183
219
  const key = prop.key;
184
- const matchesMethodKey = key.type === import_utils2.AST_NODE_TYPES.Identifier && key.name === "method" || key.type === import_utils2.AST_NODE_TYPES.Literal && key.value === "method";
220
+ const matchesMethodKey = key.type === import_utils3.AST_NODE_TYPES.Identifier && key.name === "method" || key.type === import_utils3.AST_NODE_TYPES.Literal && key.value === "method";
185
221
  if (!matchesMethodKey) continue;
186
- if (prop.value.type === import_utils2.AST_NODE_TYPES.Literal && typeof prop.value.value === "string") {
222
+ if (prop.value.type === import_utils3.AST_NODE_TYPES.Literal && typeof prop.value.value === "string") {
187
223
  return prop.value.value.toUpperCase();
188
224
  }
189
225
  return null;
@@ -192,23 +228,23 @@ function readMethodProperty(optionsArg) {
192
228
  }
193
229
  function isFetchCall(node) {
194
230
  const callee = node.callee;
195
- if (callee.type === import_utils2.AST_NODE_TYPES.Identifier && callee.name === "fetch") {
231
+ if (callee.type === import_utils3.AST_NODE_TYPES.Identifier && callee.name === "fetch") {
196
232
  const method = readMethodProperty(node.arguments[1]);
197
233
  if (method !== null && method !== "GET") {
198
234
  return false;
199
235
  }
200
236
  return true;
201
237
  }
202
- if (callee.type === import_utils2.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils2.AST_NODE_TYPES.Identifier && FETCH_LIBS.has(callee.object.name) && callee.property.type === import_utils2.AST_NODE_TYPES.Identifier) {
238
+ if (callee.type === import_utils3.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils3.AST_NODE_TYPES.Identifier && FETCH_LIBS.has(callee.object.name) && callee.property.type === import_utils3.AST_NODE_TYPES.Identifier) {
203
239
  return HTTP_METHOD_NAMES.has(callee.property.name);
204
240
  }
205
- if (callee.type === import_utils2.AST_NODE_TYPES.Identifier && (callee.name === "axios" || callee.name === "ky")) {
241
+ if (callee.type === import_utils3.AST_NODE_TYPES.Identifier && (callee.name === "axios" || callee.name === "ky")) {
206
242
  const firstArg = node.arguments[0];
207
243
  const secondArg = node.arguments[1];
208
244
  let configArg;
209
- if (firstArg?.type === import_utils2.AST_NODE_TYPES.ObjectExpression) {
245
+ if (firstArg?.type === import_utils3.AST_NODE_TYPES.ObjectExpression) {
210
246
  configArg = firstArg;
211
- } else if (secondArg?.type === import_utils2.AST_NODE_TYPES.ObjectExpression) {
247
+ } else if (secondArg?.type === import_utils3.AST_NODE_TYPES.ObjectExpression) {
212
248
  configArg = secondArg;
213
249
  }
214
250
  const method = readMethodProperty(configArg);
@@ -222,13 +258,13 @@ function isFetchCall(node) {
222
258
  function extractUrlString(node) {
223
259
  const firstArg = node.arguments[0];
224
260
  if (!firstArg) return "";
225
- if (firstArg.type === import_utils2.AST_NODE_TYPES.Literal && typeof firstArg.value === "string") {
261
+ if (firstArg.type === import_utils3.AST_NODE_TYPES.Literal && typeof firstArg.value === "string") {
226
262
  return firstArg.value;
227
263
  }
228
- if (firstArg.type === import_utils2.AST_NODE_TYPES.TemplateLiteral) {
264
+ if (firstArg.type === import_utils3.AST_NODE_TYPES.TemplateLiteral) {
229
265
  return firstArg.quasis.map((q) => q.value.cooked).join("");
230
266
  }
231
- if (firstArg.type === import_utils2.AST_NODE_TYPES.Identifier) {
267
+ if (firstArg.type === import_utils3.AST_NODE_TYPES.Identifier) {
232
268
  return firstArg.name;
233
269
  }
234
270
  return "";
@@ -238,7 +274,7 @@ function isAnalyticsCall(node) {
238
274
  if (url === "") return false;
239
275
  return url.split(/[/.]/).some((segment) => ANALYTICS_SEGMENTS.has(segment));
240
276
  }
241
- var no_client_side_data_fetching_default = import_utils2.ESLintUtils.RuleCreator(
277
+ var no_client_side_data_fetching_default = import_utils3.ESLintUtils.RuleCreator(
242
278
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
243
279
  )({
244
280
  name: "no-client-side-data-fetching",
@@ -276,10 +312,10 @@ var no_client_side_data_fetching_default = import_utils2.ESLintUtils.RuleCreator
276
312
  });
277
313
 
278
314
  // src/rules/no-comment-cruft.ts
279
- var import_utils4 = require("@typescript-eslint/utils");
315
+ var import_utils5 = require("@typescript-eslint/utils");
280
316
 
281
317
  // src/rules/_comments.ts
282
- var import_utils3 = require("@typescript-eslint/utils");
318
+ var import_utils4 = require("@typescript-eslint/utils");
283
319
  var REF_RE = /https?:\/\/|\bRFC[- ]?\d+|\bPEP[- ]?\d+|\bCVE-\d{4}|\b(?!UTF-|SHA-|ISO-|AES-|CRC-|MD-|PCM-|EOF-|API-|BASE-)[A-Z][A-Z0-9]{1,9}-\d[A-Z0-9]{0,5}\b|(?<![&\w])#\d{2,6}\b|@[a-z][\w.-]*\.(?:us|com|ai|io|net|org|dev)\b/;
284
320
  var VERSION_RE = /(?:>=|<=|==|<|>)\s*v?\d+\.\d+|\bv\d+\.\d+|\b(?:since|until|as of)\s+(?:v?\d+\.\d+|Python\s*\d)/i;
285
321
  var UNITS_RE = /[~<>]?\d+(?:\.\d+)?\s?(?:ms|s\b|sec\b|seconds?\b|min\b|minutes?\b|hours?\b|days?\b|KB|MB|MiB|GiB|kHz|Hz|bytes?\b|bit\b|-bit\b|%|px\b|rps\b|qps\b)|\b[1-5]xx\b|\b(?:301|302|304|307|308|400|401|403|404|405|409|410|412|422|425|429|500|501|502|503|504)\b/;
@@ -365,10 +401,10 @@ var NARRATION_MAX_WORDS = 6;
365
401
  var NARRATION_MIN_CONTENT = 1;
366
402
  var TOKEN_PLURAL_MIN = 4;
367
403
  var RESTATABLE_STATEMENTS = /* @__PURE__ */ new Set([
368
- import_utils3.AST_NODE_TYPES.ExpressionStatement,
369
- import_utils3.AST_NODE_TYPES.ReturnStatement,
370
- import_utils3.AST_NODE_TYPES.ThrowStatement,
371
- import_utils3.AST_NODE_TYPES.VariableDeclaration
404
+ import_utils4.AST_NODE_TYPES.ExpressionStatement,
405
+ import_utils4.AST_NODE_TYPES.ReturnStatement,
406
+ import_utils4.AST_NODE_TYPES.ThrowStatement,
407
+ import_utils4.AST_NODE_TYPES.VariableDeclaration
372
408
  ]);
373
409
  var NARRATION_VERB_RE = /^(?:add|append|assign|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|make|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|d|ed|ing)?$/i;
374
410
  var NARRATION_STOPWORDS = /* @__PURE__ */ new Set([
@@ -433,19 +469,19 @@ function headTokens(source) {
433
469
  function isTrivialInitializer(node) {
434
470
  return node.declarations.every((declarator) => {
435
471
  const init = declarator.init;
436
- if (init == null || init.type === import_utils3.AST_NODE_TYPES.Literal) return true;
437
- return init.type === import_utils3.AST_NODE_TYPES.ArrayExpression && init.elements.length === 0 || init.type === import_utils3.AST_NODE_TYPES.ObjectExpression && init.properties.length === 0;
472
+ if (init == null || init.type === import_utils4.AST_NODE_TYPES.Literal) return true;
473
+ return init.type === import_utils4.AST_NODE_TYPES.ArrayExpression && init.elements.length === 0 || init.type === import_utils4.AST_NODE_TYPES.ObjectExpression && init.properties.length === 0;
438
474
  });
439
475
  }
440
476
  function restatableStatementBelow(comment, sourceCode) {
441
477
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
442
478
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) return null;
443
- for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils3.AST_NODE_TYPES.Program; node = node.parent) {
479
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils4.AST_NODE_TYPES.Program; node = node.parent) {
444
480
  if (!RESTATABLE_STATEMENTS.has(node.type)) continue;
445
481
  if (node.loc.start.line !== token.loc.start.line || node.loc.end.line !== node.loc.start.line) {
446
482
  return null;
447
483
  }
448
- if (node.type === import_utils3.AST_NODE_TYPES.VariableDeclaration && isTrivialInitializer(node)) {
484
+ if (node.type === import_utils4.AST_NODE_TYPES.VariableDeclaration && isTrivialInitializer(node)) {
449
485
  return null;
450
486
  }
451
487
  return sourceCode.getText(node);
@@ -467,9 +503,9 @@ function restatesStatementHead(body, statement) {
467
503
 
468
504
  // src/rules/no-comment-cruft.ts
469
505
  var LEADING_PREAMBLE_MIN = 4;
470
- var STEP_NARRATION_RE = /^(?:first(?:ly)?|second(?:ly)?|third(?:ly)?|then|next|after(?:wards| that)?|finally|lastly|now)\s*[,:]\s*\S|^step\s+\d+\b/i;
506
+ var STEP_NARRATION_RE = /^(?:first(?:ly)?|second(?:ly)?|third(?:ly)?|then|next|after(?:wards| that)?|finally|lastly|now)\s*[,:]\s*\S/i;
471
507
  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;
472
- 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|todo\b|fixme\b|hack\b|xxx\b)/i;
508
+ 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;
473
509
  var LICENSE_RE = /copyright|licen[cs]ed?|spdx|permission is hereby granted|all rights reserved/i;
474
510
  var ENUMERATED_ITEM_RE = /^(?:\d+[.):]|[-*•])\s+\S/;
475
511
  var ENUMERATED_ITEM_MIN_WORDS = 3;
@@ -535,7 +571,8 @@ function isSectionLabel(text) {
535
571
  }
536
572
  var HELPER_OPENER_RE = /^(?:a\s+)?helper\s+(?:function|method|component|hook|class|type|util(?:ity)?)\b/i;
537
573
  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;
538
- var ENUMERATION_RE = /^(?:\d+[.)]\s+\S|phase\s+\d+\b)/i;
574
+ var ENUMERATION_RE = /^(?:\d+[.)]\s+\S|(?:phase|step)\s+\d+\b)/i;
575
+ var DUMMY_TRANSLATION_RE = /^(?:increment|return|returns|get|gets|set\b(?! up\b)|sets\b(?! up\b)|function to|method to)\b/i;
539
576
  var DIAGRAM_ARROW_RE = /[-=~]{2,}>|<[-=~]{2,}/;
540
577
  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\.)/;
541
578
  var CODE_TAIL_RE = /[;{}()]\s*$|=>\s*$|,\s*$/;
@@ -583,19 +620,27 @@ function isRedundantNarration(body, statementBelow, standalone, isolatedEnumerat
583
620
  if (STEP_NARRATION_RE.test(t)) return true;
584
621
  if (META_COMMENTARY_RE.test(t) && !JUSTIFICATION_RE.test(t)) return true;
585
622
  if (HELPER_OPENER_RE.test(t) || LETS_RE.test(t)) return true;
623
+ const words = t.split(/\s+/);
624
+ if (words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
625
+ const lowerT = t.toLowerCase();
626
+ const rationaleWords = ["when", "because", "if", "so that", "due to", "for", "instead of", "to prevent", "to avoid", "only"];
627
+ if (!rationaleWords.some((w) => lowerT.includes(w))) {
628
+ if (words.length > 1) return true;
629
+ }
630
+ }
586
631
  if (!nested && isSectionLabel(t)) return true;
587
632
  if (isolatedEnumeration && ENUMERATION_RE.test(t)) return true;
588
633
  }
589
634
  return restatesStatementHead(t, statementBelow);
590
635
  }
591
636
  var STATEMENT_CONTAINERS = /* @__PURE__ */ new Set([
592
- import_utils4.AST_NODE_TYPES.Program,
593
- import_utils4.AST_NODE_TYPES.BlockStatement,
594
- import_utils4.AST_NODE_TYPES.ClassBody,
595
- import_utils4.AST_NODE_TYPES.StaticBlock,
596
- import_utils4.AST_NODE_TYPES.SwitchCase,
597
- import_utils4.AST_NODE_TYPES.TSModuleBlock,
598
- import_utils4.AST_NODE_TYPES.TSInterfaceBody
637
+ import_utils5.AST_NODE_TYPES.Program,
638
+ import_utils5.AST_NODE_TYPES.BlockStatement,
639
+ import_utils5.AST_NODE_TYPES.ClassBody,
640
+ import_utils5.AST_NODE_TYPES.StaticBlock,
641
+ import_utils5.AST_NODE_TYPES.SwitchCase,
642
+ import_utils5.AST_NODE_TYPES.TSModuleBlock,
643
+ import_utils5.AST_NODE_TYPES.TSInterfaceBody
599
644
  ]);
600
645
  function runCitesAReference(comments, index) {
601
646
  for (let i = index; i >= 0; i--) {
@@ -636,7 +681,7 @@ function hasCommentedOutCode(texts, precedingProse) {
636
681
  }
637
682
  return false;
638
683
  }
639
- var no_comment_cruft_default = import_utils4.ESLintUtils.RuleCreator(
684
+ var no_comment_cruft_default = import_utils5.ESLintUtils.RuleCreator(
640
685
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
641
686
  )({
642
687
  name: "no-comment-cruft",
@@ -650,7 +695,8 @@ var no_comment_cruft_default = import_utils4.ESLintUtils.RuleCreator(
650
695
  commentedOutCode: "Commented-out code \u2014 delete it; git history remembers.",
651
696
  sectionBanner: "Section-banner / region comment \u2014 structure code with functions, not ASCII rules.",
652
697
  fileHeaderPreamble: "File-header comment preamble \u2014 use a brief doc comment for the why, not a block of `//` lines.",
653
- redundantNarration: "Comment narrates the code \u2014 delete it or say *why*, not *what*. Code is self-documenting."
698
+ redundantNarration: "Comment narrates the code \u2014 delete it or say *why*, not *what*. Code is self-documenting.",
699
+ untrackedTodo: "Untracked TODO/FIXME marker \u2014 add an issue ticket or context link."
654
700
  }
655
701
  },
656
702
  defaultOptions: [],
@@ -704,6 +750,16 @@ var no_comment_cruft_default = import_utils4.ESLintUtils.RuleCreator(
704
750
  if (isJsDoc(comment) || !isStandalone(comment)) continue;
705
751
  if (LICENSE_RE.test(comment.value)) continue;
706
752
  const texts = comment.value.split("\n").map(stripCommentMarker).filter((l) => l.length > 0 && !isDirective(l));
753
+ const firstText = texts[0];
754
+ if (firstText !== void 0 && /^(?:todo|fixme)\b/i.test(firstText)) {
755
+ if (!runCitesAReference(comments, i)) {
756
+ context.report({
757
+ node: comment,
758
+ messageId: "untrackedTodo"
759
+ });
760
+ }
761
+ continue;
762
+ }
707
763
  if (texts.some(isBanner)) {
708
764
  context.report({ node: comment, messageId: "sectionBanner" });
709
765
  continue;
@@ -732,7 +788,7 @@ var no_comment_cruft_default = import_utils4.ESLintUtils.RuleCreator(
732
788
  });
733
789
 
734
790
  // src/rules/no-enum.ts
735
- var import_utils5 = require("@typescript-eslint/utils");
791
+ var import_utils6 = require("@typescript-eslint/utils");
736
792
  var DEFAULT_IGNORE_PATTERNS = [
737
793
  /[\\/]generated[\\/]/,
738
794
  /[\\/]openapi-gen[\\/]/,
@@ -752,7 +808,7 @@ function hasGeneratedMarker(sourceText) {
752
808
  const head = sourceText.slice(0, 1024);
753
809
  return /@generated\b/.test(head);
754
810
  }
755
- var no_enum_default = import_utils5.ESLintUtils.RuleCreator(
811
+ var no_enum_default = import_utils6.ESLintUtils.RuleCreator(
756
812
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
757
813
  )({
758
814
  name: "no-enum",
@@ -803,7 +859,7 @@ var no_enum_default = import_utils5.ESLintUtils.RuleCreator(
803
859
  });
804
860
 
805
861
  // src/rules/no-insecure-random-id.ts
806
- var import_utils6 = require("@typescript-eslint/utils");
862
+ var import_utils7 = require("@typescript-eslint/utils");
807
863
  var STRONG_SECURITY_PATTERN = /token|secret|csrf|password|passwd|apikey|api[-_]?key|nonce|salt|uuid|authid/i;
808
864
  var NON_SECURITY_ID_PATTERN = /temp|tmp|cache|correlation|request|req|trace|execution|dev|hmr|mock|test|perf|marker/i;
809
865
  var PATH_OR_DOM_MARKER = /[\\/#]|\.[A-Za-z0-9]/;
@@ -944,7 +1000,7 @@ function isConcatenatedIntoPathOrDomId(node) {
944
1000
  collectStaticStringParts(top, parts);
945
1001
  return parts.some((part) => PATH_OR_DOM_MARKER.test(part));
946
1002
  }
947
- var no_insecure_random_id_default = import_utils6.ESLintUtils.RuleCreator(
1003
+ var no_insecure_random_id_default = import_utils7.ESLintUtils.RuleCreator(
948
1004
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
949
1005
  )({
950
1006
  name: "no-insecure-random-id",
@@ -988,7 +1044,7 @@ var no_insecure_random_id_default = import_utils6.ESLintUtils.RuleCreator(
988
1044
  });
989
1045
 
990
1046
  // src/rules/no-json-stringify-error.ts
991
- var import_utils7 = require("@typescript-eslint/utils");
1047
+ var import_utils8 = require("@typescript-eslint/utils");
992
1048
  var ERROR_NAME_PATTERN = /^(e|err|error|ex|exc)$/i;
993
1049
  var ERROR_PROP_PATTERN = /^(cause|lastError|error|err|exception|originalError|innerError)$/i;
994
1050
  var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
@@ -1122,7 +1178,7 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
1122
1178
  function isJsonStringify(callee) {
1123
1179
  return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "stringify";
1124
1180
  }
1125
- var no_json_stringify_error_default = import_utils7.ESLintUtils.RuleCreator(
1181
+ var no_json_stringify_error_default = import_utils8.ESLintUtils.RuleCreator(
1126
1182
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1127
1183
  )({
1128
1184
  name: "no-json-stringify-error",
@@ -1172,10 +1228,10 @@ var no_json_stringify_error_default = import_utils7.ESLintUtils.RuleCreator(
1172
1228
  });
1173
1229
 
1174
1230
  // src/rules/no-log-only-catch.ts
1175
- var import_utils9 = require("@typescript-eslint/utils");
1231
+ var import_utils10 = require("@typescript-eslint/utils");
1176
1232
 
1177
1233
  // src/rules/_logging.ts
1178
- var import_utils8 = require("@typescript-eslint/utils");
1234
+ var import_utils9 = require("@typescript-eslint/utils");
1179
1235
  var LOG_METHODS = /* @__PURE__ */ new Set([
1180
1236
  "debug",
1181
1237
  "info",
@@ -1282,7 +1338,7 @@ var DEFAULT_IGNORE_PATTERNS2 = [
1282
1338
  /\.spec\./,
1283
1339
  /[\\/]__tests__[\\/]/
1284
1340
  ];
1285
- var no_log_only_catch_default = import_utils9.ESLintUtils.RuleCreator(
1341
+ var no_log_only_catch_default = import_utils10.ESLintUtils.RuleCreator(
1286
1342
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1287
1343
  )({
1288
1344
  name: "no-log-only-catch",
@@ -1345,7 +1401,7 @@ var no_log_only_catch_default = import_utils9.ESLintUtils.RuleCreator(
1345
1401
  });
1346
1402
 
1347
1403
  // src/rules/no-raw-env.ts
1348
- var import_utils10 = require("@typescript-eslint/utils");
1404
+ var import_utils11 = require("@typescript-eslint/utils");
1349
1405
  var CONFIG_FILE_RE = /(^|[\\/])[\w.-]+\.config\.[cm]?[jt]sx?$/;
1350
1406
  var ENV_BOUNDARY_FILE_RE = /(^|[\\/])(?:env|client-env|server-env|client-settings|server-settings)\.[cm]?[jt]sx?$/;
1351
1407
  function isValidatedEnvBoundary(filename, sourceText) {
@@ -1383,7 +1439,7 @@ function isWholeEnvSpread(node) {
1383
1439
  const parent = node.parent;
1384
1440
  return parent.type === "SpreadElement" && parent.argument === node;
1385
1441
  }
1386
- var no_raw_env_default = import_utils10.ESLintUtils.RuleCreator(
1442
+ var no_raw_env_default = import_utils11.ESLintUtils.RuleCreator(
1387
1443
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1388
1444
  )({
1389
1445
  name: "no-raw-env",
@@ -1417,12 +1473,12 @@ var no_raw_env_default = import_utils10.ESLintUtils.RuleCreator(
1417
1473
  });
1418
1474
 
1419
1475
  // src/rules/no-sentinel-return-on-catch.ts
1420
- var import_utils11 = require("@typescript-eslint/utils");
1476
+ var import_utils12 = require("@typescript-eslint/utils");
1421
1477
  function sentinelKind(arg) {
1422
1478
  if (arg === null) {
1423
1479
  return null;
1424
1480
  }
1425
- if (arg.type === import_utils11.AST_NODE_TYPES.Literal) {
1481
+ if (arg.type === import_utils12.AST_NODE_TYPES.Literal) {
1426
1482
  if (arg.value === null) {
1427
1483
  return "nullish";
1428
1484
  }
@@ -1434,13 +1490,13 @@ function sentinelKind(arg) {
1434
1490
  }
1435
1491
  return null;
1436
1492
  }
1437
- if (arg.type === import_utils11.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1493
+ if (arg.type === import_utils12.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1438
1494
  return "nullish";
1439
1495
  }
1440
- if (arg.type === import_utils11.AST_NODE_TYPES.ArrayExpression) {
1496
+ if (arg.type === import_utils12.AST_NODE_TYPES.ArrayExpression) {
1441
1497
  return "array";
1442
1498
  }
1443
- if (arg.type === import_utils11.AST_NODE_TYPES.ObjectExpression) {
1499
+ if (arg.type === import_utils12.AST_NODE_TYPES.ObjectExpression) {
1444
1500
  return "object";
1445
1501
  }
1446
1502
  return null;
@@ -1449,25 +1505,25 @@ function isSentinelArgument(arg) {
1449
1505
  if (arg === null) {
1450
1506
  return false;
1451
1507
  }
1452
- if (arg.type === import_utils11.AST_NODE_TYPES.Literal && arg.value === null) {
1508
+ if (arg.type === import_utils12.AST_NODE_TYPES.Literal && arg.value === null) {
1453
1509
  return true;
1454
1510
  }
1455
- if (arg.type === import_utils11.AST_NODE_TYPES.Literal && arg.value === false) {
1511
+ if (arg.type === import_utils12.AST_NODE_TYPES.Literal && arg.value === false) {
1456
1512
  return true;
1457
1513
  }
1458
- if (arg.type === import_utils11.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1514
+ if (arg.type === import_utils12.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1459
1515
  return true;
1460
1516
  }
1461
- if (arg.type === import_utils11.AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {
1517
+ if (arg.type === import_utils12.AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {
1462
1518
  return true;
1463
1519
  }
1464
- if (arg.type === import_utils11.AST_NODE_TYPES.ObjectExpression && arg.properties.length === 0) {
1520
+ if (arg.type === import_utils12.AST_NODE_TYPES.ObjectExpression && arg.properties.length === 0) {
1465
1521
  return true;
1466
1522
  }
1467
1523
  return false;
1468
1524
  }
1469
1525
  function isFunctionNode(node) {
1470
- return node.type === import_utils11.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils11.AST_NODE_TYPES.FunctionExpression || node.type === import_utils11.AST_NODE_TYPES.ArrowFunctionExpression;
1526
+ return node.type === import_utils12.AST_NODE_TYPES.FunctionDeclaration || node.type === import_utils12.AST_NODE_TYPES.FunctionExpression || node.type === import_utils12.AST_NODE_TYPES.ArrowFunctionExpression;
1471
1527
  }
1472
1528
  function isNode(value) {
1473
1529
  return typeof value === "object" && value !== null && typeof value.type === "string";
@@ -1507,24 +1563,24 @@ function walkWithinScope(node, visit) {
1507
1563
  function containsThrow(node) {
1508
1564
  return walkWithinScope(
1509
1565
  node,
1510
- (current) => current.type === import_utils11.AST_NODE_TYPES.ThrowStatement
1566
+ (current) => current.type === import_utils12.AST_NODE_TYPES.ThrowStatement
1511
1567
  );
1512
1568
  }
1513
1569
  function bindsName(param, name) {
1514
1570
  switch (param.type) {
1515
- case import_utils11.AST_NODE_TYPES.Identifier:
1571
+ case import_utils12.AST_NODE_TYPES.Identifier:
1516
1572
  return param.name === name;
1517
- case import_utils11.AST_NODE_TYPES.AssignmentPattern:
1573
+ case import_utils12.AST_NODE_TYPES.AssignmentPattern:
1518
1574
  return bindsName(param.left, name);
1519
- case import_utils11.AST_NODE_TYPES.RestElement:
1575
+ case import_utils12.AST_NODE_TYPES.RestElement:
1520
1576
  return bindsName(param.argument, name);
1521
- case import_utils11.AST_NODE_TYPES.ArrayPattern:
1577
+ case import_utils12.AST_NODE_TYPES.ArrayPattern:
1522
1578
  return param.elements.some(
1523
1579
  (element) => element !== null && bindsName(element, name)
1524
1580
  );
1525
- case import_utils11.AST_NODE_TYPES.ObjectPattern:
1581
+ case import_utils12.AST_NODE_TYPES.ObjectPattern:
1526
1582
  return param.properties.some(
1527
- (property) => property.type === import_utils11.AST_NODE_TYPES.RestElement ? bindsName(property.argument, name) : bindsName(property.value, name)
1583
+ (property) => property.type === import_utils12.AST_NODE_TYPES.RestElement ? bindsName(property.argument, name) : bindsName(property.value, name)
1528
1584
  );
1529
1585
  default:
1530
1586
  return false;
@@ -1539,7 +1595,7 @@ function subtreeReadsName(node, name) {
1539
1595
  if (found) {
1540
1596
  return;
1541
1597
  }
1542
- if (current.type === import_utils11.AST_NODE_TYPES.Identifier && current.name === name) {
1598
+ if (current.type === import_utils12.AST_NODE_TYPES.Identifier && current.name === name) {
1543
1599
  found = true;
1544
1600
  return;
1545
1601
  }
@@ -1550,10 +1606,10 @@ function subtreeReadsName(node, name) {
1550
1606
  if (key === "parent") {
1551
1607
  continue;
1552
1608
  }
1553
- if (key === "key" && current.type === import_utils11.AST_NODE_TYPES.Property && !current.computed) {
1609
+ if (key === "key" && current.type === import_utils12.AST_NODE_TYPES.Property && !current.computed) {
1554
1610
  continue;
1555
1611
  }
1556
- if (key === "property" && current.type === import_utils11.AST_NODE_TYPES.MemberExpression && !current.computed) {
1612
+ if (key === "property" && current.type === import_utils12.AST_NODE_TYPES.MemberExpression && !current.computed) {
1557
1613
  continue;
1558
1614
  }
1559
1615
  const value = current[key];
@@ -1586,10 +1642,10 @@ var SAFE_PARSE_CONSTRUCTORS = /* @__PURE__ */ new Set([
1586
1642
  "URLPattern"
1587
1643
  ]);
1588
1644
  function isParseShapedNode(node) {
1589
- if (node.type === import_utils11.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils11.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils11.AST_NODE_TYPES.Identifier) {
1645
+ if (node.type === import_utils12.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils12.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils12.AST_NODE_TYPES.Identifier) {
1590
1646
  return node.callee.property.name === "parse";
1591
1647
  }
1592
- if (node.type === import_utils11.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils11.AST_NODE_TYPES.Identifier) {
1648
+ if (node.type === import_utils12.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils12.AST_NODE_TYPES.Identifier) {
1593
1649
  return SAFE_PARSE_CONSTRUCTORS.has(node.callee.name);
1594
1650
  }
1595
1651
  return false;
@@ -1600,10 +1656,10 @@ var BODY_DECODE_METHODS = /* @__PURE__ */ new Set([
1600
1656
  "arrayBuffer"
1601
1657
  ]);
1602
1658
  function isBodyDecodeNode(node) {
1603
- return node.type === import_utils11.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils11.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils11.AST_NODE_TYPES.Identifier && BODY_DECODE_METHODS.has(node.callee.property.name);
1659
+ return node.type === import_utils12.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils12.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils12.AST_NODE_TYPES.Identifier && BODY_DECODE_METHODS.has(node.callee.property.name);
1604
1660
  }
1605
1661
  function returnsMatching(stmt, predicate) {
1606
- return stmt.type === import_utils11.AST_NODE_TYPES.ReturnStatement && stmt.argument !== null && walkWithinScope(stmt.argument, predicate);
1662
+ return stmt.type === import_utils12.AST_NODE_TYPES.ReturnStatement && stmt.argument !== null && walkWithinScope(stmt.argument, predicate);
1607
1663
  }
1608
1664
  function enclosingReturnTypeNode(node) {
1609
1665
  let current = node.parent;
@@ -1621,11 +1677,11 @@ function enclosingFunctionName(node) {
1621
1677
  let current = node.parent;
1622
1678
  while (current !== void 0 && current !== null) {
1623
1679
  if (isFunctionNode(current)) {
1624
- if ("id" in current && isNode(current.id) && current.id.type === import_utils11.AST_NODE_TYPES.Identifier) {
1680
+ if ("id" in current && isNode(current.id) && current.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
1625
1681
  return current.id.name;
1626
1682
  }
1627
1683
  const parent = current.parent;
1628
- if (parent?.type === import_utils11.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils11.AST_NODE_TYPES.Identifier) {
1684
+ if (parent?.type === import_utils12.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
1629
1685
  return parent.id.name;
1630
1686
  }
1631
1687
  return null;
@@ -1646,10 +1702,10 @@ function isDeclaredBooleanPredicate(catchNode, kind) {
1646
1702
  return false;
1647
1703
  }
1648
1704
  let declared = enclosingReturnTypeNode(catchNode);
1649
- if (declared?.type === import_utils11.AST_NODE_TYPES.TSTypeReference && declared.typeName.type === import_utils11.AST_NODE_TYPES.Identifier && declared.typeName.name === "Promise") {
1705
+ if (declared?.type === import_utils12.AST_NODE_TYPES.TSTypeReference && declared.typeName.type === import_utils12.AST_NODE_TYPES.Identifier && declared.typeName.name === "Promise") {
1650
1706
  declared = declared.typeArguments?.params[0] ?? null;
1651
1707
  }
1652
- return declared?.type === import_utils11.AST_NODE_TYPES.TSBooleanKeyword;
1708
+ return declared?.type === import_utils12.AST_NODE_TYPES.TSBooleanKeyword;
1653
1709
  }
1654
1710
  function tryReturnsSafeParse(catchNode) {
1655
1711
  const tryBlock = tryBlockOf(catchNode);
@@ -1665,7 +1721,7 @@ function tryReturnsSafeParse(catchNode) {
1665
1721
  function enclosingFunctionBody(node) {
1666
1722
  let current = node.parent;
1667
1723
  while (current !== void 0 && current !== null) {
1668
- if (isFunctionNode(current) && "body" in current && isNode(current.body) && current.body.type === import_utils11.AST_NODE_TYPES.BlockStatement) {
1724
+ if (isFunctionNode(current) && "body" in current && isNode(current.body) && current.body.type === import_utils12.AST_NODE_TYPES.BlockStatement) {
1669
1725
  return current.body;
1670
1726
  }
1671
1727
  current = current.parent;
@@ -1678,7 +1734,7 @@ function functionReturnsSameSentinelKindElsewhere(catchNode, kind) {
1678
1734
  return false;
1679
1735
  }
1680
1736
  return walkWithinScope(functionBody, (current) => {
1681
- if (current.type !== import_utils11.AST_NODE_TYPES.ReturnStatement) {
1737
+ if (current.type !== import_utils12.AST_NODE_TYPES.ReturnStatement) {
1682
1738
  return false;
1683
1739
  }
1684
1740
  if (isWithin(current, catchNode.body)) {
@@ -1697,13 +1753,13 @@ function returnedSentinelKinds(arg) {
1697
1753
  kinds.add(direct);
1698
1754
  return kinds;
1699
1755
  }
1700
- if (arg.type === import_utils11.AST_NODE_TYPES.ConditionalExpression) {
1756
+ if (arg.type === import_utils12.AST_NODE_TYPES.ConditionalExpression) {
1701
1757
  for (const branch of [arg.consequent, arg.alternate]) {
1702
1758
  for (const nested of returnedSentinelKinds(branch)) {
1703
1759
  kinds.add(nested);
1704
1760
  }
1705
1761
  }
1706
- } else if (arg.type === import_utils11.AST_NODE_TYPES.LogicalExpression && (arg.operator === "??" || arg.operator === "||")) {
1762
+ } else if (arg.type === import_utils12.AST_NODE_TYPES.LogicalExpression && (arg.operator === "??" || arg.operator === "||")) {
1707
1763
  for (const nested of returnedSentinelKinds(arg.right)) {
1708
1764
  kinds.add(nested);
1709
1765
  }
@@ -1720,7 +1776,7 @@ function isWithin(node, ancestor) {
1720
1776
  }
1721
1777
  return false;
1722
1778
  }
1723
- var no_sentinel_return_on_catch_default = import_utils11.ESLintUtils.RuleCreator(
1779
+ var no_sentinel_return_on_catch_default = import_utils12.ESLintUtils.RuleCreator(
1724
1780
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1725
1781
  )({
1726
1782
  name: "no-sentinel-return-on-catch",
@@ -1748,7 +1804,7 @@ var no_sentinel_return_on_catch_default = import_utils11.ESLintUtils.RuleCreator
1748
1804
  const matcher = createLogMatcher(loggingOptions);
1749
1805
  function logsOrReportsError(catchBody, caughtName) {
1750
1806
  return walkWithinScope(catchBody, (current) => {
1751
- if (current.type !== import_utils11.AST_NODE_TYPES.CallExpression) {
1807
+ if (current.type !== import_utils12.AST_NODE_TYPES.CallExpression) {
1752
1808
  return false;
1753
1809
  }
1754
1810
  if (matcher.isLoggingCall(current)) {
@@ -1765,7 +1821,7 @@ var no_sentinel_return_on_catch_default = import_utils11.ESLintUtils.RuleCreator
1765
1821
  return;
1766
1822
  }
1767
1823
  const last = body[body.length - 1];
1768
- if (last === void 0 || last.type !== import_utils11.AST_NODE_TYPES.ReturnStatement) {
1824
+ if (last === void 0 || last.type !== import_utils12.AST_NODE_TYPES.ReturnStatement) {
1769
1825
  return;
1770
1826
  }
1771
1827
  if (!isSentinelArgument(last.argument)) {
@@ -1774,7 +1830,7 @@ var no_sentinel_return_on_catch_default = import_utils11.ESLintUtils.RuleCreator
1774
1830
  if (containsThrow(node.body)) {
1775
1831
  return;
1776
1832
  }
1777
- const caughtName = node.param?.type === import_utils11.AST_NODE_TYPES.Identifier ? node.param.name : null;
1833
+ const caughtName = node.param?.type === import_utils12.AST_NODE_TYPES.Identifier ? node.param.name : null;
1778
1834
  if (logsOrReportsError(node.body, caughtName)) {
1779
1835
  return;
1780
1836
  }
@@ -1801,7 +1857,7 @@ var no_sentinel_return_on_catch_default = import_utils11.ESLintUtils.RuleCreator
1801
1857
  });
1802
1858
 
1803
1859
  // src/rules/no-sequential-await.ts
1804
- var import_utils12 = require("@typescript-eslint/utils");
1860
+ var import_utils13 = require("@typescript-eslint/utils");
1805
1861
  var ARRAY_ITERATION_METHODS = /* @__PURE__ */ new Set(["forEach", "map", "filter"]);
1806
1862
  var SEQUENTIAL_ITERABLE_HINT = /sort|reverse|ordered|sequence|hook|middleware|pipeline|preset|plugin|extension|\bstage|\bstep|\bphase|migration|chain|buffer|stream|teleport|chunk|\bqueue|drain/i;
1807
1863
  var BENCH_FILE_RE = /(^|[\\/])bench(marks?)?[\\/]|\.bench\.[cm]?[jt]sx?$/i;
@@ -1955,7 +2011,7 @@ function shouldReport(awaits, earlyExit, iterableText, asserts = false) {
1955
2011
  (node) => !isTimerYield(node) && !isThreadedAccumulator(node) && !isQueueDrain(node)
1956
2012
  );
1957
2013
  }
1958
- var no_sequential_await_default = import_utils12.ESLintUtils.RuleCreator(
2014
+ var no_sequential_await_default = import_utils13.ESLintUtils.RuleCreator(
1959
2015
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1960
2016
  )({
1961
2017
  name: "no-sequential-await",
@@ -2050,7 +2106,7 @@ var no_sequential_await_default = import_utils12.ESLintUtils.RuleCreator(
2050
2106
  });
2051
2107
 
2052
2108
  // src/rules/no-string-concat-in-loop.ts
2053
- var import_utils13 = require("@typescript-eslint/utils");
2109
+ var import_utils14 = require("@typescript-eslint/utils");
2054
2110
  var LOOP_NODE_TYPES = /* @__PURE__ */ new Set([
2055
2111
  "ForStatement",
2056
2112
  "ForOfStatement",
@@ -2135,7 +2191,7 @@ function enclosingLoop(node) {
2135
2191
  }
2136
2192
  return null;
2137
2193
  }
2138
- var no_string_concat_in_loop_default = import_utils13.ESLintUtils.RuleCreator(
2194
+ var no_string_concat_in_loop_default = import_utils14.ESLintUtils.RuleCreator(
2139
2195
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2140
2196
  )({
2141
2197
  name: "no-string-concat-in-loop",
@@ -2198,7 +2254,7 @@ var no_string_concat_in_loop_default = import_utils13.ESLintUtils.RuleCreator(
2198
2254
  });
2199
2255
 
2200
2256
  // src/rules/no-unnecessary-use-client.ts
2201
- var import_utils14 = require("@typescript-eslint/utils");
2257
+ var import_utils15 = require("@typescript-eslint/utils");
2202
2258
  var HOOK_REGEX = /^use([A-Z]|$)/;
2203
2259
  var EVENT_PROP_REGEX = /^on[A-Z]/;
2204
2260
  var ERROR_FILE_REGEX = /\b(?:global-)?error\.[jt]sx?$/;
@@ -2224,13 +2280,13 @@ var CLIENT_ONLY_PACKAGES_REGEX = /^(?:@radix-ui\/|framer-motion|react-dom|react-
2224
2280
  var isBareSpecifier = (source) => !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("@/") && !source.startsWith("~");
2225
2281
  var jsxRootName = (name) => {
2226
2282
  let current = name;
2227
- while (current.type === import_utils14.AST_NODE_TYPES.JSXMemberExpression) {
2283
+ while (current.type === import_utils15.AST_NODE_TYPES.JSXMemberExpression) {
2228
2284
  current = current.object;
2229
2285
  }
2230
- return current.type === import_utils14.AST_NODE_TYPES.JSXIdentifier ? current.name : "";
2286
+ return current.type === import_utils15.AST_NODE_TYPES.JSXIdentifier ? current.name : "";
2231
2287
  };
2232
2288
  var subtreeReadsImportedBinding = (node, imported) => {
2233
- if (node.type === import_utils14.AST_NODE_TYPES.Identifier) {
2289
+ if (node.type === import_utils15.AST_NODE_TYPES.Identifier) {
2234
2290
  return imported.has(node.name);
2235
2291
  }
2236
2292
  for (const key of Object.keys(node)) {
@@ -2245,16 +2301,16 @@ var subtreeReadsImportedBinding = (node, imported) => {
2245
2301
  return false;
2246
2302
  };
2247
2303
  var isUseClientDirective = (node) => {
2248
- return node.type === import_utils14.AST_NODE_TYPES.ExpressionStatement && node.expression.type === import_utils14.AST_NODE_TYPES.Literal && node.expression.value === "use client";
2304
+ return node.type === import_utils15.AST_NODE_TYPES.ExpressionStatement && node.expression.type === import_utils15.AST_NODE_TYPES.Literal && node.expression.value === "use client";
2249
2305
  };
2250
2306
  var isGlobalReference = (node, context) => {
2251
2307
  if (!BROWSER_GLOBALS.has(node.name)) return false;
2252
2308
  const parent = node.parent;
2253
2309
  if (parent !== void 0) {
2254
- if (parent.type === import_utils14.AST_NODE_TYPES.MemberExpression && parent.property === node && !parent.computed) {
2310
+ if (parent.type === import_utils15.AST_NODE_TYPES.MemberExpression && parent.property === node && !parent.computed) {
2255
2311
  return false;
2256
2312
  }
2257
- if (parent.type === import_utils14.AST_NODE_TYPES.Property && parent.key === node && !parent.computed) {
2313
+ if (parent.type === import_utils15.AST_NODE_TYPES.Property && parent.key === node && !parent.computed) {
2258
2314
  return false;
2259
2315
  }
2260
2316
  if (parent.type.startsWith("TS")) {
@@ -2271,7 +2327,7 @@ var isGlobalReference = (node, context) => {
2271
2327
  }
2272
2328
  return true;
2273
2329
  };
2274
- var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2330
+ var no_unnecessary_use_client_default = import_utils15.ESLintUtils.RuleCreator(
2275
2331
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2276
2332
  )({
2277
2333
  name: "no-unnecessary-use-client",
@@ -2296,13 +2352,13 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2296
2352
  const importedLocals = /* @__PURE__ */ new Set();
2297
2353
  const externalLocals = /* @__PURE__ */ new Set();
2298
2354
  const markIfHookOrContext = (callee) => {
2299
- if (callee.type === import_utils14.AST_NODE_TYPES.Identifier) {
2355
+ if (callee.type === import_utils15.AST_NODE_TYPES.Identifier) {
2300
2356
  if (HOOK_REGEX.test(callee.name) || callee.name === "createContext") {
2301
2357
  hasClientIndicator = true;
2302
2358
  }
2303
2359
  return;
2304
2360
  }
2305
- if (callee.type === import_utils14.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils14.AST_NODE_TYPES.Identifier) {
2361
+ if (callee.type === import_utils15.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils15.AST_NODE_TYPES.Identifier) {
2306
2362
  const name = callee.property.name;
2307
2363
  if (HOOK_REGEX.test(name) || name === "createContext") {
2308
2364
  hasClientIndicator = true;
@@ -2312,7 +2368,7 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2312
2368
  return {
2313
2369
  Program(node) {
2314
2370
  for (const stmt of node.body) {
2315
- if (stmt.type !== import_utils14.AST_NODE_TYPES.ExpressionStatement) break;
2371
+ if (stmt.type !== import_utils15.AST_NODE_TYPES.ExpressionStatement) break;
2316
2372
  if (isUseClientDirective(stmt)) {
2317
2373
  directiveNode = stmt;
2318
2374
  break;
@@ -2325,7 +2381,7 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2325
2381
  },
2326
2382
  JSXAttribute(node) {
2327
2383
  if (directiveNode === null) return;
2328
- if (node.name.type === import_utils14.AST_NODE_TYPES.JSXIdentifier && EVENT_PROP_REGEX.test(node.name.name)) {
2384
+ if (node.name.type === import_utils15.AST_NODE_TYPES.JSXIdentifier && EVENT_PROP_REGEX.test(node.name.name)) {
2329
2385
  hasClientIndicator = true;
2330
2386
  }
2331
2387
  },
@@ -2392,8 +2448,8 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2392
2448
  });
2393
2449
 
2394
2450
  // src/rules/prefer-discriminated-union.ts
2395
- var import_utils15 = require("@typescript-eslint/utils");
2396
2451
  var import_utils16 = require("@typescript-eslint/utils");
2452
+ var import_utils17 = require("@typescript-eslint/utils");
2397
2453
  var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2398
2454
  "success",
2399
2455
  "ok",
@@ -2403,27 +2459,27 @@ var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2403
2459
  ]);
2404
2460
  var MIN_OPTIONAL_MEMBERS = 2;
2405
2461
  function getMemberName(member) {
2406
- if (member.type !== import_utils16.AST_NODE_TYPES.TSPropertySignature) {
2462
+ if (member.type !== import_utils17.AST_NODE_TYPES.TSPropertySignature) {
2407
2463
  return null;
2408
2464
  }
2409
2465
  const { key } = member;
2410
- if (key.type === import_utils16.AST_NODE_TYPES.Identifier) {
2466
+ if (key.type === import_utils17.AST_NODE_TYPES.Identifier) {
2411
2467
  return key.name;
2412
2468
  }
2413
- if (key.type === import_utils16.AST_NODE_TYPES.Literal && typeof key.value === "string") {
2469
+ if (key.type === import_utils17.AST_NODE_TYPES.Literal && typeof key.value === "string") {
2414
2470
  return key.value;
2415
2471
  }
2416
2472
  return null;
2417
2473
  }
2418
2474
  function isBooleanTyped(member) {
2419
- return member.typeAnnotation?.typeAnnotation.type === import_utils16.AST_NODE_TYPES.TSBooleanKeyword;
2475
+ return member.typeAnnotation?.typeAnnotation.type === import_utils17.AST_NODE_TYPES.TSBooleanKeyword;
2420
2476
  }
2421
2477
  function looksLikeMutuallyExclusiveState(typeLiteral) {
2422
2478
  let hasStatusBoolean = false;
2423
2479
  let optionalCount = 0;
2424
2480
  let optionalPayloadCount = 0;
2425
2481
  for (const member of typeLiteral.members) {
2426
- if (member.type !== import_utils16.AST_NODE_TYPES.TSPropertySignature) {
2482
+ if (member.type !== import_utils17.AST_NODE_TYPES.TSPropertySignature) {
2427
2483
  continue;
2428
2484
  }
2429
2485
  if (member.optional) {
@@ -2439,7 +2495,7 @@ function looksLikeMutuallyExclusiveState(typeLiteral) {
2439
2495
  }
2440
2496
  return hasStatusBoolean && optionalCount >= MIN_OPTIONAL_MEMBERS && optionalPayloadCount >= 1;
2441
2497
  }
2442
- var prefer_discriminated_union_default = import_utils15.ESLintUtils.RuleCreator(
2498
+ var prefer_discriminated_union_default = import_utils16.ESLintUtils.RuleCreator(
2443
2499
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2444
2500
  )({
2445
2501
  name: "prefer-discriminated-union",
@@ -2467,7 +2523,7 @@ var prefer_discriminated_union_default = import_utils15.ESLintUtils.RuleCreator(
2467
2523
  TSInterfaceDeclaration(node) {
2468
2524
  const synthetic = {
2469
2525
  ...node.body,
2470
- type: import_utils16.AST_NODE_TYPES.TSTypeLiteral,
2526
+ type: import_utils17.AST_NODE_TYPES.TSTypeLiteral,
2471
2527
  members: node.body.body
2472
2528
  };
2473
2529
  checkTypeLiteral(synthetic, node);
@@ -2480,13 +2536,13 @@ var prefer_discriminated_union_default = import_utils15.ESLintUtils.RuleCreator(
2480
2536
  });
2481
2537
 
2482
2538
  // src/rules/prefer-schema-for-api-payload.ts
2483
- var import_utils17 = require("@typescript-eslint/utils");
2539
+ var import_utils18 = require("@typescript-eslint/utils");
2484
2540
  var unwrap = (node) => {
2485
2541
  let current = node;
2486
2542
  while (current !== null && current !== void 0) {
2487
- if (current.type === import_utils17.AST_NODE_TYPES.TSAsExpression || current.type === import_utils17.AST_NODE_TYPES.TSTypeAssertion || current.type === import_utils17.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils17.AST_NODE_TYPES.TSSatisfiesExpression) {
2543
+ if (current.type === import_utils18.AST_NODE_TYPES.TSAsExpression || current.type === import_utils18.AST_NODE_TYPES.TSTypeAssertion || current.type === import_utils18.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils18.AST_NODE_TYPES.TSSatisfiesExpression) {
2488
2544
  current = current.expression;
2489
- } else if (current.type === import_utils17.AST_NODE_TYPES.ChainExpression) {
2545
+ } else if (current.type === import_utils18.AST_NODE_TYPES.ChainExpression) {
2490
2546
  current = current.expression;
2491
2547
  } else {
2492
2548
  break;
@@ -2497,25 +2553,25 @@ var unwrap = (node) => {
2497
2553
  var isRawPayloadSource = (node) => {
2498
2554
  let current = unwrap(node);
2499
2555
  if (current === null) return false;
2500
- if (current.type === import_utils17.AST_NODE_TYPES.AwaitExpression) {
2556
+ if (current.type === import_utils18.AST_NODE_TYPES.AwaitExpression) {
2501
2557
  current = unwrap(current.argument);
2502
2558
  }
2503
- if (current === null || current.type !== import_utils17.AST_NODE_TYPES.CallExpression) {
2559
+ if (current === null || current.type !== import_utils18.AST_NODE_TYPES.CallExpression) {
2504
2560
  return false;
2505
2561
  }
2506
2562
  const callee = unwrap(current.callee);
2507
- if (callee === null || callee.type !== import_utils17.AST_NODE_TYPES.MemberExpression) {
2563
+ if (callee === null || callee.type !== import_utils18.AST_NODE_TYPES.MemberExpression) {
2508
2564
  return false;
2509
2565
  }
2510
2566
  const property = unwrap(callee.property);
2511
- if (property === null || property.type !== import_utils17.AST_NODE_TYPES.Identifier) {
2567
+ if (property === null || property.type !== import_utils18.AST_NODE_TYPES.Identifier) {
2512
2568
  return false;
2513
2569
  }
2514
2570
  if (property.name === "json") {
2515
2571
  return true;
2516
2572
  }
2517
2573
  const object = unwrap(callee.object);
2518
- return property.name === "parse" && object !== null && object.type === import_utils17.AST_NODE_TYPES.Identifier && object.name === "JSON" && // ...but not `JSON.parse(readFileSync(p, "utf8"))` — see isLocalFileRead.
2574
+ return property.name === "parse" && object !== null && object.type === import_utils18.AST_NODE_TYPES.Identifier && object.name === "JSON" && // ...but not `JSON.parse(readFileSync(p, "utf8"))` — see isLocalFileRead.
2519
2575
  !isLocalFileRead(current.arguments[0]);
2520
2576
  };
2521
2577
  var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
@@ -2523,9 +2579,9 @@ var isLocalFileRead = (node) => {
2523
2579
  let found = false;
2524
2580
  const visit = (current) => {
2525
2581
  if (found || current === null || current === void 0) return;
2526
- if (current.type === import_utils17.AST_NODE_TYPES.CallExpression) {
2582
+ if (current.type === import_utils18.AST_NODE_TYPES.CallExpression) {
2527
2583
  const callee = unwrap(current.callee);
2528
- const name = callee?.type === import_utils17.AST_NODE_TYPES.Identifier ? callee.name : callee?.type === import_utils17.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils17.AST_NODE_TYPES.Identifier ? callee.property.name : null;
2584
+ const name = callee?.type === import_utils18.AST_NODE_TYPES.Identifier ? callee.name : callee?.type === import_utils18.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils18.AST_NODE_TYPES.Identifier ? callee.property.name : null;
2529
2585
  if (name !== null && FILE_READ_RE.test(name)) {
2530
2586
  found = true;
2531
2587
  return;
@@ -2547,15 +2603,15 @@ var isLocalFileRead = (node) => {
2547
2603
  var ASSERTION_CALLEE_RE2 = /^(expect|assert|should|invariant)$/;
2548
2604
  var isInsideAssertion = (node) => {
2549
2605
  for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
2550
- if (current.type !== import_utils17.AST_NODE_TYPES.CallExpression) continue;
2606
+ if (current.type !== import_utils18.AST_NODE_TYPES.CallExpression) continue;
2551
2607
  let callee = current.callee;
2552
- while (callee.type === import_utils17.AST_NODE_TYPES.MemberExpression) {
2608
+ while (callee.type === import_utils18.AST_NODE_TYPES.MemberExpression) {
2553
2609
  callee = callee.object;
2554
2610
  }
2555
- if (callee.type === import_utils17.AST_NODE_TYPES.CallExpression) {
2611
+ if (callee.type === import_utils18.AST_NODE_TYPES.CallExpression) {
2556
2612
  callee = callee.callee;
2557
2613
  }
2558
- if (callee.type === import_utils17.AST_NODE_TYPES.Identifier && ASSERTION_CALLEE_RE2.test(callee.name)) {
2614
+ if (callee.type === import_utils18.AST_NODE_TYPES.Identifier && ASSERTION_CALLEE_RE2.test(callee.name)) {
2559
2615
  return true;
2560
2616
  }
2561
2617
  }
@@ -2576,17 +2632,17 @@ var isGuardTestPosition = (node) => {
2576
2632
  let parent = current.parent;
2577
2633
  while (parent !== void 0 && parent !== null) {
2578
2634
  switch (parent.type) {
2579
- case import_utils17.AST_NODE_TYPES.UnaryExpression:
2580
- case import_utils17.AST_NODE_TYPES.LogicalExpression:
2581
- case import_utils17.AST_NODE_TYPES.ChainExpression:
2635
+ case import_utils18.AST_NODE_TYPES.UnaryExpression:
2636
+ case import_utils18.AST_NODE_TYPES.LogicalExpression:
2637
+ case import_utils18.AST_NODE_TYPES.ChainExpression:
2582
2638
  current = parent;
2583
2639
  parent = parent.parent;
2584
2640
  continue;
2585
- case import_utils17.AST_NODE_TYPES.IfStatement:
2586
- case import_utils17.AST_NODE_TYPES.ConditionalExpression:
2587
- case import_utils17.AST_NODE_TYPES.WhileStatement:
2588
- case import_utils17.AST_NODE_TYPES.DoWhileStatement:
2589
- case import_utils17.AST_NODE_TYPES.ForStatement:
2641
+ case import_utils18.AST_NODE_TYPES.IfStatement:
2642
+ case import_utils18.AST_NODE_TYPES.ConditionalExpression:
2643
+ case import_utils18.AST_NODE_TYPES.WhileStatement:
2644
+ case import_utils18.AST_NODE_TYPES.DoWhileStatement:
2645
+ case import_utils18.AST_NODE_TYPES.ForStatement:
2590
2646
  return parent.test === current;
2591
2647
  default:
2592
2648
  return false;
@@ -2596,13 +2652,13 @@ var isGuardTestPosition = (node) => {
2596
2652
  };
2597
2653
  var isUnvalidatedVariableRef = (node, scope, tracked) => {
2598
2654
  const unwrapped = unwrap(node);
2599
- if (unwrapped === null || unwrapped.type !== import_utils17.AST_NODE_TYPES.Identifier) {
2655
+ if (unwrapped === null || unwrapped.type !== import_utils18.AST_NODE_TYPES.Identifier) {
2600
2656
  return false;
2601
2657
  }
2602
2658
  const variable = findVariable2(scope, unwrapped.name);
2603
2659
  return variable !== null && tracked.has(variable);
2604
2660
  };
2605
- var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreator(
2661
+ var prefer_schema_for_api_payload_default = import_utils18.ESLintUtils.RuleCreator(
2606
2662
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2607
2663
  )({
2608
2664
  name: "prefer-schema-for-api-payload",
@@ -2633,11 +2689,11 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2633
2689
  return {
2634
2690
  VariableDeclarator(node) {
2635
2691
  const scope = context.sourceCode.getScope(node);
2636
- if (node.id.type === import_utils17.AST_NODE_TYPES.Identifier) {
2692
+ if (node.id.type === import_utils18.AST_NODE_TYPES.Identifier) {
2637
2693
  trackInitializer(node);
2638
2694
  return;
2639
2695
  }
2640
- if (node.id.type === import_utils17.AST_NODE_TYPES.ObjectPattern || node.id.type === import_utils17.AST_NODE_TYPES.ArrayPattern) {
2696
+ if (node.id.type === import_utils18.AST_NODE_TYPES.ObjectPattern || node.id.type === import_utils18.AST_NODE_TYPES.ArrayPattern) {
2641
2697
  if (isRawPayloadSource(node.init)) {
2642
2698
  context.report({ node: node.id, messageId: "unparsedJsonAccess" });
2643
2699
  return;
@@ -2649,7 +2705,7 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2649
2705
  },
2650
2706
  AssignmentExpression(node) {
2651
2707
  const scope = context.sourceCode.getScope(node);
2652
- if (node.left.type === import_utils17.AST_NODE_TYPES.Identifier) {
2708
+ if (node.left.type === import_utils18.AST_NODE_TYPES.Identifier) {
2653
2709
  const variable = findVariable2(scope, node.left.name);
2654
2710
  if (variable === null) return;
2655
2711
  if (isRawPayloadSource(node.right)) {
@@ -2659,7 +2715,7 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2659
2715
  }
2660
2716
  return;
2661
2717
  }
2662
- if (node.left.type === import_utils17.AST_NODE_TYPES.ObjectPattern || node.left.type === import_utils17.AST_NODE_TYPES.ArrayPattern) {
2718
+ if (node.left.type === import_utils18.AST_NODE_TYPES.ObjectPattern || node.left.type === import_utils18.AST_NODE_TYPES.ArrayPattern) {
2663
2719
  if (isRawPayloadSource(node.right)) {
2664
2720
  context.report({
2665
2721
  node: node.left,
@@ -2676,15 +2732,15 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2676
2732
  }
2677
2733
  },
2678
2734
  CallExpression(node) {
2679
- if (node.callee.type !== import_utils17.AST_NODE_TYPES.Identifier) return;
2735
+ if (node.callee.type !== import_utils18.AST_NODE_TYPES.Identifier) return;
2680
2736
  if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {
2681
2737
  return;
2682
2738
  }
2683
2739
  const scope = context.sourceCode.getScope(node);
2684
2740
  for (const arg of node.arguments) {
2685
- if (arg.type === import_utils17.AST_NODE_TYPES.SpreadElement) continue;
2741
+ if (arg.type === import_utils18.AST_NODE_TYPES.SpreadElement) continue;
2686
2742
  const unwrapped = unwrap(arg);
2687
- if (unwrapped === null || unwrapped.type !== import_utils17.AST_NODE_TYPES.Identifier) {
2743
+ if (unwrapped === null || unwrapped.type !== import_utils18.AST_NODE_TYPES.Identifier) {
2688
2744
  continue;
2689
2745
  }
2690
2746
  const variable = findVariable2(scope, unwrapped.name);
@@ -2697,13 +2753,13 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2697
2753
  const obj = unwrap(node.object);
2698
2754
  if (isRawPayloadSource(obj)) {
2699
2755
  const parent = node.parent;
2700
- if (parent.type === import_utils17.AST_NODE_TYPES.CallExpression && parent.callee === node && node.property.type === import_utils17.AST_NODE_TYPES.Identifier && (node.property.name === "parse" || node.property.name === "safeParse")) {
2756
+ if (parent.type === import_utils18.AST_NODE_TYPES.CallExpression && parent.callee === node && node.property.type === import_utils18.AST_NODE_TYPES.Identifier && (node.property.name === "parse" || node.property.name === "safeParse")) {
2701
2757
  return;
2702
2758
  }
2703
2759
  context.report({ node, messageId: "unparsedJsonAccess" });
2704
2760
  return;
2705
2761
  }
2706
- if (obj !== null && obj.type === import_utils17.AST_NODE_TYPES.Identifier && isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)) {
2762
+ if (obj !== null && obj.type === import_utils18.AST_NODE_TYPES.Identifier && isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)) {
2707
2763
  context.report({ node, messageId: "unparsedJsonAccess" });
2708
2764
  const variable = findVariable2(scope, obj.name);
2709
2765
  if (variable !== null) {
@@ -2716,7 +2772,7 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2716
2772
  });
2717
2773
 
2718
2774
  // src/rules/prefer-semantic-colors.ts
2719
- var import_utils18 = require("@typescript-eslint/utils");
2775
+ var import_utils19 = require("@typescript-eslint/utils");
2720
2776
  var import_fs = require("fs");
2721
2777
  var import_path = require("path");
2722
2778
 
@@ -2790,8 +2846,8 @@ var SVG_EXEMPT_COLOR_VALUES = /* @__PURE__ */ new Set([
2790
2846
  ]);
2791
2847
  function jsxElementName(node) {
2792
2848
  const name = node.openingElement.name;
2793
- if (name.type === import_utils18.AST_NODE_TYPES.JSXIdentifier) return name.name;
2794
- if (name.type === import_utils18.AST_NODE_TYPES.JSXMemberExpression && name.property.type === import_utils18.AST_NODE_TYPES.JSXIdentifier) {
2849
+ if (name.type === import_utils19.AST_NODE_TYPES.JSXIdentifier) return name.name;
2850
+ if (name.type === import_utils19.AST_NODE_TYPES.JSXMemberExpression && name.property.type === import_utils19.AST_NODE_TYPES.JSXIdentifier) {
2795
2851
  return name.property.name;
2796
2852
  }
2797
2853
  return null;
@@ -2802,7 +2858,7 @@ function isSvgLikeElementName(name) {
2802
2858
  var isInsideSvg = (node) => {
2803
2859
  let current = node.parent;
2804
2860
  while (current !== void 0 && current !== null) {
2805
- if (current.type === import_utils18.AST_NODE_TYPES.JSXElement) {
2861
+ if (current.type === import_utils19.AST_NODE_TYPES.JSXElement) {
2806
2862
  const name = jsxElementName(current);
2807
2863
  if (name !== null && isSvgLikeElementName(name)) return true;
2808
2864
  }
@@ -2813,7 +2869,7 @@ var isInsideSvg = (node) => {
2813
2869
  var isInsideIconFactoryPath = (node) => {
2814
2870
  let current = node.parent;
2815
2871
  while (current !== void 0 && current !== null) {
2816
- if (current.type === import_utils18.AST_NODE_TYPES.Property && propName(current.key) === "path" && current.parent.type === import_utils18.AST_NODE_TYPES.ObjectExpression && current.parent.parent.type === import_utils18.AST_NODE_TYPES.CallExpression && current.parent.parent.callee.type === import_utils18.AST_NODE_TYPES.Identifier && current.parent.parent.callee.name === "createIcon") {
2872
+ if (current.type === import_utils19.AST_NODE_TYPES.Property && propName(current.key) === "path" && current.parent.type === import_utils19.AST_NODE_TYPES.ObjectExpression && current.parent.parent.type === import_utils19.AST_NODE_TYPES.CallExpression && current.parent.parent.callee.type === import_utils19.AST_NODE_TYPES.Identifier && current.parent.parent.callee.name === "createIcon") {
2817
2873
  return true;
2818
2874
  }
2819
2875
  current = current.parent;
@@ -2849,11 +2905,11 @@ var hasSemanticTokenSystem = (filename) => {
2849
2905
  return false;
2850
2906
  };
2851
2907
  var propName = (key) => {
2852
- if (key.type === import_utils18.AST_NODE_TYPES.Identifier) return key.name;
2853
- if (key.type === import_utils18.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
2908
+ if (key.type === import_utils19.AST_NODE_TYPES.Identifier) return key.name;
2909
+ if (key.type === import_utils19.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
2854
2910
  return null;
2855
2911
  };
2856
- var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2912
+ var prefer_semantic_colors_default = import_utils19.ESLintUtils.RuleCreator(
2857
2913
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
2858
2914
  )({
2859
2915
  name: "prefer-semantic-colors",
@@ -2896,27 +2952,27 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2896
2952
  const checkClassNode = (node) => {
2897
2953
  if (node === null) return;
2898
2954
  switch (node.type) {
2899
- case import_utils18.AST_NODE_TYPES.Literal:
2955
+ case import_utils19.AST_NODE_TYPES.Literal:
2900
2956
  if (typeof node.value === "string") reportClasses(node.value, node);
2901
2957
  break;
2902
- case import_utils18.AST_NODE_TYPES.TemplateLiteral:
2958
+ case import_utils19.AST_NODE_TYPES.TemplateLiteral:
2903
2959
  for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? "", quasi);
2904
2960
  break;
2905
- case import_utils18.AST_NODE_TYPES.ArrayExpression:
2961
+ case import_utils19.AST_NODE_TYPES.ArrayExpression:
2906
2962
  for (const element of node.elements) {
2907
- if (element !== null && element.type !== import_utils18.AST_NODE_TYPES.SpreadElement) checkClassNode(element);
2963
+ if (element !== null && element.type !== import_utils19.AST_NODE_TYPES.SpreadElement) checkClassNode(element);
2908
2964
  }
2909
2965
  break;
2910
- case import_utils18.AST_NODE_TYPES.ObjectExpression:
2966
+ case import_utils19.AST_NODE_TYPES.ObjectExpression:
2911
2967
  for (const property of node.properties) {
2912
- if (property.type === import_utils18.AST_NODE_TYPES.Property) checkClassNode(property.value);
2968
+ if (property.type === import_utils19.AST_NODE_TYPES.Property) checkClassNode(property.value);
2913
2969
  }
2914
2970
  break;
2915
- case import_utils18.AST_NODE_TYPES.ConditionalExpression:
2971
+ case import_utils19.AST_NODE_TYPES.ConditionalExpression:
2916
2972
  checkClassNode(node.consequent);
2917
2973
  checkClassNode(node.alternate);
2918
2974
  break;
2919
- case import_utils18.AST_NODE_TYPES.LogicalExpression:
2975
+ case import_utils19.AST_NODE_TYPES.LogicalExpression:
2920
2976
  checkClassNode(node.right);
2921
2977
  break;
2922
2978
  default:
@@ -2924,29 +2980,29 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2924
2980
  }
2925
2981
  };
2926
2982
  const checkColorValueNode = (node) => {
2927
- if (node.type === import_utils18.AST_NODE_TYPES.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value)) {
2983
+ if (node.type === import_utils19.AST_NODE_TYPES.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value)) {
2928
2984
  context.report({ node, messageId: "inlineColor", data: { value: node.value } });
2929
2985
  }
2930
2986
  };
2931
2987
  return {
2932
2988
  "JSXAttribute[name.name='className']"(node) {
2933
2989
  if (node.value === null) return;
2934
- if (node.value.type === import_utils18.AST_NODE_TYPES.Literal) checkClassNode(node.value);
2935
- else if (node.value.type === import_utils18.AST_NODE_TYPES.JSXExpressionContainer) {
2936
- if (node.value.expression.type !== import_utils18.AST_NODE_TYPES.JSXEmptyExpression) {
2990
+ if (node.value.type === import_utils19.AST_NODE_TYPES.Literal) checkClassNode(node.value);
2991
+ else if (node.value.type === import_utils19.AST_NODE_TYPES.JSXExpressionContainer) {
2992
+ if (node.value.expression.type !== import_utils19.AST_NODE_TYPES.JSXEmptyExpression) {
2937
2993
  checkClassNode(node.value.expression);
2938
2994
  }
2939
2995
  }
2940
2996
  },
2941
2997
  CallExpression(node) {
2942
- if (node.callee.type === import_utils18.AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {
2998
+ if (node.callee.type === import_utils19.AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {
2943
2999
  for (const arg of node.arguments) {
2944
- if (arg.type !== import_utils18.AST_NODE_TYPES.SpreadElement) checkClassNode(arg);
3000
+ if (arg.type !== import_utils19.AST_NODE_TYPES.SpreadElement) checkClassNode(arg);
2945
3001
  }
2946
3002
  }
2947
3003
  },
2948
3004
  VariableDeclarator(node) {
2949
- if (node.id.type === import_utils18.AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {
3005
+ if (node.id.type === import_utils19.AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {
2950
3006
  checkClassNode(node.init);
2951
3007
  }
2952
3008
  },
@@ -2958,7 +3014,7 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2958
3014
  // Neutral drawing literals and anything inside an SVG defs container are
2959
3015
  // structural, not UI tokens, so they never fire.
2960
3016
  "JSXAttribute[name.name=/^(fill|stroke|color)$/]"(node) {
2961
- if (node.value?.type !== import_utils18.AST_NODE_TYPES.Literal) return;
3017
+ if (node.value?.type !== import_utils19.AST_NODE_TYPES.Literal) return;
2962
3018
  if (typeof node.value.value === "string" && SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())) {
2963
3019
  return;
2964
3020
  }
@@ -2975,7 +3031,7 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2975
3031
  });
2976
3032
 
2977
3033
  // src/rules/prefer-server-actions.ts
2978
- var import_utils19 = require("@typescript-eslint/utils");
3034
+ var import_utils20 = require("@typescript-eslint/utils");
2979
3035
  var MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "DELETE", "PATCH"]);
2980
3036
  var AXIOS_MUTATION_METHODS = /* @__PURE__ */ new Set(["post", "put", "delete", "patch"]);
2981
3037
  var SKIP_FILE_REGEX = /(?:\.test\.[jt]sx?$|\.spec\.[jt]sx?$|-(?:test|spec)\.[jt]sx?$|\/tests?\/|\/__tests__\/|\/__testfixtures__\/|\/scripts?\/|\/app\/api\/.*\/route\.[jt]sx?$|\/pages\/api\/)/;
@@ -3055,7 +3111,7 @@ function getPropertyNode(objNode, propName2) {
3055
3111
  }
3056
3112
  return null;
3057
3113
  }
3058
- var prefer_server_actions_default = import_utils19.ESLintUtils.RuleCreator(
3114
+ var prefer_server_actions_default = import_utils20.ESLintUtils.RuleCreator(
3059
3115
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3060
3116
  )({
3061
3117
  name: "prefer-server-actions",
@@ -3130,7 +3186,7 @@ var prefer_server_actions_default = import_utils19.ESLintUtils.RuleCreator(
3130
3186
  });
3131
3187
 
3132
3188
  // src/rules/prefer-shadcn.ts
3133
- var import_utils20 = require("@typescript-eslint/utils");
3189
+ var import_utils21 = require("@typescript-eslint/utils");
3134
3190
  var REPLACEMENTS = {
3135
3191
  select: "Select",
3136
3192
  textarea: "Textarea",
@@ -3145,10 +3201,10 @@ var SKIPPED_INPUT_TYPES = /* @__PURE__ */ new Set(["file", "hidden"]);
3145
3201
  var kebabCase = (component) => component.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
3146
3202
  var literalTypeAttr = (node) => {
3147
3203
  for (const attribute of node.attributes) {
3148
- if (attribute.type !== import_utils20.AST_NODE_TYPES.JSXAttribute || attribute.name.type !== import_utils20.AST_NODE_TYPES.JSXIdentifier || attribute.name.name !== "type") {
3204
+ if (attribute.type !== import_utils21.AST_NODE_TYPES.JSXAttribute || attribute.name.type !== import_utils21.AST_NODE_TYPES.JSXIdentifier || attribute.name.name !== "type") {
3149
3205
  continue;
3150
3206
  }
3151
- if (attribute.value?.type === import_utils20.AST_NODE_TYPES.Literal && typeof attribute.value.value === "string") {
3207
+ if (attribute.value?.type === import_utils21.AST_NODE_TYPES.Literal && typeof attribute.value.value === "string") {
3152
3208
  return { kind: "literal", value: attribute.value.value.toLowerCase() };
3153
3209
  }
3154
3210
  return { kind: "dynamic" };
@@ -3156,7 +3212,7 @@ var literalTypeAttr = (node) => {
3156
3212
  return null;
3157
3213
  };
3158
3214
  var hasFileAcceptAttr = (node) => node.attributes.some(
3159
- (attribute) => attribute.type === import_utils20.AST_NODE_TYPES.JSXAttribute && attribute.name.type === import_utils20.AST_NODE_TYPES.JSXIdentifier && attribute.name.name === "accept"
3215
+ (attribute) => attribute.type === import_utils21.AST_NODE_TYPES.JSXAttribute && attribute.name.type === import_utils21.AST_NODE_TYPES.JSXIdentifier && attribute.name.name === "accept"
3160
3216
  );
3161
3217
  var resolveInputReplacement = (node) => {
3162
3218
  const typeAttr = literalTypeAttr(node);
@@ -3165,7 +3221,7 @@ var resolveInputReplacement = (node) => {
3165
3221
  if (SKIPPED_INPUT_TYPES.has(typeAttr.value)) return null;
3166
3222
  return INPUT_TYPE_REPLACEMENTS[typeAttr.value] ?? "Input";
3167
3223
  };
3168
- var prefer_shadcn_default = import_utils20.ESLintUtils.RuleCreator(
3224
+ var prefer_shadcn_default = import_utils21.ESLintUtils.RuleCreator(
3169
3225
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3170
3226
  )({
3171
3227
  name: "prefer-shadcn",
@@ -3209,36 +3265,36 @@ var prefer_shadcn_default = import_utils20.ESLintUtils.RuleCreator(
3209
3265
  });
3210
3266
 
3211
3267
  // src/rules/require-assert-never.ts
3212
- var import_utils21 = require("@typescript-eslint/utils");
3268
+ var import_utils22 = require("@typescript-eslint/utils");
3213
3269
  var isAssertNeverCall = (expression) => {
3214
- if (expression.type !== import_utils21.AST_NODE_TYPES.CallExpression) return false;
3270
+ if (expression.type !== import_utils22.AST_NODE_TYPES.CallExpression) return false;
3215
3271
  const callee = expression.callee;
3216
- if (callee.type === import_utils21.AST_NODE_TYPES.Identifier) {
3272
+ if (callee.type === import_utils22.AST_NODE_TYPES.Identifier) {
3217
3273
  return callee.name === "assertNever";
3218
3274
  }
3219
- if (callee.type === import_utils21.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils21.AST_NODE_TYPES.Identifier) {
3275
+ if (callee.type === import_utils22.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils22.AST_NODE_TYPES.Identifier) {
3220
3276
  return callee.property.name === "assertNever";
3221
3277
  }
3222
3278
  return false;
3223
3279
  };
3224
3280
  var statementContainsAssertNever = (statement) => {
3225
- if (statement.type === import_utils21.AST_NODE_TYPES.ExpressionStatement) {
3281
+ if (statement.type === import_utils22.AST_NODE_TYPES.ExpressionStatement) {
3226
3282
  return isAssertNeverCall(statement.expression);
3227
3283
  }
3228
- if (statement.type === import_utils21.AST_NODE_TYPES.ThrowStatement) {
3284
+ if (statement.type === import_utils22.AST_NODE_TYPES.ThrowStatement) {
3229
3285
  return isAssertNeverCall(statement.argument);
3230
3286
  }
3231
- if (statement.type === import_utils21.AST_NODE_TYPES.ReturnStatement) {
3287
+ if (statement.type === import_utils22.AST_NODE_TYPES.ReturnStatement) {
3232
3288
  return statement.argument !== null && isAssertNeverCall(statement.argument);
3233
3289
  }
3234
- if (statement.type === import_utils21.AST_NODE_TYPES.BlockStatement) {
3290
+ if (statement.type === import_utils22.AST_NODE_TYPES.BlockStatement) {
3235
3291
  return statement.body.some(statementContainsAssertNever);
3236
3292
  }
3237
3293
  return false;
3238
3294
  };
3239
3295
  var isRuntimeHandlingStatement = (statement) => {
3240
- if (statement.type === import_utils21.AST_NODE_TYPES.EmptyStatement) return false;
3241
- if (statement.type === import_utils21.AST_NODE_TYPES.BlockStatement) {
3296
+ if (statement.type === import_utils22.AST_NODE_TYPES.EmptyStatement) return false;
3297
+ if (statement.type === import_utils22.AST_NODE_TYPES.BlockStatement) {
3242
3298
  return statement.body.some(isRuntimeHandlingStatement);
3243
3299
  }
3244
3300
  return true;
@@ -3254,12 +3310,12 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
3254
3310
  return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
3255
3311
  }
3256
3312
  const only = defaultCase.consequent[0];
3257
- if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === import_utils21.AST_NODE_TYPES.BlockStatement && only.body.length === 0) {
3313
+ if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === import_utils22.AST_NODE_TYPES.BlockStatement && only.body.length === 0) {
3258
3314
  return sourceCode.getCommentsInside(only).length > 0;
3259
3315
  }
3260
3316
  return false;
3261
3317
  };
3262
- var require_assert_never_default = import_utils21.ESLintUtils.RuleCreator(
3318
+ var require_assert_never_default = import_utils22.ESLintUtils.RuleCreator(
3263
3319
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3264
3320
  )({
3265
3321
  name: "require-assert-never",
@@ -3297,7 +3353,7 @@ var require_assert_never_default = import_utils21.ESLintUtils.RuleCreator(
3297
3353
  });
3298
3354
 
3299
3355
  // src/rules/require-zod-form-validation.ts
3300
- var import_utils22 = require("@typescript-eslint/utils");
3356
+ var import_utils23 = require("@typescript-eslint/utils");
3301
3357
 
3302
3358
  // src/rules/_zod.ts
3303
3359
  var ZOD_PREFIX_RE = /^Z[A-Z]/;
@@ -3308,14 +3364,14 @@ var ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;
3308
3364
  var looksLikeZodSchema = (node) => {
3309
3365
  let current = node;
3310
3366
  while (true) {
3311
- if (current.type === import_utils22.AST_NODE_TYPES.Identifier) {
3367
+ if (current.type === import_utils23.AST_NODE_TYPES.Identifier) {
3312
3368
  return current.name === "z" || ZOD_SCHEMA_NAME_RE.test(current.name);
3313
3369
  }
3314
- if (current.type === import_utils22.AST_NODE_TYPES.CallExpression) {
3370
+ if (current.type === import_utils23.AST_NODE_TYPES.CallExpression) {
3315
3371
  current = current.callee;
3316
3372
  continue;
3317
3373
  }
3318
- if (current.type === import_utils22.AST_NODE_TYPES.MemberExpression) {
3374
+ if (current.type === import_utils23.AST_NODE_TYPES.MemberExpression) {
3319
3375
  current = current.object;
3320
3376
  continue;
3321
3377
  }
@@ -3323,25 +3379,25 @@ var looksLikeZodSchema = (node) => {
3323
3379
  }
3324
3380
  };
3325
3381
  var isZodParseCall = (node) => {
3326
- if (node.type !== import_utils22.AST_NODE_TYPES.CallExpression) return false;
3382
+ if (node.type !== import_utils23.AST_NODE_TYPES.CallExpression) return false;
3327
3383
  const callee = node.callee;
3328
- if (callee.type !== import_utils22.AST_NODE_TYPES.MemberExpression) return false;
3384
+ if (callee.type !== import_utils23.AST_NODE_TYPES.MemberExpression) return false;
3329
3385
  if (callee.computed) return false;
3330
- if (callee.property.type !== import_utils22.AST_NODE_TYPES.Identifier) return false;
3386
+ if (callee.property.type !== import_utils23.AST_NODE_TYPES.Identifier) return false;
3331
3387
  const method = callee.property.name;
3332
3388
  if (method !== "parse" && method !== "safeParse") return false;
3333
3389
  return looksLikeZodSchema(callee.object);
3334
3390
  };
3335
3391
  var isFormDataMethodCall = (node) => {
3336
3392
  let current = node;
3337
- if (current.type === import_utils22.AST_NODE_TYPES.AwaitExpression) {
3393
+ if (current.type === import_utils23.AST_NODE_TYPES.AwaitExpression) {
3338
3394
  current = current.argument;
3339
3395
  }
3340
- if (current.type !== import_utils22.AST_NODE_TYPES.CallExpression) return false;
3396
+ if (current.type !== import_utils23.AST_NODE_TYPES.CallExpression) return false;
3341
3397
  const callee = current.callee;
3342
- return callee.type === import_utils22.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils22.AST_NODE_TYPES.Identifier && callee.property.name === "formData";
3398
+ return callee.type === import_utils23.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils23.AST_NODE_TYPES.Identifier && callee.property.name === "formData";
3343
3399
  };
3344
- var require_zod_form_validation_default = import_utils22.ESLintUtils.RuleCreator(
3400
+ var require_zod_form_validation_default = import_utils23.ESLintUtils.RuleCreator(
3345
3401
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3346
3402
  )({
3347
3403
  name: "require-zod-form-validation",
@@ -3361,14 +3417,14 @@ var require_zod_form_validation_default = import_utils22.ESLintUtils.RuleCreator
3361
3417
  return {};
3362
3418
  }
3363
3419
  const isFormSourceIdentifier = (node) => {
3364
- if (node.type !== import_utils22.AST_NODE_TYPES.Identifier) return false;
3420
+ if (node.type !== import_utils23.AST_NODE_TYPES.Identifier) return false;
3365
3421
  if (/formdata/i.test(node.name)) return true;
3366
3422
  let scope = context.sourceCode.getScope(node);
3367
3423
  while (scope !== null) {
3368
3424
  const variable = scope.set.get(node.name);
3369
3425
  if (variable !== void 0 && variable.defs.length === 1) {
3370
3426
  const def = variable.defs[0];
3371
- if (def !== void 0 && def.type === "Variable" && def.node.type === import_utils22.AST_NODE_TYPES.VariableDeclarator && def.node.init !== null) {
3427
+ if (def !== void 0 && def.type === "Variable" && def.node.type === import_utils23.AST_NODE_TYPES.VariableDeclarator && def.node.init !== null) {
3372
3428
  return isFormDataMethodCall(def.node.init);
3373
3429
  }
3374
3430
  return false;
@@ -3379,8 +3435,8 @@ var require_zod_form_validation_default = import_utils22.ESLintUtils.RuleCreator
3379
3435
  };
3380
3436
  const isFormDataGetCall = (node) => {
3381
3437
  const callee = node.callee;
3382
- if (callee.type !== import_utils22.AST_NODE_TYPES.MemberExpression) return false;
3383
- if (callee.property.type !== import_utils22.AST_NODE_TYPES.Identifier || callee.property.name !== "get") {
3438
+ if (callee.type !== import_utils23.AST_NODE_TYPES.MemberExpression) return false;
3439
+ if (callee.property.type !== import_utils23.AST_NODE_TYPES.Identifier || callee.property.name !== "get") {
3384
3440
  return false;
3385
3441
  }
3386
3442
  return isFormSourceIdentifier(callee.object);
@@ -3395,11 +3451,11 @@ var require_zod_form_validation_default = import_utils22.ESLintUtils.RuleCreator
3395
3451
  };
3396
3452
  const isInstanceofNarrowing = (node) => {
3397
3453
  const parent = node.parent;
3398
- return parent !== null && parent !== void 0 && parent.type === import_utils22.AST_NODE_TYPES.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3454
+ return parent !== null && parent !== void 0 && parent.type === import_utils23.AST_NODE_TYPES.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3399
3455
  };
3400
3456
  const boundDeclarator = (node) => {
3401
3457
  const parent = node.parent;
3402
- if (parent.type === import_utils22.AST_NODE_TYPES.VariableDeclarator && parent.init === node && parent.id.type === import_utils22.AST_NODE_TYPES.Identifier) {
3458
+ if (parent.type === import_utils23.AST_NODE_TYPES.VariableDeclarator && parent.init === node && parent.id.type === import_utils23.AST_NODE_TYPES.Identifier) {
3403
3459
  return parent;
3404
3460
  }
3405
3461
  return null;
@@ -3427,7 +3483,7 @@ var require_zod_form_validation_default = import_utils22.ESLintUtils.RuleCreator
3427
3483
  });
3428
3484
 
3429
3485
  // src/rules/zod-naming-convention.ts
3430
- var import_utils23 = require("@typescript-eslint/utils");
3486
+ var import_utils24 = require("@typescript-eslint/utils");
3431
3487
  var CONVENTIONS = {
3432
3488
  prefix: { test: ZOD_PREFIX_RE, messageId: "zPrefix" },
3433
3489
  suffix: { test: ZOD_SUFFIX_RE, messageId: "schemaSuffix" },
@@ -3451,15 +3507,15 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
3451
3507
  "registry",
3452
3508
  "implement"
3453
3509
  ]);
3454
- var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils23.AST_NODE_TYPES.Identifier ? callee.property.name : null;
3510
+ var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils24.AST_NODE_TYPES.Identifier ? callee.property.name : null;
3455
3511
  var calleeChainStartsWithZ = (node) => {
3456
3512
  let current = node;
3457
- while (current.type === import_utils23.AST_NODE_TYPES.MemberExpression) {
3513
+ while (current.type === import_utils24.AST_NODE_TYPES.MemberExpression) {
3458
3514
  const receiver = current.object;
3459
- if (receiver.type === import_utils23.AST_NODE_TYPES.Identifier && receiver.name === "z") {
3515
+ if (receiver.type === import_utils24.AST_NODE_TYPES.Identifier && receiver.name === "z") {
3460
3516
  return true;
3461
3517
  }
3462
- if (receiver.type === import_utils23.AST_NODE_TYPES.CallExpression) {
3518
+ if (receiver.type === import_utils24.AST_NODE_TYPES.CallExpression) {
3463
3519
  current = receiver.callee;
3464
3520
  continue;
3465
3521
  }
@@ -3467,7 +3523,7 @@ var calleeChainStartsWithZ = (node) => {
3467
3523
  }
3468
3524
  return false;
3469
3525
  };
3470
- var zod_naming_convention_default = import_utils23.ESLintUtils.RuleCreator(
3526
+ var zod_naming_convention_default = import_utils24.ESLintUtils.RuleCreator(
3471
3527
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3472
3528
  )({
3473
3529
  name: "zod-naming-convention",
@@ -3506,13 +3562,13 @@ var zod_naming_convention_default = import_utils23.ESLintUtils.RuleCreator(
3506
3562
  VariableDeclarator(node) {
3507
3563
  const init = node.init;
3508
3564
  if (init === null || init === void 0) return;
3509
- if (init.type !== import_utils23.AST_NODE_TYPES.CallExpression) return;
3565
+ if (init.type !== import_utils24.AST_NODE_TYPES.CallExpression) return;
3510
3566
  const callee = init.callee;
3511
- if (callee.type !== import_utils23.AST_NODE_TYPES.MemberExpression) return;
3567
+ if (callee.type !== import_utils24.AST_NODE_TYPES.MemberExpression) return;
3512
3568
  if (!calleeChainStartsWithZ(callee)) return;
3513
3569
  const terminal = terminalMethodName(callee);
3514
3570
  if (terminal !== null && NON_SCHEMA_TERMINALS.has(terminal)) return;
3515
- if (node.id.type !== import_utils23.AST_NODE_TYPES.Identifier) return;
3571
+ if (node.id.type !== import_utils24.AST_NODE_TYPES.Identifier) return;
3516
3572
  if (test.test(node.id.name)) return;
3517
3573
  if (acceptsSchemaWord && CONTAINS_SCHEMA_RE.test(node.id.name)) return;
3518
3574
  context.report({
@@ -3525,7 +3581,7 @@ var zod_naming_convention_default = import_utils23.ESLintUtils.RuleCreator(
3525
3581
  });
3526
3582
 
3527
3583
  // src/rules/no-cors-wildcard-with-credentials.ts
3528
- var import_utils24 = require("@typescript-eslint/utils");
3584
+ var import_utils25 = require("@typescript-eslint/utils");
3529
3585
  var ACAO_HEADER = "access-control-allow-origin";
3530
3586
  var ACAC_HEADER = "access-control-allow-credentials";
3531
3587
  var HEADER_SET_METHODS = /* @__PURE__ */ new Set(["setheader", "set", "append"]);
@@ -3667,7 +3723,7 @@ function enclosingScope(node) {
3667
3723
  }
3668
3724
  return void 0;
3669
3725
  }
3670
- var no_cors_wildcard_with_credentials_default = import_utils24.ESLintUtils.RuleCreator(
3726
+ var no_cors_wildcard_with_credentials_default = import_utils25.ESLintUtils.RuleCreator(
3671
3727
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3672
3728
  )({
3673
3729
  name: "no-cors-wildcard-with-credentials",
@@ -3735,9 +3791,9 @@ var no_cors_wildcard_with_credentials_default = import_utils24.ESLintUtils.RuleC
3735
3791
  });
3736
3792
 
3737
3793
  // src/rules/no-silent-promise-catch.ts
3738
- var import_utils25 = require("@typescript-eslint/utils");
3794
+ var import_utils26 = require("@typescript-eslint/utils");
3739
3795
  function isBodyParseCall(node) {
3740
- return node.type === import_utils25.AST_NODE_TYPES.CallExpression && node.arguments.length === 0 && node.callee.type === import_utils25.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils25.AST_NODE_TYPES.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3796
+ return node.type === import_utils26.AST_NODE_TYPES.CallExpression && node.arguments.length === 0 && node.callee.type === import_utils26.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils26.AST_NODE_TYPES.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3741
3797
  }
3742
3798
  var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3743
3799
  "cancel",
@@ -3752,21 +3808,21 @@ var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3752
3808
  var DIRECTIVE_COMMENT_RE = /^\s*(eslint-|@ts-|prettier-ignore|biome-ignore|c8 |v8 |istanbul )/;
3753
3809
  var isExplanatory = (comment) => !DIRECTIVE_COMMENT_RE.test(comment.value);
3754
3810
  function isTeardownCall(node) {
3755
- return node.type === import_utils25.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils25.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils25.AST_NODE_TYPES.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3811
+ return node.type === import_utils26.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils26.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils26.AST_NODE_TYPES.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3756
3812
  }
3757
3813
  function isSilentExpression(node) {
3758
3814
  switch (node.type) {
3759
- case import_utils25.AST_NODE_TYPES.Literal:
3815
+ case import_utils26.AST_NODE_TYPES.Literal:
3760
3816
  return !("regex" in node);
3761
- case import_utils25.AST_NODE_TYPES.Identifier:
3817
+ case import_utils26.AST_NODE_TYPES.Identifier:
3762
3818
  return node.name === "undefined";
3763
- case import_utils25.AST_NODE_TYPES.UnaryExpression:
3764
- return node.operator === "void" && node.argument.type === import_utils25.AST_NODE_TYPES.Literal;
3765
- case import_utils25.AST_NODE_TYPES.ObjectExpression:
3819
+ case import_utils26.AST_NODE_TYPES.UnaryExpression:
3820
+ return node.operator === "void" && node.argument.type === import_utils26.AST_NODE_TYPES.Literal;
3821
+ case import_utils26.AST_NODE_TYPES.ObjectExpression:
3766
3822
  return node.properties.length === 0;
3767
- case import_utils25.AST_NODE_TYPES.ArrayExpression:
3823
+ case import_utils26.AST_NODE_TYPES.ArrayExpression:
3768
3824
  return node.elements.length === 0;
3769
- case import_utils25.AST_NODE_TYPES.TSAsExpression:
3825
+ case import_utils26.AST_NODE_TYPES.TSAsExpression:
3770
3826
  return isSilentExpression(node.expression);
3771
3827
  default:
3772
3828
  return false;
@@ -3774,7 +3830,7 @@ function isSilentExpression(node) {
3774
3830
  }
3775
3831
  function isSilentHandler(handler) {
3776
3832
  const body = handler.body;
3777
- if (body.type !== import_utils25.AST_NODE_TYPES.BlockStatement) {
3833
+ if (body.type !== import_utils26.AST_NODE_TYPES.BlockStatement) {
3778
3834
  return isSilentExpression(body);
3779
3835
  }
3780
3836
  if (body.body.length === 0) {
@@ -3782,13 +3838,13 @@ function isSilentHandler(handler) {
3782
3838
  }
3783
3839
  if (body.body.length === 1) {
3784
3840
  const only = body.body[0];
3785
- if (only !== void 0 && only.type === import_utils25.AST_NODE_TYPES.ReturnStatement) {
3841
+ if (only !== void 0 && only.type === import_utils26.AST_NODE_TYPES.ReturnStatement) {
3786
3842
  return only.argument === null || isSilentExpression(only.argument);
3787
3843
  }
3788
3844
  }
3789
3845
  return false;
3790
3846
  }
3791
- var no_silent_promise_catch_default = import_utils25.ESLintUtils.RuleCreator(
3847
+ var no_silent_promise_catch_default = import_utils26.ESLintUtils.RuleCreator(
3792
3848
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3793
3849
  )({
3794
3850
  name: "no-silent-promise-catch",
@@ -3813,7 +3869,7 @@ var no_silent_promise_catch_default = import_utils25.ESLintUtils.RuleCreator(
3813
3869
  return true;
3814
3870
  }
3815
3871
  let statement = call;
3816
- while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== import_utils25.AST_NODE_TYPES.VariableDeclaration) {
3872
+ while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== import_utils26.AST_NODE_TYPES.VariableDeclaration) {
3817
3873
  statement = statement.parent;
3818
3874
  }
3819
3875
  if (sourceCode.getCommentsBefore(statement).some(isExplanatory)) {
@@ -3825,7 +3881,7 @@ var no_silent_promise_catch_default = import_utils25.ESLintUtils.RuleCreator(
3825
3881
  };
3826
3882
  return {
3827
3883
  CallExpression(node) {
3828
- if (node.callee.type !== import_utils25.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.property.type !== import_utils25.AST_NODE_TYPES.Identifier || node.callee.property.name !== "catch") {
3884
+ if (node.callee.type !== import_utils26.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.property.type !== import_utils26.AST_NODE_TYPES.Identifier || node.callee.property.name !== "catch") {
3829
3885
  return;
3830
3886
  }
3831
3887
  if (isBodyParseCall(node.callee.object)) {
@@ -3834,14 +3890,14 @@ var no_silent_promise_catch_default = import_utils25.ESLintUtils.RuleCreator(
3834
3890
  if (isTeardownCall(node.callee.object)) {
3835
3891
  return;
3836
3892
  }
3837
- if (node.parent.type === import_utils25.AST_NODE_TYPES.MemberExpression && node.parent.object === node) {
3893
+ if (node.parent.type === import_utils26.AST_NODE_TYPES.MemberExpression && node.parent.object === node) {
3838
3894
  return;
3839
3895
  }
3840
3896
  if (node.arguments.length !== 1) {
3841
3897
  return;
3842
3898
  }
3843
3899
  const handler = node.arguments[0];
3844
- if (handler === void 0 || handler.type !== import_utils25.AST_NODE_TYPES.ArrowFunctionExpression && handler.type !== import_utils25.AST_NODE_TYPES.FunctionExpression) {
3900
+ if (handler === void 0 || handler.type !== import_utils26.AST_NODE_TYPES.ArrowFunctionExpression && handler.type !== import_utils26.AST_NODE_TYPES.FunctionExpression) {
3845
3901
  return;
3846
3902
  }
3847
3903
  if (hasExplanatoryComment(node, handler)) {
@@ -3856,7 +3912,7 @@ var no_silent_promise_catch_default = import_utils25.ESLintUtils.RuleCreator(
3856
3912
  });
3857
3913
 
3858
3914
  // src/rules/require-fetch-timeout.ts
3859
- var import_utils26 = require("@typescript-eslint/utils");
3915
+ var import_utils27 = require("@typescript-eslint/utils");
3860
3916
  var CODEMOD_FIXTURE_RE = /[\\/]__testfixtures__[\\/]/;
3861
3917
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
3862
3918
  "globalThis",
@@ -3873,14 +3929,14 @@ function matchesAnyPattern2(filename, patterns) {
3873
3929
  return false;
3874
3930
  }
3875
3931
  function initProvablyLacksSignal(init) {
3876
- if (init.type !== import_utils26.AST_NODE_TYPES.ObjectExpression) {
3932
+ if (init.type !== import_utils27.AST_NODE_TYPES.ObjectExpression) {
3877
3933
  return false;
3878
3934
  }
3879
3935
  for (const prop of init.properties) {
3880
- if (prop.type === import_utils26.AST_NODE_TYPES.SpreadElement) {
3936
+ if (prop.type === import_utils27.AST_NODE_TYPES.SpreadElement) {
3881
3937
  return false;
3882
3938
  }
3883
- if (prop.key.type === import_utils26.AST_NODE_TYPES.Identifier && prop.key.name === "signal" || prop.key.type === import_utils26.AST_NODE_TYPES.Literal && prop.key.value === "signal") {
3939
+ if (prop.key.type === import_utils27.AST_NODE_TYPES.Identifier && prop.key.name === "signal" || prop.key.type === import_utils27.AST_NODE_TYPES.Literal && prop.key.value === "signal") {
3884
3940
  return false;
3885
3941
  }
3886
3942
  if (prop.computed) {
@@ -3890,9 +3946,9 @@ function initProvablyLacksSignal(init) {
3890
3946
  return true;
3891
3947
  }
3892
3948
  function isStringish(node) {
3893
- return node.type === import_utils26.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils26.AST_NODE_TYPES.TemplateLiteral;
3949
+ return node.type === import_utils27.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils27.AST_NODE_TYPES.TemplateLiteral;
3894
3950
  }
3895
- var require_fetch_timeout_default = import_utils26.ESLintUtils.RuleCreator(
3951
+ var require_fetch_timeout_default = import_utils27.ESLintUtils.RuleCreator(
3896
3952
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3897
3953
  )({
3898
3954
  name: "require-fetch-timeout",
@@ -3929,14 +3985,14 @@ var require_fetch_timeout_default = import_utils26.ESLintUtils.RuleCreator(
3929
3985
  }
3930
3986
  function resolvesToGlobal(identifier) {
3931
3987
  const scope = context.sourceCode.getScope(identifier);
3932
- const variable = import_utils26.ASTUtils.findVariable(scope, identifier.name);
3988
+ const variable = import_utils27.ASTUtils.findVariable(scope, identifier.name);
3933
3989
  return variable === null || variable.defs.length === 0;
3934
3990
  }
3935
3991
  function isGlobalFetchCall2(callee) {
3936
- if (callee.type === import_utils26.AST_NODE_TYPES.Identifier) {
3992
+ if (callee.type === import_utils27.AST_NODE_TYPES.Identifier) {
3937
3993
  return callee.name === "fetch" && resolvesToGlobal(callee);
3938
3994
  }
3939
- return callee.type === import_utils26.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils26.AST_NODE_TYPES.Identifier && callee.property.name === "fetch" && callee.object.type === import_utils26.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3995
+ return callee.type === import_utils27.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils27.AST_NODE_TYPES.Identifier && callee.property.name === "fetch" && callee.object.type === import_utils27.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3940
3996
  }
3941
3997
  return {
3942
3998
  CallExpression(node) {
@@ -3956,23 +4012,23 @@ var require_fetch_timeout_default = import_utils26.ESLintUtils.RuleCreator(
3956
4012
  });
3957
4013
 
3958
4014
  // src/rules/require-schema-validate-search.ts
3959
- var import_utils27 = require("@typescript-eslint/utils");
4015
+ var import_utils28 = require("@typescript-eslint/utils");
3960
4016
  var VALIDATOR_METHODS = /* @__PURE__ */ new Set([
3961
4017
  "parse",
3962
4018
  "safeParse",
3963
4019
  "decode"
3964
4020
  ]);
3965
4021
  function isConstTypeAnnotation(typeAnnotation) {
3966
- return typeAnnotation.type === import_utils27.AST_NODE_TYPES.TSTypeReference && typeAnnotation.typeName.type === import_utils27.AST_NODE_TYPES.Identifier && typeAnnotation.typeName.name === "const";
4022
+ return typeAnnotation.type === import_utils28.AST_NODE_TYPES.TSTypeReference && typeAnnotation.typeName.type === import_utils28.AST_NODE_TYPES.Identifier && typeAnnotation.typeName.name === "const";
3967
4023
  }
3968
4024
  function isValidatorCall(node) {
3969
- return node.callee.type === import_utils27.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils27.AST_NODE_TYPES.Identifier && VALIDATOR_METHODS.has(node.callee.property.name);
4025
+ return node.callee.type === import_utils28.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils28.AST_NODE_TYPES.Identifier && VALIDATOR_METHODS.has(node.callee.property.name);
3970
4026
  }
3971
4027
  function findCastExpression(node, insideValidatorArg) {
3972
- if ((node.type === import_utils27.AST_NODE_TYPES.TSAsExpression || node.type === import_utils27.AST_NODE_TYPES.TSTypeAssertion) && !isConstTypeAnnotation(node.typeAnnotation) && !insideValidatorArg) {
4028
+ if ((node.type === import_utils28.AST_NODE_TYPES.TSAsExpression || node.type === import_utils28.AST_NODE_TYPES.TSTypeAssertion) && !isConstTypeAnnotation(node.typeAnnotation) && !insideValidatorArg) {
3973
4029
  return node;
3974
4030
  }
3975
- if (node.type === import_utils27.AST_NODE_TYPES.CallExpression && isValidatorCall(node)) {
4031
+ if (node.type === import_utils28.AST_NODE_TYPES.CallExpression && isValidatorCall(node)) {
3976
4032
  const inCallee = findCastExpression(node.callee, insideValidatorArg);
3977
4033
  if (inCallee !== null) {
3978
4034
  return inCallee;
@@ -4005,7 +4061,7 @@ function findCastExpression(node, insideValidatorArg) {
4005
4061
  }
4006
4062
  return null;
4007
4063
  }
4008
- var require_schema_validate_search_default = import_utils27.ESLintUtils.RuleCreator(
4064
+ var require_schema_validate_search_default = import_utils28.ESLintUtils.RuleCreator(
4009
4065
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4010
4066
  )({
4011
4067
  name: "require-schema-validate-search",
@@ -4026,11 +4082,11 @@ var require_schema_validate_search_default = import_utils27.ESLintUtils.RuleCrea
4026
4082
  }
4027
4083
  return {
4028
4084
  Property(node) {
4029
- const isValidateSearchKey = !node.computed && node.key.type === import_utils27.AST_NODE_TYPES.Identifier && node.key.name === "validateSearch" || node.key.type === import_utils27.AST_NODE_TYPES.Literal && node.key.value === "validateSearch";
4085
+ const isValidateSearchKey = !node.computed && node.key.type === import_utils28.AST_NODE_TYPES.Identifier && node.key.name === "validateSearch" || node.key.type === import_utils28.AST_NODE_TYPES.Literal && node.key.value === "validateSearch";
4030
4086
  if (!isValidateSearchKey) {
4031
4087
  return;
4032
4088
  }
4033
- if (node.value.type !== import_utils27.AST_NODE_TYPES.ArrowFunctionExpression && node.value.type !== import_utils27.AST_NODE_TYPES.FunctionExpression) {
4089
+ if (node.value.type !== import_utils28.AST_NODE_TYPES.ArrowFunctionExpression && node.value.type !== import_utils28.AST_NODE_TYPES.FunctionExpression) {
4034
4090
  return;
4035
4091
  }
4036
4092
  const cast = findCastExpression(node.value.body, false);
@@ -4043,12 +4099,12 @@ var require_schema_validate_search_default = import_utils27.ESLintUtils.RuleCrea
4043
4099
  });
4044
4100
 
4045
4101
  // src/rules/no-fat-try-blocks.ts
4046
- var import_utils28 = require("@typescript-eslint/utils");
4102
+ var import_utils29 = require("@typescript-eslint/utils");
4047
4103
  var MAX_TRY_BODY_STATEMENTS = 3;
4048
4104
  var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set([
4049
- import_utils28.AST_NODE_TYPES.FunctionDeclaration,
4050
- import_utils28.AST_NODE_TYPES.FunctionExpression,
4051
- import_utils28.AST_NODE_TYPES.ArrowFunctionExpression
4105
+ import_utils29.AST_NODE_TYPES.FunctionDeclaration,
4106
+ import_utils29.AST_NODE_TYPES.FunctionExpression,
4107
+ import_utils29.AST_NODE_TYPES.ArrowFunctionExpression
4052
4108
  ]);
4053
4109
  var PURE_METHODS = /* @__PURE__ */ new Set([
4054
4110
  "map",
@@ -4146,20 +4202,20 @@ function isNode4(value) {
4146
4202
  }
4147
4203
  function isPureCall(node) {
4148
4204
  const callee = node.callee;
4149
- if (callee.type !== import_utils28.AST_NODE_TYPES.MemberExpression) {
4205
+ if (callee.type !== import_utils29.AST_NODE_TYPES.MemberExpression) {
4150
4206
  return false;
4151
4207
  }
4152
4208
  const property = callee.property;
4153
- if (property.type !== import_utils28.AST_NODE_TYPES.Identifier) {
4209
+ if (property.type !== import_utils29.AST_NODE_TYPES.Identifier) {
4154
4210
  return false;
4155
4211
  }
4156
- if (callee.object.type === import_utils28.AST_NODE_TYPES.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
4212
+ if (callee.object.type === import_utils29.AST_NODE_TYPES.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
4157
4213
  return true;
4158
4214
  }
4159
4215
  return PURE_METHODS.has(property.name);
4160
4216
  }
4161
4217
  function isPureNew(node) {
4162
- return node.callee.type === import_utils28.AST_NODE_TYPES.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
4218
+ return node.callee.type === import_utils29.AST_NODE_TYPES.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
4163
4219
  }
4164
4220
  function subtreeMatches(stmt, predicate) {
4165
4221
  let found = false;
@@ -4196,20 +4252,20 @@ function subtreeMatches(stmt, predicate) {
4196
4252
  visit(stmt);
4197
4253
  return found;
4198
4254
  }
4199
- var hasAwait = (node) => subtreeMatches(node, (n) => n.type === import_utils28.AST_NODE_TYPES.AwaitExpression);
4255
+ var hasAwait = (node) => subtreeMatches(node, (n) => n.type === import_utils29.AST_NODE_TYPES.AwaitExpression);
4200
4256
  var hasThrowingCallOrNew = (node) => subtreeMatches(
4201
4257
  node,
4202
- (n) => n.type === import_utils28.AST_NODE_TYPES.CallExpression && !isPureCall(n) || n.type === import_utils28.AST_NODE_TYPES.NewExpression && !isPureNew(n)
4258
+ (n) => n.type === import_utils29.AST_NODE_TYPES.CallExpression && !isPureCall(n) || n.type === import_utils29.AST_NODE_TYPES.NewExpression && !isPureNew(n)
4203
4259
  );
4204
4260
  function unwrap2(expr) {
4205
4261
  let current = expr;
4206
- while (current.type === import_utils28.AST_NODE_TYPES.ChainExpression || current.type === import_utils28.AST_NODE_TYPES.TSNonNullExpression) {
4262
+ while (current.type === import_utils29.AST_NODE_TYPES.ChainExpression || current.type === import_utils29.AST_NODE_TYPES.TSNonNullExpression) {
4207
4263
  current = current.expression;
4208
4264
  }
4209
4265
  return current;
4210
4266
  }
4211
4267
  function isBareCallStatement(stmt) {
4212
- return stmt.type === import_utils28.AST_NODE_TYPES.ExpressionStatement && unwrap2(stmt.expression).type === import_utils28.AST_NODE_TYPES.CallExpression;
4268
+ return stmt.type === import_utils29.AST_NODE_TYPES.ExpressionStatement && unwrap2(stmt.expression).type === import_utils29.AST_NODE_TYPES.CallExpression;
4213
4269
  }
4214
4270
  function canThrow(stmt) {
4215
4271
  if (hasAwait(stmt)) {
@@ -4218,10 +4274,10 @@ function canThrow(stmt) {
4218
4274
  if (isBareCallStatement(stmt)) {
4219
4275
  return false;
4220
4276
  }
4221
- if (stmt.type === import_utils28.AST_NODE_TYPES.BlockStatement) {
4277
+ if (stmt.type === import_utils29.AST_NODE_TYPES.BlockStatement) {
4222
4278
  return stmt.body.some(canThrow);
4223
4279
  }
4224
- if (stmt.type === import_utils28.AST_NODE_TYPES.IfStatement) {
4280
+ if (stmt.type === import_utils29.AST_NODE_TYPES.IfStatement) {
4225
4281
  return hasThrowingCallOrNew(stmt.test) || canThrow(stmt.consequent) || stmt.alternate !== null && canThrow(stmt.alternate);
4226
4282
  }
4227
4283
  return hasThrowingCallOrNew(stmt);
@@ -4232,9 +4288,9 @@ function handlerRethrows(handler) {
4232
4288
  }
4233
4289
  const body = handler.body.body;
4234
4290
  const last = body[body.length - 1];
4235
- return last !== void 0 && last.type === import_utils28.AST_NODE_TYPES.ThrowStatement;
4291
+ return last !== void 0 && last.type === import_utils29.AST_NODE_TYPES.ThrowStatement;
4236
4292
  }
4237
- var no_fat_try_blocks_default = import_utils28.ESLintUtils.RuleCreator(
4293
+ var no_fat_try_blocks_default = import_utils29.ESLintUtils.RuleCreator(
4238
4294
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4239
4295
  )({
4240
4296
  name: "no-fat-try-blocks",
@@ -4278,7 +4334,7 @@ var no_fat_try_blocks_default = import_utils28.ESLintUtils.RuleCreator(
4278
4334
  });
4279
4335
 
4280
4336
  // src/rules/no-secret-in-log.ts
4281
- var import_utils29 = require("@typescript-eslint/utils");
4337
+ var import_utils30 = require("@typescript-eslint/utils");
4282
4338
 
4283
4339
  // src/rules/_secret_names.ts
4284
4340
  var SECRET_WORDS = /* @__PURE__ */ new Set([
@@ -4540,7 +4596,7 @@ function propertyKeyName2(prop) {
4540
4596
  }
4541
4597
  return null;
4542
4598
  }
4543
- var no_secret_in_log_default = import_utils29.ESLintUtils.RuleCreator(
4599
+ var no_secret_in_log_default = import_utils30.ESLintUtils.RuleCreator(
4544
4600
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4545
4601
  )({
4546
4602
  name: "no-secret-in-log",
@@ -4617,15 +4673,15 @@ var no_secret_in_log_default = import_utils29.ESLintUtils.RuleCreator(
4617
4673
  });
4618
4674
 
4619
4675
  // src/rules/no-unsafe-cast.ts
4620
- var import_utils30 = require("@typescript-eslint/utils");
4621
4676
  var import_utils31 = require("@typescript-eslint/utils");
4677
+ var import_utils32 = require("@typescript-eslint/utils");
4622
4678
  function isAnyAnnotation(node) {
4623
- return node.type === import_utils31.AST_NODE_TYPES.TSAnyKeyword;
4679
+ return node.type === import_utils32.AST_NODE_TYPES.TSAnyKeyword;
4624
4680
  }
4625
4681
  function isConstAssertion(typeAnnotation) {
4626
- return typeAnnotation.type === import_utils31.AST_NODE_TYPES.TSTypeReference && typeAnnotation.typeName.type === import_utils31.AST_NODE_TYPES.Identifier && typeAnnotation.typeName.name === "const";
4682
+ return typeAnnotation.type === import_utils32.AST_NODE_TYPES.TSTypeReference && typeAnnotation.typeName.type === import_utils32.AST_NODE_TYPES.Identifier && typeAnnotation.typeName.name === "const";
4627
4683
  }
4628
- var no_unsafe_cast_default = import_utils30.ESLintUtils.RuleCreator(
4684
+ var no_unsafe_cast_default = import_utils31.ESLintUtils.RuleCreator(
4629
4685
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4630
4686
  )({
4631
4687
  name: "no-unsafe-cast",
@@ -4654,7 +4710,7 @@ var no_unsafe_cast_default = import_utils30.ESLintUtils.RuleCreator(
4654
4710
  return;
4655
4711
  }
4656
4712
  const inner = node.expression;
4657
- if (inner.type === import_utils31.AST_NODE_TYPES.TSAsExpression || inner.type === import_utils31.AST_NODE_TYPES.TSTypeAssertion) {
4713
+ if (inner.type === import_utils32.AST_NODE_TYPES.TSAsExpression || inner.type === import_utils32.AST_NODE_TYPES.TSTypeAssertion) {
4658
4714
  context.report({ node, messageId: "doubleCast" });
4659
4715
  }
4660
4716
  }
@@ -4665,8 +4721,57 @@ var no_unsafe_cast_default = import_utils30.ESLintUtils.RuleCreator(
4665
4721
  }
4666
4722
  });
4667
4723
 
4724
+ // src/rules/no-unsafe-mock-casting.ts
4725
+ var import_utils33 = require("@typescript-eslint/utils");
4726
+ var import_utils34 = require("@typescript-eslint/utils");
4727
+ function isMockTypeReference(node) {
4728
+ if (node.type !== import_utils34.AST_NODE_TYPES.TSTypeReference) {
4729
+ return false;
4730
+ }
4731
+ const typeName = node.typeName;
4732
+ if (typeName.type === import_utils34.AST_NODE_TYPES.Identifier) {
4733
+ const name = typeName.name;
4734
+ return name === "Mock" || name === "MockInstance" || name === "SpyInstance";
4735
+ }
4736
+ if (typeName.type === import_utils34.AST_NODE_TYPES.TSQualifiedName) {
4737
+ const rightName = typeName.right.name;
4738
+ return rightName === "Mock" || rightName === "MockInstance" || rightName === "SpyInstance";
4739
+ }
4740
+ return false;
4741
+ }
4742
+ var no_unsafe_mock_casting_default = import_utils33.ESLintUtils.RuleCreator(
4743
+ (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4744
+ )({
4745
+ name: "no-unsafe-mock-casting",
4746
+ meta: {
4747
+ type: "problem",
4748
+ docs: {
4749
+ description: "Disallow casting to mock types like `jest.Mock` or `vi.Mock`. Use `vi.mocked()` or `jest.mocked()` instead."
4750
+ },
4751
+ schema: [],
4752
+ messages: {
4753
+ unsafeMockCast: "Do not cast to a Mock type. Use `vi.mocked(fn)` or `jest.mocked(fn)` instead to preserve type safety."
4754
+ }
4755
+ },
4756
+ defaultOptions: [],
4757
+ create(context) {
4758
+ if (isGeneratedFile(context.filename, context.sourceCode.text)) {
4759
+ return {};
4760
+ }
4761
+ function checkAssertion(node) {
4762
+ if (isMockTypeReference(node.typeAnnotation)) {
4763
+ context.report({ node, messageId: "unsafeMockCast" });
4764
+ }
4765
+ }
4766
+ return {
4767
+ TSAsExpression: checkAssertion,
4768
+ TSTypeAssertion: checkAssertion
4769
+ };
4770
+ }
4771
+ });
4772
+
4668
4773
  // src/rules/prefer-string-literal-union.ts
4669
- var import_utils32 = require("@typescript-eslint/utils");
4774
+ var import_utils35 = require("@typescript-eslint/utils");
4670
4775
  var ts = __toESM(require("typescript"), 1);
4671
4776
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
4672
4777
  "status",
@@ -4709,19 +4814,19 @@ function isChoiceLikeName(name) {
4709
4814
  return CHOICE_TOKENS.has(lastWord(name));
4710
4815
  }
4711
4816
  function keyName(key) {
4712
- if (key.type === import_utils32.AST_NODE_TYPES.Identifier) {
4817
+ if (key.type === import_utils35.AST_NODE_TYPES.Identifier) {
4713
4818
  return key.name;
4714
4819
  }
4715
- if (key.type === import_utils32.AST_NODE_TYPES.Literal && typeof key.value === "string") {
4820
+ if (key.type === import_utils35.AST_NODE_TYPES.Literal && typeof key.value === "string") {
4716
4821
  return key.value;
4717
4822
  }
4718
4823
  return null;
4719
4824
  }
4720
4825
  function isStringLiteralMember(t) {
4721
- return t.type === import_utils32.AST_NODE_TYPES.TSLiteralType && t.literal.type === import_utils32.AST_NODE_TYPES.Literal && typeof t.literal.value === "string";
4826
+ return t.type === import_utils35.AST_NODE_TYPES.TSLiteralType && t.literal.type === import_utils35.AST_NODE_TYPES.Literal && typeof t.literal.value === "string";
4722
4827
  }
4723
4828
  function isStringLiteralUnion(node) {
4724
- if (node?.type !== import_utils32.AST_NODE_TYPES.TSUnionType) {
4829
+ if (node?.type !== import_utils35.AST_NODE_TYPES.TSUnionType) {
4725
4830
  return false;
4726
4831
  }
4727
4832
  return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
@@ -4750,12 +4855,12 @@ function bindingSourceExpression(decl) {
4750
4855
  return ts.isForOfStatement(node) ? node.expression : node.initializer;
4751
4856
  }
4752
4857
  function refKey(node) {
4753
- if (node.type === import_utils32.AST_NODE_TYPES.Identifier) {
4858
+ if (node.type === import_utils35.AST_NODE_TYPES.Identifier) {
4754
4859
  return node.name;
4755
4860
  }
4756
- if (node.type === import_utils32.AST_NODE_TYPES.MemberExpression && !node.computed) {
4861
+ if (node.type === import_utils35.AST_NODE_TYPES.MemberExpression && !node.computed) {
4757
4862
  const inner = refKey(node.object);
4758
- if (inner === null || node.property.type !== import_utils32.AST_NODE_TYPES.Identifier) {
4863
+ if (inner === null || node.property.type !== import_utils35.AST_NODE_TYPES.Identifier) {
4759
4864
  return null;
4760
4865
  }
4761
4866
  return `${inner}.${node.property.name}`;
@@ -4763,12 +4868,12 @@ function refKey(node) {
4763
4868
  return null;
4764
4869
  }
4765
4870
  function strLiteral(node) {
4766
- if (node.type === import_utils32.AST_NODE_TYPES.Literal && typeof node.value === "string") {
4871
+ if (node.type === import_utils35.AST_NODE_TYPES.Literal && typeof node.value === "string") {
4767
4872
  return node.value;
4768
4873
  }
4769
4874
  return null;
4770
4875
  }
4771
- var prefer_string_literal_union_default = import_utils32.ESLintUtils.RuleCreator(
4876
+ var prefer_string_literal_union_default = import_utils35.ESLintUtils.RuleCreator(
4772
4877
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4773
4878
  )({
4774
4879
  name: "prefer-string-literal-union",
@@ -4806,7 +4911,7 @@ var prefer_string_literal_union_default = import_utils32.ESLintUtils.RuleCreator
4806
4911
  );
4807
4912
  let services;
4808
4913
  try {
4809
- services = import_utils32.ESLintUtils.getParserServices(context);
4914
+ services = import_utils35.ESLintUtils.getParserServices(context);
4810
4915
  } catch {
4811
4916
  services = null;
4812
4917
  }
@@ -4918,7 +5023,7 @@ var prefer_string_literal_union_default = import_utils32.ESLintUtils.RuleCreator
4918
5023
  containersWithUnion.add(container);
4919
5024
  return;
4920
5025
  }
4921
- if (typeNode?.type !== import_utils32.AST_NODE_TYPES.TSStringKeyword) {
5026
+ if (typeNode?.type !== import_utils35.AST_NODE_TYPES.TSStringKeyword) {
4922
5027
  return;
4923
5028
  }
4924
5029
  const name = keyName(key);
@@ -5006,10 +5111,10 @@ var prefer_string_literal_union_default = import_utils32.ESLintUtils.RuleCreator
5006
5111
  }
5007
5112
  };
5008
5113
  function refKeyText(node) {
5009
- if (node.type === import_utils32.AST_NODE_TYPES.BinaryExpression) {
5114
+ if (node.type === import_utils35.AST_NODE_TYPES.BinaryExpression) {
5010
5115
  return refKey(node.left) ?? refKey(node.right) ?? "value";
5011
5116
  }
5012
- if (node.type === import_utils32.AST_NODE_TYPES.SwitchStatement) {
5117
+ if (node.type === import_utils35.AST_NODE_TYPES.SwitchStatement) {
5013
5118
  return refKey(node.discriminant) ?? "value";
5014
5119
  }
5015
5120
  return "value";
@@ -5017,8 +5122,98 @@ var prefer_string_literal_union_default = import_utils32.ESLintUtils.RuleCreator
5017
5122
  }
5018
5123
  });
5019
5124
 
5125
+ // src/rules/prefer-zod-enum.ts
5126
+ var import_utils36 = require("@typescript-eslint/utils");
5127
+ function isZodModule(source) {
5128
+ return /(^|[/@-])zod([/-]|$)/.test(source);
5129
+ }
5130
+ var prefer_zod_enum_default = import_utils36.ESLintUtils.RuleCreator(
5131
+ (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
5132
+ )({
5133
+ name: "prefer-zod-enum",
5134
+ meta: {
5135
+ type: "suggestion",
5136
+ docs: {
5137
+ description: "Prefer z.enum([...]) over z.union([z.literal(...), ...]) for string choices"
5138
+ },
5139
+ fixable: "code",
5140
+ schema: [],
5141
+ messages: {
5142
+ preferEnum: "Use `z.enum([...])` instead of a union of string-literal schemas."
5143
+ }
5144
+ },
5145
+ defaultOptions: [],
5146
+ create(context) {
5147
+ const sourceCode = context.sourceCode;
5148
+ const zodNamespaces = /* @__PURE__ */ new Set();
5149
+ function enumValues(node) {
5150
+ const callee = node.callee;
5151
+ if (callee.type !== import_utils36.AST_NODE_TYPES.MemberExpression || callee.computed || callee.object.type !== import_utils36.AST_NODE_TYPES.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== import_utils36.AST_NODE_TYPES.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
5152
+ return null;
5153
+ }
5154
+ const argument = node.arguments[0];
5155
+ if (argument === void 0 || argument.type !== import_utils36.AST_NODE_TYPES.ArrayExpression || argument.elements.length === 0) {
5156
+ return null;
5157
+ }
5158
+ const values = [];
5159
+ for (const element of argument.elements) {
5160
+ if (element === null || element.type !== import_utils36.AST_NODE_TYPES.CallExpression || element.arguments.length !== 1 || element.callee.type !== import_utils36.AST_NODE_TYPES.MemberExpression || element.callee.computed || element.callee.object.type !== import_utils36.AST_NODE_TYPES.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== import_utils36.AST_NODE_TYPES.Identifier || element.callee.property.name !== "literal") {
5161
+ return null;
5162
+ }
5163
+ const value = element.arguments[0];
5164
+ if (value === void 0 || value.type !== import_utils36.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
5165
+ return null;
5166
+ }
5167
+ values.push(value);
5168
+ }
5169
+ return values;
5170
+ }
5171
+ function buildFix(node, values) {
5172
+ const argument = node.arguments[0];
5173
+ if (argument === void 0 || argument.type !== import_utils36.AST_NODE_TYPES.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
5174
+ return void 0;
5175
+ }
5176
+ const callee = node.callee;
5177
+ if (callee.type !== import_utils36.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils36.AST_NODE_TYPES.Identifier) {
5178
+ return void 0;
5179
+ }
5180
+ return (fixer) => [
5181
+ fixer.replaceText(callee.property, "enum"),
5182
+ fixer.replaceText(
5183
+ argument,
5184
+ `[${values.map((value) => sourceCode.getText(value)).join(", ")}]`
5185
+ )
5186
+ ];
5187
+ }
5188
+ return {
5189
+ ImportDeclaration(node) {
5190
+ if (!isZodModule(node.source.value)) {
5191
+ return;
5192
+ }
5193
+ for (const specifier of node.specifiers) {
5194
+ if (specifier.type === import_utils36.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils36.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils36.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils36.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") {
5195
+ zodNamespaces.add(specifier.local.name);
5196
+ }
5197
+ }
5198
+ },
5199
+ CallExpression(node) {
5200
+ const values = enumValues(node);
5201
+ if (values === null) {
5202
+ return;
5203
+ }
5204
+ const fix = buildFix(node, values);
5205
+ context.report({
5206
+ node,
5207
+ messageId: "preferEnum",
5208
+ ...fix === void 0 ? {} : { fix }
5209
+ });
5210
+ }
5211
+ };
5212
+ }
5213
+ });
5214
+
5020
5215
  // src/rules/single-public-export.ts
5021
- var import_utils33 = require("@typescript-eslint/utils");
5216
+ var import_utils37 = require("@typescript-eslint/utils");
5022
5217
  var JUNK_DRAWER_STEMS = /* @__PURE__ */ new Set([
5023
5218
  "util",
5024
5219
  "utils",
@@ -5052,12 +5247,12 @@ var kebabCase2 = (name) => {
5052
5247
  }
5053
5248
  return normalized.replace(CAMEL_BOUNDARY_RE, "-").toLowerCase();
5054
5249
  };
5055
- var isFunctionExpression = (node) => node !== null && (node.type === import_utils33.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils33.AST_NODE_TYPES.FunctionExpression);
5250
+ var isFunctionExpression = (node) => node !== null && (node.type === import_utils37.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils37.AST_NODE_TYPES.FunctionExpression);
5056
5251
  var functionConstName = (decl) => {
5057
5252
  if (decl.declarations.length !== 1) return null;
5058
5253
  const [declarator] = decl.declarations;
5059
5254
  if (declarator === void 0) return null;
5060
- if (declarator.id.type !== import_utils33.AST_NODE_TYPES.Identifier) return null;
5255
+ if (declarator.id.type !== import_utils37.AST_NODE_TYPES.Identifier) return null;
5061
5256
  if (!isFunctionExpression(declarator.init)) return null;
5062
5257
  return declarator.id.name;
5063
5258
  };
@@ -5071,20 +5266,20 @@ var summarizeExports = (body) => {
5071
5266
  };
5072
5267
  for (const statement of body) {
5073
5268
  switch (statement.type) {
5074
- case import_utils33.AST_NODE_TYPES.ExportAllDeclaration:
5269
+ case import_utils37.AST_NODE_TYPES.ExportAllDeclaration:
5075
5270
  hasReExport = true;
5076
5271
  break;
5077
- case import_utils33.AST_NODE_TYPES.ExportDefaultDeclaration: {
5272
+ case import_utils37.AST_NODE_TYPES.ExportDefaultDeclaration: {
5078
5273
  names += 1;
5079
5274
  const decl = statement.declaration;
5080
- if (decl.type === import_utils33.AST_NODE_TYPES.FunctionDeclaration && decl.id !== null) {
5275
+ if (decl.type === import_utils37.AST_NODE_TYPES.FunctionDeclaration && decl.id !== null) {
5081
5276
  candidate = { name: decl.id.name, node: statement };
5082
- } else if (decl.type === import_utils33.AST_NODE_TYPES.ClassDeclaration && decl.id !== null) {
5277
+ } else if (decl.type === import_utils37.AST_NODE_TYPES.ClassDeclaration && decl.id !== null) {
5083
5278
  candidate = { name: decl.id.name, node: statement };
5084
5279
  }
5085
5280
  break;
5086
5281
  }
5087
- case import_utils33.AST_NODE_TYPES.ExportNamedDeclaration: {
5282
+ case import_utils37.AST_NODE_TYPES.ExportNamedDeclaration: {
5088
5283
  if (statement.source !== null) {
5089
5284
  hasReExport = true;
5090
5285
  break;
@@ -5095,15 +5290,15 @@ var summarizeExports = (body) => {
5095
5290
  break;
5096
5291
  }
5097
5292
  switch (decl.type) {
5098
- case import_utils33.AST_NODE_TYPES.FunctionDeclaration:
5293
+ case import_utils37.AST_NODE_TYPES.FunctionDeclaration:
5099
5294
  if (decl.id !== null) addCandidate(decl.id.name, statement);
5100
5295
  else names += 1;
5101
5296
  break;
5102
- case import_utils33.AST_NODE_TYPES.ClassDeclaration:
5297
+ case import_utils37.AST_NODE_TYPES.ClassDeclaration:
5103
5298
  if (decl.id !== null) addCandidate(decl.id.name, statement);
5104
5299
  else names += 1;
5105
5300
  break;
5106
- case import_utils33.AST_NODE_TYPES.VariableDeclaration: {
5301
+ case import_utils37.AST_NODE_TYPES.VariableDeclaration: {
5107
5302
  const fnName = functionConstName(decl);
5108
5303
  if (fnName !== null && decl.declarations.length === 1) {
5109
5304
  addCandidate(fnName, statement);
@@ -5123,7 +5318,7 @@ var summarizeExports = (body) => {
5123
5318
  }
5124
5319
  return { names, hasReExport, candidate };
5125
5320
  };
5126
- var single_public_export_default = import_utils33.ESLintUtils.RuleCreator(
5321
+ var single_public_export_default = import_utils37.ESLintUtils.RuleCreator(
5127
5322
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5128
5323
  )({
5129
5324
  name: "single-public-export",
@@ -5164,10 +5359,10 @@ var single_public_export_default = import_utils33.ESLintUtils.RuleCreator(
5164
5359
  });
5165
5360
 
5166
5361
  // src/rules/no-offset-pagination.ts
5167
- var import_utils35 = require("@typescript-eslint/utils");
5362
+ var import_utils39 = require("@typescript-eslint/utils");
5168
5363
 
5169
5364
  // src/rules/_sql.ts
5170
- var import_utils34 = require("@typescript-eslint/utils");
5365
+ var import_utils38 = require("@typescript-eslint/utils");
5171
5366
  function stripSqlNoise(text) {
5172
5367
  const out = [...text];
5173
5368
  const n = text.length;
@@ -5228,13 +5423,13 @@ function stripSqlNoise(text) {
5228
5423
  var SUBSTITUTION_MARKER = "?";
5229
5424
  function sqlTextOf(node) {
5230
5425
  switch (node.type) {
5231
- case import_utils34.AST_NODE_TYPES.Literal:
5426
+ case import_utils38.AST_NODE_TYPES.Literal:
5232
5427
  return typeof node.value === "string" ? node.value : null;
5233
- case import_utils34.AST_NODE_TYPES.TemplateLiteral:
5428
+ case import_utils38.AST_NODE_TYPES.TemplateLiteral:
5234
5429
  return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join(SUBSTITUTION_MARKER);
5235
- case import_utils34.AST_NODE_TYPES.TaggedTemplateExpression:
5430
+ case import_utils38.AST_NODE_TYPES.TaggedTemplateExpression:
5236
5431
  return sqlTextOf(node.quasi);
5237
- case import_utils34.AST_NODE_TYPES.BinaryExpression: {
5432
+ case import_utils38.AST_NODE_TYPES.BinaryExpression: {
5238
5433
  if (node.operator !== "+") {
5239
5434
  return null;
5240
5435
  }
@@ -5242,7 +5437,7 @@ function sqlTextOf(node) {
5242
5437
  const right = sqlTextOf(node.right);
5243
5438
  return left !== null && right !== null ? left + right : null;
5244
5439
  }
5245
- case import_utils34.AST_NODE_TYPES.ArrayExpression: {
5440
+ case import_utils38.AST_NODE_TYPES.ArrayExpression: {
5246
5441
  const parts = [];
5247
5442
  for (const element of node.elements) {
5248
5443
  if (element === null) {
@@ -5262,7 +5457,7 @@ function sqlTextOf(node) {
5262
5457
  }
5263
5458
  function isJoinedFragmentArray(node) {
5264
5459
  const parent = node.parent;
5265
- return parent?.type === import_utils34.AST_NODE_TYPES.MemberExpression && parent.object === node && !parent.computed && parent.property.type === import_utils34.AST_NODE_TYPES.Identifier && parent.property.name === "join" && parent.parent?.type === import_utils34.AST_NODE_TYPES.CallExpression;
5460
+ return parent?.type === import_utils38.AST_NODE_TYPES.MemberExpression && parent.object === node && !parent.computed && parent.property.type === import_utils38.AST_NODE_TYPES.Identifier && parent.property.name === "join" && parent.parent?.type === import_utils38.AST_NODE_TYPES.CallExpression;
5266
5461
  }
5267
5462
  function markConsumed(node, consumed) {
5268
5463
  consumed.add(node);
@@ -5312,7 +5507,7 @@ function createSqlListener(handler) {
5312
5507
  // src/rules/no-offset-pagination.ts
5313
5508
  var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
5314
5509
  var OFFSET_GATE = /offset/i;
5315
- var no_offset_pagination_default = import_utils35.ESLintUtils.RuleCreator(
5510
+ var no_offset_pagination_default = import_utils39.ESLintUtils.RuleCreator(
5316
5511
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5317
5512
  )({
5318
5513
  name: "no-offset-pagination",
@@ -5341,15 +5536,15 @@ var no_offset_pagination_default = import_utils35.ESLintUtils.RuleCreator(
5341
5536
  });
5342
5537
 
5343
5538
  // src/rules/no-positional-tuple-return.ts
5344
- var import_utils36 = require("@typescript-eslint/utils");
5539
+ var import_utils40 = require("@typescript-eslint/utils");
5345
5540
  var MIN_ELEMENTS = 2;
5346
5541
  var ACCESSOR_PAIR_LENGTH = 2;
5347
5542
  var AWAITABLE_TYPES = /* @__PURE__ */ new Set(["Promise", "PromiseLike", "Awaited"]);
5348
5543
  function tupleReturnType(node) {
5349
- if (node.type === import_utils36.AST_NODE_TYPES.TSTupleType) {
5544
+ if (node.type === import_utils40.AST_NODE_TYPES.TSTupleType) {
5350
5545
  return node;
5351
5546
  }
5352
- if (node.type === import_utils36.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils36.AST_NODE_TYPES.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5547
+ if (node.type === import_utils40.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils40.AST_NODE_TYPES.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5353
5548
  const argument = node.typeArguments?.params[0];
5354
5549
  return argument === void 0 ? null : tupleReturnType(argument);
5355
5550
  }
@@ -5363,30 +5558,30 @@ function isPermittedTuple(tuple, sourceCode) {
5363
5558
  if (elements.length < MIN_ELEMENTS) {
5364
5559
  return true;
5365
5560
  }
5366
- if (elements.some((element) => element.type === import_utils36.AST_NODE_TYPES.TSRestType)) {
5561
+ if (elements.some((element) => element.type === import_utils40.AST_NODE_TYPES.TSRestType)) {
5367
5562
  return true;
5368
5563
  }
5369
- if (elements.some((element) => element.type === import_utils36.AST_NODE_TYPES.TSNamedTupleMember)) {
5564
+ if (elements.some((element) => element.type === import_utils40.AST_NODE_TYPES.TSNamedTupleMember)) {
5370
5565
  return true;
5371
5566
  }
5372
- if (elements[0]?.type === import_utils36.AST_NODE_TYPES.TSLiteralType) {
5567
+ if (elements[0]?.type === import_utils40.AST_NODE_TYPES.TSLiteralType) {
5373
5568
  return true;
5374
5569
  }
5375
- if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === import_utils36.AST_NODE_TYPES.TSFunctionType)) {
5570
+ if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === import_utils40.AST_NODE_TYPES.TSFunctionType)) {
5376
5571
  return true;
5377
5572
  }
5378
5573
  const texts = new Set(elements.map((element) => normalizedText(sourceCode, element)));
5379
5574
  return texts.size === 1;
5380
5575
  }
5381
5576
  function functionName(node) {
5382
- if (node.type === import_utils36.AST_NODE_TYPES.FunctionDeclaration) {
5577
+ if (node.type === import_utils40.AST_NODE_TYPES.FunctionDeclaration) {
5383
5578
  return node.id?.name ?? null;
5384
5579
  }
5385
5580
  const parent = node.parent;
5386
- if (parent?.type === import_utils36.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils36.AST_NODE_TYPES.Identifier) {
5581
+ if (parent?.type === import_utils40.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils40.AST_NODE_TYPES.Identifier) {
5387
5582
  return parent.id.name;
5388
5583
  }
5389
- if ((parent?.type === import_utils36.AST_NODE_TYPES.MethodDefinition || parent?.type === import_utils36.AST_NODE_TYPES.PropertyDefinition || parent?.type === import_utils36.AST_NODE_TYPES.Property) && parent.key.type === import_utils36.AST_NODE_TYPES.Identifier) {
5584
+ if ((parent?.type === import_utils40.AST_NODE_TYPES.MethodDefinition || parent?.type === import_utils40.AST_NODE_TYPES.PropertyDefinition || parent?.type === import_utils40.AST_NODE_TYPES.Property) && parent.key.type === import_utils40.AST_NODE_TYPES.Identifier) {
5390
5585
  return parent.key.name;
5391
5586
  }
5392
5587
  return null;
@@ -5394,7 +5589,7 @@ function functionName(node) {
5394
5589
  function isInlineExported(node) {
5395
5590
  for (let current = node; current != null; current = current.parent) {
5396
5591
  const parent = current.parent;
5397
- if (parent?.type === import_utils36.AST_NODE_TYPES.ExportNamedDeclaration || parent?.type === import_utils36.AST_NODE_TYPES.ExportDefaultDeclaration) {
5592
+ if (parent?.type === import_utils40.AST_NODE_TYPES.ExportNamedDeclaration || parent?.type === import_utils40.AST_NODE_TYPES.ExportDefaultDeclaration) {
5398
5593
  return true;
5399
5594
  }
5400
5595
  }
@@ -5403,18 +5598,18 @@ function isInlineExported(node) {
5403
5598
  function moduleScopeBindingName(node) {
5404
5599
  let current = node;
5405
5600
  let child = node;
5406
- while (current.parent != null && current.parent.type !== import_utils36.AST_NODE_TYPES.Program) {
5601
+ while (current.parent != null && current.parent.type !== import_utils40.AST_NODE_TYPES.Program) {
5407
5602
  child = current;
5408
5603
  current = current.parent;
5409
5604
  }
5410
- if (current.parent?.type !== import_utils36.AST_NODE_TYPES.Program) {
5605
+ if (current.parent?.type !== import_utils40.AST_NODE_TYPES.Program) {
5411
5606
  return null;
5412
5607
  }
5413
- if (current.type === import_utils36.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils36.AST_NODE_TYPES.ClassDeclaration) {
5608
+ if (current.type === import_utils40.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils40.AST_NODE_TYPES.ClassDeclaration) {
5414
5609
  return current.id?.name ?? null;
5415
5610
  }
5416
- if (current.type === import_utils36.AST_NODE_TYPES.VariableDeclaration) {
5417
- if (child.type !== import_utils36.AST_NODE_TYPES.VariableDeclarator || child.id.type !== import_utils36.AST_NODE_TYPES.Identifier) {
5611
+ if (current.type === import_utils40.AST_NODE_TYPES.VariableDeclaration) {
5612
+ if (child.type !== import_utils40.AST_NODE_TYPES.VariableDeclarator || child.id.type !== import_utils40.AST_NODE_TYPES.Identifier) {
5418
5613
  return null;
5419
5614
  }
5420
5615
  return child.id.name;
@@ -5424,19 +5619,19 @@ function moduleScopeBindingName(node) {
5424
5619
  function specifierExportedNames(program) {
5425
5620
  const names = /* @__PURE__ */ new Set();
5426
5621
  for (const statement of program.body) {
5427
- if (statement.type === import_utils36.AST_NODE_TYPES.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5622
+ if (statement.type === import_utils40.AST_NODE_TYPES.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5428
5623
  for (const specifier of statement.specifiers) {
5429
- if (specifier.exportKind !== "type" && specifier.local.type === import_utils36.AST_NODE_TYPES.Identifier) {
5624
+ if (specifier.exportKind !== "type" && specifier.local.type === import_utils40.AST_NODE_TYPES.Identifier) {
5430
5625
  names.add(specifier.local.name);
5431
5626
  }
5432
5627
  }
5433
5628
  continue;
5434
5629
  }
5435
- if (statement.type === import_utils36.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils36.AST_NODE_TYPES.Identifier) {
5630
+ if (statement.type === import_utils40.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils40.AST_NODE_TYPES.Identifier) {
5436
5631
  names.add(statement.declaration.name);
5437
5632
  continue;
5438
5633
  }
5439
- if (statement.type === import_utils36.AST_NODE_TYPES.TSExportAssignment && statement.expression.type === import_utils36.AST_NODE_TYPES.Identifier) {
5634
+ if (statement.type === import_utils40.AST_NODE_TYPES.TSExportAssignment && statement.expression.type === import_utils40.AST_NODE_TYPES.Identifier) {
5440
5635
  names.add(statement.expression.name);
5441
5636
  }
5442
5637
  }
@@ -5452,7 +5647,7 @@ function isExported(node, specifierExports) {
5452
5647
  const binding = moduleScopeBindingName(node);
5453
5648
  return binding !== null && specifierExports.has(binding);
5454
5649
  }
5455
- var no_positional_tuple_return_default = import_utils36.ESLintUtils.RuleCreator(
5650
+ var no_positional_tuple_return_default = import_utils40.ESLintUtils.RuleCreator(
5456
5651
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5457
5652
  )({
5458
5653
  name: "no-positional-tuple-return",
@@ -5500,16 +5695,16 @@ var no_positional_tuple_return_default = import_utils36.ESLintUtils.RuleCreator(
5500
5695
  });
5501
5696
 
5502
5697
  // src/rules/no-repeated-string-literal.ts
5503
- var import_utils37 = require("@typescript-eslint/utils");
5698
+ var import_utils41 = require("@typescript-eslint/utils");
5504
5699
  var MIN_LENGTH = 40;
5505
5700
  var MIN_DISTINCT_SCOPES = 2;
5506
5701
  var PREVIEW_LENGTH = 40;
5507
5702
  var SQL_KEYWORD_RE = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES|ON CONFLICT|RETURNING|GROUP BY|ORDER BY)\b/;
5508
5703
  var IDENTIFIER_RE = /^[a-z_][a-z0-9_.]*$/;
5509
5704
  var FUNCTION_TYPES = /* @__PURE__ */ new Set([
5510
- import_utils37.AST_NODE_TYPES.FunctionDeclaration,
5511
- import_utils37.AST_NODE_TYPES.FunctionExpression,
5512
- import_utils37.AST_NODE_TYPES.ArrowFunctionExpression
5705
+ import_utils41.AST_NODE_TYPES.FunctionDeclaration,
5706
+ import_utils41.AST_NODE_TYPES.FunctionExpression,
5707
+ import_utils41.AST_NODE_TYPES.ArrowFunctionExpression
5513
5708
  ]);
5514
5709
  function isStructured(value) {
5515
5710
  return value.includes("\n") || SQL_KEYWORD_RE.test(value) || IDENTIFIER_RE.test(value);
@@ -5531,9 +5726,9 @@ function isScaffolding(node) {
5531
5726
  if (parent === void 0) {
5532
5727
  return true;
5533
5728
  }
5534
- return parent.type === import_utils37.AST_NODE_TYPES.ImportDeclaration || parent.type === import_utils37.AST_NODE_TYPES.ExportNamedDeclaration || parent.type === import_utils37.AST_NODE_TYPES.ExportAllDeclaration || parent.type === import_utils37.AST_NODE_TYPES.TSImportType || parent.type === import_utils37.AST_NODE_TYPES.JSXAttribute || parent.type === import_utils37.AST_NODE_TYPES.TSLiteralType;
5729
+ return parent.type === import_utils41.AST_NODE_TYPES.ImportDeclaration || parent.type === import_utils41.AST_NODE_TYPES.ExportNamedDeclaration || parent.type === import_utils41.AST_NODE_TYPES.ExportAllDeclaration || parent.type === import_utils41.AST_NODE_TYPES.TSImportType || parent.type === import_utils41.AST_NODE_TYPES.JSXAttribute || parent.type === import_utils41.AST_NODE_TYPES.TSLiteralType;
5535
5730
  }
5536
- var no_repeated_string_literal_default = import_utils37.ESLintUtils.RuleCreator(
5731
+ var no_repeated_string_literal_default = import_utils41.ESLintUtils.RuleCreator(
5537
5732
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5538
5733
  )({
5539
5734
  name: "no-repeated-string-literal",
@@ -5573,7 +5768,7 @@ var no_repeated_string_literal_default = import_utils37.ESLintUtils.RuleCreator(
5573
5768
  }
5574
5769
  },
5575
5770
  TemplateLiteral(node) {
5576
- if (node.parent.type === import_utils37.AST_NODE_TYPES.TaggedTemplateExpression) {
5771
+ if (node.parent.type === import_utils41.AST_NODE_TYPES.TaggedTemplateExpression) {
5577
5772
  return;
5578
5773
  }
5579
5774
  const [only] = node.quasis;
@@ -5607,7 +5802,7 @@ var no_repeated_string_literal_default = import_utils37.ESLintUtils.RuleCreator(
5607
5802
  });
5608
5803
 
5609
5804
  // src/rules/no-select-star.ts
5610
- var import_utils38 = require("@typescript-eslint/utils");
5805
+ var import_utils42 = require("@typescript-eslint/utils");
5611
5806
  var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
5612
5807
  var SELECT_KEYWORD = /\bSELECT\b/gi;
5613
5808
  var FROM_KEYWORD = /^FROM\b/i;
@@ -5647,7 +5842,7 @@ function hasRealSelectStar(sql) {
5647
5842
  }
5648
5843
  return false;
5649
5844
  }
5650
- var no_select_star_default = import_utils38.ESLintUtils.RuleCreator(
5845
+ var no_select_star_default = import_utils42.ESLintUtils.RuleCreator(
5651
5846
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5652
5847
  )({
5653
5848
  name: "no-select-star",
@@ -5676,7 +5871,7 @@ var no_select_star_default = import_utils38.ESLintUtils.RuleCreator(
5676
5871
  });
5677
5872
 
5678
5873
  // src/rules/no-sleep-in-test-body.ts
5679
- var import_utils39 = require("@typescript-eslint/utils");
5874
+ var import_utils43 = require("@typescript-eslint/utils");
5680
5875
  var SLEEP_HELPERS = /* @__PURE__ */ new Set(["sleep", "delay", "wait", "pause"]);
5681
5876
  var TEST_CALLERS = /* @__PURE__ */ new Set([
5682
5877
  "it",
@@ -5685,34 +5880,34 @@ var TEST_CALLERS = /* @__PURE__ */ new Set([
5685
5880
  "afterEach"
5686
5881
  ]);
5687
5882
  var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5688
- import_utils39.AST_NODE_TYPES.FunctionDeclaration,
5689
- import_utils39.AST_NODE_TYPES.FunctionExpression,
5690
- import_utils39.AST_NODE_TYPES.ArrowFunctionExpression
5883
+ import_utils43.AST_NODE_TYPES.FunctionDeclaration,
5884
+ import_utils43.AST_NODE_TYPES.FunctionExpression,
5885
+ import_utils43.AST_NODE_TYPES.ArrowFunctionExpression
5691
5886
  ]);
5692
5887
  function isNonzeroNumericLiteral(node) {
5693
- return node?.type === import_utils39.AST_NODE_TYPES.Literal && typeof node.value === "number" && node.value !== 0;
5888
+ return node?.type === import_utils43.AST_NODE_TYPES.Literal && typeof node.value === "number" && node.value !== 0;
5694
5889
  }
5695
5890
  function isTimedSetTimeout(node) {
5696
- return node.type === import_utils39.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils39.AST_NODE_TYPES.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5891
+ return node.type === import_utils43.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils43.AST_NODE_TYPES.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5697
5892
  }
5698
5893
  function isPromiseSleep(node) {
5699
- if (node.callee.type !== import_utils39.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise") {
5894
+ if (node.callee.type !== import_utils43.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise") {
5700
5895
  return false;
5701
5896
  }
5702
5897
  const executor = node.arguments[0];
5703
- if (executor?.type !== import_utils39.AST_NODE_TYPES.ArrowFunctionExpression && executor?.type !== import_utils39.AST_NODE_TYPES.FunctionExpression) {
5898
+ if (executor?.type !== import_utils43.AST_NODE_TYPES.ArrowFunctionExpression && executor?.type !== import_utils43.AST_NODE_TYPES.FunctionExpression) {
5704
5899
  return false;
5705
5900
  }
5706
5901
  const body = executor.body;
5707
- if (body.type !== import_utils39.AST_NODE_TYPES.BlockStatement) {
5902
+ if (body.type !== import_utils43.AST_NODE_TYPES.BlockStatement) {
5708
5903
  return isTimedSetTimeout(body);
5709
5904
  }
5710
5905
  return body.body.some(
5711
- (stmt) => stmt.type === import_utils39.AST_NODE_TYPES.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5906
+ (stmt) => stmt.type === import_utils43.AST_NODE_TYPES.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5712
5907
  );
5713
5908
  }
5714
5909
  function isHelperSleep(node) {
5715
- return node.callee.type === import_utils39.AST_NODE_TYPES.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5910
+ return node.callee.type === import_utils43.AST_NODE_TYPES.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5716
5911
  }
5717
5912
  function nearestEnclosingFunction(node) {
5718
5913
  for (let current = node.parent; current != null; current = current.parent) {
@@ -5720,7 +5915,7 @@ function nearestEnclosingFunction(node) {
5720
5915
  continue;
5721
5916
  }
5722
5917
  const grandparent = current.parent;
5723
- const isPromiseExecutor = grandparent?.type === import_utils39.AST_NODE_TYPES.NewExpression && isPromiseSleep(grandparent);
5918
+ const isPromiseExecutor = grandparent?.type === import_utils43.AST_NODE_TYPES.NewExpression && isPromiseSleep(grandparent);
5724
5919
  if (!isPromiseExecutor) {
5725
5920
  return current;
5726
5921
  }
@@ -5728,29 +5923,29 @@ function nearestEnclosingFunction(node) {
5728
5923
  return null;
5729
5924
  }
5730
5925
  function testCallerName(callee) {
5731
- if (callee.type === import_utils39.AST_NODE_TYPES.Identifier) {
5926
+ if (callee.type === import_utils43.AST_NODE_TYPES.Identifier) {
5732
5927
  return callee.name;
5733
5928
  }
5734
- if (callee.type === import_utils39.AST_NODE_TYPES.MemberExpression) {
5929
+ if (callee.type === import_utils43.AST_NODE_TYPES.MemberExpression) {
5735
5930
  return testCallerName(callee.object);
5736
5931
  }
5737
- if (callee.type === import_utils39.AST_NODE_TYPES.CallExpression) {
5932
+ if (callee.type === import_utils43.AST_NODE_TYPES.CallExpression) {
5738
5933
  return testCallerName(callee.callee);
5739
5934
  }
5740
- if (callee.type === import_utils39.AST_NODE_TYPES.TaggedTemplateExpression) {
5935
+ if (callee.type === import_utils43.AST_NODE_TYPES.TaggedTemplateExpression) {
5741
5936
  return testCallerName(callee.tag);
5742
5937
  }
5743
5938
  return null;
5744
5939
  }
5745
5940
  function isTestBody(fn) {
5746
5941
  const call = fn.parent;
5747
- if (call?.type !== import_utils39.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5942
+ if (call?.type !== import_utils43.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5748
5943
  return false;
5749
5944
  }
5750
5945
  const name = testCallerName(call.callee);
5751
5946
  return name !== null && TEST_CALLERS.has(name);
5752
5947
  }
5753
- var no_sleep_in_test_body_default = import_utils39.ESLintUtils.RuleCreator(
5948
+ var no_sleep_in_test_body_default = import_utils43.ESLintUtils.RuleCreator(
5754
5949
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5755
5950
  )({
5756
5951
  name: "no-sleep-in-test-body",
@@ -5791,8 +5986,90 @@ var no_sleep_in_test_body_default = import_utils39.ESLintUtils.RuleCreator(
5791
5986
  }
5792
5987
  });
5793
5988
 
5989
+ // src/rules/no-conditional-in-test.ts
5990
+ var import_utils44 = require("@typescript-eslint/utils");
5991
+ var TEST_CALLERS2 = /* @__PURE__ */ new Set(["it", "test"]);
5992
+ var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5993
+ import_utils44.AST_NODE_TYPES.FunctionDeclaration,
5994
+ import_utils44.AST_NODE_TYPES.FunctionExpression,
5995
+ import_utils44.AST_NODE_TYPES.ArrowFunctionExpression
5996
+ ]);
5997
+ function nearestEnclosingFunction2(node) {
5998
+ for (let current = node.parent; current != null; current = current.parent) {
5999
+ if (FUNCTION_TYPES3.has(current.type)) {
6000
+ return current;
6001
+ }
6002
+ }
6003
+ return null;
6004
+ }
6005
+ function testCallerName2(callee) {
6006
+ if (callee.type === import_utils44.AST_NODE_TYPES.Identifier) {
6007
+ return callee.name;
6008
+ }
6009
+ if (callee.type === import_utils44.AST_NODE_TYPES.MemberExpression) {
6010
+ return testCallerName2(callee.object);
6011
+ }
6012
+ if (callee.type === import_utils44.AST_NODE_TYPES.CallExpression) {
6013
+ return testCallerName2(callee.callee);
6014
+ }
6015
+ if (callee.type === import_utils44.AST_NODE_TYPES.TaggedTemplateExpression) {
6016
+ return testCallerName2(callee.tag);
6017
+ }
6018
+ return null;
6019
+ }
6020
+ function isTestBody2(fn) {
6021
+ const call = fn.parent;
6022
+ if (call?.type !== import_utils44.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
6023
+ return false;
6024
+ }
6025
+ const name = testCallerName2(call.callee);
6026
+ return name !== null && TEST_CALLERS2.has(name);
6027
+ }
6028
+ var no_conditional_in_test_default = import_utils44.ESLintUtils.RuleCreator(
6029
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6030
+ )({
6031
+ name: "no-conditional-in-test",
6032
+ meta: {
6033
+ type: "problem",
6034
+ docs: {
6035
+ description: "Disallow conditional logic (if, switch, ternary) in test bodies, which can hide missing assertions or test multiple code paths."
6036
+ },
6037
+ schema: [],
6038
+ messages: {
6039
+ noConditionalInTest: "Avoid using conditional logic in tests. It can obscure intent and hide unexecuted assertions. Split the test instead."
6040
+ }
6041
+ },
6042
+ defaultOptions: [],
6043
+ create(context) {
6044
+ if (!isTestFile(context.filename)) {
6045
+ return {};
6046
+ }
6047
+ const report = (node) => {
6048
+ const enclosing = nearestEnclosingFunction2(node);
6049
+ if (enclosing === null || !isTestBody2(enclosing)) {
6050
+ return;
6051
+ }
6052
+ context.report({ node, messageId: "noConditionalInTest" });
6053
+ };
6054
+ return {
6055
+ IfStatement(node) {
6056
+ report(node);
6057
+ },
6058
+ SwitchStatement(node) {
6059
+ report(node);
6060
+ },
6061
+ ConditionalExpression(node) {
6062
+ report(node);
6063
+ },
6064
+ LogicalExpression(node) {
6065
+ report(node);
6066
+ }
6067
+ };
6068
+ }
6069
+ });
6070
+
5794
6071
  // src/rules/prefer-constant-time-secret-compare.ts
5795
- var import_utils40 = require("@typescript-eslint/utils");
6072
+ var import_utils45 = require("@typescript-eslint/utils");
5796
6073
  var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["===", "!==", "==", "!="]);
5797
6074
  var SENTINEL_IDENTIFIERS = /* @__PURE__ */ new Set(["undefined", "NaN"]);
5798
6075
  var SENTINEL_WORDS = /(^|_)(SENTINEL|EMPTY|NONE|NULL|UNSET|MISSING|PLACEHOLDER|DUMMY|FAKE|EXAMPLE)(_|$)/;
@@ -5805,36 +6082,36 @@ function isConstantReference(identifier) {
5805
6082
  }
5806
6083
  function isExcludedOperand(node) {
5807
6084
  switch (node.type) {
5808
- case import_utils40.AST_NODE_TYPES.Literal:
6085
+ case import_utils45.AST_NODE_TYPES.Literal:
5809
6086
  return true;
5810
- case import_utils40.AST_NODE_TYPES.TemplateLiteral:
6087
+ case import_utils45.AST_NODE_TYPES.TemplateLiteral:
5811
6088
  return node.expressions.length === 0;
5812
- case import_utils40.AST_NODE_TYPES.Identifier:
6089
+ case import_utils45.AST_NODE_TYPES.Identifier:
5813
6090
  return SENTINEL_IDENTIFIERS.has(node.name) || SENTINEL_PREFIX_RE.test(node.name) || isConstantReference(node.name);
5814
- case import_utils40.AST_NODE_TYPES.MemberExpression:
5815
- return !node.computed && node.property.type === import_utils40.AST_NODE_TYPES.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
6091
+ case import_utils45.AST_NODE_TYPES.MemberExpression:
6092
+ return !node.computed && node.property.type === import_utils45.AST_NODE_TYPES.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
5816
6093
  default:
5817
6094
  return false;
5818
6095
  }
5819
6096
  }
5820
6097
  function operandName(node) {
5821
- if (node.type === import_utils40.AST_NODE_TYPES.Identifier) {
6098
+ if (node.type === import_utils45.AST_NODE_TYPES.Identifier) {
5822
6099
  return node.name;
5823
6100
  }
5824
- if (node.type === import_utils40.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === import_utils40.AST_NODE_TYPES.Identifier) {
6101
+ if (node.type === import_utils45.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === import_utils45.AST_NODE_TYPES.Identifier) {
5825
6102
  return node.property.name;
5826
6103
  }
5827
6104
  return null;
5828
6105
  }
5829
6106
  function isSecretOperand(node) {
5830
- if (node.type === import_utils40.AST_NODE_TYPES.TemplateLiteral) {
6107
+ if (node.type === import_utils45.AST_NODE_TYPES.TemplateLiteral) {
5831
6108
  return node.expressions.some((expression) => isSecretOperand(expression));
5832
6109
  }
5833
6110
  const name = operandName(node);
5834
6111
  return name !== null && isAuthSecretName(name);
5835
6112
  }
5836
6113
  function secretNameOf(node) {
5837
- if (node.type === import_utils40.AST_NODE_TYPES.TemplateLiteral) {
6114
+ if (node.type === import_utils45.AST_NODE_TYPES.TemplateLiteral) {
5838
6115
  for (const expression of node.expressions) {
5839
6116
  const nested = secretNameOf(expression);
5840
6117
  if (nested !== null) {
@@ -5845,7 +6122,7 @@ function secretNameOf(node) {
5845
6122
  }
5846
6123
  return operandName(node);
5847
6124
  }
5848
- var prefer_constant_time_secret_compare_default = import_utils40.ESLintUtils.RuleCreator(
6125
+ var prefer_constant_time_secret_compare_default = import_utils45.ESLintUtils.RuleCreator(
5849
6126
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5850
6127
  )({
5851
6128
  name: "prefer-constant-time-secret-compare",
@@ -5888,11 +6165,11 @@ var prefer_constant_time_secret_compare_default = import_utils40.ESLintUtils.Rul
5888
6165
  });
5889
6166
 
5890
6167
  // src/rules/store-insert-requires-on-conflict.ts
5891
- var import_utils41 = require("@typescript-eslint/utils");
6168
+ var import_utils46 = require("@typescript-eslint/utils");
5892
6169
  var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
5893
6170
  var CONFLICT_HANDLED = /\bON\s+CONFLICT\b|\bON\s+DUPLICATE\s+KEY\b|\bINSERT\s+OR\s+(?:IGNORE|REPLACE)\b/i;
5894
6171
  var INSERT_GATE = /insert/i;
5895
- var store_insert_requires_on_conflict_default = import_utils41.ESLintUtils.RuleCreator(
6172
+ var store_insert_requires_on_conflict_default = import_utils46.ESLintUtils.RuleCreator(
5896
6173
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5897
6174
  )({
5898
6175
  name: "store-insert-requires-on-conflict",
@@ -5921,17 +6198,17 @@ var store_insert_requires_on_conflict_default = import_utils41.ESLintUtils.RuleC
5921
6198
  });
5922
6199
 
5923
6200
  // src/rules/no-dynamic-sql.ts
5924
- var import_utils42 = require("@typescript-eslint/utils");
6201
+ var import_utils47 = require("@typescript-eslint/utils");
5925
6202
  var DEFAULT_METHODS = ["prepare", "exec", "query"];
5926
6203
  var CONSTANT_CASE_RE = /^[A-Z][A-Z0-9_]*$/;
5927
6204
  function isStaticFragment(expression) {
5928
- if (expression.type === import_utils42.AST_NODE_TYPES.Identifier) {
6205
+ if (expression.type === import_utils47.AST_NODE_TYPES.Identifier) {
5929
6206
  return CONSTANT_CASE_RE.test(expression.name);
5930
6207
  }
5931
- if (expression.type === import_utils42.AST_NODE_TYPES.MemberExpression && !expression.computed && expression.property.type === import_utils42.AST_NODE_TYPES.Identifier) {
6208
+ if (expression.type === import_utils47.AST_NODE_TYPES.MemberExpression && !expression.computed && expression.property.type === import_utils47.AST_NODE_TYPES.Identifier) {
5932
6209
  return CONSTANT_CASE_RE.test(expression.property.name);
5933
6210
  }
5934
- if (expression.type === import_utils42.AST_NODE_TYPES.Literal) {
6211
+ if (expression.type === import_utils47.AST_NODE_TYPES.Literal) {
5935
6212
  return typeof expression.value === "string";
5936
6213
  }
5937
6214
  return false;
@@ -5942,36 +6219,36 @@ function runtimeInterpolations(template) {
5942
6219
  );
5943
6220
  }
5944
6221
  function concatOperands(node) {
5945
- if (node.type === import_utils42.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
6222
+ if (node.type === import_utils47.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
5946
6223
  return [...concatOperands(node.left), ...concatOperands(node.right)];
5947
6224
  }
5948
6225
  return [node];
5949
6226
  }
5950
6227
  function runtimeConcatOperands(node) {
5951
- if (node.type !== import_utils42.AST_NODE_TYPES.BinaryExpression || node.operator !== "+") {
6228
+ if (node.type !== import_utils47.AST_NODE_TYPES.BinaryExpression || node.operator !== "+") {
5952
6229
  return [];
5953
6230
  }
5954
6231
  const operands = concatOperands(node);
5955
6232
  const hasStringLiteral = operands.some(
5956
- (operand) => operand.type === import_utils42.AST_NODE_TYPES.Literal && typeof operand.value === "string"
6233
+ (operand) => operand.type === import_utils47.AST_NODE_TYPES.Literal && typeof operand.value === "string"
5957
6234
  );
5958
6235
  if (!hasStringLiteral) {
5959
6236
  return [];
5960
6237
  }
5961
6238
  return operands.filter(
5962
- (operand) => operand.type !== import_utils42.AST_NODE_TYPES.Literal && !isStaticFragment(operand)
6239
+ (operand) => operand.type !== import_utils47.AST_NODE_TYPES.Literal && !isStaticFragment(operand)
5963
6240
  );
5964
6241
  }
5965
6242
  var SQL_STATEMENT_RE = /\b(?:select\s|insert\s+into\b|insert\s+or\b|update\s+\w|delete\s+from\b|replace\s+into\b|merge\s+into\b|upsert\s+into\b|create\s+(?:temp(?:orary)?\s+)?(?:table|index|view|trigger|schema|database)\b|alter\s+table\b|drop\s+(?:table|index|view|trigger)\b|truncate\s+table\b|pragma\s+\w|with\s+\w+\s+as\s*\(|from\s+\w+\s+where\b)/i;
5966
6243
  var RUNTIME_MARKER = " ? ";
5967
6244
  function staticStatementText(node) {
5968
- if (node.type === import_utils42.AST_NODE_TYPES.TemplateLiteral) {
6245
+ if (node.type === import_utils47.AST_NODE_TYPES.TemplateLiteral) {
5969
6246
  return node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join(RUNTIME_MARKER);
5970
6247
  }
5971
- if (node.type === import_utils42.AST_NODE_TYPES.Literal) {
6248
+ if (node.type === import_utils47.AST_NODE_TYPES.Literal) {
5972
6249
  return typeof node.value === "string" ? node.value : RUNTIME_MARKER;
5973
6250
  }
5974
- if (node.type === import_utils42.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
6251
+ if (node.type === import_utils47.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
5975
6252
  return staticStatementText(node.left) + staticStatementText(node.right);
5976
6253
  }
5977
6254
  return RUNTIME_MARKER;
@@ -5981,13 +6258,13 @@ function looksLikeSql(node) {
5981
6258
  }
5982
6259
  function statementMethodName(node, methods) {
5983
6260
  const callee = node.callee;
5984
- if (callee.type !== import_utils42.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils42.AST_NODE_TYPES.Identifier) {
6261
+ if (callee.type !== import_utils47.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils47.AST_NODE_TYPES.Identifier) {
5985
6262
  return null;
5986
6263
  }
5987
6264
  const name = callee.property.name;
5988
6265
  return methods.has(name) ? name : null;
5989
6266
  }
5990
- var no_dynamic_sql_default = import_utils42.ESLintUtils.RuleCreator(
6267
+ var no_dynamic_sql_default = import_utils47.ESLintUtils.RuleCreator(
5991
6268
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5992
6269
  )({
5993
6270
  name: "no-dynamic-sql",
@@ -6026,7 +6303,7 @@ var no_dynamic_sql_default = import_utils42.ESLintUtils.RuleCreator(
6026
6303
  if (statement === void 0 || !looksLikeSql(statement)) {
6027
6304
  return;
6028
6305
  }
6029
- const offenders = statement.type === import_utils42.AST_NODE_TYPES.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6306
+ const offenders = statement.type === import_utils47.AST_NODE_TYPES.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6030
6307
  for (const offender of offenders) {
6031
6308
  context.report({
6032
6309
  node: offender,
@@ -6040,7 +6317,7 @@ var no_dynamic_sql_default = import_utils42.ESLintUtils.RuleCreator(
6040
6317
  });
6041
6318
 
6042
6319
  // src/rules/no-raw-fetch-outside-clients.ts
6043
- var import_utils43 = require("@typescript-eslint/utils");
6320
+ var import_utils48 = require("@typescript-eslint/utils");
6044
6321
  var DEFAULT_ALLOW = [
6045
6322
  "[\\\\/]clients?[\\\\/]",
6046
6323
  "-client\\.[cm]?[jt]sx?$",
@@ -6104,7 +6381,7 @@ function compile(patterns) {
6104
6381
  }
6105
6382
  return compiled;
6106
6383
  }
6107
- var no_raw_fetch_outside_clients_default = import_utils43.ESLintUtils.RuleCreator(
6384
+ var no_raw_fetch_outside_clients_default = import_utils48.ESLintUtils.RuleCreator(
6108
6385
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6109
6386
  )({
6110
6387
  name: "no-raw-fetch-outside-clients",
@@ -6152,7 +6429,7 @@ var no_raw_fetch_outside_clients_default = import_utils43.ESLintUtils.RuleCreato
6152
6429
  });
6153
6430
 
6154
6431
  // src/rules/no-storage-in-stateless-modules.ts
6155
- var import_utils44 = require("@typescript-eslint/utils");
6432
+ var import_utils49 = require("@typescript-eslint/utils");
6156
6433
  var DEFAULT_METHODS2 = [
6157
6434
  "prepare",
6158
6435
  "put",
@@ -6171,7 +6448,7 @@ function compile2(patterns) {
6171
6448
  }
6172
6449
  function storageMethodName(node, methods) {
6173
6450
  const callee = node.callee;
6174
- if (callee.type !== import_utils44.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils44.AST_NODE_TYPES.Identifier) {
6451
+ if (callee.type !== import_utils49.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils49.AST_NODE_TYPES.Identifier) {
6175
6452
  return null;
6176
6453
  }
6177
6454
  const name = callee.property.name;
@@ -6183,7 +6460,7 @@ function storageMethodName(node, methods) {
6183
6460
  }
6184
6461
  return name;
6185
6462
  }
6186
- var no_storage_in_stateless_modules_default = import_utils44.ESLintUtils.RuleCreator(
6463
+ var no_storage_in_stateless_modules_default = import_utils49.ESLintUtils.RuleCreator(
6187
6464
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6188
6465
  )({
6189
6466
  name: "no-storage-in-stateless-modules",
@@ -6241,7 +6518,7 @@ var no_storage_in_stateless_modules_default = import_utils44.ESLintUtils.RuleCre
6241
6518
  });
6242
6519
 
6243
6520
  // src/rules/no-zod-native-enum.ts
6244
- var import_utils45 = require("@typescript-eslint/utils");
6521
+ var import_utils50 = require("@typescript-eslint/utils");
6245
6522
  var ts2 = __toESM(require("typescript"), 1);
6246
6523
  var IGNORE_PATTERNS2 = [
6247
6524
  /[\\/]generated[\\/]/,
@@ -6255,11 +6532,11 @@ function isIgnoredFile2(filename, sourceText) {
6255
6532
  }
6256
6533
  return /@generated\b/.test(sourceText.slice(0, 1024));
6257
6534
  }
6258
- function isZodModule(source) {
6535
+ function isZodModule2(source) {
6259
6536
  return /(^|[/@-])zod([/-]|$)/.test(source);
6260
6537
  }
6261
6538
  function unwrap3(node) {
6262
- if (node.type === import_utils45.AST_NODE_TYPES.TSAsExpression || node.type === import_utils45.AST_NODE_TYPES.TSSatisfiesExpression) {
6539
+ if (node.type === import_utils50.AST_NODE_TYPES.TSAsExpression || node.type === import_utils50.AST_NODE_TYPES.TSSatisfiesExpression) {
6263
6540
  return unwrap3(node.expression);
6264
6541
  }
6265
6542
  return node;
@@ -6267,14 +6544,14 @@ function unwrap3(node) {
6267
6544
  function stringValueTexts(node, sourceCode) {
6268
6545
  const texts = [];
6269
6546
  for (const prop of node.properties) {
6270
- if (prop.type !== import_utils45.AST_NODE_TYPES.Property) {
6547
+ if (prop.type !== import_utils50.AST_NODE_TYPES.Property) {
6271
6548
  return null;
6272
6549
  }
6273
6550
  if (prop.computed || prop.shorthand || prop.method || prop.kind !== "init") {
6274
6551
  return null;
6275
6552
  }
6276
6553
  const value = prop.value;
6277
- if (value.type !== import_utils45.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
6554
+ if (value.type !== import_utils50.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
6278
6555
  return null;
6279
6556
  }
6280
6557
  const text = sourceCode.getText(value);
@@ -6290,7 +6567,7 @@ function resolvesToLocalEnum(node, scope) {
6290
6567
  const variable = current.variables.find((v) => v.name === node.name);
6291
6568
  if (variable !== void 0) {
6292
6569
  return variable.defs.some(
6293
- (def) => def.node.type === import_utils45.AST_NODE_TYPES.TSEnumDeclaration
6570
+ (def) => def.node.type === import_utils50.AST_NODE_TYPES.TSEnumDeclaration
6294
6571
  );
6295
6572
  }
6296
6573
  current = current.upper;
@@ -6310,7 +6587,7 @@ function resolvesToImportedEnum(node, services) {
6310
6587
  }
6311
6588
  return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
6312
6589
  }
6313
- var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6590
+ var no_zod_native_enum_default = import_utils50.ESLintUtils.RuleCreator(
6314
6591
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6315
6592
  )({
6316
6593
  name: "no-zod-native-enum",
@@ -6337,32 +6614,32 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6337
6614
  }
6338
6615
  let services;
6339
6616
  try {
6340
- services = import_utils45.ESLintUtils.getParserServices(context);
6617
+ services = import_utils50.ESLintUtils.getParserServices(context);
6341
6618
  } catch {
6342
6619
  services = null;
6343
6620
  }
6344
6621
  const zodImportedNames = /* @__PURE__ */ new Map();
6345
6622
  function isZodMemberCall(node, api) {
6346
6623
  const callee = node.callee;
6347
- if (callee.type === import_utils45.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils45.AST_NODE_TYPES.Identifier) {
6624
+ if (callee.type === import_utils50.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils50.AST_NODE_TYPES.Identifier) {
6348
6625
  return callee.property.name === api;
6349
6626
  }
6350
- if (callee.type === import_utils45.AST_NODE_TYPES.Identifier) {
6627
+ if (callee.type === import_utils50.AST_NODE_TYPES.Identifier) {
6351
6628
  return zodImportedNames.get(callee.name) === api;
6352
6629
  }
6353
6630
  return false;
6354
6631
  }
6355
6632
  function buildFix(node) {
6356
6633
  const callee = node.callee;
6357
- if (callee.type !== import_utils45.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils45.AST_NODE_TYPES.Identifier) {
6634
+ if (callee.type !== import_utils50.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils50.AST_NODE_TYPES.Identifier) {
6358
6635
  return null;
6359
6636
  }
6360
6637
  const arg = node.arguments[0];
6361
- if (arg === void 0 || node.arguments.length !== 1 || arg.type === import_utils45.AST_NODE_TYPES.SpreadElement) {
6638
+ if (arg === void 0 || node.arguments.length !== 1 || arg.type === import_utils50.AST_NODE_TYPES.SpreadElement) {
6362
6639
  return null;
6363
6640
  }
6364
6641
  const inner = unwrap3(arg);
6365
- if (inner.type !== import_utils45.AST_NODE_TYPES.ObjectExpression) {
6642
+ if (inner.type !== import_utils50.AST_NODE_TYPES.ObjectExpression) {
6366
6643
  return null;
6367
6644
  }
6368
6645
  const values = stringValueTexts(inner, sourceCode);
@@ -6378,11 +6655,11 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6378
6655
  }
6379
6656
  return {
6380
6657
  ImportDeclaration(node) {
6381
- if (!isZodModule(node.source.value)) {
6658
+ if (!isZodModule2(node.source.value)) {
6382
6659
  return;
6383
6660
  }
6384
6661
  for (const spec of node.specifiers) {
6385
- if (spec.type === import_utils45.AST_NODE_TYPES.ImportSpecifier && spec.imported.type === import_utils45.AST_NODE_TYPES.Identifier) {
6662
+ if (spec.type === import_utils50.AST_NODE_TYPES.ImportSpecifier && spec.imported.type === import_utils50.AST_NODE_TYPES.Identifier) {
6386
6663
  zodImportedNames.set(spec.local.name, spec.imported.name);
6387
6664
  }
6388
6665
  }
@@ -6401,7 +6678,7 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6401
6678
  return;
6402
6679
  }
6403
6680
  const arg = node.arguments[0];
6404
- if (arg === void 0 || arg.type !== import_utils45.AST_NODE_TYPES.Identifier) {
6681
+ if (arg === void 0 || arg.type !== import_utils50.AST_NODE_TYPES.Identifier) {
6405
6682
  return;
6406
6683
  }
6407
6684
  const isEnum = resolvesToLocalEnum(arg, sourceCode.getScope(arg)) || services !== null && resolvesToImportedEnum(arg, services);
@@ -6418,7 +6695,7 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6418
6695
  });
6419
6696
 
6420
6697
  // src/rules/prefer-module-level-constant.ts
6421
- var import_utils46 = require("@typescript-eslint/utils");
6698
+ var import_utils51 = require("@typescript-eslint/utils");
6422
6699
  var DEFAULT_MIN_ELEMENTS = 3;
6423
6700
  var MAX_LITERAL_DEPTH = 4;
6424
6701
  var IGNORE_PATTERNS3 = [
@@ -6453,10 +6730,10 @@ var MUTATING_METHODS = /* @__PURE__ */ new Set([
6453
6730
  // Object-ish escape hatches
6454
6731
  "assign"
6455
6732
  ]);
6456
- var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
6457
- import_utils46.AST_NODE_TYPES.FunctionDeclaration,
6458
- import_utils46.AST_NODE_TYPES.FunctionExpression,
6459
- import_utils46.AST_NODE_TYPES.ArrowFunctionExpression
6733
+ var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6734
+ import_utils51.AST_NODE_TYPES.FunctionDeclaration,
6735
+ import_utils51.AST_NODE_TYPES.FunctionExpression,
6736
+ import_utils51.AST_NODE_TYPES.ArrowFunctionExpression
6460
6737
  ]);
6461
6738
  var COLLECTION_CONSTRUCTORS = /* @__PURE__ */ new Set(["Set", "Map"]);
6462
6739
  function isIgnoredFile3(filename, sourceText) {
@@ -6469,13 +6746,13 @@ function isTestFile2(filename) {
6469
6746
  return TEST_FILE_PATTERNS.some((re) => re.test(filename));
6470
6747
  }
6471
6748
  function unwrap4(node) {
6472
- if (node.type === import_utils46.AST_NODE_TYPES.TSAsExpression || node.type === import_utils46.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils46.AST_NODE_TYPES.TSNonNullExpression) {
6749
+ if (node.type === import_utils51.AST_NODE_TYPES.TSAsExpression || node.type === import_utils51.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils51.AST_NODE_TYPES.TSNonNullExpression) {
6473
6750
  return unwrap4(node.expression);
6474
6751
  }
6475
6752
  return node;
6476
6753
  }
6477
6754
  function isRegexLiteral(node) {
6478
- return node.type === import_utils46.AST_NODE_TYPES.Literal && "regex" in node && node.regex !== void 0;
6755
+ return node.type === import_utils51.AST_NODE_TYPES.Literal && "regex" in node && node.regex !== void 0;
6479
6756
  }
6480
6757
  function isLiteralOnly(node, depth) {
6481
6758
  if (depth > MAX_LITERAL_DEPTH) {
@@ -6483,29 +6760,29 @@ function isLiteralOnly(node, depth) {
6483
6760
  }
6484
6761
  const inner = unwrap4(node);
6485
6762
  switch (inner.type) {
6486
- case import_utils46.AST_NODE_TYPES.Literal: {
6763
+ case import_utils51.AST_NODE_TYPES.Literal: {
6487
6764
  return true;
6488
6765
  }
6489
- case import_utils46.AST_NODE_TYPES.TemplateLiteral: {
6766
+ case import_utils51.AST_NODE_TYPES.TemplateLiteral: {
6490
6767
  return inner.expressions.length === 0;
6491
6768
  }
6492
- case import_utils46.AST_NODE_TYPES.UnaryExpression: {
6493
- return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === import_utils46.AST_NODE_TYPES.Literal && typeof inner.argument.value === "number";
6769
+ case import_utils51.AST_NODE_TYPES.UnaryExpression: {
6770
+ return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === import_utils51.AST_NODE_TYPES.Literal && typeof inner.argument.value === "number";
6494
6771
  }
6495
- case import_utils46.AST_NODE_TYPES.ArrayExpression: {
6772
+ case import_utils51.AST_NODE_TYPES.ArrayExpression: {
6496
6773
  return inner.elements.every(
6497
- (el) => el !== null && el.type !== import_utils46.AST_NODE_TYPES.SpreadElement && isLiteralOnly(el, depth + 1)
6774
+ (el) => el !== null && el.type !== import_utils51.AST_NODE_TYPES.SpreadElement && isLiteralOnly(el, depth + 1)
6498
6775
  );
6499
6776
  }
6500
- case import_utils46.AST_NODE_TYPES.ObjectExpression: {
6777
+ case import_utils51.AST_NODE_TYPES.ObjectExpression: {
6501
6778
  return inner.properties.every((prop) => {
6502
- if (prop.type !== import_utils46.AST_NODE_TYPES.Property) {
6779
+ if (prop.type !== import_utils51.AST_NODE_TYPES.Property) {
6503
6780
  return false;
6504
6781
  }
6505
6782
  if (prop.shorthand || prop.method || prop.kind !== "init") {
6506
6783
  return false;
6507
6784
  }
6508
- if (prop.computed && prop.key.type !== import_utils46.AST_NODE_TYPES.Literal) {
6785
+ if (prop.computed && prop.key.type !== import_utils51.AST_NODE_TYPES.Literal) {
6509
6786
  return false;
6510
6787
  }
6511
6788
  return isLiteralOnly(prop.value, depth + 1);
@@ -6518,7 +6795,7 @@ function isLiteralOnly(node, depth) {
6518
6795
  }
6519
6796
  function unwrapObjectFreeze(node) {
6520
6797
  const inner = unwrap4(node);
6521
- if (inner.type === import_utils46.AST_NODE_TYPES.CallExpression && inner.callee.type === import_utils46.AST_NODE_TYPES.MemberExpression && !inner.callee.computed && inner.callee.object.type === import_utils46.AST_NODE_TYPES.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === import_utils46.AST_NODE_TYPES.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== import_utils46.AST_NODE_TYPES.SpreadElement) {
6798
+ if (inner.type === import_utils51.AST_NODE_TYPES.CallExpression && inner.callee.type === import_utils51.AST_NODE_TYPES.MemberExpression && !inner.callee.computed && inner.callee.object.type === import_utils51.AST_NODE_TYPES.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === import_utils51.AST_NODE_TYPES.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== import_utils51.AST_NODE_TYPES.SpreadElement) {
6522
6799
  return unwrap4(inner.arguments[0]);
6523
6800
  }
6524
6801
  return inner;
@@ -6534,19 +6811,19 @@ function classify(init, checkRegex) {
6534
6811
  }
6535
6812
  return { kind: "regex", size: 1 };
6536
6813
  }
6537
- if (node.type === import_utils46.AST_NODE_TYPES.ArrayExpression) {
6814
+ if (node.type === import_utils51.AST_NODE_TYPES.ArrayExpression) {
6538
6815
  return isLiteralOnly(node, 0) ? { kind: "array", size: node.elements.length } : null;
6539
6816
  }
6540
- if (node.type === import_utils46.AST_NODE_TYPES.ObjectExpression) {
6817
+ if (node.type === import_utils51.AST_NODE_TYPES.ObjectExpression) {
6541
6818
  return isLiteralOnly(node, 0) ? { kind: "object", size: node.properties.length } : null;
6542
6819
  }
6543
- if (node.type === import_utils46.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils46.AST_NODE_TYPES.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6820
+ if (node.type === import_utils51.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils51.AST_NODE_TYPES.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6544
6821
  const arg = node.arguments[0];
6545
- if (node.arguments.length !== 1 || arg === void 0 || arg.type === import_utils46.AST_NODE_TYPES.SpreadElement) {
6822
+ if (node.arguments.length !== 1 || arg === void 0 || arg.type === import_utils51.AST_NODE_TYPES.SpreadElement) {
6546
6823
  return null;
6547
6824
  }
6548
6825
  const entries = unwrap4(arg);
6549
- if (entries.type !== import_utils46.AST_NODE_TYPES.ArrayExpression) {
6826
+ if (entries.type !== import_utils51.AST_NODE_TYPES.ArrayExpression) {
6550
6827
  return null;
6551
6828
  }
6552
6829
  return isLiteralOnly(entries, 0) ? { kind: node.callee.name === "Set" ? "Set" : "Map", size: entries.elements.length } : null;
@@ -6556,7 +6833,7 @@ function classify(init, checkRegex) {
6556
6833
  function enclosingFunction2(node) {
6557
6834
  let current = node.parent;
6558
6835
  while (current !== void 0 && current !== null) {
6559
- if (FUNCTION_TYPES3.has(current.type)) {
6836
+ if (FUNCTION_TYPES4.has(current.type)) {
6560
6837
  return current;
6561
6838
  }
6562
6839
  current = current.parent;
@@ -6575,10 +6852,10 @@ var NON_RETAINING_BUILTINS = /* @__PURE__ */ new Map(
6575
6852
  );
6576
6853
  function isNonRetainingBuiltinCall(node, argument) {
6577
6854
  const callee = node.callee;
6578
- if (callee.type === import_utils46.AST_NODE_TYPES.Identifier && callee.name === "structuredClone") {
6855
+ if (callee.type === import_utils51.AST_NODE_TYPES.Identifier && callee.name === "structuredClone") {
6579
6856
  return true;
6580
6857
  }
6581
- if (callee.type !== import_utils46.AST_NODE_TYPES.MemberExpression || callee.computed || callee.object.type !== import_utils46.AST_NODE_TYPES.Identifier || callee.property.type !== import_utils46.AST_NODE_TYPES.Identifier) {
6858
+ if (callee.type !== import_utils51.AST_NODE_TYPES.MemberExpression || callee.computed || callee.object.type !== import_utils51.AST_NODE_TYPES.Identifier || callee.property.type !== import_utils51.AST_NODE_TYPES.Identifier) {
6582
6859
  return false;
6583
6860
  }
6584
6861
  const members = NON_RETAINING_BUILTINS.get(callee.object.name);
@@ -6592,43 +6869,43 @@ function isNonRetainingBuiltinCall(node, argument) {
6592
6869
  }
6593
6870
  function isSafeRead(identifier) {
6594
6871
  const parent = identifier.parent;
6595
- if (parent.type === import_utils46.AST_NODE_TYPES.MemberExpression) {
6872
+ if (parent.type === import_utils51.AST_NODE_TYPES.MemberExpression) {
6596
6873
  if (parent.object !== identifier) {
6597
6874
  return true;
6598
6875
  }
6599
6876
  const grandparent = parent.parent;
6600
- if (grandparent.type === import_utils46.AST_NODE_TYPES.AssignmentExpression && grandparent.left === parent) {
6877
+ if (grandparent.type === import_utils51.AST_NODE_TYPES.AssignmentExpression && grandparent.left === parent) {
6601
6878
  return false;
6602
6879
  }
6603
- if (grandparent.type === import_utils46.AST_NODE_TYPES.UpdateExpression) {
6880
+ if (grandparent.type === import_utils51.AST_NODE_TYPES.UpdateExpression) {
6604
6881
  return false;
6605
6882
  }
6606
- if (grandparent.type === import_utils46.AST_NODE_TYPES.UnaryExpression && grandparent.operator === "delete") {
6883
+ if (grandparent.type === import_utils51.AST_NODE_TYPES.UnaryExpression && grandparent.operator === "delete") {
6607
6884
  return false;
6608
6885
  }
6609
- if (!parent.computed && parent.property.type === import_utils46.AST_NODE_TYPES.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === import_utils46.AST_NODE_TYPES.CallExpression && grandparent.callee === parent) {
6886
+ if (!parent.computed && parent.property.type === import_utils51.AST_NODE_TYPES.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === import_utils51.AST_NODE_TYPES.CallExpression && grandparent.callee === parent) {
6610
6887
  return false;
6611
6888
  }
6612
6889
  return true;
6613
6890
  }
6614
- if (parent.type === import_utils46.AST_NODE_TYPES.ForOfStatement && parent.right === identifier) {
6891
+ if (parent.type === import_utils51.AST_NODE_TYPES.ForOfStatement && parent.right === identifier) {
6615
6892
  return true;
6616
6893
  }
6617
- if (parent.type === import_utils46.AST_NODE_TYPES.SpreadElement) {
6894
+ if (parent.type === import_utils51.AST_NODE_TYPES.SpreadElement) {
6618
6895
  return true;
6619
6896
  }
6620
- if (parent.type === import_utils46.AST_NODE_TYPES.BinaryExpression) {
6897
+ if (parent.type === import_utils51.AST_NODE_TYPES.BinaryExpression) {
6621
6898
  return true;
6622
6899
  }
6623
- if (parent.type === import_utils46.AST_NODE_TYPES.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6900
+ if (parent.type === import_utils51.AST_NODE_TYPES.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6624
6901
  return true;
6625
6902
  }
6626
- if (parent.type === import_utils46.AST_NODE_TYPES.UnaryExpression && parent.operator !== "delete") {
6903
+ if (parent.type === import_utils51.AST_NODE_TYPES.UnaryExpression && parent.operator !== "delete") {
6627
6904
  return true;
6628
6905
  }
6629
6906
  return false;
6630
6907
  }
6631
- var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreator(
6908
+ var prefer_module_level_constant_default = import_utils51.ESLintUtils.RuleCreator(
6632
6909
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6633
6910
  )({
6634
6911
  name: "prefer-module-level-constant",
@@ -6680,7 +6957,7 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6680
6957
  if (reference.isWrite()) {
6681
6958
  return false;
6682
6959
  }
6683
- if (reference.identifier.type !== import_utils46.AST_NODE_TYPES.Identifier) {
6960
+ if (reference.identifier.type !== import_utils51.AST_NODE_TYPES.Identifier) {
6684
6961
  return false;
6685
6962
  }
6686
6963
  if (!isSafeRead(reference.identifier)) {
@@ -6692,10 +6969,10 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6692
6969
  return {
6693
6970
  VariableDeclarator(node) {
6694
6971
  const declaration = node.parent;
6695
- if (declaration.type !== import_utils46.AST_NODE_TYPES.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6972
+ if (declaration.type !== import_utils51.AST_NODE_TYPES.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6696
6973
  return;
6697
6974
  }
6698
- if (node.id.type !== import_utils46.AST_NODE_TYPES.Identifier || node.init === null) {
6975
+ if (node.id.type !== import_utils51.AST_NODE_TYPES.Identifier || node.init === null) {
6699
6976
  return;
6700
6977
  }
6701
6978
  if (enclosingFunction2(node) === null) {
@@ -6722,7 +6999,7 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6722
6999
  });
6723
7000
 
6724
7001
  // src/rules/jsdoc-restates-signature.ts
6725
- var import_utils47 = require("@typescript-eslint/utils");
7002
+ var import_utils52 = require("@typescript-eslint/utils");
6726
7003
  var VALUE_TAGS = /* @__PURE__ */ new Set([
6727
7004
  "alpha",
6728
7005
  "author",
@@ -6805,30 +7082,30 @@ function declarationNames(node) {
6805
7082
  switch (node.type) {
6806
7083
  // `export function f()` — the JSDoc sits above the `export`, so the token
6807
7084
  // after it resolves to the wrapper, not to the thing being documented.
6808
- case import_utils47.AST_NODE_TYPES.ExportNamedDeclaration:
6809
- case import_utils47.AST_NODE_TYPES.ExportDefaultDeclaration:
7085
+ case import_utils52.AST_NODE_TYPES.ExportNamedDeclaration:
7086
+ case import_utils52.AST_NODE_TYPES.ExportDefaultDeclaration:
6810
7087
  return node.declaration == null ? null : declarationNames(node.declaration);
6811
- case import_utils47.AST_NODE_TYPES.FunctionDeclaration:
6812
- case import_utils47.AST_NODE_TYPES.TSDeclareFunction:
7088
+ case import_utils52.AST_NODE_TYPES.FunctionDeclaration:
7089
+ case import_utils52.AST_NODE_TYPES.TSDeclareFunction:
6813
7090
  return node.id === null ? null : { name: node.id.name, params: paramNames(node.params) };
6814
- case import_utils47.AST_NODE_TYPES.ClassDeclaration:
6815
- case import_utils47.AST_NODE_TYPES.TSInterfaceDeclaration:
6816
- case import_utils47.AST_NODE_TYPES.TSTypeAliasDeclaration:
6817
- case import_utils47.AST_NODE_TYPES.TSEnumDeclaration:
7091
+ case import_utils52.AST_NODE_TYPES.ClassDeclaration:
7092
+ case import_utils52.AST_NODE_TYPES.TSInterfaceDeclaration:
7093
+ case import_utils52.AST_NODE_TYPES.TSTypeAliasDeclaration:
7094
+ case import_utils52.AST_NODE_TYPES.TSEnumDeclaration:
6818
7095
  return node.id === null ? null : { name: node.id.name, params: [] };
6819
- case import_utils47.AST_NODE_TYPES.VariableDeclaration: {
7096
+ case import_utils52.AST_NODE_TYPES.VariableDeclaration: {
6820
7097
  const declarator = node.declarations[0];
6821
- if (declarator === void 0 || declarator.id.type !== import_utils47.AST_NODE_TYPES.Identifier) return null;
7098
+ if (declarator === void 0 || declarator.id.type !== import_utils52.AST_NODE_TYPES.Identifier) return null;
6822
7099
  const init = declarator.init;
6823
- const params = init != null && (init.type === import_utils47.AST_NODE_TYPES.ArrowFunctionExpression || init.type === import_utils47.AST_NODE_TYPES.FunctionExpression) ? paramNames(init.params) : [];
7100
+ const params = init != null && (init.type === import_utils52.AST_NODE_TYPES.ArrowFunctionExpression || init.type === import_utils52.AST_NODE_TYPES.FunctionExpression) ? paramNames(init.params) : [];
6824
7101
  return { name: declarator.id.name, params };
6825
7102
  }
6826
- case import_utils47.AST_NODE_TYPES.MethodDefinition:
6827
- case import_utils47.AST_NODE_TYPES.PropertyDefinition:
6828
- case import_utils47.AST_NODE_TYPES.TSMethodSignature:
6829
- case import_utils47.AST_NODE_TYPES.TSPropertySignature: {
6830
- if (node.key.type !== import_utils47.AST_NODE_TYPES.Identifier) return null;
6831
- const params = node.type === import_utils47.AST_NODE_TYPES.MethodDefinition ? paramNames(node.value.params) : node.type === import_utils47.AST_NODE_TYPES.TSMethodSignature ? paramNames(node.params) : [];
7103
+ case import_utils52.AST_NODE_TYPES.MethodDefinition:
7104
+ case import_utils52.AST_NODE_TYPES.PropertyDefinition:
7105
+ case import_utils52.AST_NODE_TYPES.TSMethodSignature:
7106
+ case import_utils52.AST_NODE_TYPES.TSPropertySignature: {
7107
+ if (node.key.type !== import_utils52.AST_NODE_TYPES.Identifier) return null;
7108
+ const params = node.type === import_utils52.AST_NODE_TYPES.MethodDefinition ? paramNames(node.value.params) : node.type === import_utils52.AST_NODE_TYPES.TSMethodSignature ? paramNames(node.params) : [];
6832
7109
  return { name: node.key.name, params };
6833
7110
  }
6834
7111
  default:
@@ -6838,9 +7115,9 @@ function declarationNames(node) {
6838
7115
  function paramNames(params) {
6839
7116
  const names = [];
6840
7117
  for (const param of params) {
6841
- const target = param.type === import_utils47.AST_NODE_TYPES.AssignmentPattern ? param.left : param;
6842
- if (target.type === import_utils47.AST_NODE_TYPES.Identifier) names.push(target.name);
6843
- else if (target.type === import_utils47.AST_NODE_TYPES.TSParameterProperty) continue;
7118
+ const target = param.type === import_utils52.AST_NODE_TYPES.AssignmentPattern ? param.left : param;
7119
+ if (target.type === import_utils52.AST_NODE_TYPES.Identifier) names.push(target.name);
7120
+ else if (target.type === import_utils52.AST_NODE_TYPES.TSParameterProperty) continue;
6844
7121
  }
6845
7122
  return names;
6846
7123
  }
@@ -6849,7 +7126,7 @@ function tokensOf(names) {
6849
7126
  for (const name of names) for (const part of splitIdentifier(name)) tokens.add(part);
6850
7127
  return tokens;
6851
7128
  }
6852
- var jsdoc_restates_signature_default = import_utils47.ESLintUtils.RuleCreator(
7129
+ var jsdoc_restates_signature_default = import_utils52.ESLintUtils.RuleCreator(
6853
7130
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6854
7131
  )({
6855
7132
  name: "jsdoc-restates-signature",
@@ -6885,7 +7162,7 @@ var jsdoc_restates_signature_default = import_utils47.ESLintUtils.RuleCreator(
6885
7162
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) continue;
6886
7163
  let node = sourceCode.getNodeByRangeIndex(token.range[0]);
6887
7164
  let declaration = null;
6888
- while (node != null && node.type !== import_utils47.AST_NODE_TYPES.Program) {
7165
+ while (node != null && node.type !== import_utils52.AST_NODE_TYPES.Program) {
6889
7166
  declaration = declarationNames(node);
6890
7167
  if (declaration !== null) break;
6891
7168
  node = node.parent ?? null;
@@ -6940,7 +7217,7 @@ var jsdoc_restates_signature_default = import_utils47.ESLintUtils.RuleCreator(
6940
7217
  });
6941
7218
 
6942
7219
  // src/rules/no-restated-comment.ts
6943
- var import_utils48 = require("@typescript-eslint/utils");
7220
+ var import_utils53 = require("@typescript-eslint/utils");
6944
7221
  var MAX_WORDS = 8;
6945
7222
  var MIN_CONTENT_TOKENS = 2;
6946
7223
  var DIRECTIVE_RE3 = /^(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|todo\b|fixme\b|hack\b|xxx\b)/i;
@@ -6964,7 +7241,7 @@ function headsSiblingRun(node) {
6964
7241
  const next = index >= 0 ? body[index + 1] : void 0;
6965
7242
  return next !== void 0 && next.type === node.type;
6966
7243
  }
6967
- var no_restated_comment_default = import_utils48.ESLintUtils.RuleCreator(
7244
+ var no_restated_comment_default = import_utils53.ESLintUtils.RuleCreator(
6968
7245
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6969
7246
  )({
6970
7247
  name: "no-restated-comment",
@@ -6992,7 +7269,7 @@ var no_restated_comment_default = import_utils48.ESLintUtils.RuleCreator(
6992
7269
  function labelsASiblingRun(comment) {
6993
7270
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
6994
7271
  if (token === null) return false;
6995
- for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils48.AST_NODE_TYPES.Program; node = node.parent) {
7272
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils53.AST_NODE_TYPES.Program; node = node.parent) {
6996
7273
  if (headsSiblingRun(node)) return true;
6997
7274
  }
6998
7275
  return false;
@@ -7032,7 +7309,7 @@ var no_restated_comment_default = import_utils48.ESLintUtils.RuleCreator(
7032
7309
  });
7033
7310
 
7034
7311
  // src/rules/trailing-value-narration.ts
7035
- var import_utils49 = require("@typescript-eslint/utils");
7312
+ var import_utils54 = require("@typescript-eslint/utils");
7036
7313
  var NUMBER_RE = /(?<![\w.])(\d+(?:\.\d+)?)(?![\w.])/g;
7037
7314
  var WORD_RE3 = /[A-Za-z]+(?:'[a-z]+)?|\d+(?:\.\d+)?/g;
7038
7315
  var UNIT_WORDS = /* @__PURE__ */ new Set([
@@ -7116,7 +7393,7 @@ function narratesValue(body, code) {
7116
7393
  (word) => STOPWORDS3.has(word) || UNIT_WORDS.has(word) || commentNumbers.has(word) || identifiers.has(word) || stems.has(stem(word))
7117
7394
  );
7118
7395
  }
7119
- var trailing_value_narration_default = import_utils49.ESLintUtils.RuleCreator(
7396
+ var trailing_value_narration_default = import_utils54.ESLintUtils.RuleCreator(
7120
7397
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7121
7398
  )({
7122
7399
  name: "trailing-value-narration",
@@ -7157,7 +7434,7 @@ var trailing_value_narration_default = import_utils49.ESLintUtils.RuleCreator(
7157
7434
  });
7158
7435
 
7159
7436
  // src/rules/no-tautological-expect.ts
7160
- var import_utils50 = require("@typescript-eslint/utils");
7437
+ var import_utils55 = require("@typescript-eslint/utils");
7161
7438
  var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
7162
7439
  var ZERO_ARG_MATCHERS = /* @__PURE__ */ new Set([
7163
7440
  "toBeDefined",
@@ -7171,17 +7448,17 @@ var OPERAND_PREVIEW_CHARS = 40;
7171
7448
  var NUMERIC_SIGNS = /* @__PURE__ */ new Set(["-", "+"]);
7172
7449
  function isLiteral(node) {
7173
7450
  switch (node.type) {
7174
- case import_utils50.AST_NODE_TYPES.Literal:
7451
+ case import_utils55.AST_NODE_TYPES.Literal:
7175
7452
  return true;
7176
- case import_utils50.AST_NODE_TYPES.TemplateLiteral:
7453
+ case import_utils55.AST_NODE_TYPES.TemplateLiteral:
7177
7454
  return node.expressions.length === 0;
7178
- case import_utils50.AST_NODE_TYPES.UnaryExpression:
7455
+ case import_utils55.AST_NODE_TYPES.UnaryExpression:
7179
7456
  return NUMERIC_SIGNS.has(node.operator) && isLiteral(node.argument);
7180
- case import_utils50.AST_NODE_TYPES.ArrayExpression:
7457
+ case import_utils55.AST_NODE_TYPES.ArrayExpression:
7181
7458
  return node.elements.every((element) => element !== null && isLiteral(element));
7182
- case import_utils50.AST_NODE_TYPES.ObjectExpression:
7459
+ case import_utils55.AST_NODE_TYPES.ObjectExpression:
7183
7460
  return node.properties.every(
7184
- (property) => property.type === import_utils50.AST_NODE_TYPES.Property && !property.computed && isLiteral(property.value)
7461
+ (property) => property.type === import_utils55.AST_NODE_TYPES.Property && !property.computed && isLiteral(property.value)
7185
7462
  );
7186
7463
  default:
7187
7464
  return false;
@@ -7189,12 +7466,12 @@ function isLiteral(node) {
7189
7466
  }
7190
7467
  function expectOperand(callee) {
7191
7468
  const receiver = callee.object;
7192
- if (receiver.type !== import_utils50.AST_NODE_TYPES.CallExpression || receiver.callee.type !== import_utils50.AST_NODE_TYPES.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7469
+ if (receiver.type !== import_utils55.AST_NODE_TYPES.CallExpression || receiver.callee.type !== import_utils55.AST_NODE_TYPES.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7193
7470
  return null;
7194
7471
  }
7195
7472
  return receiver.arguments[0] ?? null;
7196
7473
  }
7197
- var no_tautological_expect_default = import_utils50.ESLintUtils.RuleCreator(
7474
+ var no_tautological_expect_default = import_utils55.ESLintUtils.RuleCreator(
7198
7475
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7199
7476
  )({
7200
7477
  name: "no-tautological-expect",
@@ -7221,10 +7498,10 @@ var no_tautological_expect_default = import_utils50.ESLintUtils.RuleCreator(
7221
7498
  return {
7222
7499
  CallExpression(node) {
7223
7500
  const callee = node.callee;
7224
- if (callee.type !== import_utils50.AST_NODE_TYPES.MemberExpression || callee.computed) {
7501
+ if (callee.type !== import_utils55.AST_NODE_TYPES.MemberExpression || callee.computed) {
7225
7502
  return;
7226
7503
  }
7227
- if (callee.property.type !== import_utils50.AST_NODE_TYPES.Identifier) {
7504
+ if (callee.property.type !== import_utils55.AST_NODE_TYPES.Identifier) {
7228
7505
  return;
7229
7506
  }
7230
7507
  const matcher = callee.property.name;
@@ -7258,26 +7535,26 @@ var no_tautological_expect_default = import_utils50.ESLintUtils.RuleCreator(
7258
7535
  });
7259
7536
 
7260
7537
  // src/rules/require-interface-for-injected-service.ts
7261
- var import_utils51 = require("@typescript-eslint/utils");
7538
+ var import_utils56 = require("@typescript-eslint/utils");
7262
7539
  var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Props|Args|Env|Environment|Callbacks|Flags)$/;
7263
7540
  var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
7264
7541
  var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
7265
7542
  var TRANSPORT_WRAPPER_NAME_RE = /Client$/;
7266
7543
  var ROUTER_FACTORY_NAME = "Router";
7267
7544
  var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
7268
- var isExportedClass = (node) => node.parent.type === import_utils51.AST_NODE_TYPES.ExportNamedDeclaration || node.parent.type === import_utils51.AST_NODE_TYPES.ExportDefaultDeclaration;
7269
- var qualifiedName = (name) => name.type === import_utils51.AST_NODE_TYPES.Identifier ? name.name : name.type === import_utils51.AST_NODE_TYPES.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7545
+ var isExportedClass = (node) => node.parent.type === import_utils56.AST_NODE_TYPES.ExportNamedDeclaration || node.parent.type === import_utils56.AST_NODE_TYPES.ExportDefaultDeclaration;
7546
+ var qualifiedName = (name) => name.type === import_utils56.AST_NODE_TYPES.Identifier ? name.name : name.type === import_utils56.AST_NODE_TYPES.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7270
7547
  var typeReferenceName = (annotated) => {
7271
7548
  let target = annotated;
7272
- if (target.type === import_utils51.AST_NODE_TYPES.TSParameterProperty) target = target.parameter;
7273
- if (target.type === import_utils51.AST_NODE_TYPES.AssignmentPattern) target = target.left;
7274
- if (target.type !== import_utils51.AST_NODE_TYPES.Identifier) return null;
7549
+ if (target.type === import_utils56.AST_NODE_TYPES.TSParameterProperty) target = target.parameter;
7550
+ if (target.type === import_utils56.AST_NODE_TYPES.AssignmentPattern) target = target.left;
7551
+ if (target.type !== import_utils56.AST_NODE_TYPES.Identifier) return null;
7275
7552
  const annotation = target.typeAnnotation?.typeAnnotation;
7276
- if (annotation === void 0 || annotation.type !== import_utils51.AST_NODE_TYPES.TSTypeReference) {
7553
+ if (annotation === void 0 || annotation.type !== import_utils56.AST_NODE_TYPES.TSTypeReference) {
7277
7554
  return null;
7278
7555
  }
7279
7556
  const { typeName } = annotation;
7280
- const rightmost = typeName.type === import_utils51.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils51.AST_NODE_TYPES.TSQualifiedName ? typeName.right.name : null;
7557
+ const rightmost = typeName.type === import_utils56.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils56.AST_NODE_TYPES.TSQualifiedName ? typeName.right.name : null;
7281
7558
  if (rightmost === null) return null;
7282
7559
  return { name: target.name, typeName: rightmost, display: qualifiedName(typeName) };
7283
7560
  };
@@ -7287,17 +7564,17 @@ var readConstructor = (ctor) => {
7287
7564
  let constructedFields = 0;
7288
7565
  if (body !== null && body !== void 0) {
7289
7566
  for (const statement of body.body) {
7290
- if (statement.type !== import_utils51.AST_NODE_TYPES.ExpressionStatement) continue;
7567
+ if (statement.type !== import_utils56.AST_NODE_TYPES.ExpressionStatement) continue;
7291
7568
  const expression = statement.expression;
7292
- if (expression.type !== import_utils51.AST_NODE_TYPES.AssignmentExpression || expression.operator !== "=" || expression.left.type !== import_utils51.AST_NODE_TYPES.MemberExpression || expression.left.object.type !== import_utils51.AST_NODE_TYPES.ThisExpression) {
7569
+ if (expression.type !== import_utils56.AST_NODE_TYPES.AssignmentExpression || expression.operator !== "=" || expression.left.type !== import_utils56.AST_NODE_TYPES.MemberExpression || expression.left.object.type !== import_utils56.AST_NODE_TYPES.ThisExpression) {
7293
7570
  continue;
7294
7571
  }
7295
7572
  const source = expression.right;
7296
- if (source.type === import_utils51.AST_NODE_TYPES.NewExpression) {
7573
+ if (source.type === import_utils56.AST_NODE_TYPES.NewExpression) {
7297
7574
  constructedFields += 1;
7298
- } else if (source.type === import_utils51.AST_NODE_TYPES.Identifier) {
7575
+ } else if (source.type === import_utils56.AST_NODE_TYPES.Identifier) {
7299
7576
  storedFrom.add(source.name);
7300
- } else if (source.type === import_utils51.AST_NODE_TYPES.MemberExpression && source.object.type === import_utils51.AST_NODE_TYPES.Identifier) {
7577
+ } else if (source.type === import_utils56.AST_NODE_TYPES.MemberExpression && source.object.type === import_utils56.AST_NODE_TYPES.Identifier) {
7301
7578
  storedFrom.add(source.object.name);
7302
7579
  }
7303
7580
  }
@@ -7306,7 +7583,7 @@ var readConstructor = (ctor) => {
7306
7583
  for (const parameter of ctor.value.params) {
7307
7584
  const reference = typeReferenceName(parameter);
7308
7585
  if (reference === null) continue;
7309
- const stored = parameter.type === import_utils51.AST_NODE_TYPES.TSParameterProperty || storedFrom.has(reference.name);
7586
+ const stored = parameter.type === import_utils56.AST_NODE_TYPES.TSParameterProperty || storedFrom.has(reference.name);
7310
7587
  if (!stored) continue;
7311
7588
  if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
7312
7589
  if (CONFIGISH_NAME_RE.test(reference.name)) continue;
@@ -7336,19 +7613,19 @@ var subtreeHas = (root, found) => {
7336
7613
  return hit;
7337
7614
  };
7338
7615
  var isFrameworkWiring = (body) => subtreeHas(body, (node) => {
7339
- if (node.type === import_utils51.AST_NODE_TYPES.CallExpression) {
7616
+ if (node.type === import_utils56.AST_NODE_TYPES.CallExpression) {
7340
7617
  const { callee } = node;
7341
- if (callee.type === import_utils51.AST_NODE_TYPES.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7342
- return callee.type === import_utils51.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils51.AST_NODE_TYPES.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7618
+ if (callee.type === import_utils56.AST_NODE_TYPES.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7619
+ return callee.type === import_utils56.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils56.AST_NODE_TYPES.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7343
7620
  }
7344
- return node.type === import_utils51.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils51.AST_NODE_TYPES.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7621
+ return node.type === import_utils56.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils56.AST_NODE_TYPES.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7345
7622
  });
7346
7623
  var stem2 = (name) => name.replace(/^I(?=[A-Z])/, "").replace(/Impl$/, "");
7347
7624
  var fileInterfaceNames = (program) => {
7348
7625
  const names = [];
7349
7626
  for (const statement of program.body) {
7350
- const declaration = statement.type === import_utils51.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
7351
- if (declaration?.type === import_utils51.AST_NODE_TYPES.TSInterfaceDeclaration) names.push(declaration.id.name);
7627
+ const declaration = statement.type === import_utils56.AST_NODE_TYPES.ExportNamedDeclaration ? statement.declaration : statement;
7628
+ if (declaration?.type === import_utils56.AST_NODE_TYPES.TSInterfaceDeclaration) names.push(declaration.id.name);
7352
7629
  }
7353
7630
  return names;
7354
7631
  };
@@ -7366,16 +7643,16 @@ var isTransportWrapper = (className, collaborators, program) => {
7366
7643
  var publicMethodNames = (body) => {
7367
7644
  const names = [];
7368
7645
  for (const member of body.body) {
7369
- if (member.type !== import_utils51.AST_NODE_TYPES.MethodDefinition) continue;
7646
+ if (member.type !== import_utils56.AST_NODE_TYPES.MethodDefinition) continue;
7370
7647
  if (member.kind !== "method" || member.static) continue;
7371
7648
  if (member.accessibility === "private" || member.accessibility === "protected") continue;
7372
- if (member.key.type === import_utils51.AST_NODE_TYPES.PrivateIdentifier) continue;
7373
- if (member.key.type === import_utils51.AST_NODE_TYPES.Identifier) names.push(member.key.name);
7649
+ if (member.key.type === import_utils56.AST_NODE_TYPES.PrivateIdentifier) continue;
7650
+ if (member.key.type === import_utils56.AST_NODE_TYPES.Identifier) names.push(member.key.name);
7374
7651
  else names.push("\u2026");
7375
7652
  }
7376
7653
  return names;
7377
7654
  };
7378
- var require_interface_for_injected_service_default = import_utils51.ESLintUtils.RuleCreator(
7655
+ var require_interface_for_injected_service_default = import_utils56.ESLintUtils.RuleCreator(
7379
7656
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7380
7657
  )({
7381
7658
  name: "require-interface-for-injected-service",
@@ -7403,7 +7680,7 @@ var require_interface_for_injected_service_default = import_utils51.ESLintUtils.
7403
7680
  if (node.implements.length > 0) return;
7404
7681
  if (node.decorators.length > 0) return;
7405
7682
  const ctor = node.body.body.find(
7406
- (member) => member.type === import_utils51.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
7683
+ (member) => member.type === import_utils56.AST_NODE_TYPES.MethodDefinition && member.kind === "constructor"
7407
7684
  );
7408
7685
  if (ctor === void 0) return;
7409
7686
  const { collaborators, constructedFields } = readConstructor(ctor);
@@ -7428,26 +7705,26 @@ var require_interface_for_injected_service_default = import_utils51.ESLintUtils.
7428
7705
  });
7429
7706
 
7430
7707
  // src/rules/prefer-non-nullable-collection.ts
7431
- var import_utils52 = require("@typescript-eslint/utils");
7708
+ var import_utils57 = require("@typescript-eslint/utils");
7432
7709
  var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
7433
7710
  function propertyName(node) {
7434
7711
  const key = node.key;
7435
- if (key.type === import_utils52.AST_NODE_TYPES.Identifier) return key.name;
7436
- if (key.type === import_utils52.AST_NODE_TYPES.Literal) return String(key.value);
7712
+ if (key.type === import_utils57.AST_NODE_TYPES.Identifier) return key.name;
7713
+ if (key.type === import_utils57.AST_NODE_TYPES.Literal) return String(key.value);
7437
7714
  return "collection";
7438
7715
  }
7439
7716
  function isArrayType(node) {
7440
- if (node.type === import_utils52.AST_NODE_TYPES.TSArrayType) return true;
7441
- return node.type === import_utils52.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils52.AST_NODE_TYPES.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7717
+ if (node.type === import_utils57.AST_NODE_TYPES.TSArrayType) return true;
7718
+ return node.type === import_utils57.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils57.AST_NODE_TYPES.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7442
7719
  }
7443
7720
  function isNullishType(node) {
7444
- return node.type === import_utils52.AST_NODE_TYPES.TSNullKeyword || node.type === import_utils52.AST_NODE_TYPES.TSUndefinedKeyword;
7721
+ return node.type === import_utils57.AST_NODE_TYPES.TSNullKeyword || node.type === import_utils57.AST_NODE_TYPES.TSUndefinedKeyword;
7445
7722
  }
7446
7723
  function isNullableArrayOnly(node) {
7447
7724
  const values = node.types.filter((member) => !isNullishType(member));
7448
7725
  return values.length > 0 && values.length < node.types.length && values.every(isArrayType);
7449
7726
  }
7450
- var prefer_non_nullable_collection_default = import_utils52.ESLintUtils.RuleCreator(
7727
+ var prefer_non_nullable_collection_default = import_utils57.ESLintUtils.RuleCreator(
7451
7728
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
7452
7729
  )({
7453
7730
  name: "prefer-non-nullable-collection",
@@ -7470,7 +7747,7 @@ var prefer_non_nullable_collection_default = import_utils52.ESLintUtils.RuleCrea
7470
7747
  function checkOptionalProperty(node) {
7471
7748
  const annotation = node.typeAnnotation?.typeAnnotation;
7472
7749
  if (annotation === void 0) return;
7473
- if (annotation.type !== import_utils52.AST_NODE_TYPES.TSUnionType || !isNullableArrayOnly(annotation)) {
7750
+ if (annotation.type !== import_utils57.AST_NODE_TYPES.TSUnionType || !isNullableArrayOnly(annotation)) {
7474
7751
  return;
7475
7752
  }
7476
7753
  context.report({
@@ -7483,7 +7760,7 @@ var prefer_non_nullable_collection_default = import_utils52.ESLintUtils.RuleCrea
7483
7760
  TSPropertySignature: checkOptionalProperty,
7484
7761
  PropertyDefinition: checkOptionalProperty,
7485
7762
  TSTypeAliasDeclaration(node) {
7486
- if (node.typeAnnotation.type !== import_utils52.AST_NODE_TYPES.TSUnionType) return;
7763
+ if (node.typeAnnotation.type !== import_utils57.AST_NODE_TYPES.TSUnionType) return;
7487
7764
  if (!isNullableArrayOnly(node.typeAnnotation)) return;
7488
7765
  context.report({
7489
7766
  node,
@@ -7495,8 +7772,372 @@ var prefer_non_nullable_collection_default = import_utils52.ESLintUtils.RuleCrea
7495
7772
  }
7496
7773
  });
7497
7774
 
7775
+ // src/rules/primary-export-file-name.ts
7776
+ var import_utils58 = require("@typescript-eslint/utils");
7777
+ var CONVENTIONAL_BUCKET_EXPORTS2 = /* @__PURE__ */ new Set(["cn"]);
7778
+ var GENERIC_ENTRYPOINTS = /* @__PURE__ */ new Set(["main", "run", "cli", "setup", "teardown", "execute"]);
7779
+ var ACRONYM_OVERRIDES2 = [
7780
+ [/OAuth/g, "Oauth"],
7781
+ [/GraphQL/g, "Graphql"],
7782
+ [/gRPC/g, "Grpc"]
7783
+ ];
7784
+ var CAMEL_BOUNDARY_RE2 = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;
7785
+ var basename2 = (filename) => filename.split(/[/\\]/).pop() ?? filename;
7786
+ var stemOf2 = (base) => base.replace(/\.(test|spec|config|d|stories)\.[cm]?[jt]sx?$/i, "").replace(/\.[cm]?[jt]sx?$/i, "");
7787
+ var kebabCase3 = (name) => {
7788
+ let normalized = name;
7789
+ for (const [pattern, replacement] of ACRONYM_OVERRIDES2) {
7790
+ normalized = normalized.replace(pattern, replacement);
7791
+ }
7792
+ return normalized.replace(CAMEL_BOUNDARY_RE2, "-").toLowerCase();
7793
+ };
7794
+ var isFunctionOrClass = (node) => node.type === import_utils58.AST_NODE_TYPES.ArrowFunctionExpression || node.type === import_utils58.AST_NODE_TYPES.FunctionExpression;
7795
+ var findPrimaryExport = (body) => {
7796
+ let exportCount = 0;
7797
+ let primaryCandidate = null;
7798
+ for (const statement of body) {
7799
+ if (statement.type === import_utils58.AST_NODE_TYPES.ExportAllDeclaration) {
7800
+ return null;
7801
+ }
7802
+ if (statement.type === import_utils58.AST_NODE_TYPES.ExportDefaultDeclaration) {
7803
+ exportCount += 1;
7804
+ const decl = statement.declaration;
7805
+ if ((decl.type === import_utils58.AST_NODE_TYPES.FunctionDeclaration || decl.type === import_utils58.AST_NODE_TYPES.ClassDeclaration) && decl.id !== null) {
7806
+ primaryCandidate = { name: decl.id.name, node: statement, isDefault: true };
7807
+ } else if (decl.type === import_utils58.AST_NODE_TYPES.Identifier) {
7808
+ primaryCandidate = { name: decl.name, node: statement, isDefault: true };
7809
+ }
7810
+ } else if (statement.type === import_utils58.AST_NODE_TYPES.ExportNamedDeclaration) {
7811
+ if (statement.source !== null) {
7812
+ return null;
7813
+ }
7814
+ const decl = statement.declaration;
7815
+ if (decl === null) {
7816
+ exportCount += statement.specifiers.length;
7817
+ if (statement.specifiers.length === 1 && primaryCandidate === null) {
7818
+ const spec = statement.specifiers[0];
7819
+ if (spec && spec.exported.type === import_utils58.AST_NODE_TYPES.Identifier) {
7820
+ primaryCandidate = { name: spec.exported.name, node: statement, isDefault: false };
7821
+ }
7822
+ }
7823
+ } else if (decl.type === import_utils58.AST_NODE_TYPES.FunctionDeclaration || decl.type === import_utils58.AST_NODE_TYPES.ClassDeclaration) {
7824
+ if (decl.id !== null) {
7825
+ exportCount += 1;
7826
+ if (primaryCandidate === null) {
7827
+ primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
7828
+ }
7829
+ }
7830
+ } else if (decl.type === import_utils58.AST_NODE_TYPES.VariableDeclaration) {
7831
+ for (const declarator of decl.declarations) {
7832
+ if (declarator.id.type === import_utils58.AST_NODE_TYPES.Identifier) {
7833
+ exportCount += 1;
7834
+ if (primaryCandidate === null && declarator.init && isFunctionOrClass(declarator.init)) {
7835
+ primaryCandidate = { name: declarator.id.name, node: statement, isDefault: false };
7836
+ }
7837
+ }
7838
+ }
7839
+ } else if (decl.type === import_utils58.AST_NODE_TYPES.TSTypeAliasDeclaration || decl.type === import_utils58.AST_NODE_TYPES.TSInterfaceDeclaration) {
7840
+ exportCount += 1;
7841
+ if (primaryCandidate === null) {
7842
+ primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
7843
+ }
7844
+ }
7845
+ }
7846
+ }
7847
+ if (primaryCandidate === null || exportCount > 2) {
7848
+ return null;
7849
+ }
7850
+ return { ...primaryCandidate, count: exportCount };
7851
+ };
7852
+ var primary_export_file_name_default = import_utils58.ESLintUtils.RuleCreator(
7853
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7854
+ )({
7855
+ name: "primary-export-file-name",
7856
+ meta: {
7857
+ type: "suggestion",
7858
+ docs: {
7859
+ description: "Enforce semantic naming alignment: a file with a single primary export must be named after that export."
7860
+ },
7861
+ schema: [],
7862
+ messages: {
7863
+ primaryExportMismatch: "Module stem '{{stem}}' does not match its primary export '{{name}}' \u2014 rename the file to '{{expected}}{{ext}}' to describe its responsibility."
7864
+ }
7865
+ },
7866
+ defaultOptions: [],
7867
+ create(context) {
7868
+ const base = basename2(context.filename);
7869
+ if (base.endsWith(".d.ts") || base.startsWith("index.") || base.startsWith("_")) return {};
7870
+ if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
7871
+ const stem3 = stemOf2(base);
7872
+ 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("[")) {
7873
+ return {};
7874
+ }
7875
+ return {
7876
+ Program(node) {
7877
+ const primary = findPrimaryExport(node.body);
7878
+ if (primary === null) return;
7879
+ if (CONVENTIONAL_BUCKET_EXPORTS2.has(primary.name) || GENERIC_ENTRYPOINTS.has(primary.name)) return;
7880
+ const expectedStem = kebabCase3(primary.name);
7881
+ if (stem3 === expectedStem) return;
7882
+ const ext = base.endsWith(".tsx") ? ".tsx" : ".ts";
7883
+ context.report({
7884
+ node: primary.node,
7885
+ messageId: "primaryExportMismatch",
7886
+ data: { stem: stem3, name: primary.name, expected: expectedStem, ext }
7887
+ });
7888
+ }
7889
+ };
7890
+ }
7891
+ });
7892
+
7893
+ // src/rules/no-implicit-attribute-access.ts
7894
+ var import_utils59 = require("@typescript-eslint/utils");
7895
+ var EXCLUDED_BASES = /* @__PURE__ */ new Set([
7896
+ "environ",
7897
+ "headers",
7898
+ "cookies",
7899
+ "session",
7900
+ "redis",
7901
+ "cache",
7902
+ "state",
7903
+ "config",
7904
+ "env",
7905
+ "process",
7906
+ "localStorage",
7907
+ "sessionStorage"
7908
+ ]);
7909
+ function getBaseName(node) {
7910
+ if (node.type === import_utils59.AST_NODE_TYPES.Identifier) {
7911
+ return node.name;
7912
+ }
7913
+ if (node.type === import_utils59.AST_NODE_TYPES.MemberExpression && node.property.type === import_utils59.AST_NODE_TYPES.Identifier) {
7914
+ return node.property.name;
7915
+ }
7916
+ return null;
7917
+ }
7918
+ var no_implicit_attribute_access_default = import_utils59.ESLintUtils.RuleCreator(
7919
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7920
+ )({
7921
+ name: "no-implicit-attribute-access",
7922
+ meta: {
7923
+ type: "problem",
7924
+ docs: {
7925
+ description: "Disallow imperative dictionary access with string literals; use declarative Zod schemas."
7926
+ },
7927
+ schema: [],
7928
+ messages: {
7929
+ noImplicitAttributeAccess: "Imperative lookup for '{{key}}' \u2014 if the key is known, parse the object declaratively with a Zod schema instead."
7930
+ }
7931
+ },
7932
+ defaultOptions: [],
7933
+ create(context) {
7934
+ return {
7935
+ MemberExpression(node) {
7936
+ if (!node.computed) {
7937
+ return;
7938
+ }
7939
+ if (node.property.type === import_utils59.AST_NODE_TYPES.Literal && typeof node.property.value === "string") {
7940
+ const baseName = getBaseName(node.object);
7941
+ if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7942
+ context.report({
7943
+ node,
7944
+ messageId: "noImplicitAttributeAccess",
7945
+ data: { key: node.property.value }
7946
+ });
7947
+ }
7948
+ }
7949
+ },
7950
+ CallExpression(node) {
7951
+ const callee = node.callee;
7952
+ if (callee.type === import_utils59.AST_NODE_TYPES.MemberExpression) {
7953
+ const method = callee.property.type === import_utils59.AST_NODE_TYPES.Identifier ? callee.property.name : null;
7954
+ if (method === "get") {
7955
+ const arg = node.arguments[0];
7956
+ if (arg && arg.type === import_utils59.AST_NODE_TYPES.Literal && typeof arg.value === "string") {
7957
+ const baseName = getBaseName(callee.object);
7958
+ if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7959
+ context.report({
7960
+ node,
7961
+ messageId: "noImplicitAttributeAccess",
7962
+ data: { key: arg.value }
7963
+ });
7964
+ }
7965
+ }
7966
+ }
7967
+ }
7968
+ }
7969
+ };
7970
+ }
7971
+ });
7972
+
7973
+ // src/rules/strict-test-assertions.ts
7974
+ var import_utils60 = require("@typescript-eslint/utils");
7975
+ var strict_test_assertions_default = import_utils60.ESLintUtils.RuleCreator.withoutDocs({
7976
+ meta: {
7977
+ type: "suggestion",
7978
+ docs: {
7979
+ description: "Replace multiple sequential assertions with a single toMatchObject or toStrictEqual"
7980
+ },
7981
+ fixable: "code",
7982
+ messages: {
7983
+ combineAssertions: "Combine multiple sequential assertions on the same object into a single toMatchObject or toStrictEqual"
7984
+ },
7985
+ schema: []
7986
+ },
7987
+ defaultOptions: [],
7988
+ create(context) {
7989
+ function checkBody(body) {
7990
+ let currentObject = null;
7991
+ let sequence = [];
7992
+ function getExpectObject(expr) {
7993
+ if (expr.type === import_utils60.AST_NODE_TYPES.CallExpression && expr.callee.type === import_utils60.AST_NODE_TYPES.MemberExpression && expr.callee.object.type === import_utils60.AST_NODE_TYPES.CallExpression && expr.callee.object.callee.type === import_utils60.AST_NODE_TYPES.Identifier && expr.callee.object.callee.name === "expect" && expr.callee.object.arguments.length === 1) {
7994
+ const arg = expr.callee.object.arguments.at(0);
7995
+ if (arg?.type === import_utils60.AST_NODE_TYPES.MemberExpression) {
7996
+ return arg.object;
7997
+ }
7998
+ }
7999
+ return null;
8000
+ }
8001
+ function reportSequence() {
8002
+ const first = sequence.at(0);
8003
+ if (sequence.length > 1 && first) {
8004
+ context.report({
8005
+ node: first,
8006
+ messageId: "combineAssertions",
8007
+ fix(fixer) {
8008
+ if (!currentObject) return null;
8009
+ const objectText = context.sourceCode.getText(currentObject);
8010
+ const props = sequence.map((stmt) => {
8011
+ if (stmt.expression.type !== import_utils60.AST_NODE_TYPES.CallExpression || stmt.expression.callee.type !== import_utils60.AST_NODE_TYPES.MemberExpression || stmt.expression.callee.object.type !== import_utils60.AST_NODE_TYPES.CallExpression) {
8012
+ return null;
8013
+ }
8014
+ const actual = stmt.expression.callee.object.arguments.at(0);
8015
+ const expected = stmt.expression.arguments.at(0);
8016
+ if (actual?.type === import_utils60.AST_NODE_TYPES.MemberExpression && actual.property.type === import_utils60.AST_NODE_TYPES.Identifier && expected) {
8017
+ const propName2 = actual.property.name;
8018
+ const valText = context.sourceCode.getText(expected);
8019
+ return `${propName2}: ${valText}`;
8020
+ }
8021
+ return null;
8022
+ });
8023
+ if (props.some((p) => p === null)) return null;
8024
+ const replacement = `expect(${objectText}).toMatchObject({ ${props.join(", ")} });`;
8025
+ return [
8026
+ fixer.replaceText(first, replacement),
8027
+ ...sequence.slice(1).map((stmt) => fixer.remove(stmt))
8028
+ ];
8029
+ }
8030
+ });
8031
+ }
8032
+ }
8033
+ for (const statement of body) {
8034
+ if (statement.type === import_utils60.AST_NODE_TYPES.ExpressionStatement) {
8035
+ const obj = getExpectObject(statement.expression);
8036
+ if (obj && currentObject && context.sourceCode.getText(obj) === context.sourceCode.getText(currentObject)) {
8037
+ sequence.push(statement);
8038
+ } else {
8039
+ reportSequence();
8040
+ if (obj) {
8041
+ currentObject = obj;
8042
+ sequence = [statement];
8043
+ } else {
8044
+ currentObject = null;
8045
+ sequence = [];
8046
+ }
8047
+ }
8048
+ } else {
8049
+ reportSequence();
8050
+ currentObject = null;
8051
+ sequence = [];
8052
+ }
8053
+ }
8054
+ reportSequence();
8055
+ }
8056
+ return {
8057
+ BlockStatement(node) {
8058
+ checkBody(node.body);
8059
+ },
8060
+ Program(node) {
8061
+ checkBody(node.body);
8062
+ }
8063
+ };
8064
+ }
8065
+ });
8066
+
8067
+ // src/rules/no-async-callback-in-waitfor.ts
8068
+ var import_utils61 = require("@typescript-eslint/utils");
8069
+ var no_async_callback_in_waitfor_default = import_utils61.ESLintUtils.RuleCreator(
8070
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8071
+ )({
8072
+ name: "no-async-callback-in-waitfor",
8073
+ meta: {
8074
+ type: "problem",
8075
+ docs: {
8076
+ description: "Disallow async callbacks in `waitFor` to prevent swallowed promise rejections."
8077
+ },
8078
+ schema: [],
8079
+ messages: {
8080
+ noAsyncCallbackInWaitFor: "The callback to `waitFor` should not be async. It expects synchronous assertions and runs the callback repeatedly."
8081
+ }
8082
+ },
8083
+ defaultOptions: [],
8084
+ create(context) {
8085
+ if (!isTestFile(context.filename)) {
8086
+ return {};
8087
+ }
8088
+ return {
8089
+ CallExpression(node) {
8090
+ if (node.callee.type === import_utils61.AST_NODE_TYPES.Identifier && node.callee.name === "waitFor") {
8091
+ const callback = node.arguments[0];
8092
+ if (callback && (callback.type === import_utils61.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils61.AST_NODE_TYPES.FunctionExpression) && callback.async) {
8093
+ context.report({
8094
+ node: callback,
8095
+ messageId: "noAsyncCallbackInWaitFor"
8096
+ });
8097
+ }
8098
+ }
8099
+ }
8100
+ };
8101
+ }
8102
+ });
8103
+
8104
+ // src/rules/prefer-setup-file-mocks.ts
8105
+ var import_utils62 = require("@typescript-eslint/utils");
8106
+ var prefer_setup_file_mocks_default = import_utils62.ESLintUtils.RuleCreator(
8107
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8108
+ )({
8109
+ name: "prefer-setup-file-mocks",
8110
+ meta: {
8111
+ type: "suggestion",
8112
+ docs: {
8113
+ description: "Prefer defining module mocks in setup files rather than using vi.mock or jest.mock inline in test files."
8114
+ },
8115
+ schema: [],
8116
+ messages: {
8117
+ preferSetupFileMocks: "Define module mocks in a setup file (e.g. vitest.setup.ts) instead of using vi.mock or jest.mock directly in test files."
8118
+ }
8119
+ },
8120
+ defaultOptions: [],
8121
+ create(context) {
8122
+ if (!isTestFile(context.filename)) {
8123
+ return {};
8124
+ }
8125
+ return {
8126
+ CallExpression(node) {
8127
+ if (node.callee.type === import_utils62.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils62.AST_NODE_TYPES.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === import_utils62.AST_NODE_TYPES.Identifier && node.callee.property.name === "mock") {
8128
+ context.report({
8129
+ node,
8130
+ messageId: "preferSetupFileMocks"
8131
+ });
8132
+ }
8133
+ }
8134
+ };
8135
+ }
8136
+ });
8137
+
7498
8138
  // src/index.ts
7499
8139
  var rules = {
8140
+ "ban-loose-type-guards-in-tests": ban_loose_type_guards_in_tests_default,
7500
8141
  "enforce-file-structure": enforce_file_structure_default,
7501
8142
  "no-client-side-data-fetching": no_client_side_data_fetching_default,
7502
8143
  "no-comment-cruft": no_comment_cruft_default,
@@ -7521,8 +8162,11 @@ var rules = {
7521
8162
  "no-fat-try-blocks": no_fat_try_blocks_default,
7522
8163
  "no-secret-in-log": no_secret_in_log_default,
7523
8164
  "no-unsafe-cast": no_unsafe_cast_default,
8165
+ "no-unsafe-mock-casting": no_unsafe_mock_casting_default,
7524
8166
  "prefer-string-literal-union": prefer_string_literal_union_default,
8167
+ "prefer-zod-enum": prefer_zod_enum_default,
7525
8168
  "single-public-export": single_public_export_default,
8169
+ "primary-export-file-name": primary_export_file_name_default,
7526
8170
  "no-silent-promise-catch": no_silent_promise_catch_default,
7527
8171
  "require-fetch-timeout": require_fetch_timeout_default,
7528
8172
  "require-schema-validate-search": require_schema_validate_search_default,
@@ -7531,6 +8175,7 @@ var rules = {
7531
8175
  "no-repeated-string-literal": no_repeated_string_literal_default,
7532
8176
  "no-select-star": no_select_star_default,
7533
8177
  "no-sleep-in-test-body": no_sleep_in_test_body_default,
8178
+ "no-conditional-in-test": no_conditional_in_test_default,
7534
8179
  "prefer-constant-time-secret-compare": prefer_constant_time_secret_compare_default,
7535
8180
  "store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
7536
8181
  "no-dynamic-sql": no_dynamic_sql_default,
@@ -7543,12 +8188,16 @@ var rules = {
7543
8188
  "trailing-value-narration": trailing_value_narration_default,
7544
8189
  "no-tautological-expect": no_tautological_expect_default,
7545
8190
  "require-interface-for-injected-service": require_interface_for_injected_service_default,
7546
- "prefer-non-nullable-collection": prefer_non_nullable_collection_default
8191
+ "strict-test-assertions": strict_test_assertions_default,
8192
+ "prefer-non-nullable-collection": prefer_non_nullable_collection_default,
8193
+ "no-implicit-attribute-access": no_implicit_attribute_access_default,
8194
+ "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default,
8195
+ "prefer-setup-file-mocks": prefer_setup_file_mocks_default
7547
8196
  };
7548
8197
  var plugin = {
7549
8198
  meta: {
7550
8199
  name: "@sarj/eslint-plugin",
7551
- version: "2.15.0"
8200
+ version: "2.17.0"
7552
8201
  },
7553
8202
  rules,
7554
8203
  configs: {
@@ -7558,6 +8207,7 @@ var plugin = {
7558
8207
  "@sarj/zod-naming-convention": "warn",
7559
8208
  "@sarj/require-assert-never": "error",
7560
8209
  "@sarj/require-zod-form-validation": "error",
8210
+ "@sarj/ban-loose-type-guards-in-tests": "error",
7561
8211
  "@sarj/enforce-file-structure": "warn",
7562
8212
  "@sarj/no-client-side-data-fetching": "warn",
7563
8213
  "@sarj/prefer-server-actions": "warn",
@@ -7582,8 +8232,11 @@ var plugin = {
7582
8232
  "@sarj/no-cors-wildcard-with-credentials": "warn",
7583
8233
  "@sarj/no-secret-in-log": "warn",
7584
8234
  "@sarj/no-unsafe-cast": "warn",
8235
+ "@sarj/no-unsafe-mock-casting": "warn",
7585
8236
  "@sarj/single-public-export": "warn",
8237
+ "@sarj/primary-export-file-name": "warn",
7586
8238
  "@sarj/prefer-string-literal-union": "warn",
8239
+ "@sarj/prefer-zod-enum": "warn",
7587
8240
  // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
7588
8241
  "@sarj/require-fetch-timeout": "warn",
7589
8242
  "@sarj/no-silent-promise-catch": "warn",
@@ -7597,6 +8250,7 @@ var plugin = {
7597
8250
  "@sarj/no-offset-pagination": "warn",
7598
8251
  "@sarj/no-select-star": "warn",
7599
8252
  "@sarj/no-sleep-in-test-body": "warn",
8253
+ "@sarj/no-conditional-in-test": "warn",
7600
8254
  "@sarj/no-repeated-string-literal": "warn",
7601
8255
  "@sarj/no-positional-tuple-return": "warn",
7602
8256
  // Injection guard — low FP, applies to any repo touching SQL.
@@ -7632,7 +8286,10 @@ var plugin = {
7632
8286
  // mocking. 11-repo sweep: 229 exported classes, 82% already carry a
7633
8287
  // port, 29 fire, 28 of them true positives.
7634
8288
  "@sarj/require-interface-for-injected-service": "warn",
7635
- "@sarj/prefer-non-nullable-collection": "warn"
8289
+ "@sarj/prefer-non-nullable-collection": "warn",
8290
+ "@sarj/no-implicit-attribute-access": "warn",
8291
+ "@sarj/no-async-callback-in-waitfor": "warn",
8292
+ "@sarj/prefer-setup-file-mocks": "warn"
7636
8293
  }
7637
8294
  },
7638
8295
  strict: {
@@ -7641,6 +8298,7 @@ var plugin = {
7641
8298
  "@sarj/zod-naming-convention": "error",
7642
8299
  "@sarj/require-assert-never": "error",
7643
8300
  "@sarj/require-zod-form-validation": "error",
8301
+ "@sarj/ban-loose-type-guards-in-tests": "error",
7644
8302
  "@sarj/enforce-file-structure": "error",
7645
8303
  "@sarj/no-raw-env": "error",
7646
8304
  "@sarj/prefer-shadcn": "error",
@@ -7669,9 +8327,12 @@ var plugin = {
7669
8327
  "@sarj/no-cors-wildcard-with-credentials": "error",
7670
8328
  "@sarj/no-secret-in-log": "error",
7671
8329
  "@sarj/no-unsafe-cast": "error",
8330
+ "@sarj/no-unsafe-mock-casting": "error",
7672
8331
  "@sarj/single-public-export": "error",
8332
+ "@sarj/primary-export-file-name": "error",
7673
8333
  // Promoted to error 2026-07-25 — strict means strict (user directive).
7674
8334
  "@sarj/prefer-string-literal-union": "error",
8335
+ "@sarj/prefer-zod-enum": "error",
7675
8336
  // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
7676
8337
  "@sarj/require-fetch-timeout": "error",
7677
8338
  "@sarj/no-silent-promise-catch": "error",
@@ -7682,6 +8343,7 @@ var plugin = {
7682
8343
  "@sarj/no-offset-pagination": "error",
7683
8344
  "@sarj/no-select-star": "error",
7684
8345
  "@sarj/no-sleep-in-test-body": "error",
8346
+ "@sarj/no-conditional-in-test": "error",
7685
8347
  "@sarj/no-repeated-string-literal": "error",
7686
8348
  // API-shape advice rather than a runtime defect — a corpus sweep found its
7687
8349
  // only hits are parser `[value, cursor]` returns, which are conventional.
@@ -7710,7 +8372,10 @@ var plugin = {
7710
8372
  // / `prefer-library-fake` wave. The convention already exists in the
7711
8373
  // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
7712
8374
  "@sarj/require-interface-for-injected-service": "error",
7713
- "@sarj/prefer-non-nullable-collection": "error"
8375
+ "@sarj/prefer-non-nullable-collection": "error",
8376
+ "@sarj/no-implicit-attribute-access": "error",
8377
+ "@sarj/no-async-callback-in-waitfor": "error",
8378
+ "@sarj/prefer-setup-file-mocks": "error"
7714
8379
  }
7715
8380
  }
7716
8381
  }