refine-sql
Version:
Multi-runtime SQL data provider for Refine - Supports Cloudflare D1, Node.js 22.5+ native SQLite, and Bun 1.2+ native SQLite with zero bundle overhead
2 lines • 5.01 kB
JavaScript
var m=class{db;runtime;initPromise;constructor(s){if(!s)throw new Error("Database instance or path is required");if(typeof s=="string")if(this.runtime=this.e(),this.runtime==="bun-sqlite")try{this.db=new globalThis.Bun.sqlite(s);}catch(t){throw new Error(`Failed to initialize Bun SQLite: ${t instanceof Error?t.message:"Unknown"}`)}else this.initPromise=this.a(s);else this.runtime="d1",this.db=s;}async t(){this.initPromise&&(await this.initPromise,this.initPromise=void 0);}e(){if(typeof globalThis<"u"&&"Bun"in globalThis&&globalThis.Bun)return "bun-sqlite";if(typeof globalThis<"u"&&"process"in globalThis&&globalThis.process)return "node-sqlite";throw new Error("SQLite file paths are only supported in Node.js 22.5+ or Bun 1.2+ environments")}async a(s){try{let t=await import('sqlite');this.db=new t.DatabaseSync(s);}catch(t){throw new Error(`Failed to initialize Node.js SQLite: ${t instanceof Error?t.message:"Unknown"}`)}}async query(s,t=[]){if(await this.t(),this.runtime==="d1"){let e=this.db.prepare(s);return (await(t.length?e.bind(...t):e).all()).results||[]}return this.db.prepare(s).all(...t)}async queryFirst(s,t=[]){if(await this.t(),this.runtime==="d1"){let e=this.db.prepare(s);return await(t.length?e.bind(...t):e).first()}return this.db.prepare(s).get(...t)}async execute(s,t=[]){if(await this.t(),this.runtime==="d1"){let a=this.db.prepare(s),n=await(t.length?a.bind(...t):a).run();return {changes:n.meta.changes,lastInsertRowid:n.meta.last_row_id}}let e=this.db.prepare(s).run(...t);return {changes:e.changes||0,lastInsertRowid:e.lastInsertRowid}}async batch(s){if(await this.t(),this.runtime==="d1"){let t=s.map(({sql:a,params:r=[]})=>{let n=this.db.prepare(a);return r.length?n.bind(...r):n}),e=await this.db.batch(t);return e?e.map(a=>a.results||[]):[]}return s.map(({sql:t,params:e=[]})=>this.db.prepare(t).run(...e))}close(){this.runtime!=="d1"&&this.db?.close&&this.db.close();}getType(){return this.runtime}};var E=d=>({ne:"IS NOT",gte:">=",lte:"<=",contains:"LIKE",eq:"IS",gt:">",lt:"<"})[d]||"=",b=d=>d?.length?d.filter(t=>"field"in t).map(t=>{let{field:e,operator:a,value:r}=t;if(a==="or"||a==="and")throw new Error(`Operator '${a}' not supported`);return `${e} ${E(a)} '${r}'`}).join(" AND "):"",w=d=>{if(d?.length)return d.map(s=>`${s.field} ${s.order}`).join(", ")},f=d=>{let s=()=>new m(d);return {getList:async({resource:t,pagination:e,filters:a,sorters:r})=>{let n=s(),{current:i=1,pageSize:o=10}=e??{},c=b(a),u=w(r),l=`SELECT * FROM ${t}`;c&&(l+=` WHERE ${c}`),u&&(l+=` ORDER BY ${u}`),e&&(l+=` LIMIT ${o} OFFSET ${(i-1)*o}`);let y=await n.query(l),p=`SELECT COUNT(*) as count FROM ${t}`;c&&(p+=` WHERE ${c}`);let h=await n.queryFirst(p);return {data:y,total:h?.count||0}},getMany:async({resource:t,ids:e})=>{let a=s(),r=e.map(()=>"?").join(", ");return {data:await a.query(`SELECT * FROM ${t} WHERE id IN (${r})`,e)}},create:async({resource:t,variables:e})=>{let a=s(),r=Object.keys(e||{}),n=Object.values(e||{}),i=r.map(()=>"?").join(", "),o=await a.execute(`INSERT INTO ${t} (${r.join(", ")}) VALUES (${i})`,n);return {data:await a.queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[o.lastInsertRowid])}},update:async({resource:t,id:e,variables:a})=>{let r=s(),n=Object.keys(a||{}),i=Object.values(a||{}),o=n.map(u=>`${u} = ?`).join(", ");return await r.execute(`UPDATE ${t} SET ${o} WHERE id = ?`,[...i,e]),{data:await r.queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[e])}},getOne:async({resource:t,id:e})=>({data:await s().queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[e])}),deleteOne:async({resource:t,id:e})=>{let a=s(),r=await a.queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[e]);return await a.execute(`DELETE FROM ${t} WHERE id = ?`,[e]),{data:r}},createMany:async({resource:t,variables:e})=>{let a=s();if(!e?.length)return {data:[]};let r=[];for(let n of e){let i=Object.keys(n),o=Object.values(n),c=i.map(()=>"?").join(", "),u=await a.execute(`INSERT INTO ${t} (${i.join(", ")}) VALUES (${c})`,o),l=await a.queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[u.lastInsertRowid]);r.push(l);}return {data:r}},updateMany:async({resource:t,ids:e,variables:a})=>{let r=s();if(!e?.length)return {data:[]};let n=[],i=Object.keys(a||{}),o=Object.values(a||{}),c=i.map(u=>`${u} = ?`).join(", ");for(let u of e){await r.execute(`UPDATE ${t} SET ${c} WHERE id = ?`,[...o,u]);let l=await r.queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[u]);l&&n.push(l);}return {data:n}},deleteMany:async({resource:t,ids:e})=>{let a=s();if(!e?.length)return {data:[]};let r=[];for(let n of e){let i=await a.queryFirst(`SELECT * FROM ${t} WHERE id = ?`,[n]);i&&(await a.execute(`DELETE FROM ${t} WHERE id = ?`,[n]),r.push(i));}return {data:r}},getApiUrl:()=>"/api",custom:async({url:t,method:e,payload:a})=>{let r=s(),n="",i=[];if(a&&typeof a=="object"&&"sql"in a?(n=a.sql,i=a.params||[]):t.includes("sql=")&&(n=new URL(t,"http://localhost").searchParams.get("sql")||""),!n)throw new Error("No SQL provided");return {data:e==="get"?await r.query(n,i):await r.execute(n,i)}}}};
export{f as dataProvider};