@maas/payload-plugin-media-cloud 0.0.30 → 0.0.32

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 (157) hide show
  1. package/dist/adapter/handleDelete.d.mts +3 -3
  2. package/dist/adapter/handleDelete.mjs +6 -6
  3. package/dist/adapter/handleDelete.mjs.map +1 -1
  4. package/dist/adapter/staticHandler.d.mts +5 -3
  5. package/dist/adapter/staticHandler.mjs +8 -7
  6. package/dist/adapter/staticHandler.mjs.map +1 -1
  7. package/dist/adapter/storageAdapter.d.mts +3 -3
  8. package/dist/adapter/storageAdapter.mjs +4 -4
  9. package/dist/adapter/storageAdapter.mjs.map +1 -1
  10. package/dist/collectionHooks/afterChange.d.mts +7 -0
  11. package/dist/collectionHooks/afterChange.mjs +39 -0
  12. package/dist/collectionHooks/afterChange.mjs.map +1 -0
  13. package/dist/collectionHooks/beforeChange.d.mts +7 -0
  14. package/dist/collectionHooks/beforeChange.mjs +33 -0
  15. package/dist/collectionHooks/beforeChange.mjs.map +1 -0
  16. package/dist/collections/mediaCollection.d.mts +3 -2
  17. package/dist/collections/mediaCollection.mjs +46 -198
  18. package/dist/collections/mediaCollection.mjs.map +1 -1
  19. package/dist/components/folderFileCard/folderFileCard.d.mts +13 -0
  20. package/dist/components/folderFileCard/folderFileCard.mjs +30 -0
  21. package/dist/components/folderFileCard/folderFileCard.mjs.map +1 -0
  22. package/dist/components/gridContext/gridContext.d.mts +51 -0
  23. package/dist/components/gridContext/gridContext.mjs +227 -0
  24. package/dist/components/gridContext/gridContext.mjs.map +1 -0
  25. package/dist/components/gridView/gridView.css +50 -0
  26. package/dist/components/gridView/gridView.d.mts +16 -0
  27. package/dist/components/gridView/gridView.mjs +124 -0
  28. package/dist/components/gridView/gridView.mjs.map +1 -0
  29. package/dist/components/gridView/index.d.mts +2 -0
  30. package/dist/components/gridView/index.mjs +3 -0
  31. package/dist/components/index.d.mts +9 -7
  32. package/dist/components/index.mjs +5 -4
  33. package/dist/components/itemCardGrid/itemCardGrid.css +12 -0
  34. package/dist/components/itemCardGrid/itemCardGrid.d.mts +18 -0
  35. package/dist/components/itemCardGrid/itemCardGrid.mjs +22 -0
  36. package/dist/components/itemCardGrid/itemCardGrid.mjs.map +1 -0
  37. package/dist/components/muxPreview/index.d.mts +2 -0
  38. package/dist/components/muxPreview/index.mjs +3 -0
  39. package/dist/components/{mux-preview/mux-preview.d.mts → muxPreview/muxPreview.d.mts} +2 -2
  40. package/dist/components/{mux-preview/mux-preview.mjs → muxPreview/muxPreview.mjs} +2 -2
  41. package/dist/components/muxPreview/muxPreview.mjs.map +1 -0
  42. package/dist/components/uploadHandler/index.d.mts +2 -0
  43. package/dist/components/uploadHandler/index.mjs +3 -0
  44. package/dist/components/uploadHandler/uploadHandler.d.mts +20 -0
  45. package/dist/components/{upload-handler/upload-handler.mjs → uploadHandler/uploadHandler.mjs} +82 -52
  46. package/dist/components/uploadHandler/uploadHandler.mjs.map +1 -0
  47. package/dist/components/uploadManager/index.d.mts +2 -0
  48. package/dist/components/uploadManager/index.mjs +3 -0
  49. package/dist/components/{upload-manager/upload-manager.d.mts → uploadManager/uploadManager.d.mts} +3 -3
  50. package/dist/components/{upload-manager/upload-manager.mjs → uploadManager/uploadManager.mjs} +3 -3
  51. package/dist/components/uploadManager/uploadManager.mjs.map +1 -0
  52. package/dist/endpoints/fileExistsHandler.d.mts +12 -0
  53. package/dist/endpoints/{tusFileExistsHandler.mjs → fileExistsHandler.mjs} +7 -7
  54. package/dist/endpoints/fileExistsHandler.mjs.map +1 -0
  55. package/dist/endpoints/muxAssetHandler.d.mts +1 -0
  56. package/dist/endpoints/muxAssetHandler.mjs +3 -3
  57. package/dist/endpoints/muxAssetHandler.mjs.map +1 -1
  58. package/dist/endpoints/muxWebhookHandler.d.mts +1 -0
  59. package/dist/endpoints/muxWebhookHandler.mjs +6 -5
  60. package/dist/endpoints/muxWebhookHandler.mjs.map +1 -1
  61. package/dist/endpoints/tusCleanupHandler.d.mts +3 -2
  62. package/dist/endpoints/tusCleanupHandler.mjs +4 -4
  63. package/dist/endpoints/tusCleanupHandler.mjs.map +1 -1
  64. package/dist/endpoints/tusFolderHandler.d.mts +12 -0
  65. package/dist/endpoints/tusFolderHandler.mjs +39 -0
  66. package/dist/endpoints/tusFolderHandler.mjs.map +1 -0
  67. package/dist/endpoints/tusPostProcessorHandler.d.mts +3 -2
  68. package/dist/endpoints/tusPostProcessorHandler.mjs +6 -5
  69. package/dist/endpoints/tusPostProcessorHandler.mjs.map +1 -1
  70. package/dist/fields/alt.d.mts +7 -0
  71. package/dist/fields/alt.mjs +10 -0
  72. package/dist/fields/alt.mjs.map +1 -0
  73. package/dist/fields/filename.d.mts +7 -0
  74. package/dist/fields/filename.mjs +14 -0
  75. package/dist/fields/filename.mjs.map +1 -0
  76. package/dist/fields/height.d.mts +7 -0
  77. package/dist/fields/height.mjs +15 -0
  78. package/dist/fields/height.mjs.map +1 -0
  79. package/dist/fields/mux.d.mts +7 -0
  80. package/dist/fields/mux.mjs +149 -0
  81. package/dist/fields/mux.mjs.map +1 -0
  82. package/dist/fields/path.d.mts +7 -0
  83. package/dist/fields/path.mjs +14 -0
  84. package/dist/fields/path.mjs.map +1 -0
  85. package/dist/fields/storage.d.mts +7 -0
  86. package/dist/fields/storage.mjs +18 -0
  87. package/dist/fields/storage.mjs.map +1 -0
  88. package/dist/fields/thumbnail.d.mts +7 -0
  89. package/dist/fields/thumbnail.mjs +17 -0
  90. package/dist/fields/thumbnail.mjs.map +1 -0
  91. package/dist/fields/width.d.mts +7 -0
  92. package/dist/fields/width.mjs +15 -0
  93. package/dist/fields/width.mjs.map +1 -0
  94. package/dist/hooks/useErrorHandler.d.mts +1 -1
  95. package/dist/hooks/useErrorHandler.mjs +4 -2
  96. package/dist/hooks/useErrorHandler.mjs.map +1 -1
  97. package/dist/plugin.d.mts +5 -4
  98. package/dist/plugin.mjs +53 -29
  99. package/dist/plugin.mjs.map +1 -1
  100. package/dist/tus/stores/s3/{expiration-manager.d.mts → expirationManager.d.mts} +4 -3
  101. package/dist/tus/stores/s3/{expiration-manager.mjs → expirationManager.mjs} +6 -3
  102. package/dist/tus/stores/s3/expirationManager.mjs.map +1 -0
  103. package/dist/tus/stores/s3/{file-operations.d.mts → fileOperations.d.mts} +2 -2
  104. package/dist/tus/stores/s3/{file-operations.mjs → fileOperations.mjs} +2 -2
  105. package/dist/tus/stores/s3/fileOperations.mjs.map +1 -0
  106. package/dist/tus/stores/s3/index.d.mts +1 -1
  107. package/dist/tus/stores/s3/index.mjs +20 -9
  108. package/dist/tus/stores/s3/index.mjs.map +1 -1
  109. package/dist/tus/stores/s3/{metadata-manager.d.mts → metadataManager.d.mts} +4 -2
  110. package/dist/tus/stores/s3/{metadata-manager.mjs → metadataManager.mjs} +6 -5
  111. package/dist/tus/stores/s3/metadataManager.mjs.map +1 -0
  112. package/dist/tus/stores/s3/{parts-manager.d.mts → partsManager.d.mts} +4 -4
  113. package/dist/tus/stores/s3/{parts-manager.mjs → partsManager.mjs} +67 -29
  114. package/dist/tus/stores/s3/partsManager.mjs.map +1 -0
  115. package/dist/tus/stores/s3/{s3-store.d.mts → s3Store.d.mts} +38 -32
  116. package/dist/tus/stores/s3/{s3-store.mjs → s3Store.mjs} +102 -57
  117. package/dist/tus/stores/s3/s3Store.mjs.map +1 -0
  118. package/dist/types/errors.d.mts +32 -0
  119. package/dist/types/errors.mjs +32 -0
  120. package/dist/types/errors.mjs.map +1 -1
  121. package/dist/types/index.d.mts +42 -4
  122. package/dist/utils/buildS3Path.d.mts +10 -0
  123. package/dist/utils/buildS3Path.mjs +16 -0
  124. package/dist/utils/buildS3Path.mjs.map +1 -0
  125. package/dist/utils/buildThumbnailURL.d.mts +14 -0
  126. package/dist/utils/buildThumbnailURL.mjs +10 -0
  127. package/dist/utils/buildThumbnailURL.mjs.map +1 -0
  128. package/dist/utils/defaultOptions.d.mts +7 -0
  129. package/dist/utils/defaultOptions.mjs +12 -0
  130. package/dist/utils/defaultOptions.mjs.map +1 -0
  131. package/dist/utils/file.d.mts +16 -2
  132. package/dist/utils/file.mjs +58 -6
  133. package/dist/utils/file.mjs.map +1 -1
  134. package/dist/utils/mux.mjs +19 -8
  135. package/dist/utils/mux.mjs.map +1 -1
  136. package/dist/utils/tus.d.mts +9 -6
  137. package/dist/utils/tus.mjs +31 -11
  138. package/dist/utils/tus.mjs.map +1 -1
  139. package/package.json +9 -4
  140. package/dist/components/mux-preview/index.d.mts +0 -2
  141. package/dist/components/mux-preview/index.mjs +0 -3
  142. package/dist/components/mux-preview/mux-preview.mjs.map +0 -1
  143. package/dist/components/upload-handler/index.d.mts +0 -2
  144. package/dist/components/upload-handler/index.mjs +0 -3
  145. package/dist/components/upload-handler/upload-handler.d.mts +0 -22
  146. package/dist/components/upload-handler/upload-handler.mjs.map +0 -1
  147. package/dist/components/upload-manager/index.d.mts +0 -2
  148. package/dist/components/upload-manager/index.mjs +0 -3
  149. package/dist/components/upload-manager/upload-manager.mjs.map +0 -1
  150. package/dist/endpoints/tusFileExistsHandler.d.mts +0 -11
  151. package/dist/endpoints/tusFileExistsHandler.mjs.map +0 -1
  152. package/dist/tus/stores/s3/expiration-manager.mjs.map +0 -1
  153. package/dist/tus/stores/s3/file-operations.mjs.map +0 -1
  154. package/dist/tus/stores/s3/metadata-manager.mjs.map +0 -1
  155. package/dist/tus/stores/s3/parts-manager.mjs.map +0 -1
  156. package/dist/tus/stores/s3/s3-store.mjs.map +0 -1
  157. /package/dist/components/{upload-manager/upload-manager.css → uploadManager/uploadManager.css} +0 -0
