mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
chore: a few improvements
This commit is contained in:
@@ -130,7 +130,7 @@ export class Reflector {
|
||||
public getAll<TParam = any, TTransformed = TParam>(
|
||||
decorator: ReflectableDecorator<TParam, TTransformed>,
|
||||
targets: (Type<any> | Function)[],
|
||||
): TTransformed extends any[] ? TTransformed : TTransformed[];
|
||||
): TTransformed extends Array<any> ? TTransformed : TTransformed[];
|
||||
/**
|
||||
* Retrieve metadata for a specified key for a specified set of targets.
|
||||
*
|
||||
@@ -168,7 +168,11 @@ export class Reflector {
|
||||
public getAllAndMerge<TParam = any, TTransformed = TParam>(
|
||||
decorator: ReflectableDecorator<TParam, TTransformed>,
|
||||
targets: (Type<any> | Function)[],
|
||||
): TTransformed;
|
||||
): TTransformed extends Array<any>
|
||||
? TTransformed
|
||||
: TTransformed extends object
|
||||
? TTransformed
|
||||
: TTransformed[];
|
||||
/**
|
||||
* Retrieve metadata for a specified key for a specified set of targets and merge results.
|
||||
*
|
||||
@@ -199,6 +203,13 @@ export class Reflector {
|
||||
if (isEmpty(metadataCollection)) {
|
||||
return metadataCollection as TResult;
|
||||
}
|
||||
if (metadataCollection.length === 1) {
|
||||
const value = metadataCollection[0];
|
||||
if (isObject(value)) {
|
||||
return value as TResult;
|
||||
}
|
||||
return metadataCollection as TResult;
|
||||
}
|
||||
return metadataCollection.reduce((a, b) => {
|
||||
if (Array.isArray(a)) {
|
||||
return a.concat(b);
|
||||
|
||||
@@ -5,48 +5,63 @@ const transformDecorator = Reflector.createDecorator<string[], number>({
|
||||
transform: value => value.length,
|
||||
});
|
||||
|
||||
describe('Reflector', () => {
|
||||
let reflector: Reflector;
|
||||
type TestObject = {
|
||||
only1?: string;
|
||||
only2?: string;
|
||||
both: string;
|
||||
};
|
||||
|
||||
class Test {}
|
||||
describe('Reflector', () => {
|
||||
const key = 'key';
|
||||
let reflector: Reflector;
|
||||
|
||||
@transformDecorator(['a', 'b', 'c'])
|
||||
class TestTransform {}
|
||||
class Test {}
|
||||
class Test1 {}
|
||||
class Test2 {}
|
||||
|
||||
beforeEach(() => {
|
||||
Reflect.deleteMetadata(key, Test1);
|
||||
Reflect.deleteMetadata(key, Test2);
|
||||
reflector = new Reflector();
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('should reflect metadata by key', () => {
|
||||
const key = 'key';
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(key, value, Test);
|
||||
expect(reflector.get(key, Test)).to.eql(value);
|
||||
Reflect.defineMetadata(key, value, Test1);
|
||||
expect(reflector.get(key, Test1)).to.eql(value);
|
||||
});
|
||||
|
||||
it('should reflect metadata by decorator', () => {
|
||||
const decorator = Reflector.createDecorator<string>();
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(decorator.KEY, value, Test);
|
||||
Reflect.defineMetadata(decorator.KEY, value, Test1);
|
||||
|
||||
let reflectedValue = reflector.get(decorator, Test);
|
||||
// string
|
||||
let reflectedValue = reflector.get(decorator, Test1);
|
||||
expect(reflectedValue).to.eql(value);
|
||||
|
||||
// @ts-expect-error 'value' is not assignable to parameter of type 'string'
|
||||
reflectedValue = true;
|
||||
|
||||
reflectedValue satisfies string;
|
||||
});
|
||||
|
||||
it('should reflect metadata by decorator (custom key)', () => {
|
||||
const decorator = Reflector.createDecorator<string[]>({ key: 'custom' });
|
||||
const value = ['value'];
|
||||
Reflect.defineMetadata('custom', value, Test);
|
||||
Reflect.defineMetadata('custom', value, Test1);
|
||||
|
||||
let reflectedValue = reflector.get(decorator, Test);
|
||||
// string[]
|
||||
let reflectedValue = reflector.get(decorator, Test1);
|
||||
expect(reflectedValue).to.eql(value);
|
||||
|
||||
// @ts-expect-error 'value' is not assignable to parameter of type 'string[]'
|
||||
reflectedValue = true;
|
||||
|
||||
reflectedValue satisfies string[];
|
||||
});
|
||||
|
||||
it('should reflect metadata by decorator (with transform option)', () => {
|
||||
@@ -55,6 +70,8 @@ describe('Reflector', () => {
|
||||
|
||||
// @ts-expect-error 'value' is not assignable to type 'number'
|
||||
reflectedValue = [];
|
||||
|
||||
reflectedValue satisfies number;
|
||||
});
|
||||
|
||||
it('should require transform option when second generic type is provided', () => {
|
||||
@@ -64,53 +81,121 @@ describe('Reflector', () => {
|
||||
});
|
||||
|
||||
describe('getAll', () => {
|
||||
it('should reflect metadata of all targets', () => {
|
||||
const key = 'key';
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(key, value, Test);
|
||||
expect(reflector.getAll(key, [Test])).to.eql([value]);
|
||||
it('should reflect metadata of all targets by key', () => {
|
||||
const value1 = 'value1';
|
||||
const value2 = 'value2';
|
||||
Reflect.defineMetadata(key, value1, Test1);
|
||||
Reflect.defineMetadata(key, value2, Test2);
|
||||
expect(reflector.getAll(key, [Test1, Test2])).to.eql([value1, value2]);
|
||||
});
|
||||
it('should reflect metadata of all targets by decorator', () => {
|
||||
const decorator = Reflector.createDecorator<string>();
|
||||
const value1 = 'value1';
|
||||
const value2 = 'value2';
|
||||
Reflect.defineMetadata(decorator.KEY, value1, Test1);
|
||||
Reflect.defineMetadata(decorator.KEY, value2, Test2);
|
||||
|
||||
// string[]
|
||||
const reflectedValue = reflector.getAll(decorator, [Test1, Test2]);
|
||||
expect(reflectedValue).to.eql([value1, value2]);
|
||||
|
||||
reflectedValue satisfies string[];
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllAndMerge', () => {
|
||||
it('should return an empty array when there are no targets', () => {
|
||||
const key = 'key';
|
||||
expect(reflector.getAllAndMerge(key, [])).to.be.empty;
|
||||
});
|
||||
it('should reflect metadata of all targets and concat arrays', () => {
|
||||
const key = 'key';
|
||||
const decorator = Reflector.createDecorator<string[]>();
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(key, [value], Test);
|
||||
expect(reflector.getAllAndMerge(key, [Test, Test])).to.eql([
|
||||
value,
|
||||
value,
|
||||
Reflect.defineMetadata(decorator.KEY, [value], Test1);
|
||||
|
||||
// string[]
|
||||
const reflectedValue = reflector.getAllAndMerge(decorator, [
|
||||
Test1,
|
||||
Test1,
|
||||
]);
|
||||
expect(reflectedValue).to.eql([value, value]);
|
||||
|
||||
reflectedValue satisfies string[];
|
||||
});
|
||||
it('should reflect metadata of all targets and concat boolean arrays', () => {
|
||||
const decorator = Reflector.createDecorator<boolean>();
|
||||
const value = true;
|
||||
Reflect.defineMetadata(decorator.KEY, [value], Test1);
|
||||
|
||||
// string[]
|
||||
const reflectedValue = reflector.getAllAndMerge(decorator, [
|
||||
Test1,
|
||||
Test1,
|
||||
]);
|
||||
expect(reflectedValue).to.eql([value, value]);
|
||||
|
||||
reflectedValue satisfies boolean[];
|
||||
});
|
||||
it('should reflect metadata of all targets and create an array', () => {
|
||||
const key = 'key';
|
||||
const decorator = Reflector.createDecorator<string>();
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(key, value, Test);
|
||||
expect(reflector.getAllAndMerge(key, [Test, Test])).to.eql([
|
||||
value,
|
||||
value,
|
||||
Reflect.defineMetadata(decorator.KEY, value, Test1);
|
||||
|
||||
// string[]
|
||||
const reflectedValue = reflector.getAllAndMerge(decorator, [
|
||||
Test1,
|
||||
Test1,
|
||||
]);
|
||||
expect(reflectedValue).to.eql([value, value]);
|
||||
|
||||
reflectedValue satisfies string[];
|
||||
});
|
||||
it('should reflect metadata of all targets and merge an object', () => {
|
||||
const key = 'key';
|
||||
const value = { test: 'test' };
|
||||
Reflect.defineMetadata(key, value, Test);
|
||||
expect(reflector.getAllAndMerge(key, [Test, Test])).to.eql({
|
||||
...value,
|
||||
it('should reflect metadata of all targets and merge objects', () => {
|
||||
const decorator = Reflector.createDecorator<TestObject>();
|
||||
const value1: TestObject = { only1: 'test1', both: 'overriden' };
|
||||
const value2: TestObject = { only2: 'test2', both: 'test' };
|
||||
Reflect.defineMetadata(decorator.KEY, value1, Test1);
|
||||
Reflect.defineMetadata(decorator.KEY, value2, Test2);
|
||||
|
||||
// TestObject
|
||||
const reflectedValue = reflector.getAllAndMerge(decorator, [
|
||||
Test1,
|
||||
Test2,
|
||||
]);
|
||||
expect(reflectedValue).to.eql({
|
||||
...value1,
|
||||
...value2,
|
||||
});
|
||||
|
||||
reflectedValue satisfies TestObject;
|
||||
});
|
||||
it('should reflect metadata of all targets and create an array from a single value', () => {
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(key, value, Test1);
|
||||
|
||||
const result = reflector.getAllAndMerge(key, [Test1, Test2]);
|
||||
expect(result).to.eql([value]);
|
||||
|
||||
result satisfies string[];
|
||||
});
|
||||
it('should reflect metadata of all targets and return a single array unmodified', () => {
|
||||
const value = ['value'];
|
||||
Reflect.defineMetadata(key, value, Test1);
|
||||
expect(reflector.getAllAndMerge(key, [Test1, Test2])).to.eql(value);
|
||||
});
|
||||
it('should reflect metadata of all targets and return a single object unmodified', () => {
|
||||
const value = { test: 'value' };
|
||||
Reflect.defineMetadata(key, value, Test1);
|
||||
expect(reflector.getAllAndMerge(key, [Test1, Test2])).to.eql(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllAndOverride', () => {
|
||||
it('should reflect metadata of all targets and return a first not undefined value', () => {
|
||||
const key = 'key';
|
||||
const value = 'value';
|
||||
Reflect.defineMetadata(key, value, Test);
|
||||
expect(reflector.getAllAndOverride(key, [Test, Test])).to.eql(value);
|
||||
const value1 = 'value1';
|
||||
const value2 = 'value2';
|
||||
Reflect.defineMetadata(key, value1, Test1);
|
||||
Reflect.defineMetadata(key, value2, Test2);
|
||||
expect(reflector.getAllAndOverride(key, [Test1, Test2])).to.eql(value1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user