# create-ajv **Repository Path**: janpoem/create-ajv ## Basic Information - **Project Name**: create-ajv - **Description**: 一个可延伸的 Ajv 实例创建环境。 - **Primary Language**: TypeScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-11-12 - **Last Updated**: 2022-11-14 ## Categories & Tags **Categories**: json-tools **Tags**: None ## README # create-ajv [![version](https://img.shields.io/npm/v/create-ajv?style=for-the-badge)](https://www.npmjs.com/package/create-ajv) [![dw](https://img.shields.io/npm/dw/create-ajv?style=for-the-badge)](https://www.npmjs.com/package/create-ajv) 创建 Ajv 辅助器。 [Ajv](https://ajv.js.org/json-type-definition.html) 是基于 json-schema / JTD 对数据进行验证的一个辅助库。其功能是能满足大部分的数据验证的场景的,但这个实际运用却很生草。 首先,Ajv 将初始化和错误处理(多语言),进行了分离,使得实际调用的代码异常臃肿。 如果你需要在项目环境中引用诸如 `ajv-formats` `ajv-i18n` ,那你的代码可能会是如下: ```js import Ajv from 'ajv'; import addFormats from 'ajv-formats'; import localize_zh from 'ajv-i18n/localize/zh'; const ajv = new Ajv(); addFormats(ajv); ajv.addKeyword({ keyword : 'someKeyword', validate: () => true, }); // 这里可能还有很多你自己项目里的扩展 // 到使用: const schema = { type : 'object', properties: { // .... }, required : [ // ... ] } const validate = ajv.compile(schema); const data = {}; const valid = validate(data); if (!valid) { // 将错误信息本地化 localize_zh(validate.errors); } ``` 其次,如果你项目中需要使用 `react-hook-form`,以及 `@hookform/resolver` (`react-hook-form` 出品的包含市面常用的 js validator 的 resolver),就会发现,`@hookform/resolver/ajvResolver` 是在其内部闭环的,你无法在这过程中加入其他的 ajv 扩展或者多语言本地化的处理。 可以参考这个文件:[`@hookform/resolver/ajv.ts`](https://github.com/react-hook-form/resolvers/blob/master/ajv/src/ajv.ts) 再次,`ajv-i18n` 的汉化,仍有需要不完善的地方,大体可以用,但是总需要在实际项目进行拦截和优化。 最后的最后,往往当我们在实际项目中添加一种 format / keyword,可能希望他能被更简单的在下一个项目重用起来,而一种 format / keyword 往往是和 localize 紧密结合的,所以需要有一个更简易的环境去使用 ajv,这也是创建这个项目的目的。 Ajv 延伸,意在由你自己决定如何扩展延伸,项目本身只提供一个简易的粘合作用,将 Ajv 的一些常用方法重新调整调用的方式,以便于人类理解使用。 ## 主要内容 ### ajv.ts 该部分主要提供了一个全局简易创建和使用 Ajv 实例的快捷方式。 ```js import { createAjv, ajv } from 'create-ajv'; ``` `createAjv` 创建一个全局统一的创建 Ajv 实例的方法 ```js import addFormats from 'ajv-formats'; import localize_zh from 'ajv-i18n/localize/zh'; // 全局的 ajv 实例创建句柄 // 这样,通过 ajv 创建的所有 ajv 实例,都会自动套用 use / useLocalize 所添加的扩展和本地化 export const ajv = createAjv() // 加入扩展 .use((ajvInstance, { useLocalize }) => { // 每次创建 ajv 实例的时候会执行 addFormats(ajvInstance); // 其他扩展 ajvInstance.addKeyword({ keyword : 'someKeyword', error: { message: () => 'xxx', // => 需要将这个 keyword 的 params 进行传递,才能在本地化的时候得到这个 keyword 相应的 params params: (cxt) => cxt.params, }, validate: () => true, }); useLocalize((errors) => { if (!errors || !errors.length) return; errors.forEach(err => { if (err.keyword === 'someKeyword') { err.message = 'xxx' + err.params; } }) }); }) // 本地化 // 只在验证时发生错误时执行 .useLocalize(localize_zh) // 创建 ajv 实例时候的默认 options .setOptions({ allErrors: true }) ; // 创建一个 ajv 实例 const localAjv = ajv(); // 1. 创建一个 ajv 实例, // 2. 并 compile schema, // 3. 然后执行 validate // 默认模式 const { valid, errors } = ajv.validate(data, schema); // throw error 模式 try { ajv.validate(data, schema, true); } catch (err) { // TS 将所有 err 变为 unknown 类型,所以需要自行 detect if (ajv.isValidationError(err)) { console.log(err.errors); } } ``` `ajv` 为默认创建的一个全局单例 `export const ajv = createAjv()` ,主要用于给一些小项目直接使用(比如有些时候真的连单独创建一个 ajv 的文件都懒的时候)。但不推荐这样用(不使用他,可以不导出这个 `ajv`)。 ### schema.ts 该部分主要为快捷创建 schema 的方法封装,目前只提供 `object` 类型的快捷定义 ```ts import { schemaObject } from 'create-ajv'; schemaObject({ key: { type: 'string' }, }, ['key']) // 支持指定泛型 // 解除了 ajv 默认的 properties 锁定的设定,即: // 1. 强制限定 Type.field 的类型,必须和 properties 的类型强关联(实际应用中,验证器往往总是要包含更多情况) // 2. 如果指定 Type.field 为 ? (即可能为 undefined),会强制要求对应的 properties 声明中增加 nullable // 3. required 声明也必须限定在 Type 字段内。 // 以上三方面的限制皆去除,并且能自动根据 Type 进行代码提示。 type Type = { field: string, } schemaObject( // properties 声明 { field: { type: 'string' }, }, // required 声明 ['field'], // additionalProperties true, // 其他 schema 属性 { patternProperties: { }, // .... } ) ``` ## 更新记录 ## 1.0.3 将 schemaObject 和 jsonSchemaObject 的返回类型改回 JSONSchema6 (`@types/json-schema`)。 ajv 的 `JsonSchemaType` 和 `JTDSchemaType` ,在外部使用会有一些奇奇怪怪的问题。