Merge remote-tracking branch 'origin/main' into combined_modlog

This commit is contained in:
Dessalines 2025-01-13 23:31:37 -05:00
commit 8472692a41
15 changed files with 240 additions and 108 deletions

View file

@ -1,7 +1,7 @@
{
"name": "lemmy-js-client",
"description": "A javascript / typescript client for Lemmy",
"version": "0.20.0-reports-combined.3",
"version": "0.20.0-image-api-rework.8",
"author": "Dessalines <tyhou13@gmx.com>",
"license": "AGPL-3.0",
"main": "./dist/index.js",
@ -35,7 +35,7 @@
"typescript": "^5.5.4",
"typescript-eslint": "^8.7.0"
},
"packageManager": "pnpm@9.15.2",
"packageManager": "pnpm@9.15.3",
"types": "./dist/index.d.ts",
"lint-staged": {
"*.{ts,tsx,js}": [

View file

@ -5,7 +5,7 @@ const exportRegex = /export\s+(?:enum|interface|type)\s+([A-Za-z0-9_]+)/g;
const baseExports = [
'export * from "./http";',
'export {UploadImage,UploadImageResponse,ImageFile,DeleteImage} from "./other_types";',
'export {UploadImage} from "./other_types";',
];
async function putTypesInIndex() {

View file

@ -117,12 +117,7 @@ import { SearchResponse } from "./types/SearchResponse";
import { SiteResponse } from "./types/SiteResponse";
import { TransferCommunity } from "./types/TransferCommunity";
import { VerifyEmail } from "./types/VerifyEmail";
import {
DeleteImage,
UploadImage,
UploadImageResponse,
VERSION,
} from "./other_types";
import { UploadImage, VERSION } from "./other_types";
import { HideCommunity } from "./types/HideCommunity";
import { GenerateTotpSecretResponse } from "./types/GenerateTotpSecretResponse";
import { UpdateTotp } from "./types/UpdateTotp";
@ -163,11 +158,14 @@ import { ListPersonContent } from "./types/ListPersonContent";
import { ListPersonContentResponse } from "./types/ListPersonContentResponse";
import { ListPersonSaved } from "./types/ListPersonSaved";
import { ListPersonSavedResponse } from "./types/ListPersonSavedResponse";
import { DeleteImageParams } from "./types/DeleteImageParams";
import { UploadImageResponse } from "./types/UploadImageResponse";
enum HttpType {
Get = "GET",
Post = "POST",
Put = "PUT",
Delete = "DELETE",
}
type RequestOptions = Pick<RequestInit, "signal">;
@ -178,7 +176,6 @@ type RequestOptions = Pick<RequestInit, "signal">;
export class LemmyHttp {
#apiUrl: string;
#headers: { [key: string]: string } = {};
#pictrsUrl: string;
#fetchFunction: typeof fetch = fetch.bind(globalThis);
/**
@ -194,7 +191,6 @@ export class LemmyHttp {
},
) {
this.#apiUrl = `${baseUrl.replace(/\/+$/, "")}/api/${VERSION}`;
this.#pictrsUrl = `${baseUrl}/pictrs/image`;
if (options?.headers) {
this.#headers = options.headers;
@ -1871,64 +1867,224 @@ export class LemmyHttp {
);
}
/**
* Upload new user avatar.
*
* `HTTP.Post /account/avatar`
*/
async uploadUserAvatar(
image: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#upload("/account/avatar", image, options);
}
/**
* Delete the user avatar.
*
* `HTTP.Delete /account/avatar`
*/
async deleteUserAvatar(options?: RequestOptions): Promise<SuccessResponse> {
return this.#wrapper<object, SuccessResponse>(
HttpType.Delete,
"/account/avatar",
{},
options,
);
}
/**
* Upload new user banner.
*
* `HTTP.Post /account/banner`
*/
async uploadUserBanner(
image: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#upload("/account/banner", image, options);
}
/**
* Delete the user banner.
*
* `HTTP.Delete /account/banner`
*/
async deleteUserBanner(options?: RequestOptions): Promise<SuccessResponse> {
return this.#wrapper<object, SuccessResponse>(
HttpType.Delete,
"/account/banner",
{},
options,
);
}
/**
* Upload new community icon.
*
* `HTTP.Post /community/icon`
*/
async uploadCommunityIcon(
image: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#upload("/community/icon", image, options);
}
/**
* Delete the community icon.
*
* `HTTP.Delete /community/icon`
*/
async deleteCommunityIcon(
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#wrapper<object, SuccessResponse>(
HttpType.Delete,
"/community/icon",
{},
options,
);
}
/**
* Upload new community banner.
*
* `HTTP.Post /community/banner`
*/
async uploadCommunityBanner(
image: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#upload("/community/banner", image, options);
}
/**
* Delete the community banner.
*
* `HTTP.Delete /community/banner`
*/
async deleteCommunityBanner(
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#wrapper<object, SuccessResponse>(
HttpType.Delete,
"/community/banner",
{},
options,
);
}
/**
* Upload new site icon.
*
* `HTTP.Post /site/icon`
*/
async uploadSiteIcon(
image: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#upload("/site/icon", image, options);
}
/**
* Delete the site icon.
*
* `HTTP.Delete /site/icon`
*/
async deleteSiteIcon(options?: RequestOptions): Promise<SuccessResponse> {
return this.#wrapper<object, SuccessResponse>(
HttpType.Delete,
"/site/icon",
{},
options,
);
}
/**
* Upload new site banner.
*
* `HTTP.Post /site/banner`
*/
async uploadSiteBanner(
image: UploadImage,
options?: RequestOptions,
): Promise<SuccessResponse> {
return this.#upload("/site/banner", image, options);
}
/**
* Delete the site banner.
*
* `HTTP.Delete /site/banner`
*/
async deleteSiteBanner(options?: RequestOptions): Promise<SuccessResponse> {
return this.#wrapper<object, SuccessResponse>(
HttpType.Delete,
"/site/banner",
{},
options,
);
}
/**
* Upload an image to the server.
*
* `HTTP.Post /image`
*/
async uploadImage(
{ image }: UploadImage,
image: UploadImage,
options?: RequestOptions,
): Promise<UploadImageResponse> {
return this.#upload("/image", image, options);
}
/**
* Delete a pictrs image
*
* `HTTP.Delete /image`
*/
async deleteImage(form: DeleteImageParams, options?: RequestOptions) {
return this.#wrapper<DeleteImageParams, SuccessResponse>(
HttpType.Delete,
"/image",
form,
options,
);
}
/**
* Health check for image functionality
*
* `HTTP.Get /image/health`
*/
async imageHealth(options?: RequestOptions) {
return this.#wrapper<object, SuccessResponse>(
HttpType.Get,
"/image/health",
{},
options,
);
}
#buildFullUrl(endpoint: string) {
return `${this.#apiUrl}${endpoint}`;
}
async #upload<ResponseType>(
path: string,
{ image }: UploadImage,
options?: RequestOptions,
): Promise<ResponseType> {
const formData = createFormData(image);
let url: string | undefined = undefined;
let delete_url: string | undefined = undefined;
const response = await this.#fetchFunction(this.#pictrsUrl, {
const response = await this.#fetchFunction(this.#buildFullUrl(path), {
...options,
method: HttpType.Post,
body: formData as unknown as BodyInit,
headers: this.#headers,
});
if (response.status === 413) {
return { msg: "too_large" };
}
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,
};
}
/**
* Delete a pictrs image
*/
async deleteImage(
{ token, filename }: DeleteImage,
options?: RequestOptions,
): Promise<boolean> {
const deleteUrl = `${this.#pictrsUrl}/delete/${token}/${filename}`;
const response = await this.#fetchFunction(deleteUrl, {
...options,
method: HttpType.Get,
headers: this.#headers,
});
return response.status == 204;
}
#buildFullUrl(endpoint: string) {
return `${this.#apiUrl}${endpoint}`;
return response.json();
}
async #wrapper<BodyType extends object, ResponseType>(

