@plumile/backoffice-react 0.2.7 → 0.2.9

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.
Files changed (30) hide show
  1. package/README.md +23 -0
  2. package/lib/esm/auth/backofficeAuthHeaders.js +2 -9
  3. package/lib/esm/auth/backofficeAuthHeaders.js.map +1 -1
  4. package/lib/esm/hooks/useAuthenticatedRouter.js +79 -0
  5. package/lib/esm/hooks/useAuthenticatedRouter.js.map +1 -0
  6. package/lib/esm/index.js +26 -24
  7. package/lib/esm/provider/BackofficeProvider.js +141 -140
  8. package/lib/esm/provider/BackofficeProvider.js.map +1 -1
  9. package/lib/esm/provider/BackofficeRouterBoundary.js +22 -0
  10. package/lib/esm/provider/BackofficeRouterBoundary.js.map +1 -0
  11. package/lib/esm/router/createBackofficeRoutes.js +188 -184
  12. package/lib/esm/router/createBackofficeRoutes.js.map +1 -1
  13. package/lib/types/auth/backofficeAuthHeaders.d.ts +1 -1
  14. package/lib/types/auth/backofficeAuthHeaders.d.ts.map +1 -1
  15. package/lib/types/hooks/useAuthenticatedRouter.d.ts +18 -0
  16. package/lib/types/hooks/useAuthenticatedRouter.d.ts.map +1 -0
  17. package/lib/types/index.d.ts +2 -0
  18. package/lib/types/index.d.ts.map +1 -1
  19. package/lib/types/provider/BackofficeProvider.d.ts.map +1 -1
  20. package/lib/types/provider/BackofficeRouterBoundary.d.ts +9 -0
  21. package/lib/types/provider/BackofficeRouterBoundary.d.ts.map +1 -0
  22. package/lib/types/provider/types.d.ts +2 -1
  23. package/lib/types/provider/types.d.ts.map +1 -1
  24. package/lib/types/router/createBackofficeRoutes.d.ts +3 -2
  25. package/lib/types/router/createBackofficeRoutes.d.ts.map +1 -1
  26. package/package.json +11 -11
  27. package/lib/esm/provider/useBackofficeAuthRouteGate.js +0 -39
  28. package/lib/esm/provider/useBackofficeAuthRouteGate.js.map +0 -1
  29. package/lib/types/provider/useBackofficeAuthRouteGate.d.ts +0 -2
  30. package/lib/types/provider/useBackofficeAuthRouteGate.d.ts.map +0 -1
package/README.md CHANGED
@@ -77,6 +77,21 @@ packages.
77
77
 
78
78
  ### Hooks and backoffice helpers
79
79
 
80
+ - `BackofficeRouterBoundary` composes the existing error boundary and error
81
+ surface. It resets on location changes, accepts an optional `onError`
82
+ callback, and invokes `onRetry` so the caller can replace rejected prepared
83
+ resources with `useAuthenticatedRouter().retry`.
84
+ - `useAuthenticatedRouter({ routes, createOptions, access })` owns a browser
85
+ router and returns `{ router, retry, error }`. `createOptions` is a stable
86
+ callback creating fresh router options and disposable instrumentations for
87
+ each effect setup; `access` supplies `loginPath` and `isPublicPath(pathname)`.
88
+ It waits for initial short-token authentication before protected route
89
+ preparation, preserves an established session during a temporary refresh
90
+ failure, follows browser and router navigation, and replaces an expired
91
+ protected URL with the configured login path. `router` is null while blocked
92
+ or changing ownership. `error` reports construction failures; `retry`
93
+ recreates the router at the current URL. Consumers supply their own pending
94
+ and error UI and retain ownership of Relay session/store rotation.
80
95
  - `useBackofficeListUrlState`
81
96
  - `useConditionalSubscription`
82
97
  - `useCopyToClipboard`
