@usesoftwareau/jwt-state 1.0.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/src/hooks.ts ADDED
@@ -0,0 +1,98 @@
1
+ import { usePrevious } from "@usesoftwareau/react-utils";
2
+ import { _useJWTState } from "./common";
3
+ import { JWTReducerState } from "./reducer";
4
+
5
+ /**
6
+ * Type representing the authentication readiness state obtained from the JWT reducer state.
7
+ */
8
+ type AuthReadyFromContext = JWTReducerState<any>["authReady"];
9
+
10
+ /**
11
+ * Hook to access the authentication readiness state.
12
+ * @returns Authentication readiness state from the JWT reducer state.
13
+ */
14
+ export function _useAuthReady(): AuthReadyFromContext {
15
+ return _useJWTState()[0].authReady;
16
+ }
17
+
18
+ /**
19
+ * Type representing the claims obtained from the JWT reducer state.
20
+ */
21
+ type ClaimsFromContext<CustomClaims extends Record<string, any>> = JWTReducerState<CustomClaims>["claims"];
22
+
23
+ /**
24
+ * Hook to access the claims from the JWT reducer state.
25
+ * @param assert - Optional parameter to assert if claims are present.
26
+ * @returns Claims from the JWT reducer state.
27
+ * @example
28
+ * ```tsx
29
+ * // Custom claims used throughout the app
30
+ * declare global {
31
+ * interface CustomClaims {
32
+ * created: string;
33
+ * dbid: string;
34
+ * email: string;
35
+ * email_verified: boolean;
36
+ * mobile: string;
37
+ * admin?: boolean | string;
38
+ * banned?: string;
39
+ * }
40
+ * }
41
+ * // Local, app specific useClaims hook with the custom claims applied
42
+ * export const useClaims = <Assert extends boolean>(assert?: Assert) => _useClaims<Assert, CustomClaims>(assert);
43
+ *
44
+ * // Access the user's claims object in a screen
45
+ * const claims = useClaims();
46
+ * ```
47
+ */
48
+ export function _useClaims<T extends boolean, CustomClaims extends Record<string, any> = Record<string, any>>(assert?: T) {
49
+ const claims = _useJWTState<CustomClaims>()[0].claims;
50
+
51
+ const prevClaims = usePrevious(claims);
52
+ const selectedClaims = claims ?? prevClaims;
53
+ if (assert && !selectedClaims) {
54
+ throw new Error("(useJWTState) Claims were not present during assertion.");
55
+ }
56
+ return selectedClaims as T extends true ? NonNullable<ClaimsFromContext<CustomClaims>> : ClaimsFromContext<CustomClaims>;
57
+ }
58
+
59
+ /**
60
+ * Type representing the token obtained from the JWT reducer state.
61
+ */
62
+ type TokenFromContext = JWTReducerState<any>["token"];
63
+
64
+ /**
65
+ * Hook to access the token from the JWT reducer state.
66
+ * @param assert - Optional parameter to assert if token is present.
67
+ * @returns Token from the JWT reducer state.
68
+ * @example
69
+ * ```tsx
70
+ * // Custom claims used throughout the app
71
+ * declare global {
72
+ * interface CustomClaims {
73
+ * created: string;
74
+ * dbid: string;
75
+ * email: string;
76
+ * email_verified: boolean;
77
+ * mobile: string;
78
+ * admin?: boolean | string;
79
+ * banned?: string;
80
+ * }
81
+ * }
82
+ * // Local, app specific useClaims hook with the custom claims applied
83
+ * export const useToken = <Assert extends boolean>(assert?: Assert) => _useToken<Assert, CustomClaims>(assert);
84
+ *
85
+ * // Access the user's token in a screen
86
+ * const token = useToken();
87
+ * ```
88
+ */
89
+ export function _useToken<T extends boolean, CustomClaims extends Record<string, any> = Record<string, any>>(assert?: T) {
90
+ const token = _useJWTState<CustomClaims>()[0].token;
91
+
92
+ const prevToken = usePrevious(token);
93
+ const selectedToken = token ?? prevToken;
94
+ if (assert && typeof selectedToken !== "string") {
95
+ throw new Error("(useJWTState) Token was not present during assertion.");
96
+ }
97
+ return selectedToken as T extends true ? NonNullable<TokenFromContext> : TokenFromContext;
98
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,4 @@
1
+
2
+ export * from "./common"
3
+
4
+ export * from "./hooks";
package/src/reducer.ts ADDED
@@ -0,0 +1,98 @@
1
+ import { ActionsWithBatching } from "@usesoftwareau/react-utils";
2
+
3
+ /**
4
+ * Interface representing the standard claims type.
5
+ */
6
+ export interface _ClaimsType {
7
+ aud: string;
8
+ exp: number;
9
+ iat: number;
10
+ iss: string;
11
+ sub: string;
12
+ }
13
+
14
+ /**
15
+ * Interface representing the state of the JWT reducer.
16
+ */
17
+ export interface JWTReducerState<CustomClaims extends Record<string, any> = Record<string, any>> {
18
+ authReady: boolean;
19
+ claims: (_ClaimsType & CustomClaims) | null;
20
+ token: string | null;
21
+ }
22
+
23
+ /**
24
+ * Action interface to set the authentication readiness value.
25
+ */
26
+ interface SetAuthReadyValueAction {
27
+ type: "SET_AUTH_READY_VALUE";
28
+ payload: JWTReducerState["authReady"];
29
+ }
30
+
31
+ /**
32
+ * Action interface to set the token value.
33
+ */
34
+ interface SetTokenValueAction {
35
+ type: "SET_TOKEN_VALUE";
36
+ payload: JWTReducerState["token"];
37
+ }
38
+
39
+ /**
40
+ * Action interface to set the claims value.
41
+ */
42
+ interface SetClaimsValueAction<CustomClaims extends Record<string, any> = Record<string, any>> {
43
+ type: "SET_CLAIMS_VALUE";
44
+ payload: JWTReducerState<CustomClaims>["claims"];
45
+ }
46
+
47
+ /**
48
+ * Base action types for the JWT reducer.
49
+ */
50
+ type ReducerBaseActions<CustomClaims extends Record<string, any> = Record<string, any>> =
51
+ | SetAuthReadyValueAction
52
+ | SetClaimsValueAction<CustomClaims>
53
+ | SetTokenValueAction;
54
+
55
+ /**
56
+ * All possible action types for the JWT reducer.
57
+ */
58
+ type ReducerAllActions<CustomClaims extends Record<string, any>> = ActionsWithBatching<ReducerBaseActions<CustomClaims>>;
59
+
60
+ /**
61
+ * Type representing all actions for the JWT reducer.
62
+ */
63
+ export type JWTReducerActions<CustomClaims extends Record<string, any> = Record<string, any>> = ReducerAllActions<CustomClaims>;
64
+
65
+ /**
66
+ * Reducer function to handle JWT reducer actions.
67
+ */
68
+ export function reducerHandler<CustomClaims extends Record<string, any>>(prev: JWTReducerState<CustomClaims>, action: JWTReducerActions<CustomClaims>, originalPrev?: JWTReducerState<CustomClaims>): JWTReducerState<CustomClaims> {
69
+ const isSubAction = !!originalPrev;
70
+ const newState = isSubAction ? prev : { ...prev };
71
+ switch(action.type) {
72
+ case "MULTIPLE":
73
+ for(const subAction of action.payload) {
74
+ reducerHandler(newState, subAction, prev);
75
+ }
76
+ break;
77
+ case "SET_AUTH_READY_VALUE":
78
+ newState.authReady = action.payload;
79
+ break;
80
+ case "SET_TOKEN_VALUE": {
81
+ newState.token = action.payload ?? null;
82
+ break;
83
+ }
84
+ case "SET_CLAIMS_VALUE":
85
+ newState.claims = action.payload;
86
+ break;
87
+ }
88
+ return newState;
89
+ }
90
+
91
+ /**
92
+ * Initial state for the JWT reducer.
93
+ */
94
+ export const initialJWTReducerState: JWTReducerState<any> = {
95
+ authReady: false,
96
+ claims: null,
97
+ token: null
98
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "extends": "@tsconfig/react-native/tsconfig.json",
3
+ "compilerOptions": {
4
+ "module": "esnext",
5
+ "moduleResolution": "bundler",
6
+ "outDir": "./build",
7
+ "rootDir": "./src",
8
+ "noEmit": false,
9
+ "declaration": true
10
+ },
11
+ "exclude": ["./build", "./docs"]
12
+ }
package/typedoc.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "out": "docs",
3
+ "entryPoints": ["src/**/*.tsx"],
4
+ // Excluding .web files explicity here incse the entry points get updated in the future.
5
+ "exclude": ["**/*.test.ts", "**/*.spec.ts", "**/*.web.tsx"]
6
+ }