@lunora/auth 1.0.0-alpha.125 → 1.0.0-alpha.127
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/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/middleware.d.mts +1 -1
- package/dist/middleware.d.ts +1 -1
- package/dist/packem_shared/LunoraAuthAdminError-4r29Kj_y.mjs +1 -0
- package/dist/packem_shared/{create-auth.d-hkN1GE5-.d.mts → create-auth.d-D1CKOFWc.d.mts} +4 -0
- package/dist/packem_shared/{create-auth.d-hkN1GE5-.d.ts → create-auth.d-D1CKOFWc.d.ts} +4 -0
- package/dist/packem_shared/createSignUpInvitation-ClvskwuB.mjs +1 -0
- package/dist/packem_shared/{invite-only.d-C9Su82Iq.d.ts → invite-only.d-CsPJWAwM.d.ts} +1 -1
- package/dist/packem_shared/{invite-only.d-DsVdKwcp.d.mts → invite-only.d-DKyHHkkQ.d.mts} +1 -1
- package/dist/plugins.d.mts +2 -2
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.mjs +1 -1
- package/dist/schema.d.mts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/sql-store.mjs +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/LunoraAuthAdminError-DVW1DiAt.mjs +0 -1
- package/dist/packem_shared/createSignUpInvitation-CqqQc4S8.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { D as DoStorageLike } from "./packem_shared/adapter.d-DrD3bb1u.mjs";
|
|
2
2
|
export { l as lunoraAuthAdapter, a as lunoraD1Adapter, b as lunoraDoAdapter } from "./packem_shared/adapter.d-DrD3bb1u.mjs";
|
|
3
3
|
import { LunoraError } from '@lunora/errors';
|
|
4
|
-
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
5
|
-
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-
|
|
4
|
+
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-D1CKOFWc.mjs";
|
|
5
|
+
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-D1CKOFWc.mjs";
|
|
6
6
|
import { AppendAuthAuditEntry, AppendAuthAuditOptions, AuthAuditEvent, AuthAuditReader } from "./audit.mjs";
|
|
7
7
|
export { AUTH_AUDIT_TABLE, type AuthAuditEntry, type AuthAuditOutcome, type ReadAuthAuditOptions, appendAuthAuditEntry, createAuthAuditReader, ensureAuthAuditTable, readAuthAuditLog } from "./audit.mjs";
|
|
8
8
|
import { createAuthMiddleware } from 'better-auth/api';
|
|
@@ -11,7 +11,7 @@ export { createSqlAuthStore, d1Executor } from "./sql-store.mjs";
|
|
|
11
11
|
import { BetterAuthOptions } from 'better-auth';
|
|
12
12
|
import { EmailClassification, EmailGateConfig } from "./email-guard.mjs";
|
|
13
13
|
export { type EmailClass, type EmailGateMiddlewareOptions, assertEmailAllowed, classifyEmail, emailGateMiddleware, loadEmailDomainLists } from "./email-guard.mjs";
|
|
14
|
-
export { type I as InviteOnlyOptions, type a as IssuedSignUpInvitation, type S as SignUpInvitation, c as createSignUpInvitation, l as listSignUpInvitations, p as pruneSignUpInvitations, r as revokeSignUpInvitation } from "./packem_shared/invite-only.d-
|
|
14
|
+
export { type I as InviteOnlyOptions, type a as IssuedSignUpInvitation, type S as SignUpInvitation, c as createSignUpInvitation, l as listSignUpInvitations, p as pruneSignUpInvitations, r as revokeSignUpInvitation } from "./packem_shared/invite-only.d-DKyHHkkQ.mjs";
|
|
15
15
|
export { type LunoraAuthApiContext, LunoraAuthHeadersError, type WithAuthPluginsMiddleware, type WithAuthPluginsOptions, withAuthPlugins } from "./middleware.mjs";
|
|
16
16
|
export { default as authTables } from "./schema.mjs";
|
|
17
17
|
export { type AuthQuery, type AuthRow, type AuthStore, type AuthWhereClause, createMemoryAuthStore, matchesWhere } from "./store.mjs";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { D as DoStorageLike } from "./packem_shared/adapter.d-2a61HAY2.js";
|
|
2
2
|
export { l as lunoraAuthAdapter, a as lunoraD1Adapter, b as lunoraDoAdapter } from "./packem_shared/adapter.d-2a61HAY2.js";
|
|
3
3
|
import { LunoraError } from '@lunora/errors';
|
|
4
|
-
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
5
|
-
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-
|
|
4
|
+
import { L as LunoraAuth, a as LunoraAuthOptions } from "./packem_shared/create-auth.d-D1CKOFWc.js";
|
|
5
|
+
export { c as createAuth, r as resolveAuthOptions } from "./packem_shared/create-auth.d-D1CKOFWc.js";
|
|
6
6
|
import { AppendAuthAuditEntry, AppendAuthAuditOptions, AuthAuditEvent, AuthAuditReader } from "./audit.js";
|
|
7
7
|
export { AUTH_AUDIT_TABLE, type AuthAuditEntry, type AuthAuditOutcome, type ReadAuthAuditOptions, appendAuthAuditEntry, createAuthAuditReader, ensureAuthAuditTable, readAuthAuditLog } from "./audit.js";
|
|
8
8
|
import { createAuthMiddleware } from 'better-auth/api';
|
|
@@ -11,7 +11,7 @@ export { createSqlAuthStore, d1Executor } from "./sql-store.js";
|
|
|
11
11
|
import { BetterAuthOptions } from 'better-auth';
|
|
12
12
|
import { EmailClassification, EmailGateConfig } from "./email-guard.js";
|
|
13
13
|
export { type EmailClass, type EmailGateMiddlewareOptions, assertEmailAllowed, classifyEmail, emailGateMiddleware, loadEmailDomainLists } from "./email-guard.js";
|
|
14
|
-
export { type I as InviteOnlyOptions, type a as IssuedSignUpInvitation, type S as SignUpInvitation, c as createSignUpInvitation, l as listSignUpInvitations, p as pruneSignUpInvitations, r as revokeSignUpInvitation } from "./packem_shared/invite-only.d-
|
|
14
|
+
export { type I as InviteOnlyOptions, type a as IssuedSignUpInvitation, type S as SignUpInvitation, c as createSignUpInvitation, l as listSignUpInvitations, p as pruneSignUpInvitations, r as revokeSignUpInvitation } from "./packem_shared/invite-only.d-CsPJWAwM.js";
|
|
15
15
|
export { type LunoraAuthApiContext, LunoraAuthHeadersError, type WithAuthPluginsMiddleware, type WithAuthPluginsOptions, withAuthPlugins } from "./middleware.js";
|
|
16
16
|
export { default as authTables } from "./schema.js";
|
|
17
17
|
export { type AuthQuery, type AuthRow, type AuthStore, type AuthWhereClause, createMemoryAuthStore, matchesWhere } from "./store.js";
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as r,a as o,b as a}from"./packem_shared/adapter-DA8DdALX.mjs";import{LunoraAuthAdminError as A,createAuthAdmin as u}from"./packem_shared/LunoraAuthAdminError-
|
|
1
|
+
import{l as r,a as o,b as a}from"./packem_shared/adapter-DA8DdALX.mjs";import{LunoraAuthAdminError as A,createAuthAdmin as u}from"./packem_shared/LunoraAuthAdminError-4r29Kj_y.mjs";import{AUTH_AUDIT_TABLE as s,appendAuthAuditEntry as m,createAuthAuditReader as l,ensureAuthAuditTable as p,readAuthAuditLog as d}from"./audit.mjs";import{authAuditHook as E,buildAuditEntry as f,eventForPath as T,withAuthAudit as S}from"./packem_shared/authAuditHook-C9Gt2iYp.mjs";import{READ_AUDIT_PATH as _,INTERNAL_SECRET_HEADER as D,RESOLVE_SESSION_PATH as H,LunoraAuthDO as c}from"./packem_shared/AUTH_DO_AUDIT_PATH-ucS0M60j.mjs";import{createAuth as U,resolveAuthOptions as R}from"./packem_shared/createAuth-8aUw8v8D.mjs";import{authDoColumnAdditions as v,authDoSchemaStatements as L}from"./packem_shared/authDoColumnAdditions-UwF3Rl41.mjs";import{createDoAuthWiring as O}from"./packem_shared/createDoAuthWiring-68YJP-VM.mjs";import{emailGateDatabaseHooks as N,withEmailGate as w}from"./packem_shared/emailGateDatabaseHooks-CAygR3iq.mjs";import{assertEmailAllowed as M,classifyEmail as C,emailGateMiddleware as k,loadEmailDomainLists as q}from"./email-guard.mjs";import{DEFAULT_AUTH_BASE_PATH as G,handleAuthRequest as B}from"./packem_shared/DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";import{createSignUpInvitation as W,listSignUpInvitations as Y,pruneSignUpInvitations as j,revokeSignUpInvitation as z}from"./packem_shared/createSignUpInvitation-ClvskwuB.mjs";import{legacyIssuerCleanupStatements as K}from"./packem_shared/legacyIssuerCleanupStatements-D9Kf8OD1.mjs";import{LunoraAuthHeadersError as X,withAuthPlugins as Z}from"./middleware.mjs";import{compileMigrationsSql as tt,ensureMigrated as et}from"./packem_shared/compileMigrationsSql-ByVJhjR6.mjs";import{default as ot}from"./schema.mjs";import{sessionPresets as it,validateSessionPolicy as At}from"./packem_shared/sessionPresets-C867Mlo4.mjs";import{createSqlAuthStore as nt,d1Executor as st}from"./sql-store.mjs";import{createMemoryAuthStore as lt,matchesWhere as pt}from"./store.mjs";import{TURNSTILE_VERIFY_ENDPOINT as ht,verifyTurnstile as Et}from"./turnstile.mjs";import{verifyTurnstileMiddleware as Tt}from"./turnstile-middleware.mjs";export{s as AUTH_AUDIT_TABLE,_ as AUTH_DO_AUDIT_PATH,D as AUTH_DO_SECRET_HEADER,H as AUTH_DO_SESSION_PATH,G as DEFAULT_AUTH_BASE_PATH,A as LunoraAuthAdminError,c as LunoraAuthDO,X as LunoraAuthHeadersError,ht as TURNSTILE_VERIFY_ENDPOINT,m as appendAuthAuditEntry,M as assertEmailAllowed,E as authAuditHook,v as authDoColumnAdditions,L as authDoSchemaStatements,ot as authTables,f as buildAuditEntry,C as classifyEmail,tt as compileMigrationsSql,U as createAuth,u as createAuthAdmin,l as createAuthAuditReader,O as createDoAuthWiring,lt as createMemoryAuthStore,W as createSignUpInvitation,nt as createSqlAuthStore,st as d1Executor,N as emailGateDatabaseHooks,k as emailGateMiddleware,p as ensureAuthAuditTable,et as ensureMigrated,T as eventForPath,B as handleAuthRequest,K as legacyIssuerCleanupStatements,Y as listSignUpInvitations,q as loadEmailDomainLists,r as lunoraAuthAdapter,o as lunoraD1Adapter,a as lunoraDoAdapter,pt as matchesWhere,j as pruneSignUpInvitations,d as readAuthAuditLog,R as resolveAuthOptions,z as revokeSignUpInvitation,it as sessionPresets,At as validateSessionPolicy,Et as verifyTurnstile,Tt as verifyTurnstileMiddleware,S as withAuthAudit,Z as withAuthPlugins,w as withEmailGate};
|
package/dist/middleware.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
import { L as LunoraAuth } from "./packem_shared/create-auth.d-
|
|
2
|
+
import { L as LunoraAuth } from "./packem_shared/create-auth.d-D1CKOFWc.mjs";
|
|
3
3
|
import 'better-auth';
|
|
4
4
|
/**
|
|
5
5
|
* Structural mirror of `@lunora/server`'s `MiddlewareNext` — the continuation
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LunoraError } from '@lunora/errors';
|
|
2
|
-
import { L as LunoraAuth } from "./packem_shared/create-auth.d-
|
|
2
|
+
import { L as LunoraAuth } from "./packem_shared/create-auth.d-D1CKOFWc.js";
|
|
3
3
|
import 'better-auth';
|
|
4
4
|
/**
|
|
5
5
|
* Structural mirror of `@lunora/server`'s `MiddlewareNext` — the continuation
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as M}from"@lunora/errors";import{getAuthTables as b}from"better-auth/db";import{revokeSignUpInvitation as U,createSignUpInvitation as R}from"./createSignUpInvitation-ClvskwuB.mjs";class f extends M{constructor(c,h){super(h,c,{name:"LunoraAuthAdminError"})}}const N=50,D=500,O=3600,E=O*24,T=100*365*24*60*60,z=2880*60*1e3,k=[{field:"userId",model:"member"},{field:"userId",model:"teamMember"},{field:"userId",model:"passkey"},{field:"userId",model:"twoFactor"},{field:"userId",model:"oauthAccessToken"},{field:"userId",model:"oauthRefreshToken"},{field:"userId",model:"oauthConsent"},{field:"userId",model:"deviceCode"},{field:"userId",model:"walletAddress"},{field:"inviterId",model:"invitation"}],L=new Set(["accessToken","backupCodes","idToken","password","publicKey","refreshToken","secret","token","tokenHash"]),C=o=>Math.min(Math.max(Math.trunc(o??N),1),D),P=o=>Math.max(0,Math.trunc(o??0)),u=o=>{const c={};for(const[h,l]of Object.entries(o))L.has(h)||(c[h]=l instanceof Date?l.getTime():l);return c},g=o=>Array.isArray(o)?o.join(","):o,S=o=>o.toLowerCase().replaceAll(/[^\da-z]+/g,"-").replaceAll(/^-|-$/g,""),B=new Set(["banExpires","banned","banReason","createdAt","email","emailVerified","id","name","role","updatedAt"]),F={displayUsername:"username",phoneNumber:"phone-number",phoneNumberVerified:"phone-number",username:"username"},G=o=>o==="boolean"||o==="date"||o==="number"?o:"string",V=o=>{const c=[];for(const[h,l]of Object.entries(o))l.input===!1||l.references!==void 0||B.has(h)||c.push({name:h,plugin:F[h],required:l.required===!0,type:G(l.type),unique:l.unique===!0});return c},I=o=>typeof o=="string"&&o.includes("owner"),_=async(o,c)=>{const l=(await o.adapter.findMany({model:"member",where:[{field:"userId",value:c}]})).filter(p=>I(p.role)&&typeof p.organizationId=="string").map(p=>p.organizationId);if(l.length===0)return;const A=await Promise.all(l.map(async p=>o.adapter.findMany({model:"member",where:[{field:"organizationId",value:p}]}))),n=l.find((p,v)=>!A[v]?.some(e=>e.userId!==c&&I(e.role)));if(n!==void 0)throw new f(`user is the last owner of organization ${n} — transfer ownership or delete the organization first`,"LAST_ORGANIZATION_OWNER")},j=o=>{if(o instanceof f)return o;const c=o,h=c?.body?.code??c?.code??"AUTH_ADMIN_ERROR",l=c?.body?.message??c?.message??"auth admin operation failed";return new f(l,h)},W=(o,c={})=>{const h=o.$context,l=c.features??{},A=e=>{const a=new Set((e.plugins??[]).map(i=>i.id)),t=i=>a.has(i);return{accounts:l.accounts??!0,admin:l.admin??t("admin"),inviteOnly:l.inviteOnly??t("lunora-invite-only"),organization:l.organization??t("organization"),passkey:l.passkey??t("passkey"),twoFactor:l.twoFactor??t("two-factor")}},n=async e=>{try{return await e(await h)}catch(a){throw j(a)}},p=e=>u(e),v=async(e,a,t)=>{const i=t.where&&t.where.length>0?t.where:void 0,[r,s]=await Promise.all([e.adapter.findMany({limit:C(t.limit),model:a,offset:P(t.offset),sortBy:t.sortBy,where:i}),e.adapter.count({model:a,where:i})]);return{rows:r.map(d=>u(d)),total:s}};return{banUser:({expiresInSeconds:e,reason:a,userId:t})=>n(async i=>{let r=null;if(e!==void 0){if(!Number.isInteger(e)||e<=0)throw new f("expiresInSeconds must be a positive finite integer","INVALID_BAN_SECONDS");const d=Math.min(e,T);r=new Date(Date.now()+d*1e3)}const s=await i.internalAdapter.updateUser(t,{banExpires:r,banned:!0,banReason:a??"No reason"});return await i.internalAdapter.deleteUserSessions(t),p(s)}),cancelInvitation:({invitationId:e})=>n(async a=>{await a.adapter.delete({model:"invitation",where:[{field:"id",value:e}]})}),capabilities:()=>n(e=>Promise.resolve(A(e.options))),addMember:({organizationId:e,role:a,userId:t})=>n(async i=>{const r=await i.adapter.create({data:{createdAt:new Date,organizationId:e,role:a===void 0||a===""?"member":a,userId:t},model:"member"});return u(r)}),addTeamMember:({teamId:e,userId:a})=>n(async t=>{const i=await t.adapter.create({data:{createdAt:new Date,teamId:e,userId:a},model:"teamMember"});return u(i)}),config:()=>n(e=>{const a=e.options,t=A(a),i=new Set((a.plugins??[]).map(m=>m.id)),r=b(a),s=a.session??{},d=a.rateLimit??{};return Promise.resolve({capabilities:t,emailAndPassword:a.emailAndPassword?.enabled??!1,organization:{enabled:t.organization,roles:!!r.organizationRole,teams:!!r.team},plugins:[...i].toSorted((m,w)=>m.localeCompare(w)),rateLimit:{enabled:d.enabled??!1,max:d.max,window:d.window},session:{cookieCache:s.cookieCache?.enabled,expiresIn:s.expiresIn,freshAge:s.freshAge,updateAge:s.updateAge},socialProviders:Object.keys(a.socialProviders??{}).toSorted((m,w)=>m.localeCompare(w)),userFields:V(r.user?.fields??{})})}),createOrganization:({logo:e,metadata:a,name:t,ownerId:i,slug:r})=>n(async s=>{const d=S(r!==void 0&&r!==""?r:t);if(d==="")throw new f("could not derive a slug from the organization name","ORG_SLUG_INVALID");if(await s.adapter.findOne({model:"organization",where:[{field:"slug",value:d}]}))throw new f("an organization with this slug already exists","ORG_SLUG_TAKEN");const w=await s.adapter.create({data:{createdAt:new Date,logo:e===void 0||e===""?void 0:e,metadata:a===void 0?void 0:JSON.stringify(a),name:t,slug:d},model:"organization"});return i!==void 0&&i!==""&&await s.adapter.create({data:{createdAt:new Date,organizationId:w.id,role:"owner",userId:i},model:"member"}),u(w)}),createOrgRole:({organizationId:e,permission:a,role:t})=>n(async i=>{const r=await i.adapter.create({data:{createdAt:new Date,organizationId:e,permission:JSON.stringify(a),role:t},model:"organizationRole"});return u(r)}),createTeam:({name:e,organizationId:a})=>n(async t=>{const i=await t.adapter.create({data:{createdAt:new Date,name:e,organizationId:a},model:"team"});return u(i)}),deleteOrganization:({organizationId:e})=>n(async a=>{const t=b(a.options);if(await a.adapter.deleteMany({model:"member",where:[{field:"organizationId",value:e}]}),await a.adapter.deleteMany({model:"invitation",where:[{field:"organizationId",value:e}]}),t.team){const i=await a.adapter.findMany({model:"team",where:[{field:"organizationId",value:e}]});for(const r of i)await a.adapter.deleteMany({model:"teamMember",where:[{field:"teamId",value:r.id}]});await a.adapter.deleteMany({model:"team",where:[{field:"organizationId",value:e}]})}t.organizationRole&&await a.adapter.deleteMany({model:"organizationRole",where:[{field:"organizationId",value:e}]}),await a.adapter.delete({model:"organization",where:[{field:"id",value:e}]})}),deleteOrgRole:({roleId:e})=>n(async a=>{await a.adapter.delete({model:"organizationRole",where:[{field:"id",value:e}]})}),inviteMember:({email:e,inviterId:a,organizationId:t,role:i})=>n(async r=>{let s=a;if(s===void 0||s===""){const m=await r.adapter.findMany({model:"member",where:[{field:"organizationId",value:t}]});s=(m.find(y=>typeof y.role=="string"&&y.role.includes("owner"))??m[0])?.userId}if(s===void 0||s==="")throw new f("provide an inviter — the organization has no members to attribute the invitation to","INVITER_REQUIRED");const d=await r.adapter.create({data:{createdAt:new Date,email:e.toLowerCase(),expiresAt:new Date(Date.now()+z),inviterId:s,organizationId:t,role:i===void 0||i===""?"member":i,status:"pending"},model:"invitation"});return u(d)}),listOrgRoles:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"organizationRole",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:[{field:"organizationId",value:t}]})),listTeamMembers:({limit:e,offset:a,teamId:t})=>n(i=>v(i,"teamMember",{limit:e,offset:a,where:[{field:"teamId",value:t}]})),listTeams:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"team",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:[{field:"organizationId",value:t}]})),removeTeam:({teamId:e})=>n(async a=>{await a.adapter.deleteMany({model:"teamMember",where:[{field:"teamId",value:e}]}),await a.adapter.delete({model:"team",where:[{field:"id",value:e}]})}),removeTeamMember:({teamMemberId:e})=>n(async a=>{await a.adapter.delete({model:"teamMember",where:[{field:"id",value:e}]})}),updateMemberRole:({memberId:e,role:a})=>n(async t=>{const i=await t.adapter.update({model:"member",update:{role:g(a)},where:[{field:"id",value:e}]});return u(i??{id:e,role:g(a)})}),updateOrganization:({logo:e,metadata:a,name:t,organizationId:i,slug:r})=>n(async s=>{const d={};if(t!==void 0&&(d.name=t),r!==void 0&&r!==""&&(d.slug=S(r)),e!==void 0&&(d.logo=e===""?void 0:e),a!==void 0&&(d.metadata=JSON.stringify(a)),Object.keys(d).length===0)return u({id:i});const m=await s.adapter.update({model:"organization",update:d,where:[{field:"id",value:i}]});return u(m??{id:i})}),updateOrgRole:({permission:e,roleId:a})=>n(async t=>{const i=await t.adapter.update({model:"organizationRole",update:{permission:JSON.stringify(e),updatedAt:new Date},where:[{field:"id",value:a}]});return u(i??{id:a,permission:JSON.stringify(e)})}),updateTeam:({name:e,teamId:a})=>n(async t=>{const i=await t.adapter.update({model:"team",update:{name:e,updatedAt:new Date},where:[{field:"id",value:a}]});return u(i??{id:a,name:e})}),createUser:({data:e,email:a,name:t,password:i,role:r})=>n(async s=>{const d=a.toLowerCase();if(await s.internalAdapter.findUserByEmail(d))throw new f("a user with this email already exists","USER_ALREADY_EXISTS");const m={...e};delete m.isAnonymous;const w=await s.internalAdapter.createUser({email:d,name:t,role:r===void 0?void 0:g(r),...m},{method:"admin"});if(i!==void 0&&i!==""){const y=await s.password.hash(i);await s.internalAdapter.linkAccount({accountId:w.id,password:y,providerId:"credential",userId:w.id})}return p(w)}),deletePasskey:({passkeyId:e})=>n(async a=>{await a.adapter.delete({model:"passkey",where:[{field:"id",value:e}]})}),disableTwoFactor:({userId:e})=>n(async a=>{await a.adapter.deleteMany({model:"twoFactor",where:[{field:"userId",value:e}]}),await a.internalAdapter.updateUser(e,{twoFactorEnabled:!1})}),impersonateUser:({userId:e})=>n(async a=>{const t=await a.internalAdapter.findUserById(e);if(!t)throw new f("user not found","USER_NOT_FOUND");const i=c.impersonationSeconds;let r=O;if(i!==void 0){if(!Number.isInteger(i)||!Number.isFinite(i)||i<=0)throw new f("impersonationSeconds must be a positive finite integer","INVALID_IMPERSONATION_SECONDS");r=Math.min(i,E)}const s=new Date(Date.now()+r*1e3),d=await a.internalAdapter.createSession(e,!0,{expiresAt:s,impersonatedBy:c.impersonatedBy??e},!0);return{expiresAt:d.expiresAt instanceof Date?d.expiresAt.getTime():s.getTime(),token:d.token,user:p(t)}}),listAccounts:({userId:e})=>n(async a=>(await a.adapter.findMany({model:"account",where:[{field:"userId",value:e}]})).map(i=>u(i))),listInvitations:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"invitation",{limit:e,offset:a,where:[{field:"organizationId",value:t}]})),createSignUpInvitation:({email:e,expiresInSeconds:a,invitedBy:t})=>n(async()=>{const i=await R(o,{email:e,expiresInSeconds:a,invitedBy:t});return{...u({...i}),token:i.token}}),listSignUpInvitations:({limit:e,offset:a})=>n(t=>v(t,"signUpInvitation",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"}})),revokeSignUpInvitation:({email:e})=>n(async()=>U(o,{email:e})),listMembers:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"member",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:[{field:"organizationId",value:t}]})),listOrganizations:({limit:e,offset:a})=>n(t=>v(t,"organization",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"}})),listPasskeys:({userId:e})=>n(async a=>(await a.adapter.findMany({model:"passkey",where:[{field:"userId",value:e}]})).map(i=>u(i))),listSessions:({limit:e,offset:a,userId:t})=>n(i=>v(i,"session",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:t===void 0||t===""?void 0:[{field:"userId",value:t}]})),listUsers:({filterField:e,filterValue:a,limit:t,offset:i,search:r,searchField:s,sortBy:d,sortDirection:m})=>n(w=>{const y=[];return r!==void 0&&r!==""&&y.push({field:s??"email",operator:"contains",value:r}),a!==void 0&&y.push({field:e??"email",operator:"eq",value:a}),v(w,"user",{limit:t,offset:i,sortBy:{direction:m??"desc",field:d??"createdAt"},where:y})}),removeMember:({memberId:e})=>n(async a=>{await a.adapter.delete({model:"member",where:[{field:"id",value:e}]})}),removeUser:({userId:e})=>n(async a=>{const t=b(a.options);t.member&&await _(a,e),await Promise.all(k.filter(({model:i})=>t[i]).map(({field:i,model:r})=>a.adapter.deleteMany({model:r,where:[{field:i,value:e}]}))),await a.internalAdapter.deleteUserSessions(e),await a.internalAdapter.deleteUser(e)}),revokeUserSession:({sessionId:e})=>n(async a=>{const t=await a.adapter.findOne({model:"session",where:[{field:"id",value:e}]});t?.token&&await a.internalAdapter.deleteSession(t.token)}),revokeUserSessions:({userId:e})=>n(async a=>{await a.internalAdapter.deleteUserSessions(e)}),setRole:({role:e,userId:a})=>n(async t=>{const i=await t.internalAdapter.updateUser(a,{role:g(e)});return p(i)}),setUserPassword:({newPassword:e,userId:a})=>n(async t=>{const i=t.password.config.minPasswordLength,r=t.password.config.maxPasswordLength;if(e.length<i)throw new f(`password must be at least ${i.toString()} characters`,"PASSWORD_TOO_SHORT");if(e.length>r)throw new f(`password must be at most ${r.toString()} characters`,"PASSWORD_TOO_LONG");if(!await t.internalAdapter.findUserById(a))throw new f("user not found","USER_NOT_FOUND");const d=(await t.internalAdapter.findAccounts(a)).some(w=>w.providerId==="credential");if(!d&&t.options.emailAndPassword?.enabled!==!0)throw new f("email/password sign-in is disabled for this deployment","EMAIL_PASSWORD_DISABLED");const m=await t.password.hash(e);d?await t.internalAdapter.updatePassword(a,m):await t.internalAdapter.linkAccount({accountId:a,password:m,providerId:"credential",userId:a})}),unbanUser:({userId:e})=>n(async a=>{const t=await a.internalAdapter.updateUser(e,{banExpires:null,banned:!1,banReason:null});return p(t)}),unlinkAccount:({accountId:e,userId:a})=>n(async t=>{await t.adapter.delete({model:"account",where:[{field:"id",value:e},{connector:"AND",field:"userId",value:a}]})}),updateUser:({data:e,userId:a})=>n(async t=>{const i=await t.internalAdapter.updateUser(a,e);return p(i)})}};export{f as LunoraAuthAdminError,W as createAuthAdmin};
|
|
@@ -40,6 +40,10 @@ import { betterAuth, BetterAuthOptions } from 'better-auth';
|
|
|
40
40
|
*
|
|
41
41
|
* (Lunora can't set this for you — `ctx.waitUntil` is per-request, but
|
|
42
42
|
* `createAuth` runs once at worker setup.)
|
|
43
|
+
*
|
|
44
|
+
* `databaseHooks` never receives a Lunora `MutationCtx` — the hook runs inside
|
|
45
|
+
* better-auth's own write path. A side effect on an app table is therefore a
|
|
46
|
+
* separate write and has to be idempotent; see `concepts/authentication`.
|
|
43
47
|
*/
|
|
44
48
|
type LunoraAuthOptions = BetterAuthOptions;
|
|
45
49
|
/**
|
|
@@ -40,6 +40,10 @@ import { betterAuth, BetterAuthOptions } from 'better-auth';
|
|
|
40
40
|
*
|
|
41
41
|
* (Lunora can't set this for you — `ctx.waitUntil` is per-request, but
|
|
42
42
|
* `createAuth` runs once at worker setup.)
|
|
43
|
+
*
|
|
44
|
+
* `databaseHooks` never receives a Lunora `MutationCtx` — the hook runs inside
|
|
45
|
+
* better-auth's own write path. A side effect on an app table is therefore a
|
|
46
|
+
* separate write and has to be idempotent; see `concepts/authentication`.
|
|
43
47
|
*/
|
|
44
48
|
type LunoraAuthOptions = BetterAuthOptions;
|
|
45
49
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineErrorCodes as _}from"@better-auth/core/utils/error-codes";import{LunoraError as A}from"@lunora/errors";import{createAuthMiddleware as D,APIError as g}from"better-auth/api";const c="signUpInvitation",T=10080*60,v=365*24*60*60,y=500,w=_({SIGN_UP_INVITE_INVALID:"That sign-up invitation is not valid. Ask an administrator for a new invitation link.",SIGN_UP_INVITE_REQUIRED:"Sign-up is invite-only — ask an administrator for an invitation."}),O=32,N=/^[^\s@]+@[^\s@]+$/,x=e=>{if(!N.test(e))return!1;const t=e.slice(e.indexOf("@")+1);return t.includes(".")&&!t.startsWith(".")&&!t.endsWith(".")},m=e=>({acceptedAt:e.acceptedAt instanceof Date?e.acceptedAt:null,createdAt:e.createdAt,email:String(e.email),expiresAt:e.expiresAt,id:String(e.id),invitedBy:typeof e.invitedBy=="string"?e.invitedBy:null}),R=()=>btoa(String.fromCodePoint(...crypto.getRandomValues(new Uint8Array(O)))).replaceAll("+","-").replaceAll("/","_").replaceAll("=",""),S=async e=>{const t=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(e));return[...new Uint8Array(t)].map(i=>i.toString(16).padStart(2,"0")).join("")},U=(e,t)=>{if(e.length!==t.length)return!1;let i=0;for(let o=0;o<e.length;o+=1)i|=(e.codePointAt(o)??0)^(t.codePointAt(o)??0);return i===0},p=e=>e.trim().toLowerCase(),I=e=>{if(typeof e.email!="string")return;const t=p(e.email);return t===""?void 0:t},k="anonymous",b=e=>(e.plugins??[]).some(t=>t.id===k),E=e=>e.isAnonymous===!0,P=async(e,t)=>{const i=await e.findOne({model:c,where:[{field:"email",value:t}]});return i===null||i.acceptedAt instanceof Date?!1:i.expiresAt instanceof Date&&i.expiresAt.getTime()>Date.now()},L=e=>{e.emailAndPassword?.enabled!==!0||e.emailAndPassword.requireEmailVerification===!0||console.warn("@lunora/auth: inviteOnly() is installed with password sign-up but without `emailAndPassword: { requireEmailVerification: true }`. An invitation is keyed by email address alone, so anyone who learns an invited address can sign up as it — and without verification they hold a session the moment they do.")},C=(e={})=>{let t=e.allowFirstUser??!1,i=!1;const o=async a=>{if(!t)return!1;const n=await a.count({model:"user"}),d=i&&n>0?await a.count({model:"user",where:[{field:"isAnonymous",value:!0}]}):0;return n-d<=0?!0:(t=!1,!1)};return{$ERROR_CODES:w,hooks:{before:[{handler:D(async a=>{const n=a.body??{},d=typeof n.email=="string"?p(n.email):"",u=typeof n.inviteToken=="string"?n.inviteToken:"",r=()=>{throw new g("BAD_REQUEST",w.SIGN_UP_INVITE_INVALID)};if(d===""&&r(),await o(a.context.adapter))return;u===""&&r();const s=await a.context.adapter.findOne({model:c,where:[{field:"email",value:d}]}),f=s===null?void 0:s.tokenHash,l=await S(u);(typeof f!="string"||!U(f,l))&&r()}),matcher:a=>a.path==="/sign-up/email"}]},id:"lunora-invite-only",init:a=>{L(a.options);const{adapter:n}=a;return i=b(a.options),{options:{databaseHooks:{user:{create:{after:async r=>{const s=I(r);s===void 0||i&&E(r)||await n.update({model:c,update:{acceptedAt:new Date},where:[{field:"email",value:s}]})},before:async r=>{if(i&&E(r))return;const s=I(r);if(!(s!==void 0&&await P(n,s))&&!await o(n))throw new g("BAD_REQUEST",w.SIGN_UP_INVITE_REQUIRED)}}}}}}},schema:{[c]:{fields:{acceptedAt:{required:!1,type:"date"},tokenHash:{required:!1,type:"string"},createdAt:{defaultValue:()=>new Date,required:!0,type:"date"},email:{required:!0,type:"string",unique:!0},expiresAt:{required:!0,type:"date"},invitedBy:{required:!1,type:"string"}}}}}},H=async(e,t)=>{const i=p(t.email);if(!x(i))throw new A("VALIDATION_ERROR",`not an email address to invite: ${JSON.stringify(t.email)}`);const{expiresInSeconds:o=T}=t;if(!Number.isInteger(o)||o<=0||o>v)throw new A("VALIDATION_ERROR",`expiresInSeconds must be a positive integer no greater than ${String(v)}`);const a=new Date(Date.now()+o*1e3),n=R(),d=await S(n),u=t.invitedBy??null,r=await e.$context,s=[{field:"email",value:i}],f=async()=>r.adapter.update({model:c,update:{acceptedAt:null,expiresAt:a,invitedBy:u,tokenHash:d},where:s});if(await r.adapter.findOne({model:c,where:s})){const l=await f();if(l)return{...m(l),token:n}}try{const l=await r.adapter.create({data:{createdAt:new Date,email:i,expiresAt:a,invitedBy:u,tokenHash:d},model:c});return{...m(l),token:n}}catch(l){const h=await f();if(h===null)throw l;return{...m(h),token:n}}},G=async(e,t={})=>{const a=(await(await e.$context).adapter.findMany({limit:y,model:c,sortBy:{direction:"desc",field:"createdAt"}})).map(n=>m(n));return t.pendingOnly===!0?a.filter(n=>n.acceptedAt===null&&n.expiresAt.getTime()>Date.now()):a},Q=async(e,t)=>{await(await e.$context).adapter.delete({model:c,where:[{field:"email",value:p(t.email)}]})},V=100,B=async(e,t,i,o)=>{const a=t.filter(n=>n.acceptedAt===null&&n.expiresAt.getTime()<=i).slice(0,o);for(const n of a)await e.delete({model:c,where:[{field:"id",value:n.id}]});return a.length},W=async(e,t={})=>{const i=t.limit??y;if(!Number.isInteger(i)||i<=0)throw new A("VALIDATION_ERROR","limit must be a positive integer");const o=Math.min(i,y),a=await e.$context,n=Date.now();let d=0,u=0;for(;d<o;){const r=await a.adapter.findMany({limit:V,model:c,offset:u,sortBy:{direction:"asc",field:"expiresAt"}});if(r.length===0)break;const s=r.map(l=>m(l)),f=await B(a.adapter,s,n,o-d);if(d+=f,s.some(l=>l.expiresAt.getTime()>n))break;u+=r.length-f}return d};export{H as createSignUpInvitation,C as inviteOnly,G as listSignUpInvitations,W as pruneSignUpInvitations,Q as revokeSignUpInvitation};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BetterAuthPlugin } from 'better-auth';
|
|
2
|
-
import { L as LunoraAuth } from "./create-auth.d-
|
|
2
|
+
import { L as LunoraAuth } from "./create-auth.d-D1CKOFWc.js";
|
|
3
3
|
/** One pending or spent sign-up invitation. */
|
|
4
4
|
interface SignUpInvitation {
|
|
5
5
|
/** When an account was created for this address; `null` while the invitation is unspent. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BetterAuthPlugin } from 'better-auth';
|
|
2
|
-
import { L as LunoraAuth } from "./create-auth.d-
|
|
2
|
+
import { L as LunoraAuth } from "./create-auth.d-D1CKOFWc.mjs";
|
|
3
3
|
/** One pending or spent sign-up invitation. */
|
|
4
4
|
interface SignUpInvitation {
|
|
5
5
|
/** When an account was created for this address; `null` while the invitation is unspent. */
|
package/dist/plugins.d.mts
CHANGED
|
@@ -19,7 +19,7 @@ type a as IssuedSignUpInvitation,
|
|
|
19
19
|
* Declares the `signUpInvitation` table it reads. Lunora's own, not a better-auth
|
|
20
20
|
* re-export.
|
|
21
21
|
*/
|
|
22
|
-
type S as SignUpInvitation, i as inviteOnly } from "./packem_shared/invite-only.d-
|
|
22
|
+
type S as SignUpInvitation, i as inviteOnly } from "./packem_shared/invite-only.d-DKyHHkkQ.mjs";
|
|
23
23
|
import { BetterAuthPlugin } from 'better-auth';
|
|
24
24
|
export { apiKey } from '@better-auth/api-key';
|
|
25
25
|
export { createMcpProtectedRequestHandler, mcp, requireMcpAuth } from '@better-auth/mcp';
|
|
@@ -46,7 +46,7 @@ export { phoneNumber } from 'better-auth/plugins/phone-number';
|
|
|
46
46
|
export { siwe } from 'better-auth/plugins/siwe';
|
|
47
47
|
export { twoFactor } from 'better-auth/plugins/two-factor';
|
|
48
48
|
export { username } from 'better-auth/plugins/username';
|
|
49
|
-
import "./packem_shared/create-auth.d-
|
|
49
|
+
import "./packem_shared/create-auth.d-D1CKOFWc.mjs";
|
|
50
50
|
/** Organization sub-features a UI branches on. */
|
|
51
51
|
interface UiConfigOrganization {
|
|
52
52
|
/** Whether an ordinary user may create one at all. */
|
package/dist/plugins.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ type a as IssuedSignUpInvitation,
|
|
|
19
19
|
* Declares the `signUpInvitation` table it reads. Lunora's own, not a better-auth
|
|
20
20
|
* re-export.
|
|
21
21
|
*/
|
|
22
|
-
type S as SignUpInvitation, i as inviteOnly } from "./packem_shared/invite-only.d-
|
|
22
|
+
type S as SignUpInvitation, i as inviteOnly } from "./packem_shared/invite-only.d-CsPJWAwM.js";
|
|
23
23
|
import { BetterAuthPlugin } from 'better-auth';
|
|
24
24
|
export { apiKey } from '@better-auth/api-key';
|
|
25
25
|
export { createMcpProtectedRequestHandler, mcp, requireMcpAuth } from '@better-auth/mcp';
|
|
@@ -46,7 +46,7 @@ export { phoneNumber } from 'better-auth/plugins/phone-number';
|
|
|
46
46
|
export { siwe } from 'better-auth/plugins/siwe';
|
|
47
47
|
export { twoFactor } from 'better-auth/plugins/two-factor';
|
|
48
48
|
export { username } from 'better-auth/plugins/username';
|
|
49
|
-
import "./packem_shared/create-auth.d-
|
|
49
|
+
import "./packem_shared/create-auth.d-D1CKOFWc.js";
|
|
50
50
|
/** Organization sub-features a UI branches on. */
|
|
51
51
|
interface UiConfigOrganization {
|
|
52
52
|
/** Whether an ordinary user may create one at all. */
|
package/dist/plugins.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{inviteOnly as e}from"./packem_shared/createSignUpInvitation-
|
|
1
|
+
import{inviteOnly as e}from"./packem_shared/createSignUpInvitation-ClvskwuB.mjs";import{uiConfig as m}from"./packem_shared/uiConfig-B8pN6pks.mjs";import{apiKey as f}from"@better-auth/api-key";import{createMcpProtectedRequestHandler as i,mcp as n,requireMcpAuth as a}from"@better-auth/mcp";import{oauthDeviceAuthorization as s,oauthProvider as u}from"@better-auth/oauth-provider";import{passkey as d}from"@better-auth/passkey";import{scim as A}from"@better-auth/scim";import{captcha as v,lastLoginMethod as y,oneTap as P}from"better-auth/plugins";import{createAccessControl as T}from"better-auth/plugins/access";import{admin as z}from"better-auth/plugins/admin";import{anonymous as O}from"better-auth/plugins/anonymous";import{bearer as q}from"better-auth/plugins/bearer";import{customSession as L}from"better-auth/plugins/custom-session";import{deviceAuthorization as j}from"better-auth/plugins/device-authorization";import{emailOTP as D}from"better-auth/plugins/email-otp";import{genericOAuth as H}from"better-auth/plugins/generic-oauth";import{haveIBeenPwned as K}from"better-auth/plugins/haveibeenpwned";import{jwt as R}from"better-auth/plugins/jwt";import{magicLink as G}from"better-auth/plugins/magic-link";import{multiSession as Q}from"better-auth/plugins/multi-session";import{oAuthProxy as V}from"better-auth/plugins/oauth-proxy";import{oneTimeToken as X}from"better-auth/plugins/one-time-token";import{organization as Z}from"better-auth/plugins/organization";import{phoneNumber as $}from"better-auth/plugins/phone-number";import{siwe as ro}from"better-auth/plugins/siwe";import{twoFactor as to}from"better-auth/plugins/two-factor";import{username as po}from"better-auth/plugins/username";export{z as admin,O as anonymous,f as apiKey,q as bearer,v as captcha,T as createAccessControl,i as createMcpProtectedRequestHandler,L as customSession,j as deviceAuthorization,D as emailOTP,H as genericOAuth,K as haveIBeenPwned,e as inviteOnly,R as jwt,y as lastLoginMethod,G as magicLink,n as mcp,Q as multiSession,V as oAuthProxy,s as oauthDeviceAuthorization,u as oauthProvider,P as oneTap,X as oneTimeToken,Z as organization,d as passkey,$ as phoneNumber,a as requireMcpAuth,A as scim,ro as siwe,to as twoFactor,m as uiConfig,po as username};
|
package/dist/schema.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDefinition } from '@lunora/server';
|
|
2
|
-
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
2
|
+
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-D1CKOFWc.mjs";
|
|
3
3
|
import 'better-auth';
|
|
4
4
|
/**
|
|
5
5
|
* Derive Lunora table definitions from a better-auth config — the bridge that
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDefinition } from '@lunora/server';
|
|
2
|
-
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
2
|
+
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-D1CKOFWc.js";
|
|
3
3
|
import 'better-auth';
|
|
4
4
|
/**
|
|
5
5
|
* Derive Lunora table definitions from a better-auth config — the bridge that
|
package/dist/sql-store.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const l=
|
|
1
|
+
const l=s=>`"${s.replaceAll('"','""')}"`,T="_creationTime",N=/no such column|column .{0,64}? does not exist/iu,g={params:[],sql:"0"},R=(s,r)=>r?{column:`LOWER(${s})`,placeholder:"LOWER(?)"}:{column:s,placeholder:"?"},M=(s,r,a,c)=>{if(typeof r!="string")return g;const t=R(s,c);return a==="contains"?{params:[r],sql:`instr(${t.column}, ${t.placeholder}) > 0`}:a==="starts_with"?{params:[r],sql:`instr(${t.column}, ${t.placeholder}) = 1`}:{params:[r,r],sql:`substr(${t.column}, -length(?)) = ${t.placeholder}`}},h=(s,r,a,c)=>{if(r===null)return{params:[],sql:`${s} IS ${c?"NOT ":""}NULL`};const t=R(s,a),n=c?"<>":"=";return{params:[r],sql:`${t.column} ${n} ${t.placeholder}`}},O=(s,r,a,c)=>{const t=Array.isArray(r)?r:[];if(t.length===0)return{params:[],sql:a?"1":"0"};const n=R(s,c),e=t.map(()=>n.placeholder).join(", ");return{params:[...t],sql:`${n.column} ${a?"NOT IN":"IN"} (${e})`}},L=s=>{const r=l(s.field),{mode:a,operator:c,value:t}=s,n=a==="insensitive";switch(c){case"contains":case"ends_with":case"starts_with":return M(r,t,c,n);case"gt":return{params:[t],sql:`${r} > ?`};case"gte":return{params:[t],sql:`${r} >= ?`};case"in":return O(r,t,!1,n);case"lt":return{params:[t],sql:`${r} < ?`};case"lte":return{params:[t],sql:`${r} <= ?`};case"ne":return h(r,t,n,!0);case"not_in":return O(r,t,!0,n);default:return h(r,t,n,!1)}},d=(s,r)=>{if(s.length===0)return;const a=s.map(c=>L(c));return{params:a.flatMap(c=>c.params),sql:a.map(c=>`(${c.sql})`).join(` ${r} `)}},E=s=>{const r=[d(s.filter(a=>a.connector!=="OR"),"AND"),d(s.filter(a=>a.connector==="OR"),"OR")].filter(a=>a!==void 0);return r.length===0?{params:[],sql:""}:{params:r.flatMap(a=>a.params),sql:r.map(a=>`(${a.sql})`).join(" AND ")}},$=s=>s.sql?` WHERE ${s.sql}`:"",S=s=>{const r=(t,n)=>{const e=E(n);return s.all(`SELECT * FROM ${l(t)}${$(e)}`,e.params)},a=new Map,c=async t=>{const n=a.get(t);if(n!==void 0)return n;try{await s.all(`SELECT ${l(t)}.${l(T)} FROM ${l(t)} LIMIT 0`,[])}catch(e){return N.test(e instanceof Error?e.message:String(e))&&a.set(t,!1),!1}return a.set(t,!0),!0};return{consumeOne:async(t,n)=>{const e=E(n),o=l(t),[i]=await s.all(`DELETE FROM ${o} WHERE rowid IN (SELECT rowid FROM ${o}${$(e)} LIMIT 1) RETURNING *`,e.params);return i},count:async(t,n)=>{const e=E(n),[o]=await s.all(`SELECT COUNT(*) AS __count FROM ${l(t)}${$(e)}`,e.params);return Number(o?.__count??0)},create:async(t,n)=>{const e=T in n||!await c(t)?n:{[T]:Date.now(),...n},o=Object.keys(e),i=o.map(()=>"?").join(", "),u=`INSERT INTO ${l(t)} (${o.map(m=>l(m)).join(", ")}) VALUES (${i})`;return await s.run(u,o.map(m=>e[m])),{...n}},incrementOne:async(t,n,e,o)=>{const i=l(t),u=Object.keys(e),m=o?Object.keys(o):[],f=E(n);if(u.length===0&&m.length===0){const[p]=await s.all(`SELECT * FROM ${i}${$(f)} LIMIT 1`,f.params);return p}const I=[...u.map(p=>`${l(p)} = COALESCE(${l(p)}, 0) + ?`),...m.map(p=>`${l(p)} = ?`)].join(", "),[w]=await s.all(`UPDATE ${i} SET ${I} WHERE rowid IN (SELECT rowid FROM ${i}${$(f)} LIMIT 1) RETURNING *`,[...u.map(p=>e[p]),...m.map(p=>o[p]),...f.params]);return w},read:async(t,n)=>{const e=E(n.where),o=[...e.params];let i=`SELECT * FROM ${l(t)}${$(e)}`;return n.sortBy&&(i+=` ORDER BY ${l(n.sortBy.field)} ${n.sortBy.direction==="asc"?"ASC":"DESC"}`),n.limit!==void 0&&(i+=" LIMIT ?",o.push(Math.trunc(n.limit))),n.offset&&(i+=`${n.limit===void 0?" LIMIT -1":""} OFFSET ?`,o.push(Math.trunc(n.offset))),s.all(i,o)},remove:async(t,n)=>{const e=E(n);return(await s.all(`DELETE FROM ${l(t)}${$(e)} RETURNING *`,e.params)).length},update:async(t,n,e)=>{const o=Object.keys(e);if(o.length===0)return r(t,n);const i=o.map(m=>`${l(m)} = ?`).join(", "),u=E(n);return s.all(`UPDATE ${l(t)} SET ${i}${$(u)} RETURNING *`,[...o.map(m=>e[m]),...u.params])}}},C=s=>({all:async(r,a)=>(await s.prepare(r).bind(...a).all()).results??[],run:async(r,a)=>{await s.prepare(r).bind(...a).run()}});export{S as createSqlAuthStore,C as d1Executor};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as M}from"@lunora/errors";import{getAuthTables as b}from"better-auth/db";import{revokeSignUpInvitation as U,createSignUpInvitation as R}from"./createSignUpInvitation-CqqQc4S8.mjs";class p extends M{constructor(m,f){super(f,m,{name:"LunoraAuthAdminError"})}}const N=50,E=500,O=3600,D=O*24,T=100*365*24*60*60,z=2880*60*1e3,k=[{field:"userId",model:"member"},{field:"userId",model:"teamMember"},{field:"userId",model:"passkey"},{field:"userId",model:"twoFactor"},{field:"userId",model:"oauthAccessToken"},{field:"userId",model:"oauthRefreshToken"},{field:"userId",model:"oauthConsent"},{field:"userId",model:"deviceCode"},{field:"userId",model:"walletAddress"},{field:"inviterId",model:"invitation"}],L=new Set(["accessToken","backupCodes","idToken","password","publicKey","refreshToken","secret","token","tokenHash"]),C=o=>Math.min(Math.max(Math.trunc(o??N),1),E),P=o=>Math.max(0,Math.trunc(o??0)),u=o=>{const m={};for(const[f,l]of Object.entries(o))L.has(f)||(m[f]=l instanceof Date?l.getTime():l);return m},g=o=>Array.isArray(o)?o.join(","):o,S=o=>o.toLowerCase().replaceAll(/[^\da-z]+/g,"-").replaceAll(/^-|-$/g,""),B=new Set(["banExpires","banned","banReason","createdAt","email","emailVerified","id","name","role","updatedAt"]),F={displayUsername:"username",phoneNumber:"phone-number",phoneNumberVerified:"phone-number",username:"username"},G=o=>o==="boolean"||o==="date"||o==="number"?o:"string",V=o=>{const m=[];for(const[f,l]of Object.entries(o))l.input===!1||l.references!==void 0||B.has(f)||m.push({name:f,plugin:F[f],required:l.required===!0,type:G(l.type),unique:l.unique===!0});return m},I=o=>typeof o=="string"&&o.includes("owner"),_=async(o,m)=>{const l=(await o.adapter.findMany({model:"member",where:[{field:"userId",value:m}]})).filter(w=>I(w.role)&&typeof w.organizationId=="string").map(w=>w.organizationId);if(l.length===0)return;const A=await Promise.all(l.map(async w=>o.adapter.findMany({model:"member",where:[{field:"organizationId",value:w}]}))),n=l.find((w,v)=>!A[v]?.some(e=>e.userId!==m&&I(e.role)));if(n!==void 0)throw new p(`user is the last owner of organization ${n} — transfer ownership or delete the organization first`,"LAST_ORGANIZATION_OWNER")},j=o=>{if(o instanceof p)return o;const m=o,f=m?.body?.code??m?.code??"AUTH_ADMIN_ERROR",l=m?.body?.message??m?.message??"auth admin operation failed";return new p(l,f)},W=(o,m={})=>{const f=o.$context,l=m.features??{},A=e=>{const a=new Set((e.plugins??[]).map(i=>i.id)),t=i=>a.has(i);return{accounts:l.accounts??!0,admin:l.admin??t("admin"),inviteOnly:l.inviteOnly??t("lunora-invite-only"),organization:l.organization??t("organization"),passkey:l.passkey??t("passkey"),twoFactor:l.twoFactor??t("two-factor")}},n=async e=>{try{return await e(await f)}catch(a){throw j(a)}},w=e=>u(e),v=async(e,a,t)=>{const i=t.where&&t.where.length>0?t.where:void 0,[r,s]=await Promise.all([e.adapter.findMany({limit:C(t.limit),model:a,offset:P(t.offset),sortBy:t.sortBy,where:i}),e.adapter.count({model:a,where:i})]);return{rows:r.map(d=>u(d)),total:s}};return{banUser:({expiresInSeconds:e,reason:a,userId:t})=>n(async i=>{let r=null;if(e!==void 0){if(!Number.isInteger(e)||e<=0)throw new p("expiresInSeconds must be a positive finite integer","INVALID_BAN_SECONDS");const d=Math.min(e,T);r=new Date(Date.now()+d*1e3)}const s=await i.internalAdapter.updateUser(t,{banExpires:r,banned:!0,banReason:a??"No reason"});return await i.internalAdapter.deleteUserSessions(t),w(s)}),cancelInvitation:({invitationId:e})=>n(async a=>{await a.adapter.delete({model:"invitation",where:[{field:"id",value:e}]})}),capabilities:()=>n(e=>Promise.resolve(A(e.options))),addMember:({organizationId:e,role:a,userId:t})=>n(async i=>{const r=await i.adapter.create({data:{createdAt:new Date,organizationId:e,role:a===void 0||a===""?"member":a,userId:t},model:"member"});return u(r)}),addTeamMember:({teamId:e,userId:a})=>n(async t=>{const i=await t.adapter.create({data:{createdAt:new Date,teamId:e,userId:a},model:"teamMember"});return u(i)}),config:()=>n(e=>{const a=e.options,t=A(a),i=new Set((a.plugins??[]).map(c=>c.id)),r=b(a),s=a.session??{},d=a.rateLimit??{};return Promise.resolve({capabilities:t,emailAndPassword:a.emailAndPassword?.enabled??!1,organization:{enabled:t.organization,roles:!!r.organizationRole,teams:!!r.team},plugins:[...i].toSorted((c,h)=>c.localeCompare(h)),rateLimit:{enabled:d.enabled??!1,max:d.max,window:d.window},session:{cookieCache:s.cookieCache?.enabled,expiresIn:s.expiresIn,freshAge:s.freshAge,updateAge:s.updateAge},socialProviders:Object.keys(a.socialProviders??{}).toSorted((c,h)=>c.localeCompare(h)),userFields:V(r.user?.fields??{})})}),createOrganization:({logo:e,metadata:a,name:t,ownerId:i,slug:r})=>n(async s=>{const d=S(r!==void 0&&r!==""?r:t);if(d==="")throw new p("could not derive a slug from the organization name","ORG_SLUG_INVALID");if(await s.adapter.findOne({model:"organization",where:[{field:"slug",value:d}]}))throw new p("an organization with this slug already exists","ORG_SLUG_TAKEN");const h=await s.adapter.create({data:{createdAt:new Date,logo:e===void 0||e===""?void 0:e,metadata:a===void 0?void 0:JSON.stringify(a),name:t,slug:d},model:"organization"});return i!==void 0&&i!==""&&await s.adapter.create({data:{createdAt:new Date,organizationId:h.id,role:"owner",userId:i},model:"member"}),u(h)}),createOrgRole:({organizationId:e,permission:a,role:t})=>n(async i=>{const r=await i.adapter.create({data:{createdAt:new Date,organizationId:e,permission:JSON.stringify(a),role:t},model:"organizationRole"});return u(r)}),createTeam:({name:e,organizationId:a})=>n(async t=>{const i=await t.adapter.create({data:{createdAt:new Date,name:e,organizationId:a},model:"team"});return u(i)}),deleteOrganization:({organizationId:e})=>n(async a=>{const t=b(a.options);if(await a.adapter.deleteMany({model:"member",where:[{field:"organizationId",value:e}]}),await a.adapter.deleteMany({model:"invitation",where:[{field:"organizationId",value:e}]}),t.team){const i=await a.adapter.findMany({model:"team",where:[{field:"organizationId",value:e}]});for(const r of i)await a.adapter.deleteMany({model:"teamMember",where:[{field:"teamId",value:r.id}]});await a.adapter.deleteMany({model:"team",where:[{field:"organizationId",value:e}]})}t.organizationRole&&await a.adapter.deleteMany({model:"organizationRole",where:[{field:"organizationId",value:e}]}),await a.adapter.delete({model:"organization",where:[{field:"id",value:e}]})}),deleteOrgRole:({roleId:e})=>n(async a=>{await a.adapter.delete({model:"organizationRole",where:[{field:"id",value:e}]})}),inviteMember:({email:e,inviterId:a,organizationId:t,role:i})=>n(async r=>{let s=a;if(s===void 0||s===""){const c=await r.adapter.findMany({model:"member",where:[{field:"organizationId",value:t}]});s=(c.find(y=>typeof y.role=="string"&&y.role.includes("owner"))??c[0])?.userId}if(s===void 0||s==="")throw new p("provide an inviter — the organization has no members to attribute the invitation to","INVITER_REQUIRED");const d=await r.adapter.create({data:{createdAt:new Date,email:e.toLowerCase(),expiresAt:new Date(Date.now()+z),inviterId:s,organizationId:t,role:i===void 0||i===""?"member":i,status:"pending"},model:"invitation"});return u(d)}),listOrgRoles:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"organizationRole",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:[{field:"organizationId",value:t}]})),listTeamMembers:({limit:e,offset:a,teamId:t})=>n(i=>v(i,"teamMember",{limit:e,offset:a,where:[{field:"teamId",value:t}]})),listTeams:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"team",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:[{field:"organizationId",value:t}]})),removeTeam:({teamId:e})=>n(async a=>{await a.adapter.deleteMany({model:"teamMember",where:[{field:"teamId",value:e}]}),await a.adapter.delete({model:"team",where:[{field:"id",value:e}]})}),removeTeamMember:({teamMemberId:e})=>n(async a=>{await a.adapter.delete({model:"teamMember",where:[{field:"id",value:e}]})}),updateMemberRole:({memberId:e,role:a})=>n(async t=>{const i=await t.adapter.update({model:"member",update:{role:g(a)},where:[{field:"id",value:e}]});return u(i??{id:e,role:g(a)})}),updateOrganization:({logo:e,metadata:a,name:t,organizationId:i,slug:r})=>n(async s=>{const d={};if(t!==void 0&&(d.name=t),r!==void 0&&r!==""&&(d.slug=S(r)),e!==void 0&&(d.logo=e===""?void 0:e),a!==void 0&&(d.metadata=JSON.stringify(a)),Object.keys(d).length===0)return u({id:i});const c=await s.adapter.update({model:"organization",update:d,where:[{field:"id",value:i}]});return u(c??{id:i})}),updateOrgRole:({permission:e,roleId:a})=>n(async t=>{const i=await t.adapter.update({model:"organizationRole",update:{permission:JSON.stringify(e),updatedAt:new Date},where:[{field:"id",value:a}]});return u(i??{id:a,permission:JSON.stringify(e)})}),updateTeam:({name:e,teamId:a})=>n(async t=>{const i=await t.adapter.update({model:"team",update:{name:e,updatedAt:new Date},where:[{field:"id",value:a}]});return u(i??{id:a,name:e})}),createUser:({data:e,email:a,name:t,password:i,role:r})=>n(async s=>{const d=a.toLowerCase();if(await s.internalAdapter.findUserByEmail(d))throw new p("a user with this email already exists","USER_ALREADY_EXISTS");const c=await s.internalAdapter.createUser({email:d,name:t,role:r===void 0?void 0:g(r),...e},{method:"admin"});if(i!==void 0&&i!==""){const h=await s.password.hash(i);await s.internalAdapter.linkAccount({accountId:c.id,password:h,providerId:"credential",userId:c.id})}return w(c)}),deletePasskey:({passkeyId:e})=>n(async a=>{await a.adapter.delete({model:"passkey",where:[{field:"id",value:e}]})}),disableTwoFactor:({userId:e})=>n(async a=>{await a.adapter.deleteMany({model:"twoFactor",where:[{field:"userId",value:e}]}),await a.internalAdapter.updateUser(e,{twoFactorEnabled:!1})}),impersonateUser:({userId:e})=>n(async a=>{const t=await a.internalAdapter.findUserById(e);if(!t)throw new p("user not found","USER_NOT_FOUND");const i=m.impersonationSeconds;let r=O;if(i!==void 0){if(!Number.isInteger(i)||!Number.isFinite(i)||i<=0)throw new p("impersonationSeconds must be a positive finite integer","INVALID_IMPERSONATION_SECONDS");r=Math.min(i,D)}const s=new Date(Date.now()+r*1e3),d=await a.internalAdapter.createSession(e,!0,{expiresAt:s,impersonatedBy:m.impersonatedBy??e},!0);return{expiresAt:d.expiresAt instanceof Date?d.expiresAt.getTime():s.getTime(),token:d.token,user:w(t)}}),listAccounts:({userId:e})=>n(async a=>(await a.adapter.findMany({model:"account",where:[{field:"userId",value:e}]})).map(i=>u(i))),listInvitations:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"invitation",{limit:e,offset:a,where:[{field:"organizationId",value:t}]})),createSignUpInvitation:({email:e,expiresInSeconds:a,invitedBy:t})=>n(async()=>{const i=await R(o,{email:e,expiresInSeconds:a,invitedBy:t});return{...u({...i}),token:i.token}}),listSignUpInvitations:({limit:e,offset:a})=>n(t=>v(t,"signUpInvitation",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"}})),revokeSignUpInvitation:({email:e})=>n(async()=>U(o,{email:e})),listMembers:({limit:e,offset:a,organizationId:t})=>n(i=>v(i,"member",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:[{field:"organizationId",value:t}]})),listOrganizations:({limit:e,offset:a})=>n(t=>v(t,"organization",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"}})),listPasskeys:({userId:e})=>n(async a=>(await a.adapter.findMany({model:"passkey",where:[{field:"userId",value:e}]})).map(i=>u(i))),listSessions:({limit:e,offset:a,userId:t})=>n(i=>v(i,"session",{limit:e,offset:a,sortBy:{direction:"desc",field:"createdAt"},where:t===void 0||t===""?void 0:[{field:"userId",value:t}]})),listUsers:({filterField:e,filterValue:a,limit:t,offset:i,search:r,searchField:s,sortBy:d,sortDirection:c})=>n(h=>{const y=[];return r!==void 0&&r!==""&&y.push({field:s??"email",operator:"contains",value:r}),a!==void 0&&y.push({field:e??"email",operator:"eq",value:a}),v(h,"user",{limit:t,offset:i,sortBy:{direction:c??"desc",field:d??"createdAt"},where:y})}),removeMember:({memberId:e})=>n(async a=>{await a.adapter.delete({model:"member",where:[{field:"id",value:e}]})}),removeUser:({userId:e})=>n(async a=>{const t=b(a.options);t.member&&await _(a,e),await Promise.all(k.filter(({model:i})=>t[i]).map(({field:i,model:r})=>a.adapter.deleteMany({model:r,where:[{field:i,value:e}]}))),await a.internalAdapter.deleteUserSessions(e),await a.internalAdapter.deleteUser(e)}),revokeUserSession:({sessionId:e})=>n(async a=>{const t=await a.adapter.findOne({model:"session",where:[{field:"id",value:e}]});t?.token&&await a.internalAdapter.deleteSession(t.token)}),revokeUserSessions:({userId:e})=>n(async a=>{await a.internalAdapter.deleteUserSessions(e)}),setRole:({role:e,userId:a})=>n(async t=>{const i=await t.internalAdapter.updateUser(a,{role:g(e)});return w(i)}),setUserPassword:({newPassword:e,userId:a})=>n(async t=>{const i=t.password.config.minPasswordLength,r=t.password.config.maxPasswordLength;if(e.length<i)throw new p(`password must be at least ${i.toString()} characters`,"PASSWORD_TOO_SHORT");if(e.length>r)throw new p(`password must be at most ${r.toString()} characters`,"PASSWORD_TOO_LONG");if(!await t.internalAdapter.findUserById(a))throw new p("user not found","USER_NOT_FOUND");const d=(await t.internalAdapter.findAccounts(a)).some(h=>h.providerId==="credential");if(!d&&t.options.emailAndPassword?.enabled!==!0)throw new p("email/password sign-in is disabled for this deployment","EMAIL_PASSWORD_DISABLED");const c=await t.password.hash(e);d?await t.internalAdapter.updatePassword(a,c):await t.internalAdapter.linkAccount({accountId:a,password:c,providerId:"credential",userId:a})}),unbanUser:({userId:e})=>n(async a=>{const t=await a.internalAdapter.updateUser(e,{banExpires:null,banned:!1,banReason:null});return w(t)}),unlinkAccount:({accountId:e,userId:a})=>n(async t=>{await t.adapter.delete({model:"account",where:[{field:"id",value:e},{connector:"AND",field:"userId",value:a}]})}),updateUser:({data:e,userId:a})=>n(async t=>{const i=await t.internalAdapter.updateUser(a,e);return w(i)})}};export{p as LunoraAuthAdminError,W as createAuthAdmin};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{defineErrorCodes as S}from"@better-auth/core/utils/error-codes";import{LunoraError as A}from"@lunora/errors";import{createAuthMiddleware as T,APIError as g}from"better-auth/api";const c="signUpInvitation",_=10080*60,v=365*24*60*60,y=500,w=S({SIGN_UP_INVITE_INVALID:"That sign-up invitation is not valid. Ask an administrator for a new invitation link.",SIGN_UP_INVITE_REQUIRED:"Sign-up is invite-only — ask an administrator for an invitation."}),D=32,x=/^[^\s@]+@[^\s@]+$/,O=e=>{if(!x.test(e))return!1;const t=e.slice(e.indexOf("@")+1);return t.includes(".")&&!t.startsWith(".")&&!t.endsWith(".")},p=e=>({acceptedAt:e.acceptedAt instanceof Date?e.acceptedAt:null,createdAt:e.createdAt,email:String(e.email),expiresAt:e.expiresAt,id:String(e.id),invitedBy:typeof e.invitedBy=="string"?e.invitedBy:null}),R=()=>btoa(String.fromCodePoint(...crypto.getRandomValues(new Uint8Array(D)))).replaceAll("+","-").replaceAll("/","_").replaceAll("=",""),E=async e=>{const t=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(e));return[...new Uint8Array(t)].map(i=>i.toString(16).padStart(2,"0")).join("")},N=(e,t)=>{if(e.length!==t.length)return!1;let i=0;for(let n=0;n<e.length;n+=1)i|=(e.codePointAt(n)??0)^(t.codePointAt(n)??0);return i===0},m=e=>e.trim().toLowerCase(),I=e=>{if(typeof e.email!="string")return;const t=m(e.email);return t===""?void 0:t},k=async(e,t)=>{const i=await e.findOne({model:c,where:[{field:"email",value:t}]});return i===null||i.acceptedAt instanceof Date?!1:i.expiresAt instanceof Date&&i.expiresAt.getTime()>Date.now()},U=e=>{e.emailAndPassword?.enabled!==!0||e.emailAndPassword.requireEmailVerification===!0||console.warn("@lunora/auth: inviteOnly() is installed with password sign-up but without `emailAndPassword: { requireEmailVerification: true }`. An invitation is keyed by email address alone, so anyone who learns an invited address can sign up as it — and without verification they hold a session the moment they do.")},q=(e={})=>{let t=e.allowFirstUser??!1;const i=async n=>t?await n.count({model:"user"})===0?!0:(t=!1,!1):!1;return{$ERROR_CODES:w,hooks:{before:[{handler:T(async n=>{const r=n.body??{},a=typeof r.email=="string"?m(r.email):"",d=typeof r.inviteToken=="string"?r.inviteToken:"",s=()=>{throw new g("BAD_REQUEST",w.SIGN_UP_INVITE_INVALID)};if(a===""&&s(),await i(n.context.adapter))return;d===""&&s();const o=await n.context.adapter.findOne({model:c,where:[{field:"email",value:a}]}),u=o===null?void 0:o.tokenHash,f=await E(d);(typeof u!="string"||!N(u,f))&&s()}),matcher:n=>n.path==="/sign-up/email"}]},id:"lunora-invite-only",init:n=>{U(n.options);const{adapter:r}=n;return{options:{databaseHooks:{user:{create:{after:async s=>{const o=I(s);o!==void 0&&await r.update({model:c,update:{acceptedAt:new Date},where:[{field:"email",value:o}]})},before:async s=>{const o=I(s);if(!(o!==void 0&&await k(r,o))&&!await i(r))throw new g("BAD_REQUEST",w.SIGN_UP_INVITE_REQUIRED)}}}}}}},schema:{[c]:{fields:{acceptedAt:{required:!1,type:"date"},tokenHash:{required:!1,type:"string"},createdAt:{defaultValue:()=>new Date,required:!0,type:"date"},email:{required:!0,type:"string",unique:!0},expiresAt:{required:!0,type:"date"},invitedBy:{required:!1,type:"string"}}}}}},M=async(e,t)=>{const i=m(t.email);if(!O(i))throw new A("VALIDATION_ERROR",`not an email address to invite: ${JSON.stringify(t.email)}`);const{expiresInSeconds:n=_}=t;if(!Number.isInteger(n)||n<=0||n>v)throw new A("VALIDATION_ERROR",`expiresInSeconds must be a positive integer no greater than ${String(v)}`);const r=new Date(Date.now()+n*1e3),a=R(),d=await E(a),s=t.invitedBy??null,o=await e.$context,u=[{field:"email",value:i}],f=async()=>o.adapter.update({model:c,update:{acceptedAt:null,expiresAt:r,invitedBy:s,tokenHash:d},where:u});if(await o.adapter.findOne({model:c,where:u})){const l=await f();if(l)return{...p(l),token:a}}try{const l=await o.adapter.create({data:{createdAt:new Date,email:i,expiresAt:r,invitedBy:s,tokenHash:d},model:c});return{...p(l),token:a}}catch(l){const h=await f();if(h===null)throw l;return{...p(h),token:a}}},$=async(e,t={})=>{const r=(await(await e.$context).adapter.findMany({limit:y,model:c,sortBy:{direction:"desc",field:"createdAt"}})).map(a=>p(a));return t.pendingOnly===!0?r.filter(a=>a.acceptedAt===null&&a.expiresAt.getTime()>Date.now()):r},C=async(e,t)=>{await(await e.$context).adapter.delete({model:c,where:[{field:"email",value:m(t.email)}]})},b=100,V=async(e,t,i,n)=>{const r=t.filter(a=>a.acceptedAt===null&&a.expiresAt.getTime()<=i).slice(0,n);for(const a of r)await e.delete({model:c,where:[{field:"id",value:a.id}]});return r.length},H=async(e,t={})=>{const i=t.limit??y;if(!Number.isInteger(i)||i<=0)throw new A("VALIDATION_ERROR","limit must be a positive integer");const n=Math.min(i,y),r=await e.$context,a=Date.now();let d=0,s=0;for(;d<n;){const o=await r.adapter.findMany({limit:b,model:c,offset:s,sortBy:{direction:"asc",field:"expiresAt"}});if(o.length===0)break;const u=o.map(l=>p(l)),f=await V(r.adapter,u,a,n-d);if(d+=f,u.some(l=>l.expiresAt.getTime()>a))break;s+=o.length-f}return d};export{M as createSignUpInvitation,q as inviteOnly,$ as listSignUpInvitations,H as pruneSignUpInvitations,C as revokeSignUpInvitation};
|