better-auth 0.2.2 → 0.2.3-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access.js +1 -1
- package/dist/adapters.d.ts +32 -6
- package/dist/adapters.js +22 -1
- package/dist/api.d.ts +2 -4
- package/dist/api.js +3 -3
- package/dist/cli.js +4 -2
- package/dist/client/plugins.d.ts +5 -7
- package/dist/client/plugins.js +2 -2
- package/dist/client.d.ts +3 -5
- package/dist/client.js +1 -1
- package/dist/index-CE92ti2Z.d.ts +827 -0
- package/dist/{index-DsEvbKjm.d.ts → index-CmzUOocy.d.ts} +10 -2
- package/dist/{index-D_ohe9r9.d.ts → index-gO-yM4kI.d.ts} +77 -120
- package/dist/index.d.ts +4 -6
- package/dist/index.js +5 -3
- package/dist/next-js.d.ts +2 -4
- package/dist/next-js.js +1 -1
- package/dist/node.d.ts +4 -6
- package/dist/plugins.d.ts +6 -8
- package/dist/plugins.js +3 -3
- package/dist/react.d.ts +3 -5
- package/dist/react.js +1 -1
- package/dist/social.d.ts +3 -742
- package/dist/social.js +2 -2
- package/dist/solid-start.d.ts +4 -6
- package/dist/solid-start.js +1 -1
- package/dist/solid.d.ts +3 -5
- package/dist/solid.js +1 -1
- package/dist/svelte-kit.d.ts +4 -6
- package/dist/svelte.d.ts +3 -5
- package/dist/svelte.js +1 -1
- package/dist/types.d.ts +3 -5
- package/dist/utils.d.ts +5 -7
- package/dist/utils.js +2 -2
- package/dist/vue.d.ts +3 -5
- package/dist/vue.js +1 -1
- package/package.json +6 -4
- package/dist/.DS_Store +0 -0
- package/dist/adapter-D-m9-hQp.d.ts +0 -54
- package/dist/schema-D9o3OF80.d.ts +0 -88
package/dist/access.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var a=class extends Error{path;constructor(e,n){super(e),this.path=n}},c=class{constructor(e){this.s=e;this.statements=e}statements;newRole(e){return new i(e)}},i=class s{statements;constructor(e){this.statements=e}authorize(e,n){for(let[t,o]of Object.entries(e)){let r=this.statements[t];if(!r)return{success:!1,error:`You are not allowed to access resource: ${t}`};let p=n==="OR"?o.some(m=>r.includes(m)):o.every(m=>r.includes(m));return p?{success:p}:{success:!1,error:`unauthorized to access resource "${t}"`}}return{success:!1,error:"Not authorized"}}static fromString(e){let n=JSON.parse(e);if(typeof n!="object")throw new a("statements is not an object",".");for(let[t,o]of Object.entries(n)){if(typeof t!="string")throw new a("invalid resource identifier",t);if(!Array.isArray(o))throw new a("actions is not an array",t);for(let r=0;r<o.length;r++)if(typeof o[r]!="string")throw new a("action is not a string",`${t}[${r}]`)}return new s(n)}toString(){return JSON.stringify(this.statements)}};var l=s=>new c(s),d={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},u=l(d),S=u.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),f=u.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),x=u.newRole({organization:[],member:[],invitation:[]}),b={admin:S,owner:f,member:x};var T=s=>i.fromString(s??"");export{c as AccessControl,a as ParsingError,i as Role,S as adminAc,l as createAccessControl,u as defaultAc,b as defaultRoles,d as defaultStatements,x as memberAc,f as ownerAc,T as permissionFromString};
|
package/dist/adapters.d.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '
|
|
1
|
+
import { f as Adapter, W as Where, F as FieldAttribute } from './index-gO-yM4kI.js';
|
|
2
|
+
import { Kysely } from 'kysely';
|
|
3
|
+
import './index-CE92ti2Z.js';
|
|
4
|
+
import 'arctic';
|
|
3
5
|
import 'zod';
|
|
6
|
+
import './helper-C1ihmerM.js';
|
|
7
|
+
import 'better-call';
|
|
4
8
|
|
|
5
|
-
declare const prismaAdapter: (
|
|
9
|
+
declare const prismaAdapter: ({ db: prisma, provider, }: {
|
|
10
|
+
db: any;
|
|
11
|
+
provider: "sqlite" | "cockroachdb" | "mysql" | "postgresql" | "sqlserver";
|
|
12
|
+
}) => Adapter;
|
|
6
13
|
|
|
7
14
|
interface DrizzleAdapterOptions {
|
|
8
|
-
schema
|
|
15
|
+
schema?: Record<string, any>;
|
|
16
|
+
provider: "pg" | "mysql" | "sqlite";
|
|
9
17
|
}
|
|
10
|
-
|
|
18
|
+
interface DB {
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}
|
|
21
|
+
declare const drizzleAdapter: (db: DB, options: DrizzleAdapterOptions) => Adapter;
|
|
11
22
|
|
|
12
23
|
declare const mongodbAdapter: (mongo: any) => {
|
|
24
|
+
id: string;
|
|
13
25
|
create<T, R = T>(data: {
|
|
14
26
|
model: string;
|
|
15
27
|
data: T;
|
|
@@ -35,4 +47,18 @@ declare const mongodbAdapter: (mongo: any) => {
|
|
|
35
47
|
}): Promise<any>;
|
|
36
48
|
};
|
|
37
49
|
|
|
38
|
-
|
|
50
|
+
interface KyselyAdapterConfig {
|
|
51
|
+
/**
|
|
52
|
+
* Transform dates and booleans for sqlite.
|
|
53
|
+
*/
|
|
54
|
+
transform?: {
|
|
55
|
+
schema: {
|
|
56
|
+
[table: string]: Record<string, FieldAttribute>;
|
|
57
|
+
};
|
|
58
|
+
boolean: boolean;
|
|
59
|
+
date: boolean;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
declare const kyselyAdapter: (db: Kysely<any>, config?: KyselyAdapterConfig) => Adapter;
|
|
63
|
+
|
|
64
|
+
export { type DrizzleAdapterOptions, type KyselyAdapterConfig, drizzleAdapter, kyselyAdapter, mongodbAdapter, prismaAdapter };
|
package/dist/adapters.js
CHANGED
|
@@ -1 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import{existsSync as K}from"fs";import E from"path";var C=e=>{let o=e.plugins?.reduce((c,l)=>{let d=l.schema;if(!d)return c;for(let[u,p]of Object.entries(d))c[u]={fields:{...c[u]?.fields,...p.fields},tableName:u};return c},{}),a=e.rateLimit?.storage==="database",r={rateLimit:{tableName:e.rateLimit?.tableName||"rateLimit",fields:{key:{type:"string"},count:{type:"number"},lastRequest:{type:"number"}}}},{user:s,session:t,account:n,...i}=o||{};return{user:{tableName:e.user?.modelName||"user",fields:{name:{type:"string",required:!0},email:{type:"string",unique:!0,required:!0},emailVerified:{type:"boolean",defaultValue:()=>!1,required:!0},image:{type:"string",required:!1},createdAt:{type:"date",defaultValue:()=>new Date,required:!0},updatedAt:{type:"date",defaultValue:()=>new Date,required:!0},...s?.fields},order:0},session:{tableName:e.session?.modelName||"session",fields:{expiresAt:{type:"date",required:!0},ipAddress:{type:"string",required:!1},userAgent:{type:"string",required:!1},userId:{type:"string",references:{model:"user",field:"id",onDelete:"cascade"},required:!0},...t?.fields},order:1},account:{tableName:e.account?.modelName||"account",fields:{accountId:{type:"string",required:!0},providerId:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id",onDelete:"cascade"},required:!0},accessToken:{type:"string",required:!1},refreshToken:{type:"string",required:!1},idToken:{type:"string",required:!1},expiresAt:{type:"date",required:!1},password:{type:"string",required:!1},...n?.fields},order:2},...i,...a?r:{}}};import W from"fs/promises";import{produceSchema as H}from"@mrleebo/prisma-ast";var x=class extends Error{constructor(o,a,r){super(o),this.name="BetterAuthError",this.message=o,this.cause=a}};import{TimeSpan as he}from"oslo";import{alphabet as ke,generateRandomString as Ce}from"oslo/crypto";import{createConsola as V}from"consola";var k=V({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),G=e=>({log:(...o)=>{!e?.disabled&&k.log("",...o)},error:(...o)=>{!e?.disabled&&k.error("",...o)},warn:(...o)=>{!e?.disabled&&k.warn("",...o)},info:(...o)=>{!e?.disabled&&k.info("",...o)},debug:(...o)=>{!e?.disabled&&k.debug("",...o)},box:(...o)=>{!e?.disabled&&k.box("",...o)},success:(...o)=>{!e?.disabled&&k.success("",...o)},break:(...o)=>{!e?.disabled&&console.log(`
|
|
2
|
+
`)}}),N=G();function D(e){return e.charAt(0).toUpperCase()+e.slice(1)}import{generateState as De}from"oslo/oauth2";import{z as Pe}from"zod";function O(e){if(!e)return{};if(e.length===1){let t=e[0];return t?{[t.field]:t.value}:void 0}let o=e.filter(t=>t.connector==="AND"||!t.connector),a=e.filter(t=>t.connector==="OR"),r=o.map(t=>({[t.field]:t.operator==="eq"||!t.operator?t.value:{[t.operator]:t.value}})),s=a.map(t=>({[t.field]:{[t.operator||"eq"]:t.value}}));return{AND:r.length?r:void 0,OR:s.length?s:void 0}}var nt=({db:e,provider:o})=>{let a=e;return{id:"prisma",async create(r){let{model:s,data:t,select:n}=r;return await a[s].create({data:t,...n?.length?{select:n.reduce((i,c)=>({...i,[c]:!0}),{})}:{}})},async findOne(r){let{model:s,where:t,select:n}=r,i=O(t);return await a[s].findFirst({where:i,...n?.length?{select:n.reduce((c,l)=>({...c,[l]:!0}),{})}:{}})},async findMany(r){let{model:s,where:t}=r,n=O(t);return await a[s].findMany({where:n})},async update(r){let{model:s,where:t,update:n}=r,i=O(t);return await a[s].update({where:i,data:n})},async delete(r){let{model:s,where:t}=r,n=O(t);return await a[s].delete({where:n})},async createSchema(r,s){let t=C(r),n=s||"./prisma/schema.prisma",i=K(E.join(process.cwd(),n)),c="";return i?c=await W.readFile(E.join(process.cwd(),n),"utf-8"):c=X(o),{code:H(c,d=>{for(let p in t){let b=function(y,h){if(y==="string")return h?"String?":"String";if(y==="number")return h?"Int?":"Int";if(y==="boolean")return h?"Boolean?":"Boolean";if(y==="date")return h?"DateTime?":"DateTime"};var u=b;let g=t[p].fields,m=t[p].tableName,f=d.findByType("model",{name:m});!f&&d.model(m).field("id","String").attribute("id");for(let y in g){let h=g[y];if(f){let A=d.findByType("field",{name:y,within:f.properties});if(console.log(y,"exists"),A)continue}d.model(m).field(y,b(h.type,!h.required)),h.unique&&d.model(m).blockAttribute(`unique([${y}])`),h.references&&d.model(m).field(D(h.references.model),h.references.model).attribute(`relation(fields: [${y}], references: [${h.references.field}], onDelete: Cascade)`)}}}),fileName:n}}}},X=e=>`generator client {
|
|
3
|
+
provider = "prisma-client-js"
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
datasource db {
|
|
7
|
+
provider = "${e}"
|
|
8
|
+
url = ${e==="sqlite"?'"file:./dev.db"':'env("DATABASE_URL")'}
|
|
9
|
+
}`;import{and as Q,eq as B,or as J}from"drizzle-orm";import*as P from"prettier";import{existsSync as Y}from"fs";import Z from"fs/promises";function T(e,o){let a=Object.keys(o).find(r=>{let s=o[r].name;return s===s});if(!a)throw new Error("Model not found");return o[a]}function q(e,o){if(!e)return[];if(e.length===1){let i=e[0];return i?[B(o[i.field],i.value)]:[]}let a=e.filter(i=>i.connector==="AND"||!i.connector),r=e.filter(i=>i.connector==="OR"),s=Q(...a.map(i=>B(o[i.field],i.value))),t=J(...r.map(i=>B(o[i.field],i.value))),n=[];return a.length&&n.push(s),r.length&&n.push(t),n}var ut=(e,o)=>{let a=o?.schema||e._.schema;if(!a)throw new x("Drizzle adapter failed to initialize. Schema not found. Please provide a schema object in the adapter options object.");let r=o?.provider;return{id:"drizzle",async create(s){let{model:t,data:n}=s,i=T(t,a);return(await e.insert(i).values(n).returning())[0]},async findOne(s){let{model:t,where:n,select:i}=s,c=T(t,a),l=q(n,c),d=null;return i?.length?d=await e.select(...i.map(u=>({[u]:c[u]}))).from(c).where(...l):d=await e.select().from(c).where(...l),d.length?d[0]:null},async findMany(s){let{model:t,where:n}=s,i=T(t,a),c=n?q(n,i):[];return await e.select().from(i).findMany(...c)},async update(s){let{model:t,where:n,update:i}=s,c=T(t,a),l=q(n,c);return(await e.update(c).set(i).where(...l).returning())[0]},async delete(s){let{model:t,where:n}=s,i=T(t,a),c=q(n,i);return(await e.delete(i).where(...c))[0]},async createSchema(s,t){let n=C(s),i=t||"./schema.ts",c=r!=="sqlite"?"timestamp, boolean":"",l=r==="mysql"?"int":"integer",d="",u=Y(i);if(u){let m=await Z.readFile(i,"utf-8");m.includes("import")?d=m:d=`import { ${r}Table, text, ${l}, ${c} } from "drizzle-orm/${r}-core";
|
|
10
|
+
`}else d=`import { ${r}Table, text, ${l}, ${c} } from "drizzle-orm/${r}-core";
|
|
11
|
+
`;for(let m in n){let y=function(A,w){if(w==="string")return`text('${A}')`;if(w==="number")return`${l}('${A}')`;if(w==="boolean")return r==="sqlite"?`integer('${A}', {
|
|
12
|
+
mode: "boolean"
|
|
13
|
+
})`:`boolean('${A}')`;if(w==="date")return r==="sqlite"?`integer('${A}', {
|
|
14
|
+
mode: "timestamp"
|
|
15
|
+
})`:`timestamp('${A}')`};var g=y;let b=n[m].tableName,f=n[m].fields,h=`export const ${m} = ${r}Table("${b}", {
|
|
16
|
+
id: text("id").primaryKey(),
|
|
17
|
+
${Object.keys(f).map(A=>{let w=f[A];return`${A}: ${y(A,w.type)}${w.required?".notNull()":""}${w.unique?".unique()":""}${w.references?`.references(()=> ${w.references.model}.${w.references.field})`:""}`}).join()}
|
|
18
|
+
});`;d+=`
|
|
19
|
+
${h}
|
|
20
|
+
`}return{code:await P.format(d,{semi:!0,parser:"typescript",tabWidth:4}),fileName:i,append:u}}}};function $(e){if(!e)return{};if(e.length===1){let n=e[0];return n?{[n.field]:n.value}:void 0}let o=e.filter(n=>n.connector==="AND"||!n.connector),a=e.filter(n=>n.connector==="OR"),r=o.map(n=>({[n.field]:n.operator==="eq"||!n.operator?n.value:{[n.field]:n.value}})),s=a.map(n=>({[n.field]:n.value})),t={};return r.length&&(t={...t,$and:r}),s.length&&(t={...t,$or:s}),t}function S(e){let{_id:o,...a}=e;return a}function ee(e){return e.reduce((a,r)=>(a[r]=1,a),{})}var pt=e=>{let o=e;return{id:"mongodb",async create(a){let{model:r,data:s}=a,i={id:(await o.collection(r).insertOne({...s})).insertedId,...s};return S(i)},async findOne(a){let{model:r,where:s,select:t}=a,n=$(s),i={};t&&(i=ee(t));let l=(await o.collection(r).find({...n},{projection:i}).toArray())[0];return l?S(l):null},async findMany(a){let{model:r,where:s}=a,t=$(s),n=await o.collection(r).findMany(t);return S(n)},async update(a){let{model:r,where:s,update:t}=a,n=$(s),i=await o.collection(r).findOneAndUpdate(n,{$set:t},{returnDocument:"after"});return S(i)},async delete(a){let{model:r,where:s}=a,t=$(s);return await o.collection(r).findOneAndDelete(t)}}};import"kysely";function te(e){return e.plugins?.flatMap(a=>Object.keys(a.schema||{}).map(r=>{let t=(a.schema||{})[r];if(!t?.disableMigration)return{tableName:r,fields:t?.fields}}).filter(r=>r!==void 0))||[]}function _(e){let o=C(e),a=te(e);return[o.user,o.session,o.account,...a].reduce((s,t)=>(s[t.tableName]={fields:{...s[t.tableName]?.fields,...t.fields}},s),{})}import{Kysely as re}from"kysely";import{MysqlDialect as M,PostgresDialect as L,SqliteDialect as F}from"kysely";var ne=async e=>{if(!e.database)return;if("createDriver"in e.database)return e.database;let o;if("provider"in e.database){let a=e.database.provider,r=e.database?.url?.trim();if(a==="postgres"){let t=(await import("pg").catch(n=>{throw new x("Please install `pg` to use postgres database")})).Pool;o=new L({pool:new t({connectionString:r})})}if(a==="mysql")try{let{createPool:s}=await import("mysql2/promise").catch(i=>{throw new x("Please install `mysql2` to use mysql database")}),t=new URL(r),n=s({host:t.hostname,user:t.username,password:t.password,database:t.pathname.split("/")[1],port:Number(t.port)});o=new M({pool:n})}catch(s){throw s instanceof TypeError?new x("Invalid database URL"):s}if(a==="sqlite")try{let s=await import("better-sqlite3"),t=s.default||s;if(!t)throw new x("Failed to import better-sqlite3. Make sure `better-sqlite3` is properly installed.");let n=new t(r);o=new F({database:n})}catch(s){throw console.error(s),new x("Failed to initialize SQLite. Make sure `better-sqlite3` is properly installed.")}}return o},I=async e=>{let o=await ne(e);return o&&new re({dialect:o})},U=e=>{if("provider"in e.database)return e.database.provider;if("dialect"in e.database){if(e.database.dialect instanceof L)return"postgres";if(e.database.dialect instanceof M)return"mysql";if(e.database.dialect instanceof F)return"sqlite"}return"sqlite"};var oe={string:["character varying","text"],number:["int4","integer","bigint","smallint","numeric","real","double precision"],boolean:["bool","boolean"],date:["timestamp","date"]},se={string:["varchar","text"],number:["integer","int","bigint","smallint","decimal","float","double"],boolean:["boolean"],date:["date","datetime"]},ae={string:["TEXT"],number:["INTEGER","REAL"],boolean:["INTEGER","BOOLEAN"],date:["DATE","INTEGER"]},ie={postgres:oe,mysql:se,sqlite:ae};function ce(e,o,a){return ie[a][o].map(n=>n.toLowerCase()).includes(e.toLowerCase())}async function j(e){let o=_(e),a=U(e),r=await I(e);r||(N.error("Invalid database configuration."),process.exit(1));let s=await r.introspection.getTables(),t=[],n=[];for(let[u,p]of Object.entries(o)){let g=s.find(b=>b.name===u);if(!g){let b=t.findIndex(h=>h.table===u),f={table:u,fields:p.fields,order:p.order||1/0},y=t.findIndex(h=>(h.order||1/0)>f.order);y===-1?b===-1?t.push(f):t[b].fields={...t[b].fields,...p.fields}:t.splice(y,0,f);continue}let m={};for(let[b,f]of Object.entries(p.fields)){let y=g.columns.find(h=>h.name===b);if(!y){m[b]=f;continue}ce(y.dataType,f.type,a)||N.warn(`Field ${b} in table ${u} has a different type in the database. Expected ${f.type} but got ${y.dataType}.`)}Object.keys(m).length>0&&n.push({table:u,fields:m,order:p.order||1/0})}let i=[];function c(u){let p={string:"text",boolean:"boolean",number:"integer",date:"date"};return a==="mysql"&&u==="string"?"varchar(255)":p[u]}if(n.length)for(let u of n)for(let[p,g]of Object.entries(u.fields)){let m=c(g.type),b=r.schema.alterTable(u.table).addColumn(p,m,f=>(f=g.required!==!1?f.notNull():f,g.references&&(f=f.references(`${g.references.model}.${g.references.field}`)),f));i.push(b)}if(t.length)for(let u of t){let p=r.schema.createTable(u.table).addColumn("id",c("string"),g=>g.primaryKey());for(let[g,m]of Object.entries(u.fields)){let b=c(m.type);p=p.addColumn(g,b,f=>(f=m.required!==!1?f.notNull():f,m.references&&(f=f.references(`${m.references.model}.${m.references.field}`)),m.unique&&(f=f.unique()),f))}i.push(p)}async function l(){for(let u of i)await u.execute()}async function d(){return i.map(p=>p.compile().sql).join(`;
|
|
21
|
+
|
|
22
|
+
`)}return{toBeCreated:t,toBeAdded:n,runMigrations:l,compileMigrations:d}}function v(e){if(!e)return{and:null,or:null};let o=e?.filter(r=>r.connector==="AND"||!r.connector).reduce((r,s)=>({...r,[s.field]:s.value}),{}),a=e?.filter(r=>r.connector==="OR").reduce((r,s)=>({...r,[s.field]:s.value}),{});return{and:Object.keys(o).length?o:null,or:Object.keys(a).length?a:null}}function R(e,o,a){for(let r in e)e[r]===0&&o[r]?.type==="boolean"&&a?.boolean&&(e[r]=!1),e[r]===1&&o[r]?.type==="boolean"&&a?.boolean&&(e[r]=!0),o[r]?.type==="date"&&(e[r]instanceof Date||(e[r]=new Date(e[r])));return e}function z(e,o){for(let a in e)typeof e[a]=="boolean"&&o?.boolean&&(e[a]=e[a]?1:0),e[a]instanceof Date&&(e[a]=e[a].toISOString());return e}var St=(e,o)=>({id:"kysely",async create(a){let{model:r,data:s,select:t}=a;o?.transform&&(s=z(s,o.transform));let n=await e.insertInto(r).values(s).returningAll().executeTakeFirst();if(o?.transform){let i=o.transform.schema[r];n=i?R(s,i,o.transform):n}return t?.length&&(n=n?t.reduce((c,l)=>n?.[l]?{...c,[l]:n[l]}:c,{}):null),n},async findOne(a){let{model:r,where:s,select:t}=a,{and:n,or:i}=v(s),c=e.selectFrom(r).selectAll();i&&(c=c.where(d=>d.or(i))),n&&(c=c.where(d=>d.and(n)));let l=await c.executeTakeFirst();if(t?.length&&(l=l?t.reduce((u,p)=>l?.[p]?{...u,[p]:l[p]}:u,{}):null),o?.transform){let d=o.transform.schema[r];return l=l&&d?R(l,d,o.transform):l,l||null}return l||null},async findMany(a){let{model:r,where:s}=a,t=e.selectFrom(r),{and:n,or:i}=v(s);n&&(t=t.where(l=>l.and(n))),i&&(t=t.where(l=>l.or(i)));let c=await t.selectAll().execute();if(o?.transform){let l=o.transform.schema[r];return l?c.map(d=>R(d,l,o.transform)):c}return c},async update(a){let{model:r,where:s,update:t}=a,{and:n,or:i}=v(s);o?.transform&&(t=z(t,o.transform));let c=e.updateTable(r).set(t);n&&(c=c.where(d=>d.and(n))),i&&(c=c.where(d=>d.or(i)));let l=await c.returningAll().executeTakeFirst()||null;if(o?.transform){let d=o.transform.schema[r];return d?R(l,d,o.transform):l}return l},async delete(a){let{model:r,where:s}=a,{and:t,or:n}=v(s),i=e.deleteFrom(r);t&&(i=i.where(c=>c.and(t))),n&&(i=i.where(c=>c.or(n))),await i.execute()},async createSchema(a){let{compileMigrations:r}=await j(a);return console.log(r),{code:await r(),fileName:`./better-auth_migrations/${new Date().toISOString()}.sql`}}});export{ut as drizzleAdapter,St as kyselyAdapter,pt as mongodbAdapter,nt as prismaAdapter};
|
package/dist/api.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
export { A as AuthEndpoint, b as AuthMiddleware,
|
|
1
|
+
export { A as AuthEndpoint, b as AuthMiddleware, y as callbackOAuth, X as changePassword, a as createAuthEndpoint, c as createAuthMiddleware, Q as createEmailVerificationToken, a1 as csrfMiddleware, _ as error, M as forgetPassword, N as forgetPasswordCallback, Z as getCSRFToken, u as getEndpoints, z as getSession, C as getSessionFromCtx, E as listSessions, $ as ok, o as optionsMiddleware, O as resetPassword, J as revokeSession, K as revokeSessions, v as router, T as sendVerificationEmail, D as sessionMiddleware, Y as setPassword, x as signInEmail, w as signInOAuth, L as signOut, a0 as signUpEmail, V as updateUser, U as verifyEmail } from './index-gO-yM4kI.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import './helper-C1ihmerM.js';
|
|
4
4
|
import 'better-call';
|
|
5
5
|
import 'kysely';
|
|
6
|
-
import './
|
|
7
|
-
import './social.js';
|
|
6
|
+
import './index-CE92ti2Z.js';
|
|
8
7
|
import 'arctic';
|
|
9
|
-
import './adapter-D-m9-hQp.js';
|
package/dist/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
`)}}),_=ut();var fe=e=>{let t=new pt(e.clientId,e.clientSecret,w("google",e.redirectURI));return{id:"google",name:"Google",createAuthorizationURL({state:o,scopes:r,codeVerifier:s,redirectURI:i}){if(!e.clientId||!e.clientSecret)throw _.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new D("CLIENT_ID_AND_SECRET_REQUIRED");if(!s)throw new D("codeVerifier is required for Google");let d=r||["email","profile"];return t.createAuthorizationURL(o,s,d)},validateAuthorizationCode:(o,r,s)=>a(void 0,null,function*(){return k({code:o,codeVerifier:r,redirectURI:s||w("google",e.redirectURI),options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"})}),getUserInfo(o){return a(this,null,function*(){var s;if(!o.idToken)return null;let r=(s=mt(o.idToken()))==null?void 0:s.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}})}}};import{betterFetch as ft}from"@better-fetch/fetch";import{Spotify as gt}from"arctic";var ge=e=>{let t=new gt(e.clientId,e.clientSecret,w("spotify",e.redirectURI));return{id:"spotify",name:"Spotify",createAuthorizationURL({state:o,scopes:r}){let s=r||["user-read-email"];return t.createAuthorizationURL(o,s)},validateAuthorizationCode:(o,r,s)=>a(void 0,null,function*(){return k({code:o,codeVerifier:r,redirectURI:s||w("spotify",e.redirectURI),options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"})}),getUserInfo(o){return a(this,null,function*(){var i;let{data:r,error:s}=yield ft("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken()}`}});return s?null:{user:{id:r.id,name:r.display_name,email:r.email,image:(i=r.images[0])==null?void 0:i.url,emailVerified:!1},data:r}})}}};import{betterFetch as ht}from"@better-fetch/fetch";import{Twitch as yt}from"arctic";var he=e=>{let t=new yt(e.clientId,e.clientSecret,w("twitch",e.redirectURI));return{id:"twitch",name:"Twitch",createAuthorizationURL({state:o,scopes:r}){let s=r||["activity:write","read"];return t.createAuthorizationURL(o,s)},validateAuthorizationCode:(o,r,s)=>a(void 0,null,function*(){return k({code:o,codeVerifier:r,redirectURI:s||w("twitch",e.redirectURI),options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"})}),getUserInfo(o){return a(this,null,function*(){let{data:r,error:s}=yield ht("https://api.twitch.tv/helix/users",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken()}`}});return s?null:{user:{id:r.sub,name:r.preferred_username,email:r.email,image:r.picture,emailVerified:!1},data:r}})}}};import{betterFetch as wt}from"@better-fetch/fetch";import{Twitter as bt}from"arctic";var ye=e=>{let t=new bt(e.clientId,e.clientSecret,w("twitter",e.redirectURI));return{id:"twitter",name:"Twitter",createAuthorizationURL(o){let r=o.scopes||["account_info.read"];return t.createAuthorizationURL(o.state,o.codeVerifier,r)},validateAuthorizationCode:(o,r,s)=>a(void 0,null,function*(){return k({code:o,codeVerifier:r,redirectURI:s||w("twitch",e.redirectURI),options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"})}),getUserInfo(o){return a(this,null,function*(){let{data:r,error:s}=yield wt("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken()}`}});return s||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}})}}};import"arctic";var At={apple:ce,discord:le,facebook:ue,github:me,google:fe,spotify:ge,twitch:he,twitter:ye},we=Object.keys(At);import{generateState as kt}from"oslo/oauth2";import{z as q}from"zod";function be(e,t,n){let o=kt();return{state:JSON.stringify({code:o,callbackURL:e,currentURL:t,dontRememberMe:n}),code:o}}function W(e){return q.object({code:q.string(),callbackURL:q.string().optional(),currentURL:q.string().optional(),dontRememberMe:q.boolean().optional()}).safeParse(JSON.parse(e))}import{APIError as Rt}from"better-call";var Ae=(e,t=!1)=>{let n=new Date;return new Date(n.getTime()+(t?e*1e3:e))};import{TimeSpan as Jo}from"oslo";function S(e,t,n,o){return a(this,null,function*(){let r=e.context.authCookies.sessionToken.options;r.maxAge=n?void 0:r.maxAge,yield e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,r),n&&(yield e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options))})}function V(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}import{z as ke}from"zod";function N(e){let t="127.0.0.1";if(process.env.NODE_ENV==="test")return t;let n=["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"];for(let o of n){let r=e.headers.get(o);if(typeof r=="string"){let s=r.split(",")[0].trim();if(s)return s}}return null}var J=new Map;function Ut(e,t){if(!e.request)return"";let{method:n,url:o,headers:r}=e.request,s=e.request.headers.get("User-Agent")||"",i=N(e.request)||"",d=JSON.stringify(r);return`${n}:${o}:${d}:${s}:${i}:${t}`}var Z=()=>f("/session",{method:"GET",requireHeaders:!0},e=>a(void 0,null,function*(){try{let t=yield e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let n=Ut(e,t),o=J.get(n);if(o){if(o.expiresAt>Date.now())return e.json(o.data);J.delete(n)}let r=yield e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return V(e),r&&(yield e.context.internalAdapter.deleteSession(r.session.id)),e.json(null,{status:401});if(yield e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let i=e.context.sessionConfig.expiresIn,d=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-i*1e3+d*1e3<=Date.now()){let l=yield e.context.internalAdapter.updateSession(r.session.id,{expiresAt:Ae(e.context.sessionConfig.expiresIn,!0)});if(!l)return V(e),e.json(null,{status:401});let p=(l.expiresAt.valueOf()-Date.now())/1e3;return yield S(e,l.id,!1,{maxAge:p}),e.json({session:l,user:r.user})}return J.set(n,{data:r,expiresAt:Date.now()+5e3}),e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}})),K=e=>a(void 0,null,function*(){return yield Z()(A(g({},e),{_flag:void 0}))}),B=H(e=>a(void 0,null,function*(){let t=yield K(e);if(!(t!=null&&t.session))throw new Rt("UNAUTHORIZED");return{session:t}})),Re=()=>f("/user/list-sessions",{method:"GET",use:[B],requireHeaders:!0},e=>a(void 0,null,function*(){let n=(yield e.context.adapter.findMany({model:e.context.tables.session.tableName,where:[{field:"userId",value:e.context.session.user.id}]})).filter(o=>o.expiresAt>new Date);return e.json(n)})),Ue=f("/user/revoke-session",{method:"POST",body:ke.object({id:ke.string()}),use:[B],requireHeaders:!0},e=>a(void 0,null,function*(){let t=e.body.id,n=yield e.context.internalAdapter.findSession(t);if(!n)return e.json(null,{status:400});if(n.session.userId!==e.context.session.user.id)return e.json(null,{status:403});try{yield e.context.internalAdapter.deleteSession(t)}catch(o){return e.context.logger.error(o),e.json(null,{status:500})}return e.json({status:!0})})),Te=f("/user/revoke-sessions",{method:"POST",use:[B],requireHeaders:!0},e=>a(void 0,null,function*(){try{yield e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}return e.json({status:!0})}));var Pe=f("/sign-in/social",{method:"POST",requireHeaders:!0,query:P.object({currentURL:P.string().optional()}).optional(),body:P.object({callbackURL:P.string().optional(),provider:P.enum(we),dontRememberMe:P.boolean().default(!1).optional()})},e=>a(void 0,null,function*(){var i,d,c,u;let t=e.context.socialProviders.find(l=>l.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider to your auth config",{provider:e.body.provider}),new I("NOT_FOUND",{message:"Provider not found"});let n=e.context.authCookies,o=(i=e.query)!=null&&i.currentURL?new URL((d=e.query)==null?void 0:d.currentURL):null,r=(c=e.body.callbackURL)!=null&&c.startsWith("http")?e.body.callbackURL:`${o==null?void 0:o.origin}${e.body.callbackURL||""}`,s=be(r||(o==null?void 0:o.origin)||e.context.baseURL,(u=e.query)==null?void 0:u.currentURL);try{yield e.setSignedCookie(n.state.name,s.code,e.context.secret,n.state.options);let l=Tt();yield e.setSignedCookie(n.pkCodeVerifier.name,l,e.context.secret,n.pkCodeVerifier.options);let p=t.createAuthorizationURL({state:s.state,codeVerifier:l});return p.searchParams.set("redirect_uri",`${e.context.baseURL}/callback/${e.body.provider}`),{url:p.toString(),state:s.state,codeVerifier:l,redirect:!0}}catch(l){throw new I("INTERNAL_SERVER_ERROR")}})),ve=f("/sign-in/email",{method:"POST",body:P.object({email:P.string().email(),password:P.string(),callbackURL:P.string().optional(),dontRememberMe:P.boolean().default(!1).optional()})},e=>a(void 0,null,function*(){var l,p;if(!((p=(l=e.context.options)==null?void 0:l.emailAndPassword)!=null&&p.enabled))throw e.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!"),new I("BAD_REQUEST",{message:"Email and password is not enabled"});let t=yield K(e);t&&(yield e.context.internalAdapter.deleteSession(t.session.id));let{email:n,password:o}=e.body;if(!P.string().email().safeParse(n).success)throw new I("BAD_REQUEST",{message:"Invalid email"});let s=yield e.context.internalAdapter.findUserByEmail(n);if(!s)throw yield e.context.password.hash(o),e.context.logger.error("User not found",{email:n}),new I("UNAUTHORIZED",{message:"Invalid email or password"});let i=s.accounts.find(m=>m.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:n}),new I("UNAUTHORIZED",{message:"Invalid email or password"});let d=i==null?void 0:i.password;if(!d)throw e.context.logger.error("Password not found",{email:n}),new I("UNAUTHORIZED",{message:"Unexpected error"});if(!(yield e.context.password.verify(d,o)))throw e.context.logger.error("Invalid password"),new I("UNAUTHORIZED",{message:"Invalid email or password"});let u=yield e.context.internalAdapter.createSession(s.user.id,e.headers,e.body.dontRememberMe);if(!u)throw e.context.logger.error("Failed to create session"),new I("INTERNAL_SERVER_ERROR");return yield S(e,u.id,e.body.dontRememberMe),e.json({user:s.user,session:u,redirect:!!e.body.callbackURL,url:e.body.callbackURL})}));import{APIError as St}from"better-call";import{z as F}from"zod";import{z as h}from"zod";var wn=h.object({id:h.string(),providerId:h.string(),accountId:h.string(),userId:h.string(),accessToken:h.string().nullable().optional(),refreshToken:h.string().nullable().optional(),idToken:h.string().nullable().optional(),expiresAt:h.date().nullable().optional(),password:h.string().optional().nullable()}),Se=h.object({id:h.string(),email:h.string().transform(e=>e.toLowerCase()),emailVerified:h.boolean().default(!1),name:h.string(),image:h.string().optional(),createdAt:h.date().default(new Date),updatedAt:h.date().default(new Date)}),bn=h.object({id:h.string(),userId:h.string(),expiresAt:h.date(),ipAddress:h.string().optional(),userAgent:h.string().optional()});import{alphabet as Pt,generateRandomString as vt}from"oslo/crypto";var xe=()=>vt(36,Pt("a-z","0-9"));var C={isAction:!1};function Q(e){let t=e.accessToken(),n=e.hasRefreshToken()?e.refreshToken():void 0,o;try{o=e.accessTokenExpiresAt()}catch(r){}return{accessToken:t,refreshToken:n,expiresAt:o}}var _e=f("/callback/:id",{method:"GET",query:F.object({state:F.string(),code:F.string().optional(),error:F.string().optional()}),metadata:C},e=>a(void 0,null,function*(){var U,T,O;if(e.query.error||!e.query.code){let R=((U=W(e.query.state).data)==null?void 0:U.callbackURL)||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(b=>b.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let n=yield e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),o;try{o=yield t.validateAuthorizationCode(e.query.code,n,`${e.context.baseURL}/callback/${t.id}`)}catch(b){throw e.context.logger.error(b),e.redirect(`${e.context.baseURL}/error?error=oauth_code_verification_failed`)}let r=yield t.getUserInfo(o).then(b=>b==null?void 0:b.user),s=xe(),i=Se.safeParse(A(g({},r),{id:s})),d=W(e.query.state);if(!d.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=invalid_state_parameter`);let{callbackURL:c,currentURL:u,dontRememberMe:l}=d.data;if(!r||i.success===!1)throw e.redirect(`${e.context.baseURL}/error?error=oauth_validation_failed`);if(!c)throw e.redirect(`${e.context.baseURL}/error?error=oauth_callback_url_not_found`);let p=yield e.context.internalAdapter.findUserByEmail(r.email),m=p==null?void 0:p.user.id;if(p){let b=p.accounts.find(j=>j.providerId===t.id),R=(O=(T=e.context.options.account)==null?void 0:T.accountLinking)==null?void 0:O.trustedProviders,z=R?R.includes(t.id):!0;if(!b&&(!r.emailVerified||!z)){let j;try{j=new URL(u||c),j.searchParams.set("error","account_not_linked")}catch(Jt){throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(j.toString())}if(!b)try{yield e.context.internalAdapter.linkAccount(g({providerId:t.id,accountId:r.id,id:`${t.id}:${r.id}`,userId:p.user.id},Q(o)))}catch(j){throw console.log(j),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{yield e.context.internalAdapter.createOAuthUser(i.data,A(g({},Q(o)),{id:`${t.id}:${r.id}`,providerId:t.id,accountId:r.id,userId:s}))}catch(b){let R=new URL(u||c);throw R.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",R.toString()),e.redirect(R.toString())}if(!m&&!s)throw new St("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});let y=yield e.context.internalAdapter.createSession(m||s,e.request,l);if(!y){let b=new URL(u||c);throw b.searchParams.set("error","unable_to_create_session"),e.redirect(b.toString())}try{yield S(e,y.id,l)}catch(b){e.context.logger.error("Unable to set session cookie",b);let R=new URL(u||c);throw R.searchParams.set("error","unable_to_create_session"),e.redirect(R.toString())}throw e.redirect(c)}));import{z as X}from"zod";var Ie=f("/sign-out",{method:"POST",body:X.optional(X.object({callbackURL:X.string().optional()}))},e=>a(void 0,null,function*(){var n,o;let t=yield e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);return t?(yield e.context.internalAdapter.deleteSession(t),V(e),e.json(null,{body:{redirect:!!((n=e.body)!=null&&n.callbackURL),url:(o=e.body)==null?void 0:o.callbackURL}})):e.json(null)}));import{TimeSpan as xt}from"oslo";import{createJWT as _t,parseJWT as It}from"oslo/jwt";import{validateJWT as Ee}from"oslo/jwt";import{z as v}from"zod";var Le=f("/forget-password",{method:"POST",body:v.object({email:v.string().email(),redirectTo:v.string()})},e=>a(void 0,null,function*(){var s;if(!((s=e.context.options.emailAndPassword)!=null&&s.sendResetPassword))return e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function to your auth config!"),e.json(null,{status:400,statusText:"RESET_PASSWORD_EMAIL_NOT_SENT",body:{message:"Reset password isn't enabled"}});let{email:t}=e.body,n=yield e.context.internalAdapter.findUserByEmail(t);if(!n)return e.json({status:!1},{body:{status:!0}});let o=yield _t("HS256",Buffer.from(e.context.secret),{email:n.user.email,redirectTo:e.body.redirectTo},{expiresIn:new xt(1,"h"),issuer:"better-auth",subject:"forget-password",audiences:[n.user.email],includeIssuedTimestamp:!0}),r=`${e.context.baseURL}/reset-password/${o}`;return yield e.context.options.emailAndPassword.sendResetPassword(r,n.user),e.json({status:!0})})),Oe=f("/reset-password/:token",{method:"GET"},e=>a(void 0,null,function*(){var s;let{token:t}=e.params,n,o=v.object({email:v.string(),redirectTo:v.string()});try{if(n=yield Ee("HS256",Buffer.from(e.context.secret),t),!n.expiresAt||n.expiresAt<new Date)throw Error("Token expired")}catch(i){let d=It(t),c=o.safeParse(d==null?void 0:d.payload);throw c.success?e.redirect(`${(s=c.data)==null?void 0:s.redirectTo}?error=invalid_token`):e.redirect(`${e.context.baseURL}/error?error=invalid_token`)}let{redirectTo:r}=o.parse(n.payload);throw e.redirect(`${r}?token=${t}`)})),Ce=f("/reset-password",{method:"POST",query:v.object({currentURL:v.string()}).optional(),body:v.object({newPassword:v.string(),callbackURL:v.string().optional()})},e=>a(void 0,null,function*(){var o,r,s;let t=(o=e.query)==null?void 0:o.currentURL.split("?token=")[1];if(!t)return e.json({error:"Invalid token",data:null},{status:400,statusText:"INVALID_TOKEN",body:{message:"Invalid token"}});let{newPassword:n}=e.body;try{let i=yield Ee("HS256",Buffer.from(e.context.secret),t),d=v.string().email().parse(i.payload.email),c=yield e.context.internalAdapter.findUserByEmail(d);if(!c)return e.json({error:"User not found",data:null},{status:400,body:{message:"failed to reset password"}});if(n.length<(((r=e.context.options.emailAndPassword)==null?void 0:r.minPasswordLength)||8)||n.length>(((s=e.context.options.emailAndPassword)==null?void 0:s.maxPasswordLength)||32))return e.json({data:null,error:"password is too short or too long"},{status:400,statusText:"INVALID_PASSWORD_LENGTH",body:{message:"password is too short or too long"}});let u=yield e.context.password.hash(n);return(yield e.context.internalAdapter.updatePassword(c.user.id,u))?e.json({error:null,data:{status:!0,url:e.body.callbackURL,redirect:!!e.body.callbackURL}},{body:{status:!0,url:e.body.callbackURL,redirect:!!e.body.callbackURL}}):e.json(null,{status:400,statusText:"USER_NOT_FOUND",body:{message:"User doesn't have a credential account"}})}catch(i){return console.log(i),e.json({error:"Invalid token",data:null},{status:400,statusText:"INVALID_TOKEN",body:{message:"Invalid token"}})}}));import{TimeSpan as Et}from"oslo";import{createJWT as Lt,validateJWT as Ot}from"oslo/jwt";import{z as x}from"zod";function Y(e,t){return a(this,null,function*(){return yield Lt("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new Et(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})})}var je=f("/send-verification-email",{method:"POST",query:x.object({currentURL:x.string().optional()}).optional(),body:x.object({email:x.string().email(),callbackURL:x.string().optional()})},e=>a(void 0,null,function*(){var r,s;if(!((r=e.context.options.emailAndPassword)!=null&&r.sendVerificationEmail))return e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),e.json(null,{status:400,statusText:"VERIFICATION_EMAIL_NOT_SENT",body:{message:"Verification email isn't enabled"}});let{email:t}=e.body,n=yield Y(e.context.secret,t),o=`${e.context.baseURL}/verify-email?token=${n}&callbackURL=${e.body.callbackURL||((s=e.query)==null?void 0:s.currentURL)||"/"}`;return yield e.context.options.emailAndPassword.sendVerificationEmail(t,o,n),e.json({status:!0})})),De=f("/verify-email",{method:"GET",query:x.object({token:x.string(),callbackURL:x.string().optional()})},e=>a(void 0,null,function*(){let{token:t}=e.query,n;try{n=yield Ot("HS256",Buffer.from(e.context.secret),t)}catch(d){return e.context.logger.error("Failed to verify email",d),e.json(null,{status:400,statusText:"INVALID_TOKEN",body:{message:"Invalid token"}})}let r=x.object({email:x.string().email()}).parse(n.payload),s=yield e.context.internalAdapter.findUserByEmail(r.email);if(!s)return e.json(null,{status:400,statusText:"USER_NOT_FOUND",body:{message:"User not found"}});if(!s.accounts.find(d=>d.providerId==="credential"))throw e.redirect;if(yield e.context.internalAdapter.updateUserByEmail(r.email,{emailVerified:!0}),e.query.callbackURL)throw console.log("Redirecting to",e.query.callbackURL),e.redirect("/");return e.json({status:!0})}));import{z as E}from"zod";import{alphabet as Ct,generateRandomString as jt}from"oslo/crypto";import"better-call";var $e=f("/user/update",{method:"POST",body:E.object({name:E.string().optional(),image:E.string().optional()}),use:[B]},e=>a(void 0,null,function*(){let{name:t,image:n}=e.body,o=e.context.session;if(!n&&!t)return e.json(o.user);let r=yield e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:n});return e.json(r)})),Be=f("/user/change-password",{method:"POST",body:E.object({newPassword:E.string(),currentPassword:E.string(),revokeOtherSessions:E.boolean().optional()}),use:[B]},e=>a(void 0,null,function*(){let{newPassword:t,currentPassword:n,revokeOtherSessions:o}=e.body,r=e.context.session,s=e.context.password.config.minPasswordLength;if(t.length<s)return e.context.logger.error("Password is too short"),e.json(null,{status:400,body:{message:"Password is too short"}});let i=e.context.password.config.maxPasswordLength;if(t.length>i)return e.context.logger.error("Password is too long"),e.json(null,{status:400,body:{message:"Password is too long"}});let c=(yield e.context.internalAdapter.findAccounts(r.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!c||!c.password)return e.json(null,{status:400,body:{message:"User does not have a password"}});let u=yield e.context.password.hash(t);if(!(yield e.context.password.verify(c.password,n)))return e.json(null,{status:400,body:{message:"Invalid password"}});if(yield e.context.internalAdapter.updateAccount(c.id,{password:u}),o){yield e.context.internalAdapter.deleteSessions(r.user.id);let p=yield e.context.internalAdapter.createSession(r.user.id,e.headers);if(!p)return e.json(null,{status:500,body:{message:"Failed to create session"}});yield S(e,p.id)}return e.json(r.user)})),ze=f("/user/set-password",{method:"POST",body:E.object({newPassword:E.string()}),use:[B]},e=>a(void 0,null,function*(){let{newPassword:t}=e.body,n=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)return e.context.logger.error("Password is too short"),e.json(null,{status:400,body:{message:"Password is too short"}});let r=e.context.password.config.maxPasswordLength;if(t.length>r)return e.context.logger.error("Password is too long"),e.json(null,{status:400,body:{message:"Password is too long"}});let i=(yield e.context.internalAdapter.findAccounts(n.user.id)).find(c=>c.providerId==="credential"&&c.password),d=yield e.context.password.hash(t);return i?e.json(null,{status:400,body:{message:"User already has a password"}}):(yield e.context.internalAdapter.linkAccount({id:jt(32,Ct("a-z","0-9","A-Z")),userId:n.user.id,providerId:"credential",accountId:n.user.id,password:d}),e.json(n.user))}));import{alphabet as Dt,generateRandomString as $t}from"oslo/crypto";var qe=f("/csrf",{method:"GET",metadata:C},e=>a(void 0,null,function*(){let t=yield e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t)return{csrfToken:t};let n=$t(32,Dt("a-z","0-9","A-Z")),o=yield M(e.context.secret,n),r=`${n}!${o}`;return yield e.setSignedCookie(e.context.authCookies.csrfToken.name,r,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:n}}));var Bt=(e="Unknown")=>`<!DOCTYPE html>
|
|
1
|
+
import{APIError as Et,createRouter as Ot}from"better-call";import{APIError as Q}from"better-call";import{z as X}from"zod";import{xchacha20poly1305 as $t}from"@noble/ciphers/chacha";import{bytesToHex as zt,hexToBytes as qt,utf8ToBytes as Vt}from"@noble/ciphers/utils";import{managedNonce as Mt}from"@noble/ciphers/webcrypto";import{sha256 as Ft}from"@noble/hashes/sha256";async function j(e,t){let o=new TextEncoder,r={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",o.encode(e),r,!1,["sign","verify"]),s=await crypto.subtle.sign(r.name,n,o.encode(t));return btoa(String.fromCharCode(...new Uint8Array(s)))}import{createEndpointCreator as qe,createMiddleware as Z,createMiddlewareCreator as Ve}from"better-call";var K=Z(async()=>({})),D=Ve({use:[K,Z(async()=>({}))]}),l=qe({use:[K]});var Y=D({body:X.object({csrfToken:X.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(t.origin===new URL(e.context.baseURL).origin||e.context.options.trustedOrigins?.includes(t.origin))return;let o=e.body?.csrfToken,r=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,s]=r?.split("!")||[null,null];if(!o||!r||!n||!s||r!==o)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Q("UNAUTHORIZED",{message:"Invalid CSRF Token"});let i=await j(e.context.secret,n);if(s!==i)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Q("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as v}from"better-call";import{generateCodeVerifier as ut}from"oslo/oauth2";import{z as A}from"zod";import"arctic";import{parseJWT as Fe}from"oslo/jwt";import"@better-fetch/fetch";var I=class extends Error{constructor(t,o,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=o}};import{OAuth2Tokens as Me}from"arctic";function Ne(e){try{return new URL(e).pathname!=="/"}catch{throw new I(`Invalid base URL: ${e}. Please provide a valid base URL.`)}}function q(e,t="/api/auth"){return Ne(e)?e:(t=t.startsWith("/")?t:`/${t}`,`${e}${t}`)}function ee(e,t){if(e)return q(e,t);let o=process?.env||{},r=o.BETTER_AUTH_URL||o.NEXT_PUBLIC_BETTER_AUTH_URL||o.PUBLIC_BETTER_AUTH_URL||o.NUXT_PUBLIC_BETTER_AUTH_URL||o.NUXT_PUBLIC_AUTH_URL||(o.BASE_URL!=="/"?o.BASE_URL:void 0);if(r)return q(r,t);if(typeof window<"u")return q(window.location.origin,t)}import{betterFetch as He}from"@better-fetch/fetch";function f(e,t){return t||`${ee()}/callback/${e}`}async function y({code:e,codeVerifier:t,redirectURI:o,options:r,tokenEndpoint:n}){let s=new URLSearchParams;s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",o),s.set("client_id",r.clientId),s.set("client_secret",r.clientSecret);let{data:i,error:a}=await He(n,{method:"POST",body:s,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(a)throw a;return new Me(i)}var te=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:o,scopes:r,redirectURI:n}){let s=r||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${s.join(" ")}&state=${o}`)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("apple",e.redirectURI),options:e,tokenEndpoint:t}),async getUserInfo(o){let r=Fe(o.idToken())?.payload;return r?{user:{id:r.sub,name:r.name,email:r.email,emailVerified:r.email_verified==="true"},data:r}:null}}};import{betterFetch as Ge}from"@better-fetch/fetch";import{Discord as We}from"arctic";var re=e=>{let t=new We(e.clientId,e.clientSecret,f("discord",e.redirectURI));return{id:"discord",name:"Discord",createAuthorizationURL({state:o,scopes:r}){let n=r||["email"];return t.createAuthorizationURL(o,n)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("discord",e.redirectURI),options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(o){let{data:r,error:n}=await Ge("https://discord.com/api/users/@me",{auth:{type:"Bearer",token:o.accessToken()}});return n?null:{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified},data:r}}}};import{betterFetch as Je}from"@better-fetch/fetch";import{Facebook as Ze}from"arctic";var oe=e=>{let t=new Ze(e.clientId,e.clientSecret,f("facebook",e.redirectURI));return{id:"facebook",name:"Facebook",createAuthorizationURL({state:o,scopes:r}){let n=r||["email","public_profile"];return t.createAuthorizationURL(o,n)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("facebook",e.redirectURI),options:e,tokenEndpoint:"https://graph.facebook.com/v16.0/oauth/access_token"}),async getUserInfo(o){let{data:r,error:n}=await Je("https://graph.facebook.com/me",{auth:{type:"Bearer",token:o.accessToken()}});return n?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}}};import{betterFetch as ne}from"@better-fetch/fetch";import{GitHub as Ke}from"arctic";var se=({clientId:e,clientSecret:t,redirectURI:o})=>{let r=new Ke(e,t,f("github",o));return{id:"github",name:"Github",createAuthorizationURL({state:n,scopes:s}){let i=s||["user:email"];return r.createAuthorizationURL(n,i)},validateAuthorizationCode:async n=>await r.validateAuthorizationCode(n),async getUserInfo(n){let{data:s,error:i}=await ne("https://api.github.com/user",{auth:{type:"Bearer",token:n.accessToken()}});if(i)return null;let a=!1;if(!s.email){let{data:d,error:u}=await ne("https://api.github.com/user/emails",{auth:{type:"Bearer",token:n.accessToken()}});u||(s.email=(d.find(c=>c.primary)??d[0])?.email,a=d.find(c=>c.email===s.email)?.verified??!1)}return{user:{id:s.id,name:s.name,email:s.email,image:s.avatar_url,emailVerified:a,createdAt:new Date,updatedAt:new Date},data:s}}}};import{Google as Ye}from"arctic";import{parseJWT as et}from"oslo/jwt";import{createConsola as Qe}from"consola";var L=Qe({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Xe=e=>({log:(...t)=>{!e?.disabled&&L.log("",...t)},error:(...t)=>{!e?.disabled&&L.error("",...t)},warn:(...t)=>{!e?.disabled&&L.warn("",...t)},info:(...t)=>{!e?.disabled&&L.info("",...t)},debug:(...t)=>{!e?.disabled&&L.debug("",...t)},box:(...t)=>{!e?.disabled&&L.box("",...t)},success:(...t)=>{!e?.disabled&&L.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
2
|
+
`)}}),P=Xe();var ie=e=>{let t=new Ye(e.clientId,e.clientSecret,f("google",e.redirectURI));return{id:"google",name:"Google",createAuthorizationURL({state:o,scopes:r,codeVerifier:n,redirectURI:s}){if(!e.clientId||!e.clientSecret)throw P.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new I("CLIENT_ID_AND_SECRET_REQUIRED");if(!n)throw new I("codeVerifier is required for Google");let i=r||["email","profile"];return t.createAuthorizationURL(o,n,i)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("google",e.redirectURI),options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(o){if(!o.idToken)return null;let r=et(o.idToken())?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}}};import{betterFetch as tt}from"@better-fetch/fetch";import{Spotify as rt}from"arctic";var ae=e=>{let t=new rt(e.clientId,e.clientSecret,f("spotify",e.redirectURI));return{id:"spotify",name:"Spotify",createAuthorizationURL({state:o,scopes:r}){let n=r||["user-read-email"];return t.createAuthorizationURL(o,n)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("spotify",e.redirectURI),options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(o){let{data:r,error:n}=await tt("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken()}`}});return n?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}}};import{betterFetch as ot}from"@better-fetch/fetch";import{Twitch as nt}from"arctic";var de=e=>{let t=new nt(e.clientId,e.clientSecret,f("twitch",e.redirectURI));return{id:"twitch",name:"Twitch",createAuthorizationURL({state:o,scopes:r}){let n=r||["activity:write","read"];return t.createAuthorizationURL(o,n)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("twitch",e.redirectURI),options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(o){let{data:r,error:n}=await ot("https://api.twitch.tv/helix/users",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken()}`}});return n?null:{user:{id:r.sub,name:r.preferred_username,email:r.email,image:r.picture,emailVerified:!1},data:r}}}};import{betterFetch as st}from"@better-fetch/fetch";import{Twitter as it}from"arctic";var ce=e=>{let t=new it(e.clientId,e.clientSecret,f("twitter",e.redirectURI));return{id:"twitter",name:"Twitter",createAuthorizationURL(o){let r=o.scopes||["account_info.read"];return t.createAuthorizationURL(o.state,o.codeVerifier,r)},validateAuthorizationCode:async(o,r,n)=>y({code:o,codeVerifier:r,redirectURI:n||f("twitch",e.redirectURI),options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(o){let{data:r,error:n}=await st("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken()}`}});return n||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}}};import"arctic";var at={apple:te,discord:re,facebook:oe,github:se,google:ie,spotify:ae,twitch:de,twitter:ce},le=Object.keys(at);import{generateState as dt}from"oslo/oauth2";import{z as O}from"zod";function ue(e,t,o){let r=dt();return{state:JSON.stringify({code:r,callbackURL:e,currentURL:t,dontRememberMe:o}),code:r}}function V(e){return O.object({code:O.string(),callbackURL:O.string().optional(),currentURL:O.string().optional(),dontRememberMe:O.boolean().optional()}).safeParse(JSON.parse(e))}import{APIError as ct}from"better-call";var pe=(e,t=!1)=>{let o=new Date;return new Date(o.getTime()+(t?e*1e3:e))};import{TimeSpan as Ro}from"oslo";async function U(e,t,o,r){let n=e.context.authCookies.sessionToken.options;n.maxAge=o?void 0:n.maxAge,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,n),o&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function C(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}import{z as me}from"zod";function $(e){let t="127.0.0.1";if(process.env.NODE_ENV==="test")return t;let o=["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"];for(let r of o){let n=e.headers.get(r);if(typeof n=="string"){let s=n.split(",")[0].trim();if(s)return s}}return null}var N=new Map;function lt(e,t){if(!e.request)return"";let{method:o,url:r,headers:n}=e.request,s=e.request.headers.get("User-Agent")||"",i=$(e.request)||"",a=JSON.stringify(n);return`${o}:${r}:${a}:${s}:${i}:${t}`}var M=()=>l("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let o=lt(e,t),r=N.get(o);if(r){if(r.expiresAt>Date.now())return e.json(r.data);N.delete(o)}let n=await e.context.internalAdapter.findSession(t);if(!n||n.session.expiresAt<new Date)return C(e),n&&await e.context.internalAdapter.deleteSession(n.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(n);let i=e.context.sessionConfig.expiresIn,a=e.context.sessionConfig.updateAge;if(n.session.expiresAt.valueOf()-i*1e3+a*1e3<=Date.now()){let c=await e.context.internalAdapter.updateSession(n.session.id,{expiresAt:pe(e.context.sessionConfig.expiresIn,!0)});if(!c)return C(e),e.json(null,{status:401});let m=(c.expiresAt.valueOf()-Date.now())/1e3;return await U(e,c.id,!1,{maxAge:m}),e.json({session:c,user:n.user})}return N.set(o,{data:n,expiresAt:Date.now()+5e3}),e.json(n)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),H=async e=>await M()({...e,_flag:void 0}),E=D(async e=>{let t=await H(e);if(!t?.session)throw new ct("UNAUTHORIZED");return{session:t}}),fe=()=>l("/user/list-sessions",{method:"GET",use:[E],requireHeaders:!0},async e=>{let o=(await e.context.adapter.findMany({model:e.context.tables.session.tableName,where:[{field:"userId",value:e.context.session.user.id}]})).filter(r=>r.expiresAt>new Date);return e.json(o)}),ge=l("/user/revoke-session",{method:"POST",body:me.object({id:me.string()}),use:[E],requireHeaders:!0},async e=>{let t=e.body.id,o=await e.context.internalAdapter.findSession(t);if(!o)return e.json(null,{status:400});if(o.session.userId!==e.context.session.user.id)return e.json(null,{status:403});try{await e.context.internalAdapter.deleteSession(t)}catch(r){return e.context.logger.error(r),e.json(null,{status:500})}return e.json({status:!0})}),he=l("/user/revoke-sessions",{method:"POST",use:[E],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}return e.json({status:!0})});var ye=l("/sign-in/social",{method:"POST",requireHeaders:!0,query:A.object({currentURL:A.string().optional()}).optional(),body:A.object({callbackURL:A.string().optional(),provider:A.enum(le),dontRememberMe:A.boolean().default(!1).optional()})},async e=>{let t=e.context.socialProviders.find(i=>i.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider to your auth config",{provider:e.body.provider}),new v("NOT_FOUND",{message:"Provider not found"});let o=e.context.authCookies,r=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${r?.origin}${e.body.callbackURL||""}`,s=ue(n||r?.origin||e.context.baseURL,e.query?.currentURL);try{await e.setSignedCookie(o.state.name,s.code,e.context.secret,o.state.options);let i=ut();await e.setSignedCookie(o.pkCodeVerifier.name,i,e.context.secret,o.pkCodeVerifier.options);let a=t.createAuthorizationURL({state:s.state,codeVerifier:i});return a.searchParams.set("redirect_uri",`${e.context.baseURL}/callback/${e.body.provider}`),{url:a.toString(),state:s.state,codeVerifier:i,redirect:!0}}catch{throw new v("INTERNAL_SERVER_ERROR")}}),we=l("/sign-in/email",{method:"POST",body:A.object({email:A.string().email(),password:A.string(),callbackURL:A.string().optional(),dontRememberMe:A.boolean().default(!1).optional()})},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!"),new v("BAD_REQUEST",{message:"Email and password is not enabled"});let t=await H(e);t&&await e.context.internalAdapter.deleteSession(t.session.id);let{email:o,password:r}=e.body;if(!A.string().email().safeParse(o).success)throw new v("BAD_REQUEST",{message:"Invalid email"});let s=await e.context.internalAdapter.findUserByEmail(o);if(!s)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:o}),new v("UNAUTHORIZED",{message:"Invalid email or password"});let i=s.accounts.find(c=>c.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:o}),new v("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:o}),new v("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new v("UNAUTHORIZED",{message:"Invalid email or password"});let u=await e.context.internalAdapter.createSession(s.user.id,e.headers,e.body.dontRememberMe);if(!u)throw e.context.logger.error("Failed to create session"),new v("INTERNAL_SERVER_ERROR");return await U(e,u.id,e.body.dontRememberMe),e.json({user:s.user,session:u,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as ft}from"better-call";import{z as B}from"zod";import{z as p}from"zod";var No=p.object({id:p.string(),providerId:p.string(),accountId:p.string(),userId:p.string(),accessToken:p.string().nullable().optional(),refreshToken:p.string().nullable().optional(),idToken:p.string().nullable().optional(),expiresAt:p.date().nullable().optional(),password:p.string().optional().nullable()}),be=p.object({id:p.string(),email:p.string().transform(e=>e.toLowerCase()),emailVerified:p.boolean().default(!1),name:p.string(),image:p.string().optional(),createdAt:p.date().default(new Date),updatedAt:p.date().default(new Date)}),Mo=p.object({id:p.string(),userId:p.string(),expiresAt:p.date(),ipAddress:p.string().optional(),userAgent:p.string().optional()});import{alphabet as pt,generateRandomString as mt}from"oslo/crypto";var Ae=()=>mt(36,pt("a-z","0-9"));var _={isAction:!1};function F(e){let t=e.accessToken(),o=e.hasRefreshToken()?e.refreshToken():void 0,r;try{r=e.accessTokenExpiresAt()}catch{}return{accessToken:t,refreshToken:o,expiresAt:r}}var ke=l("/callback/:id",{method:"GET",query:B.object({state:B.string(),code:B.string().optional(),error:B.string().optional()}),metadata:_},async e=>{if(e.query.error||!e.query.code){let b=V(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${b}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let o=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),r;try{r=await t.validateAuthorizationCode(e.query.code,o,`${e.context.baseURL}/callback/${t.id}`)}catch(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=oauth_code_verification_failed`)}let n=await t.getUserInfo(r).then(h=>h?.user),s=Ae(),i=be.safeParse({...n,id:s}),a=V(e.query.state);if(!a.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=invalid_state_parameter`);let{callbackURL:d,currentURL:u,dontRememberMe:c}=a.data;if(!n||i.success===!1)throw e.redirect(`${e.context.baseURL}/error?error=oauth_validation_failed`);if(!d)throw e.redirect(`${e.context.baseURL}/error?error=oauth_callback_url_not_found`);let m=await e.context.internalAdapter.findUserByEmail(n.email),g=m?.user.id;if(m){let h=m.accounts.find(R=>R.providerId===t.id),b=e.context.options.account?.accountLinking?.trustedProviders,z=b?b.includes(t.id):!0;if(!h&&(!n.emailVerified||!z)){let R;try{R=new URL(u||d),R.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(R.toString())}if(!h)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:n.id,id:`${t.id}:${n.id}`,userId:m.user.id,...F(r)})}catch(R){throw console.log(R),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(i.data,{...F(r),id:`${t.id}:${n.id}`,providerId:t.id,accountId:n.id,userId:s})}catch{let b=new URL(u||d);throw b.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",b.toString()),e.redirect(b.toString())}if(!g&&!s)throw new ft("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});let w=await e.context.internalAdapter.createSession(g||s,e.request,c);if(!w){let h=new URL(u||d);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await U(e,w.id,c)}catch(h){e.context.logger.error("Unable to set session cookie",h);let b=new URL(u||d);throw b.searchParams.set("error","unable_to_create_session"),e.redirect(b.toString())}throw e.redirect(d)});import{z as G}from"zod";var Re=l("/sign-out",{method:"POST",body:G.optional(G.object({callbackURL:G.string().optional()}))},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);return t?(await e.context.internalAdapter.deleteSession(t),C(e),e.json(null,{body:{redirect:!!e.body?.callbackURL,url:e.body?.callbackURL}})):e.json(null)});import{TimeSpan as gt}from"oslo";import{createJWT as ht,parseJWT as yt}from"oslo/jwt";import{validateJWT as Ue}from"oslo/jwt";import{z as k}from"zod";var Te=l("/forget-password",{method:"POST",body:k.object({email:k.string().email(),redirectTo:k.string()})},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)return e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function to your auth config!"),e.json(null,{status:400,statusText:"RESET_PASSWORD_EMAIL_NOT_SENT",body:{message:"Reset password isn't enabled"}});let{email:t}=e.body,o=await e.context.internalAdapter.findUserByEmail(t);if(!o)return e.json({status:!1},{body:{status:!0}});let r=await ht("HS256",Buffer.from(e.context.secret),{email:o.user.email,redirectTo:e.body.redirectTo},{expiresIn:new gt(1,"h"),issuer:"better-auth",subject:"forget-password",audiences:[o.user.email],includeIssuedTimestamp:!0}),n=`${e.context.baseURL}/reset-password/${r}`;return await e.context.options.emailAndPassword.sendResetPassword(n,o.user),e.json({status:!0})}),Pe=l("/reset-password/:token",{method:"GET"},async e=>{let{token:t}=e.params,o,r=k.object({email:k.string(),redirectTo:k.string()});try{if(o=await Ue("HS256",Buffer.from(e.context.secret),t),!o.expiresAt||o.expiresAt<new Date)throw Error("Token expired")}catch{let i=yt(t),a=r.safeParse(i?.payload);throw a.success?e.redirect(`${a.data?.redirectTo}?error=invalid_token`):e.redirect(`${e.context.baseURL}/error?error=invalid_token`)}let{redirectTo:n}=r.parse(o.payload);throw e.redirect(`${n}?token=${t}`)}),ve=l("/reset-password",{method:"POST",query:k.object({currentURL:k.string()}).optional(),body:k.object({newPassword:k.string(),callbackURL:k.string().optional()})},async e=>{let t=e.query?.currentURL.split("?token=")[1];if(!t)return e.json({error:"Invalid token",data:null},{status:400,statusText:"INVALID_TOKEN",body:{message:"Invalid token"}});let{newPassword:o}=e.body;try{let r=await Ue("HS256",Buffer.from(e.context.secret),t),n=k.string().email().parse(r.payload.email),s=await e.context.internalAdapter.findUserByEmail(n);if(!s)return e.json({error:"User not found",data:null},{status:400,body:{message:"failed to reset password"}});if(o.length<(e.context.options.emailAndPassword?.minPasswordLength||8)||o.length>(e.context.options.emailAndPassword?.maxPasswordLength||32))return e.json({data:null,error:"password is too short or too long"},{status:400,statusText:"INVALID_PASSWORD_LENGTH",body:{message:"password is too short or too long"}});let i=await e.context.password.hash(o);return await e.context.internalAdapter.updatePassword(s.user.id,i)?e.json({error:null,data:{status:!0,url:e.body.callbackURL,redirect:!!e.body.callbackURL}},{body:{status:!0,url:e.body.callbackURL,redirect:!!e.body.callbackURL}}):e.json(null,{status:400,statusText:"USER_NOT_FOUND",body:{message:"User doesn't have a credential account"}})}catch(r){return console.log(r),e.json({error:"Invalid token",data:null},{status:400,statusText:"INVALID_TOKEN",body:{message:"Invalid token"}})}});import{TimeSpan as wt}from"oslo";import{createJWT as bt,validateJWT as At}from"oslo/jwt";import{z as T}from"zod";async function W(e,t){return await bt("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new wt(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var xe=l("/send-verification-email",{method:"POST",query:T.object({currentURL:T.string().optional()}).optional(),body:T.object({email:T.string().email(),callbackURL:T.string().optional()})},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)return e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),e.json(null,{status:400,statusText:"VERIFICATION_EMAIL_NOT_SENT",body:{message:"Verification email isn't enabled"}});let{email:t}=e.body,o=await W(e.context.secret,t),r=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(t,r,o),e.json({status:!0})}),Se=l("/verify-email",{method:"GET",query:T.object({token:T.string(),callbackURL:T.string().optional()})},async e=>{let{token:t}=e.query,o;try{o=await At("HS256",Buffer.from(e.context.secret),t)}catch(a){return e.context.logger.error("Failed to verify email",a),e.json(null,{status:400,statusText:"INVALID_TOKEN",body:{message:"Invalid token"}})}let n=T.object({email:T.string().email()}).parse(o.payload),s=await e.context.internalAdapter.findUserByEmail(n.email);if(!s)return e.json(null,{status:400,statusText:"USER_NOT_FOUND",body:{message:"User not found"}});if(!s.accounts.find(a=>a.providerId==="credential"))throw e.redirect;if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw console.log("Redirecting to",e.query.callbackURL),e.redirect("/");return e.json({status:!0})});import{z as x}from"zod";import{alphabet as kt,generateRandomString as Rt}from"oslo/crypto";import"better-call";var _e=l("/user/update",{method:"POST",body:x.object({name:x.string().optional(),image:x.string().optional()}),use:[E]},async e=>{let{name:t,image:o}=e.body,r=e.context.session;if(!o&&!t)return e.json(r.user);let n=await e.context.internalAdapter.updateUserByEmail(r.user.email,{name:t,image:o});return e.json(n)}),Ie=l("/user/change-password",{method:"POST",body:x.object({newPassword:x.string(),currentPassword:x.string(),revokeOtherSessions:x.boolean().optional()}),use:[E]},async e=>{let{newPassword:t,currentPassword:o,revokeOtherSessions:r}=e.body,n=e.context.session,s=e.context.password.config.minPasswordLength;if(t.length<s)return e.context.logger.error("Password is too short"),e.json(null,{status:400,body:{message:"Password is too short"}});let i=e.context.password.config.maxPasswordLength;if(t.length>i)return e.context.logger.error("Password is too long"),e.json(null,{status:400,body:{message:"Password is too long"}});let d=(await e.context.internalAdapter.findAccounts(n.user.id)).find(m=>m.providerId==="credential"&&m.password);if(!d||!d.password)return e.json(null,{status:400,body:{message:"User does not have a password"}});let u=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,o))return e.json(null,{status:400,body:{message:"Invalid password"}});if(await e.context.internalAdapter.updateAccount(d.id,{password:u}),r){await e.context.internalAdapter.deleteSessions(n.user.id);let m=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!m)return e.json(null,{status:500,body:{message:"Failed to create session"}});await U(e,m.id)}return e.json(n.user)}),Le=l("/user/set-password",{method:"POST",body:x.object({newPassword:x.string()}),use:[E]},async e=>{let{newPassword:t}=e.body,o=e.context.session,r=e.context.password.config.minPasswordLength;if(t.length<r)return e.context.logger.error("Password is too short"),e.json(null,{status:400,body:{message:"Password is too short"}});let n=e.context.password.config.maxPasswordLength;if(t.length>n)return e.context.logger.error("Password is too long"),e.json(null,{status:400,body:{message:"Password is too long"}});let i=(await e.context.internalAdapter.findAccounts(o.user.id)).find(d=>d.providerId==="credential"&&d.password),a=await e.context.password.hash(t);return i?e.json(null,{status:400,body:{message:"User already has a password"}}):(await e.context.internalAdapter.linkAccount({id:Rt(32,kt("a-z","0-9","A-Z")),userId:o.user.id,providerId:"credential",accountId:o.user.id,password:a}),e.json(o.user))});import{alphabet as Ut,generateRandomString as Tt}from"oslo/crypto";var Ee=l("/csrf",{method:"GET",metadata:_},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t)return{csrfToken:t};let o=Tt(32,Ut("a-z","0-9","A-Z")),r=await j(e.context.secret,o),n=`${o}!${r}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:o}});var Pt=(e="Unknown")=>`<!DOCTYPE html>
|
|
3
3
|
<html lang="en">
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
@@ -79,4 +79,4 @@ var Je=Object.defineProperty,Ze=Object.defineProperties;var Ke=Object.getOwnProp
|
|
|
79
79
|
<div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
|
|
80
80
|
</div>
|
|
81
81
|
</body>
|
|
82
|
-
</html>`,
|
|
82
|
+
</html>`,Oe=l("/error",{method:"GET",metadata:_},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(Pt(t),{headers:{"Content-Type":"text/html"}})});var Ce=l("/ok",{method:"GET",metadata:_},async e=>e.json({ok:!0}));import{alphabet as je,generateRandomString as De}from"oslo/crypto";import{z as S}from"zod";var $e=l("/sign-up/email",{method:"POST",query:S.object({currentURL:S.string().optional()}).optional(),body:S.object({name:S.string(),email:S.string(),password:S.string(),image:S.string().optional(),callbackURL:S.string().optional()})},async e=>{if(!e.context.options.emailAndPassword?.enabled)return e.json(null,{status:400,body:{message:"Email and password is not enabled"}});let{name:t,email:o,password:r,image:n}=e.body;if(!S.string().email().safeParse(o).success)return e.json(null,{status:400,body:{message:"Invalid email address"}});let i=e.context.password.config.minPasswordLength;if(r.length<i)return e.context.logger.error("Password is too short"),e.json(null,{status:400,body:{message:"Password is too short"}});let a=e.context.password.config.maxPasswordLength;if(r.length>a)return e.context.logger.error("Password is too long"),e.json(null,{status:400,body:{message:"Password is too long"}});let d=await e.context.internalAdapter.findUserByEmail(o),u=await e.context.password.hash(r);if(d?.user)return e.json(null,{status:400,body:{message:"User already exists"}});let c=await e.context.internalAdapter.createUser({id:De(32,je("a-z","0-9","A-Z")),email:o.toLowerCase(),name:t,image:n,emailVerified:!1,createdAt:new Date,updatedAt:new Date});if(!c)return e.json(null,{status:400,body:{message:"Could not create user"}});await e.context.internalAdapter.linkAccount({id:De(32,je("a-z","0-9","A-Z")),userId:c.id,providerId:"credential",accountId:c.id,password:u});let m=await e.context.internalAdapter.createSession(c.id,e.request);if(!m)return e.json(null,{status:400,body:{message:"Could not create session"}});if(await U(e,m.id),e.context.options.emailAndPassword.sendEmailVerificationOnSignUp){let g=await W(e.context.secret,c.email),w=`${e.context.baseURL}/verify-email?token=${g}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailAndPassword.sendVerificationEmail?.(c.email,w,g)}return e.json({user:c,session:m},{body:e.body.callbackURL?{url:e.body.callbackURL,redirect:!0}:{user:c,session:m}})});import J from"chalk";function vt(e,t,o){let r=Date.now(),n=t*1e3;return r-o.lastRequest<n&&o.count>=e}function xt(e){return new Response(JSON.stringify({message:"Too many requests. Please try again later."}),{status:429,statusText:"Too Many Requests",headers:{"X-Retry-After":e.toString()}})}function St(e,t){let o=Date.now(),r=t*1e3;return Math.ceil((e+r-o)/1e3)}function _t(e,t){let o=t??"rateLimit",r=e.adapter;return{get:async n=>await r.findOne({model:o,where:[{field:"key",value:n}]}),set:async(n,s,i)=>{try{i?await r.update({model:t??"rateLimit",where:[{field:"key",value:n}],update:{count:s.count,lastRequest:s.lastRequest}}):await r.create({model:t??"rateLimit",data:{key:n,count:s.count,lastRequest:s.lastRequest}})}catch(a){P.error("Error setting rate limit",a)}}}}var Be=new Map;function It(e){return e.rateLimit.customStorage?e.rateLimit.customStorage:e.rateLimit.storage==="memory"?{async get(o){return Be.get(o)},async set(o,r,n){Be.set(o,r)}}:_t(e,e.rateLimit.tableName)}async function ze(e,t){if(!t.rateLimit.enabled)return;let o=t.baseURL,r=e.url.replace(o,""),n=t.rateLimit.window,s=t.rateLimit.max,i=$(e)+r,d=Lt().find(g=>g.pathMatcher(r));d&&(n=d.window,s=d.max);for(let g of t.options.plugins||[])if(g.rateLimit){let w=g.rateLimit.find(h=>h.pathMatcher(r));if(w){n=w.window,s=w.max;break}}if(t.rateLimit.customRules){let g=t.rateLimit.customRules[r];g&&(n=g.window,s=g.max)}let u=It(t),c=await u.get(i),m=Date.now();if(!c)await u.set(i,{key:i,count:1,lastRequest:m});else{let g=m-c.lastRequest;if(vt(s,n,c)){let w=St(c.lastRequest,n);return xt(w)}else g>n*1e3?await u.set(i,{...c,count:1,lastRequest:m}):await u.set(i,{...c,count:c.count+1,lastRequest:m})}}function Lt(){return[{pathMatcher(t){return t.startsWith("/sign-in")||t.startsWith("/sign-up")},window:10,max:7}]}function Ct(e,t){let o=t.plugins?.reduce((a,d)=>({...a,...d.endpoints}),{}),r=t.plugins?.map(a=>a.middlewares?.map(d=>{let u=async c=>d.middleware({...c,context:{...e,...c.context}});return u.path=d.path,u.options=d.middleware.options,u.headers=d.middleware.headers,{path:d.path,middleware:u}})).filter(a=>a!==void 0).flat()||[],s={...{signInOAuth:ye,callbackOAuth:ke,getCSRFToken:Ee,getSession:M(),signOut:Re,signUpEmail:$e,signInEmail:we,forgetPassword:Te,resetPassword:ve,verifyEmail:Se,sendVerificationEmail:xe,changePassword:Ie,setPassword:Le,updateUser:_e,forgetPasswordCallback:Pe,listSessions:fe(),revokeSession:ge,revokeSessions:he},...o,ok:Ce,error:Oe},i={};for(let[a,d]of Object.entries(s))i[a]=async u=>{let c=await e,g=await d({...u,context:{...c,...u.context}});for(let w of t.plugins||[])if(w.hooks?.after){for(let h of w.hooks.after)if(h.matcher(u)){let z=Object.assign(u,{context:{...e,returned:g}}),R=await h.handler(z);R&&"response"in R&&(g=R.response)}}return g},i[a].path=d.path,i[a].method=d.method,i[a].options=d.options,i[a].headers=d.headers;return{api:i,middlewares:r}}var Ns=(e,t)=>{let{api:o,middlewares:r}=Ct(e,t),n=new URL(e.baseURL).pathname;return Ot(o,{extraContext:e,basePath:n,routerMiddleware:[{path:"/**",middleware:Y},...r],async onRequest(s){for(let i of e.options.plugins||[])if(i.onRequest){let a=await i.onRequest(s,e);if(a)return a}return ze(s,e)},async onResponse(s){for(let i of e.options.plugins||[])if(i.onResponse){let a=await i.onResponse(s,e);if(a)return a.response}return s},onError(s){let i=t.logger?.verboseLogging?P:void 0;if(t.logger?.disabled!==!0)if(s instanceof Et)i?.warn(s);else if(typeof s=="object"&&s!==null&&"message"in s){let a=s.message;if(!a||typeof a!="string"){i?.error(s);return}a.includes("no such table")?P?.error(`Please run ${J.green("npx better-auth migrate")} to create the tables. There are missing tables in your SQLite database.`):a.includes("relation")&&a.includes("does not exist")?P.error(`Please run ${J.green("npx better-auth migrate")} to create the tables. There are missing tables in your PostgreSQL database.`):a.includes("Table")&&a.includes("doesn't exist")?P?.error(`Please run ${J.green("npx better-auth migrate")} to create the tables. There are missing tables in your MySQL database.`):i?.error(s)}else i?.error(s)}})};export{ke as callbackOAuth,Ie as changePassword,l as createAuthEndpoint,D as createAuthMiddleware,W as createEmailVerificationToken,Y as csrfMiddleware,Oe as error,Te as forgetPassword,Pe as forgetPasswordCallback,Ee as getCSRFToken,Ct as getEndpoints,M as getSession,H as getSessionFromCtx,fe as listSessions,Ce as ok,K as optionsMiddleware,ve as resetPassword,ge as revokeSession,he as revokeSessions,Ns as router,xe as sendVerificationEmail,E as sessionMiddleware,Le as setPassword,we as signInEmail,ye as signInOAuth,Re as signOut,$e as signUpEmail,_e as updateUser,Se as verifyEmail};
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
`)}}),c=H();import J from"path";import
|
|
2
|
+
import{Command as ye}from"commander";import"dotenv/config";import{Command as le}from"commander";import{loadConfig as I}from"c12";import{createConsola as _}from"consola";var A=_({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),H=e=>({log:(...t)=>{!e?.disabled&&A.log("",...t)},error:(...t)=>{!e?.disabled&&A.error("",...t)},warn:(...t)=>{!e?.disabled&&A.warn("",...t)},info:(...t)=>{!e?.disabled&&A.info("",...t)},debug:(...t)=>{!e?.disabled&&A.debug("",...t)},box:(...t)=>{!e?.disabled&&A.box("",...t)},success:(...t)=>{!e?.disabled&&A.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
3
|
+
`)}}),c=H();import J from"path";import Y from"@babel/preset-typescript";import Z from"@babel/preset-react";var w=["auth.ts","auth.tsx"];w=[...w,...w.map(e=>`lib/${e}`),...w.map(e=>`utils/${e}`)];w=[...w,...w.map(e=>`src/${e}`)];var E={transformOptions:{babel:{presets:[[Y,{isTSX:!0,allExtensions:!0}],[Z,{runtime:"automatic"}]]}},extensions:[".ts",".tsx",".js",".jsx"]};async function B({cwd:e,configPath:t}){try{let a=null;if(t){let{config:r}=await I({configFile:J.join(e,t),dotenv:!0,jitiOptions:E});!r.auth&&!r.default&&(c.error("[#better-auth]: Couldn't read your auth config. Make sure to default export your auth instance or to export as a variable named auth."),process.exit(1)),a=r.auth?.options||r.default?.options||null}if(!a)for(let r of w)try{let{config:i}=await I({configFile:r,jitiOptions:E});if(Object.keys(i).length>0){a=i.auth?.options||i.default?.options||null,a||(c.error("[#better-auth]: Couldn't read your auth config."),c.break(),c.info("[#better-auth]: Make sure to default export your auth instance or to export as a variable named auth."),process.exit(1));break}}catch(i){c.error(i),process.exit(1)}return a}catch(a){c.error("Error while reading your auth config.",a),process.exit(1)}}import{z as M}from"zod";import{existsSync as de}from"fs";import ce from"path";import{Kysely as ee}from"kysely";import{MysqlDialect as $,PostgresDialect as L,SqliteDialect as v}from"kysely";var b=class extends Error{constructor(t,a,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=a}};var te=async e=>{if(!e.database)return;if("createDriver"in e.database)return e.database;let t;if("provider"in e.database){let a=e.database.provider,r=e.database?.url?.trim();if(a==="postgres"){let o=(await import("pg").catch(s=>{throw new b("Please install `pg` to use postgres database")})).Pool;t=new L({pool:new o({connectionString:r})})}if(a==="mysql")try{let{createPool:i}=await import("mysql2/promise").catch(n=>{throw new b("Please install `mysql2` to use mysql database")}),o=new URL(r),s=i({host:o.hostname,user:o.username,password:o.password,database:o.pathname.split("/")[1],port:Number(o.port)});t=new $({pool:s})}catch(i){throw i instanceof TypeError?new b("Invalid database URL"):i}if(a==="sqlite")try{let i=await import("better-sqlite3"),o=i.default||i;if(!o)throw new b("Failed to import better-sqlite3. Make sure `better-sqlite3` is properly installed.");let s=new o(r);t=new v({database:s})}catch(i){throw console.error(i),new b("Failed to initialize SQLite. Make sure `better-sqlite3` is properly installed.")}}return t},T=async e=>{let t=await te(e);return t&&new ee({dialect:t})},F=e=>{if("provider"in e.database)return e.database.provider;if("dialect"in e.database){if(e.database.dialect instanceof L)return"postgres";if(e.database.dialect instanceof $)return"mysql";if(e.database.dialect instanceof v)return"sqlite"}return"sqlite"};import ue from"ora";import N from"chalk";import fe from"prompts";import"kysely";var k=e=>{let t=e.plugins?.reduce((l,d)=>{let f=d.schema;if(!f)return l;for(let[u,m]of Object.entries(f))l[u]={fields:{...l[u]?.fields,...m.fields},tableName:u};return l},{}),a=e.rateLimit?.storage==="database",r={rateLimit:{tableName:e.rateLimit?.tableName||"rateLimit",fields:{key:{type:"string"},count:{type:"number"},lastRequest:{type:"number"}}}},{user:i,session:o,account:s,...n}=t||{};return{user:{tableName:e.user?.modelName||"user",fields:{name:{type:"string",required:!0},email:{type:"string",unique:!0,required:!0},emailVerified:{type:"boolean",defaultValue:()=>!1,required:!0},image:{type:"string",required:!1},createdAt:{type:"date",defaultValue:()=>new Date,required:!0},updatedAt:{type:"date",defaultValue:()=>new Date,required:!0},...i?.fields},order:0},session:{tableName:e.session?.modelName||"session",fields:{expiresAt:{type:"date",required:!0},ipAddress:{type:"string",required:!1},userAgent:{type:"string",required:!1},userId:{type:"string",references:{model:"user",field:"id",onDelete:"cascade"},required:!0},...o?.fields},order:1},account:{tableName:e.account?.modelName||"account",fields:{accountId:{type:"string",required:!0},providerId:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id",onDelete:"cascade"},required:!0},accessToken:{type:"string",required:!1},refreshToken:{type:"string",required:!1},idToken:{type:"string",required:!1},expiresAt:{type:"date",required:!1},password:{type:"string",required:!1},...s?.fields},order:2},...n,...a?r:{}}};function re(e){return e.plugins?.flatMap(a=>Object.keys(a.schema||{}).map(r=>{let o=(a.schema||{})[r];if(!o?.disableMigration)return{tableName:r,fields:o?.fields}}).filter(r=>r!==void 0))||[]}function P(e){let t=k(e),a=re(e);return[t.user,t.session,t.account,...a].reduce((i,o)=>(i[o.tableName]={fields:{...i[o.tableName]?.fields,...o.fields}},i),{})}var ae={string:["character varying","text"],number:["int4","integer","bigint","smallint","numeric","real","double precision"],boolean:["bool","boolean"],date:["timestamp","date"]},oe={string:["varchar","text"],number:["integer","int","bigint","smallint","decimal","float","double"],boolean:["boolean"],date:["date","datetime"]},ie={string:["TEXT"],number:["INTEGER","REAL"],boolean:["INTEGER","BOOLEAN"],date:["DATE","INTEGER"]},se={postgres:ae,mysql:oe,sqlite:ie};function ne(e,t,a){return se[a][t].map(s=>s.toLowerCase()).includes(e.toLowerCase())}async function D(e){let t=P(e),a=F(e),r=await T(e);r||(c.error("Invalid database configuration."),process.exit(1));let i=await r.introspection.getTables(),o=[],s=[];for(let[u,m]of Object.entries(t)){let h=i.find(y=>y.name===u);if(!h){let y=o.findIndex(O=>O.table===u),p={table:u,fields:m.fields,order:m.order||1/0},q=o.findIndex(O=>(O.order||1/0)>p.order);q===-1?y===-1?o.push(p):o[y].fields={...o[y].fields,...m.fields}:o.splice(q,0,p);continue}let g={};for(let[y,p]of Object.entries(m.fields)){let q=h.columns.find(O=>O.name===y);if(!q){g[y]=p;continue}ne(q.dataType,p.type,a)||c.warn(`Field ${y} in table ${u} has a different type in the database. Expected ${p.type} but got ${q.dataType}.`)}Object.keys(g).length>0&&s.push({table:u,fields:g,order:m.order||1/0})}let n=[];function l(u){let m={string:"text",boolean:"boolean",number:"integer",date:"date"};return a==="mysql"&&u==="string"?"varchar(255)":m[u]}if(s.length)for(let u of s)for(let[m,h]of Object.entries(u.fields)){let g=l(h.type),y=r.schema.alterTable(u.table).addColumn(m,g,p=>(p=h.required!==!1?p.notNull():p,h.references&&(p=p.references(`${h.references.model}.${h.references.field}`)),p));n.push(y)}if(o.length)for(let u of o){let m=r.schema.createTable(u.table).addColumn("id",l("string"),h=>h.primaryKey());for(let[h,g]of Object.entries(u.fields)){let y=l(g.type);m=m.addColumn(h,y,p=>(p=g.required!==!1?p.notNull():p,g.references&&(p=p.references(`${g.references.model}.${g.references.field}`)),g.unique&&(p=p.unique()),p))}n.push(m)}async function d(){for(let u of n)await u.execute()}async function f(){return n.map(m=>m.compile().sql).join(`;
|
|
4
|
+
|
|
5
|
+
`)}return{toBeCreated:o,toBeAdded:s,runMigrations:d,compileMigrations:f}}var K=new le("migrate").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("--config <config>","the path to the configuration file. defaults to the first configuration file found.").option("--y","").action(async e=>{let t=M.object({cwd:M.string(),config:M.string().optional()}).parse(e),a=ce.resolve(t.cwd);de(a)||(c.error(`The directory "${a}" does not exist.`),process.exit(1));let r=await B({cwd:a,configPath:t.config});if(!r){c.error("No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag.");return}await T(r)||(c.error("Invalid database configuration."),process.exit(1));let o=ue("preparing migration...").start(),{toBeAdded:s,toBeCreated:n,runMigrations:l}=await D(r);!s.length&&!n.length&&(o.stop(),c.success("\u{1F680} No migrations needed."),process.exit(0)),o.stop(),c.info("\u{1F511} The migration will affect the following:");for(let f of[...n,...s])c.info("->",N.magenta(Object.keys(f.fields).join(", ")),N.white("fields on"),N.yellow(`${f.table}`),N.white("table."));let{migrate:d}=await fe({type:"confirm",name:"migrate",message:"Are you sure you want to run these migrations?",initial:!1});d||(c.info("Migration cancelled."),process.exit(0)),o?.start("migrating..."),await l(),o.stop(),c.success("\u{1F680} migration was completed successfully!"),process.exit(0)});import{Command as pe}from"commander";import{z as j}from"zod";import{existsSync as W}from"fs";import x from"path";import me from"ora";import U from"prompts";function C(e){if(!e)return{and:null,or:null};let t=e?.filter(r=>r.connector==="AND"||!r.connector).reduce((r,i)=>({...r,[i.field]:i.value}),{}),a=e?.filter(r=>r.connector==="OR").reduce((r,i)=>({...r,[i.field]:i.value}),{});return{and:Object.keys(t).length?t:null,or:Object.keys(a).length?a:null}}function S(e,t,a){for(let r in e)e[r]===0&&t[r]?.type==="boolean"&&a?.boolean&&(e[r]=!1),e[r]===1&&t[r]?.type==="boolean"&&a?.boolean&&(e[r]=!0),t[r]?.type==="date"&&(e[r]instanceof Date||(e[r]=new Date(e[r])));return e}function z(e,t){for(let a in e)typeof e[a]=="boolean"&&t?.boolean&&(e[a]=e[a]?1:0),e[a]instanceof Date&&(e[a]=e[a].toISOString());return e}var V=(e,t)=>({id:"kysely",async create(a){let{model:r,data:i,select:o}=a;t?.transform&&(i=z(i,t.transform));let s=await e.insertInto(r).values(i).returningAll().executeTakeFirst();if(t?.transform){let n=t.transform.schema[r];s=n?S(i,n,t.transform):s}return o?.length&&(s=s?o.reduce((l,d)=>s?.[d]?{...l,[d]:s[d]}:l,{}):null),s},async findOne(a){let{model:r,where:i,select:o}=a,{and:s,or:n}=C(i),l=e.selectFrom(r).selectAll();n&&(l=l.where(f=>f.or(n))),s&&(l=l.where(f=>f.and(s)));let d=await l.executeTakeFirst();if(o?.length&&(d=d?o.reduce((u,m)=>d?.[m]?{...u,[m]:d[m]}:u,{}):null),t?.transform){let f=t.transform.schema[r];return d=d&&f?S(d,f,t.transform):d,d||null}return d||null},async findMany(a){let{model:r,where:i}=a,o=e.selectFrom(r),{and:s,or:n}=C(i);s&&(o=o.where(d=>d.and(s))),n&&(o=o.where(d=>d.or(n)));let l=await o.selectAll().execute();if(t?.transform){let d=t.transform.schema[r];return d?l.map(f=>S(f,d,t.transform)):l}return l},async update(a){let{model:r,where:i,update:o}=a,{and:s,or:n}=C(i);t?.transform&&(o=z(o,t.transform));let l=e.updateTable(r).set(o);s&&(l=l.where(f=>f.and(s))),n&&(l=l.where(f=>f.or(n)));let d=await l.returningAll().executeTakeFirst()||null;if(t?.transform){let f=t.transform.schema[r];return f?S(d,f,t.transform):d}return d},async delete(a){let{model:r,where:i}=a,{and:o,or:s}=C(i),n=e.deleteFrom(r);o&&(n=n.where(l=>l.and(o))),s&&(n=n.where(l=>l.or(s))),await n.execute()},async createSchema(a){let{compileMigrations:r}=await D(a);return console.log(r),{code:await r(),fileName:`./better-auth_migrations/${new Date().toISOString()}.sql`}}});async function G(e){if(!e.database)throw new b("Database configuration is required");if("create"in e.database)return e.database;let t=await T(e);if(!t)throw new b("Failed to initialize database adapter");let a=k(e),r={};for(let i of Object.values(a))r[i.tableName]=i.fields;return V(t,{transform:{schema:r,date:!0,boolean:F(e)==="sqlite"}})}import R from"fs/promises";import X from"chalk";var Q=new pe("generate").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).option("--config <config>","the path to the configuration file. defaults to the first configuration file found.").option("--out <output>","the file to output to the generated schema").option("--y","").action(async e=>{let t=j.object({cwd:j.string(),config:j.string().optional(),out:j.string().optional()}).parse(e),a=x.resolve(t.cwd);W(a)||(c.error(`The directory "${a}" does not exist.`),process.exit(1));let r=await B({cwd:a,configPath:t.config});if(!r){c.error("No configuration file found. Add a `auth.ts` file to your project or pass the path to the configuration file using the `--config` flag.");return}let i=await G(r);i.createSchema||(c.error("The adapter does not support schema generation."),process.exit(1));let o=me("preparing schema...").start(),{code:s,fileName:n,append:l}=await i.createSchema(r,t.out);if(o.stop(),l){let{append:u}=await U({type:"confirm",name:"append",message:`The file ${n} already exists. Do you want to ${X.yellow("append")} the schema to the file?`});u?(await R.appendFile(x.join(a,n),s),c.success("\u{1F680} schema was appended successfully!"),process.exit(0)):(c.error("Schema generation aborted."),process.exit(1))}let{confirm:d}=await U({type:"confirm",name:"confirm",message:`Do you want to generate the schema to ${X.yellow(n)}?`});d||(c.error("Schema generation aborted."),process.exit(1)),W(x.dirname(x.join(a,n)))||await R.mkdir(x.dirname(x.join(a,n)),{recursive:!0}),await R.writeFile(t.out||x.join(a,n),s),c.success("\u{1F680} schema was generated successfully!"),process.exit(0)});async function he(){let e=new ye().name("better-auth");e.addCommand(K).addCommand(Q),e.parse()}he();
|
package/dist/client/plugins.d.ts
CHANGED
|
@@ -2,17 +2,15 @@ import * as nanostores from 'nanostores';
|
|
|
2
2
|
import { A as AccessControl, S as StatementsPrimitive, R as Role } from '../statement-CU-fdHXK.js';
|
|
3
3
|
import * as _better_fetch_fetch from '@better-fetch/fetch';
|
|
4
4
|
import { BetterFetchOption } from '@better-fetch/fetch';
|
|
5
|
-
import { o as organization, d as Organization, M as Member, I as Invitation, u as username, m as magicLink } from '../index-
|
|
6
|
-
export { g as getPasskeyActions, c as passkeyClient, a as twoFactorClient } from '../index-
|
|
5
|
+
import { o as organization, d as Organization, M as Member, I as Invitation, u as username, m as magicLink } from '../index-CmzUOocy.js';
|
|
6
|
+
export { g as getPasskeyActions, c as passkeyClient, a as twoFactorClient } from '../index-CmzUOocy.js';
|
|
7
7
|
import { P as Prettify } from '../helper-C1ihmerM.js';
|
|
8
|
-
import '../
|
|
8
|
+
import '../index-CE92ti2Z.js';
|
|
9
|
+
import 'arctic';
|
|
9
10
|
import 'zod';
|
|
10
11
|
import 'better-call';
|
|
11
|
-
import '../index-
|
|
12
|
+
import '../index-gO-yM4kI.js';
|
|
12
13
|
import 'kysely';
|
|
13
|
-
import '../social.js';
|
|
14
|
-
import 'arctic';
|
|
15
|
-
import '../adapter-D-m9-hQp.js';
|
|
16
14
|
import '@simplewebauthn/types';
|
|
17
15
|
|
|
18
16
|
interface OrganizationClientOptions {
|
package/dist/client/plugins.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
`)}}),
|
|
1
|
+
import{atom as g}from"nanostores";var u=class extends Error{path;constructor(e,a){super(e),this.path=a}},m=class{constructor(e){this.s=e;this.statements=e}statements;newRole(e){return new f(e)}},f=class r{statements;constructor(e){this.statements=e}authorize(e,a){for(let[i,t]of Object.entries(e)){let s=this.statements[i];if(!s)return{success:!1,error:`You are not allowed to access resource: ${i}`};let o=a==="OR"?t.some(n=>s.includes(n)):t.every(n=>s.includes(n));return o?{success:o}:{success:!1,error:`unauthorized to access resource "${i}"`}}return{success:!1,error:"Not authorized"}}static fromString(e){let a=JSON.parse(e);if(typeof a!="object")throw new u("statements is not an object",".");for(let[i,t]of Object.entries(a)){if(typeof i!="string")throw new u("invalid resource identifier",i);if(!Array.isArray(t))throw new u("actions is not an array",i);for(let s=0;s<t.length;s++)if(typeof t[s]!="string")throw new u("action is not a string",`${i}[${s}]`)}return new r(a)}toString(){return JSON.stringify(this.statements)}};var h=r=>new m(r),P={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},d=h(P),U=d.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),v=d.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),E=d.newRole({organization:[],member:[],invitation:[]});import{createFetch as ee}from"@better-fetch/fetch";import"nanostores";import{betterFetch as K}from"@better-fetch/fetch";import{atom as me}from"nanostores";import"@better-fetch/fetch";import{atom as A,onMount as O}from"nanostores";var p=(r,e,a,i)=>{let t=A({data:null,error:null,isPending:!1}),s=()=>{let n=typeof i=="function"?i({data:t.get().data,error:t.get().error,isPending:t.get().isPending}):i;return a(e,{...n,onSuccess:async c=>{t.set({data:c.data,error:null,isPending:!1}),await n?.onSuccess?.(c)},async onError(c){t.set({error:c.error,data:null,isPending:!1}),await n?.onError?.(c)},async onRequest(c){let y=t.get();t.set({isPending:!0,data:y.data,error:y.error}),await n?.onRequest?.(c)}})};r=Array.isArray(r)?r:[r];let o=!1;for(let n of r)n.subscribe(()=>{o?s():O(t,()=>(s(),o=!0,()=>{t.off(),n.off()}))});return t};var ve=r=>{let e=g(void 0),a=g(!1),i=g(!1);return{id:"organization",$InferServerPlugin:{},getActions:t=>({$Infer:{ActiveOrganization:{},Organization:{},Invitation:{},Member:{}},organization:{setActive(s){e.set(s)},hasPermission:async s=>await t("/organization/has-permission",{method:"POST",body:{permission:s.permission},...s.fetchOptions})}}),getAtoms:t=>{let s=p(a,"/organization/list",t,{method:"GET"}),o=p([e,i],"/organization/activate",t,()=>({method:"POST",credentials:"include",body:{orgId:e.get()}}));return{_listOrg:a,_activeOrgSignal:i,activeOrganization:o,listOrganizations:s}},atomListeners:[{matcher(t){return t==="/organization/create"||t==="/organization/delete"},signal:"_listOrg"},{matcher(t){return t.startsWith("/organization")},signal:"_activeOrgSignal"}]}};var Ie=()=>({id:"username",$InferServerPlugin:{}});import{WebAuthnError as T,startAuthentication as w,startRegistration as x}from"@simplewebauthn/browser";import{createConsola as b}from"consola";var l=b({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),R=r=>({log:(...e)=>{!r?.disabled&&l.log("",...e)},error:(...e)=>{!r?.disabled&&l.error("",...e)},warn:(...e)=>{!r?.disabled&&l.warn("",...e)},info:(...e)=>{!r?.disabled&&l.info("",...e)},debug:(...e)=>{!r?.disabled&&l.debug("",...e)},box:(...e)=>{!r?.disabled&&l.box("",...e)},success:(...e)=>{!r?.disabled&&l.success("",...e)},break:(...e)=>{!r?.disabled&&console.log(`
|
|
2
|
+
`)}}),ze=R();import{atom as k}from"nanostores";var C=(r,{_listPasskeys:e})=>({signIn:{passkey:async(t,s)=>{let o=await r("/passkey/generate-authenticate-options",{method:"POST",body:{email:t?.email,callbackURL:t?.callbackURL}});if(!o.data)return o;try{let n=await w(o.data,t?.autoFill||!1),c=await r("/passkey/verify-authentication",{body:{response:n},...t?.fetchOptions,...s});if(!c.data)return c}catch(n){console.log(n)}}},passkey:{addPasskey:async(t,s)=>{let o=await r("/passkey/generate-register-options",{method:"GET"});if(!o.data)return o;try{let n=await x(o.data),c=await r("/passkey/verify-registration",{...t?.fetchOptions,...s,body:{response:n,name:t?.name}});if(!c.data)return c;e.set(Math.random())}catch(n){return n instanceof T?n.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:n.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:n.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:n instanceof Error?n.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),De=()=>{let r=k();return{id:"passkey",$InferServerPlugin:{},getActions:e=>C(e,{_listPasskeys:r}),getAtoms(e){return{listPasskeys:p(r,"/passkey/list-user-passkeys",e,{method:"GET",credentials:"include"}),_listPasskeys:r}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(e){return e==="/passkey/verify-registration"||e==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var Ke=(r={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:e=>e==="/two-factor/enable"||e==="/two-factor/send-otp"||e==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(e){e.data?.twoFactorRedirect&&(r.redirect||r.twoFactorPage)&&typeof window<"u"&&(window.location.href=r.twoFactorPage)}}}]});var Je=()=>({id:"magic-link",$InferServerPlugin:{}});export{C as getPasskeyActions,Je as magicLinkClient,ve as organizationClient,De as passkeyClient,Ke as twoFactorClient,Ie as usernameClient};
|