eslint-plugin-zod-utils 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -49,7 +49,7 @@ Legacy eslintrc:
49
49
 
50
50
  ### `zod-utils/no-inline-zod-schema`
51
51
 
52
- Requires Zod schemas to be created as module-level variable declarations. This avoids recreating schemas inside functions, callbacks, render paths, hooks, or argument lists.
52
+ Requires Zod schemas to be created during module initialization. This avoids recreating schemas inside functions, callbacks, render paths, hooks, or instance fields.
53
53
 
54
54
  This rule was inspired by the motivation behind [`babel-plugin-zod-hoist`](https://github.com/gajus/babel-plugin-zod-hoist#motivation), which documents the cost of repeatedly initializing equivalent Zod schemas and the benefits of hoisting them.
55
55
 
@@ -70,10 +70,10 @@ function parseUser(input: unknown) {
70
70
  ```ts
71
71
  import { z } from "zod";
72
72
 
73
- app.post("/users", {
74
- body: z.object({
73
+ app.post("/users", (request) => {
74
+ return z.object({
75
75
  id: z.string(),
76
- }),
76
+ }).parse(request.body);
77
77
  });
78
78
  ```
79
79
 
@@ -91,6 +91,16 @@ function parseUser(input: unknown) {
91
91
  }
92
92
  ```
93
93
 
94
+ ```ts
95
+ import { z } from "zod";
96
+
97
+ app.post("/users", {
98
+ body: z.object({
99
+ id: z.string(),
100
+ }),
101
+ });
102
+ ```
103
+
94
104
  The rule understands `import { z } from "zod"`, `import * as zod from "zod"`, aliased `z` imports, and direct named schema factories such as `import { object, string } from "zod"`.
95
105
 
96
106
  ## Development
package/dist/index.cjs CHANGED
@@ -141,28 +141,6 @@ function isZodImportSpecifier(node) {
141
141
  const importedName = node.imported.type === "Identifier" ? node.imported.name : node.imported.value;
142
142
  return ZOD_NAMESPACE_IMPORTS.has(importedName) || ZOD_FACTORY_IMPORTS.has(importedName);
143
143
  }
144
- function unwrapExpression(node) {
145
- let current = node;
146
- while (current.parent?.type === "TSAsExpression" || current.parent?.type === "TSNonNullExpression" || current.parent?.type === "TSSatisfiesExpression" || current.parent?.type === "TSTypeAssertion") {
147
- current = current.parent;
148
- }
149
- return current;
150
- }
151
- function isModuleLevelVariableInitializer(node) {
152
- const expression = unwrapExpression(node);
153
- if (expression.parent?.type !== "VariableDeclarator") {
154
- return false;
155
- }
156
- if (expression.parent.init !== expression) {
157
- return false;
158
- }
159
- const declaration = expression.parent.parent;
160
- if (declaration.type !== "VariableDeclaration") {
161
- return false;
162
- }
163
- const container = declaration.parent;
164
- return container.type === "Program" || container.type === "ExportNamedDeclaration" && container.parent.type === "Program";
165
- }
166
144
  var noInlineZodSchema = import_utils.ESLintUtils.RuleCreator(
167
145
  (ruleName2) => `https://www.npmjs.com/package/eslint-plugin-zod-utils#${ruleName2}`
168
146
  )({
@@ -173,7 +151,7 @@ var noInlineZodSchema = import_utils.ESLintUtils.RuleCreator(
173
151
  description: "Disallow creating Zod schemas outside module scope."
174
152
  },
175
153
  messages: {
176
- inlineSchema: "Create Zod schemas at module scope instead of inline inside functions, callbacks, classes, or arguments."
154
+ inlineSchema: "Create Zod schemas during module initialization instead of inside functions, callbacks, or other repeated execution paths."
177
155
  },
178
156
  schema: []
179
157
  },
@@ -199,6 +177,19 @@ var noInlineZodSchema = import_utils.ESLintUtils.RuleCreator(
199
177
  }
200
178
  return false;
201
179
  }
180
+ function isInsideRepeatedExecutionPath(node) {
181
+ let current = node.parent;
182
+ while (current) {
183
+ if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
184
+ return true;
185
+ }
186
+ if (current.type === "PropertyDefinition" && !current.static) {
187
+ return true;
188
+ }
189
+ current = current.parent;
190
+ }
191
+ return false;
192
+ }
202
193
  return {
203
194
  CallExpression(node) {
204
195
  if (!isZodSchemaCall(node)) {
@@ -207,7 +198,7 @@ var noInlineZodSchema = import_utils.ESLintUtils.RuleCreator(
207
198
  if (hasZodCallAncestor(node)) {
208
199
  return;
209
200
  }
210
- if (isModuleLevelVariableInitializer(node)) {
201
+ if (!isInsideRepeatedExecutionPath(node)) {
211
202
  return;
212
203
  }
213
204
  context.report({
package/dist/index.js CHANGED
@@ -113,28 +113,6 @@ function isZodImportSpecifier(node) {
113
113
  const importedName = node.imported.type === "Identifier" ? node.imported.name : node.imported.value;
114
114
  return ZOD_NAMESPACE_IMPORTS.has(importedName) || ZOD_FACTORY_IMPORTS.has(importedName);
115
115
  }
116
- function unwrapExpression(node) {
117
- let current = node;
118
- while (current.parent?.type === "TSAsExpression" || current.parent?.type === "TSNonNullExpression" || current.parent?.type === "TSSatisfiesExpression" || current.parent?.type === "TSTypeAssertion") {
119
- current = current.parent;
120
- }
121
- return current;
122
- }
123
- function isModuleLevelVariableInitializer(node) {
124
- const expression = unwrapExpression(node);
125
- if (expression.parent?.type !== "VariableDeclarator") {
126
- return false;
127
- }
128
- if (expression.parent.init !== expression) {
129
- return false;
130
- }
131
- const declaration = expression.parent.parent;
132
- if (declaration.type !== "VariableDeclaration") {
133
- return false;
134
- }
135
- const container = declaration.parent;
136
- return container.type === "Program" || container.type === "ExportNamedDeclaration" && container.parent.type === "Program";
137
- }
138
116
  var noInlineZodSchema = ESLintUtils.RuleCreator(
139
117
  (ruleName2) => `https://www.npmjs.com/package/eslint-plugin-zod-utils#${ruleName2}`
140
118
  )({
@@ -145,7 +123,7 @@ var noInlineZodSchema = ESLintUtils.RuleCreator(
145
123
  description: "Disallow creating Zod schemas outside module scope."
146
124
  },
147
125
  messages: {
148
- inlineSchema: "Create Zod schemas at module scope instead of inline inside functions, callbacks, classes, or arguments."
126
+ inlineSchema: "Create Zod schemas during module initialization instead of inside functions, callbacks, or other repeated execution paths."
149
127
  },
150
128
  schema: []
151
129
  },
@@ -171,6 +149,19 @@ var noInlineZodSchema = ESLintUtils.RuleCreator(
171
149
  }
172
150
  return false;
173
151
  }
152
+ function isInsideRepeatedExecutionPath(node) {
153
+ let current = node.parent;
154
+ while (current) {
155
+ if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
156
+ return true;
157
+ }
158
+ if (current.type === "PropertyDefinition" && !current.static) {
159
+ return true;
160
+ }
161
+ current = current.parent;
162
+ }
163
+ return false;
164
+ }
174
165
  return {
175
166
  CallExpression(node) {
176
167
  if (!isZodSchemaCall(node)) {
@@ -179,7 +170,7 @@ var noInlineZodSchema = ESLintUtils.RuleCreator(
179
170
  if (hasZodCallAncestor(node)) {
180
171
  return;
181
172
  }
182
- if (isModuleLevelVariableInitializer(node)) {
173
+ if (!isInsideRepeatedExecutionPath(node)) {
183
174
  return;
184
175
  }
185
176
  context.report({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-zod-utils",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "ESLint utilities for safer Zod schema usage.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",