vintasend 0.4.17 → 0.5.0-alpha2

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,21 +1,17 @@
1
- import type { AttachmentFile, AttachmentFileRecord, FileAttachment } from '../../types/attachment';
1
+ import type { AttachmentFile, AttachmentFileRecord, FileAttachment, StorageIdentifiers } from '../../types/attachment';
2
2
  export declare abstract class BaseAttachmentManager {
3
3
  /**
4
4
  * Upload a file and return file record (reusable across notifications)
5
5
  */
6
6
  abstract uploadFile(file: FileAttachment, filename: string, contentType?: string): Promise<AttachmentFileRecord>;
7
7
  /**
8
- * Get file metadata by ID
8
+ * Reconstruct AttachmentFile from storage identifiers
9
9
  */
10
- abstract getFile(fileId: string): Promise<AttachmentFileRecord | null>;
10
+ abstract reconstructAttachmentFile(storageIdentifiers: StorageIdentifiers): AttachmentFile;
11
11
  /**
12
- * Delete a file (only if not referenced by any notifications)
12
+ * Delete a file from storage using its identifiers
13
13
  */
14
- abstract deleteFile(fileId: string): Promise<void>;
15
- /**
16
- * Reconstruct AttachmentFile from storage metadata
17
- */
18
- abstract reconstructAttachmentFile(storageMetadata: Record<string, unknown>): AttachmentFile;
14
+ abstract deleteFileByIdentifiers(storageIdentifiers: StorageIdentifiers): Promise<void>;
19
15
  /**
20
16
  * Detect content type from filename
21
17
  * Public to allow backends and custom implementations to use it
@@ -1,4 +1,4 @@
1
- import type { AttachmentFile, AttachmentFileRecord, FileAttachment } from '../../types/attachment';
1
+ import type { AttachmentFile, AttachmentFileRecord, FileAttachment, StorageIdentifiers } from '../../types/attachment';
2
2
  import { BaseAttachmentManager } from './base-attachment-manager';
3
3
  /**
4
4
  * Configuration options for LocalFileAttachmentManager
@@ -56,7 +56,11 @@ export declare class LocalFileAttachmentManager extends BaseAttachmentManager {
56
56
  */
57
57
  deleteFile(fileId: string): Promise<void>;
58
58
  /**
59
- * Reconstruct an AttachmentFile interface from stored metadata
59
+ * Delete a file from the local filesystem using storage identifiers
60
60
  */
61
- reconstructAttachmentFile(storageMetadata: Record<string, unknown>): AttachmentFile;
61
+ deleteFileByIdentifiers(storageIdentifiers: StorageIdentifiers): Promise<void>;
62
+ /**
63
+ * Reconstruct an AttachmentFile interface from stored identifiers
64
+ */
65
+ reconstructAttachmentFile(storageIdentifiers: StorageIdentifiers): AttachmentFile;
62
66
  }
@@ -119,7 +119,8 @@ class LocalFileAttachmentManager extends base_attachment_manager_1.BaseAttachmen
119
119
  contentType: finalContentType,
120
120
  size,
121
121
  checksum,
