@awsmbiz/inbis-api-client 0.0.0-stage → 0.2.0

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.
@@ -0,0 +1,747 @@
1
+ import { Client, FetchOptions, FetchResponse } from "openapi-fetch";
2
+ import { AuthClient } from "better-auth/client";
3
+ import { AdminClientOptions, adminClient } from "better-auth/client/plugins";
4
+ import { MediaType, PathsWithMethod } from "openapi-typescript-helpers";
5
+ /** A permission declared in the app's code (`GET /api/admin/permissions`). */
6
+ interface AdminPermission {
7
+ /** Dotted name, e.g. `notes.read`. */
8
+ name: string;
9
+ description: string;
10
+ }
11
+ /** A role (`GET /api/admin/roles`). */
12
+ interface AdminRole {
13
+ id: string;
14
+ name: string;
15
+ description: string | null;
16
+ /** Declared in code: read-only (`409 SYSTEM_ROLE_IMMUTABLE`). */
17
+ system: boolean;
18
+ /** Permission names the role grants itself. */
19
+ permissions: string[];
20
+ /** IDs of the roles whose permissions this role also grants. */
21
+ inherits: string[];
22
+ /** Users assigned this role directly. */
23
+ userCount: number;
24
+ createdAt: Date;
25
+ updatedAt: Date;
26
+ }
27
+ /** A custom role's fields: all of them to create one, any of them to change one. */
28
+ interface AdminRoleInput {
29
+ /** 1–64 characters, unique among roles ignoring case. */
30
+ name: string;
31
+ /** Up to 500 characters; `null` or `""` for none. */
32
+ description?: string | null;
33
+ permissions: readonly string[];
34
+ inherits?: readonly string[];
35
+ }
36
+ /** A role a user holds directly (`GET /api/admin/users/:userId/roles`). */
37
+ interface AdminUserRole {
38
+ id: string;
39
+ name: string;
40
+ system: boolean;
41
+ assignedAt: Date;
42
+ /** The admin who assigned it, when known. */
43
+ assignedBy: string | null;
44
+ }
45
+ interface Init {
46
+ signal?: AbortSignal;
47
+ }
48
+ /** Role admin calls. Reads need the admin policy; changes also a recent sign-in (`403 SESSION_NOT_FRESH`). */
49
+ interface RoleAdminClient {
50
+ permissions: {
51
+ list(init?: Init): Promise<{
52
+ items: AdminPermission[];
53
+ }>;
54
+ };
55
+ roles: {
56
+ /** System roles first, then by name. */
57
+ list(init?: Init): Promise<{
58
+ items: AdminRole[];
59
+ }>;
60
+ /** `404 ROLE_NOT_FOUND`. */
61
+ get(roleId: string, init?: Init): Promise<AdminRole>;
62
+ /**
63
+ * Refusals: `422 VALIDATION_FAILED` (`details.issues[{ path, message }]`), `422 UNKNOWN_PERMISSION`,
64
+ * `422 UNKNOWN_ROLE`, `422 ROLE_INHERITANCE_CYCLE`, `409 ROLE_NAME_TAKEN`.
65
+ */
66
+ create(input: AdminRoleInput): Promise<AdminRole>;
67
+ /** As `create`, plus `409 SYSTEM_ROLE_IMMUTABLE` and `404 ROLE_NOT_FOUND`. */
68
+ update(roleId: string, changes: Partial<AdminRoleInput>): Promise<AdminRole>;
69
+ /** Its assignments go with it. `409 ROLE_INHERITED` while another role inherits it, `409 SYSTEM_ROLE_IMMUTABLE`. */
70
+ delete(roleId: string): Promise<void>;
71
+ };
72
+ /** A user's directly assigned roles. Assigning and removing are idempotent and return the user's roles. */
73
+ userRoles: {
74
+ list(userId: string, init?: Init): Promise<{
75
+ items: AdminUserRole[];
76
+ }>;
77
+ /** `404 ROLE_NOT_FOUND` / `404 USER_NOT_FOUND`. */
78
+ assign(userId: string, roleId: string): Promise<{
79
+ items: AdminUserRole[];
80
+ }>;
81
+ unassign(userId: string, roleId: string): Promise<{
82
+ items: AdminUserRole[];
83
+ }>;
84
+ };
85
+ }
86
+ /** The admin dashboard's counts (`GET /api/admin/auth-stats`). */
87
+ interface AuthAdminStats {
88
+ totalUsers: number;
89
+ /** Users active in the last 7 days (signed in, per the audit trail; or with a session used, without one). */
90
+ activeUsers7d: number;
91
+ /** Invitations neither accepted, revoked nor expired. */
92
+ pendingInvitations: number;
93
+ /** Failed sign-ins in the last 24 hours. */
94
+ failedSignIns24h: number;
95
+ generatedAt: Date;
96
+ }
97
+ /** One audit event (`GET /api/admin/audit-events`). */
98
+ interface AuditEvent {
99
+ id: string;
100
+ /** Dotted action name, e.g. `auth.sign_in.failed`. */
101
+ action: string;
102
+ actorId: string | null;
103
+ /** e.g. `user:<id>`. */
104
+ subjectId: string | null;
105
+ occurredAt: Date;
106
+ requestId: string | null;
107
+ metadata: Record<string, unknown> | null;
108
+ }
109
+ /** Audit timeline filters and paging. `from` is inclusive, `to` exclusive. */
110
+ interface AuditEventsQuery {
111
+ action?: string;
112
+ /** User ID of the actor. */
113
+ actor?: string;
114
+ /** e.g. `user:<id>`. */
115
+ subject?: string;
116
+ from?: Date;
117
+ to?: Date;
118
+ /** 1–200, default 50. */
119
+ limit?: number;
120
+ cursor?: string;
121
+ }
122
+ /** A user as the admin directory lists them (`GET /api/admin/users`). */
123
+ interface AdminUserSummary {
124
+ id: string;
125
+ name: string;
126
+ email: string;
127
+ /** `email` is a phone-only user's placeholder, not an address: never show it as one. */
128
+ emailIsPlaceholder: boolean;
129
+ emailVerified: boolean;
130
+ phoneNumber: string | null;
131
+ role: "admin" | "user";
132
+ /** Banned now (an expired ban reads `false`). */
133
+ banned: boolean;
134
+ banReason: string | null;
135
+ /** When the ban ends; `null` for a permanent ban or no ban. */
136
+ banExpires: Date | null;
137
+ twoFactorEnabled: boolean;
138
+ createdAt: Date;
139
+ }
140
+ /** A way a user can sign in. */
141
+ interface AdminUserSignInMethod {
142
+ kind: "password" | "phone" | "passkey" | "social";
143
+ /** `credential`, `phone-number`, `passkey`, or the OAuth provider's ID. */
144
+ providerId: string;
145
+ /** A passkey's name or the phone number, when there is one. */
146
+ label: string | null;
147
+ createdAt: Date | null;
148
+ }
149
+ /** One user in full (`GET /api/admin/users/:userId`). */
150
+ interface AdminUserDetail extends AdminUserSummary {
151
+ phoneNumberVerified: boolean;
152
+ signInMethods: AdminUserSignInMethod[];
153
+ updatedAt: Date;
154
+ }
155
+ /** The directory's search, filters (all apply at once), sort and offset paging. */
156
+ interface AdminUsersQuery {
157
+ /** Name, email or phone number contains this, ignoring case. */
158
+ search?: string;
159
+ role?: "admin" | "user";
160
+ banned?: boolean;
161
+ twoFactor?: boolean;
162
+ emailVerified?: boolean;
163
+ /** Default `createdAt` (newest first). */
164
+ sort?: "createdAt" | "name" | "email";
165
+ direction?: "asc" | "desc";
166
+ /** 1–100, default 25. */
167
+ limit?: number;
168
+ offset?: number;
169
+ }
170
+ interface AdminUsersPage {
171
+ users: AdminUserSummary[];
172
+ total: number;
173
+ limit: number;
174
+ offset: number;
175
+ }
176
+ /** The admin routes, including the role admin API (`mountRoleAdmin` from `@awsmbiz/inbis-access-control/hono`). */
177
+ interface AdminRoutesClient extends RoleAdminClient {
178
+ /** The dashboard counts. Administrators only. */
179
+ stats(init?: {
180
+ signal?: AbortSignal;
181
+ }): Promise<AuthAdminStats>;
182
+ auditEvents: {
183
+ /** Newest first. Pass the previous page's `nextCursor` as `cursor`, with the same filters. */
184
+ list(query?: AuditEventsQuery, init?: {
185
+ signal?: AbortSignal;
186
+ }): Promise<{
187
+ items: AuditEvent[];
188
+ nextCursor: string | null;
189
+ }>;
190
+ };
191
+ /** The user directory (`mountAuthUsers` from `@awsmbiz/inbis-auth/hono`). Administrators only. */
192
+ users: {
193
+ list(query?: AdminUsersQuery, init?: {
194
+ signal?: AbortSignal;
195
+ }): Promise<AdminUsersPage>;
196
+ /** `404 USER_NOT_FOUND` for an unknown ID. */
197
+ get(userId: string, init?: {
198
+ signal?: AbortSignal;
199
+ }): Promise<AdminUserDetail>;
200
+ /**
201
+ * Removes the user's authenticator and backup codes and signs them out
202
+ * everywhere (lost authenticator); audited. Needs a recent sign-in
203
+ * (`403 SESSION_NOT_FRESH`: wrap it in `withStepUp`); `400 CANNOT_RESET_OWN_TWO_FACTOR`
204
+ * for the caller's own account; `404 USER_NOT_FOUND`.
205
+ */
206
+ resetTwoFactor(userId: string): Promise<{
207
+ sessionsRevoked: number;
208
+ }>;
209
+ };
210
+ }
211
+ interface ApiClientOptions {
212
+ /** Origin of the API (e.g. `https://app.example.com`). Defaults to the page's own origin. */
213
+ baseUrl?: string;
214
+ /** Custom `fetch` (tests, SSR). */
215
+ fetch?: (request: Request) => Promise<Response>;
216
+ /** Headers sent with every call. */
217
+ headers?: Record<string, string>;
218
+ }
219
+ /**
220
+ * A typed client for an app's routes; `Paths` is the `paths` type
221
+ * `openapi-typescript` generates. Failed calls reject with an {@link ApiError}
222
+ * (so `data` is set whenever a call resolves).
223
+ */
224
+ type ApiClient<Paths extends object> = Client<Paths>;
225
+ /** Creates the typed client for the app's routes (see the README for generating `Paths`). */
226
+ export declare function createApiClient<Paths extends object>(options?: ApiClientOptions): ApiClient<Paths>;
227
+ /**
228
+ * One error type for every failed call: app routes (the platform envelope
229
+ * `{ error: { code, message, requestId, details? } }`) and auth routes
230
+ * (Better Auth's `{ code, message, details? }`).
231
+ */
232
+ /** Codes the platform returns that callers commonly branch on. Any other server code passes through as is. */
233
+ export declare const API_ERROR_CODES: {
234
+ /** No response: offline, DNS, CORS or the server is unreachable (`status` 0). */
235
+ readonly NETWORK_ERROR: "NETWORK_ERROR";
236
+ /** Sign in again with one of `details.allowedMethods` (see {@link ApiError.requirement}). */
237
+ readonly STEP_UP_REQUIRED: "STEP_UP_REQUIRED";
238
+ /** Complete two-factor authentication (or enrol an authenticator) to continue. */
239
+ readonly TWO_FACTOR_REQUIRED: "TWO_FACTOR_REQUIRED";
240
+ /** The action needs a recent sign-in. */
241
+ readonly SESSION_NOT_FRESH: "SESSION_NOT_FRESH";
242
+ /** The session has ended. */
243
+ readonly SESSION_EXPIRED: "SESSION_EXPIRED";
244
+ /** A settings change would leave no administrator able to use the admin area. */
245
+ readonly ADMIN_LOCKOUT: "ADMIN_LOCKOUT";
246
+ /** The runtime auth settings changed since they were loaded (a stale-version conflict). */
247
+ readonly SETTINGS_VERSION_CONFLICT: "SETTINGS_VERSION_CONFLICT";
248
+ readonly VALIDATION_FAILED: "VALIDATION_FAILED";
249
+ readonly RATE_LIMITED: "RATE_LIMITED";
250
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
251
+ readonly FORBIDDEN: "FORBIDDEN";
252
+ readonly NOT_FOUND: "NOT_FOUND";
253
+ readonly INTERNAL_ERROR: "INTERNAL_ERROR";
254
+ /** A failed response without a recognisable code. */
255
+ readonly REQUEST_FAILED: "REQUEST_FAILED";
256
+ };
257
+ /**
258
+ * What a route asks of the session before it can be used: complete 2FA, or
259
+ * sign in again with one of `allowedMethods`.
260
+ */
261
+ type AccessRequirement = {
262
+ kind: "two-factor";
263
+ } | {
264
+ kind: "step-up";
265
+ allowedMethods: string[];
266
+ };
267
+ declare const API_ERROR: unique symbol;
268
+ interface ApiErrorOptions {
269
+ status: number;
270
+ code: string;
271
+ message: string;
272
+ requestId?: string | null;
273
+ details?: unknown;
274
+ cause?: unknown;
275
+ }
276
+ /** A failed call. `code` is stable and machine-readable; `message` is safe to show. */
277
+ export declare class ApiError extends Error {
278
+ /** HTTP status; `0` when no response arrived (`NETWORK_ERROR`). */
279
+ readonly status: number;
280
+ readonly code: string;
281
+ /** The server's request ID (app routes), for support and logs. */
282
+ readonly requestId: string | null;
283
+ /** Extra caller-safe information from the server, e.g. `{ allowedMethods }` or validation issues. */
284
+ readonly details: unknown;
285
+ readonly [API_ERROR] = true;
286
+ constructor(options: ApiErrorOptions);
287
+ /** The server could not be reached. */
288
+ get isNetworkError(): boolean;
289
+ /**
290
+ * A stale-version conflict: someone else changed the resource since it was
291
+ * loaded (`409` with a `…VERSION_CONFLICT` code, e.g. `SETTINGS_VERSION_CONFLICT`).
292
+ * Reload and let the user reapply their change.
293
+ */
294
+ get isVersionConflict(): boolean;
295
+ /** What the session needs before retrying (`TWO_FACTOR_REQUIRED` / `STEP_UP_REQUIRED`), else `null`. */
296
+ get requirement(): AccessRequirement | null;
297
+ /** Reads a failed response's body (either error shape). Consumes the body. */
298
+ static fromResponse(response: Response): Promise<ApiError>;
299
+ /** Builds the error from a status and a parsed body (either error shape, or anything else). */
300
+ static fromBody(status: number, body: unknown): ApiError;
301
+ /** No response arrived. */
302
+ static network(cause?: unknown): ApiError;
303
+ }
304
+ /** True for any {@link ApiError}, including instances from another copy of this package. */
305
+ export declare function isApiError(value: unknown): value is ApiError;
306
+ type RegistrationMode = "open" | "invite-only" | "admin-only" | "closed";
307
+ type AuthMethodName = "password" | "phone-otp";
308
+ type BreachedPasswordCheck = "fail-open" | "off";
309
+ interface RateLimitRule {
310
+ /** Seconds. */
311
+ window: number;
312
+ max: number;
313
+ }
314
+ type RateLimitKey = "default" | "signIn" | "passwordReset" | "otp" | "twoFactor";
315
+ /** Resolved, secret-free settings (`effective` and `appConfig` of {@link AuthSettingsView}). Durations in seconds. */
316
+ interface AuthSettingsSnapshot {
317
+ registration: {
318
+ mode: RegistrationMode;
319
+ requireEmailVerification: boolean;
320
+ };
321
+ methods: {
322
+ emailPassword: boolean;
323
+ phoneOtp: boolean;
324
+ };
325
+ /** `null` when email + password is off in the app config. `maxLength` is read-only. */
326
+ password: {
327
+ minLength: number;
328
+ maxLength: number;
329
+ breachedCheck: BreachedPasswordCheck;
330
+ } | null;
331
+ policies: {
332
+ admin: {
333
+ allowedMethods: AuthMethodName[];
334
+ twoFactor: "required";
335
+ };
336
+ user: {
337
+ twoFactor: "optional" | "required";
338
+ };
339
+ };
340
+ sessions: {
341
+ admin: {
342
+ idle: number;
343
+ max: number;
344
+ freshAge: number;
345
+ };
346
+ user: {
347
+ expiresIn: number;
348
+ freshAge: number;
349
+ rememberMe: boolean;
350
+ };
351
+ };
352
+ rateLimit: Partial<Record<RateLimitKey, RateLimitRule>>;
353
+ /** `null` when phone OTP is off in the app config. */
354
+ phoneOtp: {
355
+ perNumberLimit: RateLimitRule;
356
+ perIpLimit: RateLimitRule;
357
+ dailySmsCap: number;
358
+ } | null;
359
+ }
360
+ /** The stored overrides: they can only narrow the app config. Absent means "as the app config says". */
361
+ interface RuntimeAuthSettings {
362
+ registration?: {
363
+ mode?: RegistrationMode;
364
+ requireEmailVerification?: boolean;
365
+ };
366
+ methods?: {
367
+ emailPassword?: boolean;
368
+ phoneOtp?: boolean;
369
+ };
370
+ password?: {
371
+ minLength?: number;
372
+ breachedCheck?: BreachedPasswordCheck;
373
+ };
374
+ policies?: {
375
+ admin?: {
376
+ allowedMethods?: AuthMethodName[];
377
+ };
378
+ user?: {
379
+ twoFactor?: "optional" | "required";
380
+ };
381
+ };
382
+ sessions?: {
383
+ admin?: {
384
+ idle?: number;
385
+ max?: number;
386
+ freshAge?: number;
387
+ };
388
+ user?: {
389
+ expiresIn?: number;
390
+ freshAge?: number;
391
+ rememberMe?: boolean;
392
+ };
393
+ };
394
+ rateLimit?: Partial<Record<RateLimitKey, RateLimitRule>>;
395
+ phoneOtp?: {
396
+ perNumberLimit?: RateLimitRule;
397
+ perIpLimit?: RateLimitRule;
398
+ dailySmsCap?: number;
399
+ };
400
+ }
401
+ /** A JSON merge patch of {@link RuntimeAuthSettings}: `null` removes an override (back to the app config). */
402
+ type AuthSettingsPatch = { [K in keyof RuntimeAuthSettings]?: { [F in keyof NonNullable<RuntimeAuthSettings[K]>]?: unknown; } | null; };
403
+ /** `GET /api/admin/auth-settings`. */
404
+ interface AuthSettingsView {
405
+ /** Send it back with a change; a stale one is refused with `409 SETTINGS_VERSION_CONFLICT`. */
406
+ version: number;
407
+ updatedAt: string | null;
408
+ updatedBy: string | null;
409
+ overrides: RuntimeAuthSettings;
410
+ /** What applies now. */
411
+ effective: AuthSettingsSnapshot;
412
+ /** The app config: the widest each setting can be. */
413
+ appConfig: AuthSettingsSnapshot;
414
+ }
415
+ /** One method or service in `GET /api/admin/auth-providers/status`. Never a secret. */
416
+ interface AuthProviderStatus {
417
+ id: string;
418
+ kind: "method" | "service";
419
+ /** On in the app config (for services: its secret or sender is present). */
420
+ configured: boolean;
421
+ /** On now, after the runtime settings. */
422
+ enabled: boolean;
423
+ }
424
+ interface AuthSettingsAdminClient {
425
+ get(): Promise<AuthSettingsView>;
426
+ /**
427
+ * Changes the overrides. Refusals: `409 SETTINGS_VERSION_CONFLICT` (`isVersionConflict`),
428
+ * `422 INVALID_SETTINGS` (`details.issues[{ path, code, message }]`), `422 ADMIN_LOCKOUT`
429
+ * (`details.paths` names the settings that cause it), `403 TWO_FACTOR_NOT_ENROLLED`,
430
+ * `403 SESSION_NOT_FRESH`.
431
+ */
432
+ update(input: {
433
+ version: number;
434
+ settings: AuthSettingsPatch;
435
+ }): Promise<AuthSettingsView>;
436
+ }
437
+ interface AuthProvidersAdminClient {
438
+ status(): Promise<{
439
+ items: AuthProviderStatus[];
440
+ }>;
441
+ }
442
+ interface AuthAdminClientOptions {
443
+ /** Origin of the API. Defaults to the page's own origin. */
444
+ baseURL?: string;
445
+ /** Must match the server's `app.basePath`. Default `/api/auth`. */
446
+ basePath?: string;
447
+ /** Where the app mounts the admin app routes (stats, audit events, auth settings, provider status). Default `/api/admin`. */
448
+ adminPath?: string;
449
+ /** Custom `fetch` (tests, SSR). */
450
+ fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
451
+ }
452
+ /** Better Auth's browser client with the admin plugin; methods resolve to data or reject with an {@link ApiError}. */
453
+ type BetterAuthAdminClient = AuthClient<{
454
+ plugins: [ReturnType<typeof adminClient<AdminClientOptions>>];
455
+ fetchOptions: {
456
+ throw: true;
457
+ };
458
+ }>;
459
+ type InvitationStatus = "pending" | "accepted" | "revoked" | "expired";
460
+ /** An invitation as the admin API returns it (never its token). Dates are revived by Better Auth's client. */
461
+ interface Invitation {
462
+ id: string;
463
+ kind: string;
464
+ /** Exactly one of `email` and `phoneNumber` is set. */
465
+ email: string | null;
466
+ phoneNumber: string | null;
467
+ role: "admin" | "user";
468
+ status: InvitationStatus;
469
+ expiresAt: Date;
470
+ createdAt: Date;
471
+ invitedBy: string | null;
472
+ acceptedAt: Date | null;
473
+ acceptedUserId: string | null;
474
+ revokedAt: Date | null;
475
+ }
476
+ /** `@awsmbiz/inbis-auth`'s invitation admin endpoints. Refusals reject with an {@link ApiError}. */
477
+ interface InvitationsAdminClient {
478
+ /**
479
+ * Invites by email or by phone (E.164), as `role` (default `user`). Errors include
480
+ * `INVALID_EMAIL`, `INVALID_PHONE_NUMBER`, `USER_ALREADY_EXISTS` and `INVITATION_ALREADY_PENDING`.
481
+ */
482
+ create(input: {
483
+ email: string;
484
+ role?: "admin" | "user";
485
+ } | {
486
+ phoneNumber: string;
487
+ role?: "admin" | "user";
488
+ }): Promise<{
489
+ invitation: Invitation;
490
+ }>;
491
+ /**
492
+ * Newest first. Pass the previous page's `nextCursor` as `cursor`, `status` for only
493
+ * invitations with that status (`INVALID_INVITATION_STATUS` for anything else) and
494
+ * `role` for only those inviting as that role (`INVALID_ROLE` for anything else).
495
+ */
496
+ list(input?: {
497
+ limit?: number;
498
+ cursor?: string;
499
+ status?: InvitationStatus;
500
+ role?: "admin" | "user";
501
+ }): Promise<{
502
+ items: Invitation[];
503
+ nextCursor: string | null;
504
+ }>;
505
+ /** Sends a fresh link; the expiry restarts. `INVITATION_NOT_PENDING` once accepted or revoked. */
506
+ resend(input: {
507
+ invitationId: string;
508
+ }): Promise<{
509
+ invitation: Invitation;
510
+ }>;
511
+ /** `INVITATION_NOT_PENDING` once accepted or revoked. */
512
+ revoke(input: {
513
+ invitationId: string;
514
+ }): Promise<{
515
+ invitation: Invitation;
516
+ }>;
517
+ }
518
+ /** Who a new user is: an email address, or a phone number (E.164; a phone-only user signs in with codes). */
519
+ type CreateUserInput = {
520
+ name: string;
521
+ role?: "admin" | "user";
522
+ /** Email users only. Without one, the user sets a password with "Forgot password". */
523
+ password?: string;
524
+ } & ({
525
+ email: string;
526
+ phoneNumber?: never;
527
+ } | {
528
+ phoneNumber: string;
529
+ email?: never;
530
+ });
531
+ /** A created user, as Better Auth's admin plugin returns it (dates revived). */
532
+ interface CreatedUser {
533
+ id: string;
534
+ name: string;
535
+ email: string;
536
+ role?: string | null;
537
+ createdAt: Date;
538
+ }
539
+ /**
540
+ * Admin user actions that `@awsmbiz/inbis-auth` adds to Better Auth's admin plugin.
541
+ * The rest (set role, ban, unban, revoke every session, remove) are on
542
+ * `admin`. Refusals reject with an {@link ApiError}.
543
+ */
544
+ interface UserActionsAdminClient {
545
+ /**
546
+ * Creates a user by email or by phone number. Errors include
547
+ * `USER_ALREADY_EXISTS`, `INVALID_PHONE_NUMBER`, `PHONE_COUNTRY_NOT_ALLOWED`
548
+ * and `PHONE_SIGN_IN_UNAVAILABLE`.
549
+ */
550
+ create(input: CreateUserInput): Promise<{
551
+ user: CreatedUser;
552
+ }>;
553
+ /**
554
+ * Signs a user out of one session, by the session's ID (the listing never
555
+ * carries session tokens). `404 SESSION_NOT_FOUND` once it has ended.
556
+ */
557
+ revokeSession(input: {
558
+ userId: string;
559
+ sessionId: string;
560
+ }): Promise<{
561
+ success: boolean;
562
+ }>;
563
+ }
564
+ /**
565
+ * Auth admin calls: Better Auth's admin plugin, `@awsmbiz/inbis-auth`'s invitation
566
+ * endpoints, and the admin app routes (`stats`, `auditEvents`).
567
+ */
568
+ interface AuthAdminClient extends AdminRoutesClient {
569
+ /** Better Auth's admin plugin (`listUsers`, `createUser`, `setRole`, `banUser`, `unbanUser`, …). */
570
+ admin: BetterAuthAdminClient["admin"];
571
+ invitations: InvitationsAdminClient;
572
+ /** User actions beyond Better Auth's: create by phone number, revoke a session by ID. */
573
+ userActions: UserActionsAdminClient;
574
+ /** Runtime auth settings (`GET`/`PATCH /api/admin/auth-settings`). */
575
+ settings: AuthSettingsAdminClient;
576
+ /** Method and provider status (`GET /api/admin/auth-providers/status`). */
577
+ providers: AuthProvidersAdminClient;
578
+ }
579
+ /** Creates the client for auth admin endpoints. */
580
+ export declare function createAuthAdminClient(options?: AuthAdminClientOptions): AuthAdminClient;
581
+ /** Anything that can invalidate queries by key prefix (TanStack's `QueryClient`). */
582
+ interface QueryInvalidator {
583
+ invalidateQueries(filters: {
584
+ queryKey: readonly unknown[];
585
+ }): Promise<unknown>;
586
+ }
587
+ /** Invalidates every query whose key starts with one of `keys`. */
588
+ export declare function invalidateQueries(queryClient: QueryInvalidator, ...keys: (readonly unknown[])[]): Promise<void>;
589
+ /** The key of an app-route query: `["api", path]`, or `["api", path, params]`. */
590
+ export declare function apiQueryKey<Path extends string>(path: Path): readonly ["api", Path];
591
+ export declare function apiQueryKey<Path extends string, Params>(path: Path, params: Params): readonly ["api", Path, Params];
592
+ /** Invalidates every query of the given app-route paths (any params), or of all app routes when none is given. */
593
+ export declare function invalidateApi(queryClient: QueryInvalidator, ...paths: string[]): Promise<void>;
594
+ type GetOperation<P, Path> = Path extends keyof P ? P[Path] extends {
595
+ get: infer Operation extends Record<string | number, unknown>;
596
+ } ? Operation : never : never;
597
+ type GetInit<P, Path> = FetchOptions<GetOperation<P, Path>>;
598
+ type GetData<P, Path, Init> = NonNullable<FetchResponse<GetOperation<P, Path>, Init, MediaType>["data"]>;
599
+ type RequiredKeysOf<T> = { [K in keyof T]-?: object extends Pick<T, K> ? never : K; }[keyof T];
600
+ type InitParam<Init> = RequiredKeysOf<Init> extends never ? [Init?] : [Init];
601
+ interface ApiQueryOptions<Key extends readonly unknown[], Data> {
602
+ queryKey: Key;
603
+ queryFn: (context: {
604
+ signal: AbortSignal;
605
+ }) => Promise<Data>;
606
+ }
607
+ /**
608
+ * Query options for a `GET` app route: keyed by path and `params` (see
609
+ * {@link apiQueryKey}), failing with an `ApiError`:
610
+ * `useQuery(apiQueryOptions(api, "/v1/notes/{id}", { params: { path: { id } } }))`.
611
+ */
612
+ export declare function apiQueryOptions<P extends object, Path extends PathsWithMethod<P, "get"> & string, Init extends GetInit<P, Path>>(client: ApiClient<P>, path: Path, ...[init]: InitParam<Init>): ApiQueryOptions<readonly ["api", Path] | readonly ["api", Path, unknown], GetData<P, Path, Init>>;
613
+ type Admin = AuthAdminClient["admin"];
614
+ /** Better Auth's `listUsers` query (search, filter, sort, `limit`/`offset`). */
615
+ type ListUsersQuery = NonNullable<Parameters<Admin["listUsers"]>[0]>["query"];
616
+ interface ListInvitationsQuery {
617
+ limit?: number;
618
+ cursor?: string;
619
+ status?: InvitationStatus;
620
+ role?: "admin" | "user";
621
+ }
622
+ /**
623
+ * Query keys for auth admin data. Invalidate `users()` after any change to a
624
+ * user (it covers lists, details and sessions), `invitations()` after any
625
+ * invitation change, `stats()` after anything the dashboard counts, or `all`
626
+ * for everything.
627
+ */
628
+ export declare const authAdminKeys: {
629
+ all: readonly ["auth-admin"];
630
+ users: () => readonly ["auth-admin", "users"];
631
+ userList: (query: ListUsersQuery) => readonly ["auth-admin", "users", "list", {
632
+ searchValue?: string | undefined;
633
+ searchField?: "name" | "email" | undefined;
634
+ searchOperator?: "contains" | "starts_with" | "ends_with" | undefined;
635
+ limit?: string | number | undefined;
636
+ offset?: string | number | undefined;
637
+ sortBy?: string | undefined;
638
+ sortDirection?: "asc" | "desc" | undefined;
639
+ filterField?: string | undefined;
640
+ filterValue?: string | number | boolean | string[] | number[] | undefined;
641
+ filterOperator?: "in" | "contains" | "starts_with" | "ends_with" | "lte" | "eq" | "ne" | "lt" | "gt" | "gte" | "not_in" | undefined;
642
+ }];
643
+ user: (userId: string) => readonly ["auth-admin", "users", "detail", string];
644
+ userSessions: (userId: string) => readonly ["auth-admin", "users", "detail", string, "sessions"];
645
+ /** The admin directory (`users.list`: combined filters). */
646
+ userDirectory: (query: AdminUsersQuery) => readonly ["auth-admin", "users", "directory", AdminUsersQuery];
647
+ /** One user's profile, sign-in methods and 2FA status (`users.get`). */
648
+ userProfile: (userId: string) => readonly ["auth-admin", "users", "detail", string, "profile"];
649
+ invitations: () => readonly ["auth-admin", "invitations"];
650
+ invitationList: (query: ListInvitationsQuery) => readonly ["auth-admin", "invitations", "list", ListInvitationsQuery];
651
+ settings: () => readonly ["auth-admin", "settings"];
652
+ providerStatus: () => readonly ["auth-admin", "providers", "status"];
653
+ stats: () => readonly ["auth-admin", "stats"];
654
+ auditEvents: () => readonly ["auth-admin", "audit-events"];
655
+ auditEventList: (query: AuditEventsQuery) => readonly ["auth-admin", "audit-events", "list", AuditEventsQuery];
656
+ /** The declared permission catalogue (`permissions.list`). */
657
+ permissions: () => readonly ["auth-admin", "permissions"];
658
+ /** Every role query: invalidate after a role change or an assignment (it changes `userCount`). */
659
+ roles: () => readonly ["auth-admin", "roles"];
660
+ roleList: () => readonly ["auth-admin", "roles", "list"];
661
+ role: (roleId: string) => readonly ["auth-admin", "roles", "detail", string];
662
+ /** A user's assigned roles (`userRoles.list`); covered by `users()`. */
663
+ userRoles: (userId: string) => readonly ["auth-admin", "users", "detail", string, "roles"];
664
+ };
665
+ /** Query options for auth admin data, keyed by {@link authAdminKeys}. */
666
+ export declare function authAdminQueries(auth: AuthAdminClient): {
667
+ userList: (query: ListUsersQuery) => {
668
+ queryKey: readonly ["auth-admin", "users", "list", {
669
+ searchValue?: string | undefined;
670
+ searchField?: "name" | "email" | undefined;
671
+ searchOperator?: "contains" | "starts_with" | "ends_with" | undefined;
672
+ limit?: string | number | undefined;
673
+ offset?: string | number | undefined;
674
+ sortBy?: string | undefined;
675
+ sortDirection?: "asc" | "desc" | undefined;
676
+ filterField?: string | undefined;
677
+ filterValue?: string | number | boolean | string[] | number[] | undefined;
678
+ filterOperator?: "in" | "contains" | "starts_with" | "ends_with" | "lte" | "eq" | "ne" | "lt" | "gt" | "gte" | "not_in" | undefined;
679
+ }];
680
+ queryFn: ({ signal }: {
681
+ signal: AbortSignal;
682
+ }) => Promise<{
683
+ users: import("better-auth/plugins").UserWithRole[];
684
+ total: number;
685
+ }>;
686
+ };
687
+ user: (userId: string) => {
688
+ queryKey: readonly ["auth-admin", "users", "detail", string];
689
+ queryFn: ({ signal }: {
690
+ signal: AbortSignal;
691
+ }) => Promise<import("better-auth/plugins").UserWithRole>;
692
+ };
693
+ userSessions: (userId: string) => {
694
+ queryKey: readonly ["auth-admin", "users", "detail", string, "sessions"];
695
+ queryFn: ({ signal }: {
696
+ signal: AbortSignal;
697
+ }) => Promise<{
698
+ sessions: import("better-auth/plugins").SessionWithImpersonatedBy[];
699
+ }>;
700
+ };
701
+ userDirectory: (query: AdminUsersQuery) => {
702
+ queryKey: readonly ["auth-admin", "users", "directory", AdminUsersQuery];
703
+ queryFn: ({ signal }: {
704
+ signal: AbortSignal;
705
+ }) => Promise<AdminUsersPage>;
706
+ };
707
+ userProfile: (userId: string) => {
708
+ queryKey: readonly ["auth-admin", "users", "detail", string, "profile"];
709
+ queryFn: ({ signal }: {
710
+ signal: AbortSignal;
711
+ }) => Promise<AdminUserDetail>;
712
+ };
713
+ invitationList: (query: ListInvitationsQuery) => {
714
+ queryKey: readonly ["auth-admin", "invitations", "list", ListInvitationsQuery];
715
+ queryFn: () => Promise<{
716
+ items: Invitation[];
717
+ nextCursor: string | null;
718
+ }>;
719
+ };
720
+ settings: () => {
721
+ queryKey: readonly ["auth-admin", "settings"];
722
+ queryFn: () => Promise<AuthSettingsView>;
723
+ };
724
+ providerStatus: () => {
725
+ queryKey: readonly ["auth-admin", "providers", "status"];
726
+ queryFn: () => Promise<{
727
+ items: AuthProviderStatus[];
728
+ }>;
729
+ };
730
+ stats: () => {
731
+ queryKey: readonly ["auth-admin", "stats"];
732
+ queryFn: ({ signal }: {
733
+ signal: AbortSignal;
734
+ }) => Promise<AuthAdminStats>;
735
+ };
736
+ auditEventList: (query: AuditEventsQuery) => {
737
+ queryKey: readonly ["auth-admin", "audit-events", "list", AuditEventsQuery];
738
+ queryFn: ({ signal }: {
739
+ signal: AbortSignal;
740
+ }) => Promise<{
741
+ items: AuditEvent[];
742
+ nextCursor: string | null;
743
+ }>;
744
+ };
745
+ };
746
+ export type { AccessRequirement, AdminPermission, AdminRole, AdminRoleInput, AdminRoutesClient, AdminUserDetail, AdminUserRole, AdminUserSignInMethod, AdminUserSummary, AdminUsersPage, AdminUsersQuery, ApiClient, ApiClientOptions, ApiErrorOptions, ApiQueryOptions, AuditEvent, AuditEventsQuery, AuthAdminClient, AuthAdminClientOptions, AuthAdminStats, AuthMethodName, AuthProviderStatus, AuthProvidersAdminClient, AuthSettingsAdminClient, AuthSettingsPatch, AuthSettingsSnapshot, AuthSettingsView, BetterAuthAdminClient, BreachedPasswordCheck, CreateUserInput, CreatedUser, Invitation, InvitationStatus, InvitationsAdminClient, ListInvitationsQuery, ListUsersQuery, QueryInvalidator, RateLimitKey, RateLimitRule, RegistrationMode, RoleAdminClient, RuntimeAuthSettings, UserActionsAdminClient };
747
+ //# sourceMappingURL=index.d.ts.map