eslint-plugin-zod 3.5.1 → 3.5.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/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/index.cjs +94 -83
- package/dist/index.d.cts +17 -16
- package/dist/index.d.mts +24 -0
- package/dist/index.mjs +98 -0
- package/dist/meta.cjs +11 -11
- package/dist/meta.mjs +10 -0
- package/dist/rules/array-style.cjs +88 -101
- package/dist/rules/array-style.mjs +89 -0
- package/dist/rules/consistent-import-source.cjs +59 -66
- package/dist/rules/consistent-import-source.mjs +60 -0
- package/dist/rules/consistent-import.cjs +146 -172
- package/dist/rules/consistent-import.mjs +152 -0
- package/dist/rules/consistent-object-schema-type.cjs +81 -84
- package/dist/rules/consistent-object-schema-type.mjs +81 -0
- package/dist/rules/no-any-schema.cjs +62 -67
- package/dist/rules/no-any-schema.mjs +62 -0
- package/dist/rules/no-empty-custom-schema.cjs +32 -40
- package/dist/rules/no-empty-custom-schema.mjs +34 -0
- package/dist/rules/no-number-schema-with-int.cjs +56 -62
- package/dist/rules/no-number-schema-with-int.mjs +57 -0
- package/dist/rules/no-optional-and-default-together.cjs +69 -80
- package/dist/rules/no-optional-and-default-together.mjs +71 -0
- package/dist/rules/no-string-schema-with-uuid.cjs +57 -63
- package/dist/rules/no-string-schema-with-uuid.mjs +58 -0
- package/dist/rules/no-throw-in-refine.cjs +69 -87
- package/dist/rules/no-throw-in-refine.mjs +69 -0
- package/dist/rules/no-unknown-schema.cjs +29 -35
- package/dist/rules/no-unknown-schema.mjs +31 -0
- package/dist/rules/prefer-enum-over-literal-union.cjs +63 -79
- package/dist/rules/prefer-enum-over-literal-union.mjs +63 -0
- package/dist/rules/prefer-meta-last.cjs +47 -63
- package/dist/rules/prefer-meta-last.mjs +49 -0
- package/dist/rules/prefer-meta.cjs +38 -48
- package/dist/rules/prefer-meta.mjs +40 -0
- package/dist/rules/prefer-namespace-import.cjs +110 -142
- package/dist/rules/prefer-namespace-import.mjs +116 -0
- package/dist/rules/prefer-string-schema-with-trim.cjs +45 -52
- package/dist/rules/prefer-string-schema-with-trim.mjs +47 -0
- package/dist/rules/require-brand-type-parameter.cjs +47 -60
- package/dist/rules/require-brand-type-parameter.mjs +49 -0
- package/dist/rules/require-error-message.cjs +83 -102
- package/dist/rules/require-error-message.mjs +83 -0
- package/dist/rules/require-schema-suffix.cjs +67 -78
- package/dist/rules/require-schema-suffix.mjs +67 -0
- package/dist/rules/schema-error-property-style.cjs +95 -107
- package/dist/rules/schema-error-property-style.mjs +94 -0
- package/dist/utils/build-zod-chain-replacement-fix.cjs +28 -29
- package/dist/utils/build-zod-chain-replacement-fix.mjs +30 -0
- package/dist/utils/create-plugin-rule.cjs +6 -6
- package/dist/utils/create-plugin-rule.mjs +6 -0
- package/dist/utils/detect-zod-schema-root-node.cjs +94 -96
- package/dist/utils/detect-zod-schema-root-node.mjs +101 -0
- package/dist/utils/is-zod-import-source.cjs +14 -18
- package/dist/utils/is-zod-import-source.mjs +16 -0
- package/dist/utils/track-zod-schema-imports.cjs +61 -63
- package/dist/utils/track-zod-schema-imports.mjs +64 -0
- package/package.json +14 -17
- package/dist/index.d.ts +0 -22
- package/dist/index.js +0 -84
- package/dist/meta.d.cts +0 -3
- package/dist/meta.d.ts +0 -3
- package/dist/meta.js +0 -8
- package/dist/rules/array-style.d.cts +0 -11
- package/dist/rules/array-style.d.ts +0 -11
- package/dist/rules/array-style.js +0 -99
- package/dist/rules/consistent-import-source.d.cts +0 -11
- package/dist/rules/consistent-import-source.d.ts +0 -11
- package/dist/rules/consistent-import-source.js +0 -64
- package/dist/rules/consistent-import.d.cts +0 -12
- package/dist/rules/consistent-import.d.ts +0 -12
- package/dist/rules/consistent-import.js +0 -176
- package/dist/rules/consistent-object-schema-type.d.cts +0 -13
- package/dist/rules/consistent-object-schema-type.d.ts +0 -13
- package/dist/rules/consistent-object-schema-type.js +0 -82
- package/dist/rules/no-any-schema.d.cts +0 -6
- package/dist/rules/no-any-schema.d.ts +0 -6
- package/dist/rules/no-any-schema.js +0 -65
- package/dist/rules/no-empty-custom-schema.d.cts +0 -5
- package/dist/rules/no-empty-custom-schema.d.ts +0 -5
- package/dist/rules/no-empty-custom-schema.js +0 -38
- package/dist/rules/no-number-schema-with-int.d.cts +0 -5
- package/dist/rules/no-number-schema-with-int.d.ts +0 -5
- package/dist/rules/no-number-schema-with-int.js +0 -60
- package/dist/rules/no-optional-and-default-together.d.cts +0 -12
- package/dist/rules/no-optional-and-default-together.d.ts +0 -12
- package/dist/rules/no-optional-and-default-together.js +0 -78
- package/dist/rules/no-string-schema-with-uuid.d.cts +0 -5
- package/dist/rules/no-string-schema-with-uuid.d.ts +0 -5
- package/dist/rules/no-string-schema-with-uuid.js +0 -61
- package/dist/rules/no-throw-in-refine.d.cts +0 -5
- package/dist/rules/no-throw-in-refine.d.ts +0 -5
- package/dist/rules/no-throw-in-refine.js +0 -85
- package/dist/rules/no-unknown-schema.d.cts +0 -5
- package/dist/rules/no-unknown-schema.d.ts +0 -5
- package/dist/rules/no-unknown-schema.js +0 -33
- package/dist/rules/prefer-enum-over-literal-union.d.cts +0 -5
- package/dist/rules/prefer-enum-over-literal-union.d.ts +0 -5
- package/dist/rules/prefer-enum-over-literal-union.js +0 -77
- package/dist/rules/prefer-meta-last.d.cts +0 -5
- package/dist/rules/prefer-meta-last.d.ts +0 -5
- package/dist/rules/prefer-meta-last.js +0 -61
- package/dist/rules/prefer-meta.d.cts +0 -5
- package/dist/rules/prefer-meta.d.ts +0 -5
- package/dist/rules/prefer-meta.js +0 -46
- package/dist/rules/prefer-namespace-import.d.cts +0 -5
- package/dist/rules/prefer-namespace-import.d.ts +0 -5
- package/dist/rules/prefer-namespace-import.js +0 -146
- package/dist/rules/prefer-string-schema-with-trim.d.cts +0 -5
- package/dist/rules/prefer-string-schema-with-trim.d.ts +0 -5
- package/dist/rules/prefer-string-schema-with-trim.js +0 -50
- package/dist/rules/require-brand-type-parameter.d.cts +0 -6
- package/dist/rules/require-brand-type-parameter.d.ts +0 -6
- package/dist/rules/require-brand-type-parameter.js +0 -58
- package/dist/rules/require-error-message.d.cts +0 -5
- package/dist/rules/require-error-message.d.ts +0 -5
- package/dist/rules/require-error-message.js +0 -100
- package/dist/rules/require-schema-suffix.d.cts +0 -9
- package/dist/rules/require-schema-suffix.d.ts +0 -9
- package/dist/rules/require-schema-suffix.js +0 -76
- package/dist/rules/schema-error-property-style.d.cts +0 -10
- package/dist/rules/schema-error-property-style.d.ts +0 -10
- package/dist/rules/schema-error-property-style.js +0 -102
- package/dist/utils/build-zod-chain-replacement-fix.d.cts +0 -12
- package/dist/utils/build-zod-chain-replacement-fix.d.ts +0 -12
- package/dist/utils/build-zod-chain-replacement-fix.js +0 -28
- package/dist/utils/create-plugin-rule.d.cts +0 -13
- package/dist/utils/create-plugin-rule.d.ts +0 -13
- package/dist/utils/create-plugin-rule.js +0 -3
- package/dist/utils/detect-zod-schema-root-node.d.cts +0 -10
- package/dist/utils/detect-zod-schema-root-node.d.ts +0 -10
- package/dist/utils/detect-zod-schema-root-node.js +0 -101
- package/dist/utils/is-zod-import-source.d.cts +0 -4
- package/dist/utils/is-zod-import-source.d.ts +0 -4
- package/dist/utils/is-zod-import-source.js +0 -17
- package/dist/utils/track-zod-schema-imports.d.cts +0 -18
- package/dist/utils/track-zod-schema-imports.d.ts +0 -18
- package/dist/utils/track-zod-schema-imports.js +0 -64
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
//#region src/utils/build-zod-chain-replacement-fix.ts
|
|
2
|
+
/**
|
|
3
|
+
* Utility to generate a fixer for replacing a method chain like z.string().uuid() or z.number().int()
|
|
4
|
+
* with z.uuid() or z.int(), preserving any intermediate methods.
|
|
5
|
+
*
|
|
6
|
+
* @param opts Object containing all options for the fixer
|
|
7
|
+
* @returns Fixer replaceTextRange call
|
|
8
|
+
*/
|
|
4
9
|
function buildZodChainReplacementFix(opts) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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('')}`;
|
|
30
|
-
return fixer.replaceTextRange([fromNode.range[0], toNode.range[1]], replacement);
|
|
10
|
+
const { sourceCode, fixer, methods, fromIndex, toIndex, toMethodName } = opts;
|
|
11
|
+
const fromNode = methods[fromIndex]?.node;
|
|
12
|
+
const toNode = methods[toIndex]?.node;
|
|
13
|
+
if (!fromNode || !toNode) return null;
|
|
14
|
+
const prefixObj = fromNode.callee.object;
|
|
15
|
+
const prefixText = sourceCode.getText(prefixObj);
|
|
16
|
+
const betweenSuffixes = methods.slice(fromIndex + 1, toIndex).map((m) => {
|
|
17
|
+
const betweenCallee = m.node.callee;
|
|
18
|
+
const objText = sourceCode.getText(betweenCallee.object);
|
|
19
|
+
return sourceCode.getText(m.node).slice(objText.length);
|
|
20
|
+
});
|
|
21
|
+
let replacement = `${prefixText}.${toMethodName}(`;
|
|
22
|
+
if (toNode.arguments.length) {
|
|
23
|
+
const argsText = toNode.arguments.map((arg) => sourceCode.getText(arg)).join(", ");
|
|
24
|
+
replacement += argsText;
|
|
25
|
+
}
|
|
26
|
+
replacement += `)${betweenSuffixes.join("")}`;
|
|
27
|
+
return fixer.replaceTextRange([fromNode.range[0], toNode.range[1]], replacement);
|
|
31
28
|
}
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.buildZodChainReplacementFix = buildZodChainReplacementFix;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/utils/build-zod-chain-replacement-fix.ts
|
|
2
|
+
/**
|
|
3
|
+
* Utility to generate a fixer for replacing a method chain like z.string().uuid() or z.number().int()
|
|
4
|
+
* with z.uuid() or z.int(), preserving any intermediate methods.
|
|
5
|
+
*
|
|
6
|
+
* @param opts Object containing all options for the fixer
|
|
7
|
+
* @returns Fixer replaceTextRange call
|
|
8
|
+
*/
|
|
9
|
+
function buildZodChainReplacementFix(opts) {
|
|
10
|
+
const { sourceCode, fixer, methods, fromIndex, toIndex, toMethodName } = opts;
|
|
11
|
+
const fromNode = methods[fromIndex]?.node;
|
|
12
|
+
const toNode = methods[toIndex]?.node;
|
|
13
|
+
if (!fromNode || !toNode) return null;
|
|
14
|
+
const prefixObj = fromNode.callee.object;
|
|
15
|
+
const prefixText = sourceCode.getText(prefixObj);
|
|
16
|
+
const betweenSuffixes = methods.slice(fromIndex + 1, toIndex).map((m) => {
|
|
17
|
+
const betweenCallee = m.node.callee;
|
|
18
|
+
const objText = sourceCode.getText(betweenCallee.object);
|
|
19
|
+
return sourceCode.getText(m.node).slice(objText.length);
|
|
20
|
+
});
|
|
21
|
+
let replacement = `${prefixText}.${toMethodName}(`;
|
|
22
|
+
if (toNode.arguments.length) {
|
|
23
|
+
const argsText = toNode.arguments.map((arg) => sourceCode.getText(arg)).join(", ");
|
|
24
|
+
replacement += argsText;
|
|
25
|
+
}
|
|
26
|
+
replacement += `)${betweenSuffixes.join("")}`;
|
|
27
|
+
return fixer.replaceTextRange([fromNode.range[0], toNode.range[1]], replacement);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { buildZodChainReplacementFix };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
exports.createZodPluginRule =
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_meta = require("../meta.cjs");
|
|
3
|
+
//#region src/utils/create-plugin-rule.ts
|
|
4
|
+
const createZodPluginRule = require("@typescript-eslint/utils").ESLintUtils.RuleCreator(require_meta.getRuleURL);
|
|
5
|
+
//#endregion
|
|
6
|
+
exports.createZodPluginRule = createZodPluginRule;
|
|
@@ -1,104 +1,102 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let _typescript_eslint_utils = require("@typescript-eslint/utils");
|
|
3
|
+
//#region src/utils/detect-zod-schema-root-node.ts
|
|
4
|
+
/**
|
|
5
|
+
* Helper: extract static property names (Identifier | Literal | simple template literal)
|
|
6
|
+
*/
|
|
5
7
|
function getPropertyName(prop) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
if (prop.type === utils_1.AST_NODE_TYPES.TemplateLiteral) {
|
|
16
|
-
if (prop.expressions.length === 0 && prop.quasis.length === 1) {
|
|
17
|
-
return prop.quasis[0].value.cooked;
|
|
18
|
-
}
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
return null;
|
|
8
|
+
if (!prop) return null;
|
|
9
|
+
if (prop.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) return prop.name;
|
|
10
|
+
if (prop.type === _typescript_eslint_utils.AST_NODE_TYPES.Literal) return prop.value == null ? null : String(prop.value);
|
|
11
|
+
if (prop.type === _typescript_eslint_utils.AST_NODE_TYPES.TemplateLiteral) {
|
|
12
|
+
if (prop.expressions.length === 0 && prop.quasis.length === 1) return prop.quasis[0].value.cooked;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
22
16
|
}
|
|
17
|
+
/** Quick check: only process outermost call in a chain */
|
|
23
18
|
function isOutermostCallExpression(node) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (parent.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
29
|
-
parent.object === node) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
return true;
|
|
19
|
+
const { parent } = node;
|
|
20
|
+
if (parent.type === _typescript_eslint_utils.AST_NODE_TYPES.CallExpression && parent.callee === node) return false;
|
|
21
|
+
if (parent.type === _typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && parent.object === node) return false;
|
|
22
|
+
return true;
|
|
33
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Parse a CallExpression to detect whether it's a zod schema expression (namespace or named).
|
|
26
|
+
* This helper DOES NOT require the call to be outermost.
|
|
27
|
+
*
|
|
28
|
+
* Returns:
|
|
29
|
+
* { schemaDecl, schemaType, methods, node } if successful
|
|
30
|
+
* null otherwise
|
|
31
|
+
*/
|
|
34
32
|
function parseZodCallExpression(call, zodNamespaces, zodNamedImports) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (zodNamedImports.has(leftmostIdentifier)) {
|
|
76
|
-
const factory = leftmostIdentifier;
|
|
77
|
-
return {
|
|
78
|
-
schemaDecl: 'named',
|
|
79
|
-
schemaType: factory,
|
|
80
|
-
methods,
|
|
81
|
-
node: call,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return null;
|
|
33
|
+
let cur = call.callee;
|
|
34
|
+
const methodsRightToLeft = [];
|
|
35
|
+
let leftmostIdentifier = null;
|
|
36
|
+
while (true) {
|
|
37
|
+
if (cur.type === _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) {
|
|
38
|
+
cur = cur.callee;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (cur.type === _typescript_eslint_utils.AST_NODE_TYPES.MemberExpression) {
|
|
42
|
+
const name = getPropertyName(cur.property);
|
|
43
|
+
if (!name) return null;
|
|
44
|
+
methodsRightToLeft.push(name);
|
|
45
|
+
cur = cur.object;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (cur.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) {
|
|
49
|
+
leftmostIdentifier = cur.name;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const methods = methodsRightToLeft.slice().reverse();
|
|
55
|
+
if (!leftmostIdentifier) return null;
|
|
56
|
+
if (zodNamespaces.has(leftmostIdentifier)) {
|
|
57
|
+
const factory = methods[0] ?? null;
|
|
58
|
+
if (!factory) return null;
|
|
59
|
+
return {
|
|
60
|
+
schemaDecl: "namespace",
|
|
61
|
+
schemaType: factory,
|
|
62
|
+
methods,
|
|
63
|
+
node: call
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (zodNamedImports.has(leftmostIdentifier)) return {
|
|
67
|
+
schemaDecl: "named",
|
|
68
|
+
schemaType: leftmostIdentifier,
|
|
69
|
+
methods,
|
|
70
|
+
node: call
|
|
71
|
+
};
|
|
72
|
+
return null;
|
|
85
73
|
}
|
|
74
|
+
/** Examine an expression (argument) for zod schema CallExpressions.
|
|
75
|
+
* Supports:
|
|
76
|
+
* - direct CallExpression (string(), z.string(), etc)
|
|
77
|
+
* - ArrayExpression where elements may be CallExpressions (e.g. union([a(), b()]))
|
|
78
|
+
*
|
|
79
|
+
* Returns list of parsed inner schema infos (may be empty).
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* The final exported function.
|
|
83
|
+
*
|
|
84
|
+
* node: CallExpression node given by ESLint visitor
|
|
85
|
+
* zodNamespaces: e.g. new Set(['z'])
|
|
86
|
+
* zodNamedImports: e.g. new Set(['number','string','array',...])
|
|
87
|
+
*/
|
|
86
88
|
function detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
schemaDecl: outer.schemaDecl,
|
|
100
|
-
schemaType: outer.schemaType,
|
|
101
|
-
methods: outer.methods,
|
|
102
|
-
node: call,
|
|
103
|
-
};
|
|
89
|
+
if (node.type !== _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) return null;
|
|
90
|
+
const call = node;
|
|
91
|
+
if (!isOutermostCallExpression(call)) return null;
|
|
92
|
+
const outer = parseZodCallExpression(call, zodNamespaces, zodNamedImports);
|
|
93
|
+
if (!outer) return null;
|
|
94
|
+
return {
|
|
95
|
+
schemaDecl: outer.schemaDecl,
|
|
96
|
+
schemaType: outer.schemaType,
|
|
97
|
+
methods: outer.methods,
|
|
98
|
+
node: call
|
|
99
|
+
};
|
|
104
100
|
}
|
|
101
|
+
//#endregion
|
|
102
|
+
exports.detectZodSchemaRootNode = detectZodSchemaRootNode;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from "@typescript-eslint/utils";
|
|
2
|
+
//#region src/utils/detect-zod-schema-root-node.ts
|
|
3
|
+
/**
|
|
4
|
+
* Helper: extract static property names (Identifier | Literal | simple template literal)
|
|
5
|
+
*/
|
|
6
|
+
function getPropertyName(prop) {
|
|
7
|
+
if (!prop) return null;
|
|
8
|
+
if (prop.type === AST_NODE_TYPES.Identifier) return prop.name;
|
|
9
|
+
if (prop.type === AST_NODE_TYPES.Literal) return prop.value == null ? null : String(prop.value);
|
|
10
|
+
if (prop.type === AST_NODE_TYPES.TemplateLiteral) {
|
|
11
|
+
if (prop.expressions.length === 0 && prop.quasis.length === 1) return prop.quasis[0].value.cooked;
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
/** Quick check: only process outermost call in a chain */
|
|
17
|
+
function isOutermostCallExpression(node) {
|
|
18
|
+
const { parent } = node;
|
|
19
|
+
if (parent.type === AST_NODE_TYPES.CallExpression && parent.callee === node) return false;
|
|
20
|
+
if (parent.type === AST_NODE_TYPES.MemberExpression && parent.object === node) return false;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse a CallExpression to detect whether it's a zod schema expression (namespace or named).
|
|
25
|
+
* This helper DOES NOT require the call to be outermost.
|
|
26
|
+
*
|
|
27
|
+
* Returns:
|
|
28
|
+
* { schemaDecl, schemaType, methods, node } if successful
|
|
29
|
+
* null otherwise
|
|
30
|
+
*/
|
|
31
|
+
function parseZodCallExpression(call, zodNamespaces, zodNamedImports) {
|
|
32
|
+
let cur = call.callee;
|
|
33
|
+
const methodsRightToLeft = [];
|
|
34
|
+
let leftmostIdentifier = null;
|
|
35
|
+
while (true) {
|
|
36
|
+
if (cur.type === AST_NODE_TYPES.CallExpression) {
|
|
37
|
+
cur = cur.callee;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (cur.type === AST_NODE_TYPES.MemberExpression) {
|
|
41
|
+
const name = getPropertyName(cur.property);
|
|
42
|
+
if (!name) return null;
|
|
43
|
+
methodsRightToLeft.push(name);
|
|
44
|
+
cur = cur.object;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (cur.type === AST_NODE_TYPES.Identifier) {
|
|
48
|
+
leftmostIdentifier = cur.name;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const methods = methodsRightToLeft.slice().reverse();
|
|
54
|
+
if (!leftmostIdentifier) return null;
|
|
55
|
+
if (zodNamespaces.has(leftmostIdentifier)) {
|
|
56
|
+
const factory = methods[0] ?? null;
|
|
57
|
+
if (!factory) return null;
|
|
58
|
+
return {
|
|
59
|
+
schemaDecl: "namespace",
|
|
60
|
+
schemaType: factory,
|
|
61
|
+
methods,
|
|
62
|
+
node: call
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (zodNamedImports.has(leftmostIdentifier)) return {
|
|
66
|
+
schemaDecl: "named",
|
|
67
|
+
schemaType: leftmostIdentifier,
|
|
68
|
+
methods,
|
|
69
|
+
node: call
|
|
70
|
+
};
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/** Examine an expression (argument) for zod schema CallExpressions.
|
|
74
|
+
* Supports:
|
|
75
|
+
* - direct CallExpression (string(), z.string(), etc)
|
|
76
|
+
* - ArrayExpression where elements may be CallExpressions (e.g. union([a(), b()]))
|
|
77
|
+
*
|
|
78
|
+
* Returns list of parsed inner schema infos (may be empty).
|
|
79
|
+
*/
|
|
80
|
+
/**
|
|
81
|
+
* The final exported function.
|
|
82
|
+
*
|
|
83
|
+
* node: CallExpression node given by ESLint visitor
|
|
84
|
+
* zodNamespaces: e.g. new Set(['z'])
|
|
85
|
+
* zodNamedImports: e.g. new Set(['number','string','array',...])
|
|
86
|
+
*/
|
|
87
|
+
function detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports) {
|
|
88
|
+
if (node.type !== AST_NODE_TYPES.CallExpression) return null;
|
|
89
|
+
const call = node;
|
|
90
|
+
if (!isOutermostCallExpression(call)) return null;
|
|
91
|
+
const outer = parseZodCallExpression(call, zodNamespaces, zodNamedImports);
|
|
92
|
+
if (!outer) return null;
|
|
93
|
+
return {
|
|
94
|
+
schemaDecl: outer.schemaDecl,
|
|
95
|
+
schemaType: outer.schemaType,
|
|
96
|
+
methods: outer.methods,
|
|
97
|
+
node: call
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
export { detectZodSchemaRootNode };
|
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
'zod/v4',
|
|
9
|
-
'zod/v4-mini',
|
|
10
|
-
'zod/v3',
|
|
1
|
+
//#region src/utils/is-zod-import-source.ts
|
|
2
|
+
const ZOD_IMPORT_SOURCES = [
|
|
3
|
+
"zod",
|
|
4
|
+
"zod/mini",
|
|
5
|
+
"zod/v4",
|
|
6
|
+
"zod/v4-mini",
|
|
7
|
+
"zod/v3"
|
|
11
8
|
];
|
|
12
9
|
function isZodImportSource(source, allowedSource) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (allowedSource === 'all' || allowedSource === 'zod-mini') {
|
|
18
|
-
allowedSources.push('zod/mini', 'zod/v4-mini');
|
|
19
|
-
}
|
|
20
|
-
return allowedSources.includes(source);
|
|
10
|
+
const allowedSources = [];
|
|
11
|
+
if (allowedSource === "all" || allowedSource === "zod") allowedSources.push("zod", "zod/v4", "zod/v3");
|
|
12
|
+
if (allowedSource === "all" || allowedSource === "zod-mini") allowedSources.push("zod/mini", "zod/v4-mini");
|
|
13
|
+
return allowedSources.includes(source);
|
|
21
14
|
}
|
|
15
|
+
//#endregion
|
|
16
|
+
exports.ZOD_IMPORT_SOURCES = ZOD_IMPORT_SOURCES;
|
|
17
|
+
exports.isZodImportSource = isZodImportSource;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/utils/is-zod-import-source.ts
|
|
2
|
+
const ZOD_IMPORT_SOURCES = [
|
|
3
|
+
"zod",
|
|
4
|
+
"zod/mini",
|
|
5
|
+
"zod/v4",
|
|
6
|
+
"zod/v4-mini",
|
|
7
|
+
"zod/v3"
|
|
8
|
+
];
|
|
9
|
+
function isZodImportSource(source, allowedSource) {
|
|
10
|
+
const allowedSources = [];
|
|
11
|
+
if (allowedSource === "all" || allowedSource === "zod") allowedSources.push("zod", "zod/v4", "zod/v3");
|
|
12
|
+
if (allowedSource === "all" || allowedSource === "zod-mini") allowedSources.push("zod/mini", "zod/v4-mini");
|
|
13
|
+
return allowedSources.includes(source);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ZOD_IMPORT_SOURCES, isZodImportSource };
|
|
@@ -1,67 +1,65 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_detect_zod_schema_root_node = require("./detect-zod-schema-root-node.cjs");
|
|
3
|
+
const require_is_zod_import_source = require("./is-zod-import-source.cjs");
|
|
4
|
+
let _typescript_eslint_utils = require("@typescript-eslint/utils");
|
|
5
|
+
//#region src/utils/track-zod-schema-imports.ts
|
|
6
|
+
/**
|
|
7
|
+
* Function to create helpers that allow to manage default, namespace and named `zod`
|
|
8
|
+
* imports without too much hassle.
|
|
9
|
+
*/
|
|
7
10
|
function trackZodSchemaImports(importAllowedSource) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
zodNamedImports.add(spec.local.name);
|
|
52
|
-
}
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
detectZodSchemaRootNode: (node) => (0, detect_zod_schema_root_node_js_1.detectZodSchemaRootNode)(node, zodNamespaces, zodNamedImports),
|
|
58
|
-
collectZodChainMethods,
|
|
59
|
-
};
|
|
60
|
-
return result;
|
|
11
|
+
const zodNamespaces = /* @__PURE__ */ new Set();
|
|
12
|
+
const zodNamedImports = /* @__PURE__ */ new Set();
|
|
13
|
+
function collectZodChainMethods(node) {
|
|
14
|
+
const methods = [];
|
|
15
|
+
let current = node;
|
|
16
|
+
while (current.type === _typescript_eslint_utils.AST_NODE_TYPES.CallExpression) {
|
|
17
|
+
const { callee } = current;
|
|
18
|
+
if (callee.type === _typescript_eslint_utils.AST_NODE_TYPES.MemberExpression && callee.property.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) {
|
|
19
|
+
methods.unshift({
|
|
20
|
+
name: callee.property.name,
|
|
21
|
+
node: current
|
|
22
|
+
});
|
|
23
|
+
current = callee.object;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (callee.type === _typescript_eslint_utils.AST_NODE_TYPES.Identifier) {
|
|
27
|
+
methods.unshift({
|
|
28
|
+
name: callee.name,
|
|
29
|
+
node: current
|
|
30
|
+
});
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
return methods;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
importDeclarationListener(node) {
|
|
39
|
+
if (!require_is_zod_import_source.isZodImportSource(node.source.value, importAllowedSource)) return;
|
|
40
|
+
for (const spec of node.specifiers) switch (spec.type) {
|
|
41
|
+
case _typescript_eslint_utils.AST_NODE_TYPES.ImportDefaultSpecifier:
|
|
42
|
+
case _typescript_eslint_utils.AST_NODE_TYPES.ImportNamespaceSpecifier:
|
|
43
|
+
zodNamespaces.add(spec.local.name);
|
|
44
|
+
break;
|
|
45
|
+
case _typescript_eslint_utils.AST_NODE_TYPES.ImportSpecifier:
|
|
46
|
+
if ("name" in spec.imported && spec.imported.name === "z") zodNamespaces.add(spec.local.name);
|
|
47
|
+
else zodNamedImports.add(spec.local.name);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
detectZodSchemaRootNode: (node) => require_detect_zod_schema_root_node.detectZodSchemaRootNode(node, zodNamespaces, zodNamedImports),
|
|
52
|
+
collectZodChainMethods
|
|
53
|
+
};
|
|
61
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Wrapper to avoid duplication of importAllowedSource across rule code
|
|
57
|
+
*/
|
|
62
58
|
function createZodSchemaImportTrack(zodImportAllowedSource) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
return {
|
|
60
|
+
zodImportAllowedSource,
|
|
61
|
+
trackZodSchemaImports: () => trackZodSchemaImports(zodImportAllowedSource)
|
|
62
|
+
};
|
|
67
63
|
}
|
|
64
|
+
//#endregion
|
|
65
|
+
exports.createZodSchemaImportTrack = createZodSchemaImportTrack;
|