Automated Action 545563e776 Implement comprehensive real-time chat API with NestJS
- Complete NestJS TypeScript implementation with WebSocket support
- Direct messaging (DM) and group chat functionality
- End-to-end encryption with AES encryption and key pairs
- Media file support (images, videos, audio, documents) up to 100MB
- Push notifications with Firebase Cloud Messaging integration
- Mention alerts and real-time typing indicators
- User authentication with JWT and Passport
- SQLite database with TypeORM entities and relationships
- Comprehensive API documentation with Swagger/OpenAPI
- File upload handling with secure access control
- Online/offline status tracking and presence management
- Message editing, deletion, and reply functionality
- Notification management with automatic cleanup
- Health check endpoint for monitoring
- CORS configuration for cross-origin requests
- Environment-based configuration management
- Structured for Flutter SDK integration

Features implemented:
 Real-time messaging with Socket.IO
 User registration and authentication
 Direct messages and group chats
 Media file uploads and management
 End-to-end encryption
 Push notifications
 Mention alerts
 Typing indicators
 Message read receipts
 Online status tracking
 File access control
 Comprehensive API documentation

Ready for Flutter SDK development and production deployment.
2025-06-21 17:13:05 +00:00

145 lines
3.2 KiB
JavaScript

'use strict'
/*
* merge2
* https://github.com/teambition/merge2
*
* Copyright (c) 2014-2020 Teambition
* Licensed under the MIT license.
*/
const Stream = require('stream')
const PassThrough = Stream.PassThrough
const slice = Array.prototype.slice
module.exports = merge2
function merge2 () {
const streamsQueue = []
const args = slice.call(arguments)
let merging = false
let options = args[args.length - 1]
if (options && !Array.isArray(options) && options.pipe == null) {
args.pop()
} else {
options = {}
}
const doEnd = options.end !== false
const doPipeError = options.pipeError === true
if (options.objectMode == null) {
options.objectMode = true
}
if (options.highWaterMark == null) {
options.highWaterMark = 64 * 1024
}
const mergedStream = PassThrough(options)
function addStream () {
for (let i = 0, len = arguments.length; i < len; i++) {
streamsQueue.push(pauseStreams(arguments[i], options))
}
mergeStream()
return this
}
function mergeStream () {
if (merging) {
return
}
merging = true
let streams = streamsQueue.shift()
if (!streams) {
process.nextTick(endStream)
return
}
if (!Array.isArray(streams)) {
streams = [streams]
}
let pipesCount = streams.length + 1
function next () {
if (--pipesCount > 0) {
return
}
merging = false
mergeStream()
}
function pipe (stream) {
function onend () {
stream.removeListener('merge2UnpipeEnd', onend)
stream.removeListener('end', onend)
if (doPipeError) {
stream.removeListener('error', onerror)
}
next()
}
function onerror (err) {
mergedStream.emit('error', err)
}
// skip ended stream
if (stream._readableState.endEmitted) {
return next()
}
stream.on('merge2UnpipeEnd', onend)
stream.on('end', onend)
if (doPipeError) {
stream.on('error', onerror)
}
stream.pipe(mergedStream, { end: false })
// compatible for old stream
stream.resume()
}
for (let i = 0; i < streams.length; i++) {
pipe(streams[i])
}
next()
}
function endStream () {
merging = false
// emit 'queueDrain' when all streams merged.
mergedStream.emit('queueDrain')
if (doEnd) {
mergedStream.end()
}
}
mergedStream.setMaxListeners(0)
mergedStream.add = addStream
mergedStream.on('unpipe', function (stream) {
stream.emit('merge2UnpipeEnd')
})
if (args.length) {
addStream.apply(null, args)
}
return mergedStream
}
// check and pause streams for pipe.
function pauseStreams (streams, options) {
if (!Array.isArray(streams)) {
// Backwards-compat with old-style streams
if (!streams._readableState && streams.pipe) {
streams = streams.pipe(PassThrough(options))
}
if (!streams._readableState || !streams.pause || !streams.pipe) {
throw new Error('Only readable stream can be merged.')
}
streams.pause()
} else {
for (let i = 0, len = streams.length; i < len; i++) {
streams[i] = pauseStreams(streams[i], options)
}
}
return streams
}