vintasend-aws-s3-attachments 0.4.3 → 0.4.17

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.
@@ -58,6 +58,19 @@ export declare class S3AttachmentManager extends BaseAttachmentManager {
58
58
  * @returns AttachmentFileRecord with S3 storage metadata
59
59
  */
60
60
  uploadFile(file: FileAttachment, filename: string, contentType?: string): Promise<AttachmentFileRecord>;
61
+ /**
62
+ * Get file metadata by ID.
63
+ *
64
+ * For S3, this requires fetching the object metadata from S3.
65
+ * The fileId is used to reconstruct the S3 key.
66
+ *
67
+ * Note: This implementation retrieves basic metadata from S3.
68
+ * The checksum is retrieved from object metadata if available.
69
+ *
70
+ * @param fileId - The unique identifier of the file
71
+ * @returns The file metadata or null if not found
72
+ */
73
+ getFile(fileId: string): Promise<AttachmentFileRecord | null>;
61
74
  /**
62
75
  * Reconstruct an AttachmentFile accessor from storage metadata.
63
76
  *
@@ -98,3 +111,4 @@ export declare class S3AttachmentManager extends BaseAttachmentManager {
98
111
  */
99
112
  private buildS3Key;
100
113
  }
114
+ //# sourceMappingURL=aws-s3-attachment-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws-s3-attachment-manager.d.ts","sourceRoot":"","sources":["../src/aws-s3-attachment-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oEAAoE,CAAC;AAC3G,OAAO,KAAK,EACX,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,MAAM,iCAAiC,CAAC;AAWzC,MAAM,WAAW,yBAAyB;IACzC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,mBAAoB,SAAQ,qBAAqB;IAC7D,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,yBAAyB;IAc7C;;;;;;;OAOG;IACG,UAAU,CACf,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,CAAC;IA6ChC;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAyDnE;;;;;;;;OAQG;IACH,yBAAyB,CACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC,cAAc;IAcjB;;;;;;;;;;OAUG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/C;;;;;;;OAOG;IACG,sBAAsB,CAC3B,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC;IAehB;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;CAMlB"}
@@ -1,11 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.S3AttachmentManager = void 0;
4
- const base_attachment_manager_1 = require("vintasend/dist/services/attachment-manager/base-attachment-manager");
5
- const client_s3_1 = require("@aws-sdk/client-s3");
6
- const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
7
- const node_stream_1 = require("node:stream");
8
- const node_crypto_1 = require("node:crypto");
1
+ import { BaseAttachmentManager } from 'vintasend/dist/services/attachment-manager/base-attachment-manager';
2
+ import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, } from '@aws-sdk/client-s3';
3
+ import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
4
+ import { Readable } from 'node:stream';
5
+ import { randomUUID } from 'node:crypto';
9
6
  /**
10
7
  * AWS S3 AttachmentManager implementation for VintaSend.
11
8
  *
@@ -18,12 +15,12 @@ const node_crypto_1 = require("node:crypto");
18
15
  * is stored by the Backend in its database. The Backend calls this manager's
19
16
  * uploadFile() method and stores the returned metadata.
20
17
  */
