feat: compose executable frontend runtime
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import {
|
||||
createDemoSessionAdapter,
|
||||
createExternalAuthSessionAdapter,
|
||||
createUnavailableSessionAdapter,
|
||||
} from "../adapters/auth/external-session-adapter.js";
|
||||
import { createHttpClient } from "../adapters/http/client.js";
|
||||
import {
|
||||
createQueryCacheAdapter,
|
||||
createQueryClient,
|
||||
} from "../adapters/query-cache/tanstack-query-cache.js";
|
||||
import { createBrowserStorageAdapter } from "../adapters/storage/browser-storage-adapter.js";
|
||||
import { createTelemetryAdapter } from "../adapters/telemetry/best-effort-telemetry.js";
|
||||
|
||||
/**
|
||||
* @param {Record<string, unknown>} host
|
||||
* @returns {Parameters<typeof createExternalAuthSessionAdapter>[0] | null}
|
||||
*/
|
||||
function externalOwnerFrom(host) {
|
||||
const candidate = host.__CA_FRONTEND_AUTH_OWNER__;
|
||||
if (!candidate || typeof candidate !== "object") return null;
|
||||
const owner = /** @type {Record<string, unknown>} */ (candidate);
|
||||
const required = [
|
||||
"readState",
|
||||
"subscribe",
|
||||
"beginSignIn",
|
||||
"signOut",
|
||||
"attachCredential",
|
||||
"recoverSession",
|
||||
"notifyUnauthenticated",
|
||||
];
|
||||
return required.every((name) => typeof owner[name] === "function")
|
||||
? /** @type {Parameters<typeof createExternalAuthSessionAdapter>[0]} */ (
|
||||
candidate
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
/** @param {unknown} value */
|
||||
function storageOrUndefined(value) {
|
||||
return typeof Storage !== "undefined" && value instanceof Storage
|
||||
? value
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* runtime: Awaited<ReturnType<typeof import("./load-runtime-config.js").loadRuntimeConfig>>,
|
||||
* release: Awaited<ReturnType<typeof import("./load-release-manifest.js").loadReleaseManifest>>,
|
||||
* host?: Record<string, unknown>,
|
||||
* fetcher?: typeof fetch
|
||||
* }} context
|
||||
*/
|
||||
export async function createRuntimeAdapters(context) {
|
||||
const host = context.host ?? /** @type {Record<string, unknown>} */ (globalThis);
|
||||
const config = context.runtime.config;
|
||||
const externalOwner = externalOwnerFrom(host);
|
||||
const authSession =
|
||||
config.AUTH_MODE === "demo"
|
||||
? createDemoSessionAdapter()
|
||||
: externalOwner
|
||||
? createExternalAuthSessionAdapter(externalOwner)
|
||||
: createUnavailableSessionAdapter();
|
||||
const queryClient = createQueryClient();
|
||||
const cache = createQueryCacheAdapter(queryClient);
|
||||
const storage = createBrowserStorageAdapter({
|
||||
localStorage: storageOrUndefined(host.localStorage),
|
||||
sessionStorage: storageOrUndefined(host.sessionStorage),
|
||||
});
|
||||
const telemetry = createTelemetryAdapter({
|
||||
enabled: config.TELEMETRY_ENABLED,
|
||||
endpoint: config.TELEMETRY_ENDPOINT,
|
||||
fetcher: context.fetcher,
|
||||
});
|
||||
const http = createHttpClient({
|
||||
baseUrl: config.API_BASE_URL,
|
||||
authSession,
|
||||
fetcher: context.fetcher,
|
||||
});
|
||||
const releaseInfo = Object.freeze({
|
||||
async getCurrent() {
|
||||
return structuredClone(context.release);
|
||||
},
|
||||
});
|
||||
|
||||
return Object.freeze({
|
||||
authSession,
|
||||
cache,
|
||||
http,
|
||||
queryClient,
|
||||
releaseInfo,
|
||||
storage,
|
||||
telemetry,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user