"use strict";
(() => {
// src/popup/view.ts
function renderLoggedOut(root, error) {
root.innerHTML = `
\u767B\u5F55\u540E\u624D\u80FD\u4F7F\u7528\u661F\u56FE\u589E\u5F3A\u529F\u80FD ${error} \u5DF2\u767B\u5F55 ${userInfo?.name ?? userInfo?.username ?? "\u672A\u77E5\u7528\u6237"} ${userInfo?.email ?? ""}Star Chart Search Enhancer
Star Chart Search Enhancer
resource: ${authState.resource ?? ""}
scopes: ${(authState.scopes ?? []).join(", ")}
token: ${authState.tokenAvailable ? "available" : "missing"}
expires: ${authState.accessTokenExpiresAt ?? "unknown"}
error: ${authState.lastError ?? ""}
`; root.appendChild(panel); } function setProtectedApiResult(root, value) { const output = root.querySelector( '[data-popup-protected-api-result="output"]' ); if (!output) { return; } output.textContent = value; } // src/shared/auth-config.ts var defaultAuthConfig = { apiResource: "https://talent-search.intelligrow.cn", appId: "i4jkllbvih0554r4n0fd3", enableDevAuthPanel: false, logtoEndpoint: "https://login-api.intelligrow.cn", scopes: ["openid", "profile", "offline_access", "talent-search:read"] }; function readAuthConfig(overrides = {}) { const nextConfig = { ...defaultAuthConfig, ...overrides }; if (!nextConfig.logtoEndpoint.trim()) { throw new Error("auth config logtoEndpoint is required"); } if (!nextConfig.appId.trim()) { throw new Error("auth config appId is required"); } if (!nextConfig.apiResource.trim()) { throw new Error("auth config apiResource is required"); } return nextConfig; } // src/shared/auth-messages.ts function isAuthResponseMessage(value) { if (!value || typeof value !== "object") { return false; } const candidate = value; if (candidate.ok === false) { return candidate.type === "auth:error" && typeof candidate.error === "string"; } if (candidate.ok !== true || typeof candidate.type !== "string") { return false; } if (candidate.type === "auth:ack") { return true; } if (candidate.type === "auth:token") { return Boolean( candidate.value && typeof candidate.value === "object" && typeof candidate.value.accessToken === "string" ); } if (candidate.type === "auth:state") { return Boolean( candidate.value && typeof candidate.value === "object" && typeof candidate.value.isAuthenticated === "boolean" ); } return false; } // src/shared/protected-api-client.ts function createProtectedApiClient(options) { const fetchImpl = options.fetchImpl ?? fetch; return { async loadProtectedMockData() { const token = await readAccessToken(options.sendMessage); const response = await fetchImpl( new URL("/api/mock/protected", options.baseUrl).toString(), { headers: { Authorization: `Bearer ${token}` }, method: "GET" } ); if (response.status === 401 || response.status === 403) { throw new Error("protected api unauthorized"); } if (!response.ok) { throw new Error(`protected api request failed: ${response.status}`); } return response.json(); } }; } async function readAccessToken(sendMessage) { const response = await sendMessage({ type: "auth:get-access-token" }); if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:token" || !response.value.accessToken.trim()) { throw new Error("protected api token unavailable"); } return response.value.accessToken; } // src/popup/index.ts async function bootPopup(options = {}) { const currentDocument = options.document ?? document; const popupConfig = readAuthConfig(options.config); const root = currentDocument.querySelector("#app"); const HTMLElementCtor = currentDocument.defaultView?.HTMLElement; if (!root || HTMLElementCtor && !(root instanceof HTMLElementCtor)) { throw new Error("popup root #app is required"); } const sendMessage = options.sendMessage ?? ((message) => Promise.resolve( globalThis.chrome?.runtime?.sendMessage?.(message) )); const fetchProtectedApi = options.fetchProtectedApi ?? createProtectedApiClient({ baseUrl: "http://127.0.0.1:4319", sendMessage }).loadProtectedMockData; await renderCurrentAuthState(root, popupConfig, sendMessage, fetchProtectedApi); } async function renderCurrentAuthState(root, popupConfig, sendMessage, fetchProtectedApi) { const response = await sendMessage({ type: "auth:get-state" }); if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:state") { renderLoggedOut(root, "\u8BA4\u8BC1\u72B6\u6001\u8BFB\u53D6\u5931\u8D25"); return; } if (!response.value.isAuthenticated) { renderLoggedOut(root, response.value.lastError); root.querySelector('[data-popup-sign-in="button"]')?.addEventListener("click", () => { void runAuthAction(root, popupConfig, sendMessage, { actionMessage: { type: "auth:sign-in" }, fetchProtectedApi }); }); return; } renderLoggedIn(root, response.value); root.querySelector('[data-popup-sign-out="button"]')?.addEventListener("click", () => { void runAuthAction(root, popupConfig, sendMessage, { actionMessage: { type: "auth:sign-out" }, fetchProtectedApi }); }); if (popupConfig.enableDevAuthPanel) { renderDevPanel(root, response.value); root.querySelector('[data-popup-test-protected-api="button"]')?.addEventListener("click", () => { void runProtectedApiProbe(root, fetchProtectedApi); }); } } async function runAuthAction(root, popupConfig, sendMessage, options) { const response = await sendMessage(options.actionMessage); if (isActionError(response)) { renderLoggedOut(root, response.error); root.querySelector('[data-popup-sign-in="button"]')?.addEventListener("click", () => { void runAuthAction(root, popupConfig, sendMessage, options); }); return; } await renderCurrentAuthState( root, popupConfig, sendMessage, options.fetchProtectedApi ); } function isActionError(response) { return isAuthResponseMessage(response) && !response.ok && response.type === "auth:error"; } async function runProtectedApiProbe(root, fetchProtectedApi) { setProtectedApiResult(root, "\u8BF7\u6C42\u4E2D..."); try { const result = await fetchProtectedApi(); setProtectedApiResult(root, JSON.stringify(result, null, 2)); } catch (error) { setProtectedApiResult( root, error instanceof Error ? error.message : String(error) ); } } if (typeof document !== "undefined") { void bootPopup(); } })();