Socket
Socket
Sign inDemoInstall

@aomex/core

Package Overview
Dependencies
Maintainers
1
Versions
52
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.28 to 1.0.0

README.md

61

CHANGELOG.md
# @aomex/core
## 0.0.28
## 1.0.0
### Patch Changes
### Minor Changes
- [`90ca7d5`](https://github.com/aomex/aomex/commit/90ca7d5fc736b523c4fbf7949f64653428dc413c) Thanks [@geekact](https://github.com/geekact)! - feat(core)!: 删除函数createDTO
- [`11103a2`](https://github.com/aomex/aomex/commit/11103a2aff4e081754c56b0ff18fa5130ca252e8) Thanks [@geekact](https://github.com/geekact)! - 重新制作
## 0.0.27
### Patch Changes
- [`00bafbb`](https://github.com/aomex/aomex/commit/00bafbbac2d32205b63a6bf561fb0a69c38a54bb) Thanks [@geekact](https://github.com/geekact)! - refactor(core): 缓存迁移到新的包@aomex/internal-cache
- [`8becf8e`](https://github.com/aomex/aomex/commit/8becf8ee5ef86a5909783d0654e536db7be9bf5b) Thanks [@geekact](https://github.com/geekact)! - refactor(core): 工具移动到新的包@aomex/internal-tools
- [`0776719`](https://github.com/aomex/aomex/commit/077671963401f1dafb5b03722899452d45df13fc) Thanks [@geekact](https://github.com/geekact)! - refactor: 文件搜索转移到新的包@aomex/internal-file-import
- [`f996bf7`](https://github.com/aomex/aomex/commit/f996bf7e529e7751a5e858c579feed33f5f02d65) Thanks [@geekact](https://github.com/geekact)! - fix(core): enum规则类型提示不精确
## 0.0.26
### Patch Changes
- [`fbcea3d`](https://github.com/aomex/aomex/commit/fbcea3d68ff033e6861130c645c8e5ad7336193f) Thanks [@geekact](https://github.com/geekact)! - chore(core): 升级依赖包
## 0.0.25
### Patch Changes
- [`0e6ed2c`](https://github.com/aomex/aomex/commit/0e6ed2c611100dcfaafb6fb41357624ad9f5c67a) Thanks [@geekact](https://github.com/geekact)! - fix(core): skip absolute path and replace back slash to forward slash
## 0.0.24
### Patch Changes
- [`2ac62fd`](https://github.com/aomex/aomex/commit/2ac62fd28166a1d9dd60b3c6d5a6508a6f9ee82b) Thanks [@geekact](https://github.com/geekact)! - feat(core): add function createDTO
- [`4258410`](https://github.com/aomex/aomex/commit/42584107ad9f7e34492ae1053fef83aa2d9d747a) Thanks [@geekact](https://github.com/geekact)! - feat(core): 缓存引擎增加GC处理
- [`4177cba`](https://github.com/aomex/aomex/commit/4177cba7877e38120842bd8d287eaed54e4926ca) Thanks [@geekact](https://github.com/geekact)! - feat(core): 增加url验证器
## 0.0.23
### Patch Changes
- [`7b09277`](https://github.com/aomex/aomex/commit/7b09277136910966f500c8132303c7ddee84340c) Thanks [@geekact](https://github.com/geekact)! - refactor(core): 数组验证器的forceToArray方法参数替换formatter为transform
- [`9c78999`](https://github.com/aomex/aomex/commit/9c78999ebcb2962f30344acfbf6de0733d6fdd41) Thanks [@geekact](https://github.com/geekact)! - fix(core): 注册自定义验证规则无效
- [`f4b012d`](https://github.com/aomex/aomex/commit/f4b012d98cddb2918479ea05df6c266dd914e53a) Thanks [@geekact](https://github.com/geekact)! - feat(core): 增加`ulid`验证规则
## 0.0.22
### Patch Changes
- [`6f7d706`](https://github.com/aomex/aomex/commit/6f7d7066c23711abdd149eb1c9a293ab8c4284a4) Thanks [@geekact](https://github.com/geekact)! - feat(core): validator增加严格模式
- [`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
- [`818e840`](https://github.com/aomex/aomex/commit/818e840d36c7456a863fc071968b246c123c17f5) Thanks [@geekact](https://github.com/geekact)! - refactor(core): 对象使用统一逻辑转换成验证器
- Updated dependencies [[`11103a2`](https://github.com/aomex/aomex/commit/11103a2aff4e081754c56b0ff18fa5130ca252e8)]:
- @aomex/internal-tools@1.0.0

@@ -1,18 +0,189 @@

import { NonReadonly } from '@aomex/internal-tools';
import { OpenAPIV3 } from 'openapi-types';
export { OpenAPIV3 as OpenAPI } from 'openapi-types';
import { NonReadonly } from '@aomex/internal-tools';
interface _PureFn {
<Props extends object = object>(fn: (ctx: NonReadonly<Props>, next: Next) => any): PureMiddleware<Props>;
declare abstract class I18nFormat<Args extends object | unknown = unknown> {
protected readonly __i18n_format_string__: 'i18n-format';
protected readonly generic: Args;
}
declare class PureMiddleware<Props extends object = object> extends Middleware<Props> {
protected _pure_middleware_: 'pure-middleware';
}
interface MiddlewarePlatform {
declare namespace I18n {
/**
* 没有特定上下文的纯中间件,支持所有应用
* 语言列表,可扩展
*/
readonly pure: _PureFn;
interface Locales {
zh_CN: true;
en_US: true;
}
/**
* 类型声明,可扩展
*/
interface Definition {
}
type LocaleName = keyof Locales;
type Content = GetContent<I18n.Definition>;
type Keys = GetKeys<Definition>;
type Args<Key extends string> = GetArgs<Definition, Key, ''>;
type PartialContent = GetPartialContent<I18n.Definition>;
}
declare class I18n {
protected localeName: I18n.LocaleName;
protected fallbackLocaleName?: I18n.LocaleName;
protected contents: Record<string, I18n.Content>;
constructor(locale: I18n.LocaleName, fallbackLocale?: I18n.LocaleName);
register<K extends keyof I18n.Content>(locale: I18n.LocaleName, category: K, content: I18n.Content[K]): void;
override(locale: I18n.LocaleName, content: I18n.PartialContent): void;
t<Key extends I18n.Keys>(key: Key, ...rest: unknown extends I18n.Args<Key> ? [params?: undefined, specificLocale?: I18n.LocaleName] : [params: I18n.Args<Key>, specificLocale?: I18n.LocaleName]): string;
getLocale(): I18n.LocaleName;
setLocale(localeName: I18n.LocaleName): this;
getFallbackLocale(): I18n.LocaleName | undefined;
setFallbackLocale(locale: I18n.LocaleName | undefined): this;
protected format(message: string, args: object): string;
protected set(data: Record<string, any>, override: Record<string, any>): void;
protected isMessageObject(value: any): value is {
message: string;
args: Record<string, any>;
};
}
declare const i18n: I18n;
type GetContent<T extends object> = {
[K in keyof T]: T[K] extends I18nFormat<infer R> ? string | {
message: string;
args: {
[P in keyof R]?: R[P] | ((arg: R[P]) => any);
};
} : T[K] extends object ? GetContent<T[K]> : never;
};
type GetPartialContent<T extends object> = {
[K in keyof T]?: T[K] extends I18nFormat<infer R> ? string | {
message: string;
args: {
[P in keyof R]?: R[P] | ((arg: R[P]) => any);
};
} : T[K] extends object ? GetPartialContent<T[K]> : never;
};
type GetKeys<T extends object> = {
[K in keyof T]: K extends string ? T[K] extends object ? T[K] extends I18nFormat ? K : `${K}.${GetKeys<T[K]>}` : K : never;
}[keyof T];
type GetArgs<T extends object, MatchKey extends string, Parent extends string = ''> = {
[K in keyof T]: K extends string ? T[K] extends object ? T[K] extends I18nFormat<infer R> ? CombineKey<Parent, K> extends MatchKey ? R : never : GetArgs<T[K], MatchKey, CombineKey<Parent, K>> : never : never;
}[keyof T];
type CombineKey<Parent extends string, Key extends string> = `${Parent}${'' extends Parent ? '' : '.'}${Key}`;
declare module '../i18n' {
namespace I18n {
interface Definition {
core: {
validator: {
required: I18nFormat<{
label: string;
}>;
validation_failed: I18nFormat;
array: {
must_be_array: I18nFormat<{
label: string;
}>;
length_not_in_range: I18nFormat<{
label: string;
}>;
};
boolean: {
must_be_boolean: I18nFormat<{
label: string;
}>;
};
buffer: {
must_be_buffer: I18nFormat<{
label: string;
}>;
};
dateTime: {
must_be_date: I18nFormat<{
label: string;
}>;
not_in_range: I18nFormat<{
label: string;
}>;
};
number: {
must_be_number: I18nFormat<{
label: string;
}>;
must_be_integer: I18nFormat<{
label: string;
}>;
must_be_bigint: I18nFormat<{
label: string;
}>;
not_in_range: I18nFormat<{
label: string;
}>;
};
string: {
must_be_string: I18nFormat<{
label: string;
}>;
must_be_email: I18nFormat<{
label: string;
}>;
must_be_hash: I18nFormat<{
label: string;
}>;
must_be_ulid: I18nFormat<{
label: string;
}>;
must_be_uuid: I18nFormat<{
label: string;
versions: string;
}>;
must_be_ip: I18nFormat<{
label: string;
versions: string;
}>;
length_not_in_range: I18nFormat<{
label: string;
}>;
not_match_pattern: I18nFormat<{
label: string;
}>;
};
url: {
must_be_url: I18nFormat<{
label: string;
}>;
unsupported_scheme: I18nFormat<{
label: string;
scheme: string;
}>;
};
object: {
must_be_object: I18nFormat<{
label: string;
}>;
};
enum: {
not_in_range: I18nFormat<{
label: string;
}>;
only_support_string_number: I18nFormat;
can_not_be_empty: I18nFormat<{
item: any;
}>;
};
one_of: {
not_match_rule: I18nFormat<{
label: string;
}>;
};
};
middleware: {
call_next_multiple: I18nFormat;
};
};
}
}
}
interface MiddlewarePlatform {
}
declare namespace Middleware {

@@ -26,6 +197,13 @@ type Infer<T> = T extends Middleware<infer R> ? R : T extends (...args: any[]) => Middleware<infer R> ? R : never;

declare abstract class Middleware<Props extends object = object> {
readonly fn: Middleware.Fn;
protected readonly fn: Middleware.Fn;
_contextType: object;
protected _props_must_be_used_: Props;
constructor(fn: Middleware.Fn);
/**
* 跳过执行中间件。
*
* 返回的类型未使用Partial,因为skip的设计是在部分场景下才需要触发的。
*/
skip(when: (ctx: this['_contextType']) => boolean | Promise<boolean>): Middleware<Props>;
/**
* 注册中间件

@@ -37,19 +215,32 @@ */

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 Next = () => Promise<any>;
type ComposeFn = (ctx: any, next?: Next) => Promise<void>;
/**
* 组合中间件
*/
declare const compose: (middlewareList: Middleware[]) => ComposeFn;
declare module './middleware' {
interface MiddlewarePlatform {
/**
* 没有特定上下文的纯中间件,支持所有应用
*/
readonly mixin: {
<Props extends object = object>(fn: (ctx: NonReadonly<Props>, next: Next) => any): MixinMiddleware<Props>;
};
}
}
declare class MixinMiddleware<Props extends object = object> extends Middleware<Props> {
protected _mixin_middleware_: 'mixin-middleware';
}
type MiddleWareToken<P extends object = object> = Chain<P> | Middleware<P>;
interface ChainPlatform {
/**
* 没有特定上下文的纯链条,支持所有应用
*/
readonly pure: PureChain;
type MiddleWareToken<P extends object = object> = MiddlewareChain<P> | Middleware<P>;
interface MiddlewareChainPlatform {
}
declare abstract class Chain<Props extends object = object> {
declare namespace MiddlewareChain {
type Infer<T> = T extends MiddlewareChain<infer R> ? R : never;
}
declare abstract class MiddlewareChain<Props extends object = object> {
protected readonly middlewareList: Middleware[];
protected _: Props;
protected static autoIncrementID: number;

@@ -59,13 +250,9 @@ /**

*/
static register(platform: keyof ChainPlatform, SubChain: new (...args: any[]) => Chain): void;
static register(platform: keyof MiddlewareChainPlatform, SubClass: new (...args: any[]) => MiddlewareChain): void;
protected createPoint(): string;
/**
* 平坦中间件和链条,并返回中间件列表
*/
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 split(point?: string | string[]): this;
protected readonly SubClass: new (middlewareList?: Middleware[]) => MiddlewareChain;
protected points: Record<string, number>;

@@ -76,12 +263,26 @@ constructor(middlewareList?: Middleware[]);

*/
protected mount<P extends object>(middleware: MiddleWareToken<P> | null): Chain<Props & P>;
protected mount<P extends object>(token: MiddleWareToken<P> | null): MiddlewareChain<Props & P>;
}
declare const chain: ChainPlatform;
declare const mdchain: MiddlewareChainPlatform;
type Next = () => Promise<any>;
type Compose = (ctx: any, next?: Next) => Promise<any>;
declare module './middleware-chain' {
interface MiddlewareChainPlatform {
/**
* 没有特定上下文的纯链条,支持所有应用
*/
readonly mixin: MixinMiddlewareChain;
}
}
type MixinMiddlewareToken<P extends object = object> = MixinMiddlewareChain<P> | MixinMiddleware<P>;
declare class MixinMiddlewareChain<Props extends object = object> extends MiddlewareChain<Props> {
protected _mixin_chain_: 'mixin-chain';
mount: {
<P extends object>(token: MixinMiddlewareToken<P> | null): MixinMiddlewareChain<Props & P>;
};
}
/**
* 组合中间件和链条
* 拍平中间件和链条,并返回中间件列表
*/
declare const compose: (tokens: MiddleWareToken[]) => Compose;
declare const flattenMiddlewareToken: (tokens?: MiddleWareToken | null | Array<MiddleWareToken | null>) => Middleware[];

@@ -94,6 +295,3 @@ declare namespace magistrate {

interface Fail {
errors: {
path: string[];
message: string;
}[];
errors: string[];
}

@@ -103,3 +301,3 @@ }

ok: <T>(result: T) => magistrate.Ok<T>;
fail: (message: string, key: string, superKeys: string[]) => magistrate.Fail;
fail: (message: string) => magistrate.Fail;
noError: <T_1>(result: magistrate.Result<T_1>) => result is magistrate.Ok<T_1>;

@@ -144,3 +342,2 @@ };

declare abstract class Validator<T = unknown> {
static $rootKey: string;
protected readonly SubClass: new (...args: any[]) => Validator;

@@ -151,5 +348,5 @@ constructor();

/**
* 设置严格模式,数据不再做兼容性处理。默认配置:`false`
* @param is 是否开启,默认值:`true`
*/
strict(is?: boolean): this;
protected strict(is?: boolean): this;
/**

@@ -191,7 +388,7 @@ * 扩展openapi的配置

protected default(value: any): Validator;
protected validate(value: any, key?: string, superKeys?: string[]): Promise<magistrate.Result<any>>;
protected validate(value: any, key?: string, label?: 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 abstract validateValue(value: any, key: string, label: string): Promise<magistrate.Result<any>> | magistrate.Result<any>;
protected copy(): Validator;

@@ -202,32 +399,2 @@ protected copyConfig(prev: Validator): this;

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 {

@@ -239,2 +406,6 @@ interface Options<T> extends Validator.Options<T> {

}
interface LengthRange {
min?: number;
max?: number;
}
}

@@ -246,9 +417,10 @@ declare abstract class BaseStringValidator<T = string> extends Validator<T> {

*/
trim(): this;
protected trim(is?: boolean): this;
protected length(exactLength: number): this;
protected length(range: BaseStringValidator.LengthRange): 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 validateValue(value: any, key: string, label: string): magistrate.Result<any> | Promise<magistrate.Result<any>>;
protected abstract validateString(value: string, key: string, label: string): magistrate.Result<any> | Promise<magistrate.Result<any>>;
protected copy: () => BaseStringValidator<T>;

@@ -258,30 +430,48 @@ protected toDocument(): OpenAPIV3.SchemaObject;

declare namespace BaseNumberValidator {
interface Options<T = false> extends Validator.Options<T> {
min?: number;
minInclusive?: boolean;
max?: number;
maxInclusive?: boolean;
}
}
declare abstract class BaseNumberValidator<T = number> extends Validator<T> {
protected config: BaseNumberValidator.Options<T>;
/**
* 开启/关闭严格模式,开启后有以下限制:
* - 字符串不再尝试转换为数字
*/
strict: (is?: boolean) => this;
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;
/**
* 最小范围限制
* @param min 最小值
* @param inclusive 是否包含最小值,默认值:`true`
*/
min(min: number, inclusive?: boolean): this;
/**
* 最大范围限制
* @param min 最大值
* @param inclusive 是否包含最大值,默认值:`true`
*/
max(max: number, inclusive?: boolean): this;
protected validateValue(num: number, key: string, label: string): magistrate.Result<number>;
protected abstract validateNumber(num: number, key: string, label: string): magistrate.Result<number>;
protected copy: () => BaseNumberValidator<T>;
protected toDocument(): OpenAPIV3.SchemaObject;
}
declare class ValidatorError extends Error {
protected readonly errors: magistrate.Fail['errors'];
constructor(message: string | undefined, errors?: magistrate.Fail['errors']);
getValidateErrors(): string[];
}
type ValidateOptions = {
throwIfError?: true;
} | {
throwIfError: false;
type ValidatorToken = Validator | {
[key: string]: Validator;
};
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 function toValidator(validator: ValidatorToken): Validator;
declare function toValidator(validator: undefined): undefined;
declare function toValidator(validator: ValidatorToken | undefined): Validator | undefined;

@@ -302,19 +492,2 @@ declare namespace AnyValidator {

declare namespace ArrayValidator {
interface ForceOptions {
/**
* 过滤允许转换为数组的数据
*/
filter?: (value: any) => boolean;
transform?: (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> {

@@ -326,4 +499,12 @@ itemValidator?: Validator;

};
force: boolean | ForceOptions;
fromString?: string | RegExp;
force?: {
mode: 'separator' | 'block';
separator?: string | RegExp;
};
}
interface LengthRange {
min?: number;
max?: number;
}
}

@@ -333,21 +514,2 @@ declare class ArrayValidator<T = unknown[]> extends Validator<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;

@@ -358,10 +520,36 @@ optional: () => ArrayValidator<T | Validator.TOptional>;

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateValue(value: any, key: string, superKeys: string[]): Promise<magistrate.Result<any[]>>;
/**
* 强制将`非数组`的值转换成数组类型。控制台命令行和url查询字符串场景下,如果只传了一个元素,则有可能被识别为非数组,而传递多个元素时又变成了数组结构。
*
* @param mode 转换模式
*
* - `separator` 使用分割符号,把字符串拆分成数组
* - `block` 把值当成一个整体,作为数组的一个元素
*
* @param separator 分割符号,默认值:`new RegExp('\s*,\s*')`
*/
forceToArray(mode: 'separator', separator?: string | RegExp): ArrayValidator<T>;
forceToArray(mode: 'block'): ArrayValidator<T>;
length(exactLength: number): this;
length(range: ArrayValidator.LengthRange): this;
protected validateValue(value: any, key: string, label: string): Promise<magistrate.Result<any[]>>;
protected copy: () => ArrayValidator<T>;
protected toDocument(): OpenAPIV3.SchemaObject;
}
interface ArrayValidator extends MixinLength {
declare namespace BigIntValidator {
interface Options<T = false> extends Validator.Options<T> {
min?: bigint;
minInclusive?: boolean;
max?: bigint;
maxInclusive?: boolean;
}
}
declare class BigIntValidator<T = bigint> extends Validator<T> {
protected config: BigIntValidator.Options<T>;
/**
* 开启严格模式后:
* - string或者number不再转换为大整数
*/
strict: (is?: boolean) => this;
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;

@@ -372,3 +560,6 @@ optional: () => BigIntValidator<T | Validator.TOptional>;

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateValue(value: bigint, key: string, superKeys: string[]): magistrate.Result<bigint>;
min(min: bigint, inclusive?: boolean): this;
max(max: bigint, inclusive?: boolean): this;
protected validateValue(value: bigint, _key: string, label: string): magistrate.Result<bigint>;
protected copy: () => BigIntValidator<T>;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -379,4 +570,4 @@ }

interface Options<T> extends Validator.Options<T> {
trueValues?: any[];
falseValues?: any[];
truthyValues?: any[];
falsyValues?: any[];
}

@@ -386,2 +577,4 @@ }

protected config: BooleanValidator.Options<T>;
protected static defaultTruthyValues: any[];
protected static defaultFalsyValues: any[];
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;

@@ -399,3 +592,3 @@ optional: () => BooleanValidator<T | Validator.TOptional>;

*/
trueValues(values: any[]): BooleanValidator<T>;
setTruthyValues(values: any[]): BooleanValidator<T>;
/**

@@ -408,4 +601,4 @@ * 重新设置假值。默认值:`[0, '0', false, 'false']`

*/
falseValues(values: any[]): BooleanValidator<T>;
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<boolean>;
setFalsyValues(values: any[]): BooleanValidator<T>;
protected validateValue(value: any, _key: string, label: string): magistrate.Result<boolean>;
protected copy: () => BooleanValidator<T>;

@@ -417,3 +610,5 @@ protected toDocument(): OpenAPIV3.SchemaObject;

interface Options<T = Buffer> extends Validator.Options<T> {
fromEncodings?: Encodings[];
}
type Encodings = 'base64' | 'hex';
}

@@ -427,3 +622,11 @@ declare class BufferValidator<T = Buffer> extends Validator<T> {

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<Buffer>;
/**
* 尝试从其他类型恢复为buffer类型:
*
* - `hex` 从十六进制字符串恢复
* - `base64` 从base64字符串恢复
*/
parseFrom(...encodings: BufferValidator.Encodings[]): this;
protected validateValue(value: any, _key: string, label: string): magistrate.Result<Buffer>;
protected copy: () => this;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -438,2 +641,3 @@ }

maxInclusive?: boolean;
parseFromTimestamp?: boolean;
}

@@ -450,6 +654,13 @@ }

max(freshDate: () => Date, inclusive?: boolean): DateTimeValidator<T>;
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<Date>;
/**
* 尝试把时间戳数字解析成时间对象。支持如下格式:
* - 13位:1711257956199
* - 14位:1711257956.199
* - 10位:1711257956
*/
parseFromTimestamp(is?: boolean): this;
protected validateValue(value: any, _key: string, label: string): magistrate.Result<Date>;
protected toDate(value: any): false | Date;
protected compare(date: Date): boolean;
protected copy: () => DateTimeValidator<T>;
protected copy: () => this;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -460,3 +671,2 @@ }

interface Options<T> extends BaseStringValidator.Options<T> {
lengthRange?: LengthRange;
}

@@ -472,7 +682,5 @@ }

match: (pattern: RegExp) => this;
protected validateValue(email: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(email: string, _key: string, label: string): magistrate.Result<string>;
protected toDocument(): OpenAPIV3.SchemaObject;
}
interface EmailValidator extends MixinLength {
}

@@ -484,5 +692,10 @@ declare namespace EnumValidator {

}
declare class EnumValidator<T = never> extends Validator<T> {
declare class EnumValidator<const T = never> extends Validator<T> {
protected config: EnumValidator.Options<T>;
constructor(ranges?: T[]);
/**
* 开启/关闭严格模式。开启后有如下限制:
* - 枚举中包含数字时,如果传递的值为字符串类型,则不再转换为数字后再对比
*/
strict: (is?: boolean) => this;
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;

@@ -493,3 +706,3 @@ optional: () => EnumValidator<T | Validator.TOptional>;

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateValue(value: any, key: string, superKeys: string[]): magistrate.Result<any>;
protected validateValue(value: any, _key: string, label: string): magistrate.Result<any>;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -499,3 +712,3 @@ }

declare namespace HashValidator {
type Algorithm = keyof typeof HashValidator.algorithmLength;
type Algorithm = keyof (typeof HashValidator)['algorithmLength'];
interface Options<T> extends BaseStringValidator.Options<T> {

@@ -509,3 +722,3 @@ algorithm: HashValidator.Algorithm;

*/
static algorithmLength: {
protected static algorithmLength: {
readonly md5: 32;

@@ -525,3 +738,3 @@ readonly md4: 32;

};
static algorithmPattern: Record<string, RegExp>;
protected static algorithmPattern: Record<string, RegExp>;
protected config: HashValidator.Options<T>;

@@ -534,3 +747,3 @@ constructor(algorithm: HashValidator.Algorithm);

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateValue(hash: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(hash: string, _key: string, label: string): magistrate.Result<string>;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -541,4 +754,2 @@ }

protected config: BaseNumberValidator.Options<T>;
constructor();
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;
optional: () => IntValidator<T | Validator.TOptional>;

@@ -548,2 +759,3 @@ nullable: () => IntValidator<T | null>;

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateNumber(num: number, _key: string, label: string): magistrate.Result<number>;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -571,9 +783,12 @@ }

match: (pattern: RegExp) => this;
protected validateValue(ip: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(ip: string, _key: string, label: string): magistrate.Result<string>;
protected toDocument(): OpenAPIV3.SchemaObject;
}
declare namespace NumberValidator {
interface Options<T = false> extends BaseNumberValidator.Options<T> {
}
}
declare class NumberValidator<T = number> extends BaseNumberValidator<T> {
protected config: BaseNumberValidator.Options<T>;
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;
protected config: NumberValidator.Options<T>;
optional: () => NumberValidator<T | Validator.TOptional>;

@@ -583,4 +798,4 @@ nullable: () => NumberValidator<T | null>;

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
precision(maxDecimals: number): NumberValidator<T>;
protected copy: () => NumberValidator<T>;
protected validateNumber(num: number): magistrate.Result<number>;
protected copy: () => this;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -599,3 +814,7 @@ }

constructor(properties?: ObjectValidator.Property);
strict(is?: boolean): this;
/**
* 开启严格模式后:
* - 不从字符串解析出对象,除非通过`parseFromString()`手动指定
*/
strict: (is?: boolean) => this;
docs: (docs: Validator.PartialOpenAPISchema, mode?: Validator.DocumentMergeMode) => this;

@@ -607,7 +826,8 @@ optional: () => ObjectValidator<T | Validator.TOptional>;

/**
* 如果是字符串,则尝试使用`JSON.parse`转换为对象。默认值:`false`
* 尝试使用`JSON.parse`把字符串转换为对象,在非严格模式下自动开启。
* @param is 默认值:`true`
*/
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 validateValue(origin: Record<string, any>, key: string, label: string): Promise<magistrate.Result<object>>;
protected copy: () => ObjectValidator<T>;

@@ -625,8 +845,7 @@ protected copyConfig(prev: ObjectValidator): this;

protected config: OneOfValidator.Options<T>;
constructor(rules: Validator[]);
strict(is?: boolean): this;
constructor(validators: [Validator, ...Validator[]]);
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 validateValue(value: any, key: string, label: string): Promise<magistrate.Result<any>>;
protected copyConfig(prev: OneOfValidator): this;

@@ -649,14 +868,13 @@ protected toDocument(): OpenAPIV3.SchemaObject;

match: (pattern: RegExp) => this;
trim: (is?: boolean) => this;
length: (exactOrRange: number | BaseStringValidator.LengthRange) => this;
/**
* 把空字符串`''`设置为合法的值。默认值:`false`
* 把空字符串`''`设置为合法的值
*/
allowEmpty(): StringValidator<T>;
trim: () => this;
allowEmptyString(): StringValidator<T>;
protected isEmpty(value: any): boolean;
protected validateValue(value: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(value: string): magistrate.Result<string>;
protected copy: () => StringValidator<T>;
protected toDocument(): OpenAPIV3.SchemaObject;
}
interface StringValidator extends MixinLength {
}

@@ -674,3 +892,3 @@ declare namespace UlidValidator {

transform: <T1>(fn: Validator.TransformFn<T, T1>) => TransformedValidator<T1>;
protected validateValue(ulid: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(ulid: string, _key: string, label: string): magistrate.Result<string>;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -681,3 +899,2 @@ }

interface Options<T> extends BaseStringValidator.Options<T> {
lengthRange?: LengthRange;
allowedScheme: string[];

@@ -698,8 +915,6 @@ }

scheme(scheme: string[]): UrlValidator<T>;
protected validateValue(url: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(url: string, _key: string, label: string): magistrate.Result<string>;
protected copy: () => UrlValidator<T>;
protected toDocument(): OpenAPIV3.SchemaObject;
}
interface UrlValidator extends MixinLength {
}

@@ -725,3 +940,3 @@ declare namespace UuidValidator {

match: (pattern: RegExp) => this;
protected validateValue(uuid: string, key: string, superKeys: string[]): magistrate.Result<string>;
protected validateString(uuid: string, _key: string, label: string): magistrate.Result<string>;
protected toDocument(): OpenAPIV3.SchemaObject;

@@ -753,2 +968,4 @@ }

/**
* 大整数类型
*
* 注意:非严格模式下,`number` 和 `string` 会尝试被转换成 `bigint` 类型

@@ -760,7 +977,2 @@ */

* - 默认假值:`[0, '0', false, 'false']`
*
* ```typescript
* rule.boolean();
* rule.boolean().trueValues([true, 'yes']).falseValues([false, 'no']);
* ```
*/

@@ -776,5 +988,2 @@ boolean(): BooleanValidator<boolean>;

* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型
*
* @see number()
* @see bigint()
*/

@@ -792,5 +1001,2 @@ int(): IntValidator<number>;

* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型
*
* @see int()
* @see bigint()
*/

@@ -804,3 +1010,3 @@ number(): NumberValidator<number>;

* profile: rule.object({
* sex: rule.enum(['unknow', 'male', 'female']),
* sex: rule.enum(['unknown', 'male', 'female']),
* }),

@@ -816,2 +1022,3 @@ * });

/**
* 匹配其中一个验证器
* ```typescript

@@ -838,76 +1045,13 @@ * rule.oneOf([rule.number(), rule.string()]);

type CompatibleValidator = Validator | {
[key: string]: Validator;
};
declare function forceToValidator(validator: CompatibleValidator): Validator;
declare function forceToValidator(validator: CompatibleValidator | undefined): Validator | undefined;
/**
* 验证传入数据,并返回可信的数据
*
* @param untrusted 数据源
* @param schema 验证器
* @param options.errorFormatter 报错文字格式化处理
*/
declare const validate: <T extends ValidatorToken>(untrusted: any, validators: T, options?: {
errorFormatter?: (errors: magistrate.Fail['errors']) => string | Promise<string>;
}) => Promise<Validator.Infer<T>>;
interface Caching {
/**
* 查看缓存是否存在
*/
exists(key: string): Promise<boolean>;
/**
*
* 获取缓存。如果未找到缓存并且未提供默认值,则返回`null`
* ```typescript
* await cache.get('key'); // null
* await cache.get('key', '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`
*
* ```typescript
* await cache.set('key', 'value');
* await cache.getAndDelete<string>('key'); // 'value'
* await cache.get('key'); // 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>;
/**
* 删除所有缓存。若指定了keyPrefix,则只删除有该前缀的缓存
*/
deleteAll(): Promise<boolean>;
}
export { AnyValidator, ArrayValidator, BaseNumberValidator, BaseStringValidator, BigIntValidator, BooleanValidator, BufferValidator, Caching, Chain, ChainPlatform, CompatibleValidator, Compose, DateTimeValidator, EmailValidator, EnumValidator, HashValidator, IntValidator, IpValidator, LengthRange, MiddleWareToken, Middleware, MiddlewarePlatform, MixinLength, Next, NumberValidator, ObjectValidator, OneOfValidator, PureChain, PureMiddleware, PureMiddlewareToken, Rule, StringValidator, TransformedValidator, UlidValidator, UrlValidator, UuidValidator, ValidateOptions, Validator, ValidatorError, _PureFn, chain, compose, forceToValidator, magistrate, middleware, mixinLength, rule, validate };
export { AnyValidator, ArrayValidator, BaseNumberValidator, BaseStringValidator, BigIntValidator, BooleanValidator, BufferValidator, type ComposeFn, DateTimeValidator, EmailValidator, EnumValidator, HashValidator, I18n, I18nFormat, IntValidator, IpValidator, type MiddleWareToken, Middleware, MiddlewareChain, type MiddlewareChainPlatform, type MiddlewarePlatform, MixinMiddleware, MixinMiddlewareChain, type MixinMiddlewareToken, type Next, NumberValidator, ObjectValidator, OneOfValidator, Rule, StringValidator, type TransformedValidator, UlidValidator, UrlValidator, UuidValidator, Validator, ValidatorError, type ValidatorToken, compose, flattenMiddlewareToken, i18n, magistrate, mdchain, middleware, rule, toValidator, validate };

@@ -1,64 +0,222 @@

// src/middleware/chain.ts
import { toArray } from "@aomex/internal-tools";
var Chain = class _Chain {
constructor(middlewareList = []) {
this.middlewareList = middlewareList;
this.SubClass = new.target;
// src/i18n/i18n-format.ts
var I18nFormat = class {
};
// src/i18n/i18n.ts
var I18n = class {
localeName;
fallbackLocaleName;
contents = {};
constructor(locale, fallbackLocale) {
this.localeName = locale;
this.fallbackLocaleName = fallbackLocale;
}
static autoIncrementID = 0;
/**
* 注册链条
*/
static register(platform, SubChain) {
Object.defineProperty(chain, platform, {
get() {
return new SubChain();
register(locale, category, content) {
this.contents[locale] = {
...this.contents[locale],
...{ [category]: content }
};
}
override(locale, content) {
const data = this.contents[locale];
this.set(data, content);
}
t(key, ...rest) {
const params = rest[0] || {};
const specificLocale = rest[1];
const localeName = specificLocale || this.getLocale();
const content = this.contents[localeName];
let sub = content;
if (sub) {
for (const k of key.split(".")) {
sub = sub[k];
if (!sub)
break;
}
});
}
/**
* 平坦中间件和链条,并返回中间件列表
*/
static flatten(middleware2) {
if (Array.isArray(middleware2)) {
return middleware2.reduce(
(carry, item) => carry.concat(_Chain.flatten(item)),
[]
}
if (sub) {
if (typeof sub === "string") {
return this.format(sub, params);
}
if (this.isMessageObject(sub)) {
const mergedArgs = {};
for (const [argName, argValue] of Object.entries(params)) {
const defaultArg = sub.args[argName];
mergedArgs[argName] = typeof defaultArg === "function" ? defaultArg(argValue) : argValue;
}
for (const [argName, argValue] of Object.entries(sub.args)) {
if (!Object.hasOwn(mergedArgs, argName)) {
mergedArgs[argName] = typeof argValue === "function" ? argValue(void 0) : argValue;
}
}
return this.format(sub.message, mergedArgs);
}
}
if (!specificLocale && this.fallbackLocaleName && localeName !== this.fallbackLocaleName) {
return this.t(
key,
// @ts-expect-error
params,
this.fallbackLocaleName
);
}
return middleware2 == null ? [] : middleware2 instanceof _Chain ? middleware2.middlewareList.slice() : [middleware2];
return key;
}
static createSplitPoint(chain2) {
const point = "point_" + ++this.autoIncrementID;
chain2.points[point] = chain2.middlewareList.length;
return point;
getLocale() {
return this.localeName;
}
/**
* 分割链条成两段,并返回后面那一段
*/
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);
setLocale(localeName) {
this.localeName = localeName;
return this;
}
SubClass;
points = {};
/**
* 挂载中间件和链条,支持传入`null`
*/
mount(middleware2) {
const chain2 = new this.SubClass(
this.middlewareList.concat(_Chain.flatten(middleware2))
);
chain2.points = this.points;
return chain2;
getFallbackLocale() {
return this.fallbackLocaleName;
}
setFallbackLocale(locale) {
this.fallbackLocaleName = locale;
return this;
}
format(message, args) {
for (let [argName, argValue] of Object.entries(args)) {
message = message.replace(`{{${argName}}}`, String(argValue));
}
return message;
}
set(data, override) {
Object.entries(override).forEach(([key, value]) => {
if (value === void 0)
return;
const origin = data[key];
if (!origin)
return;
if (typeof value === "string" || this.isMessageObject(value)) {
data[key] = value;
} else {
this.set(origin, value);
}
});
}
isMessageObject(value) {
return typeof value === "object" && typeof value["message"] === "string" && typeof value["args"] === "object";
}
};
var chain = {};
var i18n = new I18n("zh_CN");
// src/i18n/locales/zh-cn.ts
i18n.register("zh_CN", "core", {
validator: {
required: "{{label}}\uFF1A\u5FC5\u586B",
validation_failed: "\u9A8C\u8BC1\u5931\u8D25\uFF1A",
array: {
must_be_array: "{{label}}\uFF1A\u5FC5\u987B\u662F\u6570\u7EC4\u7C7B\u578B",
length_not_in_range: "{{label}}\uFF1A\u6570\u7EC4\u957F\u5EA6\u4E0D\u5728\u6307\u5B9A\u8303\u56F4\u5185"
},
boolean: {
must_be_boolean: "{{label}}\uFF1A\u5FC5\u987B\u662F\u5E03\u5C14\u7C7B\u578B"
},
buffer: {
must_be_buffer: "{{label}}\uFF1A\u5FC5\u987B\u662Fbuffer\u7C7B\u578B"
},
dateTime: {
must_be_date: "{{label}}\uFF1A\u5FC5\u987B\u662F\u65F6\u95F4\u7C7B\u578B",
not_in_range: "{{label}}\uFF1A\u4E0D\u5728\u6307\u5B9A\u65F6\u95F4\u5185"
},
number: {
must_be_number: "{{label}}\uFF1A\u5FC5\u987B\u662F\u6570\u5B57\u7C7B\u578B",
must_be_integer: "{{label}}\uFF1A\u5FC5\u987B\u662F\u6574\u6570",
must_be_bigint: "{{label}}\uFF1A\u5FC5\u987B\u662F\u5927\u6574\u6570\u7C7B\u578B",
not_in_range: "{{label}}\uFF1A\u4E0D\u5728\u6307\u5B9A\u7684\u6570\u5B57\u8303\u56F4"
},
string: {
must_be_string: "{{label}}\uFF1A\u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u7C7B\u578B",
must_be_email: "{{label}}\uFF1A\u5FC5\u987B\u662F\u7535\u5B50\u90AE\u4EF6\u683C\u5F0F",
must_be_hash: "{{label}}\uFF1A\u5FC5\u987B\u662F\u54C8\u5E0C\u683C\u5F0F",
must_be_ip: "{{label}}\uFF1A\u5FC5\u987B\u662FIP{{versions}}\u5730\u5740",
must_be_ulid: "{{label}}\uFF1A\u5FC5\u987B\u662FULID\u683C\u5F0F",
must_be_uuid: "{{label}}\uFF1A\u5FC5\u987B\u662FUUID{{versions}}\u683C\u5F0F",
length_not_in_range: "{{label}}\uFF1A\u5B57\u7B26\u4E32\u957F\u5EA6\u4E0D\u5408\u6CD5",
not_match_pattern: "{{label}}\uFF1A\u5B57\u7B26\u4E32\u672A\u5339\u914D\u5230\u89C4\u5219"
},
object: {
must_be_object: "{{label}}\uFF1A\u5FC5\u987B\u662F\u5BF9\u8C61\u7C7B\u578B"
},
enum: {
not_in_range: "{{label}}\uFF1A\u4E0D\u5728\u679A\u4E3E\u8303\u56F4",
only_support_string_number: "\u679A\u4E3E\u503C\u53EA\u80FD\u662F\u6570\u7EC4\u6216\u8005\u5B57\u7B26\u4E32",
can_not_be_empty: '\u679A\u4E3E\u503C\u4E0D\u80FD\u662F\u7A7A\u503C\uFF1A"{{item}}"'
},
one_of: {
not_match_rule: "{{label}}\uFF1A\u672A\u5339\u914D\u89C4\u5219"
},
url: {
must_be_url: "{{label}}\uFF1A\u5FC5\u987B\u662FURL\u683C\u5F0F",
unsupported_scheme: "{{label}}\uFF1AURL\u5305\u542B\u4E0D\u652F\u6301\u7684\u534F\u8BAE\uFF1A{{scheme}}"
}
},
middleware: {
call_next_multiple: "\u591A\u6B21\u6267\u884C\u4E2D\u95F4\u4EF6next()\u51FD\u6570"
}
});
// src/i18n/locales/en-us.ts
i18n.register("en_US", "core", {
validator: {
required: "{{label}}: required",
validation_failed: "Validate failed: ",
array: {
must_be_array: "{{label}}: must be array",
length_not_in_range: "{{label}}: array length not in range"
},
boolean: {
must_be_boolean: "{{label}}: must be boolean"
},
buffer: {
must_be_buffer: "{{label}}: must be buffer"
},
dateTime: {
must_be_date: "{{label}}: must be date-time",
not_in_range: "{{label}}: time not in range"
},
number: {
must_be_number: "{{label}}: must be number",
must_be_integer: "{{label}}: must be integer",
must_be_bigint: "{{label}}: must be bigint",
not_in_range: "{{label}}: number not in range"
},
string: {
must_be_string: "{{label}}: must be string",
must_be_email: "{{label}}: must be email",
must_be_hash: "{{label}}: must be hash format",
must_be_ip: "{{label}}: must be IP{{versions}} address",
must_be_ulid: "{{label}}: must be ULID format",
must_be_uuid: "{{label}}: must be UUID{{versions}} format",
length_not_in_range: "{{label}}: string length not in range",
not_match_pattern: "{{label}}: string not matched pattern"
},
object: {
must_be_object: "{{label}}: must be object"
},
enum: {
not_in_range: "{{label}}: not in enum",
only_support_string_number: "enum values can be only string or number",
can_not_be_empty: 'enum values can not be empty: "{{item}}"'
},
one_of: {
not_match_rule: "{{label}}: does not match rules"
},
url: {
must_be_url: "{{label}}: must be URL format",
unsupported_scheme: "{{label}}: URL contains unsupported scheme: {{scheme}}"
}
},
middleware: {
call_next_multiple: "call next() multiple times"
}
});
// src/interface/open-api.ts
import { OpenAPIV3 } from "openapi-types";
// src/middleware/compose.ts
var compose = (tokens) => {
const middlewareList = Chain.flatten(tokens);
var compose = (middlewareList) => {
return (ctx, next) => {

@@ -68,7 +226,7 @@ let lastIndex = -1;

if (i <= lastIndex) {
throw new Error("call next() multiple times");
throw new Error(i18n.t("core.middleware.call_next_multiple"));
}
const fn = i === middlewareList.length ? next : middlewareList[i].fn;
const fn = i === middlewareList.length ? next : middlewareList[i]["fn"];
lastIndex = i;
return fn?.(ctx, dispatch.bind(null, i + 1));
await fn?.(ctx, dispatch.bind(null, i + 1));
};

@@ -85,2 +243,13 @@ return dispatch(0);

/**
* 跳过执行中间件。
*
* 返回的类型未使用Partial,因为skip的设计是在部分场景下才需要触发的。
*/
skip(when) {
return middleware.mixin(async (ctx, next) => {
const skipped = await when(ctx);
return skipped ? next() : this.fn(ctx, next);
});
}
/**
* 注册中间件

@@ -91,3 +260,3 @@ */

get() {
return (fn) => new SubMiddleware(fn);
return (...args) => new SubMiddleware(...args);
}

@@ -99,15 +268,91 @@ });

// src/middleware/pure-middleware.ts
var PureMiddleware = class extends Middleware {
// src/middleware/mixin-middleware.ts
var MixinMiddleware = class extends Middleware {
};
Middleware.register("pure", PureMiddleware);
Middleware.register("mixin", MixinMiddleware);
// src/middleware/pure-chain.ts
var PureChain = class extends Chain {
// src/middleware/middleware-chain.ts
import { toArray } from "@aomex/internal-tools";
// src/middleware/flatten-middleware-token.ts
var flattenMiddlewareToken = (tokens) => {
if (Array.isArray(tokens)) {
return tokens.reduce(
(carry, item) => carry.concat(flattenMiddlewareToken(item)),
[]
);
}
return tokens == null ? [] : "middlewareList" in tokens ? tokens["middlewareList"].slice() : [tokens];
};
Chain.register("pure", PureChain);
// src/middleware/middleware-chain.ts
var MiddlewareChain = class _MiddlewareChain {
constructor(middlewareList = []) {
this.middlewareList = middlewareList;
this.SubClass = new.target;
}
_;
static autoIncrementID = 0;
/**
* 注册链条
*/
static register(platform, SubClass) {
Object.defineProperty(mdchain, platform, {
get() {
return new SubClass();
}
});
}
createPoint() {
const point = "point_" + ++_MiddlewareChain.autoIncrementID;
this.points[point] = this.middlewareList.length;
return point;
}
/**
* 分割链条成两段,并返回后面那一段
*/
split(point = []) {
const longestLengthOfPoint = toArray(point).map((p) => this.points[p]).filter(Boolean).sort((a, b) => b - a)[0];
if (!longestLengthOfPoint)
return this;
const middlewareList = this.middlewareList.slice(longestLengthOfPoint);
return new this.SubClass(middlewareList);
}
SubClass;
points = {};
/**
* 挂载中间件和链条,支持传入`null`
*/
mount(token) {
const chain = new this.SubClass(
this.middlewareList.concat(flattenMiddlewareToken(token))
);
chain.points = this.points;
return chain;
}
};
var mdchain = {};
// src/middleware/mixin-middleware-chain.ts
var MixinMiddlewareChain = class extends MiddlewareChain {
};
MiddlewareChain.register("mixin", MixinMiddlewareChain);
// src/validator/base/magistrate.ts
var magistrate = {
ok: (result) => {
return { ok: result };
},
fail: (message) => {
return {
errors: [message]
};
},
noError: (result) => {
return "ok" in result;
}
};
// src/validator/base/validator.ts
var Validator = class _Validator {
static $rootKey = Symbol("root").toString();
var Validator = class {
SubClass;

@@ -145,3 +390,3 @@ constructor() {

/**
* 设置严格模式,数据不再做兼容性处理。默认配置:`false`
* @param is 是否开启,默认值:`true`
*/

@@ -210,3 +455,3 @@ strict(is = true) {

}
async validate(value, key = _Validator.$rootKey, superKeys = []) {
async validate(value, key = "", label = "") {
const { defaultValue, required } = this.config;

@@ -218,5 +463,5 @@ if (this.isEmpty(value)) {

return magistrate.ok(
this.config.transform ? this.config.transform(value) : value
this.config.transform ? await this.config.transform(value) : value
);
return magistrate.fail("required", key, superKeys);
return magistrate.fail(i18n.t("core.validator.required", { label }));
}

@@ -226,8 +471,8 @@ }

return magistrate.ok(
this.config.transform ? this.config.transform(value) : value
this.config.transform ? await this.config.transform(value) : value
);
}
const result = await this.validateValue(value, key, superKeys);
const result = await this.validateValue(value, key, label);
if (magistrate.noError(result) && this.config.transform) {
result.ok = this.config.transform(result.ok);
result.ok = await this.config.transform(result.ok);
}

@@ -257,25 +502,75 @@ return result;

// src/validator/base/magistrate.ts
var magistrate = {
ok: (result) => {
return { ok: result };
},
fail: (message, key, superKeys) => {
// src/validator/base/base-string.ts
var BaseStringValidator = class extends Validator {
/**
* 删除两边空格后再进行验证
*/
trim(is = true) {
const validator = this.copy();
validator.config.trim = is;
return validator;
}
length(data) {
const validator = this.copy();
validator.config.lengthRange = typeof data === "number" ? { min: data, max: data } : data;
return validator;
}
match(pattern2) {
const validator = this.copy();
validator.config.pattern = pattern2;
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;
}
validateValue(value, key, label) {
const { pattern: pattern2, lengthRange } = this.config;
if (typeof value !== "string") {
return magistrate.fail(i18n.t("core.validator.string.must_be_string", { label }));
}
value = this.getTrimValue(value);
if (lengthRange) {
const { min = 0, max = Infinity } = lengthRange;
const length = value.length;
if (length < min || length > max) {
return magistrate.fail(
i18n.t("core.validator.string.length_not_in_range", { label })
);
}
}
if (pattern2 && !pattern2.test(value)) {
return magistrate.fail(
i18n.t("core.validator.string.not_match_pattern", { label })
);
}
return this.validateString(value, key, label);
}
toDocument() {
const { lengthRange = {}, pattern: pattern2 } = this.config;
return {
errors: [
{
path: superKeys.concat(key).filter((item) => item !== Validator.$rootKey),
message
}
]
type: "string",
// FIXME: openapi没地方放`pattern.flags`
pattern: pattern2 ? pattern2.source : void 0,
minLength: lengthRange.min,
maxLength: lengthRange.max
};
},
noError: (result) => {
return "ok" in result;
}
};
// src/validator/base/base-number-validator.ts
var precisionPattern = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
// src/validator/base/base-number.ts
var BaseNumberValidator = class extends Validator {
/**
* 最小范围限制
* @param min 最小值
* @param inclusive 是否包含最小值,默认值:`true`
*/
min(min, inclusive = true) {

@@ -287,2 +582,7 @@ const validator = this.copy();

}
/**
* 最大范围限制
* @param min 最大值
* @param inclusive 是否包含最大值,默认值:`true`
*/
max(max, inclusive = true) {

@@ -294,3 +594,3 @@ const validator = this.copy();

}
validateValue(num, key, superKeys) {
validateValue(num, key, label) {
const {

@@ -301,4 +601,2 @@ min = -Infinity,

maxInclusive,
onlyInteger,
precision,
strict

@@ -310,18 +608,8 @@ } = this.config;

if (!Number.isFinite(num)) {
return magistrate.fail("must be number", key, superKeys);
return magistrate.fail(i18n.t("core.validator.number.must_be_number", { label }));
}
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);
return magistrate.fail(i18n.t("core.validator.number.not_in_range", { label }));
}
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);
return this.validateNumber(num, key, label);
}

@@ -340,67 +628,14 @@ toDocument() {

// src/validator/base/base-string-validator.ts
var BaseStringValidator = class extends Validator {
/**
* 删除两边空格后再进行验证
*/
trim() {
const validator = this.copy();
validator.config.trim = true;
return validator;
// src/validator/base/validator-error.ts
var ValidatorError = class extends Error {
constructor(message, errors = []) {
super(message);
this.errors = errors;
}
match(pattern2) {
const validator = this.copy();
validator.config.pattern = pattern2;
return validator;
getValidateErrors() {
return this.errors;
}
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: pattern2 } = this.config;
if (pattern2 && !pattern2.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: pattern2 } = this.config;
return {
type: "string",
// FIXME: openapi没地方放`pattern.flags`
pattern: pattern2 ? pattern2.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
// src/validator/validators/any.ts
var AnyValidator = class extends Validator {

@@ -424,18 +659,3 @@ validateValue(value) {

// 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
// src/validator/validators/array.ts
var ArrayValidator = class extends Validator {

@@ -446,34 +666,16 @@ constructor(validator) {

this.config.lengthRange = {};
this.config.force = false;
}
strict(is = true) {
const validator = super.strict(is);
validator.config.itemValidator = validator.config.itemValidator?.strict(is);
forceToArray(mode, separator) {
const validator = this.copy();
validator.config.force = { mode, separator };
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 = {}) {
length(data) {
const validator = this.copy();
validator.config.force = options2 || true;
validator.config.lengthRange = typeof data === "number" ? { min: data, max: data } : data;
return validator;
}
async validateValue(value, key, superKeys) {
async validateValue(value, key, label) {
const {
force = false,
force,
lengthRange: { min = 0, max = Infinity },

@@ -485,28 +687,25 @@ itemValidator

items = value.slice();
} else if (force !== false) {
const {
filter = () => true,
stringCommaSeparator,
stringSeparator,
transform = (_) => [_]
} = force === true ? {} : force;
if (filter(value)) {
if ((stringCommaSeparator || stringSeparator) && typeof value === "string") {
items = value.split(
stringCommaSeparator ? /\s*,\s*/ : stringSeparator
);
} else {
items = transform(value);
}
} else if (force) {
const { mode, separator = /\s*,\s*/ } = force;
switch (mode) {
case "block":
items = [value];
break;
case "separator":
if (typeof value === "string") {
items = value.split(separator);
}
break;
}
}
if (!Array.isArray(items)) {
return magistrate.fail("must be array", key, superKeys);
return magistrate.fail(i18n.t("core.validator.array.must_be_array", { label }));
}
const length = items.length;
if (length < min || length > max) {
return magistrate.fail(`contains invalid items length`, key, superKeys);
return magistrate.fail(
i18n.t("core.validator.array.length_not_in_range", { label })
);
}
if (itemValidator) {
const newSuperKeys = superKeys.concat(key);
let error = {

@@ -520,3 +719,3 @@ errors: []

index.toString(),
newSuperKeys
label && key ? `${label}.${index}` : index.toString()
);

@@ -545,28 +744,57 @@ if (magistrate.noError(result)) {

};
mixinLength(ArrayValidator);
// src/validator/validators/bigInt-validator.ts
// src/validator/validators/bigInt.ts
var BigIntValidator = class extends Validator {
validateValue(value, key, superKeys) {
const { strict } = this.config;
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(value, _key, label) {
const {
strict,
min = -Infinity,
max = Infinity,
minInclusive,
maxInclusive
} = 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 {
let num;
if (type !== "bigint") {
if (!strict && (type === "number" || type === "string")) {
try {
num = BigInt(value);
} catch {
}
}
if (num === void 0) {
return magistrate.fail(i18n.t("core.validator.number.must_be_bigint", { label }));
}
} else {
num = value;
}
return magistrate.fail("must be bigint", key, superKeys);
if ((minInclusive ? num < min : num <= min) || (maxInclusive ? num > max : num >= max)) {
return magistrate.fail(i18n.t("core.validator.number.not_in_range", { label }));
}
return magistrate.ok(num);
}
toDocument() {
const { min, max, minInclusive, maxInclusive } = this.config;
const defaultValue = this.getDefaultValue(this.config.defaultValue);
return {
type: "string",
format: "bigint",
type: "integer",
format: "int64",
// JSON.stringify 无法处理bigint类型
default: this.getDefaultValue(
this.config.defaultValue
)?.toString()
default: defaultValue === void 0 ? void 0 : Number(defaultValue),
minimum: min === void 0 ? void 0 : Number(min),
maximum: max === void 0 ? void 0 : Number(max),
exclusiveMinimum: minInclusive === void 0 ? void 0 : !minInclusive,
exclusiveMaximum: maxInclusive === void 0 ? void 0 : !maxInclusive
};

@@ -576,6 +804,6 @@ }

// src/validator/validators/boolean-validator.ts
var defaultTrueValues = [1, "1", true, "true"];
var defaultFalseValues = [0, "0", false, "false"];
var BooleanValidator = class extends Validator {
// src/validator/validators/boolean.ts
var BooleanValidator = class _BooleanValidator extends Validator {
static defaultTruthyValues = [1, "1", true, "true"];
static defaultFalsyValues = [0, "0", false, "false"];
/**

@@ -588,5 +816,5 @@ * 重新设置真值。默认值:`[1, '1', true, 'true']`

*/
trueValues(values) {
setTruthyValues(values) {
const validator = this.copy();
validator.config.trueValues = values;
validator.config.truthyValues = values;
return validator;

@@ -601,9 +829,12 @@ }

*/
falseValues(values) {
setFalsyValues(values) {
const validator = this.copy();
validator.config.falseValues = values;
validator.config.falsyValues = values;
return validator;
}
validateValue(value, key, superKeys) {
const { trueValues = defaultTrueValues, falseValues = defaultFalseValues } = this.config;
validateValue(value, _key, label) {
const {
truthyValues: trueValues = _BooleanValidator.defaultTruthyValues,
falsyValues: falseValues = _BooleanValidator.defaultFalsyValues
} = this.config;
if (trueValues.includes(value)) {

@@ -615,3 +846,3 @@ return magistrate.ok(true);

}
return magistrate.fail("must be boolean", key, superKeys);
return magistrate.fail(i18n.t("core.validator.boolean.must_be_boolean", { label }));
}

@@ -625,11 +856,55 @@ toDocument() {

// src/validator/validators/buffer-validator.ts
// src/validator/validators/buffer.ts
var hexReg = /^(?:0x)?[0-9a-f]+$/i;
var base64Reg = /^([a-z0-9+/]{4})*([a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$/i;
var BufferValidator = class extends Validator {
validateValue(value, key, superKeys) {
/**
* 尝试从其他类型恢复为buffer类型:
*
* - `hex` 从十六进制字符串恢复
* - `base64` 从base64字符串恢复
*/
parseFrom(...encodings) {
const validator = this.copy();
validator.config.fromEncodings = [...new Set(encodings)];
return validator;
}
validateValue(value, _key, label) {
const { fromEncodings = [] } = this.config;
let buffer;
if (!Buffer.isBuffer(value)) {
return magistrate.fail("must be buffer", key, superKeys);
loop:
for (const encoding of fromEncodings) {
switch (encoding) {
case "hex":
if (typeof value === "string" && hexReg.test(value)) {
try {
buffer = Buffer.from(value.replace(/^0x/i, ""), "hex");
break loop;
} catch {
}
}
break;
case "base64":
if (typeof value === "string" && base64Reg.test(value)) {
try {
buffer = Buffer.from(value, "base64");
break loop;
} catch {
}
}
}
}
} else {
buffer = value;
}
return magistrate.ok(value);
if (!buffer) {
return magistrate.fail(i18n.t("core.validator.buffer.must_be_buffer", { label }));
}
return magistrate.ok(buffer);
}
toDocument() {
const defaultValue = this.getDefaultValue(
this.config.defaultValue
);
return {

@@ -639,3 +914,3 @@ type: "string",

// JSON 无法处理buffer类型
default: void 0
default: defaultValue && defaultValue.toString("base64")
};

@@ -645,3 +920,4 @@ }

// src/validator/validators/date-time-validator.ts
// src/validator/validators/date-time.ts
var unixTimeWithMS = /^[0-9]{10}\.[0-9]{3}$/;
var DateTimeValidator = class extends Validator {

@@ -660,9 +936,20 @@ min(freshDate, inclusive = true) {

}
validateValue(value, key, superKeys) {
/**
* 尝试把时间戳数字解析成时间对象。支持如下格式:
* - 13位:1711257956199
* - 14位:1711257956.199
* - 10位:1711257956
*/
parseFromTimestamp(is = true) {
const validator = this.copy();
validator.config.parseFromTimestamp = is;
return validator;
}
validateValue(value, _key, label) {
const date = this.toDate(value);
if (date === false) {
return magistrate.fail("must be date", key, superKeys);
if (date === false || date.toString() === "Invalid Date") {
return magistrate.fail(i18n.t("core.validator.dateTime.must_be_date", { label }));
}
if (!this.compare(date)) {
return magistrate.fail("not in date range", key, superKeys);
return magistrate.fail(i18n.t("core.validator.dateTime.not_in_range", { label }));
}

@@ -672,11 +959,16 @@ return magistrate.ok(date);

toDate(value) {
if (value instanceof Date) {
if (value.toString() !== "Invalid Date") {
const { parseFromTimestamp } = this.config;
if (value instanceof Date)
return value;
if (typeof value === "string")
return new Date(value);
if (parseFromTimestamp && typeof value === "number") {
const timestamp = value.toString();
if (timestamp.length === 10)
return new Date(Number(value + "000"));
if (timestamp.length === 13)
return new Date(value);
if (timestamp.length === 14 && unixTimeWithMS.test(timestamp)) {
return new Date(Number(timestamp.replace(".", "")));
}
} else if (typeof value === "string") {
const date = new Date(value);
if (date.toString() !== "Invalid Date") {
return date;
}
}

@@ -697,5 +989,7 @@ return false;

toDocument() {
const defaultValue = this.getDefaultValue(this.config.defaultValue);
return {
type: "string",
format: "date-time"
format: "date-time",
default: defaultValue?.toISOString()
};

@@ -705,19 +999,8 @@ }

// src/validator/validators/email-validator.ts
// src/validator/validators/email.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;
validateString(email, _key, label) {
if (!emailValidator.validate(email)) {
return magistrate.fail("must be email", key, superKeys);
return magistrate.fail(i18n.t("core.validator.string.must_be_email", { label }));
}

@@ -733,5 +1016,4 @@ return magistrate.ok(email);

};
mixinLength(EmailValidator);
// src/validator/validators/enum-validator.ts
// src/validator/validators/enum.ts
var EnumValidator = class extends Validator {

@@ -743,14 +1025,24 @@ constructor(ranges = []) {

if (this.isEmpty(item)) {
throw new Error(
`enum items should not contains empty value: "${item}"`
);
throw new Error(i18n.t("core.validator.enum.can_not_be_empty", { item }));
}
if (typeof item !== "string" && typeof item !== "number") {
throw new Error(i18n.t("core.validator.enum.only_support_string_number"));
}
});
}
validateValue(value, key, superKeys) {
const { ranges } = this.config;
if (!ranges.includes(value)) {
return magistrate.fail("not in enum range", key, superKeys);
validateValue(value, _key, label) {
const { ranges, strict } = this.config;
if (ranges.includes(value))
return magistrate.ok(value);
if (!strict && typeof value === "string") {
const num = Number(value);
if (!Number.isNaN(num)) {
const matched = ranges.find(
(item) => typeof item === "number" ? item === num : false
);
if (matched)
return magistrate.ok(matched);
}
}
return magistrate.ok(value);
return magistrate.fail(i18n.t("core.validator.enum.not_in_range", { label }));
}

@@ -767,3 +1059,3 @@ toDocument() {

// src/validator/validators/hash-validator.ts
// src/validator/validators/hash.ts
var HashValidator = class _HashValidator extends BaseStringValidator {

@@ -798,16 +1090,12 @@ /**

this.config.algorithm = algorithm;
if (!Object.hasOwn(_HashValidator.algorithmLength, algorithm)) {
throw new Error("\u672A\u77E5\u7684\u54C8\u5E0C\u7C7B\u578B");
}
}
validateValue(hash, key, superKeys) {
validateString(hash, _key, label) {
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);
const length = _HashValidator.algorithmLength[algorithm];
if (!_HashValidator.algorithmPattern[length].test(hash)) {
return magistrate.fail(i18n.t("core.validator.string.must_be_hash", { label }));
}
if (!_HashValidator.algorithmPattern[_HashValidator.algorithmLength[algorithm]].test(hash)) {
return magistrate.fail(`must be ${algorithm} hash`, key, superKeys);
}
return magistrate.ok(hash);

@@ -827,7 +1115,9 @@ }

// src/validator/validators/int-validator.ts
// src/validator/validators/int.ts
var IntValidator = class extends BaseNumberValidator {
constructor() {
super();
this.config.onlyInteger = true;
validateNumber(num, _key, label) {
if (!Number.isInteger(num)) {
return magistrate.fail(i18n.t("core.validator.number.must_be_integer", { label }));
}
return magistrate.ok(num);
}

@@ -842,3 +1132,3 @@ toDocument() {

// src/validator/validators/ip-validator.ts
// src/validator/validators/ip.ts
import ipRegexp from "ip-regex";

@@ -855,14 +1145,6 @@ var versions = ["v4", "v6"];

super();
this.config.ipVersion = version;
this.config.ipVersion = [...new Set(version)];
}
validateValue(ip, key, superKeys) {
validateString(ip, _key, label) {
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;

@@ -881,5 +1163,6 @@ if (ipVersion.length === versions.length) {

return magistrate.fail(
`must be IP${ipVersion.length === 1 ? ipVersion : `[${ipVersion.join(",")}]`} address`,
key,
superKeys
i18n.t("core.validator.string.must_be_ip", {
label,
versions: ipVersion.toString()
})
);

@@ -898,8 +1181,6 @@ }

// src/validator/validators/number-validator.ts
// src/validator/validators/number.ts
var NumberValidator = class extends BaseNumberValidator {
precision(maxDecimals) {
const validator = this.copy();
validator.config.precision = Math.min(20, Math.max(0, maxDecimals));
return validator;
validateNumber(num) {
return magistrate.ok(num);
}

@@ -914,3 +1195,3 @@ toDocument() {

// src/validator/validators/object-validator.ts
// src/validator/validators/object.ts
var ObjectValidator = class extends Validator {

@@ -921,14 +1202,5 @@ constructor(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`
* 尝试使用`JSON.parse`把字符串转换为对象,在非严格模式下自动开启。
* @param is 默认值:`true`
*/

@@ -943,7 +1215,7 @@ parseFromString(is = true) {

}
async validateValue(origin, key, superKeys) {
const { properties, stringToObject = false } = this.config;
async validateValue(origin, key, label) {
const { properties, stringToObject, strict } = this.config;
if (!this.isPlainObject(origin)) {
let valid = false;
if (stringToObject && typeof origin === "string") {
if ((!strict && stringToObject !== false || strict && stringToObject) && typeof origin === "string") {
try {

@@ -956,3 +1228,3 @@ origin = JSON.parse(origin);

if (!valid) {
return magistrate.fail("must be plain object", key, superKeys);
return magistrate.fail(i18n.t("core.validator.object.must_be_object", { label }));
}

@@ -962,4 +1234,3 @@ }

if (properties) {
const newSuperKeys = superKeys.concat(key);
let error = {
const error = {
errors: []

@@ -972,3 +1243,3 @@ };

propKey,
newSuperKeys
label && key ? `${label}.${propKey}` : propKey
);

@@ -991,3 +1262,5 @@ if (magistrate.noError(result)) {

super.copyConfig(prev);
this.config.properties = { ...prev.config.properties };
this.config.properties = prev.config.properties && {
...prev.config.properties
};
return this;

@@ -1012,30 +1285,20 @@ }

// src/validator/validators/one-of-validator.ts
// src/validator/validators/one-of.ts
var OneOfValidator = class extends Validator {
constructor(rules) {
constructor(validators) {
super();
this.config.validators = rules;
this.config.validators = validators;
}
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) {
async validateValue(value, key, label) {
const { validators } = this.config;
for (let i = 0; i < validators.length; ++i) {
const result = await validators[i].validate(
value,
key,
superKeys
);
const validator = validators[i];
const result = await validator.validate(value, key, label);
if (magistrate.noError(result))
return result;
}
return magistrate.fail("no rule matched", key, superKeys);
return magistrate.fail(i18n.t("core.validator.one_of.not_match_rule", { label }));
}

@@ -1050,5 +1313,3 @@ copyConfig(prev) {

return {
oneOf: validators.map(
(validator) => Validator.toDocument(validator).schema
)
oneOf: validators.map((validator) => Validator.toDocument(validator).schema)
};

@@ -1058,8 +1319,8 @@ }

// src/validator/validators/string-validator.ts
// src/validator/validators/string.ts
var StringValidator = class extends BaseStringValidator {
/**
* 把空字符串`''`设置为合法的值。默认值:`false`
* 把空字符串`''`设置为合法的值
*/
allowEmpty() {
allowEmptyString() {
const validator = this.copy();

@@ -1070,18 +1331,7 @@ validator.config.allowEmpty = true;

isEmpty(value) {
if (value != null && this.config.allowEmpty)
if (value === "" && 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;
validateString(value) {
return magistrate.ok(value);

@@ -1093,18 +1343,9 @@ }

};
mixinLength(StringValidator);
// src/validator/validators/ulid-validator.ts
// src/validator/validators/ulid.ts
var pattern = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
var UlidValidator = class extends BaseStringValidator {
validateValue(ulid, key, superKeys) {
let checker;
checker = this.shouldBeString(ulid, key, superKeys);
if (checker)
return checker;
ulid = this.getTrimValue(ulid);
checker = this.shouldMatchPattern(ulid, key, superKeys);
if (checker)
return checker;
validateString(ulid, _key, label) {
if (!pattern.test(ulid)) {
return magistrate.fail(`must be ULID`, key, superKeys);
return magistrate.fail(i18n.t("core.validator.string.must_be_ulid", { label }));
}

@@ -1121,3 +1362,3 @@ return magistrate.ok(ulid);

// src/validator/validators/url.validator.ts
// src/validator/validators/url.ts
import { URL } from "node:url";

@@ -1137,24 +1378,13 @@ var UrlValidator = class extends BaseStringValidator {

}
validateValue(url, key, superKeys) {
validateString(url, _key, label) {
const { allowedScheme } = this.config;
let checker;
checker = this.shouldBeString(url, key, superKeys);
if (checker)
return checker;
url = this.getTrimValue(url);
checker = this.shouldBetweenLength(url, key, superKeys);
if (checker)
return checker;
if (!/^[a-z0-9]+:\/\//.test(url)) {
return magistrate.fail("must be url", key, superKeys);
if (!/^[a-z0-9]+:\/\/.+/.test(url) || !URL.canParse(url)) {
return magistrate.fail(i18n.t("core.validator.url.must_be_url", { label }));
}
let parsedUrl;
try {
parsedUrl = new URL(url);
} catch {
return magistrate.fail("must be url", key, superKeys);
}
const parsedUrl = new URL(url);
const scheme = parsedUrl.protocol.slice(0, -1);
if (!allowedScheme.includes(scheme)) {
return magistrate.fail("invalid url scheme", key, superKeys);
return magistrate.fail(
i18n.t("core.validator.url.unsupported_scheme", { label, scheme })
);
}

@@ -1170,5 +1400,4 @@ return magistrate.ok(url);

};
mixinLength(UrlValidator);
// src/validator/validators/uuid-validator.ts
// src/validator/validators/uuid.ts
var createRegexp = (version) => {

@@ -1194,14 +1423,6 @@ const group = "[0-9a-f]";

super();
this.config.uuidVersion = versions2;
this.config.uuidVersion = [...new Set(versions2)];
}
validateValue(uuid, key, superKeys) {
validateString(uuid, _key, label) {
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;

@@ -1220,5 +1441,6 @@ if (uuidVersion.length === _UuidValidator.versions.length) {

return magistrate.fail(
`must be UUID[${uuidVersion.join(",")}]`,
key,
superKeys
i18n.t("core.validator.string.must_be_uuid", {
label,
versions: uuidVersion.join(",")
})
);

@@ -1236,4 +1458,4 @@ }

// src/validator/api/force-to-validator.ts
function forceToValidator(validator) {
// src/validator/api/to-validator.ts
function toValidator(validator) {
if (!validator)

@@ -1246,29 +1468,2 @@ return;

// src/validator/api/validate.ts
async function validate(source, schema, options2) {
const { throwIfError = true } = options2 || {};
const validator = forceToValidator(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

@@ -1293,5 +1488,7 @@ import { toArray as toArray2 } from "@aomex/internal-tools";

array(values) {
return new ArrayValidator(forceToValidator(values));
return new ArrayValidator(toValidator(values));
}
/**
* 大整数类型
*
* 注意:非严格模式下,`number` 和 `string` 会尝试被转换成 `bigint` 类型

@@ -1305,7 +1502,2 @@ */

* - 默认假值:`[0, '0', false, 'false']`
*
* ```typescript
* rule.boolean();
* rule.boolean().trueValues([true, 'yes']).falseValues([false, 'no']);
* ```
*/

@@ -1332,5 +1524,2 @@ boolean() {

* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型
*
* @see number()
* @see bigint()
*/

@@ -1348,9 +1537,6 @@ int() {

ip(version) {
return new IpValidator(toArray2(version, true));
return new IpValidator(toArray2(version));
}
/**
* 注意:非严格模式下,`string` 会尝试被转换成 `number` 类型
*
* @see int()
* @see bigint()
*/

@@ -1366,3 +1552,3 @@ number() {

* profile: rule.object({
* sex: rule.enum(['unknow', 'male', 'female']),
* sex: rule.enum(['unknown', 'male', 'female']),
* }),

@@ -1376,2 +1562,3 @@ * });

/**
* 匹配其中一个验证器
* ```typescript

@@ -1394,10 +1581,28 @@ * rule.oneOf([rule.number(), rule.string()]);

uuid(versions2) {
return new UuidValidator(toArray2(versions2, true));
return new UuidValidator(toArray2(versions2));
}
};
var rule = new Rule();
rule.url().scheme(["http", "ftp"]).strict();
// src/openapi-type/index.ts
import { OpenAPIV3 } from "openapi-types";
// src/validator/api/validate.ts
var validate = async (untrusted, validators, options2 = {}) => {
const { errorFormatter = defaultErrorFormatter } = options2;
const validator = toValidator(validators);
const source = await untrusted;
const trusted = await validator["validate"](source);
if (magistrate.noError(trusted))
return trusted.ok;
const msg = await errorFormatter(trusted.errors);
throw new ValidatorError(msg, trusted.errors);
};
var defaultErrorFormatter = (errors) => {
let msg = i18n.t("core.validator.validation_failed");
msg += "\n";
errors.forEach((err) => {
msg += `
- ${err}`;
});
msg += "\n";
return msg;
};
export {

@@ -1411,3 +1616,2 @@ AnyValidator,

BufferValidator,
Chain,
DateTimeValidator,

@@ -1417,5 +1621,10 @@ EmailValidator,

HashValidator,
I18n,
I18nFormat,
IntValidator,
IpValidator,
Middleware,
MiddlewareChain,
MixinMiddleware,
MixinMiddlewareChain,
NumberValidator,

@@ -1425,4 +1634,2 @@ ObjectValidator,

OpenAPIV3 as OpenAPI,
PureChain,
PureMiddleware,
Rule,

@@ -1435,11 +1642,12 @@ StringValidator,

ValidatorError,
chain,
compose,
forceToValidator,
flattenMiddlewareToken,
i18n,
magistrate,
mdchain,
middleware,
mixinLength,
rule,
toValidator,
validate
};
//# sourceMappingURL=index.js.map
{
"name": "@aomex/core",
"version": "0.0.28",
"description": "",
"version": "1.0.0",
"description": "aomex核心库",
"type": "module",

@@ -29,7 +29,7 @@ "types": "dist/index.d.ts",

"engines": {
"node": ">=18.12"
"node": "^20.9.0 || ^22"
},
"peerDependencies": {
"@types/node": "*",
"typescript": "^5"
"@types/node": "^20 || ^22",
"typescript": ">=5.4"
},

@@ -40,7 +40,5 @@ "dependencies": {

"openapi-types": "^12.1.3",
"@aomex/internal-tools": "^0.0.27"
"@aomex/internal-tools": "^1.0.0"
},
"scripts": {
"test": "vitest"
}
"scripts": {}
}

Sorry, the diff of this file is not supported yet

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