轉(zhuǎn)換為 Valibot)
后端前端【免費(fèi)下載鏈接】valibotThe modular and type safe schema library for validating structural data 項(xiàng)目地址https://gitcode.com/gh_mirrors/va/valibot點(diǎn)擊查看免費(fèi)下載Valibot 官方提供的valibot/zod-to-valibot是一個(gè)基于 jscodeshift 的自動(dòng)化遷移工具codemod它能夠把項(xiàng)目中的 Zod 模式、校驗(yàn)規(guī)則、鏈?zhǔn)椒椒ā㈩愋屯茖?dǎo)與解析調(diào)用批量改寫為等價(jià)的 Valibot 代碼。本文以 codemod/zod-to-valibot/README.md 為主線結(jié)合倉(cāng)庫(kù)源碼與測(cè)試夾具完整講解命令行用法、轉(zhuǎn)換覆蓋范圍、核心映射規(guī)則、底層實(shí)現(xiàn)原理與測(cè)試驗(yàn)證方式幫助你安全、高效地完成從 Zod 到 Valibot 的遷移。為什么需要這個(gè) CodemodZod 與 Valibot 都是結(jié)構(gòu)化數(shù)據(jù)的模式校驗(yàn)庫(kù)但兩者的 API 形態(tài)差異明顯Zod 以方法鏈 校驗(yàn)函數(shù)為主Valibot 則把校驗(yàn)邏輯拆分為獨(dú)立的 action并通過(guò)v.pipe()組合類型推導(dǎo)、解析結(jié)果的返回結(jié)構(gòu)、Coerce 的寫法也不盡相同。對(duì)于擁有大量 schema 定義的老項(xiàng)目手工遷移既繁瑣又容易出錯(cuò)。valibot/zod-to-valibot正是為此設(shè)計(jì)的自動(dòng)化方案。它利用 Facebook 的 jscodeshift 在 AST抽象語(yǔ)法樹(shù)層面完成代碼改寫支持 TypeScript/JavaScript 與 JSX能夠在修改代碼的同時(shí)保留原有的注釋、縮進(jìn)和大部分函數(shù)邏輯只替換模式定義與調(diào)用方式。從 package.json 可以看到該工具以bin字段暴露zod-to-valibot命令其唯一運(yùn)行時(shí)依賴是jscodeshift^17.3.0版本為 0.1.2許可證 MIT。快速上手一條命令完成遷移官方 README 給出的基本用法是npx valibot/zod-to-valibot src/**/*該命令會(huì)掃描src目錄下所有匹配**/*的文件默認(rèn)按擴(kuò)展名過(guò)濾見(jiàn)下文對(duì)其中的 Zod schema 進(jìn)行就地改寫。底層實(shí)現(xiàn)位于 cli.mjs它解析出當(dāng)前目錄下的dist/index.mjs作為 transform 腳本并定位jscodeshift/bin/jscodeshift.js最終以jscodeshift -t transformPath files的形式執(zhí)行。需要說(shuō)明的是cli.mjs 在沒(méi)有任何參數(shù)時(shí)會(huì)打印使用說(shuō)明并退出exit code 0因此直接運(yùn)行npx valibot/zod-to-valibot不會(huì)誤改任何文件——必須先指定目標(biāo)文件或目錄通配符。命令行選項(xiàng)詳解README 提供了四組常用選項(xiàng)它們最終都會(huì)透?jìng)鹘o jscodeshift 引擎# Dry run預(yù)覽改動(dòng)不寫入文件 npx valibot/zod-to-valibot --dry src/**/* # 輸出詳細(xì)日志 npx valibot/zod-to-valibot --verbose2 src/**/* # 指定解析器默認(rèn)為 --parserts npx valibot/zod-to-valibot --parserbabel src/**/* # 指定文件擴(kuò)展名默認(rèn)為 --extensionsts,tsx,js,jsx npx valibot/zod-to-valibot --extensionsts src/**/*--dry僅計(jì)算并打印改動(dòng)結(jié)果不觸碰源文件。建議在真正執(zhí)行遷移前先跑一遍人工核對(duì) diff 是否符合預(yù)期。--verbose2提升日志詳細(xì)程度便于排查某個(gè)文件為什么沒(méi)被轉(zhuǎn)換。--parser選擇 AST 解析器。cli.mjs 會(huì)檢查參數(shù)中是否已包含--parser或--parser前綴若沒(méi)有則自動(dòng)在參數(shù)最前面補(bǔ)上--parserts所以默認(rèn)即為ts解析器可覆蓋.ts、.tsx、.js、.jsx四種擴(kuò)展名手動(dòng)傳入--parserbabel則切換為 babel 解析器。--extensions默認(rèn)值同樣是 cli.mjs 注入的ts,tsx,js,jsx你可以按需收窄例如只處理.ts文件--extensionsts。由于工具本身只是 jscodeshift 的前端封裝README 也注明其余可用選項(xiàng)與 jscodeshift 保持一致。在本倉(cāng)庫(kù)中cli.mjs 打印的幫助文本列舉了--dry、--print打印輸出、--verbose2、--parserts等常用項(xiàng)并提示可通過(guò)jscodeshift --help查看完整列表。轉(zhuǎn)換覆蓋范圍到底能轉(zhuǎn)換什么README 把轉(zhuǎn)換能力歸納為四類倉(cāng)庫(kù)源碼中 constants.ts 以常量數(shù)組的形式給出了精確清單1. 基礎(chǔ) schemaany、array、bigint、boolean、custom、date、discriminatedUnion、enum、instanceof、intersection、literal、nan、nativeEnum、null、nullable、record、map、never、number、object、optional、set、string、symbol、tuple、undefined、union、unknown、void共 29 種。2. 校驗(yàn)規(guī)則validatorsbase64、cuid2、date、datetime、email、emoji、endsWith、finite、includes、int、ip、length、max、min、multipleOf同時(shí)兼容 Zod 的step、nanoid、negative、nonempty、nonnegative、nonpositive、positive、readonly、regex、safe、size、startsWith、toLowerCase、toUpperCase、trim、url、gt、gte、lt、lte、time、ulid、uuid等。其中base64url、cidr、cuid、duration、jwt由于 Valibot 暫時(shí)沒(méi)有對(duì)應(yīng) action會(huì)被標(biāo)記為未實(shí)現(xiàn)見(jiàn)下文限制與注意事項(xiàng)。3. 鏈?zhǔn)椒椒ㄅc屬性方法ZOD_METHODSarray、catchall、default、deepPartial、exclude、extend、extract、keyof、omit、optional、or、merge、nullable、nullish、parse、parseAsync、partial、passthrough、pick、refine、required、rest、safeParse、safeParseAsync、strict、strip、spa、transform、unwrap。屬性ZOD_PROPERTIESelement、description、shape以及解析結(jié)果的data、error。4. 類型推導(dǎo)infer、input、output三類類型引用會(huì)被改寫為 Valibot 的類型工具詳見(jiàn)下文類型推導(dǎo)的改寫。核心映射規(guī)則從測(cè)試夾具看實(shí)際轉(zhuǎn)換倉(cāng)庫(kù)在 codemod/zod-to-valibot/testfixtures下為每種轉(zhuǎn)換場(chǎng)景準(zhǔn)備了input.ts/output.ts成對(duì)夾具下面的映射均以這些真實(shí)夾具為準(zhǔn)?;A(chǔ) schema 與校驗(yàn)規(guī)則array-schema夾具展示了數(shù)組與內(nèi)聯(lián)校驗(yàn)的轉(zhuǎn)換// 轉(zhuǎn)換前input.ts const Schema2 z.array(z.string().email()); const Schema5 z.string().array(); const Schema7 Schema6.array(); // 轉(zhuǎn)換后output.ts const Schema2 v.array(v.pipe(v.string(), v.email())); const Schema5 v.array(v.string()); const Schema7 v.array(Schema6);可以看到三個(gè)關(guān)鍵行為同名基礎(chǔ) schema 直接替換z.string()→v.string()z.array(...)→v.array(...)前綴z統(tǒng)一替換為v鏈?zhǔn)叫r?yàn)折疊進(jìn)v.pipe()z.string().email()變成v.pipe(v.string(), v.email())反向鏈寫法歸一化z.string().array()與獨(dú)立變量引用Schema6.array()都被改寫為v.array(Schema6)。對(duì)數(shù)值與字符串的校驗(yàn)器轉(zhuǎn)換遵循按目標(biāo)類型選擇 action的規(guī)則z.number().min(0)會(huì)變成v.minValue(0)z.number().int()、z.string().min(5)等則分別映射到對(duì)應(yīng)的 Valibot action可對(duì)照 validators 目錄 中min、max、int、regex、email、url等實(shí)現(xiàn)。transform夾具中z.number().min(0).transform(...)的輸出為v.pipe(v.number(), v.minValue(0), v.transform(...))驗(yàn)證了min在數(shù)值上下文中落地為minValue。Coercionz.coerce 的特殊映射README 特別指出z.coerce.*會(huì)轉(zhuǎn)換為v.pipe(v.unknown(), v.toX())。coerce-string-schema夾具證實(shí)了這一映射并且同時(shí)支持兩種等價(jià)寫法// 轉(zhuǎn)換前 const Schema1 z.coerce.string(); const Schema2 z.string({ coerce: true }); // 轉(zhuǎn)換后 const Schema1 v.pipe(v.unknown(), v.toString()); const Schema2 v.pipe(v.unknown(), v.toString());在 string/string.ts 的源碼實(shí)現(xiàn)中g(shù)etSchemaComps會(huì)同時(shí)接收前綴標(biāo)記的 coercez.coerce.string()與選項(xiàng)對(duì)象的 coercez.string({ coerce: true })兩種信號(hào)一旦判定為 coercion就構(gòu)建v.pipe(v.unknown(), v.toString())boolean/number/bigint/date 同理對(duì)應(yīng)v.toBoolean()、v.toNumber()、v.toBigint()、v.toDate()可通過(guò) schemas 目錄 下各 schema 實(shí)現(xiàn)確認(rèn)。coerce 鏈上的后續(xù)校驗(yàn)同樣保留z.coerce.string().email()輸出v.pipe(v.unknown(), v.toString(), v.email())。對(duì)象、聯(lián)合、可選與更多組合z.union([...])→v.union([...])z.discriminatedUnion(key, {...})→v.variant(key, {...})z.optional(...)、z.nullable(...)、z.nullish(...)分別映射為v.optional(...)、v.nullable(...)、v.nullish(...)z.object({ ... })→v.object({ ... })且對(duì)象鏈上的.strict()、.passthrough()、.strip()會(huì)被檢測(cè)為對(duì)象修飾符見(jiàn) schemas-and-links.ts 中的checkForObjectModifierInChain分別改寫為v.strictObject(...)、v.looseObject(...)與默認(rèn)的v.object(...)對(duì)象方法pick/omit/partial/required/extend/merge/deepPartial等均有對(duì)應(yīng)轉(zhuǎn)換如z.object({...}).pick({...})會(huì)改寫為v.pick(v.object({...}), {...})相應(yīng)實(shí)現(xiàn)分布在 methods 目錄z.record(...)→v.record(...)z.map(...)/z.set(...)→v.map(...)/v.set(...)z.tuple([...])→v.tuple([...])z.instanceof(Class)→v.instance(Class)校驗(yàn)器的message參數(shù)會(huì)轉(zhuǎn)換為 Valibot action 的第二個(gè)字符串參數(shù)例如z.array(z.string(), { message: some message })輸出v.array(v.string(), some message)description選項(xiàng)則被提升為v.pipe(v.array(v.string()), v.description(some description))其參數(shù)提取邏輯在 schemas/helpers.ts 的getTransformedMsgs/getOptions中實(shí)現(xiàn)。解析調(diào)用與結(jié)果屬性的改寫parsing夾具完整展示了運(yùn)行時(shí) API 的遷移// 轉(zhuǎn)換前 const output1 Schema.parse(to parse); const result1 Schema.safeParse(to safeParse); if (result1.success) { const output result1.data; } else { const errors result1.error; } // 轉(zhuǎn)換后 const output1 v.parse(Schema, to parse); const result1 v.safeParse(Schema, to safeParse); if (result1.success) { const output result1.output; } else { const errors result1.issues; }要點(diǎn)方法調(diào)用變?yōu)楠?dú)立的頂層函數(shù)Schema.parse(x)→v.parse(Schema, x)safeParse/parseAsync/safeParseAsync同理Schema.spa(x)舊版別名也統(tǒng)一映射到v.safeParseAsync(Schema, x)結(jié)果對(duì)象屬性重命名result.data→result.outputresult.error→result.issues見(jiàn)toValiPropExp中data、error兩個(gè)分支。transform 與 refinez.string().transform(fn)→v.pipe(v.string(), v.transform(fn))連續(xù)多個(gè) transform 會(huì)依次放入同一個(gè) pipez.number().refine(fn)對(duì)應(yīng)改寫為 pipe 中的v.check(fn)形態(tài)z.string().regex(...)→v.regex(...)被賦給變量的 schema 引用也會(huì)被追蹤const BaseSchema z.string(); const T BaseSchema.transform(...)會(huì)輸出v.pipe(BaseSchema, v.transform(...))——這正是transformSchemasAndLinks遞歸跟蹤變量鏈接的結(jié)果。類型推導(dǎo)的改寫type-inference場(chǎng)景見(jiàn)toValiTypeExp的映射為z.infertypeof Schema→v.InferOutputtypeof Schemaz.outputtypeof Schema→v.InferOutputtypeof Schemaz.inputtypeof Schema→v.InferInputtypeof Schema類型引用同樣會(huì)從z前綴替換為v前綴。源碼工作機(jī)制兩階段轉(zhuǎn)換整個(gè) transform 的入口在 src/transform/index.ts流程分兩個(gè)階段imports 階段transformImports見(jiàn) imports/imports.ts。它查找from zod或from zod/v4的 import 語(yǔ)句要求恰好一條 import、恰好一個(gè) specifier否則判定失敗文件里根本沒(méi)有 zod import 時(shí)直接跳過(guò)skipimport 寫法不滿足要求時(shí)在文件頭部插入valibot-migrate: unable to transform imports from Zod to Valibot: 原因注釋并原樣返回。成功后把 import 改寫為import * as v from valibot若原標(biāo)識(shí)符不是z如import { z as zod } from zod則保留原標(biāo)識(shí)符作為 Valibot 的命名空間名。當(dāng)原標(biāo)識(shí)符恰為z時(shí)還會(huì)把所有z.xxx成員表達(dá)式與z.xxx類型引用批量替換為v.xxx。schemas-and-links 階段transformSchemasAndLinks見(jiàn) schemas-and-links.ts。它遍歷 AST 中所有以 Valibot 標(biāo)識(shí)符為根的成員表達(dá)式與TSTypeReference從內(nèi)到外.reverse()逐個(gè)處理調(diào)用鏈識(shí)別到 schema 名如string→ 生成對(duì)應(yīng)的 Valibot schema 調(diào)用識(shí)別到 validator 名如email→ 通過(guò) helpers.ts 的addToPipe把 action 追加進(jìn)v.pipe(...)若已是 pipe 則直接追加參數(shù)否則新建 pipe識(shí)別到方法名如optional、parse→ 調(diào)用對(duì)應(yīng)的方法轉(zhuǎn)換器遇到不認(rèn)識(shí)的屬性名或無(wú)法安全解析的鏈則標(biāo)記transformLinks false整條鏈保持原樣避免破壞代碼。轉(zhuǎn)換器通過(guò)ZOD_SCHEMA_TO_TYPE記錄每個(gè) schema 的類型族如string→length、number→value、set→size以便min/max/nonempty等通用校驗(yàn)器在目標(biāo)類型上選擇正確的 Valibot action。值得注意的細(xì)節(jié)被賦值的 schema 變量會(huì)被追蹤。當(dāng)鏈的根表達(dá)式是const X zod表達(dá)式的右值時(shí)轉(zhuǎn)換器會(huì)遞歸地以變量名X繼續(xù)掃描文件中所有引用X的表達(dá)式見(jiàn)transformSchemasAndLinksHelper末尾的變量鏈接追蹤因此const Schema z.string(); Schema.parse(...)這類跨語(yǔ)句引用也能被正確改寫。如何驗(yàn)證轉(zhuǎn)換結(jié)果測(cè)試夾具機(jī)制倉(cāng)庫(kù)沒(méi)有為轉(zhuǎn)換結(jié)果提供獨(dú)立的驗(yàn)收腳本而是把測(cè)試內(nèi)嵌在 src/utils.ts 的defineTests中它讀取__testfixtures__下每個(gè)子目錄查找input*與output*命名的文件對(duì)用 jscodeshift 的 ts 解析器對(duì)input執(zhí)行當(dāng)前 transform并將結(jié)果與output做逐字比較expect(output?.trim()).toBe(expectedOutput.trim())。測(cè)試運(yùn)行器是 vitest腳本定義在 package.json 的test: vitest。這意味著每個(gè)轉(zhuǎn)換場(chǎng)景都有一條輸入 → 輸出的金標(biāo)準(zhǔn)如果你在遷移中遇到某個(gè)寫法的轉(zhuǎn)換結(jié)果不符合預(yù)期可以對(duì)照testfixtures中對(duì)應(yīng)場(chǎng)景的output.ts判斷是工具的限制還是自己寫法超出了覆蓋范圍。倉(cāng)庫(kù)還提供了test-setup.test.ts作為測(cè)試裝配入口。限制與注意事項(xiàng)從源碼與夾具可以確認(rèn)以下幾類邊界情況遷移前值得提前排查import 寫法有嚴(yán)格要求必須恰好一條from zod或zod/v4import 且恰好一個(gè) specifier多條 import、同時(shí)存在默認(rèn)導(dǎo)入與命名導(dǎo)入等寫法會(huì)導(dǎo)致文件被跳過(guò)并插入說(shuō)明注釋。因此建議在運(yùn)行 codemod 前先統(tǒng)一 import 風(fēng)格如import { z } from zod或import * as z from zod。部分校驗(yàn)器未實(shí)現(xiàn)base64url、cidr、cuid、duration、jwt等見(jiàn) schemas-and-links.ts 中transformUnimplemented的分支會(huì)保留原調(diào)用或需要手工替換為等價(jià)實(shí)現(xiàn)屬于預(yù)期內(nèi)的降級(jí)行為。自定義 schema 的泛型z.customT(...)依賴類型參數(shù)的透?jìng)鞲膶憰r(shí)需要保證 Valibot 對(duì)應(yīng) API 的泛型語(yǔ)義一致源碼注釋也指出 parser 與類型系統(tǒng)并不完全同步ts-expect-error因此對(duì)高度依賴泛型推斷的代碼要額外 review。未知鏈保持原樣任何無(wú)法識(shí)別的屬性名或非標(biāo)識(shí)符屬性如schema[email]()都會(huì)讓整條鏈跳過(guò)轉(zhuǎn)換確保不產(chǎn)生錯(cuò)誤代碼——這同時(shí)意味著遷移后需要人工處理這些殘留。結(jié)果語(yǔ)義的細(xì)微差異result.error→result.issues、result.data→result.output是 Valibot 的命名約定z.string({ coerce: true })與z.coerce.string()會(huì)統(tǒng)一成v.pipe(v.unknown(), v.toString())語(yǔ)義上等價(jià)但運(yùn)行時(shí)多了一層unknown解析需要按項(xiàng)目對(duì)性能與錯(cuò)誤信息的要求確認(rèn)。先 dry-run再動(dòng)手建議始終先--dry預(yù)覽改動(dòng)配合--verbose2觀察被跳過(guò)的文件隨后用--extensions分批灰度遷移并用 vitest 的夾具機(jī)制作為回歸基線。遷移建議總結(jié)遷移前統(tǒng)一 Zod import 寫法確保每個(gè)文件只有一條、一個(gè) specifier 的 import用npx valibot/zod-to-valibot --dry src/**/*預(yù)覽全量改動(dòng)檢查被跳過(guò)文件與未實(shí)現(xiàn) validator 的清單確認(rèn)無(wú)誤后再執(zhí)行真實(shí)遷移并配合類型檢查與測(cè)試套件可參考__testfixtures__的輸入輸出對(duì)做全量回歸對(duì)z.coerce.*、泛型z.customT、結(jié)果對(duì)象屬性訪問(wèn)等特殊寫法重點(diǎn) review必要時(shí)手工微調(diào)。借助這套官方 codemod從 Zod 遷移到 Valibot 的大部分機(jī)械性工作可以交給自動(dòng)化完成團(tuán)隊(duì)只需把精力集中在少數(shù)邊界場(chǎng)景與業(yè)務(wù)語(yǔ)義核對(duì)上是平滑切換 schema 庫(kù)的務(wù)實(shí)起點(diǎn)。贊分享后端前端【免費(fèi)下載鏈接】valibotThe modular and type safe schema library for validating structural data 項(xiàng)目地址https://gitcode.com/gh_mirrors/va/valibot點(diǎn)擊查看免費(fèi)下載相關(guān)推薦中興光貓工廠模式解鎖終極指南zteOnu開(kāi)源工具快速上手與避坑實(shí)戰(zhàn)中興光貓工廠模式解鎖終極指南zteOnu開(kāi)源工具快速上手與避坑實(shí)戰(zhàn) 家里的 中興光貓 是不是總感覺(jué)缺了點(diǎn)什么Web管理頁(yè)面功能寥寥Telnet默認(rèn)關(guān)閉后端前端終極Valibot遷移指南從Zod無(wú)縫轉(zhuǎn)換的7個(gè)關(guān)鍵步驟終極Valibot遷移指南從Zod無(wú)縫轉(zhuǎn)換的7個(gè)關(guān)鍵步驟 Valibot是一個(gè)模塊化且類型安全的 schema驗(yàn)證庫(kù) 專門用于驗(yàn)證結(jié)構(gòu)化數(shù)據(jù)。如果你正在使用后端前端Valibot 官方 Zod 遷移 Codemod從 v0.1.0 到 ES2020 構(gòu)建目標(biāo)的版本演進(jìn)與實(shí)現(xiàn)剖析Valibot 官方 Zod 遷移 Codemod從 v0.1.0 到 ES2020 構(gòu)建目標(biāo)的版本演進(jìn)與實(shí)現(xiàn)剖析 valibot/zod to valib后端前端上一篇Arduino ESP32 核移植指南為 arduino-esp32 添加全新 SoC 支持的完整流程下一篇Loki 倉(cāng)庫(kù)內(nèi) etcd 官方 Go 客戶端 clientv3 完全指南連接管理、錯(cuò)誤處理與配置調(diào)優(yōu)創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考