@sarj/eslint-plugin 2.16.0 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- // src/rules/enforce-file-structure.ts
2
- import { ESLintUtils, AST_NODE_TYPES } from "@typescript-eslint/utils";
1
+ // src/rules/ban-loose-type-guards-in-tests.ts
2
+ import { ESLintUtils } from "@typescript-eslint/utils";
3
3
 
4
4
  // src/rules/_paths.ts
5
5
  var SCRIPT_FILE_RE = /([\\/]scripts[\\/])|(\.mjs$)/;
@@ -24,7 +24,43 @@ 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
+
27
62
  // src/rules/enforce-file-structure.ts
63
+ import { ESLintUtils as ESLintUtils2, AST_NODE_TYPES } from "@typescript-eslint/utils";
28
64
  var classifyStatement = (statement) => {
29
65
  switch (statement.type) {
30
66
  case AST_NODE_TYPES.ImportDeclaration:
@@ -44,7 +80,7 @@ var isUseServerDirective = (statement) => {
44
80
  if (expr.type !== AST_NODE_TYPES.Literal) return false;
45
81
  return expr.value === "use server";
46
82
  };
47
- var enforce_file_structure_default = ESLintUtils.RuleCreator(
83
+ var enforce_file_structure_default = ESLintUtils2.RuleCreator(
48
84
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
49
85
  )({
50
86
  name: "enforce-file-structure",
@@ -106,7 +142,7 @@ var enforce_file_structure_default = ESLintUtils.RuleCreator(
106
142
  // src/rules/no-client-side-data-fetching.ts
107
143
  import {
108
144
  AST_NODE_TYPES as AST_NODE_TYPES2,
109
- ESLintUtils as ESLintUtils2
145
+ ESLintUtils as ESLintUtils3
110
146
  } from "@typescript-eslint/utils";
111
147
  var FETCH_LIBS = /* @__PURE__ */ new Set(["axios", "ky", "superagent"]);
112
148
  var HTTP_METHOD_NAMES = /* @__PURE__ */ new Set([
@@ -204,7 +240,7 @@ function isAnalyticsCall(node) {
204
240
  if (url === "") return false;
205
241
  return url.split(/[/.]/).some((segment) => ANALYTICS_SEGMENTS.has(segment));
206
242
  }
207
- var no_client_side_data_fetching_default = ESLintUtils2.RuleCreator(
243
+ var no_client_side_data_fetching_default = ESLintUtils3.RuleCreator(
208
244
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
209
245
  )({
210
246
  name: "no-client-side-data-fetching",
@@ -242,7 +278,7 @@ var no_client_side_data_fetching_default = ESLintUtils2.RuleCreator(
242
278
  });
243
279
 
244
280
  // src/rules/no-comment-cruft.ts
245
- import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils3 } from "@typescript-eslint/utils";
281
+ import { AST_NODE_TYPES as AST_NODE_TYPES4, ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
246
282
 
247
283
  // src/rules/_comments.ts
248
284
  import { AST_NODE_TYPES as AST_NODE_TYPES3 } from "@typescript-eslint/utils";
@@ -611,7 +647,7 @@ function hasCommentedOutCode(texts, precedingProse) {
611
647
  }
612
648
  return false;
613
649
  }
614
- var no_comment_cruft_default = ESLintUtils3.RuleCreator(
650
+ var no_comment_cruft_default = ESLintUtils4.RuleCreator(
615
651
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
616
652
  )({
617
653
  name: "no-comment-cruft",
@@ -718,7 +754,7 @@ var no_comment_cruft_default = ESLintUtils3.RuleCreator(
718
754
  });
719
755
 
720
756
  // src/rules/no-enum.ts
721
- import { ESLintUtils as ESLintUtils4 } from "@typescript-eslint/utils";
757
+ import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
722
758
  var DEFAULT_IGNORE_PATTERNS = [
723
759
  /[\\/]generated[\\/]/,
724
760
  /[\\/]openapi-gen[\\/]/,
@@ -738,7 +774,7 @@ function hasGeneratedMarker(sourceText) {
738
774
  const head = sourceText.slice(0, 1024);
739
775
  return /@generated\b/.test(head);
740
776
  }
741
- var no_enum_default = ESLintUtils4.RuleCreator(
777
+ var no_enum_default = ESLintUtils5.RuleCreator(
742
778
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
743
779
  )({
744
780
  name: "no-enum",
@@ -789,7 +825,7 @@ var no_enum_default = ESLintUtils4.RuleCreator(
789
825
  });
790
826
 
791
827
  // src/rules/no-insecure-random-id.ts
792
- import { ESLintUtils as ESLintUtils5 } from "@typescript-eslint/utils";
828
+ import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
793
829
  var STRONG_SECURITY_PATTERN = /token|secret|csrf|password|passwd|apikey|api[-_]?key|nonce|salt|uuid|authid/i;
794
830
  var NON_SECURITY_ID_PATTERN = /temp|tmp|cache|correlation|request|req|trace|execution|dev|hmr|mock|test|perf|marker/i;
795
831
  var PATH_OR_DOM_MARKER = /[\\/#]|\.[A-Za-z0-9]/;
@@ -930,7 +966,7 @@ function isConcatenatedIntoPathOrDomId(node) {
930
966
  collectStaticStringParts(top, parts);
931
967
  return parts.some((part) => PATH_OR_DOM_MARKER.test(part));
932
968
  }
933
- var no_insecure_random_id_default = ESLintUtils5.RuleCreator(
969
+ var no_insecure_random_id_default = ESLintUtils6.RuleCreator(
934
970
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
935
971
  )({
936
972
  name: "no-insecure-random-id",
@@ -974,7 +1010,7 @@ var no_insecure_random_id_default = ESLintUtils5.RuleCreator(
974
1010
  });
975
1011
 
976
1012
  // src/rules/no-json-stringify-error.ts
977
- import { ESLintUtils as ESLintUtils6 } from "@typescript-eslint/utils";
1013
+ import { ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
978
1014
  var ERROR_NAME_PATTERN = /^(e|err|error|ex|exc)$/i;
979
1015
  var ERROR_PROP_PATTERN = /^(cause|lastError|error|err|exception|originalError|innerError)$/i;
980
1016
  var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
@@ -1108,7 +1144,7 @@ function isGuardedByInstanceofError(node, argExpr, sourceCode) {
1108
1144
  function isJsonStringify(callee) {
1109
1145
  return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "stringify";
1110
1146
  }
1111
- var no_json_stringify_error_default = ESLintUtils6.RuleCreator(
1147
+ var no_json_stringify_error_default = ESLintUtils7.RuleCreator(
1112
1148
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1113
1149
  )({
1114
1150
  name: "no-json-stringify-error",
@@ -1158,7 +1194,7 @@ var no_json_stringify_error_default = ESLintUtils6.RuleCreator(
1158
1194
  });
1159
1195
 
1160
1196
  // src/rules/no-log-only-catch.ts
1161
- import { ESLintUtils as ESLintUtils7 } from "@typescript-eslint/utils";
1197
+ import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
1162
1198
 
1163
1199
  // src/rules/_logging.ts
1164
1200
  import "@typescript-eslint/utils";
@@ -1268,7 +1304,7 @@ var DEFAULT_IGNORE_PATTERNS2 = [
1268
1304
  /\.spec\./,
1269
1305
  /[\\/]__tests__[\\/]/
1270
1306
  ];
1271
- var no_log_only_catch_default = ESLintUtils7.RuleCreator(
1307
+ var no_log_only_catch_default = ESLintUtils8.RuleCreator(
1272
1308
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1273
1309
  )({
1274
1310
  name: "no-log-only-catch",
@@ -1331,7 +1367,7 @@ var no_log_only_catch_default = ESLintUtils7.RuleCreator(
1331
1367
  });
1332
1368
 
1333
1369
  // src/rules/no-raw-env.ts
1334
- import { ESLintUtils as ESLintUtils8 } from "@typescript-eslint/utils";
1370
+ import { ESLintUtils as ESLintUtils9 } from "@typescript-eslint/utils";
1335
1371
  var CONFIG_FILE_RE = /(^|[\\/])[\w.-]+\.config\.[cm]?[jt]sx?$/;
1336
1372
  var ENV_BOUNDARY_FILE_RE = /(^|[\\/])(?:env|client-env|server-env|client-settings|server-settings)\.[cm]?[jt]sx?$/;
1337
1373
  function isValidatedEnvBoundary(filename, sourceText) {
@@ -1369,7 +1405,7 @@ function isWholeEnvSpread(node) {
1369
1405
  const parent = node.parent;
1370
1406
  return parent.type === "SpreadElement" && parent.argument === node;
1371
1407
  }
1372
- var no_raw_env_default = ESLintUtils8.RuleCreator(
1408
+ var no_raw_env_default = ESLintUtils9.RuleCreator(
1373
1409
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1374
1410
  )({
1375
1411
  name: "no-raw-env",
@@ -1404,7 +1440,7 @@ var no_raw_env_default = ESLintUtils8.RuleCreator(
1404
1440
 
1405
1441
  // src/rules/no-sentinel-return-on-catch.ts
1406
1442
  import {
1407
- ESLintUtils as ESLintUtils9,
1443
+ ESLintUtils as ESLintUtils10,
1408
1444
  AST_NODE_TYPES as AST_NODE_TYPES5
1409
1445
  } from "@typescript-eslint/utils";
1410
1446
  function sentinelKind(arg) {
@@ -1709,7 +1745,7 @@ function isWithin(node, ancestor) {
1709
1745
  }
1710
1746
  return false;
1711
1747
  }
1712
- var no_sentinel_return_on_catch_default = ESLintUtils9.RuleCreator(
1748
+ var no_sentinel_return_on_catch_default = ESLintUtils10.RuleCreator(
1713
1749
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1714
1750
  )({
1715
1751
  name: "no-sentinel-return-on-catch",
@@ -1790,7 +1826,7 @@ var no_sentinel_return_on_catch_default = ESLintUtils9.RuleCreator(
1790
1826
  });
1791
1827
 
1792
1828
  // src/rules/no-sequential-await.ts
1793
- import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
1829
+ import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
1794
1830
  var ARRAY_ITERATION_METHODS = /* @__PURE__ */ new Set(["forEach", "map", "filter"]);
1795
1831
  var SEQUENTIAL_ITERABLE_HINT = /sort|reverse|ordered|sequence|hook|middleware|pipeline|preset|plugin|extension|\bstage|\bstep|\bphase|migration|chain|buffer|stream|teleport|chunk|\bqueue|drain/i;
1796
1832
  var BENCH_FILE_RE = /(^|[\\/])bench(marks?)?[\\/]|\.bench\.[cm]?[jt]sx?$/i;
@@ -1944,7 +1980,7 @@ function shouldReport(awaits, earlyExit, iterableText, asserts = false) {
1944
1980
  (node) => !isTimerYield(node) && !isThreadedAccumulator(node) && !isQueueDrain(node)
1945
1981
  );
1946
1982
  }
1947
- var no_sequential_await_default = ESLintUtils10.RuleCreator(
1983
+ var no_sequential_await_default = ESLintUtils11.RuleCreator(
1948
1984
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1949
1985
  )({
1950
1986
  name: "no-sequential-await",
@@ -2039,7 +2075,7 @@ var no_sequential_await_default = ESLintUtils10.RuleCreator(
2039
2075
  });
2040
2076
 
2041
2077
  // src/rules/no-string-concat-in-loop.ts
2042
- import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
2078
+ import { ESLintUtils as ESLintUtils12 } from "@typescript-eslint/utils";
2043
2079
  var LOOP_NODE_TYPES = /* @__PURE__ */ new Set([
2044
2080
  "ForStatement",
2045
2081
  "ForOfStatement",
@@ -2124,7 +2160,7 @@ function enclosingLoop(node) {
2124
2160
  }
2125
2161
  return null;
2126
2162
  }
2127
- var no_string_concat_in_loop_default = ESLintUtils11.RuleCreator(
2163
+ var no_string_concat_in_loop_default = ESLintUtils12.RuleCreator(
2128
2164
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2129
2165
  )({
2130
2166
  name: "no-string-concat-in-loop",
@@ -2189,7 +2225,7 @@ var no_string_concat_in_loop_default = ESLintUtils11.RuleCreator(
2189
2225
  // src/rules/no-unnecessary-use-client.ts
2190
2226
  import {
2191
2227
  AST_NODE_TYPES as AST_NODE_TYPES6,
2192
- ESLintUtils as ESLintUtils12
2228
+ ESLintUtils as ESLintUtils13
2193
2229
  } from "@typescript-eslint/utils";
2194
2230
  var HOOK_REGEX = /^use([A-Z]|$)/;
2195
2231
  var EVENT_PROP_REGEX = /^on[A-Z]/;
@@ -2263,7 +2299,7 @@ var isGlobalReference = (node, context) => {
2263
2299
  }
2264
2300
  return true;
2265
2301
  };
2266
- var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2302
+ var no_unnecessary_use_client_default = ESLintUtils13.RuleCreator(
2267
2303
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2268
2304
  )({
2269
2305
  name: "no-unnecessary-use-client",
@@ -2384,7 +2420,7 @@ var no_unnecessary_use_client_default = ESLintUtils12.RuleCreator(
2384
2420
  });
2385
2421
 
2386
2422
  // src/rules/prefer-discriminated-union.ts
2387
- import { ESLintUtils as ESLintUtils13 } from "@typescript-eslint/utils";
2423
+ import { ESLintUtils as ESLintUtils14 } from "@typescript-eslint/utils";
2388
2424
  import { AST_NODE_TYPES as AST_NODE_TYPES7 } from "@typescript-eslint/utils";
2389
2425
  var STATUS_MEMBER_NAMES = /* @__PURE__ */ new Set([
2390
2426
  "success",
@@ -2431,7 +2467,7 @@ function looksLikeMutuallyExclusiveState(typeLiteral) {
2431
2467
  }
2432
2468
  return hasStatusBoolean && optionalCount >= MIN_OPTIONAL_MEMBERS && optionalPayloadCount >= 1;
2433
2469
  }
2434
- var prefer_discriminated_union_default = ESLintUtils13.RuleCreator(
2470
+ var prefer_discriminated_union_default = ESLintUtils14.RuleCreator(
2435
2471
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2436
2472
  )({
2437
2473
  name: "prefer-discriminated-union",
@@ -2474,7 +2510,7 @@ var prefer_discriminated_union_default = ESLintUtils13.RuleCreator(
2474
2510
  // src/rules/prefer-schema-for-api-payload.ts
2475
2511
  import {
2476
2512
  AST_NODE_TYPES as AST_NODE_TYPES8,
2477
- ESLintUtils as ESLintUtils14
2513
+ ESLintUtils as ESLintUtils15
2478
2514
  } from "@typescript-eslint/utils";
2479
2515
  var unwrap = (node) => {
2480
2516
  let current = node;
@@ -2597,7 +2633,7 @@ var isUnvalidatedVariableRef = (node, scope, tracked) => {
2597
2633
  const variable = findVariable2(scope, unwrapped.name);
2598
2634
  return variable !== null && tracked.has(variable);
2599
2635
  };
2600
- var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2636
+ var prefer_schema_for_api_payload_default = ESLintUtils15.RuleCreator(
2601
2637
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
2602
2638
  )({
2603
2639
  name: "prefer-schema-for-api-payload",
@@ -2711,7 +2747,7 @@ var prefer_schema_for_api_payload_default = ESLintUtils14.RuleCreator(
2711
2747
  });
2712
2748
 
2713
2749
  // src/rules/prefer-semantic-colors.ts
2714
- import { AST_NODE_TYPES as AST_NODE_TYPES9, ESLintUtils as ESLintUtils15 } from "@typescript-eslint/utils";
2750
+ import { AST_NODE_TYPES as AST_NODE_TYPES9, ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
2715
2751
  import { existsSync, readFileSync } from "fs";
2716
2752
  import { dirname, join, parse } from "path";
2717
2753
 
@@ -2848,7 +2884,7 @@ var propName = (key) => {
2848
2884
  if (key.type === AST_NODE_TYPES9.Literal && typeof key.value === "string") return key.value;
2849
2885
  return null;
2850
2886
  };
2851
- var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2887
+ var prefer_semantic_colors_default = ESLintUtils16.RuleCreator(
2852
2888
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
2853
2889
  )({
2854
2890
  name: "prefer-semantic-colors",
@@ -2970,7 +3006,7 @@ var prefer_semantic_colors_default = ESLintUtils15.RuleCreator(
2970
3006
  });
2971
3007
 
2972
3008
  // src/rules/prefer-server-actions.ts
2973
- import { ESLintUtils as ESLintUtils16 } from "@typescript-eslint/utils";
3009
+ import { ESLintUtils as ESLintUtils17 } from "@typescript-eslint/utils";
2974
3010
  var MUTATION_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "DELETE", "PATCH"]);
2975
3011
  var AXIOS_MUTATION_METHODS = /* @__PURE__ */ new Set(["post", "put", "delete", "patch"]);
2976
3012
  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\/)/;
@@ -3050,7 +3086,7 @@ function getPropertyNode(objNode, propName2) {
3050
3086
  }
3051
3087
  return null;
3052
3088
  }
3053
- var prefer_server_actions_default = ESLintUtils16.RuleCreator(
3089
+ var prefer_server_actions_default = ESLintUtils17.RuleCreator(
3054
3090
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3055
3091
  )({
3056
3092
  name: "prefer-server-actions",
@@ -3127,7 +3163,7 @@ var prefer_server_actions_default = ESLintUtils16.RuleCreator(
3127
3163
  // src/rules/prefer-shadcn.ts
3128
3164
  import {
3129
3165
  AST_NODE_TYPES as AST_NODE_TYPES10,
3130
- ESLintUtils as ESLintUtils17
3166
+ ESLintUtils as ESLintUtils18
3131
3167
  } from "@typescript-eslint/utils";
3132
3168
  var REPLACEMENTS = {
3133
3169
  select: "Select",
@@ -3163,7 +3199,7 @@ var resolveInputReplacement = (node) => {
3163
3199
  if (SKIPPED_INPUT_TYPES.has(typeAttr.value)) return null;
3164
3200
  return INPUT_TYPE_REPLACEMENTS[typeAttr.value] ?? "Input";
3165
3201
  };
3166
- var prefer_shadcn_default = ESLintUtils17.RuleCreator(
3202
+ var prefer_shadcn_default = ESLintUtils18.RuleCreator(
3167
3203
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3168
3204
  )({
3169
3205
  name: "prefer-shadcn",
@@ -3208,7 +3244,7 @@ var prefer_shadcn_default = ESLintUtils17.RuleCreator(
3208
3244
 
3209
3245
  // src/rules/require-assert-never.ts
3210
3246
  import {
3211
- ESLintUtils as ESLintUtils18,
3247
+ ESLintUtils as ESLintUtils19,
3212
3248
  AST_NODE_TYPES as AST_NODE_TYPES11
3213
3249
  } from "@typescript-eslint/utils";
3214
3250
  var isAssertNeverCall = (expression) => {
@@ -3260,7 +3296,7 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
3260
3296
  }
3261
3297
  return false;
3262
3298
  };
3263
- var require_assert_never_default = ESLintUtils18.RuleCreator(
3299
+ var require_assert_never_default = ESLintUtils19.RuleCreator(
3264
3300
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3265
3301
  )({
3266
3302
  name: "require-assert-never",
@@ -3298,7 +3334,7 @@ var require_assert_never_default = ESLintUtils18.RuleCreator(
3298
3334
  });
3299
3335
 
3300
3336
  // src/rules/require-zod-form-validation.ts
3301
- import { ESLintUtils as ESLintUtils19, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
3337
+ import { ESLintUtils as ESLintUtils20, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
3302
3338
 
3303
3339
  // src/rules/_zod.ts
3304
3340
  var ZOD_PREFIX_RE = /^Z[A-Z]/;
@@ -3342,7 +3378,7 @@ var isFormDataMethodCall = (node) => {
3342
3378
  const callee = current.callee;
3343
3379
  return callee.type === AST_NODE_TYPES12.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES12.Identifier && callee.property.name === "formData";
3344
3380
  };
3345
- var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3381
+ var require_zod_form_validation_default = ESLintUtils20.RuleCreator(
3346
3382
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3347
3383
  )({
3348
3384
  name: "require-zod-form-validation",
@@ -3428,7 +3464,7 @@ var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3428
3464
  });
3429
3465
 
3430
3466
  // src/rules/zod-naming-convention.ts
3431
- import { ESLintUtils as ESLintUtils20, AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
3467
+ import { ESLintUtils as ESLintUtils21, AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
3432
3468
  var CONVENTIONS = {
3433
3469
  prefix: { test: ZOD_PREFIX_RE, messageId: "zPrefix" },
3434
3470
  suffix: { test: ZOD_SUFFIX_RE, messageId: "schemaSuffix" },
@@ -3468,7 +3504,7 @@ var calleeChainStartsWithZ = (node) => {
3468
3504
  }
3469
3505
  return false;
3470
3506
  };
3471
- var zod_naming_convention_default = ESLintUtils20.RuleCreator(
3507
+ var zod_naming_convention_default = ESLintUtils21.RuleCreator(
3472
3508
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3473
3509
  )({
3474
3510
  name: "zod-naming-convention",
@@ -3526,7 +3562,7 @@ var zod_naming_convention_default = ESLintUtils20.RuleCreator(
3526
3562
  });
3527
3563
 
3528
3564
  // src/rules/no-cors-wildcard-with-credentials.ts
3529
- import { ESLintUtils as ESLintUtils21 } from "@typescript-eslint/utils";
3565
+ import { ESLintUtils as ESLintUtils22 } from "@typescript-eslint/utils";
3530
3566
  var ACAO_HEADER = "access-control-allow-origin";
3531
3567
  var ACAC_HEADER = "access-control-allow-credentials";
3532
3568
  var HEADER_SET_METHODS = /* @__PURE__ */ new Set(["setheader", "set", "append"]);
@@ -3668,7 +3704,7 @@ function enclosingScope(node) {
3668
3704
  }
3669
3705
  return void 0;
3670
3706
  }
3671
- var no_cors_wildcard_with_credentials_default = ESLintUtils21.RuleCreator(
3707
+ var no_cors_wildcard_with_credentials_default = ESLintUtils22.RuleCreator(
3672
3708
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3673
3709
  )({
3674
3710
  name: "no-cors-wildcard-with-credentials",
@@ -3736,7 +3772,7 @@ var no_cors_wildcard_with_credentials_default = ESLintUtils21.RuleCreator(
3736
3772
  });
3737
3773
 
3738
3774
  // src/rules/no-silent-promise-catch.ts
3739
- import { AST_NODE_TYPES as AST_NODE_TYPES14, ESLintUtils as ESLintUtils22 } from "@typescript-eslint/utils";
3775
+ import { AST_NODE_TYPES as AST_NODE_TYPES14, ESLintUtils as ESLintUtils23 } from "@typescript-eslint/utils";
3740
3776
  function isBodyParseCall(node) {
3741
3777
  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");
3742
3778
  }
@@ -3789,7 +3825,7 @@ function isSilentHandler(handler) {
3789
3825
  }
3790
3826
  return false;
3791
3827
  }
3792
- var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3828
+ var no_silent_promise_catch_default = ESLintUtils23.RuleCreator(
3793
3829
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3794
3830
  )({
3795
3831
  name: "no-silent-promise-catch",
@@ -3860,7 +3896,7 @@ var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3860
3896
  import {
3861
3897
  AST_NODE_TYPES as AST_NODE_TYPES15,
3862
3898
  ASTUtils,
3863
- ESLintUtils as ESLintUtils23
3899
+ ESLintUtils as ESLintUtils24
3864
3900
  } from "@typescript-eslint/utils";
3865
3901
  var CODEMOD_FIXTURE_RE = /[\\/]__testfixtures__[\\/]/;
3866
3902
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
@@ -3897,7 +3933,7 @@ function initProvablyLacksSignal(init) {
3897
3933
  function isStringish(node) {
3898
3934
  return node.type === AST_NODE_TYPES15.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES15.TemplateLiteral;
3899
3935
  }
3900
- var require_fetch_timeout_default = ESLintUtils23.RuleCreator(
3936
+ var require_fetch_timeout_default = ESLintUtils24.RuleCreator(
3901
3937
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3902
3938
  )({
3903
3939
  name: "require-fetch-timeout",
@@ -3961,7 +3997,7 @@ var require_fetch_timeout_default = ESLintUtils23.RuleCreator(
3961
3997
  });
3962
3998
 
3963
3999
  // src/rules/require-schema-validate-search.ts
3964
- import { AST_NODE_TYPES as AST_NODE_TYPES16, ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
4000
+ import { AST_NODE_TYPES as AST_NODE_TYPES16, ESLintUtils as ESLintUtils25 } from "@typescript-eslint/utils";
3965
4001
  var VALIDATOR_METHODS = /* @__PURE__ */ new Set([
3966
4002
  "parse",
3967
4003
  "safeParse",
@@ -4010,7 +4046,7 @@ function findCastExpression(node, insideValidatorArg) {
4010
4046
  }
4011
4047
  return null;
4012
4048
  }
4013
- var require_schema_validate_search_default = ESLintUtils24.RuleCreator(
4049
+ var require_schema_validate_search_default = ESLintUtils25.RuleCreator(
4014
4050
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4015
4051
  )({
4016
4052
  name: "require-schema-validate-search",
@@ -4049,7 +4085,7 @@ var require_schema_validate_search_default = ESLintUtils24.RuleCreator(
4049
4085
 
4050
4086
  // src/rules/no-fat-try-blocks.ts
4051
4087
  import {
4052
- ESLintUtils as ESLintUtils25,
4088
+ ESLintUtils as ESLintUtils26,
4053
4089
  AST_NODE_TYPES as AST_NODE_TYPES17
4054
4090
  } from "@typescript-eslint/utils";
4055
4091
  var MAX_TRY_BODY_STATEMENTS = 3;
@@ -4242,7 +4278,7 @@ function handlerRethrows(handler) {
4242
4278
  const last = body[body.length - 1];
4243
4279
  return last !== void 0 && last.type === AST_NODE_TYPES17.ThrowStatement;
4244
4280
  }
4245
- var no_fat_try_blocks_default = ESLintUtils25.RuleCreator(
4281
+ var no_fat_try_blocks_default = ESLintUtils26.RuleCreator(
4246
4282
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4247
4283
  )({
4248
4284
  name: "no-fat-try-blocks",
@@ -4286,7 +4322,7 @@ var no_fat_try_blocks_default = ESLintUtils25.RuleCreator(
4286
4322
  });
4287
4323
 
4288
4324
  // src/rules/no-secret-in-log.ts
4289
- import { ESLintUtils as ESLintUtils26 } from "@typescript-eslint/utils";
4325
+ import { ESLintUtils as ESLintUtils27 } from "@typescript-eslint/utils";
4290
4326
 
4291
4327
  // src/rules/_secret_names.ts
4292
4328
  var SECRET_WORDS = /* @__PURE__ */ new Set([
@@ -4548,7 +4584,7 @@ function propertyKeyName2(prop) {
4548
4584
  }
4549
4585
  return null;
4550
4586
  }
4551
- var no_secret_in_log_default = ESLintUtils26.RuleCreator(
4587
+ var no_secret_in_log_default = ESLintUtils27.RuleCreator(
4552
4588
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4553
4589
  )({
4554
4590
  name: "no-secret-in-log",
@@ -4625,7 +4661,7 @@ var no_secret_in_log_default = ESLintUtils26.RuleCreator(
4625
4661
  });
4626
4662
 
4627
4663
  // src/rules/no-unsafe-cast.ts
4628
- import { ESLintUtils as ESLintUtils27 } from "@typescript-eslint/utils";
4664
+ import { ESLintUtils as ESLintUtils28 } from "@typescript-eslint/utils";
4629
4665
  import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
4630
4666
  function isAnyAnnotation(node) {
4631
4667
  return node.type === AST_NODE_TYPES18.TSAnyKeyword;
@@ -4633,7 +4669,7 @@ function isAnyAnnotation(node) {
4633
4669
  function isConstAssertion(typeAnnotation) {
4634
4670
  return typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && typeAnnotation.typeName.name === "const";
4635
4671
  }
4636
- var no_unsafe_cast_default = ESLintUtils27.RuleCreator(
4672
+ var no_unsafe_cast_default = ESLintUtils28.RuleCreator(
4637
4673
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4638
4674
  )({
4639
4675
  name: "no-unsafe-cast",
@@ -4673,10 +4709,59 @@ var no_unsafe_cast_default = ESLintUtils27.RuleCreator(
4673
4709
  }
4674
4710
  });
4675
4711
 
4712
+ // src/rules/no-unsafe-mock-casting.ts
4713
+ import { ESLintUtils as ESLintUtils29 } from "@typescript-eslint/utils";
4714
+ import { AST_NODE_TYPES as AST_NODE_TYPES19 } from "@typescript-eslint/utils";
4715
+ function isMockTypeReference(node) {
4716
+ if (node.type !== AST_NODE_TYPES19.TSTypeReference) {
4717
+ return false;
4718
+ }
4719
+ const typeName = node.typeName;
4720
+ if (typeName.type === AST_NODE_TYPES19.Identifier) {
4721
+ const name = typeName.name;
4722
+ return name === "Mock" || name === "MockInstance" || name === "SpyInstance";
4723
+ }
4724
+ if (typeName.type === AST_NODE_TYPES19.TSQualifiedName) {
4725
+ const rightName = typeName.right.name;
4726
+ return rightName === "Mock" || rightName === "MockInstance" || rightName === "SpyInstance";
4727
+ }
4728
+ return false;
4729
+ }
4730
+ var no_unsafe_mock_casting_default = ESLintUtils29.RuleCreator(
4731
+ (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4732
+ )({
4733
+ name: "no-unsafe-mock-casting",
4734
+ meta: {
4735
+ type: "problem",
4736
+ docs: {
4737
+ description: "Disallow casting to mock types like `jest.Mock` or `vi.Mock`. Use `vi.mocked()` or `jest.mocked()` instead."
4738
+ },
4739
+ schema: [],
4740
+ messages: {
4741
+ unsafeMockCast: "Do not cast to a Mock type. Use `vi.mocked(fn)` or `jest.mocked(fn)` instead to preserve type safety."
4742
+ }
4743
+ },
4744
+ defaultOptions: [],
4745
+ create(context) {
4746
+ if (isGeneratedFile(context.filename, context.sourceCode.text)) {
4747
+ return {};
4748
+ }
4749
+ function checkAssertion(node) {
4750
+ if (isMockTypeReference(node.typeAnnotation)) {
4751
+ context.report({ node, messageId: "unsafeMockCast" });
4752
+ }
4753
+ }
4754
+ return {
4755
+ TSAsExpression: checkAssertion,
4756
+ TSTypeAssertion: checkAssertion
4757
+ };
4758
+ }
4759
+ });
4760
+
4676
4761
  // src/rules/prefer-string-literal-union.ts
4677
4762
  import {
4678
- ESLintUtils as ESLintUtils28,
4679
- AST_NODE_TYPES as AST_NODE_TYPES19
4763
+ ESLintUtils as ESLintUtils30,
4764
+ AST_NODE_TYPES as AST_NODE_TYPES20
4680
4765
  } from "@typescript-eslint/utils";
4681
4766
  import * as ts from "typescript";
4682
4767
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
@@ -4720,19 +4805,19 @@ function isChoiceLikeName(name) {
4720
4805
  return CHOICE_TOKENS.has(lastWord(name));
4721
4806
  }
4722
4807
  function keyName(key) {
4723
- if (key.type === AST_NODE_TYPES19.Identifier) {
4808
+ if (key.type === AST_NODE_TYPES20.Identifier) {
4724
4809
  return key.name;
4725
4810
  }
4726
- if (key.type === AST_NODE_TYPES19.Literal && typeof key.value === "string") {
4811
+ if (key.type === AST_NODE_TYPES20.Literal && typeof key.value === "string") {
4727
4812
  return key.value;
4728
4813
  }
4729
4814
  return null;
4730
4815
  }
4731
4816
  function isStringLiteralMember(t) {
4732
- return t.type === AST_NODE_TYPES19.TSLiteralType && t.literal.type === AST_NODE_TYPES19.Literal && typeof t.literal.value === "string";
4817
+ return t.type === AST_NODE_TYPES20.TSLiteralType && t.literal.type === AST_NODE_TYPES20.Literal && typeof t.literal.value === "string";
4733
4818
  }
4734
4819
  function isStringLiteralUnion(node) {
4735
- if (node?.type !== AST_NODE_TYPES19.TSUnionType) {
4820
+ if (node?.type !== AST_NODE_TYPES20.TSUnionType) {
4736
4821
  return false;
4737
4822
  }
4738
4823
  return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
@@ -4761,12 +4846,12 @@ function bindingSourceExpression(decl) {
4761
4846
  return ts.isForOfStatement(node) ? node.expression : node.initializer;
4762
4847
  }
4763
4848
  function refKey(node) {
4764
- if (node.type === AST_NODE_TYPES19.Identifier) {
4849
+ if (node.type === AST_NODE_TYPES20.Identifier) {
4765
4850
  return node.name;
4766
4851
  }
4767
- if (node.type === AST_NODE_TYPES19.MemberExpression && !node.computed) {
4852
+ if (node.type === AST_NODE_TYPES20.MemberExpression && !node.computed) {
4768
4853
  const inner = refKey(node.object);
4769
- if (inner === null || node.property.type !== AST_NODE_TYPES19.Identifier) {
4854
+ if (inner === null || node.property.type !== AST_NODE_TYPES20.Identifier) {
4770
4855
  return null;
4771
4856
  }
4772
4857
  return `${inner}.${node.property.name}`;
@@ -4774,12 +4859,12 @@ function refKey(node) {
4774
4859
  return null;
4775
4860
  }
4776
4861
  function strLiteral(node) {
4777
- if (node.type === AST_NODE_TYPES19.Literal && typeof node.value === "string") {
4862
+ if (node.type === AST_NODE_TYPES20.Literal && typeof node.value === "string") {
4778
4863
  return node.value;
4779
4864
  }
4780
4865
  return null;
4781
4866
  }
4782
- var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
4867
+ var prefer_string_literal_union_default = ESLintUtils30.RuleCreator(
4783
4868
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4784
4869
  )({
4785
4870
  name: "prefer-string-literal-union",
@@ -4817,7 +4902,7 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
4817
4902
  );
4818
4903
  let services;
4819
4904
  try {
4820
- services = ESLintUtils28.getParserServices(context);
4905
+ services = ESLintUtils30.getParserServices(context);
4821
4906
  } catch {
4822
4907
  services = null;
4823
4908
  }
@@ -4929,7 +5014,7 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
4929
5014
  containersWithUnion.add(container);
4930
5015
  return;
4931
5016
  }
4932
- if (typeNode?.type !== AST_NODE_TYPES19.TSStringKeyword) {
5017
+ if (typeNode?.type !== AST_NODE_TYPES20.TSStringKeyword) {
4933
5018
  return;
4934
5019
  }
4935
5020
  const name = keyName(key);
@@ -5017,10 +5102,10 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
5017
5102
  }
5018
5103
  };
5019
5104
  function refKeyText(node) {
5020
- if (node.type === AST_NODE_TYPES19.BinaryExpression) {
5105
+ if (node.type === AST_NODE_TYPES20.BinaryExpression) {
5021
5106
  return refKey(node.left) ?? refKey(node.right) ?? "value";
5022
5107
  }
5023
- if (node.type === AST_NODE_TYPES19.SwitchStatement) {
5108
+ if (node.type === AST_NODE_TYPES20.SwitchStatement) {
5024
5109
  return refKey(node.discriminant) ?? "value";
5025
5110
  }
5026
5111
  return "value";
@@ -5028,8 +5113,101 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
5028
5113
  }
5029
5114
  });
5030
5115
 
5116
+ // src/rules/prefer-zod-enum.ts
5117
+ import {
5118
+ AST_NODE_TYPES as AST_NODE_TYPES21,
5119
+ ESLintUtils as ESLintUtils31
5120
+ } from "@typescript-eslint/utils";
5121
+ function isZodModule(source) {
5122
+ return /(^|[/@-])zod([/-]|$)/.test(source);
5123
+ }
5124
+ var prefer_zod_enum_default = ESLintUtils31.RuleCreator(
5125
+ (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
5126
+ )({
5127
+ name: "prefer-zod-enum",
5128
+ meta: {
5129
+ type: "suggestion",
5130
+ docs: {
5131
+ description: "Prefer z.enum([...]) over z.union([z.literal(...), ...]) for string choices"
5132
+ },
5133
+ fixable: "code",
5134
+ schema: [],
5135
+ messages: {
5136
+ preferEnum: "Use `z.enum([...])` instead of a union of string-literal schemas."
5137
+ }
5138
+ },
5139
+ defaultOptions: [],
5140
+ create(context) {
5141
+ const sourceCode = context.sourceCode;
5142
+ const zodNamespaces = /* @__PURE__ */ new Set();
5143
+ function enumValues(node) {
5144
+ const callee = node.callee;
5145
+ if (callee.type !== AST_NODE_TYPES21.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES21.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== AST_NODE_TYPES21.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
5146
+ return null;
5147
+ }
5148
+ const argument = node.arguments[0];
5149
+ if (argument === void 0 || argument.type !== AST_NODE_TYPES21.ArrayExpression || argument.elements.length === 0) {
5150
+ return null;
5151
+ }
5152
+ const values = [];
5153
+ for (const element of argument.elements) {
5154
+ if (element === null || element.type !== AST_NODE_TYPES21.CallExpression || element.arguments.length !== 1 || element.callee.type !== AST_NODE_TYPES21.MemberExpression || element.callee.computed || element.callee.object.type !== AST_NODE_TYPES21.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== AST_NODE_TYPES21.Identifier || element.callee.property.name !== "literal") {
5155
+ return null;
5156
+ }
5157
+ const value = element.arguments[0];
5158
+ if (value === void 0 || value.type !== AST_NODE_TYPES21.Literal || typeof value.value !== "string") {
5159
+ return null;
5160
+ }
5161
+ values.push(value);
5162
+ }
5163
+ return values;
5164
+ }
5165
+ function buildFix(node, values) {
5166
+ const argument = node.arguments[0];
5167
+ if (argument === void 0 || argument.type !== AST_NODE_TYPES21.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
5168
+ return void 0;
5169
+ }
5170
+ const callee = node.callee;
5171
+ if (callee.type !== AST_NODE_TYPES21.MemberExpression || callee.property.type !== AST_NODE_TYPES21.Identifier) {
5172
+ return void 0;
5173
+ }
5174
+ return (fixer) => [
5175
+ fixer.replaceText(callee.property, "enum"),
5176
+ fixer.replaceText(
5177
+ argument,
5178
+ `[${values.map((value) => sourceCode.getText(value)).join(", ")}]`
5179
+ )
5180
+ ];
5181
+ }
5182
+ return {
5183
+ ImportDeclaration(node) {
5184
+ if (!isZodModule(node.source.value)) {
5185
+ return;
5186
+ }
5187
+ for (const specifier of node.specifiers) {
5188
+ if (specifier.type === AST_NODE_TYPES21.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES21.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES21.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES21.Identifier && specifier.imported.name === "z") {
5189
+ zodNamespaces.add(specifier.local.name);
5190
+ }
5191
+ }
5192
+ },
5193
+ CallExpression(node) {
5194
+ const values = enumValues(node);
5195
+ if (values === null) {
5196
+ return;
5197
+ }
5198
+ const fix = buildFix(node, values);
5199
+ context.report({
5200
+ node,
5201
+ messageId: "preferEnum",
5202
+ ...fix === void 0 ? {} : { fix }
5203
+ });
5204
+ }
5205
+ };
5206
+ }
5207
+ });
5208
+
5031
5209
  // src/rules/single-public-export.ts
5032
- import { ESLintUtils as ESLintUtils29, AST_NODE_TYPES as AST_NODE_TYPES20 } from "@typescript-eslint/utils";
5210
+ import { ESLintUtils as ESLintUtils32, AST_NODE_TYPES as AST_NODE_TYPES22 } from "@typescript-eslint/utils";
5033
5211
  var JUNK_DRAWER_STEMS = /* @__PURE__ */ new Set([
5034
5212
  "util",
5035
5213
  "utils",
@@ -5063,12 +5241,12 @@ var kebabCase2 = (name) => {
5063
5241
  }
5064
5242
  return normalized.replace(CAMEL_BOUNDARY_RE, "-").toLowerCase();
5065
5243
  };
5066
- var isFunctionExpression = (node) => node !== null && (node.type === AST_NODE_TYPES20.ArrowFunctionExpression || node.type === AST_NODE_TYPES20.FunctionExpression);
5244
+ var isFunctionExpression = (node) => node !== null && (node.type === AST_NODE_TYPES22.ArrowFunctionExpression || node.type === AST_NODE_TYPES22.FunctionExpression);
5067
5245
  var functionConstName = (decl) => {
5068
5246
  if (decl.declarations.length !== 1) return null;
5069
5247
  const [declarator] = decl.declarations;
5070
5248
  if (declarator === void 0) return null;
5071
- if (declarator.id.type !== AST_NODE_TYPES20.Identifier) return null;
5249
+ if (declarator.id.type !== AST_NODE_TYPES22.Identifier) return null;
5072
5250
  if (!isFunctionExpression(declarator.init)) return null;
5073
5251
  return declarator.id.name;
5074
5252
  };
@@ -5082,20 +5260,20 @@ var summarizeExports = (body) => {
5082
5260
  };
5083
5261
  for (const statement of body) {
5084
5262
  switch (statement.type) {
5085
- case AST_NODE_TYPES20.ExportAllDeclaration:
5263
+ case AST_NODE_TYPES22.ExportAllDeclaration:
5086
5264
  hasReExport = true;
5087
5265
  break;
5088
- case AST_NODE_TYPES20.ExportDefaultDeclaration: {
5266
+ case AST_NODE_TYPES22.ExportDefaultDeclaration: {
5089
5267
  names += 1;
5090
5268
  const decl = statement.declaration;
5091
- if (decl.type === AST_NODE_TYPES20.FunctionDeclaration && decl.id !== null) {
5269
+ if (decl.type === AST_NODE_TYPES22.FunctionDeclaration && decl.id !== null) {
5092
5270
  candidate = { name: decl.id.name, node: statement };
5093
- } else if (decl.type === AST_NODE_TYPES20.ClassDeclaration && decl.id !== null) {
5271
+ } else if (decl.type === AST_NODE_TYPES22.ClassDeclaration && decl.id !== null) {
5094
5272
  candidate = { name: decl.id.name, node: statement };
5095
5273
  }
5096
5274
  break;
5097
5275
  }
5098
- case AST_NODE_TYPES20.ExportNamedDeclaration: {
5276
+ case AST_NODE_TYPES22.ExportNamedDeclaration: {
5099
5277
  if (statement.source !== null) {
5100
5278
  hasReExport = true;
5101
5279
  break;
@@ -5106,15 +5284,15 @@ var summarizeExports = (body) => {
5106
5284
  break;
5107
5285
  }
5108
5286
  switch (decl.type) {
5109
- case AST_NODE_TYPES20.FunctionDeclaration:
5287
+ case AST_NODE_TYPES22.FunctionDeclaration:
5110
5288
  if (decl.id !== null) addCandidate(decl.id.name, statement);
5111
5289
  else names += 1;
5112
5290
  break;
5113
- case AST_NODE_TYPES20.ClassDeclaration:
5291
+ case AST_NODE_TYPES22.ClassDeclaration:
5114
5292
  if (decl.id !== null) addCandidate(decl.id.name, statement);
5115
5293
  else names += 1;
5116
5294
  break;
5117
- case AST_NODE_TYPES20.VariableDeclaration: {
5295
+ case AST_NODE_TYPES22.VariableDeclaration: {
5118
5296
  const fnName = functionConstName(decl);
5119
5297
  if (fnName !== null && decl.declarations.length === 1) {
5120
5298
  addCandidate(fnName, statement);
@@ -5134,7 +5312,7 @@ var summarizeExports = (body) => {
5134
5312
  }
5135
5313
  return { names, hasReExport, candidate };
5136
5314
  };
5137
- var single_public_export_default = ESLintUtils29.RuleCreator(
5315
+ var single_public_export_default = ESLintUtils32.RuleCreator(
5138
5316
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5139
5317
  )({
5140
5318
  name: "single-public-export",
@@ -5175,10 +5353,10 @@ var single_public_export_default = ESLintUtils29.RuleCreator(
5175
5353
  });
5176
5354
 
5177
5355
  // src/rules/no-offset-pagination.ts
5178
- import { ESLintUtils as ESLintUtils30 } from "@typescript-eslint/utils";
5356
+ import { ESLintUtils as ESLintUtils33 } from "@typescript-eslint/utils";
5179
5357
 
5180
5358
  // src/rules/_sql.ts
5181
- import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
5359
+ import { AST_NODE_TYPES as AST_NODE_TYPES23 } from "@typescript-eslint/utils";
5182
5360
  function stripSqlNoise(text) {
5183
5361
  const out = [...text];
5184
5362
  const n = text.length;
@@ -5239,13 +5417,13 @@ function stripSqlNoise(text) {
5239
5417
  var SUBSTITUTION_MARKER = "?";
5240
5418
  function sqlTextOf(node) {
5241
5419
  switch (node.type) {
5242
- case AST_NODE_TYPES21.Literal:
5420
+ case AST_NODE_TYPES23.Literal:
5243
5421
  return typeof node.value === "string" ? node.value : null;
5244
- case AST_NODE_TYPES21.TemplateLiteral:
5422
+ case AST_NODE_TYPES23.TemplateLiteral:
5245
5423
  return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join(SUBSTITUTION_MARKER);
5246
- case AST_NODE_TYPES21.TaggedTemplateExpression:
5424
+ case AST_NODE_TYPES23.TaggedTemplateExpression:
5247
5425
  return sqlTextOf(node.quasi);
5248
- case AST_NODE_TYPES21.BinaryExpression: {
5426
+ case AST_NODE_TYPES23.BinaryExpression: {
5249
5427
  if (node.operator !== "+") {
5250
5428
  return null;
5251
5429
  }
@@ -5253,7 +5431,7 @@ function sqlTextOf(node) {
5253
5431
  const right = sqlTextOf(node.right);
5254
5432
  return left !== null && right !== null ? left + right : null;
5255
5433
  }
5256
- case AST_NODE_TYPES21.ArrayExpression: {
5434
+ case AST_NODE_TYPES23.ArrayExpression: {
5257
5435
  const parts = [];
5258
5436
  for (const element of node.elements) {
5259
5437
  if (element === null) {
@@ -5273,7 +5451,7 @@ function sqlTextOf(node) {
5273
5451
  }
5274
5452
  function isJoinedFragmentArray(node) {
5275
5453
  const parent = node.parent;
5276
- 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;
5454
+ return parent?.type === AST_NODE_TYPES23.MemberExpression && parent.object === node && !parent.computed && parent.property.type === AST_NODE_TYPES23.Identifier && parent.property.name === "join" && parent.parent?.type === AST_NODE_TYPES23.CallExpression;
5277
5455
  }
5278
5456
  function markConsumed(node, consumed) {
5279
5457
  consumed.add(node);
@@ -5323,7 +5501,7 @@ function createSqlListener(handler) {
5323
5501
  // src/rules/no-offset-pagination.ts
5324
5502
  var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
5325
5503
  var OFFSET_GATE = /offset/i;
5326
- var no_offset_pagination_default = ESLintUtils30.RuleCreator(
5504
+ var no_offset_pagination_default = ESLintUtils33.RuleCreator(
5327
5505
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5328
5506
  )({
5329
5507
  name: "no-offset-pagination",
@@ -5352,15 +5530,15 @@ var no_offset_pagination_default = ESLintUtils30.RuleCreator(
5352
5530
  });
5353
5531
 
5354
5532
  // src/rules/no-positional-tuple-return.ts
5355
- import { AST_NODE_TYPES as AST_NODE_TYPES22, ESLintUtils as ESLintUtils31 } from "@typescript-eslint/utils";
5533
+ import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils34 } from "@typescript-eslint/utils";
5356
5534
  var MIN_ELEMENTS = 2;
5357
5535
  var ACCESSOR_PAIR_LENGTH = 2;
5358
5536
  var AWAITABLE_TYPES = /* @__PURE__ */ new Set(["Promise", "PromiseLike", "Awaited"]);
5359
5537
  function tupleReturnType(node) {
5360
- if (node.type === AST_NODE_TYPES22.TSTupleType) {
5538
+ if (node.type === AST_NODE_TYPES24.TSTupleType) {
5361
5539
  return node;
5362
5540
  }
5363
- if (node.type === AST_NODE_TYPES22.TSTypeReference && node.typeName.type === AST_NODE_TYPES22.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5541
+ if (node.type === AST_NODE_TYPES24.TSTypeReference && node.typeName.type === AST_NODE_TYPES24.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5364
5542
  const argument = node.typeArguments?.params[0];
5365
5543
  return argument === void 0 ? null : tupleReturnType(argument);
5366
5544
  }
@@ -5374,30 +5552,30 @@ function isPermittedTuple(tuple, sourceCode) {
5374
5552
  if (elements.length < MIN_ELEMENTS) {
5375
5553
  return true;
5376
5554
  }
5377
- if (elements.some((element) => element.type === AST_NODE_TYPES22.TSRestType)) {
5555
+ if (elements.some((element) => element.type === AST_NODE_TYPES24.TSRestType)) {
5378
5556
  return true;
5379
5557
  }
5380
- if (elements.some((element) => element.type === AST_NODE_TYPES22.TSNamedTupleMember)) {
5558
+ if (elements.some((element) => element.type === AST_NODE_TYPES24.TSNamedTupleMember)) {
5381
5559
  return true;
5382
5560
  }
5383
- if (elements[0]?.type === AST_NODE_TYPES22.TSLiteralType) {
5561
+ if (elements[0]?.type === AST_NODE_TYPES24.TSLiteralType) {
5384
5562
  return true;
5385
5563
  }
5386
- if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === AST_NODE_TYPES22.TSFunctionType)) {
5564
+ if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === AST_NODE_TYPES24.TSFunctionType)) {
5387
5565
  return true;
5388
5566
  }
5389
5567
  const texts = new Set(elements.map((element) => normalizedText(sourceCode, element)));
5390
5568
  return texts.size === 1;
5391
5569
  }
5392
5570
  function functionName(node) {
5393
- if (node.type === AST_NODE_TYPES22.FunctionDeclaration) {
5571
+ if (node.type === AST_NODE_TYPES24.FunctionDeclaration) {
5394
5572
  return node.id?.name ?? null;
5395
5573
  }
5396
5574
  const parent = node.parent;
5397
- if (parent?.type === AST_NODE_TYPES22.VariableDeclarator && parent.id.type === AST_NODE_TYPES22.Identifier) {
5575
+ if (parent?.type === AST_NODE_TYPES24.VariableDeclarator && parent.id.type === AST_NODE_TYPES24.Identifier) {
5398
5576
  return parent.id.name;
5399
5577
  }
5400
- 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) {
5578
+ if ((parent?.type === AST_NODE_TYPES24.MethodDefinition || parent?.type === AST_NODE_TYPES24.PropertyDefinition || parent?.type === AST_NODE_TYPES24.Property) && parent.key.type === AST_NODE_TYPES24.Identifier) {
5401
5579
  return parent.key.name;
5402
5580
  }
5403
5581
  return null;
@@ -5405,7 +5583,7 @@ function functionName(node) {
5405
5583
  function isInlineExported(node) {
5406
5584
  for (let current = node; current != null; current = current.parent) {
5407
5585
  const parent = current.parent;
5408
- if (parent?.type === AST_NODE_TYPES22.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES22.ExportDefaultDeclaration) {
5586
+ if (parent?.type === AST_NODE_TYPES24.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES24.ExportDefaultDeclaration) {
5409
5587
  return true;
5410
5588
  }
5411
5589
  }
@@ -5414,18 +5592,18 @@ function isInlineExported(node) {
5414
5592
  function moduleScopeBindingName(node) {
5415
5593
  let current = node;
5416
5594
  let child = node;
5417
- while (current.parent != null && current.parent.type !== AST_NODE_TYPES22.Program) {
5595
+ while (current.parent != null && current.parent.type !== AST_NODE_TYPES24.Program) {
5418
5596
  child = current;
5419
5597
  current = current.parent;
5420
5598
  }
5421
- if (current.parent?.type !== AST_NODE_TYPES22.Program) {
5599
+ if (current.parent?.type !== AST_NODE_TYPES24.Program) {
5422
5600
  return null;
5423
5601
  }
5424
- if (current.type === AST_NODE_TYPES22.FunctionDeclaration || current.type === AST_NODE_TYPES22.ClassDeclaration) {
5602
+ if (current.type === AST_NODE_TYPES24.FunctionDeclaration || current.type === AST_NODE_TYPES24.ClassDeclaration) {
5425
5603
  return current.id?.name ?? null;
5426
5604
  }
5427
- if (current.type === AST_NODE_TYPES22.VariableDeclaration) {
5428
- if (child.type !== AST_NODE_TYPES22.VariableDeclarator || child.id.type !== AST_NODE_TYPES22.Identifier) {
5605
+ if (current.type === AST_NODE_TYPES24.VariableDeclaration) {
5606
+ if (child.type !== AST_NODE_TYPES24.VariableDeclarator || child.id.type !== AST_NODE_TYPES24.Identifier) {
5429
5607
  return null;
5430
5608
  }
5431
5609
  return child.id.name;
@@ -5435,19 +5613,19 @@ function moduleScopeBindingName(node) {
5435
5613
  function specifierExportedNames(program) {
5436
5614
  const names = /* @__PURE__ */ new Set();
5437
5615
  for (const statement of program.body) {
5438
- if (statement.type === AST_NODE_TYPES22.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5616
+ if (statement.type === AST_NODE_TYPES24.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5439
5617
  for (const specifier of statement.specifiers) {
5440
- if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES22.Identifier) {
5618
+ if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES24.Identifier) {
5441
5619
  names.add(specifier.local.name);
5442
5620
  }
5443
5621
  }
5444
5622
  continue;
5445
5623
  }
5446
- if (statement.type === AST_NODE_TYPES22.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES22.Identifier) {
5624
+ if (statement.type === AST_NODE_TYPES24.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES24.Identifier) {
5447
5625
  names.add(statement.declaration.name);
5448
5626
  continue;
5449
5627
  }
5450
- if (statement.type === AST_NODE_TYPES22.TSExportAssignment && statement.expression.type === AST_NODE_TYPES22.Identifier) {
5628
+ if (statement.type === AST_NODE_TYPES24.TSExportAssignment && statement.expression.type === AST_NODE_TYPES24.Identifier) {
5451
5629
  names.add(statement.expression.name);
5452
5630
  }
5453
5631
  }
@@ -5463,7 +5641,7 @@ function isExported(node, specifierExports) {
5463
5641
  const binding = moduleScopeBindingName(node);
5464
5642
  return binding !== null && specifierExports.has(binding);
5465
5643
  }
5466
- var no_positional_tuple_return_default = ESLintUtils31.RuleCreator(
5644
+ var no_positional_tuple_return_default = ESLintUtils34.RuleCreator(
5467
5645
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5468
5646
  )({
5469
5647
  name: "no-positional-tuple-return",
@@ -5511,16 +5689,16 @@ var no_positional_tuple_return_default = ESLintUtils31.RuleCreator(
5511
5689
  });
5512
5690
 
5513
5691
  // src/rules/no-repeated-string-literal.ts
5514
- import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils32 } from "@typescript-eslint/utils";
5692
+ import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils35 } from "@typescript-eslint/utils";
5515
5693
  var MIN_LENGTH = 40;
5516
5694
  var MIN_DISTINCT_SCOPES = 2;
5517
5695
  var PREVIEW_LENGTH = 40;
5518
5696
  var SQL_KEYWORD_RE = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES|ON CONFLICT|RETURNING|GROUP BY|ORDER BY)\b/;
5519
5697
  var IDENTIFIER_RE = /^[a-z_][a-z0-9_.]*$/;
5520
5698
  var FUNCTION_TYPES = /* @__PURE__ */ new Set([
5521
- AST_NODE_TYPES23.FunctionDeclaration,
5522
- AST_NODE_TYPES23.FunctionExpression,
5523
- AST_NODE_TYPES23.ArrowFunctionExpression
5699
+ AST_NODE_TYPES25.FunctionDeclaration,
5700
+ AST_NODE_TYPES25.FunctionExpression,
5701
+ AST_NODE_TYPES25.ArrowFunctionExpression
5524
5702
  ]);
5525
5703
  function isStructured(value) {
5526
5704
  return value.includes("\n") || SQL_KEYWORD_RE.test(value) || IDENTIFIER_RE.test(value);
@@ -5542,9 +5720,9 @@ function isScaffolding(node) {
5542
5720
  if (parent === void 0) {
5543
5721
  return true;
5544
5722
  }
5545
- 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;
5723
+ return parent.type === AST_NODE_TYPES25.ImportDeclaration || parent.type === AST_NODE_TYPES25.ExportNamedDeclaration || parent.type === AST_NODE_TYPES25.ExportAllDeclaration || parent.type === AST_NODE_TYPES25.TSImportType || parent.type === AST_NODE_TYPES25.JSXAttribute || parent.type === AST_NODE_TYPES25.TSLiteralType;
5546
5724
  }
5547
- var no_repeated_string_literal_default = ESLintUtils32.RuleCreator(
5725
+ var no_repeated_string_literal_default = ESLintUtils35.RuleCreator(
5548
5726
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5549
5727
  )({
5550
5728
  name: "no-repeated-string-literal",
@@ -5584,7 +5762,7 @@ var no_repeated_string_literal_default = ESLintUtils32.RuleCreator(
5584
5762
  }
5585
5763
  },
5586
5764
  TemplateLiteral(node) {
5587
- if (node.parent.type === AST_NODE_TYPES23.TaggedTemplateExpression) {
5765
+ if (node.parent.type === AST_NODE_TYPES25.TaggedTemplateExpression) {
5588
5766
  return;
5589
5767
  }
5590
5768
  const [only] = node.quasis;
@@ -5618,7 +5796,7 @@ var no_repeated_string_literal_default = ESLintUtils32.RuleCreator(
5618
5796
  });
5619
5797
 
5620
5798
  // src/rules/no-select-star.ts
5621
- import { ESLintUtils as ESLintUtils33 } from "@typescript-eslint/utils";
5799
+ import { ESLintUtils as ESLintUtils36 } from "@typescript-eslint/utils";
5622
5800
  var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
5623
5801
  var SELECT_KEYWORD = /\bSELECT\b/gi;
5624
5802
  var FROM_KEYWORD = /^FROM\b/i;
@@ -5658,7 +5836,7 @@ function hasRealSelectStar(sql) {
5658
5836
  }
5659
5837
  return false;
5660
5838
  }
5661
- var no_select_star_default = ESLintUtils33.RuleCreator(
5839
+ var no_select_star_default = ESLintUtils36.RuleCreator(
5662
5840
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5663
5841
  )({
5664
5842
  name: "no-select-star",
@@ -5687,7 +5865,7 @@ var no_select_star_default = ESLintUtils33.RuleCreator(
5687
5865
  });
5688
5866
 
5689
5867
  // src/rules/no-sleep-in-test-body.ts
5690
- import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils34 } from "@typescript-eslint/utils";
5868
+ import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils37 } from "@typescript-eslint/utils";
5691
5869
  var SLEEP_HELPERS = /* @__PURE__ */ new Set(["sleep", "delay", "wait", "pause"]);
5692
5870
  var TEST_CALLERS = /* @__PURE__ */ new Set([
5693
5871
  "it",
@@ -5696,34 +5874,34 @@ var TEST_CALLERS = /* @__PURE__ */ new Set([
5696
5874
  "afterEach"
5697
5875
  ]);
5698
5876
  var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5699
- AST_NODE_TYPES24.FunctionDeclaration,
5700
- AST_NODE_TYPES24.FunctionExpression,
5701
- AST_NODE_TYPES24.ArrowFunctionExpression
5877
+ AST_NODE_TYPES26.FunctionDeclaration,
5878
+ AST_NODE_TYPES26.FunctionExpression,
5879
+ AST_NODE_TYPES26.ArrowFunctionExpression
5702
5880
  ]);
5703
5881
  function isNonzeroNumericLiteral(node) {
5704
- return node?.type === AST_NODE_TYPES24.Literal && typeof node.value === "number" && node.value !== 0;
5882
+ return node?.type === AST_NODE_TYPES26.Literal && typeof node.value === "number" && node.value !== 0;
5705
5883
  }
5706
5884
  function isTimedSetTimeout(node) {
5707
- 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]);
5885
+ return node.type === AST_NODE_TYPES26.CallExpression && node.callee.type === AST_NODE_TYPES26.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5708
5886
  }
5709
5887
  function isPromiseSleep(node) {
5710
- if (node.callee.type !== AST_NODE_TYPES24.Identifier || node.callee.name !== "Promise") {
5888
+ if (node.callee.type !== AST_NODE_TYPES26.Identifier || node.callee.name !== "Promise") {
5711
5889
  return false;
5712
5890
  }
5713
5891
  const executor = node.arguments[0];
5714
- if (executor?.type !== AST_NODE_TYPES24.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES24.FunctionExpression) {
5892
+ if (executor?.type !== AST_NODE_TYPES26.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES26.FunctionExpression) {
5715
5893
  return false;
5716
5894
  }
5717
5895
  const body = executor.body;
5718
- if (body.type !== AST_NODE_TYPES24.BlockStatement) {
5896
+ if (body.type !== AST_NODE_TYPES26.BlockStatement) {
5719
5897
  return isTimedSetTimeout(body);
5720
5898
  }
5721
5899
  return body.body.some(
5722
- (stmt) => stmt.type === AST_NODE_TYPES24.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5900
+ (stmt) => stmt.type === AST_NODE_TYPES26.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5723
5901
  );
5724
5902
  }
5725
5903
  function isHelperSleep(node) {
5726
- return node.callee.type === AST_NODE_TYPES24.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5904
+ return node.callee.type === AST_NODE_TYPES26.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5727
5905
  }
5728
5906
  function nearestEnclosingFunction(node) {
5729
5907
  for (let current = node.parent; current != null; current = current.parent) {
@@ -5731,7 +5909,7 @@ function nearestEnclosingFunction(node) {
5731
5909
  continue;
5732
5910
  }
5733
5911
  const grandparent = current.parent;
5734
- const isPromiseExecutor = grandparent?.type === AST_NODE_TYPES24.NewExpression && isPromiseSleep(grandparent);
5912
+ const isPromiseExecutor = grandparent?.type === AST_NODE_TYPES26.NewExpression && isPromiseSleep(grandparent);
5735
5913
  if (!isPromiseExecutor) {
5736
5914
  return current;
5737
5915
  }
@@ -5739,29 +5917,29 @@ function nearestEnclosingFunction(node) {
5739
5917
  return null;
5740
5918
  }
5741
5919
  function testCallerName(callee) {
5742
- if (callee.type === AST_NODE_TYPES24.Identifier) {
5920
+ if (callee.type === AST_NODE_TYPES26.Identifier) {
5743
5921
  return callee.name;
5744
5922
  }
5745
- if (callee.type === AST_NODE_TYPES24.MemberExpression) {
5923
+ if (callee.type === AST_NODE_TYPES26.MemberExpression) {
5746
5924
  return testCallerName(callee.object);
5747
5925
  }
5748
- if (callee.type === AST_NODE_TYPES24.CallExpression) {
5926
+ if (callee.type === AST_NODE_TYPES26.CallExpression) {
5749
5927
  return testCallerName(callee.callee);
5750
5928
  }
5751
- if (callee.type === AST_NODE_TYPES24.TaggedTemplateExpression) {
5929
+ if (callee.type === AST_NODE_TYPES26.TaggedTemplateExpression) {
5752
5930
  return testCallerName(callee.tag);
5753
5931
  }
5754
5932
  return null;
5755
5933
  }
5756
5934
  function isTestBody(fn) {
5757
5935
  const call = fn.parent;
5758
- if (call?.type !== AST_NODE_TYPES24.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5936
+ if (call?.type !== AST_NODE_TYPES26.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5759
5937
  return false;
5760
5938
  }
5761
5939
  const name = testCallerName(call.callee);
5762
5940
  return name !== null && TEST_CALLERS.has(name);
5763
5941
  }
5764
- var no_sleep_in_test_body_default = ESLintUtils34.RuleCreator(
5942
+ var no_sleep_in_test_body_default = ESLintUtils37.RuleCreator(
5765
5943
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5766
5944
  )({
5767
5945
  name: "no-sleep-in-test-body",
@@ -5802,8 +5980,90 @@ var no_sleep_in_test_body_default = ESLintUtils34.RuleCreator(
5802
5980
  }
5803
5981
  });
5804
5982
 
5983
+ // src/rules/no-conditional-in-test.ts
5984
+ import { AST_NODE_TYPES as AST_NODE_TYPES27, ESLintUtils as ESLintUtils38 } from "@typescript-eslint/utils";
5985
+ var TEST_CALLERS2 = /* @__PURE__ */ new Set(["it", "test"]);
5986
+ var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5987
+ AST_NODE_TYPES27.FunctionDeclaration,
5988
+ AST_NODE_TYPES27.FunctionExpression,
5989
+ AST_NODE_TYPES27.ArrowFunctionExpression
5990
+ ]);
5991
+ function nearestEnclosingFunction2(node) {
5992
+ for (let current = node.parent; current != null; current = current.parent) {
5993
+ if (FUNCTION_TYPES3.has(current.type)) {
5994
+ return current;
5995
+ }
5996
+ }
5997
+ return null;
5998
+ }
5999
+ function testCallerName2(callee) {
6000
+ if (callee.type === AST_NODE_TYPES27.Identifier) {
6001
+ return callee.name;
6002
+ }
6003
+ if (callee.type === AST_NODE_TYPES27.MemberExpression) {
6004
+ return testCallerName2(callee.object);
6005
+ }
6006
+ if (callee.type === AST_NODE_TYPES27.CallExpression) {
6007
+ return testCallerName2(callee.callee);
6008
+ }
6009
+ if (callee.type === AST_NODE_TYPES27.TaggedTemplateExpression) {
6010
+ return testCallerName2(callee.tag);
6011
+ }
6012
+ return null;
6013
+ }
6014
+ function isTestBody2(fn) {
6015
+ const call = fn.parent;
6016
+ if (call?.type !== AST_NODE_TYPES27.CallExpression || !call.arguments.some((argument) => argument === fn)) {
6017
+ return false;
6018
+ }
6019
+ const name = testCallerName2(call.callee);
6020
+ return name !== null && TEST_CALLERS2.has(name);
6021
+ }
6022
+ var no_conditional_in_test_default = ESLintUtils38.RuleCreator(
6023
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6024
+ )({
6025
+ name: "no-conditional-in-test",
6026
+ meta: {
6027
+ type: "problem",
6028
+ docs: {
6029
+ description: "Disallow conditional logic (if, switch, ternary) in test bodies, which can hide missing assertions or test multiple code paths."
6030
+ },
6031
+ schema: [],
6032
+ messages: {
6033
+ noConditionalInTest: "Avoid using conditional logic in tests. It can obscure intent and hide unexecuted assertions. Split the test instead."
6034
+ }
6035
+ },
6036
+ defaultOptions: [],
6037
+ create(context) {
6038
+ if (!isTestFile(context.filename)) {
6039
+ return {};
6040
+ }
6041
+ const report = (node) => {
6042
+ const enclosing = nearestEnclosingFunction2(node);
6043
+ if (enclosing === null || !isTestBody2(enclosing)) {
6044
+ return;
6045
+ }
6046
+ context.report({ node, messageId: "noConditionalInTest" });
6047
+ };
6048
+ return {
6049
+ IfStatement(node) {
6050
+ report(node);
6051
+ },
6052
+ SwitchStatement(node) {
6053
+ report(node);
6054
+ },
6055
+ ConditionalExpression(node) {
6056
+ report(node);
6057
+ },
6058
+ LogicalExpression(node) {
6059
+ report(node);
6060
+ }
6061
+ };
6062
+ }
6063
+ });
6064
+
5805
6065
  // src/rules/prefer-constant-time-secret-compare.ts
5806
- import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils35 } from "@typescript-eslint/utils";
6066
+ import { AST_NODE_TYPES as AST_NODE_TYPES28, ESLintUtils as ESLintUtils39 } from "@typescript-eslint/utils";
5807
6067
  var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["===", "!==", "==", "!="]);
5808
6068
  var SENTINEL_IDENTIFIERS = /* @__PURE__ */ new Set(["undefined", "NaN"]);
5809
6069
  var SENTINEL_WORDS = /(^|_)(SENTINEL|EMPTY|NONE|NULL|UNSET|MISSING|PLACEHOLDER|DUMMY|FAKE|EXAMPLE)(_|$)/;
@@ -5816,36 +6076,36 @@ function isConstantReference(identifier) {
5816
6076
  }
5817
6077
  function isExcludedOperand(node) {
5818
6078
  switch (node.type) {
5819
- case AST_NODE_TYPES25.Literal:
6079
+ case AST_NODE_TYPES28.Literal:
5820
6080
  return true;
5821
- case AST_NODE_TYPES25.TemplateLiteral:
6081
+ case AST_NODE_TYPES28.TemplateLiteral:
5822
6082
  return node.expressions.length === 0;
5823
- case AST_NODE_TYPES25.Identifier:
6083
+ case AST_NODE_TYPES28.Identifier:
5824
6084
  return SENTINEL_IDENTIFIERS.has(node.name) || SENTINEL_PREFIX_RE.test(node.name) || isConstantReference(node.name);
5825
- case AST_NODE_TYPES25.MemberExpression:
5826
- return !node.computed && node.property.type === AST_NODE_TYPES25.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
6085
+ case AST_NODE_TYPES28.MemberExpression:
6086
+ return !node.computed && node.property.type === AST_NODE_TYPES28.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
5827
6087
  default:
5828
6088
  return false;
5829
6089
  }
5830
6090
  }
5831
6091
  function operandName(node) {
5832
- if (node.type === AST_NODE_TYPES25.Identifier) {
6092
+ if (node.type === AST_NODE_TYPES28.Identifier) {
5833
6093
  return node.name;
5834
6094
  }
5835
- if (node.type === AST_NODE_TYPES25.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES25.Identifier) {
6095
+ if (node.type === AST_NODE_TYPES28.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES28.Identifier) {
5836
6096
  return node.property.name;
5837
6097
  }
5838
6098
  return null;
5839
6099
  }
5840
6100
  function isSecretOperand(node) {
5841
- if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
6101
+ if (node.type === AST_NODE_TYPES28.TemplateLiteral) {
5842
6102
  return node.expressions.some((expression) => isSecretOperand(expression));
5843
6103
  }
5844
6104
  const name = operandName(node);
5845
6105
  return name !== null && isAuthSecretName(name);
5846
6106
  }
5847
6107
  function secretNameOf(node) {
5848
- if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
6108
+ if (node.type === AST_NODE_TYPES28.TemplateLiteral) {
5849
6109
  for (const expression of node.expressions) {
5850
6110
  const nested = secretNameOf(expression);
5851
6111
  if (nested !== null) {
@@ -5856,7 +6116,7 @@ function secretNameOf(node) {
5856
6116
  }
5857
6117
  return operandName(node);
5858
6118
  }
5859
- var prefer_constant_time_secret_compare_default = ESLintUtils35.RuleCreator(
6119
+ var prefer_constant_time_secret_compare_default = ESLintUtils39.RuleCreator(
5860
6120
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5861
6121
  )({
5862
6122
  name: "prefer-constant-time-secret-compare",
@@ -5899,11 +6159,11 @@ var prefer_constant_time_secret_compare_default = ESLintUtils35.RuleCreator(
5899
6159
  });
5900
6160
 
5901
6161
  // src/rules/store-insert-requires-on-conflict.ts
5902
- import { ESLintUtils as ESLintUtils36 } from "@typescript-eslint/utils";
6162
+ import { ESLintUtils as ESLintUtils40 } from "@typescript-eslint/utils";
5903
6163
  var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
5904
6164
  var CONFLICT_HANDLED = /\bON\s+CONFLICT\b|\bON\s+DUPLICATE\s+KEY\b|\bINSERT\s+OR\s+(?:IGNORE|REPLACE)\b/i;
5905
6165
  var INSERT_GATE = /insert/i;
5906
- var store_insert_requires_on_conflict_default = ESLintUtils36.RuleCreator(
6166
+ var store_insert_requires_on_conflict_default = ESLintUtils40.RuleCreator(
5907
6167
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5908
6168
  )({
5909
6169
  name: "store-insert-requires-on-conflict",
@@ -5932,17 +6192,17 @@ var store_insert_requires_on_conflict_default = ESLintUtils36.RuleCreator(
5932
6192
  });
5933
6193
 
5934
6194
  // src/rules/no-dynamic-sql.ts
5935
- import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils37 } from "@typescript-eslint/utils";
6195
+ import { AST_NODE_TYPES as AST_NODE_TYPES29, ESLintUtils as ESLintUtils41 } from "@typescript-eslint/utils";
5936
6196
  var DEFAULT_METHODS = ["prepare", "exec", "query"];
5937
6197
  var CONSTANT_CASE_RE = /^[A-Z][A-Z0-9_]*$/;
5938
6198
  function isStaticFragment(expression) {
5939
- if (expression.type === AST_NODE_TYPES26.Identifier) {
6199
+ if (expression.type === AST_NODE_TYPES29.Identifier) {
5940
6200
  return CONSTANT_CASE_RE.test(expression.name);
5941
6201
  }
5942
- if (expression.type === AST_NODE_TYPES26.MemberExpression && !expression.computed && expression.property.type === AST_NODE_TYPES26.Identifier) {
6202
+ if (expression.type === AST_NODE_TYPES29.MemberExpression && !expression.computed && expression.property.type === AST_NODE_TYPES29.Identifier) {
5943
6203
  return CONSTANT_CASE_RE.test(expression.property.name);
5944
6204
  }
5945
- if (expression.type === AST_NODE_TYPES26.Literal) {
6205
+ if (expression.type === AST_NODE_TYPES29.Literal) {
5946
6206
  return typeof expression.value === "string";
5947
6207
  }
5948
6208
  return false;
@@ -5953,36 +6213,36 @@ function runtimeInterpolations(template) {
5953
6213
  );
5954
6214
  }
5955
6215
  function concatOperands(node) {
5956
- if (node.type === AST_NODE_TYPES26.BinaryExpression && node.operator === "+") {
6216
+ if (node.type === AST_NODE_TYPES29.BinaryExpression && node.operator === "+") {
5957
6217
  return [...concatOperands(node.left), ...concatOperands(node.right)];
5958
6218
  }
5959
6219
  return [node];
5960
6220
  }
5961
6221
  function runtimeConcatOperands(node) {
5962
- if (node.type !== AST_NODE_TYPES26.BinaryExpression || node.operator !== "+") {
6222
+ if (node.type !== AST_NODE_TYPES29.BinaryExpression || node.operator !== "+") {
5963
6223
  return [];
5964
6224
  }
5965
6225
  const operands = concatOperands(node);
5966
6226
  const hasStringLiteral = operands.some(
5967
- (operand) => operand.type === AST_NODE_TYPES26.Literal && typeof operand.value === "string"
6227
+ (operand) => operand.type === AST_NODE_TYPES29.Literal && typeof operand.value === "string"
5968
6228
  );
5969
6229
  if (!hasStringLiteral) {
5970
6230
  return [];
5971
6231
  }
5972
6232
  return operands.filter(
5973
- (operand) => operand.type !== AST_NODE_TYPES26.Literal && !isStaticFragment(operand)
6233
+ (operand) => operand.type !== AST_NODE_TYPES29.Literal && !isStaticFragment(operand)
5974
6234
  );
5975
6235
  }
5976
6236
  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;
5977
6237
  var RUNTIME_MARKER = " ? ";
5978
6238
  function staticStatementText(node) {
5979
- if (node.type === AST_NODE_TYPES26.TemplateLiteral) {
6239
+ if (node.type === AST_NODE_TYPES29.TemplateLiteral) {
5980
6240
  return node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join(RUNTIME_MARKER);
5981
6241
  }
5982
- if (node.type === AST_NODE_TYPES26.Literal) {
6242
+ if (node.type === AST_NODE_TYPES29.Literal) {
5983
6243
  return typeof node.value === "string" ? node.value : RUNTIME_MARKER;
5984
6244
  }
5985
- if (node.type === AST_NODE_TYPES26.BinaryExpression && node.operator === "+") {
6245
+ if (node.type === AST_NODE_TYPES29.BinaryExpression && node.operator === "+") {
5986
6246
  return staticStatementText(node.left) + staticStatementText(node.right);
5987
6247
  }
5988
6248
  return RUNTIME_MARKER;
@@ -5992,13 +6252,13 @@ function looksLikeSql(node) {
5992
6252
  }
5993
6253
  function statementMethodName(node, methods) {
5994
6254
  const callee = node.callee;
5995
- if (callee.type !== AST_NODE_TYPES26.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES26.Identifier) {
6255
+ if (callee.type !== AST_NODE_TYPES29.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES29.Identifier) {
5996
6256
  return null;
5997
6257
  }
5998
6258
  const name = callee.property.name;
5999
6259
  return methods.has(name) ? name : null;
6000
6260
  }
6001
- var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6261
+ var no_dynamic_sql_default = ESLintUtils41.RuleCreator(
6002
6262
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6003
6263
  )({
6004
6264
  name: "no-dynamic-sql",
@@ -6037,7 +6297,7 @@ var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6037
6297
  if (statement === void 0 || !looksLikeSql(statement)) {
6038
6298
  return;
6039
6299
  }
6040
- const offenders = statement.type === AST_NODE_TYPES26.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6300
+ const offenders = statement.type === AST_NODE_TYPES29.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6041
6301
  for (const offender of offenders) {
6042
6302
  context.report({
6043
6303
  node: offender,
@@ -6051,7 +6311,7 @@ var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6051
6311
  });
6052
6312
 
6053
6313
  // src/rules/no-raw-fetch-outside-clients.ts
6054
- import { ESLintUtils as ESLintUtils38 } from "@typescript-eslint/utils";
6314
+ import { ESLintUtils as ESLintUtils42 } from "@typescript-eslint/utils";
6055
6315
  var DEFAULT_ALLOW = [
6056
6316
  "[\\\\/]clients?[\\\\/]",
6057
6317
  "-client\\.[cm]?[jt]sx?$",
@@ -6115,7 +6375,7 @@ function compile(patterns) {
6115
6375
  }
6116
6376
  return compiled;
6117
6377
  }
6118
- var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
6378
+ var no_raw_fetch_outside_clients_default = ESLintUtils42.RuleCreator(
6119
6379
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6120
6380
  )({
6121
6381
  name: "no-raw-fetch-outside-clients",
@@ -6163,7 +6423,7 @@ var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
6163
6423
  });
6164
6424
 
6165
6425
  // src/rules/no-storage-in-stateless-modules.ts
6166
- import { AST_NODE_TYPES as AST_NODE_TYPES27, ESLintUtils as ESLintUtils39 } from "@typescript-eslint/utils";
6426
+ import { AST_NODE_TYPES as AST_NODE_TYPES30, ESLintUtils as ESLintUtils43 } from "@typescript-eslint/utils";
6167
6427
  var DEFAULT_METHODS2 = [
6168
6428
  "prepare",
6169
6429
  "put",
@@ -6182,7 +6442,7 @@ function compile2(patterns) {
6182
6442
  }
6183
6443
  function storageMethodName(node, methods) {
6184
6444
  const callee = node.callee;
6185
- if (callee.type !== AST_NODE_TYPES27.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES27.Identifier) {
6445
+ if (callee.type !== AST_NODE_TYPES30.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES30.Identifier) {
6186
6446
  return null;
6187
6447
  }
6188
6448
  const name = callee.property.name;
@@ -6194,7 +6454,7 @@ function storageMethodName(node, methods) {
6194
6454
  }
6195
6455
  return name;
6196
6456
  }
6197
- var no_storage_in_stateless_modules_default = ESLintUtils39.RuleCreator(
6457
+ var no_storage_in_stateless_modules_default = ESLintUtils43.RuleCreator(
6198
6458
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6199
6459
  )({
6200
6460
  name: "no-storage-in-stateless-modules",
@@ -6253,8 +6513,8 @@ var no_storage_in_stateless_modules_default = ESLintUtils39.RuleCreator(
6253
6513
 
6254
6514
  // src/rules/no-zod-native-enum.ts
6255
6515
  import {
6256
- ESLintUtils as ESLintUtils40,
6257
- AST_NODE_TYPES as AST_NODE_TYPES28
6516
+ ESLintUtils as ESLintUtils44,
6517
+ AST_NODE_TYPES as AST_NODE_TYPES31
6258
6518
  } from "@typescript-eslint/utils";
6259
6519
  import * as ts2 from "typescript";
6260
6520
  var IGNORE_PATTERNS2 = [
@@ -6269,11 +6529,11 @@ function isIgnoredFile2(filename, sourceText) {
6269
6529
  }
6270
6530
  return /@generated\b/.test(sourceText.slice(0, 1024));
6271
6531
  }
6272
- function isZodModule(source) {
6532
+ function isZodModule2(source) {
6273
6533
  return /(^|[/@-])zod([/-]|$)/.test(source);
6274
6534
  }
6275
6535
  function unwrap3(node) {
6276
- if (node.type === AST_NODE_TYPES28.TSAsExpression || node.type === AST_NODE_TYPES28.TSSatisfiesExpression) {
6536
+ if (node.type === AST_NODE_TYPES31.TSAsExpression || node.type === AST_NODE_TYPES31.TSSatisfiesExpression) {
6277
6537
  return unwrap3(node.expression);
6278
6538
  }
6279
6539
  return node;
@@ -6281,14 +6541,14 @@ function unwrap3(node) {
6281
6541
  function stringValueTexts(node, sourceCode) {
6282
6542
  const texts = [];
6283
6543
  for (const prop of node.properties) {
6284
- if (prop.type !== AST_NODE_TYPES28.Property) {
6544
+ if (prop.type !== AST_NODE_TYPES31.Property) {
6285
6545
  return null;
6286
6546
  }
6287
6547
  if (prop.computed || prop.shorthand || prop.method || prop.kind !== "init") {
6288
6548
  return null;
6289
6549
  }
6290
6550
  const value = prop.value;
6291
- if (value.type !== AST_NODE_TYPES28.Literal || typeof value.value !== "string") {
6551
+ if (value.type !== AST_NODE_TYPES31.Literal || typeof value.value !== "string") {
6292
6552
  return null;
6293
6553
  }
6294
6554
  const text = sourceCode.getText(value);
@@ -6304,7 +6564,7 @@ function resolvesToLocalEnum(node, scope) {
6304
6564
  const variable = current.variables.find((v) => v.name === node.name);
6305
6565
  if (variable !== void 0) {
6306
6566
  return variable.defs.some(
6307
- (def) => def.node.type === AST_NODE_TYPES28.TSEnumDeclaration
6567
+ (def) => def.node.type === AST_NODE_TYPES31.TSEnumDeclaration
6308
6568
  );
6309
6569
  }
6310
6570
  current = current.upper;
@@ -6324,7 +6584,7 @@ function resolvesToImportedEnum(node, services) {
6324
6584
  }
6325
6585
  return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
6326
6586
  }
6327
- var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6587
+ var no_zod_native_enum_default = ESLintUtils44.RuleCreator(
6328
6588
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6329
6589
  )({
6330
6590
  name: "no-zod-native-enum",
@@ -6351,32 +6611,32 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6351
6611
  }
6352
6612
  let services;
6353
6613
  try {
6354
- services = ESLintUtils40.getParserServices(context);
6614
+ services = ESLintUtils44.getParserServices(context);
6355
6615
  } catch {
6356
6616
  services = null;
6357
6617
  }
6358
6618
  const zodImportedNames = /* @__PURE__ */ new Map();
6359
6619
  function isZodMemberCall(node, api) {
6360
6620
  const callee = node.callee;
6361
- if (callee.type === AST_NODE_TYPES28.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES28.Identifier) {
6621
+ if (callee.type === AST_NODE_TYPES31.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES31.Identifier) {
6362
6622
  return callee.property.name === api;
6363
6623
  }
6364
- if (callee.type === AST_NODE_TYPES28.Identifier) {
6624
+ if (callee.type === AST_NODE_TYPES31.Identifier) {
6365
6625
  return zodImportedNames.get(callee.name) === api;
6366
6626
  }
6367
6627
  return false;
6368
6628
  }
6369
6629
  function buildFix(node) {
6370
6630
  const callee = node.callee;
6371
- if (callee.type !== AST_NODE_TYPES28.MemberExpression || callee.property.type !== AST_NODE_TYPES28.Identifier) {
6631
+ if (callee.type !== AST_NODE_TYPES31.MemberExpression || callee.property.type !== AST_NODE_TYPES31.Identifier) {
6372
6632
  return null;
6373
6633
  }
6374
6634
  const arg = node.arguments[0];
6375
- if (arg === void 0 || node.arguments.length !== 1 || arg.type === AST_NODE_TYPES28.SpreadElement) {
6635
+ if (arg === void 0 || node.arguments.length !== 1 || arg.type === AST_NODE_TYPES31.SpreadElement) {
6376
6636
  return null;
6377
6637
  }
6378
6638
  const inner = unwrap3(arg);
6379
- if (inner.type !== AST_NODE_TYPES28.ObjectExpression) {
6639
+ if (inner.type !== AST_NODE_TYPES31.ObjectExpression) {
6380
6640
  return null;
6381
6641
  }
6382
6642
  const values = stringValueTexts(inner, sourceCode);
@@ -6392,11 +6652,11 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6392
6652
  }
6393
6653
  return {
6394
6654
  ImportDeclaration(node) {
6395
- if (!isZodModule(node.source.value)) {
6655
+ if (!isZodModule2(node.source.value)) {
6396
6656
  return;
6397
6657
  }
6398
6658
  for (const spec of node.specifiers) {
6399
- if (spec.type === AST_NODE_TYPES28.ImportSpecifier && spec.imported.type === AST_NODE_TYPES28.Identifier) {
6659
+ if (spec.type === AST_NODE_TYPES31.ImportSpecifier && spec.imported.type === AST_NODE_TYPES31.Identifier) {
6400
6660
  zodImportedNames.set(spec.local.name, spec.imported.name);
6401
6661
  }
6402
6662
  }
@@ -6415,7 +6675,7 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6415
6675
  return;
6416
6676
  }
6417
6677
  const arg = node.arguments[0];
6418
- if (arg === void 0 || arg.type !== AST_NODE_TYPES28.Identifier) {
6678
+ if (arg === void 0 || arg.type !== AST_NODE_TYPES31.Identifier) {
6419
6679
  return;
6420
6680
  }
6421
6681
  const isEnum = resolvesToLocalEnum(arg, sourceCode.getScope(arg)) || services !== null && resolvesToImportedEnum(arg, services);
@@ -6433,8 +6693,8 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6433
6693
 
6434
6694
  // src/rules/prefer-module-level-constant.ts
6435
6695
  import {
6436
- ESLintUtils as ESLintUtils41,
6437
- AST_NODE_TYPES as AST_NODE_TYPES29
6696
+ ESLintUtils as ESLintUtils45,
6697
+ AST_NODE_TYPES as AST_NODE_TYPES32
6438
6698
  } from "@typescript-eslint/utils";
6439
6699
  var DEFAULT_MIN_ELEMENTS = 3;
6440
6700
  var MAX_LITERAL_DEPTH = 4;
@@ -6470,10 +6730,10 @@ var MUTATING_METHODS = /* @__PURE__ */ new Set([
6470
6730
  // Object-ish escape hatches
6471
6731
  "assign"
6472
6732
  ]);
6473
- var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
6474
- AST_NODE_TYPES29.FunctionDeclaration,
6475
- AST_NODE_TYPES29.FunctionExpression,
6476
- AST_NODE_TYPES29.ArrowFunctionExpression
6733
+ var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6734
+ AST_NODE_TYPES32.FunctionDeclaration,
6735
+ AST_NODE_TYPES32.FunctionExpression,
6736
+ AST_NODE_TYPES32.ArrowFunctionExpression
6477
6737
  ]);
6478
6738
  var COLLECTION_CONSTRUCTORS = /* @__PURE__ */ new Set(["Set", "Map"]);
6479
6739
  function isIgnoredFile3(filename, sourceText) {
@@ -6486,13 +6746,13 @@ function isTestFile2(filename) {
6486
6746
  return TEST_FILE_PATTERNS.some((re) => re.test(filename));
6487
6747
  }
6488
6748
  function unwrap4(node) {
6489
- if (node.type === AST_NODE_TYPES29.TSAsExpression || node.type === AST_NODE_TYPES29.TSSatisfiesExpression || node.type === AST_NODE_TYPES29.TSNonNullExpression) {
6749
+ if (node.type === AST_NODE_TYPES32.TSAsExpression || node.type === AST_NODE_TYPES32.TSSatisfiesExpression || node.type === AST_NODE_TYPES32.TSNonNullExpression) {
6490
6750
  return unwrap4(node.expression);
6491
6751
  }
6492
6752
  return node;
6493
6753
  }
6494
6754
  function isRegexLiteral(node) {
6495
- return node.type === AST_NODE_TYPES29.Literal && "regex" in node && node.regex !== void 0;
6755
+ return node.type === AST_NODE_TYPES32.Literal && "regex" in node && node.regex !== void 0;
6496
6756
  }
6497
6757
  function isLiteralOnly(node, depth) {
6498
6758
  if (depth > MAX_LITERAL_DEPTH) {
@@ -6500,29 +6760,29 @@ function isLiteralOnly(node, depth) {
6500
6760
  }
6501
6761
  const inner = unwrap4(node);
6502
6762
  switch (inner.type) {
6503
- case AST_NODE_TYPES29.Literal: {
6763
+ case AST_NODE_TYPES32.Literal: {
6504
6764
  return true;
6505
6765
  }
6506
- case AST_NODE_TYPES29.TemplateLiteral: {
6766
+ case AST_NODE_TYPES32.TemplateLiteral: {
6507
6767
  return inner.expressions.length === 0;
6508
6768
  }
6509
- case AST_NODE_TYPES29.UnaryExpression: {
6510
- return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === AST_NODE_TYPES29.Literal && typeof inner.argument.value === "number";
6769
+ case AST_NODE_TYPES32.UnaryExpression: {
6770
+ return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === AST_NODE_TYPES32.Literal && typeof inner.argument.value === "number";
6511
6771
  }
6512
- case AST_NODE_TYPES29.ArrayExpression: {
6772
+ case AST_NODE_TYPES32.ArrayExpression: {
6513
6773
  return inner.elements.every(
6514
- (el) => el !== null && el.type !== AST_NODE_TYPES29.SpreadElement && isLiteralOnly(el, depth + 1)
6774
+ (el) => el !== null && el.type !== AST_NODE_TYPES32.SpreadElement && isLiteralOnly(el, depth + 1)
6515
6775
  );
6516
6776
  }
6517
- case AST_NODE_TYPES29.ObjectExpression: {
6777
+ case AST_NODE_TYPES32.ObjectExpression: {
6518
6778
  return inner.properties.every((prop) => {
6519
- if (prop.type !== AST_NODE_TYPES29.Property) {
6779
+ if (prop.type !== AST_NODE_TYPES32.Property) {
6520
6780
  return false;
6521
6781
  }
6522
6782
  if (prop.shorthand || prop.method || prop.kind !== "init") {
6523
6783
  return false;
6524
6784
  }
6525
- if (prop.computed && prop.key.type !== AST_NODE_TYPES29.Literal) {
6785
+ if (prop.computed && prop.key.type !== AST_NODE_TYPES32.Literal) {
6526
6786
  return false;
6527
6787
  }
6528
6788
  return isLiteralOnly(prop.value, depth + 1);
@@ -6535,7 +6795,7 @@ function isLiteralOnly(node, depth) {
6535
6795
  }
6536
6796
  function unwrapObjectFreeze(node) {
6537
6797
  const inner = unwrap4(node);
6538
- 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) {
6798
+ if (inner.type === AST_NODE_TYPES32.CallExpression && inner.callee.type === AST_NODE_TYPES32.MemberExpression && !inner.callee.computed && inner.callee.object.type === AST_NODE_TYPES32.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === AST_NODE_TYPES32.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== AST_NODE_TYPES32.SpreadElement) {
6539
6799
  return unwrap4(inner.arguments[0]);
6540
6800
  }
6541
6801
  return inner;
@@ -6551,19 +6811,19 @@ function classify(init, checkRegex) {
6551
6811
  }
6552
6812
  return { kind: "regex", size: 1 };
6553
6813
  }
6554
- if (node.type === AST_NODE_TYPES29.ArrayExpression) {
6814
+ if (node.type === AST_NODE_TYPES32.ArrayExpression) {
6555
6815
  return isLiteralOnly(node, 0) ? { kind: "array", size: node.elements.length } : null;
6556
6816
  }
6557
- if (node.type === AST_NODE_TYPES29.ObjectExpression) {
6817
+ if (node.type === AST_NODE_TYPES32.ObjectExpression) {
6558
6818
  return isLiteralOnly(node, 0) ? { kind: "object", size: node.properties.length } : null;
6559
6819
  }
6560
- if (node.type === AST_NODE_TYPES29.NewExpression && node.callee.type === AST_NODE_TYPES29.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6820
+ if (node.type === AST_NODE_TYPES32.NewExpression && node.callee.type === AST_NODE_TYPES32.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6561
6821
  const arg = node.arguments[0];
6562
- if (node.arguments.length !== 1 || arg === void 0 || arg.type === AST_NODE_TYPES29.SpreadElement) {
6822
+ if (node.arguments.length !== 1 || arg === void 0 || arg.type === AST_NODE_TYPES32.SpreadElement) {
6563
6823
  return null;
6564
6824
  }
6565
6825
  const entries = unwrap4(arg);
6566
- if (entries.type !== AST_NODE_TYPES29.ArrayExpression) {
6826
+ if (entries.type !== AST_NODE_TYPES32.ArrayExpression) {
6567
6827
  return null;
6568
6828
  }
6569
6829
  return isLiteralOnly(entries, 0) ? { kind: node.callee.name === "Set" ? "Set" : "Map", size: entries.elements.length } : null;
@@ -6573,7 +6833,7 @@ function classify(init, checkRegex) {
6573
6833
  function enclosingFunction2(node) {
6574
6834
  let current = node.parent;
6575
6835
  while (current !== void 0 && current !== null) {
6576
- if (FUNCTION_TYPES3.has(current.type)) {
6836
+ if (FUNCTION_TYPES4.has(current.type)) {
6577
6837
  return current;
6578
6838
  }
6579
6839
  current = current.parent;
@@ -6592,10 +6852,10 @@ var NON_RETAINING_BUILTINS = /* @__PURE__ */ new Map(
6592
6852
  );
6593
6853
  function isNonRetainingBuiltinCall(node, argument) {
6594
6854
  const callee = node.callee;
6595
- if (callee.type === AST_NODE_TYPES29.Identifier && callee.name === "structuredClone") {
6855
+ if (callee.type === AST_NODE_TYPES32.Identifier && callee.name === "structuredClone") {
6596
6856
  return true;
6597
6857
  }
6598
- if (callee.type !== AST_NODE_TYPES29.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES29.Identifier || callee.property.type !== AST_NODE_TYPES29.Identifier) {
6858
+ if (callee.type !== AST_NODE_TYPES32.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES32.Identifier || callee.property.type !== AST_NODE_TYPES32.Identifier) {
6599
6859
  return false;
6600
6860
  }
6601
6861
  const members = NON_RETAINING_BUILTINS.get(callee.object.name);
@@ -6609,43 +6869,43 @@ function isNonRetainingBuiltinCall(node, argument) {
6609
6869
  }
6610
6870
  function isSafeRead(identifier) {
6611
6871
  const parent = identifier.parent;
6612
- if (parent.type === AST_NODE_TYPES29.MemberExpression) {
6872
+ if (parent.type === AST_NODE_TYPES32.MemberExpression) {
6613
6873
  if (parent.object !== identifier) {
6614
6874
  return true;
6615
6875
  }
6616
6876
  const grandparent = parent.parent;
6617
- if (grandparent.type === AST_NODE_TYPES29.AssignmentExpression && grandparent.left === parent) {
6877
+ if (grandparent.type === AST_NODE_TYPES32.AssignmentExpression && grandparent.left === parent) {
6618
6878
  return false;
6619
6879
  }
6620
- if (grandparent.type === AST_NODE_TYPES29.UpdateExpression) {
6880
+ if (grandparent.type === AST_NODE_TYPES32.UpdateExpression) {
6621
6881
  return false;
6622
6882
  }
6623
- if (grandparent.type === AST_NODE_TYPES29.UnaryExpression && grandparent.operator === "delete") {
6883
+ if (grandparent.type === AST_NODE_TYPES32.UnaryExpression && grandparent.operator === "delete") {
6624
6884
  return false;
6625
6885
  }
6626
- 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) {
6886
+ if (!parent.computed && parent.property.type === AST_NODE_TYPES32.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === AST_NODE_TYPES32.CallExpression && grandparent.callee === parent) {
6627
6887
  return false;
6628
6888
  }
6629
6889
  return true;
6630
6890
  }
6631
- if (parent.type === AST_NODE_TYPES29.ForOfStatement && parent.right === identifier) {
6891
+ if (parent.type === AST_NODE_TYPES32.ForOfStatement && parent.right === identifier) {
6632
6892
  return true;
6633
6893
  }
6634
- if (parent.type === AST_NODE_TYPES29.SpreadElement) {
6894
+ if (parent.type === AST_NODE_TYPES32.SpreadElement) {
6635
6895
  return true;
6636
6896
  }
6637
- if (parent.type === AST_NODE_TYPES29.BinaryExpression) {
6897
+ if (parent.type === AST_NODE_TYPES32.BinaryExpression) {
6638
6898
  return true;
6639
6899
  }
6640
- if (parent.type === AST_NODE_TYPES29.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6900
+ if (parent.type === AST_NODE_TYPES32.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6641
6901
  return true;
6642
6902
  }
6643
- if (parent.type === AST_NODE_TYPES29.UnaryExpression && parent.operator !== "delete") {
6903
+ if (parent.type === AST_NODE_TYPES32.UnaryExpression && parent.operator !== "delete") {
6644
6904
  return true;
6645
6905
  }
6646
6906
  return false;
6647
6907
  }
6648
- var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6908
+ var prefer_module_level_constant_default = ESLintUtils45.RuleCreator(
6649
6909
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6650
6910
  )({
6651
6911
  name: "prefer-module-level-constant",
@@ -6697,7 +6957,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6697
6957
  if (reference.isWrite()) {
6698
6958
  return false;
6699
6959
  }
6700
- if (reference.identifier.type !== AST_NODE_TYPES29.Identifier) {
6960
+ if (reference.identifier.type !== AST_NODE_TYPES32.Identifier) {
6701
6961
  return false;
6702
6962
  }
6703
6963
  if (!isSafeRead(reference.identifier)) {
@@ -6709,10 +6969,10 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6709
6969
  return {
6710
6970
  VariableDeclarator(node) {
6711
6971
  const declaration = node.parent;
6712
- if (declaration.type !== AST_NODE_TYPES29.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6972
+ if (declaration.type !== AST_NODE_TYPES32.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6713
6973
  return;
6714
6974
  }
6715
- if (node.id.type !== AST_NODE_TYPES29.Identifier || node.init === null) {
6975
+ if (node.id.type !== AST_NODE_TYPES32.Identifier || node.init === null) {
6716
6976
  return;
6717
6977
  }
6718
6978
  if (enclosingFunction2(node) === null) {
@@ -6739,7 +6999,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6739
6999
  });
6740
7000
 
6741
7001
  // src/rules/jsdoc-restates-signature.ts
6742
- import { AST_NODE_TYPES as AST_NODE_TYPES30, ESLintUtils as ESLintUtils42 } from "@typescript-eslint/utils";
7002
+ import { AST_NODE_TYPES as AST_NODE_TYPES33, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
6743
7003
  var VALUE_TAGS = /* @__PURE__ */ new Set([
6744
7004
  "alpha",
6745
7005
  "author",
@@ -6822,30 +7082,30 @@ function declarationNames(node) {
6822
7082
  switch (node.type) {
6823
7083
  // `export function f()` — the JSDoc sits above the `export`, so the token
6824
7084
  // after it resolves to the wrapper, not to the thing being documented.
6825
- case AST_NODE_TYPES30.ExportNamedDeclaration:
6826
- case AST_NODE_TYPES30.ExportDefaultDeclaration:
7085
+ case AST_NODE_TYPES33.ExportNamedDeclaration:
7086
+ case AST_NODE_TYPES33.ExportDefaultDeclaration:
6827
7087
  return node.declaration == null ? null : declarationNames(node.declaration);
6828
- case AST_NODE_TYPES30.FunctionDeclaration:
6829
- case AST_NODE_TYPES30.TSDeclareFunction:
7088
+ case AST_NODE_TYPES33.FunctionDeclaration:
7089
+ case AST_NODE_TYPES33.TSDeclareFunction:
6830
7090
  return node.id === null ? null : { name: node.id.name, params: paramNames(node.params) };
6831
- case AST_NODE_TYPES30.ClassDeclaration:
6832
- case AST_NODE_TYPES30.TSInterfaceDeclaration:
6833
- case AST_NODE_TYPES30.TSTypeAliasDeclaration:
6834
- case AST_NODE_TYPES30.TSEnumDeclaration:
7091
+ case AST_NODE_TYPES33.ClassDeclaration:
7092
+ case AST_NODE_TYPES33.TSInterfaceDeclaration:
7093
+ case AST_NODE_TYPES33.TSTypeAliasDeclaration:
7094
+ case AST_NODE_TYPES33.TSEnumDeclaration:
6835
7095
  return node.id === null ? null : { name: node.id.name, params: [] };
6836
- case AST_NODE_TYPES30.VariableDeclaration: {
7096
+ case AST_NODE_TYPES33.VariableDeclaration: {
6837
7097
  const declarator = node.declarations[0];
6838
- if (declarator === void 0 || declarator.id.type !== AST_NODE_TYPES30.Identifier) return null;
7098
+ if (declarator === void 0 || declarator.id.type !== AST_NODE_TYPES33.Identifier) return null;
6839
7099
  const init = declarator.init;
6840
- const params = init != null && (init.type === AST_NODE_TYPES30.ArrowFunctionExpression || init.type === AST_NODE_TYPES30.FunctionExpression) ? paramNames(init.params) : [];
7100
+ const params = init != null && (init.type === AST_NODE_TYPES33.ArrowFunctionExpression || init.type === AST_NODE_TYPES33.FunctionExpression) ? paramNames(init.params) : [];
6841
7101
  return { name: declarator.id.name, params };
6842
7102
  }
6843
- case AST_NODE_TYPES30.MethodDefinition:
6844
- case AST_NODE_TYPES30.PropertyDefinition:
6845
- case AST_NODE_TYPES30.TSMethodSignature:
6846
- case AST_NODE_TYPES30.TSPropertySignature: {
6847
- if (node.key.type !== AST_NODE_TYPES30.Identifier) return null;
6848
- const params = node.type === AST_NODE_TYPES30.MethodDefinition ? paramNames(node.value.params) : node.type === AST_NODE_TYPES30.TSMethodSignature ? paramNames(node.params) : [];
7103
+ case AST_NODE_TYPES33.MethodDefinition:
7104
+ case AST_NODE_TYPES33.PropertyDefinition:
7105
+ case AST_NODE_TYPES33.TSMethodSignature:
7106
+ case AST_NODE_TYPES33.TSPropertySignature: {
7107
+ if (node.key.type !== AST_NODE_TYPES33.Identifier) return null;
7108
+ const params = node.type === AST_NODE_TYPES33.MethodDefinition ? paramNames(node.value.params) : node.type === AST_NODE_TYPES33.TSMethodSignature ? paramNames(node.params) : [];
6849
7109
  return { name: node.key.name, params };
6850
7110
  }
6851
7111
  default:
@@ -6855,9 +7115,9 @@ function declarationNames(node) {
6855
7115
  function paramNames(params) {
6856
7116
  const names = [];
6857
7117
  for (const param of params) {
6858
- const target = param.type === AST_NODE_TYPES30.AssignmentPattern ? param.left : param;
6859
- if (target.type === AST_NODE_TYPES30.Identifier) names.push(target.name);
6860
- else if (target.type === AST_NODE_TYPES30.TSParameterProperty) continue;
7118
+ const target = param.type === AST_NODE_TYPES33.AssignmentPattern ? param.left : param;
7119
+ if (target.type === AST_NODE_TYPES33.Identifier) names.push(target.name);
7120
+ else if (target.type === AST_NODE_TYPES33.TSParameterProperty) continue;
6861
7121
  }
6862
7122
  return names;
6863
7123
  }
@@ -6866,7 +7126,7 @@ function tokensOf(names) {
6866
7126
  for (const name of names) for (const part of splitIdentifier(name)) tokens.add(part);
6867
7127
  return tokens;
6868
7128
  }
6869
- var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
7129
+ var jsdoc_restates_signature_default = ESLintUtils46.RuleCreator(
6870
7130
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6871
7131
  )({
6872
7132
  name: "jsdoc-restates-signature",
@@ -6902,7 +7162,7 @@ var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
6902
7162
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) continue;
6903
7163
  let node = sourceCode.getNodeByRangeIndex(token.range[0]);
6904
7164
  let declaration = null;
6905
- while (node != null && node.type !== AST_NODE_TYPES30.Program) {
7165
+ while (node != null && node.type !== AST_NODE_TYPES33.Program) {
6906
7166
  declaration = declarationNames(node);
6907
7167
  if (declaration !== null) break;
6908
7168
  node = node.parent ?? null;
@@ -6957,7 +7217,7 @@ var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
6957
7217
  });
6958
7218
 
6959
7219
  // src/rules/no-restated-comment.ts
6960
- import { AST_NODE_TYPES as AST_NODE_TYPES31, ESLintUtils as ESLintUtils43 } from "@typescript-eslint/utils";
7220
+ import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
6961
7221
  var MAX_WORDS = 8;
6962
7222
  var MIN_CONTENT_TOKENS = 2;
6963
7223
  var DIRECTIVE_RE3 = /^(eslint\b|eslint-|sarj-noqa\b|@ts-|prettier-ignore|prettier\b|biome-|c8\b|v8\b|istanbul\b|@type\b|@vite|webpack|<reference|<amd|global\b|noinspection|todo\b|fixme\b|hack\b|xxx\b)/i;
@@ -6981,7 +7241,7 @@ function headsSiblingRun(node) {
6981
7241
  const next = index >= 0 ? body[index + 1] : void 0;
6982
7242
  return next !== void 0 && next.type === node.type;
6983
7243
  }
6984
- var no_restated_comment_default = ESLintUtils43.RuleCreator(
7244
+ var no_restated_comment_default = ESLintUtils47.RuleCreator(
6985
7245
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6986
7246
  )({
6987
7247
  name: "no-restated-comment",
@@ -7009,7 +7269,7 @@ var no_restated_comment_default = ESLintUtils43.RuleCreator(
7009
7269
  function labelsASiblingRun(comment) {
7010
7270
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
7011
7271
  if (token === null) return false;
7012
- for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES31.Program; node = node.parent) {
7272
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES34.Program; node = node.parent) {
7013
7273
  if (headsSiblingRun(node)) return true;
7014
7274
  }
7015
7275
  return false;
@@ -7049,7 +7309,7 @@ var no_restated_comment_default = ESLintUtils43.RuleCreator(
7049
7309
  });
7050
7310
 
7051
7311
  // src/rules/trailing-value-narration.ts
7052
- import { ESLintUtils as ESLintUtils44 } from "@typescript-eslint/utils";
7312
+ import { ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
7053
7313
  var NUMBER_RE = /(?<![\w.])(\d+(?:\.\d+)?)(?![\w.])/g;
7054
7314
  var WORD_RE3 = /[A-Za-z]+(?:'[a-z]+)?|\d+(?:\.\d+)?/g;
7055
7315
  var UNIT_WORDS = /* @__PURE__ */ new Set([
@@ -7133,7 +7393,7 @@ function narratesValue(body, code) {
7133
7393
  (word) => STOPWORDS3.has(word) || UNIT_WORDS.has(word) || commentNumbers.has(word) || identifiers.has(word) || stems.has(stem(word))
7134
7394
  );
7135
7395
  }
7136
- var trailing_value_narration_default = ESLintUtils44.RuleCreator(
7396
+ var trailing_value_narration_default = ESLintUtils48.RuleCreator(
7137
7397
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7138
7398
  )({
7139
7399
  name: "trailing-value-narration",
@@ -7174,7 +7434,7 @@ var trailing_value_narration_default = ESLintUtils44.RuleCreator(
7174
7434
  });
7175
7435
 
7176
7436
  // src/rules/no-tautological-expect.ts
7177
- import { AST_NODE_TYPES as AST_NODE_TYPES32, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
7437
+ import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
7178
7438
  var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
7179
7439
  var ZERO_ARG_MATCHERS = /* @__PURE__ */ new Set([
7180
7440
  "toBeDefined",
@@ -7188,17 +7448,17 @@ var OPERAND_PREVIEW_CHARS = 40;
7188
7448
  var NUMERIC_SIGNS = /* @__PURE__ */ new Set(["-", "+"]);
7189
7449
  function isLiteral(node) {
7190
7450
  switch (node.type) {
7191
- case AST_NODE_TYPES32.Literal:
7451
+ case AST_NODE_TYPES35.Literal:
7192
7452
  return true;
7193
- case AST_NODE_TYPES32.TemplateLiteral:
7453
+ case AST_NODE_TYPES35.TemplateLiteral:
7194
7454
  return node.expressions.length === 0;
7195
- case AST_NODE_TYPES32.UnaryExpression:
7455
+ case AST_NODE_TYPES35.UnaryExpression:
7196
7456
  return NUMERIC_SIGNS.has(node.operator) && isLiteral(node.argument);
7197
- case AST_NODE_TYPES32.ArrayExpression:
7457
+ case AST_NODE_TYPES35.ArrayExpression:
7198
7458
  return node.elements.every((element) => element !== null && isLiteral(element));
7199
- case AST_NODE_TYPES32.ObjectExpression:
7459
+ case AST_NODE_TYPES35.ObjectExpression:
7200
7460
  return node.properties.every(
7201
- (property) => property.type === AST_NODE_TYPES32.Property && !property.computed && isLiteral(property.value)
7461
+ (property) => property.type === AST_NODE_TYPES35.Property && !property.computed && isLiteral(property.value)
7202
7462
  );
7203
7463
  default:
7204
7464
  return false;
@@ -7206,12 +7466,12 @@ function isLiteral(node) {
7206
7466
  }
7207
7467
  function expectOperand(callee) {
7208
7468
  const receiver = callee.object;
7209
- if (receiver.type !== AST_NODE_TYPES32.CallExpression || receiver.callee.type !== AST_NODE_TYPES32.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7469
+ if (receiver.type !== AST_NODE_TYPES35.CallExpression || receiver.callee.type !== AST_NODE_TYPES35.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7210
7470
  return null;
7211
7471
  }
7212
7472
  return receiver.arguments[0] ?? null;
7213
7473
  }
7214
- var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7474
+ var no_tautological_expect_default = ESLintUtils49.RuleCreator(
7215
7475
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7216
7476
  )({
7217
7477
  name: "no-tautological-expect",
@@ -7238,10 +7498,10 @@ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7238
7498
  return {
7239
7499
  CallExpression(node) {
7240
7500
  const callee = node.callee;
7241
- if (callee.type !== AST_NODE_TYPES32.MemberExpression || callee.computed) {
7501
+ if (callee.type !== AST_NODE_TYPES35.MemberExpression || callee.computed) {
7242
7502
  return;
7243
7503
  }
7244
- if (callee.property.type !== AST_NODE_TYPES32.Identifier) {
7504
+ if (callee.property.type !== AST_NODE_TYPES35.Identifier) {
7245
7505
  return;
7246
7506
  }
7247
7507
  const matcher = callee.property.name;
@@ -7275,26 +7535,26 @@ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7275
7535
  });
7276
7536
 
7277
7537
  // src/rules/require-interface-for-injected-service.ts
7278
- import { AST_NODE_TYPES as AST_NODE_TYPES33, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
7538
+ import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils50 } from "@typescript-eslint/utils";
7279
7539
  var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Props|Args|Env|Environment|Callbacks|Flags)$/;
7280
7540
  var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
7281
7541
  var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
7282
7542
  var TRANSPORT_WRAPPER_NAME_RE = /Client$/;
7283
7543
  var ROUTER_FACTORY_NAME = "Router";
7284
7544
  var FRAMEWORK_HTTP_TYPES = /* @__PURE__ */ new Set(["Request", "Response", "NextFunction"]);
7285
- var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES33.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES33.ExportDefaultDeclaration;
7286
- var qualifiedName = (name) => name.type === AST_NODE_TYPES33.Identifier ? name.name : name.type === AST_NODE_TYPES33.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7545
+ var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES36.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES36.ExportDefaultDeclaration;
7546
+ var qualifiedName = (name) => name.type === AST_NODE_TYPES36.Identifier ? name.name : name.type === AST_NODE_TYPES36.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7287
7547
  var typeReferenceName = (annotated) => {
7288
7548
  let target = annotated;
7289
- if (target.type === AST_NODE_TYPES33.TSParameterProperty) target = target.parameter;
7290
- if (target.type === AST_NODE_TYPES33.AssignmentPattern) target = target.left;
7291
- if (target.type !== AST_NODE_TYPES33.Identifier) return null;
7549
+ if (target.type === AST_NODE_TYPES36.TSParameterProperty) target = target.parameter;
7550
+ if (target.type === AST_NODE_TYPES36.AssignmentPattern) target = target.left;
7551
+ if (target.type !== AST_NODE_TYPES36.Identifier) return null;
7292
7552
  const annotation = target.typeAnnotation?.typeAnnotation;
7293
- if (annotation === void 0 || annotation.type !== AST_NODE_TYPES33.TSTypeReference) {
7553
+ if (annotation === void 0 || annotation.type !== AST_NODE_TYPES36.TSTypeReference) {
7294
7554
  return null;
7295
7555
  }
7296
7556
  const { typeName } = annotation;
7297
- const rightmost = typeName.type === AST_NODE_TYPES33.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES33.TSQualifiedName ? typeName.right.name : null;
7557
+ const rightmost = typeName.type === AST_NODE_TYPES36.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES36.TSQualifiedName ? typeName.right.name : null;
7298
7558
  if (rightmost === null) return null;
7299
7559
  return { name: target.name, typeName: rightmost, display: qualifiedName(typeName) };
7300
7560
  };
@@ -7304,17 +7564,17 @@ var readConstructor = (ctor) => {
7304
7564
  let constructedFields = 0;
7305
7565
  if (body !== null && body !== void 0) {
7306
7566
  for (const statement of body.body) {
7307
- if (statement.type !== AST_NODE_TYPES33.ExpressionStatement) continue;
7567
+ if (statement.type !== AST_NODE_TYPES36.ExpressionStatement) continue;
7308
7568
  const expression = statement.expression;
7309
- if (expression.type !== AST_NODE_TYPES33.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES33.MemberExpression || expression.left.object.type !== AST_NODE_TYPES33.ThisExpression) {
7569
+ if (expression.type !== AST_NODE_TYPES36.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES36.MemberExpression || expression.left.object.type !== AST_NODE_TYPES36.ThisExpression) {
7310
7570
  continue;
7311
7571
  }
7312
7572
  const source = expression.right;
7313
- if (source.type === AST_NODE_TYPES33.NewExpression) {
7573
+ if (source.type === AST_NODE_TYPES36.NewExpression) {
7314
7574
  constructedFields += 1;
7315
- } else if (source.type === AST_NODE_TYPES33.Identifier) {
7575
+ } else if (source.type === AST_NODE_TYPES36.Identifier) {
7316
7576
  storedFrom.add(source.name);
7317
- } else if (source.type === AST_NODE_TYPES33.MemberExpression && source.object.type === AST_NODE_TYPES33.Identifier) {
7577
+ } else if (source.type === AST_NODE_TYPES36.MemberExpression && source.object.type === AST_NODE_TYPES36.Identifier) {
7318
7578
  storedFrom.add(source.object.name);
7319
7579
  }
7320
7580
  }
@@ -7323,7 +7583,7 @@ var readConstructor = (ctor) => {
7323
7583
  for (const parameter of ctor.value.params) {
7324
7584
  const reference = typeReferenceName(parameter);
7325
7585
  if (reference === null) continue;
7326
- const stored = parameter.type === AST_NODE_TYPES33.TSParameterProperty || storedFrom.has(reference.name);
7586
+ const stored = parameter.type === AST_NODE_TYPES36.TSParameterProperty || storedFrom.has(reference.name);
7327
7587
  if (!stored) continue;
7328
7588
  if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
7329
7589
  if (CONFIGISH_NAME_RE.test(reference.name)) continue;
@@ -7353,19 +7613,19 @@ var subtreeHas = (root, found) => {
7353
7613
  return hit;
7354
7614
  };
7355
7615
  var isFrameworkWiring = (body) => subtreeHas(body, (node) => {
7356
- if (node.type === AST_NODE_TYPES33.CallExpression) {
7616
+ if (node.type === AST_NODE_TYPES36.CallExpression) {
7357
7617
  const { callee } = node;
7358
- if (callee.type === AST_NODE_TYPES33.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7359
- return callee.type === AST_NODE_TYPES33.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES33.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7618
+ if (callee.type === AST_NODE_TYPES36.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7619
+ return callee.type === AST_NODE_TYPES36.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES36.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7360
7620
  }
7361
- return node.type === AST_NODE_TYPES33.TSTypeReference && node.typeName.type === AST_NODE_TYPES33.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7621
+ return node.type === AST_NODE_TYPES36.TSTypeReference && node.typeName.type === AST_NODE_TYPES36.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7362
7622
  });
7363
7623
  var stem2 = (name) => name.replace(/^I(?=[A-Z])/, "").replace(/Impl$/, "");
7364
7624
  var fileInterfaceNames = (program) => {
7365
7625
  const names = [];
7366
7626
  for (const statement of program.body) {
7367
- const declaration = statement.type === AST_NODE_TYPES33.ExportNamedDeclaration ? statement.declaration : statement;
7368
- if (declaration?.type === AST_NODE_TYPES33.TSInterfaceDeclaration) names.push(declaration.id.name);
7627
+ const declaration = statement.type === AST_NODE_TYPES36.ExportNamedDeclaration ? statement.declaration : statement;
7628
+ if (declaration?.type === AST_NODE_TYPES36.TSInterfaceDeclaration) names.push(declaration.id.name);
7369
7629
  }
7370
7630
  return names;
7371
7631
  };
@@ -7383,16 +7643,16 @@ var isTransportWrapper = (className, collaborators, program) => {
7383
7643
  var publicMethodNames = (body) => {
7384
7644
  const names = [];
7385
7645
  for (const member of body.body) {
7386
- if (member.type !== AST_NODE_TYPES33.MethodDefinition) continue;
7646
+ if (member.type !== AST_NODE_TYPES36.MethodDefinition) continue;
7387
7647
  if (member.kind !== "method" || member.static) continue;
7388
7648
  if (member.accessibility === "private" || member.accessibility === "protected") continue;
7389
- if (member.key.type === AST_NODE_TYPES33.PrivateIdentifier) continue;
7390
- if (member.key.type === AST_NODE_TYPES33.Identifier) names.push(member.key.name);
7649
+ if (member.key.type === AST_NODE_TYPES36.PrivateIdentifier) continue;
7650
+ if (member.key.type === AST_NODE_TYPES36.Identifier) names.push(member.key.name);
7391
7651
  else names.push("\u2026");
7392
7652
  }
7393
7653
  return names;
7394
7654
  };
7395
- var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7655
+ var require_interface_for_injected_service_default = ESLintUtils50.RuleCreator(
7396
7656
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7397
7657
  )({
7398
7658
  name: "require-interface-for-injected-service",
@@ -7420,7 +7680,7 @@ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7420
7680
  if (node.implements.length > 0) return;
7421
7681
  if (node.decorators.length > 0) return;
7422
7682
  const ctor = node.body.body.find(
7423
- (member) => member.type === AST_NODE_TYPES33.MethodDefinition && member.kind === "constructor"
7683
+ (member) => member.type === AST_NODE_TYPES36.MethodDefinition && member.kind === "constructor"
7424
7684
  );
7425
7685
  if (ctor === void 0) return;
7426
7686
  const { collaborators, constructedFields } = readConstructor(ctor);
@@ -7445,26 +7705,26 @@ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7445
7705
  });
7446
7706
 
7447
7707
  // src/rules/prefer-non-nullable-collection.ts
7448
- import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
7708
+ import { AST_NODE_TYPES as AST_NODE_TYPES37, ESLintUtils as ESLintUtils51 } from "@typescript-eslint/utils";
7449
7709
  var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
7450
7710
  function propertyName(node) {
7451
7711
  const key = node.key;
7452
- if (key.type === AST_NODE_TYPES34.Identifier) return key.name;
7453
- if (key.type === AST_NODE_TYPES34.Literal) return String(key.value);
7712
+ if (key.type === AST_NODE_TYPES37.Identifier) return key.name;
7713
+ if (key.type === AST_NODE_TYPES37.Literal) return String(key.value);
7454
7714
  return "collection";
7455
7715
  }
7456
7716
  function isArrayType(node) {
7457
- if (node.type === AST_NODE_TYPES34.TSArrayType) return true;
7458
- return node.type === AST_NODE_TYPES34.TSTypeReference && node.typeName.type === AST_NODE_TYPES34.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7717
+ if (node.type === AST_NODE_TYPES37.TSArrayType) return true;
7718
+ return node.type === AST_NODE_TYPES37.TSTypeReference && node.typeName.type === AST_NODE_TYPES37.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7459
7719
  }
7460
7720
  function isNullishType(node) {
7461
- return node.type === AST_NODE_TYPES34.TSNullKeyword || node.type === AST_NODE_TYPES34.TSUndefinedKeyword;
7721
+ return node.type === AST_NODE_TYPES37.TSNullKeyword || node.type === AST_NODE_TYPES37.TSUndefinedKeyword;
7462
7722
  }
7463
7723
  function isNullableArrayOnly(node) {
7464
7724
  const values = node.types.filter((member) => !isNullishType(member));
7465
7725
  return values.length > 0 && values.length < node.types.length && values.every(isArrayType);
7466
7726
  }
7467
- var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7727
+ var prefer_non_nullable_collection_default = ESLintUtils51.RuleCreator(
7468
7728
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
7469
7729
  )({
7470
7730
  name: "prefer-non-nullable-collection",
@@ -7487,7 +7747,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7487
7747
  function checkOptionalProperty(node) {
7488
7748
  const annotation = node.typeAnnotation?.typeAnnotation;
7489
7749
  if (annotation === void 0) return;
7490
- if (annotation.type !== AST_NODE_TYPES34.TSUnionType || !isNullableArrayOnly(annotation)) {
7750
+ if (annotation.type !== AST_NODE_TYPES37.TSUnionType || !isNullableArrayOnly(annotation)) {
7491
7751
  return;
7492
7752
  }
7493
7753
  context.report({
@@ -7500,7 +7760,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7500
7760
  TSPropertySignature: checkOptionalProperty,
7501
7761
  PropertyDefinition: checkOptionalProperty,
7502
7762
  TSTypeAliasDeclaration(node) {
7503
- if (node.typeAnnotation.type !== AST_NODE_TYPES34.TSUnionType) return;
7763
+ if (node.typeAnnotation.type !== AST_NODE_TYPES37.TSUnionType) return;
7504
7764
  if (!isNullableArrayOnly(node.typeAnnotation)) return;
7505
7765
  context.report({
7506
7766
  node,
@@ -7513,7 +7773,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7513
7773
  });
7514
7774
 
7515
7775
  // src/rules/primary-export-file-name.ts
7516
- import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
7776
+ import { AST_NODE_TYPES as AST_NODE_TYPES38, ESLintUtils as ESLintUtils52 } from "@typescript-eslint/utils";
7517
7777
  var CONVENTIONAL_BUCKET_EXPORTS2 = /* @__PURE__ */ new Set(["cn"]);
7518
7778
  var GENERIC_ENTRYPOINTS = /* @__PURE__ */ new Set(["main", "run", "cli", "setup", "teardown", "execute"]);
7519
7779
  var ACRONYM_OVERRIDES2 = [
@@ -7531,23 +7791,23 @@ var kebabCase3 = (name) => {
7531
7791
  }
7532
7792
  return normalized.replace(CAMEL_BOUNDARY_RE2, "-").toLowerCase();
7533
7793
  };
7534
- var isFunctionOrClass = (node) => node.type === AST_NODE_TYPES35.ArrowFunctionExpression || node.type === AST_NODE_TYPES35.FunctionExpression;
7794
+ var isFunctionOrClass = (node) => node.type === AST_NODE_TYPES38.ArrowFunctionExpression || node.type === AST_NODE_TYPES38.FunctionExpression;
7535
7795
  var findPrimaryExport = (body) => {
7536
7796
  let exportCount = 0;
7537
7797
  let primaryCandidate = null;
7538
7798
  for (const statement of body) {
7539
- if (statement.type === AST_NODE_TYPES35.ExportAllDeclaration) {
7799
+ if (statement.type === AST_NODE_TYPES38.ExportAllDeclaration) {
7540
7800
  return null;
7541
7801
  }
7542
- if (statement.type === AST_NODE_TYPES35.ExportDefaultDeclaration) {
7802
+ if (statement.type === AST_NODE_TYPES38.ExportDefaultDeclaration) {
7543
7803
  exportCount += 1;
7544
7804
  const decl = statement.declaration;
7545
- if ((decl.type === AST_NODE_TYPES35.FunctionDeclaration || decl.type === AST_NODE_TYPES35.ClassDeclaration) && decl.id !== null) {
7805
+ if ((decl.type === AST_NODE_TYPES38.FunctionDeclaration || decl.type === AST_NODE_TYPES38.ClassDeclaration) && decl.id !== null) {
7546
7806
  primaryCandidate = { name: decl.id.name, node: statement, isDefault: true };
7547
- } else if (decl.type === AST_NODE_TYPES35.Identifier) {
7807
+ } else if (decl.type === AST_NODE_TYPES38.Identifier) {
7548
7808
  primaryCandidate = { name: decl.name, node: statement, isDefault: true };
7549
7809
  }
7550
- } else if (statement.type === AST_NODE_TYPES35.ExportNamedDeclaration) {
7810
+ } else if (statement.type === AST_NODE_TYPES38.ExportNamedDeclaration) {
7551
7811
  if (statement.source !== null) {
7552
7812
  return null;
7553
7813
  }
@@ -7556,27 +7816,27 @@ var findPrimaryExport = (body) => {
7556
7816
  exportCount += statement.specifiers.length;
7557
7817
  if (statement.specifiers.length === 1 && primaryCandidate === null) {
7558
7818
  const spec = statement.specifiers[0];
7559
- if (spec && spec.exported.type === AST_NODE_TYPES35.Identifier) {
7819
+ if (spec && spec.exported.type === AST_NODE_TYPES38.Identifier) {
7560
7820
  primaryCandidate = { name: spec.exported.name, node: statement, isDefault: false };
7561
7821
  }
7562
7822
  }
7563
- } else if (decl.type === AST_NODE_TYPES35.FunctionDeclaration || decl.type === AST_NODE_TYPES35.ClassDeclaration) {
7823
+ } else if (decl.type === AST_NODE_TYPES38.FunctionDeclaration || decl.type === AST_NODE_TYPES38.ClassDeclaration) {
7564
7824
  if (decl.id !== null) {
7565
7825
  exportCount += 1;
7566
7826
  if (primaryCandidate === null) {
7567
7827
  primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
7568
7828
  }
7569
7829
  }
7570
- } else if (decl.type === AST_NODE_TYPES35.VariableDeclaration) {
7830
+ } else if (decl.type === AST_NODE_TYPES38.VariableDeclaration) {
7571
7831
  for (const declarator of decl.declarations) {
7572
- if (declarator.id.type === AST_NODE_TYPES35.Identifier) {
7832
+ if (declarator.id.type === AST_NODE_TYPES38.Identifier) {
7573
7833
  exportCount += 1;
7574
7834
  if (primaryCandidate === null && declarator.init && isFunctionOrClass(declarator.init)) {
7575
7835
  primaryCandidate = { name: declarator.id.name, node: statement, isDefault: false };
7576
7836
  }
7577
7837
  }
7578
7838
  }
7579
- } else if (decl.type === AST_NODE_TYPES35.TSTypeAliasDeclaration || decl.type === AST_NODE_TYPES35.TSInterfaceDeclaration) {
7839
+ } else if (decl.type === AST_NODE_TYPES38.TSTypeAliasDeclaration || decl.type === AST_NODE_TYPES38.TSInterfaceDeclaration) {
7580
7840
  exportCount += 1;
7581
7841
  if (primaryCandidate === null) {
7582
7842
  primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
@@ -7589,7 +7849,7 @@ var findPrimaryExport = (body) => {
7589
7849
  }
7590
7850
  return { ...primaryCandidate, count: exportCount };
7591
7851
  };
7592
- var primary_export_file_name_default = ESLintUtils48.RuleCreator(
7852
+ var primary_export_file_name_default = ESLintUtils52.RuleCreator(
7593
7853
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7594
7854
  )({
7595
7855
  name: "primary-export-file-name",
@@ -7631,7 +7891,7 @@ var primary_export_file_name_default = ESLintUtils48.RuleCreator(
7631
7891
  });
7632
7892
 
7633
7893
  // src/rules/no-implicit-attribute-access.ts
7634
- import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
7894
+ import { AST_NODE_TYPES as AST_NODE_TYPES39, ESLintUtils as ESLintUtils53 } from "@typescript-eslint/utils";
7635
7895
  var EXCLUDED_BASES = /* @__PURE__ */ new Set([
7636
7896
  "environ",
7637
7897
  "headers",
@@ -7647,15 +7907,15 @@ var EXCLUDED_BASES = /* @__PURE__ */ new Set([
7647
7907
  "sessionStorage"
7648
7908
  ]);
7649
7909
  function getBaseName(node) {
7650
- if (node.type === AST_NODE_TYPES36.Identifier) {
7910
+ if (node.type === AST_NODE_TYPES39.Identifier) {
7651
7911
  return node.name;
7652
7912
  }
7653
- if (node.type === AST_NODE_TYPES36.MemberExpression && node.property.type === AST_NODE_TYPES36.Identifier) {
7913
+ if (node.type === AST_NODE_TYPES39.MemberExpression && node.property.type === AST_NODE_TYPES39.Identifier) {
7654
7914
  return node.property.name;
7655
7915
  }
7656
7916
  return null;
7657
7917
  }
7658
- var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7918
+ var no_implicit_attribute_access_default = ESLintUtils53.RuleCreator(
7659
7919
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7660
7920
  )({
7661
7921
  name: "no-implicit-attribute-access",
@@ -7676,7 +7936,7 @@ var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7676
7936
  if (!node.computed) {
7677
7937
  return;
7678
7938
  }
7679
- if (node.property.type === AST_NODE_TYPES36.Literal && typeof node.property.value === "string") {
7939
+ if (node.property.type === AST_NODE_TYPES39.Literal && typeof node.property.value === "string") {
7680
7940
  const baseName = getBaseName(node.object);
7681
7941
  if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7682
7942
  context.report({
@@ -7689,11 +7949,11 @@ var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7689
7949
  },
7690
7950
  CallExpression(node) {
7691
7951
  const callee = node.callee;
7692
- if (callee.type === AST_NODE_TYPES36.MemberExpression) {
7693
- const method = callee.property.type === AST_NODE_TYPES36.Identifier ? callee.property.name : null;
7952
+ if (callee.type === AST_NODE_TYPES39.MemberExpression) {
7953
+ const method = callee.property.type === AST_NODE_TYPES39.Identifier ? callee.property.name : null;
7694
7954
  if (method === "get") {
7695
7955
  const arg = node.arguments[0];
7696
- if (arg && arg.type === AST_NODE_TYPES36.Literal && typeof arg.value === "string") {
7956
+ if (arg && arg.type === AST_NODE_TYPES39.Literal && typeof arg.value === "string") {
7697
7957
  const baseName = getBaseName(callee.object);
7698
7958
  if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7699
7959
  context.report({
@@ -7710,8 +7970,174 @@ var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7710
7970
  }
7711
7971
  });
7712
7972
 
7973
+ // src/rules/strict-test-assertions.ts
7974
+ import { AST_NODE_TYPES as AST_NODE_TYPES40, ESLintUtils as ESLintUtils54 } from "@typescript-eslint/utils";
7975
+ var strict_test_assertions_default = ESLintUtils54.RuleCreator.withoutDocs({
7976
+ meta: {
7977
+ type: "suggestion",
7978
+ docs: {
7979
+ description: "Replace multiple sequential assertions with a single toMatchObject or toStrictEqual"
7980
+ },
7981
+ fixable: "code",
7982
+ messages: {
7983
+ combineAssertions: "Combine multiple sequential assertions on the same object into a single toMatchObject or toStrictEqual"
7984
+ },
7985
+ schema: []
7986
+ },
7987
+ defaultOptions: [],
7988
+ create(context) {
7989
+ function checkBody(body) {
7990
+ let currentObject = null;
7991
+ let sequence = [];
7992
+ function getExpectObject(expr) {
7993
+ if (expr.type === AST_NODE_TYPES40.CallExpression && expr.callee.type === AST_NODE_TYPES40.MemberExpression && expr.callee.object.type === AST_NODE_TYPES40.CallExpression && expr.callee.object.callee.type === AST_NODE_TYPES40.Identifier && expr.callee.object.callee.name === "expect" && expr.callee.object.arguments.length === 1) {
7994
+ const arg = expr.callee.object.arguments.at(0);
7995
+ if (arg?.type === AST_NODE_TYPES40.MemberExpression) {
7996
+ return arg.object;
7997
+ }
7998
+ }
7999
+ return null;
8000
+ }
8001
+ function reportSequence() {
8002
+ const first = sequence.at(0);
8003
+ if (sequence.length > 1 && first) {
8004
+ context.report({
8005
+ node: first,
8006
+ messageId: "combineAssertions",
8007
+ fix(fixer) {
8008
+ if (!currentObject) return null;
8009
+ const objectText = context.sourceCode.getText(currentObject);
8010
+ const props = sequence.map((stmt) => {
8011
+ if (stmt.expression.type !== AST_NODE_TYPES40.CallExpression || stmt.expression.callee.type !== AST_NODE_TYPES40.MemberExpression || stmt.expression.callee.object.type !== AST_NODE_TYPES40.CallExpression) {
8012
+ return null;
8013
+ }
8014
+ const actual = stmt.expression.callee.object.arguments.at(0);
8015
+ const expected = stmt.expression.arguments.at(0);
8016
+ if (actual?.type === AST_NODE_TYPES40.MemberExpression && actual.property.type === AST_NODE_TYPES40.Identifier && expected) {
8017
+ const propName2 = actual.property.name;
8018
+ const valText = context.sourceCode.getText(expected);
8019
+ return `${propName2}: ${valText}`;
8020
+ }
8021
+ return null;
8022
+ });
8023
+ if (props.some((p) => p === null)) return null;
8024
+ const replacement = `expect(${objectText}).toMatchObject({ ${props.join(", ")} });`;
8025
+ return [
8026
+ fixer.replaceText(first, replacement),
8027
+ ...sequence.slice(1).map((stmt) => fixer.remove(stmt))
8028
+ ];
8029
+ }
8030
+ });
8031
+ }
8032
+ }
8033
+ for (const statement of body) {
8034
+ if (statement.type === AST_NODE_TYPES40.ExpressionStatement) {
8035
+ const obj = getExpectObject(statement.expression);
8036
+ if (obj && currentObject && context.sourceCode.getText(obj) === context.sourceCode.getText(currentObject)) {
8037
+ sequence.push(statement);
8038
+ } else {
8039
+ reportSequence();
8040
+ if (obj) {
8041
+ currentObject = obj;
8042
+ sequence = [statement];
8043
+ } else {
8044
+ currentObject = null;
8045
+ sequence = [];
8046
+ }
8047
+ }
8048
+ } else {
8049
+ reportSequence();
8050
+ currentObject = null;
8051
+ sequence = [];
8052
+ }
8053
+ }
8054
+ reportSequence();
8055
+ }
8056
+ return {
8057
+ BlockStatement(node) {
8058
+ checkBody(node.body);
8059
+ },
8060
+ Program(node) {
8061
+ checkBody(node.body);
8062
+ }
8063
+ };
8064
+ }
8065
+ });
8066
+
8067
+ // src/rules/no-async-callback-in-waitfor.ts
8068
+ import { AST_NODE_TYPES as AST_NODE_TYPES41, ESLintUtils as ESLintUtils55 } from "@typescript-eslint/utils";
8069
+ var no_async_callback_in_waitfor_default = ESLintUtils55.RuleCreator(
8070
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8071
+ )({
8072
+ name: "no-async-callback-in-waitfor",
8073
+ meta: {
8074
+ type: "problem",
8075
+ docs: {
8076
+ description: "Disallow async callbacks in `waitFor` to prevent swallowed promise rejections."
8077
+ },
8078
+ schema: [],
8079
+ messages: {
8080
+ noAsyncCallbackInWaitFor: "The callback to `waitFor` should not be async. It expects synchronous assertions and runs the callback repeatedly."
8081
+ }
8082
+ },
8083
+ defaultOptions: [],
8084
+ create(context) {
8085
+ if (!isTestFile(context.filename)) {
8086
+ return {};
8087
+ }
8088
+ return {
8089
+ CallExpression(node) {
8090
+ if (node.callee.type === AST_NODE_TYPES41.Identifier && node.callee.name === "waitFor") {
8091
+ const callback = node.arguments[0];
8092
+ if (callback && (callback.type === AST_NODE_TYPES41.ArrowFunctionExpression || callback.type === AST_NODE_TYPES41.FunctionExpression) && callback.async) {
8093
+ context.report({
8094
+ node: callback,
8095
+ messageId: "noAsyncCallbackInWaitFor"
8096
+ });
8097
+ }
8098
+ }
8099
+ }
8100
+ };
8101
+ }
8102
+ });
8103
+
8104
+ // src/rules/prefer-setup-file-mocks.ts
8105
+ import { AST_NODE_TYPES as AST_NODE_TYPES42, ESLintUtils as ESLintUtils56 } from "@typescript-eslint/utils";
8106
+ var prefer_setup_file_mocks_default = ESLintUtils56.RuleCreator(
8107
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
8108
+ )({
8109
+ name: "prefer-setup-file-mocks",
8110
+ meta: {
8111
+ type: "suggestion",
8112
+ docs: {
8113
+ description: "Prefer defining module mocks in setup files rather than using vi.mock or jest.mock inline in test files."
8114
+ },
8115
+ schema: [],
8116
+ messages: {
8117
+ preferSetupFileMocks: "Define module mocks in a setup file (e.g. vitest.setup.ts) instead of using vi.mock or jest.mock directly in test files."
8118
+ }
8119
+ },
8120
+ defaultOptions: [],
8121
+ create(context) {
8122
+ if (!isTestFile(context.filename)) {
8123
+ return {};
8124
+ }
8125
+ return {
8126
+ CallExpression(node) {
8127
+ if (node.callee.type === AST_NODE_TYPES42.MemberExpression && node.callee.object.type === AST_NODE_TYPES42.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === AST_NODE_TYPES42.Identifier && node.callee.property.name === "mock") {
8128
+ context.report({
8129
+ node,
8130
+ messageId: "preferSetupFileMocks"
8131
+ });
8132
+ }
8133
+ }
8134
+ };
8135
+ }
8136
+ });
8137
+
7713
8138
  // src/index.ts
7714
8139
  var rules = {
8140
+ "ban-loose-type-guards-in-tests": ban_loose_type_guards_in_tests_default,
7715
8141
  "enforce-file-structure": enforce_file_structure_default,
7716
8142
  "no-client-side-data-fetching": no_client_side_data_fetching_default,
7717
8143
  "no-comment-cruft": no_comment_cruft_default,
@@ -7736,7 +8162,9 @@ var rules = {
7736
8162
  "no-fat-try-blocks": no_fat_try_blocks_default,
7737
8163
  "no-secret-in-log": no_secret_in_log_default,
7738
8164
  "no-unsafe-cast": no_unsafe_cast_default,
8165
+ "no-unsafe-mock-casting": no_unsafe_mock_casting_default,
7739
8166
  "prefer-string-literal-union": prefer_string_literal_union_default,
8167
+ "prefer-zod-enum": prefer_zod_enum_default,
7740
8168
  "single-public-export": single_public_export_default,
7741
8169
  "primary-export-file-name": primary_export_file_name_default,
7742
8170
  "no-silent-promise-catch": no_silent_promise_catch_default,
@@ -7747,6 +8175,7 @@ var rules = {
7747
8175
  "no-repeated-string-literal": no_repeated_string_literal_default,
7748
8176
  "no-select-star": no_select_star_default,
7749
8177
  "no-sleep-in-test-body": no_sleep_in_test_body_default,
8178
+ "no-conditional-in-test": no_conditional_in_test_default,
7750
8179
  "prefer-constant-time-secret-compare": prefer_constant_time_secret_compare_default,
7751
8180
  "store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
7752
8181
  "no-dynamic-sql": no_dynamic_sql_default,
@@ -7759,13 +8188,16 @@ var rules = {
7759
8188
  "trailing-value-narration": trailing_value_narration_default,
7760
8189
  "no-tautological-expect": no_tautological_expect_default,
7761
8190
  "require-interface-for-injected-service": require_interface_for_injected_service_default,
8191
+ "strict-test-assertions": strict_test_assertions_default,
7762
8192
  "prefer-non-nullable-collection": prefer_non_nullable_collection_default,
7763
- "no-implicit-attribute-access": no_implicit_attribute_access_default
8193
+ "no-implicit-attribute-access": no_implicit_attribute_access_default,
8194
+ "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default,
8195
+ "prefer-setup-file-mocks": prefer_setup_file_mocks_default
7764
8196
  };
7765
8197
  var plugin = {
7766
8198
  meta: {
7767
8199
  name: "@sarj/eslint-plugin",
7768
- version: "2.16.0"
8200
+ version: "2.17.0"
7769
8201
  },
7770
8202
  rules,
7771
8203
  configs: {
@@ -7775,6 +8207,7 @@ var plugin = {
7775
8207
  "@sarj/zod-naming-convention": "warn",
7776
8208
  "@sarj/require-assert-never": "error",
7777
8209
  "@sarj/require-zod-form-validation": "error",
8210
+ "@sarj/ban-loose-type-guards-in-tests": "error",
7778
8211
  "@sarj/enforce-file-structure": "warn",
7779
8212
  "@sarj/no-client-side-data-fetching": "warn",
7780
8213
  "@sarj/prefer-server-actions": "warn",
@@ -7799,9 +8232,11 @@ var plugin = {
7799
8232
  "@sarj/no-cors-wildcard-with-credentials": "warn",
7800
8233
  "@sarj/no-secret-in-log": "warn",
7801
8234
  "@sarj/no-unsafe-cast": "warn",
8235
+ "@sarj/no-unsafe-mock-casting": "warn",
7802
8236
  "@sarj/single-public-export": "warn",
7803
8237
  "@sarj/primary-export-file-name": "warn",
7804
8238
  "@sarj/prefer-string-literal-union": "warn",
8239
+ "@sarj/prefer-zod-enum": "warn",
7805
8240
  // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
7806
8241
  "@sarj/require-fetch-timeout": "warn",
7807
8242
  "@sarj/no-silent-promise-catch": "warn",
@@ -7815,6 +8250,7 @@ var plugin = {
7815
8250
  "@sarj/no-offset-pagination": "warn",
7816
8251
  "@sarj/no-select-star": "warn",
7817
8252
  "@sarj/no-sleep-in-test-body": "warn",
8253
+ "@sarj/no-conditional-in-test": "warn",
7818
8254
  "@sarj/no-repeated-string-literal": "warn",
7819
8255
  "@sarj/no-positional-tuple-return": "warn",
7820
8256
  // Injection guard — low FP, applies to any repo touching SQL.
@@ -7851,7 +8287,9 @@ var plugin = {
7851
8287
  // port, 29 fire, 28 of them true positives.
7852
8288
  "@sarj/require-interface-for-injected-service": "warn",
7853
8289
  "@sarj/prefer-non-nullable-collection": "warn",
7854
- "@sarj/no-implicit-attribute-access": "warn"
8290
+ "@sarj/no-implicit-attribute-access": "warn",
8291
+ "@sarj/no-async-callback-in-waitfor": "warn",
8292
+ "@sarj/prefer-setup-file-mocks": "warn"
7855
8293
  }
7856
8294
  },
7857
8295
  strict: {
@@ -7860,6 +8298,7 @@ var plugin = {
7860
8298
  "@sarj/zod-naming-convention": "error",
7861
8299
  "@sarj/require-assert-never": "error",
7862
8300
  "@sarj/require-zod-form-validation": "error",
8301
+ "@sarj/ban-loose-type-guards-in-tests": "error",
7863
8302
  "@sarj/enforce-file-structure": "error",
7864
8303
  "@sarj/no-raw-env": "error",
7865
8304
  "@sarj/prefer-shadcn": "error",
@@ -7888,10 +8327,12 @@ var plugin = {
7888
8327
  "@sarj/no-cors-wildcard-with-credentials": "error",
7889
8328
  "@sarj/no-secret-in-log": "error",
7890
8329
  "@sarj/no-unsafe-cast": "error",
8330
+ "@sarj/no-unsafe-mock-casting": "error",
7891
8331
  "@sarj/single-public-export": "error",
7892
8332
  "@sarj/primary-export-file-name": "error",
7893
8333
  // Promoted to error 2026-07-25 — strict means strict (user directive).
7894
8334
  "@sarj/prefer-string-literal-union": "error",
8335
+ "@sarj/prefer-zod-enum": "error",
7895
8336
  // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
7896
8337
  "@sarj/require-fetch-timeout": "error",
7897
8338
  "@sarj/no-silent-promise-catch": "error",
@@ -7902,6 +8343,7 @@ var plugin = {
7902
8343
  "@sarj/no-offset-pagination": "error",
7903
8344
  "@sarj/no-select-star": "error",
7904
8345
  "@sarj/no-sleep-in-test-body": "error",
8346
+ "@sarj/no-conditional-in-test": "error",
7905
8347
  "@sarj/no-repeated-string-literal": "error",
7906
8348
  // API-shape advice rather than a runtime defect — a corpus sweep found its
7907
8349
  // only hits are parser `[value, cursor]` returns, which are conventional.
@@ -7931,7 +8373,9 @@ var plugin = {
7931
8373
  // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
7932
8374
  "@sarj/require-interface-for-injected-service": "error",
7933
8375
  "@sarj/prefer-non-nullable-collection": "error",
7934
- "@sarj/no-implicit-attribute-access": "error"
8376
+ "@sarj/no-implicit-attribute-access": "error",
8377
+ "@sarj/no-async-callback-in-waitfor": "error",
8378
+ "@sarj/prefer-setup-file-mocks": "error"
7935
8379
  }
7936
8380
  }
7937
8381
  }