@intuned/browser-dev 0.1.10-dev.0 → 0.1.12-dev.0
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/helpers/export.d.ts +5 -12
- package/dist/helpers/index.d.ts +5 -12
- package/dist/helpers/tests/testDownloadFile.spec.js +41 -0
- package/dist/helpers/tests/testInjectAttachmentType.spec.js +16 -9
- package/dist/helpers/tests/testValidateDataUsingSchema.spec.js +111 -0
- package/dist/helpers/types/Attachment.js +23 -22
- package/dist/helpers/types/__tests__/Attachment.test.js +130 -0
- package/dist/helpers/validateDataUsingSchema.js +6 -2
- package/package.json +1 -1
package/dist/helpers/export.d.ts
CHANGED
|
@@ -1044,11 +1044,11 @@ export interface Attachment {
|
|
|
1044
1044
|
/** The S3 object key/path */
|
|
1045
1045
|
key: string;
|
|
1046
1046
|
|
|
1047
|
-
/** The S3 bucket name where the file is stored */
|
|
1048
|
-
bucket
|
|
1047
|
+
/** The S3 bucket name where the file is stored. Only present when using custom S3 storage. */
|
|
1048
|
+
bucket?: string;
|
|
1049
1049
|
|
|
1050
|
-
/** The AWS region where the S3 bucket is located */
|
|
1051
|
-
region
|
|
1050
|
+
/** The AWS region where the S3 bucket is located. Only present when using custom S3 storage. */
|
|
1051
|
+
region?: string;
|
|
1052
1052
|
|
|
1053
1053
|
/** Optional custom S3 endpoint URL. Defaults to undefined for standard AWS S3 */
|
|
1054
1054
|
endpoint?: string | null;
|
|
@@ -1069,7 +1069,7 @@ export interface Attachment {
|
|
|
1069
1069
|
/**
|
|
1070
1070
|
* Converts the file metadata to a record.
|
|
1071
1071
|
*
|
|
1072
|
-
* @returns `Record<string, string>` - Record with fileName, key, bucket, region, endpoint,
|
|
1072
|
+
* @returns `Record<string, string>` - Record with fileName, key, suggestedFileName, fileType, and optionally bucket, region, endpoint, signedUrl
|
|
1073
1073
|
*/
|
|
1074
1074
|
toDict(): Record<string, string>;
|
|
1075
1075
|
|
|
@@ -1080,13 +1080,6 @@ export interface Attachment {
|
|
|
1080
1080
|
*/
|
|
1081
1081
|
getS3Key(): string;
|
|
1082
1082
|
|
|
1083
|
-
/**
|
|
1084
|
-
* Returns the file path/key within the S3 bucket.
|
|
1085
|
-
*
|
|
1086
|
-
* @returns `string` - The fileName property (S3 object key)
|
|
1087
|
-
*/
|
|
1088
|
-
getFilePath(): string;
|
|
1089
|
-
|
|
1090
1083
|
/**
|
|
1091
1084
|
* Generates a presigned URL for secure, temporary access to the file.
|
|
1092
1085
|
*
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -1044,11 +1044,11 @@ export interface Attachment {
|
|
|
1044
1044
|
/** The S3 object key/path */
|
|
1045
1045
|
key: string;
|
|
1046
1046
|
|
|
1047
|
-
/** The S3 bucket name where the file is stored */
|
|
1048
|
-
bucket
|
|
1047
|
+
/** The S3 bucket name where the file is stored. Only present when using custom S3 storage. */
|
|
1048
|
+
bucket?: string;
|
|
1049
1049
|
|
|
1050
|
-
/** The AWS region where the S3 bucket is located */
|
|
1051
|
-
region
|
|
1050
|
+
/** The AWS region where the S3 bucket is located. Only present when using custom S3 storage. */
|
|
1051
|
+
region?: string;
|
|
1052
1052
|
|
|
1053
1053
|
/** Optional custom S3 endpoint URL. Defaults to undefined for standard AWS S3 */
|
|
1054
1054
|
endpoint?: string | null;
|
|
@@ -1069,7 +1069,7 @@ export interface Attachment {
|
|
|
1069
1069
|
/**
|
|
1070
1070
|
* Converts the file metadata to a record.
|
|
1071
1071
|
*
|
|
1072
|
-
* @returns `Record<string, string>` - Record with fileName, key, bucket, region, endpoint,
|
|
1072
|
+
* @returns `Record<string, string>` - Record with fileName, key, suggestedFileName, fileType, and optionally bucket, region, endpoint, signedUrl
|
|
1073
1073
|
*/
|
|
1074
1074
|
toDict(): Record<string, string>;
|
|
1075
1075
|
|
|
@@ -1080,13 +1080,6 @@ export interface Attachment {
|
|
|
1080
1080
|
*/
|
|
1081
1081
|
getS3Key(): string;
|
|
1082
1082
|
|
|
1083
|
-
/**
|
|
1084
|
-
* Returns the file path/key within the S3 bucket.
|
|
1085
|
-
*
|
|
1086
|
-
* @returns `string` - The fileName property (S3 object key)
|
|
1087
|
-
*/
|
|
1088
|
-
getFilePath(): string;
|
|
1089
|
-
|
|
1090
1083
|
/**
|
|
1091
1084
|
* Generates a presigned URL for secure, temporary access to the file.
|
|
1092
1085
|
*
|
|
@@ -224,6 +224,47 @@ _extendedTest.describe.skip("TestNotInGeneration", () => {
|
|
|
224
224
|
(0, _extendedTest.expect)(uploadedFile.bucket).toBe("testing_bucket");
|
|
225
225
|
(0, _extendedTest.expect)(uploadedFile.region).toBe("testing_region");
|
|
226
226
|
});
|
|
227
|
+
(0, _extendedTest.test)("should upload Buffer to s3 in generate mode", async () => {
|
|
228
|
+
const buffer = Buffer.from("hello world");
|
|
229
|
+
const uploadedFile = await (0, _.uploadFileToS3)({
|
|
230
|
+
file: buffer,
|
|
231
|
+
fileNameOverride: "test-file.txt"
|
|
232
|
+
});
|
|
233
|
+
(0, _extendedTest.expect)(uploadedFile).toBeDefined();
|
|
234
|
+
(0, _extendedTest.expect)(uploadedFile.suggestedFileName).toBeDefined();
|
|
235
|
+
(0, _extendedTest.expect)(uploadedFile.bucket).toBe("testing_bucket");
|
|
236
|
+
(0, _extendedTest.expect)(uploadedFile.region).toBe("testing_region");
|
|
237
|
+
});
|
|
238
|
+
(0, _extendedTest.test)("uploaded attachment toDict has no null fields", async () => {
|
|
239
|
+
await page.setContent(content);
|
|
240
|
+
const download = await (0, _.downloadFile)({
|
|
241
|
+
page,
|
|
242
|
+
trigger: "https://intuned-docs-public-images.s3.amazonaws.com/32UP83A_ENG_US.pdf"
|
|
243
|
+
});
|
|
244
|
+
const uploadedFile = await (0, _.uploadFileToS3)({
|
|
245
|
+
file: download
|
|
246
|
+
});
|
|
247
|
+
const dict = uploadedFile.toDict();
|
|
248
|
+
for (const [key, value] of Object.entries(dict)) {
|
|
249
|
+
(0, _extendedTest.expect)(value).not.toBeNull();
|
|
250
|
+
(0, _extendedTest.expect)(value).not.toBeUndefined();
|
|
251
|
+
}
|
|
252
|
+
(0, _extendedTest.expect)(dict.fileName).toBeDefined();
|
|
253
|
+
(0, _extendedTest.expect)(dict.key).toBeDefined();
|
|
254
|
+
(0, _extendedTest.expect)(dict.suggestedFileName).toBeDefined();
|
|
255
|
+
});
|
|
256
|
+
(0, _extendedTest.test)("getSignedUrl returns mock URL in generate_code mode", async () => {
|
|
257
|
+
await page.setContent(content);
|
|
258
|
+
const download = await (0, _.downloadFile)({
|
|
259
|
+
page,
|
|
260
|
+
trigger: "https://intuned-docs-public-images.s3.amazonaws.com/32UP83A_ENG_US.pdf"
|
|
261
|
+
});
|
|
262
|
+
const uploadedFile = await (0, _.uploadFileToS3)({
|
|
263
|
+
file: download
|
|
264
|
+
});
|
|
265
|
+
const signedUrl = await uploadedFile.getSignedUrl();
|
|
266
|
+
(0, _extendedTest.expect)(signedUrl).toBe("https://not.real.com");
|
|
267
|
+
});
|
|
227
268
|
(0, _extendedTest.test)("should download from print dialog", async () => {
|
|
228
269
|
await page.setContent(content);
|
|
229
270
|
const printButton = page.locator("#print-button");
|
|
@@ -19,7 +19,8 @@ var _validateDataUsingSchema = require("../validateDataUsingSchema");
|
|
|
19
19
|
const result = (0, _validateDataUsingSchema.injectAttachmentType)(schema);
|
|
20
20
|
(0, _extendedTest.expect)(result.$defs).toBeDefined();
|
|
21
21
|
(0, _extendedTest.expect)(result.$defs.attachment).toBeDefined();
|
|
22
|
-
(0, _extendedTest.expect)(result.$defs.attachment.
|
|
22
|
+
(0, _extendedTest.expect)(result.$defs.attachment.anyOf).toBeDefined();
|
|
23
|
+
(0, _extendedTest.expect)(result.$defs.attachment.anyOf.length).toBe(2);
|
|
23
24
|
(0, _extendedTest.expect)(result.properties.file).toEqual({
|
|
24
25
|
$ref: "#/$defs/attachment"
|
|
25
26
|
});
|
|
@@ -463,20 +464,26 @@ var _validateDataUsingSchema = require("../validateDataUsingSchema");
|
|
|
463
464
|
};
|
|
464
465
|
const result = (0, _validateDataUsingSchema.injectAttachmentType)(schema);
|
|
465
466
|
(0, _extendedTest.expect)(result.$defs.attachment).toBeDefined();
|
|
466
|
-
(0, _extendedTest.expect)(result.$defs.attachment.
|
|
467
|
-
|
|
467
|
+
(0, _extendedTest.expect)(result.$defs.attachment.anyOf).toBeDefined();
|
|
468
|
+
(0, _extendedTest.expect)(result.$defs.attachment.anyOf.length).toBe(2);
|
|
469
|
+
const baseSchema = result.$defs.attachment.anyOf[1];
|
|
470
|
+
(0, _extendedTest.expect)(baseSchema.type).toBe("object");
|
|
471
|
+
const attachmentProps = baseSchema.properties;
|
|
468
472
|
(0, _extendedTest.expect)(attachmentProps).toBeDefined();
|
|
469
473
|
(0, _extendedTest.expect)(attachmentProps.fileName).toBeDefined();
|
|
470
474
|
(0, _extendedTest.expect)(attachmentProps.bucket).toBeDefined();
|
|
471
475
|
(0, _extendedTest.expect)(attachmentProps.region).toBeDefined();
|
|
472
476
|
(0, _extendedTest.expect)(attachmentProps.key).toBeDefined();
|
|
473
477
|
(0, _extendedTest.expect)(attachmentProps.suggestedFileName).toBeDefined();
|
|
474
|
-
(0, _extendedTest.expect)(
|
|
475
|
-
(0, _extendedTest.expect)(
|
|
476
|
-
(0, _extendedTest.expect)(
|
|
477
|
-
(0, _extendedTest.expect)(
|
|
478
|
-
(0, _extendedTest.expect)(
|
|
479
|
-
(0, _extendedTest.expect)(
|
|
478
|
+
(0, _extendedTest.expect)(baseSchema.required).toBeDefined();
|
|
479
|
+
(0, _extendedTest.expect)(baseSchema.required).toContain("fileName");
|
|
480
|
+
(0, _extendedTest.expect)(baseSchema.required).toContain("bucket");
|
|
481
|
+
(0, _extendedTest.expect)(baseSchema.required).toContain("region");
|
|
482
|
+
(0, _extendedTest.expect)(baseSchema.required).toContain("key");
|
|
483
|
+
(0, _extendedTest.expect)(baseSchema.required).toContain("suggestedFileName");
|
|
484
|
+
const signedUrlSchema = result.$defs.attachment.anyOf[0];
|
|
485
|
+
(0, _extendedTest.expect)(signedUrlSchema.type).toBe("object");
|
|
486
|
+
(0, _extendedTest.expect)(signedUrlSchema.properties.downloadSignedUrl).toBeDefined();
|
|
480
487
|
});
|
|
481
488
|
});
|
|
482
489
|
});
|
|
@@ -1297,6 +1297,117 @@ var _extendedTest = require("../../common/extendedTest");
|
|
|
1297
1297
|
schema
|
|
1298
1298
|
})).not.toThrow();
|
|
1299
1299
|
});
|
|
1300
|
+
(0, _extendedTest.test)("should validate SignedUrlAttachment instance", async () => {
|
|
1301
|
+
const schema = {
|
|
1302
|
+
type: "object",
|
|
1303
|
+
properties: {
|
|
1304
|
+
file: {
|
|
1305
|
+
type: "Attachment"
|
|
1306
|
+
},
|
|
1307
|
+
name: {
|
|
1308
|
+
type: "string"
|
|
1309
|
+
}
|
|
1310
|
+
},
|
|
1311
|
+
required: ["file", "name"]
|
|
1312
|
+
};
|
|
1313
|
+
const signed = new _Attachment.SignedUrlAttachment("report.pdf", "https://my-bucket.s3.us-east-1.amazonaws.com/files/report.pdf?X-Amz-Signature=abc123", "Monthly Report.pdf");
|
|
1314
|
+
(0, _extendedTest.expect)(() => (0, _validateDataUsingSchema.validateDataUsingSchema)({
|
|
1315
|
+
data: {
|
|
1316
|
+
file: signed,
|
|
1317
|
+
name: "Signed URL file"
|
|
1318
|
+
},
|
|
1319
|
+
schema
|
|
1320
|
+
})).not.toThrow();
|
|
1321
|
+
const dict = signed.toDict();
|
|
1322
|
+
(0, _extendedTest.expect)(dict).toHaveProperty("signedUrl");
|
|
1323
|
+
(0, _extendedTest.expect)(dict.signedUrl).toBe("https://my-bucket.s3.us-east-1.amazonaws.com/files/report.pdf?X-Amz-Signature=abc123");
|
|
1324
|
+
(0, _extendedTest.expect)(dict.bucket).toBeUndefined();
|
|
1325
|
+
(0, _extendedTest.expect)(dict.region).toBeUndefined();
|
|
1326
|
+
});
|
|
1327
|
+
(0, _extendedTest.test)("should validate array of SignedUrlAttachment instances", async () => {
|
|
1328
|
+
const schema = {
|
|
1329
|
+
type: "object",
|
|
1330
|
+
properties: {
|
|
1331
|
+
title: {
|
|
1332
|
+
type: "string"
|
|
1333
|
+
},
|
|
1334
|
+
documents: {
|
|
1335
|
+
type: "array",
|
|
1336
|
+
items: {
|
|
1337
|
+
type: "Attachment"
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
},
|
|
1341
|
+
required: ["title", "documents"]
|
|
1342
|
+
};
|
|
1343
|
+
const data = {
|
|
1344
|
+
title: "Project Files",
|
|
1345
|
+
documents: [new _Attachment.SignedUrlAttachment("doc1.pdf", "https://bucket.r2.cloudflarestorage.com/doc1.pdf?sig=aaa", "Document 1.pdf"), new _Attachment.SignedUrlAttachment("doc2.pdf", "https://bucket.r2.cloudflarestorage.com/doc2.pdf?sig=bbb", "Document 2.pdf")]
|
|
1346
|
+
};
|
|
1347
|
+
(0, _extendedTest.expect)(() => (0, _validateDataUsingSchema.validateDataUsingSchema)({
|
|
1348
|
+
data,
|
|
1349
|
+
schema
|
|
1350
|
+
})).not.toThrow();
|
|
1351
|
+
});
|
|
1352
|
+
(0, _extendedTest.test)("should validate mixed Attachment and SignedUrlAttachment instances", async () => {
|
|
1353
|
+
const schema = {
|
|
1354
|
+
type: "object",
|
|
1355
|
+
properties: {
|
|
1356
|
+
name: {
|
|
1357
|
+
type: "string"
|
|
1358
|
+
},
|
|
1359
|
+
s3File: {
|
|
1360
|
+
type: "Attachment"
|
|
1361
|
+
},
|
|
1362
|
+
intunedFile: {
|
|
1363
|
+
type: "Attachment"
|
|
1364
|
+
},
|
|
1365
|
+
optionalFile: {
|
|
1366
|
+
type: ["Attachment", "null"]
|
|
1367
|
+
}
|
|
1368
|
+
},
|
|
1369
|
+
required: ["name", "s3File", "intunedFile", "optionalFile"]
|
|
1370
|
+
};
|
|
1371
|
+
const data = {
|
|
1372
|
+
name: "Mixed storage",
|
|
1373
|
+
s3File: new _Attachment.Attachment("report.pdf", "files/report.pdf", "my-bucket", "us-east-1", "Report.pdf", null, "document"),
|
|
1374
|
+
intunedFile: new _Attachment.SignedUrlAttachment("invoice.pdf", "https://bucket.r2.cloudflarestorage.com/invoice.pdf?sig=xyz", "Invoice.pdf"),
|
|
1375
|
+
optionalFile: null
|
|
1376
|
+
};
|
|
1377
|
+
(0, _extendedTest.expect)(() => (0, _validateDataUsingSchema.validateDataUsingSchema)({
|
|
1378
|
+
data,
|
|
1379
|
+
schema
|
|
1380
|
+
})).not.toThrow();
|
|
1381
|
+
});
|
|
1382
|
+
(0, _extendedTest.test)("should validate nullable SignedUrlAttachment", async () => {
|
|
1383
|
+
const schema = {
|
|
1384
|
+
type: "object",
|
|
1385
|
+
properties: {
|
|
1386
|
+
file: {
|
|
1387
|
+
type: ["Attachment", "null"]
|
|
1388
|
+
},
|
|
1389
|
+
name: {
|
|
1390
|
+
type: "string"
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1393
|
+
required: ["file", "name"]
|
|
1394
|
+
};
|
|
1395
|
+
const signed = new _Attachment.SignedUrlAttachment("report.pdf", "https://bucket.r2.cloudflarestorage.com/report.pdf?sig=abc", "Report.pdf");
|
|
1396
|
+
(0, _extendedTest.expect)(() => (0, _validateDataUsingSchema.validateDataUsingSchema)({
|
|
1397
|
+
data: {
|
|
1398
|
+
file: signed,
|
|
1399
|
+
name: "With file"
|
|
1400
|
+
},
|
|
1401
|
+
schema
|
|
1402
|
+
})).not.toThrow();
|
|
1403
|
+
(0, _extendedTest.expect)(() => (0, _validateDataUsingSchema.validateDataUsingSchema)({
|
|
1404
|
+
data: {
|
|
1405
|
+
file: null,
|
|
1406
|
+
name: "Without file"
|
|
1407
|
+
},
|
|
1408
|
+
schema
|
|
1409
|
+
})).not.toThrow();
|
|
1410
|
+
});
|
|
1300
1411
|
(0, _extendedTest.test)("should format error messages with multiple errors correctly", async () => {
|
|
1301
1412
|
const schema = {
|
|
1302
1413
|
type: "object",
|
|
@@ -13,8 +13,8 @@ const AttachmentTypeSchema = exports.AttachmentTypeSchema = _zod.z.literal("docu
|
|
|
13
13
|
const AttachmentSchema = exports.AttachmentSchema = _zod.z.object({
|
|
14
14
|
fileName: _zod.z.string(),
|
|
15
15
|
key: _zod.z.string(),
|
|
16
|
-
bucket: _zod.z.string(),
|
|
17
|
-
region: _zod.z.string(),
|
|
16
|
+
bucket: _zod.z.string().optional(),
|
|
17
|
+
region: _zod.z.string().optional(),
|
|
18
18
|
suggestedFileName: _zod.z.string(),
|
|
19
19
|
endpoint: _zod.z.string().nullable().optional(),
|
|
20
20
|
fileType: AttachmentTypeSchema.optional().nullable()
|
|
@@ -34,7 +34,6 @@ class Attachment {
|
|
|
34
34
|
this.key = validatedData.key;
|
|
35
35
|
this.bucket = validatedData.bucket;
|
|
36
36
|
this.region = validatedData.region;
|
|
37
|
-
this.key = validatedData.key;
|
|
38
37
|
this.suggestedFileName = validatedData.suggestedFileName;
|
|
39
38
|
this.endpoint = validatedData.endpoint;
|
|
40
39
|
this.fileType = validatedData.fileType;
|
|
@@ -46,9 +45,13 @@ class Attachment {
|
|
|
46
45
|
return {
|
|
47
46
|
fileName: this.fileName,
|
|
48
47
|
key: this.key,
|
|
49
|
-
bucket: this.bucket,
|
|
50
|
-
region: this.region,
|
|
51
48
|
suggestedFileName: this.suggestedFileName,
|
|
49
|
+
...(this.bucket ? {
|
|
50
|
+
bucket: this.bucket
|
|
51
|
+
} : {}),
|
|
52
|
+
...(this.region ? {
|
|
53
|
+
region: this.region
|
|
54
|
+
} : {}),
|
|
52
55
|
...(this.endpoint ? {
|
|
53
56
|
endpoint: this.endpoint
|
|
54
57
|
} : {}),
|
|
@@ -65,6 +68,9 @@ class Attachment {
|
|
|
65
68
|
if ((0, _utils.isGenerateCodeMode)()) {
|
|
66
69
|
return "https://not.real.com";
|
|
67
70
|
}
|
|
71
|
+
if (!this.bucket || !this.region) {
|
|
72
|
+
throw new Error("bucket and region are required to generate a signed URL");
|
|
73
|
+
}
|
|
68
74
|
const s3Client = (0, _getS3Client.getS3Client)(this.endpoint ?? undefined, this.region);
|
|
69
75
|
try {
|
|
70
76
|
const response = await (0, _s3RequestPresigner.getSignedUrl)(s3Client, new _clientS.GetObjectCommand({
|
|
@@ -80,41 +86,36 @@ class Attachment {
|
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
getS3Key() {
|
|
89
|
+
if (!this.bucket || !this.region) {
|
|
90
|
+
throw new Error("bucket and region are required to get the S3 key");
|
|
91
|
+
}
|
|
83
92
|
return `https://${this.bucket}.s3.${this.region}.amazonaws.com/${this.fileName}`;
|
|
84
93
|
}
|
|
85
|
-
getFilePath() {
|
|
86
|
-
return this.fileName;
|
|
87
|
-
}
|
|
88
94
|
getFileType() {
|
|
89
95
|
return this.fileType || "";
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
exports.Attachment = Attachment;
|
|
93
99
|
const SignedUrlAttachmentSchema = exports.SignedUrlAttachmentSchema = AttachmentSchema.extend({
|
|
94
|
-
|
|
100
|
+
signedUrl: _zod.z.string().url()
|
|
95
101
|
});
|
|
96
102
|
class SignedUrlAttachment extends Attachment {
|
|
97
|
-
constructor(fileName,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const key = url.pathname.substring(1);
|
|
101
|
-
const validatedUrl = _zod.z.string().url().parse(downloadSignedUrl);
|
|
102
|
-
super(fileName, key, bucket, "", suggestedFileName ?? fileName);
|
|
103
|
-
this.downloadSignedUrl = validatedUrl;
|
|
104
|
-
}
|
|
105
|
-
async getSignedUrl() {
|
|
106
|
-
return this.downloadSignedUrl;
|
|
103
|
+
constructor(fileName, signedUrl, suggestedFileName) {
|
|
104
|
+
super(fileName, fileName, undefined, undefined, suggestedFileName ?? fileName);
|
|
105
|
+
this.signedUrl = _zod.z.string().url().parse(signedUrl);
|
|
107
106
|
}
|
|
108
107
|
toDict() {
|
|
109
108
|
return {
|
|
110
109
|
...super.toDict(),
|
|
111
|
-
|
|
110
|
+
signedUrl: this.signedUrl
|
|
112
111
|
};
|
|
113
112
|
}
|
|
113
|
+
async getSignedUrl() {
|
|
114
|
+
return this.signedUrl;
|
|
115
|
+
}
|
|
114
116
|
static fromDict(data) {
|
|
115
117
|
const validatedData = SignedUrlAttachmentSchema.parse(data);
|
|
116
|
-
|
|
117
|
-
return attachment;
|
|
118
|
+
return new SignedUrlAttachment(validatedData.fileName, validatedData.signedUrl, validatedData.suggestedFileName);
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
exports.SignedUrlAttachment = SignedUrlAttachment;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _vitest = require("vitest");
|
|
4
|
+
var _Attachment = require("../Attachment");
|
|
5
|
+
const SIGNED_URL = "https://bucket.r2.cloudflarestorage.com/file.pdf?X-Amz-Signature=abc";
|
|
6
|
+
(0, _vitest.describe)("Attachment", () => {
|
|
7
|
+
(0, _vitest.test)("stores required fields", () => {
|
|
8
|
+
const a = new _Attachment.Attachment("files/report.pdf", "files/report.pdf", "my-bucket", "us-east-1", "Report.pdf");
|
|
9
|
+
(0, _vitest.expect)(a.fileName).toBe("files/report.pdf");
|
|
10
|
+
(0, _vitest.expect)(a.key).toBe("files/report.pdf");
|
|
11
|
+
(0, _vitest.expect)(a.bucket).toBe("my-bucket");
|
|
12
|
+
(0, _vitest.expect)(a.region).toBe("us-east-1");
|
|
13
|
+
(0, _vitest.expect)(a.suggestedFileName).toBe("Report.pdf");
|
|
14
|
+
});
|
|
15
|
+
(0, _vitest.test)("endpoint defaults to undefined", () => {
|
|
16
|
+
const a = new _Attachment.Attachment("f", "f", "b", "r", "s");
|
|
17
|
+
(0, _vitest.expect)(a.endpoint).toBeUndefined();
|
|
18
|
+
});
|
|
19
|
+
(0, _vitest.test)("toDict includes s3 fields", () => {
|
|
20
|
+
const a = new _Attachment.Attachment("files/report.pdf", "files/report.pdf", "my-bucket", "us-east-1", "Report.pdf");
|
|
21
|
+
const d = a.toDict();
|
|
22
|
+
(0, _vitest.expect)(d.bucket).toBe("my-bucket");
|
|
23
|
+
(0, _vitest.expect)(d.region).toBe("us-east-1");
|
|
24
|
+
(0, _vitest.expect)(d.fileName).toBe("files/report.pdf");
|
|
25
|
+
(0, _vitest.expect)(d.suggestedFileName).toBe("Report.pdf");
|
|
26
|
+
});
|
|
27
|
+
(0, _vitest.test)("toDict omits endpoint when not set", () => {
|
|
28
|
+
const a = new _Attachment.Attachment("f", "f", "b", "r", "s");
|
|
29
|
+
(0, _vitest.expect)(a.toDict().endpoint).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
(0, _vitest.test)("toDict includes endpoint when set", () => {
|
|
32
|
+
const a = new _Attachment.Attachment("f", "f", "b", "r", "s", "https://custom.s3.com");
|
|
33
|
+
(0, _vitest.expect)(a.toDict().endpoint).toBe("https://custom.s3.com");
|
|
34
|
+
});
|
|
35
|
+
(0, _vitest.test)("toJSON matches toDict", () => {
|
|
36
|
+
const a = new _Attachment.Attachment("f", "f", "b", "r", "s");
|
|
37
|
+
(0, _vitest.expect)(a.toJSON()).toEqual(a.toDict());
|
|
38
|
+
});
|
|
39
|
+
(0, _vitest.test)("fromDict round-trips", () => {
|
|
40
|
+
const a = new _Attachment.Attachment("files/report.pdf", "files/report.pdf", "my-bucket", "us-east-1", "Report.pdf");
|
|
41
|
+
const restored = _Attachment.Attachment.fromDict(a.toDict());
|
|
42
|
+
(0, _vitest.expect)(restored.bucket).toBe(a.bucket);
|
|
43
|
+
(0, _vitest.expect)(restored.region).toBe(a.region);
|
|
44
|
+
(0, _vitest.expect)(restored.fileName).toBe(a.fileName);
|
|
45
|
+
});
|
|
46
|
+
(0, _vitest.test)("getS3Key builds correct URL", () => {
|
|
47
|
+
const a = new _Attachment.Attachment("x.pdf", "x.pdf", "my-bucket", "us-east-1", "x.pdf");
|
|
48
|
+
(0, _vitest.expect)(a.getS3Key()).toBe("https://my-bucket.s3.us-east-1.amazonaws.com/x.pdf");
|
|
49
|
+
});
|
|
50
|
+
(0, _vitest.test)("getS3Key throws when bucket or region missing", () => {
|
|
51
|
+
const a = new _Attachment.Attachment("f", "f", undefined, undefined, "s");
|
|
52
|
+
(0, _vitest.expect)(() => a.getS3Key()).toThrow();
|
|
53
|
+
});
|
|
54
|
+
(0, _vitest.test)("does not have signedUrl field", () => {
|
|
55
|
+
const a = new _Attachment.Attachment("f", "f", "b", "r", "s");
|
|
56
|
+
(0, _vitest.expect)(a.signedUrl).toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
(0, _vitest.describe)("SignedUrlAttachment", () => {
|
|
60
|
+
(0, _vitest.test)("stores fields correctly", () => {
|
|
61
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL, "Report.pdf");
|
|
62
|
+
(0, _vitest.expect)(s.fileName).toBe("report.pdf");
|
|
63
|
+
(0, _vitest.expect)(s.suggestedFileName).toBe("Report.pdf");
|
|
64
|
+
(0, _vitest.expect)(s.signedUrl).toBe(SIGNED_URL);
|
|
65
|
+
});
|
|
66
|
+
(0, _vitest.test)("suggestedFileName falls back to fileName", () => {
|
|
67
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL);
|
|
68
|
+
(0, _vitest.expect)(s.suggestedFileName).toBe("report.pdf");
|
|
69
|
+
});
|
|
70
|
+
(0, _vitest.test)("toDict exposes signedUrl", () => {
|
|
71
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL, "Report.pdf");
|
|
72
|
+
(0, _vitest.expect)(s.toDict().signedUrl).toBe(SIGNED_URL);
|
|
73
|
+
});
|
|
74
|
+
(0, _vitest.test)("toDict does not include bucket or region", () => {
|
|
75
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL, "Report.pdf");
|
|
76
|
+
const d = s.toDict();
|
|
77
|
+
(0, _vitest.expect)(d.bucket).toBeUndefined();
|
|
78
|
+
(0, _vitest.expect)(d.region).toBeUndefined();
|
|
79
|
+
});
|
|
80
|
+
(0, _vitest.test)("toJSON matches toDict", () => {
|
|
81
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL, "Report.pdf");
|
|
82
|
+
(0, _vitest.expect)(s.toJSON()).toEqual(s.toDict());
|
|
83
|
+
});
|
|
84
|
+
(0, _vitest.test)("getSignedUrl returns the signed URL", async () => {
|
|
85
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL, "Report.pdf");
|
|
86
|
+
(0, _vitest.expect)(await s.getSignedUrl()).toBe(SIGNED_URL);
|
|
87
|
+
});
|
|
88
|
+
(0, _vitest.test)("fromDict round-trips", () => {
|
|
89
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL, "Report.pdf");
|
|
90
|
+
const restored = _Attachment.SignedUrlAttachment.fromDict(s.toDict());
|
|
91
|
+
(0, _vitest.expect)(restored.signedUrl).toBe(SIGNED_URL);
|
|
92
|
+
(0, _vitest.expect)(restored.fileName).toBe("report.pdf");
|
|
93
|
+
(0, _vitest.expect)(restored.suggestedFileName).toBe("Report.pdf");
|
|
94
|
+
});
|
|
95
|
+
(0, _vitest.test)("is instance of Attachment", () => {
|
|
96
|
+
const s = new _Attachment.SignedUrlAttachment("report.pdf", SIGNED_URL);
|
|
97
|
+
(0, _vitest.expect)(s instanceof _Attachment.Attachment).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
(0, _vitest.test)("rejects invalid signed URL", () => {
|
|
100
|
+
(0, _vitest.expect)(() => new _Attachment.SignedUrlAttachment("f", "not-a-url")).toThrow();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
(0, _vitest.describe)("toDict null/undefined exclusion", () => {
|
|
104
|
+
(0, _vitest.test)("Attachment with S3 fields includes bucket and region", () => {
|
|
105
|
+
const a = new _Attachment.Attachment("f.pdf", "f.pdf", "my-bucket", "us-east-1", "f.pdf");
|
|
106
|
+
const d = a.toDict();
|
|
107
|
+
(0, _vitest.expect)(d.bucket).toBe("my-bucket");
|
|
108
|
+
(0, _vitest.expect)(d.region).toBe("us-east-1");
|
|
109
|
+
(0, _vitest.expect)(d.endpoint).toBeUndefined();
|
|
110
|
+
});
|
|
111
|
+
(0, _vitest.test)("Attachment without S3 fields omits bucket and region", () => {
|
|
112
|
+
const a = new _Attachment.Attachment("f.pdf", "f.pdf", undefined, undefined, "f.pdf");
|
|
113
|
+
const d = a.toDict();
|
|
114
|
+
(0, _vitest.expect)(d.bucket).toBeUndefined();
|
|
115
|
+
(0, _vitest.expect)(d.region).toBeUndefined();
|
|
116
|
+
(0, _vitest.expect)(d.endpoint).toBeUndefined();
|
|
117
|
+
});
|
|
118
|
+
(0, _vitest.test)("SignedUrlAttachment omits bucket and region, exposes signedUrl", () => {
|
|
119
|
+
const s = new _Attachment.SignedUrlAttachment("f.pdf", SIGNED_URL, "f.pdf");
|
|
120
|
+
const d = s.toDict();
|
|
121
|
+
(0, _vitest.expect)(d.bucket).toBeUndefined();
|
|
122
|
+
(0, _vitest.expect)(d.region).toBeUndefined();
|
|
123
|
+
(0, _vitest.expect)(d.endpoint).toBeUndefined();
|
|
124
|
+
(0, _vitest.expect)(d.signedUrl).toBe(SIGNED_URL);
|
|
125
|
+
});
|
|
126
|
+
(0, _vitest.test)("toJSON matches toDict for SignedUrlAttachment", () => {
|
|
127
|
+
const s = new _Attachment.SignedUrlAttachment("f.pdf", SIGNED_URL, "f.pdf");
|
|
128
|
+
(0, _vitest.expect)(s.toJSON()).toEqual(s.toDict());
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -21,11 +21,15 @@ function injectAttachmentType(schema) {
|
|
|
21
21
|
const attachmentJsonSchema = (0, _zodToJsonSchema.zodToJsonSchema)(_Attachment.AttachmentSchema, {
|
|
22
22
|
$refStrategy: "none"
|
|
23
23
|
});
|
|
24
|
-
const
|
|
24
|
+
const signedUrlAttachmentJsonSchema = (0, _zodToJsonSchema.zodToJsonSchema)(_Attachment.SignedUrlAttachmentSchema, {
|
|
25
|
+
$refStrategy: "none"
|
|
26
|
+
});
|
|
25
27
|
if (!schemaCopy.$defs) {
|
|
26
28
|
schemaCopy.$defs = {};
|
|
27
29
|
}
|
|
28
|
-
schemaCopy.$defs.attachment =
|
|
30
|
+
schemaCopy.$defs.attachment = {
|
|
31
|
+
anyOf: [signedUrlAttachmentJsonSchema, attachmentJsonSchema]
|
|
32
|
+
};
|
|
29
33
|
function replaceAttachmentType(node) {
|
|
30
34
|
if (typeof node !== "object" || node === null) {
|
|
31
35
|
return node;
|