bknd
Version:
Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.
3 lines • 18.9 kB
JavaScript
"use client";
import $ from'dayjs';import pe from'dayjs/plugin/weekOfYear.js';import {decode}from'hono/jwt';import {createContext,useContext,useMemo,useState}from'react';import {jsx}from'react/jsx-runtime';import Ee,{useSWRConfig,mutate}from'swr';import Te from'swr/infinite';var X=Object.create;var N=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty;var ne=(i,e)=>()=>(e||i((e={exports:{}}).exports,e),e.exports);var re=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of H(e))!te.call(i,r)&&r!==t&&N(i,r,{get:()=>e[r],enumerable:!(n=Z(e,r))||n.enumerable});return i};var ie=(i,e,t)=>(t=i!=null?X(ee(i)):{},re(N(t,"default",{value:i,enumerable:true}),i));var q=ne((_e,C)=>{var a=String,S=function(){return {isColorSupported:false,reset:a,bold:a,dim:a,italic:a,underline:a,inverse:a,hidden:a,strikethrough:a,black:a,red:a,green:a,yellow:a,blue:a,magenta:a,cyan:a,white:a,gray:a,bgBlack:a,bgRed:a,bgGreen:a,bgYellow:a,bgBlue:a,bgMagenta:a,bgCyan:a,bgWhite:a,blackBright:a,redBright:a,greenBright:a,yellowBright:a,blueBright:a,magentaBright:a,cyanBright:a,whiteBright:a,bgBlackBright:a,bgRedBright:a,bgGreenBright:a,bgYellowBright:a,bgBlueBright:a,bgMagentaBright:a,bgCyanBright:a,bgWhiteBright:a}};C.exports=S();C.exports.createColors=S;});function b(i,e){let t="";function n(r){return r}for(let r in i){let s=i[r];if(s!==void 0)if(Array.isArray(s))for(let o=0;o<s.length;o++)t.length>0&&(t+="&"),t+=`${n(r)}=${n(s[o])}`;else typeof s=="object"&&(s=JSON.stringify(s)),t.length>0&&(t+="&"),t+=`${n(r)}=${n(s)}`;}return ("")+t}var B=(i,e)=>typeof i=="string"?[1,"1","true"].includes(i):!!(i||e);function A(){try{return B(0)}catch{return false}}var oe={cli_log_level:{key:"BKND_CLI_LOG_LEVEL",validate:i=>{if(typeof i=="string"&&["log","info","warn","error","debug"].includes(i.toLowerCase()))return i.toLowerCase()}},cli_create_ref:{key:"BKND_CLI_CREATE_REF",validate:i=>typeof i=="string"?i:void 0},cli_telemetry:{key:"BKND_CLI_TELEMETRY",validate:i=>{if(!(typeof i>"u"))return B(i,true)}},modules_debug:{key:"BKND_MODULES_DEBUG",validate:B}},_=(i,e,t)=>{try{let n=t?.source??process.env,r=oe[i],s=n[r.key],o=r.validate(s);if(typeof o<"u")return t?.onValid?.(o),o;t?.onFallback?.(s);}catch{}return e};function L(i,e){let t=new Set(e),n={};for(let[r,s]of Object.entries(i))t.has(r)||(n[r]=s);return n}function se(i,e){return Object.entries(i).reduce((t,[n,r])=>{let s=e(r,n);return typeof s<"u"&&(t[n]=s),t},{})}var j=se;var y=ie(q());function ae(){try{let i=process||{},e=i.argv||[],t=i.env||{};return !(t.NO_COLOR||e.includes("--no-color"))&&(!!t.FORCE_COLOR||e.includes("--color")||i.platform==="win32"||(i.stdout||{}).isTTY&&t.TERM!=="dumb"||!!t.CI)}catch{return false}}var U={critical:{prefix:"CRT",color:y.default.red,args_color:y.default.red,original:console.error},error:{prefix:"ERR",color:y.default.red,args_color:y.default.red,original:console.error},warn:{prefix:"WRN",color:y.default.yellow,args_color:y.default.yellow,original:console.warn},info:{prefix:"INF",color:y.default.cyan,original:console.info},log:{prefix:"LOG",color:y.default.dim,args_color:y.default.dim,original:console.log},debug:{prefix:"DBG",color:y.default.yellow,args_color:y.default.dim,original:console.debug}};function de(i,e){let t=ae(),n=U[i],r=n.color(`[${n.prefix}]`),s=e.map(o=>"args_color"in n&&t&&typeof o=="string"?n.args_color(o):o);return n.original(r,y.default.gray(W()),...s)}var Q=_("cli_log_level","log"),D=globalThis.__consoleConfig??={level:Q},K=Object.keys(U),F=new Proxy(D,{get:(i,e)=>{switch(e){case "original":return console;case "setLevel":return r=>{D.level=r;};case "resetLevel":return ()=>{D.level=Q;}}let t=K.indexOf(D.level),n=K.indexOf(e);return e in U&&n<=t?(...r)=>de(e,r):()=>null}});$.extend(pe);function W(i){return $(i).format("YYYY-MM-DD HH:mm:ss")}var c=class{constructor(e={},t){this._options=e;this.fetcher=t??fetch;}fetcher;getDefaultOptions(){return {}}get options(){return {host:"http://localhost",token:void 0,...this.getDefaultOptions(),...this._options}}key(){return this.options.basepath??""}getUrl(e){let t=this.options.basepath??"";return this.options.host+(t+"/"+e).replace(/\/{2,}/g,"/").replace(/\/$/,"")}request(e,t,n){let r=n?.method??"GET",s=Array.isArray(e)?e.join("/"):e,o=this.getUrl(s);t instanceof URLSearchParams?o+="?"+t.toString():typeof t=="object"&&Object.keys(t).length>0&&(o+="?"+b(t));let d=new Headers(this.options.headers??{});for(let[p,g]of Object.entries(n?.headers??{}))d.set(p,g);d.has("Accept")||d.set("Accept","application/json"),this.options.token&&this.options.token_transport==="header"&&d.set("Authorization",`Bearer ${this.options.token}`);let l=n?.body;if(n&&"body"in n&&["POST","PATCH","PUT"].includes(r)){let p=d.get("Content-Type")??void 0;(!p||p.startsWith("application/json"))&&(l=JSON.stringify(n.body),d.set("Content-Type","application/json"));}let u=new Request(o,{...n,method:r,body:l,headers:d});return new m(u,{fetcher:this.fetcher,verbose:this.options.verbose})}get(e,t,n){return this.request(e,t,{...n,method:"GET"})}post(e,t,n){return this.request(e,void 0,{...n,body:t,method:"POST"})}patch(e,t,n){return this.request(e,void 0,{...n,body:t,method:"PATCH"})}put(e,t,n){return this.request(e,void 0,{...n,body:t,method:"PUT"})}delete(e,t,n){return this.request(e,void 0,{...n,body:t,method:"DELETE"})}};function ue(i,e,t){let n=typeof t<"u"?t:e,r=["raw","body","ok","status","res","data","toJSON"];return typeof n!="object"&&(n={}),new Proxy(n,{get(s,o,d){return o==="raw"||o==="res"?i:o==="body"?e:o==="data"?t:o==="ok"?i.ok:o==="status"?i.status:o==="toJSON"?()=>s:Reflect.get(s,o,d)},has(s,o){return r.includes(o)?true:Reflect.has(s,o)},ownKeys(s){return Array.from(new Set([...Reflect.ownKeys(s),...r]))},getOwnPropertyDescriptor(s,o){return r.includes(o)?{configurable:true,enumerable:true,value:Reflect.get({raw:i,body:e,ok:i.ok,status:i.status},o)}:Reflect.getOwnPropertyDescriptor(s,o)}})}var m=class i{constructor(e,t,n){this.request=e;this.options=t;this.refineData=n;}[Symbol.toStringTag];get verbose(){return this.options?.verbose??false}refine(e){return new i(this.request,this.options,e)}async execute(){A()&&await new Promise(o=>setTimeout(o,200));let e=this.options?.fetcher??fetch;this.verbose&&F.debug("[FetchPromise] Request",{method:this.request.method,url:this.request.url});let t=await e(this.request);this.verbose&&F.debug("[FetchPromise] Response",{res:t,ok:t.ok,status:t.status});let n,r,s=t.headers.get("Content-Type")??"";if(s.startsWith("application/json")?(n=await t.json(),typeof n=="object"&&(r="data"in n?n.data:n)):s.startsWith("text")?n=await t.text():n=t.body,this.refineData)try{r=this.refineData(r);}catch(o){console.warn("[FetchPromise] Error in refineData",o),r=void 0;}return ue(t,n,r)}then(e,t){return this.execute().then(e,t)}catch(e){return this.then(void 0,e)}finally(e){return this.then(t=>(e?.(),t),t=>{throw e?.(),t})}path(){return new URL(this.request.url).pathname}key(e){let t=new URL(this.request.url);return e?.search!==false?this.path()+t.search:this.path()}keyArray(e){let t=new URL(this.request.url),n=this.path().split("/");return (e?.search!==false?[...n,t.searchParams.toString()]:n).filter(Boolean)}toString(){return this.key({search:true})}toJSON(){return {url:this.request.url,method:this.request.method}}};var O=class extends c{getDefaultOptions(){return {basepath:"/api/auth",credentials:"include"}}async login(e,t){let n=await this.post([e,"login"],t,{credentials:this.options.credentials});return n.ok&&n.body.token&&await this.options.onTokenUpdate?.(n.body.token),n}async register(e,t){let n=await this.post([e,"register"],t,{credentials:this.options.credentials});return n.ok&&n.body.token&&await this.options.onTokenUpdate?.(n.body.token),n}async actionSchema(e,t){return this.get([e,"actions",t,"schema.json"])}async action(e,t,n){return this.post([e,"actions",t],n)}async loginWithPassword(e){return this.login("password",e)}async registerWithPassword(e){return this.register("password",e)}me(){return this.get(["me"])}strategies(){return this.get(["strategies"])}async logout(){await this.options.onTokenUpdate?.(void 0);}};var x=class extends c{getDefaultOptions(){return {basepath:"/api/data",queryLengthLimit:1e3,defaultQuery:{limit:10}}}requireObjectSet(e,t){if(!e||typeof e!="object"||Object.keys(e).length===0)throw new Error(t??"object is required")}readOne(e,t,n={}){return this.get(["entity",e,t],n)}readOneBy(e,t={}){return this.readMany(e,{...t,limit:1,offset:0}).refine(n=>n[0])}readMany(e,t={}){let n=t??this.options.defaultQuery,r=this.get(["entity",e],n);return r.request.url.length<=this.options.queryLengthLimit?r:this.post(["entity",e,"query"],n)}readManyByReference(e,t,n,r={}){return this.get(["entity",e,t,n],r??this.options.defaultQuery)}createOne(e,t){return this.post(["entity",e],t)}createMany(e,t){if(!t||!Array.isArray(t)||t.length===0)throw new Error("input is required");return this.post(["entity",e],t)}updateOne(e,t,n){if(!t)throw new Error("ID is required");return this.patch(["entity",e,t],n)}updateMany(e,t,n){return this.requireObjectSet(t),this.patch(["entity",e],{update:n,where:t})}deleteOne(e,t){if(!t)throw new Error("ID is required");return this.delete(["entity",e,t])}deleteMany(e,t){return this.requireObjectSet(t),this.delete(["entity",e],t)}count(e,t={}){return this.post(["entity",e,"fn","count"],t)}exists(e,t={}){return this.post(["entity",e,"fn","exists"],t)}};var k=class extends c{getDefaultOptions(){return {basepath:"/api/media",upload_fetcher:fetch}}listFiles(){return this.get(["files"])}getFile(e){return this.get(["file",e],void 0,{headers:{Accept:"*/*"}})}async getFileStream(e){let{res:t}=await this.getFile(e);if(!t.ok||!t.body)throw new Error("Failed to fetch file");return t.body}async download(e){let{res:t}=await this.getFile(e);if(!t.ok||!t.body)throw new Error("Failed to fetch file");return await t.blob()}getFileUploadUrl(e){return e?this.getUrl(`/upload/${e.path}`):this.getUrl("/upload")}getEntityUploadUrl(e,t,n){return this.getUrl(`/entity/${e}/${t}/${n}`)}getUploadHeaders(){return this.options.token_transport==="header"&&this.options.token?new Headers({Authorization:`Bearer ${this.options.token}`}):new Headers}uploadFile(e,t){let n={"Content-Type":"application/octet-stream",...t?._init?.headers||{}},r=t?.filename||"";try{typeof e.type<"u"&&(n["Content-Type"]=e.type),t?.filename||(r=e.name);}catch{}r&&r.length>0&&r.includes("/")&&(r=r.split("/").pop()||"");let s={...t?._init||{},headers:n};if(t?.path)return this.post(t.path,e,s);if(!r||r.length===0)throw new Error("Invalid filename");return this.post(t?.path??["upload",r],e,s)}async upload(e,t={}){if(e instanceof Request||typeof e=="string"){let r=await(t.fetcher??this.options.upload_fetcher)(e);if(!r.ok||!r.body)throw new Error("Failed to fetch file");return this.uploadFile(r.body,t)}else if(e instanceof Response){if(!e.body)throw new Error("Invalid response");return this.uploadFile(e.body,{...t??{},_init:{...t._init??{},headers:{...t._init?.headers??{},"Content-Type":e.headers.get("Content-Type")||"application/octet-stream"}}})}return this.uploadFile(e,t)}async uploadToEntity(e,t,n,r,s){return this.upload(r,{...s,path:["entity",e,t,n]})}deleteFile(e){return this.delete(["file",e])}};var w=class extends c{getDefaultOptions(){return {basepath:"/api/system"}}readConfig(){return this.get("config")}readSchema(e){return this.get("schema",{config:e?.config?1:0,secrets:e?.secrets?1:0,fresh:e?.fresh?1:0})}setConfig(e,t,n){return this.post(["config","set",e].join("/")+`?force=${n?1:0}`,t)}addConfig(e,t,n){return this.post(["config","add",e,t],n)}patchConfig(e,t,n){return this.patch(["config","patch",e,t],n)}overwriteConfig(e,t,n){return this.put(["config","overwrite",e,t],n)}removeConfig(e,t){return this.delete(["config","remove",e,t])}};var R=class{constructor(e={}){this.options=e;this.verified=e.verified===true,"request"in e&&e.request?(this.options.host=e.host??new URL(e.request.url).origin,this.options.headers=e.headers??e.request.headers,this.extractToken()):"token"in e&&e.token?(this.token_transport="header",this.updateToken(e.token,{trigger:false})):"user"in e&&e.user?(this.token_transport="none",this.user=e.user,this.verified=e.verified!==false):this.extractToken(),this.buildApis();}token;user;verified=false;token_transport="header";system;data;auth;media;get fetcher(){return this.options.fetcher??fetch}get baseUrl(){return this.options.host??"http://localhost"}get tokenKey(){return this.options.key??"auth"}extractToken(){if(this.verified=false,this.options.headers){let e=ye(this.options.headers.get("cookie"),"auth");if(e){this.token_transport="cookie",this.updateToken(e);return}let t=this.options.headers.get("authorization")?.replace("Bearer ","");if(t){this.token_transport="header",this.updateToken(t);return}}else this.storage&&this.storage.getItem(this.tokenKey).then(e=>{this.token_transport="header",this.updateToken(e?String(e):void 0);});}get storage(){return this.options.storage?{getItem:async e=>await this.options.storage.getItem(e),setItem:async(e,t)=>await this.options.storage.setItem(e,t),removeItem:async e=>await this.options.storage.removeItem(e)}:null}updateToken(e,t){if(this.token=e,this.verified=false,e?this.user=L(decode(e).payload,["iat","iss","exp"]):this.user=void 0,this.storage){let n=this.tokenKey;e?this.storage.setItem(n,e).then(()=>{this.options.onAuthStateChange?.(this.getAuthState());}):this.storage.removeItem(n).then(()=>{this.options.onAuthStateChange?.(this.getAuthState());});}else t?.trigger!==false&&this.options.onAuthStateChange?.(this.getAuthState());t?.rebuild&&this.buildApis();}markAuthVerified(e){return this.verified=e,this}isAuthVerified(){return this.verified}getAuthState(){return {token:this.token,user:this.user,verified:this.verified}}isAuthenticated(){let{token:e,user:t}=this.getAuthState();return !!e&&!!t}async getVerifiedAuthState(){return await this.verifyAuth(),this.getAuthState()}async verifyAuth(){if(!this.token){this.markAuthVerified(false);return}try{let{ok:e,data:t}=await this.auth.me(),n=t?.user;if(!e||!n)throw new Error;this.user=n,this.markAuthVerified(!0);}catch{this.markAuthVerified(false),this.updateToken(void 0);}}getUser(){return this.user||null}getParams(){return Object.freeze({host:this.baseUrl,token:this.token,headers:this.options.headers,token_transport:this.token_transport,verbose:this.options.verbose})}buildApis(){let e=this.getParams(),t=this.options.fetcher;this.system=new w(e,t),this.data=new x({...e,...this.options.data},t),this.auth=new O({...e,credentials:this.options.storage?"omit":"include",...this.options.auth,onTokenUpdate:n=>{this.updateToken(n,{rebuild:true}),this.options.auth?.onTokenUpdate?.(n);}},t),this.media=new k({...e,...this.options.media},t);}};function ye(i,e){if(!i)return null;for(let t of i.split("; ")){let[n,r]=t.split("=");if(n===e&&r)return decodeURIComponent(r)}return null}var M=createContext(void 0),ge=({children:i,host:e,baseUrl:t=e,...n})=>{let r=G(),s=P(),o=t??s?.baseUrl??"",d;if(r&&(d=r.user),!o)try{o=window.location.origin;}catch{}let l={user:d,...n,host:o},u=useMemo(()=>new R({...l,verbose:A(),onAuthStateChange:h=>{n.onAuthStateChange?.(h),(!p?.token||h.token!==p?.token)&&g(h);}}),[JSON.stringify(l)]),[p,g]=useState(l.user?u.getAuthState():void 0);return jsx(M.Provider,{value:{baseUrl:u.baseUrl,api:u,authState:p},children:i})},f=i=>{let e=useContext(M);return !e?.api||i&&i.length>0&&i!==e.baseUrl?new R({host:i??""}):e.api},P=()=>useContext(M),me=()=>P()?.baseUrl;function G(){let i={logout_route:"/api/auth/logout",admin_basepath:""};return typeof window<"u"&&window.__BKND__?{...i,...window.__BKND__}:i}var Et=(i,e)=>{let t=f(),n=i(t),r=e?.refine??(l=>l),s=()=>n.execute().then(r),o=n.key();return {...Ee(e?.enabled===false?null:o,s,e),promise:n,key:o,api:t}},At=(i,e)=>{let[t,n]=useState(false),r=f(),s=u=>i(r,u),o=e?.refine??(u=>u),d=Te((u,p)=>p&&!p.length?(n(true),null):s(u).request.url,u=>new m(new Request(u),{fetcher:r.fetcher},o).execute(),{revalidateFirstPage:false}),l=d.data?[].concat(...d.data):[];return {...d,_data:d.data,data:l,endReached:t,promise:s(d.size),key:s(d.size).key(),api:r}},V=i=>{let e=useSWRConfig().mutate,t=f();return async n=>{let r="";return typeof n=="string"?r=n:typeof n=="function"&&(r=n(t).key()),i?.exact?e(r):e(s=>typeof s=="string"&&s.startsWith(r))}};var E=class extends Error{constructor(t,n){let r=n;"error"in t&&(r=t.error,n&&(r=`${n}: ${r}`));super(r??"UseEntityApiError");this.response=t;}},Oe=(i,e)=>{let t=f().data;return {create:async n=>{let r=await t.createOne(i,n);if(!r.ok)throw new E(r,`Failed to create entity "${i}"`);return r},read:async n=>{let r=e?await t.readOne(i,e,n):await t.readMany(i,n);if(!r.ok)throw new E(r,`Failed to read entity "${i}"`);return r},update:async(n,r=e)=>{if(!r)throw new Error("id is required");let s=await t.updateOne(i,r,n);if(!s.ok)throw new E(s,`Failed to update entity "${i}"`);return s},_delete:async(n=e)=>{if(!n)throw new Error("id is required");let r=await t.deleteOne(i,n);if(!r.ok)throw new E(r,`Failed to delete entity "${i}"`);return r}}};function v(i,e,t,n){return "/"+[...i.options?.basepath?.split("/")??[],e,...t?[t]:[]].filter(Boolean).join("/")+(n?"?"+b(n):"")}var xe=(i,e,t,n)=>{let r=f().data,s=v(r,i,e,t),{read:o,...d}=Oe(i,e),l=()=>o(t??{}),u=Ee(n?.enabled===false?null:s,l,{revalidateOnFocus:false,keepPreviousData:true,...n}),p=async h=>{let I=v(r,i,h);return mutate(T=>typeof T=="string"&&T.startsWith(I),void 0,{revalidate:true})},g=j(d,h=>async(...I)=>{let T=await h(...I);return n?.revalidateOnMutate!==false&&await p(),T});return {...u,...g,mutate:p,mutateRaw:u.mutate,api:r,key:s}};async function z(i,e,t,n){function r(o,d){return typeof o<"u"&&typeof d<"u"&&"id"in o&&o.id===t?{...o,...d}:o}let s=v(i,e);return mutate(o=>typeof o=="string"&&o.startsWith(s),async o=>{if(!(typeof o>"u"))return Array.isArray(o)?o.map(d=>r(d,n)):r(o,n)},{revalidate:false})}var kt=(i,e,t)=>{let{data:n,...r}=xe(i,e,void 0,{...t,enabled:false});return {...r,mutate:e?o=>z(r.api,i,e,o):(o,d)=>z(r.api,i,o,d)}};var ke=i=>{let e=f(i?.baseUrl),t=V(),{authState:n}=P(),r=n?.verified??false;async function s(p){return (await e.auth.login("password",p)).data}async function o(p){return (await e.auth.register("password",p)).data}function d(p){e.updateToken(p);}async function l(){e.updateToken(void 0),t();}async function u(){await e.verifyAuth();}return {data:n,user:n?.user,token:n?.token,verified:r,login:s,register:o,logout:l,setToken:d,verify:u}};
export{R as Api,ge as ClientProvider,m as FetchPromise,E as UseEntityApiError,v as makeKey,z as mutateEntityCache,f as useApi,At as useApiInfiniteQuery,Et as useApiQuery,ke as useAuth,me as useBaseUrl,G as useBkndWindowContext,Oe as useEntity,kt as useEntityMutate,xe as useEntityQuery,V as useInvalidate};