@openfort/react-native 0.1.17 → 0.1.18
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/dist/constants/config.js
CHANGED
package/dist/core/client.js
CHANGED
|
@@ -49,7 +49,7 @@ export function createOpenfortClient({ baseConfiguration, overrides, shieldConfi
|
|
|
49
49
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
50
|
digest: digest,
|
|
51
51
|
},
|
|
52
|
-
storage: createNormalizedStorage(SecureStorageAdapter),
|
|
52
|
+
storage: createNormalizedStorage(baseConfiguration.publishableKey, SecureStorageAdapter),
|
|
53
53
|
},
|
|
54
54
|
shieldConfiguration,
|
|
55
55
|
});
|
package/dist/core/storage.js
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
import * as SecureStore from 'expo-secure-store';
|
|
3
3
|
import { logger } from '../lib/logger';
|
|
4
4
|
import { NativeStorageUtils } from '../native';
|
|
5
|
+
/**
|
|
6
|
+
* Tracks pending write operations per key.
|
|
7
|
+
* This ensures `get` waits for any in-flight `save` to complete,
|
|
8
|
+
* providing read-after-write consistency while keeping `save` synchronous.
|
|
9
|
+
*/
|
|
10
|
+
const pendingWrites = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* Creates a scope prefix from the publishable key.
|
|
13
|
+
* Extracts the unique project identifier after the "pk_test_" or "pk_live_" prefix.
|
|
14
|
+
* Uses the first 8 characters of that unique part to keep keys readable.
|
|
15
|
+
*
|
|
16
|
+
* e.g., "pk_test_abc123xyz789" -> "abc123xy"
|
|
17
|
+
*/
|
|
18
|
+
function createScope(publishableKey) {
|
|
19
|
+
// Remove the "pk_test_" or "pk_live_" prefix (8 characters)
|
|
20
|
+
const uniquePart = publishableKey.substring(8);
|
|
21
|
+
// Use first 8 characters of the unique part as scope
|
|
22
|
+
return uniquePart.substring(0, 8);
|
|
23
|
+
}
|
|
5
24
|
// Define the StorageKeys enum values that match the Openfort SDK
|
|
6
25
|
var StorageKeys;
|
|
7
26
|
(function (StorageKeys) {
|
|
@@ -24,6 +43,11 @@ export const SecureStorageAdapter = {
|
|
|
24
43
|
async get(key) {
|
|
25
44
|
try {
|
|
26
45
|
const normalizedKey = normalizeKey(key);
|
|
46
|
+
// Wait for any pending write to complete before reading
|
|
47
|
+
const pendingWrite = pendingWrites.get(normalizedKey);
|
|
48
|
+
if (pendingWrite) {
|
|
49
|
+
await pendingWrite;
|
|
50
|
+
}
|
|
27
51
|
const result = await SecureStore.getItemAsync(normalizedKey, NativeStorageUtils.getStorageOptions());
|
|
28
52
|
// If result is a string (as expected), return it
|
|
29
53
|
if (typeof result === 'string' || result === null) {
|
|
@@ -45,14 +69,21 @@ export const SecureStorageAdapter = {
|
|
|
45
69
|
}
|
|
46
70
|
},
|
|
47
71
|
async save(key, value) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
72
|
+
const normalizedKey = normalizeKey(key);
|
|
73
|
+
const writePromise = (async () => {
|
|
74
|
+
try {
|
|
75
|
+
await SecureStore.setItemAsync(normalizedKey, value, NativeStorageUtils.getStorageOptions());
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
logger.warn('Failed to set item in secure store', error);
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
pendingWrites.delete(normalizedKey);
|
|
83
|
+
}
|
|
84
|
+
})();
|
|
85
|
+
pendingWrites.set(normalizedKey, writePromise);
|
|
86
|
+
return writePromise;
|
|
56
87
|
},
|
|
57
88
|
async remove(key) {
|
|
58
89
|
try {
|
|
@@ -78,7 +109,7 @@ export const SecureStorageAdapter = {
|
|
|
78
109
|
},
|
|
79
110
|
};
|
|
80
111
|
/**
|
|
81
|
-
*
|
|
112
|
+
* Normalizes an Openfort storage key for use with Expo Secure Store.
|
|
82
113
|
*
|
|
83
114
|
* @param key - The key provided by the Openfort SDK.
|
|
84
115
|
* @returns A key that is safe to use with Expo Secure Store.
|
|
@@ -88,38 +119,57 @@ function normalizeKey(key) {
|
|
|
88
119
|
}
|
|
89
120
|
/**
|
|
90
121
|
* Creates a type-safe storage adapter that bridges the Openfort SDK storage API with the React Native implementation.
|
|
122
|
+
* Storage keys are scoped by publishable key to isolate data between different projects.
|
|
91
123
|
*
|
|
124
|
+
* @param publishableKey - The publishable key used to scope storage keys.
|
|
92
125
|
* @param customStorage - Optional custom storage implementation. When omitted the {@link SecureStorageAdapter} is used.
|
|
93
126
|
* @returns An object that satisfies the {@link Storage} interface expected by `@openfort/openfort-js`.
|
|
94
127
|
*/
|
|
95
|
-
export function createNormalizedStorage(customStorage) {
|
|
128
|
+
export function createNormalizedStorage(publishableKey, customStorage) {
|
|
96
129
|
const baseStorage = customStorage || SecureStorageAdapter;
|
|
130
|
+
const scope = createScope(publishableKey);
|
|
131
|
+
/**
|
|
132
|
+
* Prefixes a storage key with the scope.
|
|
133
|
+
* e.g., "openfort.authentication" -> "abc123xy.openfort.authentication"
|
|
134
|
+
*/
|
|
135
|
+
function scopeKey(key) {
|
|
136
|
+
return `${scope}.${key}`;
|
|
137
|
+
}
|
|
97
138
|
return {
|
|
98
139
|
async get(key) {
|
|
99
140
|
// Convert the unknown key to our StorageKeys enum
|
|
100
141
|
const storageKey = keyToStorageKeys(key);
|
|
101
|
-
const
|
|
142
|
+
const scopedKey = scopeKey(storageKey);
|
|
143
|
+
const result = await baseStorage.get(scopedKey);
|
|
102
144
|
return result;
|
|
103
145
|
},
|
|
104
146
|
save(key, value) {
|
|
105
147
|
logger.info(`Saving to storage key: ${key}, value: ${value}`);
|
|
106
148
|
const storageKey = keyToStorageKeys(key);
|
|
149
|
+
const scopedKey = scopeKey(storageKey);
|
|
107
150
|
// Fire and forget - don't await as the SDK expects synchronous behavior
|
|
108
|
-
baseStorage.save(
|
|
151
|
+
baseStorage.save(scopedKey, value).catch((error) => {
|
|
109
152
|
logger.error('Failed to save to storage', error);
|
|
110
153
|
});
|
|
111
154
|
},
|
|
112
155
|
remove(key) {
|
|
113
156
|
logger.info(`Removing from storage key: ${key}`);
|
|
114
157
|
const storageKey = keyToStorageKeys(key);
|
|
158
|
+
const scopedKey = scopeKey(storageKey);
|
|
115
159
|
// Fire and forget - don't await as the SDK expects synchronous behavior
|
|
116
|
-
baseStorage.remove(
|
|
160
|
+
baseStorage.remove(scopedKey).catch((error) => {
|
|
117
161
|
logger.error('Failed to remove from storage', error);
|
|
118
162
|
});
|
|
119
163
|
},
|
|
120
164
|
flush() {
|
|
121
165
|
logger.info('Flushing storage');
|
|
122
|
-
|
|
166
|
+
// Remove all scoped keys for this project
|
|
167
|
+
for (const key of Object.values(StorageKeys)) {
|
|
168
|
+
const scopedKey = scopeKey(key);
|
|
169
|
+
baseStorage.remove(scopedKey).catch((error) => {
|
|
170
|
+
logger.error('Failed to remove from storage during flush', error);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
123
173
|
},
|
|
124
174
|
};
|
|
125
175
|
}
|
|
@@ -1,21 +1,10 @@
|
|
|
1
1
|
import type { Storage } from '@openfort/openfort-js';
|
|
2
|
-
declare enum StorageKeys {
|
|
3
|
-
AUTHENTICATION = "openfort.authentication",
|
|
4
|
-
SIGNER = "openfort.signer",
|
|
5
|
-
CONFIGURATION = "openfort.configuration",
|
|
6
|
-
ACCOUNT = "openfort.account",
|
|
7
|
-
TEST = "openfort.test",
|
|
8
|
-
RECOVERY = "openfort.recovery",
|
|
9
|
-
SESSION = "openfort.session",
|
|
10
|
-
PKCE_STATE = "openfort.pkce_state",
|
|
11
|
-
PKCE_VERIFIER = "openfort.pkce_verifier"
|
|
12
|
-
}
|
|
13
2
|
interface OpenfortStorage {
|
|
14
|
-
get(key:
|
|
15
|
-
save(key:
|
|
16
|
-
remove(key:
|
|
3
|
+
get(key: string): Promise<string | null>;
|
|
4
|
+
save(key: string, value: string): Promise<void>;
|
|
5
|
+
remove(key: string): Promise<void>;
|
|
17
6
|
flush(): void;
|
|
18
|
-
keyExists(key:
|
|
7
|
+
keyExists(key: string): Promise<boolean>;
|
|
19
8
|
getStorageInfo(): Promise<{
|
|
20
9
|
isAvailable: boolean;
|
|
21
10
|
platform: string;
|
|
@@ -30,9 +19,11 @@ interface OpenfortStorage {
|
|
|
30
19
|
export declare const SecureStorageAdapter: OpenfortStorage;
|
|
31
20
|
/**
|
|
32
21
|
* Creates a type-safe storage adapter that bridges the Openfort SDK storage API with the React Native implementation.
|
|
22
|
+
* Storage keys are scoped by publishable key to isolate data between different projects.
|
|
33
23
|
*
|
|
24
|
+
* @param publishableKey - The publishable key used to scope storage keys.
|
|
34
25
|
* @param customStorage - Optional custom storage implementation. When omitted the {@link SecureStorageAdapter} is used.
|
|
35
26
|
* @returns An object that satisfies the {@link Storage} interface expected by `@openfort/openfort-js`.
|
|
36
27
|
*/
|
|
37
|
-
export declare function createNormalizedStorage(customStorage?: OpenfortStorage): Storage;
|
|
28
|
+
export declare function createNormalizedStorage(publishableKey: string, customStorage?: OpenfortStorage): Storage;
|
|
38
29
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfort/react-native",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.18",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "React Native SDK for Openfort platform integration",
|
|
7
7
|
"types": "dist/types/index.d.ts",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@openfort/openfort-js": "^0.10.
|
|
19
|
+
"@openfort/openfort-js": "^0.10.39"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"expo-apple-authentication": "*",
|