1
0

feat: improve api

This commit is contained in:
2026-06-08 10:45:35 +08:00
parent c4b68400b3
commit ebe7ea5f56
7 changed files with 398 additions and 358 deletions

View File

@@ -1,75 +1,63 @@
import { apiWrapper, boolApiWrapper } from './index'
import { apiWrapper, boolApiWrapper } from './index';
// User interface
interface User {
username: string
isAdmin: boolean
// Add other user-related fields as needed
}
/** A raw admin user row as returned by the API (positional from SQL columns) */
export type AdminUserRow = [
name: string,
isAdmin: boolean,
];
/**
* Get all users (admin only)
* @param token - Authentication token
* @returns Array of users or null if operation failed
* Fetch all users (admin only).
*
* @param token - The auth token (must belong to an admin user)
* @returns An array of {@link AdminUserRow} on success, or `undefined` on failure
*/
export async function get(token: string): Promise<User[] | undefined> {
return apiWrapper('/api/admin/get', { token });
export async function get(token: string): Promise<AdminUserRow[] | undefined> {
return apiWrapper<AdminUserRow[]>('/api/admin/get', { token });
}
/**
* Add new user (admin only)
* @param token - Authentication token
* @param username - Username
* @returns Created user or null if operation failed
* Create a new user (admin only).
*
* @param token - The auth token (must belong to an admin user)
* @param username - The new username
* @returns A single {@link AdminUserRow} of the newly created user on success, or `undefined` on failure
*/
export async function add(token: string, username: string): Promise<User | undefined> {
return apiWrapper('/api/admin/add', { token, username });
export async function add(token: string, username: string): Promise<AdminUserRow | undefined> {
return apiWrapper<AdminUserRow>('/api/admin/add', { token, username });
}
/**
* Update user (admin only)
* @param token - Authentication token
* @param username - Username
* @param params - Update parameters (partial)
* @returns true if update successful, false otherwise
* Update an existing user's password and/or admin status (admin only).
*
* @param token - The auth token (must belong to an admin user)
* @param username - The target user's username
* @param password - (optional) The new password (plaintext, will be hashed server-side)
* @param isAdmin - (optional) Whether the user should be an admin
* @returns `true` on success, `false` on failure (or if no changes were provided)
*/
export async function update(
token: string,
username: string,
params: {
password?: string
isAdmin?: boolean
}
password?: string,
isAdmin?: boolean,
): Promise<boolean> {
const data: any = {
token,
username
};
const data: Record<string, any> = { token, username };
if (password !== undefined) data.password = password;
if (isAdmin !== undefined) data.isAdmin = isAdmin;
let count = 0;
if (typeof params.password !== 'undefined') {
data.password = params.password;
count++;
}
if (typeof params.isAdmin !== 'undefined') {
data.isAdmin = params.isAdmin;
count++;
}
// If no update parameters provided, return true
if (count === 0) {
return true;
}
if (Object.keys(data).length <= 2) return false;
return boolApiWrapper('/api/admin/update', data);
}
/**
* Delete user (admin only)
* @param token - Authentication token
* @param username - Username
* @returns true if deletion successful, false otherwise
* Delete a user (admin only).
*
* @param token - The auth token (must belong to an admin user)
* @param username - The username to delete
* @returns `true` on success, `false` on failure
*/
export async function deleteItem(token: string, username: string): Promise<boolean> {
export async function del(token: string, username: string): Promise<boolean> {
return boolApiWrapper('/api/admin/delete', { token, username });
}

View File

@@ -1,141 +1,172 @@
import { apiWrapper, boolApiWrapper } from './index'
import { apiWrapper, boolApiWrapper } from './index';
// Calendar event interface
interface CalendarEvent {
uuid: string
belongTo: string
title: string
description: string
eventDateTimeStart: string
eventDateTimeEnd: string
loopRules: string
timezoneOffset: number
lastChange: string
/** A raw calendar row as returned by the API (positional from SQL columns) */
export type CalendarRow = [
uuid: string,
belongTo: string,
title: string,
description: string,
lastChange: string,
eventDateTimeStart: number,
eventDateTimeEnd: number,
timezoneOffset: number,
loopRules: string,
loopDateTimeStart: number,
loopDateTimeEnd: number,
];
/** Serialized description object stored in the `description` column */
export interface CalendarDescription {
description: string;
color: string;
}
// Description object interface
interface DescriptionObject {
description: string
color: string
}
/** Default color used when deserialization fails */
const DEFAULT_COLOR = '#3388ff';
/**
* Serialize calendar description
* @param description - Description text
* @param color - Color value
* @returns JSON string
* Serialize a calendar description and color into a JSON string
* for storage in the `description` column.
*
* @param description - The description text
* @param color - The color string (e.g. `#ff0000`)
* @returns The JSON-serialized string
*/
export function serializeDescription(description: string, color: string): string {
const sobj: DescriptionObject = {
description,
color
}
return JSON.stringify(sobj)
return JSON.stringify({ description, color });
}
/**
* Deserialize calendar description
* @param str - JSON string
* @returns Description object
* Deserialize a JSON description string back into an object.
* Returns a default object on parse errors.
*
* @param str - The JSON string to deserialize
* @returns The parsed {@link CalendarDescription} object
*/
export function deserializeDescription(str: string): DescriptionObject {
export function deserializeDescription(str: string): CalendarDescription {
try {
return JSON.parse(str) as DescriptionObject
} catch (err) {
return {
description: "",
color: "#000000" // DefaultColor
}
return JSON.parse(str) as CalendarDescription;
} catch {
return { description: '', color: DEFAULT_COLOR };
}
}
/**
* Get full calendar events within date range
* @param token - Authentication token
* @param startDateTime - Start datetime
* @param endDateTime - End datetime
* @returns Array of calendar events or null if operation failed
* Fetch all calendar events within the given time range for the current user.
*
* @param token - The auth token
* @param startDateTime - Start of the time range (unix timestamp)
* @param endDateTime - End of the time range (unix timestamp)
* @returns An array of {@link CalendarRow} on success, or `undefined` on failure
*/
export async function getFull(token: string, startDateTime: string, endDateTime: string): Promise<CalendarEvent[] | undefined> {
return apiWrapper('/api/calendar/getFull', { token, startDateTime, endDateTime });
export async function getFull(token: string, startDateTime: number, endDateTime: number): Promise<CalendarRow[] | undefined> {
return apiWrapper<CalendarRow[]>('/api/calendar/getFull', {
token,
startDateTime,
endDateTime,
});
}
/**
* Get calendar event detail by UUID
* @param token - Authentication token
* @param uuid - Event UUID
* @returns Calendar event or null if operation failed
* Fetch the full detail of a single calendar event by UUID.
*
* @param token - The auth token
* @param uuid - The event UUID
* @returns A single {@link CalendarRow} on success, or `undefined` on failure
*/
export async function getDetail(token: string, uuid: string): Promise<CalendarEvent | undefined> {
return apiWrapper('/api/calendar/getDetail', { token, uuid });
export async function getDetail(token: string, uuid: string): Promise<CalendarRow | undefined> {
return apiWrapper<CalendarRow>('/api/calendar/getDetail', {
token,
uuid,
});
}
/**
* Update calendar event
* @param token - Authentication token
* @param uuid - Event UUID
* @param params - Update parameters (partial)
* @returns Updated calendar event or null if operation failed
* Update an existing calendar event. Only the fields provided will be updated.
*
* @param token - The auth token
* @param uuid - The event UUID
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @param belongTo - (optional) Collection UUID this event belongs to
* @param title - (optional) Event title
* @param description - (optional) Event description (serialized JSON)
* @param eventDateTimeStart - (optional) Start time (unix timestamp)
* @param eventDateTimeEnd - (optional) End time (unix timestamp)
* @param loopRules - (optional) Loop rules string
* @param timezoneOffset - (optional) Timezone offset in minutes
* @returns The new `lastChange` value on success, or `undefined` on failure
*/
export async function update(
token: string,
uuid: string,
params: {
belongTo?: string
title?: string
description?: string
eventDateTimeStart?: string
eventDateTimeEnd?: string
loopRules?: string
timezoneOffset?: number
lastChange: string
}
): Promise<CalendarEvent | undefined> {
const data: any = {
token,
uuid,
lastChange: params.lastChange
};
lastChange: string,
belongTo?: string,
title?: string,
description?: string,
eventDateTimeStart?: number,
eventDateTimeEnd?: number,
loopRules?: string,
timezoneOffset?: number,
): Promise<string | undefined> {
const data: Record<string, any> = { token, uuid, lastChange };
if (belongTo !== undefined) data.belongTo = belongTo;
if (title !== undefined) data.title = title;
if (description !== undefined) data.description = description;
if (eventDateTimeStart !== undefined) data.eventDateTimeStart = eventDateTimeStart;
if (eventDateTimeEnd !== undefined) data.eventDateTimeEnd = eventDateTimeEnd;
if (loopRules !== undefined) data.loopRules = loopRules;
if (timezoneOffset !== undefined) data.timezoneOffset = timezoneOffset;
if (params.belongTo !== undefined) data.belongTo = params.belongTo;
if (params.title !== undefined) data.title = params.title;
if (params.description !== undefined) data.description = params.description;
if (params.eventDateTimeStart !== undefined) data.eventDateTimeStart = params.eventDateTimeStart;
if (params.eventDateTimeEnd !== undefined) data.eventDateTimeEnd = params.eventDateTimeEnd;
if (params.loopRules !== undefined) data.loopRules = params.loopRules;
if (params.timezoneOffset !== undefined) data.timezoneOffset = params.timezoneOffset;
return apiWrapper('/api/calendar/update', data);
return apiWrapper<string>('/api/calendar/update', data);
}
/**
* Add new calendar event
* @param token - Authentication token
* @param params - Event parameters
* @returns Created calendar event or null if operation failed
* Create a new calendar event.
*
* @param token - The auth token
* @param belongTo - Collection UUID this event belongs to
* @param title - Event title
* @param description - Event description (serialized JSON)
* @param eventDateTimeStart - Start time (unix timestamp)
* @param eventDateTimeEnd - End time (unix timestamp)
* @param loopRules - Loop rules string
* @param timezoneOffset - Timezone offset in minutes
* @returns The new event UUID on success, or `undefined` on failure
*/
export async function add(
token: string,
params: {
belongTo: string
title: string
description: string
eventDateTimeStart: string
eventDateTimeEnd: string
loopRules: string
timezoneOffset: number
}
): Promise<CalendarEvent | undefined> {
return apiWrapper('/api/calendar/add', { token, ...params });
belongTo: string,
title: string,
description: string,
eventDateTimeStart: number,
eventDateTimeEnd: number,
loopRules: string,
timezoneOffset: number,
): Promise<string | undefined> {
return apiWrapper<string>('/api/calendar/add', {
token,
belongTo,
title,
description,
eventDateTimeStart,
eventDateTimeEnd,
loopRules,
timezoneOffset,
});
}
/**
* Delete calendar event
* @param token - Authentication token
* @param uuid - Event UUID
* @param lastChange - Last change timestamp
* @returns true if deletion successful, false otherwise
* Delete a calendar event.
*
* @param token - The auth token
* @param uuid - The event UUID
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns `true` on success, `false` on failure
*/
export async function deleteEvent(token: string, uuid: string, lastChange: string): Promise<boolean> {
return boolApiWrapper('/api/calendar/delete', { token, uuid, lastChange });
export async function del(token: string, uuid: string, lastChange: string): Promise<boolean> {
return boolApiWrapper('/api/calendar/delete', {
token,
uuid,
lastChange,
});
}

View File

@@ -1,126 +1,119 @@
import { apiWrapper, boolApiWrapper } from './index'
import { apiWrapper, boolApiWrapper } from './index';
type Uuid = string;
// Collection item interface
interface CollectionItem {
uuid: Uuid
name: string
lastChange: string
}
// Sharing info interface
interface SharingInfo {
target: string
// Add other sharing-related fields as needed
}
/**
* Get all owned collections
* @param token - Authentication token
* @returns Array of collection items or null if operation failed
*/
export async function getFullOwn(token: string): Promise<CollectionItem[] | undefined> {
return apiWrapper('/api/collection/getFullOwn', { token });
}
/**
* Get owned collection detail by UUID
* @param token - Authentication token
* @param uuid - Collection UUID
* @returns Collection item or null if operation failed
*/
export async function getDetailOwn(token: string, uuid: Uuid): Promise<CollectionItem | undefined> {
return apiWrapper('/api/collection/getDetailOwn', { token, uuid });
}
/**
* Add new owned collection
* @param token - Authentication token
* @param name - Collection name
* @returns Created collection item or null if operation failed
*/
export async function addOwn(token: string, name: string): Promise<Uuid | undefined> {
return apiWrapper('/api/collection/addOwn', { token, name });
}
/**
* Update owned collection
* @param token - Authentication token
* @param uuid - Collection UUID
* @param name - New name
* @param lastChange - Last change timestamp
* @returns Updated collection item or null if operation failed
*/
export async function updateOwn(
token: string,
uuid: Uuid,
/** A raw collection row as returned by the API (positional from SQL columns) */
export type CollectionRow = [
uuid: string,
name: string,
lastChange: string
): Promise<CollectionItem | undefined> {
return apiWrapper('/api/collection/updateOwn', { token, uuid, name, lastChange });
lastChange: string,
];
/** A raw shared collection row as returned by the API */
export type SharedCollectionRow = [
uuid: string,
name: string,
user: string,
];
/**
* Fetch all collections owned by the current user.
*
* @param token - The auth token
* @returns An array of {@link CollectionRow} on success, or `undefined` on failure
*/
export async function getFullOwn(token: string): Promise<CollectionRow[] | undefined> {
return apiWrapper<CollectionRow[]>('/api/collection/getFullOwn', { token });
}
/**
* Delete owned collection
* @param token - Authentication token
* @param uuid - Collection UUID
* @param lastChange - Last change timestamp
* @returns true if deletion successful, false otherwise
* Fetch the detail of a single owned collection by UUID.
*
* @param token - The auth token
* @param uuid - The collection UUID
* @returns A single {@link CollectionRow} on success, or `undefined` on failure
*/
export async function deleteOwn(token: string, uuid: Uuid, lastChange: string): Promise<boolean> {
export async function getDetailOwn(token: string, uuid: string): Promise<CollectionRow | undefined> {
return apiWrapper<CollectionRow>('/api/collection/getDetailOwn', { token, uuid });
}
/**
* Create a new collection.
*
* @param token - The auth token
* @param name - The collection name
* @returns The new collection UUID on success, or `undefined` on failure
*/
export async function addOwn(token: string, name: string): Promise<string | undefined> {
return apiWrapper<string>('/api/collection/addOwn', { token, name });
}
/**
* Update an existing collection's name.
*
* @param token - The auth token
* @param uuid - The collection UUID
* @param name - The new collection name
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns The new `lastChange` value on success, or `undefined` on failure
*/
export async function updateOwn(token: string, uuid: string, name: string, lastChange: string): Promise<string | undefined> {
return apiWrapper<string>('/api/collection/updateOwn', { token, uuid, name, lastChange });
}
/**
* Delete an owned collection.
*
* @param token - The auth token
* @param uuid - The collection UUID
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns `true` on success, `false` on failure
*/
export async function deleteOwn(token: string, uuid: string, lastChange: string): Promise<boolean> {
return boolApiWrapper('/api/collection/deleteOwn', { token, uuid, lastChange });
}
/**
* Get sharing information for a collection
* @param token - Authentication token
* @param uuid - Collection UUID
* @returns Array of sharing info or null if operation failed
* Fetch all users this collection is shared with.
*
* @param token - The auth token
* @param uuid - The collection UUID
* @returns An array of target usernames on success, or `undefined` on failure
*/
export async function getSharing(token: string, uuid: Uuid): Promise<SharingInfo[] | undefined> {
return apiWrapper('/api/collection/getSharing', { token, uuid });
export async function getSharing(token: string, uuid: string): Promise<string[] | undefined> {
return apiWrapper<string[]>('/api/collection/getSharing', { token, uuid });
}
/**
* Delete sharing for a collection
* @param token - Authentication token
* @param uuid - Collection UUID
* @param target - Target user
* @param lastChange - Last change timestamp
* @returns Result data or null if operation failed
* Remove a sharing target from a collection.
*
* @param token - The auth token
* @param uuid - The collection UUID
* @param target - The username to unshare with
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns The new `lastChange` value on success, or `undefined` on failure
*/
export async function deleteSharing(
token: string,
uuid: Uuid,
target: string,
lastChange: string
): Promise<any | undefined> {
return apiWrapper('/api/collection/deleteSharing', { token, uuid, target, lastChange });
export async function deleteSharing(token: string, uuid: string, target: string, lastChange: string): Promise<string | undefined> {
return apiWrapper<string>('/api/collection/deleteSharing', { token, uuid, target, lastChange });
}
/**
* Add sharing for a collection
* @param token - Authentication token
* @param uuid - Collection UUID
* @param target - Target user
* @param lastChange - Last change timestamp
* @returns Result data or null if operation failed
* Add a sharing target to a collection.
*
* @param token - The auth token
* @param uuid - The collection UUID
* @param target - The username to share with
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns The new `lastChange` value on success, or `undefined` on failure
*/
export async function addSharing(
token: string,
uuid: Uuid,
target: string,
lastChange: string
): Promise<any | undefined> {
return apiWrapper('/api/collection/addSharing', { token, uuid, target, lastChange });
export async function addSharing(token: string, uuid: string, target: string, lastChange: string): Promise<string | undefined> {
return apiWrapper<string>('/api/collection/addSharing', { token, uuid, target, lastChange });
}
/**
* Get all shared collections
* @param token - Authentication token
* @returns Array of collection items or null if operation failed
* Fetch all collections shared with the current user.
*
* @param token - The auth token
* @returns An array of {@link SharedCollectionRow} on success, or `undefined` on failure
*/
export async function getShared(token: string): Promise<CollectionItem[] | undefined> {
return apiWrapper('/api/collection/getShared', { token });
export async function getShared(token: string): Promise<SharedCollectionRow[] | undefined> {
return apiWrapper<SharedCollectionRow[]>('/api/collection/getShared', { token });
}

View File

@@ -1,42 +1,58 @@
import { apiWrapper, boolApiWrapper } from './index'
import { apiWrapper, boolApiWrapper } from './index';
// /**
// * Login with salt
// * @param username - Username
// * @param password - Password
// * @returns Token if login successful, undefined otherwise
// * Login via salt-challenge mechanism.
// *
// * First fetches a salt from the server, then computes the salted password hash
// * and sends it to complete login. Returns the auth token on success.
// *
// * @param username - The username
// * @param password - The plaintext password
// * @returns The auth token string on success, or `undefined` on failure
// */
// export async function login(username: string, password: string): Promise<string | undefined> {
// const salt: string | undefined = await apiWrapper('/api/common/salt', { username });
// if (typeof salt === 'undefined') return undefined;
// const salt = await apiWrapper<number>('/api/common/salt', { username });
// if (salt === undefined) return undefined;
// const computedPassword = computePasswordWithSalt(password, salt);
// return apiWrapper('/api/common/login', { username, password: computedPassword });
// const token = await apiWrapper<string>('/api/common/login', {
// username,
// password: ComputePasswordWithSalt(password, salt.toString()),
// });
// return token;
// }
/**
* Web login
* @param username - Username
* @param password - Password
* @returns Token if login successful, undefined otherwise
* Web login using password hash comparison (no salt challenge).
*
* @param username - The username
* @param password - The plaintext password
* @returns The auth token string on success, or `undefined` on failure
*/
export async function webLogin(username: string, password: string): Promise<string | undefined> {
return apiWrapper('/api/common/webLogin', { username, password });
const token = await apiWrapper<string>('/api/common/webLogin', {
username,
password,
});
return token;
}
/**
* Logout
* @param token - Authentication token
* @returns true if logout successful, false otherwise if logout failed
* Logout and invalidate the given token on the server.
*
* @param token - The auth token to invalidate
* @returns `true` on success, `false` on failure
*/
export async function logout(token: string): Promise<boolean> {
return boolApiWrapper('/api/common/logout', { token });
}
/**
* Validate token
* @param token - Authentication token
* @returns true if token is valid, false otherwise
* Check whether the given token is still valid.
*
* @param token - The auth token to validate
* @returns `true` if the token is valid, `false` otherwise
*/
export async function tokenValid(token: string): Promise<boolean> {
return boolApiWrapper('/api/common/tokenValid', { token });

View File

@@ -1,25 +1,30 @@
// Response interface
interface ApiResponse<T = any> {
success: boolean,
error: string,
data: T,
/** Response interface for all API calls */
export interface ApiResponse<T = any> {
success: boolean;
error: string;
data: T;
}
/**
* Generic API wrapper that performs a POST request with URL-encoded form data.
* Returns the `data` field on success, or `undefined` on failure.
*
* @param url - The API endpoint URL
* @param data - Key-value pairs to send as form data
* @returns The response data on success, or `undefined` on failure
*/
export async function apiWrapper<T>(url: string, data: Record<string, any>): Promise<T | undefined> {
try {
// 自动编码为 key=value&key2=value2 格式
const params = new URLSearchParams();
Object.entries(data).forEach(([key, value]) => {
params.append(key, String(value));
});
// 发起请求
const response = await fetch(url, {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
// 明确指定内容类型
'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: "follow",
@@ -27,16 +32,12 @@ export async function apiWrapper<T>(url: string, data: Record<string, any>): Pro
body: params.toString(),
});
// 检查 HTTP 状态码 (fetch 只有在网络故障时才会 rejectHTTP 404/500 不会)
if (!response.ok) {
console.error(`HTTP failed: ${response.status}`);
}
// 解析 JSON body
// 注意response.json() 返回的是一个 Promise所以需要 await
const payload = await response.json() as ApiResponse<T>;
// 检查API返回结果
if (payload.success) {
return payload.data;
} else {
@@ -44,14 +45,20 @@ export async function apiWrapper<T>(url: string, data: Record<string, any>): Pro
return undefined;
}
} catch (error) {
// 统一错误处理
console.error(`Fetch failed: ${error}`);
return undefined;
}
}
export async function boolApiWrapper<U>(url: string, data: Record<string, any>): Promise<boolean> {
/**
* Boolean API wrapper. Calls {@link apiWrapper} and returns `true` if the
* response is not `undefined`, otherwise `false`.
*
* @param url - The API endpoint URL
* @param data - Key-value pairs to send as form data
* @returns `true` on success, `false` on failure
*/
export async function boolApiWrapper(url: string, data: Record<string, any>): Promise<boolean> {
const rv = await apiWrapper<null>(url, data);
return rv !== undefined;
}

View File

@@ -1,44 +1,51 @@
import { apiWrapper, boolApiWrapper } from './index'
import { apiWrapper, boolApiWrapper } from './index';
// Token info interface
interface TokenInfo {
token: string
// Add other token-related fields as needed
}
/** A raw token row as returned by the API (positional from SQL columns) */
export type TokenRow = [
user: string,
token: string,
tokenExpireOn: number,
ua: string,
ip: string,
];
/**
* Check if current user is admin
* @param token - Authentication token
* @returns true if user is admin, false otherwise
* Check whether the current user is an admin.
*
* @param token - The auth token
* @returns `true` if the user is an admin, `false` otherwise
*/
export async function isAdmin(token: string): Promise<boolean> {
return boolApiWrapper('/api/profile/isAdmin', { token });
}
/**
* Change user password
* @param token - Authentication token
* @param password - New password
* @returns true if change successful, false otherwise
* Change the current user's password.
*
* @param token - The auth token
* @param password - The new password (plaintext, will be hashed server-side)
* @returns `true` on success, `false` on failure
*/
export async function changePassword(token: string, password: string): Promise<boolean> {
return boolApiWrapper('/api/profile/changePassword', { token, password });
}
/**
* Get user tokens
* @param token - Authentication token
* @returns Array of token info or undefined if operation failed
* Fetch all tokens associated with the current user.
*
* @param token - The auth token
* @returns An array of {@link TokenRow} on success, or `undefined` on failure
*/
export async function getToken(token: string): Promise<TokenInfo[] | undefined> {
return apiWrapper('/api/profile/getToken', { token });
export async function getToken(token: string): Promise<TokenRow[] | undefined> {
return apiWrapper<TokenRow[]>('/api/profile/getToken', { token });
}
/**
* Delete a token
* @param token - Authentication token
* @param deleteToken - Token to delete
* @returns true if deletion successful, false otherwise
* Delete a specific token belonging to the current user.
*
* @param token - The auth token
* @param deleteToken - The token string to delete
* @returns `true` on success, `false` on failure
*/
export async function deleteToken(token: string, deleteToken: string): Promise<boolean> {
return boolApiWrapper('/api/profile/deleteToken', { token, deleteToken });

View File

@@ -1,56 +1,54 @@
import axios from 'axios'
import { apiWrapper, boolApiWrapper } from './index'
import { apiWrapper, boolApiWrapper } from './index';
// Todo item interface
interface TodoItem {
uuid: string
data: any
lastChange: string
// Add other todo-related fields as needed
}
/**
* Get all todos
* @param token - Authentication token
* @returns Array of todo items or null if operation failed
*/
export async function getFull(token: string): Promise<TodoItem[] | undefined> {
return apiWrapper('/api/todo/getFull', { token });
}
/**
* Add new todo
* @param token - Authentication token
* @returns Created todo item or null if operation failed
*/
export async function add(token: string): Promise<TodoItem | undefined> {
return apiWrapper('/api/todo/add', { token });
}
/**
* Update todo
* @param token - Authentication token
* @param uuid - Todo UUID
* @param data - Todo data
* @param lastChange - Last change timestamp
* @returns Updated todo item or null if operation failed
*/
export async function update(
token: string,
/** A raw todo row as returned by the API (positional from SQL columns) */
export type TodoRow = [
uuid: string,
data: any,
lastChange: string
): Promise<TodoItem | undefined> {
return apiWrapper('/api/todo/update', { token, uuid, data, lastChange });
belongTo: string,
data: string,
lastChange: string,
];
/**
* Fetch all todo items belonging to the current user.
*
* @param token - The auth token
* @returns An array of {@link TodoRow} on success, or `undefined` on failure
*/
export async function getFull(token: string): Promise<TodoRow[] | undefined> {
return apiWrapper<TodoRow[]>('/api/todo/getFull', { token });
}
/**
* Delete todo
* @param token - Authentication token
* @param uuid - Todo UUID
* @param lastChange - Last change timestamp
* @returns true if deletion successful, false otherwise
* Create a new empty todo item.
*
* @param token - The auth token
* @returns A single {@link TodoRow} of the newly created item on success, or `undefined` on failure
*/
export async function deleteTodo(token: string, uuid: string, lastChange: string): Promise<boolean> {
export async function add(token: string): Promise<TodoRow | undefined> {
return apiWrapper<TodoRow>('/api/todo/add', { token });
}
/**
* Update an existing todo item's data.
*
* @param token - The auth token
* @param uuid - The todo UUID
* @param data - The new todo data (serialized string)
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns The new `lastChange` value on success, or `undefined` on failure
*/
export async function update(token: string, uuid: string, data: string, lastChange: string): Promise<string | undefined> {
return apiWrapper<string>('/api/todo/update', { token, uuid, data, lastChange });
}
/**
* Delete a todo item.
*
* @param token - The auth token
* @param uuid - The todo UUID
* @param lastChange - The last known `lastChange` value (optimistic concurrency)
* @returns `true` on success, `false` on failure
*/
export async function del(token: string, uuid: string, lastChange: string): Promise<boolean> {
return boolApiWrapper('/api/todo/delete', { token, uuid, lastChange });
}