feat: add logto auth and backend metrics integration
This commit is contained in:
+166
-11
@@ -1,3 +1,14 @@
|
||||
import { createAuthController, type AuthController } from "./auth/controller";
|
||||
import { createLogtoAuthClient } from "./auth/client";
|
||||
import {
|
||||
isAuthRequestMessage,
|
||||
type AuthResponseMessage
|
||||
} from "../shared/auth-messages";
|
||||
import { createBatchSubmitClient } from "../shared/batch-submit-client";
|
||||
import { createBackendMetricsClient } from "../shared/backend-metrics-client";
|
||||
import { DEFAULT_BACKEND_METRICS_BASE_URL } from "../shared/backend-metrics-config";
|
||||
import { isBackendMetricsSearchRequestMessage } from "../shared/backend-metrics-messages";
|
||||
|
||||
interface ChromeDownloadsLike {
|
||||
download(
|
||||
options: {
|
||||
@@ -32,33 +43,168 @@ type DownloadMarketCsvMessage = {
|
||||
type: "download-market-csv";
|
||||
};
|
||||
|
||||
type BatchSubmitMessage = {
|
||||
payload: unknown;
|
||||
type: "batch:submit";
|
||||
};
|
||||
|
||||
export function registerBackgroundMessageHandler(
|
||||
chromeLike: ChromeLike = (
|
||||
globalThis as typeof globalThis & {
|
||||
chrome?: ChromeLike;
|
||||
}
|
||||
).chrome ?? {}
|
||||
chromeLike: ChromeLike = readChromeLike(),
|
||||
dependencies: {
|
||||
authController?: AuthController;
|
||||
searchBackendMetrics?: (starIds: string[]) => Promise<unknown>;
|
||||
submitBatch?: (payload: unknown) => Promise<unknown>;
|
||||
} = {}
|
||||
): void {
|
||||
let authController = dependencies.authController;
|
||||
let searchBackendMetrics = dependencies.searchBackendMetrics;
|
||||
let submitBatch = dependencies.submitBatch;
|
||||
|
||||
chromeLike.runtime?.onMessage?.addListener((message, _sender, sendResponse) => {
|
||||
if (!isDownloadMarketCsvMessage(message)) {
|
||||
if (isDownloadMarketCsvMessage(message)) {
|
||||
void triggerCsvDownload(chromeLike, message)
|
||||
.then(() => {
|
||||
sendResponse({ ok: true });
|
||||
})
|
||||
.catch((error) => {
|
||||
sendResponse({
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
ok: false
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isBatchSubmitMessage(message)) {
|
||||
authController ??= createAuthController({
|
||||
authClient: createLogtoAuthClient()
|
||||
});
|
||||
submitBatch ??= createBatchSubmitClient({
|
||||
baseUrl: "http://127.0.0.1:4319",
|
||||
getAccessToken: () => authController!.getAccessToken(),
|
||||
sendMessage: () =>
|
||||
Promise.reject(new Error("background batch submit does not use sendMessage"))
|
||||
}).submitBatch;
|
||||
|
||||
void submitBatch(message.payload)
|
||||
.then((value) => {
|
||||
sendResponse({
|
||||
ok: true,
|
||||
type: "batch:ack",
|
||||
value
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
sendResponse({
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
ok: false,
|
||||
type: "batch:error"
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isBackendMetricsSearchRequestMessage(message)) {
|
||||
authController ??= createAuthController({
|
||||
authClient: createLogtoAuthClient()
|
||||
});
|
||||
searchBackendMetrics ??= createBackendMetricsClient({
|
||||
baseUrl: DEFAULT_BACKEND_METRICS_BASE_URL,
|
||||
getAccessToken: () => authController!.getAccessToken()
|
||||
}).searchByStarIds;
|
||||
|
||||
void searchBackendMetrics(message.value.starIds)
|
||||
.then((rows) => {
|
||||
sendResponse({
|
||||
ok: true,
|
||||
type: "backend-metrics:result",
|
||||
value: {
|
||||
rows
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
sendResponse({
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
ok: false,
|
||||
type: "backend-metrics:error"
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isAuthRequestMessage(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
void triggerCsvDownload(chromeLike, message)
|
||||
.then(() => {
|
||||
sendResponse({ ok: true });
|
||||
authController ??= createAuthController({
|
||||
authClient: createLogtoAuthClient()
|
||||
});
|
||||
|
||||
void handleAuthMessage(authController, message)
|
||||
.then((response) => {
|
||||
sendResponse(response);
|
||||
})
|
||||
.catch((error) => {
|
||||
sendResponse({
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
ok: false
|
||||
});
|
||||
ok: false,
|
||||
type: "auth:error"
|
||||
} satisfies AuthResponseMessage);
|
||||
});
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
async function handleAuthMessage(
|
||||
authController: AuthController,
|
||||
message: Parameters<typeof isAuthRequestMessage>[0] & { type: string }
|
||||
): Promise<AuthResponseMessage> {
|
||||
if (message.type === "auth:get-state") {
|
||||
return {
|
||||
ok: true,
|
||||
type: "auth:state",
|
||||
value: await authController.getAuthState()
|
||||
};
|
||||
}
|
||||
|
||||
if (message.type === "auth:get-access-token") {
|
||||
return {
|
||||
ok: true,
|
||||
type: "auth:token",
|
||||
value: {
|
||||
accessToken: await authController.getAccessToken()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (message.type === "auth:sign-in") {
|
||||
await authController.signIn();
|
||||
return {
|
||||
ok: true,
|
||||
type: "auth:ack"
|
||||
};
|
||||
}
|
||||
|
||||
await authController.signOut();
|
||||
return {
|
||||
ok: true,
|
||||
type: "auth:ack"
|
||||
};
|
||||
}
|
||||
|
||||
function readChromeLike(): ChromeLike {
|
||||
return (
|
||||
globalThis as typeof globalThis & {
|
||||
chrome?: ChromeLike;
|
||||
}
|
||||
).chrome ?? {};
|
||||
}
|
||||
|
||||
async function triggerCsvDownload(
|
||||
chromeLike: ChromeLike,
|
||||
message: DownloadMarketCsvMessage
|
||||
@@ -92,4 +238,13 @@ function isDownloadMarketCsvMessage(
|
||||
);
|
||||
}
|
||||
|
||||
function isBatchSubmitMessage(message: unknown): message is BatchSubmitMessage {
|
||||
if (!message || typeof message !== "object") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const candidate = message as Partial<BatchSubmitMessage>;
|
||||
return candidate.type === "batch:submit" && "payload" in candidate;
|
||||
}
|
||||
|
||||
registerBackgroundMessageHandler();
|
||||
|
||||
Reference in New Issue
Block a user