@mitway/sdk 0.7.0 → 0.7.2

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
@@ -10,7 +10,7 @@ realtime events, and manage storage against a per-tenant MITWAY-BaaS deployment.
10
10
 
11
11
  | Module | Status | Notes |
12
12
  |---|---|---|
13
- | `auth` | Working | `signUp`, `signInWithPassword`, `signOut`, `refreshSession`, `getSession`, `getUser`, `getCurrentUser`, `getProfile`, `setProfile` |
13
+ | `auth` | Working | `signUp`, `signInWithPassword`, `signOut`, `refreshSession`, `getSession`, `getUser`, `getCurrentUser`, `getProfile`, `setProfile`, `onAuthStateChange` |
14
14
  | `database` | Working | PostgREST query builder via `@supabase/postgrest-js` |
15
15
  | `realtime` | Working | Socket.IO transport with channels (postgres_changes, broadcast, presence) |
16
16
  | `storage` | Working | Bucket admin + object operations (upload, download, signed URLs, public URLs) |
@@ -47,7 +47,7 @@ const { data: session, error } = await client.auth.signInWithPassword({
47
47
  password: 'a-strong-password',
48
48
  });
49
49
 
50
- // Database query (PostgREST query builder — same surface as Supabase)
50
+ // Database query (PostgREST query builder)
51
51
  const { data: posts, error: dbError } = await client.database
52
52
  .from('posts')
53
53
  .select('*, author:users(*)')
@@ -107,7 +107,61 @@ interface MitwayBaasConfig {
107
107
  retryCount?: number; // default 3 (0 disables)
108
108
  retryDelay?: number; // default 500 ms (exponential backoff with jitter)
109
109
  autoRefreshToken?: boolean;// default true (refreshes on 401 INVALID_TOKEN)
110
+ persistSession?: boolean; // default true (session survives F5)
111
+ storageKey?: string; // default 'mitway_baas_session'
112
+ storage?: StorageAdapter; // default browser localStorage — pluggable
113
+ multiTab?: boolean; // default true (sync session across tabs via `storage` event)
114
+ realtime?: RealtimeOptions;
110
115
  }
