Skip to content

Commit 64d0d6c

Browse files
committed
feat(api): added push API module to save PushSubscriptions
1 parent 2e0769a commit 64d0d6c

21 files changed

+217
-29
lines changed

PLAYBOOK-NEST.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ nest g module notifications --dry-run
101101
nest g controller notifications --dry-run
102102
nest g service notifications notifications --dry-run
103103
nest g class notification notifications --dry-run
104+
105+
# scaffold push module
106+
nest g module push --dry-run
107+
nest g controller push --dry-run
108+
nest g service push --dry-run
109+
nest g class subscription push --no-spec --dry-run # rename as subscription.entity.ts
104110
```
105111

106112

apps/api/src/app.module.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { UserModule } from './user';
77
// import { ChatModule } from './chat';
88
import { AppController } from './app.controller';
99
import { NotificationsModule } from './notifications';
10+
import { PushModule } from './push';
1011

1112
@Module({
1213
imports: [
@@ -16,6 +17,7 @@ import { NotificationsModule } from './notifications';
1617
children: [
1718
{ path: '/auth', module: AuthModule },
1819
{ path: '/user', module: UserModule },
20+
{ path: '/push', module: PushModule },
1921
// { path: '/account', module: AccountModule },
2022
{ path: '/notifications', module: NotificationsModule },
2123
],
@@ -26,6 +28,7 @@ import { NotificationsModule } from './notifications';
2628
UserModule,
2729
// AccountModule,
2830
NotificationsModule,
31+
PushModule,
2932
// ChatModule,
3033
],
3134
controllers: [AppController],

apps/api/src/core/core.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ConnectionOptions } from 'typeorm';
1010
import { Notification } from '../notifications/notification.entity';
1111
import { User } from '../auth/user.entity';
1212
import { environment as env } from '@env-api/environment';
13+
import { Subscription } from '../push/subscription.entity';
1314

1415
@Module({
1516
imports: [
@@ -19,7 +20,7 @@ import { environment as env } from '@env-api/environment';
1920
imports: [ConfigModule],
2021
useFactory: async (config: ConfigService) => ({
2122
...env.database,
22-
entities: [Notification, User],
23+
entities: [Notification, User, Subscription],
2324
} as ConnectionOptions),
2425
inject: [ConfigService],
2526
}),

apps/api/src/core/crud/crud.controller.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export abstract class CrudController<T extends Base> {
3131
description: 'Invalid input, The response body may contain clues as to what went wrong',
3232
})
3333
@Post()
34-
async create(@Body() entity: DeepPartial<T>): Promise<T> {
34+
async create(@Body() entity: DeepPartial<T>, options?: any): Promise<T> {
3535
return this.crudService.create(entity);
3636
}
3737

@@ -43,15 +43,15 @@ export abstract class CrudController<T extends Base> {
4343
description: 'Invalid input, The response body may contain clues as to what went wrong',
4444
})
4545
@Put(':id')
46-
async update(@Param('id') id: string, @Body() entity: DeepPartial<T>): Promise<any> {
46+
async update(@Param('id') id: string, @Body() entity: DeepPartial<T>, options?: any): Promise<any> {
4747
return this.crudService.update(id, entity as any); // FIXME: https://github.com/typeorm/typeorm/issues/1544
4848
}
4949

5050
@ApiOperation({ title: 'Delete record' })
5151
@ApiResponse({ status: HttpStatus.NO_CONTENT, description: 'The record has been successfully deleted' })
5252
@ApiResponse({ status: HttpStatus.NOT_FOUND, description: 'Record not found' })
5353
@Delete(':id')
54-
async delete(@Param('id') id: string): Promise<any> {
54+
async delete(@Param('id') id: string, options?: any): Promise<any> {
5555
return this.crudService.delete(id);
5656
}
5757
}

apps/api/src/core/entities/audit-base.entity.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ export abstract class AuditBase {
1212
@PrimaryGeneratedColumn()
1313
id: number;
1414

15+
@ApiModelProperty({ type: Date })
1516
// @Exclude()
1617
@CreateDateColumn()
1718
createdAt?: Date;
1819

20+
@ApiModelProperty({ type: Date })
1921
// @Exclude()
2022
@UpdateDateColumn()
2123
updatedAt?: Date;

apps/api/src/notifications/dto/create-notification.dto.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IsAscii, IsBoolean, IsEnum, IsIn, IsNotEmpty, IsString, MaxLength, MinL
33
import { NotificationColor, NotificationIcon } from '../notification.entity';
44

55
export class CreateNotificationDto {
6-
@ApiModelProperty({ type: String, enum: NotificationIcon, default: 'notifications' })
6+
@ApiModelProperty({ type: String, enum: NotificationIcon, default: NotificationIcon.notifications })
77
@IsString()
88
@IsNotEmpty()
99
@IsEnum(NotificationIcon)
@@ -19,7 +19,7 @@ export class CreateNotificationDto {
1919
@IsNotEmpty()
2020
read: boolean = false;
2121

22-
@ApiModelProperty({ type: String, enum: NotificationColor })
22+
@ApiModelProperty({ type: String, enum: NotificationColor, default: NotificationColor.PRIMARY })
2323
@IsString()
2424
@IsNotEmpty()
2525
@IsIn(['warn', 'accent', 'primary'])

apps/api/src/notifications/notification.entity.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export enum NotificationIcon {
2020

2121
@Entity('notification')
2222
export class Notification extends Base {
23-
@ApiModelProperty({ type: String })
23+
@ApiModelProperty({ type: String, enum: NotificationIcon, default: NotificationIcon.notifications })
2424
@IsString()
2525
@IsNotEmpty()
2626
@Column()
@@ -43,10 +43,10 @@ export class Notification extends Base {
4343
@Column()
4444
read: boolean;
4545

46-
@ApiModelProperty({ type: String })
46+
@ApiModelProperty({ type: String, enum: NotificationColor, default: NotificationColor.PRIMARY })
4747
@IsString()
4848
@IsNotEmpty()
49-
@Column()
49+
@Column({ enum: ['warn', 'accent', 'primary'] })
5050
color?: NotificationColor;
5151

5252
@ApiModelProperty({ type: String, minLength: 8, maxLength: 20 })
@@ -62,6 +62,6 @@ export class Notification extends Base {
6262
@IsBoolean()
6363
@IsNotEmpty()
6464
@Index()
65-
@Column({ default: false})
65+
@Column({ default: false })
6666
native: boolean;
6767
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ApiModelProperty } from '@nestjs/swagger';
2+
import { IsNotEmpty, IsString, IsUrl } from 'class-validator';
3+
4+
export class CreateSubscriptionDto {
5+
@ApiModelProperty({ type: String })
6+
@IsNotEmpty()
7+
@IsUrl({}, { message: 'endpoint must be a valid url.' })
8+
endpoint: string;
9+
10+
@ApiModelProperty({ type: String })
11+
@IsNotEmpty()
12+
@IsString()
13+
auth: string;
14+
15+
@ApiModelProperty({ type: String })
16+
@IsNotEmpty()
17+
@IsString()
18+
p256dh: string;
19+
20+
@ApiModelProperty({ type: String, isArray: true })
21+
@IsNotEmpty()
22+
topics: string[];
23+
}

apps/api/src/push/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './push.module';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { PushController } from './push.controller';
3+
4+
describe('Push Controller', () => {
5+
let module: TestingModule;
6+
7+
beforeAll(async () => {
8+
module = await Test.createTestingModule({
9+
controllers: [PushController],
10+
}).compile();
11+
});
12+
it('should be defined', () => {
13+
const controller: PushController = module.get<PushController>(PushController);
14+
expect(controller).toBeDefined();
15+
});
16+
});

0 commit comments

Comments
 (0)