122
- storageMetadata: {
122
+ storageIdentifiers: {
123
+ id: fileId,
123
124
  path: filePath,
124
125
  backend: 'local-filesystem',
125
126
  },
@@ -147,7 +148,8 @@ class LocalFileAttachmentManager extends base_attachment_manager_1.BaseAttachmen
147
148
  contentType: metadata.contentType,
148
149
  size: metadata.size,
149
150
  checksum: metadata.checksum,
150
- storageMetadata: {
151
+ storageIdentifiers: {
152
+ id: metadata.id,
151
153
  path: filePath,
152
154
  backend: 'local-filesystem',
153
155
  },
@@ -169,7 +171,8 @@ class LocalFileAttachmentManager extends base_attachment_manager_1.BaseAttachmen
169
171
  contentType: 'application/octet-stream', // Unknown
170
172
  size: stats.size,
171
173
  checksum,
172
- storageMetadata: {
174
+ storageIdentifiers: {
175
+ id: fileId,
173
176
  path: filePath,
174
177
  backend: 'local-filesystem',
175
178
  },
@@ -210,13 +213,28 @@ class LocalFileAttachmentManager extends base_attachment_manager_1.BaseAttachmen
210
213
  }
211
214
  }
212
215
  /**
213
- * Reconstruct an AttachmentFile interface from stored metadata
216
+ * Delete a file from the local filesystem using storage identifiers
214
217
  */
215
- reconstructAttachmentFile(storageMetadata) {
216
- if (!storageMetadata.path || typeof storageMetadata.path !== 'string') {
217
- throw new Error('Invalid storage metadata: missing path');
218
+ async deleteFileByIdentifiers(storageIdentifiers) {
219
+ if (storageIdentifiers.id && typeof storageIdentifiers.id === 'string') {
220
+ await this.deleteFile(storageIdentifiers.id);
221
+ return;
218
222
  }
219
- const filePath = storageMetadata.path;
223
+ if (storageIdentifiers.path && typeof storageIdentifiers.path === 'string') {
224
+ const fileId = path.basename(storageIdentifiers.path);
225
+ await this.deleteFile(fileId);
226
+ return;
227
+ }
228
+ throw new Error('Invalid storage identifiers: missing id or path');
229
+ }
230
+ /**
231
+ * Reconstruct an AttachmentFile interface from stored identifiers
232
+ */
233
+ reconstructAttachmentFile(storageIdentifiers) {
234
+ if (!storageIdentifiers.path || typeof storageIdentifiers.path !== 'string') {
235
+ throw new Error('Invalid storage identifiers: missing path');
236
+ }
237
+ const filePath = storageIdentifiers.path;
220
238
  return new LocalAttachmentFile(filePath, this);
221
239
  }
222
240
  }
@@ -34,6 +34,19 @@ export interface BaseNotificationBackend<Config extends BaseNotificationTypeConf
34
34
  */
35
35
  injectLogger?(logger: BaseLogger): void;
36
36
  /**
37
+ * Store attachment file record in database.
38
+ * Called after AttachmentManager.uploadFile() returns storageIdentifiers.
39
+ * Backend persists file metadata and storage identifiers for later retrieval.
40
+ */
41
+ storeAttachmentFileRecord?(record: AttachmentFileRecord): Promise<void>;
42
+ /**
43
+ * Get attachment file record from database by ID.
44
+ * Returns the file metadata and storage identifiers needed to reconstruct file access.
45
+ * Used by AttachmentManager.reconstructAttachmentFile() to get file content.
46
+ */
47
+ getAttachmentFileRecord?(fileId: string): Promise<AttachmentFileRecord | null>;
48
+ /**
49
+ * @deprecated Use getAttachmentFileRecord instead.
37
50
  * Get an attachment file record by ID
38
51
  */
39
52
  getAttachmentFile?(fileId: string): Promise<AttachmentFileRecord | null>;
@@ -64,7 +77,8 @@ export interface BaseNotificationBackend<Config extends BaseNotificationTypeConf
64
77
  * Type guard to check if backend supports attachment operations
65
78
  */
66
79
  export declare function supportsAttachments<Config extends BaseNotificationTypeConfig>(backend: BaseNotificationBackend<Config>): backend is BaseNotificationBackend<Config> & {
67
- getAttachmentFile(fileId: string): Promise<AttachmentFileRecord | null>;
80
+ storeAttachmentFileRecord(record: AttachmentFileRecord): Promise<void>;
81
+ getAttachmentFileRecord(fileId: string): Promise<AttachmentFileRecord | null>;
68
82
  findAttachmentFileByChecksum(checksum: string): Promise<AttachmentFileRecord | null>;
69
83
  deleteAttachmentFile(fileId: string): Promise<void>;
70
84
  getOrphanedAttachmentFiles(): Promise<AttachmentFileRecord[]>;
@@ -5,7 +5,8 @@ exports.supportsAttachments = supportsAttachments;
5
5
  * Type guard to check if backend supports attachment operations
6
6
  */
7
7
  function supportsAttachments(backend) {
8
- return (typeof backend.getAttachmentFile === 'function' &&
8
+ return (typeof backend.storeAttachmentFileRecord === 'function' &&
9
+ typeof backend.getAttachmentFileRecord === 'function' &&
9
10
  typeof backend.findAttachmentFileByChecksum === 'function' &&
10
11
  typeof backend.deleteAttachmentFile === 'function' &&
11
12
  typeof backend.getOrphanedAttachmentFiles === 'function' &&
@@ -18,15 +18,49 @@ export interface AttachmentFile {
18
18
  url(expiresIn?: number): Promise<string>;
19
19
  delete(): Promise<void>;
20
20
  }
21
+ /**
22
+ * Generic storage identifiers returned by AttachmentManagers.
23
+ * Backends persist these as opaque data and pass them back for file reconstruction.
24
+ * Each AttachmentManager implementation defines its own specific structure.
25
+ *
26
+ * @example MedplumStorageIdentifiers
27
+ * ```typescript
28
+ * {
29
+ * id: "media-123",
30
+ * medplumBinaryId: "binary-456",
31
+ * medplumMediaId: "media-123",
32
+ * url: "Binary/binary-456"
33
+ * }
34
+ * ```
35
+ *
36
+ * @example S3StorageIdentifiers
37
+ * ```typescript
38
+ * {
39
+ * id: "file-123",
40
+ * awsS3Bucket: "my-bucket",
41
+ * awsS3Key: "uploads/file-123.pdf",
42
+ * awsS3Region: "us-east-1"
43
+ * }
44
+ * ```
45
+ */
46
+ export interface StorageIdentifiers {
47
+ id: string;
48
+ [key: string]: unknown;
49
+ }
50
+ /**
51
+ * Complete file record returned after upload.
52
+ * Contains both file metadata and storage identifiers.
53
+ * Storage identifiers are opaque to backends - used only for reconstruction.
54
+ */
21
55
  export interface AttachmentFileRecord {
22
56
  id: string;
23
57
  filename: string;
24
58
  contentType: string;
25
59
  size: number;
26
60
  checksum: string;
27
- storageMetadata: Record<string, unknown>;
28
61
  createdAt: Date;
29
62
  updatedAt: Date;
63
+ storageIdentifiers: StorageIdentifiers;
30
64
  }
31
65
  export interface StoredAttachment {
32
66
  id: string;
@@ -38,5 +72,5 @@ export interface StoredAttachment {
38
72
  createdAt: Date;
39
73
  file: AttachmentFile;
40
74
  description?: string;
41
- storageMetadata: Record<string, unknown>;
75
+ storageMetadata: StorageIdentifiers;
42
76
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vintasend",
3
- "version": "0.4.17",
3
+ "version": "0.5.0-alpha2",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist"
@@ -19,6 +19,7 @@
19
19
  "release:bump": "node scripts/release-bump.js",
20
20
  "release:bump:patch": "node scripts/release-bump.js --bump=patch",
21
21
  "release:bump:minor": "node scripts/release-bump.js --bump=minor",
22
+ "release:bump:alpha": "node scripts/release-bump.js --bump=alpha",
22
23
  "release:publish": "node scripts/release-publish.js"
23
24
  },
24
25
  "devDependencies": {