@sarj/eslint-plugin 2.16.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- // src/rules/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",
@@ -1789,255 +1825,6 @@ var no_sentinel_return_on_catch_default = ESLintUtils9.RuleCreator(
1789
1825
  }
1790
1826
  });
1791
1827
 
1792
- // src/rules/no-sequential-await.ts
1793
- import { ESLintUtils as ESLintUtils10 } from "@typescript-eslint/utils";
1794
- var ARRAY_ITERATION_METHODS = /* @__PURE__ */ new Set(["forEach", "map", "filter"]);
1795
- 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
- var BENCH_FILE_RE = /(^|[\\/])bench(marks?)?[\\/]|\.bench\.[cm]?[jt]sx?$/i;
1797
- function isFunctionLike(node) {
1798
- return node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression";
1799
- }
1800
- function isLoop(node) {
1801
- return node.type === "ForStatement" || node.type === "ForOfStatement" || node.type === "ForInStatement" || node.type === "WhileStatement" || node.type === "DoWhileStatement";
1802
- }
1803
- function isNode2(value) {
1804
- return typeof value === "object" && value !== null && typeof value.type === "string";
1805
- }
1806
- function visitScope(root, visit) {
1807
- visit(root);
1808
- for (const key of Object.keys(root)) {
1809
- if (key === "parent") {
1810
- continue;
1811
- }
1812
- const value = root[key];
1813
- const children = Array.isArray(value) ? value : [value];
1814
- for (const child of children) {
1815
- if (isNode2(child) && !isFunctionLike(child) && !isLoop(child)) {
1816
- visitScope(child, visit);
1817
- }
1818
- }
1819
- }
1820
- }
1821
- function collectAwaits(root) {
1822
- const awaits = [];
1823
- visitScope(root, (node) => {
1824
- if (node.type === "AwaitExpression") {
1825
- awaits.push(node);
1826
- }
1827
- });
1828
- return awaits;
1829
- }
1830
- var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
1831
- function hasEarlyExit(root) {
1832
- let found = false;
1833
- visitScope(root, (node) => {
1834
- if (node.type === "ReturnStatement" || node.type === "BreakStatement" || node.type === "ContinueStatement") {
1835
- found = true;
1836
- }
1837
- });
1838
- return found;
1839
- }
1840
- var TIMER_HELPER_RE = /^(sleep|timeout|delay|wait|pause|tick)$/i;
1841
- function calleeName2(callee) {
1842
- if (callee.type === "Identifier") return callee.name;
1843
- if (callee.type === "MemberExpression" && !callee.computed && callee.property.type === "Identifier") {
1844
- return callee.property.name;
1845
- }
1846
- return null;
1847
- }
1848
- function isTimerYield(node) {
1849
- const arg = node.argument;
1850
- if (arg.type === "NewExpression" && arg.callee.type === "Identifier" && arg.callee.name === "Promise") {
1851
- return true;
1852
- }
1853
- if (arg.type === "CallExpression") {
1854
- if (arg.callee.type === "MemberExpression" && !arg.callee.computed && arg.callee.object.type === "Identifier" && arg.callee.object.name === "Promise" && arg.callee.property.type === "Identifier" && (arg.callee.property.name === "resolve" || arg.callee.property.name === "reject")) {
1855
- return true;
1856
- }
1857
- const name = calleeName2(arg.callee);
1858
- return name !== null && TIMER_HELPER_RE.test(name);
1859
- }
1860
- return false;
1861
- }
1862
- var QUEUE_DRAIN_METHODS = /^(shift|pop|dequeue|next|poll)$/;
1863
- function isQueueDrain(node) {
1864
- const arg = node.argument;
1865
- return arg.type === "CallExpression" && arg.callee.type === "MemberExpression" && !arg.callee.computed && arg.callee.property.type === "Identifier" && QUEUE_DRAIN_METHODS.test(arg.callee.property.name);
1866
- }
1867
- function hasAssertion(root) {
1868
- let found = false;
1869
- visitScope(root, (node) => {
1870
- if (node.type !== "CallExpression") {
1871
- return;
1872
- }
1873
- let callee = node.callee;
1874
- while (callee.type === "MemberExpression") {
1875
- callee = callee.object;
1876
- }
1877
- if (callee.type === "CallExpression") {
1878
- callee = callee.callee;
1879
- }
1880
- if (callee.type === "Identifier" && ASSERTION_CALLEE_RE.test(callee.name)) {
1881
- found = true;
1882
- }
1883
- });
1884
- return found;
1885
- }
1886
- function referencesName(root, name) {
1887
- let found = false;
1888
- visitScope(root, (node) => {
1889
- if (node.type === "Identifier" && node.name === name) {
1890
- found = true;
1891
- }
1892
- });
1893
- return found;
1894
- }
1895
- function isThreadedAccumulator(node) {
1896
- const parent = node.parent;
1897
- let target = null;
1898
- if (parent.type === "AssignmentExpression" && parent.operator === "=" && parent.right === node && parent.left.type === "Identifier") {
1899
- target = parent.left.name;
1900
- } else if (parent.type === "VariableDeclarator" && parent.init === node && parent.id.type === "Identifier") {
1901
- target = parent.id.name;
1902
- }
1903
- if (target === null) {
1904
- return false;
1905
- }
1906
- return referencesName(node.argument, target);
1907
- }
1908
- function namesReadBy(test) {
1909
- const names = /* @__PURE__ */ new Set();
1910
- visitScope(test, (node) => {
1911
- if (node.type === "Identifier") {
1912
- names.add(node.name);
1913
- }
1914
- });
1915
- return names;
1916
- }
1917
- function testStateIsAssignedInBody(test, body) {
1918
- const testNames = namesReadBy(test);
1919
- if (testNames.size === 0) {
1920
- return false;
1921
- }
1922
- let found = false;
1923
- visitScope(body, (node) => {
1924
- if (node.type === "AssignmentExpression" && node.operator === "=" && node.left.type === "Identifier" && testNames.has(node.left.name)) {
1925
- found = true;
1926
- }
1927
- });
1928
- return found;
1929
- }
1930
- function shouldReport(awaits, earlyExit, iterableText, asserts = false) {
1931
- if (awaits.length === 0) {
1932
- return false;
1933
- }
1934
- if (earlyExit) {
1935
- return false;
1936
- }
1937
- if (asserts) {
1938
- return false;
1939
- }
1940
- if (iterableText !== null && SEQUENTIAL_ITERABLE_HINT.test(iterableText)) {
1941
- return false;
1942
- }
1943
- return awaits.some(
1944
- (node) => !isTimerYield(node) && !isThreadedAccumulator(node) && !isQueueDrain(node)
1945
- );
1946
- }
1947
- var no_sequential_await_default = ESLintUtils10.RuleCreator(
1948
- (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
1949
- )({
1950
- name: "no-sequential-await",
1951
- meta: {
1952
- type: "problem",
1953
- docs: {
1954
- description: "Disallow serial `await` inside a loop; use `await Promise.all(...)` to run the operations concurrently."
1955
- },
1956
- schema: [],
1957
- messages: {
1958
- noSequentialAwait: "Avoid `await` inside a loop \u2014 it serializes I/O. Collect the promises and `await Promise.all(xs.map(async (x) => ...))` instead."
1959
- }
1960
- },
1961
- defaultOptions: [],
1962
- create(context) {
1963
- if (isTestFile(context.filename) || BENCH_FILE_RE.test(context.filename)) {
1964
- return {};
1965
- }
1966
- function loopParts(node) {
1967
- if (node.type === "ForStatement") {
1968
- return [node.body, node.test, node.update];
1969
- }
1970
- if (node.type === "ForOfStatement" || node.type === "ForInStatement") {
1971
- return [node.body];
1972
- }
1973
- return [node.body, node.test];
1974
- }
1975
- function iterableTextOf(node) {
1976
- if (node.type === "ForOfStatement" || node.type === "ForInStatement") {
1977
- return context.sourceCode.getText(node.right);
1978
- }
1979
- return null;
1980
- }
1981
- function checkLoop(node) {
1982
- if ((node.type === "WhileStatement" || node.type === "DoWhileStatement") && testStateIsAssignedInBody(node.test, node.body)) {
1983
- return;
1984
- }
1985
- const awaits = [];
1986
- let earlyExit = false;
1987
- let asserts = false;
1988
- for (const part of loopParts(node)) {
1989
- if (part === null || isLoop(part)) {
1990
- continue;
1991
- }
1992
- awaits.push(...collectAwaits(part));
1993
- if (!earlyExit && hasEarlyExit(part)) {
1994
- earlyExit = true;
1995
- }
1996
- if (!asserts && hasAssertion(part)) {
1997
- asserts = true;
1998
- }
1999
- }
2000
- if (shouldReport(awaits, earlyExit, iterableTextOf(node), asserts)) {
2001
- context.report({ node, messageId: "noSequentialAwait" });
2002
- }
2003
- }
2004
- return {
2005
- ForStatement: checkLoop,
2006
- ForInStatement: checkLoop,
2007
- WhileStatement: checkLoop,
2008
- DoWhileStatement: checkLoop,
2009
- ForOfStatement(node) {
2010
- if (node.await) {
2011
- return;
2012
- }
2013
- checkLoop(node);
2014
- },
2015
- CallExpression(node) {
2016
- const callee = node.callee;
2017
- if (callee.type !== "MemberExpression" || callee.computed) {
2018
- return;
2019
- }
2020
- if (callee.property.type !== "Identifier" || !ARRAY_ITERATION_METHODS.has(callee.property.name)) {
2021
- return;
2022
- }
2023
- const callback = node.arguments[0];
2024
- if (callback === void 0 || !isFunctionLike(callback) || !("async" in callback && callback.async)) {
2025
- return;
2026
- }
2027
- if (callee.property.name !== "forEach" && node.parent.type !== "ExpressionStatement") {
2028
- return;
2029
- }
2030
- const awaits = collectAwaits(callback.body);
2031
- const earlyExit = hasEarlyExit(callback.body);
2032
- const iterableText = context.sourceCode.getText(callee.object);
2033
- if (shouldReport(awaits, earlyExit, iterableText, hasAssertion(callback.body))) {
2034
- context.report({ node, messageId: "noSequentialAwait" });
2035
- }
2036
- }
2037
- };
2038
- }
2039
- });
2040
-
2041
1828
  // src/rules/no-string-concat-in-loop.ts
2042
1829
  import { ESLintUtils as ESLintUtils11 } from "@typescript-eslint/utils";
2043
1830
  var LOOP_NODE_TYPES = /* @__PURE__ */ new Set([
@@ -2539,7 +2326,7 @@ var isLocalFileRead = (node) => {
2539
2326
  visit(node);
2540
2327
  return found;
2541
2328
  };
2542
- var ASSERTION_CALLEE_RE2 = /^(expect|assert|should|invariant)$/;
2329
+ var ASSERTION_CALLEE_RE = /^(expect|assert|should|invariant)$/;
2543
2330
  var isInsideAssertion = (node) => {
2544
2331
  for (let current = node.parent; current !== void 0 && current !== null; current = current.parent) {
2545
2332
  if (current.type !== AST_NODE_TYPES8.CallExpression) continue;
@@ -2550,7 +2337,7 @@ var isInsideAssertion = (node) => {
2550
2337
  if (callee.type === AST_NODE_TYPES8.CallExpression) {
2551
2338
  callee = callee.callee;
2552
2339
  }
2553
- if (callee.type === AST_NODE_TYPES8.Identifier && ASSERTION_CALLEE_RE2.test(callee.name)) {
2340
+ if (callee.type === AST_NODE_TYPES8.Identifier && ASSERTION_CALLEE_RE.test(callee.name)) {
2554
2341
  return true;
2555
2342
  }
2556
2343
  }
@@ -2764,6 +2551,7 @@ var DETECTION_FILES = [
2764
2551
  "src/styles/globals.css",
2765
2552
  "styles/globals.css"
2766
2553
  ];
2554
+ var MAX_UPWARD_DEPTH = 8;
2767
2555
  var semanticTokenCache = /* @__PURE__ */ new Map();
2768
2556
  var SVG_DEFS_CONTAINERS = /* @__PURE__ */ new Set([
2769
2557
  "mask",
@@ -2818,9 +2606,15 @@ var isInsideIconFactoryPath = (node) => {
2818
2606
  var hasSemanticTokenSystem = (filename) => {
2819
2607
  let dir = dirname(filename);
2820
2608
  const root = parse(dir).root;
2821
- for (let depth = 0; depth < 8; depth += 1) {
2609
+ const visited = [];
2610
+ let answer;
2611
+ for (let depth = 0; depth < MAX_UPWARD_DEPTH; depth += 1) {
2822
2612
  const cached = semanticTokenCache.get(dir);
2823
- if (cached !== void 0) return cached;
2613
+ if (cached !== void 0) {
2614
+ answer = cached;
2615
+ break;
2616
+ }
2617
+ visited.push(dir);
2824
2618
  let found = false;
2825
2619
  for (const rel of DETECTION_FILES) {
2826
2620
  const candidate = join(dir, rel);
@@ -2837,11 +2631,19 @@ var hasSemanticTokenSystem = (filename) => {
2837
2631
  } catch {
2838
2632
  }
2839
2633
  }
2840
- semanticTokenCache.set(dir, found);
2841
- if (found || dir === root) return found;
2634
+ if (found) {
2635
+ answer = true;
2636
+ break;
2637
+ }
2638
+ if (dir === root) {
2639
+ answer = false;
2640
+ break;
2641
+ }
2842
2642
  dir = dirname(dir);
2843
2643
  }
2844
- return false;
2644
+ if (answer === void 0) return false;
2645
+ for (const seen of visited) semanticTokenCache.set(seen, answer);
2646
+ return answer;
2845
2647
  };
2846
2648
  var propName = (key) => {
2847
2649
  if (key.type === AST_NODE_TYPES9.Identifier) return key.name;
@@ -3124,122 +2926,40 @@ var prefer_server_actions_default = ESLintUtils16.RuleCreator(
3124
2926
  }
3125
2927
  });
3126
2928
 
3127
- // src/rules/prefer-shadcn.ts
3128
- import {
3129
- AST_NODE_TYPES as AST_NODE_TYPES10,
3130
- ESLintUtils as ESLintUtils17
3131
- } from "@typescript-eslint/utils";
3132
- var REPLACEMENTS = {
3133
- select: "Select",
3134
- textarea: "Textarea",
3135
- dialog: "Dialog"
3136
- };
3137
- var INPUT_TYPE_REPLACEMENTS = {
3138
- checkbox: "Checkbox",
3139
- radio: "RadioGroup",
3140
- range: "Slider"
3141
- };
3142
- var SKIPPED_INPUT_TYPES = /* @__PURE__ */ new Set(["file", "hidden"]);
3143
- var kebabCase = (component) => component.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
3144
- var literalTypeAttr = (node) => {
3145
- for (const attribute of node.attributes) {
3146
- if (attribute.type !== AST_NODE_TYPES10.JSXAttribute || attribute.name.type !== AST_NODE_TYPES10.JSXIdentifier || attribute.name.name !== "type") {
3147
- continue;
3148
- }
3149
- if (attribute.value?.type === AST_NODE_TYPES10.Literal && typeof attribute.value.value === "string") {
3150
- return { kind: "literal", value: attribute.value.value.toLowerCase() };
3151
- }
3152
- return { kind: "dynamic" };
3153
- }
3154
- return null;
3155
- };
3156
- var hasFileAcceptAttr = (node) => node.attributes.some(
3157
- (attribute) => attribute.type === AST_NODE_TYPES10.JSXAttribute && attribute.name.type === AST_NODE_TYPES10.JSXIdentifier && attribute.name.name === "accept"
3158
- );
3159
- var resolveInputReplacement = (node) => {
3160
- const typeAttr = literalTypeAttr(node);
3161
- if (hasFileAcceptAttr(node)) return null;
3162
- if (typeAttr === null || typeAttr.kind === "dynamic") return "Input";
3163
- if (SKIPPED_INPUT_TYPES.has(typeAttr.value)) return null;
3164
- return INPUT_TYPE_REPLACEMENTS[typeAttr.value] ?? "Input";
3165
- };
3166
- var prefer_shadcn_default = ESLintUtils17.RuleCreator(
3167
- (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3168
- )({
3169
- name: "prefer-shadcn",
3170
- meta: {
3171
- type: "suggestion",
3172
- docs: {
3173
- description: "Prefer shadcn/ui form primitives over native `<input>`, `<select>`, `<textarea>`, and `<dialog>` elements."
3174
- },
3175
- schema: [],
3176
- messages: {
3177
- preferShadcn: "Use the shadcn <{{replacement}}> component from @/components/ui/{{lowercase}} instead of native <{{element}}>."
3178
- }
3179
- },
3180
- defaultOptions: [],
3181
- create(context) {
3182
- if (isTestFile(context.filename) || isStoryFile(context.filename)) {
3183
- return {};
3184
- }
3185
- return {
3186
- JSXOpeningElement(node) {
3187
- if (node.name.type !== "JSXIdentifier") {
3188
- return;
3189
- }
3190
- const elementName = node.name.name;
3191
- const replacement = elementName === "input" ? resolveInputReplacement(node) : REPLACEMENTS[elementName];
3192
- if (replacement === void 0 || replacement === null) {
3193
- return;
3194
- }
3195
- context.report({
3196
- node,
3197
- messageId: "preferShadcn",
3198
- data: {
3199
- element: elementName,
3200
- replacement,
3201
- lowercase: kebabCase(replacement)
3202
- }
3203
- });
3204
- }
3205
- };
3206
- }
3207
- });
3208
-
3209
2929
  // src/rules/require-assert-never.ts
3210
2930
  import {
3211
- ESLintUtils as ESLintUtils18,
3212
- AST_NODE_TYPES as AST_NODE_TYPES11
2931
+ ESLintUtils as ESLintUtils17,
2932
+ AST_NODE_TYPES as AST_NODE_TYPES10
3213
2933
  } from "@typescript-eslint/utils";
3214
2934
  var isAssertNeverCall = (expression) => {
3215
- if (expression.type !== AST_NODE_TYPES11.CallExpression) return false;
2935
+ if (expression.type !== AST_NODE_TYPES10.CallExpression) return false;
3216
2936
  const callee = expression.callee;
3217
- if (callee.type === AST_NODE_TYPES11.Identifier) {
2937
+ if (callee.type === AST_NODE_TYPES10.Identifier) {
3218
2938
  return callee.name === "assertNever";
3219
2939
  }
3220
- if (callee.type === AST_NODE_TYPES11.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES11.Identifier) {
2940
+ if (callee.type === AST_NODE_TYPES10.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES10.Identifier) {
3221
2941
  return callee.property.name === "assertNever";
3222
2942
  }
3223
2943
  return false;
3224
2944
  };
3225
2945
  var statementContainsAssertNever = (statement) => {
3226
- if (statement.type === AST_NODE_TYPES11.ExpressionStatement) {
2946
+ if (statement.type === AST_NODE_TYPES10.ExpressionStatement) {
3227
2947
  return isAssertNeverCall(statement.expression);
3228
2948
  }
3229
- if (statement.type === AST_NODE_TYPES11.ThrowStatement) {
2949
+ if (statement.type === AST_NODE_TYPES10.ThrowStatement) {
3230
2950
  return isAssertNeverCall(statement.argument);
3231
2951
  }
3232
- if (statement.type === AST_NODE_TYPES11.ReturnStatement) {
2952
+ if (statement.type === AST_NODE_TYPES10.ReturnStatement) {
3233
2953
  return statement.argument !== null && isAssertNeverCall(statement.argument);
3234
2954
  }
3235
- if (statement.type === AST_NODE_TYPES11.BlockStatement) {
2955
+ if (statement.type === AST_NODE_TYPES10.BlockStatement) {
3236
2956
  return statement.body.some(statementContainsAssertNever);
3237
2957
  }
3238
2958
  return false;
3239
2959
  };
3240
2960
  var isRuntimeHandlingStatement = (statement) => {
3241
- if (statement.type === AST_NODE_TYPES11.EmptyStatement) return false;
3242
- if (statement.type === AST_NODE_TYPES11.BlockStatement) {
2961
+ if (statement.type === AST_NODE_TYPES10.EmptyStatement) return false;
2962
+ if (statement.type === AST_NODE_TYPES10.BlockStatement) {
3243
2963
  return statement.body.some(isRuntimeHandlingStatement);
3244
2964
  }
3245
2965
  return true;
@@ -3255,12 +2975,12 @@ var isCommentOnlyNoopDefault = (defaultCase, sourceCode) => {
3255
2975
  return colonToken !== null && sourceCode.getCommentsAfter(colonToken).length > 0;
3256
2976
  }
3257
2977
  const only = defaultCase.consequent[0];
3258
- if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === AST_NODE_TYPES11.BlockStatement && only.body.length === 0) {
2978
+ if (only !== void 0 && defaultCase.consequent.length === 1 && only.type === AST_NODE_TYPES10.BlockStatement && only.body.length === 0) {
3259
2979
  return sourceCode.getCommentsInside(only).length > 0;
3260
2980
  }
3261
2981
  return false;
3262
2982
  };
3263
- var require_assert_never_default = ESLintUtils18.RuleCreator(
2983
+ var require_assert_never_default = ESLintUtils17.RuleCreator(
3264
2984
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3265
2985
  )({
3266
2986
  name: "require-assert-never",
@@ -3298,7 +3018,7 @@ var require_assert_never_default = ESLintUtils18.RuleCreator(
3298
3018
  });
3299
3019
 
3300
3020
  // src/rules/require-zod-form-validation.ts
3301
- import { ESLintUtils as ESLintUtils19, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
3021
+ import { ESLintUtils as ESLintUtils18, AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/utils";
3302
3022
 
3303
3023
  // src/rules/_zod.ts
3304
3024
  var ZOD_PREFIX_RE = /^Z[A-Z]/;
@@ -3309,14 +3029,14 @@ var ZOD_SCHEMA_NAME_RE = /Schema$|^Z[A-Z]/;
3309
3029
  var looksLikeZodSchema = (node) => {
3310
3030
  let current = node;
3311
3031
  while (true) {
3312
- if (current.type === AST_NODE_TYPES12.Identifier) {
3032
+ if (current.type === AST_NODE_TYPES11.Identifier) {
3313
3033
  return current.name === "z" || ZOD_SCHEMA_NAME_RE.test(current.name);
3314
3034
  }
3315
- if (current.type === AST_NODE_TYPES12.CallExpression) {
3035
+ if (current.type === AST_NODE_TYPES11.CallExpression) {
3316
3036
  current = current.callee;
3317
3037
  continue;
3318
3038
  }
3319
- if (current.type === AST_NODE_TYPES12.MemberExpression) {
3039
+ if (current.type === AST_NODE_TYPES11.MemberExpression) {
3320
3040
  current = current.object;
3321
3041
  continue;
3322
3042
  }
@@ -3324,25 +3044,25 @@ var looksLikeZodSchema = (node) => {
3324
3044
  }
3325
3045
  };
3326
3046
  var isZodParseCall = (node) => {
3327
- if (node.type !== AST_NODE_TYPES12.CallExpression) return false;
3047
+ if (node.type !== AST_NODE_TYPES11.CallExpression) return false;
3328
3048
  const callee = node.callee;
3329
- if (callee.type !== AST_NODE_TYPES12.MemberExpression) return false;
3049
+ if (callee.type !== AST_NODE_TYPES11.MemberExpression) return false;
3330
3050
  if (callee.computed) return false;
3331
- if (callee.property.type !== AST_NODE_TYPES12.Identifier) return false;
3051
+ if (callee.property.type !== AST_NODE_TYPES11.Identifier) return false;
3332
3052
  const method = callee.property.name;
3333
3053
  if (method !== "parse" && method !== "safeParse") return false;
3334
3054
  return looksLikeZodSchema(callee.object);
3335
3055
  };
3336
3056
  var isFormDataMethodCall = (node) => {
3337
3057
  let current = node;
3338
- if (current.type === AST_NODE_TYPES12.AwaitExpression) {
3058
+ if (current.type === AST_NODE_TYPES11.AwaitExpression) {
3339
3059
  current = current.argument;
3340
3060
  }
3341
- if (current.type !== AST_NODE_TYPES12.CallExpression) return false;
3061
+ if (current.type !== AST_NODE_TYPES11.CallExpression) return false;
3342
3062
  const callee = current.callee;
3343
- return callee.type === AST_NODE_TYPES12.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES12.Identifier && callee.property.name === "formData";
3063
+ return callee.type === AST_NODE_TYPES11.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES11.Identifier && callee.property.name === "formData";
3344
3064
  };
3345
- var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3065
+ var require_zod_form_validation_default = ESLintUtils18.RuleCreator(
3346
3066
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3347
3067
  )({
3348
3068
  name: "require-zod-form-validation",
@@ -3362,14 +3082,14 @@ var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3362
3082
  return {};
3363
3083
  }
3364
3084
  const isFormSourceIdentifier = (node) => {
3365
- if (node.type !== AST_NODE_TYPES12.Identifier) return false;
3085
+ if (node.type !== AST_NODE_TYPES11.Identifier) return false;
3366
3086
  if (/formdata/i.test(node.name)) return true;
3367
3087
  let scope = context.sourceCode.getScope(node);
3368
3088
  while (scope !== null) {
3369
3089
  const variable = scope.set.get(node.name);
3370
3090
  if (variable !== void 0 && variable.defs.length === 1) {
3371
3091
  const def = variable.defs[0];
3372
- if (def !== void 0 && def.type === "Variable" && def.node.type === AST_NODE_TYPES12.VariableDeclarator && def.node.init !== null) {
3092
+ if (def !== void 0 && def.type === "Variable" && def.node.type === AST_NODE_TYPES11.VariableDeclarator && def.node.init !== null) {
3373
3093
  return isFormDataMethodCall(def.node.init);
3374
3094
  }
3375
3095
  return false;
@@ -3380,8 +3100,8 @@ var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3380
3100
  };
3381
3101
  const isFormDataGetCall = (node) => {
3382
3102
  const callee = node.callee;
3383
- if (callee.type !== AST_NODE_TYPES12.MemberExpression) return false;
3384
- if (callee.property.type !== AST_NODE_TYPES12.Identifier || callee.property.name !== "get") {
3103
+ if (callee.type !== AST_NODE_TYPES11.MemberExpression) return false;
3104
+ if (callee.property.type !== AST_NODE_TYPES11.Identifier || callee.property.name !== "get") {
3385
3105
  return false;
3386
3106
  }
3387
3107
  return isFormSourceIdentifier(callee.object);
@@ -3396,11 +3116,11 @@ var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3396
3116
  };
3397
3117
  const isInstanceofNarrowing = (node) => {
3398
3118
  const parent = node.parent;
3399
- return parent !== null && parent !== void 0 && parent.type === AST_NODE_TYPES12.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3119
+ return parent !== null && parent !== void 0 && parent.type === AST_NODE_TYPES11.BinaryExpression && parent.operator === "instanceof" && parent.left === node;
3400
3120
  };
3401
3121
  const boundDeclarator = (node) => {
3402
3122
  const parent = node.parent;
3403
- if (parent.type === AST_NODE_TYPES12.VariableDeclarator && parent.init === node && parent.id.type === AST_NODE_TYPES12.Identifier) {
3123
+ if (parent.type === AST_NODE_TYPES11.VariableDeclarator && parent.init === node && parent.id.type === AST_NODE_TYPES11.Identifier) {
3404
3124
  return parent;
3405
3125
  }
3406
3126
  return null;
@@ -3428,7 +3148,7 @@ var require_zod_form_validation_default = ESLintUtils19.RuleCreator(
3428
3148
  });
3429
3149
 
3430
3150
  // src/rules/zod-naming-convention.ts
3431
- import { ESLintUtils as ESLintUtils20, AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/utils";
3151
+ import { ESLintUtils as ESLintUtils19, AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
3432
3152
  var CONVENTIONS = {
3433
3153
  prefix: { test: ZOD_PREFIX_RE, messageId: "zPrefix" },
3434
3154
  suffix: { test: ZOD_SUFFIX_RE, messageId: "schemaSuffix" },
@@ -3452,15 +3172,15 @@ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
3452
3172
  "registry",
3453
3173
  "implement"
3454
3174
  ]);
3455
- var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES13.Identifier ? callee.property.name : null;
3175
+ var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES12.Identifier ? callee.property.name : null;
3456
3176
  var calleeChainStartsWithZ = (node) => {
3457
3177
  let current = node;
3458
- while (current.type === AST_NODE_TYPES13.MemberExpression) {
3178
+ while (current.type === AST_NODE_TYPES12.MemberExpression) {
3459
3179
  const receiver = current.object;
3460
- if (receiver.type === AST_NODE_TYPES13.Identifier && receiver.name === "z") {
3180
+ if (receiver.type === AST_NODE_TYPES12.Identifier && receiver.name === "z") {
3461
3181
  return true;
3462
3182
  }
3463
- if (receiver.type === AST_NODE_TYPES13.CallExpression) {
3183
+ if (receiver.type === AST_NODE_TYPES12.CallExpression) {
3464
3184
  current = receiver.callee;
3465
3185
  continue;
3466
3186
  }
@@ -3468,7 +3188,7 @@ var calleeChainStartsWithZ = (node) => {
3468
3188
  }
3469
3189
  return false;
3470
3190
  };
3471
- var zod_naming_convention_default = ESLintUtils20.RuleCreator(
3191
+ var zod_naming_convention_default = ESLintUtils19.RuleCreator(
3472
3192
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3473
3193
  )({
3474
3194
  name: "zod-naming-convention",
@@ -3507,13 +3227,13 @@ var zod_naming_convention_default = ESLintUtils20.RuleCreator(
3507
3227
  VariableDeclarator(node) {
3508
3228
  const init = node.init;
3509
3229
  if (init === null || init === void 0) return;
3510
- if (init.type !== AST_NODE_TYPES13.CallExpression) return;
3230
+ if (init.type !== AST_NODE_TYPES12.CallExpression) return;
3511
3231
  const callee = init.callee;
3512
- if (callee.type !== AST_NODE_TYPES13.MemberExpression) return;
3232
+ if (callee.type !== AST_NODE_TYPES12.MemberExpression) return;
3513
3233
  if (!calleeChainStartsWithZ(callee)) return;
3514
3234
  const terminal = terminalMethodName(callee);
3515
3235
  if (terminal !== null && NON_SCHEMA_TERMINALS.has(terminal)) return;
3516
- if (node.id.type !== AST_NODE_TYPES13.Identifier) return;
3236
+ if (node.id.type !== AST_NODE_TYPES12.Identifier) return;
3517
3237
  if (test.test(node.id.name)) return;
3518
3238
  if (acceptsSchemaWord && CONTAINS_SCHEMA_RE.test(node.id.name)) return;
3519
3239
  context.report({
@@ -3526,7 +3246,7 @@ var zod_naming_convention_default = ESLintUtils20.RuleCreator(
3526
3246
  });
3527
3247
 
3528
3248
  // src/rules/no-cors-wildcard-with-credentials.ts
3529
- import { ESLintUtils as ESLintUtils21 } from "@typescript-eslint/utils";
3249
+ import { ESLintUtils as ESLintUtils20 } from "@typescript-eslint/utils";
3530
3250
  var ACAO_HEADER = "access-control-allow-origin";
3531
3251
  var ACAC_HEADER = "access-control-allow-credentials";
3532
3252
  var HEADER_SET_METHODS = /* @__PURE__ */ new Set(["setheader", "set", "append"]);
@@ -3558,17 +3278,17 @@ function subtreeContainsStarLiteral(node) {
3558
3278
  const value = node[key];
3559
3279
  if (Array.isArray(value)) {
3560
3280
  for (const child of value) {
3561
- if (isNode3(child) && subtreeContainsStarLiteral(child)) {
3281
+ if (isNode2(child) && subtreeContainsStarLiteral(child)) {
3562
3282
  return true;
3563
3283
  }
3564
3284
  }
3565
- } else if (isNode3(value) && subtreeContainsStarLiteral(value)) {
3285
+ } else if (isNode2(value) && subtreeContainsStarLiteral(value)) {
3566
3286
  return true;
3567
3287
  }
3568
3288
  }
3569
3289
  return false;
3570
3290
  }
3571
- function isNode3(value) {
3291
+ function isNode2(value) {
3572
3292
  return typeof value === "object" && value !== null && typeof value.type === "string";
3573
3293
  }
3574
3294
  function propertyKeyName(prop) {
@@ -3584,7 +3304,7 @@ function propertyKeyName(prop) {
3584
3304
  }
3585
3305
  return void 0;
3586
3306
  }
3587
- function calleeName3(node) {
3307
+ function calleeName2(node) {
3588
3308
  const callee = node.callee;
3589
3309
  if (callee.type === "Identifier") {
3590
3310
  return callee.name;
@@ -3595,7 +3315,7 @@ function calleeName3(node) {
3595
3315
  return void 0;
3596
3316
  }
3597
3317
  function isCorsWildcardCredentialsCall(node) {
3598
- const name = calleeName3(node);
3318
+ const name = calleeName2(node);
3599
3319
  if (name === void 0 || name.toLowerCase() !== "cors") {
3600
3320
  return false;
3601
3321
  }
@@ -3668,7 +3388,7 @@ function enclosingScope(node) {
3668
3388
  }
3669
3389
  return void 0;
3670
3390
  }
3671
- var no_cors_wildcard_with_credentials_default = ESLintUtils21.RuleCreator(
3391
+ var no_cors_wildcard_with_credentials_default = ESLintUtils20.RuleCreator(
3672
3392
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3673
3393
  )({
3674
3394
  name: "no-cors-wildcard-with-credentials",
@@ -3736,9 +3456,9 @@ var no_cors_wildcard_with_credentials_default = ESLintUtils21.RuleCreator(
3736
3456
  });
3737
3457
 
3738
3458
  // src/rules/no-silent-promise-catch.ts
3739
- import { AST_NODE_TYPES as AST_NODE_TYPES14, ESLintUtils as ESLintUtils22 } from "@typescript-eslint/utils";
3459
+ import { AST_NODE_TYPES as AST_NODE_TYPES13, ESLintUtils as ESLintUtils21 } from "@typescript-eslint/utils";
3740
3460
  function isBodyParseCall(node) {
3741
- 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");
3461
+ return node.type === AST_NODE_TYPES13.CallExpression && node.arguments.length === 0 && node.callee.type === AST_NODE_TYPES13.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES13.Identifier && (node.callee.property.name === "json" || node.callee.property.name === "text");
3742
3462
  }
3743
3463
  var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3744
3464
  "cancel",
@@ -3753,21 +3473,21 @@ var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
3753
3473
  var DIRECTIVE_COMMENT_RE = /^\s*(eslint-|@ts-|prettier-ignore|biome-ignore|c8 |v8 |istanbul )/;
3754
3474
  var isExplanatory = (comment) => !DIRECTIVE_COMMENT_RE.test(comment.value);
3755
3475
  function isTeardownCall(node) {
3756
- return node.type === AST_NODE_TYPES14.CallExpression && node.callee.type === AST_NODE_TYPES14.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES14.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3476
+ return node.type === AST_NODE_TYPES13.CallExpression && node.callee.type === AST_NODE_TYPES13.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES13.Identifier && TEARDOWN_METHODS.has(node.callee.property.name);
3757
3477
  }
3758
3478
  function isSilentExpression(node) {
3759
3479
  switch (node.type) {
3760
- case AST_NODE_TYPES14.Literal:
3480
+ case AST_NODE_TYPES13.Literal:
3761
3481
  return !("regex" in node);
3762
- case AST_NODE_TYPES14.Identifier:
3482
+ case AST_NODE_TYPES13.Identifier:
3763
3483
  return node.name === "undefined";
3764
- case AST_NODE_TYPES14.UnaryExpression:
3765
- return node.operator === "void" && node.argument.type === AST_NODE_TYPES14.Literal;
3766
- case AST_NODE_TYPES14.ObjectExpression:
3484
+ case AST_NODE_TYPES13.UnaryExpression:
3485
+ return node.operator === "void" && node.argument.type === AST_NODE_TYPES13.Literal;
3486
+ case AST_NODE_TYPES13.ObjectExpression:
3767
3487
  return node.properties.length === 0;
3768
- case AST_NODE_TYPES14.ArrayExpression:
3488
+ case AST_NODE_TYPES13.ArrayExpression:
3769
3489
  return node.elements.length === 0;
3770
- case AST_NODE_TYPES14.TSAsExpression:
3490
+ case AST_NODE_TYPES13.TSAsExpression:
3771
3491
  return isSilentExpression(node.expression);
3772
3492
  default:
3773
3493
  return false;
@@ -3775,7 +3495,7 @@ function isSilentExpression(node) {
3775
3495
  }
3776
3496
  function isSilentHandler(handler) {
3777
3497
  const body = handler.body;
3778
- if (body.type !== AST_NODE_TYPES14.BlockStatement) {
3498
+ if (body.type !== AST_NODE_TYPES13.BlockStatement) {
3779
3499
  return isSilentExpression(body);
3780
3500
  }
3781
3501
  if (body.body.length === 0) {
@@ -3783,13 +3503,13 @@ function isSilentHandler(handler) {
3783
3503
  }
3784
3504
  if (body.body.length === 1) {
3785
3505
  const only = body.body[0];
3786
- if (only !== void 0 && only.type === AST_NODE_TYPES14.ReturnStatement) {
3506
+ if (only !== void 0 && only.type === AST_NODE_TYPES13.ReturnStatement) {
3787
3507
  return only.argument === null || isSilentExpression(only.argument);
3788
3508
  }
3789
3509
  }
3790
3510
  return false;
3791
3511
  }
3792
- var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3512
+ var no_silent_promise_catch_default = ESLintUtils21.RuleCreator(
3793
3513
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3794
3514
  )({
3795
3515
  name: "no-silent-promise-catch",
@@ -3814,7 +3534,7 @@ var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3814
3534
  return true;
3815
3535
  }
3816
3536
  let statement = call;
3817
- while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== AST_NODE_TYPES14.VariableDeclaration) {
3537
+ while (statement.parent !== void 0 && statement.parent !== null && !statement.type.endsWith("Statement") && statement.type !== AST_NODE_TYPES13.VariableDeclaration) {
3818
3538
  statement = statement.parent;
3819
3539
  }
3820
3540
  if (sourceCode.getCommentsBefore(statement).some(isExplanatory)) {
@@ -3826,7 +3546,7 @@ var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3826
3546
  };
3827
3547
  return {
3828
3548
  CallExpression(node) {
3829
- if (node.callee.type !== AST_NODE_TYPES14.MemberExpression || node.callee.computed || node.callee.property.type !== AST_NODE_TYPES14.Identifier || node.callee.property.name !== "catch") {
3549
+ if (node.callee.type !== AST_NODE_TYPES13.MemberExpression || node.callee.computed || node.callee.property.type !== AST_NODE_TYPES13.Identifier || node.callee.property.name !== "catch") {
3830
3550
  return;
3831
3551
  }
3832
3552
  if (isBodyParseCall(node.callee.object)) {
@@ -3835,14 +3555,14 @@ var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3835
3555
  if (isTeardownCall(node.callee.object)) {
3836
3556
  return;
3837
3557
  }
3838
- if (node.parent.type === AST_NODE_TYPES14.MemberExpression && node.parent.object === node) {
3558
+ if (node.parent.type === AST_NODE_TYPES13.MemberExpression && node.parent.object === node) {
3839
3559
  return;
3840
3560
  }
3841
3561
  if (node.arguments.length !== 1) {
3842
3562
  return;
3843
3563
  }
3844
3564
  const handler = node.arguments[0];
3845
- if (handler === void 0 || handler.type !== AST_NODE_TYPES14.ArrowFunctionExpression && handler.type !== AST_NODE_TYPES14.FunctionExpression) {
3565
+ if (handler === void 0 || handler.type !== AST_NODE_TYPES13.ArrowFunctionExpression && handler.type !== AST_NODE_TYPES13.FunctionExpression) {
3846
3566
  return;
3847
3567
  }
3848
3568
  if (hasExplanatoryComment(node, handler)) {
@@ -3858,9 +3578,9 @@ var no_silent_promise_catch_default = ESLintUtils22.RuleCreator(
3858
3578
 
3859
3579
  // src/rules/require-fetch-timeout.ts
3860
3580
  import {
3861
- AST_NODE_TYPES as AST_NODE_TYPES15,
3581
+ AST_NODE_TYPES as AST_NODE_TYPES14,
3862
3582
  ASTUtils,
3863
- ESLintUtils as ESLintUtils23
3583
+ ESLintUtils as ESLintUtils22
3864
3584
  } from "@typescript-eslint/utils";
3865
3585
  var CODEMOD_FIXTURE_RE = /[\\/]__testfixtures__[\\/]/;
3866
3586
  var GLOBAL_OBJECTS = /* @__PURE__ */ new Set([
@@ -3878,14 +3598,14 @@ function matchesAnyPattern2(filename, patterns) {
3878
3598
  return false;
3879
3599
  }
3880
3600
  function initProvablyLacksSignal(init) {
3881
- if (init.type !== AST_NODE_TYPES15.ObjectExpression) {
3601
+ if (init.type !== AST_NODE_TYPES14.ObjectExpression) {
3882
3602
  return false;
3883
3603
  }
3884
3604
  for (const prop of init.properties) {
3885
- if (prop.type === AST_NODE_TYPES15.SpreadElement) {
3605
+ if (prop.type === AST_NODE_TYPES14.SpreadElement) {
3886
3606
  return false;
3887
3607
  }
3888
- if (prop.key.type === AST_NODE_TYPES15.Identifier && prop.key.name === "signal" || prop.key.type === AST_NODE_TYPES15.Literal && prop.key.value === "signal") {
3608
+ if (prop.key.type === AST_NODE_TYPES14.Identifier && prop.key.name === "signal" || prop.key.type === AST_NODE_TYPES14.Literal && prop.key.value === "signal") {
3889
3609
  return false;
3890
3610
  }
3891
3611
  if (prop.computed) {
@@ -3895,9 +3615,9 @@ function initProvablyLacksSignal(init) {
3895
3615
  return true;
3896
3616
  }
3897
3617
  function isStringish(node) {
3898
- return node.type === AST_NODE_TYPES15.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES15.TemplateLiteral;
3618
+ return node.type === AST_NODE_TYPES14.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES14.TemplateLiteral;
3899
3619
  }
3900
- var require_fetch_timeout_default = ESLintUtils23.RuleCreator(
3620
+ var require_fetch_timeout_default = ESLintUtils22.RuleCreator(
3901
3621
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
3902
3622
  )({
3903
3623
  name: "require-fetch-timeout",
@@ -3938,10 +3658,10 @@ var require_fetch_timeout_default = ESLintUtils23.RuleCreator(
3938
3658
  return variable === null || variable.defs.length === 0;
3939
3659
  }
3940
3660
  function isGlobalFetchCall2(callee) {
3941
- if (callee.type === AST_NODE_TYPES15.Identifier) {
3661
+ if (callee.type === AST_NODE_TYPES14.Identifier) {
3942
3662
  return callee.name === "fetch" && resolvesToGlobal(callee);
3943
3663
  }
3944
- return callee.type === AST_NODE_TYPES15.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES15.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES15.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3664
+ return callee.type === AST_NODE_TYPES14.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES14.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES14.Identifier && GLOBAL_OBJECTS.has(callee.object.name) && resolvesToGlobal(callee.object);
3945
3665
  }
3946
3666
  return {
3947
3667
  CallExpression(node) {
@@ -3960,103 +3680,16 @@ var require_fetch_timeout_default = ESLintUtils23.RuleCreator(
3960
3680
  }
3961
3681
  });
3962
3682
 
3963
- // src/rules/require-schema-validate-search.ts
3964
- import { AST_NODE_TYPES as AST_NODE_TYPES16, ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
3965
- var VALIDATOR_METHODS = /* @__PURE__ */ new Set([
3966
- "parse",
3967
- "safeParse",
3968
- "decode"
3969
- ]);
3970
- function isConstTypeAnnotation(typeAnnotation) {
3971
- return typeAnnotation.type === AST_NODE_TYPES16.TSTypeReference && typeAnnotation.typeName.type === AST_NODE_TYPES16.Identifier && typeAnnotation.typeName.name === "const";
3972
- }
3973
- function isValidatorCall(node) {
3974
- return node.callee.type === AST_NODE_TYPES16.MemberExpression && !node.callee.computed && node.callee.property.type === AST_NODE_TYPES16.Identifier && VALIDATOR_METHODS.has(node.callee.property.name);
3975
- }
3976
- function findCastExpression(node, insideValidatorArg) {
3977
- if ((node.type === AST_NODE_TYPES16.TSAsExpression || node.type === AST_NODE_TYPES16.TSTypeAssertion) && !isConstTypeAnnotation(node.typeAnnotation) && !insideValidatorArg) {
3978
- return node;
3979
- }
3980
- if (node.type === AST_NODE_TYPES16.CallExpression && isValidatorCall(node)) {
3981
- const inCallee = findCastExpression(node.callee, insideValidatorArg);
3982
- if (inCallee !== null) {
3983
- return inCallee;
3984
- }
3985
- for (const arg of node.arguments) {
3986
- const found = findCastExpression(arg, true);
3987
- if (found !== null) {
3988
- return found;
3989
- }
3990
- }
3991
- return null;
3992
- }
3993
- for (const key of Object.keys(node)) {
3994
- if (key === "parent") {
3995
- continue;
3996
- }
3997
- const value = node[key];
3998
- const children = Array.isArray(value) ? value : [value];
3999
- for (const child of children) {
4000
- if (child !== null && typeof child === "object" && "type" in child && typeof child.type === "string") {
4001
- const found = findCastExpression(
4002
- child,
4003
- insideValidatorArg
4004
- );
4005
- if (found !== null) {
4006
- return found;
4007
- }
4008
- }
4009
- }
4010
- }
4011
- return null;
4012
- }
4013
- var require_schema_validate_search_default = ESLintUtils24.RuleCreator(
4014
- (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4015
- )({
4016
- name: "require-schema-validate-search",
4017
- meta: {
4018
- type: "problem",
4019
- docs: {
4020
- description: "Disallow `as` casts inside hand-rolled `validateSearch` functions; use a schema validator (e.g. zodValidator) so search params are validated at runtime."
4021
- },
4022
- schema: [],
4023
- messages: {
4024
- castInValidateSearch: "This `validateSearch` asserts the search-param shape with `as` instead of validating it \u2014 malformed query params flow through typed as clean data. Use a schema validator (e.g. `zodValidator(searchSchema)` or `searchSchema.parse`) instead of casting."
4025
- }
4026
- },
4027
- defaultOptions: [],
4028
- create(context) {
4029
- if (isTestFile(context.filename)) {
4030
- return {};
4031
- }
4032
- return {
4033
- Property(node) {
4034
- const isValidateSearchKey = !node.computed && node.key.type === AST_NODE_TYPES16.Identifier && node.key.name === "validateSearch" || node.key.type === AST_NODE_TYPES16.Literal && node.key.value === "validateSearch";
4035
- if (!isValidateSearchKey) {
4036
- return;
4037
- }
4038
- if (node.value.type !== AST_NODE_TYPES16.ArrowFunctionExpression && node.value.type !== AST_NODE_TYPES16.FunctionExpression) {
4039
- return;
4040
- }
4041
- const cast = findCastExpression(node.value.body, false);
4042
- if (cast !== null) {
4043
- context.report({ node: cast, messageId: "castInValidateSearch" });
4044
- }
4045
- }
4046
- };
4047
- }
4048
- });
4049
-
4050
- // src/rules/no-fat-try-blocks.ts
4051
- import {
4052
- ESLintUtils as ESLintUtils25,
4053
- AST_NODE_TYPES as AST_NODE_TYPES17
4054
- } from "@typescript-eslint/utils";
4055
- var MAX_TRY_BODY_STATEMENTS = 3;
4056
- var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set([
4057
- AST_NODE_TYPES17.FunctionDeclaration,
4058
- AST_NODE_TYPES17.FunctionExpression,
4059
- AST_NODE_TYPES17.ArrowFunctionExpression
3683
+ // src/rules/no-fat-try-blocks.ts
3684
+ import {
3685
+ ESLintUtils as ESLintUtils23,
3686
+ AST_NODE_TYPES as AST_NODE_TYPES15
3687
+ } from "@typescript-eslint/utils";
3688
+ var MAX_TRY_BODY_STATEMENTS = 3;
3689
+ var NESTED_FUNCTION_TYPES = /* @__PURE__ */ new Set([
3690
+ AST_NODE_TYPES15.FunctionDeclaration,
3691
+ AST_NODE_TYPES15.FunctionExpression,
3692
+ AST_NODE_TYPES15.ArrowFunctionExpression
4060
3693
  ]);
4061
3694
  var PURE_METHODS = /* @__PURE__ */ new Set([
4062
3695
  "map",
@@ -4149,25 +3782,25 @@ var PURE_CONSTRUCTORS = /* @__PURE__ */ new Set([
4149
3782
  "Response",
4150
3783
  "AbortController"
4151
3784
  ]);
4152
- function isNode4(value) {
3785
+ function isNode3(value) {
4153
3786
  return typeof value === "object" && value !== null && typeof value.type === "string";
4154
3787
  }
4155
3788
  function isPureCall(node) {
4156
3789
  const callee = node.callee;
4157
- if (callee.type !== AST_NODE_TYPES17.MemberExpression) {
3790
+ if (callee.type !== AST_NODE_TYPES15.MemberExpression) {
4158
3791
  return false;
4159
3792
  }
4160
3793
  const property = callee.property;
4161
- if (property.type !== AST_NODE_TYPES17.Identifier) {
3794
+ if (property.type !== AST_NODE_TYPES15.Identifier) {
4162
3795
  return false;
4163
3796
  }
4164
- if (callee.object.type === AST_NODE_TYPES17.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
3797
+ if (callee.object.type === AST_NODE_TYPES15.Identifier && PURE_NAMESPACES.has(callee.object.name)) {
4165
3798
  return true;
4166
3799
  }
4167
3800
  return PURE_METHODS.has(property.name);
4168
3801
  }
4169
3802
  function isPureNew(node) {
4170
- return node.callee.type === AST_NODE_TYPES17.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
3803
+ return node.callee.type === AST_NODE_TYPES15.Identifier && PURE_CONSTRUCTORS.has(node.callee.name);
4171
3804
  }
4172
3805
  function subtreeMatches(stmt, predicate) {
4173
3806
  let found = false;
@@ -4189,11 +3822,11 @@ function subtreeMatches(stmt, predicate) {
4189
3822
  const value = current[key];
4190
3823
  if (Array.isArray(value)) {
4191
3824
  for (const child of value) {
4192
- if (isNode4(child)) {
3825
+ if (isNode3(child)) {
4193
3826
  visit(child);
4194
3827
  }
4195
3828
  }
4196
- } else if (isNode4(value)) {
3829
+ } else if (isNode3(value)) {
4197
3830
  visit(value);
4198
3831
  }
4199
3832
  if (found) {
@@ -4204,20 +3837,20 @@ function subtreeMatches(stmt, predicate) {
4204
3837
  visit(stmt);
4205
3838
  return found;
4206
3839
  }
4207
- var hasAwait = (node) => subtreeMatches(node, (n) => n.type === AST_NODE_TYPES17.AwaitExpression);
3840
+ var hasAwait = (node) => subtreeMatches(node, (n) => n.type === AST_NODE_TYPES15.AwaitExpression);
4208
3841
  var hasThrowingCallOrNew = (node) => subtreeMatches(
4209
3842
  node,
4210
- (n) => n.type === AST_NODE_TYPES17.CallExpression && !isPureCall(n) || n.type === AST_NODE_TYPES17.NewExpression && !isPureNew(n)
3843
+ (n) => n.type === AST_NODE_TYPES15.CallExpression && !isPureCall(n) || n.type === AST_NODE_TYPES15.NewExpression && !isPureNew(n)
4211
3844
  );
4212
3845
  function unwrap2(expr) {
4213
3846
  let current = expr;
4214
- while (current.type === AST_NODE_TYPES17.ChainExpression || current.type === AST_NODE_TYPES17.TSNonNullExpression) {
3847
+ while (current.type === AST_NODE_TYPES15.ChainExpression || current.type === AST_NODE_TYPES15.TSNonNullExpression) {
4215
3848
  current = current.expression;
4216
3849
  }
4217
3850
  return current;
4218
3851
  }
4219
3852
  function isBareCallStatement(stmt) {
4220
- return stmt.type === AST_NODE_TYPES17.ExpressionStatement && unwrap2(stmt.expression).type === AST_NODE_TYPES17.CallExpression;
3853
+ return stmt.type === AST_NODE_TYPES15.ExpressionStatement && unwrap2(stmt.expression).type === AST_NODE_TYPES15.CallExpression;
4221
3854
  }
4222
3855
  function canThrow(stmt) {
4223
3856
  if (hasAwait(stmt)) {
@@ -4226,10 +3859,10 @@ function canThrow(stmt) {
4226
3859
  if (isBareCallStatement(stmt)) {
4227
3860
  return false;
4228
3861
  }
4229
- if (stmt.type === AST_NODE_TYPES17.BlockStatement) {
3862
+ if (stmt.type === AST_NODE_TYPES15.BlockStatement) {
4230
3863
  return stmt.body.some(canThrow);
4231
3864
  }
4232
- if (stmt.type === AST_NODE_TYPES17.IfStatement) {
3865
+ if (stmt.type === AST_NODE_TYPES15.IfStatement) {
4233
3866
  return hasThrowingCallOrNew(stmt.test) || canThrow(stmt.consequent) || stmt.alternate !== null && canThrow(stmt.alternate);
4234
3867
  }
4235
3868
  return hasThrowingCallOrNew(stmt);
@@ -4240,9 +3873,9 @@ function handlerRethrows(handler) {
4240
3873
  }
4241
3874
  const body = handler.body.body;
4242
3875
  const last = body[body.length - 1];
4243
- return last !== void 0 && last.type === AST_NODE_TYPES17.ThrowStatement;
3876
+ return last !== void 0 && last.type === AST_NODE_TYPES15.ThrowStatement;
4244
3877
  }
4245
- var no_fat_try_blocks_default = ESLintUtils25.RuleCreator(
3878
+ var no_fat_try_blocks_default = ESLintUtils23.RuleCreator(
4246
3879
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4247
3880
  )({
4248
3881
  name: "no-fat-try-blocks",
@@ -4286,7 +3919,7 @@ var no_fat_try_blocks_default = ESLintUtils25.RuleCreator(
4286
3919
  });
4287
3920
 
4288
3921
  // src/rules/no-secret-in-log.ts
4289
- import { ESLintUtils as ESLintUtils26 } from "@typescript-eslint/utils";
3922
+ import { ESLintUtils as ESLintUtils24 } from "@typescript-eslint/utils";
4290
3923
 
4291
3924
  // src/rules/_secret_names.ts
4292
3925
  var SECRET_WORDS = /* @__PURE__ */ new Set([
@@ -4548,7 +4181,7 @@ function propertyKeyName2(prop) {
4548
4181
  }
4549
4182
  return null;
4550
4183
  }
4551
- var no_secret_in_log_default = ESLintUtils26.RuleCreator(
4184
+ var no_secret_in_log_default = ESLintUtils24.RuleCreator(
4552
4185
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4553
4186
  )({
4554
4187
  name: "no-secret-in-log",
@@ -4624,46 +4257,46 @@ var no_secret_in_log_default = ESLintUtils26.RuleCreator(
4624
4257
  }
4625
4258
  });
4626
4259
 
4627
- // src/rules/no-unsafe-cast.ts
4628
- import { ESLintUtils as ESLintUtils27 } from "@typescript-eslint/utils";
4629
- import { AST_NODE_TYPES as AST_NODE_TYPES18 } from "@typescript-eslint/utils";
4630
- function isAnyAnnotation(node) {
4631
- return node.type === AST_NODE_TYPES18.TSAnyKeyword;
4632
- }
4633
- function isConstAssertion(typeAnnotation) {
4634
- return typeAnnotation.type === AST_NODE_TYPES18.TSTypeReference && typeAnnotation.typeName.type === AST_NODE_TYPES18.Identifier && typeAnnotation.typeName.name === "const";
4260
+ // src/rules/no-unsafe-mock-casting.ts
4261
+ import { ESLintUtils as ESLintUtils25 } from "@typescript-eslint/utils";
4262
+ import { AST_NODE_TYPES as AST_NODE_TYPES16 } from "@typescript-eslint/utils";
4263
+ function isMockTypeReference(node) {
4264
+ if (node.type !== AST_NODE_TYPES16.TSTypeReference) {
4265
+ return false;
4266
+ }
4267
+ const typeName = node.typeName;
4268
+ if (typeName.type === AST_NODE_TYPES16.Identifier) {
4269
+ const name = typeName.name;
4270
+ return name === "Mock" || name === "MockInstance" || name === "SpyInstance";
4271
+ }
4272
+ if (typeName.type === AST_NODE_TYPES16.TSQualifiedName) {
4273
+ const rightName = typeName.right.name;
4274
+ return rightName === "Mock" || rightName === "MockInstance" || rightName === "SpyInstance";
4275
+ }
4276
+ return false;
4635
4277
  }
4636
- var no_unsafe_cast_default = ESLintUtils27.RuleCreator(
4278
+ var no_unsafe_mock_casting_default = ESLintUtils25.RuleCreator(
4637
4279
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4638
4280
  )({
4639
- name: "no-unsafe-cast",
4281
+ name: "no-unsafe-mock-casting",
4640
4282
  meta: {
4641
4283
  type: "problem",
4642
4284
  docs: {
4643
- description: "Disallow `as any`/`<any>` casts and `as unknown as T` double-casts, which fully disable type checking."
4285
+ description: "Disallow casting to mock types like `jest.Mock` or `vi.Mock`. Use `vi.mocked()` or `jest.mocked()` instead."
4644
4286
  },
4645
4287
  schema: [],
4646
4288
  messages: {
4647
- asAny: "`as any` disables type checking on this value. Narrow with a type guard, model the shape, or cast to a specific type instead.",
4648
- doubleCast: "`as unknown as T` double-cast bypasses the compiler's structural check. Prefer a runtime validator (e.g. a zod schema) or an accurate type at the boundary."
4289
+ unsafeMockCast: "Do not cast to a Mock type. Use `vi.mocked(fn)` or `jest.mocked(fn)` instead to preserve type safety."
4649
4290
  }
4650
4291
  },
4651
4292
  defaultOptions: [],
4652
4293
  create(context) {
4653
- if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) {
4294
+ if (isGeneratedFile(context.filename, context.sourceCode.text)) {
4654
4295
  return {};
4655
4296
  }
4656
4297
  function checkAssertion(node) {
4657
- if (isConstAssertion(node.typeAnnotation)) {
4658
- return;
4659
- }
4660
- if (isAnyAnnotation(node.typeAnnotation)) {
4661
- context.report({ node, messageId: "asAny" });
4662
- return;
4663
- }
4664
- const inner = node.expression;
4665
- if (inner.type === AST_NODE_TYPES18.TSAsExpression || inner.type === AST_NODE_TYPES18.TSTypeAssertion) {
4666
- context.report({ node, messageId: "doubleCast" });
4298
+ if (isMockTypeReference(node.typeAnnotation)) {
4299
+ context.report({ node, messageId: "unsafeMockCast" });
4667
4300
  }
4668
4301
  }
4669
4302
  return {
@@ -4675,8 +4308,8 @@ var no_unsafe_cast_default = ESLintUtils27.RuleCreator(
4675
4308
 
4676
4309
  // src/rules/prefer-string-literal-union.ts
4677
4310
  import {
4678
- ESLintUtils as ESLintUtils28,
4679
- AST_NODE_TYPES as AST_NODE_TYPES19
4311
+ ESLintUtils as ESLintUtils26,
4312
+ AST_NODE_TYPES as AST_NODE_TYPES17
4680
4313
  } from "@typescript-eslint/utils";
4681
4314
  import * as ts from "typescript";
4682
4315
  var CHOICE_TOKENS = /* @__PURE__ */ new Set([
@@ -4720,19 +4353,19 @@ function isChoiceLikeName(name) {
4720
4353
  return CHOICE_TOKENS.has(lastWord(name));
4721
4354
  }
4722
4355
  function keyName(key) {
4723
- if (key.type === AST_NODE_TYPES19.Identifier) {
4356
+ if (key.type === AST_NODE_TYPES17.Identifier) {
4724
4357
  return key.name;
4725
4358
  }
4726
- if (key.type === AST_NODE_TYPES19.Literal && typeof key.value === "string") {
4359
+ if (key.type === AST_NODE_TYPES17.Literal && typeof key.value === "string") {
4727
4360
  return key.value;
4728
4361
  }
4729
4362
  return null;
4730
4363
  }
4731
4364
  function isStringLiteralMember(t) {
4732
- return t.type === AST_NODE_TYPES19.TSLiteralType && t.literal.type === AST_NODE_TYPES19.Literal && typeof t.literal.value === "string";
4365
+ return t.type === AST_NODE_TYPES17.TSLiteralType && t.literal.type === AST_NODE_TYPES17.Literal && typeof t.literal.value === "string";
4733
4366
  }
4734
4367
  function isStringLiteralUnion(node) {
4735
- if (node?.type !== AST_NODE_TYPES19.TSUnionType) {
4368
+ if (node?.type !== AST_NODE_TYPES17.TSUnionType) {
4736
4369
  return false;
4737
4370
  }
4738
4371
  return node.types.filter(isStringLiteralMember).length >= MIN_CLUSTER_SIZE;
@@ -4761,12 +4394,12 @@ function bindingSourceExpression(decl) {
4761
4394
  return ts.isForOfStatement(node) ? node.expression : node.initializer;
4762
4395
  }
4763
4396
  function refKey(node) {
4764
- if (node.type === AST_NODE_TYPES19.Identifier) {
4397
+ if (node.type === AST_NODE_TYPES17.Identifier) {
4765
4398
  return node.name;
4766
4399
  }
4767
- if (node.type === AST_NODE_TYPES19.MemberExpression && !node.computed) {
4400
+ if (node.type === AST_NODE_TYPES17.MemberExpression && !node.computed) {
4768
4401
  const inner = refKey(node.object);
4769
- if (inner === null || node.property.type !== AST_NODE_TYPES19.Identifier) {
4402
+ if (inner === null || node.property.type !== AST_NODE_TYPES17.Identifier) {
4770
4403
  return null;
4771
4404
  }
4772
4405
  return `${inner}.${node.property.name}`;
@@ -4774,12 +4407,12 @@ function refKey(node) {
4774
4407
  return null;
4775
4408
  }
4776
4409
  function strLiteral(node) {
4777
- if (node.type === AST_NODE_TYPES19.Literal && typeof node.value === "string") {
4410
+ if (node.type === AST_NODE_TYPES17.Literal && typeof node.value === "string") {
4778
4411
  return node.value;
4779
4412
  }
4780
4413
  return null;
4781
4414
  }
4782
- var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
4415
+ var prefer_string_literal_union_default = ESLintUtils26.RuleCreator(
4783
4416
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
4784
4417
  )({
4785
4418
  name: "prefer-string-literal-union",
@@ -4817,7 +4450,7 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
4817
4450
  );
4818
4451
  let services;
4819
4452
  try {
4820
- services = ESLintUtils28.getParserServices(context);
4453
+ services = ESLintUtils26.getParserServices(context);
4821
4454
  } catch {
4822
4455
  services = null;
4823
4456
  }
@@ -4929,7 +4562,7 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
4929
4562
  containersWithUnion.add(container);
4930
4563
  return;
4931
4564
  }
4932
- if (typeNode?.type !== AST_NODE_TYPES19.TSStringKeyword) {
4565
+ if (typeNode?.type !== AST_NODE_TYPES17.TSStringKeyword) {
4933
4566
  return;
4934
4567
  }
4935
4568
  const name = keyName(key);
@@ -5017,10 +4650,10 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
5017
4650
  }
5018
4651
  };
5019
4652
  function refKeyText(node) {
5020
- if (node.type === AST_NODE_TYPES19.BinaryExpression) {
4653
+ if (node.type === AST_NODE_TYPES17.BinaryExpression) {
5021
4654
  return refKey(node.left) ?? refKey(node.right) ?? "value";
5022
4655
  }
5023
- if (node.type === AST_NODE_TYPES19.SwitchStatement) {
4656
+ if (node.type === AST_NODE_TYPES17.SwitchStatement) {
5024
4657
  return refKey(node.discriminant) ?? "value";
5025
4658
  }
5026
4659
  return "value";
@@ -5028,146 +4661,93 @@ var prefer_string_literal_union_default = ESLintUtils28.RuleCreator(
5028
4661
  }
5029
4662
  });
5030
4663
 
5031
- // src/rules/single-public-export.ts
5032
- import { ESLintUtils as ESLintUtils29, AST_NODE_TYPES as AST_NODE_TYPES20 } from "@typescript-eslint/utils";
5033
- var JUNK_DRAWER_STEMS = /* @__PURE__ */ new Set([
5034
- "util",
5035
- "utils",
5036
- "helper",
5037
- "helpers",
5038
- "common",
5039
- "constant",
5040
- "constants",
5041
- "type",
5042
- "types",
5043
- "model",
5044
- "models",
5045
- "shared",
5046
- "misc"
5047
- ]);
5048
- var CONVENTIONAL_BUCKET_EXPORTS = /* @__PURE__ */ new Set(["cn"]);
5049
- var ACRONYM_OVERRIDES = [
5050
- [/OAuth/g, "Oauth"],
5051
- [/GraphQL/g, "Graphql"],
5052
- [/gRPC/g, "Grpc"]
5053
- ];
5054
- var CAMEL_BOUNDARY_RE = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;
5055
- var TEST_FILE_RE = /\.(test|spec)\.[cm]?[jt]sx?$/i;
5056
- var SCRIPT_EXT_RE = /\.[cm]?[jt]sx?$/i;
5057
- var basename = (filename) => filename.split(/[/\\]/).pop() ?? filename;
5058
- var stemOf = (base) => base.replace(SCRIPT_EXT_RE, "");
5059
- var kebabCase2 = (name) => {
5060
- let normalized = name;
5061
- for (const [pattern, replacement] of ACRONYM_OVERRIDES) {
5062
- normalized = normalized.replace(pattern, replacement);
5063
- }
5064
- return normalized.replace(CAMEL_BOUNDARY_RE, "-").toLowerCase();
5065
- };
5066
- var isFunctionExpression = (node) => node !== null && (node.type === AST_NODE_TYPES20.ArrowFunctionExpression || node.type === AST_NODE_TYPES20.FunctionExpression);
5067
- var functionConstName = (decl) => {
5068
- if (decl.declarations.length !== 1) return null;
5069
- const [declarator] = decl.declarations;
5070
- if (declarator === void 0) return null;
5071
- if (declarator.id.type !== AST_NODE_TYPES20.Identifier) return null;
5072
- if (!isFunctionExpression(declarator.init)) return null;
5073
- return declarator.id.name;
5074
- };
5075
- var summarizeExports = (body) => {
5076
- let names = 0;
5077
- let hasReExport = false;
5078
- let candidate = null;
5079
- const addCandidate = (name, node) => {
5080
- names += 1;
5081
- candidate = { name, node };
5082
- };
5083
- for (const statement of body) {
5084
- switch (statement.type) {
5085
- case AST_NODE_TYPES20.ExportAllDeclaration:
5086
- hasReExport = true;
5087
- break;
5088
- case AST_NODE_TYPES20.ExportDefaultDeclaration: {
5089
- names += 1;
5090
- const decl = statement.declaration;
5091
- if (decl.type === AST_NODE_TYPES20.FunctionDeclaration && decl.id !== null) {
5092
- candidate = { name: decl.id.name, node: statement };
5093
- } else if (decl.type === AST_NODE_TYPES20.ClassDeclaration && decl.id !== null) {
5094
- candidate = { name: decl.id.name, node: statement };
5095
- }
5096
- break;
5097
- }
5098
- case AST_NODE_TYPES20.ExportNamedDeclaration: {
5099
- if (statement.source !== null) {
5100
- hasReExport = true;
5101
- break;
5102
- }
5103
- const decl = statement.declaration;
5104
- if (decl === null) {
5105
- names += statement.specifiers.length;
5106
- break;
5107
- }
5108
- switch (decl.type) {
5109
- case AST_NODE_TYPES20.FunctionDeclaration:
5110
- if (decl.id !== null) addCandidate(decl.id.name, statement);
5111
- else names += 1;
5112
- break;
5113
- case AST_NODE_TYPES20.ClassDeclaration:
5114
- if (decl.id !== null) addCandidate(decl.id.name, statement);
5115
- else names += 1;
5116
- break;
5117
- case AST_NODE_TYPES20.VariableDeclaration: {
5118
- const fnName = functionConstName(decl);
5119
- if (fnName !== null && decl.declarations.length === 1) {
5120
- addCandidate(fnName, statement);
5121
- } else {
5122
- names += decl.declarations.length;
5123
- }
5124
- break;
5125
- }
5126
- default:
5127
- names += 1;
5128
- }
5129
- break;
5130
- }
5131
- default:
5132
- break;
5133
- }
5134
- }
5135
- return { names, hasReExport, candidate };
5136
- };
5137
- var single_public_export_default = ESLintUtils29.RuleCreator(
5138
- (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
4664
+ // src/rules/prefer-zod-enum.ts
4665
+ import {
4666
+ AST_NODE_TYPES as AST_NODE_TYPES18,
4667
+ ESLintUtils as ESLintUtils27
4668
+ } from "@typescript-eslint/utils";
4669
+ function isZodModule(source) {
4670
+ return /(^|[/@-])zod([/-]|$)/.test(source);
4671
+ }
4672
+ var prefer_zod_enum_default = ESLintUtils27.RuleCreator(
4673
+ (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
5139
4674
  )({
5140
- name: "single-public-export",
4675
+ name: "prefer-zod-enum",
5141
4676
  meta: {
5142
4677
  type: "suggestion",
5143
4678
  docs: {
5144
- description: "A junk-drawer module stem (`utils`, `helpers`, `types`, ...) with a single public function/class/const export should be renamed after that export."
4679
+ description: "Prefer z.enum([...]) over z.union([z.literal(...), ...]) for string choices"
5145
4680
  },
4681
+ fixable: "code",
5146
4682
  schema: [],
5147
4683
  messages: {
5148
- renameJunkDrawer: "Module stem `{{stem}}` is a generic junk-drawer name; its sole public export is `{{name}}` \u2014 rename the file to `{{expected}}.ts` to describe its responsibility."
4684
+ preferEnum: "Use `z.enum([...])` instead of a union of string-literal schemas."
5149
4685
  }
5150
4686
  },
5151
4687
  defaultOptions: [],
5152
4688
  create(context) {
5153
- const base = basename(context.filename);
5154
- if (base.endsWith(".d.ts")) return {};
5155
- if (TEST_FILE_RE.test(base)) return {};
5156
- if (isTestFile(context.filename)) return {};
5157
- const stem3 = stemOf(base);
5158
- if (!JUNK_DRAWER_STEMS.has(stem3.toLowerCase())) return {};
4689
+ const sourceCode = context.sourceCode;
4690
+ const zodNamespaces = /* @__PURE__ */ new Set();
4691
+ function enumValues(node) {
4692
+ const callee = node.callee;
4693
+ if (callee.type !== AST_NODE_TYPES18.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES18.Identifier || !zodNamespaces.has(callee.object.name) || callee.property.type !== AST_NODE_TYPES18.Identifier || callee.property.name !== "union" || node.arguments.length !== 1) {
4694
+ return null;
4695
+ }
4696
+ const argument = node.arguments[0];
4697
+ if (argument === void 0 || argument.type !== AST_NODE_TYPES18.ArrayExpression || argument.elements.length === 0) {
4698
+ return null;
4699
+ }
4700
+ const values = [];
4701
+ for (const element of argument.elements) {
4702
+ if (element === null || element.type !== AST_NODE_TYPES18.CallExpression || element.arguments.length !== 1 || element.callee.type !== AST_NODE_TYPES18.MemberExpression || element.callee.computed || element.callee.object.type !== AST_NODE_TYPES18.Identifier || !zodNamespaces.has(element.callee.object.name) || element.callee.property.type !== AST_NODE_TYPES18.Identifier || element.callee.property.name !== "literal") {
4703
+ return null;
4704
+ }
4705
+ const value = element.arguments[0];
4706
+ if (value === void 0 || value.type !== AST_NODE_TYPES18.Literal || typeof value.value !== "string") {
4707
+ return null;
4708
+ }
4709
+ values.push(value);
4710
+ }
4711
+ return values;
4712
+ }
4713
+ function buildFix(node, values) {
4714
+ const argument = node.arguments[0];
4715
+ if (argument === void 0 || argument.type !== AST_NODE_TYPES18.ArrayExpression || sourceCode.getCommentsInside(argument).length > 0) {
4716
+ return void 0;
4717
+ }
4718
+ const callee = node.callee;
4719
+ if (callee.type !== AST_NODE_TYPES18.MemberExpression || callee.property.type !== AST_NODE_TYPES18.Identifier) {
4720
+ return void 0;
4721
+ }
4722
+ return (fixer) => [
4723
+ fixer.replaceText(callee.property, "enum"),
4724
+ fixer.replaceText(
4725
+ argument,
4726
+ `[${values.map((value) => sourceCode.getText(value)).join(", ")}]`
4727
+ )
4728
+ ];
4729
+ }
5159
4730
  return {
5160
- Program(node) {
5161
- const { names, hasReExport, candidate } = summarizeExports(node.body);
5162
- if (hasReExport) return;
5163
- if (names !== 1 || candidate === null) return;
5164
- if (CONVENTIONAL_BUCKET_EXPORTS.has(candidate.name)) return;
5165
- const expected = kebabCase2(candidate.name);
5166
- if (stem3 === expected) return;
4731
+ ImportDeclaration(node) {
4732
+ if (!isZodModule(node.source.value)) {
4733
+ return;
4734
+ }
4735
+ for (const specifier of node.specifiers) {
4736
+ if (specifier.type === AST_NODE_TYPES18.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES18.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES18.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES18.Identifier && specifier.imported.name === "z") {
4737
+ zodNamespaces.add(specifier.local.name);
4738
+ }
4739
+ }
4740
+ },
4741
+ CallExpression(node) {
4742
+ const values = enumValues(node);
4743
+ if (values === null) {
4744
+ return;
4745
+ }
4746
+ const fix = buildFix(node, values);
5167
4747
  context.report({
5168
- node: candidate.node,
5169
- messageId: "renameJunkDrawer",
5170
- data: { stem: stem3, name: candidate.name, expected }
4748
+ node,
4749
+ messageId: "preferEnum",
4750
+ ...fix === void 0 ? {} : { fix }
5171
4751
  });
5172
4752
  }
5173
4753
  };
@@ -5175,10 +4755,10 @@ var single_public_export_default = ESLintUtils29.RuleCreator(
5175
4755
  });
5176
4756
 
5177
4757
  // src/rules/no-offset-pagination.ts
5178
- import { ESLintUtils as ESLintUtils30 } from "@typescript-eslint/utils";
4758
+ import { ESLintUtils as ESLintUtils28 } from "@typescript-eslint/utils";
5179
4759
 
5180
4760
  // src/rules/_sql.ts
5181
- import { AST_NODE_TYPES as AST_NODE_TYPES21 } from "@typescript-eslint/utils";
4761
+ import { AST_NODE_TYPES as AST_NODE_TYPES19 } from "@typescript-eslint/utils";
5182
4762
  function stripSqlNoise(text) {
5183
4763
  const out = [...text];
5184
4764
  const n = text.length;
@@ -5239,13 +4819,13 @@ function stripSqlNoise(text) {
5239
4819
  var SUBSTITUTION_MARKER = "?";
5240
4820
  function sqlTextOf(node) {
5241
4821
  switch (node.type) {
5242
- case AST_NODE_TYPES21.Literal:
4822
+ case AST_NODE_TYPES19.Literal:
5243
4823
  return typeof node.value === "string" ? node.value : null;
5244
- case AST_NODE_TYPES21.TemplateLiteral:
4824
+ case AST_NODE_TYPES19.TemplateLiteral:
5245
4825
  return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join(SUBSTITUTION_MARKER);
5246
- case AST_NODE_TYPES21.TaggedTemplateExpression:
4826
+ case AST_NODE_TYPES19.TaggedTemplateExpression:
5247
4827
  return sqlTextOf(node.quasi);
5248
- case AST_NODE_TYPES21.BinaryExpression: {
4828
+ case AST_NODE_TYPES19.BinaryExpression: {
5249
4829
  if (node.operator !== "+") {
5250
4830
  return null;
5251
4831
  }
@@ -5253,7 +4833,7 @@ function sqlTextOf(node) {
5253
4833
  const right = sqlTextOf(node.right);
5254
4834
  return left !== null && right !== null ? left + right : null;
5255
4835
  }
5256
- case AST_NODE_TYPES21.ArrayExpression: {
4836
+ case AST_NODE_TYPES19.ArrayExpression: {
5257
4837
  const parts = [];
5258
4838
  for (const element of node.elements) {
5259
4839
  if (element === null) {
@@ -5273,7 +4853,7 @@ function sqlTextOf(node) {
5273
4853
  }
5274
4854
  function isJoinedFragmentArray(node) {
5275
4855
  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;
4856
+ return parent?.type === AST_NODE_TYPES19.MemberExpression && parent.object === node && !parent.computed && parent.property.type === AST_NODE_TYPES19.Identifier && parent.property.name === "join" && parent.parent?.type === AST_NODE_TYPES19.CallExpression;
5277
4857
  }
5278
4858
  function markConsumed(node, consumed) {
5279
4859
  consumed.add(node);
@@ -5323,7 +4903,7 @@ function createSqlListener(handler) {
5323
4903
  // src/rules/no-offset-pagination.ts
5324
4904
  var OFFSET_PAGINATION = /\bOFFSET\s+(?:%s|%\(\w+\)s|\?\d*|:\w+|@\w+|\$\d+|\d+)/i;
5325
4905
  var OFFSET_GATE = /offset/i;
5326
- var no_offset_pagination_default = ESLintUtils30.RuleCreator(
4906
+ var no_offset_pagination_default = ESLintUtils28.RuleCreator(
5327
4907
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5328
4908
  )({
5329
4909
  name: "no-offset-pagination",
@@ -5352,15 +4932,15 @@ var no_offset_pagination_default = ESLintUtils30.RuleCreator(
5352
4932
  });
5353
4933
 
5354
4934
  // src/rules/no-positional-tuple-return.ts
5355
- import { AST_NODE_TYPES as AST_NODE_TYPES22, ESLintUtils as ESLintUtils31 } from "@typescript-eslint/utils";
4935
+ import { AST_NODE_TYPES as AST_NODE_TYPES20, ESLintUtils as ESLintUtils29 } from "@typescript-eslint/utils";
5356
4936
  var MIN_ELEMENTS = 2;
5357
4937
  var ACCESSOR_PAIR_LENGTH = 2;
5358
4938
  var AWAITABLE_TYPES = /* @__PURE__ */ new Set(["Promise", "PromiseLike", "Awaited"]);
5359
4939
  function tupleReturnType(node) {
5360
- if (node.type === AST_NODE_TYPES22.TSTupleType) {
4940
+ if (node.type === AST_NODE_TYPES20.TSTupleType) {
5361
4941
  return node;
5362
4942
  }
5363
- if (node.type === AST_NODE_TYPES22.TSTypeReference && node.typeName.type === AST_NODE_TYPES22.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
4943
+ if (node.type === AST_NODE_TYPES20.TSTypeReference && node.typeName.type === AST_NODE_TYPES20.Identifier && AWAITABLE_TYPES.has(node.typeName.name)) {
5364
4944
  const argument = node.typeArguments?.params[0];
5365
4945
  return argument === void 0 ? null : tupleReturnType(argument);
5366
4946
  }
@@ -5374,30 +4954,30 @@ function isPermittedTuple(tuple, sourceCode) {
5374
4954
  if (elements.length < MIN_ELEMENTS) {
5375
4955
  return true;
5376
4956
  }
5377
- if (elements.some((element) => element.type === AST_NODE_TYPES22.TSRestType)) {
4957
+ if (elements.some((element) => element.type === AST_NODE_TYPES20.TSRestType)) {
5378
4958
  return true;
5379
4959
  }
5380
- if (elements.some((element) => element.type === AST_NODE_TYPES22.TSNamedTupleMember)) {
4960
+ if (elements.some((element) => element.type === AST_NODE_TYPES20.TSNamedTupleMember)) {
5381
4961
  return true;
5382
4962
  }
5383
- if (elements[0]?.type === AST_NODE_TYPES22.TSLiteralType) {
4963
+ if (elements[0]?.type === AST_NODE_TYPES20.TSLiteralType) {
5384
4964
  return true;
5385
4965
  }
5386
- if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === AST_NODE_TYPES22.TSFunctionType)) {
4966
+ if (elements.length === ACCESSOR_PAIR_LENGTH && elements.some((element) => element.type === AST_NODE_TYPES20.TSFunctionType)) {
5387
4967
  return true;
5388
4968
  }
5389
4969
  const texts = new Set(elements.map((element) => normalizedText(sourceCode, element)));
5390
4970
  return texts.size === 1;
5391
4971
  }
5392
4972
  function functionName(node) {
5393
- if (node.type === AST_NODE_TYPES22.FunctionDeclaration) {
4973
+ if (node.type === AST_NODE_TYPES20.FunctionDeclaration) {
5394
4974
  return node.id?.name ?? null;
5395
4975
  }
5396
4976
  const parent = node.parent;
5397
- if (parent?.type === AST_NODE_TYPES22.VariableDeclarator && parent.id.type === AST_NODE_TYPES22.Identifier) {
4977
+ if (parent?.type === AST_NODE_TYPES20.VariableDeclarator && parent.id.type === AST_NODE_TYPES20.Identifier) {
5398
4978
  return parent.id.name;
5399
4979
  }
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) {
4980
+ if ((parent?.type === AST_NODE_TYPES20.MethodDefinition || parent?.type === AST_NODE_TYPES20.PropertyDefinition || parent?.type === AST_NODE_TYPES20.Property) && parent.key.type === AST_NODE_TYPES20.Identifier) {
5401
4981
  return parent.key.name;
5402
4982
  }
5403
4983
  return null;
@@ -5405,7 +4985,7 @@ function functionName(node) {
5405
4985
  function isInlineExported(node) {
5406
4986
  for (let current = node; current != null; current = current.parent) {
5407
4987
  const parent = current.parent;
5408
- if (parent?.type === AST_NODE_TYPES22.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES22.ExportDefaultDeclaration) {
4988
+ if (parent?.type === AST_NODE_TYPES20.ExportNamedDeclaration || parent?.type === AST_NODE_TYPES20.ExportDefaultDeclaration) {
5409
4989
  return true;
5410
4990
  }
5411
4991
  }
@@ -5414,18 +4994,18 @@ function isInlineExported(node) {
5414
4994
  function moduleScopeBindingName(node) {
5415
4995
  let current = node;
5416
4996
  let child = node;
5417
- while (current.parent != null && current.parent.type !== AST_NODE_TYPES22.Program) {
4997
+ while (current.parent != null && current.parent.type !== AST_NODE_TYPES20.Program) {
5418
4998
  child = current;
5419
4999
  current = current.parent;
5420
5000
  }
5421
- if (current.parent?.type !== AST_NODE_TYPES22.Program) {
5001
+ if (current.parent?.type !== AST_NODE_TYPES20.Program) {
5422
5002
  return null;
5423
5003
  }
5424
- if (current.type === AST_NODE_TYPES22.FunctionDeclaration || current.type === AST_NODE_TYPES22.ClassDeclaration) {
5004
+ if (current.type === AST_NODE_TYPES20.FunctionDeclaration || current.type === AST_NODE_TYPES20.ClassDeclaration) {
5425
5005
  return current.id?.name ?? null;
5426
5006
  }
5427
- if (current.type === AST_NODE_TYPES22.VariableDeclaration) {
5428
- if (child.type !== AST_NODE_TYPES22.VariableDeclarator || child.id.type !== AST_NODE_TYPES22.Identifier) {
5007
+ if (current.type === AST_NODE_TYPES20.VariableDeclaration) {
5008
+ if (child.type !== AST_NODE_TYPES20.VariableDeclarator || child.id.type !== AST_NODE_TYPES20.Identifier) {
5429
5009
  return null;
5430
5010
  }
5431
5011
  return child.id.name;
@@ -5435,19 +5015,19 @@ function moduleScopeBindingName(node) {
5435
5015
  function specifierExportedNames(program) {
5436
5016
  const names = /* @__PURE__ */ new Set();
5437
5017
  for (const statement of program.body) {
5438
- if (statement.type === AST_NODE_TYPES22.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5018
+ if (statement.type === AST_NODE_TYPES20.ExportNamedDeclaration && statement.declaration == null && statement.source == null && statement.exportKind !== "type") {
5439
5019
  for (const specifier of statement.specifiers) {
5440
- if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES22.Identifier) {
5020
+ if (specifier.exportKind !== "type" && specifier.local.type === AST_NODE_TYPES20.Identifier) {
5441
5021
  names.add(specifier.local.name);
5442
5022
  }
5443
5023
  }
5444
5024
  continue;
5445
5025
  }
5446
- if (statement.type === AST_NODE_TYPES22.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES22.Identifier) {
5026
+ if (statement.type === AST_NODE_TYPES20.ExportDefaultDeclaration && statement.declaration.type === AST_NODE_TYPES20.Identifier) {
5447
5027
  names.add(statement.declaration.name);
5448
5028
  continue;
5449
5029
  }
5450
- if (statement.type === AST_NODE_TYPES22.TSExportAssignment && statement.expression.type === AST_NODE_TYPES22.Identifier) {
5030
+ if (statement.type === AST_NODE_TYPES20.TSExportAssignment && statement.expression.type === AST_NODE_TYPES20.Identifier) {
5451
5031
  names.add(statement.expression.name);
5452
5032
  }
5453
5033
  }
@@ -5463,7 +5043,7 @@ function isExported(node, specifierExports) {
5463
5043
  const binding = moduleScopeBindingName(node);
5464
5044
  return binding !== null && specifierExports.has(binding);
5465
5045
  }
5466
- var no_positional_tuple_return_default = ESLintUtils31.RuleCreator(
5046
+ var no_positional_tuple_return_default = ESLintUtils29.RuleCreator(
5467
5047
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5468
5048
  )({
5469
5049
  name: "no-positional-tuple-return",
@@ -5511,16 +5091,16 @@ var no_positional_tuple_return_default = ESLintUtils31.RuleCreator(
5511
5091
  });
5512
5092
 
5513
5093
  // src/rules/no-repeated-string-literal.ts
5514
- import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils32 } from "@typescript-eslint/utils";
5094
+ import { AST_NODE_TYPES as AST_NODE_TYPES21, ESLintUtils as ESLintUtils30 } from "@typescript-eslint/utils";
5515
5095
  var MIN_LENGTH = 40;
5516
5096
  var MIN_DISTINCT_SCOPES = 2;
5517
5097
  var PREVIEW_LENGTH = 40;
5518
5098
  var SQL_KEYWORD_RE = /\b(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|JOIN|VALUES|ON CONFLICT|RETURNING|GROUP BY|ORDER BY)\b/;
5519
5099
  var IDENTIFIER_RE = /^[a-z_][a-z0-9_.]*$/;
5520
5100
  var FUNCTION_TYPES = /* @__PURE__ */ new Set([
5521
- AST_NODE_TYPES23.FunctionDeclaration,
5522
- AST_NODE_TYPES23.FunctionExpression,
5523
- AST_NODE_TYPES23.ArrowFunctionExpression
5101
+ AST_NODE_TYPES21.FunctionDeclaration,
5102
+ AST_NODE_TYPES21.FunctionExpression,
5103
+ AST_NODE_TYPES21.ArrowFunctionExpression
5524
5104
  ]);
5525
5105
  function isStructured(value) {
5526
5106
  return value.includes("\n") || SQL_KEYWORD_RE.test(value) || IDENTIFIER_RE.test(value);
@@ -5542,9 +5122,9 @@ function isScaffolding(node) {
5542
5122
  if (parent === void 0) {
5543
5123
  return true;
5544
5124
  }
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;
5125
+ return parent.type === AST_NODE_TYPES21.ImportDeclaration || parent.type === AST_NODE_TYPES21.ExportNamedDeclaration || parent.type === AST_NODE_TYPES21.ExportAllDeclaration || parent.type === AST_NODE_TYPES21.TSImportType || parent.type === AST_NODE_TYPES21.JSXAttribute || parent.type === AST_NODE_TYPES21.TSLiteralType;
5546
5126
  }
5547
- var no_repeated_string_literal_default = ESLintUtils32.RuleCreator(
5127
+ var no_repeated_string_literal_default = ESLintUtils30.RuleCreator(
5548
5128
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5549
5129
  )({
5550
5130
  name: "no-repeated-string-literal",
@@ -5584,7 +5164,7 @@ var no_repeated_string_literal_default = ESLintUtils32.RuleCreator(
5584
5164
  }
5585
5165
  },
5586
5166
  TemplateLiteral(node) {
5587
- if (node.parent.type === AST_NODE_TYPES23.TaggedTemplateExpression) {
5167
+ if (node.parent.type === AST_NODE_TYPES21.TaggedTemplateExpression) {
5588
5168
  return;
5589
5169
  }
5590
5170
  const [only] = node.quasis;
@@ -5618,7 +5198,7 @@ var no_repeated_string_literal_default = ESLintUtils32.RuleCreator(
5618
5198
  });
5619
5199
 
5620
5200
  // src/rules/no-select-star.ts
5621
- import { ESLintUtils as ESLintUtils33 } from "@typescript-eslint/utils";
5201
+ import { ESLintUtils as ESLintUtils31 } from "@typescript-eslint/utils";
5622
5202
  var QUERY_SHAPE = /\bSELECT\b[\s\S]*?\bFROM\b/i;
5623
5203
  var SELECT_KEYWORD = /\bSELECT\b/gi;
5624
5204
  var FROM_KEYWORD = /^FROM\b/i;
@@ -5658,7 +5238,7 @@ function hasRealSelectStar(sql) {
5658
5238
  }
5659
5239
  return false;
5660
5240
  }
5661
- var no_select_star_default = ESLintUtils33.RuleCreator(
5241
+ var no_select_star_default = ESLintUtils31.RuleCreator(
5662
5242
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5663
5243
  )({
5664
5244
  name: "no-select-star",
@@ -5687,7 +5267,7 @@ var no_select_star_default = ESLintUtils33.RuleCreator(
5687
5267
  });
5688
5268
 
5689
5269
  // src/rules/no-sleep-in-test-body.ts
5690
- import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils34 } from "@typescript-eslint/utils";
5270
+ import { AST_NODE_TYPES as AST_NODE_TYPES22, ESLintUtils as ESLintUtils32 } from "@typescript-eslint/utils";
5691
5271
  var SLEEP_HELPERS = /* @__PURE__ */ new Set(["sleep", "delay", "wait", "pause"]);
5692
5272
  var TEST_CALLERS = /* @__PURE__ */ new Set([
5693
5273
  "it",
@@ -5696,34 +5276,34 @@ var TEST_CALLERS = /* @__PURE__ */ new Set([
5696
5276
  "afterEach"
5697
5277
  ]);
5698
5278
  var FUNCTION_TYPES2 = /* @__PURE__ */ new Set([
5699
- AST_NODE_TYPES24.FunctionDeclaration,
5700
- AST_NODE_TYPES24.FunctionExpression,
5701
- AST_NODE_TYPES24.ArrowFunctionExpression
5279
+ AST_NODE_TYPES22.FunctionDeclaration,
5280
+ AST_NODE_TYPES22.FunctionExpression,
5281
+ AST_NODE_TYPES22.ArrowFunctionExpression
5702
5282
  ]);
5703
5283
  function isNonzeroNumericLiteral(node) {
5704
- return node?.type === AST_NODE_TYPES24.Literal && typeof node.value === "number" && node.value !== 0;
5284
+ return node?.type === AST_NODE_TYPES22.Literal && typeof node.value === "number" && node.value !== 0;
5705
5285
  }
5706
5286
  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]);
5287
+ return node.type === AST_NODE_TYPES22.CallExpression && node.callee.type === AST_NODE_TYPES22.Identifier && node.callee.name === "setTimeout" && node.arguments.length >= 2 && isNonzeroNumericLiteral(node.arguments[1]);
5708
5288
  }
5709
5289
  function isPromiseSleep(node) {
5710
- if (node.callee.type !== AST_NODE_TYPES24.Identifier || node.callee.name !== "Promise") {
5290
+ if (node.callee.type !== AST_NODE_TYPES22.Identifier || node.callee.name !== "Promise") {
5711
5291
  return false;
5712
5292
  }
5713
5293
  const executor = node.arguments[0];
5714
- if (executor?.type !== AST_NODE_TYPES24.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES24.FunctionExpression) {
5294
+ if (executor?.type !== AST_NODE_TYPES22.ArrowFunctionExpression && executor?.type !== AST_NODE_TYPES22.FunctionExpression) {
5715
5295
  return false;
5716
5296
  }
5717
5297
  const body = executor.body;
5718
- if (body.type !== AST_NODE_TYPES24.BlockStatement) {
5298
+ if (body.type !== AST_NODE_TYPES22.BlockStatement) {
5719
5299
  return isTimedSetTimeout(body);
5720
5300
  }
5721
5301
  return body.body.some(
5722
- (stmt) => stmt.type === AST_NODE_TYPES24.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5302
+ (stmt) => stmt.type === AST_NODE_TYPES22.ExpressionStatement && isTimedSetTimeout(stmt.expression)
5723
5303
  );
5724
5304
  }
5725
5305
  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]);
5306
+ return node.callee.type === AST_NODE_TYPES22.Identifier && SLEEP_HELPERS.has(node.callee.name) && node.arguments.length >= 1 && isNonzeroNumericLiteral(node.arguments[0]);
5727
5307
  }
5728
5308
  function nearestEnclosingFunction(node) {
5729
5309
  for (let current = node.parent; current != null; current = current.parent) {
@@ -5731,7 +5311,7 @@ function nearestEnclosingFunction(node) {
5731
5311
  continue;
5732
5312
  }
5733
5313
  const grandparent = current.parent;
5734
- const isPromiseExecutor = grandparent?.type === AST_NODE_TYPES24.NewExpression && isPromiseSleep(grandparent);
5314
+ const isPromiseExecutor = grandparent?.type === AST_NODE_TYPES22.NewExpression && isPromiseSleep(grandparent);
5735
5315
  if (!isPromiseExecutor) {
5736
5316
  return current;
5737
5317
  }
@@ -5739,29 +5319,29 @@ function nearestEnclosingFunction(node) {
5739
5319
  return null;
5740
5320
  }
5741
5321
  function testCallerName(callee) {
5742
- if (callee.type === AST_NODE_TYPES24.Identifier) {
5322
+ if (callee.type === AST_NODE_TYPES22.Identifier) {
5743
5323
  return callee.name;
5744
5324
  }
5745
- if (callee.type === AST_NODE_TYPES24.MemberExpression) {
5325
+ if (callee.type === AST_NODE_TYPES22.MemberExpression) {
5746
5326
  return testCallerName(callee.object);
5747
5327
  }
5748
- if (callee.type === AST_NODE_TYPES24.CallExpression) {
5328
+ if (callee.type === AST_NODE_TYPES22.CallExpression) {
5749
5329
  return testCallerName(callee.callee);
5750
5330
  }
5751
- if (callee.type === AST_NODE_TYPES24.TaggedTemplateExpression) {
5331
+ if (callee.type === AST_NODE_TYPES22.TaggedTemplateExpression) {
5752
5332
  return testCallerName(callee.tag);
5753
5333
  }
5754
5334
  return null;
5755
5335
  }
5756
5336
  function isTestBody(fn) {
5757
5337
  const call = fn.parent;
5758
- if (call?.type !== AST_NODE_TYPES24.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5338
+ if (call?.type !== AST_NODE_TYPES22.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5759
5339
  return false;
5760
5340
  }
5761
5341
  const name = testCallerName(call.callee);
5762
5342
  return name !== null && TEST_CALLERS.has(name);
5763
5343
  }
5764
- var no_sleep_in_test_body_default = ESLintUtils34.RuleCreator(
5344
+ var no_sleep_in_test_body_default = ESLintUtils32.RuleCreator(
5765
5345
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5766
5346
  )({
5767
5347
  name: "no-sleep-in-test-body",
@@ -5802,8 +5382,90 @@ var no_sleep_in_test_body_default = ESLintUtils34.RuleCreator(
5802
5382
  }
5803
5383
  });
5804
5384
 
5385
+ // src/rules/no-conditional-in-test.ts
5386
+ import { AST_NODE_TYPES as AST_NODE_TYPES23, ESLintUtils as ESLintUtils33 } from "@typescript-eslint/utils";
5387
+ var TEST_CALLERS2 = /* @__PURE__ */ new Set(["it", "test"]);
5388
+ var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
5389
+ AST_NODE_TYPES23.FunctionDeclaration,
5390
+ AST_NODE_TYPES23.FunctionExpression,
5391
+ AST_NODE_TYPES23.ArrowFunctionExpression
5392
+ ]);
5393
+ function nearestEnclosingFunction2(node) {
5394
+ for (let current = node.parent; current != null; current = current.parent) {
5395
+ if (FUNCTION_TYPES3.has(current.type)) {
5396
+ return current;
5397
+ }
5398
+ }
5399
+ return null;
5400
+ }
5401
+ function testCallerName2(callee) {
5402
+ if (callee.type === AST_NODE_TYPES23.Identifier) {
5403
+ return callee.name;
5404
+ }
5405
+ if (callee.type === AST_NODE_TYPES23.MemberExpression) {
5406
+ return testCallerName2(callee.object);
5407
+ }
5408
+ if (callee.type === AST_NODE_TYPES23.CallExpression) {
5409
+ return testCallerName2(callee.callee);
5410
+ }
5411
+ if (callee.type === AST_NODE_TYPES23.TaggedTemplateExpression) {
5412
+ return testCallerName2(callee.tag);
5413
+ }
5414
+ return null;
5415
+ }
5416
+ function isTestBody2(fn) {
5417
+ const call = fn.parent;
5418
+ if (call?.type !== AST_NODE_TYPES23.CallExpression || !call.arguments.some((argument) => argument === fn)) {
5419
+ return false;
5420
+ }
5421
+ const name = testCallerName2(call.callee);
5422
+ return name !== null && TEST_CALLERS2.has(name);
5423
+ }
5424
+ var no_conditional_in_test_default = ESLintUtils33.RuleCreator(
5425
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5426
+ )({
5427
+ name: "no-conditional-in-test",
5428
+ meta: {
5429
+ type: "problem",
5430
+ docs: {
5431
+ description: "Disallow conditional logic (if, switch, ternary) in test bodies, which can hide missing assertions or test multiple code paths."
5432
+ },
5433
+ schema: [],
5434
+ messages: {
5435
+ noConditionalInTest: "Avoid using conditional logic in tests. It can obscure intent and hide unexecuted assertions. Split the test instead."
5436
+ }
5437
+ },
5438
+ defaultOptions: [],
5439
+ create(context) {
5440
+ if (!isTestFile(context.filename)) {
5441
+ return {};
5442
+ }
5443
+ const report = (node) => {
5444
+ const enclosing = nearestEnclosingFunction2(node);
5445
+ if (enclosing === null || !isTestBody2(enclosing)) {
5446
+ return;
5447
+ }
5448
+ context.report({ node, messageId: "noConditionalInTest" });
5449
+ };
5450
+ return {
5451
+ IfStatement(node) {
5452
+ report(node);
5453
+ },
5454
+ SwitchStatement(node) {
5455
+ report(node);
5456
+ },
5457
+ ConditionalExpression(node) {
5458
+ report(node);
5459
+ },
5460
+ LogicalExpression(node) {
5461
+ report(node);
5462
+ }
5463
+ };
5464
+ }
5465
+ });
5466
+
5805
5467
  // src/rules/prefer-constant-time-secret-compare.ts
5806
- import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils35 } from "@typescript-eslint/utils";
5468
+ import { AST_NODE_TYPES as AST_NODE_TYPES24, ESLintUtils as ESLintUtils34 } from "@typescript-eslint/utils";
5807
5469
  var EQUALITY_OPERATORS = /* @__PURE__ */ new Set(["===", "!==", "==", "!="]);
5808
5470
  var SENTINEL_IDENTIFIERS = /* @__PURE__ */ new Set(["undefined", "NaN"]);
5809
5471
  var SENTINEL_WORDS = /(^|_)(SENTINEL|EMPTY|NONE|NULL|UNSET|MISSING|PLACEHOLDER|DUMMY|FAKE|EXAMPLE)(_|$)/;
@@ -5816,36 +5478,36 @@ function isConstantReference(identifier) {
5816
5478
  }
5817
5479
  function isExcludedOperand(node) {
5818
5480
  switch (node.type) {
5819
- case AST_NODE_TYPES25.Literal:
5481
+ case AST_NODE_TYPES24.Literal:
5820
5482
  return true;
5821
- case AST_NODE_TYPES25.TemplateLiteral:
5483
+ case AST_NODE_TYPES24.TemplateLiteral:
5822
5484
  return node.expressions.length === 0;
5823
- case AST_NODE_TYPES25.Identifier:
5485
+ case AST_NODE_TYPES24.Identifier:
5824
5486
  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));
5487
+ case AST_NODE_TYPES24.MemberExpression:
5488
+ return !node.computed && node.property.type === AST_NODE_TYPES24.Identifier && (SENTINEL_PREFIX_RE.test(node.property.name) || isConstantReference(node.property.name));
5827
5489
  default:
5828
5490
  return false;
5829
5491
  }
5830
5492
  }
5831
5493
  function operandName(node) {
5832
- if (node.type === AST_NODE_TYPES25.Identifier) {
5494
+ if (node.type === AST_NODE_TYPES24.Identifier) {
5833
5495
  return node.name;
5834
5496
  }
5835
- if (node.type === AST_NODE_TYPES25.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES25.Identifier) {
5497
+ if (node.type === AST_NODE_TYPES24.MemberExpression && !node.computed && node.property.type === AST_NODE_TYPES24.Identifier) {
5836
5498
  return node.property.name;
5837
5499
  }
5838
5500
  return null;
5839
5501
  }
5840
5502
  function isSecretOperand(node) {
5841
- if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
5503
+ if (node.type === AST_NODE_TYPES24.TemplateLiteral) {
5842
5504
  return node.expressions.some((expression) => isSecretOperand(expression));
5843
5505
  }
5844
5506
  const name = operandName(node);
5845
5507
  return name !== null && isAuthSecretName(name);
5846
5508
  }
5847
5509
  function secretNameOf(node) {
5848
- if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
5510
+ if (node.type === AST_NODE_TYPES24.TemplateLiteral) {
5849
5511
  for (const expression of node.expressions) {
5850
5512
  const nested = secretNameOf(expression);
5851
5513
  if (nested !== null) {
@@ -5856,7 +5518,7 @@ function secretNameOf(node) {
5856
5518
  }
5857
5519
  return operandName(node);
5858
5520
  }
5859
- var prefer_constant_time_secret_compare_default = ESLintUtils35.RuleCreator(
5521
+ var prefer_constant_time_secret_compare_default = ESLintUtils34.RuleCreator(
5860
5522
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5861
5523
  )({
5862
5524
  name: "prefer-constant-time-secret-compare",
@@ -5899,11 +5561,11 @@ var prefer_constant_time_secret_compare_default = ESLintUtils35.RuleCreator(
5899
5561
  });
5900
5562
 
5901
5563
  // src/rules/store-insert-requires-on-conflict.ts
5902
- import { ESLintUtils as ESLintUtils36 } from "@typescript-eslint/utils";
5564
+ import { ESLintUtils as ESLintUtils35 } from "@typescript-eslint/utils";
5903
5565
  var INSERT_WRITE = /\bINSERT\s+(?:OR\s+\w+\s+)?INTO\s+[\w."'`?$:@-]+\s*(?:\([^)]*\)\s*)?(?:VALUES|SELECT|DEFAULT\s+VALUES)\b/i;
5904
5566
  var CONFLICT_HANDLED = /\bON\s+CONFLICT\b|\bON\s+DUPLICATE\s+KEY\b|\bINSERT\s+OR\s+(?:IGNORE|REPLACE)\b/i;
5905
5567
  var INSERT_GATE = /insert/i;
5906
- var store_insert_requires_on_conflict_default = ESLintUtils36.RuleCreator(
5568
+ var store_insert_requires_on_conflict_default = ESLintUtils35.RuleCreator(
5907
5569
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
5908
5570
  )({
5909
5571
  name: "store-insert-requires-on-conflict",
@@ -5932,17 +5594,17 @@ var store_insert_requires_on_conflict_default = ESLintUtils36.RuleCreator(
5932
5594
  });
5933
5595
 
5934
5596
  // src/rules/no-dynamic-sql.ts
5935
- import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils37 } from "@typescript-eslint/utils";
5597
+ import { AST_NODE_TYPES as AST_NODE_TYPES25, ESLintUtils as ESLintUtils36 } from "@typescript-eslint/utils";
5936
5598
  var DEFAULT_METHODS = ["prepare", "exec", "query"];
5937
5599
  var CONSTANT_CASE_RE = /^[A-Z][A-Z0-9_]*$/;
5938
5600
  function isStaticFragment(expression) {
5939
- if (expression.type === AST_NODE_TYPES26.Identifier) {
5601
+ if (expression.type === AST_NODE_TYPES25.Identifier) {
5940
5602
  return CONSTANT_CASE_RE.test(expression.name);
5941
5603
  }
5942
- if (expression.type === AST_NODE_TYPES26.MemberExpression && !expression.computed && expression.property.type === AST_NODE_TYPES26.Identifier) {
5604
+ if (expression.type === AST_NODE_TYPES25.MemberExpression && !expression.computed && expression.property.type === AST_NODE_TYPES25.Identifier) {
5943
5605
  return CONSTANT_CASE_RE.test(expression.property.name);
5944
5606
  }
5945
- if (expression.type === AST_NODE_TYPES26.Literal) {
5607
+ if (expression.type === AST_NODE_TYPES25.Literal) {
5946
5608
  return typeof expression.value === "string";
5947
5609
  }
5948
5610
  return false;
@@ -5953,36 +5615,36 @@ function runtimeInterpolations(template) {
5953
5615
  );
5954
5616
  }
5955
5617
  function concatOperands(node) {
5956
- if (node.type === AST_NODE_TYPES26.BinaryExpression && node.operator === "+") {
5618
+ if (node.type === AST_NODE_TYPES25.BinaryExpression && node.operator === "+") {
5957
5619
  return [...concatOperands(node.left), ...concatOperands(node.right)];
5958
5620
  }
5959
5621
  return [node];
5960
5622
  }
5961
5623
  function runtimeConcatOperands(node) {
5962
- if (node.type !== AST_NODE_TYPES26.BinaryExpression || node.operator !== "+") {
5624
+ if (node.type !== AST_NODE_TYPES25.BinaryExpression || node.operator !== "+") {
5963
5625
  return [];
5964
5626
  }
5965
5627
  const operands = concatOperands(node);
5966
5628
  const hasStringLiteral = operands.some(
5967
- (operand) => operand.type === AST_NODE_TYPES26.Literal && typeof operand.value === "string"
5629
+ (operand) => operand.type === AST_NODE_TYPES25.Literal && typeof operand.value === "string"
5968
5630
  );
5969
5631
  if (!hasStringLiteral) {
5970
5632
  return [];
5971
5633
  }
5972
5634
  return operands.filter(
5973
- (operand) => operand.type !== AST_NODE_TYPES26.Literal && !isStaticFragment(operand)
5635
+ (operand) => operand.type !== AST_NODE_TYPES25.Literal && !isStaticFragment(operand)
5974
5636
  );
5975
5637
  }
5976
5638
  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
5639
  var RUNTIME_MARKER = " ? ";
5978
5640
  function staticStatementText(node) {
5979
- if (node.type === AST_NODE_TYPES26.TemplateLiteral) {
5641
+ if (node.type === AST_NODE_TYPES25.TemplateLiteral) {
5980
5642
  return node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join(RUNTIME_MARKER);
5981
5643
  }
5982
- if (node.type === AST_NODE_TYPES26.Literal) {
5644
+ if (node.type === AST_NODE_TYPES25.Literal) {
5983
5645
  return typeof node.value === "string" ? node.value : RUNTIME_MARKER;
5984
5646
  }
5985
- if (node.type === AST_NODE_TYPES26.BinaryExpression && node.operator === "+") {
5647
+ if (node.type === AST_NODE_TYPES25.BinaryExpression && node.operator === "+") {
5986
5648
  return staticStatementText(node.left) + staticStatementText(node.right);
5987
5649
  }
5988
5650
  return RUNTIME_MARKER;
@@ -5992,13 +5654,13 @@ function looksLikeSql(node) {
5992
5654
  }
5993
5655
  function statementMethodName(node, methods) {
5994
5656
  const callee = node.callee;
5995
- if (callee.type !== AST_NODE_TYPES26.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES26.Identifier) {
5657
+ if (callee.type !== AST_NODE_TYPES25.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES25.Identifier) {
5996
5658
  return null;
5997
5659
  }
5998
5660
  const name = callee.property.name;
5999
5661
  return methods.has(name) ? name : null;
6000
5662
  }
6001
- var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
5663
+ var no_dynamic_sql_default = ESLintUtils36.RuleCreator(
6002
5664
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6003
5665
  )({
6004
5666
  name: "no-dynamic-sql",
@@ -6037,7 +5699,7 @@ var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6037
5699
  if (statement === void 0 || !looksLikeSql(statement)) {
6038
5700
  return;
6039
5701
  }
6040
- const offenders = statement.type === AST_NODE_TYPES26.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
5702
+ const offenders = statement.type === AST_NODE_TYPES25.TemplateLiteral ? runtimeInterpolations(statement) : runtimeConcatOperands(statement);
6041
5703
  for (const offender of offenders) {
6042
5704
  context.report({
6043
5705
  node: offender,
@@ -6051,7 +5713,7 @@ var no_dynamic_sql_default = ESLintUtils37.RuleCreator(
6051
5713
  });
6052
5714
 
6053
5715
  // src/rules/no-raw-fetch-outside-clients.ts
6054
- import { ESLintUtils as ESLintUtils38 } from "@typescript-eslint/utils";
5716
+ import { ESLintUtils as ESLintUtils37 } from "@typescript-eslint/utils";
6055
5717
  var DEFAULT_ALLOW = [
6056
5718
  "[\\\\/]clients?[\\\\/]",
6057
5719
  "-client\\.[cm]?[jt]sx?$",
@@ -6115,7 +5777,7 @@ function compile(patterns) {
6115
5777
  }
6116
5778
  return compiled;
6117
5779
  }
6118
- var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
5780
+ var no_raw_fetch_outside_clients_default = ESLintUtils37.RuleCreator(
6119
5781
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6120
5782
  )({
6121
5783
  name: "no-raw-fetch-outside-clients",
@@ -6163,7 +5825,7 @@ var no_raw_fetch_outside_clients_default = ESLintUtils38.RuleCreator(
6163
5825
  });
6164
5826
 
6165
5827
  // src/rules/no-storage-in-stateless-modules.ts
6166
- import { AST_NODE_TYPES as AST_NODE_TYPES27, ESLintUtils as ESLintUtils39 } from "@typescript-eslint/utils";
5828
+ import { AST_NODE_TYPES as AST_NODE_TYPES26, ESLintUtils as ESLintUtils38 } from "@typescript-eslint/utils";
6167
5829
  var DEFAULT_METHODS2 = [
6168
5830
  "prepare",
6169
5831
  "put",
@@ -6182,7 +5844,7 @@ function compile2(patterns) {
6182
5844
  }
6183
5845
  function storageMethodName(node, methods) {
6184
5846
  const callee = node.callee;
6185
- if (callee.type !== AST_NODE_TYPES27.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES27.Identifier) {
5847
+ if (callee.type !== AST_NODE_TYPES26.MemberExpression || callee.computed || callee.property.type !== AST_NODE_TYPES26.Identifier) {
6186
5848
  return null;
6187
5849
  }
6188
5850
  const name = callee.property.name;
@@ -6194,7 +5856,7 @@ function storageMethodName(node, methods) {
6194
5856
  }
6195
5857
  return name;
6196
5858
  }
6197
- var no_storage_in_stateless_modules_default = ESLintUtils39.RuleCreator(
5859
+ var no_storage_in_stateless_modules_default = ESLintUtils38.RuleCreator(
6198
5860
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6199
5861
  )({
6200
5862
  name: "no-storage-in-stateless-modules",
@@ -6253,8 +5915,8 @@ var no_storage_in_stateless_modules_default = ESLintUtils39.RuleCreator(
6253
5915
 
6254
5916
  // src/rules/no-zod-native-enum.ts
6255
5917
  import {
6256
- ESLintUtils as ESLintUtils40,
6257
- AST_NODE_TYPES as AST_NODE_TYPES28
5918
+ ESLintUtils as ESLintUtils39,
5919
+ AST_NODE_TYPES as AST_NODE_TYPES27
6258
5920
  } from "@typescript-eslint/utils";
6259
5921
  import * as ts2 from "typescript";
6260
5922
  var IGNORE_PATTERNS2 = [
@@ -6269,11 +5931,11 @@ function isIgnoredFile2(filename, sourceText) {
6269
5931
  }
6270
5932
  return /@generated\b/.test(sourceText.slice(0, 1024));
6271
5933
  }
6272
- function isZodModule(source) {
5934
+ function isZodModule2(source) {
6273
5935
  return /(^|[/@-])zod([/-]|$)/.test(source);
6274
5936
  }
6275
5937
  function unwrap3(node) {
6276
- if (node.type === AST_NODE_TYPES28.TSAsExpression || node.type === AST_NODE_TYPES28.TSSatisfiesExpression) {
5938
+ if (node.type === AST_NODE_TYPES27.TSAsExpression || node.type === AST_NODE_TYPES27.TSSatisfiesExpression) {
6277
5939
  return unwrap3(node.expression);
6278
5940
  }
6279
5941
  return node;
@@ -6281,14 +5943,14 @@ function unwrap3(node) {
6281
5943
  function stringValueTexts(node, sourceCode) {
6282
5944
  const texts = [];
6283
5945
  for (const prop of node.properties) {
6284
- if (prop.type !== AST_NODE_TYPES28.Property) {
5946
+ if (prop.type !== AST_NODE_TYPES27.Property) {
6285
5947
  return null;
6286
5948
  }
6287
5949
  if (prop.computed || prop.shorthand || prop.method || prop.kind !== "init") {
6288
5950
  return null;
6289
5951
  }
6290
5952
  const value = prop.value;
6291
- if (value.type !== AST_NODE_TYPES28.Literal || typeof value.value !== "string") {
5953
+ if (value.type !== AST_NODE_TYPES27.Literal || typeof value.value !== "string") {
6292
5954
  return null;
6293
5955
  }
6294
5956
  const text = sourceCode.getText(value);
@@ -6304,7 +5966,7 @@ function resolvesToLocalEnum(node, scope) {
6304
5966
  const variable = current.variables.find((v) => v.name === node.name);
6305
5967
  if (variable !== void 0) {
6306
5968
  return variable.defs.some(
6307
- (def) => def.node.type === AST_NODE_TYPES28.TSEnumDeclaration
5969
+ (def) => def.node.type === AST_NODE_TYPES27.TSEnumDeclaration
6308
5970
  );
6309
5971
  }
6310
5972
  current = current.upper;
@@ -6324,7 +5986,7 @@ function resolvesToImportedEnum(node, services) {
6324
5986
  }
6325
5987
  return (symbol.flags & ENUM_SYMBOL_FLAGS) !== 0;
6326
5988
  }
6327
- var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
5989
+ var no_zod_native_enum_default = ESLintUtils39.RuleCreator(
6328
5990
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6329
5991
  )({
6330
5992
  name: "no-zod-native-enum",
@@ -6351,32 +6013,32 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6351
6013
  }
6352
6014
  let services;
6353
6015
  try {
6354
- services = ESLintUtils40.getParserServices(context);
6016
+ services = ESLintUtils39.getParserServices(context);
6355
6017
  } catch {
6356
6018
  services = null;
6357
6019
  }
6358
6020
  const zodImportedNames = /* @__PURE__ */ new Map();
6359
6021
  function isZodMemberCall(node, api) {
6360
6022
  const callee = node.callee;
6361
- if (callee.type === AST_NODE_TYPES28.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES28.Identifier) {
6023
+ if (callee.type === AST_NODE_TYPES27.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES27.Identifier) {
6362
6024
  return callee.property.name === api;
6363
6025
  }
6364
- if (callee.type === AST_NODE_TYPES28.Identifier) {
6026
+ if (callee.type === AST_NODE_TYPES27.Identifier) {
6365
6027
  return zodImportedNames.get(callee.name) === api;
6366
6028
  }
6367
6029
  return false;
6368
6030
  }
6369
6031
  function buildFix(node) {
6370
6032
  const callee = node.callee;
6371
- if (callee.type !== AST_NODE_TYPES28.MemberExpression || callee.property.type !== AST_NODE_TYPES28.Identifier) {
6033
+ if (callee.type !== AST_NODE_TYPES27.MemberExpression || callee.property.type !== AST_NODE_TYPES27.Identifier) {
6372
6034
  return null;
6373
6035
  }
6374
6036
  const arg = node.arguments[0];
6375
- if (arg === void 0 || node.arguments.length !== 1 || arg.type === AST_NODE_TYPES28.SpreadElement) {
6037
+ if (arg === void 0 || node.arguments.length !== 1 || arg.type === AST_NODE_TYPES27.SpreadElement) {
6376
6038
  return null;
6377
6039
  }
6378
6040
  const inner = unwrap3(arg);
6379
- if (inner.type !== AST_NODE_TYPES28.ObjectExpression) {
6041
+ if (inner.type !== AST_NODE_TYPES27.ObjectExpression) {
6380
6042
  return null;
6381
6043
  }
6382
6044
  const values = stringValueTexts(inner, sourceCode);
@@ -6392,11 +6054,11 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6392
6054
  }
6393
6055
  return {
6394
6056
  ImportDeclaration(node) {
6395
- if (!isZodModule(node.source.value)) {
6057
+ if (!isZodModule2(node.source.value)) {
6396
6058
  return;
6397
6059
  }
6398
6060
  for (const spec of node.specifiers) {
6399
- if (spec.type === AST_NODE_TYPES28.ImportSpecifier && spec.imported.type === AST_NODE_TYPES28.Identifier) {
6061
+ if (spec.type === AST_NODE_TYPES27.ImportSpecifier && spec.imported.type === AST_NODE_TYPES27.Identifier) {
6400
6062
  zodImportedNames.set(spec.local.name, spec.imported.name);
6401
6063
  }
6402
6064
  }
@@ -6415,7 +6077,7 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6415
6077
  return;
6416
6078
  }
6417
6079
  const arg = node.arguments[0];
6418
- if (arg === void 0 || arg.type !== AST_NODE_TYPES28.Identifier) {
6080
+ if (arg === void 0 || arg.type !== AST_NODE_TYPES27.Identifier) {
6419
6081
  return;
6420
6082
  }
6421
6083
  const isEnum = resolvesToLocalEnum(arg, sourceCode.getScope(arg)) || services !== null && resolvesToImportedEnum(arg, services);
@@ -6433,8 +6095,8 @@ var no_zod_native_enum_default = ESLintUtils40.RuleCreator(
6433
6095
 
6434
6096
  // src/rules/prefer-module-level-constant.ts
6435
6097
  import {
6436
- ESLintUtils as ESLintUtils41,
6437
- AST_NODE_TYPES as AST_NODE_TYPES29
6098
+ ESLintUtils as ESLintUtils40,
6099
+ AST_NODE_TYPES as AST_NODE_TYPES28
6438
6100
  } from "@typescript-eslint/utils";
6439
6101
  var DEFAULT_MIN_ELEMENTS = 3;
6440
6102
  var MAX_LITERAL_DEPTH = 4;
@@ -6470,10 +6132,10 @@ var MUTATING_METHODS = /* @__PURE__ */ new Set([
6470
6132
  // Object-ish escape hatches
6471
6133
  "assign"
6472
6134
  ]);
6473
- var FUNCTION_TYPES3 = /* @__PURE__ */ new Set([
6474
- AST_NODE_TYPES29.FunctionDeclaration,
6475
- AST_NODE_TYPES29.FunctionExpression,
6476
- AST_NODE_TYPES29.ArrowFunctionExpression
6135
+ var FUNCTION_TYPES4 = /* @__PURE__ */ new Set([
6136
+ AST_NODE_TYPES28.FunctionDeclaration,
6137
+ AST_NODE_TYPES28.FunctionExpression,
6138
+ AST_NODE_TYPES28.ArrowFunctionExpression
6477
6139
  ]);
6478
6140
  var COLLECTION_CONSTRUCTORS = /* @__PURE__ */ new Set(["Set", "Map"]);
6479
6141
  function isIgnoredFile3(filename, sourceText) {
@@ -6486,13 +6148,13 @@ function isTestFile2(filename) {
6486
6148
  return TEST_FILE_PATTERNS.some((re) => re.test(filename));
6487
6149
  }
6488
6150
  function unwrap4(node) {
6489
- if (node.type === AST_NODE_TYPES29.TSAsExpression || node.type === AST_NODE_TYPES29.TSSatisfiesExpression || node.type === AST_NODE_TYPES29.TSNonNullExpression) {
6151
+ if (node.type === AST_NODE_TYPES28.TSAsExpression || node.type === AST_NODE_TYPES28.TSSatisfiesExpression || node.type === AST_NODE_TYPES28.TSNonNullExpression) {
6490
6152
  return unwrap4(node.expression);
6491
6153
  }
6492
6154
  return node;
6493
6155
  }
6494
6156
  function isRegexLiteral(node) {
6495
- return node.type === AST_NODE_TYPES29.Literal && "regex" in node && node.regex !== void 0;
6157
+ return node.type === AST_NODE_TYPES28.Literal && "regex" in node && node.regex !== void 0;
6496
6158
  }
6497
6159
  function isLiteralOnly(node, depth) {
6498
6160
  if (depth > MAX_LITERAL_DEPTH) {
@@ -6500,29 +6162,29 @@ function isLiteralOnly(node, depth) {
6500
6162
  }
6501
6163
  const inner = unwrap4(node);
6502
6164
  switch (inner.type) {
6503
- case AST_NODE_TYPES29.Literal: {
6165
+ case AST_NODE_TYPES28.Literal: {
6504
6166
  return true;
6505
6167
  }
6506
- case AST_NODE_TYPES29.TemplateLiteral: {
6168
+ case AST_NODE_TYPES28.TemplateLiteral: {
6507
6169
  return inner.expressions.length === 0;
6508
6170
  }
6509
- case AST_NODE_TYPES29.UnaryExpression: {
6510
- return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === AST_NODE_TYPES29.Literal && typeof inner.argument.value === "number";
6171
+ case AST_NODE_TYPES28.UnaryExpression: {
6172
+ return (inner.operator === "-" || inner.operator === "+") && inner.argument.type === AST_NODE_TYPES28.Literal && typeof inner.argument.value === "number";
6511
6173
  }
6512
- case AST_NODE_TYPES29.ArrayExpression: {
6174
+ case AST_NODE_TYPES28.ArrayExpression: {
6513
6175
  return inner.elements.every(
6514
- (el) => el !== null && el.type !== AST_NODE_TYPES29.SpreadElement && isLiteralOnly(el, depth + 1)
6176
+ (el) => el !== null && el.type !== AST_NODE_TYPES28.SpreadElement && isLiteralOnly(el, depth + 1)
6515
6177
  );
6516
6178
  }
6517
- case AST_NODE_TYPES29.ObjectExpression: {
6179
+ case AST_NODE_TYPES28.ObjectExpression: {
6518
6180
  return inner.properties.every((prop) => {
6519
- if (prop.type !== AST_NODE_TYPES29.Property) {
6181
+ if (prop.type !== AST_NODE_TYPES28.Property) {
6520
6182
  return false;
6521
6183
  }
6522
6184
  if (prop.shorthand || prop.method || prop.kind !== "init") {
6523
6185
  return false;
6524
6186
  }
6525
- if (prop.computed && prop.key.type !== AST_NODE_TYPES29.Literal) {
6187
+ if (prop.computed && prop.key.type !== AST_NODE_TYPES28.Literal) {
6526
6188
  return false;
6527
6189
  }
6528
6190
  return isLiteralOnly(prop.value, depth + 1);
@@ -6535,7 +6197,7 @@ function isLiteralOnly(node, depth) {
6535
6197
  }
6536
6198
  function unwrapObjectFreeze(node) {
6537
6199
  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) {
6200
+ if (inner.type === AST_NODE_TYPES28.CallExpression && inner.callee.type === AST_NODE_TYPES28.MemberExpression && !inner.callee.computed && inner.callee.object.type === AST_NODE_TYPES28.Identifier && inner.callee.object.name === "Object" && inner.callee.property.type === AST_NODE_TYPES28.Identifier && inner.callee.property.name === "freeze" && inner.arguments.length === 1 && inner.arguments[0] !== void 0 && inner.arguments[0].type !== AST_NODE_TYPES28.SpreadElement) {
6539
6201
  return unwrap4(inner.arguments[0]);
6540
6202
  }
6541
6203
  return inner;
@@ -6551,19 +6213,19 @@ function classify(init, checkRegex) {
6551
6213
  }
6552
6214
  return { kind: "regex", size: 1 };
6553
6215
  }
6554
- if (node.type === AST_NODE_TYPES29.ArrayExpression) {
6216
+ if (node.type === AST_NODE_TYPES28.ArrayExpression) {
6555
6217
  return isLiteralOnly(node, 0) ? { kind: "array", size: node.elements.length } : null;
6556
6218
  }
6557
- if (node.type === AST_NODE_TYPES29.ObjectExpression) {
6219
+ if (node.type === AST_NODE_TYPES28.ObjectExpression) {
6558
6220
  return isLiteralOnly(node, 0) ? { kind: "object", size: node.properties.length } : null;
6559
6221
  }
6560
- if (node.type === AST_NODE_TYPES29.NewExpression && node.callee.type === AST_NODE_TYPES29.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6222
+ if (node.type === AST_NODE_TYPES28.NewExpression && node.callee.type === AST_NODE_TYPES28.Identifier && COLLECTION_CONSTRUCTORS.has(node.callee.name)) {
6561
6223
  const arg = node.arguments[0];
6562
- if (node.arguments.length !== 1 || arg === void 0 || arg.type === AST_NODE_TYPES29.SpreadElement) {
6224
+ if (node.arguments.length !== 1 || arg === void 0 || arg.type === AST_NODE_TYPES28.SpreadElement) {
6563
6225
  return null;
6564
6226
  }
6565
6227
  const entries = unwrap4(arg);
6566
- if (entries.type !== AST_NODE_TYPES29.ArrayExpression) {
6228
+ if (entries.type !== AST_NODE_TYPES28.ArrayExpression) {
6567
6229
  return null;
6568
6230
  }
6569
6231
  return isLiteralOnly(entries, 0) ? { kind: node.callee.name === "Set" ? "Set" : "Map", size: entries.elements.length } : null;
@@ -6573,7 +6235,7 @@ function classify(init, checkRegex) {
6573
6235
  function enclosingFunction2(node) {
6574
6236
  let current = node.parent;
6575
6237
  while (current !== void 0 && current !== null) {
6576
- if (FUNCTION_TYPES3.has(current.type)) {
6238
+ if (FUNCTION_TYPES4.has(current.type)) {
6577
6239
  return current;
6578
6240
  }
6579
6241
  current = current.parent;
@@ -6592,10 +6254,10 @@ var NON_RETAINING_BUILTINS = /* @__PURE__ */ new Map(
6592
6254
  );
6593
6255
  function isNonRetainingBuiltinCall(node, argument) {
6594
6256
  const callee = node.callee;
6595
- if (callee.type === AST_NODE_TYPES29.Identifier && callee.name === "structuredClone") {
6257
+ if (callee.type === AST_NODE_TYPES28.Identifier && callee.name === "structuredClone") {
6596
6258
  return true;
6597
6259
  }
6598
- if (callee.type !== AST_NODE_TYPES29.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES29.Identifier || callee.property.type !== AST_NODE_TYPES29.Identifier) {
6260
+ if (callee.type !== AST_NODE_TYPES28.MemberExpression || callee.computed || callee.object.type !== AST_NODE_TYPES28.Identifier || callee.property.type !== AST_NODE_TYPES28.Identifier) {
6599
6261
  return false;
6600
6262
  }
6601
6263
  const members = NON_RETAINING_BUILTINS.get(callee.object.name);
@@ -6609,43 +6271,43 @@ function isNonRetainingBuiltinCall(node, argument) {
6609
6271
  }
6610
6272
  function isSafeRead(identifier) {
6611
6273
  const parent = identifier.parent;
6612
- if (parent.type === AST_NODE_TYPES29.MemberExpression) {
6274
+ if (parent.type === AST_NODE_TYPES28.MemberExpression) {
6613
6275
  if (parent.object !== identifier) {
6614
6276
  return true;
6615
6277
  }
6616
6278
  const grandparent = parent.parent;
6617
- if (grandparent.type === AST_NODE_TYPES29.AssignmentExpression && grandparent.left === parent) {
6279
+ if (grandparent.type === AST_NODE_TYPES28.AssignmentExpression && grandparent.left === parent) {
6618
6280
  return false;
6619
6281
  }
6620
- if (grandparent.type === AST_NODE_TYPES29.UpdateExpression) {
6282
+ if (grandparent.type === AST_NODE_TYPES28.UpdateExpression) {
6621
6283
  return false;
6622
6284
  }
6623
- if (grandparent.type === AST_NODE_TYPES29.UnaryExpression && grandparent.operator === "delete") {
6285
+ if (grandparent.type === AST_NODE_TYPES28.UnaryExpression && grandparent.operator === "delete") {
6624
6286
  return false;
6625
6287
  }
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) {
6288
+ if (!parent.computed && parent.property.type === AST_NODE_TYPES28.Identifier && MUTATING_METHODS.has(parent.property.name) && grandparent.type === AST_NODE_TYPES28.CallExpression && grandparent.callee === parent) {
6627
6289
  return false;
6628
6290
  }
6629
6291
  return true;
6630
6292
  }
6631
- if (parent.type === AST_NODE_TYPES29.ForOfStatement && parent.right === identifier) {
6293
+ if (parent.type === AST_NODE_TYPES28.ForOfStatement && parent.right === identifier) {
6632
6294
  return true;
6633
6295
  }
6634
- if (parent.type === AST_NODE_TYPES29.SpreadElement) {
6296
+ if (parent.type === AST_NODE_TYPES28.SpreadElement) {
6635
6297
  return true;
6636
6298
  }
6637
- if (parent.type === AST_NODE_TYPES29.BinaryExpression) {
6299
+ if (parent.type === AST_NODE_TYPES28.BinaryExpression) {
6638
6300
  return true;
6639
6301
  }
6640
- if (parent.type === AST_NODE_TYPES29.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6302
+ if (parent.type === AST_NODE_TYPES28.CallExpression && parent.arguments.includes(identifier) && isNonRetainingBuiltinCall(parent, identifier)) {
6641
6303
  return true;
6642
6304
  }
6643
- if (parent.type === AST_NODE_TYPES29.UnaryExpression && parent.operator !== "delete") {
6305
+ if (parent.type === AST_NODE_TYPES28.UnaryExpression && parent.operator !== "delete") {
6644
6306
  return true;
6645
6307
  }
6646
6308
  return false;
6647
6309
  }
6648
- var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6310
+ var prefer_module_level_constant_default = ESLintUtils40.RuleCreator(
6649
6311
  (name) => `https://github.com/sarj-ai/linting/blob/main/packages/typescript/src/rules/${name}.ts`
6650
6312
  )({
6651
6313
  name: "prefer-module-level-constant",
@@ -6697,7 +6359,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6697
6359
  if (reference.isWrite()) {
6698
6360
  return false;
6699
6361
  }
6700
- if (reference.identifier.type !== AST_NODE_TYPES29.Identifier) {
6362
+ if (reference.identifier.type !== AST_NODE_TYPES28.Identifier) {
6701
6363
  return false;
6702
6364
  }
6703
6365
  if (!isSafeRead(reference.identifier)) {
@@ -6709,10 +6371,10 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6709
6371
  return {
6710
6372
  VariableDeclarator(node) {
6711
6373
  const declaration = node.parent;
6712
- if (declaration.type !== AST_NODE_TYPES29.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6374
+ if (declaration.type !== AST_NODE_TYPES28.VariableDeclaration || declaration.kind !== "const" || declaration.declare === true) {
6713
6375
  return;
6714
6376
  }
6715
- if (node.id.type !== AST_NODE_TYPES29.Identifier || node.init === null) {
6377
+ if (node.id.type !== AST_NODE_TYPES28.Identifier || node.init === null) {
6716
6378
  return;
6717
6379
  }
6718
6380
  if (enclosingFunction2(node) === null) {
@@ -6739,7 +6401,7 @@ var prefer_module_level_constant_default = ESLintUtils41.RuleCreator(
6739
6401
  });
6740
6402
 
6741
6403
  // src/rules/jsdoc-restates-signature.ts
6742
- import { AST_NODE_TYPES as AST_NODE_TYPES30, ESLintUtils as ESLintUtils42 } from "@typescript-eslint/utils";
6404
+ import { AST_NODE_TYPES as AST_NODE_TYPES29, ESLintUtils as ESLintUtils41 } from "@typescript-eslint/utils";
6743
6405
  var VALUE_TAGS = /* @__PURE__ */ new Set([
6744
6406
  "alpha",
6745
6407
  "author",
@@ -6822,30 +6484,30 @@ function declarationNames(node) {
6822
6484
  switch (node.type) {
6823
6485
  // `export function f()` — the JSDoc sits above the `export`, so the token
6824
6486
  // after it resolves to the wrapper, not to the thing being documented.
6825
- case AST_NODE_TYPES30.ExportNamedDeclaration:
6826
- case AST_NODE_TYPES30.ExportDefaultDeclaration:
6487
+ case AST_NODE_TYPES29.ExportNamedDeclaration:
6488
+ case AST_NODE_TYPES29.ExportDefaultDeclaration:
6827
6489
  return node.declaration == null ? null : declarationNames(node.declaration);
6828
- case AST_NODE_TYPES30.FunctionDeclaration:
6829
- case AST_NODE_TYPES30.TSDeclareFunction:
6490
+ case AST_NODE_TYPES29.FunctionDeclaration:
6491
+ case AST_NODE_TYPES29.TSDeclareFunction:
6830
6492
  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:
6493
+ case AST_NODE_TYPES29.ClassDeclaration:
6494
+ case AST_NODE_TYPES29.TSInterfaceDeclaration:
6495
+ case AST_NODE_TYPES29.TSTypeAliasDeclaration:
6496
+ case AST_NODE_TYPES29.TSEnumDeclaration:
6835
6497
  return node.id === null ? null : { name: node.id.name, params: [] };
6836
- case AST_NODE_TYPES30.VariableDeclaration: {
6498
+ case AST_NODE_TYPES29.VariableDeclaration: {
6837
6499
  const declarator = node.declarations[0];
6838
- if (declarator === void 0 || declarator.id.type !== AST_NODE_TYPES30.Identifier) return null;
6500
+ if (declarator === void 0 || declarator.id.type !== AST_NODE_TYPES29.Identifier) return null;
6839
6501
  const init = declarator.init;
6840
- const params = init != null && (init.type === AST_NODE_TYPES30.ArrowFunctionExpression || init.type === AST_NODE_TYPES30.FunctionExpression) ? paramNames(init.params) : [];
6502
+ const params = init != null && (init.type === AST_NODE_TYPES29.ArrowFunctionExpression || init.type === AST_NODE_TYPES29.FunctionExpression) ? paramNames(init.params) : [];
6841
6503
  return { name: declarator.id.name, params };
6842
6504
  }
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) : [];
6505
+ case AST_NODE_TYPES29.MethodDefinition:
6506
+ case AST_NODE_TYPES29.PropertyDefinition:
6507
+ case AST_NODE_TYPES29.TSMethodSignature:
6508
+ case AST_NODE_TYPES29.TSPropertySignature: {
6509
+ if (node.key.type !== AST_NODE_TYPES29.Identifier) return null;
6510
+ const params = node.type === AST_NODE_TYPES29.MethodDefinition ? paramNames(node.value.params) : node.type === AST_NODE_TYPES29.TSMethodSignature ? paramNames(node.params) : [];
6849
6511
  return { name: node.key.name, params };
6850
6512
  }
6851
6513
  default:
@@ -6855,9 +6517,9 @@ function declarationNames(node) {
6855
6517
  function paramNames(params) {
6856
6518
  const names = [];
6857
6519
  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;
6520
+ const target = param.type === AST_NODE_TYPES29.AssignmentPattern ? param.left : param;
6521
+ if (target.type === AST_NODE_TYPES29.Identifier) names.push(target.name);
6522
+ else if (target.type === AST_NODE_TYPES29.TSParameterProperty) continue;
6861
6523
  }
6862
6524
  return names;
6863
6525
  }
@@ -6866,7 +6528,7 @@ function tokensOf(names) {
6866
6528
  for (const name of names) for (const part of splitIdentifier(name)) tokens.add(part);
6867
6529
  return tokens;
6868
6530
  }
6869
- var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
6531
+ var jsdoc_restates_signature_default = ESLintUtils41.RuleCreator(
6870
6532
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6871
6533
  )({
6872
6534
  name: "jsdoc-restates-signature",
@@ -6902,7 +6564,7 @@ var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
6902
6564
  if (token === null || token.loc.start.line !== comment.loc.end.line + 1) continue;
6903
6565
  let node = sourceCode.getNodeByRangeIndex(token.range[0]);
6904
6566
  let declaration = null;
6905
- while (node != null && node.type !== AST_NODE_TYPES30.Program) {
6567
+ while (node != null && node.type !== AST_NODE_TYPES29.Program) {
6906
6568
  declaration = declarationNames(node);
6907
6569
  if (declaration !== null) break;
6908
6570
  node = node.parent ?? null;
@@ -6957,7 +6619,7 @@ var jsdoc_restates_signature_default = ESLintUtils42.RuleCreator(
6957
6619
  });
6958
6620
 
6959
6621
  // src/rules/no-restated-comment.ts
6960
- import { AST_NODE_TYPES as AST_NODE_TYPES31, ESLintUtils as ESLintUtils43 } from "@typescript-eslint/utils";
6622
+ import { AST_NODE_TYPES as AST_NODE_TYPES30, ESLintUtils as ESLintUtils42 } from "@typescript-eslint/utils";
6961
6623
  var MAX_WORDS = 8;
6962
6624
  var MIN_CONTENT_TOKENS = 2;
6963
6625
  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 +6643,7 @@ function headsSiblingRun(node) {
6981
6643
  const next = index >= 0 ? body[index + 1] : void 0;
6982
6644
  return next !== void 0 && next.type === node.type;
6983
6645
  }
6984
- var no_restated_comment_default = ESLintUtils43.RuleCreator(
6646
+ var no_restated_comment_default = ESLintUtils42.RuleCreator(
6985
6647
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
6986
6648
  )({
6987
6649
  name: "no-restated-comment",
@@ -7009,7 +6671,7 @@ var no_restated_comment_default = ESLintUtils43.RuleCreator(
7009
6671
  function labelsASiblingRun(comment) {
7010
6672
  const token = sourceCode.getTokenAfter(comment, { includeComments: false });
7011
6673
  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) {
6674
+ for (let node = sourceCode.getNodeByRangeIndex(token.range[0]); node != null && node.type !== AST_NODE_TYPES30.Program; node = node.parent) {
7013
6675
  if (headsSiblingRun(node)) return true;
7014
6676
  }
7015
6677
  return false;
@@ -7049,7 +6711,7 @@ var no_restated_comment_default = ESLintUtils43.RuleCreator(
7049
6711
  });
7050
6712
 
7051
6713
  // src/rules/trailing-value-narration.ts
7052
- import { ESLintUtils as ESLintUtils44 } from "@typescript-eslint/utils";
6714
+ import { ESLintUtils as ESLintUtils43 } from "@typescript-eslint/utils";
7053
6715
  var NUMBER_RE = /(?<![\w.])(\d+(?:\.\d+)?)(?![\w.])/g;
7054
6716
  var WORD_RE3 = /[A-Za-z]+(?:'[a-z]+)?|\d+(?:\.\d+)?/g;
7055
6717
  var UNIT_WORDS = /* @__PURE__ */ new Set([
@@ -7133,7 +6795,7 @@ function narratesValue(body, code) {
7133
6795
  (word) => STOPWORDS3.has(word) || UNIT_WORDS.has(word) || commentNumbers.has(word) || identifiers.has(word) || stems.has(stem(word))
7134
6796
  );
7135
6797
  }
7136
- var trailing_value_narration_default = ESLintUtils44.RuleCreator(
6798
+ var trailing_value_narration_default = ESLintUtils43.RuleCreator(
7137
6799
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7138
6800
  )({
7139
6801
  name: "trailing-value-narration",
@@ -7174,7 +6836,7 @@ var trailing_value_narration_default = ESLintUtils44.RuleCreator(
7174
6836
  });
7175
6837
 
7176
6838
  // src/rules/no-tautological-expect.ts
7177
- import { AST_NODE_TYPES as AST_NODE_TYPES32, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
6839
+ import { AST_NODE_TYPES as AST_NODE_TYPES31, ESLintUtils as ESLintUtils44 } from "@typescript-eslint/utils";
7178
6840
  var EQUALITY_MATCHERS = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
7179
6841
  var ZERO_ARG_MATCHERS = /* @__PURE__ */ new Set([
7180
6842
  "toBeDefined",
@@ -7188,17 +6850,17 @@ var OPERAND_PREVIEW_CHARS = 40;
7188
6850
  var NUMERIC_SIGNS = /* @__PURE__ */ new Set(["-", "+"]);
7189
6851
  function isLiteral(node) {
7190
6852
  switch (node.type) {
7191
- case AST_NODE_TYPES32.Literal:
6853
+ case AST_NODE_TYPES31.Literal:
7192
6854
  return true;
7193
- case AST_NODE_TYPES32.TemplateLiteral:
6855
+ case AST_NODE_TYPES31.TemplateLiteral:
7194
6856
  return node.expressions.length === 0;
7195
- case AST_NODE_TYPES32.UnaryExpression:
6857
+ case AST_NODE_TYPES31.UnaryExpression:
7196
6858
  return NUMERIC_SIGNS.has(node.operator) && isLiteral(node.argument);
7197
- case AST_NODE_TYPES32.ArrayExpression:
6859
+ case AST_NODE_TYPES31.ArrayExpression:
7198
6860
  return node.elements.every((element) => element !== null && isLiteral(element));
7199
- case AST_NODE_TYPES32.ObjectExpression:
6861
+ case AST_NODE_TYPES31.ObjectExpression:
7200
6862
  return node.properties.every(
7201
- (property) => property.type === AST_NODE_TYPES32.Property && !property.computed && isLiteral(property.value)
6863
+ (property) => property.type === AST_NODE_TYPES31.Property && !property.computed && isLiteral(property.value)
7202
6864
  );
7203
6865
  default:
7204
6866
  return false;
@@ -7206,12 +6868,12 @@ function isLiteral(node) {
7206
6868
  }
7207
6869
  function expectOperand(callee) {
7208
6870
  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) {
6871
+ if (receiver.type !== AST_NODE_TYPES31.CallExpression || receiver.callee.type !== AST_NODE_TYPES31.Identifier || receiver.callee.name !== "expect" || receiver.arguments.length !== 1) {
7210
6872
  return null;
7211
6873
  }
7212
6874
  return receiver.arguments[0] ?? null;
7213
6875
  }
7214
- var no_tautological_expect_default = ESLintUtils45.RuleCreator(
6876
+ var no_tautological_expect_default = ESLintUtils44.RuleCreator(
7215
6877
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7216
6878
  )({
7217
6879
  name: "no-tautological-expect",
@@ -7238,10 +6900,10 @@ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7238
6900
  return {
7239
6901
  CallExpression(node) {
7240
6902
  const callee = node.callee;
7241
- if (callee.type !== AST_NODE_TYPES32.MemberExpression || callee.computed) {
6903
+ if (callee.type !== AST_NODE_TYPES31.MemberExpression || callee.computed) {
7242
6904
  return;
7243
6905
  }
7244
- if (callee.property.type !== AST_NODE_TYPES32.Identifier) {
6906
+ if (callee.property.type !== AST_NODE_TYPES31.Identifier) {
7245
6907
  return;
7246
6908
  }
7247
6909
  const matcher = callee.property.name;
@@ -7275,26 +6937,26 @@ var no_tautological_expect_default = ESLintUtils45.RuleCreator(
7275
6937
  });
7276
6938
 
7277
6939
  // src/rules/require-interface-for-injected-service.ts
7278
- import { AST_NODE_TYPES as AST_NODE_TYPES33, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
6940
+ import { AST_NODE_TYPES as AST_NODE_TYPES32, ESLintUtils as ESLintUtils45 } from "@typescript-eslint/utils";
7279
6941
  var CONFIGISH_TYPE_RE = /(?:Options|Opts|Config|Configuration|Settings|Params|Props|Args|Env|Environment|Callbacks|Flags)$/;
7280
6942
  var CONFIGISH_NAME_RE = /^(?:options|opts|config|configuration|settings|params|props|args|env|environment|callbacks|flags|logger|log|clock)$/i;
7281
6943
  var HTTP_TRANSPORT_TYPE_RE = /^(?:KyInstance|AxiosInstance|Session)$/;
7282
6944
  var TRANSPORT_WRAPPER_NAME_RE = /Client$/;
7283
6945
  var ROUTER_FACTORY_NAME = "Router";
7284
6946
  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}` : "";
6947
+ var isExportedClass = (node) => node.parent.type === AST_NODE_TYPES32.ExportNamedDeclaration || node.parent.type === AST_NODE_TYPES32.ExportDefaultDeclaration;
6948
+ var qualifiedName = (name) => name.type === AST_NODE_TYPES32.Identifier ? name.name : name.type === AST_NODE_TYPES32.TSQualifiedName ? `${qualifiedName(name.left)}.${name.right.name}` : "";
7287
6949
  var typeReferenceName = (annotated) => {
7288
6950
  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;
6951
+ if (target.type === AST_NODE_TYPES32.TSParameterProperty) target = target.parameter;
6952
+ if (target.type === AST_NODE_TYPES32.AssignmentPattern) target = target.left;
6953
+ if (target.type !== AST_NODE_TYPES32.Identifier) return null;
7292
6954
  const annotation = target.typeAnnotation?.typeAnnotation;
7293
- if (annotation === void 0 || annotation.type !== AST_NODE_TYPES33.TSTypeReference) {
6955
+ if (annotation === void 0 || annotation.type !== AST_NODE_TYPES32.TSTypeReference) {
7294
6956
  return null;
7295
6957
  }
7296
6958
  const { typeName } = annotation;
7297
- const rightmost = typeName.type === AST_NODE_TYPES33.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES33.TSQualifiedName ? typeName.right.name : null;
6959
+ const rightmost = typeName.type === AST_NODE_TYPES32.Identifier ? typeName.name : typeName.type === AST_NODE_TYPES32.TSQualifiedName ? typeName.right.name : null;
7298
6960
  if (rightmost === null) return null;
7299
6961
  return { name: target.name, typeName: rightmost, display: qualifiedName(typeName) };
7300
6962
  };
@@ -7304,17 +6966,17 @@ var readConstructor = (ctor) => {
7304
6966
  let constructedFields = 0;
7305
6967
  if (body !== null && body !== void 0) {
7306
6968
  for (const statement of body.body) {
7307
- if (statement.type !== AST_NODE_TYPES33.ExpressionStatement) continue;
6969
+ if (statement.type !== AST_NODE_TYPES32.ExpressionStatement) continue;
7308
6970
  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) {
6971
+ if (expression.type !== AST_NODE_TYPES32.AssignmentExpression || expression.operator !== "=" || expression.left.type !== AST_NODE_TYPES32.MemberExpression || expression.left.object.type !== AST_NODE_TYPES32.ThisExpression) {
7310
6972
  continue;
7311
6973
  }
7312
6974
  const source = expression.right;
7313
- if (source.type === AST_NODE_TYPES33.NewExpression) {
6975
+ if (source.type === AST_NODE_TYPES32.NewExpression) {
7314
6976
  constructedFields += 1;
7315
- } else if (source.type === AST_NODE_TYPES33.Identifier) {
6977
+ } else if (source.type === AST_NODE_TYPES32.Identifier) {
7316
6978
  storedFrom.add(source.name);
7317
- } else if (source.type === AST_NODE_TYPES33.MemberExpression && source.object.type === AST_NODE_TYPES33.Identifier) {
6979
+ } else if (source.type === AST_NODE_TYPES32.MemberExpression && source.object.type === AST_NODE_TYPES32.Identifier) {
7318
6980
  storedFrom.add(source.object.name);
7319
6981
  }
7320
6982
  }
@@ -7323,7 +6985,7 @@ var readConstructor = (ctor) => {
7323
6985
  for (const parameter of ctor.value.params) {
7324
6986
  const reference = typeReferenceName(parameter);
7325
6987
  if (reference === null) continue;
7326
- const stored = parameter.type === AST_NODE_TYPES33.TSParameterProperty || storedFrom.has(reference.name);
6988
+ const stored = parameter.type === AST_NODE_TYPES32.TSParameterProperty || storedFrom.has(reference.name);
7327
6989
  if (!stored) continue;
7328
6990
  if (CONFIGISH_TYPE_RE.test(reference.typeName)) continue;
7329
6991
  if (CONFIGISH_NAME_RE.test(reference.name)) continue;
@@ -7353,19 +7015,19 @@ var subtreeHas = (root, found) => {
7353
7015
  return hit;
7354
7016
  };
7355
7017
  var isFrameworkWiring = (body) => subtreeHas(body, (node) => {
7356
- if (node.type === AST_NODE_TYPES33.CallExpression) {
7018
+ if (node.type === AST_NODE_TYPES32.CallExpression) {
7357
7019
  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;
7020
+ if (callee.type === AST_NODE_TYPES32.Identifier) return callee.name === ROUTER_FACTORY_NAME;
7021
+ return callee.type === AST_NODE_TYPES32.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES32.Identifier && callee.property.name === ROUTER_FACTORY_NAME;
7360
7022
  }
7361
- return node.type === AST_NODE_TYPES33.TSTypeReference && node.typeName.type === AST_NODE_TYPES33.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7023
+ return node.type === AST_NODE_TYPES32.TSTypeReference && node.typeName.type === AST_NODE_TYPES32.TSQualifiedName && FRAMEWORK_HTTP_TYPES.has(node.typeName.right.name);
7362
7024
  });
7363
7025
  var stem2 = (name) => name.replace(/^I(?=[A-Z])/, "").replace(/Impl$/, "");
7364
7026
  var fileInterfaceNames = (program) => {
7365
7027
  const names = [];
7366
7028
  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);
7029
+ const declaration = statement.type === AST_NODE_TYPES32.ExportNamedDeclaration ? statement.declaration : statement;
7030
+ if (declaration?.type === AST_NODE_TYPES32.TSInterfaceDeclaration) names.push(declaration.id.name);
7369
7031
  }
7370
7032
  return names;
7371
7033
  };
@@ -7383,16 +7045,16 @@ var isTransportWrapper = (className, collaborators, program) => {
7383
7045
  var publicMethodNames = (body) => {
7384
7046
  const names = [];
7385
7047
  for (const member of body.body) {
7386
- if (member.type !== AST_NODE_TYPES33.MethodDefinition) continue;
7048
+ if (member.type !== AST_NODE_TYPES32.MethodDefinition) continue;
7387
7049
  if (member.kind !== "method" || member.static) continue;
7388
7050
  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);
7051
+ if (member.key.type === AST_NODE_TYPES32.PrivateIdentifier) continue;
7052
+ if (member.key.type === AST_NODE_TYPES32.Identifier) names.push(member.key.name);
7391
7053
  else names.push("\u2026");
7392
7054
  }
7393
7055
  return names;
7394
7056
  };
7395
- var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7057
+ var require_interface_for_injected_service_default = ESLintUtils45.RuleCreator(
7396
7058
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7397
7059
  )({
7398
7060
  name: "require-interface-for-injected-service",
@@ -7420,7 +7082,7 @@ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7420
7082
  if (node.implements.length > 0) return;
7421
7083
  if (node.decorators.length > 0) return;
7422
7084
  const ctor = node.body.body.find(
7423
- (member) => member.type === AST_NODE_TYPES33.MethodDefinition && member.kind === "constructor"
7085
+ (member) => member.type === AST_NODE_TYPES32.MethodDefinition && member.kind === "constructor"
7424
7086
  );
7425
7087
  if (ctor === void 0) return;
7426
7088
  const { collaborators, constructedFields } = readConstructor(ctor);
@@ -7445,26 +7107,26 @@ var require_interface_for_injected_service_default = ESLintUtils46.RuleCreator(
7445
7107
  });
7446
7108
 
7447
7109
  // src/rules/prefer-non-nullable-collection.ts
7448
- import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
7110
+ import { AST_NODE_TYPES as AST_NODE_TYPES33, ESLintUtils as ESLintUtils46 } from "@typescript-eslint/utils";
7449
7111
  var ARRAY_TYPE_NAMES = /* @__PURE__ */ new Set(["Array", "ReadonlyArray"]);
7450
7112
  function propertyName(node) {
7451
7113
  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);
7114
+ if (key.type === AST_NODE_TYPES33.Identifier) return key.name;
7115
+ if (key.type === AST_NODE_TYPES33.Literal) return String(key.value);
7454
7116
  return "collection";
7455
7117
  }
7456
7118
  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);
7119
+ if (node.type === AST_NODE_TYPES33.TSArrayType) return true;
7120
+ return node.type === AST_NODE_TYPES33.TSTypeReference && node.typeName.type === AST_NODE_TYPES33.Identifier && ARRAY_TYPE_NAMES.has(node.typeName.name);
7459
7121
  }
7460
7122
  function isNullishType(node) {
7461
- return node.type === AST_NODE_TYPES34.TSNullKeyword || node.type === AST_NODE_TYPES34.TSUndefinedKeyword;
7123
+ return node.type === AST_NODE_TYPES33.TSNullKeyword || node.type === AST_NODE_TYPES33.TSUndefinedKeyword;
7462
7124
  }
7463
7125
  function isNullableArrayOnly(node) {
7464
7126
  const values = node.types.filter((member) => !isNullishType(member));
7465
7127
  return values.length > 0 && values.length < node.types.length && values.every(isArrayType);
7466
7128
  }
7467
- var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7129
+ var prefer_non_nullable_collection_default = ESLintUtils46.RuleCreator(
7468
7130
  (name) => `https://github.com/sarj-ai/standards/tree/main/packages/typescript#${name}`
7469
7131
  )({
7470
7132
  name: "prefer-non-nullable-collection",
@@ -7487,7 +7149,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7487
7149
  function checkOptionalProperty(node) {
7488
7150
  const annotation = node.typeAnnotation?.typeAnnotation;
7489
7151
  if (annotation === void 0) return;
7490
- if (annotation.type !== AST_NODE_TYPES34.TSUnionType || !isNullableArrayOnly(annotation)) {
7152
+ if (annotation.type !== AST_NODE_TYPES33.TSUnionType || !isNullableArrayOnly(annotation)) {
7491
7153
  return;
7492
7154
  }
7493
7155
  context.report({
@@ -7500,7 +7162,7 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7500
7162
  TSPropertySignature: checkOptionalProperty,
7501
7163
  PropertyDefinition: checkOptionalProperty,
7502
7164
  TSTypeAliasDeclaration(node) {
7503
- if (node.typeAnnotation.type !== AST_NODE_TYPES34.TSUnionType) return;
7165
+ if (node.typeAnnotation.type !== AST_NODE_TYPES33.TSUnionType) return;
7504
7166
  if (!isNullableArrayOnly(node.typeAnnotation)) return;
7505
7167
  context.report({
7506
7168
  node,
@@ -7513,41 +7175,41 @@ var prefer_non_nullable_collection_default = ESLintUtils47.RuleCreator(
7513
7175
  });
7514
7176
 
7515
7177
  // src/rules/primary-export-file-name.ts
7516
- import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
7517
- var CONVENTIONAL_BUCKET_EXPORTS2 = /* @__PURE__ */ new Set(["cn"]);
7178
+ import { AST_NODE_TYPES as AST_NODE_TYPES34, ESLintUtils as ESLintUtils47 } from "@typescript-eslint/utils";
7179
+ var CONVENTIONAL_BUCKET_EXPORTS = /* @__PURE__ */ new Set(["cn"]);
7518
7180
  var GENERIC_ENTRYPOINTS = /* @__PURE__ */ new Set(["main", "run", "cli", "setup", "teardown", "execute"]);
7519
- var ACRONYM_OVERRIDES2 = [
7181
+ var ACRONYM_OVERRIDES = [
7520
7182
  [/OAuth/g, "Oauth"],
7521
7183
  [/GraphQL/g, "Graphql"],
7522
7184
  [/gRPC/g, "Grpc"]
7523
7185
  ];
7524
- var CAMEL_BOUNDARY_RE2 = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;
7525
- var basename2 = (filename) => filename.split(/[/\\]/).pop() ?? filename;
7526
- var stemOf2 = (base) => base.replace(/\.(test|spec|config|d|stories)\.[cm]?[jt]sx?$/i, "").replace(/\.[cm]?[jt]sx?$/i, "");
7527
- var kebabCase3 = (name) => {
7186
+ var CAMEL_BOUNDARY_RE = /(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/g;
7187
+ var basename = (filename) => filename.split(/[/\\]/).pop() ?? filename;
7188
+ var stemOf = (base) => base.replace(/\.(test|spec|config|d|stories)\.[cm]?[jt]sx?$/i, "").replace(/\.[cm]?[jt]sx?$/i, "");
7189
+ var kebabCase = (name) => {
7528
7190
  let normalized = name;
7529
- for (const [pattern, replacement] of ACRONYM_OVERRIDES2) {
7191
+ for (const [pattern, replacement] of ACRONYM_OVERRIDES) {
7530
7192
  normalized = normalized.replace(pattern, replacement);
7531
7193
  }
7532
- return normalized.replace(CAMEL_BOUNDARY_RE2, "-").toLowerCase();
7194
+ return normalized.replace(CAMEL_BOUNDARY_RE, "-").toLowerCase();
7533
7195
  };
7534
- var isFunctionOrClass = (node) => node.type === AST_NODE_TYPES35.ArrowFunctionExpression || node.type === AST_NODE_TYPES35.FunctionExpression;
7196
+ var isFunctionOrClass = (node) => node.type === AST_NODE_TYPES34.ArrowFunctionExpression || node.type === AST_NODE_TYPES34.FunctionExpression;
7535
7197
  var findPrimaryExport = (body) => {
7536
7198
  let exportCount = 0;
7537
7199
  let primaryCandidate = null;
7538
7200
  for (const statement of body) {
7539
- if (statement.type === AST_NODE_TYPES35.ExportAllDeclaration) {
7201
+ if (statement.type === AST_NODE_TYPES34.ExportAllDeclaration) {
7540
7202
  return null;
7541
7203
  }
7542
- if (statement.type === AST_NODE_TYPES35.ExportDefaultDeclaration) {
7204
+ if (statement.type === AST_NODE_TYPES34.ExportDefaultDeclaration) {
7543
7205
  exportCount += 1;
7544
7206
  const decl = statement.declaration;
7545
- if ((decl.type === AST_NODE_TYPES35.FunctionDeclaration || decl.type === AST_NODE_TYPES35.ClassDeclaration) && decl.id !== null) {
7207
+ if ((decl.type === AST_NODE_TYPES34.FunctionDeclaration || decl.type === AST_NODE_TYPES34.ClassDeclaration) && decl.id !== null) {
7546
7208
  primaryCandidate = { name: decl.id.name, node: statement, isDefault: true };
7547
- } else if (decl.type === AST_NODE_TYPES35.Identifier) {
7209
+ } else if (decl.type === AST_NODE_TYPES34.Identifier) {
7548
7210
  primaryCandidate = { name: decl.name, node: statement, isDefault: true };
7549
7211
  }
7550
- } else if (statement.type === AST_NODE_TYPES35.ExportNamedDeclaration) {
7212
+ } else if (statement.type === AST_NODE_TYPES34.ExportNamedDeclaration) {
7551
7213
  if (statement.source !== null) {
7552
7214
  return null;
7553
7215
  }
@@ -7556,27 +7218,27 @@ var findPrimaryExport = (body) => {
7556
7218
  exportCount += statement.specifiers.length;
7557
7219
  if (statement.specifiers.length === 1 && primaryCandidate === null) {
7558
7220
  const spec = statement.specifiers[0];
7559
- if (spec && spec.exported.type === AST_NODE_TYPES35.Identifier) {
7221
+ if (spec && spec.exported.type === AST_NODE_TYPES34.Identifier) {
7560
7222
  primaryCandidate = { name: spec.exported.name, node: statement, isDefault: false };
7561
7223
  }
7562
7224
  }
7563
- } else if (decl.type === AST_NODE_TYPES35.FunctionDeclaration || decl.type === AST_NODE_TYPES35.ClassDeclaration) {
7225
+ } else if (decl.type === AST_NODE_TYPES34.FunctionDeclaration || decl.type === AST_NODE_TYPES34.ClassDeclaration) {
7564
7226
  if (decl.id !== null) {
7565
7227
  exportCount += 1;
7566
7228
  if (primaryCandidate === null) {
7567
7229
  primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
7568
7230
  }
7569
7231
  }
7570
- } else if (decl.type === AST_NODE_TYPES35.VariableDeclaration) {
7232
+ } else if (decl.type === AST_NODE_TYPES34.VariableDeclaration) {
7571
7233
  for (const declarator of decl.declarations) {
7572
- if (declarator.id.type === AST_NODE_TYPES35.Identifier) {
7234
+ if (declarator.id.type === AST_NODE_TYPES34.Identifier) {
7573
7235
  exportCount += 1;
7574
7236
  if (primaryCandidate === null && declarator.init && isFunctionOrClass(declarator.init)) {
7575
7237
  primaryCandidate = { name: declarator.id.name, node: statement, isDefault: false };
7576
7238
  }
7577
7239
  }
7578
7240
  }
7579
- } else if (decl.type === AST_NODE_TYPES35.TSTypeAliasDeclaration || decl.type === AST_NODE_TYPES35.TSInterfaceDeclaration) {
7241
+ } else if (decl.type === AST_NODE_TYPES34.TSTypeAliasDeclaration || decl.type === AST_NODE_TYPES34.TSInterfaceDeclaration) {
7580
7242
  exportCount += 1;
7581
7243
  if (primaryCandidate === null) {
7582
7244
  primaryCandidate = { name: decl.id.name, node: statement, isDefault: false };
@@ -7589,7 +7251,7 @@ var findPrimaryExport = (body) => {
7589
7251
  }
7590
7252
  return { ...primaryCandidate, count: exportCount };
7591
7253
  };
7592
- var primary_export_file_name_default = ESLintUtils48.RuleCreator(
7254
+ var primary_export_file_name_default = ESLintUtils47.RuleCreator(
7593
7255
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7594
7256
  )({
7595
7257
  name: "primary-export-file-name",
@@ -7605,10 +7267,10 @@ var primary_export_file_name_default = ESLintUtils48.RuleCreator(
7605
7267
  },
7606
7268
  defaultOptions: [],
7607
7269
  create(context) {
7608
- const base = basename2(context.filename);
7270
+ const base = basename(context.filename);
7609
7271
  if (base.endsWith(".d.ts") || base.startsWith("index.") || base.startsWith("_")) return {};
7610
7272
  if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
7611
- const stem3 = stemOf2(base);
7273
+ const stem3 = stemOf(base);
7612
7274
  if (stem3 === "page" || stem3 === "layout" || stem3 === "loading" || stem3 === "error" || stem3 === "not-found" || stem3 === "route" || stem3 === "__root" || stem3 === "config" || stem3 === "constants" || stem3 === "types" || stem3.startsWith("$") || stem3.startsWith("[")) {
7613
7275
  return {};
7614
7276
  }
@@ -7616,8 +7278,8 @@ var primary_export_file_name_default = ESLintUtils48.RuleCreator(
7616
7278
  Program(node) {
7617
7279
  const primary = findPrimaryExport(node.body);
7618
7280
  if (primary === null) return;
7619
- if (CONVENTIONAL_BUCKET_EXPORTS2.has(primary.name) || GENERIC_ENTRYPOINTS.has(primary.name)) return;
7620
- const expectedStem = kebabCase3(primary.name);
7281
+ if (CONVENTIONAL_BUCKET_EXPORTS.has(primary.name) || GENERIC_ENTRYPOINTS.has(primary.name)) return;
7282
+ const expectedStem = kebabCase(primary.name);
7621
7283
  if (stem3 === expectedStem) return;
7622
7284
  const ext = base.endsWith(".tsx") ? ".tsx" : ".ts";
7623
7285
  context.report({
@@ -7631,7 +7293,7 @@ var primary_export_file_name_default = ESLintUtils48.RuleCreator(
7631
7293
  });
7632
7294
 
7633
7295
  // src/rules/no-implicit-attribute-access.ts
7634
- import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
7296
+ import { AST_NODE_TYPES as AST_NODE_TYPES35, ESLintUtils as ESLintUtils48 } from "@typescript-eslint/utils";
7635
7297
  var EXCLUDED_BASES = /* @__PURE__ */ new Set([
7636
7298
  "environ",
7637
7299
  "headers",
@@ -7647,15 +7309,15 @@ var EXCLUDED_BASES = /* @__PURE__ */ new Set([
7647
7309
  "sessionStorage"
7648
7310
  ]);
7649
7311
  function getBaseName(node) {
7650
- if (node.type === AST_NODE_TYPES36.Identifier) {
7312
+ if (node.type === AST_NODE_TYPES35.Identifier) {
7651
7313
  return node.name;
7652
7314
  }
7653
- if (node.type === AST_NODE_TYPES36.MemberExpression && node.property.type === AST_NODE_TYPES36.Identifier) {
7315
+ if (node.type === AST_NODE_TYPES35.MemberExpression && node.property.type === AST_NODE_TYPES35.Identifier) {
7654
7316
  return node.property.name;
7655
7317
  }
7656
7318
  return null;
7657
7319
  }
7658
- var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7320
+ var no_implicit_attribute_access_default = ESLintUtils48.RuleCreator(
7659
7321
  (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7660
7322
  )({
7661
7323
  name: "no-implicit-attribute-access",
@@ -7676,7 +7338,7 @@ var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7676
7338
  if (!node.computed) {
7677
7339
  return;
7678
7340
  }
7679
- if (node.property.type === AST_NODE_TYPES36.Literal && typeof node.property.value === "string") {
7341
+ if (node.property.type === AST_NODE_TYPES35.Literal && typeof node.property.value === "string") {
7680
7342
  const baseName = getBaseName(node.object);
7681
7343
  if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7682
7344
  context.report({
@@ -7689,11 +7351,11 @@ var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7689
7351
  },
7690
7352
  CallExpression(node) {
7691
7353
  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;
7354
+ if (callee.type === AST_NODE_TYPES35.MemberExpression) {
7355
+ const method = callee.property.type === AST_NODE_TYPES35.Identifier ? callee.property.name : null;
7694
7356
  if (method === "get") {
7695
7357
  const arg = node.arguments[0];
7696
- if (arg && arg.type === AST_NODE_TYPES36.Literal && typeof arg.value === "string") {
7358
+ if (arg && arg.type === AST_NODE_TYPES35.Literal && typeof arg.value === "string") {
7697
7359
  const baseName = getBaseName(callee.object);
7698
7360
  if (!baseName || !EXCLUDED_BASES.has(baseName)) {
7699
7361
  context.report({
@@ -7710,8 +7372,174 @@ var no_implicit_attribute_access_default = ESLintUtils49.RuleCreator(
7710
7372
  }
7711
7373
  });
7712
7374
 
7375
+ // src/rules/strict-test-assertions.ts
7376
+ import { AST_NODE_TYPES as AST_NODE_TYPES36, ESLintUtils as ESLintUtils49 } from "@typescript-eslint/utils";
7377
+ var strict_test_assertions_default = ESLintUtils49.RuleCreator.withoutDocs({
7378
+ meta: {
7379
+ type: "suggestion",
7380
+ docs: {
7381
+ description: "Replace multiple sequential assertions with a single toMatchObject or toStrictEqual"
7382
+ },
7383
+ fixable: "code",
7384
+ messages: {
7385
+ combineAssertions: "Combine multiple sequential assertions on the same object into a single toMatchObject or toStrictEqual"
7386
+ },
7387
+ schema: []
7388
+ },
7389
+ defaultOptions: [],
7390
+ create(context) {
7391
+ function checkBody(body) {
7392
+ let currentObject = null;
7393
+ let sequence = [];
7394
+ function getExpectObject(expr) {
7395
+ if (expr.type === AST_NODE_TYPES36.CallExpression && expr.callee.type === AST_NODE_TYPES36.MemberExpression && expr.callee.object.type === AST_NODE_TYPES36.CallExpression && expr.callee.object.callee.type === AST_NODE_TYPES36.Identifier && expr.callee.object.callee.name === "expect" && expr.callee.object.arguments.length === 1) {
7396
+ const arg = expr.callee.object.arguments.at(0);
7397
+ if (arg?.type === AST_NODE_TYPES36.MemberExpression) {
7398
+ return arg.object;
7399
+ }
7400
+ }
7401
+ return null;
7402
+ }
7403
+ function reportSequence() {
7404
+ const first = sequence.at(0);
7405
+ if (sequence.length > 1 && first) {
7406
+ context.report({
7407
+ node: first,
7408
+ messageId: "combineAssertions",
7409
+ fix(fixer) {
7410
+ if (!currentObject) return null;
7411
+ const objectText = context.sourceCode.getText(currentObject);
7412
+ const props = sequence.map((stmt) => {
7413
+ if (stmt.expression.type !== AST_NODE_TYPES36.CallExpression || stmt.expression.callee.type !== AST_NODE_TYPES36.MemberExpression || stmt.expression.callee.object.type !== AST_NODE_TYPES36.CallExpression) {
7414
+ return null;
7415
+ }
7416
+ const actual = stmt.expression.callee.object.arguments.at(0);
7417
+ const expected = stmt.expression.arguments.at(0);
7418
+ if (actual?.type === AST_NODE_TYPES36.MemberExpression && actual.property.type === AST_NODE_TYPES36.Identifier && expected) {
7419
+ const propName2 = actual.property.name;
7420
+ const valText = context.sourceCode.getText(expected);
7421
+ return `${propName2}: ${valText}`;
7422
+ }
7423
+ return null;
7424
+ });
7425
+ if (props.some((p) => p === null)) return null;
7426
+ const replacement = `expect(${objectText}).toMatchObject({ ${props.join(", ")} });`;
7427
+ return [
7428
+ fixer.replaceText(first, replacement),
7429
+ ...sequence.slice(1).map((stmt) => fixer.remove(stmt))
7430
+ ];
7431
+ }
7432
+ });
7433
+ }
7434
+ }
7435
+ for (const statement of body) {
7436
+ if (statement.type === AST_NODE_TYPES36.ExpressionStatement) {
7437
+ const obj = getExpectObject(statement.expression);
7438
+ if (obj && currentObject && context.sourceCode.getText(obj) === context.sourceCode.getText(currentObject)) {
7439
+ sequence.push(statement);
7440
+ } else {
7441
+ reportSequence();
7442
+ if (obj) {
7443
+ currentObject = obj;
7444
+ sequence = [statement];
7445
+ } else {
7446
+ currentObject = null;
7447
+ sequence = [];
7448
+ }
7449
+ }
7450
+ } else {
7451
+ reportSequence();
7452
+ currentObject = null;
7453
+ sequence = [];
7454
+ }
7455
+ }
7456
+ reportSequence();
7457
+ }
7458
+ return {
7459
+ BlockStatement(node) {
7460
+ checkBody(node.body);
7461
+ },
7462
+ Program(node) {
7463
+ checkBody(node.body);
7464
+ }
7465
+ };
7466
+ }
7467
+ });
7468
+
7469
+ // src/rules/no-async-callback-in-waitfor.ts
7470
+ import { AST_NODE_TYPES as AST_NODE_TYPES37, ESLintUtils as ESLintUtils50 } from "@typescript-eslint/utils";
7471
+ var no_async_callback_in_waitfor_default = ESLintUtils50.RuleCreator(
7472
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7473
+ )({
7474
+ name: "no-async-callback-in-waitfor",
7475
+ meta: {
7476
+ type: "problem",
7477
+ docs: {
7478
+ description: "Disallow async callbacks in `waitFor` to prevent swallowed promise rejections."
7479
+ },
7480
+ schema: [],
7481
+ messages: {
7482
+ noAsyncCallbackInWaitFor: "The callback to `waitFor` should not be async. It expects synchronous assertions and runs the callback repeatedly."
7483
+ }
7484
+ },
7485
+ defaultOptions: [],
7486
+ create(context) {
7487
+ if (!isTestFile(context.filename)) {
7488
+ return {};
7489
+ }
7490
+ return {
7491
+ CallExpression(node) {
7492
+ if (node.callee.type === AST_NODE_TYPES37.Identifier && node.callee.name === "waitFor") {
7493
+ const callback = node.arguments[0];
7494
+ if (callback && (callback.type === AST_NODE_TYPES37.ArrowFunctionExpression || callback.type === AST_NODE_TYPES37.FunctionExpression) && callback.async) {
7495
+ context.report({
7496
+ node: callback,
7497
+ messageId: "noAsyncCallbackInWaitFor"
7498
+ });
7499
+ }
7500
+ }
7501
+ }
7502
+ };
7503
+ }
7504
+ });
7505
+
7506
+ // src/rules/prefer-setup-file-mocks.ts
7507
+ import { AST_NODE_TYPES as AST_NODE_TYPES38, ESLintUtils as ESLintUtils51 } from "@typescript-eslint/utils";
7508
+ var prefer_setup_file_mocks_default = ESLintUtils51.RuleCreator(
7509
+ (name) => `https://github.com/sarj-ai/standards/blob/main/packages/typescript/src/rules/${name}.ts`
7510
+ )({
7511
+ name: "prefer-setup-file-mocks",
7512
+ meta: {
7513
+ type: "suggestion",
7514
+ docs: {
7515
+ description: "Prefer defining module mocks in setup files rather than using vi.mock or jest.mock inline in test files."
7516
+ },
7517
+ schema: [],
7518
+ messages: {
7519
+ 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."
7520
+ }
7521
+ },
7522
+ defaultOptions: [],
7523
+ create(context) {
7524
+ if (!isTestFile(context.filename)) {
7525
+ return {};
7526
+ }
7527
+ return {
7528
+ CallExpression(node) {
7529
+ if (node.callee.type === AST_NODE_TYPES38.MemberExpression && node.callee.object.type === AST_NODE_TYPES38.Identifier && (node.callee.object.name === "vi" || node.callee.object.name === "jest") && node.callee.property.type === AST_NODE_TYPES38.Identifier && node.callee.property.name === "mock") {
7530
+ context.report({
7531
+ node,
7532
+ messageId: "preferSetupFileMocks"
7533
+ });
7534
+ }
7535
+ }
7536
+ };
7537
+ }
7538
+ });
7539
+
7713
7540
  // src/index.ts
7714
7541
  var rules = {
7542
+ "ban-loose-type-guards-in-tests": ban_loose_type_guards_in_tests_default,
7715
7543
  "enforce-file-structure": enforce_file_structure_default,
7716
7544
  "no-client-side-data-fetching": no_client_side_data_fetching_default,
7717
7545
  "no-comment-cruft": no_comment_cruft_default,
@@ -7721,32 +7549,30 @@ var rules = {
7721
7549
  "no-log-only-catch": no_log_only_catch_default,
7722
7550
  "no-raw-env": no_raw_env_default,
7723
7551
  "no-sentinel-return-on-catch": no_sentinel_return_on_catch_default,
7724
- "no-sequential-await": no_sequential_await_default,
7725
7552
  "no-string-concat-in-loop": no_string_concat_in_loop_default,
7726
7553
  "no-unnecessary-use-client": no_unnecessary_use_client_default,
7727
7554
  "prefer-discriminated-union": prefer_discriminated_union_default,
7728
7555
  "prefer-schema-for-api-payload": prefer_schema_for_api_payload_default,
7729
7556
  "prefer-semantic-colors": prefer_semantic_colors_default,
7730
7557
  "prefer-server-actions": prefer_server_actions_default,
7731
- "prefer-shadcn": prefer_shadcn_default,
7732
7558
  "require-assert-never": require_assert_never_default,
7733
7559
  "require-zod-form-validation": require_zod_form_validation_default,
7734
7560
  "zod-naming-convention": zod_naming_convention_default,
7735
7561
  "no-cors-wildcard-with-credentials": no_cors_wildcard_with_credentials_default,
7736
7562
  "no-fat-try-blocks": no_fat_try_blocks_default,
7737
7563
  "no-secret-in-log": no_secret_in_log_default,
7738
- "no-unsafe-cast": no_unsafe_cast_default,
7564
+ "no-unsafe-mock-casting": no_unsafe_mock_casting_default,
7739
7565
  "prefer-string-literal-union": prefer_string_literal_union_default,
7740
- "single-public-export": single_public_export_default,
7566
+ "prefer-zod-enum": prefer_zod_enum_default,
7741
7567
  "primary-export-file-name": primary_export_file_name_default,
7742
7568
  "no-silent-promise-catch": no_silent_promise_catch_default,
7743
7569
  "require-fetch-timeout": require_fetch_timeout_default,
7744
- "require-schema-validate-search": require_schema_validate_search_default,
7745
7570
  "no-offset-pagination": no_offset_pagination_default,
7746
7571
  "no-positional-tuple-return": no_positional_tuple_return_default,
7747
7572
  "no-repeated-string-literal": no_repeated_string_literal_default,
7748
7573
  "no-select-star": no_select_star_default,
7749
7574
  "no-sleep-in-test-body": no_sleep_in_test_body_default,
7575
+ "no-conditional-in-test": no_conditional_in_test_default,
7750
7576
  "prefer-constant-time-secret-compare": prefer_constant_time_secret_compare_default,
7751
7577
  "store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
7752
7578
  "no-dynamic-sql": no_dynamic_sql_default,
@@ -7759,13 +7585,16 @@ var rules = {
7759
7585
  "trailing-value-narration": trailing_value_narration_default,
7760
7586
  "no-tautological-expect": no_tautological_expect_default,
7761
7587
  "require-interface-for-injected-service": require_interface_for_injected_service_default,
7588
+ "strict-test-assertions": strict_test_assertions_default,
7762
7589
  "prefer-non-nullable-collection": prefer_non_nullable_collection_default,
7763
- "no-implicit-attribute-access": no_implicit_attribute_access_default
7590
+ "no-implicit-attribute-access": no_implicit_attribute_access_default,
7591
+ "no-async-callback-in-waitfor": no_async_callback_in_waitfor_default,
7592
+ "prefer-setup-file-mocks": prefer_setup_file_mocks_default
7764
7593
  };
7765
7594
  var plugin = {
7766
7595
  meta: {
7767
7596
  name: "@sarj/eslint-plugin",
7768
- version: "2.16.0"
7597
+ version: "3.0.0"
7769
7598
  },
7770
7599
  rules,
7771
7600
  configs: {
@@ -7775,13 +7604,13 @@ var plugin = {
7775
7604
  "@sarj/zod-naming-convention": "warn",
7776
7605
  "@sarj/require-assert-never": "error",
7777
7606
  "@sarj/require-zod-form-validation": "error",
7607
+ "@sarj/ban-loose-type-guards-in-tests": "error",
7778
7608
  "@sarj/enforce-file-structure": "warn",
7779
7609
  "@sarj/no-client-side-data-fetching": "warn",
7780
7610
  "@sarj/prefer-server-actions": "warn",
7781
7611
  "@sarj/no-unnecessary-use-client": "warn",
7782
7612
  "@sarj/prefer-schema-for-api-payload": "warn",
7783
7613
  // Distilled from sarj-audit skills — warn in recommended, error in strict.
7784
- "@sarj/no-sequential-await": "warn",
7785
7614
  "@sarj/no-sentinel-return-on-catch": "warn",
7786
7615
  "@sarj/no-log-only-catch": "warn",
7787
7616
  "@sarj/no-insecure-random-id": "warn",
@@ -7798,14 +7627,13 @@ var plugin = {
7798
7627
  "@sarj/no-fat-try-blocks": "warn",
7799
7628
  "@sarj/no-cors-wildcard-with-credentials": "warn",
7800
7629
  "@sarj/no-secret-in-log": "warn",
7801
- "@sarj/no-unsafe-cast": "warn",
7802
- "@sarj/single-public-export": "warn",
7630
+ "@sarj/no-unsafe-mock-casting": "warn",
7803
7631
  "@sarj/primary-export-file-name": "warn",
7804
7632
  "@sarj/prefer-string-literal-union": "warn",
7633
+ "@sarj/prefer-zod-enum": "warn",
7805
7634
  // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
7806
7635
  "@sarj/require-fetch-timeout": "warn",
7807
7636
  "@sarj/no-silent-promise-catch": "warn",
7808
- "@sarj/require-schema-validate-search": "warn",
7809
7637
  // Second SARJ port wave — the TS/Python parity gap. Each targets a
7810
7638
  // defect class seen in production Workers code: timing-leaky secret
7811
7639
  // compares, non-idempotent store writes under queue redelivery,
@@ -7815,6 +7643,7 @@ var plugin = {
7815
7643
  "@sarj/no-offset-pagination": "warn",
7816
7644
  "@sarj/no-select-star": "warn",
7817
7645
  "@sarj/no-sleep-in-test-body": "warn",
7646
+ "@sarj/no-conditional-in-test": "warn",
7818
7647
  "@sarj/no-repeated-string-literal": "warn",
7819
7648
  "@sarj/no-positional-tuple-return": "warn",
7820
7649
  // Injection guard — low FP, applies to any repo touching SQL.
@@ -7851,7 +7680,9 @@ var plugin = {
7851
7680
  // port, 29 fire, 28 of them true positives.
7852
7681
  "@sarj/require-interface-for-injected-service": "warn",
7853
7682
  "@sarj/prefer-non-nullable-collection": "warn",
7854
- "@sarj/no-implicit-attribute-access": "warn"
7683
+ "@sarj/no-implicit-attribute-access": "warn",
7684
+ "@sarj/no-async-callback-in-waitfor": "warn",
7685
+ "@sarj/prefer-setup-file-mocks": "warn"
7855
7686
  }
7856
7687
  },
7857
7688
  strict: {
@@ -7860,16 +7691,15 @@ var plugin = {
7860
7691
  "@sarj/zod-naming-convention": "error",
7861
7692
  "@sarj/require-assert-never": "error",
7862
7693
  "@sarj/require-zod-form-validation": "error",
7694
+ "@sarj/ban-loose-type-guards-in-tests": "error",
7863
7695
  "@sarj/enforce-file-structure": "error",
7864
7696
  "@sarj/no-raw-env": "error",
7865
- "@sarj/prefer-shadcn": "error",
7866
7697
  "@sarj/no-enum": "error",
7867
7698
  "@sarj/no-client-side-data-fetching": "error",
7868
7699
  "@sarj/prefer-server-actions": "error",
7869
7700
  "@sarj/no-unnecessary-use-client": "error",
7870
7701
  "@sarj/prefer-schema-for-api-payload": "error",
7871
7702
  // Distilled from sarj-audit skills.
7872
- "@sarj/no-sequential-await": "error",
7873
7703
  "@sarj/no-sentinel-return-on-catch": "error",
7874
7704
  "@sarj/no-log-only-catch": "error",
7875
7705
  "@sarj/no-insecure-random-id": "error",
@@ -7887,21 +7717,21 @@ var plugin = {
7887
7717
  "@sarj/no-fat-try-blocks": "error",
7888
7718
  "@sarj/no-cors-wildcard-with-credentials": "error",
7889
7719
  "@sarj/no-secret-in-log": "error",
7890
- "@sarj/no-unsafe-cast": "error",
7891
- "@sarj/single-public-export": "error",
7720
+ "@sarj/no-unsafe-mock-casting": "error",
7892
7721
  "@sarj/primary-export-file-name": "error",
7893
7722
  // Promoted to error 2026-07-25 — strict means strict (user directive).
7894
7723
  "@sarj/prefer-string-literal-union": "error",
7724
+ "@sarj/prefer-zod-enum": "error",
7895
7725
  // Mined from 2y of PR review feedback + 5-repo code-smell audit (2026-07).
7896
7726
  "@sarj/require-fetch-timeout": "error",
7897
7727
  "@sarj/no-silent-promise-catch": "error",
7898
- "@sarj/require-schema-validate-search": "error",
7899
7728
  // Second SARJ port wave — the TS/Python parity gap.
7900
7729
  "@sarj/prefer-constant-time-secret-compare": "error",
7901
7730
  "@sarj/store-insert-requires-on-conflict": "error",
7902
7731
  "@sarj/no-offset-pagination": "error",
7903
7732
  "@sarj/no-select-star": "error",
7904
7733
  "@sarj/no-sleep-in-test-body": "error",
7734
+ "@sarj/no-conditional-in-test": "error",
7905
7735
  "@sarj/no-repeated-string-literal": "error",
7906
7736
  // API-shape advice rather than a runtime defect — a corpus sweep found its
7907
7737
  // only hits are parser `[value, cursor]` returns, which are conventional.
@@ -7931,7 +7761,9 @@ var plugin = {
7931
7761
  // corpus (175 `implements` clauses vs 29 hits), so strict enforces it.
7932
7762
  "@sarj/require-interface-for-injected-service": "error",
7933
7763
  "@sarj/prefer-non-nullable-collection": "error",
7934
- "@sarj/no-implicit-attribute-access": "error"
7764
+ "@sarj/no-implicit-attribute-access": "error",
7765
+ "@sarj/no-async-callback-in-waitfor": "error",
7766
+ "@sarj/prefer-setup-file-mocks": "error"
7935
7767
  }
7936
7768
  }
7937
7769
  }