feat: compose executable frontend runtime
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
*
|
||||
* @param {{
|
||||
* readState(): import("../../application/ports/auth-session-port.js").SessionState,
|
||||
* subscribe(listener: () => void): () => void,
|
||||
* beginSignIn(returnTo?: string): Promise<void>,
|
||||
* signOut(): Promise<void>,
|
||||
* attachCredential(request: Request): Promise<Request>,
|
||||
* recoverSession(): Promise<"restored" | "no-session">,
|
||||
* notifyUnauthenticated(): void
|
||||
@@ -15,6 +18,16 @@ export function createExternalAuthSessionAdapter(owner) {
|
||||
getState() {
|
||||
return owner.readState();
|
||||
},
|
||||
subscribe(listener) {
|
||||
return owner.subscribe(listener);
|
||||
},
|
||||
async beginSignIn(returnTo) {
|
||||
await owner.beginSignIn(returnTo);
|
||||
},
|
||||
async signOut() {
|
||||
await owner.signOut();
|
||||
},
|
||||
/** @param {Request} request */
|
||||
async attach(request) {
|
||||
const attached = await owner.attachCredential(request);
|
||||
if (!(attached instanceof Request)) {
|
||||
@@ -38,8 +51,74 @@ export function createExternalAuthSessionAdapter(owner) {
|
||||
export function createAnonymousSessionAdapter() {
|
||||
return createExternalAuthSessionAdapter({
|
||||
readState: () => "unauthenticated",
|
||||
subscribe: () => () => {},
|
||||
beginSignIn: async () => {},
|
||||
signOut: async () => {},
|
||||
attachCredential: async (request) => request,
|
||||
recoverSession: async () => "no-session",
|
||||
notifyUnauthenticated: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Local/test-only session seam. It never creates or stores credentials.
|
||||
*
|
||||
* @param {import("../../application/ports/auth-session-port.js").SessionState} [initialState]
|
||||
*/
|
||||
export function createDemoSessionAdapter(initialState = "unauthenticated") {
|
||||
let state = initialState;
|
||||
const listeners = new Set();
|
||||
|
||||
function notify() {
|
||||
for (const listener of listeners) listener();
|
||||
}
|
||||
|
||||
/** @param {import("../../application/ports/auth-session-port.js").SessionState} next */
|
||||
function setState(next) {
|
||||
state = next;
|
||||
notify();
|
||||
}
|
||||
|
||||
return Object.freeze({
|
||||
getState: () => state,
|
||||
/** @param {() => void} listener */
|
||||
subscribe(listener) {
|
||||
listeners.add(listener);
|
||||
return () => listeners.delete(listener);
|
||||
},
|
||||
async beginSignIn() {
|
||||
setState("authenticated");
|
||||
},
|
||||
async signOut() {
|
||||
setState("unauthenticated");
|
||||
},
|
||||
/** @param {Request} request */
|
||||
async attach(request) {
|
||||
return request;
|
||||
},
|
||||
async recover() {
|
||||
if (state === "recovery-pending") {
|
||||
setState("authenticated");
|
||||
return /** @type {const} */ ("restored");
|
||||
}
|
||||
return /** @type {const} */ ("no-session");
|
||||
},
|
||||
onUnauthenticated() {
|
||||
setState("unauthenticated");
|
||||
},
|
||||
setState,
|
||||
});
|
||||
}
|
||||
|
||||
export function createUnavailableSessionAdapter() {
|
||||
return Object.freeze({
|
||||
getState: () => /** @type {const} */ ("integration-failed"),
|
||||
subscribe: () => () => {},
|
||||
beginSignIn: async () => {},
|
||||
signOut: async () => {},
|
||||
/** @param {Request} request */
|
||||
attach: async (request) => request,
|
||||
recover: async () => /** @type {const} */ ("no-session"),
|
||||
onUnauthenticated: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user