eslint-plugin-zod 3.8.0 β†’ 3.10.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/README.md CHANGED
@@ -43,6 +43,7 @@ This plugin is primarily built for `zod`, so some rules are exclusive to `zod` a
43
43
  | [consistent-import](docs/rules/consistent-import.md) | Enforce a consistent import style for Zod | βœ… | πŸ”§ | | |
44
44
  | [consistent-import-source](docs/rules/consistent-import-source.md) | Enforce consistent source from Zod imports | | | πŸ’‘ | |
45
45
  | [consistent-object-schema-type](docs/rules/consistent-object-schema-type.md) | Enforce consistent usage of Zod schema methods | | | πŸ’‘ | |
46
+ | [consistent-schema-name](docs/rules/consistent-schema-name.md) | Enforce a consistent naming convention for Zod schema variables | βœ… βœ”οΈ | | | |
46
47
  | [consistent-schema-output-type-style](docs/rules/consistent-schema-output-type-style.md) | Enforce consistent use of z.infer or z.output for schema type inference | | πŸ”§ | | |
47
48
  | [no-any-schema](docs/rules/no-any-schema.md) | Disallow usage of `z.any()` in Zod schemas | βœ… βœ”οΈ | | πŸ’‘ | |
48
49
  | [no-empty-custom-schema](docs/rules/no-empty-custom-schema.md) | Disallow usage of `z.custom()` without arguments | βœ… | | | |
@@ -51,22 +52,27 @@ This plugin is primarily built for `zod`, so some rules are exclusive to `zod` a
51
52
  | [prefer-namespace-import](docs/rules/prefer-namespace-import.md) | Enforce importing zod as a namespace import (`import * as z from 'zod'`) | | πŸ”§ | | ❌ |
52
53
  | [require-brand-type-parameter](docs/rules/require-brand-type-parameter.md) | Require type parameter on `.brand()` functions | βœ… βœ”οΈ | | πŸ’‘ | |
53
54
  | [require-error-message](docs/rules/require-error-message.md) | Enforce that custom refinements include an error message | βœ… βœ”οΈ | πŸ”§ | | |
54
- | [require-schema-suffix](docs/rules/require-schema-suffix.md) | Require schema suffix when declaring a Zod schema | βœ… βœ”οΈ | | | |
55
+ | [require-schema-suffix](docs/rules/require-schema-suffix.md) | Require schema suffix when declaring a Zod schema | | | | ❌ |
55
56
  | [schema-error-property-style](docs/rules/schema-error-property-style.md) | Enforce consistent style for error messages in Zod schema validation (using ESQuery patterns) | | | | |
56
57
 
57
58
  ### `zod` exclusive rules
58
59
 
59
- | NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | πŸ”§ | πŸ’‘ | ❌ |
60
- | :--------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :-- | :-- | :-- | :-- |
61
- | [array-style](docs/rules/array-style.md) | Enforce consistent Zod array style | βœ… | πŸ”§ | | |
62
- | [no-number-schema-with-int](docs/rules/no-number-schema-with-int.md) | Disallow usage of `z.number().int()` as it is considered legacy | βœ… | πŸ”§ | | |
63
- | [no-optional-and-default-together](docs/rules/no-optional-and-default-together.md) | Disallow using both `.optional()` and `.default()` on the same Zod schema | βœ… | πŸ”§ | | |
64
- | [no-string-schema-with-uuid](docs/rules/no-string-schema-with-uuid.md) | Disallow usage of `z.string().uuid()` in favor of the dedicated `z.uuid()` schema | βœ… | πŸ”§ | | |
65
- | [no-throw-in-refine](docs/rules/no-throw-in-refine.md) | Disallow throwing errors directly inside Zod refine callbacks | βœ… | | | |
66
- | [no-transform-in-record-key](docs/rules/no-transform-in-record-key.md) | Disallow transforms in z.record() key schemas, which can cause silent key mutations and data loss through key collisions | | | | |
67
- | [prefer-enum-over-literal-union](docs/rules/prefer-enum-over-literal-union.md) | Prefer `z.enum()` over `z.union()` when all members are string literals. | βœ… | πŸ”§ | | |
68
- | [prefer-meta-last](docs/rules/prefer-meta-last.md) | Enforce `.meta()` as last method | βœ… | πŸ”§ | | |
69
- | [prefer-string-schema-with-trim](docs/rules/prefer-string-schema-with-trim.md) | Enforce `z.string().trim()` to prevent accidental leading/trailing whitespace | βœ… | πŸ”§ | | |
60
+ | NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | πŸ”§ | πŸ’‘ | ❌ |
61
+ | :--------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- | :-- | :-- | :-- | :-- |
62
+ | [array-style](docs/rules/array-style.md) | Enforce consistent Zod array style | βœ… | πŸ”§ | | |
63
+ | [no-number-schema-with-finite](docs/rules/no-number-schema-with-finite.md) | Disallow deprecated `z.number().finite()`. In Zod 4+ number schemas do not allow infinite values by default, so it is a no-op. | βœ… | πŸ”§ | | |
64
+ | [no-number-schema-with-int](docs/rules/no-number-schema-with-int.md) | Disallow usage of `z.number().int()` as it is considered legacy | βœ… | πŸ”§ | | |
65
+ | [no-number-schema-with-is-finite](docs/rules/no-number-schema-with-is-finite.md) | Disallow using deprecated `isFinite` on a Zod number schema; in v4+ it is always `true`. | βœ… | | | |
66
+ | [no-number-schema-with-is-int](docs/rules/no-number-schema-with-is-int.md) | Disallow using deprecated `isInt` on a Zod number schema; check the `format` property instead. | βœ… | | | |
67
+ | [no-number-schema-with-safe](docs/rules/no-number-schema-with-safe.md) | Disallow deprecated `z.number().safe()`. Use `z.int()`; `.safe()` is now identical to `.int()`. | βœ… | πŸ”§ | | |
68
+ | [no-number-schema-with-step](docs/rules/no-number-schema-with-step.md) | Disallow deprecated `z.number().step()`. Use `.multipleOf()` instead. | βœ… | πŸ”§ | | |
69
+ | [no-optional-and-default-together](docs/rules/no-optional-and-default-together.md) | Disallow using both `.optional()` and `.default()` on the same Zod schema | βœ… | πŸ”§ | | |
70
+ | [no-string-schema-with-uuid](docs/rules/no-string-schema-with-uuid.md) | Disallow usage of `z.string().uuid()` in favor of the dedicated `z.uuid()` schema | βœ… | πŸ”§ | | |
71
+ | [no-throw-in-refine](docs/rules/no-throw-in-refine.md) | Disallow throwing errors directly inside Zod refine callbacks | βœ… | | | |
72
+ | [no-transform-in-record-key](docs/rules/no-transform-in-record-key.md) | Disallow transforms in z.record() key schemas, which can cause silent key mutations and data loss through key collisions | | | | |
73
+ | [prefer-enum-over-literal-union](docs/rules/prefer-enum-over-literal-union.md) | Prefer `z.enum()` over `z.union()` when all members are string literals. | βœ… | πŸ”§ | | |
74
+ | [prefer-meta-last](docs/rules/prefer-meta-last.md) | Enforce `.meta()` as last method | βœ… | πŸ”§ | | |
75
+ | [prefer-string-schema-with-trim](docs/rules/prefer-string-schema-with-trim.md) | Enforce `z.string().trim()` to prevent accidental leading/trailing whitespace | βœ… | πŸ”§ | | |
70
76
 
