aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/mirumd/web/api/client.ts')
-rw-r--r--cmd/mirumd/web/api/client.ts34+34 −0
1 files changed, 34 insertions, 0 deletions
diff --git a/cmd/mirumd/web/api/client.ts b/cmd/mirumd/web/api/client.ts
new file mode 100644
--- /dev/null
+++ b/cmd/mirumd/web/api/client.ts
@@ -0,0 +1,34 @@
+// Copyright (c) 2026 Nikolay Govorov
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+import { createClient, type Interceptor } from "@connectrpc/connect"
+import { createConnectTransport } from "@connectrpc/connect-web"
+import { Admin, ErrorReason } from "@/gen/admin_pb"
+import { errorReason } from "@/lib/errors"
+
+const csrfInterceptor = (csrfToken: string): Interceptor =>
+ (next) => async (req) => {
+ req.header.set("X-CSRF-Token", csrfToken)
+ return next(req)
+ }
+
+// authInterceptor redirects to /auth/login on Unauthenticated so individual
+// callers don't need to handle session expiry explicitly.
+const authInterceptor: Interceptor = (next) => async (req) => {
+ try {
+ return await next(req)
+ } catch (err) {
+ if (errorReason(err) === ErrorReason.UNAUTHENTICATED) {
+ window.location.assign("/auth/login")
+ }
+ throw err
+ }
+}
+
+export function createAdminClient(csrfToken: string) {
+ const transport = createConnectTransport({
+ baseUrl: "/api/v1",
+ interceptors: [csrfInterceptor(csrfToken), authInterceptor],
+ })
+ return createClient(Admin, transport)
+}