From 360196c8aed80cfa25c5882b505ae55a76e7df7e Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Wed, 22 Mar 2023 14:33:54 -0400 Subject: [PATCH] feat: add image upload method to http client (#108) * feat: add image upload method to http client * fix: Make files optional on UploadImageResponse * fix: Fix comment typo * fix: replace loose equals with strict equals * fix: Remove useless awaits * fix: Add explicit return types to image upload helper functions * fix: Include client headers in image upload request * fix: Change type of uploadImage arg to File | Buffer instead of Blob | Buffer * doc: Add doc string * refactor: Switch to using cross-fetch instead of node-fetch v3 * chore: remove unnecessary asyncs --- package.json | 4 +- src/http.ts | 244 +++++++++++++++++++++++++-------------- src/interfaces/others.ts | 23 ++++ tsconfig.json | 7 +- yarn.lock | 31 +++-- 5 files changed, 198 insertions(+), 111 deletions(-) diff --git a/package.json b/package.json index c1fd321..897e124 100644 --- a/package.json +++ b/package.json @@ -26,11 +26,11 @@ ] }, "dependencies": { - "node-fetch": "2.6.6" + "cross-fetch": "^3.1.5", + "form-data": "^4.0.0" }, "devDependencies": { "@types/node": "^18.6.2", - "@types/node-fetch": "2.6.2", "@typescript-eslint/eslint-plugin": "^5.31.0", "@typescript-eslint/parser": "^5.31.0", "eslint": "^8.20.0", diff --git a/src/http.ts b/src/http.ts index f93231f..1d2dd83 100644 --- a/src/http.ts +++ b/src/http.ts @@ -1,4 +1,6 @@ -import fetch from "node-fetch"; +import fetch from "cross-fetch"; +import FormData from "form-data"; + import { CommentReportResponse, CommentResponse, @@ -131,7 +133,7 @@ import { SearchResponse, SiteResponse, } from "./interfaces/api/site"; -import { VERSION } from "./interfaces/others"; +import { UploadImage, UploadImageResponse, VERSION } from "./interfaces/others"; enum HttpType { Get = "GET", @@ -145,6 +147,7 @@ enum HttpType { export class LemmyHttp { private apiUrl: string; private headers: { [key: string]: string } = {}; + private pictrsUrl: string; /** * Generates a new instance of LemmyHttp. @@ -153,6 +156,7 @@ export class LemmyHttp { */ constructor(baseUrl: string, headers?: { [key: string]: string }) { this.apiUrl = `${baseUrl}/api/${VERSION}`; + this.pictrsUrl = `${baseUrl}/pictrs/image`; if (headers) { this.headers = headers; @@ -164,7 +168,7 @@ export class LemmyHttp { * * `HTTP.GET /site` */ - async getSite(form: GetSite) { + getSite(form: GetSite) { return this.wrapper(HttpType.Get, "/site", form); } @@ -173,7 +177,7 @@ export class LemmyHttp { * * `HTTP.POST /site` */ - async createSite(form: CreateSite) { + createSite(form: CreateSite) { return this.wrapper(HttpType.Post, "/site", form); } @@ -182,7 +186,7 @@ export class LemmyHttp { * * `HTTP.PUT /site` */ - async editSite(form: EditSite) { + editSite(form: EditSite) { return this.wrapper(HttpType.Put, "/site", form); } @@ -191,7 +195,7 @@ export class LemmyHttp { * * `HTTP.POST /user/leave_admin` */ - async leaveAdmin(form: LeaveAdmin) { + leaveAdmin(form: LeaveAdmin) { return this.wrapper( HttpType.Post, "/user/leave_admin", @@ -204,7 +208,7 @@ export class LemmyHttp { * * `HTTP.GET /modlog` */ - async getModlog(form: GetModlog) { + getModlog(form: GetModlog) { return this.wrapper( HttpType.Get, "/modlog", @@ -217,7 +221,7 @@ export class LemmyHttp { * * `HTTP.GET /search` */ - async search(form: Search) { + search(form: Search) { return this.wrapper(HttpType.Get, "/search", form); } @@ -226,7 +230,7 @@ export class LemmyHttp { * * `HTTP.GET /resolve_object` */ - async resolveObject(form: ResolveObject) { + resolveObject(form: ResolveObject) { return this.wrapper( HttpType.Get, "/resolve_object", @@ -239,7 +243,7 @@ export class LemmyHttp { * * `HTTP.POST /community` */ - async createCommunity(form: CreateCommunity) { + createCommunity(form: CreateCommunity) { return this.wrapper( HttpType.Post, "/community", @@ -252,7 +256,7 @@ export class LemmyHttp { * * `HTTP.GET /community` */ - async getCommunity(form: GetCommunity) { + getCommunity(form: GetCommunity) { return this.wrapper( HttpType.Get, "/community", @@ -265,7 +269,7 @@ export class LemmyHttp { * * `HTTP.PUT /community` */ - async editCommunity(form: EditCommunity) { + editCommunity(form: EditCommunity) { return this.wrapper( HttpType.Put, "/community", @@ -278,7 +282,7 @@ export class LemmyHttp { * * `HTTP.GET /community/list` */ - async listCommunities(form: ListCommunities) { + listCommunities(form: ListCommunities) { return this.wrapper( HttpType.Get, "/community/list", @@ -291,7 +295,7 @@ export class LemmyHttp { * * `HTTP.POST /community/follow` */ - async followCommunity(form: FollowCommunity) { + followCommunity(form: FollowCommunity) { return this.wrapper( HttpType.Post, "/community/follow", @@ -304,7 +308,7 @@ export class LemmyHttp { * * `HTTP.POST /community/block` */ - async blockCommunity(form: BlockCommunity) { + blockCommunity(form: BlockCommunity) { return this.wrapper( HttpType.Post, "/community/block", @@ -317,7 +321,7 @@ export class LemmyHttp { * * `HTTP.POST /community/delete` */ - async deleteCommunity(form: DeleteCommunity) { + deleteCommunity(form: DeleteCommunity) { return this.wrapper( HttpType.Post, "/community/delete", @@ -330,7 +334,7 @@ export class LemmyHttp { * * `HTTP.POST /community/remove` */ - async removeCommunity(form: RemoveCommunity) { + removeCommunity(form: RemoveCommunity) { return this.wrapper( HttpType.Post, "/community/remove", @@ -343,7 +347,7 @@ export class LemmyHttp { * * `HTTP.POST /community/transfer` */ - async transferCommunity(form: TransferCommunity) { + transferCommunity(form: TransferCommunity) { return this.wrapper( HttpType.Post, "/community/transfer", @@ -356,7 +360,7 @@ export class LemmyHttp { * * `HTTP.POST /community/ban_user` */ - async banFromCommunity(form: BanFromCommunity) { + banFromCommunity(form: BanFromCommunity) { return this.wrapper( HttpType.Post, "/community/ban_user", @@ -369,7 +373,7 @@ export class LemmyHttp { * * `HTTP.POST /community/mod` */ - async addModToCommunity(form: AddModToCommunity) { + addModToCommunity(form: AddModToCommunity) { return this.wrapper( HttpType.Post, "/community/mod", @@ -382,7 +386,7 @@ export class LemmyHttp { * * `HTTP.POST /post` */ - async createPost(form: CreatePost) { + createPost(form: CreatePost) { return this.wrapper(HttpType.Post, "/post", form); } @@ -391,7 +395,7 @@ export class LemmyHttp { * * `HTTP.GET /post` */ - async getPost(form: GetPost) { + getPost(form: GetPost) { return this.wrapper(HttpType.Get, "/post", form); } @@ -400,7 +404,7 @@ export class LemmyHttp { * * `HTTP.PUT /post` */ - async editPost(form: EditPost) { + editPost(form: EditPost) { return this.wrapper(HttpType.Put, "/post", form); } @@ -409,7 +413,7 @@ export class LemmyHttp { * * `HTTP.POST /post/delete` */ - async deletePost(form: DeletePost) { + deletePost(form: DeletePost) { return this.wrapper( HttpType.Post, "/post/delete", @@ -422,7 +426,7 @@ export class LemmyHttp { * * `HTTP.POST /post/remove` */ - async removePost(form: RemovePost) { + removePost(form: RemovePost) { return this.wrapper( HttpType.Post, "/post/remove", @@ -435,7 +439,7 @@ export class LemmyHttp { * * `HTTP.POST /post/mark_as_read` */ - async markPostAsRead(form: MarkPostAsRead) { + markPostAsRead(form: MarkPostAsRead) { return this.wrapper( HttpType.Post, "/post/mark_as_read", @@ -448,7 +452,7 @@ export class LemmyHttp { * * `HTTP.POST /post/lock` */ - async lockPost(form: LockPost) { + lockPost(form: LockPost) { return this.wrapper( HttpType.Post, "/post/lock", @@ -461,7 +465,7 @@ export class LemmyHttp { * * `HTTP.POST /post/feature` */ - async featurePost(form: FeaturePost) { + featurePost(form: FeaturePost) { return this.wrapper( HttpType.Post, "/post/feature", @@ -474,7 +478,7 @@ export class LemmyHttp { * * `HTTP.GET /post/list` */ - async getPosts(form: GetPosts) { + getPosts(form: GetPosts) { return this.wrapper( HttpType.Get, "/post/list", @@ -487,7 +491,7 @@ export class LemmyHttp { * * `HTTP.POST /post/like` */ - async likePost(form: CreatePostLike) { + likePost(form: CreatePostLike) { return this.wrapper( HttpType.Post, "/post/like", @@ -500,7 +504,7 @@ export class LemmyHttp { * * `HTTP.PUT /post/save` */ - async savePost(form: SavePost) { + savePost(form: SavePost) { return this.wrapper( HttpType.Put, "/post/save", @@ -513,7 +517,7 @@ export class LemmyHttp { * * `HTTP.POST /post/report` */ - async createPostReport(form: CreatePostReport) { + createPostReport(form: CreatePostReport) { return this.wrapper( HttpType.Post, "/post/report", @@ -526,7 +530,7 @@ export class LemmyHttp { * * `HTTP.PUT /post/report/resolve` */ - async resolvePostReport(form: ResolvePostReport) { + resolvePostReport(form: ResolvePostReport) { return this.wrapper( HttpType.Put, "/post/report/resolve", @@ -539,7 +543,7 @@ export class LemmyHttp { * * `HTTP.GET /post/report/list` */ - async listPostReports(form: ListPostReports) { + listPostReports(form: ListPostReports) { return this.wrapper( HttpType.Get, "/post/report/list", @@ -552,7 +556,7 @@ export class LemmyHttp { * * `HTTP.GET /post/site_metadata` */ - async getSiteMetadata(form: GetSiteMetadata) { + getSiteMetadata(form: GetSiteMetadata) { return this.wrapper( HttpType.Get, "/post/site_metadata", @@ -565,7 +569,7 @@ export class LemmyHttp { * * `HTTP.POST /comment` */ - async createComment(form: CreateComment) { + createComment(form: CreateComment) { return this.wrapper( HttpType.Post, "/comment", @@ -578,7 +582,7 @@ export class LemmyHttp { * * `HTTP.PUT /comment` */ - async editComment(form: EditComment) { + editComment(form: EditComment) { return this.wrapper( HttpType.Put, "/comment", @@ -591,7 +595,7 @@ export class LemmyHttp { * * `HTTP.POST /comment/delete` */ - async deleteComment(form: DeleteComment) { + deleteComment(form: DeleteComment) { return this.wrapper( HttpType.Post, "/comment/delete", @@ -604,7 +608,7 @@ export class LemmyHttp { * * `HTTP.POST /comment/remove` */ - async removeComment(form: RemoveComment) { + removeComment(form: RemoveComment) { return this.wrapper( HttpType.Post, "/comment/remove", @@ -617,7 +621,7 @@ export class LemmyHttp { * * `HTTP.POST /comment/mark_as_read` */ - async markCommentReplyAsRead(form: MarkCommentReplyAsRead) { + markCommentReplyAsRead(form: MarkCommentReplyAsRead) { return this.wrapper( HttpType.Post, "/comment/mark_as_read", @@ -630,7 +634,7 @@ export class LemmyHttp { * * `HTTP.POST /comment/like` */ - async likeComment(form: CreateCommentLike) { + likeComment(form: CreateCommentLike) { return this.wrapper( HttpType.Post, "/comment/like", @@ -643,7 +647,7 @@ export class LemmyHttp { * * `HTTP.PUT /comment/save` */ - async saveComment(form: SaveComment) { + saveComment(form: SaveComment) { return this.wrapper( HttpType.Put, "/comment/save", @@ -656,7 +660,7 @@ export class LemmyHttp { * * `HTTP.GET /comment/list` */ - async getComments(form: GetComments) { + getComments(form: GetComments) { return this.wrapper( HttpType.Get, "/comment/list", @@ -669,7 +673,7 @@ export class LemmyHttp { * * `HTTP.POST /comment/report` */ - async createCommentReport(form: CreateCommentReport) { + createCommentReport(form: CreateCommentReport) { return this.wrapper( HttpType.Post, "/comment/report", @@ -682,7 +686,7 @@ export class LemmyHttp { * * `HTTP.PUT /comment/report/resolve` */ - async resolveCommentReport(form: ResolveCommentReport) { + resolveCommentReport(form: ResolveCommentReport) { return this.wrapper( HttpType.Put, "/comment/report/resolve", @@ -695,7 +699,7 @@ export class LemmyHttp { * * `HTTP.GET /comment/report/list` */ - async listCommentReports(form: ListCommentReports) { + listCommentReports(form: ListCommentReports) { return this.wrapper( HttpType.Get, "/comment/report/list", @@ -708,7 +712,7 @@ export class LemmyHttp { * * `HTTP.GET /private_message/list` */ - async getPrivateMessages(form: GetPrivateMessages) { + getPrivateMessages(form: GetPrivateMessages) { return this.wrapper( HttpType.Get, "/private_message/list", @@ -721,7 +725,7 @@ export class LemmyHttp { * * `HTTP.POST /private_message` */ - async createPrivateMessage(form: CreatePrivateMessage) { + createPrivateMessage(form: CreatePrivateMessage) { return this.wrapper( HttpType.Post, "/private_message", @@ -734,7 +738,7 @@ export class LemmyHttp { * * `HTTP.PUT /private_message` */ - async editPrivateMessage(form: EditPrivateMessage) { + editPrivateMessage(form: EditPrivateMessage) { return this.wrapper( HttpType.Put, "/private_message", @@ -747,7 +751,7 @@ export class LemmyHttp { * * `HTTP.POST /private_message/delete` */ - async deletePrivateMessage(form: DeletePrivateMessage) { + deletePrivateMessage(form: DeletePrivateMessage) { return this.wrapper( HttpType.Post, "/private_message/delete", @@ -760,7 +764,7 @@ export class LemmyHttp { * * `HTTP.POST /private_message/mark_as_read` */ - async markPrivateMessageAsRead(form: MarkPrivateMessageAsRead) { + markPrivateMessageAsRead(form: MarkPrivateMessageAsRead) { return this.wrapper( HttpType.Post, "/private_message/mark_as_read", @@ -773,7 +777,7 @@ export class LemmyHttp { * * `HTTP.POST /private_message/report` */ - async createPrivateMessageReport(form: CreatePrivateMessageReport) { + createPrivateMessageReport(form: CreatePrivateMessageReport) { return this.wrapper< CreatePrivateMessageReport, PrivateMessageReportResponse @@ -785,7 +789,7 @@ export class LemmyHttp { * * `HTTP.PUT /private_message/report/resolve` */ - async resolvePrivateMessageReport(form: ResolvePrivateMessageReport) { + resolvePrivateMessageReport(form: ResolvePrivateMessageReport) { return this.wrapper< ResolvePrivateMessageReport, PrivateMessageReportResponse @@ -797,7 +801,7 @@ export class LemmyHttp { * * `HTTP.GET /private_message/report/list` */ - async listPrivateMessageReports(form: ListPrivateMessageReports) { + listPrivateMessageReports(form: ListPrivateMessageReports) { return this.wrapper< ListPrivateMessageReports, ListPrivateMessageReportsResponse @@ -809,7 +813,7 @@ export class LemmyHttp { * * `HTTP.POST /user/register` */ - async register(form: Register) { + register(form: Register) { return this.wrapper( HttpType.Post, "/user/register", @@ -822,7 +826,7 @@ export class LemmyHttp { * * `HTTP.POST /user/login` */ - async login(form: Login) { + login(form: Login) { return this.wrapper( HttpType.Post, "/user/login", @@ -835,7 +839,7 @@ export class LemmyHttp { * * `HTTP.GET /user` */ - async getPersonDetails(form: GetPersonDetails) { + getPersonDetails(form: GetPersonDetails) { return this.wrapper( HttpType.Get, "/user", @@ -848,7 +852,7 @@ export class LemmyHttp { * * `HTTP.GET /user/mention` */ - async getPersonMentions(form: GetPersonMentions) { + getPersonMentions(form: GetPersonMentions) { return this.wrapper( HttpType.Get, "/user/mention", @@ -861,7 +865,7 @@ export class LemmyHttp { * * `HTTP.POST /user/mention/mark_as_read` */ - async markPersonMentionAsRead(form: MarkPersonMentionAsRead) { + markPersonMentionAsRead(form: MarkPersonMentionAsRead) { return this.wrapper( HttpType.Post, "/user/mention/mark_as_read", @@ -874,7 +878,7 @@ export class LemmyHttp { * * `HTTP.GET /user/replies` */ - async getReplies(form: GetReplies) { + getReplies(form: GetReplies) { return this.wrapper( HttpType.Get, "/user/replies", @@ -887,7 +891,7 @@ export class LemmyHttp { * * `HTTP.POST /user/ban` */ - async banPerson(form: BanPerson) { + banPerson(form: BanPerson) { return this.wrapper( HttpType.Post, "/user/ban", @@ -900,7 +904,7 @@ export class LemmyHttp { * * `HTTP.GET /user/banned` */ - async getBannedPersons(form: GetBannedPersons) { + getBannedPersons(form: GetBannedPersons) { return this.wrapper( HttpType.Get, "/user/banned", @@ -913,7 +917,7 @@ export class LemmyHttp { * * `HTTP.POST /user/block` */ - async blockPerson(form: BlockPerson) { + blockPerson(form: BlockPerson) { return this.wrapper( HttpType.Post, "/user/block", @@ -926,7 +930,7 @@ export class LemmyHttp { * * `HTTP.GET /user/get_captcha` */ - async getCaptcha() { + getCaptcha() { return this.wrapper( HttpType.Get, "/user/get_captcha", @@ -939,7 +943,7 @@ export class LemmyHttp { * * `HTTP.POST /user/delete_account` */ - async deleteAccount(form: DeleteAccount) { + deleteAccount(form: DeleteAccount) { return this.wrapper( HttpType.Post, "/user/delete_account", @@ -952,7 +956,7 @@ export class LemmyHttp { * * `HTTP.POST /user/password_reset` */ - async passwordReset(form: PasswordReset) { + passwordReset(form: PasswordReset) { return this.wrapper( HttpType.Post, "/user/password_reset", @@ -965,7 +969,7 @@ export class LemmyHttp { * * `HTTP.POST /user/password_change` */ - async passwordChange(form: PasswordChange) { + passwordChange(form: PasswordChange) { return this.wrapper( HttpType.Post, "/user/password_change", @@ -978,7 +982,7 @@ export class LemmyHttp { * * `HTTP.POST /user/mark_all_as_read` */ - async markAllAsRead(form: MarkAllAsRead) { + markAllAsRead(form: MarkAllAsRead) { return this.wrapper( HttpType.Post, "/user/mark_all_as_read", @@ -991,7 +995,7 @@ export class LemmyHttp { * * `HTTP.PUT /user/save_user_settings` */ - async saveUserSettings(form: SaveUserSettings) { + saveUserSettings(form: SaveUserSettings) { return this.wrapper( HttpType.Put, "/user/save_user_settings", @@ -1004,7 +1008,7 @@ export class LemmyHttp { * * `HTTP.PUT /user/change_password` */ - async changePassword(form: ChangePassword) { + changePassword(form: ChangePassword) { return this.wrapper( HttpType.Put, "/user/change_password", @@ -1017,7 +1021,7 @@ export class LemmyHttp { * * `HTTP.GET /user/report_count` */ - async getReportCount(form: GetReportCount) { + getReportCount(form: GetReportCount) { return this.wrapper( HttpType.Get, "/user/report_count", @@ -1030,7 +1034,7 @@ export class LemmyHttp { * * `HTTP.GET /user/unread_count` */ - async getUnreadCount(form: GetUnreadCount) { + getUnreadCount(form: GetUnreadCount) { return this.wrapper( HttpType.Get, "/user/unread_count", @@ -1043,7 +1047,7 @@ export class LemmyHttp { * * `HTTP.POST /user/verify_email` */ - async verifyEmail(form: VerifyEmail) { + verifyEmail(form: VerifyEmail) { return this.wrapper( HttpType.Post, "/user/verify_email", @@ -1056,7 +1060,7 @@ export class LemmyHttp { * * `HTTP.POST /admin/add` */ - async addAdmin(form: AddAdmin) { + addAdmin(form: AddAdmin) { return this.wrapper( HttpType.Post, "/admin/add", @@ -1069,7 +1073,7 @@ export class LemmyHttp { * * `HTTP.GET /admin/registration_application/count` */ - async getUnreadRegistrationApplicationCount( + getUnreadRegistrationApplicationCount( form: GetUnreadRegistrationApplicationCount ) { return this.wrapper< @@ -1083,7 +1087,7 @@ export class LemmyHttp { * * `HTTP.GET /admin/registration_application/list` */ - async listRegistrationApplications(form: ListRegistrationApplications) { + listRegistrationApplications(form: ListRegistrationApplications) { return this.wrapper< ListRegistrationApplications, ListRegistrationApplicationsResponse @@ -1095,7 +1099,7 @@ export class LemmyHttp { * * `HTTP.PUT /admin/registration_application/approve` */ - async approveRegistrationApplication(form: ApproveRegistrationApplication) { + approveRegistrationApplication(form: ApproveRegistrationApplication) { return this.wrapper< ApproveRegistrationApplication, RegistrationApplicationResponse @@ -1107,7 +1111,7 @@ export class LemmyHttp { * * `HTTP.POST /admin/purge/person` */ - async purgePerson(form: PurgePerson) { + purgePerson(form: PurgePerson) { return this.wrapper( HttpType.Post, "/admin/purge/person", @@ -1120,7 +1124,7 @@ export class LemmyHttp { * * `HTTP.POST /admin/purge/community` */ - async purgeCommunity(form: PurgeCommunity) { + purgeCommunity(form: PurgeCommunity) { return this.wrapper( HttpType.Post, "/admin/purge/community", @@ -1133,7 +1137,7 @@ export class LemmyHttp { * * `HTTP.POST /admin/purge/post` */ - async purgePost(form: PurgePost) { + purgePost(form: PurgePost) { return this.wrapper( HttpType.Post, "/admin/purge/post", @@ -1146,7 +1150,7 @@ export class LemmyHttp { * * `HTTP.POST /admin/purge/comment` */ - async purgeComment(form: PurgeComment) { + purgeComment(form: PurgeComment) { return this.wrapper( HttpType.Post, "/admin/purge/comment", @@ -1154,7 +1158,52 @@ export class LemmyHttp { ); } - private buildFullUrl(endpoint: string): string { + /** + * Upload an image to the server. + */ + async uploadImage({ + image, + auth, + }: UploadImage): Promise { + const formData = createFormData(image); + + // If jwt cookie not already set by browser, set it with passed in auth + const headers = {} as any; + if ( + !globalThis?.document?.cookie?.includes("jwt=") && + !this.headers?.Cookie?.includes("jwt=") + ) { + headers.Cookie = `jwt=${auth}`; + } + + let url: string | undefined = undefined; + let delete_url: string | undefined = undefined; + + const response = await fetch(this.pictrsUrl, { + method: HttpType.Post, + body: formData as unknown as BodyInit, + headers: { + ...this.headers, + ...headers, + }, + }); + + const responseJson = await response.json(); + + if (responseJson.msg === "ok") { + const { file: hash, delete_token: deleteToken } = responseJson.files[0]; + delete_url = `${this.pictrsUrl}/delete/${deleteToken}/${hash}`; + url = `${this.pictrsUrl}/${hash}`; + } + + return { + ...responseJson, + url, + delete_url, + }; + } + + private buildFullUrl(endpoint: string) { return `${this.apiUrl}${endpoint}`; } @@ -1163,21 +1212,25 @@ export class LemmyHttp { endpoint: string, form: BodyType ): Promise { - if (type_ == HttpType.Get) { - let getUrl = `${this.buildFullUrl(endpoint)}?${encodeGetParams(form)}`; - return fetch(getUrl, { - method: "GET", + if (type_ === HttpType.Get) { + const getUrl = `${this.buildFullUrl(endpoint)}?${encodeGetParams(form)}`; + const response = await fetch(getUrl, { + method: HttpType.Get, headers: this.headers, - }).then(d => d.json() as Promise); + }); + + return await response.json(); } else { - return fetch(this.buildFullUrl(endpoint), { + const response = await fetch(this.buildFullUrl(endpoint), { method: type_, headers: { "Content-Type": "application/json", ...this.headers, }, body: JSON.stringify(form), - }).then(d => d.json() as Promise); + }); + + return await response.json(); } } } @@ -1188,3 +1241,16 @@ function encodeGetParams(p: BodyType): string { .map(kv => kv.map(encodeURIComponent).join("=")) .join("&"); } + +function createFormData(image: File | Buffer): FormData { + let formData = new FormData(); + + if (image.constructor.name === "File") { + formData.append("images[]", image); + } else { + // The filename doesn't affect the file type or file name that ends up in pictrs + formData.append("images[]", image, { filename: "image.jpg" }); + } + + return formData; +} diff --git a/src/interfaces/others.ts b/src/interfaces/others.ts index ea79e06..ab989f0 100644 --- a/src/interfaces/others.ts +++ b/src/interfaces/others.ts @@ -230,3 +230,26 @@ export interface SiteMetadata { image?: string; html?: string; } + +export interface UploadImage { + image: File | Buffer; + /** + * Optional if cookie with jwt set is already present. Otherwise, auth is required. + */ + auth?: string; +} + +export interface UploadImageResponse { + /** + * Is "ok" if the upload was successful; is something else otherwise. + */ + msg: string; + files?: ImageFile[]; + url?: string; + delete_url?: string; +} + +export interface ImageFile { + file: string; + delete_token: string; +} diff --git a/tsconfig.json b/tsconfig.json index 67a72e7..61b8f21 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,10 +9,9 @@ "target": "ES5", "experimentalDecorators": true, "strictNullChecks": true, - "moduleResolution": "Node" + "moduleResolution": "Node", + "esModuleInterop": true }, - "include": [ - "src/**/*" - ], + "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } diff --git a/yarn.lock b/yarn.lock index 6ae092d..d0db72e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -303,14 +303,6 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== -"@types/node-fetch@2.6.2": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" - integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node@*", "@types/node@^18.6.2": version "18.11.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" @@ -665,6 +657,13 @@ cosmiconfig@^5.0.5: js-yaml "^3.13.1" parse-json "^4.0.0" +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -988,10 +987,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" @@ -1513,10 +1512,10 @@ neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-fetch@2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0"