@transloadit/node 4.1.9 → 4.2.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.
Files changed (46) hide show
  1. package/README.md +23 -1
  2. package/dist/Transloadit.d.ts +17 -5
  3. package/dist/Transloadit.d.ts.map +1 -1
  4. package/dist/Transloadit.js +206 -39
  5. package/dist/Transloadit.js.map +1 -1
  6. package/dist/alphalib/mcache.d.ts.map +1 -1
  7. package/dist/alphalib/mcache.js +22 -7
  8. package/dist/alphalib/mcache.js.map +1 -1
  9. package/dist/alphalib/types/assemblyReplay.d.ts +56 -0
  10. package/dist/alphalib/types/assemblyReplay.d.ts.map +1 -1
  11. package/dist/alphalib/types/assemblyReplayNotification.d.ts +56 -0
  12. package/dist/alphalib/types/assemblyReplayNotification.d.ts.map +1 -1
  13. package/dist/alphalib/types/assemblyStatus.d.ts +63 -57
  14. package/dist/alphalib/types/assemblyStatus.d.ts.map +1 -1
  15. package/dist/alphalib/types/assemblyStatus.js +9 -1
  16. package/dist/alphalib/types/assemblyStatus.js.map +1 -1
  17. package/dist/alphalib/types/assemblyUrls.d.ts +1 -1
  18. package/dist/alphalib/types/assemblyUrls.d.ts.map +1 -1
  19. package/dist/alphalib/types/assemblyUrls.js.map +1 -1
  20. package/dist/alphalib/types/robots/_index.d.ts +608 -81
  21. package/dist/alphalib/types/robots/_index.d.ts.map +1 -1
  22. package/dist/alphalib/types/robots/_index.js +4 -0
  23. package/dist/alphalib/types/robots/_index.js.map +1 -1
  24. package/dist/alphalib/types/robots/_instructions-primitives.d.ts +4 -4
  25. package/dist/alphalib/types/robots/_instructions-primitives.d.ts.map +1 -1
  26. package/dist/alphalib/types/robots/_instructions-primitives.js +1 -0
  27. package/dist/alphalib/types/robots/_instructions-primitives.js.map +1 -1
  28. package/dist/alphalib/types/robots/document-optimize.d.ts +489 -0
  29. package/dist/alphalib/types/robots/document-optimize.d.ts.map +1 -0
  30. package/dist/alphalib/types/robots/document-optimize.js +151 -0
  31. package/dist/alphalib/types/robots/document-optimize.js.map +1 -0
  32. package/dist/alphalib/types/template.d.ts +1050 -174
  33. package/dist/alphalib/types/template.d.ts.map +1 -1
  34. package/dist/tus.d.ts +2 -1
  35. package/dist/tus.d.ts.map +1 -1
  36. package/dist/tus.js +2 -1
  37. package/dist/tus.js.map +1 -1
  38. package/package.json +2 -2
  39. package/src/Transloadit.ts +279 -49
  40. package/src/alphalib/mcache.ts +26 -7
  41. package/src/alphalib/types/assemblyStatus.ts +9 -1
  42. package/src/alphalib/types/assemblyUrls.ts +2 -5
  43. package/src/alphalib/types/robots/_index.ts +14 -0
  44. package/src/alphalib/types/robots/_instructions-primitives.ts +1 -0
  45. package/src/alphalib/types/robots/document-optimize.ts +180 -0
  46. package/src/tus.ts +3 -0
package/dist/tus.d.ts CHANGED
@@ -12,7 +12,8 @@ interface SendTusRequestOptions {
12
12
  uploadConcurrency: number;
13
13
  onProgress: (options: UploadProgress) => void;
14
14
  signal?: AbortSignal;
15
+ uploadUrls?: Record<string, string>;
15
16
  }
16
- export declare function sendTusRequest({ streamsMap, assembly, requestedChunkSize, uploadConcurrency, onProgress, signal, }: SendTusRequestOptions): Promise<void>;
17
+ export declare function sendTusRequest({ streamsMap, assembly, requestedChunkSize, uploadConcurrency, onProgress, signal, uploadUrls, }: SendTusRequestOptions): Promise<void>;
17
18
  export {};