@@ -1,7 +1,9 @@
1
- import { MuxPreview } from "./mux-preview/mux-preview.mjs";
2
- import "./mux-preview/index.mjs";
3
- import { UploadHandler } from "./upload-handler/upload-handler.mjs";
4
- import "./upload-handler/index.mjs";
5
- import { UploadManagerProvider, useUploadManagerContext } from "./upload-manager/upload-manager.mjs";
6
- import "./upload-manager/index.mjs";
7
- export { MuxPreview, UploadHandler, UploadManagerProvider, useUploadManagerContext };
1
+ import { GridView } from "./gridView/gridView.mjs";
2
+ import "./gridView/index.mjs";
3
+ import { MuxPreview } from "./muxPreview/muxPreview.mjs";
4
+ import "./muxPreview/index.mjs";
5
+ import { UploadHandler } from "./uploadHandler/uploadHandler.mjs";
6
+ import "./uploadHandler/index.mjs";
7
+ import { UploadManagerProvider, useUploadManagerContext } from "./uploadManager/uploadManager.mjs";
8
+ import "./uploadManager/index.mjs";
9
+ export { GridView, MuxPreview, UploadHandler, UploadManagerProvider, useUploadManagerContext };
@@ -1,5 +1,6 @@
1
- import { MuxPreview } from "./mux-preview/mux-preview.mjs";
2
- import { UploadHandler } from "./upload-handler/upload-handler.mjs";
3
- import { UploadManagerProvider, useUploadManagerContext } from "./upload-manager/upload-manager.mjs";
1
+ import { GridView } from "./gridView/gridView.mjs";
2
+ import { MuxPreview } from "./muxPreview/muxPreview.mjs";
3
+ import { UploadHandler } from "./uploadHandler/uploadHandler.mjs";
4
+ import { UploadManagerProvider, useUploadManagerContext } from "./uploadManager/uploadManager.mjs";
4
5
 
5
- export { MuxPreview, UploadHandler, UploadManagerProvider, useUploadManagerContext };
6
+ export { GridView, MuxPreview, UploadHandler, UploadManagerProvider, useUploadManagerContext };
@@ -0,0 +1,12 @@
1
+ .item-card-grid {
2
+ --gap: var(--base);
3
+ gap: var(--gap);
4
+ display: grid;
5
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
6
+ margin-bottom: var(--base);
7
+
8
+ & .item-card-grid__title {
9
+ color: var(--theme-elevation-400);
10
+ margin-bottom: calc(var(--base) / 2);
11
+ }
12
+ }
@@ -0,0 +1,18 @@
1
+ import { MappedDocument } from "../gridView/gridView.mjs";
2
+ import React from "react";
3
+ import "./itemCardGrid.css";
4
+
5
+ //#region src/components/itemCardGrid/itemCardGrid.d.ts
6
+ type ItemCardGridProps = {
7
+ items: MappedDocument[];
8
+ title?: string;
9
+ adminRoute: string;
10
+ collectionSlug: string;
11
+ };
12
+ declare function ItemCardGrid({
13
+ items,
14
+ title
15
+ }: ItemCardGridProps): React.JSX.Element;
16
+ //#endregion
17
+ export { ItemCardGrid };
18
+ //# sourceMappingURL=itemCardGrid.d.mts.map
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import { ContextFolderFileCard } from "../folderFileCard/folderFileCard.mjs";
4
+ import React from "react";
5
+ import "./itemCardGrid.css";
6
+
7
+ //#region src/components/itemCardGrid/itemCardGrid.tsx
8
+ function ItemCardGrid({ items, title }) {
9
+ const baseClass = "item-card-grid";
10
+ return <>
11
+ {title && <p className={`${baseClass}__title`}>{title}</p>}
12
+ <div className={baseClass}>
13
+ {!items || items?.length === 0 ? null : items.map((item) => {
14
+ return <ContextFolderFileCard key={item.id} index={items.indexOf(item)} item={item} className={`${baseClass}__item`} />;
15
+ })}
16
+ </div>
17
+ </>;
18
+ }
19
+
20
+ //#endregion
21
+ export { ItemCardGrid };
22
+ //# sourceMappingURL=itemCardGrid.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"itemCardGrid.mjs","names":[],"sources":["../../../src/components/itemCardGrid/itemCardGrid.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport { ContextFolderFileCard } from '../folderFileCard/folderFileCard'\n\nimport type { MappedDocument } from '../gridView/gridView'\n\nimport './itemCardGrid.css'\n\ntype ItemCardGridProps = {\n items: MappedDocument[]\n title?: string\n adminRoute: string\n collectionSlug: string\n}\n\nexport function ItemCardGrid({ items, title }: ItemCardGridProps) {\n const baseClass = 'item-card-grid'\n\n return (\n <>\n {title && <p className={`${baseClass}__title`}>{title}</p>}\n <div className={baseClass}>\n {!items || items?.length === 0\n ? null\n : items.map((item) => {\n return (\n <ContextFolderFileCard\n key={item.id}\n index={items.indexOf(item)}\n item={item}\n className={`${baseClass}__item`}\n />\n )\n })}\n </div>\n </>\n )\n}\n"],"mappings":";;;;;;;AAgBA,SAAgB,aAAa,EAAE,OAAO,SAA4B;CAChE,MAAM,YAAY;AAElB,QACE,EAAE;OACC,SAAS,CAAC,EAAE,WAAW,GAAG,UAAU,WAAW,MAAM,EAAE,GAAG;MAC3D,CAAC,IAAI,WAAW,WAAW;SACxB,CAAC,SAAS,OAAO,WAAW,IACzB,OACA,MAAM,KAAK,SAAS;AAClB,SACE,CAAC,sBACC,KAAK,KAAK,IACV,OAAO,MAAM,QAAQ,KAAK,EAC1B,MAAM,MACN,WAAW,GAAG,UAAU;GAG5B,CAAC;MACT,EAAE,IAAI;IACR"}
@@ -0,0 +1,2 @@
1
+ import { MuxPreview } from "./muxPreview.mjs";
2
+ export { MuxPreview };
@@ -0,0 +1,3 @@
1
+ import { MuxPreview } from "./muxPreview.mjs";
2
+
3
+ export { MuxPreview };
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import { UIFieldClientProps } from "payload";
3
3
 
4
- //#region src/components/mux-preview/mux-preview.d.ts
4
+ //#region src/components/muxPreview/muxPreview.d.ts
5
5
 
