transloadit 4.7.4 → 4.7.6

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 (142) hide show
  1. package/README.md +888 -5
  2. package/dist/Transloadit.d.ts +3 -3
  3. package/dist/Transloadit.d.ts.map +1 -1
  4. package/dist/Transloadit.js +2 -2
  5. package/dist/Transloadit.js.map +1 -1
  6. package/dist/alphalib/types/assembliesGet.d.ts +5 -0
  7. package/dist/alphalib/types/assembliesGet.d.ts.map +1 -1
  8. package/dist/alphalib/types/assemblyReplay.d.ts +5 -0
  9. package/dist/alphalib/types/assemblyReplay.d.ts.map +1 -1
  10. package/dist/alphalib/types/assemblyReplayNotification.d.ts +5 -0
  11. package/dist/alphalib/types/assemblyReplayNotification.d.ts.map +1 -1
  12. package/dist/alphalib/types/assemblyStatus.d.ts +25 -25
  13. package/dist/alphalib/types/assemblyStatus.d.ts.map +1 -1
  14. package/dist/alphalib/types/assemblyStatus.js +4 -1
  15. package/dist/alphalib/types/assemblyStatus.js.map +1 -1
  16. package/dist/alphalib/types/bill.d.ts +5 -0
  17. package/dist/alphalib/types/bill.d.ts.map +1 -1
  18. package/dist/alphalib/types/builtinTemplates.d.ts +83 -0
  19. package/dist/alphalib/types/builtinTemplates.d.ts.map +1 -0
  20. package/dist/alphalib/types/builtinTemplates.js +19 -0
  21. package/dist/alphalib/types/builtinTemplates.js.map +1 -0
  22. package/dist/alphalib/types/robots/ai-chat.d.ts.map +1 -1
  23. package/dist/alphalib/types/robots/ai-chat.js +1 -0
  24. package/dist/alphalib/types/robots/ai-chat.js.map +1 -1
  25. package/dist/alphalib/types/skillFrontmatter.d.ts +29 -0
  26. package/dist/alphalib/types/skillFrontmatter.d.ts.map +1 -0
  27. package/dist/alphalib/types/skillFrontmatter.js +19 -0
  28. package/dist/alphalib/types/skillFrontmatter.js.map +1 -0
  29. package/dist/alphalib/types/template.d.ts +36 -0
  30. package/dist/alphalib/types/template.d.ts.map +1 -1
  31. package/dist/alphalib/types/template.js +10 -0
  32. package/dist/alphalib/types/template.js.map +1 -1
  33. package/dist/alphalib/types/templateCredential.d.ts +10 -0
  34. package/dist/alphalib/types/templateCredential.d.ts.map +1 -1
  35. package/dist/cli/commands/assemblies.d.ts +8 -2
  36. package/dist/cli/commands/assemblies.d.ts.map +1 -1
  37. package/dist/cli/commands/assemblies.js +566 -411
  38. package/dist/cli/commands/assemblies.js.map +1 -1
  39. package/dist/cli/commands/index.d.ts.map +1 -1
  40. package/dist/cli/commands/index.js +5 -0
  41. package/dist/cli/commands/index.js.map +1 -1
  42. package/dist/cli/commands/templates.d.ts.map +1 -1
  43. package/dist/cli/commands/templates.js +4 -14
  44. package/dist/cli/commands/templates.js.map +1 -1
  45. package/dist/cli/fileProcessingOptions.d.ts +35 -0
  46. package/dist/cli/fileProcessingOptions.d.ts.map +1 -0
  47. package/dist/cli/fileProcessingOptions.js +182 -0
  48. package/dist/cli/fileProcessingOptions.js.map +1 -0
  49. package/dist/cli/generateIntentDocs.d.ts +2 -0
  50. package/dist/cli/generateIntentDocs.d.ts.map +1 -0
  51. package/dist/cli/generateIntentDocs.js +321 -0
  52. package/dist/cli/generateIntentDocs.js.map +1 -0
  53. package/dist/cli/intentCommandSpecs.d.ts +36 -0
  54. package/dist/cli/intentCommandSpecs.d.ts.map +1 -0
  55. package/dist/cli/intentCommandSpecs.js +181 -0
  56. package/dist/cli/intentCommandSpecs.js.map +1 -0
  57. package/dist/cli/intentCommands.d.ts +13 -0
  58. package/dist/cli/intentCommands.d.ts.map +1 -0
  59. package/dist/cli/intentCommands.js +368 -0
  60. package/dist/cli/intentCommands.js.map +1 -0
  61. package/dist/cli/intentFields.d.ts +25 -0
  62. package/dist/cli/intentFields.d.ts.map +1 -0
  63. package/dist/cli/intentFields.js +298 -0
  64. package/dist/cli/intentFields.js.map +1 -0
  65. package/dist/cli/intentInputPolicy.d.ts +10 -0
  66. package/dist/cli/intentInputPolicy.d.ts.map +1 -0
  67. package/dist/cli/intentInputPolicy.js +2 -0
  68. package/dist/cli/intentInputPolicy.js.map +1 -0
  69. package/dist/cli/intentRuntime.d.ts +114 -0
  70. package/dist/cli/intentRuntime.d.ts.map +1 -0
  71. package/dist/cli/intentRuntime.js +464 -0
  72. package/dist/cli/intentRuntime.js.map +1 -0
  73. package/dist/cli/resultFiles.d.ts +19 -0
  74. package/dist/cli/resultFiles.d.ts.map +1 -0
  75. package/dist/cli/resultFiles.js +66 -0
  76. package/dist/cli/resultFiles.js.map +1 -0
  77. package/dist/cli/resultUrls.d.ts +19 -0
  78. package/dist/cli/resultUrls.d.ts.map +1 -0
  79. package/dist/cli/resultUrls.js +36 -0
  80. package/dist/cli/resultUrls.js.map +1 -0
  81. package/dist/cli/semanticIntents/imageDescribe.d.ts +43 -0
  82. package/dist/cli/semanticIntents/imageDescribe.d.ts.map +1 -0
  83. package/dist/cli/semanticIntents/imageDescribe.js +188 -0
  84. package/dist/cli/semanticIntents/imageDescribe.js.map +1 -0
  85. package/dist/cli/semanticIntents/index.d.ts +18 -0
  86. package/dist/cli/semanticIntents/index.d.ts.map +1 -0
  87. package/dist/cli/semanticIntents/index.js +18 -0
  88. package/dist/cli/semanticIntents/index.js.map +1 -0
  89. package/dist/cli/semanticIntents/markdownPdf.d.ts +4 -0
  90. package/dist/cli/semanticIntents/markdownPdf.d.ts.map +1 -0
  91. package/dist/cli/semanticIntents/markdownPdf.js +93 -0
  92. package/dist/cli/semanticIntents/markdownPdf.js.map +1 -0
  93. package/dist/cli/semanticIntents/parsing.d.ts +11 -0
  94. package/dist/cli/semanticIntents/parsing.d.ts.map +1 -0
  95. package/dist/cli/semanticIntents/parsing.js +29 -0
  96. package/dist/cli/semanticIntents/parsing.js.map +1 -0
  97. package/dist/cli/stepsInput.d.ts +4 -0
  98. package/dist/cli/stepsInput.d.ts.map +1 -0
  99. package/dist/cli/stepsInput.js +23 -0
  100. package/dist/cli/stepsInput.js.map +1 -0
  101. package/dist/cli.d.ts +1 -1
  102. package/dist/cli.d.ts.map +1 -1
  103. package/dist/cli.js +5 -4
  104. package/dist/cli.js.map +1 -1
  105. package/dist/ensureUniqueCounter.d.ts +8 -0
  106. package/dist/ensureUniqueCounter.d.ts.map +1 -0
  107. package/dist/ensureUniqueCounter.js +48 -0
  108. package/dist/ensureUniqueCounter.js.map +1 -0
  109. package/dist/inputFiles.d.ts +9 -0
  110. package/dist/inputFiles.d.ts.map +1 -1
  111. package/dist/inputFiles.js +177 -26
  112. package/dist/inputFiles.js.map +1 -1
  113. package/dist/robots.js +1 -1
  114. package/dist/robots.js.map +1 -1
  115. package/package.json +9 -7
  116. package/src/Transloadit.ts +3 -3
  117. package/src/alphalib/types/assemblyStatus.ts +4 -1
  118. package/src/alphalib/types/builtinTemplates.ts +24 -0
  119. package/src/alphalib/types/robots/ai-chat.ts +1 -0
  120. package/src/alphalib/types/skillFrontmatter.ts +24 -0
  121. package/src/alphalib/types/template.ts +14 -0
  122. package/src/cli/commands/assemblies.ts +825 -505
  123. package/src/cli/commands/index.ts +6 -3
  124. package/src/cli/commands/templates.ts +6 -17
  125. package/src/cli/fileProcessingOptions.ts +294 -0
  126. package/src/cli/generateIntentDocs.ts +419 -0
  127. package/src/cli/intentCommandSpecs.ts +282 -0
  128. package/src/cli/intentCommands.ts +525 -0
  129. package/src/cli/intentFields.ts +403 -0
  130. package/src/cli/intentInputPolicy.ts +11 -0
  131. package/src/cli/intentRuntime.ts +734 -0
  132. package/src/cli/resultFiles.ts +105 -0
  133. package/src/cli/resultUrls.ts +72 -0
  134. package/src/cli/semanticIntents/imageDescribe.ts +254 -0
  135. package/src/cli/semanticIntents/index.ts +48 -0
  136. package/src/cli/semanticIntents/markdownPdf.ts +120 -0
  137. package/src/cli/semanticIntents/parsing.ts +56 -0
  138. package/src/cli/stepsInput.ts +32 -0
  139. package/src/cli.ts +5 -4
  140. package/src/ensureUniqueCounter.ts +75 -0
  141. package/src/inputFiles.ts +277 -26
  142. package/src/robots.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  import { Builtins, Cli } from 'clipanion'
