@maas/payload-plugin-media-cloud 0.0.0

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 (87) hide show
  1. package/LICENSE +8 -0
  2. package/dist/adapter/handleDelete.d.ts +20 -0
  3. package/dist/adapter/handleDelete.js +70 -0
  4. package/dist/adapter/handleDelete.js.map +1 -0
  5. package/dist/adapter/handleUpload.d.ts +12 -0
  6. package/dist/adapter/handleUpload.js +29 -0
  7. package/dist/adapter/handleUpload.js.map +1 -0
  8. package/dist/adapter/staticHandler.d.ts +17 -0
  9. package/dist/adapter/staticHandler.js +64 -0
  10. package/dist/adapter/staticHandler.js.map +1 -0
  11. package/dist/adapter/storageAdapter.d.ts +23 -0
  12. package/dist/adapter/storageAdapter.js +30 -0
  13. package/dist/adapter/storageAdapter.js.map +1 -0
  14. package/dist/collections/mediaCollection.d.ts +16 -0
  15. package/dist/collections/mediaCollection.js +139 -0
  16. package/dist/collections/mediaCollection.js.map +1 -0
  17. package/dist/components/index.d.ts +4 -0
  18. package/dist/components/index.js +5 -0
  19. package/dist/components/mux-preview/index.d.ts +2 -0
  20. package/dist/components/mux-preview/index.js +3 -0
  21. package/dist/components/mux-preview/mux-preview.d.ts +14 -0
  22. package/dist/components/mux-preview/mux-preview.js +38 -0
  23. package/dist/components/mux-preview/mux-preview.js.map +1 -0
  24. package/dist/components/upload-handler/index.d.ts +2 -0
  25. package/dist/components/upload-handler/index.js +3 -0
  26. package/dist/components/upload-handler/upload-handler.d.ts +22 -0
  27. package/dist/components/upload-handler/upload-handler.js +178 -0
  28. package/dist/components/upload-handler/upload-handler.js.map +1 -0
  29. package/dist/components/upload-manager/index.d.ts +2 -0
  30. package/dist/components/upload-manager/index.js +3 -0
  31. package/dist/components/upload-manager/upload-manager-DN4RrmYB.css +204 -0
  32. package/dist/components/upload-manager/upload-manager-DN4RrmYB.css.map +1 -0
  33. package/dist/components/upload-manager/upload-manager.css +201 -0
  34. package/dist/components/upload-manager/upload-manager.d.ts +42 -0
  35. package/dist/components/upload-manager/upload-manager.js +315 -0
  36. package/dist/components/upload-manager/upload-manager.js.map +1 -0
  37. package/dist/components/upload-manager/upload-manager2.js +0 -0
  38. package/dist/endpoints/muxAssetHandler.d.ts +11 -0
  39. package/dist/endpoints/muxAssetHandler.js +59 -0
  40. package/dist/endpoints/muxAssetHandler.js.map +1 -0
  41. package/dist/endpoints/muxCreateUploadHandler.d.ts +13 -0
  42. package/dist/endpoints/muxCreateUploadHandler.js +40 -0
  43. package/dist/endpoints/muxCreateUploadHandler.js.map +1 -0
  44. package/dist/endpoints/muxWebhookHandler.d.ts +11 -0
  45. package/dist/endpoints/muxWebhookHandler.js +49 -0
  46. package/dist/endpoints/muxWebhookHandler.js.map +1 -0
  47. package/dist/hooks/useEmitter.d.ts +48 -0
  48. package/dist/hooks/useEmitter.js +19 -0
  49. package/dist/hooks/useEmitter.js.map +1 -0
  50. package/dist/hooks/useErrorHandler.d.ts +11 -0
  51. package/dist/hooks/useErrorHandler.js +19 -0
  52. package/dist/hooks/useErrorHandler.js.map +1 -0
  53. package/dist/index.d.ts +3 -0
  54. package/dist/index.js +3 -0
  55. package/dist/plugin.d.ts +15 -0
  56. package/dist/plugin.js +242 -0
  57. package/dist/plugin.js.map +1 -0
  58. package/dist/tus/stores/s3/expiration-manager.d.ts +36 -0
  59. package/dist/tus/stores/s3/expiration-manager.js +76 -0
  60. package/dist/tus/stores/s3/expiration-manager.js.map +1 -0
  61. package/dist/tus/stores/s3/file-operations.d.ts +66 -0
  62. package/dist/tus/stores/s3/file-operations.js +90 -0
  63. package/dist/tus/stores/s3/file-operations.js.map +1 -0
  64. package/dist/tus/stores/s3/log.d.ts +5 -0
  65. package/dist/tus/stores/s3/log.js +8 -0
  66. package/dist/tus/stores/s3/log.js.map +1 -0
  67. package/dist/tus/stores/s3/metadata-manager.d.ts +85 -0
  68. package/dist/tus/stores/s3/metadata-manager.js +135 -0
  69. package/dist/tus/stores/s3/metadata-manager.js.map +1 -0
  70. package/dist/tus/stores/s3/parts-manager.d.ts +130 -0
  71. package/dist/tus/stores/s3/parts-manager.js +328 -0
  72. package/dist/tus/stores/s3/parts-manager.js.map +1 -0
  73. package/dist/tus/stores/s3/s3-store.d.ts +110 -0
  74. package/dist/tus/stores/s3/s3-store.js +342 -0
  75. package/dist/tus/stores/s3/s3-store.js.map +1 -0
  76. package/dist/tus/stores/s3/semaphore.d.ts +16 -0
  77. package/dist/tus/stores/s3/semaphore.js +32 -0
  78. package/dist/tus/stores/s3/semaphore.js.map +1 -0
  79. package/dist/types/errors.d.ts +26 -0
  80. package/dist/types/errors.js +28 -0
  81. package/dist/types/errors.js.map +1 -0
  82. package/dist/types/index.d.ts +73 -0
  83. package/dist/types/index.js +0 -0
  84. package/dist/utils/file.d.ts +30 -0
  85. package/dist/utils/file.js +84 -0
  86. package/dist/utils/file.js.map +1 -0
  87. package/package.json +92 -0
