@techfinityedge/koolbase-react-native 1.10.0 → 1.11.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
@@ -12,15 +12,13 @@ Auth, database, storage, realtime, functions, feature flags, remote config, vers
12
12
  ## Get started in 2 minutes
13
13
 
14
14
  1. Create a free account at [app.koolbase.com](https://app.koolbase.com)
15
-
16
15
  2. Create a project and copy your public key from Environments
17
-
18
16
  3. Add the SDK:
19
17
 
20
18
  ```bash
21
- npm install @techfinityedge/koolbase-react-native@^1.8.0
19
+ npm install @techfinityedge/koolbase-react-native@^1.10.0
22
20
  # or
23
- yarn add @techfinityedge/koolbase-react-native@^1.8.0
21
+ yarn add @techfinityedge/koolbase-react-native@^1.10.0
24
22
  ```
25
23
 
26
24
  **4. Initialize at app startup:**
@@ -40,7 +38,7 @@ That's it. Every feature below is now available via `Koolbase.*`.
40
38
 
41
39
  ## Authentication
42
40
 
43
- Email + password, Google, Apple, and phone + OTP — out of the box.
41
+ Email + password, Apple Sign-In, Google Sign-In, and phone + OTP — out of the box.
44
42
 
45
43
  ```typescript
46
44
  // Register
@@ -57,30 +55,60 @@ await Koolbase.auth.logout();
57
55
 
58
56
  // Password reset
59
57
  await Koolbase.auth.forgotPassword('user@example.com');
58
+
59
+ // Listen to auth state changes (fires immediately with current state)
60
+ const unsubscribe = Koolbase.auth.onAuthStateChange((user) => {
61
+ console.log(user ? 'signed in' : 'signed out');
62
+ });
60
63
  ```
61
64
 
62
- ### OAuth — Google & Apple
65
+ ### OAuth — Apple
66
+
67
+ Apple Sign-In uses the native authentication flow via `@invertase/react-native-apple-authentication` as a peer dependency:
63
68
 
64
69
  ```typescript
65
- // Google
66
- await Koolbase.auth.signInWithGoogle({ idToken: googleIdToken });
70
+ import appleAuth from '@invertase/react-native-apple-authentication';
71
+ import { Koolbase } from '@techfinityedge/koolbase-react-native';
72
+
73
+ const response = await appleAuth.performRequest({
74
+ requestedOperation: appleAuth.Operation.LOGIN,
75
+ requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
76
+ });
77
+
78
+ const session = await Koolbase.auth.signInWithApple({
79
+ identityToken: response.identityToken!,
80
+ nonce: response.nonce,
81
+ fullName: response.fullName
82
+ ? {
83
+ givenName: response.fullName.givenName ?? undefined,
84
+ familyName: response.fullName.familyName ?? undefined,
85
+ }
86
+ : undefined,
87
+ });
67
88
  ```
68
89
 
69
- Apple uses the native authentication flow via `@invertase/react-native-apple-authentication` as a peer dependency:
90
+ Configure Apple Sign-In for your environment with your iOS app's Bundle ID. Full setup guide at [docs.koolbase.com/auth/oauth](https://docs.koolbase.com/auth/oauth).
91
+
92
+ ### OAuth — Google
93
+
94
+ Google Sign-In uses the native authentication flow via `@react-native-google-signin/google-signin` as a peer dependency:
70
95
 
71
96
  ```typescript
72
- import { KoolbaseAppleAuth } from '@techfinityedge/koolbase-react-native';
73
- import { appleAuth } from '@invertase/react-native-apple-authentication';
74
-
75
- const session = await KoolbaseAppleAuth.signIn(async () => {
76
- return await appleAuth.performRequest({
77
- requestedOperation: appleAuth.Operation.LOGIN,
78
- requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
79
- });
97
+ import { GoogleSignin } from '@react-native-google-signin/google-signin';
98
+ import { Koolbase } from '@techfinityedge/koolbase-react-native';
99
+
100
+ GoogleSignin.configure({
101
+ webClientId: '<your-web-client-id>.apps.googleusercontent.com',
102
+ });
103
+
104
+ const userInfo = await GoogleSignin.signIn();
105
+
106
+ const session = await Koolbase.auth.signInWithGoogle({
107
+ idToken: userInfo.idToken!,
80
108
  });
81
109
  ```
82
110
 
83
- Full setup guide at [docs.koolbase.com/auth/oauth](https://docs.koolbase.com/auth/oauth).
111
+ Configure Google Sign-In for your environment with the OAuth client IDs from Google Cloud Console (typically one each for iOS, Android, and web). Full setup guide at [docs.koolbase.com/auth/oauth](https://docs.koolbase.com/auth/oauth).
84
112
 
85
113
  ### Phone + OTP
86
114
 
@@ -150,6 +178,7 @@ const { url } = await Koolbase.storage.upload({
150
178
  });
151
179
 
152
180
  const downloadUrl = await Koolbase.storage.getDownloadUrl('avatars', `user-${userId}.jpg`);
181
+
153
182
  await Koolbase.storage.delete('avatars', `user-${userId}.jpg`);
154
183
  ```
155
184
 
@@ -177,11 +206,10 @@ Invoke deployed serverless functions. When a user is signed in via `Koolbase.aut
177
206
  const result = await Koolbase.functions.invoke('send-welcome-email', {
178
207
  userId: '123',
179
208
  });
180
-
181
209
  if (result.success) console.log(result.data);
182
210
  ```
183
211
 
184
- Inside the function (Deno runtime), read the caller:
212
+ Inside the function, read the caller:
185
213
 
186
214
  ```typescript
187
215
  export async function handler(ctx) {
@@ -325,20 +353,18 @@ await Koolbase.messaging.send({
325
353
 
326
354
  ## What's included
327
355
 
328
- | Feature | Koolbase | Firebase | Supabase |
329
- | --- | --- | --- | --- |
330
- | TypeScript SDK | Yes | Yes | Yes |
331
- | Feature flags | Yes | — | — |
332
- | Remote config | Yes | Yes | — |
333
- | Version enforcement | Yes | — | — |
334
- | Offline-first database | Yes | Yes | — |
335
- | Code push | Yes | | |
336
- | Logic engine (flows OTA) | Yes | — | — |
337
- | Analytics | Yes | Yes | — |
338
- | Cloud Messaging | Yes | Yes | — |
339
- | Sign in with Apple | Yes | Yes | Yes |
340
- | Phone + OTP | Yes | Yes | Yes |
341
- | Authenticated functions (`ctx.auth`) | Yes | Yes | Yes |
356
+ - Authentication: email + password, Apple Sign-In, phone + OTP
357
+ - Database with offline-first cache, realtime subscriptions, and populate
358
+ - Storage with download URLs
359
+ - Realtime subscriptions over WebSocket
360
+ - Authenticated functions (`ctx.auth` exposes the caller automatically)
361
+ - Feature flags and remote config
362
+ - Version enforcement
363
+ - Code push (config + flag overrides + directives, no store release)
364
+ - Logic engine (conditional flows as data, updatable OTA)
365
+ - Analytics (DAU/WAU/MAU, funnels, retention)
366
+ - Cloud Messaging (FCM token registration, targeted send, broadcast)
367
+ - TypeScript-native with full type definitions
342
368
 
343
369
  ---
344
370
 
@@ -106,3 +106,12 @@ export declare class AppleEmailRequiredError extends KoolbaseAuthError {
106
106
  export declare class OAuthEmailConflictError extends KoolbaseAuthError {
107
107
  constructor();
108
108
  }
109
+ export declare class GoogleSignInNotConfiguredError extends KoolbaseAuthError {
110
+ constructor();
111
+ }
112
+ export declare class InvalidGoogleTokenError extends KoolbaseAuthError {
113
+ constructor();
114
+ }
115
+ export declare class GoogleEmailRequiredError extends KoolbaseAuthError {
116
+ constructor();
117
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OAuthEmailConflictError = exports.AppleEmailRequiredError = exports.InvalidAppleTokenError = exports.AppleSignInNotConfiguredError = exports.SmsConfigMissingError = exports.PhoneAlreadyLinkedError = exports.OtpRateLimitError = exports.OtpMaxAttemptsError = exports.OtpInvalidError = exports.OtpExpiredError = exports.InvalidPhoneNumberError = exports.NetworkError = exports.RateLimitError = exports.UnlockTokenInvalidError = exports.AccountLockedError = exports.TokenRevokedError = exports.SessionExpiredError = exports.WeakPasswordError = exports.UserDisabledError = exports.EmailAlreadyInUseError = exports.InvalidCredentialsError = exports.KoolbaseAuthError = void 0;
3
+ exports.GoogleEmailRequiredError = exports.InvalidGoogleTokenError = exports.GoogleSignInNotConfiguredError = exports.OAuthEmailConflictError = exports.AppleEmailRequiredError = exports.InvalidAppleTokenError = exports.AppleSignInNotConfiguredError = exports.SmsConfigMissingError = exports.PhoneAlreadyLinkedError = exports.OtpRateLimitError = exports.OtpMaxAttemptsError = exports.OtpInvalidError = exports.OtpExpiredError = exports.InvalidPhoneNumberError = exports.NetworkError = exports.RateLimitError = exports.UnlockTokenInvalidError = exports.AccountLockedError = exports.TokenRevokedError = exports.SessionExpiredError = exports.WeakPasswordError = exports.UserDisabledError = exports.EmailAlreadyInUseError = exports.InvalidCredentialsError = exports.KoolbaseAuthError = void 0;
4
4
  /**
5
5
  * Base error type for all Koolbase auth errors. Catchable via
6
6
  * `instanceof KoolbaseAuthError` to handle any auth-related failure
@@ -224,3 +224,27 @@ class OAuthEmailConflictError extends KoolbaseAuthError {
224
224
  }
225
225
  }
226
226
  exports.OAuthEmailConflictError = OAuthEmailConflictError;
227
+ class GoogleSignInNotConfiguredError extends KoolbaseAuthError {
228
+ constructor() {
229
+ super('Google Sign-In is not configured for this environment', 'google_not_configured');
230
+ this.name = 'GoogleSignInNotConfiguredError';
231
+ Object.setPrototypeOf(this, GoogleSignInNotConfiguredError.prototype);
232
+ }
233
+ }
234
+ exports.GoogleSignInNotConfiguredError = GoogleSignInNotConfiguredError;
235
+ class InvalidGoogleTokenError extends KoolbaseAuthError {
236
+ constructor() {
237
+ super('Invalid Google identity token', 'invalid_google_token');
238
+ this.name = 'InvalidGoogleTokenError';
239
+ Object.setPrototypeOf(this, InvalidGoogleTokenError.prototype);
240
+ }
241
+ }
242
+ exports.InvalidGoogleTokenError = InvalidGoogleTokenError;
243
+ class GoogleEmailRequiredError extends KoolbaseAuthError {
244
+ constructor() {
245
+ super('Google did not return email for this sign-in. Ensure the email scope is requested in the native flow.', 'google_email_required');
246
+ this.name = 'GoogleEmailRequiredError';
247
+ Object.setPrototypeOf(this, GoogleEmailRequiredError.prototype);
248
+ }
249
+ }
250
+ exports.GoogleEmailRequiredError = GoogleEmailRequiredError;
package/dist/auth.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AuthStateListener, KoolbaseConfig, KoolbaseSession, KoolbaseUser, LinkPhoneParams, LoginParams, OtpSendResult, PhoneVerifyResult, RegisterParams, RestoreResult, SendOtpParams, SignInWithAppleParams, VerifyOtpParams } from './types';
2
+ import type { SignInWithGoogleParams } from './types';
2
3
  export declare class KoolbaseAuth {
3
4
  private config;
4
5
  private storage;
@@ -85,6 +86,35 @@ export declare class KoolbaseAuth {
85
86
  * but auto-link rule blocked (409).
86
87
  */
87
88
  signInWithApple(params: SignInWithAppleParams): Promise<KoolbaseSession>;
89
+ /**
90
+ * Sign in with Google using an idToken from a native Google Sign-In SDK.
91
+ *
92
+ * The SDK is library-agnostic — use any native Google Sign-In package
93
+ * (`@react-native-google-signin/google-signin`, etc.) and pass the
94
+ * resulting `idToken`. Google embeds the user's name and email in the
95
+ * idToken itself, so this method does not take a `fullName` parameter
96
+ * (unlike `signInWithApple`).
97
+ *
98
+ * On success the session is persisted via the configured storage and
99
+ * `onAuthStateChange` fires with the resolved user.
100
+ *
101
+ * @throws GoogleSignInNotConfiguredError when Google is not enabled
102
+ * in the OAuth config for this environment (400).
103
+ * @throws InvalidGoogleTokenError when the token signature, audience,
104
+ * expiry, replay, or nonce check failed server-side (401).
105
+ * @throws UserDisabledError when the account flag is set to disabled (403).
106
+ * @throws GoogleEmailRequiredError when Google did not return email
107
+ * for a new-account sign-in (400).
108
+ * @throws OAuthEmailConflictError when email matches existing user
109
+ * but auto-link rule blocked (409).
110
+ */
111
+ signInWithGoogle(params: SignInWithGoogleParams): Promise<KoolbaseSession>;
112
+ /**
113
+ * Parses a /v1/sdk/auth/oauth/google response. Distinct from
114
+ * parseSessionResponse and parseAppleSessionResponse because OAuth
115
+ * error semantics differ per-provider.
116
+ */
117
+ private parseGoogleSessionResponse;
88
118
  /**
89
119
  * Parses a /v1/sdk/auth/oauth/apple response. Distinct from
90
120
  * parseSessionResponse because OAuth error semantics differ from
package/dist/auth.js CHANGED
@@ -259,6 +259,85 @@ class KoolbaseAuth {
259
259
  await this.setSessionInternal(session);
260
260
  return session;
261
261
  }
262
+ /**
263
+ * Sign in with Google using an idToken from a native Google Sign-In SDK.
264
+ *
265
+ * The SDK is library-agnostic — use any native Google Sign-In package
266
+ * (`@react-native-google-signin/google-signin`, etc.) and pass the
267
+ * resulting `idToken`. Google embeds the user's name and email in the
268
+ * idToken itself, so this method does not take a `fullName` parameter
269
+ * (unlike `signInWithApple`).
270
+ *
271
+ * On success the session is persisted via the configured storage and
272
+ * `onAuthStateChange` fires with the resolved user.
273
+ *
274
+ * @throws GoogleSignInNotConfiguredError when Google is not enabled
275
+ * in the OAuth config for this environment (400).
276
+ * @throws InvalidGoogleTokenError when the token signature, audience,
277
+ * expiry, replay, or nonce check failed server-side (401).
278
+ * @throws UserDisabledError when the account flag is set to disabled (403).
279
+ * @throws GoogleEmailRequiredError when Google did not return email
280
+ * for a new-account sign-in (400).
281
+ * @throws OAuthEmailConflictError when email matches existing user
282
+ * but auto-link rule blocked (409).
283
+ */
284
+ async signInWithGoogle(params) {
285
+ const body = {
286
+ identity_token: params.idToken,
287
+ };
288
+ if (params.nonce && params.nonce.length > 0) {
289
+ body.nonce = params.nonce;
290
+ }
291
+ const res = await this.authRequest('/v1/sdk/auth/oauth/google', {
292
+ method: 'POST',
293
+ body,
294
+ });
295
+ const session = await this.parseGoogleSessionResponse(res);
296
+ await this.setSessionInternal(session);
297
+ return session;
298
+ }
299
+ /**
300
+ * Parses a /v1/sdk/auth/oauth/google response. Distinct from
301
+ * parseSessionResponse and parseAppleSessionResponse because OAuth
302
+ * error semantics differ per-provider.
303
+ */
304
+ async parseGoogleSessionResponse(res) {
305
+ if (res.status === 200) {
306
+ const data = await res.json();
307
+ return {
308
+ accessToken: data.access_token,
309
+ refreshToken: data.refresh_token,
310
+ expiresAt: data.expires_at,
311
+ user: this.mapUser(data.user),
312
+ };
313
+ }
314
+ let errorMessage = '';
315
+ try {
316
+ const data = await res.json();
317
+ errorMessage = data?.error ?? '';
318
+ }
319
+ catch {
320
+ // best-effort error message extraction
321
+ }
322
+ if (res.status === 400) {
323
+ if (errorMessage.includes('not configured')) {
324
+ throw new auth_errors_1.GoogleSignInNotConfiguredError();
325
+ }
326
+ if (errorMessage.includes('did not return email')) {
327
+ throw new auth_errors_1.GoogleEmailRequiredError();
328
+ }
329
+ throw new auth_errors_1.KoolbaseAuthError(`google sign-in failed: ${errorMessage}`, 'google_signin_failed');
330
+ }
331
+ if (res.status === 401)
332
+ throw new auth_errors_1.InvalidGoogleTokenError();
333
+ if (res.status === 403)
334
+ throw new auth_errors_1.UserDisabledError();
335
+ if (res.status === 409)
336
+ throw new auth_errors_1.OAuthEmailConflictError();
337
+ if (res.status === 429)
338
+ throw new auth_errors_1.RateLimitError(errorMessage);
339
+ throw new auth_errors_1.KoolbaseAuthError(`google sign-in failed: ${res.status} ${errorMessage}`, `google_signin_http_${res.status}`);
340
+ }
262
341
  /**
263
342
  * Parses a /v1/sdk/auth/oauth/apple response. Distinct from
264
343
  * parseSessionResponse because OAuth error semantics differ from
@@ -4,7 +4,7 @@
4
4
  * version-conditional logic (deprecation warnings, schema migrations,
5
5
  * feature flags). Must match the `version` field in package.json.
6
6
  */
7
- export declare const koolbaseSdkVersion = "1.10.0";
7
+ export declare const koolbaseSdkVersion = "1.11.0";
8
8
  /**
9
9
  * Builds device-identifying headers attached to every Koolbase auth
10
10
  * request. Mirrors the Flutter SDK's `DeviceMetadata` for parity. Apps
@@ -9,7 +9,7 @@ const auth_storage_1 = require("./auth-storage");
9
9
  * version-conditional logic (deprecation warnings, schema migrations,
10
10
  * feature flags). Must match the `version` field in package.json.
11
11
  */
12
- exports.koolbaseSdkVersion = '1.10.0';
12
+ exports.koolbaseSdkVersion = '1.11.0';
13
13
  /**
14
14
  * Generate a UUIDv4-shaped string for use as a stable per-install
15
15
  * device label. Not cryptographically secure — this is a label, not a
package/dist/types.d.ts CHANGED
@@ -224,3 +224,15 @@ export interface SignInWithAppleParams {
224
224
  nonce?: string;
225
225
  fullName?: AppleFullName;
226
226
  }
227
+ /**
228
+ * Parameters for `KoolbaseAuth.signInWithGoogle`. The SDK is
229
+ * library-agnostic — `idToken` should come from any native Google
230
+ * Sign-In package (e.g. `@react-native-google-signin/google-signin`).
231
+ *
232
+ * Unlike Apple, Google embeds the user's name and email in the idToken
233
+ * itself, so no separate `fullName` parameter is needed.
234
+ */
235
+ export interface SignInWithGoogleParams {
236
+ idToken: string;
237
+ nonce?: string;
238
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techfinityedge/koolbase-react-native",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "React Native SDK for Koolbase \u2014 auth, database, storage, realtime, feature flags, and functions in one package.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",