oidc-spa 3.0.2 → 4.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/README.md +11 -3
- package/oidc.d.ts +21 -9
- package/oidc.js +94 -47
- package/oidc.js.map +1 -1
- package/package.json +14 -9
- package/react.d.ts +16 -24
- package/react.js +54 -27
- package/react.js.map +1 -1
- package/src/oidc.ts +161 -64
- package/src/react.tsx +118 -85
- package/src/tools/powerhooks/useGuaranteedMemo.ts +18 -0
- package/tools/powerhooks/useGuaranteedMemo.d.ts +1 -0
- package/tools/powerhooks/useGuaranteedMemo.js +43 -0
- package/tools/powerhooks/useGuaranteedMemo.js.map +1 -0
package/src/react.tsx
CHANGED
|
@@ -1,23 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
useState,
|
|
4
|
-
createContext,
|
|
5
|
-
useContext,
|
|
6
|
-
useReducer,
|
|
7
|
-
useMemo,
|
|
8
|
-
type ReactNode
|
|
9
|
-
} from "react";
|
|
10
|
-
import { createOidc, type Oidc } from "./oidc";
|
|
1
|
+
import { useEffect, useState, createContext, useContext, useReducer, type ReactNode } from "react";
|
|
2
|
+
import { createOidc, type ParamsOfCreateOidc, type Oidc } from "./oidc";
|
|
11
3
|
import { assert } from "tsafe/assert";
|
|
12
|
-
import { decodeJwt } from "./tools/decodeJwt";
|
|
13
4
|
import { id } from "tsafe/id";
|
|
5
|
+
import { useGuaranteedMemo } from "./tools/powerhooks/useGuaranteedMemo";
|
|
14
6
|
|
|
15
|
-
|
|
7
|
+
export type OidcReact<DecodedIdToken extends Record<string, unknown>> =
|
|
8
|
+
| OidcReact.NotLoggedIn
|
|
9
|
+
| OidcReact.LoggedIn<DecodedIdToken>;
|
|
10
|
+
|
|
11
|
+
export namespace OidcReact {
|
|
12
|
+
export type Common = Oidc.Common;
|
|
13
|
+
|
|
14
|
+
export type NotLoggedIn = Common & {
|
|
15
|
+
isUserLoggedIn: false;
|
|
16
|
+
login: Oidc.NotLoggedIn["login"];
|
|
17
|
+
oidcTokens?: never;
|
|
18
|
+
logout?: never;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type LoggedIn<DecodedIdToken extends Record<string, unknown>> = Common & {
|
|
22
|
+
isUserLoggedIn: true;
|
|
23
|
+
oidcTokens: Oidc.Tokens<DecodedIdToken>;
|
|
24
|
+
logout: Oidc.LoggedIn["logout"];
|
|
25
|
+
renewTokens: Oidc.LoggedIn["renewTokens"];
|
|
26
|
+
login?: never;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const oidcContext = createContext<
|
|
31
|
+
| {
|
|
32
|
+
oidc: Oidc;
|
|
33
|
+
decodedIdTokenSchema: ParamsOfCreateOidc["decodedIdTokenSchema"];
|
|
34
|
+
}
|
|
35
|
+
| undefined
|
|
36
|
+
>(undefined);
|
|
16
37
|
|
|
17
38
|
/** @see: https://github.com/garronej/oidc-spa#option-2-usage-directly-within-react */
|
|
18
|
-
export function
|
|
39
|
+
export function createReactOidc<
|
|
40
|
+
DecodedIdToken extends Record<string, unknown> = Record<string, unknown>
|
|
41
|
+
>(params: ParamsOfCreateOidc<DecodedIdToken>) {
|
|
19
42
|
const prOidc = createOidc(params);
|
|
20
43
|
|
|
44
|
+
const { decodedIdTokenSchema } = params;
|
|
45
|
+
|
|
21
46
|
function OidcProvider(props: { fallback?: ReactNode; children: ReactNode }) {
|
|
22
47
|
const { children, fallback } = props;
|
|
23
48
|
|
|
@@ -31,50 +56,25 @@ export function createOidcProvider(params: Parameters<typeof createOidc>[0]) {
|
|
|
31
56
|
return <>{fallback === undefined ? null : fallback}</>;
|
|
32
57
|
}
|
|
33
58
|
|
|
34
|
-
return
|
|
59
|
+
return (
|
|
60
|
+
<oidcContext.Provider value={{ oidc, decodedIdTokenSchema }}>
|
|
61
|
+
{children}
|
|
62
|
+
</oidcContext.Provider>
|
|
63
|
+
);
|
|
35
64
|
}
|
|
36
65
|
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type ReactiveOidc<DecodedIdToken extends Record<string, unknown>> =
|
|
41
|
-
| ReactiveOidc.NotLoggedIn
|
|
42
|
-
| ReactiveOidc.LoggedIn<DecodedIdToken>;
|
|
43
|
-
|
|
44
|
-
export namespace ReactiveOidc {
|
|
45
|
-
export type Common = Oidc.Common;
|
|
46
|
-
|
|
47
|
-
export type NotLoggedIn = Common & {
|
|
48
|
-
isUserLoggedIn: false;
|
|
49
|
-
login: Oidc.NotLoggedIn["login"];
|
|
50
|
-
oidcTokens: undefined;
|
|
51
|
-
logout: undefined;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export type LoggedIn<DecodedIdToken extends Record<string, unknown>> = Common & {
|
|
55
|
-
isUserLoggedIn: true;
|
|
56
|
-
oidcTokens: ReturnType<Oidc.LoggedIn["getTokens"]> & {
|
|
57
|
-
decodedIdToken: DecodedIdToken;
|
|
58
|
-
};
|
|
59
|
-
logout: Oidc.LoggedIn["logout"];
|
|
60
|
-
renewTokens: Oidc.LoggedIn["renewTokens"];
|
|
61
|
-
login: undefined;
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function createUseOidc<
|
|
66
|
-
DecodedOidcIdToken extends Record<string, unknown> = Record<string, unknown>
|
|
67
|
-
>(params?: { decodedIdTokenSchema?: { parse: (data: unknown) => DecodedOidcIdToken } }) {
|
|
68
|
-
const { decodedIdTokenSchema } = params ?? {};
|
|
69
|
-
|
|
70
|
-
function useOidc(params?: { assertUserLoggedIn: false }): ReactiveOidc<DecodedOidcIdToken>;
|
|
71
|
-
function useOidc(params: { assertUserLoggedIn: true }): ReactiveOidc.LoggedIn<DecodedOidcIdToken>;
|
|
72
|
-
function useOidc(params?: { assertUserLoggedIn: boolean }): ReactiveOidc<DecodedOidcIdToken> {
|
|
66
|
+
function useOidc(params?: { assertUserLoggedIn: false }): OidcReact<DecodedIdToken>;
|
|
67
|
+
function useOidc(params: { assertUserLoggedIn: true }): OidcReact.LoggedIn<DecodedIdToken>;
|
|
68
|
+
function useOidc(params?: { assertUserLoggedIn: boolean }): OidcReact<DecodedIdToken> {
|
|
73
69
|
const { assertUserLoggedIn = false } = params ?? {};
|
|
74
70
|
|
|
75
|
-
const oidc =
|
|
71
|
+
const { oidc, decodedIdTokenSchema: decodedIdTokenSchema_context } = (function useClosure() {
|
|
72
|
+
const context = useContext(oidcContext);
|
|
73
|
+
|
|
74
|
+
assert(context !== undefined, "You must use useOidc inside a OidcProvider");
|
|
76
75
|
|
|
77
|
-
|
|
76
|
+
return context;
|
|
77
|
+
})();
|
|
78
78
|
|
|
79
79
|
const [, forceUpdate] = useReducer(() => [], []);
|
|
80
80
|
|
|
@@ -94,46 +94,79 @@ export function createUseOidc<
|
|
|
94
94
|
);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
const { oidcTokens } = (function useClosure() {
|
|
98
|
+
const tokens = oidc.isUserLoggedIn ? oidc.getTokens() : undefined;
|
|
99
|
+
|
|
100
|
+
const oidcTokens = useGuaranteedMemo(() => {
|
|
101
|
+
if (tokens === undefined) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const oidcTokens: Oidc.Tokens<DecodedIdToken> = {
|
|
106
|
+
"accessToken": tokens.accessToken,
|
|
107
|
+
"accessTokenExpirationTime": tokens.accessTokenExpirationTime,
|
|
108
|
+
"idToken": tokens.idToken,
|
|
109
|
+
"refreshToken": tokens.refreshToken,
|
|
110
|
+
"refreshTokenExpirationTime": tokens.refreshTokenExpirationTime,
|
|
111
|
+
"decodedIdToken": null as any
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
let cache: { decodedIdToken: Record<string, unknown> } | undefined = undefined;
|
|
115
|
+
|
|
116
|
+
Object.defineProperty(oidcTokens, "decodedIdToken", {
|
|
117
|
+
"get": () => {
|
|
118
|
+
if (cache !== undefined) {
|
|
119
|
+
return cache.decodedIdToken;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let { decodedIdToken } = tokens;
|
|
123
|
+
|
|
124
|
+
if (
|
|
125
|
+
decodedIdTokenSchema !== undefined &&
|
|
126
|
+
decodedIdTokenSchema !== decodedIdTokenSchema_context
|
|
127
|
+
) {
|
|
128
|
+
decodedIdToken = decodedIdTokenSchema.parse(decodedIdToken);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
cache = { decodedIdToken };
|
|
132
|
+
|
|
133
|
+
return decodedIdToken;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return oidcTokens;
|
|
138
|
+
}, [
|
|
139
|
+
tokens?.accessToken,
|
|
140
|
+
tokens?.accessTokenExpirationTime,
|
|
141
|
+
tokens?.idToken,
|
|
142
|
+
tokens?.refreshToken,
|
|
143
|
+
tokens?.refreshTokenExpirationTime
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
return { oidcTokens };
|
|
147
|
+
})();
|
|
148
|
+
|
|
149
|
+
const common: OidcReact.Common = {
|
|
114
150
|
"params": oidc.params
|
|
115
151
|
};
|
|
116
152
|
|
|
117
153
|
return oidc.isUserLoggedIn
|
|
118
|
-
? id<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
: id<ReactiveOidc.NotLoggedIn>({
|
|
154
|
+
? id<OidcReact.LoggedIn<DecodedIdToken>>(
|
|
155
|
+
(assert(oidcTokens !== undefined),
|
|
156
|
+
{
|
|
157
|
+
...common,
|
|
158
|
+
"isUserLoggedIn": true,
|
|
159
|
+
oidcTokens,
|
|
160
|
+
"logout": oidc.logout,
|
|
161
|
+
"renewTokens": oidc.renewTokens
|
|
162
|
+
})
|
|
163
|
+
)
|
|
164
|
+
: id<OidcReact.NotLoggedIn>({
|
|
130
165
|
...common,
|
|
131
166
|
"isUserLoggedIn": false,
|
|
132
|
-
"login": oidc.login
|
|
133
|
-
"oidcTokens": undefined,
|
|
134
|
-
"logout": undefined
|
|
167
|
+
"login": oidc.login
|
|
135
168
|
});
|
|
136
169
|
}
|
|
137
170
|
|
|
138
|
-
return { useOidc };
|
|
171
|
+
return { OidcProvider, useOidc, prOidc };
|
|
139
172
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useRef } from "react";
|
|
2
|
+
|
|
3
|
+
export function useGuaranteedMemo<T>(fn: () => T, deps: readonly any[]): T {
|
|
4
|
+
const ref = useRef<{ v: T; prevDeps: any[] }>();
|
|
5
|
+
|
|
6
|
+
if (
|
|
7
|
+
!ref.current ||
|
|
8
|
+
deps.length !== ref.current.prevDeps.length ||
|
|
9
|
+
ref.current.prevDeps.map((v, i) => v === deps[i]).indexOf(false) >= 0
|
|
10
|
+
) {
|
|
11
|
+
ref.current = {
|
|
12
|
+
"v": fn(),
|
|
13
|
+
"prevDeps": [...deps]
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return ref.current.v;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useGuaranteedMemo<T>(fn: () => T, deps: readonly any[]): T;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
+
if (!m) return o;
|
|
5
|
+
var i = m.call(o), r, ar = [], e;
|
|
6
|
+
try {
|
|
7
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
+
}
|
|
9
|
+
catch (error) { e = { error: error }; }
|
|
10
|
+
finally {
|
|
11
|
+
try {
|
|
12
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
+
}
|
|
14
|
+
finally { if (e) throw e.error; }
|
|
15
|
+
}
|
|
16
|
+
return ar;
|
|
17
|
+
};
|
|
18
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
19
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
20
|
+
if (ar || !(i in from)) {
|
|
21
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
22
|
+
ar[i] = from[i];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.useGuaranteedMemo = void 0;
|
|
29
|
+
var react_1 = require("react");
|
|
30
|
+
function useGuaranteedMemo(fn, deps) {
|
|
31
|
+
var ref = (0, react_1.useRef)();
|
|
32
|
+
if (!ref.current ||
|
|
33
|
+
deps.length !== ref.current.prevDeps.length ||
|
|
34
|
+
ref.current.prevDeps.map(function (v, i) { return v === deps[i]; }).indexOf(false) >= 0) {
|
|
35
|
+
ref.current = {
|
|
36
|
+
"v": fn(),
|
|
37
|
+
"prevDeps": __spreadArray([], __read(deps), false)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return ref.current.v;
|
|
41
|
+
}
|
|
42
|
+
exports.useGuaranteedMemo = useGuaranteedMemo;
|
|
43
|
+
//# sourceMappingURL=useGuaranteedMemo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGuaranteedMemo.js","sourceRoot":"","sources":["../../src/tools/powerhooks/useGuaranteedMemo.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+BAA+B;AAE/B,SAAgB,iBAAiB,CAAI,EAAW,EAAE,IAAoB;IAClE,IAAM,GAAG,GAAG,IAAA,cAAM,GAA6B,CAAC;IAEhD,IACI,CAAC,GAAG,CAAC,OAAO;QACZ,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM;QAC3C,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAb,CAAa,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EACvE,CAAC;QACC,GAAG,CAAC,OAAO,GAAG;YACV,GAAG,EAAE,EAAE,EAAE;YACT,UAAU,2BAAM,IAAI,SAAC;SACxB,CAAC;IACN,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACzB,CAAC;AAfD,8CAeC"}
|