@aomex/core
Advanced tools
Comparing version 0.0.21 to 0.0.22
121
CHANGELOG.md
# @aomex/core | ||
## 0.0.21 | ||
## 0.0.22 | ||
### Patch Changes | ||
- Updated dependencies [[`e9996cb`](https://github.com/aomex/aomex/commit/e9996cb33cc0ef70b42147be02fbbe2b4954e022)]: | ||
- @aomex/validator@0.0.18 | ||
- [`6f7d706`](https://github.com/aomex/aomex/commit/6f7d7066c23711abdd149eb1c9a293ab8c4284a4) Thanks [@geekact](https://github.com/geekact)! - feat(core): validator增加严格模式 | ||
## 0.0.20 | ||
- [`e7bf93c`](https://github.com/aomex/aomex/commit/e7bf93cee6896c61d0bf3eb0921151dc6c1bc107) Thanks [@geekact](https://github.com/geekact)! - chore(core): 升级依赖 lru-cache 9.0.0 -> 10.0.0 | ||
chore(core): 升级依赖 glob 10.0.0 -> 10.3.3 | ||
chore(core): 升级依赖 chalk 5.2.0 -> 5.3.0 | ||
### Patch Changes | ||
- [`ddcec91`](https://github.com/aomex/aomex/commit/ddcec91803b00f35f7c55964d1a2d97c40a22c6e) Thanks [@geekact](https://github.com/geekact)! - chore(core): minimum node version is 16.14.0 | ||
## 0.0.19 | ||
### Patch Changes | ||
- Updated dependencies [[`43e3481`](https://github.com/aomex/aomex/commit/43e3481ff4edab59642b27527beb72e282b1768c), [`6cbc69b`](https://github.com/aomex/aomex/commit/6cbc69bfce9d03b4880b94f9ec0ee20c9ae937a8), [`db8c690`](https://github.com/aomex/aomex/commit/db8c690ee820dac86ef5274b544fe49f3ca41d10)]: | ||
- @aomex/cache@0.0.8 | ||
- @aomex/utility@0.0.7 | ||
- @aomex/middleware@0.0.8 | ||
- @aomex/validator@0.0.17 | ||
## 0.0.18 | ||
### Patch Changes | ||
- Updated dependencies [[`9ec29cd`](https://github.com/aomex/aomex/commit/9ec29cd492014431b12f542d487a1ae282fe473f)]: | ||
- @aomex/validator@0.0.16 | ||
## 0.0.17 | ||
### Patch Changes | ||
- Updated dependencies [[`37946d2`](https://github.com/aomex/aomex/commit/37946d2b91a560c851fa21fa327b5b968b794862)]: | ||
- @aomex/utility@0.0.6 | ||
- @aomex/middleware@0.0.7 | ||
- @aomex/validator@0.0.15 | ||
## 0.0.16 | ||
### Patch Changes | ||
- Updated dependencies [[`326c1d2`](https://github.com/aomex/aomex/commit/326c1d2a7113b2768040e1c767fe7b9ab2bd34ae), [`216aa79`](https://github.com/aomex/aomex/commit/216aa798bcd2d0856f5fe4028235aa54d4b10922), [`0e120f8`](https://github.com/aomex/aomex/commit/0e120f824f8e6c474e65a5d2b89a1849f3713aaf)]: | ||
- @aomex/validator@0.0.14 | ||
- @aomex/middleware@0.0.6 | ||
## 0.0.15 | ||
### Patch Changes | ||
- Updated dependencies [[`9881653`](https://github.com/aomex/aomex/commit/988165361439738d27bc29bd0ed5a85c608db5ef), [`ab18463`](https://github.com/aomex/aomex/commit/ab1846384f784aeb63d50f6be7778802117c94d5), [`accbb60`](https://github.com/aomex/aomex/commit/accbb606beadbbb02bdcf5512a0af2fb221db608), [`62cb525`](https://github.com/aomex/aomex/commit/62cb5251d4c482fd4dc1823c3cfabaea1eeae677), [`15ecd1c`](https://github.com/aomex/aomex/commit/15ecd1c75bc21929f79980b32e63ea46e081cc6a)]: | ||
- @aomex/validator@0.0.13 | ||
## 0.0.14 | ||
### Patch Changes | ||
- Updated dependencies [[`bf2c963`](https://github.com/aomex/aomex/commit/bf2c9639a609402be2ff094ceabe4fd2231214f8), [`e3b1be4`](https://github.com/aomex/aomex/commit/e3b1be4d02793001d441a1f1b1ced060e95b4f8a)]: | ||
- @aomex/cache@0.0.7 | ||
## 0.0.13 | ||
### Patch Changes | ||
- Updated dependencies [[`0b98122`](https://github.com/aomex/aomex/commit/0b9812229a950b7d2a8d1ed337a276a3bae62c15)]: | ||
- @aomex/validator@0.0.12 | ||
## 0.0.12 | ||
### Patch Changes | ||
- Updated dependencies [[`24790bc`](https://github.com/aomex/aomex/commit/24790bcf57f1ebfae25547189895b9a55894914f)]: | ||
- @aomex/validator@0.0.11 | ||
## 0.0.11 | ||
### Patch Changes | ||
- [`92273f9`](https://github.com/aomex/aomex/commit/92273f913e38543f34f41ec5941ff43b6e1caaa9) Thanks [@geekact](https://github.com/geekact)! - chore(core): upgrade typescript to 5.0 in peerDependencies | ||
- Updated dependencies [[`827b86d`](https://github.com/aomex/aomex/commit/827b86d692786b5708c8602e5985eedabf632981), [`d75d6f1`](https://github.com/aomex/aomex/commit/d75d6f108c6ac75a3d1b8c843b75b872071ea663), [`cc01922`](https://github.com/aomex/aomex/commit/cc019228eb3dca43e354467d60c744103424e47b), [`b1974a9`](https://github.com/aomex/aomex/commit/b1974a94eb75c9d26c3f5d466da4081973705429), [`abf846b`](https://github.com/aomex/aomex/commit/abf846b5e09f8afe23efe844201734122af2cb73), [`944b767`](https://github.com/aomex/aomex/commit/944b7679016ff5a9ba31bbb9c7cc556a776d5101)]: | ||
- @aomex/cache@0.0.6 | ||
- @aomex/validator@0.0.10 | ||
## 0.0.10 | ||
### Patch Changes | ||
- Updated dependencies [[`9f17222`](https://github.com/aomex/aomex/commit/9f172222843f92b67a839d872105d0b7f04661fb)]: | ||
- @aomex/validator@0.0.9 | ||
## 0.0.9 | ||
### Patch Changes | ||
- Updated dependencies [[`fbb7ab2`](https://github.com/aomex/aomex/commit/fbb7ab2e6ec2a18e7ad8f018788523952049b6fd)]: | ||
- @aomex/utility@0.0.5 | ||
- @aomex/middleware@0.0.5 | ||
- @aomex/validator@0.0.8 | ||
## 0.0.8 | ||
### Patch Changes | ||
- Updated dependencies [[`cba047e`](https://github.com/aomex/aomex/commit/cba047ecb496da6269aed3f58f6e316a3444c939), [`bdbf43a`](https://github.com/aomex/aomex/commit/bdbf43afcbc198a9ae97137022c6914f1a89a477), [`5092841`](https://github.com/aomex/aomex/commit/5092841c6b8a998e8648a1119d7e1ceb8534297d), [`9c0bb28`](https://github.com/aomex/aomex/commit/9c0bb285d25594310e5450634223100a01bf1b5d)]: | ||
- @aomex/validator@0.0.7 | ||
- @aomex/cache@0.0.5 | ||
## 0.0.6 | ||
### Patch Changes | ||
- [`bbc8dda`](https://github.com/aomex/aomex/commit/bbc8dda9f0876c3402608133085350cc693def6f) Thanks [@geekact](https://github.com/geekact)! - refactor: rename package helper to utility | ||
- Updated dependencies [[`bbc8dda`](https://github.com/aomex/aomex/commit/bbc8dda9f0876c3402608133085350cc693def6f), [`ceb2d82`](https://github.com/aomex/aomex/commit/ceb2d8269755dca3f79b755224259b8a99bc65d0)]: | ||
- @aomex/middleware@0.0.4 | ||
- @aomex/validator@0.0.5 | ||
- @aomex/utility@0.0.4 | ||
- @aomex/cache@0.0.3 | ||
- [`818e840`](https://github.com/aomex/aomex/commit/818e840d36c7456a863fc071968b246c123c17f5) Thanks [@geekact](https://github.com/geekact)! - refactor(core): 对象使用统一逻辑转换成验证器 |
@@ -1,4 +0,871 @@ | ||
export * from '@aomex/middleware'; | ||
export * from '@aomex/validator'; | ||
export * from '@aomex/openapi-type'; | ||
export * from '@aomex/cache'; | ||
export { default as chalk } from 'chalk'; | ||
export { default as bytes } from 'bytes'; | ||
import { OpenAPIV3 } from 'openapi-types'; | ||
export { OpenAPIV3 as OpenAPI } from 'openapi-types'; | ||
import { LRUCache } from 'lru-cache'; | ||
declare function toArray<T>(data: T | readonly T[], unique?: boolean): T[]; | ||
declare function toArray<T>(data: T | T[], unique?: boolean): T[]; | ||
declare const sleep: (ms: number) => Promise<void>; | ||
type NonReadonly<T extends object> = { | ||
-readonly [K in keyof T]: T[K]; | ||
}; | ||
type Union2Intersection<T> = (T extends any ? (arg: T) => void : never) extends (arg: infer P) => void ? P : never; | ||
interface _PureFn { | ||
<Props extends object = object>(fn: (ctx: NonReadonly<Props>, next: Next) => any): PureMiddleware<Props>; | ||
} | ||
declare class PureMiddleware<Props extends object = object> extends Middleware<Props> { | ||
protected _pure_middleware_: 'pure-middleware'; | ||
} | ||
interface MiddlewarePlatform { | ||
/** | ||
* 没有特定上下文的纯中间件,支持所有应用 | ||
*/ | ||
readonly pure: _PureFn; | ||
} | ||
declare namespace Middleware { | ||
type Infer<T> = T extends Middleware<infer R> ? R : T extends (...args: any[]) => Middleware<infer R> ? R : never; | ||
type Fn<Ctx = any> = (ctx: Ctx, next: Next) => any; | ||
} | ||
/** | ||
* 中间件基类 | ||
*/ | ||
declare abstract class Middleware<Props extends object = object> { | ||
readonly fn: Middleware.Fn; | ||
protected _props_must_be_used_: Props; | ||
constructor(fn: Middleware.Fn); | ||
/** | ||
* 注册中间件 | ||
*/ | ||
static register(platform: keyof MiddlewarePlatform, SubMiddleware: new (...args: any[]) => Middleware): void; | ||
} | ||
declare const middleware: MiddlewarePlatform; | ||
type PureMiddlewareToken<P extends object = object> = PureChain<P> | PureMiddleware<P>; | ||
declare class PureChain<Props extends object = object> extends Chain<Props> { | ||
protected _pure_chain_: 'pure-chain'; | ||
mount: { | ||
<P extends object>(middleware: PureMiddlewareToken<P> | null): PureChain<Props & P>; | ||
}; | ||
} | ||
type MiddleWareToken<P extends object = object> = Chain<P> | Middleware<P>; | ||
interface ChainPlatform { | ||
/** | ||
* 没有特定上下文的纯链条,支持所有应用 | ||
*/ | ||
readonly pure: PureChain; | ||
} | ||
declare abstract class Chain<Props extends object = object> { | ||
protected readonly middlewareList: Middleware[]; | ||
protected static autoIncrementID: number; | ||
/** | ||
* 注册链条 | ||
*/ | ||
static register(platform: keyof ChainPlatform, SubChain: new (...args: any[]) => Chain): void; | ||
/** | ||
* 平坦中间件和链条,并返回中间件列表 | ||
*/ | ||
static flatten(middleware?: MiddleWareToken | null | Array<MiddleWareToken | null>): Middleware[]; | ||
static createSplitPoint(chain: Chain): string; | ||
/** | ||
* 分割链条成两段,并返回后面那一段 | ||
*/ | ||
static split(chain: Chain, point?: string | string[]): Chain<object>; | ||
protected readonly SubClass: new (middlewareList?: Middleware[]) => Chain; | ||
protected points: Record<string, number>; | ||
constructor(middlewareList?: Middleware[]); | ||
/** | ||
* 挂载中间件和链条,支持传入`null` | ||
*/ | ||
protected mount<P extends object>(middleware: MiddleWareToken<P> | null): Chain<Props & P>; | ||
} | ||
declare const chain: ChainPlatform; | ||
type Next = () => Promise<any>; | ||
type Compose = (ctx: any, next?: Next) => Promise<any>; | ||
/** | ||
* 组合中间件和链条 | ||
*/ | ||
declare const compose: (tokens: MiddleWareToken[]) => Compose; | ||
declare namespace magistrate { | ||
type Result<T> = Ok<T> | Fail; | ||
interface Ok<T> { | ||
ok: T; | ||
} | ||
interface Fail { | ||
errors: { | ||
path: string[]; | ||
message: string; | ||
}[]; | ||
} | ||
} | ||
declare const magistrate: { | ||
ok: <T>(result: T) => magistrate.Ok<T>; | ||
fail: (message: string, key: string, superKeys: string[]) => magistrate.Fail; | ||
noError: <T_1>(result: magistrate.Result<T_1>) => result is magistrate.Ok<T_1>; | ||
}; | ||
interface TransformedValidator<T> extends Validator<T> { | ||
} | ||
declare namespace Validator { | ||
class TDefault { | ||
private _DEF_; | ||
} | ||
class TOptional { | ||
private _OPT_; | ||
} | ||
class TObject { | ||
private _OBJ_; | ||
} | ||
type ConvertOptional<T> = TDefault extends T ? ConvertOptionalToNever<T> : ConvertOptionalToUndefined<T>; | ||
type ConvertOptionalToUndefined<T> = T extends TOptional ? undefined : T extends TDefault ? never : T extends TObject ? object : T; | ||
type ConvertOptionalToNever<T> = T extends TOptional | TDefault ? never : T extends TObject ? object : T; | ||
interface TransformFn<T, T1> { | ||
(data: ConvertOptional<T>): Promise<T1> | T1; | ||
} | ||
type ParameterOrFn<T> = ConvertOptionalToNever<T> | (() => ConvertOptionalToNever<T>); | ||
type Infer<T> = T extends Validator<infer Type> ? Validator.ConvertOptional<Type> : never; | ||
type PartialOpenAPISchema = Pick<OpenAPIV3.SchemaObject, 'title' | 'description' | 'deprecated' | 'example' | 'externalDocs'>; | ||
type DocumentMergeMode = 'merge' | 'replace'; | ||
interface Options<Type> { | ||
defaultValue?: Type | (() => Type); | ||
required: boolean; | ||
nullable: boolean; | ||
transform?: (value: any) => Promise<any> | any; | ||
docs?: PartialOpenAPISchema; | ||
strict: boolean; | ||
} | ||
} | ||
declare abstract class Validator<T = unknown> { | ||
static $rootKey: string; | ||
protected readonly SubClass: new (...args: any[]) => Validator; | ||
constructor(); | ||
protected readonly config: Validator.Options<T>; | ||
static toDocument(validator: Validator): OpenAPIV3.ParameterBaseObject; | ||
/** | ||
* 设置严格模式,数据不再做兼容性处理。默认值:`true` | ||
*/ | ||
strict(is?: boolean): this; | ||
/** | ||
* 扩展openapi的配置 | ||
* - **replace:** 本次设置直接覆盖原来的扩展配置 | ||
* - **merge:** 本次设置通过`Object.assign`的形式合并到原来的扩展配置 | ||
* @param mode 默认值:`merge` | ||
*/ | ||
protected docs(docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode): this; | ||
/** | ||
* 值如果是 `undefined, null, ''`或者没传入,以上情况会直接转换成`undefined` | ||
* | ||
* 注意:如果执行了`default(...)`,则无需再执行`optional()` | ||
* | ||
* 注意:如果设置了`nullable()`,则`null`不做处理 | ||
*/ | ||
protected optional(): Validator; | ||
/** | ||
* 把`null`识别成合法的值 | ||
* @see optional | ||
*/ | ||
protected nullable(): Validator; | ||
/** | ||
* 数据验证成功最后会触发该方法,你可以把数据转换成任何格式 | ||
* ```typescript | ||
* // 最终返回类型:string | ||
* rule.string() | ||
* // 最终返回类型:Array<string> | ||
* rule.string().transform((value) => [value]) | ||
* ``` | ||
*/ | ||
protected transform<T1>(fn: (value: any) => Promise<T1> | T1): Validator; | ||
/** | ||
* 如果值为空或者没传入,则使用该默认值,而且无需验证 | ||
* | ||
* 注意:如果执行了`default(...)`,则无需再执行`optional()` | ||
*/ | ||
protected default(value: any): Validator; | ||
protected validate(value: any, key?: string, superKeys?: string[]): Promise<magistrate.Result<any>>; | ||
protected isEmpty(value: any): boolean; | ||
protected isValidNull(value: any): boolean; | ||
protected getDefaultValue<T = any>(value: any): T | undefined; | ||
protected abstract validateValue(value: any, key: string, superKeys: string[]): Promise<magistrate.Result<any>> | magistrate.Result<any>; | ||
protected copy(): Validator; | ||
protected copyConfig(prev: Validator): this; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace BaseNumberValidator { | ||
interface Options<T = false> extends Validator.Options<T> { | ||
min?: number; | ||
minInclusive?: boolean; | ||
max?: number; | ||
maxInclusive?: boolean; | ||
onlyInteger?: boolean; | ||
precision?: number; | ||
} | ||
} | ||
declare abstract class BaseNumberValidator<T = number> extends Validator<T> { | ||
protected config: BaseNumberValidator.Options<T>; | ||
min(min: number, inclusive?: boolean): this; | ||
max(max: number, inclusive?: boolean): this; | ||
protected validateValue(num: number, key: string, superKeys: string[]): magistrate.Result<number>; | ||
protected copy: () => BaseNumberValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
interface LengthRange { | ||
min?: number; | ||
max?: number; | ||
} | ||
interface MixinLength { | ||
length(exactLength: number): this; | ||
length(min: number, max: number): this; | ||
length(range: LengthRange): this; | ||
} | ||
declare function mixinLength<T extends Validator>(validator: new (...args: any[]) => MixinLength & T, configKey?: string): void; | ||
declare namespace BaseStringValidator { | ||
interface Options<T> extends Validator.Options<T> { | ||
trim?: boolean; | ||
pattern?: RegExp; | ||
lengthRange?: LengthRange; | ||
} | ||
} | ||
declare abstract class BaseStringValidator<T = string> extends Validator<T> { | ||
protected config: BaseStringValidator.Options<T>; | ||
/** | ||
* 删除两边空格后再进行验证 | ||
*/ | ||
trim(): this; | ||
protected match(pattern: RegExp): this; | ||
protected isEmpty(value: any): boolean; | ||
protected getTrimValue(value: string): string; | ||
protected shouldMatchPattern(value: string, key: string, superKeys: string[]): magistrate.Result<string> | void; | ||
protected shouldBetweenLength(value: string, key: string, superKeys: string[]): magistrate.Result<string> | void; | ||
protected shouldBeString(value: string, key: string, superKeys: string[]): magistrate.Result<string> | void; | ||
protected copy: () => BaseStringValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare class ValidatorError extends Error { | ||
} | ||
type ValidateOptions = { | ||
throwIfError?: true; | ||
} | { | ||
throwIfError: false; | ||
}; | ||
declare function validate<T extends Validator>(source: any, validator: T, options?: { | ||
throwIfError?: true; | ||
}): Promise<Validator.Infer<T>>; | ||
declare function validate<T extends Validator>(source: any, validator: T, options?: { | ||
throwIfError: false; | ||
}): Promise<magistrate.Result<Validator.Infer<T>>>; | ||
declare function validate<T extends { | ||
[key: string]: V; | ||
}, V extends Validator>(source: object | Promise<object>, validators: T, options?: { | ||
throwIfError?: true; | ||
}): Promise<{ | ||
[K in keyof T]: Validator.Infer<T[K]>; | ||
}>; | ||
declare function validate<T extends { | ||
[key: string]: V; | ||
}, V extends Validator>(source: object | Promise<object>, validators: T, options?: { | ||
throwIfError: false; | ||
}): Promise<magistrate.Result<{ | ||
[K in keyof T]: Validator.Infer<T[K]>; | ||
}>>; | ||
declare namespace AnyValidator { | ||
type Type = number | string | boolean | any[] | Validator.TObject | bigint | Buffer; | ||
} | ||
declare class AnyValidator<T = AnyValidator.Type> extends Validator<T> { | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => AnyValidator<T | Validator.TOptional>; | ||
nullable: () => AnyValidator<T | null>; | ||
default: (anyValue: Validator.ParameterOrFn<T>) => AnyValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected validateValue(value: any): magistrate.Result<any>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace ArrayValidator { | ||
interface ForceOptions { | ||
filter?: (value: any) => boolean; | ||
formatter?: (value: any) => any[]; | ||
/** | ||
* 遇到字符串则使用逗号(`/ \s*,\s* /`)分割 | ||
* | ||
* 示例:'aa,bb, cc,' => ['aa', 'bb', 'cc', ''] | ||
*/ | ||
stringCommaSeparator?: true; | ||
/** | ||
* 遇到字符串使用特定分隔符。如果是逗号,可以直接设置`stringCommaSeparator: true` | ||
*/ | ||
stringSeparator?: string | RegExp; | ||
} | ||
interface Options<T> extends Validator.Options<T> { | ||
itemValidator?: Validator; | ||
lengthRange: { | ||
min?: number; | ||
max?: number; | ||
}; | ||
force: boolean | ForceOptions; | ||
} | ||
} | ||
declare class ArrayValidator<T = unknown[]> extends Validator<T> { | ||
protected config: ArrayValidator.Options<T>; | ||
constructor(validator?: Validator); | ||
strict(is?: boolean): this; | ||
/** | ||
* 强制将`非数组`的值转换成数组类型。 | ||
* | ||
* 控制台命令行和url查询字符串场景下,如果只传了一个元素,则有可能被识别为非数组,而传递多个元素时又变成了数组结构。 | ||
* | ||
* ```typescript | ||
* rule.array().forceToArray() | ||
* // 允许针对特定值进行转换 | ||
* rule.array().forceToArray({ | ||
* filter: (value) => typeof value === 'string' | ||
* }) | ||
* // 最常用的字符串逗号分割符 | ||
* rule.array().forceToArray({ stringCommaSeparator: true }) | ||
* // 字符串使用自定义分割符 | ||
* rule.array().forceToArray({ stringSeparator: '-' }) | ||
* ``` | ||
*/ | ||
forceToArray(options?: ArrayValidator.ForceOptions): ArrayValidator<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => ArrayValidator<T | Validator.TOptional>; | ||
nullable: () => ArrayValidator<T | null>; | ||
default: (array: Validator.ParameterOrFn<T>) => ArrayValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected validateValue(value: any, key: string, superKeys: string[]): Promise<magistrate.Result<any[]>>; | ||
protected copy: () => ArrayValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
interface ArrayValidator extends MixinLength { | ||
} | ||
declare class BigIntValidator<T = bigint> extends Validator<T> { | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => BigIntValidator<T | Validator.TOptional>; | ||
nullable: () => BigIntValidator<T | null>; | ||
default: (value: bigint) => BigIntValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected validateValue(value: bigint, key: string, superKeys: string[]): magistrate.Result<bigint>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace BooleanValidator { | ||
interface Options<T> extends Validator.Options<T> { | ||
trueValues?: any[]; | ||
falseValues?: any[]; | ||
} | ||
} | ||
declare class BooleanValidator<T = boolean> extends Validator<T> { | ||
protected config: BooleanValidator.Options<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => BooleanValidator<T | Validator.TOptional>; | ||
nullable: () => BooleanValidator<T | null>; | ||
default: (boolValue: boolean) => BooleanValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
/** | ||
* 重新设置真值。默认值:`[1, '1', true, 'true']` | ||
* ```typescript | ||
* boolean.trueValues([true, 'yes']); | ||
* boolean.trueValues([true, 'on', 'good']); | ||
* ``` | ||
*/ | ||
trueValues(values: any[]): BooleanValidator<T>; | ||
/** | ||
* 重新设置假值。默认值:`[0, '0', false, 'false']` | ||
* ```typescript | ||
* boolean.falseValues([false, 'no']); | ||
* boolean.falseValues([false, 'off', 'bad']); | ||
* ``` | ||
*/ | ||
falseValues(values: any[]): BooleanValidator<T>; | ||
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<boolean>; | ||
protected copy: () => BooleanValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace BufferValidator { | ||
interface Options<T = Buffer> extends Validator.Options<T> { | ||
} | ||
} | ||
declare class BufferValidator<T = Buffer> extends Validator<T> { | ||
protected config: BufferValidator.Options<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => BufferValidator<T | Validator.TOptional>; | ||
nullable: () => BufferValidator<T | null>; | ||
default: (buffer: Buffer) => BufferValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<Buffer>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace EmailValidator { | ||
interface Options<T> extends BaseStringValidator.Options<T> { | ||
lengthRange?: LengthRange; | ||
} | ||
} | ||
declare class EmailValidator<T = string> extends BaseStringValidator<T> { | ||
protected config: EmailValidator.Options<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => EmailValidator<T | Validator.TOptional>; | ||
nullable: () => EmailValidator<T | null>; | ||
default: (email: Validator.ParameterOrFn<T>) => EmailValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
match: (pattern: RegExp) => this; | ||
protected validateValue(email: string, key: string, superKeys: string[]): magistrate.Result<string>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
interface EmailValidator extends MixinLength { | ||
} | ||
declare namespace EnumValidator { | ||
interface Options<T> extends Validator.Options<T> { | ||
ranges: T[]; | ||
} | ||
} | ||
declare class EnumValidator<T = never> extends Validator<T> { | ||
protected config: EnumValidator.Options<T>; | ||
constructor(ranges?: T[]); | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => EnumValidator<T | Validator.TOptional>; | ||
nullable: () => EnumValidator<T | null>; | ||
default: (value: Validator.ParameterOrFn<T>) => EnumValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<any>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace HashValidator { | ||
type Algorithm = keyof typeof HashValidator.algorithmLength; | ||
interface Options<T> extends BaseStringValidator.Options<T> { | ||
algorithm: HashValidator.Algorithm; | ||
} | ||
} | ||
declare class HashValidator<T = string> extends BaseStringValidator<T> { | ||
/** | ||
* @see https://github.com/validatorjs/validator.js | ||
*/ | ||
static algorithmLength: { | ||
readonly md5: 32; | ||
readonly md4: 32; | ||
readonly sha1: 40; | ||
readonly sha256: 64; | ||
readonly sha384: 96; | ||
readonly sha512: 128; | ||
readonly ripemd128: 32; | ||
readonly ripemd160: 40; | ||
readonly tiger128: 32; | ||
readonly tiger160: 40; | ||
readonly tiger192: 48; | ||
readonly crc32: 8; | ||
readonly crc32b: 8; | ||
}; | ||
static algorithmPattern: Record<string, RegExp>; | ||
protected config: HashValidator.Options<T>; | ||
constructor(algorithm: HashValidator.Algorithm); | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => HashValidator<T | Validator.TOptional>; | ||
nullable: () => HashValidator<T | null>; | ||
default: (algorithm: Validator.ParameterOrFn<T>) => HashValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected validateValue(hash: string, key: string, superKeys: string[]): magistrate.Result<string>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare class IntValidator<T = number> extends BaseNumberValidator<T> { | ||
protected config: BaseNumberValidator.Options<T>; | ||
constructor(); | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => IntValidator<T | Validator.TOptional>; | ||
nullable: () => IntValidator<T | null>; | ||
default: (integer: Validator.ParameterOrFn<T>) => IntValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare const versions: readonly ["v4", "v6"]; | ||
declare namespace IpValidator { | ||
type Version = (typeof versions)[number]; | ||
interface Options<T> extends BaseStringValidator.Options<T> { | ||
ipVersion: IpValidator.Version[]; | ||
} | ||
} | ||
declare class IpValidator<T = string> extends BaseStringValidator<T> { | ||
static patterns: { | ||
[key in IpValidator.Version | 'all']: RegExp; | ||
}; | ||
protected config: IpValidator.Options<T>; | ||
constructor(version: IpValidator.Version[]); | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => IpValidator<T | Validator.TOptional>; | ||
nullable: () => IpValidator<T | null>; | ||
default: (ip: Validator.ParameterOrFn<T>) => IpValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
match: (pattern: RegExp) => this; | ||
protected validateValue(ip: string, key: string, superKeys: string[]): magistrate.Result<string>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare class NumberValidator<T = number> extends BaseNumberValidator<T> { | ||
protected config: BaseNumberValidator.Options<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => NumberValidator<T | Validator.TOptional>; | ||
nullable: () => NumberValidator<T | null>; | ||
default: (number: Validator.ParameterOrFn<T>) => NumberValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
precision(maxDecimals: number): NumberValidator<T>; | ||
protected copy: () => NumberValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace ObjectValidator { | ||
type Property = Record<string, Validator>; | ||
interface Options<T> extends Validator.Options<T> { | ||
properties?: Property; | ||
stringToObject?: boolean; | ||
} | ||
} | ||
declare class ObjectValidator<T = Validator.TObject> extends Validator<T> { | ||
protected config: ObjectValidator.Options<T>; | ||
constructor(properties?: ObjectValidator.Property); | ||
strict(is?: boolean): this; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => ObjectValidator<T | Validator.TOptional>; | ||
nullable: () => ObjectValidator<T | null>; | ||
default: (object: Validator.ParameterOrFn<T>) => ObjectValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
/** | ||
* 如果是字符串,则尝试使用`JSON.parse`转换为对象。默认值:`false` | ||
*/ | ||
parseFromString(is?: boolean): ObjectValidator<T>; | ||
protected isPlainObject(value: any): value is object; | ||
protected validateValue(origin: Record<string, any>, key: string, superKeys: string[]): Promise<magistrate.Result<object>>; | ||
protected copy: () => ObjectValidator<T>; | ||
protected copyConfig(prev: ObjectValidator): this; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace OneOfValidator { | ||
interface Options<T> extends Validator.Options<T> { | ||
validators: Validator[]; | ||
} | ||
} | ||
declare class OneOfValidator<T = never> extends Validator<T> { | ||
protected config: OneOfValidator.Options<T>; | ||
constructor(rules: Validator[]); | ||
strict(is?: boolean): this; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
protected isEmpty(_: any): boolean; | ||
protected validateValue(value: any, key: string, superKeys: string[]): Promise<magistrate.Result<any>>; | ||
protected copyConfig(prev: OneOfValidator): this; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace StringValidator { | ||
interface Options<T> extends BaseStringValidator.Options<T> { | ||
allowEmpty?: boolean; | ||
} | ||
} | ||
declare class StringValidator<T = string> extends BaseStringValidator<T> { | ||
protected config: StringValidator.Options<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => StringValidator<T | Validator.TOptional>; | ||
nullable: () => StringValidator<T | null>; | ||
default: (string: Validator.ParameterOrFn<T>) => StringValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
match: (pattern: RegExp) => this; | ||
/** | ||
* 把空字符串`''`设置为合法的值。默认值:`false` | ||
*/ | ||
allowEmpty(): StringValidator<T>; | ||
trim: () => this; | ||
protected isEmpty(value: any): boolean; | ||
protected validateValue(value: string, key: string, superKeys: string[]): magistrate.Result<string>; | ||
protected copy: () => StringValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
interface StringValidator extends MixinLength { | ||
} | ||
declare namespace UuidValidator { | ||
type Version = (typeof UuidValidator.versions)[number]; | ||
interface Options<T = string> extends BaseStringValidator.Options<T> { | ||
uuidVersion: Version[]; | ||
} | ||
} | ||
declare class UuidValidator<T = string> extends BaseStringValidator<T> { | ||
static versions: readonly ["v1", "v2", "v3", "v4", "v5"]; | ||
static patterns: { | ||
[key in UuidValidator.Version | 'all']: RegExp; | ||
}; | ||
protected config: UuidValidator.Options<T>; | ||
constructor(versions: UuidValidator.Version[]); | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => UuidValidator<T | Validator.TOptional>; | ||
nullable: () => UuidValidator<T | null>; | ||
default: (uuid: Validator.ParameterOrFn<T>) => UuidValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
match: (pattern: RegExp) => this; | ||
protected validateValue(uuid: string, key: string, superKeys: string[]): magistrate.Result<string>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare namespace DateTimeValidator { | ||
interface Options<T = Date> extends Validator.Options<T> { | ||
min?: () => Date; | ||
minInclusive?: boolean; | ||
max?: () => Date; | ||
maxInclusive?: boolean; | ||
} | ||
} | ||
declare class DateTimeValidator<T = Date> extends Validator<T> { | ||
protected config: DateTimeValidator.Options<T>; | ||
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this; | ||
optional: () => DateTimeValidator<T | Validator.TOptional>; | ||
nullable: () => DateTimeValidator<T | null>; | ||
default: (date: Validator.ParameterOrFn<Date>) => DateTimeValidator<T | Validator.TDefault>; | ||
transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>; | ||
min(freshDate: () => Date, inclusive?: boolean): DateTimeValidator<T>; | ||
max(freshDate: () => Date, inclusive?: boolean): DateTimeValidator<T>; | ||
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<Date>; | ||
protected toDate(value: any): false | Date; | ||
protected compare(date: Date): boolean; | ||
protected copy: () => DateTimeValidator<T>; | ||
protected toDocument(): OpenAPIV3.SchemaObject; | ||
} | ||
declare class Rule { | ||
static register<T extends Rule, K extends keyof T>(this: new (...args: any[]) => T, name: K, SubValidator: new (...args: any[]) => Validator): void; | ||
/** | ||
* 允许任何类型: | ||
* - string | ||
* - number | ||
* - boolean | ||
* - array | ||
* - object | ||
* - buffer | ||
*/ | ||
any(): AnyValidator<AnyValidator.Type>; | ||
array(): ArrayValidator<unknown[]>; | ||
array<T extends Validator>(item: T): ArrayValidator<Validator.Infer<T>[]>; | ||
/** | ||
* 对象验证规则的快捷操作,等价于 `rule.array(rule.object({}))` | ||
*/ | ||
array<T extends { | ||
[key: string]: P; | ||
}, P extends Validator>(ruleObject: T): ArrayValidator<{ | ||
[K in keyof T]: Validator.Infer<T[K]>; | ||
}[]>; | ||
/** | ||
* 注意:非严格模式下,`number` 和 `string` 会尝试被转换成 `bigint` 类型 | ||
*/ | ||
bigint(): BigIntValidator<bigint>; | ||
/** | ||
* - 默认真值:`[1, '1', true, 'true']` | ||
* - 默认假值:`[0, '0', false, 'false']` | ||
* | ||
* ```typescript | ||
* rule.boolean(); | ||
* rule.boolean().trueValues([true, 'yes']).falseValues([false, 'no']); | ||
* ``` | ||
*/ | ||
boolean(): BooleanValidator<boolean>; | ||
buffer<T extends Buffer>(): BufferValidator<T>; | ||
email(): EmailValidator<string>; | ||
enum<T extends string | number | boolean>(ranges: T[]): EnumValidator<T>; | ||
enum<T extends readonly (string | number | boolean)[]>(ranges: T): EnumValidator<T[number]>; | ||
hash(algorithm: HashValidator.Algorithm): HashValidator<string>; | ||
/** | ||
* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型 | ||
* | ||
* @see number() | ||
* @see bigint() | ||
*/ | ||
int(): IntValidator<number>; | ||
/** | ||
* ```typescript | ||
* rule.ip('v4'); | ||
* rule.ip('v6'); | ||
* rule.ip(['v4', 'v6']); | ||
* ``` | ||
*/ | ||
ip(version: IpValidator.Version | [IpValidator.Version, ...IpValidator.Version[]]): IpValidator<string>; | ||
/** | ||
* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型 | ||
* | ||
* @see int() | ||
* @see bigint() | ||
*/ | ||
number(): NumberValidator<number>; | ||
/** | ||
* ```typescript | ||
* rule.object(); | ||
* rule.object({ | ||
* id: rule.int(), | ||
* profile: rule.object({ | ||
* sex: rule.enum(['unknow', 'male', 'female']), | ||
* }), | ||
* }); | ||
* ``` | ||
*/ | ||
object<T extends { | ||
[key: string]: Validator; | ||
} | undefined>(properties?: T): ObjectValidator<keyof T extends undefined ? Validator.TObject : { | ||
[K in keyof T]: Validator.Infer<T[K]>; | ||
}>; | ||
/** | ||
* ```typescript | ||
* rule.oneOf([rule.number(), rule.string()]); | ||
* ``` | ||
*/ | ||
oneOf<T extends Validator[], A extends Validator, B extends Validator>(rules: [rule1: A, rule2: B, ...others: T]): OneOfValidator<Validator.Infer<A> | Validator.Infer<B> | { | ||
[K in keyof T]: Validator.Infer<T[K]>; | ||
}[number]>; | ||
string(): StringValidator<string>; | ||
/** | ||
* ```typescript | ||
* rule.uuid('v4'); | ||
* rule.uuid(['v4', 'v5', 'v6']); | ||
* ``` | ||
*/ | ||
uuid(version: UuidValidator.Version): UuidValidator<string>; | ||
uuid(versions: [UuidValidator.Version, ...UuidValidator.Version[]]): UuidValidator<string>; | ||
dateTime(): DateTimeValidator<Date>; | ||
} | ||
declare const rule: Rule; | ||
declare function forceValidator(validator: Record<string, Validator> | Validator): Validator; | ||
declare function forceValidator(validator: Record<string, Validator> | Validator | undefined): Validator | undefined; | ||
interface CacheOptions { | ||
keyPrefix?: string; | ||
} | ||
declare abstract class Cache { | ||
protected readonly keyPrefix: string; | ||
constructor(config: CacheOptions); | ||
/** | ||
* 确保缓存没有过期 | ||
*/ | ||
exists(key: string): Promise<boolean>; | ||
/** | ||
* | ||
* 获取缓存。如果没有值并且为提供默认值,则返回`null` | ||
* ```typescript | ||
* await cache.get('non-exist'); // null | ||
* await cache.get('non-exist', 'my-value'); // my-value | ||
* ``` | ||
*/ | ||
get<T>(key: string, defaultValue: T): Promise<T>; | ||
get<T extends string | number | object | boolean>(key: string): Promise<T | null>; | ||
/** | ||
* 删除缓存并返回这个值。如果没有值并且为提供默认值,则返回`null` | ||
*/ | ||
getAndDelete<T>(key: string, defaultValue: T): Promise<T>; | ||
getAndDelete<T extends string | number | object | boolean>(key: string): Promise<T | null>; | ||
/** | ||
* 获取缓存。如果没有值,则设置该缓存 | ||
* | ||
* ```typescript | ||
* await cache.get('key'); // null | ||
* await cache.getOrSet('key', () => 'value'); // 'value' | ||
* await cache.get('key'); // 'value' | ||
* ``` | ||
*/ | ||
getOrSet<T extends string | number | object | boolean>(key: string, orSet: () => T, durationMs?: number): Promise<T>; | ||
getOrSet<T extends string | number | object | boolean>(key: string, orSet: () => Promise<T>, durationMs?: number): Promise<T>; | ||
/** | ||
* 设置缓存 | ||
* | ||
* ```typescript | ||
* await cache.set('key', 'value'); | ||
* await cache.set('key', 'value', 3600); | ||
* ``` | ||
*/ | ||
set(key: string, value: string | number | object | boolean, durationMs?: number): Promise<boolean>; | ||
/** | ||
* 设置缓存。如果缓存已经存在,则设置失败,返回`false` | ||
* | ||
* ```typescript | ||
* await cache.exists('key'); // false | ||
* await cache.add('key', 'value'); // true | ||
* | ||
* await cache.exists('key'); // true | ||
* await cache.add('key', 'value'); // false | ||
* ``` | ||
*/ | ||
add(key: string, value: any, durationMs?: number): Promise<boolean>; | ||
/** | ||
* 删除缓存 | ||
*/ | ||
delete(key: string): Promise<boolean>; | ||
/** | ||
* 删除所有缓存 | ||
*/ | ||
deleteAll(): Promise<boolean>; | ||
protected buildKey(key: string): string; | ||
protected addValue(key: string, value: string, duration?: number): Promise<boolean>; | ||
protected abstract existsKey(key: string): Promise<boolean>; | ||
protected abstract getValue(key: string): Promise<string | null>; | ||
protected abstract setValue(key: string, value: string, duration?: number): Promise<boolean>; | ||
protected abstract deleteValue(key: string): Promise<boolean>; | ||
protected abstract deleteAllValues(): Promise<boolean>; | ||
protected parseValue(value: string | null, defaultValue?: string | number | object | boolean): any; | ||
} | ||
interface MemoryCacheOptions extends CacheOptions { | ||
/** | ||
* 最大的缓存数量。默认值:`1000` | ||
*/ | ||
maxItems?: number; | ||
/** | ||
* 内存回收概率。取值范围:`1-100`。默认值:`10` | ||
*/ | ||
gcProbability?: number; | ||
} | ||
declare class MemoryCache extends Cache { | ||
readonly lru: LRUCache<string, string>; | ||
protected readonly gcProbability: number; | ||
constructor(options?: MemoryCacheOptions); | ||
getAndDelete<T>(key: string, defaultValue: T): Promise<T>; | ||
getAndDelete<T extends string | number | object | boolean>(key: string): Promise<T | null>; | ||
protected existsKey(key: string): Promise<boolean>; | ||
protected getValue(key: string): Promise<string | null>; | ||
protected syncGetValue(key: string): string | null; | ||
protected setValue(key: string, value: string, duration?: number): Promise<boolean>; | ||
protected deleteValue(key: string): Promise<boolean>; | ||
protected syncDeleteValue(key: string): boolean; | ||
protected deleteAllValues(): Promise<boolean>; | ||
protected gc(): void; | ||
} | ||
interface Options { | ||
pattern: string[]; | ||
ignore?: string[]; | ||
dot?: boolean; | ||
/** | ||
* 忽略 **node_modules** 文件夹。默认值:`true` | ||
*/ | ||
ignoreNodeModules?: boolean; | ||
/** | ||
* 忽略所有 **.d.{ts,mts,cts}** 文件。默认值:`true` | ||
*/ | ||
ignoreDTS?: boolean; | ||
} | ||
type PathToFileOptions = string | string[] | Options | Options[]; | ||
declare const pathToFiles: (paths: PathToFileOptions) => Promise<string[]>; | ||
declare const fileToModules: <T extends unknown>(files: string[], filter?: ((item?: T | undefined) => boolean) | undefined) => Promise<T[]>; | ||
export { AnyValidator, ArrayValidator, BaseNumberValidator, BaseStringValidator, BigIntValidator, BooleanValidator, BufferValidator, Cache, CacheOptions, Chain, ChainPlatform, Compose, DateTimeValidator, EmailValidator, EnumValidator, HashValidator, IntValidator, IpValidator, LengthRange, MemoryCache, MemoryCacheOptions, MiddleWareToken, Middleware, MiddlewarePlatform, MixinLength, Next, NonReadonly, NumberValidator, ObjectValidator, OneOfValidator, PathToFileOptions, PureChain, PureMiddleware, PureMiddlewareToken, Rule, StringValidator, TransformedValidator, Union2Intersection, UuidValidator, ValidateOptions, Validator, ValidatorError, _PureFn, chain, compose, fileToModules, forceValidator, magistrate, middleware, mixinLength, pathToFiles, rule, sleep, toArray, validate }; |
1534
dist/index.js
@@ -1,6 +0,1530 @@ | ||
// src/index.ts | ||
export * from "@aomex/middleware"; | ||
export * from "@aomex/validator"; | ||
export * from "@aomex/openapi-type"; | ||
export * from "@aomex/cache"; | ||
// src/utility/to-array.ts | ||
function toArray(data, unique = false) { | ||
return Array.isArray(data) ? unique ? [...new Set(data)] : data : [data]; | ||
} | ||
// src/utility/sleep.ts | ||
var sleep = (ms) => ms <= 0 ? Promise.resolve(void 0) : new Promise((resolve) => { | ||
setTimeout(resolve, ms); | ||
}); | ||
// src/utility/index.ts | ||
import { default as default2 } from "chalk"; | ||
import { default as default3 } from "bytes"; | ||
// src/middleware/chain.ts | ||
var Chain = class _Chain { | ||
constructor(middlewareList = []) { | ||
this.middlewareList = middlewareList; | ||
this.SubClass = new.target; | ||
} | ||
static autoIncrementID = 0; | ||
/** | ||
* 注册链条 | ||
*/ | ||
static register(platform, SubChain) { | ||
Object.defineProperty(chain, platform, { | ||
get() { | ||
return new SubChain(); | ||
} | ||
}); | ||
} | ||
/** | ||
* 平坦中间件和链条,并返回中间件列表 | ||
*/ | ||
static flatten(middleware2) { | ||
if (Array.isArray(middleware2)) { | ||
return middleware2.reduce( | ||
(carry, item) => carry.concat(_Chain.flatten(item)), | ||
[] | ||
); | ||
} | ||
return middleware2 == null ? [] : middleware2 instanceof _Chain ? middleware2.middlewareList.slice() : [middleware2]; | ||
} | ||
static createSplitPoint(chain2) { | ||
const point = "point_" + ++this.autoIncrementID; | ||
chain2.points[point] = chain2.middlewareList.length; | ||
return point; | ||
} | ||
/** | ||
* 分割链条成两段,并返回后面那一段 | ||
*/ | ||
static split(chain2, point = []) { | ||
const longestLengthOfPoint = toArray(point).map((p) => chain2.points[p]).filter(Boolean).sort((a, b) => b - a)[0]; | ||
if (!longestLengthOfPoint) | ||
return chain2; | ||
const middlewareList = chain2.middlewareList.slice(longestLengthOfPoint); | ||
return new chain2.SubClass(middlewareList); | ||
} | ||
SubClass; | ||
points = {}; | ||
/** | ||
* 挂载中间件和链条,支持传入`null` | ||
*/ | ||
mount(middleware2) { | ||
const chain2 = new this.SubClass( | ||
this.middlewareList.concat(_Chain.flatten(middleware2)) | ||
); | ||
chain2.points = this.points; | ||
return chain2; | ||
} | ||
}; | ||
var chain = {}; | ||
// src/middleware/compose.ts | ||
var compose = (tokens) => { | ||
const middlewareList = Chain.flatten(tokens); | ||
return (ctx, next) => { | ||
let lastIndex = -1; | ||
const dispatch = async (i) => { | ||
if (i <= lastIndex) { | ||
throw new Error("call next() multiple times"); | ||
} | ||
const fn = i === middlewareList.length ? next : middlewareList[i].fn; | ||
lastIndex = i; | ||
return fn?.(ctx, dispatch.bind(null, i + 1)); | ||
}; | ||
return dispatch(0); | ||
}; | ||
}; | ||
// src/middleware/middleware.ts | ||
var Middleware = class { | ||
constructor(fn) { | ||
this.fn = fn; | ||
} | ||
/** | ||
* 注册中间件 | ||
*/ | ||
static register(platform, SubMiddleware) { | ||
Object.defineProperty(middleware, platform, { | ||
get() { | ||
return (fn) => new SubMiddleware(fn); | ||
} | ||
}); | ||
} | ||
}; | ||
var middleware = {}; | ||
// src/middleware/pure-middleware.ts | ||
var PureMiddleware = class extends Middleware { | ||
}; | ||
Middleware.register("pure", PureMiddleware); | ||
// src/middleware/pure-chain.ts | ||
var PureChain = class extends Chain { | ||
}; | ||
Chain.register("pure", PureChain); | ||
// src/validator/base/validator.ts | ||
var Validator = class _Validator { | ||
static $rootKey = Symbol("root").toString(); | ||
SubClass; | ||
constructor() { | ||
this.SubClass = new.target; | ||
} | ||
config = { | ||
required: true, | ||
nullable: false, | ||
strict: false | ||
}; | ||
static toDocument(validator) { | ||
const { | ||
required, | ||
nullable, | ||
docs: { description, deprecated, example, ...schemaProperties } = {}, | ||
defaultValue | ||
} = validator.config; | ||
const bothProperties = { description, deprecated, example }; | ||
const schema = { | ||
...schemaProperties, | ||
...bothProperties, | ||
default: validator.getDefaultValue(defaultValue), | ||
nullable: nullable || void 0, | ||
...validator.toDocument() | ||
}; | ||
const result = { | ||
...bothProperties, | ||
required: required || void 0, | ||
schema | ||
}; | ||
return JSON.parse(JSON.stringify(result)); | ||
} | ||
/** | ||
* 设置严格模式,数据不再做兼容性处理。默认值:`true` | ||
*/ | ||
strict(is = true) { | ||
const validator = this.copy(); | ||
validator.config.strict = is; | ||
return validator; | ||
} | ||
/** | ||
* 扩展openapi的配置 | ||
* - **replace:** 本次设置直接覆盖原来的扩展配置 | ||
* - **merge:** 本次设置通过`Object.assign`的形式合并到原来的扩展配置 | ||
* @param mode 默认值:`merge` | ||
*/ | ||
docs(docs, mode = "merge") { | ||
const validator = this.copy(); | ||
validator.config.docs = mode === "merge" ? { ...validator.config.docs, ...docs } : docs; | ||
return validator; | ||
} | ||
/** | ||
* 值如果是 `undefined, null, ''`或者没传入,以上情况会直接转换成`undefined` | ||
* | ||
* 注意:如果执行了`default(...)`,则无需再执行`optional()` | ||
* | ||
* 注意:如果设置了`nullable()`,则`null`不做处理 | ||
*/ | ||
optional() { | ||
const validator = this.copy(); | ||
validator.config.required = false; | ||
return validator; | ||
} | ||
/** | ||
* 把`null`识别成合法的值 | ||
* @see optional | ||
*/ | ||
nullable() { | ||
const validator = this.copy(); | ||
validator.config.nullable = true; | ||
return validator; | ||
} | ||
/** | ||
* 数据验证成功最后会触发该方法,你可以把数据转换成任何格式 | ||
* ```typescript | ||
* // 最终返回类型:string | ||
* rule.string() | ||
* // 最终返回类型:Array<string> | ||
* rule.string().transform((value) => [value]) | ||
* ``` | ||
*/ | ||
transform(fn) { | ||
const validator = this.copy(); | ||
validator.config.transform = fn; | ||
return validator; | ||
} | ||
/** | ||
* 如果值为空或者没传入,则使用该默认值,而且无需验证 | ||
* | ||
* 注意:如果执行了`default(...)`,则无需再执行`optional()` | ||
*/ | ||
default(value) { | ||
const validator = this.copy(); | ||
validator.config.required = false; | ||
validator.config.defaultValue = value; | ||
return validator; | ||
} | ||
async validate(value, key = _Validator.$rootKey, superKeys = []) { | ||
const { defaultValue, required } = this.config; | ||
if (this.isEmpty(value)) { | ||
value = this.getDefaultValue(defaultValue); | ||
if (this.isEmpty(value)) { | ||
if (!required) | ||
return magistrate.ok( | ||
this.config.transform ? this.config.transform(value) : value | ||
); | ||
return magistrate.fail("required", key, superKeys); | ||
} | ||
} | ||
if (this.isValidNull(value)) { | ||
return magistrate.ok( | ||
this.config.transform ? this.config.transform(value) : value | ||
); | ||
} | ||
const result = await this.validateValue(value, key, superKeys); | ||
if (magistrate.noError(result) && this.config.transform) { | ||
result.ok = this.config.transform(result.ok); | ||
} | ||
return result; | ||
} | ||
isEmpty(value) { | ||
return value === void 0 || !this.config.nullable && value === null || value === ""; | ||
} | ||
isValidNull(value) { | ||
return value === null && this.config.nullable; | ||
} | ||
getDefaultValue(value) { | ||
return typeof value === "function" ? value() : value; | ||
} | ||
copy() { | ||
return new this.SubClass().copyConfig(this); | ||
} | ||
copyConfig(prev) { | ||
this.config = { ...prev.config }; | ||
return this; | ||
} | ||
toDocument() { | ||
return {}; | ||
} | ||
}; | ||
// src/validator/base/magistrate.ts | ||
var magistrate = { | ||
ok: (result) => { | ||
return { ok: result }; | ||
}, | ||
fail: (message, key, superKeys) => { | ||
return { | ||
errors: [ | ||
{ | ||
path: superKeys.concat(key).filter((item) => item !== Validator.$rootKey), | ||
message | ||
} | ||
] | ||
}; | ||
}, | ||
noError: (result) => { | ||
return "ok" in result; | ||
} | ||
}; | ||
// src/validator/base/base-number-validator.ts | ||
var precisionPattern = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/; | ||
var BaseNumberValidator = class extends Validator { | ||
min(min, inclusive = true) { | ||
const validator = this.copy(); | ||
validator.config.min = min; | ||
validator.config.minInclusive = inclusive; | ||
return validator; | ||
} | ||
max(max, inclusive = true) { | ||
const validator = this.copy(); | ||
validator.config.max = max; | ||
validator.config.maxInclusive = inclusive; | ||
return validator; | ||
} | ||
validateValue(num, key, superKeys) { | ||
const { | ||
min = -Infinity, | ||
max = Infinity, | ||
minInclusive, | ||
maxInclusive, | ||
onlyInteger, | ||
precision, | ||
strict | ||
} = this.config; | ||
if (!strict && typeof num === "string") { | ||
num = Number(num); | ||
} | ||
if (!Number.isFinite(num)) { | ||
return magistrate.fail("must be number", key, superKeys); | ||
} | ||
if (onlyInteger && !Number.isInteger(num)) { | ||
return magistrate.fail("must be integer", key, superKeys); | ||
} | ||
if ((minInclusive ? num < min : num <= min) || (maxInclusive ? num > max : num >= max)) { | ||
return magistrate.fail("too small or too big", key, superKeys); | ||
} | ||
if (precision !== void 0 && !onlyInteger) { | ||
const matches = num.toString().match(precisionPattern); | ||
const decimals = (matches[1] ? matches[1].length : 0) - (matches[2] ? Number(matches[2]) : 0); | ||
if (decimals >= 0 && decimals > precision) { | ||
return magistrate.fail("incorrect decimals", key, superKeys); | ||
} | ||
} | ||
return magistrate.ok(num); | ||
} | ||
toDocument() { | ||
const { max, maxInclusive, min, minInclusive } = this.config; | ||
return { | ||
type: "number", | ||
maximum: max, | ||
minimum: min, | ||
exclusiveMaximum: maxInclusive === void 0 ? void 0 : !maxInclusive, | ||
exclusiveMinimum: minInclusive === void 0 ? void 0 : !minInclusive | ||
}; | ||
} | ||
}; | ||
// src/validator/base/base-string-validator.ts | ||
var BaseStringValidator = class extends Validator { | ||
/** | ||
* 删除两边空格后再进行验证 | ||
*/ | ||
trim() { | ||
const validator = this.copy(); | ||
validator.config.trim = true; | ||
return validator; | ||
} | ||
match(pattern) { | ||
const validator = this.copy(); | ||
validator.config.pattern = pattern; | ||
return validator; | ||
} | ||
isEmpty(value) { | ||
if (value !== "" && super.isEmpty(value)) | ||
return true; | ||
if (typeof value !== "string") | ||
return false; | ||
if (value === "" || this.getTrimValue(value) === "") | ||
return true; | ||
return false; | ||
} | ||
getTrimValue(value) { | ||
return this.config.trim ? value.trim() : value; | ||
} | ||
shouldMatchPattern(value, key, superKeys) { | ||
const { pattern } = this.config; | ||
if (pattern && !pattern.test(value)) { | ||
return magistrate.fail("not match regexp", key, superKeys); | ||
} | ||
} | ||
shouldBetweenLength(value, key, superKeys) { | ||
const { lengthRange } = this.config; | ||
if (!lengthRange) | ||
return; | ||
const { min = 0, max = Infinity } = lengthRange; | ||
const length = value.length; | ||
if (length < min || length > max) { | ||
return magistrate.fail(`too short or too long`, key, superKeys); | ||
} | ||
} | ||
shouldBeString(value, key, superKeys) { | ||
if (typeof value !== "string") { | ||
return magistrate.fail("must be string", key, superKeys); | ||
} | ||
} | ||
toDocument() { | ||
const { lengthRange = {}, pattern } = this.config; | ||
return { | ||
type: "string", | ||
// FIXME: openapi没地方放`pattern.flags` | ||
pattern: pattern ? pattern.source : void 0, | ||
minLength: lengthRange.min, | ||
maxLength: lengthRange.max | ||
}; | ||
} | ||
}; | ||
// src/validator/base/validator-error.ts | ||
var ValidatorError = class extends Error { | ||
}; | ||
// src/validator/validators/any-validator.ts | ||
var AnyValidator = class extends Validator { | ||
validateValue(value) { | ||
return magistrate.ok(value); | ||
} | ||
toDocument() { | ||
return { | ||
anyOf: [ | ||
{ type: "array", items: {} }, | ||
{ type: "boolean" }, | ||
{ type: "integer" }, | ||
{ type: "number" }, | ||
{ type: "object" }, | ||
{ type: "string" } | ||
] | ||
}; | ||
} | ||
}; | ||
// src/validator/mixins/mixin-length.ts | ||
function mixinLength(validator, configKey = "lengthRange") { | ||
validator.prototype["length"] = function(min, max) { | ||
const validator2 = this.copy(); | ||
validator2.config[configKey] = getLengthRange(min, max); | ||
return validator2; | ||
}; | ||
} | ||
var getLengthRange = (min, max) => { | ||
if (typeof min === "number") { | ||
return { min, max: typeof max === "number" ? max : min }; | ||
} | ||
return { min: typeof min.min === "number" ? min.min : 0, max: min.max }; | ||
}; | ||
// src/validator/validators/array-validator.ts | ||
var ArrayValidator = class extends Validator { | ||
constructor(validator) { | ||
super(); | ||
this.config.itemValidator = validator; | ||
this.config.lengthRange = {}; | ||
this.config.force = false; | ||
} | ||
strict(is = true) { | ||
const validator = super.strict(is); | ||
validator.config.itemValidator = validator.config.itemValidator?.strict(is); | ||
return validator; | ||
} | ||
/** | ||
* 强制将`非数组`的值转换成数组类型。 | ||
* | ||
* 控制台命令行和url查询字符串场景下,如果只传了一个元素,则有可能被识别为非数组,而传递多个元素时又变成了数组结构。 | ||
* | ||
* ```typescript | ||
* rule.array().forceToArray() | ||
* // 允许针对特定值进行转换 | ||
* rule.array().forceToArray({ | ||
* filter: (value) => typeof value === 'string' | ||
* }) | ||
* // 最常用的字符串逗号分割符 | ||
* rule.array().forceToArray({ stringCommaSeparator: true }) | ||
* // 字符串使用自定义分割符 | ||
* rule.array().forceToArray({ stringSeparator: '-' }) | ||
* ``` | ||
*/ | ||
forceToArray(options2 = {}) { | ||
const validator = this.copy(); | ||
validator.config.force = options2 || true; | ||
return validator; | ||
} | ||
async validateValue(value, key, superKeys) { | ||
const { | ||
force = false, | ||
lengthRange: { min = 0, max = Infinity }, | ||
itemValidator | ||
} = this.config; | ||
let items; | ||
if (Array.isArray(value)) { | ||
items = value.slice(); | ||
} else if (force !== false) { | ||
const { | ||
filter = () => true, | ||
stringCommaSeparator, | ||
stringSeparator, | ||
formatter = (_) => [_] | ||
} = force === true ? {} : force; | ||
if (filter(value)) { | ||
if ((stringCommaSeparator || stringSeparator) && typeof value === "string") { | ||
items = value.split( | ||
stringCommaSeparator ? /\s*,\s*/ : stringSeparator | ||
); | ||
} else { | ||
items = formatter(value); | ||
} | ||
} | ||
} | ||
if (!Array.isArray(items)) { | ||
return magistrate.fail("must be array", key, superKeys); | ||
} | ||
const length = items.length; | ||
if (length < min || length > max) { | ||
return magistrate.fail(`contains invalid items length`, key, superKeys); | ||
} | ||
if (itemValidator) { | ||
const newSuperKeys = superKeys.concat(key); | ||
let error = { | ||
errors: [] | ||
}; | ||
await Promise.all( | ||
items.map(async (_, index, arr) => { | ||
const result = await itemValidator["validate"]( | ||
arr[index], | ||
index.toString(), | ||
newSuperKeys | ||
); | ||
if (magistrate.noError(result)) { | ||
arr[index] = result.ok; | ||
} else { | ||
error.errors = error.errors.concat(result.errors); | ||
} | ||
}) | ||
); | ||
if (error.errors.length) | ||
return error; | ||
} | ||
return magistrate.ok(items); | ||
} | ||
toDocument() { | ||
const { itemValidator, lengthRange } = this.config; | ||
return { | ||
type: "array", | ||
items: itemValidator && Validator.toDocument(itemValidator).schema || {}, | ||
minItems: lengthRange.min, | ||
maxItems: lengthRange.max | ||
}; | ||
} | ||
}; | ||
mixinLength(ArrayValidator); | ||
// src/validator/validators/bigInt-validator.ts | ||
var BigIntValidator = class extends Validator { | ||
validateValue(value, key, superKeys) { | ||
const { strict } = this.config; | ||
const type = typeof value; | ||
if (type === "bigint") { | ||
return magistrate.ok(value); | ||
} | ||
if (!strict && (type === "number" || type === "string")) { | ||
try { | ||
return magistrate.ok(BigInt(value)); | ||
} catch { | ||
} | ||
} | ||
return magistrate.fail("must be bigint", key, superKeys); | ||
} | ||
toDocument() { | ||
return { | ||
type: "string", | ||
format: "bigint", | ||
// JSON.stringify 无法处理bigint类型 | ||
default: this.getDefaultValue( | ||
this.config.defaultValue | ||
)?.toString() | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/boolean-validator.ts | ||
var defaultTrueValues = [1, "1", true, "true"]; | ||
var defaultFalseValues = [0, "0", false, "false"]; | ||
var BooleanValidator = class extends Validator { | ||
/** | ||
* 重新设置真值。默认值:`[1, '1', true, 'true']` | ||
* ```typescript | ||
* boolean.trueValues([true, 'yes']); | ||
* boolean.trueValues([true, 'on', 'good']); | ||
* ``` | ||
*/ | ||
trueValues(values) { | ||
const validator = this.copy(); | ||
validator.config.trueValues = values; | ||
return validator; | ||
} | ||
/** | ||
* 重新设置假值。默认值:`[0, '0', false, 'false']` | ||
* ```typescript | ||
* boolean.falseValues([false, 'no']); | ||
* boolean.falseValues([false, 'off', 'bad']); | ||
* ``` | ||
*/ | ||
falseValues(values) { | ||
const validator = this.copy(); | ||
validator.config.falseValues = values; | ||
return validator; | ||
} | ||
validateValue(value, key, superKeys) { | ||
const { trueValues = defaultTrueValues, falseValues = defaultFalseValues } = this.config; | ||
if (trueValues.includes(value)) { | ||
return magistrate.ok(true); | ||
} | ||
if (falseValues.includes(value)) { | ||
return magistrate.ok(false); | ||
} | ||
return magistrate.fail("must be boolean", key, superKeys); | ||
} | ||
toDocument() { | ||
return { | ||
type: "boolean" | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/buffer-validator.ts | ||
var BufferValidator = class extends Validator { | ||
validateValue(value, key, superKeys) { | ||
if (!Buffer.isBuffer(value)) { | ||
return magistrate.fail("must be buffer", key, superKeys); | ||
} | ||
return magistrate.ok(value); | ||
} | ||
toDocument() { | ||
return { | ||
type: "string", | ||
format: "byte", | ||
// JSON 无法处理buffer类型 | ||
default: void 0 | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/email-validator.ts | ||
import emailValidator from "email-validator"; | ||
var EmailValidator = class extends BaseStringValidator { | ||
validateValue(email, key, superKeys) { | ||
let checker; | ||
checker = this.shouldBeString(email, key, superKeys); | ||
if (checker) | ||
return checker; | ||
email = this.getTrimValue(email); | ||
checker = this.shouldBetweenLength(email, key, superKeys); | ||
if (checker) | ||
return checker; | ||
checker = this.shouldMatchPattern(email, key, superKeys); | ||
if (checker) | ||
return checker; | ||
if (!emailValidator.validate(email)) { | ||
return magistrate.fail("must be email", key, superKeys); | ||
} | ||
return magistrate.ok(email); | ||
} | ||
toDocument() { | ||
return { | ||
...super.toDocument(), | ||
format: "email" | ||
}; | ||
} | ||
}; | ||
mixinLength(EmailValidator); | ||
// src/validator/validators/enum-validator.ts | ||
var EnumValidator = class extends Validator { | ||
constructor(ranges = []) { | ||
super(); | ||
this.config.ranges = ranges; | ||
ranges.forEach((item) => { | ||
if (this.isEmpty(item)) { | ||
throw new Error( | ||
`enum items should not contains empty value: "${item}"` | ||
); | ||
} | ||
}); | ||
} | ||
validateValue(value, key, superKeys) { | ||
const { ranges } = this.config; | ||
if (!ranges.includes(value)) { | ||
return magistrate.fail("not in enum range", key, superKeys); | ||
} | ||
return magistrate.ok(value); | ||
} | ||
toDocument() { | ||
const { ranges } = this.config; | ||
const types = ranges.map((value) => typeof value); | ||
return { | ||
type: new Set(types).size === 1 ? types[0] : void 0, | ||
enum: ranges | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/hash-validator.ts | ||
var HashValidator = class _HashValidator extends BaseStringValidator { | ||
/** | ||
* @see https://github.com/validatorjs/validator.js | ||
*/ | ||
static algorithmLength = { | ||
md5: 32, | ||
md4: 32, | ||
sha1: 40, | ||
sha256: 64, | ||
sha384: 96, | ||
sha512: 128, | ||
ripemd128: 32, | ||
ripemd160: 40, | ||
tiger128: 32, | ||
tiger160: 40, | ||
tiger192: 48, | ||
crc32: 8, | ||
crc32b: 8 | ||
}; | ||
static algorithmPattern = (() => { | ||
const patterns = {}; | ||
Object.values(_HashValidator.algorithmLength).forEach((length) => { | ||
patterns[length] ||= new RegExp(`^[a-f0-9]{${length}}$`, "i"); | ||
}); | ||
return patterns; | ||
})(); | ||
constructor(algorithm) { | ||
super(); | ||
this.config.algorithm = algorithm; | ||
} | ||
validateValue(hash, key, superKeys) { | ||
const { algorithm } = this.config; | ||
let checker; | ||
checker = this.shouldBeString(hash, key, superKeys); | ||
if (checker) | ||
return checker; | ||
hash = this.getTrimValue(hash); | ||
if (!Object.hasOwn(_HashValidator.algorithmLength, algorithm)) { | ||
return magistrate.fail(`unknown hash: ${algorithm}`, key, superKeys); | ||
} | ||
if (!_HashValidator.algorithmPattern[_HashValidator.algorithmLength[algorithm]].test(hash)) { | ||
return magistrate.fail(`must be ${algorithm} hash`, key, superKeys); | ||
} | ||
return magistrate.ok(hash); | ||
} | ||
toDocument() { | ||
const { algorithm } = this.config; | ||
const length = _HashValidator.algorithmLength[algorithm]; | ||
return { | ||
...super.toDocument(), | ||
minLength: length, | ||
maxLength: length, | ||
format: this.config.algorithm | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/int-validator.ts | ||
var IntValidator = class extends BaseNumberValidator { | ||
constructor() { | ||
super(); | ||
this.config.onlyInteger = true; | ||
} | ||
toDocument() { | ||
return { | ||
...super.toDocument(), | ||
type: "integer" | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/ip-validator.ts | ||
import ipRegexp from "ip-regex"; | ||
var versions = ["v4", "v6"]; | ||
var options = { exact: true, includeBoundaries: true }; | ||
var IpValidator = class _IpValidator extends BaseStringValidator { | ||
static patterns = { | ||
v4: ipRegexp.v4(options), | ||
v6: ipRegexp.v6(options), | ||
all: ipRegexp(options) | ||
}; | ||
constructor(version) { | ||
super(); | ||
this.config.ipVersion = version; | ||
} | ||
validateValue(ip, key, superKeys) { | ||
const { ipVersion } = this.config; | ||
let checker; | ||
checker = this.shouldBeString(ip, key, superKeys); | ||
if (checker) | ||
return checker; | ||
ip = this.getTrimValue(ip); | ||
checker = this.shouldMatchPattern(ip, key, superKeys); | ||
if (checker) | ||
return checker; | ||
let valid = false; | ||
if (ipVersion.length === versions.length) { | ||
valid = _IpValidator.patterns.all.test(ip); | ||
} else { | ||
for (let i = ipVersion.length; i-- > 0; ) { | ||
if (_IpValidator.patterns[ipVersion[i]].test(ip)) { | ||
valid = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (!valid) { | ||
return magistrate.fail( | ||
`must be IP${ipVersion.length === 1 ? ipVersion : `[${ipVersion.join(",")}]`} address`, | ||
key, | ||
superKeys | ||
); | ||
} | ||
return magistrate.ok(ip); | ||
} | ||
toDocument() { | ||
const { ipVersion } = this.config; | ||
return { | ||
...super.toDocument(), | ||
format: ipVersion.length === 1 ? `ip${ipVersion[0]}` : "ip" | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/number-validator.ts | ||
var NumberValidator = class extends BaseNumberValidator { | ||
precision(maxDecimals) { | ||
const validator = this.copy(); | ||
validator.config.precision = Math.min(20, Math.max(0, maxDecimals)); | ||
return validator; | ||
} | ||
toDocument() { | ||
return { | ||
...super.toDocument(), | ||
type: "number" | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/object-validator.ts | ||
var ObjectValidator = class extends Validator { | ||
constructor(properties) { | ||
super(); | ||
this.config.properties = properties; | ||
} | ||
strict(is = true) { | ||
const validator = super.strict(is); | ||
const { properties } = validator.config; | ||
if (properties) { | ||
for (const [key, subValidator] of Object.entries(properties)) { | ||
properties[key] = subValidator.strict(is); | ||
} | ||
} | ||
return validator; | ||
} | ||
/** | ||
* 如果是字符串,则尝试使用`JSON.parse`转换为对象。默认值:`false` | ||
*/ | ||
parseFromString(is = true) { | ||
const validator = this.copy(); | ||
validator.config.stringToObject = is; | ||
return validator; | ||
} | ||
isPlainObject(value) { | ||
return Object.prototype.toString.call(value) === "[object Object]"; | ||
} | ||
async validateValue(origin, key, superKeys) { | ||
const { properties, stringToObject = false } = this.config; | ||
if (!this.isPlainObject(origin)) { | ||
let valid = false; | ||
if (stringToObject && typeof origin === "string") { | ||
try { | ||
origin = JSON.parse(origin); | ||
valid = this.isPlainObject(origin); | ||
} catch { | ||
} | ||
} | ||
if (!valid) { | ||
return magistrate.fail("must be plain object", key, superKeys); | ||
} | ||
} | ||
let obj = {}; | ||
if (properties) { | ||
const newSuperKeys = superKeys.concat(key); | ||
let error = { | ||
errors: [] | ||
}; | ||
await Promise.all( | ||
Object.entries(properties).map(async ([propKey, validator]) => { | ||
const result = await validator["validate"]( | ||
origin[propKey], | ||
propKey, | ||
newSuperKeys | ||
); | ||
if (magistrate.noError(result)) { | ||
obj[propKey] = result.ok; | ||
} else { | ||
error.errors = error.errors.concat(result.errors); | ||
} | ||
}) | ||
); | ||
if (error.errors.length) | ||
return error; | ||
} else { | ||
Object.assign(obj, origin); | ||
} | ||
return magistrate.ok(obj); | ||
} | ||
copyConfig(prev) { | ||
super.copyConfig(prev); | ||
this.config.properties = { ...prev.config.properties }; | ||
return this; | ||
} | ||
toDocument() { | ||
const { properties = {} } = this.config; | ||
const schemas = {}; | ||
const requiredProperties = []; | ||
Object.entries(properties).forEach(([key, validator]) => { | ||
const docs = Validator.toDocument(validator); | ||
schemas[key] = docs.schema; | ||
docs.required && requiredProperties.push(key); | ||
}); | ||
return { | ||
type: "object", | ||
properties: Object.keys(schemas).length ? schemas : void 0, | ||
required: requiredProperties.length ? requiredProperties : void 0 | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/one-of-validator.ts | ||
var OneOfValidator = class extends Validator { | ||
constructor(rules) { | ||
super(); | ||
this.config.validators = rules; | ||
} | ||
strict(is = true) { | ||
const validator = super.strict(is); | ||
validator.config.validators = validator.config.validators.map( | ||
(validator2) => validator2.strict(is) | ||
); | ||
return validator; | ||
} | ||
isEmpty(_) { | ||
return false; | ||
} | ||
async validateValue(value, key, superKeys) { | ||
const { validators } = this.config; | ||
for (let i = 0; i < validators.length; ++i) { | ||
const result = await validators[i].validate( | ||
value, | ||
key, | ||
superKeys | ||
); | ||
if (magistrate.noError(result)) | ||
return result; | ||
} | ||
return magistrate.fail("no rule matched", key, superKeys); | ||
} | ||
copyConfig(prev) { | ||
super.copyConfig(prev); | ||
this.config.validators = [...prev.config.validators]; | ||
return this; | ||
} | ||
toDocument() { | ||
const { validators } = this.config; | ||
return { | ||
oneOf: validators.map( | ||
(validator) => Validator.toDocument(validator).schema | ||
) | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/string-validator.ts | ||
var StringValidator = class extends BaseStringValidator { | ||
/** | ||
* 把空字符串`''`设置为合法的值。默认值:`false` | ||
*/ | ||
allowEmpty() { | ||
const validator = this.copy(); | ||
validator.config.allowEmpty = true; | ||
return validator; | ||
} | ||
isEmpty(value) { | ||
if (value != null && this.config.allowEmpty) | ||
return false; | ||
return super.isEmpty(value); | ||
} | ||
validateValue(value, key, superKeys) { | ||
let checker; | ||
checker = this.shouldBeString(value, key, superKeys); | ||
if (checker) | ||
return checker; | ||
value = this.getTrimValue(value); | ||
checker = this.shouldBetweenLength(value, key, superKeys); | ||
if (checker) | ||
return checker; | ||
checker = this.shouldMatchPattern(value, key, superKeys); | ||
if (checker) | ||
return checker; | ||
return magistrate.ok(value); | ||
} | ||
toDocument() { | ||
return super.toDocument(); | ||
} | ||
}; | ||
mixinLength(StringValidator); | ||
// src/validator/validators/uuid-validator.ts | ||
var createRegexp = (version) => { | ||
const group = "[0-9a-f]"; | ||
const diff = version === "all" ? `${group}{4}` : `${version}${group}{3}`; | ||
return new RegExp( | ||
`^${group}{8}-${group}{4}-${diff}-[89ab]${group}{3}-${group}{12}$`, | ||
"i" | ||
); | ||
}; | ||
var UuidValidator = class _UuidValidator extends BaseStringValidator { | ||
static versions = ["v1", "v2", "v3", "v4", "v5"]; | ||
static patterns = { | ||
v1: createRegexp(1), | ||
v2: createRegexp(2), | ||
v3: createRegexp(3), | ||
v4: createRegexp(4), | ||
v5: createRegexp(5), | ||
all: createRegexp("all") | ||
}; | ||
constructor(versions2) { | ||
super(); | ||
this.config.uuidVersion = versions2; | ||
} | ||
validateValue(uuid, key, superKeys) { | ||
const { uuidVersion } = this.config; | ||
let checker; | ||
checker = this.shouldBeString(uuid, key, superKeys); | ||
if (checker) | ||
return checker; | ||
uuid = this.getTrimValue(uuid); | ||
checker = this.shouldMatchPattern(uuid, key, superKeys); | ||
if (checker) | ||
return checker; | ||
let valid = false; | ||
if (uuidVersion.length === _UuidValidator.versions.length) { | ||
valid = _UuidValidator.patterns.all.test(uuid); | ||
} else { | ||
for (let i = uuidVersion.length; i-- > 0; ) { | ||
if (_UuidValidator.patterns[uuidVersion[i]].test(uuid)) { | ||
valid = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (!valid) { | ||
return magistrate.fail( | ||
`must be UUID[${uuidVersion.join(",")}]`, | ||
key, | ||
superKeys | ||
); | ||
} | ||
return magistrate.ok(uuid); | ||
} | ||
toDocument() { | ||
return { | ||
...super.toDocument(), | ||
format: "uuid" | ||
}; | ||
} | ||
}; | ||
// src/validator/validators/date-time-validator.ts | ||
var DateTimeValidator = class extends Validator { | ||
min(freshDate, inclusive = true) { | ||
const validator = this.copy(); | ||
validator.config.min = freshDate; | ||
validator.config.minInclusive = inclusive; | ||
return validator; | ||
} | ||
max(freshDate, inclusive = true) { | ||
const validator = this.copy(); | ||
validator.config.max = freshDate; | ||
validator.config.maxInclusive = inclusive; | ||
return validator; | ||
} | ||
validateValue(value, key, superKeys) { | ||
const date = this.toDate(value); | ||
if (date === false) { | ||
return magistrate.fail("must be date", key, superKeys); | ||
} | ||
if (!this.compare(date)) { | ||
return magistrate.fail("not in date range", key, superKeys); | ||
} | ||
return magistrate.ok(date); | ||
} | ||
toDate(value) { | ||
if (value instanceof Date) { | ||
if (value.toString() !== "Invalid Date") { | ||
return new Date(value); | ||
} | ||
} else if (typeof value === "string") { | ||
const date = new Date(value); | ||
if (date.toString() !== "Invalid Date") { | ||
return date; | ||
} | ||
} | ||
return false; | ||
} | ||
compare(date) { | ||
const { min, minInclusive, max, maxInclusive } = this.config; | ||
const timestamp = +date; | ||
if (min !== void 0 && (minInclusive ? timestamp < +min() : timestamp <= +min())) { | ||
return false; | ||
} | ||
if (max !== void 0 && (maxInclusive ? timestamp > +max() : timestamp >= +max())) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
toDocument() { | ||
return { | ||
type: "string", | ||
format: "date-time" | ||
}; | ||
} | ||
}; | ||
// src/validator/api/force-validator.ts | ||
function forceValidator(validator) { | ||
if (!validator) | ||
return; | ||
if (validator instanceof Validator) | ||
return validator; | ||
return new ObjectValidator(validator); | ||
} | ||
// src/validator/api/validate.ts | ||
async function validate(source, schema, options2) { | ||
const { throwIfError = true } = options2 || {}; | ||
const validator = forceValidator(schema); | ||
const src = await source; | ||
const result = await validator["validate"](src); | ||
if (magistrate.noError(result)) { | ||
return throwIfError ? result.ok : result; | ||
} | ||
if (throwIfError) { | ||
const errors = result.errors; | ||
let msg = "Validate failed with reasons: "; | ||
if (errors.length === 1 && !errors[0].path.length) { | ||
msg += errors[0].message; | ||
} else { | ||
msg += "\n"; | ||
result.errors.forEach((err) => { | ||
msg += ` | ||
- [${err.path.join(".")}] ${err.message}`; | ||
}); | ||
msg += "\n"; | ||
} | ||
throw new ValidatorError(msg); | ||
} | ||
return result; | ||
} | ||
// src/validator/api/rule.ts | ||
var Rule = class { | ||
static register(name, SubValidator) { | ||
this.constructor.prototype[name] = () => new SubValidator(); | ||
} | ||
/** | ||
* 允许任何类型: | ||
* - string | ||
* - number | ||
* - boolean | ||
* - array | ||
* - object | ||
* - buffer | ||
*/ | ||
any() { | ||
return new AnyValidator(); | ||
} | ||
array(values) { | ||
return new ArrayValidator(forceValidator(values)); | ||
} | ||
/** | ||
* 注意:非严格模式下,`number` 和 `string` 会尝试被转换成 `bigint` 类型 | ||
*/ | ||
bigint() { | ||
return new BigIntValidator(); | ||
} | ||
/** | ||
* - 默认真值:`[1, '1', true, 'true']` | ||
* - 默认假值:`[0, '0', false, 'false']` | ||
* | ||
* ```typescript | ||
* rule.boolean(); | ||
* rule.boolean().trueValues([true, 'yes']).falseValues([false, 'no']); | ||
* ``` | ||
*/ | ||
boolean() { | ||
return new BooleanValidator(); | ||
} | ||
buffer() { | ||
return new BufferValidator(); | ||
} | ||
email() { | ||
return new EmailValidator(); | ||
} | ||
enum(ranges) { | ||
return new EnumValidator(toArray(ranges, true)); | ||
} | ||
hash(algorithm) { | ||
return new HashValidator(algorithm); | ||
} | ||
/** | ||
* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型 | ||
* | ||
* @see number() | ||
* @see bigint() | ||
*/ | ||
int() { | ||
return new IntValidator(); | ||
} | ||
/** | ||
* ```typescript | ||
* rule.ip('v4'); | ||
* rule.ip('v6'); | ||
* rule.ip(['v4', 'v6']); | ||
* ``` | ||
*/ | ||
ip(version) { | ||
return new IpValidator(toArray(version, true)); | ||
} | ||
/** | ||
* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型 | ||
* | ||
* @see int() | ||
* @see bigint() | ||
*/ | ||
number() { | ||
return new NumberValidator(); | ||
} | ||
/** | ||
* ```typescript | ||
* rule.object(); | ||
* rule.object({ | ||
* id: rule.int(), | ||
* profile: rule.object({ | ||
* sex: rule.enum(['unknow', 'male', 'female']), | ||
* }), | ||
* }); | ||
* ``` | ||
*/ | ||
object(properties) { | ||
return new ObjectValidator(properties); | ||
} | ||
/** | ||
* ```typescript | ||
* rule.oneOf([rule.number(), rule.string()]); | ||
* ``` | ||
*/ | ||
oneOf(rules) { | ||
return new OneOfValidator(rules); | ||
} | ||
string() { | ||
return new StringValidator(); | ||
} | ||
uuid(versions2) { | ||
return new UuidValidator(toArray(versions2, true)); | ||
} | ||
dateTime() { | ||
return new DateTimeValidator(); | ||
} | ||
}; | ||
var rule = new Rule(); | ||
// src/openapi-type/index.ts | ||
import { OpenAPIV3 } from "openapi-types"; | ||
// src/caching/cache.ts | ||
import { createHash } from "node:crypto"; | ||
var Cache = class { | ||
keyPrefix; | ||
constructor(config) { | ||
this.keyPrefix = config.keyPrefix ?? ""; | ||
} | ||
/** | ||
* 确保缓存没有过期 | ||
*/ | ||
async exists(key) { | ||
return this.existsKey(this.buildKey(key)); | ||
} | ||
async get(key, defaultValue) { | ||
const hashKey = this.buildKey(key); | ||
const result = await this.getValue(hashKey); | ||
return this.parseValue(result, defaultValue); | ||
} | ||
async getAndDelete(key, defaultValue) { | ||
const result = await this.get(key, defaultValue); | ||
if (result !== null) { | ||
await this.delete(key); | ||
} | ||
return result; | ||
} | ||
async getOrSet(key, orSet, durationMs) { | ||
let value = await this.get(key); | ||
if (value !== null) | ||
return value; | ||
await this.set(key, await orSet(), durationMs); | ||
return await this.get(key); | ||
} | ||
/** | ||
* 设置缓存 | ||
* | ||
* ```typescript | ||
* await cache.set('key', 'value'); | ||
* await cache.set('key', 'value', 3600); | ||
* ``` | ||
*/ | ||
async set(key, value, durationMs) { | ||
const hashKey = this.buildKey(key); | ||
return this.setValue(hashKey, JSON.stringify(value), durationMs); | ||
} | ||
/** | ||
* 设置缓存。如果缓存已经存在,则设置失败,返回`false` | ||
* | ||
* ```typescript | ||
* await cache.exists('key'); // false | ||
* await cache.add('key', 'value'); // true | ||
* | ||
* await cache.exists('key'); // true | ||
* await cache.add('key', 'value'); // false | ||
* ``` | ||
*/ | ||
async add(key, value, durationMs) { | ||
const hashKey = this.buildKey(key); | ||
return this.addValue(hashKey, JSON.stringify(value), durationMs); | ||
} | ||
/** | ||
* 删除缓存 | ||
*/ | ||
async delete(key) { | ||
const hashKey = this.buildKey(key); | ||
return this.deleteValue(hashKey); | ||
} | ||
/** | ||
* 删除所有缓存 | ||
*/ | ||
async deleteAll() { | ||
return this.deleteAllValues(); | ||
} | ||
buildKey(key) { | ||
const hashKey = key.length <= 32 ? key : createHash("md5").update(key).digest("hex"); | ||
return this.keyPrefix + hashKey; | ||
} | ||
async addValue(key, value, duration) { | ||
if (await this.existsKey(key)) | ||
return false; | ||
if (!await this.setValue(key, value, duration)) | ||
return false; | ||
return await this.getValue(key) === value; | ||
} | ||
parseValue(value, defaultValue) { | ||
if (value === null) { | ||
return defaultValue === void 0 ? null : defaultValue; | ||
} | ||
try { | ||
return JSON.parse(value); | ||
} catch { | ||
return null; | ||
} | ||
} | ||
}; | ||
// src/caching/memory-cache.ts | ||
import { LRUCache } from "lru-cache"; | ||
var MemoryCache = class extends Cache { | ||
lru; | ||
gcProbability; | ||
constructor(options2 = {}) { | ||
super(options2); | ||
this.gcProbability = (options2.gcProbability ?? 10) / 100; | ||
this.lru = new LRUCache({ | ||
max: options2.maxItems || 1e3 | ||
}); | ||
} | ||
async getAndDelete(key, defaultValue) { | ||
const hashKey = this.buildKey(key); | ||
const result = this.syncGetValue(hashKey); | ||
result !== null && this.syncDeleteValue(hashKey); | ||
return this.parseValue(result, defaultValue); | ||
} | ||
async existsKey(key) { | ||
return this.lru.has(key); | ||
} | ||
async getValue(key) { | ||
return this.syncGetValue(key); | ||
} | ||
syncGetValue(key) { | ||
const data = this.lru.get(key); | ||
return data === void 0 ? null : data; | ||
} | ||
async setValue(key, value, duration) { | ||
this.gc(); | ||
this.lru.set(key, value, { | ||
ttl: duration | ||
}); | ||
return true; | ||
} | ||
async deleteValue(key) { | ||
return this.syncDeleteValue(key); | ||
} | ||
syncDeleteValue(key) { | ||
return this.lru.delete(key); | ||
} | ||
async deleteAllValues() { | ||
this.lru.clear(); | ||
return true; | ||
} | ||
gc() { | ||
if (Math.random() > this.gcProbability) | ||
return; | ||
this.lru.purgeStale(); | ||
} | ||
}; | ||
// src/file-parser/path-to-files.ts | ||
import path from "node:path"; | ||
import { stat } from "node:fs/promises"; | ||
import { glob, hasMagic } from "glob"; | ||
var pathToFiles = async (paths) => { | ||
const opts = normalizeSearchPath(paths); | ||
const files = await Promise.all( | ||
opts.map((opt) => { | ||
const { | ||
dot, | ||
pattern: patterns, | ||
ignoreNodeModules = true, | ||
ignoreDTS = true | ||
} = opt; | ||
const ignore = (opt.ignore || []).slice(); | ||
ignoreDTS && ignore.push("**/*.d.{ts,mts,cts}"); | ||
ignoreNodeModules && ignore.push("**/node_modules/**"); | ||
const options2 = { | ||
nodir: true, | ||
dot, | ||
ignore, | ||
withFileTypes: false | ||
}; | ||
return Promise.all( | ||
patterns.map(async (pattern) => { | ||
pattern = path.posix.resolve(pattern); | ||
if (!hasMagic(pattern, { magicalBraces: true })) { | ||
const stats = await stat(pattern); | ||
if (!stats.isFile()) { | ||
pattern = path.posix.resolve( | ||
pattern, | ||
`./**/*.{ts,js,mts,mjs,cts,cjs}` | ||
); | ||
} | ||
} | ||
return glob(pattern, options2); | ||
}) | ||
); | ||
}) | ||
); | ||
return [...new Set(files.flat(2))].sort(); | ||
}; | ||
var normalizeSearchPath = (paths) => { | ||
if (typeof paths === "string") { | ||
return [{ pattern: [paths] }]; | ||
} | ||
if (Array.isArray(paths)) { | ||
if (!paths.length) | ||
return []; | ||
return isStringArray(paths) ? [{ pattern: paths }] : paths; | ||
} | ||
return [paths]; | ||
}; | ||
var isStringArray = (data) => { | ||
return typeof data[0] === "string"; | ||
}; | ||
// src/file-parser/file-to-modules.ts | ||
import { pathToFileURL } from "node:url"; | ||
var fileToModules = async (files, filter) => { | ||
const result = await Promise.all( | ||
files.map(async (file) => { | ||
const modules2 = await import(pathToFileURL(file).toString()); | ||
return typeof modules2 === "object" ? Object.values(modules2) : []; | ||
}) | ||
); | ||
const modules = [...new Set(result.flat())]; | ||
return filter ? modules.filter(filter) : modules; | ||
}; | ||
export { | ||
AnyValidator, | ||
ArrayValidator, | ||
BaseNumberValidator, | ||
BaseStringValidator, | ||
BigIntValidator, | ||
BooleanValidator, | ||
BufferValidator, | ||
Cache, | ||
Chain, | ||
DateTimeValidator, | ||
EmailValidator, | ||
EnumValidator, | ||
HashValidator, | ||
IntValidator, | ||
IpValidator, | ||
MemoryCache, | ||
Middleware, | ||
NumberValidator, | ||
ObjectValidator, | ||
OneOfValidator, | ||
OpenAPIV3 as OpenAPI, | ||
PureChain, | ||
PureMiddleware, | ||
Rule, | ||
StringValidator, | ||
UuidValidator, | ||
Validator, | ||
ValidatorError, | ||
default3 as bytes, | ||
chain, | ||
default2 as chalk, | ||
compose, | ||
fileToModules, | ||
forceValidator, | ||
magistrate, | ||
middleware, | ||
mixinLength, | ||
pathToFiles, | ||
rule, | ||
sleep, | ||
toArray, | ||
validate | ||
}; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@aomex/core", | ||
"version": "0.0.21", | ||
"version": "0.0.22", | ||
"description": "", | ||
@@ -36,7 +36,10 @@ "type": "module", | ||
"dependencies": { | ||
"@aomex/utility": "^0.0.7", | ||
"@aomex/middleware": "^0.0.8", | ||
"@aomex/openapi-type": "^0.0.0", | ||
"@aomex/cache": "^0.0.8", | ||
"@aomex/validator": "^0.0.18" | ||
"@types/bytes": "^3.1.1", | ||
"bytes": "^3.1.2", | ||
"chalk": "^5.3.0", | ||
"email-validator": "^2.0.4", | ||
"glob": "^10.3.3", | ||
"ip-regex": "^5.0.0", | ||
"lru-cache": "^10.0.0", | ||
"openapi-types": "^12.1.3" | ||
}, | ||
@@ -43,0 +46,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
Found 1 instance in 1 package
183395
2327
10
+ Added@types/bytes@^3.1.1
+ Addedbytes@^3.1.2
+ Addedchalk@^5.3.0
+ Addedemail-validator@^2.0.4
+ Addedglob@^10.3.3
+ Addedip-regex@^5.0.0
+ Addedlru-cache@^10.0.0
+ Addedopenapi-types@^12.1.3
- Removed@aomex/cache@^0.0.8
- Removed@aomex/middleware@^0.0.8
- Removed@aomex/openapi-type@^0.0.0
- Removed@aomex/utility@^0.0.7
- Removed@aomex/validator@^0.0.18
- Removed@aomex/cache@0.0.8(transitive)
- Removed@aomex/middleware@0.0.8(transitive)
- Removed@aomex/openapi-type@0.0.0(transitive)
- Removed@aomex/utility@0.0.7(transitive)
- Removed@aomex/validator@0.0.18(transitive)
- Removedlru-cache@9.1.2(transitive)