getCheckedFilesWithPaths.ts 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. /* eslint-disable no-param-reassign */
  2. import type {
  3. PartialTree,
  4. PartialTreeFile,
  5. PartialTreeFolderNode,
  6. PartialTreeId,
  7. } from '@uppy/core/lib/Uppy'
  8. import type { CompanionFile } from '@uppy/utils/lib/CompanionFile'
  9. export interface Cache {
  10. [key: string]: (PartialTreeFile | PartialTreeFolderNode)[]
  11. }
  12. const getPath = (
  13. partialTree: PartialTree,
  14. id: PartialTreeId,
  15. cache: Cache,
  16. ): (PartialTreeFile | PartialTreeFolderNode)[] => {
  17. const sId = id === null ? 'null' : id
  18. if (cache[sId]) return cache[sId]
  19. const file = partialTree.find((f) => f.id === id)!
  20. if (file.type === 'root') return []
  21. const meAndParentPath = [...getPath(partialTree, file.parentId, cache), file]
  22. cache[sId] = meAndParentPath
  23. return meAndParentPath
  24. }
  25. // See "Uppy file properties" documentation for `.absolutePath` and `.relativePath`
  26. // (https://uppy.io/docs/uppy/#working-with-uppy-files)
  27. const getCheckedFilesWithPaths = (
  28. partialTree: PartialTree,
  29. ): CompanionFile[] => {
  30. // Equivalent to `const cache = {}`, but makes keys such as 'hasOwnProperty' safe too
  31. const cache: Cache = Object.create(null)
  32. // We're only interested in injecting paths into 'checked' files
  33. const checkedFiles = partialTree.filter(
  34. (item) => item.type === 'file' && item.status === 'checked',
  35. ) as PartialTreeFile[]
  36. const companionFilesWithInjectedPaths = checkedFiles.map((file) => {
  37. const absFolders: (PartialTreeFile | PartialTreeFolderNode)[] = getPath(
  38. partialTree,
  39. file.id,
  40. cache,
  41. )
  42. const firstCheckedFolderIndex = absFolders.findIndex(
  43. (i) => i.type === 'folder' && i.status === 'checked',
  44. )
  45. const relFolders = absFolders.slice(firstCheckedFolderIndex)
  46. const absDirPath = `/${absFolders.map((i) => i.data.name).join('/')}`
  47. const relDirPath =
  48. relFolders.length === 1 ?
  49. // Must return `undefined` (which later turns into `null` in `.getTagFile()`)
  50. // (https://github.com/transloadit/uppy/pull/4537#issuecomment-1629136652)
  51. undefined
  52. : relFolders.map((i) => i.data.name).join('/')
  53. return {
  54. ...file.data,
  55. absDirPath,
  56. relDirPath,
  57. }
  58. })
  59. return companionFilesWithInjectedPaths
  60. }
  61. export default getCheckedFilesWithPaths