View file

@ -1,10 +1,5 @@
export * from "./http";
export {
UploadImage,
UploadImageResponse,
ImageFile,
DeleteImage,
} from "./other_types";
export { UploadImage } from "./other_types";
export { ActivityId } from "./types/ActivityId";
export { AddAdmin } from "./types/AddAdmin";
export { AddAdminResponse } from "./types/AddAdminResponse";
@ -91,6 +86,7 @@ export { DeleteAccount } from "./types/DeleteAccount";
export { DeleteComment } from "./types/DeleteComment";
export { DeleteCommunity } from "./types/DeleteCommunity";
export { DeleteCustomEmoji } from "./types/DeleteCustomEmoji";
export { DeleteImageParams } from "./types/DeleteImageParams";
export { DeleteOAuthProvider } from "./types/DeleteOAuthProvider";
export { DeletePost } from "./types/DeletePost";
export { DeletePrivateMessage } from "./types/DeletePrivateMessage";
@ -144,6 +140,8 @@ export { GetUnreadRegistrationApplicationCountResponse } from "./types/GetUnread
export { HideCommunity } from "./types/HideCommunity";
export { HidePost } from "./types/HidePost";
export { ImageDetails } from "./types/ImageDetails";
export { ImageGetParams } from "./types/ImageGetParams";
export { ImageProxyParams } from "./types/ImageProxyParams";
export { Instance } from "./types/Instance";
export { InstanceId } from "./types/InstanceId";
export { InstanceWithFederationState } from "./types/InstanceWithFederationState";
@ -318,6 +316,7 @@ export { TransferCommunity } from "./types/TransferCommunity";
export { UpdateTagline } from "./types/UpdateTagline";
export { UpdateTotp } from "./types/UpdateTotp";
export { UpdateTotpResponse } from "./types/UpdateTotpResponse";
export { UploadImageResponse } from "./types/UploadImageResponse";
export { UserBlockInstanceParams } from "./types/UserBlockInstanceParams";
export { VerifyEmail } from "./types/VerifyEmail";
export { VoteView } from "./types/VoteView";

