@sarj/eslint-plugin 4.2.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- // src/rules/ban-loose-type-guards-in-tests.ts
2
- import { ESLintUtils } from "@typescript-eslint/utils";
1
+ // src/rules/enforce-file-structure.ts
2
+ import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
3
3
 
4
4
  // src/rules/_paths.ts
5
5
  var SCRIPT_FILE_RE = /([\\/]scripts[\\/])|(\.mjs$)/;
@@ -24,43 +24,7 @@ function isScriptFile(filename) {
24
24
  return SCRIPT_FILE_RE.test(filename);
25
25
  }
26
26
 
27
- // src/rules/ban-loose-type-guards-in-tests.ts
28
- var ban_loose_type_guards_in_tests_default = ESLintUtils.RuleCreator(
29
- (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
30
- )({
31
- name: "ban-loose-type-guards-in-tests",
32
- meta: {
33
- type: "problem",
34
- docs: {
35
- description: "Disallow loose type guards (`typeof` and `in`) in test files. Enforce Zod schemas or strict matchers for type validation."
36
- },
37
- schema: [],
38
- messages: {
39
- banLooseTypeGuardsInTests: "Do not use `typeof` or `in` for type validation in tests. Use Zod schemas or strict assertion matchers instead."
40
- }
41
- },
42
- defaultOptions: [],
43
- create(context) {
44
- if (!isTestFile(context.filename)) {
45
- return {};
46
- }
47
- return {
48
- UnaryExpression(node) {
49
- if (node.operator === "typeof") {
50
- context.report({ node, messageId: "banLooseTypeGuardsInTests" });
51
- }
52
- },
53
- BinaryExpression(node) {
54
- if (node.operator === "in") {
55
- context.report({ node, messageId: "banLooseTypeGuardsInTests" });
56
- }
57
- }
58
- };
59
- }
60
- });
61
-
62
27
  // src/rules/enforce-file-structure.ts
63
- import { ESLintUtils as ESLintUtils2, AST_NODE_TYPES } from "@typescript-eslint/utils";
64
28
  var classifyStatement = (statement) => {
65
29
  switch (statement.type) {
66
30
  case AST_NODE_TYPES.ImportDeclaration:
@@ -80,7 +44,7 @@ var isUseServerDirective = (statement) => {
80
44
  if (expr.type !== AST_NODE_TYPES.Literal) return false;
81
45
  return expr.value === "use server";
82
46
  };
83
- var enforce_file_structure_default = ESLintUtils2.RuleCreator(
47
+ var enforce_file_structure_default = ESLintUtils.RuleCreator(
84
48
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
85
49
  )({
86
50
  name: "enforce-file-structure",
@@ -142,7 +106,7 @@ var enforce_file_structure_default = ESLintUtils2.RuleCreator(
142
106
  // src/rules/no-client-side-data-fetching.ts
143
107
  import {
144
108
  AST_NODE_TYPES as AST_NODE_TYPES2,
145
- ESLintUtils as ESLintUtils3
109
+ ESLintUtils as ESLintUtils2
146
110
  } from "@typescript-eslint/utils";
147
111
  var FETCH_LIBS = /* @__PURE__ */ new Set(["axios", "ky", "superagent"]);
148
112
  var HTTP_METHOD_NAMES = /* @__PURE__ */ new Set([
@@ -240,7 +204,7 @@ function isAnalyticsCall(node) {
240
204
  if (url === "") return false;
241
205
  return url.split(/[/.]/).some((segment) => ANALYTICS_SEGMENTS.has(segment));
242
206
  }
243
- var no_client_side_data_fetching_default = ESLintUtils3.RuleCreator(
207
+ var no_client_side_data_fetching_default = ESLintUtils2.RuleCreator(
244
208
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
245
209
  )({
246
210
  name: "no-client-side-data-fetching",
@@ -278,7 +242,7 @@ var no_client_side_data_fetching_default = ESLintUtils3.RuleCreator(
278
242
  });
279
243
 
280
244
  // src/rules/no-comment-cruft.ts
281
- import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
245
+ import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
282
246
 
283
247
  // src/rules/_comments.ts
284
248
  import { AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
@@ -542,7 +506,8 @@ var DUMMY_TRANSLATION_RE = /^(?:increment|return|returns|get|gets|set\b(?! up\b)
542
506
  var DIAGRAM_ARROW_RE = /[-=~]{2,}>|<[-=~]{2,}/;
543
507
  var CODE_KEYWORD_RE = /^(import |export |const |let |var |function\b|class |interface |type \w|enum |return\b|throw |await |async |if\s*\(|for\s*\(|while\s*\(|switch\s*\(|new |console\.)/;
544
508
  var CODE_TAIL_RE = /[;{}()]\s*$|=>\s*$|,\s*$/;
545
- var CALL_OR_ASSIGN_RE = /^[A-Za-z_$][\w.$[\]]*\s*(?:=(?![=>])|\+=|-=|\*=)\s*\S.*[;)}\]]\s*$|^[A-Za-z_$][\w.$]*\([^)]*\)\s*;?\s*$/;
509
+ var ASSIGN_RE = /^[A-Za-z_$][\w.$[\]]*\s*(?:=(?![=>])|\+=|-=|\*=)\s*\S.*[;)}\]]\s*$/;
510
+ var CALL_RE = /^[A-Za-z_$][\w.$]*\([^)]*\)\s*;?\s*$/;
546
511
  var PSEUDOCODE_RE = /%\w+%|\[opt\]|(?:^|\s)<[A-Za-z]\w*>|…|\.\.\./;
547
512
  function stripCommentMarker(line) {
548
513
  return line.replace(/^\s*\/{1,2}/, "").replace(/^\s*\*+/, "").trim();
@@ -556,11 +521,12 @@ function isBanner(text) {
556
521
  if (BANNER_FULL_RE.test(t) || isRegionMarker(t)) return true;
557
522
  return BANNER_RUN_RE.test(t) && !DIAGRAM_ARROW_RE.test(t);
558
523
  }
559
- function looksLikeCode(text) {
524
+ function looksLikeCode(text, allowCall = true) {
560
525
  const t = text.trim();
561
526
  if (!t) return false;
562
527
  if (CODE_KEYWORD_RE.test(t) && CODE_TAIL_RE.test(t)) return true;
563
- return CALL_OR_ASSIGN_RE.test(t);
528
+ if (ASSIGN_RE.test(t)) return true;
529
+ return allowCall && CALL_RE.test(t);
564
530
  }
565
531
  function hasPseudocode(text) {
566
532
  return PSEUDOCODE_RE.test(text);
@@ -578,20 +544,24 @@ function isProse(text) {
578
544
  }
579
545
  return false;
580
546
  }
581
- 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;
547
+ 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;
548
+ function restatesWholeStatement(body, statement) {
549
+ return statement !== null && restatesStatementHead(body, statement.replaceAll("(", " "));
550
+ }
582
551
  function isRedundantNarration(body, statementBelow, standalone, isolatedEnumeration, nested) {
583
552
  const t = body.trim();
584
553
  if (!t || looksLikeCode(t) || hasPseudocode(t)) return false;
585
554
  if (standalone) {
586
- if (STEP_NARRATION_RE.test(t)) return true;
587
- if (META_COMMENTARY_RE.test(t) && !JUSTIFICATION_RE.test(t)) return true;
555
+ const justified = JUSTIFICATION_RE.test(t);
556
+ if (STEP_NARRATION_RE.test(t) && !justified) return true;
557
+ if (META_COMMENTARY_RE.test(t) && !justified) return true;
588
558
  if (HELPER_OPENER_RE.test(t) || LETS_RE.test(t)) return true;
589
559
  const words = t.split(/\s+/);
590
- if (words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
560
+ if (words.length > 1 && words.length <= 4 && DUMMY_TRANSLATION_RE.test(t) && !/[():=]/.test(t)) {
591
561
  const lowerT = t.toLowerCase();
592
562
  const rationaleWords = ["when", "because", "if", "so that", "due to", "for", "instead of", "to prevent", "to avoid", "only"];
593
- if (!rationaleWords.some((w) => lowerT.includes(w))) {
594
- if (words.length > 1) return true;
563
+ if (!rationaleWords.some((w) => lowerT.includes(w)) && restatesWholeStatement(t, statementBelow)) {
564
+ return true;
595
565
  }
596
566
  }
597
567
  if (!nested && isSectionLabel(t)) return true;
@@ -608,6 +578,10 @@ var STATEMENT_CONTAINERS = /* @__PURE__ */ new Set([
608
578
  AST_NODE_TYPES4.TSModuleBlock,
609
579
  AST_NODE_TYPES4.TSInterfaceBody
610
580
  ]);
581
+ var TYPE_MEMBER_CONTAINERS = /* @__PURE__ */ new Set([
582
+ AST_NODE_TYPES4.TSInterfaceBody,
583
+ AST_NODE_TYPES4.TSTypeLiteral
584
+ ]);
611
585
  function runCitesAReference(comments, index) {
612
586
  for (let i = index; i >= 0; i--) {
613
587
  if (i < index && !areAdjacentLineComments(comments[i], comments[i + 1])) break;
@@ -635,10 +609,10 @@ function hasIllustrationLeadInAbove(comments, index) {
635
609
  }
636
610
  return false;
637
611
  }
638
- function hasCommentedOutCode(texts, precedingProse) {
612
+ function hasCommentedOutCode(texts, precedingProse, allowCall) {
639
613
  for (let i = 0; i < texts.length; i++) {
640
614
  const line = texts[i];
641
- if (line === void 0 || !looksLikeCode(line) || hasPseudocode(line)) {
615
+ if (line === void 0 || !looksLikeCode(line, allowCall) || hasPseudocode(line)) {
642
616
  continue;
643
617
  }
644
618
  const prev = i > 0 ? texts[i - 1] : void 0;
@@ -647,7 +621,7 @@ function hasCommentedOutCode(texts, precedingProse) {
647
621
  }
648
622
  return false;
649
623
  }
650
- var no_comment_cruft_default = ESLintUtils4.RuleCreator(
624
+ var no_comment_cruft_default = ESLintUtils3.RuleCreator(
651
625
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
652
626
  )({
653
627
  name: "no-comment-cruft",
@@ -732,7 +706,9 @@ var no_comment_cruft_default = ESLintUtils4.RuleCreator(
732
706
  }
733
707
  const prev = comments[i - 1];
734
708
  const precedingProse = prev !== void 0 && prev.type === "Line" && prev.loc.end.line === comment.loc.start.line - 1 && isProse(stripCommentMarker(prev.value));
735
- if (hasCommentedOutCode(texts, precedingProse) && !hasIllustrationLeadInAbove(comments, i)) {
709
+ const container = sourceCode.getNodeByRangeIndex(comment.range[0]);
710
+ const inTypeMembers = container !== null && TYPE_MEMBER_CONTAINERS.has(container.type);
711
+ if (hasCommentedOutCode(texts, precedingProse, !inTypeMembers) && !hasIllustrationLeadInAbove(comments, i)) {
736
712
  context.report({ node: comment, messageId: "commentedOutCode" });
737
713
  continue;
738
714
  }
@@ -740,7 +716,6 @@ var no_comment_cruft_default = ESLintUtils4.RuleCreator(
740
716
  const body = texts[0];
741
717
  const statement = restatableStatementBelow(comment, sourceCode);
742
718
  const standalone = !isInsideCommentRun(comments, i);
743
- const container = sourceCode.getNodeByRangeIndex(comment.range[0]);
744
719
  const nested = container !== null && !STATEMENT_CONTAINERS.has(container.type);
745
720
  if (body !== void 0 && !runCitesAReference(comments, i) && isRedundantNarration(body, statement, standalone, enumerated.length === 1, nested)) {
746
721
  context.report({ node: comment, messageId: "redundantNarration" });
@@ -754,7 +729,7 @@ var no_comment_cruft_default = ESLintUtils4.RuleCreator(
754
729
  });
755
730
 
756
731
  // src/rules/no-enum.ts
757
- import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
732
+ import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
758
733
  var DEFAULT_IGNORE_PATTERNS = [
759
734
  /[\\/]generated[\\/]/,
760
735
  /[\\/]openapi-gen[\\/]/,
@@ -774,7 +749,7 @@ function hasGeneratedMarker(sourceText) {
774
749
  const head = sourceText.slice(0, 1024);
775
750
  return /@generated\b/.test(head);
776
751
  }
777
- var no_enum_default = ESLintUtils5.RuleCreator(
752
+ var no_enum_default = ESLintUtils4.RuleCreator(
778
753
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
779
754
  )({
780
755
  name: "no-enum",
@@ -825,7 +800,7 @@ var no_enum_default = ESLintUtils5.RuleCreator(
825
800
  });
826
801
 
827
802
  // src/rules/no-insecure-random-id.ts
828
- import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
803
+ import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
829
804
  var STRONG_SECURITY_PATTERN = /token|secret|csrf|password|passwd|apikey|api[-_]?key|nonce|salt|uuid|authid/i;
830
805
  var NON_SECURITY_ID_PATTERN = /temp|tmp|cache|correlation|request|req|trace|execution|dev|hmr|mock|test|perf|marker/i;
831
806
  var PATH_OR_DOM_MARKER = /[\\/#]|\.[A-Za-z0-9]/;
@@ -966,7 +941,7 @@ function isConcatenatedIntoPathOrDomId(node) {
966
941
  collectStaticStringParts(top, parts);
967
942
  return parts.some((part) => PATH_OR_DOM_MARKER.test(part));
968
943
  }
969
- var no_insecure_random_id_default = ESLintUtils6.RuleCreator(
944
+ var no_insecure_random_id_default = ESLintUtils5.RuleCreator(
970
945
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
971
946
  )({
972
947
  name: "no-insecure-random-id",
@@ -1010,7 +985,7 @@ var no_insecure_random_id_default = ESLintUtils6.RuleCreator(
1010
985
  });
1011
986
 
1012
987
  // src/rules/no-json-stringify-error.ts
1013
- import { ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
988
+ import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
1014
989
  var ERROR_NAME_PATTERN = /^(e|err|error|ex|exc)$/i;
1015
990
  var ERROR_PROP_PATTERN = /^(cause|lastError|error|err|exception|originalError|innerError)$/i;
1016
991
  var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
@@ -1144,7 +1119,7 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
1144
1119
  function isJsonStringify(callee) {
1145
1120
  return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "stringify";
1146
1121
  }
1147
- var no_json_stringify_error_default = ESLintUtils7.RuleCreator(
1122
+ var no_json_stringify_error_default = ESLintUtils6.RuleCreator(
1148
1123
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1149
1124
  )({
1150
1125
  name: "no-json-stringify-error",
@@ -1194,7 +1169,7 @@ var no_json_stringify_error_default = ESLintUtils7.RuleCreator(
1194
1169
  });
1195
1170
 
1196
1171
  // src/rules/no-log-only-catch.ts
1197
- import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
1172
+ import { AST_NODE_TYPES as AST_NODE_TYPES5, ASTUtils, ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
1198
1173
 
1199
1174
  // src/rules/_logging.ts
1200
1175
  import "@typescript-eslint/utils";
@@ -1299,12 +1274,92 @@ function createLogMatcher(options = {}) {
1299
1274
  }
1300
1275
 
1301
1276
  // src/rules/no-log-only-catch.ts
1302
- var DEFAULT_IGNORE_PATTERNS2 = [
1303
- /\.test\./,
1304
- /\.spec\./,
1305
- /[\\/]__tests__[\\/]/
1306
- ];
1307
- var no_log_only_catch_default = ESLintUtils8.RuleCreator(
1277
+ var BENCHMARK_DIR_RE = /(?:^|[\\/])benchmarks?[\\/]/;
1278
+ var SINGLE_STATEMENT_HOSTS = /* @__PURE__ */ new Set([
1279
+ AST_NODE_TYPES5.DoWhileStatement,
1280
+ AST_NODE_TYPES5.ForInStatement,
1281
+ AST_NODE_TYPES5.ForOfStatement,
1282
+ AST_NODE_TYPES5.ForStatement,
1283
+ AST_NODE_TYPES5.IfStatement,
1284
+ AST_NODE_TYPES5.WhileStatement
1285
+ ]);
1286
+ var FUNCTION_TYPES = /* @__PURE__ */ new Set([
1287
+ AST_NODE_TYPES5.ArrowFunctionExpression,
1288
+ AST_NODE_TYPES5.FunctionDeclaration,
1289
+ AST_NODE_TYPES5.FunctionExpression
1290
+ ]);
1291
+ function statementSlot(node) {
1292
+ const parent = node.parent;
1293
+ if (parent === void 0) return null;
1294
+ let list;
1295
+ switch (parent.type) {
1296
+ case AST_NODE_TYPES5.BlockStatement:
1297
+ case AST_NODE_TYPES5.Program:
1298
+ case AST_NODE_TYPES5.StaticBlock:
1299
+ list = parent.body;
1300
+ break;
1301
+ case AST_NODE_TYPES5.SwitchCase:
1302
+ list = parent.consequent;
1303
+ break;
1304
+ default:
1305
+ return null;
1306
+ }
1307
+ const index = list.indexOf(node);
1308
+ return index === -1 ? null : { list, index };
1309
+ }
1310
+ function hasFollowingStatement(node) {
1311
+ for (let current = node; current !== void 0 && !FUNCTION_TYPES.has(current.type); current = current.parent) {
1312
+ const slot = statementSlot(current);
1313
+ if (slot !== null && slot.index < slot.list.length - 1) return true;
1314
+ }
1315
+ return false;
1316
+ }
1317
+ function fallbackFollowsTry(tryStatement) {
1318
+ const body = tryStatement.block.body;
1319
+ const last = body.at(-1);
1320
+ return last?.type === AST_NODE_TYPES5.ReturnStatement && hasFollowingStatement(tryStatement);
1321
+ }
1322
+ function isSeedValue(node) {
1323
+ const inner = node.type === AST_NODE_TYPES5.TSAsExpression ? node.expression : node;
1324
+ switch (inner.type) {
1325
+ case AST_NODE_TYPES5.Literal:
1326
+ return true;
1327
+ case AST_NODE_TYPES5.Identifier:
1328
+ return inner.name === "undefined";
1329
+ case AST_NODE_TYPES5.UnaryExpression:
1330
+ return inner.argument.type === AST_NODE_TYPES5.Literal;
1331
+ case AST_NODE_TYPES5.ArrayExpression:
1332
+ return inner.elements.length === 0;
1333
+ case AST_NODE_TYPES5.ObjectExpression:
1334
+ return inner.properties.length === 0;
1335
+ default:
1336
+ return false;
1337
+ }
1338
+ }
1339
+ function seededFallbackHandled(tryStatement, scope) {
1340
+ const slot = statementSlot(tryStatement);
1341
+ if (slot === null || slot.index === 0) return false;
1342
+ const previous = slot.list[slot.index - 1];
1343
+ if (previous?.type !== AST_NODE_TYPES5.VariableDeclaration || previous.kind === "const") {
1344
+ return false;
1345
+ }
1346
+ const declarator = previous.declarations[0];
1347
+ if (previous.declarations.length !== 1 || declarator === void 0) return false;
1348
+ if (declarator.id.type !== AST_NODE_TYPES5.Identifier) return false;
1349
+ if (declarator.init == null || !isSeedValue(declarator.init)) return false;
1350
+ const variable = ASTUtils.findVariable(scope, declarator.id.name);
1351
+ if (variable === null) return false;
1352
+ const [tryStart, tryEnd] = tryStatement.block.range;
1353
+ let writtenInTry = false;
1354
+ let readAfter = false;
1355
+ for (const reference of variable.references) {
1356
+ const [start] = reference.identifier.range;
1357
+ if (reference.isWrite() && start >= tryStart && start < tryEnd) writtenInTry = true;
1358
+ if (reference.isRead() && start >= tryStatement.range[1]) readAfter = true;
1359
+ }
1360
+ return writtenInTry && readAfter;
1361
+ }
1362
+ var no_log_only_catch_default = ESLintUtils7.RuleCreator(
1308
1363
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1309
1364
  )({
1310
1365
  name: "no-log-only-catch",
@@ -1329,26 +1384,40 @@ var no_log_only_catch_default = ESLintUtils8.RuleCreator(
1329
1384
  create(context, [loggingOptions]) {
1330
1385
  const matcher = createLogMatcher(loggingOptions);
1331
1386
  const filename = context.filename;
1387
+ const sourceCode = context.sourceCode;
1332
1388
  function isLoggingCallStatement(statement) {
1333
1389
  if (statement.type !== "ExpressionStatement") {
1334
1390
  return false;
1335
1391
  }
1336
1392
  return matcher.isLoggingCall(statement.expression);
1337
1393
  }
1338
- const isIgnoredByDefault = DEFAULT_IGNORE_PATTERNS2.some(
1339
- (re) => re.test(filename)
1340
- );
1341
- if (isIgnoredByDefault) {
1394
+ function hasCommentDirectlyAbove(node) {
1395
+ const above = sourceCode.getCommentsBefore(node).at(-1);
1396
+ return above !== void 0 && above.loc.end.line === node.loc.start.line - 1;
1397
+ }
1398
+ function hasAdjacentRationale(node) {
1399
+ const tryStatement = node.parent;
1400
+ if (hasCommentDirectlyAbove(tryStatement) || hasCommentDirectlyAbove(node)) return true;
1401
+ const block = tryStatement.parent;
1402
+ if (block?.type !== AST_NODE_TYPES5.BlockStatement || block.body.length !== 1 || block.parent === void 0 || !SINGLE_STATEMENT_HOSTS.has(block.parent.type)) {
1403
+ return false;
1404
+ }
1405
+ return hasCommentDirectlyAbove(block.parent);
1406
+ }
1407
+ if (isTestFile(filename) || BENCHMARK_DIR_RE.test(filename.replaceAll("\\", "/"))) {
1342
1408
  return {};
1343
1409
  }
1344
1410
  return {
1345
1411
  CatchClause(node) {
1346
1412
  const statements = node.body.body;
1347
- const isDocumented = context.sourceCode.getCommentsInside(node.body).length > 0;
1413
+ const isDocumented = sourceCode.getCommentsInside(node.body).length > 0 || hasAdjacentRationale(node);
1348
1414
  if (statements.length === 0) {
1349
1415
  if (isDocumented) {
1350
1416
  return;
1351
1417
  }
1418
+ if (fallbackFollowsTry(node.parent) || seededFallbackHandled(node.parent, sourceCode.getScope(node))) {
1419
+ return;
1420
+ }
1352
1421
  context.report({ node, messageId: "emptyCatch" });
1353
1422
  return;
1354
1423
  }
@@ -1367,11 +1436,12 @@ var no_log_only_catch_default = ESLintUtils8.RuleCreator(
1367
1436
  });
1368
1437
 
1369
1438
  // src/rules/no-raw-env.ts
1370
- import { ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
1439
+ import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
1371
1440
  var CONFIG_FILE_RE = /(^|[\\/])[\w.-]+\.config\.[cm]?[jt]sx?$/;
1372
1441
  var ENV_BOUNDARY_FILE_RE = /(^|[\\/])(?:env|client-env|server-env|client-settings|server-settings)\.[cm]?[jt]sx?$/;
1442
+ var ENV_VALIDATION_MARKER_RE = /\bcreateEnv\s*\(|\bz\.object\s*\(|\.(?:safeParse|parse)\s*\(/;
1373
1443
  function isValidatedEnvBoundary(filename, sourceText) {
1374
- return ENV_BOUNDARY_FILE_RE.test(filename.replaceAll("\\", "/")) && /\bz\.object\s*\(/.test(sourceText) && /\.parse\s*\(/.test(sourceText);
1444
+ return ENV_BOUNDARY_FILE_RE.test(filename.replaceAll("\\", "/")) && ENV_VALIDATION_MARKER_RE.test(sourceText);
1375
1445
  }
1376
1446
  function isProcessEnv(node) {
1377
1447
  return !node.computed && node.object.type === "Identifier" && node.object.name === "process" && node.property.type === "Identifier" && node.property.name === "env";
@@ -1386,9 +1456,15 @@ var BUILD_TIME_CONSTANTS = /* @__PURE__ */ new Set([
1386
1456
  "PROD",
1387
1457
  "SSR"
1388
1458
  ]);
1389
- function isBuildTimeConstantAccess(node) {
1459
+ var PLATFORM_MARKERS = /* @__PURE__ */ new Set([
1460
+ "NEXT_RUNTIME",
1461
+ "VERCEL",
1462
+ "VERCEL_ENV",
1463
+ "CI"
1464
+ ]);
1465
+ function isExemptVariableAccess(node) {
1390
1466
  const parent = node.parent;
1391
- return parent.type === "MemberExpression" && parent.object === node && !parent.computed && parent.property.type === "Identifier" && BUILD_TIME_CONSTANTS.has(parent.property.name);
1467
+ 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));
1392
1468
  }
1393
1469
  function isWriteTarget(node) {
1394
1470
  const access = node.parent.type === "MemberExpression" && node.parent.object === node ? node.parent : node;
@@ -1405,7 +1481,7 @@ function isWholeEnvSpread(node) {
1405
1481
  const parent = node.parent;
1406
1482
  return parent.type === "SpreadElement" && parent.argument === node;
1407
1483
  }
1408
- var no_raw_env_default = ESLintUtils9.RuleCreator(
1484
+ var no_raw_env_default = ESLintUtils8.RuleCreator(
1409
1485
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1410
1486
  )({
1411
1487
  name: "no-raw-env",
@@ -1427,7 +1503,7 @@ var no_raw_env_default = ESLintUtils9.RuleCreator(
1427
1503
  }
1428
1504
  return {
1429
1505
  MemberExpression(node) {
1430
- if ((isProcessEnv(node) || isImportMetaEnv(node)) && !isBuildTimeConstantAccess(node) && !isWriteTarget(node) && !isWholeEnvSpread(node)) {
1506
+ if ((isProcessEnv(node) || isImportMetaEnv(node)) && !isExemptVariableAccess(node) && !isWriteTarget(node) && !isWholeEnvSpread(node)) {
1431
1507
  context.report({
1432
1508
  node,
1433
1509
  messageId: "noRawEnv"
@@ -1440,14 +1516,14 @@ var no_raw_env_default = ESLintUtils9.RuleCreator(
1440
1516
 
1441
1517
  // src/rules/no-sentinel-return-on-catch.ts
1442
1518
  import {
1443
- ESLintUtils as ESLintUtils10,
1444
- AST_NODE_TYPES as AST_NODE_TYPES5
1519
+ ESLintUtils as ESLintUtils9,
1520
+ AST_NODE_TYPES as AST_NODE_TYPES6
1445
1521
  } from "@typescript-eslint/utils";
1446
1522
  function sentinelKind(arg) {
1447
1523
  if (arg === null) {
1448
1524
  return null;
1449
1525
  }
1450
- if (arg.type === AST_NODE_TYPES5.Literal) {
1526
+ if (arg.type === AST_NODE_TYPES6.Literal) {
1451
1527
  if (arg.value === null) {
1452
1528
  return "nullish";
1453
1529
  }
@@ -1459,13 +1535,13 @@ function sentinelKind(arg) {
1459
1535
  }
1460
1536
  return null;
1461
1537
  }
1462
- if (arg.type === AST_NODE_TYPES5.Identifier && arg.name === "undefined") {
1538
+ if (arg.type === AST_NODE_TYPES6.Identifier && arg.name === "undefined") {
1463
1539
  return "nullish";
1464
1540
  }
1465
- if (arg.type === AST_NODE_TYPES5.ArrayExpression) {
1541
+ if (arg.type === AST_NODE_TYPES6.ArrayExpression) {
1466
1542
  return "array";
1467
1543
  }
1468
- if (arg.type === AST_NODE_TYPES5.ObjectExpression) {
1544
+ if (arg.type === AST_NODE_TYPES6.ObjectExpression) {
1469
1545
  return "object";
1470
1546
  }
1471
1547
  return null;
@@ -1474,25 +1550,25 @@ function isSentinelArgument(arg) {
1474
1550
  if (arg === null) {
1475
1551
  return false;
1476
1552
  }
1477
- if (arg.type === AST_NODE_TYPES5.Literal && arg.value === null) {
1553
+ if (arg.type === AST_NODE_TYPES6.Literal && arg.value === null) {
1478
1554
  return true;
1479
1555
  }
1480
- if (arg.type === AST_NODE_TYPES5.Literal && arg.value === false) {
1556
+ if (arg.type === AST_NODE_TYPES6.Literal && arg.value === false) {
1481
1557
  return true;
1482
1558
  }
1483
- if (arg.type === AST_NODE_TYPES5.Identifier && arg.name === "undefined") {
1559
+ if (arg.type === AST_NODE_TYPES6.Identifier && arg.name === "undefined") {
1484
1560
  return true;
1485
1561
  }
1486
- if (arg.type === AST_NODE_TYPES5.ArrayExpression && arg.elements.length === 0) {
1562
+ if (arg.type === AST_NODE_TYPES6.ArrayExpression && arg.elements.length === 0) {
1487
1563
  return true;
1488
1564
  }
1489
- if (arg.type === AST_NODE_TYPES5.ObjectExpression && arg.properties.length === 0) {
1565
+ if (arg.type === AST_NODE_TYPES6.ObjectExpression && arg.properties.length === 0) {
1490
1566
  return true;
1491
1567
  }
1492
1568
  return false;
1493
1569
  }
1494
1570
  function isFunctionNode(node) {
1495
- return node.type === AST_NODE_TYPES5.FunctionDeclaration || node.type === AST_NODE_TYPES5.FunctionExpression || node.type === AST_NODE_TYPES5.ArrowFunctionExpression;
1571
+ return node.type === AST_NODE_TYPES6.FunctionDeclaration || node.type === AST_NODE_TYPES6.FunctionExpression || node.type === AST_NODE_TYPES6.ArrowFunctionExpression;
1496
1572
  }
1497
1573
  function isNode(value) {
1498
1574
  return typeof value === "object" && value !== null && typeof value.type === "string";
@@ -1532,24 +1608,24 @@ function walkWithinScope(node, visit) {
1532
1608
  function containsThrow(node) {
1533
1609
  return walkWithinScope(
1534
1610
  node,
1535
- (current) => current.type === AST_NODE_TYPES5.ThrowStatement
1611
+ (current) => current.type === AST_NODE_TYPES6.ThrowStatement
1536
1612
  );
1537
1613
  }
1538
1614
  function bindsName(param, name) {
1539
1615
  switch (param.type) {
1540
- case AST_NODE_TYPES5.Identifier:
1616
+ case AST_NODE_TYPES6.Identifier:
1541
1617
  return param.name === name;
1542
- case AST_NODE_TYPES5.AssignmentPattern:
1618
+ case AST_NODE_TYPES6.AssignmentPattern:
1543
1619
  return bindsName(param.left, name);
1544
- case AST_NODE_TYPES5.RestElement:
1620
+ case AST_NODE_TYPES6.RestElement:
1545
1621
  return bindsName(param.argument, name);
1546
- case AST_NODE_TYPES5.ArrayPattern:
1622
+ case AST_NODE_TYPES6.ArrayPattern:
1547
1623
  return param.elements.some(
1548
1624
  (element) => element !== null && bindsName(element, name)
1549
1625
  );
1550
- case AST_NODE_TYPES5.ObjectPattern:
1626
+ case AST_NODE_TYPES6.ObjectPattern:
1551
1627
  return param.properties.some(
1552
- (property) => property.type === AST_NODE_TYPES5.RestElement ? bindsName(property.argument, name) : bindsName(property.value, name)
1628
+ (property) => property.type === AST_NODE_TYPES6.RestElement ? bindsName(property.argument, name) : bindsName(property.value, name)
1553
1629
  );
1554
1630
  default:
1555
1631
  return false;
@@ -1564,7 +1640,7 @@ function subtreeReadsName(node, name) {
1564
1640
  if (found) {
1565
1641
  return;
1566
1642
  }
1567
- if (current.type === AST_NODE_TYPES5.Identifier && current.name === name) {
1643
+ if (current.type === AST_NODE_TYPES6.Identifier && current.name === name) {
1568
1644
  found = true;
1569
1645
  return;
1570
1646
  }
@@ -1575,10 +1651,10 @@ function subtreeReadsName(node, name) {
1575
1651
  if (key === "parent") {
1576
1652
  continue;
1577
1653
  }
1578
- if (key === "key" && current.type === AST_NODE_TYPES5.Property && !current.computed) {
1654
+ if (key === "key" && current.type === AST_NODE_TYPES6.Property && !current.computed) {
1579
1655
  continue;
1580
1656
  }
1581
- if (key === "property" && current.type === AST_NODE_TYPES5.MemberExpression && !current.computed) {
1657
+ if (key === "property" && current.type === AST_NODE_TYPES6.MemberExpression && !current.computed) {
1582
1658
  continue;
1583
1659
  }
1584
1660
  const value = current[key];
@@ -1611,10 +1687,10 @@ var SAFE_PARSE_CONSTRUCTORS = /* @__PURE__ */ new Set([
1611
1687
  "URLPattern"
1612
1688
  ]);
1613
1689
  function isParseShapedNode(node) {
1614
- if (node.type === AST_NODE_TYPES5.CallExpression && node.callee.type === AST_NODE_TYPES5.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES5.Identifier) {
1690
+ if (node.type === AST_NODE_TYPES6.CallExpression && node.callee.type === AST_NODE_TYPES6.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES6.Identifier) {
1615
1691
  return node.callee.property.name === "parse";
1616
1692
  }
1617
- if (node.type === AST_NODE_TYPES5.NewExpression && node.callee.type === AST_NODE_TYPES5.Identifier) {
1693
+ if (node.type === AST_NODE_TYPES6.NewExpression && node.callee.type === AST_NODE_TYPES6.Identifier) {
1618
1694
  return SAFE_PARSE_CONSTRUCTORS.has(node.callee.name);
1619
1695
  }
1620
1696
  return false;
@@ -1625,10 +1701,10 @@ var BODY_DECODE_METHODS = /* @__PURE__ */ new Set([
1625
1701
  "arrayBuffer"
1626
1702
  ]);
1627
1703
  function isBodyDecodeNode(node) {
1628
- return node.type === AST_NODE_TYPES5.CallExpression && node.callee.type === AST_NODE_TYPES5.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES5.Identifier && BODY_DECODE_METHODS.has(node.callee.property.name);
1704
+ return node.type === AST_NODE_TYPES6.CallExpression && node.callee.type === AST_NODE_TYPES6.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES6.Identifier && BODY_DECODE_METHODS.has(node.callee.property.name);
1629
1705
  }
1630
1706
  function returnsMatching(stmt, predicate) {
1631
- return stmt.type === AST_NODE_TYPES5.ReturnStatement && stmt.argument !== null && walkWithinScope(stmt.argument, predicate);
1707
+ return stmt.type === AST_NODE_TYPES6.ReturnStatement && stmt.argument !== null && walkWithinScope(stmt.argument, predicate);
1632
1708
  }
1633
1709
  function enclosingReturnTypeNode(node) {
1634
1710
  let current = node.parent;
@@ -1646,11 +1722,11 @@ function enclosingFunctionName(node) {
1646
1722
  let current = node.parent;
1647
1723
  while (current !== void 0 && current !== null) {
1648
1724
  if (isFunctionNode(current)) {
1649
- if ("id" in current && isNode(current.id) && current.id.type === AST_NODE_TYPES5.Identifier) {
1725
+ if ("id" in current && isNode(current.id) && current.id.type === AST_NODE_TYPES6.Identifier) {
1650
1726
  return current.id.name;
1651
1727
  }
1652
1728
  const parent = current.parent;
1653
- if (parent?.type === AST_NODE_TYPES5.VariableDeclarator && parent.id.type === AST_NODE_TYPES5.Identifier) {
1729
+ if (parent?.type === AST_NODE_TYPES6.VariableDeclarator && parent.id.type === AST_NODE_TYPES6.Identifier) {
1654
1730
  return parent.id.name;
1655
1731
  }
1656
1732
  return null;
@@ -1671,10 +1747,10 @@ function isDeclaredBooleanPredicate(catchNode, kind) {
1671
1747
  return false;
1672
1748
  }
1673
1749
  let declared = enclosingReturnTypeNode(catchNode);
1674
- if (declared?.type === AST_NODE_TYPES5.TSTypeReference && declared.typeName.type === AST_NODE_TYPES5.Identifier && declared.typeName.name === "Promise") {
1750
+ if (declared?.type === AST_NODE_TYPES6.TSTypeReference && declared.typeName.type === AST_NODE_TYPES6.Identifier && declared.typeName.name === "Promise") {
1675
1751
  declared = declared.typeArguments?.params[0] ?? null;
1676
1752
  }
1677
- return declared?.type === AST_NODE_TYPES5.TSBooleanKeyword;
1753
+ return declared?.type === AST_NODE_TYPES6.TSBooleanKeyword;
1678
1754
  }
1679
1755
  function tryReturnsSafeParse(catchNode) {
1680
1756
  const tryBlock = tryBlockOf(catchNode);
@@ -1690,7 +1766,7 @@ function tryReturnsSafeParse(catchNode) {
1690
1766
  function enclosingFunctionBody(node) {
1691
1767
  let current = node.parent;
1692
1768
  while (current !== void 0 && current !== null) {
1693
- if (isFunctionNode(current) && "body" in current && isNode(current.body) && current.body.type === AST_NODE_TYPES5.BlockStatement) {
1769
+ if (isFunctionNode(current) && "body" in current && isNode(current.body) && current.body.type === AST_NODE_TYPES6.BlockStatement) {
1694
1770
  return current.body;
1695
1771
  }
1696
1772
  current = current.parent;
@@ -1703,7 +1779,7 @@ function functionReturnsSameSentinelKindElsewhere(catchNode, kind) {
1703
1779
  return false;
1704
1780
  }
1705
1781
  return walkWithinScope(functionBody, (current) => {
1706
- if (current.type !== AST_NODE_TYPES5.ReturnStatement) {
1782
+ if (current.type !== AST_NODE_TYPES6.ReturnStatement) {
1707
1783
  return false;
1708
1784
  }
1709
1785
  if (isWithin(current, catchNode.body)) {
@@ -1722,13 +1798,13 @@ function returnedSentinelKinds(arg) {
1722
1798
  kinds.add(direct);
1723
1799
  return kinds;
1724
1800
  }
1725
- if (arg.type === AST_NODE_TYPES5.ConditionalExpression) {
1801
+ if (arg.type === AST_NODE_TYPES6.ConditionalExpression) {
1726
1802
  for (const branch of [arg.consequent, arg.alternate]) {
1727
1803
  for (const nested of returnedSentinelKinds(branch)) {
1728
1804
  kinds.add(nested);
1729
1805
  }
1730
1806
  }
1731
- } else if (arg.type === AST_NODE_TYPES5.LogicalExpression && (arg.operator === "??" || arg.operator === "||")) {
1807
+ } else if (arg.type === AST_NODE_TYPES6.LogicalExpression && (arg.operator === "??" || arg.operator === "||")) {
1732
1808
  for (const nested of returnedSentinelKinds(arg.right)) {
1733
1809
  kinds.add(nested);
1734
1810
  }
@@ -1745,7 +1821,7 @@ function isWithin(node, ancestor) {
1745
1821
  }
1746
1822
  return false;
1747
1823
  }
1748
- var no_sentinel_return_on_catch_default = ESLintUtils10.RuleCreator(
1824
+ var no_sentinel_return_on_catch_default = ESLintUtils9.RuleCreator(
1749
1825
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1750
1826
  )({
1751
1827
  name: "no-sentinel-return-on-catch",
@@ -1773,7 +1849,7 @@ var no_sentinel_return_on_catch_default = ESLintUtils10.RuleCreator(
1773
1849
  const matcher = createLogMatcher(loggingOptions);
1774
1850
  function logsOrReportsError(catchBody, caughtName) {
1775
1851
  return walkWithinScope(catchBody, (current) => {
1776
- if (current.type !== AST_NODE_TYPES5.CallExpression) {
1852
+ if (current.type !== AST_NODE_TYPES6.CallExpression) {
1777
1853
  return false;
1778
1854
  }
1779
1855
  if (matcher.isLoggingCall(current)) {
@@ -1790,7 +1866,7 @@ var no_sentinel_return_on_catch_default = ESLintUtils10.RuleCreator(
1790
1866
  return;
1791
1867
  }
1792
1868
  const last = body[body.length - 1];
1793
- if (last === void 0 || last.type !== AST_NODE_TYPES5.ReturnStatement) {
1869
+ if (last === void 0 || last.type !== AST_NODE_TYPES6.ReturnStatement) {
1794
1870
  return;
1795
1871
  }
1796
1872
  if (!isSentinelArgument(last.argument)) {
@@ -1799,7 +1875,7 @@ var no_sentinel_return_on_catch_default = ESLintUtils10.RuleCreator(
1799
1875
  if (containsThrow(node.body)) {
1800
1876
  return;
1801
1877
  }
1802
- const caughtName = node.param?.type === AST_NODE_TYPES5.Identifier ? node.param.name : null;
1878
+ const caughtName = node.param?.type === AST_NODE_TYPES6.Identifier ? node.param.name : null;
1803
1879
  if (logsOrReportsError(node.body, caughtName)) {
1804
1880
  return;
1805
1881
  }
@@ -1826,7 +1902,7 @@ var no_sentinel_return_on_catch_default = ESLintUtils10.RuleCreator(
1826
1902
  });
1827
1903
 
1828
1904
  // src/rules/no-string-concat-in-loop.ts
1829
- import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
1905
+ import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
1830
1906
  var LOOP_NODE_TYPES = /* @__PURE__ */ new Set([
1831
1907
  "ForStatement",
1832
1908
  "ForOfStatement",
@@ -1911,7 +1987,7 @@ function enclosingLoop(node) {
1911
1987
  }
1912
1988
  return null;
1913
1989
  }
1914
- var no_string_concat_in_loop_default = ESLintUtils11.RuleCreator(
1990
+ var no_string_concat_in_loop_default = ESLintUtils10.RuleCreator(
1915
1991
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1916
1992
  )({
1917
1993
  name: "no-string-concat-in-loop",
@@ -1975,8 +2051,8 @@ var no_string_concat_in_loop_default = ESLintUtils11.RuleCreator(
1975
2051
 
1976
2052
  // src/rules/no-unnecessary-use-client.ts
1977
2053
  import {
1978
- AST_NODE_TYPES as AST_NODE_TYPES6,
1979
- ESLintUtils as ESLintUtils12
2054
+ AST_NODE_TYPES as AST_NODE_TYPES7,
2055
+ ESLintUtils as ESLintUtils11
1980
2056
  } from "@typescript-eslint/utils";
1981
2057
  var HOOK_REGEX = /^use([A-Z]|$)/;
1982
2058
  var EVENT_PROP_REGEX = /^on[A-Z]/;
@@ -2003,13 +2079,13 @@ var CLIENT_ONLY_PACKAGES_REGEX = /^(?:@radix-ui\/|framer-motion|react-dom|react-
2003
2079
  var isBareSpecifier = (source) => !source.startsWith(".") && !source.startsWith("/") && !source.startsWith("@/") && !source.startsWith("~");
2004
2080
  var jsxRootName = (name) => {
2005
2081
  let current = name;
2006
- while (current.type === AST_NODE_TYPES6.JSXMemberExpression) {
2082
+ while (current.type === AST_NODE_TYPES7.JSXMemberExpression) {
2007
2083
  current = current.object;
2008
2084
  }
2009
- return current.type === AST_NODE_TYPES6.JSXIdentifier ? current.name : "";
2085
+ return current.type === AST_NODE_TYPES7.JSXIdentifier ? current.name : "";
2010
2086
  };
2011
2087
  var subtreeReadsImportedBinding = (node, imported) => {
2012
- if (node.type === AST_NODE_TYPES6.Identifier) {
2088
+ if (node.type === AST_NODE_TYPES7.Identifier) {
2013
2089
  return imported.has(node.name);
2014
2090
  }
2015
2091
  for (const key of Object.keys(node)) {
@@ -2024,16 +2100,16 @@ var subtreeReadsImportedBinding = (node, imported) => {
2024
2100
  return false;
2025
2101
  };
2026
2102
  var isUseClientDirective = (node) => {
2027
- return node.type === AST_NODE_TYPES6.ExpressionStatement && node.expression.type === AST_NODE_TYPES6.Literal && node.expression.value === "use client";
2103
+ return node.type === AST_NODE_TYPES7.ExpressionStatement && node.expression.type === AST_NODE_TYPES7.Literal && node.expression.value === "use client";
2028
2104
  };
2029
2105
  var isGlobalReference = (node, context) => {
2030
2106
  if (!BROWSER_GLOBALS.has(node.name)) return false;
2031
2107
  const parent = node.parent;
2032
2108
  if (parent !== void 0) {
2033
- if (parent.type === AST_NODE_TYPES6.MemberExpression && parent.property === node && !parent.computed) {
2109
+ if (parent.type === AST_NODE_TYPES7.MemberExpression && parent.property === node && !parent.computed) {
2034
2110
  return false;
2035
2111
  }
2036
- if (parent.type === AST_NODE_TYPES6.Property && parent.key === node && !parent.computed) {
2112
+ if (parent.type === AST_NODE_TYPES7.Property && parent.key === node && !parent.computed) {
2037
2113
  return false;
2038
2114
  }
2039
2115
  if (parent.type.startsWith("TS")) {
@@ -2050,7 +2126,7 @@ var isGlobalReference = (node, context) => {
2050
2126
  }
2051
2127
  return true;
2052
2128
  };
2053
- var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2129
+ var no_unnecessary_use_client_default = ESLintUtils11.RuleCreator(
2054
2130
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2055
2131
  )({
2056
2132
  name: "no-unnecessary-use-client",
@@ -2075,13 +2151,13 @@ var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2075
2151
  const importedLocals = /* @__PURE__ */ new Set();
2076
2152
  const externalLocals = /* @__PURE__ */ new Set();
2077
2153
  const markIfHookOrContext = (callee) => {
2078
- if (callee.type === AST_NODE_TYPES6.Identifier) {
2154
+ if (callee.type === AST_NODE_TYPES7.Identifier) {
2079
2155
  if (HOOK_REGEX.test(callee.name) || callee.name === "createContext") {
2080
2156
  hasClientIndicator = true;
2081
2157
  }
2082
2158
  return;
2083
2159
  }
2084
- if (callee.type === AST_NODE_TYPES6.MemberExpression && callee.property.type === AST_NODE_TYPES6.Identifier) {
2160
+ if (callee.type === AST_NODE_TYPES7.MemberExpression && callee.property.type === AST_NODE_TYPES7.Identifier) {
2085
2161
  const name = callee.property.name;
2086
2162
  if (HOOK_REGEX.test(name) || name === "createContext") {
2087
2163
  hasClientIndicator = true;
@@ -2091,7 +2167,7 @@ var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2091
2167
  return {
2092
2168
  Program(node) {
2093
2169
  for (const stmt of node.body) {
2094
- if (stmt.type !== AST_NODE_TYPES6.ExpressionStatement) break;
2170
+ if (stmt.type !== AST_NODE_TYPES7.ExpressionStatement) break;
2095
2171
  if (isUseClientDirective(stmt)) {
2096
2172
  directiveNode = stmt;
2097
2173
  break;
@@ -2104,7 +2180,7 @@ var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2104
2180
  },
2105
2181
  JSXAttribute(node) {
2106
2182
  if (directiveNode === null) return;
2107
- if (node.name.type === AST_NODE_TYPES6.JSXIdentifier && EVENT_PROP_REGEX.test(node.name.name)) {
2183
+ if (node.name.type === AST_NODE_TYPES7.JSXIdentifier && EVENT_PROP_REGEX.test(node.name.name)) {
2108
2184
  hasClientIndicator = true;
2109
2185
  }
2110
2186
  },
@@ -2171,8 +2247,8 @@ var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2171
2247
  });
2172
2248
 
2173
2249
  // src/rules/prefer-discriminated-union.ts
2174
- import { ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
2175
- import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
2250
+ import { ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
2251
+ import { AST_NODE_TYPES as AST_NODE_TYPES8 } from "@typescript-eslint/utils";
2176
2252
  var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2177
2253
  "success",
2178
2254
  "ok",
@@ -2182,27 +2258,27 @@ var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2182
2258
  ]);
2183
2259
  var MIN_OPTIONAL_MEMBERS = 2;
2184
2260
  function getMemberName(member) {
2185
- if (member.type !== AST_NODE_TYPES7.TSPropertySignature) {
2261
+ if (member.type !== AST_NODE_TYPES8.TSPropertySignature) {
2186
2262
  return null;
2187
2263
  }
2188
2264
  const { key } = member;
2189
- if (key.type === AST_NODE_TYPES7.Identifier) {
2265
+ if (key.type === AST_NODE_TYPES8.Identifier) {
2190
2266
  return key.name;
2191
2267
  }
2192
- if (key.type === AST_NODE_TYPES7.Literal && typeof key.value === "string") {
2268
+ if (key.type === AST_NODE_TYPES8.Literal && typeof key.value === "string") {
2193
2269
  return key.value;
2194
2270
  }
2195
2271
  return null;
2196
2272
  }
2197
2273
  function isBooleanTyped(member) {
2198
- return member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES7.TSBooleanKeyword;
2274
+ return member.typeAnnotation?.typeAnnotation.type === AST_NODE_TYPES8.TSBooleanKeyword;
2199
2275
  }
2200
2276
  function looksLikeMutuallyExclusiveState(typeLiteral) {
2201
2277
  let hasStatusBoolean = false;
2202
2278
  let optionalCount = 0;
2203
2279
  let optionalPayloadCount = 0;
2204
2280
  for (const member of typeLiteral.members) {
2205
- if (member.type !== AST_NODE_TYPES7.TSPropertySignature) {
2281
+ if (member.type !== AST_NODE_TYPES8.TSPropertySignature) {
2206
2282
  continue;
2207
2283
  }
2208
2284
  if (member.optional) {
@@ -2218,7 +2294,7 @@ function looksLikeMutuallyExclusiveState(typeLiteral) {
2218
2294
  }
2219
2295
  return hasStatusBoolean && optionalCount >= MIN_OPTIONAL_MEMBERS && optionalPayloadCount >= 1;
2220
2296
  }
2221
- var prefer_discriminated_union_default = ESLintUtils13.RuleCreator(
2297
+ var prefer_discriminated_union_default = ESLintUtils12.RuleCreator(
2222
2298
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2223
2299
  )({
2224
2300
  name: "prefer-discriminated-union",
@@ -2246,7 +2322,7 @@ var prefer_discriminated_union_default = ESLintUtils13.RuleCreator(
2246
2322
  TSInterfaceDeclaration(node) {
2247
2323
  const synthetic = {
2248
2324
  ...node.body,
2249
- type: AST_NODE_TYPES7.TSTypeLiteral,
2325
+ type: AST_NODE_TYPES8.TSTypeLiteral,
2250
2326
  members: node.body.body
2251
2327
  };
2252
2328
  checkTypeLiteral(synthetic, node);
@@ -2260,15 +2336,15 @@ var prefer_discriminated_union_default = ESLintUtils13.RuleCreator(
2260
2336
 
2261
2337
  // src/rules/prefer-schema-for-api-payload.ts
2262
2338
  import {
2263
- AST_NODE_TYPES as AST_NODE_TYPES8,
2264
- ESLintUtils as ESLintUtils14
2339
+ AST_NODE_TYPES as AST_NODE_TYPES9,
2340
+ ESLintUtils as ESLintUtils13
2265
2341
  } from "@typescript-eslint/utils";
2266
2342
  var unwrap = (node) => {
2267
2343
  let current = node;
2268
2344
  while (current !== null && current !== void 0) {
2269
- if (current.type === AST_NODE_TYPES8.TSAsExpression || current.type === AST_NODE_TYPES8.TSTypeAssertion || current.type === AST_NODE_TYPES8.TSNonNullExpression || current.type === AST_NODE_TYPES8.TSSatisfiesExpression) {
2345
+ if (current.type === AST_NODE_TYPES9.TSAsExpression || current.type === AST_NODE_TYPES9.TSTypeAssertion || current.type === AST_NODE_TYPES9.TSNonNullExpression || current.type === AST_NODE_TYPES9.TSSatisfiesExpression) {
2270
2346
  current = current.expression;
2271
- } else if (current.type === AST_NODE_TYPES8.ChainExpression) {
2347
+ } else if (current.type === AST_NODE_TYPES9.ChainExpression) {
2272
2348
  current = current.expression;
2273
2349
  } else {
2274
2350
  break;
@@ -2276,28 +2352,40 @@ var unwrap = (node) => {
2276
2352
  }
2277
2353
  return current ?? null;
2278
2354
  };
2355
+ var PROMISE_CHAIN_METHODS = /* @__PURE__ */ new Set([
2356
+ "then",
2357
+ "catch",
2358
+ "finally"
2359
+ ]);
2360
+ var isSchemaParseReference = (node) => {
2361
+ const inner = unwrap(node);
2362
+ return inner !== null && inner.type === AST_NODE_TYPES9.MemberExpression && !inner.computed && inner.property.type === AST_NODE_TYPES9.Identifier && (inner.property.name === "parse" || inner.property.name === "safeParse");
2363
+ };
2279
2364
  var isRawPayloadSource = (node) => {
2280
2365
  let current = unwrap(node);
2281
2366
  if (current === null) return false;
2282
- if (current.type === AST_NODE_TYPES8.AwaitExpression) {
2367
+ if (current.type === AST_NODE_TYPES9.AwaitExpression) {
2283
2368
  current = unwrap(current.argument);
2284
2369
  }
2285
- if (current === null || current.type !== AST_NODE_TYPES8.CallExpression) {
2370
+ if (current === null || current.type !== AST_NODE_TYPES9.CallExpression) {
2286
2371
  return false;
2287
2372
  }
2288
2373
  const callee = unwrap(current.callee);
2289
- if (callee === null || callee.type !== AST_NODE_TYPES8.MemberExpression) {
2374
+ if (callee === null || callee.type !== AST_NODE_TYPES9.MemberExpression) {
2290
2375
  return false;
2291
2376
  }
2292
2377
  const property = unwrap(callee.property);
2293
- if (property === null || property.type !== AST_NODE_TYPES8.Identifier) {
2378
+ if (property === null || property.type !== AST_NODE_TYPES9.Identifier) {
2294
2379
  return false;
2295
2380
  }
2296
2381
  if (property.name === "json") {
2297
2382
  return true;
2298
2383
  }
2384
+ if (PROMISE_CHAIN_METHODS.has(property.name)) {
2385
+ return !current.arguments.some(isSchemaParseReference) && isRawPayloadSource(callee.object);
2386
+ }
2299
2387
  const object = unwrap(callee.object);
2300
- return property.name === "parse" && object !== null && object.type === AST_NODE_TYPES8.Identifier && object.name === "JSON" && // ...but not `JSON.parse(readFileSync(p, "utf8"))` — see isLocalFileRead.
2388
+ return property.name === "parse" && object !== null && object.type === AST_NODE_TYPES9.Identifier && object.name === "JSON" && // ...but not `JSON.parse(readFileSync(p, "utf8"))` — see isLocalFileRead.
2301
2389
  !isLocalFileRead(current.arguments[0]);
2302
2390
  };
2303
2391
  var FILE_READ_RE = /^(readFile|readFileSync|readJson|readJsonSync|readJSON)$/;
@@ -2305,9 +2393,9 @@ var isLocalFileRead = (node) => {
2305
2393
  let found = false;
2306
2394
  const visit = (current) => {
2307
2395
  if (found || current === null || current === void 0) return;
2308
- if (current.type === AST_NODE_TYPES8.CallExpression) {
2396
+ if (current.type === AST_NODE_TYPES9.CallExpression) {
2309
2397
  const callee = unwrap(current.callee);
2310
- const name = callee?.type === AST_NODE_TYPES8.Identifier ? callee.name : callee?.type === AST_NODE_TYPES8.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES8.Identifier ? callee.property.name : null;
2398
+ const name = callee?.type === AST_NODE_TYPES9.Identifier ? callee.name : callee?.type === AST_NODE_TYPES9.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES9.Identifier ? callee.property.name : null;
2311
2399
  if (name !== null && FILE_READ_RE.test(name)) {
2312
2400
  found = true;
2313
2401
  return;
@@ -2329,15 +2417,15 @@ var isLocalFileRead = (node) => {
2329
2417
  var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
2330
2418
  var isInsideAssertion = (node) => {
2331
2419
  for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
2332
- if (current.type !== AST_NODE_TYPES8.CallExpression) continue;
2420
+ if (current.type !== AST_NODE_TYPES9.CallExpression) continue;
2333
2421
  let callee = current.callee;
2334
- while (callee.type === AST_NODE_TYPES8.MemberExpression) {
2422
+ while (callee.type === AST_NODE_TYPES9.MemberExpression) {
2335
2423
  callee = callee.object;
2336
2424
  }
2337
- if (callee.type === AST_NODE_TYPES8.CallExpression) {
2425
+ if (callee.type === AST_NODE_TYPES9.CallExpression) {
2338
2426
  callee = callee.callee;
2339
2427
  }
2340
- if (callee.type === AST_NODE_TYPES8.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
2428
+ if (callee.type === AST_NODE_TYPES9.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
2341
2429
  return true;
2342
2430
  }
2343
2431
  }
@@ -2352,23 +2440,43 @@ var findVariable2 = (scope, name) => {
2352
2440
  }
2353
2441
  return null;
2354
2442
  };
2355
- var GUARD_NAME_RE = /^is[A-Z]/;
2443
+ var GUARD_NAME_RE = /^(?:is|validate|parse|assert|decode|coerce)[A-Z]/;
2444
+ var isValidationRead = (node) => {
2445
+ let current = node;
2446
+ let parent = current.parent;
2447
+ while (parent !== null && parent !== void 0 && (parent.type === AST_NODE_TYPES9.TSAsExpression || parent.type === AST_NODE_TYPES9.TSTypeAssertion || parent.type === AST_NODE_TYPES9.TSNonNullExpression || parent.type === AST_NODE_TYPES9.TSSatisfiesExpression || parent.type === AST_NODE_TYPES9.ChainExpression)) {
2448
+ current = parent;
2449
+ parent = parent.parent;
2450
+ }
2451
+ if (parent === null || parent === void 0) return false;
2452
+ if (parent.type === AST_NODE_TYPES9.UnaryExpression && parent.operator === "typeof" && parent.argument === current) {
2453
+ return true;
2454
+ }
2455
+ if (parent.type !== AST_NODE_TYPES9.CallExpression || !parent.arguments.some((arg) => arg === current)) {
2456
+ return false;
2457
+ }
2458
+ const callee = parent.callee;
2459
+ if (callee.type === AST_NODE_TYPES9.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES9.Identifier && callee.object.name === "Array" && callee.property.type === AST_NODE_TYPES9.Identifier && callee.property.name === "isArray") {
2460
+ return parent.arguments.length === 1;
2461
+ }
2462
+ return callee.type === AST_NODE_TYPES9.Identifier && GUARD_NAME_RE.test(callee.name);
2463
+ };
2356
2464
  var isGuardTestPosition = (node) => {
2357
2465
  let current = node;
2358
2466
  let parent = current.parent;
2359
2467
  while (parent !== void 0 && parent !== null) {
2360
2468
  switch (parent.type) {
2361
- case AST_NODE_TYPES8.UnaryExpression:
2362
- case AST_NODE_TYPES8.LogicalExpression:
2363
- case AST_NODE_TYPES8.ChainExpression:
2469
+ case AST_NODE_TYPES9.UnaryExpression:
2470
+ case AST_NODE_TYPES9.LogicalExpression:
2471
+ case AST_NODE_TYPES9.ChainExpression:
2364
2472
  current = parent;
2365
2473
  parent = parent.parent;
2366
2474
  continue;
2367
- case AST_NODE_TYPES8.IfStatement:
2368
- case AST_NODE_TYPES8.ConditionalExpression:
2369
- case AST_NODE_TYPES8.WhileStatement:
2370
- case AST_NODE_TYPES8.DoWhileStatement:
2371
- case AST_NODE_TYPES8.ForStatement:
2475
+ case AST_NODE_TYPES9.IfStatement:
2476
+ case AST_NODE_TYPES9.ConditionalExpression:
2477
+ case AST_NODE_TYPES9.WhileStatement:
2478
+ case AST_NODE_TYPES9.DoWhileStatement:
2479
+ case AST_NODE_TYPES9.ForStatement:
2372
2480
  return parent.test === current;
2373
2481
  default:
2374
2482
  return false;
@@ -2378,13 +2486,13 @@ var isGuardTestPosition = (node) => {
2378
2486
  };
2379
2487
  var isUnvalidatedVariableRef = (node, scope, tracked) => {
2380
2488
  const unwrapped = unwrap(node);
2381
- if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES8.Identifier) {
2489
+ if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES9.Identifier) {
2382
2490
  return false;
2383
2491
  }
2384
2492
  const variable = findVariable2(scope, unwrapped.name);
2385
2493
  return variable !== null && tracked.has(variable);
2386
2494
  };
2387
- var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2495
+ var prefer_schema_for_api_payload_default = ESLintUtils13.RuleCreator(
2388
2496
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2389
2497
  )({
2390
2498
  name: "prefer-schema-for-api-payload",
@@ -2404,6 +2512,14 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2404
2512
  return {};
2405
2513
  }
2406
2514
  const unvalidatedVariables = /* @__PURE__ */ new Set();
2515
+ const isFullyNarrowedPattern = (declarator) => {
2516
+ const declared = context.sourceCode.getDeclaredVariables(declarator);
2517
+ return declared.length > 0 && declared.every(
2518
+ (variable) => variable.references.some(
2519
+ (reference) => isValidationRead(reference.identifier)
2520
+ )
2521
+ );
2522
+ };
2407
2523
  const trackInitializer = (declarator) => {
2408
2524
  if (!isRawPayloadSource(declarator.init)) return;
2409
2525
  const declaredVars = context.sourceCode.getDeclaredVariables(declarator);
@@ -2415,13 +2531,15 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2415
2531
  return {
2416
2532
  VariableDeclarator(node) {
2417
2533
  const scope = context.sourceCode.getScope(node);
2418
- if (node.id.type === AST_NODE_TYPES8.Identifier) {
2534
+ if (node.id.type === AST_NODE_TYPES9.Identifier) {
2419
2535
  trackInitializer(node);
2420
2536
  return;
2421
2537
  }
2422
- if (node.id.type === AST_NODE_TYPES8.ObjectPattern || node.id.type === AST_NODE_TYPES8.ArrayPattern) {
2538
+ if (node.id.type === AST_NODE_TYPES9.ObjectPattern || node.id.type === AST_NODE_TYPES9.ArrayPattern) {
2423
2539
  if (isRawPayloadSource(node.init)) {
2424
- context.report({ node: node.id, messageId: "unparsedJsonAccess" });
2540
+ if (!isFullyNarrowedPattern(node)) {
2541
+ context.report({ node: node.id, messageId: "unparsedJsonAccess" });
2542
+ }
2425
2543
  return;
2426
2544
  }
2427
2545
  if (isUnvalidatedVariableRef(node.init, scope, unvalidatedVariables)) {
@@ -2431,7 +2549,7 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2431
2549
  },
2432
2550
  AssignmentExpression(node) {
2433
2551
  const scope = context.sourceCode.getScope(node);
2434
- if (node.left.type === AST_NODE_TYPES8.Identifier) {
2552
+ if (node.left.type === AST_NODE_TYPES9.Identifier) {
2435
2553
  const variable = findVariable2(scope, node.left.name);
2436
2554
  if (variable === null) return;
2437
2555
  if (isRawPayloadSource(node.right)) {
@@ -2441,7 +2559,7 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2441
2559
  }
2442
2560
  return;
2443
2561
  }
2444
- if (node.left.type === AST_NODE_TYPES8.ObjectPattern || node.left.type === AST_NODE_TYPES8.ArrayPattern) {
2562
+ if (node.left.type === AST_NODE_TYPES9.ObjectPattern || node.left.type === AST_NODE_TYPES9.ArrayPattern) {
2445
2563
  if (isRawPayloadSource(node.right)) {
2446
2564
  context.report({
2447
2565
  node: node.left,
@@ -2458,15 +2576,15 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2458
2576
  }
2459
2577
  },
2460
2578
  CallExpression(node) {
2461
- if (node.callee.type !== AST_NODE_TYPES8.Identifier) return;
2579
+ if (node.callee.type !== AST_NODE_TYPES9.Identifier) return;
2462
2580
  if (!GUARD_NAME_RE.test(node.callee.name) && !isGuardTestPosition(node)) {
2463
2581
  return;
2464
2582
  }
2465
2583
  const scope = context.sourceCode.getScope(node);
2466
2584
  for (const arg of node.arguments) {
2467
- if (arg.type === AST_NODE_TYPES8.SpreadElement) continue;
2585
+ if (arg.type === AST_NODE_TYPES9.SpreadElement) continue;
2468
2586
  const unwrapped = unwrap(arg);
2469
- if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES8.Identifier) {
2587
+ if (unwrapped === null || unwrapped.type !== AST_NODE_TYPES9.Identifier) {
2470
2588
  continue;
2471
2589
  }
2472
2590
  const variable = findVariable2(scope, unwrapped.name);
@@ -2475,17 +2593,18 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2475
2593
  },
2476
2594
  MemberExpression(node) {
2477
2595
  if (isInsideAssertion(node)) return;
2596
+ if (isValidationRead(node)) return;
2478
2597
  const scope = context.sourceCode.getScope(node);
2479
2598
  const obj = unwrap(node.object);
2480
2599
  if (isRawPayloadSource(obj)) {
2481
2600
  const parent = node.parent;
2482
- if (parent.type === AST_NODE_TYPES8.CallExpression && parent.callee === node && node.property.type === AST_NODE_TYPES8.Identifier && (node.property.name === "parse" || node.property.name === "safeParse")) {
2601
+ if (parent.type === AST_NODE_TYPES9.CallExpression && parent.callee === node && node.property.type === AST_NODE_TYPES9.Identifier && (node.property.name === "parse" || node.property.name === "safeParse" || PROMISE_CHAIN_METHODS.has(node.property.name))) {
2483
2602
  return;
2484
2603
  }
2485
2604
  context.report({ node, messageId: "unparsedJsonAccess" });
2486
2605
  return;
2487
2606
  }
2488
- if (obj !== null && obj.type === AST_NODE_TYPES8.Identifier && isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)) {
2607
+ if (obj !== null && obj.type === AST_NODE_TYPES9.Identifier && isUnvalidatedVariableRef(obj, scope, unvalidatedVariables)) {
2489
2608
  context.report({ node, messageId: "unparsedJsonAccess" });
2490
2609
  const variable = findVariable2(scope, obj.name);
2491
2610
  if (variable !== null) {
@@ -2498,7 +2617,7 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2498
2617
  });
2499
2618
 
2500
2619
  // src/rules/prefer-semantic-colors.ts
2501
- import { AST_NODE_TYPES as AST_NODE_TYPES9, ESLintUtils as ESLintUtils15 } from "@typescript-eslint/utils";
2620
+ import { AST_NODE_TYPES as AST_NODE_TYPES10, ESLintUtils as ESLintUtils14 } from "@typescript-eslint/utils";
2502
2621
  import { existsSync, readFileSync } from "fs";
2503
2622
  import { dirname, join, parse } from "path";
2504
2623
 
@@ -2510,7 +2629,8 @@ var classTokens = (value) => value.split(/\s+/).filter(Boolean);
2510
2629
  var COLOR_PREFIXES = "text|bg|border(?:-[trblxyse])?|ring(?:-offset)?|fill|stroke|from|via|to|divide|decoration|placeholder|accent|caret|shadow|outline";
2511
2630
  var PALETTE = "red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|slate|gray|zinc|neutral|stone";
2512
2631
  var COLOR_FN = "rgba?|hsla?|hwb|oklch|oklab|lab|lch|color";
2513
- var RAW_PALETTE_RE = new RegExp(`^(?:${COLOR_PREFIXES})-(?:${PALETTE})-\\d{2,3}(?:/\\d{1,3})?$`);
2632
+ var PALETTE_STEP = "50|[1-9]00|950";
2633
+ var RAW_PALETTE_RE = new RegExp(`^(?:${COLOR_PREFIXES})-(?:${PALETTE})-(?:${PALETTE_STEP})(?:/\\d{1,3})?$`);
2514
2634
  var ARBITRARY_COLOR_RE = new RegExp(
2515
2635
  `^(?:${COLOR_PREFIXES})-\\[(?:#[0-9a-fA-F]{3,8}|(?:${COLOR_FN})\\([^\\]]*\\))\\]$`,
2516
2636
  "i"
@@ -2537,6 +2657,7 @@ var STYLE_COLOR_PROPS = /* @__PURE__ */ new Set([
2537
2657
  "lightingColor"
2538
2658
  ]);
2539
2659
  var RAW_COLOR_VALUE_RE = new RegExp(`#[0-9a-fA-F]{3,8}\\b|\\b(?:${COLOR_FN})\\s*\\(`, "i");
2660
+ var CSS_VAR_REFERENCE_RE = /var\(\s*--/;
2540
2661
  var STORIES_FILE_RE = /\.stories\.[cm]?[jt]sx?$/i;
2541
2662
  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/;
2542
2663
  var DETECTION_FILES = [
@@ -2573,8 +2694,8 @@ var SVG_EXEMPT_COLOR_VALUES = /* @__PURE__ */ new Set([
2573
2694
  ]);
2574
2695
  function jsxElementName(node) {
2575
2696
  const name = node.openingElement.name;
2576
- if (name.type === AST_NODE_TYPES9.JSXIdentifier) return name.name;
2577
- if (name.type === AST_NODE_TYPES9.JSXMemberExpression && name.property.type === AST_NODE_TYPES9.JSXIdentifier) {
2697
+ if (name.type === AST_NODE_TYPES10.JSXIdentifier) return name.name;
2698
+ if (name.type === AST_NODE_TYPES10.JSXMemberExpression && name.property.type === AST_NODE_TYPES10.JSXIdentifier) {
2578
2699
  return name.property.name;
2579
2700
  }
2580
2701
  return null;
@@ -2582,10 +2703,25 @@ function jsxElementName(node) {
2582
2703
  function isSvgLikeElementName(name) {
2583
2704
  return name === "svg" || SVG_DEFS_CONTAINERS.has(name) || /svg$/i.test(name);
2584
2705
  }
2706
+ var SVG_SHAPE_PRIMITIVES = /* @__PURE__ */ new Set([
2707
+ "circle",
2708
+ "ellipse",
2709
+ "g",
2710
+ "line",
2711
+ "path",
2712
+ "polygon",
2713
+ "polyline",
2714
+ "rect",
2715
+ "stop",
2716
+ "text",
2717
+ "tspan",
2718
+ "use"
2719
+ ]);
2720
+ var EMAIL_OR_PDF_IMPORT_RE = /@react-(?:email|pdf)\//;
2585
2721
  var isInsideSvg = (node) => {
2586
2722
  let current = node.parent;
2587
2723
  while (current !== void 0 && current !== null) {
2588
- if (current.type === AST_NODE_TYPES9.JSXElement) {
2724
+ if (current.type === AST_NODE_TYPES10.JSXElement) {
2589
2725
  const name = jsxElementName(current);
2590
2726
  if (name !== null && isSvgLikeElementName(name)) return true;
2591
2727
  }
@@ -2596,7 +2732,7 @@ var isInsideSvg = (node) => {
2596
2732
  var isInsideIconFactoryPath = (node) => {
2597
2733
  let current = node.parent;
2598
2734
  while (current !== void 0 && current !== null) {
2599
- if (current.type === AST_NODE_TYPES9.Property && propName(current.key) === "path" && current.parent.type === AST_NODE_TYPES9.ObjectExpression && current.parent.parent.type === AST_NODE_TYPES9.CallExpression && current.parent.parent.callee.type === AST_NODE_TYPES9.Identifier && current.parent.parent.callee.name === "createIcon") {
2735
+ if (current.type === AST_NODE_TYPES10.Property && propName(current.key) === "path" && current.parent.type === AST_NODE_TYPES10.ObjectExpression && current.parent.parent.type === AST_NODE_TYPES10.CallExpression && current.parent.parent.callee.type === AST_NODE_TYPES10.Identifier && current.parent.parent.callee.name === "createIcon") {
2600
2736
  return true;
2601
2737
  }
2602
2738
  current = current.parent;
@@ -2646,11 +2782,11 @@ var hasSemanticTokenSystem = (filename) => {
2646
2782
  return answer;
2647
2783
  };
2648
2784
  var propName = (key) => {
2649
- if (key.type === AST_NODE_TYPES9.Identifier) return key.name;
2650
- if (key.type === AST_NODE_TYPES9.Literal && typeof key.value === "string") return key.value;
2785
+ if (key.type === AST_NODE_TYPES10.Identifier) return key.name;
2786
+ if (key.type === AST_NODE_TYPES10.Literal && typeof key.value === "string") return key.value;
2651
2787
  return null;
2652
2788
  };
2653
- var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2789
+ var prefer_semantic_colors_default = ESLintUtils14.RuleCreator(
2654
2790
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
2655
2791
  )({
2656
2792
  name: "prefer-semantic-colors",
@@ -2677,6 +2813,7 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2677
2813
  defaultOptions: [{}],
2678
2814
  create(context, [options]) {
2679
2815
  if (STORIES_FILE_RE.test(context.filename)) return {};
2816
+ if (EMAIL_OR_PDF_IMPORT_RE.test(context.sourceCode.getText())) return {};
2680
2817
  if (options?.requireSemanticTokens === true && !hasSemanticTokenSystem(context.filename)) {
2681
2818
  return {};
2682
2819
  }
@@ -2685,7 +2822,7 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2685
2822
  const base = tailwindBase(token);
2686
2823
  if (RAW_PALETTE_RE.test(base)) {
2687
2824
  context.report({ node, messageId: "rawPalette", data: { class: token } });
2688
- } else if (ARBITRARY_COLOR_RE.test(base)) {
2825
+ } else if (ARBITRARY_COLOR_RE.test(base) && !CSS_VAR_REFERENCE_RE.test(base)) {
2689
2826
  context.report({ node, messageId: "arbitraryColor", data: { class: token } });
2690
2827
  }
2691
2828
  }
@@ -2693,27 +2830,27 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2693
2830
  const checkClassNode = (node) => {
2694
2831
  if (node === null) return;
2695
2832
  switch (node.type) {
2696
- case AST_NODE_TYPES9.Literal:
2833
+ case AST_NODE_TYPES10.Literal:
2697
2834
  if (typeof node.value === "string") reportClasses(node.value, node);
2698
2835
  break;
2699
- case AST_NODE_TYPES9.TemplateLiteral:
2836
+ case AST_NODE_TYPES10.TemplateLiteral:
2700
2837
  for (const quasi of node.quasis) reportClasses(quasi.value.cooked ?? "", quasi);
2701
2838
  break;
2702
- case AST_NODE_TYPES9.ArrayExpression:
2839
+ case AST_NODE_TYPES10.ArrayExpression:
2703
2840
  for (const element of node.elements) {
2704
- if (element !== null && element.type !== AST_NODE_TYPES9.SpreadElement) checkClassNode(element);
2841
+ if (element !== null && element.type !== AST_NODE_TYPES10.SpreadElement) checkClassNode(element);
2705
2842
  }
2706
2843
  break;
2707
- case AST_NODE_TYPES9.ObjectExpression:
2844
+ case AST_NODE_TYPES10.ObjectExpression:
2708
2845
  for (const property of node.properties) {
2709
- if (property.type === AST_NODE_TYPES9.Property) checkClassNode(property.value);
2846
+ if (property.type === AST_NODE_TYPES10.Property) checkClassNode(property.value);
2710
2847
  }
2711
2848
  break;
2712
- case AST_NODE_TYPES9.ConditionalExpression:
2849
+ case AST_NODE_TYPES10.ConditionalExpression:
2713
2850
  checkClassNode(node.consequent);
2714
2851
  checkClassNode(node.alternate);
2715
2852
  break;
2716
- case AST_NODE_TYPES9.LogicalExpression:
2853
+ case AST_NODE_TYPES10.LogicalExpression:
2717
2854
  checkClassNode(node.right);
2718
2855
  break;
2719
2856
  default:
@@ -2721,29 +2858,29 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2721
2858
  }
2722
2859
  };
2723
2860
  const checkColorValueNode = (node) => {
2724
- if (node.type === AST_NODE_TYPES9.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value)) {
2861
+ if (node.type === AST_NODE_TYPES10.Literal && typeof node.value === "string" && RAW_COLOR_VALUE_RE.test(node.value) && !CSS_VAR_REFERENCE_RE.test(node.value)) {
2725
2862
  context.report({ node, messageId: "inlineColor", data: { value: node.value } });
2726
2863
  }
2727
2864
  };
2728
2865
  return {
2729
2866
  "JSXAttribute[name.name='className']"(node) {
2730
2867
  if (node.value === null) return;
2731
- if (node.value.type === AST_NODE_TYPES9.Literal) checkClassNode(node.value);
2732
- else if (node.value.type === AST_NODE_TYPES9.JSXExpressionContainer) {
2733
- if (node.value.expression.type !== AST_NODE_TYPES9.JSXEmptyExpression) {
2868
+ if (node.value.type === AST_NODE_TYPES10.Literal) checkClassNode(node.value);
2869
+ else if (node.value.type === AST_NODE_TYPES10.JSXExpressionContainer) {
2870
+ if (node.value.expression.type !== AST_NODE_TYPES10.JSXEmptyExpression) {
2734
2871
  checkClassNode(node.value.expression);
2735
2872
  }
2736
2873
  }
2737
2874
  },
2738
2875
  CallExpression(node) {
2739
- if (node.callee.type === AST_NODE_TYPES9.Identifier && CLASS_FNS.has(node.callee.name)) {
2876
+ if (node.callee.type === AST_NODE_TYPES10.Identifier && CLASS_FNS.has(node.callee.name)) {
2740
2877
  for (const arg of node.arguments) {
2741
- if (arg.type !== AST_NODE_TYPES9.SpreadElement) checkClassNode(arg);
2878
+ if (arg.type !== AST_NODE_TYPES10.SpreadElement) checkClassNode(arg);
2742
2879
  }
2743
2880
  }
2744
2881
  },
2745
2882
  VariableDeclarator(node) {
2746
- if (node.id.type === AST_NODE_TYPES9.Identifier && CLASS_NAME_RE.test(node.id.name)) {
2883
+ if (node.id.type === AST_NODE_TYPES10.Identifier && CLASS_NAME_RE.test(node.id.name)) {
2747
2884
  checkClassNode(node.init);
2748
2885
  }
2749
2886
  },
@@ -2755,7 +2892,11 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2755
2892
  // Neutral drawing literals and anything inside an SVG defs container are
2756
2893
  // structural, not UI tokens, so they never fire.
2757
2894
  "JSXAttribute[name.name=/^(fill|stroke|color)$/]"(node) {
2758
- if (node.value?.type !== AST_NODE_TYPES9.Literal) return;
2895
+ if (node.value?.type !== AST_NODE_TYPES10.Literal) return;
2896
+ const owner = node.parent.name;
2897
+ if (owner.type === AST_NODE_TYPES10.JSXIdentifier && SVG_SHAPE_PRIMITIVES.has(owner.name)) {
2898
+ return;
2899
+ }
2759
2900
  if (typeof node.value.value === "string" && SVG_EXEMPT_COLOR_VALUES.has(node.value.value.toLowerCase())) {
2760
2901
  return;
2761
2902
  }
@@ -2772,7 +2913,7 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2772
2913
  });
2773
2914
 
2774
2915
  // src/rules/prefer-server-actions.ts
2775
- import { ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
2916
+ import { ESLintUtils as ESLintUtils15 } from "@typescript-eslint/utils";
2776
2917
  var MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "DELETE", "PATCH"]);
2777
2918
  var AXIOS_MUTATION_METHODS = /* @__PURE__ */ new Set(["post", "put", "delete", "patch"]);
2778
2919
  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\/)/;
@@ -2852,7 +2993,7 @@ function getPropertyNode(objNode, propName2) {
2852
2993
  }
2853
2994
  return null;
2854
2995
  }
2855
- var prefer_server_actions_default = ESLintUtils16.RuleCreator(
2996
+ var prefer_server_actions_default = ESLintUtils15.RuleCreator(
2856
2997
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2857
2998
  )({
2858
2999
  name: "prefer-server-actions",
@@ -2928,38 +3069,38 @@ var prefer_server_actions_default = ESLintUtils16.RuleCreator(
2928
3069
 
2929
3070
  // src/rules/require-assert-never.ts
2930
3071
  import {
2931
- ESLintUtils as ESLintUtils17,
2932
- AST_NODE_TYPES as AST_NODE_TYPES10
3072
+ ESLintUtils as ESLintUtils16,
3073
+ AST_NODE_TYPES as AST_NODE_TYPES11
2933
3074
  } from "@typescript-eslint/utils";
2934
3075
  var isAssertNeverCall = (expression) => {
2935
- if (expression.type !== AST_NODE_TYPES10.CallExpression) return false;
3076
+ if (expression.type !== AST_NODE_TYPES11.CallExpression) return false;
2936
3077
  const callee = expression.callee;
2937
- if (callee.type === AST_NODE_TYPES10.Identifier) {
3078
+ if (callee.type === AST_NODE_TYPES11.Identifier) {
2938
3079
  return callee.name === "assertNever";
2939
3080
  }
2940
- if (callee.type === AST_NODE_TYPES10.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES10.Identifier) {
3081
+ if (callee.type === AST_NODE_TYPES11.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES11.Identifier) {
2941
3082
  return callee.property.name === "assertNever";
2942
3083
  }
2943
3084
  return false;
2944
3085
  };
2945
3086
  var statementContainsAssertNever = (statement) => {
2946
- if (statement.type === AST_NODE_TYPES10.ExpressionStatement) {
3087
+ if (statement.type === AST_NODE_TYPES11.ExpressionStatement) {
2947
3088
  return isAssertNeverCall(statement.expression);
2948
3089
  }
2949
- if (statement.type === AST_NODE_TYPES10.ThrowStatement) {
3090
+ if (statement.type === AST_NODE_TYPES11.ThrowStatement) {
2950
3091
  return isAssertNeverCall(statement.argument);
2951
3092
  }
2952
- if (statement.type === AST_NODE_TYPES10.ReturnStatement) {
3093
+ if (statement.type === AST_NODE_TYPES11.ReturnStatement) {
2953
3094
  return statement.argument !== null && isAssertNeverCall(statement.argument);
2954
3095
  }
2955
- if (statement.type === AST_NODE_TYPES10.BlockStatement) {
3096
+ if (statement.type === AST_NODE_TYPES11.BlockStatement) {
2956
3097
  return statement.body.some(statementContainsAssertNever);
2957
3098
  }
2958
3099
  return false;
2959
3100
  };
2960
3101
  var isRuntimeHandlingStatement = (statement) => {
2961
- if (statement.type === AST_NODE_TYPES10.EmptyStatement) return false;
2962
- if (statement.type === AST_NODE_TYPES10.BlockStatement) {
3102
+ if (statement.type === AST_NODE_TYPES11.EmptyStatement) return false;
3103
+ if (statement.type === AST_NODE_TYPES11.BlockStatement) {
2963
3104
  return statement.body.some(isRuntimeHandlingStatement);
2964
3105
  }
2965
3106
  return true;
@@ -2975,12 +3116,12 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
2975
3116
  return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
2976
3117
  }
2977
3118
  const only = defaultCase.consequent[0];
2978
- if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === AST_NODE_TYPES10.BlockStatement && only.body.length === 0) {
3119
+ if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === AST_NODE_TYPES11.BlockStatement && only.body.length === 0) {
2979
3120
  return sourceCode.getCommentsInside(only).length > 0;
2980
3121
  }
2981
3122
  return false;
2982
3123
  };
2983
- var require_assert_never_default = ESLintUtils17.RuleCreator(
3124
+ var require_assert_never_default = ESLintUtils16.RuleCreator(
2984
3125
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2985
3126
  )({
2986
3127
  name: "require-assert-never",
@@ -3018,7 +3159,7 @@ var require_assert_never_default = ESLintUtils17.RuleCreator(
3018
3159
  });
3019
3160
 
3020
3161
  // src/rules/require-zod-form-validation.ts
3021
- import { ESLintUtils as ESLintUtils18, AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/utils";
3162
+ import { ESLintUtils as ESLintUtils17, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
3022
3163
 
3023
3164
  // src/rules/_zod.ts
3024
3165
  var ZOD_PREFIX_RE = /^Z[A-Z]/;
@@ -3032,14 +3173,14 @@ function isZodModule(source) {
3032
3173
  var looksLikeZodSchema = (node) => {
3033
3174
  let current = node;
3034
3175
  while (true) {
3035
- if (current.type === AST_NODE_TYPES11.Identifier) {
3176
+ if (current.type === AST_NODE_TYPES12.Identifier) {
3036
3177
  return current.name === "z" || ZOD_SCHEMA_NAME_RE.test(current.name);
3037
3178
  }
3038
- if (current.type === AST_NODE_TYPES11.CallExpression) {
3179
+ if (current.type === AST_NODE_TYPES12.CallExpression) {
3039
3180
  current = current.callee;
3040
3181
  continue;
3041
3182
  }
3042
- if (current.type === AST_NODE_TYPES11.MemberExpression) {
3183
+ if (current.type === AST_NODE_TYPES12.MemberExpression) {
3043
3184
  current = current.object;
3044
3185
  continue;
3045
3186
  }
@@ -3047,25 +3188,25 @@ var looksLikeZodSchema = (node) => {
3047
3188
  }
3048
3189
  };
3049
3190
  var isZodParseCall = (node) => {
3050
- if (node.type !== AST_NODE_TYPES11.CallExpression) return false;
3191
+ if (node.type !== AST_NODE_TYPES12.CallExpression) return false;
3051
3192
  const callee = node.callee;
3052
- if (callee.type !== AST_NODE_TYPES11.MemberExpression) return false;
3193
+ if (callee.type !== AST_NODE_TYPES12.MemberExpression) return false;
3053
3194
  if (callee.computed) return false;
3054
- if (callee.property.type !== AST_NODE_TYPES11.Identifier) return false;
3195
+ if (callee.property.type !== AST_NODE_TYPES12.Identifier) return false;
3055
3196
  const method = callee.property.name;
3056
3197
  if (method !== "parse" && method !== "safeParse") return false;
3057
3198
  return looksLikeZodSchema(callee.object);
3058
3199
  };
3059
3200
  var isFormDataMethodCall = (node) => {
3060
3201
  let current = node;
3061
- if (current.type === AST_NODE_TYPES11.AwaitExpression) {
3202
+ if (current.type === AST_NODE_TYPES12.AwaitExpression) {
3062
3203
  current = current.argument;
3063
3204
  }
3064
- if (current.type !== AST_NODE_TYPES11.CallExpression) return false;
3205
+ if (current.type !== AST_NODE_TYPES12.CallExpression) return false;
3065
3206
  const callee = current.callee;
3066
- return callee.type === AST_NODE_TYPES11.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES11.Identifier && callee.property.name === "formData";
3207
+ return callee.type === AST_NODE_TYPES12.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES12.Identifier && callee.property.name === "formData";
3067
3208
  };
3068
- var require_zod_form_validation_default = ESLintUtils18.RuleCreator(
3209
+ var require_zod_form_validation_default = ESLintUtils17.RuleCreator(
3069
3210
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3070
3211
  )({
3071
3212
  name: "require-zod-form-validation",
@@ -3085,14 +3226,14 @@ var require_zod_form_validation_default = ESLintUtils18.RuleCreator(
3085
3226
  return {};
3086
3227
  }
3087
3228
  const isFormSourceIdentifier = (node) => {
3088
- if (node.type !== AST_NODE_TYPES11.Identifier) return false;
3229
+ if (node.type !== AST_NODE_TYPES12.Identifier) return false;
3089
3230
  if (/formdata/i.test(node.name)) return true;
3090
3231
  let scope = context.sourceCode.getScope(node);
3091
3232
  while (scope !== null) {
3092
3233
  const variable = scope.set.get(node.name);
3093
3234
  if (variable !== void 0 && variable.defs.length === 1) {
3094
3235
  const def = variable.defs[0];
3095
- if (def !== void 0 && def.type === "Variable" && def.node.type === AST_NODE_TYPES11.VariableDeclarator && def.node.init !== null) {
3236
+ if (def !== void 0 && def.type === "Variable" && def.node.type === AST_NODE_TYPES12.VariableDeclarator && def.node.init !== null) {
3096
3237
  return isFormDataMethodCall(def.node.init);
3097
3238
  }
3098
3239
  return false;
@@ -3103,8 +3244,8 @@ var require_zod_form_validation_default = ESLintUtils18.RuleCreator(
3103
3244
  };
3104
3245
  const isFormDataGetCall = (node) => {
3105
3246
  const callee = node.callee;
3106
- if (callee.type !== AST_NODE_TYPES11.MemberExpression) return false;
3107
- if (callee.property.type !== AST_NODE_TYPES11.Identifier || callee.property.name !== "get") {
3247
+ if (callee.type !== AST_NODE_TYPES12.MemberExpression) return false;
3248
+ if (callee.property.type !== AST_NODE_TYPES12.Identifier || callee.property.name !== "get") {
3108
3249
  return false;
3109
3250
  }
3110
3251
  return isFormSourceIdentifier(callee.object);
@@ -3119,11 +3260,11 @@ var require_zod_form_validation_default = ESLintUtils18.RuleCreator(
3119
3260
  };
3120
3261
  const isInstanceofNarrowing = (node) => {
3121
3262
  const parent = node.parent;
3122
- return parent !== null && parent !== void 0 && parent.type === AST_NODE_TYPES11.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3263
+ return parent !== null && parent !== void 0 && parent.type === AST_NODE_TYPES12.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3123
3264
  };
3124
3265
  const boundDeclarator = (node) => {
3125
3266
  const parent = node.parent;
3126
- if (parent.type === AST_NODE_TYPES11.VariableDeclarator && parent.init === node && parent.id.type === AST_NODE_TYPES11.Identifier) {
3267
+ if (parent.type === AST_NODE_TYPES12.VariableDeclarator && parent.init === node && parent.id.type === AST_NODE_TYPES12.Identifier) {
3127
3268
  return parent;
3128
3269
  }
3129
3270
  return null;
@@ -3151,13 +3292,14 @@ var require_zod_form_validation_default = ESLintUtils18.RuleCreator(
3151
3292
  });
3152
3293
 
3153
3294
  // src/rules/zod-naming-convention.ts
3154
- import { ESLintUtils as ESLintUtils19, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
3295
+ import { ESLintUtils as ESLintUtils18, AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
3155
3296
  var CONVENTIONS = {
3156
3297
  prefix: { test: ZOD_PREFIX_RE, messageId: "zPrefix" },
3157
3298
  suffix: { test: ZOD_SUFFIX_RE, messageId: "schemaSuffix" },
3158
3299
  either: { test: ZOD_SCHEMA_NAME_RE, messageId: "zodSchemaName" }
3159
3300
  };
3160
3301
  var CONTAINS_SCHEMA_RE = /schema/i;
3302
+ var BENCHMARK_PATH_RE = /(^|[\\/])(?:benchmarks?|bench)[\\/]/;
3161
3303
  var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
3162
3304
  "parse",
3163
3305
  "parseAsync",
@@ -3175,15 +3317,15 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
3175
3317
  "registry",
3176
3318
  "implement"
3177
3319
  ]);
3178
- var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES12.Identifier ? callee.property.name : null;
3320
+ var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES13.Identifier ? callee.property.name : null;
3179
3321
  var calleeChainStartsWithZ = (node) => {
3180
3322
  let current = node;
3181
- while (current.type === AST_NODE_TYPES12.MemberExpression) {
3323
+ while (current.type === AST_NODE_TYPES13.MemberExpression) {
3182
3324
  const receiver = current.object;
3183
- if (receiver.type === AST_NODE_TYPES12.Identifier && receiver.name === "z") {
3325
+ if (receiver.type === AST_NODE_TYPES13.Identifier && receiver.name === "z") {
3184
3326
  return true;
3185
3327
  }
3186
- if (receiver.type === AST_NODE_TYPES12.CallExpression) {
3328
+ if (receiver.type === AST_NODE_TYPES13.CallExpression) {
3187
3329
  current = receiver.callee;
3188
3330
  continue;
3189
3331
  }
@@ -3191,7 +3333,7 @@ var calleeChainStartsWithZ = (node) => {
3191
3333
  }
3192
3334
  return false;
3193
3335
  };
3194
- var zod_naming_convention_default = ESLintUtils19.RuleCreator(
3336
+ var zod_naming_convention_default = ESLintUtils18.RuleCreator(
3195
3337
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3196
3338
  )({
3197
3339
  name: "zod-naming-convention",
@@ -3223,20 +3365,20 @@ var zod_naming_convention_default = ESLintUtils19.RuleCreator(
3223
3365
  const convention = optionsArg?.convention ?? "either";
3224
3366
  const { test, messageId } = CONVENTIONS[convention];
3225
3367
  const acceptsSchemaWord = convention !== "prefix";
3226
- if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) {
3368
+ if (isTestFile(context.filename) || BENCHMARK_PATH_RE.test(context.filename.replaceAll("\\", "/")) || isGeneratedFile(context.filename, context.sourceCode.text)) {
3227
3369
  return {};
3228
3370
  }
3229
3371
  return {
3230
3372
  VariableDeclarator(node) {
3231
3373
  const init = node.init;
3232
3374
  if (init === null || init === void 0) return;
3233
- if (init.type !== AST_NODE_TYPES12.CallExpression) return;
3375
+ if (init.type !== AST_NODE_TYPES13.CallExpression) return;
3234
3376
  const callee = init.callee;
3235
- if (callee.type !== AST_NODE_TYPES12.MemberExpression) return;
3377
+ if (callee.type !== AST_NODE_TYPES13.MemberExpression) return;
3236
3378
  if (!calleeChainStartsWithZ(callee)) return;
3237
3379
  const terminal = terminalMethodName(callee);
3238
3380
  if (terminal !== null && NON_SCHEMA_TERMINALS.has(terminal)) return;
3239
- if (node.id.type !== AST_NODE_TYPES12.Identifier) return;
3381
+ if (node.id.type !== AST_NODE_TYPES13.Identifier) return;
3240
3382
  if (test.test(node.id.name)) return;
3241
3383
  if (acceptsSchemaWord && CONTAINS_SCHEMA_RE.test(node.id.name)) return;
3242
3384
  context.report({
@@ -3249,7 +3391,7 @@ var zod_naming_convention_default = ESLintUtils19.RuleCreator(
3249
3391
  });
3250
3392
 
3251
3393
  // src/rules/no-cors-wildcard-with-credentials.ts
3252
- import { ESLintUtils as ESLintUtils20 } from "@typescript-eslint/utils";
3394
+ import { ESLintUtils as ESLintUtils19 } from "@typescript-eslint/utils";
3253
3395
  var ACAO_HEADER = "access-control-allow-origin";
3254
3396
  var ACAC_HEADER = "access-control-allow-credentials";
3255
3397
  var HEADER_SET_METHODS = /* @__PURE__ */ new Set(["setheader", "set", "append"]);
@@ -3391,7 +3533,7 @@ function enclosingScope(node) {
3391
3533
  }
3392
3534
  return void 0;
3393
3535
  }
3394
- var no_cors_wildcard_with_credentials_default = ESLintUtils20.RuleCreator(
3536
+ var no_cors_wildcard_with_credentials_default = ESLintUtils19.RuleCreator(
3395
3537
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3396
3538
  )({
3397
3539
  name: "no-cors-wildcard-with-credentials",
@@ -3459,9 +3601,9 @@ var no_cors_wildcard_with_credentials_default = ESLintUtils20.RuleCreator(
3459
3601
  });
3460
3602
 
3461
3603
  // src/rules/no-silent-promise-catch.ts
3462
- import { AST_NODE_TYPES as AST_NODE_TYPES13, ESLintUtils as ESLintUtils21 } from "@typescript-eslint/utils";
3604
+ import { AST_NODE_TYPES as AST_NODE_TYPES14, ESLintUtils as ESLintUtils20 } from "@typescript-eslint/utils";
3463
3605
  function isBodyParseCall(node) {
3464
- return node.type === AST_NODE_TYPES13.CallExpression && node.arguments.length === 0 && node.callee.type === AST_NODE_TYPES13.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES13.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3606
+ return node.type === AST_NODE_TYPES14.CallExpression && node.arguments.length === 0 && node.callee.type === AST_NODE_TYPES14.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES14.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3465
3607
  }
3466
3608
  var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3467
3609
  "cancel",
@@ -3476,21 +3618,21 @@ var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3476
3618
  var DIRECTIVE_COMMENT_RE = /^\s*(eslint-|@ts-|prettier-ignore|biome-ignore|c8 |v8 |istanbul )/;
3477
3619
  var isExplanatory = (comment) => !DIRECTIVE_COMMENT_RE.test(comment.value);
3478
3620
  function isTeardownCall(node) {
3479
- return node.type === AST_NODE_TYPES13.CallExpression && node.callee.type === AST_NODE_TYPES13.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES13.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3621
+ return node.type === AST_NODE_TYPES14.CallExpression && node.callee.type === AST_NODE_TYPES14.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES14.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3480
3622
  }
3481
3623
  function isSilentExpression(node) {
3482
3624
  switch (node.type) {
3483
- case AST_NODE_TYPES13.Literal:
3625
+ case AST_NODE_TYPES14.Literal:
3484
3626
  return !("regex" in node);
3485
- case AST_NODE_TYPES13.Identifier:
3627
+ case AST_NODE_TYPES14.Identifier:
3486
3628
  return node.name === "undefined";
3487
- case AST_NODE_TYPES13.UnaryExpression:
3488
- return node.operator === "void" && node.argument.type === AST_NODE_TYPES13.Literal;
3489
- case AST_NODE_TYPES13.ObjectExpression:
3629
+ case AST_NODE_TYPES14.UnaryExpression:
3630
+ return node.operator === "void" && node.argument.type === AST_NODE_TYPES14.Literal;
3631
+ case AST_NODE_TYPES14.ObjectExpression:
3490
3632
  return node.properties.length === 0;
3491
- case AST_NODE_TYPES13.ArrayExpression:
3633
+ case AST_NODE_TYPES14.ArrayExpression:
3492
3634
  return node.elements.length === 0;
3493
- case AST_NODE_TYPES13.TSAsExpression:
3635
+ case AST_NODE_TYPES14.TSAsExpression:
3494
3636
  return isSilentExpression(node.expression);
3495
3637
  default:
3496
3638
  return false;
@@ -3498,7 +3640,7 @@ function isSilentExpression(node) {
3498
3640
  }
3499
3641
  function isSilentHandler(handler) {
3500
3642
  const body = handler.body;
3501
- if (body.type !== AST_NODE_TYPES13.BlockStatement) {
3643
+ if (body.type !== AST_NODE_TYPES14.BlockStatement) {
3502
3644
  return isSilentExpression(body);
3503
3645
  }
3504
3646
  if (body.body.length === 0) {
@@ -3506,13 +3648,13 @@ function isSilentHandler(handler) {
3506
3648
  }
3507
3649
  if (body.body.length === 1) {
3508
3650
  const only = body.body[0];
3509
- if (only !== void 0 && only.type === AST_NODE_TYPES13.ReturnStatement) {
3651
+ if (only !== void 0 && only.type === AST_NODE_TYPES14.ReturnStatement) {
3510
3652
  return only.argument === null || isSilentExpression(only.argument);
3511
3653
  }
3512
3654
  }
3513
3655
  return false;
3514
3656
  }
3515
- var no_silent_promise_catch_default = ESLintUtils21.RuleCreator(
3657
+ var no_silent_promise_catch_default = ESLintUtils20.RuleCreator(
3516
3658
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3517
3659
  )({
3518
3660
  name: "no-silent-promise-catch",
@@ -3537,7 +3679,7 @@ var no_silent_promise_catch_default = ESLintUtils21.RuleCreator(
3537
3679
  return true;
3538
3680
  }
3539
3681
  let statement = call;
3540
- while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== AST_NODE_TYPES13.VariableDeclaration) {
3682
+ while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== AST_NODE_TYPES14.VariableDeclaration) {
3541
3683
  statement = statement.parent;
3542
3684
  }
3543
3685
  if (sourceCode.getCommentsBefore(statement).some(isExplanatory)) {
@@ -3549,7 +3691,7 @@ var no_silent_promise_catch_default = ESLintUtils21.RuleCreator(
3549
3691
  };
3550
3692
  return {
3551
3693
  CallExpression(node) {
3552
- if (node.callee.type !== AST_NODE_TYPES13.MemberExpression || node.callee.computed || node.callee.property.type !== AST_NODE_TYPES13.Identifier || node.callee.property.name !== "catch") {
3694
+ if (node.callee.type !== AST_NODE_TYPES14.MemberExpression || node.callee.computed || node.callee.property.type !== AST_NODE_TYPES14.Identifier || node.callee.property.name !== "catch") {
3553
3695
  return;
3554
3696
  }
3555
3697
  if (isBodyParseCall(node.callee.object)) {
@@ -3558,14 +3700,14 @@ var no_silent_promise_catch_default = ESLintUtils21.RuleCreator(
3558
3700
  if (isTeardownCall(node.callee.object)) {
3559
3701
  return;
3560
3702
  }
3561
- if (node.parent.type === AST_NODE_TYPES13.MemberExpression && node.parent.object === node) {
3703
+ if (node.parent.type === AST_NODE_TYPES14.MemberExpression && node.parent.object === node) {
3562
3704
  return;
3563
3705
  }
3564
3706
  if (node.arguments.length !== 1) {
3565
3707
  return;
3566
3708
  }
3567
3709
  const handler = node.arguments[0];
3568
- if (handler === void 0 || handler.type !== AST_NODE_TYPES13.ArrowFunctionExpression && handler.type !== AST_NODE_TYPES13.FunctionExpression) {
3710
+ if (handler === void 0 || handler.type !== AST_NODE_TYPES14.ArrowFunctionExpression && handler.type !== AST_NODE_TYPES14.FunctionExpression) {
3569
3711
  return;
3570
3712
  }
3571
3713
  if (hasExplanatoryComment(node, handler)) {
@@ -3581,9 +3723,9 @@ var no_silent_promise_catch_default = ESLintUtils21.RuleCreator(
3581
3723
 
3582
3724
  // src/rules/require-fetch-timeout.ts
3583
3725
  import {
3584
- AST_NODE_TYPES as AST_NODE_TYPES14,
3585
- ASTUtils,
3586
- ESLintUtils as ESLintUtils22
3726
+ AST_NODE_TYPES as AST_NODE_TYPES15,
3727
+ ASTUtils as ASTUtils2,
3728
+ ESLintUtils as ESLintUtils21
3587
3729
  } from "@typescript-eslint/utils";
3588
3730
  var CODEMOD_FIXTURE_RE = /[\\/]__testfixtures__[\\/]/;
3589
3731
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
@@ -3601,14 +3743,14 @@ function matchesAnyPattern2(filename, patterns) {
3601
3743
  return false;
3602
3744
  }
3603
3745
  function initProvablyLacksSignal(init) {
3604
- if (init.type !== AST_NODE_TYPES14.ObjectExpression) {
3746
+ if (init.type !== AST_NODE_TYPES15.ObjectExpression) {
3605
3747
  return false;
3606
3748
  }
3607
3749
  for (const prop of init.properties) {
3608
- if (prop.type === AST_NODE_TYPES14.SpreadElement) {
3750
+ if (prop.type === AST_NODE_TYPES15.SpreadElement) {
3609
3751
  return false;
3610
3752
  }
3611
- if (prop.key.type === AST_NODE_TYPES14.Identifier && prop.key.name === "signal" || prop.key.type === AST_NODE_TYPES14.Literal && prop.key.value === "signal") {
3753
+ if (prop.key.type === AST_NODE_TYPES15.Identifier && prop.key.name === "signal" || prop.key.type === AST_NODE_TYPES15.Literal && prop.key.value === "signal") {
3612
3754
  return false;
3613
3755
  }
3614
3756
  if (prop.computed) {
@@ -3618,9 +3760,9 @@ function initProvablyLacksSignal(init) {
3618
3760
  return true;
3619
3761
  }
3620
3762
  function isStringish(node) {
3621
- return node.type === AST_NODE_TYPES14.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES14.TemplateLiteral;
3763
+ return node.type === AST_NODE_TYPES15.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES15.TemplateLiteral;
3622
3764
  }
3623
- var require_fetch_timeout_default = ESLintUtils22.RuleCreator(
3765
+ var require_fetch_timeout_default = ESLintUtils21.RuleCreator(
3624
3766
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3625
3767
  )({
3626
3768
  name: "require-fetch-timeout",
@@ -3657,14 +3799,14 @@ var require_fetch_timeout_default = ESLintUtils22.RuleCreator(
3657
3799
  }
3658
3800
  function resolvesToGlobal(identifier) {
3659
3801
  const scope = context.sourceCode.getScope(identifier);
3660
- const variable = ASTUtils.findVariable(scope, identifier.name);
3802
+ const variable = ASTUtils2.findVariable(scope, identifier.name);
3661
3803
  return variable === null || variable.defs.length === 0;
3662
3804
  }
3663
3805
  function isGlobalFetchCall2(callee) {
3664
- if (callee.type === AST_NODE_TYPES14.Identifier) {
3806
+ if (callee.type === AST_NODE_TYPES15.Identifier) {
3665
3807
  return callee.name === "fetch" && resolvesToGlobal(callee);
3666
3808
  }
3667
- return callee.type === AST_NODE_TYPES14.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES14.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES14.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3809
+ return callee.type === AST_NODE_TYPES15.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES15.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES15.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3668
3810
  }
3669
3811
  return {
3670
3812
  CallExpression(node) {
@@ -3685,14 +3827,14 @@ var require_fetch_timeout_default = ESLintUtils22.RuleCreator(
3685
3827
 
3686
3828
  // src/rules/no-fat-try-blocks.ts
3687
3829
  import {
3688
- ESLintUtils as ESLintUtils23,
3689
- AST_NODE_TYPES as AST_NODE_TYPES15
3830
+ ESLintUtils as ESLintUtils22,
3831
+ AST_NODE_TYPES as AST_NODE_TYPES16
3690
3832
  } from "@typescript-eslint/utils";
3691
3833
  var MAX_TRY_BODY_STATEMENTS = 3;
3692
3834
  var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set([
3693
- AST_NODE_TYPES15.FunctionDeclaration,
3694
- AST_NODE_TYPES15.FunctionExpression,
3695
- AST_NODE_TYPES15.ArrowFunctionExpression
3835
+ AST_NODE_TYPES16.FunctionDeclaration,
3836
+ AST_NODE_TYPES16.FunctionExpression,
3837
+ AST_NODE_TYPES16.ArrowFunctionExpression
3696
3838
  ]);
3697
3839
  var PURE_METHODS = /* @__PURE__ */ new Set([
3698
3840
  "map",
@@ -3790,22 +3932,22 @@ function isNode3(value) {
3790
3932
  }
3791
3933
  function isPureCall(node) {
3792
3934
  const callee = node.callee;
3793
- if (callee.type !== AST_NODE_TYPES15.MemberExpression) {
3935
+ if (callee.type !== AST_NODE_TYPES16.MemberExpression) {
3794
3936
  return false;
3795
3937
  }
3796
3938
  const property = callee.property;
3797
- if (property.type !== AST_NODE_TYPES15.Identifier) {
3939
+ if (property.type !== AST_NODE_TYPES16.Identifier) {
3798
3940
  return false;
3799
3941
  }
3800
- if (callee.object.type === AST_NODE_TYPES15.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
3942
+ if (callee.object.type === AST_NODE_TYPES16.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
3801
3943
  return true;
3802
3944
  }
3803
3945
  return PURE_METHODS.has(property.name);
3804
3946
  }
3805
3947
  function isPureNew(node) {
3806
- return node.callee.type === AST_NODE_TYPES15.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
3948
+ return node.callee.type === AST_NODE_TYPES16.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
3807
3949
  }
3808
- function subtreeMatches(stmt, predicate) {
3950
+ function subtreeMatches(stmt, predicate, descendIntoFunctions = false) {
3809
3951
  let found = false;
3810
3952
  const visit = (current) => {
3811
3953
  if (found) {
@@ -3819,7 +3961,7 @@ function subtreeMatches(stmt, predicate) {
3819
3961
  if (key === "parent") {
3820
3962
  continue;
3821
3963
  }
3822
- if (NESTED_FUNCTION_TYPES.has(current.type) && key === "body") {
3964
+ if (!descendIntoFunctions && NESTED_FUNCTION_TYPES.has(current.type) && key === "body") {
3823
3965
  continue;
3824
3966
  }
3825
3967
  const value = current[key];
@@ -3840,20 +3982,20 @@ function subtreeMatches(stmt, predicate) {
3840
3982
  visit(stmt);
3841
3983
  return found;
3842
3984
  }
3843
- var hasAwait = (node) => subtreeMatches(node, (n) => n.type === AST_NODE_TYPES15.AwaitExpression);
3985
+ var hasAwait = (node) => subtreeMatches(node, (n) => n.type === AST_NODE_TYPES16.AwaitExpression);
3844
3986
  var hasThrowingCallOrNew = (node) => subtreeMatches(
3845
3987
  node,
3846
- (n) => n.type === AST_NODE_TYPES15.CallExpression && !isPureCall(n) || n.type === AST_NODE_TYPES15.NewExpression && !isPureNew(n)
3988
+ (n) => n.type === AST_NODE_TYPES16.CallExpression && !isPureCall(n) || n.type === AST_NODE_TYPES16.NewExpression && !isPureNew(n)
3847
3989
  );
3848
3990
  function unwrap2(expr) {
3849
3991
  let current = expr;
3850
- while (current.type === AST_NODE_TYPES15.ChainExpression || current.type === AST_NODE_TYPES15.TSNonNullExpression) {
3992
+ while (current.type === AST_NODE_TYPES16.ChainExpression || current.type === AST_NODE_TYPES16.TSNonNullExpression) {
3851
3993
  current = current.expression;
3852
3994
  }
3853
3995
  return current;
3854
3996
  }
3855
3997
  function isBareCallStatement(stmt) {
3856
- return stmt.type === AST_NODE_TYPES15.ExpressionStatement && unwrap2(stmt.expression).type === AST_NODE_TYPES15.CallExpression;
3998
+ return stmt.type === AST_NODE_TYPES16.ExpressionStatement && unwrap2(stmt.expression).type === AST_NODE_TYPES16.CallExpression;
3857
3999
  }
3858
4000
  function canThrow(stmt) {
3859
4001
  if (hasAwait(stmt)) {
@@ -3862,10 +4004,10 @@ function canThrow(stmt) {
3862
4004
  if (isBareCallStatement(stmt)) {
3863
4005
  return false;
3864
4006
  }
3865
- if (stmt.type === AST_NODE_TYPES15.BlockStatement) {
4007
+ if (stmt.type === AST_NODE_TYPES16.BlockStatement) {
3866
4008
  return stmt.body.some(canThrow);
3867
4009
  }
3868
- if (stmt.type === AST_NODE_TYPES15.IfStatement) {
4010
+ if (stmt.type === AST_NODE_TYPES16.IfStatement) {
3869
4011
  return hasThrowingCallOrNew(stmt.test) || canThrow(stmt.consequent) || stmt.alternate !== null && canThrow(stmt.alternate);
3870
4012
  }
3871
4013
  return hasThrowingCallOrNew(stmt);
@@ -3876,9 +4018,137 @@ function handlerRethrows(handler) {
3876
4018
  }
3877
4019
  const body = handler.body.body;
3878
4020
  const last = body[body.length - 1];
3879
- return last !== void 0 && last.type === AST_NODE_TYPES15.ThrowStatement;
4021
+ return last !== void 0 && last.type === AST_NODE_TYPES16.ThrowStatement;
4022
+ }
4023
+ var PASS_THROUGH_PARENTS = /* @__PURE__ */ new Set([
4024
+ AST_NODE_TYPES16.IfStatement,
4025
+ AST_NODE_TYPES16.TryStatement,
4026
+ AST_NODE_TYPES16.CatchClause,
4027
+ AST_NODE_TYPES16.LabeledStatement
4028
+ ]);
4029
+ function isTerminalInFunction(node) {
4030
+ let current = node;
4031
+ let parent = current.parent;
4032
+ while (parent !== void 0) {
4033
+ if (parent.type === AST_NODE_TYPES16.BlockStatement) {
4034
+ if (parent.body[parent.body.length - 1] !== current) {
4035
+ return false;
4036
+ }
4037
+ } else if (parent.type === AST_NODE_TYPES16.Program) {
4038
+ return parent.body[parent.body.length - 1] === current;
4039
+ } else if (NESTED_FUNCTION_TYPES.has(parent.type)) {
4040
+ return true;
4041
+ } else if (!PASS_THROUGH_PARENTS.has(parent.type)) {
4042
+ return false;
4043
+ }
4044
+ current = parent;
4045
+ parent = current.parent;
4046
+ }
4047
+ return false;
3880
4048
  }
3881
- var no_fat_try_blocks_default = ESLintUtils23.RuleCreator(
4049
+ function unwrapAwait(expr) {
4050
+ const inner = unwrap2(expr);
4051
+ return inner.type === AST_NODE_TYPES16.AwaitExpression ? unwrap2(inner.argument) : inner;
4052
+ }
4053
+ function handlerEndsByHandingOff(handler) {
4054
+ const body = handler.body.body;
4055
+ const last = body[body.length - 1];
4056
+ if (last === void 0) {
4057
+ return false;
4058
+ }
4059
+ if (last.type === AST_NODE_TYPES16.ReturnStatement || last.type === AST_NODE_TYPES16.ThrowStatement) {
4060
+ return true;
4061
+ }
4062
+ return last.type === AST_NODE_TYPES16.ExpressionStatement && unwrapAwait(last.expression).type === AST_NODE_TYPES16.CallExpression;
4063
+ }
4064
+ function collectBindingNames(pattern, names) {
4065
+ if (pattern.type === AST_NODE_TYPES16.Identifier) {
4066
+ names.add(pattern.name);
4067
+ return;
4068
+ }
4069
+ if (pattern.type === AST_NODE_TYPES16.ObjectPattern) {
4070
+ for (const property of pattern.properties) {
4071
+ collectBindingNames(
4072
+ property.type === AST_NODE_TYPES16.RestElement ? property.argument : property.value,
4073
+ names
4074
+ );
4075
+ }
4076
+ return;
4077
+ }
4078
+ if (pattern.type === AST_NODE_TYPES16.ArrayPattern) {
4079
+ for (const element of pattern.elements) {
4080
+ if (element !== null) {
4081
+ collectBindingNames(element, names);
4082
+ }
4083
+ }
4084
+ return;
4085
+ }
4086
+ if (pattern.type === AST_NODE_TYPES16.AssignmentPattern || pattern.type === AST_NODE_TYPES16.RestElement) {
4087
+ collectBindingNames(
4088
+ pattern.type === AST_NODE_TYPES16.AssignmentPattern ? pattern.left : pattern.argument,
4089
+ names
4090
+ );
4091
+ }
4092
+ }
4093
+ function caughtBindingNames(handler) {
4094
+ const names = /* @__PURE__ */ new Set();
4095
+ if (handler.param !== null) {
4096
+ collectBindingNames(handler.param, names);
4097
+ }
4098
+ return names;
4099
+ }
4100
+ function isPropertyName(node) {
4101
+ const parent = node.parent;
4102
+ if (parent.type === AST_NODE_TYPES16.MemberExpression) {
4103
+ return parent.property === node && !parent.computed;
4104
+ }
4105
+ if (parent.type === AST_NODE_TYPES16.Property) {
4106
+ return parent.key === node && !parent.computed;
4107
+ }
4108
+ return false;
4109
+ }
4110
+ function handlerMentionsCaughtBinding(handler) {
4111
+ const names = caughtBindingNames(handler);
4112
+ if (names.size === 0) {
4113
+ return false;
4114
+ }
4115
+ return subtreeMatches(
4116
+ handler.body,
4117
+ (n) => n.type === AST_NODE_TYPES16.Identifier && names.has(n.name) && !isPropertyName(n),
4118
+ true
4119
+ );
4120
+ }
4121
+ function isSuccessShapedValue(expr) {
4122
+ let current = expr;
4123
+ while (current.type === AST_NODE_TYPES16.TSAsExpression || current.type === AST_NODE_TYPES16.TSNonNullExpression) {
4124
+ current = current.expression;
4125
+ }
4126
+ if (current.type === AST_NODE_TYPES16.Literal) {
4127
+ return current.value === null || current.value === false;
4128
+ }
4129
+ if (current.type === AST_NODE_TYPES16.Identifier) {
4130
+ return current.name === "undefined";
4131
+ }
4132
+ if (current.type === AST_NODE_TYPES16.UnaryExpression) {
4133
+ return current.operator === "void";
4134
+ }
4135
+ if (current.type === AST_NODE_TYPES16.ArrayExpression) {
4136
+ return current.elements.length === 0;
4137
+ }
4138
+ if (current.type === AST_NODE_TYPES16.ObjectExpression) {
4139
+ return current.properties.length === 0;
4140
+ }
4141
+ return false;
4142
+ }
4143
+ var handlerReturnsSuccessShaped = (handler) => subtreeMatches(
4144
+ handler.body,
4145
+ (n) => n.type === AST_NODE_TYPES16.ReturnStatement && n.argument !== null && isSuccessShapedValue(n.argument)
4146
+ );
4147
+ function isTerminalErrorBoundary(node) {
4148
+ const handler = node.handler;
4149
+ return handler !== null && isTerminalInFunction(node) && handlerEndsByHandingOff(handler) && handlerMentionsCaughtBinding(handler) && !handlerReturnsSuccessShaped(handler);
4150
+ }
4151
+ var no_fat_try_blocks_default = ESLintUtils22.RuleCreator(
3882
4152
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
3883
4153
  )({
3884
4154
  name: "no-fat-try-blocks",
@@ -3906,6 +4176,9 @@ var no_fat_try_blocks_default = ESLintUtils23.RuleCreator(
3906
4176
  if (handlerRethrows(node.handler)) {
3907
4177
  return;
3908
4178
  }
4179
+ if (isTerminalErrorBoundary(node)) {
4180
+ return;
4181
+ }
3909
4182
  const count = node.block.body.filter(canThrow).length;
3910
4183
  if (count <= MAX_TRY_BODY_STATEMENTS) {
3911
4184
  return;
@@ -3922,7 +4195,7 @@ var no_fat_try_blocks_default = ESLintUtils23.RuleCreator(
3922
4195
  });
3923
4196
 
3924
4197
  // src/rules/no-secret-in-log.ts
3925
- import { ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
4198
+ import { ESLintUtils as ESLintUtils23 } from "@typescript-eslint/utils";
3926
4199
 
3927
4200
  // src/rules/_secret_names.ts
3928
4201
  var SECRET_WORDS = /* @__PURE__ */ new Set([
@@ -4184,7 +4457,7 @@ function propertyKeyName2(prop) {
4184
4457
  }
4185
4458
  return null;
4186
4459
  }
4187
- var no_secret_in_log_default = ESLintUtils24.RuleCreator(
4460
+ var no_secret_in_log_default = ESLintUtils23.RuleCreator(
4188
4461
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4189
4462
  )({
4190
4463
  name: "no-secret-in-log",
@@ -4261,24 +4534,24 @@ var no_secret_in_log_default = ESLintUtils24.RuleCreator(
4261
4534
  });
4262
4535
 
4263
4536
  // src/rules/no-unsafe-mock-casting.ts
4264
- import { ESLintUtils as ESLintUtils25 } from "@typescript-eslint/utils";
4265
- import { AST_NODE_TYPES as AST_NODE_TYPES16 } from "@typescript-eslint/utils";
4537
+ import { ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
4538
+ import { AST_NODE_TYPES as AST_NODE_TYPES17 } from "@typescript-eslint/utils";
4266
4539
  function isMockTypeReference(node) {
4267
- if (node.type !== AST_NODE_TYPES16.TSTypeReference) {
4540
+ if (node.type !== AST_NODE_TYPES17.TSTypeReference) {
4268
4541
  return false;
4269
4542
  }
4270
4543
  const typeName = node.typeName;
4271
- if (typeName.type === AST_NODE_TYPES16.Identifier) {
4544
+ if (typeName.type === AST_NODE_TYPES17.Identifier) {
4272
4545
  const name = typeName.name;
4273
4546
  return name === "Mock" || name === "MockInstance" || name === "SpyInstance";
4274
4547
  }
4275
- if (typeName.type === AST_NODE_TYPES16.TSQualifiedName) {
4548
+ if (typeName.type === AST_NODE_TYPES17.TSQualifiedName) {
4276
4549
  const rightName = typeName.right.name;
4277
4550
  return rightName === "Mock" || rightName === "MockInstance" || rightName === "SpyInstance";
4278
4551
  }
4279
4552
  return false;
4280
4553
  }
4281
- var no_unsafe_mock_casting_default = ESLintUtils25.RuleCreator(
4554
+ var no_unsafe_mock_casting_default = ESLintUtils24.RuleCreator(
4282
4555
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4283
4556
  )({
4284
4557
  name: "no-unsafe-mock-casting",
@@ -4311,8 +4584,8 @@ var no_unsafe_mock_casting_default = ESLintUtils25.RuleCreator(
4311
4584
 
4312
4585
  // src/rules/prefer-string-literal-union.ts
4313
4586
  import {
4314
- ESLintUtils as ESLintUtils26,
4315
- AST_NODE_TYPES as AST_NODE_TYPES17
4587
+ ESLintUtils as ESLintUtils25,
4588
+ AST_NODE_TYPES as AST_NODE_TYPES18
4316
4589
  } from "@typescript-eslint/utils";
4317
4590
  import * as ts from "typescript";
4318
4591
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
@@ -4356,19 +4629,19 @@ function isChoiceLikeName(name) {
4356
4629
  return CHOICE_TOKENS.has(lastWord(name));
4357
4630
  }
4358
4631
  function keyName(key) {
4359
- if (key.type === AST_NODE_TYPES17.Identifier) {
4632
+ if (key.type === AST_NODE_TYPES18.Identifier) {
4360
4633
  return key.name;
4361
4634
  }
4362
- if (key.type === AST_NODE_TYPES17.Literal && typeof key.value === "string") {
4635
+ if (key.type === AST_NODE_TYPES18.Literal && typeof key.value === "string") {
4363
4636
  return key.value;
4364
4637
  }
4365
4638
  return null;
4366
4639
  }
4367
4640
  function isStringLiteralMember(t) {
4368
- return t.type === AST_NODE_TYPES17.TSLiteralType && t.literal.type === AST_NODE_TYPES17.Literal && typeof t.literal.value === "string";
4641
+ return t.type === AST_NODE_TYPES18.TSLiteralType && t.literal.type === AST_NODE_TYPES18.Literal && typeof t.literal.value === "string";
4369
4642
  }
4370
4643
  function isStringLiteralUnion(node) {
4371
- if (node?.type !== AST_NODE_TYPES17.TSUnionType) {
4644
+ if (node?.type !== AST_NODE_TYPES18.TSUnionType) {
4372
4645
  return false;
4373
4646
  }
4374
4647
  return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
@@ -4397,12 +4670,12 @@ function bindingSourceExpression(decl) {
4397
4670
  return ts.isForOfStatement(node) ? node.expression : node.initializer;
4398
4671
  }
4399
4672
  function refKey(node) {
4400
- if (node.type === AST_NODE_TYPES17.Identifier) {
4673
+ if (node.type === AST_NODE_TYPES18.Identifier) {
4401
4674
  return node.name;
4402
4675
  }
4403
- if (node.type === AST_NODE_TYPES17.MemberExpression && !node.computed) {
4676
+ if (node.type === AST_NODE_TYPES18.MemberExpression && !node.computed) {
4404
4677
  const inner = refKey(node.object);
4405
- if (inner === null || node.property.type !== AST_NODE_TYPES17.Identifier) {
4678
+ if (inner === null || node.property.type !== AST_NODE_TYPES18.Identifier) {
4406
4679
  return null;
4407
4680
  }
4408
4681
  return `${inner}.${node.property.name}`;
@@ -4410,12 +4683,12 @@ function refKey(node) {
4410
4683
  return null;
4411
4684
  }
4412
4685
  function strLiteral(node) {
4413
- if (node.type === AST_NODE_TYPES17.Literal && typeof node.value === "string") {
4686
+ if (node.type === AST_NODE_TYPES18.Literal && typeof node.value === "string") {
4414
4687
  return node.value;
4415
4688
  }
4416
4689
  return null;
4417
4690
  }
4418
- var prefer_string_literal_union_default = ESLintUtils26.RuleCreator(
4691
+ var prefer_string_literal_union_default = ESLintUtils25.RuleCreator(
4419
4692
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4420
4693
  )({
4421
4694
  name: "prefer-string-literal-union",
@@ -4453,7 +4726,7 @@ var prefer_string_literal_union_default = ESLintUtils26.RuleCreator(
4453
4726
  );
4454
4727
  let services;
4455
4728
  try {
4456
- services = ESLintUtils26.getParserServices(context);
4729
+ services = ESLintUtils25.getParserServices(context);
4457
4730
  } catch {
4458
4731
  services = null;
4459
4732
  }
@@ -4565,7 +4838,7 @@ var prefer_string_literal_union_default = ESLintUtils26.RuleCreator(
4565
4838
  containersWithUnion.add(container);
4566
4839
  return;
4567
4840
  }
4568
- if (typeNode?.type !== AST_NODE_TYPES17.TSStringKeyword) {
4841
+ if (typeNode?.type !== AST_NODE_TYPES18.TSStringKeyword) {
4569
4842
  return;
4570
4843
  }
4571
4844
  const name = keyName(key);
@@ -4653,10 +4926,10 @@ var prefer_string_literal_union_default = ESLintUtils26.RuleCreator(
4653
4926
  }
4654
4927
  };
4655
4928
  function refKeyText(node) {
4656
- if (node.type === AST_NODE_TYPES17.BinaryExpression) {
4929
+ if (node.type === AST_NODE_TYPES18.BinaryExpression) {
4657
4930
  return refKey(node.left) ?? refKey(node.right) ?? "value";
4658
4931
  }
4659
- if (node.type === AST_NODE_TYPES17.SwitchStatement) {
4932
+ if (node.type === AST_NODE_TYPES18.SwitchStatement) {
4660
4933
  return refKey(node.discriminant) ?? "value";
4661
4934
  }
4662
4935
  return "value";
@@ -4666,10 +4939,10 @@ var prefer_string_literal_union_default = ESLintUtils26.RuleCreator(
4666
4939
 
4667
4940
  // src/rules/prefer-zod-enum.ts
4668
4941
  import {
4669
- AST_NODE_TYPES as AST_NODE_TYPES18,
4670
- ESLintUtils as ESLintUtils27
4942
+ AST_NODE_TYPES as AST_NODE_TYPES19,
4943
+ ESLintUtils as ESLintUtils26
4671
4944
  } from "@typescript-eslint/utils";
4672
- var prefer_zod_enum_default = ESLintUtils27.RuleCreator(
4945
+ var prefer_zod_enum_default = ESLintUtils26.RuleCreator(
4673
4946
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
4674
4947
  )({
4675
4948
  name: "prefer-zod-enum",
@@ -4690,20 +4963,20 @@ var prefer_zod_enum_default = ESLintUtils27.RuleCreator(
4690
4963
  const zodNamespaces = /* @__PURE__ */ new Set();
4691
4964
  function enumValues(node) {
4692
4965
  const callee = node.callee;
4693
- if (callee.type !== AST_NODE_TYPES18.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES18.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== AST_NODE_TYPES18.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
4966
+ if (callee.type !== AST_NODE_TYPES19.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES19.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== AST_NODE_TYPES19.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
4694
4967
  return null;
4695
4968
  }
4696
4969
  const argument = node.arguments[0];
4697
- if (argument === void 0 || argument.type !== AST_NODE_TYPES18.ArrayExpression || argument.elements.length === 0) {
4970
+ if (argument === void 0 || argument.type !== AST_NODE_TYPES19.ArrayExpression || argument.elements.length === 0) {
4698
4971
  return null;
4699
4972
  }
4700
4973
  const values = [];
4701
4974
  for (const element of argument.elements) {
4702
- if (element === null || element.type !== AST_NODE_TYPES18.CallExpression || element.arguments.length !== 1 || element.callee.type !== AST_NODE_TYPES18.MemberExpression || element.callee.computed || element.callee.object.type !== AST_NODE_TYPES18.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== AST_NODE_TYPES18.Identifier || element.callee.property.name !== "literal") {
4975
+ if (element === null || element.type !== AST_NODE_TYPES19.CallExpression || element.arguments.length !== 1 || element.callee.type !== AST_NODE_TYPES19.MemberExpression || element.callee.computed || element.callee.object.type !== AST_NODE_TYPES19.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== AST_NODE_TYPES19.Identifier || element.callee.property.name !== "literal") {
4703
4976
  return null;
4704
4977
  }
4705
4978
  const value = element.arguments[0];
4706
- if (value === void 0 || value.type !== AST_NODE_TYPES18.Literal || typeof value.value !== "string") {
4979
+ if (value === void 0 || value.type !== AST_NODE_TYPES19.Literal || typeof value.value !== "string") {
4707
4980
  return null;
4708
4981
  }
4709
4982
  values.push(value);
@@ -4712,11 +4985,11 @@ var prefer_zod_enum_default = ESLintUtils27.RuleCreator(
4712
4985
  }
4713
4986
  function buildFix(node, values) {
4714
4987
  const argument = node.arguments[0];
4715
- if (argument === void 0 || argument.type !== AST_NODE_TYPES18.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
4988
+ if (argument === void 0 || argument.type !== AST_NODE_TYPES19.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
4716
4989
  return void 0;
4717
4990
  }
4718
4991
  const callee = node.callee;
4719
- if (callee.type !== AST_NODE_TYPES18.MemberExpression || callee.property.type !== AST_NODE_TYPES18.Identifier) {
4992
+ if (callee.type !== AST_NODE_TYPES19.MemberExpression || callee.property.type !== AST_NODE_TYPES19.Identifier) {
4720
4993
  return void 0;
4721
4994
  }
4722
4995
  return (fixer) => [
@@ -4733,7 +5006,7 @@ var prefer_zod_enum_default = ESLintUtils27.RuleCreator(
4733
5006
  return;
4734
5007
  }
4735
5008
  for (const specifier of node.specifiers) {
4736
- if (specifier.type === AST_NODE_TYPES18.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES18.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES18.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES18.Identifier && specifier.imported.name === "z") {
5009
+ if (specifier.type === AST_NODE_TYPES19.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES19.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES19.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES19.Identifier && specifier.imported.name === "z") {
4737
5010
  zodNamespaces.add(specifier.local.name);
4738
5011
  }
4739
5012
  }
@@ -4756,8 +5029,8 @@ var prefer_zod_enum_default = ESLintUtils27.RuleCreator(
4756
5029
 
4757
5030
  // src/rules/prefer-zod-infer.ts
4758
5031
  import {
4759
- AST_NODE_TYPES as AST_NODE_TYPES19,
4760
- ESLintUtils as ESLintUtils28
5032
+ AST_NODE_TYPES as AST_NODE_TYPES20,
5033
+ ESLintUtils as ESLintUtils27
4761
5034
  } from "@typescript-eslint/utils";
4762
5035
  var SHAPE_PRESERVING_METHODS = /* @__PURE__ */ new Set([
4763
5036
  "describe",
@@ -4795,44 +5068,44 @@ var ZOD_TYPE_CONSTRAINTS = /* @__PURE__ */ new Set([
4795
5068
  "Schema"
4796
5069
  ]);
4797
5070
  var LEAF_NODE_TYPES = {
4798
- string: [AST_NODE_TYPES19.TSStringKeyword],
4799
- email: [AST_NODE_TYPES19.TSStringKeyword],
4800
- url: [AST_NODE_TYPES19.TSStringKeyword],
4801
- uuid: [AST_NODE_TYPES19.TSStringKeyword],
4802
- ulid: [AST_NODE_TYPES19.TSStringKeyword],
4803
- cuid: [AST_NODE_TYPES19.TSStringKeyword],
4804
- cuid2: [AST_NODE_TYPES19.TSStringKeyword],
4805
- nanoid: [AST_NODE_TYPES19.TSStringKeyword],
4806
- iso: [AST_NODE_TYPES19.TSStringKeyword],
4807
- number: [AST_NODE_TYPES19.TSNumberKeyword],
4808
- int: [AST_NODE_TYPES19.TSNumberKeyword],
4809
- float32: [AST_NODE_TYPES19.TSNumberKeyword],
4810
- float64: [AST_NODE_TYPES19.TSNumberKeyword],
4811
- boolean: [AST_NODE_TYPES19.TSBooleanKeyword],
4812
- bigint: [AST_NODE_TYPES19.TSBigIntKeyword],
4813
- symbol: [AST_NODE_TYPES19.TSSymbolKeyword],
4814
- any: [AST_NODE_TYPES19.TSAnyKeyword],
4815
- unknown: [AST_NODE_TYPES19.TSUnknownKeyword],
4816
- never: [AST_NODE_TYPES19.TSNeverKeyword],
4817
- void: [AST_NODE_TYPES19.TSVoidKeyword],
4818
- null: [AST_NODE_TYPES19.TSNullKeyword],
4819
- undefined: [AST_NODE_TYPES19.TSUndefinedKeyword],
4820
- literal: [AST_NODE_TYPES19.TSLiteralType],
4821
- date: [AST_NODE_TYPES19.TSTypeReference],
4822
- array: [AST_NODE_TYPES19.TSArrayType, AST_NODE_TYPES19.TSTypeReference],
4823
- tuple: [AST_NODE_TYPES19.TSTupleType],
4824
- object: [AST_NODE_TYPES19.TSTypeLiteral, AST_NODE_TYPES19.TSTypeReference],
4825
- strictObject: [AST_NODE_TYPES19.TSTypeLiteral, AST_NODE_TYPES19.TSTypeReference],
4826
- looseObject: [AST_NODE_TYPES19.TSTypeLiteral, AST_NODE_TYPES19.TSTypeReference],
4827
- record: [AST_NODE_TYPES19.TSTypeReference, AST_NODE_TYPES19.TSTypeLiteral],
4828
- map: [AST_NODE_TYPES19.TSTypeReference],
4829
- set: [AST_NODE_TYPES19.TSTypeReference],
4830
- promise: [AST_NODE_TYPES19.TSTypeReference],
4831
- enum: [AST_NODE_TYPES19.TSUnionType, AST_NODE_TYPES19.TSTypeReference, AST_NODE_TYPES19.TSLiteralType],
4832
- nativeEnum: [AST_NODE_TYPES19.TSUnionType, AST_NODE_TYPES19.TSTypeReference, AST_NODE_TYPES19.TSLiteralType],
4833
- union: [AST_NODE_TYPES19.TSUnionType, AST_NODE_TYPES19.TSTypeReference],
4834
- discriminatedUnion: [AST_NODE_TYPES19.TSUnionType, AST_NODE_TYPES19.TSTypeReference],
4835
- intersection: [AST_NODE_TYPES19.TSIntersectionType, AST_NODE_TYPES19.TSTypeReference]
5071
+ string: [AST_NODE_TYPES20.TSStringKeyword],
5072
+ email: [AST_NODE_TYPES20.TSStringKeyword],
5073
+ url: [AST_NODE_TYPES20.TSStringKeyword],
5074
+ uuid: [AST_NODE_TYPES20.TSStringKeyword],
5075
+ ulid: [AST_NODE_TYPES20.TSStringKeyword],
5076
+ cuid: [AST_NODE_TYPES20.TSStringKeyword],
5077
+ cuid2: [AST_NODE_TYPES20.TSStringKeyword],
5078
+ nanoid: [AST_NODE_TYPES20.TSStringKeyword],
5079
+ iso: [AST_NODE_TYPES20.TSStringKeyword],
5080
+ number: [AST_NODE_TYPES20.TSNumberKeyword],
5081
+ int: [AST_NODE_TYPES20.TSNumberKeyword],
5082
+ float32: [AST_NODE_TYPES20.TSNumberKeyword],
5083
+ float64: [AST_NODE_TYPES20.TSNumberKeyword],
5084
+ boolean: [AST_NODE_TYPES20.TSBooleanKeyword],
5085
+ bigint: [AST_NODE_TYPES20.TSBigIntKeyword],
5086
+ symbol: [AST_NODE_TYPES20.TSSymbolKeyword],
5087
+ any: [AST_NODE_TYPES20.TSAnyKeyword],
5088
+ unknown: [AST_NODE_TYPES20.TSUnknownKeyword],
5089
+ never: [AST_NODE_TYPES20.TSNeverKeyword],
5090
+ void: [AST_NODE_TYPES20.TSVoidKeyword],
5091
+ null: [AST_NODE_TYPES20.TSNullKeyword],
5092
+ undefined: [AST_NODE_TYPES20.TSUndefinedKeyword],
5093
+ literal: [AST_NODE_TYPES20.TSLiteralType],
5094
+ date: [AST_NODE_TYPES20.TSTypeReference],
5095
+ array: [AST_NODE_TYPES20.TSArrayType, AST_NODE_TYPES20.TSTypeReference],
5096
+ tuple: [AST_NODE_TYPES20.TSTupleType],
5097
+ object: [AST_NODE_TYPES20.TSTypeLiteral, AST_NODE_TYPES20.TSTypeReference],
5098
+ strictObject: [AST_NODE_TYPES20.TSTypeLiteral, AST_NODE_TYPES20.TSTypeReference],
5099
+ looseObject: [AST_NODE_TYPES20.TSTypeLiteral, AST_NODE_TYPES20.TSTypeReference],
5100
+ record: [AST_NODE_TYPES20.TSTypeReference, AST_NODE_TYPES20.TSTypeLiteral],
5101
+ map: [AST_NODE_TYPES20.TSTypeReference],
5102
+ set: [AST_NODE_TYPES20.TSTypeReference],
5103
+ promise: [AST_NODE_TYPES20.TSTypeReference],
5104
+ enum: [AST_NODE_TYPES20.TSUnionType, AST_NODE_TYPES20.TSTypeReference, AST_NODE_TYPES20.TSLiteralType],
5105
+ nativeEnum: [AST_NODE_TYPES20.TSUnionType, AST_NODE_TYPES20.TSTypeReference, AST_NODE_TYPES20.TSLiteralType],
5106
+ union: [AST_NODE_TYPES20.TSUnionType, AST_NODE_TYPES20.TSTypeReference],
5107
+ discriminatedUnion: [AST_NODE_TYPES20.TSUnionType, AST_NODE_TYPES20.TSTypeReference],
5108
+ intersection: [AST_NODE_TYPES20.TSIntersectionType, AST_NODE_TYPES20.TSTypeReference]
4836
5109
  };
4837
5110
  function normalizeSchemaName(name) {
4838
5111
  return name.replace(/Schema$/i, "").replace(/^Z(?=[A-Z])/, "").toLowerCase();
@@ -4841,20 +5114,20 @@ function normalizeTypeName(name) {
4841
5114
  return name.replace(/Type$/, "").toLowerCase();
4842
5115
  }
4843
5116
  function unwrapNullish(annotation) {
4844
- if (annotation.type !== AST_NODE_TYPES19.TSUnionType) {
5117
+ if (annotation.type !== AST_NODE_TYPES20.TSUnionType) {
4845
5118
  return {
4846
5119
  core: annotation,
4847
- nullable: annotation.type === AST_NODE_TYPES19.TSNullKeyword
5120
+ nullable: annotation.type === AST_NODE_TYPES20.TSNullKeyword
4848
5121
  };
4849
5122
  }
4850
5123
  const rest = [];
4851
5124
  let nullable = false;
4852
5125
  for (const member of annotation.types) {
4853
- if (member.type === AST_NODE_TYPES19.TSNullKeyword) {
5126
+ if (member.type === AST_NODE_TYPES20.TSNullKeyword) {
4854
5127
  nullable = true;
4855
5128
  continue;
4856
5129
  }
4857
- if (member.type === AST_NODE_TYPES19.TSUndefinedKeyword) {
5130
+ if (member.type === AST_NODE_TYPES20.TSUndefinedKeyword) {
4858
5131
  continue;
4859
5132
  }
4860
5133
  rest.push(member);
@@ -4878,7 +5151,7 @@ function leafAgrees(leaf, annotation) {
4878
5151
  }
4879
5152
  return expected.includes(core.type);
4880
5153
  }
4881
- var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5154
+ var prefer_zod_infer_default = ESLintUtils27.RuleCreator(
4882
5155
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
4883
5156
  )({
4884
5157
  name: "prefer-zod-infer",
@@ -4921,14 +5194,14 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
4921
5194
  function zodCallChain(node) {
4922
5195
  const chain = [];
4923
5196
  let current = node;
4924
- while (current.type === AST_NODE_TYPES19.CallExpression) {
5197
+ while (current.type === AST_NODE_TYPES20.CallExpression) {
4925
5198
  const callee = current.callee;
4926
- if (callee.type !== AST_NODE_TYPES19.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES19.Identifier) {
5199
+ if (callee.type !== AST_NODE_TYPES20.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES20.Identifier) {
4927
5200
  return null;
4928
5201
  }
4929
5202
  chain.push(current);
4930
5203
  const receiver = callee.object;
4931
- if (receiver.type === AST_NODE_TYPES19.Identifier) {
5204
+ if (receiver.type === AST_NODE_TYPES20.Identifier) {
4932
5205
  return zodNamespaces.has(receiver.name) ? chain.reverse() : null;
4933
5206
  }
4934
5207
  current = receiver;
@@ -4937,19 +5210,19 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
4937
5210
  }
4938
5211
  function methodName(call) {
4939
5212
  const callee = call.callee;
4940
- return callee.type === AST_NODE_TYPES19.MemberExpression && callee.property.type === AST_NODE_TYPES19.Identifier ? callee.property.name : "";
5213
+ return callee.type === AST_NODE_TYPES20.MemberExpression && callee.property.type === AST_NODE_TYPES20.Identifier ? callee.property.name : "";
4941
5214
  }
4942
5215
  function schemaField(node) {
4943
5216
  const modifiers = [];
4944
5217
  let current = node;
4945
5218
  let leaf = null;
4946
- while (current.type === AST_NODE_TYPES19.CallExpression) {
5219
+ while (current.type === AST_NODE_TYPES20.CallExpression) {
4947
5220
  const callee = current.callee;
4948
- if (callee.type !== AST_NODE_TYPES19.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES19.Identifier) {
5221
+ if (callee.type !== AST_NODE_TYPES20.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES20.Identifier) {
4949
5222
  break;
4950
5223
  }
4951
5224
  const receiver = callee.object;
4952
- if (receiver.type === AST_NODE_TYPES19.Identifier && zodNamespaces.has(receiver.name)) {
5225
+ if (receiver.type === AST_NODE_TYPES20.Identifier && zodNamespaces.has(receiver.name)) {
4953
5226
  leaf = callee.property.name;
4954
5227
  break;
4955
5228
  }
@@ -4980,16 +5253,16 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
4980
5253
  return null;
4981
5254
  }
4982
5255
  const shape = base.arguments[0];
4983
- if (shape === void 0 || shape.type !== AST_NODE_TYPES19.ObjectExpression) {
5256
+ if (shape === void 0 || shape.type !== AST_NODE_TYPES20.ObjectExpression) {
4984
5257
  return null;
4985
5258
  }
4986
5259
  const fields = /* @__PURE__ */ new Map();
4987
5260
  for (const property of shape.properties) {
4988
- if (property.type !== AST_NODE_TYPES19.Property || property.computed) {
5261
+ if (property.type !== AST_NODE_TYPES20.Property || property.computed) {
4989
5262
  return null;
4990
5263
  }
4991
5264
  const { key } = property;
4992
- const name = key.type === AST_NODE_TYPES19.Identifier ? key.name : key.type === AST_NODE_TYPES19.Literal && typeof key.value === "string" ? key.value : null;
5265
+ const name = key.type === AST_NODE_TYPES20.Identifier ? key.name : key.type === AST_NODE_TYPES20.Literal && typeof key.value === "string" ? key.value : null;
4993
5266
  if (name === null) {
4994
5267
  return null;
4995
5268
  }
@@ -5000,11 +5273,11 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5000
5273
  function typeMembers(members) {
5001
5274
  const result = /* @__PURE__ */ new Map();
5002
5275
  for (const member of members) {
5003
- if (member.type !== AST_NODE_TYPES19.TSPropertySignature || member.computed) {
5276
+ if (member.type !== AST_NODE_TYPES20.TSPropertySignature || member.computed) {
5004
5277
  return null;
5005
5278
  }
5006
5279
  const { key } = member;
5007
- const name = key.type === AST_NODE_TYPES19.Identifier ? key.name : key.type === AST_NODE_TYPES19.Literal && typeof key.value === "string" ? key.value : null;
5280
+ const name = key.type === AST_NODE_TYPES20.Identifier ? key.name : key.type === AST_NODE_TYPES20.Literal && typeof key.value === "string" ? key.value : null;
5008
5281
  if (name === null) {
5009
5282
  return null;
5010
5283
  }
@@ -5018,8 +5291,8 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5018
5291
  return result.size === 0 ? null : result;
5019
5292
  }
5020
5293
  function collectConstrainedNames(node) {
5021
- if (node.type === AST_NODE_TYPES19.TSTypeReference) {
5022
- if (node.typeName.type === AST_NODE_TYPES19.Identifier) {
5294
+ if (node.type === AST_NODE_TYPES20.TSTypeReference) {
5295
+ if (node.typeName.type === AST_NODE_TYPES20.Identifier) {
5023
5296
  constrainedTypeNames.add(node.typeName.name);
5024
5297
  }
5025
5298
  for (const argument of node.typeArguments?.params ?? []) {
@@ -5027,11 +5300,11 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5027
5300
  }
5028
5301
  return;
5029
5302
  }
5030
- if (node.type === AST_NODE_TYPES19.TSArrayType) {
5303
+ if (node.type === AST_NODE_TYPES20.TSArrayType) {
5031
5304
  collectConstrainedNames(node.elementType);
5032
5305
  return;
5033
5306
  }
5034
- if (node.type === AST_NODE_TYPES19.TSUnionType || node.type === AST_NODE_TYPES19.TSIntersectionType) {
5307
+ if (node.type === AST_NODE_TYPES20.TSUnionType || node.type === AST_NODE_TYPES20.TSIntersectionType) {
5035
5308
  for (const member of node.types) {
5036
5309
  collectConstrainedNames(member);
5037
5310
  }
@@ -5075,13 +5348,13 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5075
5348
  return;
5076
5349
  }
5077
5350
  for (const specifier of node.specifiers) {
5078
- if (specifier.type === AST_NODE_TYPES19.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES19.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES19.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES19.Identifier && specifier.imported.name === "z") {
5351
+ if (specifier.type === AST_NODE_TYPES20.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES20.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES20.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES20.Identifier && specifier.imported.name === "z") {
5079
5352
  zodNamespaces.add(specifier.local.name);
5080
5353
  }
5081
5354
  }
5082
5355
  },
5083
5356
  VariableDeclarator(node) {
5084
- if (node.id.type !== AST_NODE_TYPES19.Identifier || node.init == null) {
5357
+ if (node.id.type !== AST_NODE_TYPES20.Identifier || node.init == null) {
5085
5358
  return;
5086
5359
  }
5087
5360
  const fields = schemaFields(node.init);
@@ -5091,14 +5364,14 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5091
5364
  },
5092
5365
  /** Guard (f): `XSchema.transform(...)` anywhere in the module. */
5093
5366
  "MemberExpression[computed=false]"(node) {
5094
- if (node.object.type === AST_NODE_TYPES19.Identifier && node.property.type === AST_NODE_TYPES19.Identifier && MODULE_LEVEL_RESHAPERS.has(node.property.name)) {
5367
+ if (node.object.type === AST_NODE_TYPES20.Identifier && node.property.type === AST_NODE_TYPES20.Identifier && MODULE_LEVEL_RESHAPERS.has(node.property.name)) {
5095
5368
  reshapedSchemaNames.add(node.object.name);
5096
5369
  }
5097
5370
  },
5098
5371
  /** Guard (c): `z.ZodType<T>` and every other type argument it carries. */
5099
5372
  TSTypeReference(node) {
5100
5373
  const { typeName } = node;
5101
- const referenced = typeName.type === AST_NODE_TYPES19.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES19.TSQualifiedName && typeName.right.type === AST_NODE_TYPES19.Identifier ? typeName.right.name : null;
5374
+ const referenced = typeName.type === AST_NODE_TYPES20.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES20.TSQualifiedName && typeName.right.type === AST_NODE_TYPES20.Identifier ? typeName.right.name : null;
5102
5375
  if (referenced === null || !ZOD_TYPE_CONSTRAINTS.has(referenced)) {
5103
5376
  return;
5104
5377
  }
@@ -5116,7 +5389,7 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5116
5389
  }
5117
5390
  },
5118
5391
  TSTypeAliasDeclaration(node) {
5119
- if (node.typeParameters !== void 0 || node.typeAnnotation.type !== AST_NODE_TYPES19.TSTypeLiteral) {
5392
+ if (node.typeParameters !== void 0 || node.typeAnnotation.type !== AST_NODE_TYPES20.TSTypeLiteral) {
5120
5393
  return;
5121
5394
  }
5122
5395
  const members = typeMembers(node.typeAnnotation.members);
@@ -5161,10 +5434,10 @@ var prefer_zod_infer_default = ESLintUtils28.RuleCreator(
5161
5434
  });
5162
5435
 
5163
5436
  // src/rules/no-offset-pagination.ts
5164
- import { ESLintUtils as ESLintUtils29 } from "@typescript-eslint/utils";
5437
+ import { ESLintUtils as ESLintUtils28 } from "@typescript-eslint/utils";
5165
5438
 
5166
5439
  // src/rules/_sql.ts
5167
- import { AST_NODE_TYPES as AST_NODE_TYPES20 } from "@typescript-eslint/utils";
5440
+ import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
5168
5441
  function stripSqlNoise(text) {
5169
5442
  const out = [...text];
5170
5443
  const n = text.length;
@@ -5225,13 +5498,13 @@ function stripSqlNoise(text) {
5225
5498
  var SUBSTITUTION_MARKER = "?";
5226
5499
  function sqlTextOf(node) {
5227
5500
  switch (node.type) {
5228
- case AST_NODE_TYPES20.Literal:
5501
+ case AST_NODE_TYPES21.Literal:
5229
5502
  return typeof node.value === "string" ? node.value : null;
5230
- case AST_NODE_TYPES20.TemplateLiteral:
5503
+ case AST_NODE_TYPES21.TemplateLiteral:
5231
5504
  return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join(SUBSTITUTION_MARKER);
5232
- case AST_NODE_TYPES20.TaggedTemplateExpression:
5505
+ case AST_NODE_TYPES21.TaggedTemplateExpression:
5233
5506
  return sqlTextOf(node.quasi);
5234
- case AST_NODE_TYPES20.BinaryExpression: {
5507
+ case AST_NODE_TYPES21.BinaryExpression: {
5235
5508
  if (node.operator !== "+") {
5236
5509
  return null;
5237
5510
  }
@@ -5239,7 +5512,7 @@ function sqlTextOf(node) {
5239
5512
  const right = sqlTextOf(node.right);
5240
5513
  return left !== null && right !== null ? left + right : null;
5241
5514
  }
5242
- case AST_NODE_TYPES20.ArrayExpression: {
5515
+ case AST_NODE_TYPES21.ArrayExpression: {
5243
5516
  const parts = [];
5244
5517
  for (const element of node.elements) {
5245
5518
  if (element === null) {
@@ -5259,7 +5532,7 @@ function sqlTextOf(node) {
5259
5532
  }
5260
5533
  function isJoinedFragmentArray(node) {
5261
5534
  const parent = node.parent;
5262
- return parent?.type === AST_NODE_TYPES20.MemberExpression && parent.object === node && !parent.computed && parent.property.type === AST_NODE_TYPES20.Identifier && parent.property.name === "join" && parent.parent?.type === AST_NODE_TYPES20.CallExpression;
5535
+ return parent?.type === AST_NODE_TYPES21.MemberExpression && parent.object === node && !parent.computed && parent.property.type === AST_NODE_TYPES21.Identifier && parent.property.name === "join" && parent.parent?.type === AST_NODE_TYPES21.CallExpression;
5263
5536
  }
5264
5537
  function markConsumed(node, consumed) {
5265
5538
  consumed.add(node);
@@ -5309,7 +5582,7 @@ function createSqlListener(handler) {
5309
5582
  // src/rules/no-offset-pagination.ts
5310
5583
  var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
5311
5584
  var OFFSET_GATE = /offset/i;
5312
- var no_offset_pagination_default = ESLintUtils29.RuleCreator(
5585
+ var no_offset_pagination_default = ESLintUtils28.RuleCreator(
5313
5586
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5314
5587
  )({
5315
5588
  name: "no-offset-pagination",
@@ -5338,15 +5611,15 @@ var no_offset_pagination_default = ESLintUtils29.RuleCreator(
5338
5611
  });
5339
5612
 
5340
5613
  // src/rules/no-positional-tuple-return.ts
5341
- import { AST_NODE_TYPES as AST_NODE_TYPES21, ESLintUtils as ESLintUtils30 } from "@typescript-eslint/utils";
5614
+ import { AST_NODE_TYPES as AST_NODE_TYPES22, ESLintUtils as ESLintUtils29 } from "@typescript-eslint/utils";
5342
5615
  var MIN_ELEMENTS = 2;
5343
5616
  var ACCESSOR_PAIR_LENGTH = 2;
5344
5617
  var AWAITABLE_TYPES = /* @__PURE__ */ new Set(["Promise", "PromiseLike", "Awaited"]);
5345
5618
  function tupleReturnType(node) {
5346
- if (node.type === AST_NODE_TYPES21.TSTupleType) {
5619
+ if (node.type === AST_NODE_TYPES22.TSTupleType) {
5347
5620
  return node;
5348
5621
  }
5349
- if (node.type === AST_NODE_TYPES21.TSTypeReference && node.typeName.type === AST_NODE_TYPES21.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5622
+ if (node.type === AST_NODE_TYPES22.TSTypeReference && node.typeName.type === AST_NODE_TYPES22.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5350
5623
  const argument = node.typeArguments?.params[0];
5351
5624
  return argument === void 0 ? null : tupleReturnType(argument);
5352
5625
  }
@@ -5360,30 +5633,30 @@ function isPermittedTuple(tuple, sourceCode) {
5360
5633
  if (elements.length < MIN_ELEMENTS) {
5361
5634
  return true;
5362
5635
  }
5363
- if (elements.some((element) => element.type === AST_NODE_TYPES21.TSRestType)) {
5636
+ if (elements.some((element) => element.type === AST_NODE_TYPES22.TSRestType)) {
5364
5637
  return true;
5365
5638
  }
5366
- if (elements.some((element) => element.type === AST_NODE_TYPES21.TSNamedTupleMember)) {
5639
+ if (elements.some((element) => element.type === AST_NODE_TYPES22.TSNamedTupleMember)) {
5367
5640
  return true;
5368
5641
  }
5369
- if (elements[0]?.type === AST_NODE_TYPES21.TSLiteralType) {
5642
+ if (elements[0]?.type === AST_NODE_TYPES22.TSLiteralType) {
5370
5643
  return true;
5371
5644
  }
5372
- if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === AST_NODE_TYPES21.TSFunctionType)) {
5645
+ if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === AST_NODE_TYPES22.TSFunctionType)) {
5373
5646
  return true;
5374
5647
  }
5375
5648
  const texts = new Set(elements.map((element) => normalizedText(sourceCode, element)));
5376
5649
  return texts.size === 1;
5377
5650
  }
5378
5651
  function functionName(node) {
5379
- if (node.type === AST_NODE_TYPES21.FunctionDeclaration) {
5652
+ if (node.type === AST_NODE_TYPES22.FunctionDeclaration) {
5380
5653
  return node.id?.name ?? null;
5381
5654
  }
5382
5655
  const parent = node.parent;
5383
- if (parent?.type === AST_NODE_TYPES21.VariableDeclarator && parent.id.type === AST_NODE_TYPES21.Identifier) {
5656
+ if (parent?.type === AST_NODE_TYPES22.VariableDeclarator && parent.id.type === AST_NODE_TYPES22.Identifier) {
5384
5657
  return parent.id.name;
5385
5658
  }
5386
- if ((parent?.type === AST_NODE_TYPES21.MethodDefinition || parent?.type === AST_NODE_TYPES21.PropertyDefinition || parent?.type === AST_NODE_TYPES21.Property) && parent.key.type === AST_NODE_TYPES21.Identifier) {
5659
+ if ((parent?.type === AST_NODE_TYPES22.MethodDefinition || parent?.type === AST_NODE_TYPES22.PropertyDefinition || parent?.type === AST_NODE_TYPES22.Property) && parent.key.type === AST_NODE_TYPES22.Identifier) {
5387
5660
  return parent.key.name;
5388
5661
  }
5389
5662
  return null;
@@ -5391,7 +5664,7 @@ function functionName(node) {
5391
5664
  function isInlineExported(node) {
5392
5665
  for (let current = node; current != null; current = current.parent) {
5393
5666
  const parent = current.parent;
5394
- if (parent?.type === AST_NODE_TYPES21.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES21.ExportDefaultDeclaration) {
5667
+ if (parent?.type === AST_NODE_TYPES22.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES22.ExportDefaultDeclaration) {
5395
5668
  return true;
5396
5669
  }
5397
5670
  }
@@ -5400,18 +5673,18 @@ function isInlineExported(node) {
5400
5673
  function moduleScopeBindingName(node) {
5401
5674
  let current = node;
5402
5675
  let child = node;
5403
- while (current.parent != null && current.parent.type !== AST_NODE_TYPES21.Program) {
5676
+ while (current.parent != null && current.parent.type !== AST_NODE_TYPES22.Program) {
5404
5677
  child = current;
5405
5678
  current = current.parent;
5406
5679
  }
5407
- if (current.parent?.type !== AST_NODE_TYPES21.Program) {
5680
+ if (current.parent?.type !== AST_NODE_TYPES22.Program) {
5408
5681
  return null;
5409
5682
  }
5410
- if (current.type === AST_NODE_TYPES21.FunctionDeclaration || current.type === AST_NODE_TYPES21.ClassDeclaration) {
5683
+ if (current.type === AST_NODE_TYPES22.FunctionDeclaration || current.type === AST_NODE_TYPES22.ClassDeclaration) {
5411
5684
  return current.id?.name ?? null;
5412
5685
  }
5413
- if (current.type === AST_NODE_TYPES21.VariableDeclaration) {
5414
- if (child.type !== AST_NODE_TYPES21.VariableDeclarator || child.id.type !== AST_NODE_TYPES21.Identifier) {
5686
+ if (current.type === AST_NODE_TYPES22.VariableDeclaration) {
5687
+ if (child.type !== AST_NODE_TYPES22.VariableDeclarator || child.id.type !== AST_NODE_TYPES22.Identifier) {
5415
5688
  return null;
5416
5689
  }
5417
5690
  return child.id.name;
@@ -5421,19 +5694,19 @@ function moduleScopeBindingName(node) {
5421
5694
  function specifierExportedNames(program) {
5422
5695
  const names = /* @__PURE__ */ new Set();
5423
5696
  for (const statement of program.body) {
5424
- if (statement.type === AST_NODE_TYPES21.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5697
+ if (statement.type === AST_NODE_TYPES22.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5425
5698
  for (const specifier of statement.specifiers) {
5426
- if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES21.Identifier) {
5699
+ if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES22.Identifier) {
5427
5700
  names.add(specifier.local.name);
5428
5701
  }
5429
5702
  }
5430
5703
  continue;
5431
5704
  }
5432
- if (statement.type === AST_NODE_TYPES21.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES21.Identifier) {
5705
+ if (statement.type === AST_NODE_TYPES22.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES22.Identifier) {
5433
5706
  names.add(statement.declaration.name);
5434
5707
  continue;
5435
5708
  }
5436
- if (statement.type === AST_NODE_TYPES21.TSExportAssignment && statement.expression.type === AST_NODE_TYPES21.Identifier) {
5709
+ if (statement.type === AST_NODE_TYPES22.TSExportAssignment && statement.expression.type === AST_NODE_TYPES22.Identifier) {
5437
5710
  names.add(statement.expression.name);
5438
5711
  }
5439
5712
  }
@@ -5449,7 +5722,7 @@ function isExported(node, specifierExports) {
5449
5722
  const binding = moduleScopeBindingName(node);
5450
5723
  return binding !== null && specifierExports.has(binding);
5451
5724
  }
5452
- var no_positional_tuple_return_default = ESLintUtils30.RuleCreator(
5725
+ var no_positional_tuple_return_default = ESLintUtils29.RuleCreator(
5453
5726
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5454
5727
  )({
5455
5728
  name: "no-positional-tuple-return",
@@ -5497,16 +5770,16 @@ var no_positional_tuple_return_default = ESLintUtils30.RuleCreator(
5497
5770
  });
5498
5771
 
5499
5772
  // src/rules/no-repeated-string-literal.ts
5500
- import { AST_NODE_TYPES as AST_NODE_TYPES22, ESLintUtils as ESLintUtils31 } from "@typescript-eslint/utils";
5773
+ import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils30 } from "@typescript-eslint/utils";
5501
5774
  var MIN_LENGTH = 40;
5502
5775
  var MIN_DISTINCT_SCOPES = 2;
5503
5776
  var PREVIEW_LENGTH = 40;
5504
5777
  var SQL_KEYWORD_RE = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES|ON CONFLICT|RETURNING|GROUP BY|ORDER BY)\b/;
5505
5778
  var IDENTIFIER_RE = /^[a-z_][a-z0-9_.]*$/;
5506
- var FUNCTION_TYPES = /* @__PURE__ */ new Set([
5507
- AST_NODE_TYPES22.FunctionDeclaration,
5508
- AST_NODE_TYPES22.FunctionExpression,
5509
- AST_NODE_TYPES22.ArrowFunctionExpression
5779
+ var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5780
+ AST_NODE_TYPES23.FunctionDeclaration,
5781
+ AST_NODE_TYPES23.FunctionExpression,
5782
+ AST_NODE_TYPES23.ArrowFunctionExpression
5510
5783
  ]);
5511
5784
  function isStructured(value) {
5512
5785
  return value.includes("\n") || SQL_KEYWORD_RE.test(value) || IDENTIFIER_RE.test(value);
@@ -5517,7 +5790,7 @@ function preview(value) {
5517
5790
  }
5518
5791
  function enclosingFunction(node) {
5519
5792
  for (let current = node.parent; current != null; current = current.parent) {
5520
- if (FUNCTION_TYPES.has(current.type)) {
5793
+ if (FUNCTION_TYPES2.has(current.type)) {
5521
5794
  return current;
5522
5795
  }
5523
5796
  }
@@ -5528,9 +5801,9 @@ function isScaffolding(node) {
5528
5801
  if (parent === void 0) {
5529
5802
  return true;
5530
5803
  }
5531
- return parent.type === AST_NODE_TYPES22.ImportDeclaration || parent.type === AST_NODE_TYPES22.ExportNamedDeclaration || parent.type === AST_NODE_TYPES22.ExportAllDeclaration || parent.type === AST_NODE_TYPES22.TSImportType || parent.type === AST_NODE_TYPES22.JSXAttribute || parent.type === AST_NODE_TYPES22.TSLiteralType;
5804
+ return parent.type === AST_NODE_TYPES23.ImportDeclaration || parent.type === AST_NODE_TYPES23.ExportNamedDeclaration || parent.type === AST_NODE_TYPES23.ExportAllDeclaration || parent.type === AST_NODE_TYPES23.TSImportType || parent.type === AST_NODE_TYPES23.JSXAttribute || parent.type === AST_NODE_TYPES23.TSLiteralType;
5532
5805
  }
5533
- var no_repeated_string_literal_default = ESLintUtils31.RuleCreator(
5806
+ var no_repeated_string_literal_default = ESLintUtils30.RuleCreator(
5534
5807
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5535
5808
  )({
5536
5809
  name: "no-repeated-string-literal",
@@ -5570,7 +5843,7 @@ var no_repeated_string_literal_default = ESLintUtils31.RuleCreator(
5570
5843
  }
5571
5844
  },
5572
5845
  TemplateLiteral(node) {
5573
- if (node.parent.type === AST_NODE_TYPES22.TaggedTemplateExpression) {
5846
+ if (node.parent.type === AST_NODE_TYPES23.TaggedTemplateExpression) {
5574
5847
  return;
5575
5848
  }
5576
5849
  const [only] = node.quasis;
@@ -5604,7 +5877,7 @@ var no_repeated_string_literal_default = ESLintUtils31.RuleCreator(
5604
5877
  });
5605
5878
 
5606
5879
  // src/rules/no-select-star.ts
5607
- import { ESLintUtils as ESLintUtils32 } from "@typescript-eslint/utils";
5880
+ import { ESLintUtils as ESLintUtils31 } from "@typescript-eslint/utils";
5608
5881
  var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
5609
5882
  var SELECT_KEYWORD = /\bSELECT\b/gi;
5610
5883
  var FROM_KEYWORD = /^FROM\b/i;
@@ -5644,7 +5917,7 @@ function hasRealSelectStar(sql) {
5644
5917
  }
5645
5918
  return false;
5646
5919
  }
5647
- var no_select_star_default = ESLintUtils32.RuleCreator(
5920
+ var no_select_star_default = ESLintUtils31.RuleCreator(
5648
5921
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5649
5922
  )({
5650
5923
  name: "no-select-star",
@@ -5673,7 +5946,7 @@ var no_select_star_default = ESLintUtils32.RuleCreator(
5673
5946
  });
5674
5947
 
5675
5948
  // src/rules/no-sleep-in-test-body.ts
5676
- import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils33 } from "@typescript-eslint/utils";
5949
+ import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils32 } from "@typescript-eslint/utils";
5677
5950
  var SLEEP_HELPERS = /* @__PURE__ */ new Set(["sleep", "delay", "wait", "pause"]);
5678
5951
  var TEST_CALLERS = /* @__PURE__ */ new Set([
5679
5952
  "it",
@@ -5681,43 +5954,43 @@ var TEST_CALLERS = /* @__PURE__ */ new Set([
5681
5954
  "beforeEach",
5682
5955
  "afterEach"
5683
5956
  ]);
5684
- var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5685
- AST_NODE_TYPES23.FunctionDeclaration,
5686
- AST_NODE_TYPES23.FunctionExpression,
5687
- AST_NODE_TYPES23.ArrowFunctionExpression
5957
+ var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5958
+ AST_NODE_TYPES24.FunctionDeclaration,
5959
+ AST_NODE_TYPES24.FunctionExpression,
5960
+ AST_NODE_TYPES24.ArrowFunctionExpression
5688
5961
  ]);
5689
5962
  function isNonzeroNumericLiteral(node) {
5690
- return node?.type === AST_NODE_TYPES23.Literal && typeof node.value === "number" && node.value !== 0;
5963
+ return node?.type === AST_NODE_TYPES24.Literal && typeof node.value === "number" && node.value !== 0;
5691
5964
  }
5692
5965
  function isTimedSetTimeout(node) {
5693
- return node.type === AST_NODE_TYPES23.CallExpression && node.callee.type === AST_NODE_TYPES23.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5966
+ return node.type === AST_NODE_TYPES24.CallExpression && node.callee.type === AST_NODE_TYPES24.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5694
5967
  }
5695
5968
  function isPromiseSleep(node) {
5696
- if (node.callee.type !== AST_NODE_TYPES23.Identifier || node.callee.name !== "Promise") {
5969
+ if (node.callee.type !== AST_NODE_TYPES24.Identifier || node.callee.name !== "Promise") {
5697
5970
  return false;
5698
5971
  }
5699
5972
  const executor = node.arguments[0];
5700
- if (executor?.type !== AST_NODE_TYPES23.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES23.FunctionExpression) {
5973
+ if (executor?.type !== AST_NODE_TYPES24.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES24.FunctionExpression) {
5701
5974
  return false;
5702
5975
  }
5703
5976
  const body = executor.body;
5704
- if (body.type !== AST_NODE_TYPES23.BlockStatement) {
5977
+ if (body.type !== AST_NODE_TYPES24.BlockStatement) {
5705
5978
  return isTimedSetTimeout(body);
5706
5979
  }
5707
5980
  return body.body.some(
5708
- (stmt) => stmt.type === AST_NODE_TYPES23.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5981
+ (stmt) => stmt.type === AST_NODE_TYPES24.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5709
5982
  );
5710
5983
  }
5711
5984
  function isHelperSleep(node) {
5712
- return node.callee.type === AST_NODE_TYPES23.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5985
+ return node.callee.type === AST_NODE_TYPES24.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5713
5986
  }
5714
5987
  function nearestEnclosingFunction(node) {
5715
5988
  for (let current = node.parent; current != null; current = current.parent) {
5716
- if (!FUNCTION_TYPES2.has(current.type)) {
5989
+ if (!FUNCTION_TYPES3.has(current.type)) {
5717
5990
  continue;
5718
5991
  }
5719
5992
  const grandparent = current.parent;
5720
- const isPromiseExecutor = grandparent?.type === AST_NODE_TYPES23.NewExpression && isPromiseSleep(grandparent);
5993
+ const isPromiseExecutor = grandparent?.type === AST_NODE_TYPES24.NewExpression && isPromiseSleep(grandparent);
5721
5994
  if (!isPromiseExecutor) {
5722
5995
  return current;
5723
5996
  }
@@ -5725,29 +5998,29 @@ function nearestEnclosingFunction(node) {
5725
5998
  return null;
5726
5999
  }
5727
6000
  function testCallerName(callee) {
5728
- if (callee.type === AST_NODE_TYPES23.Identifier) {
6001
+ if (callee.type === AST_NODE_TYPES24.Identifier) {
5729
6002
  return callee.name;
5730
6003
  }
5731
- if (callee.type === AST_NODE_TYPES23.MemberExpression) {
6004
+ if (callee.type === AST_NODE_TYPES24.MemberExpression) {
5732
6005
  return testCallerName(callee.object);
5733
6006
  }
5734
- if (callee.type === AST_NODE_TYPES23.CallExpression) {
6007
+ if (callee.type === AST_NODE_TYPES24.CallExpression) {
5735
6008
  return testCallerName(callee.callee);
5736
6009
  }
5737
- if (callee.type === AST_NODE_TYPES23.TaggedTemplateExpression) {
6010
+ if (callee.type === AST_NODE_TYPES24.TaggedTemplateExpression) {
5738
6011
  return testCallerName(callee.tag);
5739
6012
  }
5740
6013
  return null;
5741
6014
  }
5742
6015
  function isTestBody(fn) {
5743
6016
  const call = fn.parent;
5744
- if (call?.type !== AST_NODE_TYPES23.CallExpression || !call.arguments.some((argument) => argument === fn)) {
6017
+ if (call?.type !== AST_NODE_TYPES24.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5745
6018
  return false;
5746
6019
  }
5747
6020
  const name = testCallerName(call.callee);
5748
6021
  return name !== null && TEST_CALLERS.has(name);
5749
6022
  }
5750
- var no_sleep_in_test_body_default = ESLintUtils33.RuleCreator(
6023
+ var no_sleep_in_test_body_default = ESLintUtils32.RuleCreator(
5751
6024
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5752
6025
  )({
5753
6026
  name: "no-sleep-in-test-body",
@@ -5789,45 +6062,215 @@ var no_sleep_in_test_body_default = ESLintUtils33.RuleCreator(
5789
6062
  });
5790
6063
 
5791
6064
  // src/rules/no-conditional-in-test.ts
5792
- import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils34 } from "@typescript-eslint/utils";
6065
+ import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils33 } from "@typescript-eslint/utils";
5793
6066
  var TEST_CALLERS2 = /* @__PURE__ */ new Set(["it", "test"]);
5794
- var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5795
- AST_NODE_TYPES24.FunctionDeclaration,
5796
- AST_NODE_TYPES24.FunctionExpression,
5797
- AST_NODE_TYPES24.ArrowFunctionExpression
6067
+ var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6068
+ AST_NODE_TYPES25.FunctionDeclaration,
6069
+ AST_NODE_TYPES25.FunctionExpression,
6070
+ AST_NODE_TYPES25.ArrowFunctionExpression
6071
+ ]);
6072
+ var ASSERTION_ROOTS = /* @__PURE__ */ new Set([
6073
+ "expect",
6074
+ "expectTypeOf",
6075
+ "assert",
6076
+ "assertType"
6077
+ ]);
6078
+ var TYPE_ASSERTION_ROOTS = /* @__PURE__ */ new Set([
6079
+ "expectTypeOf",
6080
+ "assertType"
5798
6081
  ]);
5799
6082
  function nearestEnclosingFunction2(node) {
5800
6083
  for (let current = node.parent; current != null; current = current.parent) {
5801
- if (FUNCTION_TYPES3.has(current.type)) {
6084
+ if (FUNCTION_TYPES4.has(current.type)) {
5802
6085
  return current;
5803
6086
  }
5804
6087
  }
5805
6088
  return null;
5806
6089
  }
5807
6090
  function testCallerName2(callee) {
5808
- if (callee.type === AST_NODE_TYPES24.Identifier) {
6091
+ if (callee.type === AST_NODE_TYPES25.Identifier) {
5809
6092
  return callee.name;
5810
6093
  }
5811
- if (callee.type === AST_NODE_TYPES24.MemberExpression) {
6094
+ if (callee.type === AST_NODE_TYPES25.MemberExpression) {
5812
6095
  return testCallerName2(callee.object);
5813
6096
  }
5814
- if (callee.type === AST_NODE_TYPES24.CallExpression) {
6097
+ if (callee.type === AST_NODE_TYPES25.CallExpression) {
5815
6098
  return testCallerName2(callee.callee);
5816
6099
  }
5817
- if (callee.type === AST_NODE_TYPES24.TaggedTemplateExpression) {
6100
+ if (callee.type === AST_NODE_TYPES25.TaggedTemplateExpression) {
5818
6101
  return testCallerName2(callee.tag);
5819
6102
  }
5820
6103
  return null;
5821
6104
  }
5822
6105
  function isTestBody2(fn) {
5823
6106
  const call = fn.parent;
5824
- if (call?.type !== AST_NODE_TYPES24.CallExpression || !call.arguments.some((argument) => argument === fn)) {
6107
+ if (call?.type !== AST_NODE_TYPES25.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5825
6108
  return false;
5826
6109
  }
5827
6110
  const name = testCallerName2(call.callee);
5828
6111
  return name !== null && TEST_CALLERS2.has(name);
5829
6112
  }
5830
- var no_conditional_in_test_default = ESLintUtils34.RuleCreator(
6113
+ function subtreeMatches2(node, predicate, descendIntoFunctions = true) {
6114
+ let found = false;
6115
+ const visit = (current) => {
6116
+ if (found) {
6117
+ return;
6118
+ }
6119
+ if (predicate(current)) {
6120
+ found = true;
6121
+ return;
6122
+ }
6123
+ for (const key of Object.keys(current)) {
6124
+ if (key === "parent") {
6125
+ continue;
6126
+ }
6127
+ if (!descendIntoFunctions && FUNCTION_TYPES4.has(current.type) && key === "body") {
6128
+ continue;
6129
+ }
6130
+ const value = current[key];
6131
+ if (Array.isArray(value)) {
6132
+ for (const child of value) {
6133
+ if (typeof child === "object" && child !== null && typeof child.type === "string") {
6134
+ visit(child);
6135
+ }
6136
+ }
6137
+ } else if (typeof value === "object" && value !== null && typeof value.type === "string") {
6138
+ visit(value);
6139
+ }
6140
+ if (found) {
6141
+ return;
6142
+ }
6143
+ }
6144
+ };
6145
+ visit(node);
6146
+ return found;
6147
+ }
6148
+ function rootIdentifier(node) {
6149
+ switch (node.type) {
6150
+ case AST_NODE_TYPES25.Identifier:
6151
+ return node.name;
6152
+ case AST_NODE_TYPES25.MemberExpression:
6153
+ return rootIdentifier(node.object);
6154
+ case AST_NODE_TYPES25.UnaryExpression:
6155
+ return rootIdentifier(node.argument);
6156
+ case AST_NODE_TYPES25.AwaitExpression:
6157
+ return rootIdentifier(node.argument);
6158
+ case AST_NODE_TYPES25.ChainExpression:
6159
+ case AST_NODE_TYPES25.TSNonNullExpression:
6160
+ case AST_NODE_TYPES25.TSAsExpression:
6161
+ return rootIdentifier(node.expression);
6162
+ case AST_NODE_TYPES25.BinaryExpression:
6163
+ case AST_NODE_TYPES25.LogicalExpression:
6164
+ return rootIdentifier(node.left);
6165
+ case AST_NODE_TYPES25.CallExpression:
6166
+ return rootIdentifier(node.callee);
6167
+ default:
6168
+ return null;
6169
+ }
6170
+ }
6171
+ function calleeRootName(call) {
6172
+ let current = call.callee;
6173
+ for (; ; ) {
6174
+ if (current.type === AST_NODE_TYPES25.Identifier) {
6175
+ return current.name;
6176
+ }
6177
+ if (current.type === AST_NODE_TYPES25.MemberExpression) {
6178
+ current = current.object;
6179
+ continue;
6180
+ }
6181
+ if (current.type === AST_NODE_TYPES25.CallExpression) {
6182
+ current = current.callee;
6183
+ continue;
6184
+ }
6185
+ if (current.type === AST_NODE_TYPES25.ChainExpression || current.type === AST_NODE_TYPES25.TSNonNullExpression) {
6186
+ current = current.expression;
6187
+ continue;
6188
+ }
6189
+ return null;
6190
+ }
6191
+ }
6192
+ var isAssertionCall = (node) => node.type === AST_NODE_TYPES25.CallExpression && ASSERTION_ROOTS.has(calleeRootName(node) ?? "");
6193
+ var isTypeAssertionCall = (node) => node.type === AST_NODE_TYPES25.CallExpression && TYPE_ASSERTION_ROOTS.has(calleeRootName(node) ?? "");
6194
+ var containsAssertion = (node) => subtreeMatches2(node, isAssertionCall);
6195
+ var containsSkipCall = (node) => subtreeMatches2(
6196
+ node,
6197
+ (current) => current.type === AST_NODE_TYPES25.CallExpression && current.callee.type === AST_NODE_TYPES25.MemberExpression && !current.callee.computed && current.callee.property.type === AST_NODE_TYPES25.Identifier && current.callee.property.name === "skip"
6198
+ );
6199
+ var containsEscape = (node) => subtreeMatches2(
6200
+ node,
6201
+ (current) => current.type === AST_NODE_TYPES25.ReturnStatement || current.type === AST_NODE_TYPES25.ContinueStatement || current.type === AST_NODE_TYPES25.BreakStatement,
6202
+ false
6203
+ );
6204
+ function branchStatements(branch) {
6205
+ return branch.type === AST_NODE_TYPES25.BlockStatement ? branch.body : [branch];
6206
+ }
6207
+ function previousSibling(node) {
6208
+ const parent = node.parent;
6209
+ let siblings = null;
6210
+ if (parent.type === AST_NODE_TYPES25.BlockStatement || parent.type === AST_NODE_TYPES25.Program || parent.type === AST_NODE_TYPES25.StaticBlock) {
6211
+ siblings = parent.body;
6212
+ } else if (parent.type === AST_NODE_TYPES25.SwitchCase) {
6213
+ siblings = parent.consequent;
6214
+ }
6215
+ if (siblings === null) {
6216
+ return null;
6217
+ }
6218
+ const index = siblings.indexOf(node);
6219
+ return index > 0 ? siblings[index - 1] ?? null : null;
6220
+ }
6221
+ function isPinnedNarrowingGuard(node) {
6222
+ const testRoot = rootIdentifier(node.test);
6223
+ if (testRoot === null) {
6224
+ return false;
6225
+ }
6226
+ const previous = previousSibling(node);
6227
+ if (previous === null || previous.type !== AST_NODE_TYPES25.ExpressionStatement) {
6228
+ return false;
6229
+ }
6230
+ let matched = false;
6231
+ subtreeMatches2(previous, (current) => {
6232
+ if (current.type !== AST_NODE_TYPES25.CallExpression || current.callee.type !== AST_NODE_TYPES25.Identifier || current.callee.name !== "expect") {
6233
+ return false;
6234
+ }
6235
+ const subject = current.arguments[0];
6236
+ if (subject === void 0) {
6237
+ return false;
6238
+ }
6239
+ if (rootIdentifier(subject) === testRoot) {
6240
+ matched = true;
6241
+ return true;
6242
+ }
6243
+ return false;
6244
+ });
6245
+ return matched;
6246
+ }
6247
+ function isThrowingGuard(node) {
6248
+ if (node.alternate !== null) {
6249
+ return false;
6250
+ }
6251
+ const statements = branchStatements(node.consequent);
6252
+ return statements.length === 1 && statements[0]?.type === AST_NODE_TYPES25.ThrowStatement;
6253
+ }
6254
+ function isTypeAssertionBranch(branch) {
6255
+ const statements = branchStatements(branch);
6256
+ return statements.length > 0 && statements.every(
6257
+ (statement) => statement.type === AST_NODE_TYPES25.ExpressionStatement && isTypeAssertionCall(statement.expression)
6258
+ );
6259
+ }
6260
+ function isTypeLevelNarrowing(node) {
6261
+ return isTypeAssertionBranch(node.consequent) && (node.alternate === null || isTypeAssertionBranch(node.alternate));
6262
+ }
6263
+ var isInertBranch = (branch) => !containsAssertion(branch) && !containsEscape(branch) && !containsSkipCall(branch);
6264
+ function isInertNormalization(node) {
6265
+ return isInertBranch(node.consequent) && (node.alternate === null || isInertBranch(node.alternate));
6266
+ }
6267
+ function isExemptIfStatement(node) {
6268
+ return isPinnedNarrowingGuard(node) || isThrowingGuard(node) || isTypeLevelNarrowing(node) || isInertNormalization(node);
6269
+ }
6270
+ function isShortCircuitedAssertion(node) {
6271
+ return node.operator !== "??" && node.parent.type === AST_NODE_TYPES25.ExpressionStatement && containsAssertion(node.right);
6272
+ }
6273
+ var no_conditional_in_test_default = ESLintUtils33.RuleCreator(
5831
6274
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5832
6275
  )({
5833
6276
  name: "no-conditional-in-test",
@@ -5855,6 +6298,9 @@ var no_conditional_in_test_default = ESLintUtils34.RuleCreator(
5855
6298
  };
5856
6299
  return {
5857
6300
  IfStatement(node) {
6301
+ if (isExemptIfStatement(node)) {
6302
+ return;
6303
+ }
5858
6304
  report(node);
5859
6305
  },
5860
6306
  SwitchStatement(node) {
@@ -5864,6 +6310,9 @@ var no_conditional_in_test_default = ESLintUtils34.RuleCreator(
5864
6310
  report(node);
5865
6311
  },
5866
6312
  LogicalExpression(node) {
6313
+ if (!isShortCircuitedAssertion(node)) {
6314
+ return;
6315
+ }
5867
6316
  report(node);
5868
6317
  }
5869
6318
  };
@@ -5871,7 +6320,7 @@ var no_conditional_in_test_default = ESLintUtils34.RuleCreator(
5871
6320
  });
5872
6321
 
5873
6322
  // src/rules/prefer-constant-time-secret-compare.ts
5874
- import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils35 } from "@typescript-eslint/utils";
6323
+ import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils34 } from "@typescript-eslint/utils";
5875
6324
  var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["===", "!==", "==", "!="]);
5876
6325
  var SENTINEL_IDENTIFIERS = /* @__PURE__ */ new Set(["undefined", "NaN"]);
5877
6326
  var SENTINEL_WORDS = /(^|_)(SENTINEL|EMPTY|NONE|NULL|UNSET|MISSING|PLACEHOLDER|DUMMY|FAKE|EXAMPLE)(_|$)/;
@@ -5884,36 +6333,36 @@ function isConstantReference(identifier) {
5884
6333
  }
5885
6334
  function isExcludedOperand(node) {
5886
6335
  switch (node.type) {
5887
- case AST_NODE_TYPES25.Literal:
6336
+ case AST_NODE_TYPES26.Literal:
5888
6337
  return true;
5889
- case AST_NODE_TYPES25.TemplateLiteral:
6338
+ case AST_NODE_TYPES26.TemplateLiteral:
5890
6339
  return node.expressions.length === 0;
5891
- case AST_NODE_TYPES25.Identifier:
6340
+ case AST_NODE_TYPES26.Identifier:
5892
6341
  return SENTINEL_IDENTIFIERS.has(node.name) || SENTINEL_PREFIX_RE.test(node.name) || isConstantReference(node.name);
5893
- case AST_NODE_TYPES25.MemberExpression:
5894
- return !node.computed && node.property.type === AST_NODE_TYPES25.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
6342
+ case AST_NODE_TYPES26.MemberExpression:
6343
+ return !node.computed && node.property.type === AST_NODE_TYPES26.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
5895
6344
  default:
5896
6345
  return false;
5897
6346
  }
5898
6347
  }
5899
6348
  function operandName(node) {
5900
- if (node.type === AST_NODE_TYPES25.Identifier) {
6349
+ if (node.type === AST_NODE_TYPES26.Identifier) {
5901
6350
  return node.name;
5902
6351
  }
5903
- if (node.type === AST_NODE_TYPES25.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES25.Identifier) {
6352
+ if (node.type === AST_NODE_TYPES26.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES26.Identifier) {
5904
6353
  return node.property.name;
5905
6354
  }
5906
6355
  return null;
5907
6356
  }
5908
6357
  function isSecretOperand(node) {
5909
- if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
6358
+ if (node.type === AST_NODE_TYPES26.TemplateLiteral) {
5910
6359
  return node.expressions.some((expression) => isSecretOperand(expression));
5911
6360
  }
5912
6361
  const name = operandName(node);
5913
6362
  return name !== null && isAuthSecretName(name);
5914
6363
  }
5915
6364
  function secretNameOf(node) {
5916
- if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
6365
+ if (node.type === AST_NODE_TYPES26.TemplateLiteral) {
5917
6366
  for (const expression of node.expressions) {
5918
6367
  const nested = secretNameOf(expression);
5919
6368
  if (nested !== null) {
@@ -5924,7 +6373,7 @@ function secretNameOf(node) {
5924
6373
  }
5925
6374
  return operandName(node);
5926
6375
  }
5927
- var prefer_constant_time_secret_compare_default = ESLintUtils35.RuleCreator(
6376
+ var prefer_constant_time_secret_compare_default = ESLintUtils34.RuleCreator(
5928
6377
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5929
6378
  )({
5930
6379
  name: "prefer-constant-time-secret-compare",
@@ -5967,11 +6416,11 @@ var prefer_constant_time_secret_compare_default = ESLintUtils35.RuleCreator(
5967
6416
  });
5968
6417
 
5969
6418
  // src/rules/store-insert-requires-on-conflict.ts
5970
- import { ESLintUtils as ESLintUtils36 } from "@typescript-eslint/utils";
6419
+ import { ESLintUtils as ESLintUtils35 } from "@typescript-eslint/utils";
5971
6420
  var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
5972
6421
  var CONFLICT_HANDLED = /\bON\s+CONFLICT\b|\bON\s+DUPLICATE\s+KEY\b|\bINSERT\s+OR\s+(?:IGNORE|REPLACE)\b/i;
5973
6422
  var INSERT_GATE = /insert/i;
5974
- var store_insert_requires_on_conflict_default = ESLintUtils36.RuleCreator(
6423
+ var store_insert_requires_on_conflict_default = ESLintUtils35.RuleCreator(
5975
6424
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5976
6425
  )({
5977
6426
  name: "store-insert-requires-on-conflict",
@@ -6000,17 +6449,17 @@ var store_insert_requires_on_conflict_default = ESLintUtils36.RuleCreator(
6000
6449
  });
6001
6450
 
6002
6451
  // src/rules/no-dynamic-sql.ts
6003
- import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils37 } from "@typescript-eslint/utils";
6452
+ import { AST_NODE_TYPES as AST_NODE_TYPES27, ESLintUtils as ESLintUtils36 } from "@typescript-eslint/utils";
6004
6453
  var DEFAULT_METHODS = ["prepare", "exec", "query"];
6005
6454
  var CONSTANT_CASE_RE = /^[A-Z][A-Z0-9_]*$/;
6006
6455
  function isStaticFragment(expression) {
6007
- if (expression.type === AST_NODE_TYPES26.Identifier) {
6456
+ if (expression.type === AST_NODE_TYPES27.Identifier) {
6008
6457
  return CONSTANT_CASE_RE.test(expression.name);
6009
6458
  }
6010
- if (expression.type === AST_NODE_TYPES26.MemberExpression && !expression.computed && expression.property.type === AST_NODE_TYPES26.Identifier) {
6459
+ if (expression.type === AST_NODE_TYPES27.MemberExpression && !expression.computed && expression.property.type === AST_NODE_TYPES27.Identifier) {
6011
6460
  return CONSTANT_CASE_RE.test(expression.property.name);
6012
6461
  }
6013
- if (expression.type === AST_NODE_TYPES26.Literal) {
6462
+ if (expression.type === AST_NODE_TYPES27.Literal) {
6014
6463
  return typeof expression.value === "string";
6015
6464
  }
6016
6465
  return false;
@@ -6021,36 +6470,36 @@ function runtimeInterpolations(template) {
6021
6470
  );
6022
6471
  }
6023
6472
  function concatOperands(node) {
6024
- if (node.type === AST_NODE_TYPES26.BinaryExpression && node.operator === "+") {
6473
+ if (node.type === AST_NODE_TYPES27.BinaryExpression && node.operator === "+") {
6025
6474
  return [...concatOperands(node.left), ...concatOperands(node.right)];
6026
6475
  }
6027
6476
  return [node];
6028
6477
  }
6029
6478
  function runtimeConcatOperands(node) {
6030
- if (node.type !== AST_NODE_TYPES26.BinaryExpression || node.operator !== "+") {
6479
+ if (node.type !== AST_NODE_TYPES27.BinaryExpression || node.operator !== "+") {
6031
6480
  return [];
6032
6481
  }
6033
6482
  const operands = concatOperands(node);
6034
6483
  const hasStringLiteral = operands.some(
6035
- (operand) => operand.type === AST_NODE_TYPES26.Literal && typeof operand.value === "string"
6484
+ (operand) => operand.type === AST_NODE_TYPES27.Literal && typeof operand.value === "string"
6036
6485
  );
6037
6486
  if (!hasStringLiteral) {
6038
6487
  return [];
6039
6488
  }
6040
6489
  return operands.filter(
6041
- (operand) => operand.type !== AST_NODE_TYPES26.Literal && !isStaticFragment(operand)
6490
+ (operand) => operand.type !== AST_NODE_TYPES27.Literal && !isStaticFragment(operand)
6042
6491
  );
6043
6492
  }
6044
6493
  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;
6045
6494
  var RUNTIME_MARKER = " ? ";
6046
6495
  function staticStatementText(node) {
6047
- if (node.type === AST_NODE_TYPES26.TemplateLiteral) {
6496
+ if (node.type === AST_NODE_TYPES27.TemplateLiteral) {
6048
6497
  return node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join(RUNTIME_MARKER);
6049
6498
  }
6050
- if (node.type === AST_NODE_TYPES26.Literal) {
6499
+ if (node.type === AST_NODE_TYPES27.Literal) {
6051
6500
  return typeof node.value === "string" ? node.value : RUNTIME_MARKER;
6052
6501
  }
6053
- if (node.type === AST_NODE_TYPES26.BinaryExpression && node.operator === "+") {
6502
+ if (node.type === AST_NODE_TYPES27.BinaryExpression && node.operator === "+") {
6054
6503
  return staticStatementText(node.left) + staticStatementText(node.right);
6055
6504
  }
6056
6505
  return RUNTIME_MARKER;
@@ -6060,13 +6509,13 @@ function looksLikeSql(node) {
6060
6509
  }
6061
6510
  function statementMethodName(node, methods) {
6062
6511
  const callee = node.callee;
6063
- if (callee.type !== AST_NODE_TYPES26.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES26.Identifier) {
6512
+ if (callee.type !== AST_NODE_TYPES27.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES27.Identifier) {
6064
6513
  return null;
6065
6514
  }
6066
6515
  const name = callee.property.name;
6067
6516
  return methods.has(name) ? name : null;
6068
6517
  }
6069
- var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6518
+ var no_dynamic_sql_default = ESLintUtils36.RuleCreator(
6070
6519
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6071
6520
  )({
6072
6521
  name: "no-dynamic-sql",
@@ -6105,7 +6554,7 @@ var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6105
6554
  if (statement === void 0 || !looksLikeSql(statement)) {
6106
6555
  return;
6107
6556
  }
6108
- const offenders = statement.type === AST_NODE_TYPES26.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6557
+ const offenders = statement.type === AST_NODE_TYPES27.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6109
6558
  for (const offender of offenders) {
6110
6559
  context.report({
6111
6560
  node: offender,
@@ -6119,7 +6568,7 @@ var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6119
6568
  });
6120
6569
 
6121
6570
  // src/rules/no-raw-fetch-outside-clients.ts
6122
- import { ESLintUtils as ESLintUtils38 } from "@typescript-eslint/utils";
6571
+ import { ESLintUtils as ESLintUtils37, AST_NODE_TYPES as AST_NODE_TYPES28 } from "@typescript-eslint/utils";
6123
6572
  var DEFAULT_ALLOW = [
6124
6573
  "[\\\\/]clients?[\\\\/]",
6125
6574
  "-client\\.[cm]?[jt]sx?$",
@@ -6129,17 +6578,15 @@ var DEFAULT_ALLOW = [
6129
6578
  "[\\\\/]api[\\\\/]",
6130
6579
  "[\\\\/]api\\.[cm]?[jt]sx?$",
6131
6580
  "[-.]api\\.[cm]?[jt]sx?$",
6132
- "\\.test\\.",
6133
- "\\.spec\\.",
6134
- // `*.test-d.ts` type tests, and react-router's `single-fetch-test.ts` spelling.
6135
- "\\.(test|spec)-d\\.[cm]?[jt]sx?$",
6136
- "-(test|spec)\\.[cm]?[jt]sx?$",
6137
- "[\\\\/]__tests__[\\\\/]",
6138
- "[\\\\/]__mocks__[\\\\/]",
6139
- "[\\\\/]tests?[\\\\/]",
6140
- // jscodeshift input/output fixtures — text a codemod transforms, not code.
6141
- "[\\\\/]__testfixtures__[\\\\/]"
6581
+ // Vendor wrapper conventions: a module that exists to own one third-party
6582
+ // origin's HTTP. See the SECOND SWEEP note in the file header.
6583
+ "[\\\\/]services?[\\\\/]",
6584
+ "[\\\\/](connectors|providers|integrations|adapters|fetchers)[\\\\/]",
6585
+ "[\\\\/]notifications[\\\\/]",
6586
+ "[Ss]ervice\\.[cm]?[jt]sx?$",
6587
+ "-(service|connector|adapter|sdk|fetcher)\\.[cm]?[jt]sx?$"
6142
6588
  ];
6589
+ var NON_PRODUCTION_TREE_RE = /[\\/](playwright|cypress|__testfixtures__)[\\/]/;
6143
6590
  var GLOBAL_RECEIVERS = /* @__PURE__ */ new Set([
6144
6591
  "globalThis",
6145
6592
  "window",
@@ -6165,6 +6612,10 @@ function identifierLikeName(node) {
6165
6612
  }
6166
6613
  return null;
6167
6614
  }
6615
+ function isConstructedArgumentHandoff(node) {
6616
+ const [first] = node.arguments;
6617
+ return node.arguments.length === 1 && first !== void 0 && first.type === AST_NODE_TYPES28.NewExpression;
6618
+ }
6168
6619
  function isPresignedUrlTransfer(node) {
6169
6620
  const first = node.arguments[0];
6170
6621
  if (first === void 0) {
@@ -6183,7 +6634,7 @@ function compile(patterns) {
6183
6634
  }
6184
6635
  return compiled;
6185
6636
  }
6186
- var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
6637
+ var no_raw_fetch_outside_clients_default = ESLintUtils37.RuleCreator(
6187
6638
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6188
6639
  )({
6189
6640
  name: "no-raw-fetch-outside-clients",
@@ -6211,15 +6662,18 @@ var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
6211
6662
  },
6212
6663
  defaultOptions: [{}],
6213
6664
  create(context, [options]) {
6665
+ const filename = context.filename;
6666
+ if (isTestFile(filename) || NON_PRODUCTION_TREE_RE.test(filename)) {
6667
+ return {};
6668
+ }
6214
6669
  const patterns = options?.allow ?? DEFAULT_ALLOW;
6215
6670
  const allowed = compile(patterns);
6216
- const filename = context.filename;
6217
6671
  if (allowed.some((re) => re.test(filename))) {
6218
6672
  return {};
6219
6673
  }
6220
6674
  return {
6221
6675
  CallExpression(node) {
6222
- if (isPresignedUrlTransfer(node)) {
6676
+ if (isPresignedUrlTransfer(node) || isConstructedArgumentHandoff(node)) {
6223
6677
  return;
6224
6678
  }
6225
6679
  if (isGlobalFetchCall(node)) {
@@ -6231,7 +6685,7 @@ var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
6231
6685
  });
6232
6686
 
6233
6687
  // src/rules/no-storage-in-stateless-modules.ts
6234
- import { AST_NODE_TYPES as AST_NODE_TYPES27, ESLintUtils as ESLintUtils39 } from "@typescript-eslint/utils";
6688
+ import { AST_NODE_TYPES as AST_NODE_TYPES29, ESLintUtils as ESLintUtils38 } from "@typescript-eslint/utils";
6235
6689
  var DEFAULT_METHODS2 = [
6236
6690
  "prepare",
6237
6691
  "put",
@@ -6250,7 +6704,7 @@ function compile2(patterns) {
6250
6704
  }
6251
6705
  function storageMethodName(node, methods) {
6252
6706
  const callee = node.callee;
6253
- if (callee.type !== AST_NODE_TYPES27.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES27.Identifier) {
6707
+ if (callee.type !== AST_NODE_TYPES29.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES29.Identifier) {
6254
6708
  return null;
6255
6709
  }
6256
6710
  const name = callee.property.name;
@@ -6262,7 +6716,7 @@ function storageMethodName(node, methods) {
6262
6716
  }
6263
6717
  return name;
6264
6718
  }
6265
- var no_storage_in_stateless_modules_default = ESLintUtils39.RuleCreator(
6719
+ var no_storage_in_stateless_modules_default = ESLintUtils38.RuleCreator(
6266
6720
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6267
6721
  )({
6268
6722
  name: "no-storage-in-stateless-modules",
@@ -6321,8 +6775,8 @@ var no_storage_in_stateless_modules_default = ESLintUtils39.RuleCreator(
6321
6775
 
6322
6776
  // src/rules/no-zod-native-enum.ts
6323
6777
  import {
6324
- ESLintUtils as ESLintUtils40,
6325
- AST_NODE_TYPES as AST_NODE_TYPES28
6778
+ ESLintUtils as ESLintUtils39,
6779
+ AST_NODE_TYPES as AST_NODE_TYPES30
6326
6780
  } from "@typescript-eslint/utils";
6327
6781
  import * as ts2 from "typescript";
6328
6782
  var IGNORE_PATTERNS2 = [
@@ -6341,7 +6795,7 @@ function isZodModule2(source) {
6341
6795
  return /(^|[/@-])zod([/-]|$)/.test(source);
6342
6796
  }
6343
6797
  function unwrap3(node) {
6344
- if (node.type === AST_NODE_TYPES28.TSAsExpression || node.type === AST_NODE_TYPES28.TSSatisfiesExpression) {
6798
+ if (node.type === AST_NODE_TYPES30.TSAsExpression || node.type === AST_NODE_TYPES30.TSSatisfiesExpression) {
6345
6799
  return unwrap3(node.expression);
6346
6800
  }
6347
6801
  return node;
@@ -6349,14 +6803,14 @@ function unwrap3(node) {
6349
6803
  function stringValueTexts(node, sourceCode) {
6350
6804
  const texts = [];
6351
6805
  for (const prop of node.properties) {
6352
- if (prop.type !== AST_NODE_TYPES28.Property) {
6806
+ if (prop.type !== AST_NODE_TYPES30.Property) {
6353
6807
  return null;
6354
6808
  }
6355
6809
  if (prop.computed || prop.shorthand || prop.method || prop.kind !== "init") {
6356
6810
  return null;
6357
6811
  }
6358
6812
  const value = prop.value;
6359
- if (value.type !== AST_NODE_TYPES28.Literal || typeof value.value !== "string") {
6813
+ if (value.type !== AST_NODE_TYPES30.Literal || typeof value.value !== "string") {
6360
6814
  return null;
6361
6815
  }
6362
6816
  const text = sourceCode.getText(value);
@@ -6372,7 +6826,7 @@ function resolvesToLocalEnum(node, scope) {
6372
6826
  const variable = current.variables.find((v) => v.name === node.name);
6373
6827
  if (variable !== void 0) {
6374
6828
  return variable.defs.some(
6375
- (def) => def.node.type === AST_NODE_TYPES28.TSEnumDeclaration
6829
+ (def) => def.node.type === AST_NODE_TYPES30.TSEnumDeclaration
6376
6830
  );
6377
6831
  }
6378
6832
  current = current.upper;
@@ -6392,7 +6846,7 @@ function resolvesToImportedEnum(node, services) {
6392
6846
  }
6393
6847
  return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
6394
6848
  }
6395
- var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6849
+ var no_zod_native_enum_default = ESLintUtils39.RuleCreator(
6396
6850
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6397
6851
  )({
6398
6852
  name: "no-zod-native-enum",
@@ -6419,32 +6873,32 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6419
6873
  }
6420
6874
  let services;
6421
6875
  try {
6422
- services = ESLintUtils40.getParserServices(context);
6876
+ services = ESLintUtils39.getParserServices(context);
6423
6877
  } catch {
6424
6878
  services = null;
6425
6879
  }
6426
6880
  const zodImportedNames = /* @__PURE__ */ new Map();
6427
6881
  function isZodMemberCall(node, api) {
6428
6882
  const callee = node.callee;
6429
- if (callee.type === AST_NODE_TYPES28.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES28.Identifier) {
6883
+ if (callee.type === AST_NODE_TYPES30.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES30.Identifier) {
6430
6884
  return callee.property.name === api;
6431
6885
  }
6432
- if (callee.type === AST_NODE_TYPES28.Identifier) {
6886
+ if (callee.type === AST_NODE_TYPES30.Identifier) {
6433
6887
  return zodImportedNames.get(callee.name) === api;
6434
6888
  }
6435
6889
  return false;
6436
6890
  }
6437
6891
  function buildFix(node) {
6438
6892
  const callee = node.callee;
6439
- if (callee.type !== AST_NODE_TYPES28.MemberExpression || callee.property.type !== AST_NODE_TYPES28.Identifier) {
6893
+ if (callee.type !== AST_NODE_TYPES30.MemberExpression || callee.property.type !== AST_NODE_TYPES30.Identifier) {
6440
6894
  return null;
6441
6895
  }
6442
6896
  const arg = node.arguments[0];
6443
- if (arg === void 0 || node.arguments.length !== 1 || arg.type === AST_NODE_TYPES28.SpreadElement) {
6897
+ if (arg === void 0 || node.arguments.length !== 1 || arg.type === AST_NODE_TYPES30.SpreadElement) {
6444
6898
  return null;
6445
6899
  }
6446
6900
  const inner = unwrap3(arg);
6447
- if (inner.type !== AST_NODE_TYPES28.ObjectExpression) {
6901
+ if (inner.type !== AST_NODE_TYPES30.ObjectExpression) {
6448
6902
  return null;
6449
6903
  }
6450
6904
  const values = stringValueTexts(inner, sourceCode);
@@ -6464,7 +6918,7 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6464
6918
  return;
6465
6919
  }
6466
6920
  for (const spec of node.specifiers) {
6467
- if (spec.type === AST_NODE_TYPES28.ImportSpecifier && spec.imported.type === AST_NODE_TYPES28.Identifier) {
6921
+ if (spec.type === AST_NODE_TYPES30.ImportSpecifier && spec.imported.type === AST_NODE_TYPES30.Identifier) {
6468
6922
  zodImportedNames.set(spec.local.name, spec.imported.name);
6469
6923
  }
6470
6924
  }
@@ -6483,7 +6937,7 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6483
6937
  return;
6484
6938
  }
6485
6939
  const arg = node.arguments[0];
6486
- if (arg === void 0 || arg.type !== AST_NODE_TYPES28.Identifier) {
6940
+ if (arg === void 0 || arg.type !== AST_NODE_TYPES30.Identifier) {
6487
6941
  return;
6488
6942
  }
6489
6943
  const isEnum = resolvesToLocalEnum(arg, sourceCode.getScope(arg)) || services !== null && resolvesToImportedEnum(arg, services);
@@ -6501,8 +6955,8 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6501
6955
 
6502
6956
  // src/rules/prefer-module-level-constant.ts
6503
6957
  import {
6504
- ESLintUtils as ESLintUtils41,
6505
- AST_NODE_TYPES as AST_NODE_TYPES29
6958
+ ESLintUtils as ESLintUtils40,
6959
+ AST_NODE_TYPES as AST_NODE_TYPES31
6506
6960
  } from "@typescript-eslint/utils";
6507
6961
  var DEFAULT_MIN_ELEMENTS = 3;
6508
6962
  var MAX_LITERAL_DEPTH = 4;
@@ -6512,13 +6966,6 @@ var IGNORE_PATTERNS3 = [
6512
6966
  /\.generated\.tsx?$/,
6513
6967
  /\.d\.ts$/
6514
6968
  ];
6515
- var TEST_FILE_PATTERNS = [
6516
- /\.(?:test|spec)\.[cm]?[jt]sx?$/,
6517
- /[\\/]__tests__[\\/]/,
6518
- /[\\/]__mocks__[\\/]/,
6519
- /[\\/]tests?[\\/]/,
6520
- /\.stories\.[cm]?[jt]sx?$/
6521
- ];
6522
6969
  var MUTATING_METHODS = /* @__PURE__ */ new Set([
6523
6970
  // Array
6524
6971
  "push",
@@ -6538,10 +6985,10 @@ var MUTATING_METHODS = /* @__PURE__ */ new Set([
6538
6985
  // Object-ish escape hatches
6539
6986
  "assign"
6540
6987
  ]);
6541
- var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6542
- AST_NODE_TYPES29.FunctionDeclaration,
6543
- AST_NODE_TYPES29.FunctionExpression,
6544
- AST_NODE_TYPES29.ArrowFunctionExpression
6988
+ var FUNCTION_TYPES5 = /* @__PURE__ */ new Set([
6989
+ AST_NODE_TYPES31.FunctionDeclaration,
6990
+ AST_NODE_TYPES31.FunctionExpression,
6991
+ AST_NODE_TYPES31.ArrowFunctionExpression
6545
6992
  ]);
6546
6993
  var COLLECTION_CONSTRUCTORS = /* @__PURE__ */ new Set(["Set", "Map"]);
6547
6994
  function isIgnoredFile3(filename, sourceText) {
@@ -6550,17 +6997,18 @@ function isIgnoredFile3(filename, sourceText) {
6550
6997
  }
6551
6998
  return /@generated\b/.test(sourceText.slice(0, 1024));
6552
6999
  }
6553
- function isTestFile2(filename) {
6554
- return TEST_FILE_PATTERNS.some((re) => re.test(filename));
7000
+ function isLocalFixtureFile(filename) {
7001
+ return isTestFile(filename) || isStoryFile(filename);
6555
7002
  }
6556
7003
  function unwrap4(node) {
6557
- if (node.type === AST_NODE_TYPES29.TSAsExpression || node.type === AST_NODE_TYPES29.TSSatisfiesExpression || node.type === AST_NODE_TYPES29.TSNonNullExpression) {
7004
+ if (node.type === AST_NODE_TYPES31.TSAsExpression || node.type === AST_NODE_TYPES31.TSSatisfiesExpression || node.type === AST_NODE_TYPES31.TSNonNullExpression) {
6558
7005
  return unwrap4(node.expression);
6559
7006
  }
6560
7007
  return node;
6561
7008
  }
7009
+ var HAS_STATEFUL_FLAG_RE = /[gy]/;
6562
7010
  function isRegexLiteral(node) {
6563
- return node.type === AST_NODE_TYPES29.Literal && "regex" in node && node.regex !== void 0;
7011
+ return node.type === AST_NODE_TYPES31.Literal && "regex" in node && node.regex !== void 0;
6564
7012
  }
6565
7013
  function isLiteralOnly(node, depth) {
6566
7014
  if (depth > MAX_LITERAL_DEPTH) {
@@ -6568,29 +7016,29 @@ function isLiteralOnly(node, depth) {
6568
7016
  }
6569
7017
  const inner = unwrap4(node);
6570
7018
  switch (inner.type) {
6571
- case AST_NODE_TYPES29.Literal: {
6572
- return true;
7019
+ case AST_NODE_TYPES31.Literal: {
7020
+ return !(isRegexLiteral(inner) && HAS_STATEFUL_FLAG_RE.test(inner.regex.flags));
6573
7021
  }
6574
- case AST_NODE_TYPES29.TemplateLiteral: {
7022
+ case AST_NODE_TYPES31.TemplateLiteral: {
6575
7023
  return inner.expressions.length === 0;
6576
7024
  }
6577
- case AST_NODE_TYPES29.UnaryExpression: {
6578
- return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === AST_NODE_TYPES29.Literal && typeof inner.argument.value === "number";
7025
+ case AST_NODE_TYPES31.UnaryExpression: {
7026
+ return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === AST_NODE_TYPES31.Literal && typeof inner.argument.value === "number";
6579
7027
  }
6580
- case AST_NODE_TYPES29.ArrayExpression: {
7028
+ case AST_NODE_TYPES31.ArrayExpression: {
6581
7029
  return inner.elements.every(
6582
- (el) => el !== null && el.type !== AST_NODE_TYPES29.SpreadElement && isLiteralOnly(el, depth + 1)
7030
+ (el) => el !== null && el.type !== AST_NODE_TYPES31.SpreadElement && isLiteralOnly(el, depth + 1)
6583
7031
  );
6584
7032
  }
6585
- case AST_NODE_TYPES29.ObjectExpression: {
7033
+ case AST_NODE_TYPES31.ObjectExpression: {
6586
7034
  return inner.properties.every((prop) => {
6587
- if (prop.type !== AST_NODE_TYPES29.Property) {
7035
+ if (prop.type !== AST_NODE_TYPES31.Property) {
6588
7036
  return false;
6589
7037
  }
6590
7038
  if (prop.shorthand || prop.method || prop.kind !== "init") {
6591
7039
  return false;
6592
7040
  }
6593
- if (prop.computed && prop.key.type !== AST_NODE_TYPES29.Literal) {
7041
+ if (prop.computed && prop.key.type !== AST_NODE_TYPES31.Literal) {
6594
7042
  return false;
6595
7043
  }
6596
7044
  return isLiteralOnly(prop.value, depth + 1);
@@ -6603,7 +7051,7 @@ function isLiteralOnly(node, depth) {
6603
7051
  }
6604
7052
  function unwrapObjectFreeze(node) {
6605
7053
  const inner = unwrap4(node);
6606
- if (inner.type === AST_NODE_TYPES29.CallExpression && inner.callee.type === AST_NODE_TYPES29.MemberExpression && !inner.callee.computed && inner.callee.object.type === AST_NODE_TYPES29.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === AST_NODE_TYPES29.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== AST_NODE_TYPES29.SpreadElement) {
7054
+ if (inner.type === AST_NODE_TYPES31.CallExpression && inner.callee.type === AST_NODE_TYPES31.MemberExpression && !inner.callee.computed && inner.callee.object.type === AST_NODE_TYPES31.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === AST_NODE_TYPES31.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== AST_NODE_TYPES31.SpreadElement) {
6607
7055
  return unwrap4(inner.arguments[0]);
6608
7056
  }
6609
7057
  return inner;
@@ -6614,24 +7062,24 @@ function classify(init, checkRegex) {
6614
7062
  if (!checkRegex) {
6615
7063
  return null;
6616
7064
  }
6617
- if (/[gy]/.test(node.regex.flags)) {
7065
+ if (HAS_STATEFUL_FLAG_RE.test(node.regex.flags)) {
6618
7066
  return null;
6619
7067
  }
6620
7068
  return { kind: "regex", size: 1 };
6621
7069
  }
6622
- if (node.type === AST_NODE_TYPES29.ArrayExpression) {
7070
+ if (node.type === AST_NODE_TYPES31.ArrayExpression) {
6623
7071
  return isLiteralOnly(node, 0) ? { kind: "array", size: node.elements.length } : null;
6624
7072
  }
6625
- if (node.type === AST_NODE_TYPES29.ObjectExpression) {
7073
+ if (node.type === AST_NODE_TYPES31.ObjectExpression) {
6626
7074
  return isLiteralOnly(node, 0) ? { kind: "object", size: node.properties.length } : null;
6627
7075
  }
6628
- if (node.type === AST_NODE_TYPES29.NewExpression && node.callee.type === AST_NODE_TYPES29.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
7076
+ if (node.type === AST_NODE_TYPES31.NewExpression && node.callee.type === AST_NODE_TYPES31.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6629
7077
  const arg = node.arguments[0];
6630
- if (node.arguments.length !== 1 || arg === void 0 || arg.type === AST_NODE_TYPES29.SpreadElement) {
7078
+ if (node.arguments.length !== 1 || arg === void 0 || arg.type === AST_NODE_TYPES31.SpreadElement) {
6631
7079
  return null;
6632
7080
  }
6633
7081
  const entries = unwrap4(arg);
6634
- if (entries.type !== AST_NODE_TYPES29.ArrayExpression) {
7082
+ if (entries.type !== AST_NODE_TYPES31.ArrayExpression) {
6635
7083
  return null;
6636
7084
  }
6637
7085
  return isLiteralOnly(entries, 0) ? { kind: node.callee.name === "Set" ? "Set" : "Map", size: entries.elements.length } : null;
@@ -6641,7 +7089,7 @@ function classify(init, checkRegex) {
6641
7089
  function enclosingFunction2(node) {
6642
7090
  let current = node.parent;
6643
7091
  while (current !== void 0 && current !== null) {
6644
- if (FUNCTION_TYPES4.has(current.type)) {
7092
+ if (FUNCTION_TYPES5.has(current.type)) {
6645
7093
  return current;
6646
7094
  }
6647
7095
  current = current.parent;
@@ -6660,10 +7108,10 @@ var NON_RETAINING_BUILTINS = /* @__PURE__ */ new Map(
6660
7108
  );
6661
7109
  function isNonRetainingBuiltinCall(node, argument) {
6662
7110
  const callee = node.callee;
6663
- if (callee.type === AST_NODE_TYPES29.Identifier && callee.name === "structuredClone") {
7111
+ if (callee.type === AST_NODE_TYPES31.Identifier && callee.name === "structuredClone") {
6664
7112
  return true;
6665
7113
  }
6666
- if (callee.type !== AST_NODE_TYPES29.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES29.Identifier || callee.property.type !== AST_NODE_TYPES29.Identifier) {
7114
+ if (callee.type !== AST_NODE_TYPES31.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES31.Identifier || callee.property.type !== AST_NODE_TYPES31.Identifier) {
6667
7115
  return false;
6668
7116
  }
6669
7117
  const members = NON_RETAINING_BUILTINS.get(callee.object.name);
@@ -6677,43 +7125,43 @@ function isNonRetainingBuiltinCall(node, argument) {
6677
7125
  }
6678
7126
  function isSafeRead(identifier) {
6679
7127
  const parent = identifier.parent;
6680
- if (parent.type === AST_NODE_TYPES29.MemberExpression) {
7128
+ if (parent.type === AST_NODE_TYPES31.MemberExpression) {
6681
7129
  if (parent.object !== identifier) {
6682
7130
  return true;
6683
7131
  }
6684
7132
  const grandparent = parent.parent;
6685
- if (grandparent.type === AST_NODE_TYPES29.AssignmentExpression && grandparent.left === parent) {
7133
+ if (grandparent.type === AST_NODE_TYPES31.AssignmentExpression && grandparent.left === parent) {
6686
7134
  return false;
6687
7135
  }
6688
- if (grandparent.type === AST_NODE_TYPES29.UpdateExpression) {
7136
+ if (grandparent.type === AST_NODE_TYPES31.UpdateExpression) {
6689
7137
  return false;
6690
7138
  }
6691
- if (grandparent.type === AST_NODE_TYPES29.UnaryExpression && grandparent.operator === "delete") {
7139
+ if (grandparent.type === AST_NODE_TYPES31.UnaryExpression && grandparent.operator === "delete") {
6692
7140
  return false;
6693
7141
  }
6694
- if (!parent.computed && parent.property.type === AST_NODE_TYPES29.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === AST_NODE_TYPES29.CallExpression && grandparent.callee === parent) {
7142
+ if (!parent.computed && parent.property.type === AST_NODE_TYPES31.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === AST_NODE_TYPES31.CallExpression && grandparent.callee === parent) {
6695
7143
  return false;
6696
7144
  }
6697
7145
  return true;
6698
7146
  }
6699
- if (parent.type === AST_NODE_TYPES29.ForOfStatement && parent.right === identifier) {
7147
+ if (parent.type === AST_NODE_TYPES31.ForOfStatement && parent.right === identifier) {
6700
7148
  return true;
6701
7149
  }
6702
- if (parent.type === AST_NODE_TYPES29.SpreadElement) {
7150
+ if (parent.type === AST_NODE_TYPES31.SpreadElement) {
6703
7151
  return true;
6704
7152
  }
6705
- if (parent.type === AST_NODE_TYPES29.BinaryExpression) {
7153
+ if (parent.type === AST_NODE_TYPES31.BinaryExpression) {
6706
7154
  return true;
6707
7155
  }
6708
- if (parent.type === AST_NODE_TYPES29.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
7156
+ if (parent.type === AST_NODE_TYPES31.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6709
7157
  return true;
6710
7158
  }
6711
- if (parent.type === AST_NODE_TYPES29.UnaryExpression && parent.operator !== "delete") {
7159
+ if (parent.type === AST_NODE_TYPES31.UnaryExpression && parent.operator !== "delete") {
6712
7160
  return true;
6713
7161
  }
6714
7162
  return false;
6715
7163
  }
6716
- var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
7164
+ var prefer_module_level_constant_default = ESLintUtils40.RuleCreator(
6717
7165
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6718
7166
  )({
6719
7167
  name: "prefer-module-level-constant",
@@ -6749,7 +7197,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6749
7197
  if (isIgnoredFile3(filename, sourceCode.getText())) {
6750
7198
  return {};
6751
7199
  }
6752
- if (ignoreTestFiles && isTestFile2(filename)) {
7200
+ if (ignoreTestFiles && isLocalFixtureFile(filename)) {
6753
7201
  return {};
6754
7202
  }
6755
7203
  function allReferencesAreSafeReads(declarator) {
@@ -6765,7 +7213,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6765
7213
  if (reference.isWrite()) {
6766
7214
  return false;
6767
7215
  }
6768
- if (reference.identifier.type !== AST_NODE_TYPES29.Identifier) {
7216
+ if (reference.identifier.type !== AST_NODE_TYPES31.Identifier) {
6769
7217
  return false;
6770
7218
  }
6771
7219
  if (!isSafeRead(reference.identifier)) {
@@ -6777,10 +7225,10 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6777
7225
  return {
6778
7226
  VariableDeclarator(node) {
6779
7227
  const declaration = node.parent;
6780
- if (declaration.type !== AST_NODE_TYPES29.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
7228
+ if (declaration.type !== AST_NODE_TYPES31.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6781
7229
  return;
6782
7230
  }
6783
- if (node.id.type !== AST_NODE_TYPES29.Identifier || node.init === null) {
7231
+ if (node.id.type !== AST_NODE_TYPES31.Identifier || node.init === null) {
6784
7232
  return;
6785
7233
  }
6786
7234
  if (enclosingFunction2(node) === null) {
@@ -6807,7 +7255,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6807
7255
  });
6808
7256
 
6809
7257
  // src/rules/jsdoc-restates-signature.ts
6810
- import { AST_NODE_TYPES as AST_NODE_TYPES30, ESLintUtils as ESLintUtils42 } from "@typescript-eslint/utils";
7258
+ import { AST_NODE_TYPES as AST_NODE_TYPES32, ESLintUtils as ESLintUtils41 } from "@typescript-eslint/utils";
6811
7259
  var VALUE_TAGS = /* @__PURE__ */ new Set([
6812
7260
  "alpha",
6813
7261
  "author",
@@ -6890,30 +7338,30 @@ function declarationNames(node) {
6890
7338
  switch (node.type) {
6891
7339
  // `export function f()` — the JSDoc sits above the `export`, so the token
6892
7340
  // after it resolves to the wrapper, not to the thing being documented.
6893
- case AST_NODE_TYPES30.ExportNamedDeclaration:
6894
- case AST_NODE_TYPES30.ExportDefaultDeclaration:
7341
+ case AST_NODE_TYPES32.ExportNamedDeclaration:
7342
+ case AST_NODE_TYPES32.ExportDefaultDeclaration:
6895
7343
  return node.declaration == null ? null : declarationNames(node.declaration);
6896
- case AST_NODE_TYPES30.FunctionDeclaration:
6897
- case AST_NODE_TYPES30.TSDeclareFunction:
7344
+ case AST_NODE_TYPES32.FunctionDeclaration:
7345
+ case AST_NODE_TYPES32.TSDeclareFunction:
6898
7346
  return node.id === null ? null : { name: node.id.name, params: paramNames(node.params) };
6899
- case AST_NODE_TYPES30.ClassDeclaration:
6900
- case AST_NODE_TYPES30.TSInterfaceDeclaration:
6901
- case AST_NODE_TYPES30.TSTypeAliasDeclaration:
6902
- case AST_NODE_TYPES30.TSEnumDeclaration:
7347
+ case AST_NODE_TYPES32.ClassDeclaration:
7348
+ case AST_NODE_TYPES32.TSInterfaceDeclaration:
7349
+ case AST_NODE_TYPES32.TSTypeAliasDeclaration:
7350
+ case AST_NODE_TYPES32.TSEnumDeclaration:
6903
7351
  return node.id === null ? null : { name: node.id.name, params: [] };
6904
- case AST_NODE_TYPES30.VariableDeclaration: {
7352
+ case AST_NODE_TYPES32.VariableDeclaration: {
6905
7353
  const declarator = node.declarations[0];
6906
- if (declarator === void 0 || declarator.id.type !== AST_NODE_TYPES30.Identifier) return null;
7354
+ if (declarator === void 0 || declarator.id.type !== AST_NODE_TYPES32.Identifier) return null;
6907
7355
  const init = declarator.init;
6908
- const params = init != null && (init.type === AST_NODE_TYPES30.ArrowFunctionExpression || init.type === AST_NODE_TYPES30.FunctionExpression) ? paramNames(init.params) : [];
7356
+ const params = init != null && (init.type === AST_NODE_TYPES32.ArrowFunctionExpression || init.type === AST_NODE_TYPES32.FunctionExpression) ? paramNames(init.params) : [];
6909
7357
  return { name: declarator.id.name, params };
6910
7358
  }
6911
- case AST_NODE_TYPES30.MethodDefinition:
6912
- case AST_NODE_TYPES30.PropertyDefinition:
6913
- case AST_NODE_TYPES30.TSMethodSignature:
6914
- case AST_NODE_TYPES30.TSPropertySignature: {
6915
- if (node.key.type !== AST_NODE_TYPES30.Identifier) return null;
6916
- const params = node.type === AST_NODE_TYPES30.MethodDefinition ? paramNames(node.value.params) : node.type === AST_NODE_TYPES30.TSMethodSignature ? paramNames(node.params) : [];
7359
+ case AST_NODE_TYPES32.MethodDefinition:
7360
+ case AST_NODE_TYPES32.PropertyDefinition:
7361
+ case AST_NODE_TYPES32.TSMethodSignature:
7362
+ case AST_NODE_TYPES32.TSPropertySignature: {
7363
+ if (node.key.type !== AST_NODE_TYPES32.Identifier) return null;
7364
+ const params = node.type === AST_NODE_TYPES32.MethodDefinition ? paramNames(node.value.params) : node.type === AST_NODE_TYPES32.TSMethodSignature ? paramNames(node.params) : [];
6917
7365
  return { name: node.key.name, params };
6918
7366
  }
6919
7367
  default:
@@ -6923,9 +7371,9 @@ function declarationNames(node) {
6923
7371
  function paramNames(params) {
6924
7372
  const names = [];
6925
7373
  for (const param of params) {
6926
- const target = param.type === AST_NODE_TYPES30.AssignmentPattern ? param.left : param;
6927
- if (target.type === AST_NODE_TYPES30.Identifier) names.push(target.name);
6928
- else if (target.type === AST_NODE_TYPES30.TSParameterProperty) continue;
7374
+ const target = param.type === AST_NODE_TYPES32.AssignmentPattern ? param.left : param;
7375
+ if (target.type === AST_NODE_TYPES32.Identifier) names.push(target.name);
7376
+ else if (target.type === AST_NODE_TYPES32.TSParameterProperty) continue;
6929
7377
  }
6930
7378
  return names;
6931
7379
  }
@@ -6934,7 +7382,7 @@ function tokensOf(names) {
6934
7382
  for (const name of names) for (const part of splitIdentifier(name)) tokens.add(part);
6935
7383
  return tokens;
6936
7384
  }
6937
- var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
7385
+ var jsdoc_restates_signature_default = ESLintUtils41.RuleCreator(
6938
7386
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6939
7387
  )({
6940
7388
  name: "jsdoc-restates-signature",
@@ -6970,7 +7418,7 @@ var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
6970
7418
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) continue;
6971
7419
  let node = sourceCode.getNodeByRangeIndex(token.range[0]);
6972
7420
  let declaration = null;
6973
- while (node != null && node.type !== AST_NODE_TYPES30.Program) {
7421
+ while (node != null && node.type !== AST_NODE_TYPES32.Program) {
6974
7422
  declaration = declarationNames(node);
6975
7423
  if (declaration !== null) break;
6976
7424
  node = node.parent ?? null;
@@ -7025,7 +7473,7 @@ var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
7025
7473
  });
7026
7474
 
7027
7475
  // src/rules/no-restated-comment.ts
7028
- import { AST_NODE_TYPES as AST_NODE_TYPES31, ESLintUtils as ESLintUtils43 } from "@typescript-eslint/utils";
7476
+ import { AST_NODE_TYPES as AST_NODE_TYPES33, ESLintUtils as ESLintUtils42 } from "@typescript-eslint/utils";
7029
7477
  var MAX_WORDS = 8;
7030
7478
  var MIN_CONTENT_TOKENS = 2;
7031
7479
  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 +7497,7 @@ function headsSiblingRun(node) {
7049
7497
  const next = index >= 0 ? body[index + 1] : void 0;
7050
7498
  return next !== void 0 && next.type === node.type;
7051
7499
  }
7052
- var no_restated_comment_default = ESLintUtils43.RuleCreator(
7500
+ var no_restated_comment_default = ESLintUtils42.RuleCreator(
7053
7501
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7054
7502
  )({
7055
7503
  name: "no-restated-comment",
@@ -7077,7 +7525,7 @@ var no_restated_comment_default = ESLintUtils43.RuleCreator(
7077
7525
  function labelsASiblingRun(comment) {
7078
7526
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
7079
7527
  if (token === null) return false;
7080
- for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES31.Program; node = node.parent) {
7528
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES33.Program; node = node.parent) {
7081
7529
  if (headsSiblingRun(node)) return true;
7082
7530
  }
7083
7531
  return false;
@@ -7117,7 +7565,7 @@ var no_restated_comment_default = ESLintUtils43.RuleCreator(
7117
7565
  });
7118
7566
 
7119
7567
  // src/rules/trailing-value-narration.ts
7120
- import { ESLintUtils as ESLintUtils44 } from "@typescript-eslint/utils";
7568
+ import { ESLintUtils as ESLintUtils43 } from "@typescript-eslint/utils";
7121
7569
  var NUMBER_RE = /(?<![\w.])(\d+(?:\.\d+)?)(?![\w.])/g;
7122
7570
  var WORD_RE3 = /[A-Za-z]+(?:'[a-z]+)?|\d+(?:\.\d+)?/g;
7123
7571
  var UNIT_WORDS = /* @__PURE__ */ new Set([
@@ -7201,7 +7649,7 @@ function narratesValue(body, code) {
7201
7649
  (word) => STOPWORDS3.has(word) || UNIT_WORDS.has(word) || commentNumbers.has(word) || identifiers.has(word) || stems.has(stem(word))
7202
7650
  );
7203
7651
  }
7204
- var trailing_value_narration_default = ESLintUtils44.RuleCreator(
7652
+ var trailing_value_narration_default = ESLintUtils43.RuleCreator(
7205
7653
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7206
7654
  )({
7207
7655
  name: "trailing-value-narration",
@@ -7242,7 +7690,7 @@ var trailing_value_narration_default = ESLintUtils44.RuleCreator(
7242
7690
  });
7243
7691
 
7244
7692
  // src/rules/no-tautological-expect.ts
7245
- import { AST_NODE_TYPES as AST_NODE_TYPES32, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
7693
+ import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils44 } from "@typescript-eslint/utils";
7246
7694
  var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
7247
7695
  var ZERO_ARG_MATCHERS = /* @__PURE__ */ new Set([
7248
7696
  "toBeDefined",
@@ -7256,17 +7704,17 @@ var OPERAND_PREVIEW_CHARS = 40;
7256
7704
  var NUMERIC_SIGNS = /* @__PURE__ */ new Set(["-", "+"]);
7257
7705
  function isLiteral(node) {
7258
7706
  switch (node.type) {
7259
- case AST_NODE_TYPES32.Literal:
7707
+ case AST_NODE_TYPES34.Literal:
7260
7708
  return true;
7261
- case AST_NODE_TYPES32.TemplateLiteral:
7709
+ case AST_NODE_TYPES34.TemplateLiteral:
7262
7710
  return node.expressions.length === 0;
7263
- case AST_NODE_TYPES32.UnaryExpression:
7711
+ case AST_NODE_TYPES34.UnaryExpression:
7264
7712
  return NUMERIC_SIGNS.has(node.operator) && isLiteral(node.argument);
7265
- case AST_NODE_TYPES32.ArrayExpression:
7713
+ case AST_NODE_TYPES34.ArrayExpression:
7266
7714
  return node.elements.every((element) => element !== null && isLiteral(element));
7267
- case AST_NODE_TYPES32.ObjectExpression:
7715
+ case AST_NODE_TYPES34.ObjectExpression:
7268
7716
  return node.properties.every(
7269
- (property) => property.type === AST_NODE_TYPES32.Property && !property.computed && isLiteral(property.value)
7717
+ (property) => property.type === AST_NODE_TYPES34.Property && !property.computed && isLiteral(property.value)
7270
7718
  );
7271
7719
  default:
7272
7720
  return false;
@@ -7274,12 +7722,12 @@ function isLiteral(node) {
7274
7722
  }
7275
7723
  function expectOperand(callee) {
7276
7724
  const receiver = callee.object;
7277
- if (receiver.type !== AST_NODE_TYPES32.CallExpression || receiver.callee.type !== AST_NODE_TYPES32.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7725
+ if (receiver.type !== AST_NODE_TYPES34.CallExpression || receiver.callee.type !== AST_NODE_TYPES34.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7278
7726
  return null;
7279
7727
  }
7280
7728
  return receiver.arguments[0] ?? null;
7281
7729
  }
7282
- var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7730
+ var no_tautological_expect_default = ESLintUtils44.RuleCreator(
7283
7731
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7284
7732
  )({
7285
7733
  name: "no-tautological-expect",
@@ -7306,10 +7754,10 @@ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7306
7754
  return {
7307
7755
  CallExpression(node) {
7308
7756
  const callee = node.callee;
7309
- if (callee.type !== AST_NODE_TYPES32.MemberExpression || callee.computed) {
7757
+ if (callee.type !== AST_NODE_TYPES34.MemberExpression || callee.computed) {
7310
7758
  return;
7311
7759
  }
7312
- if (callee.property.type !== AST_NODE_TYPES32.Identifier) {
7760
+ if (callee.property.type !== AST_NODE_TYPES34.Identifier) {
7313
7761
  return;
7314
7762
  }
7315
7763
  const matcher = callee.property.name;
@@ -7343,26 +7791,26 @@ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7343
7791
  });
7344
7792
 
7345
7793
  // src/rules/require-interface-for-injected-service.ts
7346
- import { AST_NODE_TYPES as AST_NODE_TYPES33, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
7794
+ import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
7347
7795
  var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Props|Args|Env|Environment|Callbacks|Flags)$/;
7348
7796
  var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
7349
7797
  var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
7350
7798
  var TRANSPORT_WRAPPER_NAME_RE = /Client$/;
7351
7799
  var ROUTER_FACTORY_NAME = "Router";
7352
7800
  var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
7353
- var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES33.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES33.ExportDefaultDeclaration;
7354
- var qualifiedName = (name) => name.type === AST_NODE_TYPES33.Identifier ? name.name : name.type === AST_NODE_TYPES33.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7801
+ var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES35.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES35.ExportDefaultDeclaration;
7802
+ var qualifiedName = (name) => name.type === AST_NODE_TYPES35.Identifier ? name.name : name.type === AST_NODE_TYPES35.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7355
7803
  var typeReferenceName = (annotated) => {
7356
7804
  let target = annotated;
7357
- if (target.type === AST_NODE_TYPES33.TSParameterProperty) target = target.parameter;
7358
- if (target.type === AST_NODE_TYPES33.AssignmentPattern) target = target.left;
7359
- if (target.type !== AST_NODE_TYPES33.Identifier) return null;
7805
+ if (target.type === AST_NODE_TYPES35.TSParameterProperty) target = target.parameter;
7806
+ if (target.type === AST_NODE_TYPES35.AssignmentPattern) target = target.left;
7807
+ if (target.type !== AST_NODE_TYPES35.Identifier) return null;
7360
7808
  const annotation = target.typeAnnotation?.typeAnnotation;
7361
- if (annotation === void 0 || annotation.type !== AST_NODE_TYPES33.TSTypeReference) {
7809
+ if (annotation === void 0 || annotation.type !== AST_NODE_TYPES35.TSTypeReference) {
7362
7810
  return null;
7363
7811
  }
7364
7812
  const { typeName } = annotation;
7365
- const rightmost = typeName.type === AST_NODE_TYPES33.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES33.TSQualifiedName ? typeName.right.name : null;
7813
+ const rightmost = typeName.type === AST_NODE_TYPES35.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES35.TSQualifiedName ? typeName.right.name : null;
7366
7814
  if (rightmost === null) return null;
7367
7815
  return { name: target.name, typeName: rightmost, display: qualifiedName(typeName) };
7368
7816
  };
@@ -7372,17 +7820,17 @@ var readConstructor = (ctor) => {
7372
7820
  let constructedFields = 0;
7373
7821
  if (body !== null && body !== void 0) {
7374
7822
  for (const statement of body.body) {
7375
- if (statement.type !== AST_NODE_TYPES33.ExpressionStatement) continue;
7823
+ if (statement.type !== AST_NODE_TYPES35.ExpressionStatement) continue;
7376
7824
  const expression = statement.expression;
7377
- if (expression.type !== AST_NODE_TYPES33.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES33.MemberExpression || expression.left.object.type !== AST_NODE_TYPES33.ThisExpression) {
7825
+ if (expression.type !== AST_NODE_TYPES35.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES35.MemberExpression || expression.left.object.type !== AST_NODE_TYPES35.ThisExpression) {
7378
7826
  continue;
7379
7827
  }
7380
7828
  const source = expression.right;
7381
- if (source.type === AST_NODE_TYPES33.NewExpression) {
7829
+ if (source.type === AST_NODE_TYPES35.NewExpression) {
7382
7830
  constructedFields += 1;
7383
- } else if (source.type === AST_NODE_TYPES33.Identifier) {
7831
+ } else if (source.type === AST_NODE_TYPES35.Identifier) {
7384
7832
  storedFrom.add(source.name);
7385
- } else if (source.type === AST_NODE_TYPES33.MemberExpression && source.object.type === AST_NODE_TYPES33.Identifier) {
7833
+ } else if (source.type === AST_NODE_TYPES35.MemberExpression && source.object.type === AST_NODE_TYPES35.Identifier) {
7386
7834
  storedFrom.add(source.object.name);
7387
7835
  }
7388
7836
  }
@@ -7391,7 +7839,7 @@ var readConstructor = (ctor) => {
7391
7839
  for (const parameter of ctor.value.params) {
7392
7840
  const reference = typeReferenceName(parameter);
7393
7841
  if (reference === null) continue;
7394
- const stored = parameter.type === AST_NODE_TYPES33.TSParameterProperty || storedFrom.has(reference.name);
7842
+ const stored = parameter.type === AST_NODE_TYPES35.TSParameterProperty || storedFrom.has(reference.name);
7395
7843
  if (!stored) continue;
7396
7844
  if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
7397
7845
  if (CONFIGISH_NAME_RE.test(reference.name)) continue;
@@ -7421,19 +7869,19 @@ var subtreeHas = (root, found) => {
7421
7869
  return hit;
7422
7870
  };
7423
7871
  var isFrameworkWiring = (body) => subtreeHas(body, (node) => {
7424
- if (node.type === AST_NODE_TYPES33.CallExpression) {
7872
+ if (node.type === AST_NODE_TYPES35.CallExpression) {
7425
7873
  const { callee } = node;
7426
- if (callee.type === AST_NODE_TYPES33.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7427
- return callee.type === AST_NODE_TYPES33.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES33.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7874
+ if (callee.type === AST_NODE_TYPES35.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7875
+ return callee.type === AST_NODE_TYPES35.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES35.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7428
7876
  }
7429
- return node.type === AST_NODE_TYPES33.TSTypeReference && node.typeName.type === AST_NODE_TYPES33.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7877
+ return node.type === AST_NODE_TYPES35.TSTypeReference && node.typeName.type === AST_NODE_TYPES35.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7430
7878
  });
7431
7879
  var stem2 = (name) => name.replace(/^I(?=[A-Z])/, "").replace(/Impl$/, "");
7432
7880
  var fileInterfaceNames = (program) => {
7433
7881
  const names = [];
7434
7882
  for (const statement of program.body) {
7435
- const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration ? statement.declaration : statement;
7436
- if (declaration?.type === AST_NODE_TYPES33.TSInterfaceDeclaration) names.push(declaration.id.name);
7883
+ const declaration = statement.type === AST_NODE_TYPES35.ExportNamedDeclaration ? statement.declaration : statement;
7884
+ if (declaration?.type === AST_NODE_TYPES35.TSInterfaceDeclaration) names.push(declaration.id.name);
7437
7885
  }
7438
7886
  return names;
7439
7887
  };
@@ -7451,16 +7899,16 @@ var isTransportWrapper = (className, collaborators, program) => {
7451
7899
  var publicMethodNames = (body) => {
7452
7900
  const names = [];
7453
7901
  for (const member of body.body) {
7454
- if (member.type !== AST_NODE_TYPES33.MethodDefinition) continue;
7902
+ if (member.type !== AST_NODE_TYPES35.MethodDefinition) continue;
7455
7903
  if (member.kind !== "method" || member.static) continue;
7456
7904
  if (member.accessibility === "private" || member.accessibility === "protected") continue;
7457
- if (member.key.type === AST_NODE_TYPES33.PrivateIdentifier) continue;
7458
- if (member.key.type === AST_NODE_TYPES33.Identifier) names.push(member.key.name);
7905
+ if (member.key.type === AST_NODE_TYPES35.PrivateIdentifier) continue;
7906
+ if (member.key.type === AST_NODE_TYPES35.Identifier) names.push(member.key.name);
7459
7907
  else names.push("\u2026");
7460
7908
  }
7461
7909
  return names;
7462
7910
  };
7463
- var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7911
+ var require_interface_for_injected_service_default = ESLintUtils45.RuleCreator(
7464
7912
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7465
7913
  )({
7466
7914
  name: "require-interface-for-injected-service",
@@ -7488,7 +7936,7 @@ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7488
7936
  if (node.implements.length > 0) return;
7489
7937
  if (node.decorators.length > 0) return;
7490
7938
  const ctor = node.body.body.find(
7491
- (member) => member.type === AST_NODE_TYPES33.MethodDefinition && member.kind === "constructor"
7939
+ (member) => member.type === AST_NODE_TYPES35.MethodDefinition && member.kind === "constructor"
7492
7940
  );
7493
7941
  if (ctor === void 0) return;
7494
7942
  const { collaborators, constructedFields } = readConstructor(ctor);
@@ -7513,26 +7961,26 @@ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7513
7961
  });
7514
7962
 
7515
7963
  // src/rules/prefer-non-nullable-collection.ts
7516
- import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
7964
+ import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
7517
7965
  var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
7518
7966
  function propertyName(node) {
7519
7967
  const key = node.key;
7520
- if (key.type === AST_NODE_TYPES34.Identifier) return key.name;
7521
- if (key.type === AST_NODE_TYPES34.Literal) return String(key.value);
7968
+ if (key.type === AST_NODE_TYPES36.Identifier) return key.name;
7969
+ if (key.type === AST_NODE_TYPES36.Literal) return String(key.value);
7522
7970
  return "collection";
7523
7971
  }
7524
7972
  function isArrayType(node) {
7525
- if (node.type === AST_NODE_TYPES34.TSArrayType) return true;
7526
- return node.type === AST_NODE_TYPES34.TSTypeReference && node.typeName.type === AST_NODE_TYPES34.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7973
+ if (node.type === AST_NODE_TYPES36.TSArrayType) return true;
7974
+ return node.type === AST_NODE_TYPES36.TSTypeReference && node.typeName.type === AST_NODE_TYPES36.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7527
7975
  }
7528
7976
  function isNullishType(node) {
7529
- return node.type === AST_NODE_TYPES34.TSNullKeyword || node.type === AST_NODE_TYPES34.TSUndefinedKeyword;
7977
+ return node.type === AST_NODE_TYPES36.TSNullKeyword || node.type === AST_NODE_TYPES36.TSUndefinedKeyword;
7530
7978
  }
7531
7979
  function isNullableArrayOnly(node) {
7532
7980
  const values = node.types.filter((member) => !isNullishType(member));
7533
7981
  return values.length > 0 && values.length < node.types.length && values.every(isArrayType);
7534
7982
  }
7535
- var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7983
+ var prefer_non_nullable_collection_default = ESLintUtils46.RuleCreator(
7536
7984
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
7537
7985
  )({
7538
7986
  name: "prefer-non-nullable-collection",
@@ -7555,7 +8003,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7555
8003
  function checkOptionalProperty(node) {
7556
8004
  const annotation = node.typeAnnotation?.typeAnnotation;
7557
8005
  if (annotation === void 0) return;
7558
- if (annotation.type !== AST_NODE_TYPES34.TSUnionType || !isNullableArrayOnly(annotation)) {
8006
+ if (annotation.type !== AST_NODE_TYPES36.TSUnionType || !isNullableArrayOnly(annotation)) {
7559
8007
  return;
7560
8008
  }
7561
8009
  context.report({
@@ -7568,7 +8016,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7568
8016
  TSPropertySignature: checkOptionalProperty,
7569
8017
  PropertyDefinition: checkOptionalProperty,
7570
8018
  TSTypeAliasDeclaration(node) {
7571
- if (node.typeAnnotation.type !== AST_NODE_TYPES34.TSUnionType) return;
8019
+ if (node.typeAnnotation.type !== AST_NODE_TYPES36.TSUnionType) return;
7572
8020
  if (!isNullableArrayOnly(node.typeAnnotation)) return;
7573
8021
  context.report({
7574
8022
  node,
@@ -7580,174 +8028,217 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7580
8028
  }
7581
8029
  });
7582
8030
 
7583
- // src/rules/no-implicit-attribute-access.ts
7584
- import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils48 } from "@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 === AST_NODE_TYPES35.Identifier) {
7601
- return node.name;
8031
+ // src/rules/strict-test-assertions.ts
8032
+ import { AST_NODE_TYPES as AST_NODE_TYPES37, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
8033
+ var MERGEABLE_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
8034
+ var ARRAY_MATCHERS = /* @__PURE__ */ new Set(["toEqual", "toStrictEqual"]);
8035
+ var COLLECTION_PROPERTIES = /* @__PURE__ */ new Set(["length", "size"]);
8036
+ var NUMERIC_SIGNS2 = /* @__PURE__ */ new Set(["-", "+"]);
8037
+ var MIN_RUN_LENGTH = 2;
8038
+ function literalText(node, getText) {
8039
+ switch (node.type) {
8040
+ case AST_NODE_TYPES37.Literal:
8041
+ return "regex" in node ? null : getText(node);
8042
+ case AST_NODE_TYPES37.TemplateLiteral:
8043
+ return node.expressions.length === 0 ? getText(node) : null;
8044
+ case AST_NODE_TYPES37.UnaryExpression:
8045
+ return NUMERIC_SIGNS2.has(node.operator) && literalText(node.argument, getText) !== null ? getText(node) : null;
8046
+ default:
8047
+ return null;
7602
8048
  }
7603
- if (node.type === AST_NODE_TYPES35.MemberExpression && node.property.type === AST_NODE_TYPES35.Identifier) {
7604
- return node.property.name;
8049
+ }
8050
+ function isPureReceiver(node) {
8051
+ switch (node.type) {
8052
+ case AST_NODE_TYPES37.Identifier:
8053
+ case AST_NODE_TYPES37.ThisExpression:
8054
+ return true;
8055
+ case AST_NODE_TYPES37.MemberExpression:
8056
+ if (node.optional) {
8057
+ return false;
8058
+ }
8059
+ if (node.computed) {
8060
+ return node.property.type === AST_NODE_TYPES37.Literal && isPureReceiver(node.object);
8061
+ }
8062
+ return isPureReceiver(node.object);
8063
+ default:
8064
+ return false;
7605
8065
  }
7606
- return null;
7607
8066
  }
7608
- var no_implicit_attribute_access_default = ESLintUtils48.RuleCreator(
8067
+ function literalIndex(node) {
8068
+ if (node.type !== AST_NODE_TYPES37.Literal || typeof node.value !== "number") {
8069
+ return null;
8070
+ }
8071
+ return Number.isInteger(node.value) && node.value >= 0 ? node.value : null;
8072
+ }
8073
+ var strict_test_assertions_default = ESLintUtils47.RuleCreator(
7609
8074
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7610
8075
  )({
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 === AST_NODE_TYPES35.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 === AST_NODE_TYPES35.MemberExpression) {
7643
- const method = callee.property.type === AST_NODE_TYPES35.Identifier ? callee.property.name : null;
7644
- if (method === "get") {
7645
- const arg = node.arguments[0];
7646
- if (arg && arg.type === AST_NODE_TYPES35.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
- import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
7665
- var strict_test_assertions_default = ESLintUtils49.RuleCreator.withoutDocs({
8076
+ name: "strict-test-assertions",
7666
8077
  meta: {
7667
8078
  type: "suggestion",
7668
8079
  docs: {
7669
- description: "Replace multiple sequential assertions with a single toMatchObject or toStrictEqual"
8080
+ 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
8081
  },
7671
8082
  fixable: "code",
7672
8083
  messages: {
7673
- combineAssertions: "Combine multiple sequential assertions on the same object into a single toMatchObject or toStrictEqual"
8084
+ 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 })`.",
8085
+ 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
8086
  },
7675
8087
  schema: []
7676
8088
  },
7677
8089
  defaultOptions: [],
7678
8090
  create(context) {
7679
- function checkBody(body) {
7680
- let currentObject = null;
7681
- let sequence = [];
7682
- function getExpectObject(expr) {
7683
- if (expr.type === AST_NODE_TYPES36.CallExpression && expr.callee.type === AST_NODE_TYPES36.MemberExpression && expr.callee.object.type === AST_NODE_TYPES36.CallExpression && expr.callee.object.callee.type === AST_NODE_TYPES36.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 === AST_NODE_TYPES36.MemberExpression) {
7686
- return arg.object;
7687
- }
8091
+ if (!isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) {
8092
+ return {};
8093
+ }
8094
+ const { sourceCode } = context;
8095
+ function parseAssertion(statement) {
8096
+ if (statement.type !== AST_NODE_TYPES37.ExpressionStatement) {
8097
+ return null;
8098
+ }
8099
+ const call = statement.expression;
8100
+ if (call.type !== AST_NODE_TYPES37.CallExpression) {
8101
+ return null;
8102
+ }
8103
+ const callee = call.callee;
8104
+ if (callee.type !== AST_NODE_TYPES37.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES37.Identifier) {
8105
+ return null;
8106
+ }
8107
+ const matcher = callee.property.name;
8108
+ const expectCall = callee.object;
8109
+ if (expectCall.type !== AST_NODE_TYPES37.CallExpression || expectCall.callee.type !== AST_NODE_TYPES37.Identifier || expectCall.callee.name !== "expect" || expectCall.arguments.length !== 1) {
8110
+ return null;
8111
+ }
8112
+ const actual = expectCall.arguments[0];
8113
+ if (actual === void 0 || actual.type !== AST_NODE_TYPES37.MemberExpression || actual.optional) {
8114
+ return null;
8115
+ }
8116
+ if (!isPureReceiver(actual.object)) {
8117
+ return null;
8118
+ }
8119
+ let key;
8120
+ if (actual.computed) {
8121
+ const index = literalIndex(actual.property);
8122
+ if (index === null) {
8123
+ return null;
8124
+ }
8125
+ key = { kind: "index", index };
8126
+ } else {
8127
+ if (actual.property.type !== AST_NODE_TYPES37.Identifier || COLLECTION_PROPERTIES.has(actual.property.name)) {
8128
+ return null;
7688
8129
  }
8130
+ key = { kind: "property", name: actual.property.name };
8131
+ }
8132
+ if (matcher === "toBeNull" && call.arguments.length === 0) {
8133
+ return { statement, receiver: actual.object, key, matcher, expectedText: "null", expectedIsLiteral: true };
8134
+ }
8135
+ if (!MERGEABLE_MATCHERS.has(matcher)) {
7689
8136
  return null;
7690
8137
  }
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 !== AST_NODE_TYPES36.CallExpression || stmt.expression.callee.type !== AST_NODE_TYPES36.MemberExpression || stmt.expression.callee.object.type !== AST_NODE_TYPES36.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 === AST_NODE_TYPES36.MemberExpression && actual.property.type === AST_NODE_TYPES36.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
- });
8138
+ const expected = call.arguments[0];
8139
+ if (call.arguments.length !== 1 || expected === void 0 || expected.type === AST_NODE_TYPES37.SpreadElement) {
8140
+ return null;
8141
+ }
8142
+ const literal = literalText(expected, (node) => sourceCode.getText(node));
8143
+ return {
8144
+ statement,
8145
+ receiver: actual.object,
8146
+ key,
8147
+ matcher,
8148
+ expectedText: literal ?? sourceCode.getText(expected),
8149
+ expectedIsLiteral: literal !== null
8150
+ };
8151
+ }
8152
+ function reportPropertyRun(run) {
8153
+ const names = /* @__PURE__ */ new Set();
8154
+ for (const assertion of run) {
8155
+ if (assertion.key.kind !== "property" || !assertion.expectedIsLiteral) {
8156
+ return;
7721
8157
  }
8158
+ if (!MERGEABLE_MATCHERS.has(assertion.matcher) && assertion.matcher !== "toBeNull") {
8159
+ return;
8160
+ }
8161
+ if (names.has(assertion.key.name)) {
8162
+ return;
8163
+ }
8164
+ names.add(assertion.key.name);
7722
8165
  }
7723
- for (const statement of body) {
7724
- if (statement.type === AST_NODE_TYPES36.ExpressionStatement) {
7725
- const obj = getExpectObject(statement.expression);
7726
- if (obj && currentObject && context.sourceCode.getText(obj) === context.sourceCode.getText(currentObject)) {
7727
- sequence.push(statement);
8166
+ const first = run[0];
8167
+ if (first === void 0) {
8168
+ return;
8169
+ }
8170
+ const receiverText = sourceCode.getText(first.receiver);
8171
+ const properties = run.map(
8172
+ (assertion) => assertion.key.kind === "property" ? `${assertion.key.name}: ${assertion.expectedText}` : ""
8173
+ ).join(", ");
8174
+ context.report({
8175
+ node: first.statement,
8176
+ messageId: "combineAssertions",
8177
+ data: { count: String(run.length), receiver: receiverText },
8178
+ fix: (fixer) => [
8179
+ fixer.replaceText(first.statement, `expect(${receiverText}).toMatchObject({ ${properties} });`),
8180
+ ...run.slice(1).map((assertion) => fixer.remove(assertion.statement))
8181
+ ]
8182
+ });
8183
+ }
8184
+ function reportIndexRun(run) {
8185
+ const first = run[0];
8186
+ if (first === void 0 || !ARRAY_MATCHERS.has(first.matcher)) {
8187
+ return;
8188
+ }
8189
+ const indices = /* @__PURE__ */ new Set();
8190
+ for (const assertion of run) {
8191
+ if (assertion.key.kind !== "index" || assertion.matcher !== first.matcher) {
8192
+ return;
8193
+ }
8194
+ indices.add(assertion.key.index);
8195
+ }
8196
+ if (indices.size !== run.length || Math.max(...indices) !== run.length - 1) {
8197
+ return;
8198
+ }
8199
+ context.report({
8200
+ node: first.statement,
8201
+ messageId: "assertArrayOnce",
8202
+ data: {
8203
+ count: String(run.length),
8204
+ receiver: sourceCode.getText(first.receiver),
8205
+ last: String(run.length - 1),
8206
+ matcher: first.matcher
8207
+ }
8208
+ });
8209
+ }
8210
+ function checkBody(body) {
8211
+ let run = [];
8212
+ const flush = () => {
8213
+ const first = run[0];
8214
+ if (first !== void 0 && run.length >= MIN_RUN_LENGTH) {
8215
+ if (first.key.kind === "property") {
8216
+ reportPropertyRun(run);
7728
8217
  } else {
7729
- reportSequence();
7730
- if (obj) {
7731
- currentObject = obj;
7732
- sequence = [statement];
7733
- } else {
7734
- currentObject = null;
7735
- sequence = [];
7736
- }
8218
+ reportIndexRun(run);
7737
8219
  }
7738
- } else {
7739
- reportSequence();
7740
- currentObject = null;
7741
- sequence = [];
8220
+ }
8221
+ run = [];
8222
+ };
8223
+ for (const statement of body) {
8224
+ const assertion = parseAssertion(statement);
8225
+ const previous = run.at(-1);
8226
+ if (assertion !== null && previous !== void 0 && previous.key.kind === assertion.key.kind && sourceCode.getText(previous.receiver) === sourceCode.getText(assertion.receiver)) {
8227
+ run.push(assertion);
8228
+ continue;
8229
+ }
8230
+ flush();
8231
+ if (assertion !== null) {
8232
+ run = [assertion];
7742
8233
  }
7743
8234
  }
7744
- reportSequence();
8235
+ flush();
7745
8236
  }
7746
8237
  return {
7747
- BlockStatement(node) {
8238
+ BlockStatement: (node) => {
7748
8239
  checkBody(node.body);
7749
8240
  },
7750
- Program(node) {
8241
+ Program: (node) => {
7751
8242
  checkBody(node.body);
7752
8243
  }
7753
8244
  };
@@ -7755,8 +8246,8 @@ var strict_test_assertions_default = ESLintUtils49.RuleCreator.withoutDocs({
7755
8246
  });
7756
8247
 
7757
8248
  // src/rules/no-async-callback-in-waitfor.ts
7758
- import { AST_NODE_TYPES as AST_NODE_TYPES37, ESLintUtils as ESLintUtils50 } from "@typescript-eslint/utils";
7759
- var no_async_callback_in_waitfor_default = ESLintUtils50.RuleCreator(
8249
+ import { AST_NODE_TYPES as AST_NODE_TYPES38, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
8250
+ var no_async_callback_in_waitfor_default = ESLintUtils48.RuleCreator(
7760
8251
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7761
8252
  )({
7762
8253
  name: "no-async-callback-in-waitfor",
@@ -7777,9 +8268,9 @@ var no_async_callback_in_waitfor_default = ESLintUtils50.RuleCreator(
7777
8268
  }
7778
8269
  return {
7779
8270
  CallExpression(node) {
7780
- if (node.callee.type === AST_NODE_TYPES37.Identifier && node.callee.name === "waitFor") {
8271
+ if (node.callee.type === AST_NODE_TYPES38.Identifier && node.callee.name === "waitFor") {
7781
8272
  const callback = node.arguments[0];
7782
- if (callback && (callback.type === AST_NODE_TYPES37.ArrowFunctionExpression || callback.type === AST_NODE_TYPES37.FunctionExpression) && callback.async) {
8273
+ if (callback && (callback.type === AST_NODE_TYPES38.ArrowFunctionExpression || callback.type === AST_NODE_TYPES38.FunctionExpression) && callback.async) {
7783
8274
  context.report({
7784
8275
  node: callback,
7785
8276
  messageId: "noAsyncCallbackInWaitFor"
@@ -7792,7 +8283,7 @@ var no_async_callback_in_waitfor_default = ESLintUtils50.RuleCreator(
7792
8283
  });
7793
8284
 
7794
8285
  // src/rules/no-hand-rolled-sleep.ts
7795
- import { AST_NODE_TYPES as AST_NODE_TYPES38, ESLintUtils as ESLintUtils51 } from "@typescript-eslint/utils";
8286
+ import { AST_NODE_TYPES as AST_NODE_TYPES39, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
7796
8287
  var GLOBAL_OBJECTS2 = /* @__PURE__ */ new Set([
7797
8288
  "globalThis",
7798
8289
  "window",
@@ -7811,66 +8302,66 @@ function matchesAnyPattern3(filename, patterns) {
7811
8302
  return false;
7812
8303
  }
7813
8304
  function isSetTimeoutCallee(callee) {
7814
- if (callee.type === AST_NODE_TYPES38.Identifier) {
8305
+ if (callee.type === AST_NODE_TYPES39.Identifier) {
7815
8306
  return callee.name === "setTimeout";
7816
8307
  }
7817
- return callee.type === AST_NODE_TYPES38.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES38.Identifier && callee.property.name === "setTimeout" && callee.object.type === AST_NODE_TYPES38.Identifier && GLOBAL_OBJECTS2.has(callee.object.name);
8308
+ return callee.type === AST_NODE_TYPES39.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES39.Identifier && callee.property.name === "setTimeout" && callee.object.type === AST_NODE_TYPES39.Identifier && GLOBAL_OBJECTS2.has(callee.object.name);
7818
8309
  }
7819
8310
  function soleCall(fn) {
7820
- if (fn.body.type !== AST_NODE_TYPES38.BlockStatement) {
7821
- return fn.body.type === AST_NODE_TYPES38.CallExpression ? fn.body : null;
8311
+ if (fn.body.type !== AST_NODE_TYPES39.BlockStatement) {
8312
+ return fn.body.type === AST_NODE_TYPES39.CallExpression ? fn.body : null;
7822
8313
  }
7823
8314
  if (fn.body.body.length !== 1) {
7824
8315
  return null;
7825
8316
  }
7826
8317
  const [only] = fn.body.body;
7827
- if (only?.type !== AST_NODE_TYPES38.ExpressionStatement) {
8318
+ if (only?.type !== AST_NODE_TYPES39.ExpressionStatement) {
7828
8319
  return null;
7829
8320
  }
7830
- return only.expression.type === AST_NODE_TYPES38.CallExpression ? only.expression : null;
8321
+ return only.expression.type === AST_NODE_TYPES39.CallExpression ? only.expression : null;
7831
8322
  }
7832
8323
  function isTimedDelay(delay) {
7833
8324
  if (delay === void 0) {
7834
8325
  return false;
7835
8326
  }
7836
- if (delay.type === AST_NODE_TYPES38.Literal && typeof delay.value === "number") {
8327
+ if (delay.type === AST_NODE_TYPES39.Literal && typeof delay.value === "number") {
7837
8328
  return delay.value !== 0;
7838
8329
  }
7839
8330
  return true;
7840
8331
  }
7841
8332
  function settlesWithoutValue(callback, name) {
7842
- if (callback.type === AST_NODE_TYPES38.Identifier) {
8333
+ if (callback.type === AST_NODE_TYPES39.Identifier) {
7843
8334
  return callback.name === name;
7844
8335
  }
7845
- if (callback.type !== AST_NODE_TYPES38.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES38.FunctionExpression) {
8336
+ if (callback.type !== AST_NODE_TYPES39.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES39.FunctionExpression) {
7846
8337
  return false;
7847
8338
  }
7848
8339
  const call = soleCall(callback);
7849
- return call !== null && call.arguments.length === 0 && call.callee.type === AST_NODE_TYPES38.Identifier && call.callee.name === name;
8340
+ return call !== null && call.arguments.length === 0 && call.callee.type === AST_NODE_TYPES39.Identifier && call.callee.name === name;
7850
8341
  }
7851
8342
  function rejectsInCallback(callback, name) {
7852
- if (callback.type === AST_NODE_TYPES38.Identifier) {
8343
+ if (callback.type === AST_NODE_TYPES39.Identifier) {
7853
8344
  return callback.name === name;
7854
8345
  }
7855
- if (callback.type !== AST_NODE_TYPES38.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES38.FunctionExpression) {
8346
+ if (callback.type !== AST_NODE_TYPES39.ArrowFunctionExpression && callback.type !== AST_NODE_TYPES39.FunctionExpression) {
7856
8347
  return false;
7857
8348
  }
7858
8349
  const call = soleCall(callback);
7859
- return call !== null && call.callee.type === AST_NODE_TYPES38.Identifier && call.callee.name === name;
8350
+ return call !== null && call.callee.type === AST_NODE_TYPES39.Identifier && call.callee.name === name;
7860
8351
  }
7861
8352
  function parameterName(fn, index) {
7862
8353
  const parameter = fn.params[index];
7863
- return parameter?.type === AST_NODE_TYPES38.Identifier ? parameter.name : null;
8354
+ return parameter?.type === AST_NODE_TYPES39.Identifier ? parameter.name : null;
7864
8355
  }
7865
8356
  function isRaceArm(node) {
7866
8357
  const array = node.parent;
7867
- if (array?.type !== AST_NODE_TYPES38.ArrayExpression) {
8358
+ if (array?.type !== AST_NODE_TYPES39.ArrayExpression) {
7868
8359
  return false;
7869
8360
  }
7870
8361
  const call = array.parent;
7871
- return call?.type === AST_NODE_TYPES38.CallExpression && call.arguments[0] === array && call.callee.type === AST_NODE_TYPES38.MemberExpression && !call.callee.computed && call.callee.object.type === AST_NODE_TYPES38.Identifier && call.callee.object.name === "Promise" && call.callee.property.type === AST_NODE_TYPES38.Identifier && RACE_METHODS.has(call.callee.property.name);
8362
+ return call?.type === AST_NODE_TYPES39.CallExpression && call.arguments[0] === array && call.callee.type === AST_NODE_TYPES39.MemberExpression && !call.callee.computed && call.callee.object.type === AST_NODE_TYPES39.Identifier && call.callee.object.name === "Promise" && call.callee.property.type === AST_NODE_TYPES39.Identifier && RACE_METHODS.has(call.callee.property.name);
7872
8363
  }
7873
- var no_hand_rolled_sleep_default = ESLintUtils51.RuleCreator(
8364
+ var no_hand_rolled_sleep_default = ESLintUtils49.RuleCreator(
7874
8365
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7875
8366
  )({
7876
8367
  name: "no-hand-rolled-sleep",
@@ -7918,10 +8409,10 @@ var no_hand_rolled_sleep_default = ESLintUtils51.RuleCreator(
7918
8409
  }
7919
8410
  const program = sourceCode.ast;
7920
8411
  for (const statement of program.body) {
7921
- if (statement.type === AST_NODE_TYPES38.ExpressionStatement && statement.expression.type === AST_NODE_TYPES38.Literal && statement.expression.value === "use client") {
8412
+ if (statement.type === AST_NODE_TYPES39.ExpressionStatement && statement.expression.type === AST_NODE_TYPES39.Literal && statement.expression.value === "use client") {
7922
8413
  return true;
7923
8414
  }
7924
- if (statement.type === AST_NODE_TYPES38.ImportDeclaration && typeof statement.source.value === "string" && CLIENT_ONLY_MODULES.test(statement.source.value)) {
8415
+ if (statement.type === AST_NODE_TYPES39.ImportDeclaration && typeof statement.source.value === "string" && CLIENT_ONLY_MODULES.test(statement.source.value)) {
7925
8416
  return true;
7926
8417
  }
7927
8418
  }
@@ -7937,11 +8428,11 @@ var no_hand_rolled_sleep_default = ESLintUtils51.RuleCreator(
7937
8428
  };
7938
8429
  return {
7939
8430
  NewExpression(node) {
7940
- if (node.callee.type !== AST_NODE_TYPES38.Identifier || node.callee.name !== "Promise") {
8431
+ if (node.callee.type !== AST_NODE_TYPES39.Identifier || node.callee.name !== "Promise") {
7941
8432
  return;
7942
8433
  }
7943
8434
  const executor = node.arguments[0];
7944
- if (executor?.type !== AST_NODE_TYPES38.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES38.FunctionExpression) {
8435
+ if (executor?.type !== AST_NODE_TYPES39.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES39.FunctionExpression) {
7945
8436
  return;
7946
8437
  }
7947
8438
  const call = soleCall(executor);
@@ -7968,43 +8459,8 @@ var no_hand_rolled_sleep_default = ESLintUtils51.RuleCreator(
7968
8459
  }
7969
8460
  });
7970
8461
 
7971
- // src/rules/prefer-setup-file-mocks.ts
7972
- import { AST_NODE_TYPES as AST_NODE_TYPES39, ESLintUtils as ESLintUtils52 } from "@typescript-eslint/utils";
7973
- var prefer_setup_file_mocks_default = ESLintUtils52.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 === AST_NODE_TYPES39.MemberExpression && node.callee.object.type === AST_NODE_TYPES39.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === AST_NODE_TYPES39.Identifier && node.callee.property.name === "mock") {
7995
- context.report({
7996
- node,
7997
- messageId: "preferSetupFileMocks"
7998
- });
7999
- }
8000
- }
8001
- };
8002
- }
8003
- });
8004
-
8005
8462
  // src/index.ts
8006
8463
  var rules = {
8007
- "ban-loose-type-guards-in-tests": ban_loose_type_guards_in_tests_default,
8008
8464
  "enforce-file-structure": enforce_file_structure_default,
8009
8465
  "no-client-side-data-fetching": no_client_side_data_fetching_default,
8010
8466
  "no-comment-cruft": no_comment_cruft_default,
@@ -8053,14 +8509,12 @@ var rules = {
8053
8509
  "require-interface-for-injected-service": require_interface_for_injected_service_default,
8054
8510
  "strict-test-assertions": strict_test_assertions_default,
8055
8511
  "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
8512
+ "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default
8059
8513
  };
8060
8514
  var plugin = {
8061
8515
  meta: {
8062
8516
  name: "@sarj/eslint-plugin",
8063
- version: "4.2.0"
8517
+ version: "5.0.0"
8064
8518
  },
8065
8519
  rules,
8066
8520
  configs: {
@@ -8070,7 +8524,6 @@ var plugin = {
8070
8524
  "@sarj/zod-naming-convention": "warn",
8071
8525
  "@sarj/require-assert-never": "error",
8072
8526
  "@sarj/require-zod-form-validation": "error",
8073
- "@sarj/ban-loose-type-guards-in-tests": "error",
8074
8527
  "@sarj/enforce-file-structure": "warn",
8075
8528
  "@sarj/no-client-side-data-fetching": "warn",
8076
8529
  "@sarj/prefer-server-actions": "warn",
@@ -8155,9 +8608,7 @@ var plugin = {
8155
8608
  // port, 29 fire, 28 of them true positives.
8156
8609
  "@sarj/require-interface-for-injected-service": "warn",
8157
8610
  "@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"
8611
+ "@sarj/no-async-callback-in-waitfor": "warn"
8161
8612
  }
8162
8613
  },
8163
8614
  strict: {
@@ -8166,7 +8617,6 @@ var plugin = {
8166
8617
  "@sarj/zod-naming-convention": "error",
8167
8618
  "@sarj/require-assert-never": "error",
8168
8619
  "@sarj/require-zod-form-validation": "error",
8169
- "@sarj/ban-loose-type-guards-in-tests": "error",
8170
8620
  "@sarj/enforce-file-structure": "error",
8171
8621
  "@sarj/no-raw-env": "error",
8172
8622
  "@sarj/no-enum": "error",
@@ -8241,9 +8691,7 @@ var plugin = {
8241
8691
  // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
8242
8692
  "@sarj/require-interface-for-injected-service": "error",
8243
8693
  "@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"
8694
+ "@sarj/no-async-callback-in-waitfor": "error"
8247
8695
  }
8248
8696
  }
8249
8697
  }