@@ -0,0 +1,315 @@
1
+ 'use client';
2
+
3
+
4
+ import { MediaCloudError } from "../../types/errors.js";
5
+ import { useErrorHandler } from "../../hooks/useErrorHandler.js";
6
+ import { useEmitter } from "../../hooks/useEmitter.js";
7
+ import "./upload-manager2.js";
8
+ import { createContext, use, useEffect, useRef, useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { Button } from "@payloadcms/ui";
11
+
12
+ //#region src/components/upload-manager/upload-manager.tsx
13
+ const { logError } = useErrorHandler();
14
+ const UploadManagerContext = createContext({
15
+ showUploadManager: false,
16
+ activeUploads: [],
17
+ addUpload: () => {},
18
+ updateUpload: () => {}
19
+ });
20
+ /**
21
+ * Provider component for upload management context
22
+ * @param args - Arguments including children to wrap
23
+ * @returns JSX element providing upload management context
24
+ */
25
+ function UploadManagerProvider(args) {
26
+ const { children } = args;
27
+ const [showUploadManager, setShowUploadManager] = useState(false);
28
+ const [activeUploads, setActiveUploads] = useState([]);
29
+ const [activeTab, setActiveTab] = useState("uploading");
30
+ const activeTabRef = useRef(activeTab);
31
+ const activeUploadsRef = useRef(activeUploads);
32
+ useEffect(() => {
33
+ activeTabRef.current = activeTab;
34
+ }, [activeTab]);
35
+ useEffect(() => {
36
+ activeUploadsRef.current = activeUploads;
37
+ }, [activeUploads]);
38
+ const emitter = useEmitter();
39
+ function checkAutoSwitchToCompleted(uploads) {
40
+ const hasActiveUploads = uploads.some((upload) => upload.status === "uploading");
41
+ const hasProcessingUploads = uploads.some((upload) => upload.status === "processing");
42
+ const hasCompletedUploads = uploads.some((upload) => upload.status === "completed");
43
+ if (!hasActiveUploads && !hasProcessingUploads && hasCompletedUploads && activeTabRef.current !== "completed") setActiveTab("completed");
44
+ }
45
+ useEffect(() => {
46
+ const pollingUploads = activeUploads.filter((upload) => upload.polling && upload.pollingUrl);
47
+ if (pollingUploads.length === 0) return;
48
+ const pollAssets = async () => {
49
+ for (const upload of pollingUploads) try {
50
+ const response = await fetch(`${upload.pollingUrl}?upload_id=${upload.id}`, {
51
+ method: "GET",
52
+ credentials: "include"
53
+ });
54
+ if (response.ok) {
55
+ const data = await response.json();
56
+ if (data.ready) setActiveUploads((prev) => {
57
+ const updatedUploads = prev.map((u) => u.id === upload.id ? {
58
+ ...u,
59
+ polling: false,
60
+ progress: 100,
61
+ status: "completed"
62
+ } : u);
63
+ setTimeout(() => checkAutoSwitchToCompleted(updatedUploads), 0);
64
+ return updatedUploads;
65
+ });
66
+ }
67
+ } catch (_error) {
68
+ logError(MediaCloudError.UPLOAD_POLLING_ERROR);
69
+ }
70
+ };
71
+ const intervalId = setInterval(pollAssets, 2e3);
72
+ return () => clearInterval(intervalId);
73
+ }, [activeUploads, emitter]);
74
+ useEffect(() => {
75
+ emitter.on("add-upload", onAddUpload);
76
+ emitter.on("update-upload", onUpdateUpload);
77
+ emitter.on("remove-upload", onRemoveUpload);
78
+ emitter.on("upload-error", onUploadError);
79
+ emitter.on("upload-completed", onUploadCompleted);
80
+ return () => {
81
+ emitter.off("add-upload", onAddUpload);
82
+ emitter.off("update-upload", onUpdateUpload);
83
+ emitter.off("remove-upload", onRemoveUpload);
84
+ emitter.off("upload-error", onUploadError);
85
+ emitter.off("upload-completed", onUploadCompleted);
86
+ };
87
+ }, [emitter]);
88
+ /**
89
+ * Handles the 'upload-error' event
90
+ * @param event - The upload error event
91
+ */
92
+ function onUploadError(event) {
93
+ const { id, error } = event;
94
+ setActiveUploads((prev) => prev.map((upload) => upload.id === id ? {
95
+ ...upload,
96
+ error,
97
+ status: "completed"
98
+ } : upload));
99
+ logError(error);
100
+ }
101
+ /**
102
+ * Handles the 'add-upload' event
103
+ * @param event - The add upload event
104
+ */
105
+ function onAddUpload(event) {
106
+ addUpload({
107
+ id: event.id,
108
+ filename: event.filename,
109
+ polling: event.polling,
110
+ pollingUrl: event.pollingUrl
111
+ });
112
+ setShowUploadManager(true);
113
+ if (activeTabRef.current !== "uploading") setActiveTab("uploading");
114
+ }
115
+ /**
116
+ * Handles the 'update-upload' event
117
+ * @param event - The update upload event
118
+ */
119
+ function onUpdateUpload(event) {
120
+ updateUpload({
121
+ id: event.id,
122
+ progress: event.progress,
123
+ polling: event.polling
124
+ });
125
+ }
126
+ /**
127
+ * Handles the 'remove-upload' event
128
+ * @param event - The remove upload event
129
+ */
130
+ function onRemoveUpload(event) {
131
+ setActiveUploads((prev) => prev.filter((upload) => upload.id !== event.id));
132
+ }
133
+ /**
134
+ * Handles the 'upload-completed' event
135
+ * @param event - The upload completed event
136
+ */
137
+ function onUploadCompleted(event) {
138
+ const upload = activeUploadsRef.current.find((u) => u.id === event.id);
139
+ if (upload?.pollingUrl) setActiveUploads((prev) => prev.map((u) => u.id === event.id ? {
140
+ ...u,
141
+ polling: true,
142
+ progress: 100,
143
+ status: "processing"
144
+ } : u));
145
+ else setActiveUploads((prev) => {
146
+ const updatedUploads = prev.map((u) => u.id === event.id ? {
147
+ ...u,
148
+ progress: 100,
149
+ status: "completed"
150
+ } : u);
151
+ setTimeout(() => checkAutoSwitchToCompleted(updatedUploads), 0);
152
+ return updatedUploads;
153
+ });
154
+ }
155
+ /**
156
+ * Adds a new upload to the manager
157
+ * @param args - The upload arguments
158
+ */
159
+ function addUpload(args$1) {
160
+ const { id, filename, polling = false, pollingUrl } = args$1;
161
+ const upload = {
162
+ id,
163
+ filename,
164
+ progress: 0,
165
+ polling,
166
+ pollingUrl,
167
+ status: "uploading"
168
+ };
169
+ setActiveUploads((prev) => [...prev, upload]);
170
+ }
171
+ /**
172
+ * Updates an existing upload in the manager
173
+ * @param args - The update arguments
174
+ */
175
+ function updateUpload(args$1) {
176
+ const { id, progress, polling } = args$1;
177
+ setActiveUploads((prev) => prev.map((upload) => upload.id === id ? {
178
+ ...upload,
179
+ progress,
180
+ ...polling !== void 0 && { polling },
181
+ status: polling ? "processing" : progress >= 100 ? "completed" : "uploading"
182
+ } : upload));
183
+ setActiveUploads((currentUploads) => {
184
+ return currentUploads;
185
+ });
186
+ }
187
+ const uploadingFiles = activeUploads.filter((upload) => upload.status === "uploading");
188
+ const processingFiles = activeUploads.filter((upload) => upload.status === "processing");
189
+ const completedFiles = activeUploads.filter((upload) => upload.status === "completed");
190
+ /**
191
+ * Renders the upload list
192
+ * @param args - The render arguments
193
+ * @returns JSX element representing the upload list
194
+ */
195
+ function renderUploadList(args$1) {
196
+ const { uploads } = args$1;
197
+ return /* @__PURE__ */ jsx("ul", { children: uploads.map((upload) => /* @__PURE__ */ jsxs("li", {
198
+ "data-status": upload.status,
199
+ children: [/* @__PURE__ */ jsxs("div", {
200
+ className: "upload-info",
201
+ children: [/* @__PURE__ */ jsx("span", {
202
+ className: "upload-filename",
203
+ children: upload.filename
204
+ }), /* @__PURE__ */ jsx("span", {
205
+ className: "upload-meta",
206
+ children: upload.status === "processing" ? "Processing..." : upload.progress < 100 ? `${Math.ceil(upload.progress)}%` : "Completed"
207
+ })]
208
+ }), /* @__PURE__ */ jsx("div", {
209
+ className: "upload-progress-bar",
210
+ style: { ["--progress"]: upload.status === "processing" ? "1" : `${upload.progress / 100}` },
211
+ children: /* @__PURE__ */ jsx("div", {
212
+ "data-active": upload.status === "processing",
213
+ className: "upload-progress"
214
+ })
215
+ })]
216
+ }, upload.id)) });
217
+ }
218
+ /**
219
+ * Closes the upload manager
220
+ */
221
+ function closeUploadManager() {
222
+ const hasPollingUploads = activeUploads.some((upload) => upload.polling);
223
+ if (!hasPollingUploads) {
224
+ setActiveUploads([]);
225
+ setShowUploadManager(false);
226
+ }
227
+ }
228
+ const value = {
229
+ activeUploads,
230
+ addUpload,
231
+ updateUpload
232
+ };
233
+ return /* @__PURE__ */ jsxs(UploadManagerContext.Provider, {
234
+ value,
235
+ children: [showUploadManager && /* @__PURE__ */ jsxs("div", {
236
+ className: "upload-manager",
237
+ children: [
238
+ /* @__PURE__ */ jsxs("div", {
239
+ className: "upload-manager__header",
240
+ children: [/* @__PURE__ */ jsx("h4", { children: "Uploads" }), /* @__PURE__ */ jsx(Button, {
241
+ buttonStyle: "icon-label",
242
+ icon: "x",
243
+ margin: false,
244
+ onClick: closeUploadManager
245
+ })]
246
+ }),
247
+ /* @__PURE__ */ jsxs("div", {
248
+ className: "upload-manager__tabs",
249
+ children: [
250
+ /* @__PURE__ */ jsxs("button", {
251
+ "data-active": activeTab === "uploading",
252
+ className: "upload-tab",
253
+ onClick: () => setActiveTab("uploading"),
254
+ children: [
255
+ "Uploading (",
256
+ uploadingFiles.length,
257
+ ")"
258
+ ]
259
+ }),
260
+ /* @__PURE__ */ jsxs("button", {
261
+ "data-active": activeTab === "processing",
262
+ className: "upload-tab",
263
+ onClick: () => setActiveTab("processing"),
264
+ children: [
265
+ "Processing (",
266
+ processingFiles.length,
267
+ ")"
268
+ ]
269
+ }),
270
+ /* @__PURE__ */ jsxs("button", {
271
+ "data-active": activeTab === "completed",
272
+ className: "upload-tab",
273
+ onClick: () => setActiveTab("completed"),
274
+ children: [
275
+ "Completed (",
276
+ completedFiles.length,
277
+ ")"
278
+ ]
279
+ })
280
+ ]
281
+ }),
282
+ /* @__PURE__ */ jsxs("div", {
283
+ className: "upload-manager__content",
284
+ children: [
285
+ activeTab === "uploading" && uploadingFiles.length > 0 && /* @__PURE__ */ jsx("div", { children: renderUploadList({ uploads: uploadingFiles }) }),
286
+ activeTab === "processing" && processingFiles.length > 0 && /* @__PURE__ */ jsx("div", { children: renderUploadList({ uploads: processingFiles }) }),
287
+ activeTab === "completed" && completedFiles.length > 0 && /* @__PURE__ */ jsxs("div", { children: [renderUploadList({ uploads: completedFiles }), /* @__PURE__ */ jsx("div", {
288
+ className: "upload-manager__footer",
289
+ children: /* @__PURE__ */ jsx(Button, {
290
+ buttonStyle: "subtle",
291
+ size: "small",
292
+ margin: false,
293
+ onClick: () => window?.location?.reload(),
294
+ children: "Refresh"
295
+ })
296
+ })] }),
297
+ (activeTab === "uploading" && uploadingFiles.length === 0 || activeTab === "processing" && processingFiles.length === 0 || activeTab === "completed" && completedFiles.length === 0) && /* @__PURE__ */ jsxs("p", {
298
+ className: "upload-empty-state",
299
+ children: [
300
+ "No ",
301
+ activeTab,
302
+ " files"
303
+ ]
304
+ })
305
+ ]
306
+ })
307
+ ]
308
+ }), children]
309
+ });
310
+ }
311
+ const useUploadManagerContext = () => use(UploadManagerContext);
312
+
313
+ //#endregion
314
+ export { UploadManagerProvider, useUploadManagerContext };
315
+ //# sourceMappingURL=upload-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-manager.js","names":["args: UploadManagerProviderArgs","uploads: Upload[]","event: { id: string; error: MediaCloudError }","event: OnAddUploadEvent","event: OnUpdateUploadEvent","event: { id: string }","args: AddUploadArgs","args","upload: Upload","args: UpdateUploadArgs","args: RenderUploadListArgs","value: UploadManagerContextType"],"sources":["../../../src/components/upload-manager/upload-manager.tsx"],"sourcesContent":["'use client'\n\nimport { createContext, use, useState, useEffect, useRef } from 'react'\nimport { Button } from '@payloadcms/ui'\n\nimport { useEmitter } from '../../hooks/useEmitter'\nimport { useErrorHandler } from '../../hooks/useErrorHandler'\nimport { MediaCloudError } from '../../types/errors'\n\nimport type React from 'react'\n\nimport './upload-manager.css'\n\ninterface Upload {\n id: string\n filename: string\n progress: number\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: AddUploadArgs) => void\n updateUpload: (args: UpdateUploadArgs) => void\n}\n\ninterface UploadManagerProviderArgs {\n children: React.ReactNode\n}\n\ninterface OnAddUploadEvent {\n id: string\n filename: string\n polling?: boolean\n pollingUrl?: string\n}\n\ninterface OnUpdateUploadEvent {\n id: string\n progress: number\n polling?: boolean\n}\n\ninterface AddUploadArgs {\n id: string\n filename: string\n polling?: boolean\n pollingUrl?: string\n}\n\ninterface UpdateUploadArgs {\n id: string\n progress: number\n polling?: boolean\n}\n\ninterface RenderUploadListArgs {\n uploads: Upload[]\n}\n\nconst { logError } = useErrorHandler()\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 activeTabRef = useRef(activeTab)\n const activeUploadsRef = useRef(activeUploads)\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 const emitter = useEmitter()\n\n // Helper function to check if we should auto-switch to completed tab\n function checkAutoSwitchToCompleted(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 upload of pollingUploads) {\n try {\n const response = await fetch(\n `${upload.pollingUrl}?upload_id=${upload.id}`,\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((u) =>\n u.id === upload.id\n ? {\n ...u,\n polling: false,\n progress: 100,\n status: 'completed' as const,\n }\n : u\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(MediaCloudError.UPLOAD_POLLING_ERROR)\n }\n }\n }\n\n const intervalId = setInterval(pollAssets, 2000) // Poll every 2 seconds\n\n return () => clearInterval(intervalId)\n }, [activeUploads, emitter])\n\n useEffect(() => {\n emitter.on('add-upload', onAddUpload)\n emitter.on('update-upload', onUpdateUpload)\n emitter.on('remove-upload', onRemoveUpload)\n emitter.on('upload-error', onUploadError)\n emitter.on('upload-completed', onUploadCompleted)\n\n return () => {\n emitter.off('add-upload', onAddUpload)\n emitter.off('update-upload', onUpdateUpload)\n emitter.off('remove-upload', onRemoveUpload)\n emitter.off('upload-error', onUploadError)\n emitter.off('upload-completed', onUploadCompleted)\n }\n }, [emitter])\n\n /**\n * Handles the 'upload-error' event\n * @param event - The upload error event\n */\n function onUploadError(event: { id: string; error: MediaCloudError }) {\n const { id, error } = event\n setActiveUploads((prev) =>\n prev.map((upload) =>\n upload.id === id ? { ...upload, error, status: 'completed' } : upload\n )\n )\n logError(error)\n }\n\n /**\n * Handles the 'add-upload' event\n * @param event - The add upload event\n */\n function onAddUpload(event: OnAddUploadEvent) {\n addUpload({\n id: event.id,\n filename: event.filename,\n polling: event.polling,\n pollingUrl: event.pollingUrl,\n })\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 * Handles the 'update-upload' event\n * @param event - The update upload event\n */\n function onUpdateUpload(event: OnUpdateUploadEvent) {\n updateUpload({\n id: event.id,\n progress: event.progress,\n polling: event.polling,\n })\n }\n\n /**\n * Handles the 'remove-upload' event\n * @param event - The remove upload event\n */\n function onRemoveUpload(event: { id: string }) {\n setActiveUploads((prev) => prev.filter((upload) => upload.id !== event.id))\n }\n\n /**\n * Handles the 'upload-completed' event\n * @param event - The upload completed event\n */\n function onUploadCompleted(event: { id: string }) {\n // Check if this upload has a polling URL (Mux upload)\n const upload = activeUploadsRef.current.find((u) => u.id === event.id)\n if (upload?.pollingUrl) {\n setActiveUploads((prev) =>\n prev.map((u) =>\n u.id === event.id\n ? {\n ...u,\n polling: true,\n progress: 100,\n status: 'processing' as const,\n }\n : u\n )\n )\n } else {\n // Regular upload completion\n setActiveUploads((prev) => {\n const updatedUploads = prev.map((u) =>\n u.id === event.id\n ? { ...u, progress: 100, status: 'completed' as const }\n : u\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\n /**\n * Adds a new upload to the manager\n * @param args - The upload arguments\n */\n function addUpload(args: AddUploadArgs) {\n const { id, filename, polling = false, pollingUrl } = args\n const upload: Upload = {\n id,\n filename,\n progress: 0,\n polling,\n pollingUrl,\n status: 'uploading',\n }\n\n setActiveUploads((prev) => [...prev, upload])\n }\n\n /**\n * Updates an existing upload in the manager\n * @param args - The update arguments\n */\n function updateUpload(args: UpdateUploadArgs) {\n const { id, progress, polling } = args\n setActiveUploads((prev) =>\n prev.map((upload) =>\n upload.id === id\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 setActiveUploads((currentUploads) => {\n return currentUploads\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.id} 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":"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"}
@@ -0,0 +1,11 @@
1
+ import { Mux as Mux$1 } from "@mux/mux-node";
2
+ import { PayloadHandler } from "payload";
3
+
4
+ //#region src/endpoints/muxAssetHandler.d.ts
5
+ interface GetMuxAssetHandlerArgs {
6
+ getMuxClient: () => Mux$1;
7
+ }
8
+ declare function getMuxAssetHandler(args: GetMuxAssetHandlerArgs): PayloadHandler;
9
+ //#endregion
10
+ export { getMuxAssetHandler };
11
+ //# sourceMappingURL=muxAssetHandler.d.ts.map
@@ -0,0 +1,59 @@
1
+ //#region src/endpoints/muxAssetHandler.ts
2
+ function getMuxAssetHandler(args) {
3
+ const { getMuxClient } = args;
4
+ return async (req) => {
5
+ try {
6
+ const mux = getMuxClient();
7
+ const { query } = req;
8
+ const uploadId = query.upload_id;
9
+ if (!uploadId) return Response.json({ message: "Upload ID is required" }, { status: 400 });
10
+ const assets = await mux.video.assets.list({
11
+ limit: 1,
12
+ upload_id: uploadId
13
+ });
14
+ const asset = assets?.data[0];
15
+ if (!asset) return Response.json({ message: "No asset found for the given upload ID" }, { status: 404 });
16
+ if (asset.status === "ready") {
17
+ const { payload } = req;
18
+ const { docs } = await payload.find({
19
+ collection: "media",
20
+ where: { "mux.uploadId": { equals: uploadId } },
21
+ limit: 1,
22
+ pagination: false
23
+ });
24
+ if (docs.length > 0) {
25
+ if (asset?.status === "ready") {
26
+ const { id } = docs[0];
27
+ await payload.update({
28
+ collection: "media",
29
+ id,
30
+ data: { mux: {
31
+ status: asset.status,
32
+ assetId: asset.id,
33
+ playbackId: asset.playback_ids?.[0]?.id,
34
+ aspectRatio: asset.aspect_ratio,
35
+ duration: asset.duration,
36
+ maxResolutionTier: asset.max_resolution_tier,
37
+ videoQuality: asset.video_quality,
38
+ staticRenditions: asset.static_renditions
39
+ } }
40
+ });
41
+ }
42
+ }
43
+ return Response.json({
44
+ ready: asset.status === "ready",
45
+ asset
46
+ }, { status: 200 });
47
+ } else return Response.json({
48
+ ready: false,
49
+ asset
50
+ }, { status: 200 });
51
+ } catch (_error) {
52
+ return Response.json({ message: "Failed to fetch Mux asset" }, { status: 500 });
53
+ }
54
+ };
55
+ }
56
+
57
+ //#endregion
58
+ export { getMuxAssetHandler };
59
+ //# sourceMappingURL=muxAssetHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxAssetHandler.js","names":["args: GetMuxAssetHandlerArgs"],"sources":["../../src/endpoints/muxAssetHandler.ts"],"sourcesContent":["import type { Mux } from '@mux/mux-node'\n\nimport type { PayloadHandler } from 'payload'\nimport type { StaticRenditions } from '../types'\n\ninterface GetMuxAssetHandlerArgs {\n getMuxClient: () => Mux\n}\n\nexport function getMuxAssetHandler(\n args: GetMuxAssetHandlerArgs\n): PayloadHandler {\n const { getMuxClient } = args\n\n return async (req) => {\n try {\n const mux = getMuxClient()\n const { query } = req\n\n const uploadId = query.upload_id as string\n\n if (!uploadId) {\n return Response.json(\n { message: 'Upload ID is required' },\n { status: 400 }\n )\n }\n\n const assets = await mux.video.assets.list({\n limit: 1,\n upload_id: uploadId,\n })\n\n const asset = assets?.data[0]\n\n if (!asset) {\n return Response.json(\n { message: 'No asset found for the given upload ID' },\n { status: 404 }\n )\n }\n\n if (asset.status === 'ready') {\n const { payload } = req\n\n const { docs } = await payload.find({\n collection: 'media',\n where: {\n 'mux.uploadId': {\n equals: uploadId,\n },\n },\n limit: 1,\n pagination: false,\n })\n\n if (docs.length > 0) {\n if (asset?.status === 'ready') {\n const { id } = docs[0]\n await payload.update({\n collection: 'media',\n id,\n data: {\n mux: {\n status: asset.status,\n assetId: asset.id,\n playbackId: asset.playback_ids?.[0]?.id,\n aspectRatio: asset.aspect_ratio,\n duration: asset.duration,\n maxResolutionTier: asset.max_resolution_tier,\n videoQuality: asset.video_quality,\n staticRenditions: asset.static_renditions as StaticRenditions,\n },\n },\n })\n }\n }\n return Response.json(\n {\n ready: asset.status === 'ready',\n asset,\n },\n { status: 200 }\n )\n } else {\n return Response.json(\n {\n ready: false,\n asset,\n },\n { status: 200 }\n )\n }\n } catch (_error) {\n return Response.json(\n { message: 'Failed to fetch Mux asset' },\n { status: 500 }\n )\n }\n }\n}\n"],"mappings":";AASA,SAAgB,mBACdA,MACgB;CAChB,MAAM,EAAE,cAAc,GAAG;AAEzB,QAAO,OAAO,QAAQ;AACpB,MAAI;GACF,MAAM,MAAM,cAAc;GAC1B,MAAM,EAAE,OAAO,GAAG;GAElB,MAAM,WAAW,MAAM;AAEvB,OAAI,CAAC,SACH,QAAO,SAAS,KACd,EAAE,SAAS,wBAAyB,GACpC,EAAE,QAAQ,IAAK,EAChB;GAGH,MAAM,SAAS,MAAM,IAAI,MAAM,OAAO,KAAK;IACzC,OAAO;IACP,WAAW;GACZ,EAAC;GAEF,MAAM,QAAQ,QAAQ,KAAK;AAE3B,OAAI,CAAC,MACH,QAAO,SAAS,KACd,EAAE,SAAS,yCAA0C,GACrD,EAAE,QAAQ,IAAK,EAChB;AAGH,OAAI,MAAM,WAAW,SAAS;IAC5B,MAAM,EAAE,SAAS,GAAG;IAEpB,MAAM,EAAE,MAAM,GAAG,MAAM,QAAQ,KAAK;KAClC,YAAY;KACZ,OAAO,EACL,gBAAgB,EACd,QAAQ,SACT,EACF;KACD,OAAO;KACP,YAAY;IACb,EAAC;AAEF,QAAI,KAAK,SAAS,GAChB;SAAI,OAAO,WAAW,SAAS;MAC7B,MAAM,EAAE,IAAI,GAAG,KAAK;MACpB,MAAM,QAAQ,OAAO;OACnB,YAAY;OACZ;OACA,MAAM,EACJ,KAAK;QACH,QAAQ,MAAM;QACd,SAAS,MAAM;QACf,YAAY,MAAM,eAAe,IAAI;QACrC,aAAa,MAAM;QACnB,UAAU,MAAM;QAChB,mBAAmB,MAAM;QACzB,cAAc,MAAM;QACpB,kBAAkB,MAAM;OACzB,EACF;MACF,EAAC;KACH;;AAEH,WAAO,SAAS,KACd;KACE,OAAO,MAAM,WAAW;KACxB;IACD,GACD,EAAE,QAAQ,IAAK,EAChB;GACF,MACC,QAAO,SAAS,KACd;IACE,OAAO;IACP;GACD,GACD,EAAE,QAAQ,IAAK,EAChB;EAEJ,SAAQ,QAAQ;AACf,UAAO,SAAS,KACd,EAAE,SAAS,4BAA6B,GACxC,EAAE,QAAQ,IAAK,EAChB;EACF;CACF;AACF"}
@@ -0,0 +1,13 @@
1
+ import { MediaCloudPluginOptions } from "../types/index.js";
2
+ import { Mux as Mux$1 } from "@mux/mux-node";
3
+ import { PayloadHandler } from "payload";
4
+
5
+ //#region src/endpoints/muxCreateUploadHandler.d.ts
6
+ interface GetMuxCreateUploadHandlerArgs {
7
+ getMuxClient: () => Mux$1;
8
+ pluginOptions: MediaCloudPluginOptions;
9
+ }
10
+ declare function getMuxCreateUploadHandler(args: GetMuxCreateUploadHandlerArgs): PayloadHandler;
11
+ //#endregion
12
+ export { getMuxCreateUploadHandler };
13
+ //# sourceMappingURL=muxCreateUploadHandler.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { MediaCloudError } from "../types/errors.js";
2
+ import { useErrorHandler } from "../hooks/useErrorHandler.js";
3
+
4
+ //#region src/endpoints/muxCreateUploadHandler.ts
5
+ function getMuxCreateUploadHandler(args) {
6
+ const { getMuxClient, pluginOptions } = args;
7
+ return async (req) => {
8
+ const { throwError, logError } = useErrorHandler();
9
+ try {
10
+ if (!req.json) {
11
+ throwError(MediaCloudError.MUX_REQUEST_NO_JSON);
12
+ throw new Error();
13
+ }
14
+ const body = req.json ? await req.json() : "";
15
+ const { filename } = body;
16
+ const mux = getMuxClient();
17
+ const assetOptions = pluginOptions.mux?.assetOptions || {};
18
+ const upload = await mux.video.uploads.create({
19
+ cors_origin: "*",
20
+ new_asset_settings: {
21
+ playback_policies: ["public"],
22
+ meta: { title: filename },
23
+ ...assetOptions
24
+ },
25
+ test: pluginOptions.mux?.testMode ?? true
26
+ });
27
+ return Response.json({
28
+ url: upload.url,
29
+ uploadId: upload.id
30
+ });
31
+ } catch (_error) {
32
+ logError(MediaCloudError.MUX_CREATE_UPLOAD_ERROR);
33
+ return Response.json({ message: "Failed to create upload" }, { status: 500 });
34
+ }
35
+ };
36
+ }
37
+
38
+ //#endregion
39
+ export { getMuxCreateUploadHandler };
40
+ //# sourceMappingURL=muxCreateUploadHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxCreateUploadHandler.js","names":["args: GetMuxCreateUploadHandlerArgs"],"sources":["../../src/endpoints/muxCreateUploadHandler.ts"],"sourcesContent":["import type { Mux } from '@mux/mux-node'\n\nimport type { PayloadHandler } from 'payload'\nimport { MediaCloudPluginOptions } from '../types'\nimport { useErrorHandler } from '../hooks/useErrorHandler'\nimport { MediaCloudError } from '../types/errors'\n\ninterface GetMuxCreateUploadHandlerArgs {\n getMuxClient: () => Mux\n pluginOptions: MediaCloudPluginOptions\n}\n\nexport function getMuxCreateUploadHandler(\n args: GetMuxCreateUploadHandlerArgs\n): PayloadHandler {\n const { getMuxClient, pluginOptions } = args\n\n return async (req) => {\n const { throwError, logError } = useErrorHandler()\n\n try {\n if (!req.json) {\n throwError(MediaCloudError.MUX_REQUEST_NO_JSON)\n throw new Error() // This will never execute but satisfies TypeScript\n }\n const body = req.json ? await req.json() : ''\n const { filename } = body\n const mux = getMuxClient()\n const assetOptions = pluginOptions.mux?.assetOptions || {}\n const upload = await mux.video.uploads.create({\n cors_origin: '*',\n new_asset_settings: {\n playback_policies: ['public'],\n meta: {\n title: filename,\n },\n ...assetOptions,\n },\n test: pluginOptions.mux?.testMode ?? true,\n })\n return Response.json({ url: upload.url, uploadId: upload.id })\n } catch (_error) {\n logError(MediaCloudError.MUX_CREATE_UPLOAD_ERROR)\n return Response.json(\n { message: 'Failed to create upload' },\n { status: 500 }\n )\n }\n }\n}\n"],"mappings":";;;;AAYA,SAAgB,0BACdA,MACgB;CAChB,MAAM,EAAE,cAAc,eAAe,GAAG;AAExC,QAAO,OAAO,QAAQ;EACpB,MAAM,EAAE,YAAY,UAAU,GAAG,iBAAiB;AAElD,MAAI;AACF,OAAI,CAAC,IAAI,MAAM;IACb,WAAW,gBAAgB,oBAAoB;AAC/C,UAAM,IAAI;GACX;GACD,MAAM,OAAO,IAAI,OAAO,MAAM,IAAI,MAAM,GAAG;GAC3C,MAAM,EAAE,UAAU,GAAG;GACrB,MAAM,MAAM,cAAc;GAC1B,MAAM,eAAe,cAAc,KAAK,gBAAgB,CAAE;GAC1D,MAAM,SAAS,MAAM,IAAI,MAAM,QAAQ,OAAO;IAC5C,aAAa;IACb,oBAAoB;KAClB,mBAAmB,CAAC,QAAS;KAC7B,MAAM,EACJ,OAAO,SACR;KACD,GAAG;IACJ;IACD,MAAM,cAAc,KAAK,YAAY;GACtC,EAAC;AACF,UAAO,SAAS,KAAK;IAAE,KAAK,OAAO;IAAK,UAAU,OAAO;GAAI,EAAC;EAC/D,SAAQ,QAAQ;GACf,SAAS,gBAAgB,wBAAwB;AACjD,UAAO,SAAS,KACd,EAAE,SAAS,0BAA2B,GACtC,EAAE,QAAQ,IAAK,EAChB;EACF;CACF;AACF"}
@@ -0,0 +1,11 @@
1
+ import { Mux as Mux$1 } from "@mux/mux-node";
2
+ import { PayloadHandler } from "payload";
3
+
4
+ //#region src/endpoints/muxWebhookHandler.d.ts
5
+ interface GetMuxWebhookHandlerArgs {
6
+ getMuxClient: () => Mux$1;
7
+ }
8
+ declare function getMuxWebhookHandler(args: GetMuxWebhookHandlerArgs): PayloadHandler;
9
+ //#endregion
10
+ export { getMuxWebhookHandler };
11
+ //# sourceMappingURL=muxWebhookHandler.d.ts.map
@@ -0,0 +1,49 @@
1
+ //#region src/endpoints/muxWebhookHandler.ts
2
+ function getMuxWebhookHandler(args) {
3
+ const { getMuxClient } = args;
4
+ return async (req) => {
5
+ const mux = getMuxClient();
6
+ try {
7
+ const body = req.json ? await req.json() : "";
8
+ const headers = req.headers;
9
+ mux.webhooks.verifySignature(body, headers);
10
+ const event = JSON.parse(body);
11
+ console.log(`Received webhook event: ${event.type}`);
12
+ switch (event.type) {
13
+ case "video.asset.created":
14
+ console.log(`Asset created: ${event.object.id}`);
15
+ break;
16
+ case "video.asset.ready":
17
+ await updateMuxAsset(event.object.id, req.payload);
18
+ break;
19
+ case "video.asset.errored":
20
+ console.log(`Asset errored: ${event.object.id}`);
21
+ break;
22
+ case "video.asset.deleted":
23
+ console.log(`Asset deleted: ${event.object.id}`);
24
+ break;
25
+ case "video.asset.static_renditions.ready":
26
+ await updateMuxAsset(event.object.id, req.payload);
27
+ console.log(`Static renditions ready: ${event.object.id}`);
28
+ break;
29
+ case "video.asset.static_renditions.deleted":
30
+ console.log(`Static renditions deleted: ${event.object.id}`);
31
+ break;
32
+ default:
33
+ console.log(`Unknown event type: ${event.type}`);
34
+ break;
35
+ }
36
+ return Response.json({ message: "Webhook received" }, { status: 200 });
37
+ } catch (error) {
38
+ return Response.json({ message: error instanceof Error ? error.message : String(error) }, { status: 500 });
39
+ }
40
+ };
41
+ }
42
+ async function updateMuxAsset(asset, payload) {
43
+ console.log(`Updating Mux asset with ID: ${asset.id}`);
44
+ console.log(`Asset status: ${payload}`);
45
+ }
46
+
47
+ //#endregion
48
+ export { getMuxWebhookHandler };
49
+ //# sourceMappingURL=muxWebhookHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxWebhookHandler.js","names":["args: GetMuxWebhookHandlerArgs","asset: Mux.Video.Asset","payload: BasePayload"],"sources":["../../src/endpoints/muxWebhookHandler.ts"],"sourcesContent":["import type { Mux } from '@mux/mux-node'\n\nimport type { BasePayload, PayloadHandler } from 'payload'\n\ninterface GetMuxWebhookHandlerArgs {\n getMuxClient: () => Mux\n}\n\nexport function getMuxWebhookHandler(\n args: GetMuxWebhookHandlerArgs\n): PayloadHandler {\n const { getMuxClient } = args\n\n return async (req) => {\n const mux = getMuxClient()\n\n try {\n const body = req.json ? await req.json() : ''\n const headers = req.headers\n\n // Verify the webhook signature\n mux.webhooks.verifySignature(body, headers)\n\n // Parse the request body\n const event = JSON.parse(body)\n\n // Handle the event\n console.log(`Received webhook event: ${event.type}`)\n\n switch (event.type) {\n case 'video.asset.created':\n console.log(`Asset created: ${event.object.id}`)\n break\n case 'video.asset.ready':\n await updateMuxAsset(event.object.id, req.payload)\n break\n case 'video.asset.errored':\n console.log(`Asset errored: ${event.object.id}`)\n break\n case 'video.asset.deleted':\n console.log(`Asset deleted: ${event.object.id}`)\n break\n case 'video.asset.static_renditions.ready':\n await updateMuxAsset(event.object.id, req.payload)\n console.log(`Static renditions ready: ${event.object.id}`)\n break\n case 'video.asset.static_renditions.deleted':\n console.log(`Static renditions deleted: ${event.object.id}`)\n break\n default:\n console.log(`Unknown event type: ${event.type}`)\n break\n }\n\n return Response.json(\n {\n message: 'Webhook received',\n },\n { status: 200 }\n )\n } catch (error) {\n return Response.json(\n {\n message: error instanceof Error ? error.message : String(error),\n },\n {\n status: 500,\n }\n )\n }\n }\n}\n\nasync function updateMuxAsset(\n asset: Mux.Video.Asset,\n payload: BasePayload\n): Promise<void> {\n console.log(`Updating Mux asset with ID: ${asset.id}`)\n console.log(`Asset status: ${payload}`)\n}\n"],"mappings":";AAQA,SAAgB,qBACdA,MACgB;CAChB,MAAM,EAAE,cAAc,GAAG;AAEzB,QAAO,OAAO,QAAQ;EACpB,MAAM,MAAM,cAAc;AAE1B,MAAI;GACF,MAAM,OAAO,IAAI,OAAO,MAAM,IAAI,MAAM,GAAG;GAC3C,MAAM,UAAU,IAAI;GAGpB,IAAI,SAAS,gBAAgB,MAAM,QAAQ;GAG3C,MAAM,QAAQ,KAAK,MAAM,KAAK;GAG9B,QAAQ,IAAI,CAAC,wBAAwB,EAAE,MAAM,MAAM,CAAC;AAEpD,WAAQ,MAAM,MAAd;IACE,KAAK;KACH,QAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,OAAO,IAAI,CAAC;AAChD;IACF,KAAK;KACH,MAAM,eAAe,MAAM,OAAO,IAAI,IAAI,QAAQ;AAClD;IACF,KAAK;KACH,QAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,OAAO,IAAI,CAAC;AAChD;IACF,KAAK;KACH,QAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,OAAO,IAAI,CAAC;AAChD;IACF,KAAK;KACH,MAAM,eAAe,MAAM,OAAO,IAAI,IAAI,QAAQ;KAClD,QAAQ,IAAI,CAAC,yBAAyB,EAAE,MAAM,OAAO,IAAI,CAAC;AAC1D;IACF,KAAK;KACH,QAAQ,IAAI,CAAC,2BAA2B,EAAE,MAAM,OAAO,IAAI,CAAC;AAC5D;IACF;KACE,QAAQ,IAAI,CAAC,oBAAoB,EAAE,MAAM,MAAM,CAAC;AAChD;GACH;AAED,UAAO,SAAS,KACd,EACE,SAAS,mBACV,GACD,EAAE,QAAQ,IAAK,EAChB;EACF,SAAQ,OAAO;AACd,UAAO,SAAS,KACd,EACE,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAChE,GACD,EACE,QAAQ,IACT,EACF;EACF;CACF;AACF;AAED,eAAe,eACbC,OACAC,SACe;CACf,QAAQ,IAAI,CAAC,4BAA4B,EAAE,MAAM,IAAI,CAAC;CACtD,QAAQ,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;AACxC"}
@@ -0,0 +1,48 @@
1
+ import { MediaCloudError } from "../types/errors.js";
2
+ import * as mitt0 from "mitt";
3
+
4
+ //#region src/hooks/useEmitter.d.ts
5
+ type EmitterEvents = {
6
+ 'add-upload': {
7
+ id: string;
8
+ filename: string;
9
+ polling?: boolean;
10
+ pollingUrl?: string;
11
+ };
12
+ 'update-upload': {
13
+ id: string;
14
+ progress: number;
15
+ };
16
+ 'remove-upload': {
17
+ id: string;
18
+ };
19
+ 'upload-completed': {
20
+ id: string;
21
+ };
22
+ 'upload-error': {
23
+ id: string;
24
+ error: MediaCloudError;
25
+ };
26
+ };
27
+ declare const emitter: mitt0.Emitter<EmitterEvents>;
28
+ /**
29
+ * Hook to access the global event emitter for upload management
30
+ * @returns An object with emitter methods (on, off, emit)
31
+ */
32
+ declare function useEmitter(): {
33
+ on: {
34
+ <Key extends keyof EmitterEvents>(type: Key, handler: mitt0.Handler<EmitterEvents[Key]>): void;
35
+ (type: "*", handler: mitt0.WildcardHandler<EmitterEvents>): void;
36
+ };
37
+ off: {
38
+ <Key extends keyof EmitterEvents>(type: Key, handler?: mitt0.Handler<EmitterEvents[Key]> | undefined): void;
39
+ (type: "*", handler: mitt0.WildcardHandler<EmitterEvents>): void;
40
+ };
41
+ emit: {
42
+ <Key extends keyof EmitterEvents>(type: Key, event: EmitterEvents[Key]): void;
43
+ <Key extends keyof EmitterEvents>(type: undefined extends EmitterEvents[Key] ? Key : never): void;
44
+ };
45
+ };
46
+ //#endregion
47
+ export { emitter, useEmitter };
48
+ //# sourceMappingURL=useEmitter.d.ts.map
@@ -0,0 +1,19 @@
1
+ import mitt from "mitt";
2
+
3
+ //#region src/hooks/useEmitter.ts
4
+ const emitter = mitt();
5
+ /**
6
+ * Hook to access the global event emitter for upload management
7
+ * @returns An object with emitter methods (on, off, emit)
8
+ */
9
+ function useEmitter() {
10
+ return {
11
+ on: emitter.on,
12
+ off: emitter.off,
13
+ emit: emitter.emit
14
+ };
15
+ }
16
+
17
+ //#endregion
18
+ export { emitter, useEmitter };
19
+ //# sourceMappingURL=useEmitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEmitter.js","names":[],"sources":["../../src/hooks/useEmitter.ts"],"sourcesContent":["import mitt from 'mitt'\nimport { MediaCloudError } from '../types/errors'\n\ntype EmitterEvents = {\n 'add-upload': {\n id: string\n filename: string\n polling?: boolean\n pollingUrl?: string\n }\n 'update-upload': { id: string; progress: number }\n 'remove-upload': { id: string }\n 'upload-completed': { id: string }\n 'upload-error': { id: string; error: MediaCloudError }\n}\n\nconst emitter = mitt<EmitterEvents>()\n\n/**\n * Hook to access the global event emitter for upload management\n * @returns An object with emitter methods (on, off, emit)\n */\nfunction useEmitter() {\n return {\n on: emitter.on,\n off: emitter.off,\n emit: emitter.emit,\n }\n}\n\nexport { useEmitter, emitter }\n"],"mappings":";;;AAgBA,MAAM,UAAU,MAAqB;;;;;AAMrC,SAAS,aAAa;AACpB,QAAO;EACL,IAAI,QAAQ;EACZ,KAAK,QAAQ;EACb,MAAM,QAAQ;CACf;AACF"}