@oxyhq/services 5.10.6 → 5.10.7

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.
@@ -1,322 +0,0 @@
1
- import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';
2
- import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
3
-
4
- export interface S3Config {
5
- region: string;
6
- accessKeyId: string;
7
- secretAccessKey: string;
8
- bucketName: string;
9
- }
10
-
11
- export interface UploadOptions {
12
- contentType?: string;
13
- metadata?: Record<string, string>;
14
- publicRead?: boolean;
15
- }
16
-
17
- export interface FileInfo {
18
- key: string;
19
- size: number;
20
- lastModified: Date;
21
- contentType?: string;
22
- metadata?: Record<string, string>;
23
- }
24
-
25
- export interface RNFile {
26
- uri: string;
27
- name: string;
28
- type?: string;
29
- size?: number;
30
- }
31
-
32
- export class S3FileManagerRN {
33
- private s3Client: S3Client;
34
- private bucketName: string;
35
-
36
- constructor(config: S3Config) {
37
- this.s3Client = new S3Client({
38
- region: config.region,
39
- credentials: {
40
- accessKeyId: config.accessKeyId,
41
- secretAccessKey: config.secretAccessKey,
42
- },
43
- });
44
- this.bucketName = config.bucketName;
45
- }
46
-
47
- /**
48
- * Upload a file to S3 from React Native
49
- */
50
- async uploadFile(
51
- key: string,
52
- file: RNFile | Buffer | string,
53
- options: UploadOptions = {}
54
- ): Promise<string> {
55
- let body: Buffer | string;
56
- let contentType = options.contentType;
57
-
58
- if (this.isRNFile(file)) {
59
- body = await this.rnFileToBuffer(file);
60
- contentType = contentType || file.type || 'application/octet-stream';
61
- } else if (typeof file === 'string') {
62
- body = file;
63
- contentType = contentType || 'text/plain';
64
- } else {
65
- body = file;
66
- contentType = contentType || 'application/octet-stream';
67
- }
68
-
69
- const command = new PutObjectCommand({
70
- Bucket: this.bucketName,
71
- Key: key,
72
- Body: body,
73
- ContentType: contentType,
74
- Metadata: options.metadata,
75
- ACL: options.publicRead ? 'public-read' : 'private',
76
- });
77
-
78
- await this.s3Client.send(command);
79
- return `https://${this.bucketName}.s3.amazonaws.com/${key}`;
80
- }
81
-
82
- /**
83
- * Download a file from S3 to React Native
84
- */
85
- async downloadFile(key: string): Promise<Buffer> {
86
- const command = new GetObjectCommand({
87
- Bucket: this.bucketName,
88
- Key: key,
89
- });
90
-
91
- const response = await this.s3Client.send(command);
92
-
93
- if (!response.Body) {
94
- throw new Error('File not found or empty');
95
- }
96
-
97
- // Convert stream to buffer
98
- const chunks: Uint8Array[] = [];
99
- const reader = response.Body.transformToWebStream().getReader();
100
-
101
- while (true) {
102
- const { done, value } = await reader.read();
103
- if (done) break;
104
- chunks.push(value);
105
- }
106
-
107
- return Buffer.concat(chunks);
108
- }
109
-
110
- /**
111
- * Delete a file from S3
112
- */
113
- async deleteFile(key: string): Promise<void> {
114
- const command = new DeleteObjectCommand({
115
- Bucket: this.bucketName,
116
- Key: key,
117
- });
118
-
119
- await this.s3Client.send(command);
120
- }
121
-
122
- /**
123
- * Generate a presigned URL for file upload
124
- */
125
- async getPresignedUploadUrl(
126
- key: string,
127
- contentType: string,
128
- expiresIn: number = 3600
129
- ): Promise<string> {
130
- const command = new PutObjectCommand({
131
- Bucket: this.bucketName,
132
- Key: key,
133
- ContentType: contentType,
134
- });
135
-
136
- return getSignedUrl(this.s3Client, command, { expiresIn });
137
- }
138
-
139
- /**
140
- * Generate a presigned URL for file download
141
- */
142
- async getPresignedDownloadUrl(
143
- key: string,
144
- expiresIn: number = 3600
145
- ): Promise<string> {
146
- const command = new GetObjectCommand({
147
- Bucket: this.bucketName,
148
- Key: key,
149
- });
150
-
151
- return getSignedUrl(this.s3Client, command, { expiresIn });
152
- }
153
-
154
- /**
155
- * List files in a directory
156
- */
157
- async listFiles(prefix: string = '', maxKeys: number = 1000): Promise<FileInfo[]> {
158
- const command = new ListObjectsV2Command({
159
- Bucket: this.bucketName,
160
- Prefix: prefix,
161
- MaxKeys: maxKeys,
162
- });
163
-
164
- const response = await this.s3Client.send(command);
165
-
166
- if (!response.Contents) {
167
- return [];
168
- }
169
-
170
- return response.Contents.map((item) => ({
171
- key: item.Key!,
172
- size: item.Size || 0,
173
- lastModified: item.LastModified!,
174
- }));
175
- }
176
-
177
- /**
178
- * Check if a file exists
179
- */
180
- async fileExists(key: string): Promise<boolean> {
181
- try {
182
- const command = new GetObjectCommand({
183
- Bucket: this.bucketName,
184
- Key: key,
185
- });
186
-
187
- await this.s3Client.send(command);
188
- return true;
189
- } catch (error: any) {
190
- if (error.name === 'NoSuchKey') {
191
- return false;
192
- }
193
- throw error;
194
- }
195
- }
196
-
197
- /**
198
- * Get file metadata
199
- */
200
- async getFileMetadata(key: string): Promise<FileInfo | null> {
201
- try {
202
- const command = new GetObjectCommand({
203
- Bucket: this.bucketName,
204
- Key: key,
205
- });
206
-
207
- const response = await this.s3Client.send(command);
208
-
209
- return {
210
- key,
211
- size: parseInt(response.ContentLength?.toString() || '0'),
212
- lastModified: response.LastModified!,
213
- contentType: response.ContentType,
214
- metadata: response.Metadata,
215
- };
216
- } catch (error: any) {
217
- if (error.name === 'NoSuchKey') {
218
- return null;
219
- }
220
- throw error;
221
- }
222
- }
223
-
224
- /**
225
- * Convert React Native file to Buffer
226
- */
227
- private async rnFileToBuffer(file: RNFile): Promise<Buffer> {
228
- try {
229
- // For React Native, we need to fetch the file from the URI
230
- const response = await fetch(file.uri);
231
- const arrayBuffer = await response.arrayBuffer();
232
- return Buffer.from(arrayBuffer);
233
- } catch (error) {
234
- throw new Error(`Failed to read React Native file: ${error}`);
235
- }
236
- }
237
-
238
- /**
239
- * Type guard to check if object is RNFile
240
- */
241
- private isRNFile(file: any): file is RNFile {
242
- return file && typeof file === 'object' && 'uri' in file && 'name' in file;
243
- }
244
-
245
- /**
246
- * Upload multiple files
247
- */
248
- async uploadMultipleFiles(
249
- files: Array<{ key: string; file: RNFile | Buffer | string; options?: UploadOptions }>
250
- ): Promise<string[]> {
251
- const uploadPromises = files.map(({ key, file, options }) =>
252
- this.uploadFile(key, file, options)
253
- );
254
-
255
- return Promise.all(uploadPromises);
256
- }
257
-
258
- /**
259
- * Delete multiple files
260
- */
261
- async deleteMultipleFiles(keys: string[]): Promise<void> {
262
- const deletePromises = keys.map(key => this.deleteFile(key));
263
- await Promise.all(deletePromises);
264
- }
265
-
266
- /**
267
- * Copy file from one key to another
268
- */
269
- async copyFile(sourceKey: string, destinationKey: string): Promise<void> {
270
- const command = new PutObjectCommand({
271
- Bucket: this.bucketName,
272
- Key: destinationKey,
273
- Body: await this.downloadFile(sourceKey),
274
- });
275
-
276
- await this.s3Client.send(command);
277
- }
278
-
279
- /**
280
- * Move file (copy + delete)
281
- */
282
- async moveFile(sourceKey: string, destinationKey: string): Promise<void> {
283
- await this.copyFile(sourceKey, destinationKey);
284
- await this.deleteFile(sourceKey);
285
- }
286
-
287
- /**
288
- * Upload image with automatic resizing (placeholder for future implementation)
289
- */
290
- async uploadImage(
291
- key: string,
292
- file: RNFile,
293
- options: UploadOptions & { resize?: { width?: number; height?: number } } = {}
294
- ): Promise<string> {
295
- // For now, just upload as regular file
296
- // In the future, this could integrate with image processing libraries
297
- return this.uploadFile(key, file, options);
298
- }
299
-
300
- /**
301
- * Get file size from React Native file
302
- */
303
- async getFileSize(file: RNFile): Promise<number> {
304
- if (file.size) {
305
- return file.size;
306
- }
307
-
308
- try {
309
- const response = await fetch(file.uri, { method: 'HEAD' });
310
- const contentLength = response.headers.get('content-length');
311
- return contentLength ? parseInt(contentLength, 10) : 0;
312
- } catch (error) {
313
- console.warn('Could not determine file size:', error);
314
- return 0;
315
- }
316
- }
317
- }
318
-
319
- // Export a factory function for easier configuration
320
- export function createS3FileManagerRN(config: S3Config): S3FileManagerRN {
321
- return new S3FileManagerRN(config);
322
- }