116
+
117
+ interface StorageAdapter {
118
+ getItem(key: string): string | null;
119
+ setItem(key: string, value: string): void;
120
+ removeItem(key: string): void;
121
+ }
122
+ ```
123
+
124
+ ### Reactive auth — `onAuthStateChange`
125
+
126
+ Subscribe to session transitions (sign-in, sign-out, token refresh,
127
+ cross-tab sync, profile update) without polling `getSession()`. Returns
128
+ a `Subscription`; call `.unsubscribe()` to stop.
129
+
130
+ ```typescript
131
+ const sub = client.auth.onAuthStateChange((event, session) => {
132
+ // event: 'INITIAL_SESSION' | 'SIGNED_IN' | 'SIGNED_OUT'
133
+ // | 'TOKEN_REFRESHED' | 'USER_UPDATED'
134
+ if (event === 'SIGNED_OUT') router.push('/login');
135
+ });
136
+
137
+ // later
138
+ sub.unsubscribe();
139
+ ```
140
+
141
+ ### Custom storage (e.g., cross-subdomain cookie)
142
+
143
+ Pass a `storage` adapter to back the session with something other than
144
+ the default `localStorage` — cookies, a native secure store, an
145
+ in-memory stub for tests. The adapter is called on every session
146
+ mutation (sign-in, refresh, logout), so anything layered on top of it
147
+ sees a complete session lifecycle.
148
+
149
+ ```typescript
150
+ import { createClient, createLocalStorageAdapter } from '@mitway/sdk';
151
+ import type { StorageAdapter } from '@mitway/sdk';
152
+
153
+ const localAdapter = createLocalStorageAdapter();
154
+
155
+ const dualStorage: StorageAdapter = {
156
+ getItem: (k) => localAdapter.getItem(k) ?? readFromCookie(k),
157
+ setItem: (k, v) => { localAdapter.setItem(k, v); writeCookie(k, v); },
158
+ removeItem: (k) => { localAdapter.removeItem(k); clearCookie(k); },
159
+ };
160
+
161
+ const client = createClient({
162
+ baseUrl: 'https://…',
163
+ storage: dualStorage,
164
+ });
111
165
  ```
112
166
 
113
167
  `baseUrl` is the **only** URL consumers need. Auth, database, storage, and realtime
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
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(`
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
- `));}};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);}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),w=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()-w,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()-w,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 E(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();}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 E(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 E(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 E(e,"Session refresh failed")}}async initialize(){if(!this.tokenManager.restoreSession())return this.emit("INITIAL_SESSION",null),{data:null,error:new c("No persisted session",0,"NO_SESSION")};let t=this.tokenManager.getSession();if(!t)return this.emit("INITIAL_SESSION",null),{data:null,error:new c("No persisted session",0,"NO_SESSION")};this.http.setAuthToken(t.accessToken);let r=this.tokenManager.getRefreshToken();r&&this.http.setRefreshToken(r),this.lastEmittedUserId=t.user.id,this.lastEmittedAccessToken=t.accessToken;try{let s=await this.http.get("/api/auth/sessions/current");if(s?.user){this.tokenManager.setUser(s.user);let i=this.tokenManager.getSession();return this.emit("INITIAL_SESSION",i),{data:{user:s.user,accessToken:t.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(s){return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),this.emit("INITIAL_SESSION",null),E(s,"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 E(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 E(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 E(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}`,w=`${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(w,{...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=w=>{o(),this.connecting=null,i(new c(w.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;
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;
5
5
  exports.Auth=A;exports.Database=O;exports.Functions=U;exports.HttpClient=_;exports.Logger=R;exports.MitwayBaasClient=v;exports.MitwayBaasError=c;exports.Realtime=B;exports.RealtimeChannel=N;exports.Storage=I;exports.StorageBucketClient=$;exports.TokenManager=S;exports.createClient=Qe;exports.createLocalStorageAdapter=V;exports.default=Xe;
package/dist/index.d.cts CHANGED
@@ -723,9 +723,7 @@ type AuthResult<T> = {
723
723
  error: MitwayBaasError | null;
724
724
  };
725
725
  /**
726
- * Event names emitted by `auth.onAuthStateChange`. Mirrors
727
- * `@supabase/supabase-js` event names so consumers that already know that
728
- * contract do not have to re-learn ours.
726
+ * Event names emitted by `auth.onAuthStateChange`.
729
727
  *
730
728
  * - `INITIAL_SESSION` — emitted once per `auth.initialize()` call
731
729
  * regardless of whether a persisted session was found. `session` is
@@ -809,20 +807,29 @@ declare class Auth {
809
807
  */
810
808
  refreshSession(): Promise<AuthResult<AuthResponse>>;
811
809
  /**
812
- * Restore the session from localStorage and validate it with the backend.
813
- * Call this once on app startup (e.g. in a React AuthProvider useEffect).
810
+ * Validate the current session against the backend and emit
811
+ * `INITIAL_SESSION`. Call this once on app startup (e.g. in a React
812
+ * AuthProvider useEffect).
813
+ *
814
+ * The in-memory session is already populated at SDK construction time —
815
+ * `TokenManager`'s constructor reads persisted storage synchronously
816
+ * and `Auth`'s constructor seeds the `HttpClient` from it. This method
817
+ * adds the backend round-trip that guarantees the access token is
818
+ * still valid server-side, and fires `INITIAL_SESSION` so listeners
819
+ * registered before startup can transition out of their "checking"
820
+ * state.
814
821
  *
815
822
  * Flow:
816
- * 1. Read persisted session from localStorage.
817
- * 2. Populate in-memory state (TokenManager + HttpClient).
818
- * 3. Validate with `GET /api/auth/sessions/current`.
819
- * - If the access token expired, the HttpClient auto-refresh kicks in
820
- * using the persisted refresh token (sent in the POST body, not
823
+ * 1. If no in-memory session emit `INITIAL_SESSION(null)` + return
824
+ * `NO_SESSION`. The app should show the login page.
825
+ * 2. `GET /api/auth/sessions/current`.
826
+ * - If the access token expired, `HttpClient`'s auto-refresh
827
+ * kicks in with the persisted refresh token (POST body, not
821
828
  * cookies — works cross-site).
822
- * 4. Return the validated user or an error.
823
- *
824
- * If no persisted session exists, returns `{ data: null, error }` — the
825
- * app should show the login page.
829
+ * 3. Mirror the validated user into memory + emit
830
+ * `INITIAL_SESSION(session)`.
831
+ * 4. On backend rejection, clear the session + emit
832
+ * `INITIAL_SESSION(null)`.
826
833
  */
827
834
  initialize(): Promise<AuthResult<AuthResponse>>;
828
835
  /**
@@ -983,7 +990,7 @@ type UploadBody = Blob | ArrayBuffer | ArrayBufferView | ReadableStream<Uint8Arr
983
990
  * Storage module — thin wrapper over the /api/storage/* REST endpoints
984
991
  * exposed by MITWAY-BaaS.
985
992
  *
986
- * Surface mirrors what coding agents expect from a Supabase-style storage
993
+ * Surface exposes per-bucket object operations + admin bucket CRUD via `/api/storage/*`
987
994
  * SDK but routes through the Mitway backend (no direct S3 calls). Binary
988
995
  * upload/download uses `HttpClient.rawFetch`; JSON operations use the
989
996
  * standard typed `request<T>` path.
@@ -1153,7 +1160,7 @@ declare class MitwayBaasClient {
1153
1160
  *
1154
1161
  * Currently ships:
1155
1162
  * - auth (signUp, signInWithPassword, signOut, refreshSession, getSession, getUser)
1156
- * - database (PostgREST-backed query builder via @supabase/postgrest-js)
1163
+ * - database (PostgREST-backed query builder)
1157
1164
  * - realtime (Socket.IO transport: subscribe / unsubscribe / publish / on)
1158
1165
  * - storage (bucket admin + per-bucket object operations)
1159
1166
  * - functions (edge function CRUD, invoke, secrets management)
package/dist/index.d.ts CHANGED
@@ -723,9 +723,7 @@ type AuthResult<T> = {
723
723
  error: MitwayBaasError | null;
724
724
  };
725
725
  /**
726
- * Event names emitted by `auth.onAuthStateChange`. Mirrors
727
- * `@supabase/supabase-js` event names so consumers that already know that
728
- * contract do not have to re-learn ours.
726
+ * Event names emitted by `auth.onAuthStateChange`.
729
727
  *
730
728
  * - `INITIAL_SESSION` — emitted once per `auth.initialize()` call
731
729
  * regardless of whether a persisted session was found. `session` is
@@ -809,20 +807,29 @@ declare class Auth {
809
807
  */
