UNPKG

insite-ws-transfers

Version:

inSite file transfers over WebSockets

3 lines (2 loc) 17.6 kB
var Le=Object.defineProperty;var ke=n=>{throw TypeError(n)};var Be=(n,e,t)=>e in n?Le(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var i=(n,e,t)=>Be(n,typeof e!="symbol"?e+"":e,t),ye=(n,e,t)=>e.has(n)||ke("Cannot "+t);var s=(n,e,t)=>(ye(n,e,"read from private field"),t?t.call(n):e.get(n)),a=(n,e,t)=>e.has(n)?ke("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(n):e.set(n,t),f=(n,e,t,r)=>(ye(n,e,"write to private field"),r?r.call(n,t):e.set(n,t),t),u=(n,e,t)=>(ye(n,e,"access private method"),t);var l={request:"~t-request",confirm:"~t-confirm",chunk:"~t-c",progress:"~t-p",sent:"~t-sent",completed:"~t-completed",abort:"~t-abort",error:"~t-error"},ve=10*1024*1024*1024,Re=1024*256,ze=250;var k,v,R,ee,y,N,q,I,H,te,x,Ae,xe,We,z=class{constructor(e,t,r,{type:o,collect:h,encoding:c,size:d,metadata:p},B,F){a(this,x);i(this,"ws");a(this,k);i(this,"kind");i(this,"id");i(this,"type");i(this,"collect");i(this,"encoding");i(this,"size");i(this,"metadata");a(this,v);a(this,R);a(this,ee);i(this,"data");a(this,y);i(this,"isAborted",!1);i(this,"isAbortedBySender",!1);i(this,"isAbortedByReceiver",!1);i(this,"isTransfered",!1);i(this,"confirmResponse");i(this,"beginAt",null);a(this,N,null);a(this,q,[]);a(this,I,!1);i(this,"duration",null);i(this,"transferedSize",0);i(this,"processedSize",0);i(this,"bytesPerMs",null);i(this,"progress",0);i(this,"endAt",null);i(this,"error",null);a(this,H);a(this,te,0);this.ws=e,f(this,k,e.isWebSocket?[e]:[e.wss,e]),this.kind=t,this.id=r,this.type=o,this.collect=!!h,this.encoding=c,this.size=d,this.metadata=p,f(this,v,B),f(this,R,F),f(this,ee,u(this,x,Ae).call(this))}whenSetUp(){return s(this,ee)}async confirm(){for(let{begin:e}of s(this,R))if(await e?.call(...s(this,k),this)===!1)return this.throw("Transfer was rejected by receiver");this.beginAt=f(this,N,Date.now()),this.ws.sendMessage(l.confirm,this.id,this.confirmResponse),f(this,H,setInterval(()=>{s(this,te)!==this.progress&&(f(this,te,this.progress),this.ws.sendMessage(l.progress,this.id,this.progress))},ze))}async handleChunk(e,t=e.length){let r=Date.now();this.bytesPerMs=t/(r-s(this,N)),f(this,N,r),this.transferedSize+=t,s(this,q).push([e,t]),s(this,I)||(f(this,I,!0),await u(this,x,xe).call(this))}async handleSent(){this.isTransfered=!0,this.size||(this.size=this.transferedSize),this.endAt=Date.now(),this.duration=this.endAt-this.beginAt,this.bytesPerMs=this.size/this.duration,s(this,I)||await u(this,x,We).call(this)}abort(e=!1){return this.isAborted=!0,this.isAbortedBySender=e,this.isAbortedByReceiver=!e,this.throw(`Transfer is aborted by ${e?"sender":"receiver"}`,!e)}throw(e,t=!0){s(this,v).delete(this.id),clearInterval(s(this,H)),this.error=new Error(e);for(let r of s(this,R))r.once&&s(this,v).removeListener(this.kind,r),r.error?.call(...s(this,k),this,this.error);t&&this.ws.sendMessage(l.error,this.id,e)}serialize(){return{id:this.id,kind:this.kind,type:this.type,collect:this.collect,encoding:this.encoding,size:this.size,metadata:this.metadata,isAborted:this.isAborted,isAbortedBySender:this.isAbortedBySender,isAbortedByReceiver:this.isAbortedByReceiver,isTransfered:this.isTransfered,confirmResponse:this.confirmResponse,beginAt:this.beginAt,duration:this.duration,transferedSize:this.transferedSize,processedSize:this.processedSize,bytesPerMs:this.bytesPerMs,progress:this.progress,endAt:this.endAt,error:this.error}}};k=new WeakMap,v=new WeakMap,R=new WeakMap,ee=new WeakMap,y=new WeakMap,N=new WeakMap,q=new WeakMap,I=new WeakMap,H=new WeakMap,te=new WeakMap,x=new WeakSet,Ae=async function(){if(f(this,y,this.constructor.types[this.type]),s(this,y))await s(this,y).setup.call(this);else throw new Error(`Unknown type of transfer "${String(this.type)}"`);await this.confirm()},xe=async function(){let[e,t]=s(this,q).shift();s(this,y).transformChunk&&(e=await s(this,y).transformChunk.call(this,e)),this.collect&&await s(this,y).collect.call(this,e);for(let{chunk:r,progress:o}of s(this,R))await(r??o)?.call(...s(this,k),this,e);this.processedSize+=t,this.size&&(this.progress=this.processedSize/this.size),s(this,q).length?u(this,x,xe).call(this):(f(this,I,!1),this.isTransfered&&u(this,x,We).call(this))},We=async function(){this.progress=1,await s(this,y).done?.call(this);for(let e of s(this,R))e.once&&s(this,v).removeListener(this.kind,e),await e.end?.call(...s(this,k),this);clearInterval(s(this,H)),s(this,v).delete(this.id),this.ws.sendMessage(l.completed,this.id)},i(z,"types",{object:{setup(){this.data=""},collect(e){this.data+=e},done(){this.data=JSON.parse(this.data)}},datauri:{setup(){this.collect&&(this.data="")},collect(e){this.data+=e},done(){this.collect&&(this.data=`data:${this.metadata.type};base64,${this.data}`)}},string:{setup(){this.collect&&(this.data="")},collect(e){this.data+=e}}});var W,b,ue,re=class{constructor(e,t={}){i(this,"sizeLimit");a(this,W,new Map);i(this,"on",this.addTransferListener);i(this,"off",this.removeTransferListener);a(this,b,new Map);a(this,ue,{delete:e=>s(this,b).delete(e),removeListener:(e,t)=>this.removeTransferListener(e,t)});let{sizeLimit:r=ve}=t;this.sizeLimit=r,e.isWebSocketServer?(e.on(`client-message:${l.request}`,(o,...h)=>this.handleRequest(o,...h)),e.on(`client-message:${l.chunk}`,(o,...h)=>this.handleChunk(o,...h)),e.on(`client-message:${l.sent}`,(o,...h)=>this.handleSent(o,...h)),e.on(`client-message:${l.abort}`,(o,...h)=>this.handleAbort(o,...h))):(e.on(`message:${l.request}`,(...o)=>this.handleRequest(e,...o)),e.on(`message:${l.chunk}`,(...o)=>this.handleChunk(e,...o)),e.on(`message:${l.sent}`,(...o)=>this.handleSent(e,...o)),e.on(`message:${l.abort}`,(...o)=>this.handleAbort(e,...o))),Object.assign(e,{onTransfer:(o,h,c)=>this.on(o,h,c),onceTransfer:(o,h,c)=>this.once(o,h,c)})}addTransferListener(e,t,r){return r?.once&&(t.once=!0),s(this,W).get(e)?.add(t)??s(this,W).set(e,new Set([t])),this}once(e,t,r){return this.addTransferListener(e,t,{...r,once:!0})}removeTransferListener(e,t){if(t){let r=s(this,W).get(e);r&&(r.delete(t),r.size||s(this,W).delete(e))}else s(this,W).delete(e);return this}handleRequest(e,t,r,{type:o,size:h,metadata:c,...d}){let{Transfer:p}=this.constructor;s(this,W).has(t)?s(this,b).has(r)?e.sendMessage(l.error,r,"Transfer already exists"):o in p.types?h>this.sizeLimit?e.sendMessage(l.error,r,`Transfer size (${h} bytes) exeeds limit of ${this.sizeLimit} bytes`):s(this,b).set(r,new p(e,t,r,{type:o,size:h,metadata:c,...d},s(this,ue),s(this,W).get(t))):e.sendMessage(l.error,r,"Unknown type of transfer"):e.sendMessage(l.error,r,`Unknown kind of file "${t}"`)}async handleChunk(e,t,r,o=r.length){await s(this,b).get(t)?.handleChunk(r,o)}async handleSent(e,t){await s(this,b).get(t)?.handleSent()}handleAbort(e,t){s(this,b).get(t)?.abort(!0)}};W=new WeakMap,b=new WeakMap,ue=new WeakMap,i(re,"Transfer",z);var de=class extends z{};i(de,"types",{file:{setup(){this.collect&&(this.data="")},collect(e){this.data+=e},done(){this.collect&&this.encoding==="utf8"&&(this.data=atob(this.data))}},...z.types});var Te=class extends re{};i(Te,"Transfer",de);function A(){}var se=new WeakMap,_=class n extends Promise{constructor(t,r){let o,h;super((c,d)=>{o=c,h=d});i(this,"isPending",!0);i(this,"isFulfilled",!1);i(this,"isRejected",!1);i(this,"state","pending");i(this,"result");i(this,"resolve",t=>{if(this.isPending){this.isPending=!1,this.isFulfilled=!0,this.state="fulfilled",this.result=t;let r=se.get(this);r&&(r.resolve.call(this,t),se.delete(this))}});i(this,"reject",t=>{if(this.isPending){this.isPending=!1,this.isRejected=!0,this.state="rejected",this.result=t;let r=se.get(this);r&&(r.reject.call(this,t),se.delete(this))}});if(se.set(this,{resolve:o,reject:h}),r?.signal)if(r.signal.aborted)this.reject(new DOMException("Aborted","AbortError"));else{let c=()=>this.reject(new DOMException("Aborted","AbortError"));r.signal.addEventListener("abort",c),this.finally(()=>r.signal?.removeEventListener("abort",c))}if(typeof r?.timeout=="number"&&Number.isFinite(r.timeout)){let c=setTimeout(()=>this.reject(new DOMException("Timeout exceeded","TimeoutError")),r.timeout);this.finally(()=>clearTimeout(c))}t?.(this.resolve,this.reject)}static resolved(t){return new n(r=>r(t))}static rejected(t){return new n((r,o)=>o(t))}};function Fe(n,e=0,t={}){let{leading:r=!1,trailing:o=!0}=t,{maxWait:h=1/0}=t,c,d,p,B,F,$,m,E,Z=async()=>{let O=Date.now();O>=p?(c=void 0,p=void 0,clearTimeout(d),d=void 0,typeof m=="function"&&await m(),S.resolve(E),$=r):(clearTimeout(c),c=setTimeout(Z,p-O))},D=Number.isFinite(h)?()=>{m===g&&(m=!1),g(),d=setTimeout(D,h)}:null;async function g(){try{return E=await n.apply(B,F),E}catch(O){throw S.reject(O),O}}r&&typeof r=="boolean"&&(r=g),$=r,o&&typeof o=="boolean"&&(o=g),m=o;let S=Object.assign(function(...O){return F=O,B=this,p=Date.now()+e,m=o,S.promise.isPending||(S.promise=new _((Me,je)=>{S.resolve=Me,S.reject=je,typeof $=="function"&&($(),$=!1,m===g&&(m=!1)),c||(c=setTimeout(Z,e),D&&(d=setTimeout(D,h)))})),S.promise},{callback:n,promise:_.resolved(void 0),resolve:A,reject:A,run:g,clear:async O=>{clearTimeout(c),c=void 0,clearTimeout(d),d=void 0,S.resolve(O?await g():E)}});return S}Fe.noop=Object.assign(()=>{},{callback:A,promise:_.resolved(void 0),resolve:A,reject:A,run:A,clear:A});function Pe(n,e,t,r,o=!0){return Array.isArray(n)&&(n=n.length),typeof r!="string"&&(o=r??!0,r=t),(o?`${n}\xA0`:"")+Pe.raw(n,e,t,r)}Pe.raw=(n,e,t,r=t)=>{n=Math.abs(n);let o=n%10,h=n%100;return o===1&&h!==11?e:o>=2&&o<=4&&!(h>=12&&h<=15)?t:r};function $e(n="",e=""){return`${n}${Date.now().toString(36)}${Math.round(Math.random()*Number.MAX_SAFE_INTEGER).toString(36)}${e}`}var J,M,ie,Oe,U=class{constructor(e,t={}){a(this,ie);i(this,"string");i(this,"size");i(this,"chunkSize");i(this,"listener");a(this,J,0);a(this,M,0);i(this,"isAborted",!1);this.string=e,this.size=this.string.length;let{chunkSize:r=1024*256}=t;this.chunkSize=r}start(e){this.listener=e,u(this,ie,Oe).call(this)}abort(){this.isAborted=!0}};J=new WeakMap,M=new WeakMap,ie=new WeakSet,Oe=async function(){if(!this.isAborted){f(this,M,Math.min(s(this,J)+this.chunkSize,this.size));let e=await new Promise(t=>{t(this.string.slice(s(this,J),s(this,M)))});this.isAborted||(await this.listener(e),s(this,M)<this.size&&(f(this,J,s(this,M)),u(this,ie,Oe).call(this)))}};var T,V,ne,oe,K,ae,he,fe,P,Q,G,X,j,Ee,be,w=class{constructor(e,t,{data:r,type:o,incomingType:h,collect:c,metadata:d,size:p,chunkSize:B,encoding:F,incomingEncoding:$,onBegin:m,onSenderProgress:E,onProgress:Z,onEnd:D,onError:g},S){a(this,j);i(this,"ws");a(this,T);i(this,"kind");i(this,"data");i(this,"type");i(this,"collect");i(this,"metadata");i(this,"size");i(this,"encoding");i(this,"chunkSize");a(this,V);a(this,ne);a(this,oe);a(this,K);a(this,ae);a(this,he);a(this,fe);i(this,"id",$e());a(this,P);i(this,"isAborted",!1);i(this,"isTransfered",!1);i(this,"confirmResponse");i(this,"beginAt",null);a(this,Q,null);a(this,G,[]);a(this,X,!1);i(this,"duration",null);i(this,"transferedSize",0);i(this,"bytesPerMs",null);i(this,"senderProgress",0);i(this,"progress",0);i(this,"endAt",null);i(this,"error",null);i(this,"stringStreamer");i(this,"fileStreamer");i(this,"handleChunk",e=>{s(this,G).push(e),s(this,X)||(f(this,X,!0),u(this,j,be).call(this))});i(this,"sent",()=>this.ws.sendMessage(l.sent,this.id));this.ws=e,f(this,T,e.isWebSocket?[e]:[e.wss,e]),this.kind=t,this.data=r,this.type=o,this.collect=c??!1,this.metadata=d,this.size=p??null,this.encoding=F,this.chunkSize=B??this.constructor.chunkSize,f(this,V,S),m&&f(this,ne,m),E&&f(this,oe,E),Z&&f(this,K,Z),D&&f(this,ae,D),g&&f(this,he,g),f(this,fe,u(this,j,Ee).call(this,h,$))}whenSetUp(){return s(this,fe)}async handleConfirm(e){this.confirmResponse=e,this.beginAt=f(this,Q,Date.now()),await s(this,ne)?.call(...s(this,T),this),await s(this,P).confirm.call(this)}handleProgress(e){this.progress=e,s(this,K)?.call(...s(this,T),this)}async handleCompleted(){this.isTransfered=!0,this.size||(this.size=this.transferedSize,this.senderProgress=1),this.endAt=Date.now(),this.duration=this.endAt-this.beginAt,this.bytesPerMs=this.size/this.duration,s(this,V).delete(this.id),this.progress!==1&&(this.progress=1,await s(this,K)?.call(...s(this,T),this)),s(this,ae)?.call(...s(this,T),this)}throw(e){s(this,V).delete(this.id),this.error=new Error(e),s(this,he)?.call(...s(this,T),this,this.error)}abort(){return this.isAborted=!0,this.ws.sendMessage(l.abort,this.id),this.throw("Transfer is aborted by sender")}serialize(){return{id:this.id,kind:this.kind,type:this.type,collect:this.collect,encoding:this.encoding,size:this.size,metadata:this.metadata,isAborted:this.isAborted,isTransfered:this.isTransfered,confirmResponse:this.confirmResponse,beginAt:this.beginAt,duration:this.duration,transferedSize:this.transferedSize,bytesPerMs:this.bytesPerMs,senderProgress:this.senderProgress,progress:this.progress,endAt:this.endAt,error:this.error}}};T=new WeakMap,V=new WeakMap,ne=new WeakMap,oe=new WeakMap,K=new WeakMap,ae=new WeakMap,he=new WeakMap,fe=new WeakMap,P=new WeakMap,Q=new WeakMap,G=new WeakMap,X=new WeakMap,j=new WeakSet,Ee=async function(e,t){for(let[r,o,h]of this.constructor.types)if(this.type===r||o(this.data)){this.type=r,f(this,P,h);break}if(this.type)await s(this,P).setup.call(this),delete this.data;else throw new Error("Unknown type of transfer");this.ws.sendMessage(l.request,this.kind,this.id,{type:e??this.type,collect:this.collect,encoding:t??this.encoding,size:this.size,metadata:this.metadata})},be=async function(){let e=s(this,G).shift(),t=e.length;s(this,P).transformChunk&&(e=await s(this,P).transformChunk.call(this,e)),this.ws.sendMessage(l.chunk,this.id,e,t);let r=Date.now();this.bytesPerMs=t/(r-s(this,Q)),f(this,Q,r),this.transferedSize+=t,this.size&&(this.senderProgress=this.transferedSize/this.size),await s(this,oe)?.call(...s(this,T),this),s(this,G).length?u(this,j,be).call(this):(f(this,X,!1),this.senderProgress===1&&this.sent())},i(w,"types",[["object",e=>typeof e=="object",{setup(){this.stringStreamer=new U(JSON.stringify(this.data),{chunkSize:this.chunkSize}),this.collect=!0,this.size=this.stringStreamer.size,this.encoding="utf8"},confirm(){this.stringStreamer.start(this.handleChunk)}}],["datauri",e=>typeof e=="string"&&/^data:[\w-.]+\/[\w-.+,]+(?:;base64)?,/.test(e),{setup(){let[e,t]=this.data.split(/^data:|;base64,|,/).slice(1);this.stringStreamer=new U(t,{chunkSize:this.chunkSize}),this.size=this.stringStreamer.size,this.encoding="base64",this.metadata={...this.metadata,type:e}},confirm(){this.stringStreamer.start(this.handleChunk)}}],["string",e=>typeof e=="string",{setup(){this.stringStreamer=new U(this.data,{chunkSize:this.chunkSize}),this.size=this.stringStreamer.size,this.encoding||(this.encoding="utf8")},confirm(){this.stringStreamer.start(this.handleChunk)}}]]),i(w,"chunkSize",Re);var C,pe,le=class{constructor(e){a(this,C,new Map);a(this,pe,{delete:e=>s(this,C).delete(e)});e.isWebSocketServer?(e.on(`client-message:${l.confirm}`,(t,...r)=>this.handleConfirm(t,...r)),e.on(`client-message:${l.progress}`,(t,...r)=>this.handleProgress(t,...r)),e.on(`client-message:${l.completed}`,(t,...r)=>this.handleCompleted(t,...r)),e.on(`client-message:${l.error}`,(t,...r)=>this.handleError(t,...r)),Object.assign(e,{transfer:(t,r,o)=>this.transfer(t,r,o)})):(e.on(`message:${l.confirm}`,(...t)=>this.handleConfirm(e,...t)),e.on(`message:${l.progress}`,(...t)=>this.handleProgress(e,...t)),e.on(`message:${l.completed}`,(...t)=>this.handleCompleted(e,...t)),e.on(`message:${l.error}`,(...t)=>this.handleError(e,...t)),Object.assign(e,{transfer:(t,r)=>this.transfer(e,t,r)}))}transfer(e,t,r){let{Transfer:o}=this.constructor,h=new o(e,t,r,s(this,pe));return s(this,C).set(h.id,h),h}async handleConfirm(e,t,r){await s(this,C).get(t)?.handleConfirm(r)}handleProgress(e,t,r){s(this,C).get(t)?.handleProgress(r)}async handleCompleted(e,t){await s(this,C).get(t)?.handleCompleted()}handleError(e,t,r){s(this,C).get(t)?.throw(r)}};C=new WeakMap,pe=new WeakMap,i(le,"Transfer",w);function Ie(n){return new Promise(e=>{let t=new FileReader;t.onload=()=>e(typeof t?.result=="string"?t.result.slice(Math.max(0,t.result.indexOf(",")+1)):""),t.readAsDataURL(new Blob([n]))})}var Y,L,ce,we,Se,me=class{constructor(e,t={}){a(this,ce);i(this,"file");i(this,"size");i(this,"chunkSize");i(this,"fileReader");i(this,"listener");a(this,Y,0);a(this,L,0);i(this,"isAborted",!1);a(this,Se,async()=>{if(!this.isAborted){let e=this.fileReader.result;e.length=e.byteLength,await this.listener(e),s(this,L)<this.size&&(f(this,Y,s(this,L)),u(this,ce,we).call(this))}});this.file=e,this.size=this.file.size;let{chunkSize:r=1024*256}=t;this.chunkSize=r,this.fileReader=new FileReader,this.fileReader.onload=s(this,Se)}start(e){this.listener=e,u(this,ce,we).call(this)}abort(){this.isAborted=!0}};Y=new WeakMap,L=new WeakMap,ce=new WeakSet,we=function(){this.isAborted||(f(this,L,Math.min(s(this,Y)+this.chunkSize,this.size)),this.fileReader.readAsArrayBuffer(this.file.slice(s(this,Y),s(this,L))))},Se=new WeakMap;var ge=class extends w{};i(ge,"types",[["file",e=>typeof e=="object"&&e instanceof File,{setup(){let e=this.data;this.fileStreamer=new me(e,{chunkSize:this.chunkSize});let t={name:e.name,type:e.type,size:e.size,modifiedAt:e.lastModified};this.metadata?Object.assign(this.metadata,t):this.metadata=t,this.size=this.fileStreamer.size,this.encoding="buffer"},confirm(){this.fileStreamer.start(this.handleChunk)},transformChunk(e){return Ie(e)}}],...w.types]);var Ce=class extends le{};i(Ce,"Transfer",ge);export{de as IncomingTransfer,Te as IncomingTransport,ge as OutgoingTransfer,Ce as OutgoingTransport}; //# sourceMappingURL=index.js.map