@mitway/sdk 0.7.2 → 0.8.0

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.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var postgrestJs=require('@supabase/postgrest-js'),socket_ioClient=require('socket.io-client');var c=class n extends Error{statusCode;error;nextActions;constructor(e,t,r,s){super(e),this.name="MitwayBaasError",this.statusCode=t,this.error=r,this.nextActions=s;}static fromApiError(e){return new n(e.message,e.statusCode,e.error,e.nextActions)}};var X=["authorization","x-api-key","cookie","set-cookie"],Z=["password","token","accesstoken","refreshtoken","authorization","secret","apikey","api_key","email","ssn","creditcard","credit_card"];function ee(n){let e={};for(let[t,r]of Object.entries(n))X.includes(t.toLowerCase())?e[t]="***REDACTED***":e[t]=r;return e}function C(n){if(n==null)return n;if(typeof n=="string")try{let e=JSON.parse(n);return C(e)}catch{return n}if(Array.isArray(n))return n.map(C);if(typeof n=="object"){let e={};for(let[t,r]of Object.entries(n))Z.includes(t.toLowerCase().replace(/[-_]/g,""))?e[t]="***REDACTED***":e[t]=C(r);return e}return n}function G(n){if(n==null)return "";if(typeof n=="string")try{return JSON.stringify(JSON.parse(n),null,2)}catch{return n}if(typeof FormData<"u"&&n instanceof FormData)return "[FormData]";try{return JSON.stringify(n,null,2)}catch{return "[Unserializable body]"}}var R=class{enabled;customLog;constructor(e){typeof e=="function"?(this.enabled=true,this.customLog=e):(this.enabled=!!e,this.customLog=null);}log(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.log(r,...t);}warn(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.warn(r,...t);}error(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.error(r,...t);}logRequest(e,t,r,s){if(!this.enabled)return;let i=[`\u2192 ${e} ${t}`];r&&Object.keys(r).length>0&&i.push(` Headers: ${JSON.stringify(ee(r))}`);let a=G(C(s));if(a){let o=a.length>1e3?a.slice(0,1e3)+"... [truncated]":a;i.push(` Body: ${o}`);}this.log(i.join(`
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var postgrestJs=require('@mitway/postgrest-js'),socket_ioClient=require('socket.io-client');var c=class n extends Error{statusCode;error;nextActions;constructor(e,t,r,s){super(e),this.name="MitwayBaasError",this.statusCode=t,this.error=r,this.nextActions=s;}static fromApiError(e){return new n(e.message,e.statusCode,e.error,e.nextActions)}};var X=["authorization","x-api-key","cookie","set-cookie"],Z=["password","token","accesstoken","refreshtoken","authorization","secret","apikey","api_key","email","ssn","creditcard","credit_card"];function ee(n){let e={};for(let[t,r]of Object.entries(n))X.includes(t.toLowerCase())?e[t]="***REDACTED***":e[t]=r;return e}function C(n){if(n==null)return n;if(typeof n=="string")try{let e=JSON.parse(n);return C(e)}catch{return n}if(Array.isArray(n))return n.map(C);if(typeof n=="object"){let e={};for(let[t,r]of Object.entries(n))Z.includes(t.toLowerCase().replace(/[-_]/g,""))?e[t]="***REDACTED***":e[t]=C(r);return e}return n}function G(n){if(n==null)return "";if(typeof n=="string")try{return JSON.stringify(JSON.parse(n),null,2)}catch{return n}if(typeof FormData<"u"&&n instanceof FormData)return "[FormData]";try{return JSON.stringify(n,null,2)}catch{return "[Unserializable body]"}}var R=class{enabled;customLog;constructor(e){typeof e=="function"?(this.enabled=true,this.customLog=e):(this.enabled=!!e,this.customLog=null);}log(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.log(r,...t);}warn(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.warn(r,...t);}error(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.error(r,...t);}logRequest(e,t,r,s){if(!this.enabled)return;let i=[`\u2192 ${e} ${t}`];r&&Object.keys(r).length>0&&i.push(` Headers: ${JSON.stringify(ee(r))}`);let a=G(C(s));if(a){let o=a.length>1e3?a.slice(0,1e3)+"... [truncated]":a;i.push(` Body: ${o}`);}this.log(i.join(`
2
2
  `));}logResponse(e,t,r,s,i){if(!this.enabled)return;let a=[`\u2190 ${e} ${t} ${r} (${s}ms)`],o=G(C(i));if(o){let g=o.length>1e3?o.slice(0,1e3)+"... [truncated]":o;a.push(` Body: ${g}`);}r>=400?this.error(a.join(`
3
3
  `)):this.log(a.join(`
4
4
  `));}};var K="mitway_baas_csrf_token",te="mitway_baas_session";function V(){return typeof localStorage<"u"?{getItem:e=>{try{return localStorage.getItem(e)}catch{return null}},setItem:(e,t)=>{try{localStorage.setItem(e,t);}catch{}},removeItem:e=>{try{localStorage.removeItem(e);}catch{}}}:{getItem:()=>null,setItem:()=>{},removeItem:()=>{}}}var re={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};function Y(){if(typeof document>"u")return null;let n=document.cookie.split(";").find(e=>e.trim().startsWith(`${K}=`));return n&&n.split("=")[1]||null}function F(n){if(typeof document>"u")return;let e=10080*60,t=typeof window<"u"&&window.location.protocol==="https:"?"; Secure":"";document.cookie=`${K}=${encodeURIComponent(n)}; path=/; max-age=${e}; SameSite=Lax${t}`;}function D(){if(typeof document>"u")return;let n=typeof window<"u"&&window.location.protocol==="https:"?"; Secure":"";document.cookie=`${K}=; path=/; max-age=0; SameSite=Lax${n}`;}var S=class{accessToken=null;refreshToken=null;user=null;persistSession;storageKey;storage;onTokenChange=null;constructor(e){this.persistSession=e?.persistSession??true,this.storageKey=e?.storageKey??te,this.storage=this.persistSession?e?.storage??V():re,(e?.multiTab??true)&&this.persistSession&&typeof window<"u"&&typeof localStorage<"u"&&window.addEventListener("storage",this.handleStorageEvent),this.restoreSession();}handleStorageEvent=e=>{e.key===this.storageKey&&(typeof localStorage<"u"&&e.storageArea!==localStorage||this.syncFromStorage(e.newValue));};syncFromStorage(e){let t=this.accessToken;if(e===null)this.accessToken=null,this.refreshToken=null,this.user=null;else try{let r=JSON.parse(e);if(!r.accessToken||!r.user)return;this.accessToken=r.accessToken,this.refreshToken=r.refreshToken??null,this.user=r.user;}catch{return}t!==this.accessToken&&this.onTokenChange&&this.onTokenChange();}saveSession(e){let t=e.accessToken!==this.accessToken;this.accessToken=e.accessToken,this.user=e.user,e.refreshToken!==void 0&&(this.refreshToken=e.refreshToken??null),this.persist(),t&&this.onTokenChange&&this.onTokenChange();}getSession(){return !this.accessToken||!this.user?null:{accessToken:this.accessToken,refreshToken:this.refreshToken??void 0,user:this.user}}getAccessToken(){return this.accessToken}setAccessToken(e){let t=e!==this.accessToken;this.accessToken=e,this.persist(),t&&this.onTokenChange&&this.onTokenChange();}getRefreshToken(){return this.refreshToken}setRefreshToken(e){this.refreshToken=e,this.persist();}getUser(){return this.user}setUser(e){this.user=e,this.persist();}clearSession(){let e=this.accessToken!==null;this.accessToken=null,this.refreshToken=null,this.user=null,this.removePersisted(),e&&this.onTokenChange&&this.onTokenChange();}restoreSession(){if(!this.persistSession)return false;try{let e=this.storage.getItem(this.storageKey);if(!e)return !1;let t=JSON.parse(e);return !t.accessToken||!t.user?!1:(this.accessToken=t.accessToken,this.refreshToken=t.refreshToken??null,this.user=t.user,!0)}catch{return false}}persist(){if(!this.persistSession||!this.accessToken||!this.user)return;let e={accessToken:this.accessToken,user:this.user};this.refreshToken&&(e.refreshToken=this.refreshToken),this.storage.setItem(this.storageKey,JSON.stringify(e));}removePersisted(){this.persistSession&&this.storage.removeItem(this.storageKey);}};function P(n){if(!n||typeof n!="object")return n;let e=n,t={...e},r=false;return "access_token"in e&&!("accessToken"in e)&&(t.accessToken=e.access_token,delete t.access_token,r=true),"csrf_token"in e&&!("csrfToken"in e)&&(t.csrfToken=e.csrf_token,delete t.csrf_token,r=true),"refresh_token"in e&&!("refreshToken"in e)&&(t.refreshToken=e.refresh_token,delete t.refresh_token,r=true),r?t:n}var se=new Set([500,502,503,504]),ne=new Set(["GET","HEAD","PUT","DELETE","OPTIONS"]),_=class{baseUrl;fetch;defaultHeaders;anonKey;userToken=null;logger;autoRefreshToken=true;isRefreshing=false;refreshPromise=null;tokenManager;refreshToken=null;timeout;retryCount;retryDelay;constructor(e,t,r){if(this.baseUrl=e.baseUrl||"http://localhost:7130",this.autoRefreshToken=e.autoRefreshToken??true,this.fetch=e.fetch||(globalThis.fetch?globalThis.fetch.bind(globalThis):void 0),this.anonKey=e.anonKey,this.defaultHeaders={...e.headers},this.tokenManager=t??new S,this.logger=r||new R(false),this.timeout=e.timeout??3e4,this.retryCount=e.retryCount??3,this.retryDelay=e.retryDelay??500,!this.fetch)throw new Error("Fetch is not available. Provide a fetch implementation in the SDK config.")}buildUrl(e,t){let r=new URL(e,this.baseUrl);return t&&Object.entries(t).forEach(([s,i])=>{if(s==="select"){let a=i.replace(/\s+/g," ").trim();a=a.replace(/\s*\(\s*/g,"(").replace(/\s*\)\s*/g,")").replace(/\(\s+/g,"(").replace(/\s+\)/g,")").replace(/,\s+(?=[^()]*\))/g,","),r.searchParams.append(s,a);}else r.searchParams.append(s,i);}),r.toString()}isRetryableStatus(e){return se.has(e)}computeRetryDelay(e){let r=this.retryDelay*Math.pow(2,e-1)*(.85+Math.random()*.3);return Math.round(r)}async handleRequest(e,t,r={}){let{params:s,headers:i={},body:a,signal:o,...g}=r,p=this.buildUrl(t,s),E=Date.now(),T=ne.has(e.toUpperCase())||r.idempotent===true?this.retryCount:0,b={...this.defaultHeaders},J=this.userToken||this.anonKey;J&&(b.Authorization=`Bearer ${J}`);let M;a!==void 0&&(typeof FormData<"u"&&a instanceof FormData?M=a:(e!=="GET"&&(b["Content-Type"]="application/json;charset=UTF-8"),M=JSON.stringify(a))),i instanceof Headers?i.forEach((f,h)=>{b[h]=f;}):Array.isArray(i)?i.forEach(([f,h])=>{b[f]=h;}):Object.assign(b,i),this.logger.logRequest(e,p,b,M);let H;for(let f=0;f<=T;f++){if(f>0){let l=this.computeRetryDelay(f);if(this.logger.warn(`Retry ${f}/${T} for ${e} ${p} in ${l}ms`),o?.aborted)throw o.reason;await new Promise((u,q)=>{let y=()=>{clearTimeout(Q),q(o.reason);},Q=setTimeout(()=>{o&&o.removeEventListener("abort",y),u();},l);o&&o.addEventListener("abort",y,{once:true});});}let h,m;if((this.timeout>0||o)&&(h=new AbortController,this.timeout>0&&(m=setTimeout(()=>h.abort(),this.timeout)),o))if(o.aborted)h.abort(o.reason);else {let l=()=>h.abort(o.reason);o.addEventListener("abort",l,{once:true}),h.signal.addEventListener("abort",()=>{o.removeEventListener("abort",l);},{once:true});}try{let l=await this.fetch(p,{method:e,headers:b,body:M,...g,...h?{signal:h.signal}:{}});if(this.isRetryableStatus(l.status)&&f<T){m!==void 0&&clearTimeout(m),await l.body?.cancel(),H=new c(`Server error: ${l.status} ${l.statusText}`,l.status,"SERVER_ERROR");continue}if(l.status===204){m!==void 0&&clearTimeout(m);return}let u,q=l.headers.get("content-type");try{q?.includes("json")?u=await l.json():u=await l.text();}catch(y){throw m!==void 0&&clearTimeout(m),new c(`Failed to parse response body: ${y?.message||"Unknown error"}`,l.status,l.ok?"PARSE_ERROR":"REQUEST_FAILED")}if(m!==void 0&&clearTimeout(m),!l.ok){if(this.logger.logResponse(e,p,l.status,Date.now()-E,u),u&&typeof u=="object"&&"error"in u&&u.error!==null&&typeof u.error=="object"){let y=u.error;throw new c(y.message||l.statusText||"Request failed",y.statusCode||l.status,y.code||y.error||"REQUEST_FAILED",y.nextActions)}throw new c(`Request failed: ${l.statusText}`,l.status,"REQUEST_FAILED")}return this.logger.logResponse(e,p,l.status,Date.now()-E,u),u&&typeof u=="object"&&"data"in u&&"error"in u&&u.error===null?u.data:u}catch(l){if(m!==void 0&&clearTimeout(m),l?.name==="AbortError")throw h&&h.signal.aborted&&this.timeout>0&&!o?.aborted?new c(`Request timed out after ${this.timeout}ms`,408,"REQUEST_TIMEOUT"):l;if(l instanceof c)throw l;if(f<T){H=l;continue}throw new c(`Network request failed: ${l?.message||"Unknown error"}`,0,"NETWORK_ERROR")}}throw H||new c("Request failed after all retry attempts",0,"NETWORK_ERROR")}async request(e,t,r={}){try{return await this.handleRequest(e,t,{...r})}catch(s){if(s instanceof c&&s.statusCode===401&&s.error==="INVALID_TOKEN"&&this.autoRefreshToken)try{let i=await this.handleTokenRefresh();return this.setAuthToken(i.accessToken),this.tokenManager.saveSession(i),i.csrfToken&&F(i.csrfToken),i.refreshToken&&this.setRefreshToken(i.refreshToken),await this.handleRequest(e,t,{...r})}catch(i){throw this.tokenManager.clearSession(),this.userToken=null,this.refreshToken=null,D(),i}throw s}}async rawFetch(e,t={}){let r=this.buildUrl(e),s=new Headers(t.headers??{});for(let[i,a]of Object.entries(this.defaultHeaders))s.has(i)||s.set(i,a);if(!s.has("Authorization")){let i=this.userToken??this.anonKey;i&&s.set("Authorization",`Bearer ${i}`);}return this.fetch(r,{...t,headers:s})}get(e,t){return this.request("GET",e,t)}post(e,t,r){return this.request("POST",e,{...r,body:t})}put(e,t,r){return this.request("PUT",e,{...r,body:t})}patch(e,t,r){return this.request("PATCH",e,{...r,body:t})}delete(e,t){return this.request("DELETE",e,t)}setAuthToken(e){this.userToken=e;}setRefreshToken(e){this.refreshToken=e;}getHeaders(){let e={...this.defaultHeaders},t=this.userToken||this.anonKey;return t&&(e.Authorization=`Bearer ${t}`),e}async handleTokenRefresh(){return this.isRefreshing?this.refreshPromise:(this.isRefreshing=true,this.refreshPromise=(async()=>{try{let e=Y(),t=this.refreshToken?{refreshToken:this.refreshToken}:void 0,r=await this.handleRequest("POST","/api/auth/refresh",{body:t,headers:e?{"X-CSRF-Token":e}:{},credentials:"include"});return P(r)}finally{this.isRefreshing=false,this.refreshPromise=null;}})(),this.refreshPromise)}};function w(n,e){return n instanceof c?{data:null,error:n}:{data:null,error:new c(n instanceof Error?n.message:e,500,"AUTH_ERROR")}}var A=class{constructor(e,t){this.http=e;this.tokenManager=t;this.tokenManager.onTokenChange=()=>this._emitFromTokenChange();let r=this.tokenManager.getSession();if(r){this.http.setAuthToken(r.accessToken);let s=this.tokenManager.getRefreshToken();s&&this.http.setRefreshToken(s),this.lastEmittedUserId=r.user.id,this.lastEmittedAccessToken=r.accessToken;}}http;tokenManager;stateChangeListeners=new Set;lastEmittedUserId=null;lastEmittedAccessToken=null;onAuthStateChange(e){return this.stateChangeListeners.add(e),{unsubscribe:()=>{this.stateChangeListeners.delete(e);}}}emit(e,t){for(let r of this.stateChangeListeners)try{r(e,t);}catch{}}_emitFromTokenChange(){let e=this.tokenManager.getSession(),t=this.lastEmittedUserId,r=this.lastEmittedAccessToken;if(!e){t!==null&&(this.lastEmittedUserId=null,this.lastEmittedAccessToken=null,this.emit("SIGNED_OUT",null));return}let s=e.user.id;if(t===null){this.lastEmittedUserId=s,this.lastEmittedAccessToken=e.accessToken,this.emit("SIGNED_IN",e);return}if(t!==s){this.lastEmittedUserId=null,this.lastEmittedAccessToken=null,this.emit("SIGNED_OUT",null),this.lastEmittedUserId=s,this.lastEmittedAccessToken=e.accessToken,this.emit("SIGNED_IN",e);return}r!==e.accessToken&&(this.lastEmittedAccessToken=e.accessToken,this.emit("TOKEN_REFRESHED",e));}saveSessionFromResponse(e){let t={accessToken:e.accessToken,refreshToken:e.refreshToken,user:e.user};e.csrfToken&&F(e.csrfToken),this.tokenManager.saveSession(t),this.http.setAuthToken(e.accessToken),this.http.setRefreshToken(e.refreshToken??null);}async signUp(e){try{let t=await this.http.post("/api/auth/register",e,{credentials:"include"}),r=P(t);return r?.accessToken&&r.user&&this.saveSessionFromResponse(r),{data:r,error:null}}catch(t){return w(t,"Sign up failed")}}async signInWithPassword(e){try{let t=await this.http.post("/api/auth/login",e,{credentials:"include"}),r=P(t);return r?.accessToken&&r.user&&this.saveSessionFromResponse(r),{data:r,error:null}}catch(t){return w(t,"Sign in failed")}}async signOut(){try{try{await this.http.post("/api/auth/logout",void 0,{credentials:"include"});}catch{}return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),D(),{error:null}}catch{return {error:new c("Failed to sign out",500,"SIGNOUT_ERROR")}}}async refreshSession(){try{let e=await this.http.handleTokenRefresh();return e?.accessToken&&e.user&&this.saveSessionFromResponse(e),{data:e,error:null}}catch(e){return w(e,"Session refresh failed")}}async initialize(){let e=this.tokenManager.getSession();if(!e)return this.emit("INITIAL_SESSION",null),{data:null,error:new c("No persisted session",0,"NO_SESSION")};try{let t=await this.http.get("/api/auth/sessions/current");if(t?.user){this.tokenManager.setUser(t.user);let r=this.tokenManager.getSession();return this.emit("INITIAL_SESSION",r),{data:{user:t.user,accessToken:e.accessToken},error:null}}return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),this.emit("INITIAL_SESSION",null),{data:null,error:new c("Invalid session",401,"INVALID_SESSION")}}catch(t){return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),this.emit("INITIAL_SESSION",null),w(t,"Session restore failed")}}getSession(){return this.tokenManager.getSession()}getUser(){return this.tokenManager.getUser()}async getCurrentUser(){try{let e=await this.http.get("/api/auth/sessions/current");if(e?.user){let t={accessToken:this.tokenManager.getSession()?.accessToken??"",user:e.user};this.tokenManager.saveSession(t);}return {data:e,error:null}}catch(e){return w(e,"Failed to get current user")}}async getProfile(e){try{return {data:await this.http.get(`/api/auth/profiles/${encodeURIComponent(e)}`),error:null}}catch(t){return w(t,"Failed to get profile")}}async setProfile(e){try{let t=await this.http.patch("/api/auth/profiles/current",{profile:e}),r=this.tokenManager.getUser();if(t?.profile&&r){let s={...r,profile:t.profile};this.tokenManager.setUser(s),this.emit("USER_UPDATED",this.tokenManager.getSession());}return {data:t,error:null}}catch(t){return w(t,"Failed to update profile")}}};function oe(n,e,t){return async(r,s)=>{let i=typeof r=="string"?r:r.toString(),a=new URL(i),o=a.pathname.startsWith("/")?a.pathname.slice(1):a.pathname,g=o.match(/^rpc\/(.+)$/),p=g?`/api/database/rpc/${g[1]}`:`/api/database/records/${o}`,E=`${n.baseUrl}${p}${a.search}`,x=new Headers(s?.headers);if(!x.has("Authorization")){let T=e.getAccessToken()??t;T&&x.set("Authorization",`Bearer ${T}`);}return fetch(E,{...s,headers:x})}}var O=class{postgrest;httpClient;constructor(e,t,r){this.httpClient=e,this.postgrest=new postgrestJs.PostgrestClient("http://dummy",{fetch:oe(e,t,r),headers:{}});}from(e){if(!e||typeof e!="string")throw new c("Database.from(table) requires a non-empty string",400,"INVALID_TABLE_NAME");return this.postgrest.from(e)}rpc(e,t,r){return this.postgrest.rpc(e,t,r)}getUrl(){return this.httpClient.baseUrl}};var ce=2e4;function z(n,e){let t=new Error(e);return t.code=n,t}var le=1e4,N=class{constructor(e,t,r={}){this.topic=e;this.realtime=t;this.options=r;}topic;realtime;bindings=[];state="closed";statusCallback=null;presence={};trackedState=null;presenceHeartbeat=null;lastBroadcastTimestamp=null;options;get isPrivate(){return this.options.config?.private===true}get presenceKey(){return this.options.config?.presence?.key}_state(){return this.state}async _rejoinAfterReconnect(){if(this.state!=="closed"){for(let e of this.bindings)e.type==="postgres_changes"&&(e.subscriptionId=void 0);this.state="joining";try{if(await this.registerAllBindings(),this.trackedState){let e=this.realtime._getSocket(),t=this.presenceKey;e?.emit("realtime:presence:track",t!==void 0?{channel:this.topic,state:this.trackedState,key:t}:{channel:this.topic,state:this.trackedState});}this.lastBroadcastTimestamp&&this.bindings.some(e=>e.type==="broadcast")&&this.replay({since:this.lastBroadcastTimestamp}).catch(()=>{}),this.state="joined",this.statusCallback?.("SUBSCRIBED");}catch(e){this.state="errored",this.statusCallback?.("CHANNEL_ERROR",z("REJOIN_FAILED",e instanceof Error?e.message:String(e)));}}}on(e,t,r){return e==="postgres_changes"?this.bindings.push({type:"postgres_changes",filter:t,callback:r}):e==="broadcast"?this.bindings.push({type:"broadcast",filter:t,callback:r}):this.bindings.push({type:"presence",filter:t,callback:r}),this}async track(e){let t=this.realtime._getSocket();if(!t)throw new c("Socket not connected",503,"NOT_CONNECTED");this.trackedState=e;let r=this.presenceKey;t.emit("realtime:presence:track",r!==void 0?{channel:this.topic,state:e,key:r}:{channel:this.topic,state:e}),this.presenceHeartbeat||(this.presenceHeartbeat=setInterval(()=>{let i=this.realtime._getSocket();i&&this.trackedState&&i.emit("realtime:presence:track",r!==void 0?{channel:this.topic,state:this.trackedState,key:r}:{channel:this.topic,state:this.trackedState});},ce),this.presenceHeartbeat.unref?.());}untrack(){this.trackedState=null,this.presenceHeartbeat&&(clearInterval(this.presenceHeartbeat),this.presenceHeartbeat=null),this.realtime._getSocket()?.emit("realtime:presence:untrack",{channel:this.topic});}presenceState(){return this.presence}subscribe(e){return this.statusCallback=e??null,this.state==="joining"||this.state==="joined"?this:(this.state="joining",this.realtime.connect().then(async()=>{try{await this.registerAllBindings(),this.state="joined",this.statusCallback?.("SUBSCRIBED");}catch(t){this.state="errored";let r=t instanceof Error?t.message:String(t);this.statusCallback?.("CHANNEL_ERROR",z("SUBSCRIBE_FAILED",r));}},t=>{this.state="errored",this.statusCallback?.("CHANNEL_ERROR",z("CONNECT_FAILED",t.message));}),this)}async unsubscribe(){if(this.state==="closed")return;let e=this.realtime._getSocket();if(this.presenceHeartbeat&&(clearInterval(this.presenceHeartbeat),this.presenceHeartbeat=null),!e){this.trackedState=null,this.state="closed";return}this.trackedState&&(e.emit("realtime:presence:untrack",{channel:this.topic}),this.trackedState=null);let t=this.bindings.filter(r=>r.type==="postgres_changes");for(let r of t)r.subscriptionId&&(e.emit("realtime:postgres_changes:unsubscribe",{subscription_id:r.subscriptionId}),r.subscriptionId=void 0);this.bindings.some(r=>r.type==="broadcast"||r.type==="presence")&&e.emit("realtime:unsubscribe",{channel:this.topic}),this.realtime._detachChannel(this),this.state="closed",this.statusCallback?.("CLOSED");}async send(e){if(e.type!=="broadcast")throw new c('Only "broadcast" sends are supported \u2014 DB changes flow via your DB writes, not channel.send()',400,"UNSUPPORTED_SEND_TYPE");if(new Set(["postgres_changes","presence_state","presence_join","presence_leave"]).has(e.event))throw new c(`"${e.event}" is a reserved event name \u2014 pick a different name for broadcast events`,400,"RESERVED_EVENT_NAME");let r=this.realtime._getSocket();if(!r)throw new c("Socket not connected",503,"NOT_CONNECTED");let s=this.options.config?.broadcast?.self,i={channel:this.topic,event:e.event,payload:e.payload};return s===false&&(i.self=false),await new Promise(a=>{r.emit("realtime:publish",i,o=>{a(o);});})}async replay(e){let t=this.realtime._getSocket();if(!t)throw new c("Socket not connected",503,"NOT_CONNECTED");t.emit("realtime:broadcast:replay",{channel:this.topic,since:e.since,limit:e.limit,private:this.isPrivate});}_dispatch(e,t){if(e==="postgres_changes"){let s=t;for(let i of this.bindings)if(!(i.type!=="postgres_changes"||!i.subscriptionId||!s.ids.includes(i.subscriptionId)||!(i.filter.event==="*"||i.filter.event===s.data.eventType)))try{i.callback(s.data);}catch{}return}if(e==="presence_state"||e==="presence_join"||e==="presence_leave"){let s=t;if(s.channel!==this.topic)return;if(e==="presence_state"&&s.state)this.presence={...s.state},this.firePresence({event:"sync",state:this.presence});else if(e==="presence_join"&&s.joins)Object.assign(this.presence,s.joins),this.firePresence({event:"join",joins:s.joins});else if(e==="presence_leave"&&s.leaves){for(let i of Object.keys(s.leaves))delete this.presence[i];this.firePresence({event:"leave",leaves:s.leaves});}return}let r=t.meta;r?.timestamp&&(!this.lastBroadcastTimestamp||r.timestamp>this.lastBroadcastTimestamp)&&(this.lastBroadcastTimestamp=r.timestamp);for(let s of this.bindings){if(s.type!=="broadcast"||s.filter.event!==e)continue;let{meta:i,...a}=t;try{s.callback({type:"broadcast",event:e,payload:a});}catch{}}}firePresence(e){for(let t of this.bindings)if(t.type==="presence"&&t.filter.event===e.event)try{e.event==="sync"?t.callback():(e.event,t.callback(e));}catch{}}async registerAllBindings(){let e=this.realtime._getSocket();if(!e)throw new Error("Socket not available");this.bindings.some(s=>s.type==="broadcast"||s.type==="presence")&&await new Promise((s,i)=>{e.emit("realtime:subscribe",{channel:this.topic,private:this.isPrivate},a=>{a.status==="ok"?s():i(new Error(a.error?.message??"subscribe failed"));});});let r=this.bindings.filter(s=>s.type==="postgres_changes");await Promise.all(r.map(s=>new Promise((i,a)=>{e.emit("realtime:postgres_changes:subscribe",{event:s.filter.event,schema:s.filter.schema??"public",table:s.filter.table,filter:s.filter.filter},o=>{o.status==="ok"&&o.subscription_id?(s.subscriptionId=o.subscription_id,i()):a(new Error(o.error?.message??"postgres_changes subscribe failed"));});})));}},B=class{socket=null;baseUrl;options;anonKey;tokenManager;channels=new Map;connecting=null;firstConnected=false;constructor(e,t,r,s={}){this.baseUrl=e,this.tokenManager=t,this.anonKey=r,this.options=s;}get isConnected(){return this.socket?.connected===true}get socketId(){return this.socket?.id}channel(e,t){let r=this.channels.get(e);if(r)return r;let s=new N(e,this,t);return this.channels.set(e,s),s}connect(){return this.isConnected?Promise.resolve():this.connecting?this.connecting:(this.connecting=this.openSocket(),this.connecting)}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null,this.firstConnected=false);}_getSocket(){return this.socket}_detachChannel(e){this.channels.delete(e.topic);}openSocket(){let e=this.tokenManager.getAccessToken()??this.anonKey;if(!e){let s=new c("Realtime requires an access token or anonKey",401,"AUTH_INVALID_API_KEY");return this.connecting=null,Promise.reject(s)}let t=this.options.timeoutMs??le,r=socket_ioClient.io(this.baseUrl,{path:this.options.path,transports:this.options.transports??["websocket"],auth:{token:e,...this.options.extraAuth??{}},reconnection:true,timeout:t});return this.socket=r,r.onAny((s,...i)=>this.dispatch(s,i)),r.on("connect",()=>{if(this.firstConnected)for(let s of this.channels.values()){let i=s._state();(i==="joined"||i==="errored")&&s._rejoinAfterReconnect();}}),new Promise((s,i)=>{let a=setTimeout(()=>{r.off("connect",g),r.off("connect_error",p),this.connecting=null,i(new c(`Realtime connection timeout after ${t}ms`,408,"CONNECTION_TIMEOUT"));},t),o=()=>{clearTimeout(a),r.off("connect",g),r.off("connect_error",p);},g=()=>{o(),this.connecting=null,this.firstConnected=true,s();},p=E=>{o(),this.connecting=null,i(new c(E.message,0,"CONNECTION_FAILED"));};r.once("connect",g),r.once("connect_error",p);})}dispatch(e,t){if(e==="postgres_changes"){let s=t[0]??{};this.channels.forEach(i=>i._dispatch("postgres_changes",s));return}if(e==="connect"||e==="disconnect"||e==="connect_error"||e==="error"||e==="realtime:error"||e==="realtime:shutdown")return;let r=t[0]??{};this.channels.forEach(s=>s._dispatch(e,r));}};function L(n){return {id:n.id,name:n.name,public:n.public,fileSizeLimitBytes:n.file_size_limit_bytes,allowedMimeTypes:n.allowed_mime_types,createdAt:n.created_at,updatedAt:n.updated_at}}function j(n,e){return {id:n.id,bucket:e,key:n.key,size:n.size,mimeType:n.mime_type,etag:n.etag,cacheControl:n.cache_control,contentDisposition:n.content_disposition,uploadedBy:n.uploaded_by,uploadedAt:n.uploaded_at,updatedAt:n.updated_at}}function ue(n){return {defaultFileSizeLimitBytes:n.default_file_size_limit_bytes,maxFileSizeLimitBytes:n.max_file_size_limit_bytes,tenantStorageQuotaBytes:n.tenant_storage_quota_bytes,reservedSpaceBytes:n.reserved_space_bytes,signedUrlDefaultTtlSec:n.signed_url_default_ttl_sec,signedUrlMaxTtlSec:n.signed_url_max_ttl_sec}}function de(n){return n.split("/").map(encodeURIComponent).join("/")}function d(n,e){return n instanceof c?{data:null,error:n}:{data:null,error:new c(n instanceof Error?n.message:e,0,"STORAGE_ERROR")}}async function W(n){let e="STORAGE_ERROR",t=`HTTP ${n.status}`;try{let r=await n.json();r&&r.error&&(e=r.error.code??e,t=r.error.message??t);}catch{}return new c(t,n.status,e)}var $=class{constructor(e,t){this.http=e;this.bucketName=t;}http;bucketName;bucketBase(){return `/api/storage/buckets/${encodeURIComponent(this.bucketName)}`}objectPath(e){return `${this.bucketBase()}/objects/${de(e)}`}async upload(e,t,r={}){try{let s=r.upsert?"PUT":"POST",i={"Content-Type":r.contentType??"application/octet-stream"};r.cacheControl&&(i["Cache-Control"]=r.cacheControl),r.contentDisposition&&(i["Content-Disposition"]=r.contentDisposition);let a=await this.http.rawFetch(this.objectPath(e),{method:s,headers:i,body:t,signal:r.abortSignal});if(!a.ok)return {data:null,error:await W(a)};let o=await a.json();return o.error||!o.data?{data:null,error:new c(o.error?.message??"Upload failed",a.status,o.error?.code??"STORAGE_ERROR")}:{data:j(o.data,this.bucketName),error:null}}catch(s){return d(s,"Upload failed")}}async download(e,t={}){try{let r={};t.range&&(r.Range=`bytes=${t.range.start}-${t.range.end}`);let s=await this.http.rawFetch(this.objectPath(e),{method:"GET",headers:r,signal:t.abortSignal});return s.ok?{data:await s.blob(),error:null}:{data:null,error:await W(s)}}catch(r){return d(r,"Download failed")}}async getStream(e,t={}){try{let r={};t.range&&(r.Range=`bytes=${t.range.start}-${t.range.end}`);let s=await this.http.rawFetch(this.objectPath(e),{method:"GET",headers:r,signal:t.abortSignal});return s.ok?s.body?{data:s.body,error:null}:{data:null,error:new c("Response body is not a stream",s.status,"STORAGE_ERROR")}:{data:null,error:await W(s)}}catch(r){return d(r,"Download failed")}}async remove(e){try{let t=await Promise.allSettled(e.map(i=>this.http.rawFetch(this.objectPath(i),{method:"DELETE"}))),r=[],s=[];for(let i=0;i<e.length;i++){let a=e[i],o=t[i];if(o.status==="fulfilled"&&o.value.ok)r.push(a);else if(o.status==="fulfilled")s.push(`${a}: HTTP ${o.value.status}`);else {let g=o.reason instanceof Error?o.reason.message:String(o.reason);s.push(`${a}: ${g}`);}}return s.length>0?{data:null,error:new c(`Failed to delete some objects: ${s.join("; ")}`,0,"STORAGE_ERROR")}:{data:{removed:r},error:null}}catch(t){return d(t,"Delete failed")}}async list(e={}){try{let t={};return e.prefix!==void 0&&(t.prefix=e.prefix),e.limit!==void 0&&(t.limit=String(e.limit)),e.startAfter!==void 0&&(t.start_after=e.startAfter),{data:(await this.http.get(`${this.bucketBase()}/objects`,{params:t})).map(s=>j(s,this.bucketName)),error:null}}catch(t){return d(t,"List failed")}}async copy(e,t,r){try{let s=await this.http.post(`${this.objectPath(e)}/copy`,{dest_bucket:r??this.bucketName,dest_key:t});return {data:j(s,r??this.bucketName),error:null}}catch(s){return d(s,"Copy failed")}}async move(e,t,r){try{let s=await this.http.post(`${this.objectPath(e)}/move`,{dest_bucket:r??this.bucketName,dest_key:t});return {data:j(s,r??this.bucketName),error:null}}catch(s){return d(s,"Move failed")}}async createSignedUrl(e,t={}){try{let r={};t.expiresIn!==void 0&&(r.expires_in=t.expiresIn);let s=await this.http.post(`${this.objectPath(e)}/sign`,r);return {data:{url:s.url,token:s.token,expiresAt:s.expiresAt},error:null}}catch(r){return d(r,"Sign failed")}}getPublicUrl(e){return {data:{url:`${this.http.baseUrl.replace(/\/$/,"")}${this.objectPath(e)}`}}}},I=class{constructor(e){this.http=e;}http;from(e){return new $(this.http,e)}async listBuckets(){try{return {data:(await this.http.get("/api/storage/buckets")).map(L),error:null}}catch(e){return d(e,"listBuckets failed")}}async getBucket(e){try{let t=await this.http.get(`/api/storage/buckets/${encodeURIComponent(e)}`);return {data:L(t),error:null}}catch(t){return d(t,"getBucket failed")}}async createBucket(e,t={}){try{let r={name:e};t.public!==void 0&&(r.public=t.public),t.fileSizeLimitBytes!==void 0&&(r.file_size_limit_bytes=t.fileSizeLimitBytes),t.allowedMimeTypes!==void 0&&(r.allowed_mime_types=t.allowedMimeTypes);let s=await this.http.post("/api/storage/buckets",r);return {data:L(s),error:null}}catch(r){return d(r,"createBucket failed")}}async updateBucket(e,t){try{let r={};t.public!==void 0&&(r.public=t.public),t.fileSizeLimitBytes!==void 0&&(r.file_size_limit_bytes=t.fileSizeLimitBytes),t.allowedMimeTypes!==void 0&&(r.allowed_mime_types=t.allowedMimeTypes);let s=await this.http.patch(`/api/storage/buckets/${encodeURIComponent(e)}`,r);return {data:L(s),error:null}}catch(r){return d(r,"updateBucket failed")}}async deleteBucket(e){try{return await this.http.delete(`/api/storage/buckets/${encodeURIComponent(e)}`),{data:null,error:null}}catch(t){return d(t,"deleteBucket failed")}}async emptyBucket(e){try{return {data:await this.http.post(`/api/storage/buckets/${encodeURIComponent(e)}/empty`,{}),error:null}}catch(t){return d(t,"emptyBucket failed")}}async getConfig(){try{let e=await this.http.get("/api/storage/config");return {data:ue(e),error:null}}catch(e){return d(e,"getConfig failed")}}};function he(n){return {key:n.key,digest:n.digest,updatedAt:n.updated_at}}function k(n,e){return n instanceof c?{data:null,error:n}:{data:null,error:new c(n instanceof Error?n.message:e,0,"FUNCTIONS_ERROR")}}function ge(n){return typeof n=="object"&&n!==null&&!ArrayBuffer.isView(n)&&!(n instanceof Blob)&&!(n instanceof FormData)&&!(n instanceof URLSearchParams)&&!(n instanceof ReadableStream)}var U=class{constructor(e){this.http=e;}http;async list(){try{return {data:await this.http.get("/api/functions"),error:null}}catch(e){return k(e,"list failed")}}async get(e){try{return {data:await this.http.get(`/api/functions/${encodeURIComponent(e)}`),error:null}}catch(t){return k(t,"get failed")}}async create(e){try{return {data:await this.http.post("/api/functions",e),error:null}}catch(t){return k(t,"create failed")}}async update(e,t){try{return {data:await this.http.put(`/api/functions/${encodeURIComponent(e)}`,t),error:null}}catch(r){return k(r,"update failed")}}async remove(e){try{return await this.http.delete(`/api/functions/${encodeURIComponent(e)}`),{data:{deleted:!0},error:null}}catch(t){return k(t,"remove failed")}}async invoke(e,t={}){try{let r=t.method??"POST",s={...t.headers},i;return t.body!==void 0&&t.body!==null&&(ge(t.body)?(i=JSON.stringify(t.body),s["Content-Type"]||(s["Content-Type"]="application/json")):i=t.body),{data:await this.http.rawFetch(`/api/invoke/${encodeURIComponent(e)}`,{method:r,headers:s,body:i}),error:null}}catch(r){return k(r,"invoke failed")}}async listSecrets(){try{return {data:(await this.http.get("/api/functions/secrets")).secrets.map(he),error:null}}catch(e){return k(e,"listSecrets failed")}}async setSecrets(e){try{return await this.http.put("/api/functions/secrets",{secrets:e}),{data:{saved:!0},error:null}}catch(t){return k(t,"setSecrets failed")}}async deleteSecret(e){try{return await this.http.delete(`/api/functions/secrets/${encodeURIComponent(e)}`),{data:{deleted:!0},error:null}}catch(t){return k(t,"deleteSecret failed")}}};var v=class{http;tokenManager;auth;database;realtime;storage;functions;constructor(e={}){let t=new R(e.debug);this.tokenManager=new S({persistSession:e.persistSession,storageKey:e.storageKey,storage:e.storage,multiTab:e.multiTab}),this.http=new _(e,this.tokenManager,t),this.auth=new A(this.http,this.tokenManager),this.database=new O(this.http,this.tokenManager,e.anonKey),this.realtime=new B(this.http.baseUrl,this.tokenManager,e.anonKey,e.realtime),this.storage=new I(this.http),this.functions=new U(this.http);}getHttpClient(){return this.http}};function Qe(n){return new v(n)}var Xe=v;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Socket } from 'socket.io-client';
2
- import * as _supabase_postgrest_js from '@supabase/postgrest-js';
2
+ import * as _mitway_postgrest_js from '@mitway/postgrest-js';
3
3
 
4
4
  /**
5
5
  * User shape returned by the MITWAY-BaaS auth endpoints.
@@ -471,11 +471,10 @@ declare class Realtime {
471
471
 
472
472
  interface MitwayBaasConfig {
473
473
  /**
474
- * Base URL of the MITWAY-BaaS backend. In production this is typically
475
- * `https://{cliente}.api.dev.nttmitway.com` (or the equivalent pro
476
- * domain). The SDK routes all traffic — auth, database (via the
477
- * backend's PostgREST proxy at `/api/database/records/*`), and future
478
- * storage/functions — through this one URL.
474
+ * Base URL of the MITWAY-BaaS backend the SDK should talk to. The SDK
475
+ * routes every request — auth, database (via the backend's PostgREST
476
+ * proxy at `/api/database/records/*`), storage, realtime (via
477
+ * `/socket.io/`) and functions through this single URL.
479
478
  *
480
479
  * @default "http://localhost:7130"
481
480
  */
@@ -887,7 +886,7 @@ declare class Database {
887
886
  * .select()
888
887
  * .single();
889
888
  */
890
- from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
889
+ from(table: string): _mitway_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
891
890
  /**
892
891
  * Call a PostgreSQL stored function (RPC).
893
892
  *
@@ -899,7 +898,7 @@ declare class Database {
899
898
  head?: boolean;
900
899
  get?: boolean;
901
900
  count?: 'exact' | 'planned' | 'estimated';
902
- }): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
901
+ }): _mitway_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
903
902
  /**
904
903
  * The backend base URL the database client is targeting. Useful for
905
904
  * debugging — the actual PostgREST instance is internal and not
@@ -1120,7 +1119,7 @@ declare class Functions {
1120
1119
  * import { createClient } from '@mitway/sdk';
1121
1120
  *
1122
1121
  * const client = createClient({
1123
- * baseUrl: 'https://acme.api.dev.nttmitway.com',
1122
+ * baseUrl: 'https://your-baas.example.com',
1124
1123
  * anonKey: 'eyJhbGciOiJIUzI1NiIs...', // optional
1125
1124
  * });
1126
1125
  *
@@ -1177,11 +1176,11 @@ declare class MitwayBaasClient {
1177
1176
  *
1178
1177
  * @example
1179
1178
  * ```typescript
1180
- * import { createClient } from '@mitway-baas/sdk';
1179
+ * import { createClient } from '@mitway/sdk';
1181
1180
  *
1182
1181
  * const client = createClient({
1183
- * baseUrl: 'https://acme.api.dev.nttmitway.com',
1184
- * postgrestUrl: 'https://acme.db.dev.nttmitway.com',
1182
+ * baseUrl: 'https://your-baas.example.com',
1183
+ * anonKey: 'eyJhbGciOiJIUzI1NiIs...', // optional
1185
1184
  * });
1186
1185
  * ```
1187
1186
  */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Socket } from 'socket.io-client';
2
- import * as _supabase_postgrest_js from '@supabase/postgrest-js';
2
+ import * as _mitway_postgrest_js from '@mitway/postgrest-js';
3
3
 
4
4
  /**
5
5
  * User shape returned by the MITWAY-BaaS auth endpoints.
@@ -471,11 +471,10 @@ declare class Realtime {
471
471
 
472
472
  interface MitwayBaasConfig {
473
473
  /**
474
- * Base URL of the MITWAY-BaaS backend. In production this is typically
475
- * `https://{cliente}.api.dev.nttmitway.com` (or the equivalent pro
476
- * domain). The SDK routes all traffic — auth, database (via the
477
- * backend's PostgREST proxy at `/api/database/records/*`), and future
478
- * storage/functions — through this one URL.
474
+ * Base URL of the MITWAY-BaaS backend the SDK should talk to. The SDK
475
+ * routes every request — auth, database (via the backend's PostgREST
476
+ * proxy at `/api/database/records/*`), storage, realtime (via
477
+ * `/socket.io/`) and functions through this single URL.
479
478
  *
480
479
  * @default "http://localhost:7130"
481
480
  */
@@ -887,7 +886,7 @@ declare class Database {
887
886
  * .select()
888
887
  * .single();
889
888
  */
890
- from(table: string): _supabase_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
889
+ from(table: string): _mitway_postgrest_js.PostgrestQueryBuilder<any, any, any, string, unknown>;
891
890
  /**
892
891
  * Call a PostgreSQL stored function (RPC).
893
892
  *
@@ -899,7 +898,7 @@ declare class Database {
899
898
  head?: boolean;
900
899
  get?: boolean;
901
900
  count?: 'exact' | 'planned' | 'estimated';
902
- }): _supabase_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
901
+ }): _mitway_postgrest_js.PostgrestFilterBuilder<any, any, any, any, string, null, "RPC">;
903
902
  /**
904
903
  * The backend base URL the database client is targeting. Useful for
905
904
  * debugging — the actual PostgREST instance is internal and not
@@ -1120,7 +1119,7 @@ declare class Functions {
1120
1119
  * import { createClient } from '@mitway/sdk';
1121
1120
  *
1122
1121
  * const client = createClient({
1123
- * baseUrl: 'https://acme.api.dev.nttmitway.com',
1122
+ * baseUrl: 'https://your-baas.example.com',
1124
1123
  * anonKey: 'eyJhbGciOiJIUzI1NiIs...', // optional
1125
1124
  * });
1126
1125
  *
@@ -1177,11 +1176,11 @@ declare class MitwayBaasClient {
1177
1176
  *
1178
1177
  * @example
1179
1178
  * ```typescript
1180
- * import { createClient } from '@mitway-baas/sdk';
1179
+ * import { createClient } from '@mitway/sdk';
1181
1180
  *
1182
1181
  * const client = createClient({
1183
- * baseUrl: 'https://acme.api.dev.nttmitway.com',
1184
- * postgrestUrl: 'https://acme.db.dev.nttmitway.com',
1182
+ * baseUrl: 'https://your-baas.example.com',
1183
+ * anonKey: 'eyJhbGciOiJIUzI1NiIs...', // optional
1185
1184
  * });
1186
1185
  * ```
1187
1186
  */
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {PostgrestClient}from'@supabase/postgrest-js';import {io}from'socket.io-client';var c=class n extends Error{statusCode;error;nextActions;constructor(e,t,r,s){super(e),this.name="MitwayBaasError",this.statusCode=t,this.error=r,this.nextActions=s;}static fromApiError(e){return new n(e.message,e.statusCode,e.error,e.nextActions)}};var X=["authorization","x-api-key","cookie","set-cookie"],Z=["password","token","accesstoken","refreshtoken","authorization","secret","apikey","api_key","email","ssn","creditcard","credit_card"];function ee(n){let e={};for(let[t,r]of Object.entries(n))X.includes(t.toLowerCase())?e[t]="***REDACTED***":e[t]=r;return e}function C(n){if(n==null)return n;if(typeof n=="string")try{let e=JSON.parse(n);return C(e)}catch{return n}if(Array.isArray(n))return n.map(C);if(typeof n=="object"){let e={};for(let[t,r]of Object.entries(n))Z.includes(t.toLowerCase().replace(/[-_]/g,""))?e[t]="***REDACTED***":e[t]=C(r);return e}return n}function G(n){if(n==null)return "";if(typeof n=="string")try{return JSON.stringify(JSON.parse(n),null,2)}catch{return n}if(typeof FormData<"u"&&n instanceof FormData)return "[FormData]";try{return JSON.stringify(n,null,2)}catch{return "[Unserializable body]"}}var R=class{enabled;customLog;constructor(e){typeof e=="function"?(this.enabled=true,this.customLog=e):(this.enabled=!!e,this.customLog=null);}log(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.log(r,...t);}warn(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.warn(r,...t);}error(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.error(r,...t);}logRequest(e,t,r,s){if(!this.enabled)return;let i=[`\u2192 ${e} ${t}`];r&&Object.keys(r).length>0&&i.push(` Headers: ${JSON.stringify(ee(r))}`);let a=G(C(s));if(a){let o=a.length>1e3?a.slice(0,1e3)+"... [truncated]":a;i.push(` Body: ${o}`);}this.log(i.join(`
1
+ import {PostgrestClient}from'@mitway/postgrest-js';import {io}from'socket.io-client';var c=class n extends Error{statusCode;error;nextActions;constructor(e,t,r,s){super(e),this.name="MitwayBaasError",this.statusCode=t,this.error=r,this.nextActions=s;}static fromApiError(e){return new n(e.message,e.statusCode,e.error,e.nextActions)}};var X=["authorization","x-api-key","cookie","set-cookie"],Z=["password","token","accesstoken","refreshtoken","authorization","secret","apikey","api_key","email","ssn","creditcard","credit_card"];function ee(n){let e={};for(let[t,r]of Object.entries(n))X.includes(t.toLowerCase())?e[t]="***REDACTED***":e[t]=r;return e}function C(n){if(n==null)return n;if(typeof n=="string")try{let e=JSON.parse(n);return C(e)}catch{return n}if(Array.isArray(n))return n.map(C);if(typeof n=="object"){let e={};for(let[t,r]of Object.entries(n))Z.includes(t.toLowerCase().replace(/[-_]/g,""))?e[t]="***REDACTED***":e[t]=C(r);return e}return n}function G(n){if(n==null)return "";if(typeof n=="string")try{return JSON.stringify(JSON.parse(n),null,2)}catch{return n}if(typeof FormData<"u"&&n instanceof FormData)return "[FormData]";try{return JSON.stringify(n,null,2)}catch{return "[Unserializable body]"}}var R=class{enabled;customLog;constructor(e){typeof e=="function"?(this.enabled=true,this.customLog=e):(this.enabled=!!e,this.customLog=null);}log(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.log(r,...t);}warn(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.warn(r,...t);}error(e,...t){if(!this.enabled)return;let r=`[MITWAY-BaaS Debug] ${e}`;this.customLog?this.customLog(r,...t):console.error(r,...t);}logRequest(e,t,r,s){if(!this.enabled)return;let i=[`\u2192 ${e} ${t}`];r&&Object.keys(r).length>0&&i.push(` Headers: ${JSON.stringify(ee(r))}`);let a=G(C(s));if(a){let o=a.length>1e3?a.slice(0,1e3)+"... [truncated]":a;i.push(` Body: ${o}`);}this.log(i.join(`
2
2
  `));}logResponse(e,t,r,s,i){if(!this.enabled)return;let a=[`\u2190 ${e} ${t} ${r} (${s}ms)`],o=G(C(i));if(o){let g=o.length>1e3?o.slice(0,1e3)+"... [truncated]":o;a.push(` Body: ${g}`);}r>=400?this.error(a.join(`
3
3
  `)):this.log(a.join(`
4
4
  `));}};var K="mitway_baas_csrf_token",te="mitway_baas_session";function V(){return typeof localStorage<"u"?{getItem:e=>{try{return localStorage.getItem(e)}catch{return null}},setItem:(e,t)=>{try{localStorage.setItem(e,t);}catch{}},removeItem:e=>{try{localStorage.removeItem(e);}catch{}}}:{getItem:()=>null,setItem:()=>{},removeItem:()=>{}}}var re={getItem:()=>null,setItem:()=>{},removeItem:()=>{}};function Y(){if(typeof document>"u")return null;let n=document.cookie.split(";").find(e=>e.trim().startsWith(`${K}=`));return n&&n.split("=")[1]||null}function F(n){if(typeof document>"u")return;let e=10080*60,t=typeof window<"u"&&window.location.protocol==="https:"?"; Secure":"";document.cookie=`${K}=${encodeURIComponent(n)}; path=/; max-age=${e}; SameSite=Lax${t}`;}function D(){if(typeof document>"u")return;let n=typeof window<"u"&&window.location.protocol==="https:"?"; Secure":"";document.cookie=`${K}=; path=/; max-age=0; SameSite=Lax${n}`;}var S=class{accessToken=null;refreshToken=null;user=null;persistSession;storageKey;storage;onTokenChange=null;constructor(e){this.persistSession=e?.persistSession??true,this.storageKey=e?.storageKey??te,this.storage=this.persistSession?e?.storage??V():re,(e?.multiTab??true)&&this.persistSession&&typeof window<"u"&&typeof localStorage<"u"&&window.addEventListener("storage",this.handleStorageEvent),this.restoreSession();}handleStorageEvent=e=>{e.key===this.storageKey&&(typeof localStorage<"u"&&e.storageArea!==localStorage||this.syncFromStorage(e.newValue));};syncFromStorage(e){let t=this.accessToken;if(e===null)this.accessToken=null,this.refreshToken=null,this.user=null;else try{let r=JSON.parse(e);if(!r.accessToken||!r.user)return;this.accessToken=r.accessToken,this.refreshToken=r.refreshToken??null,this.user=r.user;}catch{return}t!==this.accessToken&&this.onTokenChange&&this.onTokenChange();}saveSession(e){let t=e.accessToken!==this.accessToken;this.accessToken=e.accessToken,this.user=e.user,e.refreshToken!==void 0&&(this.refreshToken=e.refreshToken??null),this.persist(),t&&this.onTokenChange&&this.onTokenChange();}getSession(){return !this.accessToken||!this.user?null:{accessToken:this.accessToken,refreshToken:this.refreshToken??void 0,user:this.user}}getAccessToken(){return this.accessToken}setAccessToken(e){let t=e!==this.accessToken;this.accessToken=e,this.persist(),t&&this.onTokenChange&&this.onTokenChange();}getRefreshToken(){return this.refreshToken}setRefreshToken(e){this.refreshToken=e,this.persist();}getUser(){return this.user}setUser(e){this.user=e,this.persist();}clearSession(){let e=this.accessToken!==null;this.accessToken=null,this.refreshToken=null,this.user=null,this.removePersisted(),e&&this.onTokenChange&&this.onTokenChange();}restoreSession(){if(!this.persistSession)return false;try{let e=this.storage.getItem(this.storageKey);if(!e)return !1;let t=JSON.parse(e);return !t.accessToken||!t.user?!1:(this.accessToken=t.accessToken,this.refreshToken=t.refreshToken??null,this.user=t.user,!0)}catch{return false}}persist(){if(!this.persistSession||!this.accessToken||!this.user)return;let e={accessToken:this.accessToken,user:this.user};this.refreshToken&&(e.refreshToken=this.refreshToken),this.storage.setItem(this.storageKey,JSON.stringify(e));}removePersisted(){this.persistSession&&this.storage.removeItem(this.storageKey);}};function P(n){if(!n||typeof n!="object")return n;let e=n,t={...e},r=false;return "access_token"in e&&!("accessToken"in e)&&(t.accessToken=e.access_token,delete t.access_token,r=true),"csrf_token"in e&&!("csrfToken"in e)&&(t.csrfToken=e.csrf_token,delete t.csrf_token,r=true),"refresh_token"in e&&!("refreshToken"in e)&&(t.refreshToken=e.refresh_token,delete t.refresh_token,r=true),r?t:n}var se=new Set([500,502,503,504]),ne=new Set(["GET","HEAD","PUT","DELETE","OPTIONS"]),_=class{baseUrl;fetch;defaultHeaders;anonKey;userToken=null;logger;autoRefreshToken=true;isRefreshing=false;refreshPromise=null;tokenManager;refreshToken=null;timeout;retryCount;retryDelay;constructor(e,t,r){if(this.baseUrl=e.baseUrl||"http://localhost:7130",this.autoRefreshToken=e.autoRefreshToken??true,this.fetch=e.fetch||(globalThis.fetch?globalThis.fetch.bind(globalThis):void 0),this.anonKey=e.anonKey,this.defaultHeaders={...e.headers},this.tokenManager=t??new S,this.logger=r||new R(false),this.timeout=e.timeout??3e4,this.retryCount=e.retryCount??3,this.retryDelay=e.retryDelay??500,!this.fetch)throw new Error("Fetch is not available. Provide a fetch implementation in the SDK config.")}buildUrl(e,t){let r=new URL(e,this.baseUrl);return t&&Object.entries(t).forEach(([s,i])=>{if(s==="select"){let a=i.replace(/\s+/g," ").trim();a=a.replace(/\s*\(\s*/g,"(").replace(/\s*\)\s*/g,")").replace(/\(\s+/g,"(").replace(/\s+\)/g,")").replace(/,\s+(?=[^()]*\))/g,","),r.searchParams.append(s,a);}else r.searchParams.append(s,i);}),r.toString()}isRetryableStatus(e){return se.has(e)}computeRetryDelay(e){let r=this.retryDelay*Math.pow(2,e-1)*(.85+Math.random()*.3);return Math.round(r)}async handleRequest(e,t,r={}){let{params:s,headers:i={},body:a,signal:o,...g}=r,p=this.buildUrl(t,s),E=Date.now(),T=ne.has(e.toUpperCase())||r.idempotent===true?this.retryCount:0,b={...this.defaultHeaders},J=this.userToken||this.anonKey;J&&(b.Authorization=`Bearer ${J}`);let M;a!==void 0&&(typeof FormData<"u"&&a instanceof FormData?M=a:(e!=="GET"&&(b["Content-Type"]="application/json;charset=UTF-8"),M=JSON.stringify(a))),i instanceof Headers?i.forEach((f,h)=>{b[h]=f;}):Array.isArray(i)?i.forEach(([f,h])=>{b[f]=h;}):Object.assign(b,i),this.logger.logRequest(e,p,b,M);let H;for(let f=0;f<=T;f++){if(f>0){let l=this.computeRetryDelay(f);if(this.logger.warn(`Retry ${f}/${T} for ${e} ${p} in ${l}ms`),o?.aborted)throw o.reason;await new Promise((u,q)=>{let y=()=>{clearTimeout(Q),q(o.reason);},Q=setTimeout(()=>{o&&o.removeEventListener("abort",y),u();},l);o&&o.addEventListener("abort",y,{once:true});});}let h,m;if((this.timeout>0||o)&&(h=new AbortController,this.timeout>0&&(m=setTimeout(()=>h.abort(),this.timeout)),o))if(o.aborted)h.abort(o.reason);else {let l=()=>h.abort(o.reason);o.addEventListener("abort",l,{once:true}),h.signal.addEventListener("abort",()=>{o.removeEventListener("abort",l);},{once:true});}try{let l=await this.fetch(p,{method:e,headers:b,body:M,...g,...h?{signal:h.signal}:{}});if(this.isRetryableStatus(l.status)&&f<T){m!==void 0&&clearTimeout(m),await l.body?.cancel(),H=new c(`Server error: ${l.status} ${l.statusText}`,l.status,"SERVER_ERROR");continue}if(l.status===204){m!==void 0&&clearTimeout(m);return}let u,q=l.headers.get("content-type");try{q?.includes("json")?u=await l.json():u=await l.text();}catch(y){throw m!==void 0&&clearTimeout(m),new c(`Failed to parse response body: ${y?.message||"Unknown error"}`,l.status,l.ok?"PARSE_ERROR":"REQUEST_FAILED")}if(m!==void 0&&clearTimeout(m),!l.ok){if(this.logger.logResponse(e,p,l.status,Date.now()-E,u),u&&typeof u=="object"&&"error"in u&&u.error!==null&&typeof u.error=="object"){let y=u.error;throw new c(y.message||l.statusText||"Request failed",y.statusCode||l.status,y.code||y.error||"REQUEST_FAILED",y.nextActions)}throw new c(`Request failed: ${l.statusText}`,l.status,"REQUEST_FAILED")}return this.logger.logResponse(e,p,l.status,Date.now()-E,u),u&&typeof u=="object"&&"data"in u&&"error"in u&&u.error===null?u.data:u}catch(l){if(m!==void 0&&clearTimeout(m),l?.name==="AbortError")throw h&&h.signal.aborted&&this.timeout>0&&!o?.aborted?new c(`Request timed out after ${this.timeout}ms`,408,"REQUEST_TIMEOUT"):l;if(l instanceof c)throw l;if(f<T){H=l;continue}throw new c(`Network request failed: ${l?.message||"Unknown error"}`,0,"NETWORK_ERROR")}}throw H||new c("Request failed after all retry attempts",0,"NETWORK_ERROR")}async request(e,t,r={}){try{return await this.handleRequest(e,t,{...r})}catch(s){if(s instanceof c&&s.statusCode===401&&s.error==="INVALID_TOKEN"&&this.autoRefreshToken)try{let i=await this.handleTokenRefresh();return this.setAuthToken(i.accessToken),this.tokenManager.saveSession(i),i.csrfToken&&F(i.csrfToken),i.refreshToken&&this.setRefreshToken(i.refreshToken),await this.handleRequest(e,t,{...r})}catch(i){throw this.tokenManager.clearSession(),this.userToken=null,this.refreshToken=null,D(),i}throw s}}async rawFetch(e,t={}){let r=this.buildUrl(e),s=new Headers(t.headers??{});for(let[i,a]of Object.entries(this.defaultHeaders))s.has(i)||s.set(i,a);if(!s.has("Authorization")){let i=this.userToken??this.anonKey;i&&s.set("Authorization",`Bearer ${i}`);}return this.fetch(r,{...t,headers:s})}get(e,t){return this.request("GET",e,t)}post(e,t,r){return this.request("POST",e,{...r,body:t})}put(e,t,r){return this.request("PUT",e,{...r,body:t})}patch(e,t,r){return this.request("PATCH",e,{...r,body:t})}delete(e,t){return this.request("DELETE",e,t)}setAuthToken(e){this.userToken=e;}setRefreshToken(e){this.refreshToken=e;}getHeaders(){let e={...this.defaultHeaders},t=this.userToken||this.anonKey;return t&&(e.Authorization=`Bearer ${t}`),e}async handleTokenRefresh(){return this.isRefreshing?this.refreshPromise:(this.isRefreshing=true,this.refreshPromise=(async()=>{try{let e=Y(),t=this.refreshToken?{refreshToken:this.refreshToken}:void 0,r=await this.handleRequest("POST","/api/auth/refresh",{body:t,headers:e?{"X-CSRF-Token":e}:{},credentials:"include"});return P(r)}finally{this.isRefreshing=false,this.refreshPromise=null;}})(),this.refreshPromise)}};function w(n,e){return n instanceof c?{data:null,error:n}:{data:null,error:new c(n instanceof Error?n.message:e,500,"AUTH_ERROR")}}var A=class{constructor(e,t){this.http=e;this.tokenManager=t;this.tokenManager.onTokenChange=()=>this._emitFromTokenChange();let r=this.tokenManager.getSession();if(r){this.http.setAuthToken(r.accessToken);let s=this.tokenManager.getRefreshToken();s&&this.http.setRefreshToken(s),this.lastEmittedUserId=r.user.id,this.lastEmittedAccessToken=r.accessToken;}}http;tokenManager;stateChangeListeners=new Set;lastEmittedUserId=null;lastEmittedAccessToken=null;onAuthStateChange(e){return this.stateChangeListeners.add(e),{unsubscribe:()=>{this.stateChangeListeners.delete(e);}}}emit(e,t){for(let r of this.stateChangeListeners)try{r(e,t);}catch{}}_emitFromTokenChange(){let e=this.tokenManager.getSession(),t=this.lastEmittedUserId,r=this.lastEmittedAccessToken;if(!e){t!==null&&(this.lastEmittedUserId=null,this.lastEmittedAccessToken=null,this.emit("SIGNED_OUT",null));return}let s=e.user.id;if(t===null){this.lastEmittedUserId=s,this.lastEmittedAccessToken=e.accessToken,this.emit("SIGNED_IN",e);return}if(t!==s){this.lastEmittedUserId=null,this.lastEmittedAccessToken=null,this.emit("SIGNED_OUT",null),this.lastEmittedUserId=s,this.lastEmittedAccessToken=e.accessToken,this.emit("SIGNED_IN",e);return}r!==e.accessToken&&(this.lastEmittedAccessToken=e.accessToken,this.emit("TOKEN_REFRESHED",e));}saveSessionFromResponse(e){let t={accessToken:e.accessToken,refreshToken:e.refreshToken,user:e.user};e.csrfToken&&F(e.csrfToken),this.tokenManager.saveSession(t),this.http.setAuthToken(e.accessToken),this.http.setRefreshToken(e.refreshToken??null);}async signUp(e){try{let t=await this.http.post("/api/auth/register",e,{credentials:"include"}),r=P(t);return r?.accessToken&&r.user&&this.saveSessionFromResponse(r),{data:r,error:null}}catch(t){return w(t,"Sign up failed")}}async signInWithPassword(e){try{let t=await this.http.post("/api/auth/login",e,{credentials:"include"}),r=P(t);return r?.accessToken&&r.user&&this.saveSessionFromResponse(r),{data:r,error:null}}catch(t){return w(t,"Sign in failed")}}async signOut(){try{try{await this.http.post("/api/auth/logout",void 0,{credentials:"include"});}catch{}return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),D(),{error:null}}catch{return {error:new c("Failed to sign out",500,"SIGNOUT_ERROR")}}}async refreshSession(){try{let e=await this.http.handleTokenRefresh();return e?.accessToken&&e.user&&this.saveSessionFromResponse(e),{data:e,error:null}}catch(e){return w(e,"Session refresh failed")}}async initialize(){let e=this.tokenManager.getSession();if(!e)return this.emit("INITIAL_SESSION",null),{data:null,error:new c("No persisted session",0,"NO_SESSION")};try{let t=await this.http.get("/api/auth/sessions/current");if(t?.user){this.tokenManager.setUser(t.user);let r=this.tokenManager.getSession();return this.emit("INITIAL_SESSION",r),{data:{user:t.user,accessToken:e.accessToken},error:null}}return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),this.emit("INITIAL_SESSION",null),{data:null,error:new c("Invalid session",401,"INVALID_SESSION")}}catch(t){return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),this.emit("INITIAL_SESSION",null),w(t,"Session restore failed")}}getSession(){return this.tokenManager.getSession()}getUser(){return this.tokenManager.getUser()}async getCurrentUser(){try{let e=await this.http.get("/api/auth/sessions/current");if(e?.user){let t={accessToken:this.tokenManager.getSession()?.accessToken??"",user:e.user};this.tokenManager.saveSession(t);}return {data:e,error:null}}catch(e){return w(e,"Failed to get current user")}}async getProfile(e){try{return {data:await this.http.get(`/api/auth/profiles/${encodeURIComponent(e)}`),error:null}}catch(t){return w(t,"Failed to get profile")}}async setProfile(e){try{let t=await this.http.patch("/api/auth/profiles/current",{profile:e}),r=this.tokenManager.getUser();if(t?.profile&&r){let s={...r,profile:t.profile};this.tokenManager.setUser(s),this.emit("USER_UPDATED",this.tokenManager.getSession());}return {data:t,error:null}}catch(t){return w(t,"Failed to update profile")}}};function oe(n,e,t){return async(r,s)=>{let i=typeof r=="string"?r:r.toString(),a=new URL(i),o=a.pathname.startsWith("/")?a.pathname.slice(1):a.pathname,g=o.match(/^rpc\/(.+)$/),p=g?`/api/database/rpc/${g[1]}`:`/api/database/records/${o}`,E=`${n.baseUrl}${p}${a.search}`,x=new Headers(s?.headers);if(!x.has("Authorization")){let T=e.getAccessToken()??t;T&&x.set("Authorization",`Bearer ${T}`);}return fetch(E,{...s,headers:x})}}var O=class{postgrest;httpClient;constructor(e,t,r){this.httpClient=e,this.postgrest=new PostgrestClient("http://dummy",{fetch:oe(e,t,r),headers:{}});}from(e){if(!e||typeof e!="string")throw new c("Database.from(table) requires a non-empty string",400,"INVALID_TABLE_NAME");return this.postgrest.from(e)}rpc(e,t,r){return this.postgrest.rpc(e,t,r)}getUrl(){return this.httpClient.baseUrl}};var ce=2e4;function z(n,e){let t=new Error(e);return t.code=n,t}var le=1e4,N=class{constructor(e,t,r={}){this.topic=e;this.realtime=t;this.options=r;}topic;realtime;bindings=[];state="closed";statusCallback=null;presence={};trackedState=null;presenceHeartbeat=null;lastBroadcastTimestamp=null;options;get isPrivate(){return this.options.config?.private===true}get presenceKey(){return this.options.config?.presence?.key}_state(){return this.state}async _rejoinAfterReconnect(){if(this.state!=="closed"){for(let e of this.bindings)e.type==="postgres_changes"&&(e.subscriptionId=void 0);this.state="joining";try{if(await this.registerAllBindings(),this.trackedState){let e=this.realtime._getSocket(),t=this.presenceKey;e?.emit("realtime:presence:track",t!==void 0?{channel:this.topic,state:this.trackedState,key:t}:{channel:this.topic,state:this.trackedState});}this.lastBroadcastTimestamp&&this.bindings.some(e=>e.type==="broadcast")&&this.replay({since:this.lastBroadcastTimestamp}).catch(()=>{}),this.state="joined",this.statusCallback?.("SUBSCRIBED");}catch(e){this.state="errored",this.statusCallback?.("CHANNEL_ERROR",z("REJOIN_FAILED",e instanceof Error?e.message:String(e)));}}}on(e,t,r){return e==="postgres_changes"?this.bindings.push({type:"postgres_changes",filter:t,callback:r}):e==="broadcast"?this.bindings.push({type:"broadcast",filter:t,callback:r}):this.bindings.push({type:"presence",filter:t,callback:r}),this}async track(e){let t=this.realtime._getSocket();if(!t)throw new c("Socket not connected",503,"NOT_CONNECTED");this.trackedState=e;let r=this.presenceKey;t.emit("realtime:presence:track",r!==void 0?{channel:this.topic,state:e,key:r}:{channel:this.topic,state:e}),this.presenceHeartbeat||(this.presenceHeartbeat=setInterval(()=>{let i=this.realtime._getSocket();i&&this.trackedState&&i.emit("realtime:presence:track",r!==void 0?{channel:this.topic,state:this.trackedState,key:r}:{channel:this.topic,state:this.trackedState});},ce),this.presenceHeartbeat.unref?.());}untrack(){this.trackedState=null,this.presenceHeartbeat&&(clearInterval(this.presenceHeartbeat),this.presenceHeartbeat=null),this.realtime._getSocket()?.emit("realtime:presence:untrack",{channel:this.topic});}presenceState(){return this.presence}subscribe(e){return this.statusCallback=e??null,this.state==="joining"||this.state==="joined"?this:(this.state="joining",this.realtime.connect().then(async()=>{try{await this.registerAllBindings(),this.state="joined",this.statusCallback?.("SUBSCRIBED");}catch(t){this.state="errored";let r=t instanceof Error?t.message:String(t);this.statusCallback?.("CHANNEL_ERROR",z("SUBSCRIBE_FAILED",r));}},t=>{this.state="errored",this.statusCallback?.("CHANNEL_ERROR",z("CONNECT_FAILED",t.message));}),this)}async unsubscribe(){if(this.state==="closed")return;let e=this.realtime._getSocket();if(this.presenceHeartbeat&&(clearInterval(this.presenceHeartbeat),this.presenceHeartbeat=null),!e){this.trackedState=null,this.state="closed";return}this.trackedState&&(e.emit("realtime:presence:untrack",{channel:this.topic}),this.trackedState=null);let t=this.bindings.filter(r=>r.type==="postgres_changes");for(let r of t)r.subscriptionId&&(e.emit("realtime:postgres_changes:unsubscribe",{subscription_id:r.subscriptionId}),r.subscriptionId=void 0);this.bindings.some(r=>r.type==="broadcast"||r.type==="presence")&&e.emit("realtime:unsubscribe",{channel:this.topic}),this.realtime._detachChannel(this),this.state="closed",this.statusCallback?.("CLOSED");}async send(e){if(e.type!=="broadcast")throw new c('Only "broadcast" sends are supported \u2014 DB changes flow via your DB writes, not channel.send()',400,"UNSUPPORTED_SEND_TYPE");if(new Set(["postgres_changes","presence_state","presence_join","presence_leave"]).has(e.event))throw new c(`"${e.event}" is a reserved event name \u2014 pick a different name for broadcast events`,400,"RESERVED_EVENT_NAME");let r=this.realtime._getSocket();if(!r)throw new c("Socket not connected",503,"NOT_CONNECTED");let s=this.options.config?.broadcast?.self,i={channel:this.topic,event:e.event,payload:e.payload};return s===false&&(i.self=false),await new Promise(a=>{r.emit("realtime:publish",i,o=>{a(o);});})}async replay(e){let t=this.realtime._getSocket();if(!t)throw new c("Socket not connected",503,"NOT_CONNECTED");t.emit("realtime:broadcast:replay",{channel:this.topic,since:e.since,limit:e.limit,private:this.isPrivate});}_dispatch(e,t){if(e==="postgres_changes"){let s=t;for(let i of this.bindings)if(!(i.type!=="postgres_changes"||!i.subscriptionId||!s.ids.includes(i.subscriptionId)||!(i.filter.event==="*"||i.filter.event===s.data.eventType)))try{i.callback(s.data);}catch{}return}if(e==="presence_state"||e==="presence_join"||e==="presence_leave"){let s=t;if(s.channel!==this.topic)return;if(e==="presence_state"&&s.state)this.presence={...s.state},this.firePresence({event:"sync",state:this.presence});else if(e==="presence_join"&&s.joins)Object.assign(this.presence,s.joins),this.firePresence({event:"join",joins:s.joins});else if(e==="presence_leave"&&s.leaves){for(let i of Object.keys(s.leaves))delete this.presence[i];this.firePresence({event:"leave",leaves:s.leaves});}return}let r=t.meta;r?.timestamp&&(!this.lastBroadcastTimestamp||r.timestamp>this.lastBroadcastTimestamp)&&(this.lastBroadcastTimestamp=r.timestamp);for(let s of this.bindings){if(s.type!=="broadcast"||s.filter.event!==e)continue;let{meta:i,...a}=t;try{s.callback({type:"broadcast",event:e,payload:a});}catch{}}}firePresence(e){for(let t of this.bindings)if(t.type==="presence"&&t.filter.event===e.event)try{e.event==="sync"?t.callback():(e.event,t.callback(e));}catch{}}async registerAllBindings(){let e=this.realtime._getSocket();if(!e)throw new Error("Socket not available");this.bindings.some(s=>s.type==="broadcast"||s.type==="presence")&&await new Promise((s,i)=>{e.emit("realtime:subscribe",{channel:this.topic,private:this.isPrivate},a=>{a.status==="ok"?s():i(new Error(a.error?.message??"subscribe failed"));});});let r=this.bindings.filter(s=>s.type==="postgres_changes");await Promise.all(r.map(s=>new Promise((i,a)=>{e.emit("realtime:postgres_changes:subscribe",{event:s.filter.event,schema:s.filter.schema??"public",table:s.filter.table,filter:s.filter.filter},o=>{o.status==="ok"&&o.subscription_id?(s.subscriptionId=o.subscription_id,i()):a(new Error(o.error?.message??"postgres_changes subscribe failed"));});})));}},B=class{socket=null;baseUrl;options;anonKey;tokenManager;channels=new Map;connecting=null;firstConnected=false;constructor(e,t,r,s={}){this.baseUrl=e,this.tokenManager=t,this.anonKey=r,this.options=s;}get isConnected(){return this.socket?.connected===true}get socketId(){return this.socket?.id}channel(e,t){let r=this.channels.get(e);if(r)return r;let s=new N(e,this,t);return this.channels.set(e,s),s}connect(){return this.isConnected?Promise.resolve():this.connecting?this.connecting:(this.connecting=this.openSocket(),this.connecting)}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null,this.firstConnected=false);}_getSocket(){return this.socket}_detachChannel(e){this.channels.delete(e.topic);}openSocket(){let e=this.tokenManager.getAccessToken()??this.anonKey;if(!e){let s=new c("Realtime requires an access token or anonKey",401,"AUTH_INVALID_API_KEY");return this.connecting=null,Promise.reject(s)}let t=this.options.timeoutMs??le,r=io(this.baseUrl,{path:this.options.path,transports:this.options.transports??["websocket"],auth:{token:e,...this.options.extraAuth??{}},reconnection:true,timeout:t});return this.socket=r,r.onAny((s,...i)=>this.dispatch(s,i)),r.on("connect",()=>{if(this.firstConnected)for(let s of this.channels.values()){let i=s._state();(i==="joined"||i==="errored")&&s._rejoinAfterReconnect();}}),new Promise((s,i)=>{let a=setTimeout(()=>{r.off("connect",g),r.off("connect_error",p),this.connecting=null,i(new c(`Realtime connection timeout after ${t}ms`,408,"CONNECTION_TIMEOUT"));},t),o=()=>{clearTimeout(a),r.off("connect",g),r.off("connect_error",p);},g=()=>{o(),this.connecting=null,this.firstConnected=true,s();},p=E=>{o(),this.connecting=null,i(new c(E.message,0,"CONNECTION_FAILED"));};r.once("connect",g),r.once("connect_error",p);})}dispatch(e,t){if(e==="postgres_changes"){let s=t[0]??{};this.channels.forEach(i=>i._dispatch("postgres_changes",s));return}if(e==="connect"||e==="disconnect"||e==="connect_error"||e==="error"||e==="realtime:error"||e==="realtime:shutdown")return;let r=t[0]??{};this.channels.forEach(s=>s._dispatch(e,r));}};function L(n){return {id:n.id,name:n.name,public:n.public,fileSizeLimitBytes:n.file_size_limit_bytes,allowedMimeTypes:n.allowed_mime_types,createdAt:n.created_at,updatedAt:n.updated_at}}function j(n,e){return {id:n.id,bucket:e,key:n.key,size:n.size,mimeType:n.mime_type,etag:n.etag,cacheControl:n.cache_control,contentDisposition:n.content_disposition,uploadedBy:n.uploaded_by,uploadedAt:n.uploaded_at,updatedAt:n.updated_at}}function ue(n){return {defaultFileSizeLimitBytes:n.default_file_size_limit_bytes,maxFileSizeLimitBytes:n.max_file_size_limit_bytes,tenantStorageQuotaBytes:n.tenant_storage_quota_bytes,reservedSpaceBytes:n.reserved_space_bytes,signedUrlDefaultTtlSec:n.signed_url_default_ttl_sec,signedUrlMaxTtlSec:n.signed_url_max_ttl_sec}}function de(n){return n.split("/").map(encodeURIComponent).join("/")}function d(n,e){return n instanceof c?{data:null,error:n}:{data:null,error:new c(n instanceof Error?n.message:e,0,"STORAGE_ERROR")}}async function W(n){let e="STORAGE_ERROR",t=`HTTP ${n.status}`;try{let r=await n.json();r&&r.error&&(e=r.error.code??e,t=r.error.message??t);}catch{}return new c(t,n.status,e)}var $=class{constructor(e,t){this.http=e;this.bucketName=t;}http;bucketName;bucketBase(){return `/api/storage/buckets/${encodeURIComponent(this.bucketName)}`}objectPath(e){return `${this.bucketBase()}/objects/${de(e)}`}async upload(e,t,r={}){try{let s=r.upsert?"PUT":"POST",i={"Content-Type":r.contentType??"application/octet-stream"};r.cacheControl&&(i["Cache-Control"]=r.cacheControl),r.contentDisposition&&(i["Content-Disposition"]=r.contentDisposition);let a=await this.http.rawFetch(this.objectPath(e),{method:s,headers:i,body:t,signal:r.abortSignal});if(!a.ok)return {data:null,error:await W(a)};let o=await a.json();return o.error||!o.data?{data:null,error:new c(o.error?.message??"Upload failed",a.status,o.error?.code??"STORAGE_ERROR")}:{data:j(o.data,this.bucketName),error:null}}catch(s){return d(s,"Upload failed")}}async download(e,t={}){try{let r={};t.range&&(r.Range=`bytes=${t.range.start}-${t.range.end}`);let s=await this.http.rawFetch(this.objectPath(e),{method:"GET",headers:r,signal:t.abortSignal});return s.ok?{data:await s.blob(),error:null}:{data:null,error:await W(s)}}catch(r){return d(r,"Download failed")}}async getStream(e,t={}){try{let r={};t.range&&(r.Range=`bytes=${t.range.start}-${t.range.end}`);let s=await this.http.rawFetch(this.objectPath(e),{method:"GET",headers:r,signal:t.abortSignal});return s.ok?s.body?{data:s.body,error:null}:{data:null,error:new c("Response body is not a stream",s.status,"STORAGE_ERROR")}:{data:null,error:await W(s)}}catch(r){return d(r,"Download failed")}}async remove(e){try{let t=await Promise.allSettled(e.map(i=>this.http.rawFetch(this.objectPath(i),{method:"DELETE"}))),r=[],s=[];for(let i=0;i<e.length;i++){let a=e[i],o=t[i];if(o.status==="fulfilled"&&o.value.ok)r.push(a);else if(o.status==="fulfilled")s.push(`${a}: HTTP ${o.value.status}`);else {let g=o.reason instanceof Error?o.reason.message:String(o.reason);s.push(`${a}: ${g}`);}}return s.length>0?{data:null,error:new c(`Failed to delete some objects: ${s.join("; ")}`,0,"STORAGE_ERROR")}:{data:{removed:r},error:null}}catch(t){return d(t,"Delete failed")}}async list(e={}){try{let t={};return e.prefix!==void 0&&(t.prefix=e.prefix),e.limit!==void 0&&(t.limit=String(e.limit)),e.startAfter!==void 0&&(t.start_after=e.startAfter),{data:(await this.http.get(`${this.bucketBase()}/objects`,{params:t})).map(s=>j(s,this.bucketName)),error:null}}catch(t){return d(t,"List failed")}}async copy(e,t,r){try{let s=await this.http.post(`${this.objectPath(e)}/copy`,{dest_bucket:r??this.bucketName,dest_key:t});return {data:j(s,r??this.bucketName),error:null}}catch(s){return d(s,"Copy failed")}}async move(e,t,r){try{let s=await this.http.post(`${this.objectPath(e)}/move`,{dest_bucket:r??this.bucketName,dest_key:t});return {data:j(s,r??this.bucketName),error:null}}catch(s){return d(s,"Move failed")}}async createSignedUrl(e,t={}){try{let r={};t.expiresIn!==void 0&&(r.expires_in=t.expiresIn);let s=await this.http.post(`${this.objectPath(e)}/sign`,r);return {data:{url:s.url,token:s.token,expiresAt:s.expiresAt},error:null}}catch(r){return d(r,"Sign failed")}}getPublicUrl(e){return {data:{url:`${this.http.baseUrl.replace(/\/$/,"")}${this.objectPath(e)}`}}}},I=class{constructor(e){this.http=e;}http;from(e){return new $(this.http,e)}async listBuckets(){try{return {data:(await this.http.get("/api/storage/buckets")).map(L),error:null}}catch(e){return d(e,"listBuckets failed")}}async getBucket(e){try{let t=await this.http.get(`/api/storage/buckets/${encodeURIComponent(e)}`);return {data:L(t),error:null}}catch(t){return d(t,"getBucket failed")}}async createBucket(e,t={}){try{let r={name:e};t.public!==void 0&&(r.public=t.public),t.fileSizeLimitBytes!==void 0&&(r.file_size_limit_bytes=t.fileSizeLimitBytes),t.allowedMimeTypes!==void 0&&(r.allowed_mime_types=t.allowedMimeTypes);let s=await this.http.post("/api/storage/buckets",r);return {data:L(s),error:null}}catch(r){return d(r,"createBucket failed")}}async updateBucket(e,t){try{let r={};t.public!==void 0&&(r.public=t.public),t.fileSizeLimitBytes!==void 0&&(r.file_size_limit_bytes=t.fileSizeLimitBytes),t.allowedMimeTypes!==void 0&&(r.allowed_mime_types=t.allowedMimeTypes);let s=await this.http.patch(`/api/storage/buckets/${encodeURIComponent(e)}`,r);return {data:L(s),error:null}}catch(r){return d(r,"updateBucket failed")}}async deleteBucket(e){try{return await this.http.delete(`/api/storage/buckets/${encodeURIComponent(e)}`),{data:null,error:null}}catch(t){return d(t,"deleteBucket failed")}}async emptyBucket(e){try{return {data:await this.http.post(`/api/storage/buckets/${encodeURIComponent(e)}/empty`,{}),error:null}}catch(t){return d(t,"emptyBucket failed")}}async getConfig(){try{let e=await this.http.get("/api/storage/config");return {data:ue(e),error:null}}catch(e){return d(e,"getConfig failed")}}};function he(n){return {key:n.key,digest:n.digest,updatedAt:n.updated_at}}function k(n,e){return n instanceof c?{data:null,error:n}:{data:null,error:new c(n instanceof Error?n.message:e,0,"FUNCTIONS_ERROR")}}function ge(n){return typeof n=="object"&&n!==null&&!ArrayBuffer.isView(n)&&!(n instanceof Blob)&&!(n instanceof FormData)&&!(n instanceof URLSearchParams)&&!(n instanceof ReadableStream)}var U=class{constructor(e){this.http=e;}http;async list(){try{return {data:await this.http.get("/api/functions"),error:null}}catch(e){return k(e,"list failed")}}async get(e){try{return {data:await this.http.get(`/api/functions/${encodeURIComponent(e)}`),error:null}}catch(t){return k(t,"get failed")}}async create(e){try{return {data:await this.http.post("/api/functions",e),error:null}}catch(t){return k(t,"create failed")}}async update(e,t){try{return {data:await this.http.put(`/api/functions/${encodeURIComponent(e)}`,t),error:null}}catch(r){return k(r,"update failed")}}async remove(e){try{return await this.http.delete(`/api/functions/${encodeURIComponent(e)}`),{data:{deleted:!0},error:null}}catch(t){return k(t,"remove failed")}}async invoke(e,t={}){try{let r=t.method??"POST",s={...t.headers},i;return t.body!==void 0&&t.body!==null&&(ge(t.body)?(i=JSON.stringify(t.body),s["Content-Type"]||(s["Content-Type"]="application/json")):i=t.body),{data:await this.http.rawFetch(`/api/invoke/${encodeURIComponent(e)}`,{method:r,headers:s,body:i}),error:null}}catch(r){return k(r,"invoke failed")}}async listSecrets(){try{return {data:(await this.http.get("/api/functions/secrets")).secrets.map(he),error:null}}catch(e){return k(e,"listSecrets failed")}}async setSecrets(e){try{return await this.http.put("/api/functions/secrets",{secrets:e}),{data:{saved:!0},error:null}}catch(t){return k(t,"setSecrets failed")}}async deleteSecret(e){try{return await this.http.delete(`/api/functions/secrets/${encodeURIComponent(e)}`),{data:{deleted:!0},error:null}}catch(t){return k(t,"deleteSecret failed")}}};var v=class{http;tokenManager;auth;database;realtime;storage;functions;constructor(e={}){let t=new R(e.debug);this.tokenManager=new S({persistSession:e.persistSession,storageKey:e.storageKey,storage:e.storage,multiTab:e.multiTab}),this.http=new _(e,this.tokenManager,t),this.auth=new A(this.http,this.tokenManager),this.database=new O(this.http,this.tokenManager,e.anonKey),this.realtime=new B(this.http.baseUrl,this.tokenManager,e.anonKey,e.realtime),this.storage=new I(this.http),this.functions=new U(this.http);}getHttpClient(){return this.http}};function Qe(n){return new v(n)}var Xe=v;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mitway/sdk",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "TypeScript/JavaScript client for MITWAY-BaaS — auth + database for end-user apps",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -18,14 +18,6 @@
18
18
  "LICENSE"
19
19
  ],
20
20
  "type": "module",
21
- "scripts": {
22
- "build": "tsup",
23
- "dev": "tsup --watch",
24
- "test": "vitest run --passWithNoTests",
25
- "test:watch": "vitest",
26
- "typecheck": "tsc --noEmit",
27
- "prepublishOnly": "pnpm build"
28
- },
29
21
  "keywords": [
30
22
  "mitway",
31
23
  "mitway-baas",
@@ -47,7 +39,7 @@
47
39
  },
48
40
  "homepage": "https://github.com/INC-DataInnovation/MITWAY-Sdk#readme",
49
41
  "dependencies": {
50
- "@supabase/postgrest-js": "^1.21.3",
42
+ "@mitway/postgrest-js": "^1.0.0",
51
43
  "socket.io-client": "^4.8.3"
52
44
  },
53
45
  "devDependencies": {
@@ -61,5 +53,12 @@
61
53
  },
62
54
  "publishConfig": {
63
55
  "access": "public"
56
+ },
57
+ "scripts": {
58
+ "build": "tsup",
59
+ "dev": "tsup --watch",
60
+ "test": "vitest run --passWithNoTests",
61
+ "test:watch": "vitest",
62
+ "typecheck": "tsc --noEmit"
64
63
  }
65
- }
64
+ }