nexabase-console 2.0.0 → 2.0.2

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
@@ -220,47 +220,120 @@ async function potongStokAman(productId, variantId, qtyBeli) {
220
220
 
221
221
  ---
222
222
 
223
- ### 3. Autentikasi Pengguna & OTP Tanpa Sandi
223
+ ### 3. Autentikasi Pengguna & OTP Tanpa Sandi (SDK v2.0.0)
224
224
 
225
- #### Pendaftaran & Login Tradisional
225
+ #### Inisialisasi Auth & Realtime State Listener
226
226
  ```javascript
227
- // Registrasi User Baru
227
+ import { getAuth, NexaAuthError } from 'nexabase-console';
228
+
229
+ const auth = getAuth(app);
230
+
231
+ // Realtime Listener & Sync Sesi Multi-Tab via StorageEvent
232
+ const unsubscribe = auth.onAuthStateChanged((user) => {
233
+ if (user) {
234
+ console.log("User terautentikasi:", user.uid, "| Email:", user.email);
235
+ } else {
236
+ console.log("User ter-logout / belum login");
237
+ }
238
+ });
239
+ ```
240
+
241
+ #### Pendaftaran & Login Email/Password
242
+ ```javascript
243
+ // 1. Registrasi Akun Baru
228
244
  const register = async () => {
229
- const user = await app.auth().createUserWithEmailAndPassword(
230
- 'test@example.com',
231
- 'password123',
232
- 'Andi Wijaya'
233
- );
234
- console.log("Registrasi Berhasil:", user);
245
+ try {
246
+ const session = await auth.createUserWithEmailAndPassword(
247
+ 'budi@example.com',
248
+ 'Password123!',
249
+ 'Budi Santoso'
250
+ );
251
+ console.log("Registrasi Berhasil! UID:", session.user.uid);
252
+ } catch (err) {
253
+ if (err instanceof NexaAuthError && err.code === 'auth/email-already-in-use') {
254
+ console.error("Email sudah terdaftar.");
255
+ }
256
+ }
235
257
  };
236
258
 
237
- // Login User
259
+ // 2. Login User (Dukungan Automatic Single-Flight Token Refresh)
238
260
  const login = async () => {
239
- const authSession = await app.auth().signInWithEmailAndPassword(
240
- 'test@example.com',
241
- 'password123'
242
- );
243
- console.log("Token Sesi JWT:", authSession.token);
244
- console.log("Data Akun Pengguna:", authSession.user);
261
+ try {
262
+ const session = await auth.signInWithEmailAndPassword(
263
+ 'budi@example.com',
264
+ 'Password123!'
265
+ );
266
+ console.log("Access Token JWT:", session.accessToken);
267
+ console.log("Refresh Token:", session.refreshToken);
268
+ } catch (err) {
269
+ if (err instanceof NexaAuthError && err.code === 'auth/invalid-credential') {
270
+ console.error("Email atau password salah.");
271
+ }
272
+ }
245
273
  };
246
274
  ```
247
275
 
248
- #### Login Passwordless dengan OTP (Email)
276
+ #### Login Passwordless dengan OTP (Email 6-Digit)
249
277
  ```javascript
250
- // 1. Kirim OTP Ke Email Pengguna
278
+ // 1. Kirim OTP Ke Email (Berlaku 5 Menit, Hash Single-Use)
251
279
  const sendMyOtp = async () => {
252
- const res = await app.auth().sendOtp('test@example.com');
253
- console.log("Kode OTP berhasil terkirim ke email Anda.");
280
+ const res = await auth.sendOtp('budi@example.com');
281
+ console.log("Kode OTP berhasil terkirim:", res.message);
254
282
  };
255
283
 
256
284
  // 2. Verifikasi OTP dari Input Pengguna
257
285
  const verifyMyOtp = async () => {
258
- const otpCode = '123456'; // Kode 6 digit yang dikirim ke email
259
- const authSession = await app.auth().signInWithOtp('test@example.com', otpCode, 'Andi Wijaya');
260
- console.log("Login OTP Berhasil! Sesi JWT Aktif:", authSession.token);
286
+ try {
287
+ const otpCode = '123456'; // Kode 6 digit yang dikirim ke email
288
+ const session = await auth.signInWithOtp('budi@example.com', otpCode);
289
+ console.log("Login OTP Berhasil! Welcome:", session.user.email);
290
+ } catch (err) {
291
+ if (err instanceof NexaAuthError) {
292
+ if (err.code === 'auth/invalid-otp') console.error("OTP tidak valid.");
293
+ if (err.code === 'auth/expired-otp') console.error("OTP kedaluwarsa.");
294
+ if (err.code === 'auth/too-many-otp-attempts') console.error("Terlalu banyak percobaan.");
295
+ }
296
+ }
261
297
  };
262
298
  ```
263
299
 
300
+ #### Mengambil ID Token untuk Request API / Server Verification
301
+ ```javascript
302
+ // Mengambil token JWT (dengan auto-refresh jika hampir expired)
303
+ const idToken = await auth.getIdToken(/* forceRefresh */ false);
304
+
305
+ // Mengambil rincian klaim token (exp, authTime, claims)
306
+ const tokenResult = await auth.getIdTokenResult();
307
+ console.log("Token Kedaluwarsa:", tokenResult.expirationTime);
308
+ ```
309
+
310
+ #### Update Profil, Reset Password & Sign Out
311
+ ```javascript
312
+ // Update Profil
313
+ await auth.updateProfile({ name: 'Budi Santoso, M.T.', photoURL: 'https://example.com/photo.jpg' });
314
+
315
+ // Reset Password Email
316
+ await auth.sendPasswordResetEmail('budi@example.com');
317
+
318
+ // Revoke All Sessions
319
+ await auth.revokeAllSessions();
320
+
321
+ // === Opsi Logout Akun (Sign Out) ===
322
+ // 1. Method Instance (Rekomendasi)
323
+ await auth.signOut();
324
+
325
+ // 2. Fungsi Standar Modular
326
+ import { signOut } from 'nexabase-console';
327
+ await signOut(auth);
328
+
329
+ // 3. Namespace Helper
330
+ import { NexabaseAuth } from 'nexabase-console';
331
+ await NexabaseAuth.signOut(auth);
332
+
333
+ // 4. Shortcut dari objek App
334
+ await app.signOut();
335
+ ```
336
+
264
337
  ---
265
338
 
266
339
  ### 4. File Storage API
@@ -1,8 +1,9 @@
1
1
  import { AxiosInstance } from 'axios';
2
- import { NexaConfig, User, AuthResponse, DatabaseReference, StorageReference, UploadOptions, OfflineJob } from '../types/index';
2
+ import { NexaConfig, DatabaseReference, StorageReference, UploadOptions, OfflineJob } from '../types/index';
3
3
  import { HttpClient } from '../transport/HttpClient';
4
4
  import { SSEClient } from '../transport/SSEClient';
5
5
  import { Auth } from '../auth/Auth';
6
+ import { User as AuthUser, AuthSession } from '../auth/authTypes';
6
7
  import { IndexedDB } from '../persistence/IndexedDB';
7
8
  import { LocalStore } from '../persistence/LocalStore';
8
9
  import { MutationQueue } from '../persistence/MutationQueue';
@@ -44,15 +45,15 @@ export declare class NexaApp {
44
45
  _ensureFirestoreSSE(): void;
45
46
  _closeFirestoreSSEIfIdle(): void;
46
47
  _notifySnapshotCallbacks(path: string, actionType: string, payload: any): void;
47
- signInWithEmailAndPassword(email: string, password: string): Promise<AuthResponse>;
48
- createUserWithEmailAndPassword(email: string, password: string, name: string): Promise<User>;
48
+ signInWithEmailAndPassword(email: string, password: string): Promise<AuthSession>;
49
+ createUserWithEmailAndPassword(email: string, password: string, name?: string): Promise<AuthSession>;
49
50
  sendOtp(email: string): Promise<{
50
51
  success: boolean;
51
52
  message: string;
52
53
  }>;
53
- signInWithOtp(email: string, otp: string, name?: string): Promise<AuthResponse>;
54
+ signInWithOtp(email: string, otp: string): Promise<AuthSession>;
54
55
  signOut(): void;
55
- getCurrentUser(): User | null;
56
+ getCurrentUser(): AuthUser | null;
56
57
  ref(path: string): DatabaseReference;
57
58
  storageRef(path: string): StorageReference;
58
59
  uploadFile(path: string, file: File | Blob, options?: UploadOptions): Promise<{
@@ -150,8 +150,8 @@ class NexaApp {
150
150
  async sendOtp(email) {
151
151
  return this.authService.sendOtp(email);
152
152
  }
153
- async signInWithOtp(email, otp, name) {
154
- const res = await this.authService.signInWithOtp(email, otp, name);
153
+ async signInWithOtp(email, otp) {
154
+ const res = await this.authService.signInWithOtp(email, otp);
155
155
  this.token = this.authService.getToken();
156
156
  return res;
157
157
  }
@@ -1,8 +1,14 @@
1
1
  import { NexaApp } from './NexaApp';
2
2
  import { NexaConfig } from '../types/index';
3
+ import { Auth } from '../auth/Auth';
3
4
  export declare const NexaBase: {
4
5
  init: (config: NexaConfig) => NexaApp;
5
6
  initializeApp: (config: NexaConfig) => NexaApp;
6
7
  };
7
8
  export declare const initializeApp: (config: NexaConfig) => NexaApp;
8
9
  export declare const getFirestore: (app: NexaApp) => NexaApp;
10
+ export declare const getAuth: (app: NexaApp) => Auth;
11
+ export declare const signOut: (auth: Auth) => Promise<void>;
12
+ export declare const NexabaseAuth: {
13
+ signOut: (auth: Auth) => Promise<void>;
14
+ };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFirestore = exports.initializeApp = exports.NexaBase = void 0;
3
+ exports.NexabaseAuth = exports.signOut = exports.getAuth = exports.getFirestore = exports.initializeApp = exports.NexaBase = void 0;
4
4
  const NexaApp_1 = require("./NexaApp");
5
5
  exports.NexaBase = {
6
6
  init: (config) => {
@@ -25,3 +25,16 @@ const getFirestore = (app) => {
25
25
  return app;
26
26
  };
27
27
  exports.getFirestore = getFirestore;
28
+ const getAuth = (app) => {
29
+ return app.authService;
30
+ };
31
+ exports.getAuth = getAuth;
32
+ const signOut = (auth) => {
33
+ return auth.signOut();
34
+ };
35
+ exports.signOut = signOut;
36
+ exports.NexabaseAuth = {
37
+ signOut: (auth) => {
38
+ return auth.signOut();
39
+ }
40
+ };
@@ -1,21 +1,53 @@
1
1
  import { AxiosInstance } from 'axios';
2
- import { User, AuthResponse } from './authTypes';
2
+ import { User, AuthSession, IdTokenResult, UserProfileUpdate, AuthStateCallback } from './authTypes';
3
3
  export declare class Auth {
4
4
  private projectId;
5
5
  private client;
6
- private token;
7
6
  private persistence;
7
+ private emulatorUrl;
8
+ private currentSession;
9
+ private listeners;
10
+ private refreshPromise;
11
+ private refreshTimer;
8
12
  constructor(projectId: string, client: AxiosInstance, initialToken: string | null);
13
+ connectAuthEmulator(url: string): void;
14
+ get emulator(): string | null;
15
+ private initSession;
16
+ onAuthStateChanged(callback: AuthStateCallback): () => void;
17
+ private notifyListeners;
18
+ private handleStorageChange;
19
+ get currentUser(): User | null;
9
20
  getToken(): string | null;
10
21
  setToken(token: string | null): void;
11
- signInWithEmailAndPassword(email: string, password: string): Promise<AuthResponse>;
12
- createUserWithEmailAndPassword(email: string, password: string, name: string): Promise<User>;
22
+ getIdToken(forceRefresh?: boolean): Promise<string>;
23
+ getIdTokenResult(forceRefresh?: boolean): Promise<IdTokenResult>;
24
+ private parseJwtClaims;
25
+ private refreshAccessTokenDeduplicated;
26
+ private refreshAccessToken;
27
+ private scheduleAutoRefresh;
28
+ private clearAutoRefresh;
29
+ createUserWithEmailAndPassword(email: string, password: string, name?: string): Promise<AuthSession>;
30
+ signInWithEmailAndPassword(email: string, password: string): Promise<AuthSession>;
13
31
  sendOtp(email: string): Promise<{
14
32
  success: boolean;
15
33
  message: string;
16
34
  }>;
17
- signInWithOtp(email: string, otp: string, name?: string): Promise<AuthResponse>;
18
- signOut(): void;
35
+ signInWithOtp(email: string, otp: string): Promise<AuthSession>;
36
+ sendPasswordResetEmail(email: string): Promise<{
37
+ success: boolean;
38
+ }>;
39
+ confirmPasswordReset(code: string, newPassword: string): Promise<{
40
+ success: boolean;
41
+ }>;
42
+ sendEmailVerification(): Promise<{
43
+ success: boolean;
44
+ }>;
45
+ updateProfile(update: UserProfileUpdate): Promise<User>;
46
+ updatePassword(newPassword: string): Promise<void>;
47
+ deleteUser(): Promise<void>;
48
+ revokeSession(sessionId?: string): Promise<void>;
49
+ revokeAllSessions(): Promise<void>;
50
+ signOut(): Promise<void>;
19
51
  getCurrentUser(): User | null;
20
52
  }
21
53
  export { Auth as AuthService };