Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@aomex/core

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aomex/core - npm Package Compare versions

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): 对象使用统一逻辑转换成验证器

875

dist/index.d.ts

@@ -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 };

@@ -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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc