@variamosple/variamos-components 0.3.0 → 0.4.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 +2 -0
- package/dist/Components/Header/HeaderOptions.js +28 -29
- package/dist/Components/Header/submitBugReport.d.ts +1 -2
- package/dist/Components/Header/submitBugReport.js +12 -13
- package/dist/Context/NotificationContext.js +20 -20
- package/dist/Context/SessionContext.js +59 -58
- package/dist/Context/notificationAccessToken.d.ts +1 -3
- package/dist/Context/notificationAccessToken.js +13 -17
- package/dist/Context/storedSessionToken.d.ts +8 -0
- package/dist/Context/storedSessionToken.js +11 -0
- package/dist/Model/SessionInfoResponse.d.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,8 @@ import { Header, SessionProvider } from "@variamosple/variamos-components";
|
|
|
16
16
|
|
|
17
17
|
The user menu of the header has the class `variamos-header-options`; its id is generated, so tests and styles should use the class.
|
|
18
18
|
|
|
19
|
+
The session lives in the httpOnly `authToken` cookie of the admin service: requests must send it (`credentials: "include"`, or `withCredentials` with axios). Since 0.4.0 the library never keeps the token in `localStorage`, and `SessionProvider` removes the copy that older versions kept there; a front end should not add an `Authorization` header from that storage.
|
|
20
|
+
|
|
19
21
|
## Development
|
|
20
22
|
|
|
21
23
|
Requires Node 26 (`.nvmrc`, `.mise.toml`). `npm install` sets up the Git hooks: Biome and cspell on the staged files before a commit, the conventional commit format, and typecheck, lint and tests before a push.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { jsxs as f, Fragment as
|
|
2
|
-
import { useId as
|
|
1
|
+
import { jsxs as f, Fragment as v, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
import { useId as C, useState as m, useCallback as O, useEffect as T, useMemo as U } from "react";
|
|
3
3
|
import { NavDropdown as i } from "react-bootstrap";
|
|
4
|
-
import { Events as
|
|
5
|
-
import { isAllowedFor as
|
|
4
|
+
import { Events as b } from "../../Common/Events.js";
|
|
5
|
+
import { isAllowedFor as j } from "../../Common/isAllowedFor.js";
|
|
6
6
|
import "../../Context/AnalyticsContext.js";
|
|
7
|
-
import { useMenu as
|
|
7
|
+
import { useMenu as k } from "../../Context/MenuContext.js";
|
|
8
8
|
import "../../Context/NotificationContext.js";
|
|
9
9
|
import { useRouter as x } from "../../Context/RouterContext.js";
|
|
10
10
|
import { useSession as D } from "../../Context/SessionContext.js";
|
|
@@ -20,66 +20,65 @@ const c = {}, y = [
|
|
|
20
20
|
"Account/Security",
|
|
21
21
|
"Other"
|
|
22
22
|
], $ = ({
|
|
23
|
-
adminApiUrl:
|
|
23
|
+
adminApiUrl: h
|
|
24
24
|
}) => {
|
|
25
|
-
const { user:
|
|
25
|
+
const { user: t, isAuthenticated: n, logout: M } = D(), { options: d } = k(), { navigate: S } = x(), B = C(), [E, s] = m(!1), [I, p] = m(!1), [A, l] = m(null), w = h || (c == null ? void 0 : c.VITE_ADMIN_API_URL) || "/v1", e = O(() => {
|
|
26
26
|
l(null), s(!0);
|
|
27
27
|
}, []);
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
T(() => (b.subscribe("openReportBugModal", e), () => {
|
|
29
|
+
b.unsubscribe(
|
|
30
30
|
"openReportBugModal",
|
|
31
31
|
e
|
|
32
32
|
);
|
|
33
33
|
}), [e]);
|
|
34
|
-
const R = async (
|
|
34
|
+
const R = async (o, u) => {
|
|
35
35
|
p(!0), l(null);
|
|
36
|
-
const g = await N(
|
|
36
|
+
const g = await N(o, u, {
|
|
37
37
|
adminApiUrl: w,
|
|
38
|
-
reporterEmail:
|
|
39
|
-
authToken: localStorage.getItem("authToken")
|
|
38
|
+
reporterEmail: t == null ? void 0 : t.email
|
|
40
39
|
});
|
|
41
40
|
p(!1), g ? l(g) : s(!1);
|
|
42
|
-
}, a =
|
|
43
|
-
() => (d ?? []).filter((
|
|
44
|
-
[d,
|
|
41
|
+
}, a = U(
|
|
42
|
+
() => (d ?? []).filter((o) => j(o, t)),
|
|
43
|
+
[d, t]
|
|
45
44
|
);
|
|
46
|
-
return a.length === 0 && !n ? null : /* @__PURE__ */ f(
|
|
45
|
+
return a.length === 0 && !n ? null : /* @__PURE__ */ f(v, { children: [
|
|
47
46
|
/* @__PURE__ */ f(
|
|
48
47
|
i,
|
|
49
48
|
{
|
|
50
|
-
title: (
|
|
51
|
-
id:
|
|
49
|
+
title: (t == null ? void 0 : t.name) || "Options",
|
|
50
|
+
id: B,
|
|
52
51
|
className: "variamos-header-options",
|
|
53
52
|
children: [
|
|
54
|
-
a.map((
|
|
53
|
+
a.map((o) => /* @__PURE__ */ r(
|
|
55
54
|
i.Item,
|
|
56
55
|
{
|
|
57
56
|
onClick: () => {
|
|
58
|
-
if (
|
|
57
|
+
if (o.location.endsWith("#report-bug")) {
|
|
59
58
|
e();
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
|
-
|
|
63
|
-
target: F(
|
|
61
|
+
S(o.location, {
|
|
62
|
+
target: F(o.target)
|
|
64
63
|
});
|
|
65
64
|
},
|
|
66
|
-
children:
|
|
65
|
+
children: o.title
|
|
67
66
|
},
|
|
68
|
-
|
|
67
|
+
o.title
|
|
69
68
|
)),
|
|
70
69
|
n && a.length > 0 ? /* @__PURE__ */ r(i.Divider, {}) : null,
|
|
71
|
-
n ? /* @__PURE__ */ r(i.Item, { onClick:
|
|
70
|
+
n ? /* @__PURE__ */ r(i.Item, { onClick: M, children: "Logout" }) : null
|
|
72
71
|
]
|
|
73
72
|
}
|
|
74
73
|
),
|
|
75
74
|
/* @__PURE__ */ r(
|
|
76
75
|
L,
|
|
77
76
|
{
|
|
78
|
-
show:
|
|
77
|
+
show: E,
|
|
79
78
|
onHide: () => s(!1),
|
|
80
|
-
onSubmit: (
|
|
79
|
+
onSubmit: (o, u) => void R(o, u),
|
|
81
80
|
categories: y,
|
|
82
|
-
isSubmitting:
|
|
81
|
+
isSubmitting: I,
|
|
83
82
|
errorMessage: A
|
|
84
83
|
}
|
|
85
84
|
)
|
|
@@ -6,10 +6,9 @@ export interface BugReport {
|
|
|
6
6
|
export interface BugReportSender {
|
|
7
7
|
adminApiUrl: string;
|
|
8
8
|
reporterEmail?: string;
|
|
9
|
-
authToken?: string | null;
|
|
10
9
|
fetchImpl?: typeof fetch;
|
|
11
10
|
}
|
|
12
11
|
/** The bug route, next to the versioned API: ".../v1" and ".../" give "/bugs". */
|
|
13
12
|
export declare const bugReportUrl: (adminApiUrl: string) => string;
|
|
14
13
|
/** Sends the report; resolves to null once sent, or to the message to show. */
|
|
15
|
-
export declare function submitBugReport(report: BugReport, file: File | undefined, { adminApiUrl, reporterEmail,
|
|
14
|
+
export declare function submitBugReport(report: BugReport, file: File | undefined, { adminApiUrl, reporterEmail, fetchImpl }: BugReportSender): Promise<string | null>;
|
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
import { fieldOf as
|
|
2
|
-
const
|
|
3
|
-
async function
|
|
1
|
+
import { fieldOf as s } from "../../Common/fieldOf.js";
|
|
2
|
+
const p = "Failed to submit bug. Please try again.", l = (t) => `${t.replace(/\/v1$/, "").replace(/\/$/, "")}/bugs`;
|
|
3
|
+
async function m(t, n, { adminApiUrl: c, reporterEmail: a, fetchImpl: d = fetch }) {
|
|
4
4
|
const e = new FormData();
|
|
5
|
-
e.append("title", t.title), e.append("description", t.description), e.append("priority", "medium"), e.append("category", t.category),
|
|
5
|
+
e.append("title", t.title), e.append("description", t.description), e.append("priority", "medium"), e.append("category", t.category), a && e.append("reporterEmail", a), n && e.append("file", n);
|
|
6
6
|
try {
|
|
7
|
-
const r = await l(
|
|
7
|
+
const r = await d(l(c), {
|
|
8
8
|
method: "POST",
|
|
9
|
-
headers: i ? { Authorization: `Bearer ${i}` } : {},
|
|
10
9
|
body: e,
|
|
11
10
|
credentials: "include"
|
|
12
|
-
}),
|
|
13
|
-
if (r.ok && !
|
|
14
|
-
const o =
|
|
15
|
-
return typeof o == "string" && o !== "" ? o :
|
|
11
|
+
}), i = await r.json();
|
|
12
|
+
if (r.ok && !s(i, "errorCode")) return null;
|
|
13
|
+
const o = s(i, "message");
|
|
14
|
+
return typeof o == "string" && o !== "" ? o : p;
|
|
16
15
|
} catch (r) {
|
|
17
|
-
return console.error(r),
|
|
16
|
+
return console.error(r), p;
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
export {
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
l as bugReportUrl,
|
|
21
|
+
m as submitBugReport
|
|
23
22
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as ve } from "react/jsx-runtime";
|
|
2
|
-
import { createContext as Ee, useMemo as P, useEffect as ke, useContext as
|
|
3
|
-
import { createAccessTokenProvider as
|
|
2
|
+
import { createContext as Ee, useMemo as P, useEffect as ke, useContext as Ae } from "react";
|
|
3
|
+
import { createAccessTokenProvider as Te, accessTokenUrl as Oe } from "./notificationAccessToken.js";
|
|
4
4
|
import { createNotificationApi as Re, notificationItemOf as Ce } from "./notificationApi.js";
|
|
5
5
|
import { useSession as Se } from "./SessionContext.js";
|
|
6
6
|
import { useNotificationList as Be, useNotificationChanges as Ne, useNotificationPreferences as xe } from "./useNotificationState.js";
|
|
@@ -116,10 +116,10 @@ function Ue() {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
let I;
|
|
119
|
-
function
|
|
119
|
+
function A(n) {
|
|
120
120
|
return n.reduce((e, t) => e + t.length, 0);
|
|
121
121
|
}
|
|
122
|
-
function
|
|
122
|
+
function T(n, e) {
|
|
123
123
|
if (n[0].length === e)
|
|
124
124
|
return n.shift();
|
|
125
125
|
const t = new Uint8Array(e);
|
|
@@ -136,28 +136,28 @@ function Ve(n, e) {
|
|
|
136
136
|
transform(o, c) {
|
|
137
137
|
for (t.push(o); ; ) {
|
|
138
138
|
if (s === 0) {
|
|
139
|
-
if (
|
|
139
|
+
if (A(t) < 1)
|
|
140
140
|
break;
|
|
141
|
-
const h =
|
|
141
|
+
const h = T(t, 1);
|
|
142
142
|
r = (h[0] & 128) === 128, i = h[0] & 127, i < 126 ? s = 3 : i === 126 ? s = 1 : s = 2;
|
|
143
143
|
} else if (s === 1) {
|
|
144
|
-
if (
|
|
144
|
+
if (A(t) < 2)
|
|
145
145
|
break;
|
|
146
|
-
const h =
|
|
146
|
+
const h = T(t, 2);
|
|
147
147
|
i = new DataView(h.buffer, h.byteOffset, h.length).getUint16(0), s = 3;
|
|
148
148
|
} else if (s === 2) {
|
|
149
|
-
if (
|
|
149
|
+
if (A(t) < 8)
|
|
150
150
|
break;
|
|
151
|
-
const h =
|
|
151
|
+
const h = T(t, 8), l = new DataView(h.buffer, h.byteOffset, h.length), f = l.getUint32(0);
|
|
152
152
|
if (f > Math.pow(2, 21) - 1) {
|
|
153
153
|
c.enqueue(F);
|
|
154
154
|
break;
|
|
155
155
|
}
|
|
156
156
|
i = f * Math.pow(2, 32) + l.getUint32(4), s = 3;
|
|
157
157
|
} else {
|
|
158
|
-
if (
|
|
158
|
+
if (A(t) < i)
|
|
159
159
|
break;
|
|
160
|
-
const h =
|
|
160
|
+
const h = T(t, i);
|
|
161
161
|
c.enqueue(W(r ? h : I.decode(h), e)), s = 0;
|
|
162
162
|
}
|
|
163
163
|
if (i === 0 || i > n) {
|
|
@@ -1422,7 +1422,7 @@ const kt = Number.isInteger || function(n) {
|
|
|
1422
1422
|
function re(n) {
|
|
1423
1423
|
return Object.prototype.toString.call(n) === "[object Object]";
|
|
1424
1424
|
}
|
|
1425
|
-
const
|
|
1425
|
+
const At = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1426
1426
|
__proto__: null,
|
|
1427
1427
|
Decoder: z,
|
|
1428
1428
|
Encoder: vt,
|
|
@@ -1435,7 +1435,7 @@ function y(n, e, t) {
|
|
|
1435
1435
|
n.off(e, t);
|
|
1436
1436
|
};
|
|
1437
1437
|
}
|
|
1438
|
-
const
|
|
1438
|
+
const Tt = Object.freeze({
|
|
1439
1439
|
connect: 1,
|
|
1440
1440
|
connect_error: 1,
|
|
1441
1441
|
disconnect: 1,
|
|
@@ -1560,7 +1560,7 @@ class _e extends u {
|
|
|
1560
1560
|
*/
|
|
1561
1561
|
emit(e, ...t) {
|
|
1562
1562
|
var s, i, r;
|
|
1563
|
-
if (
|
|
1563
|
+
if (Tt.hasOwnProperty(e))
|
|
1564
1564
|
throw new Error('"' + e.toString() + '" is a reserved event name');
|
|
1565
1565
|
if (t.unshift(e), this._opts.retries && !this.flags.fromQueue && !this.flags.volatile)
|
|
1566
1566
|
return this._addToQueue(t), this;
|
|
@@ -2067,7 +2067,7 @@ class H extends u {
|
|
|
2067
2067
|
max: this.reconnectionDelayMax(),
|
|
2068
2068
|
jitter: this.randomizationFactor()
|
|
2069
2069
|
}), this.timeout(t.timeout == null ? 2e4 : t.timeout), this._readyState = "closed", this.uri = e;
|
|
2070
|
-
const i = t.parser ||
|
|
2070
|
+
const i = t.parser || At;
|
|
2071
2071
|
this.encoder = new i.Encoder(), this.decoder = new i.Decoder(), this._autoConnect = t.autoConnect !== !1, this._autoConnect && this.open();
|
|
2072
2072
|
}
|
|
2073
2073
|
reconnection(e) {
|
|
@@ -2313,10 +2313,10 @@ Object.assign(B, {
|
|
|
2313
2313
|
const we = Ee(
|
|
2314
2314
|
void 0
|
|
2315
2315
|
), Ot = (n) => async () => {
|
|
2316
|
-
const
|
|
2316
|
+
const e = await (n == null ? void 0 : n.get());
|
|
2317
2317
|
return {
|
|
2318
2318
|
"Content-Type": "application/json",
|
|
2319
|
-
...
|
|
2319
|
+
...e ? { Authorization: `Bearer ${e}` } : {}
|
|
2320
2320
|
};
|
|
2321
2321
|
}, Pt = ({
|
|
2322
2322
|
apiUrl: n,
|
|
@@ -2325,7 +2325,7 @@ const we = Ee(
|
|
|
2325
2325
|
}) => {
|
|
2326
2326
|
var Z;
|
|
2327
2327
|
const s = (Z = Se().user) == null ? void 0 : Z.id, i = P(
|
|
2328
|
-
() => e ?
|
|
2328
|
+
() => e ? Te({ url: Oe(e) }) : null,
|
|
2329
2329
|
[e]
|
|
2330
2330
|
), r = P(
|
|
2331
2331
|
() => s ? Re({
|
|
@@ -2389,7 +2389,7 @@ const we = Ee(
|
|
|
2389
2389
|
);
|
|
2390
2390
|
return /* @__PURE__ */ ve(we.Provider, { value: be, children: t });
|
|
2391
2391
|
}, qt = () => {
|
|
2392
|
-
const n =
|
|
2392
|
+
const n = Ae(we);
|
|
2393
2393
|
if (n === void 0)
|
|
2394
2394
|
throw new Error(
|
|
2395
2395
|
"useNotifications must be used within a NotificationProvider"
|
|
@@ -1,90 +1,91 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { createContext as
|
|
3
|
-
import { Events as
|
|
4
|
-
import { usePageVisibility as
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
t && localStorage.setItem("authToken", t);
|
|
1
|
+
import { jsx as G } from "react/jsx-runtime";
|
|
2
|
+
import { createContext as L, useState as g, useEffect as d, useContext as T } from "react";
|
|
3
|
+
import { Events as _ } from "../Common/Events.js";
|
|
4
|
+
import { usePageVisibility as j } from "../Hooks/usePageVisibility.js";
|
|
5
|
+
import { forgetStoredSessionToken as s } from "./storedSessionToken.js";
|
|
6
|
+
const I = L(void 0), w = "guestId", E = (r) => {
|
|
7
|
+
r && _.publish("variamosNavigate", r);
|
|
9
8
|
};
|
|
10
|
-
function f(
|
|
11
|
-
var a, c
|
|
12
|
-
return
|
|
9
|
+
function f(r, i) {
|
|
10
|
+
var a, c;
|
|
11
|
+
return r != null && r.errorCode ? (i(null), !1) : (i(((a = r == null ? void 0 : r.data) == null ? void 0 : a.user) ?? null), E((c = r == null ? void 0 : r.data) == null ? void 0 : c.redirect), !0);
|
|
13
12
|
}
|
|
14
|
-
const
|
|
15
|
-
loginUrl:
|
|
13
|
+
const S = "Sign in error.", V = ({
|
|
14
|
+
loginUrl: r,
|
|
16
15
|
getSessionInfo: i,
|
|
17
16
|
requestSignUp: a,
|
|
18
17
|
requestSignIn: c,
|
|
19
|
-
requestSignInAsGuest:
|
|
20
|
-
requestLogout:
|
|
21
|
-
children:
|
|
18
|
+
requestSignInAsGuest: l,
|
|
19
|
+
requestLogout: y,
|
|
20
|
+
children: C
|
|
22
21
|
}) => {
|
|
23
|
-
const [
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const [h, e] = g(null), [x, o] = g(!0), u = h !== null, m = j();
|
|
23
|
+
d(() => {
|
|
24
|
+
s();
|
|
25
|
+
}, []), d(() => {
|
|
26
|
+
o(!0), i().then((t) => f(t, e)).catch(() => {
|
|
26
27
|
e(null);
|
|
27
28
|
}).finally(() => o(!1));
|
|
28
|
-
}, [i]),
|
|
29
|
-
if (!(u &&
|
|
30
|
-
const
|
|
31
|
-
i().then((
|
|
29
|
+
}, [i]), d(() => {
|
|
30
|
+
if (!(u && m)) return;
|
|
31
|
+
const t = () => {
|
|
32
|
+
i().then((R) => f(R, e)).catch(() => {
|
|
32
33
|
e(null);
|
|
33
34
|
});
|
|
34
35
|
};
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
return () => clearInterval(
|
|
38
|
-
}, [u,
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
),
|
|
36
|
+
t();
|
|
37
|
+
const n = setInterval(t, 6e4);
|
|
38
|
+
return () => clearInterval(n);
|
|
39
|
+
}, [u, m, i]);
|
|
40
|
+
const v = (t) => i().then((n) => (f(n, e) || t.withError(
|
|
41
|
+
n.errorCode ?? 500,
|
|
42
|
+
n.message ?? S
|
|
43
|
+
), t)).catch(() => (e(null), t.withError(500, S))), P = (t) => {
|
|
43
44
|
if (!a)
|
|
44
45
|
throw new Error("requestSignUp is not defined.");
|
|
45
|
-
return o(!0), a(
|
|
46
|
-
},
|
|
46
|
+
return o(!0), a(t).finally(() => o(!1));
|
|
47
|
+
}, b = (t) => {
|
|
47
48
|
if (!c)
|
|
48
49
|
throw new Error("requestSignIn is not defined.");
|
|
49
|
-
return o(!0), c(
|
|
50
|
-
(
|
|
50
|
+
return o(!0), c(t).then(
|
|
51
|
+
(n) => n != null && n.errorCode ? n : v(n)
|
|
51
52
|
).finally(() => o(!1));
|
|
52
|
-
},
|
|
53
|
-
if (!
|
|
53
|
+
}, A = () => {
|
|
54
|
+
if (!l)
|
|
54
55
|
throw new Error("requestSignInAsGuest is not defined.");
|
|
55
|
-
return o(!0),
|
|
56
|
-
var
|
|
57
|
-
return
|
|
56
|
+
return o(!0), l(localStorage.getItem(w)).then((t) => {
|
|
57
|
+
var n;
|
|
58
|
+
return t != null && t.errorCode ? t : (localStorage.setItem(w, ((n = t == null ? void 0 : t.data) == null ? void 0 : n.id) || ""), v(t));
|
|
58
59
|
}).finally(() => o(!1));
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
}, N = () => {
|
|
61
|
+
y().then(() => {
|
|
62
|
+
s(), E(r), setTimeout(() => {
|
|
62
63
|
e(null);
|
|
63
64
|
}, 200);
|
|
64
65
|
});
|
|
65
66
|
};
|
|
66
|
-
return /* @__PURE__ */
|
|
67
|
-
|
|
67
|
+
return /* @__PURE__ */ G(
|
|
68
|
+
I.Provider,
|
|
68
69
|
{
|
|
69
70
|
value: {
|
|
70
|
-
user:
|
|
71
|
+
user: h,
|
|
71
72
|
isAuthenticated: u,
|
|
72
|
-
logout:
|
|
73
|
-
signUp:
|
|
74
|
-
signIn:
|
|
75
|
-
signInAsGuest:
|
|
76
|
-
isLoading:
|
|
73
|
+
logout: N,
|
|
74
|
+
signUp: P,
|
|
75
|
+
signIn: b,
|
|
76
|
+
signInAsGuest: A,
|
|
77
|
+
isLoading: x
|
|
77
78
|
},
|
|
78
|
-
children:
|
|
79
|
+
children: C
|
|
79
80
|
}
|
|
80
81
|
);
|
|
81
|
-
},
|
|
82
|
-
const
|
|
83
|
-
if (
|
|
82
|
+
}, z = () => {
|
|
83
|
+
const r = T(I);
|
|
84
|
+
if (r === void 0)
|
|
84
85
|
throw new Error("useSession must be used within a SessionProvider");
|
|
85
|
-
return
|
|
86
|
+
return r;
|
|
86
87
|
};
|
|
87
88
|
export {
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
V as SessionProvider,
|
|
90
|
+
z as useSession
|
|
90
91
|
};
|
|
@@ -10,8 +10,6 @@ export interface NotificationAccessToken {
|
|
|
10
10
|
export declare function accessTokenUrl(adminApiUrl: string): string;
|
|
11
11
|
export interface AccessTokenProviderOptions {
|
|
12
12
|
url: string;
|
|
13
|
-
/** Session token of the platform, sent to the admin service. */
|
|
14
|
-
getSessionToken?: () => string | null;
|
|
15
13
|
fetchImpl?: typeof fetch;
|
|
16
14
|
now?: () => number;
|
|
17
15
|
/** A token is renewed this long before it expires. */
|
|
@@ -26,4 +24,4 @@ export interface AccessTokenProvider {
|
|
|
26
24
|
* Keeps one token in memory, renews it shortly before it expires, and
|
|
27
25
|
* shares a single request between concurrent callers.
|
|
28
26
|
*/
|
|
29
|
-
export declare function createAccessTokenProvider({ url,
|
|
27
|
+
export declare function createAccessTokenProvider({ url, fetchImpl, now, refreshMarginMs, }: AccessTokenProviderOptions): AccessTokenProvider;
|
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
import { fieldOf as
|
|
2
|
-
function
|
|
1
|
+
import { fieldOf as s } from "../Common/fieldOf.js";
|
|
2
|
+
function d(t) {
|
|
3
3
|
return `${t.replace(/\/+$/, "").replace(/\/v1$/, "")}/v1/notifications/access-token`;
|
|
4
4
|
}
|
|
5
|
-
function
|
|
5
|
+
function k({
|
|
6
6
|
url: t,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
refreshMarginMs: p = 6e4
|
|
7
|
+
fetchImpl: o = (...e) => fetch(...e),
|
|
8
|
+
now: i = Date.now,
|
|
9
|
+
refreshMarginMs: u = 6e4
|
|
11
10
|
}) {
|
|
12
11
|
let e = null, n = null;
|
|
13
|
-
const
|
|
12
|
+
const f = async () => {
|
|
14
13
|
try {
|
|
15
|
-
const
|
|
16
|
-
credentials: "include",
|
|
17
|
-
headers: a ? { Authorization: `Bearer ${a}` } : {}
|
|
18
|
-
});
|
|
14
|
+
const c = await o(t, { credentials: "include" });
|
|
19
15
|
if (!c.ok) return null;
|
|
20
|
-
const l =
|
|
21
|
-
return typeof r != "string" || Number.isNaN(
|
|
16
|
+
const l = s(await c.json(), "data"), r = s(l, "token"), a = Date.parse(String(s(l, "expiresAt")));
|
|
17
|
+
return typeof r != "string" || Number.isNaN(a) ? null : (e = { token: r, expiresAt: a }, r);
|
|
22
18
|
} catch {
|
|
23
19
|
return null;
|
|
24
20
|
}
|
|
25
21
|
};
|
|
26
22
|
return {
|
|
27
23
|
get() {
|
|
28
|
-
return e &&
|
|
24
|
+
return e && i() < e.expiresAt - u ? Promise.resolve(e.token) : (n ?? (n = f().finally(() => {
|
|
29
25
|
n = null;
|
|
30
26
|
})), n);
|
|
31
27
|
},
|
|
@@ -35,6 +31,6 @@ function h({
|
|
|
35
31
|
};
|
|
36
32
|
}
|
|
37
33
|
export {
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
d as accessTokenUrl,
|
|
35
|
+
k as createAccessTokenProvider
|
|
40
36
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Key under which versions before 0.4.0 kept the session token. */
|
|
2
|
+
export declare const STORED_TOKEN_KEY = "authToken";
|
|
3
|
+
/**
|
|
4
|
+
* Removes the session token that versions before 0.4.0 kept in the browser
|
|
5
|
+
* storage, where any script of the page can read it. The session lives in
|
|
6
|
+
* the httpOnly cookie of the admin service alone (EV-117).
|
|
7
|
+
*/
|
|
8
|
+
export declare function forgetStoredSessionToken(storage?: Pick<Storage, "removeItem"> | undefined): void;
|