@transloadit/node 4.3.0 → 4.3.1

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/src/tus.ts CHANGED
@@ -9,6 +9,9 @@ import type { AssemblyStatus } from './alphalib/types/assemblyStatus.ts'
9
9
  import type { UploadProgress } from './Transloadit.ts'
10
10
 
11
11
  const log = debug('transloadit')
12
+ const logWarn = debug('transloadit:warn')
13
+
14
+ export type UploadBehavior = 'await' | 'background' | 'none'
12
15
 
13
16
  export interface Stream {
14
17
  path?: string
@@ -23,6 +26,7 @@ interface SendTusRequestOptions {
23
26
  onProgress: (options: UploadProgress) => void
24
27
  signal?: AbortSignal
25
28
  uploadUrls?: Record<string, string>
29
+ uploadBehavior?: UploadBehavior
26
30
  }
27
31
 
28
32
  export async function sendTusRequest({
@@ -33,6 +37,7 @@ export async function sendTusRequest({
33
37
  onProgress,
34
38
  signal,
35
39
  uploadUrls,
40
+ uploadBehavior = 'await',
36
41
  }: SendTusRequestOptions) {
37
42
  const streamLabels = Object.keys(streamsMap)
38
43
 
@@ -40,6 +45,7 @@ export async function sendTusRequest({
40
45
  let lastEmittedProgress = 0
41
46
 
42
47
  const sizes: Record<string, number> = {}
48
+ const uploadUrlsResult: Record<string, string> = { ...(uploadUrls ?? {}) }
43
49
 
44
50
  const haveUnknownLengthStreams = streamLabels.some((label) => !streamsMap[label]?.path)
45
51
 
@@ -67,6 +73,9 @@ export async function sendTusRequest({
67
73
 
68
74
  const uploadProgresses: Record<string, number> = {}
69
75
 
76
+ const completionPromises: Array<Promise<void>> = []
77
+ const uploadUrlPromises: Array<Promise<void>> = []
78
+
70
79
  async function uploadSingleStream(label: string) {
71
80
  uploadProgresses[label] = 0
72
81
 
@@ -110,7 +119,45 @@ export async function sendTusRequest({
110
119
 
111
120
  const filename = path ? basename(path) : label
112
121
 
113
- await new Promise<OnSuccessPayload>((resolvePromise, rejectPromise) => {
122
+ if (uploadBehavior === 'none' && uploadUrls?.[label]) {
123
+ uploadUrlsResult[label] = uploadUrls[label]
124
+ uploadUrlPromises.push(Promise.resolve())
125
+ completionPromises.push(Promise.resolve())
126
+ return
127
+ }
128
+
129
+ let urlResolved = false
130
+ let resolveUrl: () => void = () => {}
131
+ let rejectUrl: (err: Error) => void = () => {}
132
+ const uploadUrlPromise = new Promise<void>((resolve, reject) => {
133
+ resolveUrl = () => {
134
+ if (urlResolved) return
135
+ urlResolved = true
136
+ resolve()
137
+ }
138
+ rejectUrl = (err) => {
139
+ if (urlResolved) return
140
+ urlResolved = true
141
+ reject(err)
142
+ }
143
+ })
144
+
145
+ let resolveCompletion: () => void = () => {}
146
+ let rejectCompletion: (err: Error) => void = () => {}
147
+ const completionPromise = new Promise<void>((resolve, reject) => {
148
+ resolveCompletion = resolve
149
+ rejectCompletion = reject
150
+ })
151
+
152
+ uploadUrlPromises.push(uploadUrlPromise)
153
+ completionPromises.push(completionPromise)
154
+
155
+ if (uploadUrls?.[label]) {
156
+ uploadUrlsResult[label] = uploadUrls[label]
157
+ resolveUrl()
158
+ }
159
+
160
+ const startPromise = new Promise<void>((resolvePromise, rejectPromise) => {
114
161
  if (!assembly.assembly_ssl_url) {
115
162
  rejectPromise(new Error('assembly_ssl_url is not present in the assembly status'))
116
163
  return
@@ -124,15 +171,20 @@ export async function sendTusRequest({
124
171
 
125
172
  // Wrap resolve/reject to clean up abort listener
126
173
  let abortHandler: (() => void) | undefined
127
- const resolve = (payload: OnSuccessPayload) => {
174
+ const resolve = (_payload: OnSuccessPayload) => {
128
175
  if (abortHandler) signal?.removeEventListener('abort', abortHandler)
129
- resolvePromise(payload)
176
+ resolveCompletion()
177
+ resolveUrl()
178
+ resolvePromise()
130
179
  }
131
180
  const reject = (err: unknown) => {
132
181
  if (abortHandler) signal?.removeEventListener('abort', abortHandler)
182
+ rejectCompletion(err as Error)
183
+ rejectUrl(err as Error)
133
184
  rejectPromise(err)
134
185
  }
135
186
 
187
+ let tusUpload: Upload
136
188
  const tusOptions: UploadOptions = {
137
189
  endpoint: assembly.tus_url,
138
190
  uploadUrl: uploadUrls?.[label],
@@ -144,13 +196,24 @@ export async function sendTusRequest({
144
196
  onError: reject,
145
197
  onProgress: onTusProgress,
146
198
  onSuccess: resolve,
199
+ onUploadUrlAvailable: () => {
200
+ const url = tusUpload?.url
201
+ if (url) {
202
+ uploadUrlsResult[label] = url
203
+ }
204
+ resolveUrl()
205
+ if (uploadBehavior === 'none') {
206
+ tusUpload.abort()
207
+ resolveCompletion()
208
+ }
209
+ },
147
210
  }
148
211
  // tus-js-client doesn't like undefined/null
149
212
  if (size != null) tusOptions.uploadSize = size
150
213
  if (chunkSize) tusOptions.chunkSize = chunkSize
151
214
  if (uploadLengthDeferred) tusOptions.uploadLengthDeferred = uploadLengthDeferred
152
215
 
153
- const tusUpload = new Upload(stream, tusOptions)
216
+ tusUpload = new Upload(stream, tusOptions)
154
217
 
155
218
  // Handle abort signal
156
219
  if (signal) {
@@ -164,8 +227,31 @@ export async function sendTusRequest({
164
227
  tusUpload.start()
165
228
  })
166
229
 
167
- log(label, 'upload done')
230
+ if (uploadBehavior === 'await') {
231
+ await startPromise
232
+ log(label, 'upload done')
233
+ return
234
+ }
235
+
236
+ startPromise.catch((err) => {
237
+ logWarn('Background upload failed', err)
238
+ })
239
+
240
+ await uploadUrlPromise
241
+ log(label, 'upload started')
168
242
  }
169
243
 
170
244
  await pMap(streamLabels, uploadSingleStream, { concurrency: uploadConcurrency, signal })
245
+
246
+ await Promise.all(uploadUrlPromises)
247
+
248
+ if (uploadBehavior === 'await') {
249
+ await Promise.all(completionPromises)
250
+ } else {
251
+ Promise.allSettled(completionPromises).catch((err) => {
252
+ logWarn('Background upload failed', err)
253
+ })
254
+ }
255
+
256
+ return { uploadUrls: uploadUrlsResult }
171
257
  }