810
808
  refreshSession(): Promise<AuthResult<AuthResponse>>;
811
809
  /**
812
- * Restore the session from localStorage and validate it with the backend.
813
- * Call this once on app startup (e.g. in a React AuthProvider useEffect).
810
+ * Validate the current session against the backend and emit
811
+ * `INITIAL_SESSION`. Call this once on app startup (e.g. in a React
812
+ * AuthProvider useEffect).
813
+ *
814
+ * The in-memory session is already populated at SDK construction time —
815
+ * `TokenManager`'s constructor reads persisted storage synchronously
816
+ * and `Auth`'s constructor seeds the `HttpClient` from it. This method
817
+ * adds the backend round-trip that guarantees the access token is
818
+ * still valid server-side, and fires `INITIAL_SESSION` so listeners
819
+ * registered before startup can transition out of their "checking"
820
+ * state.
814
821
  *
815
822
  * Flow:
816
- * 1. Read persisted session from localStorage.
817
- * 2. Populate in-memory state (TokenManager + HttpClient).
818
- * 3. Validate with `GET /api/auth/sessions/current`.
819
- * - If the access token expired, the HttpClient auto-refresh kicks in
820
- * using the persisted refresh token (sent in the POST body, not
823
+ * 1. If no in-memory session emit `INITIAL_SESSION(null)` + return
824
+ * `NO_SESSION`. The app should show the login page.
825
+ * 2. `GET /api/auth/sessions/current`.
826
+ * - If the access token expired, `HttpClient`'s auto-refresh
827
+ * kicks in with the persisted refresh token (POST body, not
821
828
  * cookies — works cross-site).
822
- * 4. Return the validated user or an error.
823
- *
824
- * If no persisted session exists, returns `{ data: null, error }` — the
825
- * app should show the login page.
829
+ * 3. Mirror the validated user into memory + emit
830
+ * `INITIAL_SESSION(session)`.
831
+ * 4. On backend rejection, clear the session + emit
832
+ * `INITIAL_SESSION(null)`.
826
833
  */
