@sarj/eslint-plugin 15.17.1 → 15.17.2

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
@@ -12019,100 +12019,371 @@ var prefer_module_level_schema_default = createRule({
12019
12019
  });
12020
12020
 
12021
12021
  // src/rules/prefer-module-level-refined-schema.ts
12022
- import { AST_NODE_TYPES as AST_NODE_TYPES53 } from "@typescript-eslint/utils";
12022
+ import {
12023
+ AST_NODE_TYPES as AST_NODE_TYPES53,
12024
+ ASTUtils as ASTUtils15
12025
+ } from "@typescript-eslint/utils";
12026
+ var BENCHMARK_PATH_RE = /(^|[/\\])(?:benchmarks?|bench)[/\\]/;
12023
12027
  var FACTORIES = /* @__PURE__ */ new Set([
12024
12028
  "array",
12029
+ "base64",
12030
+ "base64url",
12025
12031
  "bigint",
12026
12032
  "boolean",
12033
+ "cidrv4",
12034
+ "cidrv6",
12035
+ "codec",
12036
+ "custom",
12027
12037
  "date",
12028
- "number",
12029
- "string"
12030
- ]);
12031
- var REFINEMENTS = /* @__PURE__ */ new Set([
12032
- "brand",
12033
- "check",
12038
+ "datetime",
12039
+ "duration",
12034
12040
  "email",
12035
- "finite",
12036
- "int",
12037
- "length",
12038
- "max",
12039
- "min",
12040
- "multipleOf",
12041
- "nonempty",
12042
- "positive",
12043
- "regex",
12044
- "refine",
12045
- "safe",
12046
- "superRefine",
12047
- "transform",
12048
- "trim",
12041
+ "emoji",
12042
+ "enum",
12043
+ "file",
12044
+ "function",
12045
+ "hash",
12046
+ "hex",
12047
+ "hostname",
12048
+ "instanceof",
12049
+ "ipv4",
12050
+ "ipv6",
12051
+ "json",
12052
+ "jwt",
12053
+ "literal",
12054
+ "map",
12055
+ "nan",
12056
+ "nativeEnum",
12057
+ "never",
12058
+ "null",
12059
+ "nullable",
12060
+ "nullish",
12061
+ "number",
12062
+ "optional",
12063
+ "partialRecord",
12064
+ "preprocess",
12065
+ "promise",
12066
+ "set",
12067
+ "string",
12068
+ "stringbool",
12069
+ "symbol",
12070
+ "templateLiteral",
12071
+ "time",
12072
+ "undefined",
12049
12073
  "url",
12050
- "uuid"
12074
+ "uuid",
12075
+ "void"
12076
+ ]);
12077
+ var COMPOSITE_FACTORIES = /* @__PURE__ */ new Set([
12078
+ "discriminatedUnion",
12079
+ "intersection",
12080
+ "looseObject",
12081
+ "object",
12082
+ "record",
12083
+ "strictObject",
12084
+ "tuple",
12085
+ "union"
12086
+ ]);
12087
+ var FACTORY_NAMESPACES = /* @__PURE__ */ new Set(["coerce", "iso"]);
12088
+ var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
12089
+ "decode",
12090
+ "decodeAsync",
12091
+ "encode",
12092
+ "encodeAsync",
12093
+ "flattenError",
12094
+ "formatError",
12095
+ "implement",
12096
+ "isNullable",
12097
+ "isOptional",
12098
+ "parse",
12099
+ "parseAsync",
12100
+ "prettifyError",
12101
+ "registry",
12102
+ "safeDecode",
12103
+ "safeDecodeAsync",
12104
+ "safeEncode",
12105
+ "safeEncodeAsync",
12106
+ "safeParse",
12107
+ "safeParseAsync",
12108
+ "spa",
12109
+ "toJSONSchema",
12110
+ "treeifyError"
12111
+ ]);
12112
+ var MEMO_CALLEES2 = /* @__PURE__ */ new Set([
12113
+ "lazy",
12114
+ "memo",
12115
+ "once",
12116
+ "useMemo"
12117
+ ]);
12118
+ var I18N_CALLEE_NAMES2 = /* @__PURE__ */ new Set([
12119
+ "$t",
12120
+ "defineMessage",
12121
+ "gettext",
12122
+ "msg",
12123
+ "ngettext",
12124
+ "t",
12125
+ "translate"
12126
+ ]);
12127
+ var I18N_RECEIVER_NAMES2 = /* @__PURE__ */ new Set([
12128
+ "$i18n",
12129
+ "i18n",
12130
+ "intl"
12131
+ ]);
12132
+ var FUNCTION_TYPES9 = /* @__PURE__ */ new Set([
12133
+ AST_NODE_TYPES53.ArrowFunctionExpression,
12134
+ AST_NODE_TYPES53.FunctionDeclaration,
12135
+ AST_NODE_TYPES53.FunctionExpression
12051
12136
  ]);
12052
12137
  var PREFER_MODULE_LEVEL_REFINED_SCHEMA_DOCUMENTATION = {
12053
- summary: "Declare closed, refined Zod scalar and array schemas at module scope.",
12138
+ summary: "Declare closed Zod scalar, format, and wrapper schemas at module scope.",
12054
12139
  rationale: "A closed validation pipeline created inside a function is rebuilt on every invocation and obscures a reusable constraint.",
12055
- remediation: "Move the validation schema to module scope and call parse on the shared schema.",
12140
+ remediation: "Move the validation schema to module scope, name it with a PascalCase Schema suffix, and call parse on the shared schema.",
12056
12141
  category: "performance",
12057
- limitations: ["Only direct Zod scalar/array chains with at least two refinement methods and no non-literal arguments are reported."],
12142
+ limitations: [
12143
+ "Composite object/record/tuple/union schemas are owned by prefer-module-level-schema.",
12144
+ "Schemas that depend on function-local or mutable state, localized text, receiver state, lazy construction, or recognized memoization are excluded.",
12145
+ "Literal string z.enum domains are owned by prefer-shared-zod-enum."
12146
+ ],
12058
12147
  examples: [
12059
- { id: "module-refinement", title: "Share the validation schema", outcome: "no-match", files: [{ path: "src/options.ts", source: "import { z } from 'zod'; const BatchSize = z.number().int().min(1).max(1000); export function parse(value: unknown) { return BatchSize.parse(value); }" }], focusPath: "src/options.ts", expectedCount: 0, public: true },
12060
- { id: "local-refinement", title: "Do not rebuild a closed validation chain", outcome: "match", files: [{ path: "src/options.ts", source: "import { z } from 'zod'; export function parse(value: unknown) { return z.number().int().min(1).max(1000).parse(value); }" }], focusPath: "src/options.ts", expectedCount: 1, public: true }
12148
+ {
12149
+ id: "module-refinement",
12150
+ title: "Share the validation schema",
12151
+ outcome: "no-match",
12152
+ files: [{
12153
+ path: "src/options.ts",
12154
+ source: "import { z } from 'zod'; const BatchSizeSchema = z.number().int().min(1).max(1000); export function parse(value: unknown) { return BatchSizeSchema.parse(value); }"
12155
+ }],
12156
+ focusPath: "src/options.ts",
12157
+ expectedCount: 0,
12158
+ public: true
12159
+ },
12160
+ {
12161
+ id: "local-refinement",
12162
+ title: "Do not rebuild a closed validation chain",
12163
+ outcome: "match",
12164
+ files: [{
12165
+ path: "src/options.ts",
12166
+ source: "import { z } from 'zod'; export function parse(value: unknown) { return z.string().trim().min(1).max(128).parse(value); }"
12167
+ }],
12168
+ focusPath: "src/options.ts",
12169
+ expectedCount: 1,
12170
+ public: true
12171
+ }
12061
12172
  ]
12062
12173
  };
