@techfinityedge/koolbase-react-native 1.8.0 → 1.10.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 +114 -60
- package/dist/auth-errors.d.ts +83 -0
- package/dist/auth-errors.js +159 -1
- package/dist/auth-storage.d.ts +26 -0
- package/dist/auth-storage.js +105 -0
- package/dist/auth.d.ts +115 -8
- package/dist/auth.js +489 -67
- package/dist/device-metadata.d.ts +36 -0
- package/dist/device-metadata.js +102 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +27 -1
- package/dist/types.d.ts +84 -0
- package/dist/types.js +16 -1
- package/package.json +11 -4
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeviceMetadata = exports.koolbaseSdkVersion = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const auth_storage_1 = require("./auth-storage");
|
|
6
|
+
/**
|
|
7
|
+
* Koolbase React Native SDK version. Sent in the `x-koolbase-sdk-version`
|
|
8
|
+
* header on every authenticated request so the server can route
|
|
9
|
+
* version-conditional logic (deprecation warnings, schema migrations,
|
|
10
|
+
* feature flags). Must match the `version` field in package.json.
|
|
11
|
+
*/
|
|
12
|
+
exports.koolbaseSdkVersion = '1.10.0';
|
|
13
|
+
/**
|
|
14
|
+
* Generate a UUIDv4-shaped string for use as a stable per-install
|
|
15
|
+
* device label. Not cryptographically secure — this is a label, not a
|
|
16
|
+
* security primitive. Avoids pulling in a crypto-grade UUID dependency.
|
|
17
|
+
*/
|
|
18
|
+
function generateDeviceLabel() {
|
|
19
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
20
|
+
const r = (Math.random() * 16) | 0;
|
|
21
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
22
|
+
return v.toString(16);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Builds device-identifying headers attached to every Koolbase auth
|
|
27
|
+
* request. Mirrors the Flutter SDK's `DeviceMetadata` for parity. Apps
|
|
28
|
+
* with privacy concerns can swap in a custom storage adapter to avoid
|
|
29
|
+
* persisting the device label.
|
|
30
|
+
*
|
|
31
|
+
* Headers emitted:
|
|
32
|
+
* - User-Agent: koolbase-react-native/<sdk> (<platform> <version>)
|
|
33
|
+
* - x-koolbase-sdk: react-native
|
|
34
|
+
* - x-koolbase-sdk-version: <koolbaseSdkVersion>
|
|
35
|
+
* - x-koolbase-platform: ios | android | web | etc.
|
|
36
|
+
* - x-koolbase-platform-version: numeric SDK level or OS version string
|
|
37
|
+
* - x-koolbase-app-version: from KoolbaseConfig.appVersion or 'unknown'
|
|
38
|
+
* - x-koolbase-device-label: persistent UUID per install
|
|
39
|
+
*/
|
|
40
|
+
class DeviceMetadata {
|
|
41
|
+
constructor(appVersion) {
|
|
42
|
+
this.cached = null;
|
|
43
|
+
this.ephemeralLabel = null;
|
|
44
|
+
this.appVersion = appVersion ?? 'unknown';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build (or return cached) device headers. The first call may perform
|
|
48
|
+
* an async keychain read to look up the persisted device label;
|
|
49
|
+
* subsequent calls return the in-memory cache synchronously via the
|
|
50
|
+
* returned Promise.
|
|
51
|
+
*/
|
|
52
|
+
async build() {
|
|
53
|
+
if (this.cached)
|
|
54
|
+
return this.cached;
|
|
55
|
+
const platform = String(react_native_1.Platform.OS);
|
|
56
|
+
const platformVersion = String(react_native_1.Platform.Version);
|
|
57
|
+
const deviceLabel = await this.getOrCreateDeviceLabel();
|
|
58
|
+
const userAgent = `koolbase-react-native/${exports.koolbaseSdkVersion} (${platform} ${platformVersion})`;
|
|
59
|
+
this.cached = {
|
|
60
|
+
'User-Agent': userAgent,
|
|
61
|
+
'x-koolbase-sdk': 'react-native',
|
|
62
|
+
'x-koolbase-sdk-version': exports.koolbaseSdkVersion,
|
|
63
|
+
'x-koolbase-platform': platform,
|
|
64
|
+
'x-koolbase-platform-version': platformVersion,
|
|
65
|
+
'x-koolbase-app-version': this.appVersion,
|
|
66
|
+
'x-koolbase-device-label': deviceLabel,
|
|
67
|
+
};
|
|
68
|
+
return this.cached;
|
|
69
|
+
}
|
|
70
|
+
async getOrCreateDeviceLabel() {
|
|
71
|
+
// No keychain available → ephemeral per-session label.
|
|
72
|
+
// (Better than no label — still useful for in-session debugging.)
|
|
73
|
+
if (!(0, auth_storage_1.isKeychainAvailable)()) {
|
|
74
|
+
if (!this.ephemeralLabel) {
|
|
75
|
+
this.ephemeralLabel = generateDeviceLabel();
|
|
76
|
+
}
|
|
77
|
+
return this.ephemeralLabel;
|
|
78
|
+
}
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
80
|
+
const Keychain = require('react-native-keychain');
|
|
81
|
+
const service = 'koolbase_device_label_v1';
|
|
82
|
+
try {
|
|
83
|
+
const existing = await Keychain.getGenericPassword({ service });
|
|
84
|
+
if (existing && existing.password) {
|
|
85
|
+
return existing.password;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// fall through to create
|
|
90
|
+
}
|
|
91
|
+
const newLabel = generateDeviceLabel();
|
|
92
|
+
try {
|
|
93
|
+
await Keychain.setGenericPassword('device', newLabel, { service });
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Persistence failed — return the generated label anyway, but
|
|
97
|
+
// don't cache it as ephemeral since future requests may persist.
|
|
98
|
+
}
|
|
99
|
+
return newLabel;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.DeviceMetadata = DeviceMetadata;
|
package/dist/index.d.ts
CHANGED
|
@@ -36,3 +36,8 @@ export declare const Koolbase: {
|
|
|
36
36
|
readonly messaging: KoolbaseMessaging;
|
|
37
37
|
checkVersion(currentVersion: string): VersionCheckResult;
|
|
38
38
|
};
|
|
39
|
+
export { koolbaseSdkVersion } from './device-metadata';
|
|
40
|
+
export { RestoreResult } from './types';
|
|
41
|
+
export type { AuthStateListener, FetchLike, KoolbaseAuthStorage } from './types';
|
|
42
|
+
export { SecureAuthStorage } from './auth-storage';
|
|
43
|
+
export { KoolbaseAuthError, InvalidCredentialsError, EmailAlreadyInUseError, UserDisabledError, WeakPasswordError, SessionExpiredError, TokenRevokedError, AccountLockedError, UnlockTokenInvalidError, RateLimitError, NetworkError, InvalidPhoneNumberError, OtpExpiredError, OtpInvalidError, OtpMaxAttemptsError, OtpRateLimitError, PhoneAlreadyLinkedError, SmsConfigMissingError, } from './auth-errors';
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.Koolbase = exports.KoolbaseStorage = exports.KoolbaseRealtime = exports.KoolbaseFunctions = exports.KoolbaseFlags = exports.KoolbaseDatabase = exports.KoolbaseAuth = exports.KoolbaseCodePush = exports.KoolbaseAnalytics = exports.KoolbaseAppleAuth = exports.KoolbaseMessaging = void 0;
|
|
20
|
+
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 = exports.SecureAuthStorage = exports.RestoreResult = exports.koolbaseSdkVersion = exports.Koolbase = exports.KoolbaseStorage = exports.KoolbaseRealtime = exports.KoolbaseFunctions = exports.KoolbaseFlags = exports.KoolbaseDatabase = exports.KoolbaseAuth = exports.KoolbaseCodePush = exports.KoolbaseAnalytics = exports.KoolbaseAppleAuth = exports.KoolbaseMessaging = void 0;
|
|
21
21
|
const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
|
|
22
22
|
const auth_1 = require("./auth");
|
|
23
23
|
Object.defineProperty(exports, "KoolbaseAuth", { enumerable: true, get: function () { return auth_1.KoolbaseAuth; } });
|
|
@@ -164,3 +164,29 @@ exports.Koolbase = {
|
|
|
164
164
|
return _flags.checkVersion(currentVersion);
|
|
165
165
|
},
|
|
166
166
|
};
|
|
167
|
+
// v1.9.0 additions
|
|
168
|
+
var device_metadata_1 = require("./device-metadata");
|
|
169
|
+
Object.defineProperty(exports, "koolbaseSdkVersion", { enumerable: true, get: function () { return device_metadata_1.koolbaseSdkVersion; } });
|
|
170
|
+
var types_1 = require("./types");
|
|
171
|
+
Object.defineProperty(exports, "RestoreResult", { enumerable: true, get: function () { return types_1.RestoreResult; } });
|
|
172
|
+
var auth_storage_1 = require("./auth-storage");
|
|
173
|
+
Object.defineProperty(exports, "SecureAuthStorage", { enumerable: true, get: function () { return auth_storage_1.SecureAuthStorage; } });
|
|
174
|
+
var auth_errors_1 = require("./auth-errors");
|
|
175
|
+
Object.defineProperty(exports, "KoolbaseAuthError", { enumerable: true, get: function () { return auth_errors_1.KoolbaseAuthError; } });
|
|
176
|
+
Object.defineProperty(exports, "InvalidCredentialsError", { enumerable: true, get: function () { return auth_errors_1.InvalidCredentialsError; } });
|
|
177
|
+
Object.defineProperty(exports, "EmailAlreadyInUseError", { enumerable: true, get: function () { return auth_errors_1.EmailAlreadyInUseError; } });
|
|
178
|
+
Object.defineProperty(exports, "UserDisabledError", { enumerable: true, get: function () { return auth_errors_1.UserDisabledError; } });
|
|
179
|
+
Object.defineProperty(exports, "WeakPasswordError", { enumerable: true, get: function () { return auth_errors_1.WeakPasswordError; } });
|
|
180
|
+
Object.defineProperty(exports, "SessionExpiredError", { enumerable: true, get: function () { return auth_errors_1.SessionExpiredError; } });
|
|
181
|
+
Object.defineProperty(exports, "TokenRevokedError", { enumerable: true, get: function () { return auth_errors_1.TokenRevokedError; } });
|
|
182
|
+
Object.defineProperty(exports, "AccountLockedError", { enumerable: true, get: function () { return auth_errors_1.AccountLockedError; } });
|
|
183
|
+
Object.defineProperty(exports, "UnlockTokenInvalidError", { enumerable: true, get: function () { return auth_errors_1.UnlockTokenInvalidError; } });
|
|
184
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return auth_errors_1.RateLimitError; } });
|
|
185
|
+
Object.defineProperty(exports, "NetworkError", { enumerable: true, get: function () { return auth_errors_1.NetworkError; } });
|
|
186
|
+
Object.defineProperty(exports, "InvalidPhoneNumberError", { enumerable: true, get: function () { return auth_errors_1.InvalidPhoneNumberError; } });
|
|
187
|
+
Object.defineProperty(exports, "OtpExpiredError", { enumerable: true, get: function () { return auth_errors_1.OtpExpiredError; } });
|
|
188
|
+
Object.defineProperty(exports, "OtpInvalidError", { enumerable: true, get: function () { return auth_errors_1.OtpInvalidError; } });
|
|
189
|
+
Object.defineProperty(exports, "OtpMaxAttemptsError", { enumerable: true, get: function () { return auth_errors_1.OtpMaxAttemptsError; } });
|
|
190
|
+
Object.defineProperty(exports, "OtpRateLimitError", { enumerable: true, get: function () { return auth_errors_1.OtpRateLimitError; } });
|
|
191
|
+
Object.defineProperty(exports, "PhoneAlreadyLinkedError", { enumerable: true, get: function () { return auth_errors_1.PhoneAlreadyLinkedError; } });
|
|
192
|
+
Object.defineProperty(exports, "SmsConfigMissingError", { enumerable: true, get: function () { return auth_errors_1.SmsConfigMissingError; } });
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,24 @@ export interface KoolbaseConfig {
|
|
|
5
5
|
analyticsEnabled?: boolean;
|
|
6
6
|
appVersion?: string;
|
|
7
7
|
messagingEnabled?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Optional custom storage adapter for persisting auth state. If omitted,
|
|
10
|
+
* the SDK uses SecureAuthStorage backed by react-native-keychain (must
|
|
11
|
+
* be installed). For Expo Go or custom secure backends, provide your
|
|
12
|
+
* own KoolbaseAuthStorage implementation.
|
|
13
|
+
*/
|
|
14
|
+
authStorage?: KoolbaseAuthStorage;
|
|
15
|
+
/**
|
|
16
|
+
* Per-request timeout in milliseconds for auth endpoints. Default 10000.
|
|
17
|
+
* On timeout, fetch rejects with an AbortError. restoreSession() treats
|
|
18
|
+
* this as Offline (preserves optimistic state).
|
|
19
|
+
*/
|
|
20
|
+
authTimeout?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Injectable fetch implementation. Defaults to the global fetch. Useful
|
|
23
|
+
* for testing (mock fetch), corporate proxies, or instrumented HTTP.
|
|
24
|
+
*/
|
|
25
|
+
fetch?: FetchLike;
|
|
8
26
|
}
|
|
9
27
|
export interface KoolbaseUser {
|
|
10
28
|
id: string;
|
|
@@ -19,8 +37,51 @@ export interface KoolbaseUser {
|
|
|
19
37
|
export interface KoolbaseSession {
|
|
20
38
|
accessToken: string;
|
|
21
39
|
refreshToken: string;
|
|
40
|
+
/** ISO 8601 timestamp when accessToken expires; from server response. */
|
|
41
|
+
expiresAt: string;
|
|
22
42
|
user: KoolbaseUser;
|
|
23
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Abstract storage interface for persisting authentication state.
|
|
46
|
+
*
|
|
47
|
+
* The SDK ships with SecureAuthStorage (react-native-keychain) as the
|
|
48
|
+
* default. Apps with custom requirements — Expo Go (where keychain is
|
|
49
|
+
* unavailable), compliant encryption layers, or in-memory test mocks —
|
|
50
|
+
* can implement this interface and inject it via KoolbaseConfig.authStorage.
|
|
51
|
+
*/
|
|
52
|
+
export interface KoolbaseAuthStorage {
|
|
53
|
+
saveSession(session: KoolbaseSession): Promise<void>;
|
|
54
|
+
readSession(): Promise<KoolbaseSession | null>;
|
|
55
|
+
clear(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Result of KoolbaseAuth.restoreSession(). Apps should branch on this:
|
|
59
|
+
* - NoSession → show login screen
|
|
60
|
+
* - Restored → show authenticated UI
|
|
61
|
+
* - Expired → show login screen with "session expired" message
|
|
62
|
+
* - Offline → show authenticated UI optimistically; API calls will
|
|
63
|
+
* fail until network is reachable
|
|
64
|
+
*/
|
|
65
|
+
export declare enum RestoreResult {
|
|
66
|
+
NoSession = "no_session",
|
|
67
|
+
Restored = "restored",
|
|
68
|
+
Expired = "expired",
|
|
69
|
+
Offline = "offline"
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Callback invoked when authentication state changes. Receives the
|
|
73
|
+
* current user, or null when signed out. Listeners fire on login,
|
|
74
|
+
* register, refresh, session restoration, logout, setSession, and
|
|
75
|
+
* linkPhone. Errors thrown from a listener are swallowed so one
|
|
76
|
+
* broken listener cannot break propagation to others.
|
|
77
|
+
*/
|
|
78
|
+
export type AuthStateListener = (user: KoolbaseUser | null) => void;
|
|
79
|
+
/**
|
|
80
|
+
* Drop-in replacement for the global `fetch` function. Inject via
|
|
81
|
+
* KoolbaseConfig.fetch for testing (mock fetch), proxying, or
|
|
82
|
+
* monitoring. Matches the standard fetch signature.
|
|
83
|
+
*/
|
|
84
|
+
export type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
24
85
|
export interface RegisterParams {
|
|
25
86
|
email: string;
|
|
26
87
|
password: string;
|
|
@@ -140,3 +201,26 @@ export interface FunctionInvokeResult {
|
|
|
140
201
|
data: Record<string, unknown> | null;
|
|
141
202
|
success: boolean;
|
|
142
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Apple's optional full-name structure returned only on a user's FIRST
|
|
206
|
+
* Sign in with Apple. Both fields nullable; subsequent sign-ins omit
|
|
207
|
+
* this entirely.
|
|
208
|
+
*
|
|
209
|
+
* Pass to `KoolbaseAuth.signInWithApple` only on first sign-in. The
|
|
210
|
+
* server persists at link time and ignores on subsequent sign-ins
|
|
211
|
+
* (matches Apple's documented contract).
|
|
212
|
+
*/
|
|
213
|
+
export interface AppleFullName {
|
|
214
|
+
givenName?: string;
|
|
215
|
+
familyName?: string;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Parameters for `KoolbaseAuth.signInWithApple`. The SDK is
|
|
219
|
+
* library-agnostic — `identityToken` should come from any native
|
|
220
|
+
* Apple Sign-In package (e.g. `@invertase/react-native-apple-authentication`).
|
|
221
|
+
*/
|
|
222
|
+
export interface SignInWithAppleParams {
|
|
223
|
+
identityToken: string;
|
|
224
|
+
nonce?: string;
|
|
225
|
+
fullName?: AppleFullName;
|
|
226
|
+
}
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FunctionRuntime = void 0;
|
|
3
|
+
exports.FunctionRuntime = exports.RestoreResult = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Result of KoolbaseAuth.restoreSession(). Apps should branch on this:
|
|
6
|
+
* - NoSession → show login screen
|
|
7
|
+
* - Restored → show authenticated UI
|
|
8
|
+
* - Expired → show login screen with "session expired" message
|
|
9
|
+
* - Offline → show authenticated UI optimistically; API calls will
|
|
10
|
+
* fail until network is reachable
|
|
11
|
+
*/
|
|
12
|
+
var RestoreResult;
|
|
13
|
+
(function (RestoreResult) {
|
|
14
|
+
RestoreResult["NoSession"] = "no_session";
|
|
15
|
+
RestoreResult["Restored"] = "restored";
|
|
16
|
+
RestoreResult["Expired"] = "expired";
|
|
17
|
+
RestoreResult["Offline"] = "offline";
|
|
18
|
+
})(RestoreResult || (exports.RestoreResult = RestoreResult = {}));
|
|
4
19
|
// ─── Functions ─────────────────────────────────────────────────────────────
|
|
5
20
|
var FunctionRuntime;
|
|
6
21
|
(function (FunctionRuntime) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@techfinityedge/koolbase-react-native",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "React Native SDK for Koolbase
|
|
3
|
+
"version": "1.10.0",
|
|
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",
|
|
7
7
|
"files": [
|
|
@@ -27,17 +27,24 @@
|
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/jszip": "^3.4.0",
|
|
30
|
+
"react-native-keychain": "^10.0.0",
|
|
30
31
|
"typescript": "^5.0.0"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
|
-
"react-native": ">=0.70.0"
|
|
34
|
+
"react-native": ">=0.70.0",
|
|
35
|
+
"react-native-keychain": ">=8.0.0"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
38
|
"@react-native-async-storage/async-storage": "^3.0.2",
|
|
37
39
|
"@react-native-community/netinfo": "^12.0.1",
|
|
38
40
|
"jszip": "^3.10.1"
|
|
39
41
|
},
|
|
40
|
-
|
|
42
|
+
"publishConfig": {
|
|
41
43
|
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"peerDependenciesMeta": {
|
|
46
|
+
"react-native-keychain": {
|
|
47
|
+
"optional": true
|
|
48
|
+
}
|
|
42
49
|
}
|
|
43
50
|
}
|