mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-21 00:21:27 +00:00
- Fix display label `image:` → `name:` for SnapshotPulling/SnapshotPulled in format_event_detail - Fix grammar: "an Sandbox" → "a Sandbox" in README and parallel.rs - Fix typo: "sandboxs" → "sandboxes" in parallel.rs - Update remaining "execution environment" comments to "sandbox" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
import { importPKCS8, SignJWT } from "jose";
|
|
|
|
const ARC_API_BASE_URL = process.env.ARC_API_BASE_URL;
|
|
const ARC_JWT_PRIVATE_KEY = process.env.ARC_JWT_PRIVATE_KEY;
|
|
|
|
let cachedKey: CryptoKey | null = null;
|
|
|
|
async function getSigningKey(): Promise<CryptoKey> {
|
|
if (cachedKey) return cachedKey;
|
|
if (!ARC_JWT_PRIVATE_KEY) {
|
|
throw new Error("ARC_JWT_PRIVATE_KEY environment variable is not set");
|
|
}
|
|
cachedKey = await importPKCS8(ARC_JWT_PRIVATE_KEY, "EdDSA");
|
|
return cachedKey;
|
|
}
|
|
|
|
async function signToken(): Promise<string> {
|
|
const key = await getSigningKey();
|
|
return new SignJWT({ iss: "arc-web" })
|
|
.setProtectedHeader({ alg: "EdDSA" })
|
|
.setIssuedAt()
|
|
.setExpirationTime("30s")
|
|
.sign(key);
|
|
}
|
|
|
|
/**
|
|
* Fetch wrapper that signs requests with a JWT for service-to-service auth.
|
|
*/
|
|
export async function apiFetch(
|
|
path: string,
|
|
init?: RequestInit
|
|
): Promise<Response> {
|
|
if (!ARC_API_BASE_URL) {
|
|
throw new Error("ARC_API_BASE_URL environment variable is not set");
|
|
}
|
|
|
|
const headers = new Headers(init?.headers);
|
|
if (ARC_JWT_PRIVATE_KEY) {
|
|
const token = await signToken();
|
|
headers.set("Authorization", `Bearer ${token}`);
|
|
}
|
|
|
|
return fetch(`${ARC_API_BASE_URL}${path}`, {
|
|
...init,
|
|
headers,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Typed JSON fetch helper. Calls apiFetch and parses the JSON response.
|
|
*/
|
|
export async function apiJson<T>(path: string, init?: RequestInit): Promise<T> {
|
|
const res = await apiFetch(path, init);
|
|
if (!res.ok) throw new Response(null, { status: res.status });
|
|
return res.json() as Promise<T>;
|
|
}
|