71
77
  <!-- end auto-generated rules list -->
72
78
 
package/dist/index.cjs CHANGED
@@ -3,10 +3,16 @@ const require_array_style = require("./rules/array-style.cjs");
3
3
  const require_consistent_import_source = require("./rules/consistent-import-source.cjs");
4
4
  const require_consistent_import = require("./rules/consistent-import.cjs");
5
5
  const require_consistent_object_schema_type = require("./rules/consistent-object-schema-type.cjs");
6
+ const require_consistent_schema_name = require("./rules/consistent-schema-name.cjs");
6
7
  const require_consistent_schema_output_type_style = require("./rules/consistent-schema-output-type-style.cjs");
7
8
  const require_no_any_schema = require("./rules/no-any-schema.cjs");
8
9
  const require_no_empty_custom_schema = require("./rules/no-empty-custom-schema.cjs");
10
+ const require_no_number_schema_with_finite = require("./rules/no-number-schema-with-finite.cjs");
9
11
  const require_no_number_schema_with_int = require("./rules/no-number-schema-with-int.cjs");
12
+ const require_no_number_schema_with_is_finite = require("./rules/no-number-schema-with-is-finite.cjs");
13
+ const require_no_number_schema_with_is_int = require("./rules/no-number-schema-with-is-int.cjs");
14
+ const require_no_number_schema_with_safe = require("./rules/no-number-schema-with-safe.cjs");
15
+ const require_no_number_schema_with_step = require("./rules/no-number-schema-with-step.cjs");
10
16
  const require_no_optional_and_default_together = require("./rules/no-optional-and-default-together.cjs");
11
17
  const require_no_string_schema_with_uuid = require("./rules/no-string-schema-with-uuid.cjs");
12
18
  const require_no_throw_in_refine = require("./rules/no-throw-in-refine.cjs");