2
2
 
3
3
  import packageJson from '../../../package.json' with { type: 'json' }
4
-
4
+ import { intentCommands } from '../intentCommands.ts'
5
5
  import {
6
6
  AssembliesCreateCommand,
7
7
  AssembliesDeleteCommand,
@@ -10,9 +10,7 @@ import {
10
10
  AssembliesListCommand,
11
11
  AssembliesReplayCommand,
12
12
  } from './assemblies.ts'
13
-
14
13
  import { SignatureCommand, SmartCdnSignatureCommand, TokenCommand } from './auth.ts'
15
-
16
14
  import { BillsGetCommand } from './bills.ts'
17
15
  import { DocsRobotsGetCommand, DocsRobotsListCommand } from './docs.ts'
18
16
  import { NotificationsReplayCommand } from './notifications.ts'
@@ -71,5 +69,10 @@ export function createCli(): Cli {
71
69
  cli.register(DocsRobotsListCommand)
72
70
  cli.register(DocsRobotsGetCommand)
73
71
 
72
+ // Intent-first commands
73
+ for (const command of intentCommands) {
74
+ cli.register(command)
75
+ }
76
+
74
77
  return cli
75
78
  }
@@ -5,12 +5,11 @@ import { Command, Option } from 'clipanion'
5
5
  import rreaddir from 'recursive-readdir'
6
6
  import { z } from 'zod'
7
7
  import { tryCatch } from '../../alphalib/tryCatch.ts'
8
- import type { Steps } from '../../alphalib/types/template.ts'
9
- import { stepsSchema } from '../../alphalib/types/template.ts'
10
8
  import type { TemplateContent } from '../../apiTypes.ts'
11
9
  import type { Transloadit } from '../../Transloadit.ts'
12
10
  import { createReadStream, formatAPIError, streamToBuffer } from '../helpers.ts'
13
11
  import type { IOutputCtl } from '../OutputCtl.ts'
12
+ import { parseStepsInputJson } from '../stepsInput.ts'
14
13
  import ModifiedLookup from '../template-last-modified.ts'
15
14
  import type { TemplateFile } from '../types.ts'
16
15
  import { ensureError, isTransloaditAPIError, TemplateFileDataSchema } from '../types.ts'
@@ -60,16 +59,11 @@ export async function create(
60
59
  try {
61
60
  const buf = await streamToBuffer(createReadStream(file))
62
61
 
63
- const parsed: unknown = JSON.parse(buf.toString())
64
- const validated = stepsSchema.safeParse(parsed)
65
- if (!validated.success) {
66
- throw new Error(`Invalid template steps format: ${validated.error.message}`)
67
- }
62
+ const steps = parseStepsInputJson(buf.toString())
68
63
 
69
64
  const result = await client.createTemplate({
70
65
  name,
71
- // Steps (validated) is assignable to StepsInput at runtime; cast for TS
72
- template: { steps: validated.data } as TemplateContent,
66
+ template: { steps } as TemplateContent,
73
67
  })
74
68
  output.print(result.id, result)
75
69
  return result
@@ -106,23 +100,18 @@ export async function modify(
106
100
  try {
107
101
  const buf = await streamToBuffer(createReadStream(file))
108
102
 
109
- let steps: Steps | null = null
103
+ let steps: TemplateContent['steps'] | null = null
110
104
  let newName = name
111
105
 
112
106
  if (buf.length > 0) {
113
- const parsed: unknown = JSON.parse(buf.toString())
114
- const validated = stepsSchema.safeParse(parsed)
115
- if (!validated.success) {
116
- throw new Error(`Invalid template steps format: ${validated.error.message}`)
117
- }
118
- steps = validated.data
107
+ steps = parseStepsInputJson(buf.toString()) as TemplateContent['steps']
119
108
  }
120
109
 
121
110
  if (!name || buf.length === 0) {
122
111
  const tpl = await client.getTemplate(template)
123
112
  if (!name) newName = tpl.name
124
113
  if (buf.length === 0 && tpl.content.steps) {
125
- steps = tpl.content.steps
114
+ steps = tpl.content.steps as TemplateContent['steps']
126
115
  }
127
116
  }
128
117
 
@@ -0,0 +1,294 @@
1
+ import { Option } from 'clipanion'
2
+ import * as t from 'typanion'
3
+
4
+ export interface SharedCliOptionDocumentation {
5
+ description: string
6
+ example: string
7
+ flags: string
8
+ required: string
9
+ type: string
10
+ }
11
+
12
+ interface SharedCliOptionDefinition {
13
+ docs: SharedCliOptionDocumentation
14
+ optionFlags: string
15
+ }
16
+
17
+ interface SharedCliOptionExports<T> {
18
+ docs: (description?: string) => SharedCliOptionDocumentation
19
+ option: (description?: string) => T
20
+ }
21
+
22
+ export interface SharedFileProcessingValidationInput {
23
+ explicitInputCount: number
24
+ singleAssembly: boolean
25
+ watch: boolean
26
+ watchRequiresInputsMessage: string
27
+ }
28
+
29
+ const inputPathsOptionDefinition = {
30
+ docs: {
31
+ flags: '--input, -i',
32
+ type: 'path | dir | url | -',
33
+ required: 'varies',
34
+ example: 'input.file',
35
+ description: 'Provide an input path, directory, URL, or - for stdin',
36
+ },
37
+ optionFlags: '--input,-i',
38
+ } as const satisfies SharedCliOptionDefinition
39
+
40
+ const recursiveOptionDefinition = {
41
+ docs: {
42
+ flags: '--recursive, -r',
43
+ type: 'boolean',
44
+ required: 'no',
45
+ example: 'false',
46
+ description: 'Enumerate input directories recursively',
47
+ },
48
+ optionFlags: '--recursive,-r',
49
+ } as const satisfies SharedCliOptionDefinition
50
+
51
+ const deleteAfterProcessingOptionDefinition = {
52
+ docs: {
53
+ flags: '--delete-after-processing, -d',
54
+ type: 'boolean',
55
+ required: 'no',
56
+ example: 'false',
57
+ description: 'Delete input files after they are processed',
58
+ },
59
+ optionFlags: '--delete-after-processing,-d',
60
+ } as const satisfies SharedCliOptionDefinition
61
+
62
+ const reprocessStaleOptionDefinition = {
63
+ docs: {
64
+ flags: '--reprocess-stale',
65
+ type: 'boolean',
66
+ required: 'no',
67
+ example: 'false',
68
+ description: 'Process inputs even if output is newer',
69
+ },
70
+ optionFlags: '--reprocess-stale',
71
+ } as const satisfies SharedCliOptionDefinition
72
+
73
+ const watchOptionDefinition = {
74
+ docs: {
75
+ flags: '--watch, -w',
76
+ type: 'boolean',
77
+ required: 'no',
78
+ example: 'false',
79
+ description: 'Watch inputs for changes',
80
+ },
81
+ optionFlags: '--watch,-w',
82
+ } as const satisfies SharedCliOptionDefinition
83
+
84
+ const singleAssemblyOptionDefinition = {
85
+ docs: {
86
+ flags: '--single-assembly',
87
+ type: 'boolean',
88
+ required: 'no',
89
+ example: 'false',
90
+ description: 'Pass all input files to a single assembly instead of one assembly per file',
91
+ },
92
+ optionFlags: '--single-assembly',
93
+ } as const satisfies SharedCliOptionDefinition
94
+
95
+ const concurrencyOptionDefinition = {
96
+ docs: {
97
+ flags: '--concurrency, -c',
98
+ type: 'number',
99
+ required: 'no',
100
+ example: '5',
101
+ description: 'Maximum number of concurrent assemblies (default: 5)',
102
+ },
103
+ optionFlags: '--concurrency,-c',
104
+ } as const satisfies SharedCliOptionDefinition
105
+
106
+ const printUrlsOptionDefinition = {
107
+ docs: {
108
+ flags: '--print-urls',
109
+ type: 'boolean',
110
+ required: 'no',
111
+ example: 'false',
112
+ description: 'Print temporary result URLs after completion',
113
+ },
114
+ optionFlags: '--print-urls',
115
+ } as const satisfies SharedCliOptionDefinition
116
+
117
+ function getSharedCliOptionDocumentation(
118
+ definition: SharedCliOptionDefinition,
119
+ description = definition.docs.description,
120
+ ): SharedCliOptionDocumentation {
121
+ return {
122
+ ...definition.docs,
123
+ description,
124
+ }
125
+ }
126
+
127
+ function arrayOption(
128
+ definition: SharedCliOptionDefinition,
129
+ description = definition.docs.description,
130
+ ): string[] {
131
+ return Option.Array(definition.optionFlags, {
132
+ description,
133
+ }) as unknown as string[]
134
+ }
135
+
136
+ function booleanOption(
137
+ definition: SharedCliOptionDefinition,
138
+ description = definition.docs.description,
139
+ ): boolean {
140
+ return Option.Boolean(definition.optionFlags, false, {
141
+ description,
142
+ }) as unknown as boolean
143
+ }
144
+
145
+ function createArrayOptionExports(
146
+ definition: SharedCliOptionDefinition,
147
+ ): SharedCliOptionExports<string[]> {
148
+ return {
149
+ docs: (description = definition.docs.description) =>
150
+ getSharedCliOptionDocumentation(definition, description),
151
+ option: (description = definition.docs.description) => arrayOption(definition, description),
152
+ }
153
+ }
154
+
155
+ function createBooleanOptionExports(
156
+ definition: SharedCliOptionDefinition,
157
+ ): SharedCliOptionExports<boolean> {
158
+ return {
159
+ docs: (description = definition.docs.description) =>
160
+ getSharedCliOptionDocumentation(definition, description),
161
+ option: (description = definition.docs.description) => booleanOption(definition, description),
162
+ }
163
+ }
164
+
165
+ const inputPathsOptionExports = createArrayOptionExports(inputPathsOptionDefinition)
166
+ const recursiveOptionExports = createBooleanOptionExports(recursiveOptionDefinition)
167
+ const deleteAfterProcessingOptionExports = createBooleanOptionExports(
168
+ deleteAfterProcessingOptionDefinition,
169
+ )
170
+ const reprocessStaleOptionExports = createBooleanOptionExports(reprocessStaleOptionDefinition)
171
+ const watchOptionExports = createBooleanOptionExports(watchOptionDefinition)
172
+ const singleAssemblyOptionExports = createBooleanOptionExports(singleAssemblyOptionDefinition)
173
+
174
+ export function getInputPathsOptionDocumentation(
175
+ description = inputPathsOptionDefinition.docs.description,
176
+ ): SharedCliOptionDocumentation {
177
+ return inputPathsOptionExports.docs(description)
178
+ }
179
+
180
+ export function inputPathsOption(
181
+ description = inputPathsOptionDefinition.docs.description,
182
+ ): string[] {
183
+ return inputPathsOptionExports.option(description)
184
+ }
185
+
186
+ export function getRecursiveOptionDocumentation(
187
+ description = recursiveOptionDefinition.docs.description,
188
+ ): SharedCliOptionDocumentation {
189
+ return recursiveOptionExports.docs(description)
190
+ }
191
+
192
+ export function recursiveOption(description = recursiveOptionDefinition.docs.description): boolean {
193
+ return recursiveOptionExports.option(description)
194
+ }
195
+
196
+ export function getDeleteAfterProcessingOptionDocumentation(
197
+ description = deleteAfterProcessingOptionDefinition.docs.description,
198
+ ): SharedCliOptionDocumentation {
199
+ return deleteAfterProcessingOptionExports.docs(description)
200
+ }
201
+
202
+ export function deleteAfterProcessingOption(
203
+ description = deleteAfterProcessingOptionDefinition.docs.description,
204
+ ): boolean {
205
+ return deleteAfterProcessingOptionExports.option(description)
206
+ }
207
+
208
+ export function getReprocessStaleOptionDocumentation(
209
+ description = reprocessStaleOptionDefinition.docs.description,
210
+ ): SharedCliOptionDocumentation {
211
+ return reprocessStaleOptionExports.docs(description)
212
+ }
213
+
214
+ export function reprocessStaleOption(
215
+ description = reprocessStaleOptionDefinition.docs.description,
216
+ ): boolean {
217
+ return reprocessStaleOptionExports.option(description)
218
+ }
219
+
220
+ export function getWatchOptionDocumentation(
221
+ description = watchOptionDefinition.docs.description,
222
+ ): SharedCliOptionDocumentation {
223
+ return watchOptionExports.docs(description)
224
+ }
225
+
226
+ export function watchOption(description = watchOptionDefinition.docs.description): boolean {
227
+ return watchOptionExports.option(description)
228
+ }
229
+
230
+ export function getSingleAssemblyOptionDocumentation(
231
+ description = singleAssemblyOptionDefinition.docs.description,
232
+ ): SharedCliOptionDocumentation {
233
+ return singleAssemblyOptionExports.docs(description)
234
+ }
235
+
236
+ export function singleAssemblyOption(
237
+ description = singleAssemblyOptionDefinition.docs.description,
238
+ ): boolean {
239
+ return singleAssemblyOptionExports.option(description)
240
+ }
241
+
242
+ export function getConcurrencyOptionDocumentation(
243
+ description = concurrencyOptionDefinition.docs.description,
244
+ ): SharedCliOptionDocumentation {
245
+ return getSharedCliOptionDocumentation(concurrencyOptionDefinition, description)
246
+ }
247
+
248
+ export function concurrencyOption(
249
+ description = concurrencyOptionDefinition.docs.description,
250
+ ): number | undefined {
251
+ return Option.String(concurrencyOptionDefinition.optionFlags, {
252
+ description,
253
+ validator: t.applyCascade(t.isNumber(), [t.isAtLeast(1)]),
254
+ }) as unknown as number | undefined
255
+ }
256
+
257
+ export function getPrintUrlsOptionDocumentation(
258
+ description = printUrlsOptionDefinition.docs.description,
259
+ ): SharedCliOptionDocumentation {
260
+ return getSharedCliOptionDocumentation(printUrlsOptionDefinition, description)
261
+ }
262
+
263
+ export function printUrlsOption(description = printUrlsOptionDefinition.docs.description): boolean {
264
+ return Option.Boolean(printUrlsOptionDefinition.optionFlags, {
265
+ description,
266
+ }) as unknown as boolean
267
+ }
268
+
269
+ export function countProvidedInputs({
270
+ inputBase64,
271
+ inputs,
272
+ }: {
273
+ inputBase64?: string[]
274
+ inputs?: string[]
275
+ }): number {
276
+ return (inputs ?? []).length + (inputBase64 ?? []).length
277
+ }
278
+
279
+ export function validateSharedFileProcessingOptions({
280
+ explicitInputCount,
281
+ singleAssembly,
282
+ watch,
283
+ watchRequiresInputsMessage,
284
+ }: SharedFileProcessingValidationInput): string | undefined {
285
+ if (watch && explicitInputCount === 0) {
286
+ return watchRequiresInputsMessage
287
+ }
288
+
289
+ if (watch && singleAssembly) {
290
+ return '--single-assembly cannot be used with --watch'
291
+ }
292
+
293
+ return undefined
294
+ }