diff --git a/dist/index.js b/dist/index.js index a49dd85..8983813 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,55 +1,55 @@ -import { jsxs as I, jsx as u } from "react/jsx-runtime"; -import { useState as B, useRef as T, useEffect as A, useCallback as D, createContext as U, useMemo as F, useContext as H } from "react"; -import { HStack as S, IconButton as K, Button as j, Input as L, Text as k } from "@chakra-ui/react"; -import { IoChevronForwardOutline as V, IoChevronBackOutline as W } from "react-icons/io5"; -import X from "keycloak-js"; -import { useQuery as Z } from "@tanstack/react-query"; -import P from "axios"; -const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => String(e).replace(/\d/g, (t) => "۰۱۲۳۴۵۶۷۸۹"[Number(t)]), E = (e) => String(e).replace(/[۰-۹]/g, (o) => String("۰۱۲۳۴۵۶۷۸۹".indexOf(o))), ye = ({ +import { jsxs as I, jsx as a } from "react/jsx-runtime"; +import { useState as B, useRef as z, useEffect as C, useCallback as E, createContext as G, useMemo as R, useContext as Z } from "react"; +import { HStack as k, IconButton as D, Button as V, Input as W, Text as S } from "@chakra-ui/react"; +import { IoChevronForwardOutline as O, IoChevronBackOutline as q } from "react-icons/io5"; +import P from "keycloak-js"; +import { useQuery as ee } from "@tanstack/react-query"; +import te from "axios"; +const Be = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), p = (e) => String(e).replace(/\d/g, (t) => "۰۱۲۳۴۵۶۷۸۹"[Number(t)]), K = (e) => String(e).replace(/[۰-۹]/g, (r) => String("۰۱۲۳۴۵۶۷۸۹".indexOf(r))), Ce = ({ currentPage: e, totalPages: t, - totalCount: o, + totalCount: r, onPageChange: l }) => { - const [d, i] = B(f(e)), [w, r] = B(!1), [s, c] = B(null), m = T(null), y = [.../* @__PURE__ */ new Set([1, e, t])].filter( + const [c, i] = B(p(e)), [u, o] = B(!1), [f, s] = B(null), w = z(null), y = [.../* @__PURE__ */ new Set([1, e, t])].filter( (n) => n >= 1 && n <= t ); - A(() => { - if (s !== null) { - e === s && (c(null), r(!1), i(f(e))); + C(() => { + if (f !== null) { + e === f && (s(null), o(!1), i(p(e))); return; } - w || i(f(e)); - }, [e, w, s]), A(() => { - if (!w || !d || s !== null) return; - const n = parseInt(E(d), 10); + u || i(p(e)); + }, [e, u, f]), C(() => { + if (!u || !c || f !== null) return; + const n = parseInt(K(c), 10); if (isNaN(n)) return; - const p = setTimeout(() => { + const h = setTimeout(() => { var b; - const h = Math.min(Math.max(n, 1), t); - h !== e ? (c(h), i(f(h)), l(h)) : (r(!1), i(f(e))), (b = m.current) == null || b.blur(); + const m = Math.min(Math.max(n, 1), t); + m !== e ? (s(m), i(p(m)), l(m)) : (o(!1), i(p(e))), (b = w.current) == null || b.blur(); }, 1e3); - return () => clearTimeout(p); + return () => clearTimeout(h); }, [ - d, - w, - s, + c, + u, + f, t, e, l ]); const v = () => { - var h, b; - const n = parseInt(E(d), 10); + var m, b; + const n = parseInt(K(c), 10); if (isNaN(n)) { - i(f(e)), r(!1), c(null), (h = m.current) == null || h.blur(); + i(p(e)), o(!1), s(null), (m = w.current) == null || m.blur(); return; } - const p = Math.min(Math.max(n, 1), t); - p !== e ? (c(p), i(f(p)), l(p)) : (i(f(e)), r(!1), c(null)), (b = m.current) == null || b.blur(); + const h = Math.min(Math.max(n, 1), t); + h !== e ? (s(h), i(p(h)), l(h)) : (i(p(e)), o(!1), s(null)), (b = w.current) == null || b.blur(); }; - return t === 0 || !o ? null : /* @__PURE__ */ I( - S, + return t === 0 || !r ? null : /* @__PURE__ */ I( + k, { justifyContent: "space-around", backgroundColor: "white", @@ -60,9 +60,9 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S borderColor: "blue.200", w: "100%", children: [ - /* @__PURE__ */ I(S, { spacing: 2, alignItems: "center", justifyContent: "center", children: [ - /* @__PURE__ */ u( - K, + /* @__PURE__ */ I(k, { spacing: 2, alignItems: "center", justifyContent: "center", children: [ + /* @__PURE__ */ a( + D, { size: "md", bg: "#e6e6f1", @@ -70,12 +70,12 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: "#cbcbe8" }, onClick: () => l(e - 1), isDisabled: e === 1, - icon: /* @__PURE__ */ u(V, {}), + icon: /* @__PURE__ */ a(O, {}), "aria-label": "صفحه قبلی" } ), - y.map((n) => /* @__PURE__ */ u( - j, + y.map((n) => /* @__PURE__ */ a( + V, { size: "md", px: 2, @@ -84,12 +84,12 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: e === n ? "#4B49AC" : "#cbcbe8" }, onClick: () => l(n), variant: "soft", - children: f(n) + children: p(n) }, n )), - /* @__PURE__ */ u( - K, + /* @__PURE__ */ a( + D, { size: "md", bg: "#e6e6f1", @@ -97,28 +97,28 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: "#cbcbe8" }, onClick: () => l(e + 1), isDisabled: e === t, - icon: /* @__PURE__ */ u(W, {}), + icon: /* @__PURE__ */ a(q, {}), "aria-label": "صفحه بعدی" } ), - /* @__PURE__ */ u( - L, + /* @__PURE__ */ a( + W, { - ref: m, + ref: w, type: "text", inputMode: "numeric", placeholder: "صفحه", w: "56px", - value: d, + value: c, onFocus: () => { - r(!0), c(null), i(""); + o(!0), s(null), i(""); }, onChange: (n) => { - const p = n.target.value, h = E(p).replace(/\D/g, ""); - i(f(h)); + const h = n.target.value, m = K(h).replace(/\D/g, ""); + i(p(m)); }, onBlur: () => { - d || (i(f(e)), r(!1), c(null)); + c || (i(p(e)), o(!1), s(null)); }, onKeyDown: (n) => { n.key === "Enter" && v(); @@ -131,58 +131,58 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S } ) ] }), - /* @__PURE__ */ I(S, { spacing: 2, children: [ - /* @__PURE__ */ u(k, { w: "auto", fontWeight: "bold", whiteSpace: "nowrap", children: "تعداد کل:" }), - /* @__PURE__ */ u(k, { children: f(o) }) + /* @__PURE__ */ I(k, { spacing: 2, children: [ + /* @__PURE__ */ a(S, { w: "auto", fontWeight: "bold", whiteSpace: "nowrap", children: "تعداد کل:" }), + /* @__PURE__ */ a(S, { children: p(r) }) ] }) ] } ); -}, xe = ({ +}, ke = ({ currentPage: e, totalPages: t, - totalCount: o, + totalCount: r, onPageChange: l }) => { - const [d, i] = B(f(e)), [w, r] = B(!1), [s, c] = B(null), m = T(null), y = Array.from( + const [c, i] = B(p(e)), [u, o] = B(!1), [f, s] = B(null), w = z(null), y = Array.from( /* @__PURE__ */ new Set([1, e, e + 1, t]) - ).filter((n) => n >= 1 && n <= t).sort((n, p) => n - p); - A(() => { - if (s !== null) { - e === s && (c(null), r(!1), i(f(e))); + ).filter((n) => n >= 1 && n <= t).sort((n, h) => n - h); + C(() => { + if (f !== null) { + e === f && (s(null), o(!1), i(p(e))); return; } - w || i(f(e)); - }, [e, w, s]), A(() => { - if (!w || !d || s !== null) return; - const n = parseInt(E(d), 10); + u || i(p(e)); + }, [e, u, f]), C(() => { + if (!u || !c || f !== null) return; + const n = parseInt(K(c), 10); if (isNaN(n)) return; - const p = setTimeout(() => { + const h = setTimeout(() => { var b; - const h = Math.min(Math.max(n, 1), t); - h !== e ? (c(h), i(f(h)), l(h)) : (r(!1), i(f(e))), (b = m.current) == null || b.blur(); + const m = Math.min(Math.max(n, 1), t); + m !== e ? (s(m), i(p(m)), l(m)) : (o(!1), i(p(e))), (b = w.current) == null || b.blur(); }, 1e3); - return () => clearTimeout(p); + return () => clearTimeout(h); }, [ - d, - w, - s, + c, + u, + f, t, e, l ]); const v = () => { - var h, b; - const n = parseInt(E(d), 10); + var m, b; + const n = parseInt(K(c), 10); if (isNaN(n)) { - i(f(e)), r(!1), c(null), (h = m.current) == null || h.blur(); + i(p(e)), o(!1), s(null), (m = w.current) == null || m.blur(); return; } - const p = Math.min(Math.max(n, 1), t); - p !== e ? (c(p), i(f(p)), l(p)) : (i(f(e)), r(!1), c(null)), (b = m.current) == null || b.blur(); + const h = Math.min(Math.max(n, 1), t); + h !== e ? (s(h), i(p(h)), l(h)) : (i(p(e)), o(!1), s(null)), (b = w.current) == null || b.blur(); }; - return t === 0 || !o ? null : /* @__PURE__ */ I( - S, + return t === 0 || !r ? null : /* @__PURE__ */ I( + k, { justifyContent: "space-around", backgroundColor: "white", @@ -193,15 +193,15 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S borderColor: "blue.200", w: "100%", children: [ - /* @__PURE__ */ I(S, { spacing: 2, whiteSpace: "nowrap", children: [ - /* @__PURE__ */ u(k, { fontWeight: "bold", children: "صفحه" }), - /* @__PURE__ */ u(k, { children: f(e) }), - /* @__PURE__ */ u(k, { fontWeight: "bold", children: "از" }), - /* @__PURE__ */ u(k, { children: f(t) }) + /* @__PURE__ */ I(k, { spacing: 2, whiteSpace: "nowrap", children: [ + /* @__PURE__ */ a(S, { fontWeight: "bold", children: "صفحه" }), + /* @__PURE__ */ a(S, { children: p(e) }), + /* @__PURE__ */ a(S, { fontWeight: "bold", children: "از" }), + /* @__PURE__ */ a(S, { children: p(t) }) ] }), - /* @__PURE__ */ I(S, { spacing: 2, alignItems: "center", justifyContent: "center", children: [ - /* @__PURE__ */ u( - K, + /* @__PURE__ */ I(k, { spacing: 2, alignItems: "center", justifyContent: "center", children: [ + /* @__PURE__ */ a( + D, { size: "md", bg: "#e6e6f1", @@ -209,12 +209,12 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: "#cbcbe8" }, onClick: () => l(e - 1), isDisabled: e === 1, - icon: /* @__PURE__ */ u(V, {}), + icon: /* @__PURE__ */ a(O, {}), "aria-label": "صفحه قبلی" } ), - y.map((n) => /* @__PURE__ */ u( - j, + y.map((n) => /* @__PURE__ */ a( + V, { size: "md", bg: e === n ? "#4B49AC" : "#e6e6f1", @@ -222,12 +222,12 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: e === n ? "#4B49AC" : "#cbcbe8" }, onClick: () => l(n), variant: "soft", - children: f(n) + children: p(n) }, n )), - /* @__PURE__ */ u( - K, + /* @__PURE__ */ a( + D, { size: "md", bg: "#e6e6f1", @@ -235,28 +235,28 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: "#cbcbe8" }, onClick: () => l(e + 1), isDisabled: e === t, - icon: /* @__PURE__ */ u(W, {}), + icon: /* @__PURE__ */ a(q, {}), "aria-label": "صفحه بعدی" } ), - /* @__PURE__ */ u( - L, + /* @__PURE__ */ a( + W, { - ref: m, + ref: w, type: "text", inputMode: "numeric", placeholder: "صفحه", w: "100px", - value: d, + value: c, onFocus: () => { - r(!0), c(null), i(""); + o(!0), s(null), i(""); }, onChange: (n) => { - const p = n.target.value, h = E(p).replace(/\D/g, ""); - i(f(h)); + const h = n.target.value, m = K(h).replace(/\D/g, ""); + i(p(m)); }, onBlur: () => { - d || (i(f(e)), r(!1), c(null)); + c || (i(p(e)), o(!1), s(null)); }, onKeyDown: (n) => { n.key === "Enter" && v(); @@ -269,69 +269,69 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S } ) ] }), - /* @__PURE__ */ I(S, { spacing: 2, whiteSpace: "nowrap", children: [ - /* @__PURE__ */ u(k, { fontWeight: "bold", children: "تعداد کل:" }), - /* @__PURE__ */ u(k, { children: f(o) }) + /* @__PURE__ */ I(k, { spacing: 2, whiteSpace: "nowrap", children: [ + /* @__PURE__ */ a(S, { fontWeight: "bold", children: "تعداد کل:" }), + /* @__PURE__ */ a(S, { children: p(r) }) ] }) ] } ); -}, ve = ({ +}, Se = ({ currentPage: e, totalPages: t, - totalCount: o, + totalCount: r, onPageChange: l }) => { - const [d, i] = B(""), [w, r] = B(!1), [s, c] = B(null), m = T(null), y = s ?? e, v = D( + const [c, i] = B(""), [u, o] = B(!1), [f, s] = B(null), w = z(null), y = f ?? e, v = E( (x) => { - const C = Math.min(Math.max(x, 1), t); - r(!1), i(""), c(null), C !== e && l(C); + const A = Math.min(Math.max(x, 1), t); + o(!1), i(""), s(null), A !== e && l(A); }, [e, t, l] - ), n = D(() => { - if (!d) { - r(!1), i(""), c(null); + ), n = E(() => { + if (!c) { + o(!1), i(""), s(null); return; } - const x = parseInt(E(d), 10); + const x = parseInt(K(c), 10); if (isNaN(x)) { - r(!1), i(""), c(null); + o(!1), i(""), s(null); return; } - const C = Math.min(Math.max(x, 1), t); - r(!1), i(""), C !== e ? (c(C), l(C)) : c(null); - }, [d, e, t, l]); - A(() => { + const A = Math.min(Math.max(x, 1), t); + o(!1), i(""), A !== e ? (s(A), l(A)) : s(null); + }, [c, e, t, l]); + C(() => { var x; - w && ((x = m.current) == null || x.focus()); - }, [w]), A(() => { - s !== null && e === s && c(null); - }, [e, s]), A(() => { - if (!w || !d) return; + u && ((x = w.current) == null || x.focus()); + }, [u]), C(() => { + f !== null && e === f && s(null); + }, [e, f]), C(() => { + if (!u || !c) return; const x = setTimeout(() => { n(); }, 1e3); return () => clearTimeout(x); - }, [d, w, n]); - const p = () => { - c(null), i(""), r(!0); - }, h = (x, C = !1) => /* @__PURE__ */ u( - j, + }, [c, u, n]); + const h = () => { + s(null), i(""), o(!0); + }, m = (x, A = !1) => /* @__PURE__ */ a( + V, { size: "md", - bg: C ? "#4B49AC" : "#e6e6f1", - color: C ? "#e6e6f1" : "#4B49AC", - _hover: { bg: C ? "#4B49AC" : "#cbcbe8" }, - onClick: C ? p : () => v(x), + bg: A ? "#4B49AC" : "#e6e6f1", + color: A ? "#e6e6f1" : "#4B49AC", + _hover: { bg: A ? "#4B49AC" : "#cbcbe8" }, + onClick: A ? h : () => v(x), variant: "soft", - children: f(x) + children: p(x) }, x ); - if (t === 0 || !o) return null; - const b = t > 1 && y !== 1, M = t > 1 && y !== t; - return /* @__PURE__ */ u( - S, + if (t === 0 || !r) return null; + const b = t > 1 && y !== 1, _ = t > 1 && y !== t; + return /* @__PURE__ */ a( + k, { justifyContent: "center", backgroundColor: "white", @@ -341,9 +341,9 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S border: "1px", borderColor: "blue.200", w: "100%", - children: /* @__PURE__ */ I(S, { spacing: 2, alignItems: "center", justifyContent: "center", children: [ - /* @__PURE__ */ u( - K, + children: /* @__PURE__ */ I(k, { spacing: 2, alignItems: "center", justifyContent: "center", children: [ + /* @__PURE__ */ a( + D, { size: "md", bg: "#e6e6f1", @@ -351,29 +351,29 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: "#cbcbe8" }, onClick: () => v(y - 1), isDisabled: y === 1, - icon: /* @__PURE__ */ u(V, {}), + icon: /* @__PURE__ */ a(O, {}), "aria-label": "صفحه قبلی" } ), - b && h(1), - w ? /* @__PURE__ */ u( - L, + b && m(1), + u ? /* @__PURE__ */ a( + W, { - ref: m, + ref: w, type: "text", inputMode: "numeric", placeholder: "صفحه", w: "48px", - value: d, + value: c, onChange: (x) => { - const C = x.target.value, g = E(C).replace(/\D/g, ""); - i(f(g)); + const A = x.target.value, X = K(A).replace(/\D/g, ""); + i(p(X)); }, onBlur: () => { - d ? n() : (i(""), r(!1), c(null)); + c ? n() : (i(""), o(!1), s(null)); }, onKeyDown: (x) => { - x.key === "Enter" && n(), x.key === "Escape" && (i(""), r(!1), c(null)); + x.key === "Enter" && n(), x.key === "Escape" && (i(""), o(!1), s(null)); }, textAlign: "center", color: "#1D2939", @@ -381,10 +381,10 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S minW: 0, dir: "ltr" } - ) : h(y, !0), - M && h(t), - /* @__PURE__ */ u( - K, + ) : m(y, !0), + _ && m(t), + /* @__PURE__ */ a( + D, { size: "md", bg: "#e6e6f1", @@ -392,7 +392,7 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S _hover: { bg: "#cbcbe8" }, onClick: () => v(y + 1), isDisabled: y === t, - icon: /* @__PURE__ */ u(W, {}), + icon: /* @__PURE__ */ a(q, {}), "aria-label": "صفحه بعدی" } ) @@ -400,88 +400,92 @@ const we = (e) => new Intl.NumberFormat("fa-IR").format(Number(e)), f = (e) => S } ); }; -let a = null, _ = null, R = !1; -const ee = U(null), te = ({ url: e, realm: t, clientId: o }) => (a || (a = new X({ +let j = null, d = null, F = null, L = !1; +const ne = G(null), re = ({ url: e, realm: t, clientId: r }) => (d || (d = new P({ url: e, realm: t, - clientId: o -})), a), G = ({ config: e, initOptions: t = {} }) => { - const o = te(e); - return _ || (_ = o.init({ + clientId: r +})), d), ie = (e) => (j = e, j), oe = () => L, $ = () => !!(d != null && d.authenticated), N = () => (d == null ? void 0 : d.token) ?? null, U = async (e = 30) => d ? d.updateToken(e) : !1, J = (e) => d == null ? void 0 : d.logout(e), Ie = (e) => d == null ? void 0 : d.login(e), Q = ({ config: e, initOptions: t = {} } = {}) => { + const r = e ?? j; + if (!(r != null && r.url) || !(r != null && r.realm) || !(r != null && r.clientId)) + throw new Error("Keycloak config is required."); + ie(r); + const l = re(r); + return F || (F = l.init({ onLoad: "login-required", checkLoginIframe: !1, flow: "implicit", ...t - }).then((l) => (R = !0, l)).catch((l) => { - throw R = !0, l; - })), _; -}, ne = () => R, $ = () => !!(a != null && a.authenticated), N = () => (a == null ? void 0 : a.token) ?? null, q = async (e = 30) => a ? a.updateToken(e) : !1, J = (e) => a == null ? void 0 : a.logout(e), Ce = (e) => a == null ? void 0 : a.login(e), Be = ({ + }).then((c) => (L = !0, c)).catch((c) => { + throw L = !0, c; + })), F; +}, Ee = ({ children: e, config: t, - initOptions: o, + initOptions: r, loading: l = null }) => { - const [d, i] = B(!1), [w, r] = B(!1), [s, c] = B(null), m = T(!1), y = D(() => { - a && (r(!!a.authenticated), c(a.token ?? null)); + const [c, i] = B(!1), [u, o] = B(!1), [f, s] = B(null), w = z(!1), y = E(() => { + d && (o(!!d.authenticated), s(d.token ?? null)); }, []); - A(() => (m.current = !0, G({ config: t, initOptions: o }).then((b) => { - m.current && (r(!!b), c((a == null ? void 0 : a.token) ?? null), i(!0)); + C(() => (w.current = !0, Q({ config: t, initOptions: r }).then((b) => { + w.current && (o(!!b), s((d == null ? void 0 : d.token) ?? null), i(!0)); }).catch(() => { - m.current && (r(!1), c(null), i(!0)); + w.current && (o(!1), s(null), i(!0)); }), () => { - m.current = !1; - }), [t, o]); - const v = D(() => a == null ? void 0 : a.login(), []), n = D((b) => a == null ? void 0 : a.logout(b), []), p = D( + w.current = !1; + }), [t, r]); + const v = E(() => d == null ? void 0 : d.login(), []), n = E((b) => d == null ? void 0 : d.logout(b), []), h = E( async (b = 30) => { - if (!a) return !1; - const M = await a.updateToken(b); - return y(), M; + if (!d) return !1; + const _ = await d.updateToken(b); + return y(), _; }, [y] - ), h = F( + ), m = R( () => ({ - initialized: d, - authenticated: w, - token: s, + initialized: c, + authenticated: u, + token: f, login: v, logout: n, - updateToken: p + updateToken: h }), - [d, w, s, v, n, p] + [c, u, f, v, n, h] ); - return d ? /* @__PURE__ */ u(ee.Provider, { value: h, children: e }) : l; -}, Q = U(null), z = "permissions", ie = (e) => (e == null ? void 0 : e.storageKey) || z, Ae = ({ + return c ? /* @__PURE__ */ a(ne.Provider, { value: m, children: e }) : l; +}, Y = G(null), M = "permissions", se = (e) => (e == null ? void 0 : e.storageKey) || M, Ke = ({ user: e = null, children: t, - config: o, - loading: l = /* @__PURE__ */ u("div", { children: "Loading permissions..." }), - errorFallback: d = /* @__PURE__ */ u("div", { children: "Error loading permissions" }) + config: r, + loading: l = /* @__PURE__ */ a("div", { children: "Loading permissions..." }), + errorFallback: c = /* @__PURE__ */ a("div", { children: "Error loading permissions" }) }) => { - const i = ie(o), [w, r] = B( - () => re(i) - ), { data: s, isLoading: c, error: m } = ue(o), y = s ?? w; - A(() => { - s && (oe(i, s), r(s)); - }, [s, i]); - const v = F( - () => se(y), + const i = se(r), [u, o] = B( + () => le(i) + ), { data: f, isLoading: s, error: w } = fe(r), y = f ?? u; + C(() => { + f && (ce(i, f), o(f)); + }, [f, i]); + const v = R( + () => ue(y), [y] - ), n = D( - (b = "") => le(v, b), + ), n = E( + (b = "") => ae(v, b), [v] - ), p = D((b = "") => !n(b), [n]), h = F( + ), h = E((b = "") => !n(b), [n]), m = R( () => ({ user: e, can: n, - cannot: p, + cannot: h, permissions: y, - isLoading: c, - error: m + isLoading: s, + error: w }), - [e, n, p, y, c, m] + [e, n, h, y, s, w] ); - return m && !y ? d : c && !y ? l : /* @__PURE__ */ u(Q.Provider, { value: h, children: t }); -}, re = (e = z) => { + return w && !y ? c : s && !y ? l : /* @__PURE__ */ a(Y.Provider, { value: m, children: t }); +}, le = (e = M) => { if (!(typeof window > "u")) try { const t = localStorage.getItem(e); @@ -489,34 +493,34 @@ const ee = U(null), te = ({ url: e, realm: t, clientId: o }) => (a || (a = new X } catch { return; } -}, oe = (e = z, t) => { +}, ce = (e = M, t) => { if (!(typeof window > "u")) try { localStorage.setItem(e, JSON.stringify(t)); } catch { } -}, Se = (e = z) => { +}, De = (e = M) => { if (!(typeof window > "u")) try { localStorage.removeItem(e); } catch { } -}, se = (e) => e ? new Set(e.map((t) => t.name)) : /* @__PURE__ */ new Set(), le = (e, t = "") => { +}, ue = (e) => e ? new Set(e.map((t) => t.name)) : /* @__PURE__ */ new Set(), ae = (e, t = "") => { if (!t) return !1; if (e.has(t) || [...e].some((l) => l.startsWith(t))) return !0; - let o = t; - for (; o.includes(":"); ) - if (o = o.slice(0, o.lastIndexOf(":")), e.has(`${o}:*`)) return !0; + let r = t; + for (; r.includes(":"); ) + if (r = r.slice(0, r.lastIndexOf(":")), e.has(`${r}:*`)) return !0; return !1; -}, Y = { +}, H = { all: ["permissions"], - list: (e) => [...Y.all, e] -}, ce = async (e) => { + list: (e) => [...H.all, e] +}, de = async (e) => { if (!(e != null && e.url) || !(e != null && e.clientId)) throw new Error("Permission config requires url and clientId."); - const t = N(), o = new URL(e.url); - o.searchParams.set("client_id", e.clientId); - const l = await fetch(o.toString(), { + const t = N(), r = new URL(e.url); + r.searchParams.set("client_id", e.clientId); + const l = await fetch(r.toString(), { method: "GET", headers: { ...t ? { Authorization: `Bearer ${t}` } : {} @@ -525,101 +529,120 @@ const ee = U(null), te = ({ url: e, realm: t, clientId: o }) => (a || (a = new X if (!l.ok) throw new Error("Failed to load permissions"); return l.json(); -}, O = () => { - const e = H(Q); +}, g = () => { + const e = Z(Y); if (!e) throw new Error("usePermission must be used within PermissionProvider"); return e; -}, ue = (e) => Z({ - queryKey: Y.list(e == null ? void 0 : e.clientId), - queryFn: () => ce(e), +}, fe = (e) => ee({ + queryKey: H.list(e == null ? void 0 : e.clientId), + queryFn: () => de(e), enabled: !!(e != null && e.url) && !!(e != null && e.clientId) && $(), staleTime: 1 / 0, refetchOnWindowFocus: !1, refetchOnReconnect: !1 -}), ke = ({ +}), Ne = ({ perm: e, children: t, - fallback: o = /* @__PURE__ */ u("div", { children: "You are not allowed to do this" }) + fallback: r = /* @__PURE__ */ a("div", { children: "You are not allowed to do this" }) }) => { - const { can: l } = O(); - return l(e) ? t : o; -}, Ie = ({ children: e }) => { - const { can: t, permissions: o } = O(); - return o && t("admin") ? e : null; -}, De = ({ children: e }) => { - const { can: t, isLoading: o } = O(); - return A(() => { - o || t("panel_access") || J(); - }, [o, t]), e; -}, Ee = (e) => { - const { api: t, keycloak: o } = e, l = P.create({ + const { can: l } = g(); + return l(e) ? t : r; +}, Te = ({ children: e }) => { + const { can: t, permissions: r } = g(); + return r && t("admin") ? e : null; +}, ze = ({ children: e }) => { + const { can: t, isLoading: r } = g(); + return C(() => { + r || t("panel_access") || J(); + }, [r, t]), e; +}; +let T = null; +const pe = (e) => { + const { api: t } = e, r = te.create({ baseURL: t.baseUrl - }), d = async () => { - (!ne() || !$()) && await G({ config: o }); - }, i = async (r) => { - await d(); - let s = N(); - if (s) { + }), l = async () => { + (!oe() || !$()) && await Q(); + }, c = async (u) => { + await l(); + let o = N(); + if (o) { try { - await q(5), s = N(); + await U(5), o = N(); } catch { } - r.headers = { - ...r.headers, - Authorization: `Bearer ${s}` + u.headers = { + ...u.headers, + Authorization: `Bearer ${o}` }; } - return r; - }, w = async (r) => { - var c; - const s = r.config; - if (((c = r == null ? void 0 : r.response) == null ? void 0 : c.status) === 401 && !(s != null && s._retry)) { - s._retry = !0; + return u; + }, i = async (u) => { + var f; + const o = u.config; + if (((f = u == null ? void 0 : u.response) == null ? void 0 : f.status) === 401 && !(o != null && o._retry)) { + o._retry = !0; try { - await q(30); - const m = N(); - return s.headers = { - ...s.headers, - Authorization: `Bearer ${m}` - }, l(s); + await U(30); + const s = N(); + return o.headers = { + ...o.headers, + Authorization: `Bearer ${s}` + }, r(o); } catch { J({ redirectUri: window.location.origin }); } } - return Promise.reject(r); + return Promise.reject(u); }; - return t.interceptors.request.use(i), t.interceptors.response.use((r) => r, w), { - api: l + return r.interceptors.request.use(c), r.interceptors.response.use( + (u) => u, + i + ), { + api: r }; -}; +}, Me = (e) => (T = pe(e), T), he = () => { + if (!T) + throw new Error("api is not configured. Call configureApi(config) first."); + return T.api; +}, _e = new Proxy( + {}, + { + get(e, t) { + return he()[t]; + } + } +); export { - Ie as AdminGuard, - ke as Can, - Be as KeycloakProvider, - ye as LightPagination, - xe as Pagination, - De as PanelAccessGuard, - Ae as PermissionProvider, - ve as SimplePagination, - le as checkPermission, - Se as clearCachedPermissions, - Ee as createApi, - se as createPermissionSet, - re as getCachedPermissions, + Te as AdminGuard, + Ne as Can, + Ee as KeycloakProvider, + Ce as LightPagination, + ke as Pagination, + ze as PanelAccessGuard, + Ke as PermissionProvider, + Se as SimplePagination, + _e as api, + ae as checkPermission, + De as clearCachedPermissions, + Me as configureApi, + pe as createApi, + ue as createPermissionSet, + he as getApi, + le as getCachedPermissions, N as getKeycloakToken, - ce as getPermissions, - G as initKeycloak, + de as getPermissions, + Q as initKeycloak, $ as isKeycloakAuthenticated, - ne as isKeycloakInitialized, - Ce as loginKeycloak, + oe as isKeycloakInitialized, + Ie as loginKeycloak, J as logoutKeycloak, - Y as permissionKeys, - oe as setCachedPermissions, - E as toEnDigits, - f as toFaDigits, - we as toFaNumber, - q as updateKeycloakToken, - O as usePermission, - ue as usePermissionsQuery + H as permissionKeys, + ce as setCachedPermissions, + K as toEnDigits, + p as toFaDigits, + Be as toFaNumber, + U as updateKeycloakToken, + g as usePermission, + fe as usePermissionsQuery }; diff --git a/src/core/api.js b/src/core/api.js index d27877e..cf34ada 100644 --- a/src/core/api.js +++ b/src/core/api.js @@ -8,8 +8,10 @@ import { updateKeycloakToken, } from "./keycloak.jsx"; +let configuredApi = null; + export const createApi = (config) => { - const { api, keycloak } = config; + const { api } = config; // instances @@ -21,7 +23,7 @@ export const createApi = (config) => { const waitForKeycloak = async () => { if (!isKeycloakInitialized() || !isKeycloakAuthenticated()) { - await initKeycloak({ config: keycloak }); + await initKeycloak(); } }; @@ -29,17 +31,21 @@ export const createApi = (config) => { const handleAuthRequestInterceptor = async (config) => { await waitForKeycloak(); + let token = getKeycloakToken(); + if (token) { try { await updateKeycloakToken(5); token = getKeycloakToken(); } catch {} + config.headers = { ...config.headers, Authorization: `Bearer ${token}`, }; } + return config; }; @@ -47,29 +53,60 @@ export const createApi = (config) => { const handleAuthResponseInterceptor = async (error) => { const originalRequest = error.config; + if (error?.response?.status === 401 && !originalRequest?._retry) { originalRequest._retry = true; + try { await updateKeycloakToken(30); + const token = getKeycloakToken(); + originalRequest.headers = { ...originalRequest.headers, Authorization: `Bearer ${token}`, }; + return axiosInstance(originalRequest); } catch (err) { logoutKeycloak({ redirectUri: window.location.origin }); } } + return Promise.reject(error); }; // add interceptors - api.interceptors.request.use(handleAuthRequestInterceptor); - api.interceptors.response.use((res) => res, handleAuthResponseInterceptor); + axiosInstance.interceptors.request.use(handleAuthRequestInterceptor); + axiosInstance.interceptors.response.use( + (res) => res, + handleAuthResponseInterceptor, + ); return { api: axiosInstance, }; }; + +export const configureApi = (config) => { + configuredApi = createApi(config); + return configuredApi; +}; + +export const getApi = () => { + if (!configuredApi) { + throw new Error("api is not configured. Call configureApi(config) first."); + } + + return configuredApi.api; +}; + +export const api = new Proxy( + {}, + { + get(_, prop) { + return getApi()[prop]; + }, + }, +); diff --git a/src/core/keycloak.jsx b/src/core/keycloak.jsx index 3ce5de5..a2ec9e2 100644 --- a/src/core/keycloak.jsx +++ b/src/core/keycloak.jsx @@ -10,6 +10,7 @@ import { // variables +let keycloakConfig = null; let keycloakInstance = null; let initPromise = null; let initializedValue = false; @@ -29,31 +30,16 @@ const createKeycloak = ({ url, realm, clientId }) => { return keycloakInstance; }; -// initializations +// exports -export const initKeycloak = ({ config, initOptions = {} }) => { - const keycloak = createKeycloak(config); - if (!initPromise) { - initPromise = keycloak - .init({ - onLoad: "login-required", - checkLoginIframe: false, - flow: "implicit", - ...initOptions, - }) - .then((auth) => { - initializedValue = true; - return auth; - }) - .catch((error) => { - initializedValue = true; - throw error; - }); - } - return initPromise; +export const setKeycloakConfig = (config) => { + keycloakConfig = config; + return keycloakConfig; }; -// exports +export const getKeycloakConfig = () => { + return keycloakConfig; +}; export const isKeycloakInitialized = () => { return initializedValue; @@ -81,6 +67,35 @@ export const loginKeycloak = (options) => { return keycloakInstance?.login(options); }; +// initializations + +export const initKeycloak = ({ config, initOptions = {} } = {}) => { + const finalConfig = config ?? keycloakConfig; + if (!finalConfig?.url || !finalConfig?.realm || !finalConfig?.clientId) { + throw new Error("Keycloak config is required."); + } + setKeycloakConfig(finalConfig); + const keycloak = createKeycloak(finalConfig); + if (!initPromise) { + initPromise = keycloak + .init({ + onLoad: "login-required", + checkLoginIframe: false, + flow: "implicit", + ...initOptions, + }) + .then((auth) => { + initializedValue = true; + return auth; + }) + .catch((error) => { + initializedValue = true; + throw error; + }); + } + return initPromise; +}; + // providers export const KeycloakProvider = ({ diff --git a/src/index.js b/src/index.js index 3f4ae56..2e6db63 100644 --- a/src/index.js +++ b/src/index.js @@ -31,4 +31,4 @@ export { getPermissions, } from "./core/permission.jsx"; -export { createApi } from "./core/api.js"; +export { createApi, configureApi, getApi, api } from "./core/api.js";