Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/frog4js/schema

JSONSchema (draft-03, draft-02, draft-01) Validation in Node.js (esm)
https://github.com/frog4js/schema

esmodule javascript jsonschema nodejs

Last synced: 17 days ago
JSON representation

JSONSchema (draft-03, draft-02, draft-01) Validation in Node.js (esm)

Awesome Lists containing this project

README

        

# @frog4js/schema

- [中文](README-zh_CN.md)
- [English](README.md)

适用于 Node.js 和浏览器的 JSON Schema。即将支持所有的 draft(目前支持 draft-01,draft-02,draft-03,draft-04,draft-05,draft-06,draft-07)。

## 功能

- 使用函数式编程(esm + jsDoc + Function)
- 会对 schema 进行预编译, 会占用额外的内存,单不会产生额外代码(和 ajv 有本质的区别)
- 0 dependencies
- [x] 通过 JSON Schema test suite,包括可选的(部分跳过的如下)
- (可选)none of the properties mentioned
- (可选)valid leap second, large positive time-offset
- (可选)valid leap second, large negative time-offset
- (可选)a float is not an integer even without fractional part
- (可选)refs to future drafts are processed as future drafts
- (可选)format is iri, iri-reference, idn-email.json,idn-hostname
- [x] 基于词汇的验证
- [x] format assertions
- [x] flag to enable in draft <= 7
- [ ] 自定义 format
- [ ] 内置 format
- [x] regex, uuid
- [x] ipv4, ipv6
- [x] hostname, email
- [ ] idn-hostname, idn-email
- [x] date, time, date-time
- [x] json-pointer, relative-json-pointer
- [x] uri, uri-reference, uri-template
- [ ] iri, iri-reference
- [ ] period
- [x] content assertions
- [x] flag to enable in draft <= 7
- [x] contentEncoding
- [x] base64
- [ ] 自定义
- [x] contentMediaType
- [x] application/json
- [ ] 自定义
- [ ] contentSchema
- [ ] custom vocabulary
- [x] 引用的 schema 的可以是不同的 draft
- [x] 对 schema 更严格的检查
- [x] default
- [x] examples
- [x] ref
- [x] format

## Installation

```shell
npm install --save @frog4js/schema
```

## Quick Usage

```javascript
import { contextManage } from "@frog4js/schema/context";
import { schemaManage } from "@frog4js/schema/schema";
import { vocabularyActuatorManage } from "@frog4js/schema/vocabulary-actuator";

const context = contextManage.create();
schemaManage.setMainSchema(context, {
type: "object",
});
schemaManage.compile(context);
console.log(vocabularyActuatorManage.validate(context, 1));
```

## 后续

- 进行性能测试并优化性能
- 支持 draft-2019-09, draft-2020-12
- 完善 error
- 支持剩余的 format
- 检测无限循环陷阱
- 自定义 format, vocabulary-actuator
- 完善文档

## API Reference

### contextManage

主要是用来创建 Context, Context 是用来挂载各种数据(如 schema,instance,errors 等等), 是执行过程的上下文数据。

#### contextManage.create(defaultConfig?: DefaultConfig) => Context

创建上下文, defaultConfig 是默认的一些配置。

### schemaManage

可以设置 main schema 和 ref schema。

#### schemaManage.addReferenceSchema: (context: Context, schema: Schema) => void;

添加被引用的 schema

#### schemaManage.setMainSchema: (context: Context, schema: Schema) => void;

设置 main schema

#### schemaManage.compile: () => void;

完成设置, 这里会检查$ref 指定的 schema 是否存在, 同时将禁止再修改 schema 相关的数据了

### vocabularyActuatorManage

验证 instance 是否符合 schema 的要求

#### vocabularyActuatorManage.validate: (context: Context,instance: any,locale?: string) => {errors: ExecuteError[];valid: boolean;};

验证通过 valid 为 true, 否则为 false, 同时 errors 中为具体失败的原因

## Struct Definition

### Context

```ts
export type Context = {
errors: Array;
locks: Array<{
paths: Array;
errors: Array;
}>;
caches: Array<{
schemaPaths: Array;
instancePaths: Array;
data: Record;
}>;
startTime: number;
endTime: number;
instancePaths: Array;
schemaPaths: Array;
version: number;
schemaData: {
origin?: Schema;
main?: Schema;
current?: RefData;
};
instanceData: {
origin?: any;
current?: RefData;
locale?: string;
};
referenceSchemas: Record;
defaultConfig: DefaultConfig;
state: number;
phase?: number;
waitValidateRefs: {
$ref: string;
schema: Schema;
}[];
};
```

### DefaultConfig

```ts
export type DefaultConfig = {
$schema?: string;
baseURI?: string;
errorMessages?: Record>;
locale?: string;
strict?: boolean;
};
```

### Schema

