From b99c6c43e2e181ca99e9a5d0f1c3616f7c179035 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Wed, 13 Sep 2023 20:04:12 +0530 Subject: [PATCH 1/7] feat: add fcm module initial apis Signed-off-by: Sai Ranjit Tummalapalli --- .env.example | 4 + src/constants.ts | 4 + .../fcm/PushNotificationsFcmApi.ts | 68 +++++++++++ .../fcm/PushNotificationsFcmModule.ts | 38 +++++++ src/push-notifications/fcm/constants.ts | 5 + .../PushNotificationsFcmProblemReportError.ts | 30 +++++ ...PushNotificationsFcmProblemReportReason.ts | 11 ++ src/push-notifications/fcm/errors/index.ts | 2 + .../PushNotificationsFcmDeviceInfoHandler.ts | 18 +++ ...ushNotificationsFcmProblemReportHandler.ts | 18 +++ ...ushNotificationsFcmSetDeviceInfoHandler.ts | 24 ++++ src/push-notifications/fcm/handlers/index.ts | 3 + src/push-notifications/fcm/index.ts | 4 + .../PushNotificationsFcmDeviceInfoMessage.ts | 43 +++++++ ...ushNotificationsFcmProblemReportMessage.ts | 23 ++++ ...ushNotificationsFcmSetDeviceInfoMessage.ts | 40 +++++++ src/push-notifications/fcm/messages/index.ts | 3 + .../fcm/models/FcmDeviceInfo.ts | 4 + .../fcm/models/PushNotificationsFcmRole.ts | 10 ++ src/push-notifications/fcm/models/index.ts | 2 + .../repository/PushNotificationsFcmRecord.ts | 51 +++++++++ .../PushNotificationsFcmRepository.ts | 13 +++ .../fcm/repository/index.ts | 2 + .../services/PushNotificationsFcmService.ts | 106 ++++++++++++++++++ src/push-notifications/fcm/services/index.ts | 1 + 25 files changed, 527 insertions(+) create mode 100644 src/push-notifications/fcm/PushNotificationsFcmApi.ts create mode 100644 src/push-notifications/fcm/PushNotificationsFcmModule.ts create mode 100644 src/push-notifications/fcm/constants.ts create mode 100644 src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportError.ts create mode 100644 src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportReason.ts create mode 100644 src/push-notifications/fcm/errors/index.ts create mode 100644 src/push-notifications/fcm/handlers/PushNotificationsFcmDeviceInfoHandler.ts create mode 100644 src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts create mode 100644 src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts create mode 100644 src/push-notifications/fcm/handlers/index.ts create mode 100644 src/push-notifications/fcm/index.ts create mode 100644 src/push-notifications/fcm/messages/PushNotificationsFcmDeviceInfoMessage.ts create mode 100644 src/push-notifications/fcm/messages/PushNotificationsFcmProblemReportMessage.ts create mode 100644 src/push-notifications/fcm/messages/PushNotificationsFcmSetDeviceInfoMessage.ts create mode 100644 src/push-notifications/fcm/messages/index.ts create mode 100644 src/push-notifications/fcm/models/FcmDeviceInfo.ts create mode 100644 src/push-notifications/fcm/models/PushNotificationsFcmRole.ts create mode 100644 src/push-notifications/fcm/models/index.ts create mode 100644 src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts create mode 100644 src/push-notifications/fcm/repository/PushNotificationsFcmRepository.ts create mode 100644 src/push-notifications/fcm/repository/index.ts create mode 100644 src/push-notifications/fcm/services/PushNotificationsFcmService.ts create mode 100644 src/push-notifications/fcm/services/index.ts diff --git a/.env.example b/.env.example index ef25a8d..93c3107 100644 --- a/.env.example +++ b/.env.example @@ -3,3 +3,7 @@ POSTGRES_PASSWORD= POSTGRES_HOST= POSTGRES_ADMIN_USER= POSTGRES_ADMIN_PASSWORD= + +FIREBASE_PROJECT_ID= +FIREBASE_NOTIFICATION_TITLE=You have message from your contacts +FIREBASE_NOTIFICATION_BODY=Please open your app to read the message \ No newline at end of file diff --git a/src/constants.ts b/src/constants.ts index a8d0bd7..c874596 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -15,6 +15,10 @@ export const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD export const POSTGRES_ADMIN_USER = process.env.POSTGRES_ADMIN_USER export const POSTGRES_ADMIN_PASSWORD = process.env.POSTGRES_ADMIN_PASSWORD +export const FIREBASE_PROJECT_ID = process.env.FIREBASE_PROJECT_ID +export const FIREBASE_NOTIFICATION_TITLE = process.env.FIREBASE_NOTIFICATION_TITLE +export const FIREBASE_NOTIFICATION_BODY = process.env.FIREBASE_NOTIFICATION_BODY + export const INVITATION_URL = process.env.INVITATION_URL export const LOG_LEVEL = LogLevel.debug diff --git a/src/push-notifications/fcm/PushNotificationsFcmApi.ts b/src/push-notifications/fcm/PushNotificationsFcmApi.ts new file mode 100644 index 0000000..e2ceed7 --- /dev/null +++ b/src/push-notifications/fcm/PushNotificationsFcmApi.ts @@ -0,0 +1,68 @@ +import type { FcmDeviceInfo } from './models' + +import { + OutboundMessageContext, + AgentContext, + ConnectionService, + injectable, + MessageSender, +} from '@aries-framework/core' + +import { PushNotificationsFcmService } from './services/PushNotificationsFcmService' + +@injectable() +export class PushNotificationsFcmApi { + private messageSender: MessageSender + private pushNotificationsService: PushNotificationsFcmService + private connectionService: ConnectionService + private agentContext: AgentContext + + public constructor( + messageSender: MessageSender, + pushNotificationsService: PushNotificationsFcmService, + connectionService: ConnectionService, + agentContext: AgentContext + ) { + this.messageSender = messageSender + this.pushNotificationsService = pushNotificationsService + this.connectionService = connectionService + this.agentContext = agentContext + } + + /** + * Sends a set request with the fcm device info (token) to another agent via a `connectionId` + * + * @param connectionId The connection ID string + * @param deviceInfo The FCM device info + * @returns Promise + */ + public async setDeviceInfo(connectionId: string, deviceInfo: FcmDeviceInfo) { + const connection = await this.connectionService.getById(this.agentContext, connectionId) + connection.assertReady() + + await this.pushNotificationsService.setDeviceInfo(this.agentContext, connection.id, deviceInfo) + } + + /** + * Sends the requested fcm device info (token) to another agent via a `connectionId` + * Response for `push-notifications-fcm/get-device-info` + * + * @param connectionId The connection ID string + * @param threadId get-device-info message ID + * @param deviceInfo The FCM device info + * @returns Promise + */ + public async deviceInfo(options: { connectionId: string; threadId: string; deviceInfo: FcmDeviceInfo }) { + const { connectionId, threadId, deviceInfo } = options + const connection = await this.connectionService.getById(this.agentContext, connectionId) + connection.assertReady() + + const message = this.pushNotificationsService.createDeviceInfo({ threadId, deviceInfo }) + + const outbound = new OutboundMessageContext(message, { + agentContext: this.agentContext, + connection: connection, + }) + await this.messageSender.sendMessage(outbound) + } +} diff --git a/src/push-notifications/fcm/PushNotificationsFcmModule.ts b/src/push-notifications/fcm/PushNotificationsFcmModule.ts new file mode 100644 index 0000000..f48a2d4 --- /dev/null +++ b/src/push-notifications/fcm/PushNotificationsFcmModule.ts @@ -0,0 +1,38 @@ +import type { DependencyManager, FeatureRegistry, Module } from '@aries-framework/core' + +import { Protocol } from '@aries-framework/core' + +import { PushNotificationsFcmApi } from './PushNotificationsFcmApi' +import { PushNotificationsFcmService } from './services/PushNotificationsFcmService' +import { + PushNotificationsFcmDeviceInfoHandler, + PushNotificationsFcmProblemReportHandler, + PushNotificationsFcmSetDeviceInfoHandler, +} from './handlers' +import { PushNotificationsFcmRole } from './models' + +/** + * Module that exposes push notification get and set functionality + */ +export class PushNotificationsFcmModule implements Module { + public readonly api = PushNotificationsFcmApi + + public register(dependencyManager: DependencyManager, featureRegistry: FeatureRegistry): void { + dependencyManager.registerContextScoped(PushNotificationsFcmApi) + + dependencyManager.registerSingleton(PushNotificationsFcmService) + + featureRegistry.register( + new Protocol({ + id: 'https://didcomm.org/push-notifications-fcm/1.0', + roles: [PushNotificationsFcmRole.Sender, PushNotificationsFcmRole.Receiver], + }) + ) + + dependencyManager.registerMessageHandlers([ + new PushNotificationsFcmDeviceInfoHandler(), + new PushNotificationsFcmSetDeviceInfoHandler(), + new PushNotificationsFcmProblemReportHandler(), + ]) + } +} diff --git a/src/push-notifications/fcm/constants.ts b/src/push-notifications/fcm/constants.ts new file mode 100644 index 0000000..8c21622 --- /dev/null +++ b/src/push-notifications/fcm/constants.ts @@ -0,0 +1,5 @@ +// FIREBASE +export const SCOPES = ['https://www.googleapis.com/auth/firebase.messaging'] +export const BASE_URL = 'https://fcm.googleapis.com' +export const ENDPOINT_PREFIX = 'v1/projects/' +export const ENDPOINT_SUFFIX = '/messages:send' diff --git a/src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportError.ts b/src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportError.ts new file mode 100644 index 0000000..c1e973a --- /dev/null +++ b/src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportError.ts @@ -0,0 +1,30 @@ +import type { PushNotificationsFcmProblemReportReason } from './PushNotificationsFcmProblemReportReason' +import type { ProblemReportErrorOptions } from '@aries-framework/core' + +import { ProblemReportError } from '@aries-framework/core' + +import { PushNotificationsFcmProblemReportMessage } from '../messages' + +/** + * @internal + */ +interface PushNotificationsFcmProblemReportErrorOptions extends ProblemReportErrorOptions { + problemCode: PushNotificationsFcmProblemReportReason +} + +/** + * @internal + */ +export class PushNotificationsFcmProblemReportError extends ProblemReportError { + public problemReport: PushNotificationsFcmProblemReportMessage + + public constructor(public message: string, { problemCode }: PushNotificationsFcmProblemReportErrorOptions) { + super(message, { problemCode }) + this.problemReport = new PushNotificationsFcmProblemReportMessage({ + description: { + en: message, + code: problemCode, + }, + }) + } +} diff --git a/src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportReason.ts b/src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportReason.ts new file mode 100644 index 0000000..fd6f344 --- /dev/null +++ b/src/push-notifications/fcm/errors/PushNotificationsFcmProblemReportReason.ts @@ -0,0 +1,11 @@ +/** + * Push Notification FCM errors discussed in RFC 0734. + * + * @see https://github.com/hyperledger/aries-rfcs/tree/main/features/0734-push-notifications-fcm#set-device-info + * @see https://github.com/hyperledger/aries-rfcs/tree/main/features/0734-push-notifications-fcm#device-info + * @internal + */ +export enum PushNotificationsFcmProblemReportReason { + MissingValue = 'missing-value', + NotRegistered = 'not-registered-for-push-notifications', +} diff --git a/src/push-notifications/fcm/errors/index.ts b/src/push-notifications/fcm/errors/index.ts new file mode 100644 index 0000000..a1155d8 --- /dev/null +++ b/src/push-notifications/fcm/errors/index.ts @@ -0,0 +1,2 @@ +export * from './PushNotificationsFcmProblemReportReason' +export * from './PushNotificationsFcmProblemReportError' diff --git a/src/push-notifications/fcm/handlers/PushNotificationsFcmDeviceInfoHandler.ts b/src/push-notifications/fcm/handlers/PushNotificationsFcmDeviceInfoHandler.ts new file mode 100644 index 0000000..a44c466 --- /dev/null +++ b/src/push-notifications/fcm/handlers/PushNotificationsFcmDeviceInfoHandler.ts @@ -0,0 +1,18 @@ +import type { MessageHandler, MessageHandlerInboundMessage } from '@aries-framework/core' + +import { PushNotificationsFcmDeviceInfoMessage } from '../messages' + +/** + * Handler for incoming fcm push notification device info messages + */ +export class PushNotificationsFcmDeviceInfoHandler implements MessageHandler { + public supportedMessages = [PushNotificationsFcmDeviceInfoMessage] + + /** + /* We don't really need to do anything with this at the moment + /* The result can be hooked into through the generic message processed event + */ + public async handle(inboundMessage: MessageHandlerInboundMessage) { + inboundMessage.assertReadyConnection() + } +} diff --git a/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts b/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts new file mode 100644 index 0000000..c14c622 --- /dev/null +++ b/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts @@ -0,0 +1,18 @@ +import type { MessageHandler, MessageHandlerInboundMessage } from '@aries-framework/core' + +import { PushNotificationsFcmProblemReportMessage } from '../messages' + +/** + * Handler for incoming push notification problem report messages + */ +export class PushNotificationsFcmProblemReportHandler implements MessageHandler { + public supportedMessages = [PushNotificationsFcmProblemReportMessage] + + /** + /* We don't really need to do anything with this at the moment + /* The result can be hooked into through the generic message processed event + */ + public async handle(inboundMessage: MessageHandlerInboundMessage) { + inboundMessage.assertReadyConnection() + } +} diff --git a/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts b/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts new file mode 100644 index 0000000..d9350d8 --- /dev/null +++ b/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts @@ -0,0 +1,24 @@ +import type { MessageHandler, MessageHandlerInboundMessage } from '@aries-framework/core' + +import { PushNotificationsFcmService } from '../services/PushNotificationsFcmService' +import { PushNotificationsFcmSetDeviceInfoMessage } from '../messages' + +/** + * Handler for incoming push notification device info messages + */ +export class PushNotificationsFcmSetDeviceInfoHandler implements MessageHandler { + public supportedMessages = [PushNotificationsFcmSetDeviceInfoMessage] + + /** + /* Only perform checks about message fields + /* + /* The result can be hooked into through the generic message processed event + */ + public async handle(inboundMessage: MessageHandlerInboundMessage) { + inboundMessage.assertReadyConnection() + + const pushNotificationsFcmService = + inboundMessage.agentContext.dependencyManager.resolve(PushNotificationsFcmService) + pushNotificationsFcmService.processSetDeviceInfo(inboundMessage) + } +} diff --git a/src/push-notifications/fcm/handlers/index.ts b/src/push-notifications/fcm/handlers/index.ts new file mode 100644 index 0000000..0b99b3c --- /dev/null +++ b/src/push-notifications/fcm/handlers/index.ts @@ -0,0 +1,3 @@ +export { PushNotificationsFcmDeviceInfoHandler } from './PushNotificationsFcmDeviceInfoHandler' +export { PushNotificationsFcmSetDeviceInfoHandler } from './PushNotificationsFcmSetDeviceInfoHandler' +export { PushNotificationsFcmProblemReportHandler } from './PushNotificationsFcmProblemReportHandler' diff --git a/src/push-notifications/fcm/index.ts b/src/push-notifications/fcm/index.ts new file mode 100644 index 0000000..bda65d2 --- /dev/null +++ b/src/push-notifications/fcm/index.ts @@ -0,0 +1,4 @@ +export { PushNotificationsFcmApi } from './PushNotificationsFcmApi' +export { PushNotificationsFcmModule } from './PushNotificationsFcmModule' +export * from './models' +export * from './messages' diff --git a/src/push-notifications/fcm/messages/PushNotificationsFcmDeviceInfoMessage.ts b/src/push-notifications/fcm/messages/PushNotificationsFcmDeviceInfoMessage.ts new file mode 100644 index 0000000..6b33346 --- /dev/null +++ b/src/push-notifications/fcm/messages/PushNotificationsFcmDeviceInfoMessage.ts @@ -0,0 +1,43 @@ +import type { FcmDeviceInfo } from '../models' + +import { AgentMessage, IsValidMessageType, parseMessageType } from '@aries-framework/core' +import { Expose } from 'class-transformer' +import { IsString, ValidateIf } from 'class-validator' + +interface PushNotificationsFcmDeviceInfoOptions extends FcmDeviceInfo { + id?: string + threadId: string +} + +/** + * Message to send the fcm device information from another agent for push notifications + * This is used as a response for the `get-device-info` message + * + * @see https://github.com/hyperledger/aries-rfcs/tree/main/features/0734-push-notifications-fcm#device-info + */ +export class PushNotificationsFcmDeviceInfoMessage extends AgentMessage { + public constructor(options: PushNotificationsFcmDeviceInfoOptions) { + super() + + if (options) { + this.id = options.id ?? this.generateId() + this.setThread({ threadId: options.threadId }) + this.deviceToken = options.deviceToken + this.devicePlatform = options.devicePlatform + } + } + + @Expose({ name: 'device_token' }) + @IsString() + @ValidateIf((object, value) => value !== null) + public deviceToken!: string | null + + @Expose({ name: 'device_platform' }) + @IsString() + @ValidateIf((object, value) => value !== null) + public devicePlatform!: string | null + + @IsValidMessageType(PushNotificationsFcmDeviceInfoMessage.type) + public readonly type = PushNotificationsFcmDeviceInfoMessage.type.messageTypeUri + public static readonly type = parseMessageType('https://didcomm.org/push-notifications-fcm/1.0/device-info') +} diff --git a/src/push-notifications/fcm/messages/PushNotificationsFcmProblemReportMessage.ts b/src/push-notifications/fcm/messages/PushNotificationsFcmProblemReportMessage.ts new file mode 100644 index 0000000..df86cb8 --- /dev/null +++ b/src/push-notifications/fcm/messages/PushNotificationsFcmProblemReportMessage.ts @@ -0,0 +1,23 @@ +import type { ProblemReportMessageOptions } from '@aries-framework/core' + +import { IsValidMessageType, parseMessageType, ProblemReportMessage } from '@aries-framework/core' + +export type PushNotificationsFcmProblemReportMessageOptions = ProblemReportMessageOptions + +/** + * @see https://github.com/hyperledger/aries-rfcs/blob/main/features/0035-report-problem/README.md + * @internal + */ +export class PushNotificationsFcmProblemReportMessage extends ProblemReportMessage { + /** + * Create new ConnectionProblemReportMessage instance. + * @param options + */ + public constructor(options: PushNotificationsFcmProblemReportMessageOptions) { + super(options) + } + + @IsValidMessageType(PushNotificationsFcmProblemReportMessage.type) + public readonly type = PushNotificationsFcmProblemReportMessage.type.messageTypeUri + public static readonly type = parseMessageType('https://didcomm.org/push-notifications-fcm/1.0/problem-report') +} diff --git a/src/push-notifications/fcm/messages/PushNotificationsFcmSetDeviceInfoMessage.ts b/src/push-notifications/fcm/messages/PushNotificationsFcmSetDeviceInfoMessage.ts new file mode 100644 index 0000000..8115b21 --- /dev/null +++ b/src/push-notifications/fcm/messages/PushNotificationsFcmSetDeviceInfoMessage.ts @@ -0,0 +1,40 @@ +import type { FcmDeviceInfo } from '../models' + +import { AgentMessage, IsValidMessageType, parseMessageType } from '@aries-framework/core' +import { Expose } from 'class-transformer' +import { IsString, ValidateIf } from 'class-validator' + +interface PushNotificationsFcmSetDeviceInfoOptions extends FcmDeviceInfo { + id?: string +} + +/** + * Message to set the fcm device information at another agent for push notifications + * + * @see https://github.com/hyperledger/aries-rfcs/tree/main/features/0734-push-notifications-fcm#set-device-info + */ +export class PushNotificationsFcmSetDeviceInfoMessage extends AgentMessage { + public constructor(options: PushNotificationsFcmSetDeviceInfoOptions) { + super() + + if (options) { + this.id = options.id ?? this.generateId() + this.deviceToken = options.deviceToken + this.devicePlatform = options.devicePlatform + } + } + + @Expose({ name: 'device_token' }) + @IsString() + @ValidateIf((object, value) => value !== null) + public deviceToken!: string | null + + @Expose({ name: 'device_platform' }) + @IsString() + @ValidateIf((object, value) => value !== null) + public devicePlatform!: string | null + + @IsValidMessageType(PushNotificationsFcmSetDeviceInfoMessage.type) + public readonly type = PushNotificationsFcmSetDeviceInfoMessage.type.messageTypeUri + public static readonly type = parseMessageType('https://didcomm.org/push-notifications-fcm/1.0/set-device-info') +} diff --git a/src/push-notifications/fcm/messages/index.ts b/src/push-notifications/fcm/messages/index.ts new file mode 100644 index 0000000..7bbb56c --- /dev/null +++ b/src/push-notifications/fcm/messages/index.ts @@ -0,0 +1,3 @@ +export { PushNotificationsFcmDeviceInfoMessage } from './PushNotificationsFcmDeviceInfoMessage' +export { PushNotificationsFcmSetDeviceInfoMessage } from './PushNotificationsFcmSetDeviceInfoMessage' +export { PushNotificationsFcmProblemReportMessage } from './PushNotificationsFcmProblemReportMessage' diff --git a/src/push-notifications/fcm/models/FcmDeviceInfo.ts b/src/push-notifications/fcm/models/FcmDeviceInfo.ts new file mode 100644 index 0000000..644c230 --- /dev/null +++ b/src/push-notifications/fcm/models/FcmDeviceInfo.ts @@ -0,0 +1,4 @@ +export type FcmDeviceInfo = { + deviceToken: string | null + devicePlatform: string | null +} diff --git a/src/push-notifications/fcm/models/PushNotificationsFcmRole.ts b/src/push-notifications/fcm/models/PushNotificationsFcmRole.ts new file mode 100644 index 0000000..e94cbc7 --- /dev/null +++ b/src/push-notifications/fcm/models/PushNotificationsFcmRole.ts @@ -0,0 +1,10 @@ +/** + * Push Notification FCM roles based on the flow defined in RFC 0734. + * + * @see https://github.com/hyperledger/aries-rfcs/tree/main/features/0734-push-notifications-fcm#roles + * @public + */ +export enum PushNotificationsFcmRole { + Sender = 'notification-sender', + Receiver = 'notification-receiver', +} diff --git a/src/push-notifications/fcm/models/index.ts b/src/push-notifications/fcm/models/index.ts new file mode 100644 index 0000000..a30d50c --- /dev/null +++ b/src/push-notifications/fcm/models/index.ts @@ -0,0 +1,2 @@ +export * from './FcmDeviceInfo' +export * from './PushNotificationsFcmRole' diff --git a/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts b/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts new file mode 100644 index 0000000..45e6bb3 --- /dev/null +++ b/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts @@ -0,0 +1,51 @@ +import type { TagsBase } from '@aries-framework/core' + +import { utils, BaseRecord } from '@aries-framework/core' + +export type DefaultPushNotificationsFcmTags = { + deviceToken: string | null + devicePlatform: string | null + connectionId: string +} + +export type CustomPushNotificationsFcmTags = TagsBase + +export interface PushNotificationsFcmStorageProps { + id?: string + deviceToken: string | null + devicePlatform: string | null + connectionId: string + tags?: CustomPushNotificationsFcmTags +} + +export class PushNotificationsFcmRecord extends BaseRecord< + DefaultPushNotificationsFcmTags, + CustomPushNotificationsFcmTags +> { + public deviceToken!: string | null + public devicePlatform!: string | null + public connectionId!: string + + public static readonly type = 'PushNotificationsFcmRecord' + public readonly type = PushNotificationsFcmRecord.type + + public constructor(props: PushNotificationsFcmStorageProps) { + super() + + if (props) { + this.id = props.id ?? utils.uuid() + this.devicePlatform = props.devicePlatform + this.deviceToken = props.deviceToken + this._tags = props.tags ?? {} + } + } + + public getTags() { + return { + ...this._tags, + deviceToken: this.deviceToken, + devicePlatform: this.devicePlatform, + connectionId: this.connectionId, + } + } +} diff --git a/src/push-notifications/fcm/repository/PushNotificationsFcmRepository.ts b/src/push-notifications/fcm/repository/PushNotificationsFcmRepository.ts new file mode 100644 index 0000000..6c3ce21 --- /dev/null +++ b/src/push-notifications/fcm/repository/PushNotificationsFcmRepository.ts @@ -0,0 +1,13 @@ +import { EventEmitter, inject, injectable, InjectionSymbols, Repository, StorageService } from '@aries-framework/core' + +import { PushNotificationsFcmRecord } from './PushNotificationsFcmRecord' + +@injectable() +export class PushNotificationsFcmRepository extends Repository { + public constructor( + @inject(InjectionSymbols.StorageService) storageService: StorageService, + eventEmitter: EventEmitter + ) { + super(PushNotificationsFcmRecord, storageService, eventEmitter) + } +} diff --git a/src/push-notifications/fcm/repository/index.ts b/src/push-notifications/fcm/repository/index.ts new file mode 100644 index 0000000..d7b176e --- /dev/null +++ b/src/push-notifications/fcm/repository/index.ts @@ -0,0 +1,2 @@ +export * from './PushNotificationsFcmRecord' +export * from './PushNotificationsFcmRepository' diff --git a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts new file mode 100644 index 0000000..9ea13bf --- /dev/null +++ b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts @@ -0,0 +1,106 @@ +import type { FcmDeviceInfo } from '../models/FcmDeviceInfo' +import type { AgentContext, InboundMessageContext } from '@aries-framework/core' + +import { AriesFrameworkError } from '@aries-framework/core' +import { Lifecycle, scoped } from 'tsyringe' + +import { PushNotificationsFcmProblemReportError, PushNotificationsFcmProblemReportReason } from '../errors' +import { PushNotificationsFcmSetDeviceInfoMessage, PushNotificationsFcmDeviceInfoMessage } from '../messages' +import { PushNotificationsFcmRecord, PushNotificationsFcmRepository } from '../repository' +import fetch from 'node-fetch' +import { BASE_URL, ENDPOINT_PREFIX, ENDPOINT_SUFFIX } from '../constants' +import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE, FIREBASE_PROJECT_ID } from 'src/constants' + +@scoped(Lifecycle.ContainerScoped) +export class PushNotificationsFcmService { + private pushNotificationsFcmRepository: PushNotificationsFcmRepository + + public constructor(pushNotificationsFcmRepository: PushNotificationsFcmRepository) { + this.pushNotificationsFcmRepository = pushNotificationsFcmRepository + } + + public async setDeviceInfo(agentContext: AgentContext, connectionId: string, deviceInfo: FcmDeviceInfo) { + if ( + (deviceInfo.deviceToken === null && deviceInfo.devicePlatform !== null) || + (deviceInfo.deviceToken !== null && deviceInfo.devicePlatform === null) + ) + throw new AriesFrameworkError('Both or none of deviceToken and devicePlatform must be null') + + const pushNotificationsFcmSetDeviceInfoRecord = new PushNotificationsFcmRecord({ + connectionId, + deviceToken: deviceInfo.deviceToken, + devicePlatform: deviceInfo.devicePlatform, + }) + + await this.pushNotificationsFcmRepository.save(agentContext, pushNotificationsFcmSetDeviceInfoRecord) + + return pushNotificationsFcmSetDeviceInfoRecord + } + + public createDeviceInfo(options: { threadId: string; deviceInfo: FcmDeviceInfo }) { + const { threadId, deviceInfo } = options + if ( + (deviceInfo.deviceToken === null && deviceInfo.devicePlatform !== null) || + (deviceInfo.deviceToken !== null && deviceInfo.devicePlatform === null) + ) + throw new AriesFrameworkError('Both or none of deviceToken and devicePlatform must be null') + + return new PushNotificationsFcmDeviceInfoMessage({ + threadId, + deviceToken: deviceInfo.deviceToken, + devicePlatform: deviceInfo.devicePlatform, + }) + } + + public processSetDeviceInfo(messageContext: InboundMessageContext) { + const { message } = messageContext + if ( + (message.deviceToken === null && message.devicePlatform !== null) || + (message.deviceToken !== null && message.devicePlatform === null) + ) + throw new PushNotificationsFcmProblemReportError('Both or none of deviceToken and devicePlatform must be null', { + problemCode: PushNotificationsFcmProblemReportReason.MissingValue, + }) + } + + public async sendNotification(agentContext: AgentContext, connectionId: string) { + const record = await this.pushNotificationsFcmRepository.getById(agentContext, connectionId) + + if (!record.deviceToken) { + return + } + + const response = await this.sendFcmNotification(record.deviceToken) + console.log('first response', response) + } + + private async sendFcmNotification(deviceToken: string) { + const headers = { + Authorization: 'Bearer ', + 'Content-Type': 'application/json; UTF-8', + } + + const PROJECT_ID = FIREBASE_PROJECT_ID + const FCM_ENDPOINT = ENDPOINT_PREFIX + PROJECT_ID + ENDPOINT_SUFFIX + const FCM_URL = BASE_URL + '/' + FCM_ENDPOINT + + const body = { + message: { + token: deviceToken, + notification: { + title: FIREBASE_NOTIFICATION_TITLE, + body: FIREBASE_NOTIFICATION_BODY, + }, + }, + } + try { + return fetch(FCM_URL, { + method: 'POST', + body: JSON.stringify(body), + headers, + }) + } catch (error) { + throw error + } + } +} diff --git a/src/push-notifications/fcm/services/index.ts b/src/push-notifications/fcm/services/index.ts new file mode 100644 index 0000000..b746547 --- /dev/null +++ b/src/push-notifications/fcm/services/index.ts @@ -0,0 +1 @@ +export * from './PushNotificationsFcmService' From e8a0a6eaf374dc2ee0f7cb533dd10fff5db3f8cc Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Mon, 18 Sep 2023 19:56:18 +0530 Subject: [PATCH 2/7] refactor: fcm message handlers Signed-off-by: Sai Ranjit Tummalapalli --- src/agent.ts | 2 ++ .../fcm/PushNotificationsFcmApi.ts | 11 +++++++++++ .../fcm/PushNotificationsFcmModule.ts | 12 ++++++------ .../PushNotificationsFcmProblemReportHandler.ts | 6 ++++++ .../PushNotificationsFcmSetDeviceInfoHandler.ts | 11 ++++++----- .../fcm/services/PushNotificationsFcmService.ts | 17 +++++++++++++++-- 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/agent.ts b/src/agent.ts index f601ed2..12ed572 100644 --- a/src/agent.ts +++ b/src/agent.ts @@ -23,6 +23,7 @@ import { AGENT_ENDPOINTS, AGENT_NAME, AGENT_PORT, LOG_LEVEL, POSTGRES_HOST, WALL import { askarPostgresConfig } from './database' import { Logger } from './logger' import { StorageMessageQueueModule } from './storage/StorageMessageQueueModule' +import { PushNotificationsFcmModule } from './push-notifications/fcm' function createModules() { const modules = { @@ -40,6 +41,7 @@ function createModules() { ariesAskar, multiWalletDatabaseScheme: AskarMultiWalletDatabaseScheme.ProfilePerWallet, }), + pushNotificationsFcm: new PushNotificationsFcmModule(), } return modules diff --git a/src/push-notifications/fcm/PushNotificationsFcmApi.ts b/src/push-notifications/fcm/PushNotificationsFcmApi.ts index e2ceed7..e77f61c 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmApi.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmApi.ts @@ -9,6 +9,11 @@ import { } from '@aries-framework/core' import { PushNotificationsFcmService } from './services/PushNotificationsFcmService' +import { + PushNotificationsFcmDeviceInfoHandler, + PushNotificationsFcmProblemReportHandler, + PushNotificationsFcmSetDeviceInfoHandler, +} from './handlers' @injectable() export class PushNotificationsFcmApi { @@ -27,6 +32,12 @@ export class PushNotificationsFcmApi { this.pushNotificationsService = pushNotificationsService this.connectionService = connectionService this.agentContext = agentContext + + this.agentContext.dependencyManager.registerMessageHandlers([ + new PushNotificationsFcmSetDeviceInfoHandler(this.pushNotificationsService), + new PushNotificationsFcmDeviceInfoHandler(), + new PushNotificationsFcmProblemReportHandler(this.pushNotificationsService), + ]) } /** diff --git a/src/push-notifications/fcm/PushNotificationsFcmModule.ts b/src/push-notifications/fcm/PushNotificationsFcmModule.ts index f48a2d4..5793b43 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmModule.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmModule.ts @@ -10,6 +10,7 @@ import { PushNotificationsFcmSetDeviceInfoHandler, } from './handlers' import { PushNotificationsFcmRole } from './models' +import { PushNotificationsFcmRepository } from './repository' /** * Module that exposes push notification get and set functionality @@ -18,21 +19,20 @@ export class PushNotificationsFcmModule implements Module { public readonly api = PushNotificationsFcmApi public register(dependencyManager: DependencyManager, featureRegistry: FeatureRegistry): void { + // Api dependencyManager.registerContextScoped(PushNotificationsFcmApi) + // Services dependencyManager.registerSingleton(PushNotificationsFcmService) + // Repository + dependencyManager.registerSingleton(PushNotificationsFcmRepository) + featureRegistry.register( new Protocol({ id: 'https://didcomm.org/push-notifications-fcm/1.0', roles: [PushNotificationsFcmRole.Sender, PushNotificationsFcmRole.Receiver], }) ) - - dependencyManager.registerMessageHandlers([ - new PushNotificationsFcmDeviceInfoHandler(), - new PushNotificationsFcmSetDeviceInfoHandler(), - new PushNotificationsFcmProblemReportHandler(), - ]) } } diff --git a/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts b/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts index c14c622..368c666 100644 --- a/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts +++ b/src/push-notifications/fcm/handlers/PushNotificationsFcmProblemReportHandler.ts @@ -1,13 +1,19 @@ import type { MessageHandler, MessageHandlerInboundMessage } from '@aries-framework/core' import { PushNotificationsFcmProblemReportMessage } from '../messages' +import { PushNotificationsFcmService } from '../services' /** * Handler for incoming push notification problem report messages */ export class PushNotificationsFcmProblemReportHandler implements MessageHandler { + private pushNotificationsFcmService: PushNotificationsFcmService public supportedMessages = [PushNotificationsFcmProblemReportMessage] + public constructor(pushNotificationsFcmService: PushNotificationsFcmService) { + this.pushNotificationsFcmService = pushNotificationsFcmService + } + /** /* We don't really need to do anything with this at the moment /* The result can be hooked into through the generic message processed event diff --git a/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts b/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts index d9350d8..ba2eb8a 100644 --- a/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts +++ b/src/push-notifications/fcm/handlers/PushNotificationsFcmSetDeviceInfoHandler.ts @@ -7,18 +7,19 @@ import { PushNotificationsFcmSetDeviceInfoMessage } from '../messages' * Handler for incoming push notification device info messages */ export class PushNotificationsFcmSetDeviceInfoHandler implements MessageHandler { + private pushNotificationsFcmService: PushNotificationsFcmService public supportedMessages = [PushNotificationsFcmSetDeviceInfoMessage] + public constructor(pushNotificationsFcmService: PushNotificationsFcmService) { + this.pushNotificationsFcmService = pushNotificationsFcmService + } + /** /* Only perform checks about message fields /* /* The result can be hooked into through the generic message processed event */ public async handle(inboundMessage: MessageHandlerInboundMessage) { - inboundMessage.assertReadyConnection() - - const pushNotificationsFcmService = - inboundMessage.agentContext.dependencyManager.resolve(PushNotificationsFcmService) - pushNotificationsFcmService.processSetDeviceInfo(inboundMessage) + await this.pushNotificationsFcmService.processSetDeviceInfo(inboundMessage) } } diff --git a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts index 9ea13bf..2328a29 100644 --- a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts +++ b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts @@ -52,15 +52,28 @@ export class PushNotificationsFcmService { }) } - public processSetDeviceInfo(messageContext: InboundMessageContext) { + public async processSetDeviceInfo(messageContext: InboundMessageContext) { const { message } = messageContext if ( (message.deviceToken === null && message.devicePlatform !== null) || (message.deviceToken !== null && message.devicePlatform === null) - ) + ) { throw new PushNotificationsFcmProblemReportError('Both or none of deviceToken and devicePlatform must be null', { problemCode: PushNotificationsFcmProblemReportReason.MissingValue, }) + } + + const connection = messageContext.assertReadyConnection() + + const pushNotificationsFcmRecord = new PushNotificationsFcmRecord({ + connectionId: connection.id, + deviceToken: message.deviceToken, + devicePlatform: message.devicePlatform, + }) + + await this.pushNotificationsFcmRepository.save(messageContext.agentContext, pushNotificationsFcmRecord) + + return pushNotificationsFcmRecord } public async sendNotification(agentContext: AgentContext, connectionId: string) { From 9611cfca7ec54ae79b112e21906a7180a8db8062 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Wed, 20 Sep 2023 20:23:03 +0530 Subject: [PATCH 3/7] feat: add firebase config and send notifications using firebase cloud messaging Signed-off-by: Sai Ranjit Tummalapalli --- .env.example | 4 + package.json | 5 +- patches/@aries-framework+core+0.4.1.patch | 93 ++ src/agent.ts | 31 +- src/constants.ts | 15 +- src/events/PushNotificationEvent.ts | 27 + src/events/RoutingEvents.ts | 17 + .../fcm/PushNotificationsFcmApi.ts | 10 + .../fcm/PushNotificationsFcmModule.ts | 5 - .../repository/PushNotificationsFcmRecord.ts | 5 +- .../services/PushNotificationsFcmService.ts | 46 +- yarn.lock | 1138 ++++++++++++++++- 12 files changed, 1317 insertions(+), 79 deletions(-) create mode 100644 patches/@aries-framework+core+0.4.1.patch create mode 100644 src/events/PushNotificationEvent.ts create mode 100644 src/events/RoutingEvents.ts diff --git a/.env.example b/.env.example index 93c3107..6225582 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,10 @@ POSTGRES_HOST= POSTGRES_ADMIN_USER= POSTGRES_ADMIN_PASSWORD= +USE_PUSH_NOTIFICATIONS=true + FIREBASE_PROJECT_ID= +FIREBASE_PRIVATE_KEY= +FIREBASE_CLIENT_EMAIL= FIREBASE_NOTIFICATION_TITLE=You have message from your contacts FIREBASE_NOTIFICATION_BODY=Please open your app to read the message \ No newline at end of file diff --git a/package.json b/package.json index 3e79a8a..2344652 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "prepublishOnly": "yarn run build", "dev": "ts-node dev", "start": "NODE_ENV=production node build/index.js", - "validate": "yarn build && yarn check-format" + "validate": "yarn build && yarn check-format", + "postinstall": "patch-package" }, "dependencies": { "@aries-framework/askar": "^0.4.1", @@ -36,6 +37,7 @@ "@aries-framework/node": "^0.4.1", "@hyperledger/aries-askar-nodejs": "^0.1.0", "express": "^4.18.1", + "firebase-admin": "^11.10.1", "prettier": "^2.8.4", "tslog": "^3.3.3", "tsyringe": "^4.7.0", @@ -49,6 +51,7 @@ "dotenv": "^16.0.1", "jest": "^29.2.2", "ngrok": "^4.3.1", + "patch-package": "^8.0.0", "ts-jest": "^29.0.3", "ts-node": "^10.9.1", "typescript": "^4.8.4" diff --git a/patches/@aries-framework+core+0.4.1.patch b/patches/@aries-framework+core+0.4.1.patch new file mode 100644 index 0000000..bc024fb --- /dev/null +++ b/patches/@aries-framework+core+0.4.1.patch @@ -0,0 +1,93 @@ +diff --git a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts +index 578a26f..3cb7221 100644 +--- a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts ++++ b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts +@@ -2,11 +2,12 @@ import type { KeylistUpdate } from './messages/KeylistUpdateMessage'; + import type { MediationState } from './models/MediationState'; + import type { MediationRecord } from './repository/MediationRecord'; + import type { BaseEvent } from '../../agent/Events'; +-import type { Routing } from '../connections'; ++import type { ConnectionRecord, Routing } from '../connections'; + export declare enum RoutingEventTypes { + MediationStateChanged = "MediationStateChanged", + RecipientKeylistUpdated = "RecipientKeylistUpdated", +- RoutingCreatedEvent = "RoutingCreatedEvent" ++ RoutingCreatedEvent = "RoutingCreatedEvent", ++ ForwardMessageEvent = "ForwardMessageEvent" + } + export interface RoutingCreatedEvent extends BaseEvent { + type: typeof RoutingEventTypes.RoutingCreatedEvent; +@@ -28,3 +29,9 @@ export interface KeylistUpdatedEvent extends BaseEvent { + keylist: KeylistUpdate[]; + }; + } ++export interface ForwardMessageEvent extends BaseEvent { ++ type: typeof RoutingEventTypes.ForwardMessageEvent; ++ payload: { ++ connectionRecord: ConnectionRecord; ++ }; ++} +diff --git a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.js b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.js +index ad9e68b..1aa5cb6 100644 +--- a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.js ++++ b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.js +@@ -6,5 +6,6 @@ var RoutingEventTypes; + RoutingEventTypes["MediationStateChanged"] = "MediationStateChanged"; + RoutingEventTypes["RecipientKeylistUpdated"] = "RecipientKeylistUpdated"; + RoutingEventTypes["RoutingCreatedEvent"] = "RoutingCreatedEvent"; ++ RoutingEventTypes["ForwardMessageEvent"] = "ForwardMessageEvent"; + })(RoutingEventTypes = exports.RoutingEventTypes || (exports.RoutingEventTypes = {})); + //# sourceMappingURL=RoutingEvents.js.map +\ No newline at end of file +diff --git a/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js b/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js +index bb61eee..8e2069b 100644 +--- a/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js ++++ b/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js +@@ -12,6 +12,8 @@ class ForwardHandler { + async handle(messageContext) { + const { encryptedMessage, mediationRecord } = await this.mediatorService.processForwardMessage(messageContext); + const connectionRecord = await this.connectionService.getById(messageContext.agentContext, mediationRecord.connectionId); ++ // Send forward message to the event emitter so that it can be picked up events ++ await this.mediatorService.emitForwardEvent(messageContext.agentContext, connectionRecord); + // The message inside the forward message is packed so we just send the packed + // message to the connection associated with it + await this.messageSender.sendPackage(messageContext.agentContext, { +diff --git a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts +index e02dbab..ec9ba0d 100644 +--- a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts ++++ b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts +@@ -2,6 +2,7 @@ import type { AgentContext } from '../../../agent'; + import type { InboundMessageContext } from '../../../agent/models/InboundMessageContext'; + import type { Query } from '../../../storage/StorageService'; + import type { EncryptedMessage } from '../../../types'; ++import type { ConnectionRecord } from '../../connections'; + import type { ForwardMessage, MediationRequestMessage } from '../messages'; + import { EventEmitter } from '../../../agent/EventEmitter'; + import { Logger } from '../../../logger'; +@@ -23,6 +24,7 @@ export declare class MediatorService { + mediationRecord: MediationRecord; + encryptedMessage: EncryptedMessage; + }>; ++ emitForwardEvent(agentContext: AgentContext, connectionRecord: ConnectionRecord): Promise; + processKeylistUpdateRequest(messageContext: InboundMessageContext): Promise; + createGrantMediationMessage(agentContext: AgentContext, mediationRecord: MediationRecord): Promise<{ + mediationRecord: MediationRecord; +diff --git a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js +index ec8cd1b..2118939 100644 +--- a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js ++++ b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js +@@ -61,6 +61,14 @@ let MediatorService = class MediatorService { + mediationRecord, + }; + } ++ async emitForwardEvent(agentContext, connectionRecord) { ++ this.eventEmitter.emit(agentContext, { ++ type: RoutingEvents_1.RoutingEventTypes.ForwardMessageEvent, ++ payload: { ++ connectionRecord, ++ }, ++ }); ++ } + async processKeylistUpdateRequest(messageContext) { + // Assert Ready connection + const connection = messageContext.assertReadyConnection(); diff --git a/src/agent.ts b/src/agent.ts index 12ed572..34aa260 100644 --- a/src/agent.ts +++ b/src/agent.ts @@ -19,11 +19,26 @@ import type { Socket } from 'net' import express from 'express' import { Server } from 'ws' -import { AGENT_ENDPOINTS, AGENT_NAME, AGENT_PORT, LOG_LEVEL, POSTGRES_HOST, WALLET_KEY, WALLET_NAME } from './constants' +import { + AGENT_ENDPOINTS, + AGENT_NAME, + AGENT_PORT, + FIREBASE_CLIENT_EMAIL, + FIREBASE_PRIVATE_KEY, + FIREBASE_PROJECT_ID, + LOG_LEVEL, + POSTGRES_HOST, + USE_PUSH_NOTIFICATIONS, + WALLET_KEY, + WALLET_NAME, +} from './constants' import { askarPostgresConfig } from './database' import { Logger } from './logger' import { StorageMessageQueueModule } from './storage/StorageMessageQueueModule' import { PushNotificationsFcmModule } from './push-notifications/fcm' +import { routingEvents } from './events/RoutingEvents' +import { initializeApp } from 'firebase-admin/app' +import { credential } from 'firebase-admin' function createModules() { const modules = { @@ -125,6 +140,18 @@ export async function createAgent() { await agent.initialize() + // Register all event handlers and initialize fcm module + if (USE_PUSH_NOTIFICATIONS) { + initializeApp({ + credential: credential.cert({ + projectId: FIREBASE_PROJECT_ID, + clientEmail: FIREBASE_CLIENT_EMAIL, + privateKey: FIREBASE_PRIVATE_KEY, + }), + }) + routingEvents(agent) + } + // When an 'upgrade' to WS is made on our http server, we forward the // request to the WS server httpInboundTransport.server?.on('upgrade', (request, socket, head) => { @@ -136,4 +163,4 @@ export async function createAgent() { return agent } -export type MediatorAgent = ReturnType +export type MediatorAgent = Agent> diff --git a/src/constants.ts b/src/constants.ts index c874596..c6dd518 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -15,12 +15,19 @@ export const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD export const POSTGRES_ADMIN_USER = process.env.POSTGRES_ADMIN_USER export const POSTGRES_ADMIN_PASSWORD = process.env.POSTGRES_ADMIN_PASSWORD -export const FIREBASE_PROJECT_ID = process.env.FIREBASE_PROJECT_ID -export const FIREBASE_NOTIFICATION_TITLE = process.env.FIREBASE_NOTIFICATION_TITLE -export const FIREBASE_NOTIFICATION_BODY = process.env.FIREBASE_NOTIFICATION_BODY - export const INVITATION_URL = process.env.INVITATION_URL export const LOG_LEVEL = LogLevel.debug export const IS_DEV = process.env.NODE_ENV === 'development' + +export const USE_PUSH_NOTIFICATIONS = process.env.USE_PUSH_NOTIFICATIONS === 'true' + +export const FIREBASE_PROJECT_ID = process.env.FIREBASE_PROJECT_ID +export const FIREBASE_PRIVATE_KEY = process.env.FIREBASE_PRIVATE_KEY + ? process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n') + : undefined +export const FIREBASE_CLIENT_EMAIL = process.env.FIREBASE_CLIENT_EMAIL + +export const FIREBASE_NOTIFICATION_TITLE = process.env.FIREBASE_NOTIFICATION_TITLE +export const FIREBASE_NOTIFICATION_BODY = process.env.FIREBASE_NOTIFICATION_BODY diff --git a/src/events/PushNotificationEvent.ts b/src/events/PushNotificationEvent.ts new file mode 100644 index 0000000..7172756 --- /dev/null +++ b/src/events/PushNotificationEvent.ts @@ -0,0 +1,27 @@ +import type { Logger } from '@aries-framework/core' +import * as admin from 'firebase-admin' +import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE } from '../constants' +import { PushNotificationsFcmRecord } from '../push-notifications/fcm/repository' + +export const sendNotificationEvent = async (pushNotificationFcmRecord: PushNotificationsFcmRecord, logger: Logger) => { + try { + if (!pushNotificationFcmRecord?.deviceToken) { + logger.info(`No device token found for connectionId ${pushNotificationFcmRecord.connectionId}`) + return + } + const message = { + notification: { + title: FIREBASE_NOTIFICATION_TITLE, + body: FIREBASE_NOTIFICATION_BODY, + }, + token: pushNotificationFcmRecord.deviceToken, + } + const response = await admin.messaging().send(message) + logger.info(`Notification sent successfully to ${pushNotificationFcmRecord.connectionId}`) + return response + } catch (error) { + logger.error(`Error sending notification`, { + cause: error, + }) + } +} diff --git a/src/events/RoutingEvents.ts b/src/events/RoutingEvents.ts new file mode 100644 index 0000000..302642e --- /dev/null +++ b/src/events/RoutingEvents.ts @@ -0,0 +1,17 @@ +import type { Agent, ForwardMessageEvent } from '@aries-framework/core' + +import { RoutingEventTypes } from '@aries-framework/core' +import { sendNotificationEvent } from './PushNotificationEvent' +import { MediatorAgent } from '../agent' + +export const routingEvents = async (agent: MediatorAgent) => { + agent.events.on(RoutingEventTypes.ForwardMessageEvent, async (event: ForwardMessageEvent) => { + const record = event.payload.connectionRecord + + // Get device info from PushNotificationsFcmRecord + const fcmDeviceInfoRecord = await agent.modules.pushNotificationsFcm.getDeviceInfoByConnectionId(record.id) + + // Send notification to device + await sendNotificationEvent(fcmDeviceInfoRecord, agent.config.logger) + }) +} diff --git a/src/push-notifications/fcm/PushNotificationsFcmApi.ts b/src/push-notifications/fcm/PushNotificationsFcmApi.ts index e77f61c..09ef1a6 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmApi.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmApi.ts @@ -76,4 +76,14 @@ export class PushNotificationsFcmApi { }) await this.messageSender.sendMessage(outbound) } + + /** + * Get push notification record by `connectionId` + * + * @param connectionId The connection ID string + * @returns Promise + */ + public async getDeviceInfoByConnectionId(connectionId: string) { + return this.pushNotificationsService.getDeviceInfo(this.agentContext, connectionId) + } } diff --git a/src/push-notifications/fcm/PushNotificationsFcmModule.ts b/src/push-notifications/fcm/PushNotificationsFcmModule.ts index 5793b43..705edfe 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmModule.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmModule.ts @@ -4,11 +4,6 @@ import { Protocol } from '@aries-framework/core' import { PushNotificationsFcmApi } from './PushNotificationsFcmApi' import { PushNotificationsFcmService } from './services/PushNotificationsFcmService' -import { - PushNotificationsFcmDeviceInfoHandler, - PushNotificationsFcmProblemReportHandler, - PushNotificationsFcmSetDeviceInfoHandler, -} from './handlers' import { PushNotificationsFcmRole } from './models' import { PushNotificationsFcmRepository } from './repository' diff --git a/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts b/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts index 45e6bb3..ef08330 100644 --- a/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts +++ b/src/push-notifications/fcm/repository/PushNotificationsFcmRecord.ts @@ -3,8 +3,6 @@ import type { TagsBase } from '@aries-framework/core' import { utils, BaseRecord } from '@aries-framework/core' export type DefaultPushNotificationsFcmTags = { - deviceToken: string | null - devicePlatform: string | null connectionId: string } @@ -36,6 +34,7 @@ export class PushNotificationsFcmRecord extends BaseRecord< this.id = props.id ?? utils.uuid() this.devicePlatform = props.devicePlatform this.deviceToken = props.deviceToken + this.connectionId = props.connectionId this._tags = props.tags ?? {} } } @@ -43,8 +42,6 @@ export class PushNotificationsFcmRecord extends BaseRecord< public getTags() { return { ...this._tags, - deviceToken: this.deviceToken, - devicePlatform: this.devicePlatform, connectionId: this.connectionId, } } diff --git a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts index 2328a29..1116a17 100644 --- a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts +++ b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts @@ -7,9 +7,6 @@ import { Lifecycle, scoped } from 'tsyringe' import { PushNotificationsFcmProblemReportError, PushNotificationsFcmProblemReportReason } from '../errors' import { PushNotificationsFcmSetDeviceInfoMessage, PushNotificationsFcmDeviceInfoMessage } from '../messages' import { PushNotificationsFcmRecord, PushNotificationsFcmRepository } from '../repository' -import fetch from 'node-fetch' -import { BASE_URL, ENDPOINT_PREFIX, ENDPOINT_SUFFIX } from '../constants' -import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE, FIREBASE_PROJECT_ID } from 'src/constants' @scoped(Lifecycle.ContainerScoped) export class PushNotificationsFcmService { @@ -76,44 +73,15 @@ export class PushNotificationsFcmService { return pushNotificationsFcmRecord } - public async sendNotification(agentContext: AgentContext, connectionId: string) { - const record = await this.pushNotificationsFcmRepository.getById(agentContext, connectionId) - - if (!record.deviceToken) { - return - } - - const response = await this.sendFcmNotification(record.deviceToken) - console.log('first response', response) - } + public async getDeviceInfo(agentContext: AgentContext, connectionId: string) { + const pushNotificationsFcmRecord = await this.pushNotificationsFcmRepository.getSingleByQuery(agentContext, { + connectionId, + }) - private async sendFcmNotification(deviceToken: string) { - const headers = { - Authorization: 'Bearer ', - 'Content-Type': 'application/json; UTF-8', + if (!pushNotificationsFcmRecord) { + console.error(`No device info found for connection ${connectionId}`) } - const PROJECT_ID = FIREBASE_PROJECT_ID - const FCM_ENDPOINT = ENDPOINT_PREFIX + PROJECT_ID + ENDPOINT_SUFFIX - const FCM_URL = BASE_URL + '/' + FCM_ENDPOINT - - const body = { - message: { - token: deviceToken, - notification: { - title: FIREBASE_NOTIFICATION_TITLE, - body: FIREBASE_NOTIFICATION_BODY, - }, - }, - } - try { - return fetch(FCM_URL, { - method: 'POST', - body: JSON.stringify(body), - headers, - }) - } catch (error) { - throw error - } + return pushNotificationsFcmRecord } } diff --git a/yarn.lock b/yarn.lock index 159fd84..8029b95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -218,6 +218,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.11.tgz#becf8ee33aad2a35ed5607f521fe6e72a615f905" integrity sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g== +"@babel/parser@^7.20.15": + version "7.22.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95" + integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA== + "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -423,6 +428,147 @@ "@digitalcredentials/jsonld-signatures" "^9.3.1" credentials-context "^2.0.0" +"@fastify/busboy@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-1.2.1.tgz#9c6db24a55f8b803b5222753b24fe3aea2ba9ca3" + integrity sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q== + dependencies: + text-decoding "^1.0.0" + +"@firebase/app-types@0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e" + integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q== + +"@firebase/auth-interop-types@0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.1.tgz#78884f24fa539e34a06c03612c75f222fcc33742" + integrity sha512-VOaGzKp65MY6P5FI84TfYKBXEPi6LmOCSMMzys6o2BN2LOsqy7pCuZCup7NYnfbk5OkkQKzvIfHOzTm0UDpkyg== + +"@firebase/component@0.6.4": + version "0.6.4" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.4.tgz#8981a6818bd730a7554aa5e0516ffc9b1ae3f33d" + integrity sha512-rLMyrXuO9jcAUCaQXCMjCMUsWrba5fzHlNK24xz5j2W6A/SRmK8mZJ/hn7V0fViLbxC0lPMtrK1eYzk6Fg03jA== + dependencies: + "@firebase/util" "1.9.3" + tslib "^2.1.0" + +"@firebase/database-compat@^0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-0.3.4.tgz#4e57932f7a5ba761cd5ac946ab6b6ab3f660522c" + integrity sha512-kuAW+l+sLMUKBThnvxvUZ+Q1ZrF/vFJ58iUY9kAcbX48U03nVzIF6Tmkf0p3WVQwMqiXguSgtOPIB6ZCeF+5Gg== + dependencies: + "@firebase/component" "0.6.4" + "@firebase/database" "0.14.4" + "@firebase/database-types" "0.10.4" + "@firebase/logger" "0.4.0" + "@firebase/util" "1.9.3" + tslib "^2.1.0" + +"@firebase/database-types@0.10.4", "@firebase/database-types@^0.10.4": + version "0.10.4" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.10.4.tgz#47ba81113512dab637abace61cfb65f63d645ca7" + integrity sha512-dPySn0vJ/89ZeBac70T+2tWWPiJXWbmRygYv0smT5TfE3hDrQ09eKMF3Y+vMlTdrMWq7mUdYW5REWPSGH4kAZQ== + dependencies: + "@firebase/app-types" "0.9.0" + "@firebase/util" "1.9.3" + +"@firebase/database@0.14.4": + version "0.14.4" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.14.4.tgz#9e7435a16a540ddfdeb5d99d45618e6ede179aa6" + integrity sha512-+Ea/IKGwh42jwdjCyzTmeZeLM3oy1h0mFPsTy6OqCWzcu/KFqRAr5Tt1HRCOBlNOdbh84JPZC47WLU18n2VbxQ== + dependencies: + "@firebase/auth-interop-types" "0.2.1" + "@firebase/component" "0.6.4" + "@firebase/logger" "0.4.0" + "@firebase/util" "1.9.3" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/logger@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.0.tgz#15ecc03c452525f9d47318ad9491b81d1810f113" + integrity sha512-eRKSeykumZ5+cJPdxxJRgAC3G5NknY2GwEbKfymdnXtnT0Ucm4pspfR6GT4MUQEDuJwRVbVcSx85kgJulMoFFA== + dependencies: + tslib "^2.1.0" + +"@firebase/util@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.9.3.tgz#45458dd5cd02d90e55c656e84adf6f3decf4b7ed" + integrity sha512-DY02CRhOZwpzO36fHpuVysz6JZrscPiBXD0fXp6qSrL9oNOx5KWICKdR95C0lSITzxp0TZosVyHqzatE8JbcjA== + dependencies: + tslib "^2.1.0" + +"@google-cloud/firestore@^6.6.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@google-cloud/firestore/-/firestore-6.7.0.tgz#9b6105442f972307ffc252b372ba7e67e38243fd" + integrity sha512-bkH2jb5KkQSUa+NAvpip9HQ+rpYhi77IaqHovWuN07adVmvNXX08gPpvPWEzoXYa/wDjEVI7LiAtCWkJJEYTNg== + dependencies: + fast-deep-equal "^3.1.1" + functional-red-black-tree "^1.0.1" + google-gax "^3.5.7" + protobufjs "^7.0.0" + +"@google-cloud/paginator@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.7.tgz#fb6f8e24ec841f99defaebf62c75c2e744dd419b" + integrity sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" + integrity sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA== + +"@google-cloud/promisify@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-3.0.1.tgz#8d724fb280f47d1ff99953aee0c1669b25238c2e" + integrity sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA== + +"@google-cloud/storage@^6.9.5": + version "6.12.0" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-6.12.0.tgz#a5d3093cc075252dca5bd19a3cfda406ad3a9de1" + integrity sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw== + dependencies: + "@google-cloud/paginator" "^3.0.7" + "@google-cloud/projectify" "^3.0.0" + "@google-cloud/promisify" "^3.0.0" + abort-controller "^3.0.0" + async-retry "^1.3.3" + compressible "^2.0.12" + duplexify "^4.0.0" + ent "^2.2.0" + extend "^3.0.2" + fast-xml-parser "^4.2.2" + gaxios "^5.0.0" + google-auth-library "^8.0.1" + mime "^3.0.0" + mime-types "^2.0.8" + p-limit "^3.0.1" + retry-request "^5.0.0" + teeny-request "^8.0.0" + uuid "^8.0.0" + +"@grpc/grpc-js@~1.8.0": + version "1.8.21" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.8.21.tgz#d282b122c71227859bf6c5866f4c40f4a2696513" + integrity sha512-KeyQeZpxeEBSqFVTi3q2K7PiPXmgBfECc4updA1ejCLjYmoAlvvM3ZMp5ztTDUCUQmoY3CpDxvchjO1+rFkoHg== + dependencies: + "@grpc/proto-loader" "^0.7.0" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.7.0": + version "0.7.10" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.10.tgz#6bf26742b1b54d0a473067743da5d3189d06d720" + integrity sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.4" + yargs "^17.7.2" + "@hyperledger/aries-askar-nodejs@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@hyperledger/aries-askar-nodejs/-/aries-askar-nodejs-0.1.1.tgz#93d59cec0a21aae3e06ce6149a2424564a0e3238" @@ -691,6 +837,13 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jsdoc/salty@^0.2.1": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@jsdoc/salty/-/salty-0.2.5.tgz#1b2fa5bb8c66485b536d86eee877c263d322f692" + integrity sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw== + dependencies: + lodash "^4.17.21" + "@mapbox/node-pre-gyp@^1.0.10": version "1.0.11" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" @@ -759,6 +912,59 @@ tslib "^2.5.0" webcrypto-core "^1.7.7" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -852,6 +1058,11 @@ dependencies: defer-to-connect "^2.0.0" +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -940,7 +1151,7 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express@^4.17.13", "@types/express@^4.17.15": +"@types/express@^4.17.13", "@types/express@^4.17.14", "@types/express@^4.17.15": version "4.17.17" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== @@ -950,6 +1161,14 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/glob@*": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== + dependencies: + "@types/minimatch" "^5.1.2" + "@types/node" "*" + "@types/graceful-fs@^4.1.3": version "4.1.6" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" @@ -994,6 +1213,13 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/jsonwebtoken@^9.0.0": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz#1f22283b8e1f933af9e195d720798b64b399d84c" + integrity sha512-b0jGiOgHtZ2jqdPgPnP6WLCXZk1T8p06A/vPGzUvxpFGgKMbjXJDjC5m52ErqBnIuWZFgGoIJyRdeG5AyreJjA== + dependencies: + "@types/node" "*" + "@types/keyv@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" @@ -1001,6 +1227,29 @@ dependencies: "@types/node" "*" +"@types/linkify-it@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.3.tgz#15a0712296c5041733c79efe233ba17ae5a7587b" + integrity sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g== + +"@types/long@^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/markdown-it@^12.2.3": + version "12.2.3" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-12.2.3.tgz#0d6f6e5e413f8daaa26522904597be3d6cd93b51" + integrity sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ== + dependencies: + "@types/linkify-it" "*" + "@types/mdurl" "*" + +"@types/mdurl@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" + integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== + "@types/mime@*": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" @@ -1011,6 +1260,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/minimatch@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" + integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== + "@types/node-fetch@^2.6.4": version "2.6.4" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" @@ -1024,6 +1278,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377" integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA== +"@types/node@>=12.12.47", "@types/node@>=13.7.0": + version "20.6.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.3.tgz#5b763b321cd3b80f6b8dde7a37e1a77ff9358dd9" + integrity sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA== + "@types/node@^16": version "16.18.46" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.46.tgz#9f2102d0ba74a318fcbe170cbff5463f119eab59" @@ -1051,6 +1310,14 @@ dependencies: "@types/node" "*" +"@types/rimraf@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.2.tgz#a63d175b331748e5220ad48c901d7bbf1f44eef8" + integrity sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ== + dependencies: + "@types/glob" "*" + "@types/node" "*" + "@types/send@*": version "0.17.1" resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" @@ -1119,6 +1386,11 @@ expo-modules-autolinking "^0.0.3" invariant "^2.2.4" +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1139,12 +1411,17 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.4.1: +acorn@^8.4.1, acorn@^8.9.0: version "8.10.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== @@ -1220,6 +1497,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -1233,6 +1515,11 @@ array-index@^1.0.0: debug "^2.2.0" es6-symbol "^3.0.2" +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asmcrypto.js@^0.22.0: version "0.22.0" resolved "https://registry.yarnpkg.com/asmcrypto.js/-/asmcrypto.js-0.22.0.tgz#38fc1440884d802c7bd37d1d23c2b26a5cd5d2d2" @@ -1247,6 +1534,13 @@ asn1js@^3.0.1, asn1js@^3.0.5: pvutils "^1.1.3" tslib "^2.4.0" +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1356,6 +1650,11 @@ bignumber.js@^9.0.0: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" @@ -1400,6 +1699,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -1436,6 +1742,11 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -1505,6 +1816,13 @@ canonicalize@^1.0.1: resolved "https://registry.yarnpkg.com/canonicalize/-/canonicalize-1.0.8.tgz#24d1f1a00ed202faafd9bf8e63352cd4450c6df1" integrity sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A== +catharsis@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" + integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A== + dependencies: + lodash "^4.17.15" + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1514,7 +1832,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1532,7 +1850,7 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== -ci-info@^3.2.0: +ci-info@^3.2.0, ci-info@^3.7.0: version "3.8.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== @@ -1638,6 +1956,13 @@ compare-versions@^3.4.0: resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62" integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA== +compressible@^2.0.12: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1726,7 +2051,7 @@ debug@2.6.9, debug@^2.2.0: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1757,6 +2082,11 @@ dedent@^1.0.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== +deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -1817,6 +2147,23 @@ dotenv@^16.0.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== +duplexify@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1842,13 +2189,23 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0: +end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== + +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -1902,11 +2259,52 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -esprima@^4.0.0: +escodegen@^1.13.0: + version "1.14.3" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-visitor-keys@^3.4.1: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +espree@^9.0.0: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -2010,6 +2408,11 @@ ext@^1.1.2: dependencies: type "^2.7.2" +extend@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" @@ -2021,6 +2424,11 @@ extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + fast-glob@^3.2.5: version "3.3.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" @@ -2037,11 +2445,23 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-text-encoding@^1.0.3: +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-text-encoding@^1.0.0, fast-text-encoding@^1.0.3: version "1.0.6" resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== +fast-xml-parser@^4.2.2: + version "4.3.0" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.3.0.tgz#fdaec352125c9f2157e472cd9894e84f91fd6da4" + integrity sha512-5Wln/SBrtlN37aboiNNFHfSALwLzpUx1vJhDgDVPKKG3JrNe8BWTUoNKqkeKk/HqNbKxC8nEAJaBydq30yHoLA== + dependencies: + strnum "^1.0.5" + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -2049,6 +2469,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +faye-websocket@0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" @@ -2121,6 +2548,30 @@ find-up@~5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +firebase-admin@^11.10.1: + version "11.10.1" + resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-11.10.1.tgz#5f0f83a44627e89938d350c5e4bbac76596c963e" + integrity sha512-atv1E6GbuvcvWaD3eHwrjeP5dAVs+EaHEJhu9CThMzPY6In8QYDiUR6tq5SwGl4SdA/GcAU0nhwWc/FSJsAzfQ== + dependencies: + "@fastify/busboy" "^1.2.1" + "@firebase/database-compat" "^0.3.4" + "@firebase/database-types" "^0.10.4" + "@types/node" ">=12.12.47" + jsonwebtoken "^9.0.0" + jwks-rsa "^3.0.1" + node-forge "^1.3.1" + uuid "^9.0.0" + optionalDependencies: + "@google-cloud/firestore" "^6.6.0" + "@google-cloud/storage" "^6.9.5" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -2140,7 +2591,7 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -2172,6 +2623,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + gauge@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" @@ -2187,6 +2643,24 @@ gauge@^3.0.0: strip-ansi "^6.0.1" wide-align "^1.1.2" +gaxios@^5.0.0, gaxios@^5.0.1: + version "5.1.3" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-5.1.3.tgz#f7fa92da0fe197c846441e5ead2573d4979e9013" + integrity sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA== + dependencies: + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.6.9" + +gcp-metadata@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-5.3.0.tgz#6f45eb473d0cb47d15001476b48b663744d25408" + integrity sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w== + dependencies: + gaxios "^5.0.0" + json-bigint "^1.0.0" + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -2255,11 +2729,65 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +google-auth-library@^8.0.1, google-auth-library@^8.0.2: + version "8.9.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-8.9.0.tgz#15a271eb2ec35d43b81deb72211bd61b1ef14dd0" + integrity sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^5.0.0" + gcp-metadata "^5.3.0" + gtoken "^6.1.0" + jws "^4.0.0" + lru-cache "^6.0.0" + +google-gax@^3.5.7: + version "3.6.1" + resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-3.6.1.tgz#02c78fc496f5adf86f2ca9145545f4b6575f6118" + integrity sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w== + dependencies: + "@grpc/grpc-js" "~1.8.0" + "@grpc/proto-loader" "^0.7.0" + "@types/long" "^4.0.0" + "@types/rimraf" "^3.0.2" + abort-controller "^3.0.0" + duplexify "^4.0.0" + fast-text-encoding "^1.0.3" + google-auth-library "^8.0.2" + is-stream-ended "^0.1.4" + node-fetch "^2.6.1" + object-hash "^3.0.0" + proto3-json-serializer "^1.0.0" + protobufjs "7.2.4" + protobufjs-cli "1.1.1" + retry-request "^5.0.0" + +google-p12-pem@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a" + integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ== + dependencies: + node-forge "^1.3.1" + got@^11.8.5: version "11.8.6" resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" @@ -2277,11 +2805,20 @@ got@^11.8.5: p-cancelable "^2.0.0" responselike "^2.0.0" -graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +gtoken@^6.1.0: + version "6.1.2" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" + integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ== + dependencies: + gaxios "^5.0.1" + google-p12-pem "^4.0.0" + jws "^4.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2340,6 +2877,20 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + http2-wrapper@^1.0.0-beta.5.2: version "1.0.3" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" @@ -2423,6 +2974,11 @@ is-core-module@^2.13.0: dependencies: has "^1.0.3" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2450,11 +3006,23 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-stream-ended@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" + integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2895,6 +3463,11 @@ jest@^29.2.2: import-local "^3.0.2" jest-cli "^29.6.4" +jose@^4.10.4: + version "4.14.6" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.6.tgz#94dca1d04a0ad8c6bff0998cdb51220d473cc3af" + integrity sha512-EqJPEUlZD0/CSUMubKtMaYUOtWe91tZXTWMJZoKSbLk+KtdhNdcvppH8lA9XwVu2V4Ailvsj0GBZJ2ZwDjfesQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2908,11 +3481,46 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js2xmlparser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" + integrity sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA== + dependencies: + xmlcreate "^2.0.4" + +jsdoc@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-4.0.2.tgz#a1273beba964cf433ddf7a70c23fd02c3c60296e" + integrity sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg== + dependencies: + "@babel/parser" "^7.20.15" + "@jsdoc/salty" "^0.2.1" + "@types/markdown-it" "^12.2.3" + bluebird "^3.7.2" + catharsis "^0.9.0" + escape-string-regexp "^2.0.0" + js2xmlparser "^4.0.2" + klaw "^3.0.0" + markdown-it "^12.3.2" + markdown-it-anchor "^8.4.1" + marked "^4.0.10" + mkdirp "^1.0.4" + requizzle "^0.2.3" + strip-json-comments "^3.1.0" + underscore "~1.13.2" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -2923,6 +3531,13 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-stable-stringify@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + json-text-sequence@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/json-text-sequence/-/json-text-sequence-0.3.0.tgz#6603e0ee45da41f949669fd18744b97fb209e6ce" @@ -2944,6 +3559,73 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jwa@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc" + integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jwks-rsa@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jwks-rsa/-/jwks-rsa-3.0.1.tgz#ba79ddca7ee7520f7bb26b942ef1aee91df8d7e4" + integrity sha512-UUOZ0CVReK1QVU3rbi9bC7N5/le8ziUj0A2ef1Q0M7OPD2KvjEYizptqIxGIo6fSLYDkqBrazILS18tYuRc8gw== + dependencies: + "@types/express" "^4.17.14" + "@types/jsonwebtoken" "^9.0.0" + debug "^4.3.4" + jose "^4.10.4" + limiter "^1.1.5" + lru-memoizer "^2.1.4" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + keyv@^4.0.0: version "4.5.3" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" @@ -2951,6 +3633,20 @@ keyv@^4.0.0: dependencies: json-buffer "3.0.1" +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" + integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== + dependencies: + graceful-fs "^4.1.9" + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -2974,16 +3670,36 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + libphonenumber-js@^1.10.14: version "1.10.43" resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.43.tgz#ef8b697c70a160142a653fc92931852c403a656f" integrity sha512-M/iPACJGsTvEy8QmUY4K0SoIFB71X2j7y2JvUMYzUXUxCNmiU+NTfHdz7gt+dC48BVfBzZi2oO6s9TDGllCfxA== +limiter@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" + integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -2998,16 +3714,66 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + lodash.memoize@4.x: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + +lodash@^4.17.15, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +long@^5.0.0: + version "5.2.3" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" + integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -3034,6 +3800,22 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + integrity sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw== + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +lru-memoizer@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-2.2.0.tgz#b9d90c91637b4b1a423ef76f3156566691293df8" + integrity sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw== + dependencies: + lodash.clonedeep "^4.5.0" + lru-cache "~4.0.0" + lru_map@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.4.1.tgz#f7b4046283c79fb7370c36f8fca6aee4324b0a98" @@ -3070,6 +3852,32 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +markdown-it-anchor@^8.4.1: + version "8.6.7" + resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz#ee6926daf3ad1ed5e4e3968b1740eef1c6399634" + integrity sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA== + +markdown-it@^12.3.2: + version "12.3.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" + integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marked@^4.0.10: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -3095,7 +3903,7 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -3103,12 +3911,12 @@ micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" -mime-db@1.52.0: +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -3120,6 +3928,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -3142,6 +3955,18 @@ minimatch@^3.0.4, minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + minipass@^3.0.0: version "3.3.6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" @@ -3162,7 +3987,7 @@ minizlib@^2.1.1: minipass "^3.0.0" yallist "^4.0.0" -mkdirp@^1.0.3: +mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -3236,13 +4061,18 @@ node-fetch@3.0.0-beta.9: data-uri-to-buffer "^3.0.1" fetch-blob "^2.1.1" -node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.6.9: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-gyp-build@^4.2.1: version "4.6.1" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" @@ -3297,6 +4127,11 @@ object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + object-inspect@^1.10.3, object-inspect@^1.9.0: version "1.12.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" @@ -3323,6 +4158,31 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-cancelable@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" @@ -3335,7 +4195,7 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.1, p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -3376,6 +4236,27 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +patch-package@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61" + integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + ci-info "^3.7.0" + cross-spawn "^7.0.3" + find-yarn-workspace-root "^2.0.0" + fs-extra "^9.0.0" + json-stable-stringify "^1.0.2" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + rimraf "^2.6.3" + semver "^7.5.3" + slash "^2.0.0" + tmp "^0.0.33" + yaml "^2.2.2" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -3428,6 +4309,11 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + prettier@^2.8.4: version "2.8.8" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" @@ -3450,6 +4336,65 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +proto3-json-serializer@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-1.1.1.tgz#1b5703152b6ce811c5cdcc6468032caf53521331" + integrity sha512-AwAuY4g9nxx0u52DnSMkqqgyLHaW/XaPLtaAo3y/ZCfeaQB/g4YDH4kb8Wc/mWzWvu0YjOznVnfn373MVZZrgw== + dependencies: + protobufjs "^7.0.0" + +protobufjs-cli@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/protobufjs-cli/-/protobufjs-cli-1.1.1.tgz#f531201b1c8c7772066aa822bf9a08318b24a704" + integrity sha512-VPWMgIcRNyQwWUv8OLPyGQ/0lQY/QTQAVN5fh+XzfDwsVw1FZ2L3DM/bcBf8WPiRz2tNpaov9lPZfNcmNo6LXA== + dependencies: + chalk "^4.0.0" + escodegen "^1.13.0" + espree "^9.0.0" + estraverse "^5.1.0" + glob "^8.0.0" + jsdoc "^4.0.0" + minimist "^1.2.0" + semver "^7.1.2" + tmp "^0.2.1" + uglify-js "^3.7.7" + +protobufjs@7.2.4: + version "7.2.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.4.tgz#3fc1ec0cdc89dd91aef9ba6037ba07408485c3ae" + integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + +protobufjs@^7.0.0, protobufjs@^7.2.4: + version "7.2.5" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.5.tgz#45d5c57387a6d29a17aab6846dcc283f9b8e7f2d" + integrity sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -3458,6 +4403,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -3537,7 +4487,7 @@ react-native-securerandom@^0.1.1: dependencies: base64-js "*" -readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -3581,6 +4531,13 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +requizzle@^0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" + integrity sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw== + dependencies: + lodash "^4.17.21" + resolve-alpn@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" @@ -3619,12 +4576,32 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +retry-request@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" + integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== + dependencies: + debug "^4.1.1" + extend "^3.0.2" + +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.2: +rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -3645,7 +4622,7 @@ rxjs@^7.2.0: dependencies: tslib "^2.1.0" -safe-buffer@5.2.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3660,7 +4637,7 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: +semver@^7.1.2, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -3744,6 +4721,11 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3765,7 +4747,7 @@ source-map-support@^0.5.21: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -3797,6 +4779,18 @@ str2buf@^1.3.0: resolved "https://registry.yarnpkg.com/str2buf/-/str2buf-1.3.0.tgz#a4172afff4310e67235178e738a2dbb573abead0" integrity sha512-xIBmHIUHYZDP4HyoXGHYNVmxlXLXDrtFHYT0eV6IOdEj3VO9ccaF1Ejl9Oq8iFjITllpT8FhaXb4KsNmw+3EuA== +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -3843,11 +4837,21 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-json-comments@^3.1.1: +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -3886,6 +4890,17 @@ tar@^6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" +teeny-request@^8.0.0: + version "8.0.3" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-8.0.3.tgz#5cb9c471ef5e59f2fca8280dc3c5909595e6ca24" + integrity sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww== + dependencies: + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.1" + stream-events "^1.0.5" + uuid "^9.0.0" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -3895,6 +4910,25 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-decoding@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-decoding/-/text-decoding-1.0.0.tgz#38a5692d23b5c2b12942d6e245599cb58b1bc52f" + integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -3979,6 +5013,13 @@ tsyringe@^4.7.0: dependencies: tslib "^1.9.3" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -4017,6 +5058,21 @@ typescript@^4.8.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +uglify-js@^3.7.7: + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + +underscore@~1.13.2: + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + universalify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" @@ -4045,7 +5101,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -"uuid@^7.0.0 || ^8.0.0": +"uuid@^7.0.0 || ^8.0.0", uuid@^8.0.0: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -4120,6 +5176,20 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -4142,6 +5212,11 @@ wide-align@^1.1.2: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +word-wrap@~1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -4169,11 +5244,21 @@ ws@^8.13.0, ws@^8.8.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== +xmlcreate@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" + integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -4189,12 +5274,17 @@ yaml@^1.10.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.2.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" + integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== + yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.3.1: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 0075e18dd70114e14a28933604f7c3f776c4312f Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Thu, 21 Sep 2023 19:58:45 +0530 Subject: [PATCH 4/7] fix: update old fcm record if device token is updated Signed-off-by: Sai Ranjit Tummalapalli --- src/events/RoutingEvents.ts | 29 ++++++-- .../fcm/PushNotificationsFcmApi.ts | 14 ---- .../fcm/PushNotificationsFcmModule.ts | 1 + src/push-notifications/fcm/constants.ts | 5 -- .../services/PushNotificationsFcmService.ts | 69 +++++++++---------- 5 files changed, 56 insertions(+), 62 deletions(-) delete mode 100644 src/push-notifications/fcm/constants.ts diff --git a/src/events/RoutingEvents.ts b/src/events/RoutingEvents.ts index 302642e..a3ed28a 100644 --- a/src/events/RoutingEvents.ts +++ b/src/events/RoutingEvents.ts @@ -1,17 +1,32 @@ -import type { Agent, ForwardMessageEvent } from '@aries-framework/core' +import type { ForwardMessageEvent } from '@aries-framework/core' -import { RoutingEventTypes } from '@aries-framework/core' +import { RecordDuplicateError, RoutingEventTypes } from '@aries-framework/core' import { sendNotificationEvent } from './PushNotificationEvent' import { MediatorAgent } from '../agent' export const routingEvents = async (agent: MediatorAgent) => { agent.events.on(RoutingEventTypes.ForwardMessageEvent, async (event: ForwardMessageEvent) => { - const record = event.payload.connectionRecord + try { + const record = event.payload.connectionRecord - // Get device info from PushNotificationsFcmRecord - const fcmDeviceInfoRecord = await agent.modules.pushNotificationsFcm.getDeviceInfoByConnectionId(record.id) + // Get device info from PushNotificationsFcmRecord + const fcmDeviceInfoRecord = await agent.modules.pushNotificationsFcm.getDeviceInfoByConnectionId(record.id) - // Send notification to device - await sendNotificationEvent(fcmDeviceInfoRecord, agent.config.logger) + if (fcmDeviceInfoRecord?.deviceToken) { + agent.config.logger.info(`Sending notification to ${fcmDeviceInfoRecord.connectionId}`) + // Send notification to device + await sendNotificationEvent(fcmDeviceInfoRecord, agent.config.logger) + } else { + agent.config.logger.info(`No device token found for connectionId so skipping send notification event`) + } + } catch (error) { + if (error instanceof RecordDuplicateError) { + agent.config.logger.error(`Multiple device info found for connectionId ${event.payload.connectionRecord.id}`) + } else { + agent.config.logger.error(`Error sending notification`, { + cause: error, + }) + } + } }) } diff --git a/src/push-notifications/fcm/PushNotificationsFcmApi.ts b/src/push-notifications/fcm/PushNotificationsFcmApi.ts index 09ef1a6..766f111 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmApi.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmApi.ts @@ -40,20 +40,6 @@ export class PushNotificationsFcmApi { ]) } - /** - * Sends a set request with the fcm device info (token) to another agent via a `connectionId` - * - * @param connectionId The connection ID string - * @param deviceInfo The FCM device info - * @returns Promise - */ - public async setDeviceInfo(connectionId: string, deviceInfo: FcmDeviceInfo) { - const connection = await this.connectionService.getById(this.agentContext, connectionId) - connection.assertReady() - - await this.pushNotificationsService.setDeviceInfo(this.agentContext, connection.id, deviceInfo) - } - /** * Sends the requested fcm device info (token) to another agent via a `connectionId` * Response for `push-notifications-fcm/get-device-info` diff --git a/src/push-notifications/fcm/PushNotificationsFcmModule.ts b/src/push-notifications/fcm/PushNotificationsFcmModule.ts index 705edfe..ed6c7ee 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmModule.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmModule.ts @@ -23,6 +23,7 @@ export class PushNotificationsFcmModule implements Module { // Repository dependencyManager.registerSingleton(PushNotificationsFcmRepository) + // Feature Registry featureRegistry.register( new Protocol({ id: 'https://didcomm.org/push-notifications-fcm/1.0', diff --git a/src/push-notifications/fcm/constants.ts b/src/push-notifications/fcm/constants.ts deleted file mode 100644 index 8c21622..0000000 --- a/src/push-notifications/fcm/constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -// FIREBASE -export const SCOPES = ['https://www.googleapis.com/auth/firebase.messaging'] -export const BASE_URL = 'https://fcm.googleapis.com' -export const ENDPOINT_PREFIX = 'v1/projects/' -export const ENDPOINT_SUFFIX = '/messages:send' diff --git a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts index 1116a17..26a0712 100644 --- a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts +++ b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts @@ -1,37 +1,23 @@ import type { FcmDeviceInfo } from '../models/FcmDeviceInfo' -import type { AgentContext, InboundMessageContext } from '@aries-framework/core' +import type { AgentContext, InboundMessageContext, Logger } from '@aries-framework/core' -import { AriesFrameworkError } from '@aries-framework/core' -import { Lifecycle, scoped } from 'tsyringe' +import { AriesFrameworkError, inject, InjectionSymbols, injectable } from '@aries-framework/core' import { PushNotificationsFcmProblemReportError, PushNotificationsFcmProblemReportReason } from '../errors' import { PushNotificationsFcmSetDeviceInfoMessage, PushNotificationsFcmDeviceInfoMessage } from '../messages' import { PushNotificationsFcmRecord, PushNotificationsFcmRepository } from '../repository' -@scoped(Lifecycle.ContainerScoped) +@injectable() export class PushNotificationsFcmService { private pushNotificationsFcmRepository: PushNotificationsFcmRepository + private logger: Logger - public constructor(pushNotificationsFcmRepository: PushNotificationsFcmRepository) { + public constructor( + pushNotificationsFcmRepository: PushNotificationsFcmRepository, + @inject(InjectionSymbols.Logger) logger: Logger + ) { this.pushNotificationsFcmRepository = pushNotificationsFcmRepository - } - - public async setDeviceInfo(agentContext: AgentContext, connectionId: string, deviceInfo: FcmDeviceInfo) { - if ( - (deviceInfo.deviceToken === null && deviceInfo.devicePlatform !== null) || - (deviceInfo.deviceToken !== null && deviceInfo.devicePlatform === null) - ) - throw new AriesFrameworkError('Both or none of deviceToken and devicePlatform must be null') - - const pushNotificationsFcmSetDeviceInfoRecord = new PushNotificationsFcmRecord({ - connectionId, - deviceToken: deviceInfo.deviceToken, - devicePlatform: deviceInfo.devicePlatform, - }) - - await this.pushNotificationsFcmRepository.save(agentContext, pushNotificationsFcmSetDeviceInfoRecord) - - return pushNotificationsFcmSetDeviceInfoRecord + this.logger = logger } public createDeviceInfo(options: { threadId: string; deviceInfo: FcmDeviceInfo }) { @@ -50,7 +36,7 @@ export class PushNotificationsFcmService { } public async processSetDeviceInfo(messageContext: InboundMessageContext) { - const { message } = messageContext + const { message, agentContext } = messageContext if ( (message.deviceToken === null && message.devicePlatform !== null) || (message.deviceToken !== null && message.devicePlatform === null) @@ -62,26 +48,37 @@ export class PushNotificationsFcmService { const connection = messageContext.assertReadyConnection() - const pushNotificationsFcmRecord = new PushNotificationsFcmRecord({ + let pushNotificationsFcmRecord = await this.pushNotificationsFcmRepository.findSingleByQuery(agentContext, { connectionId: connection.id, - deviceToken: message.deviceToken, - devicePlatform: message.devicePlatform, }) - await this.pushNotificationsFcmRepository.save(messageContext.agentContext, pushNotificationsFcmRecord) + if (pushNotificationsFcmRecord) { + if (pushNotificationsFcmRecord.deviceToken === message.deviceToken) { + this.logger.debug(`Device token is same for connection ${connection.id}. So skipping update`) + return + } - return pushNotificationsFcmRecord + // Update the record with new device token + pushNotificationsFcmRecord.deviceToken = message.deviceToken + + this.logger.debug(`Device token changed for connection ${connection.id}. Updating record`) + await this.pushNotificationsFcmRepository.update(agentContext, pushNotificationsFcmRecord) + } else { + this.logger.debug(`No device info found for connection ${connection.id}. So creating new record`) + + pushNotificationsFcmRecord = new PushNotificationsFcmRecord({ + connectionId: connection.id, + deviceToken: message.deviceToken, + devicePlatform: message.devicePlatform, + }) + + await this.pushNotificationsFcmRepository.save(agentContext, pushNotificationsFcmRecord) + } } public async getDeviceInfo(agentContext: AgentContext, connectionId: string) { - const pushNotificationsFcmRecord = await this.pushNotificationsFcmRepository.getSingleByQuery(agentContext, { + return this.pushNotificationsFcmRepository.findSingleByQuery(agentContext, { connectionId, }) - - if (!pushNotificationsFcmRecord) { - console.error(`No device info found for connection ${connectionId}`) - } - - return pushNotificationsFcmRecord } } From 54d6285c4c87d2a433792ba081138b97c94e2c4a Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Fri, 22 Sep 2023 11:48:23 +0530 Subject: [PATCH 5/7] fix: add apns config while sending notifications Signed-off-by: Sai Ranjit Tummalapalli --- src/events/PushNotificationEvent.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/events/PushNotificationEvent.ts b/src/events/PushNotificationEvent.ts index 7172756..713bdf8 100644 --- a/src/events/PushNotificationEvent.ts +++ b/src/events/PushNotificationEvent.ts @@ -14,6 +14,13 @@ export const sendNotificationEvent = async (pushNotificationFcmRecord: PushNotif title: FIREBASE_NOTIFICATION_TITLE, body: FIREBASE_NOTIFICATION_BODY, }, + apns: { + payload: { + aps: { + sound: 'default', + }, + }, + }, token: pushNotificationFcmRecord.deviceToken, } const response = await admin.messaging().send(message) From 44eb696ed5bdffbbfa5f54fb625a56780a2512c2 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Fri, 22 Sep 2023 16:11:18 +0530 Subject: [PATCH 6/7] refactor: add send notification method to service Signed-off-by: Sai Ranjit Tummalapalli --- src/events/PushNotificationEvent.ts | 34 ------------- src/events/RoutingEvents.ts | 24 ++------- .../fcm/PushNotificationsFcmApi.ts | 8 +-- .../services/PushNotificationsFcmService.ts | 49 +++++++++++++++++-- 4 files changed, 53 insertions(+), 62 deletions(-) delete mode 100644 src/events/PushNotificationEvent.ts diff --git a/src/events/PushNotificationEvent.ts b/src/events/PushNotificationEvent.ts deleted file mode 100644 index 713bdf8..0000000 --- a/src/events/PushNotificationEvent.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { Logger } from '@aries-framework/core' -import * as admin from 'firebase-admin' -import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE } from '../constants' -import { PushNotificationsFcmRecord } from '../push-notifications/fcm/repository' - -export const sendNotificationEvent = async (pushNotificationFcmRecord: PushNotificationsFcmRecord, logger: Logger) => { - try { - if (!pushNotificationFcmRecord?.deviceToken) { - logger.info(`No device token found for connectionId ${pushNotificationFcmRecord.connectionId}`) - return - } - const message = { - notification: { - title: FIREBASE_NOTIFICATION_TITLE, - body: FIREBASE_NOTIFICATION_BODY, - }, - apns: { - payload: { - aps: { - sound: 'default', - }, - }, - }, - token: pushNotificationFcmRecord.deviceToken, - } - const response = await admin.messaging().send(message) - logger.info(`Notification sent successfully to ${pushNotificationFcmRecord.connectionId}`) - return response - } catch (error) { - logger.error(`Error sending notification`, { - cause: error, - }) - } -} diff --git a/src/events/RoutingEvents.ts b/src/events/RoutingEvents.ts index a3ed28a..5accf6f 100644 --- a/src/events/RoutingEvents.ts +++ b/src/events/RoutingEvents.ts @@ -1,7 +1,6 @@ import type { ForwardMessageEvent } from '@aries-framework/core' -import { RecordDuplicateError, RoutingEventTypes } from '@aries-framework/core' -import { sendNotificationEvent } from './PushNotificationEvent' +import { RoutingEventTypes } from '@aries-framework/core' import { MediatorAgent } from '../agent' export const routingEvents = async (agent: MediatorAgent) => { @@ -9,24 +8,11 @@ export const routingEvents = async (agent: MediatorAgent) => { try { const record = event.payload.connectionRecord - // Get device info from PushNotificationsFcmRecord - const fcmDeviceInfoRecord = await agent.modules.pushNotificationsFcm.getDeviceInfoByConnectionId(record.id) - - if (fcmDeviceInfoRecord?.deviceToken) { - agent.config.logger.info(`Sending notification to ${fcmDeviceInfoRecord.connectionId}`) - // Send notification to device - await sendNotificationEvent(fcmDeviceInfoRecord, agent.config.logger) - } else { - agent.config.logger.info(`No device token found for connectionId so skipping send notification event`) - } + await agent.modules.pushNotificationsFcm.sendNotification(record.id) } catch (error) { - if (error instanceof RecordDuplicateError) { - agent.config.logger.error(`Multiple device info found for connectionId ${event.payload.connectionRecord.id}`) - } else { - agent.config.logger.error(`Error sending notification`, { - cause: error, - }) - } + agent.config.logger.error(`Error sending notification`, { + cause: error, + }) } }) } diff --git a/src/push-notifications/fcm/PushNotificationsFcmApi.ts b/src/push-notifications/fcm/PushNotificationsFcmApi.ts index 766f111..12c320b 100644 --- a/src/push-notifications/fcm/PushNotificationsFcmApi.ts +++ b/src/push-notifications/fcm/PushNotificationsFcmApi.ts @@ -64,12 +64,12 @@ export class PushNotificationsFcmApi { } /** - * Get push notification record by `connectionId` + * Send push notification to device * * @param connectionId The connection ID string - * @returns Promise + * @returns Promise */ - public async getDeviceInfoByConnectionId(connectionId: string) { - return this.pushNotificationsService.getDeviceInfo(this.agentContext, connectionId) + public async sendNotification(connectionId: string) { + return this.pushNotificationsService.sendNotification(this.agentContext, connectionId) } } diff --git a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts index 26a0712..968e162 100644 --- a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts +++ b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts @@ -1,12 +1,15 @@ import type { FcmDeviceInfo } from '../models/FcmDeviceInfo' import type { AgentContext, InboundMessageContext, Logger } from '@aries-framework/core' -import { AriesFrameworkError, inject, InjectionSymbols, injectable } from '@aries-framework/core' +import { AriesFrameworkError, inject, InjectionSymbols, injectable, RecordDuplicateError } from '@aries-framework/core' import { PushNotificationsFcmProblemReportError, PushNotificationsFcmProblemReportReason } from '../errors' import { PushNotificationsFcmSetDeviceInfoMessage, PushNotificationsFcmDeviceInfoMessage } from '../messages' import { PushNotificationsFcmRecord, PushNotificationsFcmRepository } from '../repository' +import * as admin from 'firebase-admin' +import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE } from '../../../constants' + @injectable() export class PushNotificationsFcmService { private pushNotificationsFcmRepository: PushNotificationsFcmRepository @@ -76,9 +79,45 @@ export class PushNotificationsFcmService { } } - public async getDeviceInfo(agentContext: AgentContext, connectionId: string) { - return this.pushNotificationsFcmRepository.findSingleByQuery(agentContext, { - connectionId, - }) + public async sendNotification(agentContext: AgentContext, connectionId: string) { + try { + // Get the device token for the connection + const pushNotificationFcmRecord = await this.pushNotificationsFcmRepository.findSingleByQuery(agentContext, { + connectionId, + }) + + if (!pushNotificationFcmRecord?.deviceToken) { + this.logger.info(`No device token found for connectionId so skip sending notification`) + return + } + + // Prepare a message to be sent to the device + const message = { + notification: { + title: FIREBASE_NOTIFICATION_TITLE, + body: FIREBASE_NOTIFICATION_BODY, + }, + apns: { + payload: { + aps: { + sound: 'default', + }, + }, + }, + token: pushNotificationFcmRecord.deviceToken, + } + + this.logger.info(`Sending notification to ${pushNotificationFcmRecord?.connectionId}`) + await admin.messaging().send(message) + this.logger.info(`Notification sent successfully to ${pushNotificationFcmRecord.connectionId}`) + } catch (error) { + if (error instanceof RecordDuplicateError) { + this.logger.error(`Multiple device info found for connectionId ${connectionId}`) + } else { + this.logger.error(`Error sending notification`, { + cause: error, + }) + } + } } } From bedb00f0b736d489437f69fa9d09eb43f3873a21 Mon Sep 17 00:00:00 2001 From: Sai Ranjit Tummalapalli Date: Fri, 22 Sep 2023 16:31:48 +0530 Subject: [PATCH 7/7] refactor: skip sending notification if connection is active Signed-off-by: Sai Ranjit Tummalapalli --- .../services/PushNotificationsFcmService.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts index 968e162..9925a7d 100644 --- a/src/push-notifications/fcm/services/PushNotificationsFcmService.ts +++ b/src/push-notifications/fcm/services/PushNotificationsFcmService.ts @@ -1,7 +1,14 @@ import type { FcmDeviceInfo } from '../models/FcmDeviceInfo' import type { AgentContext, InboundMessageContext, Logger } from '@aries-framework/core' -import { AriesFrameworkError, inject, InjectionSymbols, injectable, RecordDuplicateError } from '@aries-framework/core' +import { + AriesFrameworkError, + inject, + InjectionSymbols, + injectable, + RecordDuplicateError, + TransportService, +} from '@aries-framework/core' import { PushNotificationsFcmProblemReportError, PushNotificationsFcmProblemReportReason } from '../errors' import { PushNotificationsFcmSetDeviceInfoMessage, PushNotificationsFcmDeviceInfoMessage } from '../messages' @@ -14,13 +21,16 @@ import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE } from '../../. export class PushNotificationsFcmService { private pushNotificationsFcmRepository: PushNotificationsFcmRepository private logger: Logger + private transportService: TransportService public constructor( pushNotificationsFcmRepository: PushNotificationsFcmRepository, + transportService: TransportService, @inject(InjectionSymbols.Logger) logger: Logger ) { this.pushNotificationsFcmRepository = pushNotificationsFcmRepository this.logger = logger + this.transportService = transportService } public createDeviceInfo(options: { threadId: string; deviceInfo: FcmDeviceInfo }) { @@ -81,6 +91,14 @@ export class PushNotificationsFcmService { public async sendNotification(agentContext: AgentContext, connectionId: string) { try { + // Get the session for the connection + const session = await this.transportService.findSessionByConnectionId(connectionId) + + if (session) { + this.logger.info(`Connection ${connectionId} is active. So skip sending notification`) + return + } + // Get the device token for the connection const pushNotificationFcmRecord = await this.pushNotificationsFcmRepository.findSingleByQuery(agentContext, { connectionId,