@sarj/eslint-plugin 4.2.0 → 5.1.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,13 +35,14 @@ __export(index_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
- // src/rules/ban-loose-type-guards-in-tests.ts
38
+ // src/rules/enforce-file-structure.ts
39
39
  var import_utils = require("@typescript-eslint/utils");
40
40
 
41
41
  // src/rules/_paths.ts
42
42
  var SCRIPT_FILE_RE = /([\\/]scripts[\\/])|(\.mjs$)/;
43
43
  var STORY_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
44
- var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types)[\\/])|(\.gen\.[cm]?[jt]sx?$)|(\.generated\.[cm]?[jt]sx?$)|(\.d\.[cm]?ts$)|(\.types\.[cm]?ts$)/;
44
+ var STORY_DIR_RE = /(^|\/)stories(?:[_-][^/]*)?\//i;
45
+ var GENERATED_FILE_RE = /([\\/](?:generated|openapi-gen|graphql[\\/]types|vendor|vendored|external|third[-_]?party)[\\/])|(\.gen\.[cm]?[jt]sx?$)|(\.generated\.[cm]?[jt]sx?$)|(\.d\.[cm]?ts$)|(\.types\.[cm]?ts$)/;
45
46
  var GENERATED_MARKER_RE = /(?:@generated\b|generated (?:with|by)|generated (?:graphql )?types|do not edit(?: directly| manually)?)/i;
46
47
  function isTestFile(filename) {
47
48
  const normalized = filename.replaceAll("\\", "/");
@@ -49,10 +50,13 @@ function isTestFile(filename) {
49
50
  if (/[.\-_](test|spec|e2e)\.[cm]?[jt]sx?$/.test(base) || /\.integration\.[cm]?[jt]sx?$/.test(base)) {
50
51
  return true;
51
52
  }
52
- return /(^|\/)(tests?|__tests__|__mocks__|fixtures|e2e|integration)\//.test(normalized);
53
+ return /(^|\/)(tests?|__tests__|__mocks__|__fixtures__|__testfixtures__|fixtures?|e2e|integration)\//.test(
54
+ normalized
55
+ );
53
56
  }
54
57
  function isStoryFile(filename) {
55
- return STORY_FILE_RE.test(filename);
58
+ const normalized = filename.replaceAll("\\", "/");
59
+ return STORY_FILE_RE.test(normalized) || STORY_DIR_RE.test(normalized);
56
60
  }