18
19
  //# sourceMappingURL=tus.d.ts.map
package/dist/tus.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tus.d.ts","sourceRoot":"","sources":["../src/tus.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAK3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAItD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,QAAQ,CAAA;CACjB;AAED,UAAU,qBAAqB;IAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,QAAQ,EAAE,cAAc,CAAA;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,UAAU,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,wBAAsB,cAAc,CAAC,EACnC,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,MAAM,GACP,EAAE,qBAAqB,iBAsIvB"}
1
+ {"version":3,"file":"tus.d.ts","sourceRoot":"","sources":["../src/tus.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAK3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAItD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,QAAQ,CAAA;CACjB;AAED,UAAU,qBAAqB;IAC7B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,QAAQ,EAAE,cAAc,CAAA;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,UAAU,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACpC;AAED,wBAAsB,cAAc,CAAC,EACnC,UAAU,EACV,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,MAAM,EACN,UAAU,GACX,EAAE,qBAAqB,iBAuIvB"}
package/dist/tus.js CHANGED
@@ -4,7 +4,7 @@ import debug from 'debug';
4
4
  import pMap from 'p-map';
5
5
  import { Upload } from 'tus-js-client';
6
6
  const log = debug('transloadit');
7
- export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize, uploadConcurrency, onProgress, signal, }) {
7
+ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize, uploadConcurrency, onProgress, signal, uploadUrls, }) {
8
8
  const streamLabels = Object.keys(streamsMap);
9
9
  let totalBytes = 0;
10
10
  let lastEmittedProgress = 0;
@@ -88,6 +88,7 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
88
88
  };
