@nocloud/sdk 0.1.11 → 0.1.13

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/README.md CHANGED
@@ -59,7 +59,7 @@ const cloud = new NoCloud({
59
59
  apiKey: "your-api-key",
60
60
  baseUrl: "https://api.nonefivem.com", // optional
61
61
  retries: 3, // optional
62
- retryDelayMs: 1000, // optional
62
+ retryDelayMs: 1000 // optional
63
63
  });
64
64
  ```
65
65
 
@@ -83,7 +83,7 @@ const { id, url } = await cloud.storage.upload(base64);
83
83
  // With metadata
84
84
  const { id, url } = await cloud.storage.upload(file, {
85
85
  userId: "123",
86
- category: "avatars",
86
+ category: "avatars"
87
87
  });
88
88
  ```
89
89
 
@@ -94,7 +94,7 @@ const stream = getReadableStream();
94
94
  const { id, url } = await cloud.storage.uploadStream(
95
95
  stream,
96
96
  "video/mp4",
97
- fileSize,
97
+ fileSize
98
98
  );
99
99
  ```
100
100
 
@@ -121,6 +121,10 @@ Base64 strings with data URLs (`data:image/png;base64,...`) or raw base64 are au
121
121
 
122
122
  ## ⚠️ Error Handling
123
123
 
124
+ The SDK provides detailed error handling through `NoCloudAPIError` and `NoCloudError` enum.
125
+
126
+ ### Basic Error Handling
127
+
124
128
  ```typescript
125
129
  import { NoCloud, NoCloudAPIError } from "@nocloud/sdk";
126
130
 
@@ -128,7 +132,28 @@ try {
128
132
  await cloud.storage.upload(file);
129
133
  } catch (error) {
130
134
  if (error instanceof NoCloudAPIError) {
131
- console.error(`API Error: ${error.message} (${error.status})`);
135
+ console.error(`API Error: ${error.message}`);
136
+ console.error(`Status: ${error.status}`);
137
+ console.error(`Code: ${error.code}`);
138
+ }
139
+ }
140
+ ```
141
+
142
+ ### Check for Specific Errors
143
+
144
+ ```typescript
145
+ import { NoCloudAPIError, NoCloudError } from "@nocloud/sdk";
146
+
147
+ try {
148
+ await cloud.storage.upload(file);
149
+ } catch (error) {
150
+ // Using the static isError method
151
+ if (NoCloudAPIError.isError(error, NoCloudError.RATE_LIMIT_EXCEEDED)) {
152
+ console.log("Rate limited, retry later");
153
+ } else if (NoCloudAPIError.isError(error, NoCloudError.INVALID_API_KEY)) {
154
+ console.log("Check your API key");
155
+ } else if (NoCloudAPIError.isError(error)) {
156
+ console.log(`Other API error: ${error.code}`);
132
157
  }
133
158
  }
