@thetechfossil/upfiles 1.0.6 → 1.0.9

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/index.d.mts CHANGED
@@ -56,6 +56,8 @@ type UpfilesClientOptions = {
56
56
  apiKey?: string;
57
57
  apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
58
58
  thumbnailsPath?: string;
59
+ completionPath?: string;
60
+ callCompletionEndpoint?: boolean;
59
61
  };
60
62
  /**
61
63
  * UpfilesClient - Main client class for interacting with Upfiles Plugin API
@@ -81,6 +83,8 @@ declare class UpfilesClient {
81
83
  private apiKey?;
82
84
  private apiKeyHeader;
83
85
  private thumbnailsPath;
86
+ private completionPath;
87
+ private callCompletionEndpoint;
84
88
  constructor(opts: UpfilesClientOptions);
85
89
  getPresignedUrl(params: {
86
90
  fileName: string;
@@ -94,8 +98,23 @@ declare class UpfilesClient {
94
98
  projectId?: string;
95
99
  folderPath?: string;
96
100
  fetchThumbnails?: boolean;
101
+ callCompletionEndpoint?: boolean;
97
102
  }): Promise<UploadedFileResult>;
103
+ completeUpload(params: {
104
+ fileKey: string;
105
+ originalName: string;
106
+ size: number;
107
+ contentType: string;
108
+ projectId?: string;
109
+ }): Promise<void>;
98
110
  getThumbnails(fileKey: string): Promise<Thumbnail[]>;
111
+ generateThumbnails(fileKey: string): Promise<{
112
+ masterWebp?: {
113
+ key: string;
114
+ url: string;
115
+ };
116
+ thumbnails: Thumbnail[];
117
+ }>;
99
118
  getProjectFiles(params?: {
100
119
  folderPath?: string;
101
120
  }): Promise<FileListItem[]>;
package/dist/index.d.ts CHANGED
@@ -56,6 +56,8 @@ type UpfilesClientOptions = {
56
56
  apiKey?: string;
57
57
  apiKeyHeader?: 'authorization' | 'x-api-key' | 'x-up-api-key';
58
58
  thumbnailsPath?: string;
59
+ completionPath?: string;
60
+ callCompletionEndpoint?: boolean;
59
61
  };
60
62
  /**
61
63
  * UpfilesClient - Main client class for interacting with Upfiles Plugin API
@@ -81,6 +83,8 @@ declare class UpfilesClient {
81
83
  private apiKey?;
82
84
  private apiKeyHeader;
83
85
  private thumbnailsPath;
86
+ private completionPath;
87
+ private callCompletionEndpoint;
84
88
  constructor(opts: UpfilesClientOptions);
85
89
  getPresignedUrl(params: {
86
90
  fileName: string;
@@ -94,8 +98,23 @@ declare class UpfilesClient {
94
98
  projectId?: string;
95
99
  folderPath?: string;
96
100
  fetchThumbnails?: boolean;
101
+ callCompletionEndpoint?: boolean;
97
102
  }): Promise<UploadedFileResult>;
103
+ completeUpload(params: {
104
+ fileKey: string;
105
+ originalName: string;
106
+ size: number;
107
+ contentType: string;
108
+ projectId?: string;
109
+ }): Promise<void>;
98
110
  getThumbnails(fileKey: string): Promise<Thumbnail[]>;
111
+ generateThumbnails(fileKey: string): Promise<{
112
+ masterWebp?: {
113
+ key: string;
114
+ url: string;
115
+ };
116
+ thumbnails: Thumbnail[];
117
+ }>;
99
118
  getProjectFiles(params?: {
100
119
  folderPath?: string;
101
120
  }): Promise<FileListItem[]>;
package/dist/index.js CHANGED
@@ -58,6 +58,8 @@ var UpfilesClient = class {
58
58
  this.apiKey = opts.apiKey;
59
59
  this.apiKeyHeader = opts.apiKeyHeader ?? "authorization";
60
60
  this.thumbnailsPath = opts.thumbnailsPath ?? "/api/plugin/thumbnails";
61
+ this.completionPath = opts.completionPath ?? "/api/plugin/upload/complete";
62
+ this.callCompletionEndpoint = opts.callCompletionEndpoint ?? false;
61
63
  }
62
64
  async getPresignedUrl(params) {
63
65
  if (!params.fileName) throw new Error("fileName is required");
@@ -116,6 +118,20 @@ var UpfilesClient = class {
116
118
  if (!res.ok) {
117
119
  throw new Error(`Upload failed with status ${res.status}`);
118
120
  }
121
+ const shouldCallCompletion = extras?.callCompletionEndpoint ?? this.callCompletionEndpoint;
122
+ if (shouldCallCompletion) {
123
+ try {
124
+ await this.completeUpload({
125
+ fileKey: presign.fileKey,
126
+ originalName: file.name,
127
+ size: file.size,
128
+ contentType: file.type || "application/octet-stream",
129
+ projectId: extras?.projectId
130
+ });
131
+ } catch (error) {
132
+ throw new Error(`Upload verification failed: ${error.message}`);
133
+ }
134
+ }
119
135
  let thumbnails;
120
136
  if (extras?.fetchThumbnails) {
121
137
  try {
@@ -135,6 +151,37 @@ var UpfilesClient = class {
135
151
  thumbnails
136
152
  };
137
153
  }
154
+ async completeUpload(params) {
155
+ const target = this.baseUrl ? `${this.baseUrl}${this.completionPath}` : this.completionPath;
156
+ const headers = {
157
+ "content-type": "application/json",
158
+ ...this.headers || {}
159
+ };
160
+ if (this.apiKey) {
161
+ if (this.apiKeyHeader === "authorization") {
162
+ headers["authorization"] = this.apiKey.startsWith("upk_") ? `Bearer ${this.apiKey}` : this.apiKey;
163
+ } else if (this.apiKeyHeader === "x-api-key") {
164
+ headers["x-api-key"] = this.apiKey;
165
+ } else {
166
+ headers["x-up-api-key"] = this.apiKey;
167
+ }
168
+ }
169
+ const res = await fetch(target, {
170
+ method: "POST",
171
+ headers,
172
+ credentials: this.withCredentials ? "include" : "same-origin",
173
+ body: JSON.stringify(params)
174
+ });
175
+ if (!res.ok) {
176
+ let msg = "Failed to complete upload";
177
+ try {
178
+ const data = await res.json();
179
+ msg = data.error || msg;
180
+ } catch {
181
+ }
182
+ throw new Error(msg);
183
+ }
184
+ }
138
185
  async getThumbnails(fileKey) {
139
186
  const target = this.baseUrl ? `${this.baseUrl}${this.thumbnailsPath}` : this.thumbnailsPath;
140
187
  const url = `${target}?fileKey=${encodeURIComponent(fileKey)}`;
@@ -161,6 +208,39 @@ var UpfilesClient = class {
161
208
  const data = await res.json();
162
209
  return data?.thumbnails ?? [];
163
210
  }
211
+ async generateThumbnails(fileKey) {
212
+ const target = this.baseUrl ? `${this.baseUrl}${this.thumbnailsPath}` : this.thumbnailsPath;
213
+ const headers = {
214
+ "content-type": "application/json",
215
+ ...this.headers || {}
216
+ };
217
+ if (this.apiKey) {
218
+ if (this.apiKeyHeader === "authorization") {
219
+ headers["authorization"] = this.apiKey.startsWith("upk_") ? `Bearer ${this.apiKey}` : this.apiKey;
220
+ } else if (this.apiKeyHeader === "x-api-key") {
221
+ headers["x-api-key"] = this.apiKey;
222
+ } else {
223
+ headers["x-up-api-key"] = this.apiKey;
224
+ }
225
+ }
226
+ const res = await fetch(target, {
227
+ method: "POST",
228
+ headers,
229
+ credentials: this.withCredentials ? "include" : "same-origin",
230
+ body: JSON.stringify({ fileKey })
231
+ });
232
+ if (!res.ok) {
233
+ let msg = "Failed to generate thumbnails";
234
+ try {
235
+ const data2 = await res.json();
236
+ msg = data2.error || msg;
237
+ } catch {
238
+ }
239
+ throw new Error(msg);
240
+ }
241
+ const data = await res.json();
242
+ return { masterWebp: data.masterWebp, thumbnails: data.thumbnails ?? [] };
243
+ }
164
244
  async getProjectFiles(params) {
165
245
  const basePath = this.thumbnailsPath.replace(/\/thumbnails$/, "");
166
246
  const filesPath = `${basePath}/files`;
@@ -286,45 +366,31 @@ var Uploader = ({
286
366
  xhr.setRequestHeader("Content-Type", item.type || "application/octet-stream");
287
367
  xhr.send(item.file);
288
368
  });
289
- let thumbs;
290
- try {
291
- if (fetchThumbnails) {
292
- thumbs = await client.getThumbnails(presign.fileKey);
293
- }
294
- } catch {
295
- }
296
369
  if (autoRecordToDb && projectId) {
297
370
  try {
298
- const baseUrl = clientOptions?.baseUrl || "";
299
- const url = baseUrl ? `${baseUrl}${recordUrl}` : recordUrl;
300
- const headers = {
301
- "content-type": "application/json",
302
- ...clientOptions?.headers || {}
303
- };
304
- if (clientOptions?.apiKey) {
305
- const keyHeader = clientOptions.apiKeyHeader || "authorization";
306
- if (keyHeader === "authorization") {
307
- headers["authorization"] = clientOptions.apiKey.startsWith("upk_") ? `Bearer ${clientOptions.apiKey}` : clientOptions.apiKey;
308
- } else {
309
- headers[keyHeader] = clientOptions.apiKey;
310
- }
311
- }
312
- await fetch(url, {
313
- method: "POST",
314
- headers,
315
- credentials: clientOptions?.withCredentials ? "include" : "same-origin",
316
- body: JSON.stringify({
317
- key: presign.fileKey,
318
- originalName: item.name,
319
- size: item.size,
320
- contentType: item.type,
321
- projectId
322
- })
371
+ await client.completeUpload({
372
+ fileKey: presign.fileKey,
373
+ originalName: item.name,
374
+ size: item.size,
375
+ contentType: item.type,
376
+ projectId
323
377
  });
324
378
  } catch (e) {
325
- console.warn("Failed to record file to database:", e);
379
+ console.error("Failed to complete upload:", e);
380
+ throw new Error(`Upload verification failed: ${e.message}`);
326
381
  }
327
382
  }
383
+ let thumbs;
384
+ let masterWebp;
385
+ try {
386
+ if (fetchThumbnails) {
387
+ const result2 = await client.generateThumbnails(presign.fileKey);
388
+ thumbs = result2.thumbnails;
389
+ masterWebp = result2.masterWebp;
390
+ }
391
+ } catch (e) {
392
+ console.warn("Failed to generate thumbnails:", e);
393
+ }
328
394
  const result = {
329
395
  ...item,
330
396
  status: "success",
@@ -334,7 +400,9 @@ var Uploader = ({
334
400
  projectId: presign.projectId,
335
401
  apiKeyId: presign.apiKeyId,
336
402
  // @ts-ignore - allow downstream to access thumbs if present
337
- thumbnails: thumbs
403
+ thumbnails: thumbs,
404
+ // @ts-ignore - allow downstream to access masterWebp if present
405
+ masterWebp
338
406
  };
339
407
  update({ status: "success", progress: 100, fileKey: presign.fileKey, publicUrl: presign.publicUrl });
340
408
  onClientUploadComplete?.(result);
package/dist/index.mjs CHANGED
@@ -9,6 +9,8 @@ var UpfilesClient = class {
9
9
  this.apiKey = opts.apiKey;
10
10
  this.apiKeyHeader = opts.apiKeyHeader ?? "authorization";
11
11
  this.thumbnailsPath = opts.thumbnailsPath ?? "/api/plugin/thumbnails";
12
+ this.completionPath = opts.completionPath ?? "/api/plugin/upload/complete";
13
+ this.callCompletionEndpoint = opts.callCompletionEndpoint ?? false;
12
14
  }
13
15
  async getPresignedUrl(params) {
14
16
  if (!params.fileName) throw new Error("fileName is required");
@@ -67,6 +69,20 @@ var UpfilesClient = class {
67
69
  if (!res.ok) {
68
70
  throw new Error(`Upload failed with status ${res.status}`);
69
71
  }
72
+ const shouldCallCompletion = extras?.callCompletionEndpoint ?? this.callCompletionEndpoint;
73
+ if (shouldCallCompletion) {
74
+ try {
75
+ await this.completeUpload({
76
+ fileKey: presign.fileKey,
77
+ originalName: file.name,
78
+ size: file.size,
79
+ contentType: file.type || "application/octet-stream",
80
+ projectId: extras?.projectId
81
+ });
82
+ } catch (error) {
83
+ throw new Error(`Upload verification failed: ${error.message}`);
84
+ }
85
+ }
70
86
  let thumbnails;
71
87
  if (extras?.fetchThumbnails) {
72
88
  try {
@@ -86,6 +102,37 @@ var UpfilesClient = class {
86
102
  thumbnails
87
103
  };
88
104
  }
105
+ async completeUpload(params) {
106
+ const target = this.baseUrl ? `${this.baseUrl}${this.completionPath}` : this.completionPath;
107
+ const headers = {
108
+ "content-type": "application/json",
109
+ ...this.headers || {}
110
+ };
111
+ if (this.apiKey) {
112
+ if (this.apiKeyHeader === "authorization") {
113
+ headers["authorization"] = this.apiKey.startsWith("upk_") ? `Bearer ${this.apiKey}` : this.apiKey;
114
+ } else if (this.apiKeyHeader === "x-api-key") {
115
+ headers["x-api-key"] = this.apiKey;
116
+ } else {
117
+ headers["x-up-api-key"] = this.apiKey;
118
+ }
119
+ }
120
+ const res = await fetch(target, {
121
+ method: "POST",
122
+ headers,
123
+ credentials: this.withCredentials ? "include" : "same-origin",
124
+ body: JSON.stringify(params)
125
+ });
126
+ if (!res.ok) {
127
+ let msg = "Failed to complete upload";
128
+ try {
129
+ const data = await res.json();
130
+ msg = data.error || msg;
131
+ } catch {
132
+ }
133
+ throw new Error(msg);
134
+ }
135
+ }
89
136
  async getThumbnails(fileKey) {
90
137
  const target = this.baseUrl ? `${this.baseUrl}${this.thumbnailsPath}` : this.thumbnailsPath;
91
138
  const url = `${target}?fileKey=${encodeURIComponent(fileKey)}`;
@@ -112,6 +159,39 @@ var UpfilesClient = class {
112
159
  const data = await res.json();
113
160
  return data?.thumbnails ?? [];
114
161
  }
162
+ async generateThumbnails(fileKey) {
163
+ const target = this.baseUrl ? `${this.baseUrl}${this.thumbnailsPath}` : this.thumbnailsPath;
164
+ const headers = {
165
+ "content-type": "application/json",
166
+ ...this.headers || {}
167
+ };
168
+ if (this.apiKey) {
169
+ if (this.apiKeyHeader === "authorization") {
170
+ headers["authorization"] = this.apiKey.startsWith("upk_") ? `Bearer ${this.apiKey}` : this.apiKey;
171
+ } else if (this.apiKeyHeader === "x-api-key") {
172
+ headers["x-api-key"] = this.apiKey;
173
+ } else {
174
+ headers["x-up-api-key"] = this.apiKey;
175
+ }
176
+ }
177
+ const res = await fetch(target, {
178
+ method: "POST",
179
+ headers,
180
+ credentials: this.withCredentials ? "include" : "same-origin",
181
+ body: JSON.stringify({ fileKey })
182
+ });
183
+ if (!res.ok) {
184
+ let msg = "Failed to generate thumbnails";
185
+ try {
186
+ const data2 = await res.json();
187
+ msg = data2.error || msg;
188
+ } catch {
189
+ }
190
+ throw new Error(msg);
191
+ }
192
+ const data = await res.json();
193
+ return { masterWebp: data.masterWebp, thumbnails: data.thumbnails ?? [] };
194
+ }
115
195
  async getProjectFiles(params) {
116
196
  const basePath = this.thumbnailsPath.replace(/\/thumbnails$/, "");
117
197
  const filesPath = `${basePath}/files`;
@@ -237,45 +317,31 @@ var Uploader = ({
237
317
  xhr.setRequestHeader("Content-Type", item.type || "application/octet-stream");
238
318
  xhr.send(item.file);
239
319
  });
240
- let thumbs;
241
- try {
242
- if (fetchThumbnails) {
243
- thumbs = await client.getThumbnails(presign.fileKey);
244
- }
245
- } catch {
246
- }
247
320
  if (autoRecordToDb && projectId) {
248
321
  try {
249
- const baseUrl = clientOptions?.baseUrl || "";
250
- const url = baseUrl ? `${baseUrl}${recordUrl}` : recordUrl;
251
- const headers = {
252
- "content-type": "application/json",
253
- ...clientOptions?.headers || {}
254
- };
255
- if (clientOptions?.apiKey) {
256
- const keyHeader = clientOptions.apiKeyHeader || "authorization";
257
- if (keyHeader === "authorization") {
258
- headers["authorization"] = clientOptions.apiKey.startsWith("upk_") ? `Bearer ${clientOptions.apiKey}` : clientOptions.apiKey;
259
- } else {
260
- headers[keyHeader] = clientOptions.apiKey;
261
- }
262
- }
263
- await fetch(url, {
264
- method: "POST",
265
- headers,
266
- credentials: clientOptions?.withCredentials ? "include" : "same-origin",
267
- body: JSON.stringify({
268
- key: presign.fileKey,
269
- originalName: item.name,
270
- size: item.size,
271
- contentType: item.type,
272
- projectId
273
- })
322
+ await client.completeUpload({
323
+ fileKey: presign.fileKey,
324
+ originalName: item.name,
325
+ size: item.size,
326
+ contentType: item.type,
327
+ projectId
274
328
  });
275
329
  } catch (e) {
276
- console.warn("Failed to record file to database:", e);
330
+ console.error("Failed to complete upload:", e);
331
+ throw new Error(`Upload verification failed: ${e.message}`);
277
332
  }
278
333
  }
334
+ let thumbs;
335
+ let masterWebp;
336
+ try {
337
+ if (fetchThumbnails) {
338
+ const result2 = await client.generateThumbnails(presign.fileKey);
339
+ thumbs = result2.thumbnails;
340
+ masterWebp = result2.masterWebp;
341
+ }
342
+ } catch (e) {
343
+ console.warn("Failed to generate thumbnails:", e);
344
+ }
279
345
  const result = {
280
346
  ...item,
281
347
  status: "success",
@@ -285,7 +351,9 @@ var Uploader = ({
285
351
  projectId: presign.projectId,
286
352
  apiKeyId: presign.apiKeyId,
287
353
  // @ts-ignore - allow downstream to access thumbs if present
288
- thumbnails: thumbs
354
+ thumbnails: thumbs,
355
+ // @ts-ignore - allow downstream to access masterWebp if present
356
+ masterWebp
289
357
  };
290
358
  update({ status: "success", progress: 100, fileKey: presign.fileKey, publicUrl: presign.publicUrl });
291
359
  onClientUploadComplete?.(result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thetechfossil/upfiles",
3
- "version": "1.0.6",
3
+ "version": "1.0.9",
4
4
  "description": "Lightweight client and React components for Upfiles Plugin API (presigned S3)",
5
5
  "license": "MIT",
6
6
  "author": "UpFiles",