@herdingbits/trailhead-core 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/public-api.d.ts +2 -1
- package/dist/adapters/public-api.d.ts.map +1 -1
- package/dist/adapters/public-api.js +1 -1
- package/dist/adapters/types.d.ts +47 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/types.js +11 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/lib/reauth.d.ts +32 -0
- package/dist/lib/reauth.d.ts.map +1 -0
- package/dist/lib/reauth.js +56 -0
- package/dist/shell.d.ts +2 -0
- package/dist/shell.d.ts.map +1 -1
- package/dist/shell.js +5 -0
- package/dist/types/public-api.d.ts +1 -1
- package/dist/types/public-api.d.ts.map +1 -1
- package/dist/types/shell-api.d.ts +31 -0
- package/dist/types/shell-api.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Public Adapter API - For creating custom design system adapters
|
|
3
3
|
*/
|
|
4
|
-
export type { DesignSystemAdapter, FeedbackAdapter, ToastVariant, DialogButton, DialogConfig, DialogResult, } from './types.js';
|
|
4
|
+
export type { DesignSystemAdapter, FeedbackAdapter, ToastVariant, DialogButton, DialogConfig, DialogResult, AuthAdapter, Credentials, CredentialPromptHandle, } from './types.js';
|
|
5
|
+
export { NoopAuthAdapter } from './types.js';
|
|
5
6
|
//# sourceMappingURL=public-api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../src/adapters/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../src/adapters/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/adapters/types.d.ts
CHANGED
|
@@ -48,6 +48,47 @@ export interface FeedbackAdapter {
|
|
|
48
48
|
/** Render a modal dialog and resolve with whichever button the user clicked. */
|
|
49
49
|
showDialog<T extends string>(config: DialogConfig<T>): Promise<DialogResult<T>>;
|
|
50
50
|
}
|
|
51
|
+
/** Credentials collected by an `AuthAdapter`'s re-authentication prompt. */
|
|
52
|
+
export interface Credentials {
|
|
53
|
+
username: string;
|
|
54
|
+
password: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A still-open (or just-closed) credential prompt. Returned by `AuthAdapter.promptCredentials`
|
|
58
|
+
* so the core orchestration in `lib/reauth.ts` can dismiss a stale prompt — e.g. when another
|
|
59
|
+
* browser tab's re-authentication already succeeded and this tab's own prompt is no longer
|
|
60
|
+
* needed. `close()` must be safe to call after the prompt has already resolved on its own.
|
|
61
|
+
*/
|
|
62
|
+
export interface CredentialPromptHandle {
|
|
63
|
+
/** Resolves with the entered credentials, or `null` if the user cancelled. */
|
|
64
|
+
result: Promise<Credentials | null>;
|
|
65
|
+
/** Dismisses the prompt programmatically, resolving `result` with `null` if still pending. */
|
|
66
|
+
close(): void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Implemented by adapters to collect credentials for in-place session re-authentication —
|
|
70
|
+
* e.g. when a request fails because the session expired, and the app wants to recover without
|
|
71
|
+
* losing the user's place (no navigation, no lost form state) rather than forcing a full reload.
|
|
72
|
+
* Each adapter renders this however fits its design system; `lib/reauth.ts` only depends on the
|
|
73
|
+
* `promptCredentials` contract, never on how it's drawn.
|
|
74
|
+
*/
|
|
75
|
+
export interface AuthAdapter {
|
|
76
|
+
/**
|
|
77
|
+
* Prompts for a username and password.
|
|
78
|
+
* @param errorMessage - Set when re-prompting after a failed attempt (e.g. "Incorrect
|
|
79
|
+
* username or password."); omitted on the first prompt.
|
|
80
|
+
*/
|
|
81
|
+
promptCredentials(errorMessage?: string): CredentialPromptHandle;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* `AuthAdapter` that never actually prompts — `promptCredentials` resolves `null` (cancelled)
|
|
85
|
+
* immediately. Lets an adapter satisfy the required `auth` field with zero UI work: requests
|
|
86
|
+
* that hit an expired session simply fail exactly as they would with no re-authentication
|
|
87
|
+
* support at all, until a real implementation is built for that design system.
|
|
88
|
+
*/
|
|
89
|
+
export declare class NoopAuthAdapter implements AuthAdapter {
|
|
90
|
+
promptCredentials(): CredentialPromptHandle;
|
|
91
|
+
}
|
|
51
92
|
/**
|
|
52
93
|
* The integration contract between Trailhead core and a specific design system.
|
|
53
94
|
* Implement this interface to support a new component library as the shell's UI layer.
|
|
@@ -64,5 +105,11 @@ export interface DesignSystemAdapter {
|
|
|
64
105
|
init(shellUrl: string): Promise<void>;
|
|
65
106
|
/** Feedback implementation backed by this adapter's design system components. */
|
|
66
107
|
feedback: FeedbackAdapter;
|
|
108
|
+
/**
|
|
109
|
+
* Credential-prompt implementation backed by this adapter's design system components.
|
|
110
|
+
* Required so every adapter has an explicit answer — use `NoopAuthAdapter` if this design
|
|
111
|
+
* system doesn't have a real implementation yet.
|
|
112
|
+
*/
|
|
113
|
+
auth: AuthAdapter;
|
|
67
114
|
}
|
|
68
115
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2FAA2F;AAC3F,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,EAAE,CAAC,CAAC;IACT,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,6FAA6F;IAC7F,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,6DAA6D;IAC7D,SAAS,IAAI,IAAI,CAAC;IAElB,oFAAoF;IACpF,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3E,gFAAgF;IAChF,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CACjF;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAC;IAEb,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,iFAAiF;IACjF,QAAQ,EAAE,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,2FAA2F;AAC3F,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,KAAK,EAAE,CAAC,CAAC;IACT,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACrD,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,6FAA6F;IAC7F,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,6DAA6D;IAC7D,SAAS,IAAI,IAAI,CAAC;IAElB,oFAAoF;IACpF,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3E,gFAAgF;IAChF,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CACjF;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACpC,8FAA8F;IAC9F,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,sBAAsB,CAAC;CAClE;AAED;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,WAAW;IACjD,iBAAiB,IAAI,sBAAsB;CAG5C;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAC;IAEb,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,iFAAiF;IACjF,QAAQ,EAAE,eAAe,CAAC;IAE1B;;;;OAIG;IACH,IAAI,EAAE,WAAW,CAAC;CACnB"}
|
package/dist/adapters/types.js
CHANGED
|
@@ -3,4 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These interfaces define the contract between Trailhead core and design system implementations.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* `AuthAdapter` that never actually prompts — `promptCredentials` resolves `null` (cancelled)
|
|
8
|
+
* immediately. Lets an adapter satisfy the required `auth` field with zero UI work: requests
|
|
9
|
+
* that hit an expired session simply fail exactly as they would with no re-authentication
|
|
10
|
+
* support at all, until a real implementation is built for that design system.
|
|
11
|
+
*/
|
|
12
|
+
export class NoopAuthAdapter {
|
|
13
|
+
promptCredentials() {
|
|
14
|
+
return { result: Promise.resolve(null), close: () => { } };
|
|
15
|
+
}
|
|
16
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@
|
|
|
5
5
|
export { Trailhead } from './shell.js';
|
|
6
6
|
export type { ShellConfig } from './shell.js';
|
|
7
7
|
export type { NavItem, NavLink, NavSection, NavDivider, AppEntry, ShellManifest } from './types/shell-api.js';
|
|
8
|
+
export { NoopAuthAdapter } from './adapters/types.js';
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAK9G,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,3 +3,7 @@
|
|
|
3
3
|
* Core shell orchestration and services
|
|
4
4
|
*/
|
|
5
5
|
export { Trailhead } from './shell.js';
|
|
6
|
+
// Adapter contracts are otherwise type-only (see @herdingbits/trailhead-types/adapters), but
|
|
7
|
+
// NoopAuthAdapter is a real runtime value — a types-only package can't carry it, so it's
|
|
8
|
+
// exported from here instead. Adapters already depend on trailhead-core as a peer dependency.
|
|
9
|
+
export { NoopAuthAdapter } from './adapters/types.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-place session re-authentication.
|
|
3
|
+
*
|
|
4
|
+
* Lets a product recover from an expired session without a full page reload — the app calls
|
|
5
|
+
* `reauthenticate(attempt)` when a request fails due to expiry; this shows a credential prompt
|
|
6
|
+
* (via the configured `AuthAdapter`), retries `attempt` until it succeeds or the user cancels,
|
|
7
|
+
* and keeps every open browser tab in sync so re-authenticating in one tab resolves a pending
|
|
8
|
+
* prompt in every other tab too.
|
|
9
|
+
*/
|
|
10
|
+
import type { AuthAdapter } from "../adapters/types.js";
|
|
11
|
+
export interface Reauthenticator {
|
|
12
|
+
/**
|
|
13
|
+
* Prompts for credentials and calls `attempt` with them, re-prompting (with an error message)
|
|
14
|
+
* on failure, until `attempt` succeeds or the user cancels. Concurrent callers share a single
|
|
15
|
+
* in-flight prompt rather than each showing their own.
|
|
16
|
+
*
|
|
17
|
+
* @param attempt - Validates one username/password pair against the product's own login
|
|
18
|
+
* endpoint and returns whether it succeeded. `AuthAdapter` and this orchestrator never see
|
|
19
|
+
* or know about the actual authentication mechanism.
|
|
20
|
+
* @returns `true` once a session has been re-established (by this tab or another one),
|
|
21
|
+
* `false` if the user cancelled.
|
|
22
|
+
*/
|
|
23
|
+
reauthenticate(attempt: (username: string, password: string) => Promise<boolean>): Promise<boolean>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a `Reauthenticator` backed by the given adapter. Pass `NoopAuthAdapter` (or any
|
|
27
|
+
* adapter that never actually prompts) to disable re-authentication entirely — `reauthenticate`
|
|
28
|
+
* then always resolves `false`, and callers fall through to whatever they'd otherwise do when a
|
|
29
|
+
* session expires.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createReauthenticator(adapter: AuthAdapter): Reauthenticator;
|
|
32
|
+
//# sourceMappingURL=reauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reauth.d.ts","sourceRoot":"","sources":["../../src/lib/reauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIxD,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;OAUG;IACH,cAAc,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrG;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,eAAe,CAqD3E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const CHANNEL_NAME = "trailhead-reauth";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a `Reauthenticator` backed by the given adapter. Pass `NoopAuthAdapter` (or any
|
|
4
|
+
* adapter that never actually prompts) to disable re-authentication entirely — `reauthenticate`
|
|
5
|
+
* then always resolves `false`, and callers fall through to whatever they'd otherwise do when a
|
|
6
|
+
* session expires.
|
|
7
|
+
*/
|
|
8
|
+
export function createReauthenticator(adapter) {
|
|
9
|
+
let inFlight = null;
|
|
10
|
+
const channel = typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(CHANNEL_NAME) : null;
|
|
11
|
+
function reauthenticate(attempt) {
|
|
12
|
+
if (inFlight)
|
|
13
|
+
return inFlight;
|
|
14
|
+
inFlight = run(attempt).finally(() => {
|
|
15
|
+
inFlight = null;
|
|
16
|
+
});
|
|
17
|
+
return inFlight;
|
|
18
|
+
}
|
|
19
|
+
async function run(attempt) {
|
|
20
|
+
let errorMessage;
|
|
21
|
+
while (true) {
|
|
22
|
+
const prompt = adapter.promptCredentials(errorMessage);
|
|
23
|
+
let onMessage = null;
|
|
24
|
+
const otherTabSucceeded = new Promise((resolve) => {
|
|
25
|
+
if (!channel)
|
|
26
|
+
return; // no BroadcastChannel support — never resolves, harmless
|
|
27
|
+
onMessage = (e) => {
|
|
28
|
+
if (e.data === "success")
|
|
29
|
+
resolve(true);
|
|
30
|
+
};
|
|
31
|
+
channel.addEventListener("message", onMessage);
|
|
32
|
+
});
|
|
33
|
+
const outcome = await Promise.race([
|
|
34
|
+
prompt.result.then((credentials) => ({ kind: "prompt", credentials })),
|
|
35
|
+
otherTabSucceeded.then(() => ({ kind: "other-tab", credentials: null })),
|
|
36
|
+
]);
|
|
37
|
+
if (onMessage && channel)
|
|
38
|
+
channel.removeEventListener("message", onMessage);
|
|
39
|
+
if (outcome.kind === "other-tab") {
|
|
40
|
+
prompt.close();
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (outcome.credentials === null) {
|
|
44
|
+
return false; // user cancelled
|
|
45
|
+
}
|
|
46
|
+
const ok = await attempt(outcome.credentials.username, outcome.credentials.password);
|
|
47
|
+
if (ok) {
|
|
48
|
+
channel?.postMessage("success");
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
errorMessage = "Incorrect username or password.";
|
|
52
|
+
// loop — re-prompt with the error
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return { reauthenticate };
|
|
56
|
+
}
|
package/dist/shell.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export declare class Trailhead {
|
|
|
37
37
|
private readonly shellUrl;
|
|
38
38
|
/** The active design system adapter supplying UI components to the shell. */
|
|
39
39
|
readonly adapter: DesignSystemAdapter;
|
|
40
|
+
/** Backs `window.shell.auth.reauthenticate` — built from `adapter.auth`. */
|
|
41
|
+
private readonly reauthenticator;
|
|
40
42
|
/**
|
|
41
43
|
* Creates the shell and immediately begins async initialisation (adapter setup,
|
|
42
44
|
* navigation load, initial route handling). Mount errors are logged to the console.
|
package/dist/shell.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAY,OAAO,EAAW,QAAQ,EAAiB,MAAM,sBAAsB,CAAC;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAY,OAAO,EAAW,QAAQ,EAAiB,MAAM,sBAAsB,CAAC;AAChG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAK/D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,0FAA0F;IAC1F,OAAO,EAAE,mBAAmB,CAAC;IAE7B,wKAAwK;IACxK,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,qHAAqH;IACrH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,oBAAoB,CAAqC;IAEjE,oFAAoF;IACpF,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC,6EAA6E;IAC7E,SAAgB,OAAO,EAAE,mBAAmB,CAAC;IAE7C,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAElD;;;;;OAKG;gBACS,MAAM,EAAE,WAAW;IAQ/B;;;OAGG;IACI,aAAa,IAAI,OAAO,EAAE;IAIjC;;;OAGG;IACI,OAAO,IAAI,QAAQ,EAAE;IAI5B;;OAEG;YACW,IAAI;IAwBlB;;OAEG;YACW,WAAW;IAUzB;;OAEG;IACH,OAAO,CAAC,SAAS;IAoFjB;;OAEG;YACW,cAAc;IAa5B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAkDxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;OAEG;IACH,OAAO,CAAC,WAAW;IAsBnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;YACW,UAAU;CAqDzB"}
|
package/dist/shell.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as http from "./lib/http.js";
|
|
2
2
|
import * as requestManager from "./lib/requestManager.js";
|
|
3
|
+
import { createReauthenticator } from "./lib/reauth.js";
|
|
3
4
|
/**
|
|
4
5
|
* The Trailhead shell. Bootstraps the micro-frontend host by loading navigation config,
|
|
5
6
|
* mounting SPAs on route activation, and exposing `window.shell` to every hosted application.
|
|
@@ -26,6 +27,7 @@ export class Trailhead {
|
|
|
26
27
|
this.appBasePath = config.appBasePath || "";
|
|
27
28
|
this.shellUrl = config.shellUrl || this.appBasePath;
|
|
28
29
|
this.adapter = config.adapter;
|
|
30
|
+
this.reauthenticator = createReauthenticator(this.adapter.auth);
|
|
29
31
|
this.init(config.apiUrl);
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
@@ -150,6 +152,9 @@ export class Trailhead {
|
|
|
150
152
|
};
|
|
151
153
|
},
|
|
152
154
|
},
|
|
155
|
+
auth: {
|
|
156
|
+
reauthenticate: (attempt) => this.reauthenticator.reauthenticate(attempt),
|
|
157
|
+
},
|
|
153
158
|
};
|
|
154
159
|
}
|
|
155
160
|
/**
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Public Shell API - Only these types are exposed to plugin applications
|
|
3
3
|
* This file explicitly defines what's public vs internal
|
|
4
4
|
*/
|
|
5
|
-
export type { ShellAPI, ShellPlugin, FeedbackAPI, AlertVariant, HttpAPI, RequestOptions, Result, SuccessResult, ErrorResult, HttpError, NavigationAPI, NavItem, NavLink, NavSection, NavDivider, AppEntry, ShellManifest, } from "./shell-api.js";
|
|
5
|
+
export type { ShellAPI, ShellPlugin, FeedbackAPI, AlertVariant, HttpAPI, RequestOptions, Result, SuccessResult, ErrorResult, HttpError, NavigationAPI, NavItem, NavLink, NavSection, NavDivider, AppEntry, ShellManifest, AuthAPI, } from "./shell-api.js";
|
|
6
6
|
//# sourceMappingURL=public-api.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../src/types/public-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,EACZ,OAAO,EACP,cAAc,EACd,MAAM,EACN,aAAa,EACb,WAAW,EACX,SAAS,EACT,aAAa,EACb,OAAO,EACP,OAAO,EACP,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../src/types/public-api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,EACZ,OAAO,EACP,cAAc,EACd,MAAM,EACN,aAAa,EACb,WAAW,EACX,SAAS,EACT,aAAa,EACb,OAAO,EACP,OAAO,EACP,UAAU,EACV,UAAU,EACV,QAAQ,EACR,aAAa,EACb,OAAO,GACR,MAAM,gBAAgB,CAAC"}
|
|
@@ -21,6 +21,37 @@ export interface ShellAPI {
|
|
|
21
21
|
http: HttpAPI;
|
|
22
22
|
/** Navigation and routing utilities */
|
|
23
23
|
navigation: NavigationAPI;
|
|
24
|
+
/** In-place session re-authentication — see `AuthAPI`. */
|
|
25
|
+
auth: AuthAPI;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* In-place session re-authentication API.
|
|
29
|
+
*
|
|
30
|
+
* Lets an app recover from an expired session without a full page reload: show a credential
|
|
31
|
+
* prompt over whatever the user was doing, retry the failed action once they're signed back in.
|
|
32
|
+
* Always present — backed by `NoopAuthAdapter` (always resolves as cancelled) on adapters that
|
|
33
|
+
* don't have a real implementation yet, so calling this is always safe.
|
|
34
|
+
*/
|
|
35
|
+
export interface AuthAPI {
|
|
36
|
+
/**
|
|
37
|
+
* Prompts for credentials and calls `attempt` with them, re-prompting on failure until it
|
|
38
|
+
* succeeds or the user cancels. Concurrent calls share a single prompt, and a successful
|
|
39
|
+
* re-authentication in one browser tab resolves a pending prompt in every other open tab too.
|
|
40
|
+
*
|
|
41
|
+
* @param attempt - Validates one username/password pair against the app's own login endpoint
|
|
42
|
+
* and returns whether it succeeded. The shell never sees the credentials otherwise, and has
|
|
43
|
+
* no opinion on the authentication mechanism.
|
|
44
|
+
* @returns `true` once a session has been re-established, `false` if the user cancelled.
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const ok = await shell.auth.reauthenticate(async (username, password) => {
|
|
48
|
+
* const res = await fetch('/api/login', { method: 'POST', body: JSON.stringify({ username, password }) });
|
|
49
|
+
* return res.ok;
|
|
50
|
+
* });
|
|
51
|
+
* if (ok) retryOriginalRequest();
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
reauthenticate(attempt: (username: string, password: string) => Promise<boolean>): Promise<boolean>;
|
|
24
55
|
}
|
|
25
56
|
/**
|
|
26
57
|
* Contract implemented by applications that can be hosted by the Shell.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell-api.d.ts","sourceRoot":"","sources":["../../src/types/shell-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,QAAQ;IACvB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAEhB,mEAAmE;IACnE,QAAQ,EAAE,WAAW,CAAC;IAEtB,uEAAuE;IACvE,IAAI,EAAE,OAAO,CAAC;IAEd,uCAAuC;IACvC,UAAU,EAAE,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"shell-api.d.ts","sourceRoot":"","sources":["../../src/types/shell-api.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herdingbits/trailhead-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Simple application shell that orchestrates multiple SPAs. No webpack magic, just the browser's native module system.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"typescript": "^6.0.3",
|
|
29
|
-
"vitest": "^4.1.
|
|
29
|
+
"vitest": "^4.1.9"
|
|
30
30
|
},
|
|
31
31
|
"keywords": [
|
|
32
32
|
"micro-frontend",
|