mirror of https://github.com/usememos/memos
chore: use `axios` instead of `fetch`
parent
a580df5c9f
commit
b52c16c43f
@ -1,209 +1,99 @@
|
||||
import axios from "axios";
|
||||
|
||||
type ResponseObject<T> = {
|
||||
data: T;
|
||||
error?: string;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
type RequestConfig = {
|
||||
method: string;
|
||||
url: string;
|
||||
data?: any;
|
||||
dataType?: "json" | "file";
|
||||
};
|
||||
export function getSystemStatus() {
|
||||
return axios.get<ResponseObject<SystemStatus>>("/api/status");
|
||||
}
|
||||
|
||||
export function login(email: string, password: string) {
|
||||
return axios.post<ResponseObject<User>>("/api/auth/login", {
|
||||
email,
|
||||
password,
|
||||
});
|
||||
}
|
||||
|
||||
export function signup(email: string, password: string, role: UserRole) {
|
||||
return axios.post<ResponseObject<User>>("/api/auth/signup", {
|
||||
email,
|
||||
password,
|
||||
role,
|
||||
name: email,
|
||||
});
|
||||
}
|
||||
|
||||
export function signout() {
|
||||
return axios.post("/api/auth/logout");
|
||||
}
|
||||
|
||||
export function createUser(userCreate: UserCreate) {
|
||||
return axios.post<ResponseObject<User>>("/api/user", userCreate);
|
||||
}
|
||||
|
||||
export function getUser() {
|
||||
return axios.get<ResponseObject<User>>("/api/user/me");
|
||||
}
|
||||
|
||||
export function getUserList() {
|
||||
return axios.get<ResponseObject<User[]>>("/api/user");
|
||||
}
|
||||
|
||||
export function patchUser(userPatch: UserPatch) {
|
||||
return axios.patch<ResponseObject<User>>("/api/user/me", userPatch);
|
||||
}
|
||||
|
||||
export function getMyMemos() {
|
||||
return axios.get<ResponseObject<Memo[]>>("/api/memo");
|
||||
}
|
||||
|
||||
export function getMyArchivedMemos() {
|
||||
return axios.get<ResponseObject<Memo[]>>("/api/memo?rowStatus=ARCHIVED");
|
||||
}
|
||||
|
||||
export function createMemo(memoCreate: MemoCreate) {
|
||||
return axios.post<ResponseObject<Memo>>("/api/memo", memoCreate);
|
||||
}
|
||||
|
||||
export function patchMemo(memoPatch: MemoPatch) {
|
||||
return axios.patch<ResponseObject<Memo>>(`/api/memo/${memoPatch.id}`, memoPatch);
|
||||
}
|
||||
|
||||
export function pinMemo(memoId: MemoId) {
|
||||
return axios.post(`/api/memo/${memoId}/organizer`, {
|
||||
pinned: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function unpinMemo(memoId: MemoId) {
|
||||
return axios.post(`/api/memo/${memoId}/organizer`, {
|
||||
pinned: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteMemo(memoId: MemoId) {
|
||||
return axios.delete(`/api/memo/${memoId}`);
|
||||
}
|
||||
|
||||
export function getMyShortcuts() {
|
||||
return axios.get<ResponseObject<Shortcut[]>>("/api/shortcut");
|
||||
}
|
||||
|
||||
export function createShortcut(shortcutCreate: ShortcutCreate) {
|
||||
return axios.post<ResponseObject<Shortcut>>("/api/shortcut", shortcutCreate);
|
||||
}
|
||||
|
||||
async function request<T>(config: RequestConfig): Promise<T> {
|
||||
const { method, url, data, dataType } = config;
|
||||
const requestConfig: RequestInit = {
|
||||
method,
|
||||
};
|
||||
|
||||
if (data !== undefined) {
|
||||
if (dataType === "file") {
|
||||
requestConfig.body = data;
|
||||
} else {
|
||||
requestConfig.headers = {
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
requestConfig.body = JSON.stringify(data);
|
||||
}
|
||||
}
|
||||
|
||||
const response = await fetch(url, requestConfig);
|
||||
const responseData = (await response.json()) as ResponseObject<T>;
|
||||
|
||||
if (responseData.error || responseData.message) {
|
||||
throw new Error(responseData.error || responseData.message);
|
||||
}
|
||||
|
||||
return responseData.data;
|
||||
}
|
||||
|
||||
namespace api {
|
||||
export function getSystemStatus() {
|
||||
return request<SystemStatus>({
|
||||
method: "GET",
|
||||
url: "/api/status",
|
||||
});
|
||||
}
|
||||
|
||||
export function login(email: string, password: string) {
|
||||
return request<User>({
|
||||
method: "POST",
|
||||
url: "/api/auth/login",
|
||||
data: {
|
||||
email,
|
||||
password,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function signup(email: string, password: string, role: UserRole) {
|
||||
return request<User>({
|
||||
method: "POST",
|
||||
url: "/api/auth/signup",
|
||||
data: {
|
||||
email,
|
||||
password,
|
||||
role,
|
||||
name: email,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function signout() {
|
||||
return request({
|
||||
method: "POST",
|
||||
url: "/api/auth/logout",
|
||||
});
|
||||
}
|
||||
|
||||
export function createUser(userCreate: UserCreate) {
|
||||
return request<User[]>({
|
||||
method: "POST",
|
||||
url: "/api/user",
|
||||
data: userCreate,
|
||||
});
|
||||
}
|
||||
|
||||
export function getUser() {
|
||||
return request<User>({
|
||||
method: "GET",
|
||||
url: "/api/user/me",
|
||||
});
|
||||
}
|
||||
|
||||
export function getUserList() {
|
||||
return request<User[]>({
|
||||
method: "GET",
|
||||
url: "/api/user",
|
||||
});
|
||||
}
|
||||
|
||||
export function patchUser(userPatch: UserPatch) {
|
||||
return request<User>({
|
||||
method: "PATCH",
|
||||
url: "/api/user/me",
|
||||
data: userPatch,
|
||||
});
|
||||
}
|
||||
|
||||
export function getMyMemos() {
|
||||
return request<Memo[]>({
|
||||
method: "GET",
|
||||
url: "/api/memo",
|
||||
});
|
||||
}
|
||||
|
||||
export function getMyArchivedMemos() {
|
||||
return request<Memo[]>({
|
||||
method: "GET",
|
||||
url: "/api/memo?rowStatus=ARCHIVED",
|
||||
});
|
||||
}
|
||||
|
||||
export function createMemo(memoCreate: MemoCreate) {
|
||||
return request<Memo>({
|
||||
method: "POST",
|
||||
url: "/api/memo",
|
||||
data: memoCreate,
|
||||
});
|
||||
}
|
||||
|
||||
export function patchMemo(memoPatch: MemoPatch) {
|
||||
return request<Memo>({
|
||||
method: "PATCH",
|
||||
url: `/api/memo/${memoPatch.id}`,
|
||||
data: {
|
||||
memoPatch,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function pinMemo(memoId: MemoId) {
|
||||
return request({
|
||||
method: "POST",
|
||||
url: `/api/memo/${memoId}/organizer`,
|
||||
data: {
|
||||
pinned: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function unpinMemo(memoId: MemoId) {
|
||||
return request({
|
||||
method: "POST",
|
||||
url: `/api/memo/${memoId}/organizer`,
|
||||
data: {
|
||||
pinned: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteMemo(memoId: MemoId) {
|
||||
return request({
|
||||
method: "DELETE",
|
||||
url: `/api/memo/${memoId}`,
|
||||
});
|
||||
}
|
||||
|
||||
export function getMyShortcuts() {
|
||||
return request<Shortcut[]>({
|
||||
method: "GET",
|
||||
url: "/api/shortcut",
|
||||
});
|
||||
}
|
||||
|
||||
export function createShortcut(shortcutCreate: ShortcutCreate) {
|
||||
return request<Shortcut>({
|
||||
method: "POST",
|
||||
url: "/api/shortcut",
|
||||
data: shortcutCreate,
|
||||
});
|
||||
}
|
||||
|
||||
export function patchShortcut(shortcutPatch: ShortcutPatch) {
|
||||
return request<Shortcut>({
|
||||
method: "PATCH",
|
||||
url: `/api/shortcut/${shortcutPatch.id}`,
|
||||
data: shortcutPatch,
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteShortcutById(shortcutId: ShortcutId) {
|
||||
return request({
|
||||
method: "DELETE",
|
||||
url: `/api/shortcut/${shortcutId}`,
|
||||
});
|
||||
}
|
||||
|
||||
export function uploadFile(formData: FormData) {
|
||||
return request<Resource>({
|
||||
method: "POST",
|
||||
url: "/api/resource",
|
||||
data: formData,
|
||||
dataType: "file",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default api;
|
||||
export function patchShortcut(shortcutPatch: ShortcutPatch) {
|
||||
return axios.patch<ResponseObject<Shortcut>>(`/api/shortcut/${shortcutPatch.id}`, shortcutPatch);
|
||||
}
|
||||
|
||||
export function deleteShortcutById(shortcutId: ShortcutId) {
|
||||
return axios.delete(`/api/shortcut/${shortcutId}`);
|
||||
}
|
||||
|
||||
export function uploadFile(formData: FormData) {
|
||||
return axios.post<ResponseObject<Resource>>("/api/resource", formData);
|
||||
}
|
||||
|
@ -1,223 +1,219 @@
|
||||
namespace utils {
|
||||
export function getNowTimeStamp(): number {
|
||||
return Date.now();
|
||||
}
|
||||
export function getNowTimeStamp(): number {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
export function getOSVersion(): "Windows" | "MacOS" | "Linux" | "Unknown" {
|
||||
const appVersion = navigator.userAgent;
|
||||
let detectedOS: "Windows" | "MacOS" | "Linux" | "Unknown" = "Unknown";
|
||||
export function getOSVersion(): "Windows" | "MacOS" | "Linux" | "Unknown" {
|
||||
const appVersion = navigator.userAgent;
|
||||
let detectedOS: "Windows" | "MacOS" | "Linux" | "Unknown" = "Unknown";
|
||||
|
||||
if (appVersion.indexOf("Win") != -1) {
|
||||
detectedOS = "Windows";
|
||||
} else if (appVersion.indexOf("Mac") != -1) {
|
||||
detectedOS = "MacOS";
|
||||
} else if (appVersion.indexOf("Linux") != -1) {
|
||||
detectedOS = "Linux";
|
||||
}
|
||||
|
||||
return detectedOS;
|
||||
if (appVersion.indexOf("Win") != -1) {
|
||||
detectedOS = "Windows";
|
||||
} else if (appVersion.indexOf("Mac") != -1) {
|
||||
detectedOS = "MacOS";
|
||||
} else if (appVersion.indexOf("Linux") != -1) {
|
||||
detectedOS = "Linux";
|
||||
}
|
||||
|
||||
export function getTimeStampByDate(t: Date | number | string): number {
|
||||
if (typeof t === "string") {
|
||||
t = t.replaceAll("-", "/");
|
||||
}
|
||||
const d = new Date(t);
|
||||
return detectedOS;
|
||||
}
|
||||
|
||||
return d.getTime();
|
||||
export function getTimeStampByDate(t: Date | number | string): number {
|
||||
if (typeof t === "string") {
|
||||
t = t.replaceAll("-", "/");
|
||||
}
|
||||
const d = new Date(t);
|
||||
|
||||
export function getDateStampByDate(t: Date | number | string): number {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
return d.getTime();
|
||||
}
|
||||
|
||||
return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
||||
}
|
||||
export function getDateStampByDate(t: Date | number | string): number {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
|
||||
export function getDateString(t: Date | number | string): string {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
||||
}
|
||||
|
||||
const year = d.getFullYear();
|
||||
const month = d.getMonth() + 1;
|
||||
const date = d.getDate();
|
||||
export function getDateString(t: Date | number | string): string {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
|
||||
return `${year}/${month}/${date}`;
|
||||
}
|
||||
const year = d.getFullYear();
|
||||
const month = d.getMonth() + 1;
|
||||
const date = d.getDate();
|
||||
|
||||
export function getDataStringWithTs(ts: number): string {
|
||||
return getDateTimeString(ts * 1000);
|
||||
}
|
||||
return `${year}/${month}/${date}`;
|
||||
}
|
||||
|
||||
export function getTimeString(t: Date | number | string): string {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
export function getDataStringWithTs(ts: number): string {
|
||||
return getDateTimeString(ts * 1000);
|
||||
}
|
||||
|
||||
const hours = d.getHours();
|
||||
const mins = d.getMinutes();
|
||||
export function getTimeString(t: Date | number | string): string {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
|
||||
const hoursStr = hours < 10 ? "0" + hours : hours;
|
||||
const minsStr = mins < 10 ? "0" + mins : mins;
|
||||
const hours = d.getHours();
|
||||
const mins = d.getMinutes();
|
||||
|
||||
return `${hoursStr}:${minsStr}`;
|
||||
}
|
||||
const hoursStr = hours < 10 ? "0" + hours : hours;
|
||||
const minsStr = mins < 10 ? "0" + mins : mins;
|
||||
|
||||
// For example: 2021-4-8 17:52:17
|
||||
export function getDateTimeString(t: Date | number | string): string {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
return `${hoursStr}:${minsStr}`;
|
||||
}
|
||||
|
||||
const year = d.getFullYear();
|
||||
const month = d.getMonth() + 1;
|
||||
const date = d.getDate();
|
||||
const hours = d.getHours();
|
||||
const mins = d.getMinutes();
|
||||
const secs = d.getSeconds();
|
||||
// For example: 2021-4-8 17:52:17
|
||||
export function getDateTimeString(t: Date | number | string): string {
|
||||
const d = new Date(getTimeStampByDate(t));
|
||||
|
||||
const monthStr = month < 10 ? "0" + month : month;
|
||||
const dateStr = date < 10 ? "0" + date : date;
|
||||
const hoursStr = hours < 10 ? "0" + hours : hours;
|
||||
const minsStr = mins < 10 ? "0" + mins : mins;
|
||||
const secsStr = secs < 10 ? "0" + secs : secs;
|
||||
const year = d.getFullYear();
|
||||
const month = d.getMonth() + 1;
|
||||
const date = d.getDate();
|
||||
const hours = d.getHours();
|
||||
const mins = d.getMinutes();
|
||||
const secs = d.getSeconds();
|
||||
|
||||
return `${year}/${monthStr}/${dateStr} ${hoursStr}:${minsStr}:${secsStr}`;
|
||||
}
|
||||
const monthStr = month < 10 ? "0" + month : month;
|
||||
const dateStr = date < 10 ? "0" + date : date;
|
||||
const hoursStr = hours < 10 ? "0" + hours : hours;
|
||||
const minsStr = mins < 10 ? "0" + mins : mins;
|
||||
const secsStr = secs < 10 ? "0" + secs : secs;
|
||||
|
||||
export function dedupe<T>(data: T[]): T[] {
|
||||
return Array.from(new Set(data));
|
||||
}
|
||||
return `${year}/${monthStr}/${dateStr} ${hoursStr}:${minsStr}:${secsStr}`;
|
||||
}
|
||||
|
||||
export function dedupeObjectWithId<T extends { id: string | number }>(data: T[]): T[] {
|
||||
const idSet = new Set<string | number>();
|
||||
const result = [];
|
||||
export function dedupe<T>(data: T[]): T[] {
|
||||
return Array.from(new Set(data));
|
||||
}
|
||||
|
||||
for (const d of data) {
|
||||
if (!idSet.has(d.id)) {
|
||||
idSet.add(d.id);
|
||||
result.push(d);
|
||||
}
|
||||
}
|
||||
export function dedupeObjectWithId<T extends { id: string | number }>(data: T[]): T[] {
|
||||
const idSet = new Set<string | number>();
|
||||
const result = [];
|
||||
|
||||
return result;
|
||||
for (const d of data) {
|
||||
if (!idSet.has(d.id)) {
|
||||
idSet.add(d.id);
|
||||
result.push(d);
|
||||
}
|
||||
}
|
||||
|
||||
export function debounce(fn: FunctionType, delay: number) {
|
||||
let timer: number | null = null;
|
||||
|
||||
return () => {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(fn, delay);
|
||||
} else {
|
||||
timer = setTimeout(fn, delay);
|
||||
}
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function throttle(fn: FunctionType, delay: number) {
|
||||
let valid = true;
|
||||
export function debounce(fn: FunctionType, delay: number) {
|
||||
let timer: number | null = null;
|
||||
|
||||
return () => {
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
valid = false;
|
||||
setTimeout(() => {
|
||||
fn();
|
||||
valid = true;
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
return () => {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(fn, delay);
|
||||
} else {
|
||||
timer = setTimeout(fn, delay);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function transformObjectToParamsString(object: KVObject): string {
|
||||
const params = [];
|
||||
const keys = Object.keys(object).sort();
|
||||
export function throttle(fn: FunctionType, delay: number) {
|
||||
let valid = true;
|
||||
|
||||
for (const key of keys) {
|
||||
const val = object[key];
|
||||
if (val) {
|
||||
if (typeof val === "object") {
|
||||
params.push(...transformObjectToParamsString(val).split("&"));
|
||||
} else {
|
||||
params.push(`${key}=${val}`);
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
valid = false;
|
||||
setTimeout(() => {
|
||||
fn();
|
||||
valid = true;
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
return params.join("&");
|
||||
}
|
||||
|
||||
export function transformParamsStringToObject(paramsString: string): KVObject {
|
||||
const object: KVObject = {};
|
||||
const params = paramsString.split("&");
|
||||
export function transformObjectToParamsString(object: KVObject): string {
|
||||
const params = [];
|
||||
const keys = Object.keys(object).sort();
|
||||
|
||||
for (const p of params) {
|
||||
const [key, val] = p.split("=");
|
||||
if (key && val) {
|
||||
object[key] = val;
|
||||
for (const key of keys) {
|
||||
const val = object[key];
|
||||
if (val) {
|
||||
if (typeof val === "object") {
|
||||
params.push(...transformObjectToParamsString(val).split("&"));
|
||||
} else {
|
||||
params.push(`${key}=${val}`);
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
export function filterObjectNullKeys(object: KVObject): KVObject {
|
||||
if (!object) {
|
||||
return {};
|
||||
}
|
||||
return params.join("&");
|
||||
}
|
||||
|
||||
const finalObject: KVObject = {};
|
||||
const keys = Object.keys(object).sort();
|
||||
export function transformParamsStringToObject(paramsString: string): KVObject {
|
||||
const object: KVObject = {};
|
||||
const params = paramsString.split("&");
|
||||
|
||||
for (const key of keys) {
|
||||
const val = object[key];
|
||||
if (typeof val === "object") {
|
||||
const temp = filterObjectNullKeys(JSON.parse(JSON.stringify(val)));
|
||||
if (temp && Object.keys(temp).length > 0) {
|
||||
finalObject[key] = temp;
|
||||
}
|
||||
} else {
|
||||
if (val) {
|
||||
finalObject[key] = val;
|
||||
}
|
||||
}
|
||||
for (const p of params) {
|
||||
const [key, val] = p.split("=");
|
||||
if (key && val) {
|
||||
object[key] = val;
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
return finalObject;
|
||||
export function filterObjectNullKeys(object: KVObject): KVObject {
|
||||
if (!object) {
|
||||
return {};
|
||||
}
|
||||
|
||||
export async function copyTextToClipboard(text: string) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (error: unknown) {
|
||||
console.warn("Copy to clipboard failed.", error);
|
||||
const finalObject: KVObject = {};
|
||||
const keys = Object.keys(object).sort();
|
||||
|
||||
for (const key of keys) {
|
||||
const val = object[key];
|
||||
if (typeof val === "object") {
|
||||
const temp = filterObjectNullKeys(JSON.parse(JSON.stringify(val)));
|
||||
if (temp && Object.keys(temp).length > 0) {
|
||||
finalObject[key] = temp;
|
||||
}
|
||||
} else {
|
||||
console.warn("Copy to clipboard failed, methods not supports.");
|
||||
if (val) {
|
||||
finalObject[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getImageSize(src: string): Promise<{ width: number; height: number }> {
|
||||
return new Promise((resolve) => {
|
||||
const imgEl = new Image();
|
||||
return finalObject;
|
||||
}
|
||||
|
||||
export async function copyTextToClipboard(text: string) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (error: unknown) {
|
||||
console.warn("Copy to clipboard failed.", error);
|
||||
}
|
||||
} else {
|
||||
console.warn("Copy to clipboard failed, methods not supports.");
|
||||
}
|
||||
}
|
||||
|
||||
imgEl.onload = () => {
|
||||
const { width, height } = imgEl;
|
||||
export function getImageSize(src: string): Promise<{ width: number; height: number }> {
|
||||
return new Promise((resolve) => {
|
||||
const imgEl = new Image();
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
resolve({ width, height });
|
||||
} else {
|
||||
resolve({ width: 0, height: 0 });
|
||||
}
|
||||
};
|
||||
imgEl.onload = () => {
|
||||
const { width, height } = imgEl;
|
||||
|
||||
imgEl.onerror = () => {
|
||||
if (width > 0 && height > 0) {
|
||||
resolve({ width, height });
|
||||
} else {
|
||||
resolve({ width: 0, height: 0 });
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
imgEl.className = "hidden";
|
||||
imgEl.src = src;
|
||||
document.body.appendChild(imgEl);
|
||||
imgEl.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
imgEl.onerror = () => {
|
||||
resolve({ width: 0, height: 0 });
|
||||
};
|
||||
|
||||
export default utils;
|
||||
imgEl.className = "hidden";
|
||||
imgEl.src = src;
|
||||
document.body.appendChild(imgEl);
|
||||
imgEl.remove();
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue