bknd
Version:
Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.
2 lines (1 loc) • 4.29 kB
JavaScript
import{readFile as D,writeFile as I}from"node:fs/promises";import C from"node:path";import{serve as B}from"@hono/node-server";import{serveStatic as L}from"@hono/node-server/serve-static";import{registries as F}from"bknd";import{readFile as g,readdir as A,stat as l,unlink as $,writeFile as N}from"node:fs/promises";import{StorageAdapter as P,guessMimeType as h}from"bknd";import{parse as R,s as y,isFile as v}from"bknd/utils";var w=y.object({path:y.string({default:"./"})},{title:"Local",description:"Local file system storage",additionalProperties:!1}),p=class extends P{config;constructor(e={}){super(),this.config=R(w,e)}getSchema(){return w}getName(){return"local"}async listObjects(e){let t=await A(this.config.path);return await Promise.all(t.filter(n=>!e||n.startsWith(e)).map(async n=>{let a=await l(`${this.config.path}/${n}`);return{key:n,last_modified:a.mtime,size:a.size}}))}async computeEtag(e){let t=v(e)?e:new Response(e),r=await crypto.subtle.digest("SHA-256",await t.arrayBuffer());return`"${Array.from(new Uint8Array(r)).map(i=>i.toString(16).padStart(2,"0")).join("")}"`}async putObject(e,t){if(t===null)throw new Error("Body is empty");let r=`${this.config.path}/${e}`;return await N(r,v(t)?t.stream():t),await this.computeEtag(t)}async deleteObject(e){try{await $(`${this.config.path}/${e}`)}catch{}}async objectExists(e){try{return(await l(`${this.config.path}/${e}`)).isFile()}catch{return!1}}parseRangeHeader(e,t){let r=e.match(/^bytes=(\d*)-(\d*)$/);if(!r)return null;let[,n,a]=r,i=n?Number.parseInt(n,10):0,o=a?Number.parseInt(a,10):t-1;return!n&&a&&(i=Math.max(0,t-Number.parseInt(a,10)),o=t-1),i<0||o>=t||i>o?null:{start:i,end:o}}async getObject(e,t){try{let r=`${this.config.path}/${e}`,a=(await l(r)).size,i=h(e),o=new Headers({"Accept-Ranges":"bytes","Content-Type":i||"application/octet-stream"}),d=t.get("range");if(d){let c=this.parseRangeHeader(d,a);if(!c)return o.set("Content-Range",`bytes */${a}`),new Response("",{status:416,headers:o});let{start:m,end:f}=c,u=(await g(r,{encoding:null})).slice(m,f+1);return o.set("Content-Range",`bytes ${m}-${f}/${a}`),o.set("Content-Length",u.length.toString()),new Response(u,{status:206,headers:o})}else{let c=await g(r);return o.set("Content-Length",c.length.toString()),new Response(c,{status:200,headers:o})}}catch{return new Response("",{status:404})}}getObjectUrl(e){throw new Error("Method not implemented.")}async getObjectMeta(e){let t=await l(`${this.config.path}/${e}`);return{type:h(e)||"application/octet-stream",size:t.size}}toJSON(e){return{type:this.getName(),config:this.config}}};var b=!1;function S(){return b||(F.media.register("local",p),b=!0),(s={})=>new p(s).toJSON(!0)}import{createRuntimeApp as q}from"bknd/adapter";import{config as O}from"bknd";import{$console as E}from"bknd/utils";async function j({distPath:s,relativeDistPath:e,...t}={},r=process.env){let n=C.relative(process.cwd(),C.resolve(s??e??"./node_modules/bknd/dist","static"));return e&&E.warn("relativeDistPath is deprecated, please use distPath instead"),S(),await q({serveStatic:L({root:n}),...t},r)}function k(s={},e=process.env){let t;return async r=>(t||(t=await j(s,e)),t.fetch(r))}function ne({port:s=O.server.default_port,hostname:e,listener:t,...r}={},n=process.env){B({port:s,hostname:e,fetch:k(r,n)},a=>{E.log(`Server is running on http://localhost:${a.port}`),t?.(a)})}import{genericSqlite as H}from"bknd";import{DatabaseSync as x}from"node:sqlite";import{omitKeys as M}from"bknd/utils";function ce(s){let e;return s&&("database"in s&&s.database?e=s.database:s.url&&(e=new x(s.url))),e||(e=new x(":memory:")),H("node-sqlite",e,t=>{let r=n=>e.prepare(n);return{db:e,query:t.buildQueryFn({all:(n,a=[])=>r(n).all(...a),run:(n,a=[])=>{let{changes:i,lastInsertRowid:o}=r(n).run(...a);return{insertId:t.parseBigInt(o),numAffectedRows:t.parseBigInt(i)}}}),close:()=>e.close(),iterator:(n,a,i=[])=>{if(!n)throw new Error("Only support select in stream()");return r(a).iterate(...i)}}},{...M(s??{},["database","url","name","supports"]),supports:{batching:!1}})}async function de(s,e){await I(s,e)}async function me(s){return await D(s,"utf-8")}export{p as StorageLocalAdapter,j as createApp,k as createHandler,w as localAdapterConfig,ce as nodeSqlite,me as reader,S as registerLocalMediaAdapter,ne as serve,de as writer};