UNPKG

assistant-cloud

Version:

Cloud integration for assistant-ui

168 lines (167 loc) 5.72 kB
import { CloudResponseError, readCloudRecord, readCloudString } from "./cloudResponse.js"; //#region src/AssistantCloudAuthStrategy.ts const getJwtExpiry = (jwt) => { try { const bodyPart = jwt.split(".")[1]; if (!bodyPart) throw new Error("Invalid JWT format"); let base64 = bodyPart.replace(/-/g, "+").replace(/_/g, "/"); while (base64.length % 4 !== 0) base64 += "="; const payload = atob(base64); const exp = JSON.parse(payload).exp; if (!exp || typeof exp !== "number") throw new Error("JWT does not contain a valid \"exp\" field"); return exp * 1e3; } catch (error) { throw new Error(`Unable to determine the token expiry: ${error}`); } }; const readNonEmptyCloudString = (value, field) => { const result = readCloudString(value, field); if (result.length === 0) throw new CloudResponseError(`Invalid Assistant Cloud response for "${field}": expected a non-empty string`); return result; }; const readRefreshTokenResponse = (value, field) => { const refreshToken = readCloudRecord(value, field); return { token: readNonEmptyCloudString(refreshToken.token, `${field}.token`), expires_at: readNonEmptyCloudString(refreshToken.expires_at, `${field}.expires_at`) }; }; const readAuthTokenResponse = async (response, field) => { let value; try { value = await response.json(); } catch { throw new CloudResponseError(`Invalid Assistant Cloud response for "${field}": expected valid JSON`); } const data = readCloudRecord(value, field); return { data, accessToken: readNonEmptyCloudString(data.access_token, `${field}.access_token`) }; }; var AssistantCloudJWTAuthStrategy = class { strategy = "jwt"; cachedToken = null; tokenExpiry = null; tokenRequest = null; #authTokenCallback; constructor(authTokenCallback) { this.#authTokenCallback = authTokenCallback; } async getAuthHeaders() { const currentTime = Date.now(); if (this.cachedToken && this.tokenExpiry && this.tokenExpiry - currentTime > 30 * 1e3) return { Authorization: `Bearer ${this.cachedToken}` }; if (!this.tokenRequest) this.tokenRequest = this.fetchAuthHeaders(); const tokenRequest = this.tokenRequest; try { return await tokenRequest; } finally { if (this.tokenRequest === tokenRequest) this.tokenRequest = null; } } async fetchAuthHeaders() { const token = await this.#authTokenCallback(); if (!token) return false; this.cachedToken = token; this.tokenExpiry = getJwtExpiry(token); return { Authorization: `Bearer ${token}` }; } readAuthHeaders(headers) { const authHeader = headers.get("Authorization"); if (!authHeader) return; const [scheme, token] = authHeader.split(" "); if (scheme !== "Bearer" || !token) throw new Error("Invalid auth header received"); this.cachedToken = token; this.tokenExpiry = getJwtExpiry(token); } }; var AssistantCloudAPIKeyAuthStrategy = class { strategy = "api-key"; #apiKey; #userId; #workspaceId; constructor(apiKey, userId, workspaceId) { this.#apiKey = apiKey; this.#userId = userId; this.#workspaceId = workspaceId; } async getAuthHeaders() { return { Authorization: `Bearer ${this.#apiKey}`, "Aui-User-Id": this.#userId, "Aui-Workspace-Id": this.#workspaceId }; } readAuthHeaders() {} }; const AUI_REFRESH_TOKEN_NAME = "aui:refresh_token"; const getLocalStorage = () => { if (!("localStorage" in globalThis)) return null; try { return globalThis.localStorage; } catch { return null; } }; const readRefreshToken = () => { const storage = getLocalStorage(); if (!storage) return void 0; try { const value = storage.getItem(AUI_REFRESH_TOKEN_NAME); return value ? JSON.parse(value) : void 0; } catch { return; } }; const writeRefreshToken = (refreshToken) => { const storage = getLocalStorage(); if (!storage) return; try { storage.setItem(AUI_REFRESH_TOKEN_NAME, JSON.stringify(refreshToken)); } catch {} }; const removeRefreshToken = () => { const storage = getLocalStorage(); if (!storage) return; try { storage.removeItem(AUI_REFRESH_TOKEN_NAME); } catch {} }; var AssistantCloudAnonymousAuthStrategy = class { strategy = "anon"; baseUrl; jwtStrategy; constructor(baseUrl) { this.baseUrl = baseUrl; this.jwtStrategy = new AssistantCloudJWTAuthStrategy(async () => { const currentTime = Date.now(); const storedRefreshToken = readRefreshToken(); if (storedRefreshToken) if (new Date(storedRefreshToken.expires_at).getTime() - currentTime > 30 * 1e3) { const response = await fetch(`${this.baseUrl}/v1/auth/tokens/refresh`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ refresh_token: storedRefreshToken.token }) }); if (response.ok) { const { data, accessToken } = await readAuthTokenResponse(response, "refresh auth token response"); if (data.refresh_token != null) writeRefreshToken(readRefreshTokenResponse(data.refresh_token, "refresh auth token response.refresh_token")); return accessToken; } } else removeRefreshToken(); const response = await fetch(`${this.baseUrl}/v1/auth/tokens/anonymous`, { method: "POST" }); if (!response.ok) return null; const { data, accessToken } = await readAuthTokenResponse(response, "anonymous auth token response"); writeRefreshToken(readRefreshTokenResponse(data.refresh_token, "anonymous auth token response.refresh_token")); return accessToken; }); } async getAuthHeaders() { return this.jwtStrategy.getAuthHeaders(); } readAuthHeaders(headers) { this.jwtStrategy.readAuthHeaders(headers); } }; //#endregion export { AssistantCloudAPIKeyAuthStrategy, AssistantCloudAnonymousAuthStrategy, AssistantCloudJWTAuthStrategy }; //# sourceMappingURL=AssistantCloudAuthStrategy.js.map