Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support zod #4287

Open
wants to merge 15 commits into
base: v4-next
Choose a base branch
from
2 changes: 1 addition & 1 deletion packages/core/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ export interface IMidwayBaseApplication<CTX extends IMidwayContext> {
* Get all configuration values or get the specified configuration through parameters
* @param key config key
*/
getConfig(key?: string): any;
getConfig<T = any>(key?: string): T;

/**
* Get default logger object or get the specified logger through parameters
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/service/configService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,11 @@ export class MidwayConfigService implements IConfigService {
this.isReady = true;
}

public getConfiguration(configKey?: string) {
public getConfiguration<T = any>(configKey?: string): T {
if (configKey) {
return safelyGet(configKey, this.configuration);
return safelyGet(configKey, this.configuration) as T;
}
return this.configuration;
return this.configuration as T;
}

public getConfigMergeOrder(): Array<ConfigMergeInfo> {
Expand Down
28 changes: 28 additions & 0 deletions packages/core/test/context/container.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -992,5 +992,33 @@ describe('/test/context/container.test.ts', () => {
container.get(TestClass);
}).toThrow(MidwayDefinitionNotFoundError);
});

it('should test inject with multi-level extends', () => {

@Provide()
class Katana {}

class GrandParent {
@Inject()
katana1: Katana;
}

class Parent extends GrandParent {
}

@Provide()
class Child extends Parent {
@Inject()
katana2: Katana;
}

const container = new Container();
container.bind(Child);
container.bind(Katana);

const child = container.get(Child);
expect(child.katana1).toBeDefined();
expect(child.katana2).toBeDefined();
});
});
});
41 changes: 36 additions & 5 deletions packages/i18n/src/i18nService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class MidwayI18nServiceSingleton {
private i18nConfig: I18nOptions;

private localeTextMap: Map<string, Map<string, any>> = new Map();
private localeJSONMap: Map<string, any> = new Map();
private defaultLocale: string;
private fallbackMatch: Array<{
pattern: any;
Expand Down Expand Up @@ -47,8 +48,10 @@ export class MidwayI18nServiceSingleton {
* @param localeTextMapping
*/
public addLocale(locale: string, localeTextMapping: Record<string, any>) {
const currentLangMap = getMap(this.localeTextMap, locale, true);
locale = formatLocale(locale);
const currentLangMap = getMap(this.localeTextMap, locale);

// set to text map
for (const key in localeTextMapping) {
if (typeof localeTextMapping[key] === 'string') {
// set to default
Expand All @@ -63,6 +66,9 @@ export class MidwayI18nServiceSingleton {
}
}
}

// set to origin json map
this.localeJSONMap.set(locale, localeTextMapping);
}

/**
Expand Down Expand Up @@ -173,14 +179,40 @@ export class MidwayI18nServiceSingleton {
* @param locale
* @param group
*/
public getLocaleMapping(locale: string, group = 'default') {
public getLocaleMapping(
locale: string,
group = 'default'
): Map<string, any> | undefined {
locale = formatLocale(locale);
const langMap = this.localeTextMap.get(locale);
if (langMap) {
if (langMap && langMap.size > 0) {
return langMap.get(group);
}
}

/**
* get locale list by group
* @since 4.0.0
*/
public getLocaleList(group = 'default') {
const list = [];
for (const key of this.localeTextMap.keys()) {
if (this.localeTextMap.get(key).has(group)) {
list.push(key);
}
}
return list;
}

/**
* get origin locale json
* @since 4.0.0
*/
public getOriginLocaleJSON(locale: string, group = 'default') {
locale = formatLocale(locale);
return this.localeJSONMap.get(locale)?.[group];
}

/**
* get current default language
*/
Expand Down Expand Up @@ -288,8 +320,7 @@ function getES6Object(o) {
return o;
}

function getMap(o: Map<string, any>, key: string, formatKey = false) {
key = formatKey ? formatLocale(key) : key;
function getMap(o: Map<string, any>, key: string) {
if (!o.has(key)) {
o.set(key, new Map());
}
Expand Down
3 changes: 2 additions & 1 deletion packages/i18n/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function formatWithObject(text, values) {
}

export function formatLocale(locale: string) {
// support zh_CN, en_US => zh-CN, en-US
if (!locale) return locale;
// support zh_CN, en_US => zh-cn, en-us
return locale.replace('_', '-').toLowerCase();
}
104 changes: 104 additions & 0 deletions packages/validation-class-validator/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"$IS_INSTANCE decorator expects and object as value, but got falsy value.": "$IS_INSTANCE decorator expects and object as value, but got falsy value.",
"$property is $constraint1": "$property is $constraint1",
"$property is not a valid decimal number.": "$property is not a valid decimal number.",
"$property must be a BIC or SWIFT code": "$property must be a BIC or SWIFT code",
"$property must be a boolean string": "$property must be a boolean string",
"$property must be a boolean value": "$property must be a boolean value",
"$property must be a BTC address": "$property must be a BTC address",
"$property must be a credit card": "$property must be a credit card",
"$property must be a currency": "$property must be a currency",
"$property must be a data uri format": "",
"$property must be a Date instance": "",
"$property must be a Firebase Push Id": "",
"$property must be a hash of type $constraint1": "",
"$property must be a hexadecimal color": "",
"$property must be a hexadecimal number": "",
"$property must be a HSL color": "",
"$property must be a identity card number": "",
"$property must be a ISSN": "",
"$property must be a json string": "",
"$property must be a jwt string": "",
"$property must be a latitude string or number": "",
"$property must be a latitude,longitude string": "",
"$property must be a longitude string or number": "",
"$property must be a lowercase string": "",
"$property must be a MAC Address": "",
"$property must be a mongodb id": "",
"$property must be a negative number": "",
"$property must be a non-empty object": "",
"$property must be a number conforming to the specified constraints": "",
"$property must be a number string": "",
"$property must be a phone number": "",
"$property must be a port": "",
"$property must be a positive number": "",
"$property must be a postal code": "",
"$property must be a Semantic Versioning Specification": "",
"$property must be a string": "",
"$property must be a UUID": "",
"$property must be a valid domain name": "",
"$property must be a valid enum value": "",
"$property must be a valid ISO 8601 date string": "",
"$property must be a valid ISO31661 Alpha2 code": "",
"$property must be a valid ISO31661 Alpha3 code": "",
"$property must be a valid phone number": "",
"$property must be a valid representation of military time in the format HH:MM": "",
"$property must be an array": "",
"$property must be an EAN (European Article Number)": "",
"$property must be an email": "",
"$property must be an Ethereum address": "",
"$property must be an IBAN": "",
"$property must be an instance of $constraint1name": "",
"$property must be an integer number": "",
"$property must be an ip address": "",
"$property must be an ISBN": "",
"$property must be an ISIN (stock/security identifier)": "",
"$property must be an ISRC": "",
"$property must be an object": "",
"$property must be an URL address": "",
"$property must be base32 encoded": "",
"$property must be base64 encoded": "",
"$property must be divisible by $constraint1": "",
"$property must be empty": "",
"$property must be equal to $constraint1": "",
"$property must be locale": "",
"$property must be longer than or equal to $constraint1 and shorter than or equal to $constraint2 characters": "",
"$property must be longer than or equal to $constraint1 characters": "",
"$property must be magnet uri format": "",
"$property must be MIME type format": "",
"$property must be one of the following values: $constraint1": "",
"$property must be RFC 3339 date": "",
"$property must be RGB color": "",
"$property must be shorter than or equal to $constraint1 characters": "",
"$property must be shorter than or equal to $constraint2 characters": "",
"$property must be uppercase": "",
"$property must be valid octal number": "",
"$property must be valid passport number": "",
"$property must contain $constraint1 values": "",
"$property must contain a $constraint1 string": "",
"$property must contain a full-width and half-width characters": "",
"$property must contain a full-width characters": "",
"$property must contain a half-width characters": "",
"$property must contain any surrogate pairs chars": "",
"$property must contain at least $constraint1 elements": "",
"$property must contain not more than $constraint1 elements": "",
"$property must contain one or more multibyte chars": "",
"$property must contain only ASCII characters": "",
"$property must contain only letters (a-zA-Z)": "",
"$property must contain only letters and numbers": "",
"$property must match $constraint1 regular expression": "",
"$property must not be greater than $constraint1": "",
"$property must not be less than $constraint1": "",
"$property should not be empty": "",
"$property should not be equal to $constraint1": "",
"$property should not be null or undefined": "",
"$property should not be one of the following values: $constraint1": "",
"$property should not contain $constraint1 values": "",
"$property should not contain a $constraint1 string": "",
"$property's byte length must fall into ($constraint1, $constraint2) range": "",
"All $property's elements must be unique": "",
"each value in ": "",
"maximal allowed date for ": "",
"minimal allowed date for ": "",
"nested property $property must be either object or array": ""
}
104 changes: 104 additions & 0 deletions packages/validation-class-validator/i18n/zh.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"$IS_INSTANCE decorator expects and object as value, but got falsy value.": "$IS_INSTANCE 装饰者期望值和对象作为值,但却获得虚假值。",
"$property is $constraint1": "$property 是 $constraint1",
"$property is not a valid decimal number.": "$property 不是一个有效的十进制数字。",
"$property must be a BIC or SWIFT code": "$property 必须是 BIC 或 SWIFT 代码",
"$property must be a boolean string": "$property 必须是一个布尔值",
"$property must be a boolean value": "$property 必须是一个布尔值",
"$property must be a BTC address": "$property 必须是 BTC 地址",
"$property must be a credit card": "$property 必须是一张信用卡",
"$property must be a currency": "$property 必须是货币",
"$property must be a data uri format": "$property 必须是一个数据 uri 格式",
"$property must be a Date instance": "$property 必须是日期实例",
"$property must be a Firebase Push Id": "$property 必须是 Firebase推送ID",
"$property must be a hash of type $constraint1": "$property 必须是类型 $constraint1 的哈希值",
"$property must be a hexadecimal color": "$property 必须是十六进制颜色",
"$property must be a hexadecimal number": "$property 必须是十六进制数字",
"$property must be a HSL color": "$property 必须是一个 HSL 颜色",
"$property must be a identity card number": "$property 必须是身份卡号",
"$property must be a ISSN": "$property 必须是一个 ISSN",
"$property must be a json string": "$property 必须是 json 字符串",
"$property must be a jwt string": "$property 必须是 jwt 字符串",
"$property must be a latitude string or number": "$property 必须是纬度字符串或数字",
"$property must be a latitude,longitude string": "$property 必须是纬度字符串,经度字符串",
"$property must be a longitude string or number": "$property 必须是经度字符串或数字",
"$property must be a lowercase string": "$property 必须是小写字符串",
"$property must be a MAC Address": "$property 必须是 MAC 地址",
"$property must be a mongodb id": "$property 必须是 Mongodb id",
"$property must be a negative number": "$property 必须是负数",
"$property must be a non-empty object": "$property 必须是非空对象",
"$property must be a number conforming to the specified constraints": "$property 必须是符合指定约束的数字",
"$property must be a number string": "$property 必须是一个数字字符串",
"$property must be a phone number": "$property 必须是电话号码",
"$property must be a port": "$property 必须是一个端口",
"$property must be a positive number": "$property 必须是一个正数",
"$property must be a postal code": "$property 必须是一个邮政编码",
"$property must be a Semantic Versioning Specification": "$property 必须是语义版本规格。",
"$property must be a string": "$property 必须是字符串",
"$property must be a UUID": "$property 必须是 UUID",
"$property must be a valid domain name": "$property 必须是一个有效的域名",
"$property must be a valid enum value": "$property 必须是一个有效的枚举值",
"$property must be a valid ISO 8601 date string": "$property 必须是一个有效的 ISO 8601 日期字符串",
"$property must be a valid ISO31661 Alpha2 code": "$property 必须是有效的 ISO31661 Alpha2 代码",
"$property must be a valid ISO31661 Alpha3 code": "$property 必须是有效的 ISO31661 Alpha3 代码",
"$property must be a valid phone number": "$property 必须是一个有效的电话号码",
"$property must be a valid representation of military time in the format HH:MM": "$property 必须是以HH:MM 格式有效的军事时间",
"$property must be an array": "$property 必须是一个数组",
"$property must be an EAN (European Article Number)": "$property 必须是 ECO(欧洲文章编号)",
"$property must be an email": "$property 必须是电子邮件",
"$property must be an Ethereum address": "$property 必须是 Ethereum 地址",
"$property must be an IBAN": "$property 必须是 IBAN",
"$property must be an instance of $constraint1name": "$property 必须是 $constraint1name 的实例",
"$property must be an integer number": "$property 必须是整数",
"$property must be an ip address": "$property 必须是一个IP地址",
"$property must be an ISBN": "$property 必须是一个 ISBN",
"$property must be an ISIN (stock/security identifier)": "$property 必须是 ISIN (库存/安全标识符)",
"$property must be an ISRC": "$property 必须是一个 ISRC",
"$property must be an object": "$property 必须是对象",
"$property must be an URL address": "$property 必须是一个URL地址",
"$property must be base32 encoded": "$property 必须以 base32 编码",
"$property must be base64 encoded": "$property 必须以 base64 编码",
"$property must be divisible by $constraint1": "$property 必须被 $constraint1 拆分",
"$property must be empty": "$property 必须为空",
"$property must be equal to $constraint1": "$property 必须等于 $constraint1",
"$property must be locale": "$property 必须是区域设置",
"$property must be longer than or equal to $constraint1 and shorter than or equal to $constraint2 characters": "$property 必须长于或等于 $constraint1 并且短于或等于 $constraint2 个字符",
"$property must be longer than or equal to $constraint1 characters": "$property 必须长于或等于 $constraint1 个字符",
"$property must be magnet uri format": "$property 必须是 magnet uri 格式",
"$property must be MIME type format": "$property 必须是 MIME 类型格式",
"$property must be one of the following values: $constraint1": "$property 必须是以下值之一: $constraint1",
"$property must be RFC 3339 date": "$property 必须是 RFC 3339 日期",
"$property must be RGB color": "$property 必须是 RGB 颜色",
"$property must be shorter than or equal to $constraint1 characters": "$property 必须小于或等于 $constraint1 个字符",
"$property must be shorter than or equal to $constraint2 characters": "$property 必须小于或等于 $constraint2 个字符",
"$property must be uppercase": "$property 必须是大写",
"$property must be valid octal number": "$property 必须是有效的八进制数字",
"$property must be valid passport number": "$property 必须是有效的护照号码",
"$property must contain $constraint1 values": "$property 必须包含 $constraint1 个值",
"$property must contain a $constraint1 string": "$property 必须包含 $constraint1 字符串",
"$property must contain a full-width and half-width characters": "$property 必须包含全宽和半宽字符",
"$property must contain a full-width characters": "$property 必须包含全宽字符",
"$property must contain a half-width characters": "$property 必须包含半宽字符",
"$property must contain any surrogate pairs chars": "$property 必须包含任何代理对字符",
"$property must contain at least $constraint1 elements": "$property 必须包含至少 $constraint1 元素",
"$property must contain not more than $constraint1 elements": "$property 必须包含不超过 $constraint1 元素",
"$property must contain one or more multibyte chars": "$property 必须包含一个或多个多字节",
"$property must contain only ASCII characters": "$property 只能包含 ASCII 字符",
"$property must contain only letters (a-zA-Z)": "$property 只能包含字母 (a-zA-Z)",
"$property must contain only letters and numbers": "$property 只能包含字母和数字",
"$property must match $constraint1 regular expression": "$property 必须匹配 $constraint1 正则表达式",
"$property must not be greater than $constraint1": "$property 不能大于 $constraint1",
"$property must not be less than $constraint1": "$property 不能小于 $constraint1",
"$property should not be empty": "$property 不应该为空",
"$property should not be equal to $constraint1": "$property 不能等于 $constraint1",
"$property should not be null or undefined": "$property 不应为空或未定义",
"$property should not be one of the following values: $constraint1": "$property 不应该是以下值之一: $constraint1",
"$property should not contain $constraint1 values": "$property 不应该包含 $constraint1 个值",
"$property should not contain a $constraint1 string": "$property 不应该包含 $constraint1 字符串",
"$property's byte length must fall into ($constraint1, $constraint2) range": "$property的字节长度必须到 ($constraint1, $constraint2) 范围",
"All $property's elements must be unique": "所有 $property的元素必须是唯一的",
"each value in ": "每个值在 ",
"maximal allowed date for ": "最大允许日期 ",
"minimal allowed date for ": "最小允许日期 ",
"nested property $property must be either object or array": "嵌套属性 $property 必须是对象或数组"
}
7 changes: 7 additions & 0 deletions packages/validation-class-validator/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ValidatorOptions } from 'class-validator';

declare module '@midwayjs/core/dist/interface' {
interface MidwayConfig {
classValidator?: ValidatorOptions;
}
}
7 changes: 7 additions & 0 deletions packages/validation-class-validator/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testPathIgnorePatterns: ['dist'],
coveragePathIgnorePatterns: ['dist'],
setupFilesAfterEnv: ['./jest.setup.js'],
};
1 change: 1 addition & 0 deletions packages/validation-class-validator/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jest.setTimeout(30000);
Loading
Loading