@transloadit/node 4.1.9 → 4.3.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 +81 -1
- package/dist/Transloadit.d.ts +36 -5
- package/dist/Transloadit.d.ts.map +1 -1
- package/dist/Transloadit.js +228 -39
- 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/mcache.d.ts.map +1 -1
- package/dist/alphalib/mcache.js +22 -7
- package/dist/alphalib/mcache.js.map +1 -1
- 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/alphalib/types/assemblyReplay.d.ts +56 -0
- package/dist/alphalib/types/assemblyReplay.d.ts.map +1 -1
- package/dist/alphalib/types/assemblyReplayNotification.d.ts +56 -0
- package/dist/alphalib/types/assemblyReplayNotification.d.ts.map +1 -1
- package/dist/alphalib/types/assemblyStatus.d.ts +63 -57
- package/dist/alphalib/types/assemblyStatus.d.ts.map +1 -1
- package/dist/alphalib/types/assemblyStatus.js +9 -1
- package/dist/alphalib/types/assemblyStatus.js.map +1 -1
- package/dist/alphalib/types/assemblyUrls.d.ts +1 -1
- package/dist/alphalib/types/assemblyUrls.d.ts.map +1 -1
- package/dist/alphalib/types/assemblyUrls.js.map +1 -1
- package/dist/alphalib/types/robots/_index.d.ts +608 -81
- package/dist/alphalib/types/robots/_index.d.ts.map +1 -1
- package/dist/alphalib/types/robots/_index.js +4 -0
- package/dist/alphalib/types/robots/_index.js.map +1 -1
- package/dist/alphalib/types/robots/_instructions-primitives.d.ts +4 -4
- package/dist/alphalib/types/robots/_instructions-primitives.d.ts.map +1 -1
- package/dist/alphalib/types/robots/_instructions-primitives.js +1 -0
- package/dist/alphalib/types/robots/_instructions-primitives.js.map +1 -1
- package/dist/alphalib/types/robots/document-optimize.d.ts +489 -0
- package/dist/alphalib/types/robots/document-optimize.d.ts.map +1 -0
- package/dist/alphalib/types/robots/document-optimize.js +151 -0
- package/dist/alphalib/types/robots/document-optimize.js.map +1 -0
- package/dist/alphalib/types/template.d.ts +1050 -174
- package/dist/alphalib/types/template.d.ts.map +1 -1
- 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 +2 -1
- package/dist/cli/commands/index.js.map +1 -1
- 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/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/tus.d.ts +2 -1
- package/dist/tus.d.ts.map +1 -1
- package/dist/tus.js +2 -1
- package/dist/tus.js.map +1 -1
- package/package.json +5 -2
- package/src/Transloadit.ts +318 -49
- package/src/alphalib/assembly-linter.lang.en.ts +393 -0
- package/src/alphalib/assembly-linter.ts +1475 -0
- package/src/alphalib/mcache.ts +26 -7
- package/src/alphalib/object.ts +27 -0
- package/src/alphalib/stepParsing.ts +1465 -0
- package/src/alphalib/templateMerge.ts +32 -0
- package/src/alphalib/types/assemblyStatus.ts +9 -1
- package/src/alphalib/types/assemblyUrls.ts +2 -5
- package/src/alphalib/types/robots/_index.ts +14 -0
- package/src/alphalib/types/robots/_instructions-primitives.ts +1 -0
- package/src/alphalib/types/robots/document-optimize.ts +180 -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 +2 -0
- package/src/cli/docs/assemblyLintingExamples.ts +9 -0
- package/src/cli/helpers.ts +50 -0
- package/src/lintAssemblyInput.ts +89 -0
- package/src/lintAssemblyInstructions.ts +72 -0
- package/src/tus.ts +3 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import type { AssemblyLinterResult } from './assembly-linter.ts'
|
|
2
|
+
import { stackVersions } from './types/stackVersions.ts'
|
|
3
|
+
|
|
4
|
+
interface LintMessage {
|
|
5
|
+
simple: string
|
|
6
|
+
text: string
|
|
7
|
+
desc: string
|
|
8
|
+
example?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Define specific result types for each message
|
|
12
|
+
interface SmartCdnMaxStepsResult {
|
|
13
|
+
maxStepCount?: number
|
|
14
|
+
stepCount?: number
|
|
15
|
+
}
|
|
16
|
+
interface SmartCdnRobotNotAllowedResult {
|
|
17
|
+
robotName?: string
|
|
18
|
+
robot?: string
|
|
19
|
+
}
|
|
20
|
+
interface StepNameResult {
|
|
21
|
+
stepName?: string
|
|
22
|
+
}
|
|
23
|
+
interface RobotResult {
|
|
24
|
+
robot?: string
|
|
25
|
+
stepName?: string
|
|
26
|
+
}
|
|
27
|
+
interface StepNameWrongStepResult {
|
|
28
|
+
stepName?: string
|
|
29
|
+
wrongStepName?: string
|
|
30
|
+
}
|
|
31
|
+
interface SchemaViolationResult {
|
|
32
|
+
message?: string
|
|
33
|
+
}
|
|
34
|
+
interface FfmpegResult {
|
|
35
|
+
robot?: string
|
|
36
|
+
isAudioRobot?: boolean
|
|
37
|
+
}
|
|
38
|
+
interface FfmpegVersionResult {
|
|
39
|
+
stepName?: string
|
|
40
|
+
stackVersion?: string
|
|
41
|
+
isAudioRobot?: boolean
|
|
42
|
+
}
|
|
43
|
+
interface ImageMagickVersionResult {
|
|
44
|
+
stepName?: string
|
|
45
|
+
stackVersion?: string
|
|
46
|
+
}
|
|
47
|
+
interface DuplicateKeyResult {
|
|
48
|
+
stepName?: string
|
|
49
|
+
duplicateKeys?: string[]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const linterMessages = {
|
|
53
|
+
'smart-cdn-max-steps-exceeded': (result: SmartCdnMaxStepsResult): LintMessage => ({
|
|
54
|
+
simple: `Smart CDN Assemblies are limited to ${result.maxStepCount} steps, but found ${result.stepCount} steps`,
|
|
55
|
+
text: `Smart CDN Assemblies are limited to ${result.maxStepCount} steps, but found ${result.stepCount} steps`,
|
|
56
|
+
desc: `
|
|
57
|
+
When using the /file/serve Robot for Smart CDN Assemblies, Transloadit limits the number of steps to ${result.maxStepCount} for performance and security reasons.
|
|
58
|
+
|
|
59
|
+
Your Assembly currently has ${result.stepCount} steps. Please reduce the number of steps to ${result.maxStepCount} or fewer. Consider combining operations or restructuring your Assembly.
|
|
60
|
+
`,
|
|
61
|
+
}),
|
|
62
|
+
|
|
63
|
+
'smart-cdn-robot-not-allowed': (result: SmartCdnRobotNotAllowedResult): LintMessage => {
|
|
64
|
+
const robotName = result.robotName ?? result.robot ?? 'unknown'
|
|
65
|
+
return {
|
|
66
|
+
simple: `Robot "${robotName}" is not allowed in Smart CDN Assemblies`,
|
|
67
|
+
text: `Robot \`${robotName}\` is not allowed in Smart CDN Assemblies`,
|
|
68
|
+
desc: `
|
|
69
|
+
Smart CDN Assemblies, which use the /file/serve Robot, only support certain robots for security and performance reasons. The Robot "${robotName}" is not compatible with Smart CDN.
|
|
70
|
+
|
|
71
|
+
Please check the [Content Delivery documentation](/services/content-delivery/) for more information about which robots are allowed in Smart CDN Assemblies.
|
|
72
|
+
`,
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
'empty-steps': (): LintMessage => ({
|
|
76
|
+
simple: `The "steps" property is empty`,
|
|
77
|
+
text: 'The `steps` property is empty',
|
|
78
|
+
desc: 'The `steps` property is the main part of your Assembly Instructions. It defines which transcoding operations should be performed on your files and in which order. Each property inside `steps` represents a single transcoding operation, although this could be on multiple files passing through.',
|
|
79
|
+
}),
|
|
80
|
+
'missing-steps': (): LintMessage => ({
|
|
81
|
+
simple: `The "steps" property is missing`,
|
|
82
|
+
text: 'The `steps` property is missing',
|
|
83
|
+
desc: `
|
|
84
|
+
The \`steps\` property is the main part of your Assembly Instructions. It defines which transcoding operations should be performed on your files and in which order. Each property inside \`steps\` represents a single transcoding operation.
|
|
85
|
+
|
|
86
|
+
Here's an example of a valid \`steps\` structure:
|
|
87
|
+
|
|
88
|
+
\`\`\`json
|
|
89
|
+
{
|
|
90
|
+
"steps": {
|
|
91
|
+
"resize": {
|
|
92
|
+
"robot": "/image/resize",
|
|
93
|
+
"use": ":original",
|
|
94
|
+
"width": 100,
|
|
95
|
+
"height": 100
|
|
96
|
+
},
|
|
97
|
+
"store": {
|
|
98
|
+
"robot": "/s3/store",
|
|
99
|
+
"use": "resize"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
\`\`\`
|
|
104
|
+
`,
|
|
105
|
+
}),
|
|
106
|
+
|
|
107
|
+
'invalid-steps-type': (): LintMessage => ({
|
|
108
|
+
simple: `The "steps" property must be an object`,
|
|
109
|
+
text: 'The `steps` property must be an object',
|
|
110
|
+
desc: `
|
|
111
|
+
The \`steps\` property in your Assembly Instructions must be an object, not an array or any other type. Each key in the \`steps\` object represents a _Step_ name, and its value should be an object describing that Step.
|
|
112
|
+
|
|
113
|
+
Here's an example of the correct structure:
|
|
114
|
+
|
|
115
|
+
\`\`\`json
|
|
116
|
+
{
|
|
117
|
+
"steps": {
|
|
118
|
+
"resize": {
|
|
119
|
+
"robot": "/image/resize",
|
|
120
|
+
"use": ":original",
|
|
121
|
+
"width": 100,
|
|
122
|
+
"height": 100
|
|
123
|
+
},
|
|
124
|
+
"store": {
|
|
125
|
+
"robot": "/s3/store",
|
|
126
|
+
"use": "resize"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
\`\`\`
|
|
131
|
+
|
|
132
|
+
If you've used an array for \`steps\`, convert it to an object where each array item becomes a named _Step_.
|
|
133
|
+
`,
|
|
134
|
+
}),
|
|
135
|
+
|
|
136
|
+
'step-is-not-an-object': (result: StepNameResult): LintMessage => ({
|
|
137
|
+
simple: `Step "${result.stepName}" is not an object`,
|
|
138
|
+
text: `Step \`${result.stepName}\` is not an object`,
|
|
139
|
+
desc: 'Each _Step_ should be an object.',
|
|
140
|
+
}),
|
|
141
|
+
'missing-robot': (result: StepNameResult): LintMessage => ({
|
|
142
|
+
simple: `Step "${result.stepName}" is missing the "robot" parameter`,
|
|
143
|
+
text: `Step \`${result.stepName}\` is missing the \`robot\` parameter`,
|
|
144
|
+
desc: `
|
|
145
|
+
The \`robot\` parameter defines which _Robot_ should be used for a given _Step_. Each _Robot_ performs a specific transcoding operation on the files you give it. For example, 🤖/image/resize can resize and add effects to images. A list of available _Robots_ can be found in [the documentation](/docs/robots/#overview).
|
|
146
|
+
|
|
147
|
+
In order to use the _Robot_, you specify its name in the \`robot\` property. The \`use\` property indicates which files the _Robot_ should be working on. For example:
|
|
148
|
+
`,
|
|
149
|
+
}),
|
|
150
|
+
'undefined-robot': (result: RobotResult): LintMessage => ({
|
|
151
|
+
simple: `Step "${result.stepName}" is using a non-existing Robot "${result.robot}"`,
|
|
152
|
+
text: `Step \`${result.stepName}\` is using a non-existing Robot \`${result.robot}\``,
|
|
153
|
+
desc: `
|
|
154
|
+
The \`robot\` parameter defines which _Robot_ should be used for a given _Step_. Each _Robot_ performs a specific transcoding operation on the files it is given. However, the _Robot_ that you are referring to with (\`${result.robot}\`) does not exist. Please have a look at [our documentation](/docs/robots/#overview) for a list of all available _Robots_.
|
|
155
|
+
`,
|
|
156
|
+
}),
|
|
157
|
+
'missing-url': (): LintMessage => ({
|
|
158
|
+
simple: `The "url" property is missing`,
|
|
159
|
+
text: '🤖/html/convert either needs the `use` or `url` parameter',
|
|
160
|
+
desc: `
|
|
161
|
+
🤖/html/convert requires either the \`use\` or \`url\`. These are mutually exclusive. If the \`url\` parameter is given, the _Robot_ will create a screenshot of a given website. If the \`use\` parameter is given, the _Robot_ will create a screenshot of a provided HTML document. Here is an example showcasing the \`url\` parameter:
|
|
162
|
+
`,
|
|
163
|
+
}),
|
|
164
|
+
'schema-violation': (result: SchemaViolationResult): LintMessage => ({
|
|
165
|
+
simple: `Schema violation: ${result.message}`,
|
|
166
|
+
text: `Schema violation: ${result.message}`,
|
|
167
|
+
desc: 'It is possible that the Instructions do not match the schema.',
|
|
168
|
+
}),
|
|
169
|
+
'missing-use': (result: StepNameResult): LintMessage => ({
|
|
170
|
+
simple: `Step "${result.stepName}" is missing the "use" parameter`,
|
|
171
|
+
text: `Step \`${result.stepName}\` is missing the \`use\` parameter`,
|
|
172
|
+
desc: `
|
|
173
|
+
The \`use\` parameter defines which files a _Robot_ should process. You can reference another _Step_ name in order to use its output files as an input for your current _Step_, \`${result.stepName}\`. Alternatively, you can also use the built-in \`:original\` _Step_. In this case, the _Robot_ will process all uploaded files.
|
|
174
|
+
|
|
175
|
+
In the following example, you can see a pipeline where the _Step_ \`crop_thumbed\` uses the uploaded files from \`:original\` and the _Step_ \`exported\` uses \`:original\` and \`crop_thumbed\` as an input:
|
|
176
|
+
`,
|
|
177
|
+
}),
|
|
178
|
+
'missing-use-steps': (): LintMessage => ({
|
|
179
|
+
simple: `The "use" parameter is an object and must have a "steps" property`,
|
|
180
|
+
text: 'The `use` parameter is an object and must have a `steps` property',
|
|
181
|
+
desc: `
|
|
182
|
+
The \`use\` parameter can be a string, an object, or an array. The object form can be used if the output from multiple _Steps_ should be bundled and processed in one take, for instance, to create a single slideshow from many images, as opposed to a slideshow for each individual image.
|
|
183
|
+
|
|
184
|
+
In this case, the _Steps_ should be listed in the \`steps\` property inside the \`use\` object. In the following example, the \`archived\` _Step_ produces a TAR archive containing the files from the \`:original\` and \`resized\` _Steps_:
|
|
185
|
+
`,
|
|
186
|
+
}),
|
|
187
|
+
'undefined-step': (result: StepNameWrongStepResult): LintMessage => ({
|
|
188
|
+
simple: `Step "${result.stepName}" is using a non-existing Step "${result.wrongStepName}"`,
|
|
189
|
+
text: `Step \`${result.stepName}\` references a non-existing Step \`${result.wrongStepName}\``,
|
|
190
|
+
desc: `
|
|
191
|
+
The _Step_ \`${result.stepName}\` attempts to use the output files from _Step_ \`${result.wrongStepName}\`, but _Step_ \`${result.wrongStepName}\` does not exist in these _Assembly Instructions_. Please add the missing _Step_ or use another _Step_.
|
|
192
|
+
`,
|
|
193
|
+
}),
|
|
194
|
+
'wrong-use-type': (result: StepNameResult): LintMessage => ({
|
|
195
|
+
simple: `The "use" parameter must be a string, object, or an array`,
|
|
196
|
+
text: 'The `use` parameter must be a string, object, or an array',
|
|
197
|
+
desc: `
|
|
198
|
+
The \`use\` parameter can be a string, an object, or an array.
|
|
199
|
+
|
|
200
|
+
If the _Step_ \`${result.stepName}\` should only process the output of **one other Step**, you can use a string like \`"use": ":original"\`.
|
|
201
|
+
|
|
202
|
+
If the _Step_ \`${result.stepName}\` should process the output of **multiple Steps individually**, you can use an array, such as: \`"use": [ ":original", "crop_thumbed" ]\`.
|
|
203
|
+
|
|
204
|
+
If the _Step_ \`${result.stepName}\` should process the output of **multiple Steps combined**, you can use an object, such as in this more complex example:
|
|
205
|
+
`,
|
|
206
|
+
}),
|
|
207
|
+
'wrong-step-name': (): LintMessage => ({
|
|
208
|
+
simple: `When receiving uploads using "/upload/handle", the Step must be named ":original"`,
|
|
209
|
+
text: 'When receiving uploads using `/upload/handle`, the Step must be named `:original`',
|
|
210
|
+
desc: `
|
|
211
|
+
There are three constraints when using this _Robot_:
|
|
212
|
+
|
|
213
|
+
* **not** define a \`use\` parameter, contrary to all other _Robots_
|
|
214
|
+
* only use it **once** in a single set of _Assembly Instructions_
|
|
215
|
+
* name the _Step_ that it's used in: \`:original\`
|
|
216
|
+
`,
|
|
217
|
+
}),
|
|
218
|
+
'missing-input': (): LintMessage => ({
|
|
219
|
+
simple: 'The Template does not take any input files',
|
|
220
|
+
text: 'The _Template_ does not take any input files',
|
|
221
|
+
desc: `
|
|
222
|
+
Templates can operate on user-uploaded files, or import files from file storage services and from around the web.
|
|
223
|
+
|
|
224
|
+
Use [🤖/upload/handle](/docs/robots/#upload-handle) to process uploaded files. Transloadit offers a range of [import _Robot_s](/docs/robots/#service-file-importing) for services like S3, Dropbox, and many others.
|
|
225
|
+
`,
|
|
226
|
+
}),
|
|
227
|
+
'no-storage': (): LintMessage => ({
|
|
228
|
+
simple: 'No storage Robot is used to save the results',
|
|
229
|
+
text: 'No storage _Robot_ is used to save the results',
|
|
230
|
+
desc: `
|
|
231
|
+
Transloadit stores the encoding results of your _Assemblies_ for only 24 hours on its own servers at \`tmp.transloadit.com\`. After this period, the files will not be available from these locations anymore. To ensure that you are still able to access these files, we recommend to store them on your own servers (such as FTP and SFTP) or export them to cloud provider storage like AWS S3, Google Cloud Storage, or Microsoft Azure Storage.
|
|
232
|
+
|
|
233
|
+
For all of those destinations and many more, we offer [dedicated export Robots](/docs/robots/#service-file-exporting). For example, if you want to export your encoding results to AWS S3, you can use [🤖/s3/store](/docs/robots/#s3-store) like so:
|
|
234
|
+
`,
|
|
235
|
+
}),
|
|
236
|
+
'missing-original-storage': (): LintMessage => ({
|
|
237
|
+
simple: 'The uploaded files are not stored for later reprocessing',
|
|
238
|
+
text: 'The uploaded files are not stored for later reprocessing',
|
|
239
|
+
desc: `
|
|
240
|
+
Transloadit stores the uploaded files of your _Assemblies_ for only 24 hours on its own servers at \`tmp.transloadit.com\`. After this period, the files will not be available from these locations anymore. Storing not only the encoded result files but also the files that your users originally uploaded gives you the chance to re-encode them later into different formats as your requirements change. If you do not store them, they are lost forever, as asking your users to upload them again is likely not an option.
|
|
241
|
+
|
|
242
|
+
In order to store the uploaded files, you can add the \`:original\` _Step_ to the \`use\` parameter in your storage _Step_.
|
|
243
|
+
`,
|
|
244
|
+
}),
|
|
245
|
+
'empty-use-array': (result: StepNameResult): LintMessage => ({
|
|
246
|
+
simple: `The "use" array is empty`,
|
|
247
|
+
text: 'The `use` array is empty',
|
|
248
|
+
desc: `
|
|
249
|
+
The \`use\` parameter can be a string, an object, or an array. If it is an array, the _Step_ \`${result.stepName}\` will use the output of all _Steps_ that are referenced in the \`use\` parameter as its input. In following example, the \`exported\` _Step_ uses the output files from the \`crop_thumbed\` and the \`:original\` _Steps_:
|
|
250
|
+
`,
|
|
251
|
+
}),
|
|
252
|
+
'infinite-assembly': (result: StepNameResult): LintMessage => ({
|
|
253
|
+
simple: `This "use" parameter creates an infinite loop`,
|
|
254
|
+
text: 'The `use` parameter creates an infinite loop',
|
|
255
|
+
desc: `
|
|
256
|
+
The \`use\` parameter used in _Step_ \`${result.stepName}\` creates an infinite _Assembly_ execution loop. The _Assembly_ will error upon execution. Please make sure that the \`use\` parameter does not create an infinite loop.
|
|
257
|
+
`,
|
|
258
|
+
}),
|
|
259
|
+
'invalid-json': (result: SchemaViolationResult): LintMessage => ({
|
|
260
|
+
simple: result.message ?? 'Invalid JSON',
|
|
261
|
+
text: result.message ?? 'Invalid JSON',
|
|
262
|
+
desc: `
|
|
263
|
+
The _Assembly Instructions_ are written using JSON syntax, but the input above is not in a valid notation. Please consult the error on the editor's left hand side for more details.
|
|
264
|
+
`,
|
|
265
|
+
}),
|
|
266
|
+
'missing-ffmpeg-stack': (result: FfmpegResult): LintMessage => ({
|
|
267
|
+
simple: `🤖${result.robot} should define the "ffmpeg_stack" parameter`,
|
|
268
|
+
text: `🤖${result.robot} should define the \`ffmpeg_stack\` parameter`,
|
|
269
|
+
desc: `
|
|
270
|
+
The \`ffmpeg_stack\` parameter specifies which version of the FFmpeg stack should be used for this _Step_. If this parameter is absent, your _Step_ will fall back to an older FFmpeg stack which might not support all the latest features. The current recommendation is to use \`${stackVersions.ffmpeg.recommendedVersion}\`. Other valid values can be found at ${result.isAudioRobot ? '[Audio Encoding Presets](/docs/presets/audio)' : '[Video Encoding Presets](/docs/presets/video/)'}.
|
|
271
|
+
|
|
272
|
+
Here is an example showcasing the \`ffmpeg_stack\` parameter:
|
|
273
|
+
`,
|
|
274
|
+
}),
|
|
275
|
+
'wrong-ffmpeg-version': (result: FfmpegVersionResult): LintMessage => ({
|
|
276
|
+
simple: `Step "${result.stepName}" is using a nonexistent FFmpeg stack "${result.stackVersion}"`,
|
|
277
|
+
text: `Step \`${result.stepName}\` is using a nonexistent FFmpeg stack \`${result.stackVersion}\``,
|
|
278
|
+
desc: `
|
|
279
|
+
The \`ffmpeg_stack\` parameter defines which version of our internal FFmpeg stack should be used for a given _Step_. However, the \`ffmpeg_stack\` that you are referring to (\`${result.stackVersion}\`) does not exist. Please have a look at ${result.isAudioRobot ? '[Audio Encoding Presets](/docs/presets/audio)' : '[Video Encoding Presets](/docs/presets/video/)'} for a list of all available versions.
|
|
280
|
+
|
|
281
|
+
If you are unsure, we recommend using \`${stackVersions.ffmpeg.recommendedVersion}\`.
|
|
282
|
+
`,
|
|
283
|
+
}),
|
|
284
|
+
'missing-imagemagick-stack': (): LintMessage => ({
|
|
285
|
+
simple: `The "imagemagick_stack" parameter is missing`,
|
|
286
|
+
text: 'The `imagemagick_stack` parameter is missing',
|
|
287
|
+
desc: `
|
|
288
|
+
The \`imagemagick_stack\` parameter specifies which version of the ImageMagick stack should be used for this _Step_. If this parameter is absent, your _Step_ will fall back to an older ImageMagick stack which might not support all the latest features. The current recommendation is to use \`${stackVersions.imagemagick.recommendedVersion}\`. Other valid values can be found at [Supported Image Formats](/docs/supported-formats/#image-formats).
|
|
289
|
+
|
|
290
|
+
Here is an example showcasing the \`imagemagick_stack\` parameter:
|
|
291
|
+
`,
|
|
292
|
+
}),
|
|
293
|
+
'wrong-imagemagick-version': (result: ImageMagickVersionResult): LintMessage => ({
|
|
294
|
+
simple: `Step "${result.stepName}" is using a nonexistent ImageMagick stack "${result.stackVersion}"`,
|
|
295
|
+
text: `Step \`${result.stepName}\` is using a nonexistent ImageMagick stack \`${result.stackVersion}\``,
|
|
296
|
+
desc: `
|
|
297
|
+
The \`imagemagick_stack\` parameter defines which version of our internal ImageMagick stack should be used for a given _Step_. However, the \`imagemagick_stack\` that you are referring to (\`${result.stackVersion}\`) does not exist. Please have a look at [Supported Image Formats](/docs/supported-formats/#image-formats) for a list of all available versions.
|
|
298
|
+
|
|
299
|
+
If you are unsure, we recommend using \`${stackVersions.imagemagick.recommendedVersion}\`.
|
|
300
|
+
`,
|
|
301
|
+
}),
|
|
302
|
+
'unqualified-http-import-url': (result: StepNameResult): LintMessage => ({
|
|
303
|
+
simple: `The /http/import url in Step "${result.stepName}" should start with a protocol and domain name`,
|
|
304
|
+
text: `The \`url\` parameter in Step \`${result.stepName}\` should start with a protocol and domain name`,
|
|
305
|
+
desc: `
|
|
306
|
+
When using the /http/import Robot, it's important to prefix any path variable with a full URL including the protocol, domain/bucket name, and optionally folder, in the \`url\` or \`path\` parameter. This ensures that Transloadit only imports files from intended sources and attackers can't just import from any source.
|
|
307
|
+
|
|
308
|
+
Signature Authentication can also help prevent this, but it's recommended to have layers of protection against this if you can.
|
|
309
|
+
|
|
310
|
+
Instead of using a relative URL or just a field variable like \`\${'{fields.input}'}\`, you should provide a complete URL. For example:
|
|
311
|
+
|
|
312
|
+
\`\`\`json
|
|
313
|
+
"${result.stepName}": {
|
|
314
|
+
"robot": "/http/import",
|
|
315
|
+
"url": "https://example.com/\${fields.input}"
|
|
316
|
+
}
|
|
317
|
+
\`\`\`
|
|
318
|
+
|
|
319
|
+
This practice helps prevent potential security issues by ensuring that files are only imported from specified domains.
|
|
320
|
+
`,
|
|
321
|
+
}),
|
|
322
|
+
'duplicate-key-in-step': (result: DuplicateKeyResult): LintMessage => ({
|
|
323
|
+
simple: `Duplicate key(s) found${result.stepName ? ` in Step "${result.stepName}"` : ''}: ${result.duplicateKeys?.join(
|
|
324
|
+
', ',
|
|
325
|
+
)}`,
|
|
326
|
+
text: `Duplicate key(s) found${result.stepName ? ` in Step \`${result.stepName}\`` : ''}: \`${result.duplicateKeys?.join(', ')}\``,
|
|
327
|
+
desc: `
|
|
328
|
+
Each key within an object must be unique. Duplicate keys can lead to unexpected behavior and may cause some settings to be overwritten.
|
|
329
|
+
|
|
330
|
+
Please remove or rename the duplicate key(s)${result.stepName ? ` in the _Step_ \`${result.stepName}\`` : ''} to ensure that each key is unique.
|
|
331
|
+
`,
|
|
332
|
+
}),
|
|
333
|
+
'smart-cdn-input-field-missing': (): LintMessage => ({
|
|
334
|
+
simple: 'Smart CDN path component available as ${fields.input}',
|
|
335
|
+
text: `You may have accidentally omitted the Smart CDN's \`\${'{fields.input}'}\` path component`,
|
|
336
|
+
desc: `
|
|
337
|
+
When using Transloadit's Smart CDN with the 🤖 /file/serve Robot, the path component of the URL is automatically made available as \`\${'{fields.input}'}\`. For example, if your Smart CDN URL is \`https://my-app.tlcdn.com/img-preview/cities/amsterdam.jpg?w=400\`, then \`\${'{fields.input}'}\` would be set to \`/cities/amsterdam.jpg\`.
|
|
338
|
+
|
|
339
|
+
This is typically used to fetch the correct file from your storage bucket, before transforming and serving it. While the Smart CDN can be used in other ways, you may want to check if you accidentally omitted the \`\${'{fields.input}'}\` path component in your import _Step_. For example:
|
|
340
|
+
|
|
341
|
+
\`\`\`json
|
|
342
|
+
"imported": {
|
|
343
|
+
"robot": "/http/import",
|
|
344
|
+
"url": "https://example.com/\${fields.input}"
|
|
345
|
+
}
|
|
346
|
+
\`\`\`
|
|
347
|
+
`,
|
|
348
|
+
example: `{
|
|
349
|
+
"robot": "/file/serve",
|
|
350
|
+
"url": "s3://my-bucket\${fields.input}"
|
|
351
|
+
}`,
|
|
352
|
+
}),
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const firstNonEmptyLine = (text: string): string | undefined =>
|
|
356
|
+
text
|
|
357
|
+
.split('\n')
|
|
358
|
+
.map((line) => line.trim())
|
|
359
|
+
.find((line) => line.length > 0)
|
|
360
|
+
|
|
361
|
+
export const getLintIssueDescription = (issue: AssemblyLinterResult): string => {
|
|
362
|
+
const message = linterMessages[issue.code](issue)
|
|
363
|
+
return message.desc.trim()
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export const getLintIssueSummary = (issue: AssemblyLinterResult): string => {
|
|
367
|
+
if (issue.message) return issue.message
|
|
368
|
+
const fromDesc = issue.desc ?? getLintIssueDescription(issue)
|
|
369
|
+
return firstNonEmptyLine(fromDesc) ?? issue.code
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export type HydratedLintIssue = AssemblyLinterResult & {
|
|
373
|
+
desc: string
|
|
374
|
+
summary: string
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export const hydrateLintIssue = (issue: AssemblyLinterResult): HydratedLintIssue => {
|
|
378
|
+
const desc = issue.desc ?? getLintIssueDescription(issue)
|
|
379
|
+
const summary = getLintIssueSummary({ ...issue, desc })
|
|
380
|
+
return { ...issue, desc, summary }
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export const hydrateLintIssues = (issues: AssemblyLinterResult[]): HydratedLintIssue[] =>
|
|
384
|
+
issues.map((issue) => hydrateLintIssue(issue))
|
|
385
|
+
|
|
386
|
+
export const formatLintIssue = (issue: AssemblyLinterResult): string => {
|
|
387
|
+
const summary =
|
|
388
|
+
'summary' in issue && typeof issue.summary === 'string'
|
|
389
|
+
? issue.summary
|
|
390
|
+
: getLintIssueSummary(issue)
|
|
391
|
+
const stepInfo = issue.stepName ? ` ${issue.stepName}` : ''
|
|
392
|
+
return `[${issue.type}] ${issue.code} (${issue.row}:${issue.column})${stepInfo} ${summary}`
|
|
393
|
+
}
|