ngx-better-auth 0.5.2 → 0.7.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.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  ![angular](https://img.shields.io/badge/angular-20+-dd0031?logo=angular&logoColor=white)
9
9
  ![better-auth](https://img.shields.io/badge/better--auth-1.3.7+-blueviolet)
10
10
 
11
- An **Angular 20+ integration for [Better Auth](https://github.com/better-auth/better-auth)**.
11
+ An **Angular 20+ wrapper for [Better Auth](https://github.com/better-auth/better-auth)**.
12
12
  Provides reactive session handling with **signals**, clean **DI provider setup** with **observables**, and modern **guards**.
13
13
 
14
14
  ---
@@ -49,7 +49,9 @@ export const appConfig: ApplicationConfig = {
49
49
 
50
50
  ## 🧩 Different services
51
51
 
52
- You can inject different services depending on your needs:
52
+ You can inject different services depending on your needs.
53
+ **AuthService** provides the core Better Auth client methods (login, logout, register, e.g.).
54
+ The full list of methods is available at the end of this README.
53
55
 
54
56
  ### Global services
55
57
  - `AuthService`
@@ -58,6 +60,7 @@ You can inject different services depending on your needs:
58
60
 
59
61
  ### Plugin services
60
62
  Authentication:
63
+ - `UsernameService`
61
64
  - `TwoFactorService`
62
65
  - `PasskeyService`
63
66
  - `GenericOauthService`
@@ -108,7 +111,7 @@ This library ships with guards to quickly set up route protection.
108
111
  ### Usage in routes
109
112
  ```ts
110
113
  import { Routes } from '@angular/router'
111
- import { canActivate, redirectLoggedInTo, redirectUnauthorizedTo, hasRole } from 'ngx-better-auth/guards'
114
+ import { canActivate, redirectLoggedInTo, redirectUnauthorizedTo, hasRole } from 'ngx-better-auth'
112
115
 
113
116
  export const routes: Routes = [
114
117
  {
@@ -127,4 +130,9 @@ export const routes: Routes = [
127
130
  ...canActivate(redirectLoggedInTo(['/']))
128
131
  }
129
132
  ]
130
- ```
133
+ ```
134
+
135
+ ## 📋 Full list of AuthService methods
136
+
137
+ ### AuthService
138
+
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, Injectable, signal, computed, InjectionToken, makeEnvironmentProviders } from '@angular/core';
3
- import { Observable, filter, map, shareReplay, defer, switchMap, tap } from 'rxjs';
3
+ import { Observable, filter, map, shareReplay, defer, switchMap } from 'rxjs';
4
4
  import { createAuthClient } from 'better-auth/client';
5
5
  import { Router } from '@angular/router';
6
6
 
@@ -9,6 +9,12 @@ class MainService {
9
9
  authClient = createAuthClient({
10
10
  ...this.config,
11
11
  });
12
+ mapData(data) {
13
+ if (data.error) {
14
+ throw data.error;
15
+ }
16
+ return data.data;
17
+ }
12
18
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: MainService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
13
19
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: MainService, providedIn: 'root' });
14
20
  }
@@ -19,11 +25,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImpor
19
25
  }]
20
26
  }] });
21
27
 
22
- function isEmail(email) {
23
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
24
- return emailRegex.test(email);
25
- }
26
-
27
28
  class AuthService {
28
29
  mainService = inject(MainService);
29
30
  client = this.mainService.authClient;
@@ -77,24 +78,9 @@ class AuthService {
77
78
  this.session.set(session.data);
78
79
  });
79
80
  }
80
- /**
81
- * pass either email or username to sign in. Needs username plugin enabled to use username.
82
- * @param data : { email?: string; username?: string; password: string; rememberMe?: boolean }
83
- */
84
- signIn(data) {
85
- if (isEmail(data.login)) {
86
- return this.signInEmail({ email: data.login, password: data.password, rememberMe: data.rememberMe });
87
- }
88
- else {
89
- return this.signInUsername({ username: data.login, password: data.password, rememberMe: data.rememberMe });
90
- }
91
- }
92
81
  signInEmail(data) {
93
82
  return defer(() => this.client.signIn.email(data)).pipe(switchMap(() => this.sessionState$.pipe(filter((s) => s !== null))));
94
83
  }
95
- signInUsername(data) {
96
- return defer(() => this.client.signIn.username(data)).pipe(switchMap(() => this.sessionState$.pipe(filter((s) => s !== null))));
97
- }
98
84
  /**
99
85
  * Sign up a new user using email and password.
100
86
  *
@@ -111,28 +97,25 @@ class AuthService {
111
97
  return defer(() => this.client.signOut()).pipe(switchMap(() => this.sessionState$.pipe(filter((s) => s === null))));
112
98
  }
113
99
  sendVerificationEmail(data) {
114
- return defer(() => this.client.sendVerificationEmail(data));
100
+ return defer(() => this.client.sendVerificationEmail(data)).pipe(map((data) => this.mainService.mapData(data)));
115
101
  }
116
102
  requestPasswordReset(data) {
117
- return defer(() => this.client.requestPasswordReset(data));
103
+ return defer(() => this.client.requestPasswordReset(data)).pipe(map((data) => this.mainService.mapData(data)));
118
104
  }
119
105
  resetPassword(data) {
120
- return defer(() => this.client.resetPassword(data));
106
+ return defer(() => this.client.resetPassword(data)).pipe(map((data) => this.mainService.mapData(data)));
121
107
  }
122
108
  changePassword(data) {
123
- return defer(() => this.client.changePassword(data));
109
+ return defer(() => this.client.changePassword(data)).pipe(map((data) => this.mainService.mapData(data)));
124
110
  }
125
111
  changeEmail(data) {
126
- return defer(() => this.client.changeEmail(data));
112
+ return defer(() => this.client.changeEmail(data)).pipe(map((data) => this.mainService.mapData(data)));
127
113
  }
128
114
  updateUser(data) {
129
- return defer(() => this.client.updateUser(data));
130
- }
131
- isUsernameAvailable(data) {
132
- return defer(() => this.client.isUsernameAvailable(data));
115
+ return defer(() => this.client.updateUser(data)).pipe(map((data) => this.mainService.mapData(data)));
133
116
  }
134
117
  deleteUser(data) {
135
- return defer(() => this.client.deleteUser(data)).pipe(tap(() => this.sessionState$.pipe(filter((s) => s === null))));
118
+ return defer(() => this.client.deleteUser(data)).pipe(switchMap(() => this.sessionState$.pipe(filter((s) => s === null))));
136
119
  }
137
120
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
138
121
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: AuthService, providedIn: 'root' });
@@ -148,16 +131,16 @@ class SessionService {
148
131
  mainService = inject(MainService);
149
132
  client = this.mainService.authClient;
150
133
  listSessions() {
151
- return defer(() => this.client.listSessions());
134
+ return defer(() => this.client.listSessions()).pipe(map((data) => this.mainService.mapData(data)));
152
135
  }
153
- revokeSession(sessionToken) {
154
- return defer(() => this.client.revokeSession({ token: sessionToken }));
136
+ revokeSession(data) {
137
+ return defer(() => this.client.revokeSession(data)).pipe(map((data) => this.mainService.mapData(data)));
155
138
  }
156
139
  revokeOtherSessions() {
157
- return defer(() => this.client.revokeOtherSessions());
140
+ return defer(() => this.client.revokeOtherSessions()).pipe(map((data) => this.mainService.mapData(data)));
158
141
  }
159
142
  revokeAllSessions() {
160
- return defer(() => this.client.revokeSessions());
143
+ return defer(() => this.client.revokeSessions()).pipe(map((data) => this.mainService.mapData(data)));
161
144
  }
162
145
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: SessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
163
146
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: SessionService, providedIn: 'root' });
@@ -171,13 +154,13 @@ class AccountService {
171
154
  mainService = inject(MainService);
172
155
  client = this.mainService.authClient;
173
156
  listAccounts() {
174
- return defer(() => this.client.listAccounts());
157
+ return defer(() => this.client.listAccounts()).pipe(map((data) => this.mainService.mapData(data)));
175
158
  }
176
159
  linkSocial(data) {
177
- return defer(() => this.client.linkSocial(data));
160
+ return defer(() => this.client.linkSocial(data)).pipe(map((data) => this.mainService.mapData(data)));
178
161
  }
179
162
  unlinkAccount(data) {
180
- return defer(() => this.client.unlinkAccount(data));
163
+ return defer(() => this.client.unlinkAccount(data)).pipe(map((data) => this.mainService.mapData(data)));
181
164
  }
182
165
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: AccountService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
183
166
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: AccountService, providedIn: 'root' });
@@ -205,28 +188,28 @@ class TwoFactorService {
205
188
  this.twoFactor = client.twoFactor;
206
189
  }
207
190
  enable(data) {
208
- return defer(() => this.twoFactor.enable(data));
191
+ return defer(() => this.twoFactor.enable(data)).pipe(map((data) => this.mainService.mapData(data)));
209
192
  }
210
193
  disable(data) {
211
- return defer(() => this.twoFactor.disable(data));
194
+ return defer(() => this.twoFactor.disable(data)).pipe(map((data) => this.mainService.mapData(data)));
212
195
  }
213
196
  getTotpUri(data) {
214
- return defer(() => this.twoFactor.getTotpUri(data));
197
+ return defer(() => this.twoFactor.getTotpUri(data)).pipe(map((data) => this.mainService.mapData(data)));
215
198
  }
216
199
  verifyTotp(data) {
217
- return defer(() => this.twoFactor.verifyTotp(data));
200
+ return defer(() => this.twoFactor.verifyTotp(data)).pipe(map((data) => this.mainService.mapData(data)));
218
201
  }
219
- sendOtp(data) {
220
- return defer(() => this.twoFactor.sendOtp(data));
202
+ sendOtp() {
203
+ return defer(() => this.twoFactor.sendOtp()).pipe(map((data) => this.mainService.mapData(data)));
221
204
  }
222
205
  verifyOtp(data) {
223
- return defer(() => this.twoFactor.verifyOtp(data));
206
+ return defer(() => this.twoFactor.verifyOtp(data)).pipe(map((data) => this.mainService.mapData(data)));
224
207
  }
225
208
  generateBackupCodes(data) {
226
- return defer(() => this.twoFactor.generateBackupCodes(data));
209
+ return defer(() => this.twoFactor.generateBackupCodes(data)).pipe(map((data) => this.mainService.mapData(data)));
227
210
  }
228
211
  verifyBackupCode(data) {
229
- return defer(() => this.twoFactor.verifyBackupCode(data));
212
+ return defer(() => this.twoFactor.verifyBackupCode(data)).pipe(map((data) => this.mainService.mapData(data)));
230
213
  }
231
214
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: TwoFactorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
232
215
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: TwoFactorService, providedIn: 'root' });
@@ -245,16 +228,19 @@ class PasskeyService {
245
228
  this.passkey = client.passkey;
246
229
  }
247
230
  addPasskey(data) {
248
- return defer(() => this.passkey.addPasskey(data));
231
+ return defer(() => this.passkey.addPasskey(data)).pipe(map((data) => this.mainService.mapData(data)));
232
+ }
233
+ signIn(data) {
234
+ return defer(() => this.mainService.authClient.signIn.passkey(data));
249
235
  }
250
236
  listUserPasskeys() {
251
- return defer(() => this.passkey.listUserPasskeys());
237
+ return defer(() => this.passkey.listUserPasskeys()).pipe(map((data) => this.mainService.mapData(data)));
252
238
  }
253
239
  deletePasskey(data) {
254
- return defer(() => this.passkey.deletePasskey(data));
240
+ return defer(() => this.passkey.deletePasskey(data)).pipe(map((data) => this.mainService.mapData(data)));
255
241
  }
256
242
  updatePasskey(data) {
257
- return defer(() => this.passkey.updatePasskey(data));
243
+ return defer(() => this.passkey.updatePasskey(data)).pipe(map((data) => this.mainService.mapData(data)));
258
244
  }
259
245
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: PasskeyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
260
246
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: PasskeyService, providedIn: 'root' });
@@ -369,40 +355,49 @@ class AdminService {
369
355
  this.admin = client.admin;
370
356
  }
371
357
  setRole(data) {
372
- return defer(() => this.admin.setRole(data));
358
+ return defer(() => this.admin.setRole(data)).pipe(map((data) => this.mainService.mapData(data)));
373
359
  }
374
- setUserPassword(data) {
375
- return defer(() => this.admin.setUserPassword(data));
360
+ createUser(data) {
361
+ return defer(() => this.admin.createUser(data)).pipe(map((data) => this.mainService.mapData(data)));
376
362
  }
377
- banUser(data) {
378
- return defer(() => this.admin.banUser(data));
363
+ updateUser(data) {
364
+ return defer(() => this.admin.updateUser(data)).pipe(map((data) => this.mainService.mapData(data)));
379
365
  }
380
- unbanUser(data) {
381
- return defer(() => this.admin.unbanUser(data));
366
+ listUsers(data) {
367
+ return defer(() => this.admin.listUsers(data)).pipe(map((data) => this.mainService.mapData(data)));
382
368
  }
383
369
  listUserSessions(data) {
384
- return defer(() => this.admin.listUserSessions(data));
370
+ return defer(() => this.admin.listUserSessions(data)).pipe(map((data) => this.mainService.mapData(data)));
385
371
  }
386
- revokeUserSession(data) {
387
- return defer(() => this.admin.revokeUserSession(data));
372
+ unbanUser(data) {
373
+ return defer(() => this.admin.unbanUser(data)).pipe(map((data) => this.mainService.mapData(data)));
388
374
  }
389
- revokeUserSessions(data) {
390
- return defer(() => this.admin.revokeUserSessions(data));
375
+ banUser(data) {
376
+ return defer(() => this.admin.banUser(data)).pipe(map((data) => this.mainService.mapData(data)));
391
377
  }
392
378
  impersonateUser(data) {
393
- return defer(() => this.admin.impersonateUser(data));
379
+ return defer(() => this.admin.impersonateUser(data)).pipe(map((data) => this.mainService.mapData(data)));
394
380
  }
395
381
  stopImpersonating() {
396
382
  return defer(() => this.admin.stopImpersonating());
397
383
  }
384
+ revokeUserSession(data) {
385
+ return defer(() => this.admin.revokeUserSession(data)).pipe(map((data) => this.mainService.mapData(data)));
386
+ }
387
+ revokeUserSessions(data) {
388
+ return defer(() => this.admin.revokeUserSessions(data)).pipe(map((data) => this.mainService.mapData(data)));
389
+ }
398
390
  removeUser(data) {
399
- return defer(() => this.admin.removeUser(data));
391
+ return defer(() => this.admin.removeUser(data)).pipe(map((data) => this.mainService.mapData(data)));
392
+ }
393
+ setUserPassword(data) {
394
+ return defer(() => this.admin.setUserPassword(data)).pipe(map((data) => this.mainService.mapData(data)));
400
395
  }
401
396
  hasPermission(data) {
402
397
  return defer(() => this.admin.hasPermission(data));
403
398
  }
404
399
  checkRolePermission(data) {
405
- return this.admin.checkRolePermission(data);
400
+ return defer(() => this.admin.checkRolePermission(data));
406
401
  }
407
402
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: AdminService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
408
403
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: AdminService, providedIn: 'root' });
@@ -420,62 +415,62 @@ class OrganizationService {
420
415
  validatePlugin(client, 'organization');
421
416
  this.organization = client.organization;
422
417
  }
423
- createOrganization(data) {
424
- return defer(() => this.organization.create(data));
418
+ create(data) {
419
+ return defer(() => this.organization.create(data)).pipe(map((data) => this.mainService.mapData(data)));
425
420
  }
426
421
  checkSlug(data) {
427
422
  return defer(() => this.organization.checkSlug(data));
428
423
  }
429
424
  list() {
430
- return defer(() => this.organization.list());
425
+ return defer(() => this.organization.list()).pipe(map((data) => this.mainService.mapData(data)));
431
426
  }
432
427
  setActive(data) {
433
- return defer(() => this.organization.setActive(data));
428
+ return defer(() => this.organization.setActive(data)).pipe(map((data) => this.mainService.mapData(data)));
434
429
  }
435
430
  getFullOrganization(data) {
436
- return defer(() => this.organization.getFullOrganization(data));
431
+ return defer(() => this.organization.getFullOrganization(data)).pipe(map((data) => this.mainService.mapData(data)));
437
432
  }
438
433
  update(data) {
439
- return defer(() => this.organization.update(data));
434
+ return defer(() => this.organization.update(data)).pipe(map((data) => this.mainService.mapData(data)));
440
435
  }
441
436
  delete(data) {
442
- return defer(() => this.organization.delete(data));
437
+ return defer(() => this.organization.delete(data)).pipe(map((data) => this.mainService.mapData(data)));
443
438
  }
444
439
  inviteMember(data) {
445
- return defer(() => this.organization.inviteMember(data));
440
+ return defer(() => this.organization.inviteMember(data)).pipe(map((data) => this.mainService.mapData(data)));
446
441
  }
447
442
  acceptInvitation(data) {
448
- return defer(() => this.organization.acceptInvitation(data));
443
+ return defer(() => this.organization.acceptInvitation(data)).pipe(map((data) => this.mainService.mapData(data)));
449
444
  }
450
445
  cancelInvitation(data) {
451
- return defer(() => this.organization.cancelInvitation(data));
446
+ return defer(() => this.organization.cancelInvitation(data)).pipe(map((data) => this.mainService.mapData(data)));
452
447
  }
453
448
  rejectInvitation(data) {
454
- return defer(() => this.organization.rejectInvitation(data));
449
+ return defer(() => this.organization.rejectInvitation(data)).pipe(map((data) => this.mainService.mapData(data)));
455
450
  }
456
451
  getInvitation(data) {
457
- return defer(() => this.organization.getInvitation(data));
452
+ return defer(() => this.organization.getInvitation(data)).pipe(map((data) => this.mainService.mapData(data)));
458
453
  }
459
454
  listInvitations(data) {
460
- return defer(() => this.organization.listInvitations(data));
455
+ return defer(() => this.organization.listInvitations(data)).pipe(map((data) => this.mainService.mapData(data)));
461
456
  }
462
457
  listUserInvitations() {
463
- return defer(() => this.organization.listUserInvitations());
458
+ return defer(() => this.organization.listUserInvitations()).pipe(map((data) => this.mainService.mapData(data)));
464
459
  }
465
460
  listMembers(data = {}) {
466
461
  return defer(() => this.organization.listMembers(data));
467
462
  }
468
463
  removeMember(data) {
469
- return defer(() => this.organization.removeMember(data));
464
+ return defer(() => this.organization.removeMember(data)).pipe(map((data) => this.mainService.mapData(data)));
470
465
  }
471
466
  updateMemberRoles(data) {
472
467
  return defer(() => this.organization.updateMemberRoles(data));
473
468
  }
474
469
  getActiveMember() {
475
- return defer(() => this.organization.getActiveMember());
470
+ return defer(() => this.organization.getActiveMember()).pipe(map((data) => this.mainService.mapData(data)));
476
471
  }
477
472
  leave(data) {
478
- return defer(() => this.organization.leave(data));
473
+ return defer(() => this.organization.leave(data)).pipe(map((data) => this.mainService.mapData(data)));
479
474
  }
480
475
  createTeam(data) {
481
476
  return defer(() => this.organization.createTeam(data));
@@ -555,7 +550,7 @@ function hasRole(requiredRoles, redirectTo = ['/unauthorized']) {
555
550
  if (!session || !session.user) {
556
551
  return router.createUrlTree(redirectTo);
557
552
  }
558
- const role = session?.user?.role;
553
+ const role = session?.user?.['role'];
559
554
  if (Array.isArray(role)) {
560
555
  if (role.some((r) => requiredRoles.includes(r))) {
561
556
  return true;