@intuned/browser-dev 0.1.10-dev.0 → 0.1.13-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.
@@ -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: string;
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: string;
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, suggestedFileName, and fileType
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
  *
@@ -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: string;
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: string;
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, suggestedFileName, and fileType
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.type).toBe("object");
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,28 @@ 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.type).toBe("object");
467
- const attachmentProps = result.$defs.attachment.properties;
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)(result.$defs.attachment.required).toBeDefined();
475
- (0, _extendedTest.expect)(result.$defs.attachment.required).toContain("fileName");
476
- (0, _extendedTest.expect)(result.$defs.attachment.required).toContain("bucket");
477
- (0, _extendedTest.expect)(result.$defs.attachment.required).toContain("region");
478
- (0, _extendedTest.expect)(result.$defs.attachment.required).toContain("key");
479
- (0, _extendedTest.expect)(result.$defs.attachment.required).toContain("suggestedFileName");
478
+ (0, _extendedTest.expect)(baseSchema.required).toBeDefined();
479
+ (0, _extendedTest.expect)(baseSchema.required).toContain("fileName");
480
+ (0, _extendedTest.expect)(baseSchema.required).not.toContain("bucket");
481
+ (0, _extendedTest.expect)(baseSchema.required).not.toContain("region");
482
+ (0, _extendedTest.expect)(baseSchema.required).toContain("key");
483
+ (0, _extendedTest.expect)(baseSchema.required).toContain("suggestedFileName");
484
+ (0, _extendedTest.expect)(attachmentProps.bucket).toBeDefined();
485
+ (0, _extendedTest.expect)(attachmentProps.region).toBeDefined();
486
+ const signedUrlSchema = result.$defs.attachment.anyOf[0];
487
+ (0, _extendedTest.expect)(signedUrlSchema.type).toBe("object");
488
+ (0, _extendedTest.expect)(signedUrlSchema.properties.signedUrl).toBeDefined();
480
489
  });
481
490
  });
482
491
  });
@@ -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
- downloadSignedUrl: _zod.z.string().url()
100
+ signedUrl: _zod.z.string().url()
95
101
  });
