eslint-plugin-zod-utils 1.0.0 → 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 +16 -4
- package/dist/index.cjs +15 -24
- package/dist/index.js +15 -24
- package/package.json +1 -1
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
|
|
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,9 +70,11 @@ function parseUser(input: unknown) {
|
|
|
70
70
|
```ts
|
|
71
71
|
import { z } from "zod";
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
app.post("/users", (request) => {
|
|
74
|
+
return z.object({
|
|
75
|
+
id: z.string(),
|
|
76
|
+
}).parse(request.body);
|
|
77
|
+
});
|
|
76
78
|
```
|
|
77
79
|
|
|
78
80
|
Valid:
|
|
@@ -89,6 +91,16 @@ function parseUser(input: unknown) {
|
|
|
89
91
|
}
|
|
90
92
|
```
|
|
91
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
|
+
|
|
92
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"`.
|
|
93
105
|
|
|
94
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
|
|
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 (
|
|
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
|
|
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 (
|
|
173
|
+
if (!isInsideRepeatedExecutionPath(node)) {
|
|
183
174
|
return;
|
|
184
175
|
}
|
|
185
176
|
context.report({
|