diff --git a/api/package.json b/api/package.json index 81f9157..527cbf9 100644 --- a/api/package.json +++ b/api/package.json @@ -28,7 +28,7 @@ "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@noahspan/azure-database": "^3.1.2", - "@noahspan/noahspan-modules": "^0.5.2", + "@noahspan/noahspan-modules": "^0.6.5", "axios": "^1.7.9", "reflect-metadata": "^0.1.14", "rxjs": "^7.8.1", diff --git a/api/src/app.controller.ts b/api/src/app.controller.ts new file mode 100644 index 0000000..3bf2b15 --- /dev/null +++ b/api/src/app.controller.ts @@ -0,0 +1,78 @@ +import { + Controller, + Get, + Headers, + Query, + StreamableFile, + UseGuards +} from '@nestjs/common'; +// import { Client as MsGraphClient } from '@microsoft/microsoft-graph-client'; +import { MsGraphService } from '@noahspan/noahspan-modules' + +@Controller() +export class AppController { + constructor( + private readonly msGraphService: MsGraphService + ) {} + + @Get('userPhoto') + async getProfilePhoto(@Headers() headers: any): Promise { + // try { + // const graphToken: string = await this.msGraphService.getMsGraphAuth( + // headers.authorization.replace('Bearer ', ''), + // ['user.read'] + // ); + // const client: MsGraphClient = + // await this.msGraphService.getMsGraphClientDelegated(graphToken); + // const blob: Blob = await client.api(`me/photos('48x48')/$value`).get(); + // const arrayBuffer: ArrayBuffer = await blob.arrayBuffer(); + // const buffer: Buffer = Buffer.from(arrayBuffer); + + // return new StreamableFile(buffer, { + // type: 'application/json', + // disposition: `attachment; filename="user_photo.png"` + // }); + // } catch (error) { + // return error; + // } + + try { + const buffer = await this.msGraphService.getProfilePhoto( + headers.authorization.replace('Bearer ', ''), + ['user.read'] + ) + + return new StreamableFile(buffer, { + type: 'application/json', + disposition: `attachment; filename="user_photo.png"` + }); + } catch (error) { + return error; + } + } + + @Get('userProfile') + async getUserProfile(@Headers() headers: any): Promise { + // try { + // const graphToken: string = await this.msGraphService.getMsGraphAuth( + // headers.authorization.replace('Bearer ', ''), + // ['user.read'] + // ); + // const client: MsGraphClient = + // await this.msGraphService.getMsGraphClientDelegated(graphToken); + // const userProfile = await client.api(`me`).get(); + + // return userProfile; + // } catch (error) { + // return error; + // } + + try { + const userProfile = await this.msGraphService.getUserProfile(headers.authorization.replace('Bearer ', '')); + + return userProfile; + } catch (error) { + return error; + } + } +} diff --git a/api/src/app.module.ts b/api/src/app.module.ts index 0e4d247..bd23c2b 100644 --- a/api/src/app.module.ts +++ b/api/src/app.module.ts @@ -1,18 +1,50 @@ import { Module } from '@nestjs/common'; -import { GitHubApiModule } from './github/github.module'; -import { APP_FILTER } from '@nestjs/core'; +import { APP_FILTER, APP_GUARD } from '@nestjs/core'; import { HttpExceptionFilter } from './filters/http-exception.filter'; import { ProjectModule } from './project/project.module'; +import { AuthGuard, AuthModule, MsGraphModule } from '@noahspan/noahspan-modules' +import { ConfigModule, ConfigService } from '@nestjs/config'; +import configuration from './config/configuration'; +import { AppController } from './app.controller'; @Module({ imports: [ - GitHubApiModule, + AuthModule.registerAsync({ + inject: [ConfigService], + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => { + return { + clientId: configService.get('clientId'), + clientSecret: configService.get('clientSecret'), + tenantId: configService.get('tenantId') + } + } + }), + ConfigModule.forRoot({ + load: [configuration] + }), + MsGraphModule.registerAsync({ + inject: [ConfigService], + imports: [ConfigModule], + useFactory: async (configService: ConfigService) => { + return { + clientId: configService.get('clientId'), + clientSecret: configService.get('clientSecret'), + tenantId: configService.get('tenantId') + } + } + }), ProjectModule ], + controllers: [AppController], providers: [ { provide: APP_FILTER, useClass: HttpExceptionFilter + }, + { + provide: APP_GUARD, + useClass: AuthGuard } ] }) diff --git a/api/src/config/configuration.ts b/api/src/config/configuration.ts index dbaedbb..b92caed 100644 --- a/api/src/config/configuration.ts +++ b/api/src/config/configuration.ts @@ -1,4 +1,5 @@ export default () => ({ - githubApiUsername: process.env.GITHUB_API_USERNAME, - githubApiPassword: process.env.GITHUB_API_PAT + clientId: process.env.CLIENT_ID, + clientSecret: process.env.CLIENT_SECRET, + tenantId: process.env.TENANT_ID }) \ No newline at end of file diff --git a/api/src/project/project.controller.ts b/api/src/project/project.controller.ts index 13d8b15..e3e0283 100644 --- a/api/src/project/project.controller.ts +++ b/api/src/project/project.controller.ts @@ -6,12 +6,13 @@ import { HttpException, Param, Post, - Put + Put, + UseGuards } from '@nestjs/common'; import { ProjectDto } from './project.dto'; import { Project } from './project.entity'; import { ProjectService } from './project.service'; -import { CustomError } from '@noahspan/noahspan-modules'; +import { CustomError, Public } from '@noahspan/noahspan-modules'; @Controller('projects') export class ProjectController { @@ -31,6 +32,7 @@ export class ProjectController { } } + @Public() @Get() async findAll() { try { diff --git a/app2/src/components/projects/Projects.tsx b/app2/src/components/projects/Projects.tsx index 828e148..c2e28f6 100644 --- a/app2/src/components/projects/Projects.tsx +++ b/app2/src/components/projects/Projects.tsx @@ -43,12 +43,12 @@ const Projects = () => { const getProjects = async (): Promise => { try { - const config = isAuthenticated - ? { headers: { Authorization: await getAccessToken() } } - : {}; + // const config = isAuthenticated + // ? { headers: { Authorization: await getAccessToken() } } + // : {}; const response: AxiosResponse = await httpClient.get( `api/projects`, - config + // config ); const projects: Project[] = response.data; diff --git a/infrastructure/app_config.tf b/infrastructure/app_config.tf deleted file mode 100644 index 6740cef..0000000 --- a/infrastructure/app_config.tf +++ /dev/null @@ -1,47 +0,0 @@ -# data "azurerm_client_config" "current" {} - -# data "azurerm_user_assigned_identity" "user_assigned_identity" { -# name = "noahspanflyingdevuser" -# resource_group_name = azurerm_resource_group.resource_group.name -# } - -# resource "azurerm_app_configuration" "app_configuration" { -# name = "noahspan-appconfig" -# resource_group_name = azurerm_resource_group.resource_group.name -# location = azurerm_resource_group.resource_group.location - -# identity { -# type = "UserAssigned" -# identity_ids = [ -# data.azurerm_user_assigned_identity.user_assigned_identity.id -# ] -# } -# } - - - -# resource "azurerm_role_assignment" "role_assignment" { -# scope = azurerm_app_configuration.app_configuration.id -# role_definition_name = "App Configuration Data Owner" -# principal_id = data.azurerm_client_config.current.object_id -# } - -# resource "azurerm_app_configuration_feature" "flying-pilots" { -# configuration_store_id = azurerm_app_configuration.app_configuration.id -# description = "Feature flag for pilots page in flying app" -# name = "flying-pilots" -# label = "flying-pilots-label" -# enabled = false - -# depends_on = [ azurerm_role_assignment.role_assignment ] -# } - -# resource "azurerm_app_configuration_feature" "flying-logbook" { -# configuration_store_id = azurerm_app_configuration.app_configuration.id -# description = "Feature flag for logbook page in flying app" -# name = "flying-logbook" -# label = "flying-logbook-label" -# enabled = false - -# depends_on = [ azurerm_role_assignment.role_assignment ] -# } \ No newline at end of file diff --git a/infrastructure/config/main.tf b/infrastructure/config/main.tf index 1a4ffa4..3266463 100644 --- a/infrastructure/config/main.tf +++ b/infrastructure/config/main.tf @@ -39,14 +39,23 @@ locals { prod = "root-prod" } + custom_domain_count = { + test = 0 + prod = 1 + } + log_analytics_workspace_name = { test = "root-log-analytics-workspace-test" prod = "root-log-analytics-workspace-prod" } - storage_account_name = { test = "noahspanroottest" prod = "noahspanrootprod" } + + storage_tables = { + test = ["logs", "pilots"] + prod = ["logs", "pilots"] + } } \ No newline at end of file diff --git a/infrastructure/dns.tf b/infrastructure/dns.tf deleted file mode 100644 index 681efb4..0000000 --- a/infrastructure/dns.tf +++ /dev/null @@ -1,49 +0,0 @@ -# resource "azurerm_static_web_app_custom_domain" "static_web_app_custom_domain_txt" { -# static_web_app_id = module.static_web_app.id -# domain_name = var.DOMAIN_NAME -# validation_type = "dns-txt-token" -# } - -# resource "azurerm_dns_zone" "dns_zone" { -# name = var.DOMAIN_NAME -# resource_group_name = azurerm_resource_group.resource_group.name -# } - -# resource "azurerm_dns_txt_record" "dns_txt_record" { -# name = var.WEBSITE_NAME == var.DOMAIN_NAME ? "@" : split(".", var.WEBSITE_NAME)[0] -# zone_name = azurerm_dns_zone.dns_zone.name -# resource_group_name = azurerm_resource_group.resource_group.name -# ttl = 14400 -# record { -# value = azurerm_static_web_app_custom_domain.static_web_app_custom_domain.validation_token == "" ? "validated" : azurerm_static_web_app_custom_domain.static_web_app_custom_domain.validation_token -# } - -# # email -# record { -# value = var.EMAIL_TXT_VALUE == "" ? "validated" : var.EMAIL_TXT_VALUE -# } - -# record { -# value = var.EMAIL_SPF_VALUE == "" ? "validated" : var.EMAIL_SPF_VALUE -# } -# } - -# email - -# resource "azurerm_dns_mx_record" "dns_mx_record" { -# name = "@" -# zone_name = azurerm_dns_zone.dns_zone.name -# resource_group_name = azurerm_resource_group.resource_group.name -# ttl = 14400 - -# record { -# preference = 10 -# exchange = "mx01.mail.icloud.com." -# } - -# record { -# preference = 10 -# exchange = "mx02.mail.icloud.com." -# } -# } - diff --git a/infrastructure/main.tf b/infrastructure/main.tf index e03e45e..02b47cc 100644 --- a/infrastructure/main.tf +++ b/infrastructure/main.tf @@ -1,205 +1,23 @@ -# module "static_web_app" { -# source = "./modules/static_web_app" -# region = var.REGION -# resource_group_name = azurerm_resource_group.resource_group.name -# static_web_app_name = var.STATIC_WEB_APP_NAME -# custom_domain_name_count = var.CUSTOM_DOMAIN_NAME_COUNT -# domain_name = var.DOMAIN_NAME -# subdomain_name = var.SUBDOMAIN_NAME -# } - -# resource "azurerm_static_web_app" "static_web_app" { -# name = var.STATIC_WEB_APP_NAME -# resource_group_name = azurerm_resource_group.resource_group.name -# location = var.REGION -# } - -# resource "azurerm_static_web_app_custom_domain" "static_web_app_custom_domain" { -# static_web_app_id = azurerm_static_web_app.static_web_app.id -# domain_name = var.WEBSITE_NAME -# validation_type = "dns-txt-token" -# } - -# resource "azurerm_dns_a_record" "dns_a_record" { -# name = var.WEBSITE_NAME == var.DOMAIN_NAME ? "@" : split(".", var.WEBSITE_NAME)[0] -# zone_name = azurerm_dns_zone.dns_zone.name -# resource_group_name = azurerm_resource_group.resource_group.name -# ttl = 14400 -# target_resource_id = azurerm_static_web_app.static_web_app.id -# } - -# resource "azurerm_dns_cname_record" "dns_cname_record" { -# name = "www" -# zone_name = azurerm_dns_zone.dns_zone.name -# resource_group_name = azurerm_resource_group.resource_group.name -# ttl = 14400 -# record = azurerm_static_web_app.static_web_app.default_host_name -# } - -# resource "azurerm_static_web_app_custom_domain" "static_web_app_custom_domain_www" { -# static_web_app_id = azurerm_static_web_app.static_web_app.id -# domain_name = "www.${var.DOMAIN_NAME}" -# validation_type = "cname-delegation" - -# depends_on = [ azurerm_dns_cname_record.dns_cname_record ] -# } - - -# data "azurerm_client_config" "current" { -# } - -# resource "azurerm_log_analytics_workspace" "log_analytics_workspace" { -# name = module.environment.log_analytics_workspace_name -# location = data.azurerm_resource_group.resource_group.location -# resource_group_name = data.azurerm_resource_group.resource_group.name -# sku = "PerGB2018" -# retention_in_days = 30 -# } - -# resource "azurerm_container_app_environment" "container_app_environment" { -# name = module.environment.container_app_environment_name -# location = data.azurerm_resource_group.resource_group.location -# resource_group_name = data.azurerm_resource_group.resource_group.name -# log_analytics_workspace_id = azurerm_log_analytics_workspace.log_analytics_workspace.id -# } - -# resource "azurerm_container_app" "container_app_api" { -# name = module.environment.container_app_api_name -# container_app_environment_id = azurerm_container_app_environment.container_app_environment.id -# resource_group_name = data.azurerm_resource_group.resource_group.name -# revision_mode = "Single" - -# registry { -# server = "index.docker.io" -# username = var.DOCKER_IO_USERNAME -# password_secret_name = "docker-io-password" -# } - -# template { -# min_replicas = 0 -# max_replicas = 2 - -# container { -# name = module.environment.container_app_api_container_name -# image = module.environment.container_app_api_container_image -# cpu = 0.25 -# memory = "0.5Gi" - -# env { -# name = "AZURE_STORAGE_CONNECTION_STRING" -# secret_name = "azure-storage-connection-string" -# } - -# env { -# name = "CLIENT_ID" -# secret_name = "client-id" -# } - -# env { -# name = "CLIENT_SECRET" -# secret_name = "client-secret" -# } - -# env { -# name = "TENANT_ID" -# secret_name = "tenant-id" -# } -# } -# } - -# ingress { -# allow_insecure_connections = false -# external_enabled = true -# target_port = 3000 -# transport = "auto" - -# traffic_weight { -# latest_revision = true -# percentage = 100 -# } -# } - -# secret { -# name = "docker-io-password" -# value = var.DOCKER_IO_PASSWORD -# } - -# secret { -# name = "azure-storage-connection-string" -# value = azurerm_storage_account.storage_account.primary_connection_string -# } - -# secret { -# name = "client-id" -# value = var.CLIENT_ID -# } - -# secret { -# name = "client-secret" -# value = var.CLIENT_SECRET -# } - -# secret { -# name = "tenant-id" -# value = var.TENANT_ID -# } - -# lifecycle { -# ignore_changes = [ template[0].container[0].image ] -# } -# } - -# resource "azurerm_container_app" "container_app_app" { -# name = module.environment.container_app_app_name -# container_app_environment_id = azurerm_container_app_environment.container_app_environment.id -# resource_group_name = data.azurerm_resource_group.resource_group.name -# revision_mode = "Single" - -# registry { -# server = "index.docker.io" -# username = var.DOCKER_IO_USERNAME -# password_secret_name = "docker-io-password" -# } - -# template { -# min_replicas = 0 -# max_replicas = 2 - -# container { -# name = module.environment.container_app_app_container_name -# image = module.environment.container_app_app_container_image -# cpu = 0.25 -# memory = "0.5Gi" -# } -# } - -# ingress { -# allow_insecure_connections = false -# external_enabled = true -# target_port = 8080 -# transport = "auto" - -# traffic_weight { -# latest_revision = true -# percentage = 100 -# } -# } - -# secret { -# name = "docker-io-password" -# value = var.DOCKER_IO_PASSWORD -# } - -# lifecycle { -# ignore_changes = [ template[0].container[0].image ] -# } -# } - -# resource "azurerm_container_app_custom_domain" "custom_domain" { -# name = trimsuffix(trimprefix(azurerm_dns_txt_record.dns_txt_record.fqdn, "asuid."), ".") -# container_app_id = azurerm_container_app.container_app_app.id - -# lifecycle { -# ignore_changes = [ certificate_binding_type, container_app_environment_certificate_id ] -# } -# } \ No newline at end of file +module "container_app" { + source = "github.com/noahspannbauer/noahspan-terraform/modules/container_app" + app_subdomain_name = var.APP_SUBDOMAIN_NAME + client_id = var.CLIENT_ID + client_secret = var.CLIENT_SECRET + container_app_app_name = module.environment.container_app_app_name + container_app_app_container_image = module.environment.container_app_api_container_image + container_app_app_container_name = module.environment.container_app_api_container_name + container_app_api_name = module.environment.container_app_api_name + container_app_api_container_image = module.environment.container_app_api_container_image + container_app_api_container_name = module.environment.container_app_api_container_name + container_app_environment_name = module.environment.container_app_environment_name + custom_domain_count = module.environment.custom_domain_count + dns_zone_resource_group = var.DNS_ZONE_RESOURCE_GROUP + docker_io_password = var.DOCKER_IO_PASSWORD + docker_io_username = var.DOCKER_IO_USERNAME + domain_name = var.DOMAIN_NAME + log_analytics_workspace_name = module.environment.log_analytics_workspace_name + resource_group_name = var.RESOURCE_GROUP_NAME + storage_account_name = module.environment.storage_account_name + storage_tables = module.environment.storage_tables + tenant_id = var.TENANT_ID +} \ No newline at end of file diff --git a/infrastructure/modules/static_web_app/main.tf b/infrastructure/modules/static_web_app/main.tf deleted file mode 100644 index 54033c2..0000000 --- a/infrastructure/modules/static_web_app/main.tf +++ /dev/null @@ -1,12 +0,0 @@ -# resource "azurerm_static_web_app" "static_web_app" { -# name = var.static_web_app_name -# resource_group_name = var.resource_group_name -# location = var.region -# } - -# resource "azurerm_static_web_app_custom_domain" "static_web_app_custom_domain" { -# count = var.custom_domain_name_count -# static_web_app_id = azurerm_static_web_app.static_web_app.id -# domain_name = "${var.subdomain_name}.${var.domain_name}" -# validation_type = "cname-delegation" -# } \ No newline at end of file diff --git a/infrastructure/modules/static_web_app/outputs.tf b/infrastructure/modules/static_web_app/outputs.tf deleted file mode 100644 index 0754524..0000000 --- a/infrastructure/modules/static_web_app/outputs.tf +++ /dev/null @@ -1,11 +0,0 @@ -# output "id" { -# value = azurerm_static_web_app.static_web_app.id -# } - -# output "api_key" { -# value = azurerm_static_web_app.static_web_app.api_key -# } - -# output "default_host_name" { -# value = azurerm_static_web_app.static_web_app.default_host_name -# } \ No newline at end of file diff --git a/infrastructure/modules/static_web_app/variables.tf b/infrastructure/modules/static_web_app/variables.tf deleted file mode 100644 index a3dc9c9..0000000 --- a/infrastructure/modules/static_web_app/variables.tf +++ /dev/null @@ -1,24 +0,0 @@ -# variable "region" { - -# } - -# variable "resource_group_name" { - -# } - -# variable "static_web_app_name" { - -# } - -# variable "custom_domain_name_count" { - -# } - -# variable "domain_name" { - -# } - -# variable "subdomain_name" { - -# } - diff --git a/infrastructure/outputs.tf b/infrastructure/outputs.tf deleted file mode 100644 index a26f319..0000000 --- a/infrastructure/outputs.tf +++ /dev/null @@ -1,17 +0,0 @@ -# output "api_key" { -# value = azurerm_static_web_app.static_web_app.api_key -# sensitive = true -# } - -# output "default_host_name" { -# value = azurerm_static_web_app.static_web_app.default_host_name -# } - -# output "validation_token" { -# value = azurerm_static_web_app_custom_domain.static_web_app_custom_domain_txt.validation_token -# sensitive = false -# } - -# output "name_servers" { -# value = azurerm_dns_zone.dns_zone.name_servers -# } \ No newline at end of file diff --git a/infrastructure/resource_group.tf b/infrastructure/resource_group.tf deleted file mode 100644 index cbaf81a..0000000 --- a/infrastructure/resource_group.tf +++ /dev/null @@ -1,3 +0,0 @@ -data "azurerm_resource_group" "resource_group" { - name = var.RESOURCE_GROUP_NAME -} \ No newline at end of file diff --git a/infrastructure/storage_account.tf b/infrastructure/storage_account.tf deleted file mode 100644 index b188d1d..0000000 --- a/infrastructure/storage_account.tf +++ /dev/null @@ -1,12 +0,0 @@ -resource "azurerm_storage_account" "storage_account" { - name = module.environment.storage_account_name - resource_group_name = data.azurerm_resource_group.resource_group.name - location = data.azurerm_resource_group.resource_group.location - account_tier = "Standard" - account_replication_type = "LRS" -} - -resource "azurerm_storage_table" "projects_table" { - name = "projects" - storage_account_name = azurerm_storage_account.storage_account.name -} \ No newline at end of file diff --git a/infrastructure/variables.tf b/infrastructure/variables.tf index 76a21dd..4ecbe04 100644 --- a/infrastructure/variables.tf +++ b/infrastructure/variables.tf @@ -1,7 +1,3 @@ -variable "API_SUBDOMAIN_NAME" { - type = string -} - variable "APP_SUBDOMAIN_NAME" { type = string } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa41f01..618a0da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,8 +35,8 @@ importers: specifier: ^3.1.2 version: 3.1.2(@nestjs/common@10.4.15(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.15) '@noahspan/noahspan-modules': - specifier: ^0.5.2 - version: 0.5.9 + specifier: ^0.6.5 + version: 0.6.5 axios: specifier: ^1.7.9 version: 1.7.9 @@ -1441,6 +1441,9 @@ packages: '@noahspan/noahspan-modules@0.5.9': resolution: {integrity: sha512-kkL9P/TNxuPp5T/gd6gTLAmAGi8SJD4MjTWtsrMvw4WWF69x69m2Nr2G6zCv9WLtFrm4NaJhF8I1MVVuNOCinw==} + '@noahspan/noahspan-modules@0.6.5': + resolution: {integrity: sha512-XxmEuaO8v6/u4A5hHZHjyCqY0rrkGqVqqydkZ02Gt0EuErVOo8QuiqEkfEZGLeZNmKZI86IOXWpbXOyn8YGz2g==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -7083,6 +7086,38 @@ snapshots: - stream-browserify - supports-color + '@noahspan/noahspan-modules@0.6.5': + dependencies: + '@azure/app-configuration': 1.8.0 + '@azure/data-tables': 13.3.0 + '@azure/identity': 4.6.0 + '@azure/msal-node': 2.16.2 + '@dapr/dapr': 3.4.1 + '@microsoft/microsoft-graph-client': 3.0.7(@azure/identity@4.6.0) + '@nestjs/common': 10.4.15(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.15)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/passport': 10.0.3(@nestjs/common@10.4.15(reflect-metadata@0.1.14)(rxjs@7.8.1))(passport@0.7.0) + '@nestjs/platform-express': 10.4.15(@nestjs/common@10.4.15(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.15) + axios: 1.7.9 + express-jwt: 8.5.1 + jwks-rsa: 3.1.0 + passport: 0.7.0 + passport-azure-ad: 4.3.5 + passport-jwt: 4.0.1 + reflect-metadata: 0.2.2 + rxjs: 7.8.1 + transitivePeerDependencies: + - '@azure/msal-browser' + - '@nestjs/microservices' + - '@nestjs/websockets' + - buffer + - class-transformer + - class-validator + - debug + - encoding + - stream-browserify + - supports-color + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5