@explorins/pers-sdk-react-native 2.1.17 → 2.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/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +11 -12
- package/dist/index.js +47 -39
- package/dist/index.js.map +1 -1
- package/dist/providers/PersSDKProvider.d.ts.map +1 -1
- package/dist/providers/PersSDKProvider.js +26 -27
- package/package.json +182 -182
- package/src/hooks/useAuth.ts +12 -14
- package/src/providers/PersSDKProvider.tsx +29 -31
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PersSDKProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PersSDKProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAuC,SAAS,EAA2C,MAAM,OAAO,CAAC;AAEvH,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAIpF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAkB3D,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAE7B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAGpB,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAGzC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAGhC,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sBAAsB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5F,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC/C;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,
|
|
1
|
+
{"version":3,"file":"PersSDKProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PersSDKProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAuC,SAAS,EAA2C,MAAM,OAAO,CAAC;AAEvH,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAIpF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAkB3D,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAE7B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAGpB,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAGzC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAGhC,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sBAAsB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5F,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC/C;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,CA6NA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
|
|
@@ -38,6 +38,7 @@ const SDKContext = createContext(null);
|
|
|
38
38
|
*/
|
|
39
39
|
export const PersSDKProvider = ({ children, config }) => {
|
|
40
40
|
const initializingRef = useRef(false);
|
|
41
|
+
const eventUnsubscribeRef = useRef(null);
|
|
41
42
|
// State refs for stable functions to read current values
|
|
42
43
|
const sdkRef = useRef(null);
|
|
43
44
|
const isInitializedRef = useRef(false);
|
|
@@ -91,6 +92,21 @@ export const PersSDKProvider = ({ children, config }) => {
|
|
|
91
92
|
};
|
|
92
93
|
// Initialize PersSDK with platform-aware auth provider
|
|
93
94
|
const sdkInstance = new PersSDK(httpClient, sdkConfig);
|
|
95
|
+
// Subscribe to auth events BEFORE exposing SDK to consumers
|
|
96
|
+
// This ensures no events are missed due to React timing
|
|
97
|
+
eventUnsubscribeRef.current = sdkInstance.events.subscribe((event) => {
|
|
98
|
+
if (event.type === 'session_restored' || event.type === 'login_success') {
|
|
99
|
+
const details = event.details;
|
|
100
|
+
if (details?.user) {
|
|
101
|
+
setUser(details.user);
|
|
102
|
+
setIsAuthenticated(true);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (event.type === 'logout_success' || event.type === 'session_restoration_failed' || event.code === 'AUTH_FAILED') {
|
|
106
|
+
setUser(null);
|
|
107
|
+
setIsAuthenticated(false);
|
|
108
|
+
}
|
|
109
|
+
}, { domains: ['authentication'], replay: true });
|
|
94
110
|
setAuthProvider(authProvider);
|
|
95
111
|
setSdk(sdkInstance);
|
|
96
112
|
setIsInitialized(true);
|
|
@@ -104,6 +120,15 @@ export const PersSDKProvider = ({ children, config }) => {
|
|
|
104
120
|
initializingRef.current = false;
|
|
105
121
|
}
|
|
106
122
|
}, [isInitialized]);
|
|
123
|
+
// Cleanup subscription on unmount
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
return () => {
|
|
126
|
+
if (eventUnsubscribeRef.current) {
|
|
127
|
+
eventUnsubscribeRef.current();
|
|
128
|
+
eventUnsubscribeRef.current = null;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
107
132
|
const setAuthenticationState = useCallback((user, isAuthenticated) => {
|
|
108
133
|
setUser(user);
|
|
109
134
|
setIsAuthenticated(isAuthenticated);
|
|
@@ -150,32 +175,7 @@ export const PersSDKProvider = ({ children, config }) => {
|
|
|
150
175
|
console.error('[PersSDK] Failed to restore session:', error);
|
|
151
176
|
throw error;
|
|
152
177
|
}
|
|
153
|
-
}, [setAuthenticationState]);
|
|
154
|
-
// Listen for authentication events from core SDK
|
|
155
|
-
// Set up immediately when SDK is created (don't wait for isInitialized)
|
|
156
|
-
// to catch session_restored events that fire during SDK initialization
|
|
157
|
-
useEffect(() => {
|
|
158
|
-
if (!sdk)
|
|
159
|
-
return;
|
|
160
|
-
const unsubscribe = sdk.events.subscribe((event) => {
|
|
161
|
-
// Handle both session restoration and fresh login
|
|
162
|
-
if (event.type === 'session_restored' || event.type === 'login_success') {
|
|
163
|
-
const details = event.details;
|
|
164
|
-
if (details?.user) {
|
|
165
|
-
console.log(`[PersSDK] ${event.type}: syncing user state`);
|
|
166
|
-
setAuthenticationState(details.user, true);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
// Session restoration failed or auth error - clear React state
|
|
170
|
-
if (event.type === 'session_restoration_failed' || event.code === 'AUTH_FAILED') {
|
|
171
|
-
console.log('[PersSDK] Authentication failed - clearing session');
|
|
172
|
-
setAuthenticationState(null, false);
|
|
173
|
-
}
|
|
174
|
-
}, { domains: ['authentication'], replay: true });
|
|
175
|
-
return () => {
|
|
176
|
-
unsubscribe();
|
|
177
|
-
};
|
|
178
|
-
}, [sdk, setAuthenticationState]);
|
|
178
|
+
}, [setAuthenticationState]);
|
|
179
179
|
// iOS/Android: Monitor app state and validate tokens when app becomes active
|
|
180
180
|
useEffect(() => {
|
|
181
181
|
if (!sdk || Platform.OS === 'web') {
|
|
@@ -183,7 +183,6 @@ export const PersSDKProvider = ({ children, config }) => {
|
|
|
183
183
|
}
|
|
184
184
|
const handleAppStateChange = async (nextAppState) => {
|
|
185
185
|
if (nextAppState === 'active' && isAuthenticated) {
|
|
186
|
-
console.log('[PersSDK] App became active - validating tokens');
|
|
187
186
|
try {
|
|
188
187
|
// Trigger token validation when app resumes from background
|
|
189
188
|
// This ensures tokens are checked after extended inactivity
|
package/package.json
CHANGED
|
@@ -1,182 +1,182 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@explorins/pers-sdk-react-native",
|
|
3
|
-
"version": "2.1.
|
|
4
|
-
"description": "React Native SDK for PERS Platform - Tourism Loyalty System with Blockchain Transaction Signing and WebAuthn Authentication",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc && rollup -c --bundleConfigAsCjs",
|
|
9
|
-
"build:watch": "rollup -c --bundleConfigAsCjs --watch",
|
|
10
|
-
"dev": "tsc --watch",
|
|
11
|
-
"clean": "rimraf dist",
|
|
12
|
-
"docs": "typedoc",
|
|
13
|
-
"docs:dev": "typedoc --watch",
|
|
14
|
-
"docs:json": "typedoc --json docs/api.json",
|
|
15
|
-
"docs:serve": "npx http-server docs -p 8080",
|
|
16
|
-
"prepublishOnly": "npm run clean && npm run build",
|
|
17
|
-
"publish-version": "npm run clean && npm run build && npm version patch && npm publish",
|
|
18
|
-
"publish-with-docs": "npm run clean && npm run build && npm run docs && npm version patch && npm publish",
|
|
19
|
-
"yalc:publish": "npm version patch --no-git-tag-version && npm run build && yalc publish",
|
|
20
|
-
"yalc:push": "npm version patch --no-git-tag-version && npm run build && yalc push"
|
|
21
|
-
},
|
|
22
|
-
"keywords": [
|
|
23
|
-
"pers",
|
|
24
|
-
"sdk",
|
|
25
|
-
"react-native",
|
|
26
|
-
"tourism",
|
|
27
|
-
"loyalty",
|
|
28
|
-
"blockchain",
|
|
29
|
-
"web3",
|
|
30
|
-
"webauthn",
|
|
31
|
-
"transaction-signing",
|
|
32
|
-
"rewards",
|
|
33
|
-
"authentication",
|
|
34
|
-
"biometrics",
|
|
35
|
-
"secure-storage"
|
|
36
|
-
],
|
|
37
|
-
"author": "eXplorins",
|
|
38
|
-
"license": "MIT",
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"@explorins/pers-sdk": "^2.1.
|
|
41
|
-
"@explorins/pers-signer": "^1.0.33",
|
|
42
|
-
"buffer": "^6.0.3",
|
|
43
|
-
"ethers": "^6.15.0",
|
|
44
|
-
"react-native-get-random-values": "^2.0.0",
|
|
45
|
-
"react-native-keychain": "^10.0.0",
|
|
46
|
-
"react-native-passkey": "^3.3.2",
|
|
47
|
-
"react-native-quick-crypto": "^1.0.6"
|
|
48
|
-
},
|
|
49
|
-
"browser": {
|
|
50
|
-
"crypto": false,
|
|
51
|
-
"url": false,
|
|
52
|
-
"http": false,
|
|
53
|
-
"https": false,
|
|
54
|
-
"zlib": false,
|
|
55
|
-
"stream": false,
|
|
56
|
-
"assert": false,
|
|
57
|
-
"path": false,
|
|
58
|
-
"fs": false,
|
|
59
|
-
"os": false,
|
|
60
|
-
"readable-stream": false,
|
|
61
|
-
"util": false,
|
|
62
|
-
"events": false,
|
|
63
|
-
"net": false,
|
|
64
|
-
"tls": false,
|
|
65
|
-
"child_process": false,
|
|
66
|
-
"pngjs": false,
|
|
67
|
-
"pngjs/lib/bitmapper": false,
|
|
68
|
-
"pngjs/lib/parser-async": false,
|
|
69
|
-
"pngjs/lib/parser-sync": false,
|
|
70
|
-
"./bitmapper": false,
|
|
71
|
-
"hash-base": false,
|
|
72
|
-
"@ethereumjs/common": false,
|
|
73
|
-
"@ethereumjs/tx": false,
|
|
74
|
-
"@ethereumjs/util": false,
|
|
75
|
-
"stream-browserify": false,
|
|
76
|
-
"crypto-browserify": false,
|
|
77
|
-
"inherits": false,
|
|
78
|
-
"safe-buffer": false,
|
|
79
|
-
"string_decoder": false,
|
|
80
|
-
"process-nextick-args": false,
|
|
81
|
-
"isarray": false,
|
|
82
|
-
"core-util-is": false,
|
|
83
|
-
"util-deprecate": false,
|
|
84
|
-
"ethereum-cryptography": false,
|
|
85
|
-
"keccak": false,
|
|
86
|
-
"secp256k1": false,
|
|
87
|
-
"scrypt-js": false,
|
|
88
|
-
"bech32": false,
|
|
89
|
-
"ws": false,
|
|
90
|
-
"xhr2-cookies": false,
|
|
91
|
-
"aes-js": false,
|
|
92
|
-
"@ethersproject/sha2": false,
|
|
93
|
-
"@ethersproject/pbkdf2": false,
|
|
94
|
-
"@ethersproject/scrypt": false
|
|
95
|
-
},
|
|
96
|
-
"peerDependencies": {
|
|
97
|
-
"@react-native-async-storage/async-storage": ">=1.15.0",
|
|
98
|
-
"react": ">=16.8.0",
|
|
99
|
-
"react-native": ">=0.60.0"
|
|
100
|
-
},
|
|
101
|
-
"peerDependenciesMeta": {
|
|
102
|
-
"react-native-keychain": {
|
|
103
|
-
"optional": true
|
|
104
|
-
},
|
|
105
|
-
"@react-native-async-storage/async-storage": {
|
|
106
|
-
"optional": false
|
|
107
|
-
},
|
|
108
|
-
"react-native-get-random-values": {
|
|
109
|
-
"optional": true
|
|
110
|
-
},
|
|
111
|
-
"react-native-url-polyfill": {
|
|
112
|
-
"optional": true
|
|
113
|
-
},
|
|
114
|
-
"react-native-polyfill-globals": {
|
|
115
|
-
"optional": true
|
|
116
|
-
},
|
|
117
|
-
"web-streams-polyfill": {
|
|
118
|
-
"optional": true
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
"overrides": {
|
|
122
|
-
"readable-stream": false,
|
|
123
|
-
"@ethereumjs/common": false,
|
|
124
|
-
"@ethereumjs/util": false,
|
|
125
|
-
"@ethereumjs/rlp": false,
|
|
126
|
-
"@ethereumjs/tx": false,
|
|
127
|
-
"stream": false,
|
|
128
|
-
"util": false,
|
|
129
|
-
"events": false,
|
|
130
|
-
"crypto": false,
|
|
131
|
-
"fs": false,
|
|
132
|
-
"path": false,
|
|
133
|
-
"os": false,
|
|
134
|
-
"net": false,
|
|
135
|
-
"tls": false,
|
|
136
|
-
"child_process": false,
|
|
137
|
-
"hash-base": false,
|
|
138
|
-
"inherits": false,
|
|
139
|
-
"safe-buffer": false,
|
|
140
|
-
"string_decoder": false,
|
|
141
|
-
"process-nextick-args": false,
|
|
142
|
-
"isarray": false,
|
|
143
|
-
"core-util-is": false,
|
|
144
|
-
"util-deprecate": false,
|
|
145
|
-
"ethereum-cryptography": false,
|
|
146
|
-
"keccak": false,
|
|
147
|
-
"secp256k1": false,
|
|
148
|
-
"scrypt-js": false,
|
|
149
|
-
"bech32": false,
|
|
150
|
-
"ws": false,
|
|
151
|
-
"xhr2-cookies": false,
|
|
152
|
-
"aes-js": false,
|
|
153
|
-
"@ethersproject/sha2": false,
|
|
154
|
-
"@ethersproject/pbkdf2": false,
|
|
155
|
-
"@ethersproject/scrypt": false
|
|
156
|
-
},
|
|
157
|
-
"devDependencies": {
|
|
158
|
-
"@explorins/pers-shared": "^2.1.128",
|
|
159
|
-
"@react-native-async-storage/async-storage": "^3.0.2",
|
|
160
|
-
"@rollup/plugin-commonjs": "^25.0.7",
|
|
161
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
162
|
-
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
163
|
-
"@types/react": "^19.1.1",
|
|
164
|
-
"@types/react-native": "^0.72.8",
|
|
165
|
-
"rimraf": "^5.0.0",
|
|
166
|
-
"rollup": "^4.0.0",
|
|
167
|
-
"rollup-plugin-typescript2": "^0.36.0",
|
|
168
|
-
"typedoc": "^0.25.13",
|
|
169
|
-
"typedoc-plugin-markdown": "^3.17.1",
|
|
170
|
-
"typescript": "^5.2.0"
|
|
171
|
-
},
|
|
172
|
-
"files": [
|
|
173
|
-
"dist/**/*",
|
|
174
|
-
"src/**/*",
|
|
175
|
-
"README.md"
|
|
176
|
-
],
|
|
177
|
-
"repository": {
|
|
178
|
-
"type": "git",
|
|
179
|
-
"url": "git+https://github.com/eXplorins/pers-sdk.git",
|
|
180
|
-
"directory": "packages/pers-sdk-react-native"
|
|
181
|
-
}
|
|
182
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@explorins/pers-sdk-react-native",
|
|
3
|
+
"version": "2.1.18",
|
|
4
|
+
"description": "React Native SDK for PERS Platform - Tourism Loyalty System with Blockchain Transaction Signing and WebAuthn Authentication",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc && rollup -c --bundleConfigAsCjs",
|
|
9
|
+
"build:watch": "rollup -c --bundleConfigAsCjs --watch",
|
|
10
|
+
"dev": "tsc --watch",
|
|
11
|
+
"clean": "rimraf dist",
|
|
12
|
+
"docs": "typedoc",
|
|
13
|
+
"docs:dev": "typedoc --watch",
|
|
14
|
+
"docs:json": "typedoc --json docs/api.json",
|
|
15
|
+
"docs:serve": "npx http-server docs -p 8080",
|
|
16
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
17
|
+
"publish-version": "npm run clean && npm run build && npm version patch && npm publish",
|
|
18
|
+
"publish-with-docs": "npm run clean && npm run build && npm run docs && npm version patch && npm publish",
|
|
19
|
+
"yalc:publish": "npm version patch --no-git-tag-version && npm run build && yalc publish",
|
|
20
|
+
"yalc:push": "npm version patch --no-git-tag-version && npm run build && yalc push"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"pers",
|
|
24
|
+
"sdk",
|
|
25
|
+
"react-native",
|
|
26
|
+
"tourism",
|
|
27
|
+
"loyalty",
|
|
28
|
+
"blockchain",
|
|
29
|
+
"web3",
|
|
30
|
+
"webauthn",
|
|
31
|
+
"transaction-signing",
|
|
32
|
+
"rewards",
|
|
33
|
+
"authentication",
|
|
34
|
+
"biometrics",
|
|
35
|
+
"secure-storage"
|
|
36
|
+
],
|
|
37
|
+
"author": "eXplorins",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@explorins/pers-sdk": "^2.1.26",
|
|
41
|
+
"@explorins/pers-signer": "^1.0.33",
|
|
42
|
+
"buffer": "^6.0.3",
|
|
43
|
+
"ethers": "^6.15.0",
|
|
44
|
+
"react-native-get-random-values": "^2.0.0",
|
|
45
|
+
"react-native-keychain": "^10.0.0",
|
|
46
|
+
"react-native-passkey": "^3.3.2",
|
|
47
|
+
"react-native-quick-crypto": "^1.0.6"
|
|
48
|
+
},
|
|
49
|
+
"browser": {
|
|
50
|
+
"crypto": false,
|
|
51
|
+
"url": false,
|
|
52
|
+
"http": false,
|
|
53
|
+
"https": false,
|
|
54
|
+
"zlib": false,
|
|
55
|
+
"stream": false,
|
|
56
|
+
"assert": false,
|
|
57
|
+
"path": false,
|
|
58
|
+
"fs": false,
|
|
59
|
+
"os": false,
|
|
60
|
+
"readable-stream": false,
|
|
61
|
+
"util": false,
|
|
62
|
+
"events": false,
|
|
63
|
+
"net": false,
|
|
64
|
+
"tls": false,
|
|
65
|
+
"child_process": false,
|
|
66
|
+
"pngjs": false,
|
|
67
|
+
"pngjs/lib/bitmapper": false,
|
|
68
|
+
"pngjs/lib/parser-async": false,
|
|
69
|
+
"pngjs/lib/parser-sync": false,
|
|
70
|
+
"./bitmapper": false,
|
|
71
|
+
"hash-base": false,
|
|
72
|
+
"@ethereumjs/common": false,
|
|
73
|
+
"@ethereumjs/tx": false,
|
|
74
|
+
"@ethereumjs/util": false,
|
|
75
|
+
"stream-browserify": false,
|
|
76
|
+
"crypto-browserify": false,
|
|
77
|
+
"inherits": false,
|
|
78
|
+
"safe-buffer": false,
|
|
79
|
+
"string_decoder": false,
|
|
80
|
+
"process-nextick-args": false,
|
|
81
|
+
"isarray": false,
|
|
82
|
+
"core-util-is": false,
|
|
83
|
+
"util-deprecate": false,
|
|
84
|
+
"ethereum-cryptography": false,
|
|
85
|
+
"keccak": false,
|
|
86
|
+
"secp256k1": false,
|
|
87
|
+
"scrypt-js": false,
|
|
88
|
+
"bech32": false,
|
|
89
|
+
"ws": false,
|
|
90
|
+
"xhr2-cookies": false,
|
|
91
|
+
"aes-js": false,
|
|
92
|
+
"@ethersproject/sha2": false,
|
|
93
|
+
"@ethersproject/pbkdf2": false,
|
|
94
|
+
"@ethersproject/scrypt": false
|
|
95
|
+
},
|
|
96
|
+
"peerDependencies": {
|
|
97
|
+
"@react-native-async-storage/async-storage": ">=1.15.0",
|
|
98
|
+
"react": ">=16.8.0",
|
|
99
|
+
"react-native": ">=0.60.0"
|
|
100
|
+
},
|
|
101
|
+
"peerDependenciesMeta": {
|
|
102
|
+
"react-native-keychain": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"@react-native-async-storage/async-storage": {
|
|
106
|
+
"optional": false
|
|
107
|
+
},
|
|
108
|
+
"react-native-get-random-values": {
|
|
109
|
+
"optional": true
|
|
110
|
+
},
|
|
111
|
+
"react-native-url-polyfill": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"react-native-polyfill-globals": {
|
|
115
|
+
"optional": true
|
|
116
|
+
},
|
|
117
|
+
"web-streams-polyfill": {
|
|
118
|
+
"optional": true
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"overrides": {
|
|
122
|
+
"readable-stream": false,
|
|
123
|
+
"@ethereumjs/common": false,
|
|
124
|
+
"@ethereumjs/util": false,
|
|
125
|
+
"@ethereumjs/rlp": false,
|
|
126
|
+
"@ethereumjs/tx": false,
|
|
127
|
+
"stream": false,
|
|
128
|
+
"util": false,
|
|
129
|
+
"events": false,
|
|
130
|
+
"crypto": false,
|
|
131
|
+
"fs": false,
|
|
132
|
+
"path": false,
|
|
133
|
+
"os": false,
|
|
134
|
+
"net": false,
|
|
135
|
+
"tls": false,
|
|
136
|
+
"child_process": false,
|
|
137
|
+
"hash-base": false,
|
|
138
|
+
"inherits": false,
|
|
139
|
+
"safe-buffer": false,
|
|
140
|
+
"string_decoder": false,
|
|
141
|
+
"process-nextick-args": false,
|
|
142
|
+
"isarray": false,
|
|
143
|
+
"core-util-is": false,
|
|
144
|
+
"util-deprecate": false,
|
|
145
|
+
"ethereum-cryptography": false,
|
|
146
|
+
"keccak": false,
|
|
147
|
+
"secp256k1": false,
|
|
148
|
+
"scrypt-js": false,
|
|
149
|
+
"bech32": false,
|
|
150
|
+
"ws": false,
|
|
151
|
+
"xhr2-cookies": false,
|
|
152
|
+
"aes-js": false,
|
|
153
|
+
"@ethersproject/sha2": false,
|
|
154
|
+
"@ethersproject/pbkdf2": false,
|
|
155
|
+
"@ethersproject/scrypt": false
|
|
156
|
+
},
|
|
157
|
+
"devDependencies": {
|
|
158
|
+
"@explorins/pers-shared": "^2.1.128",
|
|
159
|
+
"@react-native-async-storage/async-storage": "^3.0.2",
|
|
160
|
+
"@rollup/plugin-commonjs": "^25.0.7",
|
|
161
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
162
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
163
|
+
"@types/react": "^19.1.1",
|
|
164
|
+
"@types/react-native": "^0.72.8",
|
|
165
|
+
"rimraf": "^5.0.0",
|
|
166
|
+
"rollup": "^4.0.0",
|
|
167
|
+
"rollup-plugin-typescript2": "^0.36.0",
|
|
168
|
+
"typedoc": "^0.25.13",
|
|
169
|
+
"typedoc-plugin-markdown": "^3.17.1",
|
|
170
|
+
"typescript": "^5.2.0"
|
|
171
|
+
},
|
|
172
|
+
"files": [
|
|
173
|
+
"dist/**/*",
|
|
174
|
+
"src/**/*",
|
|
175
|
+
"README.md"
|
|
176
|
+
],
|
|
177
|
+
"repository": {
|
|
178
|
+
"type": "git",
|
|
179
|
+
"url": "git+https://github.com/eXplorins/pers-sdk.git",
|
|
180
|
+
"directory": "packages/pers-sdk-react-native"
|
|
181
|
+
}
|
|
182
|
+
}
|
package/src/hooks/useAuth.ts
CHANGED
|
@@ -50,8 +50,7 @@ export const useAuth = () => {
|
|
|
50
50
|
authProvider,
|
|
51
51
|
isInitialized,
|
|
52
52
|
isAuthenticated,
|
|
53
|
-
user,
|
|
54
|
-
setAuthenticationState,
|
|
53
|
+
user,
|
|
55
54
|
refreshUserData
|
|
56
55
|
} = usePersSDK();
|
|
57
56
|
|
|
@@ -79,8 +78,7 @@ export const useAuth = () => {
|
|
|
79
78
|
// Set token in auth provider
|
|
80
79
|
await authProvider.setAccessToken(jwtToken);
|
|
81
80
|
|
|
82
|
-
// Perform login
|
|
83
|
-
// SDK emits login_success event with user data - PersSDKProvider handles state sync
|
|
81
|
+
// Perform login - emits login_success event which Provider handles
|
|
84
82
|
const result = await sdk.auth.loginWithToken(jwtToken, userType);
|
|
85
83
|
|
|
86
84
|
return result;
|
|
@@ -108,8 +106,7 @@ export const useAuth = () => {
|
|
|
108
106
|
}
|
|
109
107
|
|
|
110
108
|
try {
|
|
111
|
-
// Use the raw data login
|
|
112
|
-
// SDK emits login_success event with user data - PersSDKProvider handles state sync
|
|
109
|
+
// Use the raw data login - emits login_success event which Provider handles
|
|
113
110
|
const result = await sdk.auth.loginWithRawData(rawUserData);
|
|
114
111
|
|
|
115
112
|
// Set token from result
|
|
@@ -135,17 +132,18 @@ export const useAuth = () => {
|
|
|
135
132
|
* ```
|
|
136
133
|
*/
|
|
137
134
|
const logout = useCallback(async (): Promise<void> => {
|
|
135
|
+
if (!sdk) {
|
|
136
|
+
throw new Error('SDK not initialized. Call initialize() first.');
|
|
137
|
+
}
|
|
138
|
+
|
|
138
139
|
try {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
setAuthenticationState(null, false);
|
|
140
|
+
// clearAuth emits logout_success event which Provider handles
|
|
141
|
+
await sdk.auth.clearAuth();
|
|
144
142
|
} catch (error) {
|
|
145
143
|
console.error('Logout failed:', error);
|
|
146
144
|
throw error;
|
|
147
145
|
}
|
|
148
|
-
}, [
|
|
146
|
+
}, [sdk]);
|
|
149
147
|
|
|
150
148
|
/**
|
|
151
149
|
* Retrieves the current authenticated user data
|
|
@@ -223,9 +221,9 @@ export const useAuth = () => {
|
|
|
223
221
|
if (!sdk) {
|
|
224
222
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
225
223
|
}
|
|
224
|
+
// clearAuth emits logout_success event which Provider handles
|
|
226
225
|
await sdk.auth.clearAuth();
|
|
227
|
-
|
|
228
|
-
}, [sdk, setAuthenticationState]);
|
|
226
|
+
}, [sdk]);
|
|
229
227
|
|
|
230
228
|
/**
|
|
231
229
|
* Checks if the current authentication is valid (non-expired)
|
|
@@ -89,6 +89,7 @@ export const PersSDKProvider: React.FC<{
|
|
|
89
89
|
config?: PersConfig;
|
|
90
90
|
}> = ({ children, config }) => {
|
|
91
91
|
const initializingRef = useRef(false);
|
|
92
|
+
const eventUnsubscribeRef = useRef<(() => void) | null>(null);
|
|
92
93
|
|
|
93
94
|
// State refs for stable functions to read current values
|
|
94
95
|
const sdkRef = useRef<PersSDK | null>(null);
|
|
@@ -156,6 +157,23 @@ export const PersSDKProvider: React.FC<{
|
|
|
156
157
|
// Initialize PersSDK with platform-aware auth provider
|
|
157
158
|
const sdkInstance = new PersSDK(httpClient, sdkConfig);
|
|
158
159
|
|
|
160
|
+
// Subscribe to auth events BEFORE exposing SDK to consumers
|
|
161
|
+
// This ensures no events are missed due to React timing
|
|
162
|
+
eventUnsubscribeRef.current = sdkInstance.events.subscribe((event) => {
|
|
163
|
+
if (event.type === 'session_restored' || event.type === 'login_success') {
|
|
164
|
+
const details = event.details as { user?: UserDTO | AdminDTO };
|
|
165
|
+
if (details?.user) {
|
|
166
|
+
setUser(details.user);
|
|
167
|
+
setIsAuthenticated(true);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (event.type === 'logout_success' || event.type === 'session_restoration_failed' || event.code === 'AUTH_FAILED') {
|
|
172
|
+
setUser(null);
|
|
173
|
+
setIsAuthenticated(false);
|
|
174
|
+
}
|
|
175
|
+
}, { domains: ['authentication'], replay: true });
|
|
176
|
+
|
|
159
177
|
setAuthProvider(authProvider);
|
|
160
178
|
setSdk(sdkInstance);
|
|
161
179
|
setIsInitialized(true);
|
|
@@ -167,6 +185,16 @@ export const PersSDKProvider: React.FC<{
|
|
|
167
185
|
initializingRef.current = false;
|
|
168
186
|
}
|
|
169
187
|
}, [isInitialized]);
|
|
188
|
+
|
|
189
|
+
// Cleanup subscription on unmount
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
return () => {
|
|
192
|
+
if (eventUnsubscribeRef.current) {
|
|
193
|
+
eventUnsubscribeRef.current();
|
|
194
|
+
eventUnsubscribeRef.current = null;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}, []);
|
|
170
198
|
|
|
171
199
|
const setAuthenticationState = useCallback((user: UserDTO | AdminDTO | null, isAuthenticated: boolean) => {
|
|
172
200
|
setUser(user);
|
|
@@ -219,36 +247,7 @@ export const PersSDKProvider: React.FC<{
|
|
|
219
247
|
console.error('[PersSDK] Failed to restore session:', error);
|
|
220
248
|
throw error;
|
|
221
249
|
}
|
|
222
|
-
}, [setAuthenticationState]);
|
|
223
|
-
|
|
224
|
-
// Listen for authentication events from core SDK
|
|
225
|
-
// Set up immediately when SDK is created (don't wait for isInitialized)
|
|
226
|
-
// to catch session_restored events that fire during SDK initialization
|
|
227
|
-
useEffect(() => {
|
|
228
|
-
if (!sdk) return;
|
|
229
|
-
|
|
230
|
-
const unsubscribe = sdk.events.subscribe((event) => {
|
|
231
|
-
// Handle both session restoration and fresh login
|
|
232
|
-
if (event.type === 'session_restored' || event.type === 'login_success') {
|
|
233
|
-
const details = event.details as { user?: UserDTO | AdminDTO };
|
|
234
|
-
|
|
235
|
-
if (details?.user) {
|
|
236
|
-
console.log(`[PersSDK] ${event.type}: syncing user state`);
|
|
237
|
-
setAuthenticationState(details.user, true);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Session restoration failed or auth error - clear React state
|
|
242
|
-
if (event.type === 'session_restoration_failed' || event.code === 'AUTH_FAILED') {
|
|
243
|
-
console.log('[PersSDK] Authentication failed - clearing session');
|
|
244
|
-
setAuthenticationState(null, false);
|
|
245
|
-
}
|
|
246
|
-
}, { domains: ['authentication'], replay: true });
|
|
247
|
-
|
|
248
|
-
return () => {
|
|
249
|
-
unsubscribe();
|
|
250
|
-
};
|
|
251
|
-
}, [sdk, setAuthenticationState]);
|
|
250
|
+
}, [setAuthenticationState]);
|
|
252
251
|
|
|
253
252
|
// iOS/Android: Monitor app state and validate tokens when app becomes active
|
|
254
253
|
useEffect(() => {
|
|
@@ -258,7 +257,6 @@ export const PersSDKProvider: React.FC<{
|
|
|
258
257
|
|
|
259
258
|
const handleAppStateChange = async (nextAppState: AppStateStatus) => {
|
|
260
259
|
if (nextAppState === 'active' && isAuthenticated) {
|
|
261
|
-
console.log('[PersSDK] App became active - validating tokens');
|
|
262
260
|
try {
|
|
263
261
|
// Trigger token validation when app resumes from background
|
|
264
262
|
// This ensures tokens are checked after extended inactivity
|