diff --git a/apps/api/src/domain/generated/socketIoAttachments/dto/connect-socketIoAttachments.dto.ts b/apps/api/src/domain/generated/socketIoAttachments/dto/connect-socketIoAttachments.dto.ts new file mode 100644 index 000000000..94369f320 --- /dev/null +++ b/apps/api/src/domain/generated/socketIoAttachments/dto/connect-socketIoAttachments.dto.ts @@ -0,0 +1,5 @@ + + export class ConnectSocketIoAttachmentsDto { + id: number; + } + \ No newline at end of file diff --git a/apps/api/src/domain/generated/socketIoAttachments/dto/create-socketIoAttachments.dto.ts b/apps/api/src/domain/generated/socketIoAttachments/dto/create-socketIoAttachments.dto.ts new file mode 100644 index 000000000..54365eb6b --- /dev/null +++ b/apps/api/src/domain/generated/socketIoAttachments/dto/create-socketIoAttachments.dto.ts @@ -0,0 +1,9 @@ + + + + + + +export class CreateSocketIoAttachmentsDto { + payload: Buffer; +} diff --git a/apps/api/src/domain/generated/socketIoAttachments/dto/index.ts b/apps/api/src/domain/generated/socketIoAttachments/dto/index.ts new file mode 100644 index 000000000..18fa99d69 --- /dev/null +++ b/apps/api/src/domain/generated/socketIoAttachments/dto/index.ts @@ -0,0 +1,4 @@ + +export * from './connect-socketIoAttachments.dto'; +export * from './create-socketIoAttachments.dto'; +export * from './update-socketIoAttachments.dto'; \ No newline at end of file diff --git a/apps/api/src/domain/generated/socketIoAttachments/dto/update-socketIoAttachments.dto.ts b/apps/api/src/domain/generated/socketIoAttachments/dto/update-socketIoAttachments.dto.ts new file mode 100644 index 000000000..b7fb021a9 --- /dev/null +++ b/apps/api/src/domain/generated/socketIoAttachments/dto/update-socketIoAttachments.dto.ts @@ -0,0 +1,9 @@ + + + + + + +export class UpdateSocketIoAttachmentsDto { + payload?: Buffer; +} diff --git a/apps/api/src/domain/generated/socketIoAttachments/entities/index.ts b/apps/api/src/domain/generated/socketIoAttachments/entities/index.ts new file mode 100644 index 000000000..17624815f --- /dev/null +++ b/apps/api/src/domain/generated/socketIoAttachments/entities/index.ts @@ -0,0 +1,2 @@ + +export * from './socketIoAttachments.entity'; \ No newline at end of file diff --git a/apps/api/src/domain/generated/socketIoAttachments/entities/socketIoAttachments.entity.ts b/apps/api/src/domain/generated/socketIoAttachments/entities/socketIoAttachments.entity.ts new file mode 100644 index 000000000..941f8ab4a --- /dev/null +++ b/apps/api/src/domain/generated/socketIoAttachments/entities/socketIoAttachments.entity.ts @@ -0,0 +1,9 @@ + + + + +export class SocketIoAttachments { + id: number ; +createdAt: Date ; +payload: Buffer ; +} diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index 61f5d4635..da170db9e 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -8,6 +8,7 @@ import { setupSwagger } from './config/swagger.config' import { setupExceptions } from './config/exceptions.config' import { setupValidation } from './config/validation.config' import { setupShutdownHooks } from './config/shutdown.config' +import { PostgresIoAdapter } from './sockets/notifications/adapter' const globalPrefix = process.env.GLOBAL_PREFIX ?? 'api/v1' const logLevels: LogLevel[] = ['error', 'warn'] @@ -27,6 +28,10 @@ async function bootstrap() { app.setGlobalPrefix(globalPrefix) app.enableVersioning({ type: VersioningType.URI }) + const postgresIoAdapter = new PostgresIoAdapter(app) + await postgresIoAdapter.connectToPostgres() + app.useWebSocketAdapter(postgresIoAdapter) + const appVersion = process.env.APP_VERSION || 'unknown' setupHelmet(app) setupCors(app) diff --git a/apps/api/src/sockets/notifications/adapter.ts b/apps/api/src/sockets/notifications/adapter.ts new file mode 100644 index 000000000..5c674b898 --- /dev/null +++ b/apps/api/src/sockets/notifications/adapter.ts @@ -0,0 +1,29 @@ +import { Logger } from '@nestjs/common' +import { IoAdapter } from '@nestjs/platform-socket.io' +import { createAdapter } from '@socket.io/postgres-adapter' +import { Pool } from 'pg' +import { ServerOptions } from 'socket.io' + +const { DB_PORT, DB_USER, DB_PASS, DB_HOST } = process.env + +export class PostgresIoAdapter extends IoAdapter { + private adapterConstructor: ReturnType + + async connectToPostgres(): Promise { + const pool = new Pool({ + user: DB_USER, + host: DB_HOST, + database: 'postgres', + password: DB_PASS, + port: Number(DB_PORT) || 5432, + }) + + this.adapterConstructor = createAdapter(pool) + } + + createIOServer(port: number, options?: ServerOptions): any { + const server = super.createIOServer(port, options) + server.adapter(this.adapterConstructor) + return server + } +} diff --git a/apps/api/src/sockets/notifications/gateway.ts b/apps/api/src/sockets/notifications/gateway.ts index dea85aa18..0af140b66 100644 --- a/apps/api/src/sockets/notifications/gateway.ts +++ b/apps/api/src/sockets/notifications/gateway.ts @@ -6,13 +6,14 @@ import { WebSocketServer, } from '@nestjs/websockets' import { Logger } from '@nestjs/common' +import { Server } from 'socket.io' @WebSocketGateway({ namespace: '/api/v1', transport: 'websocket' }) export class NotificationGateway implements OnGatewayConnection, OnGatewayInit, OnGatewayDisconnect { constructor() {} - @WebSocketServer() server + @WebSocketServer() server: Server afterInit() { Logger.log('Websocket server initiated and ready to receive connections') diff --git a/migrations/20230313144628_add_socket_io_attachments_table/migration.sql b/migrations/20230313144628_add_socket_io_attachments_table/migration.sql new file mode 100644 index 000000000..7318e13c4 --- /dev/null +++ b/migrations/20230313144628_add_socket_io_attachments_table/migration.sql @@ -0,0 +1,8 @@ +-- CreateTable +CREATE TABLE "socket-io-attachments" ( + "id" SERIAL NOT NULL, + "created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "payload" BYTEA NOT NULL, + + CONSTRAINT "socket-io-attachments_pkey" PRIMARY KEY ("id") +); diff --git a/package.json b/package.json index 9b224cb13..414876618 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,9 @@ "@sendgrid/client": "7.6.2", "@sendgrid/mail": "7.6.0", "@sentry/node": "^7.46.0", + "@socket.io/postgres-adapter": "^0.3.1", + "@socket.io/postgres-emitter": "^0.1.0", + "@types/pg": "^8.6.6", "@types/cron": "^2.0.0", "aws-sdk": "2.1199.0", "class-transformer": "0.5.1", @@ -60,6 +63,7 @@ "nest-keycloak-connect": "^1.9.1", "reflect-metadata": "0.1.13", "rxjs": "7.5.5", + "socket.io": "latest", "stripe": "11.14.0", "swagger-ui-express": "4.5.0", "tslib": "2.4.0" @@ -99,6 +103,7 @@ "prettier": "2.6.0", "prisma": "4.9.0", "prisma-dbml-generator": "^0.10.0", + "socket.io-client": "^4.6.0", "supertest": "^6.3.3", "ts-jest": "^29.0.5", "ts-node": "^10.9.1", diff --git a/podkrepi.dbml b/podkrepi.dbml index 20ad18de8..57a4e8d2f 100644 --- a/podkrepi.dbml +++ b/podkrepi.dbml @@ -473,6 +473,12 @@ Table bank_transactions_files { personId String [not null] } +Table SocketIoAttachments { + id Int [pk, increment] + createdAt DateTime [default: `now()`, not null] + payload Bytes [not null] +} + Enum BeneficiaryType { individual company diff --git a/schema.prisma b/schema.prisma index a08810a66..79b92a858 100644 --- a/schema.prisma +++ b/schema.prisma @@ -1,6 +1,6 @@ generator client { - provider = "prisma-client-js" - binaryTargets = ["native"] + provider = "prisma-client-js" + binaryTargets = ["native"] previewFeatures = ["orderByNulls"] } @@ -573,6 +573,12 @@ model BankTransactionsFile { @@map("bank_transactions_files") } +model SocketIoAttachments { + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6) + payload Bytes +} + enum BeneficiaryType { individual company diff --git a/yarn.lock b/yarn.lock index 61fa942e3..ff87b0db7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2224,6 +2224,13 @@ __metadata: languageName: node linkType: hard +"@msgpack/msgpack@npm:^2.7.0, @msgpack/msgpack@npm:~2.8.0": + version: 2.8.0 + resolution: "@msgpack/msgpack@npm:2.8.0" + checksum: bead9393f57239007a2fe455df5277cbc03b125f14f310162a652b81471dcf3ab6780eaa24b36e20aa742998910a6840147d08b7267063b8e2de5d40c624360e + languageName: node + linkType: hard + "@nestjs/axios@npm:^2.0.0": version: 2.0.0 resolution: "@nestjs/axios@npm:2.0.0" @@ -3544,6 +3551,30 @@ __metadata: languageName: node linkType: hard +"@socket.io/postgres-adapter@npm:^0.3.1": + version: 0.3.1 + resolution: "@socket.io/postgres-adapter@npm:0.3.1" + dependencies: + "@msgpack/msgpack": ~2.8.0 + "@types/pg": ^8.6.6 + debug: ~4.3.4 + pg: ^8.9.0 + peerDependencies: + socket.io-adapter: ^2.4.0 + checksum: 90506fd017f8482c918e62de5818655c219ef5d5f8adc4f82748a4b3b391d5f4f9af1fcd6e1f08b9073cdb5b46c9472c0aa8887ddd359a55854f14ced4bfe4b1 + languageName: node + linkType: hard + +"@socket.io/postgres-emitter@npm:^0.1.0": + version: 0.1.0 + resolution: "@socket.io/postgres-emitter@npm:0.1.0" + dependencies: + "@msgpack/msgpack": ^2.7.0 + debug: ~4.3.1 + checksum: fdfec5a986b640e3cdc7dbc95cf0d4a493f1fd219dd08bb8ceb46e9b0d5e94d430db62ff6ab21e34630a6f95a075f257057a6872b94ef643548fc8aa22404978 + languageName: node + linkType: hard + "@testim/chrome-version@npm:^1.1.3": version: 1.1.3 resolution: "@testim/chrome-version@npm:1.1.3" @@ -3963,6 +3994,17 @@ __metadata: languageName: node linkType: hard +"@types/pg@npm:^8.6.6": + version: 8.6.6 + resolution: "@types/pg@npm:8.6.6" + dependencies: + "@types/node": "*" + pg-protocol: "*" + pg-types: ^2.2.0 + checksum: ac145553a8ad2f357feacad1bceaf5d6ce904eb9d66233b84c469a2b4fa3738d4ebdf29b7ea45387be2d07f915fd873a229f90a2f766d7c377afa7c41fbcf8d1 + languageName: node + linkType: hard + "@types/prettier@npm:^2.1.5": version: 2.7.2 resolution: "@types/prettier@npm:2.7.2" @@ -5332,6 +5374,13 @@ __metadata: languageName: node linkType: hard +"buffer-writer@npm:2.0.0": + version: 2.0.0 + resolution: "buffer-writer@npm:2.0.0" + checksum: 11736b48bb75106c52ca8ec9f025e7c1b3b25ce31875f469d7210eabd5c576c329e34f6b805d4a8d605ff3f0db1e16342328802c4c963e9c826b0e43a4e631c2 + languageName: node + linkType: hard + "buffer@npm:4.9.2": version: 4.9.2 resolution: "buffer@npm:4.9.2" @@ -6409,7 +6458,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:~4.3.1, debug@npm:~4.3.2": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:~4.3.1, debug@npm:~4.3.2, debug@npm:~4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -6879,6 +6928,19 @@ __metadata: languageName: node linkType: hard +"engine.io-client@npm:~6.4.0": + version: 6.4.0 + resolution: "engine.io-client@npm:6.4.0" + dependencies: + "@socket.io/component-emitter": ~3.1.0 + debug: ~4.3.1 + engine.io-parser: ~5.0.3 + ws: ~8.11.0 + xmlhttprequest-ssl: ~2.0.0 + checksum: f412a5d490d073bc6b1240002ea9d46c4813bfb7ad98edd54db3760d75cac1d7f73c2f802a7ce04827c1e304fa26f4d464785efdb003d6231cadedca649a7146 + languageName: node + linkType: hard + "engine.io-parser@npm:~5.0.3": version: 5.0.6 resolution: "engine.io-parser@npm:5.0.6" @@ -11931,6 +11993,13 @@ __metadata: languageName: node linkType: hard +"packet-reader@npm:1.0.0": + version: 1.0.0 + resolution: "packet-reader@npm:1.0.0" + checksum: 0b7516f0cbf3e322aad591bed29ba544220088c53943145c0d9121a6f59182ad811f7fd6785a8979a34356aca69d97653689029964c5998dc02645633d88ffd7 + languageName: node + linkType: hard + "pako@npm:~1.0.2": version: 1.0.11 resolution: "pako@npm:1.0.11" @@ -12090,6 +12159,78 @@ __metadata: languageName: node linkType: hard +"pg-connection-string@npm:^2.5.0": + version: 2.5.0 + resolution: "pg-connection-string@npm:2.5.0" + checksum: a6f3a068f7c9416a5b33a326811caf0dfaaee045c225b7c628b4c9b4e9a2b25bdd12a21e4c48940e1000ea223a4e608ca122d2ff3dd08c8b1db0fc9f5705133a + languageName: node + linkType: hard + +"pg-int8@npm:1.0.1": + version: 1.0.1 + resolution: "pg-int8@npm:1.0.1" + checksum: a1e3a05a69005ddb73e5f324b6b4e689868a447c5fa280b44cd4d04e6916a344ac289e0b8d2695d66e8e89a7fba023affb9e0e94778770ada5df43f003d664c9 + languageName: node + linkType: hard + +"pg-pool@npm:^3.5.2": + version: 3.5.2 + resolution: "pg-pool@npm:3.5.2" + peerDependencies: + pg: ">=8.0" + checksum: a5d029200257671f0c17ca54b9ab6213e2060e64e5cc792b78edd50ab471a26cd364890d05d546d9296949e079e943821cf2ceb4d488f4e6a6789fb781a628bf + languageName: node + linkType: hard + +"pg-protocol@npm:*, pg-protocol@npm:^1.6.0": + version: 1.6.0 + resolution: "pg-protocol@npm:1.6.0" + checksum: e12662d2de2011e0c3a03f6a09f435beb1025acdc860f181f18a600a5495dc38a69d753bbde1ace279c8c442536af9c1a7c11e1d0fe3fad3aa1348b28d9d2683 + languageName: node + linkType: hard + +"pg-types@npm:^2.1.0, pg-types@npm:^2.2.0": + version: 2.2.0 + resolution: "pg-types@npm:2.2.0" + dependencies: + pg-int8: 1.0.1 + postgres-array: ~2.0.0 + postgres-bytea: ~1.0.0 + postgres-date: ~1.0.4 + postgres-interval: ^1.1.0 + checksum: bf4ec3f594743442857fb3a8dfe5d2478a04c98f96a0a47365014557cbc0b4b0cee01462c79adca863b93befbf88f876299b75b72c665b5fb84a2c94fbd10316 + languageName: node + linkType: hard + +"pg@npm:^8.9.0": + version: 8.9.0 + resolution: "pg@npm:8.9.0" + dependencies: + buffer-writer: 2.0.0 + packet-reader: 1.0.0 + pg-connection-string: ^2.5.0 + pg-pool: ^3.5.2 + pg-protocol: ^1.6.0 + pg-types: ^2.1.0 + pgpass: 1.x + peerDependencies: + pg-native: ">=3.0.1" + peerDependenciesMeta: + pg-native: + optional: true + checksum: dfd158955318f9ffb9428eaada29f3ee98b9eb07e87ed4b56589a19984d109f23bb8f88db78b7d7f870553e5b75ca0d58d0ed55755a8c6aed5df44e038c1d529 + languageName: node + linkType: hard + +"pgpass@npm:1.x": + version: 1.0.5 + resolution: "pgpass@npm:1.0.5" + dependencies: + split2: ^4.1.0 + checksum: 947ac096c031eebdf08d989de2e9f6f156b8133d6858c7c2c06c041e1e71dda6f5f3bad3c0ec1e96a09497bbc6ef89e762eefe703b5ef9cb2804392ec52ec400 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" @@ -12185,6 +12326,8 @@ __metadata: "@sendgrid/client": 7.6.2 "@sendgrid/mail": 7.6.0 "@sentry/node": ^7.46.0 + "@socket.io/postgres-adapter": ^0.3.1 + "@socket.io/postgres-emitter": ^0.1.0 "@types/cron": ^2.0.0 "@types/express": 4.17.13 "@types/faker": 5.5.9 @@ -12193,6 +12336,7 @@ __metadata: "@types/mjml": 4.7.0 "@types/multer": 1.4.7 "@types/node": 16.9.1 + "@types/pg": ^8.6.6 "@typescript-eslint/eslint-plugin": ^5.48.1 "@typescript-eslint/parser": ^5.48.1 "@vegardit/prisma-generator-nestjs-dto": 1.5.1 @@ -12223,6 +12367,8 @@ __metadata: prisma-dbml-generator: ^0.10.0 reflect-metadata: 0.1.13 rxjs: 7.5.5 + socket.io: latest + socket.io-client: ^4.6.0 stripe: 11.14.0 supertest: ^6.3.3 swagger-ui-express: 4.5.0 @@ -12637,6 +12783,36 @@ __metadata: languageName: node linkType: hard +"postgres-array@npm:~2.0.0": + version: 2.0.0 + resolution: "postgres-array@npm:2.0.0" + checksum: 0e1e659888147c5de579d229a2d95c0d83ebdbffc2b9396d890a123557708c3b758a0a97ed305ce7f58edfa961fa9f0bbcd1ea9f08b6e5df73322e683883c464 + languageName: node + linkType: hard + +"postgres-bytea@npm:~1.0.0": + version: 1.0.0 + resolution: "postgres-bytea@npm:1.0.0" + checksum: d844ae4ca7a941b70e45cac1261a73ee8ed39d72d3d74ab1d645248185a1b7f0ac91a3c63d6159441020f4e1f7fe64689ac56536a307b31cef361e5187335090 + languageName: node + linkType: hard + +"postgres-date@npm:~1.0.4": + version: 1.0.7 + resolution: "postgres-date@npm:1.0.7" + checksum: 5745001d47e51cd767e46bcb1710649cd705d91a24d42fa661c454b6dcbb7353c066a5047983c90a626cd3bbfea9e626cc6fa84a35ec57e5bbb28b49f78e13ed + languageName: node + linkType: hard + +"postgres-interval@npm:^1.1.0": + version: 1.2.0 + resolution: "postgres-interval@npm:1.2.0" + dependencies: + xtend: ^4.0.0 + checksum: 746b71f93805ae33b03528e429dc624706d1f9b20ee81bf743263efb6a0cd79ae02a642a8a480dbc0f09547b4315ab7df6ce5ec0be77ed700bac42730f5c76b2 + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -13689,6 +13865,18 @@ __metadata: languageName: node linkType: hard +"socket.io-client@npm:^4.6.0": + version: 4.6.0 + resolution: "socket.io-client@npm:4.6.0" + dependencies: + "@socket.io/component-emitter": ~3.1.0 + debug: ~4.3.2 + engine.io-client: ~6.4.0 + socket.io-parser: ~4.2.1 + checksum: c0443a0e59e0d3f1953f8a3b1fdb7e4408edee8449f26e657d5e4df13c15a9c18df00c657e5641f5699f922a76b74a61f4b6f087b9ced0be72ae6e4dd34631e1 + languageName: node + linkType: hard + "socket.io-parser@npm:~4.2.1": version: 4.2.2 resolution: "socket.io-parser@npm:4.2.2" @@ -13699,7 +13887,7 @@ __metadata: languageName: node linkType: hard -"socket.io@npm:4.6.1": +"socket.io@npm:4.6.1, socket.io@npm:latest": version: 4.6.1 resolution: "socket.io@npm:4.6.1" dependencies: @@ -13894,6 +14082,13 @@ __metadata: languageName: node linkType: hard +"split2@npm:^4.1.0": + version: 4.1.0 + resolution: "split2@npm:4.1.0" + checksum: ec581597cb74c13cdfb5e2047543dd40cb1e8e9803c7b1e0c29ede05f2b4f049b2d6e7f2788a225d544549375719658b8f38e9366364dec35dc7a12edfda5ee5 + languageName: node + linkType: hard + "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -15526,6 +15721,13 @@ __metadata: languageName: node linkType: hard +"xmlhttprequest-ssl@npm:~2.0.0": + version: 2.0.0 + resolution: "xmlhttprequest-ssl@npm:2.0.0" + checksum: 1e98df67f004fec15754392a131343ea92e6ab5ac4d77e842378c5c4e4fd5b6a9134b169d96842cc19422d77b1606b8df84a5685562b3b698cb68441636f827e + languageName: node + linkType: hard + "xtend@npm:^4.0.0": version: 4.0.2 resolution: "xtend@npm:4.0.2"