134
159
  ```
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- var{defineProperty:P,getOwnPropertyNames:q,getOwnPropertyDescriptor:u}=Object,G=Object.prototype.hasOwnProperty;var v=new WeakMap,L=(h)=>{var F=v.get(h),c;if(F)return F;if(F=P({},"__esModule",{value:!0}),h&&typeof h==="object"||typeof h==="function")q(h).map((x)=>!G.call(F,x)&&P(F,x,{get:()=>h[x],enumerable:!(c=u(h,x))||c.enumerable}));return v.set(h,F),F};var k=(h,F)=>{for(var c in F)P(h,c,{get:F[c],enumerable:!0,configurable:!0,set:(x)=>F[c]=()=>x})};var J={};k(J,{default:()=>g,NoCloudAPIError:()=>O,NoCloud:()=>A});module.exports=L(J);var C="https://api.nonefivem.com",Q="/cloud";class O extends Error{status;constructor(h,F){super(h);this.status=F;this.name="NoCloudAPIError"}}function w(h){return new Promise((F)=>setTimeout(F,h))}async function V(h,F=3,c=1000){let x;for(let f=0;f<=F;f++)try{return await h()}catch(K){if(x=K,f<F)await w(c)}throw x}var E={iVBORw0KGgo:"image/png","/9j/":"image/jpeg",R0lGOD:"image/gif",UklGR:"image/webp",AAAA:"video/mp4",JVBERi0:"application/pdf",UEsDB:"application/zip",PD94bWw:"application/xml",PHN2Zw:"image/svg+xml"};function W(h){let F=h.match(/^data:([^;,]+)/);if(F?.[1])return F[1];for(let[c,x]of Object.entries(E))if(h.startsWith(c))return x;return null}function X(h){let F=h.match(/^data:[^;,]+;base64,(.+)$/);if(F?.[1])return F[1];return h}function Y(h){let F=atob(h),c=new Uint8Array(F.length);for(let x=0;x<F.length;x++)c[x]=F.charCodeAt(x);return c}function Z(h){return h.split(";")[0]?.trim()??h}class r{baseUrl;basePath;apiKey;retryCount;retryDelayMs;constructor(h){if(this.apiKey=h.apiKey,this.baseUrl=(h.baseUrl||C).replace(/\/+$/,""),this.basePath=(h.basePath??Q).replace(/^\/+|\/+$/g,""),this.retryCount=h.retries??3,this.retryDelayMs=h.retryDelayMs??1000,!this.apiKey)throw Error("API key is required")}buildUrl(h){let F=this.basePath?`${this.basePath}/${h}`:h;return`${this.baseUrl}/${F}`}fetch(h,F={}){let c=this.buildUrl(h);return V(()=>fetch(c,{...F,headers:{Authorization:`Bearer ${this.apiKey}`,...F.headers||{}}}),F.retries??this.retryCount,F.retryDelayMs??this.retryDelayMs)}}async function U(h){if(!h.ok){let F=await h.json().catch(()=>({}));throw new O(F.message||"Unknown error",h.status)}return await h.json()}class B{fetcher;constructor(h){this.fetcher=h}fetch(h,F){return this.fetcher.fetch(h,F)}}class H extends B{async generateSignedUrl(h,F,c){let x=new URLSearchParams;x.append("contentType",h),x.append("size",F.toString());let f=await this.fetch(`storage/signed-url?${x.toString()}`);return U(f)}getBodyInfo(h){if(typeof Blob<"u"&&h instanceof Blob)return{contentType:Z(h.type)||"application/octet-stream",size:h.size,normalizedBody:h};if(typeof ArrayBuffer<"u"&&h instanceof ArrayBuffer)return{contentType:"application/octet-stream",size:h.byteLength,normalizedBody:h};if(typeof h==="string"){let F=W(h);if(F){let x=X(h),f=Y(x);return{contentType:F,size:f.byteLength,normalizedBody:new Blob([f.buffer])}}let c=new TextEncoder().encode(h);return{contentType:"text/plain",size:c.length,normalizedBody:new Blob([c.buffer])}}throw new O("Unsupported body type",400)}async upload(h,F){let{contentType:c,size:x,normalizedBody:f}=this.getBodyInfo(h),{url:K,mediaUrl:D,mediaId:_}=await this.generateSignedUrl(c,x,F),$=await fetch(K,{method:"PUT",headers:{"Content-Length":x.toString()},body:f});if(!$.ok){let j=await $.text().catch(()=>$.statusText);throw new O(`Failed to upload file to R2: ${j}`,$.status)}return{id:_,url:D}}async uploadStream(h,F,c,x){let{url:f,mediaUrl:K,mediaId:D}=await this.generateSignedUrl(F,c,x),_=await fetch(f,{method:"PUT",headers:{"Content-Length":c.toString()},body:h,duplex:"half"});if(!_.ok){let $=await _.text().catch(()=>_.statusText);throw new O(`Failed to upload stream to R2: ${$}`,_.status)}return{id:D,url:K}}async delete(h){let F=await this.fetch(`storage/${h}`,{method:"DELETE"});await U(F)}}class A{fetcher;constructor(h){if(typeof h==="string")h={apiKey:h};this.fetcher=new r({apiKey:h.apiKey,baseUrl:h.baseUrl,basePath:h.basePath,retries:h.retries,retryDelayMs:h.retryDelayMs})}_storage;get storage(){return this._storage??=new H(this.fetcher)}}var g=A;
1
+ var{defineProperty:W,getOwnPropertyNames:z,getOwnPropertyDescriptor:M}=Object,R=Object.prototype.hasOwnProperty;var q=new WeakMap,S=(h)=>{var f=q.get(h),x;if(f)return f;if(f=W({},"__esModule",{value:!0}),h&&typeof h==="object"||typeof h==="function")z(h).map((F)=>!R.call(f,F)&&W(f,F,{get:()=>h[F],enumerable:!(x=M(h,F))||x.enumerable}));return q.set(h,f),f};var c=(h,f)=>{for(var x in f)W(h,x,{get:f[x],enumerable:!0,configurable:!0,set:(F)=>f[x]=()=>F})};var b={};c(b,{default:()=>A,NoCloudError:()=>L,NoCloudAPIError:()=>O,NoCloud:()=>V});module.exports=S(b);var w="https://api.nonefivem.com",G="/cloud";var L;((D)=>{D.INVALID_API_KEY="INVALID_API_KEY";D.BAD_REQUEST="BAD_REQUEST";D.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";D.RESOURCE_NOT_FOUND="RESOURCE_NOT_FOUND";D.INTERNAL_SERVER_ERROR="INTERNAL_SERVER_ERROR";D.UNKNOWN_ERROR="UNKNOWN_ERROR"})(L||={});class O extends Error{status;code;constructor(h,f,x){super(h);this.status=f;this.code=x;this.name="NoCloudAPIError",this.code=x}static isError(h,f){if(!(h instanceof O))return!1;if(f&&h.code!==f)return!1;return!0}static fromCode(h,f){switch(h){case"BAD_REQUEST":return new O(f,400,h);case"INVALID_API_KEY":return new O(f,401,h);case"RATE_LIMIT_EXCEEDED":return new O(f,429,h);case"RESOURCE_NOT_FOUND":return new O(f,404,h);case"INTERNAL_SERVER_ERROR":case"UNKNOWN_ERROR":return new O(f,500,h);default:return new O(f,500,"INTERNAL_SERVER_ERROR")}}static fromStatus(h,f){switch(h){case 400:return new O(f,h,"BAD_REQUEST");case 401:return new O(f,h,"INVALID_API_KEY");case 429:return new O(f,h,"RATE_LIMIT_EXCEEDED");case 404:return new O(f,h,"RESOURCE_NOT_FOUND");case 500:return new O(f,h,"INTERNAL_SERVER_ERROR");default:return new O(f,h,"UNKNOWN_ERROR")}}}function y(h){return new Promise((f)=>setTimeout(f,h))}async function B(h,f=3,x=1000){let F;for(let $=0;$<=f;$++)try{return await h()}catch(_){if(F=_,$<f)await y(x)}throw F}var P={iVBORw0KGgo:"image/png","/9j/":"image/jpeg",R0lGOD:"image/gif",UklGR:"image/webp",AAAA:"video/mp4",JVBERi0:"application/pdf",UEsDB:"application/zip",PD94bWw:"application/xml",PHN2Zw:"image/svg+xml"};function k(h){let f=h.match(/^data:([^;,]+)/);if(f?.[1])return f[1];for(let[x,F]of Object.entries(P))if(h.startsWith(x))return F;return null}function Z(h){let f=h.match(/^data:[^;,]+;base64,(.+)$/);if(f?.[1])return f[1];return h}function v(h){let f=atob(h),x=new Uint8Array(f.length);for(let F=0;F<f.length;F++)x[F]=f.charCodeAt(F);return x}function H(h){return h.split(";")[0]?.trim()??h}class X{baseUrl;basePath;apiKey;retryCount;retryDelayMs;constructor(h){if(this.apiKey=h.apiKey,this.baseUrl=(h.baseUrl||w).replace(/\/+$/,""),this.basePath=(h.basePath??G).replace(/^\/+|\/+$/g,""),this.retryCount=h.retries??3,this.retryDelayMs=h.retryDelayMs??1000,!this.apiKey)throw Error("API key is required")}buildUrl(h){let f=this.basePath?`${this.basePath}/${h}`:h;return`${this.baseUrl}/${f}`}fetch(h,f={}){let x=this.buildUrl(h);return B(()=>fetch(x,{...f,headers:{Authorization:`Bearer ${this.apiKey}`,...f.headers||{}}}),f.retries??this.retryCount,f.retryDelayMs??this.retryDelayMs)}}async function Q(h){if(!h.ok){let f=await h.json().catch(()=>({}));throw O.fromStatus(h.status,f.message||"Unknown error")}return await h.json()}class Y{fetcher;constructor(h){this.fetcher=h}fetch(h,f){return this.fetcher.fetch(h,f)}}class j extends Y{async generateSignedUrl(h,f,x){let F=new URLSearchParams;F.append("contentType",h),F.append("size",f.toString());let $=await this.fetch(`storage/signed-url?${F.toString()}`);return Q($)}getBodyInfo(h){if(typeof Blob<"u"&&h instanceof Blob)return{contentType:H(h.type)||"application/octet-stream",size:h.size,normalizedBody:h};if(typeof ArrayBuffer<"u"&&h instanceof ArrayBuffer)return{contentType:"application/octet-stream",size:h.byteLength,normalizedBody:h};if(typeof h==="string"){let f=k(h);if(f){let F=Z(h),$=v(F);return{contentType:f,size:$.byteLength,normalizedBody:new Blob([$.buffer])}}let x=new TextEncoder().encode(h);return{contentType:"text/plain",size:x.length,normalizedBody:new Blob([x.buffer])}}throw O.fromStatus(400,"Unsupported body type")}async upload(h,f){let{contentType:x,size:F,normalizedBody:$}=this.getBodyInfo(h),{url:_,mediaUrl:D,mediaId:K}=await this.generateSignedUrl(x,F,f),U=await fetch(_,{method:"PUT",headers:{"Content-Length":F.toString()},body:$});if(!U.ok){let J=await U.text().catch(()=>U.statusText);throw O.fromStatus(U.status,`Failed to upload file to R2: ${J}`)}return{id:K,url:D}}async uploadStream(h,f,x,F){let{url:$,mediaUrl:_,mediaId:D}=await this.generateSignedUrl(f,x,F),K=await fetch($,{method:"PUT",headers:{"Content-Length":x.toString()},body:h,duplex:"half"});if(!K.ok){let U=await K.text().catch(()=>K.statusText);throw O.fromStatus(K.status,`Failed to upload stream to R2: ${U}`)}return{id:D,url:_}}async delete(h){if(!Array.isArray(h)){let F=await this.fetch(`storage/${h}`,{method:"DELETE"});await Q(F);return}if(h.length===0)return;if(h.length===1)return this.delete(h[0]);let f=100,x=Math.ceil(h.length/f);for(let F=0;F<x;F++){let $=F*f,_=Math.min($+f,h.length),D=h.slice($,_),K=await this.fetch("storage/bulk",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:D})});await Q(K)}}}class V{fetcher;constructor(h){if(typeof h==="string")h={apiKey:h};this.fetcher=new X({apiKey:h.apiKey,baseUrl:h.baseUrl,basePath:h.basePath,retries:h.retries,retryDelayMs:h.retryDelayMs})}_storage;get storage(){return this._storage??=new j(this.fetcher)}}var A=V;
package/dist/index.d.ts CHANGED
@@ -107,11 +107,11 @@ declare class Storage$1 extends SDKModule {
107
107
  uploadStream(stream: ReadableStream, contentType: string, contentLength: number, metadata?: FileMetadata): Promise<UploadResponse>;
108
108
  /**
109
109
  * Deletes a media file from the storage.
110
- * @param mediaId The ID of the media file to be deleted.
110
+ * @param mediaId - The ID of the media to delete, or an array of IDs for batch deletion (max 100 per batch).
111
111
  * @returns {Promise<void>} A promise that resolves when the deletion is complete.
112
112
  * @throws {NoCloudAPIError} If the deletion fails.
113
113
  */
114
- delete(mediaId: string): Promise<void>;
114
+ delete(mediaId: string | string[]): Promise<void>;
115
115
  }
116
116
  export interface NoCloudOptions {
117
117
  /**
@@ -181,9 +181,39 @@ export declare class NoCloud {
181
181
  */
182
182
  get storage(): Storage$1;
183
183
  }
184
+ export declare enum NoCloudError {
185
+ INVALID_API_KEY = "INVALID_API_KEY",
186
+ BAD_REQUEST = "BAD_REQUEST",
187
+ RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED",
188
+ RESOURCE_NOT_FOUND = "RESOURCE_NOT_FOUND",
189
+ INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR",
190
+ UNKNOWN_ERROR = "UNKNOWN_ERROR"
191
+ }
184
192
  export declare class NoCloudAPIError extends Error {
185
193
  readonly status: number;
186
- constructor(message: string, status: number);
194
+ readonly code: NoCloudError;
195
+ constructor(message: string, status: number, code: NoCloudError);
196
+ /**
197
+ * Checks if the given object is a NoCloudAPIError with an optional specific error code.
198
+ * @param value - The value to check.
199
+ * @param code - Optional specific error code to match.
200
+ * @return True if the value is a NoCloudAPIError (and matches the code if provided), false otherwise.
201
+ */
202
+ static isError(value: unknown, code?: NoCloudError): value is NoCloudAPIError;
203
+ /**
204
+ * Creates a NoCloudAPIError instance based on the provided error code.
205
+ * @param code - The error code.
206
+ * @param message - The error message.
207
+ * @returns A NoCloudAPIError instance corresponding to the error code.
208
+ */
209
+ static fromCode(code: NoCloudError, message: string): NoCloudAPIError;
210
+ /**
211
+ * Creates a NoCloudAPIError instance based on the provided HTTP status code.
212
+ * @param status - The HTTP status code.
213
+ * @param message - The error message.
214
+ * @returns A NoCloudAPIError instance corresponding to the HTTP status code.
215
+ */
216
+ static fromStatus(status: number, message: string): NoCloudAPIError;
187
217
  }
188
218
 
189
219
  export {
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var H="https://api.nonefivem.com",v="/cloud";class O extends Error{status;constructor(h,F){super(h);this.status=F;this.name="NoCloudAPIError"}}function Z(h){return new Promise((F)=>setTimeout(F,h))}async function C(h,F=3,c=1000){let x;for(let f=0;f<=F;f++)try{return await h()}catch(K){if(x=K,f<F)await Z(c)}throw x}var j={iVBORw0KGgo:"image/png","/9j/":"image/jpeg",R0lGOD:"image/gif",UklGR:"image/webp",AAAA:"video/mp4",JVBERi0:"application/pdf",UEsDB:"application/zip",PD94bWw:"application/xml",PHN2Zw:"image/svg+xml"};function Q(h){let F=h.match(/^data:([^;,]+)/);if(F?.[1])return F[1];for(let[c,x]of Object.entries(j))if(h.startsWith(c))return x;return null}function V(h){let F=h.match(/^data:[^;,]+;base64,(.+)$/);if(F?.[1])return F[1];return h}function W(h){let F=atob(h),c=new Uint8Array(F.length);for(let x=0;x<F.length;x++)c[x]=F.charCodeAt(x);return c}function X(h){return h.split(";")[0]?.trim()??h}class D{baseUrl;basePath;apiKey;retryCount;retryDelayMs;constructor(h){if(this.apiKey=h.apiKey,this.baseUrl=(h.baseUrl||H).replace(/\/+$/,""),this.basePath=(h.basePath??v).replace(/^\/+|\/+$/g,""),this.retryCount=h.retries??3,this.retryDelayMs=h.retryDelayMs??1000,!this.apiKey)throw Error("API key is required")}buildUrl(h){let F=this.basePath?`${this.basePath}/${h}`:h;return`${this.baseUrl}/${F}`}fetch(h,F={}){let c=this.buildUrl(h);return C(()=>fetch(c,{...F,headers:{Authorization:`Bearer ${this.apiKey}`,...F.headers||{}}}),F.retries??this.retryCount,F.retryDelayMs??this.retryDelayMs)}}async function P(h){if(!h.ok){let F=await h.json().catch(()=>({}));throw new O(F.message||"Unknown error",h.status)}return await h.json()}class r{fetcher;constructor(h){this.fetcher=h}fetch(h,F){return this.fetcher.fetch(h,F)}}class U extends r{async generateSignedUrl(h,F,c){let x=new URLSearchParams;x.append("contentType",h),x.append("size",F.toString());let f=await this.fetch(`storage/signed-url?${x.toString()}`);return P(f)}getBodyInfo(h){if(typeof Blob<"u"&&h instanceof Blob)return{contentType:X(h.type)||"application/octet-stream",size:h.size,normalizedBody:h};if(typeof ArrayBuffer<"u"&&h instanceof ArrayBuffer)return{contentType:"application/octet-stream",size:h.byteLength,normalizedBody:h};if(typeof h==="string"){let F=Q(h);if(F){let x=V(h),f=W(x);return{contentType:F,size:f.byteLength,normalizedBody:new Blob([f.buffer])}}let c=new TextEncoder().encode(h);return{contentType:"text/plain",size:c.length,normalizedBody:new Blob([c.buffer])}}throw new O("Unsupported body type",400)}async upload(h,F){let{contentType:c,size:x,normalizedBody:f}=this.getBodyInfo(h),{url:K,mediaUrl:A,mediaId:_}=await this.generateSignedUrl(c,x,F),$=await fetch(K,{method:"PUT",headers:{"Content-Length":x.toString()},body:f});if(!$.ok){let Y=await $.text().catch(()=>$.statusText);throw new O(`Failed to upload file to R2: ${Y}`,$.status)}return{id:_,url:A}}async uploadStream(h,F,c,x){let{url:f,mediaUrl:K,mediaId:A}=await this.generateSignedUrl(F,c,x),_=await fetch(f,{method:"PUT",headers:{"Content-Length":c.toString()},body:h,duplex:"half"});if(!_.ok){let $=await _.text().catch(()=>_.statusText);throw new O(`Failed to upload stream to R2: ${$}`,_.status)}return{id:A,url:K}}async delete(h){let F=await this.fetch(`storage/${h}`,{method:"DELETE"});await P(F)}}class B{fetcher;constructor(h){if(typeof h==="string")h={apiKey:h};this.fetcher=new D({apiKey:h.apiKey,baseUrl:h.baseUrl,basePath:h.basePath,retries:h.retries,retryDelayMs:h.retryDelayMs})}_storage;get storage(){return this._storage??=new U(this.fetcher)}}var hh=B;export{hh as default,O as NoCloudAPIError,B as NoCloud};
1
+ var j="https://api.nonefivem.com",q="/cloud";var v;((D)=>{D.INVALID_API_KEY="INVALID_API_KEY";D.BAD_REQUEST="BAD_REQUEST";D.RATE_LIMIT_EXCEEDED="RATE_LIMIT_EXCEEDED";D.RESOURCE_NOT_FOUND="RESOURCE_NOT_FOUND";D.INTERNAL_SERVER_ERROR="INTERNAL_SERVER_ERROR";D.UNKNOWN_ERROR="UNKNOWN_ERROR"})(v||={});class O extends Error{status;code;constructor(h,f,x){super(h);this.status=f;this.code=x;this.name="NoCloudAPIError",this.code=x}static isError(h,f){if(!(h instanceof O))return!1;if(f&&h.code!==f)return!1;return!0}static fromCode(h,f){switch(h){case"BAD_REQUEST":return new O(f,400,h);case"INVALID_API_KEY":return new O(f,401,h);case"RATE_LIMIT_EXCEEDED":return new O(f,429,h);case"RESOURCE_NOT_FOUND":return new O(f,404,h);case"INTERNAL_SERVER_ERROR":case"UNKNOWN_ERROR":return new O(f,500,h);default:return new O(f,500,"INTERNAL_SERVER_ERROR")}}static fromStatus(h,f){switch(h){case 400:return new O(f,h,"BAD_REQUEST");case 401:return new O(f,h,"INVALID_API_KEY");case 429:return new O(f,h,"RATE_LIMIT_EXCEEDED");case 404:return new O(f,h,"RESOURCE_NOT_FOUND");case 500:return new O(f,h,"INTERNAL_SERVER_ERROR");default:return new O(f,h,"UNKNOWN_ERROR")}}}function H(h){return new Promise((f)=>setTimeout(f,h))}async function w(h,f=3,x=1000){let F;for(let $=0;$<=f;$++)try{return await h()}catch(_){if(F=_,$<f)await H(x)}throw F}var J={iVBORw0KGgo:"image/png","/9j/":"image/jpeg",R0lGOD:"image/gif",UklGR:"image/webp",AAAA:"video/mp4",JVBERi0:"application/pdf",UEsDB:"application/zip",PD94bWw:"application/xml",PHN2Zw:"image/svg+xml"};function G(h){let f=h.match(/^data:([^;,]+)/);if(f?.[1])return f[1];for(let[x,F]of Object.entries(J))if(h.startsWith(x))return F;return null}function L(h){let f=h.match(/^data:[^;,]+;base64,(.+)$/);if(f?.[1])return f[1];return h}function B(h){let f=atob(h),x=new Uint8Array(f.length);for(let F=0;F<f.length;F++)x[F]=f.charCodeAt(F);return x}function k(h){return h.split(";")[0]?.trim()??h}class V{baseUrl;basePath;apiKey;retryCount;retryDelayMs;constructor(h){if(this.apiKey=h.apiKey,this.baseUrl=(h.baseUrl||j).replace(/\/+$/,""),this.basePath=(h.basePath??q).replace(/^\/+|\/+$/g,""),this.retryCount=h.retries??3,this.retryDelayMs=h.retryDelayMs??1000,!this.apiKey)throw Error("API key is required")}buildUrl(h){let f=this.basePath?`${this.basePath}/${h}`:h;return`${this.baseUrl}/${f}`}fetch(h,f={}){let x=this.buildUrl(h);return w(()=>fetch(x,{...f,headers:{Authorization:`Bearer ${this.apiKey}`,...f.headers||{}}}),f.retries??this.retryCount,f.retryDelayMs??this.retryDelayMs)}}async function Q(h){if(!h.ok){let f=await h.json().catch(()=>({}));throw O.fromStatus(h.status,f.message||"Unknown error")}return await h.json()}class W{fetcher;constructor(h){this.fetcher=h}fetch(h,f){return this.fetcher.fetch(h,f)}}class X extends W{async generateSignedUrl(h,f,x){let F=new URLSearchParams;F.append("contentType",h),F.append("size",f.toString());let $=await this.fetch(`storage/signed-url?${F.toString()}`);return Q($)}getBodyInfo(h){if(typeof Blob<"u"&&h instanceof Blob)return{contentType:k(h.type)||"application/octet-stream",size:h.size,normalizedBody:h};if(typeof ArrayBuffer<"u"&&h instanceof ArrayBuffer)return{contentType:"application/octet-stream",size:h.byteLength,normalizedBody:h};if(typeof h==="string"){let f=G(h);if(f){let F=L(h),$=B(F);return{contentType:f,size:$.byteLength,normalizedBody:new Blob([$.buffer])}}let x=new TextEncoder().encode(h);return{contentType:"text/plain",size:x.length,normalizedBody:new Blob([x.buffer])}}throw O.fromStatus(400,"Unsupported body type")}async upload(h,f){let{contentType:x,size:F,normalizedBody:$}=this.getBodyInfo(h),{url:_,mediaUrl:D,mediaId:K}=await this.generateSignedUrl(x,F,f),U=await fetch(_,{method:"PUT",headers:{"Content-Length":F.toString()},body:$});if(!U.ok){let Z=await U.text().catch(()=>U.statusText);throw O.fromStatus(U.status,`Failed to upload file to R2: ${Z}`)}return{id:K,url:D}}async uploadStream(h,f,x,F){let{url:$,mediaUrl:_,mediaId:D}=await this.generateSignedUrl(f,x,F),K=await fetch($,{method:"PUT",headers:{"Content-Length":x.toString()},body:h,duplex:"half"});if(!K.ok){let U=await K.text().catch(()=>K.statusText);throw O.fromStatus(K.status,`Failed to upload stream to R2: ${U}`)}return{id:D,url:_}}async delete(h){if(!Array.isArray(h)){let F=await this.fetch(`storage/${h}`,{method:"DELETE"});await Q(F);return}if(h.length===0)return;if(h.length===1)return this.delete(h[0]);let f=100,x=Math.ceil(h.length/f);for(let F=0;F<x;F++){let $=F*f,_=Math.min($+f,h.length),D=h.slice($,_),K=await this.fetch("storage/bulk",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:D})});await Q(K)}}}class Y{fetcher;constructor(h){if(typeof h==="string")h={apiKey:h};this.fetcher=new V({apiKey:h.apiKey,baseUrl:h.baseUrl,basePath:h.basePath,retries:h.retries,retryDelayMs:h.retryDelayMs})}_storage;get storage(){return this._storage??=new X(this.fetcher)}}var fh=Y;export{fh as default,v as NoCloudError,O as NoCloudAPIError,Y as NoCloud};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocloud/sdk",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Official SDK for NoCloud services - file storage and more",
5
5
  "author": {
6
6
  "name": "sinanovicanes",