filejar 0.5.0 → 0.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0 (2026-01-03)
4
+
5
+ Full Changelog: [v0.5.0...v0.6.0](https://github.com/filejar/node/compare/v0.5.0...v0.6.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** api update ([00b875b](https://github.com/filejar/node/commit/00b875bd36e6d6839ca7d294c1831c1f5e70f2a2))
10
+ * **api:** api update ([51aff53](https://github.com/filejar/node/commit/51aff536b805929a85a2a1cf650465f955ece363))
11
+ * **api:** api update ([9f67e36](https://github.com/filejar/node/commit/9f67e365bb6d2324c904dc1f2d4ca6134bffffaa))
12
+ * **api:** manual updates ([1a6c4bf](https://github.com/filejar/node/commit/1a6c4bf09534aa5c91360b28e63e20d361a23a0a))
13
+ * **api:** manual updates ([4e2646f](https://github.com/filejar/node/commit/4e2646f9ebf459caf0663e1ad660b0de1cf1d66d))
14
+
3
15
  ## 0.5.0 (2026-01-02)
4
16
 
5
17
  Full Changelog: [v0.4.0...v0.5.0](https://github.com/filejar/node/compare/v0.4.0...v0.5.0)
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  This library provides convenient access to the Filejar REST API from server-side TypeScript or JavaScript.
6
6
 
7
- The full API of this library can be found in [api.md](api.md).
7
+ The REST API documentation can be found on [docs.filejar.dev](https://docs.filejar.dev). The full API of this library can be found in [api.md](api.md).
8
8
 
9
9
  It is generated with [Stainless](https://www.stainless.com/).
10
10
 
@@ -27,9 +27,7 @@ const client = new Filejar({
27
27
  environment: 'local', // defaults to 'production'
28
28
  });
29
29
 
30
- const response = await client.upload.prepare({ file_name: 'example.jpg' });
31
-
32
- console.log(response.upload_id);
30
+ const response = await client.upload.prepare({ body: [{}, {}, {}] });
33
31
  ```
34
32
 
35
33
  ### Request & Response types
@@ -45,7 +43,12 @@ const client = new Filejar({
45
43
  environment: 'local', // defaults to 'production'
46
44
  });
47
45
 
48
- const params: Filejar.UploadAcknowledgeParams = { upload_id: '41b293b2-b086-4e26-b3ab-5870f369a525' };
46
+ const params: Filejar.UploadAcknowledgeParams = {
47
+ body: [
48
+ { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
49
+ { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
50
+ ],
51
+ };
49
52
  const response: Filejar.UploadAcknowledgeResponse = await client.upload.acknowledge(params);
50
53
  ```
51
54
 
@@ -60,7 +63,12 @@ a subclass of `APIError` will be thrown:
60
63
  <!-- prettier-ignore -->
61
64
  ```ts
62
65
  const response = await client.upload
63
- .acknowledge({ upload_id: '41b293b2-b086-4e26-b3ab-5870f369a525' })
66
+ .acknowledge({
67
+ body: [
68
+ { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
69
+ { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
70
+ ],
71
+ })
64
72
  .catch(async (err) => {
65
73
  if (err instanceof Filejar.APIError) {
66
74
  console.log(err.status); // 400
@@ -101,7 +109,7 @@ const client = new Filejar({
101
109
  });
102
110
 
103
111
  // Or, configure per-request:
104
- await client.upload.acknowledge({ upload_id: '41b293b2-b086-4e26-b3ab-5870f369a525' }, {
112
+ await client.upload.acknowledge({ body: [{ upload_id: '123e4567-e89b-12d3-a456-426614174000' }, { upload_id: '223e4567-e89b-12d3-a456-426614174001' }] }, {
105
113
  maxRetries: 5,
106
114
  });
107
115
  ```
@@ -118,7 +126,7 @@ const client = new Filejar({
118
126
  });
119
127
 
120
128
  // Override per-request:
121
- await client.upload.acknowledge({ upload_id: '41b293b2-b086-4e26-b3ab-5870f369a525' }, {
129
+ await client.upload.acknowledge({ body: [{ upload_id: '123e4567-e89b-12d3-a456-426614174000' }, { upload_id: '223e4567-e89b-12d3-a456-426614174001' }] }, {
122
130
  timeout: 5 * 1000,
123
131
  });
124
132
  ```
@@ -142,16 +150,26 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse
142
150
  const client = new Filejar();
143
151
 
144
152
  const response = await client.upload
145
- .acknowledge({ upload_id: '41b293b2-b086-4e26-b3ab-5870f369a525' })
153
+ .acknowledge({
154
+ body: [
155
+ { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
156
+ { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
157
+ ],
158
+ })
146
159
  .asResponse();
147
160
  console.log(response.headers.get('X-My-Header'));
148
161
  console.log(response.statusText); // access the underlying Response object
149
162
 
150
163
  const { data: response, response: raw } = await client.upload
151
- .acknowledge({ upload_id: '41b293b2-b086-4e26-b3ab-5870f369a525' })
164
+ .acknowledge({
165
+ body: [
166
+ { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
167
+ { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
168
+ ],
169
+ })
152
170
  .withResponse();
153
171
  console.log(raw.headers.get('X-My-Header'));
154
- console.log(response.acknowledged_at);
172
+ console.log(response);
155
173
  ```
156
174
 
157
175
  ### Logging
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "filejar",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "The official TypeScript library for the Filejar API",
5
5
  "author": "Filejar <>",
6
6
  "types": "./index.d.ts",
@@ -4,93 +4,149 @@ import { RequestOptions } from "../internal/request-options.mjs";
4
4
  import { type ToFileInput } from "../internal/to-file.mjs";
5
5
  export declare class Upload extends APIResource {
6
6
  /**
7
- * Acknowledges that a file upload has been completed. This endpoint verifies the
8
- * file exists in storage and updates the upload record with metadata.
7
+ * Acknowledges that one or more file uploads have been completed. This endpoint
8
+ * verifies files exist in storage and updates upload records with metadata.
9
+ * Processes multiple uploads in parallel. Each result in the response array may be
10
+ * a success or error object.
9
11
  *
10
12
  * @example
11
13
  * ```ts
12
14
  * const response = await client.upload.acknowledge({
13
- * upload_id: '123e4567-e89b-12d3-a456-426614174000',
15
+ * body: [
16
+ * { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
17
+ * { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
18
+ * ],
14
19
  * });
15
20
  * ```
16
21
  */
17
- acknowledge(body: UploadAcknowledgeParams, options?: RequestOptions): APIPromise<UploadAcknowledgeResponse>;
22
+ acknowledge(params: UploadAcknowledgeParams, options?: RequestOptions): APIPromise<UploadAcknowledgeResponse>;
18
23
  /**
19
- * Creates a presigned URL for file upload to R2 storage. Requires API key
20
- * authentication.
24
+ * Creates presigned URLs for one or more file uploads to Filejar storage.
25
+ * Processes multiple files in parallel. Requires API key authentication.
21
26
  *
22
27
  * @example
23
28
  * ```ts
24
- * const response = await client.upload.prepare();
29
+ * const response = await client.upload.prepare({
30
+ * body: [{}, {}, {}],
31
+ * });
25
32
  * ```
26
33
  */
27
- prepare(body: UploadPrepareParams, options?: RequestOptions): APIPromise<UploadPrepareResponse>;
34
+ prepare(params: UploadPrepareParams, options?: RequestOptions): APIPromise<UploadPrepareResponse>;
28
35
  /**
29
- * Uploads a file to the signed URL.
36
+ * Uploads files to signed URLs.
30
37
  *
31
38
  * Accepts File objects, Buffers, ArrayBuffers, or other uploadable types.
39
+ * If params are not provided, file names will be extracted from File objects
40
+ * or generated automatically.
32
41
  *
33
42
  * @example
34
43
  * ```ts
35
- * // Using a File object
36
- * const response = await client.upload.uploadFile(file, prepareResponse);
44
+ * // With explicit file names
45
+ * const response = await client.upload.uploadFile([file1, file2], {
46
+ * body: [{ file_name: 'file1.txt' }, { file_name: 'file2.txt' }],
47
+ * });
37
48
  *
38
- * // Using a Buffer (Node.js)
39
- * const buffer = fs.readFileSync('path/to/file.txt');
40
- * const response = await client.upload.uploadFile(buffer, prepareResponse);
49
+ * // Without params (file names extracted from File objects or auto-generated)
50
+ * const response = await client.upload.uploadFile([file1, file2]);
41
51
  * ```
42
52
  */
43
- uploadFile(file: ToFileInput, options?: {
44
- file_name?: string;
45
- }): Promise<{
46
- response: Response;
53
+ uploadFile(files: Array<ToFileInput>, params?: UploadPrepareParams): Promise<{
54
+ response: {
55
+ key: string;
56
+ upload_id: string;
57
+ }[];
47
58
  acknowledge: UploadAcknowledgeResponse;
48
59
  prepare: UploadPrepareResponse;
49
60
  }>;
50
61
  }
51
- export interface UploadAcknowledgeResponse {
52
- /**
53
- * Timestamp when the upload was acknowledged
54
- */
55
- acknowledged_at: string;
62
+ /**
63
+ * Array of acknowledgment results. Each item may be a success object or an error
64
+ * object.
65
+ */
66
+ export type UploadAcknowledgeResponse = Array<UploadAcknowledgeResponse.UnionMember0 | UploadAcknowledgeResponse.UnionMember1>;
67
+ export declare namespace UploadAcknowledgeResponse {
56
68
  /**
57
- * MIME type of the uploaded file
69
+ * Successful acknowledgment
58
70
  */
59
- content_type: string;
71
+ interface UnionMember0 {
72
+ /**
73
+ * Timestamp when the upload was acknowledged
74
+ */
75
+ acknowledged_at: string;
76
+ /**
77
+ * MIME type of the uploaded file
78
+ */
79
+ content_type: string;
80
+ /**
81
+ * File size in bytes
82
+ */
83
+ size: number;
84
+ /**
85
+ * The upload ID that was acknowledged
86
+ */
87
+ upload_id: string;
88
+ }
60
89
  /**
61
- * File size in bytes
90
+ * Error for a specific upload
62
91
  */
63
- size: number;
92
+ interface UnionMember1 {
93
+ /**
94
+ * Error message (e.g., 'Upload not found' or 'Upload is not completed yet')
95
+ */
96
+ error: string;
97
+ /**
98
+ * The upload ID that failed
99
+ */
100
+ upload_id: string;
101
+ }
64
102
  }
65
- export interface UploadPrepareResponse {
66
- /**
67
- * File key/path in storage
68
- */
69
- key: string;
70
- /**
71
- * Presigned URL for uploading the file
72
- */
73
- signed_url: string;
74
- /**
75
- * Timestamp when the upload was prepared
76
- */
77
- time: string;
78
- /**
79
- * Unique identifier for this upload
80
- */
81
- upload_id: string;
103
+ /**
104
+ * Array of prepared uploads
105
+ */
106
+ export type UploadPrepareResponse = Array<UploadPrepareResponse.UploadPrepareResponseItem>;
107
+ export declare namespace UploadPrepareResponse {
108
+ interface UploadPrepareResponseItem {
109
+ /**
110
+ * File key/path in storage
111
+ */
112
+ key: string;
113
+ /**
114
+ * Proxy URL for uploading files through the API (PUT request to /v1/files/{key})
115
+ */
116
+ signed_url: string;
117
+ /**
118
+ * Unique identifier for this upload
119
+ */
120
+ upload_id: string;
121
+ }
82
122
  }
83
123
  export interface UploadAcknowledgeParams {
84
124
  /**
85
- * The upload ID returned from /prepare endpoint
125
+ * Array of upload IDs to acknowledge
86
126
  */
87
- upload_id: string;
127
+ body: Array<UploadAcknowledgeParams.Body>;
128
+ }
129
+ export declare namespace UploadAcknowledgeParams {
130
+ interface Body {
131
+ /**
132
+ * The upload ID returned from /prepare endpoint
133
+ */
134
+ upload_id: string;
135
+ }
88
136
  }
89
137
  export interface UploadPrepareParams {
90
138
  /**
91
- * Optional file name. If not provided, a random UUID will be used.
139
+ * Array of files to prepare for upload
92
140
  */
93
- file_name?: string;
141
+ body: Array<UploadPrepareParams.Body>;
142
+ }
143
+ export declare namespace UploadPrepareParams {
144
+ interface Body {
145
+ /**
146
+ * Optional file name. If not provided, a random UUID will be used.
147
+ */
148
+ file_name?: string;
149
+ }
94
150
  }
95
151
  export declare namespace Upload {
96
152
  export { type UploadAcknowledgeResponse as UploadAcknowledgeResponse, type UploadPrepareResponse as UploadPrepareResponse, type UploadAcknowledgeParams as UploadAcknowledgeParams, type UploadPrepareParams as UploadPrepareParams, };
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.mts","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,EAAE,UAAU,EAAE;OACd,EAAE,cAAc,EAAE;OAClB,EAAU,KAAK,WAAW,EAAE;AAEnC,qBAAa,MAAO,SAAQ,WAAW;IACrC;;;;;;;;;;OAUG;IACH,WAAW,CACT,IAAI,EAAE,uBAAuB,EAC7B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,yBAAyB,CAAC;IAIxC;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,qBAAqB,CAAC;IAI/F;;;;;;;;;;;;;;OAcG;IACG,UAAU,CACd,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC;QACT,QAAQ,EAAE,QAAQ,CAAC;QACnB,WAAW,EAAE,yBAAyB,CAAC;QACvC,OAAO,EAAE,qBAAqB,CAAC;KAChC,CAAC;CAsBH;AAED,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC;IAC9B,OAAO,EACL,KAAK,yBAAyB,IAAI,yBAAyB,EAC3D,KAAK,qBAAqB,IAAI,qBAAqB,EACnD,KAAK,uBAAuB,IAAI,uBAAuB,EACvD,KAAK,mBAAmB,IAAI,mBAAmB,GAChD,CAAC;CACH"}
1
+ {"version":3,"file":"upload.d.mts","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,EAAE,UAAU,EAAE;OACd,EAAE,cAAc,EAAE;OAClB,EAAU,KAAK,WAAW,EAAE;AAEnC,qBAAa,MAAO,SAAQ,WAAW;IACrC;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CACT,MAAM,EAAE,uBAAuB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,yBAAyB,CAAC;IAKxC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,qBAAqB,CAAC;IAKjG;;;;;;;;;;;;;;;;;OAiBG;IACG,UAAU,CACd,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,EACzB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC;QACT,QAAQ,EAAE;YACR,GAAG,EAAE,MAAM,CAAC;YACZ,SAAS,EAAE,MAAM,CAAC;SACnB,EAAE,CAAC;QACJ,WAAW,EAAE,yBAAyB,CAAC;QACvC,OAAO,EAAE,qBAAqB,CAAC;KAChC,CAAC;CAkGH;AAED;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,KAAK,CAC3C,yBAAyB,CAAC,YAAY,GAAG,yBAAyB,CAAC,YAAY,CAChF,CAAC;AAEF,yBAAiB,yBAAyB,CAAC;IACzC;;OAEG;IACH,UAAiB,YAAY;QAC3B;;WAEG;QACH,eAAe,EAAE,MAAM,CAAC;QAExB;;WAEG;QACH,YAAY,EAAE,MAAM,CAAC;QAErB;;WAEG;QACH,IAAI,EAAE,MAAM,CAAC;QAEb;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;IAED;;OAEG;IACH,UAAiB,YAAY;QAC3B;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;CACF;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC,yBAAyB,CAAC,CAAC;AAE3F,yBAAiB,qBAAqB,CAAC;IACrC,UAAiB,yBAAyB;QACxC;;WAEG;QACH,GAAG,EAAE,MAAM,CAAC;QAEZ;;WAEG;QACH,UAAU,EAAE,MAAM,CAAC;QAEnB;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,yBAAiB,uBAAuB,CAAC;IACvC,UAAiB,IAAI;QACnB;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;CACF;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,yBAAiB,mBAAmB,CAAC;IACnC,UAAiB,IAAI;QACnB;;WAEG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CACF;AAED,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC;IAC9B,OAAO,EACL,KAAK,yBAAyB,IAAI,yBAAyB,EAC3D,KAAK,qBAAqB,IAAI,qBAAqB,EACnD,KAAK,uBAAuB,IAAI,uBAAuB,EACvD,KAAK,mBAAmB,IAAI,mBAAmB,GAChD,CAAC;CACH"}
@@ -4,93 +4,149 @@ import { RequestOptions } from "../internal/request-options.js";
4
4
  import { type ToFileInput } from "../internal/to-file.js";
5
5
  export declare class Upload extends APIResource {
6
6
  /**
7
- * Acknowledges that a file upload has been completed. This endpoint verifies the
8
- * file exists in storage and updates the upload record with metadata.
7
+ * Acknowledges that one or more file uploads have been completed. This endpoint
8
+ * verifies files exist in storage and updates upload records with metadata.
9
+ * Processes multiple uploads in parallel. Each result in the response array may be
10
+ * a success or error object.
9
11
  *
10
12
  * @example
11
13
  * ```ts
12
14
  * const response = await client.upload.acknowledge({
13
- * upload_id: '123e4567-e89b-12d3-a456-426614174000',
15
+ * body: [
16
+ * { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
17
+ * { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
18
+ * ],
14
19
  * });
15
20
  * ```
16
21
  */
17
- acknowledge(body: UploadAcknowledgeParams, options?: RequestOptions): APIPromise<UploadAcknowledgeResponse>;
22
+ acknowledge(params: UploadAcknowledgeParams, options?: RequestOptions): APIPromise<UploadAcknowledgeResponse>;
18
23
  /**
19
- * Creates a presigned URL for file upload to R2 storage. Requires API key
20
- * authentication.
24
+ * Creates presigned URLs for one or more file uploads to Filejar storage.
25
+ * Processes multiple files in parallel. Requires API key authentication.
21
26
  *
22
27
  * @example
23
28
  * ```ts
24
- * const response = await client.upload.prepare();
29
+ * const response = await client.upload.prepare({
30
+ * body: [{}, {}, {}],
31
+ * });
25
32
  * ```
26
33
  */
27
- prepare(body: UploadPrepareParams, options?: RequestOptions): APIPromise<UploadPrepareResponse>;
34
+ prepare(params: UploadPrepareParams, options?: RequestOptions): APIPromise<UploadPrepareResponse>;
28
35
  /**
29
- * Uploads a file to the signed URL.
36
+ * Uploads files to signed URLs.
30
37
  *
31
38
  * Accepts File objects, Buffers, ArrayBuffers, or other uploadable types.
39
+ * If params are not provided, file names will be extracted from File objects
40
+ * or generated automatically.
32
41
  *
33
42
  * @example
34
43
  * ```ts
35
- * // Using a File object
36
- * const response = await client.upload.uploadFile(file, prepareResponse);
44
+ * // With explicit file names
45
+ * const response = await client.upload.uploadFile([file1, file2], {
46
+ * body: [{ file_name: 'file1.txt' }, { file_name: 'file2.txt' }],
47
+ * });
37
48
  *
38
- * // Using a Buffer (Node.js)
39
- * const buffer = fs.readFileSync('path/to/file.txt');
40
- * const response = await client.upload.uploadFile(buffer, prepareResponse);
49
+ * // Without params (file names extracted from File objects or auto-generated)
50
+ * const response = await client.upload.uploadFile([file1, file2]);
41
51
  * ```
42
52
  */
43
- uploadFile(file: ToFileInput, options?: {
44
- file_name?: string;
45
- }): Promise<{
46
- response: Response;
53
+ uploadFile(files: Array<ToFileInput>, params?: UploadPrepareParams): Promise<{
54
+ response: {
55
+ key: string;
56
+ upload_id: string;
57
+ }[];
47
58
  acknowledge: UploadAcknowledgeResponse;
48
59
  prepare: UploadPrepareResponse;
49
60
  }>;
50
61
  }
51
- export interface UploadAcknowledgeResponse {
52
- /**
53
- * Timestamp when the upload was acknowledged
54
- */
55
- acknowledged_at: string;
62
+ /**
63
+ * Array of acknowledgment results. Each item may be a success object or an error
64
+ * object.
65
+ */
66
+ export type UploadAcknowledgeResponse = Array<UploadAcknowledgeResponse.UnionMember0 | UploadAcknowledgeResponse.UnionMember1>;
67
+ export declare namespace UploadAcknowledgeResponse {
56
68
  /**
57
- * MIME type of the uploaded file
69
+ * Successful acknowledgment
58
70
  */
59
- content_type: string;
71
+ interface UnionMember0 {
72
+ /**
73
+ * Timestamp when the upload was acknowledged
74
+ */
75
+ acknowledged_at: string;
76
+ /**
77
+ * MIME type of the uploaded file
78
+ */
79
+ content_type: string;
80
+ /**
81
+ * File size in bytes
82
+ */
83
+ size: number;
84
+ /**
85
+ * The upload ID that was acknowledged
86
+ */
87
+ upload_id: string;
88
+ }
60
89
  /**
61
- * File size in bytes
90
+ * Error for a specific upload
62
91
  */
63
- size: number;
92
+ interface UnionMember1 {
93
+ /**
94
+ * Error message (e.g., 'Upload not found' or 'Upload is not completed yet')
95
+ */
96
+ error: string;
97
+ /**
98
+ * The upload ID that failed
99
+ */
100
+ upload_id: string;
101
+ }
64
102
  }
65
- export interface UploadPrepareResponse {
66
- /**
67
- * File key/path in storage
68
- */
69
- key: string;
70
- /**
71
- * Presigned URL for uploading the file
72
- */
73
- signed_url: string;
74
- /**
75
- * Timestamp when the upload was prepared
76
- */
77
- time: string;
78
- /**
79
- * Unique identifier for this upload
80
- */
81
- upload_id: string;
103
+ /**
104
+ * Array of prepared uploads
105
+ */
106
+ export type UploadPrepareResponse = Array<UploadPrepareResponse.UploadPrepareResponseItem>;
107
+ export declare namespace UploadPrepareResponse {
108
+ interface UploadPrepareResponseItem {
109
+ /**
110
+ * File key/path in storage
111
+ */
112
+ key: string;
113
+ /**
114
+ * Proxy URL for uploading files through the API (PUT request to /v1/files/{key})
115
+ */
116
+ signed_url: string;
117
+ /**
118
+ * Unique identifier for this upload
119
+ */
120
+ upload_id: string;
121
+ }
82
122
  }
83
123
  export interface UploadAcknowledgeParams {
84
124
  /**
85
- * The upload ID returned from /prepare endpoint
125
+ * Array of upload IDs to acknowledge
86
126
  */
87
- upload_id: string;
127
+ body: Array<UploadAcknowledgeParams.Body>;
128
+ }
129
+ export declare namespace UploadAcknowledgeParams {
130
+ interface Body {
131
+ /**
132
+ * The upload ID returned from /prepare endpoint
133
+ */
134
+ upload_id: string;
135
+ }
88
136
  }
89
137
  export interface UploadPrepareParams {
90
138
  /**
91
- * Optional file name. If not provided, a random UUID will be used.
139
+ * Array of files to prepare for upload
92
140
  */
93
- file_name?: string;
141
+ body: Array<UploadPrepareParams.Body>;
142
+ }
143
+ export declare namespace UploadPrepareParams {
144
+ interface Body {
145
+ /**
146
+ * Optional file name. If not provided, a random UUID will be used.
147
+ */
148
+ file_name?: string;
149
+ }
94
150
  }
95
151
  export declare namespace Upload {
96
152
  export { type UploadAcknowledgeResponse as UploadAcknowledgeResponse, type UploadPrepareResponse as UploadPrepareResponse, type UploadAcknowledgeParams as UploadAcknowledgeParams, type UploadPrepareParams as UploadPrepareParams, };
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,EAAE,UAAU,EAAE;OACd,EAAE,cAAc,EAAE;OAClB,EAAU,KAAK,WAAW,EAAE;AAEnC,qBAAa,MAAO,SAAQ,WAAW;IACrC;;;;;;;;;;OAUG;IACH,WAAW,CACT,IAAI,EAAE,uBAAuB,EAC7B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,yBAAyB,CAAC;IAIxC;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,qBAAqB,CAAC;IAI/F;;;;;;;;;;;;;;OAcG;IACG,UAAU,CACd,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC;QACT,QAAQ,EAAE,QAAQ,CAAC;QACnB,WAAW,EAAE,yBAAyB,CAAC;QACvC,OAAO,EAAE,qBAAqB,CAAC;KAChC,CAAC;CAsBH;AAED,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC;IAC9B,OAAO,EACL,KAAK,yBAAyB,IAAI,yBAAyB,EAC3D,KAAK,qBAAqB,IAAI,qBAAqB,EACnD,KAAK,uBAAuB,IAAI,uBAAuB,EACvD,KAAK,mBAAmB,IAAI,mBAAmB,GAChD,CAAC;CACH"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"OAEO,EAAE,WAAW,EAAE;OACf,EAAE,UAAU,EAAE;OACd,EAAE,cAAc,EAAE;OAClB,EAAU,KAAK,WAAW,EAAE;AAEnC,qBAAa,MAAO,SAAQ,WAAW;IACrC;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CACT,MAAM,EAAE,uBAAuB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,yBAAyB,CAAC;IAKxC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,qBAAqB,CAAC;IAKjG;;;;;;;;;;;;;;;;;OAiBG;IACG,UAAU,CACd,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,EACzB,MAAM,CAAC,EAAE,mBAAmB,GAC3B,OAAO,CAAC;QACT,QAAQ,EAAE;YACR,GAAG,EAAE,MAAM,CAAC;YACZ,SAAS,EAAE,MAAM,CAAC;SACnB,EAAE,CAAC;QACJ,WAAW,EAAE,yBAAyB,CAAC;QACvC,OAAO,EAAE,qBAAqB,CAAC;KAChC,CAAC;CAkGH;AAED;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG,KAAK,CAC3C,yBAAyB,CAAC,YAAY,GAAG,yBAAyB,CAAC,YAAY,CAChF,CAAC;AAEF,yBAAiB,yBAAyB,CAAC;IACzC;;OAEG;IACH,UAAiB,YAAY;QAC3B;;WAEG;QACH,eAAe,EAAE,MAAM,CAAC;QAExB;;WAEG;QACH,YAAY,EAAE,MAAM,CAAC;QAErB;;WAEG;QACH,IAAI,EAAE,MAAM,CAAC;QAEb;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;IAED;;OAEG;IACH,UAAiB,YAAY;QAC3B;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;CACF;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC,yBAAyB,CAAC,CAAC;AAE3F,yBAAiB,qBAAqB,CAAC;IACrC,UAAiB,yBAAyB;QACxC;;WAEG;QACH,GAAG,EAAE,MAAM,CAAC;QAEZ;;WAEG;QACH,UAAU,EAAE,MAAM,CAAC;QAEnB;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,yBAAiB,uBAAuB,CAAC;IACvC,UAAiB,IAAI;QACnB;;WAEG;QACH,SAAS,EAAE,MAAM,CAAC;KACnB;CACF;AAED,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,yBAAiB,mBAAmB,CAAC;IACnC,UAAiB,IAAI;QACnB;;WAEG;QACH,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CACF;AAED,MAAM,CAAC,OAAO,WAAW,MAAM,CAAC;IAC9B,OAAO,EACL,KAAK,yBAAyB,IAAI,yBAAyB,EAC3D,KAAK,qBAAqB,IAAI,qBAAqB,EACnD,KAAK,uBAAuB,IAAI,uBAAuB,EACvD,KAAK,mBAAmB,IAAI,mBAAmB,GAChD,CAAC;CACH"}
@@ -6,62 +6,139 @@ const resource_1 = require("../core/resource.js");
6
6
  const to_file_1 = require("../internal/to-file.js");
7
7
  class Upload extends resource_1.APIResource {
8
8
  /**
9
- * Acknowledges that a file upload has been completed. This endpoint verifies the
10
- * file exists in storage and updates the upload record with metadata.
9
+ * Acknowledges that one or more file uploads have been completed. This endpoint
10
+ * verifies files exist in storage and updates upload records with metadata.
11
+ * Processes multiple uploads in parallel. Each result in the response array may be
12
+ * a success or error object.
11
13
  *
12
14
  * @example
13
15
  * ```ts
14
16
  * const response = await client.upload.acknowledge({
15
- * upload_id: '123e4567-e89b-12d3-a456-426614174000',
17
+ * body: [
18
+ * { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
19
+ * { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
20
+ * ],
16
21
  * });
17
22
  * ```
18
23
  */
19
- acknowledge(body, options) {
20
- return this._client.post('/v1/upload/ack', { body, ...options });
24
+ acknowledge(params, options) {
25
+ const { body } = params;
26
+ return this._client.post('/v1/upload/ack', { body: body, ...options });
21
27
  }
22
28
  /**
23
- * Creates a presigned URL for file upload to R2 storage. Requires API key
24
- * authentication.
29
+ * Creates presigned URLs for one or more file uploads to Filejar storage.
30
+ * Processes multiple files in parallel. Requires API key authentication.
25
31
  *
26
32
  * @example
27
33
  * ```ts
28
- * const response = await client.upload.prepare();
34
+ * const response = await client.upload.prepare({
35
+ * body: [{}, {}, {}],
36
+ * });
29
37
  * ```
30
38
  */
31
- prepare(body, options) {
32
- return this._client.post('/v1/upload/prepare', { body, ...options });
39
+ prepare(params, options) {
40
+ const { body } = params;
41
+ return this._client.post('/v1/upload/prepare', { body: body, ...options });
33
42
  }
34
43
  /**
35
- * Uploads a file to the signed URL.
44
+ * Uploads files to signed URLs.
36
45
  *
37
46
  * Accepts File objects, Buffers, ArrayBuffers, or other uploadable types.
47
+ * If params are not provided, file names will be extracted from File objects
48
+ * or generated automatically.
38
49
  *
39
50
  * @example
40
51
  * ```ts
41
- * // Using a File object
42
- * const response = await client.upload.uploadFile(file, prepareResponse);
52
+ * // With explicit file names
53
+ * const response = await client.upload.uploadFile([file1, file2], {
54
+ * body: [{ file_name: 'file1.txt' }, { file_name: 'file2.txt' }],
55
+ * });
43
56
  *
44
- * // Using a Buffer (Node.js)
45
- * const buffer = fs.readFileSync('path/to/file.txt');
46
- * const response = await client.upload.uploadFile(buffer, prepareResponse);
57
+ * // Without params (file names extracted from File objects or auto-generated)
58
+ * const response = await client.upload.uploadFile([file1, file2]);
47
59
  * ```
48
60
  */
49
- async uploadFile(file, options) {
50
- const file_name = options?.file_name ?? (file instanceof File ? file.name : undefined);
51
- const preparedResponse = await this.prepare({
52
- file_name: file_name ?? Date.now().toString(),
53
- });
54
- const fileObj = await (0, to_file_1.toFile)(file);
55
- const apiPromise = this._client.put(preparedResponse.signed_url, {
56
- body: fileObj,
57
- });
58
- const uploadResponse = await apiPromise.asResponse();
59
- const acknowledgeResponse = await this.acknowledge({
60
- upload_id: preparedResponse.upload_id,
61
+ async uploadFile(files, params) {
62
+ // Helper function to extract file extension
63
+ const getFileExtension = (fileName) => {
64
+ const lastDot = fileName.lastIndexOf('.');
65
+ return lastDot > 0 ? fileName.substring(lastDot) : '';
66
+ };
67
+ // Helper function to get extension from MIME type
68
+ const getExtensionFromMimeType = (mimeType) => {
69
+ if (!mimeType)
70
+ return '';
71
+ const mimeToExt = {
72
+ 'image/jpeg': '.jpg',
73
+ 'image/png': '.png',
74
+ 'image/gif': '.gif',
75
+ 'image/webp': '.webp',
76
+ 'text/plain': '.txt',
77
+ 'text/html': '.html',
78
+ 'application/json': '.json',
79
+ 'application/pdf': '.pdf',
80
+ 'video/mp4': '.mp4',
81
+ 'audio/mpeg': '.mp3',
82
+ };
83
+ return mimeToExt[mimeType] || '';
84
+ };
85
+ // Generate params if not provided
86
+ const prepareParams = params ??
87
+ {
88
+ body: files.map((file, index) => {
89
+ let fileName;
90
+ let mimeType;
91
+ // Try to extract file name from File object
92
+ if (file instanceof File) {
93
+ fileName = file.name;
94
+ mimeType = file.type;
95
+ }
96
+ // For other types, try to get name from the file-like object
97
+ else if (typeof file === 'object' && file !== null) {
98
+ if ('name' in file && file.name) {
99
+ fileName = String(file.name);
100
+ }
101
+ if ('type' in file && file.type) {
102
+ mimeType = String(file.type);
103
+ }
104
+ }
105
+ // If we have a file name, ensure it has an extension
106
+ if (fileName) {
107
+ const ext = getFileExtension(fileName);
108
+ // If no extension found, try to infer from MIME type
109
+ if (!ext && mimeType) {
110
+ const inferredExt = getExtensionFromMimeType(mimeType);
111
+ if (inferredExt) {
112
+ fileName = fileName + inferredExt;
113
+ }
114
+ }
115
+ return { file_name: fileName };
116
+ }
117
+ // Generate a unique default name with extension
118
+ const defaultExt = mimeType ? getExtensionFromMimeType(mimeType) : '';
119
+ return {
120
+ file_name: `file-${Date.now()}-${index}-${Math.random().toString(36).substring(7)}${defaultExt}`,
121
+ };
122
+ }),
123
+ };
124
+ const preparedResponse = await this.prepare(prepareParams);
125
+ const uploadResponses = await Promise.all(files.map(async (file) => {
126
+ const fileObj = await (0, to_file_1.toFile)(file);
127
+ const uploadResponse = await this._client.put(preparedResponse[files.indexOf(file)]?.signed_url ?? '', { body: fileObj });
128
+ return {
129
+ key: preparedResponse[files.indexOf(file)]?.key ?? '',
130
+ upload_id: preparedResponse[files.indexOf(file)]?.upload_id ?? '',
131
+ };
132
+ }));
133
+ const acknowledgeResponses = await this.acknowledge({
134
+ body: uploadResponses.map((response) => ({ upload_id: response.upload_id })),
61
135
  });
62
136
  return {
63
- response: uploadResponse,
64
- acknowledge: acknowledgeResponse,
137
+ response: uploadResponses.map((upload) => ({
138
+ key: upload.key,
139
+ upload_id: upload.upload_id,
140
+ })) ?? [],
141
+ acknowledge: acknowledgeResponses,
65
142
  prepare: preparedResponse,
66
143
  };
67
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;AAEtF,kDAA+C;AAG/C,oDAA+D;AAE/D,MAAa,MAAO,SAAQ,sBAAW;IACrC;;;;;;;;;;OAUG;IACH,WAAW,CACT,IAA6B,EAC7B,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAyB,EAAE,OAAwB;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,UAAU,CACd,IAAiB,EACjB,OAEC;QAMD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACvF,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC1C,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SAC9C,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,IAAA,gBAAM,EAAC,IAAI,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAW,gBAAgB,CAAC,UAAU,EAAE;YACzE,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;QACrD,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC;YACjD,SAAS,EAAE,gBAAgB,CAAC,SAAS;SACtC,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE,cAAc;YACxB,WAAW,EAAE,mBAAmB;YAChC,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;CACF;AA9ED,wBA8EC"}
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"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"}
@@ -3,62 +3,139 @@ import { APIResource } from "../core/resource.mjs";
3
3
  import { toFile } from "../internal/to-file.mjs";
4
4
  export class Upload extends APIResource {
5
5
  /**
6
- * Acknowledges that a file upload has been completed. This endpoint verifies the
7
- * file exists in storage and updates the upload record with metadata.
6
+ * Acknowledges that one or more file uploads have been completed. This endpoint
7
+ * verifies files exist in storage and updates upload records with metadata.
8
+ * Processes multiple uploads in parallel. Each result in the response array may be
9
+ * a success or error object.
8
10
  *
9
11
  * @example
10
12
  * ```ts
11
13
  * const response = await client.upload.acknowledge({
12
- * upload_id: '123e4567-e89b-12d3-a456-426614174000',
14
+ * body: [
15
+ * { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
16
+ * { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
17
+ * ],
13
18
  * });
14
19
  * ```
15
20
  */
16
- acknowledge(body, options) {
17
- return this._client.post('/v1/upload/ack', { body, ...options });
21
+ acknowledge(params, options) {
22
+ const { body } = params;
23
+ return this._client.post('/v1/upload/ack', { body: body, ...options });
18
24
  }
19
25
  /**
20
- * Creates a presigned URL for file upload to R2 storage. Requires API key
21
- * authentication.
26
+ * Creates presigned URLs for one or more file uploads to Filejar storage.
27
+ * Processes multiple files in parallel. Requires API key authentication.
22
28
  *
23
29
  * @example
24
30
  * ```ts
25
- * const response = await client.upload.prepare();
31
+ * const response = await client.upload.prepare({
32
+ * body: [{}, {}, {}],
33
+ * });
26
34
  * ```
27
35
  */
28
- prepare(body, options) {
29
- return this._client.post('/v1/upload/prepare', { body, ...options });
36
+ prepare(params, options) {
37
+ const { body } = params;
38
+ return this._client.post('/v1/upload/prepare', { body: body, ...options });
30
39
  }
31
40
  /**
32
- * Uploads a file to the signed URL.
41
+ * Uploads files to signed URLs.
33
42
  *
34
43
  * Accepts File objects, Buffers, ArrayBuffers, or other uploadable types.
44
+ * If params are not provided, file names will be extracted from File objects
45
+ * or generated automatically.
35
46
  *
36
47
  * @example
37
48
  * ```ts
38
- * // Using a File object
39
- * const response = await client.upload.uploadFile(file, prepareResponse);
49
+ * // With explicit file names
50
+ * const response = await client.upload.uploadFile([file1, file2], {
51
+ * body: [{ file_name: 'file1.txt' }, { file_name: 'file2.txt' }],
52
+ * });
40
53
  *
41
- * // Using a Buffer (Node.js)
42
- * const buffer = fs.readFileSync('path/to/file.txt');
43
- * const response = await client.upload.uploadFile(buffer, prepareResponse);
54
+ * // Without params (file names extracted from File objects or auto-generated)
55
+ * const response = await client.upload.uploadFile([file1, file2]);
44
56
  * ```
45
57
  */
46
- async uploadFile(file, options) {
47
- const file_name = options?.file_name ?? (file instanceof File ? file.name : undefined);
48
- const preparedResponse = await this.prepare({
49
- file_name: file_name ?? Date.now().toString(),
50
- });
51
- const fileObj = await toFile(file);
52
- const apiPromise = this._client.put(preparedResponse.signed_url, {
53
- body: fileObj,
54
- });
55
- const uploadResponse = await apiPromise.asResponse();
56
- const acknowledgeResponse = await this.acknowledge({
57
- upload_id: preparedResponse.upload_id,
58
+ async uploadFile(files, params) {
59
+ // Helper function to extract file extension
60
+ const getFileExtension = (fileName) => {
61
+ const lastDot = fileName.lastIndexOf('.');
62
+ return lastDot > 0 ? fileName.substring(lastDot) : '';
63
+ };
64
+ // Helper function to get extension from MIME type
65
+ const getExtensionFromMimeType = (mimeType) => {
66
+ if (!mimeType)
67
+ return '';
68
+ const mimeToExt = {
69
+ 'image/jpeg': '.jpg',
70
+ 'image/png': '.png',
71
+ 'image/gif': '.gif',
72
+ 'image/webp': '.webp',
73
+ 'text/plain': '.txt',
74
+ 'text/html': '.html',
75
+ 'application/json': '.json',
76
+ 'application/pdf': '.pdf',
77
+ 'video/mp4': '.mp4',
78
+ 'audio/mpeg': '.mp3',
79
+ };
80
+ return mimeToExt[mimeType] || '';
81
+ };
82
+ // Generate params if not provided
83
+ const prepareParams = params ??
84
+ {
85
+ body: files.map((file, index) => {
86
+ let fileName;
87
+ let mimeType;
88
+ // Try to extract file name from File object
89
+ if (file instanceof File) {
90
+ fileName = file.name;
91
+ mimeType = file.type;
92
+ }
93
+ // For other types, try to get name from the file-like object
94
+ else if (typeof file === 'object' && file !== null) {
95
+ if ('name' in file && file.name) {
96
+ fileName = String(file.name);
97
+ }
98
+ if ('type' in file && file.type) {
99
+ mimeType = String(file.type);
100
+ }
101
+ }
102
+ // If we have a file name, ensure it has an extension
103
+ if (fileName) {
104
+ const ext = getFileExtension(fileName);
105
+ // If no extension found, try to infer from MIME type
106
+ if (!ext && mimeType) {
107
+ const inferredExt = getExtensionFromMimeType(mimeType);
108
+ if (inferredExt) {
109
+ fileName = fileName + inferredExt;
110
+ }
111
+ }
112
+ return { file_name: fileName };
113
+ }
114
+ // Generate a unique default name with extension
115
+ const defaultExt = mimeType ? getExtensionFromMimeType(mimeType) : '';
116
+ return {
117
+ file_name: `file-${Date.now()}-${index}-${Math.random().toString(36).substring(7)}${defaultExt}`,
118
+ };
119
+ }),
120
+ };
121
+ const preparedResponse = await this.prepare(prepareParams);
122
+ const uploadResponses = await Promise.all(files.map(async (file) => {
123
+ const fileObj = await toFile(file);
124
+ const uploadResponse = await this._client.put(preparedResponse[files.indexOf(file)]?.signed_url ?? '', { body: fileObj });
125
+ return {
126
+ key: preparedResponse[files.indexOf(file)]?.key ?? '',
127
+ upload_id: preparedResponse[files.indexOf(file)]?.upload_id ?? '',
128
+ };
129
+ }));
130
+ const acknowledgeResponses = await this.acknowledge({
131
+ body: uploadResponses.map((response) => ({ upload_id: response.upload_id })),
58
132
  });
59
133
  return {
60
- response: uploadResponse,
61
- acknowledge: acknowledgeResponse,
134
+ response: uploadResponses.map((upload) => ({
135
+ key: upload.key,
136
+ upload_id: upload.upload_id,
137
+ })) ?? [],
138
+ acknowledge: acknowledgeResponses,
62
139
  prepare: preparedResponse,
63
140
  };
64
141
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upload.mjs","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,WAAW,EAAE;OAGf,EAAE,MAAM,EAAoB;AAEnC,MAAM,OAAO,MAAO,SAAQ,WAAW;IACrC;;;;;;;;;;OAUG;IACH,WAAW,CACT,IAA6B,EAC7B,OAAwB;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAyB,EAAE,OAAwB;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,UAAU,CACd,IAAiB,EACjB,OAEC;QAMD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACvF,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC1C,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SAC9C,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAW,gBAAgB,CAAC,UAAU,EAAE;YACzE,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;QACrD,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC;YACjD,SAAS,EAAE,gBAAgB,CAAC,SAAS;SACtC,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE,cAAc;YACxB,WAAW,EAAE,mBAAmB;YAChC,OAAO,EAAE,gBAAgB;SAC1B,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"upload.mjs","sourceRoot":"","sources":["../src/resources/upload.ts"],"names":[],"mappings":"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"}
@@ -7,135 +7,277 @@ import { toFile, type ToFileInput } from '../internal/to-file';
7
7
 
8
8
  export class Upload extends APIResource {
9
9
  /**
10
- * Acknowledges that a file upload has been completed. This endpoint verifies the
11
- * file exists in storage and updates the upload record with metadata.
10
+ * Acknowledges that one or more file uploads have been completed. This endpoint
11
+ * verifies files exist in storage and updates upload records with metadata.
12
+ * Processes multiple uploads in parallel. Each result in the response array may be
13
+ * a success or error object.
12
14
  *
13
15
  * @example
14
16
  * ```ts
15
17
  * const response = await client.upload.acknowledge({
16
- * upload_id: '123e4567-e89b-12d3-a456-426614174000',
18
+ * body: [
19
+ * { upload_id: '123e4567-e89b-12d3-a456-426614174000' },
20
+ * { upload_id: '223e4567-e89b-12d3-a456-426614174001' },
21
+ * ],
17
22
  * });
18
23
  * ```
19
24
  */
20
25
  acknowledge(
21
- body: UploadAcknowledgeParams,
26
+ params: UploadAcknowledgeParams,
22
27
  options?: RequestOptions,
23
28
  ): APIPromise<UploadAcknowledgeResponse> {
24
- return this._client.post('/v1/upload/ack', { body, ...options });
29
+ const { body } = params;
30
+ return this._client.post('/v1/upload/ack', { body: body, ...options });
25
31
  }
26
32
 
27
33
  /**
28
- * Creates a presigned URL for file upload to R2 storage. Requires API key
29
- * authentication.
34
+ * Creates presigned URLs for one or more file uploads to Filejar storage.
35
+ * Processes multiple files in parallel. Requires API key authentication.
30
36
  *
31
37
  * @example
32
38
  * ```ts
33
- * const response = await client.upload.prepare();
39
+ * const response = await client.upload.prepare({
40
+ * body: [{}, {}, {}],
41
+ * });
34
42
  * ```
35
43
  */
36
- prepare(body: UploadPrepareParams, options?: RequestOptions): APIPromise<UploadPrepareResponse> {
37
- return this._client.post('/v1/upload/prepare', { body, ...options });
44
+ prepare(params: UploadPrepareParams, options?: RequestOptions): APIPromise<UploadPrepareResponse> {
45
+ const { body } = params;
46
+ return this._client.post('/v1/upload/prepare', { body: body, ...options });
38
47
  }
39
48
 
40
49
  /**
41
- * Uploads a file to the signed URL.
50
+ * Uploads files to signed URLs.
42
51
  *
43
52
  * Accepts File objects, Buffers, ArrayBuffers, or other uploadable types.
53
+ * If params are not provided, file names will be extracted from File objects
54
+ * or generated automatically.
44
55
  *
45
56
  * @example
46
57
  * ```ts
47
- * // Using a File object
48
- * const response = await client.upload.uploadFile(file, prepareResponse);
58
+ * // With explicit file names
59
+ * const response = await client.upload.uploadFile([file1, file2], {
60
+ * body: [{ file_name: 'file1.txt' }, { file_name: 'file2.txt' }],
61
+ * });
49
62
  *
50
- * // Using a Buffer (Node.js)
51
- * const buffer = fs.readFileSync('path/to/file.txt');
52
- * const response = await client.upload.uploadFile(buffer, prepareResponse);
63
+ * // Without params (file names extracted from File objects or auto-generated)
64
+ * const response = await client.upload.uploadFile([file1, file2]);
53
65
  * ```
54
66
  */
55
67
  async uploadFile(
56
- file: ToFileInput,
57
- options?: {
58
- file_name?: string;
59
- },
68
+ files: Array<ToFileInput>,
69
+ params?: UploadPrepareParams,
60
70
  ): Promise<{
61
- response: Response;
71
+ response: {
72
+ key: string;
73
+ upload_id: string;
74
+ }[];
62
75
  acknowledge: UploadAcknowledgeResponse;
63
76
  prepare: UploadPrepareResponse;
64
77
  }> {
65
- const file_name = options?.file_name ?? (file instanceof File ? file.name : undefined);
66
- const preparedResponse = await this.prepare({
67
- file_name: file_name ?? Date.now().toString(),
68
- });
78
+ // Helper function to extract file extension
79
+ const getFileExtension = (fileName: string): string => {
80
+ const lastDot = fileName.lastIndexOf('.');
81
+ return lastDot > 0 ? fileName.substring(lastDot) : '';
82
+ };
69
83
 
70
- const fileObj = await toFile(file);
71
- const apiPromise = this._client.put<Response>(preparedResponse.signed_url, {
72
- body: fileObj,
73
- });
84
+ // Helper function to get extension from MIME type
85
+ const getExtensionFromMimeType = (mimeType?: string): string => {
86
+ if (!mimeType) return '';
87
+ const mimeToExt: Record<string, string> = {
88
+ 'image/jpeg': '.jpg',
89
+ 'image/png': '.png',
90
+ 'image/gif': '.gif',
91
+ 'image/webp': '.webp',
92
+ 'text/plain': '.txt',
93
+ 'text/html': '.html',
94
+ 'application/json': '.json',
95
+ 'application/pdf': '.pdf',
96
+ 'video/mp4': '.mp4',
97
+ 'audio/mpeg': '.mp3',
98
+ };
99
+ return mimeToExt[mimeType] || '';
100
+ };
101
+
102
+ // Generate params if not provided
103
+ const prepareParams: UploadPrepareParams =
104
+ params ??
105
+ ({
106
+ body: files.map((file, index) => {
107
+ let fileName: string | undefined;
108
+ let mimeType: string | undefined;
109
+
110
+ // Try to extract file name from File object
111
+ if (file instanceof File) {
112
+ fileName = file.name;
113
+ mimeType = file.type;
114
+ }
115
+ // For other types, try to get name from the file-like object
116
+ else if (typeof file === 'object' && file !== null) {
117
+ if ('name' in file && file.name) {
118
+ fileName = String(file.name);
119
+ }
120
+ if ('type' in file && file.type) {
121
+ mimeType = String(file.type);
122
+ }
123
+ }
124
+
125
+ // If we have a file name, ensure it has an extension
126
+ if (fileName) {
127
+ const ext = getFileExtension(fileName);
128
+ // If no extension found, try to infer from MIME type
129
+ if (!ext && mimeType) {
130
+ const inferredExt = getExtensionFromMimeType(mimeType);
131
+ if (inferredExt) {
132
+ fileName = fileName + inferredExt;
133
+ }
134
+ }
135
+ return { file_name: fileName };
136
+ }
74
137
 
75
- const uploadResponse = await apiPromise.asResponse();
76
- const acknowledgeResponse = await this.acknowledge({
77
- upload_id: preparedResponse.upload_id,
138
+ // Generate a unique default name with extension
139
+ const defaultExt = mimeType ? getExtensionFromMimeType(mimeType) : '';
140
+ return {
141
+ file_name: `file-${Date.now()}-${index}-${Math.random().toString(36).substring(7)}${defaultExt}`,
142
+ };
143
+ }),
144
+ } as UploadPrepareParams);
145
+
146
+ const preparedResponse = await this.prepare(prepareParams);
147
+ const uploadResponses = await Promise.all(
148
+ files.map(async (file) => {
149
+ const fileObj = await toFile(file);
150
+ const uploadResponse = await this._client.put<Response>(
151
+ preparedResponse[files.indexOf(file)]?.signed_url ?? '',
152
+ { body: fileObj },
153
+ );
154
+ return {
155
+ key: preparedResponse[files.indexOf(file)]?.key ?? '',
156
+ upload_id: preparedResponse[files.indexOf(file)]?.upload_id ?? '',
157
+ };
158
+ }),
159
+ );
160
+
161
+ const acknowledgeResponses = await this.acknowledge({
162
+ body: uploadResponses.map((response) => ({ upload_id: response.upload_id })),
78
163
  });
79
164
 
80
165
  return {
81
- response: uploadResponse,
82
- acknowledge: acknowledgeResponse,
166
+ response:
167
+ uploadResponses.map((upload) => ({
168
+ key: upload.key,
169
+ upload_id: upload.upload_id,
170
+ })) ?? [],
171
+ acknowledge: acknowledgeResponses,
83
172
  prepare: preparedResponse,
84
173
  };
85
174
  }
86
175
  }
87
176
 
88
- export interface UploadAcknowledgeResponse {
89
- /**
90
- * Timestamp when the upload was acknowledged
91
- */
92
- acknowledged_at: string;
177
+ /**
178
+ * Array of acknowledgment results. Each item may be a success object or an error
179
+ * object.
180
+ */
181
+ export type UploadAcknowledgeResponse = Array<
182
+ UploadAcknowledgeResponse.UnionMember0 | UploadAcknowledgeResponse.UnionMember1
183
+ >;
93
184
 
185
+ export namespace UploadAcknowledgeResponse {
94
186
  /**
95
- * MIME type of the uploaded file
187
+ * Successful acknowledgment
96
188
  */
97
- content_type: string;
189
+ export interface UnionMember0 {
190
+ /**
191
+ * Timestamp when the upload was acknowledged
192
+ */
193
+ acknowledged_at: string;
194
+
195
+ /**
196
+ * MIME type of the uploaded file
197
+ */
198
+ content_type: string;
199
+
200
+ /**
201
+ * File size in bytes
202
+ */
203
+ size: number;
204
+
205
+ /**
206
+ * The upload ID that was acknowledged
207
+ */
208
+ upload_id: string;
209
+ }
98
210
 
99
211
  /**
100
- * File size in bytes
212
+ * Error for a specific upload
101
213
  */
102
- size: number;
214
+ export interface UnionMember1 {
215
+ /**
216
+ * Error message (e.g., 'Upload not found' or 'Upload is not completed yet')
217
+ */
218
+ error: string;
219
+
220
+ /**
221
+ * The upload ID that failed
222
+ */
223
+ upload_id: string;
224
+ }
103
225
  }
104
226
 
105
- export interface UploadPrepareResponse {
106
- /**
107
- * File key/path in storage
108
- */
109
- key: string;
227
+ /**
228
+ * Array of prepared uploads
229
+ */
230
+ export type UploadPrepareResponse = Array<UploadPrepareResponse.UploadPrepareResponseItem>;
110
231
 
111
- /**
112
- * Presigned URL for uploading the file
113
- */
114
- signed_url: string;
232
+ export namespace UploadPrepareResponse {
233
+ export interface UploadPrepareResponseItem {
234
+ /**
235
+ * File key/path in storage
236
+ */
237
+ key: string;
115
238
 
116
- /**
117
- * Timestamp when the upload was prepared
118
- */
119
- time: string;
239
+ /**
240
+ * Proxy URL for uploading files through the API (PUT request to /v1/files/{key})
241
+ */
242
+ signed_url: string;
120
243
 
121
- /**
122
- * Unique identifier for this upload
123
- */
124
- upload_id: string;
244
+ /**
245
+ * Unique identifier for this upload
246
+ */
247
+ upload_id: string;
248
+ }
125
249
  }
126
250
 
127
251
  export interface UploadAcknowledgeParams {
128
252
  /**
129
- * The upload ID returned from /prepare endpoint
253
+ * Array of upload IDs to acknowledge
130
254
  */
131
- upload_id: string;
255
+ body: Array<UploadAcknowledgeParams.Body>;
256
+ }
257
+
258
+ export namespace UploadAcknowledgeParams {
259
+ export interface Body {
260
+ /**
261
+ * The upload ID returned from /prepare endpoint
262
+ */
263
+ upload_id: string;
264
+ }
132
265
  }
133
266
 
134
267
  export interface UploadPrepareParams {
135
268
  /**
136
- * Optional file name. If not provided, a random UUID will be used.
269
+ * Array of files to prepare for upload
137
270
  */
138
- file_name?: string;
271
+ body: Array<UploadPrepareParams.Body>;
272
+ }
273
+
274
+ export namespace UploadPrepareParams {
275
+ export interface Body {
276
+ /**
277
+ * Optional file name. If not provided, a random UUID will be used.
278
+ */
279
+ file_name?: string;
280
+ }
139
281
  }
140
282
 
141
283
  export declare namespace Upload {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.5.0'; // x-release-please-version
1
+ export const VERSION = '0.6.0'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.5.0";
1
+ export declare const VERSION = "0.6.0";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.5.0";
1
+ export declare const VERSION = "0.6.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.5.0'; // x-release-please-version
4
+ exports.VERSION = '0.6.0'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.5.0'; // x-release-please-version
1
+ export const VERSION = '0.6.0'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map