better-auth
Version:
The most comprehensive authentication framework for TypeScript.
730 lines (729 loc) • 21.2 kB
text/typescript
import { Session as Session$1, User as User$1 } from "../../types/models.mjs";
import "../../types/index.mjs";
import { AccessControl, Role } from "../access/types.mjs";
import "../access/index.mjs";
import { Invitation, Member, Organization, OrganizationRole, Team, TeamMember } from "./schema.mjs";
import { AuthContext, Awaitable, GenericEndpointContext } from "@better-auth/core";
import { DBFieldAttribute } from "@better-auth/core/db";
//#region src/plugins/organization/types.d.ts
interface OrganizationOptions {
/**
* Configure whether new users are able to create new organizations.
* You can also pass a function that returns a boolean.
*
* @example
* ```ts
* allowUserToCreateOrganization: async (user) => {
* const plan = await getUserPlan(user);
* return plan.name === "pro";
* }
* ```
* @default true
*/
allowUserToCreateOrganization?: (boolean | ((user: User$1 & Record<string, any>) => Awaitable<boolean>)) | undefined;
/**
* The maximum number of organizations a user can create.
*
* You can also pass a function that returns a boolean. The function should return `true` if the user has reached their organization limit, and `false` otherwise.
*
* @default unlimited
* @example
* ```ts
* organizationLimit: async (user) => {
* const plan = await getUserPlan(user);
* // Return true if the user has reached their organization limit, false otherwise
* return plan.name === "pro";
* }
* ```
*/
organizationLimit?: (number | ((user: User$1 & Record<string, any>) => Awaitable<boolean>)) | undefined;
/**
* The role that is assigned to the creator of the
* organization.
*
* @default "owner"
*/
creatorRole?: string | undefined;
/**
* The maximum number of members allowed in an organization.
*
* @default 100
*/
membershipLimit?: number | undefined;
/**
* Configure the roles and permissions for the
* organization plugin.
*/
ac?: AccessControl | undefined;
/**
* Custom permissions for roles.
*/
roles?: { [key in string]?: Role<any> } | undefined;
/**
* Dynamic access control for the organization plugin.
*/
dynamicAccessControl?: {
/**
* Whether to enable dynamic access control for the organization plugin.
*
* @default false
*/
enabled?: boolean;
/**
* The maximum number of roles that can be created for an organization.
*
* @default Infinite
*/
maximumRolesPerOrganization?: number | ((organizationId: string) => Awaitable<number>);
} | undefined;
/**
* Support for team.
*/
teams?: {
/**
* Enable team features.
*/
enabled: boolean;
/**
* Default team configuration
*/
defaultTeam?: {
/**
* Enable creating a default team when an organization is created
*
* @default true
*/
enabled: boolean;
/**
* Pass a custom default team creator function
*/
customCreateDefaultTeam?: (organization: Organization & Record<string, any>, ctx?: GenericEndpointContext) => Promise<Team & Record<string, any>>;
};
/**
* Maximum number of teams an organization can have.
*
* You can pass a number or a function that returns a number
*
* @default "unlimited"
*
* @param organization
* @param request
* @returns
*/
maximumTeams?: ((data: {
organizationId: string;
session: {
user: User$1;
session: Session$1;
} | null;
}, ctx?: GenericEndpointContext) => Awaitable<number>) | number;
/**
* The maximum number of members per team.
*
* if `undefined`, there is no limit.
*
* @default undefined
*/
maximumMembersPerTeam?: number | ((data: {
teamId: string;
session: {
user: User$1;
session: Session$1;
};
organizationId: string;
}) => Awaitable<number>) | undefined;
/**
* By default, if an organization does only have one team, they'll not be able to remove it.
*
* You can disable this behavior by setting this to `false.
*
* @default false
*/
allowRemovingAllTeams?: boolean;
};
/**
* The expiration time for the invitation link.
*
* @default 48 hours
*/
invitationExpiresIn?: number | undefined;
/**
* The maximum invitation a user can send.
*
* @default 100
*/
invitationLimit?: number | ((data: {
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
member: Member & Record<string, any>;
}, ctx: AuthContext) => Awaitable<number>) | undefined;
/**
* Cancel pending invitations on re-invite.
*
* @default false
*/
cancelPendingInvitationsOnReInvite?: boolean | undefined;
/**
* Require email verification on accepting or rejecting an invitation
*
* @default false
*/
requireEmailVerificationOnInvitation?: boolean | undefined;
/**
* Send an email with the
* invitation link to the user.
*
* Note: Better Auth doesn't
* generate invitation URLs.
* You'll need to construct the
* URL using the invitation ID
* and pass it to the
* acceptInvitation endpoint for
* the user to accept the
* invitation.
*
* @example
* ```ts
* sendInvitationEmail: async (data) => {
* const url = `https://yourapp.com/organization/
* accept-invitation?id=${data.id}`;
* sendEmail(data.email, "Invitation to join
* organization", `Click the link to join the
* organization: ${url}`);
* }
* ```
*/
sendInvitationEmail?: ((data: {
/**
* the invitation id
*/
id: string;
/**
* the role of the user
*/
role: string;
/**
* the email of the user
*/
email: string;
/**
* the organization the user is invited to join
*/
organization: Organization;
/**
* the invitation object
*/
invitation: Invitation;
/**
* the member who is inviting the user
*/
inviter: Member & {
user: User$1;
};
},
/**
* The request object
*/
request?: Request) => Promise<void>) | undefined;
/**
* The schema for the organization plugin.
*/
schema?: {
session?: {
fields?: {
activeOrganizationId?: string;
activeTeamId?: string;
};
};
organization?: {
modelName?: string;
fields?: { [key in keyof Omit<Organization, "id">]?: string };
additionalFields?: { [key in string]: DBFieldAttribute };
};
member?: {
modelName?: string;
fields?: { [key in keyof Omit<Member, "id">]?: string };
additionalFields?: { [key in string]: DBFieldAttribute };
};
invitation?: {
modelName?: string;
fields?: { [key in keyof Omit<Invitation, "id">]?: string };
additionalFields?: { [key in string]: DBFieldAttribute };
};
team?: {
modelName?: string;
fields?: { [key in keyof Omit<Team, "id">]?: string };
additionalFields?: { [key in string]: DBFieldAttribute };
};
teamMember?: {
modelName?: string;
fields?: { [key in keyof Omit<TeamMember, "id">]?: string };
};
organizationRole?: {
modelName?: string;
fields?: { [key in keyof Omit<OrganizationRole, "id">]?: string };
additionalFields?: { [key in string]: DBFieldAttribute };
};
} | undefined;
/**
* Disable organization deletion
*
* @default false
*/
disableOrganizationDeletion?: boolean | undefined;
/**
* Configure how organization deletion is handled
*
* @deprecated Use `organizationHooks` instead
*/
organizationDeletion?: {
/**
* disable deleting organization
*
* @deprecated Use `disableOrganizationDeletion` instead
*/
disabled?: boolean;
/**
* A callback that runs before the organization is
* deleted
*
* @deprecated Use `organizationHooks` instead
* @param data - organization and user object
* @param request - the request object
* @returns
*/
beforeDelete?: (data: {
organization: Organization;
user: User$1;
}, request?: Request) => Promise<void>;
/**
* A callback that runs after the organization is
* deleted
*
* @deprecated Use `organizationHooks` instead
* @param data - organization and user object
* @param request - the request object
* @returns
*/
afterDelete?: (data: {
organization: Organization;
user: User$1;
}, request?: Request) => Promise<void>;
} | undefined;
/**
* @deprecated Use `organizationHooks` instead
*/
organizationCreation?: {
disabled?: boolean;
beforeCreate?: (data: {
organization: Omit<Organization, "id"> & Record<string, any>;
user: User$1 & Record<string, any>;
}, request?: Request) => Promise<void | {
data: Record<string, any>;
}>;
afterCreate?: (data: {
organization: Organization & Record<string, any>;
member: Member & Record<string, any>;
user: User$1 & Record<string, any>;
}, request?: Request) => Promise<void>;
} | undefined;
/**
* Hooks for organization
*/
organizationHooks?: {
/**
* A callback that runs before the organization is created
*
* You can return a `data` object to override the default data.
*
* @example
* ```ts
* beforeCreateOrganization: async (data) => {
* return {
* data: {
* ...data.organization,
* },
* };
* }
* ```
*
* You can also throw `new APIError` to stop the organization creation.
*
* @example
* ```ts
* beforeCreateOrganization: async (data) => {
* throw new APIError("BAD_REQUEST", {
* message: "Organization creation is disabled",
* });
* }
*/
beforeCreateOrganization?: (data: {
organization: {
name?: string;
slug?: string;
logo?: string;
metadata?: Record<string, any>;
[key: string]: any;
};
user: User$1 & Record<string, any>;
}) => Promise<void | {
data: Record<string, any>;
}>;
/**
* A callback that runs after the organization is created
*/
afterCreateOrganization?: (data: {
organization: Organization & Record<string, any>;
member: Member & Record<string, any>;
user: User$1 & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before the organization is updated
*
* You can return a `data` object to override the default data.
*
* @example
* ```ts
* beforeUpdateOrganization: async (data) => {
* return { data: { ...data.organization } };
* }
*/
beforeUpdateOrganization?: (data: {
organization: {
name?: string;
slug?: string;
logo?: string;
metadata?: Record<string, any>;
[key: string]: any;
};
user: User$1 & Record<string, any>;
member: Member & Record<string, any>;
}) => Promise<void | {
data: {
name?: string;
slug?: string;
logo?: string;
metadata?: Record<string, any>;
[key: string]: any;
};
}>;
/**
* A callback that runs after the organization is updated
*
* @example
* ```ts
* afterUpdateOrganization: async (data) => {
* console.log(data.organization);
* }
* ```
*/
afterUpdateOrganization?: (data: {
/**
* Updated organization object
*
* This could be `null` if an adapter doesn't return updated organization.
*/
organization: (Organization & Record<string, any>) | null;
user: User$1 & Record<string, any>;
member: Member & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before the organization is deleted
*/
beforeDeleteOrganization?: (data: {
organization: Organization & Record<string, any>;
user: User$1 & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after the organization is deleted
*/
afterDeleteOrganization?: (data: {
organization: Organization & Record<string, any>;
user: User$1 & Record<string, any>;
}) => Promise<void>;
/**
* Member hooks
*/
/**
* A callback that runs before a member is added to an organization
*
* You can return a `data` object to override the default data.
*
* @example
* ```ts
* beforeAddMember: async (data) => {
* return {
* data: {
* ...data.member,
* role: "custom-role"
* }
* };
* }
* ```
*/
beforeAddMember?: (data: {
member: {
userId: string;
organizationId: string;
role: string;
[key: string]: any;
};
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void | {
data: Record<string, any>;
}>;
/**
* A callback that runs after a member is added to an organization
*/
afterAddMember?: (data: {
member: Member & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before a member is removed from an organization
*/
beforeRemoveMember?: (data: {
member: Member & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after a member is removed from an organization
*/
afterRemoveMember?: (data: {
member: Member & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before a member's role is updated
*
* You can return a `data` object to override the default data.
*/
beforeUpdateMemberRole?: (data: {
member: Member & Record<string, any>;
newRole: string;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void | {
data: {
role: string;
[key: string]: any;
};
}>;
/**
* A callback that runs after a member's role is updated
*/
afterUpdateMemberRole?: (data: {
member: Member & Record<string, any>;
previousRole: string;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* Invitation hooks
*/
/**
* A callback that runs before an invitation is created
*
* You can return a `data` object to override the default data.
*
* @example
* ```ts
* beforeCreateInvitation: async (data) => {
* return {
* data: {
* ...data.invitation,
* expiresAt: new Date(Date.now() + 1000 * 60 * 60 * 24 * 7) // 7 days
* }
* };
* }
* ```
*/
beforeCreateInvitation?: (data: {
invitation: {
email: string;
role: string;
organizationId: string;
inviterId: string;
teamId?: string;
[key: string]: any;
};
inviter: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void | {
data: Record<string, any>;
}>;
/**
* A callback that runs after an invitation is created
*/
afterCreateInvitation?: (data: {
invitation: Invitation & Record<string, any>;
inviter: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before an invitation is accepted
*/
beforeAcceptInvitation?: (data: {
invitation: Invitation & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after an invitation is accepted
*/
afterAcceptInvitation?: (data: {
invitation: Invitation & Record<string, any>;
member: Member & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before an invitation is rejected
*/
beforeRejectInvitation?: (data: {
invitation: Invitation & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after an invitation is rejected
*/
afterRejectInvitation?: (data: {
invitation: Invitation & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before an invitation is cancelled
*/
beforeCancelInvitation?: (data: {
invitation: Invitation & Record<string, any>;
cancelledBy: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after an invitation is cancelled
*/
afterCancelInvitation?: (data: {
invitation: Invitation & Record<string, any>;
cancelledBy: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* Team hooks (when teams are enabled)
*/
/**
* A callback that runs before a team is created
*
* You can return a `data` object to override the default data.
*/
beforeCreateTeam?: (data: {
team: {
name: string;
organizationId: string;
[key: string]: any;
};
user?: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void | {
data: Record<string, any>;
}>;
/**
* A callback that runs after a team is created
*/
afterCreateTeam?: (data: {
team: Team & Record<string, any>;
user?: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before a team is updated
*
* You can return a `data` object to override the default data.
*/
beforeUpdateTeam?: (data: {
team: Team & Record<string, any>;
updates: {
name?: string;
[key: string]: any;
};
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void | {
data: Record<string, any>;
}>;
/**
* A callback that runs after a team is updated
*/
afterUpdateTeam?: (data: {
team: (Team & Record<string, any>) | null;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before a team is deleted
*/
beforeDeleteTeam?: (data: {
team: Team & Record<string, any>;
user?: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after a team is deleted
*/
afterDeleteTeam?: (data: {
team: Team & Record<string, any>;
user?: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before a member is added to a team
*/
beforeAddTeamMember?: (data: {
teamMember: {
teamId: string;
userId: string;
[key: string]: any;
};
team: Team & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void | {
data: Record<string, any>;
}>;
/**
* A callback that runs after a member is added to a team
*/
afterAddTeamMember?: (data: {
teamMember: TeamMember & Record<string, any>;
team: Team & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs before a member is removed from a team
*/
beforeRemoveTeamMember?: (data: {
teamMember: TeamMember & Record<string, any>;
team: Team & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
/**
* A callback that runs after a member is removed from a team
*/
afterRemoveTeamMember?: (data: {
teamMember: TeamMember & Record<string, any>;
team: Team & Record<string, any>;
user: User$1 & Record<string, any>;
organization: Organization & Record<string, any>;
}) => Promise<void>;
} | undefined;
}
//#endregion
export { OrganizationOptions };
//# sourceMappingURL=types.d.mts.map