@transloadit/node 4.1.3

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 (593) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +701 -0
  3. package/dist/ApiError.d.ts +22 -0
  4. package/dist/ApiError.d.ts.map +1 -0
  5. package/dist/ApiError.js +33 -0
  6. package/dist/ApiError.js.map +1 -0
  7. package/dist/InconsistentResponseError.d.ts +4 -0
  8. package/dist/InconsistentResponseError.d.ts.map +1 -0
  9. package/dist/InconsistentResponseError.js +4 -0
  10. package/dist/InconsistentResponseError.js.map +1 -0
  11. package/dist/PaginationStream.d.ts +14 -0
  12. package/dist/PaginationStream.d.ts.map +1 -0
  13. package/dist/PaginationStream.js +36 -0
  14. package/dist/PaginationStream.js.map +1 -0
  15. package/dist/PollingTimeoutError.d.ts +5 -0
  16. package/dist/PollingTimeoutError.d.ts.map +1 -0
  17. package/dist/PollingTimeoutError.js +5 -0
  18. package/dist/PollingTimeoutError.js.map +1 -0
  19. package/dist/Transloadit.d.ts +250 -0
  20. package/dist/Transloadit.d.ts.map +1 -0
  21. package/dist/Transloadit.js +661 -0
  22. package/dist/Transloadit.js.map +1 -0
  23. package/dist/alphalib/lib/nativeGlobby.d.ts +14 -0
  24. package/dist/alphalib/lib/nativeGlobby.d.ts.map +1 -0
  25. package/dist/alphalib/lib/nativeGlobby.js +181 -0
  26. package/dist/alphalib/lib/nativeGlobby.js.map +1 -0
  27. package/dist/alphalib/mcache.d.ts +65 -0
  28. package/dist/alphalib/mcache.d.ts.map +1 -0
  29. package/dist/alphalib/mcache.js +135 -0
  30. package/dist/alphalib/mcache.js.map +1 -0
  31. package/dist/alphalib/tryCatch.d.ts +21 -0
  32. package/dist/alphalib/tryCatch.d.ts.map +1 -0
  33. package/dist/alphalib/tryCatch.js +17 -0
  34. package/dist/alphalib/tryCatch.js.map +1 -0
  35. package/dist/alphalib/types/assembliesGet.d.ts +62 -0
  36. package/dist/alphalib/types/assembliesGet.d.ts.map +1 -0
  37. package/dist/alphalib/types/assembliesGet.js +33 -0
  38. package/dist/alphalib/types/assembliesGet.js.map +1 -0
  39. package/dist/alphalib/types/assemblyReplay.d.ts +7858 -0
  40. package/dist/alphalib/types/assemblyReplay.d.ts.map +1 -0
  41. package/dist/alphalib/types/assemblyReplay.js +15 -0
  42. package/dist/alphalib/types/assemblyReplay.js.map +1 -0
  43. package/dist/alphalib/types/assemblyReplayNotification.d.ts +7849 -0
  44. package/dist/alphalib/types/assemblyReplayNotification.d.ts.map +1 -0
  45. package/dist/alphalib/types/assemblyReplayNotification.js +13 -0
  46. package/dist/alphalib/types/assemblyReplayNotification.js.map +1 -0
  47. package/dist/alphalib/types/assemblyStatus.d.ts +71084 -0
  48. package/dist/alphalib/types/assemblyStatus.d.ts.map +1 -0
  49. package/dist/alphalib/types/assemblyStatus.js +710 -0
  50. package/dist/alphalib/types/assemblyStatus.js.map +1 -0
  51. package/dist/alphalib/types/bill.d.ts +44 -0
  52. package/dist/alphalib/types/bill.d.ts.map +1 -0
  53. package/dist/alphalib/types/bill.js +8 -0
  54. package/dist/alphalib/types/bill.js.map +1 -0
  55. package/dist/alphalib/types/robots/_index.d.ts +76306 -0
  56. package/dist/alphalib/types/robots/_index.d.ts.map +1 -0
  57. package/dist/alphalib/types/robots/_index.js +354 -0
  58. package/dist/alphalib/types/robots/_index.js.map +1 -0
  59. package/dist/alphalib/types/robots/_instructions-primitives.d.ts +3533 -0
  60. package/dist/alphalib/types/robots/_instructions-primitives.d.ts.map +1 -0
  61. package/dist/alphalib/types/robots/_instructions-primitives.js +1491 -0
  62. package/dist/alphalib/types/robots/_instructions-primitives.js.map +1 -0
  63. package/dist/alphalib/types/robots/ai-chat.d.ts +2096 -0
  64. package/dist/alphalib/types/robots/ai-chat.d.ts.map +1 -0
  65. package/dist/alphalib/types/robots/ai-chat.js +223 -0
  66. package/dist/alphalib/types/robots/ai-chat.js.map +1 -0
  67. package/dist/alphalib/types/robots/assembly-savejson.d.ts +52 -0
  68. package/dist/alphalib/types/robots/assembly-savejson.d.ts.map +1 -0
  69. package/dist/alphalib/types/robots/assembly-savejson.js +22 -0
  70. package/dist/alphalib/types/robots/assembly-savejson.js.map +1 -0
  71. package/dist/alphalib/types/robots/audio-artwork.d.ts +2867 -0
  72. package/dist/alphalib/types/robots/audio-artwork.d.ts.map +1 -0
  73. package/dist/alphalib/types/robots/audio-artwork.js +73 -0
  74. package/dist/alphalib/types/robots/audio-artwork.js.map +1 -0
  75. package/dist/alphalib/types/robots/audio-concat.d.ts +2916 -0
  76. package/dist/alphalib/types/robots/audio-concat.d.ts.map +1 -0
  77. package/dist/alphalib/types/robots/audio-concat.js +106 -0
  78. package/dist/alphalib/types/robots/audio-concat.js.map +1 -0
  79. package/dist/alphalib/types/robots/audio-encode.d.ts +2864 -0
  80. package/dist/alphalib/types/robots/audio-encode.d.ts.map +1 -0
  81. package/dist/alphalib/types/robots/audio-encode.js +67 -0
  82. package/dist/alphalib/types/robots/audio-encode.js.map +1 -0
  83. package/dist/alphalib/types/robots/audio-loop.d.ts +2879 -0
  84. package/dist/alphalib/types/robots/audio-loop.d.ts.map +1 -0
  85. package/dist/alphalib/types/robots/audio-loop.js +67 -0
  86. package/dist/alphalib/types/robots/audio-loop.js.map +1 -0
  87. package/dist/alphalib/types/robots/audio-merge.d.ts +2931 -0
  88. package/dist/alphalib/types/robots/audio-merge.d.ts.map +1 -0
  89. package/dist/alphalib/types/robots/audio-merge.js +101 -0
  90. package/dist/alphalib/types/robots/audio-merge.js.map +1 -0
  91. package/dist/alphalib/types/robots/audio-waveform.d.ts +3131 -0
  92. package/dist/alphalib/types/robots/audio-waveform.d.ts.map +1 -0
  93. package/dist/alphalib/types/robots/audio-waveform.js +238 -0
  94. package/dist/alphalib/types/robots/audio-waveform.js.map +1 -0
  95. package/dist/alphalib/types/robots/azure-import.d.ts +210 -0
  96. package/dist/alphalib/types/robots/azure-import.d.ts.map +1 -0
  97. package/dist/alphalib/types/robots/azure-import.js +73 -0
  98. package/dist/alphalib/types/robots/azure-import.js.map +1 -0
  99. package/dist/alphalib/types/robots/azure-store.d.ts +562 -0
  100. package/dist/alphalib/types/robots/azure-store.d.ts.map +1 -0
  101. package/dist/alphalib/types/robots/azure-store.js +115 -0
  102. package/dist/alphalib/types/robots/azure-store.js.map +1 -0
  103. package/dist/alphalib/types/robots/backblaze-import.d.ts +210 -0
  104. package/dist/alphalib/types/robots/backblaze-import.d.ts.map +1 -0
  105. package/dist/alphalib/types/robots/backblaze-import.js +81 -0
  106. package/dist/alphalib/types/robots/backblaze-import.js.map +1 -0
  107. package/dist/alphalib/types/robots/backblaze-store.d.ts +478 -0
  108. package/dist/alphalib/types/robots/backblaze-store.d.ts.map +1 -0
  109. package/dist/alphalib/types/robots/backblaze-store.js +76 -0
  110. package/dist/alphalib/types/robots/backblaze-store.js.map +1 -0
  111. package/dist/alphalib/types/robots/cloudfiles-import.d.ts +234 -0
  112. package/dist/alphalib/types/robots/cloudfiles-import.d.ts.map +1 -0
  113. package/dist/alphalib/types/robots/cloudfiles-import.js +80 -0
  114. package/dist/alphalib/types/robots/cloudfiles-import.js.map +1 -0
  115. package/dist/alphalib/types/robots/cloudfiles-store.d.ts +490 -0
  116. package/dist/alphalib/types/robots/cloudfiles-store.d.ts.map +1 -0
  117. package/dist/alphalib/types/robots/cloudfiles-store.js +70 -0
  118. package/dist/alphalib/types/robots/cloudfiles-store.js.map +1 -0
  119. package/dist/alphalib/types/robots/cloudflare-import.d.ts +234 -0
  120. package/dist/alphalib/types/robots/cloudflare-import.d.ts.map +1 -0
  121. package/dist/alphalib/types/robots/cloudflare-import.js +81 -0
  122. package/dist/alphalib/types/robots/cloudflare-import.js.map +1 -0
  123. package/dist/alphalib/types/robots/cloudflare-store.d.ts +514 -0
  124. package/dist/alphalib/types/robots/cloudflare-store.d.ts.map +1 -0
  125. package/dist/alphalib/types/robots/cloudflare-store.js +86 -0
  126. package/dist/alphalib/types/robots/cloudflare-store.js.map +1 -0
  127. package/dist/alphalib/types/robots/digitalocean-import.d.ts +234 -0
  128. package/dist/alphalib/types/robots/digitalocean-import.d.ts.map +1 -0
  129. package/dist/alphalib/types/robots/digitalocean-import.js +78 -0
  130. package/dist/alphalib/types/robots/digitalocean-import.js.map +1 -0
  131. package/dist/alphalib/types/robots/digitalocean-store.d.ts +526 -0
  132. package/dist/alphalib/types/robots/digitalocean-store.d.ts.map +1 -0
  133. package/dist/alphalib/types/robots/digitalocean-store.js +91 -0
  134. package/dist/alphalib/types/robots/digitalocean-store.js.map +1 -0
  135. package/dist/alphalib/types/robots/document-autorotate.d.ts +405 -0
  136. package/dist/alphalib/types/robots/document-autorotate.d.ts.map +1 -0
  137. package/dist/alphalib/types/robots/document-autorotate.js +44 -0
  138. package/dist/alphalib/types/robots/document-autorotate.js.map +1 -0
  139. package/dist/alphalib/types/robots/document-convert.d.ts +513 -0
  140. package/dist/alphalib/types/robots/document-convert.d.ts.map +1 -0
  141. package/dist/alphalib/types/robots/document-convert.js +273 -0
  142. package/dist/alphalib/types/robots/document-convert.js.map +1 -0
  143. package/dist/alphalib/types/robots/document-merge.d.ts +429 -0
  144. package/dist/alphalib/types/robots/document-merge.d.ts.map +1 -0
  145. package/dist/alphalib/types/robots/document-merge.js +86 -0
  146. package/dist/alphalib/types/robots/document-merge.js.map +1 -0
  147. package/dist/alphalib/types/robots/document-ocr.d.ts +441 -0
  148. package/dist/alphalib/types/robots/document-ocr.d.ts.map +1 -0
  149. package/dist/alphalib/types/robots/document-ocr.js +86 -0
  150. package/dist/alphalib/types/robots/document-ocr.js.map +1 -0
  151. package/dist/alphalib/types/robots/document-split.d.ts +417 -0
  152. package/dist/alphalib/types/robots/document-split.d.ts.map +1 -0
  153. package/dist/alphalib/types/robots/document-split.js +48 -0
  154. package/dist/alphalib/types/robots/document-split.js.map +1 -0
  155. package/dist/alphalib/types/robots/document-thumbs.d.ts +592 -0
  156. package/dist/alphalib/types/robots/document-thumbs.d.ts.map +1 -0
  157. package/dist/alphalib/types/robots/document-thumbs.js +196 -0
  158. package/dist/alphalib/types/robots/document-thumbs.js.map +1 -0
  159. package/dist/alphalib/types/robots/dropbox-import.d.ts +144 -0
  160. package/dist/alphalib/types/robots/dropbox-import.d.ts.map +1 -0
  161. package/dist/alphalib/types/robots/dropbox-import.js +65 -0
  162. package/dist/alphalib/types/robots/dropbox-import.js.map +1 -0
  163. package/dist/alphalib/types/robots/dropbox-store.d.ts +449 -0
  164. package/dist/alphalib/types/robots/dropbox-store.d.ts.map +1 -0
  165. package/dist/alphalib/types/robots/dropbox-store.js +68 -0
  166. package/dist/alphalib/types/robots/dropbox-store.js.map +1 -0
  167. package/dist/alphalib/types/robots/edgly-deliver.d.ts +100 -0
  168. package/dist/alphalib/types/robots/edgly-deliver.d.ts.map +1 -0
  169. package/dist/alphalib/types/robots/edgly-deliver.js +46 -0
  170. package/dist/alphalib/types/robots/edgly-deliver.js.map +1 -0
  171. package/dist/alphalib/types/robots/file-compress.d.ts +477 -0
  172. package/dist/alphalib/types/robots/file-compress.d.ts.map +1 -0
  173. package/dist/alphalib/types/robots/file-compress.js +139 -0
  174. package/dist/alphalib/types/robots/file-compress.js.map +1 -0
  175. package/dist/alphalib/types/robots/file-decompress.d.ts +404 -0
  176. package/dist/alphalib/types/robots/file-decompress.d.ts.map +1 -0
  177. package/dist/alphalib/types/robots/file-decompress.js +94 -0
  178. package/dist/alphalib/types/robots/file-decompress.js.map +1 -0
  179. package/dist/alphalib/types/robots/file-filter.d.ts +465 -0
  180. package/dist/alphalib/types/robots/file-filter.d.ts.map +1 -0
  181. package/dist/alphalib/types/robots/file-filter.js +136 -0
  182. package/dist/alphalib/types/robots/file-filter.js.map +1 -0
  183. package/dist/alphalib/types/robots/file-hash.d.ts +417 -0
  184. package/dist/alphalib/types/robots/file-hash.d.ts.map +1 -0
  185. package/dist/alphalib/types/robots/file-hash.js +59 -0
  186. package/dist/alphalib/types/robots/file-hash.js.map +1 -0
  187. package/dist/alphalib/types/robots/file-preview.d.ts +854 -0
  188. package/dist/alphalib/types/robots/file-preview.d.ts.map +1 -0
  189. package/dist/alphalib/types/robots/file-preview.js +221 -0
  190. package/dist/alphalib/types/robots/file-preview.js.map +1 -0
  191. package/dist/alphalib/types/robots/file-read.d.ts +405 -0
  192. package/dist/alphalib/types/robots/file-read.d.ts.map +1 -0
  193. package/dist/alphalib/types/robots/file-read.js +44 -0
  194. package/dist/alphalib/types/robots/file-read.js.map +1 -0
  195. package/dist/alphalib/types/robots/file-serve.d.ts +418 -0
  196. package/dist/alphalib/types/robots/file-serve.d.ts.map +1 -0
  197. package/dist/alphalib/types/robots/file-serve.js +99 -0
  198. package/dist/alphalib/types/robots/file-serve.js.map +1 -0
  199. package/dist/alphalib/types/robots/file-verify.d.ts +441 -0
  200. package/dist/alphalib/types/robots/file-verify.d.ts.map +1 -0
  201. package/dist/alphalib/types/robots/file-verify.js +73 -0
  202. package/dist/alphalib/types/robots/file-verify.js.map +1 -0
  203. package/dist/alphalib/types/robots/file-virusscan.d.ts +435 -0
  204. package/dist/alphalib/types/robots/file-virusscan.d.ts.map +1 -0
  205. package/dist/alphalib/types/robots/file-virusscan.js +82 -0
  206. package/dist/alphalib/types/robots/file-virusscan.js.map +1 -0
  207. package/dist/alphalib/types/robots/file-watermark.d.ts +417 -0
  208. package/dist/alphalib/types/robots/file-watermark.d.ts.map +1 -0
  209. package/dist/alphalib/types/robots/file-watermark.js +28 -0
  210. package/dist/alphalib/types/robots/file-watermark.js.map +1 -0
  211. package/dist/alphalib/types/robots/ftp-import.d.ts +198 -0
  212. package/dist/alphalib/types/robots/ftp-import.d.ts.map +1 -0
  213. package/dist/alphalib/types/robots/ftp-import.js +60 -0
  214. package/dist/alphalib/types/robots/ftp-import.js.map +1 -0
  215. package/dist/alphalib/types/robots/ftp-store.d.ts +532 -0
  216. package/dist/alphalib/types/robots/ftp-store.d.ts.map +1 -0
  217. package/dist/alphalib/types/robots/ftp-store.js +91 -0
  218. package/dist/alphalib/types/robots/ftp-store.js.map +1 -0
  219. package/dist/alphalib/types/robots/google-import.d.ts +174 -0
  220. package/dist/alphalib/types/robots/google-import.d.ts.map +1 -0
  221. package/dist/alphalib/types/robots/google-import.js +77 -0
  222. package/dist/alphalib/types/robots/google-import.js.map +1 -0
  223. package/dist/alphalib/types/robots/google-store.d.ts +476 -0
  224. package/dist/alphalib/types/robots/google-store.d.ts.map +1 -0
  225. package/dist/alphalib/types/robots/google-store.js +111 -0
  226. package/dist/alphalib/types/robots/google-store.js.map +1 -0
  227. package/dist/alphalib/types/robots/html-convert.d.ts +531 -0
  228. package/dist/alphalib/types/robots/html-convert.d.ts.map +1 -0
  229. package/dist/alphalib/types/robots/html-convert.js +137 -0
  230. package/dist/alphalib/types/robots/html-convert.js.map +1 -0
  231. package/dist/alphalib/types/robots/http-import.d.ts +215 -0
  232. package/dist/alphalib/types/robots/http-import.d.ts.map +1 -0
  233. package/dist/alphalib/types/robots/http-import.js +135 -0
  234. package/dist/alphalib/types/robots/http-import.js.map +1 -0
  235. package/dist/alphalib/types/robots/image-bgremove.d.ts +453 -0
  236. package/dist/alphalib/types/robots/image-bgremove.d.ts.map +1 -0
  237. package/dist/alphalib/types/robots/image-bgremove.js +65 -0
  238. package/dist/alphalib/types/robots/image-bgremove.js.map +1 -0
  239. package/dist/alphalib/types/robots/image-describe.d.ts +453 -0
  240. package/dist/alphalib/types/robots/image-describe.d.ts.map +1 -0
  241. package/dist/alphalib/types/robots/image-describe.js +86 -0
  242. package/dist/alphalib/types/robots/image-describe.js.map +1 -0
  243. package/dist/alphalib/types/robots/image-facedetect.d.ts +477 -0
  244. package/dist/alphalib/types/robots/image-facedetect.d.ts.map +1 -0
  245. package/dist/alphalib/types/robots/image-facedetect.js +151 -0
  246. package/dist/alphalib/types/robots/image-facedetect.js.map +1 -0
  247. package/dist/alphalib/types/robots/image-generate.d.ts +522 -0
  248. package/dist/alphalib/types/robots/image-generate.d.ts.map +1 -0
  249. package/dist/alphalib/types/robots/image-generate.js +64 -0
  250. package/dist/alphalib/types/robots/image-generate.js.map +1 -0
  251. package/dist/alphalib/types/robots/image-merge.d.ts +477 -0
  252. package/dist/alphalib/types/robots/image-merge.d.ts.map +1 -0
  253. package/dist/alphalib/types/robots/image-merge.js +92 -0
  254. package/dist/alphalib/types/robots/image-merge.js.map +1 -0
  255. package/dist/alphalib/types/robots/image-ocr.d.ts +441 -0
  256. package/dist/alphalib/types/robots/image-ocr.d.ts.map +1 -0
  257. package/dist/alphalib/types/robots/image-ocr.js +79 -0
  258. package/dist/alphalib/types/robots/image-ocr.js.map +1 -0
  259. package/dist/alphalib/types/robots/image-optimize.d.ts +453 -0
  260. package/dist/alphalib/types/robots/image-optimize.d.ts.map +1 -0
  261. package/dist/alphalib/types/robots/image-optimize.js +81 -0
  262. package/dist/alphalib/types/robots/image-optimize.js.map +1 -0
  263. package/dist/alphalib/types/robots/image-resize.d.ts +1758 -0
  264. package/dist/alphalib/types/robots/image-resize.d.ts.map +1 -0
  265. package/dist/alphalib/types/robots/image-resize.js +602 -0
  266. package/dist/alphalib/types/robots/image-resize.js.map +1 -0
  267. package/dist/alphalib/types/robots/meta-read.d.ts +98 -0
  268. package/dist/alphalib/types/robots/meta-read.d.ts.map +1 -0
  269. package/dist/alphalib/types/robots/meta-read.js +24 -0
  270. package/dist/alphalib/types/robots/meta-read.js.map +1 -0
  271. package/dist/alphalib/types/robots/meta-write.d.ts +2842 -0
  272. package/dist/alphalib/types/robots/meta-write.d.ts.map +1 -0
  273. package/dist/alphalib/types/robots/meta-write.js +66 -0
  274. package/dist/alphalib/types/robots/meta-write.js.map +1 -0
  275. package/dist/alphalib/types/robots/minio-import.d.ts +234 -0
  276. package/dist/alphalib/types/robots/minio-import.d.ts.map +1 -0
  277. package/dist/alphalib/types/robots/minio-import.js +81 -0
  278. package/dist/alphalib/types/robots/minio-import.js.map +1 -0
  279. package/dist/alphalib/types/robots/minio-store.d.ts +514 -0
  280. package/dist/alphalib/types/robots/minio-store.d.ts.map +1 -0
  281. package/dist/alphalib/types/robots/minio-store.js +87 -0
  282. package/dist/alphalib/types/robots/minio-store.js.map +1 -0
  283. package/dist/alphalib/types/robots/progress-simulate.d.ts +229 -0
  284. package/dist/alphalib/types/robots/progress-simulate.d.ts.map +1 -0
  285. package/dist/alphalib/types/robots/progress-simulate.js +25 -0
  286. package/dist/alphalib/types/robots/progress-simulate.js.map +1 -0
  287. package/dist/alphalib/types/robots/s3-import.d.ts +246 -0
  288. package/dist/alphalib/types/robots/s3-import.d.ts.map +1 -0
  289. package/dist/alphalib/types/robots/s3-import.js +137 -0
  290. package/dist/alphalib/types/robots/s3-import.js.map +1 -0
  291. package/dist/alphalib/types/robots/s3-store.d.ts +593 -0
  292. package/dist/alphalib/types/robots/s3-store.d.ts.map +1 -0
  293. package/dist/alphalib/types/robots/s3-store.js +169 -0
  294. package/dist/alphalib/types/robots/s3-store.js.map +1 -0
  295. package/dist/alphalib/types/robots/script-run.d.ts +423 -0
  296. package/dist/alphalib/types/robots/script-run.d.ts.map +1 -0
  297. package/dist/alphalib/types/robots/script-run.js +95 -0
  298. package/dist/alphalib/types/robots/script-run.js.map +1 -0
  299. package/dist/alphalib/types/robots/sftp-import.d.ts +192 -0
  300. package/dist/alphalib/types/robots/sftp-import.d.ts.map +1 -0
  301. package/dist/alphalib/types/robots/sftp-import.js +62 -0
  302. package/dist/alphalib/types/robots/sftp-import.js.map +1 -0
  303. package/dist/alphalib/types/robots/sftp-store.d.ts +520 -0
  304. package/dist/alphalib/types/robots/sftp-store.d.ts.map +1 -0
  305. package/dist/alphalib/types/robots/sftp-store.js +83 -0
  306. package/dist/alphalib/types/robots/sftp-store.js.map +1 -0
  307. package/dist/alphalib/types/robots/speech-transcribe.d.ts +465 -0
  308. package/dist/alphalib/types/robots/speech-transcribe.d.ts.map +1 -0
  309. package/dist/alphalib/types/robots/speech-transcribe.js +103 -0
  310. package/dist/alphalib/types/robots/speech-transcribe.js.map +1 -0
  311. package/dist/alphalib/types/robots/supabase-import.d.ts +246 -0
  312. package/dist/alphalib/types/robots/supabase-import.d.ts.map +1 -0
  313. package/dist/alphalib/types/robots/supabase-import.js +83 -0
  314. package/dist/alphalib/types/robots/supabase-import.js.map +1 -0
  315. package/dist/alphalib/types/robots/supabase-store.d.ts +514 -0
  316. package/dist/alphalib/types/robots/supabase-store.d.ts.map +1 -0
  317. package/dist/alphalib/types/robots/supabase-store.js +77 -0
  318. package/dist/alphalib/types/robots/supabase-store.js.map +1 -0
  319. package/dist/alphalib/types/robots/swift-import.d.ts +246 -0
  320. package/dist/alphalib/types/robots/swift-import.d.ts.map +1 -0
  321. package/dist/alphalib/types/robots/swift-import.js +81 -0
  322. package/dist/alphalib/types/robots/swift-import.js.map +1 -0
  323. package/dist/alphalib/types/robots/swift-store.d.ts +526 -0
  324. package/dist/alphalib/types/robots/swift-store.d.ts.map +1 -0
  325. package/dist/alphalib/types/robots/swift-store.js +84 -0
  326. package/dist/alphalib/types/robots/swift-store.js.map +1 -0
  327. package/dist/alphalib/types/robots/text-speak.d.ts +465 -0
  328. package/dist/alphalib/types/robots/text-speak.d.ts.map +1 -0
  329. package/dist/alphalib/types/robots/text-speak.js +119 -0
  330. package/dist/alphalib/types/robots/text-speak.js.map +1 -0
  331. package/dist/alphalib/types/robots/text-translate.d.ts +441 -0
  332. package/dist/alphalib/types/robots/text-translate.d.ts.map +1 -0
  333. package/dist/alphalib/types/robots/text-translate.js +211 -0
  334. package/dist/alphalib/types/robots/text-translate.js.map +1 -0
  335. package/dist/alphalib/types/robots/tigris-import.d.ts +244 -0
  336. package/dist/alphalib/types/robots/tigris-import.d.ts.map +1 -0
  337. package/dist/alphalib/types/robots/tigris-import.js +85 -0
  338. package/dist/alphalib/types/robots/tigris-import.js.map +1 -0
  339. package/dist/alphalib/types/robots/tigris-store.d.ts +524 -0
  340. package/dist/alphalib/types/robots/tigris-store.d.ts.map +1 -0
  341. package/dist/alphalib/types/robots/tigris-store.js +91 -0
  342. package/dist/alphalib/types/robots/tigris-store.js.map +1 -0
  343. package/dist/alphalib/types/robots/tlcdn-deliver.d.ts +100 -0
  344. package/dist/alphalib/types/robots/tlcdn-deliver.d.ts.map +1 -0
  345. package/dist/alphalib/types/robots/tlcdn-deliver.js +46 -0
  346. package/dist/alphalib/types/robots/tlcdn-deliver.js.map +1 -0
  347. package/dist/alphalib/types/robots/tus-store.d.ts +477 -0
  348. package/dist/alphalib/types/robots/tus-store.d.ts.map +1 -0
  349. package/dist/alphalib/types/robots/tus-store.js +102 -0
  350. package/dist/alphalib/types/robots/tus-store.js.map +1 -0
  351. package/dist/alphalib/types/robots/upload-handle.d.ts +100 -0
  352. package/dist/alphalib/types/robots/upload-handle.d.ts.map +1 -0
  353. package/dist/alphalib/types/robots/upload-handle.js +66 -0
  354. package/dist/alphalib/types/robots/upload-handle.js.map +1 -0
  355. package/dist/alphalib/types/robots/video-adaptive.d.ts +2915 -0
  356. package/dist/alphalib/types/robots/video-adaptive.d.ts.map +1 -0
  357. package/dist/alphalib/types/robots/video-adaptive.js +144 -0
  358. package/dist/alphalib/types/robots/video-adaptive.js.map +1 -0
  359. package/dist/alphalib/types/robots/video-concat.d.ts +2891 -0
  360. package/dist/alphalib/types/robots/video-concat.d.ts.map +1 -0
  361. package/dist/alphalib/types/robots/video-concat.js +96 -0
  362. package/dist/alphalib/types/robots/video-concat.js.map +1 -0
  363. package/dist/alphalib/types/robots/video-encode.d.ts +3280 -0
  364. package/dist/alphalib/types/robots/video-encode.d.ts.map +1 -0
  365. package/dist/alphalib/types/robots/video-encode.js +107 -0
  366. package/dist/alphalib/types/robots/video-encode.js.map +1 -0
  367. package/dist/alphalib/types/robots/video-merge.d.ts +2987 -0
  368. package/dist/alphalib/types/robots/video-merge.d.ts.map +1 -0
  369. package/dist/alphalib/types/robots/video-merge.js +102 -0
  370. package/dist/alphalib/types/robots/video-merge.js.map +1 -0
  371. package/dist/alphalib/types/robots/video-ondemand.d.ts +4553 -0
  372. package/dist/alphalib/types/robots/video-ondemand.d.ts.map +1 -0
  373. package/dist/alphalib/types/robots/video-ondemand.js +112 -0
  374. package/dist/alphalib/types/robots/video-ondemand.js.map +1 -0
  375. package/dist/alphalib/types/robots/video-subtitle.d.ts +2975 -0
  376. package/dist/alphalib/types/robots/video-subtitle.d.ts.map +1 -0
  377. package/dist/alphalib/types/robots/video-subtitle.js +122 -0
  378. package/dist/alphalib/types/robots/video-subtitle.js.map +1 -0
  379. package/dist/alphalib/types/robots/video-thumbs.d.ts +2938 -0
  380. package/dist/alphalib/types/robots/video-thumbs.d.ts.map +1 -0
  381. package/dist/alphalib/types/robots/video-thumbs.js +122 -0
  382. package/dist/alphalib/types/robots/video-thumbs.js.map +1 -0
  383. package/dist/alphalib/types/robots/vimeo-import.d.ts +189 -0
  384. package/dist/alphalib/types/robots/vimeo-import.d.ts.map +1 -0
  385. package/dist/alphalib/types/robots/vimeo-import.js +92 -0
  386. package/dist/alphalib/types/robots/vimeo-import.js.map +1 -0
  387. package/dist/alphalib/types/robots/vimeo-store.d.ts +520 -0
  388. package/dist/alphalib/types/robots/vimeo-store.d.ts.map +1 -0
  389. package/dist/alphalib/types/robots/vimeo-store.js +115 -0
  390. package/dist/alphalib/types/robots/vimeo-store.js.map +1 -0
  391. package/dist/alphalib/types/robots/wasabi-import.d.ts +244 -0
  392. package/dist/alphalib/types/robots/wasabi-import.d.ts.map +1 -0
  393. package/dist/alphalib/types/robots/wasabi-import.js +85 -0
  394. package/dist/alphalib/types/robots/wasabi-import.js.map +1 -0
  395. package/dist/alphalib/types/robots/wasabi-store.d.ts +526 -0
  396. package/dist/alphalib/types/robots/wasabi-store.d.ts.map +1 -0
  397. package/dist/alphalib/types/robots/wasabi-store.js +85 -0
  398. package/dist/alphalib/types/robots/wasabi-store.js.map +1 -0
  399. package/dist/alphalib/types/robots/youtube-store.d.ts +477 -0
  400. package/dist/alphalib/types/robots/youtube-store.d.ts.map +1 -0
  401. package/dist/alphalib/types/robots/youtube-store.js +122 -0
  402. package/dist/alphalib/types/robots/youtube-store.js.map +1 -0
  403. package/dist/alphalib/types/stackVersions.d.ts +13 -0
  404. package/dist/alphalib/types/stackVersions.d.ts.map +1 -0
  405. package/dist/alphalib/types/stackVersions.js +13 -0
  406. package/dist/alphalib/types/stackVersions.js.map +1 -0
  407. package/dist/alphalib/types/template.d.ts +131710 -0
  408. package/dist/alphalib/types/template.d.ts.map +1 -0
  409. package/dist/alphalib/types/template.js +218 -0
  410. package/dist/alphalib/types/template.js.map +1 -0
  411. package/dist/alphalib/types/templateCredential.d.ts +95 -0
  412. package/dist/alphalib/types/templateCredential.d.ts.map +1 -0
  413. package/dist/alphalib/types/templateCredential.js +57 -0
  414. package/dist/alphalib/types/templateCredential.js.map +1 -0
  415. package/dist/alphalib/zodParseWithContext.d.ts +17 -0
  416. package/dist/alphalib/zodParseWithContext.d.ts.map +1 -0
  417. package/dist/alphalib/zodParseWithContext.js +248 -0
  418. package/dist/alphalib/zodParseWithContext.js.map +1 -0
  419. package/dist/apiTypes.d.ts +112 -0
  420. package/dist/apiTypes.d.ts.map +1 -0
  421. package/dist/apiTypes.js +3 -0
  422. package/dist/apiTypes.js.map +1 -0
  423. package/dist/cli/OutputCtl.d.ts +47 -0
  424. package/dist/cli/OutputCtl.d.ts.map +1 -0
  425. package/dist/cli/OutputCtl.js +85 -0
  426. package/dist/cli/OutputCtl.js.map +1 -0
  427. package/dist/cli/commands/BaseCommand.d.ts +24 -0
  428. package/dist/cli/commands/BaseCommand.d.ts.map +1 -0
  429. package/dist/cli/commands/BaseCommand.js +52 -0
  430. package/dist/cli/commands/BaseCommand.js.map +1 -0
  431. package/dist/cli/commands/assemblies.d.ts +93 -0
  432. package/dist/cli/commands/assemblies.d.ts.map +1 -0
  433. package/dist/cli/commands/assemblies.js +1021 -0
  434. package/dist/cli/commands/assemblies.js.map +1 -0
  435. package/dist/cli/commands/auth.d.ts +28 -0
  436. package/dist/cli/commands/auth.d.ts.map +1 -0
  437. package/dist/cli/commands/auth.js +280 -0
  438. package/dist/cli/commands/auth.js.map +1 -0
  439. package/dist/cli/commands/bills.d.ts +14 -0
  440. package/dist/cli/commands/bills.d.ts.map +1 -0
  441. package/dist/cli/commands/bills.js +69 -0
  442. package/dist/cli/commands/bills.js.map +1 -0
  443. package/dist/cli/commands/index.d.ts +3 -0
  444. package/dist/cli/commands/index.d.ts.map +1 -0
  445. package/dist/cli/commands/index.js +39 -0
  446. package/dist/cli/commands/index.js.map +1 -0
  447. package/dist/cli/commands/notifications.d.ts +9 -0
  448. package/dist/cli/commands/notifications.d.ts.map +1 -0
  449. package/dist/cli/commands/notifications.js +44 -0
  450. package/dist/cli/commands/notifications.js.map +1 -0
  451. package/dist/cli/commands/templates.d.ts +73 -0
  452. package/dist/cli/commands/templates.d.ts.map +1 -0
  453. package/dist/cli/commands/templates.js +428 -0
  454. package/dist/cli/commands/templates.js.map +1 -0
  455. package/dist/cli/helpers.d.ts +13 -0
  456. package/dist/cli/helpers.d.ts.map +1 -0
  457. package/dist/cli/helpers.js +39 -0
  458. package/dist/cli/helpers.js.map +1 -0
  459. package/dist/cli/template-last-modified.d.ts +10 -0
  460. package/dist/cli/template-last-modified.d.ts.map +1 -0
  461. package/dist/cli/template-last-modified.js +134 -0
  462. package/dist/cli/template-last-modified.js.map +1 -0
  463. package/dist/cli/types.d.ts +78 -0
  464. package/dist/cli/types.d.ts.map +1 -0
  465. package/dist/cli/types.js +49 -0
  466. package/dist/cli/types.js.map +1 -0
  467. package/dist/cli.d.ts +6 -0
  468. package/dist/cli.d.ts.map +1 -0
  469. package/dist/cli.js +41 -0
  470. package/dist/cli.js.map +1 -0
  471. package/dist/tus.d.ts +18 -0
  472. package/dist/tus.d.ts.map +1 -0
  473. package/dist/tus.js +122 -0
  474. package/dist/tus.js.map +1 -0
  475. package/package.json +92 -0
  476. package/src/ApiError.ts +49 -0
  477. package/src/InconsistentResponseError.ts +3 -0
  478. package/src/PaginationStream.ts +54 -0
  479. package/src/PollingTimeoutError.ts +5 -0
  480. package/src/Transloadit.ts +980 -0
  481. package/src/alphalib/lib/nativeGlobby.ts +244 -0
  482. package/src/alphalib/mcache.ts +184 -0
  483. package/src/alphalib/tryCatch.ts +30 -0
  484. package/src/alphalib/types/assembliesGet.ts +42 -0
  485. package/src/alphalib/types/assemblyReplay.ts +24 -0
  486. package/src/alphalib/types/assemblyReplayNotification.ts +16 -0
  487. package/src/alphalib/types/assemblyStatus.ts +794 -0
  488. package/src/alphalib/types/bill.ts +9 -0
  489. package/src/alphalib/types/robots/_index.ts +1201 -0
  490. package/src/alphalib/types/robots/_instructions-primitives.ts +1770 -0
  491. package/src/alphalib/types/robots/ai-chat.ts +278 -0
  492. package/src/alphalib/types/robots/assembly-savejson.ts +37 -0
  493. package/src/alphalib/types/robots/audio-artwork.ts +107 -0
  494. package/src/alphalib/types/robots/audio-concat.ts +142 -0
  495. package/src/alphalib/types/robots/audio-encode.ts +103 -0
  496. package/src/alphalib/types/robots/audio-loop.ts +102 -0
  497. package/src/alphalib/types/robots/audio-merge.ts +137 -0
  498. package/src/alphalib/types/robots/audio-waveform.ts +280 -0
  499. package/src/alphalib/types/robots/azure-import.ts +111 -0
  500. package/src/alphalib/types/robots/azure-store.ts +143 -0
  501. package/src/alphalib/types/robots/backblaze-import.ts +119 -0
  502. package/src/alphalib/types/robots/backblaze-store.ts +104 -0
  503. package/src/alphalib/types/robots/cloudfiles-import.ts +118 -0
  504. package/src/alphalib/types/robots/cloudfiles-store.ts +104 -0
  505. package/src/alphalib/types/robots/cloudflare-import.ts +121 -0
  506. package/src/alphalib/types/robots/cloudflare-store.ts +120 -0
  507. package/src/alphalib/types/robots/digitalocean-import.ts +118 -0
  508. package/src/alphalib/types/robots/digitalocean-store.ts +125 -0
  509. package/src/alphalib/types/robots/document-autorotate.ts +74 -0
  510. package/src/alphalib/types/robots/document-convert.ts +302 -0
  511. package/src/alphalib/types/robots/document-merge.ts +114 -0
  512. package/src/alphalib/types/robots/document-ocr.ts +120 -0
  513. package/src/alphalib/types/robots/document-split.ts +78 -0
  514. package/src/alphalib/types/robots/document-thumbs.ts +231 -0
  515. package/src/alphalib/types/robots/dropbox-import.ts +100 -0
  516. package/src/alphalib/types/robots/dropbox-store.ts +97 -0
  517. package/src/alphalib/types/robots/edgly-deliver.ts +73 -0
  518. package/src/alphalib/types/robots/file-compress.ts +167 -0
  519. package/src/alphalib/types/robots/file-decompress.ts +125 -0
  520. package/src/alphalib/types/robots/file-filter.ts +173 -0
  521. package/src/alphalib/types/robots/file-hash.ts +86 -0
  522. package/src/alphalib/types/robots/file-preview.ts +260 -0
  523. package/src/alphalib/types/robots/file-read.ts +71 -0
  524. package/src/alphalib/types/robots/file-serve.ts +128 -0
  525. package/src/alphalib/types/robots/file-verify.ts +102 -0
  526. package/src/alphalib/types/robots/file-virusscan.ts +113 -0
  527. package/src/alphalib/types/robots/file-watermark.ts +56 -0
  528. package/src/alphalib/types/robots/ftp-import.ts +95 -0
  529. package/src/alphalib/types/robots/ftp-store.ts +119 -0
  530. package/src/alphalib/types/robots/google-import.ts +115 -0
  531. package/src/alphalib/types/robots/google-store.ts +139 -0
  532. package/src/alphalib/types/robots/html-convert.ts +165 -0
  533. package/src/alphalib/types/robots/http-import.ts +168 -0
  534. package/src/alphalib/types/robots/image-bgremove.ts +95 -0
  535. package/src/alphalib/types/robots/image-describe.ts +121 -0
  536. package/src/alphalib/types/robots/image-facedetect.ts +187 -0
  537. package/src/alphalib/types/robots/image-generate.ts +92 -0
  538. package/src/alphalib/types/robots/image-merge.ts +127 -0
  539. package/src/alphalib/types/robots/image-ocr.ts +112 -0
  540. package/src/alphalib/types/robots/image-optimize.ts +114 -0
  541. package/src/alphalib/types/robots/image-resize.ts +653 -0
  542. package/src/alphalib/types/robots/meta-read.ts +44 -0
  543. package/src/alphalib/types/robots/meta-write.ts +93 -0
  544. package/src/alphalib/types/robots/minio-import.ts +120 -0
  545. package/src/alphalib/types/robots/minio-store.ts +115 -0
  546. package/src/alphalib/types/robots/progress-simulate.ts +40 -0
  547. package/src/alphalib/types/robots/s3-import.ts +175 -0
  548. package/src/alphalib/types/robots/s3-store.ts +198 -0
  549. package/src/alphalib/types/robots/script-run.ts +122 -0
  550. package/src/alphalib/types/robots/sftp-import.ts +92 -0
  551. package/src/alphalib/types/robots/sftp-store.ts +110 -0
  552. package/src/alphalib/types/robots/speech-transcribe.ts +139 -0
  553. package/src/alphalib/types/robots/supabase-import.ts +122 -0
  554. package/src/alphalib/types/robots/supabase-store.ts +105 -0
  555. package/src/alphalib/types/robots/swift-import.ts +120 -0
  556. package/src/alphalib/types/robots/swift-store.ts +112 -0
  557. package/src/alphalib/types/robots/text-speak.ts +152 -0
  558. package/src/alphalib/types/robots/text-translate.ts +245 -0
  559. package/src/alphalib/types/robots/tigris-import.ts +124 -0
  560. package/src/alphalib/types/robots/tigris-store.ts +119 -0
  561. package/src/alphalib/types/robots/tlcdn-deliver.ts +73 -0
  562. package/src/alphalib/types/robots/tus-store.ts +129 -0
  563. package/src/alphalib/types/robots/upload-handle.ts +95 -0
  564. package/src/alphalib/types/robots/video-adaptive.ts +179 -0
  565. package/src/alphalib/types/robots/video-concat.ts +130 -0
  566. package/src/alphalib/types/robots/video-encode.ts +141 -0
  567. package/src/alphalib/types/robots/video-merge.ts +138 -0
  568. package/src/alphalib/types/robots/video-ondemand.ts +161 -0
  569. package/src/alphalib/types/robots/video-subtitle.ts +159 -0
  570. package/src/alphalib/types/robots/video-thumbs.ts +158 -0
  571. package/src/alphalib/types/robots/vimeo-import.ts +126 -0
  572. package/src/alphalib/types/robots/vimeo-store.ts +143 -0
  573. package/src/alphalib/types/robots/wasabi-import.ts +124 -0
  574. package/src/alphalib/types/robots/wasabi-store.ts +113 -0
  575. package/src/alphalib/types/robots/youtube-store.ts +153 -0
  576. package/src/alphalib/types/stackVersions.ts +12 -0
  577. package/src/alphalib/types/template.ts +277 -0
  578. package/src/alphalib/types/templateCredential.ts +61 -0
  579. package/src/alphalib/zodParseWithContext.ts +306 -0
  580. package/src/apiTypes.ts +154 -0
  581. package/src/cli/OutputCtl.ts +115 -0
  582. package/src/cli/commands/BaseCommand.ts +71 -0
  583. package/src/cli/commands/assemblies.ts +1373 -0
  584. package/src/cli/commands/auth.ts +354 -0
  585. package/src/cli/commands/bills.ts +91 -0
  586. package/src/cli/commands/index.ts +65 -0
  587. package/src/cli/commands/notifications.ts +63 -0
  588. package/src/cli/commands/templates.ts +556 -0
  589. package/src/cli/helpers.ts +50 -0
  590. package/src/cli/template-last-modified.ts +156 -0
  591. package/src/cli/types.ts +70 -0
  592. package/src/cli.ts +44 -0
  593. package/src/tus.ts +168 -0
