transloadit 4.2.0 → 4.4.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/README.md +116 -1
- package/dist/Transloadit.d.ts +49 -4
- package/dist/Transloadit.d.ts.map +1 -1
- package/dist/Transloadit.js +106 -22
- package/dist/Transloadit.js.map +1 -1
- package/dist/alphalib/assembly-linter.d.ts +123 -0
- package/dist/alphalib/assembly-linter.d.ts.map +1 -0
- package/dist/alphalib/assembly-linter.js +1142 -0
- package/dist/alphalib/assembly-linter.js.map +1 -0
- package/dist/alphalib/assembly-linter.lang.en.d.ts +87 -0
- package/dist/alphalib/assembly-linter.lang.en.d.ts.map +1 -0
- package/dist/alphalib/assembly-linter.lang.en.js +326 -0
- package/dist/alphalib/assembly-linter.lang.en.js.map +1 -0
- 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/alphalib/object.d.ts +20 -0
- package/dist/alphalib/object.d.ts.map +1 -0
- package/dist/alphalib/object.js +23 -0
- package/dist/alphalib/object.js.map +1 -0
- package/dist/alphalib/stepParsing.d.ts +93 -0
- package/dist/alphalib/stepParsing.d.ts.map +1 -0
- package/dist/alphalib/stepParsing.js +1154 -0
- package/dist/alphalib/stepParsing.js.map +1 -0
- package/dist/alphalib/templateMerge.d.ts +4 -0
- package/dist/alphalib/templateMerge.d.ts.map +1 -0
- package/dist/alphalib/templateMerge.js +22 -0
- package/dist/alphalib/templateMerge.js.map +1 -0
- package/dist/cli/commands/assemblies.d.ts +20 -1
- package/dist/cli/commands/assemblies.d.ts.map +1 -1
- package/dist/cli/commands/assemblies.js +137 -2
- package/dist/cli/commands/assemblies.js.map +1 -1
- package/dist/cli/commands/auth.d.ts.map +1 -1
- package/dist/cli/commands/auth.js +19 -19
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +5 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/upload.d.ts +22 -0
- package/dist/cli/commands/upload.d.ts.map +1 -0
- package/dist/cli/commands/upload.js +95 -0
- package/dist/cli/commands/upload.js.map +1 -0
- package/dist/cli/docs/assemblyLintingExamples.d.ts +2 -0
- package/dist/cli/docs/assemblyLintingExamples.d.ts.map +1 -0
- package/dist/cli/docs/assemblyLintingExamples.js +10 -0
- package/dist/cli/docs/assemblyLintingExamples.js.map +1 -0
- package/dist/cli/helpers.d.ts +11 -0
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/helpers.js +29 -0
- package/dist/cli/helpers.js.map +1 -1
- 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/lintAssemblyInput.d.ts +10 -0
- package/dist/lintAssemblyInput.d.ts.map +1 -0
- package/dist/lintAssemblyInput.js +73 -0
- package/dist/lintAssemblyInput.js.map +1 -0
- package/dist/lintAssemblyInstructions.d.ts +29 -0
- package/dist/lintAssemblyInstructions.d.ts.map +1 -0
- package/dist/lintAssemblyInstructions.js +33 -0
- package/dist/lintAssemblyInstructions.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 +6 -6
- package/src/Transloadit.ts +179 -27
- package/src/alphalib/assembly-linter.lang.en.ts +393 -0
- package/src/alphalib/assembly-linter.ts +1475 -0
- package/src/alphalib/goldenTemplates.ts +53 -0
- package/src/alphalib/object.ts +27 -0
- package/src/alphalib/stepParsing.ts +1465 -0
- package/src/alphalib/templateMerge.ts +32 -0
- package/src/alphalib/typings/json-to-ast.d.ts +34 -0
- package/src/cli/commands/assemblies.ts +161 -2
- package/src/cli/commands/auth.ts +19 -22
- package/src/cli/commands/index.ts +6 -0
- package/src/cli/commands/upload.ts +129 -0
- package/src/cli/docs/assemblyLintingExamples.ts +9 -0
- package/src/cli/helpers.ts +50 -0
- package/src/inputFiles.ts +278 -0
- package/src/lintAssemblyInput.ts +89 -0
- package/src/lintAssemblyInstructions.ts +72 -0
- package/src/robots.ts +317 -0
- package/src/tus.ts +91 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "transloadit",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "Node.js SDK for Transloadit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@aws-sdk/client-s3": "^3.891.0",
|
|
21
21
|
"@aws-sdk/s3-request-presigner": "^3.891.0",
|
|
22
|
-
"@transloadit/sev-logger": "^0.
|
|
23
|
-
"@transloadit/utils": "^4.
|
|
22
|
+
"@transloadit/sev-logger": "^0.1.9",
|
|
23
|
+
"@transloadit/utils": "^4.3.0",
|
|
24
24
|
"clipanion": "^4.0.0-rc.4",
|
|
25
25
|
"debug": "^4.4.3",
|
|
26
26
|
"dotenv": "^17.2.3",
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
"got": "14.4.9",
|
|
29
29
|
"into-stream": "^9.0.0",
|
|
30
30
|
"is-stream": "^4.0.1",
|
|
31
|
+
"json-to-ast": "^2.1.0",
|
|
32
|
+
"lodash-es": "^4.17.21",
|
|
31
33
|
"node-watch": "^0.7.4",
|
|
32
34
|
"p-map": "^7.0.3",
|
|
33
35
|
"p-queue": "^9.0.1",
|
|
@@ -77,7 +79,5 @@
|
|
|
77
79
|
"dist",
|
|
78
80
|
"src"
|
|
79
81
|
],
|
|
80
|
-
"bin":
|
|
81
|
-
"transloadit": "./dist/cli.js"
|
|
82
|
-
}
|
|
82
|
+
"bin": "./dist/cli.js"
|
|
83
83
|
}
|
package/src/Transloadit.ts
CHANGED
|
@@ -45,9 +45,14 @@ import type {
|
|
|
45
45
|
TemplateResponse,
|
|
46
46
|
} from './apiTypes.ts'
|
|
47
47
|
import InconsistentResponseError from './InconsistentResponseError.ts'
|
|
48
|
+
import type {
|
|
49
|
+
LintAssemblyInstructionsInput,
|
|
50
|
+
LintAssemblyInstructionsResult,
|
|
51
|
+
} from './lintAssemblyInstructions.ts'
|
|
52
|
+
import { lintAssemblyInstructions as lintAssemblyInstructionsInternal } from './lintAssemblyInstructions.ts'
|
|
48
53
|
import PaginationStream from './PaginationStream.ts'
|
|
49
54
|
import PollingTimeoutError from './PollingTimeoutError.ts'
|
|
50
|
-
import type { Stream } from './tus.ts'
|
|
55
|
+
import type { Stream, UploadBehavior } from './tus.ts'
|
|
51
56
|
import { sendTusRequest } from './tus.ts'
|
|
52
57
|
|
|
53
58
|
// See https://github.com/sindresorhus/got/tree/v11.8.6?tab=readme-ov-file#errors
|
|
@@ -61,10 +66,30 @@ export {
|
|
|
61
66
|
TimeoutError,
|
|
62
67
|
UploadError,
|
|
63
68
|
} from 'got'
|
|
64
|
-
|
|
69
|
+
export { goldenTemplates } from './alphalib/goldenTemplates.ts'
|
|
65
70
|
export type { AssemblyStatus } from './alphalib/types/assemblyStatus.ts'
|
|
66
71
|
export * from './apiTypes.ts'
|
|
67
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'
|
|
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'
|
|
68
93
|
|
|
69
94
|
const log = debug('transloadit')
|
|
70
95
|
const logWarn = debug('transloadit:warn')
|
|
@@ -74,6 +99,12 @@ export interface UploadProgress {
|
|
|
74
99
|
totalBytes?: number | undefined
|
|
75
100
|
}
|
|
76
101
|
|
|
102
|
+
export type { UploadBehavior }
|
|
103
|
+
|
|
104
|
+
export type AssemblyStatusWithUploadUrls = AssemblyStatus & {
|
|
105
|
+
upload_urls?: Record<string, string>
|
|
106
|
+
}
|
|
107
|
+
|
|
77
108
|
const { version } = packageJson
|
|
78
109
|
|
|
79
110
|
export type AssemblyProgress = (assembly: AssemblyStatus) => void
|
|
@@ -151,6 +182,7 @@ interface AssemblyUploadOptions {
|
|
|
151
182
|
uploads?: {
|
|
152
183
|
[name: string]: Readable | IntoStreamInput
|
|
153
184
|
}
|
|
185
|
+
uploadBehavior?: UploadBehavior
|
|
154
186
|
waitForCompletion?: boolean
|
|
155
187
|
chunkSize?: number
|
|
156
188
|
uploadConcurrency?: number
|
|
@@ -167,6 +199,10 @@ interface AssemblyUploadOptions {
|
|
|
167
199
|
export interface CreateAssemblyOptions extends AssemblyUploadOptions {
|
|
168
200
|
params?: CreateAssemblyParams
|
|
169
201
|
assemblyId?: string
|
|
202
|
+
/**
|
|
203
|
+
* Expected number of tus uploads when files will be uploaded separately.
|
|
204
|
+
*/
|
|
205
|
+
expectedUploads?: number
|
|
170
206
|
}
|
|
171
207
|
|
|
172
208
|
export interface ResumeAssemblyUploadsOptions extends AssemblyUploadOptions {
|
|
@@ -196,6 +232,14 @@ export interface AwaitAssemblyCompletionOptions {
|
|
|
196
232
|
onPoll?: () => boolean | undefined
|
|
197
233
|
}
|
|
198
234
|
|
|
235
|
+
export interface LintAssemblyInstructionsOptions
|
|
236
|
+
extends Omit<LintAssemblyInstructionsInput, 'template'> {
|
|
237
|
+
/**
|
|
238
|
+
* Template ID to merge with the provided instructions before linting.
|
|
239
|
+
*/
|
|
240
|
+
templateId?: string
|
|
241
|
+
}
|
|
242
|
+
|
|
199
243
|
export interface SmartCDNUrlOptions {
|
|
200
244
|
/**
|
|
201
245
|
* Workspace slug
|
|
@@ -223,7 +267,7 @@ export interface SmartCDNUrlOptions {
|
|
|
223
267
|
export type Fields = Record<string, string | number>
|
|
224
268
|
|
|
225
269
|
// A special promise that lets the user immediately get the assembly ID (synchronously before the request is sent)
|
|
226
|
-
interface CreateAssemblyPromise extends Promise<
|
|
270
|
+
interface CreateAssemblyPromise extends Promise<AssemblyStatusWithUploadUrls> {
|
|
227
271
|
assemblyId: string
|
|
228
272
|
}
|
|
229
273
|
|
|
@@ -259,9 +303,19 @@ function checkResult<T>(result: T | { error: string }): asserts result is T {
|
|
|
259
303
|
}
|
|
260
304
|
}
|
|
261
305
|
|
|
262
|
-
|
|
306
|
+
type AuthKeySecret = {
|
|
263
307
|
authKey: string
|
|
264
308
|
authSecret: string
|
|
309
|
+
authToken?: undefined
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
type AuthToken = {
|
|
313
|
+
authToken: string
|
|
314
|
+
authKey?: string
|
|
315
|
+
authSecret?: string
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
type BaseOptions = {
|
|
265
319
|
endpoint?: string
|
|
266
320
|
maxRetries?: number
|
|
267
321
|
timeout?: number
|
|
@@ -269,11 +323,15 @@ export interface Options {
|
|
|
269
323
|
validateResponses?: boolean
|
|
270
324
|
}
|
|
271
325
|
|
|
326
|
+
export type Options = BaseOptions & (AuthKeySecret | AuthToken)
|
|
327
|
+
|
|
272
328
|
export class Transloadit {
|
|
273
329
|
private _authKey: string
|
|
274
330
|
|
|
275
331
|
private _authSecret: string
|
|
276
332
|
|
|
333
|
+
private _authToken: string | null
|
|
334
|
+
|
|
277
335
|
private _endpoint: string
|
|
278
336
|
|
|
279
337
|
private _maxRetries: number
|
|
@@ -287,20 +345,26 @@ export class Transloadit {
|
|
|
287
345
|
private _validateResponses = false
|
|
288
346
|
|
|
289
347
|
constructor(opts: Options) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (opts.authSecret == null) {
|
|
295
|
-
throw new Error('Please provide an authSecret')
|
|
296
|
-
}
|
|
348
|
+
const rawToken = typeof opts?.authToken === 'string' ? opts.authToken.trim() : ''
|
|
349
|
+
const hasToken = rawToken.length > 0
|
|
297
350
|
|
|
298
351
|
if (opts.endpoint?.endsWith('/')) {
|
|
299
352
|
throw new Error('Trailing slash in endpoint is not allowed')
|
|
300
353
|
}
|
|
301
354
|
|
|
302
|
-
|
|
303
|
-
|
|
355
|
+
if (!hasToken) {
|
|
356
|
+
if (opts?.authKey == null) {
|
|
357
|
+
throw new Error('Please provide an authKey')
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (opts.authSecret == null) {
|
|
361
|
+
throw new Error('Please provide an authSecret')
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
this._authKey = opts.authKey ?? ''
|
|
366
|
+
this._authSecret = opts.authSecret ?? ''
|
|
367
|
+
this._authToken = hasToken ? rawToken : null
|
|
304
368
|
this._endpoint = opts.endpoint || 'https://api2.transloadit.com'
|
|
305
369
|
this._maxRetries = opts.maxRetries != null ? opts.maxRetries : 5
|
|
306
370
|
this._defaultTimeout = opts.timeout != null ? opts.timeout : 60000
|
|
@@ -336,7 +400,9 @@ export class Transloadit {
|
|
|
336
400
|
files = {},
|
|
337
401
|
uploads = {},
|
|
338
402
|
assemblyId,
|
|
403
|
+
expectedUploads,
|
|
339
404
|
signal,
|
|
405
|
+
uploadBehavior = 'await',
|
|
340
406
|
} = opts
|
|
341
407
|
|
|
342
408
|
// Keep track of how long the request took
|
|
@@ -392,30 +458,38 @@ export class Transloadit {
|
|
|
392
458
|
const streamErrorPromise = createStreamErrorPromise(allStreamsMap)
|
|
393
459
|
|
|
394
460
|
const createAssemblyAndUpload = async () => {
|
|
395
|
-
const
|
|
461
|
+
const totalExpectedUploads =
|
|
462
|
+
expectedUploads == null ? allStreams.length : Math.max(expectedUploads, allStreams.length)
|
|
463
|
+
|
|
464
|
+
const result: AssemblyStatusWithUploadUrls = await this._remoteJson({
|
|
396
465
|
urlSuffix,
|
|
397
466
|
method: 'post',
|
|
398
467
|
timeout: { request: timeout },
|
|
399
468
|
params,
|
|
400
469
|
fields: {
|
|
401
|
-
tus_num_expected_upload_files:
|
|
470
|
+
tus_num_expected_upload_files: totalExpectedUploads,
|
|
402
471
|
},
|
|
403
472
|
signal,
|
|
404
473
|
})
|
|
405
474
|
checkResult(result)
|
|
406
475
|
|
|
407
476
|
if (Object.keys(allStreamsMap).length > 0) {
|
|
408
|
-
await sendTusRequest({
|
|
477
|
+
const { uploadUrls } = await sendTusRequest({
|
|
409
478
|
streamsMap: allStreamsMap,
|
|
410
479
|
assembly: result,
|
|
411
480
|
onProgress: onUploadProgress,
|
|
412
481
|
requestedChunkSize,
|
|
413
482
|
uploadConcurrency,
|
|
414
483
|
signal,
|
|
484
|
+
uploadBehavior,
|
|
415
485
|
})
|
|
486
|
+
if (uploadBehavior !== 'await' && Object.keys(uploadUrls).length > 0) {
|
|
487
|
+
result.upload_urls = uploadUrls
|
|
488
|
+
}
|
|
416
489
|
}
|
|
417
490
|
|
|
418
|
-
|
|
491
|
+
const shouldWaitForCompletion = waitForCompletion && uploadBehavior === 'await'
|
|
492
|
+
if (!shouldWaitForCompletion) return result
|
|
419
493
|
|
|
420
494
|
if (result.assembly_id == null) {
|
|
421
495
|
throw new InconsistentResponseError(
|
|
@@ -439,7 +513,34 @@ export class Transloadit {
|
|
|
439
513
|
return Object.assign(promise, { assemblyId: effectiveAssemblyId })
|
|
440
514
|
}
|
|
441
515
|
|
|
442
|
-
|
|
516
|
+
/**
|
|
517
|
+
* Lint Assembly Instructions locally.
|
|
518
|
+
*
|
|
519
|
+
* If a templateId is provided, the template content is merged with the instructions,
|
|
520
|
+
* just like the API. When a template sets `allow_steps_override=false`, providing
|
|
521
|
+
* `steps` will throw a TEMPLATE_DENIES_STEPS_OVERRIDE error.
|
|
522
|
+
*
|
|
523
|
+
* The `assemblyInstructions` input may be a JSON string, a full instructions object,
|
|
524
|
+
* or a steps-only object (missing the `steps` property).
|
|
525
|
+
*/
|
|
526
|
+
async lintAssemblyInstructions(
|
|
527
|
+
options: LintAssemblyInstructionsOptions,
|
|
528
|
+
): Promise<LintAssemblyInstructionsResult> {
|
|
529
|
+
const { templateId, ...rest } = options
|
|
530
|
+
if (!templateId) {
|
|
531
|
+
return await lintAssemblyInstructionsInternal(rest)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const template = await this.getTemplate(templateId)
|
|
535
|
+
return await lintAssemblyInstructionsInternal({
|
|
536
|
+
...rest,
|
|
537
|
+
template: template.content,
|
|
538
|
+
})
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async resumeAssemblyUploads(
|
|
542
|
+
opts: ResumeAssemblyUploadsOptions,
|
|
543
|
+
): Promise<AssemblyStatusWithUploadUrls> {
|
|
443
544
|
const {
|
|
444
545
|
assemblyUrl,
|
|
445
546
|
files = {},
|
|
@@ -451,12 +552,16 @@ export class Transloadit {
|
|
|
451
552
|
onUploadProgress = () => {},
|
|
452
553
|
onAssemblyProgress = () => {},
|
|
453
554
|
signal,
|
|
555
|
+
uploadBehavior = 'await',
|
|
454
556
|
} = opts
|
|
455
557
|
|
|
456
558
|
const startTimeMs = getHrTimeMs()
|
|
457
559
|
|
|
458
560
|
getAssemblyIdFromUrl(assemblyUrl)
|
|
459
|
-
const assembly = await this._fetchAssemblyStatus({
|
|
561
|
+
const assembly: AssemblyStatusWithUploadUrls = await this._fetchAssemblyStatus({
|
|
562
|
+
url: assemblyUrl,
|
|
563
|
+
signal,
|
|
564
|
+
})
|
|
460
565
|
const statusUrl = assembly.assembly_ssl_url ?? assembly.assembly_url ?? assemblyUrl
|
|
461
566
|
|
|
462
567
|
const finishedKeys = new Set<string>()
|
|
@@ -532,13 +637,25 @@ export class Transloadit {
|
|
|
532
637
|
onProgress: onUploadProgress,
|
|
533
638
|
signal,
|
|
534
639
|
uploadUrls: uploadUrlsByLabel,
|
|
640
|
+
uploadBehavior,
|
|
535
641
|
})
|
|
536
642
|
|
|
537
643
|
await Promise.race([uploadPromise, streamErrorPromise])
|
|
644
|
+
const { uploadUrls } = await uploadPromise
|
|
645
|
+
if (uploadBehavior !== 'await' && Object.keys(uploadUrls).length > 0) {
|
|
646
|
+
assembly.upload_urls = uploadUrls
|
|
647
|
+
}
|
|
538
648
|
}
|
|
539
649
|
|
|
540
|
-
const latestAssembly = await this._fetchAssemblyStatus({
|
|
541
|
-
|
|
650
|
+
const latestAssembly: AssemblyStatusWithUploadUrls = await this._fetchAssemblyStatus({
|
|
651
|
+
url: statusUrl,
|
|
652
|
+
signal,
|
|
653
|
+
})
|
|
654
|
+
if (uploadBehavior !== 'await' && assembly.upload_urls) {
|
|
655
|
+
latestAssembly.upload_urls = assembly.upload_urls
|
|
656
|
+
}
|
|
657
|
+
const shouldWaitForCompletion = waitForCompletion && uploadBehavior === 'await'
|
|
658
|
+
if (!shouldWaitForCompletion) return latestAssembly
|
|
542
659
|
|
|
543
660
|
if (latestAssembly.assembly_id == null) {
|
|
544
661
|
throw new InconsistentResponseError(
|
|
@@ -662,6 +779,7 @@ export class Transloadit {
|
|
|
662
779
|
const { assembly_ssl_url: url } = await this.getAssembly(assemblyId)
|
|
663
780
|
const rawResult = await this._remoteJson<Record<string, unknown>, OptionalAuthParams>({
|
|
664
781
|
url,
|
|
782
|
+
isTrustedUrl: true,
|
|
665
783
|
method: 'delete',
|
|
666
784
|
})
|
|
667
785
|
|
|
@@ -790,6 +908,7 @@ export class Transloadit {
|
|
|
790
908
|
const rawResult = await this._remoteJson<Record<string, unknown>, OptionalAuthParams>({
|
|
791
909
|
url,
|
|
792
910
|
urlSuffix: url ? undefined : `/assemblies/${assemblyId}`,
|
|
911
|
+
isTrustedUrl: Boolean(url),
|
|
793
912
|
signal,
|
|
794
913
|
})
|
|
795
914
|
|
|
@@ -982,6 +1101,9 @@ export class Transloadit {
|
|
|
982
1101
|
params: OptionalAuthParams,
|
|
983
1102
|
algorithm?: string,
|
|
984
1103
|
): { signature: string; params: string } {
|
|
1104
|
+
if (!this._authKey || !this._authSecret) {
|
|
1105
|
+
throw new Error('Cannot sign params without authKey and authSecret.')
|
|
1106
|
+
}
|
|
985
1107
|
const jsonParams = this._prepareParams(params)
|
|
986
1108
|
const signature = this._calcSignature(jsonParams, algorithm)
|
|
987
1109
|
|
|
@@ -992,6 +1114,9 @@ export class Transloadit {
|
|
|
992
1114
|
* Construct a signed Smart CDN URL. See https://transloadit.com/docs/topics/signature-authentication/#smart-cdn.
|
|
993
1115
|
*/
|
|
994
1116
|
getSignedSmartCDNUrl(opts: SmartCDNUrlOptions): string {
|
|
1117
|
+
if (!this._authKey || !this._authSecret) {
|
|
1118
|
+
throw new Error('authKey and authSecret are required to sign Smart CDN URLs.')
|
|
1119
|
+
}
|
|
995
1120
|
return getSignedSmartCdnUrl({
|
|
996
1121
|
...opts,
|
|
997
1122
|
authKey: this._authKey,
|
|
@@ -1000,15 +1125,24 @@ export class Transloadit {
|
|
|
1000
1125
|
}
|
|
1001
1126
|
|
|
1002
1127
|
private _calcSignature(toSign: string, algorithm = 'sha384'): string {
|
|
1128
|
+
if (!this._authSecret) {
|
|
1129
|
+
throw new Error('Cannot sign params without authSecret.')
|
|
1130
|
+
}
|
|
1003
1131
|
return signParamsSync(toSign, this._authSecret, algorithm)
|
|
1004
1132
|
}
|
|
1005
1133
|
|
|
1006
1134
|
// Sets the multipart/form-data for POST, PUT and DELETE requests, including
|
|
1007
1135
|
// the streams, the signed params, and any additional fields.
|
|
1008
1136
|
private _appendForm(form: FormData, params: OptionalAuthParams, fields?: Fields): void {
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1137
|
+
const shouldSign = Boolean(this._authKey && this._authSecret)
|
|
1138
|
+
let jsonParams = JSON.stringify(params ?? {})
|
|
1139
|
+
let signature: string | undefined
|
|
1140
|
+
|
|
1141
|
+
if (shouldSign) {
|
|
1142
|
+
const sigData = this.calcSignature(params)
|
|
1143
|
+
jsonParams = sigData.params
|
|
1144
|
+
signature = sigData.signature
|
|
1145
|
+
}
|
|
1012
1146
|
|
|
1013
1147
|
form.append('params', jsonParams)
|
|
1014
1148
|
|
|
@@ -1018,16 +1152,24 @@ export class Transloadit {
|
|
|
1018
1152
|
}
|
|
1019
1153
|
}
|
|
1020
1154
|
|
|
1021
|
-
|
|
1155
|
+
if (signature) {
|
|
1156
|
+
form.append('signature', signature)
|
|
1157
|
+
}
|
|
1022
1158
|
}
|
|
1023
1159
|
|
|
1024
1160
|
// Implements HTTP GET query params, handling the case where the url already
|
|
1025
1161
|
// has params.
|
|
1026
1162
|
private _appendParamsToUrl(url: string, params: OptionalAuthParams): string {
|
|
1027
|
-
const { signature, params: jsonParams } = this.calcSignature(params)
|
|
1028
|
-
|
|
1029
1163
|
const prefix = url.indexOf('?') === -1 ? '?' : '&'
|
|
1030
1164
|
|
|
1165
|
+
const shouldSign = Boolean(this._authKey && this._authSecret)
|
|
1166
|
+
if (!shouldSign) {
|
|
1167
|
+
const jsonParams = JSON.stringify(params ?? {})
|
|
1168
|
+
return `${url}${prefix}params=${encodeURIComponent(jsonParams)}`
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
const { signature, params: jsonParams } = this.calcSignature(params)
|
|
1172
|
+
|
|
1031
1173
|
return `${url}${prefix}signature=${signature}¶ms=${encodeURIComponent(jsonParams)}`
|
|
1032
1174
|
}
|
|
1033
1175
|
|
|
@@ -1063,6 +1205,7 @@ export class Transloadit {
|
|
|
1063
1205
|
private async _remoteJson<TRet, TParams extends OptionalAuthParams>(opts: {
|
|
1064
1206
|
urlSuffix?: string
|
|
1065
1207
|
url?: string
|
|
1208
|
+
isTrustedUrl?: boolean
|
|
1066
1209
|
timeout?: Delays
|
|
1067
1210
|
method?: 'delete' | 'get' | 'post' | 'put'
|
|
1068
1211
|
params?: TParams
|
|
@@ -1073,6 +1216,7 @@ export class Transloadit {
|
|
|
1073
1216
|
const {
|
|
1074
1217
|
urlSuffix,
|
|
1075
1218
|
url: urlInput,
|
|
1219
|
+
isTrustedUrl = false,
|
|
1076
1220
|
timeout = { request: this._defaultTimeout },
|
|
1077
1221
|
method = 'get',
|
|
1078
1222
|
params = {},
|
|
@@ -1084,6 +1228,13 @@ export class Transloadit {
|
|
|
1084
1228
|
// Allow providing either a `urlSuffix` or a full `url`
|
|
1085
1229
|
if (!urlSuffix && !urlInput) throw new Error('No URL provided')
|
|
1086
1230
|
let url = urlInput || `${this._endpoint}${urlSuffix}`
|
|
1231
|
+
if (urlInput && !isTrustedUrl) {
|
|
1232
|
+
const allowed = new URL(this._endpoint)
|
|
1233
|
+
const candidate = new URL(urlInput)
|
|
1234
|
+
if (allowed.origin !== candidate.origin) {
|
|
1235
|
+
throw new Error(`Untrusted URL: ${candidate.origin}`)
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1087
1238
|
|
|
1088
1239
|
if (method === 'get') {
|
|
1089
1240
|
url = this._appendParamsToUrl(url, params)
|
|
@@ -1108,6 +1259,7 @@ export class Transloadit {
|
|
|
1108
1259
|
headers: {
|
|
1109
1260
|
'Transloadit-Client': `node-sdk:${version}`,
|
|
1110
1261
|
'User-Agent': undefined, // Remove got's user-agent
|
|
1262
|
+
...(this._authToken ? { Authorization: `Bearer ${this._authToken}` } : {}),
|
|
1111
1263
|
...headers,
|
|
1112
1264
|
},
|
|
1113
1265
|
responseType: 'json',
|