UNPKG

surreal-better-auth

Version:
7 lines (5 loc) 17.6 kB
'use strict';var surrealdb=require('surrealdb'),adapters=require('better-auth/adapters'),betterAuth=require('better-auth');var se={userId:"user",organizationId:"organization",teamId:"team",inviterId:"user",activeOrganizationId:"organization",activeTeamId:"team"},V={eq:"=",ne:"!=",gt:">",gte:">=",lt:"<",lte:"<="},P={contains:"CONTAINS",starts_with:"starts_with",ends_with:"ends_with"},ie=[{sourceModel:"account",sourceField:"accountId",targetModel:"user",condition:e=>e.providerId==="credential"},{sourceModel:"oauthAccessToken",sourceField:"clientId",targetModel:"oauthApplication"},{sourceModel:"oauthConsent",sourceField:"clientId",targetModel:"oauthApplication"}];function _(e){let r={...e};for(let o of Object.keys(r))r[o]===null&&(r[o]=void 0);return r}function T(e,r){return r instanceof surrealdb.RecordId?r:typeof r=="string"?r.includes(":")?new surrealdb.RecordId(r.split(":")[0],r.split(":")[1]):new surrealdb.RecordId(e,r):new surrealdb.RecordId(e,r)}function O(e){if(e==null)return e;if(e instanceof surrealdb.RecordId)return e.id?`${e.tb}:${e.id}`:e.toString();if(e instanceof Date)return e;if(Array.isArray(e))return e.map(r=>O(r));if(typeof e=="object"){let r={};for(let[o,i]of Object.entries(e))r[o]=O(i);return r}return e}function ae(e,r,o){let i={tableSpecific:{}};if(!e)return i;for(let a in e){let p=e[a];if(!p?.fields)continue;let n=r(a);i.tableSpecific[n]||(i.tableSpecific[n]={});for(let u in p.fields){let b=p.fields[u];if(b?.references?.model){let c=o({model:a,field:u}),g=r(b.references.model);i.tableSpecific[n][c]=g;}}}return i}function U(e,r,o,i,a){if(!e?.debugLogs||e.debugLogs&&typeof e.debugLogs=="object"&&!("isRunningAdapterTests"in e.debugLogs)&&(o==="create"&&!e.debugLogs.create||o==="update"&&!e.debugLogs.update||o==="updateMany"&&!e.debugLogs.updateMany||o==="findOne"&&!e.debugLogs.findOne||o==="findMany"&&!e.debugLogs.findMany||o==="delete"&&!e.debugLogs.delete||o==="deleteMany"&&!e.debugLogs.deleteMany||o==="count"&&!e.debugLogs.count))return;let p=i.build(a),[n,u]=surrealdb.decodeCbor(p),b=n;Object.entries(u).forEach(([$,R])=>{let y=new RegExp(`\\$${$}\\b`,"g"),l;R instanceof surrealdb.RecordId?l=R.toString():typeof R=="string"&&R.includes(":")?l=R:l=JSON.stringify(R),b=b.replace(y,l);});let c={reset:"\x1B[0m",bright:"\x1B[1m",dim:"\x1B[2m",fg:{surreal_pink:"\x1B[38;5;200m",surreal_purple:"\x1B[38;5;93m",yellow:"\x1B[33m",magenta:"\x1B[35m"},bg:{obsidian_violet:"\x1B[48;5;233m",black:"\x1B[40m"}};function g($,R){let y=`${c.fg.magenta}###`,l=`${c.bg.black}${c.fg.yellow}[0/#]${c.reset}`,E=`${c.bright}${o}`,S=`${c.dim}(PreparedQuery)${c.reset}:`,m=" ",t=`${c.bg.obsidian_violet}`;return t+=m,t+=`${c.fg.surreal_purple}[${$}]`,t+=` ${c.fg.surreal_pink}${R}`,t+=m,t+=`${c.reset}`,`${y} ${l} ${E} ${S} ${t} `}r(`${g("SurrealQL",b)}`);}var Y={modelNotFound:(e,r)=>{r?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Model '${e}' not found in schema, skipping operation `);},fieldMappingSkipped:(e,r,o)=>{o?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Skipping field mapping rule for '${e}': ${r} `);},unsupportedOperator:(e,r)=>{r?.debugLogs&&betterAuth.logger.warn(`[surreal-better-auth]: Unknown operator '${e}', falling back to equality comparison `);}};function de(e,r,o,i,a,p,n){let u=i(e),b=a({model:u,field:r}),c=se[b];if(c)try{let $=p(c);return n?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Found default reference: ${e}.${r} -> ${$} `),$}catch{Y.modelNotFound(c,n);}let g=o.tableSpecific[e]?.[r];return g&&n?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Found table-specific reference: ${e}.${r} -> ${g} `),g||null}function ue(e,r,o){let i={};for(let a of ie)try{let p=e(a.sourceModel),n=e(a.targetModel),u=r({model:a.sourceModel,field:a.sourceField});i[p]||(i[p]={}),i[p][u]={recordTable:n,condition:a.condition},o?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Registered field mapping: ${p}.${u} -> to record ${n} `);}catch(p){let n=p;Y.fieldMappingSkipped(`${a.sourceModel}.${a.sourceField}`,n.message,o);}return i}function ce(e,r,o,i,a){let p={...r},n=i();a?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Serializing record ID fields for table: ${e} `,{fieldCount:Object.keys(p).length,hasSpecialCases:!!n[e]});for(let u in p){let b=p[u];if(typeof b!="string"||!b)continue;let c=n[e]?.[u];if(c)if(!c.condition||c.condition(p)){let $=T(c.recordTable,b);p[u]=$,a?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Applied special case mapping: ${e}.${u} = "${b}" -> "${$}" `);}else a?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Special case condition not met for: ${e}.${u} `);else {let g=o(e,u);if(g){let $=T(g,b);p[u]=$,a?.debugLogs&&betterAuth.logger.debug(`[surreal-better-auth]: Applied default reference mapping: ${e}.${u} = "${b}" -> "${$}" `);}}}return p}function le(e,r,o){if(!e||e.length===0)return null;let i=o(r),a=e.findIndex(n=>n.field==="id"&&n.operator==="eq");if(a!==-1){let n=e[a],u=T(i,n.value),b=e.filter((c,g)=>g!==a);return {recordIds:[u],remainingWhere:b}}let p=e.findIndex(n=>n.field==="id"&&n.operator==="in"&&Array.isArray(n.value));if(p!==-1){let u=e[p].value.map(c=>T(i,c)),b=e.filter((c,g)=>g!==p);return {recordIds:u,remainingWhere:b}}return null}function H(e={},r){let{sortBy:o,limit:i,offset:a,groupAll:p,returnAfter:n,returnFields:u,limitOne:b,model:c}=e,g="";if(o&&c&&r){let $=r({model:c,field:o.field}),R=o.direction==="desc"?"DESC":"ASC";g+=` ORDER BY ${$} ${R}`;}return b?g+=" LIMIT 1":typeof i=="number"&&(g+=` LIMIT ${i}`),typeof a=="number"&&(g+=` START AT ${a}`),p&&(g+=" GROUP ALL"),n?g+=" RETURN AFTER":u&&(g+=` RETURN ${u}`),g}function pe(e,r,{where:o,model:i},a,p,n,u){if(!o||o.length===0)return "";let b=[],c=a(i);return o.forEach((g,$)=>{let{field:R,value:y,operator:l="eq",connector:E="AND"}=g;if(l==="in"&&Array.isArray(y)&&y.length===0||l==="not_in"&&Array.isArray(y)&&y.length===0)return;let S=p({model:i,field:R}),m=`where_${$}`,t=new surrealdb.Gap;e[m]=t;let s="";if(l==="in"){s=`${S} IN $${m}`;let d=Array.isArray(y)?y:[y],f=d;if(R==="id")f=d.map(h=>T(c,h));else {let h=n(c,S);h&&(f=d.map(I=>typeof I=="string"?T(h,I):I));}r.push(t.fill(f));}else if(l==="not_in"){s=`${S} NOT IN $${m}`;let d=Array.isArray(y)?y:[y],f=d;if(R==="id")f=d.map(h=>T(c,h));else {let h=n(c,S);h&&(f=d.map(I=>typeof I=="string"?T(h,I):I));}r.push(t.fill(f));}else if(l in V)if(s=`${S} ${V[l]} $${m}`,R==="id"){let d=T(c,y);r.push(t.fill(d));}else {let d=n(c,S);if(d&&typeof y=="string"){let f=T(d,y);r.push(t.fill(f));}else r.push(t.fill(y));}else l in P?(P[l]==="CONTAINS"?s=`${S} CONTAINS $${m}`:s=`string::${P[l]}(${S}, $${m})`,r.push(t.fill(y))):(s=`${S} = $${m}`,r.push(t.fill(y)),Y.unsupportedOperator(l,u));b.length>0?b.push(` ${E.toUpperCase()} ${s}`):b.push(s);}),b.length===0?"":` WHERE ${b.join("")}`}function fe(e,r,o,i,a,p){let n,u=i??(p?p():null);if(u)n=T(e,u).toString();else switch(o?.idGenerator){case "surreal.ULID":n=`type::thing('${e}', rand::ulid())`;break;case "surreal.UUID":n=`type::thing('${e}', rand::uuid())`;break;case "surreal.UUIDv4":n=`type::thing('${e}', rand::uuid::v4())`;break;case "surreal.UUIDv7":n=`type::thing('${e}', rand::uuid::v7())`;break;case "surreal.guid":n=`type::thing('${e}', rand::guid())`;break;default:n=`type::table('${e}')`;break}let b=H({returnFields:a}),c=`CREATE ${n} CONTENT $content${b}`,g={content:new surrealdb.Gap},$=[g.content.fill(r)];return {query:new surrealdb.PreparedQuery(c,g),fills:$}}function J(e){let{file:r,tables:o,getModelName:i,getFieldName:a,getReferencedModel:p}=e,n=[],u=new Date,b=`${u.getUTCFullYear()}-${String(u.getUTCMonth()+1).padStart(2,"0")}-${String(u.getUTCDate()).padStart(2,"0")} at ${String(u.getUTCHours()).padStart(2,"0")}:${String(u.getUTCMinutes()).padStart(2,"0")}:${String(u.getUTCSeconds()).padStart(2,"0")} UTC`;n.push("-- \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557","-- \u2551 SurrealDB Better Auth Schema \u2551","-- \u255F\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2562","-- \u2551 This schema was auto-generated for BetterAuth integration \u2551","-- \u2551 Adapter: surreal-better-auth \u2551","-- \u2551 Repo: https://github.com/oskar-gmerek/surreal-better-auth \u2551","-- \u2551 Author: Oskar Gmerek \u2551","-- \u2551 \u2551",`-- \u2551 Generation Date: ${b.padEnd(53)}\u2551`,"-- \u255F\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2562","-- \u2551 Warning: It is strongly recommended to manually review the schema \u2551","-- \u2551 after each generation to ensure it fully meets your \u2551","-- \u2551 project's specific requirements. \u2551","-- \u255F\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2562","-- \u2551 Tip: The easiest way to apply this schema to your db is to copy its \u2551","-- \u2551 contents and paste them directly into the Surrealist. \u2551","-- \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D","","","");function c(R,y=76){let l=y-8,E=R.padEnd(l," "),S=`-- \u2554${"\u2550".repeat(y-4)}\u2557`,m=`-- \u2551 ${E} \u2551`,t=`-- \u255A${"\u2550".repeat(y-4)}\u255D`;return [S,m,t]}function g(R,y,l){try{let m=i("account"),t=i("user"),s=a({model:"account",field:"accountId"});if(R===m&&y===s)return `record<${t}> | string`}catch{}try{let m=i("oauthAccessToken"),t=i("oauthApplication"),s=a({model:"oauthAccessToken",field:"clientId"});if(R===m&&y===s)return `record<${t}>`}catch{}try{let m=i("oauthConsent"),t=i("oauthApplication"),s=a({model:"oauthConsent",field:"clientId"});if(R===m&&y===s)return `record<${t}>`}catch{}let E=p(R,y);return E?`record<${E}>`:{boolean:"bool",date:"datetime"}[l||""]||l||"any"}for(let[R,y]of Object.entries(o)){let l=i(R);if(!y.disableMigrations){n.push(...c(`TABLE: ${l}`)),n.push(`DEFINE TABLE OVERWRITE ${l} SCHEMAFULL;`),n.push(""),n.push(`DEFINE FIELD OVERWRITE id ON TABLE ${l} TYPE record<${l}>;`);for(let[E,S]of Object.entries(y.fields)){let m=a({model:R,field:E}),t=g(l,m,S.type?.toString()),s=S.required===false?`option<${t}>`:t;n.push(`DEFINE FIELD OVERWRITE ${m} ON TABLE ${l} TYPE ${s};`);}n.push(""),n.push(`DEFINE INDEX OVERWRITE idx_${l}_id ON ${l} COLUMNS id UNIQUE;`);for(let[E,S]of Object.entries(y.fields)){let m=a({model:R,field:E}),s={user:"email",account:"userId",session:["userId","token"],verification:"identifier",invitation:["email","organizationId"],member:["userId","organizationId"],organization:"slug",passkey:"userId",twoFactor:"secret"}[R];s&&(Array.isArray(s)&&s.includes(E)||s===E)&&n.push(`DEFINE INDEX OVERWRITE idx_${l}_${m} ON ${l} COLUMNS ${m}${S.unique?" UNIQUE":""};`);}n.push("");}}return {path:r??"schema.surql",code:n.join(` `),overwrite:true}}var Ee=(e,r)=>adapters.createAdapter({config:{adapterId:"surrealdb_adapter",adapterName:"surreal-better-auth",usePlural:r?.usePlural??false,debugLogs:r?.debugLogs??false,supportsNumericIds:false,supportsBooleans:true,supportsDates:true,supportsJSON:true,customIdGenerator:r?.idGenerator?.startsWith("sdk.")?({model:o})=>{switch(r?.debugLogs&&betterAuth.logger.info(`[surreal-better-auth]: Generating custom ID for model: ${o} using ${r.idGenerator} `),r.idGenerator){case "sdk.UUIDv4":return surrealdb.Uuid.v4().toString();case "sdk.UUIDv7":return surrealdb.Uuid.v7().toString();default:throw new Error(`Invalid ID generator type: ${r.idGenerator}. Supported types: "sdk.UUIDv4", "sdk.UUIDv7", "surreal", "surreal.ULID", "surreal.UUID", "surreal.UUIDv4", "surreal.UUIDv7", "surreal.guid"`)}}:void 0,disableIdGeneration:r?.idGenerator?.startsWith("surreal")??false,customTransformOutput({data:o}){return o===void 0?null:O(o)}},adapter:({options:o,getModelName:i,getFieldName:a,getDefaultModelName:p,getDefaultFieldName:n,debugLog:u})=>{let b=ae(o?.schema?.tables,i,a),c=o?.advanced?.database?.generateId,g=(t,s)=>de(t,s,b,p,n,i,r),$=()=>ue(i,a,r),R=(t,s)=>ce(t,s,g,$,r),y=(t,s)=>le(t,s,i),l=(t={})=>H(t,a),E=(t,s,{where:d,model:f})=>pe(t,s,{where:d,model:f},i,a,g,r),S=(t,s,d,f)=>fe(t,s,r,d,f,c);async function m(t){let{method:s,model:d,where:f,baseQuery:h,directRecordQuery:I,content:A,suffix:M="",processResult:x=q=>q,returnCount:F=false,singleRecord:C=false}=t,N=y(f,d);if(N&&I){let{recordIds:q,remainingWhere:ee}=N,re=I(q);if(ee.length===0){let j={},v=[];A!==void 0&&(j.content=new surrealdb.Gap,v.push(j.content.fill(A)));let ne=new surrealdb.PreparedQuery(re+M,j);U(r,u,s,ne,v);let z=await e.query(ne,v);return F?z[0]?.length||0:x(z[0])}let G={},w=[];A!==void 0&&(G.content=new surrealdb.Gap,w.push(G.content.fill(A)));let be=E(G,w,{where:ee,model:d}),Re=re+be+M,te=new surrealdb.PreparedQuery(Re,G);U(r,u,s,te,w);let W=await e.query(te,w);return F?W[0]?.length||0:x(W[0])}let Q={},k=[];A!==void 0&&(Q.content=new surrealdb.Gap,k.push(Q.content.fill(A)));let ye=E(Q,k,{where:f||[],model:d}),me=h+ye+M,Z=new surrealdb.PreparedQuery(me,Q);U(r,u,s,Z,k);let B=await e.query(Z,k);return F?B[0]?.length||0:x(B[0])}return {async create({model:t,data:s,select:d}){let f=i(t),h=R(f,_(s)),I=(r?.allowPassingId||r?.idGenerator?.startsWith("sdk."))&&h.id?h.id:void 0;h.id=void 0;let A;if(d&&Array.isArray(d)&&d.length>0){let C=d.map(N=>a({model:t,field:N}));C.includes("id")||C.unshift("id"),A=C.join(", ");}let{query:M,fills:x}=S(f,h,I,A);U(r,u,"create",M,x);let F=await e.query(M,x);return O(F[0][0])},async findOne({model:t,where:s,select:d}){let f=i(t),h=d?typeof d=="string"?a({model:t,field:d}):d.map(I=>a({model:t,field:I})).join(", "):"*";return m({method:"findOne",model:t,where:s,baseQuery:`SELECT ${h} FROM ONLY ${f}`,directRecordQuery:I=>`SELECT ${h} FROM ONLY ${I[0].toString()}`,suffix:l({limitOne:true}),processResult:I=>O(I)||null,singleRecord:true})},async findMany({model:t,where:s,limit:d,offset:f,sortBy:h}){let I=i(t),A="*";return m({method:"findMany",model:t,where:s,baseQuery:`SELECT ${A} FROM ${I}`,directRecordQuery:M=>`SELECT ${A} FROM [${M.map(x=>x.toString()).join(", ")}]`,suffix:l({sortBy:h,limit:d,offset:f,model:t}),processResult:O})},async count({model:t,where:s}){let d=i(t);return m({method:"count",model:t,where:s,baseQuery:`SELECT count() FROM ${d}`,directRecordQuery:f=>`SELECT count() FROM [${f.map(h=>h.toString()).join(", ")}]`,suffix:l({groupAll:true}),processResult:f=>f[0].count||0,singleRecord:true})},async update({model:t,where:s,update:d}){let f=i(t),h=R(f,_(d));return m({method:"update",model:t,where:s,baseQuery:`UPDATE ONLY ${f} MERGE $content`,directRecordQuery:I=>`UPDATE ONLY ${I[0].toString()} MERGE $content`,content:h,suffix:l({returnAfter:true}),processResult:I=>O(I)||null,singleRecord:true})},async updateMany({model:t,where:s,update:d}){let f=i(t),h=R(f,_(d));return m({method:"updateMany",model:t,where:s,baseQuery:`UPDATE ${f} MERGE $content`,directRecordQuery:I=>`UPDATE [${I.map(A=>A.toString()).join(", ")}] MERGE $content`,content:h,returnCount:true})},async delete({model:t,where:s}){let d=i(t);return m({method:"delete",model:t,where:s,baseQuery:`DELETE ${d}`,directRecordQuery:f=>`DELETE ${f[0].toString()}`,processResult:()=>{}})},async deleteMany({model:t,where:s}){let d=i(t);return m({method:"deleteMany",model:t,where:s,baseQuery:`DELETE ${d}`,directRecordQuery:f=>`DELETE [${f.map(h=>h.toString()).join(", ")}]`,returnCount:true})},async createSchema({file:t,tables:s}){return J({file:t,tables:s,getModelName:i,getFieldName:a,getReferencedModel:g})}}}});exports.generateSchema=J;exports.surrealdbAdapter=Ee;//# sourceMappingURL=index.cjs.map //# sourceMappingURL=index.cjs.map