window.EEPROM = (() => { const errGeneric = 'generic'; const errInvalid = 'invalid'; const errAuth = 'auth'; const errAccess = 'access'; const errDMCA = 'dmca'; const errGone = 'gone'; const errSize = 'size'; const errServer = 'server'; const createClient = function(srcId, endPoint, authorization) { if(typeof srcId !== 'number') srcId = parseInt(srcId); if(typeof endPoint !== 'string') throw 'endPoint must be a string'; if(typeof authorization !== 'string' && typeof authorization !== 'function') throw 'authorization must be a string or a function returning a string'; const createUpload = file => { const uploadTask = { onComplete: undefined, onFailure: undefined, onProgress: undefined }; let userAborted = false; const xhr = new XMLHttpRequest; const fd = new FormData; fd.append('src', srcId); fd.append('file', file); const reportUploadProgress = ev => { if(typeof uploadTask.onProgress === 'function') uploadTask.onProgress({ loaded: ev.loaded, total: ev.total, progress: Math.ceil((ev.loaded / ev.total) * 100), }); }; xhr.upload.addEventListener('loadstart', reportUploadProgress); xhr.upload.addEventListener('progress', reportUploadProgress); xhr.upload.addEventListener('load', reportUploadProgress); xhr.addEventListener('readystatechange', () => { if(xhr.readyState !== 4) return; if(xhr.status !== 201) { const failureResponse = { userAborted: userAborted, error: errGeneric, }; switch(xhr.status) { case 400: case 405: failureResponse.error = errInvalid; break; case 401: failureResponse.error = errAuth; break; case 403: failureResponse.error = errAccess; break; case 404: case 410: failureResponse.error = errGone; break; case 451: failureResponse.error = errDMCA; break; case 413: failureResponse.error = errSize; failureResponse.maxSize = parseInt(xhr.getResponseHeader('X-EEPROM-Max-Size')); break; case 500: case 503: failureResponse.error = errServer; break; } if(typeof uploadTask.onFailure === 'function') uploadTask.onFailure(failureResponse); return; } if(typeof uploadTask.onComplete === 'function') { const fileInfo = JSON.parse(xhr.responseText); if(typeof fileInfo !== 'object') { if(typeof uploadTask.onFailure === 'function') uploadTask.onFailure({ userAborted: userAborted, error: errServer, }); return; } fileInfo.isImage = () => typeof fileInfo.type === 'string' && fileInfo.type.indexOf('image/') === 0; fileInfo.isVideo = () => typeof fileInfo.type === 'string' && fileInfo.type.indexOf('video/') === 0; fileInfo.isAudio = () => typeof fileInfo.type === 'string' && (fileInfo.type === 'application/x-font-gdos' || fileInfo.type.indexOf('audio/') === 0); fileInfo.isMedia = () => typeof fileInfo.type === 'string' && (fileInfo.isImage() || fileInfo.isAudio() || fileInfo.isVideo()); uploadTask.onComplete(fileInfo); } }); uploadTask.abort = () => { userAborted = true; xhr.abort(); }; uploadTask.start = () => { xhr.open('POST', endPoint); const authIsFunc = typeof authorization === 'function'; if(authIsFunc || typeof authorization === 'string') xhr.setRequestHeader('Authorization', authIsFunc ? authorization() : authorization); else xhr.withCredentials = true; xhr.send(fd); }; return uploadTask; }; const deleteUpload = fileInfo => { const deleteTask = { onSuccess: undefined, onFailure: undefined }; const xhr = new XMLHttpRequest; xhr.addEventListener('readystatechange', () => { if(xhr.readyState !== 4) return; if(xhr.status !== 204) { let errorCode = errGeneric; switch(xhr.status) { case 401: errorCode = errAuth; break; case 403: errorCode = errAccess; break; case 404: case 410: errorCode = errGone; break; case 500: case 503: errorCode = errServer; break; } if(typeof deleteTask.onFailure === 'function') deleteTask.onFailure(errorCode); return; } if(typeof deleteTask.onSuccess === 'function') deleteTask.onSuccess(); }); deleteTask.start = () => { xhr.open('DELETE', fileInfo.urlf); const authIsFunc = typeof authorization === 'function'; if(authIsFunc || typeof authorization === 'string') xhr.setRequestHeader('Authorization', authIsFunc ? authorization() : authorization); else xhr.withCredentials = true; xhr.send(); }; return deleteTask; }; return { createUpload: createUpload, deleteUpload: deleteUpload, }; }; Object.defineProperties(createClient, { ERR_GENERIC: { value: errGeneric }, ERR_INVALID: { value: errInvalid }, ERR_AUTH: { value: errAuth }, ERR_ACCESS: { value: errAccess }, ERR_DMCA: { value: errDMCA }, ERR_GONE: { value: errGone }, ERR_SERVER: { value: errServer }, ERR_SIZE: { value: errSize }, }); return createClient; })();