```ts
type Reference = { $ref: string };
type CoreV3 = {
id?: string;
};

type BasicTypeV3 = "string" | "boolean" | "array" | "object" | "integer" | "null" | "any" | "number";
type BasicTypeV4 = "string" | "boolean" | "array" | "object" | "integer" | "null" | "number";
// ============= v1
type ValidationV1 = {
type?: BasicTypeV3 | Array;
default?: any;
optional?: boolean;
properties?: Record;
items?: ChildSchemaV1 | Array;
additionalProperties?: boolean | ChildSchemaV1;
requires?: string | ChildSchemaV1;
minimum?: number;
maximum?: number;
minimumCanEqual?: boolean;
maximumCanEqual?: boolean;
minItems?: number;
maxItems?: number;
format?: string;
pattern?: string;
maxLength?: number;
minLength?: number;
enum?: Array;
title?: string;
description?: string;
contentEncoding?: string;
maxDecimal?: number;
disallow?: BasicTypeV3 | Array;
};
type ChildSchemaV1 = ValidationV1 | Reference;
type SchemaV1 = CoreV3 & ValidationV1 & { $schema: "http://json-schema.org/draft-01/schema#" };
// ============= v1

// ============= v2
type ValidationV2 = Exclude & {
type?: BasicTypeV3 | Array;
properties?: Record;
items?: ChildSchemaV2 | Array;
additionalProperties?: boolean | ChildSchemaV2;
requires?: string | ChildSchemaV2;
divisibleBy?: number;
uniqueItems?: boolean;
};
type ChildSchemaV2 = ValidationV2 | Reference;
type SchemaV2 = CoreV3 & ValidationV2 & { $schema: "http://json-schema.org/draft-01/schema#" };
// ============= v2

// ============= v3
type ValidationV3 = Exclude & {
type?: BasicTypeV3 | Array;
properties?: Record;
items?: ChildSchemaV3 | Array;
additionalProperties?: boolean | ChildSchemaV3;
requires?: string | ChildSchemaV3;
additionalItems?: boolean | ChildSchemaV3;
patternProperties?: Record;
dependencies?: Record | ChildSchemaV3>;
exclusiveMinimum?: boolean;
exclusiveMaximum?: boolean;
};
type ChildSchemaV3 = ValidationV3 | Reference;
type SchemaV3 = CoreV3 & ValidationV3 & { $schema: "http://json-schema.org/draft-01/schema#" };
// ============= v3

// ============= v4
type CoreV4 = {
id?: string;
definitions?: Record;
};
type ValidationV4 = Exclude & {
type?: BasicTypeV4 | Array;
properties?: Record;
items?: ChildSchemaV4 | Array;
additionalProperties?: boolean | ChildSchemaV4;
additionalItems?: boolean | ChildSchemaV4;
patternProperties?: Record;
dependencies?: Record | ChildSchemaV4>;
anyOf?: Array;
oneOf?: Array;
allOf?: Array;
requires?: Array;
minProperties?: number;
maxProperties?: number;
multipleOf?: number;
};
type ChildSchemaV4 = ValidationV4 | Reference;
type SchemaV4 = CoreV4 & ValidationV4 & { $schema: "http://json-schema.org/draft-04/schema#" };
// ============= v4

// ============= v5
type SchemaV5 = CoreV4 & ValidationV4 & { $schema: "http://json-schema.org/draft-05/schema#" };
// ============= v5

// ============= v6
type CoreV6 = {
$id?: string;
definitions?: Record;
};
type ValidationV6 = ValidationV4 & {
properties?: Record;
items?: ChildSchemaV6 | Array;
additionalProperties?: boolean | ChildSchemaV6;
additionalItems?: boolean | ChildSchemaV6;
patternProperties?: Record;
dependencies?: Record | ChildSchemaV6>;
anyOf?: Array;
oneOf?: Array;
allOf?: Array;
propertyNames?: ChildSchemaV6;
const?: any;
examples?: Array;
exclusiveMinimum?: number;
exclusiveMaximum?: number;
};
type ChildSchemaV6 = ValidationV6 | Reference | boolean;
type SchemaV6 = CoreV6 & ValidationV6 & { $schema: "http://json-schema.org/draft-06/schema#" };
// ============= v6

// ============= v7
type CoreV7 = {
$schema?: "http://json-schema.org/draft-07/schema#";
$id?: string;
definitions?: Record;
};
type ValidationV7 = ValidationV6 & {
properties?: Record;
items?: ChildSchemaV7 | Array;
additionalProperties?: boolean | ChildSchemaV7;
additionalItems?: boolean | ChildSchemaV7;
patternProperties?: Record;
dependencies?: Record | ChildSchemaV7>;
anyOf?: Array;
oneOf?: Array;
allOf?: Array;
propertyNames?: ChildSchemaV7;
if?: boolean | ChildSchemaV7;
then?: boolean | ChildSchemaV7;
else?: boolean | ChildSchemaV7;
};
type ChildSchemaV7 = ValidationV7 | Reference | boolean;
type SchemaV7 = CoreV7 & ValidationV7;
// ============= v7
export type Schema = SchemaV1 | SchemaV2 | SchemaV3 | SchemaV4 | SchemaV5 | SchemaV6 | SchemaV7;
```

### Error

```ts
export type ExecuteError = {
instancePath: string;
schemaPath: string;
currentSchemaKey: string;
currentSchemaValue: any;
currentInstanceKey: string;
currentInstanceValue: any;
message: string;
};
```