nexabase-console 2.0.1 → 2.0.3
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 +130 -23
- package/dist/app/NexaApp.d.ts +6 -5
- package/dist/app/NexaApp.js +2 -2
- package/dist/app/initializeApp.d.ts +6 -0
- package/dist/app/initializeApp.js +14 -1
- package/dist/auth/Auth.d.ts +38 -6
- package/dist/auth/Auth.js +341 -28
- package/dist/auth/NexaAuthError.d.ts +5 -0
- package/dist/auth/NexaAuthError.js +15 -0
- package/dist/auth/authTypes.d.ts +38 -1
- package/dist/auth/persistence.d.ts +7 -5
- package/dist/auth/persistence.js +42 -13
- package/dist/facade/nexaSDK.d.ts +93 -0
- package/dist/facade/nexaSDK.js +129 -0
- package/dist/firestore/Query.d.ts +9 -1
- package/dist/firestore/Query.js +62 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/storage/Storage.d.ts +5 -0
- package/dist/storage/Storage.js +17 -1
- package/dist/storage/StorageReference.d.ts +18 -0
- package/dist/storage/StorageReference.js +33 -1
- package/dist/types/index.d.ts +17 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,6 +142,40 @@ const listenLiveChats = () => {
|
|
|
142
142
|
};
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
+
#### Agregasi Data & Hitung Dokumen (`getCountFromServer` / `getAggregateFromServer`)
|
|
146
|
+
Mendukung fungsi agregasi server 1:1 seperti Firebase SDK: `getCountFromServer()`, `getAggregateFromServer()`, `count()`, `sum()`, dan `average()`.
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
import {
|
|
150
|
+
collection,
|
|
151
|
+
query,
|
|
152
|
+
where,
|
|
153
|
+
getCountFromServer,
|
|
154
|
+
getAggregateFromServer,
|
|
155
|
+
count,
|
|
156
|
+
sum,
|
|
157
|
+
average
|
|
158
|
+
} from 'nexabase-console';
|
|
159
|
+
|
|
160
|
+
// 1. Menghitung total dokumen (getCountFromServer)
|
|
161
|
+
const productsRef = collection(db, 'products');
|
|
162
|
+
const qAvailable = query(productsRef, where('status', '==', 'active'));
|
|
163
|
+
|
|
164
|
+
const countSnapshot = await getCountFromServer(qAvailable);
|
|
165
|
+
console.log("Total produk aktif:", countSnapshot.data().count);
|
|
166
|
+
|
|
167
|
+
// 2. Agregasi multi-field (getAggregateFromServer)
|
|
168
|
+
const orderStats = await getAggregateFromServer(collection(db, 'orders'), {
|
|
169
|
+
totalOrders: count(),
|
|
170
|
+
totalRevenue: sum('totalAmount'),
|
|
171
|
+
avgOrderValue: average('totalAmount')
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
console.log("Jumlah order:", orderStats.data().totalOrders);
|
|
175
|
+
console.log("Total pendapatan:", orderStats.data().totalRevenue);
|
|
176
|
+
console.log("Rata-rata transaksi:", orderStats.data().avgOrderValue);
|
|
177
|
+
```
|
|
178
|
+
|
|
145
179
|
#### Menggunakan Atomic Write Batch (Untuk Upload File / Excel Massal)
|
|
146
180
|
Jika Anda mengunggah data sekaligus dalam jumlah besar dari file (misal: import 500 resi dari Excel), hindari memanggil `setDoc` satu per satu di dalam _looping_. Gunakan fitur `writeBatch` yang membundel seluruh operasi Anda dalam satu pengiriman jaringan (hingga 500 operasi per eksekusi).
|
|
147
181
|
|
|
@@ -220,47 +254,120 @@ async function potongStokAman(productId, variantId, qtyBeli) {
|
|
|
220
254
|
|
|
221
255
|
---
|
|
222
256
|
|
|
223
|
-
### 3. Autentikasi Pengguna & OTP Tanpa Sandi
|
|
257
|
+
### 3. Autentikasi Pengguna & OTP Tanpa Sandi (SDK v2.0.0)
|
|
258
|
+
|
|
259
|
+
#### Inisialisasi Auth & Realtime State Listener
|
|
260
|
+
```javascript
|
|
261
|
+
import { getAuth, NexaAuthError } from 'nexabase-console';
|
|
262
|
+
|
|
263
|
+
const auth = getAuth(app);
|
|
224
264
|
|
|
225
|
-
|
|
265
|
+
// Realtime Listener & Sync Sesi Multi-Tab via StorageEvent
|
|
266
|
+
const unsubscribe = auth.onAuthStateChanged((user) => {
|
|
267
|
+
if (user) {
|
|
268
|
+
console.log("User terautentikasi:", user.uid, "| Email:", user.email);
|
|
269
|
+
} else {
|
|
270
|
+
console.log("User ter-logout / belum login");
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
#### Pendaftaran & Login Email/Password
|
|
226
276
|
```javascript
|
|
227
|
-
// Registrasi
|
|
277
|
+
// 1. Registrasi Akun Baru
|
|
228
278
|
const register = async () => {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
279
|
+
try {
|
|
280
|
+
const session = await auth.createUserWithEmailAndPassword(
|
|
281
|
+
'budi@example.com',
|
|
282
|
+
'Password123!',
|
|
283
|
+
'Budi Santoso'
|
|
284
|
+
);
|
|
285
|
+
console.log("Registrasi Berhasil! UID:", session.user.uid);
|
|
286
|
+
} catch (err) {
|
|
287
|
+
if (err instanceof NexaAuthError && err.code === 'auth/email-already-in-use') {
|
|
288
|
+
console.error("Email sudah terdaftar.");
|
|
289
|
+
}
|
|
290
|
+
}
|
|
235
291
|
};
|
|
236
292
|
|
|
237
|
-
// Login User
|
|
293
|
+
// 2. Login User (Dukungan Automatic Single-Flight Token Refresh)
|
|
238
294
|
const login = async () => {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
295
|
+
try {
|
|
296
|
+
const session = await auth.signInWithEmailAndPassword(
|
|
297
|
+
'budi@example.com',
|
|
298
|
+
'Password123!'
|
|
299
|
+
);
|
|
300
|
+
console.log("Access Token JWT:", session.accessToken);
|
|
301
|
+
console.log("Refresh Token:", session.refreshToken);
|
|
302
|
+
} catch (err) {
|
|
303
|
+
if (err instanceof NexaAuthError && err.code === 'auth/invalid-credential') {
|
|
304
|
+
console.error("Email atau password salah.");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
245
307
|
};
|
|
246
308
|
```
|
|
247
309
|
|
|
248
|
-
#### Login Passwordless dengan OTP (Email)
|
|
310
|
+
#### Login Passwordless dengan OTP (Email 6-Digit)
|
|
249
311
|
```javascript
|
|
250
|
-
// 1. Kirim OTP Ke Email
|
|
312
|
+
// 1. Kirim OTP Ke Email (Berlaku 5 Menit, Hash Single-Use)
|
|
251
313
|
const sendMyOtp = async () => {
|
|
252
|
-
const res = await
|
|
253
|
-
console.log("Kode OTP berhasil terkirim
|
|
314
|
+
const res = await auth.sendOtp('budi@example.com');
|
|
315
|
+
console.log("Kode OTP berhasil terkirim:", res.message);
|
|
254
316
|
};
|
|
255
317
|
|
|
256
318
|
// 2. Verifikasi OTP dari Input Pengguna
|
|
257
319
|
const verifyMyOtp = async () => {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
320
|
+
try {
|
|
321
|
+
const otpCode = '123456'; // Kode 6 digit yang dikirim ke email
|
|
322
|
+
const session = await auth.signInWithOtp('budi@example.com', otpCode);
|
|
323
|
+
console.log("Login OTP Berhasil! Welcome:", session.user.email);
|
|
324
|
+
} catch (err) {
|
|
325
|
+
if (err instanceof NexaAuthError) {
|
|
326
|
+
if (err.code === 'auth/invalid-otp') console.error("OTP tidak valid.");
|
|
327
|
+
if (err.code === 'auth/expired-otp') console.error("OTP kedaluwarsa.");
|
|
328
|
+
if (err.code === 'auth/too-many-otp-attempts') console.error("Terlalu banyak percobaan.");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
261
331
|
};
|
|
262
332
|
```
|
|
263
333
|
|
|
334
|
+
#### Mengambil ID Token untuk Request API / Server Verification
|
|
335
|
+
```javascript
|
|
336
|
+
// Mengambil token JWT (dengan auto-refresh jika hampir expired)
|
|
337
|
+
const idToken = await auth.getIdToken(/* forceRefresh */ false);
|
|
338
|
+
|
|
339
|
+
// Mengambil rincian klaim token (exp, authTime, claims)
|
|
340
|
+
const tokenResult = await auth.getIdTokenResult();
|
|
341
|
+
console.log("Token Kedaluwarsa:", tokenResult.expirationTime);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Update Profil, Reset Password & Sign Out
|
|
345
|
+
```javascript
|
|
346
|
+
// Update Profil
|
|
347
|
+
await auth.updateProfile({ name: 'Budi Santoso, M.T.', photoURL: 'https://example.com/photo.jpg' });
|
|
348
|
+
|
|
349
|
+
// Reset Password Email
|
|
350
|
+
await auth.sendPasswordResetEmail('budi@example.com');
|
|
351
|
+
|
|
352
|
+
// Revoke All Sessions
|
|
353
|
+
await auth.revokeAllSessions();
|
|
354
|
+
|
|
355
|
+
// === Opsi Logout Akun (Sign Out) ===
|
|
356
|
+
// 1. Method Instance (Rekomendasi)
|
|
357
|
+
await auth.signOut();
|
|
358
|
+
|
|
359
|
+
// 2. Fungsi Standar Modular
|
|
360
|
+
import { signOut } from 'nexabase-console';
|
|
361
|
+
await signOut(auth);
|
|
362
|
+
|
|
363
|
+
// 3. Namespace Helper
|
|
364
|
+
import { NexabaseAuth } from 'nexabase-console';
|
|
365
|
+
await NexabaseAuth.signOut(auth);
|
|
366
|
+
|
|
367
|
+
// 4. Shortcut dari objek App
|
|
368
|
+
await app.signOut();
|
|
369
|
+
```
|
|
370
|
+
|
|
264
371
|
---
|
|
265
372
|
|
|
266
373
|
### 4. File Storage API
|
package/dist/app/NexaApp.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import { NexaConfig,
|
|
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<
|
|
48
|
-
createUserWithEmailAndPassword(email: string, password: string, name
|
|
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
|
|
54
|
+
signInWithOtp(email: string, otp: string): Promise<AuthSession>;
|
|
54
55
|
signOut(): void;
|
|
55
|
-
getCurrentUser():
|
|
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<{
|
package/dist/app/NexaApp.js
CHANGED
|
@@ -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
|
|
154
|
-
const res = await this.authService.signInWithOtp(email, otp
|
|
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
|
+
};
|
package/dist/auth/Auth.d.ts
CHANGED
|
@@ -1,21 +1,53 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import { User,
|
|
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
|
-
|
|
12
|
-
|
|
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
|
|
18
|
-
|
|
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 };
|