UNPKG

@tigthor/kokocrypt

Version:

Enhanced Fortress Edition - Secure, quantum-resistant, high-performance encryption package

227 lines 10.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var KafkaService_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.KafkaService = void 0; const common_1 = require("@nestjs/common"); const microservices_1 = require("@nestjs/microservices"); const crypto_service_1 = require("../core/crypto.service"); const rxjs_1 = require("rxjs"); const sodiumNative = __importStar(require("sodium-native")); let KafkaService = KafkaService_1 = class KafkaService { logError(message, error) { if (this.isTestEnv) { this.logger.debug(message, error); return; } this.logger.error(message, error); } constructor(cryptoService, client) { this.cryptoService = cryptoService; this.client = client; this.logger = new common_1.Logger(KafkaService_1.name); this.topics = [ 'test.topic', 'test.batch', 'test.errors', 'test.performance', ]; this.isTestEnv = process.env.NODE_ENV === 'test' || !!process.env.JEST_WORKER_ID; } async onModuleInit() { try { await this.client.connect(); this.logger.log('✓ Connected to Kafka'); for (const topic of this.topics) { this.client.subscribeToResponseOf(topic); } this.logger.log(`✓ Subscribed to response topics: ${this.topics.join(', ')}`); } catch (error) { this.logError('❌ Failed to initialize Kafka service:', error); throw new common_1.ServiceUnavailableException('Failed to connect to Kafka service'); } } async onModuleDestroy() { try { await this.client.close(); this.logger.log('✓ Disconnected from Kafka'); } catch (error) { this.logError('❌ Error disconnecting from Kafka:', error); } } async sendMessage(topic, message, key) { var _a, _b; try { if (key.length !== sodiumNative.crypto_secretbox_KEYBYTES) { throw new common_1.BadRequestException(`Invalid key length. Expected ${sodiumNative.crypto_secretbox_KEYBYTES} bytes`); } this.logger.debug(`📤 Sending message to ${topic}`); if (!message || typeof message !== 'object') { throw new common_1.BadRequestException('Invalid message format'); } const encryptedMessage = await this.cryptoService.boxRaw(Buffer.from(JSON.stringify(message)), key); const response = (await (0, rxjs_1.firstValueFrom)(this.client.send(topic, { value: encryptedMessage.toString('base64'), timestamp: Date.now().toString(), }))); this.logger.debug(`✓ Message sent to topic ${topic}`); return response; } catch (err) { const error = err; this.logError(`❌ Error sending message to ${topic}:`, error); if (error instanceof common_1.BadRequestException) { throw error; } if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('ECONNREFUSED')) { throw new common_1.ServiceUnavailableException('Kafka service is not available'); } if ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('decryption failed')) { throw new common_1.BadRequestException('Message encryption failed'); } throw error; } } async sendBatch(topic, messages, key) { var _a; try { if (key.length !== sodiumNative.crypto_secretbox_KEYBYTES) { throw new common_1.BadRequestException(`Invalid key length. Expected ${sodiumNative.crypto_secretbox_KEYBYTES} bytes`); } if (!Array.isArray(messages) || messages.length === 0) { throw new common_1.BadRequestException('Invalid batch message format'); } this.logger.debug(`📤 Sending batch of ${messages.length} messages to ${topic}`); const encryptedMessages = await Promise.all(messages.map(async (message) => { if (!message || typeof message !== 'object') { throw new common_1.BadRequestException('Invalid message in batch'); } const encrypted = await this.cryptoService.boxRaw(Buffer.from(JSON.stringify(message)), key); return { value: encrypted.toString('base64'), timestamp: Date.now().toString(), }; })); const responses = (await Promise.all(encryptedMessages.map(msg => (0, rxjs_1.firstValueFrom)(this.client.send(topic, msg))))); this.logger.debug(`✓ Batch sent to topic ${topic}`); return responses; } catch (err) { const error = err; this.logError(`❌ Error sending batch to ${topic}:`, error); if (error instanceof common_1.BadRequestException) { throw error; } if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('ECONNREFUSED')) { throw new common_1.ServiceUnavailableException('Kafka service is not available'); } throw error; } } async sendInvalidMessage() { try { this.logger.debug('📤 Sending invalid message for error testing'); const response = (await (0, rxjs_1.firstValueFrom)(this.client.send('test.errors', { value: 'invalid_data', timestamp: Date.now().toString(), }))); return response; } catch (error) { this.logError('❌ Expected error sending invalid message:', error); throw error; } } async runPerformanceTest(messageCount, key) { var _a; try { if (key.length !== sodiumNative.crypto_secretbox_KEYBYTES) { throw new common_1.BadRequestException(`Invalid key length. Expected ${sodiumNative.crypto_secretbox_KEYBYTES} bytes`); } if (!Number.isInteger(messageCount) || messageCount <= 0) { throw new common_1.BadRequestException('Invalid message count'); } this.logger.debug(`📊 Running performance test with ${messageCount} messages`); const startTime = Date.now(); const messages = Array.from({ length: messageCount }, (_, i) => ({ id: i, data: `Performance test message ${i}`, timestamp: Date.now(), })); const responses = (await Promise.all(messages.map(message => this.sendMessage('test.performance', message, key)))); const endTime = Date.now(); const duration = (endTime - startTime) / 1000; const messagesPerSecond = messageCount / duration; this.logger.debug(`✓ Performance test completed: - Messages sent: ${messageCount} - Duration: ${duration.toFixed(2)} seconds - Rate: ${messagesPerSecond.toFixed(2)} messages/second`); return responses; } catch (err) { const error = err; this.logError('❌ Error in performance test:', error); if (error instanceof common_1.BadRequestException) { throw error; } if ((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('ECONNREFUSED')) { throw new common_1.ServiceUnavailableException('Kafka service is not available'); } throw error; } } }; exports.KafkaService = KafkaService; exports.KafkaService = KafkaService = KafkaService_1 = __decorate([ (0, common_1.Injectable)(), __param(1, (0, common_1.Inject)('KAFKA_CLIENT')), __metadata("design:paramtypes", [crypto_service_1.CryptoService, microservices_1.ClientKafka]) ], KafkaService); //# sourceMappingURL=kafka.service.js.map