@flytedesk/app-kit 6.0.0 → 7.1.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.
Files changed (45) hide show
  1. package/README.md +192 -41
  2. package/dist/auth/client/authSession.d.ts +168 -0
  3. package/dist/auth/client/authSession.js +581 -0
  4. package/dist/auth/client/authSession.js.map +1 -0
  5. package/dist/auth/client/browserEnvironment.d.ts +22 -0
  6. package/dist/auth/client/browserEnvironment.js +87 -0
  7. package/dist/auth/client/browserEnvironment.js.map +1 -0
  8. package/dist/auth/client/httpClient.d.ts +32 -28
  9. package/dist/auth/client/httpClient.js +91 -84
  10. package/dist/auth/client/httpClient.js.map +1 -1
  11. package/dist/auth/client/index.d.ts +15 -8
  12. package/dist/auth/client/index.js +13 -7
  13. package/dist/auth/client/index.js.map +1 -1
  14. package/dist/auth/client/testing.d.ts +6 -0
  15. package/dist/auth/client/testing.js +20 -0
  16. package/dist/auth/client/testing.js.map +1 -0
  17. package/dist/auth/client/useAuthSession.d.ts +54 -91
  18. package/dist/auth/client/useAuthSession.js +65 -252
  19. package/dist/auth/client/useAuthSession.js.map +1 -1
  20. package/dist/auth/index.d.ts +3 -4
  21. package/dist/auth/index.js +1 -2
  22. package/dist/auth/index.js.map +1 -1
  23. package/dist/auth/oidc-client.d.ts +18 -4
  24. package/dist/auth/oidc-client.js +18 -1
  25. package/dist/auth/oidc-client.js.map +1 -1
  26. package/dist/auth/plugin.js +244 -225
  27. package/dist/auth/plugin.js.map +1 -1
  28. package/dist/auth/returnTarget.d.ts +30 -0
  29. package/dist/auth/returnTarget.js +48 -0
  30. package/dist/auth/returnTarget.js.map +1 -0
  31. package/dist/auth/shared-types.d.ts +18 -41
  32. package/dist/auth/shared-types.js +18 -45
  33. package/dist/auth/shared-types.js.map +1 -1
  34. package/dist/auth/testing/fake-idp.d.ts +29 -1
  35. package/dist/auth/testing/fake-idp.js +142 -31
  36. package/dist/auth/testing/fake-idp.js.map +1 -1
  37. package/dist/auth/types.d.ts +26 -29
  38. package/dist/bigquery/index.d.ts +1 -1
  39. package/dist/bigquery/params.d.ts +6 -0
  40. package/dist/bigquery/params.js +79 -0
  41. package/dist/bigquery/params.js.map +1 -0
  42. package/dist/bigquery/query.js +3 -0
  43. package/dist/bigquery/query.js.map +1 -1
  44. package/dist/bigquery/types.d.ts +37 -4
  45. package/package.json +9 -3
@@ -0,0 +1,20 @@
1
+ /**
2
+ * `@flytedesk/app-kit/auth/client/testing` — seams for an app's OWN unit tests (AK-35),
3
+ * never for app code. The session's access token and lifecycle are private to
4
+ * `@flytedesk/app-kit/auth/client`; a test that exercises `apiRequest` against a mocked
5
+ * `fetch`, or renders a component under `useAuthSession`, sets them up through here.
6
+ */
7
+ import { setAccessToken } from "./httpClient.js";
8
+ import { resetAuthSession } from "./browserEnvironment.js";
9
+ /** Makes every following `apiRequest`/`apiUpload`/`apiDownload` send `token` as its
10
+ * Bearer — as if the session had just refreshed. `null` clears it. */
11
+ export function setTestAccessToken(token) {
12
+ setAccessToken(token);
13
+ }
14
+ /** Stops the tab's session lifecycle, forgets its state and clears the access token, so
15
+ * the next test starts from a fresh boot. */
16
+ export function resetAuthSessionForTests() {
17
+ resetAuthSession();
18
+ setAccessToken(null);
19
+ }
20
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../../../src/auth/client/testing.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3D;uEACuE;AACvE,MAAM,UAAU,kBAAkB,CAAC,KAAoB;IACrD,cAAc,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC;AAED;8CAC8C;AAC9C,MAAM,UAAU,wBAAwB;IACtC,gBAAgB,EAAE,CAAC;IACnB,cAAc,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC"}
@@ -1,100 +1,63 @@
1
- import { AuthUnavailableError } from "./httpClient.js";
2
- import { type AppSwitcherEntry } from "../shared-types.js";
3
- export type AuthStatus = "loading" | "authenticated" | "unauthenticated" | "unavailable" | "error";
4
- /** First delay before re-verifying a session the server could not verify (AK-23). */
5
- export declare const UNAVAILABLE_RETRY_BASE_MS = 1000;
6
- /** The backoff's ceiling: an outage is retried every this-many ms at most. */
7
- export declare const UNAVAILABLE_RETRY_MAX_MS = 30000;
8
1
  /**
9
- * Jittered exponential backoff for the `"unavailable"` state's automatic retries: the
10
- * ceiling doubles per attempt (1s, 2s, 4s, … capped at UNAVAILABLE_RETRY_MAX_MS) and the
11
- * delay is drawn uniformly from its upper half ("equal jitter", AK-23 L-c) — so every
12
- * tab that saw the same outage does not retry in the same instant when it ends, while a
13
- * retry never comes sooner than half the ceiling. `attempt` counts from 0; `random` is
14
- * `Math.random` (a seam for tests).
2
+ * The React face of the flytedesk ID session lifecycle (AK-35) — a view of the ONE
3
+ * per-tab `authSession` (`./browserEnvironment.ts`), never a lifecycle of its own: any
4
+ * number of components can call `useAuthSession()` and there is still exactly one
5
+ * bootstrap, one check timer, one sign-in. Everything it shows, and when, is decided in
6
+ * `./authSession.ts`; an app only renders.
7
+ *
8
+ * The app's one piece of wiring is `SessionBoundary`: its shell for a usable session,
9
+ * the design system's `SessionScreen` for everything else —
10
+ *
11
+ * <SessionBoundary<AuthedUserDto>
12
+ * screen={(state) => <SessionScreen {...state} productName="SMS" />}
13
+ * >
14
+ * {(session) => <Shell session={session} />}
15
+ * </SessionBoundary>
16
+ *
17
+ * `@flytedesk/app-kit` never imports the design system, and the design system never
18
+ * imports this package: `SessionScreenState` is a plain shape `SessionScreen` accepts,
19
+ * checked structurally at the app's call site.
15
20
  */
