方案)
drizzle-zod 0.4.3 新增 PgDateString 支持PostgreSQL 日期列的類型化 Zod 校驗(yàn)方案【免費(fèi)下載鏈接】drizzle-ormORM項(xiàng)目地址: https://gitcode.com/gh_mirrors/dr/drizzle-ormdrizzle-zod 是 Drizzle ORM 的官方 Zod 集成插件能夠從 Drizzle 表結(jié)構(gòu)自動(dòng)生成 Zod 校驗(yàn) Schema。0.4.3 版本的核心變更是為 PostgreSQL 的date({ mode: string })日期列補(bǔ)齊了類型化映射此前該類列只能退化為通用z.any()校驗(yàn)升級(jí)后會(huì)被正確生成為z.string()校驗(yàn)器。本文以 changelogs/drizzle-zod/0.4.3.md 為主線結(jié)合 drizzle-orm 與 drizzle-zod 的源碼實(shí)現(xiàn)完整梳理該版本的能力變化、底層機(jī)制與實(shí)戰(zhàn)用法。版本要點(diǎn)PgDateString 類型映射補(bǔ)全0.4.3 版本的變更記錄非常精簡只有一條 Added PgDateString to drizzle-zod#665要理解這條變更需要先回到 Drizzle ORM 對(duì) PostgreSQLdate列的類型設(shè)計(jì)。在 drizzle-orm/src/pg-core/columns/date.ts 中date()構(gòu)造器接受一個(gè){ mode: date | string }配置date({ mode: date })返回PgDate列其dataType為dateTypeScript 側(cè)數(shù)據(jù)類型為Date讀寫時(shí)負(fù)責(zé) Date 對(duì)象與驅(qū)動(dòng)字符串之間的雙向轉(zhuǎn)換見 date.ts#L33-L49date({ mode: string })返回PgDateString列其dataType為stringTypeScript 側(cè)數(shù)據(jù)類型為string僅負(fù)責(zé)把驅(qū)動(dòng)返回的 Date 統(tǒng)一裁剪為YYYY-MM-DD格式的日期字符串見 date.ts#L80-L92。在 drizzle-zod 0.4.3 之前由于映射邏輯只識(shí)別了PgDate以及PgTimestamp等列類型PgDateString列無法命中任何已知分支最終會(huì)落入columnToSchema兜底的z.any()等于放棄了運(yùn)行時(shí)校驗(yàn)?zāi)芰Α?.4.3 正是補(bǔ)齊了這個(gè)缺口當(dāng)columnType PgDateString時(shí)生成的 Zod Schema 為z.string()。源碼級(jí)驗(yàn)證從列類型到 Zod Schema 的映射鏈路底層實(shí)現(xiàn)PgDateString 的判定與生成在 drizzle-zod/src/column.ts 中columnToSchema函數(shù)負(fù)責(zé)把 Drizzle 列轉(zhuǎn)換為 Zod Schema。其判定順序是先檢查枚舉列isWithEnum再按列類型逐個(gè)匹配幾何、向量、數(shù)組、數(shù)值、布爾、日期、字符串、JSON 等類型。0.4.3 新增的映射位于字符串分支stringColumnToSchemacolumn.ts#L267-L318export const columnToSchema ( column: Column, factory: CreateSchemaFactoryOptions..., ): zod.ZodType { ... } else if (column.dataType string) { schema stringColumnToSchema(column, z, coerce); } ... };而stringColumnToSchema內(nèi)部正是通過isColumnType(column, [PgDateString])判定該分支function stringColumnToSchema(column: Column, z: typeof zod, coerce: ...): zod.ZodType { // PgUUID 映射為 z.uuid() // 常規(guī)字符串列根據(jù) length/char/enum 等約束生成 z.string() 及其長度限制 // 新增PgDateString 在此分支中命中生成 z.string() }由于PgDateString的dataType為string它天然進(jìn)入字符串處理分支并按字符串列的標(biāo)準(zhǔn)流程生成 Schema——不附加長度約束、不附加正則約束最終等價(jià)于z.string()。驅(qū)動(dòng)層確認(rèn)PgDateString 的運(yùn)行時(shí)行為在 drizzle-orm 側(cè)PgDateString的getSQLType()返回date即底層 SQL 類型仍是 PostgreSQL 的date只是 TS 層以字符串承載。mapFromDriverValue會(huì)將驅(qū)動(dòng)返回的Date或字符串統(tǒng)一裁剪為YYYY-MM-DDvalue.toISOString().slice(0, -14)mapToDriverValue未做特殊處理。這一點(diǎn)保證了生成的z.string()與運(yùn)行時(shí)實(shí)際數(shù)據(jù)形態(tài)一致——從數(shù)據(jù)庫讀出的日期值一定是字符串。測(cè)試佐證期望 Schema 的形狀drizzle-zod 的 PostgreSQL 測(cè)試 tests/pg.test.ts 中all data types用例覆蓋了date({ mode: date })與date({ mode: string })兩種寫法const table pgTable(test, ({ date }) ({ date1: date({ mode: date }).notNull(), date2: date({ mode: string }).notNull(), ... })); const result createSelectSchema(table); const expected z.object({ date1: z.date(), // PgDate → z.date() date2: z.string(), // PgDateString → z.string()0.4.3 新增 ... }); expectSchemaShape(t, expected).from(result);同時(shí)type coercion - mixed用例也驗(yàn)證了在createSchemaFactory({ coerce: { date: true } })下timestamp會(huì)被包裝為z.coerce.date()而字符串模式列不受 coerce 影響。在項(xiàng)目中的實(shí)際應(yīng)用安裝與基本用法drizzle-zod 是獨(dú)立包需要與 drizzle-orm、zod 配合使用pnpm add drizzle-zod zod drizzle-orm在表定義中按需選擇日期模式import { date, pgTable, serial, text } from drizzle-orm/pg-core; import { createInsertSchema, createSelectSchema } from drizzle-zod; import { z } from zod; const events pgTable(events, { id: serial(id).primaryKey(), title: text(title).notNull(), eventDate: date(event_date, { mode: string }).notNull(), // 0.4.3 起生成 z.string() createdAt: date(created_at, { mode: date }).notNull(), // 生成 z.date() }); const selectEventSchema createSelectSchema(events); // selectEventSchema 形狀 // { id: ..., title: ..., eventDate: z.string(), createdAt: z.date() } const insertEventSchema createInsertSchema(events);此后insertEventSchema.parse()會(huì)嚴(yán)格校驗(yàn)eventDate必須為字符串createdAt必須為 Date 對(duì)象不再像 0.4.3 之前那樣對(duì)eventDate靜默放行。與 coerce 選項(xiàng)的配合createSchemaFactory提供的coerce選項(xiàng)可統(tǒng)一控制日期列的轉(zhuǎn)換行為drizzle-zod/src/schema.tsimport { createSchemaFactory } from drizzle-zod; const { createSelectSchema } createSchemaFactory({ coerce: { date: true, // 僅影響 date 模式的列 → z.coerce.date() }, });字符串模式列因生成的是z.string()不受該開關(guān)影響如需把字符串日期列也做成寬松校驗(yàn)可在createInsertSchema的第二個(gè)參數(shù)中顯式覆蓋字段const relaxed createInsertSchema(events, { eventDate: z.coerce.string(), });版本適用范圍本文描述的行為以當(dāng)前倉庫為準(zhǔn)drizzle-zod 0.4.3 引入了PgDateString映射適用于 PostgreSQL 方言drizzle-orm/pg-coreMySQL、SQLite、SingleStore 等其他方言的日期列映射仍遵循各自已有的規(guī)則。若你使用的是更早版本請(qǐng)先升級(jí)到 0.4.3 或以上。小結(jié)drizzle-zod 0.4.3 通過識(shí)別PgDateString列類型將 PostgreSQL 字符串模式日期列從“無法校驗(yàn)”提升為“精確的z.string()校驗(yàn)”同時(shí)保證了與date({ mode: date })z.date()在類型層面的清晰區(qū)分。對(duì)于以字符串格式在前后端之間傳遞日期的團(tuán)隊(duì)這一補(bǔ)全讓接口入?yún)?、出參?Zod 校驗(yàn)真正做到了“表結(jié)構(gòu)即校驗(yàn)規(guī)則”配合createSchemaFactory的coerce選項(xiàng)還可按需放寬轉(zhuǎn)換策略?!久赓M(fèi)下載鏈接】drizzle-ormORM項(xiàng)目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考