1- import { Body , Controller , Get , Inject , Param , Post , Query , Req , Res , Session , UseGuards } from '@nestjs/common' ;
1+ import { Body , Controller , Get , Inject , Param , Post , Query , Req , Res , UseGuards , OnModuleInit , OnModuleDestroy } from '@nestjs/common' ;
2+ import { filter , Subject , take } from 'rxjs' ;
3+ import { v4 as uuidv4 } from 'uuid' ;
4+ import { Response } from 'express' ;
25import {
36 CREDENTIAL_CREATOR_FACADE ,
47 ICredentialCreatorFacade
58} from '../../core/applications/credentials/facade/icredential.facade' ;
6- import { Response } from 'express' ;
79import { AUTH_CONTROLLER_MAPPER , IcredentialsControllerMapper } from './mapper/icredentials.controller.mapper' ;
8- import { v4 as uuidv4 } from 'uuid' ;
9- import { filter , Subject , take } from 'rxjs' ;
1010import { SubjectData } from './isubject.data' ;
1111import { JwtGuard } from '../../guards/jwt.guard' ;
1212import { CredentialsGenerateEmailOtpApiRequestQuery } from "./requests/credentials.generate-email-otp.request.api" ;
@@ -21,9 +21,10 @@ import { ChainId } from '../../core/domain/entities/environment';
2121type Siwens = { address : string , ens : string , chainId : ChainId } ;
2222
2323@Controller ( 'credentials' )
24- export class CredentialsController {
24+ export class CredentialsController implements OnModuleInit , OnModuleDestroy {
2525
2626 private authSubjects : Map < string , Subject < SubjectData > > = new Map ( ) ;
27+ private heartbeatInterval : NodeJS . Timer ;
2728
2829 constructor (
2930 @Inject ( CREDENTIAL_CREATOR_FACADE )
@@ -33,6 +34,32 @@ export class CredentialsController {
3334 private readonly authControllerMapper : IcredentialsControllerMapper
3435 ) { }
3536
37+ onModuleInit ( ) {
38+ this . heartbeatInterval = setInterval ( ( ) => {
39+ this . sendHeartbeats ( ) ;
40+ } , 10000 ) ;
41+ }
42+
43+ onModuleDestroy ( ) {
44+ if ( this . heartbeatInterval ) {
45+ clearInterval ( this . heartbeatInterval ) ;
46+ }
47+ }
48+
49+ private sendHeartbeats ( ) {
50+ this . authSubjects . forEach ( ( subject , authId ) => {
51+ try {
52+ subject . next ( {
53+ authId,
54+ heartbeat : true ,
55+ } ) ;
56+ } catch ( error ) {
57+ this . authSubjects . delete ( authId ) ;
58+ throw Error ( `Failed to send heartbeat to ${ authId } : ${ error } ` ) ;
59+ }
60+ } ) ;
61+ }
62+
3663 @UseGuards ( JwtGuard )
3764 @Get ( 'socials/:authName' )
3865 async getAuthUrl (
@@ -51,7 +78,6 @@ export class CredentialsController {
5178 authId
5279 )
5380
54-
5581 res . writeHead ( 200 , {
5682 'Content-Type' : 'text/event-stream' ,
5783 'Cache-Control' : 'no-cache' ,
@@ -61,11 +87,11 @@ export class CredentialsController {
6187 res . write ( `data: ${ JSON . stringify ( { redirectUrl } ) } \n\n` ) ;
6288
6389 subject . pipe (
64- filter ( data => data . authId === authId ) ,
90+ filter ( data => data . authId === authId && ! data . heartbeat ) ,
6591 take ( 1 )
6692 ) . subscribe (
6793 ( data ) => {
68- res . write ( `data: ${ JSON . stringify ( { result :data . result } ) } \n\n` ) ;
94+ res . write ( `data: ${ JSON . stringify ( { result : data . result } ) } \n\n` ) ;
6995 res . end ( ) ;
7096 this . authSubjects . delete ( authId ) ;
7197 } ,
@@ -74,7 +100,7 @@ export class CredentialsController {
74100 res . end ( ) ;
75101 this . authSubjects . delete ( authId ) ;
76102 }
77- ) ;
103+ )
78104 }
79105
80106 @Get ( 'socials/:authName/callback' )
@@ -95,6 +121,7 @@ export class CredentialsController {
95121 const subject = this . authSubjects . get ( authId ) ;
96122 subject ?. next ( {
97123 authId,
124+ heartbeat : false ,
98125 result : {
99126 verifiableCredential,
100127 dataKey
0 commit comments