827
834
  initialize(): Promise<AuthResult<AuthResponse>>;
828
835
  /**
@@ -983,7 +990,7 @@ type UploadBody = Blob | ArrayBuffer | ArrayBufferView | ReadableStream<Uint8Arr
983
990
  * Storage module — thin wrapper over the /api/storage/* REST endpoints
984
991
  * exposed by MITWAY-BaaS.
985
992
  *
986
- * Surface mirrors what coding agents expect from a Supabase-style storage
993
+ * Surface exposes per-bucket object operations + admin bucket CRUD via `/api/storage/*`
987
994
  * SDK but routes through the Mitway backend (no direct S3 calls). Binary
988
995
  * upload/download uses `HttpClient.rawFetch`; JSON operations use the
989
996
  * standard typed `request<T>` path.
@@ -1153,7 +1160,7 @@ declare class MitwayBaasClient {
1153
1160
  *
1154
1161
  * Currently ships:
1155
1162
  * - auth (signUp, signInWithPassword, signOut, refreshSession, getSession, getUser)
1156
- * - database (PostgREST-backed query builder via @supabase/postgrest-js)
1163
+ * - database (PostgREST-backed query builder)
1157
1164
  * - realtime (Socket.IO transport: subscribe / unsubscribe / publish / on)
1158
1165
  * - storage (bucket admin + per-bucket object operations)
1159
1166
  * - functions (edge function CRUD, invoke, secrets management)
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
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(`
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
- `));}};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);}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),w=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()-w,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()-w,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 E(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();}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 E(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 E(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 E(e,"Session refresh failed")}}async initialize(){if(!this.tokenManager.restoreSession())return this.emit("INITIAL_SESSION",null),{data:null,error:new c("No persisted session",0,"NO_SESSION")};let t=this.tokenManager.getSession();if(!t)return this.emit("INITIAL_SESSION",null),{data:null,error:new c("No persisted session",0,"NO_SESSION")};this.http.setAuthToken(t.accessToken);let r=this.tokenManager.getRefreshToken();r&&this.http.setRefreshToken(r),this.lastEmittedUserId=t.user.id,this.lastEmittedAccessToken=t.accessToken;try{let s=await this.http.get("/api/auth/sessions/current");if(s?.user){this.tokenManager.setUser(s.user);let i=this.tokenManager.getSession();return this.emit("INITIAL_SESSION",i),{data:{user:s.user,accessToken:t.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(s){return this.tokenManager.clearSession(),this.http.setAuthToken(null),this.http.setRefreshToken(null),this.emit("INITIAL_SESSION",null),E(s,"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 E(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 E(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 E(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}`,w=`${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(w,{...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=w=>{o(),this.connecting=null,i(new c(w.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;
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;
5
5
  export{A as Auth,O as Database,U as Functions,_ as HttpClient,R as Logger,v as MitwayBaasClient,c as MitwayBaasError,B as Realtime,N as RealtimeChannel,I as Storage,$ as StorageBucketClient,S as TokenManager,Qe as createClient,V as createLocalStorageAdapter,Xe as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mitway/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
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",