21
- class S3AttachmentManager extends base_attachment_manager_1.BaseAttachmentManager {
18
+ export class S3AttachmentManager extends BaseAttachmentManager {
22
19
  constructor(config) {
23
20
  super();
24
21
  this.bucket = config.bucket;
25
22
  this.keyPrefix = config.keyPrefix || '';
26
- this.s3Client = new client_s3_1.S3Client({
23
+ this.s3Client = new S3Client({
27
24
  region: config.region,
28
25
  credentials: config.credentials,
29
26
  endpoint: config.endpoint,
@@ -46,10 +43,10 @@ class S3AttachmentManager extends base_attachment_manager_1.BaseAttachmentManage
46
43
  // Detect content type if not provided
47
44
  const finalContentType = contentType || this.detectContentType(filename);
48
45
  // Generate unique S3 key
49
- const fileId = (0, node_crypto_1.randomUUID)();
46
+ const fileId = randomUUID();
50
47
  const key = this.buildS3Key(fileId, filename);
51
48
  // Upload to S3
52
- const putCommand = new client_s3_1.PutObjectCommand({
49
+ const putCommand = new PutObjectCommand({
53
50
  Bucket: this.bucket,
54
51
  Key: key,
55
52
  Body: buffer,
@@ -76,6 +73,66 @@ class S3AttachmentManager extends base_attachment_manager_1.BaseAttachmentManage
76
73
  updatedAt: new Date(),
77
74
  };
78
75
  }
76
+ /**
77
+ * Get file metadata by ID.
78
+ *
79
+ * For S3, this requires fetching the object metadata from S3.
80
+ * The fileId is used to reconstruct the S3 key.
81
+ *
82
+ * Note: This implementation retrieves basic metadata from S3.
83
+ * The checksum is retrieved from object metadata if available.
84
+ *
85
+ * @param fileId - The unique identifier of the file
86
+ * @returns The file metadata or null if not found
87
+ */
88
+ async getFile(fileId) {
89
+ try {
90
+ // For S3, we need to list objects with the fileId prefix to find the actual key
91
+ const prefix = `${this.keyPrefix}${fileId}/`;
92
+ // Import HeadObjectCommand for metadata retrieval
93
+ const { HeadObjectCommand } = await import('@aws-sdk/client-s3');
94
+ const { ListObjectsV2Command } = await import('@aws-sdk/client-s3');
95
+ // List objects with the fileId prefix
96
+ const listCommand = new ListObjectsV2Command({
97
+ Bucket: this.bucket,
98
+ Prefix: prefix,
99
+ MaxKeys: 1,
100
+ });
101
+ const listResponse = await this.s3Client.send(listCommand);
102
+ if (!listResponse.Contents || listResponse.Contents.length === 0) {
103
+ return null;
104
+ }
105
+ const key = listResponse.Contents[0].Key;
106
+ if (!key) {
107
+ return null;
108
+ }
109
+ // Get detailed metadata
110
+ const headCommand = new HeadObjectCommand({
111
+ Bucket: this.bucket,
112
+ Key: key,
113
+ });
114
+ const headResponse = await this.s3Client.send(headCommand);
115
+ const filename = headResponse.Metadata?.originalFilename || key.split('/').pop() || 'unknown';
116
+ const checksum = headResponse.Metadata?.checksum || '';
117
+ return {
118
+ id: fileId,
119
+ filename,
120
+ contentType: headResponse.ContentType || 'application/octet-stream',
121
+ size: headResponse.ContentLength || 0,
122
+ checksum,
123
+ storageMetadata: {
124
+ bucket: this.bucket,
125
+ key,
126
+ region: this.s3Client.config.region,
127
+ },
128
+ createdAt: headResponse.LastModified || new Date(),
129
+ updatedAt: headResponse.LastModified || new Date(),
130
+ };
131
+ }
132
+ catch (error) {
133
+ return null;
134
+ }
135
+ }
79
136
  /**
80
137
  * Reconstruct an AttachmentFile accessor from storage metadata.
81
138
  *
@@ -117,7 +174,7 @@ class S3AttachmentManager extends base_attachment_manager_1.BaseAttachmentManage
117
174
  if (!storageMetadata.key) {
118
175
  throw new Error('Storage metadata must contain key for S3 file deletion');
119
176
  }
120
- const deleteCommand = new client_s3_1.DeleteObjectCommand({
177
+ const deleteCommand = new DeleteObjectCommand({
121
178
  Bucket: this.bucket,
122
179
  Key: storageMetadata.key,
123
180
  });
@@ -137,7 +194,6 @@ class S3AttachmentManager extends base_attachment_manager_1.BaseAttachmentManage
137
194
  return `${this.keyPrefix}${fileId}/${sanitizedFilename}`;
138
195
  }
139
196
  }
140
- exports.S3AttachmentManager = S3AttachmentManager;
141
197
  /**
142
198
  * S3 AttachmentFile implementation.
143
199
  *
@@ -158,7 +214,7 @@ class S3AttachmentFile {
158
214
  * Use this for small files. For large files, prefer streaming.
159
215
  */
160
216
  async read() {
161
- const getCommand = new client_s3_1.GetObjectCommand({
217
+ const getCommand = new GetObjectCommand({
162
218
  Bucket: this.bucket,
163
219
  Key: this.key,
164
220
  });
@@ -175,7 +231,7 @@ class S3AttachmentFile {
175
231
  * Use this for large files to avoid loading everything into memory.
176
232
  */
177
233
  async stream() {
178
- const getCommand = new client_s3_1.GetObjectCommand({
234
+ const getCommand = new GetObjectCommand({
179
235
  Bucket: this.bucket,
180
236
  Key: this.key,
181
237
  });
@@ -185,7 +241,7 @@ class S3AttachmentFile {
185
241
  }
186
242
  // Convert Node.js Readable to Web ReadableStream
187
243
  const nodeStream = response.Body;
188
- return node_stream_1.Readable.toWeb(nodeStream);
244
+ return Readable.toWeb(nodeStream);
189
245
  }
190
246
  /**
191
247
  * Generate a presigned URL for accessing the file.
@@ -194,11 +250,11 @@ class S3AttachmentFile {
194
250
  * @returns A presigned URL for secure file access
195
251
  */
196
252
  async url(expiresIn = 3600) {
197
- const getCommand = new client_s3_1.GetObjectCommand({
253
+ const getCommand = new GetObjectCommand({
198
254
  Bucket: this.bucket,
199
255
  Key: this.key,
200
256
  });
201
- return (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, getCommand, { expiresIn });
257
+ return getSignedUrl(this.s3Client, getCommand, { expiresIn });
202
258
  }
203
259
  /**
204
260
  * Delete this file from S3.
@@ -206,7 +262,7 @@ class S3AttachmentFile {
206
262
  * Note: This is typically called by the AttachmentManager, not directly.
207
263
  */
208
264
  async delete() {
209
- const deleteCommand = new client_s3_1.DeleteObjectCommand({
265
+ const deleteCommand = new DeleteObjectCommand({
210
266
  Bucket: this.bucket,
211
267
  Key: this.key,
212
268
  });
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { S3AttachmentManager, type S3AttachmentManagerConfig, } from './aws-s3-attachment-manager';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,mBAAmB,EACnB,KAAK,yBAAyB,GAC9B,MAAM,6BAA6B,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.S3AttachmentManager = void 0;
4
- var aws_s3_attachment_manager_1 = require("./aws-s3-attachment-manager");
5
- Object.defineProperty(exports, "S3AttachmentManager", { enumerable: true, get: function () { return aws_s3_attachment_manager_1.S3AttachmentManager; } });
1
+ export { S3AttachmentManager, } from './aws-s3-attachment-manager';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vintasend-aws-s3-attachments",
3
- "version": "0.4.3",
3
+ "version": "0.4.17",
4
4
  "description": "Implementation of AWS S3 Attachments for VintaSend",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -16,14 +16,14 @@
16
16
  "author": "Hugo Bessa",
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
- "@aws-sdk/client-s3": "^3.967.0",
20
- "@aws-sdk/s3-request-presigner": "^3.967.0",
21
- "vintasend": "^0.4.3"
19
+ "@aws-sdk/client-s3": "^3.981.0",
20
+ "@aws-sdk/s3-request-presigner": "^3.981.0",
21
+ "vintasend": "^0.4.17"
22
22
  },
23
23
  "devDependencies": {
24
- "@types/jest": "^29.5.14",
25
- "jest": "^29.7.0",
26
- "ts-jest": "^29.2.6",
27
- "typescript": "^5.8.2"
24
+ "@types/jest": "^30.0.0",
25
+ "jest": "^30.2.0",
26
+ "ts-jest": "^29.4.6",
27
+ "typescript": "^5.9.3"
28
28
  }
29
29
  }