AssemblyOptions.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import ErrorWithCause from '@uppy/utils/lib/ErrorWithCause'
  2. /**
  3. * Check that Assembly parameters are present and include all required fields.
  4. */
  5. function validateParams (params) {
  6. if (params == null) {
  7. throw new Error('Transloadit: The `params` option is required.')
  8. }
  9. if (typeof params === 'string') {
  10. try {
  11. // eslint-disable-next-line no-param-reassign
  12. params = JSON.parse(params)
  13. } catch (err) {
  14. // Tell the user that this is not an Uppy bug!
  15. throw new ErrorWithCause('Transloadit: The `params` option is a malformed JSON string.', { cause: err })
  16. }
  17. }
  18. if (!params.auth || !params.auth.key) {
  19. throw new Error('Transloadit: The `params.auth.key` option is required. '
  20. + 'You can find your Transloadit API key at https://transloadit.com/c/template-credentials')
  21. }
  22. }
  23. /**
  24. * Combine Assemblies with the same options into a single Assembly for all the
  25. * relevant files.
  26. */
  27. function dedupe (list) {
  28. const dedupeMap = Object.create(null)
  29. for (const { fileIDs, options } of list.filter(Boolean)) {
  30. const id = JSON.stringify(options)
  31. if (id in dedupeMap) {
  32. dedupeMap[id].fileIDArrays.push(fileIDs)
  33. } else {
  34. dedupeMap[id] = {
  35. options,
  36. fileIDArrays: [fileIDs],
  37. }
  38. }
  39. }
  40. return Object.values(dedupeMap).map(({ options, fileIDArrays }) => ({
  41. options,
  42. fileIDs: fileIDArrays.flat(1),
  43. }))
  44. }
  45. async function getAssemblyOptions (file, options) {
  46. const assemblyOptions = typeof options.assemblyOptions === 'function'
  47. ? await options.assemblyOptions(file, options)
  48. : options.assemblyOptions
  49. validateParams(assemblyOptions.params)
  50. return assemblyOptions
  51. }
  52. function getFields (file, assemblyOptions) {
  53. const { fields } = assemblyOptions
  54. if (fields == null) {
  55. return {}
  56. }
  57. if (Array.isArray(fields)) {
  58. return Object.fromEntries(
  59. fields.map((fieldName) => [fieldName, file.meta[fieldName]]),
  60. )
  61. }
  62. return fields
  63. }
  64. /**
  65. * Turn Transloadit plugin options and a list of files into a list of Assembly
  66. * options.
  67. */
  68. class AssemblyOptions {
  69. constructor (files, opts) {
  70. this.files = files
  71. this.opts = opts
  72. }
  73. /**
  74. * Generate a set of Assemblies that will handle the upload.
  75. * Returns a Promise for an object with keys:
  76. * - fileIDs - an array of file IDs to add to this Assembly
  77. * - options - Assembly options
  78. */
  79. async build () {
  80. const options = this.opts
  81. if (this.files.length > 0) {
  82. return Promise.all(
  83. this.files.map(async (file) => {
  84. if (file == null) return undefined
  85. const assemblyOptions = await getAssemblyOptions(file, options)
  86. // We check if the file is present here again, because it could had been
  87. // removed during the await, e.g. if the user hit cancel while we were
  88. // waiting for the options.
  89. if (file == null) return undefined
  90. assemblyOptions.fields = getFields(file, assemblyOptions)
  91. return {
  92. fileIDs: [file.id],
  93. options: assemblyOptions,
  94. }
  95. }),
  96. ).then(dedupe)
  97. }
  98. if (options.alwaysRunAssembly) {
  99. // No files, just generate one Assembly
  100. const assemblyOptions = await getAssemblyOptions(null, options)
  101. return [
  102. {
  103. fileIDs: this.files.map((file) => file.id),
  104. options: assemblyOptions,
  105. },
  106. ]
  107. }
  108. // If there are no files and we do not `alwaysRunAssembly`,
  109. // don't do anything.
  110. return []
  111. }
  112. }
  113. export default AssemblyOptions
  114. export { validateParams }