@techfinityedge/koolbase-react-native 1.6.1 → 1.8.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
@@ -1,4 +1,16 @@
1
- # koolbase-react-native
1
+ # Koolbase React Native SDK
2
+
3
+ ⚠️ ## This package has moved
4
+
5
+ This package is deprecated.
6
+
7
+ 👉 Install the official version:
8
+
9
+ ```bash
10
+ npm install @techfinityedge/koolbase-react-native
11
+ ```
12
+
13
+ ---
2
14
 
3
15
  [![npm](https://img.shields.io/npm/v/koolbase-react-native.svg)](https://www.npmjs.com/package/koolbase-react-native)
4
16
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
@@ -11,11 +23,12 @@ Auth, database, storage, realtime, functions, feature flags, remote config, vers
11
23
 
12
24
  ## Get started in 2 minutes
13
25
 
14
- **1. Create a free account at [app.koolbase.com](https://app.koolbase.com)**
26
+ 1. Create a free account at [app.koolbase.com](https://app.koolbase.com)
27
+
28
+ 2. Create a project and copy your public key from Environments
15
29
 
16
- **2. Create a project and copy your public key from Environments**
30
+ 3. Add the SDK:
17
31
 
18
- **3. Add the SDK:**
19
32
  ```bash
20
33
  npm install koolbase-react-native
21
34
  # or
@@ -23,6 +36,7 @@ yarn add koolbase-react-native
23
36
  ```
24
37
 
25
38
  **4. Initialize at app startup:**
39
+
26
40
  ```typescript
27
41
  import { Koolbase } from 'koolbase-react-native';
28
42
 
@@ -37,6 +51,7 @@ That's it. Every feature below is now available via `Koolbase.*`.
37
51
  ---
38
52
 
39
53
  ## Authentication
54
+
40
55
  ```typescript
41
56
  // Register
42
57
  await Koolbase.auth.register({ email: 'user@example.com', password: 'password' });
@@ -57,6 +72,7 @@ await Koolbase.auth.forgotPassword('user@example.com');
57
72
  ---
58
73
 
59
74
  ## Database
75
+
60
76
  ```typescript
61
77
  // Insert
62
78
  await Koolbase.db.insert('posts', { title: 'Hello', published: true });
@@ -80,6 +96,7 @@ await Koolbase.db.delete('record-id');
80
96
  ```
81
97
 
82
98
  ### Offline-first
99
+
83
100
  ```typescript
84
101
  const { records, isFromCache } = await Koolbase.db.query('posts', { limit: 20 });
85
102
  if (isFromCache) console.log('Served from local cache');
@@ -90,6 +107,7 @@ await Koolbase.db.syncPendingWrites();
90
107
  ---
91
108
 
92
109
  ## Storage
110
+
93
111
  ```typescript
94
112
  const { url } = await Koolbase.storage.upload({
95
113
  bucket: 'avatars',
@@ -104,6 +122,7 @@ await Koolbase.storage.delete('avatars', `user-${userId}.jpg`);
104
122
  ---
105
123
 
106
124
  ## Realtime
125
+
107
126
  ```typescript
108
127
  const unsubscribe = Koolbase.realtime.subscribe('messages', (event) => {
109
128
  if (event.type === 'created') setMessages(prev => [event.record, ...prev]);
@@ -116,6 +135,7 @@ unsubscribe();
116
135
  ---
117
136
 
118
137
  ## Feature Flags & Remote Config
138
+
119
139
  ```typescript
120
140
  if (Koolbase.isEnabled('new_checkout')) { ... }
121
141
 
@@ -127,6 +147,7 @@ const dark = Koolbase.configBool('force_dark_mode', false);
127
147
  ---
128
148
 
129
149
  ## Version Enforcement
150
+
130
151
  ```typescript
131
152
  const result = Koolbase.checkVersion('1.2.3');
132
153
  if (result.status === 'force_update') {
@@ -137,6 +158,7 @@ if (result.status === 'force_update') {
137
158
  ---
138
159
 
139
160
  ## Code Push
161
+
140
162
  ```typescript
141
163
  await Koolbase.initialize({
142
164
  publicKey: 'pk_live_xxxx',
@@ -157,6 +179,7 @@ Koolbase.codePush.applyDirectives();
157
179
  ---
158
180
 
159
181
  ## Logic Engine
182
+
160
183
  ```typescript
161
184
  // Define flows in your bundle's flows.json
162
185
  // Execute from anywhere in your app
@@ -173,6 +196,7 @@ if (result.hasEvent) {
173
196
  ---
174
197
 
175
198
  ## Analytics
199
+
176
200
  ```typescript
177
201
  await Koolbase.initialize({
178
202
  publicKey: 'pk_live_xxxx',
@@ -198,6 +222,7 @@ Koolbase.analytics.reset();
198
222
  ---
199
223
 
200
224
  ## Cloud Messaging
225
+
201
226
  ```typescript
202
227
  await Koolbase.initialize({
203
228
  publicKey: 'pk_live_xxxx',
@@ -0,0 +1,25 @@
1
+ export declare class KoolbaseAuthError extends Error {
2
+ code?: string;
3
+ constructor(message: string, code?: string);
4
+ }
5
+ export declare class InvalidPhoneNumberError extends KoolbaseAuthError {
6
+ constructor();
7
+ }
8
+ export declare class OtpExpiredError extends KoolbaseAuthError {
9
+ constructor();
10
+ }
11
+ export declare class OtpInvalidError extends KoolbaseAuthError {
12
+ constructor();
13
+ }
14
+ export declare class OtpMaxAttemptsError extends KoolbaseAuthError {
15
+ constructor();
16
+ }
17
+ export declare class OtpRateLimitError extends KoolbaseAuthError {
18
+ constructor();
19
+ }
20
+ export declare class PhoneAlreadyLinkedError extends KoolbaseAuthError {
21
+ constructor();
22
+ }
23
+ export declare class SmsConfigMissingError extends KoolbaseAuthError {
24
+ constructor();
25
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SmsConfigMissingError = exports.PhoneAlreadyLinkedError = exports.OtpRateLimitError = exports.OtpMaxAttemptsError = exports.OtpInvalidError = exports.OtpExpiredError = exports.InvalidPhoneNumberError = exports.KoolbaseAuthError = void 0;
4
+ class KoolbaseAuthError extends Error {
5
+ constructor(message, code) {
6
+ super(message);
7
+ this.code = code;
8
+ this.name = 'KoolbaseAuthError';
9
+ Object.setPrototypeOf(this, KoolbaseAuthError.prototype);
10
+ }
11
+ }
12
+ exports.KoolbaseAuthError = KoolbaseAuthError;
13
+ class InvalidPhoneNumberError extends KoolbaseAuthError {
14
+ constructor() {
15
+ super('Phone number must be in E.164 format (e.g. +233XXXXXXXXX)', 'invalid_phone');
16
+ this.name = 'InvalidPhoneNumberError';
17
+ Object.setPrototypeOf(this, InvalidPhoneNumberError.prototype);
18
+ }
19
+ }
20
+ exports.InvalidPhoneNumberError = InvalidPhoneNumberError;
21
+ class OtpExpiredError extends KoolbaseAuthError {
22
+ constructor() {
23
+ super('OTP has expired, please request a new code', 'otp_expired');
24
+ this.name = 'OtpExpiredError';
25
+ Object.setPrototypeOf(this, OtpExpiredError.prototype);
26
+ }
27
+ }
28
+ exports.OtpExpiredError = OtpExpiredError;
29
+ class OtpInvalidError extends KoolbaseAuthError {
30
+ constructor() {
31
+ super('Invalid OTP code', 'otp_invalid');
32
+ this.name = 'OtpInvalidError';
33
+ Object.setPrototypeOf(this, OtpInvalidError.prototype);
34
+ }
35
+ }
36
+ exports.OtpInvalidError = OtpInvalidError;
37
+ class OtpMaxAttemptsError extends KoolbaseAuthError {
38
+ constructor() {
39
+ super('Too many incorrect attempts, please request a new code', 'otp_max_attempts');
40
+ this.name = 'OtpMaxAttemptsError';
41
+ Object.setPrototypeOf(this, OtpMaxAttemptsError.prototype);
42
+ }
43
+ }
44
+ exports.OtpMaxAttemptsError = OtpMaxAttemptsError;
45
+ class OtpRateLimitError extends KoolbaseAuthError {
46
+ constructor() {
47
+ super('Too many OTP requests, please wait before trying again', 'otp_rate_limit');
48
+ this.name = 'OtpRateLimitError';
49
+ Object.setPrototypeOf(this, OtpRateLimitError.prototype);
50
+ }
51
+ }
52
+ exports.OtpRateLimitError = OtpRateLimitError;
53
+ class PhoneAlreadyLinkedError extends KoolbaseAuthError {
54
+ constructor() {
55
+ super('Phone number is already associated with another account', 'phone_taken');
56
+ this.name = 'PhoneAlreadyLinkedError';
57
+ Object.setPrototypeOf(this, PhoneAlreadyLinkedError.prototype);
58
+ }
59
+ }
60
+ exports.PhoneAlreadyLinkedError = PhoneAlreadyLinkedError;
61
+ class SmsConfigMissingError extends KoolbaseAuthError {
62
+ constructor() {
63
+ super('SMS provider not configured for this project', 'sms_config_missing');
64
+ this.name = 'SmsConfigMissingError';
65
+ Object.setPrototypeOf(this, SmsConfigMissingError.prototype);
66
+ }
67
+ }
68
+ exports.SmsConfigMissingError = SmsConfigMissingError;
package/dist/auth.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { KoolbaseConfig, KoolbaseSession, KoolbaseUser, LoginParams, RegisterParams } from './types';
1
+ import { KoolbaseConfig, KoolbaseSession, KoolbaseUser, LinkPhoneParams, LoginParams, OtpSendResult, PhoneVerifyResult, RegisterParams, SendOtpParams, VerifyOtpParams } from './types';
2
2
  export declare class KoolbaseAuth {
3
3
  private config;
4
4
  private session;
@@ -21,4 +21,9 @@ export declare class KoolbaseAuth {
21
21
  name?: string;
22
22
  avatarUrl?: string;
23
23
  }): Promise<Record<string, unknown> | null>;
24
+ sendOtp(params: SendOtpParams): Promise<OtpSendResult>;
25
+ verifyOtp(params: VerifyOtpParams): Promise<PhoneVerifyResult>;
26
+ linkPhone(params: LinkPhoneParams): Promise<void>;
27
+ private validatePhone;
28
+ private parsePhoneResponse;
24
29
  }
package/dist/auth.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KoolbaseAuth = void 0;
4
+ const auth_errors_1 = require("./auth-errors");
4
5
  class KoolbaseAuth {
5
6
  constructor(config) {
6
7
  this.session = null;
@@ -81,5 +82,93 @@ class KoolbaseAuth {
81
82
  return null;
82
83
  }
83
84
  }
85
+ async sendOtp(params) {
86
+ this.validatePhone(params.phoneNumber);
87
+ const res = await fetch(`${this.config.baseUrl}/v1/sdk/auth/phone/send-otp`, {
88
+ method: 'POST',
89
+ headers: this.headers,
90
+ body: JSON.stringify({ phone_number: params.phoneNumber }),
91
+ });
92
+ const data = await this.parsePhoneResponse(res);
93
+ return { expiresAt: data.expires_at };
94
+ }
95
+ async verifyOtp(params) {
96
+ this.validatePhone(params.phoneNumber);
97
+ const res = await fetch(`${this.config.baseUrl}/v1/sdk/auth/phone/verify-otp`, {
98
+ method: 'POST',
99
+ headers: this.headers,
100
+ body: JSON.stringify({
101
+ phone_number: params.phoneNumber,
102
+ code: params.code,
103
+ }),
104
+ });
105
+ const data = await this.parsePhoneResponse(res);
106
+ const user = {
107
+ id: data.user.id,
108
+ email: data.user.email ?? '',
109
+ phoneNumber: data.user.phone_number,
110
+ phoneVerified: data.user.phone_verified ?? false,
111
+ fullName: data.user.full_name,
112
+ avatarUrl: data.user.avatar_url,
113
+ verified: data.user.verified ?? false,
114
+ createdAt: data.user.created_at,
115
+ };
116
+ const session = {
117
+ accessToken: data.access_token,
118
+ refreshToken: data.refresh_token,
119
+ user,
120
+ };
121
+ this.session = session;
122
+ return { session, isNewUser: data.is_new_user ?? false };
123
+ }
124
+ async linkPhone(params) {
125
+ if (!this.session) {
126
+ throw new auth_errors_1.KoolbaseAuthError('Must be signed in to link a phone number', 'unauthenticated');
127
+ }
128
+ this.validatePhone(params.phoneNumber);
129
+ const res = await fetch(`${this.config.baseUrl}/v1/sdk/auth/phone/link`, {
130
+ method: 'POST',
131
+ headers: this.authHeaders,
132
+ body: JSON.stringify({
133
+ phone_number: params.phoneNumber,
134
+ code: params.code,
135
+ }),
136
+ });
137
+ await this.parsePhoneResponse(res);
138
+ }
139
+ validatePhone(phoneNumber) {
140
+ if (!/^\+[1-9]\d{6,14}$/.test(phoneNumber)) {
141
+ throw new auth_errors_1.InvalidPhoneNumberError();
142
+ }
143
+ }
144
+ async parsePhoneResponse(res) {
145
+ let body = {};
146
+ try {
147
+ body = await res.json();
148
+ }
149
+ catch { }
150
+ if (res.ok)
151
+ return body;
152
+ const msg = body.error ?? '';
153
+ if (res.status === 429)
154
+ throw new auth_errors_1.OtpRateLimitError();
155
+ if (res.status === 409)
156
+ throw new auth_errors_1.PhoneAlreadyLinkedError();
157
+ if (msg.includes('E.164'))
158
+ throw new auth_errors_1.InvalidPhoneNumberError();
159
+ if (msg.includes('OTP has expired'))
160
+ throw new auth_errors_1.OtpExpiredError();
161
+ if (msg.includes('too many incorrect attempts')) {
162
+ throw new auth_errors_1.OtpMaxAttemptsError();
163
+ }
164
+ if (msg.includes('invalid OTP') ||
165
+ msg.includes('invalid or expired OTP')) {
166
+ throw new auth_errors_1.OtpInvalidError();
167
+ }
168
+ if (msg.includes('SMS provider not configured')) {
169
+ throw new auth_errors_1.SmsConfigMissingError();
170
+ }
171
+ throw new auth_errors_1.KoolbaseAuthError(msg || 'An unexpected error occurred');
172
+ }
84
173
  }
85
174
  exports.KoolbaseAuth = KoolbaseAuth;
@@ -1,7 +1,8 @@
1
1
  import { KoolbaseConfig, FunctionInvokeResult, DeployOptions, DeployResult } from './types';
2
2
  export declare class KoolbaseFunctions {
3
3
  private config;
4
- constructor(config: KoolbaseConfig);
4
+ private getUserAccessToken?;
5
+ constructor(config: KoolbaseConfig, getUserAccessToken?: () => string | null);
5
6
  deploy(options: DeployOptions): Promise<DeployResult>;
6
7
  invoke(name: string, body?: Record<string, unknown>): Promise<FunctionInvokeResult>;
7
8
  }
package/dist/functions.js CHANGED
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.KoolbaseFunctions = void 0;
4
4
  const types_1 = require("./types");
5
5
  class KoolbaseFunctions {
6
- constructor(config) {
6
+ constructor(config, getUserAccessToken) {
7
7
  this.config = config;
8
+ this.getUserAccessToken = getUserAccessToken;
8
9
  }
9
10
  // ─── Deploy ────────────────────────────────────────────────────────────────
10
11
  async deploy(options) {
@@ -40,12 +41,17 @@ class KoolbaseFunctions {
40
41
  }
41
42
  // ─── Invoke ────────────────────────────────────────────────────────────────
42
43
  async invoke(name, body) {
44
+ const headers = {
45
+ 'Content-Type': 'application/json',
46
+ 'x-api-key': this.config.publicKey,
47
+ };
48
+ const userToken = this.getUserAccessToken?.();
49
+ if (userToken) {
50
+ headers['Authorization'] = `Bearer ${userToken}`;
51
+ }
43
52
  const res = await fetch(`${this.config.baseUrl}/v1/sdk/functions/${name}`, {
44
53
  method: 'POST',
45
- headers: {
46
- 'Content-Type': 'application/json',
47
- 'x-api-key': this.config.publicKey,
48
- },
54
+ headers,
49
55
  body: JSON.stringify({ body: body ?? {} }),
50
56
  });
51
57
  const data = await res.json().catch(() => null);
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ import { KoolbaseRealtime } from './realtime';
17
17
  import { KoolbaseStorage } from './storage';
18
18
  import { KoolbaseConfig, VersionCheckResult } from './types';
19
19
  export * from './types';
20
+ export * from './auth-errors';
20
21
  export { KoolbaseAuth, KoolbaseDatabase, KoolbaseFlags, KoolbaseFunctions, KoolbaseRealtime, KoolbaseStorage };
21
22
  export declare const Koolbase: {
22
23
  initialize(config: KoolbaseConfig): Promise<void>;
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ Object.defineProperty(exports, "KoolbaseRealtime", { enumerable: true, get: func
44
44
  const storage_1 = require("./storage");
45
45
  Object.defineProperty(exports, "KoolbaseStorage", { enumerable: true, get: function () { return storage_1.KoolbaseStorage; } });
46
46
  __exportStar(require("./types"), exports);
47
+ __exportStar(require("./auth-errors"), exports);
47
48
  let _auth = null;
48
49
  let _db = null;
49
50
  let _storage = null;
@@ -68,7 +69,7 @@ exports.Koolbase = {
68
69
  _db = new database_1.KoolbaseDatabase(config, () => _auth?.currentUser?.id ?? null);
69
70
  _storage = new storage_1.KoolbaseStorage(config, () => _auth?.accessToken ?? null);
70
71
  _realtime = new realtime_1.KoolbaseRealtime(config);
71
- _functions = new functions_1.KoolbaseFunctions(config);
72
+ _functions = new functions_1.KoolbaseFunctions(config, () => _auth?.accessToken ?? null);
72
73
  _flags = new flags_1.KoolbaseFlags(config, 'rn-device');
73
74
  _codePush = new code_push_1.KoolbaseCodePush(config, config.codePushChannel ?? 'stable');
74
75
  // Initialize code push — loads cached bundle then checks in background
package/dist/types.d.ts CHANGED
@@ -9,6 +9,8 @@ export interface KoolbaseConfig {
9
9
  export interface KoolbaseUser {
10
10
  id: string;
11
11
  email: string;
12
+ phoneNumber?: string;
13
+ phoneVerified?: boolean;
12
14
  fullName?: string;
13
15
  avatarUrl?: string;
14
16
  verified: boolean;
@@ -28,6 +30,24 @@ export interface LoginParams {
28
30
  email: string;
29
31
  password: string;
30
32
  }
33
+ export interface SendOtpParams {
34
+ phoneNumber: string;
35
+ }
36
+ export interface VerifyOtpParams {
37
+ phoneNumber: string;
38
+ code: string;
39
+ }
40
+ export interface LinkPhoneParams {
41
+ phoneNumber: string;
42
+ code: string;
43
+ }
44
+ export interface OtpSendResult {
45
+ expiresAt: string;
46
+ }
47
+ export interface PhoneVerifyResult {
48
+ session: KoolbaseSession;
49
+ isNewUser: boolean;
50
+ }
31
51
  export interface KoolbaseRecord {
32
52
  id: string;
33
53
  projectId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techfinityedge/koolbase-react-native",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "description": "React Native SDK for Koolbase — auth, database, storage, realtime, feature flags, and functions in one package.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",