6
6
  /**
7
7
  * React component for previewing Mux video assets
@@ -11,4 +11,4 @@ import { UIFieldClientProps } from "payload";
11
11
  declare function MuxPreview(props: UIFieldClientProps): React.JSX.Element | null;
12
12
  //#endregion
13
13
  export { MuxPreview };
14
- //# sourceMappingURL=mux-preview.d.mts.map
14
+ //# sourceMappingURL=muxPreview.d.mts.map
@@ -3,7 +3,7 @@
3
3
  import { useEffect, useState } from "react";
4
4
  import MuxPlayer from "@mux/mux-player-react";
5
5
 
6
- //#region src/components/mux-preview/mux-preview.tsx
6
+ //#region src/components/muxPreview/muxPreview.tsx
7
7
  /**
8
8
  * React component for previewing Mux video assets
9
9
  * @param props - The UI field client props containing field data
@@ -26,4 +26,4 @@ function MuxPreview(props) {
26
26
 
27
27
  //#endregion
28
28
  export { MuxPreview };
29
- //# sourceMappingURL=mux-preview.mjs.map
29
+ //# sourceMappingURL=muxPreview.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxPreview.mjs","names":[],"sources":["../../../src/components/muxPreview/muxPreview.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport MuxPlayer from '@mux/mux-player-react'\n\nimport type React from 'react'\nimport type { UIFieldClientProps } from 'payload'\n\n/**\n * React component for previewing Mux video assets\n * @param props - The UI field client props containing field data\n * @returns JSX element for Mux video preview\n */\nexport function MuxPreview(props: UIFieldClientProps) {\n const [playbackId, setPlaybackId] = useState<string | null>(null)\n const [isClient, setIsClient] = useState(false)\n\n // Ensure we’re on the client side\n useEffect(() => {\n setIsClient(true)\n }, [])\n\n useEffect(() => {\n if (!isClient) {\n return\n }\n\n // Get collection from schemaPath and ID from URL\n const collection = props.schemaPath?.split('.')[0] // \"media.muxPlayer\" -> \"media\"\n const docId = window.location.pathname.split('/').pop() // Get last part of URL\n\n if (collection && docId && docId !== 'create' && docId !== 'admin') {\n fetch(`/api/${collection}/${docId}`)\n .then((res) => res.json())\n .then((data) => setPlaybackId(data.mux?.playbackId || null))\n .catch(() => setPlaybackId(null))\n }\n }, [props.schemaPath, isClient])\n\n // Only render on client with playbackId\n return isClient && playbackId ? (\n <MuxPlayer\n playbackId={playbackId}\n streamType=\"on-demand\"\n disableTracking={true}\n style={{ height: '60vh' }}\n nohotkeys={true}\n preload=\"metadata\"\n />\n ) : null\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,WAAW,OAA2B;CACpD,MAAM,CAAC,YAAY,iBAAiB,SAAwB,KAAK;CACjE,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;AAG/C,iBAAgB;AACd,cAAY,KAAK;IAChB,EAAE,CAAC;AAEN,iBAAgB;AACd,MAAI,CAAC,SACH;EAIF,MAAM,aAAa,MAAM,YAAY,MAAM,IAAI,CAAC;EAChD,MAAM,QAAQ,OAAO,SAAS,SAAS,MAAM,IAAI,CAAC,KAAK;AAEvD,MAAI,cAAc,SAAS,UAAU,YAAY,UAAU,QACzD,OAAM,QAAQ,WAAW,GAAG,QAAQ,CACjC,MAAM,QAAQ,IAAI,MAAM,CAAC,CACzB,MAAM,SAAS,cAAc,KAAK,KAAK,cAAc,KAAK,CAAC,CAC3D,YAAY,cAAc,KAAK,CAAC;IAEpC,CAAC,MAAM,YAAY,SAAS,CAAC;AAGhC,QAAO,YAAY,aACjB,CAAC,UACC,YAAY,YACZ,uBACA,iBAAiB,MACjB,OAAO,EAAE,QAAQ,QAAQ,EACzB,WAAW,MACX,wBAEA"}
@@ -0,0 +1,2 @@
1
+ import { UploadHandler } from "./uploadHandler.mjs";
2
+ export { UploadHandler };
@@ -0,0 +1,3 @@
1
+ import { UploadHandler } from "./uploadHandler.mjs";
2
+
3
+ export { UploadHandler };
@@ -0,0 +1,20 @@
1
+ import { MediaCloudPluginOptions } from "../../types/index.mjs";
2
+ import * as react0 from "react";
3
+ import { ReactNode } from "react";
4
+ import { UploadCollectionSlug } from "payload";
5
+
6
+ //#region src/components/uploadHandler/uploadHandler.d.ts
7
+ type ClientUploadHandlerProps<T extends Record<string, unknown>> = {
8
+ children: ReactNode;
9
+ collectionSlug: UploadCollectionSlug;
10
+ enabled?: boolean;
11
+ extra: T;
12
+ prefix?: string;
13
+ serverHandlerPath: `/${string}`;
14
+ };
15
+ declare function UploadHandler(props: ClientUploadHandlerProps<{
16
+ pluginOptions: MediaCloudPluginOptions;
17
+ }>): react0.JSX.Element;
18
+ //#endregion
19
+ export { UploadHandler };
20
+ //# sourceMappingURL=uploadHandler.d.mts.map
@@ -1,17 +1,15 @@
1
1
  'use client';
2
2
 
3
3
  import { MediaCloudErrors, MediaCloudLogs } from "../../types/errors.mjs";
4
+ import { useMagicError } from "../../error-handler/dist/index.mjs";
4
5
  import { useErrorHandler } from "../../hooks/useErrorHandler.mjs";
5
- import { generateUniqueFilename, getFileType, isVideo } from "../../utils/file.mjs";
6
+ import { generateUniqueFilename, getMimeType, isVideo, sanitizeFilename } from "../../utils/file.mjs";
6
7
  import { useMediaCloudEmitter } from "../../hooks/useMediaCloudEmitter.mjs";
7
8
  import * as upchunk from "@mux/upchunk";
8
9
  import * as tus from "tus-js-client";
9
- import { toast } from "@payloadcms/ui";
10
10
  import { createClientUploadHandler } from "@payloadcms/plugin-cloud-storage/client";
11
11
 
12
- //#region src/components/upload-handler/upload-handler.tsx
13
- const { logError, throwError } = useErrorHandler();
14
- const emitter = useMediaCloudEmitter();
12
+ //#region src/components/uploadHandler/uploadHandler.tsx
15
13
  const MUX_CHUNK_SIZE = 30720;
16
14
  const TUS_CHUNK_SIZE = 1024 * 1024;
17
15
  const TUS_RETRY_DELAYS = [
@@ -20,6 +18,9 @@ const TUS_RETRY_DELAYS = [
20
18
  2e3,
21
19
  5e3
22
20
  ];
21
+ const magicError = useMagicError({ prefix: "PLUGIN-MEDIA-CLOUD" });
22
+ const { throwError } = magicError;
23
+ const emitter = useMediaCloudEmitter();
23
24
  /**
24
25
  * Handles Mux video upload with progress tracking
25
26
  * @param args - The upload arguments including file, server URL, and callbacks
@@ -27,9 +28,10 @@ const TUS_RETRY_DELAYS = [
27
28
  */
28
29
  async function muxUpload(args) {
29
30
  const { file, serverURL, apiRoute, mimeType } = args;
31
+ const endpoint = `${serverURL}${apiRoute}`;
30
32
  const filename = file.name;
31
33
  try {
32
- const { url, uploadId } = await (await fetch(`${serverURL}${apiRoute}/mux/upload`, {
34
+ const { url, uploadId } = await (await fetch(`${endpoint}/mux/upload`, {
33
35
  body: JSON.stringify({
34
36
  filename,
35
37
  mimeType
@@ -47,12 +49,11 @@ async function muxUpload(args) {
47
49
  filename,
48
50
  uploadId,
49
51
  polling: false,
50
- pollingUrl: `${serverURL}${apiRoute}/mux/asset`
52
+ pollingUrl: `${endpoint}/mux/asset`
51
53
  });
52
54
  uploader.on("error", function() {
53
- logError(MediaCloudErrors.MUX_UPLOAD_ERROR.message);
54
- toast.error("Video upload failed");
55
55
  emitter.emit("removeUpload", { uploadId });
56
+ throwError(MediaCloudErrors.MUX_UPLOAD_ERROR);
56
57
  });
57
58
  uploader.on("progress", function(progress) {
58
59
  emitter.emit("updateUpload", {
@@ -69,9 +70,12 @@ async function muxUpload(args) {
69
70
  mimeType,
70
71
  storage: "mux"
71
72
  };
72
- } catch (_error) {
73
- logError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR.message);
74
- toast.error("Video upload failed");
73
+ } catch {
74
+ throwError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR);
75
+ emitter.emit("uploadError", {
76
+ filename,
77
+ error: "Video upload failed"
78
+ });
75
79
  return null;
76
80
  }
77
81
  }
@@ -81,10 +85,11 @@ async function muxUpload(args) {
81
85
  * @returns Promise that resolves to upload result or null if upload fails
82
86
  */
83
87
  async function tusUpload(args) {
84
- const { apiRoute, serverURL, file, mimeType } = args;
88
+ const { apiRoute, serverURL, file, prefix = "", mimeType } = args;
85
89
  const filename = file.name;
86
90
  const filetype = file.type;
87
91
  const filesize = file.size.toString();
92
+ const endpoint = `${serverURL}${apiRoute}/uploads`;
88
93
  Object.keys(localStorage).filter((key) => key.startsWith("tus::")).forEach((key) => localStorage.removeItem(key));
89
94
  let uploadUrlAvailable = false;
90
95
  let eventListenerAdded = false;
@@ -94,11 +99,11 @@ async function tusUpload(args) {
94
99
  }
95
100
  function onPageUnload() {
96
101
  window.removeEventListener("unload", onPageUnload);
97
- navigator.sendBeacon(`${serverURL}${apiRoute}/uploads/cleanup`, JSON.stringify({ filename }));
102
+ navigator.sendBeacon(`${endpoint}/cleanup`, JSON.stringify({ filename }));
98
103
  }
99
104
  return new Promise((resolve) => {
100
105
  new tus.Upload(file, {
101
- endpoint: `${serverURL}${apiRoute}/uploads`,
106
+ endpoint,
102
107
  retryDelays: TUS_RETRY_DELAYS,
103
108
  chunkSize: TUS_CHUNK_SIZE,
104
109
  storeFingerprintForResuming: false,
@@ -106,16 +111,22 @@ async function tusUpload(args) {
106
111
  filetype,
107
112
  filesize,
108
113
  filename,
114
+ prefix,
109
115
  contentType: filetype,
110
116
  contentLength: filesize,
111
117
  contentDisposition: "inline"
112
118
  },
113
119
  onError(error) {
114
- logError(MediaCloudErrors.TUS_UPLOAD_ERROR.message);
115
- logError(error.message);
116
- navigator.sendBeacon(`${serverURL}${apiRoute}/uploads/cleanup`, JSON.stringify({ filename }));
120
+ navigator.sendBeacon(`${endpoint}/cleanup`, JSON.stringify({ filename }));
121
+ emitter.emit("uploadError", {
122
+ filename,
123
+ error: error.message
124
+ });
117
125
  emitter.emit("removeUpload", { filename });
118
- toast.error("File upload failed");
126
+ throwError({
127
+ ...MediaCloudErrors.TUS_UPLOAD_ERROR,
128
+ cause: error
129
+ });
119
130
  resolve(null);
120
131
  },
121
132
  onBeforeRequest() {
@@ -132,11 +143,12 @@ async function tusUpload(args) {
132
143
  progress: percentage
133
144
  });
134
145
  },
135
- onSuccess() {
146
+ async onSuccess() {
136
147
  window.removeEventListener("beforeunload", onBeforeUnload);
137
148
  window.removeEventListener("unload", onPageUnload);
138
149
  emitter.emit("uploadComplete", { filename });
139
- fetch(`${serverURL}${apiRoute}/uploads/${filename}/process`);
150
+ await fetch(`${endpoint}/${filename}/process`);
151
+ await fetch(`${endpoint}/${filename}/folder`);
140
152
  },
141
153
  onUploadUrlAvailable: async function() {
142
154
  if (uploadUrlAvailable) return;
@@ -152,42 +164,60 @@ async function tusUpload(args) {
152
164
  });
153
165
  }
154
166
  const { log } = useErrorHandler();
155
- const UploadHandler = createClientUploadHandler({ handler: async function(args) {
156
- const { serverURL, apiRoute, file, updateFilename } = args;
157
- try {
158
- const mimeType = await getFileType(file) || file.type || "application/octet-stream";
159
- if (!mimeType) {
160
- throwError(MediaCloudErrors.FILE_TYPE_UNKNOWN);
167
+ function UploadHandler(props) {
168
+ return createClientUploadHandler({ handler: async function(args) {
169
+ const { serverURL, apiRoute, file, prefix, updateFilename, extra } = args;
170
+ const { pluginOptions } = extra;
171
+ const mimeType = await getMimeType(file);
172
+ magicError.assert(mimeType, MediaCloudErrors.FILE_TYPE_UNKNOWN);
173
+ if (!(pluginOptions.limits?.mimeTypes ?? []).some((allowed) => allowed.endsWith("/*") ? mimeType?.startsWith(allowed.replace("/*", "/")) : mimeType === allowed)) {
174
+ throwError(MediaCloudErrors.FILE_TYPE_NOT_ALLOWED);
175
+ return null;
176
+ }
177
+ if (file.size > (pluginOptions.limits?.fileSize ?? Infinity)) {
178
+ throwError(MediaCloudErrors.FILE_SIZE_EXCEEDED);
161
179
  return null;
162
180
  }
163
- const isVideoFile = await isVideo(file);
164
181
  let mappedFile = file;
165
- if (!isVideoFile) try {
166
- if ((await fetch(`${serverURL}${apiRoute}/uploads/${file.name}/exists`).catch(() => {}))?.status === 200) {
167
- log(MediaCloudLogs.S3_STORE_FILE_FOUND);
168
- const newFilename = generateUniqueFilename(file.name);
169
- mappedFile = new File([file], newFilename, { type: file.type });
170
- await updateFilename(newFilename);
182
+ try {
183
+ const endpoint = `${serverURL}${apiRoute}/uploads`;
184
+ const response = await fetch(`${endpoint}/${file.name}/exists`);
185
+ if (response?.status === 200) log(MediaCloudLogs.S3_STORE_FILE_FOUND);
186
+ const newFilename = response?.status === 200 ? generateUniqueFilename(file.name) : sanitizeFilename(file.name);
187
+ mappedFile = new File([file], newFilename, { type: file.type });
188
+ await updateFilename(newFilename);
189
+ } catch (error) {
190
+ throwError({
191
+ ...MediaCloudErrors.NAMING_FUNCTION_ERROR,
192
+ cause: error
193
+ });
194
+ return null;
195
+ }
196
+ try {
197
+ const uploadArgs = {
198
+ file: mappedFile,
199
+ serverURL,
200
+ apiRoute,
201
+ mimeType,
202
+ prefix
203
+ };
204
+ const storageForMimeType = pluginOptions.storage && Object.prototype.hasOwnProperty.call(pluginOptions.storage, mimeType) ? pluginOptions.storage[mimeType] : void 0;
205
+ const isVideoFile = await isVideo(file);
206
+ const storeOnMux = pluginOptions.storage?.["video/*"] === "mux" || storageForMimeType === "mux";
207
+ switch (true) {
208
+ case storeOnMux && isVideoFile: return await muxUpload(uploadArgs);
209
+ default: return await tusUpload(uploadArgs);
171
210
  }
172
- } catch (_error) {
173
- logError(MediaCloudErrors.NAMING_FUNCTION_ERROR.message);
211
+ } catch (error) {
212
+ throwError({
213
+ ...MediaCloudErrors.UPLOAD_HANDLER_ERROR,
214
+ cause: error
215
+ });
216
+ return null;
174
217
  }
175
- const uploadArgs = {
176
- file: mappedFile,
177
- serverURL,
178
- apiRoute,
179
- mimeType
180
- };
181
- if (isVideoFile) return await muxUpload(uploadArgs);
182
- else return await tusUpload(uploadArgs);
183
- } catch (error) {
184
- console.error("[PLUGIN-MEDIA-CLOUD] Upload handler detailed error:", error);
185
- logError(MediaCloudErrors.UPLOAD_HANDLER_ERROR.message);
186
- toast.error(`Upload failed: ${error instanceof Error ? error.message : "Unknown error"}`);
187
- return null;
188
- }
189
- } });
218
+ } })(props);
219
+ }
190
220
 
191
221
  //#endregion
192
222
  export { UploadHandler };
193
- //# sourceMappingURL=upload-handler.mjs.map
223
+ //# sourceMappingURL=uploadHandler.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadHandler.mjs","names":["magicError: UseMagicErrorReturn","uploadArgs: UploadArgs"],"sources":["../../../src/components/uploadHandler/uploadHandler.tsx"],"sourcesContent":["'use client'\n\nimport * as upchunk from '@mux/upchunk'\nimport * as tus from 'tus-js-client'\n\nimport { createClientUploadHandler } from '@payloadcms/plugin-cloud-storage/client'\n\nimport { MediaCloudErrors, MediaCloudLogs } from '../../types/errors'\nimport { useMediaCloudEmitter } from '../../hooks/useMediaCloudEmitter'\nimport { useErrorHandler } from '../../hooks/useErrorHandler'\nimport {\n isVideo,\n getMimeType,\n generateUniqueFilename,\n sanitizeFilename,\n} from '../../utils/file'\n\nimport type {\n MediaCloudPluginOptions,\n Storage,\n MimeType,\n} from '../../types/index'\nimport type { ReactNode } from 'react'\nimport type { UploadCollectionSlug } from 'payload'\nimport { useMagicError, UseMagicErrorReturn } from '@maas/error-handler'\n\ninterface UploadArgs {\n serverURL: string\n apiRoute: string\n file: File\n mimeType: MimeType\n prefix?: string\n}\n\ninterface UploadResult {\n storage: Storage\n mimeType: MimeType\n filename: string\n uploadId?: string\n}\n\ninterface MuxCreateUploadResponse {\n url: string\n uploadId: string\n filename: string\n}\n\nconst MUX_CHUNK_SIZE = 30720\nconst TUS_CHUNK_SIZE = 1024 * 1024\nconst TUS_RETRY_DELAYS = [0, 1000, 2000, 5000]\n\nconst magicError: UseMagicErrorReturn = useMagicError({\n prefix: 'PLUGIN-MEDIA-CLOUD',\n})\n\nconst { throwError } = magicError\nconst emitter = useMediaCloudEmitter()\n\n/**\n * Handles Mux video upload with progress tracking\n * @param args - The upload arguments including file, server URL, and callbacks\n * @returns Promise that resolves to upload result or null if upload fails\n */\nasync function muxUpload(args: UploadArgs): Promise<UploadResult | null> {\n const { file, serverURL, apiRoute, mimeType } = args\n\n const endpoint = `${serverURL}${apiRoute}`\n const filename = file.name\n\n try {\n // Request upload URL from Mux\n const response = await fetch(`${endpoint}/mux/upload`, {\n body: JSON.stringify({ filename, mimeType }),\n credentials: 'include',\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n\n const { url, uploadId } = (await response.json()) as MuxCreateUploadResponse\n\n // Create upchunk uploader\n const uploader = await upchunk.createUpload({\n endpoint: url,\n file,\n chunkSize: MUX_CHUNK_SIZE,\n })\n\n // Add upload to tracker\n emitter.emit('addUpload', {\n filename,\n uploadId,\n polling: false,\n pollingUrl: `${endpoint}/mux/asset`,\n })\n\n // Set up event handlers\n uploader.on('error', function () {\n emitter.emit('removeUpload', { uploadId })\n throwError(MediaCloudErrors.MUX_UPLOAD_ERROR)\n })\n\n uploader.on('progress', function (progress) {\n emitter.emit('updateUpload', {\n filename,\n progress: progress.detail,\n })\n })\n\n uploader.on('success', function () {\n emitter.emit('uploadComplete', { filename })\n })\n\n // Update collection entry\n // with filename, uploadId, mimeType, and storage\n return {\n filename,\n uploadId,\n mimeType,\n storage: 'mux',\n }\n } catch {\n throwError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR)\n emitter.emit('uploadError', { filename, error: 'Video upload failed' })\n return null\n }\n}\n\n/**\n * Handles TUS file upload with resumable capabilities\n * @param args - The upload arguments including file, server URL, and callbacks\n * @returns Promise that resolves to upload result or null if upload fails\n */\nasync function tusUpload(args: UploadArgs): Promise<UploadResult | null> {\n const { apiRoute, serverURL, file, prefix = '', mimeType } = args\n\n const filename = file.name\n const filetype = file.type\n const filesize = file.size.toString()\n\n const endpoint = `${serverURL}${apiRoute}/uploads`\n\n // Clear any stale TUS uploads from localStorage\n Object.keys(localStorage)\n .filter((key) => key.startsWith('tus::'))\n .forEach((key) => localStorage.removeItem(key))\n\n // Flag to prevent multiple onUploadUrlAvailable calls\n let uploadUrlAvailable = false\n let eventListenerAdded = false\n\n function onBeforeUnload(e: BeforeUnloadEvent) {\n window.removeEventListener('beforeunload', onBeforeUnload)\n e.preventDefault()\n }\n\n function onPageUnload() {\n window.removeEventListener('unload', onPageUnload)\n navigator.sendBeacon(`${endpoint}/cleanup`, JSON.stringify({ filename }))\n }\n\n return new Promise((resolve) => {\n const upload = new tus.Upload(file, {\n endpoint,\n retryDelays: TUS_RETRY_DELAYS,\n chunkSize: TUS_CHUNK_SIZE,\n storeFingerprintForResuming: false,\n metadata: {\n filetype,\n filesize,\n filename,\n prefix,\n contentType: filetype,\n contentLength: filesize,\n contentDisposition: 'inline',\n },\n onError(error) {\n // Clean up\n navigator.sendBeacon(\n `${endpoint}/cleanup`,\n JSON.stringify({ filename })\n )\n\n // Inform user\n emitter.emit('uploadError', { filename, error: error.message })\n emitter.emit('removeUpload', { filename })\n throwError({ ...MediaCloudErrors.TUS_UPLOAD_ERROR, cause: error })\n resolve(null)\n },\n onBeforeRequest() {\n if (!eventListenerAdded) {\n window.addEventListener('beforeunload', onBeforeUnload)\n window.addEventListener('unload', onPageUnload)\n eventListenerAdded = true\n }\n },\n onProgress: function (bytesUploaded, bytesTotal) {\n const percentage = Math.round((bytesUploaded / bytesTotal) * 100)\n emitter.emit('updateUpload', {\n filename,\n progress: percentage,\n })\n },\n async onSuccess() {\n // Clean up beforeunload listener\n window.removeEventListener('beforeunload', onBeforeUnload)\n window.removeEventListener('unload', onPageUnload)\n\n // Mark upload as complete in UI\n emitter.emit('uploadComplete', { filename })\n\n // Trigger post upload processing\n await fetch(`${endpoint}/${filename}/process`)\n\n // Move file to correct folder\n await fetch(`${endpoint}/${filename}/folder`)\n },\n onUploadUrlAvailable: async function () {\n // Prevent multiple callbacks\n if (uploadUrlAvailable) {\n return\n }\n\n // Update flag\n uploadUrlAvailable = true\n\n // Add upload to UI\n emitter.emit('addUpload', { filename })\n\n // Update collection entry\n // with filename, mimeType, and storage\n resolve({\n filename,\n mimeType,\n storage: 's3',\n })\n },\n })\n\n upload.start()\n })\n}\n\nconst { log } = useErrorHandler()\n\ninterface Extra {\n pluginOptions: MediaCloudPluginOptions\n}\n\ntype ClientUploadHandlerProps<T extends Record<string, unknown>> = {\n children: ReactNode\n collectionSlug: UploadCollectionSlug\n enabled?: boolean\n extra: T\n prefix?: string\n serverHandlerPath: `/${string}`\n}\n\nexport function UploadHandler(\n props: ClientUploadHandlerProps<{ pluginOptions: MediaCloudPluginOptions }>\n) {\n return createClientUploadHandler({\n handler: async function (args) {\n const { serverURL, apiRoute, file, prefix, updateFilename, extra } = args\n const { pluginOptions } = extra as unknown as Extra\n\n // Check mime type\n const mimeType = await getMimeType(file)\n\n magicError.assert(mimeType, MediaCloudErrors.FILE_TYPE_UNKNOWN)\n\n const allowedMimeTypes = pluginOptions.limits?.mimeTypes ?? []\n const mimeTypeMatches = allowedMimeTypes.some((allowed) =>\n allowed.endsWith('/*')\n ? mimeType?.startsWith(allowed.replace('/*', '/'))\n : mimeType === allowed\n )\n\n if (!mimeTypeMatches) {\n throwError(MediaCloudErrors.FILE_TYPE_NOT_ALLOWED)\n return null\n }\n\n // Check file size limit\n if (file.size > (pluginOptions.limits?.fileSize ?? Infinity)) {\n throwError(MediaCloudErrors.FILE_SIZE_EXCEEDED)\n return null\n }\n\n // Clone file\n let mappedFile = file\n\n try {\n // Check if file with same name exists\n const endpoint = `${serverURL}${apiRoute}/uploads`\n const response = await fetch(`${endpoint}/${file.name}/exists`)\n\n if (response?.status === 200) {\n log(MediaCloudLogs.S3_STORE_FILE_FOUND)\n }\n\n // If file exists, generate a cloned file with a unique filename\n // If not, generate a cloned file with a sanitized filename\n const newFilename =\n response?.status === 200\n ? generateUniqueFilename(file.name)\n : sanitizeFilename(file.name)\n\n mappedFile = new File([file], newFilename, {\n type: file.type,\n })\n\n await updateFilename(newFilename)\n } catch (error) {\n throwError({\n ...MediaCloudErrors.NAMING_FUNCTION_ERROR,\n cause: error,\n })\n return null\n }\n\n try {\n const uploadArgs: UploadArgs = {\n file: mappedFile,\n serverURL,\n apiRoute,\n mimeType,\n prefix,\n }\n\n // Check storage mapping for mime type\n type StorageMap = NonNullable<typeof pluginOptions.storage>\n\n const storageForMimeType =\n pluginOptions.storage &&\n Object.prototype.hasOwnProperty.call(pluginOptions.storage, mimeType)\n ? pluginOptions.storage[mimeType as keyof StorageMap]\n : undefined\n\n const isVideoFile = await isVideo(file)\n const storeOnMux =\n pluginOptions.storage?.['video/*'] === 'mux' ||\n storageForMimeType === 'mux'\n\n switch (true) {\n case storeOnMux && isVideoFile:\n return await muxUpload(uploadArgs)\n default:\n return await tusUpload(uploadArgs)\n }\n } catch (error) {\n throwError({ ...MediaCloudErrors.UPLOAD_HANDLER_ERROR, cause: error })\n return null\n }\n },\n })(props)\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { UploadManagerProvider, useUploadManagerContext } from "./uploadManager.mjs";
2
+ export { UploadManagerProvider, useUploadManagerContext };
@@ -0,0 +1,3 @@
1
+ import { UploadManagerProvider, useUploadManagerContext } from "./uploadManager.mjs";
2
+
3
+ export { UploadManagerProvider, useUploadManagerContext };
@@ -1,8 +1,8 @@
1
1
  import { MediaCloudEmitterEvents } from "../../types/index.mjs";
2
2
  import React from "react";
3
- import "./upload-manager.css";
3
+ import "./uploadManager.css";
4
4
 
5
- //#region src/components/upload-manager/upload-manager.d.ts
5
+ //#region src/components/uploadManager/uploadManager.d.ts
6
6
  interface Upload {
7
7
  filename: string;
8
8
  progress: number;
@@ -30,4 +30,4 @@ declare function UploadManagerProvider(args: UploadManagerProviderArgs): React.J
30
30
  declare const useUploadManagerContext: () => UploadManagerContextType;
31
31
  //#endregion
32
32
  export { UploadManagerProvider, useUploadManagerContext };
33
- //# sourceMappingURL=upload-manager.d.mts.map
33
+ //# sourceMappingURL=uploadManager.d.mts.map
@@ -5,9 +5,9 @@ import { useErrorHandler } from "../../hooks/useErrorHandler.mjs";
5
5
  import { useMediaCloudEmitter } from "../../hooks/useMediaCloudEmitter.mjs";
6
6
  import { createContext, use, useCallback, useEffect, useRef, useState } from "react";
7
7
  import { Button } from "@payloadcms/ui";
8
- import "./upload-manager.css";
8
+ import "./uploadManager.css";
9
9
 
10
- //#region src/components/upload-manager/upload-manager.tsx
10
+ //#region src/components/uploadManager/uploadManager.tsx
11
11
  const UploadManagerContext = createContext({
12
12
  showUploadManager: false,
13
13
  activeUploads: [],
@@ -270,4 +270,4 @@ const useUploadManagerContext = () => use(UploadManagerContext);
270
270
 
271
271
  //#endregion
272
272
  export { UploadManagerProvider, useUploadManagerContext };
273
- //# sourceMappingURL=upload-manager.mjs.map
273
+ //# sourceMappingURL=uploadManager.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploadManager.mjs","names":["upload: Upload","args","value: UploadManagerContextType"],"sources":["../../../src/components/uploadManager/uploadManager.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n use,\n useState,\n useCallback,\n useEffect,\n useRef,\n} from 'react'\nimport { Button } from '@payloadcms/ui'\n\nimport { useMediaCloudEmitter } from '../../hooks/useMediaCloudEmitter'\nimport { useErrorHandler } from '../../hooks/useErrorHandler'\nimport { MediaCloudErrors } from '../../types/errors'\n\nimport type { MediaCloudEmitterEvents } from '../../types'\nimport type React from 'react'\n\nimport './uploadManager.css'\n\ninterface Upload {\n filename: string\n progress: number\n uploadId?: string\n error?: string\n polling?: boolean\n pollingUrl?: string\n status?: 'uploading' | 'processing' | 'completed'\n}\n\ninterface UploadManagerContextType {\n showUploadManager?: boolean\n activeUploads: Upload[]\n addUpload: (args: MediaCloudEmitterEvents['addUpload']) => void\n updateUpload: (args: MediaCloudEmitterEvents['updateUpload']) => void\n}\n\ninterface UploadManagerProviderArgs {\n children: React.ReactNode\n}\n\ninterface RenderUploadListArgs {\n uploads: Upload[]\n}\n\nconst UploadManagerContext = createContext<UploadManagerContextType>({\n showUploadManager: false,\n activeUploads: [],\n addUpload: () => {},\n updateUpload: () => {},\n})\n\n/**\n * Provider component for upload management context\n * @param args - Arguments including children to wrap\n * @returns JSX element providing upload management context\n */\nexport function UploadManagerProvider(args: UploadManagerProviderArgs) {\n const { children } = args\n const [showUploadManager, setShowUploadManager] = useState(false)\n const [activeUploads, setActiveUploads] = useState<Upload[]>([])\n const [activeTab, setActiveTab] = useState<\n 'uploading' | 'processing' | 'completed'\n >('uploading')\n\n const emitter = useMediaCloudEmitter()\n const activeTabRef = useRef(activeTab)\n const activeUploadsRef = useRef(activeUploads)\n\n const { logError } = useErrorHandler()\n\n // Keep refs in sync with state\n useEffect(() => {\n activeTabRef.current = activeTab\n }, [activeTab])\n\n useEffect(() => {\n activeUploadsRef.current = activeUploads\n }, [activeUploads])\n\n // Helper function to check if we should auto-switch to completed tab\n const checkAutoSwitchToCompleted = useCallback((uploads: Upload[]) => {\n const hasActiveUploads = uploads.some(\n (upload) => upload.status === 'uploading'\n )\n const hasProcessingUploads = uploads.some(\n (upload) => upload.status === 'processing'\n )\n const hasCompletedUploads = uploads.some(\n (upload) => upload.status === 'completed'\n )\n\n // Auto-switch to completed tab if no uploading/processing uploads remain\n if (\n !hasActiveUploads &&\n !hasProcessingUploads &&\n hasCompletedUploads &&\n activeTabRef.current !== 'completed'\n ) {\n setActiveTab('completed')\n }\n }, [])\n\n // Polling logic\n useEffect(() => {\n const pollingUploads = activeUploads.filter(\n (upload) => upload.polling && upload.pollingUrl\n )\n\n if (pollingUploads.length === 0) {\n return\n }\n\n const pollAssets = async () => {\n for (const pollingUpload of pollingUploads) {\n try {\n const response = await fetch(\n `${pollingUpload.pollingUrl}?upload_id=${pollingUpload.uploadId}`,\n {\n method: 'GET',\n credentials: 'include',\n }\n )\n\n if (response.ok) {\n const data = await response.json()\n\n if (data.ready) {\n // Asset is ready, stop polling for this upload\n setActiveUploads((prev) => {\n const updatedUploads = prev.map((upload) =>\n upload.uploadId === pollingUpload.uploadId\n ? {\n ...upload,\n polling: false,\n progress: 100,\n status: 'completed' as const,\n }\n : upload\n )\n\n // Check if we should auto-switch to completed tab\n setTimeout(() => checkAutoSwitchToCompleted(updatedUploads), 0)\n\n return updatedUploads\n })\n }\n }\n } catch (_error) {\n logError(MediaCloudErrors.UPLOAD_POLLING_ERROR.message)\n }\n }\n }\n\n const intervalId = setInterval(pollAssets, 2000) // Poll every 2 seconds\n\n return () => clearInterval(intervalId)\n }, [activeUploads, checkAutoSwitchToCompleted, logError])\n\n /**\n * Handles the 'uploadError' event\n * @param event - The upload error event\n */\n const onUploadError = useCallback(\n (event: MediaCloudEmitterEvents['uploadError']) => {\n const { filename, error } = event\n\n logError(MediaCloudErrors.TUS_UPLOAD_ERROR.message)\n\n setActiveUploads((prev) =>\n prev.map((upload) =>\n upload.filename === filename\n ? { ...upload, error: error, status: 'completed' }\n : upload\n )\n )\n },\n [logError]\n )\n\n /**\n * Handles the 'addUpload' event\n * @param event - The add upload event\n */\n const onAddUpload = useCallback(\n (event: MediaCloudEmitterEvents['addUpload']) => {\n const upload: Upload = {\n filename: event.filename,\n uploadId: event.uploadId,\n progress: 0,\n polling: event.polling,\n pollingUrl: event.pollingUrl,\n status: 'uploading',\n }\n\n setActiveUploads((prev) => [...prev, upload])\n\n // Show the upload manager when new upload starts\n setShowUploadManager(true)\n\n // Auto-switch to uploading tab when new upload starts\n if (activeTabRef.current !== 'uploading') {\n setActiveTab('uploading')\n }\n },\n []\n )\n\n /**\n * Handles the 'updateUpload' event\n * @param event - The update upload event\n */\n const onUpdateUpload = useCallback(\n (event: MediaCloudEmitterEvents['updateUpload']) => {\n const { filename, progress, polling } = event\n setActiveUploads((prev) =>\n prev.map((upload) =>\n upload.filename === filename\n ? {\n ...upload,\n progress,\n ...(polling !== undefined && { polling }),\n status: polling\n ? 'processing'\n : progress >= 100\n ? 'completed'\n : 'uploading',\n }\n : upload\n )\n )\n },\n []\n )\n\n /**\n * Handles the 'removeUpload' event\n * @param event - The remove upload event\n */\n const onRemoveUpload = useCallback(\n (event: MediaCloudEmitterEvents['removeUpload']) => {\n setActiveUploads((prev) =>\n prev.filter((upload) => upload.filename !== event.filename)\n )\n },\n []\n )\n\n /**\n * Handles the 'uploadComplete' event\n * @param event - The upload completed event\n */\n const onUploadComplete = useCallback(\n (event: MediaCloudEmitterEvents['uploadComplete']) => {\n // Check if this upload has a polling URL (Mux upload)\n const upload = activeUploadsRef.current.find(\n (upload) => upload.filename === event.filename\n )\n if (upload?.pollingUrl) {\n setActiveUploads((prev) =>\n prev.map((upload) =>\n upload.filename === event.filename\n ? {\n ...upload,\n polling: true,\n progress: 100,\n status: 'processing' as const,\n }\n : upload\n )\n )\n } else {\n // Regular upload completion\n setActiveUploads((prev) => {\n const updatedUploads = prev.map((upload) =>\n upload.filename === event.filename\n ? { ...upload, progress: 100, status: 'completed' as const }\n : upload\n )\n\n // Check if we should auto-switch to completed tab\n setTimeout(() => checkAutoSwitchToCompleted(updatedUploads), 0)\n\n return updatedUploads\n })\n }\n },\n [checkAutoSwitchToCompleted]\n )\n\n useEffect(() => {\n emitter.on('addUpload', onAddUpload)\n emitter.on('updateUpload', onUpdateUpload)\n emitter.on('removeUpload', onRemoveUpload)\n emitter.on('uploadError', onUploadError)\n emitter.on('uploadComplete', onUploadComplete)\n\n return () => {\n emitter.off('addUpload', onAddUpload)\n emitter.off('updateUpload', onUpdateUpload)\n emitter.off('removeUpload', onRemoveUpload)\n emitter.off('uploadError', onUploadError)\n emitter.off('uploadComplete', onUploadComplete)\n }\n }, [\n emitter,\n onAddUpload,\n onUpdateUpload,\n onRemoveUpload,\n onUploadError,\n onUploadComplete,\n ])\n\n /**\n * Adds a new upload to the manager\n * @param args - The upload arguments\n */\n const addUpload = useCallback(\n (args: MediaCloudEmitterEvents['addUpload']) => {\n const { filename, polling = false, pollingUrl } = args\n const upload: Upload = {\n filename,\n progress: 0,\n polling,\n pollingUrl,\n status: 'uploading',\n }\n\n setActiveUploads((prev) => [...prev, upload])\n },\n []\n )\n\n /**\n * Updates an existing upload in the manager\n * @param args - The update arguments\n */\n const updateUpload = useCallback(\n (args: MediaCloudEmitterEvents['updateUpload']) => {\n const { filename, progress, polling } = args\n setActiveUploads((prev) =>\n prev.map((upload) =>\n upload.filename === filename\n ? {\n ...upload,\n progress,\n ...(polling !== undefined && { polling }),\n status: polling\n ? 'processing'\n : progress >= 100\n ? 'completed'\n : 'uploading',\n }\n : upload\n )\n )\n },\n []\n )\n\n // Filter uploads by status\n const uploadingFiles = activeUploads.filter(\n (upload) => upload.status === 'uploading'\n )\n const processingFiles = activeUploads.filter(\n (upload) => upload.status === 'processing'\n )\n const completedFiles = activeUploads.filter(\n (upload) => upload.status === 'completed'\n )\n\n /**\n * Renders the upload list\n * @param args - The render arguments\n * @returns JSX element representing the upload list\n */\n function renderUploadList(args: RenderUploadListArgs) {\n const { uploads } = args\n return (\n <ul>\n {uploads.map((upload) => (\n <li key={upload.filename} data-status={upload.status}>\n <div className=\"upload-info\">\n <span className=\"upload-filename\">{upload.filename}</span>\n <span className=\"upload-meta\">\n {upload.status === 'processing'\n ? 'Processing...'\n : upload.progress < 100\n ? `${Math.ceil(upload.progress)}%`\n : 'Completed'}\n </span>\n </div>\n <div\n className=\"upload-progress-bar\"\n style={\n {\n ['--progress']:\n upload.status === 'processing'\n ? '1'\n : `${upload.progress / 100}`,\n } as React.CSSProperties\n }\n >\n <div\n data-active={upload.status === 'processing'}\n className=\"upload-progress\"\n />\n </div>\n </li>\n ))}\n </ul>\n )\n }\n\n /**\n * Closes the upload manager\n */\n function closeUploadManager() {\n // Only allow closing if no uploads are actively polling\n const hasPollingUploads = activeUploads.some((upload) => upload.polling)\n if (!hasPollingUploads) {\n setActiveUploads([])\n setShowUploadManager(false)\n }\n }\n\n const value: UploadManagerContextType = {\n activeUploads,\n addUpload,\n updateUpload,\n }\n\n return (\n <UploadManagerContext.Provider value={value}>\n {showUploadManager && (\n <div className=\"upload-manager\">\n <div className=\"upload-manager__header\">\n <h4>Uploads</h4>\n <Button\n buttonStyle=\"icon-label\"\n icon=\"x\"\n margin={false}\n onClick={closeUploadManager}\n />\n </div>\n\n <div className=\"upload-manager__tabs\">\n <button\n data-active={activeTab === 'uploading'}\n className=\"upload-tab\"\n onClick={() => setActiveTab('uploading')}\n >\n Uploading ({uploadingFiles.length})\n </button>\n <button\n data-active={activeTab === 'processing'}\n className=\"upload-tab\"\n onClick={() => setActiveTab('processing')}\n >\n Processing ({processingFiles.length})\n </button>\n <button\n data-active={activeTab === 'completed'}\n className=\"upload-tab\"\n onClick={() => setActiveTab('completed')}\n >\n Completed ({completedFiles.length})\n </button>\n </div>\n\n <div className=\"upload-manager__content\">\n {activeTab === 'uploading' && uploadingFiles.length > 0 && (\n <div>{renderUploadList({ uploads: uploadingFiles })}</div>\n )}\n {activeTab === 'processing' && processingFiles.length > 0 && (\n <div>{renderUploadList({ uploads: processingFiles })}</div>\n )}\n {activeTab === 'completed' && completedFiles.length > 0 && (\n <div>\n {renderUploadList({ uploads: completedFiles })}\n <div className=\"upload-manager__footer\">\n <Button\n buttonStyle=\"subtle\"\n size=\"small\"\n margin={false}\n onClick={() => window?.location?.reload()}\n >\n Refresh\n </Button>\n </div>\n </div>\n )}\n {((activeTab === 'uploading' && uploadingFiles.length === 0) ||\n (activeTab === 'processing' && processingFiles.length === 0) ||\n (activeTab === 'completed' && completedFiles.length === 0)) && (\n <p className=\"upload-empty-state\">No {activeTab} files</p>\n )}\n </div>\n </div>\n )}\n {children}\n </UploadManagerContext.Provider>\n )\n}\n\nexport const useUploadManagerContext = () => use(UploadManagerContext)\n"],"mappings":";;;;;;;;;;AA8CA,MAAM,uBAAuB,cAAwC;CACnE,mBAAmB;CACnB,eAAe,EAAE;CACjB,iBAAiB;CACjB,oBAAoB;CACrB,CAAC;;;;;;AAOF,SAAgB,sBAAsB,MAAiC;CACrE,MAAM,EAAE,aAAa;CACrB,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,MAAM;CACjE,MAAM,CAAC,eAAe,oBAAoB,SAAmB,EAAE,CAAC;CAChE,MAAM,CAAC,WAAW,gBAAgB,SAEhC,YAAY;CAEd,MAAM,UAAU,sBAAsB;CACtC,MAAM,eAAe,OAAO,UAAU;CACtC,MAAM,mBAAmB,OAAO,cAAc;CAE9C,MAAM,EAAE,aAAa,iBAAiB;AAGtC,iBAAgB;AACd,eAAa,UAAU;IACtB,CAAC,UAAU,CAAC;AAEf,iBAAgB;AACd,mBAAiB,UAAU;IAC1B,CAAC,cAAc,CAAC;CAGnB,MAAM,6BAA6B,aAAa,YAAsB;EACpE,MAAM,mBAAmB,QAAQ,MAC9B,WAAW,OAAO,WAAW,YAC/B;EACD,MAAM,uBAAuB,QAAQ,MAClC,WAAW,OAAO,WAAW,aAC/B;EACD,MAAM,sBAAsB,QAAQ,MACjC,WAAW,OAAO,WAAW,YAC/B;AAGD,MACE,CAAC,oBACD,CAAC,wBACD,uBACA,aAAa,YAAY,YAEzB,cAAa,YAAY;IAE1B,EAAE,CAAC;AAGN,iBAAgB;EACd,MAAM,iBAAiB,cAAc,QAClC,WAAW,OAAO,WAAW,OAAO,WACtC;AAED,MAAI,eAAe,WAAW,EAC5B;EAGF,MAAM,aAAa,YAAY;AAC7B,QAAK,MAAM,iBAAiB,eAC1B,KAAI;IACF,MAAM,WAAW,MAAM,MACrB,GAAG,cAAc,WAAW,aAAa,cAAc,YACvD;KACE,QAAQ;KACR,aAAa;KACd,CACF;AAED,QAAI,SAAS,IAGX;UAFa,MAAM,SAAS,MAAM,EAEzB,MAEP,mBAAkB,SAAS;MACzB,MAAM,iBAAiB,KAAK,KAAK,WAC/B,OAAO,aAAa,cAAc,WAC9B;OACE,GAAG;OACH,SAAS;OACT,UAAU;OACV,QAAQ;OACT,GACD,OACL;AAGD,uBAAiB,2BAA2B,eAAe,EAAE,EAAE;AAE/D,aAAO;OACP;;YAGC,QAAQ;AACf,aAAS,iBAAiB,qBAAqB,QAAQ;;;EAK7D,MAAM,aAAa,YAAY,YAAY,IAAK;AAEhD,eAAa,cAAc,WAAW;IACrC;EAAC;EAAe;EAA4B;EAAS,CAAC;;;;;CAMzD,MAAM,gBAAgB,aACnB,UAAkD;EACjD,MAAM,EAAE,UAAU,UAAU;AAE5B,WAAS,iBAAiB,iBAAiB,QAAQ;AAEnD,oBAAkB,SAChB,KAAK,KAAK,WACR,OAAO,aAAa,WAChB;GAAE,GAAG;GAAe;GAAO,QAAQ;GAAa,GAChD,OACL,CACF;IAEH,CAAC,SAAS,CACX;;;;;CAMD,MAAM,cAAc,aACjB,UAAgD;EAC/C,MAAMA,SAAiB;GACrB,UAAU,MAAM;GAChB,UAAU,MAAM;GAChB,UAAU;GACV,SAAS,MAAM;GACf,YAAY,MAAM;GAClB,QAAQ;GACT;AAED,oBAAkB,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC;AAG7C,uBAAqB,KAAK;AAG1B,MAAI,aAAa,YAAY,YAC3B,cAAa,YAAY;IAG7B,EAAE,CACH;;;;;CAMD,MAAM,iBAAiB,aACpB,UAAmD;EAClD,MAAM,EAAE,UAAU,UAAU,YAAY;AACxC,oBAAkB,SAChB,KAAK,KAAK,WACR,OAAO,aAAa,WAChB;GACE,GAAG;GACH;GACA,GAAI,YAAY,UAAa,EAAE,SAAS;GACxC,QAAQ,UACJ,eACA,YAAY,MACV,cACA;GACP,GACD,OACL,CACF;IAEH,EAAE,CACH;;;;;CAMD,MAAM,iBAAiB,aACpB,UAAmD;AAClD,oBAAkB,SAChB,KAAK,QAAQ,WAAW,OAAO,aAAa,MAAM,SAAS,CAC5D;IAEH,EAAE,CACH;;;;;CAMD,MAAM,mBAAmB,aACtB,UAAqD;AAKpD,MAHe,iBAAiB,QAAQ,MACrC,WAAW,OAAO,aAAa,MAAM,SACvC,EACW,WACV,mBAAkB,SAChB,KAAK,KAAK,WACR,OAAO,aAAa,MAAM,WACtB;GACE,GAAG;GACH,SAAS;GACT,UAAU;GACV,QAAQ;GACT,GACD,OACL,CACF;MAGD,mBAAkB,SAAS;GACzB,MAAM,iBAAiB,KAAK,KAAK,WAC/B,OAAO,aAAa,MAAM,WACtB;IAAE,GAAG;IAAQ,UAAU;IAAK,QAAQ;IAAsB,GAC1D,OACL;AAGD,oBAAiB,2BAA2B,eAAe,EAAE,EAAE;AAE/D,UAAO;IACP;IAGN,CAAC,2BAA2B,CAC7B;AAED,iBAAgB;AACd,UAAQ,GAAG,aAAa,YAAY;AACpC,UAAQ,GAAG,gBAAgB,eAAe;AAC1C,UAAQ,GAAG,gBAAgB,eAAe;AAC1C,UAAQ,GAAG,eAAe,cAAc;AACxC,UAAQ,GAAG,kBAAkB,iBAAiB;AAE9C,eAAa;AACX,WAAQ,IAAI,aAAa,YAAY;AACrC,WAAQ,IAAI,gBAAgB,eAAe;AAC3C,WAAQ,IAAI,gBAAgB,eAAe;AAC3C,WAAQ,IAAI,eAAe,cAAc;AACzC,WAAQ,IAAI,kBAAkB,iBAAiB;;IAEhD;EACD;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;;;;CAMF,MAAM,YAAY,aACf,WAA+C;EAC9C,MAAM,EAAE,UAAU,UAAU,OAAO,eAAeC;EAClD,MAAMD,SAAiB;GACrB;GACA,UAAU;GACV;GACA;GACA,QAAQ;GACT;AAED,oBAAkB,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC;IAE/C,EAAE,CACH;;;;;CAMD,MAAM,eAAe,aAClB,WAAkD;EACjD,MAAM,EAAE,UAAU,UAAU,YAAYC;AACxC,oBAAkB,SAChB,KAAK,KAAK,WACR,OAAO,aAAa,WAChB;GACE,GAAG;GACH;GACA,GAAI,YAAY,UAAa,EAAE,SAAS;GACxC,QAAQ,UACJ,eACA,YAAY,MACV,cACA;GACP,GACD,OACL,CACF;IAEH,EAAE,CACH;CAGD,MAAM,iBAAiB,cAAc,QAClC,WAAW,OAAO,WAAW,YAC/B;CACD,MAAM,kBAAkB,cAAc,QACnC,WAAW,OAAO,WAAW,aAC/B;CACD,MAAM,iBAAiB,cAAc,QAClC,WAAW,OAAO,WAAW,YAC/B;;;;;;CAOD,SAAS,iBAAiB,QAA4B;EACpD,MAAM,EAAE,YAAYA;AACpB,SACE,CAAC,GAAG;SACD,QAAQ,KAAK,WACZ,CAAC,GAAG,KAAK,OAAO,UAAU,aAAa,OAAO,QAAQ;YACpD,CAAC,IAAI,wBAAwB;cAC3B,CAAC,KAAK,6BAA6B,OAAO,SAAS,EAAE,KAAK;cAC1D,CAAC,KAAK,wBAAwB;iBAC3B,OAAO,WAAW,eACf,kBACA,OAAO,WAAW,MAChB,GAAG,KAAK,KAAK,OAAO,SAAS,CAAC,KAC9B,YAAY;cACpB,EAAE,KAAK;YACT,EAAE,IAAI;YACN,CAAC,IACC,gCACA,OACE,GACG,eACC,OAAO,WAAW,eACd,MACA,GAAG,OAAO,WAAW,OAC5B,EAEJ;cACC,CAAC,IACC,aAAa,OAAO,WAAW,cAC/B,8BACA;YACJ,EAAE,IAAI;UACR,EAAE,IACF,CAAC;MACL,EAAE;;;;;CAON,SAAS,qBAAqB;AAG5B,MAAI,CADsB,cAAc,MAAM,WAAW,OAAO,QAAQ,EAChD;AACtB,oBAAiB,EAAE,CAAC;AACpB,wBAAqB,MAAM;;;CAI/B,MAAMC,QAAkC;EACtC;EACA;EACA;EACD;AAED,QACE,CAAC,qBAAqB,SAAS,OAAO,OAAO;OAC1C,qBACC,CAAC,IAAI,2BAA2B;UAC9B,CAAC,IAAI,mCAAmC;YACtC,CAAC,GAAG,OAAO,EAAE,GAAG;YAChB,CAAC,OACC,yBACA,SACA,QAAQ,OACR,SAAS,sBACT;UACJ,EAAE,IAAI;;UAEN,CAAC,IAAI,iCAAiC;YACpC,CAAC,OACC,aAAa,cAAc,aAC3B,uBACA,eAAe,aAAa,YAAY,EACzC;0BACa,eAAe,OAAO;YACpC,EAAE,OAAO;YACT,CAAC,OACC,aAAa,cAAc,cAC3B,uBACA,eAAe,aAAa,aAAa,EAC1C;2BACc,gBAAgB,OAAO;YACtC,EAAE,OAAO;YACT,CAAC,OACC,aAAa,cAAc,aAC3B,uBACA,eAAe,aAAa,YAAY,EACzC;0BACa,eAAe,OAAO;YACpC,EAAE,OAAO;UACX,EAAE,IAAI;;UAEN,CAAC,IAAI,oCAAoC;aACtC,cAAc,eAAe,eAAe,SAAS,KACpD,CAAC,KAAK,iBAAiB,EAAE,SAAS,gBAAgB,CAAC,CAAC,EAAE,KACtD;aACD,cAAc,gBAAgB,gBAAgB,SAAS,KACtD,CAAC,KAAK,iBAAiB,EAAE,SAAS,iBAAiB,CAAC,CAAC,EAAE,KACvD;aACD,cAAc,eAAe,eAAe,SAAS,KACpD,CAAC,IAAI;iBACF,iBAAiB,EAAE,SAAS,gBAAgB,CAAC,CAAC;gBAC/C,CAAC,IAAI,mCAAmC;kBACtC,CAAC,OACC,qBACA,aACA,QAAQ,OACR,eAAe,QAAQ,UAAU,QAAQ,EAC1C;;kBAED,EAAE,OAAO;gBACX,EAAE,IAAI;cACR,EAAE,KACF;cACC,cAAc,eAAe,eAAe,WAAW,KACvD,cAAc,gBAAgB,gBAAgB,WAAW,KACzD,cAAc,eAAe,eAAe,WAAW,MACxD,CAAC,EAAE,+BAA+B,IAAI,UAAU,MAAM,EAAE,GACxD;UACJ,EAAE,IAAI;QACR,EAAE,KACF;OACD,SAAS;IACZ,EAAE,qBAAqB;;AAI3B,MAAa,gCAAgC,IAAI,qBAAqB"}
@@ -0,0 +1,12 @@
1
+ import { S3Store } from "../tus/stores/s3/s3Store.mjs";
2
+ import { PayloadHandler } from "payload";
3
+
4
+ //#region src/endpoints/fileExistsHandler.d.ts
5
+ interface GetFileExistsHandlerArgs {
6
+ getS3Store: () => S3Store;
7
+ collection: string;
8
+ }
9
+ declare function getFileExistsHandler(args: GetFileExistsHandlerArgs): PayloadHandler;
10
+ //#endregion
11
+ export { getFileExistsHandler };
12
+ //# sourceMappingURL=fileExistsHandler.d.mts.map
@@ -1,9 +1,9 @@
1
1
  import { MediaCloudErrors } from "../types/errors.mjs";
2
2
  import { useErrorHandler } from "../hooks/useErrorHandler.mjs";
3
3
 
4
- //#region src/endpoints/tusFileExistsHandler.ts
5
- function getTusFileExistsHandler(args) {
6
- const { s3Store } = args;
4
+ //#region src/endpoints/fileExistsHandler.ts
5
+ function getFileExistsHandler(args) {
6
+ const { getS3Store, collection } = args;
7
7
  const { throwError, logError } = useErrorHandler();
8
8
  return async function(req) {
9
9
  try {
@@ -11,13 +11,13 @@ function getTusFileExistsHandler(args) {
11
11
  const filename = routeParams?.filename;
12
12
  if (!filename) throwError(MediaCloudErrors.FILE_MISSING_NAME);
13
13
  const { docs } = await payload.find({
14
- collection: "media",
14
+ collection,
15
15
  where: { filename: { equals: filename } },
16
16
  limit: 1,
17
17
  pagination: false
18
18
  });
19
19
  if (docs.length > 0) return Response.json({ message: "File found [payload]" }, { status: 200 });
20
- const url = s3Store.getUrl(filename);
20
+ const url = getS3Store().getUrl(filename);
21
21
  if ((await fetch(url, { method: "HEAD" })).status === 200) return Response.json({ message: "File found [S3]" }, { status: 200 });
22
22
  return Response.json({ message: "File not found" }, { status: 404 });
23
23
  } catch (_error) {
@@ -28,5 +28,5 @@ function getTusFileExistsHandler(args) {
28
28
  }
29
29
 
30
30
  //#endregion
31
- export { getTusFileExistsHandler };
32
- //# sourceMappingURL=tusFileExistsHandler.mjs.map
31
+ export { getFileExistsHandler };
32
+ //# sourceMappingURL=fileExistsHandler.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileExistsHandler.mjs","names":[],"sources":["../../src/endpoints/fileExistsHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\nimport { useErrorHandler } from '../hooks/useErrorHandler'\nimport { MediaCloudErrors } from '../types/errors'\n\nimport { S3Store } from '../tus/stores/s3/s3Store'\n\ninterface GetFileExistsHandlerArgs {\n getS3Store: () => S3Store\n collection: string\n}\n\nexport function getFileExistsHandler(\n args: GetFileExistsHandlerArgs\n): PayloadHandler {\n const { getS3Store, collection } = args\n const { throwError, logError } = useErrorHandler()\n\n return async function (req) {\n try {\n const { routeParams, payload } = req\n const filename = routeParams?.filename as string\n\n if (!filename) {\n throwError(MediaCloudErrors.FILE_MISSING_NAME)\n }\n\n // Check if file exists in Payload database\n const { docs } = await payload.find({\n collection,\n where: {\n filename: {\n equals: filename,\n },\n },\n limit: 1,\n pagination: false,\n })\n\n if (docs.length > 0) {\n return Response.json(\n { message: 'File found [payload]' },\n { status: 200 }\n )\n }\n\n // Check if completed file exists in S3\n const url = getS3Store().getUrl(filename)\n const s3Response = await fetch(url, { method: 'HEAD' })\n\n if (s3Response.status === 200) {\n return Response.json({ message: 'File found [S3]' }, { status: 200 })\n }\n\n return Response.json({ message: 'File not found' }, { status: 404 })\n } catch (_error) {\n logError(MediaCloudErrors.FILE_DIMENSIONS_ERROR.message)\n return Response.json(\n { message: 'Failed to process asset' },\n { status: 500 }\n )\n }\n }\n}\n"],"mappings":";;;;AAWA,SAAgB,qBACd,MACgB;CAChB,MAAM,EAAE,YAAY,eAAe;CACnC,MAAM,EAAE,YAAY,aAAa,iBAAiB;AAElD,QAAO,eAAgB,KAAK;AAC1B,MAAI;GACF,MAAM,EAAE,aAAa,YAAY;GACjC,MAAM,WAAW,aAAa;AAE9B,OAAI,CAAC,SACH,YAAW,iBAAiB,kBAAkB;GAIhD,MAAM,EAAE,SAAS,MAAM,QAAQ,KAAK;IAClC;IACA,OAAO,EACL,UAAU,EACR,QAAQ,UACT,EACF;IACD,OAAO;IACP,YAAY;IACb,CAAC;AAEF,OAAI,KAAK,SAAS,EAChB,QAAO,SAAS,KACd,EAAE,SAAS,wBAAwB,EACnC,EAAE,QAAQ,KAAK,CAChB;GAIH,MAAM,MAAM,YAAY,CAAC,OAAO,SAAS;AAGzC,QAFmB,MAAM,MAAM,KAAK,EAAE,QAAQ,QAAQ,CAAC,EAExC,WAAW,IACxB,QAAO,SAAS,KAAK,EAAE,SAAS,mBAAmB,EAAE,EAAE,QAAQ,KAAK,CAAC;AAGvE,UAAO,SAAS,KAAK,EAAE,SAAS,kBAAkB,EAAE,EAAE,QAAQ,KAAK,CAAC;WAC7D,QAAQ;AACf,YAAS,iBAAiB,sBAAsB,QAAQ;AACxD,UAAO,SAAS,KACd,EAAE,SAAS,2BAA2B,EACtC,EAAE,QAAQ,KAAK,CAChB"}
@@ -4,6 +4,7 @@ import { PayloadHandler } from "payload";
4
4
  //#region src/endpoints/muxAssetHandler.d.ts
5
5
  interface GetMuxAssetHandlerArgs {
6
6
  getMuxClient: () => Mux$1;
7
+ collection: string;
7
8
  }
8
9
  declare function getMuxAssetHandler(args: GetMuxAssetHandlerArgs): PayloadHandler;
9
10
  //#endregion