Openinary Upload Signature Helper
openinary/upload-tokenFreeUtility
Server-side helper that requests a short-lived presigned upload signature from POST /upload/sign using an Openinary API key.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/openinary/openinary/main/r/upload-token.jsonSource
1/**2 * Server-side helper to mint a short-lived presigned upload signature for the3 * Openinary file uploader. Call this from your backend (route handler, server4 * action, Worker, etc.) using an Openinary API key, and hand the returned5 * signature to the browser component.6 *7 * This is a thin client for `POST /upload/sign`. Openinary itself computes8 * the HMAC signature, your backend never needs to hold `API_SECRET`, only an9 * API key (the same kind used for any other authenticated Openinary request).10 *11 * SECURITY: never call this endpoint, or expose your API key, from the12 * browser. Protect the route that calls this helper with your own auth and13 * rate limiting, and scope `folder` to the authenticated user server-side.14 */1516export interface SignUploadOptions {17 /** Destination folder the signature will be scoped to. Defaults to the root. */18 folder?: string;19 /** Signature lifetime in seconds. The server clamps this to [1, 3600]. Default 300. */20 expiresIn?: number;21}2223export interface SignedUpload {24 signature: string;25 /** Unix timestamp (seconds) after which the signature is no longer valid. */26 expires: number;27 folder: string;28}2930/**31 * Requests a presigned upload signature from your Openinary instance.32 *33 * @param baseUrl Your Openinary API URL, e.g. https://media.example.com.34 * @param apiKey An Openinary API key (Authorization: Bearer).35 */36export async function signUpload(37 baseUrl: string,38 apiKey: string,39 options: SignUploadOptions = {},40): Promise<SignedUpload> {41 const res = await fetch(`${baseUrl.replace(/\/$/, "")}/upload/sign`, {42 method: "POST",43 headers: {44 "Content-Type": "application/json",45 Authorization: `Bearer ${apiKey}`,46 },47 body: JSON.stringify(options),48 });4950 let body: any = null;51 try {52 body = await res.json();53 } catch {54 /* non-JSON response */55 }5657 if (!res.ok || !body?.success) {58 throw new Error(body?.error ?? `Failed to sign upload (HTTP ${res.status})`);59 }6061 return {62 signature: body.signature,63 expires: body.expires,64 folder: body.folder,65 };66}
