@telestack/storage 1.2.0 → 1.2.1
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/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.global.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -237,9 +237,11 @@ declare class QueryBuilder {
|
|
|
237
237
|
private _limit;
|
|
238
238
|
constructor(client: HttpClient);
|
|
239
239
|
nameContains(text: string): this;
|
|
240
|
+
search(text: string): this;
|
|
240
241
|
where(key: string, value: any): this;
|
|
241
242
|
limit(n: number): this;
|
|
242
243
|
get(): Promise<FileMetadata[]>;
|
|
244
|
+
run(): Promise<FileMetadata[]>;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -237,9 +237,11 @@ declare class QueryBuilder {
|
|
|
237
237
|
private _limit;
|
|
238
238
|
constructor(client: HttpClient);
|
|
239
239
|
nameContains(text: string): this;
|
|
240
|
+
search(text: string): this;
|
|
240
241
|
where(key: string, value: any): this;
|
|
241
242
|
limit(n: number): this;
|
|
242
243
|
get(): Promise<FileMetadata[]>;
|
|
244
|
+
run(): Promise<FileMetadata[]>;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
/**
|
package/dist/index.global.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var TelestackStorageSetup=(()=>{var U=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var S=(l,t)=>{for(var e in t)U(l,e,{get:t[e],enumerable:!0})},M=(l,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of x(t))!C.call(l,r)&&r!==e&&U(l,r,{get:()=>t[r],enumerable:!(s=B(t,r))||s.enumerable});return l};var E=l=>M(U({},"__esModule",{value:!0}),l);var O={};S(O,{BatchBuilder:()=>b,CryptoHelper:()=>d,DirRef:()=>y,FileRef:()=>f,HttpClient:()=>_,ImageHelper:()=>g,QueryBuilder:()=>v,StorageRef:()=>w,TelestackError:()=>u,TelestackStorage:()=>T,UploadTask:()=>m});var _=class{baseUrl;tenantId;headers;constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.tenantId=t.tenantId,this.headers={"Content-Type":"application/json","X-Tenant-ID":t.tenantId},t.apiKey?this.headers["X-API-Key"]=t.apiKey:t.token&&(this.headers.Authorization=`Bearer ${t.token}`)}async _fetchWithRetry(t,e,s=3){for(let r=0;r<=s;r++)try{let i=await fetch(t,e);if((i.status===429||i.status>=500)&&r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network error ${i.status}. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}return i}catch(i){if(r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network un-reachable. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}throw i}throw new Error("Unreachable code in retry logic")}async get(t,e){let s=new URL(`${this.baseUrl}${t}`);e&&Object.entries(e).forEach(([i,a])=>{a!==void 0&&s.searchParams.set(i,a)});let r=await this._fetchWithRetry(s.toString(),{headers:this.headers});return this._handle(r)}async post(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"POST",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async patch(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PATCH",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async put(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PUT",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async delete(t){let e=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"DELETE",headers:this.headers});return this._handle(e)}async uploadToPresignedUrl(t,e,s,r){for(let a=0;a<=3;a++)try{await new Promise((n,h)=>{let o=new XMLHttpRequest;o.open("PUT",t),o.setRequestHeader("Content-Type",s),r&&(o.upload.onprogress=p=>{p.lengthComputable&&r(Math.round(p.loaded/p.total*100))}),o.onload=()=>{o.status>=200&&o.status<300?n():o.status===429||o.status>=500?h(new Error(`Retryable network error: ${o.status}`)):h(new u(`Upload failed: ${o.status}`,o.status))},o.onerror=()=>h(new Error("Retryable network error")),o.send(e)});return}catch(n){if(n instanceof u||a>=3)throw n;let h=Math.min(1e3*Math.pow(2,a),1e4);console.warn(`[TelestackStorage] Upload chunk failed. Retrying in ${h}ms...`),await new Promise(o=>setTimeout(o,h))}}async _handle(t){let e=await t.json();if(!t.ok)throw new u(e.error||t.statusText,t.status,e.code);return e}},u=class extends Error{constructor(e,s,r){super(e);this.status=s;this.code=r;this.name="TelestackError"}};var d=class{static async generateKey(){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=await crypto.subtle.exportKey("raw",t);return btoa(String.fromCharCode(...new Uint8Array(e)))}static async encrypt(t,e){let s=await this._importKey(e),r=crypto.getRandomValues(new Uint8Array(12)),i=await t.arrayBuffer(),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},s,i);return new Blob([r,a],{type:"application/octet-stream"})}static async decrypt(t,e,s="application/octet-stream"){let r=await this._importKey(e),i=await t.arrayBuffer(),a=i.slice(0,12),n=i.slice(12),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(a)},r,n);return new Blob([h],{type:s})}static async _importKey(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0));return crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"])}};var g=class{static async compress(t,e={}){if(!t.type.startsWith("image/"))return t;let{maxWidth:s=1920,maxHeight:r=1080,quality:i=.8}=e;return new Promise((a,n)=>{let h=new Image,o=URL.createObjectURL(t);h.onload=()=>{URL.revokeObjectURL(o);let p=h.width,c=h.height;p>s&&(c=Math.round(c*s/p),p=s),c>r&&(p=Math.round(p*r/c),c=r);let R=document.createElement("canvas");R.width=p,R.height=c;let P=R.getContext("2d");if(!P)return n(new Error("Failed to get canvas 2d context for image compression"));P.drawImage(h,0,0,p,c);let k=t.type==="image/png"?"image/png":"image/webp";R.toBlob(I=>{I?a(I):n(new Error("Canvas toBlob failed"))},k,i)},h.onerror=()=>{URL.revokeObjectURL(o),n(new Error("Failed to load image for compression"))},h.src=o})}};var m=class{constructor(t,e,s,r,i,a){this.client=t;this.path=e;this.name=r;this.contentType=i;this.options=a;this._data=s,this._totalBytes=s.size,this._promise=new Promise((n,h)=>{this._resolve=n,this._reject=h}),this._start()}_state="processing";_bytesTransferred=0;_totalBytes=0;_data;_observers=[];_promise;_resolve;_reject;_uploadId;_parts=[];_currentPartIndex=0;_activeXhr;_isResumable=!1;_simpleFileMetadata;on(t,e,s,r){let i=typeof e=="function"?{next:e,error:s,complete:r}:e||{error:s,complete:r};return this._observers.push(i),i.next&&i.next(this.snapshot),()=>{this._observers=this._observers.filter(a=>a!==i)}}pause(){return this._state!=="running"?!1:(this._state="paused",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._notifyObservers(),!0)}resume(){return this._state!=="paused"?!1:(this._state="running",this._notifyObservers(),this._isResumable?this._continueResumable().catch(this._handleError):(this._bytesTransferred=0,this._notifyObservers(),this._startSimple().catch(this._handleError)),!0)}cancel(){if(this._state==="success"||this._state==="error"||this._state==="canceled")return!1;this._state="canceled",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._isResumable&&this._uploadId?this.client.post("/files/resumable/abort",{path:this.path,uploadId:this._uploadId}).catch(()=>{}):!this._isResumable&&this._simpleFileMetadata&&this.client.delete(`/files/${encodeURIComponent(this.path)}`).catch(()=>{}),this._notifyObservers();let t=new Error("Upload canceled by user");return t.name="UploadCanceled",this._handleError(t),!0}get snapshot(){return{bytesTransferred:this._bytesTransferred,totalBytes:this._totalBytes,state:this._state,task:this}}then(t,e){return this._promise.then(t,e)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}[Symbol.toStringTag]="UploadTask";async _start(){try{if(this.options.compressImage&&this._data.type.startsWith("image/")&&(this._data=await g.compress(this._data,this.options.compressImage)),this.options.encryptionKey&&(this._data=await d.encrypt(this._data,this.options.encryptionKey)),this._totalBytes=this._data.size,this._state!=="processing")return;this._state="running",this._notifyObservers();let t=50*1024*1024;this._isResumable=this._totalBytes>=t,this._isResumable?await this._startResumable():await this._startSimple()}catch(t){this._handleError(t)}}async _startSimple(){let t=await this.client.post("/files/upload-url",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});if(this._simpleFileMetadata=t.file,this._state!=="running")return;let e=new XMLHttpRequest;this._activeXhr=e,await new Promise((s,r)=>{e.open("PUT",t.uploadUrl),e.setRequestHeader("Content-Type",this.contentType),e.upload.onprogress=i=>{i.lengthComputable&&this._state==="running"&&(this._bytesTransferred=i.loaded,this._notifyObservers())},e.onload=()=>{e.status>=200&&e.status<300?s():r(new Error(`Upload failed: ${e.status} ${e.responseText}`))},e.onerror=()=>r(new Error("Network error during upload")),e.onabort=()=>r(new Error("Upload aborted")),e.send(this._data)}),this._activeXhr=void 0,this._state==="running"&&(await this.client.post("/files/complete-upload",{path:this.path}),this._bytesTransferred=this._totalBytes,this._state="success",this._notifyObservers(),this._resolve({file:t.file,resumable:!1}))}async _startResumable(){let t=await this.client.post("/files/resumable/init",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});this._uploadId=t.uploadId,this._simpleFileMetadata=t.file,await this._continueResumable()}async _continueResumable(){if(!this._uploadId||!this._simpleFileMetadata)return;let t=this.options.chunkSize??10*1024*1024,e=Math.ceil(this._totalBytes/t);try{for(;this._currentPartIndex<e;){if(this._state!=="running")return;let s=this._currentPartIndex*t,r=Math.min(s+t,this._totalBytes),i=this._data.slice(s,r),a=await this.client.post("/files/resumable/part-url",{path:this.path,uploadId:this._uploadId,partNumber:this._currentPartIndex+1});if(this._state!=="running")return;let n=await this._uploadChunkWithProgress(a.uploadUrl,i,s);this._parts.push({PartNumber:this._currentPartIndex+1,ETag:n}),this._currentPartIndex++,this._bytesTransferred=Math.min(this._currentPartIndex*t,this._totalBytes),this._notifyObservers()}this._state==="running"&&(await this.client.post("/files/resumable/complete",{path:this.path,uploadId:this._uploadId,parts:this._parts}),this._state="success",this._notifyObservers(),this._resolve({file:this._simpleFileMetadata,resumable:!0}))}catch(s){if(s.message==="Upload aborted")return;this._handleError(s)}}_uploadChunkWithProgress(t,e,s){return new Promise((r,i)=>{let a=new XMLHttpRequest;this._activeXhr=a,a.open("PUT",t),a.setRequestHeader("Content-Type",this.contentType),a.upload.onprogress=n=>{n.lengthComputable&&this._state==="running"&&(this._bytesTransferred=s+n.loaded,this._notifyObservers())},a.onload=()=>{if(a.status>=200&&a.status<300){let n=a.getResponseHeader("ETag")||"";r(n.replace(/"/g,""))}else i(new Error(`Part upload failed: ${a.status}`))},a.onerror=()=>i(new Error("Network error during part upload")),a.onabort=()=>i(new Error("Upload aborted")),a.send(e)})}_notifyObservers(){let t=this.snapshot;this._observers.forEach(e=>{t.state==="success"&&e.complete?e.complete():e.next&&e.next(t)})}_handleError=t=>{this._state!=="canceled"&&(this._state="error",this._activeXhr=void 0,this._notifyObservers(),this._observers.forEach(e=>e.error?.(t)),this._reject(t))}};var w=class{constructor(t,e,s){this.client=t;this.path=e;this.tenantId=s}child(t){let s=(this.path?this.path.endsWith("/")?this.path:this.path+"/":"")+t.replace(/^\//,"");return s.endsWith("/")?new y(this.client,s,this.tenantId):new f(this.client,s,this.tenantId)}},y=class extends w{async listAll(t=100){return(await this.client.get("/files",{prefix:this.path,limit:String(t)})).files}},f=class extends w{put(t,e){let s=(t instanceof File,t.size),r=t instanceof File?t.name:this.path.split("/").pop()||"file",i=t.type||"application/octet-stream";return new m(this.client,this.path,t,r,i,e)}putBytes(t,e,s){let r=this.path.split("/").pop()||"file",i=new Blob([t],{type:e});return new m(this.client,this.path,i,r,e,s)}async getDownloadUrl(t){return t?.versionId?(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t.versionId})).downloadUrl:(await this.client.get(`/files/download-url/${encodeURIComponent(this.path)}`)).downloadUrl}async getDecryptedBlob(t){let e=await this.getDownloadUrl(),s=await fetch(e);if(!s.ok)throw new Error(`Failed to download file from S3: ${s.status}`);let r=await s.blob(),i=await this.getMetadata();return await d.decrypt(r,t,i.content_type)}async getMetadata(){return(await this.client.get(`/files/metadata/${encodeURIComponent(this.path)}`)).file}async updateMetadata(t){return(await this.client.patch(`/files/metadata/${encodeURIComponent(this.path)}`,{metadata:t})).file}async delete(){await this.client.delete(`/files/${encodeURIComponent(this.path)}`)}async listVersions(){return this.client.get(`/files/versions/${encodeURIComponent(this.path)}`)}async getVersionUrl(t){return(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t})).downloadUrl}async getTags(){return(await this.client.get(`/files/tags/${encodeURIComponent(this.path)}`)).tags}async setTags(t){await this.client.put(`/files/tags/${encodeURIComponent(this.path)}`,{tags:t})}async setLegalHold(t){await this.client.post(`/files/legal-hold/${encodeURIComponent(this.path)}`,{status:t})}};var b=class{constructor(t){this.client=t}_op=null;_paths=[];_dest="";delete(t){return this._op="delete",this._paths=t,this}copy(t,e){return this._op="copy",this._paths=t,this._dest=e,this}move(t,e){return this._op="move",this._paths=t,this._dest=e,this}async run(){if(!this._op)throw new Error("No batch operation specified");if(this._op==="delete")return this.client.post("/files/batch/delete",{paths:this._paths});let t={sourcePaths:this._paths,destinationPrefix:this._dest};return this.client.post(`/files/batch/${this._op}`,t)}};var v=class{constructor(t){this.client=t}_query="";_metadata={};_limit=20;nameContains(t){return this._query=t,this}where(t,e){return this._metadata[t]=e,this}limit(t){return this._limit=t,this}async get(){let t={q:this._query||void 0,limit:String(this._limit),metadata:Object.keys(this._metadata).length>0?JSON.stringify(this._metadata):void 0};return(await this.client.get("/files/search",t)).files}};var T=class{constructor(t){this.config=t;this.http=new _(t),this.tenantId=t.tenantId}http;tenantId;ref(t){if(t.endsWith("/"))throw new Error("Use .dir() for directory references");return new f(this.http,t,this.tenantId)}dir(t){let e=t.endsWith("/")?t:t+"/";return new y(this.http,e,this.tenantId)}async list(t){let e={prefix:t?.prefix||"",limit:String(t?.limit||100)};return(await this.http.get("/files",e)).files}async rename(t,e){return this.http.post("/files/rename",{oldPath:t,newName:e})}batch(){return new b(this.http)}query(){return new v(this.http)}async generateApiKey(t){return this.http.post("/internal/keys/generate",{name:t})}async revokeApiKey(t){await this.http.post("/internal/keys/revoke",{keyId:t})}async getBucketInfo(){return this.http.get("/internal/bucket-info")}};return E(O);})();
|
|
1
|
+
"use strict";var TelestackStorageSetup=(()=>{var U=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var S=(l,t)=>{for(var e in t)U(l,e,{get:t[e],enumerable:!0})},M=(l,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of C(t))!x.call(l,r)&&r!==e&&U(l,r,{get:()=>t[r],enumerable:!(s=B(t,r))||s.enumerable});return l};var E=l=>M(U({},"__esModule",{value:!0}),l);var O={};S(O,{BatchBuilder:()=>b,CryptoHelper:()=>d,DirRef:()=>y,FileRef:()=>f,HttpClient:()=>_,ImageHelper:()=>g,QueryBuilder:()=>v,StorageRef:()=>w,TelestackError:()=>u,TelestackStorage:()=>T,UploadTask:()=>m});var _=class{baseUrl;tenantId;headers;constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.tenantId=t.tenantId,this.headers={"Content-Type":"application/json","X-Tenant-ID":t.tenantId},t.apiKey?this.headers["X-API-Key"]=t.apiKey:t.token&&(this.headers.Authorization=`Bearer ${t.token}`)}async _fetchWithRetry(t,e,s=3){for(let r=0;r<=s;r++)try{let i=await fetch(t,e);if((i.status===429||i.status>=500)&&r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network error ${i.status}. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}return i}catch(i){if(r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network un-reachable. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}throw i}throw new Error("Unreachable code in retry logic")}async get(t,e){let s=new URL(`${this.baseUrl}${t}`);e&&Object.entries(e).forEach(([i,a])=>{a!==void 0&&s.searchParams.set(i,a)});let r=await this._fetchWithRetry(s.toString(),{headers:this.headers});return this._handle(r)}async post(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"POST",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async patch(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PATCH",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async put(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PUT",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async delete(t){let e=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"DELETE",headers:this.headers});return this._handle(e)}async uploadToPresignedUrl(t,e,s,r){for(let a=0;a<=3;a++)try{await new Promise((n,h)=>{let o=new XMLHttpRequest;o.open("PUT",t),o.setRequestHeader("Content-Type",s),r&&(o.upload.onprogress=p=>{p.lengthComputable&&r(Math.round(p.loaded/p.total*100))}),o.onload=()=>{o.status>=200&&o.status<300?n():o.status===429||o.status>=500?h(new Error(`Retryable network error: ${o.status}`)):h(new u(`Upload failed: ${o.status}`,o.status))},o.onerror=()=>h(new Error("Retryable network error")),o.send(e)});return}catch(n){if(n instanceof u||a>=3)throw n;let h=Math.min(1e3*Math.pow(2,a),1e4);console.warn(`[TelestackStorage] Upload chunk failed. Retrying in ${h}ms...`),await new Promise(o=>setTimeout(o,h))}}async _handle(t){let e=await t.json();if(!t.ok)throw new u(e.error||t.statusText,t.status,e.code);return e}},u=class extends Error{constructor(e,s,r){super(e);this.status=s;this.code=r;this.name="TelestackError"}};var d=class{static async generateKey(){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=await crypto.subtle.exportKey("raw",t);return btoa(String.fromCharCode(...new Uint8Array(e)))}static async encrypt(t,e){let s=await this._importKey(e),r=crypto.getRandomValues(new Uint8Array(12)),i=await t.arrayBuffer(),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},s,i);return new Blob([r,a],{type:"application/octet-stream"})}static async decrypt(t,e,s="application/octet-stream"){let r=await this._importKey(e),i=await t.arrayBuffer(),a=i.slice(0,12),n=i.slice(12),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(a)},r,n);return new Blob([h],{type:s})}static async _importKey(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0));return crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"])}};var g=class{static async compress(t,e={}){if(!t.type.startsWith("image/"))return t;let{maxWidth:s=1920,maxHeight:r=1080,quality:i=.8}=e;return new Promise((a,n)=>{let h=new Image,o=URL.createObjectURL(t);h.onload=()=>{URL.revokeObjectURL(o);let p=h.width,c=h.height;p>s&&(c=Math.round(c*s/p),p=s),c>r&&(p=Math.round(p*r/c),c=r);let R=document.createElement("canvas");R.width=p,R.height=c;let P=R.getContext("2d");if(!P)return n(new Error("Failed to get canvas 2d context for image compression"));P.drawImage(h,0,0,p,c);let k=t.type==="image/png"?"image/png":"image/webp";R.toBlob(I=>{I?a(I):n(new Error("Canvas toBlob failed"))},k,i)},h.onerror=()=>{URL.revokeObjectURL(o),n(new Error("Failed to load image for compression"))},h.src=o})}};var m=class{constructor(t,e,s,r,i,a){this.client=t;this.path=e;this.name=r;this.contentType=i;this.options=a;this._data=s,this._totalBytes=s.size,this._promise=new Promise((n,h)=>{this._resolve=n,this._reject=h}),this._start()}_state="processing";_bytesTransferred=0;_totalBytes=0;_data;_observers=[];_promise;_resolve;_reject;_uploadId;_parts=[];_currentPartIndex=0;_activeXhr;_isResumable=!1;_simpleFileMetadata;on(t,e,s,r){let i=typeof e=="function"?{next:e,error:s,complete:r}:e||{error:s,complete:r};return this._observers.push(i),i.next&&i.next(this.snapshot),()=>{this._observers=this._observers.filter(a=>a!==i)}}pause(){return this._state!=="running"?!1:(this._state="paused",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._notifyObservers(),!0)}resume(){return this._state!=="paused"?!1:(this._state="running",this._notifyObservers(),this._isResumable?this._continueResumable().catch(this._handleError):(this._bytesTransferred=0,this._notifyObservers(),this._startSimple().catch(this._handleError)),!0)}cancel(){if(this._state==="success"||this._state==="error"||this._state==="canceled")return!1;this._state="canceled",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._isResumable&&this._uploadId?this.client.post("/files/resumable/abort",{path:this.path,uploadId:this._uploadId}).catch(()=>{}):!this._isResumable&&this._simpleFileMetadata&&this.client.delete(`/files/${encodeURIComponent(this.path)}`).catch(()=>{}),this._notifyObservers();let t=new Error("Upload canceled by user");return t.name="UploadCanceled",this._handleError(t),!0}get snapshot(){return{bytesTransferred:this._bytesTransferred,totalBytes:this._totalBytes,state:this._state,task:this}}then(t,e){return this._promise.then(t,e)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}[Symbol.toStringTag]="UploadTask";async _start(){try{if(this.options.compressImage&&this._data.type.startsWith("image/")&&(this._data=await g.compress(this._data,this.options.compressImage)),this.options.encryptionKey&&(this._data=await d.encrypt(this._data,this.options.encryptionKey)),this._totalBytes=this._data.size,this._state!=="processing")return;this._state="running",this._notifyObservers();let t=50*1024*1024;this._isResumable=this._totalBytes>=t,this._isResumable?await this._startResumable():await this._startSimple()}catch(t){this._handleError(t)}}async _startSimple(){let t=await this.client.post("/files/upload-url",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});if(this._simpleFileMetadata=t.file,this._state!=="running")return;let e=new XMLHttpRequest;this._activeXhr=e,await new Promise((s,r)=>{e.open("PUT",t.uploadUrl),e.setRequestHeader("Content-Type",this.contentType),e.upload.onprogress=i=>{i.lengthComputable&&this._state==="running"&&(this._bytesTransferred=i.loaded,this._notifyObservers())},e.onload=()=>{e.status>=200&&e.status<300?s():r(new Error(`Upload failed: ${e.status} ${e.responseText}`))},e.onerror=()=>r(new Error("Network error during upload")),e.onabort=()=>r(new Error("Upload aborted")),e.send(this._data)}),this._activeXhr=void 0,this._state==="running"&&(await this.client.post("/files/complete-upload",{path:this.path}),this._bytesTransferred=this._totalBytes,this._state="success",this._notifyObservers(),this._resolve({file:t.file,resumable:!1}))}async _startResumable(){let t=await this.client.post("/files/resumable/init",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});this._uploadId=t.uploadId,this._simpleFileMetadata=t.file,await this._continueResumable()}async _continueResumable(){if(!this._uploadId||!this._simpleFileMetadata)return;let t=this.options.chunkSize??10*1024*1024,e=Math.ceil(this._totalBytes/t);try{for(;this._currentPartIndex<e;){if(this._state!=="running")return;let s=this._currentPartIndex*t,r=Math.min(s+t,this._totalBytes),i=this._data.slice(s,r),a=await this.client.post("/files/resumable/part-url",{path:this.path,uploadId:this._uploadId,partNumber:this._currentPartIndex+1});if(this._state!=="running")return;let n=await this._uploadChunkWithProgress(a.uploadUrl,i,s);this._parts.push({PartNumber:this._currentPartIndex+1,ETag:n}),this._currentPartIndex++,this._bytesTransferred=Math.min(this._currentPartIndex*t,this._totalBytes),this._notifyObservers()}this._state==="running"&&(await this.client.post("/files/resumable/complete",{path:this.path,uploadId:this._uploadId,parts:this._parts}),this._state="success",this._notifyObservers(),this._resolve({file:this._simpleFileMetadata,resumable:!0}))}catch(s){if(s.message==="Upload aborted")return;this._handleError(s)}}_uploadChunkWithProgress(t,e,s){return new Promise((r,i)=>{let a=new XMLHttpRequest;this._activeXhr=a,a.open("PUT",t),a.setRequestHeader("Content-Type",this.contentType),a.upload.onprogress=n=>{n.lengthComputable&&this._state==="running"&&(this._bytesTransferred=s+n.loaded,this._notifyObservers())},a.onload=()=>{if(a.status>=200&&a.status<300){let n=a.getResponseHeader("ETag")||"";r(n.replace(/"/g,""))}else i(new Error(`Part upload failed: ${a.status}`))},a.onerror=()=>i(new Error("Network error during part upload")),a.onabort=()=>i(new Error("Upload aborted")),a.send(e)})}_notifyObservers(){let t=this.snapshot;this._observers.forEach(e=>{t.state==="success"&&e.complete?e.complete():e.next&&e.next(t)})}_handleError=t=>{this._state!=="canceled"&&(this._state="error",this._activeXhr=void 0,this._notifyObservers(),this._observers.forEach(e=>e.error?.(t)),this._reject(t))}};var w=class{constructor(t,e,s){this.client=t;this.path=e;this.tenantId=s}child(t){let s=(this.path?this.path.endsWith("/")?this.path:this.path+"/":"")+t.replace(/^\//,"");return s.endsWith("/")?new y(this.client,s,this.tenantId):new f(this.client,s,this.tenantId)}},y=class extends w{async listAll(t=100){return(await this.client.get("/files",{prefix:this.path,limit:String(t)})).files}},f=class extends w{put(t,e){let s=(t instanceof File,t.size),r=t instanceof File?t.name:this.path.split("/").pop()||"file",i=t.type||"application/octet-stream";return new m(this.client,this.path,t,r,i,e)}putBytes(t,e,s){let r=this.path.split("/").pop()||"file",i=new Blob([t],{type:e});return new m(this.client,this.path,i,r,e,s)}async getDownloadUrl(t){return t?.versionId?(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t.versionId})).downloadUrl:(await this.client.get(`/files/download-url/${encodeURIComponent(this.path)}`)).downloadUrl}async getDecryptedBlob(t){let e=await this.getDownloadUrl(),s=await fetch(e);if(!s.ok)throw new Error(`Failed to download file from S3: ${s.status}`);let r=await s.blob(),i=await this.getMetadata();return await d.decrypt(r,t,i.content_type)}async getMetadata(){return(await this.client.get(`/files/metadata/${encodeURIComponent(this.path)}`)).file}async updateMetadata(t){return(await this.client.patch(`/files/metadata/${encodeURIComponent(this.path)}`,{metadata:t})).file}async delete(){await this.client.delete(`/files/${encodeURIComponent(this.path)}`)}async listVersions(){return this.client.get(`/files/versions/${encodeURIComponent(this.path)}`)}async getVersionUrl(t){return(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t})).downloadUrl}async getTags(){return(await this.client.get(`/files/tags/${encodeURIComponent(this.path)}`)).tags}async setTags(t){await this.client.put(`/files/tags/${encodeURIComponent(this.path)}`,{tags:t})}async setLegalHold(t){await this.client.post(`/files/legal-hold/${encodeURIComponent(this.path)}`,{status:t})}};var b=class{constructor(t){this.client=t}_op=null;_paths=[];_dest="";delete(t){return this._op="delete",this._paths=t,this}copy(t,e){return this._op="copy",this._paths=t,this._dest=e,this}move(t,e){return this._op="move",this._paths=t,this._dest=e,this}async run(){if(!this._op)throw new Error("No batch operation specified");if(this._op==="delete")return this.client.post("/files/batch/delete",{paths:this._paths});let t={sourcePaths:this._paths,destinationPrefix:this._dest};return this.client.post(`/files/batch/${this._op}`,t)}};var v=class{constructor(t){this.client=t}_query="";_metadata={};_limit=20;nameContains(t){return this._query=t,this}search(t){return this.nameContains(t)}where(t,e){return this._metadata[t]=e,this}limit(t){return this._limit=t,this}async get(){let t={q:this._query||void 0,limit:String(this._limit),metadata:Object.keys(this._metadata).length>0?JSON.stringify(this._metadata):void 0};return(await this.client.get("/files/search",t)).files}async run(){return this.get()}};var T=class{constructor(t){this.config=t;this.http=new _(t),this.tenantId=t.tenantId}http;tenantId;ref(t){if(t.endsWith("/"))throw new Error("Use .dir() for directory references");return new f(this.http,t,this.tenantId)}dir(t){let e=t.endsWith("/")?t:t+"/";return new y(this.http,e,this.tenantId)}async list(t){let e={prefix:t?.prefix||"",limit:String(t?.limit||100)};return(await this.http.get("/files",e)).files}async rename(t,e){return this.http.post("/files/rename",{oldPath:t,newName:e})}batch(){return new b(this.http)}query(){return new v(this.http)}async generateApiKey(t){return this.http.post("/internal/keys/generate",{name:t})}async revokeApiKey(t){await this.http.post("/internal/keys/revoke",{keyId:t})}async getBucketInfo(){return this.http.get("/internal/bucket-info")}};return E(O);})();
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var U=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var S=(l,t)=>{for(var e in t)U(l,e,{get:t[e],enumerable:!0})},M=(l,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of x(t))!C.call(l,r)&&r!==e&&U(l,r,{get:()=>t[r],enumerable:!(s=B(t,r))||s.enumerable});return l};var E=l=>M(U({},"__esModule",{value:!0}),l);var O={};S(O,{BatchBuilder:()=>b,CryptoHelper:()=>d,DirRef:()=>y,FileRef:()=>f,HttpClient:()=>_,ImageHelper:()=>g,QueryBuilder:()=>v,StorageRef:()=>w,TelestackError:()=>u,TelestackStorage:()=>T,UploadTask:()=>m});module.exports=E(O);var _=class{baseUrl;tenantId;headers;constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.tenantId=t.tenantId,this.headers={"Content-Type":"application/json","X-Tenant-ID":t.tenantId},t.apiKey?this.headers["X-API-Key"]=t.apiKey:t.token&&(this.headers.Authorization=`Bearer ${t.token}`)}async _fetchWithRetry(t,e,s=3){for(let r=0;r<=s;r++)try{let i=await fetch(t,e);if((i.status===429||i.status>=500)&&r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network error ${i.status}. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}return i}catch(i){if(r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network un-reachable. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}throw i}throw new Error("Unreachable code in retry logic")}async get(t,e){let s=new URL(`${this.baseUrl}${t}`);e&&Object.entries(e).forEach(([i,a])=>{a!==void 0&&s.searchParams.set(i,a)});let r=await this._fetchWithRetry(s.toString(),{headers:this.headers});return this._handle(r)}async post(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"POST",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async patch(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PATCH",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async put(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PUT",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async delete(t){let e=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"DELETE",headers:this.headers});return this._handle(e)}async uploadToPresignedUrl(t,e,s,r){for(let a=0;a<=3;a++)try{await new Promise((n,h)=>{let o=new XMLHttpRequest;o.open("PUT",t),o.setRequestHeader("Content-Type",s),r&&(o.upload.onprogress=p=>{p.lengthComputable&&r(Math.round(p.loaded/p.total*100))}),o.onload=()=>{o.status>=200&&o.status<300?n():o.status===429||o.status>=500?h(new Error(`Retryable network error: ${o.status}`)):h(new u(`Upload failed: ${o.status}`,o.status))},o.onerror=()=>h(new Error("Retryable network error")),o.send(e)});return}catch(n){if(n instanceof u||a>=3)throw n;let h=Math.min(1e3*Math.pow(2,a),1e4);console.warn(`[TelestackStorage] Upload chunk failed. Retrying in ${h}ms...`),await new Promise(o=>setTimeout(o,h))}}async _handle(t){let e=await t.json();if(!t.ok)throw new u(e.error||t.statusText,t.status,e.code);return e}},u=class extends Error{constructor(e,s,r){super(e);this.status=s;this.code=r;this.name="TelestackError"}};var d=class{static async generateKey(){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=await crypto.subtle.exportKey("raw",t);return btoa(String.fromCharCode(...new Uint8Array(e)))}static async encrypt(t,e){let s=await this._importKey(e),r=crypto.getRandomValues(new Uint8Array(12)),i=await t.arrayBuffer(),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},s,i);return new Blob([r,a],{type:"application/octet-stream"})}static async decrypt(t,e,s="application/octet-stream"){let r=await this._importKey(e),i=await t.arrayBuffer(),a=i.slice(0,12),n=i.slice(12),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(a)},r,n);return new Blob([h],{type:s})}static async _importKey(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0));return crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"])}};var g=class{static async compress(t,e={}){if(!t.type.startsWith("image/"))return t;let{maxWidth:s=1920,maxHeight:r=1080,quality:i=.8}=e;return new Promise((a,n)=>{let h=new Image,o=URL.createObjectURL(t);h.onload=()=>{URL.revokeObjectURL(o);let p=h.width,c=h.height;p>s&&(c=Math.round(c*s/p),p=s),c>r&&(p=Math.round(p*r/c),c=r);let R=document.createElement("canvas");R.width=p,R.height=c;let P=R.getContext("2d");if(!P)return n(new Error("Failed to get canvas 2d context for image compression"));P.drawImage(h,0,0,p,c);let k=t.type==="image/png"?"image/png":"image/webp";R.toBlob(I=>{I?a(I):n(new Error("Canvas toBlob failed"))},k,i)},h.onerror=()=>{URL.revokeObjectURL(o),n(new Error("Failed to load image for compression"))},h.src=o})}};var m=class{constructor(t,e,s,r,i,a){this.client=t;this.path=e;this.name=r;this.contentType=i;this.options=a;this._data=s,this._totalBytes=s.size,this._promise=new Promise((n,h)=>{this._resolve=n,this._reject=h}),this._start()}_state="processing";_bytesTransferred=0;_totalBytes=0;_data;_observers=[];_promise;_resolve;_reject;_uploadId;_parts=[];_currentPartIndex=0;_activeXhr;_isResumable=!1;_simpleFileMetadata;on(t,e,s,r){let i=typeof e=="function"?{next:e,error:s,complete:r}:e||{error:s,complete:r};return this._observers.push(i),i.next&&i.next(this.snapshot),()=>{this._observers=this._observers.filter(a=>a!==i)}}pause(){return this._state!=="running"?!1:(this._state="paused",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._notifyObservers(),!0)}resume(){return this._state!=="paused"?!1:(this._state="running",this._notifyObservers(),this._isResumable?this._continueResumable().catch(this._handleError):(this._bytesTransferred=0,this._notifyObservers(),this._startSimple().catch(this._handleError)),!0)}cancel(){if(this._state==="success"||this._state==="error"||this._state==="canceled")return!1;this._state="canceled",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._isResumable&&this._uploadId?this.client.post("/files/resumable/abort",{path:this.path,uploadId:this._uploadId}).catch(()=>{}):!this._isResumable&&this._simpleFileMetadata&&this.client.delete(`/files/${encodeURIComponent(this.path)}`).catch(()=>{}),this._notifyObservers();let t=new Error("Upload canceled by user");return t.name="UploadCanceled",this._handleError(t),!0}get snapshot(){return{bytesTransferred:this._bytesTransferred,totalBytes:this._totalBytes,state:this._state,task:this}}then(t,e){return this._promise.then(t,e)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}[Symbol.toStringTag]="UploadTask";async _start(){try{if(this.options.compressImage&&this._data.type.startsWith("image/")&&(this._data=await g.compress(this._data,this.options.compressImage)),this.options.encryptionKey&&(this._data=await d.encrypt(this._data,this.options.encryptionKey)),this._totalBytes=this._data.size,this._state!=="processing")return;this._state="running",this._notifyObservers();let t=50*1024*1024;this._isResumable=this._totalBytes>=t,this._isResumable?await this._startResumable():await this._startSimple()}catch(t){this._handleError(t)}}async _startSimple(){let t=await this.client.post("/files/upload-url",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});if(this._simpleFileMetadata=t.file,this._state!=="running")return;let e=new XMLHttpRequest;this._activeXhr=e,await new Promise((s,r)=>{e.open("PUT",t.uploadUrl),e.setRequestHeader("Content-Type",this.contentType),e.upload.onprogress=i=>{i.lengthComputable&&this._state==="running"&&(this._bytesTransferred=i.loaded,this._notifyObservers())},e.onload=()=>{e.status>=200&&e.status<300?s():r(new Error(`Upload failed: ${e.status} ${e.responseText}`))},e.onerror=()=>r(new Error("Network error during upload")),e.onabort=()=>r(new Error("Upload aborted")),e.send(this._data)}),this._activeXhr=void 0,this._state==="running"&&(await this.client.post("/files/complete-upload",{path:this.path}),this._bytesTransferred=this._totalBytes,this._state="success",this._notifyObservers(),this._resolve({file:t.file,resumable:!1}))}async _startResumable(){let t=await this.client.post("/files/resumable/init",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});this._uploadId=t.uploadId,this._simpleFileMetadata=t.file,await this._continueResumable()}async _continueResumable(){if(!this._uploadId||!this._simpleFileMetadata)return;let t=this.options.chunkSize??10*1024*1024,e=Math.ceil(this._totalBytes/t);try{for(;this._currentPartIndex<e;){if(this._state!=="running")return;let s=this._currentPartIndex*t,r=Math.min(s+t,this._totalBytes),i=this._data.slice(s,r),a=await this.client.post("/files/resumable/part-url",{path:this.path,uploadId:this._uploadId,partNumber:this._currentPartIndex+1});if(this._state!=="running")return;let n=await this._uploadChunkWithProgress(a.uploadUrl,i,s);this._parts.push({PartNumber:this._currentPartIndex+1,ETag:n}),this._currentPartIndex++,this._bytesTransferred=Math.min(this._currentPartIndex*t,this._totalBytes),this._notifyObservers()}this._state==="running"&&(await this.client.post("/files/resumable/complete",{path:this.path,uploadId:this._uploadId,parts:this._parts}),this._state="success",this._notifyObservers(),this._resolve({file:this._simpleFileMetadata,resumable:!0}))}catch(s){if(s.message==="Upload aborted")return;this._handleError(s)}}_uploadChunkWithProgress(t,e,s){return new Promise((r,i)=>{let a=new XMLHttpRequest;this._activeXhr=a,a.open("PUT",t),a.setRequestHeader("Content-Type",this.contentType),a.upload.onprogress=n=>{n.lengthComputable&&this._state==="running"&&(this._bytesTransferred=s+n.loaded,this._notifyObservers())},a.onload=()=>{if(a.status>=200&&a.status<300){let n=a.getResponseHeader("ETag")||"";r(n.replace(/"/g,""))}else i(new Error(`Part upload failed: ${a.status}`))},a.onerror=()=>i(new Error("Network error during part upload")),a.onabort=()=>i(new Error("Upload aborted")),a.send(e)})}_notifyObservers(){let t=this.snapshot;this._observers.forEach(e=>{t.state==="success"&&e.complete?e.complete():e.next&&e.next(t)})}_handleError=t=>{this._state!=="canceled"&&(this._state="error",this._activeXhr=void 0,this._notifyObservers(),this._observers.forEach(e=>e.error?.(t)),this._reject(t))}};var w=class{constructor(t,e,s){this.client=t;this.path=e;this.tenantId=s}child(t){let s=(this.path?this.path.endsWith("/")?this.path:this.path+"/":"")+t.replace(/^\//,"");return s.endsWith("/")?new y(this.client,s,this.tenantId):new f(this.client,s,this.tenantId)}},y=class extends w{async listAll(t=100){return(await this.client.get("/files",{prefix:this.path,limit:String(t)})).files}},f=class extends w{put(t,e){let s=(t instanceof File,t.size),r=t instanceof File?t.name:this.path.split("/").pop()||"file",i=t.type||"application/octet-stream";return new m(this.client,this.path,t,r,i,e)}putBytes(t,e,s){let r=this.path.split("/").pop()||"file",i=new Blob([t],{type:e});return new m(this.client,this.path,i,r,e,s)}async getDownloadUrl(t){return t?.versionId?(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t.versionId})).downloadUrl:(await this.client.get(`/files/download-url/${encodeURIComponent(this.path)}`)).downloadUrl}async getDecryptedBlob(t){let e=await this.getDownloadUrl(),s=await fetch(e);if(!s.ok)throw new Error(`Failed to download file from S3: ${s.status}`);let r=await s.blob(),i=await this.getMetadata();return await d.decrypt(r,t,i.content_type)}async getMetadata(){return(await this.client.get(`/files/metadata/${encodeURIComponent(this.path)}`)).file}async updateMetadata(t){return(await this.client.patch(`/files/metadata/${encodeURIComponent(this.path)}`,{metadata:t})).file}async delete(){await this.client.delete(`/files/${encodeURIComponent(this.path)}`)}async listVersions(){return this.client.get(`/files/versions/${encodeURIComponent(this.path)}`)}async getVersionUrl(t){return(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t})).downloadUrl}async getTags(){return(await this.client.get(`/files/tags/${encodeURIComponent(this.path)}`)).tags}async setTags(t){await this.client.put(`/files/tags/${encodeURIComponent(this.path)}`,{tags:t})}async setLegalHold(t){await this.client.post(`/files/legal-hold/${encodeURIComponent(this.path)}`,{status:t})}};var b=class{constructor(t){this.client=t}_op=null;_paths=[];_dest="";delete(t){return this._op="delete",this._paths=t,this}copy(t,e){return this._op="copy",this._paths=t,this._dest=e,this}move(t,e){return this._op="move",this._paths=t,this._dest=e,this}async run(){if(!this._op)throw new Error("No batch operation specified");if(this._op==="delete")return this.client.post("/files/batch/delete",{paths:this._paths});let t={sourcePaths:this._paths,destinationPrefix:this._dest};return this.client.post(`/files/batch/${this._op}`,t)}};var v=class{constructor(t){this.client=t}_query="";_metadata={};_limit=20;nameContains(t){return this._query=t,this}where(t,e){return this._metadata[t]=e,this}limit(t){return this._limit=t,this}async get(){let t={q:this._query||void 0,limit:String(this._limit),metadata:Object.keys(this._metadata).length>0?JSON.stringify(this._metadata):void 0};return(await this.client.get("/files/search",t)).files}};var T=class{constructor(t){this.config=t;this.http=new _(t),this.tenantId=t.tenantId}http;tenantId;ref(t){if(t.endsWith("/"))throw new Error("Use .dir() for directory references");return new f(this.http,t,this.tenantId)}dir(t){let e=t.endsWith("/")?t:t+"/";return new y(this.http,e,this.tenantId)}async list(t){let e={prefix:t?.prefix||"",limit:String(t?.limit||100)};return(await this.http.get("/files",e)).files}async rename(t,e){return this.http.post("/files/rename",{oldPath:t,newName:e})}batch(){return new b(this.http)}query(){return new v(this.http)}async generateApiKey(t){return this.http.post("/internal/keys/generate",{name:t})}async revokeApiKey(t){await this.http.post("/internal/keys/revoke",{keyId:t})}async getBucketInfo(){return this.http.get("/internal/bucket-info")}};0&&(module.exports={BatchBuilder,CryptoHelper,DirRef,FileRef,HttpClient,ImageHelper,QueryBuilder,StorageRef,TelestackError,TelestackStorage,UploadTask});
|
|
1
|
+
"use strict";var U=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var S=(l,t)=>{for(var e in t)U(l,e,{get:t[e],enumerable:!0})},M=(l,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of C(t))!x.call(l,r)&&r!==e&&U(l,r,{get:()=>t[r],enumerable:!(s=B(t,r))||s.enumerable});return l};var E=l=>M(U({},"__esModule",{value:!0}),l);var O={};S(O,{BatchBuilder:()=>b,CryptoHelper:()=>d,DirRef:()=>y,FileRef:()=>f,HttpClient:()=>_,ImageHelper:()=>g,QueryBuilder:()=>v,StorageRef:()=>w,TelestackError:()=>u,TelestackStorage:()=>T,UploadTask:()=>m});module.exports=E(O);var _=class{baseUrl;tenantId;headers;constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.tenantId=t.tenantId,this.headers={"Content-Type":"application/json","X-Tenant-ID":t.tenantId},t.apiKey?this.headers["X-API-Key"]=t.apiKey:t.token&&(this.headers.Authorization=`Bearer ${t.token}`)}async _fetchWithRetry(t,e,s=3){for(let r=0;r<=s;r++)try{let i=await fetch(t,e);if((i.status===429||i.status>=500)&&r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network error ${i.status}. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}return i}catch(i){if(r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network un-reachable. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}throw i}throw new Error("Unreachable code in retry logic")}async get(t,e){let s=new URL(`${this.baseUrl}${t}`);e&&Object.entries(e).forEach(([i,a])=>{a!==void 0&&s.searchParams.set(i,a)});let r=await this._fetchWithRetry(s.toString(),{headers:this.headers});return this._handle(r)}async post(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"POST",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async patch(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PATCH",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async put(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PUT",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async delete(t){let e=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"DELETE",headers:this.headers});return this._handle(e)}async uploadToPresignedUrl(t,e,s,r){for(let a=0;a<=3;a++)try{await new Promise((n,h)=>{let o=new XMLHttpRequest;o.open("PUT",t),o.setRequestHeader("Content-Type",s),r&&(o.upload.onprogress=p=>{p.lengthComputable&&r(Math.round(p.loaded/p.total*100))}),o.onload=()=>{o.status>=200&&o.status<300?n():o.status===429||o.status>=500?h(new Error(`Retryable network error: ${o.status}`)):h(new u(`Upload failed: ${o.status}`,o.status))},o.onerror=()=>h(new Error("Retryable network error")),o.send(e)});return}catch(n){if(n instanceof u||a>=3)throw n;let h=Math.min(1e3*Math.pow(2,a),1e4);console.warn(`[TelestackStorage] Upload chunk failed. Retrying in ${h}ms...`),await new Promise(o=>setTimeout(o,h))}}async _handle(t){let e=await t.json();if(!t.ok)throw new u(e.error||t.statusText,t.status,e.code);return e}},u=class extends Error{constructor(e,s,r){super(e);this.status=s;this.code=r;this.name="TelestackError"}};var d=class{static async generateKey(){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=await crypto.subtle.exportKey("raw",t);return btoa(String.fromCharCode(...new Uint8Array(e)))}static async encrypt(t,e){let s=await this._importKey(e),r=crypto.getRandomValues(new Uint8Array(12)),i=await t.arrayBuffer(),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},s,i);return new Blob([r,a],{type:"application/octet-stream"})}static async decrypt(t,e,s="application/octet-stream"){let r=await this._importKey(e),i=await t.arrayBuffer(),a=i.slice(0,12),n=i.slice(12),h=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(a)},r,n);return new Blob([h],{type:s})}static async _importKey(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0));return crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"])}};var g=class{static async compress(t,e={}){if(!t.type.startsWith("image/"))return t;let{maxWidth:s=1920,maxHeight:r=1080,quality:i=.8}=e;return new Promise((a,n)=>{let h=new Image,o=URL.createObjectURL(t);h.onload=()=>{URL.revokeObjectURL(o);let p=h.width,c=h.height;p>s&&(c=Math.round(c*s/p),p=s),c>r&&(p=Math.round(p*r/c),c=r);let R=document.createElement("canvas");R.width=p,R.height=c;let P=R.getContext("2d");if(!P)return n(new Error("Failed to get canvas 2d context for image compression"));P.drawImage(h,0,0,p,c);let k=t.type==="image/png"?"image/png":"image/webp";R.toBlob(I=>{I?a(I):n(new Error("Canvas toBlob failed"))},k,i)},h.onerror=()=>{URL.revokeObjectURL(o),n(new Error("Failed to load image for compression"))},h.src=o})}};var m=class{constructor(t,e,s,r,i,a){this.client=t;this.path=e;this.name=r;this.contentType=i;this.options=a;this._data=s,this._totalBytes=s.size,this._promise=new Promise((n,h)=>{this._resolve=n,this._reject=h}),this._start()}_state="processing";_bytesTransferred=0;_totalBytes=0;_data;_observers=[];_promise;_resolve;_reject;_uploadId;_parts=[];_currentPartIndex=0;_activeXhr;_isResumable=!1;_simpleFileMetadata;on(t,e,s,r){let i=typeof e=="function"?{next:e,error:s,complete:r}:e||{error:s,complete:r};return this._observers.push(i),i.next&&i.next(this.snapshot),()=>{this._observers=this._observers.filter(a=>a!==i)}}pause(){return this._state!=="running"?!1:(this._state="paused",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._notifyObservers(),!0)}resume(){return this._state!=="paused"?!1:(this._state="running",this._notifyObservers(),this._isResumable?this._continueResumable().catch(this._handleError):(this._bytesTransferred=0,this._notifyObservers(),this._startSimple().catch(this._handleError)),!0)}cancel(){if(this._state==="success"||this._state==="error"||this._state==="canceled")return!1;this._state="canceled",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._isResumable&&this._uploadId?this.client.post("/files/resumable/abort",{path:this.path,uploadId:this._uploadId}).catch(()=>{}):!this._isResumable&&this._simpleFileMetadata&&this.client.delete(`/files/${encodeURIComponent(this.path)}`).catch(()=>{}),this._notifyObservers();let t=new Error("Upload canceled by user");return t.name="UploadCanceled",this._handleError(t),!0}get snapshot(){return{bytesTransferred:this._bytesTransferred,totalBytes:this._totalBytes,state:this._state,task:this}}then(t,e){return this._promise.then(t,e)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}[Symbol.toStringTag]="UploadTask";async _start(){try{if(this.options.compressImage&&this._data.type.startsWith("image/")&&(this._data=await g.compress(this._data,this.options.compressImage)),this.options.encryptionKey&&(this._data=await d.encrypt(this._data,this.options.encryptionKey)),this._totalBytes=this._data.size,this._state!=="processing")return;this._state="running",this._notifyObservers();let t=50*1024*1024;this._isResumable=this._totalBytes>=t,this._isResumable?await this._startResumable():await this._startSimple()}catch(t){this._handleError(t)}}async _startSimple(){let t=await this.client.post("/files/upload-url",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});if(this._simpleFileMetadata=t.file,this._state!=="running")return;let e=new XMLHttpRequest;this._activeXhr=e,await new Promise((s,r)=>{e.open("PUT",t.uploadUrl),e.setRequestHeader("Content-Type",this.contentType),e.upload.onprogress=i=>{i.lengthComputable&&this._state==="running"&&(this._bytesTransferred=i.loaded,this._notifyObservers())},e.onload=()=>{e.status>=200&&e.status<300?s():r(new Error(`Upload failed: ${e.status} ${e.responseText}`))},e.onerror=()=>r(new Error("Network error during upload")),e.onabort=()=>r(new Error("Upload aborted")),e.send(this._data)}),this._activeXhr=void 0,this._state==="running"&&(await this.client.post("/files/complete-upload",{path:this.path}),this._bytesTransferred=this._totalBytes,this._state="success",this._notifyObservers(),this._resolve({file:t.file,resumable:!1}))}async _startResumable(){let t=await this.client.post("/files/resumable/init",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});this._uploadId=t.uploadId,this._simpleFileMetadata=t.file,await this._continueResumable()}async _continueResumable(){if(!this._uploadId||!this._simpleFileMetadata)return;let t=this.options.chunkSize??10*1024*1024,e=Math.ceil(this._totalBytes/t);try{for(;this._currentPartIndex<e;){if(this._state!=="running")return;let s=this._currentPartIndex*t,r=Math.min(s+t,this._totalBytes),i=this._data.slice(s,r),a=await this.client.post("/files/resumable/part-url",{path:this.path,uploadId:this._uploadId,partNumber:this._currentPartIndex+1});if(this._state!=="running")return;let n=await this._uploadChunkWithProgress(a.uploadUrl,i,s);this._parts.push({PartNumber:this._currentPartIndex+1,ETag:n}),this._currentPartIndex++,this._bytesTransferred=Math.min(this._currentPartIndex*t,this._totalBytes),this._notifyObservers()}this._state==="running"&&(await this.client.post("/files/resumable/complete",{path:this.path,uploadId:this._uploadId,parts:this._parts}),this._state="success",this._notifyObservers(),this._resolve({file:this._simpleFileMetadata,resumable:!0}))}catch(s){if(s.message==="Upload aborted")return;this._handleError(s)}}_uploadChunkWithProgress(t,e,s){return new Promise((r,i)=>{let a=new XMLHttpRequest;this._activeXhr=a,a.open("PUT",t),a.setRequestHeader("Content-Type",this.contentType),a.upload.onprogress=n=>{n.lengthComputable&&this._state==="running"&&(this._bytesTransferred=s+n.loaded,this._notifyObservers())},a.onload=()=>{if(a.status>=200&&a.status<300){let n=a.getResponseHeader("ETag")||"";r(n.replace(/"/g,""))}else i(new Error(`Part upload failed: ${a.status}`))},a.onerror=()=>i(new Error("Network error during part upload")),a.onabort=()=>i(new Error("Upload aborted")),a.send(e)})}_notifyObservers(){let t=this.snapshot;this._observers.forEach(e=>{t.state==="success"&&e.complete?e.complete():e.next&&e.next(t)})}_handleError=t=>{this._state!=="canceled"&&(this._state="error",this._activeXhr=void 0,this._notifyObservers(),this._observers.forEach(e=>e.error?.(t)),this._reject(t))}};var w=class{constructor(t,e,s){this.client=t;this.path=e;this.tenantId=s}child(t){let s=(this.path?this.path.endsWith("/")?this.path:this.path+"/":"")+t.replace(/^\//,"");return s.endsWith("/")?new y(this.client,s,this.tenantId):new f(this.client,s,this.tenantId)}},y=class extends w{async listAll(t=100){return(await this.client.get("/files",{prefix:this.path,limit:String(t)})).files}},f=class extends w{put(t,e){let s=(t instanceof File,t.size),r=t instanceof File?t.name:this.path.split("/").pop()||"file",i=t.type||"application/octet-stream";return new m(this.client,this.path,t,r,i,e)}putBytes(t,e,s){let r=this.path.split("/").pop()||"file",i=new Blob([t],{type:e});return new m(this.client,this.path,i,r,e,s)}async getDownloadUrl(t){return t?.versionId?(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t.versionId})).downloadUrl:(await this.client.get(`/files/download-url/${encodeURIComponent(this.path)}`)).downloadUrl}async getDecryptedBlob(t){let e=await this.getDownloadUrl(),s=await fetch(e);if(!s.ok)throw new Error(`Failed to download file from S3: ${s.status}`);let r=await s.blob(),i=await this.getMetadata();return await d.decrypt(r,t,i.content_type)}async getMetadata(){return(await this.client.get(`/files/metadata/${encodeURIComponent(this.path)}`)).file}async updateMetadata(t){return(await this.client.patch(`/files/metadata/${encodeURIComponent(this.path)}`,{metadata:t})).file}async delete(){await this.client.delete(`/files/${encodeURIComponent(this.path)}`)}async listVersions(){return this.client.get(`/files/versions/${encodeURIComponent(this.path)}`)}async getVersionUrl(t){return(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t})).downloadUrl}async getTags(){return(await this.client.get(`/files/tags/${encodeURIComponent(this.path)}`)).tags}async setTags(t){await this.client.put(`/files/tags/${encodeURIComponent(this.path)}`,{tags:t})}async setLegalHold(t){await this.client.post(`/files/legal-hold/${encodeURIComponent(this.path)}`,{status:t})}};var b=class{constructor(t){this.client=t}_op=null;_paths=[];_dest="";delete(t){return this._op="delete",this._paths=t,this}copy(t,e){return this._op="copy",this._paths=t,this._dest=e,this}move(t,e){return this._op="move",this._paths=t,this._dest=e,this}async run(){if(!this._op)throw new Error("No batch operation specified");if(this._op==="delete")return this.client.post("/files/batch/delete",{paths:this._paths});let t={sourcePaths:this._paths,destinationPrefix:this._dest};return this.client.post(`/files/batch/${this._op}`,t)}};var v=class{constructor(t){this.client=t}_query="";_metadata={};_limit=20;nameContains(t){return this._query=t,this}search(t){return this.nameContains(t)}where(t,e){return this._metadata[t]=e,this}limit(t){return this._limit=t,this}async get(){let t={q:this._query||void 0,limit:String(this._limit),metadata:Object.keys(this._metadata).length>0?JSON.stringify(this._metadata):void 0};return(await this.client.get("/files/search",t)).files}async run(){return this.get()}};var T=class{constructor(t){this.config=t;this.http=new _(t),this.tenantId=t.tenantId}http;tenantId;ref(t){if(t.endsWith("/"))throw new Error("Use .dir() for directory references");return new f(this.http,t,this.tenantId)}dir(t){let e=t.endsWith("/")?t:t+"/";return new y(this.http,e,this.tenantId)}async list(t){let e={prefix:t?.prefix||"",limit:String(t?.limit||100)};return(await this.http.get("/files",e)).files}async rename(t,e){return this.http.post("/files/rename",{oldPath:t,newName:e})}batch(){return new b(this.http)}query(){return new v(this.http)}async generateApiKey(t){return this.http.post("/internal/keys/generate",{name:t})}async revokeApiKey(t){await this.http.post("/internal/keys/revoke",{keyId:t})}async getBucketInfo(){return this.http.get("/internal/bucket-info")}};0&&(module.exports={BatchBuilder,CryptoHelper,DirRef,FileRef,HttpClient,ImageHelper,QueryBuilder,StorageRef,TelestackError,TelestackStorage,UploadTask});
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var _=class{baseUrl;tenantId;headers;constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.tenantId=t.tenantId,this.headers={"Content-Type":"application/json","X-Tenant-ID":t.tenantId},t.apiKey?this.headers["X-API-Key"]=t.apiKey:t.token&&(this.headers.Authorization=`Bearer ${t.token}`)}async _fetchWithRetry(t,e,s=3){for(let r=0;r<=s;r++)try{let i=await fetch(t,e);if((i.status===429||i.status>=500)&&r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network error ${i.status}. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}return i}catch(i){if(r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network un-reachable. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}throw i}throw new Error("Unreachable code in retry logic")}async get(t,e){let s=new URL(`${this.baseUrl}${t}`);e&&Object.entries(e).forEach(([i,a])=>{a!==void 0&&s.searchParams.set(i,a)});let r=await this._fetchWithRetry(s.toString(),{headers:this.headers});return this._handle(r)}async post(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"POST",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async patch(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PATCH",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async put(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PUT",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async delete(t){let e=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"DELETE",headers:this.headers});return this._handle(e)}async uploadToPresignedUrl(t,e,s,r){for(let a=0;a<=3;a++)try{await new Promise((n,l)=>{let o=new XMLHttpRequest;o.open("PUT",t),o.setRequestHeader("Content-Type",s),r&&(o.upload.onprogress=h=>{h.lengthComputable&&r(Math.round(h.loaded/h.total*100))}),o.onload=()=>{o.status>=200&&o.status<300?n():o.status===429||o.status>=500?l(new Error(`Retryable network error: ${o.status}`)):l(new u(`Upload failed: ${o.status}`,o.status))},o.onerror=()=>l(new Error("Retryable network error")),o.send(e)});return}catch(n){if(n instanceof u||a>=3)throw n;let l=Math.min(1e3*Math.pow(2,a),1e4);console.warn(`[TelestackStorage] Upload chunk failed. Retrying in ${l}ms...`),await new Promise(o=>setTimeout(o,l))}}async _handle(t){let e=await t.json();if(!t.ok)throw new u(e.error||t.statusText,t.status,e.code);return e}},u=class extends Error{constructor(e,s,r){super(e);this.status=s;this.code=r;this.name="TelestackError"}};var c=class{static async generateKey(){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=await crypto.subtle.exportKey("raw",t);return btoa(String.fromCharCode(...new Uint8Array(e)))}static async encrypt(t,e){let s=await this._importKey(e),r=crypto.getRandomValues(new Uint8Array(12)),i=await t.arrayBuffer(),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},s,i);return new Blob([r,a],{type:"application/octet-stream"})}static async decrypt(t,e,s="application/octet-stream"){let r=await this._importKey(e),i=await t.arrayBuffer(),a=i.slice(0,12),n=i.slice(12),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(a)},r,n);return new Blob([l],{type:s})}static async _importKey(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0));return crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"])}};var g=class{static async compress(t,e={}){if(!t.type.startsWith("image/"))return t;let{maxWidth:s=1920,maxHeight:r=1080,quality:i=.8}=e;return new Promise((a,n)=>{let l=new Image,o=URL.createObjectURL(t);l.onload=()=>{URL.revokeObjectURL(o);let h=l.width,d=l.height;h>s&&(d=Math.round(d*s/h),h=s),d>r&&(h=Math.round(h*r/d),d=r);let R=document.createElement("canvas");R.width=h,R.height=d;let U=R.getContext("2d");if(!U)return n(new Error("Failed to get canvas 2d context for image compression"));U.drawImage(l,0,0,h,d);let I=t.type==="image/png"?"image/png":"image/webp";R.toBlob(P=>{P?a(P):n(new Error("Canvas toBlob failed"))},I,i)},l.onerror=()=>{URL.revokeObjectURL(o),n(new Error("Failed to load image for compression"))},l.src=o})}};var m=class{constructor(t,e,s,r,i,a){this.client=t;this.path=e;this.name=r;this.contentType=i;this.options=a;this._data=s,this._totalBytes=s.size,this._promise=new Promise((n,l)=>{this._resolve=n,this._reject=l}),this._start()}_state="processing";_bytesTransferred=0;_totalBytes=0;_data;_observers=[];_promise;_resolve;_reject;_uploadId;_parts=[];_currentPartIndex=0;_activeXhr;_isResumable=!1;_simpleFileMetadata;on(t,e,s,r){let i=typeof e=="function"?{next:e,error:s,complete:r}:e||{error:s,complete:r};return this._observers.push(i),i.next&&i.next(this.snapshot),()=>{this._observers=this._observers.filter(a=>a!==i)}}pause(){return this._state!=="running"?!1:(this._state="paused",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._notifyObservers(),!0)}resume(){return this._state!=="paused"?!1:(this._state="running",this._notifyObservers(),this._isResumable?this._continueResumable().catch(this._handleError):(this._bytesTransferred=0,this._notifyObservers(),this._startSimple().catch(this._handleError)),!0)}cancel(){if(this._state==="success"||this._state==="error"||this._state==="canceled")return!1;this._state="canceled",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._isResumable&&this._uploadId?this.client.post("/files/resumable/abort",{path:this.path,uploadId:this._uploadId}).catch(()=>{}):!this._isResumable&&this._simpleFileMetadata&&this.client.delete(`/files/${encodeURIComponent(this.path)}`).catch(()=>{}),this._notifyObservers();let t=new Error("Upload canceled by user");return t.name="UploadCanceled",this._handleError(t),!0}get snapshot(){return{bytesTransferred:this._bytesTransferred,totalBytes:this._totalBytes,state:this._state,task:this}}then(t,e){return this._promise.then(t,e)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}[Symbol.toStringTag]="UploadTask";async _start(){try{if(this.options.compressImage&&this._data.type.startsWith("image/")&&(this._data=await g.compress(this._data,this.options.compressImage)),this.options.encryptionKey&&(this._data=await c.encrypt(this._data,this.options.encryptionKey)),this._totalBytes=this._data.size,this._state!=="processing")return;this._state="running",this._notifyObservers();let t=50*1024*1024;this._isResumable=this._totalBytes>=t,this._isResumable?await this._startResumable():await this._startSimple()}catch(t){this._handleError(t)}}async _startSimple(){let t=await this.client.post("/files/upload-url",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});if(this._simpleFileMetadata=t.file,this._state!=="running")return;let e=new XMLHttpRequest;this._activeXhr=e,await new Promise((s,r)=>{e.open("PUT",t.uploadUrl),e.setRequestHeader("Content-Type",this.contentType),e.upload.onprogress=i=>{i.lengthComputable&&this._state==="running"&&(this._bytesTransferred=i.loaded,this._notifyObservers())},e.onload=()=>{e.status>=200&&e.status<300?s():r(new Error(`Upload failed: ${e.status} ${e.responseText}`))},e.onerror=()=>r(new Error("Network error during upload")),e.onabort=()=>r(new Error("Upload aborted")),e.send(this._data)}),this._activeXhr=void 0,this._state==="running"&&(await this.client.post("/files/complete-upload",{path:this.path}),this._bytesTransferred=this._totalBytes,this._state="success",this._notifyObservers(),this._resolve({file:t.file,resumable:!1}))}async _startResumable(){let t=await this.client.post("/files/resumable/init",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});this._uploadId=t.uploadId,this._simpleFileMetadata=t.file,await this._continueResumable()}async _continueResumable(){if(!this._uploadId||!this._simpleFileMetadata)return;let t=this.options.chunkSize??10*1024*1024,e=Math.ceil(this._totalBytes/t);try{for(;this._currentPartIndex<e;){if(this._state!=="running")return;let s=this._currentPartIndex*t,r=Math.min(s+t,this._totalBytes),i=this._data.slice(s,r),a=await this.client.post("/files/resumable/part-url",{path:this.path,uploadId:this._uploadId,partNumber:this._currentPartIndex+1});if(this._state!=="running")return;let n=await this._uploadChunkWithProgress(a.uploadUrl,i,s);this._parts.push({PartNumber:this._currentPartIndex+1,ETag:n}),this._currentPartIndex++,this._bytesTransferred=Math.min(this._currentPartIndex*t,this._totalBytes),this._notifyObservers()}this._state==="running"&&(await this.client.post("/files/resumable/complete",{path:this.path,uploadId:this._uploadId,parts:this._parts}),this._state="success",this._notifyObservers(),this._resolve({file:this._simpleFileMetadata,resumable:!0}))}catch(s){if(s.message==="Upload aborted")return;this._handleError(s)}}_uploadChunkWithProgress(t,e,s){return new Promise((r,i)=>{let a=new XMLHttpRequest;this._activeXhr=a,a.open("PUT",t),a.setRequestHeader("Content-Type",this.contentType),a.upload.onprogress=n=>{n.lengthComputable&&this._state==="running"&&(this._bytesTransferred=s+n.loaded,this._notifyObservers())},a.onload=()=>{if(a.status>=200&&a.status<300){let n=a.getResponseHeader("ETag")||"";r(n.replace(/"/g,""))}else i(new Error(`Part upload failed: ${a.status}`))},a.onerror=()=>i(new Error("Network error during part upload")),a.onabort=()=>i(new Error("Upload aborted")),a.send(e)})}_notifyObservers(){let t=this.snapshot;this._observers.forEach(e=>{t.state==="success"&&e.complete?e.complete():e.next&&e.next(t)})}_handleError=t=>{this._state!=="canceled"&&(this._state="error",this._activeXhr=void 0,this._notifyObservers(),this._observers.forEach(e=>e.error?.(t)),this._reject(t))}};var w=class{constructor(t,e,s){this.client=t;this.path=e;this.tenantId=s}child(t){let s=(this.path?this.path.endsWith("/")?this.path:this.path+"/":"")+t.replace(/^\//,"");return s.endsWith("/")?new y(this.client,s,this.tenantId):new f(this.client,s,this.tenantId)}},y=class extends w{async listAll(t=100){return(await this.client.get("/files",{prefix:this.path,limit:String(t)})).files}},f=class extends w{put(t,e){let s=(t instanceof File,t.size),r=t instanceof File?t.name:this.path.split("/").pop()||"file",i=t.type||"application/octet-stream";return new m(this.client,this.path,t,r,i,e)}putBytes(t,e,s){let r=this.path.split("/").pop()||"file",i=new Blob([t],{type:e});return new m(this.client,this.path,i,r,e,s)}async getDownloadUrl(t){return t?.versionId?(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t.versionId})).downloadUrl:(await this.client.get(`/files/download-url/${encodeURIComponent(this.path)}`)).downloadUrl}async getDecryptedBlob(t){let e=await this.getDownloadUrl(),s=await fetch(e);if(!s.ok)throw new Error(`Failed to download file from S3: ${s.status}`);let r=await s.blob(),i=await this.getMetadata();return await c.decrypt(r,t,i.content_type)}async getMetadata(){return(await this.client.get(`/files/metadata/${encodeURIComponent(this.path)}`)).file}async updateMetadata(t){return(await this.client.patch(`/files/metadata/${encodeURIComponent(this.path)}`,{metadata:t})).file}async delete(){await this.client.delete(`/files/${encodeURIComponent(this.path)}`)}async listVersions(){return this.client.get(`/files/versions/${encodeURIComponent(this.path)}`)}async getVersionUrl(t){return(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t})).downloadUrl}async getTags(){return(await this.client.get(`/files/tags/${encodeURIComponent(this.path)}`)).tags}async setTags(t){await this.client.put(`/files/tags/${encodeURIComponent(this.path)}`,{tags:t})}async setLegalHold(t){await this.client.post(`/files/legal-hold/${encodeURIComponent(this.path)}`,{status:t})}};var b=class{constructor(t){this.client=t}_op=null;_paths=[];_dest="";delete(t){return this._op="delete",this._paths=t,this}copy(t,e){return this._op="copy",this._paths=t,this._dest=e,this}move(t,e){return this._op="move",this._paths=t,this._dest=e,this}async run(){if(!this._op)throw new Error("No batch operation specified");if(this._op==="delete")return this.client.post("/files/batch/delete",{paths:this._paths});let t={sourcePaths:this._paths,destinationPrefix:this._dest};return this.client.post(`/files/batch/${this._op}`,t)}};var v=class{constructor(t){this.client=t}_query="";_metadata={};_limit=20;nameContains(t){return this._query=t,this}where(t,e){return this._metadata[t]=e,this}limit(t){return this._limit=t,this}async get(){let t={q:this._query||void 0,limit:String(this._limit),metadata:Object.keys(this._metadata).length>0?JSON.stringify(this._metadata):void 0};return(await this.client.get("/files/search",t)).files}};var T=class{constructor(t){this.config=t;this.http=new _(t),this.tenantId=t.tenantId}http;tenantId;ref(t){if(t.endsWith("/"))throw new Error("Use .dir() for directory references");return new f(this.http,t,this.tenantId)}dir(t){let e=t.endsWith("/")?t:t+"/";return new y(this.http,e,this.tenantId)}async list(t){let e={prefix:t?.prefix||"",limit:String(t?.limit||100)};return(await this.http.get("/files",e)).files}async rename(t,e){return this.http.post("/files/rename",{oldPath:t,newName:e})}batch(){return new b(this.http)}query(){return new v(this.http)}async generateApiKey(t){return this.http.post("/internal/keys/generate",{name:t})}async revokeApiKey(t){await this.http.post("/internal/keys/revoke",{keyId:t})}async getBucketInfo(){return this.http.get("/internal/bucket-info")}};export{b as BatchBuilder,c as CryptoHelper,y as DirRef,f as FileRef,_ as HttpClient,g as ImageHelper,v as QueryBuilder,w as StorageRef,u as TelestackError,T as TelestackStorage,m as UploadTask};
|
|
1
|
+
var _=class{baseUrl;tenantId;headers;constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.tenantId=t.tenantId,this.headers={"Content-Type":"application/json","X-Tenant-ID":t.tenantId},t.apiKey?this.headers["X-API-Key"]=t.apiKey:t.token&&(this.headers.Authorization=`Bearer ${t.token}`)}async _fetchWithRetry(t,e,s=3){for(let r=0;r<=s;r++)try{let i=await fetch(t,e);if((i.status===429||i.status>=500)&&r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network error ${i.status}. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}return i}catch(i){if(r<s){let a=Math.min(1e3*Math.pow(2,r),1e4);console.warn(`[TelestackStorage] Network un-reachable. Retrying in ${a}ms...`),await new Promise(n=>setTimeout(n,a));continue}throw i}throw new Error("Unreachable code in retry logic")}async get(t,e){let s=new URL(`${this.baseUrl}${t}`);e&&Object.entries(e).forEach(([i,a])=>{a!==void 0&&s.searchParams.set(i,a)});let r=await this._fetchWithRetry(s.toString(),{headers:this.headers});return this._handle(r)}async post(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"POST",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async patch(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PATCH",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async put(t,e){let s=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"PUT",headers:this.headers,body:JSON.stringify(e)});return this._handle(s)}async delete(t){let e=await this._fetchWithRetry(`${this.baseUrl}${t}`,{method:"DELETE",headers:this.headers});return this._handle(e)}async uploadToPresignedUrl(t,e,s,r){for(let a=0;a<=3;a++)try{await new Promise((n,l)=>{let o=new XMLHttpRequest;o.open("PUT",t),o.setRequestHeader("Content-Type",s),r&&(o.upload.onprogress=h=>{h.lengthComputable&&r(Math.round(h.loaded/h.total*100))}),o.onload=()=>{o.status>=200&&o.status<300?n():o.status===429||o.status>=500?l(new Error(`Retryable network error: ${o.status}`)):l(new u(`Upload failed: ${o.status}`,o.status))},o.onerror=()=>l(new Error("Retryable network error")),o.send(e)});return}catch(n){if(n instanceof u||a>=3)throw n;let l=Math.min(1e3*Math.pow(2,a),1e4);console.warn(`[TelestackStorage] Upload chunk failed. Retrying in ${l}ms...`),await new Promise(o=>setTimeout(o,l))}}async _handle(t){let e=await t.json();if(!t.ok)throw new u(e.error||t.statusText,t.status,e.code);return e}},u=class extends Error{constructor(e,s,r){super(e);this.status=s;this.code=r;this.name="TelestackError"}};var c=class{static async generateKey(){let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=await crypto.subtle.exportKey("raw",t);return btoa(String.fromCharCode(...new Uint8Array(e)))}static async encrypt(t,e){let s=await this._importKey(e),r=crypto.getRandomValues(new Uint8Array(12)),i=await t.arrayBuffer(),a=await crypto.subtle.encrypt({name:"AES-GCM",iv:r},s,i);return new Blob([r,a],{type:"application/octet-stream"})}static async decrypt(t,e,s="application/octet-stream"){let r=await this._importKey(e),i=await t.arrayBuffer(),a=i.slice(0,12),n=i.slice(12),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:new Uint8Array(a)},r,n);return new Blob([l],{type:s})}static async _importKey(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0));return crypto.subtle.importKey("raw",e,{name:"AES-GCM"},!1,["encrypt","decrypt"])}};var g=class{static async compress(t,e={}){if(!t.type.startsWith("image/"))return t;let{maxWidth:s=1920,maxHeight:r=1080,quality:i=.8}=e;return new Promise((a,n)=>{let l=new Image,o=URL.createObjectURL(t);l.onload=()=>{URL.revokeObjectURL(o);let h=l.width,d=l.height;h>s&&(d=Math.round(d*s/h),h=s),d>r&&(h=Math.round(h*r/d),d=r);let R=document.createElement("canvas");R.width=h,R.height=d;let U=R.getContext("2d");if(!U)return n(new Error("Failed to get canvas 2d context for image compression"));U.drawImage(l,0,0,h,d);let I=t.type==="image/png"?"image/png":"image/webp";R.toBlob(P=>{P?a(P):n(new Error("Canvas toBlob failed"))},I,i)},l.onerror=()=>{URL.revokeObjectURL(o),n(new Error("Failed to load image for compression"))},l.src=o})}};var m=class{constructor(t,e,s,r,i,a){this.client=t;this.path=e;this.name=r;this.contentType=i;this.options=a;this._data=s,this._totalBytes=s.size,this._promise=new Promise((n,l)=>{this._resolve=n,this._reject=l}),this._start()}_state="processing";_bytesTransferred=0;_totalBytes=0;_data;_observers=[];_promise;_resolve;_reject;_uploadId;_parts=[];_currentPartIndex=0;_activeXhr;_isResumable=!1;_simpleFileMetadata;on(t,e,s,r){let i=typeof e=="function"?{next:e,error:s,complete:r}:e||{error:s,complete:r};return this._observers.push(i),i.next&&i.next(this.snapshot),()=>{this._observers=this._observers.filter(a=>a!==i)}}pause(){return this._state!=="running"?!1:(this._state="paused",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._notifyObservers(),!0)}resume(){return this._state!=="paused"?!1:(this._state="running",this._notifyObservers(),this._isResumable?this._continueResumable().catch(this._handleError):(this._bytesTransferred=0,this._notifyObservers(),this._startSimple().catch(this._handleError)),!0)}cancel(){if(this._state==="success"||this._state==="error"||this._state==="canceled")return!1;this._state="canceled",this._activeXhr&&(this._activeXhr.abort(),this._activeXhr=void 0),this._isResumable&&this._uploadId?this.client.post("/files/resumable/abort",{path:this.path,uploadId:this._uploadId}).catch(()=>{}):!this._isResumable&&this._simpleFileMetadata&&this.client.delete(`/files/${encodeURIComponent(this.path)}`).catch(()=>{}),this._notifyObservers();let t=new Error("Upload canceled by user");return t.name="UploadCanceled",this._handleError(t),!0}get snapshot(){return{bytesTransferred:this._bytesTransferred,totalBytes:this._totalBytes,state:this._state,task:this}}then(t,e){return this._promise.then(t,e)}catch(t){return this._promise.catch(t)}finally(t){return this._promise.finally(t)}[Symbol.toStringTag]="UploadTask";async _start(){try{if(this.options.compressImage&&this._data.type.startsWith("image/")&&(this._data=await g.compress(this._data,this.options.compressImage)),this.options.encryptionKey&&(this._data=await c.encrypt(this._data,this.options.encryptionKey)),this._totalBytes=this._data.size,this._state!=="processing")return;this._state="running",this._notifyObservers();let t=50*1024*1024;this._isResumable=this._totalBytes>=t,this._isResumable?await this._startResumable():await this._startSimple()}catch(t){this._handleError(t)}}async _startSimple(){let t=await this.client.post("/files/upload-url",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});if(this._simpleFileMetadata=t.file,this._state!=="running")return;let e=new XMLHttpRequest;this._activeXhr=e,await new Promise((s,r)=>{e.open("PUT",t.uploadUrl),e.setRequestHeader("Content-Type",this.contentType),e.upload.onprogress=i=>{i.lengthComputable&&this._state==="running"&&(this._bytesTransferred=i.loaded,this._notifyObservers())},e.onload=()=>{e.status>=200&&e.status<300?s():r(new Error(`Upload failed: ${e.status} ${e.responseText}`))},e.onerror=()=>r(new Error("Network error during upload")),e.onabort=()=>r(new Error("Upload aborted")),e.send(this._data)}),this._activeXhr=void 0,this._state==="running"&&(await this.client.post("/files/complete-upload",{path:this.path}),this._bytesTransferred=this._totalBytes,this._state="success",this._notifyObservers(),this._resolve({file:t.file,resumable:!1}))}async _startResumable(){let t=await this.client.post("/files/resumable/init",{path:this.path,name:this.name,size:this._totalBytes,contentType:this.contentType,userId:this.options.userId,metadata:this.options.metadata});this._uploadId=t.uploadId,this._simpleFileMetadata=t.file,await this._continueResumable()}async _continueResumable(){if(!this._uploadId||!this._simpleFileMetadata)return;let t=this.options.chunkSize??10*1024*1024,e=Math.ceil(this._totalBytes/t);try{for(;this._currentPartIndex<e;){if(this._state!=="running")return;let s=this._currentPartIndex*t,r=Math.min(s+t,this._totalBytes),i=this._data.slice(s,r),a=await this.client.post("/files/resumable/part-url",{path:this.path,uploadId:this._uploadId,partNumber:this._currentPartIndex+1});if(this._state!=="running")return;let n=await this._uploadChunkWithProgress(a.uploadUrl,i,s);this._parts.push({PartNumber:this._currentPartIndex+1,ETag:n}),this._currentPartIndex++,this._bytesTransferred=Math.min(this._currentPartIndex*t,this._totalBytes),this._notifyObservers()}this._state==="running"&&(await this.client.post("/files/resumable/complete",{path:this.path,uploadId:this._uploadId,parts:this._parts}),this._state="success",this._notifyObservers(),this._resolve({file:this._simpleFileMetadata,resumable:!0}))}catch(s){if(s.message==="Upload aborted")return;this._handleError(s)}}_uploadChunkWithProgress(t,e,s){return new Promise((r,i)=>{let a=new XMLHttpRequest;this._activeXhr=a,a.open("PUT",t),a.setRequestHeader("Content-Type",this.contentType),a.upload.onprogress=n=>{n.lengthComputable&&this._state==="running"&&(this._bytesTransferred=s+n.loaded,this._notifyObservers())},a.onload=()=>{if(a.status>=200&&a.status<300){let n=a.getResponseHeader("ETag")||"";r(n.replace(/"/g,""))}else i(new Error(`Part upload failed: ${a.status}`))},a.onerror=()=>i(new Error("Network error during part upload")),a.onabort=()=>i(new Error("Upload aborted")),a.send(e)})}_notifyObservers(){let t=this.snapshot;this._observers.forEach(e=>{t.state==="success"&&e.complete?e.complete():e.next&&e.next(t)})}_handleError=t=>{this._state!=="canceled"&&(this._state="error",this._activeXhr=void 0,this._notifyObservers(),this._observers.forEach(e=>e.error?.(t)),this._reject(t))}};var w=class{constructor(t,e,s){this.client=t;this.path=e;this.tenantId=s}child(t){let s=(this.path?this.path.endsWith("/")?this.path:this.path+"/":"")+t.replace(/^\//,"");return s.endsWith("/")?new y(this.client,s,this.tenantId):new f(this.client,s,this.tenantId)}},y=class extends w{async listAll(t=100){return(await this.client.get("/files",{prefix:this.path,limit:String(t)})).files}},f=class extends w{put(t,e){let s=(t instanceof File,t.size),r=t instanceof File?t.name:this.path.split("/").pop()||"file",i=t.type||"application/octet-stream";return new m(this.client,this.path,t,r,i,e)}putBytes(t,e,s){let r=this.path.split("/").pop()||"file",i=new Blob([t],{type:e});return new m(this.client,this.path,i,r,e,s)}async getDownloadUrl(t){return t?.versionId?(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t.versionId})).downloadUrl:(await this.client.get(`/files/download-url/${encodeURIComponent(this.path)}`)).downloadUrl}async getDecryptedBlob(t){let e=await this.getDownloadUrl(),s=await fetch(e);if(!s.ok)throw new Error(`Failed to download file from S3: ${s.status}`);let r=await s.blob(),i=await this.getMetadata();return await c.decrypt(r,t,i.content_type)}async getMetadata(){return(await this.client.get(`/files/metadata/${encodeURIComponent(this.path)}`)).file}async updateMetadata(t){return(await this.client.patch(`/files/metadata/${encodeURIComponent(this.path)}`,{metadata:t})).file}async delete(){await this.client.delete(`/files/${encodeURIComponent(this.path)}`)}async listVersions(){return this.client.get(`/files/versions/${encodeURIComponent(this.path)}`)}async getVersionUrl(t){return(await this.client.get(`/files/version-url/${encodeURIComponent(this.path)}`,{versionId:t})).downloadUrl}async getTags(){return(await this.client.get(`/files/tags/${encodeURIComponent(this.path)}`)).tags}async setTags(t){await this.client.put(`/files/tags/${encodeURIComponent(this.path)}`,{tags:t})}async setLegalHold(t){await this.client.post(`/files/legal-hold/${encodeURIComponent(this.path)}`,{status:t})}};var b=class{constructor(t){this.client=t}_op=null;_paths=[];_dest="";delete(t){return this._op="delete",this._paths=t,this}copy(t,e){return this._op="copy",this._paths=t,this._dest=e,this}move(t,e){return this._op="move",this._paths=t,this._dest=e,this}async run(){if(!this._op)throw new Error("No batch operation specified");if(this._op==="delete")return this.client.post("/files/batch/delete",{paths:this._paths});let t={sourcePaths:this._paths,destinationPrefix:this._dest};return this.client.post(`/files/batch/${this._op}`,t)}};var v=class{constructor(t){this.client=t}_query="";_metadata={};_limit=20;nameContains(t){return this._query=t,this}search(t){return this.nameContains(t)}where(t,e){return this._metadata[t]=e,this}limit(t){return this._limit=t,this}async get(){let t={q:this._query||void 0,limit:String(this._limit),metadata:Object.keys(this._metadata).length>0?JSON.stringify(this._metadata):void 0};return(await this.client.get("/files/search",t)).files}async run(){return this.get()}};var T=class{constructor(t){this.config=t;this.http=new _(t),this.tenantId=t.tenantId}http;tenantId;ref(t){if(t.endsWith("/"))throw new Error("Use .dir() for directory references");return new f(this.http,t,this.tenantId)}dir(t){let e=t.endsWith("/")?t:t+"/";return new y(this.http,e,this.tenantId)}async list(t){let e={prefix:t?.prefix||"",limit:String(t?.limit||100)};return(await this.http.get("/files",e)).files}async rename(t,e){return this.http.post("/files/rename",{oldPath:t,newName:e})}batch(){return new b(this.http)}query(){return new v(this.http)}async generateApiKey(t){return this.http.post("/internal/keys/generate",{name:t})}async revokeApiKey(t){await this.http.post("/internal/keys/revoke",{keyId:t})}async getBucketInfo(){return this.http.get("/internal/bucket-info")}};export{b as BatchBuilder,c as CryptoHelper,y as DirRef,f as FileRef,_ as HttpClient,g as ImageHelper,v as QueryBuilder,w as StorageRef,u as TelestackError,T as TelestackStorage,m as UploadTask};
|
package/package.json
CHANGED