Skip to content

Commit 959039f

Browse files
committed
feat(): composition with mixins
1 parent 6680820 commit 959039f

File tree

6 files changed

+67
-2
lines changed

6 files changed

+67
-2
lines changed

src/coffees/coffees.controller.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { CoffeesService } from './coffees.service'
1313
import { CreateCoffeeDto } from './dto/create-coffee.dto'
1414
import { UpdateCoffeeDto } from './dto/update-coffee.dto'
1515
import { CircuitBreakerInterceptor } from '../common/interceptors/circuit-breaker/circuit-breaker.interceptor'
16+
import { EntityExistPipe } from 'src/common/pipes/entity-exists.pipe'
17+
import { Coffee } from './entities/coffee.entity'
1618

1719
@UseInterceptors(CircuitBreakerInterceptor)
1820
@Controller('coffees')
@@ -36,7 +38,11 @@ export class CoffeesController {
3638
}
3739

3840
@Patch(':id')
39-
update(@Param('id') id: string, @Body() updateCoffeeDto: UpdateCoffeeDto) {
41+
update(
42+
// @Param('id', EntityExistPipe(Coffee)) id: string,
43+
@Param('id') id: string,
44+
@Body() updateCoffeeDto: UpdateCoffeeDto,
45+
) {
4046
return this.coffeesService.update(+id, updateCoffeeDto)
4147
}
4248

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1-
export class Coffee {}
1+
import { WithUuid } from '../../common/mixins/with-uuid.mixin'
2+
3+
export class Coffee {
4+
constructor(public name: string) {}
5+
}
6+
7+
const CoffeeWithUuidCls = WithUuid(Coffee)
8+
const coffee = new CoffeeWithUuidCls('Flat White')
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { WithUuidMixin } from './with-uuid.mixin';
2+
3+
describe('WithUuidMixin', () => {
4+
it('should be defined', () => {
5+
expect(new WithUuidMixin()).toBeDefined();
6+
});
7+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Type } from '@nestjs/common'
2+
import { randomUUID } from 'crypto'
3+
4+
export function WithUuid<TBase extends Type>(Base: TBase) {
5+
return class extends Base {
6+
uuid = randomUUID()
7+
8+
regenerateUuid() {
9+
this.uuid = randomUUID()
10+
}
11+
}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { EntityExistsPipe } from './entity-exists.pipe';
2+
3+
describe('EntityExistsPipe', () => {
4+
it('should be defined', () => {
5+
expect(new EntityExistsPipe()).toBeDefined();
6+
});
7+
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {
2+
ArgumentMetadata,
3+
Inject,
4+
Injectable,
5+
PipeTransform,
6+
Type,
7+
} from '@nestjs/common'
8+
9+
export function EntityExistPipe(entityCls: Type): Type<PipeTransform> {
10+
@Injectable()
11+
class EntityExistsPipeCls implements PipeTransform {
12+
constructor(
13+
@Inject(entityCls)
14+
private entityRepository: { exists(condition: unknown): Promise<void> },
15+
// inline random type, but generally in normal application, this would likely
16+
// represent a repository provided by an ORM
17+
) {}
18+
19+
async transform(value: any, metadata: ArgumentMetadata) {
20+
await this.entityRepository.exists({ where: { id: value } }) // throws if entity does not exist
21+
return value
22+
}
23+
}
24+
25+
return EntityExistsPipeCls
26+
}

0 commit comments

Comments
 (0)