@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/README.md +58 -4
- package/dist/Transloadit.d.ts +26 -4
- package/dist/Transloadit.d.ts.map +1 -1
- package/dist/Transloadit.js +82 -21
- package/dist/Transloadit.js.map +1 -1
- package/dist/alphalib/goldenTemplates.d.ts +52 -0
- package/dist/alphalib/goldenTemplates.d.ts.map +1 -0
- package/dist/alphalib/goldenTemplates.js +46 -0
- package/dist/alphalib/goldenTemplates.js.map +1 -0
- package/dist/inputFiles.d.ts +41 -0
- package/dist/inputFiles.d.ts.map +1 -0
- package/dist/inputFiles.js +214 -0
- package/dist/inputFiles.js.map +1 -0
- package/dist/robots.d.ts +38 -0
- package/dist/robots.d.ts.map +1 -0
- package/dist/robots.js +230 -0
- package/dist/robots.js.map +1 -0
- package/dist/tus.d.ts +5 -1
- package/dist/tus.d.ts.map +1 -1
- package/dist/tus.js +80 -6
- package/dist/tus.js.map +1 -1
- package/package.json +1 -1
- package/src/Transloadit.ts +131 -26
- package/src/alphalib/goldenTemplates.ts +53 -0
- package/src/inputFiles.ts +278 -0
- package/src/robots.ts +317 -0
- package/src/tus.ts +91 -5
package/dist/tus.js
CHANGED
|
@@ -4,11 +4,13 @@ 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
|
-
|
|
7
|
+
const logWarn = debug('transloadit:warn');
|
|
8
|
+
export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize, uploadConcurrency, onProgress, signal, uploadUrls, uploadBehavior = 'await', }) {
|
|
8
9
|
const streamLabels = Object.keys(streamsMap);
|
|
9
10
|
let totalBytes = 0;
|
|
10
11
|
let lastEmittedProgress = 0;
|
|
11
12
|
const sizes = {};
|
|
13
|
+
const uploadUrlsResult = { ...(uploadUrls ?? {}) };
|
|
12
14
|
const haveUnknownLengthStreams = streamLabels.some((label) => !streamsMap[label]?.path);
|
|
13
15
|
// Initialize size data
|
|
14
16
|
await pMap(streamLabels, async (label) => {
|
|
@@ -27,6 +29,8 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
|
|
|
27
29
|
}
|
|
28
30
|
}, { concurrency: 5, signal });
|
|
29
31
|
const uploadProgresses = {};
|
|
32
|
+
const completionPromises = [];
|
|
33
|
+
const uploadUrlPromises = [];
|
|
30
34
|
async function uploadSingleStream(label) {
|
|
31
35
|
uploadProgresses[label] = 0;
|
|
32
36
|
const streamInfo = streamsMap[label];
|
|
@@ -64,7 +68,42 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
|
|
|
64
68
|
}
|
|
65
69
|
};
|
|
66
70
|
const filename = path ? basename(path) : label;
|
|
67
|
-
|
|
71
|
+
if (uploadBehavior === 'none' && uploadUrls?.[label]) {
|
|
72
|
+
uploadUrlsResult[label] = uploadUrls[label];
|
|
73
|
+
uploadUrlPromises.push(Promise.resolve());
|
|
74
|
+
completionPromises.push(Promise.resolve());
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
let urlResolved = false;
|
|
78
|
+
let resolveUrl = () => { };
|
|
79
|
+
let rejectUrl = () => { };
|
|
80
|
+
const uploadUrlPromise = new Promise((resolve, reject) => {
|
|
81
|
+
resolveUrl = () => {
|
|
82
|
+
if (urlResolved)
|
|
83
|
+
return;
|
|
84
|
+
urlResolved = true;
|
|
85
|
+
resolve();
|
|
86
|
+
};
|
|
87
|
+
rejectUrl = (err) => {
|
|
88
|
+
if (urlResolved)
|
|
89
|
+
return;
|
|
90
|
+
urlResolved = true;
|
|
91
|
+
reject(err);
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
let resolveCompletion = () => { };
|
|
95
|
+
let rejectCompletion = () => { };
|
|
96
|
+
const completionPromise = new Promise((resolve, reject) => {
|
|
97
|
+
resolveCompletion = resolve;
|
|
98
|
+
rejectCompletion = reject;
|
|
99
|
+
});
|
|
100
|
+
uploadUrlPromises.push(uploadUrlPromise);
|
|
101
|
+
completionPromises.push(completionPromise);
|
|
102
|
+
if (uploadUrls?.[label]) {
|
|
103
|
+
uploadUrlsResult[label] = uploadUrls[label];
|
|
104
|
+
resolveUrl();
|
|
105
|
+
}
|
|
106
|
+
const startPromise = new Promise((resolvePromise, rejectPromise) => {
|
|
68
107
|
if (!assembly.assembly_ssl_url) {
|
|
69
108
|
rejectPromise(new Error('assembly_ssl_url is not present in the assembly status'));
|
|
70
109
|
return;
|
|
@@ -76,16 +115,21 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
|
|
|
76
115
|
}
|
|
77
116
|
// Wrap resolve/reject to clean up abort listener
|
|
78
117
|
let abortHandler;
|
|
79
|
-
const resolve = (
|
|
118
|
+
const resolve = (_payload) => {
|
|
80
119
|
if (abortHandler)
|
|
81
120
|
signal?.removeEventListener('abort', abortHandler);
|
|
82
|
-
|
|
121
|
+
resolveCompletion();
|
|
122
|
+
resolveUrl();
|
|
123
|
+
resolvePromise();
|
|
83
124
|
};
|
|
84
125
|
const reject = (err) => {
|
|
85
126
|
if (abortHandler)
|
|
86
127
|
signal?.removeEventListener('abort', abortHandler);
|
|
128
|
+
rejectCompletion(err);
|
|
129
|
+
rejectUrl(err);
|
|
87
130
|
rejectPromise(err);
|
|
88
131
|
};
|
|
132
|
+
let tusUpload;
|
|
89
133
|
const tusOptions = {
|
|
90
134
|
endpoint: assembly.tus_url,
|
|
91
135
|
uploadUrl: uploadUrls?.[label],
|
|
@@ -97,6 +141,17 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
|
|
|
97
141
|
onError: reject,
|
|
98
142
|
onProgress: onTusProgress,
|
|
99
143
|
onSuccess: resolve,
|
|
144
|
+
onUploadUrlAvailable: () => {
|
|
145
|
+
const url = tusUpload?.url;
|
|
146
|
+
if (url) {
|
|
147
|
+
uploadUrlsResult[label] = url;
|
|
148
|
+
}
|
|
149
|
+
resolveUrl();
|
|
150
|
+
if (uploadBehavior === 'none') {
|
|
151
|
+
tusUpload.abort();
|
|
152
|
+
resolveCompletion();
|
|
153
|
+
}
|
|
154
|
+
},
|
|
100
155
|
};
|
|
101
156
|
// tus-js-client doesn't like undefined/null
|
|
102
157
|
if (size != null)
|
|
@@ -105,7 +160,7 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
|
|
|
105
160
|
tusOptions.chunkSize = chunkSize;
|
|
106
161
|
if (uploadLengthDeferred)
|
|
107
162
|
tusOptions.uploadLengthDeferred = uploadLengthDeferred;
|
|
108
|
-
|
|
163
|
+
tusUpload = new Upload(stream, tusOptions);
|
|
109
164
|
// Handle abort signal
|
|
110
165
|
if (signal) {
|
|
111
166
|
abortHandler = () => {
|
|
@@ -116,8 +171,27 @@ export async function sendTusRequest({ streamsMap, assembly, requestedChunkSize,
|
|
|
116
171
|
}
|
|
117
172
|
tusUpload.start();
|
|
118
173
|
});
|
|
119
|
-
|
|
174
|
+
if (uploadBehavior === 'await') {
|
|
175
|
+
await startPromise;
|
|
176
|
+
log(label, 'upload done');
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
startPromise.catch((err) => {
|
|
180
|
+
logWarn('Background upload failed', err);
|
|
181
|
+
});
|
|
182
|
+
await uploadUrlPromise;
|
|
183
|
+
log(label, 'upload started');
|
|
120
184
|
}
|
|
121
185
|
await pMap(streamLabels, uploadSingleStream, { concurrency: uploadConcurrency, signal });
|
|
186
|
+
await Promise.all(uploadUrlPromises);
|
|
187
|
+
if (uploadBehavior === 'await') {
|
|
188
|
+
await Promise.all(completionPromises);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
Promise.allSettled(completionPromises).catch((err) => {
|
|
192
|
+
logWarn('Background upload failed', err);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return { uploadUrls: uploadUrlsResult };
|
|
122
196
|
}
|
|
123
197
|
//# sourceMappingURL=tus.js.map
|
package/dist/tus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tus.js","sourceRoot":"","sources":["../src/tus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,IAAI,MAAM,OAAO,CAAA;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAItC,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"tus.js","sourceRoot":"","sources":["../src/tus.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/Transloadit.ts
CHANGED
|
@@ -52,7 +52,7 @@ import type {
|
|
|
52
52
|
import { lintAssemblyInstructions as lintAssemblyInstructionsInternal } from './lintAssemblyInstructions.ts'
|
|
53
53
|
import PaginationStream from './PaginationStream.ts'
|
|
54
54
|
import PollingTimeoutError from './PollingTimeoutError.ts'
|
|
55
|
-
import type { Stream } from './tus.ts'
|
|
55
|
+
import type { Stream, UploadBehavior } from './tus.ts'
|
|
56
56
|
import { sendTusRequest } from './tus.ts'
|
|
57
57
|
|
|
58
58
|
// See https://github.com/sindresorhus/got/tree/v11.8.6?tab=readme-ov-file#errors
|
|
@@ -66,11 +66,30 @@ export {
|
|
|
66
66
|
TimeoutError,
|
|
67
67
|
UploadError,
|
|
68
68
|
} from 'got'
|
|
69
|
-
|
|
69
|
+
export { goldenTemplates } from './alphalib/goldenTemplates.ts'
|
|
70
70
|
export type { AssemblyStatus } from './alphalib/types/assemblyStatus.ts'
|
|
71
71
|
export * from './apiTypes.ts'
|
|
72
72
|
export { InconsistentResponseError, ApiError }
|
|
73
|
+
export { mergeTemplateContent } from './alphalib/templateMerge.ts'
|
|
74
|
+
export type {
|
|
75
|
+
Base64Strategy,
|
|
76
|
+
InputFile,
|
|
77
|
+
PrepareInputFilesOptions,
|
|
78
|
+
PrepareInputFilesResult,
|
|
79
|
+
UploadInput,
|
|
80
|
+
UrlStrategy,
|
|
81
|
+
} from './inputFiles.ts'
|
|
82
|
+
export { prepareInputFiles } from './inputFiles.ts'
|
|
73
83
|
export type { LintAssemblyInstructionsResult, LintFatalLevel } from './lintAssemblyInstructions.ts'
|
|
84
|
+
export type {
|
|
85
|
+
RobotHelp,
|
|
86
|
+
RobotHelpOptions,
|
|
87
|
+
RobotListItem,
|
|
88
|
+
RobotListOptions,
|
|
89
|
+
RobotListResult,
|
|
90
|
+
RobotParamHelp,
|
|
91
|
+
} from './robots.ts'
|
|
92
|
+
export { getRobotHelp, listRobots } from './robots.ts'
|
|
74
93
|
|
|
75
94
|
const log = debug('transloadit')
|
|
76
95
|
const logWarn = debug('transloadit:warn')
|
|
@@ -80,6 +99,12 @@ export interface UploadProgress {
|
|
|
80
99
|
totalBytes?: number | undefined
|
|
81
100
|
}
|
|
82
101
|
|
|
102
|
+
export type { UploadBehavior }
|
|
103
|
+
|
|
104
|
+
export type AssemblyStatusWithUploadUrls = AssemblyStatus & {
|
|
105
|
+
upload_urls?: Record<string, string>
|
|
106
|
+
}
|
|
107
|
+
|
|
83
108
|
const { version } = packageJson
|
|
84
109
|
|
|
85
110
|
export type AssemblyProgress = (assembly: AssemblyStatus) => void
|
|
@@ -157,6 +182,7 @@ interface AssemblyUploadOptions {
|
|
|
157
182
|
uploads?: {
|
|
158
183
|
[name: string]: Readable | IntoStreamInput
|
|
159
184
|
}
|
|
185
|
+
uploadBehavior?: UploadBehavior
|
|
160
186
|
waitForCompletion?: boolean
|
|
161
187
|
chunkSize?: number
|
|
162
188
|
uploadConcurrency?: number
|
|
@@ -237,7 +263,7 @@ export interface SmartCDNUrlOptions {
|
|
|
237
263
|
export type Fields = Record<string, string | number>
|
|
238
264
|
|
|
239
265
|
// A special promise that lets the user immediately get the assembly ID (synchronously before the request is sent)
|
|
240
|
-
interface CreateAssemblyPromise extends Promise<
|
|
266
|
+
interface CreateAssemblyPromise extends Promise<AssemblyStatusWithUploadUrls> {
|
|
241
267
|
assemblyId: string
|
|
242
268
|
}
|
|
243
269
|
|
|
@@ -273,9 +299,19 @@ function checkResult<T>(result: T | { error: string }): asserts result is T {
|
|
|
273
299
|
}
|
|
274
300
|
}
|
|
275
301
|
|
|
276
|
-
|
|
302
|
+
type AuthKeySecret = {
|
|
277
303
|
authKey: string
|
|
278
304
|
authSecret: string
|
|
305
|
+
authToken?: undefined
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
type AuthToken = {
|
|
309
|
+
authToken: string
|
|
310
|
+
authKey?: string
|
|
311
|
+
authSecret?: string
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
type BaseOptions = {
|
|
279
315
|
endpoint?: string
|
|
280
316
|
maxRetries?: number
|
|
281
317
|
timeout?: number
|
|
@@ -283,11 +319,15 @@ export interface Options {
|
|
|
283
319
|
validateResponses?: boolean
|
|
284
320
|
}
|
|
285
321
|
|
|
322
|
+
export type Options = BaseOptions & (AuthKeySecret | AuthToken)
|
|
323
|
+
|
|
286
324
|
export class Transloadit {
|
|
287
325
|
private _authKey: string
|
|
288
326
|
|
|
289
327
|
private _authSecret: string
|
|
290
328
|
|
|
329
|
+
private _authToken: string | null
|
|
330
|
+
|
|
291
331
|
private _endpoint: string
|
|
292
332
|
|
|
293
333
|
private _maxRetries: number
|
|
@@ -301,20 +341,26 @@ export class Transloadit {
|
|
|
301
341
|
private _validateResponses = false
|
|
302
342
|
|
|
303
343
|
constructor(opts: Options) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (opts.authSecret == null) {
|
|
309
|
-
throw new Error('Please provide an authSecret')
|
|
310
|
-
}
|
|
344
|
+
const rawToken = typeof opts?.authToken === 'string' ? opts.authToken.trim() : ''
|
|
345
|
+
const hasToken = rawToken.length > 0
|
|
311
346
|
|
|
312
347
|
if (opts.endpoint?.endsWith('/')) {
|
|
313
348
|
throw new Error('Trailing slash in endpoint is not allowed')
|
|
314
349
|
}
|
|
315
350
|
|
|
316
|
-
|
|
317
|
-
|
|
351
|
+
if (!hasToken) {
|
|
352
|
+
if (opts?.authKey == null) {
|
|
353
|
+
throw new Error('Please provide an authKey')
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (opts.authSecret == null) {
|
|
357
|
+
throw new Error('Please provide an authSecret')
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
this._authKey = opts.authKey ?? ''
|
|
362
|
+
this._authSecret = opts.authSecret ?? ''
|
|
363
|
+
this._authToken = hasToken ? rawToken : null
|
|
318
364
|
this._endpoint = opts.endpoint || 'https://api2.transloadit.com'
|
|
319
365
|
this._maxRetries = opts.maxRetries != null ? opts.maxRetries : 5
|
|
320
366
|
this._defaultTimeout = opts.timeout != null ? opts.timeout : 60000
|
|
@@ -351,6 +397,7 @@ export class Transloadit {
|
|
|
351
397
|
uploads = {},
|
|
352
398
|
assemblyId,
|
|
353
399
|
signal,
|
|
400
|
+
uploadBehavior = 'await',
|
|
354
401
|
} = opts
|
|
355
402
|
|
|
356
403
|
// Keep track of how long the request took
|
|
@@ -406,7 +453,7 @@ export class Transloadit {
|
|
|
406
453
|
const streamErrorPromise = createStreamErrorPromise(allStreamsMap)
|
|
407
454
|
|
|
408
455
|
const createAssemblyAndUpload = async () => {
|
|
409
|
-
const result:
|
|
456
|
+
const result: AssemblyStatusWithUploadUrls = await this._remoteJson({
|
|
410
457
|
urlSuffix,
|
|
411
458
|
method: 'post',
|
|
412
459
|
timeout: { request: timeout },
|
|
@@ -419,17 +466,22 @@ export class Transloadit {
|
|
|
419
466
|
checkResult(result)
|
|
420
467
|
|
|
421
468
|
if (Object.keys(allStreamsMap).length > 0) {
|
|
422
|
-
await sendTusRequest({
|
|
469
|
+
const { uploadUrls } = await sendTusRequest({
|
|
423
470
|
streamsMap: allStreamsMap,
|
|
424
471
|
assembly: result,
|
|
425
472
|
onProgress: onUploadProgress,
|
|
426
473
|
requestedChunkSize,
|
|
427
474
|
uploadConcurrency,
|
|
428
475
|
signal,
|
|
476
|
+
uploadBehavior,
|
|
429
477
|
})
|
|
478
|
+
if (uploadBehavior !== 'await' && Object.keys(uploadUrls).length > 0) {
|
|
479
|
+
result.upload_urls = uploadUrls
|
|
480
|
+
}
|
|
430
481
|
}
|
|
431
482
|
|
|
432
|
-
|
|
483
|
+
const shouldWaitForCompletion = waitForCompletion && uploadBehavior === 'await'
|
|
484
|
+
if (!shouldWaitForCompletion) return result
|
|
433
485
|
|
|
434
486
|
if (result.assembly_id == null) {
|
|
435
487
|
throw new InconsistentResponseError(
|
|
@@ -478,7 +530,9 @@ export class Transloadit {
|
|
|
478
530
|
})
|
|
479
531
|
}
|
|
480
532
|
|
|
481
|
-
async resumeAssemblyUploads(
|
|
533
|
+
async resumeAssemblyUploads(
|
|
534
|
+
opts: ResumeAssemblyUploadsOptions,
|
|
535
|
+
): Promise<AssemblyStatusWithUploadUrls> {
|
|
482
536
|
const {
|
|
483
537
|
assemblyUrl,
|
|
484
538
|
files = {},
|
|
@@ -490,12 +544,16 @@ export class Transloadit {
|
|
|
490
544
|
onUploadProgress = () => {},
|
|
491
545
|
onAssemblyProgress = () => {},
|
|
492
546
|
signal,
|
|
547
|
+
uploadBehavior = 'await',
|
|
493
548
|
} = opts
|
|
494
549
|
|
|
495
550
|
const startTimeMs = getHrTimeMs()
|
|
496
551
|
|
|
497
552
|
getAssemblyIdFromUrl(assemblyUrl)
|
|
498
|
-
const assembly = await this._fetchAssemblyStatus({
|
|
553
|
+
const assembly: AssemblyStatusWithUploadUrls = await this._fetchAssemblyStatus({
|
|
554
|
+
url: assemblyUrl,
|
|
555
|
+
signal,
|
|
556
|
+
})
|
|
499
557
|
const statusUrl = assembly.assembly_ssl_url ?? assembly.assembly_url ?? assemblyUrl
|
|
500
558
|
|
|
501
559
|
const finishedKeys = new Set<string>()
|
|
@@ -571,13 +629,25 @@ export class Transloadit {
|
|
|
571
629
|
onProgress: onUploadProgress,
|
|
572
630
|
signal,
|
|
573
631
|
uploadUrls: uploadUrlsByLabel,
|
|
632
|
+
uploadBehavior,
|
|
574
633
|
})
|
|
575
634
|
|
|
576
635
|
await Promise.race([uploadPromise, streamErrorPromise])
|
|
636
|
+
const { uploadUrls } = await uploadPromise
|
|
637
|
+
if (uploadBehavior !== 'await' && Object.keys(uploadUrls).length > 0) {
|
|
638
|
+
assembly.upload_urls = uploadUrls
|
|
639
|
+
}
|
|
577
640
|
}
|
|
578
641
|
|
|
579
|
-
const latestAssembly = await this._fetchAssemblyStatus({
|
|
580
|
-
|
|
642
|
+
const latestAssembly: AssemblyStatusWithUploadUrls = await this._fetchAssemblyStatus({
|
|
643
|
+
url: statusUrl,
|
|
644
|
+
signal,
|
|
645
|
+
})
|
|
646
|
+
if (uploadBehavior !== 'await' && assembly.upload_urls) {
|
|
647
|
+
latestAssembly.upload_urls = assembly.upload_urls
|
|
648
|
+
}
|
|
649
|
+
const shouldWaitForCompletion = waitForCompletion && uploadBehavior === 'await'
|
|
650
|
+
if (!shouldWaitForCompletion) return latestAssembly
|
|
581
651
|
|
|
582
652
|
if (latestAssembly.assembly_id == null) {
|
|
583
653
|
throw new InconsistentResponseError(
|
|
@@ -701,6 +771,7 @@ export class Transloadit {
|
|
|
701
771
|
const { assembly_ssl_url: url } = await this.getAssembly(assemblyId)
|
|
702
772
|
const rawResult = await this._remoteJson<Record<string, unknown>, OptionalAuthParams>({
|
|
703
773
|
url,
|
|
774
|
+
isTrustedUrl: true,
|
|
704
775
|
method: 'delete',
|
|
705
776
|
})
|
|
706
777
|
|
|
@@ -829,6 +900,7 @@ export class Transloadit {
|
|
|
829
900
|
const rawResult = await this._remoteJson<Record<string, unknown>, OptionalAuthParams>({
|
|
830
901
|
url,
|
|
831
902
|
urlSuffix: url ? undefined : `/assemblies/${assemblyId}`,
|
|
903
|
+
isTrustedUrl: Boolean(url),
|
|
832
904
|
signal,
|
|
833
905
|
})
|
|
834
906
|
|
|
@@ -1021,6 +1093,9 @@ export class Transloadit {
|
|
|
1021
1093
|
params: OptionalAuthParams,
|
|
1022
1094
|
algorithm?: string,
|
|
1023
1095
|
): { signature: string; params: string } {
|
|
1096
|
+
if (!this._authKey || !this._authSecret) {
|
|
1097
|
+
throw new Error('Cannot sign params without authKey and authSecret.')
|
|
1098
|
+
}
|
|
1024
1099
|
const jsonParams = this._prepareParams(params)
|
|
1025
1100
|
const signature = this._calcSignature(jsonParams, algorithm)
|
|
1026
1101
|
|
|
@@ -1031,6 +1106,9 @@ export class Transloadit {
|
|
|
1031
1106
|
* Construct a signed Smart CDN URL. See https://transloadit.com/docs/topics/signature-authentication/#smart-cdn.
|
|
1032
1107
|
*/
|
|
1033
1108
|
getSignedSmartCDNUrl(opts: SmartCDNUrlOptions): string {
|
|
1109
|
+
if (!this._authKey || !this._authSecret) {
|
|
1110
|
+
throw new Error('authKey and authSecret are required to sign Smart CDN URLs.')
|
|
1111
|
+
}
|
|
1034
1112
|
return getSignedSmartCdnUrl({
|
|
1035
1113
|
...opts,
|
|
1036
1114
|
authKey: this._authKey,
|
|
@@ -1039,15 +1117,24 @@ export class Transloadit {
|
|
|
1039
1117
|
}
|
|
1040
1118
|
|
|
1041
1119
|
private _calcSignature(toSign: string, algorithm = 'sha384'): string {
|
|
1120
|
+
if (!this._authSecret) {
|
|
1121
|
+
throw new Error('Cannot sign params without authSecret.')
|
|
1122
|
+
}
|
|
1042
1123
|
return signParamsSync(toSign, this._authSecret, algorithm)
|
|
1043
1124
|
}
|
|
1044
1125
|
|
|
1045
1126
|
// Sets the multipart/form-data for POST, PUT and DELETE requests, including
|
|
1046
1127
|
// the streams, the signed params, and any additional fields.
|
|
1047
1128
|
private _appendForm(form: FormData, params: OptionalAuthParams, fields?: Fields): void {
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1129
|
+
const shouldSign = Boolean(this._authKey && this._authSecret)
|
|
1130
|
+
let jsonParams = JSON.stringify(params ?? {})
|
|
1131
|
+
let signature: string | undefined
|
|
1132
|
+
|
|
1133
|
+
if (shouldSign) {
|
|
1134
|
+
const sigData = this.calcSignature(params)
|
|
1135
|
+
jsonParams = sigData.params
|
|
1136
|
+
signature = sigData.signature
|
|
1137
|
+
}
|
|
1051
1138
|
|
|
1052
1139
|
form.append('params', jsonParams)
|
|
1053
1140
|
|
|
@@ -1057,16 +1144,24 @@ export class Transloadit {
|
|
|
1057
1144
|
}
|
|
1058
1145
|
}
|
|
1059
1146
|
|
|
1060
|
-
|
|
1147
|
+
if (signature) {
|
|
1148
|
+
form.append('signature', signature)
|
|
1149
|
+
}
|
|
1061
1150
|
}
|
|
1062
1151
|
|
|
1063
1152
|
// Implements HTTP GET query params, handling the case where the url already
|
|
1064
1153
|
// has params.
|
|
1065
1154
|
private _appendParamsToUrl(url: string, params: OptionalAuthParams): string {
|
|
1066
|
-
const { signature, params: jsonParams } = this.calcSignature(params)
|
|
1067
|
-
|
|
1068
1155
|
const prefix = url.indexOf('?') === -1 ? '?' : '&'
|
|
1069
1156
|
|
|
1157
|
+
const shouldSign = Boolean(this._authKey && this._authSecret)
|
|
1158
|
+
if (!shouldSign) {
|
|
1159
|
+
const jsonParams = JSON.stringify(params ?? {})
|
|
1160
|
+
return `${url}${prefix}params=${encodeURIComponent(jsonParams)}`
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
const { signature, params: jsonParams } = this.calcSignature(params)
|
|
1164
|
+
|
|
1070
1165
|
return `${url}${prefix}signature=${signature}¶ms=${encodeURIComponent(jsonParams)}`
|
|
1071
1166
|
}
|
|
1072
1167
|
|
|
@@ -1102,6 +1197,7 @@ export class Transloadit {
|
|
|
1102
1197
|
private async _remoteJson<TRet, TParams extends OptionalAuthParams>(opts: {
|
|
1103
1198
|
urlSuffix?: string
|
|
1104
1199
|
url?: string
|
|
1200
|
+
isTrustedUrl?: boolean
|
|
1105
1201
|
timeout?: Delays
|
|
1106
1202
|
method?: 'delete' | 'get' | 'post' | 'put'
|
|
1107
1203
|
params?: TParams
|
|
@@ -1112,6 +1208,7 @@ export class Transloadit {
|
|
|
1112
1208
|
const {
|
|
1113
1209
|
urlSuffix,
|
|
1114
1210
|
url: urlInput,
|
|
1211
|
+
isTrustedUrl = false,
|
|
1115
1212
|
timeout = { request: this._defaultTimeout },
|
|
1116
1213
|
method = 'get',
|
|
1117
1214
|
params = {},
|
|
@@ -1123,6 +1220,13 @@ export class Transloadit {
|
|
|
1123
1220
|
// Allow providing either a `urlSuffix` or a full `url`
|
|
1124
1221
|
if (!urlSuffix && !urlInput) throw new Error('No URL provided')
|
|
1125
1222
|
let url = urlInput || `${this._endpoint}${urlSuffix}`
|
|
1223
|
+
if (urlInput && !isTrustedUrl) {
|
|
1224
|
+
const allowed = new URL(this._endpoint)
|
|
1225
|
+
const candidate = new URL(urlInput)
|
|
1226
|
+
if (allowed.origin !== candidate.origin) {
|
|
1227
|
+
throw new Error(`Untrusted URL: ${candidate.origin}`)
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1126
1230
|
|
|
1127
1231
|
if (method === 'get') {
|
|
1128
1232
|
url = this._appendParamsToUrl(url, params)
|
|
@@ -1147,6 +1251,7 @@ export class Transloadit {
|
|
|
1147
1251
|
headers: {
|
|
1148
1252
|
'Transloadit-Client': `node-sdk:${version}`,
|
|
1149
1253
|
'User-Agent': undefined, // Remove got's user-agent
|
|
1254
|
+
...(this._authToken ? { Authorization: `Bearer ${this._authToken}` } : {}),
|
|
1150
1255
|
...headers,
|
|
1151
1256
|
},
|
|
1152
1257
|
responseType: 'json',
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type GoldenTemplate = {
|
|
2
|
+
slug: string
|
|
3
|
+
version: string
|
|
4
|
+
description: string
|
|
5
|
+
steps: Record<string, unknown>
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const goldenTemplates = {
|
|
9
|
+
'~transloadit/encode-hls-video@0.0.1': {
|
|
10
|
+
slug: '~transloadit/encode-hls-video@0.0.1',
|
|
11
|
+
version: '0.0.1',
|
|
12
|
+
description:
|
|
13
|
+
'Encode an input video into HLS renditions (270p, 360p, 540p) with an adaptive playlist.',
|
|
14
|
+
steps: {
|
|
15
|
+
':original': {
|
|
16
|
+
robot: '/upload/handle',
|
|
17
|
+
},
|
|
18
|
+
low: {
|
|
19
|
+
robot: '/video/encode',
|
|
20
|
+
use: ':original',
|
|
21
|
+
ffmpeg_stack: 'v7.0.0',
|
|
22
|
+
preset: 'hls-270p',
|
|
23
|
+
result: true,
|
|
24
|
+
turbo: true,
|
|
25
|
+
},
|
|
26
|
+
mid: {
|
|
27
|
+
robot: '/video/encode',
|
|
28
|
+
use: ':original',
|
|
29
|
+
ffmpeg_stack: 'v7.0.0',
|
|
30
|
+
preset: 'hls-360p',
|
|
31
|
+
result: true,
|
|
32
|
+
turbo: true,
|
|
33
|
+
},
|
|
34
|
+
high: {
|
|
35
|
+
robot: '/video/encode',
|
|
36
|
+
use: ':original',
|
|
37
|
+
ffmpeg_stack: 'v7.0.0',
|
|
38
|
+
preset: 'hls-540p',
|
|
39
|
+
result: true,
|
|
40
|
+
turbo: true,
|
|
41
|
+
},
|
|
42
|
+
adaptive: {
|
|
43
|
+
robot: '/video/adaptive',
|
|
44
|
+
use: {
|
|
45
|
+
steps: ['low', 'mid', 'high'],
|
|
46
|
+
bundle_steps: true,
|
|
47
|
+
},
|
|
48
|
+
technique: 'hls',
|
|
49
|
+
playlist_name: 'my_playlist.m3u8',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
} satisfies Record<string, GoldenTemplate>
|