feat: add api wrapper

This commit is contained in:
Paul Pan 2023-07-16 19:34:00 +08:00
parent e964fc8fff
commit a4b0d0308c
6 changed files with 260 additions and 0 deletions

3
src/api/api.ts Normal file
View File

@ -0,0 +1,3 @@
export { send } from "./base";
export { UserApi } from "./user.ts";

35
src/api/base.ts Normal file
View File

@ -0,0 +1,35 @@
import axios from "axios";
axios.defaults.baseURL =
process.env.NODE_ENV === "production"
? "/api/v1"
: "http://127.0.0.1:8000/api/v1";
export interface ResponseWrap<T> {
code: number;
msg: string;
body: T;
}
export interface Meta {
ID: number;
CreatedAt: number;
UpdatedAt: number;
DeletedAt: number;
}
export async function send<D, T>(
api: string,
data?: D,
token?: string,
): Promise<T> {
try {
const resp = await axios.post<ResponseWrap<T>>(api, data, {
headers: { token: token },
});
if (resp.data.code !== 0) return Promise.reject(resp.data.msg);
return resp.data.body;
} catch (err) {
return Promise.reject(err);
}
}

72
src/api/problem.ts Normal file
View File

@ -0,0 +1,72 @@
import { Meta, send } from "./base.ts";
import { UserProfile } from "./user.ts";
export interface TaskInfo {
Languages: { Lang: string }[];
Runtime: {
MemoryLimit: number;
NProcLimit: number;
TimeLimit: number;
};
Tasks: { Id: number; Points: number }[];
}
export interface ProblemInfo {
meta: Meta;
title: string;
statement: string;
provider: UserProfile;
is_enabled: boolean;
}
export interface CreateVersionReq {
pid: number;
storage_key: string;
}
export interface DetailsReq {
pid: number;
}
export interface DetailsResp {
context: TaskInfo;
problem: ProblemInfo;
}
export interface SearchReq {
search: string;
}
export interface UpdateReq {
pid: number;
title: string;
statement: string;
is_enabled: boolean;
}
export interface UploadResp {
key: string;
url: string;
}
export class ProblemApi {
async CreateVersion(data: CreateVersionReq, token: string): Promise<void> {
return send("/problem/create_version", data, token);
}
async Details(data: DetailsReq): Promise<DetailsResp> {
return send("/problem/details", data);
}
async Search(data: SearchReq): Promise<ProblemInfo[]> {
return send("/problem/search", data);
}
async Update(data: UpdateReq, token: string): Promise<ProblemInfo> {
return send("/problem/update", data, token);
}
async Upload(token: string): Promise<UploadResp> {
return send("/problem/upload", null, token);
}
}

61
src/api/status.ts Normal file
View File

@ -0,0 +1,61 @@
import { Meta, send } from "./base.ts";
import { SubmissionInfo } from "./submission.ts";
export enum Verdict {
Accepted,
WrongAnswer,
JuryFailed,
PartialCorrect,
TimeLimitExceeded,
MemoryLimitExceeded,
RuntimeError,
CompileError,
SystemError,
}
export interface TaskResultInfo {
id: number;
points: number;
real_time: number;
cpu_time: number;
memory: number;
verdict: Verdict;
message: string;
}
export interface ContextInfo {
message: string;
tasks: TaskResultInfo[];
}
export interface QueryReq {
sid: number;
}
export interface QueryByVersionReq {
pvid: number;
offset?: number;
limit: number;
}
export interface QueryResp {
meta: Meta;
submission: SubmissionInfo;
problem_version_id: number;
context: ContextInfo;
point: number;
is_enabled: boolean;
}
export class StatusApi {
async Query(data: QueryReq): Promise<QueryResp> {
return send("/status/query", data);
}
async QueryByVersion(
data: QueryByVersionReq,
token: string,
): Promise<QueryResp[]> {
return send("/status/problem_version", data, token);
}
}

49
src/api/submission.ts Normal file
View File

@ -0,0 +1,49 @@
import { Meta, send } from "./base.ts";
import { UserProfile } from "./user.ts";
export interface SubmissionInfo {
meta: Meta;
problem_id: number;
user: UserProfile;
language: string;
code: string;
}
export interface SubmitReq {
pid: number;
language: string;
code: string;
}
export interface QueryReq {
pid?: number;
uid?: number;
offset?: number;
limit: number;
}
export interface QueryResp {
submission: SubmissionInfo;
point: number;
}
export interface ReJudgeReq {
sid: number;
}
export class SubmissionApi {
async Create(data: SubmitReq, token: string): Promise<void> {
return send("/submission/create", data, token);
}
async Query(data: QueryReq, token: string): Promise<QueryResp[]> {
if (!data.pid && !data.uid) {
throw new Error("Missing required fields");
}
return send("/submission/query", data, token);
}
async ReJudge(data: ReJudgeReq, token: string): Promise<void> {
return send("/submission/rejudge", data, token);
}
}

40
src/api/user.ts Normal file
View File

@ -0,0 +1,40 @@
import { Meta, send } from "./base.ts";
export interface UserReq {
username?: string;
password?: string;
nickname?: string;
uid?: number;
}
export interface UserProfile {
meta: Meta;
user_name: string;
nick_name: string;
role: number;
is_enabled: boolean;
}
export class UserApi {
async Create(data: UserReq): Promise<string> {
if (!data.username || !data.password || !data.nickname) {
throw new Error("Missing required fields");
}
return send("/user/create", data);
}
async Login(data: UserReq): Promise<string> {
if (!data.username || !data.password) {
throw new Error("Missing required fields");
}
return send("/user/login", data);
}
async Logout(token: string): Promise<void> {
return send("/user/logout", null, token);
}
async Profile(data: UserReq, token: string): Promise<UserProfile> {
return send("/user/profile", data, token);
}
}