UNPKG

@astrify/react-s3-upload

Version:

React file upload system built for S3-compatible storage with shadcn/ui components

2 lines 124 kB
import{ImageIcon as Fe,UploadIcon as le}from"lucide-react";import{useDropzone as we}from"react-dropzone";import{Slot as ye}from"@radix-ui/react-slot";import{cva as xe}from"class-variance-authority";import{clsx as he}from"clsx";import{twMerge as ve}from"tailwind-merge";function A(...e){return ve(he(e))}import{jsx as be}from"react/jsx-runtime";var Ue=xe("inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",destructive:"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",outline:"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",sm:"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9"}},defaultVariants:{variant:"default",size:"default"}});function L({className:e,variant:t,size:o,asChild:r=!1,...a}){return be(r?ye:"button",{"data-slot":"button",className:A(Ue({variant:t,size:o,className:e})),...a})}import{jsx as T,jsxs as te}from"react/jsx-runtime";function Re(e,t,o,r,a){switch(t){case"file-too-large":return{message:"File size exceeded",details:e.name};case"file-invalid-type":return{message:"Invalid file type",details:e.name};case"too-many-files":return{message:"Too many files",details:e.name};default:return{message:o,details:e.name}}}function ce(e){if(!e)return!1;let t=Object.keys(e);return t.length>0&&t.every(o=>o.startsWith("image/"))}function Se(e,t){return t||(ce(e)?T(Fe,{className:"size-4 opacity-60"}):T(le,{className:"size-4 opacity-60"}))}function Ee(e){if(!e||Object.keys(e).length===0)return"Any file type";let t=[];for(let o of Object.values(e))o&&o.length>0&&t.push(...o.map(r=>r.toUpperCase().replace(".","")));return t.length>0?t.join(", "):"Any file type"}function ze(e,t,o,r,a,i){let n=ce(e),l=t||(n?a===1?"Drop your image here":"Drop your images here":a===1?"Drop file here":"Drop files here"),m=o,u="";if(!m){let g=`max. ${H(r,{si:!1,decimalPlaces:0})}`;m=`${Ee(e)} (${g})`}return a>1&&(u=`${i}/${a}`),{title:l,description:m,fileCountText:u,isImageOnly:n}}function Ne({onDrop:e,maxSize:t,maxFiles:o,accept:r,className:a,emptyIcon:i,emptyTitle:n,emptyDescription:l}){let m=P(),u=t??m.maxFileSize??50*1024*1024,g=o??m.config.maxFiles??10,U=r??m.acceptedFileTypes,E=g>1,F=m.remainingSlots??g,z=N=>{let C=[];for(let _ of N){let{file:W,errors:Z}=_;for(let $ of Z){let q=Re(W,$.code,$.message,u,g);C.push({type:"validation_error",message:q.message,details:q.details})}}return C.length>0&&m.addErrors(C),C},y=e||(async(N,C)=>{m.clearErrors(),C.length>0&&setTimeout(()=>{z(C)},50),N.length>0&&await m.addFiles(N)}),{getRootProps:V,getInputProps:O,isDragActive:X,open:K}=we({onDrop:y,accept:U,maxSize:u,maxFiles:F,multiple:E,noClick:!0}),G=g-F,J=Se(U,i),{title:Q,description:w,fileCountText:M,isImageOnly:Y}=ze(U,n,l,u,g,G);return te("div",{...V({className:A("relative rounded-lg border border-dashed p-6 text-center transition-colors",X?"border-primary bg-primary/5":"border-muted-foreground/25 hover:border-muted-foreground/50",a)}),children:[T("input",{...O(),className:"sr-only","aria-label":"Upload file"}),te("div",{className:"flex flex-col items-center justify-center px-4 py-3 text-center",children:[T("div",{className:"mb-2 flex size-10 shrink-0 items-center justify-center rounded-full border bg-background","aria-hidden":"true",children:J}),T("p",{className:"mb-1.5 font-medium text-sm",children:Q}),T("p",{className:"text-muted-foreground text-xs",children:w}),te(L,{variant:"outline",className:"mt-4",onClick:N=>{N.stopPropagation(),K()},children:[T(le,{className:"-ms-1 size-4 opacity-60","aria-hidden":"true"}),"Select"," ",Y?g===1?"image":"images":g===1?"file":"files"]})]}),M&&T("div",{className:"absolute right-3 bottom-4 text-muted-foreground text-xs",children:M})]})}import{useEffect as Ce}from"react";import{Toaster as Pe,toast as ke}from"sonner";import{jsx as Le}from"react/jsx-runtime";function Ae(){let e=re(),{clearErrors:t}=P();return Ce(()=>{e.length>0&&(e.forEach(o=>{ke.error(o.message,{description:typeof o.details=="string"?o.details:void 0,richColors:!0})}),t())},[e,t]),Le(Pe,{expand:!0})}import{CloudUpload as Te,Trash2 as Be}from"lucide-react";import{useRef as Me}from"react";import{jsx as se,jsxs as I}from"react/jsx-runtime";function De(e){if(!e)return;let t=[];for(let[o,r]of Object.entries(e))t.push(o),r&&r.length>0&&t.push(...r);return t.join(",")}function je({className:e,title:t="Files",showAddButton:o=!0,showClearButton:r=!0,addButtonText:a="Add files",clearButtonText:i="Remove all"}){let{files:n,removeAll:l,addFiles:m,canAcceptMore:u,config:g}=P(),U=Me(null);if(n.length===0)return null;let E=()=>{var z;(z=U.current)==null||z.click()},F=async z=>{let y=Array.from(z.target.files||[]);y.length>0&&await m(y),z.target.value=""};return I("div",{className:A("flex items-center justify-between gap-2",e),children:[se("input",{ref:U,type:"file",multiple:(g.maxFiles??10)>1,accept:De(g.accept),onChange:F,className:"sr-only","aria-label":"Upload file"}),I("h3",{className:"truncate font-medium text-sm",children:[t," (",n.length,")"]}),I("div",{className:"flex gap-2",children:[o&&I(L,{variant:"outline",size:"sm",onClick:E,disabled:!u,children:[se(Te,{className:"-ms-0.5 size-3.5 opacity-60","aria-hidden":"true"}),a]}),r&&n.length>0&&I(L,{variant:"outline",size:"sm",onClick:l,children:[se(Be,{className:"-ms-0.5 size-3.5 opacity-60","aria-hidden":"true"}),i]})]})]})}import{FileArchiveIcon as He,FileIcon as Ie,FileSpreadsheetIcon as Oe,FileTextIcon as _e,HeadphonesIcon as We,ImageIcon as $e,RefreshCwIcon as qe,VideoIcon as Ve,XIcon as Xe}from"lucide-react";import{useEffect as Ke,useState as Ge}from"react";import{jsx as p,jsxs as k}from"react/jsx-runtime";function Je({file:e,showPreview:t}){let[o,r]=Ge(null);if(Ke(()=>{if(t&&e.type.startsWith("image/")){if(e.preview)r(e.preview);else if(e.file instanceof File){let i=URL.createObjectURL(e.file);return r(i),()=>URL.revokeObjectURL(i)}}},[e,t]),t&&o&&e.type.startsWith("image/")){if(e.status==="pending"||e.status==="uploading"){let i=e.status==="pending"?0:e.progress||0;return k("div",{className:"relative size-10 overflow-hidden rounded",children:[p("img",{src:o,alt:e.name,className:"absolute inset-0 size-10 object-cover opacity-30"}),p("div",{className:"absolute inset-0 overflow-hidden",style:{width:`${i}%`},children:p("img",{src:o,alt:e.name,className:"size-10 object-cover"})}),e.status==="uploading"&&i>0&&i<100&&p("div",{className:"absolute inset-y-0 w-0.5 bg-primary/50",style:{left:`${i}%`}})]})}return p("img",{src:o,alt:e.name,className:"size-10 rounded object-cover"})}let a=p("div",{className:"flex size-10 items-center justify-center",children:Qe(e)});return e.status==="pending"?k("div",{className:"relative size-10",children:[a,k("svg",{className:"absolute inset-0 size-10",viewBox:"0 0 40 40","aria-label":"Pending upload",children:[p("title",{children:"Pending upload"}),p("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeDasharray:"4 3",className:"text-muted-foreground/40"})]})]}):e.status==="uploading"&&e.progress>0?k("div",{className:"relative size-10",children:[a,k("svg",{className:"-rotate-90 absolute inset-0 size-10",viewBox:"0 0 40 40","aria-label":"Upload progress",children:[p("title",{children:"Upload progress"}),p("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"text-muted-foreground/20"}),p("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeDasharray:`${2*Math.PI*18}`,strokeDashoffset:`${2*Math.PI*18*(1-e.progress/100)}`,className:"text-primary transition-all duration-300",strokeLinecap:"round"})]})]}):a}function Qe(e){let t=(e instanceof File,e.type),o=(e instanceof File,e.name);return t.includes("pdf")||o.endsWith(".pdf")||t.includes("word")||o.endsWith(".doc")||o.endsWith(".docx")?p(_e,{className:"size-4 opacity-60"}):t.includes("zip")||t.includes("archive")||o.endsWith(".zip")||o.endsWith(".rar")?p(He,{className:"size-4 opacity-60"}):t.includes("excel")||o.endsWith(".xls")||o.endsWith(".xlsx")?p(Oe,{className:"size-4 opacity-60"}):t.includes("video/")?p(Ve,{className:"size-4 opacity-60"}):t.includes("audio/")?p(We,{className:"size-4 opacity-60"}):t.startsWith("image/")?p($e,{className:"size-4 opacity-60"}):p(Ie,{className:"size-4 opacity-60"})}function Ye(e){switch(e.status){case"pending":return p("p",{className:"text-muted-foreground text-xs",children:"Queued"});case"uploading":return k("p",{className:"text-muted-foreground text-xs",children:["Uploading ",e.progress?`${Math.round(e.progress)}%`:""]});case"complete":return p("p",{className:"text-muted-foreground text-xs",children:H(e.size)});case"error":return p("p",{className:"text-destructive text-xs",children:e.error||"Upload failed"});default:return null}}function Ze({showActions:e=!0,showImagePreviews:t=!1,className:o}){let{files:r,removeFile:a,retryUpload:i}=P();return r.length===0?null:p("div",{className:A("space-y-2",o),children:r.map(n=>k("div",{className:A("flex items-center justify-between gap-2 rounded-lg border bg-background p-2 pe-3",n.status==="pending"&&"opacity-60",n.duplicateAlert&&"bg-primary/10"),children:[k("div",{className:"flex items-center gap-3 overflow-hidden",children:[p("div",{className:"shrink-0",children:p(Je,{file:n,showPreview:t})}),k("div",{className:"flex min-w-0 flex-col gap-0.5",children:[p("p",{className:"truncate font-medium text-[13px]",children:n.name}),Ye(n)]})]}),e&&k("div",{className:"flex items-center",children:[n.status==="error"&&p(L,{size:"icon",variant:"ghost",className:"size-8 text-muted-foreground/80 hover:bg-transparent hover:text-foreground",onClick:()=>i(n.sha256),"aria-label":"Retry upload",children:p(qe,{className:"size-4","aria-hidden":"true"})}),p(L,{size:"icon",variant:"ghost",className:"-me-2 size-8 text-muted-foreground/80 hover:bg-transparent hover:text-foreground",onClick:()=>a(n.sha256),"aria-label":"Remove file",children:p(Xe,{className:"size-4","aria-hidden":"true"})})]})]},n.sha256))})}import{createContext as it,useCallback as S,useContext as lt,useEffect as ct,useMemo as B,useRef as ue,useState as ie}from"react";async function oe({file:e,signedUrl:t,sha256:o,onProgress:r,signal:a}){try{await de({file:e,signedUrl:t.url,onProgress:i=>r==null?void 0:r(o,i),signal:a})}catch(i){let n=i instanceof Error?i.message:"Upload failed to S3",l=(i==null?void 0:i.details)||i;throw D("s3_upload",n,l)}}async function ne(e){let t=await e.arrayBuffer(),o=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(o)).map(i=>i.toString(16).padStart(2,"0")).join("")}function et(){var t;let e=(t=document.cookie.split("; ").find(o=>o.startsWith("XSRF-TOKEN=")))==null?void 0:t.split("=")[1];return e?decodeURIComponent(e):null}async function tt(e){let t=new Headers;t.set("Content-Type","application/json"),t.set("X-Requested-With","XMLHttpRequest"),t.set("Accept","application/json");let o=et();if(o&&t.set("X-XSRF-TOKEN",o),e){let r=typeof e=="function"?await e():e;for(let[a,i]of Object.entries(r))a.toLowerCase()!=="content-type"&&a.toLowerCase()!=="accept"&&a.toLowerCase()!=="x-requested-with"&&t.set(a,i)}return t}function rt(e){if(!e.errors)return null;let t=Object.keys(e.errors).filter(o=>o.startsWith("files.")).flatMap(o=>{var r;return(r=e.errors)==null?void 0:r[o]});return t.length>0?t.join(", "):null}function st(e){switch(e){case 401:return"User not authenticated";case 403:return"User not authorized";case 404:return"Upload endpoint not found";case 419:return"Session expired. Please refresh the page";case 429:return"Too many requests. Please try again later";case 500:case 502:case 503:case 504:return"Server error. Please try again later";default:return`Server responded with status ${e}`}}async function ot(e){try{let t=await e.json(),o=rt(t);if(o)return D("validation_error",o,t);let r=t.message||"Invalid file parameters";return D("validation_error",r,t)}catch{return D("validation_error","Invalid file parameters")}}async function nt(e,t){if(e.status===422)throw await ot(e);let o=st(e.status),r={};try{r=await e.json()}catch{}throw D("server_error",t,{...r,status:e.status,details:o})}async function ae(e,t,o){let r=t||"/upload/signed-url",a={files:e.map(({file:n,sha256:l})=>({contentType:n.type||"application/octet-stream",filename:n.name,filesize:n.size,sha256:l}))},i=await tt(o);try{let n=await fetch(r,{method:"POST",headers:i,body:JSON.stringify(a),credentials:"same-origin"});n.ok||await nt(n,"Unable to obtain upload URL");let l=await n.json();if(!(l.files&&Array.isArray(l.files)))throw D("invalid_response","Invalid response from server","Expected array of signed URLs");return l.files}catch(n){if(n.type)throw n;let l="";throw navigator.onLine?n instanceof TypeError&&n.message.includes("Failed to fetch")?l="Unable to reach server":l=n instanceof Error?n.message:"Network request failed":l="No internet connection",D("network_error","Unable to obtain upload URL",l)}}async function de(e){return new Promise((t,o)=>{var i,n;let r=new XMLHttpRequest,a=()=>{r.abort(),o(new Error("Upload aborted"))};if((i=e.signal)!=null&&i.aborted){a();return}if((n=e.signal)==null||n.addEventListener("abort",a),r.onloadend=()=>{var l,m;if((l=e.signal)==null||l.removeEventListener("abort",a),r.readyState===4&&r.status===200)(m=e.onProgress)==null||m.call(e,1),t();else{let u="Upload failed",g="";r.status===403?(u="Upload unauthorized",g="Signed URL may have expired"):r.status===0?(u="Upload failed",g="Network error or CORS issue"):(u="Upload failed",g=`Status ${r.status}`);let U=new Error(u);U.details=g,o(U)}},r.upload.addEventListener("progress",l=>{var m;if(l.lengthComputable){let u=l.loaded/l.total;(m=e.onProgress)==null||m.call(e,u)}}),r.onerror=()=>{var l;(l=e.signal)==null||l.removeEventListener("abort",a),o(new Error("Network error during upload"))},r.open("PUT",e.signedUrl),e.headers)for(let[l,m]of Object.entries(e.headers))r.setRequestHeader(l,m);r.send(e.file)})}function D(e,t,o){return{type:e,message:t,details:o}}function H(e,t={}){let{si:o=!0,decimalPlaces:r=0}=t;if(e===0)return"0 B";let a=o?1e3:1024,i=r<0?0:r,n=o?["B","kB","MB","GB","TB","PB"]:["B","KiB","MiB","GiB","TiB","PiB"],l=Math.floor(Math.log(e)/Math.log(a));if(l===0)return`${e} B`;let m=e/a**l,u=i===0?Math.round(m):Number.parseFloat(m.toFixed(i));return`${i===0?u.toString():u.toFixed(i)} ${n[l]}`}import{jsx as ut}from"react/jsx-runtime";var pe=it(void 0);function dt({children:e,config:t={},defaultFiles:o=[]}){let r=B(()=>({maxFiles:t.maxFiles??10,maxSize:t.maxSize??52428800,accept:t.accept,signedUrlEndpoint:t.signedUrlEndpoint??"/upload/signed-url",signedUrlHeaders:t.signedUrlHeaders,onUploadComplete:t.onUploadComplete,onUploadError:t.onUploadError,onFilesChange:t.onFilesChange,uploadLib:t.uploadLib}),[t.maxFiles,t.maxSize,t.accept,t.signedUrlEndpoint,t.signedUrlHeaders,t.onUploadComplete,t.onUploadError,t.onFilesChange,t.uploadLib]),a=B(()=>{var s,c,h;return{calculateSHA256:((s=r.uploadLib)==null?void 0:s.calculateSHA256)??ne,requestBatchSignedUrls:((c=r.uploadLib)==null?void 0:c.requestBatchSignedUrls)??ae,uploadFile:((h=r.uploadLib)==null?void 0:h.uploadFile)??oe}},[r.uploadLib]),i=B(()=>o.map(s=>({...s,id:s.sha256,status:"complete",progress:100})),[o]),[n,l]=ie(new Map(i.map(s=>[s.sha256,s]))),[m,u]=ie([]),[g,U]=ie(new Set),E=ue(new Map),F=ue(new Map),z=3,y=B(()=>Array.from(n.values()),[n]),V=g.size>0,O=(r.maxFiles??10)-y.length,X=O>0,K=B(()=>y.some(s=>s.status==="pending"),[y]),G=B(()=>y.some(s=>s.status==="uploading"),[y]),J=B(()=>y.some(s=>s.status==="error")||m.length>0,[y,m]),Q=B(()=>y.some(s=>s.status==="complete"),[y]),w=S((s,c)=>{l(h=>{let f=new Map(h),d=f.get(s);return d&&f.set(s,{...d,...c}),f})},[]),M=S(async s=>{let c=[],h=[];try{let f=await a.requestBatchSignedUrls(s.map(d=>({file:F.current.get(d.sha256)||new File([],d.name),sha256:d.sha256})),r.signedUrlEndpoint,r.signedUrlHeaders);s.forEach((d,v)=>{let b=f[v];if(b){let x={id:d.sha256,name:d.name,size:d.size,type:d.type,sha256:d.sha256,url:b.url,status:"pending",progress:0,preview:d.preview,file:F.current.get(d.sha256)};l(R=>{let j=new Map(R);return j.set(d.sha256,x),j}),c.push(d)}})}catch(f){let d=f;h.push(d),s.forEach(v=>{n.has(v.sha256)&&w(v.sha256,{status:"error",error:d.message})})}return{success:c,errors:h}},[r.signedUrlEndpoint,r.signedUrlHeaders,n,w,a]),Y=S(s=>{l(c=>{let h=new Map(c),f=h.get(s);if(f){f.preview&&URL.revokeObjectURL(f.preview);let d=E.current.get(s);d&&(d.abort(),E.current.delete(s)),h.delete(s),F.current.delete(s)}return h}),U(c=>{let h=new Set(c);return h.delete(s),h})},[]),N=S(()=>{for(let s of Array.from(E.current.values()))s.abort();E.current.clear(),U(new Set),n.forEach(s=>{s.preview&&URL.revokeObjectURL(s.preview)}),l(new Map),F.current.clear(),u([])},[n]),C=S(async s=>{var f,d;let c=F.current.get(s.sha256);if(!c)return;let h=new AbortController;E.current.set(s.sha256,h),U(v=>new Set(v).add(s.sha256));try{w(s.sha256,{status:"uploading"}),await a.uploadFile({file:c,sha256:s.sha256,signal:h.signal,signedUrl:{sha256:s.sha256,bucket:"",key:"",url:s.url},onProgress:(b,x)=>{w(s.sha256,{progress:x*100})}}),w(s.sha256,{status:"complete",progress:100});let v=n.get(s.sha256);v&&((f=r.onUploadComplete)==null||f.call(r,[v]))}catch(v){let b=v;b.type==="duplicate_file"?(l(x=>{let R=new Map(x);return R.delete(s.sha256),R}),u(x=>[...x,{type:"duplicate_file",message:`${s.name} was not uploaded`,details:"This file already exists on the server"}])):(w(s.sha256,{status:"error",error:b.message}),(d=r.onUploadError)==null||d.call(r,[{file:c,error:b}]))}finally{E.current.delete(s.sha256),U(v=>{let b=new Set(v);return b.delete(s.sha256),b})}},[r.onUploadComplete,r.onUploadError,w,n,a]);ct(()=>{if(g.size>=z)return;let s=y.filter(f=>f.status==="pending"&&!g.has(f.sha256)),c=z-g.size;s.slice(0,c).forEach(f=>{C(f)})},[y,g,C]);let _=S(async s=>{try{let c=await a.calculateSHA256(s);return F.current.set(c,s),{name:s.name,size:s.size,type:s.type,sha256:c,preview:s.type.startsWith("image/")?URL.createObjectURL(s):void 0}}catch{return null}},[a]),W=S(s=>{w(s,{duplicateAlert:!0}),setTimeout(()=>{w(s,{duplicateAlert:!1})},1e3)},[w]),Z=S(async s=>{u([]);let c=r.maxFiles??10,h=n.size,f=c-h;if(f<=0){u([{type:"validation_error",message:"Maximum files reached",details:`Maximum ${c} files allowed`}]);return}let d=s.slice(0,f);s.length>d.length&&u(x=>[...x,{type:"validation_error",message:"File limit exceeded",details:`Only ${f} more file(s) can be added`}]);let v=[],b=[];for(let x of d){let R=await _(x);if(!R){b.push({type:"validation_error",message:"Failed to process file",details:x.name});continue}n.has(R.sha256)?W(R.sha256):v.push(R)}if(b.length>0&&u(x=>[...x,...b]),v.length>0){let{success:x,errors:R}=await M(v);if(R.length>0&&u(j=>[...j,...R]),x.length>0&&r.onFilesChange){let j=x.map(ee=>F.current.get(ee.sha256)).filter(ee=>ee!==void 0);r.onFilesChange(j)}}},[n,r.maxFiles,r.onFilesChange,M,W,_]),$=S(async s=>{let c=n.get(s),h=F.current.get(s);if(!(c&&h)||g.has(s))return;let f={name:c.name,size:c.size,type:c.type,sha256:c.sha256,preview:c.preview},{errors:d}=await M([f]);d.length>0&&u(v=>[...v,...d])},[n,g,M]),q=S(()=>{N()},[N]),me=S(s=>{s.length>0&&u(c=>[...c,...s])},[]),ge=S(()=>{u([])},[]),fe={files:y,errors:m,isUploading:V,remainingSlots:O,config:r,hasPending:K,hasUploading:G,hasErrors:J,hasComplete:Q,addFiles:Z,removeFile:Y,removeAll:N,retryUpload:$,reset:q,addErrors:me,clearErrors:ge,canAcceptMore:X,acceptedFileTypes:r.accept,maxFileSize:r.maxSize??50*1024*1024};return ut(pe.Provider,{value:fe,children:e})}function P(){let e=lt(pe);if(!e)throw new Error("useFileUpload must be used within FileUploadProvider");return e}function re(){let{errors:e}=P();return e}export{Ne as Dropzone,Ae as Errors,dt as FileUploadProvider,je as Header,Ze as List,ne as calculateSHA256,H as formatBytes,ae as requestBatchSignedUrls,oe as uploadFile,de as uploadToS3Storage,re as useFileErrors,P as useFileUpload}; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvbXBvbmVudHMvYXN0cmlmeS91cGxvYWQvZHJvcHpvbmUudHN4IiwgIi4uL3NyYy9jb21wb25lbnRzL3VpL2J1dHRvbi50c3giLCAiLi4vc3JjL2xpYi91dGlscy50cyIsICIuLi9zcmMvY29tcG9uZW50cy9hc3RyaWZ5L3VwbG9hZC9lcnJvcnMudHN4IiwgIi4uL3NyYy9jb21wb25lbnRzL2FzdHJpZnkvdXBsb2FkL2hlYWRlci50c3giLCAiLi4vc3JjL2NvbXBvbmVudHMvYXN0cmlmeS91cGxvYWQvbGlzdC50c3giLCAiLi4vc3JjL0ZpbGVVcGxvYWRDb250ZXh0LnRzeCIsICIuLi9zcmMvbGliL3VwbG9hZC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHsgZm9ybWF0Qnl0ZXMsIHVzZUZpbGVVcGxvYWQgfSBmcm9tIFwiQGFzdHJpZnkvcmVhY3QtczMtdXBsb2FkXCI7XG5pbXBvcnQgeyBJbWFnZUljb24sIFVwbG9hZEljb24gfSBmcm9tIFwibHVjaWRlLXJlYWN0XCI7XG5pbXBvcnQgdHlwZSAqIGFzIFJlYWN0IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdHlwZSBBY2NlcHQsIHR5cGUgRmlsZVJlamVjdGlvbiwgdXNlRHJvcHpvbmUgfSBmcm9tIFwicmVhY3QtZHJvcHpvbmVcIjtcbmltcG9ydCB7IEJ1dHRvbiB9IGZyb20gXCJAL2NvbXBvbmVudHMvdWkvYnV0dG9uXCI7XG5pbXBvcnQgeyBjbiB9IGZyb20gXCJAL2xpYi91dGlsc1wiO1xuXG5pbnRlcmZhY2UgRHJvcHpvbmVQcm9wcyB7XG5cdG9uRHJvcD86IChhY2NlcHRlZEZpbGVzOiBGaWxlW10sIHJlamVjdGVkRmlsZXM6IEZpbGVSZWplY3Rpb25bXSkgPT4gdm9pZDtcblx0bWF4U2l6ZT86IG51bWJlcjtcblx0bWF4RmlsZXM/OiBudW1iZXI7XG5cdGFjY2VwdD86IEFjY2VwdDtcblx0Y2xhc3NOYW1lPzogc3RyaW5nO1xuXHRjaGlsZHJlbj86IFJlYWN0LlJlYWN0Tm9kZTtcblx0aGlkZURlZmF1bHRDb250ZW50PzogYm9vbGVhbjtcblx0ZW1wdHlJY29uPzogUmVhY3QuUmVhY3ROb2RlO1xuXHRlbXB0eVRpdGxlPzogc3RyaW5nO1xuXHRlbXB0eURlc2NyaXB0aW9uPzogc3RyaW5nO1xufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gZm9ybWF0IHJlamVjdGlvbiBlcnJvciBtZXNzYWdlc1xuZnVuY3Rpb24gZm9ybWF0UmVqZWN0aW9uRXJyb3IoXG5cdGZpbGU6IEZpbGUsXG5cdGVycm9yQ29kZTogc3RyaW5nLFxuXHRlcnJvck1lc3NhZ2U6IHN0cmluZyxcblx0X21heFNpemU6IG51bWJlcixcblx0X21heEZpbGVzOiBudW1iZXIsXG4pOiB7IG1lc3NhZ2U6IHN0cmluZzsgZGV0YWlsczogc3RyaW5nIH0ge1xuXHRzd2l0Y2ggKGVycm9yQ29kZSkge1xuXHRcdGNhc2UgXCJmaWxlLXRvby1sYXJnZVwiOlxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0bWVzc2FnZTogXCJGaWxlIHNpemUgZXhjZWVkZWRcIixcblx0XHRcdFx0ZGV0YWlsczogZmlsZS5uYW1lLFxuXHRcdFx0fTtcblx0XHRjYXNlIFwiZmlsZS1pbnZhbGlkLXR5cGVcIjpcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdG1lc3NhZ2U6IFwiSW52YWxpZCBmaWxlIHR5cGVcIixcblx0XHRcdFx0ZGV0YWlsczogZmlsZS5uYW1lLFxuXHRcdFx0fTtcblx0XHRjYXNlIFwidG9vLW1hbnktZmlsZXNcIjpcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdG1lc3NhZ2U6IFwiVG9vIG1hbnkgZmlsZXNcIixcblx0XHRcdFx0ZGV0YWlsczogZmlsZS5uYW1lLFxuXHRcdFx0fTtcblx0XHRkZWZhdWx0OlxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0bWVzc2FnZTogZXJyb3JNZXNzYWdlLFxuXHRcdFx0XHRkZXRhaWxzOiBmaWxlLm5hbWUsXG5cdFx0XHR9O1xuXHR9XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayBpZiBhY2NlcHQgb25seSBhbGxvd3MgaW1hZ2VzXG5mdW5jdGlvbiBpc0ltYWdlT25seUFjY2VwdChhY2NlcHQ6IEFjY2VwdCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuXHRpZiAoIWFjY2VwdCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRjb25zdCBtaW1lVHlwZXMgPSBPYmplY3Qua2V5cyhhY2NlcHQpO1xuXHRyZXR1cm4gKFxuXHRcdG1pbWVUeXBlcy5sZW5ndGggPiAwICYmIG1pbWVUeXBlcy5ldmVyeSgodHlwZSkgPT4gdHlwZS5zdGFydHNXaXRoKFwiaW1hZ2UvXCIpKVxuXHQpO1xufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IGRyb3B6b25lIGljb25cbmZ1bmN0aW9uIGdldERyb3B6b25lSWNvbihcblx0YWNjZXB0OiBBY2NlcHQgfCB1bmRlZmluZWQsXG5cdGVtcHR5SWNvbjogUmVhY3QuUmVhY3ROb2RlIHwgdW5kZWZpbmVkLFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcblx0aWYgKGVtcHR5SWNvbikge1xuXHRcdHJldHVybiBlbXB0eUljb247XG5cdH1cblxuXHRjb25zdCBpc0ltYWdlT25seSA9IGlzSW1hZ2VPbmx5QWNjZXB0KGFjY2VwdCk7XG5cdGlmIChpc0ltYWdlT25seSkge1xuXHRcdHJldHVybiA8SW1hZ2VJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0cmV0dXJuIDxVcGxvYWRJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBnZW5lcmF0ZSBmaWxlIHR5cGUgZGVzY3JpcHRpb24gZnJvbSBBY2NlcHQgb2JqZWN0XG5mdW5jdGlvbiBnZXRBY2NlcHREZXNjcmlwdGlvbihhY2NlcHQ6IEFjY2VwdCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG5cdGlmICghYWNjZXB0IHx8IE9iamVjdC5rZXlzKGFjY2VwdCkubGVuZ3RoID09PSAwKSB7XG5cdFx0cmV0dXJuIFwiQW55IGZpbGUgdHlwZVwiO1xuXHR9XG5cblx0Y29uc3QgYWxsRXh0ZW5zaW9uczogc3RyaW5nW10gPSBbXTtcblxuXHRmb3IgKGNvbnN0IGV4dGVuc2lvbnMgb2YgT2JqZWN0LnZhbHVlcyhhY2NlcHQpKSB7XG5cdFx0aWYgKGV4dGVuc2lvbnMgJiYgZXh0ZW5zaW9ucy5sZW5ndGggPiAwKSB7XG5cdFx0XHRhbGxFeHRlbnNpb25zLnB1c2goXG5cdFx0XHRcdC4uLmV4dGVuc2lvbnMubWFwKChleHQpID0+IGV4dC50b1VwcGVyQ2FzZSgpLnJlcGxhY2UoXCIuXCIsIFwiXCIpKSxcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGFsbEV4dGVuc2lvbnMubGVuZ3RoID4gMCA/IGFsbEV4dGVuc2lvbnMuam9pbihcIiwgXCIpIDogXCJBbnkgZmlsZSB0eXBlXCI7XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBnZXQgZHJvcHpvbmUgdGV4dCBjb250ZW50XG5mdW5jdGlvbiBnZXREcm9wem9uZVRleHQoXG5cdGFjY2VwdDogQWNjZXB0IHwgdW5kZWZpbmVkLFxuXHRlbXB0eVRpdGxlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG5cdGVtcHR5RGVzY3JpcHRpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcblx0bWF4U2l6ZTogbnVtYmVyLFxuXHRtYXhGaWxlczogbnVtYmVyLFxuXHRjdXJyZW50RmlsZUNvdW50OiBudW1iZXIsXG4pIHtcblx0Y29uc3QgaXNJbWFnZU9ubHkgPSBpc0ltYWdlT25seUFjY2VwdChhY2NlcHQpO1xuXG5cdGNvbnN0IHRpdGxlID1cblx0XHRlbXB0eVRpdGxlIHx8XG5cdFx0KGlzSW1hZ2VPbmx5XG5cdFx0XHQ/IG1heEZpbGVzID09PSAxXG5cdFx0XHRcdD8gXCJEcm9wIHlvdXIgaW1hZ2UgaGVyZVwiXG5cdFx0XHRcdDogXCJEcm9wIHlvdXIgaW1hZ2VzIGhlcmVcIlxuXHRcdFx0OiBtYXhGaWxlcyA9PT0gMVxuXHRcdFx0XHQ/IFwiRHJvcCBmaWxlIGhlcmVcIlxuXHRcdFx0XHQ6IFwiRHJvcCBmaWxlcyBoZXJlXCIpO1xuXG5cdGxldCBkZXNjcmlwdGlvbiA9IGVtcHR5RGVzY3JpcHRpb247XG5cdGxldCBmaWxlQ291bnRUZXh0ID0gXCJcIjtcblxuXHRpZiAoIWRlc2NyaXB0aW9uKSB7XG5cdFx0Y29uc3Qgc2l6ZVRleHQgPSBgbWF4LiAke2Zvcm1hdEJ5dGVzKG1heFNpemUsIHsgc2k6IGZhbHNlLCBkZWNpbWFsUGxhY2VzOiAwIH0pfWA7XG5cdFx0Y29uc3QgZmlsZVR5cGVzID0gZ2V0QWNjZXB0RGVzY3JpcHRpb24oYWNjZXB0KTtcblx0XHRkZXNjcmlwdGlvbiA9IGAke2ZpbGVUeXBlc30gKCR7c2l6ZVRleHR9KWA7XG5cdH1cblxuXHQvLyBBZGQgZmlsZSBjb3VudCBvbiBzZXBhcmF0ZSBsaW5lIGlmIG1heEZpbGVzID4gMVxuXHRpZiAobWF4RmlsZXMgPiAxKSB7XG5cdFx0ZmlsZUNvdW50VGV4dCA9IGAke2N1cnJlbnRGaWxlQ291bnR9LyR7bWF4RmlsZXN9YDtcblx0fVxuXG5cdHJldHVybiB7IHRpdGxlLCBkZXNjcmlwdGlvbiwgZmlsZUNvdW50VGV4dCwgaXNJbWFnZU9ubHkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIERyb3B6b25lKHtcblx0b25Ecm9wOiBvbkRyb3BQcm9wLFxuXHRtYXhTaXplOiBtYXhTaXplUHJvcCxcblx0bWF4RmlsZXM6IG1heEZpbGVzUHJvcCxcblx0YWNjZXB0OiBhY2NlcHRQcm9wLFxuXHRjbGFzc05hbWUsXG5cdGVtcHR5SWNvbixcblx0ZW1wdHlUaXRsZSxcblx0ZW1wdHlEZXNjcmlwdGlvbixcbn06IERyb3B6b25lUHJvcHMpIHtcblx0Ly8gR2V0IGNvbmZpZyBmcm9tIGNvbnRleHQgKHJlcXVpcmVkKVxuXHRjb25zdCBjb250ZXh0ID0gdXNlRmlsZVVwbG9hZCgpO1xuXG5cdGNvbnN0IG1heFNpemUgPSBtYXhTaXplUHJvcCA/PyBjb250ZXh0Lm1heEZpbGVTaXplID8/IDUwICogMTAyNCAqIDEwMjQ7XG5cdGNvbnN0IG1heEZpbGVzID0gbWF4RmlsZXNQcm9wID8/IGNvbnRleHQuY29uZmlnLm1heEZpbGVzID8/IDEwO1xuXHRjb25zdCBhY2NlcHQgPSBhY2NlcHRQcm9wID8/IGNvbnRleHQuYWNjZXB0ZWRGaWxlVHlwZXM7XG5cdGNvbnN0IG11bHRpcGxlID0gbWF4RmlsZXMgPiAxO1xuXHRjb25zdCByZW1haW5pbmdTbG90cyA9IGNvbnRleHQucmVtYWluaW5nU2xvdHMgPz8gbWF4RmlsZXM7XG5cblx0Ly8gSGFuZGxlIGZpbGUgcmVqZWN0aW9ucyBhbmQgZm9ybWF0IGVycm9yIG1lc3NhZ2VzXG5cdGNvbnN0IGhhbmRsZVJlamVjdGlvbnMgPSAoZmlsZVJlamVjdGlvbnM6IEZpbGVSZWplY3Rpb25bXSkgPT4ge1xuXHRcdGNvbnN0IGVycm9yTWVzc2FnZXM6IEFycmF5PHtcblx0XHRcdHR5cGU6IFwidmFsaWRhdGlvbl9lcnJvclwiO1xuXHRcdFx0bWVzc2FnZTogc3RyaW5nO1xuXHRcdFx0ZGV0YWlsczogc3RyaW5nO1xuXHRcdH0+ID0gW107XG5cblx0XHRmb3IgKGNvbnN0IHJlamVjdGlvbiBvZiBmaWxlUmVqZWN0aW9ucykge1xuXHRcdFx0Y29uc3QgeyBmaWxlLCBlcnJvcnMgfSA9IHJlamVjdGlvbjtcblx0XHRcdGZvciAoY29uc3QgZXJyb3Igb2YgZXJyb3JzKSB7XG5cdFx0XHRcdGNvbnN0IGZvcm1hdHRlZCA9IGZvcm1hdFJlamVjdGlvbkVycm9yKFxuXHRcdFx0XHRcdGZpbGUsXG5cdFx0XHRcdFx0ZXJyb3IuY29kZSxcblx0XHRcdFx0XHRlcnJvci5tZXNzYWdlLFxuXHRcdFx0XHRcdG1heFNpemUsXG5cdFx0XHRcdFx0bWF4RmlsZXMsXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGVycm9yTWVzc2FnZXMucHVzaCh7XG5cdFx0XHRcdFx0dHlwZTogXCJ2YWxpZGF0aW9uX2Vycm9yXCIsXG5cdFx0XHRcdFx0bWVzc2FnZTogZm9ybWF0dGVkLm1lc3NhZ2UsXG5cdFx0XHRcdFx0ZGV0YWlsczogZm9ybWF0dGVkLmRldGFpbHMsXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFB1c2ggZXJyb3JzIHRvIGNvbnRleHRcblx0XHRpZiAoZXJyb3JNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb250ZXh0LmFkZEVycm9ycyhlcnJvck1lc3NhZ2VzKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXJyb3JNZXNzYWdlcztcblx0fTtcblxuXHQvLyBVc2UgY29udGV4dCBhZGRGaWxlcyBhbmQgb3B0aW9uYWwgY3VzdG9tIG9uRHJvcFxuXHRjb25zdCBoYW5kbGVEcm9wID1cblx0XHRvbkRyb3BQcm9wIHx8XG5cdFx0KGFzeW5jIChhY2NlcHRlZEZpbGVzOiBGaWxlW10sIGZpbGVSZWplY3Rpb25zOiBGaWxlUmVqZWN0aW9uW10pID0+IHtcblx0XHRcdC8vIENsZWFyIGFueSBleGlzdGluZyBlcnJvcnMgYXQgdGhlIHN0YXJ0IG9mIGEgbmV3IGRyb3Bcblx0XHRcdGNvbnRleHQuY2xlYXJFcnJvcnMoKTtcblxuXHRcdFx0Ly8gSGFuZGxlIHJlamVjdGlvbnMgd2l0aCBhIHNtYWxsIGRlbGF5IHRvIHRyaWdnZXIgcmUtYW5pbWF0aW9uXG5cdFx0XHRpZiAoZmlsZVJlamVjdGlvbnMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0XHRoYW5kbGVSZWplY3Rpb25zKGZpbGVSZWplY3Rpb25zKTtcblx0XHRcdFx0fSwgNTApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaGVuIGhhbmRsZSBhY2NlcHRlZCBmaWxlc1xuXHRcdFx0aWYgKGFjY2VwdGVkRmlsZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRhd2FpdCBjb250ZXh0LmFkZEZpbGVzKGFjY2VwdGVkRmlsZXMpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdGNvbnN0IHsgZ2V0Um9vdFByb3BzLCBnZXRJbnB1dFByb3BzLCBpc0RyYWdBY3RpdmUsIG9wZW4gfSA9IHVzZURyb3B6b25lKHtcblx0XHRvbkRyb3A6IGhhbmRsZURyb3AsXG5cdFx0YWNjZXB0LFxuXHRcdG1heFNpemUsXG5cdFx0bWF4RmlsZXM6IHJlbWFpbmluZ1Nsb3RzLFxuXHRcdG11bHRpcGxlLFxuXHRcdG5vQ2xpY2s6IHRydWUsIC8vIFdlJ2xsIGhhbmRsZSBjbGljayBtYW51YWxseVxuXHR9KTtcblxuXHRjb25zdCBjdXJyZW50RmlsZUNvdW50ID0gbWF4RmlsZXMgLSByZW1haW5pbmdTbG90cztcblxuXHRjb25zdCBpY29uID0gZ2V0RHJvcHpvbmVJY29uKGFjY2VwdCwgZW1wdHlJY29uKTtcblxuXHRjb25zdCB7IHRpdGxlLCBkZXNjcmlwdGlvbiwgZmlsZUNvdW50VGV4dCwgaXNJbWFnZU9ubHkgfSA9IGdldERyb3B6b25lVGV4dChcblx0XHRhY2NlcHQsXG5cdFx0ZW1wdHlUaXRsZSxcblx0XHRlbXB0eURlc2NyaXB0aW9uLFxuXHRcdG1heFNpemUsXG5cdFx0bWF4RmlsZXMsXG5cdFx0Y3VycmVudEZpbGVDb3VudCxcblx0KTtcblxuXHRyZXR1cm4gKFxuXHRcdDxkaXZcblx0XHRcdHsuLi5nZXRSb290UHJvcHMoe1xuXHRcdFx0XHRjbGFzc05hbWU6IGNuKFxuXHRcdFx0XHRcdFwicmVsYXRpdmUgcm91bmRlZC1sZyBib3JkZXIgYm9yZGVyLWRhc2hlZCBwLTYgdGV4dC1jZW50ZXIgdHJhbnNpdGlvbi1jb2xvcnNcIixcblx0XHRcdFx0XHRpc0RyYWdBY3RpdmVcblx0XHRcdFx0XHRcdD8gXCJib3JkZXItcHJpbWFyeSBiZy1wcmltYXJ5LzVcIlxuXHRcdFx0XHRcdFx0OiBcImJvcmRlci1tdXRlZC1mb3JlZ3JvdW5kLzI1IGhvdmVyOmJvcmRlci1tdXRlZC1mb3JlZ3JvdW5kLzUwXCIsXG5cdFx0XHRcdFx0Y2xhc3NOYW1lLFxuXHRcdFx0XHQpLFxuXHRcdFx0fSl9XG5cdFx0PlxuXHRcdFx0PGlucHV0XG5cdFx0XHRcdHsuLi5nZXRJbnB1dFByb3BzKCl9XG5cdFx0XHRcdGNsYXNzTmFtZT1cInNyLW9ubHlcIlxuXHRcdFx0XHRhcmlhLWxhYmVsPVwiVXBsb2FkIGZpbGVcIlxuXHRcdFx0Lz5cblxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweC00IHB5LTMgdGV4dC1jZW50ZXJcIj5cblx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdGNsYXNzTmFtZT1cIm1iLTIgZmxleCBzaXplLTEwIHNocmluay0wIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLWZ1bGwgYm9yZGVyIGJnLWJhY2tncm91bmRcIlxuXHRcdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG5cdFx0XHRcdD5cblx0XHRcdFx0XHR7aWNvbn1cblx0XHRcdFx0PC9kaXY+XG5cblx0XHRcdFx0PHAgY2xhc3NOYW1lPVwibWItMS41IGZvbnQtbWVkaXVtIHRleHQtc21cIj57dGl0bGV9PC9wPlxuXHRcdFx0XHQ8cCBjbGFzc05hbWU9XCJ0ZXh0LW11dGVkLWZvcmVncm91bmQgdGV4dC14c1wiPntkZXNjcmlwdGlvbn08L3A+XG5cdFx0XHRcdDxCdXR0b25cblx0XHRcdFx0XHR2YXJpYW50PVwib3V0bGluZVwiXG5cdFx0XHRcdFx0Y2xhc3NOYW1lPVwibXQtNFwiXG5cdFx0XHRcdFx0b25DbGljaz17KGUpID0+IHtcblx0XHRcdFx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0XHRvcGVuKCk7XG5cdFx0XHRcdFx0fX1cblx0XHRcdFx0PlxuXHRcdFx0XHRcdDxVcGxvYWRJY29uIGNsYXNzTmFtZT1cIi1tcy0xIHNpemUtNCBvcGFjaXR5LTYwXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCIgLz5cblx0XHRcdFx0XHRTZWxlY3R7XCIgXCJ9XG5cdFx0XHRcdFx0e2lzSW1hZ2VPbmx5XG5cdFx0XHRcdFx0XHQ/IG1heEZpbGVzID09PSAxXG5cdFx0XHRcdFx0XHRcdD8gXCJpbWFnZVwiXG5cdFx0XHRcdFx0XHRcdDogXCJpbWFnZXNcIlxuXHRcdFx0XHRcdFx0OiBtYXhGaWxlcyA9PT0gMVxuXHRcdFx0XHRcdFx0XHQ/IFwiZmlsZVwiXG5cdFx0XHRcdFx0XHRcdDogXCJmaWxlc1wifVxuXHRcdFx0XHQ8L0J1dHRvbj5cblx0XHRcdDwvZGl2PlxuXG5cdFx0XHR7ZmlsZUNvdW50VGV4dCAmJiAoXG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiYWJzb2x1dGUgcmlnaHQtMyBib3R0b20tNCB0ZXh0LW11dGVkLWZvcmVncm91bmQgdGV4dC14c1wiPlxuXHRcdFx0XHRcdHtmaWxlQ291bnRUZXh0fVxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdCl9XG5cdFx0PC9kaXY+XG5cdCk7XG59XG4iLCAiaW1wb3J0IHsgU2xvdCB9IGZyb20gXCJAcmFkaXgtdWkvcmVhY3Qtc2xvdFwiO1xuaW1wb3J0IHsgdHlwZSBWYXJpYW50UHJvcHMsIGN2YSB9IGZyb20gXCJjbGFzcy12YXJpYW5jZS1hdXRob3JpdHlcIjtcbmltcG9ydCB0eXBlICogYXMgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5cbmltcG9ydCB7IGNuIH0gZnJvbSBcIkAvbGliL3V0aWxzXCI7XG5cbmNvbnN0IGJ1dHRvblZhcmlhbnRzID0gY3ZhKFxuXHRcImlubGluZS1mbGV4IHNocmluay0wIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBnYXAtMiB3aGl0ZXNwYWNlLW5vd3JhcCByb3VuZGVkLW1kIGZvbnQtbWVkaXVtIHRleHQtc20gb3V0bGluZS1ub25lIHRyYW5zaXRpb24tYWxsIGZvY3VzLXZpc2libGU6Ym9yZGVyLXJpbmcgZm9jdXMtdmlzaWJsZTpyaW5nLVszcHhdIGZvY3VzLXZpc2libGU6cmluZy1yaW5nLzUwIGRpc2FibGVkOnBvaW50ZXItZXZlbnRzLW5vbmUgZGlzYWJsZWQ6b3BhY2l0eS01MCBhcmlhLWludmFsaWQ6Ym9yZGVyLWRlc3RydWN0aXZlIGFyaWEtaW52YWxpZDpyaW5nLWRlc3RydWN0aXZlLzIwIGRhcms6YXJpYS1pbnZhbGlkOnJpbmctZGVzdHJ1Y3RpdmUvNDAgWyZfc3ZnOm5vdChbY2xhc3MqPSdzaXplLSddKV06c2l6ZS00IFsmX3N2Z106cG9pbnRlci1ldmVudHMtbm9uZSBbJl9zdmddOnNocmluay0wXCIsXG5cdHtcblx0XHR2YXJpYW50czoge1xuXHRcdFx0dmFyaWFudDoge1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFwiYmctcHJpbWFyeSB0ZXh0LXByaW1hcnktZm9yZWdyb3VuZCBzaGFkb3cteHMgaG92ZXI6YmctcHJpbWFyeS85MFwiLFxuXHRcdFx0XHRkZXN0cnVjdGl2ZTpcblx0XHRcdFx0XHRcImJnLWRlc3RydWN0aXZlIHRleHQtd2hpdGUgc2hhZG93LXhzIGhvdmVyOmJnLWRlc3RydWN0aXZlLzkwIGZvY3VzLXZpc2libGU6cmluZy1kZXN0cnVjdGl2ZS8yMCBkYXJrOmJnLWRlc3RydWN0aXZlLzYwIGRhcms6Zm9jdXMtdmlzaWJsZTpyaW5nLWRlc3RydWN0aXZlLzQwXCIsXG5cdFx0XHRcdG91dGxpbmU6XG5cdFx0XHRcdFx0XCJib3JkZXIgYmctYmFja2dyb3VuZCBzaGFkb3cteHMgaG92ZXI6YmctYWNjZW50IGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQgZGFyazpib3JkZXItaW5wdXQgZGFyazpiZy1pbnB1dC8zMCBkYXJrOmhvdmVyOmJnLWlucHV0LzUwXCIsXG5cdFx0XHRcdHNlY29uZGFyeTpcblx0XHRcdFx0XHRcImJnLXNlY29uZGFyeSB0ZXh0LXNlY29uZGFyeS1mb3JlZ3JvdW5kIHNoYWRvdy14cyBob3ZlcjpiZy1zZWNvbmRhcnkvODBcIixcblx0XHRcdFx0Z2hvc3Q6XG5cdFx0XHRcdFx0XCJob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCBkYXJrOmhvdmVyOmJnLWFjY2VudC81MFwiLFxuXHRcdFx0XHRsaW5rOiBcInRleHQtcHJpbWFyeSB1bmRlcmxpbmUtb2Zmc2V0LTQgaG92ZXI6dW5kZXJsaW5lXCIsXG5cdFx0XHR9LFxuXHRcdFx0c2l6ZToge1xuXHRcdFx0XHRkZWZhdWx0OiBcImgtOSBweC00IHB5LTIgaGFzLVs+c3ZnXTpweC0zXCIsXG5cdFx0XHRcdHNtOiBcImgtOCBnYXAtMS41IHJvdW5kZWQtbWQgcHgtMyBoYXMtWz5zdmddOnB4LTIuNVwiLFxuXHRcdFx0XHRsZzogXCJoLTEwIHJvdW5kZWQtbWQgcHgtNiBoYXMtWz5zdmddOnB4LTRcIixcblx0XHRcdFx0aWNvbjogXCJzaXplLTlcIixcblx0XHRcdH0sXG5cdFx0fSxcblx0XHRkZWZhdWx0VmFyaWFudHM6IHtcblx0XHRcdHZhcmlhbnQ6IFwiZGVmYXVsdFwiLFxuXHRcdFx0c2l6ZTogXCJkZWZhdWx0XCIsXG5cdFx0fSxcblx0fSxcbik7XG5cbmZ1bmN0aW9uIEJ1dHRvbih7XG5cdGNsYXNzTmFtZSxcblx0dmFyaWFudCxcblx0c2l6ZSxcblx0YXNDaGlsZCA9IGZhbHNlLFxuXHQuLi5wcm9wc1xufTogUmVhY3QuQ29tcG9uZW50UHJvcHM8XCJidXR0b25cIj4gJlxuXHRWYXJpYW50UHJvcHM8dHlwZW9mIGJ1dHRvblZhcmlhbnRzPiAmIHtcblx0XHRhc0NoaWxkPzogYm9vbGVhbjtcblx0fSkge1xuXHRjb25zdCBDb21wID0gYXNDaGlsZCA/IFNsb3QgOiBcImJ1dHRvblwiO1xuXG5cdHJldHVybiAoXG5cdFx0PENvbXBcblx0XHRcdGRhdGEtc2xvdD1cImJ1dHRvblwiXG5cdFx0XHRjbGFzc05hbWU9e2NuKGJ1dHRvblZhcmlhbnRzKHsgdmFyaWFudCwgc2l6ZSwgY2xhc3NOYW1lIH0pKX1cblx0XHRcdHsuLi5wcm9wc31cblx0XHQvPlxuXHQpO1xufVxuXG5leHBvcnQgeyBCdXR0b24sIGJ1dHRvblZhcmlhbnRzIH07XG4iLCAiaW1wb3J0IHsgdHlwZSBDbGFzc1ZhbHVlLCBjbHN4IH0gZnJvbSBcImNsc3hcIjtcbmltcG9ydCB7IHR3TWVyZ2UgfSBmcm9tIFwidGFpbHdpbmQtbWVyZ2VcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNuKC4uLmlucHV0czogQ2xhc3NWYWx1ZVtdKSB7XG5cdHJldHVybiB0d01lcmdlKGNsc3goaW5wdXRzKSk7XG59XG4iLCAiaW1wb3J0IHsgdXNlRmlsZUVycm9ycywgdXNlRmlsZVVwbG9hZCB9IGZyb20gXCJAYXN0cmlmeS9yZWFjdC1zMy11cGxvYWRcIjtcbmltcG9ydCB7IHVzZUVmZmVjdCB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgVG9hc3RlciwgdG9hc3QgfSBmcm9tIFwic29ubmVyXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBFcnJvcnMoKSB7XG5cdGNvbnN0IGVycm9ycyA9IHVzZUZpbGVFcnJvcnMoKTtcblx0Y29uc3QgeyBjbGVhckVycm9ycyB9ID0gdXNlRmlsZVVwbG9hZCgpO1xuXG5cdC8vIFNob3cgZXJyb3JzIGFzIHRvYXN0c1xuXHR1c2VFZmZlY3QoKCkgPT4ge1xuXHRcdGlmIChlcnJvcnMubGVuZ3RoID4gMCkge1xuXHRcdFx0Ly8gU2hvdyB0b2FzdHMgZm9yIGFsbCBlcnJvcnNcblx0XHRcdGVycm9ycy5mb3JFYWNoKChlcnJvcikgPT4ge1xuXHRcdFx0XHR0b2FzdC5lcnJvcihlcnJvci5tZXNzYWdlLCB7XG5cdFx0XHRcdFx0ZGVzY3JpcHRpb246XG5cdFx0XHRcdFx0XHR0eXBlb2YgZXJyb3IuZGV0YWlscyA9PT0gXCJzdHJpbmdcIiA/IGVycm9yLmRldGFpbHMgOiB1bmRlZmluZWQsXG5cdFx0XHRcdFx0cmljaENvbG9yczogdHJ1ZSxcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gQ2xlYXIgZXJyb3JzIGltbWVkaWF0ZWx5IGFmdGVyIHNob3dpbmcgdG9hc3RzXG5cdFx0XHRjbGVhckVycm9ycygpO1xuXHRcdH1cblx0fSwgW2Vycm9ycywgY2xlYXJFcnJvcnNdKTtcblxuXHQvLyBSZXBsYWNlIHdpdGggbnVsbCBpZiB5b3UncmUgbG9hZGluZyB0aGUgVG9hc3RlciBpbiBhIGRpZmZlcmVudCBjb21wb25lbnRcblx0cmV0dXJuIDxUb2FzdGVyIGV4cGFuZD17dHJ1ZX0gLz47XG59XG4iLCAiaW1wb3J0IHsgdXNlRmlsZVVwbG9hZCB9IGZyb20gXCJAYXN0cmlmeS9yZWFjdC1zMy11cGxvYWRcIjtcbmltcG9ydCB7IENsb3VkVXBsb2FkLCBUcmFzaDIgfSBmcm9tIFwibHVjaWRlLXJlYWN0XCI7XG5pbXBvcnQgdHlwZSBSZWFjdCBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZVJlZiB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHR5cGUgeyBBY2NlcHQgfSBmcm9tIFwicmVhY3QtZHJvcHpvbmVcIjtcbmltcG9ydCB7IEJ1dHRvbiB9IGZyb20gXCJAL2NvbXBvbmVudHMvdWkvYnV0dG9uXCI7XG5pbXBvcnQgeyBjbiB9IGZyb20gXCJAL2xpYi91dGlsc1wiO1xuXG4vLyBDb252ZXJ0IEFjY2VwdCBvYmplY3QgdG8gSFRNTCBpbnB1dCBhY2NlcHQgc3RyaW5nXG5mdW5jdGlvbiBhY2NlcHRUb1N0cmluZyhhY2NlcHQ6IEFjY2VwdCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG5cdGlmICghYWNjZXB0KSB7XG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuXHRmb3IgKGNvbnN0IFttaW1lVHlwZSwgZXh0ZW5zaW9uc10gb2YgT2JqZWN0LmVudHJpZXMoYWNjZXB0KSkge1xuXHRcdHBhcnRzLnB1c2gobWltZVR5cGUpO1xuXHRcdGlmIChleHRlbnNpb25zICYmIGV4dGVuc2lvbnMubGVuZ3RoID4gMCkge1xuXHRcdFx0cGFydHMucHVzaCguLi5leHRlbnNpb25zKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHBhcnRzLmpvaW4oXCIsXCIpO1xufVxuXG5pbnRlcmZhY2UgSGVhZGVyUHJvcHMge1xuXHRjbGFzc05hbWU/OiBzdHJpbmc7XG5cdHRpdGxlPzogc3RyaW5nO1xuXHRzaG93QWRkQnV0dG9uPzogYm9vbGVhbjtcblx0c2hvd0NsZWFyQnV0dG9uPzogYm9vbGVhbjtcblx0YWRkQnV0dG9uVGV4dD86IHN0cmluZztcblx0Y2xlYXJCdXR0b25UZXh0Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gSGVhZGVyKHtcblx0Y2xhc3NOYW1lLFxuXHR0aXRsZSA9IFwiRmlsZXNcIixcblx0c2hvd0FkZEJ1dHRvbiA9IHRydWUsXG5cdHNob3dDbGVhckJ1dHRvbiA9IHRydWUsXG5cdGFkZEJ1dHRvblRleHQgPSBcIkFkZCBmaWxlc1wiLFxuXHRjbGVhckJ1dHRvblRleHQgPSBcIlJlbW92ZSBhbGxcIixcbn06IEhlYWRlclByb3BzKSB7XG5cdGNvbnN0IHsgZmlsZXMsIHJlbW92ZUFsbCwgYWRkRmlsZXMsIGNhbkFjY2VwdE1vcmUsIGNvbmZpZyB9ID0gdXNlRmlsZVVwbG9hZCgpO1xuXHRjb25zdCBmaWxlSW5wdXRSZWYgPSB1c2VSZWY8SFRNTElucHV0RWxlbWVudD4obnVsbCk7XG5cblx0aWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Y29uc3Qgb3BlbkZpbGVEaWFsb2cgPSAoKSA9PiB7XG5cdFx0ZmlsZUlucHV0UmVmLmN1cnJlbnQ/LmNsaWNrKCk7XG5cdH07XG5cblx0Y29uc3QgaGFuZGxlRmlsZUlucHV0Q2hhbmdlID0gYXN5bmMgKFxuXHRcdGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+LFxuXHQpID0+IHtcblx0XHRjb25zdCBuZXdGaWxlcyA9IEFycmF5LmZyb20oZS50YXJnZXQuZmlsZXMgfHwgW10pO1xuXHRcdGlmIChuZXdGaWxlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRhd2FpdCBhZGRGaWxlcyhuZXdGaWxlcyk7XG5cdFx0fVxuXHRcdGUudGFyZ2V0LnZhbHVlID0gXCJcIjtcblx0fTtcblxuXHRyZXR1cm4gKFxuXHRcdDxkaXYgY2xhc3NOYW1lPXtjbihcImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBnYXAtMlwiLCBjbGFzc05hbWUpfT5cblx0XHRcdDxpbnB1dFxuXHRcdFx0XHRyZWY9e2ZpbGVJbnB1dFJlZn1cblx0XHRcdFx0dHlwZT1cImZpbGVcIlxuXHRcdFx0XHRtdWx0aXBsZT17KGNvbmZpZy5tYXhGaWxlcyA/PyAxMCkgPiAxfVxuXHRcdFx0XHRhY2NlcHQ9e2FjY2VwdFRvU3RyaW5nKGNvbmZpZy5hY2NlcHQpfVxuXHRcdFx0XHRvbkNoYW5nZT17aGFuZGxlRmlsZUlucHV0Q2hhbmdlfVxuXHRcdFx0XHRjbGFzc05hbWU9XCJzci1vbmx5XCJcblx0XHRcdFx0YXJpYS1sYWJlbD1cIlVwbG9hZCBmaWxlXCJcblx0XHRcdC8+XG5cblx0XHRcdDxoMyBjbGFzc05hbWU9XCJ0cnVuY2F0ZSBmb250LW1lZGl1bSB0ZXh0LXNtXCI+XG5cdFx0XHRcdHt0aXRsZX0gKHtmaWxlcy5sZW5ndGh9KVxuXHRcdFx0PC9oMz5cblxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IGdhcC0yXCI+XG5cdFx0XHRcdHtzaG93QWRkQnV0dG9uICYmIChcblx0XHRcdFx0XHQ8QnV0dG9uXG5cdFx0XHRcdFx0XHR2YXJpYW50PVwib3V0bGluZVwiXG5cdFx0XHRcdFx0XHRzaXplPVwic21cIlxuXHRcdFx0XHRcdFx0b25DbGljaz17b3BlbkZpbGVEaWFsb2d9XG5cdFx0XHRcdFx0XHRkaXNhYmxlZD17IWNhbkFjY2VwdE1vcmV9XG5cdFx0XHRcdFx0PlxuXHRcdFx0XHRcdFx0PENsb3VkVXBsb2FkXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cIi1tcy0wLjUgc2l6ZS0zLjUgb3BhY2l0eS02MFwiXG5cdFx0XHRcdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0e2FkZEJ1dHRvblRleHR9XG5cdFx0XHRcdFx0PC9CdXR0b24+XG5cdFx0XHRcdCl9XG5cblx0XHRcdFx0e3Nob3dDbGVhckJ1dHRvbiAmJiBmaWxlcy5sZW5ndGggPiAwICYmIChcblx0XHRcdFx0XHQ8QnV0dG9uIHZhcmlhbnQ9XCJvdXRsaW5lXCIgc2l6ZT1cInNtXCIgb25DbGljaz17cmVtb3ZlQWxsfT5cblx0XHRcdFx0XHRcdDxUcmFzaDJcblx0XHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiLW1zLTAuNSBzaXplLTMuNSBvcGFjaXR5LTYwXCJcblx0XHRcdFx0XHRcdFx0YXJpYS1oaWRkZW49XCJ0cnVlXCJcblx0XHRcdFx0XHRcdC8+XG5cdFx0XHRcdFx0XHR7Y2xlYXJCdXR0b25UZXh0fVxuXHRcdFx0XHRcdDwvQnV0dG9uPlxuXHRcdFx0XHQpfVxuXHRcdFx0PC9kaXY+XG5cdFx0PC9kaXY+XG5cdCk7XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBGaWxlVHlwZSwgRmlsZVVwbG9hZCB9IGZyb20gXCJAYXN0cmlmeS9yZWFjdC1zMy11cGxvYWRcIjtcbmltcG9ydCB7IGZvcm1hdEJ5dGVzLCB1c2VGaWxlVXBsb2FkIH0gZnJvbSBcIkBhc3RyaWZ5L3JlYWN0LXMzLXVwbG9hZFwiO1xuaW1wb3J0IHtcblx0RmlsZUFyY2hpdmVJY29uLFxuXHRGaWxlSWNvbixcblx0RmlsZVNwcmVhZHNoZWV0SWNvbixcblx0RmlsZVRleHRJY29uLFxuXHRIZWFkcGhvbmVzSWNvbixcblx0SW1hZ2VJY29uLFxuXHRSZWZyZXNoQ3dJY29uLFxuXHRWaWRlb0ljb24sXG5cdFhJY29uLFxufSBmcm9tIFwibHVjaWRlLXJlYWN0XCI7XG5pbXBvcnQgeyB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBCdXR0b24gfSBmcm9tIFwiQC9jb21wb25lbnRzL3VpL2J1dHRvblwiO1xuaW1wb3J0IHsgY24gfSBmcm9tIFwiQC9saWIvdXRpbHNcIjtcblxuZnVuY3Rpb24gRmlsZVByZXZpZXdXaXRoUHJvZ3Jlc3Moe1xuXHRmaWxlLFxuXHRzaG93UHJldmlldyxcbn06IHtcblx0ZmlsZTogRmlsZVVwbG9hZDtcblx0c2hvd1ByZXZpZXc6IGJvb2xlYW47XG59KSB7XG5cdGNvbnN0IFtwcmV2aWV3VXJsLCBzZXRQcmV2aWV3VXJsXSA9IHVzZVN0YXRlPHN0cmluZyB8IG51bGw+KG51bGwpO1xuXG5cdHVzZUVmZmVjdCgoKSA9PiB7XG5cdFx0Ly8gQ3JlYXRlIHByZXZpZXcgVVJMIGlmIGl0J3MgYW4gaW1hZ2UgYW5kIHdlIGhhdmUgdGhlIGZpbGUgb3IgYSBwcmV2aWV3IFVSTFxuXHRcdGlmIChzaG93UHJldmlldyAmJiBmaWxlLnR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSkge1xuXHRcdFx0aWYgKGZpbGUucHJldmlldykge1xuXHRcdFx0XHRzZXRQcmV2aWV3VXJsKGZpbGUucHJldmlldyk7XG5cdFx0XHR9IGVsc2UgaWYgKGZpbGUuZmlsZSBpbnN0YW5jZW9mIEZpbGUpIHtcblx0XHRcdFx0Y29uc3QgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlLmZpbGUpO1xuXHRcdFx0XHRzZXRQcmV2aWV3VXJsKHVybCk7XG5cdFx0XHRcdHJldHVybiAoKSA9PiBVUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LCBbZmlsZSwgc2hvd1ByZXZpZXddKTtcblxuXHQvLyBGb3IgaW1hZ2VzIHdpdGggcHJldmlldyBlbmFibGVkLCB1c2UgcHJvZ3Jlc3NpdmUgcmV2ZWFsIGVmZmVjdFxuXHRpZiAoc2hvd1ByZXZpZXcgJiYgcHJldmlld1VybCAmJiBmaWxlLnR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSkge1xuXHRcdGlmIChmaWxlLnN0YXR1cyA9PT0gXCJwZW5kaW5nXCIgfHwgZmlsZS5zdGF0dXMgPT09IFwidXBsb2FkaW5nXCIpIHtcblx0XHRcdGNvbnN0IHByb2dyZXNzID0gZmlsZS5zdGF0dXMgPT09IFwicGVuZGluZ1wiID8gMCA6IGZpbGUucHJvZ3Jlc3MgfHwgMDtcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicmVsYXRpdmUgc2l6ZS0xMCBvdmVyZmxvdy1oaWRkZW4gcm91bmRlZFwiPlxuXHRcdFx0XHRcdHsvKiBEaW1tZWQgYmFzZSBpbWFnZSAqL31cblx0XHRcdFx0XHQ8aW1nXG5cdFx0XHRcdFx0XHRzcmM9e3ByZXZpZXdVcmx9XG5cdFx0XHRcdFx0XHRhbHQ9e2ZpbGUubmFtZX1cblx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImFic29sdXRlIGluc2V0LTAgc2l6ZS0xMCBvYmplY3QtY292ZXIgb3BhY2l0eS0zMFwiXG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0XHR7LyogUHJvZ3Jlc3NpdmUgcmV2ZWFsIG92ZXJsYXkgKi99XG5cdFx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiYWJzb2x1dGUgaW5zZXQtMCBvdmVyZmxvdy1oaWRkZW5cIlxuXHRcdFx0XHRcdFx0c3R5bGU9e3sgd2lkdGg6IGAke3Byb2dyZXNzfSVgIH19XG5cdFx0XHRcdFx0PlxuXHRcdFx0XHRcdFx0PGltZ1xuXHRcdFx0XHRcdFx0XHRzcmM9e3ByZXZpZXdVcmx9XG5cdFx0XHRcdFx0XHRcdGFsdD17ZmlsZS5uYW1lfVxuXHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJzaXplLTEwIG9iamVjdC1jb3ZlclwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdHsvKiBPcHRpb25hbDogQWRkIGEgc3VidGxlIHByb2dyZXNzIGxpbmUgKi99XG5cdFx0XHRcdFx0e2ZpbGUuc3RhdHVzID09PSBcInVwbG9hZGluZ1wiICYmIHByb2dyZXNzID4gMCAmJiBwcm9ncmVzcyA8IDEwMCAmJiAoXG5cdFx0XHRcdFx0XHQ8ZGl2XG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cImFic29sdXRlIGluc2V0LXktMCB3LTAuNSBiZy1wcmltYXJ5LzUwXCJcblx0XHRcdFx0XHRcdFx0c3R5bGU9e3sgbGVmdDogYCR7cHJvZ3Jlc3N9JWAgfX1cblx0XHRcdFx0XHRcdC8+XG5cdFx0XHRcdFx0KX1cblx0XHRcdFx0PC9kaXY+XG5cdFx0XHQpO1xuXHRcdH1cblx0XHQvLyBDb21wbGV0ZWQgb3IgZXJyb3Igc3RhdGUgLSBzaG93IGZ1bGwgaW1hZ2Vcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGltZ1xuXHRcdFx0XHRzcmM9e3ByZXZpZXdVcmx9XG5cdFx0XHRcdGFsdD17ZmlsZS5uYW1lfVxuXHRcdFx0XHRjbGFzc05hbWU9XCJzaXplLTEwIHJvdW5kZWQgb2JqZWN0LWNvdmVyXCJcblx0XHRcdC8+XG5cdFx0KTtcblx0fVxuXG5cdC8vIEZvciBub24taW1hZ2UgZmlsZXMsIHVzZSB0aGUgY2lyY3VsYXIgcHJvZ3Jlc3MgaW5kaWNhdG9yXG5cdGNvbnN0IGljb25Db250ZW50ID0gKFxuXHRcdDxkaXYgY2xhc3NOYW1lPVwiZmxleCBzaXplLTEwIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlclwiPlxuXHRcdFx0e2dldEZpbGVJY29uKGZpbGUpfVxuXHRcdDwvZGl2PlxuXHQpO1xuXG5cdGlmIChmaWxlLnN0YXR1cyA9PT0gXCJwZW5kaW5nXCIpIHtcblx0XHRyZXR1cm4gKFxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJyZWxhdGl2ZSBzaXplLTEwXCI+XG5cdFx0XHRcdHtpY29uQ29udGVudH1cblx0XHRcdFx0PHN2Z1xuXHRcdFx0XHRcdGNsYXNzTmFtZT1cImFic29sdXRlIGluc2V0LTAgc2l6ZS0xMFwiXG5cdFx0XHRcdFx0dmlld0JveD1cIjAgMCA0MCA0MFwiXG5cdFx0XHRcdFx0YXJpYS1sYWJlbD1cIlBlbmRpbmcgdXBsb2FkXCJcblx0XHRcdFx0PlxuXHRcdFx0XHRcdDx0aXRsZT5QZW5kaW5nIHVwbG9hZDwvdGl0bGU+XG5cdFx0XHRcdFx0PGNpcmNsZVxuXHRcdFx0XHRcdFx0Y3g9XCIyMFwiXG5cdFx0XHRcdFx0XHRjeT1cIjIwXCJcblx0XHRcdFx0XHRcdHI9XCIxOFwiXG5cdFx0XHRcdFx0XHRmaWxsPVwibm9uZVwiXG5cdFx0XHRcdFx0XHRzdHJva2U9XCJjdXJyZW50Q29sb3JcIlxuXHRcdFx0XHRcdFx0c3Ryb2tlV2lkdGg9XCIyXCJcblx0XHRcdFx0XHRcdHN0cm9rZURhc2hhcnJheT1cIjQgM1wiXG5cdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJ0ZXh0LW11dGVkLWZvcmVncm91bmQvNDBcIlxuXHRcdFx0XHRcdC8+XG5cdFx0XHRcdDwvc3ZnPlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxuXG5cdGlmIChmaWxlLnN0YXR1cyA9PT0gXCJ1cGxvYWRpbmdcIiAmJiBmaWxlLnByb2dyZXNzID4gMCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInJlbGF0aXZlIHNpemUtMTBcIj5cblx0XHRcdFx0e2ljb25Db250ZW50fVxuXHRcdFx0XHQ8c3ZnXG5cdFx0XHRcdFx0Y2xhc3NOYW1lPVwiLXJvdGF0ZS05MCBhYnNvbHV0ZSBpbnNldC0wIHNpemUtMTBcIlxuXHRcdFx0XHRcdHZpZXdCb3g9XCIwIDAgNDAgNDBcIlxuXHRcdFx0XHRcdGFyaWEtbGFiZWw9XCJVcGxvYWQgcHJvZ3Jlc3NcIlxuXHRcdFx0XHQ+XG5cdFx0XHRcdFx0PHRpdGxlPlVwbG9hZCBwcm9ncmVzczwvdGl0bGU+XG5cdFx0XHRcdFx0PGNpcmNsZVxuXHRcdFx0XHRcdFx0Y3g9XCIyMFwiXG5cdFx0XHRcdFx0XHRjeT1cIjIwXCJcblx0XHRcdFx0XHRcdHI9XCIxOFwiXG5cdFx0XHRcdFx0XHRmaWxsPVwibm9uZVwiXG5cdFx0XHRcdFx0XHRzdHJva2U9XCJjdXJyZW50Q29sb3JcIlxuXHRcdFx0XHRcdFx0c3Ryb2tlV2lkdGg9XCIyXCJcblx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cInRleHQtbXV0ZWQtZm9yZWdyb3VuZC8yMFwiXG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0XHQ8Y2lyY2xlXG5cdFx0XHRcdFx0XHRjeD1cIjIwXCJcblx0XHRcdFx0XHRcdGN5PVwiMjBcIlxuXHRcdFx0XHRcdFx0cj1cIjE4XCJcblx0XHRcdFx0XHRcdGZpbGw9XCJub25lXCJcblx0XHRcdFx0XHRcdHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG5cdFx0XHRcdFx0XHRzdHJva2VXaWR0aD1cIjJcIlxuXHRcdFx0XHRcdFx0c3Ryb2tlRGFzaGFycmF5PXtgJHsyICogTWF0aC5QSSAqIDE4fWB9XG5cdFx0XHRcdFx0XHRzdHJva2VEYXNob2Zmc2V0PXtgJHsyICogTWF0aC5QSSAqIDE4ICogKDEgLSBmaWxlLnByb2dyZXNzIC8gMTAwKX1gfVxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwidGV4dC1wcmltYXJ5IHRyYW5zaXRpb24tYWxsIGR1cmF0aW9uLTMwMFwiXG5cdFx0XHRcdFx0XHRzdHJva2VMaW5lY2FwPVwicm91bmRcIlxuXHRcdFx0XHRcdC8+XG5cdFx0XHRcdDwvc3ZnPlxuXHRcdFx0PC9kaXY+XG5cdFx0KTtcblx0fVxuXG5cdHJldHVybiBpY29uQ29udGVudDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbGVJY29uKGZpbGU6IEZpbGVUeXBlKSB7XG5cdGNvbnN0IHR5cGUgPSBmaWxlIGluc3RhbmNlb2YgRmlsZSA/IGZpbGUudHlwZSA6IGZpbGUudHlwZTtcblx0Y29uc3QgbmFtZSA9IGZpbGUgaW5zdGFuY2VvZiBGaWxlID8gZmlsZS5uYW1lIDogZmlsZS5uYW1lO1xuXG5cdGlmIChcblx0XHR0eXBlLmluY2x1ZGVzKFwicGRmXCIpIHx8XG5cdFx0bmFtZS5lbmRzV2l0aChcIi5wZGZcIikgfHxcblx0XHR0eXBlLmluY2x1ZGVzKFwid29yZFwiKSB8fFxuXHRcdG5hbWUuZW5kc1dpdGgoXCIuZG9jXCIpIHx8XG5cdFx0bmFtZS5lbmRzV2l0aChcIi5kb2N4XCIpXG5cdCkge1xuXHRcdHJldHVybiA8RmlsZVRleHRJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0aWYgKFxuXHRcdHR5cGUuaW5jbHVkZXMoXCJ6aXBcIikgfHxcblx0XHR0eXBlLmluY2x1ZGVzKFwiYXJjaGl2ZVwiKSB8fFxuXHRcdG5hbWUuZW5kc1dpdGgoXCIuemlwXCIpIHx8XG5cdFx0bmFtZS5lbmRzV2l0aChcIi5yYXJcIilcblx0KSB7XG5cdFx0cmV0dXJuIDxGaWxlQXJjaGl2ZUljb24gY2xhc3NOYW1lPVwic2l6ZS00IG9wYWNpdHktNjBcIiAvPjtcblx0fVxuXHRpZiAoXG5cdFx0dHlwZS5pbmNsdWRlcyhcImV4Y2VsXCIpIHx8XG5cdFx0bmFtZS5lbmRzV2l0aChcIi54bHNcIikgfHxcblx0XHRuYW1lLmVuZHNXaXRoKFwiLnhsc3hcIilcblx0KSB7XG5cdFx0cmV0dXJuIDxGaWxlU3ByZWFkc2hlZXRJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0aWYgKHR5cGUuaW5jbHVkZXMoXCJ2aWRlby9cIikpIHtcblx0XHRyZXR1cm4gPFZpZGVvSWNvbiBjbGFzc05hbWU9XCJzaXplLTQgb3BhY2l0eS02MFwiIC8+O1xuXHR9XG5cdGlmICh0eXBlLmluY2x1ZGVzKFwiYXVkaW8vXCIpKSB7XG5cdFx0cmV0dXJuIDxIZWFkcGhvbmVzSWNvbiBjbGFzc05hbWU9XCJzaXplLTQgb3BhY2l0eS02MFwiIC8+O1xuXHR9XG5cdGlmICh0eXBlLnN0YXJ0c1dpdGgoXCJpbWFnZS9cIikpIHtcblx0XHRyZXR1cm4gPEltYWdlSWNvbiBjbGFzc05hbWU9XCJzaXplLTQgb3BhY2l0eS02MFwiIC8+O1xuXHR9XG5cdHJldHVybiA8RmlsZUljb24gY2xhc3NOYW1lPVwic2l6ZS00IG9wYWNpdHktNjBcIiAvPjtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhdHVzRGlzcGxheShmaWxlOiBGaWxlVXBsb2FkKSB7XG5cdHN3aXRjaCAoZmlsZS5zdGF0dXMpIHtcblx0XHRjYXNlIFwicGVuZGluZ1wiOlxuXHRcdFx0cmV0dXJuIDxwIGNsYXNzTmFtZT1cInRleHQtbXV0ZWQtZm9yZWdyb3VuZCB0ZXh0LXhzXCI+UXVldWVkPC9wPjtcblx0XHRjYXNlIFwidXBsb2FkaW5nXCI6XG5cdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHQ8cCBjbGFzc05hbWU9XCJ0ZXh0LW11dGVkLWZvcmVncm91bmQgdGV4dC14c1wiPlxuXHRcdFx0XHRcdFVwbG9hZGluZyB7ZmlsZS5wcm9ncmVzcyA/IGAke01hdGgucm91bmQoZmlsZS5wcm9ncmVzcyl9JWAgOiBcIlwifVxuXHRcdFx0XHQ8L3A+XG5cdFx0XHQpO1xuXHRcdGNhc2UgXCJjb21wbGV0ZVwiOlxuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PHAgY2xhc3NOYW1lPVwidGV4dC1tdXRlZC1mb3JlZ3JvdW5kIHRleHQteHNcIj5cblx0XHRcdFx0XHR7Zm9ybWF0Qnl0ZXMoZmlsZS5zaXplKX1cblx0XHRcdFx0PC9wPlxuXHRcdFx0KTtcblx0XHRjYXNlIFwiZXJyb3JcIjpcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxwIGNsYXNzTmFtZT1cInRleHQtZGVzdHJ1Y3RpdmUgdGV4dC14c1wiPlxuXHRcdFx0XHRcdHtmaWxlLmVycm9yIHx8IFwiVXBsb2FkIGZhaWxlZFwifVxuXHRcdFx0XHQ8L3A+XG5cdFx0XHQpO1xuXHRcdGRlZmF1bHQ6XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0fVxufVxuXG5pbnRlcmZhY2UgTGlzdFByb3BzIHtcblx0c2hvd0FjdGlvbnM/OiBib29sZWFuO1xuXHRzaG93SW1hZ2VQcmV2aWV3cz86IGJvb2xlYW47XG5cdGNsYXNzTmFtZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIExpc3Qoe1xuXHRzaG93QWN0aW9ucyA9IHRydWUsXG5cdHNob3dJbWFnZVByZXZpZXdzID0gZmFsc2UsXG5cdGNsYXNzTmFtZSxcbn06IExpc3RQcm9wcykge1xuXHRjb25zdCB7IGZpbGVzLCByZW1vdmVGaWxlLCByZXRyeVVwbG9hZCB9ID0gdXNlRmlsZVVwbG9hZCgpO1xuXG5cdGlmIChmaWxlcy5sZW5ndGggPT09IDApIHtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxuXG5cdHJldHVybiAoXG5cdFx0PGRpdiBjbGFzc05hbWU9e2NuKFwic3BhY2UteS0yXCIsIGNsYXNzTmFtZSl9PlxuXHRcdFx0e2ZpbGVzLm1hcCgoZmlsZSkgPT4gKFxuXHRcdFx0XHQ8ZGl2XG5cdFx0XHRcdFx0a2V5PXtmaWxlLnNoYTI1Nn1cblx0XHRcdFx0XHRjbGFzc05hbWU9e2NuKFxuXHRcdFx0XHRcdFx0XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gZ2FwLTIgcm91bmRlZC1sZyBib3JkZXIgYmctYmFja2dyb3VuZCBwLTIgcGUtM1wiLFxuXHRcdFx0XHRcdFx0ZmlsZS5zdGF0dXMgPT09IFwicGVuZGluZ1wiICYmIFwib3BhY2l0eS02MFwiLFxuXHRcdFx0XHRcdFx0ZmlsZS5kdXBsaWNhdGVBbGVydCAmJiBcImJnLXByaW1hcnkvMTBcIixcblx0XHRcdFx0XHQpfVxuXHRcdFx0XHQ+XG5cdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMyBvdmVyZmxvdy1oaWRkZW5cIj5cblx0XHRcdFx0XHRcdDxkaXYgY2xhc3NOY