cadenlane-cli-2 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/LICENSE +21 -0
- package/README.md +333 -0
- package/bin.js +2 -0
- package/dist/application/config/config.manager.d.ts +62 -0
- package/dist/application/config/config.manager.d.ts.map +1 -0
- package/dist/application/config/config.manager.js +146 -0
- package/dist/application/config/config.manager.js.map +1 -0
- package/dist/application/services/application.service.d.ts +35 -0
- package/dist/application/services/application.service.d.ts.map +1 -0
- package/dist/application/services/application.service.js +174 -0
- package/dist/application/services/application.service.js.map +1 -0
- package/dist/application/services/download.service.d.ts +27 -0
- package/dist/application/services/download.service.d.ts.map +1 -0
- package/dist/application/services/download.service.js +197 -0
- package/dist/application/services/download.service.js.map +1 -0
- package/dist/application/services/file-naming.service.d.ts +34 -0
- package/dist/application/services/file-naming.service.d.ts.map +1 -0
- package/dist/application/services/file-naming.service.js +142 -0
- package/dist/application/services/file-naming.service.js.map +1 -0
- package/dist/application/services/queue.service.d.ts +53 -0
- package/dist/application/services/queue.service.d.ts.map +1 -0
- package/dist/application/services/queue.service.js +82 -0
- package/dist/application/services/queue.service.js.map +1 -0
- package/dist/cli/commands/start.command.d.ts +39 -0
- package/dist/cli/commands/start.command.d.ts.map +1 -0
- package/dist/cli/commands/start.command.js +196 -0
- package/dist/cli/commands/start.command.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +86 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/domain/constants/config.constants.d.ts +54 -0
- package/dist/domain/constants/config.constants.d.ts.map +1 -0
- package/dist/domain/constants/config.constants.js +142 -0
- package/dist/domain/constants/config.constants.js.map +1 -0
- package/dist/domain/dtos/index.d.ts +4 -0
- package/dist/domain/dtos/index.d.ts.map +1 -0
- package/dist/domain/dtos/index.js +10 -0
- package/dist/domain/dtos/index.js.map +1 -0
- package/dist/domain/dtos/log-entry.dto.d.ts +15 -0
- package/dist/domain/dtos/log-entry.dto.d.ts.map +1 -0
- package/dist/domain/dtos/log-entry.dto.js +64 -0
- package/dist/domain/dtos/log-entry.dto.js.map +1 -0
- package/dist/domain/dtos/message.dto.d.ts +27 -0
- package/dist/domain/dtos/message.dto.d.ts.map +1 -0
- package/dist/domain/dtos/message.dto.js +140 -0
- package/dist/domain/dtos/message.dto.js.map +1 -0
- package/dist/domain/dtos/queue-message.dto.d.ts +10 -0
- package/dist/domain/dtos/queue-message.dto.d.ts.map +1 -0
- package/dist/domain/dtos/queue-message.dto.js +39 -0
- package/dist/domain/dtos/queue-message.dto.js.map +1 -0
- package/dist/domain/entities/cli-instance.entity.d.ts +55 -0
- package/dist/domain/entities/cli-instance.entity.d.ts.map +1 -0
- package/dist/domain/entities/cli-instance.entity.js +132 -0
- package/dist/domain/entities/cli-instance.entity.js.map +1 -0
- package/dist/domain/entities/index.d.ts +3 -0
- package/dist/domain/entities/index.d.ts.map +1 -0
- package/dist/domain/entities/index.js +8 -0
- package/dist/domain/entities/index.js.map +1 -0
- package/dist/domain/entities/log-entry.entity.d.ts +60 -0
- package/dist/domain/entities/log-entry.entity.d.ts.map +1 -0
- package/dist/domain/entities/log-entry.entity.js +101 -0
- package/dist/domain/entities/log-entry.entity.js.map +1 -0
- package/dist/domain/entities/message.entity.d.ts +64 -0
- package/dist/domain/entities/message.entity.d.ts.map +1 -0
- package/dist/domain/entities/message.entity.js +110 -0
- package/dist/domain/entities/message.entity.js.map +1 -0
- package/dist/domain/enums/error-category.enum.d.ts +11 -0
- package/dist/domain/enums/error-category.enum.d.ts.map +1 -0
- package/dist/domain/enums/error-category.enum.js +15 -0
- package/dist/domain/enums/error-category.enum.js.map +1 -0
- package/dist/domain/enums/index.d.ts +4 -0
- package/dist/domain/enums/index.d.ts.map +1 -0
- package/dist/domain/enums/index.js +10 -0
- package/dist/domain/enums/index.js.map +1 -0
- package/dist/domain/enums/log-level.enum.d.ts +11 -0
- package/dist/domain/enums/log-level.enum.d.ts.map +1 -0
- package/dist/domain/enums/log-level.enum.js +15 -0
- package/dist/domain/enums/log-level.enum.js.map +1 -0
- package/dist/domain/enums/message-status.enum.d.ts +11 -0
- package/dist/domain/enums/message-status.enum.d.ts.map +1 -0
- package/dist/domain/enums/message-status.enum.js +15 -0
- package/dist/domain/enums/message-status.enum.js.map +1 -0
- package/dist/domain/interfaces/adapters/ifilesystem.adapter.d.ts +34 -0
- package/dist/domain/interfaces/adapters/ifilesystem.adapter.d.ts.map +1 -0
- package/dist/domain/interfaces/adapters/ifilesystem.adapter.js +3 -0
- package/dist/domain/interfaces/adapters/ifilesystem.adapter.js.map +1 -0
- package/dist/domain/interfaces/adapters/ihttp.adapter.d.ts +22 -0
- package/dist/domain/interfaces/adapters/ihttp.adapter.d.ts.map +1 -0
- package/dist/domain/interfaces/adapters/ihttp.adapter.js +3 -0
- package/dist/domain/interfaces/adapters/ihttp.adapter.js.map +1 -0
- package/dist/domain/interfaces/adapters/index.d.ts +4 -0
- package/dist/domain/interfaces/adapters/index.d.ts.map +1 -0
- package/dist/domain/interfaces/adapters/index.js +3 -0
- package/dist/domain/interfaces/adapters/index.js.map +1 -0
- package/dist/domain/interfaces/adapters/isupabase.adapter.d.ts +27 -0
- package/dist/domain/interfaces/adapters/isupabase.adapter.d.ts.map +1 -0
- package/dist/domain/interfaces/adapters/isupabase.adapter.js +3 -0
- package/dist/domain/interfaces/adapters/isupabase.adapter.js.map +1 -0
- package/dist/domain/interfaces/repositories/ilog.repository.d.ts +32 -0
- package/dist/domain/interfaces/repositories/ilog.repository.d.ts.map +1 -0
- package/dist/domain/interfaces/repositories/ilog.repository.js +3 -0
- package/dist/domain/interfaces/repositories/ilog.repository.js.map +1 -0
- package/dist/domain/interfaces/repositories/imessage.repository.d.ts +39 -0
- package/dist/domain/interfaces/repositories/imessage.repository.d.ts.map +1 -0
- package/dist/domain/interfaces/repositories/imessage.repository.js +3 -0
- package/dist/domain/interfaces/repositories/imessage.repository.js.map +1 -0
- package/dist/domain/interfaces/repositories/index.d.ts +4 -0
- package/dist/domain/interfaces/repositories/index.d.ts.map +1 -0
- package/dist/domain/interfaces/repositories/index.js +3 -0
- package/dist/domain/interfaces/repositories/index.js.map +1 -0
- package/dist/domain/interfaces/repositories/iqueue.repository.d.ts +75 -0
- package/dist/domain/interfaces/repositories/iqueue.repository.d.ts.map +1 -0
- package/dist/domain/interfaces/repositories/iqueue.repository.js +3 -0
- package/dist/domain/interfaces/repositories/iqueue.repository.js.map +1 -0
- package/dist/domain/interfaces/services/idownload.service.d.ts +28 -0
- package/dist/domain/interfaces/services/idownload.service.d.ts.map +1 -0
- package/dist/domain/interfaces/services/idownload.service.js +3 -0
- package/dist/domain/interfaces/services/idownload.service.js.map +1 -0
- package/dist/domain/interfaces/services/iqueue.service.d.ts +35 -0
- package/dist/domain/interfaces/services/iqueue.service.d.ts.map +1 -0
- package/dist/domain/interfaces/services/iqueue.service.js +3 -0
- package/dist/domain/interfaces/services/iqueue.service.js.map +1 -0
- package/dist/domain/services/path-resolver.service.d.ts +94 -0
- package/dist/domain/services/path-resolver.service.d.ts.map +1 -0
- package/dist/domain/services/path-resolver.service.js +332 -0
- package/dist/domain/services/path-resolver.service.js.map +1 -0
- package/dist/domain/validators/index.d.ts +4 -0
- package/dist/domain/validators/index.d.ts.map +1 -0
- package/dist/domain/validators/index.js +10 -0
- package/dist/domain/validators/index.js.map +1 -0
- package/dist/domain/validators/message.validator.d.ts +20 -0
- package/dist/domain/validators/message.validator.d.ts.map +1 -0
- package/dist/domain/validators/message.validator.js +31 -0
- package/dist/domain/validators/message.validator.js.map +1 -0
- package/dist/domain/validators/path.validator.d.ts +44 -0
- package/dist/domain/validators/path.validator.d.ts.map +1 -0
- package/dist/domain/validators/path.validator.js +156 -0
- package/dist/domain/validators/path.validator.js.map +1 -0
- package/dist/domain/validators/url.validator.d.ts +19 -0
- package/dist/domain/validators/url.validator.d.ts.map +1 -0
- package/dist/domain/validators/url.validator.js +46 -0
- package/dist/domain/validators/url.validator.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/adapters/filesystem.adapter.d.ts +35 -0
- package/dist/infrastructure/adapters/filesystem.adapter.d.ts.map +1 -0
- package/dist/infrastructure/adapters/filesystem.adapter.js +103 -0
- package/dist/infrastructure/adapters/filesystem.adapter.js.map +1 -0
- package/dist/infrastructure/adapters/http.adapter.d.ts +15 -0
- package/dist/infrastructure/adapters/http.adapter.d.ts.map +1 -0
- package/dist/infrastructure/adapters/http.adapter.js +80 -0
- package/dist/infrastructure/adapters/http.adapter.js.map +1 -0
- package/dist/infrastructure/adapters/index.d.ts +4 -0
- package/dist/infrastructure/adapters/index.d.ts.map +1 -0
- package/dist/infrastructure/adapters/index.js +10 -0
- package/dist/infrastructure/adapters/index.js.map +1 -0
- package/dist/infrastructure/adapters/pgmq.adapter.d.ts +29 -0
- package/dist/infrastructure/adapters/pgmq.adapter.d.ts.map +1 -0
- package/dist/infrastructure/adapters/pgmq.adapter.js +84 -0
- package/dist/infrastructure/adapters/pgmq.adapter.js.map +1 -0
- package/dist/infrastructure/adapters/supabase.adapter.d.ts +79 -0
- package/dist/infrastructure/adapters/supabase.adapter.d.ts.map +1 -0
- package/dist/infrastructure/adapters/supabase.adapter.js +97 -0
- package/dist/infrastructure/adapters/supabase.adapter.js.map +1 -0
- package/dist/infrastructure/database/supabase.client.d.ts +20 -0
- package/dist/infrastructure/database/supabase.client.d.ts.map +1 -0
- package/dist/infrastructure/database/supabase.client.js +36 -0
- package/dist/infrastructure/database/supabase.client.js.map +1 -0
- package/dist/infrastructure/di/container.d.ts +18 -0
- package/dist/infrastructure/di/container.d.ts.map +1 -0
- package/dist/infrastructure/di/container.js +103 -0
- package/dist/infrastructure/di/container.js.map +1 -0
- package/dist/infrastructure/repositories/cli-instance.repository.d.ts +64 -0
- package/dist/infrastructure/repositories/cli-instance.repository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/cli-instance.repository.js +154 -0
- package/dist/infrastructure/repositories/cli-instance.repository.js.map +1 -0
- package/dist/infrastructure/repositories/config.repository.d.ts +52 -0
- package/dist/infrastructure/repositories/config.repository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/config.repository.js +130 -0
- package/dist/infrastructure/repositories/config.repository.js.map +1 -0
- package/dist/infrastructure/repositories/index.d.ts +4 -0
- package/dist/infrastructure/repositories/index.d.ts.map +1 -0
- package/dist/infrastructure/repositories/index.js +10 -0
- package/dist/infrastructure/repositories/index.js.map +1 -0
- package/dist/infrastructure/repositories/log.repository.d.ts +44 -0
- package/dist/infrastructure/repositories/log.repository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/log.repository.js +108 -0
- package/dist/infrastructure/repositories/log.repository.js.map +1 -0
- package/dist/infrastructure/repositories/message.repository.d.ts +51 -0
- package/dist/infrastructure/repositories/message.repository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/message.repository.js +161 -0
- package/dist/infrastructure/repositories/message.repository.js.map +1 -0
- package/dist/infrastructure/repositories/queue.repository.d.ts +69 -0
- package/dist/infrastructure/repositories/queue.repository.d.ts.map +1 -0
- package/dist/infrastructure/repositories/queue.repository.js +130 -0
- package/dist/infrastructure/repositories/queue.repository.js.map +1 -0
- package/dist/infrastructure/utils/connection-health.util.d.ts +23 -0
- package/dist/infrastructure/utils/connection-health.util.d.ts.map +1 -0
- package/dist/infrastructure/utils/connection-health.util.js +64 -0
- package/dist/infrastructure/utils/connection-health.util.js.map +1 -0
- package/package.json +105 -0
- package/pm2.config.js +104 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
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;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ApplicationService = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const crypto_1 = require("crypto");
|
|
18
|
+
const os_1 = require("os");
|
|
19
|
+
const queue_service_1 = require("./queue.service");
|
|
20
|
+
const download_service_1 = require("./download.service");
|
|
21
|
+
const message_repository_1 = require("../../infrastructure/repositories/message.repository");
|
|
22
|
+
const log_repository_1 = require("../../infrastructure/repositories/log.repository");
|
|
23
|
+
const entities_1 = require("../../domain/entities");
|
|
24
|
+
const enums_1 = require("../../domain/enums");
|
|
25
|
+
/**
|
|
26
|
+
* Application Service
|
|
27
|
+
* Main orchestrator for message processing workflow
|
|
28
|
+
*/
|
|
29
|
+
let ApplicationService = class ApplicationService {
|
|
30
|
+
queueService;
|
|
31
|
+
downloadService;
|
|
32
|
+
messageRepository;
|
|
33
|
+
logRepository;
|
|
34
|
+
constructor(queueService, downloadService, messageRepository, logRepository) {
|
|
35
|
+
this.queueService = queueService;
|
|
36
|
+
this.downloadService = downloadService;
|
|
37
|
+
this.messageRepository = messageRepository;
|
|
38
|
+
this.logRepository = logRepository;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Processes the next message from the queue
|
|
42
|
+
* @returns true if a message was processed, false if queue is empty
|
|
43
|
+
*/
|
|
44
|
+
async processNextMessage() {
|
|
45
|
+
try {
|
|
46
|
+
// Poll for a message
|
|
47
|
+
const queueMessage = await this.queueService.pollMessage();
|
|
48
|
+
if (!queueMessage) {
|
|
49
|
+
return false; // Queue is empty
|
|
50
|
+
}
|
|
51
|
+
return await this.processMessage(queueMessage);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
55
|
+
console.error('Error processing message:', errorMessage);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Processes a specific message (used when message is pre-fetched)
|
|
61
|
+
* @param queueMessage - The PGMQ message to process
|
|
62
|
+
* @returns true if processed successfully
|
|
63
|
+
*/
|
|
64
|
+
async processMessage(queueMessage) {
|
|
65
|
+
try {
|
|
66
|
+
const pgmqMessageId = queueMessage.msg_id;
|
|
67
|
+
const { file_url, target_folder } = queueMessage.message;
|
|
68
|
+
const queueName = this.queueService.getQueueName();
|
|
69
|
+
console.log(`📋 Message ID: ${pgmqMessageId}`);
|
|
70
|
+
console.log(`📮 Queue: ${queueName}`);
|
|
71
|
+
console.log(`🔗 File URL: ${file_url}`);
|
|
72
|
+
console.log(`📁 Target Folder: ${target_folder}`);
|
|
73
|
+
// Create message record with instance tracking
|
|
74
|
+
console.log('💾 Creating message record in database...');
|
|
75
|
+
const instanceId = process.env.CLI_INSTANCE_ID || `${(0, os_1.hostname)()}-${(0, os_1.platform)()}`;
|
|
76
|
+
const messageEntity = new entities_1.MessageEntity((0, crypto_1.randomUUID)(), pgmqMessageId, file_url, target_folder, enums_1.MessageStatus.RECEIVED, new Date(), undefined, // processed_by_instance_id (UUID - not used)
|
|
77
|
+
instanceId, // processed_by_instance_name (our CLI_INSTANCE_ID)
|
|
78
|
+
(0, os_1.hostname)(), // processed_by_hostname
|
|
79
|
+
(0, os_1.platform)() // processed_by_platform
|
|
80
|
+
);
|
|
81
|
+
await this.messageRepository.create(messageEntity);
|
|
82
|
+
await this.logInfo(messageEntity.id, 'Message received from queue');
|
|
83
|
+
console.log('✅ Message record created');
|
|
84
|
+
// Mark as processing
|
|
85
|
+
console.log('⚙️ Marking message as processing...');
|
|
86
|
+
messageEntity.markAsProcessing();
|
|
87
|
+
await this.messageRepository.update(messageEntity);
|
|
88
|
+
await this.logInfo(messageEntity.id, 'Started processing message');
|
|
89
|
+
console.log('✅ Status updated to processing');
|
|
90
|
+
// Download the image
|
|
91
|
+
console.log('⬇️ Starting image download...');
|
|
92
|
+
const downloadResult = await this.downloadService.downloadImage(messageEntity);
|
|
93
|
+
if (downloadResult.success) {
|
|
94
|
+
// Mark as completed
|
|
95
|
+
console.log(`✅ Download completed successfully!`);
|
|
96
|
+
console.log(` 📄 File: ${downloadResult.fileName}`);
|
|
97
|
+
console.log(` 📦 Size: ${(downloadResult.fileSizeBytes / 1024).toFixed(2)} KB`);
|
|
98
|
+
console.log(` ⏱️ Duration: ${downloadResult.durationMs}ms`);
|
|
99
|
+
messageEntity.markAsCompleted(downloadResult.fileName, downloadResult.filePath, downloadResult.fileSizeBytes, downloadResult.durationMs);
|
|
100
|
+
await this.messageRepository.update(messageEntity);
|
|
101
|
+
await this.logInfo(messageEntity.id, 'Download completed successfully', {
|
|
102
|
+
fileName: downloadResult.fileName,
|
|
103
|
+
filePath: downloadResult.filePath,
|
|
104
|
+
fileSizeBytes: downloadResult.fileSizeBytes,
|
|
105
|
+
durationMs: downloadResult.durationMs,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Mark as failed
|
|
110
|
+
console.log(`❌ Download failed!`);
|
|
111
|
+
console.log(` Error: ${downloadResult.error.message}`);
|
|
112
|
+
console.log(` Category: ${downloadResult.error.category}`);
|
|
113
|
+
messageEntity.markAsFailed(downloadResult.error.message, downloadResult.error.category);
|
|
114
|
+
await this.messageRepository.update(messageEntity);
|
|
115
|
+
await this.logError(messageEntity.id, 'Download failed', new Error(downloadResult.error.message), { category: downloadResult.error.category });
|
|
116
|
+
}
|
|
117
|
+
// Mark message as deleted from queue
|
|
118
|
+
console.log('🗑️ Removing message from queue...');
|
|
119
|
+
messageEntity.markAsDeletedFromQueue();
|
|
120
|
+
await this.messageRepository.update(messageEntity);
|
|
121
|
+
// Acknowledge message (delete from queue)
|
|
122
|
+
await this.queueService.acknowledgeMessage(pgmqMessageId);
|
|
123
|
+
await this.logInfo(messageEntity.id, 'Message acknowledged and removed from queue');
|
|
124
|
+
console.log('✅ Message removed from queue');
|
|
125
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
130
|
+
console.error('❌ Error processing message:', errorMessage);
|
|
131
|
+
if (error instanceof Error && error.stack) {
|
|
132
|
+
console.error('Stack trace:', error.stack);
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Logs an info message
|
|
139
|
+
*/
|
|
140
|
+
async logInfo(messageId, message, data) {
|
|
141
|
+
try {
|
|
142
|
+
const logEntry = entities_1.LogEntryEntity.createInfo(messageId, message, data);
|
|
143
|
+
await this.logRepository.create(logEntry);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error('Failed to create log entry:', error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Logs an error message
|
|
151
|
+
*/
|
|
152
|
+
async logError(messageId, message, error, data) {
|
|
153
|
+
try {
|
|
154
|
+
const logEntry = entities_1.LogEntryEntity.createError(messageId, message, error, data);
|
|
155
|
+
await this.logRepository.create(logEntry);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
console.error('Failed to create error log entry:', err);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
exports.ApplicationService = ApplicationService;
|
|
163
|
+
exports.ApplicationService = ApplicationService = __decorate([
|
|
164
|
+
(0, tsyringe_1.injectable)(),
|
|
165
|
+
__param(0, (0, tsyringe_1.inject)(queue_service_1.QueueService)),
|
|
166
|
+
__param(1, (0, tsyringe_1.inject)(download_service_1.DownloadService)),
|
|
167
|
+
__param(2, (0, tsyringe_1.inject)(message_repository_1.MessageRepository)),
|
|
168
|
+
__param(3, (0, tsyringe_1.inject)(log_repository_1.LogRepository)),
|
|
169
|
+
__metadata("design:paramtypes", [queue_service_1.QueueService,
|
|
170
|
+
download_service_1.DownloadService,
|
|
171
|
+
message_repository_1.MessageRepository,
|
|
172
|
+
log_repository_1.LogRepository])
|
|
173
|
+
], ApplicationService);
|
|
174
|
+
//# sourceMappingURL=application.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application.service.js","sourceRoot":"","sources":["../../../src/application/services/application.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IDownloadService, DownloadResult } from '../../domain/interfaces/services/idownload.service';
|
|
2
|
+
import { MessageEntity } from '../../domain/entities';
|
|
3
|
+
import { HttpAdapter } from '../../infrastructure/adapters/http.adapter';
|
|
4
|
+
import { FileSystemAdapter } from '../../infrastructure/adapters/filesystem.adapter';
|
|
5
|
+
import { UrlValidator } from '../../domain/validators/url.validator';
|
|
6
|
+
import { PathValidator } from '../../domain/validators/path.validator';
|
|
7
|
+
import { FileNamingService } from './file-naming.service';
|
|
8
|
+
/**
|
|
9
|
+
* Download Service
|
|
10
|
+
* Handles image download operations with validation
|
|
11
|
+
*/
|
|
12
|
+
export declare class DownloadService implements IDownloadService {
|
|
13
|
+
private httpAdapter;
|
|
14
|
+
private fsAdapter;
|
|
15
|
+
private urlValidator;
|
|
16
|
+
private pathValidator;
|
|
17
|
+
private fileNamingService;
|
|
18
|
+
private readonly pathResolver;
|
|
19
|
+
constructor(httpAdapter: HttpAdapter, fsAdapter: FileSystemAdapter, urlValidator: UrlValidator, pathValidator: PathValidator, fileNamingService: FileNamingService);
|
|
20
|
+
/**
|
|
21
|
+
* Downloads an image from URL and saves to target folder
|
|
22
|
+
* @param message - Message entity containing download details
|
|
23
|
+
* @returns Download result
|
|
24
|
+
*/
|
|
25
|
+
downloadImage(message: MessageEntity): Promise<DownloadResult>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=download.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.service.d.ts","sourceRoot":"","sources":["../../../src/application/services/download.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAEnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;GAGG;AACH,qBACa,eAAgB,YAAW,gBAAgB;IAI/B,OAAO,CAAC,WAAW;IACb,OAAO,CAAC,SAAS;IACtB,OAAO,CAAC,YAAY;IACnB,OAAO,CAAC,aAAa;IACjB,OAAO,CAAC,iBAAiB;IAPtD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;gBAGpB,WAAW,EAAE,WAAW,EAClB,SAAS,EAAE,iBAAiB,EACjC,YAAY,EAAE,YAAY,EACzB,aAAa,EAAE,aAAa,EACxB,iBAAiB,EAAE,iBAAiB;IAKzE;;;;OAIG;IACG,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAqHrE"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
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;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
45
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.DownloadService = void 0;
|
|
49
|
+
const tsyringe_1 = require("tsyringe");
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const enums_1 = require("../../domain/enums");
|
|
52
|
+
const http_adapter_1 = require("../../infrastructure/adapters/http.adapter");
|
|
53
|
+
const filesystem_adapter_1 = require("../../infrastructure/adapters/filesystem.adapter");
|
|
54
|
+
const url_validator_1 = require("../../domain/validators/url.validator");
|
|
55
|
+
const path_validator_1 = require("../../domain/validators/path.validator");
|
|
56
|
+
const path_resolver_service_1 = require("../../domain/services/path-resolver.service");
|
|
57
|
+
const file_naming_service_1 = require("./file-naming.service");
|
|
58
|
+
/**
|
|
59
|
+
* Download Service
|
|
60
|
+
* Handles image download operations with validation
|
|
61
|
+
*/
|
|
62
|
+
let DownloadService = class DownloadService {
|
|
63
|
+
httpAdapter;
|
|
64
|
+
fsAdapter;
|
|
65
|
+
urlValidator;
|
|
66
|
+
pathValidator;
|
|
67
|
+
fileNamingService;
|
|
68
|
+
pathResolver;
|
|
69
|
+
constructor(httpAdapter, fsAdapter, urlValidator, pathValidator, fileNamingService) {
|
|
70
|
+
this.httpAdapter = httpAdapter;
|
|
71
|
+
this.fsAdapter = fsAdapter;
|
|
72
|
+
this.urlValidator = urlValidator;
|
|
73
|
+
this.pathValidator = pathValidator;
|
|
74
|
+
this.fileNamingService = fileNamingService;
|
|
75
|
+
this.pathResolver = new path_resolver_service_1.PathResolverService();
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Downloads an image from URL and saves to target folder
|
|
79
|
+
* @param message - Message entity containing download details
|
|
80
|
+
* @returns Download result
|
|
81
|
+
*/
|
|
82
|
+
async downloadImage(message) {
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
try {
|
|
85
|
+
// Validate URL
|
|
86
|
+
if (!this.urlValidator.isValid(message.file_url)) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: {
|
|
90
|
+
message: `Invalid URL: ${message.file_url}`,
|
|
91
|
+
category: enums_1.ErrorCategory.VALIDATION,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Validate target folder using basic validator
|
|
96
|
+
if (!this.pathValidator.isValid(message.target_folder)) {
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: {
|
|
100
|
+
message: `Invalid target folder: ${message.target_folder}`,
|
|
101
|
+
category: enums_1.ErrorCategory.VALIDATION,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// Check for path traversal using basic validator
|
|
106
|
+
if (!this.pathValidator.isSafe(message.target_folder)) {
|
|
107
|
+
return {
|
|
108
|
+
success: false,
|
|
109
|
+
error: {
|
|
110
|
+
message: `Unsafe path detected: ${message.target_folder}`,
|
|
111
|
+
category: enums_1.ErrorCategory.VALIDATION,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Resolve path using PathResolverService for cross-platform support
|
|
116
|
+
const pathResolution = this.pathResolver.resolve(message.target_folder);
|
|
117
|
+
if (!pathResolution.isValid) {
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
error: {
|
|
121
|
+
message: pathResolution.error || 'Path resolution failed',
|
|
122
|
+
category: enums_1.ErrorCategory.VALIDATION,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const targetDir = pathResolution.absolutePath;
|
|
127
|
+
// Additional safety check after resolution
|
|
128
|
+
if (!this.pathResolver.isSafePath(targetDir)) {
|
|
129
|
+
return {
|
|
130
|
+
success: false,
|
|
131
|
+
error: {
|
|
132
|
+
message: `Path contains directory traversal after resolution: ${targetDir}`,
|
|
133
|
+
category: enums_1.ErrorCategory.VALIDATION,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
// Extract filename from URL
|
|
138
|
+
let fileName = this.urlValidator.extractFilename(message.file_url);
|
|
139
|
+
// Download the image
|
|
140
|
+
const downloadResult = await this.httpAdapter.download(message.file_url, 30000);
|
|
141
|
+
// Ensure filename has extension (use content-type or default to .jpg)
|
|
142
|
+
fileName = this.fileNamingService.ensureExtension(fileName, downloadResult.contentType || null);
|
|
143
|
+
// Ensure target directory exists
|
|
144
|
+
await this.fsAdapter.ensureDir(targetDir);
|
|
145
|
+
// Ensure filename is unique in target directory
|
|
146
|
+
fileName = await this.fileNamingService.ensureUniqueFilename(targetDir, fileName);
|
|
147
|
+
const fullPath = path.join(targetDir, fileName);
|
|
148
|
+
// Write file to disk
|
|
149
|
+
await this.fsAdapter.writeFile(fullPath, downloadResult.buffer);
|
|
150
|
+
// Get file stats
|
|
151
|
+
const stats = await this.fsAdapter.getFileStats(fullPath);
|
|
152
|
+
const durationMs = Date.now() - startTime;
|
|
153
|
+
return {
|
|
154
|
+
success: true,
|
|
155
|
+
fileName,
|
|
156
|
+
filePath: fullPath,
|
|
157
|
+
fileSizeBytes: stats.size,
|
|
158
|
+
durationMs,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
const durationMs = Date.now() - startTime;
|
|
163
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
164
|
+
// Categorize error
|
|
165
|
+
let category = enums_1.ErrorCategory.UNKNOWN;
|
|
166
|
+
if (errorMessage.includes('timeout') || errorMessage.includes('network') || errorMessage.includes('HTTP')) {
|
|
167
|
+
category = enums_1.ErrorCategory.NETWORK;
|
|
168
|
+
}
|
|
169
|
+
else if (errorMessage.includes('Permission') || errorMessage.includes('EACCES') || errorMessage.includes('ENOENT')) {
|
|
170
|
+
category = enums_1.ErrorCategory.FILESYSTEM;
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
durationMs,
|
|
175
|
+
error: {
|
|
176
|
+
message: errorMessage,
|
|
177
|
+
category,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
exports.DownloadService = DownloadService;
|
|
184
|
+
exports.DownloadService = DownloadService = __decorate([
|
|
185
|
+
(0, tsyringe_1.injectable)(),
|
|
186
|
+
__param(0, (0, tsyringe_1.inject)(http_adapter_1.HttpAdapter)),
|
|
187
|
+
__param(1, (0, tsyringe_1.inject)(filesystem_adapter_1.FileSystemAdapter)),
|
|
188
|
+
__param(2, (0, tsyringe_1.inject)(url_validator_1.UrlValidator)),
|
|
189
|
+
__param(3, (0, tsyringe_1.inject)(path_validator_1.PathValidator)),
|
|
190
|
+
__param(4, (0, tsyringe_1.inject)(file_naming_service_1.FileNamingService)),
|
|
191
|
+
__metadata("design:paramtypes", [http_adapter_1.HttpAdapter,
|
|
192
|
+
filesystem_adapter_1.FileSystemAdapter,
|
|
193
|
+
url_validator_1.UrlValidator,
|
|
194
|
+
path_validator_1.PathValidator,
|
|
195
|
+
file_naming_service_1.FileNamingService])
|
|
196
|
+
], DownloadService);
|
|
197
|
+
//# sourceMappingURL=download.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.service.js","sourceRoot":"","sources":["../../../src/application/services/download.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FileSystemAdapter } from '../../infrastructure/adapters/filesystem.adapter';
|
|
2
|
+
/**
|
|
3
|
+
* File Naming Service
|
|
4
|
+
* Handles file naming logic including deduplication and extension detection
|
|
5
|
+
*/
|
|
6
|
+
export declare class FileNamingService {
|
|
7
|
+
private fsAdapter;
|
|
8
|
+
private readonly MAX_ATTEMPTS;
|
|
9
|
+
private readonly CONTENT_TYPE_MAP;
|
|
10
|
+
constructor(fsAdapter: FileSystemAdapter);
|
|
11
|
+
/**
|
|
12
|
+
* Ensures the filename has an extension
|
|
13
|
+
* Priority: existing extension > content-type header > default .jpg
|
|
14
|
+
* @param filename - Original filename
|
|
15
|
+
* @param contentType - HTTP Content-Type header (optional)
|
|
16
|
+
* @returns Filename with extension
|
|
17
|
+
*/
|
|
18
|
+
ensureExtension(filename: string, contentType: string | null): string;
|
|
19
|
+
/**
|
|
20
|
+
* Ensures the filename is unique in the target directory
|
|
21
|
+
* Appends _1, _2, _3, etc. if file already exists
|
|
22
|
+
* @param targetDir - Target directory path
|
|
23
|
+
* @param filename - Desired filename
|
|
24
|
+
* @returns Unique filename
|
|
25
|
+
*/
|
|
26
|
+
ensureUniqueFilename(targetDir: string, filename: string): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Extracts file extension from Content-Type header
|
|
29
|
+
* @param contentType - HTTP Content-Type header
|
|
30
|
+
* @returns File extension without dot, or null if not found
|
|
31
|
+
*/
|
|
32
|
+
private getExtensionFromContentType;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=file-naming.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-naming.service.d.ts","sourceRoot":"","sources":["../../../src/application/services/file-naming.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8CAA8C,CAAC;AAEjF;;;GAGG;AACH,qBACa,iBAAiB;IAgBC,OAAO,CAAC,SAAS;IAf9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAO;IAGpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAS/B;gBAGmC,SAAS,EAAE,iBAAiB;IAGjE;;;;;;OAMG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM;IAmBrE;;;;;;OAMG;IACG,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6BhF;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;CAMpC"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
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;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
42
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
43
|
+
};
|
|
44
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
45
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.FileNamingService = void 0;
|
|
49
|
+
const tsyringe_1 = require("tsyringe");
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const filesystem_adapter_1 = require("../../infrastructure/adapters/filesystem.adapter");
|
|
52
|
+
/**
|
|
53
|
+
* File Naming Service
|
|
54
|
+
* Handles file naming logic including deduplication and extension detection
|
|
55
|
+
*/
|
|
56
|
+
let FileNamingService = class FileNamingService {
|
|
57
|
+
fsAdapter;
|
|
58
|
+
MAX_ATTEMPTS = 100;
|
|
59
|
+
// Map content types to file extensions
|
|
60
|
+
CONTENT_TYPE_MAP = {
|
|
61
|
+
'image/jpeg': 'jpg',
|
|
62
|
+
'image/jpg': 'jpg',
|
|
63
|
+
'image/png': 'png',
|
|
64
|
+
'image/gif': 'gif',
|
|
65
|
+
'image/webp': 'webp',
|
|
66
|
+
'image/svg+xml': 'svg',
|
|
67
|
+
'image/bmp': 'bmp',
|
|
68
|
+
'image/tiff': 'tiff',
|
|
69
|
+
};
|
|
70
|
+
constructor(fsAdapter) {
|
|
71
|
+
this.fsAdapter = fsAdapter;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Ensures the filename has an extension
|
|
75
|
+
* Priority: existing extension > content-type header > default .jpg
|
|
76
|
+
* @param filename - Original filename
|
|
77
|
+
* @param contentType - HTTP Content-Type header (optional)
|
|
78
|
+
* @returns Filename with extension
|
|
79
|
+
*/
|
|
80
|
+
ensureExtension(filename, contentType) {
|
|
81
|
+
// Check if filename already has an extension
|
|
82
|
+
const ext = path.extname(filename);
|
|
83
|
+
if (ext) {
|
|
84
|
+
return filename; // Already has extension, keep it
|
|
85
|
+
}
|
|
86
|
+
// Try to get extension from content type
|
|
87
|
+
if (contentType) {
|
|
88
|
+
const extension = this.getExtensionFromContentType(contentType);
|
|
89
|
+
if (extension) {
|
|
90
|
+
return `${filename}.${extension}`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Default to .jpg
|
|
94
|
+
return `${filename}.jpg`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Ensures the filename is unique in the target directory
|
|
98
|
+
* Appends _1, _2, _3, etc. if file already exists
|
|
99
|
+
* @param targetDir - Target directory path
|
|
100
|
+
* @param filename - Desired filename
|
|
101
|
+
* @returns Unique filename
|
|
102
|
+
*/
|
|
103
|
+
async ensureUniqueFilename(targetDir, filename) {
|
|
104
|
+
const ext = path.extname(filename);
|
|
105
|
+
const basename = path.basename(filename, ext);
|
|
106
|
+
// Check if original filename is available
|
|
107
|
+
const originalPath = path.join(targetDir, filename);
|
|
108
|
+
const exists = await this.fsAdapter.fileExists(originalPath);
|
|
109
|
+
if (!exists) {
|
|
110
|
+
return filename;
|
|
111
|
+
}
|
|
112
|
+
// Try with counter suffix
|
|
113
|
+
for (let counter = 1; counter <= this.MAX_ATTEMPTS; counter++) {
|
|
114
|
+
const newFilename = ext
|
|
115
|
+
? `${basename}_${counter}${ext}`
|
|
116
|
+
: `${basename}_${counter}`;
|
|
117
|
+
const newPath = path.join(targetDir, newFilename);
|
|
118
|
+
const exists = await this.fsAdapter.fileExists(newPath);
|
|
119
|
+
if (!exists) {
|
|
120
|
+
return newFilename;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
throw new Error(`Could not find unique filename after ${this.MAX_ATTEMPTS} attempts`);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Extracts file extension from Content-Type header
|
|
127
|
+
* @param contentType - HTTP Content-Type header
|
|
128
|
+
* @returns File extension without dot, or null if not found
|
|
129
|
+
*/
|
|
130
|
+
getExtensionFromContentType(contentType) {
|
|
131
|
+
// Remove charset and other parameters
|
|
132
|
+
const mimeType = contentType.split(';')[0].trim().toLowerCase();
|
|
133
|
+
return this.CONTENT_TYPE_MAP[mimeType] || null;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
exports.FileNamingService = FileNamingService;
|
|
137
|
+
exports.FileNamingService = FileNamingService = __decorate([
|
|
138
|
+
(0, tsyringe_1.injectable)(),
|
|
139
|
+
__param(0, (0, tsyringe_1.inject)(filesystem_adapter_1.FileSystemAdapter)),
|
|
140
|
+
__metadata("design:paramtypes", [filesystem_adapter_1.FileSystemAdapter])
|
|
141
|
+
], FileNamingService);
|
|
142
|
+
//# sourceMappingURL=file-naming.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-naming.service.js","sourceRoot":"","sources":["../../../src/application/services/file-naming.service.ts"],"names":[],"mappings":"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"}
|