Skip to content

Commit

Permalink
feat: dto helper support extend method
Browse files Browse the repository at this point in the history
  • Loading branch information
fuguohong committed Aug 28, 2021
1 parent d38d2f6 commit 5f32bd5
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 20 deletions.
21 changes: 10 additions & 11 deletions packages/decorator/src/common/decoratorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,18 +456,17 @@ export function getClassExtendedMetadata(
}
const extKey = DecoratorManager.getDecoratorClsExtendedKey(decoratorNameKey);
let metadata = manager.getMetadata(extKey, target);
if (metadata === undefined) {
const metaChain = [manager.getMetadata(decoratorNameKey, target)];
let father = Reflect.getPrototypeOf(target);
while (father.constructor !== Object) {
metaChain.push(manager.getMetadata(decoratorNameKey, father));
father = Reflect.getPrototypeOf(father);
}
for (let i = metaChain.length - 1; i >= 0; i--) {
metadata = mergeMeta(metadata, metaChain[i]);
}
manager.saveMetadata(extKey, metadata || null, target);
if (metadata !== undefined) {
return metadata;
}
const father = Reflect.getPrototypeOf(target);
if (father.constructor !== Object) {
metadata = mergeMeta(
getClassExtendedMetadata(decoratorNameKey, father),
manager.getMetadata(decoratorNameKey, target)
);
}
manager.saveMetadata(extKey, metadata || null, target);
return metadata;
}

Expand Down
10 changes: 7 additions & 3 deletions packages/decorator/src/util/dtoHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ export function PickDto<T, K extends keyof T>(
dto: Dto<T>,
keys: K[]
): Dto<Pick<T, typeof keys[number]>> {
const pickedDto = class {};
const pickedDto: any = function () {};
pickedDto.prototype = dto.prototype;
const fatherRule = getClassExtendedMetadata(RULES_KEY, dto);
const pickedRule: any = {};
for (const key of keys) {
pickedRule[key] = fatherRule[key];
if (fatherRule[key]) {
pickedRule[key] = fatherRule[key];
}
}
saveClassMetadata(RULES_KEY, pickedRule, pickedDto);
return pickedDto as Dto<Pick<T, typeof keys[number]>>;
Expand All @@ -26,7 +29,8 @@ export function OmitDto<T, K extends keyof T>(
dto: Dto<T>,
keys: K[]
): Dto<Omit<T, typeof keys[number]>> {
const pickedDto = class {};
const pickedDto: any = function () {};
pickedDto.prototype = dto.prototype;
const fatherRule = getClassExtendedMetadata(RULES_KEY, dto);
const pickedRule: any = Object.assign({}, fatherRule);
for (const key of keys) {
Expand Down
45 changes: 39 additions & 6 deletions packages/decorator/test/util/dtoHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ import {
OmitDto,
} from '../../src';

class TestDto {
class BaseDto {
hello(): string {
return 'hello midway';
}

@Rule(RuleType.number().integer())
baseAttr: number;
}

class TestDto extends BaseDto {
@Rule(RuleType.date())
createTime: Date;

Expand All @@ -19,6 +28,11 @@ class TestDto {

@Rule(RuleType.number().integer())
quantity: number;

addPrice(p: number): number {
this.price += p;
return this.price;
}
}

describe('/test/util/dtoHelper.test.ts', () => {
Expand All @@ -27,18 +41,20 @@ describe('/test/util/dtoHelper.test.ts', () => {
@Rule(RuleType.number().integer())
id: number;

@Rule(RuleType.number().integer().max(5))
@Rule(RuleType.string())
quantity: number;

@Rule(RuleType.string())
comment: string;
}
const rules = getClassExtendedMetadata(RULES_KEY, ChildDto);
const ruleKeys = Object.keys(rules);
expect(ruleKeys.length).toBe(6);
expect(ruleKeys.length).toBe(7);
expect(ruleKeys.includes('id')).toBeTruthy();
expect(ruleKeys.includes('price')).toBeTruthy();
expect(ruleKeys.includes('quantity')).toBeTruthy();
expect(ruleKeys.includes('baseAttr')).toBeTruthy();
expect(rules.quantity.type).toEqual('string');
});

it('should test PickDto', async () => {
Expand All @@ -51,11 +67,28 @@ describe('/test/util/dtoHelper.test.ts', () => {
});

it('should test OmitDto', async () => {
class PickedDto extends OmitDto(TestDto, ['productName']) {}
const rules = getClassExtendedMetadata(RULES_KEY, PickedDto);
class OmittedDto extends OmitDto(TestDto, ['productName']) {}
const rules = getClassExtendedMetadata(RULES_KEY, OmittedDto);
const ruleKeys = Object.keys(rules);
expect(ruleKeys.length).toBe(3);
expect(ruleKeys.length).toBe(4);
expect(ruleKeys.includes('productName')).toBeFalsy();
expect(ruleKeys.includes('quantity')).toBeTruthy();
});

it('should test method extend', async () => {
class PickedDto extends PickDto(TestDto, ['price', 'addPrice', 'hello']) {}
class OmittedDto extends OmitDto(TestDto, ['productName']) {}
const pInst = new PickedDto();
pInst.price = 10;
expect(pInst.hello()).toEqual('hello midway');
expect(pInst.addPrice(20)).toEqual(30);

const oInst = new OmittedDto();
oInst.price = 100;
expect(oInst.hello()).toEqual('hello midway');
expect(oInst.addPrice(-20)).toEqual(80);

expect(pInst instanceof BaseDto).toBeTruthy();
expect(oInst instanceof BaseDto).toBeTruthy();
});
});

0 comments on commit 5f32bd5

Please sign in to comment.