eslint-plugin-zod 3.2.0 → 3.3.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 +1 -0
- package/dist/index.cjs +3 -0
- package/dist/index.js +3 -0
- package/dist/rules/no-optional-and-default-together.cjs +2 -2
- package/dist/rules/no-optional-and-default-together.js +2 -2
- package/dist/rules/prefer-string-schema-with-trim.cjs +52 -0
- package/dist/rules/prefer-string-schema-with-trim.d.cts +4 -0
- package/dist/rules/prefer-string-schema-with-trim.d.ts +4 -0
- package/dist/rules/prefer-string-schema-with-trim.js +49 -0
- package/dist/utils/build-zod-chain-replacement-fix.cjs +8 -1
- package/dist/utils/build-zod-chain-replacement-fix.js +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
| [prefer-meta](docs/rules/prefer-meta.md) | Enforce usage of `.meta()` over `.describe()` | ✅ | 🔧 | | |
|
|
47
47
|
| [prefer-meta-last](docs/rules/prefer-meta-last.md) | Enforce `.meta()` as last method | ✅ | 🔧 | | |
|
|
48
48
|
| [prefer-namespace-import](docs/rules/prefer-namespace-import.md) | Enforce importing zod as a namespace import (`import * as z from 'zod'`) | | 🔧 | | ❌ |
|
|
49
|
+
| [prefer-string-schema-with-trim](docs/rules/prefer-string-schema-with-trim.md) | Enforce `z.string().trim()` to prevent accidental leading/trailing whitespace | ✅ | 🔧 | | |
|
|
49
50
|
| [require-brand-type-parameter](docs/rules/require-brand-type-parameter.md) | Require type parameter on `.brand()` functions | ✅ | | 💡 | |
|
|
50
51
|
| [require-error-message](docs/rules/require-error-message.md) | Enforce that custom refinements include an error message | ✅ | 🔧 | | |
|
|
51
52
|
| [require-schema-suffix](docs/rules/require-schema-suffix.md) | Require schema suffix when declaring a Zod schema | ✅ | | | |
|
package/dist/index.cjs
CHANGED
|
@@ -16,6 +16,7 @@ const prefer_enum_over_literal_union_js_1 = require("./rules/prefer-enum-over-li
|
|
|
16
16
|
const prefer_meta_last_js_1 = require("./rules/prefer-meta-last.cjs");
|
|
17
17
|
const prefer_meta_js_1 = require("./rules/prefer-meta.cjs");
|
|
18
18
|
const prefer_namespace_import_js_1 = require("./rules/prefer-namespace-import.cjs");
|
|
19
|
+
const prefer_string_schema_with_trim_js_1 = require("./rules/prefer-string-schema-with-trim.cjs");
|
|
19
20
|
const require_brand_type_parameter_js_1 = require("./rules/require-brand-type-parameter.cjs");
|
|
20
21
|
const require_error_message_js_1 = require("./rules/require-error-message.cjs");
|
|
21
22
|
const require_schema_suffix_js_1 = require("./rules/require-schema-suffix.cjs");
|
|
@@ -41,6 +42,7 @@ const eslintPluginZod = {
|
|
|
41
42
|
'prefer-meta': prefer_meta_js_1.preferMeta,
|
|
42
43
|
'prefer-meta-last': prefer_meta_last_js_1.preferMetaLast,
|
|
43
44
|
'prefer-namespace-import': prefer_namespace_import_js_1.preferNamespaceImport,
|
|
45
|
+
'prefer-string-schema-with-trim': prefer_string_schema_with_trim_js_1.preferStringSchemaWithTrim,
|
|
44
46
|
'require-brand-type-parameter': require_brand_type_parameter_js_1.requireBrandTypeParameter,
|
|
45
47
|
'require-error-message': require_error_message_js_1.requireErrorMessage,
|
|
46
48
|
'require-schema-suffix': require_schema_suffix_js_1.requireSchemaSuffix,
|
|
@@ -65,6 +67,7 @@ const recommendedConfig = {
|
|
|
65
67
|
'zod/prefer-enum-over-literal-union': 'error',
|
|
66
68
|
'zod/prefer-meta': 'error',
|
|
67
69
|
'zod/prefer-meta-last': 'error',
|
|
70
|
+
'zod/prefer-string-schema-with-trim': 'error',
|
|
68
71
|
'zod/require-brand-type-parameter': 'error',
|
|
69
72
|
'zod/require-error-message': 'error',
|
|
70
73
|
'zod/require-schema-suffix': 'error',
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { preferEnumOverLiteralUnion } from "./rules/prefer-enum-over-literal-uni
|
|
|
14
14
|
import { preferMetaLast } from "./rules/prefer-meta-last.js";
|
|
15
15
|
import { preferMeta } from "./rules/prefer-meta.js";
|
|
16
16
|
import { preferNamespaceImport } from "./rules/prefer-namespace-import.js";
|
|
17
|
+
import { preferStringSchemaWithTrim } from "./rules/prefer-string-schema-with-trim.js";
|
|
17
18
|
import { requireBrandTypeParameter } from "./rules/require-brand-type-parameter.js";
|
|
18
19
|
import { requireErrorMessage } from "./rules/require-error-message.js";
|
|
19
20
|
import { requireSchemaSuffix } from "./rules/require-schema-suffix.js";
|
|
@@ -39,6 +40,7 @@ const eslintPluginZod = {
|
|
|
39
40
|
'prefer-meta': preferMeta,
|
|
40
41
|
'prefer-meta-last': preferMetaLast,
|
|
41
42
|
'prefer-namespace-import': preferNamespaceImport,
|
|
43
|
+
'prefer-string-schema-with-trim': preferStringSchemaWithTrim,
|
|
42
44
|
'require-brand-type-parameter': requireBrandTypeParameter,
|
|
43
45
|
'require-error-message': requireErrorMessage,
|
|
44
46
|
'require-schema-suffix': requireSchemaSuffix,
|
|
@@ -63,6 +65,7 @@ const recommendedConfig = {
|
|
|
63
65
|
'zod/prefer-enum-over-literal-union': 'error',
|
|
64
66
|
'zod/prefer-meta': 'error',
|
|
65
67
|
'zod/prefer-meta-last': 'error',
|
|
68
|
+
'zod/prefer-string-schema-with-trim': 'error',
|
|
66
69
|
'zod/require-brand-type-parameter': 'error',
|
|
67
70
|
'zod/require-error-message': 'error',
|
|
68
71
|
'zod/require-schema-suffix': 'error',
|
|
@@ -35,11 +35,11 @@ exports.noOptionalAndDefaultTogether = utils_1.ESLintUtils.RuleCreator(meta_js_1
|
|
|
35
35
|
defaultOptions: [defaultOptions],
|
|
36
36
|
create(context, [{ preferredMethod }]) {
|
|
37
37
|
const { sourceCode } = context;
|
|
38
|
-
const { importDeclarationListener, detectZodSchemaRootNode
|
|
38
|
+
const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods, } = (0, track_zod_schema_imports_js_1.trackZodSchemaImports)();
|
|
39
39
|
return {
|
|
40
40
|
ImportDeclaration: importDeclarationListener,
|
|
41
41
|
CallExpression(node) {
|
|
42
|
-
if (!
|
|
42
|
+
if (!detectZodSchemaRootNode(node)) {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
const methods = collectZodChainMethods(node);
|
|
@@ -32,11 +32,11 @@ export const noOptionalAndDefaultTogether = ESLintUtils.RuleCreator(getRuleURL)(
|
|
|
32
32
|
defaultOptions: [defaultOptions],
|
|
33
33
|
create(context, [{ preferredMethod }]) {
|
|
34
34
|
const { sourceCode } = context;
|
|
35
|
-
const { importDeclarationListener, detectZodSchemaRootNode
|
|
35
|
+
const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods, } = trackZodSchemaImports();
|
|
36
36
|
return {
|
|
37
37
|
ImportDeclaration: importDeclarationListener,
|
|
38
38
|
CallExpression(node) {
|
|
39
|
-
if (!
|
|
39
|
+
if (!detectZodSchemaRootNode(node)) {
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
const methods = collectZodChainMethods(node);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.preferStringSchemaWithTrim = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const meta_js_1 = require("../meta.cjs");
|
|
6
|
+
const track_zod_schema_imports_js_1 = require("../utils/track-zod-schema-imports.cjs");
|
|
7
|
+
exports.preferStringSchemaWithTrim = utils_1.ESLintUtils.RuleCreator(meta_js_1.getRuleURL)({
|
|
8
|
+
name: 'prefer-string-schema-with-trim',
|
|
9
|
+
meta: {
|
|
10
|
+
type: 'problem',
|
|
11
|
+
fixable: 'code',
|
|
12
|
+
docs: {
|
|
13
|
+
description: 'Enforce `z.string().trim()` to prevent accidental leading/trailing whitespace',
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
addTrim: '`z.string()` schemas should use `.trim()`.',
|
|
17
|
+
},
|
|
18
|
+
schema: [],
|
|
19
|
+
},
|
|
20
|
+
defaultOptions: [],
|
|
21
|
+
create(context) {
|
|
22
|
+
const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods, } = (0, track_zod_schema_imports_js_1.trackZodSchemaImports)();
|
|
23
|
+
return {
|
|
24
|
+
ImportDeclaration: importDeclarationListener,
|
|
25
|
+
CallExpression(node) {
|
|
26
|
+
const zodSchemaMeta = detectZodSchemaRootNode(node);
|
|
27
|
+
if ((zodSchemaMeta === null || zodSchemaMeta === void 0 ? void 0 : zodSchemaMeta.schemaType) !== 'string') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const methods = collectZodChainMethods(zodSchemaMeta.node);
|
|
31
|
+
if (methods.some((it) => it.name === 'trim')) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (zodSchemaMeta.schemaDecl === 'named') {
|
|
35
|
+
context.report({
|
|
36
|
+
node,
|
|
37
|
+
messageId: 'addTrim',
|
|
38
|
+
});
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
context.report({
|
|
42
|
+
node,
|
|
43
|
+
messageId: 'addTrim',
|
|
44
|
+
fix(fixer) {
|
|
45
|
+
const lastMethod = methods.at(0);
|
|
46
|
+
return fixer.insertTextAfter(lastMethod.node, '.trim()');
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getRuleURL } from "../meta.js";
|
|
3
|
+
import { trackZodSchemaImports } from "../utils/track-zod-schema-imports.js";
|
|
4
|
+
export const preferStringSchemaWithTrim = ESLintUtils.RuleCreator(getRuleURL)({
|
|
5
|
+
name: 'prefer-string-schema-with-trim',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
fixable: 'code',
|
|
9
|
+
docs: {
|
|
10
|
+
description: 'Enforce `z.string().trim()` to prevent accidental leading/trailing whitespace',
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
addTrim: '`z.string()` schemas should use `.trim()`.',
|
|
14
|
+
},
|
|
15
|
+
schema: [],
|
|
16
|
+
},
|
|
17
|
+
defaultOptions: [],
|
|
18
|
+
create(context) {
|
|
19
|
+
const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods, } = trackZodSchemaImports();
|
|
20
|
+
return {
|
|
21
|
+
ImportDeclaration: importDeclarationListener,
|
|
22
|
+
CallExpression(node) {
|
|
23
|
+
const zodSchemaMeta = detectZodSchemaRootNode(node);
|
|
24
|
+
if ((zodSchemaMeta === null || zodSchemaMeta === void 0 ? void 0 : zodSchemaMeta.schemaType) !== 'string') {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const methods = collectZodChainMethods(zodSchemaMeta.node);
|
|
28
|
+
if (methods.some((it) => it.name === 'trim')) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (zodSchemaMeta.schemaDecl === 'named') {
|
|
32
|
+
context.report({
|
|
33
|
+
node,
|
|
34
|
+
messageId: 'addTrim',
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
context.report({
|
|
39
|
+
node,
|
|
40
|
+
messageId: 'addTrim',
|
|
41
|
+
fix(fixer) {
|
|
42
|
+
const lastMethod = methods.at(0);
|
|
43
|
+
return fixer.insertTextAfter(lastMethod.node, '.trim()');
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
});
|
|
@@ -19,6 +19,13 @@ function buildZodChainReplacementFix(opts) {
|
|
|
19
19
|
const fullText = sourceCode.getText(m.node);
|
|
20
20
|
return fullText.slice(objText.length);
|
|
21
21
|
});
|
|
22
|
-
|
|
22
|
+
let replacement = `${prefixText}.${toMethodName}(`;
|
|
23
|
+
if (toNode.arguments.length) {
|
|
24
|
+
const argsText = toNode.arguments
|
|
25
|
+
.map((arg) => sourceCode.getText(arg))
|
|
26
|
+
.join(', ');
|
|
27
|
+
replacement += argsText;
|
|
28
|
+
}
|
|
29
|
+
replacement += `)${betweenSuffixes.join('')}`;
|
|
23
30
|
return fixer.replaceTextRange([fromNode.range[0], toNode.range[1]], replacement);
|
|
24
31
|
}
|
|
@@ -16,6 +16,13 @@ export function buildZodChainReplacementFix(opts) {
|
|
|
16
16
|
const fullText = sourceCode.getText(m.node);
|
|
17
17
|
return fullText.slice(objText.length);
|
|
18
18
|
});
|
|
19
|
-
|
|
19
|
+
let replacement = `${prefixText}.${toMethodName}(`;
|
|
20
|
+
if (toNode.arguments.length) {
|
|
21
|
+
const argsText = toNode.arguments
|
|
22
|
+
.map((arg) => sourceCode.getText(arg))
|
|
23
|
+
.join(', ');
|
|
24
|
+
replacement += argsText;
|
|
25
|
+
}
|
|
26
|
+
replacement += `)${betweenSuffixes.join('')}`;
|
|
20
27
|
return fixer.replaceTextRange([fromNode.range[0], toNode.range[1]], replacement);
|
|
21
28
|
}
|