@@ -0,0 +1,1373 @@
1
+ import EventEmitter from 'node:events'
2
+ import fs from 'node:fs'
3
+ import fsp from 'node:fs/promises'
4
+ import path from 'node:path'
5
+ import process from 'node:process'
6
+ import type { Readable, Writable } from 'node:stream'
7
+ import { pipeline } from 'node:stream/promises'
8
+ import { setTimeout as delay } from 'node:timers/promises'
9
+ import tty from 'node:tty'
10
+ import { promisify } from 'node:util'
11
+ import { Command, Option } from 'clipanion'
12
+ import got from 'got'
13
+ import PQueue from 'p-queue'
14
+ import * as t from 'typanion'
15
+ import { z } from 'zod'
16
+ import { tryCatch } from '../../alphalib/tryCatch.ts'
17
+ import type { Steps, StepsInput } from '../../alphalib/types/template.ts'
18
+ import { stepsSchema } from '../../alphalib/types/template.ts'
19
+ import type { CreateAssemblyParams, ReplayAssemblyParams } from '../../apiTypes.ts'
20
+ import type { CreateAssemblyOptions, Transloadit } from '../../Transloadit.ts'
21
+ import { createReadStream, formatAPIError, streamToBuffer } from '../helpers.ts'
22
+ import type { IOutputCtl } from '../OutputCtl.ts'
23
+ import { ensureError, isErrnoException } from '../types.ts'
24
+ import { AuthenticatedCommand } from './BaseCommand.ts'
25
+
26
+ // --- From assemblies.ts: Schemas and interfaces ---
27
+ export interface AssemblyListOptions {
28
+ before?: string
29
+ after?: string
30
+ fields?: string[]
31
+ keywords?: string[]
32
+ pagesize?: number
33
+ }
34
+
35
+ export interface AssemblyGetOptions {
36
+ assemblies: string[]
37
+ }
38
+
39
+ interface AssemblyDeleteOptions {
40
+ assemblies: string[]
41
+ }
42
+
43
+ export interface AssemblyReplayOptions {
44
+ fields?: Record<string, string>
45
+ reparse?: boolean
46
+ steps?: string
47
+ notify_url?: string
48
+ assemblies: string[]
49
+ }
50
+
51
+ const AssemblySchema = z.object({
52
+ id: z.string(),
53
+ })
54
+
55
+ // --- Business logic functions (from assemblies.ts) ---
56
+
57
+ export function list(
58
+ output: IOutputCtl,
59
+ client: Transloadit,
60
+ { before, after, fields, keywords }: AssemblyListOptions,
61
+ ): Promise<void> {
62
+ const assemblies = client.streamAssemblies({
63
+ fromdate: after,
64
+ todate: before,
65
+ keywords,
66
+ })
67
+
68
+ assemblies.on('readable', () => {
69
+ const assembly: unknown = assemblies.read()
70
+ if (assembly == null) return
71
+
72
+ const parsed = AssemblySchema.safeParse(assembly)
73
+ if (!parsed.success) return
74
+
75
+ if (fields == null) {
76
+ output.print(parsed.data.id, assembly)
77
+ } else {
78
+ const assemblyRecord = assembly as Record<string, unknown>
79
+ output.print(fields.map((field) => assemblyRecord[field]).join(' '), assembly)
80
+ }
81
+ })
82
+
83
+ return new Promise<void>((resolve) => {
84
+ assemblies.on('end', resolve)
85
+ assemblies.on('error', (err: unknown) => {
86
+ output.error(formatAPIError(err))
87
+ resolve()
88
+ })
89
+ })
90
+ }
91
+
92
+ export async function get(
93
+ output: IOutputCtl,
94
+ client: Transloadit,
95
+ { assemblies }: AssemblyGetOptions,
96
+ ): Promise<void> {
97
+ for (const assembly of assemblies) {
98
+ await delay(1000)
99
+ const [err, result] = await tryCatch(client.getAssembly(assembly))
100
+ if (err) {
101
+ output.error(formatAPIError(err))
102
+ throw ensureError(err)
103
+ }
104
+ output.print(result, result)
105
+ }
106
+ }
107
+
108
+ async function deleteAssemblies(
109
+ output: IOutputCtl,
110
+ client: Transloadit,
111
+ { assemblies }: AssemblyDeleteOptions,
112
+ ): Promise<void> {
113
+ const promises = assemblies.map(async (assembly) => {
114
+ const [err] = await tryCatch(client.cancelAssembly(assembly))
115
+ if (err) {
116
+ output.error(formatAPIError(err))
117
+ }
118
+ })
119
+ await Promise.all(promises)
120
+ }
121
+
122
+ // Export with `delete` alias for tests (can't use `delete` as function name)
123
+ export { deleteAssemblies as delete }
124
+
125
+ export async function replay(
126
+ output: IOutputCtl,
127
+ client: Transloadit,
128
+ { fields, reparse, steps, notify_url, assemblies }: AssemblyReplayOptions,
129
+ ): Promise<void> {
130
+ if (steps) {
131
+ try {
132
+ const buf = await streamToBuffer(createReadStream(steps))
133
+ const parsed: unknown = JSON.parse(buf.toString())
134
+ const validated = stepsSchema.safeParse(parsed)
135
+ if (!validated.success) {
136
+ throw new Error(`Invalid steps format: ${validated.error.message}`)
137
+ }
138
+ await apiCall(validated.data)
139
+ } catch (err) {
140
+ const error = ensureError(err)
141
+ output.error(error.message)
142
+ }
143
+ } else {
144
+ await apiCall()
145
+ }
146
+
147
+ async function apiCall(stepsOverride?: Steps): Promise<void> {
148
+ const promises = assemblies.map(async (assembly) => {
149
+ const [err] = await tryCatch(
150
+ client.replayAssembly(assembly, {
151
+ reparse_template: reparse ? 1 : 0,
152
+ fields,
153
+ notify_url,
154
+ // Steps (validated) is assignable to StepsInput at runtime; cast for TS
155
+ steps: stepsOverride as ReplayAssemblyParams['steps'],
156
+ }),
157
+ )
158
+ if (err) {
159
+ output.error(formatAPIError(err))
160
+ }
161
+ })
162
+ await Promise.all(promises)
163
+ }
164
+ }
165
+
166
+ // --- From assemblies-create.ts: Helper classes and functions ---
167
+ interface NodeWatcher {
168
+ on(event: 'error', listener: (err: Error) => void): void
169
+ on(event: 'close', listener: () => void): void
170
+ on(event: 'change', listener: (evt: string, filename: string) => void): void
171
+ on(event: string, listener: (...args: unknown[]) => void): void
172
+ close(): void
173
+ }
174
+
175
+ type NodeWatchFn = (path: string, options?: { recursive?: boolean }) => NodeWatcher
176
+
177
+ let nodeWatch: NodeWatchFn | undefined
178
+
179
+ async function getNodeWatch(): Promise<NodeWatchFn> {
180
+ if (!nodeWatch) {
181
+ const mod = (await import('node-watch')) as unknown as { default: NodeWatchFn }
182
+ nodeWatch = mod.default
183
+ }
184
+ return nodeWatch
185
+ }
186
+
187
+ // workaround for determining mime-type of stdin
188
+ const stdinWithPath = process.stdin as unknown as { path: string }
189
+ stdinWithPath.path = '/dev/stdin'
190
+
191
+ interface OutStream extends Writable {
192
+ path?: string
193
+ mtime?: Date
194
+ }
195
+
196
+ interface Job {
197
+ in: Readable | null
198
+ out: OutStream | null
199
+ }
200
+
201
+ type OutstreamProvider = (inpath: string | null, indir?: string) => Promise<OutStream | null>
202
+
203
+ interface StreamRegistry {
204
+ [key: string]: OutStream | undefined
205
+ }
206
+
207
+ interface JobEmitterOptions {
208
+ recursive?: boolean
209
+ outstreamProvider: OutstreamProvider
210
+ streamRegistry: StreamRegistry
211
+ watch?: boolean
212
+ reprocessStale?: boolean
213
+ }
214
+
215
+ interface ReaddirJobEmitterOptions {
216
+ dir: string
217
+ streamRegistry: StreamRegistry
218
+ recursive?: boolean
219
+ outstreamProvider: OutstreamProvider
220
+ topdir?: string
221
+ }
222
+
223
+ interface SingleJobEmitterOptions {
224
+ file: string
225
+ streamRegistry: StreamRegistry
226
+ outstreamProvider: OutstreamProvider
227
+ }
228
+
229
+ interface WatchJobEmitterOptions {
230
+ file: string
231
+ streamRegistry: StreamRegistry
232
+ recursive?: boolean
233
+ outstreamProvider: OutstreamProvider
234
+ }
235
+
236
+ interface StatLike {
237
+ isDirectory(): boolean
238
+ }
239
+
240
+ const fstatAsync = promisify(fs.fstat)
241
+
242
+ async function myStat(
243
+ stdioStream: NodeJS.ReadStream | NodeJS.WriteStream,
244
+ filepath: string,
245
+ ): Promise<fs.Stats> {
246
+ if (filepath === '-') {
247
+ const stream = stdioStream as NodeJS.ReadStream & { fd: number }
248
+ return await fstatAsync(stream.fd)
249
+ }
250
+ return await fsp.stat(filepath)
251
+ }
252
+
253
+ function dirProvider(output: string): OutstreamProvider {
254
+ return async (inpath, indir = process.cwd()) => {
255
+ if (inpath == null || inpath === '-') {
256
+ throw new Error('You must provide an input to output to a directory')
257
+ }
258
+
259
+ let relpath = path.relative(indir, inpath)
260
+ relpath = relpath.replace(/^(\.\.\/)+/, '')
261
+ const outpath = path.join(output, relpath)
262
+ const outdir = path.dirname(outpath)
263
+
264
+ await fsp.mkdir(outdir, { recursive: true })
265
+ const [, stats] = await tryCatch(fsp.stat(outpath))
266
+ const mtime = stats?.mtime ?? new Date(0)
267
+ const outstream = fs.createWriteStream(outpath) as OutStream
268
+ // Attach a no-op error handler to prevent unhandled errors if stream is destroyed
269
+ // before being consumed (e.g., due to output collision detection)
270
+ outstream.on('error', () => {})
271
+ outstream.mtime = mtime
272
+ return outstream
273
+ }
274
+ }
275
+
276
+ function fileProvider(output: string): OutstreamProvider {
277
+ const dirExistsP = fsp.mkdir(path.dirname(output), { recursive: true })
278
+ return async (_inpath) => {
279
+ await dirExistsP
280
+ if (output === '-') return process.stdout as OutStream
281
+
282
+ const [, stats] = await tryCatch(fsp.stat(output))
283
+ const mtime = stats?.mtime ?? new Date(0)
284
+ const outstream = fs.createWriteStream(output) as OutStream
285
+ // Attach a no-op error handler to prevent unhandled errors if stream is destroyed
286
+ // before being consumed (e.g., due to output collision detection)
287
+ outstream.on('error', () => {})
288
+ outstream.mtime = mtime
289
+ return outstream
290
+ }
291
+ }
292
+
293
+ function nullProvider(): OutstreamProvider {
294
+ return async (_inpath) => null
295
+ }
296
+
297
+ class MyEventEmitter extends EventEmitter {
298
+ protected hasEnded: boolean
299
+
300
+ constructor() {
301
+ super()
302
+ this.hasEnded = false
303
+ }
304
+
305
+ override emit(event: string | symbol, ...args: unknown[]): boolean {
306
+ if (this.hasEnded) return false
307
+ if (event === 'end' || event === 'error') {
308
+ this.hasEnded = true
309
+ return super.emit(event, ...args)
310
+ }
311
+ return super.emit(event, ...args)
312
+ }
313
+ }
314
+
315
+ class ReaddirJobEmitter extends MyEventEmitter {
316
+ constructor({
317
+ dir,
318
+ streamRegistry,
319
+ recursive,
320
+ outstreamProvider,
321
+ topdir = dir,
322
+ }: ReaddirJobEmitterOptions) {
323
+ super()
324
+
325
+ process.nextTick(() => {
326
+ this.processDirectory({ dir, streamRegistry, recursive, outstreamProvider, topdir }).catch(
327
+ (err) => {
328
+ this.emit('error', err)
329
+ },
330
+ )
331
+ })
332
+ }
333
+
334
+ private async processDirectory({
335
+ dir,
336
+ streamRegistry,
337
+ recursive,
338
+ outstreamProvider,
339
+ topdir,
340
+ }: ReaddirJobEmitterOptions & { topdir: string }): Promise<void> {
341
+ const files = await fsp.readdir(dir)
342
+
343
+ const pendingOperations: Promise<void>[] = []
344
+
345
+ for (const filename of files) {
346
+ const file = path.normalize(path.join(dir, filename))
347
+ pendingOperations.push(
348
+ this.processFile({ file, streamRegistry, recursive, outstreamProvider, topdir }),
349
+ )
350
+ }
351
+
352
+ await Promise.all(pendingOperations)
353
+ this.emit('end')
354
+ }
355
+
356
+ private async processFile({
357
+ file,
358
+ streamRegistry,
359
+ recursive = false,
360
+ outstreamProvider,
361
+ topdir,
362
+ }: {
363
+ file: string
364
+ streamRegistry: StreamRegistry
365
+ recursive?: boolean
366
+ outstreamProvider: OutstreamProvider
367
+ topdir: string
368
+ }): Promise<void> {
369
+ const stats = await fsp.stat(file)
370
+
371
+ if (stats.isDirectory()) {
372
+ if (recursive) {
373
+ await new Promise<void>((resolve, reject) => {
374
+ const subdirEmitter = new ReaddirJobEmitter({
375
+ dir: file,
376
+ streamRegistry,
377
+ recursive,
378
+ outstreamProvider,
379
+ topdir,
380
+ })
381
+ subdirEmitter.on('job', (job: Job) => this.emit('job', job))
382
+ subdirEmitter.on('error', (error: Error) => reject(error))
383
+ subdirEmitter.on('end', () => resolve())
384
+ })
385
+ }
386
+ } else {
387
+ const existing = streamRegistry[file]
388
+ if (existing) existing.end()
389
+ const outstream = await outstreamProvider(file, topdir)
390
+ streamRegistry[file] = outstream ?? undefined
391
+ const instream = fs.createReadStream(file)
392
+ // Attach a no-op error handler to prevent unhandled errors if stream is destroyed
393
+ // before being consumed (e.g., due to output collision detection)
394
+ instream.on('error', () => {})
395
+ this.emit('job', { in: instream, out: outstream })
396
+ }
397
+ }
398
+ }
399
+
400
+ class SingleJobEmitter extends MyEventEmitter {
401
+ constructor({ file, streamRegistry, outstreamProvider }: SingleJobEmitterOptions) {
402
+ super()
403
+
404
+ const normalizedFile = path.normalize(file)
405
+ const existing = streamRegistry[normalizedFile]
406
+ if (existing) existing.end()
407
+ outstreamProvider(normalizedFile).then((outstream) => {
408
+ streamRegistry[normalizedFile] = outstream ?? undefined
409
+
410
+ let instream: Readable | null
411
+ if (normalizedFile === '-') {
412
+ if (tty.isatty(process.stdin.fd)) {
413
+ instream = null
414
+ } else {
415
+ instream = process.stdin
416
+ }
417
+ } else {
418
+ instream = fs.createReadStream(normalizedFile)
419
+ // Attach a no-op error handler to prevent unhandled errors if stream is destroyed
420
+ // before being consumed (e.g., due to output collision detection)
421
+ instream.on('error', () => {})
422
+ }
423
+
424
+ process.nextTick(() => {
425
+ this.emit('job', { in: instream, out: outstream })
426
+ this.emit('end')
427
+ })
428
+ })
429
+ }
430
+ }
431
+
432
+ class InputlessJobEmitter extends MyEventEmitter {
433
+ constructor({
434
+ outstreamProvider,
435
+ }: { streamRegistry: StreamRegistry; outstreamProvider: OutstreamProvider }) {
436
+ super()
437
+
438
+ process.nextTick(() => {
439
+ outstreamProvider(null).then((outstream) => {
440
+ try {
441
+ this.emit('job', { in: null, out: outstream })
442
+ } catch (err) {
443
+ this.emit('error', err)
444
+ }
445
+
446
+ this.emit('end')
447
+ })
448
+ })
449
+ }
450
+ }
451
+
452
+ class NullJobEmitter extends MyEventEmitter {
453
+ constructor() {
454
+ super()
455
+ process.nextTick(() => this.emit('end'))
456
+ }
457
+ }
458
+
459
+ class WatchJobEmitter extends MyEventEmitter {
460
+ private watcher: NodeWatcher | null = null
461
+
462
+ constructor({ file, streamRegistry, recursive, outstreamProvider }: WatchJobEmitterOptions) {
463
+ super()
464
+
465
+ this.init({ file, streamRegistry, recursive, outstreamProvider }).catch((err) => {
466
+ this.emit('error', err)
467
+ })
468
+
469
+ // Clean up watcher on process exit signals
470
+ const cleanup = () => this.close()
471
+ process.once('SIGINT', cleanup)
472
+ process.once('SIGTERM', cleanup)
473
+ }
474
+
475
+ /** Close the file watcher and release resources */
476
+ close(): void {
477
+ if (this.watcher) {
478
+ this.watcher.close()
479
+ this.watcher = null
480
+ }
481
+ }
482
+
483
+ private async init({
484
+ file,
485
+ streamRegistry,
486
+ recursive,
487
+ outstreamProvider,
488
+ }: WatchJobEmitterOptions): Promise<void> {
489
+ const stats = await fsp.stat(file)
490
+ const topdir = stats.isDirectory() ? file : undefined
491
+
492
+ const watchFn = await getNodeWatch()
493
+ this.watcher = watchFn(file, { recursive })
494
+
495
+ this.watcher.on('error', (err: Error) => {
496
+ this.close()
497
+ this.emit('error', err)
498
+ })
499
+ this.watcher.on('close', () => this.emit('end'))
500
+ this.watcher.on('change', (_evt: string, filename: string) => {
501
+ const normalizedFile = path.normalize(filename)
502
+ this.handleChange(normalizedFile, topdir, streamRegistry, outstreamProvider).catch((err) => {
503
+ this.emit('error', err)
504
+ })
505
+ })
506
+ }
507
+
508
+ private async handleChange(
509
+ normalizedFile: string,
510
+ topdir: string | undefined,
511
+ streamRegistry: StreamRegistry,
512
+ outstreamProvider: OutstreamProvider,
513
+ ): Promise<void> {
514
+ const stats = await fsp.stat(normalizedFile)
515
+ if (stats.isDirectory()) return
516
+
517
+ const existing = streamRegistry[normalizedFile]
518
+ if (existing) existing.end()
519
+
520
+ const outstream = await outstreamProvider(normalizedFile, topdir)
521
+ streamRegistry[normalizedFile] = outstream ?? undefined
522
+
523
+ const instream = fs.createReadStream(normalizedFile)
524
+ // Attach a no-op error handler to prevent unhandled errors if stream is destroyed
525
+ // before being consumed (e.g., due to output collision detection)
526
+ instream.on('error', () => {})
527
+ this.emit('job', { in: instream, out: outstream })
528
+ }
529
+ }
530
+
531
+ class MergedJobEmitter extends MyEventEmitter {
532
+ constructor(...jobEmitters: MyEventEmitter[]) {
533
+ super()
534
+
535
+ let ncomplete = 0
536
+
537
+ for (const jobEmitter of jobEmitters) {
538
+ jobEmitter.on('error', (err: Error) => this.emit('error', err))
539
+ jobEmitter.on('job', (job: Job) => this.emit('job', job))
540
+ jobEmitter.on('end', () => {
541
+ if (++ncomplete === jobEmitters.length) this.emit('end')
542
+ })
543
+ }
544
+
545
+ if (jobEmitters.length === 0) {
546
+ this.emit('end')
547
+ }
548
+ }
549
+ }
550
+
551
+ class ConcattedJobEmitter extends MyEventEmitter {
552
+ constructor(emitterFn: () => MyEventEmitter, ...emitterFns: (() => MyEventEmitter)[]) {
553
+ super()
554
+
555
+ const emitter = emitterFn()
556
+
557
+ emitter.on('error', (err: Error) => this.emit('error', err))
558
+ emitter.on('job', (job: Job) => this.emit('job', job))
559
+
560
+ if (emitterFns.length === 0) {
561
+ emitter.on('end', () => this.emit('end'))
562
+ } else {
563
+ emitter.on('end', () => {
564
+ const firstFn = emitterFns[0]
565
+ if (!firstFn) {
566
+ this.emit('end')
567
+ return
568
+ }
569
+ const restEmitter = new ConcattedJobEmitter(firstFn, ...emitterFns.slice(1))
570
+ restEmitter.on('error', (err: Error) => this.emit('error', err))
571
+ restEmitter.on('job', (job: Job) => this.emit('job', job))
572
+ restEmitter.on('end', () => this.emit('end'))
573
+ })
574
+ }
575
+ }
576
+ }
577
+
578
+ function detectConflicts(jobEmitter: EventEmitter): MyEventEmitter {
579
+ const emitter = new MyEventEmitter()
580
+ const outfileAssociations: Record<string, string> = {}
581
+
582
+ jobEmitter.on('end', () => emitter.emit('end'))
583
+ jobEmitter.on('error', (err: Error) => emitter.emit('error', err))
584
+ jobEmitter.on('job', (job: Job) => {
585
+ if (job.in == null || job.out == null) {
586
+ emitter.emit('job', job)
587
+ return
588
+ }
589
+ const inPath = (job.in as fs.ReadStream).path as string
590
+ const outPath = job.out.path as string
591
+ if (Object.hasOwn(outfileAssociations, outPath) && outfileAssociations[outPath] !== inPath) {
592
+ emitter.emit(
593
+ 'error',
594
+ new Error(`Output collision between '${inPath}' and '${outfileAssociations[outPath]}'`),
595
+ )
596
+ } else {
597
+ outfileAssociations[outPath] = inPath
598
+ emitter.emit('job', job)
599
+ }
600
+ })
601
+
602
+ return emitter
603
+ }
604
+
605
+ function dismissStaleJobs(jobEmitter: EventEmitter): MyEventEmitter {
606
+ const emitter = new MyEventEmitter()
607
+ const pendingChecks: Promise<void>[] = []
608
+
609
+ jobEmitter.on('end', () => Promise.all(pendingChecks).then(() => emitter.emit('end')))
610
+ jobEmitter.on('error', (err: Error) => emitter.emit('error', err))
611
+ jobEmitter.on('job', (job: Job) => {
612
+ if (job.in == null || job.out == null) {
613
+ emitter.emit('job', job)
614
+ return
615
+ }
616
+
617
+ const inPath = (job.in as fs.ReadStream).path as string
618
+ const checkPromise = fsp
619
+ .stat(inPath)
620
+ .then((stats) => {
621
+ const inM = stats.mtime
622
+ const outM = job.out?.mtime ?? new Date(0)
623
+
624
+ if (outM <= inM) emitter.emit('job', job)
625
+ })
626
+ .catch(() => {
627
+ emitter.emit('job', job)
628
+ })
629
+ pendingChecks.push(checkPromise)
630
+ })
631
+
632
+ return emitter
633
+ }
634
+
635
+ function makeJobEmitter(
636
+ inputs: string[],
637
+ {
638
+ recursive,
639
+ outstreamProvider,
640
+ streamRegistry,
641
+ watch: watchOption,
642
+ reprocessStale,
643
+ }: JobEmitterOptions,
644
+ ): MyEventEmitter {
645
+ const emitter = new EventEmitter()
646
+
647
+ const emitterFns: (() => MyEventEmitter)[] = []
648
+ const watcherFns: (() => MyEventEmitter)[] = []
649
+
650
+ async function processInputs(): Promise<void> {
651
+ for (const input of inputs) {
652
+ if (input === '-') {
653
+ emitterFns.push(
654
+ () => new SingleJobEmitter({ file: input, outstreamProvider, streamRegistry }),
655
+ )
656
+ watcherFns.push(() => new NullJobEmitter())
657
+ } else {
658
+ const stats = await fsp.stat(input)
659
+ if (stats.isDirectory()) {
660
+ emitterFns.push(
661
+ () =>
662
+ new ReaddirJobEmitter({ dir: input, recursive, outstreamProvider, streamRegistry }),
663
+ )
664
+ watcherFns.push(
665
+ () =>
666
+ new WatchJobEmitter({ file: input, recursive, outstreamProvider, streamRegistry }),
667
+ )
668
+ } else {
669
+ emitterFns.push(
670
+ () => new SingleJobEmitter({ file: input, outstreamProvider, streamRegistry }),
671
+ )
672
+ watcherFns.push(
673
+ () =>
674
+ new WatchJobEmitter({ file: input, recursive, outstreamProvider, streamRegistry }),
675
+ )
676
+ }
677
+ }
678
+ }
679
+
680
+ if (inputs.length === 0) {
681
+ emitterFns.push(() => new InputlessJobEmitter({ outstreamProvider, streamRegistry }))
682
+ }
683
+
684
+ startEmitting()
685
+ }
686
+
687
+ function startEmitting(): void {
688
+ let source: MyEventEmitter = new MergedJobEmitter(...emitterFns.map((f) => f()))
689
+
690
+ if (watchOption) {
691
+ source = new ConcattedJobEmitter(
692
+ () => source,
693
+ () => new MergedJobEmitter(...watcherFns.map((f) => f())),
694
+ )
695
+ }
696
+
697
+ source.on('job', (job: Job) => emitter.emit('job', job))
698
+ source.on('error', (err: Error) => emitter.emit('error', err))
699
+ source.on('end', () => emitter.emit('end'))
700
+ }
701
+
702
+ processInputs().catch((err) => {
703
+ emitter.emit('error', err)
704
+ })
705
+
706
+ const stalefilter = reprocessStale ? (x: EventEmitter) => x as MyEventEmitter : dismissStaleJobs
707
+ return stalefilter(detectConflicts(emitter))
708
+ }
709
+
710
+ export interface AssembliesCreateOptions {
711
+ steps?: string
712
+ template?: string
713
+ fields?: Record<string, string>
714
+ watch?: boolean
715
+ recursive?: boolean
716
+ inputs: string[]
717
+ output?: string | null
718
+ del?: boolean
719
+ reprocessStale?: boolean
720
+ singleAssembly?: boolean
721
+ concurrency?: number
722
+ }
723
+
724
+ const DEFAULT_CONCURRENCY = 5
725
+
726
+ // --- Main assembly create function ---
727
+ export async function create(
728
+ outputctl: IOutputCtl,
729
+ client: Transloadit,
730
+ {
731
+ steps,
732
+ template,
733
+ fields,
734
+ watch: watchOption,
735
+ recursive,
736
+ inputs,
737
+ output,
738
+ del,
739
+ reprocessStale,
740
+ singleAssembly,
741
+ concurrency = DEFAULT_CONCURRENCY,
742
+ }: AssembliesCreateOptions,
743
+ ): Promise<{ results: unknown[]; hasFailures: boolean }> {
744
+ // Quick fix for https://github.com/transloadit/transloadify/issues/13
745
+ // Only default to stdout when output is undefined (not provided), not when explicitly null
746
+ let resolvedOutput = output
747
+ if (resolvedOutput === undefined && !process.stdout.isTTY) resolvedOutput = '-'
748
+
749
+ // Read steps file async before entering the Promise constructor
750
+ // We use StepsInput (the input type) rather than Steps (the transformed output type)
751
+ // to avoid zod adding default values that the API may reject
752
+ let stepsData: StepsInput | undefined
753
+ if (steps) {
754
+ const stepsContent = await fsp.readFile(steps, 'utf8')
755
+ const parsed: unknown = JSON.parse(stepsContent)
756
+ // Basic structural validation: must be an object with step names as keys
757
+ if (parsed == null || typeof parsed !== 'object' || Array.isArray(parsed)) {
758
+ throw new Error('Invalid steps format: expected an object with step names as keys')
759
+ }
760
+ // Validate each step has a robot field
761
+ for (const [stepName, step] of Object.entries(parsed)) {
762
+ if (step == null || typeof step !== 'object' || Array.isArray(step)) {
763
+ throw new Error(`Invalid steps format: step '${stepName}' must be an object`)
764
+ }
765
+ if (!('robot' in step) || typeof (step as Record<string, unknown>).robot !== 'string') {
766
+ throw new Error(
767
+ `Invalid steps format: step '${stepName}' must have a 'robot' string property`,
768
+ )
769
+ }
770
+ }
771
+ stepsData = parsed as StepsInput
772
+ }
773
+
774
+ // Determine output stat async before entering the Promise constructor
775
+ let outstat: StatLike | undefined
776
+ if (resolvedOutput != null) {
777
+ const [err, stat] = await tryCatch(myStat(process.stdout, resolvedOutput))
778
+ if (err && (!isErrnoException(err) || err.code !== 'ENOENT')) throw err
779
+ outstat = stat ?? { isDirectory: () => false }
780
+
781
+ if (!outstat.isDirectory() && inputs.length !== 0) {
782
+ const firstInput = inputs[0]
783
+ if (firstInput) {
784
+ const firstInputStat = await myStat(process.stdin, firstInput)
785
+ if (inputs.length > 1 || firstInputStat.isDirectory()) {
786
+ const msg = 'Output must be a directory when specifying multiple inputs'
787
+ outputctl.error(msg)
788
+ throw new Error(msg)
789
+ }
790
+ }
791
+ }
792
+ }
793
+
794
+ return new Promise((resolve, reject) => {
795
+ const params: CreateAssemblyParams = (
796
+ stepsData ? { steps: stepsData as CreateAssemblyParams['steps'] } : { template_id: template }
797
+ ) as CreateAssemblyParams
798
+ if (fields) {
799
+ params.fields = fields
800
+ }
801
+
802
+ const outstreamProvider: OutstreamProvider =
803
+ resolvedOutput == null
804
+ ? nullProvider()
805
+ : outstat?.isDirectory()
806
+ ? dirProvider(resolvedOutput)
807
+ : fileProvider(resolvedOutput)
808
+ const streamRegistry: StreamRegistry = {}
809
+
810
+ const emitter = makeJobEmitter(inputs, {
811
+ recursive,
812
+ watch: watchOption,
813
+ outstreamProvider,
814
+ streamRegistry,
815
+ reprocessStale,
816
+ })
817
+
818
+ // Use p-queue for concurrency management
819
+ const queue = new PQueue({ concurrency })
820
+ const results: unknown[] = []
821
+ let hasFailures = false
822
+ // AbortController to cancel all in-flight createAssembly calls when an error occurs
823
+ const abortController = new AbortController()
824
+
825
+ // Helper to process a single assembly job
826
+ async function processAssemblyJob(
827
+ inPath: string | null,
828
+ outPath: string | null,
829
+ outMtime: Date | undefined,
830
+ ): Promise<unknown> {
831
+ outputctl.debug(`PROCESSING JOB ${inPath ?? 'null'} ${outPath ?? 'null'}`)
832
+
833
+ // Create fresh streams for this job
834
+ const inStream = inPath ? fs.createReadStream(inPath) : null
835
+ inStream?.on('error', () => {})
836
+ const outStream = outPath ? (fs.createWriteStream(outPath) as OutStream) : null
837
+ outStream?.on('error', () => {})
838
+ if (outStream) outStream.mtime = outMtime
839
+
840
+ let superceded = false
841
+ if (outStream != null) {
842
+ outStream.on('finish', () => {
843
+ superceded = true
844
+ })
845
+ }
846
+
847
+ const createOptions: CreateAssemblyOptions = {
848
+ params,
849
+ signal: abortController.signal,
850
+ }
851
+ if (inStream != null) {
852
+ createOptions.uploads = { in: inStream }
853
+ }
854
+
855
+ const result = await client.createAssembly(createOptions)
856
+ if (superceded) return undefined
857
+
858
+ const assemblyId = result.assembly_id
859
+ if (!assemblyId) throw new Error('No assembly_id in result')
860
+
861
+ const assembly = await client.awaitAssemblyCompletion(assemblyId, {
862
+ signal: abortController.signal,
863
+ onPoll: () => {
864
+ if (superceded) return false
865
+ return true
866
+ },
867
+ onAssemblyProgress: (status) => {
868
+ outputctl.debug(`Assembly status: ${status.ok}`)
869
+ },
870
+ })
871
+
872
+ if (superceded) return undefined
873
+
874
+ if (assembly.error || (assembly.ok && assembly.ok !== 'ASSEMBLY_COMPLETED')) {
875
+ const msg = `Assembly failed: ${assembly.error || assembly.message} (Status: ${assembly.ok})`
876
+ outputctl.error(msg)
877
+ throw new Error(msg)
878
+ }
879
+
880
+ if (!assembly.results) throw new Error('No results in assembly')
881
+ const resultsKeys = Object.keys(assembly.results)
882
+ const firstKey = resultsKeys[0]
883
+ if (!firstKey) throw new Error('No results in assembly')
884
+ const firstResult = assembly.results[firstKey]
885
+ if (!firstResult || !firstResult[0]) throw new Error('No results in assembly')
886
+ const resulturl = firstResult[0].url
887
+
888
+ if (outStream != null && resulturl && !superceded) {
889
+ outputctl.debug('DOWNLOADING')
890
+ const [dlErr] = await tryCatch(
891
+ pipeline(got.stream(resulturl, { signal: abortController.signal }), outStream),
892
+ )
893
+ if (dlErr) {
894
+ if (dlErr.name !== 'AbortError') {
895
+ outputctl.error(dlErr.message)
896
+ throw dlErr
897
+ }
898
+ }
899
+ }
900
+
901
+ outputctl.debug(`COMPLETED ${inPath ?? 'null'} ${outPath ?? 'null'}`)
902
+
903
+ if (del && inPath) {
904
+ await fsp.unlink(inPath)
905
+ }
906
+ return assembly
907
+ }
908
+
909
+ if (singleAssembly) {
910
+ // Single-assembly mode: collect file paths, then create one assembly with all inputs
911
+ // We close streams immediately to avoid exhausting file descriptors with many files
912
+ const collectedPaths: string[] = []
913
+
914
+ emitter.on('job', (job: Job) => {
915
+ if (job.in != null) {
916
+ const inPath = (job.in as fs.ReadStream).path as string
917
+ outputctl.debug(`COLLECTING JOB ${inPath}`)
918
+ collectedPaths.push(inPath)
919
+ // Close the stream immediately to avoid file descriptor exhaustion
920
+ ;(job.in as fs.ReadStream).destroy()
921
+ outputctl.debug(`STREAM CLOSED ${inPath}`)
922
+ }
923
+ })
924
+
925
+ emitter.on('error', (err: Error) => {
926
+ abortController.abort()
927
+ queue.clear()
928
+ outputctl.error(err)
929
+ reject(err)
930
+ })
931
+
932
+ emitter.on('end', async () => {
933
+ if (collectedPaths.length === 0) {
934
+ resolve({ results: [], hasFailures: false })
935
+ return
936
+ }
937
+
938
+ // Build uploads object, creating fresh streams for each file
939
+ const uploads: Record<string, Readable> = {}
940
+ const inputPaths: string[] = []
941
+ for (const inPath of collectedPaths) {
942
+ const basename = path.basename(inPath)
943
+ let key = basename
944
+ let counter = 1
945
+ while (key in uploads) {
946
+ key = `${path.parse(basename).name}_${counter}${path.parse(basename).ext}`
947
+ counter++
948
+ }
949
+ uploads[key] = fs.createReadStream(inPath)
950
+ inputPaths.push(inPath)
951
+ }
952
+
953
+ outputctl.debug(`Creating single assembly with ${Object.keys(uploads).length} files`)
954
+
955
+ try {
956
+ const assembly = await queue.add(async () => {
957
+ const createOptions: CreateAssemblyOptions = {
958
+ params,
959
+ signal: abortController.signal,
960
+ }
961
+ if (Object.keys(uploads).length > 0) {
962
+ createOptions.uploads = uploads
963
+ }
964
+
965
+ const result = await client.createAssembly(createOptions)
966
+ const assemblyId = result.assembly_id
967
+ if (!assemblyId) throw new Error('No assembly_id in result')
968
+
969
+ const asm = await client.awaitAssemblyCompletion(assemblyId, {
970
+ signal: abortController.signal,
971
+ onAssemblyProgress: (status) => {
972
+ outputctl.debug(`Assembly status: ${status.ok}`)
973
+ },
974
+ })
975
+
976
+ if (asm.error || (asm.ok && asm.ok !== 'ASSEMBLY_COMPLETED')) {
977
+ const msg = `Assembly failed: ${asm.error || asm.message} (Status: ${asm.ok})`
978
+ outputctl.error(msg)
979
+ throw new Error(msg)
980
+ }
981
+
982
+ // Download all results
983
+ if (asm.results && resolvedOutput != null) {
984
+ for (const [stepName, stepResults] of Object.entries(asm.results)) {
985
+ for (const stepResult of stepResults) {
986
+ const resultUrl = stepResult.url
987
+ if (!resultUrl) continue
988
+
989
+ let outPath: string
990
+ if (outstat?.isDirectory()) {
991
+ outPath = path.join(resolvedOutput, stepResult.name || `${stepName}_result`)
992
+ } else {
993
+ outPath = resolvedOutput
994
+ }
995
+
996
+ outputctl.debug(`DOWNLOADING ${stepResult.name} to ${outPath}`)
997
+ const [dlErr] = await tryCatch(
998
+ pipeline(
999
+ got.stream(resultUrl, { signal: abortController.signal }),
1000
+ fs.createWriteStream(outPath),
1001
+ ),
1002
+ )
1003
+ if (dlErr) {
1004
+ if (dlErr.name === 'AbortError') continue
1005
+ outputctl.error(dlErr.message)
1006
+ throw dlErr
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+
1012
+ // Delete input files if requested
1013
+ if (del) {
1014
+ for (const inPath of inputPaths) {
1015
+ await fsp.unlink(inPath)
1016
+ }
1017
+ }
1018
+ return asm
1019
+ })
1020
+ results.push(assembly)
1021
+ } catch (err) {
1022
+ hasFailures = true
1023
+ outputctl.error(err as Error)
1024
+ }
1025
+
1026
+ resolve({ results, hasFailures })
1027
+ })
1028
+ } else {
1029
+ // Default mode: one assembly per file with p-queue concurrency limiting
1030
+ emitter.on('job', (job: Job) => {
1031
+ const inPath = job.in
1032
+ ? (((job.in as fs.ReadStream).path as string | undefined) ?? null)
1033
+ : null
1034
+ const outPath = job.out?.path ?? null
1035
+ const outMtime = job.out?.mtime
1036
+ outputctl.debug(`GOT JOB ${inPath ?? 'null'} ${outPath ?? 'null'}`)
1037
+
1038
+ // Close the original streams immediately - we'll create fresh ones when processing
1039
+ if (job.in != null) {
1040
+ ;(job.in as fs.ReadStream).destroy()
1041
+ }
1042
+ if (job.out != null) {
1043
+ job.out.destroy()
1044
+ }
1045
+
1046
+ // Add job to queue - p-queue handles concurrency automatically
1047
+ queue
1048
+ .add(async () => {
1049
+ const result = await processAssemblyJob(inPath, outPath, outMtime)
1050
+ if (result !== undefined) {
1051
+ results.push(result)
1052
+ }
1053
+ })
1054
+ .catch((err: unknown) => {
1055
+ hasFailures = true
1056
+ outputctl.error(err as Error)
1057
+ })
1058
+ })
1059
+
1060
+ emitter.on('error', (err: Error) => {
1061
+ abortController.abort()
1062
+ queue.clear()
1063
+ outputctl.error(err)
1064
+ reject(err)
1065
+ })
1066
+
1067
+ emitter.on('end', async () => {
1068
+ // Wait for all queued jobs to complete
1069
+ await queue.onIdle()
1070
+ resolve({ results, hasFailures })
1071
+ })
1072
+ }
1073
+ })
1074
+ }
1075
+
1076
+ // --- Command classes ---
1077
+ export class AssembliesCreateCommand extends AuthenticatedCommand {
1078
+ static override paths = [
1079
+ ['assemblies', 'create'],
1080
+ ['assembly', 'create'],
1081
+ ['a', 'create'],
1082
+ ['a', 'c'],
1083
+ ]
1084
+
1085
+ static override usage = Command.Usage({
1086
+ category: 'Assemblies',
1087
+ description: 'Create assemblies to process media',
1088
+ details: `
1089
+ Create assemblies to process media files using Transloadit.
1090
+ You must specify either --steps or --template.
1091
+ `,
1092
+ examples: [
1093
+ [
1094
+ 'Process a file with steps',
1095
+ 'transloadit assemblies create --steps steps.json -i input.jpg -o output.jpg',
1096
+ ],
1097
+ [
1098
+ 'Process with a template',
1099
+ 'transloadit assemblies create --template TEMPLATE_ID -i input.jpg -o output/',
1100
+ ],
1101
+ [
1102
+ 'Watch for changes',
1103
+ 'transloadit assemblies create --steps steps.json -i input/ -o output/ --watch',
1104
+ ],
1105
+ ],
1106
+ })
1107
+
1108
+ steps = Option.String('--steps,-s', {
1109
+ description: 'Specify assembly instructions with a JSON file',
1110
+ })
1111
+
1112
+ template = Option.String('--template,-t', {
1113
+ description: 'Specify a template to use for these assemblies',
1114
+ })
1115
+
1116
+ inputs = Option.Array('--input,-i', {
1117
+ description: 'Provide an input file or a directory',
1118
+ })
1119
+
1120
+ outputPath = Option.String('--output,-o', {
1121
+ description: 'Specify an output file or directory',
1122
+ })
1123
+
1124
+ fields = Option.Array('--field,-f', {
1125
+ description: 'Set a template field (KEY=VAL)',
1126
+ })
1127
+
1128
+ watch = Option.Boolean('--watch,-w', false, {
1129
+ description: 'Watch inputs for changes',
1130
+ })
1131
+
1132
+ recursive = Option.Boolean('--recursive,-r', false, {
1133
+ description: 'Enumerate input directories recursively',
1134
+ })
1135
+
1136
+ deleteAfterProcessing = Option.Boolean('--delete-after-processing,-d', false, {
1137
+ description: 'Delete input files after they are processed',
1138
+ })
1139
+
1140
+ reprocessStale = Option.Boolean('--reprocess-stale', false, {
1141
+ description: 'Process inputs even if output is newer',
1142
+ })
1143
+
1144
+ singleAssembly = Option.Boolean('--single-assembly', false, {
1145
+ description: 'Pass all input files to a single assembly instead of one assembly per file',
1146
+ })
1147
+
1148
+ concurrency = Option.String('--concurrency,-c', {
1149
+ description: 'Maximum number of concurrent assemblies (default: 5)',
1150
+ validator: t.isNumber(),
1151
+ })
1152
+
1153
+ protected async run(): Promise<number | undefined> {
1154
+ if (!this.steps && !this.template) {
1155
+ this.output.error('assemblies create requires exactly one of either --steps or --template')
1156
+ return 1
1157
+ }
1158
+ if (this.steps && this.template) {
1159
+ this.output.error('assemblies create requires exactly one of either --steps or --template')
1160
+ return 1
1161
+ }
1162
+
1163
+ const inputList = this.inputs ?? []
1164
+ if (inputList.length === 0 && this.watch) {
1165
+ this.output.error('assemblies create --watch requires at least one input')
1166
+ return 1
1167
+ }
1168
+
1169
+ // Default to stdin if no inputs and not a TTY
1170
+ if (inputList.length === 0 && !process.stdin.isTTY) {
1171
+ inputList.push('-')
1172
+ }
1173
+
1174
+ const fieldsMap: Record<string, string> = {}
1175
+ for (const field of this.fields ?? []) {
1176
+ const eqIndex = field.indexOf('=')
1177
+ if (eqIndex === -1) {
1178
+ this.output.error(`invalid argument for --field: '${field}'`)
1179
+ return 1
1180
+ }
1181
+ const key = field.slice(0, eqIndex)
1182
+ const value = field.slice(eqIndex + 1)
1183
+ fieldsMap[key] = value
1184
+ }
1185
+
1186
+ if (this.singleAssembly && this.watch) {
1187
+ this.output.error('--single-assembly cannot be used with --watch')
1188
+ return 1
1189
+ }
1190
+
1191
+ const { hasFailures } = await create(this.output, this.client, {
1192
+ steps: this.steps,
1193
+ template: this.template,
1194
+ fields: fieldsMap,
1195
+ watch: this.watch,
1196
+ recursive: this.recursive,
1197
+ inputs: inputList,
1198
+ output: this.outputPath ?? null,
1199
+ del: this.deleteAfterProcessing,
1200
+ reprocessStale: this.reprocessStale,
1201
+ singleAssembly: this.singleAssembly,
1202
+ concurrency: this.concurrency,
1203
+ })
1204
+ return hasFailures ? 1 : undefined
1205
+ }
1206
+ }
1207
+
1208
+ export class AssembliesListCommand extends AuthenticatedCommand {
1209
+ static override paths = [
1210
+ ['assemblies', 'list'],
1211
+ ['assembly', 'list'],
1212
+ ['a', 'list'],
1213
+ ['a', 'l'],
1214
+ ]
1215
+
1216
+ static override usage = Command.Usage({
1217
+ category: 'Assemblies',
1218
+ description: 'List assemblies matching given criteria',
1219
+ examples: [
1220
+ ['List recent assemblies', 'transloadit assemblies list'],
1221
+ ['List assemblies after a date', 'transloadit assemblies list --after 2024-01-01'],
1222
+ ],
1223
+ })
1224
+
1225
+ before = Option.String('--before,-b', {
1226
+ description: 'Return only assemblies created before specified date',
1227
+ })
1228
+
1229
+ after = Option.String('--after,-a', {
1230
+ description: 'Return only assemblies created after specified date',
1231
+ })
1232
+
1233
+ keywords = Option.String('--keywords', {
1234
+ description: 'Comma-separated list of keywords to match assemblies',
1235
+ })
1236
+
1237
+ fields = Option.String('--fields', {
1238
+ description: 'Comma-separated list of fields to return for each assembly',
1239
+ })
1240
+
1241
+ protected async run(): Promise<number | undefined> {
1242
+ const keywordList = this.keywords ? this.keywords.split(',') : undefined
1243
+ const fieldList = this.fields ? this.fields.split(',') : undefined
1244
+
1245
+ await list(this.output, this.client, {
1246
+ before: this.before,
1247
+ after: this.after,
1248
+ keywords: keywordList,
1249
+ fields: fieldList,
1250
+ })
1251
+ return undefined
1252
+ }
1253
+ }
1254
+
1255
+ export class AssembliesGetCommand extends AuthenticatedCommand {
1256
+ static override paths = [
1257
+ ['assemblies', 'get'],
1258
+ ['assembly', 'get'],
1259
+ ['a', 'get'],
1260
+ ['a', 'g'],
1261
+ ]
1262
+
1263
+ static override usage = Command.Usage({
1264
+ category: 'Assemblies',
1265
+ description: 'Fetch assembly statuses',
1266
+ examples: [['Get assembly status', 'transloadit assemblies get ASSEMBLY_ID']],
1267
+ })
1268
+
1269
+ assemblyIds = Option.Rest({ required: 1 })
1270
+
1271
+ protected async run(): Promise<number | undefined> {
1272
+ await get(this.output, this.client, {
1273
+ assemblies: this.assemblyIds,
1274
+ })
1275
+ return undefined
1276
+ }
1277
+ }
1278
+
1279
+ export class AssembliesDeleteCommand extends AuthenticatedCommand {
1280
+ static override paths = [
1281
+ ['assemblies', 'delete'],
1282
+ ['assembly', 'delete'],
1283
+ ['a', 'delete'],
1284
+ ['a', 'd'],
1285
+ ['assemblies', 'cancel'],
1286
+ ['assembly', 'cancel'],
1287
+ ]
1288
+
1289
+ static override usage = Command.Usage({
1290
+ category: 'Assemblies',
1291
+ description: 'Cancel assemblies',
1292
+ examples: [['Cancel an assembly', 'transloadit assemblies delete ASSEMBLY_ID']],
1293
+ })
1294
+
1295
+ assemblyIds = Option.Rest({ required: 1 })
1296
+
1297
+ protected async run(): Promise<number | undefined> {
1298
+ await deleteAssemblies(this.output, this.client, {
1299
+ assemblies: this.assemblyIds,
1300
+ })
1301
+ return undefined
1302
+ }
1303
+ }
1304
+
1305
+ export class AssembliesReplayCommand extends AuthenticatedCommand {
1306
+ static override paths = [
1307
+ ['assemblies', 'replay'],
1308
+ ['assembly', 'replay'],
1309
+ ['a', 'replay'],
1310
+ ['a', 'r'],
1311
+ ]
1312
+
1313
+ static override usage = Command.Usage({
1314
+ category: 'Assemblies',
1315
+ description: 'Replay assemblies',
1316
+ details: `
1317
+ Replay one or more assemblies. By default, replays use the original assembly instructions.
1318
+ Use --steps to override the instructions, or --reparse-template to use the latest template version.
1319
+ `,
1320
+ examples: [
1321
+ ['Replay an assembly with original steps', 'transloadit assemblies replay ASSEMBLY_ID'],
1322
+ [
1323
+ 'Replay with different steps',
1324
+ 'transloadit assemblies replay --steps new-steps.json ASSEMBLY_ID',
1325
+ ],
1326
+ [
1327
+ 'Replay with updated template',
1328
+ 'transloadit assemblies replay --reparse-template ASSEMBLY_ID',
1329
+ ],
1330
+ ],
1331
+ })
1332
+
1333
+ fields = Option.Array('--field,-f', {
1334
+ description: 'Set a template field (KEY=VAL)',
1335
+ })
1336
+
1337
+ steps = Option.String('--steps,-s', {
1338
+ description: 'Optional JSON file to override assembly instructions',
1339
+ })
1340
+
1341
+ notifyUrl = Option.String('--notify-url', {
1342
+ description: 'Specify a new URL for assembly notifications',
1343
+ })
1344
+
1345
+ reparseTemplate = Option.Boolean('--reparse-template', false, {
1346
+ description: 'Use the most up-to-date version of the template',
1347
+ })
1348
+
1349
+ assemblyIds = Option.Rest({ required: 1 })
1350
+
1351
+ protected async run(): Promise<number | undefined> {
1352
+ const fieldsMap: Record<string, string> = {}
1353
+ for (const field of this.fields ?? []) {
1354
+ const eqIndex = field.indexOf('=')
1355
+ if (eqIndex === -1) {
1356
+ this.output.error(`invalid argument for --field: '${field}'`)
1357
+ return 1
1358
+ }
1359
+ const key = field.slice(0, eqIndex)
1360
+ const value = field.slice(eqIndex + 1)
1361
+ fieldsMap[key] = value
1362
+ }
1363
+
1364
+ await replay(this.output, this.client, {
1365
+ fields: fieldsMap,
1366
+ reparse: this.reparseTemplate,
1367
+ steps: this.steps,
1368
+ notify_url: this.notifyUrl,
1369
+ assemblies: this.assemblyIds,
1370
+ })
1371
+ return undefined
1372
+ }
1373
+ }