@tmlmobilidade/interfaces 20250906.141.55 → 20250908.1919.56
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/dist/src/interfaces/files/files.d.ts +7 -2
- package/dist/src/interfaces/files/files.js +46 -4
- package/dist/src/providers/storage/oci-storage.d.ts +2 -1
- package/dist/src/providers/storage/oci-storage.js +18 -12
- package/dist/src/providers/storage/s3-storage.d.ts +1 -1
- package/dist/src/providers/storage/storage.interface.d.ts +2 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MongoCollectionClass } from '../../mongo-collection.js';
|
|
2
2
|
import { CreateFileDto, File, UpdateFileDto } from '@tmlmobilidade/types';
|
|
3
3
|
import { DeleteOptions, DeleteResult, IndexDescription, InsertOneOptions, WithId } from 'mongodb';
|
|
4
|
+
import { Readable } from 'node:stream';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
declare class FilesClass extends MongoCollectionClass<File, CreateFileDto, UpdateFileDto> {
|
|
6
7
|
private static _instance;
|
|
@@ -44,11 +45,15 @@ declare class FilesClass extends MongoCollectionClass<File, CreateFileDto, Updat
|
|
|
44
45
|
}): Promise<string>;
|
|
45
46
|
/**
|
|
46
47
|
* Uploads a file to the storage service and inserts it into the database.
|
|
47
|
-
* @param file - The file to upload.
|
|
48
|
+
* @param file - The file to upload, either as a string, buffer, or readable stream.
|
|
48
49
|
* @param createFileDto - The file type to create.
|
|
49
50
|
* @returns The file that was uploaded.
|
|
50
51
|
*/
|
|
51
|
-
upload(file: Buffer, createFileDto: CreateFileDto
|
|
52
|
+
upload(file: Buffer | Readable | ReadableStream | string, createFileDto: CreateFileDto & {
|
|
53
|
+
_id?: string;
|
|
54
|
+
}, options?: InsertOneOptions & {
|
|
55
|
+
override?: boolean;
|
|
56
|
+
}): Promise<File>;
|
|
52
57
|
protected getCollectionIndexes(): IndexDescription[];
|
|
53
58
|
protected getCollectionName(): string;
|
|
54
59
|
protected getEnvName(): string;
|
|
@@ -151,14 +151,56 @@ class FilesClass extends MongoCollectionClass {
|
|
|
151
151
|
}
|
|
152
152
|
/**
|
|
153
153
|
* Uploads a file to the storage service and inserts it into the database.
|
|
154
|
-
* @param file - The file to upload.
|
|
154
|
+
* @param file - The file to upload, either as a string, buffer, or readable stream.
|
|
155
155
|
* @param createFileDto - The file type to create.
|
|
156
156
|
* @returns The file that was uploaded.
|
|
157
157
|
*/
|
|
158
158
|
async upload(file, createFileDto, options) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
//
|
|
160
|
+
//
|
|
161
|
+
// A. Define variables
|
|
162
|
+
if (createFileDto._id && !options?.override) {
|
|
163
|
+
throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, 'When File ID is provided, override must be true');
|
|
164
|
+
}
|
|
165
|
+
const fileId = createFileDto._id || generateRandomString({ length: 5 });
|
|
166
|
+
const fileExtension = Files.getFileExtension(createFileDto.name);
|
|
167
|
+
const mimeType = Files.getMimeTypeFromFileExtension(createFileDto.name);
|
|
168
|
+
const filePath = `${createFileDto.scope}/${createFileDto.resource_id}/${fileId}.${fileExtension}`;
|
|
169
|
+
//
|
|
170
|
+
// C. Handle database transaction
|
|
171
|
+
const session = this.getMongoConnector().client.startSession();
|
|
172
|
+
let result;
|
|
173
|
+
try {
|
|
174
|
+
session.startTransaction();
|
|
175
|
+
//
|
|
176
|
+
// C.1. Handle file override if specified
|
|
177
|
+
if (options?.override) {
|
|
178
|
+
const existingFile = await this.findOne({ _id: fileId });
|
|
179
|
+
if (existingFile) {
|
|
180
|
+
const existingFileExtension = Files.getFileExtension(existingFile.name);
|
|
181
|
+
const existingFilePath = `${existingFile.scope}/${existingFile.resource_id}/${existingFile._id}.${existingFileExtension}`;
|
|
182
|
+
if (existingFilePath !== filePath) {
|
|
183
|
+
throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, 'File ID is provided, but the file path is different from the existing file', { cause: { existingFilePath, filePath } });
|
|
184
|
+
}
|
|
185
|
+
await super.deleteById(fileId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//
|
|
189
|
+
// C.2. Upload file to storage
|
|
190
|
+
await this.storageService.uploadFile(filePath, file, mimeType);
|
|
191
|
+
//
|
|
192
|
+
// C.3. Insert file record
|
|
193
|
+
result = await this.insertOne({ ...createFileDto, _id: fileId }, { options });
|
|
194
|
+
await session.commitTransaction();
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
await session.abortTransaction();
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
session.endSession();
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
162
204
|
}
|
|
163
205
|
getCollectionIndexes() {
|
|
164
206
|
return [
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IStorageProvider } from './storage.interface.js';
|
|
2
|
+
import { Readable } from 'node:stream';
|
|
2
3
|
export interface OCIStorageProviderConfiguration {
|
|
3
4
|
bucket_name: string;
|
|
4
5
|
fingerprint: string;
|
|
@@ -25,5 +26,5 @@ export declare class OCIStorageProvider implements IStorageProvider {
|
|
|
25
26
|
fileExists(key: string): Promise<boolean>;
|
|
26
27
|
getFileUrl(key: string): Promise<string>;
|
|
27
28
|
listFiles(prefix?: string): Promise<string[]>;
|
|
28
|
-
uploadFile(key: string, body: Buffer, mimeType?: string): Promise<void>;
|
|
29
|
+
uploadFile(key: string, body: Buffer | Readable | ReadableStream, mimeType?: string): Promise<void>;
|
|
29
30
|
}
|
|
@@ -88,17 +88,23 @@ export class OCIStorageProvider {
|
|
|
88
88
|
async uploadFile(key, body, mimeType) {
|
|
89
89
|
const isImage = mimeType === mimeTypes.png || mimeType === mimeTypes.jpg || mimeType === mimeTypes.jpeg || mimeType === mimeTypes.gif || mimeType === mimeTypes.svg;
|
|
90
90
|
const uploadManager = new UploadManager(this.ociClient, { enforceMD5: true });
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
91
|
+
try {
|
|
92
|
+
await uploadManager.upload({
|
|
93
|
+
content: body instanceof Buffer
|
|
94
|
+
? { blob: new Blob([body], { type: mimeType }) }
|
|
95
|
+
: { stream: body },
|
|
96
|
+
requestDetails: {
|
|
97
|
+
bucketName: this.bucketName,
|
|
98
|
+
contentDisposition: isImage ? 'inline' : 'attachment',
|
|
99
|
+
contentType: mimeType,
|
|
100
|
+
namespaceName: this.namespace,
|
|
101
|
+
objectName: key,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error('Error uploading file:', JSON.stringify(error, null, 2));
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
103
109
|
}
|
|
104
110
|
}
|
|
@@ -60,5 +60,5 @@ export declare class S3StorageProvider implements IStorageProvider {
|
|
|
60
60
|
* @param key - The file path and name in S3.
|
|
61
61
|
* @param body - The content to upload, either as a string, buffer, or readable stream.
|
|
62
62
|
*/
|
|
63
|
-
uploadFile(key: string, body: Buffer | Readable | string, mimeType?: string): Promise<void>;
|
|
63
|
+
uploadFile(key: string, body: Buffer | Readable | ReadableStream | string, mimeType?: string): Promise<void>;
|
|
64
64
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
1
2
|
export interface IStorageProvider {
|
|
2
3
|
copyFile(source: string, destination: string): Promise<void>;
|
|
3
4
|
deleteFile(key: string): Promise<void>;
|
|
@@ -5,5 +6,5 @@ export interface IStorageProvider {
|
|
|
5
6
|
fileExists(key: string): Promise<boolean>;
|
|
6
7
|
getFileUrl(key: string): Promise<string>;
|
|
7
8
|
listFiles(prefix?: string): Promise<string[]>;
|
|
8
|
-
uploadFile(key: string, body: Buffer, mimeType?: string): Promise<void>;
|
|
9
|
+
uploadFile(key: string, body: Buffer | Readable | ReadableStream | string, mimeType?: string): Promise<void>;
|
|
9
10
|
}
|
package/package.json
CHANGED