89
89
  const tusOptions = {
90
90
  endpoint: assembly.tus_url,
91
+ uploadUrl: uploadUrls?.[label],
91
92
  metadata: {
92
93
  assembly_url: assembly.assembly_ssl_url,
93
94
  fieldname: label,
package/dist/tus.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tus.js","sourceRoot":"","sources":["../src/tus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tus.js","sourceRoot":"","sources":["../src/tus.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transloadit/node",
3
- "version": "4.1.9",
3
+ "version": "4.2.0",
4
4
  "description": "Node.js SDK for Transloadit",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -20,7 +20,7 @@
20
20
  "@aws-sdk/client-s3": "^3.891.0",
21
21
  "@aws-sdk/s3-request-presigner": "^3.891.0",
22
22
  "@transloadit/sev-logger": "^0.0.15",
23
- "@transloadit/utils": "^4.1.9",
23
+ "@transloadit/utils": "^4.2.0",
24
24
  "clipanion": "^4.0.0-rc.4",
25
25
  "debug": "^4.4.3",
26
26
  "dotenv": "^17.2.3",
@@ -1,7 +1,8 @@
1
1
  import * as assert from 'node:assert'
2
2
  import { randomUUID } from 'node:crypto'
3
3
  import { constants, createReadStream } from 'node:fs'
4
- import { access } from 'node:fs/promises'
4
+ import { access, stat } from 'node:fs/promises'
5
+ import { basename } from 'node:path'
5
6
  import type { Readable } from 'node:stream'
6
7
  import { setTimeout as delay } from 'node:timers/promises'
7
8
  import { getSignedSmartCdnUrl, signParamsSync } from '@transloadit/utils/node'
@@ -77,8 +78,73 @@ const { version } = packageJson
77
78
 
78
79
  export type AssemblyProgress = (assembly: AssemblyStatus) => void
79
80
 
80
- export interface CreateAssemblyOptions {
81
- params?: CreateAssemblyParams
81
+ type UploadDescriptor = {
82
+ label: string
83
+ filename: string
84
+ size?: number
85
+ path?: string
86
+ value?: Readable | IntoStreamInput
87
+ }
88
+
89
+ const getUploadKey = (
90
+ fieldname: string | null | undefined,
91
+ filename: string | null | undefined,
92
+ size: number | null | undefined,
93
+ ): string | null => {
94
+ if (!fieldname || !filename || size == null) return null
95
+ return JSON.stringify([fieldname, filename, size])
96
+ }
97
+
98
+ const getSizeFromValue = (value: Readable | IntoStreamInput): number | undefined => {
99
+ if (typeof value === 'string') return Buffer.byteLength(value)
100
+ if (Buffer.isBuffer(value)) return value.length
101
+ if (value instanceof ArrayBuffer) return value.byteLength
102
+ if (ArrayBuffer.isView(value)) return value.byteLength
103
+ return undefined
104
+ }
105
+
106
+ const toReadableUpload = (label: string, value: Readable | IntoStreamInput): Readable => {
107
+ const readable = isReadableStream(value)
108
+ if (!readable && isStream(value)) {
109
+ throw new Error(`Upload named "${label}" is not a Readable stream`)
110
+ }
111
+ return readable ? value : intoStream(value)
112
+ }
113
+
114
+ const buildStreamsMap = (descriptors: UploadDescriptor[]): Record<string, Stream> =>
115
+ Object.fromEntries(
116
+ descriptors.map((descriptor) => {
117
+ if (descriptor.path) {
118
+ const stream = createReadStream(descriptor.path)
119
+ return [descriptor.label, { stream, path: descriptor.path }]
120
+ }
121
+
122
+ const value = descriptor.value
123
+ if (value == null) {
124
+ throw new Error(`Upload named "${descriptor.label}" has no data`)
125
+ }
126
+ const stream = toReadableUpload(descriptor.label, value)
127
+ return [descriptor.label, { stream }]
128
+ }),
129
+ )
130
+
131
+ const pauseStreams = (streamsMap: Record<string, Stream>): void => {
132
+ for (const { stream } of Object.values(streamsMap)) {
133
+ stream.pause()
134
+ }
135
+ }
136
+
137
+ const createStreamErrorPromise = (streamsMap: Record<string, Stream>): Promise<never> => {
138
+ const promise = new Promise<never>((_resolve, reject) => {
139
+ for (const { stream } of Object.values(streamsMap)) {
140
+ stream.on('error', reject)
141
+ }
142
+ })
143
+ promise.catch(() => {})
144
+ return promise
145
+ }
146
+
147
+ interface AssemblyUploadOptions {
82
148
  files?: {
83
149
  [name: string]: string
84
150
  }
@@ -91,19 +157,32 @@ export interface CreateAssemblyOptions {
91
157
  timeout?: number
92
158
  onUploadProgress?: (uploadProgress: UploadProgress) => void
93
159
  onAssemblyProgress?: AssemblyProgress
94
- assemblyId?: string
95
160
  /**
96
- * Optional AbortSignal to cancel the assembly creation and upload.
161
+ * Optional AbortSignal to cancel the upload and any follow-up polling.
97
162
  * When aborted, any in-flight HTTP requests and TUS uploads will be cancelled.
98
163
  */
99
164
  signal?: AbortSignal
100
165
  }
101
166
 
167
+ export interface CreateAssemblyOptions extends AssemblyUploadOptions {
168
+ params?: CreateAssemblyParams
169
+ assemblyId?: string
170
+ }
171
+
172
+ export interface ResumeAssemblyUploadsOptions extends AssemblyUploadOptions {
173
+ assemblyUrl: string
174
+ }
175
+
102
176
  export interface AwaitAssemblyCompletionOptions {
103
177
  onAssemblyProgress?: AssemblyProgress
104
178
  timeout?: number
105
179
  interval?: number
106
180
  startTimeMs?: number
181
+ /**
182
+ * Optional assembly URL to poll instead of the configured client endpoint.
183
+ * Useful when resuming an Assembly created on a different host/region.
184
+ */
185
+ assemblyUrl?: string
107
186
  /**
108
187
  * Optional AbortSignal to cancel polling.
109
188
  * When aborted, the polling loop will stop and throw an AbortError.
@@ -159,6 +238,14 @@ function getHrTimeMs(): number {
159
238
  return Number(process.hrtime.bigint() / 1000000n)
160
239
  }
161
240
 
241
+ function getAssemblyIdFromUrl(assemblyUrl: string): string {
242
+ const match = assemblyUrl.match(/\/assemblies\/([^/?#]+)/)
243
+ if (!match) {
244
+ throw new Error(`Invalid assembly URL: ${assemblyUrl}`)
245
+ }
246
+ return match[1] ?? ''
247
+ }
248
+
162
249
  function checkResult<T>(result: T | { error: string }): asserts result is T {
163
250
  // In case server returned a successful HTTP status code, but an `error` in the JSON object
164
251
  // This happens sometimes, for example when createAssembly with an invalid file (IMPORT_FILE_ERROR)
@@ -276,36 +363,25 @@ export class Transloadit {
276
363
  { concurrency: 5 },
277
364
  )
278
365
 
279
- // Convert uploads to streams
280
- const streamsMap = Object.fromEntries(
281
- Object.entries(uploads).map(([label, value]) => {
282
- const isReadable = isReadableStream(value)
283
- if (!isReadable && isStream(value)) {
284
- // https://github.com/transloadit/node-sdk/issues/92
285
- throw new Error(`Upload named "${label}" is not a Readable stream`)
286
- }
287
-
288
- return [label, isReadableStream(value) ? value : intoStream(value)]
289
- }),
290
- )
291
-
292
- // Wrap in object structure (so we can store whether it's a pathless stream or not)
293
- const allStreamsMap = Object.fromEntries<Stream>(
294
- Object.entries(streamsMap).map(([label, stream]) => [label, { stream }]),
295
- )
296
-
297
- // Create streams from files too
298
- for (const [label, path] of Object.entries(files)) {
299
- const stream = createReadStream(path)
300
- allStreamsMap[label] = { stream, path } // File streams have path
301
- }
366
+ const descriptors: UploadDescriptor[] = [
367
+ ...Object.entries(files).map(([label, path]) => ({
368
+ label,
369
+ path,
370
+ filename: basename(path),
371
+ })),
372
+ ...Object.entries(uploads).map(([label, value]) => ({
373
+ label,
374
+ filename: label,
375
+ value,
376
+ })),
377
+ ]
378
+
379
+ const allStreamsMap = buildStreamsMap(descriptors)
302
380
 
303
381
  const allStreams = Object.values(allStreamsMap)
304
382
 
305
383
  // Pause all streams
306
- for (const { stream } of allStreams) {
307
- stream.pause()
308
- }
384
+ pauseStreams(allStreamsMap)
309
385
 
310
386
  // If any stream emits error, we want to handle this and exit with error.
311
387
  // This promise races against createAssemblyAndUpload() below via Promise.race().
@@ -313,12 +389,7 @@ export class Transloadit {
313
389
  // it's no longer awaited, but stream error handlers remain attached.
314
390
  // The no-op catch prevents Node's unhandled rejection warning if a stream
315
391
  // errors after the race is already won.
316
- const streamErrorPromise = new Promise<AssemblyStatus>((_resolve, reject) => {
317
- for (const { stream } of allStreams) {
318
- stream.on('error', reject)
319
- }
320
- })
321
- streamErrorPromise.catch(() => {})
392
+ const streamErrorPromise = createStreamErrorPromise(allStreamsMap)
322
393
 
323
394
  const createAssemblyAndUpload = async () => {
324
395
  const result: AssemblyStatus = await this._remoteJson({
@@ -368,6 +439,124 @@ export class Transloadit {
368
439
  return Object.assign(promise, { assemblyId: effectiveAssemblyId })
369
440
  }
370
441
 
442
+ async resumeAssemblyUploads(opts: ResumeAssemblyUploadsOptions): Promise<AssemblyStatus> {
443
+ const {
444
+ assemblyUrl,
445
+ files = {},
446
+ uploads = {},
447
+ chunkSize: requestedChunkSize = Number.POSITIVE_INFINITY,
448
+ uploadConcurrency = 10,
449
+ timeout = 24 * 60 * 60 * 1000, // 1 day
450
+ waitForCompletion = false,
451
+ onUploadProgress = () => {},
452
+ onAssemblyProgress = () => {},
453
+ signal,
454
+ } = opts
455
+
456
+ const startTimeMs = getHrTimeMs()
457
+
458
+ getAssemblyIdFromUrl(assemblyUrl)
459
+ const assembly = await this._fetchAssemblyStatus({ url: assemblyUrl, signal })
460
+ const statusUrl = assembly.assembly_ssl_url ?? assembly.assembly_url ?? assemblyUrl
461
+
462
+ const finishedKeys = new Set<string>()
463
+ for (const upload of assembly.uploads ?? []) {
464
+ const key = getUploadKey(upload.field ?? null, upload.basename ?? null, upload.size)
465
+ if (key) finishedKeys.add(key)
466
+ }
467
+ for (const upload of assembly.tus_uploads ?? []) {
468
+ if (!upload.finished) continue
469
+ const key = getUploadKey(upload.fieldname, upload.filename, upload.size)
470
+ if (key) finishedKeys.add(key)
471
+ }
472
+
473
+ const resumeUrls = new Map<string, string>()
474
+ for (const upload of assembly.tus_uploads ?? []) {
475
+ if (upload.finished) continue
476
+ if (!upload.upload_url) continue
477
+ const key = getUploadKey(upload.fieldname, upload.filename, upload.size)
478
+ if (key) resumeUrls.set(key, upload.upload_url)
479
+ }
480
+
481
+ const descriptors: UploadDescriptor[] = []
482
+
483
+ await pMap(
484
+ Object.entries(files),
485
+ async ([label, path]) => {
486
+ await access(path, constants.F_OK | constants.R_OK)
487
+ const info = await stat(path)
488
+ descriptors.push({
489
+ label,
490
+ path,
491
+ filename: basename(path),
492
+ size: info.size,
493
+ })
494
+ },
495
+ { concurrency: 5 },
496
+ )
497
+
498
+ for (const [label, value] of Object.entries(uploads)) {
499
+ descriptors.push({
500
+ label,
501
+ filename: label,
502
+ size: isReadableStream(value) ? undefined : getSizeFromValue(value),
503
+ value,
504
+ })
505
+ }
506
+
507
+ const descriptorsToUpload = descriptors.filter((descriptor) => {
508
+ const key = getUploadKey(descriptor.label, descriptor.filename, descriptor.size ?? null)
509
+ return key ? !finishedKeys.has(key) : true
510
+ })
511
+
512
+ const uploadUrlsByLabel: Record<string, string> = {}
513
+ for (const descriptor of descriptorsToUpload) {
514
+ if (!descriptor.path) continue
515
+ const key = getUploadKey(descriptor.label, descriptor.filename, descriptor.size ?? null)
516
+ if (!key) continue
517
+ const uploadUrl = resumeUrls.get(key)
518
+ if (uploadUrl) uploadUrlsByLabel[descriptor.label] = uploadUrl
519
+ }
520
+
521
+ const streamsMap = buildStreamsMap(descriptorsToUpload)
522
+ pauseStreams(streamsMap)
523
+
524
+ if (Object.keys(streamsMap).length > 0) {
525
+ const streamErrorPromise = createStreamErrorPromise(streamsMap)
526
+
527
+ const uploadPromise = sendTusRequest({
528
+ streamsMap,
529
+ assembly,
530
+ requestedChunkSize,
531
+ uploadConcurrency,
532
+ onProgress: onUploadProgress,
533
+ signal,
534
+ uploadUrls: uploadUrlsByLabel,
535
+ })
536
+
537
+ await Promise.race([uploadPromise, streamErrorPromise])
538
+ }
539
+
540
+ const latestAssembly = await this._fetchAssemblyStatus({ url: statusUrl, signal })
541
+ if (!waitForCompletion) return latestAssembly
542
+
543
+ if (latestAssembly.assembly_id == null) {
544
+ throw new InconsistentResponseError(
545
+ 'Server returned an assembly response without an assembly_id after resuming uploads',
546
+ )
547
+ }
548
+
549
+ const awaitResult = await this.awaitAssemblyCompletion(latestAssembly.assembly_id, {
550
+ timeout,
551
+ onAssemblyProgress,
552
+ startTimeMs,
553
+ assemblyUrl: statusUrl,
554
+ signal,
555
+ })
556
+ checkResult(awaitResult)
557
+ return awaitResult
558
+ }
559
+
371
560
  async awaitAssemblyCompletion(
372
561
  assemblyId: string,
373
562
  {
@@ -375,6 +564,7 @@ export class Transloadit {
375
564
  timeout,
376
565
  startTimeMs = getHrTimeMs(),
377
566
  interval = 1000,
567
+ assemblyUrl,
378
568
  signal,
379
569
  onPoll,
380
570
  }: AwaitAssemblyCompletionOptions = {},
@@ -383,6 +573,12 @@ export class Transloadit {
383
573
 
384
574
  let lastResult: AssemblyStatus | undefined
385
575
 
576
+ const fetchAssemblyStatus = (): Promise<AssemblyStatus> => {
577
+ return assemblyUrl
578
+ ? this._fetchAssemblyStatus({ url: assemblyUrl, signal })
579
+ : this.getAssembly(assemblyId, { signal })
580
+ }
581
+
386
582
  while (true) {
387
583
  // Check if caller wants to stop polling early
388
584
  if (onPoll?.() === false && lastResult) {
@@ -394,7 +590,7 @@ export class Transloadit {
394
590
  throw signal.reason ?? new DOMException('Aborted', 'AbortError')
395
591
  }
396
592
 
397
- const result = await this.getAssembly(assemblyId, { signal })
593
+ const result = await fetchAssemblyStatus()
398
594
  lastResult = result
399
595
 
400
596
  // If 'ok' is not in result, it implies a terminal state (e.g., error, completed, canceled).
@@ -576,16 +772,33 @@ export class Transloadit {
576
772
  assemblyId: string,
577
773
  options?: { signal?: AbortSignal },
578
774
  ): Promise<AssemblyStatus> {
579
- const rawResult = await this._remoteJson<Record<string, unknown>, OptionalAuthParams>({
580
- urlSuffix: `/assemblies/${assemblyId}`,
775
+ return await this._fetchAssemblyStatus({
776
+ assemblyId,
581
777
  signal: options?.signal,
582
778
  })
779
+ }
780
+
781
+ private async _fetchAssemblyStatus({
782
+ assemblyId,
783
+ url,
784
+ signal,
785
+ }: {
786
+ assemblyId?: string
787
+ url?: string
788
+ signal?: AbortSignal
789
+ }): Promise<AssemblyStatus> {
790
+ const rawResult = await this._remoteJson<Record<string, unknown>, OptionalAuthParams>({
791
+ url,
792
+ urlSuffix: url ? undefined : `/assemblies/${assemblyId}`,
793
+ signal,
794
+ })
583
795
 
584
796
  const parsedResult = zodParseWithContext(assemblyStatusSchema, rawResult)
585
797
 
586
798
  if (!parsedResult.success) {
799
+ const label = assemblyId ?? url ?? 'unknown'
587
800
  this.maybeThrowInconsistentResponseError(
588
- `The API responded with data that does not match the expected schema while getting Assembly: ${assemblyId}.\n${parsedResult.humanReadable}`,
801
+ `The API responded with data that does not match the expected schema while getting Assembly: ${label}.\n${parsedResult.humanReadable}`,
589
802
  )
590
803
  }
591
804
 
@@ -915,23 +1128,40 @@ export class Transloadit {
915
1128
 
916
1129
  // check whether we should retry
917
1130
  // https://transloadit.com/blog/2012/04/introducing-rate-limiting/
918
- if (
1131
+ const retryAfterHeader = err.response?.headers?.['retry-after']
1132
+ const retryAfterSeconds =
1133
+ typeof retryAfterHeader === 'string' ? Number(retryAfterHeader) : undefined
1134
+ const retryInFromInfo =
919
1135
  typeof body === 'object' &&
920
1136
  body != null &&
921
- 'error' in body &&
922
1137
  'info' in body &&
923
1138
  typeof body.info === 'object' &&
924
1139
  body.info != null &&
925
1140
  'retryIn' in body.info &&
926
1141
  typeof body.info.retryIn === 'number' &&
927
- Boolean(body.info.retryIn) &&
1142
+ body.info.retryIn > 0
1143
+ ? body.info.retryIn
1144
+ : undefined
1145
+ const retryInSec =
1146
+ retryInFromInfo ??
1147
+ (typeof retryAfterSeconds === 'number' && retryAfterSeconds > 0
1148
+ ? retryAfterSeconds
1149
+ : undefined)
1150
+ const shouldRetry =
928
1151
  retryCount < this._maxRetries && // 413 taken from https://transloadit.com/blog/2012/04/introducing-rate-limiting/
929
1152
  // todo can 413 be removed?
930
- ((statusCode === 413 && body.error === 'RATE_LIMIT_REACHED') || statusCode === 429)
931
- ) {
932
- const { retryIn: retryInSec } = body.info
933
- logWarn(`Rate limit reached, retrying request in approximately ${retryInSec} seconds.`)
934
- const retryInMs = 1000 * (retryInSec * (1 + 0.1 * Math.random()))
1153
+ ((statusCode === 413 &&
1154
+ body &&
1155
+ typeof body === 'object' &&
1156
+ body.error === 'RATE_LIMIT_REACHED') ||
1157
+ statusCode === 429)
1158
+
1159
+ if (shouldRetry) {
1160
+ const retryDelaySec = retryInSec ?? 1
1161
+ logWarn(
1162
+ `Rate limit reached, retrying request in approximately ${retryDelaySec} seconds.`,
1163
+ )
1164
+ const retryInMs = 1000 * (retryDelaySec * (1 + 0.1 * Math.random()))
935
1165
  await delay(retryInMs)
936
1166
  // Retry
937
1167
  } else {
@@ -37,11 +37,13 @@ interface CacheEntry<T> {
37
37
  */
38
38
  export class Mcache<T> {
39
39
  #cache: Map<string, CacheEntry<T>>
40
+ #pending: Map<string, Promise<T>>
40
41
  #opts: Required<Omit<McacheOpts, 'logger' | 'zodSchema' | 'keyFn'>> &
41
42
  Pick<McacheOpts, 'logger' | 'zodSchema' | 'keyFn'>
42
43
 
43
44
  constructor(opts: McacheOpts = {}) {
44
45
  this.#cache = new Map()
46
+ this.#pending = new Map()
45
47
  this.#opts = {
46
48
  ttlMs: opts.ttlMs ?? Number.POSITIVE_INFINITY,
47
49
  maxSize: opts.maxSize ?? 10_000,
@@ -56,6 +58,8 @@ export class Mcache<T> {
56
58
  * The cache key is generated from the args using JSON.stringify by default,
57
59
  * or using the custom keyFn if provided.
58
60
  */
61
+
62
+ // biome-ignore lint/suspicious/useAwait: @TODO check this out later
59
63
  async get(producer: () => Promise<T> | T, ...args: unknown[]): Promise<T> {
60
64
  const key = this.#opts.keyFn ? this.#opts.keyFn(...args) : JSON.stringify(args)
61
65
  const cached = this.#cache.get(key)
@@ -73,16 +77,31 @@ export class Mcache<T> {
73
77
  this.#cache.delete(key)
74
78
  }
75
79
 
80
+ const pending = this.#pending.get(key)
81
+ if (pending) {
82
+ this.#opts.logger?.debug(`Cache miss for key ${key}, waiting for pending request`)
83
+ return pending
84
+ }
85
+
76
86
  this.#opts.logger?.debug(`Cache miss for key ${key}, computing value`)
77
- const value = await producer()
78
87
 
79
- // Validate if schema provided
80
- if (this.#opts.zodSchema) {
81
- this.#opts.zodSchema.parse(value)
82
- }
88
+ const promise = Promise.resolve().then(async () => {
89
+ const value = await producer()
83
90
 
84
- this.#set(key, value)
85
- return value
91
+ // Validate if schema provided
92
+ if (this.#opts.zodSchema) {
93
+ this.#opts.zodSchema.parse(value)
94
+ }
95
+
96
+ this.#set(key, value)
97
+ return value
98
+ })
99
+
100
+ this.#pending.set(key, promise)
101
+ void promise.finally(() => {
102
+ this.#pending.delete(key)
103
+ })
104
+ return promise
86
105
  }
87
106
 
88
107
  /**
@@ -78,6 +78,8 @@ export const assemblyStatusErrCodeSchema = z.enum([
78
78
  'DIGITALOCEAN_STORE_ACCESS_DENIED',
79
79
  'DO_NOT_REUSE_ASSEMBLY_IDS',
80
80
  'DOCUMENT_CONVERT_UNSUPPORTED_CONVERSION',
81
+ 'DOCUMENT_OPTIMIZE_UNSUPPORTED_INPUT',
82
+ 'DOCUMENT_OPTIMIZE_VALIDATION',
81
83
  'DOCUMENT_SPLIT_VALIDATION',
82
84
  'FILE_DOWNLOAD_ERROR',
83
85
  'FILE_FILTER_DECLINED_FILE',
@@ -112,6 +114,7 @@ export const assemblyStatusErrCodeSchema = z.enum([
112
114
  'INVALID_AUTH_REFERER_PARAMETER',
113
115
  'INVALID_FILE_META_DATA',
114
116
  'INVALID_FORM_DATA',
117
+ 'INVALID_URL_ENCODING',
115
118
  'INVALID_INPUT_ERROR',
116
119
  'INVALID_PARAMS_FIELD',
117
120
  'INVALID_SIGNATURE',
@@ -156,6 +159,9 @@ export const assemblyStatusErrCodeSchema = z.enum([
156
159
  'TMP_FILE_DOWNLOAD_ERROR',
157
160
  'USER_COMMAND_ERROR',
158
161
  'VERIFIED_EMAIL_REQUIRED',
162
+ 'VIDEO_CONCAT_INVALID_INPUT',
163
+ 'VIDEO_CONCAT_NO_OUTPUT',
164
+ 'VIDEO_CONCAT_VALIDATION',
159
165
  'VIDEO_ENCODE_VALIDATION',
160
166
  'VIMEO_IMPORT_FAILURE',
161
167
  'WORKER_JOB_ERROR',
@@ -379,7 +385,7 @@ export const assemblyStatusUploadSchema = z
379
385
  basename: z.string(),
380
386
  ext: z.string(),
381
387
  size: z.number(),
382
- mime: z.string(),
388
+ mime: z.string().nullable(),
383
389
  type: z.string().nullable(),
384
390
  field: z.string().nullable(),
385
391
  md5hash: z.string().nullable(),
@@ -614,6 +620,8 @@ export const assemblyStatusErrSchema = assemblyStatusBaseSchema
614
620
  reason: z.string().optional(),
615
621
  step: z.string().optional(),
616
622
  previousStep: z.string().optional(),
623
+ file: z.string().optional(),
624
+ name: z.string().optional(),
617
625
  path: z.string().optional(),
618
626
  exitCode: z.number().nullable().optional(),
619
627
  exitSignal: z.string().nullable().optional(),
@@ -1,5 +1,5 @@
1
+ import type { AssemblyStatus } from './assemblyStatus.ts'
1
2
  import {
2
- type AssemblyStatus,
3
3
  isAssemblyBusyStatus,
4
4
  isAssemblyTerminalError,
5
5
  isAssemblyTerminalOk,
@@ -56,10 +56,7 @@ const assemblyUrlKeys = ['assembly_ssl_url', 'assembly_url', 'assemblyUrl'] as c
56
56
  const isRecord = (value: unknown): value is Record<string, unknown> =>
57
57
  value !== null && typeof value === 'object' && !Array.isArray(value)
58
58
 
59
- const pickString = (
60
- record: Record<string, unknown>,
61
- keys: readonly string[],
62
- ): string | null => {
59
+ const pickString = (record: Record<string, unknown>, keys: readonly string[]): string | null => {
63
60
  for (const key of keys) {
64
61
  const value = record[key]
65
62
  if (typeof value === 'string' && value.length > 0) return value