{"version":3,"file":"types-ndj-bYfi.mjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["/**\n * Core types for @emdash-cms/auth\n */\n\n// ============================================================================\n// Roles & Permissions\n// ============================================================================\n\nexport const Role = {\n\tSUBSCRIBER: 10,\n\tCONTRIBUTOR: 20,\n\tAUTHOR: 30,\n\tEDITOR: 40,\n\tADMIN: 50,\n} as const;\n\nexport type RoleLevel = (typeof Role)[keyof typeof Role];\nexport type RoleName = keyof typeof Role;\n\nexport function roleFromLevel(level: number): RoleName | undefined {\n\tconst entry = Object.entries(Role).find(([, v]) => v === level);\n\tif (!entry) return undefined;\n\tconst name = entry[0];\n\tif (isRoleName(name)) return name;\n\treturn undefined;\n}\n\nfunction isRoleName(value: string): value is RoleName {\n\treturn value in Role;\n}\n\nconst ROLE_LEVEL_MAP = new Map<number, RoleLevel>(Object.values(Role).map((v) => [v, v]));\n\nexport function toRoleLevel(value: number): RoleLevel {\n\tconst level = ROLE_LEVEL_MAP.get(value);\n\tif (level !== undefined) return level;\n\tthrow new Error(`Invalid role level: ${value}`);\n}\n\nconst DEVICE_TYPE_MAP: Record<string, DeviceType | undefined> = {\n\tsingleDevice: \"singleDevice\",\n\tmultiDevice: \"multiDevice\",\n};\n\nexport function toDeviceType(value: string): DeviceType {\n\tconst dt = DEVICE_TYPE_MAP[value];\n\tif (dt !== undefined) return dt;\n\tthrow new Error(`Invalid device type: ${value}`);\n}\n\nconst TOKEN_TYPE_MAP: Record<string, TokenType | undefined> = {\n\tmagic_link: \"magic_link\",\n\temail_verify: \"email_verify\",\n\tinvite: \"invite\",\n\trecovery: \"recovery\",\n};\n\nexport function toTokenType(value: string): TokenType {\n\tconst tt = TOKEN_TYPE_MAP[value];\n\tif (tt !== undefined) return tt;\n\tthrow new Error(`Invalid token type: ${value}`);\n}\n\nexport function roleToLevel(name: RoleName): RoleLevel {\n\treturn Role[name];\n}\n\n// ============================================================================\n// User\n// ============================================================================\n\nexport interface User {\n\tid: string;\n\temail: string;\n\tname: string | null;\n\tavatarUrl: string | null;\n\trole: RoleLevel;\n\temailVerified: boolean;\n\tdisabled: boolean;\n\tdata: Record<string, unknown> | null;\n\tcreatedAt: Date;\n\tupdatedAt: Date;\n}\n\nexport interface NewUser {\n\temail: string;\n\tname?: string | null;\n\tavatarUrl?: string | null;\n\trole?: RoleLevel;\n\temailVerified?: boolean;\n\tdata?: Record<string, unknown> | null;\n}\n\nexport interface UpdateUser {\n\temail?: string;\n\tname?: string | null;\n\tavatarUrl?: string | null;\n\trole?: RoleLevel;\n\temailVerified?: boolean;\n\tdisabled?: boolean;\n\tdata?: Record<string, unknown> | null;\n}\n\n// ============================================================================\n// Credentials (Passkeys)\n// ============================================================================\n\nexport type AuthenticatorTransport = \"usb\" | \"nfc\" | \"ble\" | \"internal\" | \"hybrid\";\nexport type DeviceType = \"singleDevice\" | \"multiDevice\";\n\nexport interface Credential {\n\tid: string; // Base64url credential ID\n\tuserId: string;\n\tpublicKey: Uint8Array; // Encoded public key (SEC1 for ECDSA, PKIX for RSA)\n\talgorithm: number; // COSE algorithm identifier (e.g., -7 for ES256, -257 for RS256)\n\tcounter: number;\n\tdeviceType: DeviceType;\n\tbackedUp: boolean;\n\ttransports: AuthenticatorTransport[];\n\tname: string | null;\n\tcreatedAt: Date;\n\tlastUsedAt: Date;\n}\n\nexport interface NewCredential {\n\tid: string;\n\tuserId: string;\n\tpublicKey: Uint8Array;\n\talgorithm: number;\n\tcounter: number;\n\tdeviceType: DeviceType;\n\tbackedUp: boolean;\n\ttransports: AuthenticatorTransport[];\n\tname?: string | null;\n}\n\n// ============================================================================\n// Sessions\n// ============================================================================\n\nexport interface Session {\n\tid: string;\n\tuserId: string;\n\texpiresAt: Date;\n\tipAddress: string | null;\n\tuserAgent: string | null;\n\tcreatedAt: Date;\n}\n\nexport interface SessionData {\n\tuserId: string;\n\texpiresAt: number; // Unix timestamp\n}\n\n// ============================================================================\n// Auth Tokens (magic links, invites, etc.)\n// ============================================================================\n\nexport type TokenType = \"magic_link\" | \"email_verify\" | \"invite\" | \"recovery\";\n\nexport interface AuthToken {\n\thash: string; // SHA-256 hash of the raw token\n\tuserId: string | null; // null for pre-user tokens (invite/signup)\n\temail: string | null; // For pre-user tokens\n\ttype: TokenType;\n\trole: RoleLevel | null; // For invites\n\tinvitedBy: string | null;\n\texpiresAt: Date;\n\tcreatedAt: Date;\n}\n\nexport interface NewAuthToken {\n\thash: string;\n\tuserId?: string | null;\n\temail?: string | null;\n\ttype: TokenType;\n\trole?: RoleLevel | null;\n\tinvitedBy?: string | null;\n\texpiresAt: Date;\n}\n\n// ============================================================================\n// OAuth Accounts\n// ============================================================================\n\nexport interface OAuthAccount {\n\tprovider: string;\n\tproviderAccountId: string;\n\tuserId: string;\n\tcreatedAt: Date;\n}\n\nexport interface NewOAuthAccount {\n\tprovider: string;\n\tproviderAccountId: string;\n\tuserId: string;\n}\n\n// ============================================================================\n// OAuth Connections (SSO config)\n// ============================================================================\n\nexport interface OAuthConnection {\n\tid: string;\n\tname: string;\n\tprovider: \"oidc\" | \"github\" | \"google\";\n\tclientId: string;\n\tclientSecretEnc: string; // Encrypted\n\tissuerUrl: string | null;\n\tconfig: Record<string, unknown> | null;\n\tenabled: boolean;\n\tcreatedAt: Date;\n}\n\n// ============================================================================\n// OAuth Clients (when EmDash is provider)\n// ============================================================================\n\nexport interface OAuthClient {\n\tid: string;\n\tname: string;\n\tsecretHash: string;\n\tredirectUris: string[];\n\tscopes: string[];\n\tcreatedAt: Date;\n}\n\n// ============================================================================\n// Allowed Domains (self-signup)\n// ============================================================================\n\nexport interface AllowedDomain {\n\tdomain: string;\n\tdefaultRole: RoleLevel;\n\tenabled: boolean;\n\tcreatedAt: Date;\n}\n\n// ============================================================================\n// User Listing Types (for admin UI)\n// ============================================================================\n\n/** Extended user with list view computed fields */\nexport interface UserListItem extends User {\n\tlastLogin: Date | null;\n\tcredentialCount: number;\n\toauthProviders: string[];\n}\n\n/** User with full details including related data */\nexport interface UserWithDetails {\n\tuser: User;\n\tcredentials: Credential[];\n\toauthAccounts: OAuthAccount[];\n\tlastLogin: Date | null;\n}\n\n// ============================================================================\n// Auth Adapter Interface\n// ============================================================================\n\nexport interface AuthAdapter {\n\t// Users\n\tgetUserById(id: string): Promise<User | null>;\n\tgetUserByEmail(email: string): Promise<User | null>;\n\tcreateUser(user: NewUser): Promise<User>;\n\tupdateUser(id: string, data: UpdateUser): Promise<void>;\n\tdeleteUser(id: string): Promise<void>;\n\tcountUsers(): Promise<number>;\n\n\t// User listing and details (for admin)\n\tgetUsers(options?: {\n\t\tsearch?: string;\n\t\trole?: number;\n\t\tcursor?: string;\n\t\tlimit?: number;\n\t}): Promise<{ items: UserListItem[]; nextCursor?: string }>;\n\tgetUserWithDetails(id: string): Promise<UserWithDetails | null>;\n\tcountAdmins(): Promise<number>;\n\n\t// Credentials\n\tgetCredentialById(id: string): Promise<Credential | null>;\n\tgetCredentialsByUserId(userId: string): Promise<Credential[]>;\n\tcreateCredential(credential: NewCredential): Promise<Credential>;\n\tupdateCredentialCounter(id: string, counter: number): Promise<void>;\n\tupdateCredentialName(id: string, name: string | null): Promise<void>;\n\tdeleteCredential(id: string): Promise<void>;\n\tcountCredentialsByUserId(userId: string): Promise<number>;\n\n\t// Auth Tokens\n\tcreateToken(token: NewAuthToken): Promise<void>;\n\tgetToken(hash: string, type: TokenType): Promise<AuthToken | null>;\n\tdeleteToken(hash: string): Promise<void>;\n\tdeleteExpiredTokens(): Promise<void>;\n\n\t// OAuth Accounts\n\tgetOAuthAccount(provider: string, providerAccountId: string): Promise<OAuthAccount | null>;\n\tgetOAuthAccountsByUserId(userId: string): Promise<OAuthAccount[]>;\n\tcreateOAuthAccount(account: NewOAuthAccount): Promise<OAuthAccount>;\n\tdeleteOAuthAccount(provider: string, providerAccountId: string): Promise<void>;\n\n\t// Allowed Domains\n\tgetAllowedDomain(domain: string): Promise<AllowedDomain | null>;\n\tgetAllowedDomains(): Promise<AllowedDomain[]>;\n\tcreateAllowedDomain(domain: string, defaultRole: RoleLevel): Promise<AllowedDomain>;\n\tupdateAllowedDomain(domain: string, enabled: boolean, defaultRole?: RoleLevel): Promise<void>;\n\tdeleteAllowedDomain(domain: string): Promise<void>;\n}\n\n// ============================================================================\n// Email Adapter Interface\n// ============================================================================\n\nexport interface EmailMessage {\n\tto: string;\n\tsubject: string;\n\ttext: string;\n\thtml?: string;\n}\n\nexport interface EmailAdapter {\n\tsend(message: EmailMessage): Promise<void>;\n}\n\n// ============================================================================\n// Auth Errors\n// ============================================================================\n\nexport class AuthError extends Error {\n\tconstructor(\n\t\tpublic code: AuthErrorCode,\n\t\tmessage?: string,\n\t) {\n\t\tsuper(message ?? code);\n\t\tthis.name = \"AuthError\";\n\t}\n}\n\nexport type AuthErrorCode =\n\t| \"invalid_credentials\"\n\t| \"invalid_token\"\n\t| \"token_expired\"\n\t| \"user_not_found\"\n\t| \"user_exists\"\n\t| \"credential_exists\"\n\t| \"max_credentials\"\n\t| \"email_not_verified\"\n\t| \"signup_not_allowed\"\n\t| \"domain_not_allowed\"\n\t| \"forbidden\"\n\t| \"unauthorized\"\n\t| \"rate_limited\"\n\t| \"invalid_request\"\n\t| \"internal_error\";\n"],"mappings":";;;;AAQA,MAAa,OAAO;CACnB,YAAY;CACZ,aAAa;CACb,QAAQ;CACR,QAAQ;CACR,OAAO;CACP;AAKD,SAAgB,cAAc,OAAqC;CAClE,MAAM,QAAQ,OAAO,QAAQ,KAAK,CAAC,MAAM,GAAG,OAAO,MAAM,MAAM;AAC/D,KAAI,CAAC,MAAO,QAAO;CACnB,MAAM,OAAO,MAAM;AACnB,KAAI,WAAW,KAAK,CAAE,QAAO;;AAI9B,SAAS,WAAW,OAAkC;AACrD,QAAO,SAAS;;AAGjB,MAAM,iBAAiB,IAAI,IAAuB,OAAO,OAAO,KAAK,CAAC,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;AAEzF,SAAgB,YAAY,OAA0B;CACrD,MAAM,QAAQ,eAAe,IAAI,MAAM;AACvC,KAAI,UAAU,OAAW,QAAO;AAChC,OAAM,IAAI,MAAM,uBAAuB,QAAQ;;AAGhD,MAAM,kBAA0D;CAC/D,cAAc;CACd,aAAa;CACb;AAED,SAAgB,aAAa,OAA2B;CACvD,MAAM,KAAK,gBAAgB;AAC3B,KAAI,OAAO,OAAW,QAAO;AAC7B,OAAM,IAAI,MAAM,wBAAwB,QAAQ;;AAGjD,MAAM,iBAAwD;CAC7D,YAAY;CACZ,cAAc;CACd,QAAQ;CACR,UAAU;CACV;AAED,SAAgB,YAAY,OAA0B;CACrD,MAAM,KAAK,eAAe;AAC1B,KAAI,OAAO,OAAW,QAAO;AAC7B,OAAM,IAAI,MAAM,uBAAuB,QAAQ;;AAGhD,SAAgB,YAAY,MAA2B;AACtD,QAAO,KAAK;;AAwQb,IAAa,YAAb,cAA+B,MAAM;CACpC,YACC,AAAO,MACP,SACC;AACD,QAAM,WAAW,KAAK;EAHf;AAIP,OAAK,OAAO"}