eslint-plugin-zod 4.4.0 → 4.5.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
@@ -50,6 +50,7 @@ Find out more about [Oxlint's `jsPLugins`](https://oxc.rs/docs/guide/usage/linte
50
50
  | [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()`. | ✅ | 🔧 | | |
51
51
  | [no-number-schema-with-step](docs/rules/no-number-schema-with-step.md) | Disallow deprecated `z.number().step()`. Use `.multipleOf()` instead. | ✅ | 🔧 | | |
52
52
  | [no-optional-and-default-together](docs/rules/no-optional-and-default-together.md) | Disallow using both `.optional()` and `.default()` on the same Zod schema | ✅ | 🔧 | | |
53
+ | [no-promise-schema](docs/rules/no-promise-schema.md) | Disallow deprecated `z.promise()` schemas. | ✅ | | | |
53
54
  | [no-schema-with-is-nullable](docs/rules/no-schema-with-is-nullable.md) | Disallow deprecated `.isNullable()` on a Zod schema; use `safeParse(null).success` instead. | ✅ | | | |
54
55
  | [no-schema-with-is-optional](docs/rules/no-schema-with-is-optional.md) | Disallow deprecated `.isOptional()` on a Zod schema; use `safeParse(undefined).success` instead. | ✅ | | | |
55
56
  | [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 | ✅ | 🔧 | | ❌ |
package/dist/index.cjs CHANGED
@@ -15,6 +15,7 @@ const require_no_number_schema_with_is_int = require("./rules/no-number-schema-w
15
15
  const require_no_number_schema_with_safe = require("./rules/no-number-schema-with-safe.cjs");
16
16
  const require_no_number_schema_with_step = require("./rules/no-number-schema-with-step.cjs");
17
17
  const require_no_optional_and_default_together = require("./rules/no-optional-and-default-together.cjs");
18
+ const require_no_promise_schema = require("./rules/no-promise-schema.cjs");
18
19
  const require_no_schema_with_is_nullable = require("./rules/no-schema-with-is-nullable.cjs");
19
20
  const require_no_schema_with_is_optional = require("./rules/no-schema-with-is-optional.cjs");
20
21
  const require_no_string_schema_with_uuid = require("./rules/no-string-schema-with-uuid.cjs");
@@ -56,6 +57,7 @@ const eslintPluginZod = {
56
57
  "no-number-schema-with-step": require_no_number_schema_with_step.noNumberSchemaWithStep,
57
58
  "no-string-schema-with-uuid": require_no_string_schema_with_uuid.noStringSchemaWithUuid,
58
59
  "no-optional-and-default-together": require_no_optional_and_default_together.noOptionalAndDefaultTogether,
60
+ "no-promise-schema": require_no_promise_schema.noPromiseSchema,
59
61
  "no-schema-with-is-nullable": require_no_schema_with_is_nullable.noSchemaWithIsNullable,
60
62
  "no-schema-with-is-optional": require_no_schema_with_is_optional.noSchemaWithIsOptional,
61
63
  "no-throw-in-refine": require_no_throw_in_refine.noThrowInRefine,
@@ -93,6 +95,7 @@ const recommendedConfig = {
93
95
  "zod/no-number-schema-with-step": "error",
94
96
  "zod/no-string-schema-with-uuid": "error",
95
97
  "zod/no-optional-and-default-together": "error",
98
+ "zod/no-promise-schema": "error",
96
99
  "zod/no-schema-with-is-nullable": "error",
97
100
  "zod/no-schema-with-is-optional": "error",
98
101
  "zod/no-throw-in-refine": "error",
package/dist/index.mjs CHANGED
@@ -15,6 +15,7 @@ import { noNumberSchemaWithIsInt } from "./rules/no-number-schema-with-is-int.mj
15
15
  import { noNumberSchemaWithSafe } from "./rules/no-number-schema-with-safe.mjs";
16
16
  import { noNumberSchemaWithStep } from "./rules/no-number-schema-with-step.mjs";
17
17
  import { noOptionalAndDefaultTogether } from "./rules/no-optional-and-default-together.mjs";
18
+ import { noPromiseSchema } from "./rules/no-promise-schema.mjs";
18
19
  import { noSchemaWithIsNullable } from "./rules/no-schema-with-is-nullable.mjs";
19
20
  import { noSchemaWithIsOptional } from "./rules/no-schema-with-is-optional.mjs";
20
21
  import { noStringSchemaWithUuid } from "./rules/no-string-schema-with-uuid.mjs";
@@ -56,6 +57,7 @@ const eslintPluginZod = {
56
57
  "no-number-schema-with-step": noNumberSchemaWithStep,
57
58
  "no-string-schema-with-uuid": noStringSchemaWithUuid,
58
59
  "no-optional-and-default-together": noOptionalAndDefaultTogether,
60
+ "no-promise-schema": noPromiseSchema,
59
61
  "no-schema-with-is-nullable": noSchemaWithIsNullable,
60
62
  "no-schema-with-is-optional": noSchemaWithIsOptional,
61
63
  "no-throw-in-refine": noThrowInRefine,
@@ -93,6 +95,7 @@ const recommendedConfig = {
93
95
  "zod/no-number-schema-with-step": "error",
94
96
  "zod/no-string-schema-with-uuid": "error",
95
97
  "zod/no-optional-and-default-together": "error",
98
+ "zod/no-promise-schema": "error",
96
99
  "zod/no-schema-with-is-nullable": "error",
97
100
  "zod/no-schema-with-is-optional": "error",
98
101
  "zod/no-throw-in-refine": "error",
@@ -0,0 +1,30 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
3
+ let _eslint_zod_utils = require("@eslint-zod/utils");
4
+ //#region src/rules/no-promise-schema.ts
5
+ const { trackZodSchemaImports } = (0, _eslint_zod_utils.createZodSchemaImportTrack)(_eslint_zod_utils.zodImportScope);
6
+ const noPromiseSchema = require_create_plugin_rule.createZodPluginRule({
7
+ name: "no-promise-schema",
8
+ meta: {
9
+ type: "problem",
10
+ docs: { description: "Disallow deprecated `z.promise()` schemas." },
11
+ messages: { noPromiseSchema: "`z.promise()` is deprecated in Zod 4. Await the value before parsing it instead." },
12
+ schema: []
13
+ },
14
+ defaultOptions: [],
15
+ create(context) {
16
+ const { importDeclarationListener, detectZodSchemaRootNode } = trackZodSchemaImports();
17
+ return {
18
+ ImportDeclaration: importDeclarationListener,
19
+ CallExpression(node) {
20
+ if (detectZodSchemaRootNode(node)?.schemaType !== "promise") return;
21
+ context.report({
22
+ node,
23
+ messageId: "noPromiseSchema"
24
+ });
25
+ }
26
+ };
27
+ }
28
+ });
29
+ //#endregion
30
+ exports.noPromiseSchema = noPromiseSchema;
@@ -0,0 +1,29 @@
1
+ import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
+ import { createZodSchemaImportTrack, zodImportScope } from "@eslint-zod/utils";
3
+ //#region src/rules/no-promise-schema.ts
4
+ const { trackZodSchemaImports } = createZodSchemaImportTrack(zodImportScope);
5
+ const noPromiseSchema = createZodPluginRule({
6
+ name: "no-promise-schema",
7
+ meta: {
8
+ type: "problem",
9
+ docs: { description: "Disallow deprecated `z.promise()` schemas." },
10
+ messages: { noPromiseSchema: "`z.promise()` is deprecated in Zod 4. Await the value before parsing it instead." },
11
+ schema: []
12
+ },
13
+ defaultOptions: [],
14
+ create(context) {
15
+ const { importDeclarationListener, detectZodSchemaRootNode } = trackZodSchemaImports();
16
+ return {
17
+ ImportDeclaration: importDeclarationListener,
18
+ CallExpression(node) {
19
+ if (detectZodSchemaRootNode(node)?.schemaType !== "promise") return;
20
+ context.report({
21
+ node,
22
+ messageId: "noPromiseSchema"
23
+ });
24
+ }
25
+ };
26
+ }
27
+ });
28
+ //#endregion
29
+ export { noPromiseSchema };
@@ -1,9 +1,7 @@
1
1
  require("../_virtual/_rolldown/runtime.cjs");
2
2
  const require_create_plugin_rule = require("../utils/create-plugin-rule.cjs");
3
3
  let _eslint_zod_utils = require("@eslint-zod/utils");
4
- let _typescript_eslint_utils = require("@typescript-eslint/utils");
5
4
  //#region src/rules/prefer-enum-over-literal-union.ts
6
- const { trackZodSchemaImports } = (0, _eslint_zod_utils.createZodSchemaImportTrack)(_eslint_zod_utils.zodImportScope);
7
5
  const preferEnumOverLiteralUnion = require_create_plugin_rule.createZodPluginRule({
8
6
  name: "prefer-enum-over-literal-union",
9
7
  meta: {
@@ -14,42 +12,7 @@ const preferEnumOverLiteralUnion = require_create_plugin_rule.createZodPluginRul
14
12
  schema: []
15
13
  },
16
14
  defaultOptions: [],
17
- create(context) {
18
- const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
19
- return {
20
- ImportDeclaration: importDeclarationListener,
21
- CallExpression(node) {
22
- const zodSchemaMeta = detectZodSchemaRootNode(node);
23
- if (zodSchemaMeta?.schemaType !== "union") return;
24
- const union = collectZodChainMethods(zodSchemaMeta.node).find((it) => it.name === "union");
25
- if (!union) return;
26
- const unionNode = union.node;
27
- const unionArgument = unionNode.arguments.at(0);
28
- if (unionArgument?.type !== _typescript_eslint_utils.AST_NODE_TYPES.ArrayExpression) return;
29
- /**
30
- * Collect zod literals name that later can be used to implement the fix,
31
- * if the item isn't a literal schema return null
32
- */
33
- const zodLiteralStrings = unionArgument.elements.map((s) => {
34
- if (!s) return null;
35
- const maybeLiteralSchema = detectZodSchemaRootNode(s);
36
- if (maybeLiteralSchema?.schemaType !== "literal") return null;
37
- const [literalArgument] = maybeLiteralSchema.node.arguments;
38
- if (literalArgument.type === _typescript_eslint_utils.AST_NODE_TYPES.Literal && typeof literalArgument.value === "string") return literalArgument.raw;
39
- return null;
40
- });
41
- if (zodLiteralStrings.some((it) => it === null)) return;
42
- context.report({
43
- node,
44
- messageId: "useEnum",
45
- fix(fixer) {
46
- if (zodSchemaMeta.schemaDecl === "named") return null;
47
- return [fixer.replaceText(unionNode.callee.property, "enum"), fixer.replaceText(unionNode.arguments[0], `[${zodLiteralStrings.join(", ")}]`)];
48
- }
49
- });
50
- }
51
- };
52
- }
15
+ create: (0, _eslint_zod_utils.buildPreferEnumOverLiteralUnionCreate)(_eslint_zod_utils.zodImportScope)
53
16
  });
54
17
  //#endregion
55
18
  exports.preferEnumOverLiteralUnion = preferEnumOverLiteralUnion;
@@ -1,8 +1,6 @@
1
1
  import { createZodPluginRule } from "../utils/create-plugin-rule.mjs";
2
- import { createZodSchemaImportTrack, zodImportScope } from "@eslint-zod/utils";
3
- import { AST_NODE_TYPES } from "@typescript-eslint/utils";
2
+ import { buildPreferEnumOverLiteralUnionCreate, zodImportScope } from "@eslint-zod/utils";
4
3
  //#region src/rules/prefer-enum-over-literal-union.ts
5
- const { trackZodSchemaImports } = createZodSchemaImportTrack(zodImportScope);
6
4
  const preferEnumOverLiteralUnion = createZodPluginRule({
7
5
  name: "prefer-enum-over-literal-union",
8
6
  meta: {
@@ -13,42 +11,7 @@ const preferEnumOverLiteralUnion = createZodPluginRule({
13
11
  schema: []
14
12
  },
15
13
  defaultOptions: [],
16
- create(context) {
17
- const { importDeclarationListener, detectZodSchemaRootNode, collectZodChainMethods } = trackZodSchemaImports();
18
- return {
19
- ImportDeclaration: importDeclarationListener,
20
- CallExpression(node) {
21
- const zodSchemaMeta = detectZodSchemaRootNode(node);
22
- if (zodSchemaMeta?.schemaType !== "union") return;
23
- const union = collectZodChainMethods(zodSchemaMeta.node).find((it) => it.name === "union");
24
- if (!union) return;
25
- const unionNode = union.node;
26
- const unionArgument = unionNode.arguments.at(0);
27
- if (unionArgument?.type !== AST_NODE_TYPES.ArrayExpression) return;
28
- /**
29
- * Collect zod literals name that later can be used to implement the fix,
30
- * if the item isn't a literal schema return null
31
- */
32
- const zodLiteralStrings = unionArgument.elements.map((s) => {
33
- if (!s) return null;
34
- const maybeLiteralSchema = detectZodSchemaRootNode(s);
35
- if (maybeLiteralSchema?.schemaType !== "literal") return null;
36
- const [literalArgument] = maybeLiteralSchema.node.arguments;
37
- if (literalArgument.type === AST_NODE_TYPES.Literal && typeof literalArgument.value === "string") return literalArgument.raw;
38
- return null;
39
- });
40
- if (zodLiteralStrings.some((it) => it === null)) return;
41
- context.report({
42
- node,
43
- messageId: "useEnum",
44
- fix(fixer) {
45
- if (zodSchemaMeta.schemaDecl === "named") return null;
46
- return [fixer.replaceText(unionNode.callee.property, "enum"), fixer.replaceText(unionNode.arguments[0], `[${zodLiteralStrings.join(", ")}]`)];
47
- }
48
- });
49
- }
50
- };
51
- }
14
+ create: buildPreferEnumOverLiteralUnionCreate(zodImportScope)
52
15
  });
53
16
  //#endregion
54
17
  export { preferEnumOverLiteralUnion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-zod",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "ESLint plugin that adds custom linting rules to enforce best practices when using Zod",
5
5
  "keywords": [
6
6
  "eslint",
@@ -40,17 +40,17 @@
40
40
  "dependencies": {
41
41
  "@typescript-eslint/utils": "^8.57.0",
42
42
  "esquery": "^1.6.0",
43
- "@eslint-zod/utils": "1.2.0"
43
+ "@eslint-zod/utils": "1.3.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@marcalexiei/prettier-config": "2.0.0",
47
47
  "@types/esquery": "1.5.4",
48
- "@typescript-eslint/rule-tester": "8.59.2",
48
+ "@typescript-eslint/rule-tester": "8.59.3",
49
49
  "dedent": "1.7.2",
50
50
  "eslint-doc-generator": "3.3.2",
51
51
  "prettier": "3.8.3",
52
- "tsdown": "0.21.10",
53
- "vitest": "4.1.5"
52
+ "tsdown": "0.22.0",
53
+ "vitest": "4.1.6"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "eslint": "^9 || ^10",