eslint-plugin-zod 3.10.0 → 3.12.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 +18 -17
- package/dist/index.cjs +7 -4
- package/dist/index.mjs +7 -4
- package/dist/rules/{consistent-schema-name.cjs → consistent-schema-var-name.cjs} +4 -4
- package/dist/rules/{consistent-schema-name.mjs → consistent-schema-var-name.mjs} +4 -4
- package/dist/rules/prefer-trim-before-string-length-checks.cjs +63 -0
- package/dist/rules/prefer-trim-before-string-length-checks.mjs +63 -0
- package/dist/rules/require-schema-suffix.cjs +1 -1
- package/dist/rules/require-schema-suffix.mjs +1 -1
- package/dist/rules/schema-error-property-style.cjs +1 -1
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -43,8 +43,8 @@ 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 | ✅ ✔️ | | | |
|
|
47
46
|
| [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
|
+
| [consistent-schema-var-name](docs/rules/consistent-schema-var-name.md) | Enforce a consistent naming convention for Zod schema variables | ✅ ✔️ | | | |
|
|
48
48
|
| [no-any-schema](docs/rules/no-any-schema.md) | Disallow usage of `z.any()` in Zod schemas | ✅ ✔️ | | 💡 | |
|
|
49
49
|
| [no-empty-custom-schema](docs/rules/no-empty-custom-schema.md) | Disallow usage of `z.custom()` without arguments | ✅ | | | |
|
|
50
50
|
| [no-unknown-schema](docs/rules/no-unknown-schema.md) | Disallow usage of `z.unknown()` in Zod schemas | | | | |
|
|
@@ -57,22 +57,23 @@ This plugin is primarily built for `zod`, so some rules are exclusive to `zod` a
|
|
|
57
57
|
|
|
58
58
|
### `zod` exclusive rules
|
|
59
59
|
|
|
60
|
-
| Name
|
|
61
|
-
|
|
|
62
|
-
| [array-style](docs/rules/array-style.md)
|
|
63
|
-
| [no-number-schema-with-finite](docs/rules/no-number-schema-with-finite.md)
|
|
64
|
-
| [no-number-schema-with-int](docs/rules/no-number-schema-with-int.md)
|
|
65
|
-
| [no-number-schema-with-is-finite](docs/rules/no-number-schema-with-is-finite.md)
|
|
66
|
-
| [no-number-schema-with-is-int](docs/rules/no-number-schema-with-is-int.md)
|
|
67
|
-
| [no-number-schema-with-safe](docs/rules/no-number-schema-with-safe.md)
|
|
68
|
-
| [no-number-schema-with-step](docs/rules/no-number-schema-with-step.md)
|
|
69
|
-
| [no-optional-and-default-together](docs/rules/no-optional-and-default-together.md)
|
|
70
|
-
| [no-string-schema-with-uuid](docs/rules/no-string-schema-with-uuid.md)
|
|
71
|
-
| [no-throw-in-refine](docs/rules/no-throw-in-refine.md)
|
|
72
|
-
| [no-transform-in-record-key](docs/rules/no-transform-in-record-key.md)
|
|
73
|
-
| [prefer-enum-over-literal-union](docs/rules/prefer-enum-over-literal-union.md)
|
|
74
|
-
| [prefer-meta-last](docs/rules/prefer-meta-last.md)
|
|
75
|
-
| [prefer-string-schema-with-trim](docs/rules/prefer-string-schema-with-trim.md)
|
|
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 | ✅ | 🔧 | | |
|
|
76
|
+
| [prefer-trim-before-string-length-checks](docs/rules/prefer-trim-before-string-length-checks.md) | Enforce `.trim()` is called before string length checks to ensure accurate validation | ✅ | 🔧 | | |
|
|
76
77
|
|
|
77
78
|
<!-- end auto-generated rules list -->
|
|
78
79
|
|
package/dist/index.cjs
CHANGED
|
@@ -3,8 +3,8 @@ 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");
|
|
7
6
|
const require_consistent_schema_output_type_style = require("./rules/consistent-schema-output-type-style.cjs");
|
|
7
|
+
const require_consistent_schema_var_name = require("./rules/consistent-schema-var-name.cjs");
|
|
8
8
|
const require_no_any_schema = require("./rules/no-any-schema.cjs");
|
|
9
9
|
const require_no_empty_custom_schema = require("./rules/no-empty-custom-schema.cjs");
|
|
10
10
|
const require_no_number_schema_with_finite = require("./rules/no-number-schema-with-finite.cjs");
|
|
@@ -23,6 +23,7 @@ const require_prefer_meta_last = require("./rules/prefer-meta-last.cjs");
|
|
|
23
23
|
const require_prefer_meta = require("./rules/prefer-meta.cjs");
|
|
24
24
|
const require_prefer_namespace_import = require("./rules/prefer-namespace-import.cjs");
|
|
25
25
|
const require_prefer_string_schema_with_trim = require("./rules/prefer-string-schema-with-trim.cjs");
|
|
26
|
+
const require_prefer_trim_before_string_length_checks = require("./rules/prefer-trim-before-string-length-checks.cjs");
|
|
26
27
|
const require_require_brand_type_parameter = require("./rules/require-brand-type-parameter.cjs");
|
|
27
28
|
const require_require_error_message = require("./rules/require-error-message.cjs");
|
|
28
29
|
const require_require_schema_suffix = require("./rules/require-schema-suffix.cjs");
|
|
@@ -38,7 +39,7 @@ const eslintPluginZod = {
|
|
|
38
39
|
"consistent-import-source": require_consistent_import_source.consistentImportSource,
|
|
39
40
|
"consistent-import": require_consistent_import.consistentImport,
|
|
40
41
|
"consistent-object-schema-type": require_consistent_object_schema_type.consistentObjectSchemaType,
|
|
41
|
-
"consistent-schema-name":
|
|
42
|
+
"consistent-schema-var-name": require_consistent_schema_var_name.consistentSchemaVarName,
|
|
42
43
|
"consistent-schema-output-type-style": require_consistent_schema_output_type_style.consistentSchemaOutputTypeStyle,
|
|
43
44
|
"no-any-schema": require_no_any_schema.noAnySchema,
|
|
44
45
|
"no-empty-custom-schema": require_no_empty_custom_schema.noEmptyCustomSchema,
|
|
@@ -58,6 +59,7 @@ const eslintPluginZod = {
|
|
|
58
59
|
"prefer-meta-last": require_prefer_meta_last.preferMetaLast,
|
|
59
60
|
"prefer-namespace-import": require_prefer_namespace_import.preferNamespaceImport,
|
|
60
61
|
"prefer-string-schema-with-trim": require_prefer_string_schema_with_trim.preferStringSchemaWithTrim,
|
|
62
|
+
"prefer-trim-before-string-length-checks": require_prefer_trim_before_string_length_checks.preferTrimBeforeStringLengthChecks,
|
|
61
63
|
"require-brand-type-parameter": require_require_brand_type_parameter.requireBrandTypeParameter,
|
|
62
64
|
"require-error-message": require_require_error_message.requireErrorMessage,
|
|
63
65
|
"require-schema-suffix": require_require_schema_suffix.requireSchemaSuffix,
|
|
@@ -74,7 +76,7 @@ const recommendedConfig = {
|
|
|
74
76
|
rules: {
|
|
75
77
|
"zod/array-style": "error",
|
|
76
78
|
"zod/consistent-import": "error",
|
|
77
|
-
"zod/consistent-schema-name": "error",
|
|
79
|
+
"zod/consistent-schema-var-name": "error",
|
|
78
80
|
"zod/no-any-schema": "error",
|
|
79
81
|
"zod/no-empty-custom-schema": "error",
|
|
80
82
|
"zod/no-number-schema-with-finite": "error",
|
|
@@ -90,6 +92,7 @@ const recommendedConfig = {
|
|
|
90
92
|
"zod/prefer-meta": "error",
|
|
91
93
|
"zod/prefer-meta-last": "error",
|
|
92
94
|
"zod/prefer-string-schema-with-trim": "error",
|
|
95
|
+
"zod/prefer-trim-before-string-length-checks": "error",
|
|
93
96
|
"zod/require-brand-type-parameter": "error",
|
|
94
97
|
"zod/require-error-message": "error"
|
|
95
98
|
}
|
|
@@ -97,7 +100,7 @@ const recommendedConfig = {
|
|
|
97
100
|
const recommendedConfigMini = {
|
|
98
101
|
...baseConfig,
|
|
99
102
|
rules: {
|
|
100
|
-
"zod/consistent-schema-name": "error",
|
|
103
|
+
"zod/consistent-schema-var-name": "error",
|
|
101
104
|
"zod/no-any-schema": "error",
|
|
102
105
|
"zod/prefer-meta": "error",
|
|
103
106
|
"zod/require-brand-type-parameter": "error",
|
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,8 @@ 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";
|
|
7
6
|
import { consistentSchemaOutputTypeStyle } from "./rules/consistent-schema-output-type-style.mjs";
|
|
7
|
+
import { consistentSchemaVarName } from "./rules/consistent-schema-var-name.mjs";
|
|
8
8
|
import { noAnySchema } from "./rules/no-any-schema.mjs";
|
|
9
9
|
import { noEmptyCustomSchema } from "./rules/no-empty-custom-schema.mjs";
|
|
10
10
|
import { noNumberSchemaWithFinite } from "./rules/no-number-schema-with-finite.mjs";
|
|
@@ -23,6 +23,7 @@ import { preferMetaLast } from "./rules/prefer-meta-last.mjs";
|
|
|
23
23
|
import { preferMeta } from "./rules/prefer-meta.mjs";
|
|
24
24
|
import { preferNamespaceImport } from "./rules/prefer-namespace-import.mjs";
|
|
25
25
|
import { preferStringSchemaWithTrim } from "./rules/prefer-string-schema-with-trim.mjs";
|
|
26
|
+
import { preferTrimBeforeStringLengthChecks } from "./rules/prefer-trim-before-string-length-checks.mjs";
|
|
26
27
|
import { requireBrandTypeParameter } from "./rules/require-brand-type-parameter.mjs";
|
|
27
28
|
import { requireErrorMessage } from "./rules/require-error-message.mjs";
|
|
28
29
|
import { requireSchemaSuffix } from "./rules/require-schema-suffix.mjs";
|
|
@@ -38,7 +39,7 @@ const eslintPluginZod = {
|
|
|
38
39
|
"consistent-import-source": consistentImportSource,
|
|
39
40
|
"consistent-import": consistentImport,
|
|
40
41
|
"consistent-object-schema-type": consistentObjectSchemaType,
|
|
41
|
-
"consistent-schema-name":
|
|
42
|
+
"consistent-schema-var-name": consistentSchemaVarName,
|
|
42
43
|
"consistent-schema-output-type-style": consistentSchemaOutputTypeStyle,
|
|
43
44
|
"no-any-schema": noAnySchema,
|
|
44
45
|
"no-empty-custom-schema": noEmptyCustomSchema,
|
|
@@ -58,6 +59,7 @@ const eslintPluginZod = {
|
|
|
58
59
|
"prefer-meta-last": preferMetaLast,
|
|
59
60
|
"prefer-namespace-import": preferNamespaceImport,
|
|
60
61
|
"prefer-string-schema-with-trim": preferStringSchemaWithTrim,
|
|
62
|
+
"prefer-trim-before-string-length-checks": preferTrimBeforeStringLengthChecks,
|
|
61
63
|
"require-brand-type-parameter": requireBrandTypeParameter,
|
|
62
64
|
"require-error-message": requireErrorMessage,
|
|
63
65
|
"require-schema-suffix": requireSchemaSuffix,
|
|
@@ -74,7 +76,7 @@ const recommendedConfig = {
|
|
|
74
76
|
rules: {
|
|
75
77
|
"zod/array-style": "error",
|
|
76
78
|
"zod/consistent-import": "error",
|
|
77
|
-
"zod/consistent-schema-name": "error",
|
|
79
|
+
"zod/consistent-schema-var-name": "error",
|
|
78
80
|
"zod/no-any-schema": "error",
|
|
79
81
|
"zod/no-empty-custom-schema": "error",
|
|
80
82
|
"zod/no-number-schema-with-finite": "error",
|
|
@@ -90,6 +92,7 @@ const recommendedConfig = {
|
|
|
90
92
|
"zod/prefer-meta": "error",
|
|
91
93
|
"zod/prefer-meta-last": "error",
|
|
92
94
|
"zod/prefer-string-schema-with-trim": "error",
|
|
95
|
+
"zod/prefer-trim-before-string-length-checks": "error",
|
|
93
96
|
"zod/require-brand-type-parameter": "error",
|
|
94
97
|
"zod/require-error-message": "error"
|
|
95
98
|
}
|
|
@@ -97,7 +100,7 @@ const recommendedConfig = {
|
|
|
97
100
|
const recommendedConfigMini = {
|
|
98
101
|
...baseConfig,
|
|
99
102
|
rules: {
|
|
100
|
-
"zod/consistent-schema-name": "error",
|
|
103
|
+
"zod/consistent-schema-var-name": "error",
|
|
101
104
|
"zod/no-any-schema": "error",
|
|
102
105
|
"zod/prefer-meta": "error",
|
|
103
106
|
"zod/require-brand-type-parameter": "error",
|
|
@@ -2,10 +2,10 @@ require("../_virtual/_rolldown/runtime.cjs");
|
|
|
2
2
|
const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
|
|
3
3
|
const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
|
|
4
4
|
let _typescript_eslint_utils = require("@typescript-eslint/utils");
|
|
5
|
-
//#region src/rules/consistent-schema-name.ts
|
|
5
|
+
//#region src/rules/consistent-schema-var-name.ts
|
|
6
6
|
const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("all");
|
|
7
|
-
const
|
|
8
|
-
name: "consistent-schema-name",
|
|
7
|
+
const consistentSchemaVarName = require_create_plugin_rule.createZodPluginRule({
|
|
8
|
+
name: "consistent-schema-var-name",
|
|
9
9
|
meta: {
|
|
10
10
|
type: "suggestion",
|
|
11
11
|
docs: {
|
|
@@ -73,4 +73,4 @@ const consistentSchemaName = require_create_plugin_rule.createZodPluginRule({
|
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
//#endregion
|
|
76
|
-
exports.
|
|
76
|
+
exports.consistentSchemaVarName = consistentSchemaVarName;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
|
|
2
2
|
import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
|
|
3
3
|
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
4
|
-
//#region src/rules/consistent-schema-name.ts
|
|
4
|
+
//#region src/rules/consistent-schema-var-name.ts
|
|
5
5
|
const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("all");
|
|
6
|
-
const
|
|
7
|
-
name: "consistent-schema-name",
|
|
6
|
+
const consistentSchemaVarName = createZodPluginRule({
|
|
7
|
+
name: "consistent-schema-var-name",
|
|
8
8
|
meta: {
|
|
9
9
|
type: "suggestion",
|
|
10
10
|
docs: {
|
|
@@ -72,4 +72,4 @@ const consistentSchemaName = createZodPluginRule({
|
|
|
72
72
|
}
|
|
73
73
|
});
|
|
74
74
|
//#endregion
|
|
75
|
-
export {
|
|
75
|
+
export { consistentSchemaVarName };
|
|
@@ -0,0 +1,63 @@
|
|
|
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_find_parent_schema_matching_condition = require("../utils/find-parent-schema-matching-condition.cjs");
|
|
4
|
+
//#region src/rules/prefer-trim-before-string-length-checks.ts
|
|
5
|
+
const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("zod");
|
|
6
|
+
const LENGTH_CHECK_METHODS = [
|
|
7
|
+
"min",
|
|
8
|
+
"max",
|
|
9
|
+
"length"
|
|
10
|
+
];
|
|
11
|
+
const preferTrimBeforeStringLengthChecks = require_create_plugin_rule.createZodPluginRule({
|
|
12
|
+
name: "prefer-trim-before-string-length-checks",
|
|
13
|
+
meta: {
|
|
14
|
+
type: "problem",
|
|
15
|
+
fixable: "code",
|
|
16
|
+
docs: {
|
|
17
|
+
zodImportAllowedSource,
|
|
18
|
+
description: "Enforce `.trim()` is called before string length checks to ensure accurate validation"
|
|
19
|
+
},
|
|
20
|
+
messages: { trimBeforeLengthCheck: "`.trim()` must be called before length checks (`.min()`, `.max()`, `.length()`) to ensure accurate validation." },
|
|
21
|
+
schema: []
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create(context) {
|
|
25
|
+
const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
|
|
26
|
+
return {
|
|
27
|
+
ImportDeclaration: importDeclarationListener,
|
|
28
|
+
CallExpression(node) {
|
|
29
|
+
const zodSchemaMeta = detectZodSchemaRootNode(node);
|
|
30
|
+
if (zodSchemaMeta?.schemaType !== "string") return;
|
|
31
|
+
if (require_find_parent_schema_matching_condition.findParentSchemaMatchingCondition(zodSchemaMeta.node, {
|
|
32
|
+
schemaName: "record",
|
|
33
|
+
condition: (callParent) => callParent.arguments.length > 0 && callParent.arguments[0] === zodSchemaMeta.node
|
|
34
|
+
})) return;
|
|
35
|
+
const methods = collectZodChainMethods(zodSchemaMeta.node);
|
|
36
|
+
const trimIndex = methods.findIndex((m) => m.name === "trim");
|
|
37
|
+
if (trimIndex === -1) return;
|
|
38
|
+
const firstLengthCheckIndex = methods.findIndex((m) => LENGTH_CHECK_METHODS.includes(m.name));
|
|
39
|
+
if (firstLengthCheckIndex === -1) return;
|
|
40
|
+
if (trimIndex < firstLengthCheckIndex) return;
|
|
41
|
+
if (zodSchemaMeta.schemaDecl === "named") {
|
|
42
|
+
context.report({
|
|
43
|
+
node,
|
|
44
|
+
messageId: "trimBeforeLengthCheck"
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
context.report({
|
|
49
|
+
node,
|
|
50
|
+
messageId: "trimBeforeLengthCheck",
|
|
51
|
+
fix(fixer) {
|
|
52
|
+
const stringMethodNode = methods[0].node;
|
|
53
|
+
const trimMethodNode = methods[trimIndex].node;
|
|
54
|
+
const trimCallee = trimMethodNode.callee;
|
|
55
|
+
return [fixer.removeRange([trimCallee.object.range[1], trimMethodNode.range[1]]), fixer.insertTextAfter(stringMethodNode, ".trim()")];
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
//#endregion
|
|
63
|
+
exports.preferTrimBeforeStringLengthChecks = preferTrimBeforeStringLengthChecks;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
|
|
2
|
+
import { createZodSchemaImportTrack } from "../utils/track-zod-schema-imports.mjs";
|
|
3
|
+
import { findParentSchemaMatchingCondition } from "../utils/find-parent-schema-matching-condition.mjs";
|
|
4
|
+
//#region src/rules/prefer-trim-before-string-length-checks.ts
|
|
5
|
+
const { zodImportAllowedSource, trackZodSchemaImports } = createZodSchemaImportTrack("zod");
|
|
6
|
+
const LENGTH_CHECK_METHODS = [
|
|
7
|
+
"min",
|
|
8
|
+
"max",
|
|
9
|
+
"length"
|
|
10
|
+
];
|
|
11
|
+
const preferTrimBeforeStringLengthChecks = createZodPluginRule({
|
|
12
|
+
name: "prefer-trim-before-string-length-checks",
|
|
13
|
+
meta: {
|
|
14
|
+
type: "problem",
|
|
15
|
+
fixable: "code",
|
|
16
|
+
docs: {
|
|
17
|
+
zodImportAllowedSource,
|
|
18
|
+
description: "Enforce `.trim()` is called before string length checks to ensure accurate validation"
|
|
19
|
+
},
|
|
20
|
+
messages: { trimBeforeLengthCheck: "`.trim()` must be called before length checks (`.min()`, `.max()`, `.length()`) to ensure accurate validation." },
|
|
21
|
+
schema: []
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create(context) {
|
|
25
|
+
const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
|
|
26
|
+
return {
|
|
27
|
+
ImportDeclaration: importDeclarationListener,
|
|
28
|
+
CallExpression(node) {
|
|
29
|
+
const zodSchemaMeta = detectZodSchemaRootNode(node);
|
|
30
|
+
if (zodSchemaMeta?.schemaType !== "string") return;
|
|
31
|
+
if (findParentSchemaMatchingCondition(zodSchemaMeta.node, {
|
|
32
|
+
schemaName: "record",
|
|
33
|
+
condition: (callParent) => callParent.arguments.length > 0 && callParent.arguments[0] === zodSchemaMeta.node
|
|
34
|
+
})) return;
|
|
35
|
+
const methods = collectZodChainMethods(zodSchemaMeta.node);
|
|
36
|
+
const trimIndex = methods.findIndex((m) => m.name === "trim");
|
|
37
|
+
if (trimIndex === -1) return;
|
|
38
|
+
const firstLengthCheckIndex = methods.findIndex((m) => LENGTH_CHECK_METHODS.includes(m.name));
|
|
39
|
+
if (firstLengthCheckIndex === -1) return;
|
|
40
|
+
if (trimIndex < firstLengthCheckIndex) return;
|
|
41
|
+
if (zodSchemaMeta.schemaDecl === "named") {
|
|
42
|
+
context.report({
|
|
43
|
+
node,
|
|
44
|
+
messageId: "trimBeforeLengthCheck"
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
context.report({
|
|
49
|
+
node,
|
|
50
|
+
messageId: "trimBeforeLengthCheck",
|
|
51
|
+
fix(fixer) {
|
|
52
|
+
const stringMethodNode = methods[0].node;
|
|
53
|
+
const trimMethodNode = methods[trimIndex].node;
|
|
54
|
+
const trimCallee = trimMethodNode.callee;
|
|
55
|
+
return [fixer.removeRange([trimCallee.object.range[1], trimMethodNode.range[1]]), fixer.insertTextAfter(stringMethodNode, ".trim()")];
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
//#endregion
|
|
63
|
+
export { preferTrimBeforeStringLengthChecks };
|
|
@@ -8,7 +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
|
+
deprecated: { message: "Use `zod/consistent-schema-var-name`" },
|
|
12
12
|
docs: {
|
|
13
13
|
zodImportAllowedSource,
|
|
14
14
|
description: "Require schema suffix when declaring a Zod schema"
|
|
@@ -7,7 +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
|
+
deprecated: { message: "Use `zod/consistent-schema-var-name`" },
|
|
11
11
|
docs: {
|
|
12
12
|
zodImportAllowedSource,
|
|
13
13
|
description: "Require schema suffix when declaring a Zod schema"
|
|
@@ -3,7 +3,7 @@ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
|
|
|
3
3
|
const require_track_zod_schema_imports = require("../utils/track-zod-schema-imports.cjs");
|
|
4
4
|
let _typescript_eslint_utils = require("@typescript-eslint/utils");
|
|
5
5
|
let esquery = require("esquery");
|
|
6
|
-
esquery = require_runtime.__toESM(esquery);
|
|
6
|
+
esquery = require_runtime.__toESM(esquery, 1);
|
|
7
7
|
//#region src/rules/schema-error-property-style.ts
|
|
8
8
|
const { zodImportAllowedSource, trackZodSchemaImports } = require_track_zod_schema_imports.createZodSchemaImportTrack("all");
|
|
9
9
|
const schemaErrorPropertyStyle = require_create_plugin_rule.createZodPluginRule({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-zod",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.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": {
|
|
@@ -62,26 +62,26 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@changesets/changelog-github": "0.6.0",
|
|
65
|
-
"@changesets/cli": "2.
|
|
65
|
+
"@changesets/cli": "2.31.0",
|
|
66
66
|
"@marcalexiei/eslint-config": "6.0.0",
|
|
67
67
|
"@marcalexiei/prettier-config": "1.1.4",
|
|
68
68
|
"@types/esquery": "1.5.4",
|
|
69
|
-
"@types/node": "25.
|
|
70
|
-
"@typescript-eslint/rule-tester": "8.
|
|
71
|
-
"@vitest/eslint-plugin": "1.6.
|
|
69
|
+
"@types/node": "25.6.0",
|
|
70
|
+
"@typescript-eslint/rule-tester": "8.59.0",
|
|
71
|
+
"@vitest/eslint-plugin": "1.6.16",
|
|
72
72
|
"dedent": "1.7.2",
|
|
73
|
-
"eslint": "10.2.
|
|
73
|
+
"eslint": "10.2.1",
|
|
74
74
|
"eslint-doc-generator": "3.3.2",
|
|
75
75
|
"eslint-import-resolver-typescript": "4.4.4",
|
|
76
76
|
"eslint-plugin-eslint-plugin": "7.3.2",
|
|
77
77
|
"eslint-plugin-import-x": "4.16.2",
|
|
78
78
|
"eslint-plugin-n": "17.24.0",
|
|
79
|
-
"knip": "6.
|
|
80
|
-
"prettier": "3.8.
|
|
81
|
-
"tsdown": "0.21.
|
|
82
|
-
"typescript": "6.0.
|
|
83
|
-
"typescript-eslint": "8.
|
|
84
|
-
"vitest": "4.1.
|
|
79
|
+
"knip": "6.7.0",
|
|
80
|
+
"prettier": "3.8.3",
|
|
81
|
+
"tsdown": "0.21.10",
|
|
82
|
+
"typescript": "6.0.3",
|
|
83
|
+
"typescript-eslint": "8.59.0",
|
|
84
|
+
"vitest": "4.1.5"
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"build": "tsdown",
|