96
102
  class SignedUrlAttachment extends Attachment {
97
- constructor(fileName, downloadSignedUrl, suggestedFileName) {
98
- const url = new URL(downloadSignedUrl);
99
- const bucket = url.hostname.split(".")[0];
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
- downloadSignedUrl: this.downloadSignedUrl
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
- const attachment = new SignedUrlAttachment(validatedData.fileName, validatedData.downloadSignedUrl, validatedData.suggestedFileName);
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 attachmentDefinition = typeof attachmentJsonSchema === "object" && attachmentJsonSchema !== null ? attachmentJsonSchema : {};
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 = attachmentDefinition;
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;
@@ -88,16 +88,15 @@ class APIGateway {
88
88
  const modelLower = model.toLowerCase();
89
89
  return (0, _getModelProvider.getModelProvider)(modelLower);
90
90
  }
91
- buildGatewayUrl(provider) {
91
+ buildGatewayUrl() {
92
92
  var _this$config$function;
93
93
  if (!this.config) {
94
94
  throw new Error("Gateway configuration not initialized");
95
95
  }
96
96
  const baseDomain = (_this$config$function = this.config.functionsDomain) === null || _this$config$function === void 0 ? void 0 : _this$config$function.replace(/\/$/, "");
97
- return `${baseDomain}/api/${this.config.workspaceId}/functions/${this.config.integrationId}/${provider === "anthropic" ? "anthropic/v1" : provider === "google_vertexai" ? "google_vertexai/v1beta" : provider}`;
97
+ return `${baseDomain}/api/${this.config.workspaceId}/functions/${this.config.integrationId}/intuned-ai-gateway`;
98
98
  }
99
99
  getModelConfig(extraHeaders) {
100
- const provider = this.detectProvider(this.model);
101
100
  if (!this.useGateway && this.apiKey) {
102
101
  return {
103
102
  model: this.model,
@@ -106,7 +105,7 @@ class APIGateway {
106
105
  baseUrl: undefined
107
106
  };
108
107
  }
109
- const baseUrl = this.buildGatewayUrl(provider);
108
+ const baseUrl = this.buildGatewayUrl();
110
109
  return {
111
110
  model: this.model,
112
111
  apiKey: "--THIS_VALUE_WILL_BE_REPLACED_BY_INTUNED_BE--",
@@ -118,8 +118,8 @@ const mockLoadRuntime = _vitest.vi.mocked(_loadRuntime.loadRuntime);
118
118
  model: "claude-3-sonnet"
119
119
  });
120
120
  await gateway["ensureInitialized"]();
121
- const result = gateway["buildGatewayUrl"]("anthropic");
122
- (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/anthropic/v1");
121
+ const result = gateway["buildGatewayUrl"]();
122
+ (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/intuned-ai-gateway");
123
123
  });
124
124
  (0, _extendedTest.it)("should build correct URL for google_vertexai", async () => {
125
125
  mockGetModelProvider.mockReturnValue("google_vertexai");
@@ -130,8 +130,8 @@ const mockLoadRuntime = _vitest.vi.mocked(_loadRuntime.loadRuntime);
130
130
  model: "gemini-pro"
131
131
  });
132
132
  await gateway["ensureInitialized"]();
133
- const result = gateway["buildGatewayUrl"]("google_vertexai");
134
- (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/google_vertexai/v1beta");
133
+ const result = gateway["buildGatewayUrl"]();
134
+ (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/intuned-ai-gateway");
135
135
  });
136
136
  (0, _extendedTest.it)("should build correct URL for other providers", async () => {
137
137
  mockGetModelProvider.mockReturnValue("openai");
@@ -142,8 +142,8 @@ const mockLoadRuntime = _vitest.vi.mocked(_loadRuntime.loadRuntime);
142
142
  model: "gpt-4"
143
143
  });
144
144
  await gateway["ensureInitialized"]();
145
- const result = gateway["buildGatewayUrl"]("openai");
146
- (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/openai");
145
+ const result = gateway["buildGatewayUrl"]();
146
+ (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/intuned-ai-gateway");
147
147
  });
148
148
  (0, _extendedTest.it)("should strip trailing slash from domain", async () => {
149
149
  process.env.FUNCTIONS_DOMAIN = "https://functions.example.com/";
@@ -155,8 +155,8 @@ const mockLoadRuntime = _vitest.vi.mocked(_loadRuntime.loadRuntime);
155
155
  model: "gpt-4"
156
156
  });
157
157
  await newGateway["ensureInitialized"]();
158
- const result = newGateway["buildGatewayUrl"]("openai");
159
- (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/openai");
158
+ const result = newGateway["buildGatewayUrl"]();
159
+ (0, _extendedTest.expect)(result).toBe("https://functions.example.com/api/workspace123/functions/integration456/intuned-ai-gateway");
160
160
  });
161
161
  });
162
162
  (0, _extendedTest.describe)("ensureInitialized", () => {
@@ -236,7 +236,7 @@ const mockLoadRuntime = _vitest.vi.mocked(_loadRuntime.loadRuntime);
236
236
  apiKey: "--THIS_VALUE_WILL_BE_REPLACED_BY_INTUNED_BE--",
237
237
  headers: undefined,
238
238
  model: "claude-3-sonnet",
239
- baseUrl: "https://functions.example.com/api/workspace123/functions/integration456/anthropic/v1"
239
+ baseUrl: "https://functions.example.com/api/workspace123/functions/integration456/intuned-ai-gateway"
240
240
  });
241
241
  (0, _extendedTest.expect)(result).toBe(mockInstance);
242
242
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intuned/browser-dev",
3
- "version": "0.1.10-dev.0",
3
+ "version": "0.1.13-dev.0",
4
4
  "description": "runner package for intuned functions",
5
5
  "types": "./dist/index.d.ts",
6
6
  "typesVersions": {