UNPKG

@carere/gel-better-auth

Version:

Adapter for Better Auth and Gel/EdgeDB

28 lines (25 loc) 6.48 kB
import {createAdapter}from'better-auth/adapters';import {pipe,values,map,merge,join,mapKeys,keys,filter,entries,capitalize,mapToObj}from'remeda';import {match}from'ts-pattern';var N="filter_",x="params_",w=(s,d,n,i)=>s==="id"?i==="in"?"array<uuid>":"uuid":match(d).with("string",()=>i==="in"?"array<str>":"str").with("number",()=>i==="in"?"array<int>":"int").with("boolean",()=>i==="in"?"array<bool>":"bool").with("date",()=>i==="in"?"array<datetime>":"datetime").with("string[]",()=>"array<str>").with("number[]",()=>"array<int>").otherwise(()=>capitalize(n??s)),_=s=>match(s).with("eq",()=>"=").with("ne",()=>"!=").with("lt",()=>"<").with("lte",()=>"<=").with("gt",()=>">").with("gte",()=>">=").with("in",()=>"in").otherwise(()=>"like"),A=(s,d)=>{let n=d[s]?.fields;if(!n)throw new Error(`[Gel Adapter] Model ${s} not found in schema`);let i={};for(let[r,e]of Object.entries(n))i[r]=e,e.fieldName&&e.fieldName!==r&&(i[e.fieldName]=e);return i},o=(s,d,n)=>{let i=A(d,n);return pipe(s,map(({connector:r,field:e,operator:t},a)=>{let c=i[e],u=c.fieldName??e;return pipe(a===0?"":r==="AND"?"and ":"or ",l=>{let f=_(t),$=w(e,c.type,u,t),g=c.references!==void 0;return match(t).with("in",()=>`${l}.${g?`${c.references?.model}.id`:e} ${f} array_unpack(<${g?"uuid":$}>$${N}${u})`).otherwise(()=>`${l}.${g?`${c.references?.model}.id`:e} ${f} <${g?"uuid":$}>$${N}${u}`)})}),join(` `))},m=(s,d,n)=>{if(!s)return;let i=A(d,n),r="00000000-0000-0000-0000-000000000000",e=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;return mapToObj(s,t=>{let a=i[t.field],c=t.field==="id",u=a?.references!==void 0,l=match(t.operator).with("contains",()=>`%${t.value}%`).with("starts_with",()=>`${t.value}%`).with("ends_with",()=>`%${t.value}`).otherwise(()=>t.value);return (c||u)&&typeof l=="string"&&!e.test(l)&&(l=r),[`${N}${a?.fieldName??t.field}`,l]})},y=(s,d,n)=>{let i=A(s,d),r=keys(d[s]?.fields??{});return pipe(r,filter(e=>n&&n.length>0?n.includes(i[e]?.fieldName??e):true),map(e=>{let t=`${e}`;return i[e]?.fieldName&&i[e].fieldName!==e&&(t=`${i[e].fieldName} := .${t}`),t}),join(", "))},S=(s,d,n)=>{let i=A(d,n),r=keys(n[d]?.fields??{}),e=keys(s);return pipe(r,filter(t=>e?e.includes(i[t]?.fieldName??t):true),map(t=>`${t} := <${w(t,i[t]?.type??"string",t)}>$${x}${i[t]?.fieldName??t}`),join(", "))},M=s=>mapKeys(s,d=>`${x}${d}`),D=(s,d)=>{let n={},i=[];return {scalarEnumTypes:n,fields:entries(s).map(([r,{type:e,required:t=false,unique:a=false,fieldName:c=r,references:u}])=>{let l=false,f=[],$=match(e).with("string",()=>"str").with("number",()=>"int").with("boolean",()=>"bool").with("date",()=>"datetime").with("string[]",()=>(l=true,"str")).with("number[]",()=>(l=true,"int")).otherwise(g=>{let F=capitalize(c);return n[F]=`scalar type ${F} extending enum<${g.join(", ")}>;`,F});return a&&f.push("constraint exclusive"),u&&($=u.model,c=u.model,i.push(`${r} := .${c}.id;`),u.onDelete==="cascade"&&f.push("on target delete delete source")),pipe(`${c}: ${$}`,g=>l?`multi ${g}`:g,g=>t?`required ${g}`:g,g=>f.length>0?`${g} { ${f.join(`; `)}; }`:g,g=>f.length>0?g:`${g};`)}).concat(i).concat(pipe(d??[],filter(r=>{if(Array.isArray(r))return true;let e=s[r];return e?!e.unique&&!e.references:false}),map(r=>Array.isArray(r)?`index on ((${r.map(e=>`.${e}`).join(", ")}));`:`index on (.${r});`))).join(` `)}};var V=(s,d)=>createAdapter({config:{adapterId:"gel-adapter",adapterName:"Gel Adapter",usePlural:false,debugLogs:d?.debugLogs??false,disableIdGeneration:true,supportsJSON:true,supportsDates:true,supportsBooleans:true,supportsNumericIds:false},adapter:n=>{let i=d?.moduleName??"default";return {create:async({data:r,model:e,select:t})=>{let a=keys(r),c=keys(n.schema[e]?.fields??{}),u=` select ( insert ${i}::${e} { ${pipe(c,filter(l=>a.includes(n.getFieldName({model:e,field:l})??l)),map(l=>{let f=n.getFieldName({model:e,field:l}),$=n.getFieldAttributes({model:e,field:l});if($.references){let g=$.references.model;return `${g} := (select ${i}::${g} filter .id = <uuid>$${f})`}return `${l} := <${w(l,$.type,f)}>$${f}`}),join(", "))} } ) { ${y(e,n.schema,t)} }`;return n.debugLog("[Create] Query: ",u),await s.queryRequiredSingle(u,r)},update:async({model:r,update:e,where:t})=>{let a=`update ${i}::${r}`;return t.length>0&&(a+=` filter ${o(t,r,n.schema)}`),a+=` set { ${S(e,r,n.schema)} }`,a=`select (${a}) { ${y(r,n.schema,[])} } limit 1`,n.debugLog("[Update] Query: ",a),(await s.query(a,{...m(t,r,n.schema),...M(e)}))[0]},updateMany:async({model:r,update:e,where:t})=>{let a=`update ${i}::${r}`;return t.length>0&&(a+=` filter ${o(t,r,n.schema)}`),a+=` set { ${S(e,r,n.schema)} }`,a=`select (${a}) { ${y(r,n.schema,[])} }`,n.debugLog("[Update Many] Query: ",a),(await s.query(a,{...m(t,r,n.schema),...M(e)})).length},delete:async({model:r,where:e})=>{let t=`delete ${i}::${r}`;e&&e.length>0&&(t+=` filter ${o(e,r,n.schema)}`),n.debugLog("[Delete] Query: ",t),await s.query(t,m(e,r,n.schema));},count:async({model:r,where:e})=>{let t=`select ${i}::${r}`;if(e&&e.length>0){let a=o(e,r,n.schema);t+=` filter ${a}`;}return t=`select count ((${t}))`,n.debugLog(t),await s.query(t,m(e,r,n.schema))},findOne:async({model:r,where:e,select:t})=>{let a=` select ${i}::${r} { ${y(r,n.schema,t)} } filter ${o(e,r,n.schema)} limit 1`;return n.debugLog("[Find One] Query: ",a),(await s.query(a,m(e,r,n.schema)))[0]},findMany:async({model:r,where:e,limit:t,sortBy:a,offset:c})=>{let u=`select ${i}::${r} { * }`;if(e&&e.length>0){let l=o(e,r,n.schema);u+=` filter ${l}`;}return a&&(u+=` order by .${a.field} ${a.direction==="desc"?"desc":"asc"}`),c&&(u+=` offset ${c}`),t&&(u+=` limit ${t}`),n.debugLog("[Find Many] Query: ",u),await s.query(u,m(e,r,n.schema))},deleteMany:async({model:r,where:e})=>{let t=`delete ${i}::${r}`;return e&&e.length>0&&(t+=` filter ${o(e,r,n.schema)}`),n.debugLog("[Delete Many] Query: ",t),(await s.query(t,m(e,r,n.schema))).length},createSchema:async({tables:r,file:e=`./dbschema/${i}.gel`})=>{let t={},a=pipe(values(r),map(({modelName:c,fields:u})=>{let l=d?.indexes?.[c],{scalarEnumTypes:f,fields:$}=D(u,l);return t=merge(t,f),` type ${c} { ${$} };`}),join(` `),c=>{let u=values(t).length>0?` ${values(t).join(` `)} `:"";return `module ${i} { ${u}${c} } `});return {path:e,append:false,overwrite:true,code:a}}}}});export{V as gelAdapter};//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map