@softwarepatterns/am-react 0.1.0 → 0.2.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 +15 -1
- package/dist/AuthProvider.d.ts +37 -5
- package/dist/AuthProvider.js +38 -21
- package/dist/AuthProvider.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Headless React auth adapter for **AccountMaker (Am)**.
|
|
4
4
|
|
|
5
5
|
This package exposes the React provider and hook for an `Am` instance and its
|
|
6
|
-
current
|
|
6
|
+
current session.
|
|
7
7
|
|
|
8
8
|
Examples live in [`examples/`](./examples).
|
|
9
9
|
|
|
@@ -37,6 +37,20 @@ export function App() {
|
|
|
37
37
|
}
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
## Callback props
|
|
41
|
+
|
|
42
|
+
`AuthProvider` exposes auth lifecycle callbacks that mirror the core `am`
|
|
43
|
+
events:
|
|
44
|
+
|
|
45
|
+
- `onSignedIn`
|
|
46
|
+
- `onTokensUpdated`
|
|
47
|
+
- `onProfileUpdated`
|
|
48
|
+
- `onAuthLost`
|
|
49
|
+
- `onReloadRequired`
|
|
50
|
+
|
|
51
|
+
`onAuthLost` is for recoverable client-side auth loss. `onReloadRequired` is
|
|
52
|
+
the terminal transition that should end in a hard navigation.
|
|
53
|
+
|
|
40
54
|
## Exports
|
|
41
55
|
|
|
42
56
|
- `AuthProvider`
|
package/dist/AuthProvider.d.ts
CHANGED
|
@@ -1,12 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides the headless React auth context for an `Am` instance.
|
|
3
|
+
*
|
|
4
|
+
* This file owns the provider and hooks that expose the current session to a
|
|
5
|
+
* React tree. It also owns the translation from `am` auth events into React
|
|
6
|
+
* state and callback props.
|
|
7
|
+
*
|
|
8
|
+
* Local invariants:
|
|
9
|
+
* - sessions are obtained from `Am`, never constructed here
|
|
10
|
+
* - `signedIn` is the only event that replaces React session state
|
|
11
|
+
* - `authLost` and `reloadRequired` are forwarded without clearing React state
|
|
12
|
+
* - startup restores or refreshes the current session before marking ready
|
|
13
|
+
*/
|
|
1
14
|
import React from 'react';
|
|
2
|
-
import { Am,
|
|
15
|
+
import { Am, AuthError, type AuthSession } from '@softwarepatterns/am';
|
|
3
16
|
import type { SessionProfile, SessionTokens } from '@softwarepatterns/am';
|
|
4
17
|
export type AuthProviderProps = {
|
|
18
|
+
/**
|
|
19
|
+
* `Am` instance whose session state drives this provider.
|
|
20
|
+
*/
|
|
5
21
|
am: Am;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Called when the current session rotates tokens.
|
|
24
|
+
*/
|
|
25
|
+
onTokensUpdated?: (newTokens: SessionTokens) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Called when the current session refreshes profile data.
|
|
28
|
+
*/
|
|
29
|
+
onProfileUpdated?: (profile: SessionProfile) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Called when auth is lost without requiring a reload.
|
|
32
|
+
*/
|
|
33
|
+
onAuthLost?: (e: AuthError) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Called after `Am` establishes the signed-in session.
|
|
36
|
+
*/
|
|
37
|
+
onSignedIn?: (session: AuthSession) => void | Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Called when the current session can continue only after a hard reload.
|
|
40
|
+
*/
|
|
41
|
+
onReloadRequired?: () => void;
|
|
10
42
|
};
|
|
11
43
|
export type AuthContextValue = {
|
|
12
44
|
auth: Am;
|
package/dist/AuthProvider.js
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Provides the headless React auth context for an `Am` instance.
|
|
4
|
+
*
|
|
5
|
+
* This file owns the provider and hooks that expose the current session to a
|
|
6
|
+
* React tree. It also owns the translation from `am` auth events into React
|
|
7
|
+
* state and callback props.
|
|
8
|
+
*
|
|
9
|
+
* Local invariants:
|
|
10
|
+
* - sessions are obtained from `Am`, never constructed here
|
|
11
|
+
* - `signedIn` is the only event that replaces React session state
|
|
12
|
+
* - `authLost` and `reloadRequired` are forwarded without clearing React state
|
|
13
|
+
* - startup restores or refreshes the current session before marking ready
|
|
14
|
+
*/
|
|
2
15
|
import React, { useMemo, createContext, useContext, useEffect, useState, } from 'react';
|
|
3
|
-
import { Am,
|
|
16
|
+
import { Am, AuthError, } from '@softwarepatterns/am'; // adjust import paths
|
|
4
17
|
const AuthContext = createContext(null);
|
|
5
18
|
/**
|
|
6
19
|
* Hook to access authentication state and actions.
|
|
@@ -57,37 +70,41 @@ export function useRequiredAuth() {
|
|
|
57
70
|
* ```;
|
|
58
71
|
*/
|
|
59
72
|
export function AuthProvider(props) {
|
|
60
|
-
const { children, am,
|
|
73
|
+
const { children, am, onAuthLost, onProfileUpdated, onTokensUpdated, onSignedIn, onReloadRequired, } = props;
|
|
61
74
|
const [session, setSession] = useState(null);
|
|
62
75
|
const [isReady, setIsReady] = useState(false);
|
|
63
76
|
useEffect(() => {
|
|
64
77
|
const unsubs = [];
|
|
65
|
-
unsubs.push(am.on('
|
|
78
|
+
unsubs.push(am.on('signedIn', (session) => {
|
|
66
79
|
const syncSessionState = async () => {
|
|
67
|
-
if (
|
|
68
|
-
await Promise.resolve(
|
|
80
|
+
if (onSignedIn) {
|
|
81
|
+
await Promise.resolve(onSignedIn(session));
|
|
69
82
|
}
|
|
70
83
|
setSession(session);
|
|
71
84
|
};
|
|
72
85
|
syncSessionState().catch((error) => {
|
|
73
|
-
console.error('Failed to apply
|
|
86
|
+
console.error('Failed to apply signed-in state', error);
|
|
74
87
|
setSession(session);
|
|
75
88
|
});
|
|
76
89
|
}));
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
unsubs.push(am.on('profileChange', onProfileChange));
|
|
90
|
+
if (onAuthLost) {
|
|
91
|
+
// authLost is recoverable. Forward it to the app without changing the
|
|
92
|
+
// current session state in React.
|
|
93
|
+
unsubs.push(am.on('authLost', onAuthLost));
|
|
94
|
+
}
|
|
95
|
+
if (onProfileUpdated) {
|
|
96
|
+
unsubs.push(am.on('profileUpdated', onProfileUpdated));
|
|
97
|
+
}
|
|
98
|
+
if (onTokensUpdated) {
|
|
99
|
+
unsubs.push(am.on('tokensUpdated', onTokensUpdated));
|
|
88
100
|
}
|
|
89
|
-
if (
|
|
90
|
-
unsubs.push(am.on('
|
|
101
|
+
if (onReloadRequired) {
|
|
102
|
+
unsubs.push(am.on('reloadRequired', () => {
|
|
103
|
+
// Keep the current session in React while the app performs a hard
|
|
104
|
+
// navigation. Clearing it early can crash components during the
|
|
105
|
+
// transition.
|
|
106
|
+
onReloadRequired();
|
|
107
|
+
}));
|
|
91
108
|
}
|
|
92
109
|
(async () => {
|
|
93
110
|
const currentSession = am.restoreSession() ?? am.session;
|
|
@@ -97,7 +114,7 @@ export function AuthProvider(props) {
|
|
|
97
114
|
setSession(currentSession);
|
|
98
115
|
}
|
|
99
116
|
catch {
|
|
100
|
-
|
|
117
|
+
setSession(null);
|
|
101
118
|
}
|
|
102
119
|
}
|
|
103
120
|
else {
|
|
@@ -107,7 +124,7 @@ export function AuthProvider(props) {
|
|
|
107
124
|
setIsReady(true);
|
|
108
125
|
})().catch(console.error);
|
|
109
126
|
return () => unsubs.forEach((u) => u());
|
|
110
|
-
}, [am,
|
|
127
|
+
}, [am, onAuthLost, onProfileUpdated, onReloadRequired, onSignedIn, onTokensUpdated]);
|
|
111
128
|
const value = useMemo(() => ({ auth: am, session, isReady }), [am, session, isReady]);
|
|
112
129
|
return _jsx(AuthContext.Provider, { value: value, children: children });
|
|
113
130
|
}
|
package/dist/AuthProvider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EACZ,OAAO,EACP,aAAa,EACb,UAAU,EACV,SAAS,EACT,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EACL,EAAE,EACF,
|
|
1
|
+
{"version":3,"file":"AuthProvider.js","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softwarepatterns/am-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Headless React auth adapter for AccountMaker (Am)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authentication",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"lint": "oxlint"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@softwarepatterns/am": "^0.
|
|
50
|
+
"@softwarepatterns/am": "^0.4.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=19"
|