57
61
  function isGeneratedFile(filename, sourceText = "") {
58
62
  return GENERATED_FILE_RE.test(filename.replaceAll("\\", "/")) || GENERATED_MARKER_RE.test(sourceText.slice(0, 2048));
@@ -61,63 +65,27 @@ function isScriptFile(filename) {
61
65
  return SCRIPT_FILE_RE.test(filename);
62
66
  }
63
67
 
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
-
99
68
  // src/rules/enforce-file-structure.ts
100
- var import_utils2 = require("@typescript-eslint/utils");
101
69
  var classifyStatement = (statement) => {
102
70
  switch (statement.type) {
103
- case import_utils2.AST_NODE_TYPES.ImportDeclaration:
71
+ case import_utils.AST_NODE_TYPES.ImportDeclaration:
104
72
  return "import";
105
- case import_utils2.AST_NODE_TYPES.ExportAllDeclaration:
73
+ case import_utils.AST_NODE_TYPES.ExportAllDeclaration:
106
74
  return "reexport";
107
- case import_utils2.AST_NODE_TYPES.ExportNamedDeclaration:
75
+ case import_utils.AST_NODE_TYPES.ExportNamedDeclaration:
108
76
  return statement.declaration === null ? "reexport" : "body";
109
77
  default:
110
78
  return "body";
111
79
  }
112
80
  };
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 ");
81
+ 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 ");
114
82
  var isUseServerDirective = (statement) => {
115
- if (statement.type !== import_utils2.AST_NODE_TYPES.ExpressionStatement) return false;
83
+ if (statement.type !== import_utils.AST_NODE_TYPES.ExpressionStatement) return false;
116
84
  const expr = statement.expression;
117
- if (expr.type !== import_utils2.AST_NODE_TYPES.Literal) return false;
85
+ if (expr.type !== import_utils.AST_NODE_TYPES.Literal) return false;
118
86
  return expr.value === "use server";
119
87
  };
120
- var enforce_file_structure_default = import_utils2.ESLintUtils.RuleCreator(
88
+ var enforce_file_structure_default = import_utils.ESLintUtils.RuleCreator(
121
89
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
122
90
  )({
123
91
  name: "enforce-file-structure",
@@ -177,7 +145,7 @@ var enforce_file_structure_default = import_utils2.ESLintUtils.RuleCreator(
177
145
  });
178
146
 
179
147
  // src/rules/no-client-side-data-fetching.ts
180
- var import_utils3 = require("@typescript-eslint/utils");
148
+ var import_utils2 = require("@typescript-eslint/utils");
181
149
  var FETCH_LIBS = /* @__PURE__ */ new Set(["axios", "ky", "superagent"]);
182
150
  var HTTP_METHOD_NAMES = /* @__PURE__ */ new Set([
183
151
  "get",
@@ -201,25 +169,25 @@ var ANALYTICS_SEGMENTS = /* @__PURE__ */ new Set([
201
169
  ]);
202
170
  function isEffectHookCall(node) {
203
171
  const callee = node.callee;
204
- if (callee.type === import_utils3.AST_NODE_TYPES.Identifier) {
172
+ if (callee.type === import_utils2.AST_NODE_TYPES.Identifier) {
205
173
  return callee.name === "useEffect" || callee.name === "useLayoutEffect";
206
174
  }
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) {
175
+ 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) {
208
176
  return callee.property.name === "useEffect" || callee.property.name === "useLayoutEffect";
209
177
  }
210
178
  return false;
211
179
  }
212
180
  function readMethodProperty(optionsArg) {
213
- if (!optionsArg || optionsArg.type !== import_utils3.AST_NODE_TYPES.ObjectExpression) {
181
+ if (!optionsArg || optionsArg.type !== import_utils2.AST_NODE_TYPES.ObjectExpression) {
214
182
  return null;
215
183
  }
216
184
  for (const prop of optionsArg.properties) {
217
- if (prop.type !== import_utils3.AST_NODE_TYPES.Property) continue;
185
+ if (prop.type !== import_utils2.AST_NODE_TYPES.Property) continue;
218
186
  if (prop.computed) continue;
219
187
  const key = prop.key;
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";
188
+ const matchesMethodKey = key.type === import_utils2.AST_NODE_TYPES.Identifier && key.name === "method" || key.type === import_utils2.AST_NODE_TYPES.Literal && key.value === "method";
221
189
  if (!matchesMethodKey) continue;
222
- if (prop.value.type === import_utils3.AST_NODE_TYPES.Literal && typeof prop.value.value === "string") {
190
+ if (prop.value.type === import_utils2.AST_NODE_TYPES.Literal && typeof prop.value.value === "string") {
223
191
  return prop.value.value.toUpperCase();
224
192
  }
225
193
  return null;
@@ -228,23 +196,23 @@ function readMethodProperty(optionsArg) {
228
196
  }
229
197
  function isFetchCall(node) {
230
198
  const callee = node.callee;
231
- if (callee.type === import_utils3.AST_NODE_TYPES.Identifier && callee.name === "fetch") {
199
+ if (callee.type === import_utils2.AST_NODE_TYPES.Identifier && callee.name === "fetch") {
232
200
  const method = readMethodProperty(node.arguments[1]);
233
201
  if (method !== null && method !== "GET") {
234
202
  return false;
235
203
  }
236
204
  return true;
237
205
  }
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) {
206
+ 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) {
239
207
  return HTTP_METHOD_NAMES.has(callee.property.name);
240
208
  }
241
- if (callee.type === import_utils3.AST_NODE_TYPES.Identifier && (callee.name === "axios" || callee.name === "ky")) {
209
+ if (callee.type === import_utils2.AST_NODE_TYPES.Identifier && (callee.name === "axios" || callee.name === "ky")) {
242
210
  const firstArg = node.arguments[0];
243
211
  const secondArg = node.arguments[1];
244
212
  let configArg;
245
- if (firstArg?.type === import_utils3.AST_NODE_TYPES.ObjectExpression) {
213
+ if (firstArg?.type === import_utils2.AST_NODE_TYPES.ObjectExpression) {
246
214
  configArg = firstArg;
247
- } else if (secondArg?.type === import_utils3.AST_NODE_TYPES.ObjectExpression) {
215
+ } else if (secondArg?.type === import_utils2.AST_NODE_TYPES.ObjectExpression) {
248
216
  configArg = secondArg;
249
217
  }
250
218
  const method = readMethodProperty(configArg);
@@ -258,13 +226,13 @@ function isFetchCall(node) {
258
226
  function extractUrlString(node) {
259
227
  const firstArg = node.arguments[0];
260
228
  if (!firstArg) return "";
261
- if (firstArg.type === import_utils3.AST_NODE_TYPES.Literal && typeof firstArg.value === "string") {
229
+ if (firstArg.type === import_utils2.AST_NODE_TYPES.Literal && typeof firstArg.value === "string") {
262
230
  return firstArg.value;
263
231
  }
264
- if (firstArg.type === import_utils3.AST_NODE_TYPES.TemplateLiteral) {
232
+ if (firstArg.type === import_utils2.AST_NODE_TYPES.TemplateLiteral) {
265
233
  return firstArg.quasis.map((q) => q.value.cooked).join("");
266
234
  }
267
- if (firstArg.type === import_utils3.AST_NODE_TYPES.Identifier) {
235
+ if (firstArg.type === import_utils2.AST_NODE_TYPES.Identifier) {
268
236
  return firstArg.name;
269
237
  }
270
238
  return "";
@@ -274,7 +242,7 @@ function isAnalyticsCall(node) {
274
242
  if (url === "") return false;
275
243
  return url.split(/[/.]/).some((segment) => ANALYTICS_SEGMENTS.has(segment));
276
244
  }
277
- var no_client_side_data_fetching_default = import_utils3.ESLintUtils.RuleCreator(
245
+ var no_client_side_data_fetching_default = import_utils2.ESLintUtils.RuleCreator(
278
246
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
279
247
  )({
280
248
  name: "no-client-side-data-fetching",
@@ -312,10 +280,10 @@ var no_client_side_data_fetching_default = import_utils3.ESLintUtils.RuleCreator
312
280
  });
313
281
 
314
282
  // src/rules/no-comment-cruft.ts
315
- var import_utils5 = require("@typescript-eslint/utils");
283
+ var import_utils4 = require("@typescript-eslint/utils");
316
284
 
317
285
  // src/rules/_comments.ts
318
- var import_utils4 = require("@typescript-eslint/utils");
286
+ var import_utils3 = require("@typescript-eslint/utils");
319
287
  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/;
320
288
  var VERSION_RE = /(?:>=|<=|==|<|>)\s*v?\d+\.\d+|\bv\d+\.\d+|\b(?:since|until|as of)\s+(?:v?\d+\.\d+|Python\s*\d)/i;
321
289
  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/;
@@ -401,10 +369,10 @@ var NARRATION_MAX_WORDS = 6;
401
369
  var NARRATION_MIN_CONTENT = 1;
402
370
  var TOKEN_PLURAL_MIN = 4;
403
371
  var RESTATABLE_STATEMENTS = /* @__PURE__ */ new Set([
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
+ import_utils3.AST_NODE_TYPES.ExpressionStatement,
373
+ import_utils3.AST_NODE_TYPES.ReturnStatement,
374
+ import_utils3.AST_NODE_TYPES.ThrowStatement,
375
+ import_utils3.AST_NODE_TYPES.VariableDeclaration
408
376
  ]);
409
377
  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;
410
378
  var NARRATION_STOPWORDS = /* @__PURE__ */ new Set([
@@ -469,19 +437,19 @@ function headTokens(source) {
469
437
  function isTrivialInitializer(node) {
470
438
  return node.declarations.every((declarator) => {
471
439
  const init = declarator.init;
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;
440
+ if (init == null || init.type === import_utils3.AST_NODE_TYPES.Literal) return true;
441
+ 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;
474
442
  });
475
443
  }
476
444
  function restatableStatementBelow(comment, sourceCode) {
477
445
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
478
446
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) return null;
479
- for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils4.AST_NODE_TYPES.Program; node = node.parent) {
447
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils3.AST_NODE_TYPES.Program; node = node.parent) {
480
448
  if (!RESTATABLE_STATEMENTS.has(node.type)) continue;
481
449
  if (node.loc.start.line !== token.loc.start.line || node.loc.end.line !== node.loc.start.line) {
482
450
  return null;
483
451
  }
484
- if (node.type === import_utils4.AST_NODE_TYPES.VariableDeclaration && isTrivialInitializer(node)) {
452
+ if (node.type === import_utils3.AST_NODE_TYPES.VariableDeclaration && isTrivialInitializer(node)) {
485
453
  return null;
486
454
  }
487
455
  return sourceCode.getText(node);
@@ -576,7 +544,8 @@ var DUMMY_TRANSLATION_RE = /^(?:increment|return|returns|get|gets|set\b(?! up\b)
576
544
  var DIAGRAM_ARROW_RE = /[-=~]{2,}>|<[-=~]{2,}/;
577
545
  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\.)/;
578
546
  var CODE_TAIL_RE = /[;{}()]\s*$|=>\s*$|,\s*$/;
579
- var CALL_OR_ASSIGN_RE = /^[A-Za-z_$][\w.$[\]]*\s*(?:=(?![=>])|\+=|-=|\*=)\s*\S.*[;)}\]]\s*$|^[A-Za-z_$][\w.$]*\([^)]*\)\s*;?\s*$/;
547
+ var ASSIGN_RE = /^[A-Za-z_$][\w.$[\]]*\s*(?:=(?![=>])|\+=|-=|\*=)\s*\S.*[;)}\]]\s*$/;
548
+ var CALL_RE = /^[A-Za-z_$][\w.$]*\([^)]*\)\s*;?\s*$/;
580
549
  var PSEUDOCODE_RE = /%\w+%|\[opt\]|(?:^|\s)<[A-Za-z]\w*>|…|\.\.\./;
581
550
  function stripCommentMarker(line) {
582
551
  return line.replace(/^\s*\/{1,2}/, "").replace(/^\s*\*+/, "").trim();
@@ -590,11 +559,12 @@ function isBanner(text) {
590
559
  if (BANNER_FULL_RE.test(t) || isRegionMarker(t)) return true;
591
560
  return BANNER_RUN_RE.test(t) && !DIAGRAM_ARROW_RE.test(t);
592
561
  }
593
- function looksLikeCode(text) {
562
+ function looksLikeCode(text, allowCall = true) {
594
563
  const t = text.trim();
595
564
  if (!t) return false;
596
565
  if (CODE_KEYWORD_RE.test(t) && CODE_TAIL_RE.test(t)) return true;
597
- return CALL_OR_ASSIGN_RE.test(t);
566
+ if (ASSIGN_RE.test(t)) return true;
567
+ return allowCall && CALL_RE.test(t);
598
568
  }
599
569
  function hasPseudocode(text) {
600
570
  return PSEUDOCODE_RE.test(text);
@@ -612,20 +582,24 @@ function isProse(text) {
612
582
  }
613
583
  return false;
614
584
  }
615
- var JUSTIFICATION_RE = /\b(?:because|since|until|due to|so that|otherwise|which is why|in order to|to avoid|to work around|to prevent)\b/i;
585
+ var JUSTIFICATION_RE = /\b(?:because|since|until|due to|so that|so we|so it|so the|otherwise|which is why|in order to|to avoid|to work around|to prevent|backwards? compat(?:ibility)?|for compatibility)\b/i;
586
+ function restatesWholeStatement(body, statement) {
587
+ return statement !== null && restatesStatementHead(body, statement.replaceAll("(", " "));
588
+ }
616
589
  function isRedundantNarration(body, statementBelow, standalone, isolatedEnumeration, nested) {
617
590
  const t = body.trim();
618
591
  if (!t || looksLikeCode(t) || hasPseudocode(t)) return false;
619
592
  if (standalone) {
620
- if (STEP_NARRATION_RE.test(t)) return true;
621
- if (META_COMMENTARY_RE.test(t) && !JUSTIFICATION_RE.test(t)) return true;
593
+ const justified = JUSTIFICATION_RE.test(t);
594
+ if (STEP_NARRATION_RE.test(t) && !justified) return true;
595
+ if (META_COMMENTARY_RE.test(t) && !justified) return true;
622
596
  if (HELPER_OPENER_RE.test(t) || LETS_RE.test(t)) return true;
623
597
  const words = t.split(/\s+/);
624
- if (words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
598
+ if (words.length > 1 && words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
625
599
  const lowerT = t.toLowerCase();
626
600
  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;
601
+ if (!rationaleWords.some((w) => lowerT.includes(w)) && restatesWholeStatement(t, statementBelow)) {
602
+ return true;
629
603
  }
630
604
  }
631
605
  if (!nested && isSectionLabel(t)) return true;
@@ -634,13 +608,17 @@ function isRedundantNarration(body, statementBelow, standalone, isolatedEnumerat
634
608
  return restatesStatementHead(t, statementBelow);
635
609
  }
636
610
  var STATEMENT_CONTAINERS = /* @__PURE__ */ new Set([
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
611
+ import_utils4.AST_NODE_TYPES.Program,
612
+ import_utils4.AST_NODE_TYPES.BlockStatement,
613
+ import_utils4.AST_NODE_TYPES.ClassBody,
614
+ import_utils4.AST_NODE_TYPES.StaticBlock,
615
+ import_utils4.AST_NODE_TYPES.SwitchCase,
616
+ import_utils4.AST_NODE_TYPES.TSModuleBlock,
617
+ import_utils4.AST_NODE_TYPES.TSInterfaceBody
618
+ ]);
619
+ var TYPE_MEMBER_CONTAINERS = /* @__PURE__ */ new Set([
620
+ import_utils4.AST_NODE_TYPES.TSInterfaceBody,
621
+ import_utils4.AST_NODE_TYPES.TSTypeLiteral
644
622
  ]);
645
623
  function runCitesAReference(comments, index) {
646
624
  for (let i = index; i >= 0; i--) {
@@ -669,10 +647,10 @@ function hasIllustrationLeadInAbove(comments, index) {
669
647
  }
670
648
  return false;
671
649
  }
672
- function hasCommentedOutCode(texts, precedingProse) {
650
+ function hasCommentedOutCode(texts, precedingProse, allowCall) {
673
651
  for (let i = 0; i < texts.length; i++) {
674
652
  const line = texts[i];
675
- if (line === void 0 || !looksLikeCode(line) || hasPseudocode(line)) {
653
+ if (line === void 0 || !looksLikeCode(line, allowCall) || hasPseudocode(line)) {
676
654
  continue;
677
655
  }
678
656
  const prev = i > 0 ? texts[i - 1] : void 0;
@@ -681,7 +659,7 @@ function hasCommentedOutCode(texts, precedingProse) {
681
659
  }
682
660
  return false;
683
661
  }
684
- var no_comment_cruft_default = import_utils5.ESLintUtils.RuleCreator(
662
+ var no_comment_cruft_default = import_utils4.ESLintUtils.RuleCreator(
685
663
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
686
664
  )({
687
665
  name: "no-comment-cruft",
@@ -766,7 +744,9 @@ var no_comment_cruft_default = import_utils5.ESLintUtils.RuleCreator(
766
744
  }
767
745
  const prev = comments[i - 1];
768
746
  const precedingProse = prev !== void 0 && prev.type === "Line" && prev.loc.end.line === comment.loc.start.line - 1 && isProse(stripCommentMarker(prev.value));
769
- if (hasCommentedOutCode(texts, precedingProse) && !hasIllustrationLeadInAbove(comments, i)) {
747
+ const container = sourceCode.getNodeByRangeIndex(comment.range[0]);
748
+ const inTypeMembers = container !== null && TYPE_MEMBER_CONTAINERS.has(container.type);
749
+ if (hasCommentedOutCode(texts, precedingProse, !inTypeMembers) && !hasIllustrationLeadInAbove(comments, i)) {
770
750
  context.report({ node: comment, messageId: "commentedOutCode" });
771
751
  continue;
772
752
  }
@@ -774,7 +754,6 @@ var no_comment_cruft_default = import_utils5.ESLintUtils.RuleCreator(
774
754
  const body = texts[0];
775
755
  const statement = restatableStatementBelow(comment, sourceCode);
776
756
  const standalone = !isInsideCommentRun(comments, i);
777
- const container = sourceCode.getNodeByRangeIndex(comment.range[0]);
778
757
  const nested = container !== null && !STATEMENT_CONTAINERS.has(container.type);
779
758
  if (body !== void 0 && !runCitesAReference(comments, i) && isRedundantNarration(body, statement, standalone, enumerated.length === 1, nested)) {
780
759
  context.report({ node: comment, messageId: "redundantNarration" });
@@ -788,7 +767,7 @@ var no_comment_cruft_default = import_utils5.ESLintUtils.RuleCreator(
788
767
  });
789
768
 
790
769
  // src/rules/no-enum.ts
791
- var import_utils6 = require("@typescript-eslint/utils");
770
+ var import_utils5 = require("@typescript-eslint/utils");
792
771
  var DEFAULT_IGNORE_PATTERNS = [
793
772
  /[\\/]generated[\\/]/,
794
773
  /[\\/]openapi-gen[\\/]/,
@@ -808,7 +787,7 @@ function hasGeneratedMarker(sourceText) {
808
787
  const head = sourceText.slice(0, 1024);
809
788
  return /@generated\b/.test(head);
810
789
  }
811
- var no_enum_default = import_utils6.ESLintUtils.RuleCreator(
790
+ var no_enum_default = import_utils5.ESLintUtils.RuleCreator(
812
791
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
813
792
  )({
814
793
  name: "no-enum",
@@ -859,7 +838,7 @@ var no_enum_default = import_utils6.ESLintUtils.RuleCreator(
859
838
  });
860
839
 
861
840
  // src/rules/no-insecure-random-id.ts
862
- var import_utils7 = require("@typescript-eslint/utils");
841
+ var import_utils6 = require("@typescript-eslint/utils");
863
842
  var STRONG_SECURITY_PATTERN = /token|secret|csrf|password|passwd|apikey|api[-_]?key|nonce|salt|uuid|authid/i;
864
843
  var NON_SECURITY_ID_PATTERN = /temp|tmp|cache|correlation|request|req|trace|execution|dev|hmr|mock|test|perf|marker/i;
865
844
  var PATH_OR_DOM_MARKER = /[\\/#]|\.[A-Za-z0-9]/;
@@ -1000,7 +979,7 @@ function isConcatenatedIntoPathOrDomId(node) {
1000
979
  collectStaticStringParts(top, parts);
1001
980
  return parts.some((part) => PATH_OR_DOM_MARKER.test(part));
1002
981
  }
1003
- var no_insecure_random_id_default = import_utils7.ESLintUtils.RuleCreator(
982
+ var no_insecure_random_id_default = import_utils6.ESLintUtils.RuleCreator(
1004
983
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1005
984
  )({
1006
985
  name: "no-insecure-random-id",
@@ -1044,7 +1023,7 @@ var no_insecure_random_id_default = import_utils7.ESLintUtils.RuleCreator(
1044
1023
  });
1045
1024
 
1046
1025
  // src/rules/no-json-stringify-error.ts
1047
- var import_utils8 = require("@typescript-eslint/utils");
1026
+ var import_utils7 = require("@typescript-eslint/utils");
1048
1027
  var ERROR_NAME_PATTERN = /^(e|err|error|ex|exc)$/i;
1049
1028
  var ERROR_PROP_PATTERN = /^(cause|lastError|error|err|exception|originalError|innerError)$/i;
1050
1029
  var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
@@ -1178,7 +1157,7 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
1178
1157
  function isJsonStringify(callee) {
1179
1158
  return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "stringify";
1180
1159
  }
1181
- var no_json_stringify_error_default = import_utils8.ESLintUtils.RuleCreator(
1160
+ var no_json_stringify_error_default = import_utils7.ESLintUtils.RuleCreator(
1182
1161
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1183
1162
  )({
1184
1163
  name: "no-json-stringify-error",
@@ -1228,10 +1207,10 @@ var no_json_stringify_error_default = import_utils8.ESLintUtils.RuleCreator(
1228
1207
  });
1229
1208
 
1230
1209
  // src/rules/no-log-only-catch.ts
1231
- var import_utils10 = require("@typescript-eslint/utils");
1210
+ var import_utils9 = require("@typescript-eslint/utils");
1232
1211
 
1233
1212
  // src/rules/_logging.ts
1234
- var import_utils9 = require("@typescript-eslint/utils");
1213
+ var import_utils8 = require("@typescript-eslint/utils");
1235
1214
  var LOG_METHODS = /* @__PURE__ */ new Set([
1236
1215
  "debug",
1237
1216
  "info",
@@ -1333,12 +1312,92 @@ function createLogMatcher(options = {}) {
1333
1312
  }
1334
1313
 
1335
1314
  // src/rules/no-log-only-catch.ts
1336
- var DEFAULT_IGNORE_PATTERNS2 = [
1337
- /\.test\./,
1338
- /\.spec\./,
1339
- /[\\/]__tests__[\\/]/
1340
- ];
1341
- var no_log_only_catch_default = import_utils10.ESLintUtils.RuleCreator(
1315
+ var BENCHMARK_DIR_RE = /(?:^|[\\/])benchmarks?[\\/]/;
1316
+ var SINGLE_STATEMENT_HOSTS = /* @__PURE__ */ new Set([
1317
+ import_utils9.AST_NODE_TYPES.DoWhileStatement,
1318
+ import_utils9.AST_NODE_TYPES.ForInStatement,
1319
+ import_utils9.AST_NODE_TYPES.ForOfStatement,
1320
+ import_utils9.AST_NODE_TYPES.ForStatement,
1321
+ import_utils9.AST_NODE_TYPES.IfStatement,
1322
+ import_utils9.AST_NODE_TYPES.WhileStatement
1323
+ ]);
1324
+ var FUNCTION_TYPES = /* @__PURE__ */ new Set([
1325
+ import_utils9.AST_NODE_TYPES.ArrowFunctionExpression,
1326
+ import_utils9.AST_NODE_TYPES.FunctionDeclaration,
1327
+ import_utils9.AST_NODE_TYPES.FunctionExpression
1328
+ ]);
1329
+ function statementSlot(node) {
1330
+ const parent = node.parent;
1331
+ if (parent === void 0) return null;
1332
+ let list;
1333
+ switch (parent.type) {
1334
+ case import_utils9.AST_NODE_TYPES.BlockStatement:
1335
+ case import_utils9.AST_NODE_TYPES.Program:
1336
+ case import_utils9.AST_NODE_TYPES.StaticBlock:
1337
+ list = parent.body;
1338
+ break;
1339
+ case import_utils9.AST_NODE_TYPES.SwitchCase:
1340
+ list = parent.consequent;
1341
+ break;
1342
+ default:
1343
+ return null;
1344
+ }
1345
+ const index = list.indexOf(node);
1346
+ return index === -1 ? null : { list, index };
1347
+ }
1348
+ function hasFollowingStatement(node) {
1349
+ for (let current = node; current !== void 0 && !FUNCTION_TYPES.has(current.type); current = current.parent) {
1350
+ const slot = statementSlot(current);
1351
+ if (slot !== null && slot.index < slot.list.length - 1) return true;
1352
+ }
1353
+ return false;
1354
+ }
1355
+ function fallbackFollowsTry(tryStatement) {
1356
+ const body = tryStatement.block.body;
1357
+ const last = body.at(-1);
1358
+ return last?.type === import_utils9.AST_NODE_TYPES.ReturnStatement && hasFollowingStatement(tryStatement);
1359
+ }
1360
+ function isSeedValue(node) {
1361
+ const inner = node.type === import_utils9.AST_NODE_TYPES.TSAsExpression ? node.expression : node;
1362
+ switch (inner.type) {
1363
+ case import_utils9.AST_NODE_TYPES.Literal:
1364
+ return true;
1365
+ case import_utils9.AST_NODE_TYPES.Identifier:
1366
+ return inner.name === "undefined";
1367
+ case import_utils9.AST_NODE_TYPES.UnaryExpression:
1368
+ return inner.argument.type === import_utils9.AST_NODE_TYPES.Literal;
1369
+ case import_utils9.AST_NODE_TYPES.ArrayExpression:
1370
+ return inner.elements.length === 0;
1371
+ case import_utils9.AST_NODE_TYPES.ObjectExpression:
1372
+ return inner.properties.length === 0;
1373
+ default:
1374
+ return false;
1375
+ }
1376
+ }
1377
+ function seededFallbackHandled(tryStatement, scope) {
1378
+ const slot = statementSlot(tryStatement);
1379
+ if (slot === null || slot.index === 0) return false;
1380
+ const previous = slot.list[slot.index - 1];
1381
+ if (previous?.type !== import_utils9.AST_NODE_TYPES.VariableDeclaration || previous.kind === "const") {
1382
+ return false;
1383
+ }
1384
+ const declarator = previous.declarations[0];
1385
+ if (previous.declarations.length !== 1 || declarator === void 0) return false;
1386
+ if (declarator.id.type !== import_utils9.AST_NODE_TYPES.Identifier) return false;
1387
+ if (declarator.init == null || !isSeedValue(declarator.init)) return false;
1388
+ const variable = import_utils9.ASTUtils.findVariable(scope, declarator.id.name);
1389
+ if (variable === null) return false;
1390
+ const [tryStart, tryEnd] = tryStatement.block.range;
1391
+ let writtenInTry = false;
1392
+ let readAfter = false;
1393
+ for (const reference of variable.references) {
1394
+ const [start] = reference.identifier.range;
1395
+ if (reference.isWrite() && start >= tryStart && start < tryEnd) writtenInTry = true;
1396
+ if (reference.isRead() && start >= tryStatement.range[1]) readAfter = true;
1397
+ }
1398
+ return writtenInTry && readAfter;
1399
+ }
1400
+ var no_log_only_catch_default = import_utils9.ESLintUtils.RuleCreator(
1342
1401
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1343
1402
  )({
1344
1403
  name: "no-log-only-catch",
@@ -1363,26 +1422,40 @@ var no_log_only_catch_default = import_utils10.ESLintUtils.RuleCreator(
1363
1422
  create(context, [loggingOptions]) {
1364
1423
  const matcher = createLogMatcher(loggingOptions);
1365
1424
  const filename = context.filename;
1425
+ const sourceCode = context.sourceCode;
1366
1426
  function isLoggingCallStatement(statement) {
1367
1427
  if (statement.type !== "ExpressionStatement") {
1368
1428
  return false;
1369
1429
  }
1370
1430
  return matcher.isLoggingCall(statement.expression);
1371
1431
  }
1372
- const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS2.some(
1373
- (re) => re.test(filename)
1374
- );
1375
- if (isIgnoredByDefault) {
1432
+ function hasCommentDirectlyAbove(node) {
1433
+ const above = sourceCode.getCommentsBefore(node).at(-1);
1434
+ return above !== void 0 && above.loc.end.line === node.loc.start.line - 1;
1435
+ }
1436
+ function hasAdjacentRationale(node) {
1437
+ const tryStatement = node.parent;
1438
+ if (hasCommentDirectlyAbove(tryStatement) || hasCommentDirectlyAbove(node)) return true;
1439
+ const block = tryStatement.parent;
1440
+ if (block?.type !== import_utils9.AST_NODE_TYPES.BlockStatement || block.body.length !== 1 || block.parent === void 0 || !SINGLE_STATEMENT_HOSTS.has(block.parent.type)) {
1441
+ return false;
1442
+ }
1443
+ return hasCommentDirectlyAbove(block.parent);
1444
+ }
1445
+ if (isTestFile(filename) || BENCHMARK_DIR_RE.test(filename.replaceAll("\\", "/"))) {
1376
1446
  return {};
1377
1447
  }
1378
1448
  return {
1379
1449
  CatchClause(node) {
1380
1450
  const statements = node.body.body;
1381
- const isDocumented = context.sourceCode.getCommentsInside(node.body).length > 0;
1451
+ const isDocumented = sourceCode.getCommentsInside(node.body).length > 0 || hasAdjacentRationale(node);
1382
1452
  if (statements.length === 0) {
1383
1453
  if (isDocumented) {
1384
1454
  return;
1385
1455
  }
1456
+ if (fallbackFollowsTry(node.parent) || seededFallbackHandled(node.parent, sourceCode.getScope(node))) {
1457
+ return;
1458
+ }
1386
1459
  context.report({ node, messageId: "emptyCatch" });
1387
1460
  return;
1388
1461
  }
@@ -1401,11 +1474,12 @@ var no_log_only_catch_default = import_utils10.ESLintUtils.RuleCreator(
1401
1474
  });
1402
1475
 
1403
1476
  // src/rules/no-raw-env.ts
1404
- var import_utils11 = require("@typescript-eslint/utils");
1477
+ var import_utils10 = require("@typescript-eslint/utils");
1405
1478
  var CONFIG_FILE_RE = /(^|[\\/])[\w.-]+\.config\.[cm]?[jt]sx?$/;
1406
1479
  var ENV_BOUNDARY_FILE_RE = /(^|[\\/])(?:env|client-env|server-env|client-settings|server-settings)\.[cm]?[jt]sx?$/;
1480
+ var ENV_VALIDATION_MARKER_RE = /\bcreateEnv\s*\(|\bz\.object\s*\(|\.(?:safeParse|parse)\s*\(/;
1407
1481
  function isValidatedEnvBoundary(filename, sourceText) {
1408
- return ENV_BOUNDARY_FILE_RE.test(filename.replaceAll("\\", "/")) && /\bz\.object\s*\(/.test(sourceText) && /\.parse\s*\(/.test(sourceText);
1482
+ return ENV_BOUNDARY_FILE_RE.test(filename.replaceAll("\\", "/")) && ENV_VALIDATION_MARKER_RE.test(sourceText);
1409
1483
  }
1410
1484
  function isProcessEnv(node) {
1411
1485
  return !node.computed && node.object.type === "Identifier" && node.object.name === "process" && node.property.type === "Identifier" && node.property.name === "env";
@@ -1420,9 +1494,15 @@ var BUILD_TIME_CONSTANTS = /* @__PURE__ */ new Set([
1420
1494
  "PROD",
1421
1495
  "SSR"
1422
1496
  ]);
1423
- function isBuildTimeConstantAccess(node) {
1497
+ var PLATFORM_MARKERS = /* @__PURE__ */ new Set([
1498
+ "NEXT_RUNTIME",
1499
+ "VERCEL",
1500
+ "VERCEL_ENV",
1501
+ "CI"
1502
+ ]);
1503
+ function isExemptVariableAccess(node) {
1424
1504
  const parent = node.parent;
1425
- return parent.type === "MemberExpression" && parent.object === node && !parent.computed && parent.property.type === "Identifier" && BUILD_TIME_CONSTANTS.has(parent.property.name);
1505
+ return parent.type === "MemberExpression" && parent.object === node && !parent.computed && parent.property.type === "Identifier" && (BUILD_TIME_CONSTANTS.has(parent.property.name) || PLATFORM_MARKERS.has(parent.property.name));
1426
1506
  }
1427
1507
  function isWriteTarget(node) {
1428
1508
  const access = node.parent.type === "MemberExpression" && node.parent.object === node ? node.parent : node;
@@ -1439,7 +1519,7 @@ function isWholeEnvSpread(node) {
1439
1519
  const parent = node.parent;
1440
1520
  return parent.type === "SpreadElement" && parent.argument === node;
1441
1521
  }
1442
- var no_raw_env_default = import_utils11.ESLintUtils.RuleCreator(
1522
+ var no_raw_env_default = import_utils10.ESLintUtils.RuleCreator(
1443
1523
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1444
1524
  )({
1445
1525
  name: "no-raw-env",
@@ -1461,7 +1541,7 @@ var no_raw_env_default = import_utils11.ESLintUtils.RuleCreator(
1461
1541
  }
1462
1542
  return {
1463
1543
  MemberExpression(node) {
1464
- if ((isProcessEnv(node) || isImportMetaEnv(node)) && !isBuildTimeConstantAccess(node) && !isWriteTarget(node) && !isWholeEnvSpread(node)) {
1544
+ if ((isProcessEnv(node) || isImportMetaEnv(node)) && !isExemptVariableAccess(node) && !isWriteTarget(node) && !isWholeEnvSpread(node)) {
1465
1545
  context.report({
1466
1546
  node,
1467
1547
  messageId: "noRawEnv"
@@ -1473,12 +1553,12 @@ var no_raw_env_default = import_utils11.ESLintUtils.RuleCreator(
1473
1553
  });
1474
1554
 
1475
1555
  // src/rules/no-sentinel-return-on-catch.ts
1476
- var import_utils12 = require("@typescript-eslint/utils");
1556
+ var import_utils11 = require("@typescript-eslint/utils");
1477
1557
  function sentinelKind(arg) {
1478
1558
  if (arg === null) {
1479
1559
  return null;
1480
1560
  }
1481
- if (arg.type === import_utils12.AST_NODE_TYPES.Literal) {
1561
+ if (arg.type === import_utils11.AST_NODE_TYPES.Literal) {
1482
1562
  if (arg.value === null) {
1483
1563
  return "nullish";
1484
1564
  }
@@ -1490,13 +1570,13 @@ function sentinelKind(arg) {
1490
1570
  }
1491
1571
  return null;
1492
1572
  }
1493
- if (arg.type === import_utils12.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1573
+ if (arg.type === import_utils11.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1494
1574
  return "nullish";
1495
1575
  }
1496
- if (arg.type === import_utils12.AST_NODE_TYPES.ArrayExpression) {
1576
+ if (arg.type === import_utils11.AST_NODE_TYPES.ArrayExpression) {
1497
1577
  return "array";
1498
1578
  }
1499
- if (arg.type === import_utils12.AST_NODE_TYPES.ObjectExpression) {
1579
+ if (arg.type === import_utils11.AST_NODE_TYPES.ObjectExpression) {
1500
1580
  return "object";
1501
1581
  }
1502
1582
  return null;
@@ -1505,25 +1585,25 @@ function isSentinelArgument(arg) {
1505
1585
  if (arg === null) {
1506
1586
  return false;
1507
1587
  }
1508
- if (arg.type === import_utils12.AST_NODE_TYPES.Literal && arg.value === null) {
1588
+ if (arg.type === import_utils11.AST_NODE_TYPES.Literal && arg.value === null) {
1509
1589
  return true;
1510
1590
  }
1511
- if (arg.type === import_utils12.AST_NODE_TYPES.Literal && arg.value === false) {
1591
+ if (arg.type === import_utils11.AST_NODE_TYPES.Literal && arg.value === false) {
1512
1592
  return true;
1513
1593
  }
1514
- if (arg.type === import_utils12.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1594
+ if (arg.type === import_utils11.AST_NODE_TYPES.Identifier && arg.name === "undefined") {
1515
1595
  return true;
1516
1596
  }
1517
- if (arg.type === import_utils12.AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {
1597
+ if (arg.type === import_utils11.AST_NODE_TYPES.ArrayExpression && arg.elements.length === 0) {
1518
1598
  return true;
1519
1599
  }
1520
- if (arg.type === import_utils12.AST_NODE_TYPES.ObjectExpression && arg.properties.length === 0) {
1600
+ if (arg.type === import_utils11.AST_NODE_TYPES.ObjectExpression && arg.properties.length === 0) {
1521
1601
  return true;
1522
1602
  }
1523
1603
  return false;
1524
1604
  }
1525
1605
  function isFunctionNode(node) {
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;
1606
+ 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;
1527
1607
  }
1528
1608
  function isNode(value) {
1529
1609
  return typeof value === "object" && value !== null && typeof value.type === "string";
@@ -1563,24 +1643,24 @@ function walkWithinScope(node, visit) {
1563
1643
  function containsThrow(node) {
1564
1644
  return walkWithinScope(
1565
1645
  node,
1566
- (current) => current.type === import_utils12.AST_NODE_TYPES.ThrowStatement
1646
+ (current) => current.type === import_utils11.AST_NODE_TYPES.ThrowStatement
1567
1647
  );
1568
1648
  }
1569
1649
  function bindsName(param, name) {
1570
1650
  switch (param.type) {
1571
- case import_utils12.AST_NODE_TYPES.Identifier:
1651
+ case import_utils11.AST_NODE_TYPES.Identifier:
1572
1652
  return param.name === name;
1573
- case import_utils12.AST_NODE_TYPES.AssignmentPattern:
1653
+ case import_utils11.AST_NODE_TYPES.AssignmentPattern:
1574
1654
  return bindsName(param.left, name);
1575
- case import_utils12.AST_NODE_TYPES.RestElement:
1655
+ case import_utils11.AST_NODE_TYPES.RestElement:
1576
1656
  return bindsName(param.argument, name);
1577
- case import_utils12.AST_NODE_TYPES.ArrayPattern:
1657
+ case import_utils11.AST_NODE_TYPES.ArrayPattern:
1578
1658
  return param.elements.some(
1579
1659
  (element) => element !== null && bindsName(element, name)
1580
1660
  );
1581
- case import_utils12.AST_NODE_TYPES.ObjectPattern:
1661
+ case import_utils11.AST_NODE_TYPES.ObjectPattern:
1582
1662
  return param.properties.some(
1583
- (property) => property.type === import_utils12.AST_NODE_TYPES.RestElement ? bindsName(property.argument, name) : bindsName(property.value, name)
1663
+ (property) => property.type === import_utils11.AST_NODE_TYPES.RestElement ? bindsName(property.argument, name) : bindsName(property.value, name)
1584
1664
  );
1585
1665
  default:
1586
1666
  return false;
@@ -1595,7 +1675,7 @@ function subtreeReadsName(node, name) {
1595
1675
  if (found) {
1596
1676
  return;
1597
1677
  }
1598
- if (current.type === import_utils12.AST_NODE_TYPES.Identifier && current.name === name) {
1678
+ if (current.type === import_utils11.AST_NODE_TYPES.Identifier && current.name === name) {
1599
1679
  found = true;
1600
1680
  return;
1601
1681
  }
@@ -1606,10 +1686,10 @@ function subtreeReadsName(node, name) {
1606
1686
  if (key === "parent") {
1607
1687
  continue;
1608
1688
  }
1609
- if (key === "key" && current.type === import_utils12.AST_NODE_TYPES.Property && !current.computed) {
1689
+ if (key === "key" && current.type === import_utils11.AST_NODE_TYPES.Property && !current.computed) {
1610
1690
  continue;
1611
1691
  }
1612
- if (key === "property" && current.type === import_utils12.AST_NODE_TYPES.MemberExpression && !current.computed) {
1692
+ if (key === "property" && current.type === import_utils11.AST_NODE_TYPES.MemberExpression && !current.computed) {
1613
1693
  continue;
1614
1694
  }
1615
1695
  const value = current[key];
@@ -1642,10 +1722,10 @@ var SAFE_PARSE_CONSTRUCTORS = /* @__PURE__ */ new Set([
1642
1722
  "URLPattern"
1643
1723
  ]);
1644
1724
  function isParseShapedNode(node) {
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) {
1725
+ 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) {
1646
1726
  return node.callee.property.name === "parse";
1647
1727
  }
1648
- if (node.type === import_utils12.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils12.AST_NODE_TYPES.Identifier) {
1728
+ if (node.type === import_utils11.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils11.AST_NODE_TYPES.Identifier) {
1649
1729
  return SAFE_PARSE_CONSTRUCTORS.has(node.callee.name);
1650
1730
  }
1651
1731
  return false;
@@ -1656,10 +1736,10 @@ var BODY_DECODE_METHODS = /* @__PURE__ */ new Set([
1656
1736
  "arrayBuffer"
1657
1737
  ]);
1658
1738
  function isBodyDecodeNode(node) {
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);
1739
+ 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);
1660
1740
  }
1661
1741
  function returnsMatching(stmt, predicate) {
1662
- return stmt.type === import_utils12.AST_NODE_TYPES.ReturnStatement && stmt.argument !== null && walkWithinScope(stmt.argument, predicate);
1742
+ return stmt.type === import_utils11.AST_NODE_TYPES.ReturnStatement && stmt.argument !== null && walkWithinScope(stmt.argument, predicate);
1663
1743
  }
1664
1744
  function enclosingReturnTypeNode(node) {
1665
1745
  let current = node.parent;
@@ -1677,11 +1757,11 @@ function enclosingFunctionName(node) {
1677
1757
  let current = node.parent;
1678
1758
  while (current !== void 0 && current !== null) {
1679
1759
  if (isFunctionNode(current)) {
1680
- if ("id" in current && isNode(current.id) && current.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
1760
+ if ("id" in current && isNode(current.id) && current.id.type === import_utils11.AST_NODE_TYPES.Identifier) {
1681
1761
  return current.id.name;
1682
1762
  }
1683
1763
  const parent = current.parent;
1684
- if (parent?.type === import_utils12.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils12.AST_NODE_TYPES.Identifier) {
1764
+ if (parent?.type === import_utils11.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils11.AST_NODE_TYPES.Identifier) {
1685
1765
  return parent.id.name;
1686
1766
  }
1687
1767
  return null;
@@ -1702,10 +1782,10 @@ function isDeclaredBooleanPredicate(catchNode, kind) {
1702
1782
  return false;
1703
1783
  }
1704
1784
  let declared = enclosingReturnTypeNode(catchNode);
1705
- if (declared?.type === import_utils12.AST_NODE_TYPES.TSTypeReference && declared.typeName.type === import_utils12.AST_NODE_TYPES.Identifier && declared.typeName.name === "Promise") {
1785
+ if (declared?.type === import_utils11.AST_NODE_TYPES.TSTypeReference && declared.typeName.type === import_utils11.AST_NODE_TYPES.Identifier && declared.typeName.name === "Promise") {
1706
1786
  declared = declared.typeArguments?.params[0] ?? null;
1707
1787
  }
1708
- return declared?.type === import_utils12.AST_NODE_TYPES.TSBooleanKeyword;
1788
+ return declared?.type === import_utils11.AST_NODE_TYPES.TSBooleanKeyword;
1709
1789
  }
1710
1790
  function tryReturnsSafeParse(catchNode) {
1711
1791
  const tryBlock = tryBlockOf(catchNode);
@@ -1721,7 +1801,7 @@ function tryReturnsSafeParse(catchNode) {
1721
1801
  function enclosingFunctionBody(node) {
1722
1802
  let current = node.parent;
1723
1803
  while (current !== void 0 && current !== null) {
1724
- if (isFunctionNode(current) && "body" in current && isNode(current.body) && current.body.type === import_utils12.AST_NODE_TYPES.BlockStatement) {
1804
+ if (isFunctionNode(current) && "body" in current && isNode(current.body) && current.body.type === import_utils11.AST_NODE_TYPES.BlockStatement) {
1725
1805
  return current.body;
1726
1806
  }
1727
1807
  current = current.parent;
@@ -1734,7 +1814,7 @@ function functionReturnsSameSentinelKindElsewhere(catchNode, kind) {
1734
1814
  return false;
1735
1815
  }
1736
1816
  return walkWithinScope(functionBody, (current) => {
1737
- if (current.type !== import_utils12.AST_NODE_TYPES.ReturnStatement) {
1817
+ if (current.type !== import_utils11.AST_NODE_TYPES.ReturnStatement) {
1738
1818
  return false;
1739
1819
  }
1740
1820
  if (isWithin(current, catchNode.body)) {
@@ -1753,13 +1833,13 @@ function returnedSentinelKinds(arg) {
1753
1833
  kinds.add(direct);
1754
1834
  return kinds;
1755
1835
  }
1756
- if (arg.type === import_utils12.AST_NODE_TYPES.ConditionalExpression) {
1836
+ if (arg.type === import_utils11.AST_NODE_TYPES.ConditionalExpression) {
1757
1837
  for (const branch of [arg.consequent, arg.alternate]) {
1758
1838
  for (const nested of returnedSentinelKinds(branch)) {
1759
1839
  kinds.add(nested);
1760
1840
  }
1761
1841
  }
1762
- } else if (arg.type === import_utils12.AST_NODE_TYPES.LogicalExpression && (arg.operator === "??" || arg.operator === "||")) {
1842
+ } else if (arg.type === import_utils11.AST_NODE_TYPES.LogicalExpression && (arg.operator === "??" || arg.operator === "||")) {
1763
1843
  for (const nested of returnedSentinelKinds(arg.right)) {
1764
1844
  kinds.add(nested);
1765
1845
  }
@@ -1776,7 +1856,7 @@ function isWithin(node, ancestor) {
1776
1856
  }
1777
1857
  return false;
1778
1858
  }
1779
- var no_sentinel_return_on_catch_default = import_utils12.ESLintUtils.RuleCreator(
1859
+ var no_sentinel_return_on_catch_default = import_utils11.ESLintUtils.RuleCreator(
1780
1860
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1781
1861
  )({
1782
1862
  name: "no-sentinel-return-on-catch",
@@ -1804,7 +1884,7 @@ var no_sentinel_return_on_catch_default = import_utils12.ESLintUtils.RuleCreator
1804
1884
  const matcher = createLogMatcher(loggingOptions);
1805
1885
  function logsOrReportsError(catchBody, caughtName) {
1806
1886
  return walkWithinScope(catchBody, (current) => {
1807
- if (current.type !== import_utils12.AST_NODE_TYPES.CallExpression) {
1887
+ if (current.type !== import_utils11.AST_NODE_TYPES.CallExpression) {
1808
1888
  return false;
1809
1889
  }
1810
1890
  if (matcher.isLoggingCall(current)) {
@@ -1821,7 +1901,7 @@ var no_sentinel_return_on_catch_default = import_utils12.ESLintUtils.RuleCreator
1821
1901
  return;
1822
1902
  }
1823
1903
  const last = body[body.length - 1];
1824
- if (last === void 0 || last.type !== import_utils12.AST_NODE_TYPES.ReturnStatement) {
1904
+ if (last === void 0 || last.type !== import_utils11.AST_NODE_TYPES.ReturnStatement) {
1825
1905
  return;
1826
1906
  }
1827
1907
  if (!isSentinelArgument(last.argument)) {
@@ -1830,7 +1910,7 @@ var no_sentinel_return_on_catch_default = import_utils12.ESLintUtils.RuleCreator
1830
1910
  if (containsThrow(node.body)) {
1831
1911
  return;
1832
1912
  }
1833
- const caughtName = node.param?.type === import_utils12.AST_NODE_TYPES.Identifier ? node.param.name : null;
1913
+ const caughtName = node.param?.type === import_utils11.AST_NODE_TYPES.Identifier ? node.param.name : null;
1834
1914
  if (logsOrReportsError(node.body, caughtName)) {
1835
1915
  return;
1836
1916
  }
@@ -1857,7 +1937,7 @@ var no_sentinel_return_on_catch_default = import_utils12.ESLintUtils.RuleCreator
1857
1937
  });
1858
1938
 
1859
1939
  // src/rules/no-string-concat-in-loop.ts
1860
- var import_utils13 = require("@typescript-eslint/utils");
1940
+ var import_utils12 = require("@typescript-eslint/utils");
1861
1941
  var LOOP_NODE_TYPES = /* @__PURE__ */ new Set([
1862
1942
  "ForStatement",
1863
1943
  "ForOfStatement",
@@ -1942,7 +2022,7 @@ function enclosingLoop(node) {
1942
2022
  }
1943
2023
  return null;
1944
2024
  }
1945
- var no_string_concat_in_loop_default = import_utils13.ESLintUtils.RuleCreator(
2025
+ var no_string_concat_in_loop_default = import_utils12.ESLintUtils.RuleCreator(
1946
2026
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1947
2027
  )({
1948
2028
  name: "no-string-concat-in-loop",
@@ -2005,7 +2085,7 @@ var no_string_concat_in_loop_default = import_utils13.ESLintUtils.RuleCreator(
2005
2085
  });
2006
2086
 
2007
2087
  // src/rules/no-unnecessary-use-client.ts
2008
- var import_utils14 = require("@typescript-eslint/utils");
2088
+ var import_utils13 = require("@typescript-eslint/utils");
2009
2089
  var HOOK_REGEX = /^use([A-Z]|$)/;
2010
2090
  var EVENT_PROP_REGEX = /^on[A-Z]/;
2011
2091
  var ERROR_FILE_REGEX = /\b(?:global-)?error\.[jt]sx?$/;
@@ -2031,13 +2111,13 @@ var CLIENT_ONLY_PACKAGES_REGEX = /^(?:@radix-ui\/|framer-motion|react-dom|react-
2031
2111
  var isBareSpecifier = (source) => !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("@/") && !source.startsWith("~");
2032
2112
  var jsxRootName = (name) => {
2033
2113
  let current = name;
2034
- while (current.type === import_utils14.AST_NODE_TYPES.JSXMemberExpression) {
2114
+ while (current.type === import_utils13.AST_NODE_TYPES.JSXMemberExpression) {
2035
2115
  current = current.object;
2036
2116
  }
2037
- return current.type === import_utils14.AST_NODE_TYPES.JSXIdentifier ? current.name : "";
2117
+ return current.type === import_utils13.AST_NODE_TYPES.JSXIdentifier ? current.name : "";
2038
2118
  };
2039
2119
  var subtreeReadsImportedBinding = (node, imported) => {
2040
- if (node.type === import_utils14.AST_NODE_TYPES.Identifier) {
2120
+ if (node.type === import_utils13.AST_NODE_TYPES.Identifier) {
2041
2121
  return imported.has(node.name);
2042
2122
  }
2043
2123
  for (const key of Object.keys(node)) {
@@ -2052,16 +2132,16 @@ var subtreeReadsImportedBinding = (node, imported) => {
2052
2132
  return false;
2053
2133
  };
2054
2134
  var isUseClientDirective = (node) => {
2055
- return node.type === import_utils14.AST_NODE_TYPES.ExpressionStatement && node.expression.type === import_utils14.AST_NODE_TYPES.Literal && node.expression.value === "use client";
2135
+ return node.type === import_utils13.AST_NODE_TYPES.ExpressionStatement && node.expression.type === import_utils13.AST_NODE_TYPES.Literal && node.expression.value === "use client";
2056
2136
  };
2057
2137
  var isGlobalReference = (node, context) => {
2058
2138
  if (!BROWSER_GLOBALS.has(node.name)) return false;
2059
2139
  const parent = node.parent;
2060
2140
  if (parent !== void 0) {
2061
- if (parent.type === import_utils14.AST_NODE_TYPES.MemberExpression && parent.property === node && !parent.computed) {
2141
+ if (parent.type === import_utils13.AST_NODE_TYPES.MemberExpression && parent.property === node && !parent.computed) {
2062
2142
  return false;
2063
2143
  }
2064
- if (parent.type === import_utils14.AST_NODE_TYPES.Property && parent.key === node && !parent.computed) {
2144
+ if (parent.type === import_utils13.AST_NODE_TYPES.Property && parent.key === node && !parent.computed) {
2065
2145
  return false;
2066
2146
  }
2067
2147
  if (parent.type.startsWith("TS")) {
@@ -2078,7 +2158,7 @@ var isGlobalReference = (node, context) => {
2078
2158
  }
2079
2159
  return true;
2080
2160
  };
2081
- var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2161
+ var no_unnecessary_use_client_default = import_utils13.ESLintUtils.RuleCreator(
2082
2162
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2083
2163
  )({
2084
2164
  name: "no-unnecessary-use-client",
@@ -2103,13 +2183,13 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2103
2183
  const importedLocals = /* @__PURE__ */ new Set();
2104
2184
  const externalLocals = /* @__PURE__ */ new Set();
2105
2185
  const markIfHookOrContext = (callee) => {
2106
- if (callee.type === import_utils14.AST_NODE_TYPES.Identifier) {
2186
+ if (callee.type === import_utils13.AST_NODE_TYPES.Identifier) {
2107
2187
  if (HOOK_REGEX.test(callee.name) || callee.name === "createContext") {
2108
2188
  hasClientIndicator = true;
2109
2189
  }
2110
2190
  return;
2111
2191
  }
2112
- if (callee.type === import_utils14.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils14.AST_NODE_TYPES.Identifier) {
2192
+ if (callee.type === import_utils13.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils13.AST_NODE_TYPES.Identifier) {
2113
2193
  const name = callee.property.name;
2114
2194
  if (HOOK_REGEX.test(name) || name === "createContext") {
2115
2195
  hasClientIndicator = true;
@@ -2119,7 +2199,7 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2119
2199
  return {
2120
2200
  Program(node) {
2121
2201
  for (const stmt of node.body) {
2122
- if (stmt.type !== import_utils14.AST_NODE_TYPES.ExpressionStatement) break;
2202
+ if (stmt.type !== import_utils13.AST_NODE_TYPES.ExpressionStatement) break;
2123
2203
  if (isUseClientDirective(stmt)) {
2124
2204
  directiveNode = stmt;
2125
2205
  break;
@@ -2132,7 +2212,7 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2132
2212
  },
2133
2213
  JSXAttribute(node) {
2134
2214
  if (directiveNode === null) return;
2135
- if (node.name.type === import_utils14.AST_NODE_TYPES.JSXIdentifier && EVENT_PROP_REGEX.test(node.name.name)) {
2215
+ if (node.name.type === import_utils13.AST_NODE_TYPES.JSXIdentifier && EVENT_PROP_REGEX.test(node.name.name)) {
2136
2216
  hasClientIndicator = true;
2137
2217
  }
2138
2218
  },
@@ -2199,8 +2279,8 @@ var no_unnecessary_use_client_default = import_utils14.ESLintUtils.RuleCreator(
2199
2279
  });
2200
2280
 
2201
2281
  // src/rules/prefer-discriminated-union.ts
2282
+ var import_utils14 = require("@typescript-eslint/utils");
2202
2283
  var import_utils15 = require("@typescript-eslint/utils");
2203
- var import_utils16 = require("@typescript-eslint/utils");
2204
2284
  var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2205
2285
  "success",
2206
2286
  "ok",
@@ -2210,27 +2290,27 @@ var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2210
2290
  ]);
2211
2291
  var MIN_OPTIONAL_MEMBERS = 2;
2212
2292
  function getMemberName(member) {
2213
- if (member.type !== import_utils16.AST_NODE_TYPES.TSPropertySignature) {
2293
+ if (member.type !== import_utils15.AST_NODE_TYPES.TSPropertySignature) {
2214
2294
  return null;
2215
2295
  }
2216
2296
  const { key } = member;
2217
- if (key.type === import_utils16.AST_NODE_TYPES.Identifier) {
2297
+ if (key.type === import_utils15.AST_NODE_TYPES.Identifier) {
2218
2298
  return key.name;
2219
2299
  }
2220
- if (key.type === import_utils16.AST_NODE_TYPES.Literal && typeof key.value === "string") {
2300
+ if (key.type === import_utils15.AST_NODE_TYPES.Literal && typeof key.value === "string") {
2221
2301
  return key.value;
2222
2302
  }
2223
2303
  return null;
2224
2304
  }
2225
2305
  function isBooleanTyped(member) {
2226
- return member.typeAnnotation?.typeAnnotation.type === import_utils16.AST_NODE_TYPES.TSBooleanKeyword;
2306
+ return member.typeAnnotation?.typeAnnotation.type === import_utils15.AST_NODE_TYPES.TSBooleanKeyword;
2227
2307
  }
2228
2308
  function looksLikeMutuallyExclusiveState(typeLiteral) {
2229
2309
  let hasStatusBoolean = false;
2230
2310
  let optionalCount = 0;
2231
2311
  let optionalPayloadCount = 0;
2232
2312
  for (const member of typeLiteral.members) {
2233
- if (member.type !== import_utils16.AST_NODE_TYPES.TSPropertySignature) {
2313
+ if (member.type !== import_utils15.AST_NODE_TYPES.TSPropertySignature) {
2234
2314
  continue;
2235
2315
  }
2236
2316
  if (member.optional) {
@@ -2246,7 +2326,7 @@ function looksLikeMutuallyExclusiveState(typeLiteral) {
2246
2326
  }
2247
2327
  return hasStatusBoolean && optionalCount >= MIN_OPTIONAL_MEMBERS && optionalPayloadCount >= 1;
2248
2328
  }
2249
- var prefer_discriminated_union_default = import_utils15.ESLintUtils.RuleCreator(
2329
+ var prefer_discriminated_union_default = import_utils14.ESLintUtils.RuleCreator(
2250
2330
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2251
2331
  )({
2252
2332
  name: "prefer-discriminated-union",
@@ -2274,7 +2354,7 @@ var prefer_discriminated_union_default = import_utils15.ESLintUtils.RuleCreator(
2274
2354
  TSInterfaceDeclaration(node) {
2275
2355
  const synthetic = {
2276
2356
  ...node.body,
2277
- type: import_utils16.AST_NODE_TYPES.TSTypeLiteral,
2357
+ type: import_utils15.AST_NODE_TYPES.TSTypeLiteral,
2278
2358
  members: node.body.body
2279
2359
  };
2280
2360
  checkTypeLiteral(synthetic, node);
@@ -2287,13 +2367,13 @@ var prefer_discriminated_union_default = import_utils15.ESLintUtils.RuleCreator(
2287
2367
  });
2288
2368
 
2289
2369
  // src/rules/prefer-schema-for-api-payload.ts
2290
- var import_utils17 = require("@typescript-eslint/utils");
2370
+ var import_utils16 = require("@typescript-eslint/utils");
2291
2371
  var unwrap = (node) => {
2292
2372
  let current = node;
2293
2373
  while (current !== null && current !== void 0) {
2294
- 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) {
2374
+ if (current.type === import_utils16.AST_NODE_TYPES.TSAsExpression || current.type === import_utils16.AST_NODE_TYPES.TSTypeAssertion || current.type === import_utils16.AST_NODE_TYPES.TSNonNullExpression || current.type === import_utils16.AST_NODE_TYPES.TSSatisfiesExpression) {
2295
2375
  current = current.expression;
2296
- } else if (current.type === import_utils17.AST_NODE_TYPES.ChainExpression) {
2376
+ } else if (current.type === import_utils16.AST_NODE_TYPES.ChainExpression) {
2297
2377
  current = current.expression;
2298
2378
  } else {
2299
2379
  break;
@@ -2301,28 +2381,40 @@ var unwrap = (node) => {
2301
2381
  }
2302
2382
  return current ?? null;
2303
2383
  };
2384
+ var PROMISE_CHAIN_METHODS = /* @__PURE__ */ new Set([
2385
+ "then",
2386
+ "catch",
2387
+ "finally"
2388
+ ]);
2389
+ var isSchemaParseReference = (node) => {
2390
+ const inner = unwrap(node);
2391
+ return inner !== null && inner.type === import_utils16.AST_NODE_TYPES.MemberExpression && !inner.computed && inner.property.type === import_utils16.AST_NODE_TYPES.Identifier && (inner.property.name === "parse" || inner.property.name === "safeParse");
2392
+ };
2304
2393
  var isRawPayloadSource = (node) => {
2305
2394
  let current = unwrap(node);
2306
2395
  if (current === null) return false;
2307
- if (current.type === import_utils17.AST_NODE_TYPES.AwaitExpression) {
2396
+ if (current.type === import_utils16.AST_NODE_TYPES.AwaitExpression) {
2308
2397
  current = unwrap(current.argument);
2309
2398
  }
2310
- if (current === null || current.type !== import_utils17.AST_NODE_TYPES.CallExpression) {
2399
+ if (current === null || current.type !== import_utils16.AST_NODE_TYPES.CallExpression) {
2311
2400
  return false;
2312
2401
  }
2313
2402
  const callee = unwrap(current.callee);
2314
- if (callee === null || callee.type !== import_utils17.AST_NODE_TYPES.MemberExpression) {
2403
+ if (callee === null || callee.type !== import_utils16.AST_NODE_TYPES.MemberExpression) {
2315
2404
  return false;
2316
2405
  }
2317
2406
  const property = unwrap(callee.property);
2318
- if (property === null || property.type !== import_utils17.AST_NODE_TYPES.Identifier) {
2407
+ if (property === null || property.type !== import_utils16.AST_NODE_TYPES.Identifier) {
2319
2408
  return false;
2320
2409
  }
2321
2410
  if (property.name === "json") {
2322
2411
  return true;
2323
2412
  }
2413
+ if (PROMISE_CHAIN_METHODS.has(property.name)) {
2414
+ return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
2415
+ }
2324
2416
  const object = unwrap(callee.object);
2325
- 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.
2417
+ return property.name === "parse" && object !== null && object.type === import_utils16.AST_NODE_TYPES.Identifier && object.name === "JSON" && // ...but not `JSON.parse(readFileSync(p, "utf8"))` — see isLocalFileRead.
2326
2418
  !isLocalFileRead(current.arguments[0]);
2327
2419
  };
2328
2420
  var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
@@ -2330,9 +2422,9 @@ var isLocalFileRead = (node) => {
2330
2422
  let found = false;
2331
2423
  const visit = (current) => {
2332
2424
  if (found || current === null || current === void 0) return;
2333
- if (current.type === import_utils17.AST_NODE_TYPES.CallExpression) {
2425
+ if (current.type === import_utils16.AST_NODE_TYPES.CallExpression) {
2334
2426
  const callee = unwrap(current.callee);
2335
- 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;
2427
+ const name = callee?.type === import_utils16.AST_NODE_TYPES.Identifier ? callee.name : callee?.type === import_utils16.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils16.AST_NODE_TYPES.Identifier ? callee.property.name : null;
2336
2428
  if (name !== null && FILE_READ_RE.test(name)) {
2337
2429
  found = true;
2338
2430
  return;
@@ -2354,15 +2446,15 @@ var isLocalFileRead = (node) => {
2354
2446
  var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
2355
2447
  var isInsideAssertion = (node) => {
2356
2448
  for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
2357
- if (current.type !== import_utils17.AST_NODE_TYPES.CallExpression) continue;
2449
+ if (current.type !== import_utils16.AST_NODE_TYPES.CallExpression) continue;
2358
2450
  let callee = current.callee;
2359
- while (callee.type === import_utils17.AST_NODE_TYPES.MemberExpression) {
2451
+ while (callee.type === import_utils16.AST_NODE_TYPES.MemberExpression) {
2360
2452
  callee = callee.object;
2361
2453
  }
2362
- if (callee.type === import_utils17.AST_NODE_TYPES.CallExpression) {
2454
+ if (callee.type === import_utils16.AST_NODE_TYPES.CallExpression) {
2363
2455
  callee = callee.callee;
2364
2456
  }
2365
- if (callee.type === import_utils17.AST_NODE_TYPES.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
2457
+ if (callee.type === import_utils16.AST_NODE_TYPES.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
2366
2458
  return true;
2367
2459
  }
2368
2460
  }
@@ -2377,23 +2469,43 @@ var findVariable2 = (scope, name) => {
2377
2469
  }
2378
2470
  return null;
2379
2471
  };
2380
- var GUARD_NAME_RE = /^is[A-Z]/;
2472
+ var GUARD_NAME_RE = /^(?:is|validate|parse|assert|decode|coerce)[A-Z]/;
2473
+ var isValidationRead = (node) => {
2474
+ let current = node;
2475
+ let parent = current.parent;
2476
+ while (parent !== null && parent !== void 0 && (parent.type === import_utils16.AST_NODE_TYPES.TSAsExpression || parent.type === import_utils16.AST_NODE_TYPES.TSTypeAssertion || parent.type === import_utils16.AST_NODE_TYPES.TSNonNullExpression || parent.type === import_utils16.AST_NODE_TYPES.TSSatisfiesExpression || parent.type === import_utils16.AST_NODE_TYPES.ChainExpression)) {
2477
+ current = parent;
2478
+ parent = parent.parent;
2479
+ }
2480
+ if (parent === null || parent === void 0) return false;
2481
+ if (parent.type === import_utils16.AST_NODE_TYPES.UnaryExpression && parent.operator === "typeof" && parent.argument === current) {
2482
+ return true;
2483
+ }
2484
+ if (parent.type !== import_utils16.AST_NODE_TYPES.CallExpression || !parent.arguments.some((arg) => arg === current)) {
2485
+ return false;
2486
+ }
2487
+ const callee = parent.callee;
2488
+ if (callee.type === import_utils16.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === import_utils16.AST_NODE_TYPES.Identifier && callee.object.name === "Array" && callee.property.type === import_utils16.AST_NODE_TYPES.Identifier && callee.property.name === "isArray") {
2489
+ return parent.arguments.length === 1;
2490
+ }
2491
+ return callee.type === import_utils16.AST_NODE_TYPES.Identifier && GUARD_NAME_RE.test(callee.name);
2492
+ };
2381
2493
  var isGuardTestPosition = (node) => {
2382
2494
  let current = node;
2383
2495
  let parent = current.parent;
2384
2496
  while (parent !== void 0 && parent !== null) {
2385
2497
  switch (parent.type) {
2386
- case import_utils17.AST_NODE_TYPES.UnaryExpression:
2387
- case import_utils17.AST_NODE_TYPES.LogicalExpression:
2388
- case import_utils17.AST_NODE_TYPES.ChainExpression:
2498
+ case import_utils16.AST_NODE_TYPES.UnaryExpression:
2499
+ case import_utils16.AST_NODE_TYPES.LogicalExpression:
2500
+ case import_utils16.AST_NODE_TYPES.ChainExpression:
2389
2501
  current = parent;
2390
2502
  parent = parent.parent;
2391
2503
  continue;
2392
- case import_utils17.AST_NODE_TYPES.IfStatement:
2393
- case import_utils17.AST_NODE_TYPES.ConditionalExpression:
2394
- case import_utils17.AST_NODE_TYPES.WhileStatement:
2395
- case import_utils17.AST_NODE_TYPES.DoWhileStatement:
2396
- case import_utils17.AST_NODE_TYPES.ForStatement:
2504
+ case import_utils16.AST_NODE_TYPES.IfStatement:
2505
+ case import_utils16.AST_NODE_TYPES.ConditionalExpression:
2506
+ case import_utils16.AST_NODE_TYPES.WhileStatement:
2507
+ case import_utils16.AST_NODE_TYPES.DoWhileStatement:
2508
+ case import_utils16.AST_NODE_TYPES.ForStatement:
2397
2509
  return parent.test === current;
2398
2510
  default:
2399
2511
  return false;
@@ -2403,13 +2515,13 @@ var isGuardTestPosition = (node) => {
2403
2515
  };
2404
2516
  var isUnvalidatedVariableRef = (node, scope, tracked) => {
2405
2517
  const unwrapped = unwrap(node);
2406
- if (unwrapped === null || unwrapped.type !== import_utils17.AST_NODE_TYPES.Identifier) {
2518
+ if (unwrapped === null || unwrapped.type !== import_utils16.AST_NODE_TYPES.Identifier) {
2407
2519
  return false;
2408
2520
  }
2409
2521
  const variable = findVariable2(scope, unwrapped.name);
2410
2522
  return variable !== null && tracked.has(variable);
2411
2523
  };
2412
- var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreator(
2524
+ var prefer_schema_for_api_payload_default = import_utils16.ESLintUtils.RuleCreator(
2413
2525
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2414
2526
  )({
2415
2527
  name: "prefer-schema-for-api-payload",
@@ -2429,6 +2541,14 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2429
2541
  return {};
2430
2542
  }
2431
2543
  const unvalidatedVariables = /* @__PURE__ */ new Set();
2544
+ const isFullyNarrowedPattern = (declarator) => {
2545
+ const declared = context.sourceCode.getDeclaredVariables(declarator);
2546
+ return declared.length > 0 && declared.every(
2547
+ (variable) => variable.references.some(
2548
+ (reference) => isValidationRead(reference.identifier)
2549
+ )
2550
+ );
2551
+ };
2432
2552
  const trackInitializer = (declarator) => {
2433
2553
  if (!isRawPayloadSource(declarator.init)) return;
2434
2554
  const declaredVars = context.sourceCode.getDeclaredVariables(declarator);
@@ -2440,13 +2560,15 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2440
2560
  return {
2441
2561
  VariableDeclarator(node) {
2442
2562
  const scope = context.sourceCode.getScope(node);
2443
- if (node.id.type === import_utils17.AST_NODE_TYPES.Identifier) {
2563
+ if (node.id.type === import_utils16.AST_NODE_TYPES.Identifier) {
2444
2564
  trackInitializer(node);
2445
2565
  return;
2446
2566
  }
2447
- if (node.id.type === import_utils17.AST_NODE_TYPES.ObjectPattern || node.id.type === import_utils17.AST_NODE_TYPES.ArrayPattern) {
2567
+ if (node.id.type === import_utils16.AST_NODE_TYPES.ObjectPattern || node.id.type === import_utils16.AST_NODE_TYPES.ArrayPattern) {
2448
2568
  if (isRawPayloadSource(node.init)) {
2449
- context.report({ node: node.id, messageId: "unparsedJsonAccess" });
2569
+ if (!isFullyNarrowedPattern(node)) {
2570
+ context.report({ node: node.id, messageId: "unparsedJsonAccess" });
2571
+ }
2450
2572
  return;
2451
2573
  }
2452
2574
  if (isUnvalidatedVariableRef(node.init, scope, unvalidatedVariables)) {
@@ -2456,7 +2578,7 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2456
2578
  },
2457
2579
  AssignmentExpression(node) {
2458
2580
  const scope = context.sourceCode.getScope(node);
2459
- if (node.left.type === import_utils17.AST_NODE_TYPES.Identifier) {
2581
+ if (node.left.type === import_utils16.AST_NODE_TYPES.Identifier) {
2460
2582
  const variable = findVariable2(scope, node.left.name);
2461
2583
  if (variable === null) return;
2462
2584
  if (isRawPayloadSource(node.right)) {
@@ -2466,7 +2588,7 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2466
2588
  }
2467
2589
  return;
2468
2590
  }
2469
- if (node.left.type === import_utils17.AST_NODE_TYPES.ObjectPattern || node.left.type === import_utils17.AST_NODE_TYPES.ArrayPattern) {
2591
+ if (node.left.type === import_utils16.AST_NODE_TYPES.ObjectPattern || node.left.type === import_utils16.AST_NODE_TYPES.ArrayPattern) {
2470
2592
  if (isRawPayloadSource(node.right)) {
2471
2593
  context.report({
2472
2594
  node: node.left,
@@ -2483,15 +2605,15 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2483
2605
  }
2484
2606
  },
2485
2607
  CallExpression(node) {
2486
- if (node.callee.type !== import_utils17.AST_NODE_TYPES.Identifier) return;
2608
+ if (node.callee.type !== import_utils16.AST_NODE_TYPES.Identifier) return;
2487
2609
  if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {
2488
2610
  return;
2489
2611
  }
2490
2612
  const scope = context.sourceCode.getScope(node);
2491
2613
  for (const arg of node.arguments) {
2492
- if (arg.type === import_utils17.AST_NODE_TYPES.SpreadElement) continue;
2614
+ if (arg.type === import_utils16.AST_NODE_TYPES.SpreadElement) continue;
2493
2615
  const unwrapped = unwrap(arg);
2494
- if (unwrapped === null || unwrapped.type !== import_utils17.AST_NODE_TYPES.Identifier) {
2616
+ if (unwrapped === null || unwrapped.type !== import_utils16.AST_NODE_TYPES.Identifier) {
2495
2617
  continue;
2496
2618
  }
2497
2619
  const variable = findVariable2(scope, unwrapped.name);
@@ -2500,17 +2622,18 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2500
2622
  },
2501
2623
  MemberExpression(node) {
2502
2624
  if (isInsideAssertion(node)) return;
2625
+ if (isValidationRead(node)) return;
2503
2626
  const scope = context.sourceCode.getScope(node);
2504
2627
  const obj = unwrap(node.object);
2505
2628
  if (isRawPayloadSource(obj)) {
2506
2629
  const parent = node.parent;
2507
- 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")) {
2630
+ if (parent.type === import_utils16.AST_NODE_TYPES.CallExpression && parent.callee === node && node.property.type === import_utils16.AST_NODE_TYPES.Identifier && (node.property.name === "parse" || node.property.name === "safeParse" || PROMISE_CHAIN_METHODS.has(node.property.name))) {
2508
2631
  return;
2509
2632
  }
2510
2633
  context.report({ node, messageId: "unparsedJsonAccess" });
2511
2634
  return;
2512
2635
  }
2513
- if (obj !== null && obj.type === import_utils17.AST_NODE_TYPES.Identifier && isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)) {
2636
+ if (obj !== null && obj.type === import_utils16.AST_NODE_TYPES.Identifier && isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)) {
2514
2637
  context.report({ node, messageId: "unparsedJsonAccess" });
2515
2638
  const variable = findVariable2(scope, obj.name);
2516
2639
  if (variable !== null) {
@@ -2523,7 +2646,7 @@ var prefer_schema_for_api_payload_default = import_utils17.ESLintUtils.RuleCreat
2523
2646
  });
2524
2647
 
2525
2648
  // src/rules/prefer-semantic-colors.ts
2526
- var import_utils18 = require("@typescript-eslint/utils");
2649
+ var import_utils17 = require("@typescript-eslint/utils");
2527
2650
  var import_fs = require("fs");
2528
2651
  var import_path = require("path");
2529
2652
 
@@ -2535,7 +2658,8 @@ var classTokens = (value) => value.split(/\s+/).filter(Boolean);
2535
2658
  var COLOR_PREFIXES = "text|bg|border(?:-[trblxyse])?|ring(?:-offset)?|fill|stroke|from|via|to|divide|decoration|placeholder|accent|caret|shadow|outline";
2536
2659
  var PALETTE = "red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|slate|gray|zinc|neutral|stone";
2537
2660
  var COLOR_FN = "rgba?|hsla?|hwb|oklch|oklab|lab|lch|color";
2538
- var RAW_PALETTE_RE = new RegExp(`^(?:${COLOR_PREFIXES})-(?:${PALETTE})-\\d{2,3}(?:/\\d{1,3})?$`);
2661
+ var PALETTE_STEP = "50|[1-9]00|950";
2662
+ var RAW_PALETTE_RE = new RegExp(`^(?:${COLOR_PREFIXES})-(?:${PALETTE})-(?:${PALETTE_STEP})(?:/\\d{1,3})?$`);
2539
2663
  var ARBITRARY_COLOR_RE = new RegExp(
2540
2664
  `^(?:${COLOR_PREFIXES})-\\[(?:#[0-9a-fA-F]{3,8}|(?:${COLOR_FN})\\([^\\]]*\\))\\]$`,
2541
2665
  "i"
@@ -2562,6 +2686,7 @@ var STYLE_COLOR_PROPS = /* @__PURE__ */ new Set([
2562
2686
  "lightingColor"
2563
2687
  ]);
2564
2688
  var RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\b|\\b(?:${COLOR_FN})\\s*\\(`, "i");
2689
+ var CSS_VAR_REFERENCE_RE = /var\(\s*--/;
2565
2690
  var STORIES_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
2566
2691
  var SEMANTIC_TOKEN_RE = /--(?:background|foreground|primary|secondary|muted|accent|destructive|border|card|popover)\b|(?:bg|text|border)-(?:background|foreground|primary|secondary|muted|accent|destructive|border|card|popover)\b/;
2567
2692
  var DETECTION_FILES = [
@@ -2598,8 +2723,8 @@ var SVG_EXEMPT_COLOR_VALUES = /* @__PURE__ */ new Set([
2598
2723
  ]);
2599
2724
  function jsxElementName(node) {
2600
2725
  const name = node.openingElement.name;
2601
- if (name.type === import_utils18.AST_NODE_TYPES.JSXIdentifier) return name.name;
2602
- if (name.type === import_utils18.AST_NODE_TYPES.JSXMemberExpression && name.property.type === import_utils18.AST_NODE_TYPES.JSXIdentifier) {
2726
+ if (name.type === import_utils17.AST_NODE_TYPES.JSXIdentifier) return name.name;
2727
+ if (name.type === import_utils17.AST_NODE_TYPES.JSXMemberExpression && name.property.type === import_utils17.AST_NODE_TYPES.JSXIdentifier) {
2603
2728
  return name.property.name;
2604
2729
  }
2605
2730
  return null;
@@ -2607,10 +2732,25 @@ function jsxElementName(node) {
2607
2732
  function isSvgLikeElementName(name) {
2608
2733
  return name === "svg" || SVG_DEFS_CONTAINERS.has(name) || /svg$/i.test(name);
2609
2734
  }
2735
+ var SVG_SHAPE_PRIMITIVES = /* @__PURE__ */ new Set([
2736
+ "circle",
2737
+ "ellipse",
2738
+ "g",
2739
+ "line",
2740
+ "path",
2741
+ "polygon",
2742
+ "polyline",
2743
+ "rect",
2744
+ "stop",
2745
+ "text",
2746
+ "tspan",
2747
+ "use"
2748
+ ]);
2749
+ var EMAIL_OR_PDF_IMPORT_RE = /@react-(?:email|pdf)\//;
2610
2750
  var isInsideSvg = (node) => {
2611
2751
  let current = node.parent;
2612
2752
  while (current !== void 0 && current !== null) {
2613
- if (current.type === import_utils18.AST_NODE_TYPES.JSXElement) {
2753
+ if (current.type === import_utils17.AST_NODE_TYPES.JSXElement) {
2614
2754
  const name = jsxElementName(current);
2615
2755
  if (name !== null && isSvgLikeElementName(name)) return true;
2616
2756
  }
@@ -2621,7 +2761,7 @@ var isInsideSvg = (node) => {
2621
2761
  var isInsideIconFactoryPath = (node) => {
2622
2762
  let current = node.parent;
2623
2763
  while (current !== void 0 && current !== null) {
2624
- 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") {
2764
+ if (current.type === import_utils17.AST_NODE_TYPES.Property && propName(current.key) === "path" && current.parent.type === import_utils17.AST_NODE_TYPES.ObjectExpression && current.parent.parent.type === import_utils17.AST_NODE_TYPES.CallExpression && current.parent.parent.callee.type === import_utils17.AST_NODE_TYPES.Identifier && current.parent.parent.callee.name === "createIcon") {
2625
2765
  return true;
2626
2766
  }
2627
2767
  current = current.parent;
@@ -2671,11 +2811,11 @@ var hasSemanticTokenSystem = (filename) => {
2671
2811
  return answer;
2672
2812
  };
2673
2813
  var propName = (key) => {
2674
- if (key.type === import_utils18.AST_NODE_TYPES.Identifier) return key.name;
2675
- if (key.type === import_utils18.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
2814
+ if (key.type === import_utils17.AST_NODE_TYPES.Identifier) return key.name;
2815
+ if (key.type === import_utils17.AST_NODE_TYPES.Literal && typeof key.value === "string") return key.value;
2676
2816
  return null;
2677
2817
  };
2678
- var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2818
+ var prefer_semantic_colors_default = import_utils17.ESLintUtils.RuleCreator(
2679
2819
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
2680
2820
  )({
2681
2821
  name: "prefer-semantic-colors",
@@ -2702,6 +2842,7 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2702
2842
  defaultOptions: [{}],
2703
2843
  create(context, [options]) {
2704
2844
  if (STORIES_FILE_RE.test(context.filename)) return {};
2845
+ if (EMAIL_OR_PDF_IMPORT_RE.test(context.sourceCode.getText())) return {};
2705
2846
  if (options?.requireSemanticTokens === true && !hasSemanticTokenSystem(context.filename)) {
2706
2847
  return {};
2707
2848
  }
@@ -2710,7 +2851,7 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2710
2851
  const base = tailwindBase(token);
2711
2852
  if (RAW_PALETTE_RE.test(base)) {
2712
2853
  context.report({ node, messageId: "rawPalette", data: { class: token } });
2713
- } else if (ARBITRARY_COLOR_RE.test(base)) {
2854
+ } else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
2714
2855
  context.report({ node, messageId: "arbitraryColor", data: { class: token } });
2715
2856
  }
2716
2857
  }
@@ -2718,27 +2859,27 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2718
2859
  const checkClassNode = (node) => {
2719
2860
  if (node === null) return;
2720
2861
  switch (node.type) {
2721
- case import_utils18.AST_NODE_TYPES.Literal:
2862
+ case import_utils17.AST_NODE_TYPES.Literal:
2722
2863
  if (typeof node.value === "string") reportClasses(node.value, node);
2723
2864
  break;
2724
- case import_utils18.AST_NODE_TYPES.TemplateLiteral:
2865
+ case import_utils17.AST_NODE_TYPES.TemplateLiteral:
2725
2866
  for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? "", quasi);
2726
2867
  break;
2727
- case import_utils18.AST_NODE_TYPES.ArrayExpression:
2868
+ case import_utils17.AST_NODE_TYPES.ArrayExpression:
2728
2869
  for (const element of node.elements) {
2729
- if (element !== null && element.type !== import_utils18.AST_NODE_TYPES.SpreadElement) checkClassNode(element);
2870
+ if (element !== null && element.type !== import_utils17.AST_NODE_TYPES.SpreadElement) checkClassNode(element);
2730
2871
  }
2731
2872
  break;
2732
- case import_utils18.AST_NODE_TYPES.ObjectExpression:
2873
+ case import_utils17.AST_NODE_TYPES.ObjectExpression:
2733
2874
  for (const property of node.properties) {
2734
- if (property.type === import_utils18.AST_NODE_TYPES.Property) checkClassNode(property.value);
2875
+ if (property.type === import_utils17.AST_NODE_TYPES.Property) checkClassNode(property.value);
2735
2876
  }
2736
2877
  break;
2737
- case import_utils18.AST_NODE_TYPES.ConditionalExpression:
2878
+ case import_utils17.AST_NODE_TYPES.ConditionalExpression:
2738
2879
  checkClassNode(node.consequent);
2739
2880
  checkClassNode(node.alternate);
2740
2881
  break;
2741
- case import_utils18.AST_NODE_TYPES.LogicalExpression:
2882
+ case import_utils17.AST_NODE_TYPES.LogicalExpression:
2742
2883
  checkClassNode(node.right);
2743
2884
  break;
2744
2885
  default:
@@ -2746,29 +2887,29 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2746
2887
  }
2747
2888
  };
2748
2889
  const checkColorValueNode = (node) => {
2749
- if (node.type === import_utils18.AST_NODE_TYPES.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value)) {
2890
+ if (node.type === import_utils17.AST_NODE_TYPES.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value) && !CSS_VAR_REFERENCE_RE.test(node.value)) {
2750
2891
  context.report({ node, messageId: "inlineColor", data: { value: node.value } });
2751
2892
  }
2752
2893
  };
2753
2894
  return {
2754
2895
  "JSXAttribute[name.name='className']"(node) {
2755
2896
  if (node.value === null) return;
2756
- if (node.value.type === import_utils18.AST_NODE_TYPES.Literal) checkClassNode(node.value);
2757
- else if (node.value.type === import_utils18.AST_NODE_TYPES.JSXExpressionContainer) {
2758
- if (node.value.expression.type !== import_utils18.AST_NODE_TYPES.JSXEmptyExpression) {
2897
+ if (node.value.type === import_utils17.AST_NODE_TYPES.Literal) checkClassNode(node.value);
2898
+ else if (node.value.type === import_utils17.AST_NODE_TYPES.JSXExpressionContainer) {
2899
+ if (node.value.expression.type !== import_utils17.AST_NODE_TYPES.JSXEmptyExpression) {
2759
2900
  checkClassNode(node.value.expression);
2760
2901
  }
2761
2902
  }
2762
2903
  },
2763
2904
  CallExpression(node) {
2764
- if (node.callee.type === import_utils18.AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {
2905
+ if (node.callee.type === import_utils17.AST_NODE_TYPES.Identifier && CLASS_FNS.has(node.callee.name)) {
2765
2906
  for (const arg of node.arguments) {
2766
- if (arg.type !== import_utils18.AST_NODE_TYPES.SpreadElement) checkClassNode(arg);
2907
+ if (arg.type !== import_utils17.AST_NODE_TYPES.SpreadElement) checkClassNode(arg);
2767
2908
  }
2768
2909
  }
2769
2910
  },
2770
2911
  VariableDeclarator(node) {
2771
- if (node.id.type === import_utils18.AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {
2912
+ if (node.id.type === import_utils17.AST_NODE_TYPES.Identifier && CLASS_NAME_RE.test(node.id.name)) {
2772
2913
  checkClassNode(node.init);
2773
2914
  }
2774
2915
  },
@@ -2780,7 +2921,11 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2780
2921
  // Neutral drawing literals and anything inside an SVG defs container are
2781
2922
  // structural, not UI tokens, so they never fire.
2782
2923
  "JSXAttribute[name.name=/^(fill|stroke|color)$/]"(node) {
2783
- if (node.value?.type !== import_utils18.AST_NODE_TYPES.Literal) return;
2924
+ if (node.value?.type !== import_utils17.AST_NODE_TYPES.Literal) return;
2925
+ const owner = node.parent.name;
2926
+ if (owner.type === import_utils17.AST_NODE_TYPES.JSXIdentifier && SVG_SHAPE_PRIMITIVES.has(owner.name)) {
2927
+ return;
2928
+ }
2784
2929
  if (typeof node.value.value === "string" && SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())) {
2785
2930
  return;
2786
2931
  }
@@ -2797,7 +2942,7 @@ var prefer_semantic_colors_default = import_utils18.ESLintUtils.RuleCreator(
2797
2942
  });
2798
2943
 
2799
2944
  // src/rules/prefer-server-actions.ts
2800
- var import_utils19 = require("@typescript-eslint/utils");
2945
+ var import_utils18 = require("@typescript-eslint/utils");
2801
2946
  var MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "DELETE", "PATCH"]);
2802
2947
  var AXIOS_MUTATION_METHODS = /* @__PURE__ */ new Set(["post", "put", "delete", "patch"]);
2803
2948
  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\/)/;
@@ -2877,7 +3022,7 @@ function getPropertyNode(objNode, propName2) {
2877
3022
  }
2878
3023
  return null;
2879
3024
  }
2880
- var prefer_server_actions_default = import_utils19.ESLintUtils.RuleCreator(
3025
+ var prefer_server_actions_default = import_utils18.ESLintUtils.RuleCreator(
2881
3026
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2882
3027
  )({
2883
3028
  name: "prefer-server-actions",
@@ -2952,36 +3097,36 @@ var prefer_server_actions_default = import_utils19.ESLintUtils.RuleCreator(
2952
3097
  });
2953
3098
 
2954
3099
  // src/rules/require-assert-never.ts
2955
- var import_utils20 = require("@typescript-eslint/utils");
3100
+ var import_utils19 = require("@typescript-eslint/utils");
2956
3101
  var isAssertNeverCall = (expression) => {
2957
- if (expression.type !== import_utils20.AST_NODE_TYPES.CallExpression) return false;
3102
+ if (expression.type !== import_utils19.AST_NODE_TYPES.CallExpression) return false;
2958
3103
  const callee = expression.callee;
2959
- if (callee.type === import_utils20.AST_NODE_TYPES.Identifier) {
3104
+ if (callee.type === import_utils19.AST_NODE_TYPES.Identifier) {
2960
3105
  return callee.name === "assertNever";
2961
3106
  }
2962
- if (callee.type === import_utils20.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils20.AST_NODE_TYPES.Identifier) {
3107
+ if (callee.type === import_utils19.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils19.AST_NODE_TYPES.Identifier) {
2963
3108
  return callee.property.name === "assertNever";
2964
3109
  }
2965
3110
  return false;
2966
3111
  };
2967
3112
  var statementContainsAssertNever = (statement) => {
2968
- if (statement.type === import_utils20.AST_NODE_TYPES.ExpressionStatement) {
3113
+ if (statement.type === import_utils19.AST_NODE_TYPES.ExpressionStatement) {
2969
3114
  return isAssertNeverCall(statement.expression);
2970
3115
  }
2971
- if (statement.type === import_utils20.AST_NODE_TYPES.ThrowStatement) {
3116
+ if (statement.type === import_utils19.AST_NODE_TYPES.ThrowStatement) {
2972
3117
  return isAssertNeverCall(statement.argument);
2973
3118
  }
2974
- if (statement.type === import_utils20.AST_NODE_TYPES.ReturnStatement) {
3119
+ if (statement.type === import_utils19.AST_NODE_TYPES.ReturnStatement) {
2975
3120
  return statement.argument !== null && isAssertNeverCall(statement.argument);
2976
3121
  }
2977
- if (statement.type === import_utils20.AST_NODE_TYPES.BlockStatement) {
3122
+ if (statement.type === import_utils19.AST_NODE_TYPES.BlockStatement) {
2978
3123
  return statement.body.some(statementContainsAssertNever);
2979
3124
  }
2980
3125
  return false;
2981
3126
  };
2982
3127
  var isRuntimeHandlingStatement = (statement) => {
2983
- if (statement.type === import_utils20.AST_NODE_TYPES.EmptyStatement) return false;
2984
- if (statement.type === import_utils20.AST_NODE_TYPES.BlockStatement) {
3128
+ if (statement.type === import_utils19.AST_NODE_TYPES.EmptyStatement) return false;
3129
+ if (statement.type === import_utils19.AST_NODE_TYPES.BlockStatement) {
2985
3130
  return statement.body.some(isRuntimeHandlingStatement);
2986
3131
  }
2987
3132
  return true;
@@ -2997,12 +3142,12 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
2997
3142
  return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
2998
3143
  }
2999
3144
  const only = defaultCase.consequent[0];
3000
- if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === import_utils20.AST_NODE_TYPES.BlockStatement && only.body.length === 0) {
3145
+ if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === import_utils19.AST_NODE_TYPES.BlockStatement && only.body.length === 0) {
3001
3146
  return sourceCode.getCommentsInside(only).length > 0;
3002
3147
  }
3003
3148
  return false;
3004
3149
  };
3005
- var require_assert_never_default = import_utils20.ESLintUtils.RuleCreator(
3150
+ var require_assert_never_default = import_utils19.ESLintUtils.RuleCreator(
3006
3151
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3007
3152
  )({
3008
3153
  name: "require-assert-never",
@@ -3040,7 +3185,7 @@ var require_assert_never_default = import_utils20.ESLintUtils.RuleCreator(
3040
3185
  });
3041
3186
 
3042
3187
  // src/rules/require-zod-form-validation.ts
3043
- var import_utils21 = require("@typescript-eslint/utils");
3188
+ var import_utils20 = require("@typescript-eslint/utils");
3044
3189
 
3045
3190
  // src/rules/_zod.ts
3046
3191
  var ZOD_PREFIX_RE = /^Z[A-Z]/;
@@ -3054,14 +3199,14 @@ function isZodModule(source) {
3054
3199
  var looksLikeZodSchema = (node) => {
3055
3200
  let current = node;
3056
3201
  while (true) {
3057
- if (current.type === import_utils21.AST_NODE_TYPES.Identifier) {
3202
+ if (current.type === import_utils20.AST_NODE_TYPES.Identifier) {
3058
3203
  return current.name === "z" || ZOD_SCHEMA_NAME_RE.test(current.name);
3059
3204
  }
3060
- if (current.type === import_utils21.AST_NODE_TYPES.CallExpression) {
3205
+ if (current.type === import_utils20.AST_NODE_TYPES.CallExpression) {
3061
3206
  current = current.callee;
3062
3207
  continue;
3063
3208
  }
3064
- if (current.type === import_utils21.AST_NODE_TYPES.MemberExpression) {
3209
+ if (current.type === import_utils20.AST_NODE_TYPES.MemberExpression) {
3065
3210
  current = current.object;
3066
3211
  continue;
3067
3212
  }
@@ -3069,25 +3214,25 @@ var looksLikeZodSchema = (node) => {
3069
3214
  }
3070
3215
  };
3071
3216
  var isZodParseCall = (node) => {
3072
- if (node.type !== import_utils21.AST_NODE_TYPES.CallExpression) return false;
3217
+ if (node.type !== import_utils20.AST_NODE_TYPES.CallExpression) return false;
3073
3218
  const callee = node.callee;
3074
- if (callee.type !== import_utils21.AST_NODE_TYPES.MemberExpression) return false;
3219
+ if (callee.type !== import_utils20.AST_NODE_TYPES.MemberExpression) return false;
3075
3220
  if (callee.computed) return false;
3076
- if (callee.property.type !== import_utils21.AST_NODE_TYPES.Identifier) return false;
3221
+ if (callee.property.type !== import_utils20.AST_NODE_TYPES.Identifier) return false;
3077
3222
  const method = callee.property.name;
3078
3223
  if (method !== "parse" && method !== "safeParse") return false;
3079
3224
  return looksLikeZodSchema(callee.object);
3080
3225
  };
3081
3226
  var isFormDataMethodCall = (node) => {
3082
3227
  let current = node;
3083
- if (current.type === import_utils21.AST_NODE_TYPES.AwaitExpression) {
3228
+ if (current.type === import_utils20.AST_NODE_TYPES.AwaitExpression) {
3084
3229
  current = current.argument;
3085
3230
  }
3086
- if (current.type !== import_utils21.AST_NODE_TYPES.CallExpression) return false;
3231
+ if (current.type !== import_utils20.AST_NODE_TYPES.CallExpression) return false;
3087
3232
  const callee = current.callee;
3088
- return callee.type === import_utils21.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils21.AST_NODE_TYPES.Identifier && callee.property.name === "formData";
3233
+ return callee.type === import_utils20.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils20.AST_NODE_TYPES.Identifier && callee.property.name === "formData";
3089
3234
  };
3090
- var require_zod_form_validation_default = import_utils21.ESLintUtils.RuleCreator(
3235
+ var require_zod_form_validation_default = import_utils20.ESLintUtils.RuleCreator(
3091
3236
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3092
3237
  )({
3093
3238
  name: "require-zod-form-validation",
@@ -3107,14 +3252,14 @@ var require_zod_form_validation_default = import_utils21.ESLintUtils.RuleCreator
3107
3252
  return {};
3108
3253
  }
3109
3254
  const isFormSourceIdentifier = (node) => {
3110
- if (node.type !== import_utils21.AST_NODE_TYPES.Identifier) return false;
3255
+ if (node.type !== import_utils20.AST_NODE_TYPES.Identifier) return false;
3111
3256
  if (/formdata/i.test(node.name)) return true;
3112
3257
  let scope = context.sourceCode.getScope(node);
3113
3258
  while (scope !== null) {
3114
3259
  const variable = scope.set.get(node.name);
3115
3260
  if (variable !== void 0 && variable.defs.length === 1) {
3116
3261
  const def = variable.defs[0];
3117
- if (def !== void 0 && def.type === "Variable" && def.node.type === import_utils21.AST_NODE_TYPES.VariableDeclarator && def.node.init !== null) {
3262
+ if (def !== void 0 && def.type === "Variable" && def.node.type === import_utils20.AST_NODE_TYPES.VariableDeclarator && def.node.init !== null) {
3118
3263
  return isFormDataMethodCall(def.node.init);
3119
3264
  }
3120
3265
  return false;
@@ -3125,8 +3270,8 @@ var require_zod_form_validation_default = import_utils21.ESLintUtils.RuleCreator
3125
3270
  };
3126
3271
  const isFormDataGetCall = (node) => {
3127
3272
  const callee = node.callee;
3128
- if (callee.type !== import_utils21.AST_NODE_TYPES.MemberExpression) return false;
3129
- if (callee.property.type !== import_utils21.AST_NODE_TYPES.Identifier || callee.property.name !== "get") {
3273
+ if (callee.type !== import_utils20.AST_NODE_TYPES.MemberExpression) return false;
3274
+ if (callee.property.type !== import_utils20.AST_NODE_TYPES.Identifier || callee.property.name !== "get") {
3130
3275
  return false;
3131
3276
  }
3132
3277
  return isFormSourceIdentifier(callee.object);
@@ -3141,11 +3286,11 @@ var require_zod_form_validation_default = import_utils21.ESLintUtils.RuleCreator
3141
3286
  };
3142
3287
  const isInstanceofNarrowing = (node) => {
3143
3288
  const parent = node.parent;
3144
- return parent !== null && parent !== void 0 && parent.type === import_utils21.AST_NODE_TYPES.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3289
+ return parent !== null && parent !== void 0 && parent.type === import_utils20.AST_NODE_TYPES.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3145
3290
  };
3146
3291
  const boundDeclarator = (node) => {
3147
3292
  const parent = node.parent;
3148
- if (parent.type === import_utils21.AST_NODE_TYPES.VariableDeclarator && parent.init === node && parent.id.type === import_utils21.AST_NODE_TYPES.Identifier) {
3293
+ if (parent.type === import_utils20.AST_NODE_TYPES.VariableDeclarator && parent.init === node && parent.id.type === import_utils20.AST_NODE_TYPES.Identifier) {
3149
3294
  return parent;
3150
3295
  }
3151
3296
  return null;
@@ -3173,13 +3318,14 @@ var require_zod_form_validation_default = import_utils21.ESLintUtils.RuleCreator
3173
3318
  });
3174
3319
 
3175
3320
  // src/rules/zod-naming-convention.ts
3176
- var import_utils22 = require("@typescript-eslint/utils");
3321
+ var import_utils21 = require("@typescript-eslint/utils");
3177
3322
  var CONVENTIONS = {
3178
3323
  prefix: { test: ZOD_PREFIX_RE, messageId: "zPrefix" },
3179
3324
  suffix: { test: ZOD_SUFFIX_RE, messageId: "schemaSuffix" },
3180
3325
  either: { test: ZOD_SCHEMA_NAME_RE, messageId: "zodSchemaName" }
3181
3326
  };
3182
3327
  var CONTAINS_SCHEMA_RE = /schema/i;
3328
+ var BENCHMARK_PATH_RE = /(^|[\\/])(?:benchmarks?|bench)[\\/]/;
3183
3329
  var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
3184
3330
  "parse",
3185
3331
  "parseAsync",
@@ -3197,15 +3343,15 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
3197
3343
  "registry",
3198
3344
  "implement"
3199
3345
  ]);
3200
- var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils22.AST_NODE_TYPES.Identifier ? callee.property.name : null;
3346
+ var terminalMethodName = (callee) => !callee.computed && callee.property.type === import_utils21.AST_NODE_TYPES.Identifier ? callee.property.name : null;
3201
3347
  var calleeChainStartsWithZ = (node) => {
3202
3348
  let current = node;
3203
- while (current.type === import_utils22.AST_NODE_TYPES.MemberExpression) {
3349
+ while (current.type === import_utils21.AST_NODE_TYPES.MemberExpression) {
3204
3350
  const receiver = current.object;
3205
- if (receiver.type === import_utils22.AST_NODE_TYPES.Identifier && receiver.name === "z") {
3351
+ if (receiver.type === import_utils21.AST_NODE_TYPES.Identifier && receiver.name === "z") {
3206
3352
  return true;
3207
3353
  }
3208
- if (receiver.type === import_utils22.AST_NODE_TYPES.CallExpression) {
3354
+ if (receiver.type === import_utils21.AST_NODE_TYPES.CallExpression) {
3209
3355
  current = receiver.callee;
3210
3356
  continue;
3211
3357
  }
@@ -3213,7 +3359,7 @@ var calleeChainStartsWithZ = (node) => {
3213
3359
  }
3214
3360
  return false;
3215
3361
  };
3216
- var zod_naming_convention_default = import_utils22.ESLintUtils.RuleCreator(
3362
+ var zod_naming_convention_default = import_utils21.ESLintUtils.RuleCreator(
3217
3363
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3218
3364
  )({
3219
3365
  name: "zod-naming-convention",
@@ -3245,20 +3391,20 @@ var zod_naming_convention_default = import_utils22.ESLintUtils.RuleCreator(
3245
3391
  const convention = optionsArg?.convention ?? "either";
3246
3392
  const { test, messageId } = CONVENTIONS[convention];
3247
3393
  const acceptsSchemaWord = convention !== "prefix";
3248
- if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) {
3394
+ if (isTestFile(context.filename) || BENCHMARK_PATH_RE.test(context.filename.replaceAll("\\", "/")) || isGeneratedFile(context.filename, context.sourceCode.text)) {
3249
3395
  return {};
3250
3396
  }
3251
3397
  return {
3252
3398
  VariableDeclarator(node) {
3253
3399
  const init = node.init;
3254
3400
  if (init === null || init === void 0) return;
3255
- if (init.type !== import_utils22.AST_NODE_TYPES.CallExpression) return;
3401
+ if (init.type !== import_utils21.AST_NODE_TYPES.CallExpression) return;
3256
3402
  const callee = init.callee;
3257
- if (callee.type !== import_utils22.AST_NODE_TYPES.MemberExpression) return;
3403
+ if (callee.type !== import_utils21.AST_NODE_TYPES.MemberExpression) return;
3258
3404
  if (!calleeChainStartsWithZ(callee)) return;
3259
3405
  const terminal = terminalMethodName(callee);
3260
3406
  if (terminal !== null && NON_SCHEMA_TERMINALS.has(terminal)) return;
3261
- if (node.id.type !== import_utils22.AST_NODE_TYPES.Identifier) return;
3407
+ if (node.id.type !== import_utils21.AST_NODE_TYPES.Identifier) return;
3262
3408
  if (test.test(node.id.name)) return;
3263
3409
  if (acceptsSchemaWord && CONTAINS_SCHEMA_RE.test(node.id.name)) return;
3264
3410
  context.report({
@@ -3271,7 +3417,7 @@ var zod_naming_convention_default = import_utils22.ESLintUtils.RuleCreator(
3271
3417
  });
3272
3418
 
3273
3419
  // src/rules/no-cors-wildcard-with-credentials.ts
3274
- var import_utils23 = require("@typescript-eslint/utils");
3420
+ var import_utils22 = require("@typescript-eslint/utils");
3275
3421
  var ACAO_HEADER = "access-control-allow-origin";
3276
3422
  var ACAC_HEADER = "access-control-allow-credentials";
3277
3423
  var HEADER_SET_METHODS = /* @__PURE__ */ new Set(["setheader", "set", "append"]);
@@ -3413,7 +3559,7 @@ function enclosingScope(node) {
3413
3559
  }
3414
3560
  return void 0;
3415
3561
  }
3416
- var no_cors_wildcard_with_credentials_default = import_utils23.ESLintUtils.RuleCreator(
3562
+ var no_cors_wildcard_with_credentials_default = import_utils22.ESLintUtils.RuleCreator(
3417
3563
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3418
3564
  )({
3419
3565
  name: "no-cors-wildcard-with-credentials",
@@ -3481,9 +3627,9 @@ var no_cors_wildcard_with_credentials_default = import_utils23.ESLintUtils.RuleC
3481
3627
  });
3482
3628
 
3483
3629
  // src/rules/no-silent-promise-catch.ts
3484
- var import_utils24 = require("@typescript-eslint/utils");
3630
+ var import_utils23 = require("@typescript-eslint/utils");
3485
3631
  function isBodyParseCall(node) {
3486
- return node.type === import_utils24.AST_NODE_TYPES.CallExpression && node.arguments.length === 0 && node.callee.type === import_utils24.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils24.AST_NODE_TYPES.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3632
+ return node.type === import_utils23.AST_NODE_TYPES.CallExpression && node.arguments.length === 0 && node.callee.type === import_utils23.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils23.AST_NODE_TYPES.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3487
3633
  }
3488
3634
  var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3489
3635
  "cancel",
@@ -3498,21 +3644,21 @@ var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3498
3644
  var DIRECTIVE_COMMENT_RE = /^\s*(eslint-|@ts-|prettier-ignore|biome-ignore|c8 |v8 |istanbul )/;
3499
3645
  var isExplanatory = (comment) => !DIRECTIVE_COMMENT_RE.test(comment.value);
3500
3646
  function isTeardownCall(node) {
3501
- return node.type === import_utils24.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils24.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils24.AST_NODE_TYPES.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3647
+ return node.type === import_utils23.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils23.AST_NODE_TYPES.MemberExpression && !node.callee.computed && node.callee.property.type === import_utils23.AST_NODE_TYPES.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3502
3648
  }
3503
3649
  function isSilentExpression(node) {
3504
3650
  switch (node.type) {
3505
- case import_utils24.AST_NODE_TYPES.Literal:
3651
+ case import_utils23.AST_NODE_TYPES.Literal:
3506
3652
  return !("regex" in node);
3507
- case import_utils24.AST_NODE_TYPES.Identifier:
3653
+ case import_utils23.AST_NODE_TYPES.Identifier:
3508
3654
  return node.name === "undefined";
3509
- case import_utils24.AST_NODE_TYPES.UnaryExpression:
3510
- return node.operator === "void" && node.argument.type === import_utils24.AST_NODE_TYPES.Literal;
3511
- case import_utils24.AST_NODE_TYPES.ObjectExpression:
3655
+ case import_utils23.AST_NODE_TYPES.UnaryExpression:
3656
+ return node.operator === "void" && node.argument.type === import_utils23.AST_NODE_TYPES.Literal;
3657
+ case import_utils23.AST_NODE_TYPES.ObjectExpression:
3512
3658
  return node.properties.length === 0;
3513
- case import_utils24.AST_NODE_TYPES.ArrayExpression:
3659
+ case import_utils23.AST_NODE_TYPES.ArrayExpression:
3514
3660
  return node.elements.length === 0;
3515
- case import_utils24.AST_NODE_TYPES.TSAsExpression:
3661
+ case import_utils23.AST_NODE_TYPES.TSAsExpression:
3516
3662
  return isSilentExpression(node.expression);
3517
3663
  default:
3518
3664
  return false;
@@ -3520,7 +3666,7 @@ function isSilentExpression(node) {
3520
3666
  }
3521
3667
  function isSilentHandler(handler) {
3522
3668
  const body = handler.body;
3523
- if (body.type !== import_utils24.AST_NODE_TYPES.BlockStatement) {
3669
+ if (body.type !== import_utils23.AST_NODE_TYPES.BlockStatement) {
3524
3670
  return isSilentExpression(body);
3525
3671
  }
3526
3672
  if (body.body.length === 0) {
@@ -3528,13 +3674,13 @@ function isSilentHandler(handler) {
3528
3674
  }
3529
3675
  if (body.body.length === 1) {
3530
3676
  const only = body.body[0];
3531
- if (only !== void 0 && only.type === import_utils24.AST_NODE_TYPES.ReturnStatement) {
3677
+ if (only !== void 0 && only.type === import_utils23.AST_NODE_TYPES.ReturnStatement) {
3532
3678
  return only.argument === null || isSilentExpression(only.argument);
3533
3679
  }
3534
3680
  }
3535
3681
  return false;
3536
3682
  }
3537
- var no_silent_promise_catch_default = import_utils24.ESLintUtils.RuleCreator(
3683
+ var no_silent_promise_catch_default = import_utils23.ESLintUtils.RuleCreator(
3538
3684
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3539
3685
  )({
3540
3686
  name: "no-silent-promise-catch",
@@ -3559,7 +3705,7 @@ var no_silent_promise_catch_default = import_utils24.ESLintUtils.RuleCreator(
3559
3705
  return true;
3560
3706
  }
3561
3707
  let statement = call;
3562
- while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== import_utils24.AST_NODE_TYPES.VariableDeclaration) {
3708
+ while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== import_utils23.AST_NODE_TYPES.VariableDeclaration) {
3563
3709
  statement = statement.parent;
3564
3710
  }
3565
3711
  if (sourceCode.getCommentsBefore(statement).some(isExplanatory)) {
@@ -3571,7 +3717,7 @@ var no_silent_promise_catch_default = import_utils24.ESLintUtils.RuleCreator(
3571
3717
  };
3572
3718
  return {
3573
3719
  CallExpression(node) {
3574
- if (node.callee.type !== import_utils24.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.property.type !== import_utils24.AST_NODE_TYPES.Identifier || node.callee.property.name !== "catch") {
3720
+ if (node.callee.type !== import_utils23.AST_NODE_TYPES.MemberExpression || node.callee.computed || node.callee.property.type !== import_utils23.AST_NODE_TYPES.Identifier || node.callee.property.name !== "catch") {
3575
3721
  return;
3576
3722
  }
3577
3723
  if (isBodyParseCall(node.callee.object)) {
@@ -3580,14 +3726,14 @@ var no_silent_promise_catch_default = import_utils24.ESLintUtils.RuleCreator(
3580
3726
  if (isTeardownCall(node.callee.object)) {
3581
3727
  return;
3582
3728
  }
3583
- if (node.parent.type === import_utils24.AST_NODE_TYPES.MemberExpression && node.parent.object === node) {
3729
+ if (node.parent.type === import_utils23.AST_NODE_TYPES.MemberExpression && node.parent.object === node) {
3584
3730
  return;
3585
3731
  }
3586
3732
  if (node.arguments.length !== 1) {
3587
3733
  return;
3588
3734
  }
3589
3735
  const handler = node.arguments[0];
3590
- if (handler === void 0 || handler.type !== import_utils24.AST_NODE_TYPES.ArrowFunctionExpression && handler.type !== import_utils24.AST_NODE_TYPES.FunctionExpression) {
3736
+ if (handler === void 0 || handler.type !== import_utils23.AST_NODE_TYPES.ArrowFunctionExpression && handler.type !== import_utils23.AST_NODE_TYPES.FunctionExpression) {
3591
3737
  return;
3592
3738
  }
3593
3739
  if (hasExplanatoryComment(node, handler)) {
@@ -3602,7 +3748,7 @@ var no_silent_promise_catch_default = import_utils24.ESLintUtils.RuleCreator(
3602
3748
  });
3603
3749
 
3604
3750
  // src/rules/require-fetch-timeout.ts
3605
- var import_utils25 = require("@typescript-eslint/utils");
3751
+ var import_utils24 = require("@typescript-eslint/utils");
3606
3752
  var CODEMOD_FIXTURE_RE = /[\\/]__testfixtures__[\\/]/;
3607
3753
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
3608
3754
  "globalThis",
@@ -3619,14 +3765,14 @@ function matchesAnyPattern2(filename, patterns) {
3619
3765
  return false;
3620
3766
  }
3621
3767
  function initProvablyLacksSignal(init) {
3622
- if (init.type !== import_utils25.AST_NODE_TYPES.ObjectExpression) {
3768
+ if (init.type !== import_utils24.AST_NODE_TYPES.ObjectExpression) {
3623
3769
  return false;
3624
3770
  }
3625
3771
  for (const prop of init.properties) {
3626
- if (prop.type === import_utils25.AST_NODE_TYPES.SpreadElement) {
3772
+ if (prop.type === import_utils24.AST_NODE_TYPES.SpreadElement) {
3627
3773
  return false;
3628
3774
  }
3629
- if (prop.key.type === import_utils25.AST_NODE_TYPES.Identifier && prop.key.name === "signal" || prop.key.type === import_utils25.AST_NODE_TYPES.Literal && prop.key.value === "signal") {
3775
+ if (prop.key.type === import_utils24.AST_NODE_TYPES.Identifier && prop.key.name === "signal" || prop.key.type === import_utils24.AST_NODE_TYPES.Literal && prop.key.value === "signal") {
3630
3776
  return false;
3631
3777
  }
3632
3778
  if (prop.computed) {
@@ -3636,9 +3782,9 @@ function initProvablyLacksSignal(init) {
3636
3782
  return true;
3637
3783
  }
3638
3784
  function isStringish(node) {
3639
- return node.type === import_utils25.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils25.AST_NODE_TYPES.TemplateLiteral;
3785
+ return node.type === import_utils24.AST_NODE_TYPES.Literal && typeof node.value === "string" || node.type === import_utils24.AST_NODE_TYPES.TemplateLiteral;
3640
3786
  }
3641
- var require_fetch_timeout_default = import_utils25.ESLintUtils.RuleCreator(
3787
+ var require_fetch_timeout_default = import_utils24.ESLintUtils.RuleCreator(
3642
3788
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3643
3789
  )({
3644
3790
  name: "require-fetch-timeout",
@@ -3675,14 +3821,14 @@ var require_fetch_timeout_default = import_utils25.ESLintUtils.RuleCreator(
3675
3821
  }
3676
3822
  function resolvesToGlobal(identifier) {
3677
3823
  const scope = context.sourceCode.getScope(identifier);
3678
- const variable = import_utils25.ASTUtils.findVariable(scope, identifier.name);
3824
+ const variable = import_utils24.ASTUtils.findVariable(scope, identifier.name);
3679
3825
  return variable === null || variable.defs.length === 0;
3680
3826
  }
3681
3827
  function isGlobalFetchCall2(callee) {
3682
- if (callee.type === import_utils25.AST_NODE_TYPES.Identifier) {
3828
+ if (callee.type === import_utils24.AST_NODE_TYPES.Identifier) {
3683
3829
  return callee.name === "fetch" && resolvesToGlobal(callee);
3684
3830
  }
3685
- return callee.type === import_utils25.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils25.AST_NODE_TYPES.Identifier && callee.property.name === "fetch" && callee.object.type === import_utils25.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3831
+ return callee.type === import_utils24.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils24.AST_NODE_TYPES.Identifier && callee.property.name === "fetch" && callee.object.type === import_utils24.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3686
3832
  }
3687
3833
  return {
3688
3834
  CallExpression(node) {
@@ -3702,12 +3848,12 @@ var require_fetch_timeout_default = import_utils25.ESLintUtils.RuleCreator(
3702
3848
  });
3703
3849
 
3704
3850
  // src/rules/no-fat-try-blocks.ts
3705
- var import_utils26 = require("@typescript-eslint/utils");
3851
+ var import_utils25 = require("@typescript-eslint/utils");
3706
3852
  var MAX_TRY_BODY_STATEMENTS = 3;
3707
3853
  var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set([
3708
- import_utils26.AST_NODE_TYPES.FunctionDeclaration,
3709
- import_utils26.AST_NODE_TYPES.FunctionExpression,
3710
- import_utils26.AST_NODE_TYPES.ArrowFunctionExpression
3854
+ import_utils25.AST_NODE_TYPES.FunctionDeclaration,
3855
+ import_utils25.AST_NODE_TYPES.FunctionExpression,
3856
+ import_utils25.AST_NODE_TYPES.ArrowFunctionExpression
3711
3857
  ]);
3712
3858
  var PURE_METHODS = /* @__PURE__ */ new Set([
3713
3859
  "map",
@@ -3805,22 +3951,22 @@ function isNode3(value) {
3805
3951
  }
3806
3952
  function isPureCall(node) {
3807
3953
  const callee = node.callee;
3808
- if (callee.type !== import_utils26.AST_NODE_TYPES.MemberExpression) {
3954
+ if (callee.type !== import_utils25.AST_NODE_TYPES.MemberExpression) {
3809
3955
  return false;
3810
3956
  }
3811
3957
  const property = callee.property;
3812
- if (property.type !== import_utils26.AST_NODE_TYPES.Identifier) {
3958
+ if (property.type !== import_utils25.AST_NODE_TYPES.Identifier) {
3813
3959
  return false;
3814
3960
  }
3815
- if (callee.object.type === import_utils26.AST_NODE_TYPES.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
3961
+ if (callee.object.type === import_utils25.AST_NODE_TYPES.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
3816
3962
  return true;
3817
3963
  }
3818
3964
  return PURE_METHODS.has(property.name);
3819
3965
  }
3820
3966
  function isPureNew(node) {
3821
- return node.callee.type === import_utils26.AST_NODE_TYPES.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
3967
+ return node.callee.type === import_utils25.AST_NODE_TYPES.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
3822
3968
  }
3823
- function subtreeMatches(stmt, predicate) {
3969
+ function subtreeMatches(stmt, predicate, descendIntoFunctions = false) {
3824
3970
  let found = false;
3825
3971
  const visit = (current) => {
3826
3972
  if (found) {
@@ -3834,7 +3980,7 @@ function subtreeMatches(stmt, predicate) {
3834
3980
  if (key === "parent") {
3835
3981
  continue;
3836
3982
  }
3837
- if (NESTED_FUNCTION_TYPES.has(current.type) && key === "body") {
3983
+ if (!descendIntoFunctions && NESTED_FUNCTION_TYPES.has(current.type) && key === "body") {
3838
3984
  continue;
3839
3985
  }
3840
3986
  const value = current[key];
@@ -3855,20 +4001,20 @@ function subtreeMatches(stmt, predicate) {
3855
4001
  visit(stmt);
3856
4002
  return found;
3857
4003
  }
3858
- var hasAwait = (node) => subtreeMatches(node, (n) => n.type === import_utils26.AST_NODE_TYPES.AwaitExpression);
4004
+ var hasAwait = (node) => subtreeMatches(node, (n) => n.type === import_utils25.AST_NODE_TYPES.AwaitExpression);
3859
4005
  var hasThrowingCallOrNew = (node) => subtreeMatches(
3860
4006
  node,
3861
- (n) => n.type === import_utils26.AST_NODE_TYPES.CallExpression && !isPureCall(n) || n.type === import_utils26.AST_NODE_TYPES.NewExpression && !isPureNew(n)
4007
+ (n) => n.type === import_utils25.AST_NODE_TYPES.CallExpression && !isPureCall(n) || n.type === import_utils25.AST_NODE_TYPES.NewExpression && !isPureNew(n)
3862
4008
  );
3863
4009
  function unwrap2(expr) {
3864
4010
  let current = expr;
3865
- while (current.type === import_utils26.AST_NODE_TYPES.ChainExpression || current.type === import_utils26.AST_NODE_TYPES.TSNonNullExpression) {
4011
+ while (current.type === import_utils25.AST_NODE_TYPES.ChainExpression || current.type === import_utils25.AST_NODE_TYPES.TSNonNullExpression) {
3866
4012
  current = current.expression;
3867
4013
  }
3868
4014
  return current;
3869
4015
  }
3870
4016
  function isBareCallStatement(stmt) {
3871
- return stmt.type === import_utils26.AST_NODE_TYPES.ExpressionStatement && unwrap2(stmt.expression).type === import_utils26.AST_NODE_TYPES.CallExpression;
4017
+ return stmt.type === import_utils25.AST_NODE_TYPES.ExpressionStatement && unwrap2(stmt.expression).type === import_utils25.AST_NODE_TYPES.CallExpression;
3872
4018
  }
3873
4019
  function canThrow(stmt) {
3874
4020
  if (hasAwait(stmt)) {
@@ -3877,10 +4023,10 @@ function canThrow(stmt) {
3877
4023
  if (isBareCallStatement(stmt)) {
3878
4024
  return false;
3879
4025
  }
3880
- if (stmt.type === import_utils26.AST_NODE_TYPES.BlockStatement) {
4026
+ if (stmt.type === import_utils25.AST_NODE_TYPES.BlockStatement) {
3881
4027
  return stmt.body.some(canThrow);
3882
4028
  }
3883
- if (stmt.type === import_utils26.AST_NODE_TYPES.IfStatement) {
4029
+ if (stmt.type === import_utils25.AST_NODE_TYPES.IfStatement) {
3884
4030
  return hasThrowingCallOrNew(stmt.test) || canThrow(stmt.consequent) || stmt.alternate !== null && canThrow(stmt.alternate);
3885
4031
  }
3886
4032
  return hasThrowingCallOrNew(stmt);
@@ -3891,9 +4037,137 @@ function handlerRethrows(handler) {
3891
4037
  }
3892
4038
  const body = handler.body.body;
3893
4039
  const last = body[body.length - 1];
3894
- return last !== void 0 && last.type === import_utils26.AST_NODE_TYPES.ThrowStatement;
4040
+ return last !== void 0 && last.type === import_utils25.AST_NODE_TYPES.ThrowStatement;
4041
+ }
4042
+ var PASS_THROUGH_PARENTS = /* @__PURE__ */ new Set([
4043
+ import_utils25.AST_NODE_TYPES.IfStatement,
4044
+ import_utils25.AST_NODE_TYPES.TryStatement,
4045
+ import_utils25.AST_NODE_TYPES.CatchClause,
4046
+ import_utils25.AST_NODE_TYPES.LabeledStatement
4047
+ ]);
4048
+ function isTerminalInFunction(node) {
4049
+ let current = node;
4050
+ let parent = current.parent;
4051
+ while (parent !== void 0) {
4052
+ if (parent.type === import_utils25.AST_NODE_TYPES.BlockStatement) {
4053
+ if (parent.body[parent.body.length - 1] !== current) {
4054
+ return false;
4055
+ }
4056
+ } else if (parent.type === import_utils25.AST_NODE_TYPES.Program) {
4057
+ return parent.body[parent.body.length - 1] === current;
4058
+ } else if (NESTED_FUNCTION_TYPES.has(parent.type)) {
4059
+ return true;
4060
+ } else if (!PASS_THROUGH_PARENTS.has(parent.type)) {
4061
+ return false;
4062
+ }
4063
+ current = parent;
4064
+ parent = current.parent;
4065
+ }
4066
+ return false;
4067
+ }
4068
+ function unwrapAwait(expr) {
4069
+ const inner = unwrap2(expr);
4070
+ return inner.type === import_utils25.AST_NODE_TYPES.AwaitExpression ? unwrap2(inner.argument) : inner;
4071
+ }
4072
+ function handlerEndsByHandingOff(handler) {
4073
+ const body = handler.body.body;
4074
+ const last = body[body.length - 1];
4075
+ if (last === void 0) {
4076
+ return false;
4077
+ }
4078
+ if (last.type === import_utils25.AST_NODE_TYPES.ReturnStatement || last.type === import_utils25.AST_NODE_TYPES.ThrowStatement) {
4079
+ return true;
4080
+ }
4081
+ return last.type === import_utils25.AST_NODE_TYPES.ExpressionStatement && unwrapAwait(last.expression).type === import_utils25.AST_NODE_TYPES.CallExpression;
4082
+ }
4083
+ function collectBindingNames(pattern, names) {
4084
+ if (pattern.type === import_utils25.AST_NODE_TYPES.Identifier) {
4085
+ names.add(pattern.name);
4086
+ return;
4087
+ }
4088
+ if (pattern.type === import_utils25.AST_NODE_TYPES.ObjectPattern) {
4089
+ for (const property of pattern.properties) {
4090
+ collectBindingNames(
4091
+ property.type === import_utils25.AST_NODE_TYPES.RestElement ? property.argument : property.value,
4092
+ names
4093
+ );
4094
+ }
4095
+ return;
4096
+ }
4097
+ if (pattern.type === import_utils25.AST_NODE_TYPES.ArrayPattern) {
4098
+ for (const element of pattern.elements) {
4099
+ if (element !== null) {
4100
+ collectBindingNames(element, names);
4101
+ }
4102
+ }
4103
+ return;
4104
+ }
4105
+ if (pattern.type === import_utils25.AST_NODE_TYPES.AssignmentPattern || pattern.type === import_utils25.AST_NODE_TYPES.RestElement) {
4106
+ collectBindingNames(
4107
+ pattern.type === import_utils25.AST_NODE_TYPES.AssignmentPattern ? pattern.left : pattern.argument,
4108
+ names
4109
+ );
4110
+ }
4111
+ }
4112
+ function caughtBindingNames(handler) {
4113
+ const names = /* @__PURE__ */ new Set();
4114
+ if (handler.param !== null) {
4115
+ collectBindingNames(handler.param, names);
4116
+ }
4117
+ return names;
4118
+ }
4119
+ function isPropertyName(node) {
4120
+ const parent = node.parent;
4121
+ if (parent.type === import_utils25.AST_NODE_TYPES.MemberExpression) {
4122
+ return parent.property === node && !parent.computed;
4123
+ }
4124
+ if (parent.type === import_utils25.AST_NODE_TYPES.Property) {
4125
+ return parent.key === node && !parent.computed;
4126
+ }
4127
+ return false;
4128
+ }
4129
+ function handlerMentionsCaughtBinding(handler) {
4130
+ const names = caughtBindingNames(handler);
4131
+ if (names.size === 0) {
4132
+ return false;
4133
+ }
4134
+ return subtreeMatches(
4135
+ handler.body,
4136
+ (n) => n.type === import_utils25.AST_NODE_TYPES.Identifier && names.has(n.name) && !isPropertyName(n),
4137
+ true
4138
+ );
4139
+ }
4140
+ function isSuccessShapedValue(expr) {
4141
+ let current = expr;
4142
+ while (current.type === import_utils25.AST_NODE_TYPES.TSAsExpression || current.type === import_utils25.AST_NODE_TYPES.TSNonNullExpression) {
4143
+ current = current.expression;
4144
+ }
4145
+ if (current.type === import_utils25.AST_NODE_TYPES.Literal) {
4146
+ return current.value === null || current.value === false;
4147
+ }
4148
+ if (current.type === import_utils25.AST_NODE_TYPES.Identifier) {
4149
+ return current.name === "undefined";
4150
+ }
4151
+ if (current.type === import_utils25.AST_NODE_TYPES.UnaryExpression) {
4152
+ return current.operator === "void";
4153
+ }
4154
+ if (current.type === import_utils25.AST_NODE_TYPES.ArrayExpression) {
4155
+ return current.elements.length === 0;
4156
+ }
4157
+ if (current.type === import_utils25.AST_NODE_TYPES.ObjectExpression) {
4158
+ return current.properties.length === 0;
4159
+ }
4160
+ return false;
4161
+ }
4162
+ var handlerReturnsSuccessShaped = (handler) => subtreeMatches(
4163
+ handler.body,
4164
+ (n) => n.type === import_utils25.AST_NODE_TYPES.ReturnStatement && n.argument !== null && isSuccessShapedValue(n.argument)
4165
+ );
4166
+ function isTerminalErrorBoundary(node) {
4167
+ const handler = node.handler;
4168
+ return handler !== null && isTerminalInFunction(node) && handlerEndsByHandingOff(handler) && handlerMentionsCaughtBinding(handler) && !handlerReturnsSuccessShaped(handler);
3895
4169
  }
3896
- var no_fat_try_blocks_default = import_utils26.ESLintUtils.RuleCreator(
4170
+ var no_fat_try_blocks_default = import_utils25.ESLintUtils.RuleCreator(
3897
4171
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
3898
4172
  )({
3899
4173
  name: "no-fat-try-blocks",
@@ -3921,6 +4195,9 @@ var no_fat_try_blocks_default = import_utils26.ESLintUtils.RuleCreator(
3921
4195
  if (handlerRethrows(node.handler)) {
3922
4196
  return;
3923
4197
  }
4198
+ if (isTerminalErrorBoundary(node)) {
4199
+ return;
4200
+ }
3924
4201
  const count = node.block.body.filter(canThrow).length;
3925
4202
  if (count <= MAX_TRY_BODY_STATEMENTS) {
3926
4203
  return;
@@ -3937,7 +4214,7 @@ var no_fat_try_blocks_default = import_utils26.ESLintUtils.RuleCreator(
3937
4214
  });
3938
4215
 
3939
4216
  // src/rules/no-secret-in-log.ts
3940
- var import_utils27 = require("@typescript-eslint/utils");
4217
+ var import_utils26 = require("@typescript-eslint/utils");
3941
4218
 
3942
4219
  // src/rules/_secret_names.ts
3943
4220
  var SECRET_WORDS = /* @__PURE__ */ new Set([
@@ -4199,7 +4476,7 @@ function propertyKeyName2(prop) {
4199
4476
  }
4200
4477
  return null;
4201
4478
  }
4202
- var no_secret_in_log_default = import_utils27.ESLintUtils.RuleCreator(
4479
+ var no_secret_in_log_default = import_utils26.ESLintUtils.RuleCreator(
4203
4480
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4204
4481
  )({
4205
4482
  name: "no-secret-in-log",
@@ -4276,24 +4553,24 @@ var no_secret_in_log_default = import_utils27.ESLintUtils.RuleCreator(
4276
4553
  });
4277
4554
 
4278
4555
  // src/rules/no-unsafe-mock-casting.ts
4556
+ var import_utils27 = require("@typescript-eslint/utils");
4279
4557
  var import_utils28 = require("@typescript-eslint/utils");
4280
- var import_utils29 = require("@typescript-eslint/utils");
4281
4558
  function isMockTypeReference(node) {
4282
- if (node.type !== import_utils29.AST_NODE_TYPES.TSTypeReference) {
4559
+ if (node.type !== import_utils28.AST_NODE_TYPES.TSTypeReference) {
4283
4560
  return false;
4284
4561
  }
4285
4562
  const typeName = node.typeName;
4286
- if (typeName.type === import_utils29.AST_NODE_TYPES.Identifier) {
4563
+ if (typeName.type === import_utils28.AST_NODE_TYPES.Identifier) {
4287
4564
  const name = typeName.name;
4288
4565
  return name === "Mock" || name === "MockInstance" || name === "SpyInstance";
4289
4566
  }
4290
- if (typeName.type === import_utils29.AST_NODE_TYPES.TSQualifiedName) {
4567
+ if (typeName.type === import_utils28.AST_NODE_TYPES.TSQualifiedName) {
4291
4568
  const rightName = typeName.right.name;
4292
4569
  return rightName === "Mock" || rightName === "MockInstance" || rightName === "SpyInstance";
4293
4570
  }
4294
4571
  return false;
4295
4572
  }
4296
- var no_unsafe_mock_casting_default = import_utils28.ESLintUtils.RuleCreator(
4573
+ var no_unsafe_mock_casting_default = import_utils27.ESLintUtils.RuleCreator(
4297
4574
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4298
4575
  )({
4299
4576
  name: "no-unsafe-mock-casting",
@@ -4325,7 +4602,7 @@ var no_unsafe_mock_casting_default = import_utils28.ESLintUtils.RuleCreator(
4325
4602
  });
4326
4603
 
4327
4604
  // src/rules/prefer-string-literal-union.ts
4328
- var import_utils30 = require("@typescript-eslint/utils");
4605
+ var import_utils29 = require("@typescript-eslint/utils");
4329
4606
  var ts = __toESM(require("typescript"), 1);
4330
4607
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
4331
4608
  "status",
@@ -4368,19 +4645,19 @@ function isChoiceLikeName(name) {
4368
4645
  return CHOICE_TOKENS.has(lastWord(name));
4369
4646
  }
4370
4647
  function keyName(key) {
4371
- if (key.type === import_utils30.AST_NODE_TYPES.Identifier) {
4648
+ if (key.type === import_utils29.AST_NODE_TYPES.Identifier) {
4372
4649
  return key.name;
4373
4650
  }
4374
- if (key.type === import_utils30.AST_NODE_TYPES.Literal && typeof key.value === "string") {
4651
+ if (key.type === import_utils29.AST_NODE_TYPES.Literal && typeof key.value === "string") {
4375
4652
  return key.value;
4376
4653
  }
4377
4654
  return null;
4378
4655
  }
4379
4656
  function isStringLiteralMember(t) {
4380
- return t.type === import_utils30.AST_NODE_TYPES.TSLiteralType && t.literal.type === import_utils30.AST_NODE_TYPES.Literal && typeof t.literal.value === "string";
4657
+ return t.type === import_utils29.AST_NODE_TYPES.TSLiteralType && t.literal.type === import_utils29.AST_NODE_TYPES.Literal && typeof t.literal.value === "string";
4381
4658
  }
4382
4659
  function isStringLiteralUnion(node) {
4383
- if (node?.type !== import_utils30.AST_NODE_TYPES.TSUnionType) {
4660
+ if (node?.type !== import_utils29.AST_NODE_TYPES.TSUnionType) {
4384
4661
  return false;
4385
4662
  }
4386
4663
  return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
@@ -4409,12 +4686,12 @@ function bindingSourceExpression(decl) {
4409
4686
  return ts.isForOfStatement(node) ? node.expression : node.initializer;
4410
4687
  }
4411
4688
  function refKey(node) {
4412
- if (node.type === import_utils30.AST_NODE_TYPES.Identifier) {
4689
+ if (node.type === import_utils29.AST_NODE_TYPES.Identifier) {
4413
4690
  return node.name;
4414
4691
  }
4415
- if (node.type === import_utils30.AST_NODE_TYPES.MemberExpression && !node.computed) {
4692
+ if (node.type === import_utils29.AST_NODE_TYPES.MemberExpression && !node.computed) {
4416
4693
  const inner = refKey(node.object);
4417
- if (inner === null || node.property.type !== import_utils30.AST_NODE_TYPES.Identifier) {
4694
+ if (inner === null || node.property.type !== import_utils29.AST_NODE_TYPES.Identifier) {
4418
4695
  return null;
4419
4696
  }
4420
4697
  return `${inner}.${node.property.name}`;
@@ -4422,12 +4699,12 @@ function refKey(node) {
4422
4699
  return null;
4423
4700
  }
4424
4701
  function strLiteral(node) {
4425
- if (node.type === import_utils30.AST_NODE_TYPES.Literal && typeof node.value === "string") {
4702
+ if (node.type === import_utils29.AST_NODE_TYPES.Literal && typeof node.value === "string") {
4426
4703
  return node.value;
4427
4704
  }
4428
4705
  return null;
4429
4706
  }
4430
- var prefer_string_literal_union_default = import_utils30.ESLintUtils.RuleCreator(
4707
+ var prefer_string_literal_union_default = import_utils29.ESLintUtils.RuleCreator(
4431
4708
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4432
4709
  )({
4433
4710
  name: "prefer-string-literal-union",
@@ -4465,7 +4742,7 @@ var prefer_string_literal_union_default = import_utils30.ESLintUtils.RuleCreator
4465
4742
  );
4466
4743
  let services;
4467
4744
  try {
4468
- services = import_utils30.ESLintUtils.getParserServices(context);
4745
+ services = import_utils29.ESLintUtils.getParserServices(context);
4469
4746
  } catch {
4470
4747
  services = null;
4471
4748
  }
@@ -4577,7 +4854,7 @@ var prefer_string_literal_union_default = import_utils30.ESLintUtils.RuleCreator
4577
4854
  containersWithUnion.add(container);
4578
4855
  return;
4579
4856
  }
4580
- if (typeNode?.type !== import_utils30.AST_NODE_TYPES.TSStringKeyword) {
4857
+ if (typeNode?.type !== import_utils29.AST_NODE_TYPES.TSStringKeyword) {
4581
4858
  return;
4582
4859
  }
4583
4860
  const name = keyName(key);
@@ -4665,10 +4942,10 @@ var prefer_string_literal_union_default = import_utils30.ESLintUtils.RuleCreator
4665
4942
  }
4666
4943
  };
4667
4944
  function refKeyText(node) {
4668
- if (node.type === import_utils30.AST_NODE_TYPES.BinaryExpression) {
4945
+ if (node.type === import_utils29.AST_NODE_TYPES.BinaryExpression) {
4669
4946
  return refKey(node.left) ?? refKey(node.right) ?? "value";
4670
4947
  }
4671
- if (node.type === import_utils30.AST_NODE_TYPES.SwitchStatement) {
4948
+ if (node.type === import_utils29.AST_NODE_TYPES.SwitchStatement) {
4672
4949
  return refKey(node.discriminant) ?? "value";
4673
4950
  }
4674
4951
  return "value";
@@ -4677,8 +4954,8 @@ var prefer_string_literal_union_default = import_utils30.ESLintUtils.RuleCreator
4677
4954
  });
4678
4955
 
4679
4956
  // src/rules/prefer-zod-enum.ts
4680
- var import_utils31 = require("@typescript-eslint/utils");
4681
- var prefer_zod_enum_default = import_utils31.ESLintUtils.RuleCreator(
4957
+ var import_utils30 = require("@typescript-eslint/utils");
4958
+ var prefer_zod_enum_default = import_utils30.ESLintUtils.RuleCreator(
4682
4959
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
4683
4960
  )({
4684
4961
  name: "prefer-zod-enum",
@@ -4699,20 +4976,20 @@ var prefer_zod_enum_default = import_utils31.ESLintUtils.RuleCreator(
4699
4976
  const zodNamespaces = /* @__PURE__ */ new Set();
4700
4977
  function enumValues(node) {
4701
4978
  const callee = node.callee;
4702
- if (callee.type !== import_utils31.AST_NODE_TYPES.MemberExpression || callee.computed || callee.object.type !== import_utils31.AST_NODE_TYPES.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== import_utils31.AST_NODE_TYPES.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
4979
+ if (callee.type !== import_utils30.AST_NODE_TYPES.MemberExpression || callee.computed || callee.object.type !== import_utils30.AST_NODE_TYPES.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== import_utils30.AST_NODE_TYPES.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
4703
4980
  return null;
4704
4981
  }
4705
4982
  const argument = node.arguments[0];
4706
- if (argument === void 0 || argument.type !== import_utils31.AST_NODE_TYPES.ArrayExpression || argument.elements.length === 0) {
4983
+ if (argument === void 0 || argument.type !== import_utils30.AST_NODE_TYPES.ArrayExpression || argument.elements.length === 0) {
4707
4984
  return null;
4708
4985
  }
4709
4986
  const values = [];
4710
4987
  for (const element of argument.elements) {
4711
- if (element === null || element.type !== import_utils31.AST_NODE_TYPES.CallExpression || element.arguments.length !== 1 || element.callee.type !== import_utils31.AST_NODE_TYPES.MemberExpression || element.callee.computed || element.callee.object.type !== import_utils31.AST_NODE_TYPES.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== import_utils31.AST_NODE_TYPES.Identifier || element.callee.property.name !== "literal") {
4988
+ if (element === null || element.type !== import_utils30.AST_NODE_TYPES.CallExpression || element.arguments.length !== 1 || element.callee.type !== import_utils30.AST_NODE_TYPES.MemberExpression || element.callee.computed || element.callee.object.type !== import_utils30.AST_NODE_TYPES.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== import_utils30.AST_NODE_TYPES.Identifier || element.callee.property.name !== "literal") {
4712
4989
  return null;
4713
4990
  }
4714
4991
  const value = element.arguments[0];
4715
- if (value === void 0 || value.type !== import_utils31.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
4992
+ if (value === void 0 || value.type !== import_utils30.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
4716
4993
  return null;
4717
4994
  }
4718
4995
  values.push(value);
@@ -4721,11 +4998,11 @@ var prefer_zod_enum_default = import_utils31.ESLintUtils.RuleCreator(
4721
4998
  }
4722
4999
  function buildFix(node, values) {
4723
5000
  const argument = node.arguments[0];
4724
- if (argument === void 0 || argument.type !== import_utils31.AST_NODE_TYPES.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
5001
+ if (argument === void 0 || argument.type !== import_utils30.AST_NODE_TYPES.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
4725
5002
  return void 0;
4726
5003
  }
4727
5004
  const callee = node.callee;
4728
- if (callee.type !== import_utils31.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils31.AST_NODE_TYPES.Identifier) {
5005
+ if (callee.type !== import_utils30.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils30.AST_NODE_TYPES.Identifier) {
4729
5006
  return void 0;
4730
5007
  }
4731
5008
  return (fixer) => [
@@ -4742,7 +5019,7 @@ var prefer_zod_enum_default = import_utils31.ESLintUtils.RuleCreator(
4742
5019
  return;
4743
5020
  }
4744
5021
  for (const specifier of node.specifiers) {
4745
- if (specifier.type === import_utils31.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils31.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils31.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils31.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") {
5022
+ if (specifier.type === import_utils30.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils30.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils30.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils30.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") {
4746
5023
  zodNamespaces.add(specifier.local.name);
4747
5024
  }
4748
5025
  }
@@ -4764,7 +5041,7 @@ var prefer_zod_enum_default = import_utils31.ESLintUtils.RuleCreator(
4764
5041
  });
4765
5042
 
4766
5043
  // src/rules/prefer-zod-infer.ts
4767
- var import_utils32 = require("@typescript-eslint/utils");
5044
+ var import_utils31 = require("@typescript-eslint/utils");
4768
5045
  var SHAPE_PRESERVING_METHODS = /* @__PURE__ */ new Set([
4769
5046
  "describe",
4770
5047
  "refine",
@@ -4801,44 +5078,44 @@ var ZOD_TYPE_CONSTRAINTS = /* @__PURE__ */ new Set([
4801
5078
  "Schema"
4802
5079
  ]);
4803
5080
  var LEAF_NODE_TYPES = {
4804
- string: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4805
- email: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4806
- url: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4807
- uuid: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4808
- ulid: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4809
- cuid: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4810
- cuid2: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4811
- nanoid: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4812
- iso: [import_utils32.AST_NODE_TYPES.TSStringKeyword],
4813
- number: [import_utils32.AST_NODE_TYPES.TSNumberKeyword],
4814
- int: [import_utils32.AST_NODE_TYPES.TSNumberKeyword],
4815
- float32: [import_utils32.AST_NODE_TYPES.TSNumberKeyword],
4816
- float64: [import_utils32.AST_NODE_TYPES.TSNumberKeyword],
4817
- boolean: [import_utils32.AST_NODE_TYPES.TSBooleanKeyword],
4818
- bigint: [import_utils32.AST_NODE_TYPES.TSBigIntKeyword],
4819
- symbol: [import_utils32.AST_NODE_TYPES.TSSymbolKeyword],
4820
- any: [import_utils32.AST_NODE_TYPES.TSAnyKeyword],
4821
- unknown: [import_utils32.AST_NODE_TYPES.TSUnknownKeyword],
4822
- never: [import_utils32.AST_NODE_TYPES.TSNeverKeyword],
4823
- void: [import_utils32.AST_NODE_TYPES.TSVoidKeyword],
4824
- null: [import_utils32.AST_NODE_TYPES.TSNullKeyword],
4825
- undefined: [import_utils32.AST_NODE_TYPES.TSUndefinedKeyword],
4826
- literal: [import_utils32.AST_NODE_TYPES.TSLiteralType],
4827
- date: [import_utils32.AST_NODE_TYPES.TSTypeReference],
4828
- array: [import_utils32.AST_NODE_TYPES.TSArrayType, import_utils32.AST_NODE_TYPES.TSTypeReference],
4829
- tuple: [import_utils32.AST_NODE_TYPES.TSTupleType],
4830
- object: [import_utils32.AST_NODE_TYPES.TSTypeLiteral, import_utils32.AST_NODE_TYPES.TSTypeReference],
4831
- strictObject: [import_utils32.AST_NODE_TYPES.TSTypeLiteral, import_utils32.AST_NODE_TYPES.TSTypeReference],
4832
- looseObject: [import_utils32.AST_NODE_TYPES.TSTypeLiteral, import_utils32.AST_NODE_TYPES.TSTypeReference],
4833
- record: [import_utils32.AST_NODE_TYPES.TSTypeReference, import_utils32.AST_NODE_TYPES.TSTypeLiteral],
4834
- map: [import_utils32.AST_NODE_TYPES.TSTypeReference],
4835
- set: [import_utils32.AST_NODE_TYPES.TSTypeReference],
4836
- promise: [import_utils32.AST_NODE_TYPES.TSTypeReference],
4837
- enum: [import_utils32.AST_NODE_TYPES.TSUnionType, import_utils32.AST_NODE_TYPES.TSTypeReference, import_utils32.AST_NODE_TYPES.TSLiteralType],
4838
- nativeEnum: [import_utils32.AST_NODE_TYPES.TSUnionType, import_utils32.AST_NODE_TYPES.TSTypeReference, import_utils32.AST_NODE_TYPES.TSLiteralType],
4839
- union: [import_utils32.AST_NODE_TYPES.TSUnionType, import_utils32.AST_NODE_TYPES.TSTypeReference],
4840
- discriminatedUnion: [import_utils32.AST_NODE_TYPES.TSUnionType, import_utils32.AST_NODE_TYPES.TSTypeReference],
4841
- intersection: [import_utils32.AST_NODE_TYPES.TSIntersectionType, import_utils32.AST_NODE_TYPES.TSTypeReference]
5081
+ string: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5082
+ email: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5083
+ url: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5084
+ uuid: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5085
+ ulid: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5086
+ cuid: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5087
+ cuid2: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5088
+ nanoid: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5089
+ iso: [import_utils31.AST_NODE_TYPES.TSStringKeyword],
5090
+ number: [import_utils31.AST_NODE_TYPES.TSNumberKeyword],
5091
+ int: [import_utils31.AST_NODE_TYPES.TSNumberKeyword],
5092
+ float32: [import_utils31.AST_NODE_TYPES.TSNumberKeyword],
5093
+ float64: [import_utils31.AST_NODE_TYPES.TSNumberKeyword],
5094
+ boolean: [import_utils31.AST_NODE_TYPES.TSBooleanKeyword],
5095
+ bigint: [import_utils31.AST_NODE_TYPES.TSBigIntKeyword],
5096
+ symbol: [import_utils31.AST_NODE_TYPES.TSSymbolKeyword],
5097
+ any: [import_utils31.AST_NODE_TYPES.TSAnyKeyword],
5098
+ unknown: [import_utils31.AST_NODE_TYPES.TSUnknownKeyword],
5099
+ never: [import_utils31.AST_NODE_TYPES.TSNeverKeyword],
5100
+ void: [import_utils31.AST_NODE_TYPES.TSVoidKeyword],
5101
+ null: [import_utils31.AST_NODE_TYPES.TSNullKeyword],
5102
+ undefined: [import_utils31.AST_NODE_TYPES.TSUndefinedKeyword],
5103
+ literal: [import_utils31.AST_NODE_TYPES.TSLiteralType],
5104
+ date: [import_utils31.AST_NODE_TYPES.TSTypeReference],
5105
+ array: [import_utils31.AST_NODE_TYPES.TSArrayType, import_utils31.AST_NODE_TYPES.TSTypeReference],
5106
+ tuple: [import_utils31.AST_NODE_TYPES.TSTupleType],
5107
+ object: [import_utils31.AST_NODE_TYPES.TSTypeLiteral, import_utils31.AST_NODE_TYPES.TSTypeReference],
5108
+ strictObject: [import_utils31.AST_NODE_TYPES.TSTypeLiteral, import_utils31.AST_NODE_TYPES.TSTypeReference],
5109
+ looseObject: [import_utils31.AST_NODE_TYPES.TSTypeLiteral, import_utils31.AST_NODE_TYPES.TSTypeReference],
5110
+ record: [import_utils31.AST_NODE_TYPES.TSTypeReference, import_utils31.AST_NODE_TYPES.TSTypeLiteral],
5111
+ map: [import_utils31.AST_NODE_TYPES.TSTypeReference],
5112
+ set: [import_utils31.AST_NODE_TYPES.TSTypeReference],
5113
+ promise: [import_utils31.AST_NODE_TYPES.TSTypeReference],
5114
+ enum: [import_utils31.AST_NODE_TYPES.TSUnionType, import_utils31.AST_NODE_TYPES.TSTypeReference, import_utils31.AST_NODE_TYPES.TSLiteralType],
5115
+ nativeEnum: [import_utils31.AST_NODE_TYPES.TSUnionType, import_utils31.AST_NODE_TYPES.TSTypeReference, import_utils31.AST_NODE_TYPES.TSLiteralType],
5116
+ union: [import_utils31.AST_NODE_TYPES.TSUnionType, import_utils31.AST_NODE_TYPES.TSTypeReference],
5117
+ discriminatedUnion: [import_utils31.AST_NODE_TYPES.TSUnionType, import_utils31.AST_NODE_TYPES.TSTypeReference],
5118
+ intersection: [import_utils31.AST_NODE_TYPES.TSIntersectionType, import_utils31.AST_NODE_TYPES.TSTypeReference]
4842
5119
  };
4843
5120
  function normalizeSchemaName(name) {
4844
5121
  return name.replace(/Schema$/i, "").replace(/^Z(?=[A-Z])/, "").toLowerCase();
@@ -4847,20 +5124,20 @@ function normalizeTypeName(name) {
4847
5124
  return name.replace(/Type$/, "").toLowerCase();
4848
5125
  }
4849
5126
  function unwrapNullish(annotation) {
4850
- if (annotation.type !== import_utils32.AST_NODE_TYPES.TSUnionType) {
5127
+ if (annotation.type !== import_utils31.AST_NODE_TYPES.TSUnionType) {
4851
5128
  return {
4852
5129
  core: annotation,
4853
- nullable: annotation.type === import_utils32.AST_NODE_TYPES.TSNullKeyword
5130
+ nullable: annotation.type === import_utils31.AST_NODE_TYPES.TSNullKeyword
4854
5131
  };
4855
5132
  }
4856
5133
  const rest = [];
4857
5134
  let nullable = false;
4858
5135
  for (const member of annotation.types) {
4859
- if (member.type === import_utils32.AST_NODE_TYPES.TSNullKeyword) {
5136
+ if (member.type === import_utils31.AST_NODE_TYPES.TSNullKeyword) {
4860
5137
  nullable = true;
4861
5138
  continue;
4862
5139
  }
4863
- if (member.type === import_utils32.AST_NODE_TYPES.TSUndefinedKeyword) {
5140
+ if (member.type === import_utils31.AST_NODE_TYPES.TSUndefinedKeyword) {
4864
5141
  continue;
4865
5142
  }
4866
5143
  rest.push(member);
@@ -4884,7 +5161,7 @@ function leafAgrees(leaf, annotation) {
4884
5161
  }
4885
5162
  return expected.includes(core.type);
4886
5163
  }
4887
- var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5164
+ var prefer_zod_infer_default = import_utils31.ESLintUtils.RuleCreator(
4888
5165
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
4889
5166
  )({
4890
5167
  name: "prefer-zod-infer",
@@ -4927,14 +5204,14 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
4927
5204
  function zodCallChain(node) {
4928
5205
  const chain = [];
4929
5206
  let current = node;
4930
- while (current.type === import_utils32.AST_NODE_TYPES.CallExpression) {
5207
+ while (current.type === import_utils31.AST_NODE_TYPES.CallExpression) {
4931
5208
  const callee = current.callee;
4932
- if (callee.type !== import_utils32.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils32.AST_NODE_TYPES.Identifier) {
5209
+ if (callee.type !== import_utils31.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils31.AST_NODE_TYPES.Identifier) {
4933
5210
  return null;
4934
5211
  }
4935
5212
  chain.push(current);
4936
5213
  const receiver = callee.object;
4937
- if (receiver.type === import_utils32.AST_NODE_TYPES.Identifier) {
5214
+ if (receiver.type === import_utils31.AST_NODE_TYPES.Identifier) {
4938
5215
  return zodNamespaces.has(receiver.name) ? chain.reverse() : null;
4939
5216
  }
4940
5217
  current = receiver;
@@ -4943,19 +5220,19 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
4943
5220
  }
4944
5221
  function methodName(call) {
4945
5222
  const callee = call.callee;
4946
- return callee.type === import_utils32.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils32.AST_NODE_TYPES.Identifier ? callee.property.name : "";
5223
+ return callee.type === import_utils31.AST_NODE_TYPES.MemberExpression && callee.property.type === import_utils31.AST_NODE_TYPES.Identifier ? callee.property.name : "";
4947
5224
  }
4948
5225
  function schemaField(node) {
4949
5226
  const modifiers = [];
4950
5227
  let current = node;
4951
5228
  let leaf = null;
4952
- while (current.type === import_utils32.AST_NODE_TYPES.CallExpression) {
5229
+ while (current.type === import_utils31.AST_NODE_TYPES.CallExpression) {
4953
5230
  const callee = current.callee;
4954
- if (callee.type !== import_utils32.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils32.AST_NODE_TYPES.Identifier) {
5231
+ if (callee.type !== import_utils31.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils31.AST_NODE_TYPES.Identifier) {
4955
5232
  break;
4956
5233
  }
4957
5234
  const receiver = callee.object;
4958
- if (receiver.type === import_utils32.AST_NODE_TYPES.Identifier && zodNamespaces.has(receiver.name)) {
5235
+ if (receiver.type === import_utils31.AST_NODE_TYPES.Identifier && zodNamespaces.has(receiver.name)) {
4959
5236
  leaf = callee.property.name;
4960
5237
  break;
4961
5238
  }
@@ -4986,16 +5263,16 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
4986
5263
  return null;
4987
5264
  }
4988
5265
  const shape = base.arguments[0];
4989
- if (shape === void 0 || shape.type !== import_utils32.AST_NODE_TYPES.ObjectExpression) {
5266
+ if (shape === void 0 || shape.type !== import_utils31.AST_NODE_TYPES.ObjectExpression) {
4990
5267
  return null;
4991
5268
  }
4992
5269
  const fields = /* @__PURE__ */ new Map();
4993
5270
  for (const property of shape.properties) {
4994
- if (property.type !== import_utils32.AST_NODE_TYPES.Property || property.computed) {
5271
+ if (property.type !== import_utils31.AST_NODE_TYPES.Property || property.computed) {
4995
5272
  return null;
4996
5273
  }
4997
5274
  const { key } = property;
4998
- const name = key.type === import_utils32.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils32.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
5275
+ const name = key.type === import_utils31.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils31.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
4999
5276
  if (name === null) {
5000
5277
  return null;
5001
5278
  }
@@ -5006,11 +5283,11 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5006
5283
  function typeMembers(members) {
5007
5284
  const result = /* @__PURE__ */ new Map();
5008
5285
  for (const member of members) {
5009
- if (member.type !== import_utils32.AST_NODE_TYPES.TSPropertySignature || member.computed) {
5286
+ if (member.type !== import_utils31.AST_NODE_TYPES.TSPropertySignature || member.computed) {
5010
5287
  return null;
5011
5288
  }
5012
5289
  const { key } = member;
5013
- const name = key.type === import_utils32.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils32.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
5290
+ const name = key.type === import_utils31.AST_NODE_TYPES.Identifier ? key.name : key.type === import_utils31.AST_NODE_TYPES.Literal && typeof key.value === "string" ? key.value : null;
5014
5291
  if (name === null) {
5015
5292
  return null;
5016
5293
  }
@@ -5024,8 +5301,8 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5024
5301
  return result.size === 0 ? null : result;
5025
5302
  }
5026
5303
  function collectConstrainedNames(node) {
5027
- if (node.type === import_utils32.AST_NODE_TYPES.TSTypeReference) {
5028
- if (node.typeName.type === import_utils32.AST_NODE_TYPES.Identifier) {
5304
+ if (node.type === import_utils31.AST_NODE_TYPES.TSTypeReference) {
5305
+ if (node.typeName.type === import_utils31.AST_NODE_TYPES.Identifier) {
5029
5306
  constrainedTypeNames.add(node.typeName.name);
5030
5307
  }
5031
5308
  for (const argument of node.typeArguments?.params ?? []) {
@@ -5033,11 +5310,11 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5033
5310
  }
5034
5311
  return;
5035
5312
  }
5036
- if (node.type === import_utils32.AST_NODE_TYPES.TSArrayType) {
5313
+ if (node.type === import_utils31.AST_NODE_TYPES.TSArrayType) {
5037
5314
  collectConstrainedNames(node.elementType);
5038
5315
  return;
5039
5316
  }
5040
- if (node.type === import_utils32.AST_NODE_TYPES.TSUnionType || node.type === import_utils32.AST_NODE_TYPES.TSIntersectionType) {
5317
+ if (node.type === import_utils31.AST_NODE_TYPES.TSUnionType || node.type === import_utils31.AST_NODE_TYPES.TSIntersectionType) {
5041
5318
  for (const member of node.types) {
5042
5319
  collectConstrainedNames(member);
5043
5320
  }
@@ -5081,13 +5358,13 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5081
5358
  return;
5082
5359
  }
5083
5360
  for (const specifier of node.specifiers) {
5084
- if (specifier.type === import_utils32.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils32.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils32.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils32.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") {
5361
+ if (specifier.type === import_utils31.AST_NODE_TYPES.ImportNamespaceSpecifier || specifier.type === import_utils31.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils31.AST_NODE_TYPES.ImportSpecifier && specifier.imported.type === import_utils31.AST_NODE_TYPES.Identifier && specifier.imported.name === "z") {
5085
5362
  zodNamespaces.add(specifier.local.name);
5086
5363
  }
5087
5364
  }
5088
5365
  },
5089
5366
  VariableDeclarator(node) {
5090
- if (node.id.type !== import_utils32.AST_NODE_TYPES.Identifier || node.init == null) {
5367
+ if (node.id.type !== import_utils31.AST_NODE_TYPES.Identifier || node.init == null) {
5091
5368
  return;
5092
5369
  }
5093
5370
  const fields = schemaFields(node.init);
@@ -5097,14 +5374,14 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5097
5374
  },
5098
5375
  /** Guard (f): `XSchema.transform(...)` anywhere in the module. */
5099
5376
  "MemberExpression[computed=false]"(node) {
5100
- if (node.object.type === import_utils32.AST_NODE_TYPES.Identifier && node.property.type === import_utils32.AST_NODE_TYPES.Identifier && MODULE_LEVEL_RESHAPERS.has(node.property.name)) {
5377
+ if (node.object.type === import_utils31.AST_NODE_TYPES.Identifier && node.property.type === import_utils31.AST_NODE_TYPES.Identifier && MODULE_LEVEL_RESHAPERS.has(node.property.name)) {
5101
5378
  reshapedSchemaNames.add(node.object.name);
5102
5379
  }
5103
5380
  },
5104
5381
  /** Guard (c): `z.ZodType<T>` and every other type argument it carries. */
5105
5382
  TSTypeReference(node) {
5106
5383
  const { typeName } = node;
5107
- const referenced = typeName.type === import_utils32.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils32.AST_NODE_TYPES.TSQualifiedName && typeName.right.type === import_utils32.AST_NODE_TYPES.Identifier ? typeName.right.name : null;
5384
+ const referenced = typeName.type === import_utils31.AST_NODE_TYPES.Identifier ? typeName.name : typeName.type === import_utils31.AST_NODE_TYPES.TSQualifiedName && typeName.right.type === import_utils31.AST_NODE_TYPES.Identifier ? typeName.right.name : null;
5108
5385
  if (referenced === null || !ZOD_TYPE_CONSTRAINTS.has(referenced)) {
5109
5386
  return;
5110
5387
  }
@@ -5122,7 +5399,7 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5122
5399
  }
5123
5400
  },
5124
5401
  TSTypeAliasDeclaration(node) {
5125
- if (node.typeParameters !== void 0 || node.typeAnnotation.type !== import_utils32.AST_NODE_TYPES.TSTypeLiteral) {
5402
+ if (node.typeParameters !== void 0 || node.typeAnnotation.type !== import_utils31.AST_NODE_TYPES.TSTypeLiteral) {
5126
5403
  return;
5127
5404
  }
5128
5405
  const members = typeMembers(node.typeAnnotation.members);
@@ -5167,10 +5444,10 @@ var prefer_zod_infer_default = import_utils32.ESLintUtils.RuleCreator(
5167
5444
  });
5168
5445
 
5169
5446
  // src/rules/no-offset-pagination.ts
5170
- var import_utils34 = require("@typescript-eslint/utils");
5447
+ var import_utils33 = require("@typescript-eslint/utils");
5171
5448
 
5172
5449
  // src/rules/_sql.ts
5173
- var import_utils33 = require("@typescript-eslint/utils");
5450
+ var import_utils32 = require("@typescript-eslint/utils");
5174
5451
  function stripSqlNoise(text) {
5175
5452
  const out = [...text];
5176
5453
  const n = text.length;
@@ -5231,13 +5508,13 @@ function stripSqlNoise(text) {
5231
5508
  var SUBSTITUTION_MARKER = "?";
5232
5509
  function sqlTextOf(node) {
5233
5510
  switch (node.type) {
5234
- case import_utils33.AST_NODE_TYPES.Literal:
5511
+ case import_utils32.AST_NODE_TYPES.Literal:
5235
5512
  return typeof node.value === "string" ? node.value : null;
5236
- case import_utils33.AST_NODE_TYPES.TemplateLiteral:
5513
+ case import_utils32.AST_NODE_TYPES.TemplateLiteral:
5237
5514
  return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join(SUBSTITUTION_MARKER);
5238
- case import_utils33.AST_NODE_TYPES.TaggedTemplateExpression:
5515
+ case import_utils32.AST_NODE_TYPES.TaggedTemplateExpression:
5239
5516
  return sqlTextOf(node.quasi);
5240
- case import_utils33.AST_NODE_TYPES.BinaryExpression: {
5517
+ case import_utils32.AST_NODE_TYPES.BinaryExpression: {
5241
5518
  if (node.operator !== "+") {
5242
5519
  return null;
5243
5520
  }
@@ -5245,7 +5522,7 @@ function sqlTextOf(node) {
5245
5522
  const right = sqlTextOf(node.right);
5246
5523
  return left !== null && right !== null ? left + right : null;
5247
5524
  }
5248
- case import_utils33.AST_NODE_TYPES.ArrayExpression: {
5525
+ case import_utils32.AST_NODE_TYPES.ArrayExpression: {
5249
5526
  const parts = [];
5250
5527
  for (const element of node.elements) {
5251
5528
  if (element === null) {
@@ -5265,7 +5542,7 @@ function sqlTextOf(node) {
5265
5542
  }
5266
5543
  function isJoinedFragmentArray(node) {
5267
5544
  const parent = node.parent;
5268
- return parent?.type === import_utils33.AST_NODE_TYPES.MemberExpression && parent.object === node && !parent.computed && parent.property.type === import_utils33.AST_NODE_TYPES.Identifier && parent.property.name === "join" && parent.parent?.type === import_utils33.AST_NODE_TYPES.CallExpression;
5545
+ return parent?.type === import_utils32.AST_NODE_TYPES.MemberExpression && parent.object === node && !parent.computed && parent.property.type === import_utils32.AST_NODE_TYPES.Identifier && parent.property.name === "join" && parent.parent?.type === import_utils32.AST_NODE_TYPES.CallExpression;
5269
5546
  }
5270
5547
  function markConsumed(node, consumed) {
5271
5548
  consumed.add(node);
@@ -5315,7 +5592,7 @@ function createSqlListener(handler) {
5315
5592
  // src/rules/no-offset-pagination.ts
5316
5593
  var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
5317
5594
  var OFFSET_GATE = /offset/i;
5318
- var no_offset_pagination_default = import_utils34.ESLintUtils.RuleCreator(
5595
+ var no_offset_pagination_default = import_utils33.ESLintUtils.RuleCreator(
5319
5596
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5320
5597
  )({
5321
5598
  name: "no-offset-pagination",
@@ -5344,15 +5621,15 @@ var no_offset_pagination_default = import_utils34.ESLintUtils.RuleCreator(
5344
5621
  });
5345
5622
 
5346
5623
  // src/rules/no-positional-tuple-return.ts
5347
- var import_utils35 = require("@typescript-eslint/utils");
5624
+ var import_utils34 = require("@typescript-eslint/utils");
5348
5625
  var MIN_ELEMENTS = 2;
5349
5626
  var ACCESSOR_PAIR_LENGTH = 2;
5350
5627
  var AWAITABLE_TYPES = /* @__PURE__ */ new Set(["Promise", "PromiseLike", "Awaited"]);
5351
5628
  function tupleReturnType(node) {
5352
- if (node.type === import_utils35.AST_NODE_TYPES.TSTupleType) {
5629
+ if (node.type === import_utils34.AST_NODE_TYPES.TSTupleType) {
5353
5630
  return node;
5354
5631
  }
5355
- if (node.type === import_utils35.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils35.AST_NODE_TYPES.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5632
+ if (node.type === import_utils34.AST_NODE_TYPES.TSTypeReference && node.typeName.type === import_utils34.AST_NODE_TYPES.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5356
5633
  const argument = node.typeArguments?.params[0];
5357
5634
  return argument === void 0 ? null : tupleReturnType(argument);
5358
5635
  }
@@ -5366,30 +5643,30 @@ function isPermittedTuple(tuple, sourceCode) {
5366
5643
  if (elements.length < MIN_ELEMENTS) {
5367
5644
  return true;
5368
5645
  }
5369
- if (elements.some((element) => element.type === import_utils35.AST_NODE_TYPES.TSRestType)) {
5646
+ if (elements.some((element) => element.type === import_utils34.AST_NODE_TYPES.TSRestType)) {
5370
5647
  return true;
5371
5648
  }
5372
- if (elements.some((element) => element.type === import_utils35.AST_NODE_TYPES.TSNamedTupleMember)) {
5649
+ if (elements.some((element) => element.type === import_utils34.AST_NODE_TYPES.TSNamedTupleMember)) {
5373
5650
  return true;
5374
5651
  }
5375
- if (elements[0]?.type === import_utils35.AST_NODE_TYPES.TSLiteralType) {
5652
+ if (elements[0]?.type === import_utils34.AST_NODE_TYPES.TSLiteralType) {
5376
5653
  return true;
5377
5654
  }
5378
- if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === import_utils35.AST_NODE_TYPES.TSFunctionType)) {
5655
+ if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === import_utils34.AST_NODE_TYPES.TSFunctionType)) {
5379
5656
  return true;
5380
5657
  }
5381
5658
  const texts = new Set(elements.map((element) => normalizedText(sourceCode, element)));
5382
5659
  return texts.size === 1;
5383
5660
  }
5384
5661
  function functionName(node) {
5385
- if (node.type === import_utils35.AST_NODE_TYPES.FunctionDeclaration) {
5662
+ if (node.type === import_utils34.AST_NODE_TYPES.FunctionDeclaration) {
5386
5663
  return node.id?.name ?? null;
5387
5664
  }
5388
5665
  const parent = node.parent;
5389
- if (parent?.type === import_utils35.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils35.AST_NODE_TYPES.Identifier) {
5666
+ if (parent?.type === import_utils34.AST_NODE_TYPES.VariableDeclarator && parent.id.type === import_utils34.AST_NODE_TYPES.Identifier) {
5390
5667
  return parent.id.name;
5391
5668
  }
5392
- if ((parent?.type === import_utils35.AST_NODE_TYPES.MethodDefinition || parent?.type === import_utils35.AST_NODE_TYPES.PropertyDefinition || parent?.type === import_utils35.AST_NODE_TYPES.Property) && parent.key.type === import_utils35.AST_NODE_TYPES.Identifier) {
5669
+ if ((parent?.type === import_utils34.AST_NODE_TYPES.MethodDefinition || parent?.type === import_utils34.AST_NODE_TYPES.PropertyDefinition || parent?.type === import_utils34.AST_NODE_TYPES.Property) && parent.key.type === import_utils34.AST_NODE_TYPES.Identifier) {
5393
5670
  return parent.key.name;
5394
5671
  }
5395
5672
  return null;
@@ -5397,7 +5674,7 @@ function functionName(node) {
5397
5674
  function isInlineExported(node) {
5398
5675
  for (let current = node; current != null; current = current.parent) {
5399
5676
  const parent = current.parent;
5400
- if (parent?.type === import_utils35.AST_NODE_TYPES.ExportNamedDeclaration || parent?.type === import_utils35.AST_NODE_TYPES.ExportDefaultDeclaration) {
5677
+ if (parent?.type === import_utils34.AST_NODE_TYPES.ExportNamedDeclaration || parent?.type === import_utils34.AST_NODE_TYPES.ExportDefaultDeclaration) {
5401
5678
  return true;
5402
5679
  }
5403
5680
  }
@@ -5406,18 +5683,18 @@ function isInlineExported(node) {
5406
5683
  function moduleScopeBindingName(node) {
5407
5684
  let current = node;
5408
5685
  let child = node;
5409
- while (current.parent != null && current.parent.type !== import_utils35.AST_NODE_TYPES.Program) {
5686
+ while (current.parent != null && current.parent.type !== import_utils34.AST_NODE_TYPES.Program) {
5410
5687
  child = current;
5411
5688
  current = current.parent;
5412
5689
  }
5413
- if (current.parent?.type !== import_utils35.AST_NODE_TYPES.Program) {
5690
+ if (current.parent?.type !== import_utils34.AST_NODE_TYPES.Program) {
5414
5691
  return null;
5415
5692
  }
5416
- if (current.type === import_utils35.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils35.AST_NODE_TYPES.ClassDeclaration) {
5693
+ if (current.type === import_utils34.AST_NODE_TYPES.FunctionDeclaration || current.type === import_utils34.AST_NODE_TYPES.ClassDeclaration) {
5417
5694
  return current.id?.name ?? null;
5418
5695
  }
5419
- if (current.type === import_utils35.AST_NODE_TYPES.VariableDeclaration) {
5420
- if (child.type !== import_utils35.AST_NODE_TYPES.VariableDeclarator || child.id.type !== import_utils35.AST_NODE_TYPES.Identifier) {
5696
+ if (current.type === import_utils34.AST_NODE_TYPES.VariableDeclaration) {
5697
+ if (child.type !== import_utils34.AST_NODE_TYPES.VariableDeclarator || child.id.type !== import_utils34.AST_NODE_TYPES.Identifier) {
5421
5698
  return null;
5422
5699
  }
5423
5700
  return child.id.name;
@@ -5427,19 +5704,19 @@ function moduleScopeBindingName(node) {
5427
5704
  function specifierExportedNames(program) {
5428
5705
  const names = /* @__PURE__ */ new Set();
5429
5706
  for (const statement of program.body) {
5430
- if (statement.type === import_utils35.AST_NODE_TYPES.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5707
+ if (statement.type === import_utils34.AST_NODE_TYPES.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5431
5708
  for (const specifier of statement.specifiers) {
5432
- if (specifier.exportKind !== "type" && specifier.local.type === import_utils35.AST_NODE_TYPES.Identifier) {
5709
+ if (specifier.exportKind !== "type" && specifier.local.type === import_utils34.AST_NODE_TYPES.Identifier) {
5433
5710
  names.add(specifier.local.name);
5434
5711
  }
5435
5712
  }
5436
5713
  continue;
5437
5714
  }
5438
- if (statement.type === import_utils35.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils35.AST_NODE_TYPES.Identifier) {
5715
+ if (statement.type === import_utils34.AST_NODE_TYPES.ExportDefaultDeclaration && statement.declaration.type === import_utils34.AST_NODE_TYPES.Identifier) {
5439
5716
  names.add(statement.declaration.name);
5440
5717
  continue;
5441
5718
  }
5442
- if (statement.type === import_utils35.AST_NODE_TYPES.TSExportAssignment && statement.expression.type === import_utils35.AST_NODE_TYPES.Identifier) {
5719
+ if (statement.type === import_utils34.AST_NODE_TYPES.TSExportAssignment && statement.expression.type === import_utils34.AST_NODE_TYPES.Identifier) {
5443
5720
  names.add(statement.expression.name);
5444
5721
  }
5445
5722
  }
@@ -5455,7 +5732,7 @@ function isExported(node, specifierExports) {
5455
5732
  const binding = moduleScopeBindingName(node);
5456
5733
  return binding !== null && specifierExports.has(binding);
5457
5734
  }
5458
- var no_positional_tuple_return_default = import_utils35.ESLintUtils.RuleCreator(
5735
+ var no_positional_tuple_return_default = import_utils34.ESLintUtils.RuleCreator(
5459
5736
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5460
5737
  )({
5461
5738
  name: "no-positional-tuple-return",
@@ -5503,16 +5780,16 @@ var no_positional_tuple_return_default = import_utils35.ESLintUtils.RuleCreator(
5503
5780
  });
5504
5781
 
5505
5782
  // src/rules/no-repeated-string-literal.ts
5506
- var import_utils36 = require("@typescript-eslint/utils");
5783
+ var import_utils35 = require("@typescript-eslint/utils");
5507
5784
  var MIN_LENGTH = 40;
5508
5785
  var MIN_DISTINCT_SCOPES = 2;
5509
5786
  var PREVIEW_LENGTH = 40;
5510
5787
  var SQL_KEYWORD_RE = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES|ON CONFLICT|RETURNING|GROUP BY|ORDER BY)\b/;
5511
5788
  var IDENTIFIER_RE = /^[a-z_][a-z0-9_.]*$/;
5512
- var FUNCTION_TYPES = /* @__PURE__ */ new Set([
5513
- import_utils36.AST_NODE_TYPES.FunctionDeclaration,
5514
- import_utils36.AST_NODE_TYPES.FunctionExpression,
5515
- import_utils36.AST_NODE_TYPES.ArrowFunctionExpression
5789
+ var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5790
+ import_utils35.AST_NODE_TYPES.FunctionDeclaration,
5791
+ import_utils35.AST_NODE_TYPES.FunctionExpression,
5792
+ import_utils35.AST_NODE_TYPES.ArrowFunctionExpression
5516
5793
  ]);
5517
5794
  function isStructured(value) {
5518
5795
  return value.includes("\n") || SQL_KEYWORD_RE.test(value) || IDENTIFIER_RE.test(value);
@@ -5523,7 +5800,7 @@ function preview(value) {
5523
5800
  }
5524
5801
  function enclosingFunction(node) {
5525
5802
  for (let current = node.parent; current != null; current = current.parent) {
5526
- if (FUNCTION_TYPES.has(current.type)) {
5803
+ if (FUNCTION_TYPES2.has(current.type)) {
5527
5804
  return current;
5528
5805
  }
5529
5806
  }
@@ -5534,9 +5811,9 @@ function isScaffolding(node) {
5534
5811
  if (parent === void 0) {
5535
5812
  return true;
5536
5813
  }
5537
- return parent.type === import_utils36.AST_NODE_TYPES.ImportDeclaration || parent.type === import_utils36.AST_NODE_TYPES.ExportNamedDeclaration || parent.type === import_utils36.AST_NODE_TYPES.ExportAllDeclaration || parent.type === import_utils36.AST_NODE_TYPES.TSImportType || parent.type === import_utils36.AST_NODE_TYPES.JSXAttribute || parent.type === import_utils36.AST_NODE_TYPES.TSLiteralType;
5814
+ return parent.type === import_utils35.AST_NODE_TYPES.ImportDeclaration || parent.type === import_utils35.AST_NODE_TYPES.ExportNamedDeclaration || parent.type === import_utils35.AST_NODE_TYPES.ExportAllDeclaration || parent.type === import_utils35.AST_NODE_TYPES.TSImportType || parent.type === import_utils35.AST_NODE_TYPES.JSXAttribute || parent.type === import_utils35.AST_NODE_TYPES.TSLiteralType;
5538
5815
  }
5539
- var no_repeated_string_literal_default = import_utils36.ESLintUtils.RuleCreator(
5816
+ var no_repeated_string_literal_default = import_utils35.ESLintUtils.RuleCreator(
5540
5817
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5541
5818
  )({
5542
5819
  name: "no-repeated-string-literal",
@@ -5576,7 +5853,7 @@ var no_repeated_string_literal_default = import_utils36.ESLintUtils.RuleCreator(
5576
5853
  }
5577
5854
  },
5578
5855
  TemplateLiteral(node) {
5579
- if (node.parent.type === import_utils36.AST_NODE_TYPES.TaggedTemplateExpression) {
5856
+ if (node.parent.type === import_utils35.AST_NODE_TYPES.TaggedTemplateExpression) {
5580
5857
  return;
5581
5858
  }
5582
5859
  const [only] = node.quasis;
@@ -5610,7 +5887,7 @@ var no_repeated_string_literal_default = import_utils36.ESLintUtils.RuleCreator(
5610
5887
  });
5611
5888
 
5612
5889
  // src/rules/no-select-star.ts
5613
- var import_utils37 = require("@typescript-eslint/utils");
5890
+ var import_utils36 = require("@typescript-eslint/utils");
5614
5891
  var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
5615
5892
  var SELECT_KEYWORD = /\bSELECT\b/gi;
5616
5893
  var FROM_KEYWORD = /^FROM\b/i;
@@ -5650,7 +5927,7 @@ function hasRealSelectStar(sql) {
5650
5927
  }
5651
5928
  return false;
5652
5929
  }
5653
- var no_select_star_default = import_utils37.ESLintUtils.RuleCreator(
5930
+ var no_select_star_default = import_utils36.ESLintUtils.RuleCreator(
5654
5931
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5655
5932
  )({
5656
5933
  name: "no-select-star",
@@ -5679,7 +5956,7 @@ var no_select_star_default = import_utils37.ESLintUtils.RuleCreator(
5679
5956
  });
5680
5957
 
5681
5958
  // src/rules/no-sleep-in-test-body.ts
5682
- var import_utils38 = require("@typescript-eslint/utils");
5959
+ var import_utils37 = require("@typescript-eslint/utils");
5683
5960
  var SLEEP_HELPERS = /* @__PURE__ */ new Set(["sleep", "delay", "wait", "pause"]);
5684
5961
  var TEST_CALLERS = /* @__PURE__ */ new Set([
5685
5962
  "it",
@@ -5687,43 +5964,43 @@ var TEST_CALLERS = /* @__PURE__ */ new Set([
5687
5964
  "beforeEach",
5688
5965
  "afterEach"
5689
5966
  ]);
5690
- var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5691
- import_utils38.AST_NODE_TYPES.FunctionDeclaration,
5692
- import_utils38.AST_NODE_TYPES.FunctionExpression,
5693
- import_utils38.AST_NODE_TYPES.ArrowFunctionExpression
5967
+ var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5968
+ import_utils37.AST_NODE_TYPES.FunctionDeclaration,
5969
+ import_utils37.AST_NODE_TYPES.FunctionExpression,
5970
+ import_utils37.AST_NODE_TYPES.ArrowFunctionExpression
5694
5971
  ]);
5695
5972
  function isNonzeroNumericLiteral(node) {
5696
- return node?.type === import_utils38.AST_NODE_TYPES.Literal && typeof node.value === "number" && node.value !== 0;
5973
+ return node?.type === import_utils37.AST_NODE_TYPES.Literal && typeof node.value === "number" && node.value !== 0;
5697
5974
  }
5698
5975
  function isTimedSetTimeout(node) {
5699
- return node.type === import_utils38.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils38.AST_NODE_TYPES.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5976
+ return node.type === import_utils37.AST_NODE_TYPES.CallExpression && node.callee.type === import_utils37.AST_NODE_TYPES.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5700
5977
  }
5701
5978
  function isPromiseSleep(node) {
5702
- if (node.callee.type !== import_utils38.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise") {
5979
+ if (node.callee.type !== import_utils37.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise") {
5703
5980
  return false;
5704
5981
  }
5705
5982
  const executor = node.arguments[0];
5706
- if (executor?.type !== import_utils38.AST_NODE_TYPES.ArrowFunctionExpression && executor?.type !== import_utils38.AST_NODE_TYPES.FunctionExpression) {
5983
+ if (executor?.type !== import_utils37.AST_NODE_TYPES.ArrowFunctionExpression && executor?.type !== import_utils37.AST_NODE_TYPES.FunctionExpression) {
5707
5984
  return false;
5708
5985
  }
5709
5986
  const body = executor.body;
5710
- if (body.type !== import_utils38.AST_NODE_TYPES.BlockStatement) {
5987
+ if (body.type !== import_utils37.AST_NODE_TYPES.BlockStatement) {
5711
5988
  return isTimedSetTimeout(body);
5712
5989
  }
5713
5990
  return body.body.some(
5714
- (stmt) => stmt.type === import_utils38.AST_NODE_TYPES.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5991
+ (stmt) => stmt.type === import_utils37.AST_NODE_TYPES.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5715
5992
  );
5716
5993
  }
5717
5994
  function isHelperSleep(node) {
5718
- return node.callee.type === import_utils38.AST_NODE_TYPES.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5995
+ return node.callee.type === import_utils37.AST_NODE_TYPES.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5719
5996
  }
5720
5997
  function nearestEnclosingFunction(node) {
5721
5998
  for (let current = node.parent; current != null; current = current.parent) {
5722
- if (!FUNCTION_TYPES2.has(current.type)) {
5999
+ if (!FUNCTION_TYPES3.has(current.type)) {
5723
6000
  continue;
5724
6001
  }
5725
6002
  const grandparent = current.parent;
5726
- const isPromiseExecutor = grandparent?.type === import_utils38.AST_NODE_TYPES.NewExpression && isPromiseSleep(grandparent);
6003
+ const isPromiseExecutor = grandparent?.type === import_utils37.AST_NODE_TYPES.NewExpression && isPromiseSleep(grandparent);
5727
6004
  if (!isPromiseExecutor) {
5728
6005
  return current;
5729
6006
  }
@@ -5731,29 +6008,29 @@ function nearestEnclosingFunction(node) {
5731
6008
  return null;
5732
6009
  }
5733
6010
  function testCallerName(callee) {
5734
- if (callee.type === import_utils38.AST_NODE_TYPES.Identifier) {
6011
+ if (callee.type === import_utils37.AST_NODE_TYPES.Identifier) {
5735
6012
  return callee.name;
5736
6013
  }
5737
- if (callee.type === import_utils38.AST_NODE_TYPES.MemberExpression) {
6014
+ if (callee.type === import_utils37.AST_NODE_TYPES.MemberExpression) {
5738
6015
  return testCallerName(callee.object);
5739
6016
  }
5740
- if (callee.type === import_utils38.AST_NODE_TYPES.CallExpression) {
6017
+ if (callee.type === import_utils37.AST_NODE_TYPES.CallExpression) {
5741
6018
  return testCallerName(callee.callee);
5742
6019
  }
5743
- if (callee.type === import_utils38.AST_NODE_TYPES.TaggedTemplateExpression) {
6020
+ if (callee.type === import_utils37.AST_NODE_TYPES.TaggedTemplateExpression) {
5744
6021
  return testCallerName(callee.tag);
5745
6022
  }
5746
6023
  return null;
5747
6024
  }
5748
6025
  function isTestBody(fn) {
5749
6026
  const call = fn.parent;
5750
- if (call?.type !== import_utils38.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
6027
+ if (call?.type !== import_utils37.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5751
6028
  return false;
5752
6029
  }
5753
6030
  const name = testCallerName(call.callee);
5754
6031
  return name !== null && TEST_CALLERS.has(name);
5755
6032
  }
5756
- var no_sleep_in_test_body_default = import_utils38.ESLintUtils.RuleCreator(
6033
+ var no_sleep_in_test_body_default = import_utils37.ESLintUtils.RuleCreator(
5757
6034
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5758
6035
  )({
5759
6036
  name: "no-sleep-in-test-body",
@@ -5795,52 +6072,222 @@ var no_sleep_in_test_body_default = import_utils38.ESLintUtils.RuleCreator(
5795
6072
  });
5796
6073
 
5797
6074
  // src/rules/no-conditional-in-test.ts
5798
- var import_utils39 = require("@typescript-eslint/utils");
6075
+ var import_utils38 = require("@typescript-eslint/utils");
5799
6076
  var TEST_CALLERS2 = /* @__PURE__ */ new Set(["it", "test"]);
5800
- var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5801
- import_utils39.AST_NODE_TYPES.FunctionDeclaration,
5802
- import_utils39.AST_NODE_TYPES.FunctionExpression,
5803
- import_utils39.AST_NODE_TYPES.ArrowFunctionExpression
6077
+ var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6078
+ import_utils38.AST_NODE_TYPES.FunctionDeclaration,
6079
+ import_utils38.AST_NODE_TYPES.FunctionExpression,
6080
+ import_utils38.AST_NODE_TYPES.ArrowFunctionExpression
6081
+ ]);
6082
+ var ASSERTION_ROOTS = /* @__PURE__ */ new Set([
6083
+ "expect",
6084
+ "expectTypeOf",
6085
+ "assert",
6086
+ "assertType"
6087
+ ]);
6088
+ var TYPE_ASSERTION_ROOTS = /* @__PURE__ */ new Set([
6089
+ "expectTypeOf",
6090
+ "assertType"
5804
6091
  ]);
5805
6092
  function nearestEnclosingFunction2(node) {
5806
6093
  for (let current = node.parent; current != null; current = current.parent) {
5807
- if (FUNCTION_TYPES3.has(current.type)) {
6094
+ if (FUNCTION_TYPES4.has(current.type)) {
5808
6095
  return current;
5809
6096
  }
5810
6097
  }
5811
6098
  return null;
5812
6099
  }
5813
6100
  function testCallerName2(callee) {
5814
- if (callee.type === import_utils39.AST_NODE_TYPES.Identifier) {
6101
+ if (callee.type === import_utils38.AST_NODE_TYPES.Identifier) {
5815
6102
  return callee.name;
5816
6103
  }
5817
- if (callee.type === import_utils39.AST_NODE_TYPES.MemberExpression) {
6104
+ if (callee.type === import_utils38.AST_NODE_TYPES.MemberExpression) {
5818
6105
  return testCallerName2(callee.object);
5819
6106
  }
5820
- if (callee.type === import_utils39.AST_NODE_TYPES.CallExpression) {
6107
+ if (callee.type === import_utils38.AST_NODE_TYPES.CallExpression) {
5821
6108
  return testCallerName2(callee.callee);
5822
6109
  }
5823
- if (callee.type === import_utils39.AST_NODE_TYPES.TaggedTemplateExpression) {
6110
+ if (callee.type === import_utils38.AST_NODE_TYPES.TaggedTemplateExpression) {
5824
6111
  return testCallerName2(callee.tag);
5825
6112
  }
5826
6113
  return null;
5827
6114
  }
5828
6115
  function isTestBody2(fn) {
5829
6116
  const call = fn.parent;
5830
- if (call?.type !== import_utils39.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
6117
+ if (call?.type !== import_utils38.AST_NODE_TYPES.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5831
6118
  return false;
5832
6119
  }
5833
6120
  const name = testCallerName2(call.callee);
5834
6121
  return name !== null && TEST_CALLERS2.has(name);
5835
6122
  }
5836
- var no_conditional_in_test_default = import_utils39.ESLintUtils.RuleCreator(
5837
- (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5838
- )({
5839
- name: "no-conditional-in-test",
5840
- meta: {
5841
- type: "problem",
5842
- docs: {
5843
- description: "Disallow conditional logic (if, switch, ternary) in test bodies, which can hide missing assertions or test multiple code paths."
6123
+ function subtreeMatches2(node, predicate, descendIntoFunctions = true) {
6124
+ let found = false;
6125
+ const visit = (current) => {
6126
+ if (found) {
6127
+ return;
6128
+ }
6129
+ if (predicate(current)) {
6130
+ found = true;
6131
+ return;
6132
+ }
6133
+ for (const key of Object.keys(current)) {
6134
+ if (key === "parent") {
6135
+ continue;
6136
+ }
6137
+ if (!descendIntoFunctions && FUNCTION_TYPES4.has(current.type) && key === "body") {
6138
+ continue;
6139
+ }
6140
+ const value = current[key];
6141
+ if (Array.isArray(value)) {
6142
+ for (const child of value) {
6143
+ if (typeof child === "object" && child !== null && typeof child.type === "string") {
6144
+ visit(child);
6145
+ }
6146
+ }
6147
+ } else if (typeof value === "object" && value !== null && typeof value.type === "string") {
6148
+ visit(value);
6149
+ }
6150
+ if (found) {
6151
+ return;
6152
+ }
6153
+ }
6154
+ };
6155
+ visit(node);
6156
+ return found;
6157
+ }
6158
+ function rootIdentifier(node) {
6159
+ switch (node.type) {
6160
+ case import_utils38.AST_NODE_TYPES.Identifier:
6161
+ return node.name;
6162
+ case import_utils38.AST_NODE_TYPES.MemberExpression:
6163
+ return rootIdentifier(node.object);
6164
+ case import_utils38.AST_NODE_TYPES.UnaryExpression:
6165
+ return rootIdentifier(node.argument);
6166
+ case import_utils38.AST_NODE_TYPES.AwaitExpression:
6167
+ return rootIdentifier(node.argument);
6168
+ case import_utils38.AST_NODE_TYPES.ChainExpression:
6169
+ case import_utils38.AST_NODE_TYPES.TSNonNullExpression:
6170
+ case import_utils38.AST_NODE_TYPES.TSAsExpression:
6171
+ return rootIdentifier(node.expression);
6172
+ case import_utils38.AST_NODE_TYPES.BinaryExpression:
6173
+ case import_utils38.AST_NODE_TYPES.LogicalExpression:
6174
+ return rootIdentifier(node.left);
6175
+ case import_utils38.AST_NODE_TYPES.CallExpression:
6176
+ return rootIdentifier(node.callee);
6177
+ default:
6178
+ return null;
6179
+ }
6180
+ }
6181
+ function calleeRootName(call) {
6182
+ let current = call.callee;
6183
+ for (; ; ) {
6184
+ if (current.type === import_utils38.AST_NODE_TYPES.Identifier) {
6185
+ return current.name;
6186
+ }
6187
+ if (current.type === import_utils38.AST_NODE_TYPES.MemberExpression) {
6188
+ current = current.object;
6189
+ continue;
6190
+ }
6191
+ if (current.type === import_utils38.AST_NODE_TYPES.CallExpression) {
6192
+ current = current.callee;
6193
+ continue;
6194
+ }
6195
+ if (current.type === import_utils38.AST_NODE_TYPES.ChainExpression || current.type === import_utils38.AST_NODE_TYPES.TSNonNullExpression) {
6196
+ current = current.expression;
6197
+ continue;
6198
+ }
6199
+ return null;
6200
+ }
6201
+ }
6202
+ var isAssertionCall = (node) => node.type === import_utils38.AST_NODE_TYPES.CallExpression && ASSERTION_ROOTS.has(calleeRootName(node) ?? "");
6203
+ var isTypeAssertionCall = (node) => node.type === import_utils38.AST_NODE_TYPES.CallExpression && TYPE_ASSERTION_ROOTS.has(calleeRootName(node) ?? "");
6204
+ var containsAssertion = (node) => subtreeMatches2(node, isAssertionCall);
6205
+ var containsSkipCall = (node) => subtreeMatches2(
6206
+ node,
6207
+ (current) => current.type === import_utils38.AST_NODE_TYPES.CallExpression && current.callee.type === import_utils38.AST_NODE_TYPES.MemberExpression && !current.callee.computed && current.callee.property.type === import_utils38.AST_NODE_TYPES.Identifier && current.callee.property.name === "skip"
6208
+ );
6209
+ var containsEscape = (node) => subtreeMatches2(
6210
+ node,
6211
+ (current) => current.type === import_utils38.AST_NODE_TYPES.ReturnStatement || current.type === import_utils38.AST_NODE_TYPES.ContinueStatement || current.type === import_utils38.AST_NODE_TYPES.BreakStatement,
6212
+ false
6213
+ );
6214
+ function branchStatements(branch) {
6215
+ return branch.type === import_utils38.AST_NODE_TYPES.BlockStatement ? branch.body : [branch];
6216
+ }
6217
+ function previousSibling(node) {
6218
+ const parent = node.parent;
6219
+ let siblings = null;
6220
+ if (parent.type === import_utils38.AST_NODE_TYPES.BlockStatement || parent.type === import_utils38.AST_NODE_TYPES.Program || parent.type === import_utils38.AST_NODE_TYPES.StaticBlock) {
6221
+ siblings = parent.body;
6222
+ } else if (parent.type === import_utils38.AST_NODE_TYPES.SwitchCase) {
6223
+ siblings = parent.consequent;
6224
+ }
6225
+ if (siblings === null) {
6226
+ return null;
6227
+ }
6228
+ const index = siblings.indexOf(node);
6229
+ return index > 0 ? siblings[index - 1] ?? null : null;
6230
+ }
6231
+ function isPinnedNarrowingGuard(node) {
6232
+ const testRoot = rootIdentifier(node.test);
6233
+ if (testRoot === null) {
6234
+ return false;
6235
+ }
6236
+ const previous = previousSibling(node);
6237
+ if (previous === null || previous.type !== import_utils38.AST_NODE_TYPES.ExpressionStatement) {
6238
+ return false;
6239
+ }
6240
+ let matched = false;
6241
+ subtreeMatches2(previous, (current) => {
6242
+ if (current.type !== import_utils38.AST_NODE_TYPES.CallExpression || current.callee.type !== import_utils38.AST_NODE_TYPES.Identifier || current.callee.name !== "expect") {
6243
+ return false;
6244
+ }
6245
+ const subject = current.arguments[0];
6246
+ if (subject === void 0) {
6247
+ return false;
6248
+ }
6249
+ if (rootIdentifier(subject) === testRoot) {
6250
+ matched = true;
6251
+ return true;
6252
+ }
6253
+ return false;
6254
+ });
6255
+ return matched;
6256
+ }
6257
+ function isThrowingGuard(node) {
6258
+ if (node.alternate !== null) {
6259
+ return false;
6260
+ }
6261
+ const statements = branchStatements(node.consequent);
6262
+ return statements.length === 1 && statements[0]?.type === import_utils38.AST_NODE_TYPES.ThrowStatement;
6263
+ }
6264
+ function isTypeAssertionBranch(branch) {
6265
+ const statements = branchStatements(branch);
6266
+ return statements.length > 0 && statements.every(
6267
+ (statement) => statement.type === import_utils38.AST_NODE_TYPES.ExpressionStatement && isTypeAssertionCall(statement.expression)
6268
+ );
6269
+ }
6270
+ function isTypeLevelNarrowing(node) {
6271
+ return isTypeAssertionBranch(node.consequent) && (node.alternate === null || isTypeAssertionBranch(node.alternate));
6272
+ }
6273
+ var isInertBranch = (branch) => !containsAssertion(branch) && !containsEscape(branch) && !containsSkipCall(branch);
6274
+ function isInertNormalization(node) {
6275
+ return isInertBranch(node.consequent) && (node.alternate === null || isInertBranch(node.alternate));
6276
+ }
6277
+ function isExemptIfStatement(node) {
6278
+ return isPinnedNarrowingGuard(node) || isThrowingGuard(node) || isTypeLevelNarrowing(node) || isInertNormalization(node);
6279
+ }
6280
+ function isShortCircuitedAssertion(node) {
6281
+ return node.operator !== "??" && node.parent.type === import_utils38.AST_NODE_TYPES.ExpressionStatement && containsAssertion(node.right);
6282
+ }
6283
+ var no_conditional_in_test_default = import_utils38.ESLintUtils.RuleCreator(
6284
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6285
+ )({
6286
+ name: "no-conditional-in-test",
6287
+ meta: {
6288
+ type: "problem",
6289
+ docs: {
6290
+ description: "Disallow conditional logic (if, switch, ternary) in test bodies, which can hide missing assertions or test multiple code paths."
5844
6291
  },
5845
6292
  schema: [],
5846
6293
  messages: {
@@ -5861,6 +6308,9 @@ var no_conditional_in_test_default = import_utils39.ESLintUtils.RuleCreator(
5861
6308
  };
5862
6309
  return {
5863
6310
  IfStatement(node) {
6311
+ if (isExemptIfStatement(node)) {
6312
+ return;
6313
+ }
5864
6314
  report(node);
5865
6315
  },
5866
6316
  SwitchStatement(node) {
@@ -5870,6 +6320,9 @@ var no_conditional_in_test_default = import_utils39.ESLintUtils.RuleCreator(
5870
6320
  report(node);
5871
6321
  },
5872
6322
  LogicalExpression(node) {
6323
+ if (!isShortCircuitedAssertion(node)) {
6324
+ return;
6325
+ }
5873
6326
  report(node);
5874
6327
  }
5875
6328
  };
@@ -5877,7 +6330,7 @@ var no_conditional_in_test_default = import_utils39.ESLintUtils.RuleCreator(
5877
6330
  });
5878
6331
 
5879
6332
  // src/rules/prefer-constant-time-secret-compare.ts
5880
- var import_utils40 = require("@typescript-eslint/utils");
6333
+ var import_utils39 = require("@typescript-eslint/utils");
5881
6334
  var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["===", "!==", "==", "!="]);
5882
6335
  var SENTINEL_IDENTIFIERS = /* @__PURE__ */ new Set(["undefined", "NaN"]);
5883
6336
  var SENTINEL_WORDS = /(^|_)(SENTINEL|EMPTY|NONE|NULL|UNSET|MISSING|PLACEHOLDER|DUMMY|FAKE|EXAMPLE)(_|$)/;
@@ -5890,36 +6343,36 @@ function isConstantReference(identifier) {
5890
6343
  }
5891
6344
  function isExcludedOperand(node) {
5892
6345
  switch (node.type) {
5893
- case import_utils40.AST_NODE_TYPES.Literal:
6346
+ case import_utils39.AST_NODE_TYPES.Literal:
5894
6347
  return true;
5895
- case import_utils40.AST_NODE_TYPES.TemplateLiteral:
6348
+ case import_utils39.AST_NODE_TYPES.TemplateLiteral:
5896
6349
  return node.expressions.length === 0;
5897
- case import_utils40.AST_NODE_TYPES.Identifier:
6350
+ case import_utils39.AST_NODE_TYPES.Identifier:
5898
6351
  return SENTINEL_IDENTIFIERS.has(node.name) || SENTINEL_PREFIX_RE.test(node.name) || isConstantReference(node.name);
5899
- case import_utils40.AST_NODE_TYPES.MemberExpression:
5900
- return !node.computed && node.property.type === import_utils40.AST_NODE_TYPES.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
6352
+ case import_utils39.AST_NODE_TYPES.MemberExpression:
6353
+ return !node.computed && node.property.type === import_utils39.AST_NODE_TYPES.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
5901
6354
  default:
5902
6355
  return false;
5903
6356
  }
5904
6357
  }
5905
6358
  function operandName(node) {
5906
- if (node.type === import_utils40.AST_NODE_TYPES.Identifier) {
6359
+ if (node.type === import_utils39.AST_NODE_TYPES.Identifier) {
5907
6360
  return node.name;
5908
6361
  }
5909
- if (node.type === import_utils40.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === import_utils40.AST_NODE_TYPES.Identifier) {
6362
+ if (node.type === import_utils39.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === import_utils39.AST_NODE_TYPES.Identifier) {
5910
6363
  return node.property.name;
5911
6364
  }
5912
6365
  return null;
5913
6366
  }
5914
6367
  function isSecretOperand(node) {
5915
- if (node.type === import_utils40.AST_NODE_TYPES.TemplateLiteral) {
6368
+ if (node.type === import_utils39.AST_NODE_TYPES.TemplateLiteral) {
5916
6369
  return node.expressions.some((expression) => isSecretOperand(expression));
5917
6370
  }
5918
6371
  const name = operandName(node);
5919
6372
  return name !== null && isAuthSecretName(name);
5920
6373
  }
5921
6374
  function secretNameOf(node) {
5922
- if (node.type === import_utils40.AST_NODE_TYPES.TemplateLiteral) {
6375
+ if (node.type === import_utils39.AST_NODE_TYPES.TemplateLiteral) {
5923
6376
  for (const expression of node.expressions) {
5924
6377
  const nested = secretNameOf(expression);
5925
6378
  if (nested !== null) {
@@ -5930,7 +6383,7 @@ function secretNameOf(node) {
5930
6383
  }
5931
6384
  return operandName(node);
5932
6385
  }
5933
- var prefer_constant_time_secret_compare_default = import_utils40.ESLintUtils.RuleCreator(
6386
+ var prefer_constant_time_secret_compare_default = import_utils39.ESLintUtils.RuleCreator(
5934
6387
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5935
6388
  )({
5936
6389
  name: "prefer-constant-time-secret-compare",
@@ -5973,11 +6426,11 @@ var prefer_constant_time_secret_compare_default = import_utils40.ESLintUtils.Rul
5973
6426
  });
5974
6427
 
5975
6428
  // src/rules/store-insert-requires-on-conflict.ts
5976
- var import_utils41 = require("@typescript-eslint/utils");
6429
+ var import_utils40 = require("@typescript-eslint/utils");
5977
6430
  var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
5978
6431
  var CONFLICT_HANDLED = /\bON\s+CONFLICT\b|\bON\s+DUPLICATE\s+KEY\b|\bINSERT\s+OR\s+(?:IGNORE|REPLACE)\b/i;
5979
6432
  var INSERT_GATE = /insert/i;
5980
- var store_insert_requires_on_conflict_default = import_utils41.ESLintUtils.RuleCreator(
6433
+ var store_insert_requires_on_conflict_default = import_utils40.ESLintUtils.RuleCreator(
5981
6434
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5982
6435
  )({
5983
6436
  name: "store-insert-requires-on-conflict",
@@ -6006,17 +6459,17 @@ var store_insert_requires_on_conflict_default = import_utils41.ESLintUtils.RuleC
6006
6459
  });
6007
6460
 
6008
6461
  // src/rules/no-dynamic-sql.ts
6009
- var import_utils42 = require("@typescript-eslint/utils");
6462
+ var import_utils41 = require("@typescript-eslint/utils");
6010
6463
  var DEFAULT_METHODS = ["prepare", "exec", "query"];
6011
6464
  var CONSTANT_CASE_RE = /^[A-Z][A-Z0-9_]*$/;
6012
6465
  function isStaticFragment(expression) {
6013
- if (expression.type === import_utils42.AST_NODE_TYPES.Identifier) {
6466
+ if (expression.type === import_utils41.AST_NODE_TYPES.Identifier) {
6014
6467
  return CONSTANT_CASE_RE.test(expression.name);
6015
6468
  }
6016
- if (expression.type === import_utils42.AST_NODE_TYPES.MemberExpression && !expression.computed && expression.property.type === import_utils42.AST_NODE_TYPES.Identifier) {
6469
+ if (expression.type === import_utils41.AST_NODE_TYPES.MemberExpression && !expression.computed && expression.property.type === import_utils41.AST_NODE_TYPES.Identifier) {
6017
6470
  return CONSTANT_CASE_RE.test(expression.property.name);
6018
6471
  }
6019
- if (expression.type === import_utils42.AST_NODE_TYPES.Literal) {
6472
+ if (expression.type === import_utils41.AST_NODE_TYPES.Literal) {
6020
6473
  return typeof expression.value === "string";
6021
6474
  }
6022
6475
  return false;
@@ -6027,36 +6480,36 @@ function runtimeInterpolations(template) {
6027
6480
  );
6028
6481
  }
6029
6482
  function concatOperands(node) {
6030
- if (node.type === import_utils42.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
6483
+ if (node.type === import_utils41.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
6031
6484
  return [...concatOperands(node.left), ...concatOperands(node.right)];
6032
6485
  }
6033
6486
  return [node];
6034
6487
  }
6035
6488
  function runtimeConcatOperands(node) {
6036
- if (node.type !== import_utils42.AST_NODE_TYPES.BinaryExpression || node.operator !== "+") {
6489
+ if (node.type !== import_utils41.AST_NODE_TYPES.BinaryExpression || node.operator !== "+") {
6037
6490
  return [];
6038
6491
  }
6039
6492
  const operands = concatOperands(node);
6040
6493
  const hasStringLiteral = operands.some(
6041
- (operand) => operand.type === import_utils42.AST_NODE_TYPES.Literal && typeof operand.value === "string"
6494
+ (operand) => operand.type === import_utils41.AST_NODE_TYPES.Literal && typeof operand.value === "string"
6042
6495
  );
6043
6496
  if (!hasStringLiteral) {
6044
6497
  return [];
6045
6498
  }
6046
6499
  return operands.filter(
6047
- (operand) => operand.type !== import_utils42.AST_NODE_TYPES.Literal && !isStaticFragment(operand)
6500
+ (operand) => operand.type !== import_utils41.AST_NODE_TYPES.Literal && !isStaticFragment(operand)
6048
6501
  );
6049
6502
  }
6050
6503
  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;
6051
6504
  var RUNTIME_MARKER = " ? ";
6052
6505
  function staticStatementText(node) {
6053
- if (node.type === import_utils42.AST_NODE_TYPES.TemplateLiteral) {
6506
+ if (node.type === import_utils41.AST_NODE_TYPES.TemplateLiteral) {
6054
6507
  return node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join(RUNTIME_MARKER);
6055
6508
  }
6056
- if (node.type === import_utils42.AST_NODE_TYPES.Literal) {
6509
+ if (node.type === import_utils41.AST_NODE_TYPES.Literal) {
6057
6510
  return typeof node.value === "string" ? node.value : RUNTIME_MARKER;
6058
6511
  }
6059
- if (node.type === import_utils42.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
6512
+ if (node.type === import_utils41.AST_NODE_TYPES.BinaryExpression && node.operator === "+") {
6060
6513
  return staticStatementText(node.left) + staticStatementText(node.right);
6061
6514
  }
6062
6515
  return RUNTIME_MARKER;
@@ -6066,13 +6519,13 @@ function looksLikeSql(node) {
6066
6519
  }
6067
6520
  function statementMethodName(node, methods) {
6068
6521
  const callee = node.callee;
6069
- if (callee.type !== import_utils42.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils42.AST_NODE_TYPES.Identifier) {
6522
+ if (callee.type !== import_utils41.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils41.AST_NODE_TYPES.Identifier) {
6070
6523
  return null;
6071
6524
  }
6072
6525
  const name = callee.property.name;
6073
6526
  return methods.has(name) ? name : null;
6074
6527
  }
6075
- var no_dynamic_sql_default = import_utils42.ESLintUtils.RuleCreator(
6528
+ var no_dynamic_sql_default = import_utils41.ESLintUtils.RuleCreator(
6076
6529
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6077
6530
  )({
6078
6531
  name: "no-dynamic-sql",
@@ -6111,7 +6564,7 @@ var no_dynamic_sql_default = import_utils42.ESLintUtils.RuleCreator(
6111
6564
  if (statement === void 0 || !looksLikeSql(statement)) {
6112
6565
  return;
6113
6566
  }
6114
- const offenders = statement.type === import_utils42.AST_NODE_TYPES.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6567
+ const offenders = statement.type === import_utils41.AST_NODE_TYPES.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6115
6568
  for (const offender of offenders) {
6116
6569
  context.report({
6117
6570
  node: offender,
@@ -6125,7 +6578,7 @@ var no_dynamic_sql_default = import_utils42.ESLintUtils.RuleCreator(
6125
6578
  });
6126
6579
 
6127
6580
  // src/rules/no-raw-fetch-outside-clients.ts
6128
- var import_utils43 = require("@typescript-eslint/utils");
6581
+ var import_utils42 = require("@typescript-eslint/utils");
6129
6582
  var DEFAULT_ALLOW = [
6130
6583
  "[\\\\/]clients?[\\\\/]",
6131
6584
  "-client\\.[cm]?[jt]sx?$",
@@ -6135,17 +6588,15 @@ var DEFAULT_ALLOW = [
6135
6588
  "[\\\\/]api[\\\\/]",
6136
6589
  "[\\\\/]api\\.[cm]?[jt]sx?$",
6137
6590
  "[-.]api\\.[cm]?[jt]sx?$",
6138
- "\\.test\\.",
6139
- "\\.spec\\.",
6140
- // `*.test-d.ts` type tests, and react-router's `single-fetch-test.ts` spelling.
6141
- "\\.(test|spec)-d\\.[cm]?[jt]sx?$",
6142
- "-(test|spec)\\.[cm]?[jt]sx?$",
6143
- "[\\\\/]__tests__[\\\\/]",
6144
- "[\\\\/]__mocks__[\\\\/]",
6145
- "[\\\\/]tests?[\\\\/]",
6146
- // jscodeshift input/output fixtures — text a codemod transforms, not code.
6147
- "[\\\\/]__testfixtures__[\\\\/]"
6591
+ // Vendor wrapper conventions: a module that exists to own one third-party
6592
+ // origin's HTTP. See the SECOND SWEEP note in the file header.
6593
+ "[\\\\/]services?[\\\\/]",
6594
+ "[\\\\/](connectors|providers|integrations|adapters|fetchers)[\\\\/]",
6595
+ "[\\\\/]notifications[\\\\/]",
6596
+ "[Ss]ervice\\.[cm]?[jt]sx?$",
6597
+ "-(service|connector|adapter|sdk|fetcher)\\.[cm]?[jt]sx?$"
6148
6598
  ];
6599
+ var NON_PRODUCTION_TREE_RE = /[\\/](playwright|cypress|__testfixtures__)[\\/]/;
6149
6600
  var GLOBAL_RECEIVERS = /* @__PURE__ */ new Set([
6150
6601
  "globalThis",
6151
6602
  "window",
@@ -6171,6 +6622,10 @@ function identifierLikeName(node) {
6171
6622
  }
6172
6623
  return null;
6173
6624
  }
6625
+ function isConstructedArgumentHandoff(node) {
6626
+ const [first] = node.arguments;
6627
+ return node.arguments.length === 1 && first !== void 0 && first.type === import_utils42.AST_NODE_TYPES.NewExpression;
6628
+ }
6174
6629
  function isPresignedUrlTransfer(node) {
6175
6630
  const first = node.arguments[0];
6176
6631
  if (first === void 0) {
@@ -6189,7 +6644,7 @@ function compile(patterns) {
6189
6644
  }
6190
6645
  return compiled;
6191
6646
  }
6192
- var no_raw_fetch_outside_clients_default = import_utils43.ESLintUtils.RuleCreator(
6647
+ var no_raw_fetch_outside_clients_default = import_utils42.ESLintUtils.RuleCreator(
6193
6648
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6194
6649
  )({
6195
6650
  name: "no-raw-fetch-outside-clients",
@@ -6217,15 +6672,18 @@ var no_raw_fetch_outside_clients_default = import_utils43.ESLintUtils.RuleCreato
6217
6672
  },
6218
6673
  defaultOptions: [{}],
6219
6674
  create(context, [options]) {
6675
+ const filename = context.filename;
6676
+ if (isTestFile(filename) || NON_PRODUCTION_TREE_RE.test(filename)) {
6677
+ return {};
6678
+ }
6220
6679
  const patterns = options?.allow ?? DEFAULT_ALLOW;
6221
6680
  const allowed = compile(patterns);
6222
- const filename = context.filename;
6223
6681
  if (allowed.some((re) => re.test(filename))) {
6224
6682
  return {};
6225
6683
  }
6226
6684
  return {
6227
6685
  CallExpression(node) {
6228
- if (isPresignedUrlTransfer(node)) {
6686
+ if (isPresignedUrlTransfer(node) || isConstructedArgumentHandoff(node)) {
6229
6687
  return;
6230
6688
  }
6231
6689
  if (isGlobalFetchCall(node)) {
@@ -6237,7 +6695,7 @@ var no_raw_fetch_outside_clients_default = import_utils43.ESLintUtils.RuleCreato
6237
6695
  });
6238
6696
 
6239
6697
  // src/rules/no-storage-in-stateless-modules.ts
6240
- var import_utils44 = require("@typescript-eslint/utils");
6698
+ var import_utils43 = require("@typescript-eslint/utils");
6241
6699
  var DEFAULT_METHODS2 = [
6242
6700
  "prepare",
6243
6701
  "put",
@@ -6256,7 +6714,7 @@ function compile2(patterns) {
6256
6714
  }
6257
6715
  function storageMethodName(node, methods) {
6258
6716
  const callee = node.callee;
6259
- if (callee.type !== import_utils44.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils44.AST_NODE_TYPES.Identifier) {
6717
+ if (callee.type !== import_utils43.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils43.AST_NODE_TYPES.Identifier) {
6260
6718
  return null;
6261
6719
  }
6262
6720
  const name = callee.property.name;
@@ -6268,7 +6726,7 @@ function storageMethodName(node, methods) {
6268
6726
  }
6269
6727
  return name;
6270
6728
  }
6271
- var no_storage_in_stateless_modules_default = import_utils44.ESLintUtils.RuleCreator(
6729
+ var no_storage_in_stateless_modules_default = import_utils43.ESLintUtils.RuleCreator(
6272
6730
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6273
6731
  )({
6274
6732
  name: "no-storage-in-stateless-modules",
@@ -6326,7 +6784,7 @@ var no_storage_in_stateless_modules_default = import_utils44.ESLintUtils.RuleCre
6326
6784
  });
6327
6785
 
6328
6786
  // src/rules/no-zod-native-enum.ts
6329
- var import_utils45 = require("@typescript-eslint/utils");
6787
+ var import_utils44 = require("@typescript-eslint/utils");
6330
6788
  var ts2 = __toESM(require("typescript"), 1);
6331
6789
  var IGNORE_PATTERNS2 = [
6332
6790
  /[\\/]generated[\\/]/,
@@ -6344,7 +6802,7 @@ function isZodModule2(source) {
6344
6802
  return /(^|[/@-])zod([/-]|$)/.test(source);
6345
6803
  }
6346
6804
  function unwrap3(node) {
6347
- if (node.type === import_utils45.AST_NODE_TYPES.TSAsExpression || node.type === import_utils45.AST_NODE_TYPES.TSSatisfiesExpression) {
6805
+ if (node.type === import_utils44.AST_NODE_TYPES.TSAsExpression || node.type === import_utils44.AST_NODE_TYPES.TSSatisfiesExpression) {
6348
6806
  return unwrap3(node.expression);
6349
6807
  }
6350
6808
  return node;
@@ -6352,14 +6810,14 @@ function unwrap3(node) {
6352
6810
  function stringValueTexts(node, sourceCode) {
6353
6811
  const texts = [];
6354
6812
  for (const prop of node.properties) {
6355
- if (prop.type !== import_utils45.AST_NODE_TYPES.Property) {
6813
+ if (prop.type !== import_utils44.AST_NODE_TYPES.Property) {
6356
6814
  return null;
6357
6815
  }
6358
6816
  if (prop.computed || prop.shorthand || prop.method || prop.kind !== "init") {
6359
6817
  return null;
6360
6818
  }
6361
6819
  const value = prop.value;
6362
- if (value.type !== import_utils45.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
6820
+ if (value.type !== import_utils44.AST_NODE_TYPES.Literal || typeof value.value !== "string") {
6363
6821
  return null;
6364
6822
  }
6365
6823
  const text = sourceCode.getText(value);
@@ -6375,7 +6833,7 @@ function resolvesToLocalEnum(node, scope) {
6375
6833
  const variable = current.variables.find((v) => v.name === node.name);
6376
6834
  if (variable !== void 0) {
6377
6835
  return variable.defs.some(
6378
- (def) => def.node.type === import_utils45.AST_NODE_TYPES.TSEnumDeclaration
6836
+ (def) => def.node.type === import_utils44.AST_NODE_TYPES.TSEnumDeclaration
6379
6837
  );
6380
6838
  }
6381
6839
  current = current.upper;
@@ -6395,7 +6853,7 @@ function resolvesToImportedEnum(node, services) {
6395
6853
  }
6396
6854
  return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
6397
6855
  }
6398
- var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6856
+ var no_zod_native_enum_default = import_utils44.ESLintUtils.RuleCreator(
6399
6857
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6400
6858
  )({
6401
6859
  name: "no-zod-native-enum",
@@ -6422,32 +6880,32 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6422
6880
  }
6423
6881
  let services;
6424
6882
  try {
6425
- services = import_utils45.ESLintUtils.getParserServices(context);
6883
+ services = import_utils44.ESLintUtils.getParserServices(context);
6426
6884
  } catch {
6427
6885
  services = null;
6428
6886
  }
6429
6887
  const zodImportedNames = /* @__PURE__ */ new Map();
6430
6888
  function isZodMemberCall(node, api) {
6431
6889
  const callee = node.callee;
6432
- if (callee.type === import_utils45.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils45.AST_NODE_TYPES.Identifier) {
6890
+ if (callee.type === import_utils44.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils44.AST_NODE_TYPES.Identifier) {
6433
6891
  return callee.property.name === api;
6434
6892
  }
6435
- if (callee.type === import_utils45.AST_NODE_TYPES.Identifier) {
6893
+ if (callee.type === import_utils44.AST_NODE_TYPES.Identifier) {
6436
6894
  return zodImportedNames.get(callee.name) === api;
6437
6895
  }
6438
6896
  return false;
6439
6897
  }
6440
6898
  function buildFix(node) {
6441
6899
  const callee = node.callee;
6442
- if (callee.type !== import_utils45.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils45.AST_NODE_TYPES.Identifier) {
6900
+ if (callee.type !== import_utils44.AST_NODE_TYPES.MemberExpression || callee.property.type !== import_utils44.AST_NODE_TYPES.Identifier) {
6443
6901
  return null;
6444
6902
  }
6445
6903
  const arg = node.arguments[0];
6446
- if (arg === void 0 || node.arguments.length !== 1 || arg.type === import_utils45.AST_NODE_TYPES.SpreadElement) {
6904
+ if (arg === void 0 || node.arguments.length !== 1 || arg.type === import_utils44.AST_NODE_TYPES.SpreadElement) {
6447
6905
  return null;
6448
6906
  }
6449
6907
  const inner = unwrap3(arg);
6450
- if (inner.type !== import_utils45.AST_NODE_TYPES.ObjectExpression) {
6908
+ if (inner.type !== import_utils44.AST_NODE_TYPES.ObjectExpression) {
6451
6909
  return null;
6452
6910
  }
6453
6911
  const values = stringValueTexts(inner, sourceCode);
@@ -6467,7 +6925,7 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6467
6925
  return;
6468
6926
  }
6469
6927
  for (const spec of node.specifiers) {
6470
- if (spec.type === import_utils45.AST_NODE_TYPES.ImportSpecifier && spec.imported.type === import_utils45.AST_NODE_TYPES.Identifier) {
6928
+ if (spec.type === import_utils44.AST_NODE_TYPES.ImportSpecifier && spec.imported.type === import_utils44.AST_NODE_TYPES.Identifier) {
6471
6929
  zodImportedNames.set(spec.local.name, spec.imported.name);
6472
6930
  }
6473
6931
  }
@@ -6486,7 +6944,7 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6486
6944
  return;
6487
6945
  }
6488
6946
  const arg = node.arguments[0];
6489
- if (arg === void 0 || arg.type !== import_utils45.AST_NODE_TYPES.Identifier) {
6947
+ if (arg === void 0 || arg.type !== import_utils44.AST_NODE_TYPES.Identifier) {
6490
6948
  return;
6491
6949
  }
6492
6950
  const isEnum = resolvesToLocalEnum(arg, sourceCode.getScope(arg)) || services !== null && resolvesToImportedEnum(arg, services);
@@ -6503,7 +6961,7 @@ var no_zod_native_enum_default = import_utils45.ESLintUtils.RuleCreator(
6503
6961
  });
6504
6962
 
6505
6963
  // src/rules/prefer-module-level-constant.ts
6506
- var import_utils46 = require("@typescript-eslint/utils");
6964
+ var import_utils45 = require("@typescript-eslint/utils");
6507
6965
  var DEFAULT_MIN_ELEMENTS = 3;
6508
6966
  var MAX_LITERAL_DEPTH = 4;
6509
6967
  var IGNORE_PATTERNS3 = [
@@ -6512,13 +6970,6 @@ var IGNORE_PATTERNS3 = [
6512
6970
  /\.generated\.tsx?$/,
6513
6971
  /\.d\.ts$/
6514
6972
  ];
6515
- var TEST_FILE_PATTERNS = [
6516
- /\.(?:test|spec)\.[cm]?[jt]sx?$/,
6517
- /[\\/]__tests__[\\/]/,
6518
- /[\\/]__mocks__[\\/]/,
6519
- /[\\/]tests?[\\/]/,
6520
- /\.stories\.[cm]?[jt]sx?$/
6521
- ];
6522
6973
  var MUTATING_METHODS = /* @__PURE__ */ new Set([
6523
6974
  // Array
6524
6975
  "push",
@@ -6538,10 +6989,10 @@ var MUTATING_METHODS = /* @__PURE__ */ new Set([
6538
6989
  // Object-ish escape hatches
6539
6990
  "assign"
6540
6991
  ]);
6541
- var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6542
- import_utils46.AST_NODE_TYPES.FunctionDeclaration,
6543
- import_utils46.AST_NODE_TYPES.FunctionExpression,
6544
- import_utils46.AST_NODE_TYPES.ArrowFunctionExpression
6992
+ var FUNCTION_TYPES5 = /* @__PURE__ */ new Set([
6993
+ import_utils45.AST_NODE_TYPES.FunctionDeclaration,
6994
+ import_utils45.AST_NODE_TYPES.FunctionExpression,
6995
+ import_utils45.AST_NODE_TYPES.ArrowFunctionExpression
6545
6996
  ]);
6546
6997
  var COLLECTION_CONSTRUCTORS = /* @__PURE__ */ new Set(["Set", "Map"]);
6547
6998
  function isIgnoredFile3(filename, sourceText) {
@@ -6550,17 +7001,18 @@ function isIgnoredFile3(filename, sourceText) {
6550
7001
  }
6551
7002
  return /@generated\b/.test(sourceText.slice(0, 1024));
6552
7003
  }
6553
- function isTestFile2(filename) {
6554
- return TEST_FILE_PATTERNS.some((re) => re.test(filename));
7004
+ function isLocalFixtureFile(filename) {
7005
+ return isTestFile(filename) || isStoryFile(filename);
6555
7006
  }
6556
7007
  function unwrap4(node) {
6557
- 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) {
7008
+ if (node.type === import_utils45.AST_NODE_TYPES.TSAsExpression || node.type === import_utils45.AST_NODE_TYPES.TSSatisfiesExpression || node.type === import_utils45.AST_NODE_TYPES.TSNonNullExpression) {
6558
7009
  return unwrap4(node.expression);
6559
7010
  }
6560
7011
  return node;
6561
7012
  }
7013
+ var HAS_STATEFUL_FLAG_RE = /[gy]/;
6562
7014
  function isRegexLiteral(node) {
6563
- return node.type === import_utils46.AST_NODE_TYPES.Literal && "regex" in node && node.regex !== void 0;
7015
+ return node.type === import_utils45.AST_NODE_TYPES.Literal && "regex" in node && node.regex !== void 0;
6564
7016
  }
6565
7017
  function isLiteralOnly(node, depth) {
6566
7018
  if (depth > MAX_LITERAL_DEPTH) {
@@ -6568,29 +7020,29 @@ function isLiteralOnly(node, depth) {
6568
7020
  }
6569
7021
  const inner = unwrap4(node);
6570
7022
  switch (inner.type) {
6571
- case import_utils46.AST_NODE_TYPES.Literal: {
6572
- return true;
7023
+ case import_utils45.AST_NODE_TYPES.Literal: {
7024
+ return !(isRegexLiteral(inner) && HAS_STATEFUL_FLAG_RE.test(inner.regex.flags));
6573
7025
  }
6574
- case import_utils46.AST_NODE_TYPES.TemplateLiteral: {
7026
+ case import_utils45.AST_NODE_TYPES.TemplateLiteral: {
6575
7027
  return inner.expressions.length === 0;
6576
7028
  }
6577
- case import_utils46.AST_NODE_TYPES.UnaryExpression: {
6578
- return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === import_utils46.AST_NODE_TYPES.Literal && typeof inner.argument.value === "number";
7029
+ case import_utils45.AST_NODE_TYPES.UnaryExpression: {
7030
+ return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === import_utils45.AST_NODE_TYPES.Literal && typeof inner.argument.value === "number";
6579
7031
  }
6580
- case import_utils46.AST_NODE_TYPES.ArrayExpression: {
7032
+ case import_utils45.AST_NODE_TYPES.ArrayExpression: {
6581
7033
  return inner.elements.every(
6582
- (el) => el !== null && el.type !== import_utils46.AST_NODE_TYPES.SpreadElement && isLiteralOnly(el, depth + 1)
7034
+ (el) => el !== null && el.type !== import_utils45.AST_NODE_TYPES.SpreadElement && isLiteralOnly(el, depth + 1)
6583
7035
  );
6584
7036
  }
6585
- case import_utils46.AST_NODE_TYPES.ObjectExpression: {
7037
+ case import_utils45.AST_NODE_TYPES.ObjectExpression: {
6586
7038
  return inner.properties.every((prop) => {
6587
- if (prop.type !== import_utils46.AST_NODE_TYPES.Property) {
7039
+ if (prop.type !== import_utils45.AST_NODE_TYPES.Property) {
6588
7040
  return false;
6589
7041
  }
6590
7042
  if (prop.shorthand || prop.method || prop.kind !== "init") {
6591
7043
  return false;
6592
7044
  }
6593
- if (prop.computed && prop.key.type !== import_utils46.AST_NODE_TYPES.Literal) {
7045
+ if (prop.computed && prop.key.type !== import_utils45.AST_NODE_TYPES.Literal) {
6594
7046
  return false;
6595
7047
  }
6596
7048
  return isLiteralOnly(prop.value, depth + 1);
@@ -6603,7 +7055,7 @@ function isLiteralOnly(node, depth) {
6603
7055
  }
6604
7056
  function unwrapObjectFreeze(node) {
6605
7057
  const inner = unwrap4(node);
6606
- 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) {
7058
+ if (inner.type === import_utils45.AST_NODE_TYPES.CallExpression && inner.callee.type === import_utils45.AST_NODE_TYPES.MemberExpression && !inner.callee.computed && inner.callee.object.type === import_utils45.AST_NODE_TYPES.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === import_utils45.AST_NODE_TYPES.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== import_utils45.AST_NODE_TYPES.SpreadElement) {
6607
7059
  return unwrap4(inner.arguments[0]);
6608
7060
  }
6609
7061
  return inner;
@@ -6614,24 +7066,24 @@ function classify(init, checkRegex) {
6614
7066
  if (!checkRegex) {
6615
7067
  return null;
6616
7068
  }
6617
- if (/[gy]/.test(node.regex.flags)) {
7069
+ if (HAS_STATEFUL_FLAG_RE.test(node.regex.flags)) {
6618
7070
  return null;
6619
7071
  }
6620
7072
  return { kind: "regex", size: 1 };
6621
7073
  }
6622
- if (node.type === import_utils46.AST_NODE_TYPES.ArrayExpression) {
7074
+ if (node.type === import_utils45.AST_NODE_TYPES.ArrayExpression) {
6623
7075
  return isLiteralOnly(node, 0) ? { kind: "array", size: node.elements.length } : null;
6624
7076
  }
6625
- if (node.type === import_utils46.AST_NODE_TYPES.ObjectExpression) {
7077
+ if (node.type === import_utils45.AST_NODE_TYPES.ObjectExpression) {
6626
7078
  return isLiteralOnly(node, 0) ? { kind: "object", size: node.properties.length } : null;
6627
7079
  }
6628
- if (node.type === import_utils46.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils46.AST_NODE_TYPES.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
7080
+ if (node.type === import_utils45.AST_NODE_TYPES.NewExpression && node.callee.type === import_utils45.AST_NODE_TYPES.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6629
7081
  const arg = node.arguments[0];
6630
- if (node.arguments.length !== 1 || arg === void 0 || arg.type === import_utils46.AST_NODE_TYPES.SpreadElement) {
7082
+ if (node.arguments.length !== 1 || arg === void 0 || arg.type === import_utils45.AST_NODE_TYPES.SpreadElement) {
6631
7083
  return null;
6632
7084
  }
6633
7085
  const entries = unwrap4(arg);
6634
- if (entries.type !== import_utils46.AST_NODE_TYPES.ArrayExpression) {
7086
+ if (entries.type !== import_utils45.AST_NODE_TYPES.ArrayExpression) {
6635
7087
  return null;
6636
7088
  }
6637
7089
  return isLiteralOnly(entries, 0) ? { kind: node.callee.name === "Set" ? "Set" : "Map", size: entries.elements.length } : null;
@@ -6641,7 +7093,7 @@ function classify(init, checkRegex) {
6641
7093
  function enclosingFunction2(node) {
6642
7094
  let current = node.parent;
6643
7095
  while (current !== void 0 && current !== null) {
6644
- if (FUNCTION_TYPES4.has(current.type)) {
7096
+ if (FUNCTION_TYPES5.has(current.type)) {
6645
7097
  return current;
6646
7098
  }
6647
7099
  current = current.parent;
@@ -6660,10 +7112,10 @@ var NON_RETAINING_BUILTINS = /* @__PURE__ */ new Map(
6660
7112
  );
6661
7113
  function isNonRetainingBuiltinCall(node, argument) {
6662
7114
  const callee = node.callee;
6663
- if (callee.type === import_utils46.AST_NODE_TYPES.Identifier && callee.name === "structuredClone") {
7115
+ if (callee.type === import_utils45.AST_NODE_TYPES.Identifier && callee.name === "structuredClone") {
6664
7116
  return true;
6665
7117
  }
6666
- 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) {
7118
+ if (callee.type !== import_utils45.AST_NODE_TYPES.MemberExpression || callee.computed || callee.object.type !== import_utils45.AST_NODE_TYPES.Identifier || callee.property.type !== import_utils45.AST_NODE_TYPES.Identifier) {
6667
7119
  return false;
6668
7120
  }
6669
7121
  const members = NON_RETAINING_BUILTINS.get(callee.object.name);
@@ -6677,43 +7129,43 @@ function isNonRetainingBuiltinCall(node, argument) {
6677
7129
  }
6678
7130
  function isSafeRead(identifier) {
6679
7131
  const parent = identifier.parent;
6680
- if (parent.type === import_utils46.AST_NODE_TYPES.MemberExpression) {
7132
+ if (parent.type === import_utils45.AST_NODE_TYPES.MemberExpression) {
6681
7133
  if (parent.object !== identifier) {
6682
7134
  return true;
6683
7135
  }
6684
7136
  const grandparent = parent.parent;
6685
- if (grandparent.type === import_utils46.AST_NODE_TYPES.AssignmentExpression && grandparent.left === parent) {
7137
+ if (grandparent.type === import_utils45.AST_NODE_TYPES.AssignmentExpression && grandparent.left === parent) {
6686
7138
  return false;
6687
7139
  }
6688
- if (grandparent.type === import_utils46.AST_NODE_TYPES.UpdateExpression) {
7140
+ if (grandparent.type === import_utils45.AST_NODE_TYPES.UpdateExpression) {
6689
7141
  return false;
6690
7142
  }
6691
- if (grandparent.type === import_utils46.AST_NODE_TYPES.UnaryExpression && grandparent.operator === "delete") {
7143
+ if (grandparent.type === import_utils45.AST_NODE_TYPES.UnaryExpression && grandparent.operator === "delete") {
6692
7144
  return false;
6693
7145
  }
6694
- 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) {
7146
+ if (!parent.computed && parent.property.type === import_utils45.AST_NODE_TYPES.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === import_utils45.AST_NODE_TYPES.CallExpression && grandparent.callee === parent) {
6695
7147
  return false;
6696
7148
  }
6697
7149
  return true;
6698
7150
  }
6699
- if (parent.type === import_utils46.AST_NODE_TYPES.ForOfStatement && parent.right === identifier) {
7151
+ if (parent.type === import_utils45.AST_NODE_TYPES.ForOfStatement && parent.right === identifier) {
6700
7152
  return true;
6701
7153
  }
6702
- if (parent.type === import_utils46.AST_NODE_TYPES.SpreadElement) {
7154
+ if (parent.type === import_utils45.AST_NODE_TYPES.SpreadElement) {
6703
7155
  return true;
6704
7156
  }
6705
- if (parent.type === import_utils46.AST_NODE_TYPES.BinaryExpression) {
7157
+ if (parent.type === import_utils45.AST_NODE_TYPES.BinaryExpression) {
6706
7158
  return true;
6707
7159
  }
6708
- if (parent.type === import_utils46.AST_NODE_TYPES.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
7160
+ if (parent.type === import_utils45.AST_NODE_TYPES.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6709
7161
  return true;
6710
7162
  }
6711
- if (parent.type === import_utils46.AST_NODE_TYPES.UnaryExpression && parent.operator !== "delete") {
7163
+ if (parent.type === import_utils45.AST_NODE_TYPES.UnaryExpression && parent.operator !== "delete") {
6712
7164
  return true;
6713
7165
  }
6714
7166
  return false;
6715
7167
  }
6716
- var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreator(
7168
+ var prefer_module_level_constant_default = import_utils45.ESLintUtils.RuleCreator(
6717
7169
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6718
7170
  )({
6719
7171
  name: "prefer-module-level-constant",
@@ -6749,7 +7201,7 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6749
7201
  if (isIgnoredFile3(filename, sourceCode.getText())) {
6750
7202
  return {};
6751
7203
  }
6752
- if (ignoreTestFiles && isTestFile2(filename)) {
7204
+ if (ignoreTestFiles && isLocalFixtureFile(filename)) {
6753
7205
  return {};
6754
7206
  }
6755
7207
  function allReferencesAreSafeReads(declarator) {
@@ -6765,7 +7217,7 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6765
7217
  if (reference.isWrite()) {
6766
7218
  return false;
6767
7219
  }
6768
- if (reference.identifier.type !== import_utils46.AST_NODE_TYPES.Identifier) {
7220
+ if (reference.identifier.type !== import_utils45.AST_NODE_TYPES.Identifier) {
6769
7221
  return false;
6770
7222
  }
6771
7223
  if (!isSafeRead(reference.identifier)) {
@@ -6777,10 +7229,10 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6777
7229
  return {
6778
7230
  VariableDeclarator(node) {
6779
7231
  const declaration = node.parent;
6780
- if (declaration.type !== import_utils46.AST_NODE_TYPES.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
7232
+ if (declaration.type !== import_utils45.AST_NODE_TYPES.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6781
7233
  return;
6782
7234
  }
6783
- if (node.id.type !== import_utils46.AST_NODE_TYPES.Identifier || node.init === null) {
7235
+ if (node.id.type !== import_utils45.AST_NODE_TYPES.Identifier || node.init === null) {
6784
7236
  return;
6785
7237
  }
6786
7238
  if (enclosingFunction2(node) === null) {
@@ -6807,7 +7259,7 @@ var prefer_module_level_constant_default = import_utils46.ESLintUtils.RuleCreato
6807
7259
  });
6808
7260
 
6809
7261
  // src/rules/jsdoc-restates-signature.ts
6810
- var import_utils47 = require("@typescript-eslint/utils");
7262
+ var import_utils46 = require("@typescript-eslint/utils");
6811
7263
  var VALUE_TAGS = /* @__PURE__ */ new Set([
6812
7264
  "alpha",
6813
7265
  "author",
@@ -6890,30 +7342,30 @@ function declarationNames(node) {
6890
7342
  switch (node.type) {
6891
7343
  // `export function f()` — the JSDoc sits above the `export`, so the token
6892
7344
  // after it resolves to the wrapper, not to the thing being documented.
6893
- case import_utils47.AST_NODE_TYPES.ExportNamedDeclaration:
6894
- case import_utils47.AST_NODE_TYPES.ExportDefaultDeclaration:
7345
+ case import_utils46.AST_NODE_TYPES.ExportNamedDeclaration:
7346
+ case import_utils46.AST_NODE_TYPES.ExportDefaultDeclaration:
6895
7347
  return node.declaration == null ? null : declarationNames(node.declaration);
6896
- case import_utils47.AST_NODE_TYPES.FunctionDeclaration:
6897
- case import_utils47.AST_NODE_TYPES.TSDeclareFunction:
7348
+ case import_utils46.AST_NODE_TYPES.FunctionDeclaration:
7349
+ case import_utils46.AST_NODE_TYPES.TSDeclareFunction:
6898
7350
  return node.id === null ? null : { name: node.id.name, params: paramNames(node.params) };
6899
- case import_utils47.AST_NODE_TYPES.ClassDeclaration:
6900
- case import_utils47.AST_NODE_TYPES.TSInterfaceDeclaration:
6901
- case import_utils47.AST_NODE_TYPES.TSTypeAliasDeclaration:
6902
- case import_utils47.AST_NODE_TYPES.TSEnumDeclaration:
7351
+ case import_utils46.AST_NODE_TYPES.ClassDeclaration:
7352
+ case import_utils46.AST_NODE_TYPES.TSInterfaceDeclaration:
7353
+ case import_utils46.AST_NODE_TYPES.TSTypeAliasDeclaration:
7354
+ case import_utils46.AST_NODE_TYPES.TSEnumDeclaration:
6903
7355
  return node.id === null ? null : { name: node.id.name, params: [] };
6904
- case import_utils47.AST_NODE_TYPES.VariableDeclaration: {
7356
+ case import_utils46.AST_NODE_TYPES.VariableDeclaration: {
6905
7357
  const declarator = node.declarations[0];
6906
- if (declarator === void 0 || declarator.id.type !== import_utils47.AST_NODE_TYPES.Identifier) return null;
7358
+ if (declarator === void 0 || declarator.id.type !== import_utils46.AST_NODE_TYPES.Identifier) return null;
6907
7359
  const init = declarator.init;
6908
- const params = init != null && (init.type === import_utils47.AST_NODE_TYPES.ArrowFunctionExpression || init.type === import_utils47.AST_NODE_TYPES.FunctionExpression) ? paramNames(init.params) : [];
7360
+ const params = init != null && (init.type === import_utils46.AST_NODE_TYPES.ArrowFunctionExpression || init.type === import_utils46.AST_NODE_TYPES.FunctionExpression) ? paramNames(init.params) : [];
6909
7361
  return { name: declarator.id.name, params };
6910
7362
  }
6911
- case import_utils47.AST_NODE_TYPES.MethodDefinition:
6912
- case import_utils47.AST_NODE_TYPES.PropertyDefinition:
6913
- case import_utils47.AST_NODE_TYPES.TSMethodSignature:
6914
- case import_utils47.AST_NODE_TYPES.TSPropertySignature: {
6915
- if (node.key.type !== import_utils47.AST_NODE_TYPES.Identifier) return null;
6916
- 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) : [];
7363
+ case import_utils46.AST_NODE_TYPES.MethodDefinition:
7364
+ case import_utils46.AST_NODE_TYPES.PropertyDefinition:
7365
+ case import_utils46.AST_NODE_TYPES.TSMethodSignature:
7366
+ case import_utils46.AST_NODE_TYPES.TSPropertySignature: {
7367
+ if (node.key.type !== import_utils46.AST_NODE_TYPES.Identifier) return null;
7368
+ const params = node.type === import_utils46.AST_NODE_TYPES.MethodDefinition ? paramNames(node.value.params) : node.type === import_utils46.AST_NODE_TYPES.TSMethodSignature ? paramNames(node.params) : [];
6917
7369
  return { name: node.key.name, params };
6918
7370
  }
6919
7371
  default:
@@ -6923,9 +7375,9 @@ function declarationNames(node) {
6923
7375
  function paramNames(params) {
6924
7376
  const names = [];
6925
7377
  for (const param of params) {
6926
- const target = param.type === import_utils47.AST_NODE_TYPES.AssignmentPattern ? param.left : param;
6927
- if (target.type === import_utils47.AST_NODE_TYPES.Identifier) names.push(target.name);
6928
- else if (target.type === import_utils47.AST_NODE_TYPES.TSParameterProperty) continue;
7378
+ const target = param.type === import_utils46.AST_NODE_TYPES.AssignmentPattern ? param.left : param;
7379
+ if (target.type === import_utils46.AST_NODE_TYPES.Identifier) names.push(target.name);
7380
+ else if (target.type === import_utils46.AST_NODE_TYPES.TSParameterProperty) continue;
6929
7381
  }
6930
7382
  return names;
6931
7383
  }
@@ -6934,7 +7386,7 @@ function tokensOf(names) {
6934
7386
  for (const name of names) for (const part of splitIdentifier(name)) tokens.add(part);
6935
7387
  return tokens;
6936
7388
  }
6937
- var jsdoc_restates_signature_default = import_utils47.ESLintUtils.RuleCreator(
7389
+ var jsdoc_restates_signature_default = import_utils46.ESLintUtils.RuleCreator(
6938
7390
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6939
7391
  )({
6940
7392
  name: "jsdoc-restates-signature",
@@ -6970,7 +7422,7 @@ var jsdoc_restates_signature_default = import_utils47.ESLintUtils.RuleCreator(
6970
7422
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) continue;
6971
7423
  let node = sourceCode.getNodeByRangeIndex(token.range[0]);
6972
7424
  let declaration = null;
6973
- while (node != null && node.type !== import_utils47.AST_NODE_TYPES.Program) {
7425
+ while (node != null && node.type !== import_utils46.AST_NODE_TYPES.Program) {
6974
7426
  declaration = declarationNames(node);
6975
7427
  if (declaration !== null) break;
6976
7428
  node = node.parent ?? null;
@@ -7025,7 +7477,7 @@ var jsdoc_restates_signature_default = import_utils47.ESLintUtils.RuleCreator(
7025
7477
  });
7026
7478
 
7027
7479
  // src/rules/no-restated-comment.ts
7028
- var import_utils48 = require("@typescript-eslint/utils");
7480
+ var import_utils47 = require("@typescript-eslint/utils");
7029
7481
  var MAX_WORDS = 8;
7030
7482
  var MIN_CONTENT_TOKENS = 2;
7031
7483
  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;
@@ -7049,7 +7501,7 @@ function headsSiblingRun(node) {
7049
7501
  const next = index >= 0 ? body[index + 1] : void 0;
7050
7502
  return next !== void 0 && next.type === node.type;
7051
7503
  }
7052
- var no_restated_comment_default = import_utils48.ESLintUtils.RuleCreator(
7504
+ var no_restated_comment_default = import_utils47.ESLintUtils.RuleCreator(
7053
7505
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7054
7506
  )({
7055
7507
  name: "no-restated-comment",
@@ -7077,7 +7529,7 @@ var no_restated_comment_default = import_utils48.ESLintUtils.RuleCreator(
7077
7529
  function labelsASiblingRun(comment) {
7078
7530
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
7079
7531
  if (token === null) return false;
7080
- for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils48.AST_NODE_TYPES.Program; node = node.parent) {
7532
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== import_utils47.AST_NODE_TYPES.Program; node = node.parent) {
7081
7533
  if (headsSiblingRun(node)) return true;
7082
7534
  }
7083
7535
  return false;
@@ -7117,7 +7569,7 @@ var no_restated_comment_default = import_utils48.ESLintUtils.RuleCreator(
7117
7569
  });
7118
7570
 
7119
7571
  // src/rules/trailing-value-narration.ts
7120
- var import_utils49 = require("@typescript-eslint/utils");
7572
+ var import_utils48 = require("@typescript-eslint/utils");
7121
7573
  var NUMBER_RE = /(?<![\w.])(\d+(?:\.\d+)?)(?![\w.])/g;
7122
7574
  var WORD_RE3 = /[A-Za-z]+(?:'[a-z]+)?|\d+(?:\.\d+)?/g;
7123
7575
  var UNIT_WORDS = /* @__PURE__ */ new Set([
@@ -7201,7 +7653,7 @@ function narratesValue(body, code) {
7201
7653
  (word) => STOPWORDS3.has(word) || UNIT_WORDS.has(word) || commentNumbers.has(word) || identifiers.has(word) || stems.has(stem(word))
7202
7654
  );
7203
7655
  }
7204
- var trailing_value_narration_default = import_utils49.ESLintUtils.RuleCreator(
7656
+ var trailing_value_narration_default = import_utils48.ESLintUtils.RuleCreator(
7205
7657
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7206
7658
  )({
7207
7659
  name: "trailing-value-narration",
@@ -7241,6 +7693,188 @@ var trailing_value_narration_default = import_utils49.ESLintUtils.RuleCreator(
7241
7693
  }
7242
7694
  });
7243
7695
 
7696
+ // src/rules/no-type-member-comment-wall.ts
7697
+ var import_utils49 = require("@typescript-eslint/utils");
7698
+ var DEFAULTS = {
7699
+ // Below three rows "a wall" is not a fair description of what the reader sees.
7700
+ minCommentedMembers: 3,
7701
+ // A minority of commented members is a GROUP LABEL, not a wall.
7702
+ minCommentedRatio: 0.6,
7703
+ // Room for one substantive row in four; a type where a quarter of the comments
7704
+ // say something real is a type someone was documenting, not decorating.
7705
+ minRestatedRatio: 0.75,
7706
+ // One word beyond the member's own text. Zero is `jsdoc-restates-signature`'s
7707
+ // test and is already covered there; two admits definitions ("Partial match"
7708
+ // beside "Exact match"), which the evidence file counts.
7709
+ maxNovelWords: 1
7710
+ };
7711
+ var VALUE_TAG_RE = /@(?:deprecated|see|example|throws|remarks|since|default|defaultvalue|link|internal|alpha|beta|experimental|template|typeparam|inheritdoc|todo|fixme|override)\b/i;
7712
+ var DEFAULT_RE = /^\s*@?default\b|\bdefaults? (?:to|:)/i;
7713
+ var DIGIT_RE = /\d/;
7714
+ var UNIT_WORD_RE = /\b(?:ms|milliseconds?|seconds?|minutes?|hours?|days?|weeks?|months?|years?|bytes?|kb|mb|gb|percent|pixels?|px|utc|epoch)\b/i;
7715
+ var EXAMPLE_RE = /["'`]|\be\.g\.|\bi\.e\./;
7716
+ var BANNER_RE = /[=\-─-╿*#~_.]{3,}/;
7717
+ var NON_ASCII_LETTER_RE2 = /[^\p{ASCII}\p{N}\p{P}\p{Z}]/u;
7718
+ var STOPWORDS4 = new Set(
7719
+ `the a an of to for in on with and or as at by is are was be been being
7720
+ this that it its if whether when where which what will would can could should
7721
+ must may into from over about not no does do done has have had used use uses
7722
+ using given provided specified current new existing all any each per via
7723
+ instance object value values data item
7724
+ items element callback handler prop props param arg return
7725
+ returns returning result optional required true false null undefined
7726
+ string number boolean array list promise set map record type name`.split(/\s+/)
7727
+ );
7728
+ var WORD_RE4 = /[A-Za-z][A-Za-z0-9]*/g;
7729
+ var BARE_LABEL_RE = /^[A-Za-z][A-Za-z0-9]*$/;
7730
+ function labelStems(body) {
7731
+ return splitIdentifier(body).map(stem).join(" ");
7732
+ }
7733
+ function isNamedMember(node) {
7734
+ return (node.type === import_utils49.AST_NODE_TYPES.TSPropertySignature || node.type === import_utils49.AST_NODE_TYPES.TSMethodSignature) && !node.computed;
7735
+ }
7736
+ function commentBody(comment) {
7737
+ return comment.value.replace(/^\*+/, "").replace(/^[ \t]*\*[ \t]?/gm, "").trim();
7738
+ }
7739
+ function carriesValue(body) {
7740
+ return isProtected(body) || VALUE_TAG_RE.test(body) || DEFAULT_RE.test(body) || DIGIT_RE.test(body) || UNIT_WORD_RE.test(body) || EXAMPLE_RE.test(body) || BANNER_RE.test(body) || NON_ASCII_LETTER_RE2.test(body);
7741
+ }
7742
+ function knownTokens(source) {
7743
+ const tokens = /* @__PURE__ */ new Set();
7744
+ for (const identifier of source.match(/[A-Za-z_$][\w$]*/g) ?? []) {
7745
+ for (const part of splitIdentifier(identifier)) {
7746
+ tokens.add(part);
7747
+ tokens.add(stem(part));
7748
+ }
7749
+ }
7750
+ return tokens;
7751
+ }
7752
+ function novelWords(body, known) {
7753
+ let novel = 0;
7754
+ for (const word of body.match(WORD_RE4) ?? []) {
7755
+ const lower = word.toLowerCase();
7756
+ if (lower.length < 2 || STOPWORDS4.has(lower)) continue;
7757
+ if (!known.has(lower) && !known.has(stem(lower))) novel += 1;
7758
+ }
7759
+ return novel;
7760
+ }
7761
+ var no_type_member_comment_wall_default = import_utils49.ESLintUtils.RuleCreator(
7762
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7763
+ )({
7764
+ name: "no-type-member-comment-wall",
7765
+ meta: {
7766
+ type: "suggestion",
7767
+ docs: {
7768
+ description: "Flag an object type whose member comments mostly re-spell the members' own names and types."
7769
+ },
7770
+ schema: [
7771
+ {
7772
+ type: "object",
7773
+ additionalProperties: false,
7774
+ properties: {
7775
+ minCommentedMembers: {
7776
+ type: "integer",
7777
+ minimum: 2,
7778
+ description: "Fewest commented members that can count as a wall."
7779
+ },
7780
+ minCommentedRatio: {
7781
+ type: "number",
7782
+ minimum: 0,
7783
+ maximum: 1,
7784
+ description: "Least share of the type's members that must be commented; below it the comments are group labels."
7785
+ },
7786
+ minRestatedRatio: {
7787
+ type: "number",
7788
+ minimum: 0,
7789
+ maximum: 1,
7790
+ description: "Least share of the member comments that must be restatements."
7791
+ },
7792
+ maxNovelWords: {
7793
+ type: "integer",
7794
+ minimum: 0,
7795
+ description: "Most content words a comment may add beyond its member's own source and still count as a restatement."
7796
+ }
7797
+ }
7798
+ }
7799
+ ],
7800
+ messages: {
7801
+ commentWall: "{{restated}} of this type's {{commented}} member comments only re-spell the member's own name and type \u2014 delete them, and keep the rows that say what the name cannot."
7802
+ }
7803
+ },
7804
+ defaultOptions: [DEFAULTS],
7805
+ create(context, [provided]) {
7806
+ const options = { ...DEFAULTS, ...provided };
7807
+ const sourceCode = context.sourceCode;
7808
+ if (isGeneratedFile(context.filename, sourceCode.text) || isTestFile(context.filename) || isStoryFile(context.filename)) {
7809
+ return {};
7810
+ }
7811
+ const endingOn = /* @__PURE__ */ new Map();
7812
+ const startingOn = /* @__PURE__ */ new Map();
7813
+ for (const comment of sourceCode.getAllComments()) {
7814
+ endingOn.set(comment.loc.end.line, comment);
7815
+ if (!startingOn.has(comment.loc.start.line)) startingOn.set(comment.loc.start.line, comment);
7816
+ }
7817
+ function documentingComment(member) {
7818
+ const beforeMember = sourceCode.getTokenBefore(member, { includeComments: false });
7819
+ const ownsItsLine = beforeMember === null || beforeMember.loc.end.line < member.loc.start.line;
7820
+ const lead = ownsItsLine ? endingOn.get(member.loc.start.line - 1) : void 0;
7821
+ if (lead !== void 0) {
7822
+ const before = sourceCode.getTokenBefore(lead, { includeComments: false });
7823
+ if (before === null || before.loc.end.line < lead.loc.start.line) return lead;
7824
+ }
7825
+ const trail = startingOn.get(member.loc.end.line);
7826
+ return trail !== void 0 && trail.range[0] > member.range[0] ? trail : void 0;
7827
+ }
7828
+ function isGroupLabel(comment, member, headsRun) {
7829
+ if (comment.loc.end.line >= member.loc.start.line) return false;
7830
+ const body = commentBody(comment);
7831
+ if (!BARE_LABEL_RE.test(body)) return false;
7832
+ if (labelStems(body) === labelStems(sourceCode.getText(member.key))) return false;
7833
+ const lineAbove = sourceCode.lines[comment.loc.start.line - 2];
7834
+ return headsRun || lineAbove !== void 0 && lineAbove.trim().length === 0;
7835
+ }
7836
+ function check(node) {
7837
+ const members = node.type === import_utils49.AST_NODE_TYPES.TSInterfaceBody ? node.body : node.members;
7838
+ const named = members.filter(isNamedMember);
7839
+ if (named.length === 0) return;
7840
+ const documented = named.map((member) => ({ member, comment: documentingComment(member) }));
7841
+ let commented = 0;
7842
+ let restated = 0;
7843
+ const claimed = /* @__PURE__ */ new Set();
7844
+ for (const [index, { member, comment }] of documented.entries()) {
7845
+ if (comment === void 0 || claimed.has(comment)) continue;
7846
+ const next = documented[index + 1];
7847
+ if (isGroupLabel(comment, member, next !== void 0 && next.comment === void 0)) {
7848
+ continue;
7849
+ }
7850
+ claimed.add(comment);
7851
+ commented += 1;
7852
+ const body = commentBody(comment);
7853
+ if (body.length === 0 || carriesValue(body)) continue;
7854
+ if (novelWords(body, knownTokens(sourceCode.getText(member))) <= options.maxNovelWords) {
7855
+ restated += 1;
7856
+ }
7857
+ }
7858
+ if (commented < options.minCommentedMembers || commented / named.length < options.minCommentedRatio || restated / commented < options.minRestatedRatio) {
7859
+ return;
7860
+ }
7861
+ context.report({
7862
+ node,
7863
+ loc: {
7864
+ start: node.loc.start,
7865
+ end: { line: node.loc.start.line, column: node.loc.start.column + 1 }
7866
+ },
7867
+ messageId: "commentWall",
7868
+ data: { restated: String(restated), commented: String(commented) }
7869
+ });
7870
+ }
7871
+ return {
7872
+ TSInterfaceBody: check,
7873
+ TSTypeLiteral: check
7874
+ };
7875
+ }
7876
+ });
7877
+
7244
7878
  // src/rules/no-tautological-expect.ts
7245
7879
  var import_utils50 = require("@typescript-eslint/utils");
7246
7880
  var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
@@ -7580,174 +8214,217 @@ var prefer_non_nullable_collection_default = import_utils52.ESLintUtils.RuleCrea
7580
8214
  }
7581
8215
  });
7582
8216
 
7583
- // src/rules/no-implicit-attribute-access.ts
8217
+ // src/rules/strict-test-assertions.ts
7584
8218
  var import_utils53 = require("@typescript-eslint/utils");
7585
- var EXCLUDED_BASES = /* @__PURE__ */ new Set([
7586
- "environ",
7587
- "headers",
7588
- "cookies",
7589
- "session",
7590
- "redis",
7591
- "cache",
7592
- "state",
7593
- "config",
7594
- "env",
7595
- "process",
7596
- "localStorage",
7597
- "sessionStorage"
7598
- ]);
7599
- function getBaseName(node) {
7600
- if (node.type === import_utils53.AST_NODE_TYPES.Identifier) {
7601
- return node.name;
8219
+ var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
8220
+ var ARRAY_MATCHERS = /* @__PURE__ */ new Set(["toEqual", "toStrictEqual"]);
8221
+ var COLLECTION_PROPERTIES = /* @__PURE__ */ new Set(["length", "size"]);
8222
+ var NUMERIC_SIGNS2 = /* @__PURE__ */ new Set(["-", "+"]);
8223
+ var MIN_RUN_LENGTH = 2;
8224
+ function literalText(node, getText) {
8225
+ switch (node.type) {
8226
+ case import_utils53.AST_NODE_TYPES.Literal:
8227
+ return "regex" in node ? null : getText(node);
8228
+ case import_utils53.AST_NODE_TYPES.TemplateLiteral:
8229
+ return node.expressions.length === 0 ? getText(node) : null;
8230
+ case import_utils53.AST_NODE_TYPES.UnaryExpression:
8231
+ return NUMERIC_SIGNS2.has(node.operator) && literalText(node.argument, getText) !== null ? getText(node) : null;
8232
+ default:
8233
+ return null;
7602
8234
  }
7603
- if (node.type === import_utils53.AST_NODE_TYPES.MemberExpression && node.property.type === import_utils53.AST_NODE_TYPES.Identifier) {
7604
- return node.property.name;
8235
+ }
8236
+ function isPureReceiver(node) {
8237
+ switch (node.type) {
8238
+ case import_utils53.AST_NODE_TYPES.Identifier:
8239
+ case import_utils53.AST_NODE_TYPES.ThisExpression:
8240
+ return true;
8241
+ case import_utils53.AST_NODE_TYPES.MemberExpression:
8242
+ if (node.optional) {
8243
+ return false;
8244
+ }
8245
+ if (node.computed) {
8246
+ return node.property.type === import_utils53.AST_NODE_TYPES.Literal && isPureReceiver(node.object);
8247
+ }
8248
+ return isPureReceiver(node.object);
8249
+ default:
8250
+ return false;
7605
8251
  }
7606
- return null;
7607
8252
  }
7608
- var no_implicit_attribute_access_default = import_utils53.ESLintUtils.RuleCreator(
8253
+ function literalIndex(node) {
8254
+ if (node.type !== import_utils53.AST_NODE_TYPES.Literal || typeof node.value !== "number") {
8255
+ return null;
8256
+ }
8257
+ return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
8258
+ }
8259
+ var strict_test_assertions_default = import_utils53.ESLintUtils.RuleCreator(
7609
8260
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7610
8261
  )({
7611
- name: "no-implicit-attribute-access",
7612
- meta: {
7613
- type: "problem",
7614
- docs: {
7615
- description: "Disallow imperative dictionary access with string literals; use declarative Zod schemas."
7616
- },
7617
- schema: [],
7618
- messages: {
7619
- noImplicitAttributeAccess: "Imperative lookup for '{{key}}' \u2014 if the key is known, parse the object declaratively with a Zod schema instead."
7620
- }
7621
- },
7622
- defaultOptions: [],
7623
- create(context) {
7624
- return {
7625
- MemberExpression(node) {
7626
- if (!node.computed) {
7627
- return;
7628
- }
7629
- if (node.property.type === import_utils53.AST_NODE_TYPES.Literal && typeof node.property.value === "string") {
7630
- const baseName = getBaseName(node.object);
7631
- if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7632
- context.report({
7633
- node,
7634
- messageId: "noImplicitAttributeAccess",
7635
- data: { key: node.property.value }
7636
- });
7637
- }
7638
- }
7639
- },
7640
- CallExpression(node) {
7641
- const callee = node.callee;
7642
- if (callee.type === import_utils53.AST_NODE_TYPES.MemberExpression) {
7643
- const method = callee.property.type === import_utils53.AST_NODE_TYPES.Identifier ? callee.property.name : null;
7644
- if (method === "get") {
7645
- const arg = node.arguments[0];
7646
- if (arg && arg.type === import_utils53.AST_NODE_TYPES.Literal && typeof arg.value === "string") {
7647
- const baseName = getBaseName(callee.object);
7648
- if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7649
- context.report({
7650
- node,
7651
- messageId: "noImplicitAttributeAccess",
7652
- data: { key: arg.value }
7653
- });
7654
- }
7655
- }
7656
- }
7657
- }
7658
- }
7659
- };
7660
- }
7661
- });
7662
-
7663
- // src/rules/strict-test-assertions.ts
7664
- var import_utils54 = require("@typescript-eslint/utils");
7665
- var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.withoutDocs({
8262
+ name: "strict-test-assertions",
7666
8263
  meta: {
7667
8264
  type: "suggestion",
7668
8265
  docs: {
7669
- description: "Replace multiple sequential assertions with a single toMatchObject or toStrictEqual"
8266
+ description: "Collapse a run of consecutive assertions on the same object into one assertion about the whole object, so every mismatch is reported and nothing outside the asserted keys goes unchecked."
7670
8267
  },
7671
8268
  fixable: "code",
7672
8269
  messages: {
7673
- combineAssertions: "Combine multiple sequential assertions on the same object into a single toMatchObject or toStrictEqual"
8270
+ combineAssertions: "These {{count}} assertions each check one property of `{{receiver}}` against a literal, so the first mismatch hides the rest. Assert the object once: `expect({{receiver}}).toMatchObject({ \u2026 })`.",
8271
+ assertArrayOnce: "These {{count}} assertions check `{{receiver}}[0]`\u2026`{{receiver}}[{{last}}]` one at a time, which never checks how long `{{receiver}}` is \u2014 extra elements pass unnoticed. Assert the array once: `expect({{receiver}}).{{matcher}}([ \u2026 ])`."
7674
8272
  },
7675
8273
  schema: []
7676
8274
  },
7677
8275
  defaultOptions: [],
7678
8276
  create(context) {
7679
- function checkBody(body) {
7680
- let currentObject = null;
7681
- let sequence = [];
7682
- function getExpectObject(expr) {
7683
- if (expr.type === import_utils54.AST_NODE_TYPES.CallExpression && expr.callee.type === import_utils54.AST_NODE_TYPES.MemberExpression && expr.callee.object.type === import_utils54.AST_NODE_TYPES.CallExpression && expr.callee.object.callee.type === import_utils54.AST_NODE_TYPES.Identifier && expr.callee.object.callee.name === "expect" && expr.callee.object.arguments.length === 1) {
7684
- const arg = expr.callee.object.arguments.at(0);
7685
- if (arg?.type === import_utils54.AST_NODE_TYPES.MemberExpression) {
7686
- return arg.object;
7687
- }
8277
+ if (!isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) {
8278
+ return {};
8279
+ }
8280
+ const { sourceCode } = context;
8281
+ function parseAssertion(statement) {
8282
+ if (statement.type !== import_utils53.AST_NODE_TYPES.ExpressionStatement) {
8283
+ return null;
8284
+ }
8285
+ const call = statement.expression;
8286
+ if (call.type !== import_utils53.AST_NODE_TYPES.CallExpression) {
8287
+ return null;
8288
+ }
8289
+ const callee = call.callee;
8290
+ if (callee.type !== import_utils53.AST_NODE_TYPES.MemberExpression || callee.computed || callee.property.type !== import_utils53.AST_NODE_TYPES.Identifier) {
8291
+ return null;
8292
+ }
8293
+ const matcher = callee.property.name;
8294
+ const expectCall = callee.object;
8295
+ if (expectCall.type !== import_utils53.AST_NODE_TYPES.CallExpression || expectCall.callee.type !== import_utils53.AST_NODE_TYPES.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
8296
+ return null;
8297
+ }
8298
+ const actual = expectCall.arguments[0];
8299
+ if (actual === void 0 || actual.type !== import_utils53.AST_NODE_TYPES.MemberExpression || actual.optional) {
8300
+ return null;
8301
+ }
8302
+ if (!isPureReceiver(actual.object)) {
8303
+ return null;
8304
+ }
8305
+ let key;
8306
+ if (actual.computed) {
8307
+ const index = literalIndex(actual.property);
8308
+ if (index === null) {
8309
+ return null;
8310
+ }
8311
+ key = { kind: "index", index };
8312
+ } else {
8313
+ if (actual.property.type !== import_utils53.AST_NODE_TYPES.Identifier || COLLECTION_PROPERTIES.has(actual.property.name)) {
8314
+ return null;
7688
8315
  }
8316
+ key = { kind: "property", name: actual.property.name };
8317
+ }
8318
+ if (matcher === "toBeNull" && call.arguments.length === 0) {
8319
+ return { statement, receiver: actual.object, key, matcher, expectedText: "null", expectedIsLiteral: true };
8320
+ }
8321
+ if (!MERGEABLE_MATCHERS.has(matcher)) {
7689
8322
  return null;
7690
8323
  }
7691
- function reportSequence() {
7692
- const first = sequence.at(0);
7693
- if (sequence.length > 1 && first) {
7694
- context.report({
7695
- node: first,
7696
- messageId: "combineAssertions",
7697
- fix(fixer) {
7698
- if (!currentObject) return null;
7699
- const objectText = context.sourceCode.getText(currentObject);
7700
- const props = sequence.map((stmt) => {
7701
- if (stmt.expression.type !== import_utils54.AST_NODE_TYPES.CallExpression || stmt.expression.callee.type !== import_utils54.AST_NODE_TYPES.MemberExpression || stmt.expression.callee.object.type !== import_utils54.AST_NODE_TYPES.CallExpression) {
7702
- return null;
7703
- }
7704
- const actual = stmt.expression.callee.object.arguments.at(0);
7705
- const expected = stmt.expression.arguments.at(0);
7706
- if (actual?.type === import_utils54.AST_NODE_TYPES.MemberExpression && actual.property.type === import_utils54.AST_NODE_TYPES.Identifier && expected) {
7707
- const propName2 = actual.property.name;
7708
- const valText = context.sourceCode.getText(expected);
7709
- return `${propName2}: ${valText}`;
7710
- }
7711
- return null;
7712
- });
7713
- if (props.some((p) => p === null)) return null;
7714
- const replacement = `expect(${objectText}).toMatchObject({ ${props.join(", ")} });`;
7715
- return [
7716
- fixer.replaceText(first, replacement),
7717
- ...sequence.slice(1).map((stmt) => fixer.remove(stmt))
7718
- ];
7719
- }
7720
- });
8324
+ const expected = call.arguments[0];
8325
+ if (call.arguments.length !== 1 || expected === void 0 || expected.type === import_utils53.AST_NODE_TYPES.SpreadElement) {
8326
+ return null;
8327
+ }
8328
+ const literal = literalText(expected, (node) => sourceCode.getText(node));
8329
+ return {
8330
+ statement,
8331
+ receiver: actual.object,
8332
+ key,
8333
+ matcher,
8334
+ expectedText: literal ?? sourceCode.getText(expected),
8335
+ expectedIsLiteral: literal !== null
8336
+ };
8337
+ }
8338
+ function reportPropertyRun(run) {
8339
+ const names = /* @__PURE__ */ new Set();
8340
+ for (const assertion of run) {
8341
+ if (assertion.key.kind !== "property" || !assertion.expectedIsLiteral) {
8342
+ return;
8343
+ }
8344
+ if (!MERGEABLE_MATCHERS.has(assertion.matcher) && assertion.matcher !== "toBeNull") {
8345
+ return;
8346
+ }
8347
+ if (names.has(assertion.key.name)) {
8348
+ return;
7721
8349
  }
8350
+ names.add(assertion.key.name);
7722
8351
  }
7723
- for (const statement of body) {
7724
- if (statement.type === import_utils54.AST_NODE_TYPES.ExpressionStatement) {
7725
- const obj = getExpectObject(statement.expression);
7726
- if (obj && currentObject && context.sourceCode.getText(obj) === context.sourceCode.getText(currentObject)) {
7727
- sequence.push(statement);
8352
+ const first = run[0];
8353
+ if (first === void 0) {
8354
+ return;
8355
+ }
8356
+ const receiverText = sourceCode.getText(first.receiver);
8357
+ const properties = run.map(
8358
+ (assertion) => assertion.key.kind === "property" ? `${assertion.key.name}: ${assertion.expectedText}` : ""
8359
+ ).join(", ");
8360
+ context.report({
8361
+ node: first.statement,
8362
+ messageId: "combineAssertions",
8363
+ data: { count: String(run.length), receiver: receiverText },
8364
+ fix: (fixer) => [
8365
+ fixer.replaceText(first.statement, `expect(${receiverText}).toMatchObject({ ${properties} });`),
8366
+ ...run.slice(1).map((assertion) => fixer.remove(assertion.statement))
8367
+ ]
8368
+ });
8369
+ }
8370
+ function reportIndexRun(run) {
8371
+ const first = run[0];
8372
+ if (first === void 0 || !ARRAY_MATCHERS.has(first.matcher)) {
8373
+ return;
8374
+ }
8375
+ const indices = /* @__PURE__ */ new Set();
8376
+ for (const assertion of run) {
8377
+ if (assertion.key.kind !== "index" || assertion.matcher !== first.matcher) {
8378
+ return;
8379
+ }
8380
+ indices.add(assertion.key.index);
8381
+ }
8382
+ if (indices.size !== run.length || Math.max(...indices) !== run.length - 1) {
8383
+ return;
8384
+ }
8385
+ context.report({
8386
+ node: first.statement,
8387
+ messageId: "assertArrayOnce",
8388
+ data: {
8389
+ count: String(run.length),
8390
+ receiver: sourceCode.getText(first.receiver),
8391
+ last: String(run.length - 1),
8392
+ matcher: first.matcher
8393
+ }
8394
+ });
8395
+ }
8396
+ function checkBody(body) {
8397
+ let run = [];
8398
+ const flush = () => {
8399
+ const first = run[0];
8400
+ if (first !== void 0 && run.length >= MIN_RUN_LENGTH) {
8401
+ if (first.key.kind === "property") {
8402
+ reportPropertyRun(run);
7728
8403
  } else {
7729
- reportSequence();
7730
- if (obj) {
7731
- currentObject = obj;
7732
- sequence = [statement];
7733
- } else {
7734
- currentObject = null;
7735
- sequence = [];
7736
- }
8404
+ reportIndexRun(run);
7737
8405
  }
7738
- } else {
7739
- reportSequence();
7740
- currentObject = null;
7741
- sequence = [];
8406
+ }
8407
+ run = [];
8408
+ };
8409
+ for (const statement of body) {
8410
+ const assertion = parseAssertion(statement);
8411
+ const previous = run.at(-1);
8412
+ if (assertion !== null && previous !== void 0 && previous.key.kind === assertion.key.kind && sourceCode.getText(previous.receiver) === sourceCode.getText(assertion.receiver)) {
8413
+ run.push(assertion);
8414
+ continue;
8415
+ }
8416
+ flush();
8417
+ if (assertion !== null) {
8418
+ run = [assertion];
7742
8419
  }
7743
8420
  }
7744
- reportSequence();
8421
+ flush();
7745
8422
  }
7746
8423
  return {
7747
- BlockStatement(node) {
8424
+ BlockStatement: (node) => {
7748
8425
  checkBody(node.body);
7749
8426
  },
7750
- Program(node) {
8427
+ Program: (node) => {
7751
8428
  checkBody(node.body);
7752
8429
  }
7753
8430
  };
@@ -7755,8 +8432,8 @@ var strict_test_assertions_default = import_utils54.ESLintUtils.RuleCreator.with
7755
8432
  });
7756
8433
 
7757
8434
  // src/rules/no-async-callback-in-waitfor.ts
7758
- var import_utils55 = require("@typescript-eslint/utils");
7759
- var no_async_callback_in_waitfor_default = import_utils55.ESLintUtils.RuleCreator(
8435
+ var import_utils54 = require("@typescript-eslint/utils");
8436
+ var no_async_callback_in_waitfor_default = import_utils54.ESLintUtils.RuleCreator(
7760
8437
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7761
8438
  )({
7762
8439
  name: "no-async-callback-in-waitfor",
@@ -7777,9 +8454,9 @@ var no_async_callback_in_waitfor_default = import_utils55.ESLintUtils.RuleCreato
7777
8454
  }
7778
8455
  return {
7779
8456
  CallExpression(node) {
7780
- if (node.callee.type === import_utils55.AST_NODE_TYPES.Identifier && node.callee.name === "waitFor") {
8457
+ if (node.callee.type === import_utils54.AST_NODE_TYPES.Identifier && node.callee.name === "waitFor") {
7781
8458
  const callback = node.arguments[0];
7782
- if (callback && (callback.type === import_utils55.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils55.AST_NODE_TYPES.FunctionExpression) && callback.async) {
8459
+ if (callback && (callback.type === import_utils54.AST_NODE_TYPES.ArrowFunctionExpression || callback.type === import_utils54.AST_NODE_TYPES.FunctionExpression) && callback.async) {
7783
8460
  context.report({
7784
8461
  node: callback,
7785
8462
  messageId: "noAsyncCallbackInWaitFor"
@@ -7792,7 +8469,7 @@ var no_async_callback_in_waitfor_default = import_utils55.ESLintUtils.RuleCreato
7792
8469
  });
7793
8470
 
7794
8471
  // src/rules/no-hand-rolled-sleep.ts
7795
- var import_utils56 = require("@typescript-eslint/utils");
8472
+ var import_utils55 = require("@typescript-eslint/utils");
7796
8473
  var GLOBAL_OBJECTS2 = /* @__PURE__ */ new Set([
7797
8474
  "globalThis",
7798
8475
  "window",
@@ -7811,66 +8488,66 @@ function matchesAnyPattern3(filename, patterns) {
7811
8488
  return false;
7812
8489
  }
7813
8490
  function isSetTimeoutCallee(callee) {
7814
- if (callee.type === import_utils56.AST_NODE_TYPES.Identifier) {
8491
+ if (callee.type === import_utils55.AST_NODE_TYPES.Identifier) {
7815
8492
  return callee.name === "setTimeout";
7816
8493
  }
7817
- return callee.type === import_utils56.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils56.AST_NODE_TYPES.Identifier && callee.property.name === "setTimeout" && callee.object.type === import_utils56.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS2.has(callee.object.name);
8494
+ return callee.type === import_utils55.AST_NODE_TYPES.MemberExpression && !callee.computed && callee.property.type === import_utils55.AST_NODE_TYPES.Identifier && callee.property.name === "setTimeout" && callee.object.type === import_utils55.AST_NODE_TYPES.Identifier && GLOBAL_OBJECTS2.has(callee.object.name);
7818
8495
  }
7819
8496
  function soleCall(fn) {
7820
- if (fn.body.type !== import_utils56.AST_NODE_TYPES.BlockStatement) {
7821
- return fn.body.type === import_utils56.AST_NODE_TYPES.CallExpression ? fn.body : null;
8497
+ if (fn.body.type !== import_utils55.AST_NODE_TYPES.BlockStatement) {
8498
+ return fn.body.type === import_utils55.AST_NODE_TYPES.CallExpression ? fn.body : null;
7822
8499
  }
7823
8500
  if (fn.body.body.length !== 1) {
7824
8501
  return null;
7825
8502
  }
7826
8503
  const [only] = fn.body.body;
7827
- if (only?.type !== import_utils56.AST_NODE_TYPES.ExpressionStatement) {
8504
+ if (only?.type !== import_utils55.AST_NODE_TYPES.ExpressionStatement) {
7828
8505
  return null;
7829
8506
  }
7830
- return only.expression.type === import_utils56.AST_NODE_TYPES.CallExpression ? only.expression : null;
8507
+ return only.expression.type === import_utils55.AST_NODE_TYPES.CallExpression ? only.expression : null;
7831
8508
  }
7832
8509
  function isTimedDelay(delay) {
7833
8510
  if (delay === void 0) {
7834
8511
  return false;
7835
8512
  }
7836
- if (delay.type === import_utils56.AST_NODE_TYPES.Literal && typeof delay.value === "number") {
8513
+ if (delay.type === import_utils55.AST_NODE_TYPES.Literal && typeof delay.value === "number") {
7837
8514
  return delay.value !== 0;
7838
8515
  }
7839
8516
  return true;
7840
8517
  }
7841
8518
  function settlesWithoutValue(callback, name) {
7842
- if (callback.type === import_utils56.AST_NODE_TYPES.Identifier) {
8519
+ if (callback.type === import_utils55.AST_NODE_TYPES.Identifier) {
7843
8520
  return callback.name === name;
7844
8521
  }
7845
- if (callback.type !== import_utils56.AST_NODE_TYPES.ArrowFunctionExpression && callback.type !== import_utils56.AST_NODE_TYPES.FunctionExpression) {
8522
+ if (callback.type !== import_utils55.AST_NODE_TYPES.ArrowFunctionExpression && callback.type !== import_utils55.AST_NODE_TYPES.FunctionExpression) {
7846
8523
  return false;
7847
8524
  }
7848
8525
  const call = soleCall(callback);
7849
- return call !== null && call.arguments.length === 0 && call.callee.type === import_utils56.AST_NODE_TYPES.Identifier && call.callee.name === name;
8526
+ return call !== null && call.arguments.length === 0 && call.callee.type === import_utils55.AST_NODE_TYPES.Identifier && call.callee.name === name;
7850
8527
  }
7851
8528
  function rejectsInCallback(callback, name) {
7852
- if (callback.type === import_utils56.AST_NODE_TYPES.Identifier) {
8529
+ if (callback.type === import_utils55.AST_NODE_TYPES.Identifier) {
7853
8530
  return callback.name === name;
7854
8531
  }
7855
- if (callback.type !== import_utils56.AST_NODE_TYPES.ArrowFunctionExpression && callback.type !== import_utils56.AST_NODE_TYPES.FunctionExpression) {
8532
+ if (callback.type !== import_utils55.AST_NODE_TYPES.ArrowFunctionExpression && callback.type !== import_utils55.AST_NODE_TYPES.FunctionExpression) {
7856
8533
  return false;
7857
8534
  }
7858
8535
  const call = soleCall(callback);
7859
- return call !== null && call.callee.type === import_utils56.AST_NODE_TYPES.Identifier && call.callee.name === name;
8536
+ return call !== null && call.callee.type === import_utils55.AST_NODE_TYPES.Identifier && call.callee.name === name;
7860
8537
  }
7861
8538
  function parameterName(fn, index) {
7862
8539
  const parameter = fn.params[index];
7863
- return parameter?.type === import_utils56.AST_NODE_TYPES.Identifier ? parameter.name : null;
8540
+ return parameter?.type === import_utils55.AST_NODE_TYPES.Identifier ? parameter.name : null;
7864
8541
  }
7865
8542
  function isRaceArm(node) {
7866
8543
  const array = node.parent;
7867
- if (array?.type !== import_utils56.AST_NODE_TYPES.ArrayExpression) {
8544
+ if (array?.type !== import_utils55.AST_NODE_TYPES.ArrayExpression) {
7868
8545
  return false;
7869
8546
  }
7870
8547
  const call = array.parent;
7871
- return call?.type === import_utils56.AST_NODE_TYPES.CallExpression && call.arguments[0] === array && call.callee.type === import_utils56.AST_NODE_TYPES.MemberExpression && !call.callee.computed && call.callee.object.type === import_utils56.AST_NODE_TYPES.Identifier && call.callee.object.name === "Promise" && call.callee.property.type === import_utils56.AST_NODE_TYPES.Identifier && RACE_METHODS.has(call.callee.property.name);
8548
+ return call?.type === import_utils55.AST_NODE_TYPES.CallExpression && call.arguments[0] === array && call.callee.type === import_utils55.AST_NODE_TYPES.MemberExpression && !call.callee.computed && call.callee.object.type === import_utils55.AST_NODE_TYPES.Identifier && call.callee.object.name === "Promise" && call.callee.property.type === import_utils55.AST_NODE_TYPES.Identifier && RACE_METHODS.has(call.callee.property.name);
7872
8549
  }
7873
- var no_hand_rolled_sleep_default = import_utils56.ESLintUtils.RuleCreator(
8550
+ var no_hand_rolled_sleep_default = import_utils55.ESLintUtils.RuleCreator(
7874
8551
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7875
8552
  )({
7876
8553
  name: "no-hand-rolled-sleep",
@@ -7918,10 +8595,10 @@ var no_hand_rolled_sleep_default = import_utils56.ESLintUtils.RuleCreator(
7918
8595
  }
7919
8596
  const program = sourceCode.ast;
7920
8597
  for (const statement of program.body) {
7921
- if (statement.type === import_utils56.AST_NODE_TYPES.ExpressionStatement && statement.expression.type === import_utils56.AST_NODE_TYPES.Literal && statement.expression.value === "use client") {
8598
+ if (statement.type === import_utils55.AST_NODE_TYPES.ExpressionStatement && statement.expression.type === import_utils55.AST_NODE_TYPES.Literal && statement.expression.value === "use client") {
7922
8599
  return true;
7923
8600
  }
7924
- if (statement.type === import_utils56.AST_NODE_TYPES.ImportDeclaration && typeof statement.source.value === "string" && CLIENT_ONLY_MODULES.test(statement.source.value)) {
8601
+ if (statement.type === import_utils55.AST_NODE_TYPES.ImportDeclaration && typeof statement.source.value === "string" && CLIENT_ONLY_MODULES.test(statement.source.value)) {
7925
8602
  return true;
7926
8603
  }
7927
8604
  }
@@ -7937,11 +8614,11 @@ var no_hand_rolled_sleep_default = import_utils56.ESLintUtils.RuleCreator(
7937
8614
  };
7938
8615
  return {
7939
8616
  NewExpression(node) {
7940
- if (node.callee.type !== import_utils56.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise") {
8617
+ if (node.callee.type !== import_utils55.AST_NODE_TYPES.Identifier || node.callee.name !== "Promise") {
7941
8618
  return;
7942
8619
  }
7943
8620
  const executor = node.arguments[0];
7944
- if (executor?.type !== import_utils56.AST_NODE_TYPES.ArrowFunctionExpression && executor?.type !== import_utils56.AST_NODE_TYPES.FunctionExpression) {
8621
+ if (executor?.type !== import_utils55.AST_NODE_TYPES.ArrowFunctionExpression && executor?.type !== import_utils55.AST_NODE_TYPES.FunctionExpression) {
7945
8622
  return;
7946
8623
  }
7947
8624
  const call = soleCall(executor);
@@ -7968,43 +8645,8 @@ var no_hand_rolled_sleep_default = import_utils56.ESLintUtils.RuleCreator(
7968
8645
  }
7969
8646
  });
7970
8647
 
7971
- // src/rules/prefer-setup-file-mocks.ts
7972
- var import_utils57 = require("@typescript-eslint/utils");
7973
- var prefer_setup_file_mocks_default = import_utils57.ESLintUtils.RuleCreator(
7974
- (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7975
- )({
7976
- name: "prefer-setup-file-mocks",
7977
- meta: {
7978
- type: "suggestion",
7979
- docs: {
7980
- description: "Prefer defining module mocks in setup files rather than using vi.mock or jest.mock inline in test files."
7981
- },
7982
- schema: [],
7983
- messages: {
7984
- 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."
7985
- }
7986
- },
7987
- defaultOptions: [],
7988
- create(context) {
7989
- if (!isTestFile(context.filename)) {
7990
- return {};
7991
- }
7992
- return {
7993
- CallExpression(node) {
7994
- if (node.callee.type === import_utils57.AST_NODE_TYPES.MemberExpression && node.callee.object.type === import_utils57.AST_NODE_TYPES.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === import_utils57.AST_NODE_TYPES.Identifier && node.callee.property.name === "mock") {
7995
- context.report({
7996
- node,
7997
- messageId: "preferSetupFileMocks"
7998
- });
7999
- }
8000
- }
8001
- };
8002
- }
8003
- });
8004
-
8005
8648
  // src/index.ts
8006
8649
  var rules = {
8007
- "ban-loose-type-guards-in-tests": ban_loose_type_guards_in_tests_default,
8008
8650
  "enforce-file-structure": enforce_file_structure_default,
8009
8651
  "no-client-side-data-fetching": no_client_side_data_fetching_default,
8010
8652
  "no-comment-cruft": no_comment_cruft_default,
@@ -8049,18 +8691,17 @@ var rules = {
8049
8691
  "jsdoc-restates-signature": jsdoc_restates_signature_default,
8050
8692
  "no-restated-comment": no_restated_comment_default,
8051
8693
  "trailing-value-narration": trailing_value_narration_default,
8694
+ "no-type-member-comment-wall": no_type_member_comment_wall_default,
8052
8695
  "no-tautological-expect": no_tautological_expect_default,
8053
8696
  "require-interface-for-injected-service": require_interface_for_injected_service_default,
8054
8697
  "strict-test-assertions": strict_test_assertions_default,
8055
8698
  "prefer-non-nullable-collection": prefer_non_nullable_collection_default,
8056
- "no-implicit-attribute-access": no_implicit_attribute_access_default,
8057
- "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default,
8058
- "prefer-setup-file-mocks": prefer_setup_file_mocks_default
8699
+ "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default
8059
8700
  };
8060
8701
  var plugin = {
8061
8702
  meta: {
8062
8703
  name: "@sarj/eslint-plugin",
8063
- version: "4.2.0"
8704
+ version: "5.1.0"
8064
8705
  },
8065
8706
  rules,
8066
8707
  configs: {
@@ -8070,7 +8711,6 @@ var plugin = {
8070
8711
  "@sarj/zod-naming-convention": "warn",
8071
8712
  "@sarj/require-assert-never": "error",
8072
8713
  "@sarj/require-zod-form-validation": "error",
8073
- "@sarj/ban-loose-type-guards-in-tests": "error",
8074
8714
  "@sarj/enforce-file-structure": "warn",
8075
8715
  "@sarj/no-client-side-data-fetching": "warn",
8076
8716
  "@sarj/prefer-server-actions": "warn",
@@ -8141,6 +8781,14 @@ var plugin = {
8141
8781
  "@sarj/no-restated-comment": "warn",
8142
8782
  "@sarj/jsdoc-restates-signature": "warn",
8143
8783
  "@sarj/trailing-value-narration": "warn",
8784
+ // The VOLUME arm of the same family (2026-07). Its siblings judge one
8785
+ // comment at a time and can only condemn one that adds nothing; this
8786
+ // one judges a TYPE, so it can report ten rows that each add a word.
8787
+ // 33 OSS TS repos / 46,861 files: 22 findings, all read, 0 false; zero
8788
+ // across ten first-party repos, where the generated-file sniff alone
8789
+ // removed 321 of the 407 raw hits. Measurements and the six false
8790
+ // positives that shaped the guards: docs/rules/no-type-member-comment-wall.md
8791
+ "@sarj/no-type-member-comment-wall": "warn",
8144
8792
  // The TS half of SARJ057 (2026-07). Python has caught the
8145
8793
  // assertion-FREE test since 0.15.0 (SARJ043) and had no TS
8146
8794
  // counterpart, which is how `expect(true).toBe(true); // placeholder`
@@ -8155,9 +8803,7 @@ var plugin = {
8155
8803
  // port, 29 fire, 28 of them true positives.
8156
8804
  "@sarj/require-interface-for-injected-service": "warn",
8157
8805
  "@sarj/prefer-non-nullable-collection": "warn",
8158
- "@sarj/no-implicit-attribute-access": "warn",
8159
- "@sarj/no-async-callback-in-waitfor": "warn",
8160
- "@sarj/prefer-setup-file-mocks": "warn"
8806
+ "@sarj/no-async-callback-in-waitfor": "warn"
8161
8807
  }
8162
8808
  },
8163
8809
  strict: {
@@ -8166,7 +8812,6 @@ var plugin = {
8166
8812
  "@sarj/zod-naming-convention": "error",
8167
8813
  "@sarj/require-assert-never": "error",
8168
8814
  "@sarj/require-zod-form-validation": "error",
8169
- "@sarj/ban-loose-type-guards-in-tests": "error",
8170
8815
  "@sarj/enforce-file-structure": "error",
8171
8816
  "@sarj/no-raw-env": "error",
8172
8817
  "@sarj/no-enum": "error",
@@ -8234,6 +8879,7 @@ var plugin = {
8234
8879
  "@sarj/no-restated-comment": "error",
8235
8880
  "@sarj/jsdoc-restates-signature": "error",
8236
8881
  "@sarj/trailing-value-narration": "error",
8882
+ "@sarj/no-type-member-comment-wall": "error",
8237
8883
  // TS half of SARJ057 — see the `recommended` block for the measurement.
8238
8884
  "@sarj/no-tautological-expect": "error",
8239
8885
  // Substitutability: the TS sibling of the Python `prefer-real-store-in-tests`
@@ -8241,9 +8887,7 @@ var plugin = {
8241
8887
  // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
8242
8888
  "@sarj/require-interface-for-injected-service": "error",
8243
8889
  "@sarj/prefer-non-nullable-collection": "error",
8244
- "@sarj/no-implicit-attribute-access": "error",
8245
- "@sarj/no-async-callback-in-waitfor": "error",
8246
- "@sarj/prefer-setup-file-mocks": "error"
8890
+ "@sarj/no-async-callback-in-waitfor": "error"
8247
8891
  }
8248
8892
  }
8249
8893
  }