@longzai-intelligence-oxlint/zod-plugin 0.1.12 → 0.1.14
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/index.js +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";function n(e){return e.callee?.type===`MemberExpression`&&r(e.callee)}function r(e){return e.object?.type===`Identifier`&&e.object.name===`z`&&e.property?.type===`Identifier`}function i(e){if(e.callee?.type!==`MemberExpression`)return!1;let t=e.callee.object;for(;t.type===`CallExpression`;){if(n(t))return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return t.type===`Identifier`&&t.name===`z`}function a(e){if(n(e)||i(e))return!0;if(e.callee?.type===`MemberExpression`&&e.callee.object?.type===`Identifier`){let t=e.callee.object.name.toLowerCase();return t.endsWith(`schema`)||t===`schema`||t===`validator`||t===`zodschema`}return!1}function o(e){if(e.property?.type===`Identifier`)return e.property.name}function s(e){if(e.type===`Identifier`){let t=e.name.toLowerCase();return t===`error`||t===`err`||t===`e`||t===`zoderror`||t===`validationerror`}return e.type===`MemberExpression`&&o(e)===`error`}const c=[`parse`,`parseAsync`,`safeParse`,`safeParseAsync`,`spa`,`encode`,`encodeAsync`,`decode`,`decodeAsync`,`safeEncode`,`safeEncodeAsync`,`safeDecode`,`safeDecodeAsync`,`codec`,`treeifyError`,`prettifyError`,`formatError`,`flattenError`];function l(e){let t=e;for(;t!==null;)if(t.type===`CallExpression`){if(n(t)){let e=t.callee.type===`MemberExpression`&&t.callee.property?.type===`Identifier`?t.callee.property.name:void 0;if(e&&!c.includes(e))return!0;break}if(i(t))return!0;if(t.callee?.type===`MemberExpression`)t=t.callee;else break}else if(t.type===`MemberExpression`)if(t.object?.type===`CallExpression`)t=t.object;else if(t.object?.type===`MemberExpression`)t=t.object;else break;else break;return!1}const u=e({meta:{type:`suggestion`,docs:{description:`强制 Zod schema 变量命名约定`}},createOnce(e){return{VariableDeclarator(t){if(t.id?.type!==`Identifier`)return;let n=t.init;if(n?.type!==`CallExpression`||!l(n))return;let r=t.id.name;r.endsWith(`Schema`)||e.report({node:t.id,message:`Zod schema 变量 "${r}" 应遵循命名约定:后缀 "Schema"。`})}}}}),d=e({meta:{type:`suggestion`,docs:{description:`禁止使用 z.any()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`any`&&e.report({node:t,message:`禁止使用 z.any()。z.any() 不提供任何类型安全,请使用 z.unknown() 或更具体的类型替代。`})}}}}),f=e({meta:{type:`problem`,docs:{description:`禁止使用 .deepPartial()(Zod v4 已移除)`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`deepPartial`){if(!a(t))return;e.report({node:t,message:`禁止使用 .deepPartial()。Zod v4 中已移除,应手动实现深度可选。`})}}}}}),p=[`invalid_type_error`,`required_error`],m=e({meta:{type:`problem`,docs:{description:`禁止使用 invalid_type_error/required_error 参数`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`){for(let n of t.arguments||[])if(n?.type===`ObjectExpression`)for(let t of n.properties||[])t?.type===`Property`&&t.key?.type===`Identifier`&&p.includes(t.key.name)&&e.report({node:t,message:`禁止使用 ${t.key.name} 参数。Zod v4 中已移除,请使用 error 参数替代。`})}}}}}),h=[`format`,`flatten`],g=e({meta:{type:`problem`,docs:{description:`禁止在 ZodError 上使用 .format()/.flatten()(Zod v4 已移除)`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&h.includes(t.callee.property.name)&&s(t.callee.object)&&e.report({node:t,message:`禁止在 ZodError 上使用 .${t.callee.property.name}()。Zod v4 中已移除,请使用 z.treeifyError() 替代。`})}}}}),_={strict:`z.strictObject()`,passthrough:`z.looseObject()`,strip:`z.object(schema.shape)`},v=e({meta:{type:`problem`,docs:{description:`禁止使用 .strict()/.passthrough()/.strip()(Zod v4 已废弃)`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`){let n=t.callee.property.name;if(!Object.hasOwn(_,n)||!a(t))return;let r=_[n];e.report({node:t,message:`禁止使用 .${n}()。Zod v4 中已废弃,请使用 ${r} 替代。`})}}}}}),y=e({meta:{type:`problem`,docs:{description:`禁止访问 .errors 属性,推荐使用 .issues`}},createOnce(e){return{MemberExpression(t){t.property?.type===`Identifier`&&t.property.name===`errors`&&s(t.object)&&e.report({node:t,message:`禁止访问 .errors 属性。Zod v4 中已移除,请使用 .issues 替代。`})}}}}),b=e({meta:{type:`problem`,docs:{description:`禁止使用 .merge(),推荐使用 .extend()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`merge`){if(!a(t))return;e.report({node:t,message:`禁止使用 .merge()。Zod v4 中已废弃,请使用 .extend() 或展开语法替代。`})}}}}}),x=e({meta:{type:`problem`,docs:{description:`禁止使用 z.nativeEnum(),推荐使用 z.enum()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`nativeEnum`&&e.report({node:t,message:`禁止使用 z.nativeEnum()。Zod v4 中已废弃,请使用 z.enum() 替代。`})}}}});function S(e){let t=e.object;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const C=e({meta:{type:`problem`,docs:{description:`禁止使用 .finite()(Zod v4 默认不允许无限值)`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`finite`&&S(t.callee)&&e.report({node:t,message:`禁止使用 .finite()。Zod v4 中 z.number() 默认不允许无限值,此方法已不再需要。`})}}}}),w=e({meta:{type:`problem`,docs:{description:`禁止使用 z.number().int(),推荐使用 z.int()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`int`){let n=t.callee.object;n?.type===`CallExpression`&&n.callee?.type===`MemberExpression`&&n.callee.object?.type===`Identifier`&&n.callee.object.name===`z`&&n.callee.property?.type===`Identifier`&&n.callee.property.name===`number`&&e.report({node:t,message:`禁止使用 z.number().int()。Zod v4 中已废弃,请使用 z.int() 替代。`})}}}}});function T(e){let t=e;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const E=e({meta:{type:`problem`,docs:{description:`禁止访问 .isFinite 属性(Zod v4 始终为 true)`}},createOnce(e){return{MemberExpression(t){if(t.property?.type===`Identifier`&&t.property.name===`isFinite`){let n=t.object;n?.type===`CallExpression`&&T(n)&&e.report({node:t,message:`禁止访问 .isFinite 属性。Zod v4 中此属性始终为 true,已无意义。`})}}}}});function D(e){let t=e;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const O=e({meta:{type:`problem`,docs:{description:`禁止访问 .isInt 属性(Zod v4 已废弃)`}},createOnce(e){return{MemberExpression(t){if(t.property?.type===`Identifier`&&t.property.name===`isInt`){let n=t.object;n?.type===`CallExpression`&&D(n)&&e.report({node:t,message:`禁止访问 .isInt 属性。Zod v4 中已废弃,应检查 format 属性替代。`})}}}}});function k(e){let t=e.object;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const A=e({meta:{type:`problem`,docs:{description:`禁止使用 .safe(),推荐使用 z.int()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`safe`&&k(t.callee)&&e.report({node:t,message:`禁止使用 .safe()。Zod v4 中已废弃,请使用 z.int() 替代。`})}}}});function j(e){let t=e.object;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const M=e({meta:{type:`problem`,docs:{description:`禁止使用 .step(),推荐使用 .multipleOf()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`step`&&j(t.callee)&&e.report({node:t,message:`禁止使用 .step()。Zod v4 中已废弃,请使用 .multipleOf() 替代。`})}}}});function N(e){let t=[],n=e;for(;n!==null&&!(n.callee?.type!==`MemberExpression`||n.callee.property?.type!==`Identifier`||(t.push(n.callee.property.name),n.callee.object?.type!==`CallExpression`));)n=n.callee.object;return t}const P=e({meta:{type:`problem`,docs:{description:`禁止同时使用 .optional() 和 .default()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`){if(!a(t))return;let n=N(t),r=n.includes(`optional`),i=n.includes(`default`);r&&i&&e.report({node:t,message:`禁止同时使用 .optional() 和 .default()。.default() 已隐含可选语义,请移除 .optional()。`})}}}}}),F=e({meta:{type:`problem`,docs:{description:`禁止使用 z.promise()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`promise`&&e.report({node:t,message:`禁止使用 z.promise()。Zod v4 中已移除,应在解析前使用 await。`})}}}}),I=e({meta:{type:`problem`,docs:{description:`要求 z.record() 必须有两个参数`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`record`&&t.arguments?.length===1&&e.report({node:t,message:`z.record() 必须提供两个参数(key schema 和 value schema)。Zod v4 不再支持单参数形式。`})}}}}),L=e({meta:{type:`problem`,docs:{description:`禁止使用 .superRefine(),推荐使用 .check()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`superRefine`){if(!a(t))return;e.report({node:t,message:`禁止使用 .superRefine()。Zod v4 中已废弃,请使用 .check() 替代。`})}}}}}),R=[`refine`,`superRefine`,`transform`],z=e({meta:{type:`problem`,docs:{description:`禁止在 refine 回调中使用 throw 语句`}},createOnce(e){return{ThrowStatement(t){let n=t.parent;for(;n;){if(n.type===`TryStatement`)return;if(n.type===`FunctionExpression`||n.type===`ArrowFunctionExpression`){let r=n.parent;if(r?.type===`CallExpression`&&r.callee?.type===`MemberExpression`&&r.callee.property?.type===`Identifier`&&R.includes(r.callee.property.name)){if(!a(r))return;let n={refine:`禁止在 .refine() 回调中使用 throw 语句。应返回 falsy 值来表示验证失败。`,superRefine:`禁止在 .superRefine() 回调中使用 throw 语句。应使用 ctx.addIssue() 报告错误。`,transform:`禁止在 .transform() 回调中使用 throw 语句。应使用 ctx.issues.push() 并返回 z.NEVER。`}[r.callee.property.name];n&&e.report({node:t,message:n})}return}if(n.type===`FunctionDeclaration`||n.type===`Program`)return;n=n.parent}}}}}),B=e({meta:{type:`suggestion`,docs:{description:`优先使用 z.enum() 替代全字符串字面量的 z.union()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`union`){let n=t.arguments?.[0];if(n?.type!==`ArrayExpression`)return;let r=!0;for(let e of n.elements||[]){if(!e){r=!1;break}if(e.type!==`CallExpression`){r=!1;break}if(e.callee?.type!==`MemberExpression`||e.callee.object?.type!==`Identifier`||e.callee.object.name!==`z`||e.callee.property?.type!==`Identifier`||e.callee.property.name!==`literal`){r=!1;break}let t=e.arguments?.[0];if(t?.type!==`Literal`||typeof t.value!=`string`){r=!1;break}}r&&(n.elements?.length??0)>0&&e.report({node:t,message:`优先使用 z.enum() 替代全字符串字面量的 z.union()。`})}}}}}),V=e({meta:{type:`suggestion`,docs:{description:`推荐使用 error 参数替代 message 参数`}},createOnce(e){return{CallExpression(t){if(!(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`object`)&&t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`){for(let n of t.arguments||[])if(n?.type===`ObjectExpression`)for(let t of n.properties||[])t?.type===`Property`&&t.key?.type===`Identifier`&&t.key.name===`message`&&e.report({node:t,message:`推荐使用 error 参数替代 message 参数。Zod v4 中 message 参数已废弃。`})}}}}}),H=e({meta:{type:`suggestion`,docs:{description:`推荐使用 .meta() 替代 .describe()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`describe`){if(!a(t))return;e.report({node:t,message:`推荐使用 .meta() 替代 .describe()。Zod v4 中 .describe() 已废弃,.meta() 提供更丰富的元数据支持。`})}}}}}),U=e({meta:{type:`suggestion`,docs:{description:`推荐使用 .safeParse() 替代 .parse()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`parse`){if(!a(t))return;e.report({node:t,message:`推荐使用 .safeParse() 替代 .parse()。.safeParse() 不会抛出异常,是更安全的验证方式。`})}}}}}),W={email:`email`,uuid:`uuid`,url:`url`,uri:`uri`,date:`date`,time:`time`,datetime:`datetime`,duration:`duration`,ipv4:`ipv4`,ipv6:`ipv6`,cidrv4:`cidrv4`,cidrv6:`cidrv6`,base64:`base64`,base64url:`base64url`,json:`json`,regex:`regex`,hostname:`hostname`},G=e({meta:{type:`suggestion`,docs:{description:`优先使用顶层字符串格式 schema 替代 z.string().<format>()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type!==`MemberExpression`||t.callee.property?.type!==`Identifier`)return;let n=t.callee.property.name;if(!Object.hasOwn(W,n))return;let r=t.callee.object;if(r?.type===`CallExpression`&&r.callee?.type===`MemberExpression`&&r.callee.object?.type===`Identifier`&&r.callee.object.name===`z`&&r.callee.property?.type===`Identifier`&&r.callee.property.name===`string`){let r=W[n];e.report({node:t,message:`禁止使用 z.string().${n}()。Zod v4 中已废弃,请使用 z.${r}() 替代。`})}}}}}),K=e({meta:{type:`suggestion`,docs:{description:`强制使用命名空间导入 zod`}},createOnce(e){return{ImportDeclaration(t){let n=t.source?.value;if(!(n!==`zod`&&!n?.startsWith(`zod/`)))for(let n of t.specifiers||[])n.type===`ImportDefaultSpecifier`&&e.report({node:n,message:`请使用命名空间导入 zod(import * as z from "zod")代替默认导入。`}),n.type===`ImportSpecifier`&&n.imported?.type===`Identifier`&&n.imported.name===`z`&&e.report({node:n,message:`请使用命名空间导入 zod(import * as z from "zod")代替命名导入。`})}}}});function q(e){let t=e.callee?.type===`MemberExpression`&&e.callee.property?.type===`Identifier`&&e.callee.property.name===`refine`;if(t&&!a(e))return!1;let n=e.callee?.type===`MemberExpression`&&e.callee.object?.type===`Identifier`&&e.callee.object.name===`z`&&e.callee.property?.type===`Identifier`&&e.callee.property.name===`custom`;return t||n}function J(e,t){if(!e.arguments||e.arguments.length<2){t.report({node:e,message:`.refine() 和 z.custom() 必须包含错误消息(error 属性)。`});return}let n=e.arguments[1];if(!(n?.type===`Literal`&&typeof n.value==`string`)&&n?.type===`ObjectExpression`){let r=(n.properties||[]).some(e=>e?.type===`Property`&&e.key?.type===`Identifier`&&e.key.name===`error`),i=(n.properties||[]).some(e=>e?.type===`Property`&&e.key?.type===`Identifier`&&e.key.name===`message`);if(i&&!r){for(let e of n.properties||[])e?.type===`Property`&&e.key?.type===`Identifier`&&e.key.name===`message`&&t.report({node:e,message:`请将 message 属性替换为 error 属性。Zod v4 中 message 已废弃。`});return}!r&&!i&&t.report({node:e,message:`.refine() 和 z.custom() 必须包含错误消息(error 属性)。`})}}const Y=t({meta:{name:`@longzai-intelligence-oxlint/zod-plugin`},rules:{"no-native-enum":x,"no-promise-schema":F,"no-deep-partial":f,"no-record-single-arg":I,"no-merge-method":b,"no-errors-property":y,"no-deprecated-object-methods":v,"no-deprecated-format-methods":g,"no-deprecated-error-params":m,"no-superrefine":L,"prefer-safe-parse":U,"prefer-error-param":V,"no-throw-in-refine":z,"no-any-schema":d,"no-optional-and-default-together":P,"prefer-enum-over-literal-union":B,"prefer-meta":H,"require-error-message":e({meta:{type:`suggestion`,docs:{description:`要求 refine 包含错误消息`}},createOnce(e){return{CallExpression(t){q(t)&&J(t,e)}}}}),"consistent-schema-var-name":u,"prefer-top-level-string-formats":G,"prefer-zod-namespace":K,"no-number-schema-with-int":w,"no-number-schema-with-finite":C,"no-number-schema-with-safe":A,"no-number-schema-with-step":M,"no-number-schema-with-is-finite":E,"no-number-schema-with-is-int":O}});export{Y as default,Y as zodPlugin};
|
|
1
|
+
import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";function n(e){return e.callee?.type===`MemberExpression`&&r(e.callee)}function r(e){return e.object?.type===`Identifier`&&e.object.name===`z`&&e.property?.type===`Identifier`}function i(e){if(e.callee?.type!==`MemberExpression`)return!1;let t=e.callee.object;for(;t.type===`CallExpression`;){if(n(t))return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return t.type===`Identifier`&&t.name===`z`}function a(e){if(n(e)||i(e))return!0;if(e.callee?.type===`MemberExpression`&&e.callee.object?.type===`Identifier`){let t=e.callee.object.name.toLowerCase();return t.endsWith(`schema`)||t===`schema`||t===`validator`||t===`zodschema`}return!1}function o(e){if(e.property?.type===`Identifier`)return e.property.name}function s(e){if(e.type===`Identifier`){let t=e.name.toLowerCase();return t===`error`||t===`err`||t===`e`||t===`zoderror`||t===`validationerror`}return e.type===`MemberExpression`&&o(e)===`error`}const c=[`parse`,`parseAsync`,`safeParse`,`safeParseAsync`,`spa`,`encode`,`encodeAsync`,`decode`,`decodeAsync`,`safeEncode`,`safeEncodeAsync`,`safeDecode`,`safeDecodeAsync`,`codec`,`treeifyError`,`prettifyError`,`formatError`,`flattenError`];function l(e){let t=e;for(;t!==null;)if(t.type===`CallExpression`){if(n(t)){let e=t.callee.type===`MemberExpression`&&t.callee.property?.type===`Identifier`?t.callee.property.name:void 0;if(e&&!c.includes(e))return!0;break}if(i(t))return!0;if(t.callee?.type===`MemberExpression`)t=t.callee;else break}else if(t.type===`MemberExpression`)if(t.object?.type===`CallExpression`)t=t.object;else if(t.object?.type===`MemberExpression`)t=t.object;else break;else break;return!1}const u=e({meta:{type:`suggestion`,docs:{description:`强制 Zod schema 变量命名约定`}},createOnce(e){return{VariableDeclarator(t){if(t.id?.type!==`Identifier`)return;let n=t.init;if(n?.type!==`CallExpression`||!l(n))return;let r=t.id.name;r.endsWith(`Schema`)||e.report({node:t.id,message:`Zod schema 变量 "${r}" 应遵循命名约定:后缀 "Schema"。`})}}}}),d=e({meta:{type:`suggestion`,docs:{description:`禁止使用 z.any()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`any`&&e.report({node:t,message:`禁止使用 z.any()。z.any() 不提供任何类型安全,请使用 z.unknown() 或更具体的类型替代。`})}}}}),f=e({meta:{type:`problem`,docs:{description:`禁止使用 .deepPartial()(Zod v4 已移除)`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`deepPartial`){if(!a(t))return;e.report({node:t,message:`禁止使用 .deepPartial()。Zod v4 中已移除,应手动实现深度可选。`})}}}}}),p=[`invalid_type_error`,`required_error`],m=e({meta:{type:`problem`,docs:{description:`禁止使用 invalid_type_error/required_error 参数`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`){for(let n of t.arguments||[])if(n?.type===`ObjectExpression`)for(let t of n.properties||[])t?.type===`Property`&&t.key?.type===`Identifier`&&p.includes(t.key.name)&&e.report({node:t,message:`禁止使用 ${t.key.name} 参数。Zod v4 中已移除,请使用 error 参数替代。`})}}}}}),h=[`format`,`flatten`],g=e({meta:{type:`problem`,docs:{description:`禁止在 ZodError 上使用 .format()/.flatten()(Zod v4 已移除)`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&h.includes(t.callee.property.name)&&s(t.callee.object)&&e.report({node:t,message:`禁止在 ZodError 上使用 .${t.callee.property.name}()。Zod v4 中已移除,请使用 z.treeifyError() 替代。`})}}}}),_={strict:`z.strictObject()`,passthrough:`z.looseObject()`,strip:`z.object(schema.shape)`},v=e({meta:{type:`problem`,docs:{description:`禁止使用 .strict()/.passthrough()/.strip()(Zod v4 已废弃)`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`){let n=t.callee.property.name;if(!Object.hasOwn(_,n)||!a(t))return;let r=_[n];e.report({node:t,message:`禁止使用 .${n}()。Zod v4 中已废弃,请使用 ${r} 替代。`})}}}}}),y=e({meta:{type:`problem`,docs:{description:`禁止访问 .errors 属性,推荐使用 .issues`}},createOnce(e){return{MemberExpression(t){t.property?.type===`Identifier`&&t.property.name===`errors`&&s(t.object)&&e.report({node:t,message:`禁止访问 .errors 属性。Zod v4 中已移除,请使用 .issues 替代。`})}}}}),b=e({meta:{type:`problem`,docs:{description:`禁止使用 .merge(),推荐使用 .extend()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`merge`){if(!a(t))return;e.report({node:t,message:`禁止使用 .merge()。Zod v4 中已废弃,请使用 .extend() 或展开语法替代。`})}}}}}),x=e({meta:{type:`problem`,docs:{description:`禁止使用 z.nativeEnum(),推荐使用 z.enum()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`nativeEnum`&&e.report({node:t,message:`禁止使用 z.nativeEnum()。Zod v4 中已废弃,请使用 z.enum() 替代。`})}}}});function S(e){let t=e.object;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const C=e({meta:{type:`problem`,docs:{description:`禁止使用 .finite()(Zod v4 默认不允许无限值)`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`finite`&&S(t.callee)&&e.report({node:t,message:`禁止使用 .finite()。Zod v4 中 z.number() 默认不允许无限值,此方法已不再需要。`})}}}}),w=e({meta:{type:`problem`,docs:{description:`禁止使用 z.number().int(),推荐使用 z.int()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`int`){let n=t.callee.object;n?.type===`CallExpression`&&n.callee?.type===`MemberExpression`&&n.callee.object?.type===`Identifier`&&n.callee.object.name===`z`&&n.callee.property?.type===`Identifier`&&n.callee.property.name===`number`&&e.report({node:t,message:`禁止使用 z.number().int()。Zod v4 中已废弃,请使用 z.int() 替代。`})}}}}});function T(e){let t=e;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const E=e({meta:{type:`problem`,docs:{description:`禁止访问 .isFinite 属性(Zod v4 始终为 true)`}},createOnce(e){return{MemberExpression(t){if(t.property?.type===`Identifier`&&t.property.name===`isFinite`){let n=t.object;n?.type===`CallExpression`&&T(n)&&e.report({node:t,message:`禁止访问 .isFinite 属性。Zod v4 中此属性始终为 true,已无意义。`})}}}}});function D(e){let t=e;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const O=e({meta:{type:`problem`,docs:{description:`禁止访问 .isInt 属性(Zod v4 已废弃)`}},createOnce(e){return{MemberExpression(t){if(t.property?.type===`Identifier`&&t.property.name===`isInt`){let n=t.object;n?.type===`CallExpression`&&D(n)&&e.report({node:t,message:`禁止访问 .isInt 属性。Zod v4 中已废弃,应检查 format 属性替代。`})}}}}});function k(e){let t=e.object;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const A=e({meta:{type:`problem`,docs:{description:`禁止使用 .safe(),推荐使用 z.int()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`safe`&&k(t.callee)&&e.report({node:t,message:`禁止使用 .safe()。Zod v4 中已废弃,请使用 z.int() 替代。`})}}}});function j(e){let t=e.object;for(;t?.type===`CallExpression`;){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`number`)return!0;if(t.callee?.type===`MemberExpression`)t=t.callee.object;else break}return!1}const M=e({meta:{type:`problem`,docs:{description:`禁止使用 .step(),推荐使用 .multipleOf()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`step`&&j(t.callee)&&e.report({node:t,message:`禁止使用 .step()。Zod v4 中已废弃,请使用 .multipleOf() 替代。`})}}}});function N(e){let t=[],n=e;for(;n!==null&&!(n.callee?.type!==`MemberExpression`||n.callee.property?.type!==`Identifier`||(t.push(n.callee.property.name),n.callee.object?.type!==`CallExpression`));)n=n.callee.object;return t}const P=e({meta:{type:`problem`,docs:{description:`禁止同时使用 .optional() 和 .default()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`){if(!a(t))return;let n=N(t),r=n.includes(`optional`),i=n.includes(`default`);r&&i&&e.report({node:t,message:`禁止同时使用 .optional() 和 .default()。.default() 已隐含可选语义,请移除 .optional()。`})}}}}}),F=e({meta:{type:`problem`,docs:{description:`禁止使用 z.promise()`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`promise`&&e.report({node:t,message:`禁止使用 z.promise()。Zod v4 中已移除,应在解析前使用 await。`})}}}}),I=e({meta:{type:`problem`,docs:{description:`要求 z.record() 必须有两个参数`}},createOnce(e){return{CallExpression(t){t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`record`&&t.arguments?.length===1&&e.report({node:t,message:`z.record() 必须提供两个参数(key schema 和 value schema)。Zod v4 不再支持单参数形式。`})}}}}),L=e({meta:{type:`problem`,docs:{description:`禁止使用 .superRefine(),推荐使用 .check()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`superRefine`){if(!a(t))return;e.report({node:t,message:`禁止使用 .superRefine()。Zod v4 中已废弃,请使用 .check() 替代。`})}}}}}),R=[`refine`,`superRefine`,`transform`],z=e({meta:{type:`problem`,docs:{description:`禁止在 refine 回调中使用 throw 语句`}},createOnce(e){return{ThrowStatement(t){let n=t.parent;for(;n;){if(n.type===`TryStatement`)return;if(n.type===`FunctionExpression`||n.type===`ArrowFunctionExpression`){let r=n.parent;if(r?.type===`CallExpression`&&r.callee?.type===`MemberExpression`&&r.callee.property?.type===`Identifier`&&R.includes(r.callee.property.name)){if(!a(r))return;let n={refine:`禁止在 .refine() 回调中使用 throw 语句。应返回 falsy 值来表示验证失败。`,superRefine:`禁止在 .superRefine() 回调中使用 throw 语句。应使用 ctx.addIssue() 报告错误。`,transform:`禁止在 .transform() 回调中使用 throw 语句。应使用 ctx.issues.push() 并返回 z.NEVER。`}[r.callee.property.name];n&&e.report({node:t,message:n})}return}if(n.type===`FunctionDeclaration`||n.type===`Program`)return;n=n.parent}}}}}),B=e({meta:{type:`suggestion`,docs:{description:`优先使用 z.enum() 替代全字符串字面量的 z.union()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`union`){let n=t.arguments?.[0];if(n?.type!==`ArrayExpression`)return;let r=!0;for(let e of n.elements||[]){if(!e){r=!1;break}if(e.type!==`CallExpression`){r=!1;break}if(e.callee?.type!==`MemberExpression`||e.callee.object?.type!==`Identifier`||e.callee.object.name!==`z`||e.callee.property?.type!==`Identifier`||e.callee.property.name!==`literal`){r=!1;break}let t=e.arguments?.[0];if(t?.type!==`Literal`||typeof t.value!=`string`){r=!1;break}}r&&(n.elements?.length??0)>0&&e.report({node:t,message:`优先使用 z.enum() 替代全字符串字面量的 z.union()。`})}}}}}),V=e({meta:{type:`suggestion`,docs:{description:`推荐使用 error 参数替代 message 参数`}},createOnce(e){return{CallExpression(t){if((t.callee?.type!==`MemberExpression`||t.callee.object?.type!==`Identifier`||t.callee.object.name!==`z`||t.callee.property?.type!==`Identifier`||t.callee.property.name!==`object`)&&t.callee?.type===`MemberExpression`&&t.callee.object?.type===`Identifier`&&t.callee.object.name===`z`){for(let n of t.arguments||[])if(n?.type===`ObjectExpression`)for(let t of n.properties||[])t?.type===`Property`&&t.key?.type===`Identifier`&&t.key.name===`message`&&e.report({node:t,message:`推荐使用 error 参数替代 message 参数。Zod v4 中 message 参数已废弃。`})}}}}}),H=e({meta:{type:`suggestion`,docs:{description:`推荐使用 .meta() 替代 .describe()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`describe`){if(!a(t))return;e.report({node:t,message:`推荐使用 .meta() 替代 .describe()。Zod v4 中 .describe() 已废弃,.meta() 提供更丰富的元数据支持。`})}}}}}),U=e({meta:{type:`suggestion`,docs:{description:`推荐使用 .safeParse() 替代 .parse()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type===`MemberExpression`&&t.callee.property?.type===`Identifier`&&t.callee.property.name===`parse`){if(!a(t))return;e.report({node:t,message:`推荐使用 .safeParse() 替代 .parse()。.safeParse() 不会抛出异常,是更安全的验证方式。`})}}}}}),W={email:`email`,uuid:`uuid`,url:`url`,uri:`uri`,date:`date`,time:`time`,datetime:`datetime`,duration:`duration`,ipv4:`ipv4`,ipv6:`ipv6`,cidrv4:`cidrv4`,cidrv6:`cidrv6`,base64:`base64`,base64url:`base64url`,json:`json`,regex:`regex`,hostname:`hostname`},G=e({meta:{type:`suggestion`,docs:{description:`优先使用顶层字符串格式 schema 替代 z.string().<format>()`}},createOnce(e){return{CallExpression(t){if(t.callee?.type!==`MemberExpression`||t.callee.property?.type!==`Identifier`)return;let n=t.callee.property.name;if(!Object.hasOwn(W,n))return;let r=t.callee.object;if(r?.type===`CallExpression`&&r.callee?.type===`MemberExpression`&&r.callee.object?.type===`Identifier`&&r.callee.object.name===`z`&&r.callee.property?.type===`Identifier`&&r.callee.property.name===`string`){let r=W[n];e.report({node:t,message:`禁止使用 z.string().${n}()。Zod v4 中已废弃,请使用 z.${r}() 替代。`})}}}}}),K=e({meta:{type:`suggestion`,docs:{description:`强制使用命名空间导入 zod`}},createOnce(e){return{ImportDeclaration(t){let n=t.source?.value;if(!(n!==`zod`&&!n?.startsWith(`zod/`)))for(let n of t.specifiers||[])n.type===`ImportDefaultSpecifier`&&e.report({node:n,message:`请使用命名空间导入 zod(import * as z from "zod")代替默认导入。`}),n.type===`ImportSpecifier`&&n.imported?.type===`Identifier`&&n.imported.name===`z`&&e.report({node:n,message:`请使用命名空间导入 zod(import * as z from "zod")代替命名导入。`})}}}});function q(e){let t=e.callee?.type===`MemberExpression`&&e.callee.property?.type===`Identifier`&&e.callee.property.name===`refine`;if(t&&!a(e))return!1;let n=e.callee?.type===`MemberExpression`&&e.callee.object?.type===`Identifier`&&e.callee.object.name===`z`&&e.callee.property?.type===`Identifier`&&e.callee.property.name===`custom`;return t||n}function J(e,t){if(!e.arguments||e.arguments.length<2){t.report({node:e,message:`.refine() 和 z.custom() 必须包含错误消息(error 属性)。`});return}let n=e.arguments[1];if((n?.type!==`Literal`||typeof n.value!=`string`)&&n?.type===`ObjectExpression`){let r=(n.properties||[]).some(e=>e?.type===`Property`&&e.key?.type===`Identifier`&&e.key.name===`error`),i=(n.properties||[]).some(e=>e?.type===`Property`&&e.key?.type===`Identifier`&&e.key.name===`message`);if(i&&!r){for(let e of n.properties||[])e?.type===`Property`&&e.key?.type===`Identifier`&&e.key.name===`message`&&t.report({node:e,message:`请将 message 属性替换为 error 属性。Zod v4 中 message 已废弃。`});return}!r&&!i&&t.report({node:e,message:`.refine() 和 z.custom() 必须包含错误消息(error 属性)。`})}}const Y=e({meta:{type:`suggestion`,docs:{description:`要求 refine 包含错误消息`}},createOnce(e){return{CallExpression(t){q(t)&&J(t,e)}}}}),X=t({meta:{name:`@longzai-intelligence-oxlint/zod-plugin`},rules:{"no-native-enum":x,"no-promise-schema":F,"no-deep-partial":f,"no-record-single-arg":I,"no-merge-method":b,"no-errors-property":y,"no-deprecated-object-methods":v,"no-deprecated-format-methods":g,"no-deprecated-error-params":m,"no-superrefine":L,"prefer-safe-parse":U,"prefer-error-param":V,"no-throw-in-refine":z,"no-any-schema":d,"no-optional-and-default-together":P,"prefer-enum-over-literal-union":B,"prefer-meta":H,"require-error-message":Y,"consistent-schema-var-name":u,"prefer-top-level-string-formats":G,"prefer-zod-namespace":K,"no-number-schema-with-int":w,"no-number-schema-with-finite":C,"no-number-schema-with-safe":A,"no-number-schema-with-step":M,"no-number-schema-with-is-finite":E,"no-number-schema-with-is-int":O}});export{X as default,X as zodPlugin};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longzai-intelligence-oxlint/zod-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Zod v4 Oxlint 插件,提供 Zod v4 最佳实践和 v3 兼容模式误用检测",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"files": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"typecheck:test": "lzi-tsgo typecheck tsconfig/test.json"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@longzai-intelligence-oxlint/core": "0.1.
|
|
39
|
+
"@longzai-intelligence-oxlint/core": "0.1.14",
|
|
40
40
|
"@oxlint/plugins": "^1.74.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|