feat: complete TASK-WP2-01 project foundations

This commit is contained in:
suyx
2026-07-28 20:12:12 +08:00
parent 59e566885b
commit 4d38530361
19 changed files with 3696 additions and 12 deletions
+33 -1
View File
@@ -1,6 +1,6 @@
// Generated from openapi/openapi.json. Do not edit by hand.
import type { AccountDeletionResponse, AccountDeletionCompleteRequest, AdminLoginCompleteResponse, AdminLoginCompleteRequest, LoginCompleteResponse, LoginCompleteRequest, RegistrationCompleteResponse, RegistrationCompleteRequest, AccountSettingsResponse, AdminSessionResponse, UserSessionResponse, LogoutResponse, AccountDeletionSendResponse, RegistrationSendResponse, AdminLoginSendRequest, LoginSendRequest, RegistrationSendRequest, AccountProfileUpdateResponse, AccountProfileUpdateRequest } from "./types.gen.js";
import type { AccountDeletionResponse, AccountDeletionCompleteRequest, AdminLoginCompleteResponse, AdminLoginCompleteRequest, LoginCompleteResponse, LoginCompleteRequest, RegistrationCompleteResponse, RegistrationCompleteRequest, AccountSettingsResponse, AdminSessionResponse, ProjectDetailResponse, UserSessionResponse, ProjectListResponse, LogoutResponse, ProjectRenameResponse, ProjectRenameRequest, AccountDeletionSendResponse, RegistrationSendResponse, AdminLoginSendRequest, LoginSendRequest, RegistrationSendRequest, FailedEmptyTrashResponse, FailedEmptyTrashRequest, AccountProfileUpdateResponse, AccountProfileUpdateRequest } from "./types.gen.js";
export interface ClientOptions { baseUrl?: string; fetch?: typeof globalThis.fetch; headers?: HeadersInit; }
@@ -138,6 +138,13 @@ export function getEvents(options: Pick<ClientOptions, "baseUrl"> = {}): string
return `${options.baseUrl ?? ""}/api/v1/events`;
}
export async function getProject(options: ClientOptions = {}): Promise<ProjectDetailResponse> {
const request = options.fetch ?? globalThis.fetch;
const response = await request(`${options.baseUrl ?? ""}/api/v1/projects/{projectId}`, { method: "GET", headers: options.headers ?? {} });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json() as Promise<ProjectDetailResponse>;
}
export async function getUserSession(options: ClientOptions = {}): Promise<UserSessionResponse> {
const request = options.fetch ?? globalThis.fetch;
const response = await request(`${options.baseUrl ?? ""}/api/v1/auth/session`, { method: "GET", headers: options.headers ?? {} });
@@ -145,6 +152,13 @@ export async function getUserSession(options: ClientOptions = {}): Promise<UserS
return response.json() as Promise<UserSessionResponse>;
}
export async function listProjects(options: ClientOptions = {}): Promise<ProjectListResponse> {
const request = options.fetch ?? globalThis.fetch;
const response = await request(`${options.baseUrl ?? ""}/api/v1/projects`, { method: "GET", headers: options.headers ?? {} });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json() as Promise<ProjectListResponse>;
}
export async function logoutUser(options: ClientOptions = {}): Promise<LogoutResponse> {
const request = options.fetch ?? globalThis.fetch;
const response = await request(`${options.baseUrl ?? ""}/api/v1/auth/logout`, { method: "POST", headers: options.headers ?? {} });
@@ -152,6 +166,15 @@ export async function logoutUser(options: ClientOptions = {}): Promise<LogoutRes
return response.json() as Promise<LogoutResponse>;
}
export async function renameProject(body: ProjectRenameRequest, options: ClientOptions = {}): Promise<ProjectRenameResponse> {
const request = options.fetch ?? globalThis.fetch;
const headers = new Headers(options.headers);
headers.set("Content-Type", "application/json");
const response = await request(`${options.baseUrl ?? ""}/api/v1/projects/{projectId}`, { body: JSON.stringify(body), method: "PATCH", headers });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json() as Promise<ProjectRenameResponse>;
}
export async function sendAccountDeletionCode(options: ClientOptions = {}): Promise<AccountDeletionSendResponse> {
const request = options.fetch ?? globalThis.fetch;
const response = await request(`${options.baseUrl ?? ""}/api/v1/account/deletion/send`, { method: "POST", headers: options.headers ?? {} });
@@ -186,6 +209,15 @@ export async function sendRegistrationCode(body: RegistrationSendRequest, option
return response.json() as Promise<RegistrationSendResponse>;
}
export async function trashFailedEmptyProjects(body: FailedEmptyTrashRequest, options: ClientOptions = {}): Promise<FailedEmptyTrashResponse> {
const request = options.fetch ?? globalThis.fetch;
const headers = new Headers(options.headers);
headers.set("Content-Type", "application/json");
const response = await request(`${options.baseUrl ?? ""}/api/v1/projects/failed-empty/trash`, { body: JSON.stringify(body), method: "POST", headers });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.json() as Promise<FailedEmptyTrashResponse>;
}
export async function updateAccountProfile(body: AccountProfileUpdateRequest, options: ClientOptions = {}): Promise<AccountProfileUpdateResponse> {
const request = options.fetch ?? globalThis.fetch;
const headers = new Headers(options.headers);
+87
View File
@@ -187,8 +187,27 @@ export type ErrorEnvelope = {
};
};
export type FailedEmptyTrashRequest = {
"project_ids": Array<ProjectId>;
};
export type FailedEmptyTrashResponse = {
"ignored_project_ids": Array<ProjectId>;
"trashed_project_ids": Array<ProjectId>;
};
export type GenerationErrorCategory = "upstream_timeout" | "upstream_failed" | "safety_rejected" | "model_disabled" | "gateway_balance_insufficient" | "gateway_contract_invalid" | "reference_invalid" | "unknown_retryable" | "unknown_non_retryable";
export type GenerationProjectItem = {
"created_at": string;
"error_category": GenerationErrorCategory | null;
"generation_id": string;
"prompt": string;
"ratio": ProjectRatio;
"status": "queued" | "running" | "succeeded" | "failed" | "rejected";
"updated_at": string;
};
export type LoginCompleteRequest = {
"registration_id": string;
"verification_code": string;
@@ -231,6 +250,74 @@ export type ModelRuntimeSseEvent = {
"runtime_availability_version": number;
};
export type ProjectDetailResponse = {
"created_at": string;
"current_image_id": ProjectId | null;
"deleted_at": string | null;
"draft_prompt": string;
"generations": Array<GenerationProjectItem>;
"images": Array<ProjectImageItem>;
"name": string;
"pixel_height": number;
"pixel_width": number;
"project_id": ProjectId;
"purge_at": string | null;
"ratio": ProjectRatio;
"state_version": number;
"status": ProjectViewStatus;
"successful_image_count": number;
"updated_at": string;
};
export type ProjectId = string;
export type ProjectImageItem = {
"created_at": string;
"generation_id": string;
"image_id": ProjectId;
};
export type ProjectListQuery = {
"status"?: "active" | "trashed";
};
export type ProjectListResponse = {
"active_count": number;
"active_limit": 20;
"projects": Array<ProjectSummary>;
};
export type ProjectParams = {
"projectId": ProjectId;
};
export type ProjectRatio = "3:4" | "1:1" | "4:3" | "9:16";
export type ProjectRenameRequest = {
"name": string;
};
export type ProjectRenameResponse = {
"name": string;
"state_version": number;
"status": "renamed";
};
export type ProjectSummary = {
"current_image_id": ProjectId | null;
"deleted_at": string | null;
"name": string;
"project_id": ProjectId;
"purge_at": string | null;
"ratio": ProjectRatio;
"state_version": number;
"status": ProjectViewStatus;
"successful_image_count": number;
"updated_at": string;
};
export type ProjectViewStatus = "active" | "failed_empty" | "trashed";
export type RegistrationCompleteHeaders = {
"idempotency-key": string;
};