@xeonr/console-shell 0.5.7 → 0.5.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.
- package/dist/CommandPalette.d.ts.map +1 -1
- package/dist/CommandPalette.js +2 -0
- package/dist/CommandPalette.js.map +1 -1
- package/dist/ConsoleShell.d.ts +10 -1
- package/dist/ConsoleShell.d.ts.map +1 -1
- package/dist/ConsoleShell.js +47 -4
- package/dist/ConsoleShell.js.map +1 -1
- package/dist/ScopeCard.d.ts.map +1 -1
- package/dist/ScopeCard.js +2 -0
- package/dist/ScopeCard.js.map +1 -1
- package/dist/client.d.ts +4 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +8 -4
- package/dist/client.js.map +1 -1
- package/dist/devMock.d.ts.map +1 -1
- package/dist/devMock.js +7 -0
- package/dist/devMock.js.map +1 -1
- package/dist/gen/xeonr/console/v1/console_pb.d.ts +76 -0
- package/dist/gen/xeonr/console/v1/console_pb.d.ts.map +1 -1
- package/dist/gen/xeonr/console/v1/console_pb.js +24 -19
- package/dist/gen/xeonr/console/v1/console_pb.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/screen.d.ts +16 -0
- package/dist/screen.d.ts.map +1 -1
- package/dist/screen.js +14 -0
- package/dist/screen.js.map +1 -1
- package/dist/session.d.ts +148 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +151 -0
- package/dist/session.js.map +1 -0
- package/dist/sessionReact.d.ts +41 -0
- package/dist/sessionReact.d.ts.map +1 -0
- package/dist/sessionReact.js +58 -0
- package/dist/sessionReact.js.map +1 -0
- package/dist/shellConfig.d.ts +3 -0
- package/dist/shellConfig.d.ts.map +1 -1
- package/dist/shellConfig.js.map +1 -1
- package/dist/switchNotice.d.ts +28 -0
- package/dist/switchNotice.d.ts.map +1 -0
- package/dist/switchNotice.js +20 -0
- package/dist/switchNotice.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -4
- package/scripts/check-entity-crumbs.mjs +319 -0
package/dist/session.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// The BFF session from a console's side (BUILDING-SERVICES §11.7): what
|
|
2
|
+
// /auth/me answered, the sign-in redirect, and the loop guard that stops the
|
|
3
|
+
// redirect bouncing. connectConsoleClient's default Unauthenticated handling
|
|
4
|
+
// goes through signIn() here, so the shell's redirect and the console's are
|
|
5
|
+
// one redirect with one guard rather than two.
|
|
6
|
+
//
|
|
7
|
+
// Everything that decides is a plain function over an injectable clock,
|
|
8
|
+
// storage and navigation, so it is tested without a DOM; the React side
|
|
9
|
+
// (sessionReact.tsx) only holds the answer in state.
|
|
10
|
+
/** Sorts an /auth/me response. */
|
|
11
|
+
export async function readAuthMe(resp) {
|
|
12
|
+
if (resp.status === 401)
|
|
13
|
+
return { kind: "none" };
|
|
14
|
+
let body = null;
|
|
15
|
+
if (resp.headers.get("content-type")?.includes("application/json")) {
|
|
16
|
+
try {
|
|
17
|
+
body = await resp.json();
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
body = null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const authenticated = typeof body === "object" && body !== null && body.authenticated === true;
|
|
24
|
+
if (!resp.ok)
|
|
25
|
+
return { kind: "denied", status: resp.status, signedIn: authenticated };
|
|
26
|
+
if (authenticated)
|
|
27
|
+
return { kind: "session", me: body };
|
|
28
|
+
return { kind: "none" };
|
|
29
|
+
}
|
|
30
|
+
/** Asks the console's own BFF who is signed in. A request that never got an answer is `denied` with status 0. */
|
|
31
|
+
export async function fetchAuthMe(fetchImpl = fetch) {
|
|
32
|
+
let resp;
|
|
33
|
+
try {
|
|
34
|
+
resp = await fetchImpl("/auth/me", { credentials: "same-origin" });
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return { kind: "denied", status: 0, signedIn: false };
|
|
38
|
+
}
|
|
39
|
+
return readAuthMe(resp);
|
|
40
|
+
}
|
|
41
|
+
// ---- the loop guard ----
|
|
42
|
+
/**
|
|
43
|
+
* How recently a sign-in redirect has to have gone out for a console to count
|
|
44
|
+
* coming back without a session as a loop. A bounce comes round in a second or
|
|
45
|
+
* two; two minutes leaves room for an interactive sign-in without ever looping
|
|
46
|
+
* more than once.
|
|
47
|
+
*
|
|
48
|
+
* Only a recent attempt counts. sessionStorage lives as long as the tab, across
|
|
49
|
+
* every navigation to other origins and back, so a bare "have we tried" flag —
|
|
50
|
+
* what the consoles' own copies were until CON-39 — latched the refusal wall
|
|
51
|
+
* for good after one failed round trip, even once its cause was fixed.
|
|
52
|
+
*/
|
|
53
|
+
export const SIGN_IN_WINDOW_MS = 2 * 60_000;
|
|
54
|
+
/** One key per origin is enough: sessionStorage is per-origin, and each console has its own. */
|
|
55
|
+
const ATTEMPT_KEY = "xeonr_signin_attempted";
|
|
56
|
+
function storageOf(env) {
|
|
57
|
+
if (env?.storage !== undefined)
|
|
58
|
+
return env.storage;
|
|
59
|
+
try {
|
|
60
|
+
return globalThis.sessionStorage ?? null;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Storage disabled (some private modes throw on access): losing the guard
|
|
64
|
+
// costs only the loop protection, so carry on without it.
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const nowOf = (env) => (env?.now ?? Date.now)();
|
|
69
|
+
export function markSignInAttempt(env) {
|
|
70
|
+
try {
|
|
71
|
+
storageOf(env)?.setItem(ATTEMPT_KEY, String(nowOf(env)));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
/* see storageOf */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function clearSignInAttempt(env) {
|
|
78
|
+
try {
|
|
79
|
+
storageOf(env)?.removeItem(ATTEMPT_KEY);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
/* see storageOf */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/** Whether a sign-in redirect went out inside the window. A value that is not a timestamp — the old "1" — does not count. */
|
|
86
|
+
export function signInAttemptedRecently(env) {
|
|
87
|
+
try {
|
|
88
|
+
const at = Number(storageOf(env)?.getItem(ATTEMPT_KEY));
|
|
89
|
+
const age = nowOf(env) - at;
|
|
90
|
+
return at > 0 && age >= 0 && age < SIGN_IN_WINDOW_MS;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// ---- signing in and out ----
|
|
97
|
+
function here() {
|
|
98
|
+
const loc = globalThis.location;
|
|
99
|
+
return loc ? loc.pathname + loc.search : "/";
|
|
100
|
+
}
|
|
101
|
+
const assign = (url) => globalThis.location.assign(url);
|
|
102
|
+
/** The BFF's sign-in, landing back on `returnTo` (default: the current page). */
|
|
103
|
+
export function signInUrl(returnTo = here()) {
|
|
104
|
+
return `/auth/login?return=${encodeURIComponent(returnTo)}`;
|
|
105
|
+
}
|
|
106
|
+
/** The BFF's sign-out: it clears the session and ends the issuer's, so every console signs out. */
|
|
107
|
+
export const signOutUrl = "/auth/logout";
|
|
108
|
+
/**
|
|
109
|
+
* Sends the browser to sign in and records the attempt — unless one went out
|
|
110
|
+
* inside the window, in which case it does nothing and returns false: the
|
|
111
|
+
* caller is looking at a loop and should say so (SessionWall's `stuck`) rather
|
|
112
|
+
* than bounce again.
|
|
113
|
+
*/
|
|
114
|
+
export function signIn(opts = {}) {
|
|
115
|
+
if (!opts.force && signInAttemptedRecently(opts))
|
|
116
|
+
return false;
|
|
117
|
+
markSignInAttempt(opts);
|
|
118
|
+
(opts.navigate ?? assign)(signInUrl(opts.returnTo));
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* What a client does with an Unauthenticated error it was not told how to
|
|
123
|
+
* handle: sign in, guarded, and never settle — the page is leaving. Inside the
|
|
124
|
+
* guard's window that would loop, so it rethrows the error instead and the
|
|
125
|
+
* console's SessionWall explains. connectConsoleClient's default.
|
|
126
|
+
*/
|
|
127
|
+
export function signInOrThrow(err, opts = {}) {
|
|
128
|
+
if (!signIn(opts))
|
|
129
|
+
throw err;
|
|
130
|
+
return new Promise(() => { });
|
|
131
|
+
}
|
|
132
|
+
/** Signs out everywhere. Clears the guard, so the next sign-in is not mistaken for a loop. */
|
|
133
|
+
export function signOut(opts = {}) {
|
|
134
|
+
clearSignInAttempt(opts);
|
|
135
|
+
(opts.navigate ?? assign)(signOutUrl);
|
|
136
|
+
}
|
|
137
|
+
/** Turns an answer into a state, signing in (guarded) when there is no session. A session clears the guard. */
|
|
138
|
+
export function settleSession(answer, opts = {}) {
|
|
139
|
+
switch (answer.kind) {
|
|
140
|
+
case "session":
|
|
141
|
+
clearSignInAttempt(opts);
|
|
142
|
+
return { status: "signed-in", me: answer.me };
|
|
143
|
+
case "denied":
|
|
144
|
+
return { status: "denied", httpStatus: answer.status, signedIn: answer.signedIn };
|
|
145
|
+
case "none":
|
|
146
|
+
if (opts.signedOut === "render")
|
|
147
|
+
return { status: "signed-out" };
|
|
148
|
+
return signIn(opts) ? { status: "signing-in" } : { status: "stuck" };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type SessionState, type SettleOptions } from "./session.ts";
|
|
3
|
+
export interface AuthSessionProviderProps {
|
|
4
|
+
/**
|
|
5
|
+
* What no session means here: `"sign-in"` (default) redirects, guarded;
|
|
6
|
+
* `"render"` hands `signed-out` to the console — a public surface, or a
|
|
7
|
+
* deployment running without authentication.
|
|
8
|
+
*/
|
|
9
|
+
signedOut?: SettleOptions["signedOut"];
|
|
10
|
+
/** For tests and the dev mock; defaults to the global fetch. */
|
|
11
|
+
fetchImpl?: typeof fetch | undefined;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
/** Resolves the session once for the whole console. Mount it above anything that calls useAuthSession. */
|
|
15
|
+
export declare function AuthSessionProvider({ signedOut, fetchImpl, children }: AuthSessionProviderProps): import("react").JSX.Element;
|
|
16
|
+
/**
|
|
17
|
+
* The session, typed with the product's own view of the caller (`me.product`).
|
|
18
|
+
* Throws outside AuthSessionProvider: a screen that reads the session before
|
|
19
|
+
* it exists is a wiring mistake, not a signed-out caller.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useAuthSession<P = unknown>(): {
|
|
22
|
+
state: SessionState<P>;
|
|
23
|
+
reload: () => void;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The page for a session state a console cannot render its screens in and
|
|
27
|
+
* must not redirect out of, or null for every other state.
|
|
28
|
+
*
|
|
29
|
+
* - `stuck`: a sign-in went round and came back without a session. Try again
|
|
30
|
+
* is a person's choice, so it goes even inside the guard's window.
|
|
31
|
+
* - `denied` with `signedIn`: the product refused a session that verified —
|
|
32
|
+
* its required group, most often. Signing in as someone else is the way out.
|
|
33
|
+
* - `denied` otherwise: the product failed, or could not be reached.
|
|
34
|
+
*
|
|
35
|
+
* `product` names the console in the copy ("Databases", "Trellis").
|
|
36
|
+
*/
|
|
37
|
+
export declare function SessionWall({ state, product }: {
|
|
38
|
+
state: SessionState<unknown>;
|
|
39
|
+
product: string;
|
|
40
|
+
}): ReactNode;
|
|
41
|
+
//# sourceMappingURL=sessionReact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionReact.d.ts","sourceRoot":"","sources":["../src/sessionReact.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpG,OAAO,EAA+C,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAclH,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACvC,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,KAAK,GAAG,SAAS,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,0GAA0G;AAC1G,wBAAgB,mBAAmB,CAAC,EAAE,SAAqB,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,wBAAwB,+BAgB3G;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,GAAG,OAAO,KAAK;IAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,CAI5F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAgC5G"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
|
3
|
+
import { AppButton, EmptyState } from "@xeonr/platform-ui";
|
|
4
|
+
import { fetchAuthMe, settleSession, signIn, signOut } from "./session.js";
|
|
5
|
+
const AuthSessionCtx = createContext(null);
|
|
6
|
+
/** Resolves the session once for the whole console. Mount it above anything that calls useAuthSession. */
|
|
7
|
+
export function AuthSessionProvider({ signedOut = "sign-in", fetchImpl, children }) {
|
|
8
|
+
const [state, setState] = useState({ status: "loading" });
|
|
9
|
+
const [generation, setGeneration] = useState(0);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
let live = true;
|
|
12
|
+
void fetchAuthMe(fetchImpl).then((answer) => {
|
|
13
|
+
if (live)
|
|
14
|
+
setState(settleSession(answer, { signedOut }));
|
|
15
|
+
});
|
|
16
|
+
return () => {
|
|
17
|
+
live = false;
|
|
18
|
+
};
|
|
19
|
+
}, [fetchImpl, signedOut, generation]);
|
|
20
|
+
const reload = useCallback(() => setGeneration((g) => g + 1), []);
|
|
21
|
+
return _jsx(AuthSessionCtx.Provider, { value: { state, reload }, children: children });
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The session, typed with the product's own view of the caller (`me.product`).
|
|
25
|
+
* Throws outside AuthSessionProvider: a screen that reads the session before
|
|
26
|
+
* it exists is a wiring mistake, not a signed-out caller.
|
|
27
|
+
*/
|
|
28
|
+
export function useAuthSession() {
|
|
29
|
+
const v = useContext(AuthSessionCtx);
|
|
30
|
+
if (!v)
|
|
31
|
+
throw new Error("useAuthSession needs an AuthSessionProvider above it");
|
|
32
|
+
return v;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The page for a session state a console cannot render its screens in and
|
|
36
|
+
* must not redirect out of, or null for every other state.
|
|
37
|
+
*
|
|
38
|
+
* - `stuck`: a sign-in went round and came back without a session. Try again
|
|
39
|
+
* is a person's choice, so it goes even inside the guard's window.
|
|
40
|
+
* - `denied` with `signedIn`: the product refused a session that verified —
|
|
41
|
+
* its required group, most often. Signing in as someone else is the way out.
|
|
42
|
+
* - `denied` otherwise: the product failed, or could not be reached.
|
|
43
|
+
*
|
|
44
|
+
* `product` names the console in the copy ("Databases", "Trellis").
|
|
45
|
+
*/
|
|
46
|
+
export function SessionWall({ state, product }) {
|
|
47
|
+
if (state.status === "stuck") {
|
|
48
|
+
return (_jsx(EmptyState, { icon: "lock", title: "Sign-in didn't finish", desc: "You were sent to sign in, but came back without a session. Try again \u2014 if it keeps happening, tell the platform team.", action: _jsx(AppButton, { variant: "grad", onClick: () => { signIn({ force: true }); }, children: "Try again" }) }));
|
|
49
|
+
}
|
|
50
|
+
if (state.status === "denied" && state.signedIn) {
|
|
51
|
+
return (_jsx(EmptyState, { icon: "lock", title: "Signed in, but not allowed here", desc: `${product} didn't accept your account. If you've just been given access, sign in again; otherwise ask an organisation admin.`, action: _jsx(AppButton, { onClick: () => { signOut(); }, children: "Sign in as someone else" }) }));
|
|
52
|
+
}
|
|
53
|
+
if (state.status === "denied") {
|
|
54
|
+
return (_jsx(EmptyState, { icon: "error", title: "Couldn't load your account", desc: `${product} couldn't open a session for you. Reload to try again; if it keeps happening, tell the platform team.`, action: _jsx(AppButton, { onClick: () => { globalThis.location.reload(); }, children: "Reload" }) }));
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=sessionReact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionReact.js","sourceRoot":"","sources":["../src/sessionReact.tsx"],"names":[],"mappings":"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"}
|
package/dist/shellConfig.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface ShellConfig {
|
|
|
8
8
|
scope: Scope;
|
|
9
9
|
scopes: ScopeMap;
|
|
10
10
|
can?: Can | undefined;
|
|
11
|
+
/** the host's `organisation` prop, else GetMe's (CON-47); readers never look at either directly */
|
|
11
12
|
organisation?: {
|
|
12
13
|
name: string;
|
|
13
14
|
avatarUrl?: string | undefined;
|
|
@@ -31,6 +32,8 @@ export interface ShellConfig {
|
|
|
31
32
|
onScopeChange?: ((scope: Scope, place: Place) => string | void) | undefined;
|
|
32
33
|
/** the sidebar is the 56px icon column */
|
|
33
34
|
collapsed: boolean;
|
|
35
|
+
/** a team row was picked: remember the lit section so a dropped one can be named (CON-42) */
|
|
36
|
+
noteSwitch: (team: Team) => void;
|
|
34
37
|
/** close the phone drawer — every navigation from the chrome does */
|
|
35
38
|
closeDrawer: () => void;
|
|
36
39
|
/** where a signed-out reader signs in (the account menu's signInHref) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shellConfig.d.ts","sourceRoot":"","sources":["../src/shellConfig.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAO9C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,QAAQ,CAAC;IACjB,GAAG,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;IACtB,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5E,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,sEAAsE;IACtE,cAAc,EAAE,cAAc,CAAC;IAC/B,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,eAAe,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1E,oEAAoE;IACpE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5E,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,qEAAqE;IACrE,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CAClE;AAID,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEnG;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAIvD;AAED,wBAAgB,cAAc,IAAI,WAAW,CAI5C"}
|
|
1
|
+
{"version":3,"file":"shellConfig.d.ts","sourceRoot":"","sources":["../src/shellConfig.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAO9C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,QAAQ,CAAC;IACjB,GAAG,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;IACtB,mGAAmG;IACnG,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;IAC5E,SAAS,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACjC,sEAAsE;IACtE,cAAc,EAAE,cAAc,CAAC;IAC/B,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,eAAe,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1E,oEAAoE;IACpE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IAC5E,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,6FAA6F;IAC7F,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACjC,qEAAqE;IACrE,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CAClE;AAID,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAEnG;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAIvD;AAED,wBAAgB,cAAc,IAAI,WAAW,CAI5C"}
|
package/dist/shellConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shellConfig.js","sourceRoot":"","sources":["../src/shellConfig.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAKlE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"shellConfig.js","sourceRoot":"","sources":["../src/shellConfig.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAKlE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA2CvC,MAAM,GAAG,GAAG,aAAa,CAAqB,IAAI,CAAC,CAAC;AAEpD,MAAM,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAA+C;IAClG,OAAO,KAAC,GAAG,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAgB,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC;IACjC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC/D,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Scope } from "./types.ts";
|
|
2
|
+
export interface PendingSwitch {
|
|
3
|
+
/** the team switched to, as the card names it */
|
|
4
|
+
team: string;
|
|
5
|
+
/** the lit section when the switch was made */
|
|
6
|
+
fromKey: string;
|
|
7
|
+
fromLabel: string;
|
|
8
|
+
/** set when the switch left a personal or organisation page */
|
|
9
|
+
fromScope?: Exclude<Scope, "team"> | undefined;
|
|
10
|
+
/** the pathname the switch was made on; nothing is said until it changes */
|
|
11
|
+
path: string;
|
|
12
|
+
at: number;
|
|
13
|
+
}
|
|
14
|
+
/** How long a switch waits for its navigation before it is forgotten. */
|
|
15
|
+
export declare const SWITCH_WINDOW_MS = 3000;
|
|
16
|
+
/** How long the URL must be still before the lit section is read (redirects, useActiveSection). */
|
|
17
|
+
export declare const SWITCH_SETTLE_MS = 300;
|
|
18
|
+
/**
|
|
19
|
+
* The notice for a settled switch, or null when the section was kept, nothing
|
|
20
|
+
* was lit to begin with, or the switch never navigated.
|
|
21
|
+
*/
|
|
22
|
+
export declare function droppedSectionNotice(p: PendingSwitch, now: {
|
|
23
|
+
path: string;
|
|
24
|
+
key: string | undefined;
|
|
25
|
+
label: string | undefined;
|
|
26
|
+
at: number;
|
|
27
|
+
}): string | null;
|
|
28
|
+
//# sourceMappingURL=switchNotice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switchNotice.d.ts","sourceRoot":"","sources":["../src/switchNotice.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAaxC,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAC/C,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,OAAO,CAAC;AACrC,mGAAmG;AACnG,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAO3J"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** How long a switch waits for its navigation before it is forgotten. */
|
|
2
|
+
export const SWITCH_WINDOW_MS = 3000;
|
|
3
|
+
/** How long the URL must be still before the lit section is read (redirects, useActiveSection). */
|
|
4
|
+
export const SWITCH_SETTLE_MS = 300;
|
|
5
|
+
/**
|
|
6
|
+
* The notice for a settled switch, or null when the section was kept, nothing
|
|
7
|
+
* was lit to begin with, or the switch never navigated.
|
|
8
|
+
*/
|
|
9
|
+
export function droppedSectionNotice(p, now) {
|
|
10
|
+
if (now.path === p.path)
|
|
11
|
+
return null;
|
|
12
|
+
if (now.at - p.at > SWITCH_WINDOW_MS)
|
|
13
|
+
return null;
|
|
14
|
+
if (now.key === p.fromKey)
|
|
15
|
+
return null;
|
|
16
|
+
const to = now.label ?? "the start page";
|
|
17
|
+
const why = p.fromScope === "personal" ? "is a personal page" : p.fromScope === "organisation" ? "is an organisation page" : "isn't kept on a team switch here";
|
|
18
|
+
return `Switched to ${p.team}. ${p.fromLabel} ${why}, so you're on ${to}.`;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=switchNotice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switchNotice.js","sourceRoot":"","sources":["../src/switchNotice.ts"],"names":[],"mappings":"AA0BA,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AACrC,mGAAmG;AACnG,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAAgB,EAAE,GAAqF;IAC1I,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,gBAAgB;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,IAAI,gBAAgB,CAAC;IACzC,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,kCAAkC,CAAC;IAChK,OAAO,eAAe,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,SAAS,IAAI,GAAG,kBAAkB,EAAE,GAAG,CAAC;AAC7E,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -45,6 +45,13 @@ export interface Team {
|
|
|
45
45
|
/** Whether the caller could enable it for this team themselves. */
|
|
46
46
|
canEnable?: boolean | undefined;
|
|
47
47
|
}
|
|
48
|
+
/** The organisation a console belongs to (GetMe's `organisation`, AUTH-112). */
|
|
49
|
+
export interface Organisation {
|
|
50
|
+
name: string;
|
|
51
|
+
slug?: string | undefined;
|
|
52
|
+
/** absolute URL; absent when it has none, and the shell draws initials */
|
|
53
|
+
avatarUrl?: string | undefined;
|
|
54
|
+
}
|
|
48
55
|
export interface Me {
|
|
49
56
|
subject: string;
|
|
50
57
|
displayName: string;
|
|
@@ -56,6 +63,12 @@ export interface Me {
|
|
|
56
63
|
isOrgAdmin: boolean;
|
|
57
64
|
/** why the team list is degraded, when it is (from the BFF) */
|
|
58
65
|
warnings?: string[] | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* The organisation the console belongs to. Absent when auth predates the
|
|
68
|
+
* lookup or refused it; the shell then uses ConsoleShell's `organisation`
|
|
69
|
+
* prop, then `scopes.organisation.label`, then "Organisation".
|
|
70
|
+
*/
|
|
71
|
+
organisation?: Organisation | undefined;
|
|
59
72
|
}
|
|
60
73
|
export interface Invitation {
|
|
61
74
|
id: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,KAAK,GAAG,UAAU,GAAG,MAAM,GAAG,cAAc,CAAC;AAEzD,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,MAAM,GACN,iBAAiB,GACjB,YAAY,GACZ,eAAe,GACf,mBAAmB,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAE/D,wGAAwG;AACxG,MAAM,WAAW,OAAO;IACtB,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,kGAAkG;IAClG,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB,qFAAqF;IACrF,SAAS,EAAE,OAAO,CAAC;IACnB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,IAAI;IACnB,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,2BAA2B;IAC3B,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,mEAAmE;IACnE,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,EAAE;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xeonr/console-shell",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"description": "The Xeonr Cloud Console chrome: product rail, team switcher, section sidebar, top bar, ⌘K and the All-products launcher, plus the console context hooks every product console mounts.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -16,14 +16,18 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
|
-
"dist"
|
|
19
|
+
"dist",
|
|
20
|
+
"scripts"
|
|
20
21
|
],
|
|
22
|
+
"bin": {
|
|
23
|
+
"xeonr-check-entity-crumbs": "./scripts/check-entity-crumbs.mjs"
|
|
24
|
+
},
|
|
21
25
|
"peerDependencies": {
|
|
22
26
|
"react": "^19.0.0",
|
|
23
27
|
"react-dom": "^19.0.0",
|
|
24
28
|
"react-router-dom": "^7.0.0",
|
|
25
29
|
"styled-components": "^6.0.0",
|
|
26
|
-
"@xeonr/platform-ui": "^0.5.
|
|
30
|
+
"@xeonr/platform-ui": "^0.5.9"
|
|
27
31
|
},
|
|
28
32
|
"devDependencies": {
|
|
29
33
|
"@types/node": "^24.19.2",
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
"react-router-dom": "^7.8.0",
|
|
35
39
|
"styled-components": "^6.1.19",
|
|
36
40
|
"typescript": "^5.9.2",
|
|
37
|
-
"@xeonr/platform-ui": "0.5.
|
|
41
|
+
"@xeonr/platform-ui": "0.5.9"
|
|
38
42
|
},
|
|
39
43
|
"dependencies": {
|
|
40
44
|
"@bufbuild/protobuf": "^2.10.2",
|