@@ -32,10 +38,16 @@ const eslintPluginZod = {
32
38
  "consistent-import-source": require_consistent_import_source.consistentImportSource,
33
39
  "consistent-import": require_consistent_import.consistentImport,
34
40
  "consistent-object-schema-type": require_consistent_object_schema_type.consistentObjectSchemaType,
41
+ "consistent-schema-name": require_consistent_schema_name.consistentSchemaName,
35
42
  "consistent-schema-output-type-style": require_consistent_schema_output_type_style.consistentSchemaOutputTypeStyle,
36
43
  "no-any-schema": require_no_any_schema.noAnySchema,
37
44
  "no-empty-custom-schema": require_no_empty_custom_schema.noEmptyCustomSchema,
45
+ "no-number-schema-with-finite": require_no_number_schema_with_finite.noNumberSchemaWithFinite,
38
46
  "no-number-schema-with-int": require_no_number_schema_with_int.noNumberSchemaWithInt,
47
+ "no-number-schema-with-is-finite": require_no_number_schema_with_is_finite.noNumberSchemaWithIsFinite,
48
+ "no-number-schema-with-is-int": require_no_number_schema_with_is_int.noNumberSchemaWithIsInt,
49
+ "no-number-schema-with-safe": require_no_number_schema_with_safe.noNumberSchemaWithSafe,
50
+ "no-number-schema-with-step": require_no_number_schema_with_step.noNumberSchemaWithStep,
39
51
  "no-string-schema-with-uuid": require_no_string_schema_with_uuid.noStringSchemaWithUuid,
40
52
  "no-optional-and-default-together": require_no_optional_and_default_together.noOptionalAndDefaultTogether,
41
53
  "no-throw-in-refine": require_no_throw_in_refine.noThrowInRefine,
@@ -62,9 +74,15 @@ const recommendedConfig = {
62
74
  rules: {
63
75
  "zod/array-style": "error",
64
76
  "zod/consistent-import": "error",
77
+ "zod/consistent-schema-name": "error",
65
78
  "zod/no-any-schema": "error",
66
79
  "zod/no-empty-custom-schema": "error",
80
+ "zod/no-number-schema-with-finite": "error",
67
81
  "zod/no-number-schema-with-int": "error",
82
+ "zod/no-number-schema-with-is-finite": "error",
83
+ "zod/no-number-schema-with-is-int": "error",
84
+ "zod/no-number-schema-with-safe": "error",
85
+ "zod/no-number-schema-with-step": "error",
68
86
  "zod/no-string-schema-with-uuid": "error",
69
87
  "zod/no-optional-and-default-together": "error",
70
88
  "zod/no-throw-in-refine": "error",
@@ -73,18 +91,17 @@ const recommendedConfig = {
73
91
  "zod/prefer-meta-last": "error",
74
92
  "zod/prefer-string-schema-with-trim": "error",
75
93
  "zod/require-brand-type-parameter": "error",
76
- "zod/require-error-message": "error",
77
- "zod/require-schema-suffix": "error"
94
+ "zod/require-error-message": "error"
78
95
  }
79
96
  };
80
97
  const recommendedConfigMini = {
81
98
  ...baseConfig,
82
99
  rules: {
100
+ "zod/consistent-schema-name": "error",
83
101
  "zod/no-any-schema": "error",
84
102
  "zod/prefer-meta": "error",
85
103
  "zod/require-brand-type-parameter": "error",
86
- "zod/require-error-message": "error",
87
- "zod/require-schema-suffix": "error"
104
+ "zod/require-error-message": "error"
88
105
  }
89
106
  };
90
107
  var src_default = {
package/dist/index.mjs CHANGED
@@ -3,10 +3,16 @@ import { arrayStyle } from "./rules/array-style.mjs";
3
3
  import { consistentImportSource } from "./rules/consistent-import-source.mjs";
4
4
  import { consistentImport } from "./rules/consistent-import.mjs";
5
5
  import { consistentObjectSchemaType } from "./rules/consistent-object-schema-type.mjs";
6
+ import { consistentSchemaName } from "./rules/consistent-schema-name.mjs";
6
7
  import { consistentSchemaOutputTypeStyle } from "./rules/consistent-schema-output-type-style.mjs";
7
8
  import { noAnySchema } from "./rules/no-any-schema.mjs";
8
9
  import { noEmptyCustomSchema } from "./rules/no-empty-custom-schema.mjs";
10
+ import { noNumberSchemaWithFinite } from "./rules/no-number-schema-with-finite.mjs";
9
11
  import { noNumberSchemaWithInt } from "./rules/no-number-schema-with-int.mjs";
12
+ import { noNumberSchemaWithIsFinite } from "./rules/no-number-schema-with-is-finite.mjs";
13
+ import { noNumberSchemaWithIsInt } from "./rules/no-number-schema-with-is-int.mjs";
14
+ import { noNumberSchemaWithSafe } from "./rules/no-number-schema-with-safe.mjs";
15
+ import { noNumberSchemaWithStep } from "./rules/no-number-schema-with-step.mjs";
10
16
  import { noOptionalAndDefaultTogether } from "./rules/no-optional-and-default-together.mjs";
11
17
  import { noStringSchemaWithUuid } from "./rules/no-string-schema-with-uuid.mjs";
12
18
  import { noThrowInRefine } from "./rules/no-throw-in-refine.mjs";
@@ -32,10 +38,16 @@ const eslintPluginZod = {
32
38
  "consistent-import-source": consistentImportSource,
33
39
  "consistent-import": consistentImport,
34
40
  "consistent-object-schema-type": consistentObjectSchemaType,
41
+ "consistent-schema-name": consistentSchemaName,
35
42
  "consistent-schema-output-type-style": consistentSchemaOutputTypeStyle,
36
43
  "no-any-schema": noAnySchema,
37
44
  "no-empty-custom-schema": noEmptyCustomSchema,
45
+ "no-number-schema-with-finite": noNumberSchemaWithFinite,
38
46
  "no-number-schema-with-int": noNumberSchemaWithInt,
47
+ "no-number-schema-with-is-finite": noNumberSchemaWithIsFinite,
48
+ "no-number-schema-with-is-int": noNumberSchemaWithIsInt,
49
+ "no-number-schema-with-safe": noNumberSchemaWithSafe,
50
+ "no-number-schema-with-step": noNumberSchemaWithStep,
39
51
  "no-string-schema-with-uuid": noStringSchemaWithUuid,
40
52
  "no-optional-and-default-together": noOptionalAndDefaultTogether,
41
53
  "no-throw-in-refine": noThrowInRefine,
@@ -62,9 +74,15 @@ const recommendedConfig = {
62
74
  rules: {
63
75
  "zod/array-style": "error",
64
76
  "zod/consistent-import": "error",
77
+ "zod/consistent-schema-name": "error",
65
78
  "zod/no-any-schema": "error",
66
79
  "zod/no-empty-custom-schema": "error",
80
+ "zod/no-number-schema-with-finite": "error",
67
81
  "zod/no-number-schema-with-int": "error",
82
+ "zod/no-number-schema-with-is-finite": "error",
83
+ "zod/no-number-schema-with-is-int": "error",
84
+ "zod/no-number-schema-with-safe": "error",
85
+ "zod/no-number-schema-with-step": "error",
68
86
  "zod/no-string-schema-with-uuid": "error",
69
87
  "zod/no-optional-and-default-together": "error",
70
88
  "zod/no-throw-in-refine": "error",
@@ -73,18 +91,17 @@ const recommendedConfig = {
73
91
  "zod/prefer-meta-last": "error",
74
92
  "zod/prefer-string-schema-with-trim": "error",
75
93
  "zod/require-brand-type-parameter": "error",
76
- "zod/require-error-message": "error",
77
- "zod/require-schema-suffix": "error"
94
+ "zod/require-error-message": "error"
78
95
  }
79
96
  };
80
97
  const recommendedConfigMini = {
81
98
  ...baseConfig,
82
99
  rules: {
100
+ "zod/consistent-schema-name": "error",
83
101
  "zod/no-any-schema": "error",
84
102
  "zod/prefer-meta": "error",
85
103
  "zod/require-brand-type-parameter": "error",
86
- "zod/require-error-message": "error",
87
- "zod/require-schema-suffix": "error"
104
+ "zod/require-error-message": "error"
88
105
  }
89
106
  };
90
107
  var src_default = {
@@ -0,0 +1,76 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
3
+ const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
4
+ let _typescript_eslint_utils = require("@typescript-eslint/utils");
5
+ //#region src/rules/consistent-schema-name.ts
6
+ const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("all");
7
+ const consistentSchemaName = require_create_plugin_rule.createZodPluginRule({
8
+ name: "consistent-schema-name",
9
+ meta: {
10
+ type: "suggestion",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Enforce a consistent naming convention for Zod schema variables"
14
+ },
15
+ messages: { invalidName: "Rename this Zod schema to \"{{expected}}\"" },
16
+ schema: [{
17
+ type: "object",
18
+ properties: {
19
+ before: {
20
+ type: "string",
21
+ description: "The required prefix for Zod schema variables"
22
+ },
23
+ after: {
24
+ type: "string",
25
+ description: "The required suffix for Zod schema variables"
26
+ }
27
+ },
28
+ additionalProperties: false
29
+ }]
30
+ },
31
+ defaultOptions: [{ after: "Schema" }],
32
+ create(context, [{ before = "", after = "" }]) {
33
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
34
+ return {
35
+ ImportDeclaration: importDeclarationListener,
36
+ VariableDeclarator(node) {
37
+ const initNode = node.init;
38
+ if (initNode?.type !== _typescript_eslint_utils.AST_NODE_TYPES.CallExpression || !detectZodSchemaRootNode(initNode)) return;
39
+ const chainMethods = collectZodChainMethods(initNode).map((it) => it.name);
40
+ if ([
41
+ "parse",
42
+ "parseAsync",
43
+ "safeParse",
44
+ "safeParseAsync",
45
+ "spa",
46
+ "encode",
47
+ "encodeAsync",
48
+ "decode",
49
+ "decodeAsync",
50
+ "safeEncode",
51
+ "safeEncodeAsync",
52
+ "safeDecode",
53
+ "safeDecodeAsync",
54
+ "codec",
55
+ "treeifyError",
56
+ "prettifyError",
57
+ "formatError",
58
+ "flattenError"
59
+ ].some((it) => chainMethods.includes(it))) return;
60
+ if (node.id.type !== _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return;
61
+ const { name } = node.id;
62
+ const validPrefix = !before || name.startsWith(before);
63
+ const validSuffix = !after || name.endsWith(after);
64
+ if (validPrefix && validSuffix) return;
65
+ const expected = (validPrefix ? "" : before) + name + (validSuffix ? "" : after);
66
+ context.report({
67
+ node,
68
+ messageId: "invalidName",
69
+ data: { expected }
70
+ });
71
+ }
72
+ };
73
+ }
74
+ });
75
+ //#endregion
76
+ exports.consistentSchemaName = consistentSchemaName;
@@ -0,0 +1,75 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+ //#region src/rules/consistent-schema-name.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("all");
6
+ const consistentSchemaName = createZodPluginRule({
7
+ name: "consistent-schema-name",
8
+ meta: {
9
+ type: "suggestion",
10
+ docs: {
11
+ zodImportAllowedSource,
12
+ description: "Enforce a consistent naming convention for Zod schema variables"
13
+ },
14
+ messages: { invalidName: "Rename this Zod schema to \"{{expected}}\"" },
15
+ schema: [{
16
+ type: "object",
17
+ properties: {
18
+ before: {
19
+ type: "string",
20
+ description: "The required prefix for Zod schema variables"
21
+ },
22
+ after: {
23
+ type: "string",
24
+ description: "The required suffix for Zod schema variables"
25
+ }
26
+ },
27
+ additionalProperties: false
28
+ }]
29
+ },
30
+ defaultOptions: [{ after: "Schema" }],
31
+ create(context, [{ before = "", after = "" }]) {
32
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
33
+ return {
34
+ ImportDeclaration: importDeclarationListener,
35
+ VariableDeclarator(node) {
36
+ const initNode = node.init;
37
+ if (initNode?.type !== AST_NODE_TYPES.CallExpression || !detectZodSchemaRootNode(initNode)) return;
38
+ const chainMethods = collectZodChainMethods(initNode).map((it) => it.name);
39
+ if ([
40
+ "parse",
41
+ "parseAsync",
42
+ "safeParse",
43
+ "safeParseAsync",
44
+ "spa",
45
+ "encode",
46
+ "encodeAsync",
47
+ "decode",
48
+ "decodeAsync",
49
+ "safeEncode",
50
+ "safeEncodeAsync",
51
+ "safeDecode",
52
+ "safeDecodeAsync",
53
+ "codec",
54
+ "treeifyError",
55
+ "prettifyError",
56
+ "formatError",
57
+ "flattenError"
58
+ ].some((it) => chainMethods.includes(it))) return;
59
+ if (node.id.type !== AST_NODE_TYPES.Identifier) return;
60
+ const { name } = node.id;
61
+ const validPrefix = !before || name.startsWith(before);
62
+ const validSuffix = !after || name.endsWith(after);
63
+ if (validPrefix && validSuffix) return;
64
+ const expected = (validPrefix ? "" : before) + name + (validSuffix ? "" : after);
65
+ context.report({
66
+ node,
67
+ messageId: "invalidName",
68
+ data: { expected }
69
+ });
70
+ }
71
+ };
72
+ }
73
+ });
74
+ //#endregion
75
+ export { consistentSchemaName };
@@ -0,0 +1,44 @@
1
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
2
+ const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
3
+ const require_build_zod_chain_remove_method_fix = require("../utils/build-zod-chain-remove-method-fix.cjs");
4
+ //#region src/rules/no-number-schema-with-finite.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithFinite = require_create_plugin_rule.createZodPluginRule({
7
+ name: "no-number-schema-with-finite",
8
+ meta: {
9
+ fixable: "code",
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow deprecated `z.number().finite()`. In Zod 4+ number schemas do not allow infinite values by default, so it is a no-op."
14
+ },
15
+ messages: { removeFinite: "`.finite()` is deprecated. In Zod 4+ `z.number()` does not allow infinite values by default. Remove this call." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
21
+ return {
22
+ ImportDeclaration: importDeclarationListener,
23
+ CallExpression(node) {
24
+ if (detectZodSchemaRootNode(node)?.schemaType !== "number") return;
25
+ const methods = collectZodChainMethods(node);
26
+ const finiteIndex = methods.findIndex((m) => m.name === "finite" && m.node === node);
27
+ if (finiteIndex === -1) return;
28
+ context.report({
29
+ node,
30
+ messageId: "removeFinite",
31
+ fix(fixer) {
32
+ return require_build_zod_chain_remove_method_fix.buildZodChainRemoveMethodFix({
33
+ fixer,
34
+ methods,
35
+ removeIndex: finiteIndex
36
+ });
37
+ }
38
+ });
39
+ }
40
+ };
41
+ }
42
+ });
43
+ //#endregion
44
+ exports.noNumberSchemaWithFinite = noNumberSchemaWithFinite;
@@ -0,0 +1,44 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
3
+ import { buildZodChainRemoveMethodFix } from "../utils/build-zod-chain-remove-method-fix.mjs";
4
+ //#region src/rules/no-number-schema-with-finite.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithFinite = createZodPluginRule({
7
+ name: "no-number-schema-with-finite",
8
+ meta: {
9
+ fixable: "code",
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow deprecated `z.number().finite()`. In Zod 4+ number schemas do not allow infinite values by default, so it is a no-op."
14
+ },
15
+ messages: { removeFinite: "`.finite()` is deprecated. In Zod 4+ `z.number()` does not allow infinite values by default. Remove this call." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
21
+ return {
22
+ ImportDeclaration: importDeclarationListener,
23
+ CallExpression(node) {
24
+ if (detectZodSchemaRootNode(node)?.schemaType !== "number") return;
25
+ const methods = collectZodChainMethods(node);
26
+ const finiteIndex = methods.findIndex((m) => m.name === "finite" && m.node === node);
27
+ if (finiteIndex === -1) return;
28
+ context.report({
29
+ node,
30
+ messageId: "removeFinite",
31
+ fix(fixer) {
32
+ return buildZodChainRemoveMethodFix({
33
+ fixer,
34
+ methods,
35
+ removeIndex: finiteIndex
36
+ });
37
+ }
38
+ });
39
+ }
40
+ };
41
+ }
42
+ });
43
+ //#endregion
44
+ export { noNumberSchemaWithFinite };
@@ -0,0 +1,38 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
3
+ const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
4
+ let _typescript_eslint_utils = require("@typescript-eslint/utils");
5
+ //#region src/rules/no-number-schema-with-is-finite.ts
6
+ const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("zod");
7
+ const noNumberSchemaWithIsFinite = require_create_plugin_rule.createZodPluginRule({
8
+ name: "no-number-schema-with-is-finite",
9
+ meta: {
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow using deprecated `isFinite` on a Zod number schema; in v4+ it is always `true`."
14
+ },
15
+ messages: { deprecated: "`isFinite` is deprecated. Number schemas no longer accept infinite values, so this is always `true` for `z.number()`." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { importDeclarationListener, isZodNumberSchemaCallExpression } = trackZodSchemaImports();
21
+ return {
22
+ ImportDeclaration: importDeclarationListener,
23
+ MemberExpression(node) {
24
+ if (node.computed) return;
25
+ if (node.property.type !== _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return;
26
+ if (node.property.name !== "isFinite") return;
27
+ if (node.object.type !== _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) return;
28
+ if (!isZodNumberSchemaCallExpression(node.object)) return;
29
+ context.report({
30
+ node,
31
+ messageId: "deprecated"
32
+ });
33
+ }
34
+ };
35
+ }
36
+ });
37
+ //#endregion
38
+ exports.noNumberSchemaWithIsFinite = noNumberSchemaWithIsFinite;
@@ -0,0 +1,37 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+ //#region src/rules/no-number-schema-with-is-finite.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithIsFinite = createZodPluginRule({
7
+ name: "no-number-schema-with-is-finite",
8
+ meta: {
9
+ type: "problem",
10
+ docs: {
11
+ zodImportAllowedSource,
12
+ description: "Disallow using deprecated `isFinite` on a Zod number schema; in v4+ it is always `true`."
13
+ },
14
+ messages: { deprecated: "`isFinite` is deprecated. Number schemas no longer accept infinite values, so this is always `true` for `z.number()`." },
15
+ schema: []
16
+ },
17
+ defaultOptions: [],
18
+ create(context) {
19
+ const { importDeclarationListener, isZodNumberSchemaCallExpression } = trackZodSchemaImports();
20
+ return {
21
+ ImportDeclaration: importDeclarationListener,
22
+ MemberExpression(node) {
23
+ if (node.computed) return;
24
+ if (node.property.type !== AST_NODE_TYPES.Identifier) return;
25
+ if (node.property.name !== "isFinite") return;
26
+ if (node.object.type !== AST_NODE_TYPES.CallExpression) return;
27
+ if (!isZodNumberSchemaCallExpression(node.object)) return;
28
+ context.report({
29
+ node,
30
+ messageId: "deprecated"
31
+ });
32
+ }
33
+ };
34
+ }
35
+ });
36
+ //#endregion
37
+ export { noNumberSchemaWithIsFinite };
@@ -0,0 +1,38 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
3
+ const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
4
+ let _typescript_eslint_utils = require("@typescript-eslint/utils");
5
+ //#region src/rules/no-number-schema-with-is-int.ts
6
+ const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("zod");
7
+ const noNumberSchemaWithIsInt = require_create_plugin_rule.createZodPluginRule({
8
+ name: "no-number-schema-with-is-int",
9
+ meta: {
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow using deprecated `isInt` on a Zod number schema; check the `format` property instead."
14
+ },
15
+ messages: { useFormat: "`isInt` is deprecated. Check the `format` property on the number schema instead (or compare to `\"int\"` or `\"float\"`)." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { importDeclarationListener, isZodNumberSchemaCallExpression } = trackZodSchemaImports();
21
+ return {
22
+ ImportDeclaration: importDeclarationListener,
23
+ MemberExpression(node) {
24
+ if (node.computed) return;
25
+ if (node.property.type !== _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return;
26
+ if (node.property.name !== "isInt") return;
27
+ if (node.object.type !== _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) return;
28
+ if (!isZodNumberSchemaCallExpression(node.object)) return;
29
+ context.report({
30
+ node,
31
+ messageId: "useFormat"
32
+ });
33
+ }
34
+ };
35
+ }
36
+ });
37
+ //#endregion
38
+ exports.noNumberSchemaWithIsInt = noNumberSchemaWithIsInt;
@@ -0,0 +1,37 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+ //#region src/rules/no-number-schema-with-is-int.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithIsInt = createZodPluginRule({
7
+ name: "no-number-schema-with-is-int",
8
+ meta: {
9
+ type: "problem",
10
+ docs: {
11
+ zodImportAllowedSource,
12
+ description: "Disallow using deprecated `isInt` on a Zod number schema; check the `format` property instead."
13
+ },
14
+ messages: { useFormat: "`isInt` is deprecated. Check the `format` property on the number schema instead (or compare to `\"int\"` or `\"float\"`)." },
15
+ schema: []
16
+ },
17
+ defaultOptions: [],
18
+ create(context) {
19
+ const { importDeclarationListener, isZodNumberSchemaCallExpression } = trackZodSchemaImports();
20
+ return {
21
+ ImportDeclaration: importDeclarationListener,
22
+ MemberExpression(node) {
23
+ if (node.computed) return;
24
+ if (node.property.type !== AST_NODE_TYPES.Identifier) return;
25
+ if (node.property.name !== "isInt") return;
26
+ if (node.object.type !== AST_NODE_TYPES.CallExpression) return;
27
+ if (!isZodNumberSchemaCallExpression(node.object)) return;
28
+ context.report({
29
+ node,
30
+ messageId: "useFormat"
31
+ });
32
+ }
33
+ };
34
+ }
35
+ });
36
+ //#endregion
37
+ export { noNumberSchemaWithIsInt };
@@ -0,0 +1,57 @@
1
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
2
+ const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
3
+ const require_build_zod_chain_replacement_fix = require("../utils/build-zod-chain-replacement-fix.cjs");
4
+ //#region src/rules/no-number-schema-with-safe.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithSafe = require_create_plugin_rule.createZodPluginRule({
7
+ name: "no-number-schema-with-safe",
8
+ meta: {
9
+ fixable: "code",
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow deprecated `z.number().safe()`. Use `z.int()`; `.safe()` is now identical to `.int()`."
14
+ },
15
+ messages: { useInt: "`.safe()` is deprecated; it is identical to `.int()`. Use `z.int()` (or the equivalent) instead of chaining `.safe()` on `z.number()`." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { sourceCode } = context;
21
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
22
+ return {
23
+ ImportDeclaration: importDeclarationListener,
24
+ CallExpression(node) {
25
+ const zodSchemaMeta = detectZodSchemaRootNode(node);
26
+ if (zodSchemaMeta?.schemaType !== "number") return;
27
+ const methods = collectZodChainMethods(node);
28
+ const safeIndex = methods.findIndex((m) => m.name === "safe" && m.node === node);
29
+ if (safeIndex === -1) return;
30
+ const numberIndex = methods.findIndex((m) => m.name === "number");
31
+ if (zodSchemaMeta.schemaDecl === "named") {
32
+ context.report({
33
+ node,
34
+ messageId: "useInt"
35
+ });
36
+ return;
37
+ }
38
+ context.report({
39
+ node,
40
+ messageId: "useInt",
41
+ fix(fixer) {
42
+ return require_build_zod_chain_replacement_fix.buildZodChainReplacementFix({
43
+ sourceCode,
44
+ fixer,
45
+ methods,
46
+ fromIndex: numberIndex,
47
+ toIndex: safeIndex,
48
+ toMethodName: "int"
49
+ });
50
+ }
51
+ });
52
+ }
53
+ };
54
+ }
55
+ });
56
+ //#endregion
57
+ exports.noNumberSchemaWithSafe = noNumberSchemaWithSafe;
@@ -0,0 +1,57 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
3
+ import { buildZodChainReplacementFix } from "../utils/build-zod-chain-replacement-fix.mjs";
4
+ //#region src/rules/no-number-schema-with-safe.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithSafe = createZodPluginRule({
7
+ name: "no-number-schema-with-safe",
8
+ meta: {
9
+ fixable: "code",
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow deprecated `z.number().safe()`. Use `z.int()`; `.safe()` is now identical to `.int()`."
14
+ },
15
+ messages: { useInt: "`.safe()` is deprecated; it is identical to `.int()`. Use `z.int()` (or the equivalent) instead of chaining `.safe()` on `z.number()`." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { sourceCode } = context;
21
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
22
+ return {
23
+ ImportDeclaration: importDeclarationListener,
24
+ CallExpression(node) {
25
+ const zodSchemaMeta = detectZodSchemaRootNode(node);
26
+ if (zodSchemaMeta?.schemaType !== "number") return;
27
+ const methods = collectZodChainMethods(node);
28
+ const safeIndex = methods.findIndex((m) => m.name === "safe" && m.node === node);
29
+ if (safeIndex === -1) return;
30
+ const numberIndex = methods.findIndex((m) => m.name === "number");
31
+ if (zodSchemaMeta.schemaDecl === "named") {
32
+ context.report({
33
+ node,
34
+ messageId: "useInt"
35
+ });
36
+ return;
37
+ }
38
+ context.report({
39
+ node,
40
+ messageId: "useInt",
41
+ fix(fixer) {
42
+ return buildZodChainReplacementFix({
43
+ sourceCode,
44
+ fixer,
45
+ methods,
46
+ fromIndex: numberIndex,
47
+ toIndex: safeIndex,
48
+ toMethodName: "int"
49
+ });
50
+ }
51
+ });
52
+ }
53
+ };
54
+ }
55
+ });
56
+ //#endregion
57
+ export { noNumberSchemaWithSafe };
@@ -0,0 +1,43 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
3
+ const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
4
+ let _typescript_eslint_utils = require("@typescript-eslint/utils");
5
+ //#region src/rules/no-number-schema-with-step.ts
6
+ const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("zod");
7
+ const noNumberSchemaWithStep = require_create_plugin_rule.createZodPluginRule({
8
+ name: "no-number-schema-with-step",
9
+ meta: {
10
+ fixable: "code",
11
+ type: "problem",
12
+ docs: {
13
+ zodImportAllowedSource,
14
+ description: "Disallow deprecated `z.number().step()`. Use `.multipleOf()` instead."
15
+ },
16
+ messages: { useMultipleOf: "`.step()` is deprecated. Use `.multipleOf()` with the same argument instead." },
17
+ schema: []
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
22
+ return {
23
+ ImportDeclaration: importDeclarationListener,
24
+ CallExpression(node) {
25
+ if (detectZodSchemaRootNode(node)?.schemaType !== "number") return;
26
+ if (collectZodChainMethods(node).findIndex((m) => m.name === "step" && m.node === node) === -1) return;
27
+ const { callee } = node;
28
+ if (callee.type !== _typescript_eslint_utils.AST_NODE_TYPES.MemberExpression) return;
29
+ if (callee.property.type !== _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return;
30
+ const { property } = callee;
31
+ context.report({
32
+ node,
33
+ messageId: "useMultipleOf",
34
+ fix(fixer) {
35
+ return fixer.replaceText(property, "multipleOf");
36
+ }
37
+ });
38
+ }
39
+ };
40
+ }
41
+ });
42
+ //#endregion
43
+ exports.noNumberSchemaWithStep = noNumberSchemaWithStep;
@@ -0,0 +1,42 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
3
+ import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
+ //#region src/rules/no-number-schema-with-step.ts
5
+ const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("zod");
6
+ const noNumberSchemaWithStep = createZodPluginRule({
7
+ name: "no-number-schema-with-step",
8
+ meta: {
9
+ fixable: "code",
10
+ type: "problem",
11
+ docs: {
12
+ zodImportAllowedSource,
13
+ description: "Disallow deprecated `z.number().step()`. Use `.multipleOf()` instead."
14
+ },
15
+ messages: { useMultipleOf: "`.step()` is deprecated. Use `.multipleOf()` with the same argument instead." },
16
+ schema: []
17
+ },
18
+ defaultOptions: [],
19
+ create(context) {
20
+ const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
21
+ return {
22
+ ImportDeclaration: importDeclarationListener,
23
+ CallExpression(node) {
24
+ if (detectZodSchemaRootNode(node)?.schemaType !== "number") return;
25
+ if (collectZodChainMethods(node).findIndex((m) => m.name === "step" && m.node === node) === -1) return;
26
+ const { callee } = node;
27
+ if (callee.type !== AST_NODE_TYPES.MemberExpression) return;
28
+ if (callee.property.type !== AST_NODE_TYPES.Identifier) return;
29
+ const { property } = callee;
30
+ context.report({
31
+ node,
32
+ messageId: "useMultipleOf",
33
+ fix(fixer) {
34
+ return fixer.replaceText(property, "multipleOf");
35
+ }
36
+ });
37
+ }
38
+ };
39
+ }
40
+ });
41
+ //#endregion
42
+ export { noNumberSchemaWithStep };
@@ -8,6 +8,7 @@ const requireSchemaSuffix = require_create_plugin_rule.createZodPluginRule({
8
8
  name: "require-schema-suffix",
9
9
  meta: {
10
10
  type: "suggestion",
11
+ deprecated: { message: "Use `zod/consistent-schema-name`" },
11
12
  docs: {
12
13
  zodImportAllowedSource,
13
14
  description: "Require schema suffix when declaring a Zod schema"
@@ -7,6 +7,7 @@ const requireSchemaSuffix = createZodPluginRule({
7
7
  name: "require-schema-suffix",
8
8
  meta: {
9
9
  type: "suggestion",
10
+ deprecated: { message: "Use `zod/consistent-schema-name`" },
10
11
  docs: {
11
12
  zodImportAllowedSource,
12
13
  description: "Require schema suffix when declaring a Zod schema"
@@ -0,0 +1,15 @@
1
+ //#region src/utils/build-zod-chain-remove-method-fix.ts
2
+ /**
3
+ * Remove one call from a zod method chain, e.g. `z.number().min(0).finite()` β†’
4
+ * `z.number().min(0)`.
5
+ */
6
+ function buildZodChainRemoveMethodFix(opts) {
7
+ const { fixer, methods, removeIndex } = opts;
8
+ if (removeIndex < 1) return null;
9
+ const prev = methods[removeIndex - 1]?.node;
10
+ const toRemove = methods[removeIndex]?.node;
11
+ if (!prev?.range || !toRemove?.range) return null;
12
+ return fixer.removeRange([prev.range[1], toRemove.range[1]]);
13
+ }
14
+ //#endregion
15
+ exports.buildZodChainRemoveMethodFix = buildZodChainRemoveMethodFix;
@@ -0,0 +1,15 @@
1
+ //#region src/utils/build-zod-chain-remove-method-fix.ts
2
+ /**
3
+ * Remove one call from a zod method chain, e.g. `z.number().min(0).finite()` β†’
4
+ * `z.number().min(0)`.
5
+ */
6
+ function buildZodChainRemoveMethodFix(opts) {
7
+ const { fixer, methods, removeIndex } = opts;
8
+ if (removeIndex < 1) return null;
9
+ const prev = methods[removeIndex - 1]?.node;
10
+ const toRemove = methods[removeIndex]?.node;
11
+ if (!prev?.range || !toRemove?.range) return null;
12
+ return fixer.removeRange([prev.range[1], toRemove.range[1]]);
13
+ }
14
+ //#endregion
15
+ export { buildZodChainRemoveMethodFix };
@@ -71,6 +71,16 @@ function parseZodCallExpression(call, zodNamespaces, zodNamedImports) {
71
71
  };
72
72
  return null;
73
73
  }
74
+ /**
75
+ * True when `node` is a zod number schema call chain (e.g. `z.number().min(1)`) or `number().min(1)`.
76
+ * Used for member access like `z.number().isInt` where the call is not the outermost expression
77
+ * in the file (so {@link detectZodSchemaRootNode} does not apply).
78
+ */
79
+ function isZodNumberSchemaCallExpression(node, zodNamespaces, zodNamedImports) {
80
+ if (node.type !== _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) return false;
81
+ const parsed = parseZodCallExpression(node, zodNamespaces, zodNamedImports);
82
+ return parsed !== null && parsed.schemaType === "number";
83
+ }
74
84
  /** Examine an expression (argument) for zod schema CallExpressions.
75
85
  * Supports:
76
86
  * - direct CallExpression (string(), z.string(), etc)
@@ -100,3 +110,4 @@ function detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports) {
100
110
  }
101
111
  //#endregion
102
112
  exports.detectZodSchemaRootNode = detectZodSchemaRootNode;
113
+ exports.isZodNumberSchemaCallExpression = isZodNumberSchemaCallExpression;
@@ -70,6 +70,16 @@ function parseZodCallExpression(call, zodNamespaces, zodNamedImports) {
70
70
  };
71
71
  return null;
72
72
  }
73
+ /**
74
+ * True when `node` is a zod number schema call chain (e.g. `z.number().min(1)`) or `number().min(1)`.
75
+ * Used for member access like `z.number().isInt` where the call is not the outermost expression
76
+ * in the file (so {@link detectZodSchemaRootNode} does not apply).
77
+ */
78
+ function isZodNumberSchemaCallExpression(node, zodNamespaces, zodNamedImports) {
79
+ if (node.type !== AST_NODE_TYPES.CallExpression) return false;
80
+ const parsed = parseZodCallExpression(node, zodNamespaces, zodNamedImports);
81
+ return parsed !== null && parsed.schemaType === "number";
82
+ }
73
83
  /** Examine an expression (argument) for zod schema CallExpressions.
74
84
  * Supports:
75
85
  * - direct CallExpression (string(), z.string(), etc)
@@ -98,4 +108,4 @@ function detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports) {
98
108
  };
99
109
  }
100
110
  //#endregion
101
- export { detectZodSchemaRootNode };
111
+ export { detectZodSchemaRootNode, isZodNumberSchemaCallExpression };
@@ -58,7 +58,8 @@ function trackZodSchemaImports(importAllowedSource) {
58
58
  getNamedImportOriginal: (localName) => zodNamedImports.get(localName),
59
59
  getNamedImportLocal: (originalName) => zodNamedImportsByOriginal.get(originalName),
60
60
  detectZodSchemaRootNode: (node) => require_detect_zod_schema_root_node.detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports),
61
- collectZodChainMethods
61
+ collectZodChainMethods,
62
+ isZodNumberSchemaCallExpression: (node) => require_detect_zod_schema_root_node.isZodNumberSchemaCallExpression(node, zodNamespaces, zodNamedImports)
62
63
  };
63
64
  }
64
65
  /**
@@ -1,4 +1,4 @@
1
- import { detectZodSchemaRootNode } from "./detect-zod-schema-root-node.mjs";
1
+ import { detectZodSchemaRootNode, isZodNumberSchemaCallExpression } from "./detect-zod-schema-root-node.mjs";
2
2
  import { isZodImportSource } from "./is-zod-import-source.mjs";
3
3
  import { AST_NODE_TYPES } from "@typescript-eslint/utils";
4
4
  //#region src/utils/track-zod-schema-imports.ts
@@ -57,7 +57,8 @@ function trackZodSchemaImports(importAllowedSource) {
57
57
  getNamedImportOriginal: (localName) => zodNamedImports.get(localName),
58
58
  getNamedImportLocal: (originalName) => zodNamedImportsByOriginal.get(originalName),
59
59
  detectZodSchemaRootNode: (node) => detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports),
60
- collectZodChainMethods
60
+ collectZodChainMethods,
61
+ isZodNumberSchemaCallExpression: (node) => isZodNumberSchemaCallExpression(node, zodNamespaces, zodNamedImports)
61
62
  };
62
63
  }
63
64
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-zod",
3
- "version": "3.8.0",
3
+ "version": "3.10.0",
4
4
  "type": "module",
5
5
  "description": "ESLint plugin that adds custom linting rules to enforce best practices when using Zod",
6
6
  "engines": {