import type { BillingUser } from "./types.js"; import type { WorkOSOrgMap } from "./adapters/workos-org.js"; export interface InvitationEmailContext { /** WorkOS invitation id (use it in your accept link). */ id: string; email: string; roleSlug: string; /** App orgId (post-map). */ orgId: string; /** WorkOS organization id. */ organizationId: string; /** `${baseUrl}${acceptPath}/${id}` — ready-made link for a custom email. */ acceptUrl: string; inviterUserId?: string; } export interface InvitationHooks { /** Send a branded email. Omit → rely on WorkOS's default invitation email. */ sendEmail?(ctx: InvitationEmailContext): Promise; /** Decide whether `user` may accept an invite addressed to `invitedEmail`. * Omit → case-insensitive match against the user's WorkOS primary email. * Return false for a generic rejection, or throw for a custom message. */ canAccept?(invitedEmail: string, user: BillingUser): Promise; } export interface Invitation { id: string; email: string; roleSlug: string; /** App orgId (post-map), or "" if it can't be resolved. */ orgId: string; organizationId: string; state: "pending" | "accepted" | "expired" | "revoked"; createdAt: string; expiresAt: string; /** * Where the invited person accepts, built from this service's own `baseUrl` + `acceptPath`. * * On the record rather than only in the email hook's context, because the email is no * longer the only thing that needs it: a notification carries the link to whoever renders * it, and the alternative — every consumer of the event re-deriving the path — is how the * link in the email and the route that accepts it come to disagree. */ acceptUrl?: string; /** * The WorkOS user this invitation belongs to — present from `send`, absent elsewhere. * * Sending an invitation CREATES the user (measured: it exists the moment `send` returns, * which is also why a pending membership already blocks acceptance — see `accept`). That * makes it possible to act on the invited person before they ever sign in, and the one * caller that needs to is `inviteMember` with a `seatType`: a seat is stored per USER, so * seating an invitee needs their id and nothing else. * * Resolved only here, not in `normalize`: `list` would otherwise pay a lookup per row for * a field almost nobody reads. `acceptedUserId` is NOT it — WorkOS leaves that null until * acceptance. */ userId?: string | null; } export interface WorkOSInvitationsOptions { apiKey?: string; clientId?: string; /** ws↔org id map (share the adapter's). Omit → orgId IS the WorkOS org id. */ map?: WorkOSOrgMap; /** Base URL for the custom-email accept link. */ baseUrl?: string; /** Accept-link path prefix. Default "/invita". */ acceptPath?: string; hooks?: InvitationHooks; } export interface InvitationService { send(orgId: string, email: string, roleSlug: string, inviterUserId?: string): Promise; list(orgId: string): Promise; get(invitationId: string): Promise; accept(invitationId: string, user: BillingUser): Promise<{ orgId: string; }>; revoke(orgId: string, invitationId: string): Promise; } export declare function createWorkOSInvitations(opts?: WorkOSInvitationsOptions): InvitationService; //# sourceMappingURL=invitations.d.ts.map