Skip to content

Commit 82d2ef3

Browse files
jbl428imdudu1
andcommitted
feat: add bearer decorator
Co-authored-by: imdudu1 <[email protected]>
1 parent 7fb80bb commit 82d2ef3

13 files changed

+156
-30
lines changed

lib/builders/request-header.builder.spec.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import { RequestHeaderBuilder } from './request-header.builder';
44
describe('RequestHeaderBuilder', () => {
55
test('should build header with explicit key', () => {
66
// given
7-
const builder = new RequestHeaderBuilder(0, 'keyword');
7+
const builder = new RequestHeaderBuilder({
8+
parameterIndex: 0,
9+
key: 'keyword',
10+
});
811
const args = ['search'];
912

1013
// when
@@ -16,7 +19,11 @@ describe('RequestHeaderBuilder', () => {
1619

1720
test('should build header with explicit key and default', () => {
1821
// given
19-
const builder = new RequestHeaderBuilder(0, 'keyword', 'search');
22+
const builder = new RequestHeaderBuilder({
23+
parameterIndex: 0,
24+
key: 'keyword',
25+
defaultValue: 'search',
26+
});
2027
const args = [null];
2128

2229
// when
@@ -28,7 +35,9 @@ describe('RequestHeaderBuilder', () => {
2835

2936
test('should build header without key', () => {
3037
// given
31-
const builder = new RequestHeaderBuilder(1);
38+
const builder = new RequestHeaderBuilder({
39+
parameterIndex: 1,
40+
});
3241
const args = ['invalid', { foo: 'bar' }];
3342

3443
// when
@@ -37,4 +46,20 @@ describe('RequestHeaderBuilder', () => {
3746
// then
3847
expect(actual).toEqual({ foo: 'bar' });
3948
});
49+
50+
test('should apply transform function to args', () => {
51+
// given
52+
const builder = new RequestHeaderBuilder({
53+
parameterIndex: 0,
54+
key: 'keyword',
55+
transform: (value) => value.toUpperCase(),
56+
});
57+
const args = ['search'];
58+
59+
// when
60+
const actual = builder.build(args);
61+
62+
// then
63+
expect(actual).toEqual({ keyword: 'SEARCH' });
64+
});
4065
});

lib/builders/request-header.builder.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
11
import { TupleArrayBuilder } from './tuple-array.builder';
2+
import { type ParamDecoratorOption } from '../types/param-decorator-option.interface';
23

34
export class RequestHeaderBuilder {
4-
metadata: Array<
5-
[
6-
index: number,
7-
value: [key: string | undefined, defaultValue: string | undefined],
8-
]
9-
> = [];
5+
metadata: Array<ParamDecoratorOption<string, string>> = [];
106

11-
constructor(index: number, key?: string, defaultValue?: string) {
12-
this.add(index, key, defaultValue);
7+
constructor(option: ParamDecoratorOption<string, string>) {
8+
this.add(option);
139
}
1410

15-
add(index: number, key?: string, defaultValue?: string): void {
16-
this.metadata.push([index, [key, defaultValue]]);
11+
add(option: ParamDecoratorOption<string, string>): void {
12+
this.metadata.push(option);
1713
}
1814

1915
build(args: any[]): HeadersInit {
2016
return this.metadata.reduce<Record<string, string>>(
21-
(acc, [index, [key, defaultValue]]) => {
17+
(acc, { parameterIndex, key, defaultValue, transform }) => {
2218
if (key != null) {
23-
acc[key] = String(args[index] ?? defaultValue ?? '');
19+
const value = String(args[parameterIndex] ?? defaultValue ?? '');
20+
acc[key] = transform != null ? transform(value) : value;
2421
return acc;
2522
}
2623

27-
TupleArrayBuilder.of<string, unknown>(args[index]).forEach(
24+
TupleArrayBuilder.of<string, unknown>(args[parameterIndex]).forEach(
2825
([key, value]) => {
2926
acc[key] = String(value);
3027
},

lib/decorators/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export * from './request-header.decorator';
66
export * from './request-param.decorator';
77
export * from './request-form.decorator';
88
export * from './constants';
9+
export * from './utils';

lib/decorators/request-body.decorator.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { REQUEST_BODY_METADATA } from './constants';
22
import { RequestBodyBuilder } from '../builders/request-body.builder';
33

4+
export function RequestBody(key?: string): ParameterDecorator;
5+
export function RequestBody(
6+
key: string,
7+
defaultValue?: unknown,
8+
): ParameterDecorator;
49
export function RequestBody(
510
key?: string,
611
defaultValue?: unknown,

lib/decorators/request-form.decorator.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { REQUEST_FORM_METADATA } from './constants';
22
import { RequestFormBuilder } from '../builders/request-form.builder';
33

4+
export function RequestForm(key?: string): ParameterDecorator;
5+
export function RequestForm(
6+
key: string,
7+
defaultValue?: string,
8+
): ParameterDecorator;
49
export function RequestForm(
510
key?: string,
611
defaultValue?: string,

lib/decorators/request-header.decorator.spec.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,14 @@ describe('RequestHeader', () => {
4040
);
4141

4242
// then
43-
expect(result.metadata).toEqual([[0, [undefined, undefined]]]);
43+
expect(result.metadata).toMatchInlineSnapshot(`
44+
[
45+
{
46+
"key": undefined,
47+
"parameterIndex": 0,
48+
},
49+
]
50+
`);
4451
});
4552

4653
test('should set request header metadata with key', () => {
@@ -59,14 +66,21 @@ describe('RequestHeader', () => {
5966
);
6067

6168
// then
62-
expect(result.metadata).toEqual([[0, ['foo', undefined]]]);
69+
expect(result.metadata).toMatchInlineSnapshot(`
70+
[
71+
{
72+
"key": "foo",
73+
"parameterIndex": 0,
74+
},
75+
]
76+
`);
6377
});
6478

6579
test('should set request header metadata with multiple decorator', () => {
6680
// given
6781
class TestService {
6882
request(
69-
@RequestHeader('foo', 'default') foo: string,
83+
@RequestHeader('foo', { defaultValue: 'default' }) foo: string,
7084
@RequestHeader() bar: { bar: string },
7185
): string {
7286
return foo;
@@ -81,9 +95,18 @@ describe('RequestHeader', () => {
8195
);
8296

8397
// then
84-
expect(result.metadata).toEqual([
85-
[1, [undefined, undefined]],
86-
[0, ['foo', 'default']],
87-
]);
98+
expect(result.metadata).toMatchInlineSnapshot(`
99+
[
100+
{
101+
"key": undefined,
102+
"parameterIndex": 1,
103+
},
104+
{
105+
"defaultValue": "default",
106+
"key": "foo",
107+
"parameterIndex": 0,
108+
},
109+
]
110+
`);
88111
});
89112
});

lib/decorators/request-header.decorator.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { REQUEST_HEADER_METADATA } from './constants';
22
import { RequestHeaderBuilder } from '../builders/request-header.builder';
33

4+
export function RequestHeader(key?: string): ParameterDecorator;
5+
export function RequestHeader(
6+
key: string,
7+
option?: { defaultValue?: string; transform?: (value: string) => string },
8+
): ParameterDecorator;
49
export function RequestHeader(
510
key?: string,
6-
defaultValue?: string,
11+
option?: { defaultValue?: string; transform?: (value: string) => string },
712
): ParameterDecorator {
813
return (target, propertyKey, parameterIndex) => {
914
if (propertyKey == null) {
@@ -17,13 +22,13 @@ export function RequestHeader(
1722
);
1823

1924
if (builder != null) {
20-
builder.add(parameterIndex, key, defaultValue);
25+
builder.add({ parameterIndex, key, ...option });
2126
return;
2227
}
2328

2429
Reflect.defineMetadata(
2530
REQUEST_HEADER_METADATA,
26-
new RequestHeaderBuilder(parameterIndex, key, defaultValue),
31+
new RequestHeaderBuilder({ parameterIndex, key, ...option }),
2732
target,
2833
propertyKey,
2934
);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, expect, test } from 'vitest';
2+
import { Bearer } from './bearer.decorator';
3+
import { type RequestHeaderBuilder } from '../../builders/request-header.builder';
4+
import { REQUEST_HEADER_METADATA } from '../constants';
5+
6+
describe('Bearer', () => {
7+
test('should set request header metadata with key', () => {
8+
// given
9+
class TestService {
10+
request(@Bearer() token: string): string {
11+
return token;
12+
}
13+
}
14+
15+
// when
16+
const result: RequestHeaderBuilder = Reflect.getMetadata(
17+
REQUEST_HEADER_METADATA,
18+
TestService.prototype,
19+
'request',
20+
);
21+
22+
// then
23+
expect(result.metadata).toHaveLength(1);
24+
expect(result.metadata[0].key).toBe('Authorization');
25+
expect(result.metadata[0].transform?.('token')).toBe('Bearer token');
26+
});
27+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { RequestHeader } from '../request-header.decorator';
2+
3+
export function Bearer(): ParameterDecorator {
4+
return RequestHeader('Authorization', {
5+
transform: (value) => `Bearer ${value}`,
6+
});
7+
}

lib/decorators/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './bearer.decorator';

0 commit comments

Comments
 (0)