flit-baas 1.0.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,481 @@
1
+ /**
2
+ * Pluggable Storage Adapter for session persistence.
3
+ * By default, Flit SDK stores sessions strictly in-memory to prevent XSS localStorage leaks.
4
+ */
5
+ interface StorageAdapter {
6
+ getItem(key: string): string | null | Promise<string | null>;
7
+ setItem(key: string, value: string): void | Promise<void>;
8
+ removeItem(key: string): void | Promise<void>;
9
+ }
10
+ /**
11
+ * Flit SDK Configuration Options
12
+ */
13
+ interface FlitClientOptions {
14
+ /**
15
+ * Unique Application ID provided by Flit
16
+ */
17
+ appId: string;
18
+ /**
19
+ * Public Anon Key (flit_pk_...) or Secret Service Key (flit_sk_...)
20
+ * Note: Secret keys (flit_sk_...) are strictly rejected in browser environments for security.
21
+ */
22
+ apiKey?: string;
23
+ /**
24
+ * Base API endpoint (defaults to https://api.flit.site)
25
+ */
26
+ endpoint?: string;
27
+ /**
28
+ * Request timeout in milliseconds (default: 15000ms)
29
+ */
30
+ timeout?: number;
31
+ /**
32
+ * Custom HTTP headers injected into every request
33
+ */
34
+ headers?: Record<string, string>;
35
+ /**
36
+ * Custom storage adapter for auth sessions.
37
+ * Defaults to secure in-memory storage (zero localStorage usage to prevent XSS attacks).
38
+ */
39
+ storage?: StorageAdapter;
40
+ /**
41
+ * Request credentials mode ('include', 'same-origin', 'omit').
42
+ * Defaults to 'include' to automatically forward HttpOnly session cookies.
43
+ */
44
+ credentials?: RequestCredentials;
45
+ /**
46
+ * Custom fetch implementation (useful for testing or specific edge environments)
47
+ */
48
+ fetch?: typeof globalThis.fetch;
49
+ /**
50
+ * Enable verbose console logging for development
51
+ */
52
+ debug?: boolean;
53
+ }
54
+
55
+ /**
56
+ * Flit BaaS Database Types & Interfaces
57
+ */
58
+ interface BaaSRecord {
59
+ id: string;
60
+ createdAt?: string;
61
+ updatedAt?: string;
62
+ [key: string]: any;
63
+ }
64
+ type NewBaaSRecord<T> = Omit<T, 'id' | 'createdAt' | 'updatedAt'>;
65
+ interface QueryOptions<T = any> {
66
+ /**
67
+ * Maximum number of documents to return (default: 50, max: 200)
68
+ */
69
+ limit?: number;
70
+ /**
71
+ * Number of documents to skip for pagination
72
+ */
73
+ offset?: number;
74
+ /**
75
+ * Field name to sort by
76
+ */
77
+ orderBy?: keyof T | string;
78
+ /**
79
+ * Sort direction
80
+ */
81
+ order?: 'asc' | 'desc';
82
+ }
83
+ type FilterCondition<T = any> = {
84
+ [K in keyof T]?: T[K] | any;
85
+ } & Record<string, any>;
86
+ interface QueryResponse<T> {
87
+ success: boolean;
88
+ collection: string;
89
+ total: number;
90
+ records: T[];
91
+ error?: string;
92
+ }
93
+ interface SingleRecordResponse<T> {
94
+ success: boolean;
95
+ record?: T;
96
+ error?: string;
97
+ }
98
+
99
+ declare class Collection<T = any> {
100
+ private readonly client;
101
+ readonly name: string;
102
+ constructor(client: FlitClient, name: string);
103
+ /**
104
+ * Helper to normalize a record returned from the PostgreSQL JSONB document store.
105
+ * Flattens { id, createdAt, updatedAt, data: { ... } } into a single intuitive object.
106
+ */
107
+ private normalizeRecord;
108
+ /**
109
+ * Find documents matching optional filters, with pagination and sorting
110
+ * @param filter Key-value pairs to match against document properties
111
+ * @param options Query options (limit, offset, orderBy, order)
112
+ */
113
+ find(filter?: FilterCondition<T>, options?: QueryOptions<T>): Promise<T[]>;
114
+ /**
115
+ * Find a single document by its unique ID
116
+ * @param id Document UUID
117
+ */
118
+ findById(id: string): Promise<T | null>;
119
+ /**
120
+ * Insert a new document into the collection
121
+ * @param data The document payload (without id, createdAt, updatedAt)
122
+ */
123
+ insert(data: NewBaaSRecord<T>): Promise<T>;
124
+ /**
125
+ * Insert multiple documents sequentially
126
+ * @param items Array of document payloads
127
+ */
128
+ insertMany(items: Array<NewBaaSRecord<T>>): Promise<T[]>;
129
+ /**
130
+ * Update an existing document by ID
131
+ * @param id Document UUID
132
+ * @param data Partial update payload
133
+ */
134
+ update(id: string, data: Partial<T>): Promise<T>;
135
+ /**
136
+ * Delete a document by ID
137
+ * @param id Document UUID
138
+ */
139
+ delete(id: string): Promise<boolean>;
140
+ /**
141
+ * Count documents matching an optional filter
142
+ */
143
+ count(filter?: FilterCondition<T>): Promise<number>;
144
+ }
145
+
146
+ /**
147
+ * Mobile Money & Payment Types
148
+ */
149
+ type MobileMoneyOperator = 'ORANGE' | 'MTN' | 'WAVE' | 'AIRTEL' | 'MOOV' | 'MPESA';
150
+ type PaymentCurrency = 'XAF' | 'XOF' | 'KES' | 'GHS' | 'USD';
151
+ type PaymentStatus = 'PENDING' | 'SUCCESS' | 'FAILED' | 'EXPIRED' | 'CANCELLED';
152
+ interface PaymentInitiateRequest {
153
+ /**
154
+ * Mobile Money Operator (Orange Money, MTN MoMo, Wave, etc.)
155
+ */
156
+ operator: MobileMoneyOperator;
157
+ /**
158
+ * Recipient / Customer phone number (international or national format)
159
+ * Examples: "+237690000000", "690000000", "770000000"
160
+ */
161
+ phone: string;
162
+ /**
163
+ * Amount in specified currency (must be positive integer or decimal)
164
+ */
165
+ amount: number;
166
+ /**
167
+ * Regional Currency (default: 'XAF')
168
+ */
169
+ currency?: PaymentCurrency;
170
+ /**
171
+ * Order / Transaction title or memo displayed to customer
172
+ */
173
+ title?: string;
174
+ /**
175
+ * Customer full name
176
+ */
177
+ customerName?: string;
178
+ /**
179
+ * Customer email address
180
+ */
181
+ customerEmail?: string;
182
+ /**
183
+ * Custom metadata payload returned with webhook callbacks
184
+ */
185
+ metadata?: Record<string, any>;
186
+ }
187
+ interface PaymentInitiateResponse {
188
+ success: boolean;
189
+ transactionId: string;
190
+ depositId?: string;
191
+ status: PaymentStatus;
192
+ operator: MobileMoneyOperator;
193
+ amount: number;
194
+ currency: PaymentCurrency;
195
+ message?: string;
196
+ }
197
+ interface PaymentStatusResponse {
198
+ success: boolean;
199
+ transactionId: string;
200
+ status: PaymentStatus;
201
+ operator: MobileMoneyOperator;
202
+ amount: number;
203
+ currency: PaymentCurrency;
204
+ createdAt: string;
205
+ completedAt?: string;
206
+ errorMessage?: string;
207
+ metadata?: Record<string, any>;
208
+ }
209
+
210
+ declare class FlitPayments {
211
+ private readonly client;
212
+ constructor(client: FlitClient);
213
+ /**
214
+ * Initiate a Mobile Money STK Push deposit (Orange Money, MTN MoMo, Wave, etc.)
215
+ * @param order Payment order specifications
216
+ */
217
+ initiate(order: PaymentInitiateRequest): Promise<PaymentInitiateResponse>;
218
+ /**
219
+ * Retrieve current real-time status of a payment transaction
220
+ * @param transactionId Transaction or deposit reference
221
+ */
222
+ getStatus(transactionId: string): Promise<PaymentStatusResponse>;
223
+ /**
224
+ * Poll for transaction completion until a final status (SUCCESS, FAILED, EXPIRED) is reached
225
+ * @param transactionId Transaction reference
226
+ * @param options Polling configuration (timeoutMs default 60000ms, intervalMs default 3000ms)
227
+ */
228
+ waitForStatus(transactionId: string, options?: {
229
+ timeoutMs?: number;
230
+ intervalMs?: number;
231
+ }): Promise<PaymentStatusResponse>;
232
+ }
233
+
234
+ /**
235
+ * Authentication Types & Interfaces
236
+ */
237
+ interface AuthUser {
238
+ id: string;
239
+ email: string;
240
+ name?: string;
241
+ phone?: string;
242
+ role?: string;
243
+ metadata?: Record<string, any>;
244
+ createdAt: string;
245
+ updatedAt?: string;
246
+ }
247
+ interface AuthSession {
248
+ token: string;
249
+ refreshToken?: string;
250
+ expiresAt: number;
251
+ user: AuthUser;
252
+ }
253
+ interface SignUpCredentials {
254
+ email: string;
255
+ password?: string;
256
+ name?: string;
257
+ phone?: string;
258
+ metadata?: Record<string, any>;
259
+ }
260
+ interface SignInCredentials {
261
+ email: string;
262
+ password?: string;
263
+ phone?: string;
264
+ }
265
+ interface AuthResponse {
266
+ success: boolean;
267
+ user?: AuthUser;
268
+ session?: AuthSession;
269
+ error?: string;
270
+ }
271
+
272
+ /**
273
+ * Universal Cookie & Cryptographic Utilities
274
+ * In strict compliance with Web Security Standards:
275
+ * - RFC 6265 Cookies with HttpOnly, Secure, and SameSite=Lax flags
276
+ * - AES-256-GCM authenticated symmetric encryption via standard Web Crypto API (crypto.subtle)
277
+ * - Zero XSS vulnerability: Tokens never touch document.cookie or localStorage
278
+ */
279
+ interface CookieOptions {
280
+ name?: string;
281
+ path?: string;
282
+ maxAge?: number;
283
+ domain?: string;
284
+ secure?: boolean;
285
+ httpOnly?: boolean;
286
+ sameSite?: 'Lax' | 'Strict' | 'None';
287
+ }
288
+ interface EncryptedSessionPayload {
289
+ token: string;
290
+ userId: string;
291
+ appId: string;
292
+ expiresAt: number;
293
+ [key: string]: any;
294
+ }
295
+ /**
296
+ * Encrypt a session payload into a compact base64-encoded string using AES-256-GCM
297
+ */
298
+ declare function encryptSession(payload: EncryptedSessionPayload, secretKey: string): Promise<string>;
299
+ /**
300
+ * Decrypt and verify an AES-256-GCM encrypted session string
301
+ */
302
+ declare function decryptSession(encryptedText: string, secretKey: string): Promise<EncryptedSessionPayload | null>;
303
+ /**
304
+ * Build a standard RFC 6265 Set-Cookie header string with HttpOnly and Secure flags
305
+ */
306
+ declare function buildSetCookieHeader(value: string, options?: CookieOptions): string;
307
+ /**
308
+ * Build a Set-Cookie header to immediately expire and delete the session cookie
309
+ */
310
+ declare function buildClearCookieHeader(options?: CookieOptions): string;
311
+ /**
312
+ * Parse a specific cookie value from an incoming `Cookie` header string
313
+ */
314
+ declare function parseCookieFromHeader(cookieHeader: string | null | undefined, cookieName?: string): string | null;
315
+
316
+ declare class FlitAuth {
317
+ private readonly client;
318
+ private readonly storage?;
319
+ private currentSession;
320
+ private readonly storageKey;
321
+ constructor(client: FlitClient, storage?: StorageAdapter);
322
+ /**
323
+ * Initialize session securely.
324
+ * If a custom storage adapter was provided (e.g. secure encrypted cookie store),
325
+ * load the session from it. Otherwise keep in-memory only (zero XSS localStorage exposure).
326
+ */
327
+ private initSession;
328
+ private persistSession;
329
+ /**
330
+ * Register a new user
331
+ */
332
+ signUp(credentials: SignUpCredentials): Promise<AuthResponse>;
333
+ /**
334
+ * Sign in an existing user with email and password
335
+ */
336
+ signInWithPassword(credentials: SignInCredentials): Promise<AuthResponse>;
337
+ /**
338
+ * Sign out the currently authenticated user
339
+ */
340
+ signOut(): Promise<void>;
341
+ /**
342
+ * Get current session if available (in-memory)
343
+ */
344
+ getSession(): AuthSession | null;
345
+ /**
346
+ * Get current user if authenticated
347
+ */
348
+ getUser(): AuthUser | null;
349
+ /**
350
+ * Server-Side Helper: Generate a cryptographically encrypted (AES-256-GCM) HttpOnly Set-Cookie header.
351
+ * Immunizes authentication tokens against XSS attacks.
352
+ *
353
+ * @param session The authenticated session to encrypt
354
+ * @param secretKey Encryption key (defaults to client's secret apiKey or appId)
355
+ * @param options Custom cookie attributes (Path, Domain, Max-Age, etc.)
356
+ */
357
+ createSessionCookie(session: AuthSession, secretKey?: string, options?: CookieOptions): Promise<string>;
358
+ /**
359
+ * Server-Side Helper: Decrypt and verify an incoming HttpOnly cookie header using AES-256-GCM.
360
+ *
361
+ * @param cookieHeader The incoming Cookie request header string
362
+ * @param secretKey Encryption key (must match the key used in createSessionCookie)
363
+ */
364
+ verifySessionCookie(cookieHeader: string | null | undefined, secretKey?: string, cookieName?: string): Promise<EncryptedSessionPayload | null>;
365
+ /**
366
+ * Server-Side Helper: Generate a Set-Cookie header that expires and destroys the session cookie.
367
+ */
368
+ clearSessionCookie(options?: CookieOptions): string;
369
+ }
370
+
371
+ interface StorageUploadResponse {
372
+ success: boolean;
373
+ url: string;
374
+ key: string;
375
+ size?: number;
376
+ contentType?: string;
377
+ }
378
+ declare class FlitStorage {
379
+ private readonly client;
380
+ constructor(client: FlitClient);
381
+ /**
382
+ * Upload a file (Blob, File, or Buffer) to Flit Cloud Storage
383
+ */
384
+ upload(file: any, fileName: string, options?: {
385
+ contentType?: string;
386
+ }): Promise<StorageUploadResponse>;
387
+ /**
388
+ * Generate a public URL for a stored asset
389
+ */
390
+ getPublicUrl(key: string): string;
391
+ }
392
+
393
+ declare class FlitClient {
394
+ readonly appId: string;
395
+ readonly apiKey?: string;
396
+ readonly endpoint: string;
397
+ readonly timeout: number;
398
+ private readonly customHeaders;
399
+ private readonly customFetch?;
400
+ private readonly debug;
401
+ private readonly credentials;
402
+ private readonly _storageAdapter?;
403
+ private _payments?;
404
+ private _auth?;
405
+ private _storage?;
406
+ constructor(options: FlitClientOptions);
407
+ /**
408
+ * Access a database collection
409
+ * @param name Name of the collection (e.g. 'products', 'users', 'orders')
410
+ */
411
+ collection<T = any>(name: string): Collection<T>;
412
+ /**
413
+ * Access Mobile Money payments service (Orange Money, MTN MoMo, Wave)
414
+ */
415
+ get payments(): FlitPayments;
416
+ /**
417
+ * Access Authentication service
418
+ */
419
+ get auth(): FlitAuth;
420
+ /**
421
+ * Access Storage & File upload service
422
+ */
423
+ get storage(): FlitStorage;
424
+ /**
425
+ * Internal HTTP request transport with timeout and error handling
426
+ */
427
+ request<T = any>(path: string, init?: RequestInit): Promise<T>;
428
+ }
429
+
430
+ /**
431
+ * Flit SDK Error Hierarchy
432
+ */
433
+ declare class FlitError extends Error {
434
+ readonly code: string;
435
+ constructor(message: string, code?: string);
436
+ }
437
+ declare class FlitAPIError extends FlitError {
438
+ readonly status: number;
439
+ readonly details?: any;
440
+ constructor(message: string, status: number, code?: string, details?: any);
441
+ }
442
+ declare class FlitPaymentError extends FlitError {
443
+ readonly operator?: string;
444
+ readonly transactionId?: string;
445
+ constructor(message: string, operator?: string, transactionId?: string);
446
+ }
447
+ declare class FlitAuthError extends FlitError {
448
+ constructor(message: string, code?: string);
449
+ }
450
+
451
+ /**
452
+ * Flit BaaS & Mobile Money SDK
453
+ * Official TypeScript Client Library
454
+ */
455
+
456
+ /**
457
+ * Creates and initializes a new Flit BaaS Client instance
458
+ *
459
+ * @example
460
+ * ```typescript
461
+ * import { createClient } from '@flit/baas';
462
+ *
463
+ * export const flit = createClient({
464
+ * appId: process.env.NEXT_PUBLIC_FLIT_APP_ID!,
465
+ * apiKey: process.env.NEXT_PUBLIC_FLIT_API_KEY!,
466
+ * });
467
+ *
468
+ * // Query documents
469
+ * const products = await flit.collection('products').find();
470
+ *
471
+ * // Initiate Mobile Money payment
472
+ * const payment = await flit.payments.initiate({
473
+ * operator: 'ORANGE',
474
+ * phone: '690000000',
475
+ * amount: 15000,
476
+ * });
477
+ * ```
478
+ */
479
+ declare function createClient(options: FlitClientOptions): FlitClient;
480
+
481
+ export { type AuthResponse, type AuthSession, type AuthUser, type BaaSRecord, Collection, type CookieOptions, type EncryptedSessionPayload, type FilterCondition, FlitAPIError, FlitAuth, FlitAuthError, FlitClient, type FlitClientOptions, FlitError, FlitPaymentError, FlitPayments, FlitStorage, type MobileMoneyOperator, type NewBaaSRecord, type PaymentCurrency, type PaymentInitiateRequest, type PaymentInitiateResponse, type PaymentStatus, type PaymentStatusResponse, type QueryOptions, type QueryResponse, type SignInCredentials, type SignUpCredentials, type SingleRecordResponse, type StorageAdapter, buildClearCookieHeader, buildSetCookieHeader, createClient, decryptSession, createClient as default, encryptSession, parseCookieFromHeader };