View file

@ -3,23 +3,3 @@ export const VERSION = "v4";
export interface UploadImage {
image: File | Buffer;
}
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;
}
export interface DeleteImage {
token: string;
filename: string;
}

View file

@ -14,8 +14,6 @@ export type CreateSite = {
name: string;
sidebar?: string;
description?: string;
icon?: string;
banner?: string;
enable_nsfw?: boolean;
community_creation_admin_only?: boolean;
require_email_verification?: boolean;

View file

@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DeleteImageParams = { filename: string; token: string };

View file

@ -20,14 +20,6 @@ export type EditCommunity = {
* A shorter, one line description of your community.
*/
description?: string;
/**
* An icon URL.
*/
icon?: string;
/**
* A banner URL.
*/
banner?: string;
/**
* Whether its an NSFW community.
*/

View file

@ -20,14 +20,6 @@ export type EditSite = {
* A shorter, one line description of your site.
*/
description?: string;
/**
* A url for your site's icon.
*/
icon?: string;
/**
* A url for your site's banner.
*/
banner?: string;
/**
* Whether to enable NSFW.
*/

View file

@ -27,4 +27,5 @@ export type GetSiteResponse = {
oauth_providers?: Array<PublicOAuthProvider>;
admin_oauth_providers?: Array<OAuthProvider>;
blocked_urls: Array<LocalSiteUrlBlocklist>;
image_upload_disabled: boolean;
};

View file

@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ImageGetParams = { file_type?: string; max_size?: number };

View file

@ -0,0 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type ImageProxyParams = {
url: string;
file_type?: string;
max_size?: number;
};

View file

@ -22,6 +22,8 @@ export type LemmyErrorType =
| { error: "pictrs_api_key_not_provided" }
| { error: "no_content_type_header" }
| { error: "not_an_image_type" }
| { error: "invalid_image_upload" }
| { error: "image_upload_disabled" }
| { error: "not_a_mod_or_admin" }
| { error: "not_top_mod" }
| { error: "not_logged_in" }

View file

@ -42,14 +42,6 @@ export type SaveUserSettings = {
* The language of the lemmy interface
*/
interface_language?: string;
/**
* A URL for your avatar.
*/
avatar?: string;
/**
* A URL for your banner.
*/
banner?: string;
/**
* Your display name, which can contain strange characters, and does not need to be unique.
*/

View file

@ -0,0 +1,7 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type UploadImageResponse = {
image_url: string;
filename: string;
delete_token: string;
};