From 6b5932fbe1d43fe531a861512b1ac8f31776303e Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Tue, 3 Jan 2023 16:48:43 +0800 Subject: [PATCH] feat: replace axios with ky --- nodejs/package-lock.json | 213 ++++++++++++++++++++++++++++++++++++++- nodejs/package.json | 4 +- nodejs/src/index.ts | 119 ++++++++++------------ 3 files changed, 267 insertions(+), 69 deletions(-) diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index 70585a5..32dbb74 100644 --- a/nodejs/package-lock.json +++ b/nodejs/package-lock.json @@ -1,15 +1,17 @@ { "name": "@hackmd/api", - "version": "2.2.1", + "version": "2.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@hackmd/api", - "version": "2.2.1", + "version": "2.3.0", "license": "MIT", "dependencies": { "axios": "^0.25.0", + "ky": "^0.33.1", + "ky-universal": "^0.11.0", "tslib": "^1.14.1" }, "devDependencies": { @@ -355,6 +357,17 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", @@ -542,6 +555,14 @@ "node": ">= 8" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -780,6 +801,14 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -835,6 +864,28 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -897,6 +948,17 @@ } } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1095,6 +1157,41 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/ky": { + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.1.tgz", + "integrity": "sha512-zZ9OlhgM4UEunvgJBH1bBl7+a7vas1HnCLSezu2CJawc4Ka+yJculRAVKbakUece4gW7kC5Dz+UGvbXIlpDt1w==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, + "node_modules/ky-universal": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", + "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", + "dependencies": { + "abort-controller": "^3.0.0", + "node-fetch": "^3.2.10" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky-universal?sponsor=1" + }, + "peerDependencies": { + "ky": ">=0.31.4", + "web-streams-polyfill": ">=3.2.1" + }, + "peerDependenciesMeta": { + "web-streams-polyfill": { + "optional": true + } + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -1184,6 +1281,41 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", + "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1653,6 +1785,14 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1916,6 +2056,14 @@ "eslint-visitor-keys": "^3.0.0" } }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", @@ -2061,6 +2209,11 @@ "which": "^2.0.1" } }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" + }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", @@ -2232,6 +2385,11 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2283,6 +2441,15 @@ "reusify": "^1.0.4" } }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2322,6 +2489,14 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2472,6 +2647,20 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "ky": { + "version": "0.33.1", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.1.tgz", + "integrity": "sha512-zZ9OlhgM4UEunvgJBH1bBl7+a7vas1HnCLSezu2CJawc4Ka+yJculRAVKbakUece4gW7kC5Dz+UGvbXIlpDt1w==" + }, + "ky-universal": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", + "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", + "requires": { + "abort-controller": "^3.0.0", + "node-fetch": "^3.2.10" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2546,6 +2735,21 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz", + "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2852,6 +3056,11 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/nodejs/package.json b/nodejs/package.json index e1c0592..adbc068 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@hackmd/api", - "version": "2.2.1", + "version": "2.3.0", "description": "HackMD Node.js API Client", "main": "dist/index.js", "declaration": "./dist/index.d.ts", @@ -36,6 +36,8 @@ }, "dependencies": { "axios": "^0.25.0", + "ky": "^0.33.1", + "ky-universal": "^0.11.0", "tslib": "^1.14.1" } } diff --git a/nodejs/src/index.ts b/nodejs/src/index.ts index cb0ae0a..2dd9c4c 100644 --- a/nodejs/src/index.ts +++ b/nodejs/src/index.ts @@ -1,119 +1,106 @@ -import axios, { AxiosInstance, AxiosRequestConfig, AxiosError, AxiosResponse } from 'axios' -import { User, Note, Team, CreateNoteOptions, GetMe, GetUserHistory, GetUserNotes, GetUserNote, CreateUserNote, GetUserTeams, GetTeamNotes, CreateTeamNote, DeleteUserNote, DeleteTeamNote, UpdateUserNote, SingleNote, UpdateTeamNote } from './type' +import ky from 'ky-universal' + +import { CreateNoteOptions, GetMe, GetUserHistory, GetUserNotes, GetUserNote, CreateUserNote, GetUserTeams, GetTeamNotes, CreateTeamNote, DeleteUserNote, DeleteTeamNote, UpdateUserNote, SingleNote, UpdateTeamNote } from './type' import * as HackMDErrors from './error' export default class API { - private axios: AxiosInstance + private ky: ReturnType constructor (readonly accessToken: string, public hackmdAPIEndpointURL: string = "https://api.hackmd.io/v1") { if (!accessToken) { throw new HackMDErrors.MissingRequiredArgument('Missing access token when creating HackMD client') } - this.axios = axios.create({ - baseURL: hackmdAPIEndpointURL, - headers:{ - "Content-Type": "application/json", - } - }) - - this.axios.interceptors.request.use( - (config: AxiosRequestConfig) =>{ - config.headers!.Authorization = `Bearer ${accessToken}` - return config + this.ky = ky.create({ + prefixUrl: hackmdAPIEndpointURL, + headers: { + Authorization: `Bearer ${accessToken}` }, - (err: AxiosError) => { - return Promise.reject(err) + hooks: { + afterResponse: [ + async (request, options, response) => { + if (!response.ok) { + if (response.status >= 500) { + throw new HackMDErrors.InternalServerError( + `HackMD internal error (${response.status} ${response.statusText})`, + response.status, + response.statusText, + ) + } else { + throw new HackMDErrors.HttpResponseError( + `Received an error response (${response.status} ${response.statusText}) from HackMD`, + response.status, + response.statusText, + ) + } + } + } + ] } - ) - - this.axios.interceptors.response.use( - (response: AxiosResponse) => { - return response - }, - async (err: AxiosError) => { - if (!err.response) { - return Promise.reject(err) - } - - if (err.response.status >= 500) { - throw new HackMDErrors.InternalServerError( - `HackMD internal error (${err.response.status} ${err.response.statusText})`, - err.response.status, - err.response.statusText, - ) - } else { - throw new HackMDErrors.HttpResponseError( - `Received an error response (${err.response.status} ${err.response.statusText}) from HackMD`, - err.response.status, - err.response.statusText, - ) - } - } - ) + }) } async getMe (): Promise { - const { data } = await this.axios.get("me") - return data + return this.ky.get("me").json() } async getHistory (): Promise { - const { data } = await this.axios.get("history") - return data + return this.ky.get("history").json() } async getNoteList (): Promise { - const { data } = await this.axios.get("notes") - return data + return ky.get("notes").json() } async getNote (noteId: string): Promise { - const { data } = await this.axios.get(`notes/${noteId}`) - return data + return ky.get(`notes/${noteId}`).json() } async createNote (options: CreateNoteOptions): Promise { - const { data } = await this.axios.post("notes", options) - return data + return ky.post("notes", { + json: options + }).json() } async updateNoteContent (noteId: string, content?: string): Promise { - await this.axios.patch(`notes/${noteId}`, { content }) + await this.ky.patch(`notes/${noteId}`, { json: { content } }) } - async updateNote (noteId: string, options: Partial>): Promise { - return await this.axios.patch(`notes/${noteId}`, options) + async updateNote (noteId: string, options: Partial>) { + return await this.ky.patch(`notes/${noteId}`, { + json: options + }).json() } async deleteNote (noteId: string): Promise { - await this.axios.delete(`notes/${noteId}`) + await this.ky.delete(`notes/${noteId}`) } async getTeams (): Promise { - const { data } = await this.axios.get("teams") - return data + return await this.ky("teams").json() } async getTeamNotes (teamPath: string): Promise { - const { data } = await this.axios.get(`teams/${teamPath}/notes`) - return data + return this.ky.get(`teams/${teamPath}/notes`).json() } async createTeamNote (teamPath: string, options: CreateNoteOptions): Promise { - const { data } = await this.axios.post(`teams/${teamPath}/notes`, options) - return data + return await this.ky.post(`teams/${teamPath}/notes`, { + json: options + }).json() } async updateTeamNoteContent (teamPath: string, noteId: string, content?: string): Promise { - await this.axios.patch(`teams/${teamPath}/notes/${noteId}`, { content }) + await this.ky.patch(`teams/${teamPath}/notes/${noteId}`, { json: { content } }).json() } - async updateTeamNote (teamPath: string, noteId: string, options: Partial>): Promise { - return await this.axios.patch(`teams/${teamPath}/notes/${noteId}`, options) + async updateTeamNote (teamPath: string, noteId: string, options: Partial>) { + return await this.ky.patch(`teams/${teamPath}/notes/${noteId}`, { + json: options + }).json() } async deleteTeamNote (teamPath: string, noteId: string): Promise { - await this.axios.delete(`teams/${teamPath}/notes/${noteId}`) + await this.ky.delete(`teams/${teamPath}/notes/${noteId}`) } }