@maas/payload-plugin-media-cloud 0.0.27 → 0.0.29
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.
- package/dist/adapter/handleUpload.d.mts +1 -0
- package/dist/adapter/handleUpload.mjs +12 -7
- package/dist/adapter/handleUpload.mjs.map +1 -1
- package/dist/collections/mediaCollection.mjs +1 -28
- package/dist/collections/mediaCollection.mjs.map +1 -1
- package/dist/components/upload-handler/upload-handler.d.mts +3 -3
- package/dist/components/upload-handler/upload-handler.mjs +2 -6
- package/dist/components/upload-handler/upload-handler.mjs.map +1 -1
- package/dist/endpoints/tusCleanupHandler.mjs +1 -1
- package/dist/endpoints/tusCleanupHandler.mjs.map +1 -1
- package/dist/utils/mux.d.mts +3 -3
- package/dist/utils/tus.d.mts +3 -3
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { HandleUpload } from "@payloadcms/plugin-cloud-storage/types";
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Creates a handle upload function for processing file uploads to both Mux and S3 storage
|
|
7
|
+
* Since PayloadCMS 3.70.0, this runs in afterChange hook, so we need to update the document
|
|
7
8
|
* @returns A HandleUpload function that processes client upload context and updates document data
|
|
8
9
|
*/
|
|
9
10
|
declare function getHandleUpload(): HandleUpload;
|
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
//#region src/adapter/handleUpload.ts
|
|
2
2
|
/**
|
|
3
3
|
* Creates a handle upload function for processing file uploads to both Mux and S3 storage
|
|
4
|
+
* Since PayloadCMS 3.70.0, this runs in afterChange hook, so we need to update the document
|
|
4
5
|
* @returns A HandleUpload function that processes client upload context and updates document data
|
|
5
6
|
*/
|
|
6
7
|
function getHandleUpload() {
|
|
7
|
-
return async function({ clientUploadContext, data }) {
|
|
8
|
-
if (!clientUploadContext) return
|
|
8
|
+
return async function({ clientUploadContext, data, collection, req }) {
|
|
9
|
+
if (!clientUploadContext) return;
|
|
9
10
|
const ctx = clientUploadContext;
|
|
10
|
-
|
|
11
|
+
const updateData = { mimeType: ctx.mimeType };
|
|
11
12
|
switch (ctx.storage) {
|
|
12
13
|
case "mux":
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
updateData.storage = "mux";
|
|
15
|
+
updateData.mux = {
|
|
15
16
|
uploadId: ctx.uploadId ?? "",
|
|
16
17
|
status: "preparing"
|
|
17
18
|
};
|
|
18
19
|
break;
|
|
19
20
|
default:
|
|
20
|
-
|
|
21
|
+
updateData.storage = "s3";
|
|
21
22
|
break;
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
+
await req.payload.update({
|
|
25
|
+
collection: collection.slug,
|
|
26
|
+
id: data.id,
|
|
27
|
+
data: updateData
|
|
28
|
+
});
|
|
24
29
|
};
|
|
25
30
|
}
|
|
26
31
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleUpload.mjs","names":[],"sources":["../../src/adapter/handleUpload.ts"],"sourcesContent":["import type { HandleUpload } from '@payloadcms/plugin-cloud-storage/types'\n\ninterface ClientUploadContext {\n storage: 'mux' | 's3'\n uploadId?: string\n mimeType?: string\n}\n\n/**\n * Creates a handle upload function for processing file uploads to both Mux and S3 storage\n * @returns A HandleUpload function that processes client upload context and updates document data\n */\nexport function getHandleUpload(): HandleUpload {\n return async function ({ clientUploadContext, data }) {\n if (!clientUploadContext) {\n return
|
|
1
|
+
{"version":3,"file":"handleUpload.mjs","names":["updateData: Record<string, any>"],"sources":["../../src/adapter/handleUpload.ts"],"sourcesContent":["import type { HandleUpload } from '@payloadcms/plugin-cloud-storage/types'\n\ninterface ClientUploadContext {\n storage: 'mux' | 's3'\n uploadId?: string\n mimeType?: string\n}\n\n/**\n * Creates a handle upload function for processing file uploads to both Mux and S3 storage\n * Since PayloadCMS 3.70.0, this runs in afterChange hook, so we need to update the document\n * @returns A HandleUpload function that processes client upload context and updates document data\n */\nexport function getHandleUpload(): HandleUpload {\n return async function ({ clientUploadContext, data, collection, req }) {\n if (!clientUploadContext) {\n return\n }\n\n const ctx = clientUploadContext as ClientUploadContext\n\n // Prepare the update data\n const updateData: Record<string, any> = {\n mimeType: ctx.mimeType,\n }\n\n switch (ctx.storage) {\n case 'mux':\n updateData.storage = 'mux'\n updateData.mux = {\n uploadId: ctx.uploadId ?? '',\n status: 'preparing',\n }\n break\n default:\n updateData.storage = 's3'\n break\n }\n\n // Update the document in the database since afterChange hook runs after save\n await req.payload.update({\n collection: collection.slug,\n id: data.id,\n data: updateData,\n })\n }\n}\n"],"mappings":";;;;;;AAaA,SAAgB,kBAAgC;AAC9C,QAAO,eAAgB,EAAE,qBAAqB,MAAM,YAAY,OAAO;AACrE,MAAI,CAAC,oBACH;EAGF,MAAM,MAAM;EAGZ,MAAMA,aAAkC,EACtC,UAAU,IAAI,UACf;AAED,UAAQ,IAAI,SAAZ;GACE,KAAK;AACH,eAAW,UAAU;AACrB,eAAW,MAAM;KACf,UAAU,IAAI,YAAY;KAC1B,QAAQ;KACT;AACD;GACF;AACE,eAAW,UAAU;AACrB;;AAIJ,QAAM,IAAI,QAAQ,OAAO;GACvB,YAAY,WAAW;GACvB,IAAI,KAAK;GACT,MAAM;GACP,CAAC"}
|
|
@@ -150,34 +150,7 @@ function getMediaCollection(args) {
|
|
|
150
150
|
{
|
|
151
151
|
name: "staticRenditions",
|
|
152
152
|
label: "Static Renditions",
|
|
153
|
-
type: "json"
|
|
154
|
-
typescriptSchema: [({ jsonSchema }) => ({
|
|
155
|
-
...jsonSchema,
|
|
156
|
-
type: "object",
|
|
157
|
-
properties: { files: {
|
|
158
|
-
type: "array",
|
|
159
|
-
items: {
|
|
160
|
-
type: "object",
|
|
161
|
-
properties: {
|
|
162
|
-
width: { type: "number" },
|
|
163
|
-
name: { type: "string" },
|
|
164
|
-
height: { type: "number" },
|
|
165
|
-
filesize: { type: "string" },
|
|
166
|
-
ext: { type: "string" },
|
|
167
|
-
bitrate: { type: "number" }
|
|
168
|
-
},
|
|
169
|
-
required: [
|
|
170
|
-
"width",
|
|
171
|
-
"name",
|
|
172
|
-
"height",
|
|
173
|
-
"filesize",
|
|
174
|
-
"ext",
|
|
175
|
-
"bitrate"
|
|
176
|
-
]
|
|
177
|
-
}
|
|
178
|
-
} },
|
|
179
|
-
required: ["files"]
|
|
180
|
-
})]
|
|
153
|
+
type: "json"
|
|
181
154
|
}
|
|
182
155
|
]
|
|
183
156
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediaCollection.mjs","names":["config: CollectionConfig"],"sources":["../../src/collections/mediaCollection.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\nimport type { Document } from 'payload'\nimport type { S3Store } from './../tus/stores/s3/s3-store'\n\ninterface GetMediaCollectionArgs {\n s3Store: S3Store\n baseCollection?: CollectionConfig\n}\n\n/**\n * Creates a media collection configuration for Payload CMS\n * @param args - Arguments including the S3Store instance\n * @returns A configured Payload collection for media files\n */\nexport function getMediaCollection(\n args: GetMediaCollectionArgs\n): CollectionConfig {\n const { s3Store, baseCollection } = args\n\n const config: CollectionConfig = {\n slug: 'media',\n access: {\n read: () => true,\n delete: () => true,\n },\n admin: {\n group: 'Media Cloud',\n pagination: {\n defaultLimit: 50,\n },\n },\n upload: {\n crop: false,\n displayPreview: true,\n hideRemoveFile: true,\n adminThumbnail({ doc }: { doc: Document }) {\n if (doc?.storage === 'mux' && doc?.mux?.playbackId) {\n return `https://image.mux.com/${doc.mux.playbackId}/thumbnail.jpg?width=200&height=200&fit_mode=pad`\n } else if (doc?.storage === 's3') {\n // @TODO: Make configurable\n const url = s3Store.getUrl(doc.filename)\n return `https://wsrv.nl/?url=${url}?width=200&height=200&default=1`\n }\n return null\n },\n },\n fields: [\n {\n name: 'alt',\n label: 'Alternative Text',\n type: 'text',\n },\n {\n name: 'caption',\n label: 'Caption',\n type: 'text',\n },\n {\n name: 'copyright',\n label: 'Copyright',\n type: 'text',\n },\n {\n type: 'row',\n fields: [\n {\n name: 'width',\n label: 'Width',\n type: 'text',\n admin: {\n readOnly: true,\n hidden: false,\n width: '50%',\n },\n },\n {\n name: 'height',\n label: 'Height',\n type: 'number',\n admin: {\n readOnly: true,\n hidden: false,\n width: '50%',\n },\n },\n ],\n },\n {\n name: 'storage',\n label: 'Storage',\n type: 'select',\n options: [\n {\n label: 'Mux',\n value: 'mux',\n },\n {\n label: 'S3',\n value: 's3',\n },\n ],\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'mux',\n label: 'Mux',\n type: 'group',\n admin: {\n disableListColumn: true,\n disableBulkEdit: true,\n disableListFilter: true,\n readOnly: true,\n condition: (data) => {\n return data.storage === 'mux'\n },\n },\n fields: [\n {\n name: 'preview',\n type: 'ui',\n admin: {\n condition: (data) => {\n return data.storage === 'mux'\n },\n disableListColumn: true,\n components: {\n Field: '@maas/payload-plugin-media-cloud/components#MuxPreview',\n },\n },\n },\n {\n name: 'status',\n label: 'Status',\n type: 'text',\n },\n {\n name: 'uploadId',\n label: 'Upload ID',\n type: 'text',\n },\n {\n name: 'assetId',\n label: 'Asset ID',\n type: 'text',\n },\n {\n name: 'playbackId',\n label: 'Playback ID',\n type: 'text',\n },\n {\n name: 'aspectRatio',\n label: 'Aspect Ratio',\n type: 'text',\n },\n {\n name: 'duration',\n label: 'Duration',\n type: 'number',\n },\n {\n name: 'tracks',\n label: 'Tracks',\n type: 'json',\n },\n {\n name: 'maxResolutionTier',\n label: 'Max Resolution Tier',\n type: 'text',\n },\n {\n name: 'videoQuality',\n label: 'Video Quality',\n type: 'text',\n },\n {\n name: 'staticRenditions',\n label: 'Static Renditions',\n type: 'json',\n
|
|
1
|
+
{"version":3,"file":"mediaCollection.mjs","names":["config: CollectionConfig"],"sources":["../../src/collections/mediaCollection.ts"],"sourcesContent":["import type { CollectionConfig } from 'payload'\nimport type { Document } from 'payload'\nimport type { S3Store } from './../tus/stores/s3/s3-store'\n\ninterface GetMediaCollectionArgs {\n s3Store: S3Store\n baseCollection?: CollectionConfig\n}\n\n/**\n * Creates a media collection configuration for Payload CMS\n * @param args - Arguments including the S3Store instance\n * @returns A configured Payload collection for media files\n */\nexport function getMediaCollection(\n args: GetMediaCollectionArgs\n): CollectionConfig {\n const { s3Store, baseCollection } = args\n\n const config: CollectionConfig = {\n slug: 'media',\n access: {\n read: () => true,\n delete: () => true,\n },\n admin: {\n group: 'Media Cloud',\n pagination: {\n defaultLimit: 50,\n },\n },\n upload: {\n crop: false,\n displayPreview: true,\n hideRemoveFile: true,\n adminThumbnail({ doc }: { doc: Document }) {\n if (doc?.storage === 'mux' && doc?.mux?.playbackId) {\n return `https://image.mux.com/${doc.mux.playbackId}/thumbnail.jpg?width=200&height=200&fit_mode=pad`\n } else if (doc?.storage === 's3') {\n // @TODO: Make configurable\n const url = s3Store.getUrl(doc.filename)\n return `https://wsrv.nl/?url=${url}?width=200&height=200&default=1`\n }\n return null\n },\n },\n fields: [\n {\n name: 'alt',\n label: 'Alternative Text',\n type: 'text',\n },\n {\n name: 'caption',\n label: 'Caption',\n type: 'text',\n },\n {\n name: 'copyright',\n label: 'Copyright',\n type: 'text',\n },\n {\n type: 'row',\n fields: [\n {\n name: 'width',\n label: 'Width',\n type: 'text',\n admin: {\n readOnly: true,\n hidden: false,\n width: '50%',\n },\n },\n {\n name: 'height',\n label: 'Height',\n type: 'number',\n admin: {\n readOnly: true,\n hidden: false,\n width: '50%',\n },\n },\n ],\n },\n {\n name: 'storage',\n label: 'Storage',\n type: 'select',\n options: [\n {\n label: 'Mux',\n value: 'mux',\n },\n {\n label: 'S3',\n value: 's3',\n },\n ],\n admin: {\n readOnly: true,\n },\n },\n {\n name: 'mux',\n label: 'Mux',\n type: 'group',\n admin: {\n disableListColumn: true,\n disableBulkEdit: true,\n disableListFilter: true,\n readOnly: true,\n condition: (data) => {\n return data.storage === 'mux'\n },\n },\n fields: [\n {\n name: 'preview',\n type: 'ui',\n admin: {\n condition: (data) => {\n return data.storage === 'mux'\n },\n disableListColumn: true,\n components: {\n Field: '@maas/payload-plugin-media-cloud/components#MuxPreview',\n },\n },\n },\n {\n name: 'status',\n label: 'Status',\n type: 'text',\n },\n {\n name: 'uploadId',\n label: 'Upload ID',\n type: 'text',\n },\n {\n name: 'assetId',\n label: 'Asset ID',\n type: 'text',\n },\n {\n name: 'playbackId',\n label: 'Playback ID',\n type: 'text',\n },\n {\n name: 'aspectRatio',\n label: 'Aspect Ratio',\n type: 'text',\n },\n {\n name: 'duration',\n label: 'Duration',\n type: 'number',\n },\n {\n name: 'tracks',\n label: 'Tracks',\n type: 'json',\n },\n {\n name: 'maxResolutionTier',\n label: 'Max Resolution Tier',\n type: 'text',\n },\n {\n name: 'videoQuality',\n label: 'Video Quality',\n type: 'text',\n },\n {\n name: 'staticRenditions',\n label: 'Static Renditions',\n type: 'json',\n },\n ],\n },\n ],\n }\n\n // Simple merge: if baseCollection exists, spread it first, then our config overrides\n if (!baseCollection) {\n return config\n }\n\n return {\n ...baseCollection,\n ...config,\n fields: [...(baseCollection.fields || []), ...config.fields],\n }\n}\n"],"mappings":";;;;;;AAcA,SAAgB,mBACd,MACkB;CAClB,MAAM,EAAE,SAAS,mBAAmB;CAEpC,MAAMA,SAA2B;EAC/B,MAAM;EACN,QAAQ;GACN,YAAY;GACZ,cAAc;GACf;EACD,OAAO;GACL,OAAO;GACP,YAAY,EACV,cAAc,IACf;GACF;EACD,QAAQ;GACN,MAAM;GACN,gBAAgB;GAChB,gBAAgB;GAChB,eAAe,EAAE,OAA0B;AACzC,QAAI,KAAK,YAAY,SAAS,KAAK,KAAK,WACtC,QAAO,yBAAyB,IAAI,IAAI,WAAW;aAC1C,KAAK,YAAY,KAG1B,QAAO,wBADK,QAAQ,OAAO,IAAI,SAAS,CACL;AAErC,WAAO;;GAEV;EACD,QAAQ;GACN;IACE,MAAM;IACN,OAAO;IACP,MAAM;IACP;GACD;IACE,MAAM;IACN,OAAO;IACP,MAAM;IACP;GACD;IACE,MAAM;IACN,OAAO;IACP,MAAM;IACP;GACD;IACE,MAAM;IACN,QAAQ,CACN;KACE,MAAM;KACN,OAAO;KACP,MAAM;KACN,OAAO;MACL,UAAU;MACV,QAAQ;MACR,OAAO;MACR;KACF,EACD;KACE,MAAM;KACN,OAAO;KACP,MAAM;KACN,OAAO;MACL,UAAU;MACV,QAAQ;MACR,OAAO;MACR;KACF,CACF;IACF;GACD;IACE,MAAM;IACN,OAAO;IACP,MAAM;IACN,SAAS,CACP;KACE,OAAO;KACP,OAAO;KACR,EACD;KACE,OAAO;KACP,OAAO;KACR,CACF;IACD,OAAO,EACL,UAAU,MACX;IACF;GACD;IACE,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;KACL,mBAAmB;KACnB,iBAAiB;KACjB,mBAAmB;KACnB,UAAU;KACV,YAAY,SAAS;AACnB,aAAO,KAAK,YAAY;;KAE3B;IACD,QAAQ;KACN;MACE,MAAM;MACN,MAAM;MACN,OAAO;OACL,YAAY,SAAS;AACnB,eAAO,KAAK,YAAY;;OAE1B,mBAAmB;OACnB,YAAY,EACV,OAAO,0DACR;OACF;MACF;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACD;MACE,MAAM;MACN,OAAO;MACP,MAAM;MACP;KACF;IACF;GACF;EACF;AAGD,KAAI,CAAC,eACH,QAAO;AAGT,QAAO;EACL,GAAG;EACH,GAAG;EACH,QAAQ,CAAC,GAAI,eAAe,UAAU,EAAE,EAAG,GAAG,OAAO,OAAO;EAC7D"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react0 from "react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as payload3 from "payload";
|
|
3
3
|
|
|
4
4
|
//#region src/components/upload-handler/upload-handler.d.ts
|
|
5
5
|
declare const UploadHandler: ({
|
|
@@ -11,11 +11,11 @@ declare const UploadHandler: ({
|
|
|
11
11
|
serverHandlerPath
|
|
12
12
|
}: {
|
|
13
13
|
children: react0.ReactNode;
|
|
14
|
-
collectionSlug:
|
|
14
|
+
collectionSlug: payload3.UploadCollectionSlug;
|
|
15
15
|
enabled?: boolean;
|
|
16
16
|
extra: Record<string, unknown>;
|
|
17
17
|
prefix?: string;
|
|
18
|
-
serverHandlerPath: string
|
|
18
|
+
serverHandlerPath: `/${string}`;
|
|
19
19
|
}) => react0.JSX.Element;
|
|
20
20
|
//#endregion
|
|
21
21
|
export { UploadHandler };
|
|
@@ -87,7 +87,6 @@ async function tusUpload(args) {
|
|
|
87
87
|
const filesize = file.size.toString();
|
|
88
88
|
Object.keys(localStorage).filter((key) => key.startsWith("tus::")).forEach((key) => localStorage.removeItem(key));
|
|
89
89
|
let uploadUrlAvailable = false;
|
|
90
|
-
let eventListenerAdded = false;
|
|
91
90
|
function onBeforeUnload(e) {
|
|
92
91
|
window.removeEventListener("beforeunload", onBeforeUnload);
|
|
93
92
|
e.preventDefault();
|
|
@@ -119,11 +118,8 @@ async function tusUpload(args) {
|
|
|
119
118
|
resolve(null);
|
|
120
119
|
},
|
|
121
120
|
onBeforeRequest() {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
window.addEventListener("unload", onPageUnload);
|
|
125
|
-
eventListenerAdded = true;
|
|
126
|
-
}
|
|
121
|
+
window.addEventListener("beforeunload", onBeforeUnload);
|
|
122
|
+
window.addEventListener("unload", onPageUnload);
|
|
127
123
|
},
|
|
128
124
|
onProgress: function(bytesUploaded, bytesTotal) {
|
|
129
125
|
const percentage = Math.round(bytesUploaded / bytesTotal * 100);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-handler.mjs","names":["uploadArgs: UploadArgs"],"sources":["../../../src/components/upload-handler/upload-handler.tsx"],"sourcesContent":["'use client'\n\nimport * as upchunk from '@mux/upchunk'\nimport * as tus from 'tus-js-client'\n\nimport { toast } from '@payloadcms/ui'\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 { isVideo, getFileType, generateUniqueFilename } from '../../utils/file'\n\ninterface UploadArgs {\n serverURL: string\n apiRoute: string\n file: File\n mimeType: string\n}\n\ninterface UploadResult {\n filename: string\n uploadId?: string\n mimeType: string\n storage: 'mux' | 's3'\n}\n\ninterface MuxCreateUploadResponse {\n url: string\n uploadId: string\n filename: string\n}\n\nconst { logError, throwError } = useErrorHandler()\nconst emitter = useMediaCloudEmitter()\n\nconst MUX_CHUNK_SIZE = 30720\nconst TUS_CHUNK_SIZE = 1024 * 1024\nconst TUS_RETRY_DELAYS = [0, 1000, 2000, 5000]\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 filename = file.name\n try {\n // Request upload URL from Mux\n const response = await fetch(`${serverURL}${apiRoute}/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: `${serverURL}${apiRoute}/mux/asset`,\n })\n\n // Set up event handlers\n uploader.on('error', function () {\n logError(MediaCloudErrors.MUX_UPLOAD_ERROR.message)\n toast.error('Video upload failed')\n emitter.emit('removeUpload', { uploadId })\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 (_error) {\n logError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR.message)\n toast.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, mimeType } = args\n\n const filename = file.name\n const filetype = file.type\n const filesize = file.size.toString()\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(\n `${serverURL}${apiRoute}/uploads/cleanup`,\n JSON.stringify({ filename })\n )\n }\n\n return new Promise((resolve) => {\n const upload = new tus.Upload(file, {\n endpoint: `${serverURL}${apiRoute}/uploads`,\n retryDelays: TUS_RETRY_DELAYS,\n chunkSize: TUS_CHUNK_SIZE,\n storeFingerprintForResuming: false,\n metadata: {\n filetype,\n filesize,\n filename,\n contentType: filetype,\n contentLength: filesize,\n contentDisposition: 'inline',\n },\n onError(error) {\n logError(MediaCloudErrors.TUS_UPLOAD_ERROR.message)\n logError(error.message)\n\n // Clean up\n navigator.sendBeacon(\n `${serverURL}${apiRoute}/uploads/cleanup`,\n JSON.stringify({ filename })\n )\n\n // Inform user\n emitter.emit('removeUpload', { filename })\n toast.error('File upload failed')\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 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 fetch(`${serverURL}${apiRoute}/uploads/${filename}/process`)\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\nexport const UploadHandler = createClientUploadHandler({\n handler: async function (args) {\n const { serverURL, apiRoute, file, updateFilename } = args\n console.log('upload handler called', file)\n try {\n const mimeType =\n (await getFileType(file)) || file.type || 'application/octet-stream'\n if (!mimeType) {\n throwError(MediaCloudErrors.FILE_TYPE_UNKNOWN)\n return null\n }\n\n const isVideoFile = await isVideo(file)\n\n // Clone file\n let mappedFile = file\n\n if (!isVideoFile) {\n try {\n // Check if file with same name exists\n const response = await fetch(\n `${serverURL}${apiRoute}/uploads/${file.name}/exists`\n ).catch(() => {})\n\n // If file exists, generate a cloned file with a unique filename\n if (response?.status === 200) {\n log(MediaCloudLogs.S3_STORE_FILE_FOUND)\n\n const newFilename = generateUniqueFilename(file.name)\n mappedFile = new File([file], newFilename, { type: file.type })\n await updateFilename(newFilename)\n }\n } catch (_error) {\n logError(MediaCloudErrors.NAMING_FUNCTION_ERROR.message)\n }\n }\n\n const uploadArgs: UploadArgs = {\n file: mappedFile,\n serverURL,\n apiRoute,\n mimeType,\n }\n\n if (isVideoFile) {\n return await muxUpload(uploadArgs)\n } else {\n return await tusUpload(uploadArgs)\n }\n } catch (error) {\n console.error(\n '[PLUGIN-MEDIA-CLOUD] Upload handler detailed error:',\n error\n )\n logError(MediaCloudErrors.UPLOAD_HANDLER_ERROR.message)\n toast.error(\n `Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n )\n return null\n }\n },\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"upload-handler.mjs","names":["uploadArgs: UploadArgs"],"sources":["../../../src/components/upload-handler/upload-handler.tsx"],"sourcesContent":["'use client'\n\nimport * as upchunk from '@mux/upchunk'\nimport * as tus from 'tus-js-client'\n\nimport { toast } from '@payloadcms/ui'\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 { isVideo, getFileType, generateUniqueFilename } from '../../utils/file'\n\ninterface UploadArgs {\n serverURL: string\n apiRoute: string\n file: File\n mimeType: string\n}\n\ninterface UploadResult {\n filename: string\n uploadId?: string\n mimeType: string\n storage: 'mux' | 's3'\n}\n\ninterface MuxCreateUploadResponse {\n url: string\n uploadId: string\n filename: string\n}\n\nconst { logError, throwError } = useErrorHandler()\nconst emitter = useMediaCloudEmitter()\n\nconst MUX_CHUNK_SIZE = 30720\nconst TUS_CHUNK_SIZE = 1024 * 1024\nconst TUS_RETRY_DELAYS = [0, 1000, 2000, 5000]\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 filename = file.name\n try {\n // Request upload URL from Mux\n const response = await fetch(`${serverURL}${apiRoute}/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: `${serverURL}${apiRoute}/mux/asset`,\n })\n\n // Set up event handlers\n uploader.on('error', function () {\n logError(MediaCloudErrors.MUX_UPLOAD_ERROR.message)\n toast.error('Video upload failed')\n emitter.emit('removeUpload', { uploadId })\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 (_error) {\n logError(MediaCloudErrors.MUX_DIRECT_UPLOAD_ERROR.message)\n toast.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, mimeType } = args\n\n const filename = file.name\n const filetype = file.type\n const filesize = file.size.toString()\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(\n `${serverURL}${apiRoute}/uploads/cleanup`,\n JSON.stringify({ filename })\n )\n }\n\n return new Promise((resolve) => {\n const upload = new tus.Upload(file, {\n endpoint: `${serverURL}${apiRoute}/uploads`,\n retryDelays: TUS_RETRY_DELAYS,\n chunkSize: TUS_CHUNK_SIZE,\n storeFingerprintForResuming: false,\n metadata: {\n filetype,\n filesize,\n filename,\n contentType: filetype,\n contentLength: filesize,\n contentDisposition: 'inline',\n },\n onError(error) {\n logError(MediaCloudErrors.TUS_UPLOAD_ERROR.message)\n logError(error.message)\n\n // Clean up\n navigator.sendBeacon(\n `${serverURL}${apiRoute}/uploads/cleanup`,\n JSON.stringify({ filename })\n )\n\n // Inform user\n emitter.emit('removeUpload', { filename })\n toast.error('File upload failed')\n resolve(null)\n },\n onBeforeRequest() {\n if (!eventListenerAdded) {\n window.addEventListener('beforeunload', onBeforeUnload)\n window.addEventListener('unload', onPageUnload)\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 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 fetch(`${serverURL}${apiRoute}/uploads/${filename}/process`)\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\nexport const UploadHandler = createClientUploadHandler({\n handler: async function (args) {\n const { serverURL, apiRoute, file, updateFilename } = args\n console.log('upload handler called', file)\n try {\n const mimeType =\n (await getFileType(file)) || file.type || 'application/octet-stream'\n if (!mimeType) {\n throwError(MediaCloudErrors.FILE_TYPE_UNKNOWN)\n return null\n }\n\n const isVideoFile = await isVideo(file)\n\n // Clone file\n let mappedFile = file\n\n if (!isVideoFile) {\n try {\n // Check if file with same name exists\n const response = await fetch(\n `${serverURL}${apiRoute}/uploads/${file.name}/exists`\n ).catch(() => {})\n\n // If file exists, generate a cloned file with a unique filename\n if (response?.status === 200) {\n log(MediaCloudLogs.S3_STORE_FILE_FOUND)\n\n const newFilename = generateUniqueFilename(file.name)\n mappedFile = new File([file], newFilename, { type: file.type })\n await updateFilename(newFilename)\n }\n } catch (_error) {\n logError(MediaCloudErrors.NAMING_FUNCTION_ERROR.message)\n }\n }\n\n const uploadArgs: UploadArgs = {\n file: mappedFile,\n serverURL,\n apiRoute,\n mimeType,\n }\n\n if (isVideoFile) {\n return await muxUpload(uploadArgs)\n } else {\n return await tusUpload(uploadArgs)\n }\n } catch (error) {\n console.error(\n '[PLUGIN-MEDIA-CLOUD] Upload handler detailed error:',\n error\n )\n logError(MediaCloudErrors.UPLOAD_HANDLER_ERROR.message)\n toast.error(\n `Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`\n )\n return null\n }\n },\n})\n"],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ function getTusCleanupHandler(args) {
|
|
|
21
21
|
id: docs[0].id
|
|
22
22
|
});
|
|
23
23
|
return new Response("Cleanup successful", { status: 200 });
|
|
24
|
-
} catch {
|
|
24
|
+
} catch (error) {
|
|
25
25
|
logError(MediaCloudErrors.TUS_CLEANUP_ERROR.message);
|
|
26
26
|
return new Response("Cleanup failed", { status: 500 });
|
|
27
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tusCleanupHandler.mjs","names":[],"sources":["../../src/endpoints/tusCleanupHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\nimport { useErrorHandler } from '../hooks/useErrorHandler'\nimport { createS3Store } from '../tus/stores/s3'\nimport { MediaCloudErrors } from '../types/errors'\n\ninterface GetTusCleanupHandlerArgs {\n s3Store: ReturnType<typeof createS3Store>\n}\n\nconst { logError } = useErrorHandler()\n\nexport function getTusCleanupHandler(\n args: GetTusCleanupHandlerArgs\n): PayloadHandler {\n const { s3Store } = args\n\n return async (req) => {\n try {\n const data = await req.json?.()\n const { filename } = data\n\n if (!filename) {\n return new Response('Missing filename', { status: 400 })\n }\n\n // Abort the multipart upload and delete S3 objects (.info, .part)\n await s3Store.remove(filename)\n\n // Find and delete the Payload document\n const payload = req.payload\n const { docs } = await req.payload.find({\n collection: 'media',\n where: {\n filename: {\n equals: filename,\n },\n },\n limit: 1,\n })\n\n if (docs?.length > 0) {\n await payload.delete({\n collection: 'media',\n id: docs[0].id,\n })\n }\n\n return new Response('Cleanup successful', { status: 200 })\n } catch {\n logError(MediaCloudErrors.TUS_CLEANUP_ERROR.message)\n return new Response('Cleanup failed', { status: 500 })\n }\n }\n}\n"],"mappings":";;;;AASA,MAAM,EAAE,aAAa,iBAAiB;AAEtC,SAAgB,qBACd,MACgB;CAChB,MAAM,EAAE,YAAY;AAEpB,QAAO,OAAO,QAAQ;AACpB,MAAI;GAEF,MAAM,EAAE,aADK,MAAM,IAAI,QAAQ;AAG/B,OAAI,CAAC,SACH,QAAO,IAAI,SAAS,oBAAoB,EAAE,QAAQ,KAAK,CAAC;AAI1D,SAAM,QAAQ,OAAO,SAAS;GAG9B,MAAM,UAAU,IAAI;GACpB,MAAM,EAAE,SAAS,MAAM,IAAI,QAAQ,KAAK;IACtC,YAAY;IACZ,OAAO,EACL,UAAU,EACR,QAAQ,UACT,EACF;IACD,OAAO;IACR,CAAC;AAEF,OAAI,MAAM,SAAS,EACjB,OAAM,QAAQ,OAAO;IACnB,YAAY;IACZ,IAAI,KAAK,GAAG;IACb,CAAC;AAGJ,UAAO,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"tusCleanupHandler.mjs","names":[],"sources":["../../src/endpoints/tusCleanupHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\nimport { useErrorHandler } from '../hooks/useErrorHandler'\nimport { createS3Store } from '../tus/stores/s3'\nimport { MediaCloudErrors } from '../types/errors'\n\ninterface GetTusCleanupHandlerArgs {\n s3Store: ReturnType<typeof createS3Store>\n}\n\nconst { logError } = useErrorHandler()\n\nexport function getTusCleanupHandler(\n args: GetTusCleanupHandlerArgs\n): PayloadHandler {\n const { s3Store } = args\n\n return async (req) => {\n try {\n const data = await req.json?.()\n const { filename } = data\n\n if (!filename) {\n return new Response('Missing filename', { status: 400 })\n }\n\n // Abort the multipart upload and delete S3 objects (.info, .part)\n await s3Store.remove(filename)\n\n // Find and delete the Payload document\n const payload = req.payload\n const { docs } = await req.payload.find({\n collection: 'media',\n where: {\n filename: {\n equals: filename,\n },\n },\n limit: 1,\n })\n\n if (docs?.length > 0) {\n await payload.delete({\n collection: 'media',\n id: docs[0].id,\n })\n }\n\n return new Response('Cleanup successful', { status: 200 })\n } catch (error) {\n logError(MediaCloudErrors.TUS_CLEANUP_ERROR.message)\n return new Response('Cleanup failed', { status: 500 })\n }\n }\n}\n"],"mappings":";;;;AASA,MAAM,EAAE,aAAa,iBAAiB;AAEtC,SAAgB,qBACd,MACgB;CAChB,MAAM,EAAE,YAAY;AAEpB,QAAO,OAAO,QAAQ;AACpB,MAAI;GAEF,MAAM,EAAE,aADK,MAAM,IAAI,QAAQ;AAG/B,OAAI,CAAC,SACH,QAAO,IAAI,SAAS,oBAAoB,EAAE,QAAQ,KAAK,CAAC;AAI1D,SAAM,QAAQ,OAAO,SAAS;GAG9B,MAAM,UAAU,IAAI;GACpB,MAAM,EAAE,SAAS,MAAM,IAAI,QAAQ,KAAK;IACtC,YAAY;IACZ,OAAO,EACL,UAAU,EACR,QAAQ,UACT,EACF;IACD,OAAO;IACR,CAAC;AAEF,OAAI,MAAM,SAAS,EACjB,OAAM,QAAQ,OAAO;IACnB,YAAY;IACZ,IAAI,KAAK,GAAG;IACb,CAAC;AAGJ,UAAO,IAAI,SAAS,sBAAsB,EAAE,QAAQ,KAAK,CAAC;WACnD,OAAO;AACd,YAAS,iBAAiB,kBAAkB,QAAQ;AACpD,UAAO,IAAI,SAAS,kBAAkB,EAAE,QAAQ,KAAK,CAAC"}
|
package/dist/utils/mux.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MediaCloudPluginOptions } from "../types/index.mjs";
|
|
2
2
|
import Mux from "@mux/mux-node";
|
|
3
|
-
import * as
|
|
3
|
+
import * as payload0 from "payload";
|
|
4
4
|
|
|
5
5
|
//#region src/utils/mux.d.ts
|
|
6
6
|
|
|
@@ -14,11 +14,11 @@ interface CreateMuxEndpointsArgs {
|
|
|
14
14
|
pluginOptions: MediaCloudPluginOptions;
|
|
15
15
|
}
|
|
16
16
|
declare function createMuxEndpoints(args: CreateMuxEndpointsArgs): ({
|
|
17
|
-
handler:
|
|
17
|
+
handler: payload0.PayloadHandler;
|
|
18
18
|
method: "post";
|
|
19
19
|
path: string;
|
|
20
20
|
} | {
|
|
21
|
-
handler:
|
|
21
|
+
handler: payload0.PayloadHandler;
|
|
22
22
|
method: "get";
|
|
23
23
|
path: string;
|
|
24
24
|
})[];
|
package/dist/utils/tus.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MediaCloudPluginOptions } from "../types/index.mjs";
|
|
2
2
|
import { S3Store } from "../tus/stores/s3/s3-store.mjs";
|
|
3
3
|
import { Server } from "@tus/server";
|
|
4
|
-
import * as
|
|
4
|
+
import * as payload1 from "payload";
|
|
5
5
|
import { PayloadRequest } from "payload";
|
|
6
6
|
|
|
7
7
|
//#region src/utils/tus.d.ts
|
|
@@ -42,11 +42,11 @@ declare function createTusEndpoints(args: CreateTusEndpointsArgs): ({
|
|
|
42
42
|
method: "delete";
|
|
43
43
|
path: string;
|
|
44
44
|
} | {
|
|
45
|
-
handler:
|
|
45
|
+
handler: payload1.PayloadHandler;
|
|
46
46
|
method: "get";
|
|
47
47
|
path: string;
|
|
48
48
|
} | {
|
|
49
|
-
handler:
|
|
49
|
+
handler: payload1.PayloadHandler;
|
|
50
50
|
method: "post";
|
|
51
51
|
path: string;
|
|
52
52
|
})[];
|