@@ -220,6 +235,14 @@ const instrumentations = [
220
235
 
221
236
  If `instrumentations` is omitted, routing still works normally.
222
237
 
238
+ The provider uses the same authenticated-router lifecycle as public application
239
+ consumers. Its route error surface retries by recreating the current router;
240
+ it also preserves the optional `auth.session.authStatusQuery` mode. The
241
+ GraphQL configuration forwards `fetchImpl` explicitly for auth-aware transport,
242
+ and `getAuthHeaders` may accept an operation `AbortSignal`. The backoffice
243
+ header adapter delegates token/cancellation behavior to `@plumile/auth` and
244
+ only owns the base-path-aware classification of authentication URLs.
245
+
223
246
  ## Validation Notes
224
247
 
225
248
  - public helpers that are pure or mostly pure should have focused unit tests
@@ -1,16 +1,9 @@
1
1
  import { isBackofficeAuthPath as e } from "../router/backofficeAuthPaths.js";
2
- import { getShortAccessToken as t } from "@plumile/auth/shortAccessToken.js";
2
+ import { createShortAccessTokenAuthHeaders as t } from "@plumile/auth/authHeaders.js";
3
3
  //#region src/auth/backofficeAuthHeaders.ts
4
4
  var n = (n = {}) => {
5
5
  let r = n.basePath ?? "/";
6
- return async () => {
7
- try {
8
- return { Authorization: `Bearer ${await t()}` };
9
- } catch (t) {
10
- if (typeof window < "u" && e(r, window.location.pathname)) return {};
11
- throw t;
12
- }
13
- };
6
+ return t({ allowAnonymous: () => typeof window < "u" && e(r, window.location.pathname) });
14
7
  };
15
8
  //#endregion
16
9
  export { n as createBackofficeAuthHeaders };
@@ -1 +1 @@
1
- {"version":3,"file":"backofficeAuthHeaders.js","names":[],"sources":["../../../src/auth/backofficeAuthHeaders.ts"],"sourcesContent":["import { getShortAccessToken } from '@plumile/auth/shortAccessToken.js';\n\nimport { isBackofficeAuthPath } from '../router/backofficeAuthPaths.js';\n\nexport type BackofficeAuthHeadersOptions = {\n basePath?: string;\n};\n\n/**\n * Builds the auth-header provider used by a backoffice Relay environment.\n *\n * Authentication failures are allowed to become anonymous requests only on\n * the explicit authentication routes. Protected operations reject before the\n * network request is sent, so an expired session cannot reach a private\n * GraphQL subgraph as an anonymous request.\n */\nexport const createBackofficeAuthHeaders = (\n options: BackofficeAuthHeadersOptions = {},\n): (() => Promise<Record<string, string>>) => {\n const basePath = options.basePath ?? '/';\n return async () => {\n try {\n const token = await getShortAccessToken();\n return { Authorization: `Bearer ${token}` };\n } catch (error: unknown) {\n if (\n typeof window !== 'undefined' &&\n isBackofficeAuthPath(basePath, window.location.pathname)\n ) {\n const anonymousHeaders: Record<string, string> = {};\n return anonymousHeaders;\n }\n throw error;\n }\n };\n};\n"],"mappings":";;;AAgBA,IAAa,KACX,IAAwC,CAAC,MACG;CAC5C,IAAM,IAAW,EAAQ,YAAY;CACrC,OAAO,YAAY;EACjB,IAAI;GAEF,OAAO,EAAE,eAAe,UAAU,MADd,EAAoB,IACE;EAC5C,SAAS,GAAgB;GACvB,IACE,OAAO,SAAW,OAClB,EAAqB,GAAU,OAAO,SAAS,QAAQ,GAGvD,OAAO,CAAA;GAET,MAAM;EACR;CACF;AACF"}
1
+ {"version":3,"file":"backofficeAuthHeaders.js","names":[],"sources":["../../../src/auth/backofficeAuthHeaders.ts"],"sourcesContent":["import { createShortAccessTokenAuthHeaders } from '@plumile/auth/authHeaders.js';\nimport { isBackofficeAuthPath } from '../router/backofficeAuthPaths.js';\n\nexport type BackofficeAuthHeadersOptions = {\n basePath?: string;\n};\n\n/** Restricts anonymous Relay operations to the configured backoffice auth routes. */\nexport const createBackofficeAuthHeaders = (\n options: BackofficeAuthHeadersOptions = {},\n): ((signal?: AbortSignal) => Promise<Record<string, string>>) => {\n const basePath = options.basePath ?? '/';\n return createShortAccessTokenAuthHeaders({\n allowAnonymous: () => {\n return (\n typeof window !== 'undefined' &&\n isBackofficeAuthPath(basePath, window.location.pathname)\n );\n },\n });\n};\n"],"mappings":";;;AAQA,IAAa,KACX,IAAwC,CAAC,MACuB;CAChE,IAAM,IAAW,EAAQ,YAAY;CACrC,OAAO,EAAkC,EACvC,sBAEI,OAAO,SAAW,OAClB,EAAqB,GAAU,OAAO,SAAS,QAAQ,EAG7D,CAAC;AACH"}
@@ -0,0 +1,79 @@
1
+ import { useCallback as e, useEffect as t, useReducer as n, useState as r, useSyncExternalStore as i } from "react";
2
+ import { addAuthRefreshStateListener as a, getAuthRefreshState as o, getShortAccessToken as s } from "@plumile/auth/shortAccessToken.js";
3
+ import c from "@plumile/router/routing/createRouter.js";
4
+ //#region src/hooks/useAuthenticatedRouter.ts
5
+ var l = (e) => a(e), u = () => typeof window > "u" ? "/" : window.location.pathname, d = (e) => e.status === "authenticated" || (e.status === "refreshing" || e.status === "temporarily_unavailable") && e.previousExpiresAtMs != null, f = ({ routes: a, createOptions: f, access: p }) => {
6
+ let m = i(l, o, o), [, h] = n((e) => e + 1, 0), [g, _] = r(0), [v, y] = r(null), b = p.isPublicPath(u()), x = b || d(m);
7
+ t(() => {
8
+ let e = () => {
9
+ h();
10
+ };
11
+ return window.addEventListener("popstate", e), e(), () => {
12
+ window.removeEventListener("popstate", e);
13
+ };
14
+ }, []), t(() => {
15
+ if (b || m.status === "authenticated") return;
16
+ if (m.status === "session_expired") {
17
+ window.history.replaceState(window.history.state, "", p.loginPath), h();
18
+ return;
19
+ }
20
+ if (m.status === "refreshing") return;
21
+ let e = () => {
22
+ s().catch(() => {});
23
+ };
24
+ if (m.status === "temporarily_unavailable") {
25
+ if (m.retryAtMs == null) return;
26
+ let t = setTimeout(e, Math.max(0, m.retryAtMs - Date.now()));
27
+ return () => {
28
+ clearTimeout(t);
29
+ };
30
+ }
31
+ e();
32
+ }, [
33
+ p.loginPath,
34
+ m,
35
+ b
36
+ ]), t(() => {
37
+ if (!x) return;
38
+ let e = null, t = null;
39
+ try {
40
+ e = c(a, f());
41
+ } catch (e) {
42
+ t = Error("Router creation failed", { cause: e }), e instanceof Error && (t = e);
43
+ }
44
+ let n = {
45
+ router: e,
46
+ error: t,
47
+ routes: a,
48
+ createOptions: f,
49
+ revision: g,
50
+ disposed: !1
51
+ }, r = e?.context.history.subscribe(() => {
52
+ h();
53
+ });
54
+ return y(n), h(), () => {
55
+ n.disposed = !0, r?.(), e?.cleanup();
56
+ };
57
+ }, [
58
+ x,
59
+ f,
60
+ g,
61
+ a
62
+ ]);
63
+ let S = e(() => {
64
+ _((e) => e + 1);
65
+ }, []);
66
+ return x && v != null && !v.disposed && v.routes === a && v.createOptions === f && v.revision === g ? {
67
+ router: v.router,
68
+ error: v.error,
69
+ retry: S
70
+ } : {
71
+ router: null,
72
+ error: null,
73
+ retry: S
74
+ };
75
+ };
76
+ //#endregion
77
+ export { f as useAuthenticatedRouter };
78
+
79
+ //# sourceMappingURL=useAuthenticatedRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuthenticatedRouter.js","names":[],"sources":["../../../src/hooks/useAuthenticatedRouter.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useReducer,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport {\n addAuthRefreshStateListener,\n getAuthRefreshState,\n getShortAccessToken,\n} from '@plumile/auth/shortAccessToken.js';\nimport type { AuthRefreshState } from '@plumile/auth/authRefreshState.js';\nimport createRouter, {\n type CreateRouterOptions,\n type CreateRouterReturn,\n} from '@plumile/router/routing/createRouter.js';\nimport type { RouteNode } from '@plumile/router/types.js';\n\nexport type AuthenticatedRouterAccess = {\n loginPath: string;\n isPublicPath: (pathname: string) => boolean;\n};\n\nexport type AuthenticatedRouterOptions<TContext, R extends RouteNode[]> = {\n routes: R;\n createOptions: () => CreateRouterOptions<TContext>;\n access: AuthenticatedRouterAccess;\n};\n\nexport type AuthenticatedRouterResult<TContext, R extends RouteNode[]> = {\n router: CreateRouterReturn<TContext, R> | null;\n retry: () => void;\n error: Error | null;\n};\n\nconst subscribe = (onStoreChange: () => void): (() => void) => {\n return addAuthRefreshStateListener(onStoreChange);\n};\n\nconst currentPathname = (): string => {\n if (typeof window === 'undefined') {\n return '/';\n }\n return window.location.pathname;\n};\n\nconst hasEstablishedSession = (state: AuthRefreshState): boolean => {\n return (\n state.status === 'authenticated' ||\n ((state.status === 'refreshing' ||\n state.status === 'temporarily_unavailable') &&\n state.previousExpiresAtMs != null)\n );\n};\n\n/** Owns a fresh browser router per effect lifetime and gates protected routes on auth. */\nexport const useAuthenticatedRouter = <TContext, R extends RouteNode[]>({\n routes,\n createOptions,\n access,\n}: AuthenticatedRouterOptions<TContext, R>): AuthenticatedRouterResult<\n TContext,\n R\n> => {\n const authState = useSyncExternalStore(\n subscribe,\n getAuthRefreshState,\n getAuthRefreshState,\n );\n const [, refreshLocation] = useReducer((value: number) => {\n return value + 1;\n }, 0);\n const [revision, setRevision] = useState(0);\n const [owned, setOwned] = useState<{\n router: CreateRouterReturn<TContext, R> | null;\n error: Error | null;\n routes: R;\n createOptions: AuthenticatedRouterOptions<TContext, R>['createOptions'];\n revision: number;\n disposed: boolean;\n } | null>(null);\n // History notifications are asynchronous; auth may change before they arrive.\n const isPublicPath = access.isPublicPath(currentPathname());\n const canMount = isPublicPath || hasEstablishedSession(authState);\n\n useEffect(() => {\n const onLocation = (): void => {\n refreshLocation();\n };\n window.addEventListener('popstate', onLocation);\n onLocation();\n return () => {\n window.removeEventListener('popstate', onLocation);\n };\n }, []);\n\n useEffect(() => {\n if (isPublicPath || authState.status === 'authenticated') return undefined;\n if (authState.status === 'session_expired') {\n window.history.replaceState(window.history.state, '', access.loginPath);\n refreshLocation();\n return undefined;\n }\n if (authState.status === 'refreshing') return undefined;\n const authenticate = (): void => {\n getShortAccessToken().catch(() => {\n // The auth store owns the typed failure and retry policy.\n });\n };\n if (authState.status === 'temporarily_unavailable') {\n if (authState.retryAtMs == null) return undefined;\n const timer = setTimeout(\n authenticate,\n Math.max(0, authState.retryAtMs - Date.now()),\n );\n return () => {\n clearTimeout(timer);\n };\n }\n authenticate();\n return undefined;\n }, [access.loginPath, authState, isPublicPath]);\n\n useEffect(() => {\n if (!canMount) return undefined;\n let nextRouter: CreateRouterReturn<TContext, R> | null = null;\n let error: Error | null = null;\n try {\n nextRouter = createRouter<TContext, R>(routes, createOptions());\n } catch (cause: unknown) {\n error = new Error('Router creation failed', { cause });\n if (cause instanceof Error) {\n error = cause;\n }\n }\n const next = {\n router: nextRouter,\n error,\n routes,\n createOptions,\n revision,\n disposed: false,\n };\n const unsubscribe = nextRouter?.context.history.subscribe(() => {\n refreshLocation();\n });\n setOwned(next);\n refreshLocation();\n return () => {\n next.disposed = true;\n unsubscribe?.();\n nextRouter?.cleanup();\n };\n }, [canMount, createOptions, revision, routes]);\n\n const retry = useCallback(() => {\n setRevision((previous) => {\n return previous + 1;\n });\n }, []);\n\n const isCurrent =\n canMount &&\n owned != null &&\n !owned.disposed &&\n owned.routes === routes &&\n owned.createOptions === createOptions &&\n owned.revision === revision;\n if (isCurrent) {\n return { router: owned.router, error: owned.error, retry };\n }\n return { router: null, error: null, retry };\n};\n"],"mappings":";;;;AAoCA,IAAM,KAAa,MACV,EAA4B,CAAa,GAG5C,UACA,OAAO,SAAW,MACb,MAEF,OAAO,SAAS,UAGnB,KAAyB,MAE3B,EAAM,WAAW,oBACf,EAAM,WAAW,gBACjB,EAAM,WAAW,8BACjB,EAAM,uBAAuB,MAKtB,KAA2D,EACtE,WACA,kBACA,gBAIG;CACH,IAAM,IAAY,EAChB,GACA,GACA,CACF,GACM,GAAG,KAAmB,GAAY,MAC/B,IAAQ,GACd,CAAC,GACE,CAAC,GAAU,KAAe,EAAS,CAAC,GACpC,CAAC,GAAO,KAAY,EAOhB,IAAI,GAER,IAAe,EAAO,aAAa,EAAgB,CAAC,GACpD,IAAW,KAAgB,EAAsB,CAAS;CAwChE,AAtCA,QAAgB;EACd,IAAM,UAAyB;GAC7B,EAAgB;EAClB;EAGA,OAFA,OAAO,iBAAiB,YAAY,CAAU,GAC9C,EAAW,SACE;GACX,OAAO,oBAAoB,YAAY,CAAU;EACnD;CACF,GAAG,CAAC,CAAC,GAEL,QAAgB;EACd,IAAI,KAAgB,EAAU,WAAW,iBAAiB;EAC1D,IAAI,EAAU,WAAW,mBAAmB;GAE1C,AADA,OAAO,QAAQ,aAAa,OAAO,QAAQ,OAAO,IAAI,EAAO,SAAS,GACtE,EAAgB;GAChB;EACF;EACA,IAAI,EAAU,WAAW,cAAc;EACvC,IAAM,UAA2B;GAC/B,EAAoB,CAAC,CAAC,YAAY,CAElC,CAAC;EACH;EACA,IAAI,EAAU,WAAW,2BAA2B;GAClD,IAAI,EAAU,aAAa,MAAM;GACjC,IAAM,IAAQ,WACZ,GACA,KAAK,IAAI,GAAG,EAAU,YAAY,KAAK,IAAI,CAAC,CAC9C;GACA,aAAa;IACX,aAAa,CAAK;GACpB;EACF;EACA,EAAa;CAEf,GAAG;EAAC,EAAO;EAAW;EAAW;CAAY,CAAC,GAE9C,QAAgB;EACd,IAAI,CAAC,GAAU;EACf,IAAI,IAAqD,MACrD,IAAsB;EAC1B,IAAI;GACF,IAAa,EAA0B,GAAQ,EAAc,CAAC;EAChE,SAAS,GAAgB;GAEvB,AADA,IAAY,MAAM,0BAA0B,EAAE,SAAM,CAAC,GACjD,aAAiB,UACnB,IAAQ;EAEZ;EACA,IAAM,IAAO;GACX,QAAQ;GACR;GACA;GACA;GACA;GACA,UAAU;EACZ,GACM,IAAc,GAAY,QAAQ,QAAQ,gBAAgB;GAC9D,EAAgB;EAClB,CAAC;EAGD,OAFA,EAAS,CAAI,GACb,EAAgB,SACH;GAGX,AAFA,EAAK,WAAW,IAChB,IAAc,GACd,GAAY,QAAQ;EACtB;CACF,GAAG;EAAC;EAAU;EAAe;EAAU;CAAM,CAAC;CAE9C,IAAM,IAAQ,QAAkB;EAC9B,GAAa,MACJ,IAAW,CACnB;CACH,GAAG,CAAC,CAAC;CAYL,OATE,KACA,KAAS,QACT,CAAC,EAAM,YACP,EAAM,WAAW,KACjB,EAAM,kBAAkB,KACxB,EAAM,aAAa,IAEZ;EAAE,QAAQ,EAAM;EAAQ,OAAO,EAAM;EAAO;CAAM,IAEpD;EAAE,QAAQ;EAAM,OAAO;EAAM;CAAM;AAC5C"}
package/lib/esm/index.js CHANGED
@@ -34,11 +34,11 @@ import { BackofficeLink as R } from "./components/backoffice/links/BackofficeLin
34
34
  import { BackofficeLinkLabel as z } from "./components/backoffice/links/BackofficeLinkLabel.js";
35
35
  import { BackofficeRightPageLayout as B } from "./components/backoffice/layout/breadcrumb/BackofficeRightPageLayout.js";
36
36
  import { BackofficeOverviewLayout as V } from "./components/backoffice/overview/BackofficeOverviewLayout.js";
37
- import { BackofficeFilterableCell as ee } from "./components/backoffice/shared/BackofficeFilterableCell.js";
38
- import { BackofficeEntityLink as H } from "./components/backoffice/refs/BackofficeEntityLink.js";
39
- import { BackofficeLazyEntityCount as U } from "./components/backoffice/refs/BackofficeLazyEntityCount.js";
40
- import { BackofficeRelatedCountLink as W } from "./components/backoffice/refs/BackofficeRelatedCountLink.js";
41
- import { BackofficeTabbedDetailShell as G } from "./components/backoffice/scaffolds/BackofficeTabbedDetailShell.js";
37
+ import { BackofficeFilterableCell as H } from "./components/backoffice/shared/BackofficeFilterableCell.js";
38
+ import { BackofficeEntityLink as U } from "./components/backoffice/refs/BackofficeEntityLink.js";
39
+ import { BackofficeLazyEntityCount as W } from "./components/backoffice/refs/BackofficeLazyEntityCount.js";
40
+ import { BackofficeRelatedCountLink as G } from "./components/backoffice/refs/BackofficeRelatedCountLink.js";
41
+ import { BackofficeTabbedDetailShell as ee } from "./components/backoffice/scaffolds/BackofficeTabbedDetailShell.js";
42
42
  import { BackofficeFormattedCurrency as K } from "./components/backoffice/shared/BackofficeFormattedCurrency.js";
43
43
  import { BackofficeFormattedNumber as q } from "./components/backoffice/shared/BackofficeFormattedNumber.js";
44
44
  import { BackofficeInlineFilterRow as J } from "./components/backoffice/shared/BackofficeInlineFilterRow.js";
@@ -49,22 +49,24 @@ import { BackofficeToolsQueryBoundary as Q } from "./components/backoffice/tools
49
49
  import { parseToolJson as $ } from "./components/backoffice/tools/parseToolJson.js";
50
50
  import { base64UrlToBuffer as te, bufferToBase64Url as ne, mapWebAuthnRegistrationError as re, parseSignCount as ie } from "./modules/webauthn.js";
51
51
  import { createUseAuth as ae } from "./hooks/useAuth.js";
52
- import { useBackofficeListUrlState as oe } from "./hooks/useBackofficeListUrlState.js";
53
- import { useConditionalSubscription as se } from "./hooks/useConditionalSubscription.js";
54
- import ce from "./hooks/useCopyToClipboard.js";
55
- import { useRefetchNeededReload as le } from "./hooks/useRefetchNeededReload.js";
56
- import { createI18nInstance as ue } from "./i18n/createI18nInstance.js";
57
- import { backofficeReactI18nResources as de, withBackofficeReactI18nResources as fe } from "./i18n/resources.js";
58
- import { useReviewStatusLabel as pe } from "./i18n/useReviewStatusLabel.js";
59
- import { BackofficeProvider as me } from "./provider/BackofficeProvider.js";
60
- import { createBackofficeLazyValue as he } from "./provider/lazyValue.js";
61
- import { formatFileSize as ge } from "./modules/formatFileSize.js";
62
- import { uploadFilesSequentially as _e } from "./modules/uploads.js";
63
- import { resolveVisibleDetailPages as ve } from "./pages/detail/pageResolution.js";
64
- import { createInlineDataReader as ye } from "./relay/createInlineReader.js";
65
- import { appendNodeToConnections as be } from "./relay/connectionUtils.js";
66
- import { useMutationAction as xe } from "./relay/useMutationAction.js";
67
- import { identityView as Se } from "./relay/identityView.js";
68
- import { useCursorResumableSubscription as Ce } from "./subscriptions/useCursorResumableSubscription.js";
69
- import { decodeBase64ToUtf8 as we, encodeUtf8ToBase64 as Te } from "@plumile/backoffice-core/base64.js";
70
- export { s as AcceptInvitationScreen, e as AuthRefreshNotice, b as BackofficeBillingUsageChart, E as BackofficeDetailBadgeRow, H as BackofficeEntityLink, D as BackofficeEntitySummaryHeader, _ as BackofficeErrorBoundary, P as BackofficeFilterAction, ee as BackofficeFilterableCell, K as BackofficeFormattedCurrency, q as BackofficeFormattedNumber, L as BackofficeHubTemplate, J as BackofficeInlineFilterRow, w as BackofficeInlineLink, U as BackofficeLazyEntityCount, O as BackofficeLifecycleTimelineSection, R as BackofficeLink, z as BackofficeLinkLabel, V as BackofficeOverviewLayout, me as BackofficeProvider, W as BackofficeRelatedCountLink, k as BackofficeRelationGrid, k as BackofficeRelationsSummaryGrid, B as BackofficeRightPageLayout, G as BackofficeTabbedDetailShell, A as BackofficeTokenUsageBreakdown, Y as BackofficeToolsDocPanel, X as BackofficeToolsErrorFallback, Z as BackofficeToolsJsonForm, Q as BackofficeToolsQueryBoundary, j as BackofficeUsageCostBreakdown, F as EntityFilterValue, I as EntityFilterValueText, g as EntityIdFilterField, y as EntityIdPickerDialog, a as LoginFlow, c as PasswordResetCompleteScreen, l as PasswordResetRequestScreen, n as TotpQrCode, u as VerifyEmailScreen, be as appendNodeToConnections, de as backofficeReactI18nResources, te as base64UrlToBuffer, ne as bufferToBase64Url, T as buildDataTableColumns, r as buildTotpOtpAuthUri, i as createBackofficeAuthHeaders, M as createBackofficeEntityLinkProps, he as createBackofficeLazyValue, ue as createI18nInstance, ye as createInlineDataReader, ae as createUseAuth, we as decodeBase64ToUtf8, Te as encodeUtf8ToBase64, ge as formatFileSize, N as formatListAsMarkdown, Se as identityView, re as mapWebAuthnRegistrationError, ie as parseSignCount, $ as parseToolJson, d as requireField, f as requireLinkedRecordId, p as resolveAgentStartOutcome, S as resolveBackofficeLink, x as resolveBackofficeTargetIcon, m as resolveMutationOutcome, ve as resolveVisibleDetailPages, o as synchronizeAuthStatusQuery, _e as uploadFilesSequentially, t as useAuthRefreshStateSnapshot, h as useBackofficeConfig, C as useBackofficeLink, oe as useBackofficeListUrlState, se as useConditionalSubscription, ce as useCopyToClipboard, Ce as useCursorResumableSubscription, v as useInfiniteConnection, xe as useMutationAction, le as useRefetchNeededReload, pe as useReviewStatusLabel, fe as withBackofficeReactI18nResources };
52
+ import { useAuthenticatedRouter as oe } from "./hooks/useAuthenticatedRouter.js";
53
+ import { useBackofficeListUrlState as se } from "./hooks/useBackofficeListUrlState.js";
54
+ import { useConditionalSubscription as ce } from "./hooks/useConditionalSubscription.js";
55
+ import le from "./hooks/useCopyToClipboard.js";
56
+ import { useRefetchNeededReload as ue } from "./hooks/useRefetchNeededReload.js";
57
+ import { createI18nInstance as de } from "./i18n/createI18nInstance.js";
58
+ import { backofficeReactI18nResources as fe, withBackofficeReactI18nResources as pe } from "./i18n/resources.js";
59
+ import { useReviewStatusLabel as me } from "./i18n/useReviewStatusLabel.js";
60
+ import { BackofficeRouterBoundary as he } from "./provider/BackofficeRouterBoundary.js";
61
+ import { BackofficeProvider as ge } from "./provider/BackofficeProvider.js";
62
+ import { createBackofficeLazyValue as _e } from "./provider/lazyValue.js";
63
+ import { formatFileSize as ve } from "./modules/formatFileSize.js";
64
+ import { uploadFilesSequentially as ye } from "./modules/uploads.js";
65
+ import { resolveVisibleDetailPages as be } from "./pages/detail/pageResolution.js";
66
+ import { createInlineDataReader as xe } from "./relay/createInlineReader.js";
67
+ import { appendNodeToConnections as Se } from "./relay/connectionUtils.js";
68
+ import { useMutationAction as Ce } from "./relay/useMutationAction.js";
69
+ import { identityView as we } from "./relay/identityView.js";
70
+ import { useCursorResumableSubscription as Te } from "./subscriptions/useCursorResumableSubscription.js";
71
+ import { decodeBase64ToUtf8 as Ee, encodeUtf8ToBase64 as De } from "@plumile/backoffice-core/base64.js";
72
+ export { s as AcceptInvitationScreen, e as AuthRefreshNotice, b as BackofficeBillingUsageChart, E as BackofficeDetailBadgeRow, U as BackofficeEntityLink, D as BackofficeEntitySummaryHeader, _ as BackofficeErrorBoundary, P as BackofficeFilterAction, H as BackofficeFilterableCell, K as BackofficeFormattedCurrency, q as BackofficeFormattedNumber, L as BackofficeHubTemplate, J as BackofficeInlineFilterRow, w as BackofficeInlineLink, W as BackofficeLazyEntityCount, O as BackofficeLifecycleTimelineSection, R as BackofficeLink, z as BackofficeLinkLabel, V as BackofficeOverviewLayout, ge as BackofficeProvider, G as BackofficeRelatedCountLink, k as BackofficeRelationGrid, k as BackofficeRelationsSummaryGrid, B as BackofficeRightPageLayout, he as BackofficeRouterBoundary, ee as BackofficeTabbedDetailShell, A as BackofficeTokenUsageBreakdown, Y as BackofficeToolsDocPanel, X as BackofficeToolsErrorFallback, Z as BackofficeToolsJsonForm, Q as BackofficeToolsQueryBoundary, j as BackofficeUsageCostBreakdown, F as EntityFilterValue, I as EntityFilterValueText, g as EntityIdFilterField, y as EntityIdPickerDialog, a as LoginFlow, c as PasswordResetCompleteScreen, l as PasswordResetRequestScreen, n as TotpQrCode, u as VerifyEmailScreen, Se as appendNodeToConnections, fe as backofficeReactI18nResources, te as base64UrlToBuffer, ne as bufferToBase64Url, T as buildDataTableColumns, r as buildTotpOtpAuthUri, i as createBackofficeAuthHeaders, M as createBackofficeEntityLinkProps, _e as createBackofficeLazyValue, de as createI18nInstance, xe as createInlineDataReader, ae as createUseAuth, Ee as decodeBase64ToUtf8, De as encodeUtf8ToBase64, ve as formatFileSize, N as formatListAsMarkdown, we as identityView, re as mapWebAuthnRegistrationError, ie as parseSignCount, $ as parseToolJson, d as requireField, f as requireLinkedRecordId, p as resolveAgentStartOutcome, S as resolveBackofficeLink, x as resolveBackofficeTargetIcon, m as resolveMutationOutcome, be as resolveVisibleDetailPages, o as synchronizeAuthStatusQuery, ye as uploadFilesSequentially, t as useAuthRefreshStateSnapshot, oe as useAuthenticatedRouter, h as useBackofficeConfig, C as useBackofficeLink, se as useBackofficeListUrlState, ce as useConditionalSubscription, le as useCopyToClipboard, Te as useCursorResumableSubscription, v as useInfiniteConnection, Ce as useMutationAction, ue as useRefetchNeededReload, me as useReviewStatusLabel, pe as withBackofficeReactI18nResources };
@@ -1,182 +1,183 @@
1
- import { BackofficeConfigProvider as e } from "./BackofficeConfigContext.js";
2
- import { validateBackofficeDashboardRegistrations as t } from "./dashboardRegistrations.js";
3
- import { BackofficeRouteFallback as n, BackofficeStaticRouteFallback as r } from "../components/backoffice/routing/BackofficeRouteFallback.js";
4
- import { useRelayEnvironment as i } from "../relay/useRelayEnvironment.js";
5
- import { createI18nInstance as a } from "../i18n/createI18nInstance.js";
6
- import { withBackofficeReactI18nResources as o } from "../i18n/resources.js";
7
- import { createBackofficeRoutes as s } from "../router/createBackofficeRoutes.js";
8
- import { createBackofficeEntityRegistry as c } from "./entityRegistry.js";
9
- import { useBackofficeAuthRouteGate as l } from "./useBackofficeAuthRouteGate.js";
10
- import { StrictMode as u, useEffect as d, useMemo as f, useRef as p, useState as m } from "react";
11
- import { BackofficeThemeProvider as h, RoutePendingBar as g } from "@plumile/ui";
12
- import { jsx as _, jsxs as v } from "react/jsx-runtime";
13
- import { I18nextProvider as y } from "react-i18next";
14
- import b from "@plumile/router/routing/RoutingContext.js";
15
- import { createInstance as x } from "i18next";
16
- import S from "@plumile/router/routing/createRouter.js";
17
- import C from "@plumile/router/routing/RouterRenderer.js";
18
- import { RelayProvider as w, configureRelayEnvironment as T, useRelayOperationActivity as E } from "@plumile/relay";
1
+ import { getBackofficeLoginPath as e, isBackofficeAuthPath as t } from "../router/backofficeAuthPaths.js";
2
+ import { BackofficeConfigProvider as n } from "./BackofficeConfigContext.js";
3
+ import { validateBackofficeDashboardRegistrations as r } from "./dashboardRegistrations.js";
4
+ import { BackofficeRouteFallback as i, BackofficeStaticRouteFallback as a } from "../components/backoffice/routing/BackofficeRouteFallback.js";
5
+ import { useAuthenticatedRouter as o } from "../hooks/useAuthenticatedRouter.js";
6
+ import { useRelayEnvironment as s } from "../relay/useRelayEnvironment.js";
7
+ import { createI18nInstance as c } from "../i18n/createI18nInstance.js";
8
+ import { withBackofficeReactI18nResources as l } from "../i18n/resources.js";
9
+ import { BackofficeRouterBoundary as u } from "./BackofficeRouterBoundary.js";
10
+ import { createBackofficeRoutes as d } from "../router/createBackofficeRoutes.js";
11
+ import { createBackofficeEntityRegistry as f } from "./entityRegistry.js";
12
+ import { StrictMode as p, useCallback as m, useEffect as h, useMemo as g, useState as _ } from "react";
13
+ import { BackofficeThemeProvider as v, ErrorState as y, RoutePendingBar as b } from "@plumile/ui";
14
+ import { jsx as x, jsxs as S } from "react/jsx-runtime";
15
+ import { I18nextProvider as C } from "react-i18next";
16
+ import w from "@plumile/router/routing/RoutingContext.js";
17
+ import { createInstance as T } from "i18next";
18
+ import E from "@plumile/router/routing/RouterRenderer.js";
19
+ import { RelayProvider as D, configureRelayEnvironment as O, useRelayOperationActivity as k } from "@plumile/relay";
19
20
  //#region src/provider/BackofficeProvider.tsx
20
- var D = (e) => e.trim() === "" || e === "/" ? "/" : e.startsWith("/") ? e.endsWith("/") ? e.slice(0, -1) : e : `/${e}`, O = (e, t) => {
21
- let n = D(t), r = D(e);
21
+ var A = (e) => e.trim() === "" || e === "/" ? "/" : e.startsWith("/") ? e.endsWith("/") ? e.slice(0, -1) : e : `/${e}`, j = (e, t) => {
22
+ let n = A(t), r = A(e);
22
23
  return r === "/" || n === r || n.startsWith(`${r}/`) ? n : n === "/" ? r : `${r}${n}`;
23
- }, k = (e, t) => Object.fromEntries(Object.entries(e).map(([e, n]) => [e, {
24
+ }, M = (e, t) => Object.fromEntries(Object.entries(e).map(([e, n]) => [e, {
24
25
  ...n,
25
26
  routes: {
26
- list: O(t, n.routes.list),
27
- detail: (e) => O(t, n.routes.detail(e)),
28
- detailPage: (e, r) => O(t, n.routes.detailPage(e, r))
27
+ list: j(t, n.routes.list),
28
+ detail: (e) => j(t, n.routes.detail(e)),
29
+ detailPage: (e, r) => j(t, n.routes.detailPage(e, r))
29
30
  }
30
- }])), A = ({ routes: e, context: t, instrumentations: n }) => {
31
- let [r, i] = m(null), a = p(null);
32
- return d(() => {
33
- let r = S(e, {
34
- context: t,
35
- instrumentations: n
36
- });
37
- return a.current = r, i(r), () => {
38
- a.current === r && (a.current = null), r.cleanup();
39
- };
40
- }, [
41
- t,
42
- n,
43
- e
44
- ]), r;
45
- }, j = ({ routes: e, instrumentations: t }) => {
46
- let r = i(), a = E(), o = A({
47
- routes: e,
48
- context: f(() => ({ relayEnvironment: r }), [r]),
49
- instrumentations: t
31
+ }])), N = ({ routes: n, instrumentations: r, basePath: a }) => {
32
+ let c = s(), l = k(), d = g(() => ({ relayEnvironment: c }), [c]), f = m(() => ({
33
+ context: d,
34
+ instrumentations: r
35
+ }), [r, d]), p = g(() => ({
36
+ loginPath: e(a),
37
+ isPublicPath: (e) => t(a, e)
38
+ }), [a]), { router: h, retry: _, error: v } = o({
39
+ routes: n,
40
+ createOptions: f,
41
+ access: p
50
42
  });
51
- return o == null ? /* @__PURE__ */ _(n, {}) : /* @__PURE__ */ _(b.Provider, {
52
- value: o.context,
53
- children: /* @__PURE__ */ _(C, {
54
- enableTransition: !0,
55
- externalPending: a.pendingCount > 0,
56
- fallback: /* @__PURE__ */ _(n, {}),
57
- pending: /* @__PURE__ */ _(g, {})
43
+ return v == null ? h == null ? /* @__PURE__ */ x(i, {}) : /* @__PURE__ */ x(w.Provider, {
44
+ value: h.context,
45
+ children: /* @__PURE__ */ x(u, {
46
+ onRetry: _,
47
+ children: /* @__PURE__ */ x(E, {
48
+ enableTransition: !0,
49
+ externalPending: l.pendingCount > 0,
50
+ fallback: /* @__PURE__ */ x(i, {}),
51
+ pending: /* @__PURE__ */ x(b, {})
52
+ })
58
53
  })
54
+ }) : /* @__PURE__ */ x(y, {
55
+ variant: "plain",
56
+ onRetry: _
59
57
  });
60
- }, M = (n) => {
61
- let i = D(n.basePath ?? "/"), p = l(i), g = f(() => k(n.entityManifest, i), [i, n.entityManifest]), b = f(() => c(g, { basePath: i }), [i, g]), S = n.graphql, C = f(() => t(n.dashboards), [n.dashboards]);
62
- d(() => {
63
- let e = S.httpUrl ?? S.endpoint, t = S.wsUrl ?? S.wsEndpoint;
64
- T({
58
+ }, P = (e) => {
59
+ let t = A(e.basePath ?? "/"), i = g(() => M(e.entityManifest, t), [t, e.entityManifest]), o = g(() => f(i, { basePath: t }), [t, i]), s = e.graphql, u = g(() => r(e.dashboards), [e.dashboards]);
60
+ h(() => {
61
+ let e = s.httpUrl ?? s.endpoint, t = s.wsUrl ?? s.wsEndpoint;
62
+ O({
65
63
  httpUrl: e,
66
64
  wsUrl: t,
67
- getDataId: S.getDataId,
68
- logEvents: S.logEvents,
69
- getAuthHeaders: S.getAuthHeaders
65
+ getDataId: s.getDataId,
66
+ logEvents: s.logEvents,
67
+ getAuthHeaders: s.getAuthHeaders,
68
+ fetchImpl: s.fetchImpl
70
69
  });
71
70
  }, [
72
- S.endpoint,
73
- S.getAuthHeaders,
74
- S.getDataId,
75
- S.httpUrl,
76
- S.logEvents,
77
- S.wsEndpoint,
78
- S.wsUrl
71
+ s.endpoint,
72
+ s.fetchImpl,
73
+ s.getAuthHeaders,
74
+ s.getDataId,
75
+ s.httpUrl,
76
+ s.logEvents,
77
+ s.wsEndpoint,
78
+ s.wsUrl
79
79
  ]);
80
- let E = f(() => o(n.i18n?.resources ?? {}), [n.i18n?.resources]), O = f(() => n.i18n?.instance ?? x(), [n.i18n?.instance]), [A, M] = m(O.isInitialized);
81
- d(() => {
82
- let e = !0, t = () => {
83
- e && M(!0);
80
+ let m = g(() => l(e.i18n?.resources ?? {}), [e.i18n?.resources]), y = g(() => e.i18n?.instance ?? T(), [e.i18n?.instance]), [b, w] = _(y.isInitialized);
81
+ h(() => {
82
+ let t = !0, n = () => {
83
+ t && w(!0);
84
84
  };
85
- if (O.on("initialized", t), O.isInitialized) return t(), () => {
86
- e = !1, O.off("initialized", t);
85
+ if (y.on("initialized", n), y.isInitialized) return n(), () => {
86
+ t = !1, y.off("initialized", n);
87
87
  };
88
88
  let r = globalThis.setTimeout(() => {
89
- O.isInitialized && t();
90
- }, 0), i = n.i18n?.initOptions ?? {}, o = i.defaultNS ?? "translations", s = i.ns ?? [
89
+ y.isInitialized && n();
90
+ }, 0), i = e.i18n?.initOptions ?? {}, a = i.defaultNS ?? "translations", o = i.ns ?? [
91
91
  "backofficeReact",
92
92
  "translations",
93
93
  "ui"
94
94
  ];
95
- return a({
96
- resources: E,
97
- lng: n.i18n?.lng,
98
- fallbackLng: n.i18n?.fallbackLng,
95
+ return c({
96
+ resources: m,
97
+ lng: e.i18n?.lng,
98
+ fallbackLng: e.i18n?.fallbackLng,
99
99
  initOptions: {
100
100
  ...i,
101
- defaultNS: o,
102
- ns: s,
101
+ defaultNS: a,
102
+ ns: o,
103
103
  react: {
104
104
  useSuspense: !1,
105
105
  ...i.react
106
106
  }
107
107
  },
108
- instance: O,
109
- useLanguageDetector: n.i18n?.useLanguageDetector,
110
- detection: n.i18n?.detection
111
- }).then(t).catch((e) => {
112
- t(), console.error(e);
108
+ instance: y,
109
+ useLanguageDetector: e.i18n?.useLanguageDetector,
110
+ detection: e.i18n?.detection
111
+ }).then(n).catch((e) => {
112
+ n(), console.error(e);
113
113
  }), () => {
114
- e = !1, globalThis.clearTimeout(r), O.off("initialized", t);
114
+ t = !1, globalThis.clearTimeout(r), y.off("initialized", n);
115
115
  };
116
116
  }, [
117
- O,
118
- E,
119
- n.i18n?.initOptions,
120
- n.i18n?.detection,
121
- n.i18n?.fallbackLng,
122
- n.i18n?.lng,
123
- n.i18n?.useLanguageDetector
117
+ y,
118
+ m,
119
+ e.i18n?.initOptions,
120
+ e.i18n?.detection,
121
+ e.i18n?.fallbackLng,
122
+ e.i18n?.lng,
123
+ e.i18n?.useLanguageDetector
124
124
  ]);
125
- let N = f(() => ({
126
- basePath: i,
127
- entities: g,
128
- entityManifest: g,
129
- entityRegistry: b,
130
- filterColumnAliases: n.filterColumnAliases,
131
- sidebar: n.sidebar,
132
- dashboard: n.dashboard,
133
- dashboards: C,
134
- auth: n.auth,
135
- graphql: n.graphql
125
+ let E = g(() => ({
126
+ basePath: t,
127
+ entities: i,
128
+ entityManifest: i,
129
+ entityRegistry: o,
130
+ filterColumnAliases: e.filterColumnAliases,
131
+ sidebar: e.sidebar,
132
+ dashboard: e.dashboard,
133
+ dashboards: u,
134
+ auth: e.auth,
135
+ graphql: e.graphql
136
136
  }), [
137
+ t,
138
+ e.auth,
139
+ e.dashboard,
140
+ u,
137
141
  i,
138
- n.auth,
139
- n.dashboard,
140
- C,
141
- g,
142
- b,
143
- n.filterColumnAliases,
144
- n.graphql,
145
- n.sidebar
146
- ]), P = f(() => s({
147
- basePath: i,
148
- entityManifest: g,
149
- entityRegistry: b,
150
- sidebar: n.sidebar,
151
- auth: n.auth,
152
- dashboard: n.dashboard,
153
- dashboards: C,
154
- toolsOperationPage: n.toolsOperationPage
142
+ o,
143
+ e.filterColumnAliases,
144
+ e.graphql,
145
+ e.sidebar
146
+ ]), k = g(() => d({
147
+ basePath: t,
148
+ entityManifest: i,
149
+ entityRegistry: o,
150
+ sidebar: e.sidebar,
151
+ auth: e.auth,
152
+ dashboard: e.dashboard,
153
+ dashboards: u,
154
+ toolsOperationPage: e.toolsOperationPage
155
155
  }), [
156
+ t,
156
157
  i,
157
- g,
158
- b,
159
- n.auth,
160
- n.dashboard,
161
- C,
162
- n.toolsOperationPage,
163
- n.sidebar
164
- ]), F = /* @__PURE__ */ _(r, { label: "Loading..." });
165
- return A && p && (F = /* @__PURE__ */ _(h, {
166
- ...n.theme,
167
- children: /* @__PURE__ */ _(w, { children: /* @__PURE__ */ v(e, {
168
- value: N,
169
- children: [n.overlay, /* @__PURE__ */ _(j, {
170
- routes: P,
171
- instrumentations: n.instrumentations
158
+ o,
159
+ e.auth,
160
+ e.dashboard,
161
+ u,
162
+ e.toolsOperationPage,
163
+ e.sidebar
164
+ ]), j = /* @__PURE__ */ x(a, { label: "Loading..." });
165
+ return b && (j = /* @__PURE__ */ x(v, {
166
+ ...e.theme,
167
+ children: /* @__PURE__ */ x(D, { children: /* @__PURE__ */ S(n, {
168
+ value: E,
169
+ children: [e.overlay, /* @__PURE__ */ x(N, {
170
+ routes: k,
171
+ basePath: t,
172
+ instrumentations: e.instrumentations
172
173
  })]
173
174
  }) })
174
- })), /* @__PURE__ */ _(u, { children: /* @__PURE__ */ _(y, {
175
- i18n: O,
176
- children: F
175
+ })), /* @__PURE__ */ x(p, { children: /* @__PURE__ */ x(C, {
176
+ i18n: y,
177
+ children: j
177
178
  }) });
178
179
  };
179
180
  //#endregion
180
- export { M as BackofficeProvider, M as default };
181
+ export { P as BackofficeProvider, P as default };
181
182
 
182
183
  //# sourceMappingURL=BackofficeProvider.js.map