vintasend-medplum 0.4.12 → 0.4.14
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.
|
@@ -40,7 +40,7 @@ export declare class MedplumAttachmentManager extends BaseAttachmentManager {
|
|
|
40
40
|
/**
|
|
41
41
|
* Reconstruct an AttachmentFile from storage metadata.
|
|
42
42
|
*
|
|
43
|
-
* @param storageMetadata - Metadata containing
|
|
43
|
+
* @param storageMetadata - Metadata containing 'binaryId' or 'url'
|
|
44
44
|
* @returns AttachmentFile instance for accessing the file
|
|
45
45
|
*/
|
|
46
46
|
reconstructAttachmentFile(storageMetadata: Record<string, unknown>): AttachmentFile;
|
|
@@ -53,9 +53,13 @@ export declare class MedplumAttachmentManager extends BaseAttachmentManager {
|
|
|
53
53
|
export declare class MedplumAttachmentFile implements AttachmentFile {
|
|
54
54
|
private medplum;
|
|
55
55
|
private binaryId;
|
|
56
|
-
constructor(medplum: MedplumClient,
|
|
56
|
+
constructor(medplum: MedplumClient, binaryId: string);
|
|
57
57
|
/**
|
|
58
58
|
* Read the entire file into memory as a Buffer.
|
|
59
|
+
*
|
|
60
|
+
* Works with Binary resources that have either:
|
|
61
|
+
* - Inline data (base64 encoded)
|
|
62
|
+
* - A presigned URL to download from
|
|
59
63
|
*/
|
|
60
64
|
read(): Promise<Buffer>;
|
|
61
65
|
/**
|
|
@@ -68,16 +72,12 @@ export declare class MedplumAttachmentFile implements AttachmentFile {
|
|
|
68
72
|
/**
|
|
69
73
|
* Generate a URL for accessing the file.
|
|
70
74
|
*
|
|
71
|
-
* For Medplum, this returns the Binary resource
|
|
72
|
-
* In production, you might want to generate a presigned URL.
|
|
75
|
+
* For Medplum, this returns a presigned URL from the Binary resource.
|
|
73
76
|
*
|
|
74
77
|
* @param expiresIn - Seconds until the URL expires (not used for Medplum)
|
|
75
|
-
* @returns URL for file access
|
|
78
|
+
* @returns Presigned URL for file access
|
|
76
79
|
*/
|
|
77
80
|
url(expiresIn?: number): Promise<string>;
|
|
78
|
-
/**
|
|
79
|
-
* Delete this file from storage.
|
|
80
|
-
*/
|
|
81
81
|
delete(): Promise<void>;
|
|
82
82
|
}
|
|
83
83
|
//# sourceMappingURL=medplum-attachment-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"medplum-attachment-manager.d.ts","sourceRoot":"","sources":["../src/medplum-attachment-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oEAAoE,CAAC;AAC3G,OAAO,KAAK,EACV,oBAAoB,EACpB,cAAc,EACd,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC;;;;;;;;GAQG;AACH,qBAAa,wBAAyB,SAAQ,qBAAqB;IACrD,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAI1C;;;;;;;OAOG;IACG,UAAU,CACd,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,CAAC;IAkEhC;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"medplum-attachment-manager.d.ts","sourceRoot":"","sources":["../src/medplum-attachment-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,oEAAoE,CAAC;AAC3G,OAAO,KAAK,EACV,oBAAoB,EACpB,cAAc,EACd,cAAc,EACf,MAAM,iCAAiC,CAAC;AAEzC;;;;;;;;GAQG;AACH,qBAAa,wBAAyB,SAAQ,qBAAqB;IACrD,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAI1C;;;;;;;OAOG;IACG,UAAU,CACd,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,oBAAoB,CAAC;IAkEhC;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA+CnE;;;;;;OAMG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB/C;;;;;OAKG;IACH,yBAAyB,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc;CAiBpF;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAExD,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;gBADR,OAAO,EAAE,aAAa,EACtB,QAAQ,EAAE,MAAM;IAG1B;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAsB7B;;;;;OAKG;IACG,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAUvC;;;;;;;OAOG;IACG,GAAG,CAAC,SAAS,SAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAWtC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAG9B"}
|
|
@@ -91,14 +91,28 @@ export class MedplumAttachmentManager extends BaseAttachmentManager {
|
|
|
91
91
|
if (!media.content || !media.id) {
|
|
92
92
|
return null;
|
|
93
93
|
}
|
|
94
|
+
// Extract Binary ID from identifier
|
|
95
|
+
const binaryIdIdentifier = media.identifier?.find((id) => id.system === 'http://vintasend.com/fhir/binary-id');
|
|
96
|
+
let binaryId = binaryIdIdentifier?.value;
|
|
97
|
+
// If binaryId not found in identifier, try to extract from content.url
|
|
98
|
+
if (!binaryId && media.content.url) {
|
|
99
|
+
const match = media.content.url.match(/Binary\/([^/]+)/);
|
|
100
|
+
if (match) {
|
|
101
|
+
binaryId = match[1];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Extract checksum from identifier
|
|
105
|
+
const checksumIdentifier = media.identifier?.find((id) => id.system === 'http://vintasend.com/fhir/attachment-checksum');
|
|
106
|
+
const checksum = checksumIdentifier?.value || '';
|
|
94
107
|
return {
|
|
95
108
|
id: media.id,
|
|
96
109
|
filename: media.content.title || 'untitled',
|
|
97
110
|
contentType: media.content.contentType || 'application/octet-stream',
|
|
98
111
|
size: media.content.size || 0,
|
|
99
|
-
checksum
|
|
112
|
+
checksum,
|
|
100
113
|
storageMetadata: {
|
|
101
114
|
url: media.content.url,
|
|
115
|
+
binaryId: binaryId,
|
|
102
116
|
creation: media.content.creation,
|
|
103
117
|
},
|
|
104
118
|
createdAt: media.meta?.lastUpdated ? new Date(media.meta.lastUpdated) : new Date(),
|
|
@@ -141,24 +155,22 @@ export class MedplumAttachmentManager extends BaseAttachmentManager {
|
|
|
141
155
|
/**
|
|
142
156
|
* Reconstruct an AttachmentFile from storage metadata.
|
|
143
157
|
*
|
|
144
|
-
* @param storageMetadata - Metadata containing
|
|
158
|
+
* @param storageMetadata - Metadata containing 'binaryId' or 'url'
|
|
145
159
|
* @returns AttachmentFile instance for accessing the file
|
|
146
160
|
*/
|
|
147
161
|
reconstructAttachmentFile(storageMetadata) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (storageMetadata.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// Binary URL format (from uploadFile)
|
|
156
|
-
binaryUrl = storageMetadata.url;
|
|
162
|
+
let binaryId = storageMetadata.binaryId;
|
|
163
|
+
// If binaryId not provided directly, try to extract from url
|
|
164
|
+
if (!binaryId && storageMetadata.url && typeof storageMetadata.url === 'string') {
|
|
165
|
+
const match = storageMetadata.url.match(/Binary\/([^/]+)/);
|
|
166
|
+
if (match) {
|
|
167
|
+
binaryId = match[1];
|
|
168
|
+
}
|
|
157
169
|
}
|
|
158
|
-
|
|
159
|
-
throw new Error('Storage metadata must contain binaryId
|
|
170
|
+
if (!binaryId) {
|
|
171
|
+
throw new Error('Storage metadata must contain binaryId or a url with Binary reference');
|
|
160
172
|
}
|
|
161
|
-
return new MedplumAttachmentFile(this.medplum,
|
|
173
|
+
return new MedplumAttachmentFile(this.medplum, binaryId);
|
|
162
174
|
}
|
|
163
175
|
}
|
|
164
176
|
/**
|
|
@@ -167,49 +179,34 @@ export class MedplumAttachmentManager extends BaseAttachmentManager {
|
|
|
167
179
|
* Provides access to files stored in Medplum Binary resources.
|
|
168
180
|
*/
|
|
169
181
|
export class MedplumAttachmentFile {
|
|
170
|
-
constructor(medplum,
|
|
182
|
+
constructor(medplum, binaryId) {
|
|
171
183
|
this.medplum = medplum;
|
|
172
|
-
|
|
173
|
-
// Supports two formats:
|
|
174
|
-
// 1. Simple reference: "Binary/{id}"
|
|
175
|
-
// 2. Full Medplum storage URL: "https://storage.medplum.com/binary/{projectId}/{binaryId}?..."
|
|
176
|
-
console.log(`[MedplumAttachmentFile] Constructing with binaryUrl: ${binaryUrl}`);
|
|
177
|
-
// Try to extract from full URL first
|
|
178
|
-
const fullUrlMatch = binaryUrl.match(/\/binary\/[^/]+\/([^/?]+)/);
|
|
179
|
-
if (fullUrlMatch) {
|
|
180
|
-
this.binaryId = fullUrlMatch[1];
|
|
181
|
-
console.log(`[MedplumAttachmentFile] Extracted binaryId from full URL: ${this.binaryId}`);
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// Fall back to simple Binary reference
|
|
185
|
-
const simpleMatch = binaryUrl.match(/Binary\/([^/]+)/);
|
|
186
|
-
if (simpleMatch) {
|
|
187
|
-
this.binaryId = simpleMatch[1];
|
|
188
|
-
console.log(`[MedplumAttachmentFile] Extracted binaryId from simple reference: ${this.binaryId}`);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
throw new Error(`Invalid Binary URL format: ${binaryUrl}`);
|
|
184
|
+
this.binaryId = binaryId;
|
|
192
185
|
}
|
|
193
186
|
/**
|
|
194
187
|
* Read the entire file into memory as a Buffer.
|
|
188
|
+
*
|
|
189
|
+
* Works with Binary resources that have either:
|
|
190
|
+
* - Inline data (base64 encoded)
|
|
191
|
+
* - A presigned URL to download from
|
|
195
192
|
*/
|
|
196
193
|
async read() {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (!binary.data) {
|
|
202
|
-
throw new Error('Binary resource has no data');
|
|
203
|
-
}
|
|
204
|
-
const buffer = Buffer.from(binary.data, 'base64');
|
|
205
|
-
console.log(`[MedplumAttachmentFile.read] Successfully converted to buffer, size: ${buffer.length} bytes`);
|
|
206
|
-
return buffer;
|
|
194
|
+
const binary = await this.medplum.readResource('Binary', this.binaryId);
|
|
195
|
+
// If data is embedded in the Binary resource, use it directly
|
|
196
|
+
if (binary.data) {
|
|
197
|
+
return Buffer.from(binary.data, 'base64');
|
|
207
198
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
199
|
+
// If data is not embedded but a URL is available, download it
|
|
200
|
+
if (binary.url) {
|
|
201
|
+
const response = await fetch(binary.url);
|
|
202
|
+
if (!response.ok) {
|
|
203
|
+
throw new Error(`Failed to download binary from URL: ${response.statusText}`);
|
|
204
|
+
}
|
|
205
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
206
|
+
return Buffer.from(arrayBuffer);
|
|
212
207
|
}
|
|
208
|
+
// Neither data nor URL available
|
|
209
|
+
throw new Error('Binary resource has neither data nor url');
|
|
213
210
|
}
|
|
214
211
|
/**
|
|
215
212
|
* Get a readable stream for the file.
|
|
@@ -229,21 +226,19 @@ export class MedplumAttachmentFile {
|
|
|
229
226
|
/**
|
|
230
227
|
* Generate a URL for accessing the file.
|
|
231
228
|
*
|
|
232
|
-
* For Medplum, this returns the Binary resource
|
|
233
|
-
* In production, you might want to generate a presigned URL.
|
|
229
|
+
* For Medplum, this returns a presigned URL from the Binary resource.
|
|
234
230
|
*
|
|
235
231
|
* @param expiresIn - Seconds until the URL expires (not used for Medplum)
|
|
236
|
-
* @returns URL for file access
|
|
232
|
+
* @returns Presigned URL for file access
|
|
237
233
|
*/
|
|
238
234
|
async url(expiresIn = 3600) {
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
235
|
+
// Fetch the Binary resource to get the presigned URL
|
|
236
|
+
const binary = await this.medplum.readResource('Binary', this.binaryId);
|
|
237
|
+
if (!binary.url) {
|
|
238
|
+
throw new Error(`Binary resource ${this.binaryId} does not have a presigned URL`);
|
|
239
|
+
}
|
|
240
|
+
return binary.url;
|
|
243
241
|
}
|
|
244
|
-
/**
|
|
245
|
-
* Delete this file from storage.
|
|
246
|
-
*/
|
|
247
242
|
async delete() {
|
|
248
243
|
await this.medplum.deleteResource('Binary', this.binaryId);
|
|
249
244
|
}
|