jeffboudier's picture
jeffboudier HF Staff
Launch private community demo applications with HF sign-in and admin review
002876e verified
Raw History Blame Contribute Delete
2.29 kB
export type FormData = {title: string; email: string; space_url: string; pitch: string; uses_buckets: boolean; bucket_details: string; setup_notes: string; expectations_confirmed: boolean; team_confirmed: boolean};
export type Space = {id: string; url: string; title: string; runtime: string; warning?: string | null};
export type Application = FormData & {id: string; username: string; revision: number; state: 'draft'|'submitted'|'withdrawn'; created_at: string; submitted_at?: string; updated_at: string; confirmed: boolean; decision?: string | null; decision_message?: string; space?: Space};
export type ReviewApplication = Application & {review_decision: string; review_notes: string; review_message: string; published_decision?: string; published_message?: string; audit: {at:string; actor:string; action:string}[]};
export type User = {username: string; name: string; email: string; is_reviewer: boolean};
export type Config = {deadline: string; applications_open: boolean; max_demos: number; event_url: string; base_url: string};
export class ApiError extends Error {
constructor(message:string, public code:string, public fields:Record<string,string> = {}, public status:number = 0) {super(message);}
}
export async function api<T>(path:string, options:RequestInit = {}, csrf?:string):Promise<T> {
let response:Response;
try { response = await fetch(path, {credentials: 'same-origin', ...options, headers: {'Content-Type':'application/json', ...(csrf ? {'X-CSRF-Token':csrf} : {}), ...options.headers}}); }
catch {throw new ApiError('Could not connect. Your current form is still here; please try again.', 'network_error');}
const data = await response.json().catch(() => ({}));
if (!response.ok) throw new ApiError(data.error?.message || 'The service is temporarily unavailable. Please try again.', data.error?.code || 'request_failed', data.error?.fields || {}, response.status);
return data;
}
export const blankForm:FormData = {title:'',email:'',space_url:'',pitch:'',uses_buckets:false,bucket_details:'',setup_notes:'',expectations_confirmed:false,team_confirmed:false};
export function formFrom(app:Application):FormData {return Object.fromEntries(Object.keys(blankForm).map(k => [k, app[k as keyof FormData] ?? blankForm[k as keyof FormData]])) as FormData;}