16
- export declare function unavailableRetryDelayMs(attempt: number, random?: () => number): number;
17
- interface AuthSessionActions {
18
- /** Surfaces a failed sign-out as a rejection (fail loudly, AK-16) — local state is
19
- * cleared once the api confirms it, OR once a `logout_store_failed` response proves
20
- * the server already revoked this session regardless (see the doc comment on the
21
- * `logout_store_failed` branch below). A caller showing a pending state on this
22
- * promise (as a design system's AccountMenu typically does) gets an honest failure
23
- * instead of silence. */
21
+ import * as React from "react";
22
+ import type { AuthenticatedState, AuthSessionState, UnavailableState } from "./authSession.js";
23
+ export interface AuthSessionActions {
24
+ /** Explicit sign-out — see `AuthSessionController.signOut`. Navigates away on
25
+ * success; rejects when the server did not end the session. */
24
26
  signOut: () => Promise<void>;
25
- /** Starts a new bootstrap load from scratch — e.g. a Retry action on the error state.
26
- * It supersedes any load (or pending retry) already in flight: that load's answer is
27
- * ignored, and the one `POST /refresh` it may be waiting on is joined, not repeated. */
28
- refetch: () => void;
29
- }
30
- /**
31
- * The "All flytedesk apps" switcher feed is decoration, not the session (AK-23, N2): it
32
- * never decides the status. When `GET {routePrefix}/apps` fails, `apps` is `[]` and
33
- * `appsError` carries the failure (for an optional "couldn't load apps" hint); the session
34
- * still becomes "authenticated". The next successful load clears it.
35
- */
36
- interface AppsFeed {
37
- apps: AppSwitcherEntry[];
38
- appsError: Error | null;
27
+ /** The failure states' "Try again" — see `AuthSessionController.retry`. */
28
+ retry: () => void;
29
+ /** Re-reads the signed-in user after the app changed it server-side. */
30
+ refreshUser: () => Promise<void>;
39
31
  }
40
- export interface LoadingSessionState extends AuthSessionActions, AppsFeed {
41
- status: "loading";
42
- user: null;
43
- appsError: null;
44
- error: null;
45
- }
46
- /** "authenticated" always carries a user — there is no way to construct this variant
47
- * without one, unlike the pre-AK-18 `{ status: AuthStatus; user: TUser | null }` shape
48
- * that forced every consumer to handle an impossible `authenticated && !user` state by
49
- * hand (sms-app's App.tsx, before this card). */
50
- export interface AuthenticatedSessionState<TUser> extends AuthSessionActions, AppsFeed {
51
- status: "authenticated";
32
+ export type AuthSession<TUser> = AuthSessionState<TUser> & AuthSessionActions;
33
+ /** A session an app can render its shell for: signed in, or an outage that still has a
34
+ * last-known user to show (display-only — see `UnavailableState`). */
35
+ export type UsableSession<TUser> = (AuthenticatedState<TUser> | (UnavailableState<TUser> & {
52
36
  user: TUser;
53
- error: null;
54
- }
55
- export interface UnauthenticatedSessionState extends AuthSessionActions, AppsFeed {
56
- status: "unauthenticated";
57
- user: null;
58
- appsError: null;
59
- error: null;
60
- }
61
- /**
62
- * AK-23: the server could not verify the session right now — flytedesk-id or the app's
63
- * AuthStore is down (an `AuthUnavailableError`, a 503). NOT signed out: the session is
64
- * kept (`user` is the last verified user, or null if none was verified yet) and the hook
65
- * re-verifies it by itself, with exponential backoff (`retryInMs` until the next try,
66
- * capped at UNAVAILABLE_RETRY_MAX_MS), until the server answers — then it moves to
67
- * "authenticated", or to "unauthenticated" only if the server actually says so. Entered
68
- * from the bootstrap, or from "authenticated" when any request made through this
69
- * client hits the outage — including the automatic refresh reaching no decision at all
70
- * (no answer, no answer in time, or an infrastructure 502/503/504: `AUTH_UNREACHABLE_CODE`).
71
- * Render it as "reconnecting", never as a sign-in screen.
72
- *
73
- * `user` is DISPLAY-ONLY (AK-23, L-c): it is who was signed in when the outage began, kept
74
- * so the page can keep showing them while it reconnects. It is not a verified identity
75
- * right now — no authorization decision (showing an admin-only control, enabling a
76
- * destructive action) may be based on it; the server re-checks every request anyway.
77
- */
78
- export interface UnavailableSessionState<TUser> extends AuthSessionActions, AppsFeed {
79
- status: "unavailable";
80
- user: TUser | null;
81
- error: AuthUnavailableError;
82
- retryInMs: number;
37
+ })) & AuthSessionActions;
38
+ export type SessionScreenKind = "signing-in" | "session-expired" | "signing-out" | "reconnecting" | "sign-in-failed" | "load-failed";
39
+ /** What the design system's `SessionScreen` renders for every non-usable state. `error`
40
+ * and `onRetry` are set exactly for the two failure kinds. */
41
+ export interface SessionScreenState {
42
+ kind: SessionScreenKind;
43
+ error: string | null;
44
+ onRetry: (() => void) | null;
83
45
  }
84
- /** Set only when loading the session failed for a reason OTHER than being signed out or
85
- * an auth outage — the api errored, or a request it depends on missed its deadline. */
86
- export interface ErrorSessionState extends AuthSessionActions, AppsFeed {
87
- status: "error";
88
- user: null;
89
- appsError: null;
90
- error: Error;
46
+ /** The tab's session, re-rendering on every change. `TUser` is the shape `GET
47
+ * {routePrefix}/me` answers for this app (e.g. `AuthedUserDto`). */
48
+ export declare function useAuthSession<TUser>(): AuthSession<TUser>;
49
+ /** The screen for a state the app does not render itself, or `null` when the session is
50
+ * usable. The one mapping from lifecycle state to what the user sees. */
51
+ export declare function sessionScreenFor<TUser>(state: AuthSessionState<TUser>): SessionScreenState | null;
52
+ export interface SessionBoundaryProps<TUser> {
53
+ /** The app, for a usable session. */
54
+ children: (session: UsableSession<TUser>) => React.ReactNode;
55
+ /** Everything else — pass the design system's `SessionScreen`. */
56
+ screen: (state: SessionScreenState) => React.ReactNode;
91
57
  }
92
- export type AuthSessionState<TUser> = LoadingSessionState | AuthenticatedSessionState<TUser> | UnauthenticatedSessionState | UnavailableSessionState<TUser> | ErrorSessionState;
93
58
  /**
94
- * `TUser` defaults to `unknown` deliberately: a consuming app almost always has its
95
- * own richer local type (or the exact shape @flytedesk/app-kit/auth's AuthedUser
96
- * describes) it wants `GET {api}{routePrefix}/me`'s `user` decoded as, and should pass
97
- * it explicitly (`useAuthSession<MyUser>(...)`) rather than this module guessing.
59
+ * Renders the app only while the session is usable. In every other state the app is
60
+ * UNMOUNTED — no data panel can fail on its own with an auth error, and nothing it runs
61
+ * (a poll, a timer) keeps calling the api for a session that is over.
98
62
  */
99
- export declare function useAuthSession<TUser = unknown>(): AuthSessionState<TUser>;
100
- export {};
63
+ export declare function SessionBoundary<TUser>({ children, screen, }: SessionBoundaryProps<TUser>): React.ReactNode;
@@ -1,261 +1,74 @@
1
1
  /**
2
- * Generic browser session hook for `@flytedesk/app-kit/auth`'s BFF pattern: bootstraps
3
- * via POST {api}{routePrefix}/refresh (the httpOnly refresh cookie) -> GET
4
- * {api}{routePrefix}/me -> GET {api}{routePrefix}/apps (the "All flytedesk apps"
5
- * switcher feed) — all three routes served by the plugin itself (see ../plugin.js) at
6
- * the paths ../shared-types.js's route contract names, never a hand-typed string on
7
- * either side. Every consuming app was on track to re-implement this by hand (sms-app's
8
- * apps/web/src/session/useAuthSession.ts, before this card) — extracting it here (AK-16)
9
- * means every one gets the StrictMode-safe single-flight bootstrap and the fail-loudly
10
- * sign-out for free, instead of each app getting a slightly different (and possibly
11
- * wrong) version of the same ~80 lines.
2
+ * The React face of the flytedesk ID session lifecycle (AK-35) — a view of the ONE
3
+ * per-tab `authSession` (`./browserEnvironment.ts`), never a lifecycle of its own: any
4
+ * number of components can call `useAuthSession()` and there is still exactly one
5
+ * bootstrap, one check timer, one sign-in. Everything it shows, and when, is decided in
6
+ * `./authSession.ts`; an app only renders.
12
7
  *
13
- * Deliberately narrower than media-planner's SessionKit (packages/design-system/src/
14
- * session.ts): no silent OIDC resume, no cross-tab identity-switch reload, no RBAC
15
- * flag helpers. Those stay app-specific policy layered on top of this shared
16
- * mechanism — media-planner's own switch-over (the PLN-1 card this AK-18 card files)
17
- * keeps SessionKit, just pointed at this module's apiRequest instead of its local copy.
8
+ * The app's one piece of wiring is `SessionBoundary`: its shell for a usable session,
9
+ * the design system's `SessionScreen` for everything else —
10
+ *
11
+ * <SessionBoundary<AuthedUserDto>
12
+ * screen={(state) => <SessionScreen {...state} productName="SMS" />}
13
+ * >
14
+ * {(session) => <Shell session={session} />}
15
+ * </SessionBoundary>
16
+ *
17
+ * `@flytedesk/app-kit` never imports the design system, and the design system never
18
+ * imports this package: `SessionScreenState` is a plain shape `SessionScreen` accepts,
19
+ * checked structurally at the app's call site.
18
20
  */
19
21
  import * as React from "react";
20
- import { apiRequest, ApiRequestError, AuthUnavailableError, onAuthUnavailable, refreshAccessToken, setAccessToken, } from "./httpClient.js";
21
- import { AUTH_ROUTE_PREFIX, authRoutePath } from "../shared-types.js";
22
- /** First delay before re-verifying a session the server could not verify (AK-23). */
23
- export const UNAVAILABLE_RETRY_BASE_MS = 1_000;
24
- /** The backoff's ceiling: an outage is retried every this-many ms at most. */
25
- export const UNAVAILABLE_RETRY_MAX_MS = 30_000;
26
- /**
27
- * Jittered exponential backoff for the `"unavailable"` state's automatic retries: the
28
- * ceiling doubles per attempt (1s, 2s, 4s, … capped at UNAVAILABLE_RETRY_MAX_MS) and the
29
- * delay is drawn uniformly from its upper half ("equal jitter", AK-23 L-c) — so every
30
- * tab that saw the same outage does not retry in the same instant when it ends, while a
31
- * retry never comes sooner than half the ceiling. `attempt` counts from 0; `random` is
32
- * `Math.random` (a seam for tests).
33
- */
34
- export function unavailableRetryDelayMs(attempt, random = Math.random) {
35
- const ceiling = Math.min(UNAVAILABLE_RETRY_BASE_MS * 2 ** attempt, UNAVAILABLE_RETRY_MAX_MS);
36
- return Math.round(ceiling / 2 + random() * (ceiling / 2));
22
+ import { authSession } from "./browserEnvironment.js";
23
+ const actions = {
24
+ signOut: () => authSession.signOut(),
25
+ retry: () => authSession.retry(),
26
+ refreshUser: () => authSession.refreshUser(),
27
+ };
28
+ /** The tab's session, re-rendering on every change. `TUser` is the shape `GET
29
+ * {routePrefix}/me` answers for this app (e.g. `AuthedUserDto`). */
30
+ export function useAuthSession() {
31
+ const state = React.useSyncExternalStore(authSession.subscribe, () => authSession.getSnapshot(), () => authSession.getSnapshot());
32
+ return React.useMemo(() => ({ ...state, ...actions }), [state]);
33
+ }
34
+ /** The screen for a state the app does not render itself, or `null` when the session is
35
+ * usable. The one mapping from lifecycle state to what the user sees. */
36
+ export function sessionScreenFor(state) {
37
+ switch (state.status) {
38
+ case "authenticated":
39
+ return null;
40
+ case "unavailable":
41
+ return state.user === null
42
+ ? { kind: "reconnecting", error: null, onRetry: null }
43
+ : null;
44
+ case "checking":
45
+ return { kind: "signing-in", error: null, onRetry: null };
46
+ case "signing-in":
47
+ return {
48
+ kind: state.reason === "expired" ? "session-expired" : "signing-in",
49
+ error: null,
50
+ onRetry: null,
51
+ };
52
+ case "signing-out":
53
+ return { kind: "signing-out", error: null, onRetry: null };
54
+ case "error":
55
+ return {
56
+ kind: state.kind,
57
+ error: state.error.message,
58
+ onRetry: actions.retry,
59
+ };
60
+ }
37
61
  }
38
- const ME_PATH = authRoutePath(AUTH_ROUTE_PREFIX, "me");
39
- const APPS_PATH = authRoutePath(AUTH_ROUTE_PREFIX, "apps");
40
- const LOGOUT_PATH = authRoutePath(AUTH_ROUTE_PREFIX, "logout");
41
62
  /**
42
- * `TUser` defaults to `unknown` deliberately: a consuming app almost always has its
43
- * own richer local type (or the exact shape @flytedesk/app-kit/auth's AuthedUser
44
- * describes) it wants `GET {api}{routePrefix}/me`'s `user` decoded as, and should pass
45
- * it explicitly (`useAuthSession<MyUser>(...)`) rather than this module guessing.
63
+ * Renders the app only while the session is usable. In every other state the app is
64
+ * UNMOUNTED — no data panel can fail on its own with an auth error, and nothing it runs
65
+ * (a poll, a timer) keeps calling the api for a session that is over.
46
66
  */
47
- export function useAuthSession() {
48
- const [status, setStatus] = React.useState("loading");
49
- const [user, setUser] = React.useState(null);
50
- const [apps, setApps] = React.useState([]);
51
- const [appsError, setAppsError] = React.useState(null);
52
- const [error, setError] = React.useState(null);
53
- const [unavailable, setUnavailable] = React.useState(null);
54
- const [generation, setGeneration] = React.useState(0);
55
- // POST {routePrefix}/refresh ROTATES the refresh cookie on every call (reuse detection
56
- // — see @flytedesk/app-kit/auth's plugin.ts) — a second call presenting the same,
57
- // now-already-consumed cookie is treated as token replay and revokes the whole
58
- // session. React 18+'s <StrictMode> intentionally double-invokes this effect in dev
59
- // (mount -> cleanup -> mount, on the SAME fiber, so this ref survives it) with the
60
- // SAME `generation`, which without a guard fires two concurrent refresh calls
61
- // against that one cookie: the loser gets "token_reuse_detected" and this hook
62
- // bounces to "unauthenticated" for no signed-out reason at all. Tracking which
63
- // generation has already started a load — rather than an unconditional `cancelled`
64
- // flag — is what makes the second StrictMode invocation a no-op while still letting
65
- // `refetch()` (which bumps `generation`) start a genuinely new load.
66
- const startedGenerationRef = React.useRef(null);
67
- // The load/retry machinery, created once per mounted hook (lazy useState initializer:
68
- // guaranteed stable, unlike useMemo). It only touches state setters, which React keeps
69
- // stable, and its own mutable fields.
70
- const [session] = React.useState(() => {
71
- const engine = {
72
- /** Mirrors `status`, readable from outside a render (the outage listener). */
73
- status: "loading",
74
- /** Whether the hook is mounted — a retry never fires into an unmounted one. */
75
- active: false,
76
- retryTimer: null,
77
- retryAttempt: 0,
78
- /**
79
- * AK-23 (L-a): which load may still change state. `signOut` and every fresh load
80
- * (the bootstrap, `refetch`) bump it; a load that finds the epoch moved on since it
81
- * started is stale and drops its answer — so a retry still in flight can neither
82
- * put a signed-out session back into "unavailable" nor overwrite a newer load.
83
- */
84
- epoch: 0,
85
- setStatus(next) {
86
- engine.status = next;
87
- setStatus(next);
88
- },
89
- clearRetry() {
90
- if (engine.retryTimer !== null)
91
- clearTimeout(engine.retryTimer);
92
- engine.retryTimer = null;
93
- },
94
- /** Ends every load in flight and any pending retry — their answers are ignored —
95
- * and returns the new epoch. */
96
- supersede() {
97
- engine.clearRetry();
98
- engine.epoch += 1;
99
- return engine.epoch;
100
- },
101
- /**
102
- * Refresh -> me -> apps. `fresh` (a new bootstrap) supersedes any load in flight and
103
- * shows "loading"; a retry keeps whatever the user is looking at until it has an
104
- * answer.
105
- *
106
- * The refresh is httpClient's shared, single-flighted `refreshAccessToken`, so a
107
- * load started while another one (or any 401-triggered refresh) is waiting on
108
- * `POST /refresh` JOINS that request instead of presenting the same rotating cookie
109
- * a second time. `/me` and `/apps` skip the 401 -> refresh -> recovery dance: right
110
- * after a refresh, a 401 is the answer itself, and a load must never start the
111
- * app's auth recovery (which could sign a user back in after `signOut`).
112
- */
113
- async load(fresh) {
114
- const epoch = fresh ? engine.supersede() : engine.epoch;
115
- const current = () => epoch === engine.epoch;
116
- if (fresh) {
117
- engine.retryAttempt = 0;
118
- setError(null);
119
- setUnavailable(null);
120
- engine.setStatus("loading");
121
- }
122
- try {
123
- const accessToken = await refreshAccessToken();
124
- if (!current())
125
- return;
126
- if (accessToken === null) {
127
- engine.settleSignedOut();
128
- return;
129
- }
130
- const me = await apiRequest(ME_PATH, { skipAuthRetry: true });
131
- if (!current())
132
- return;
133
- const feed = await engine.loadApps();
134
- if (!current())
135
- return;
136
- setUser(me.user);
137
- setApps(feed.apps);
138
- setAppsError(feed.error);
139
- engine.retryAttempt = 0;
140
- setUnavailable(null);
141
- engine.setStatus("authenticated");
142
- }
143
- catch (err) {
144
- if (!current())
145
- return;
146
- if (err instanceof AuthUnavailableError) {
147
- engine.scheduleRetry(err);
148
- return;
149
- }
150
- if (err instanceof ApiRequestError && err.status === 401) {
151
- engine.settleSignedOut();
152
- return;
153
- }
154
- engine.retryAttempt = 0;
155
- setUnavailable(null);
156
- setError(err instanceof Error ? err : new Error(String(err)));
157
- engine.setStatus("error");
158
- }
159
- },
160
- /** The switcher feed, non-blocking (AK-23, N2): a failure is `apps: []` plus the
161
- * error, never a failed load. */
162
- async loadApps() {
163
- try {
164
- const res = await apiRequest(APPS_PATH, { skipAuthRetry: true });
165
- return { apps: res.apps, error: null };
166
- }
167
- catch (err) {
168
- return { apps: [], error: err instanceof Error ? err : new Error(String(err)) };
169
- }
170
- },
171
- /** The server said this browser has no session: local state follows. */
172
- settleSignedOut() {
173
- engine.clearRetry();
174
- engine.retryAttempt = 0;
175
- setAccessToken(null);
176
- setUser(null);
177
- setApps([]);
178
- setAppsError(null);
179
- setUnavailable(null);
180
- engine.setStatus("unauthenticated");
181
- },
182
- /** Enters (or stays in) "unavailable" and re-verifies after the next backoff delay.
183
- * One pending retry at a time: a burst of failing requests schedules one. */
184
- scheduleRetry(err) {
185
- if (!engine.active || engine.retryTimer !== null)
186
- return;
187
- const retryInMs = unavailableRetryDelayMs(engine.retryAttempt);
188
- engine.retryAttempt += 1;
189
- setUnavailable({ error: err, retryInMs });
190
- engine.setStatus("unavailable");
191
- engine.retryTimer = setTimeout(() => {
192
- engine.retryTimer = null;
193
- void engine.load(false);
194
- }, retryInMs);
195
- },
196
- };
197
- return engine;
198
- });
199
- React.useEffect(() => {
200
- session.active = true;
201
- // An ordinary request (anywhere in the app) hitting an outage while signed in: keep
202
- // the user, show "unavailable", and re-verify — never treat it as a sign-out.
203
- const unsubscribe = onAuthUnavailable((err) => {
204
- if (session.status === "authenticated")
205
- session.scheduleRetry(err);
206
- });
207
- return () => {
208
- session.active = false;
209
- session.clearRetry();
210
- unsubscribe();
211
- };
212
- }, [session]);
213
- React.useEffect(() => {
214
- if (startedGenerationRef.current === generation)
215
- return;
216
- startedGenerationRef.current = generation;
217
- void session.load(true);
218
- }, [generation, session]);
219
- const signOut = React.useCallback(async () => {
220
- // Whatever load or retry is in flight belongs to the session being ended: its answer
221
- // must never land after this one (AK-23, L-a).
222
- session.supersede();
223
- try {
224
- await apiRequest(LOGOUT_PATH, { method: "POST" });
225
- }
226
- catch (err) {
227
- if (err instanceof ApiRequestError && err.code === "logout_store_failed") {
228
- // The plugin clears the refresh cookie on EVERY logout outcome (AK-23, in a
229
- // `finally`) and attempts each AuthStore step independently, so this browser
230
- // no longer holds a usable session no matter which step failed here (plugin.ts's
231
- // POST {routePrefix}/logout). Leaving local state at
232
- // "authenticated" here would be exactly the bug the SMS-5 gate found (the design
233
- // system's AccountMenu swallowing this rejection and showing nothing): a UI
234
- // claiming a live session the server has already revoked. Clearing local state
235
- // mirrors the server's actual state; re-throwing still fails loudly so a caller
236
- // can surface "sign-out did not fully complete" rather than reporting a clean one.
237
- session.settleSignedOut();
238
- }
239
- throw err;
240
- }
241
- session.settleSignedOut();
242
- }, [session]);
243
- const refetch = React.useCallback(() => setGeneration((g) => g + 1), []);
244
- const actions = { signOut, refetch };
245
- if (status === "authenticated") {
246
- // Invariant: the only place status flips to "authenticated" is the line right after
247
- // setUser(me.user) above, in the same synchronous pass — so by the time a render
248
- // observes status === "authenticated", `user` is never null.
249
- return { ...actions, status, user: user, apps, appsError, error: null };
250
- }
251
- if (status === "unavailable" && unavailable) {
252
- return { ...actions, status, user, apps, appsError, error: unavailable.error, retryInMs: unavailable.retryInMs };
253
- }
254
- if (status === "error") {
255
- return { ...actions, status, user: null, apps, appsError: null, error: error ?? new Error("unknown error") };
256
- }
257
- if (status === "loading")
258
- return { ...actions, status, user: null, apps, appsError: null, error: null };
259
- return { ...actions, status: "unauthenticated", user: null, apps, appsError: null, error: null };
67
+ export function SessionBoundary({ children, screen, }) {
68
+ const session = useAuthSession();
69
+ const shown = sessionScreenFor(session);
70
+ if (shown !== null)
71
+ return screen(shown);
72
+ return children(session);
260
73
  }
261
74
  //# sourceMappingURL=useAuthSession.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthSession.js","sourceRoot":"","sources":["../../../src/auth/client/useAuthSession.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAuthSession.js","sourceRoot":"","sources":["../../../src/auth/client/useAuthSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAqCtD,MAAM,OAAO,GAAuB;IAClC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE;IACpC,KAAK,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE;IAChC,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE;CAC7C,CAAC;AAEF;qEACqE;AACrE,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,oBAAoB,CACtC,WAAW,CAAC,SAAS,EACrB,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAS,EACtC,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAS,CACvC,CAAC;IACF,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;0EAC0E;AAC1E,MAAM,UAAU,gBAAgB,CAC9B,KAA8B;IAE9B,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,eAAe;YAClB,OAAO,IAAI,CAAC;QACd,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC,IAAI,KAAK,IAAI;gBACxB,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;gBACtD,CAAC,CAAC,IAAI,CAAC;QACX,KAAK,UAAU;YACb,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5D,KAAK,YAAY;YACf,OAAO;gBACL,IAAI,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,YAAY;gBACnE,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,KAAK,aAAa;YAChB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC7D,KAAK,OAAO;YACV,OAAO;gBACL,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;gBAC1B,OAAO,EAAE,OAAO,CAAC,KAAK;aACvB,CAAC;IACN,CAAC;AACH,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAQ,EACrC,QAAQ,EACR,MAAM,GACsB;IAC5B,MAAM,OAAO,GAAG,cAAc,EAAS,CAAC;IACxC,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,QAAQ,CAAC,OAA+B,CAAC,CAAC;AACnD,CAAC"}
@@ -34,7 +34,6 @@
34
34
  * redirectUri: "https://my-app.flytedesk.com/api/v1/auth/callback",
35
35
  * appId: "my-app",
36
36
  * postLoginRedirect: "https://my-app.flytedesk.com/",
37
- * signInUrl: "https://my-app.flytedesk.com/sign-in",
38
37
  * cookieSecret: process.env.COOKIE_SECRET!,
39
38
  * secureCookies: process.env.NODE_ENV === "production",
40
39
  * accessTokenSecret: process.env.JWT_SECRET!,
@@ -44,11 +43,11 @@
44
43
  * app.get("/me", { preHandler: requireAuth }, async (request) => request.authUser);
45
44
  */
46
45
  export { requireAuth, requirePermission } from "./guards.js";
47
- export type { AuthedUser, AuthStore, CreateIdpSessionInput, CreateRefreshTokenInput, FlytedeskAuthOptions, IdpRole, IdpSessionLockedStore, IdpSessionRow, RefreshTokenRevocation, RefreshTokenRevocationReason, RefreshTokenRow, RevokeFamilyReason, SignInContext, SignInMode, UpdateIdpSessionInput, UserinfoClaims, } from "./types.js";
46
+ export type { AuthedUser, AuthStore, CreateIdpSessionInput, CreateRefreshTokenInput, FlytedeskAuthOptions, IdpRole, IdpSessionLockedStore, IdpSessionRow, RefreshTokenRevocation, RefreshTokenRevocationReason, RefreshTokenRow, RevokeFamilyReason, UpdateIdpSessionInput, UserinfoClaims, } from "./types.js";
48
47
  export type { AppSwitcherEntry, IdpAuthorization, IdpTokenResponse, IdTokenClaims, OidcClient, OidcClientOptions, } from "./oidc-client.js";
49
48
  export { createOidcClient, DEFAULT_OIDC_SCOPES, DEFAULT_IDP_REQUEST_TIMEOUT_MS } from "./oidc-client.js";
50
- export type { ApiErrorBody, AuthUnavailableCode, SilentAuthDetailCode, SilentAuthMessage, SignInErrorCode, } from "./shared-types.js";
51
- export { AUTH_REQUEST_DEADLINE_MS, AUTH_ROUTE_PREFIX, AUTH_ROUTE_SEGMENTS, AUTH_UNAVAILABLE_CODES, authRoutePath, SILENT_AUTH_DETAIL_CODES, SILENT_AUTH_MESSAGE_SOURCE, SIGNIN_ERROR_QUERY_PARAM, SIGNIN_ERROR_CODES, type AuthRouteSegment, } from "./shared-types.js";
49
+ export type { ApiErrorBody, AuthUnavailableCode, SignInErrorCode, } from "./shared-types.js";
50
+ export { AUTH_REQUEST_DEADLINE_MS, AUTH_ROUTE_PREFIX, AUTH_ROUTE_SEGMENTS, AUTH_UNAVAILABLE_CODES, authRoutePath, SIGNIN_ERROR_QUERY_PARAM, SIGNIN_ERROR_CODES, type AuthRouteSegment, } from "./shared-types.js";
52
51
  export { IdpError, IdpUnavailableError, IdpTimeoutError, IdpAccessRevokedError, AuthStoreError, OidcHttpError, OidcTokenError, classifyIdpError, } from "./errors.js";
53
52
  export { generatePkce, randomState, type PkcePair } from "./pkce.js";
54
53
  export { generateRefreshToken, hashRefreshToken, signAccessToken, verifyAccessToken, type AccessTokenClaims, } from "./tokens.js";
@@ -34,7 +34,6 @@
34
34
  * redirectUri: "https://my-app.flytedesk.com/api/v1/auth/callback",
35
35
  * appId: "my-app",
36
36
  * postLoginRedirect: "https://my-app.flytedesk.com/",
37
- * signInUrl: "https://my-app.flytedesk.com/sign-in",
38
37
  * cookieSecret: process.env.COOKIE_SECRET!,
39
38
  * secureCookies: process.env.NODE_ENV === "production",
40
39
  * accessTokenSecret: process.env.JWT_SECRET!,
@@ -45,7 +44,7 @@
45
44
  */
46
45
  export { requireAuth, requirePermission } from "./guards.js";
47
46
  export { createOidcClient, DEFAULT_OIDC_SCOPES, DEFAULT_IDP_REQUEST_TIMEOUT_MS } from "./oidc-client.js";
48
- export { AUTH_REQUEST_DEADLINE_MS, AUTH_ROUTE_PREFIX, AUTH_ROUTE_SEGMENTS, AUTH_UNAVAILABLE_CODES, authRoutePath, SILENT_AUTH_DETAIL_CODES, SILENT_AUTH_MESSAGE_SOURCE, SIGNIN_ERROR_QUERY_PARAM, SIGNIN_ERROR_CODES, } from "./shared-types.js";
47
+ export { AUTH_REQUEST_DEADLINE_MS, AUTH_ROUTE_PREFIX, AUTH_ROUTE_SEGMENTS, AUTH_UNAVAILABLE_CODES, authRoutePath, SIGNIN_ERROR_QUERY_PARAM, SIGNIN_ERROR_CODES, } from "./shared-types.js";
49
48
  export { IdpError, IdpUnavailableError, IdpTimeoutError, IdpAccessRevokedError, AuthStoreError, OidcHttpError, OidcTokenError, classifyIdpError, } from "./errors.js";
50
49
  export { generatePkce, randomState } from "./pkce.js";
51
50
  export { generateRefreshToken, hashRefreshToken, signAccessToken, verifyAccessToken, } from "./tokens.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA6B7D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AASzG,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,wBAAwB,EACxB,0BAA0B,EAC1B,wBAAwB,EACxB,kBAAkB,GAEnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAiB,MAAM,WAAW,CAAC;AAErE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAElB,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA2B7D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAOzG,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,aAAa,EACb,wBAAwB,EACxB,kBAAkB,GAEnB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAiB,MAAM,WAAW,CAAC;AAErE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAElB,MAAM,aAAa,CAAC"}