12063
- function enclosingFunction4(node) {
12174
+ function outermostEnclosingFunction2(node) {
12175
+ let outermost;
12064
12176
  let current = node.parent ?? void 0;
12065
12177
  while (current !== void 0) {
12066
- if ([AST_NODE_TYPES53.ArrowFunctionExpression, AST_NODE_TYPES53.FunctionDeclaration, AST_NODE_TYPES53.FunctionExpression].includes(current.type)) return current;
12178
+ if (FUNCTION_TYPES9.has(current.type)) outermost = current;
12067
12179
  current = current.parent ?? void 0;
12068
12180
  }
12069
- return void 0;
12181
+ return outermost;
12070
12182
  }
12071
12183
  function collectReferences2(scope, output) {
12072
12184
  output.push(...scope.references);
12073
12185
  for (const child of scope.childScopes) collectReferences2(child, output);
12074
12186
  }
12187
+ function subtreeSome2(root, predicate) {
12188
+ let found = false;
12189
+ const visit = (value) => {
12190
+ if (found || value === null || typeof value !== "object") return;
12191
+ if (Array.isArray(value)) {
12192
+ for (const item of value) visit(item);
12193
+ return;
12194
+ }
12195
+ const candidate2 = value;
12196
+ if (typeof candidate2.type !== "string") return;
12197
+ if (predicate(candidate2)) {
12198
+ found = true;
12199
+ return;
12200
+ }
12201
+ for (const key of Object.keys(candidate2)) {
12202
+ if (key === "parent" || key === "loc" || key === "range") continue;
12203
+ visit(candidate2[key]);
12204
+ }
12205
+ };
12206
+ visit(root);
12207
+ return found;
12208
+ }
12209
+ function readsReceiver2(node) {
12210
+ return subtreeSome2(
12211
+ node,
12212
+ (inner) => inner.type === AST_NODE_TYPES53.ThisExpression || inner.type === AST_NODE_TYPES53.Super || inner.type === AST_NODE_TYPES53.Identifier && inner.name === "arguments"
12213
+ );
12214
+ }
12215
+ function buildsLocalizedText2(node) {
12216
+ return subtreeSome2(node, (inner) => {
12217
+ if (inner.type === AST_NODE_TYPES53.TaggedTemplateExpression) return true;
12218
+ if (inner.type !== AST_NODE_TYPES53.CallExpression) return false;
12219
+ const { callee } = inner;
12220
+ if (callee.type === AST_NODE_TYPES53.Identifier)
12221
+ return I18N_CALLEE_NAMES2.has(callee.name);
12222
+ return callee.type === AST_NODE_TYPES53.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES53.Identifier && I18N_RECEIVER_NAMES2.has(callee.object.name);
12223
+ });
12224
+ }
12225
+ function calleeChainRoot(node) {
12226
+ let current = node;
12227
+ for (; ; ) {
12228
+ if (current.type === AST_NODE_TYPES53.Identifier) return current;
12229
+ if (current.type === AST_NODE_TYPES53.MemberExpression) {
12230
+ current = current.object;
12231
+ continue;
12232
+ }
12233
+ if (current.type === AST_NODE_TYPES53.CallExpression) {
12234
+ current = current.callee;
12235
+ continue;
12236
+ }
12237
+ return null;
12238
+ }
12239
+ }
12240
+ function chainMemberNames(node) {
12241
+ const names = [];
12242
+ let current = node;
12243
+ for (; ; ) {
12244
+ if (current.type === AST_NODE_TYPES53.MemberExpression) {
12245
+ if (current.computed || current.property.type !== AST_NODE_TYPES53.Identifier)
12246
+ return [];
12247
+ names.push(current.property.name);
12248
+ current = current.object;
12249
+ continue;
12250
+ }
12251
+ if (current.type === AST_NODE_TYPES53.CallExpression) {
12252
+ current = current.callee;
12253
+ continue;
12254
+ }
12255
+ break;
12256
+ }
12257
+ names.reverse();
12258
+ return names;
12259
+ }
12260
+ function schemaExpression2(node) {
12261
+ let current = node;
12262
+ for (; ; ) {
12263
+ const parent = current.parent ?? void 0;
12264
+ if (parent?.type === AST_NODE_TYPES53.MemberExpression && parent.object === current && !parent.computed && parent.property.type === AST_NODE_TYPES53.Identifier && parent.parent?.type === AST_NODE_TYPES53.CallExpression && parent.parent.callee === parent) {
12265
+ if (NON_SCHEMA_TERMINALS.has(parent.property.name)) return current;
12266
+ current = parent.parent;
12267
+ continue;
12268
+ }
12269
+ if (parent?.type === AST_NODE_TYPES53.TSAsExpression || parent?.type === AST_NODE_TYPES53.TSNonNullExpression || parent?.type === AST_NODE_TYPES53.TSSatisfiesExpression || parent?.type === AST_NODE_TYPES53.TSTypeAssertion) {
12270
+ current = parent;
12271
+ continue;
12272
+ }
12273
+ return current;
12274
+ }
12275
+ }
12075
12276
  var prefer_module_level_refined_schema_default = createRule({
12076
12277
  name: "prefer-module-level-refined-schema",
12077
12278
  documentation: PREFER_MODULE_LEVEL_REFINED_SCHEMA_DOCUMENTATION,
12078
- meta: { type: "suggestion", docs: { description: "Declare closed, refined Zod scalar and array schemas at module scope." }, schema: [], messages: { hoistRefinedSchema: "Move this closed refined Zod schema to module scope and reuse it for parsing." } },
12279
+ meta: {
12280
+ type: "suggestion",
12281
+ docs: {
12282
+ description: "Declare closed Zod scalar, format, and wrapper schemas at module scope."
12283
+ },
12284
+ schema: [],
12285
+ messages: {
12286
+ hoistRefinedSchema: "Move this closed Zod schema to module scope, give it a PascalCase Schema name, and reuse it for parsing."
12287
+ }
12288
+ },
12079
12289
  defaultOptions: [],
12080
12290
  create(context) {
12081
- if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text)) return {};
12082
- const namespaces = /* @__PURE__ */ new Set();
12291
+ if (isTestFile(context.filename) || BENCHMARK_PATH_RE.test(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text))
12292
+ return {};
12293
+ const zodBindings = /* @__PURE__ */ new Set();
12294
+ function resolvedBinding(identifier) {
12295
+ return ASTUtils15.findVariable(
12296
+ context.sourceCode.getScope(identifier),
12297
+ identifier.name
12298
+ );
12299
+ }
12300
+ function recordZodBinding(identifier) {
12301
+ const binding = resolvedBinding(identifier);
12302
+ if (binding !== null) zodBindings.add(binding);
12303
+ }
12304
+ function factoryName(node, allowed) {
12305
+ if (node.callee.type !== AST_NODE_TYPES53.MemberExpression) return null;
12306
+ const root = calleeChainRoot(node.callee);
12307
+ if (root === null) return null;
12308
+ const binding = resolvedBinding(root);
12309
+ if (binding === null || !zodBindings.has(binding)) return null;
12310
+ const names = chainMemberNames(node.callee);
12311
+ if (names.length === 1 && allowed.has(names[0] ?? ""))
12312
+ return names[0] ?? null;
12313
+ if (names.length === 2 && FACTORY_NAMESPACES.has(names[0] ?? "") && allowed.has(names[1] ?? ""))
12314
+ return names[1] ?? null;
12315
+ return null;
12316
+ }
12317
+ function isSharedEnumDomain(node, factory) {
12318
+ if (factory !== "enum") return false;
12319
+ const [argument] = node.arguments;
12320
+ return argument?.type === AST_NODE_TYPES53.ArrayExpression && argument.elements.length >= 2 && argument.elements.every(
12321
+ (element) => element?.type === AST_NODE_TYPES53.Literal && typeof element.value === "string"
12322
+ );
12323
+ }
12324
+ function isNestedInOwnedFactory(node) {
12325
+ let current = node;
12326
+ while (current.parent != null) {
12327
+ current = current.parent;
12328
+ if (FUNCTION_TYPES9.has(current.type)) return false;
12329
+ if (current.type === AST_NODE_TYPES53.CallExpression && (factoryName(current, FACTORIES) !== null || factoryName(current, COMPOSITE_FACTORIES) !== null))
12330
+ return true;
12331
+ }
12332
+ return false;
12333
+ }
12334
+ function isMemoized(node) {
12335
+ let current = node.parent ?? void 0;
12336
+ while (current !== void 0) {
12337
+ if (current.type === AST_NODE_TYPES53.CallExpression && (current.callee.type === AST_NODE_TYPES53.Identifier && MEMO_CALLEES2.has(current.callee.name) || current.callee.type === AST_NODE_TYPES53.MemberExpression && !current.callee.computed && current.callee.property.type === AST_NODE_TYPES53.Identifier && MEMO_CALLEES2.has(current.callee.property.name)))
12338
+ return true;
12339
+ current = current.parent ?? void 0;
12340
+ }
12341
+ return false;
12342
+ }
12343
+ function closesOverNothing(node, enclosing) {
12344
+ const references = [];
12345
+ collectReferences2(context.sourceCode.getScope(node), references);
12346
+ const [start, end] = node.range;
12347
+ const [functionStart, functionEnd] = enclosing.range;
12348
+ for (const reference of references) {
12349
+ const [referenceStart] = reference.identifier.range;
12350
+ if (referenceStart < start || referenceStart >= end) continue;
12351
+ const resolved = reference.resolved;
12352
+ if (resolved === null) continue;
12353
+ for (const definition of resolved.defs) {
12354
+ if (definition.type === "ImportBinding") {
12355
+ const parent = reference.identifier.parent;
12356
+ if (parent?.type === AST_NODE_TYPES53.CallExpression && parent.callee === reference.identifier && !zodBindings.has(resolved))
12357
+ return false;
12358
+ continue;
12359
+ }
12360
+ if (definition.node.type === AST_NODE_TYPES53.VariableDeclarator && definition.node.parent.type === AST_NODE_TYPES53.VariableDeclaration && definition.node.parent.kind !== "const")
12361
+ return false;
12362
+ const [definitionStart, definitionEnd] = definition.node.range;
12363
+ if (definitionStart >= start && definitionEnd <= end) continue;
12364
+ if (definitionStart >= functionStart && definitionEnd <= functionEnd)
12365
+ return false;
12366
+ }
12367
+ }
12368
+ return true;
12369
+ }
12083
12370
  return {
12084
12371
  ImportDeclaration(node) {
12085
12372
  if (!isZodModule(node.source.value)) return;
12086
- for (const specifier of node.specifiers) if (specifier.type === AST_NODE_TYPES53.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES53.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES53.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES53.Identifier && specifier.imported.name === "z") namespaces.add(specifier.local.name);
12373
+ for (const specifier of node.specifiers) {
12374
+ if (specifier.type === AST_NODE_TYPES53.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES53.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES53.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES53.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z"))
12375
+ recordZodBinding(specifier.local);
12376
+ }
12087
12377
  },
12088
12378
  CallExpression(node) {
12089
- const enclosing = enclosingFunction4(node);
12090
- if (enclosing === void 0 || node.parent?.type !== AST_NODE_TYPES53.MemberExpression || node.parent.object !== node) return;
12091
- if (node.callee.type !== AST_NODE_TYPES53.MemberExpression || node.callee.computed || node.callee.object.type !== AST_NODE_TYPES53.Identifier || !namespaces.has(node.callee.object.name) || node.callee.property.type !== AST_NODE_TYPES53.Identifier || !FACTORIES.has(node.callee.property.name)) return;
12092
- let current = node;
12093
- let refinements = 0;
12094
- while (current.parent?.type === AST_NODE_TYPES53.MemberExpression && current.parent.object === current && !current.parent.computed && current.parent.property.type === AST_NODE_TYPES53.Identifier && current.parent.parent?.type === AST_NODE_TYPES53.CallExpression && current.parent.parent.callee === current.parent) {
12095
- const call = current.parent.parent;
12096
- if (["parse", "parseAsync", "safeParse", "safeParseAsync"].includes(current.parent.property.name)) break;
12097
- if (REFINEMENTS.has(current.parent.property.name)) refinements += 1;
12098
- current = call;
12099
- }
12100
- if (refinements < 2) return;
12101
- const references = [];
12102
- collectReferences2(context.sourceCode.getScope(current), references);
12103
- const [start, end] = current.range;
12104
- const [functionStart, functionEnd] = enclosing.range;
12105
- for (const reference of references) {
12106
- const [referenceStart] = reference.identifier.range;
12107
- if (referenceStart < start || referenceStart >= end || reference.resolved === null) continue;
12108
- for (const definition of reference.resolved.defs) {
12109
- if (definition.type === "ImportBinding") continue;
12110
- if (definition.node.type === AST_NODE_TYPES53.VariableDeclarator && definition.node.parent.type === AST_NODE_TYPES53.VariableDeclaration && definition.node.parent.kind !== "const") return;
12111
- const [definitionStart, definitionEnd] = definition.node.range;
12112
- if (definitionStart >= start && definitionEnd <= end) continue;
12113
- if (definitionStart >= functionStart && definitionEnd <= functionEnd) return;
12114
- }
12115
- }
12379
+ const factory = factoryName(node, FACTORIES);
12380
+ if (factory === null || isSharedEnumDomain(node, factory) || isNestedInOwnedFactory(node) || isMemoized(node))
12381
+ return;
12382
+ const enclosing = outermostEnclosingFunction2(node);
12383
+ if (enclosing === void 0) return;
12384
+ const expression = schemaExpression2(node);
12385
+ if (readsReceiver2(expression) || buildsLocalizedText2(expression) || !closesOverNothing(expression, enclosing))
12386
+ return;
12116
12387
  context.report({ node, messageId: "hoistRefinedSchema" });
12117
12388
  }
12118
12389
  };
@@ -12120,26 +12391,30 @@ var prefer_module_level_refined_schema_default = createRule({
12120
12391
  });
12121
12392
 
12122
12393
  // src/rules/prefer-multi-value-zod-literal.ts
12123
- import { AST_NODE_TYPES as AST_NODE_TYPES54 } from "@typescript-eslint/utils";
12394
+ import {
12395
+ AST_NODE_TYPES as AST_NODE_TYPES54,
12396
+ ASTUtils as ASTUtils16
12397
+ } from "@typescript-eslint/utils";
12124
12398
  var PREFER_MULTI_VALUE_ZOD_LITERAL_DOCUMENTATION = {
12125
12399
  summary: "Use the Zod 4 multi-value literal API instead of a union of literal schemas.",
12126
12400
  rationale: "One multi-value literal expresses the same closed value domain without repeated schema wrappers.",
12127
12401
  remediation: "Replace the union with z.literal([value1, value2, ...]).",
12128
12402
  category: "maintainability",
12403
+ autofix: "safe",
12129
12404
  limitations: [
12130
- "Bare `zod` imports are analyzed only when the rule option explicitly declares `zodMajorVersion: 4`; `zod/v4` imports are self-declaring."
12405
+ "Bare zod imports are analyzed only when the rule option explicitly declares zodMajorVersion: 4; explicit zod/v4 entrypoints are self-declaring.",
12406
+ "All-string domains are left to zod/prefer-enum-over-literal-union.",
12407
+ "A finding containing comments is not autofixed because moving its trivia is ambiguous."
12131
12408
  ],
12132
12409
  examples: [
12133
12410
  {
12134
12411
  id: "multi-value",
12135
12412
  title: "Use one multi-value literal",
12136
12413
  outcome: "no-match",
12137
- files: [
12138
- {
12139
- path: "src/schema.ts",
12140
- source: "import { z } from 'zod'; export const Version = z.literal([1, 2, 3]);"
12141
- }
12142
- ],
12414
+ files: [{
12415
+ path: "src/schema.ts",
12416
+ source: "import { z } from 'zod'; export const Version = z.literal([1, 2, 3]);"
12417
+ }],
12143
12418
  focusPath: "src/schema.ts",
12144
12419
  expectedCount: 0,
12145
12420
  public: true
@@ -12148,80 +12423,116 @@ var PREFER_MULTI_VALUE_ZOD_LITERAL_DOCUMENTATION = {
12148
12423
  id: "literal-union",
12149
12424
  title: "Avoid repeated literal wrappers",
12150
12425
  outcome: "match",
12151
- files: [
12152
- {
12153
- path: "src/schema.ts",
12154
- source: "import { z } from 'zod'; export const Version = z.union([z.literal(1), z.literal(2), z.literal(3)]);"
12155
- }
12156
- ],
12426
+ files: [{
12427
+ path: "src/schema.ts",
12428
+ source: "import { z } from 'zod'; export const Version = z.union([z.literal(1), z.literal(2), z.literal(3)]);"
12429
+ }],
12430
+ fixedFiles: [{
12431
+ path: "src/schema.ts",
12432
+ source: "import { z } from 'zod'; export const Version = z.literal([1, 2, 3]);"
12433
+ }],
12157
12434
  focusPath: "src/schema.ts",
12158
12435
  expectedCount: 1,
12159
12436
  public: true
12160
12437
  }
12161
12438
  ]
12162
12439
  };
12163
- function memberCall(node, object, method) {
12164
- return node.callee.type === AST_NODE_TYPES54.MemberExpression && !node.callee.computed && node.callee.object.type === AST_NODE_TYPES54.Identifier && node.callee.object.name === object && node.callee.property.type === AST_NODE_TYPES54.Identifier && node.callee.property.name === method;
12440
+ function isStaticPrimitive(node, context) {
12441
+ if (node.type === AST_NODE_TYPES54.Literal) {
12442
+ return node.value === null || ["bigint", "boolean", "number", "string"].includes(typeof node.value);
12443
+ }
12444
+ if (node.type === AST_NODE_TYPES54.TemplateLiteral && node.expressions.length === 0)
12445
+ return true;
12446
+ if (node.type === AST_NODE_TYPES54.Identifier && node.name === "undefined") {
12447
+ const binding = ASTUtils16.findVariable(
12448
+ context.sourceCode.getScope(node),
12449
+ node.name
12450
+ );
12451
+ return binding === null || binding.defs.length === 0;
12452
+ }
12453
+ return node.type === AST_NODE_TYPES54.UnaryExpression && node.operator === "-" && node.argument.type === AST_NODE_TYPES54.Literal && ["bigint", "number"].includes(typeof node.argument.value);
12454
+ }
12455
+ function isStaticString(node) {
12456
+ return node.type === AST_NODE_TYPES54.Literal && typeof node.value === "string" || node.type === AST_NODE_TYPES54.TemplateLiteral && node.expressions.length === 0;
12165
12457
  }
12166
12458
  var prefer_multi_value_zod_literal_default = createRule({
12167
12459
  name: "prefer-multi-value-zod-literal",
12168
12460
  documentation: PREFER_MULTI_VALUE_ZOD_LITERAL_DOCUMENTATION,
12169
12461
  meta: {
12170
12462
  type: "suggestion",
12463
+ fixable: "code",
12171
12464
  docs: {
12172
12465
  description: "Use the Zod 4 multi-value literal API instead of a union of literal schemas."
12173
12466
  },
12174
- schema: [
12175
- {
12176
- type: "object",
12177
- additionalProperties: false,
12178
- properties: {
12179
- zodMajorVersion: { type: "integer", minimum: 4, maximum: 4 }
12180
- }
12467
+ schema: [{
12468
+ type: "object",
12469
+ additionalProperties: false,
12470
+ properties: {
12471
+ zodMajorVersion: { type: "integer", minimum: 4, maximum: 4 }
12181
12472
  }
12182
- ],
12473
+ }],
12183
12474
  messages: {
12184
- useMultiValueLiteral: "Replace this literal-schema union with `{{zod}}.literal([\u2026])`."
12475
+ useMultiValueLiteral: "Replace this literal-schema union with {{zod}}.literal([\u2026])."
12185
12476
  }
12186
12477
  },
12187
12478
  defaultOptions: [{}],
12188
12479
  create(context, [options]) {
12189
12480
  if (isTestFile(context.filename) || isGeneratedFile(context.filename, context.sourceCode.text))
12190
12481
  return {};
12191
- const namespaces = /* @__PURE__ */ new Set();
12192
- const zod4Namespaces = /* @__PURE__ */ new Set();
12482
+ const zodBindings = /* @__PURE__ */ new Set();
12483
+ const zod4Bindings = /* @__PURE__ */ new Set();
12484
+ function resolvedBinding(identifier) {
12485
+ return ASTUtils16.findVariable(
12486
+ context.sourceCode.getScope(identifier),
12487
+ identifier.name
12488
+ );
12489
+ }
12490
+ function directMemberCall(node, binding, method) {
12491
+ if (node.callee.type !== AST_NODE_TYPES54.MemberExpression || node.callee.computed || node.callee.object.type !== AST_NODE_TYPES54.Identifier || node.callee.property.type !== AST_NODE_TYPES54.Identifier || node.callee.property.name !== method)
12492
+ return false;
12493
+ return resolvedBinding(node.callee.object) === binding;
12494
+ }
12193
12495
  return {
12194
12496
  ImportDeclaration(node) {
12195
12497
  if (!isZodModule(node.source.value)) return;
12498
+ const isExplicitV4 = /^zod\/v4(?:$|[-/])/.test(node.source.value);
12196
12499
  for (const specifier of node.specifiers) {
12197
- if (specifier.type === AST_NODE_TYPES54.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES54.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES54.ImportSpecifier && specifier.imported.type === AST_NODE_TYPES54.Identifier && specifier.imported.name === "z") {
12198
- namespaces.add(specifier.local.name);
12199
- if (node.source.value === "zod/v4" || node.source.value.startsWith("zod/v4/"))
12200
- zod4Namespaces.add(specifier.local.name);
12500
+ if (specifier.type === AST_NODE_TYPES54.ImportDefaultSpecifier || specifier.type === AST_NODE_TYPES54.ImportNamespaceSpecifier || specifier.type === AST_NODE_TYPES54.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES54.Identifier ? specifier.imported.name === "z" : specifier.imported.value === "z")) {
12501
+ const binding = resolvedBinding(specifier.local);
12502
+ if (binding === null) continue;
12503
+ zodBindings.add(binding);
12504
+ if (isExplicitV4) zod4Bindings.add(binding);
12201
12505
  }
12202
12506
  }
12203
12507
  },
12204
12508
  CallExpression(node) {
12205
- const namespace = [...namespaces].find(
12206
- (name) => memberCall(node, name, "union")
12207
- );
12208
- if (namespace === void 0 || options?.zodMajorVersion !== 4 && !zod4Namespaces.has(namespace) || node.arguments.length !== 1)
12509
+ if (node.callee.type !== AST_NODE_TYPES54.MemberExpression || node.callee.object.type !== AST_NODE_TYPES54.Identifier)
12510
+ return;
12511
+ const binding = resolvedBinding(node.callee.object);
12512
+ if (binding === null || !zodBindings.has(binding) || !directMemberCall(node, binding, "union") || options?.zodMajorVersion !== 4 && !zod4Bindings.has(binding) || node.arguments.length !== 1)
12209
12513
  return;
12210
12514
  const [argument] = node.arguments;
12211
- if (argument?.type !== AST_NODE_TYPES54.ArrayExpression || argument.elements.length < 3 || argument.elements.some((element) => {
12212
- if (element === null || element.type !== AST_NODE_TYPES54.CallExpression || !memberCall(element, namespace, "literal") || element.arguments.length !== 1)
12213
- return true;
12214
- const [value] = element.arguments;
12215
- return value === void 0 || value.type === AST_NODE_TYPES54.SpreadElement || ![
12216
- AST_NODE_TYPES54.Literal,
12217
- AST_NODE_TYPES54.TemplateLiteral
12218
- ].includes(value.type);
12219
- }))
12515
+ if (argument?.type !== AST_NODE_TYPES54.ArrayExpression || argument.elements.length < 2)
12220
12516
  return;
12517
+ const values = [];
12518
+ for (const element of argument.elements) {
12519
+ if (element === null || element.type !== AST_NODE_TYPES54.CallExpression || !directMemberCall(element, binding, "literal") || element.arguments.length !== 1)
12520
+ return;
12521
+ const [value] = element.arguments;
12522
+ if (value === void 0 || !isStaticPrimitive(value, context)) return;
12523
+ values.push(value);
12524
+ }
12525
+ if (values.every(isStaticString)) return;
12526
+ const namespace = node.callee.object.name;
12527
+ const hasComments = context.sourceCode.getCommentsInside(node).length > 0;
12221
12528
  context.report({
12222
12529
  node,
12223
12530
  messageId: "useMultiValueLiteral",
12224
- data: { zod: namespace }
12531
+ data: { zod: namespace },
12532
+ fix: hasComments ? null : (fixer) => fixer.replaceText(
12533
+ node,
12534
+ `${namespace}.literal([${values.map((value) => context.sourceCode.getText(value)).join(", ")}])`
12535
+ )
12225
12536
  });
12226
12537
  }
12227
12538
  };
@@ -12338,7 +12649,7 @@ var prefer_named_complex_return_type_default = createRule({
12338
12649
  });
12339
12650
 
12340
12651
  // src/rules/prefer-native-random-uuid.ts
12341
- import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils15 } from "@typescript-eslint/utils";
12652
+ import { AST_NODE_TYPES as AST_NODE_TYPES57, ASTUtils as ASTUtils17 } from "@typescript-eslint/utils";
12342
12653
  var PREFER_NATIVE_RANDOM_UUID_DOCUMENTATION = {
12343
12654
  summary: "Prefer `globalThis.crypto.randomUUID()` over resolved zero-argument UUID v4 bindings from the `uuid` package.",
12344
12655
  rationale: "The platform implementation avoids an unnecessary dependency for standard random UUID generation.",
@@ -12374,7 +12685,7 @@ var prefer_native_random_uuid_default = createRule({
12374
12685
  const directBindings = /* @__PURE__ */ new Set();
12375
12686
  const namespaceBindings = /* @__PURE__ */ new Set();
12376
12687
  function resolve(identifier) {
12377
- return ASTUtils15.findVariable(context.sourceCode.getScope(identifier), identifier.name);
12688
+ return ASTUtils17.findVariable(context.sourceCode.getScope(identifier), identifier.name);
12378
12689
  }
12379
12690
  function record(identifier, destination) {
12380
12691
  const variable = resolve(identifier);
@@ -12437,7 +12748,7 @@ var prefer_native_random_uuid_default = createRule({
12437
12748
  });
12438
12749
 
12439
12750
  // src/rules/prefer-node-crypto-hash.ts
12440
- import { AST_NODE_TYPES as AST_NODE_TYPES58, ASTUtils as ASTUtils16 } from "@typescript-eslint/utils";
12751
+ import { AST_NODE_TYPES as AST_NODE_TYPES58, ASTUtils as ASTUtils18 } from "@typescript-eslint/utils";
12441
12752
  var PREFER_NODE_CRYPTO_HASH_DOCUMENTATION = {
12442
12753
  summary: "Prefer the modern one-shot node:crypto hash API when streaming state is unnecessary.",
12443
12754
  rationale: "A createHash-update-digest chain allocates mutable streaming state for a single in-memory value; Node's built-in hash function expresses the one-shot operation directly and can use its optimized fast path.",
@@ -12493,7 +12804,7 @@ var prefer_node_crypto_hash_default = createRule({
12493
12804
  const directBindings = /* @__PURE__ */ new Set();
12494
12805
  const namespaceBindings = /* @__PURE__ */ new Set();
12495
12806
  function resolve(identifier) {
12496
- return ASTUtils16.findVariable(
12807
+ return ASTUtils18.findVariable(
12497
12808
  context.sourceCode.getScope(identifier),
12498
12809
  identifier.name
12499
12810
  );
@@ -12680,7 +12991,7 @@ var prefer_node_fs_promises_default = createRule({
12680
12991
  });
12681
12992
 
12682
12993
  // src/rules/prefer-non-nullable-collection.ts
12683
- import { AST_NODE_TYPES as AST_NODE_TYPES60, ASTUtils as ASTUtils17 } from "@typescript-eslint/utils";
12994
+ import { AST_NODE_TYPES as AST_NODE_TYPES60, ASTUtils as ASTUtils19 } from "@typescript-eslint/utils";
12684
12995
  var PREFER_NON_NULLABLE_COLLECTION_DOCUMENTATION = {
12685
12996
  summary: "Suggest non-null arrays only when local control flow proves the nullish state is equivalent to an empty collection.",
12686
12997
  rationale: "A redundant nullish collection state spreads defaults and guards through consumers without carrying information.",
@@ -12810,14 +13121,14 @@ function directlyCoalesced(node) {
12810
13121
  return parent?.type === AST_NODE_TYPES60.LogicalExpression && parent.left === node && (parent.operator === "??" || parent.operator === "||") && emptyArray(parent.right);
12811
13122
  }
12812
13123
  function identifierIsOnlyCoalesced(context, binding, fn) {
12813
- const variable = ASTUtils17.findVariable(context.sourceCode.getScope(binding), binding.name);
13124
+ const variable = ASTUtils19.findVariable(context.sourceCode.getScope(binding), binding.name);
12814
13125
  if (variable === null || variable.references.length === 0) return false;
12815
13126
  return variable.references.every(
12816
13127
  (reference) => belongsToFunction(reference.identifier, fn) && directlyCoalesced(reference.identifier)
12817
13128
  );
12818
13129
  }
12819
13130
  function memberIsOnlyCoalesced(context, object, property, fn) {
12820
- const variable = ASTUtils17.findVariable(context.sourceCode.getScope(object), object.name);
13131
+ const variable = ASTUtils19.findVariable(context.sourceCode.getScope(object), object.name);
12821
13132
  if (variable === null) return false;
12822
13133
  const accesses = variable.references.flatMap((reference) => {
12823
13134
  if (!belongsToFunction(reference.identifier, fn)) return [null];
@@ -12927,7 +13238,7 @@ var prefer_non_nullable_collection_default = createRule({
12927
13238
  // src/rules/prefer-nullish-filter-predicate.ts
12928
13239
  import {
12929
13240
  AST_NODE_TYPES as AST_NODE_TYPES61,
12930
- ASTUtils as ASTUtils18,
13241
+ ASTUtils as ASTUtils20,
12931
13242
  ESLintUtils as ESLintUtils5
12932
13243
  } from "@typescript-eslint/utils";
12933
13244
  import ts3 from "typescript";
@@ -12973,7 +13284,7 @@ var PREFER_NULLISH_FILTER_PREDICATE_DOCUMENTATION = {
12973
13284
  ]
12974
13285
  };
12975
13286
  function isUnshadowedBoolean(node, context) {
12976
- const variable = ASTUtils18.findVariable(context.sourceCode.getScope(node), node.name);
13287
+ const variable = ASTUtils20.findVariable(context.sourceCode.getScope(node), node.name);
12977
13288
  return variable === null || variable.defs.length === 0;
12978
13289
  }
12979
13290
  function isBuiltinArrayFilter(node, services) {
@@ -13032,7 +13343,7 @@ function isProvablyTruthy(type, checker) {
13032
13343
  }
13033
13344
  function availableParameterName(node, context) {
13034
13345
  for (const name of ["value", "item", "element", "candidate"]) {
13035
- if (ASTUtils18.findVariable(context.sourceCode.getScope(node), name) === null) return name;
13346
+ if (ASTUtils20.findVariable(context.sourceCode.getScope(node), name) === null) return name;
13036
13347
  }
13037
13348
  return null;
13038
13349
  }
@@ -13086,7 +13397,7 @@ var prefer_nullish_filter_predicate_default = createRule({
13086
13397
 
13087
13398
  // src/rules/prefer-await-in-async-return.ts
13088
13399
  import {
13089
- ASTUtils as ASTUtils19,
13400
+ ASTUtils as ASTUtils21,
13090
13401
  ESLintUtils as ESLintUtils6,
13091
13402
  AST_NODE_TYPES as AST_NODE_TYPES62
13092
13403
  } from "@typescript-eslint/utils";
@@ -13200,13 +13511,13 @@ var prefer_await_in_async_return_default = createRule({
13200
13511
  if (services === null) return {};
13201
13512
  const frameworkLoaders = /* @__PURE__ */ new Set();
13202
13513
  const rememberFrameworkLoader = (identifier) => {
13203
- const variable = ASTUtils19.findVariable(context.sourceCode.getScope(identifier), identifier.name);
13514
+ const variable = ASTUtils21.findVariable(context.sourceCode.getScope(identifier), identifier.name);
13204
13515
  if (variable !== null) frameworkLoaders.add(variable);
13205
13516
  };
13206
13517
  const isFrameworkLoaderCallback = (owner) => {
13207
13518
  const parent = owner.parent;
13208
13519
  if (parent.type !== AST_NODE_TYPES62.CallExpression || parent.arguments[0] !== owner || parent.callee.type !== AST_NODE_TYPES62.Identifier) return false;
13209
- const variable = ASTUtils19.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
13520
+ const variable = ASTUtils21.findVariable(context.sourceCode.getScope(parent.callee), parent.callee.name);
13210
13521
  return variable !== null && frameworkLoaders.has(variable);
13211
13522
  };
13212
13523
  return {
@@ -14786,7 +15097,7 @@ var prefer_whole_object_assertion_default = createRule({
14786
15097
  });
14787
15098
 
14788
15099
  // src/rules/repeated-static-call-cases.ts
14789
- import { AST_NODE_TYPES as AST_NODE_TYPES68, ASTUtils as ASTUtils20 } from "@typescript-eslint/utils";
15100
+ import { AST_NODE_TYPES as AST_NODE_TYPES68, ASTUtils as ASTUtils22 } from "@typescript-eslint/utils";
14790
15101
  var REPEATED_STATIC_CALL_CASES_DOCUMENTATION = {
14791
15102
  summary: "Report three or more consecutive literal call assertions that should be independently named test cases.",
14792
15103
  rationale: "Copy-pasted cases obscure the input table and stop later cases from being reported after the first failure.",
@@ -14812,7 +15123,7 @@ function staticMemberName5(node) {
14812
15123
  return null;
14813
15124
  }
14814
15125
  function importedName6(identifier, context, modules) {
14815
- const variable = ASTUtils20.findVariable(context.sourceCode.getScope(identifier), identifier.name);
15126
+ const variable = ASTUtils22.findVariable(context.sourceCode.getScope(identifier), identifier.name);
14816
15127
  if (variable === null || variable.defs.length === 0) return identifier.name;
14817
15128
  for (const definition of variable.defs) {
14818
15129
  if (definition.node.type !== AST_NODE_TYPES68.ImportSpecifier) continue;
@@ -15813,7 +16124,7 @@ var require_assert_never_default = createRule({
15813
16124
  });
15814
16125
 
15815
16126
  // src/rules/require-fetch-timeout.ts
15816
- import { AST_NODE_TYPES as AST_NODE_TYPES71, ASTUtils as ASTUtils21 } from "@typescript-eslint/utils";
16127
+ import { AST_NODE_TYPES as AST_NODE_TYPES71, ASTUtils as ASTUtils23 } from "@typescript-eslint/utils";
15817
16128
  var REQUIRE_FETCH_TIMEOUT_DOCUMENTATION = {
15818
16129
  summary: "Require an abort `signal` (e.g. `AbortSignal.timeout(ms)`) on global `fetch()` calls so stalled upstreams cannot hang the caller forever.",
15819
16130
  rationale: "An unbounded request can occupy work indefinitely when an upstream stalls.",
@@ -15894,7 +16205,7 @@ var require_fetch_timeout_default = createRule({
15894
16205
  }
15895
16206
  function resolvesToGlobal(identifier) {
15896
16207
  const scope = context.sourceCode.getScope(identifier);
15897
- const variable = ASTUtils21.findVariable(scope, identifier.name);
16208
+ const variable = ASTUtils23.findVariable(scope, identifier.name);
15898
16209
  return variable === null || variable.defs.length === 0;
15899
16210
  }
15900
16211
  function isGlobalFetchCall2(callee) {
@@ -15904,7 +16215,7 @@ var require_fetch_timeout_default = createRule({
15904
16215
  return callee.type === AST_NODE_TYPES71.MemberExpression && !callee.computed && callee.property.type === AST_NODE_TYPES71.Identifier && callee.property.name === "fetch" && callee.object.type === AST_NODE_TYPES71.Identifier && GLOBAL_OBJECTS2.has(callee.object.name) && resolvesToGlobal(callee.object);
15905
16216
  }
15906
16217
  function localConstInitProvablyLacksSignal(identifier) {
15907
- const variable = ASTUtils21.findVariable(
16218
+ const variable = ASTUtils23.findVariable(
15908
16219
  context.sourceCode.getScope(identifier),
15909
16220
  identifier.name
15910
16221
  );
@@ -16993,7 +17304,7 @@ var require_static_next_matcher_default = createRule({
16993
17304
  });
16994
17305
 
16995
17306
  // src/rules/require-use-form-default-values.ts
16996
- import { ASTUtils as ASTUtils22 } from "@typescript-eslint/utils";
17307
+ import { ASTUtils as ASTUtils24 } from "@typescript-eslint/utils";
16997
17308
  var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
16998
17309
  summary: "react-hook-form useForm call without defaultValues",
16999
17310
  rationale: "Without an explicit initial value, fields can change from uncontrolled to controlled as data arrives, reset behavior becomes ambiguous, and the form's initial shape no longer documents the values users can edit.",
@@ -17047,13 +17358,13 @@ var require_use_form_default_values_default = createRule({
17047
17358
  if (node.source.value !== "react-hook-form") return;
17048
17359
  for (const specifier of node.specifiers) {
17049
17360
  if (specifier.type !== "ImportSpecifier" || (specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value) !== "useForm") continue;
17050
- const variable = ASTUtils22.findVariable(context.sourceCode.getScope(specifier.local), specifier.local.name);
17361
+ const variable = ASTUtils24.findVariable(context.sourceCode.getScope(specifier.local), specifier.local.name);
17051
17362
  if (variable) importedHooks.add(variable);
17052
17363
  }
17053
17364
  },
17054
17365
  CallExpression(node) {
17055
17366
  if (node.callee.type !== "Identifier") return;
17056
- const variable = ASTUtils22.findVariable(context.sourceCode.getScope(node.callee), node.callee.name);
17367
+ const variable = ASTUtils24.findVariable(context.sourceCode.getScope(node.callee), node.callee.name);
17057
17368
  const options = node.arguments[0];
17058
17369
  if (!variable || !importedHooks.has(variable) || options !== void 0 && options.type !== "ObjectExpression" || hasDefaultValues(options)) return;
17059
17370
  context.report({ node, messageId: "requireUseFormDefaultValues" });
@@ -17131,7 +17442,7 @@ var require_use_server_in_actions_file_default = createRule({
17131
17442
  // src/rules/require-zod-form-validation.ts
17132
17443
  import {
17133
17444
  AST_NODE_TYPES as AST_NODE_TYPES76,
17134
- ASTUtils as ASTUtils23
17445
+ ASTUtils as ASTUtils25
17135
17446
  } from "@typescript-eslint/utils";
17136
17447
  var REQUIRE_ZOD_FORM_VALIDATION_DOCUMENTATION = {
17137
17448
  summary: "Require Zod validation (`Schema.parse(...)` / `Schema.safeParse(...)`) when reading values out of a `FormData` object.",
@@ -17199,7 +17510,7 @@ var require_zod_form_validation_default = createRule({
17199
17510
  return {};
17200
17511
  }
17201
17512
  const zodBindings = /* @__PURE__ */ new Set();
17202
- const resolvedBinding = (identifier) => ASTUtils23.findVariable(
17513
+ const resolvedBinding = (identifier) => ASTUtils25.findVariable(
17203
17514
  context.sourceCode.getScope(identifier),
17204
17515
  identifier.name
17205
17516
  );
@@ -17496,7 +17807,7 @@ var store_insert_requires_on_conflict_default = createRule({
17496
17807
  });
17497
17808
 
17498
17809
  // src/rules/stepdown.ts
17499
- import { AST_NODE_TYPES as AST_NODE_TYPES77, ASTUtils as ASTUtils24 } from "@typescript-eslint/utils";
17810
+ import { AST_NODE_TYPES as AST_NODE_TYPES77, ASTUtils as ASTUtils26 } from "@typescript-eslint/utils";
17500
17811
  var STEPDOWN_DOCUMENTATION = {
17501
17812
  summary: "Place a private helper below its sole direct same-scope caller.",
17502
17813
  rationale: "Caller-first ordering lets a reader follow the main flow before descending into implementation details.",
@@ -17701,7 +18012,7 @@ function methodName(node) {
17701
18012
  return !node.computed && node.key.type === AST_NODE_TYPES77.Identifier ? node.key.name : null;
17702
18013
  }
17703
18014
  function referencedMethod(context, node, classVariables) {
17704
- const objectVariable = node.object.type === AST_NODE_TYPES77.Identifier ? ASTUtils24.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
18015
+ const objectVariable = node.object.type === AST_NODE_TYPES77.Identifier ? ASTUtils26.findVariable(context.sourceCode.getScope(node.object), node.object.name) : null;
17705
18016
  const isClassReference = objectVariable !== null && classVariables.has(objectVariable);
17706
18017
  if (node.object.type !== AST_NODE_TYPES77.ThisExpression && !isClassReference) return null;
17707
18018
  if (node.property.type === AST_NODE_TYPES77.PrivateIdentifier) return `#${node.property.name}`;
@@ -17754,11 +18065,11 @@ function classScope(context, node, computedReferenceNames) {
17754
18065
  const pinned = /* @__PURE__ */ new Set();
17755
18066
  const classVariables = /* @__PURE__ */ new Set();
17756
18067
  if (node.id !== null) {
17757
- const internal = ASTUtils24.findVariable(context.sourceCode.getScope(node), node.id.name);
18068
+ const internal = ASTUtils26.findVariable(context.sourceCode.getScope(node), node.id.name);
17758
18069
  if (internal !== null) classVariables.add(internal);
17759
18070
  }
17760
18071
  if (node.type === AST_NODE_TYPES77.ClassExpression && node.parent.type === AST_NODE_TYPES77.VariableDeclarator && node.parent.id.type === AST_NODE_TYPES77.Identifier) {
17761
- const outer = ASTUtils24.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
18072
+ const outer = ASTUtils26.findVariable(context.sourceCode.getScope(node.parent), node.parent.id.name);
17762
18073
  if (outer !== null) classVariables.add(outer);
17763
18074
  }
17764
18075
  for (const method of methods) {
@@ -17794,7 +18105,7 @@ function classScope(context, node, computedReferenceNames) {
17794
18105
  return;
17795
18106
  }
17796
18107
  if (binding.type !== AST_NODE_TYPES77.Identifier) return;
17797
- const variable = ASTUtils24.findVariable(context.sourceCode.getScope(binding), binding.name);
18108
+ const variable = ASTUtils26.findVariable(context.sourceCode.getScope(binding), binding.name);
17798
18109
  if (variable !== null) {
17799
18110
  methodClassVariables.add(variable);
17800
18111
  methodAliases.add(variable);
@@ -17824,7 +18135,7 @@ function classScope(context, node, computedReferenceNames) {
17824
18135
  return;
17825
18136
  }
17826
18137
  if (!privateNames.has(target)) return;
17827
- const objectVariable = current.object.type === AST_NODE_TYPES77.Identifier ? ASTUtils24.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
18138
+ const objectVariable = current.object.type === AST_NODE_TYPES77.Identifier ? ASTUtils26.findVariable(context.sourceCode.getScope(current.object), current.object.name) : null;
17828
18139
  if (objectVariable !== null && methodAliases.has(objectVariable)) {
17829
18140
  pinned.add(target);
17830
18141
  return;
@@ -18405,7 +18716,7 @@ var iac_source_coupled_test_default = createSourceCoupledRule(
18405
18716
  // src/rules/require-pascal-case-zod-schema-name.ts
18406
18717
  import {
18407
18718
  AST_NODE_TYPES as AST_NODE_TYPES80,
18408
- ASTUtils as ASTUtils25
18719
+ ASTUtils as ASTUtils27
18409
18720
  } from "@typescript-eslint/utils";
18410
18721
  var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
18411
18722
  summary: "Require confirmed module-level Zod schema contracts to use PascalCase with a `Schema` suffix.",
@@ -18425,8 +18736,8 @@ var REQUIRE_PASCAL_CASE_ZOD_SCHEMA_NAME_DOCUMENTATION = {
18425
18736
  ]
18426
18737
  };
18427
18738
  var PASCAL_SCHEMA_NAME_RE = /^[A-Z][A-Za-z0-9]*Schema$/;
18428
- var BENCHMARK_PATH_RE = /(^|[\\/])(?:benchmarks?|bench)[\\/]/;
18429
- var NON_SCHEMA_TERMINALS = /* @__PURE__ */ new Set([
18739
+ var BENCHMARK_PATH_RE2 = /(^|[\\/])(?:benchmarks?|bench)[\\/]/;
18740
+ var NON_SCHEMA_TERMINALS2 = /* @__PURE__ */ new Set([
18430
18741
  "parse",
18431
18742
  "parseAsync",
18432
18743
  "safeParse",
@@ -18539,7 +18850,7 @@ var SCHEMA_RETURNING_METHODS = /* @__PURE__ */ new Set([
18539
18850
  "transform"
18540
18851
  ]);
18541
18852
  var terminalMethodName = (callee) => !callee.computed && callee.property.type === AST_NODE_TYPES80.Identifier ? callee.property.name : null;
18542
- var calleeChainRoot = (node) => {
18853
+ var calleeChainRoot2 = (node) => {
18543
18854
  let current = node;
18544
18855
  for (; ; ) {
18545
18856
  if (current.type === AST_NODE_TYPES80.Identifier) {
@@ -18556,7 +18867,7 @@ var calleeChainRoot = (node) => {
18556
18867
  return null;
18557
18868
  }
18558
18869
  };
18559
- var chainMemberNames = (node) => {
18870
+ var chainMemberNames2 = (node) => {
18560
18871
  const names = [];
18561
18872
  let current = node;
18562
18873
  for (; ; ) {
@@ -18606,7 +18917,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
18606
18917
  const zodBindings = /* @__PURE__ */ new Set();
18607
18918
  const schemaBindings = /* @__PURE__ */ new Set();
18608
18919
  function resolvedBinding(identifier) {
18609
- return ASTUtils25.findVariable(
18920
+ return ASTUtils27.findVariable(
18610
18921
  context.sourceCode.getScope(identifier),
18611
18922
  identifier.name
18612
18923
  );
@@ -18616,7 +18927,7 @@ var require_pascal_case_zod_schema_name_default = createRule({
18616
18927
  if (binding !== null) zodBindings.add(binding);
18617
18928
  }
18618
18929
  function isZodChain(node) {
18619
- const root = calleeChainRoot(node);
18930
+ const root = calleeChainRoot2(node);
18620
18931
  if (root === null) return false;
18621
18932
  const binding = resolvedBinding(root);
18622
18933
  return binding !== null && zodBindings.has(binding);
@@ -18632,16 +18943,16 @@ var require_pascal_case_zod_schema_name_default = createRule({
18632
18943
  return false;
18633
18944
  }
18634
18945
  const terminal = terminalMethodName(init.callee);
18635
- if (terminal === null || NON_SCHEMA_TERMINALS.has(terminal)) return false;
18636
- const names = chainMemberNames(init.callee);
18946
+ if (terminal === null || NON_SCHEMA_TERMINALS2.has(terminal)) return false;
18947
+ const names = chainMemberNames2(init.callee);
18637
18948
  if (names.length === 0) return false;
18638
18949
  if (isZodChain(init.callee)) {
18639
18950
  return ZOD_SCHEMA_FACTORIES.has(names[0] ?? "") || ZOD_FACTORY_NAMESPACES.has(names[0] ?? "") && ZOD_SCHEMA_FACTORIES.has(names[1] ?? "");
18640
18951
  }
18641
- const root = calleeChainRoot(init.callee);
18952
+ const root = calleeChainRoot2(init.callee);
18642
18953
  return root !== null && isSchemaBinding(root) && SCHEMA_RETURNING_METHODS.has(terminal);
18643
18954
  }
18644
- if (isTestFile(context.filename) || BENCHMARK_PATH_RE.test(context.filename.replaceAll("\\", "/")) || isGeneratedFile(context.filename, context.sourceCode.text)) {
18955
+ if (isTestFile(context.filename) || BENCHMARK_PATH_RE2.test(context.filename.replaceAll("\\", "/")) || isGeneratedFile(context.filename, context.sourceCode.text)) {
18645
18956
  return {};
18646
18957
  }
18647
18958
  return {
@@ -18844,14 +19155,14 @@ var RULES = {
18844
19155
  "require-static-next-matcher": require_static_next_matcher_default,
18845
19156
  "require-zod-form-validation": require_zod_form_validation_default,
18846
19157
  "store-insert-requires-on-conflict": store_insert_requires_on_conflict_default,
18847
- stepdown: stepdown_default,
19158
+ "stepdown": stepdown_default,
18848
19159
  "source-coupled-test": source_coupled_test_default,
18849
19160
  "sole-export-matches-filename": sole_export_matches_filename_default,
18850
19161
  "require-pascal-case-zod-schema-name": require_pascal_case_zod_schema_name_default
18851
19162
  };
18852
19163
  var meta = {
18853
19164
  name: "@sarj/eslint-plugin",
18854
- version: "15.17.1"
19165
+ version: "15.17.2"
18855
19166
  };
18856
19167
  var APPLICATION_ONLY_RULES = [
18857
19168
  "no-restricted-library-load",