From 883cb34697716e7144c54ff89232642b93da1a0c Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Sat, 27 May 2023 23:48:09 +0200 Subject: [PATCH 01/18] feat!: use autodoc inventory for automatic typegen Using the autodoc inventory for typegen means: - Easier and faster type updates - Full docs coverage -! We can't split types into multiple files easily --- autotype/main.ts | 194 ++++++++++ autotype/types.ts | 113 ++++++ effis/index.ts | 44 --- oprish/index.ts | 63 ---- package.json | 32 +- pandemonium/index.ts | 24 -- src/v0.3.3.ts | 517 ++++++++++++++++++++++++++ tsconfig.json | 4 +- yarn.lock | 845 ++++++++++--------------------------------- 9 files changed, 1033 insertions(+), 803 deletions(-) create mode 100644 autotype/main.ts create mode 100644 autotype/types.ts delete mode 100644 effis/index.ts delete mode 100644 oprish/index.ts delete mode 100644 pandemonium/index.ts create mode 100644 src/v0.3.3.ts diff --git a/autotype/main.ts b/autotype/main.ts new file mode 100644 index 0000000..73e1f76 --- /dev/null +++ b/autotype/main.ts @@ -0,0 +1,194 @@ +import { FileHandle, open } from "fs/promises"; +import { + StructInfo, + ItemInfo, + EnumInfo, + RouteInfo, + FieldInfo, + VariantType, + EnumVariant, +} from "./types"; +import { argv } from "process"; + +const converters: Map string> = new Map([ + [/^String$/, (_) => "string"], + [/^(u|i)(size|\d\d)$/, (str) => "number"], + [ + /^Option<.+>/, + (str) => convertType(str.replace(/^Option<(.+)>$/, "$1")) + " | null", + ], + [/^bool$/, (_) => "boolean"], + [/^TempFile$/, (_) => "unknown"], + [/^Box<.*>/, (str) => convertType(str.replace(/^Box<(.+)>$/, "$1"))], +]); + +function switchCase(content: string, newCase: string | null): string { + if (newCase == "SCREAMING_SNAKE_CASE") { + return content.replace(/(\S)([A-Z])/gm, "$1_$2").toUpperCase(); + } + return content; +} + +function convertDoc(doc: string) { + return doc.replace(/\[`(.+?)`\]/g, "{@link $1}"); +} + +function convertType(type: string): string { + for (const [regex, converter] of converters) { + if (regex.test(type)) { + console.debug(`[DEBUG] Converting ${type} to ${converter(type)}`); + return converter(type); + } + } + return type; +} + +function indent(str: string, spaces: number) { + return str + .split("\n") + .map((line) => (line === "" ? "" : " ".repeat(spaces) + line)) + .join("\n"); +} + +function fieldToType(field: FieldInfo): string { + let doc = ""; + if (field.doc) { + doc = `/** ${convertDoc(field.doc)} */\n`; + } + return `${doc}${field.name}: ${convertType(field.field_type)}`; +} + +function handleRoute(route: ItemInfo, routes: string[]) { + let doc = ""; + if (route.doc) { + doc = `/** ${convertDoc(route.doc)} */\n`; + } + const camelCaseName = route.name.replace( + /_(\w)/g, + (match: string, p1: string) => p1.toUpperCase() + ); + routes.push( + `${doc}export const ${camelCaseName} = () => ${route.item.route}` + ); +} + +async function buildTypes(fh: FileHandle, typeUrl: string, routes: string[]) { + console.log(`[INFO] Building types for ${typeUrl}`); + const type = await (await fetch(typeUrl)).json(); + if (type.item.type === "struct") { + handleStruct(fh, type); + } else if (type.item.type === "enum") { + handleEnum(fh, type); + } else if (type.item.type === "route") { + handleRoute(type, routes); + } else { + console.log(`[WARN] Unknown type ${type.type} for ${typeUrl}`); + } +} + +async function handleEnum(fh: FileHandle, info: ItemInfo) { + await fh.write( + `export type ${info.name} = ${ + info.item.variants.map((v) => v.name).join(" | ") || "never" + }\n` + ); + + for (const variant of info.item.variants) { + handleEnumVariant(fh, variant, info.item); + } +} + +async function handleEnumVariant( + fh: FileHandle, + variant: EnumVariant, + item: EnumInfo +): Promise { + let typeStr = ""; + let doc = ""; + let bases: string[] = []; + if (variant.type === VariantType.Unit) { + if (item.tag) { + if (variant.doc) { + doc = `/** ${convertDoc(variant.doc)} */`; + } + typeStr += ` ${item.tag}: "${switchCase( + variant.name, + item.rename_all + )}"\n`; + } + } else if (variant.type === VariantType.Tuple) { + if (item.tag) { + typeStr += ` ${item.tag}: "${switchCase( + variant.name, + item.rename_all + )}"\n`; + if (variant.doc) { + doc += ` /** ${convertDoc(variant.doc)} */`; + } + if (item.content) { + typeStr += ` ${item.content}: ${convertType(variant.field_type)}\n`; + } + } + } else if (variant.type === VariantType.Struct) { + if (item.tag) { + if (variant.doc) { + doc = `/** ${convertDoc(variant.doc)} */`; + } + typeStr += ` ${item.tag}: "${switchCase( + variant.name, + item.rename_all + )}"\n`; + for (const field of variant.fields) { + if (field.flattened) { + bases.push(convertType(field.field_type)); + } else { + typeStr += ` ${field.name}: ${convertType(field.field_type)}\n`; + } + } + } + } + typeStr += "}"; + let basesStr = bases.join(", "); + if (basesStr) { + basesStr = ` extends ${basesStr}`; + } + + typeStr = `${doc}\nexport interface ${variant.name}${basesStr} {\n` + typeStr; + await fh.write(typeStr + "\n"); + + return bases; +} + +async function handleStruct(fh: FileHandle, info: ItemInfo) { + let doc = ""; + if (info.doc) { + doc = `/** ${convertDoc(info.doc)} */\n`; + } + let typeStr = `${doc}export interface ${info.name} {\n`; + typeStr += info.item.fields + .map((field) => indent(fieldToType(field), 2)) + .join("\n"); + typeStr += "\n}"; + await fh.write(typeStr + "\n"); +} + +async function main(inventoryIndex: string, output: string) { + let fh = await open(output, "w"); + await fh.write("// This file was @generated by typegen\n"); + + let routes: string[] = []; + + const inventory: string[] = await ( + await fetch(`${inventoryIndex}/index.json`) + ).json(); + + await Promise.all( + inventory.map((url) => { + buildTypes(fh, `${inventoryIndex}/${url}`, routes); + }) + ); + + await fh.write(routes.join("\n")); +} + +main(argv[2], argv[3]); diff --git a/autotype/types.ts b/autotype/types.ts new file mode 100644 index 0000000..46d50c2 --- /dev/null +++ b/autotype/types.ts @@ -0,0 +1,113 @@ +/* MIT License + +Copyright (c) 2022-present Eludris + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. */ + +export enum ItemType { + Struct = "struct", + Enum = "enum", + Route = "route", +} + +export interface FieldInfo { + name: string; + doc: string | null; + field_type: string; + flattened: boolean; + nullable: boolean; + ommitable: boolean; +} + +export interface StructInfo { + type: ItemType.Struct; + fields: FieldInfo[]; +} + +export enum VariantType { + Unit = "unit", + Tuple = "tuple", + Struct = "struct", +} + +export interface UnitEnumVariant { + type: VariantType.Unit; + name: string; + doc: string | null; +} + +export interface TupleEnumVariant { + type: VariantType.Tuple; + name: string; + doc: string | null; + field_type: string; +} + +export interface StructEnumVariant { + type: VariantType.Struct; + name: string; + doc: string | null; + fields: FieldInfo[]; +} + +export type EnumVariant = + | UnitEnumVariant + | TupleEnumVariant + | StructEnumVariant; + +export interface EnumInfo { + type: ItemType.Enum; + tag: string | null; + untagged: boolean; + content: string | null; + rename_all: string | null; + variants: EnumVariant[]; +} + +export interface PathParamInfo { + name: string; + param_type: string; +} + +export interface QueryParamInfo { + name: string; + param_type: string; +} + +export interface RouteInfo { + type: ItemType.Route; + method: string; + route: string; + path_params: PathParamInfo[]; + query_params: QueryParamInfo[]; + body_type: string | null; + return_type: string | null; + guards: string[]; +} + +export type Item = StructInfo | EnumInfo | RouteInfo; + +export interface ItemInfo { + name: string; + doc: string; + category: string; + hidden: boolean; + package: string; + item: T; +} diff --git a/effis/index.ts b/effis/index.ts deleted file mode 100644 index 25304bf..0000000 --- a/effis/index.ts +++ /dev/null @@ -1,44 +0,0 @@ - -export interface TextMetadata { - /** The type of file as a lowercase string, always "text". */ - type: "text"; -} - -export interface ImageMetadata { - /** The type of file as a lowercase string, always "image". */ - type: "image"; - /** The width of the image in pixels. */ - width: number; - /** The height of the image in pixels. */ - height: number; -} - -export interface VideoMetadata { - /** The type of file as a lowercase string, always "video". */ - type: "video"; - /** The width of the video in pixels. */ - width: number; - /** The height of the video in pixels. */ - height: number; -} - -export interface OtherMetadata { - /** The type of file as a lowercase string. */ - type: string; -} - -export type FileMetadata = TextMetadata | ImageMetadata | VideoMetadata | OtherMetadata; - -/** Represents a file stored on Effis. */ -export interface FileData { - /** The id of the file. */ - id: string; - /** The name of the file. */ - name: string; - /** The bucket to which the file belongs. */ - bucket: string; - /** Whether this file is spoiler tagged. This is not provided if false. */ - spoiler?: boolean; - /** A {@link FileMetadata} object containing meta-information about the file. */ - metadata: FileMetadata; -} diff --git a/oprish/index.ts b/oprish/index.ts deleted file mode 100644 index 4d0813a..0000000 --- a/oprish/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** Represents info about an instance. */ -export interface InstanceInfo { - /** The name of the connected Eludris instance. */ - instance_name: string; - /** The description of the connected Eludris instance. If provided, this must be within 1 and 2048 characters long. */ - description?: string; - /** The version of the conencted Eludris instance. */ - version: string; - /** The maximum allowed message content length. */ - message_limit: number; - /** The url to this instance's REST api. */ - oprish_url: string; - /** The url to this instance's gateway. */ - pandemonium_url: string; - /** The url to this instance's CDN. */ - effis_url: string; - /** The maximum number of bytes for an asset. */ - file_size: number; - /** The maximum number of bytes for an attachment. */ - attachment_file_size: number; -} -/** Represents a message sent to or received from Eludris. The message contains its author and content. */ -export interface Message { - /** The author of the message, between 2-32 characters long. */ - author: string; - /** The content of the message. At least one character; The upper bound can be requested as part of the instance's {@link InstanceInfo}. */ - content: string; -} - -/** Represents a ratelimit for a specific part of the Eludris spec. */ -export interface RateLimitConf { - /** The number of seconds the client should wait before making new requests. */ - reset_after: number; - /** The number of requests that can be made within the timeframe denoted by reset_after. */ - limit: number; -} - -/** Represents all ratelimits that apply to the connected Eludris instance. - * This includes individual ratelimit information for Oprish (REST-api), Pandemonium (Gateway), and Effis (CDN). - */ -export interface InstanceRateLimits { - /** Represents the ratelimits for Oprish (REST-api). - * This denotes the ratelimits on each individual route. */ - oprish: { - /** The ratelimit information for the / route. */ - info: RateLimitConf; - /** The ratelimit information for the /messages route. */ - message_create: RateLimitConf; - /** The ratelimit information for the /ratelimts route. */ - ratelimits: RateLimitConf; - }, - /** The ratelimits that apply to the connected Eludris instance's gateway. */ - pandemonium: RateLimitConf - /** The ratelimits that apply to the connected Eludris instance's CDN. */ - effis: RateLimitConf & { - /** The maximum number of bytes that can be uploaded in the timeframe denoted by reset_after. */ - file_size_limit: number; - } -} - -export type OprishRateLimitConf = InstanceRateLimits["oprish"]; -export type PandemoniumRateLimitConf = InstanceRateLimits["pandemonium"]; -export type EffisRateLimitConf = InstanceRateLimits["effis"]; \ No newline at end of file diff --git a/package.json b/package.json index 5044ca2..bd1620e 100644 --- a/package.json +++ b/package.json @@ -1,40 +1,28 @@ { "name": "eludris-api-types", - "version": "0.1.2", + "version": "0.2.0", "author": "teaishealthy", "license": "MIT", "exports": { - "pandemonium": { - "import": "./pandemonium/index.mjs", - "require": "./pandemonium/index.js", - "types": "./pandemonium/index.d.ts" - }, - "oprish": { - "import": "./oprish/index.mjs", - "require": "./oprish/index.js", - "types": "./oprish/index.d.ts" - }, - "effis": { - "import": "./effis/index.mjs", - "require": "./effis/index.js", - "types": "./effis/index.d.ts" + "v0.3.3": { + "import": "./dist/v0.3.3.mjs", + "require": "./pandemonium/v0.3.3.js", + "types": "./dist/v0.3.3.d.ts" } }, "devDependencies": { + "@types/node": "^20.2.5", "gen-esm-wrapper": "^1.1.3", - "npm-run-all": "^4.1.5", "rimraf": "^3.0.2", + "tsx": "^3.12.7", "typescript": "^4.9.4" }, "scripts": { "dev": "tsc -w", - "clean": "rimraf {pandemonium,oprish,effis}/**/*.{js,mjs,d.ts,*map}", - "build": "tsc && run-s esm:*", - "esm:pandemonium": "gen-esm-wrapper pandemonium/index.js pandemonium/index.mjs", - "esm:oprish": "gen-esm-wrapper oprish/index.js oprish/index.mjs", - "esm:effis": "gen-esm-wrapper effis/index.js effis/index.mjs" + "clean": "rimraf dist", + "build": "tsc && find dist -type f -name \"*.js\" | xargs -I {} gen-esm-wrapper {} {}.mjs" }, "files": [ - "{pandemonium,oprish,effis}/*.{js,mjs,d.ts,*map}" + "0.3.3/*.{js,mjs,d.ts,*map}" ] } diff --git a/pandemonium/index.ts b/pandemonium/index.ts deleted file mode 100644 index 9ad51e2..0000000 --- a/pandemonium/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -export enum GatewayOp { - PING = "PING", - PONG = "PONG", - MESSAGE_CREATE = "MESSAGE_CREATE", -} - -export interface Ping { - op: GatewayOp.PING; -} - -export interface Pong { - op: GatewayOp.PONG; -} - -export interface MessageCreate { - op: GatewayOp.MESSAGE_CREATE; - d: { - author: string; - content: string; - }; -} - -export type IncomingMessage = Pong | MessageCreate; -export type OutgoingMessage = Ping; diff --git a/src/v0.3.3.ts b/src/v0.3.3.ts new file mode 100644 index 0000000..fc21aa6 --- /dev/null +++ b/src/v0.3.3.ts @@ -0,0 +1,517 @@ +// This file was @generated by typegen +export type FileMetadata = Text | Image | Video | Other; + +export interface Text { + type: "Text"; +} + +export interface Image { + type: "Image"; + width: number | null; + height: number | null; +} + +export interface Video { + type: "Video"; + width: number | null; + height: number | null; +} + +export interface Other { + type: "Other"; +} +/** Represents information about the connected Eludris instance. + +----- + +### Example + +```json +{ + "instance_name": "eludris", + "description": "The *almost* official Eludris instance - ooliver.", + "version": "0.3.2", + "message_limit": 2000, + "oprish_url": "https://api.eludris.gay", + "pandemonium_url": "wss://ws.eludris.gay/", + "effis_url": "https://cdn.eludris.gay", + "file_size": 20000000, + "attachment_file_size": 25000000, + "rate_limits": { + "oprish": { + "info": { + "reset_after": 5, + "limit": 2 + }, + "message_create": { + "reset_after": 5, + "limit": 10 + }, + "rate_limits": { + "reset_after": 5, + "limit": 2 + } + }, + "pandemonium": { + "reset_after": 10, + "limit": 5 + }, + "effis": { + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } + } + } +} +``` */ +export interface InstanceInfo { + /** The name of the instance. */ + instance_name: string; + /** The description of the instance. + + This is between 1 and 2048 characters long. */ + description: string | null; + /** The Eludris version the instance is running. */ + version: string; + /** The maximum length of a message's content. */ + message_limit: number; + /** The URL of the instance's Oprish (REST API) endpoint. */ + oprish_url: string; + /** The URL of the instance's Pandemonium (WebSocket API) endpoint. */ + pandemonium_url: string; + /** The URL of the instance's Effis (CDN) endpoint. */ + effis_url: string; + /** The maximum file size (in bytes) of an asset. */ + file_size: number; + /** The maximum file size (in bytes) of an attachment. */ + attachment_file_size: number; + /** The rate limits that apply to the connected Eludris instance. + + This is not present if the `rate_limits` query parameter is not set. */ + rate_limits: InstanceRateLimits | null; +} +/** Represents a file stored on Effis. + +----- + +### Example + +```json +{ + "id": 2195354353667, + "name": "das_ding.png", + "bucket": "attachments", + "metadata": { + "type": "image", + "width": 1600, + "height": 1600 + } +} +``` */ +export interface FileData { + /** The ID of the file. */ + id: number; + /** The name of the file. */ + name: string; + /** The bucket the file is stored in. */ + bucket: string; + /** If the file is spoilered. */ + spoiler: boolean; + /** The {@link FileMetadata} of the file. */ + metadata: FileMetadata; +} +/** The message payload. + +----- + +### Example + +```json +{ + "author": "Not a weeb", + "content": "Hello, World!" +} +``` */ +export interface Message { + /** The author of message. This field has to be between 2 and 32 characters long. + + The author will be trimmed from leading and trailing whitespace. */ + author: string; + /** The content of the message. This field has to be at-least 2 characters long. The upper limit + is the instance's {@link InstanceInfo} `message_limit`. + + The content will be trimmed from leading and trailing whitespace. */ + content: string; +} +/** Represents a single rate limit for Effis. + +----- + +### Example + +```json +{ + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 +} +``` */ +export interface EffisRateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; + /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ + file_size_limit: number; +} +/** Represents a single rate limit. + +----- + +### Example + +```json +{ + "reset_after": 60, + "limit": 30 +} +``` */ +export interface RateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; +} +/** Represents all rate limits that apply to the connected Eludris instance. + +----- + +### Example +```json +{ + "oprish": { + "info": { + "reset_after": 5, + "limit": 2 + }, + "message_create": { + "reset_after": 5, + "limit": 10 + }, + "rate_limits": { + "reset_after": 5, + "limit": 2 + } + }, + "pandemonium": { + "reset_after": 10, + "limit": 5 + }, + "effis": { + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } + } +} +``` */ +export interface InstanceRateLimits { + /** Rate limits for Oprish (The REST API). */ + oprish: OprishRateLimits; + /** Rate limits for Pandemonium (The WebSocket API). */ + pandemonium: RateLimitConf; + /** Rate limits for Effis (The CDN). */ + effis: EffisRateLimits; +} +export type ServerPayload = Pong | RateLimit | Hello | MessageCreate; +/** Rate limits that apply to Oprish (The REST API). + +----- + +### Example + +```json +{ + "get_instance_info": { + "reset_after": 5, + "limit": 2 + }, + "create_message": { + "reset_after": 5, + "limit": 10 + } +} +``` */ +export interface OprishRateLimits { + /** Rate limits for the {@link get_instance_info} endpoint. */ + get_instance_info: RateLimitConf; + /** Rate limits for the {@link create_message} endpoint. */ + create_message: RateLimitConf; +} +/** Rate limits that apply to Effis (The CDN). + +----- + +### Example + +```json +{ + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } +} +``` */ +export interface EffisRateLimits { + /** Rate limits for the asset buckets. */ + assets: EffisRateLimitConf; + /** Rate limits for the attachment bucket. */ + attachments: EffisRateLimitConf; + /** Rate limits for the file fetching endpoints. */ + fetch_file: RateLimitConf; +} +/** The data format for uploading a file. + +This is a `multipart/form-data` form. + +----- + +### Example + +```sh +curl \ + -F file=@trolley.mp4 \ + -F spoiler=true \ + https://cdn.eludris.gay/attachments/ +``` */ +export interface FileUpload { + file: unknown; + spoiler: boolean; +} +/** A {@link ClientPayload} `PING` payload response. + +----- + +### Example + +```json +{ + "op": "PONG" +} +``` */ +export interface Pong { + op: "PONG"; +} +/** The event sent when the client gets gateway rate limited. + +The client is supposed to wait `wait` milliseconds before sending any more events, +otherwise they are disconnected. + +----- + +### Example + +```json +{ + "op": "RATE_LIMIT", + "d": { + "wait": 1010 // 1.01 seconds + } +} +``` */ +export interface RateLimit { + op: "RATE_LIMIT"; + wait: number; +} +/** The payload sent by the server when you initiate a new gateway connection. + +----- + +### Example + +```json +{ + "op": "HELLO", + "d": { + "heartbeat_interval": 45000, + "instance_info": { + "instance_name": "EmreLand", + "description": "More based than Oliver's instance (trust)", + "version": "0.3.3", + "message_limit": 2048, + "oprish_url": "https://example.com", + "pandemonium_url": "https://example.com", + "effis_url": "https://example.com", + "file_size": 20000000, + "attachment_file_size": 100000000 + }, + "rate_limit": { + "reset_after": 10, + "limit": 5 + } + } +} +``` */ +export interface Hello { + op: "HELLO"; + heartbeat_interval: number; + instance_info: InstanceInfo; + rate_limit: RateLimitConf; +} +/** The event sent when the client receives a {@link Message}. + +----- + +### Example + +```json +{ + "op": "MESSAGE_CREATE", + "d": { + "author": "A Certain Woo", + "content": "Woo!" + } +} +``` */ +export interface MessageCreate { + op: "MESSAGE_CREATE"; + d: Message; +} +/** Shared fields between all error response variants. */ +export interface SharedErrorData { + /** The HTTP status of the error. */ + status: number; + /** A brief explanation of the error. */ + message: string; +} +export type ClientPayload = Ping; +/** The payload the client is supposed to periodically send the server to not get disconnected. + +The interval where these pings are supposed to be sent can be found in the `HELLO` payload +of the {@link ServerPayload} enum. + +----- + +> **Note** +> +> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, +`RAND` being a random floating number between 0 and 1. +> +> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. + +### Example + +```json +> {"op":"PING"} +< {"op":"PONG"} +``` */ +export interface Ping { + op: "PING"; +} +export type ErrorResponse = RateLimited | Validation | NotFound | Server; +/** The error when a client is rate limited. + +------ + +### Example + +```json +{ + "type": "RATE_LIMITED", + "status": 429, + "message": "You have been rate limited", + "retry_after": 1234 +} +``` */ +export interface RateLimited extends SharedErrorData { + type: "RATE_LIMITED"; + retry_after: number; +} +/** The error when a request a client sends is incorrect and fails validation. + +----- + +### Example + +```json +{ + "type": "VALIDATION", + "status": 422, + "message": "Invalid request", + "value_name": "author", + "info": "author name is a bit too cringe" +} +``` */ +export interface Validation extends SharedErrorData { + type: "VALIDATION"; + value_name: string; + info: string; +} +/** The error when a client requests a resource that does not exist. + +----- + +### Example + +```json +{ + "type": "NOT_FOUND", + "status": 404, + "message": "The requested resource could not be found" +} +``` */ +export interface NotFound extends SharedErrorData { + type: "NOT_FOUND"; +} +/** The error when the server fails to process a request. + +Getting this error means that it's the server's fault and not the client that the request +failed. + +----- + +### Example + +```json +{ + "type": "SERVER", + "status": 500, + "message": "Server encountered an unexpected error", + "info": "Server got stabbed 28 times" +} +``` */ +export interface Server extends SharedErrorData { + type: "SERVER"; + info: string; +} diff --git a/tsconfig.json b/tsconfig.json index 35424e5..3bf0b7f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,14 +7,14 @@ "noUnusedParameters": true, "sourceMap": true, "declaration": true, + "outDir": "./dist", "declarationMap": true, "noUnusedLocals": true, "removeComments": false, "target": "ES2020", - "importsNotUsedAsValues": "error", "strictNullChecks": true, "preserveConstEnums": true, "exactOptionalPropertyTypes": true }, - "include": ["pandemonium", "oprish", "effis"] + "include": ["src/**/*"], } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 3c65ab2..2aea67a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,12 +2,144 @@ # yarn lockfile v1 -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" +"@esbuild-kit/cjs-loader@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.2.tgz#cb4dde00fbf744a68c4f20162ea15a8242d0fa54" + integrity sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg== + dependencies: + "@esbuild-kit/core-utils" "^3.0.0" + get-tsconfig "^4.4.0" + +"@esbuild-kit/core-utils@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@esbuild-kit/core-utils/-/core-utils-3.1.0.tgz#49945d533dbd5e1b7620aa0fc522c15e6ec089c5" + integrity sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw== + dependencies: + esbuild "~0.17.6" + source-map-support "^0.5.21" + +"@esbuild-kit/esm-loader@^2.5.5": + version "2.5.5" + resolved "https://registry.yarnpkg.com/@esbuild-kit/esm-loader/-/esm-loader-2.5.5.tgz#b82da14fcee3fc1d219869756c06f43f67d1ca71" + integrity sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw== + dependencies: + "@esbuild-kit/core-utils" "^3.0.0" + get-tsconfig "^4.4.0" + +"@esbuild/android-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" + integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== + +"@esbuild/android-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" + integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== + +"@esbuild/android-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" + integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== + +"@esbuild/darwin-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" + integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== + +"@esbuild/darwin-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" + integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== + +"@esbuild/freebsd-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" + integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== + +"@esbuild/freebsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" + integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== + +"@esbuild/linux-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" + integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== + +"@esbuild/linux-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" + integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== + +"@esbuild/linux-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" + integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== + +"@esbuild/linux-loong64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" + integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== + +"@esbuild/linux-mips64el@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" + integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== + +"@esbuild/linux-ppc64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" + integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== + +"@esbuild/linux-riscv64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" + integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== + +"@esbuild/linux-s390x@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" + integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== + +"@esbuild/linux-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" + integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== + +"@esbuild/netbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" + integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== + +"@esbuild/openbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" + integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== + +"@esbuild/sunos-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" + integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== + +"@esbuild/win32-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" + integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== + +"@esbuild/win32-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" + integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== + +"@esbuild/win32-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" + integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== + +"@types/node@^20.2.5": + version "20.2.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" + integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== assert@^1.4.1: version "1.5.0" @@ -17,11 +149,6 @@ assert@^1.4.1: object-assign "^4.1.1" util "0.10.3" -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -35,158 +162,53 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -chalk@^2.4.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.19.0, es-abstract@^1.20.4: - version "1.21.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.0.tgz#dd1b69ea5bfc3c27199c9753efd4de015102c252" - integrity sha512-GUGtW7eXQay0c+PRq0sGIKSdaBorfVqsCMhGHo4elP7YVqZu9nCZS4UkK4gv71gOWNMra/PaSKD3ao1oWExO0g== - dependencies: - call-bind "^1.0.2" - es-set-tostringtag "^2.0.0" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.4" - is-array-buffer "^3.0.0" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.2" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-set-tostringtag@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" - integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - has-tostringtag "^1.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" +esbuild@~0.17.6: + version "0.17.19" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" + integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== + optionalDependencies: + "@esbuild/android-arm" "0.17.19" + "@esbuild/android-arm64" "0.17.19" + "@esbuild/android-x64" "0.17.19" + "@esbuild/darwin-arm64" "0.17.19" + "@esbuild/darwin-x64" "0.17.19" + "@esbuild/freebsd-arm64" "0.17.19" + "@esbuild/freebsd-x64" "0.17.19" + "@esbuild/linux-arm" "0.17.19" + "@esbuild/linux-arm64" "0.17.19" + "@esbuild/linux-ia32" "0.17.19" + "@esbuild/linux-loong64" "0.17.19" + "@esbuild/linux-mips64el" "0.17.19" + "@esbuild/linux-ppc64" "0.17.19" + "@esbuild/linux-riscv64" "0.17.19" + "@esbuild/linux-s390x" "0.17.19" + "@esbuild/linux-x64" "0.17.19" + "@esbuild/netbsd-x64" "0.17.19" + "@esbuild/openbsd-x64" "0.17.19" + "@esbuild/sunos-x64" "0.17.19" + "@esbuild/win32-arm64" "0.17.19" + "@esbuild/win32-ia32" "0.17.19" + "@esbuild/win32-x64" "0.17.19" fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== gen-esm-wrapper@^1.1.3: version "1.1.3" @@ -195,22 +217,10 @@ gen-esm-wrapper@^1.1.3: dependencies: is-valid-identifier "^2.0.2" -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" +get-tsconfig@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.5.0.tgz#6d52d1c7b299bd3ee9cd7638561653399ac77b0f" + integrity sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ== glob@^7.1.3: version "7.2.3" @@ -224,71 +234,6 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globalthis@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" - integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== - dependencies: - define-properties "^1.1.3" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.1.2: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hosted-git-info@^2.1.4: - version "2.8.9" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" - integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -307,115 +252,6 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== -internal-slot@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3" - integrity sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ== - dependencies: - get-intrinsic "^1.1.3" - has "^1.0.3" - side-channel "^1.0.4" - -is-array-buffer@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.1.tgz#deb1db4fcae48308d54ef2442706c0393997052a" - integrity sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-typed-array "^1.1.10" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-valid-identifier@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-valid-identifier/-/is-valid-identifier-2.0.2.tgz#146d9dbf29821b8118580b039d2203aa4bd1da4b" @@ -423,100 +259,18 @@ is-valid-identifier@^2.0.2: dependencies: assert "^1.4.1" -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== - -minimatch@^3.0.4, minimatch@^3.1.1: +minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -npm-run-all@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" - integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== - dependencies: - ansi-styles "^3.2.1" - chalk "^2.4.1" - cross-spawn "^6.0.5" - memorystream "^0.3.1" - minimatch "^3.0.4" - pidtree "^0.3.0" - read-pkg "^3.0.0" - shell-quote "^1.6.1" - string.prototype.padend "^3.0.0" - object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -524,73 +278,11 @@ once@^1.3.0: dependencies: wrappy "1" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -pidtree@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" - integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA== - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -resolve@^1.10.0: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -598,140 +290,35 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== +source-map-support@^0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" - -"semver@2 || 3 || 4 || 5", semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" + buffer-from "^1.0.0" + source-map "^0.6.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - -shell-quote@^1.6.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" - integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" - integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== - -string.prototype.padend@^3.0.0: - version "3.1.4" - resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz#2c43bb3a89eb54b6750de5942c123d6c98dd65b6" - integrity sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== +tsx@^3.12.7: + version "3.12.7" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-3.12.7.tgz#b3b8b0fc79afc8260d1e14f9e995616c859a91e9" + integrity sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== - dependencies: - call-bind "^1.0.2" - for-each "^0.3.3" - is-typed-array "^1.1.9" + "@esbuild-kit/cjs-loader" "^2.4.2" + "@esbuild-kit/core-utils" "^3.0.0" + "@esbuild-kit/esm-loader" "^2.5.5" + optionalDependencies: + fsevents "~2.3.2" typescript@^4.9.4: version "4.9.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" @@ -739,44 +326,6 @@ util@0.10.3: dependencies: inherits "2.0.1" -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 4df09eefc7f49549321fafc8c6514f3be8ade6cd Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Sun, 25 Jun 2023 13:58:41 +0200 Subject: [PATCH 02/18] feat(autotype): automatic version detection --- autotype/main.ts | 67 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/autotype/main.ts b/autotype/main.ts index 73e1f76..bfb75cc 100644 --- a/autotype/main.ts +++ b/autotype/main.ts @@ -9,6 +9,8 @@ import { EnumVariant, } from "./types"; import { argv } from "process"; +import { existsSync } from "fs"; +import { createInterface } from "readline/promises"; const converters: Map string> = new Map([ [/^String$/, (_) => "string"], @@ -20,6 +22,7 @@ const converters: Map string> = new Map([ [/^bool$/, (_) => "boolean"], [/^TempFile$/, (_) => "unknown"], [/^Box<.*>/, (str) => convertType(str.replace(/^Box<(.+)>$/, "$1"))], + [/^IpAddr$/, (_) => "string"], ]); function switchCase(content: string, newCase: string | null): string { @@ -55,7 +58,9 @@ function fieldToType(field: FieldInfo): string { if (field.doc) { doc = `/** ${convertDoc(field.doc)} */\n`; } - return `${doc}${field.name}: ${convertType(field.field_type)}`; + return `${doc}${field.name}${field.ommitable ? "?" : ""}: ${convertType( + field.field_type + )}`; } function handleRoute(route: ItemInfo, routes: string[]) { @@ -130,20 +135,21 @@ async function handleEnumVariant( } } } else if (variant.type === VariantType.Struct) { - if (item.tag) { - if (variant.doc) { - doc = `/** ${convertDoc(variant.doc)} */`; - } - typeStr += ` ${item.tag}: "${switchCase( - variant.name, - item.rename_all - )}"\n`; - for (const field of variant.fields) { - if (field.flattened) { - bases.push(convertType(field.field_type)); - } else { - typeStr += ` ${field.name}: ${convertType(field.field_type)}\n`; - } + if (!item.tag) { + return []; + } + if (variant.doc) { + doc = `/** ${convertDoc(variant.doc)} */`; + } + typeStr += ` ${item.tag}: "${switchCase( + variant.name, + item.rename_all + )}"\n`; + for (const field of variant.fields) { + if (field.flattened) { + bases.push(convertType(field.field_type)); + } else { + typeStr += fieldToType(field) + "\n"; } } } @@ -173,17 +179,34 @@ async function handleStruct(fh: FileHandle, info: ItemInfo) { } async function main(inventoryIndex: string, output: string) { - let fh = await open(output, "w"); - await fh.write("// This file was @generated by typegen\n"); - let routes: string[] = []; - const inventory: string[] = await ( - await fetch(`${inventoryIndex}/index.json`) - ).json(); + const inventory: { + version: string; + items: string[]; + } = await (await fetch(`${inventoryIndex}/index.json`)).json(); + console.log(inventory); + + if (existsSync(`${output}/v${inventory["version"]}.ts`)) { + console.log( + `[INFO] v${inventory["version"]}.ts already exists, do you want to overwrite it?` + ); + const rl = createInterface({ + input: process.stdin, + output: process.stdout, + }); + const answer = await rl.question("Overwrite? (y/n) "); + rl.close(); + if (answer !== "y") { + return; + } + } + + let fh = await open(`${output}/v${inventory["version"]}.ts`, "w"); + await fh.write("// This file was @generated by typegen\n"); await Promise.all( - inventory.map((url) => { + inventory.items.map((url) => { buildTypes(fh, `${inventoryIndex}/${url}`, routes); }) ); From 3b25b1f1da7c09d3c6915c7046e02d90a60672ed Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Sun, 25 Jun 2023 13:58:47 +0200 Subject: [PATCH 03/18] chore: update types --- src/v0.3.3.ts | 654 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 438 insertions(+), 216 deletions(-) diff --git a/src/v0.3.3.ts b/src/v0.3.3.ts index fc21aa6..50bff00 100644 --- a/src/v0.3.3.ts +++ b/src/v0.3.3.ts @@ -1,25 +1,335 @@ // This file was @generated by typegen -export type FileMetadata = Text | Image | Video | Other; +export type ErrorResponse = + | Unauthorized + | Forbidden + | NotFound + | Conflict + | Validation + | RateLimited + | Server; +/** The error when the client is missing authorization. This error often occurs when the user +doesn't pass in the required authentication or passes in invalid credentials. -export interface Text { - type: "Text"; +----- + +### Example + +```json +{ + "type": "UNAUTHORIZED", + "status": 401, + "message": "The user is missing authentication or the passed credentials are invalid" +} +``` */ +export interface Unauthorized extends SharedErrorData { + type: "UNAUTHORIZED"; } +/** The error when a client *has* been succesfully authorized but does not have the required +permissions to execute an action. -export interface Image { - type: "Image"; - width: number | null; - height: number | null; +----- + +### Example + +```json +{ + "type": "FORBIDDEN", + "status": 403, + "message": "The user is missing the requried permissions to execute this action", +} +``` */ +export interface Forbidden extends SharedErrorData { + type: "FORBIDDEN"; } +/** The error when a client requests a resource that does not exist. -export interface Video { - type: "Video"; - width: number | null; - height: number | null; +----- + +### Example + +```json +{ + "type": "NOT_FOUND", + "status": 404, + "message": "The requested resource could not be found" +} +``` */ +export interface NotFound extends SharedErrorData { + type: "NOT_FOUND"; } +/** The error when a client's request causes a conflict, usually when they're trying to create +something that already exists. -export interface Other { - type: "Other"; +----- + +### Example + +```json +{ + "type": "CONFLICT", + "status": 409, + "message": "The request couldn't be completed due to conflicting with other data on the server", + "item": "username", +} +``` */ +export interface Conflict extends SharedErrorData { + type: "CONFLICT"; + /** The conflicting item. */ + item: string; +} +/** The error when a request a client sends is incorrect and fails validation. + +----- + +### Example + +```json +{ + "type": "VALIDATION", + "status": 422, + "message": "Invalid request", + "value_name": "author", + "info": "author name is a bit too cringe" +} +``` */ +export interface Validation extends SharedErrorData { + type: "VALIDATION"; + /** The name of the value that failed validation. */ + value_name: string; + /** Extra information about what went wrong. */ + info: string; +} +/** The error when a client is rate limited. + +----- + +### Example + +```json +{ + "type": "RATE_LIMITED", + "status": 429, + "message": "You have been rate limited", + "retry_after": 1234 +} +``` */ +export interface RateLimited extends SharedErrorData { + type: "RATE_LIMITED"; + /** The amount of milliseconds you're still rate limited for. */ + retry_after: number; +} +/** The error when the server fails to process a request. + +Getting this error means that it's the server's fault and not the client that the request +failed. + +----- + +### Example + +```json +{ + "type": "SERVER", + "status": 500, + "message": "Server encountered an unexpected error", + "info": "Server got stabbed 28 times" +} +``` */ +export interface Server extends SharedErrorData { + type: "SERVER"; + /** Extra information about what went wrong. */ + info: string; +} +export type ClientPayload = Ping; +/** The payload the client is supposed to periodically send the server to not get disconnected. + +The interval where these pings are supposed to be sent can be found in the `HELLO` payload +of the {@link ServerPayload} enum. + +----- + +> **Note** +> +> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, +`RAND` being a random floating number between 0 and 1. +> +> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. + +### Example + +```json +> {"op":"PING"} +< {"op":"PONG"} +``` */ +export interface Ping { + op: "PING"; +} +/** The SessionCreate payload. + +This is used to authenticate a user and obtain a token to interface with the API. + +----- + +### Example + +```json +{ + "indentifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" +} +``` */ +export interface SessionCreate { + /** The session user's identifier. This can be either their email or username. */ + identifier: string; + /** The session user's password. */ + password: string; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; +} +/** The UserCreate payload. + +This is used when a user is initially first created. For authentication payloads check +{@link SessionCreate}. + +----- + +### Examples + +```json +{ + "username": "yendri", + "email": "yendri@llamoyendri.io", + "password": "autentícame por favor" // don't actually use this as a password +} +``` */ +export interface UserCreate { + /** The user's name. + + This is different to their `display_name` as it denotes how they're more formally + referenced by the API. */ + username: string; + /** The user's email. */ + email: string; + /** The user's password. */ + password: string; } +/** Rate limits that apply to Oprish (The REST API). + +----- + +### Example + +```json +{ + "get_instance_info": { + "reset_after": 5, + "limit": 2 + }, + "create_message": { + "reset_after": 5, + "limit": 10 + } +} +``` */ +export interface OprishRateLimits { + /** Rate limits for the {@link get_instance_info} endpoint. */ + get_instance_info: RateLimitConf; + /** Rate limits for the {@link create_message} endpoint. */ + create_message: RateLimitConf; +} +/** The session payload. + +The user should ideally have one session for every client they have on every device. + +----- + +### Example + +```json +{ + "id": 2312155037697, + "user_id": 2312155693057, + "platform": "linux", + "client": "pilfer" +} +``` */ +export interface Session { + /** The session's ID. */ + id: number; + /** The session user's ID. */ + user_id: number; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; + /** The session's creation IP address. */ + ip: string; +} +/** The data format for uploading a file. + +This is a `multipart/form-data` form. + +----- + +### Example + +```sh +curl \ + -F file=@trolley.mp4 \ + -F spoiler=true \ + https://cdn.eludris.gay/attachments/ +``` */ +export interface FileUpload { + file: unknown; + spoiler: boolean; +} +/** The user payload. + +----- + +### Example + +```json +{ + "id": 48615849987333, + "username": "yendri", + "display_name": "Nicolas", + "social_credit": -69420, + "status": "ayúdame por favor", + "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", + "avatar": 2255112175647, + "banner": 2255049523230, + "badges": 0, + "permissions": 0 +} +``` */ +export interface User { + /** The user's ID. */ + id: number; + /** The user's username. This field has to be between 2 and 32 characters long. */ + username: string; + /** The user's display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null; + /** The user's social credit score. */ + social_credit: number; + /** The user's status. This field cannot be more than 128 characters long. */ + status?: string | null; + /** The user's bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null; + /** The user's avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null; + /** The user's banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null; + /** The user's badges as a bitfield. */ + badges: number; + /** The user's instance-wide permissions as a bitfield. */ + permissions: number; +} +export type FileMetadata = Text | Image | Video | Other; /** Represents information about the connected Eludris instance. ----- @@ -76,13 +386,13 @@ export interface Other { } ``` */ export interface InstanceInfo { - /** The name of the instance. */ + /** The instance's name. */ instance_name: string; - /** The description of the instance. + /** The instance's description. This is between 1 and 2048 characters long. */ description: string | null; - /** The Eludris version the instance is running. */ + /** The instance's Eludris version. */ version: string; /** The maximum length of a message's content. */ message_limit: number; @@ -99,39 +409,33 @@ export interface InstanceInfo { /** The rate limits that apply to the connected Eludris instance. This is not present if the `rate_limits` query parameter is not set. */ - rate_limits: InstanceRateLimits | null; + rate_limits?: InstanceRateLimits | null; } -/** Represents a file stored on Effis. ------ +export interface Text { + type: "Text"; +} -### Example +export interface Image { + type: "Image"; + /** The image's width in pixels. */ + width?: number | null; + /** The image's height in pixels. */ + height?: number | null; +} -```json -{ - "id": 2195354353667, - "name": "das_ding.png", - "bucket": "attachments", - "metadata": { - "type": "image", - "width": 1600, - "height": 1600 - } +export interface Video { + type: "Video"; + /** The video's width in pixels. */ + width?: number | null; + /** The video's height in pixels. */ + height?: number | null; } -``` */ -export interface FileData { - /** The ID of the file. */ - id: number; - /** The name of the file. */ - name: string; - /** The bucket the file is stored in. */ - bucket: string; - /** If the file is spoilered. */ - spoiler: boolean; - /** The {@link FileMetadata} of the file. */ - metadata: FileMetadata; + +export interface Other { + type: "Other"; } -/** The message payload. +/** The response to a {@link SessionCreate}. ----- @@ -139,20 +443,20 @@ export interface FileData { ```json { - "author": "Not a weeb", - "content": "Hello, World!" + "token": "", + "session": { + "indentifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" + } } ``` */ -export interface Message { - /** The author of message. This field has to be between 2 and 32 characters long. - - The author will be trimmed from leading and trailing whitespace. */ - author: string; - /** The content of the message. This field has to be at-least 2 characters long. The upper limit - is the instance's {@link InstanceInfo} `message_limit`. - - The content will be trimmed from leading and trailing whitespace. */ - content: string; +export interface SessionCreated { + /** The session's token. This can be used by the user to properly interface with the API. */ + token: string; + /** The session object that was created. */ + session: Session; } /** Represents a single rate limit for Effis. @@ -175,7 +479,15 @@ export interface EffisRateLimitConf { /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ file_size_limit: number; } -/** Represents a single rate limit. +/** Shared fields between all error response variants. */ +export interface SharedErrorData { + /** The HTTP status of the error. */ + status: number; + /** A brief explanation of the error. */ + message: string; +} +export type ServerPayload = Pong | RateLimit | Hello | MessageCreate; +/** Represents a file stored on Effis. ----- @@ -183,15 +495,27 @@ export interface EffisRateLimitConf { ```json { - "reset_after": 60, - "limit": 30 + "id": 2195354353667, + "name": "das_ding.png", + "bucket": "attachments", + "metadata": { + "type": "image", + "width": 1600, + "height": 1600 + } } ``` */ -export interface RateLimitConf { - /** The amount of seconds after which the rate limit resets. */ - reset_after: number; - /** The amount of requests that can be made within the `reset_after` interval. */ - limit: number; +export interface FileData { + /** The file's ID. */ + id: number; + /** The file's name. */ + name: string; + /** The bucket the file is stored in. */ + bucket: string; + /** Whether the file is marked as a spoiler. */ + spoiler?: boolean; + /** The {@link FileMetadata} of the file. */ + metadata: FileMetadata; } /** Represents all rate limits that apply to the connected Eludris instance. @@ -237,39 +561,14 @@ export interface RateLimitConf { } ``` */ export interface InstanceRateLimits { - /** Rate limits for Oprish (The REST API). */ + /** The instance's Oprish rate limit information (The REST API). */ oprish: OprishRateLimits; - /** Rate limits for Pandemonium (The WebSocket API). */ + /** The instance's Pandemonium rate limit information (The WebSocket API). */ pandemonium: RateLimitConf; - /** Rate limits for Effis (The CDN). */ + /** The instance's Effis rate limit information (The CDN). */ effis: EffisRateLimits; } -export type ServerPayload = Pong | RateLimit | Hello | MessageCreate; -/** Rate limits that apply to Oprish (The REST API). - ------ - -### Example - -```json -{ - "get_instance_info": { - "reset_after": 5, - "limit": 2 - }, - "create_message": { - "reset_after": 5, - "limit": 10 - } -} -``` */ -export interface OprishRateLimits { - /** Rate limits for the {@link get_instance_info} endpoint. */ - get_instance_info: RateLimitConf; - /** Rate limits for the {@link create_message} endpoint. */ - create_message: RateLimitConf; -} -/** Rate limits that apply to Effis (The CDN). +/** Represents a single rate limit. ----- @@ -277,47 +576,15 @@ export interface OprishRateLimits { ```json { - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } -} -``` */ -export interface EffisRateLimits { - /** Rate limits for the asset buckets. */ - assets: EffisRateLimitConf; - /** Rate limits for the attachment bucket. */ - attachments: EffisRateLimitConf; - /** Rate limits for the file fetching endpoints. */ - fetch_file: RateLimitConf; + "reset_after": 60, + "limit": 30 } -/** The data format for uploading a file. - -This is a `multipart/form-data` form. - ------ - -### Example - -```sh -curl \ - -F file=@trolley.mp4 \ - -F spoiler=true \ - https://cdn.eludris.gay/attachments/ ``` */ -export interface FileUpload { - file: unknown; - spoiler: boolean; +export interface RateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; } /** A {@link ClientPayload} `PING` payload response. @@ -352,6 +619,7 @@ otherwise they are disconnected. ``` */ export interface RateLimit { op: "RATE_LIMIT"; + /** The amount of milliseconds you have to wait before the rate limit ends */ wait: number; } /** The payload sent by the server when you initiate a new gateway connection. @@ -385,8 +653,14 @@ export interface RateLimit { ``` */ export interface Hello { op: "HELLO"; + /** The amount of milliseconds your ping interval is supposed to be. */ heartbeat_interval: number; + /** The instance's info. + +This is the same payload you get from the {@link get_instance_info} payload without +ratelimits */ instance_info: InstanceInfo; + /** The pandemonium ratelimit info. */ rate_limit: RateLimitConf; } /** The event sent when the client receives a {@link Message}. @@ -408,57 +682,7 @@ export interface MessageCreate { op: "MESSAGE_CREATE"; d: Message; } -/** Shared fields between all error response variants. */ -export interface SharedErrorData { - /** The HTTP status of the error. */ - status: number; - /** A brief explanation of the error. */ - message: string; -} -export type ClientPayload = Ping; -/** The payload the client is supposed to periodically send the server to not get disconnected. - -The interval where these pings are supposed to be sent can be found in the `HELLO` payload -of the {@link ServerPayload} enum. - ------ - -> **Note** -> -> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, -`RAND` being a random floating number between 0 and 1. -> -> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. - -### Example - -```json -> {"op":"PING"} -< {"op":"PONG"} -``` */ -export interface Ping { - op: "PING"; -} -export type ErrorResponse = RateLimited | Validation | NotFound | Server; -/** The error when a client is rate limited. - ------- - -### Example - -```json -{ - "type": "RATE_LIMITED", - "status": 429, - "message": "You have been rate limited", - "retry_after": 1234 -} -``` */ -export interface RateLimited extends SharedErrorData { - type: "RATE_LIMITED"; - retry_after: number; -} -/** The error when a request a client sends is incorrect and fails validation. +/** The message payload. ----- @@ -466,38 +690,22 @@ export interface RateLimited extends SharedErrorData { ```json { - "type": "VALIDATION", - "status": 422, - "message": "Invalid request", - "value_name": "author", - "info": "author name is a bit too cringe" + "author": "Not a weeb", + "content": "Hello, World!" } ``` */ -export interface Validation extends SharedErrorData { - type: "VALIDATION"; - value_name: string; - info: string; -} -/** The error when a client requests a resource that does not exist. - ------ +export interface Message { + /** The message's author. This field has to be between 2 and 32 characters long. -### Example + The author will be trimmed from leading and trailing whitespace. */ + author: string; + /** The message's content. This field has to be at-least 2 characters long. The upper limit + is the instance's {@link InstanceInfo} `message_limit`. -```json -{ - "type": "NOT_FOUND", - "status": 404, - "message": "The requested resource could not be found" -} -``` */ -export interface NotFound extends SharedErrorData { - type: "NOT_FOUND"; + The content will be trimmed from leading and trailing whitespace. */ + content: string; } -/** The error when the server fails to process a request. - -Getting this error means that it's the server's fault and not the client that the request -failed. +/** Rate limits that apply to Effis (The CDN). ----- @@ -505,13 +713,27 @@ failed. ```json { - "type": "SERVER", - "status": 500, - "message": "Server encountered an unexpected error", - "info": "Server got stabbed 28 times" + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } } ``` */ -export interface Server extends SharedErrorData { - type: "SERVER"; - info: string; +export interface EffisRateLimits { + /** Rate limits for the asset buckets. */ + assets: EffisRateLimitConf; + /** Rate limits for the attachment bucket. */ + attachments: EffisRateLimitConf; + /** Rate limits for the file fetching endpoints. */ + fetch_file: RateLimitConf; } From 148059f7b853f2fe860abe4d19a618204e7454db Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Sun, 25 Jun 2023 14:13:09 +0200 Subject: [PATCH 04/18] fix: make types actually importable --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index bd1620e..eeb6ab4 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "eludris-api-types", - "version": "0.2.0", + "version": "0.2.1-2", "author": "teaishealthy", "license": "MIT", "exports": { - "v0.3.3": { + "./v0.3.3": { "import": "./dist/v0.3.3.mjs", - "require": "./pandemonium/v0.3.3.js", + "require": "./dist/v0.3.3.js", "types": "./dist/v0.3.3.d.ts" } }, @@ -23,6 +23,6 @@ "build": "tsc && find dist -type f -name \"*.js\" | xargs -I {} gen-esm-wrapper {} {}.mjs" }, "files": [ - "0.3.3/*.{js,mjs,d.ts,*map}" + "dist" ] } From d018c7d606119f97735ff5c1682c5d2352ac113d Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Thu, 27 Jul 2023 20:03:53 +0200 Subject: [PATCH 05/18] feat: add v0.4.0-alpha1 This will be removed once real v0.4 is here --- autotype/main.ts | 1 + package.json | 7 +- src/v0.4.0-alpha1.ts | 1068 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1075 insertions(+), 1 deletion(-) create mode 100644 src/v0.4.0-alpha1.ts diff --git a/autotype/main.ts b/autotype/main.ts index bfb75cc..07b8dee 100644 --- a/autotype/main.ts +++ b/autotype/main.ts @@ -23,6 +23,7 @@ const converters: Map string> = new Map([ [/^TempFile$/, (_) => "unknown"], [/^Box<.*>/, (str) => convertType(str.replace(/^Box<(.+)>$/, "$1"))], [/^IpAddr$/, (_) => "string"], + [/^Vec<.*>/, (str) => convertType(str.replace(/^Vec<(.+)>$/, "$1[]"))], ]); function switchCase(content: string, newCase: string | null): string { diff --git a/package.json b/package.json index eeb6ab4..49b8c0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eludris-api-types", - "version": "0.2.1-2", + "version": "0.2.1-3", "author": "teaishealthy", "license": "MIT", "exports": { @@ -8,6 +8,11 @@ "import": "./dist/v0.3.3.mjs", "require": "./dist/v0.3.3.js", "types": "./dist/v0.3.3.d.ts" + }, + "./v0.4.0-alpha1.ts": { + "import": "./dist/v0.4.0-alpha1.mjs", + "require": "./dist/v0.4.0-alpha1.js", + "types": "./dist/v0.4.0-alpha1.d.ts" } }, "devDependencies": { diff --git a/src/v0.4.0-alpha1.ts b/src/v0.4.0-alpha1.ts new file mode 100644 index 0000000..720f0da --- /dev/null +++ b/src/v0.4.0-alpha1.ts @@ -0,0 +1,1068 @@ +// This file was @generated by typegen +/** The data format for uploading a file. + +This is a `multipart/form-data` form. + +----- + +### Example + +```sh +curl \ + -F file=@trolley.mp4 \ + -F spoiler=true \ + https://cdn.eludris.gay/attachments/ +``` */ +export interface FileUpload { + file: unknown; + spoiler: boolean; +} +/** Represents a single rate limit. + +----- + +### Example + +```json +{ + "reset_after": 60, + "limit": 30 +} +``` */ +export interface RateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; +} +/** Rate limits that apply to Effis (The CDN). + +----- + +### Example + +```json +{ + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } +} +``` */ +export interface EffisRateLimits { + /** Rate limits for the asset buckets. */ + assets: EffisRateLimitConf; + /** Rate limits for the attachment bucket. */ + attachments: EffisRateLimitConf; + /** Rate limits for the file fetching endpoints. */ + fetch_file: RateLimitConf; +} +/** The ResetPassword payload. This is used when the user wants to reset their password using a +password reset code. + +----- + +### Example + +```json +{ + "code": 234567, + "email": "someemail@ma.il", + "password": "wow such security" +} +``` */ +export interface ResetPassword { + /** The password reset code the user got emailed. */ + code: number; + /** The user's email. */ + email: string; + /** The user's new password. */ + password: string; +} +/** The MessageCreate payload. This is used when you want to create a message using the REST API. + +----- + +### Example + +```json +{ + "content": "Hello, World!" +} +``` */ +export interface MessageCreate { + /** The message's content. This field has to be at-least 2 characters long. The upper limit + is the instance's {@link InstanceInfo} `message_limit`. + + The content will be trimmed from leading and trailing whitespace. */ + content: string; + _disguise?: MessageDisguise | null; +} +/** The DeleteCredentials payload. This is used in multiple places in the API to provide extra +credentials for deleting important user-related stuff. + +----- + +### Example + +```json +{ + "password": "wowsuchpassword" +} +``` */ +export interface PasswordDeleteCredentials { + password: string; +} +export type FileMetadata = Text | Image | Video | Other; +/** Represents information about the connected Eludris instance. + +----- + +### Example + +```json +{ + "instance_name": "eludris", + "description": "The *almost* official Eludris instance - ooliver.", + "version": "0.3.2", + "message_limit": 2000, + "oprish_url": "https://api.eludris.gay", + "pandemonium_url": "wss://ws.eludris.gay/", + "effis_url": "https://cdn.eludris.gay", + "file_size": 20000000, + "attachment_file_size": 25000000, + "rate_limits": { + "oprish": { + "info": { + "reset_after": 5, + "limit": 2 + }, + "message_create": { + "reset_after": 5, + "limit": 10 + }, + "rate_limits": { + "reset_after": 5, + "limit": 2 + } + }, + "pandemonium": { + "reset_after": 10, + "limit": 5 + }, + "effis": { + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } + } + } +} +``` */ +export interface InstanceInfo { + /** The instance's name. */ + instance_name: string; + /** The instance's description. + + This is between 1 and 2048 characters long. */ + description: string | null; + /** The instance's Eludris version. */ + version: string; + /** The maximum length of a message's content. */ + message_limit: number; + /** The URL of the instance's Oprish (REST API) endpoint. */ + oprish_url: string; + /** The URL of the instance's Pandemonium (WebSocket API) endpoint. */ + pandemonium_url: string; + /** The URL of the instance's Effis (CDN) endpoint. */ + effis_url: string; + /** The maximum file size (in bytes) of an asset. */ + file_size: number; + /** The maximum file size (in bytes) of an attachment. */ + attachment_file_size: number; + /** The instance's email address if any. */ + email_address?: string | null; + /** The rate limits that apply to the connected Eludris instance. + + This is not present if the `rate_limits` query parameter is not set. */ + rate_limits?: InstanceRateLimits | null; +} + +export interface Text { + type: "Text"; +} + +export interface Image { + type: "Image"; + /** The image's width in pixels. */ + width?: number | null; + /** The image's height in pixels. */ + height?: number | null; +} + +export interface Video { + type: "Video"; + /** The video's width in pixels. */ + width?: number | null; + /** The video's height in pixels. */ + height?: number | null; +} + +export interface Other { + type: "Other"; +} +/** The response to a {@link SessionCreate}. + +----- + +### Example + +```json +{ + "token": "", + "session": { + "indentifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" + } +} +``` */ +export interface SessionCreated { + /** The session's token. This can be used by the user to properly interface with the API. */ + token: string; + /** The session object that was created. */ + session: Session; +} +/** The CreatePasswordResetCode payload. This is used when a user wants to generate a code +to reset their password, most commonly because they forgot their old one. + +----- + +### Example + +```json +{ + "email": "someemail@ma.il" +} +``` */ +export interface CreatePasswordResetCode { + /** The user's email. */ + email: string; +} +/** A user's status. + +----- + +### Example + +```json +{ + "type": "BUSY", + "text": "ayúdame por favor", +} +``` */ +export interface Status { + type: StatusType; + text?: string | null; +} +/** The Message payload. This is returned when you're provided information about a pre-existing +message. + +----- + +### Example + +```json +{ + "author": { + "id": 48615849987333, + "username": "mlynar", + "social_credit": 9999. + "badges": 256, + "permissions": 8 + } + "content": "Hello, World!" +} +``` */ +export interface Message { + /** The message's author. */ + author: User; + /** There message's data. */ + message: MessageCreate; +} +export type ClientPayload = Ping | Authenticate; +/** The user payload. + +----- + +### Example + +```json +{ + "id": 48615849987333, + "username": "yendri", + "display_name": "Nicolas", + "social_credit": -69420, + "status": { + "type": "BUSY", + "text": "ayúdame por favor", + }, + "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", + "avatar": 2255112175647, + "banner": 2255049523230, + "badges": 0, + "permissions": 0 +} +``` */ +export interface User { + /** The user's ID. */ + id: number; + /** The user's username. This field has to be between 2 and 32 characters long. */ + username: string; + /** The user's display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null; + /** The user's social credit score. */ + social_credit: number; + /** The user's status. */ + status: Status; + /** The user's bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null; + /** The user's avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null; + /** The user's banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null; + /** The user's badges as a bitfield. */ + badges: number; + /** The user's instance-wide permissions as a bitfield. */ + permissions: number; + /** The user's email. This is only shown when the user queries their own data. */ + email?: string | null; + /** The user's verification status. This is only shown when the user queries their own data. */ + verified?: boolean | null; +} +export type ServerPayload = + | Pong + | RateLimit + | Hello + | Authenticated + | UserUpdate + | PresenceUpdate + | MessageCreate; +export type StatusType = Online | Offline | Idle | Busy; +/** Represents a single rate limit for Effis. + +----- + +### Example + +```json +{ + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 +} +``` */ +export interface EffisRateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; + /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ + file_size_limit: number; +} +/** Represents all rate limits that apply to the connected Eludris instance. + +----- + +### Example +```json +{ + "oprish": { + "info": { + "reset_after": 5, + "limit": 2 + }, + "message_create": { + "reset_after": 5, + "limit": 10 + }, + "rate_limits": { + "reset_after": 5, + "limit": 2 + } + }, + "pandemonium": { + "reset_after": 10, + "limit": 5 + }, + "effis": { + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } + } +} +``` */ +export interface InstanceRateLimits { + /** The instance's Oprish rate limit information (The REST API). */ + oprish: OprishRateLimits; + /** The instance's Pandemonium rate limit information (The WebSocket API). */ + pandemonium: RateLimitConf; + /** The instance's Effis rate limit information (The CDN). */ + effis: EffisRateLimits; +} +/** The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded +and won't affect the user. + +----- + +### Example + +```json +{ + "password": "authentícame por favor", + "username": "yendli", + "email": "yendli2@yemail.yom" +} +``` */ +export interface UpdateUser { + /** The user's current password for validation. */ + password: string; + /** The user's new username. */ + username?: string | null; + /** The user's new email. */ + email?: string | null; + /** The user's new password. */ + new_password?: string | null; +} +/** The UserCreate payload. + +This is used when a user is initially first created. For authentication payloads check +{@link SessionCreate}. + +----- + +### Example + +```json +{ + "username": "yendri",d + "email": "yendri@llamoyendri.io", + "password": "authentícame por favor" // don't actually use this as a password +} +``` */ +export interface UserCreate { + /** The user's name. + + This is different to their `display_name` as it denotes how they're more formally + referenced by the API. */ + username: string; + /** The user's email. */ + email: string; + /** The user's password. */ + password: string; +} +/** The SessionCreate payload. + +This is used to authenticate a user and obtain a token to interface with the API. + +----- + +### Example + +```json +{ + "identifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" +} +``` */ +export interface SessionCreate { + /** The session user's identifier. This can be either their email or username. */ + identifier: string; + /** The session user's password. */ + password: string; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; +} +/** The payload the client is supposed to periodically send the server to not get disconnected. + +The interval where these pings are supposed to be sent can be found in the `HELLO` payload +of the {@link ServerPayload} enum. + +----- + +> **Note** +> +> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, +`RAND` being a random floating number between 0 and 1. +> +> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. + +### Example + +```json +{ + "op": "PING" +} +``` */ +export interface Ping { + op: "PING"; +} +/** The first payload the client is supposed to send. The data of this payload is expected to +be a session token obtained from the {@link create_session} route. + +----- + +### Example + +```json +{ + "op": "AUTHENTICATE", + "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) +} +``` */ +export interface Authenticate { + op: "AUTHENTICATE"; + d: string; +} +/** A {@link ClientPayload} `PING` payload response. + +----- + +### Example + +```json +{ + "op": "PONG" +} +``` */ +export interface Pong { + op: "PONG"; +} +/** The payload sent when the client gets gateway rate limited. + +The client is supposed to wait `wait` milliseconds before sending any more events, +otherwise they are disconnected. + +----- + +### Example + +```json +{ + "op": "RATE_LIMIT", + "d": { + "wait": 1010 // 1.01 seconds + } +} +``` */ +export interface RateLimit { + op: "RATE_LIMIT"; + /** The amount of milliseconds you have to wait before the rate limit ends */ + wait: number; +} +/** The payload sent by the server when you initiate a new gateway connection. + +----- + +### Example + +```json +{ + "op": "HELLO", + "d": { + "heartbeat_interval": 45000, + "instance_info": { + "instance_name": "EmreLand", + "description": "More based than Oliver's instance (trust)", + "version": "0.3.3", + "message_limit": 2048, + "oprish_url": "https://example.com", + "pandemonium_url": "https://example.com", + "effis_url": "https://example.com", + "file_size": 20000000, + "attachment_file_size": 100000000 + }, + "rate_limit": { + "reset_after": 10, + "limit": 5 + } + } +} +``` */ +export interface Hello { + op: "HELLO"; + /** The amount of milliseconds your ping interval is supposed to be. */ + heartbeat_interval: number; + /** The instance's info. + +This is the same payload you get from the {@link get_instance_info} payload without +ratelimits */ + instance_info: InstanceInfo; + /** The pandemonium ratelimit info. */ + rate_limit: RateLimitConf; +} +/** The payload sent when the client has successfully authenticated. This contains the data the +user needs on startup. + +----- + +### Example + +```json +{ + "op": "AUTHENTICATED", + "user": { + "id": 48615849987334, + "username": "barbaz", + "social_credit": 3, + "badges": 0, + "permissions": 0 + }, + "users": [ + { + "id": 48615849987333, + "username": "foobar", + "social_credit": 42, + "badges": 0, + "permissions": 0 + } + ], +} +``` */ +export interface Authenticated { + op: "AUTHENTICATED"; + user: User; + /** The currently online users who are relavent to the connector. */ + users: User[]; +} +/** The payload received when a user updates themselves. This includes both user updates from +the {@link update_user} endpoint and profile updates from the {@link update_profile} endpoint. + +----- + +### Example + +```json +{ + "id": 48615849987333, + "username": "foobar", + "social_credit": 42, + "badges": 0, + "permissions": 0 +} +``` */ +export interface UserUpdate { + op: "USER_UPDATE"; + d: User; +} +/** The payload sent when a user's presence is updated. + +This is mainly used for when a user goes offline or online. + +----- + +### Example + +```json +{ + "user_id": 48615849987333, + "status": { + "type": "IDLE", + "text": "BURY THE LIGHT DEEP WITHIN" + } +} +``` */ +export interface PresenceUpdate { + op: "PRESENCE_UPDATE"; + user_id: number; + status: Status; +} +/** The payload sent when the client receives a {@link Message}. + +----- + +### Example + +```json +{ + "op": "MESSAGE_CREATE", + "d": { + "author": "A Certain Woo", + "content": "Woo!" + } +} +``` */ +export interface MessageCreate { + op: "MESSAGE_CREATE"; + d: Message; +} + +export interface Online {} + +export interface Offline {} + +export interface Idle {} + +export interface Busy {} +export type ErrorResponse = + | Unauthorized + | Forbidden + | NotFound + | Conflict + | Misdirected + | Validation + | RateLimited + | Server; +/** Shared fields between all error response variants. */ +export interface SharedErrorData { + /** The HTTP status of the error. */ + status: number; + /** A brief explanation of the error. */ + message: string; +} +/** The UpdateUserProfile payload. This payload is used to update a user's profile. The abscence of a +field or it being `undefined` means that it won't have an effect. Explicitly setting a field as +`null` will clear it. + +----- + +### Example + +```json +{ + "display_name": "HappyRu", + "bio": "I am very happy!" +} +``` */ +export interface UpdateUserProfile { + /** The user's new display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null | null; + /** The user's new status. This field cannot be more than 150 characters long. */ + status?: string | null | null; + /** The user's new status type. This must be one of `ONLINE`, `OFFLINE`, `IDLE` and `BUSY`. */ + status_type?: StatusType | null; + /** The user's new bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null | null; + /** The user's new avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null | null; + /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null | null; +} +/** The session payload. + +The user should ideally have one session for every client they have on every device. + +----- + +### Example + +```json +{ + "id": 2312155037697, + "user_id": 2312155693057, + "platform": "linux", + "client": "pilfer" +} +``` */ +export interface Session { + /** The session's ID. */ + id: number; + /** The session user's ID. */ + user_id: number; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; + /** The session's creation IP address. */ + ip: string; +} +/** The error when the client is missing authorization. This error often occurs when the user +doesn't pass in the required authentication or passes in invalid credentials. + +----- + +### Example + +```json +{ + "type": "UNAUTHORIZED", + "status": 401, + "message": "The user is missing authentication or the passed credentials are invalid" +} +``` */ +export interface Unauthorized extends SharedErrorData { + type: "UNAUTHORIZED"; +} +/** The error when a client *has* been succesfully authorized but does not have the required +permissions to execute an action. + +----- + +### Example + +```json +{ + "type": "FORBIDDEN", + "status": 403, + "message": "The user is missing the requried permissions to execute this action", +} +``` */ +export interface Forbidden extends SharedErrorData { + type: "FORBIDDEN"; +} +/** The error when a client requests a resource that does not exist. + +----- + +### Example + +```json +{ + "type": "NOT_FOUND", + "status": 404, + "message": "The requested resource could not be found" +} +``` */ +export interface NotFound extends SharedErrorData { + type: "NOT_FOUND"; +} +/** The error when a client's request causes a conflict, usually when they're trying to create +something that already exists. + +----- + +### Example + +```json +{ + "type": "CONFLICT", + "status": 409, + "message": "The request couldn't be completed due to conflicting with other data on the server", + "item": "username", +} +``` */ +export interface Conflict extends SharedErrorData { + type: "CONFLICT"; + /** The conflicting item. */ + item: string; +} +/** The error when a server isn't able to reduce a response even though the client's request +isn't explicitly wrong. This usually happens when an instance isn't configured to provide a +response. + +----- + +### Example + +```json +{ + "type": "MISDIRECTED", + "status": 421, + "message": "Misdirected request", + "info": "The instance isn't configured to deal with unbased individuals" +} +``` */ +export interface Misdirected extends SharedErrorData { + type: "MISDIRECTED"; + /** Extra information about what went wrong. */ + info: string; +} +/** The error when a request a client sends is incorrect and fails validation. + +----- + +### Example + +```json +{ + "type": "VALIDATION", + "status": 422, + "message": "Invalid request", + "value_name": "author", + "info": "author name is a bit too cringe" +} +``` */ +export interface Validation extends SharedErrorData { + type: "VALIDATION"; + /** The name of the value that failed validation. */ + value_name: string; + /** Extra information about what went wrong. */ + info: string; +} +/** The error when a client is rate limited. + +----- + +### Example + +```json +{ + "type": "RATE_LIMITED", + "status": 429, + "message": "You have been rate limited", + "retry_after": 1234 +} +``` */ +export interface RateLimited extends SharedErrorData { + type: "RATE_LIMITED"; + /** The amount of milliseconds you're still rate limited for. */ + retry_after: number; +} +/** The error when the server fails to process a request. + +Getting this error means that it's the server's fault and not the client that the request +failed. + +----- + +### Example + +```json +{ + "type": "SERVER", + "status": 500, + "message": "Server encountered an unexpected error", + "info": "Server got stabbed 28 times" +} +``` */ +export interface Server extends SharedErrorData { + type: "SERVER"; + /** Extra information about what went wrong. */ + info: string; +} +/** Rate limits that apply to Oprish (The REST API). + +----- + +### Example + +```json +{ + "get_instance_info": { + "reset_after": 5, + "limit": 2 + }, + "create_message": { + "reset_after": 5, + "limit": 10 + }, + "create_user": { + }, +} +``` */ +export interface OprishRateLimits { + /** Rate limits for the {@link get_instance_info} endpoint. */ + get_instance_info: RateLimitConf; + /** Rate limits for the {@link create_message} endpoint. */ + create_message: RateLimitConf; + /** Rate limits for the {@link create_user} endpoint. */ + create_user: RateLimitConf; + /** Rate limits for the {@link verify_user} endpoint. */ + verify_user: RateLimitConf; + /** Rate limits for the {@link get_self}, {@link get_user} and {@link get_user_from_username} endpoints. */ + get_user: RateLimitConf; + /** Rate limits for the {@link get_self}, {@link get_user} and {@link get_user_from_username} endpoints for + someone who hasn't made an account. */ + guest_get_user: RateLimitConf; + /** Rate limits for the {@link update_user} enpoint. */ + update_user: RateLimitConf; + /** Rate limits for the {@link update_profile} enpoint. */ + update_profile: RateLimitConf; + /** Rate limits for the {@link delete_user} enpoint. */ + delete_user: RateLimitConf; + /** Rate limits for the {@link create_password_reset_code} enpoint. */ + create_password_reset_code: RateLimitConf; + /** Rate limits for the {@link reset_password} enpoint. */ + reset_password: RateLimitConf; + /** Rate limits for the {@link create_session} endpoint. */ + create_session: RateLimitConf; + /** Rate limits for the {@link get_sessions} endpoint. */ + get_sessions: RateLimitConf; + /** Rate limits for the {@link delete_session} endpoint. */ + delete_session: RateLimitConf; +} +/** Represents a file stored on Effis. + +----- + +### Example + +```json +{ + "id": 2195354353667, + "name": "das_ding.png", + "bucket": "attachments", + "metadata": { + "type": "IMAGE", + "width": 1600, + "height": 1600 + } +} +``` */ +export interface FileData { + /** The file's ID. */ + id: number; + /** The file's name. */ + name: string; + /** The bucket the file is stored in. */ + bucket: string; + /** Whether the file is marked as a spoiler. */ + spoiler?: boolean; + /** The {@link FileMetadata} of the file. */ + metadata: FileMetadata; +} +/** A temporary way to mask the message's author's name and avatar. This is mainly used for +bridging and will be removed when webhooks are officially supported. + +----- + +### Example + +```json +{ + "name": "Jeff", + "avatar": "https://some-u.rl/to/some-image.png" +} +``` */ +export interface MessageDisguise { + /** The name of the message's disguise. */ + name: string | null; + /** The URL of the message's disguise. */ + avatar: string | null; +} From 0db4ab964d94db1800aad0acbe78bb3e491a385e Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Thu, 27 Jul 2023 20:06:16 +0200 Subject: [PATCH 06/18] fix: dont include extension --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 49b8c0f..ae99e7c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "require": "./dist/v0.3.3.js", "types": "./dist/v0.3.3.d.ts" }, - "./v0.4.0-alpha1.ts": { + "./v0.4.0-alpha1": { "import": "./dist/v0.4.0-alpha1.mjs", "require": "./dist/v0.4.0-alpha1.js", "types": "./dist/v0.4.0-alpha1.d.ts" From 0d04a043f18e5cbae62903792417c215ae0f0a35 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 14:15:17 +0200 Subject: [PATCH 07/18] fix: prefix enum variants with their name --- autotype/main.ts | 9 +- package.json | 2 +- src/v0.4.0-alpha1.ts | 1246 +++++++++++++++++++++--------------------- 3 files changed, 633 insertions(+), 624 deletions(-) diff --git a/autotype/main.ts b/autotype/main.ts index 07b8dee..b5c7b7e 100644 --- a/autotype/main.ts +++ b/autotype/main.ts @@ -95,20 +95,21 @@ async function buildTypes(fh: FileHandle, typeUrl: string, routes: string[]) { async function handleEnum(fh: FileHandle, info: ItemInfo) { await fh.write( `export type ${info.name} = ${ - info.item.variants.map((v) => v.name).join(" | ") || "never" + info.item.variants.map((v) => `${info.name}${v.name}`).join(" | ") || "never" }\n` ); for (const variant of info.item.variants) { - handleEnumVariant(fh, variant, info.item); + handleEnumVariant(fh, variant, info); } } async function handleEnumVariant( fh: FileHandle, variant: EnumVariant, - item: EnumInfo + info: ItemInfo ): Promise { + const {item, name} = info; let typeStr = ""; let doc = ""; let bases: string[] = []; @@ -160,7 +161,7 @@ async function handleEnumVariant( basesStr = ` extends ${basesStr}`; } - typeStr = `${doc}\nexport interface ${variant.name}${basesStr} {\n` + typeStr; + typeStr = `${doc}\nexport interface ${name}${variant.name}${basesStr} {\n` + typeStr; await fh.write(typeStr + "\n"); return bases; diff --git a/package.json b/package.json index ae99e7c..bd8c6c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eludris-api-types", - "version": "0.2.1-3", + "version": "0.2.1-6", "author": "teaishealthy", "license": "MIT", "exports": { diff --git a/src/v0.4.0-alpha1.ts b/src/v0.4.0-alpha1.ts index 720f0da..04e93c7 100644 --- a/src/v0.4.0-alpha1.ts +++ b/src/v0.4.0-alpha1.ts @@ -17,78 +17,6 @@ export interface FileUpload { file: unknown; spoiler: boolean; } -/** Represents a single rate limit. - ------ - -### Example - -```json -{ - "reset_after": 60, - "limit": 30 -} -``` */ -export interface RateLimitConf { - /** The amount of seconds after which the rate limit resets. */ - reset_after: number; - /** The amount of requests that can be made within the `reset_after` interval. */ - limit: number; -} -/** Rate limits that apply to Effis (The CDN). - ------ - -### Example - -```json -{ - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } -} -``` */ -export interface EffisRateLimits { - /** Rate limits for the asset buckets. */ - assets: EffisRateLimitConf; - /** Rate limits for the attachment bucket. */ - attachments: EffisRateLimitConf; - /** Rate limits for the file fetching endpoints. */ - fetch_file: RateLimitConf; -} -/** The ResetPassword payload. This is used when the user wants to reset their password using a -password reset code. - ------ - -### Example - -```json -{ - "code": 234567, - "email": "someemail@ma.il", - "password": "wow such security" -} -``` */ -export interface ResetPassword { - /** The password reset code the user got emailed. */ - code: number; - /** The user's email. */ - email: string; - /** The user's new password. */ - password: string; -} /** The MessageCreate payload. This is used when you want to create a message using the REST API. ----- @@ -108,23 +36,33 @@ export interface MessageCreate { content: string; _disguise?: MessageDisguise | null; } -/** The DeleteCredentials payload. This is used in multiple places in the API to provide extra -credentials for deleting important user-related stuff. +export type ClientPayload = ClientPayloadPing | ClientPayloadAuthenticate; +/** The payload the client is supposed to periodically send the server to not get disconnected. + +The interval where these pings are supposed to be sent can be found in the `HELLO` payload +of the {@link ServerPayload} enum. ----- +> **Note** +> +> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, +`RAND` being a random floating number between 0 and 1. +> +> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. + ### Example ```json { - "password": "wowsuchpassword" + "op": "PING" } ``` */ -export interface PasswordDeleteCredentials { - password: string; +export interface ClientPayloadPing { + op: "PING"; } -export type FileMetadata = Text | Image | Video | Other; -/** Represents information about the connected Eludris instance. +/** The first payload the client is supposed to send. The data of this payload is expected to +be a session token obtained from the {@link create_session} route. ----- @@ -132,106 +70,15 @@ export type FileMetadata = Text | Image | Video | Other; ```json { - "instance_name": "eludris", - "description": "The *almost* official Eludris instance - ooliver.", - "version": "0.3.2", - "message_limit": 2000, - "oprish_url": "https://api.eludris.gay", - "pandemonium_url": "wss://ws.eludris.gay/", - "effis_url": "https://cdn.eludris.gay", - "file_size": 20000000, - "attachment_file_size": 25000000, - "rate_limits": { - "oprish": { - "info": { - "reset_after": 5, - "limit": 2 - }, - "message_create": { - "reset_after": 5, - "limit": 10 - }, - "rate_limits": { - "reset_after": 5, - "limit": 2 - } - }, - "pandemonium": { - "reset_after": 10, - "limit": 5 - }, - "effis": { - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } - } - } + "op": "AUTHENTICATE", + "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) } ``` */ -export interface InstanceInfo { - /** The instance's name. */ - instance_name: string; - /** The instance's description. - - This is between 1 and 2048 characters long. */ - description: string | null; - /** The instance's Eludris version. */ - version: string; - /** The maximum length of a message's content. */ - message_limit: number; - /** The URL of the instance's Oprish (REST API) endpoint. */ - oprish_url: string; - /** The URL of the instance's Pandemonium (WebSocket API) endpoint. */ - pandemonium_url: string; - /** The URL of the instance's Effis (CDN) endpoint. */ - effis_url: string; - /** The maximum file size (in bytes) of an asset. */ - file_size: number; - /** The maximum file size (in bytes) of an attachment. */ - attachment_file_size: number; - /** The instance's email address if any. */ - email_address?: string | null; - /** The rate limits that apply to the connected Eludris instance. - - This is not present if the `rate_limits` query parameter is not set. */ - rate_limits?: InstanceRateLimits | null; -} - -export interface Text { - type: "Text"; -} - -export interface Image { - type: "Image"; - /** The image's width in pixels. */ - width?: number | null; - /** The image's height in pixels. */ - height?: number | null; -} - -export interface Video { - type: "Video"; - /** The video's width in pixels. */ - width?: number | null; - /** The video's height in pixels. */ - height?: number | null; -} - -export interface Other { - type: "Other"; +export interface ClientPayloadAuthenticate { + op: "AUTHENTICATE"; + d: string; } -/** The response to a {@link SessionCreate}. +/** Represents a single rate limit. ----- @@ -239,23 +86,34 @@ export interface Other { ```json { - "token": "", - "session": { - "indentifier": "yendri", - "password": "authentícame por favor", - "platform": "linux", - "client": "pilfer" - } + "reset_after": 60, + "limit": 30 } ``` */ -export interface SessionCreated { - /** The session's token. This can be used by the user to properly interface with the API. */ - token: string; - /** The session object that was created. */ - session: Session; +export interface RateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; } -/** The CreatePasswordResetCode payload. This is used when a user wants to generate a code -to reset their password, most commonly because they forgot their old one. +export type ErrorResponse = + | ErrorResponseUnauthorized + | ErrorResponseForbidden + | ErrorResponseNotFound + | ErrorResponseConflict + | ErrorResponseMisdirected + | ErrorResponseValidation + | ErrorResponseRateLimited + | ErrorResponseServer; +export type StatusType = + | StatusTypeOnline + | StatusTypeOffline + | StatusTypeIdle + | StatusTypeBusy; +/** The UserCreate payload. + +This is used when a user is initially first created. For authentication payloads check +{@link SessionCreate}. ----- @@ -263,14 +121,25 @@ to reset their password, most commonly because they forgot their old one. ```json { - "email": "someemail@ma.il" + "username": "yendri",d + "email": "yendri@llamoyendri.io", + "password": "authentícame por favor" // don't actually use this as a password } ``` */ -export interface CreatePasswordResetCode { +export interface UserCreate { + /** The user's name. + + This is different to their `display_name` as it denotes how they're more formally + referenced by the API. */ + username: string; /** The user's email. */ email: string; + /** The user's password. */ + password: string; } -/** A user's status. +/** The session payload. + +The user should ideally have one session for every client they have on every device. ----- @@ -278,13 +147,23 @@ export interface CreatePasswordResetCode { ```json { - "type": "BUSY", - "text": "ayúdame por favor", + "id": 2312155037697, + "user_id": 2312155693057, + "platform": "linux", + "client": "pilfer" } ``` */ -export interface Status { - type: StatusType; - text?: string | null; +export interface Session { + /** The session's ID. */ + id: number; + /** The session user's ID. */ + user_id: number; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; + /** The session's creation IP address. */ + ip: string; } /** The Message payload. This is returned when you're provided information about a pre-existing message. @@ -311,8 +190,9 @@ export interface Message { /** There message's data. */ message: MessageCreate; } -export type ClientPayload = Ping | Authenticate; -/** The user payload. +/** The SessionCreate payload. + +This is used to authenticate a user and obtain a token to interface with the API. ----- @@ -320,56 +200,22 @@ export type ClientPayload = Ping | Authenticate; ```json { - "id": 48615849987333, - "username": "yendri", - "display_name": "Nicolas", - "social_credit": -69420, - "status": { - "type": "BUSY", - "text": "ayúdame por favor", - }, - "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", - "avatar": 2255112175647, - "banner": 2255049523230, - "badges": 0, - "permissions": 0 + "identifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" } ``` */ -export interface User { - /** The user's ID. */ - id: number; - /** The user's username. This field has to be between 2 and 32 characters long. */ - username: string; - /** The user's display name. This field has to be between 2 and 32 characters long. */ - display_name?: string | null; - /** The user's social credit score. */ - social_credit: number; - /** The user's status. */ - status: Status; - /** The user's bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ - bio?: string | null; - /** The user's avatar. This field has to be a valid file ID in the "avatar" bucket. */ - avatar?: number | null; - /** The user's banner. This field has to be a valid file ID in the "banner" bucket. */ - banner?: number | null; - /** The user's badges as a bitfield. */ - badges: number; - /** The user's instance-wide permissions as a bitfield. */ - permissions: number; - /** The user's email. This is only shown when the user queries their own data. */ - email?: string | null; - /** The user's verification status. This is only shown when the user queries their own data. */ - verified?: boolean | null; +export interface SessionCreate { + /** The session user's identifier. This can be either their email or username. */ + identifier: string; + /** The session user's password. */ + password: string; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; } -export type ServerPayload = - | Pong - | RateLimit - | Hello - | Authenticated - | UserUpdate - | PresenceUpdate - | MessageCreate; -export type StatusType = Online | Offline | Idle | Busy; /** Represents a single rate limit for Effis. ----- @@ -391,59 +237,25 @@ export interface EffisRateLimitConf { /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ file_size_limit: number; } -/** Represents all rate limits that apply to the connected Eludris instance. +/** The error when the client is missing authorization. This error often occurs when the user +doesn't pass in the required authentication or passes in invalid credentials. ----- ### Example + ```json { - "oprish": { - "info": { - "reset_after": 5, - "limit": 2 - }, - "message_create": { - "reset_after": 5, - "limit": 10 - }, - "rate_limits": { - "reset_after": 5, - "limit": 2 - } - }, - "pandemonium": { - "reset_after": 10, - "limit": 5 - }, - "effis": { - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } - } + "type": "UNAUTHORIZED", + "status": 401, + "message": "The user is missing authentication or the passed credentials are invalid" } ``` */ -export interface InstanceRateLimits { - /** The instance's Oprish rate limit information (The REST API). */ - oprish: OprishRateLimits; - /** The instance's Pandemonium rate limit information (The WebSocket API). */ - pandemonium: RateLimitConf; - /** The instance's Effis rate limit information (The CDN). */ - effis: EffisRateLimits; +export interface ErrorResponseUnauthorized extends SharedErrorData { + type: "UNAUTHORIZED"; } -/** The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded -and won't affect the user. +/** The error when a client *has* been succesfully authorized but does not have the required +permissions to execute an action. ----- @@ -451,25 +263,15 @@ and won't affect the user. ```json { - "password": "authentícame por favor", - "username": "yendli", - "email": "yendli2@yemail.yom" + "type": "FORBIDDEN", + "status": 403, + "message": "The user is missing the requried permissions to execute this action", } ``` */ -export interface UpdateUser { - /** The user's current password for validation. */ - password: string; - /** The user's new username. */ - username?: string | null; - /** The user's new email. */ - email?: string | null; - /** The user's new password. */ - new_password?: string | null; +export interface ErrorResponseForbidden extends SharedErrorData { + type: "FORBIDDEN"; } -/** The UserCreate payload. - -This is used when a user is initially first created. For authentication payloads check -{@link SessionCreate}. +/** The error when a client requests a resource that does not exist. ----- @@ -477,25 +279,16 @@ This is used when a user is initially first created. For authentication payloads ```json { - "username": "yendri",d - "email": "yendri@llamoyendri.io", - "password": "authentícame por favor" // don't actually use this as a password + "type": "NOT_FOUND", + "status": 404, + "message": "The requested resource could not be found" } ``` */ -export interface UserCreate { - /** The user's name. - - This is different to their `display_name` as it denotes how they're more formally - referenced by the API. */ - username: string; - /** The user's email. */ - email: string; - /** The user's password. */ - password: string; +export interface ErrorResponseNotFound extends SharedErrorData { + type: "NOT_FOUND"; } -/** The SessionCreate payload. - -This is used to authenticate a user and obtain a token to interface with the API. +/** The error when a client's request causes a conflict, usually when they're trying to create +something that already exists. ----- @@ -503,48 +296,39 @@ This is used to authenticate a user and obtain a token to interface with the API ```json { - "identifier": "yendri", - "password": "authentícame por favor", - "platform": "linux", - "client": "pilfer" + "type": "CONFLICT", + "status": 409, + "message": "The request couldn't be completed due to conflicting with other data on the server", + "item": "username", } ``` */ -export interface SessionCreate { - /** The session user's identifier. This can be either their email or username. */ - identifier: string; - /** The session user's password. */ - password: string; - /** The session's platform (linux, windows, mac, etc.) */ - platform: string; - /** The client the session was created by. */ - client: string; +export interface ErrorResponseConflict extends SharedErrorData { + type: "CONFLICT"; + /** The conflicting item. */ + item: string; } -/** The payload the client is supposed to periodically send the server to not get disconnected. - -The interval where these pings are supposed to be sent can be found in the `HELLO` payload -of the {@link ServerPayload} enum. +/** The error when a server isn't able to reduce a response even though the client's request +isn't explicitly wrong. This usually happens when an instance isn't configured to provide a +response. ----- -> **Note** -> -> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, -`RAND` being a random floating number between 0 and 1. -> -> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. - ### Example ```json { - "op": "PING" + "type": "MISDIRECTED", + "status": 421, + "message": "Misdirected request", + "info": "The instance isn't configured to deal with unbased individuals" } ``` */ -export interface Ping { - op: "PING"; +export interface ErrorResponseMisdirected extends SharedErrorData { + type: "MISDIRECTED"; + /** Extra information about what went wrong. */ + info: string; } -/** The first payload the client is supposed to send. The data of this payload is expected to -be a session token obtained from the {@link create_session} route. +/** The error when a request a client sends is incorrect and fails validation. ----- @@ -552,15 +336,21 @@ be a session token obtained from the {@link create_session} route. ```json { - "op": "AUTHENTICATE", - "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) + "type": "VALIDATION", + "status": 422, + "message": "Invalid request", + "value_name": "author", + "info": "author name is a bit too cringe" } ``` */ -export interface Authenticate { - op: "AUTHENTICATE"; - d: string; +export interface ErrorResponseValidation extends SharedErrorData { + type: "VALIDATION"; + /** The name of the value that failed validation. */ + value_name: string; + /** Extra information about what went wrong. */ + info: string; } -/** A {@link ClientPayload} `PING` payload response. +/** The error when a client is rate limited. ----- @@ -568,16 +358,21 @@ export interface Authenticate { ```json { - "op": "PONG" + "type": "RATE_LIMITED", + "status": 429, + "message": "You have been rate limited", + "retry_after": 1234 } ``` */ -export interface Pong { - op: "PONG"; +export interface ErrorResponseRateLimited extends SharedErrorData { + type: "RATE_LIMITED"; + /** The amount of milliseconds you're still rate limited for. */ + retry_after: number; } -/** The payload sent when the client gets gateway rate limited. +/** The error when the server fails to process a request. -The client is supposed to wait `wait` milliseconds before sending any more events, -otherwise they are disconnected. +Getting this error means that it's the server's fault and not the client that the request +failed. ----- @@ -585,18 +380,27 @@ otherwise they are disconnected. ```json { - "op": "RATE_LIMIT", - "d": { - "wait": 1010 // 1.01 seconds - } + "type": "SERVER", + "status": 500, + "message": "Server encountered an unexpected error", + "info": "Server got stabbed 28 times" } ``` */ -export interface RateLimit { - op: "RATE_LIMIT"; - /** The amount of milliseconds you have to wait before the rate limit ends */ - wait: number; +export interface ErrorResponseServer extends SharedErrorData { + type: "SERVER"; + /** Extra information about what went wrong. */ + info: string; } -/** The payload sent by the server when you initiate a new gateway connection. + +export interface StatusTypeOnline {} + +export interface StatusTypeOffline {} + +export interface StatusTypeIdle {} + +export interface StatusTypeBusy {} +/** The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded +and won't affect the user. ----- @@ -604,75 +408,74 @@ export interface RateLimit { ```json { - "op": "HELLO", - "d": { - "heartbeat_interval": 45000, - "instance_info": { - "instance_name": "EmreLand", - "description": "More based than Oliver's instance (trust)", - "version": "0.3.3", - "message_limit": 2048, - "oprish_url": "https://example.com", - "pandemonium_url": "https://example.com", - "effis_url": "https://example.com", - "file_size": 20000000, - "attachment_file_size": 100000000 - }, - "rate_limit": { - "reset_after": 10, - "limit": 5 - } - } + "password": "authentícame por favor", + "username": "yendli", + "email": "yendli2@yemail.yom" } ``` */ -export interface Hello { - op: "HELLO"; - /** The amount of milliseconds your ping interval is supposed to be. */ - heartbeat_interval: number; - /** The instance's info. - -This is the same payload you get from the {@link get_instance_info} payload without -ratelimits */ - instance_info: InstanceInfo; - /** The pandemonium ratelimit info. */ - rate_limit: RateLimitConf; +export interface UpdateUser { + /** The user's current password for validation. */ + password: string; + /** The user's new username. */ + username?: string | null; + /** The user's new email. */ + email?: string | null; + /** The user's new password. */ + new_password?: string | null; } -/** The payload sent when the client has successfully authenticated. This contains the data the -user needs on startup. +/** Represents all rate limits that apply to the connected Eludris instance. ----- ### Example - ```json { - "op": "AUTHENTICATED", - "user": { - "id": 48615849987334, - "username": "barbaz", - "social_credit": 3, - "badges": 0, - "permissions": 0 + "oprish": { + "info": { + "reset_after": 5, + "limit": 2 + }, + "message_create": { + "reset_after": 5, + "limit": 10 + }, + "rate_limits": { + "reset_after": 5, + "limit": 2 + } }, - "users": [ - { - "id": 48615849987333, - "username": "foobar", - "social_credit": 42, - "badges": 0, - "permissions": 0 + "pandemonium": { + "reset_after": 10, + "limit": 5 + }, + "effis": { + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 } - ], + } } ``` */ -export interface Authenticated { - op: "AUTHENTICATED"; - user: User; - /** The currently online users who are relavent to the connector. */ - users: User[]; +export interface InstanceRateLimits { + /** The instance's Oprish rate limit information (The REST API). */ + oprish: OprishRateLimits; + /** The instance's Pandemonium rate limit information (The WebSocket API). */ + pandemonium: RateLimitConf; + /** The instance's Effis rate limit information (The CDN). */ + effis: EffisRateLimits; } -/** The payload received when a user updates themselves. This includes both user updates from -the {@link update_user} endpoint and profile updates from the {@link update_profile} endpoint. +/** A temporary way to mask the message's author's name and avatar. This is mainly used for +bridging and will be removed when webhooks are officially supported. ----- @@ -680,20 +483,18 @@ the {@link update_user} endpoint and profile updates from the {@link update_prof ```json { - "id": 48615849987333, - "username": "foobar", - "social_credit": 42, - "badges": 0, - "permissions": 0 + "name": "Jeff", + "avatar": "https://some-u.rl/to/some-image.png" } ``` */ -export interface UserUpdate { - op: "USER_UPDATE"; - d: User; +export interface MessageDisguise { + /** The name of the message's disguise. */ + name: string | null; + /** The URL of the message's disguise. */ + avatar: string | null; } -/** The payload sent when a user's presence is updated. - -This is mainly used for when a user goes offline or online. +/** The CreatePasswordResetCode payload. This is used when a user wants to generate a code +to reset their password, most commonly because they forgot their old one. ----- @@ -701,19 +502,15 @@ This is mainly used for when a user goes offline or online. ```json { - "user_id": 48615849987333, - "status": { - "type": "IDLE", - "text": "BURY THE LIGHT DEEP WITHIN" - } + "email": "someemail@ma.il" } ``` */ -export interface PresenceUpdate { - op: "PRESENCE_UPDATE"; - user_id: number; - status: Status; +export interface CreatePasswordResetCode { + /** The user's email. */ + email: string; } -/** The payload sent when the client receives a {@link Message}. +/** The ResetPassword payload. This is used when the user wants to reset their password using a +password reset code. ----- @@ -721,40 +518,18 @@ export interface PresenceUpdate { ```json { - "op": "MESSAGE_CREATE", - "d": { - "author": "A Certain Woo", - "content": "Woo!" - } + "code": 234567, + "email": "someemail@ma.il", + "password": "wow such security" } ``` */ -export interface MessageCreate { - op: "MESSAGE_CREATE"; - d: Message; -} - -export interface Online {} - -export interface Offline {} - -export interface Idle {} - -export interface Busy {} -export type ErrorResponse = - | Unauthorized - | Forbidden - | NotFound - | Conflict - | Misdirected - | Validation - | RateLimited - | Server; -/** Shared fields between all error response variants. */ -export interface SharedErrorData { - /** The HTTP status of the error. */ - status: number; - /** A brief explanation of the error. */ - message: string; +export interface ResetPassword { + /** The password reset code the user got emailed. */ + code: number; + /** The user's email. */ + email: string; + /** The user's new password. */ + password: string; } /** The UpdateUserProfile payload. This payload is used to update a user's profile. The abscence of a field or it being `undefined` means that it won't have an effect. Explicitly setting a field as @@ -784,53 +559,7 @@ export interface UpdateUserProfile { /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ banner?: number | null | null; } -/** The session payload. - -The user should ideally have one session for every client they have on every device. - ------ - -### Example - -```json -{ - "id": 2312155037697, - "user_id": 2312155693057, - "platform": "linux", - "client": "pilfer" -} -``` */ -export interface Session { - /** The session's ID. */ - id: number; - /** The session user's ID. */ - user_id: number; - /** The session's platform (linux, windows, mac, etc.) */ - platform: string; - /** The client the session was created by. */ - client: string; - /** The session's creation IP address. */ - ip: string; -} -/** The error when the client is missing authorization. This error often occurs when the user -doesn't pass in the required authentication or passes in invalid credentials. - ------ - -### Example - -```json -{ - "type": "UNAUTHORIZED", - "status": 401, - "message": "The user is missing authentication or the passed credentials are invalid" -} -``` */ -export interface Unauthorized extends SharedErrorData { - type: "UNAUTHORIZED"; -} -/** The error when a client *has* been succesfully authorized but does not have the required -permissions to execute an action. +/** Represents information about the connected Eludris instance. ----- @@ -838,32 +567,82 @@ permissions to execute an action. ```json { - "type": "FORBIDDEN", - "status": 403, - "message": "The user is missing the requried permissions to execute this action", + "instance_name": "eludris", + "description": "The *almost* official Eludris instance - ooliver.", + "version": "0.3.2", + "message_limit": 2000, + "oprish_url": "https://api.eludris.gay", + "pandemonium_url": "wss://ws.eludris.gay/", + "effis_url": "https://cdn.eludris.gay", + "file_size": 20000000, + "attachment_file_size": 25000000, + "rate_limits": { + "oprish": { + "info": { + "reset_after": 5, + "limit": 2 + }, + "message_create": { + "reset_after": 5, + "limit": 10 + }, + "rate_limits": { + "reset_after": 5, + "limit": 2 + } + }, + "pandemonium": { + "reset_after": 10, + "limit": 5 + }, + "effis": { + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } + } + } } ``` */ -export interface Forbidden extends SharedErrorData { - type: "FORBIDDEN"; -} -/** The error when a client requests a resource that does not exist. - ------ +export interface InstanceInfo { + /** The instance's name. */ + instance_name: string; + /** The instance's description. -### Example + This is between 1 and 2048 characters long. */ + description: string | null; + /** The instance's Eludris version. */ + version: string; + /** The maximum length of a message's content. */ + message_limit: number; + /** The URL of the instance's Oprish (REST API) endpoint. */ + oprish_url: string; + /** The URL of the instance's Pandemonium (WebSocket API) endpoint. */ + pandemonium_url: string; + /** The URL of the instance's Effis (CDN) endpoint. */ + effis_url: string; + /** The maximum file size (in bytes) of an asset. */ + file_size: number; + /** The maximum file size (in bytes) of an attachment. */ + attachment_file_size: number; + /** The instance's email address if any. */ + email_address?: string | null; + /** The rate limits that apply to the connected Eludris instance. -```json -{ - "type": "NOT_FOUND", - "status": 404, - "message": "The requested resource could not be found" -} -``` */ -export interface NotFound extends SharedErrorData { - type: "NOT_FOUND"; + This is not present if the `rate_limits` query parameter is not set. */ + rate_limits?: InstanceRateLimits | null; } -/** The error when a client's request causes a conflict, usually when they're trying to create -something that already exists. +/** The response to a {@link SessionCreate}. ----- @@ -871,20 +650,28 @@ something that already exists. ```json { - "type": "CONFLICT", - "status": 409, - "message": "The request couldn't be completed due to conflicting with other data on the server", - "item": "username", + "token": "", + "session": { + "indentifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" + } } ``` */ -export interface Conflict extends SharedErrorData { - type: "CONFLICT"; - /** The conflicting item. */ - item: string; +export interface SessionCreated { + /** The session's token. This can be used by the user to properly interface with the API. */ + token: string; + /** The session object that was created. */ + session: Session; } -/** The error when a server isn't able to reduce a response even though the client's request -isn't explicitly wrong. This usually happens when an instance isn't configured to provide a -response. +export type FileMetadata = + | FileMetadataText + | FileMetadataImage + | FileMetadataVideo + | FileMetadataOther; +/** The DeleteCredentials payload. This is used in multiple places in the API to provide extra +credentials for deleting important user-related stuff. ----- @@ -892,40 +679,20 @@ response. ```json { - "type": "MISDIRECTED", - "status": 421, - "message": "Misdirected request", - "info": "The instance isn't configured to deal with unbased individuals" + "password": "wowsuchpassword" } ``` */ -export interface Misdirected extends SharedErrorData { - type: "MISDIRECTED"; - /** Extra information about what went wrong. */ - info: string; -} -/** The error when a request a client sends is incorrect and fails validation. - ------ - -### Example - -```json -{ - "type": "VALIDATION", - "status": 422, - "message": "Invalid request", - "value_name": "author", - "info": "author name is a bit too cringe" +export interface PasswordDeleteCredentials { + password: string; } -``` */ -export interface Validation extends SharedErrorData { - type: "VALIDATION"; - /** The name of the value that failed validation. */ - value_name: string; - /** Extra information about what went wrong. */ - info: string; +/** Shared fields between all error response variants. */ +export interface SharedErrorData { + /** The HTTP status of the error. */ + status: number; + /** A brief explanation of the error. */ + message: string; } -/** The error when a client is rate limited. +/** Rate limits that apply to Effis (The CDN). ----- @@ -933,21 +700,31 @@ export interface Validation extends SharedErrorData { ```json { - "type": "RATE_LIMITED", - "status": 429, - "message": "You have been rate limited", - "retry_after": 1234 + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 + } } ``` */ -export interface RateLimited extends SharedErrorData { - type: "RATE_LIMITED"; - /** The amount of milliseconds you're still rate limited for. */ - retry_after: number; +export interface EffisRateLimits { + /** Rate limits for the asset buckets. */ + assets: EffisRateLimitConf; + /** Rate limits for the attachment bucket. */ + attachments: EffisRateLimitConf; + /** Rate limits for the file fetching endpoints. */ + fetch_file: RateLimitConf; } -/** The error when the server fails to process a request. - -Getting this error means that it's the server's fault and not the client that the request -failed. +/** The user payload. ----- @@ -955,16 +732,46 @@ failed. ```json { - "type": "SERVER", - "status": 500, - "message": "Server encountered an unexpected error", - "info": "Server got stabbed 28 times" + "id": 48615849987333, + "username": "yendri", + "display_name": "Nicolas", + "social_credit": -69420, + "status": { + "type": "BUSY", + "text": "ayúdame por favor", + }, + "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", + "avatar": 2255112175647, + "banner": 2255049523230, + "badges": 0, + "permissions": 0 } ``` */ -export interface Server extends SharedErrorData { - type: "SERVER"; - /** Extra information about what went wrong. */ - info: string; +export interface User { + /** The user's ID. */ + id: number; + /** The user's username. This field has to be between 2 and 32 characters long. */ + username: string; + /** The user's display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null; + /** The user's social credit score. */ + social_credit: number; + /** The user's status. */ + status: Status; + /** The user's bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null; + /** The user's avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null; + /** The user's banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null; + /** The user's badges as a bitfield. */ + badges: number; + /** The user's instance-wide permissions as a bitfield. */ + permissions: number; + /** The user's email. This is only shown when the user queries their own data. */ + email?: string | null; + /** The user's verification status. This is only shown when the user queries their own data. */ + verified?: boolean | null; } /** Rate limits that apply to Oprish (The REST API). @@ -1047,8 +854,7 @@ export interface FileData { /** The {@link FileMetadata} of the file. */ metadata: FileMetadata; } -/** A temporary way to mask the message's author's name and avatar. This is mainly used for -bridging and will be removed when webhooks are officially supported. +/** A user's status. ----- @@ -1056,13 +862,215 @@ bridging and will be removed when webhooks are officially supported. ```json { - "name": "Jeff", - "avatar": "https://some-u.rl/to/some-image.png" + "type": "BUSY", + "text": "ayúdame por favor", } ``` */ -export interface MessageDisguise { - /** The name of the message's disguise. */ - name: string | null; - /** The URL of the message's disguise. */ - avatar: string | null; +export interface Status { + type: StatusType; + text?: string | null; +} + +export interface FileMetadataText { + type: "Text"; +} + +export interface FileMetadataImage { + type: "Image"; + /** The image's width in pixels. */ + width?: number | null; + /** The image's height in pixels. */ + height?: number | null; +} + +export interface FileMetadataVideo { + type: "Video"; + /** The video's width in pixels. */ + width?: number | null; + /** The video's height in pixels. */ + height?: number | null; +} + +export interface FileMetadataOther { + type: "Other"; +} +export type ServerPayload = + | ServerPayloadPong + | ServerPayloadRateLimit + | ServerPayloadHello + | ServerPayloadAuthenticated + | ServerPayloadUserUpdate + | ServerPayloadPresenceUpdate + | ServerPayloadMessageCreate; +/** A {@link ClientPayload} `PING` payload response. + +----- + +### Example + +```json +{ + "op": "PONG" +} +``` */ +export interface ServerPayloadPong { + op: "PONG"; +} +/** The payload sent when the client gets gateway rate limited. + +The client is supposed to wait `wait` milliseconds before sending any more events, +otherwise they are disconnected. + +----- + +### Example + +```json +{ + "op": "RATE_LIMIT", + "d": { + "wait": 1010 // 1.01 seconds + } +} +``` */ +export interface ServerPayloadRateLimit { + op: "RATE_LIMIT"; + /** The amount of milliseconds you have to wait before the rate limit ends */ + wait: number; +} +/** The payload sent by the server when you initiate a new gateway connection. + +----- + +### Example + +```json +{ + "op": "HELLO", + "d": { + "heartbeat_interval": 45000, + "instance_info": { + "instance_name": "EmreLand", + "description": "More based than Oliver's instance (trust)", + "version": "0.3.3", + "message_limit": 2048, + "oprish_url": "https://example.com", + "pandemonium_url": "https://example.com", + "effis_url": "https://example.com", + "file_size": 20000000, + "attachment_file_size": 100000000 + }, + "rate_limit": { + "reset_after": 10, + "limit": 5 + } + } +} +``` */ +export interface ServerPayloadHello { + op: "HELLO"; + /** The amount of milliseconds your ping interval is supposed to be. */ + heartbeat_interval: number; + /** The instance's info. + +This is the same payload you get from the {@link get_instance_info} payload without +ratelimits */ + instance_info: InstanceInfo; + /** The pandemonium ratelimit info. */ + rate_limit: RateLimitConf; +} +/** The payload sent when the client has successfully authenticated. This contains the data the +user needs on startup. + +----- + +### Example + +```json +{ + "op": "AUTHENTICATED", + "user": { + "id": 48615849987334, + "username": "barbaz", + "social_credit": 3, + "badges": 0, + "permissions": 0 + }, + "users": [ + { + "id": 48615849987333, + "username": "foobar", + "social_credit": 42, + "badges": 0, + "permissions": 0 + } + ], +} +``` */ +export interface ServerPayloadAuthenticated { + op: "AUTHENTICATED"; + user: User; + /** The currently online users who are relavent to the connector. */ + users: User[]; +} +/** The payload received when a user updates themselves. This includes both user updates from +the {@link update_user} endpoint and profile updates from the {@link update_profile} endpoint. + +----- + +### Example + +```json +{ + "id": 48615849987333, + "username": "foobar", + "social_credit": 42, + "badges": 0, + "permissions": 0 +} +``` */ +export interface ServerPayloadUserUpdate { + op: "USER_UPDATE"; + d: User; +} +/** The payload sent when a user's presence is updated. + +This is mainly used for when a user goes offline or online. + +----- + +### Example + +```json +{ + "user_id": 48615849987333, + "status": { + "type": "IDLE", + "text": "BURY THE LIGHT DEEP WITHIN" + } +} +``` */ +export interface ServerPayloadPresenceUpdate { + op: "PRESENCE_UPDATE"; + user_id: number; + status: Status; +} +/** The payload sent when the client receives a {@link Message}. + +----- + +### Example + +```json +{ + "op": "MESSAGE_CREATE", + "d": { + "author": "A Certain Woo", + "content": "Woo!" + } +} +``` */ +export interface ServerPayloadMessageCreate { + op: "MESSAGE_CREATE"; + d: Message; } From 1e88b629b88d74d4178db4bb0b513a6334370c9a Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 15:33:50 +0200 Subject: [PATCH 08/18] fix: no wrong flatten fix: bases for structs --- autotype/main.ts | 33 +- package.json | 2 +- src/v0.4.0-alpha1.ts | 940 ++++++++++++++++++++++--------------------- 3 files changed, 498 insertions(+), 477 deletions(-) diff --git a/autotype/main.ts b/autotype/main.ts index b5c7b7e..193453c 100644 --- a/autotype/main.ts +++ b/autotype/main.ts @@ -95,7 +95,8 @@ async function buildTypes(fh: FileHandle, typeUrl: string, routes: string[]) { async function handleEnum(fh: FileHandle, info: ItemInfo) { await fh.write( `export type ${info.name} = ${ - info.item.variants.map((v) => `${info.name}${v.name}`).join(" | ") || "never" + info.item.variants.map((v) => `${info.name}${v.name}`).join(" | ") || + "never" }\n` ); @@ -109,7 +110,8 @@ async function handleEnumVariant( variant: EnumVariant, info: ItemInfo ): Promise { - const {item, name} = info; + const { item, name } = info; + console.log("content", item.content, variant.name); let typeStr = ""; let doc = ""; let bases: string[] = []; @@ -147,6 +149,10 @@ async function handleEnumVariant( variant.name, item.rename_all )}"\n`; + + if (item.content) { + typeStr += ` ${item.content}: {\n`; + } for (const field of variant.fields) { if (field.flattened) { bases.push(convertType(field.field_type)); @@ -154,6 +160,9 @@ async function handleEnumVariant( typeStr += fieldToType(field) + "\n"; } } + if (item.content) { + typeStr += " }\n"; + } } typeStr += "}"; let basesStr = bases.join(", "); @@ -161,7 +170,8 @@ async function handleEnumVariant( basesStr = ` extends ${basesStr}`; } - typeStr = `${doc}\nexport interface ${name}${variant.name}${basesStr} {\n` + typeStr; + typeStr = + `${doc}\nexport interface ${name}${variant.name}${basesStr} {\n` + typeStr; await fh.write(typeStr + "\n"); return bases; @@ -172,12 +182,17 @@ async function handleStruct(fh: FileHandle, info: ItemInfo) { if (info.doc) { doc = `/** ${convertDoc(info.doc)} */\n`; } - let typeStr = `${doc}export interface ${info.name} {\n`; - typeStr += info.item.fields - .map((field) => indent(fieldToType(field), 2)) - .join("\n"); - typeStr += "\n}"; - await fh.write(typeStr + "\n"); + let bases: string[] = []; + let typeStr = '{\n'; + for (const field of info.item.fields) { + if (field.flattened) { + bases.push(convertType(field.field_type)); + } else { + typeStr += fieldToType(field) + "\n"; + } + } + + await fh.write(`${doc}export interface ${info.name}${ bases.length ? " extends" : "" } ${bases.join(", ")} ${typeStr}}\n`); } async function main(inventoryIndex: string, output: string) { diff --git a/package.json b/package.json index bd8c6c2..e66b020 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eludris-api-types", - "version": "0.2.1-6", + "version": "0.2.1-7", "author": "teaishealthy", "license": "MIT", "exports": { diff --git a/src/v0.4.0-alpha1.ts b/src/v0.4.0-alpha1.ts index 04e93c7..3e21983 100644 --- a/src/v0.4.0-alpha1.ts +++ b/src/v0.4.0-alpha1.ts @@ -17,7 +17,7 @@ export interface FileUpload { file: unknown; spoiler: boolean; } -/** The MessageCreate payload. This is used when you want to create a message using the REST API. +/** Represents a single rate limit. ----- @@ -25,60 +25,44 @@ export interface FileUpload { ```json { - "content": "Hello, World!" + "reset_after": 60, + "limit": 30 } ``` */ -export interface MessageCreate { - /** The message's content. This field has to be at-least 2 characters long. The upper limit - is the instance's {@link InstanceInfo} `message_limit`. - - The content will be trimmed from leading and trailing whitespace. */ - content: string; - _disguise?: MessageDisguise | null; +export interface RateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; } -export type ClientPayload = ClientPayloadPing | ClientPayloadAuthenticate; -/** The payload the client is supposed to periodically send the server to not get disconnected. +/** The UserCreate payload. -The interval where these pings are supposed to be sent can be found in the `HELLO` payload -of the {@link ServerPayload} enum. +This is used when a user is initially first created. For authentication payloads check +{@link SessionCreate}. ----- -> **Note** -> -> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, -`RAND` being a random floating number between 0 and 1. -> -> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. - ### Example ```json { - "op": "PING" + "username": "yendri",d + "email": "yendri@llamoyendri.io", + "password": "authentícame por favor" // don't actually use this as a password } ``` */ -export interface ClientPayloadPing { - op: "PING"; -} -/** The first payload the client is supposed to send. The data of this payload is expected to -be a session token obtained from the {@link create_session} route. - ------ - -### Example +export interface UserCreate { + /** The user's name. -```json -{ - "op": "AUTHENTICATE", - "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) -} -``` */ -export interface ClientPayloadAuthenticate { - op: "AUTHENTICATE"; - d: string; +This is different to their `display_name` as it denotes how they're more formally +referenced by the API. */ + username: string; + /** The user's email. */ + email: string; + /** The user's password. */ + password: string; } -/** Represents a single rate limit. +/** Represents a single rate limit for Effis. ----- @@ -87,33 +71,20 @@ export interface ClientPayloadAuthenticate { ```json { "reset_after": 60, - "limit": 30 + "limit": 5, + "file_size_limit": 30000000 } ``` */ -export interface RateLimitConf { +export interface EffisRateLimitConf { /** The amount of seconds after which the rate limit resets. */ reset_after: number; /** The amount of requests that can be made within the `reset_after` interval. */ limit: number; + /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ + file_size_limit: number; } -export type ErrorResponse = - | ErrorResponseUnauthorized - | ErrorResponseForbidden - | ErrorResponseNotFound - | ErrorResponseConflict - | ErrorResponseMisdirected - | ErrorResponseValidation - | ErrorResponseRateLimited - | ErrorResponseServer; -export type StatusType = - | StatusTypeOnline - | StatusTypeOffline - | StatusTypeIdle - | StatusTypeBusy; -/** The UserCreate payload. - -This is used when a user is initially first created. For authentication payloads check -{@link SessionCreate}. +/** The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded +and won't affect the user. ----- @@ -121,22 +92,26 @@ This is used when a user is initially first created. For authentication payloads ```json { - "username": "yendri",d - "email": "yendri@llamoyendri.io", - "password": "authentícame por favor" // don't actually use this as a password + "password": "authentícame por favor", + "username": "yendli", + "email": "yendli2@yemail.yom" } ``` */ -export interface UserCreate { - /** The user's name. - - This is different to their `display_name` as it denotes how they're more formally - referenced by the API. */ - username: string; - /** The user's email. */ - email: string; - /** The user's password. */ +export interface UpdateUser { + /** The user's current password for validation. */ password: string; + /** The user's new username. */ + username?: string | null; + /** The user's new email. */ + email?: string | null; + /** The user's new password. */ + new_password?: string | null; } +export type StatusType = + | StatusTypeOnline + | StatusTypeOffline + | StatusTypeIdle + | StatusTypeBusy; /** The session payload. The user should ideally have one session for every client they have on every device. @@ -165,8 +140,8 @@ export interface Session { /** The session's creation IP address. */ ip: string; } -/** The Message payload. This is returned when you're provided information about a pre-existing -message. +/** The CreatePasswordResetCode payload. This is used when a user wants to generate a code +to reset their password, most commonly because they forgot their old one. ----- @@ -174,21 +149,31 @@ message. ```json { - "author": { - "id": 48615849987333, - "username": "mlynar", - "social_credit": 9999. - "badges": 256, - "permissions": 8 - } - "content": "Hello, World!" + "email": "someemail@ma.il" } ``` */ -export interface Message { - /** The message's author. */ - author: User; - /** There message's data. */ - message: MessageCreate; +export interface CreatePasswordResetCode { + /** The user's email. */ + email: string; +} +/** A temporary way to mask the message's author's name and avatar. This is mainly used for +bridging and will be removed when webhooks are officially supported. + +----- + +### Example + +```json +{ + "name": "Jeff", + "avatar": "https://some-u.rl/to/some-image.png" +} +``` */ +export interface MessageDisguise { + /** The name of the message's disguise. */ + name: string | null; + /** The URL of the message's disguise. */ + avatar: string | null; } /** The SessionCreate payload. @@ -216,46 +201,15 @@ export interface SessionCreate { /** The client the session was created by. */ client: string; } -/** Represents a single rate limit for Effis. - ------ - -### Example -```json -{ - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 -} -``` */ -export interface EffisRateLimitConf { - /** The amount of seconds after which the rate limit resets. */ - reset_after: number; - /** The amount of requests that can be made within the `reset_after` interval. */ - limit: number; - /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ - file_size_limit: number; -} -/** The error when the client is missing authorization. This error often occurs when the user -doesn't pass in the required authentication or passes in invalid credentials. +export interface StatusTypeOnline {} ------ +export interface StatusTypeOffline {} -### Example +export interface StatusTypeIdle {} -```json -{ - "type": "UNAUTHORIZED", - "status": 401, - "message": "The user is missing authentication or the passed credentials are invalid" -} -``` */ -export interface ErrorResponseUnauthorized extends SharedErrorData { - type: "UNAUTHORIZED"; -} -/** The error when a client *has* been succesfully authorized but does not have the required -permissions to execute an action. +export interface StatusTypeBusy {} +/** Represents a file stored on Effis. ----- @@ -263,15 +217,30 @@ permissions to execute an action. ```json { - "type": "FORBIDDEN", - "status": 403, - "message": "The user is missing the requried permissions to execute this action", + "id": 2195354353667, + "name": "das_ding.png", + "bucket": "attachments", + "metadata": { + "type": "IMAGE", + "width": 1600, + "height": 1600 + } } ``` */ -export interface ErrorResponseForbidden extends SharedErrorData { - type: "FORBIDDEN"; +export interface FileData { + /** The file's ID. */ + id: number; + /** The file's name. */ + name: string; + /** The bucket the file is stored in. */ + bucket: string; + /** Whether the file is marked as a spoiler. */ + spoiler?: boolean; + /** The {@link FileMetadata} of the file. */ + metadata: FileMetadata; } -/** The error when a client requests a resource that does not exist. +export type ClientPayload = ClientPayloadPing | ClientPayloadAuthenticate; +/** The MessageCreate payload. This is used when you want to create a message using the REST API. ----- @@ -279,151 +248,18 @@ export interface ErrorResponseForbidden extends SharedErrorData { ```json { - "type": "NOT_FOUND", - "status": 404, - "message": "The requested resource could not be found" + "content": "Hello, World!" } ``` */ -export interface ErrorResponseNotFound extends SharedErrorData { - type: "NOT_FOUND"; -} -/** The error when a client's request causes a conflict, usually when they're trying to create -something that already exists. - ------ - -### Example +export interface MessageCreate { + /** The message's content. This field has to be at-least 2 characters long. The upper limit +is the instance's {@link InstanceInfo} `message_limit`. -```json -{ - "type": "CONFLICT", - "status": 409, - "message": "The request couldn't be completed due to conflicting with other data on the server", - "item": "username", -} -``` */ -export interface ErrorResponseConflict extends SharedErrorData { - type: "CONFLICT"; - /** The conflicting item. */ - item: string; +The content will be trimmed from leading and trailing whitespace. */ + content: string; + _disguise?: MessageDisguise | null; } -/** The error when a server isn't able to reduce a response even though the client's request -isn't explicitly wrong. This usually happens when an instance isn't configured to provide a -response. - ------ - -### Example - -```json -{ - "type": "MISDIRECTED", - "status": 421, - "message": "Misdirected request", - "info": "The instance isn't configured to deal with unbased individuals" -} -``` */ -export interface ErrorResponseMisdirected extends SharedErrorData { - type: "MISDIRECTED"; - /** Extra information about what went wrong. */ - info: string; -} -/** The error when a request a client sends is incorrect and fails validation. - ------ - -### Example - -```json -{ - "type": "VALIDATION", - "status": 422, - "message": "Invalid request", - "value_name": "author", - "info": "author name is a bit too cringe" -} -``` */ -export interface ErrorResponseValidation extends SharedErrorData { - type: "VALIDATION"; - /** The name of the value that failed validation. */ - value_name: string; - /** Extra information about what went wrong. */ - info: string; -} -/** The error when a client is rate limited. - ------ - -### Example - -```json -{ - "type": "RATE_LIMITED", - "status": 429, - "message": "You have been rate limited", - "retry_after": 1234 -} -``` */ -export interface ErrorResponseRateLimited extends SharedErrorData { - type: "RATE_LIMITED"; - /** The amount of milliseconds you're still rate limited for. */ - retry_after: number; -} -/** The error when the server fails to process a request. - -Getting this error means that it's the server's fault and not the client that the request -failed. - ------ - -### Example - -```json -{ - "type": "SERVER", - "status": 500, - "message": "Server encountered an unexpected error", - "info": "Server got stabbed 28 times" -} -``` */ -export interface ErrorResponseServer extends SharedErrorData { - type: "SERVER"; - /** Extra information about what went wrong. */ - info: string; -} - -export interface StatusTypeOnline {} - -export interface StatusTypeOffline {} - -export interface StatusTypeIdle {} - -export interface StatusTypeBusy {} -/** The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded -and won't affect the user. - ------ - -### Example - -```json -{ - "password": "authentícame por favor", - "username": "yendli", - "email": "yendli2@yemail.yom" -} -``` */ -export interface UpdateUser { - /** The user's current password for validation. */ - password: string; - /** The user's new username. */ - username?: string | null; - /** The user's new email. */ - email?: string | null; - /** The user's new password. */ - new_password?: string | null; -} -/** Represents all rate limits that apply to the connected Eludris instance. +/** Represents all rate limits that apply to the connected Eludris instance. ----- @@ -474,8 +310,14 @@ export interface InstanceRateLimits { /** The instance's Effis rate limit information (The CDN). */ effis: EffisRateLimits; } -/** A temporary way to mask the message's author's name and avatar. This is mainly used for -bridging and will be removed when webhooks are officially supported. +export type FileMetadata = + | FileMetadataText + | FileMetadataImage + | FileMetadataVideo + | FileMetadataOther; +/** The UpdateUserProfile payload. This payload is used to update a user's profile. The abscence of a +field or it being `undefined` means that it won't have an effect. Explicitly setting a field as +`null` will clear it. ----- @@ -483,18 +325,26 @@ bridging and will be removed when webhooks are officially supported. ```json { - "name": "Jeff", - "avatar": "https://some-u.rl/to/some-image.png" + "display_name": "HappyRu", + "bio": "I am very happy!" } ``` */ -export interface MessageDisguise { - /** The name of the message's disguise. */ - name: string | null; - /** The URL of the message's disguise. */ - avatar: string | null; +export interface UpdateUserProfile { + /** The user's new display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null | null; + /** The user's new status. This field cannot be more than 150 characters long. */ + status?: string | null | null; + /** The user's new status type. This must be one of `ONLINE`, `OFFLINE`, `IDLE` and `BUSY`. */ + status_type?: StatusType | null; + /** The user's new bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null | null; + /** The user's new avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null | null; + /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null | null; } -/** The CreatePasswordResetCode payload. This is used when a user wants to generate a code -to reset their password, most commonly because they forgot their old one. +/** The Message payload. This is returned when you're provided information about a pre-existing +message. ----- @@ -502,12 +352,58 @@ to reset their password, most commonly because they forgot their old one. ```json { - "email": "someemail@ma.il" + "author": { + "id": 48615849987333, + "username": "mlynar", + "social_credit": 9999. + "badges": 256, + "permissions": 8 + } + "content": "Hello, World!" } ``` */ -export interface CreatePasswordResetCode { - /** The user's email. */ - email: string; +export interface Message extends MessageCreate { + /** The message's author. */ + author: User; +} +/** A user's status. + +----- + +### Example + +```json +{ + "type": "BUSY", + "text": "ayúdame por favor", +} +``` */ +export interface Status { + type: StatusType; + text?: string | null; +} +/** The response to a {@link SessionCreate}. + +----- + +### Example + +```json +{ + "token": "", + "session": { + "indentifier": "yendri", + "password": "authentícame por favor", + "platform": "linux", + "client": "pilfer" + } +} +``` */ +export interface SessionCreated { + /** The session's token. This can be used by the user to properly interface with the API. */ + token: string; + /** The session object that was created. */ + session: Session; } /** The ResetPassword payload. This is used when the user wants to reset their password using a password reset code. @@ -531,9 +427,8 @@ export interface ResetPassword { /** The user's new password. */ password: string; } -/** The UpdateUserProfile payload. This payload is used to update a user's profile. The abscence of a -field or it being `undefined` means that it won't have an effect. Explicitly setting a field as -`null` will clear it. +/** The DeleteCredentials payload. This is used in multiple places in the API to provide extra +credentials for deleting important user-related stuff. ----- @@ -541,23 +436,11 @@ field or it being `undefined` means that it won't have an effect. Explicitly set ```json { - "display_name": "HappyRu", - "bio": "I am very happy!" + "password": "wowsuchpassword" } ``` */ -export interface UpdateUserProfile { - /** The user's new display name. This field has to be between 2 and 32 characters long. */ - display_name?: string | null | null; - /** The user's new status. This field cannot be more than 150 characters long. */ - status?: string | null | null; - /** The user's new status type. This must be one of `ONLINE`, `OFFLINE`, `IDLE` and `BUSY`. */ - status_type?: StatusType | null; - /** The user's new bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ - bio?: string | null | null; - /** The user's new avatar. This field has to be a valid file ID in the "avatar" bucket. */ - avatar?: number | null | null; - /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ - banner?: number | null | null; +export interface PasswordDeleteCredentials { + password: string; } /** Represents information about the connected Eludris instance. @@ -619,7 +502,7 @@ export interface InstanceInfo { instance_name: string; /** The instance's description. - This is between 1 and 2048 characters long. */ +This is between 1 and 2048 characters long. */ description: string | null; /** The instance's Eludris version. */ version: string; @@ -639,10 +522,171 @@ export interface InstanceInfo { email_address?: string | null; /** The rate limits that apply to the connected Eludris instance. - This is not present if the `rate_limits` query parameter is not set. */ +This is not present if the `rate_limits` query parameter is not set. */ rate_limits?: InstanceRateLimits | null; } -/** The response to a {@link SessionCreate}. +export type ErrorResponse = + | ErrorResponseUnauthorized + | ErrorResponseForbidden + | ErrorResponseNotFound + | ErrorResponseConflict + | ErrorResponseMisdirected + | ErrorResponseValidation + | ErrorResponseRateLimited + | ErrorResponseServer; +/** The payload the client is supposed to periodically send the server to not get disconnected. + +The interval where these pings are supposed to be sent can be found in the `HELLO` payload +of the {@link ServerPayload} enum. + +----- + +> **Note** +> +> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, +`RAND` being a random floating number between 0 and 1. +> +> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. + +### Example + +```json +{ + "op": "PING" +} +``` */ +export interface ClientPayloadPing { + op: "PING"; +} +/** The first payload the client is supposed to send. The data of this payload is expected to +be a session token obtained from the {@link create_session} route. + +----- + +### Example + +```json +{ + "op": "AUTHENTICATE", + "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) +} +``` */ +export interface ClientPayloadAuthenticate { + op: "AUTHENTICATE"; + d: string; +} + +export interface FileMetadataText { + type: "Text"; +} + +export interface FileMetadataImage { + type: "Image"; + /** The image's width in pixels. */ + width?: number | null; + /** The image's height in pixels. */ + height?: number | null; +} + +export interface FileMetadataVideo { + type: "Video"; + /** The video's width in pixels. */ + width?: number | null; + /** The video's height in pixels. */ + height?: number | null; +} + +export interface FileMetadataOther { + type: "Other"; +} +/** Shared fields between all error response variants. */ +export interface SharedErrorData { + /** The HTTP status of the error. */ + status: number; + /** A brief explanation of the error. */ + message: string; +} +export type ServerPayload = + | ServerPayloadPong + | ServerPayloadRateLimit + | ServerPayloadHello + | ServerPayloadAuthenticated + | ServerPayloadUserUpdate + | ServerPayloadPresenceUpdate + | ServerPayloadMessageCreate; +/** The error when the client is missing authorization. This error often occurs when the user +doesn't pass in the required authentication or passes in invalid credentials. + +----- + +### Example + +```json +{ + "type": "UNAUTHORIZED", + "status": 401, + "message": "The user is missing authentication or the passed credentials are invalid" +} +``` */ +export interface ErrorResponseUnauthorized extends SharedErrorData { + type: "UNAUTHORIZED"; +} +/** The error when a client *has* been succesfully authorized but does not have the required +permissions to execute an action. + +----- + +### Example + +```json +{ + "type": "FORBIDDEN", + "status": 403, + "message": "The user is missing the requried permissions to execute this action", +} +``` */ +export interface ErrorResponseForbidden extends SharedErrorData { + type: "FORBIDDEN"; +} +/** The error when a client requests a resource that does not exist. + +----- + +### Example + +```json +{ + "type": "NOT_FOUND", + "status": 404, + "message": "The requested resource could not be found" +} +``` */ +export interface ErrorResponseNotFound extends SharedErrorData { + type: "NOT_FOUND"; +} +/** The error when a client's request causes a conflict, usually when they're trying to create +something that already exists. + +----- + +### Example + +```json +{ + "type": "CONFLICT", + "status": 409, + "message": "The request couldn't be completed due to conflicting with other data on the server", + "item": "username", +} +``` */ +export interface ErrorResponseConflict extends SharedErrorData { + type: "CONFLICT"; + /** The conflicting item. */ + item: string; +} +/** The error when a server isn't able to reduce a response even though the client's request +isn't explicitly wrong. This usually happens when an instance isn't configured to provide a +response. ----- @@ -650,28 +694,18 @@ export interface InstanceInfo { ```json { - "token": "", - "session": { - "indentifier": "yendri", - "password": "authentícame por favor", - "platform": "linux", - "client": "pilfer" - } + "type": "MISDIRECTED", + "status": 421, + "message": "Misdirected request", + "info": "The instance isn't configured to deal with unbased individuals" } ``` */ -export interface SessionCreated { - /** The session's token. This can be used by the user to properly interface with the API. */ - token: string; - /** The session object that was created. */ - session: Session; +export interface ErrorResponseMisdirected extends SharedErrorData { + type: "MISDIRECTED"; + /** Extra information about what went wrong. */ + info: string; } -export type FileMetadata = - | FileMetadataText - | FileMetadataImage - | FileMetadataVideo - | FileMetadataOther; -/** The DeleteCredentials payload. This is used in multiple places in the API to provide extra -credentials for deleting important user-related stuff. +/** The error when a request a client sends is incorrect and fails validation. ----- @@ -679,20 +713,21 @@ credentials for deleting important user-related stuff. ```json { - "password": "wowsuchpassword" + "type": "VALIDATION", + "status": 422, + "message": "Invalid request", + "value_name": "author", + "info": "author name is a bit too cringe" } ``` */ -export interface PasswordDeleteCredentials { - password: string; -} -/** Shared fields between all error response variants. */ -export interface SharedErrorData { - /** The HTTP status of the error. */ - status: number; - /** A brief explanation of the error. */ - message: string; +export interface ErrorResponseValidation extends SharedErrorData { + type: "VALIDATION"; + /** The name of the value that failed validation. */ + value_name: string; + /** Extra information about what went wrong. */ + info: string; } -/** Rate limits that apply to Effis (The CDN). +/** The error when a client is rate limited. ----- @@ -700,31 +735,21 @@ export interface SharedErrorData { ```json { - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } + "type": "RATE_LIMITED", + "status": 429, + "message": "You have been rate limited", + "retry_after": 1234 } ``` */ -export interface EffisRateLimits { - /** Rate limits for the asset buckets. */ - assets: EffisRateLimitConf; - /** Rate limits for the attachment bucket. */ - attachments: EffisRateLimitConf; - /** Rate limits for the file fetching endpoints. */ - fetch_file: RateLimitConf; +export interface ErrorResponseRateLimited extends SharedErrorData { + type: "RATE_LIMITED"; + /** The amount of milliseconds you're still rate limited for. */ + retry_after: number; } -/** The user payload. +/** The error when the server fails to process a request. + +Getting this error means that it's the server's fault and not the client that the request +failed. ----- @@ -732,46 +757,16 @@ export interface EffisRateLimits { ```json { - "id": 48615849987333, - "username": "yendri", - "display_name": "Nicolas", - "social_credit": -69420, - "status": { - "type": "BUSY", - "text": "ayúdame por favor", - }, - "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", - "avatar": 2255112175647, - "banner": 2255049523230, - "badges": 0, - "permissions": 0 + "type": "SERVER", + "status": 500, + "message": "Server encountered an unexpected error", + "info": "Server got stabbed 28 times" } ``` */ -export interface User { - /** The user's ID. */ - id: number; - /** The user's username. This field has to be between 2 and 32 characters long. */ - username: string; - /** The user's display name. This field has to be between 2 and 32 characters long. */ - display_name?: string | null; - /** The user's social credit score. */ - social_credit: number; - /** The user's status. */ - status: Status; - /** The user's bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ - bio?: string | null; - /** The user's avatar. This field has to be a valid file ID in the "avatar" bucket. */ - avatar?: number | null; - /** The user's banner. This field has to be a valid file ID in the "banner" bucket. */ - banner?: number | null; - /** The user's badges as a bitfield. */ - badges: number; - /** The user's instance-wide permissions as a bitfield. */ - permissions: number; - /** The user's email. This is only shown when the user queries their own data. */ - email?: string | null; - /** The user's verification status. This is only shown when the user queries their own data. */ - verified?: boolean | null; +export interface ErrorResponseServer extends SharedErrorData { + type: "SERVER"; + /** Extra information about what went wrong. */ + info: string; } /** Rate limits that apply to Oprish (The REST API). @@ -805,7 +800,7 @@ export interface OprishRateLimits { /** Rate limits for the {@link get_self}, {@link get_user} and {@link get_user_from_username} endpoints. */ get_user: RateLimitConf; /** Rate limits for the {@link get_self}, {@link get_user} and {@link get_user_from_username} endpoints for - someone who hasn't made an account. */ +someone who hasn't made an account. */ guest_get_user: RateLimitConf; /** Rate limits for the {@link update_user} enpoint. */ update_user: RateLimitConf; @@ -824,7 +819,7 @@ export interface OprishRateLimits { /** Rate limits for the {@link delete_session} endpoint. */ delete_session: RateLimitConf; } -/** Represents a file stored on Effis. +/** Rate limits that apply to Effis (The CDN). ----- @@ -832,29 +827,31 @@ export interface OprishRateLimits { ```json { - "id": 2195354353667, - "name": "das_ding.png", - "bucket": "attachments", - "metadata": { - "type": "IMAGE", - "width": 1600, - "height": 1600 + "assets": { + "reset_after": 60, + "limit": 5, + "file_size_limit": 30000000 + }, + "attachments": { + "reset_after": 180, + "limit": 20, + "file_size_limit": 500000000 + }, + "fetch_file": { + "reset_after": 60, + "limit": 30 } } ``` */ -export interface FileData { - /** The file's ID. */ - id: number; - /** The file's name. */ - name: string; - /** The bucket the file is stored in. */ - bucket: string; - /** Whether the file is marked as a spoiler. */ - spoiler?: boolean; - /** The {@link FileMetadata} of the file. */ - metadata: FileMetadata; +export interface EffisRateLimits { + /** Rate limits for the asset buckets. */ + assets: EffisRateLimitConf; + /** Rate limits for the attachment bucket. */ + attachments: EffisRateLimitConf; + /** Rate limits for the file fetching endpoints. */ + fetch_file: RateLimitConf; } -/** A user's status. +/** The user payload. ----- @@ -862,46 +859,47 @@ export interface FileData { ```json { - "type": "BUSY", - "text": "ayúdame por favor", + "id": 48615849987333, + "username": "yendri", + "display_name": "Nicolas", + "social_credit": -69420, + "status": { + "type": "BUSY", + "text": "ayúdame por favor", + }, + "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", + "avatar": 2255112175647, + "banner": 2255049523230, + "badges": 0, + "permissions": 0 } ``` */ -export interface Status { - type: StatusType; - text?: string | null; -} - -export interface FileMetadataText { - type: "Text"; -} - -export interface FileMetadataImage { - type: "Image"; - /** The image's width in pixels. */ - width?: number | null; - /** The image's height in pixels. */ - height?: number | null; -} - -export interface FileMetadataVideo { - type: "Video"; - /** The video's width in pixels. */ - width?: number | null; - /** The video's height in pixels. */ - height?: number | null; -} - -export interface FileMetadataOther { - type: "Other"; +export interface User { + /** The user's ID. */ + id: number; + /** The user's username. This field has to be between 2 and 32 characters long. */ + username: string; + /** The user's display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null; + /** The user's social credit score. */ + social_credit: number; + /** The user's status. */ + status: Status; + /** The user's bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null; + /** The user's avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null; + /** The user's banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null; + /** The user's badges as a bitfield. */ + badges: number; + /** The user's instance-wide permissions as a bitfield. */ + permissions: number; + /** The user's email. This is only shown when the user queries their own data. */ + email?: string | null; + /** The user's verification status. This is only shown when the user queries their own data. */ + verified?: boolean | null; } -export type ServerPayload = - | ServerPayloadPong - | ServerPayloadRateLimit - | ServerPayloadHello - | ServerPayloadAuthenticated - | ServerPayloadUserUpdate - | ServerPayloadPresenceUpdate - | ServerPayloadMessageCreate; /** A {@link ClientPayload} `PING` payload response. ----- @@ -935,8 +933,10 @@ otherwise they are disconnected. ``` */ export interface ServerPayloadRateLimit { op: "RATE_LIMIT"; - /** The amount of milliseconds you have to wait before the rate limit ends */ - wait: number; + d: { + /** The amount of milliseconds you have to wait before the rate limit ends */ + wait: number; + }; } /** The payload sent by the server when you initiate a new gateway connection. @@ -969,15 +969,17 @@ export interface ServerPayloadRateLimit { ``` */ export interface ServerPayloadHello { op: "HELLO"; - /** The amount of milliseconds your ping interval is supposed to be. */ - heartbeat_interval: number; - /** The instance's info. + d: { + /** The amount of milliseconds your ping interval is supposed to be. */ + heartbeat_interval: number; + /** The instance's info. This is the same payload you get from the {@link get_instance_info} payload without ratelimits */ - instance_info: InstanceInfo; - /** The pandemonium ratelimit info. */ - rate_limit: RateLimitConf; + instance_info: InstanceInfo; + /** The pandemonium ratelimit info. */ + rate_limit: RateLimitConf; + }; } /** The payload sent when the client has successfully authenticated. This contains the data the user needs on startup. @@ -1009,9 +1011,11 @@ user needs on startup. ``` */ export interface ServerPayloadAuthenticated { op: "AUTHENTICATED"; - user: User; - /** The currently online users who are relavent to the connector. */ - users: User[]; + d: { + user: User; + /** The currently online users who are relavent to the connector. */ + users: User[]; + }; } /** The payload received when a user updates themselves. This includes both user updates from the {@link update_user} endpoint and profile updates from the {@link update_profile} endpoint. @@ -1052,8 +1056,10 @@ This is mainly used for when a user goes offline or online. ``` */ export interface ServerPayloadPresenceUpdate { op: "PRESENCE_UPDATE"; - user_id: number; - status: Status; + d: { + user_id: number; + status: Status; + }; } /** The payload sent when the client receives a {@link Message}. From 6c3a1095c7b643341372a7c279bdfbe6c41518ce Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 18:34:51 +0200 Subject: [PATCH 09/18] docs: add docs --- .gitignore | 4 ++- package.json | 2 ++ typedoc.json | 10 ++++++++ yarn.lock | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 typedoc.json diff --git a/.gitignore b/.gitignore index 2a0f423..e166322 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ *.*map node_modules -yarn-error.log \ No newline at end of file +yarn-error.log + +docs/ \ No newline at end of file diff --git a/package.json b/package.json index e66b020..15ff805 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,12 @@ } }, "devDependencies": { + "@mxssfd/typedoc-theme": "^1.1.2", "@types/node": "^20.2.5", "gen-esm-wrapper": "^1.1.3", "rimraf": "^3.0.2", "tsx": "^3.12.7", + "typedoc": "^0.24.8", "typescript": "^4.9.4" }, "scripts": { diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..116e61e --- /dev/null +++ b/typedoc.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": [".src/*"], + "out": "./docs", + "plugin": ["@mxssfd/typedoc-theme"], + "theme": "my-theme", + "name": "eludris-api-types", + "readme": "./README.md", + "hideGenerator": true +} diff --git a/yarn.lock b/yarn.lock index 2aea67a..e812f61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -136,11 +136,21 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== +"@mxssfd/typedoc-theme@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@mxssfd/typedoc-theme/-/typedoc-theme-1.1.2.tgz#cd17ef3227c7093e249a0432893c201a836d382c" + integrity sha512-Q/9Z+sff8ey92PaB7bnsGOfyNa85vTjyofO8EOH8KwEdfGnV4lGXwLFt4AUth7CCqYplqI9q4JxHNt869mlEcw== + "@types/node@^20.2.5": version "20.2.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + assert@^1.4.1: version "1.5.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" @@ -162,6 +172,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -259,6 +276,21 @@ is-valid-identifier@^2.0.2: dependencies: assert "^1.4.1" +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +marked@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -266,6 +298,13 @@ minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.0: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -290,6 +329,16 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +shiki@^0.14.1: + version "0.14.3" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.3.tgz#d1a93c463942bdafb9866d74d619a4347d0bbf64" + integrity sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + source-map-support@^0.5.21: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -314,6 +363,16 @@ tsx@^3.12.7: optionalDependencies: fsevents "~2.3.2" +typedoc@^0.24.8: + version "0.24.8" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.8.tgz#cce9f47ba6a8d52389f5e583716a2b3b4335b63e" + integrity sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.0" + shiki "^0.14.1" + typescript@^4.9.4: version "4.9.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" @@ -326,6 +385,16 @@ util@0.10.3: dependencies: inherits "2.0.1" +vscode-oniguruma@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== + +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 9a388622ef834e7e44894c17d5d473362d86f671 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 22:12:43 +0200 Subject: [PATCH 10/18] feat: use a real code-generation framework This reduces bugs, yields much better doc comment, reduces overall code size We also get routes --- autotype/main.ts | 411 ++++--- package.json | 1 + src/v0.4.0-alpha1.ts | 2642 +++++++++++++++++++++++++++--------------- yarn.lock | 159 +++ 4 files changed, 2133 insertions(+), 1080 deletions(-) diff --git a/autotype/main.ts b/autotype/main.ts index 193453c..fb8a626 100644 --- a/autotype/main.ts +++ b/autotype/main.ts @@ -1,19 +1,28 @@ -import { FileHandle, open } from "fs/promises"; +import { open, stat } from "fs/promises"; +import { createInterface } from "readline/promises"; +import { + CodeBlockWriter, + Project, + Scope, + SourceFile, + StructureKind, +} from "ts-morph"; import { - StructInfo, - ItemInfo, EnumInfo, + Item, + ItemInfo, + ItemType, RouteInfo, - FieldInfo, + StructInfo, VariantType, - EnumVariant, } from "./types"; import { argv } from "process"; -import { existsSync } from "fs"; -import { createInterface } from "readline/promises"; + +main(argv[2], argv[3]); const converters: Map string> = new Map([ [/^String$/, (_) => "string"], + [/^str$/, (_) => "string"], [/^(u|i)(size|\d\d)$/, (str) => "number"], [ /^Option<.+>/, @@ -26,209 +35,273 @@ const converters: Map string> = new Map([ [/^Vec<.*>/, (str) => convertType(str.replace(/^Vec<(.+)>$/, "$1[]"))], ]); -function switchCase(content: string, newCase: string | null): string { - if (newCase == "SCREAMING_SNAKE_CASE") { - return content.replace(/(\S)([A-Z])/gm, "$1_$2").toUpperCase(); - } - return content; -} - -function convertDoc(doc: string) { - return doc.replace(/\[`(.+?)`\]/g, "{@link $1}"); -} - function convertType(type: string): string { for (const [regex, converter] of converters) { if (regex.test(type)) { - console.debug(`[DEBUG] Converting ${type} to ${converter(type)}`); return converter(type); } } return type; } -function indent(str: string, spaces: number) { - return str - .split("\n") - .map((line) => (line === "" ? "" : " ".repeat(spaces) + line)) - .join("\n"); -} - -function fieldToType(field: FieldInfo): string { - let doc = ""; - if (field.doc) { - doc = `/** ${convertDoc(field.doc)} */\n`; +function switchCase(content: string, newCase: string | null): string { + if (newCase == "SCREAMING_SNAKE_CASE") { + return content.replace(/(\S)([A-Z])/gm, "$1_$2").toUpperCase(); } - return `${doc}${field.name}${field.ommitable ? "?" : ""}: ${convertType( - field.field_type - )}`; + return content; } -function handleRoute(route: ItemInfo, routes: string[]) { - let doc = ""; - if (route.doc) { - doc = `/** ${convertDoc(route.doc)} */\n`; +async function main(inventoryIndex: string, output: string) { + const inventory: { + version: string; + items: string[]; + } = await (await fetch(`${inventoryIndex}/index.json`)).json(); + + if (await stat(`${output}/v${inventory["version"]}.ts`)) { + console.log( + `[INFO] v${inventory["version"]}.ts already exists, do you want to overwrite it?` + ); + const rl = createInterface({ + input: process.stdin, + output: process.stdout, + }); + const answer = await rl.question("Overwrite? (y/n) "); + rl.close(); + if (answer !== "y") { + return; + } } - const camelCaseName = route.name.replace( - /_(\w)/g, - (match: string, p1: string) => p1.toUpperCase() + + const project = new Project(); + const sourceFile = project.createSourceFile( + `${output}/v${inventory["version"]}.ts`, + undefined, + { + overwrite: true, + } ); - routes.push( - `${doc}export const ${camelCaseName} = () => ${route.item.route}` + + let items: ItemInfo[] = await Promise.all( + inventory.items.sort().map(async (url) => { + const response = await fetch(`${inventoryIndex}/${url}`); + return await response.json(); + }) ); -} -async function buildTypes(fh: FileHandle, typeUrl: string, routes: string[]) { - console.log(`[INFO] Building types for ${typeUrl}`); - const type = await (await fetch(typeUrl)).json(); - if (type.item.type === "struct") { - handleStruct(fh, type); - } else if (type.item.type === "enum") { - handleEnum(fh, type); - } else if (type.item.type === "route") { - handleRoute(type, routes); - } else { - console.log(`[WARN] Unknown type ${type.type} for ${typeUrl}`); - } + const builder = new Builder(sourceFile, items); + builder.buildTypes(); + + sourceFile.formatText({ + indentSize: 2, + convertTabsToSpaces: true, + ensureNewLineAtEndOfFile: true, + }); + + sourceFile.organizeImports(); + await sourceFile.save(); + await project.save(); } -async function handleEnum(fh: FileHandle, info: ItemInfo) { - await fh.write( - `export type ${info.name} = ${ - info.item.variants.map((v) => `${info.name}${v.name}`).join(" | ") || - "never" - }\n` - ); +class Builder { + sourceFile: SourceFile; + routes: ItemInfo[] = []; + itemInfos: ItemInfo[] = []; - for (const variant of info.item.variants) { - handleEnumVariant(fh, variant, info); + constructor(sourceFile: SourceFile, itemInfos: ItemInfo[]) { + this.sourceFile = sourceFile; + this.itemInfos = itemInfos; } -} -async function handleEnumVariant( - fh: FileHandle, - variant: EnumVariant, - info: ItemInfo -): Promise { - const { item, name } = info; - console.log("content", item.content, variant.name); - let typeStr = ""; - let doc = ""; - let bases: string[] = []; - if (variant.type === VariantType.Unit) { - if (item.tag) { - if (variant.doc) { - doc = `/** ${convertDoc(variant.doc)} */`; - } - typeStr += ` ${item.tag}: "${switchCase( - variant.name, - item.rename_all - )}"\n`; + convertDoc(doc: string) { + for (const route of this.routes) { + doc = doc.replace(route.name, convertToCamelCase(route.name)); } - } else if (variant.type === VariantType.Tuple) { - if (item.tag) { - typeStr += ` ${item.tag}: "${switchCase( - variant.name, - item.rename_all - )}"\n`; - if (variant.doc) { - doc += ` /** ${convertDoc(variant.doc)} */`; - } - if (item.content) { - typeStr += ` ${item.content}: ${convertType(variant.field_type)}\n`; + return doc.replace(/\[`(.+?)`\]/g, "{@link $1}"); + } + + buildTypes() { + for (const itemInfo of this.itemInfos) { + if (itemInfo.item.type === ItemType.Route) { + this.routes.push(itemInfo); } } - } else if (variant.type === VariantType.Struct) { - if (!item.tag) { - return []; - } - if (variant.doc) { - doc = `/** ${convertDoc(variant.doc)} */`; - } - typeStr += ` ${item.tag}: "${switchCase( - variant.name, - item.rename_all - )}"\n`; - if (item.content) { - typeStr += ` ${item.content}: {\n`; - } - for (const field of variant.fields) { - if (field.flattened) { - bases.push(convertType(field.field_type)); - } else { - typeStr += fieldToType(field) + "\n"; + for (const itemInfo of this.itemInfos) { + if (itemInfo.item.type === ItemType.Struct) { + this.handleStruct(itemInfo as ItemInfo); + } else if (itemInfo.item.type === ItemType.Enum) { + this.handleEnum(itemInfo as ItemInfo); + } else if (itemInfo.item.type === ItemType.Route) { + this.handleRoute(itemInfo as ItemInfo); } } - if (item.content) { - typeStr += " }\n"; - } - } - typeStr += "}"; - let basesStr = bases.join(", "); - if (basesStr) { - basesStr = ` extends ${basesStr}`; + + this.sourceFile.addStatements((writer) => { + writer.writeLine("export const ROUTES = {"); + for (const route of this.routes) { + //docs + writer.writeLine(`/**`); + let doc = " * " + this.convertDoc(route.doc).split("\n").join("\n * ") + doc = doc.replace(/\* \n/g, "*\n") + writer.writeLine(doc); + writer.writeLine(`*/`); + + writer.writeLine(`${convertToCamelCase(route.name)},`); + } + writer.writeLine("};"); + }); } - typeStr = - `${doc}\nexport interface ${name}${variant.name}${basesStr} {\n` + typeStr; - await fh.write(typeStr + "\n"); + handleStruct(itemInfo: ItemInfo) { + const { item, name, doc } = itemInfo; + const struct = this.sourceFile.addInterface({ + name, + isExported: false, + docs: [this.convertDoc(doc)], + extends: item.fields.filter((f) => f.flattened).map((f) => f.field_type), + }); + struct.setIsExported(true); - return bases; -} + for (const field of item.fields.filter((f) => !f.flattened)) { + const { name, doc, field_type } = field; -async function handleStruct(fh: FileHandle, info: ItemInfo) { - let doc = ""; - if (info.doc) { - doc = `/** ${convertDoc(info.doc)} */\n`; - } - let bases: string[] = []; - let typeStr = '{\n'; - for (const field of info.item.fields) { - if (field.flattened) { - bases.push(convertType(field.field_type)); - } else { - typeStr += fieldToType(field) + "\n"; + const property = struct.addProperty({ + name, + type: convertType(field_type), + hasQuestionToken: field.ommitable, + }); + + if (doc) { + property.addJsDoc(this.convertDoc(doc)); + } } } - await fh.write(`${doc}export interface ${info.name}${ bases.length ? " extends" : "" } ${bases.join(", ")} ${typeStr}}\n`); -} + handleEnum(itemInfo: ItemInfo) { + const { item, name, doc } = itemInfo; + const union = this.sourceFile.addTypeAlias({ + name, + isExported: true, + docs: [this.convertDoc(doc)], + type: item.variants.map((v) => name + v.name).join(" | "), + }); + union.setIsExported(true); -async function main(inventoryIndex: string, output: string) { - let routes: string[] = []; + for (const variant of item.variants) { + const variantInterface = this.sourceFile.addInterface({ + name: name + variant.name, + }); + variantInterface.setIsExported(true); - const inventory: { - version: string; - items: string[]; - } = await (await fetch(`${inventoryIndex}/index.json`)).json(); - console.log(inventory); + if (variant.type === VariantType.Unit) { + const property = variantInterface.addProperty({ + name: "type", + type: switchCase(`"${variant.name}"`, item.rename_all), + }); - if (existsSync(`${output}/v${inventory["version"]}.ts`)) { - console.log( - `[INFO] v${inventory["version"]}.ts already exists, do you want to overwrite it?` - ); - const rl = createInterface({ - input: process.stdin, - output: process.stdout, - }); - const answer = await rl.question("Overwrite? (y/n) "); - rl.close(); - if (answer !== "y") { - return; + if (variant.doc) { + property.addJsDoc(this.convertDoc(variant.doc)); + } + } else if (variant.type === VariantType.Tuple) { + if (!item.tag) { + continue; + } + + const property = variantInterface.addProperty({ + name: item.tag, + type: switchCase(`"${variant.name}"`, item.rename_all), + }); + + if (variant.doc) { + property.addJsDoc(this.convertDoc(variant.doc)); + } + + if (item.content) { + variantInterface.addProperty({ + name: item.content, + type: convertType(variant.field_type), + }); + } + } else if (variant.type === VariantType.Struct) { + if (!item.tag) { + continue; + } + + const property = variantInterface.addProperty({ + name: item.tag, + type: switchCase(`"${variant.name}"`, item.rename_all), + }); + + if (variant.doc) { + property.addJsDoc(this.convertDoc(variant.doc)); + } + + for (const field of variant.fields) { + if (field.flattened) { + variantInterface.addExtends(convertType(field.field_type)); + } else { + const property = variantInterface.addProperty({ + name: field.name, + type: convertType(field.field_type), + hasQuestionToken: field.ommitable, + }); + + if (field.doc) { + property.addJsDoc(this.convertDoc(field.doc)); + } + } + } + } } } - let fh = await open(`${output}/v${inventory["version"]}.ts`, "w"); - await fh.write("// This file was @generated by typegen\n"); + handleRoute(itemInfo: ItemInfo) { + let params = [ + { + name: "baseUrl", + param_type: "string", + }, + ]; + params = params.concat(itemInfo.item.path_params); + params = params.concat(itemInfo.item.query_params); + const camelCaseName = itemInfo.name.replace(/_(\w)/g, (_, c) => + c.toUpperCase() + ); - await Promise.all( - inventory.items.map((url) => { - buildTypes(fh, `${inventoryIndex}/${url}`, routes); - }) - ); + const routeFunction = this.sourceFile.addFunction({ + name: camelCaseName, + parameters: params.map((p) => ({ + name: convertToCamelCase(p.name), + type: convertType(p.param_type), + })), + + returnType: "string", + }); + + routeFunction.addStatements((writer) => { + writer.write("return `${baseUrl}"); + const route = itemInfo.item.route.replace(/\/?\??<.+>/g, ""); + writer.write(`${route}/`); - await fh.write(routes.join("\n")); + for (const pathParam of itemInfo.item.path_params) { + const camelCaseParamName = convertToCamelCase(pathParam.name); + writer.write(`\${${camelCaseParamName}}/`); + } + + if (itemInfo.item.query_params.length > 0) { + writer.write("?"); + } + + let queryParams = itemInfo.item.query_params.map( + (p) => `\${${convertToCamelCase(p.name)}}` + ); + writer.write(queryParams.join("&")); + + writer.write("`;"); + }); + } } -main(argv[2], argv[3]); +function convertToCamelCase(str: string) { + return str.replace(/_(\w)/g, (_, c) => c.toUpperCase()); +} diff --git a/package.json b/package.json index 15ff805..e952eac 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@types/node": "^20.2.5", "gen-esm-wrapper": "^1.1.3", "rimraf": "^3.0.2", + "ts-morph": "^19.0.0", "tsx": "^3.12.7", "typedoc": "^0.24.8", "typescript": "^4.9.4" diff --git a/src/v0.4.0-alpha1.ts b/src/v0.4.0-alpha1.ts index 3e21983..0dafc4d 100644 --- a/src/v0.4.0-alpha1.ts +++ b/src/v0.4.0-alpha1.ts @@ -1,232 +1,432 @@ -// This file was @generated by typegen -/** The data format for uploading a file. - -This is a `multipart/form-data` form. - ------ +function downloadAttachment(baseUrl: string, id: number): string { + return `${baseUrl}/download/${id}/`; +} -### Example +function downloadFile(baseUrl: string, bucket: string, id: number): string { + return `${baseUrl}/download/${bucket}/${id}/`; +} -```sh -curl \ - -F file=@trolley.mp4 \ - -F spoiler=true \ - https://cdn.eludris.gay/attachments/ -``` */ -export interface FileUpload { - file: unknown; - spoiler: boolean; +function downloadStaticFile(baseUrl: string, name: string): string { + return `${baseUrl}/download/${name}/`; } -/** Represents a single rate limit. ------ +function getAttachment(baseUrl: string, id: number): string { + return `${baseUrl}/${id}/`; +} -### Example +function getAttachmentData(baseUrl: string, id: number): string { + return `${baseUrl}/data/${id}/`; +} -```json -{ - "reset_after": 60, - "limit": 30 +function getFile(baseUrl: string, bucket: string, id: number): string { + return `${baseUrl}/${bucket}/${id}/`; } -``` */ -export interface RateLimitConf { - /** The amount of seconds after which the rate limit resets. */ - reset_after: number; - /** The amount of requests that can be made within the `reset_after` interval. */ - limit: number; + +function getFileData(baseUrl: string, bucket: string, id: number): string { + return `${baseUrl}/data/${bucket}/${id}/`; } -/** The UserCreate payload. -This is used when a user is initially first created. For authentication payloads check -{@link SessionCreate}. +function getStaticFile(baseUrl: string, name: string): string { + return `${baseUrl}/${name}/`; +} ------ +function uploadAttachment(baseUrl: string): string { + return `${baseUrl}//`; +} -### Example +function uploadFile(baseUrl: string, bucket: string): string { + return `${baseUrl}/${bucket}/`; +} -```json -{ - "username": "yendri",d - "email": "yendri@llamoyendri.io", - "password": "authentícame por favor" // don't actually use this as a password +function createMessage(baseUrl: string): string { + return `${baseUrl}/messages/`; } -``` */ -export interface UserCreate { - /** The user's name. -This is different to their `display_name` as it denotes how they're more formally -referenced by the API. */ - username: string; - /** The user's email. */ - email: string; - /** The user's password. */ - password: string; +function createPasswordResetCode(baseUrl: string): string { + return `${baseUrl}/users/reset-password/`; } -/** Represents a single rate limit for Effis. ------ +function createSession(baseUrl: string): string { + return `${baseUrl}/sessions/`; +} -### Example +function createUser(baseUrl: string): string { + return `${baseUrl}/users/`; +} -```json -{ - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 +function deleteSession(baseUrl: string, sessionId: number): string { + return `${baseUrl}/sessions/${sessionId}/`; } -``` */ -export interface EffisRateLimitConf { - /** The amount of seconds after which the rate limit resets. */ - reset_after: number; - /** The amount of requests that can be made within the `reset_after` interval. */ - limit: number; - /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ - file_size_limit: number; + +function deleteUser(baseUrl: string): string { + return `${baseUrl}/users/`; } -/** The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded -and won't affect the user. ------ +function getInstanceInfo(baseUrl: string, rateLimits: boolean): string { + return `${baseUrl}/?${rateLimits}`; +} -### Example +function getSelf(baseUrl: string): string { + return `${baseUrl}/users/@me/`; +} -```json -{ - "password": "authentícame por favor", - "username": "yendli", - "email": "yendli2@yemail.yom" +function getSessions(baseUrl: string): string { + return `${baseUrl}/sessions/`; } -``` */ -export interface UpdateUser { - /** The user's current password for validation. */ - password: string; - /** The user's new username. */ - username?: string | null; - /** The user's new email. */ - email?: string | null; - /** The user's new password. */ - new_password?: string | null; + +function getUser(baseUrl: string, userId: number): string { + return `${baseUrl}/users/${userId}/`; } -export type StatusType = - | StatusTypeOnline - | StatusTypeOffline - | StatusTypeIdle - | StatusTypeBusy; -/** The session payload. -The user should ideally have one session for every client they have on every device. +function getUserWithUsername(baseUrl: string, username: string): string { + return `${baseUrl}/users/${username}/`; +} ------ +function resetPassword(baseUrl: string): string { + return `${baseUrl}/users/reset-password/`; +} -### Example +function updateProfile(baseUrl: string): string { + return `${baseUrl}/users/profile/`; +} -```json -{ - "id": 2312155037697, - "user_id": 2312155693057, - "platform": "linux", - "client": "pilfer" +function updateUser(baseUrl: string): string { + return `${baseUrl}/users/`; } -``` */ -export interface Session { - /** The session's ID. */ - id: number; - /** The session user's ID. */ - user_id: number; - /** The session's platform (linux, windows, mac, etc.) */ - platform: string; - /** The client the session was created by. */ - client: string; - /** The session's creation IP address. */ - ip: string; + +function verifyUser(baseUrl: string, code: number): string { + return `${baseUrl}/users/verify/?${code}`; } -/** The CreatePasswordResetCode payload. This is used when a user wants to generate a code -to reset their password, most commonly because they forgot their old one. ------ +/** Pandemonium websocket payloads sent by the client to the server. */ +export type ClientPayload = ClientPayloadPing | ClientPayloadAuthenticate; -### Example +export interface ClientPayloadPing { + /** + * The payload the client is supposed to periodically send the server to not get disconnected. + * + * The interval where these pings are supposed to be sent can be found in the `HELLO` payload + * of the {@link ServerPayload} enum. + * + * ----- + * + * > **Note** + * > + * > You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, + * `RAND` being a random floating number between 0 and 1. + * > + * > This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. + * + * ### Example + * + * ```json + * { + * "op": "PING" + * } + * ``` + */ + type: "_PING"; +} -```json -{ - "email": "someemail@ma.il" +export interface ClientPayloadAuthenticate { + /** + * The first payload the client is supposed to send. The data of this payload is expected to + * be a session token obtained from the {@link createSession} route. + * + * ----- + * + * ### Example + * + * ```json + * { + * "op": "AUTHENTICATE", + * "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) + * } + * ``` + */ + op: "_AUTHENTICATE"; + d: string; } -``` */ + +/** + * The CreatePasswordResetCode payload. This is used when a user wants to generate a code + * to reset their password, most commonly because they forgot their old one. + * + * ----- + * + * ### Example + * + * ```json + * { + * "email": "someemail@ma.il" + * } + * ``` + */ export interface CreatePasswordResetCode { /** The user's email. */ email: string; } -/** A temporary way to mask the message's author's name and avatar. This is mainly used for -bridging and will be removed when webhooks are officially supported. - ------ -### Example - -```json -{ - "name": "Jeff", - "avatar": "https://some-u.rl/to/some-image.png" -} -``` */ -export interface MessageDisguise { - /** The name of the message's disguise. */ - name: string | null; - /** The URL of the message's disguise. */ - avatar: string | null; +/** + * Represents a single rate limit for Effis. + * + * ----- + * + * ### Example + * + * ```json + * { + * "reset_after": 60, + * "limit": 5, + * "file_size_limit": 30000000 + * } + * ``` + */ +export interface EffisRateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; + /** The maximum amount of bytes that can be sent within the `reset_after` interval. */ + file_size_limit: number; } -/** The SessionCreate payload. - -This is used to authenticate a user and obtain a token to interface with the API. ------ +/** + * Rate limits that apply to Effis (The CDN). + * + * ----- + * + * ### Example + * + * ```json + * { + * "assets": { + * "reset_after": 60, + * "limit": 5, + * "file_size_limit": 30000000 + * }, + * "attachments": { + * "reset_after": 180, + * "limit": 20, + * "file_size_limit": 500000000 + * }, + * "fetch_file": { + * "reset_after": 60, + * "limit": 30 + * } + * } + * ``` + */ +export interface EffisRateLimits { + /** Rate limits for the asset buckets. */ + assets: EffisRateLimitConf; + /** Rate limits for the attachment bucket. */ + attachments: EffisRateLimitConf; + /** Rate limits for the file fetching endpoints. */ + fetch_file: RateLimitConf; +} -### Example +/** All the possible error responses that are returned from Eludris HTTP microservices. */ +export type ErrorResponse = ErrorResponseUnauthorized | ErrorResponseForbidden | ErrorResponseNotFound | ErrorResponseConflict | ErrorResponseMisdirected | ErrorResponseValidation | ErrorResponseRateLimited | ErrorResponseServer; -```json -{ - "identifier": "yendri", - "password": "authentícame por favor", - "platform": "linux", - "client": "pilfer" -} -``` */ -export interface SessionCreate { - /** The session user's identifier. This can be either their email or username. */ - identifier: string; - /** The session user's password. */ - password: string; - /** The session's platform (linux, windows, mac, etc.) */ - platform: string; - /** The client the session was created by. */ - client: string; +export interface ErrorResponseUnauthorized extends SharedErrorData { + /** + * The error when the client is missing authorization. This error often occurs when the user + * doesn't pass in the required authentication or passes in invalid credentials. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "UNAUTHORIZED", + * "status": 401, + * "message": "The user is missing authentication or the passed credentials are invalid" + * } + * ``` + */ + type: "_UNAUTHORIZED"; } -export interface StatusTypeOnline {} +export interface ErrorResponseForbidden extends SharedErrorData { + /** + * The error when a client *has* been succesfully authorized but does not have the required + * permissions to execute an action. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "FORBIDDEN", + * "status": 403, + * "message": "The user is missing the requried permissions to execute this action", + * } + * ``` + */ + type: "_FORBIDDEN"; +} -export interface StatusTypeOffline {} +export interface ErrorResponseNotFound extends SharedErrorData { + /** + * The error when a client requests a resource that does not exist. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "NOT_FOUND", + * "status": 404, + * "message": "The requested resource could not be found" + * } + * ``` + */ + type: "_NOT_FOUND"; +} -export interface StatusTypeIdle {} +export interface ErrorResponseConflict extends SharedErrorData { + /** + * The error when a client's request causes a conflict, usually when they're trying to create + * something that already exists. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "CONFLICT", + * "status": 409, + * "message": "The request couldn't be completed due to conflicting with other data on the server", + * "item": "username", + * } + * ``` + */ + type: "_CONFLICT"; + /** The conflicting item. */ + item: string; +} -export interface StatusTypeBusy {} -/** Represents a file stored on Effis. +export interface ErrorResponseMisdirected extends SharedErrorData { + /** + * The error when a server isn't able to reduce a response even though the client's request + * isn't explicitly wrong. This usually happens when an instance isn't configured to provide a + * response. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "MISDIRECTED", + * "status": 421, + * "message": "Misdirected request", + * "info": "The instance isn't configured to deal with unbased individuals" + * } + * ``` + */ + type: "_MISDIRECTED"; + /** Extra information about what went wrong. */ + info: string; +} ------ +export interface ErrorResponseValidation extends SharedErrorData { + /** + * The error when a request a client sends is incorrect and fails validation. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "VALIDATION", + * "status": 422, + * "message": "Invalid request", + * "value_name": "author", + * "info": "author name is a bit too cringe" + * } + * ``` + */ + type: "_VALIDATION"; + /** The name of the value that failed validation. */ + value_name: string; + /** Extra information about what went wrong. */ + info: string; +} -### Example +export interface ErrorResponseRateLimited extends SharedErrorData { + /** + * The error when a client is rate limited. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "RATE_LIMITED", + * "status": 429, + * "message": "You have been rate limited", + * "retry_after": 1234 + * } + * ``` + */ + type: "_RATE_LIMITED"; + /** The amount of milliseconds you're still rate limited for. */ + retry_after: number; +} -```json -{ - "id": 2195354353667, - "name": "das_ding.png", - "bucket": "attachments", - "metadata": { - "type": "IMAGE", - "width": 1600, - "height": 1600 - } +export interface ErrorResponseServer extends SharedErrorData { + /** + * The error when the server fails to process a request. + * + * Getting this error means that it's the server's fault and not the client that the request + * failed. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "SERVER", + * "status": 500, + * "message": "Server encountered an unexpected error", + * "info": "Server got stabbed 28 times" + * } + * ``` + */ + type: "_SERVER"; + /** Extra information about what went wrong. */ + info: string; } -``` */ + +/** + * Represents a file stored on Effis. + * + * ----- + * + * ### Example + * + * ```json + * { + * "id": 2195354353667, + * "name": "das_ding.png", + * "bucket": "attachments", + * "metadata": { + * "type": "IMAGE", + * "width": 1600, + * "height": 1600 + * } + * } + * ``` + */ export interface FileData { /** The file's ID. */ id: number; @@ -239,270 +439,145 @@ export interface FileData { /** The {@link FileMetadata} of the file. */ metadata: FileMetadata; } -export type ClientPayload = ClientPayloadPing | ClientPayloadAuthenticate; -/** The MessageCreate payload. This is used when you want to create a message using the REST API. - ------ - -### Example - -```json -{ - "content": "Hello, World!" -} -``` */ -export interface MessageCreate { - /** The message's content. This field has to be at-least 2 characters long. The upper limit -is the instance's {@link InstanceInfo} `message_limit`. - -The content will be trimmed from leading and trailing whitespace. */ - content: string; - _disguise?: MessageDisguise | null; -} -/** Represents all rate limits that apply to the connected Eludris instance. - ------ - -### Example -```json -{ - "oprish": { - "info": { - "reset_after": 5, - "limit": 2 - }, - "message_create": { - "reset_after": 5, - "limit": 10 - }, - "rate_limits": { - "reset_after": 5, - "limit": 2 - } - }, - "pandemonium": { - "reset_after": 10, - "limit": 5 - }, - "effis": { - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } - } -} -``` */ -export interface InstanceRateLimits { - /** The instance's Oprish rate limit information (The REST API). */ - oprish: OprishRateLimits; - /** The instance's Pandemonium rate limit information (The WebSocket API). */ - pandemonium: RateLimitConf; - /** The instance's Effis rate limit information (The CDN). */ - effis: EffisRateLimits; -} -export type FileMetadata = - | FileMetadataText - | FileMetadataImage - | FileMetadataVideo - | FileMetadataOther; -/** The UpdateUserProfile payload. This payload is used to update a user's profile. The abscence of a -field or it being `undefined` means that it won't have an effect. Explicitly setting a field as -`null` will clear it. ------ +/** + * The enum representing all the possible Effis supported file metadatas. + * + * ----- + * + * ### Examples + * + * ```json + * { + * "type": "TEXT" + * } + * { + * "type": "IMAGE", + * "width": 5120, + * "height": 1440 + * } + * { + * "type": "VIDEO", + * "width": 1920, + * "height": 1080 + * } + * { + * "type": "OTHER" + * } + * ``` + */ +export type FileMetadata = FileMetadataText | FileMetadataImage | FileMetadataVideo | FileMetadataOther; -### Example - -```json -{ - "display_name": "HappyRu", - "bio": "I am very happy!" -} -``` */ -export interface UpdateUserProfile { - /** The user's new display name. This field has to be between 2 and 32 characters long. */ - display_name?: string | null | null; - /** The user's new status. This field cannot be more than 150 characters long. */ - status?: string | null | null; - /** The user's new status type. This must be one of `ONLINE`, `OFFLINE`, `IDLE` and `BUSY`. */ - status_type?: StatusType | null; - /** The user's new bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ - bio?: string | null | null; - /** The user's new avatar. This field has to be a valid file ID in the "avatar" bucket. */ - avatar?: number | null | null; - /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ - banner?: number | null | null; +export interface FileMetadataText { + type: "Text"; } -/** The Message payload. This is returned when you're provided information about a pre-existing -message. - ------ -### Example - -```json -{ - "author": { - "id": 48615849987333, - "username": "mlynar", - "social_credit": 9999. - "badges": 256, - "permissions": 8 - } - "content": "Hello, World!" -} -``` */ -export interface Message extends MessageCreate { - /** The message's author. */ - author: User; +export interface FileMetadataImage { + type: "Image"; + /** The image's width in pixels. */ + width?: number | null; + /** The image's height in pixels. */ + height?: number | null; } -/** A user's status. - ------ -### Example - -```json -{ - "type": "BUSY", - "text": "ayúdame por favor", -} -``` */ -export interface Status { - type: StatusType; - text?: string | null; +export interface FileMetadataVideo { + type: "Video"; + /** The video's width in pixels. */ + width?: number | null; + /** The video's height in pixels. */ + height?: number | null; } -/** The response to a {@link SessionCreate}. ------ - -### Example - -```json -{ - "token": "", - "session": { - "indentifier": "yendri", - "password": "authentícame por favor", - "platform": "linux", - "client": "pilfer" - } -} -``` */ -export interface SessionCreated { - /** The session's token. This can be used by the user to properly interface with the API. */ - token: string; - /** The session object that was created. */ - session: Session; +export interface FileMetadataOther { + type: "Other"; } -/** The ResetPassword payload. This is used when the user wants to reset their password using a -password reset code. - ------ -### Example - -```json -{ - "code": 234567, - "email": "someemail@ma.il", - "password": "wow such security" -} -``` */ -export interface ResetPassword { - /** The password reset code the user got emailed. */ - code: number; - /** The user's email. */ - email: string; - /** The user's new password. */ - password: string; +/** + * The data format for uploading a file. + * + * This is a `multipart/form-data` form. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -F file=@trolley.mp4 \ + * -F spoiler=true \ + * https://cdn.eludris.gay/attachments/ + * ``` + */ +export interface FileUpload { + file: unknown; + spoiler: boolean; } -/** The DeleteCredentials payload. This is used in multiple places in the API to provide extra -credentials for deleting important user-related stuff. - ------ -### Example - -```json -{ - "password": "wowsuchpassword" -} -``` */ -export interface PasswordDeleteCredentials { - password: string; -} -/** Represents information about the connected Eludris instance. - ------ - -### Example - -```json -{ - "instance_name": "eludris", - "description": "The *almost* official Eludris instance - ooliver.", - "version": "0.3.2", - "message_limit": 2000, - "oprish_url": "https://api.eludris.gay", - "pandemonium_url": "wss://ws.eludris.gay/", - "effis_url": "https://cdn.eludris.gay", - "file_size": 20000000, - "attachment_file_size": 25000000, - "rate_limits": { - "oprish": { - "info": { - "reset_after": 5, - "limit": 2 - }, - "message_create": { - "reset_after": 5, - "limit": 10 - }, - "rate_limits": { - "reset_after": 5, - "limit": 2 - } - }, - "pandemonium": { - "reset_after": 10, - "limit": 5 - }, - "effis": { - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } - } - } -} -``` */ +/** + * Represents information about the connected Eludris instance. + * + * ----- + * + * ### Example + * + * ```json + * { + * "instance_name": "eludris", + * "description": "The *almost* official Eludris instance - ooliver.", + * "version": "0.3.2", + * "message_limit": 2000, + * "oprish_url": "https://api.eludris.gay", + * "pandemonium_url": "wss://ws.eludris.gay/", + * "effis_url": "https://cdn.eludris.gay", + * "file_size": 20000000, + * "attachment_file_size": 25000000, + * "rate_limits": { + * "oprish": { + * "info": { + * "reset_after": 5, + * "limit": 2 + * }, + * "message_create": { + * "reset_after": 5, + * "limit": 10 + * }, + * "rate_limits": { + * "reset_after": 5, + * "limit": 2 + * } + * }, + * "pandemonium": { + * "reset_after": 10, + * "limit": 5 + * }, + * "effis": { + * "assets": { + * "reset_after": 60, + * "limit": 5, + * "file_size_limit": 30000000 + * }, + * "attachments": { + * "reset_after": 180, + * "limit": 20, + * "file_size_limit": 500000000 + * }, + * "fetch_file": { + * "reset_after": 60, + * "limit": 30 + * } + * } + * } + * } + * ``` + */ export interface InstanceInfo { /** The instance's name. */ instance_name: string; - /** The instance's description. - -This is between 1 and 2048 characters long. */ + /** + * The instance's description. + * + * This is between 1 and 2048 characters long. + */ description: string | null; /** The instance's Eludris version. */ version: string; @@ -520,360 +595,677 @@ This is between 1 and 2048 characters long. */ attachment_file_size: number; /** The instance's email address if any. */ email_address?: string | null; - /** The rate limits that apply to the connected Eludris instance. - -This is not present if the `rate_limits` query parameter is not set. */ + /** + * The rate limits that apply to the connected Eludris instance. + * + * This is not present if the `rate_limits` query parameter is not set. + */ rate_limits?: InstanceRateLimits | null; } -export type ErrorResponse = - | ErrorResponseUnauthorized - | ErrorResponseForbidden - | ErrorResponseNotFound - | ErrorResponseConflict - | ErrorResponseMisdirected - | ErrorResponseValidation - | ErrorResponseRateLimited - | ErrorResponseServer; -/** The payload the client is supposed to periodically send the server to not get disconnected. - -The interval where these pings are supposed to be sent can be found in the `HELLO` payload -of the {@link ServerPayload} enum. - ------ - -> **Note** -> -> You are supposed to send your first ping in a connection after `RAND * heartbeat_interval` seconds, -`RAND` being a random floating number between 0 and 1. -> -> This is done to avoid immediately overloading Pandemonium by connecting if it ever has to go down. -### Example - -```json -{ - "op": "PING" -} -``` */ -export interface ClientPayloadPing { - op: "PING"; +/** + * Represents all rate limits that apply to the connected Eludris instance. + * + * ----- + * + * ### Example + * ```json + * { + * "oprish": { + * "info": { + * "reset_after": 5, + * "limit": 2 + * }, + * "message_create": { + * "reset_after": 5, + * "limit": 10 + * }, + * "rate_limits": { + * "reset_after": 5, + * "limit": 2 + * } + * }, + * "pandemonium": { + * "reset_after": 10, + * "limit": 5 + * }, + * "effis": { + * "assets": { + * "reset_after": 60, + * "limit": 5, + * "file_size_limit": 30000000 + * }, + * "attachments": { + * "reset_after": 180, + * "limit": 20, + * "file_size_limit": 500000000 + * }, + * "fetch_file": { + * "reset_after": 60, + * "limit": 30 + * } + * } + * } + * ``` + */ +export interface InstanceRateLimits { + /** The instance's Oprish rate limit information (The REST API). */ + oprish: OprishRateLimits; + /** The instance's Pandemonium rate limit information (The WebSocket API). */ + pandemonium: RateLimitConf; + /** The instance's Effis rate limit information (The CDN). */ + effis: EffisRateLimits; } -/** The first payload the client is supposed to send. The data of this payload is expected to -be a session token obtained from the {@link create_session} route. ------ - -### Example - -```json -{ - "op": "AUTHENTICATE", - "d": "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMzQxMDY1MjYxMDU3LCJzZXNzaW9uX2lkIjoyMzQxMDgyNDMxNDg5fQ.j-nMmVTLXplaC4opGdZH32DUSWt1yD9Tm9hgB9M6oi4" // You're not supposed to use this example token (eckd) -} -``` */ -export interface ClientPayloadAuthenticate { - op: "AUTHENTICATE"; - d: string; +/** + * The Message payload. This is returned when you're provided information about a pre-existing + * message. + * + * ----- + * + * ### Example + * + * ```json + * { + * "author": { + * "id": 48615849987333, + * "username": "mlynar", + * "social_credit": 9999. + * "badges": 256, + * "permissions": 8 + * } + * "content": "Hello, World!" + * } + * ``` + */ +export interface Message extends MessageCreate { + /** The message's author. */ + author: User; } -export interface FileMetadataText { - type: "Text"; +/** + * The MessageCreate payload. This is used when you want to create a message using the REST API. + * + * ----- + * + * ### Example + * + * ```json + * { + * "content": "Hello, World!" + * } + * ``` + */ +export interface MessageCreate { + /** + * The message's content. This field has to be at-least 2 characters long. The upper limit + * is the instance's {@link InstanceInfo} `message_limit`. + * + * The content will be trimmed from leading and trailing whitespace. + */ + content: string; + _disguise?: MessageDisguise | null; } -export interface FileMetadataImage { - type: "Image"; - /** The image's width in pixels. */ - width?: number | null; - /** The image's height in pixels. */ - height?: number | null; +/** + * A temporary way to mask the message's author's name and avatar. This is mainly used for + * bridging and will be removed when webhooks are officially supported. + * + * ----- + * + * ### Example + * + * ```json + * { + * "name": "Jeff", + * "avatar": "https://some-u.rl/to/some-image.png" + * } + * ``` + */ +export interface MessageDisguise { + /** The name of the message's disguise. */ + name: string | null; + /** The URL of the message's disguise. */ + avatar: string | null; } -export interface FileMetadataVideo { - type: "Video"; - /** The video's width in pixels. */ - width?: number | null; - /** The video's height in pixels. */ - height?: number | null; +/** + * Rate limits that apply to Oprish (The REST API). + * + * ----- + * + * ### Example + * + * ```json + * { + * "getInstanceInfo": { + * "reset_after": 5, + * "limit": 2 + * }, + * "createMessage": { + * "reset_after": 5, + * "limit": 10 + * }, + * "createUser": { + * }, + * } + * ``` + */ +export interface OprishRateLimits { + /** Rate limits for the {@link getInstanceInfo} endpoint. */ + get_instance_info: RateLimitConf; + /** Rate limits for the {@link createMessage} endpoint. */ + create_message: RateLimitConf; + /** Rate limits for the {@link createUser} endpoint. */ + create_user: RateLimitConf; + /** Rate limits for the {@link verifyUser} endpoint. */ + verify_user: RateLimitConf; + /** Rate limits for the {@link getSelf}, {@link getUser} and {@link get_user_from_username} endpoints. */ + get_user: RateLimitConf; + /** + * Rate limits for the {@link getSelf}, {@link getUser} and {@link get_user_from_username} endpoints for + * someone who hasn't made an account. + */ + guest_get_user: RateLimitConf; + /** Rate limits for the {@link updateUser} enpoint. */ + update_user: RateLimitConf; + /** Rate limits for the {@link updateProfile} enpoint. */ + update_profile: RateLimitConf; + /** Rate limits for the {@link deleteUser} enpoint. */ + delete_user: RateLimitConf; + /** Rate limits for the {@link createPasswordResetCode} enpoint. */ + create_password_reset_code: RateLimitConf; + /** Rate limits for the {@link resetPassword} enpoint. */ + reset_password: RateLimitConf; + /** Rate limits for the {@link createSession} endpoint. */ + create_session: RateLimitConf; + /** Rate limits for the {@link getSessions} endpoint. */ + get_sessions: RateLimitConf; + /** Rate limits for the {@link deleteSession} endpoint. */ + delete_session: RateLimitConf; } -export interface FileMetadataOther { - type: "Other"; -} -/** Shared fields between all error response variants. */ -export interface SharedErrorData { - /** The HTTP status of the error. */ - status: number; - /** A brief explanation of the error. */ - message: string; +/** + * The DeleteCredentials payload. This is used in multiple places in the API to provide extra + * credentials for deleting important user-related stuff. + * + * ----- + * + * ### Example + * + * ```json + * { + * "password": "wowsuchpassword" + * } + * ``` + */ +export interface PasswordDeleteCredentials { + password: string; } -export type ServerPayload = - | ServerPayloadPong - | ServerPayloadRateLimit - | ServerPayloadHello - | ServerPayloadAuthenticated - | ServerPayloadUserUpdate - | ServerPayloadPresenceUpdate - | ServerPayloadMessageCreate; -/** The error when the client is missing authorization. This error often occurs when the user -doesn't pass in the required authentication or passes in invalid credentials. ------ - -### Example - -```json -{ - "type": "UNAUTHORIZED", - "status": 401, - "message": "The user is missing authentication or the passed credentials are invalid" -} -``` */ -export interface ErrorResponseUnauthorized extends SharedErrorData { - type: "UNAUTHORIZED"; +/** + * Represents a single rate limit. + * + * ----- + * + * ### Example + * + * ```json + * { + * "reset_after": 60, + * "limit": 30 + * } + * ``` + */ +export interface RateLimitConf { + /** The amount of seconds after which the rate limit resets. */ + reset_after: number; + /** The amount of requests that can be made within the `reset_after` interval. */ + limit: number; } -/** The error when a client *has* been succesfully authorized but does not have the required -permissions to execute an action. - ------ - -### Example -```json -{ - "type": "FORBIDDEN", - "status": 403, - "message": "The user is missing the requried permissions to execute this action", -} -``` */ -export interface ErrorResponseForbidden extends SharedErrorData { - type: "FORBIDDEN"; +/** + * The ResetPassword payload. This is used when the user wants to reset their password using a + * password reset code. + * + * ----- + * + * ### Example + * + * ```json + * { + * "code": 234567, + * "email": "someemail@ma.il", + * "password": "wow such security" + * } + * ``` + */ +export interface ResetPassword { + /** The password reset code the user got emailed. */ + code: number; + /** The user's email. */ + email: string; + /** The user's new password. */ + password: string; } -/** The error when a client requests a resource that does not exist. - ------ -### Example +/** Pandemonium websocket payloads sent by the server to the client. */ +export type ServerPayload = ServerPayloadPong | ServerPayloadRateLimit | ServerPayloadHello | ServerPayloadAuthenticated | ServerPayloadUserUpdate | ServerPayloadPresenceUpdate | ServerPayloadMessageCreate; -```json -{ - "type": "NOT_FOUND", - "status": 404, - "message": "The requested resource could not be found" -} -``` */ -export interface ErrorResponseNotFound extends SharedErrorData { - type: "NOT_FOUND"; +export interface ServerPayloadPong { + /** + * A {@link ClientPayload} `PING` payload response. + * + * ----- + * + * ### Example + * + * ```json + * { + * "op": "PONG" + * } + * ``` + */ + type: "_PONG"; } -/** The error when a client's request causes a conflict, usually when they're trying to create -something that already exists. - ------ - -### Example -```json -{ - "type": "CONFLICT", - "status": 409, - "message": "The request couldn't be completed due to conflicting with other data on the server", - "item": "username", -} -``` */ -export interface ErrorResponseConflict extends SharedErrorData { - type: "CONFLICT"; - /** The conflicting item. */ - item: string; +export interface ServerPayloadRateLimit { + /** + * The payload sent when the client gets gateway rate limited. + * + * The client is supposed to wait `wait` milliseconds before sending any more events, + * otherwise they are disconnected. + * + * ----- + * + * ### Example + * + * ```json + * { + * "op": "RATE_LIMIT", + * "d": { + * "wait": 1010 // 1.01 seconds + * } + * } + * ``` + */ + op: "_RATE_LIMIT"; + /** The amount of milliseconds you have to wait before the rate limit ends */ + wait: number; } -/** The error when a server isn't able to reduce a response even though the client's request -isn't explicitly wrong. This usually happens when an instance isn't configured to provide a -response. - ------ -### Example - -```json -{ - "type": "MISDIRECTED", - "status": 421, - "message": "Misdirected request", - "info": "The instance isn't configured to deal with unbased individuals" -} -``` */ -export interface ErrorResponseMisdirected extends SharedErrorData { - type: "MISDIRECTED"; - /** Extra information about what went wrong. */ - info: string; +export interface ServerPayloadHello { + /** + * The payload sent by the server when you initiate a new gateway connection. + * + * ----- + * + * ### Example + * + * ```json + * { + * "op": "HELLO", + * "d": { + * "heartbeat_interval": 45000, + * "instance_info": { + * "instance_name": "EmreLand", + * "description": "More based than Oliver's instance (trust)", + * "version": "0.3.3", + * "message_limit": 2048, + * "oprish_url": "https://example.com", + * "pandemonium_url": "https://example.com", + * "effis_url": "https://example.com", + * "file_size": 20000000, + * "attachment_file_size": 100000000 + * }, + * "rate_limit": { + * "reset_after": 10, + * "limit": 5 + * } + * } + * } + * ``` + */ + op: "_HELLO"; + /** The amount of milliseconds your ping interval is supposed to be. */ + heartbeat_interval: number; + /** + * The instance's info. + * + * This is the same payload you get from the {@link getInstanceInfo} payload without + * ratelimits + */ + instance_info: InstanceInfo; + /** The pandemonium ratelimit info. */ + rate_limit: RateLimitConf; } -/** The error when a request a client sends is incorrect and fails validation. ------ - -### Example +export interface ServerPayloadAuthenticated { + /** + * The payload sent when the client has successfully authenticated. This contains the data the + * user needs on startup. + * + * ----- + * + * ### Example + * + * ```json + * { + * "op": "AUTHENTICATED", + * "user": { + * "id": 48615849987334, + * "username": "barbaz", + * "social_credit": 3, + * "badges": 0, + * "permissions": 0 + * }, + * "users": [ + * { + * "id": 48615849987333, + * "username": "foobar", + * "social_credit": 42, + * "badges": 0, + * "permissions": 0 + * } + * ], + * } + * ``` + */ + op: "_AUTHENTICATED"; + user: User; + /** The currently online users who are relavent to the connector. */ + users: User[]; +} -```json -{ - "type": "VALIDATION", - "status": 422, - "message": "Invalid request", - "value_name": "author", - "info": "author name is a bit too cringe" +export interface ServerPayloadUserUpdate { + /** + * The payload received when a user updates themselves. This includes both user updates from + * the {@link updateUser} endpoint and profile updates from the {@link updateProfile} endpoint. + * + * ----- + * + * ### Example + * + * ```json + * { + * "id": 48615849987333, + * "username": "foobar", + * "social_credit": 42, + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + op: "_USER_UPDATE"; + d: User; } -``` */ -export interface ErrorResponseValidation extends SharedErrorData { - type: "VALIDATION"; - /** The name of the value that failed validation. */ - value_name: string; - /** Extra information about what went wrong. */ - info: string; + +export interface ServerPayloadPresenceUpdate { + /** + * The payload sent when a user's presence is updated. + * + * This is mainly used for when a user goes offline or online. + * + * ----- + * + * ### Example + * + * ```json + * { + * "user_id": 48615849987333, + * "status": { + * "type": "IDLE", + * "text": "BURY THE LIGHT DEEP WITHIN" + * } + * } + * ``` + */ + op: "_PRESENCE_UPDATE"; + user_id: number; + status: Status; } -/** The error when a client is rate limited. ------ +export interface ServerPayloadMessageCreate { + /** + * The payload sent when the client receives a {@link Message}. + * + * ----- + * + * ### Example + * + * ```json + * { + * "op": "MESSAGE_CREATE", + * "d": { + * "author": "A Certain Woo", + * "content": "Woo!" + * } + * } + * ``` + */ + op: "_MESSAGE_CREATE"; + d: Message; +} -### Example +/** + * The session payload. + * + * The user should ideally have one session for every client they have on every device. + * + * ----- + * + * ### Example + * + * ```json + * { + * "id": 2312155037697, + * "user_id": 2312155693057, + * "platform": "linux", + * "client": "pilfer" + * } + * ``` + */ +export interface Session { + /** The session's ID. */ + id: number; + /** The session user's ID. */ + user_id: number; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; + /** The session's creation IP address. */ + ip: string; +} -```json -{ - "type": "RATE_LIMITED", - "status": 429, - "message": "You have been rate limited", - "retry_after": 1234 +/** + * The SessionCreate payload. + * + * This is used to authenticate a user and obtain a token to interface with the API. + * + * ----- + * + * ### Example + * + * ```json + * { + * "identifier": "yendri", + * "password": "authentícame por favor", + * "platform": "linux", + * "client": "pilfer" + * } + * ``` + */ +export interface SessionCreate { + /** The session user's identifier. This can be either their email or username. */ + identifier: string; + /** The session user's password. */ + password: string; + /** The session's platform (linux, windows, mac, etc.) */ + platform: string; + /** The client the session was created by. */ + client: string; } -``` */ -export interface ErrorResponseRateLimited extends SharedErrorData { - type: "RATE_LIMITED"; - /** The amount of milliseconds you're still rate limited for. */ - retry_after: number; + +/** + * The response to a {@link SessionCreate}. + * + * ----- + * + * ### Example + * + * ```json + * { + * "token": "", + * "session": { + * "indentifier": "yendri", + * "password": "authentícame por favor", + * "platform": "linux", + * "client": "pilfer" + * } + * } + * ``` + */ +export interface SessionCreated { + /** The session's token. This can be used by the user to properly interface with the API. */ + token: string; + /** The session object that was created. */ + session: Session; } -/** The error when the server fails to process a request. -Getting this error means that it's the server's fault and not the client that the request -failed. +/** Shared fields between all error response variants. */ +export interface SharedErrorData { + /** The HTTP status of the error. */ + status: number; + /** A brief explanation of the error. */ + message: string; +} ------ +/** + * A user's status. + * + * ----- + * + * ### Example + * + * ```json + * { + * "type": "BUSY", + * "text": "ayúdame por favor", + * } + * ``` + */ +export interface Status { + type: StatusType; + text?: string | null; +} -### Example +/** + * The type of a user's status. + * + * This is a string. + */ +export type StatusType = StatusTypeOnline | StatusTypeOffline | StatusTypeIdle | StatusTypeBusy; -```json -{ - "type": "SERVER", - "status": 500, - "message": "Server encountered an unexpected error", - "info": "Server got stabbed 28 times" -} -``` */ -export interface ErrorResponseServer extends SharedErrorData { - type: "SERVER"; - /** Extra information about what went wrong. */ - info: string; +export interface StatusTypeOnline { + type: "Online"; } -/** Rate limits that apply to Oprish (The REST API). ------ +export interface StatusTypeOffline { + type: "Offline"; +} -### Example +export interface StatusTypeIdle { + type: "Idle"; +} -```json -{ - "get_instance_info": { - "reset_after": 5, - "limit": 2 - }, - "create_message": { - "reset_after": 5, - "limit": 10 - }, - "create_user": { - }, +export interface StatusTypeBusy { + type: "Busy"; } -``` */ -export interface OprishRateLimits { - /** Rate limits for the {@link get_instance_info} endpoint. */ - get_instance_info: RateLimitConf; - /** Rate limits for the {@link create_message} endpoint. */ - create_message: RateLimitConf; - /** Rate limits for the {@link create_user} endpoint. */ - create_user: RateLimitConf; - /** Rate limits for the {@link verify_user} endpoint. */ - verify_user: RateLimitConf; - /** Rate limits for the {@link get_self}, {@link get_user} and {@link get_user_from_username} endpoints. */ - get_user: RateLimitConf; - /** Rate limits for the {@link get_self}, {@link get_user} and {@link get_user_from_username} endpoints for -someone who hasn't made an account. */ - guest_get_user: RateLimitConf; - /** Rate limits for the {@link update_user} enpoint. */ - update_user: RateLimitConf; - /** Rate limits for the {@link update_profile} enpoint. */ - update_profile: RateLimitConf; - /** Rate limits for the {@link delete_user} enpoint. */ - delete_user: RateLimitConf; - /** Rate limits for the {@link create_password_reset_code} enpoint. */ - create_password_reset_code: RateLimitConf; - /** Rate limits for the {@link reset_password} enpoint. */ - reset_password: RateLimitConf; - /** Rate limits for the {@link create_session} endpoint. */ - create_session: RateLimitConf; - /** Rate limits for the {@link get_sessions} endpoint. */ - get_sessions: RateLimitConf; - /** Rate limits for the {@link delete_session} endpoint. */ - delete_session: RateLimitConf; + +/** + * The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded + * and won't affect the user. + * + * ----- + * + * ### Example + * + * ```json + * { + * "password": "authentícame por favor", + * "username": "yendli", + * "email": "yendli2@yemail.yom" + * } + * ``` + */ +export interface UpdateUser { + /** The user's current password for validation. */ + password: string; + /** The user's new username. */ + username?: string | null; + /** The user's new email. */ + email?: string | null; + /** The user's new password. */ + new_password?: string | null; } -/** Rate limits that apply to Effis (The CDN). - ------ - -### Example - -```json -{ - "assets": { - "reset_after": 60, - "limit": 5, - "file_size_limit": 30000000 - }, - "attachments": { - "reset_after": 180, - "limit": 20, - "file_size_limit": 500000000 - }, - "fetch_file": { - "reset_after": 60, - "limit": 30 - } -} -``` */ -export interface EffisRateLimits { - /** Rate limits for the asset buckets. */ - assets: EffisRateLimitConf; - /** Rate limits for the attachment bucket. */ - attachments: EffisRateLimitConf; - /** Rate limits for the file fetching endpoints. */ - fetch_file: RateLimitConf; + +/** + * The UpdateUserProfile payload. This payload is used to update a user's profile. The abscence of a + * field or it being `undefined` means that it won't have an effect. Explicitly setting a field as + * `null` will clear it. + * + * ----- + * + * ### Example + * + * ```json + * { + * "display_name": "HappyRu", + * "bio": "I am very happy!" + * } + * ``` + */ +export interface UpdateUserProfile { + /** The user's new display name. This field has to be between 2 and 32 characters long. */ + display_name?: string | null | null; + /** The user's new status. This field cannot be more than 150 characters long. */ + status?: string | null | null; + /** The user's new status type. This must be one of `ONLINE`, `OFFLINE`, `IDLE` and `BUSY`. */ + status_type?: StatusType | null; + /** The user's new bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ + bio?: string | null | null; + /** The user's new avatar. This field has to be a valid file ID in the "avatar" bucket. */ + avatar?: number | null | null; + /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ + banner?: number | null | null; } -/** The user payload. - ------ - -### Example - -```json -{ - "id": 48615849987333, - "username": "yendri", - "display_name": "Nicolas", - "social_credit": -69420, - "status": { - "type": "BUSY", - "text": "ayúdame por favor", - }, - "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", - "avatar": 2255112175647, - "banner": 2255049523230, - "badges": 0, - "permissions": 0 -} -``` */ + +/** + * The user payload. + * + * ----- + * + * ### Example + * + * ```json + * { + * "id": 48615849987333, + * "username": "yendri", + * "display_name": "Nicolas", + * "social_credit": -69420, + * "status": { + * "type": "BUSY", + * "text": "ayúdame por favor", + * }, + * "bio": "NICOLAAAAAAAAAAAAAAAAAAS!!!\n\n\nhttps://cdn.eludris.gay/static/nicolas.mp4", + * "avatar": 2255112175647, + * "banner": 2255049523230, + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ export interface User { /** The user's ID. */ id: number; @@ -900,183 +1292,611 @@ export interface User { /** The user's verification status. This is only shown when the user queries their own data. */ verified?: boolean | null; } -/** A {@link ClientPayload} `PING` payload response. - ------ -### Example - -```json -{ - "op": "PONG" -} -``` */ -export interface ServerPayloadPong { - op: "PONG"; -} -/** The payload sent when the client gets gateway rate limited. - -The client is supposed to wait `wait` milliseconds before sending any more events, -otherwise they are disconnected. - ------ - -### Example - -```json -{ - "op": "RATE_LIMIT", - "d": { - "wait": 1010 // 1.01 seconds - } -} -``` */ -export interface ServerPayloadRateLimit { - op: "RATE_LIMIT"; - d: { - /** The amount of milliseconds you have to wait before the rate limit ends */ - wait: number; - }; -} -/** The payload sent by the server when you initiate a new gateway connection. - ------ - -### Example - -```json -{ - "op": "HELLO", - "d": { - "heartbeat_interval": 45000, - "instance_info": { - "instance_name": "EmreLand", - "description": "More based than Oliver's instance (trust)", - "version": "0.3.3", - "message_limit": 2048, - "oprish_url": "https://example.com", - "pandemonium_url": "https://example.com", - "effis_url": "https://example.com", - "file_size": 20000000, - "attachment_file_size": 100000000 - }, - "rate_limit": { - "reset_after": 10, - "limit": 5 - } - } -} -``` */ -export interface ServerPayloadHello { - op: "HELLO"; - d: { - /** The amount of milliseconds your ping interval is supposed to be. */ - heartbeat_interval: number; - /** The instance's info. - -This is the same payload you get from the {@link get_instance_info} payload without -ratelimits */ - instance_info: InstanceInfo; - /** The pandemonium ratelimit info. */ - rate_limit: RateLimitConf; - }; -} -/** The payload sent when the client has successfully authenticated. This contains the data the -user needs on startup. - ------ - -### Example - -```json -{ - "op": "AUTHENTICATED", - "user": { - "id": 48615849987334, - "username": "barbaz", - "social_credit": 3, - "badges": 0, - "permissions": 0 - }, - "users": [ - { - "id": 48615849987333, - "username": "foobar", - "social_credit": 42, - "badges": 0, - "permissions": 0 - } - ], -} -``` */ -export interface ServerPayloadAuthenticated { - op: "AUTHENTICATED"; - d: { - user: User; - /** The currently online users who are relavent to the connector. */ - users: User[]; - }; -} -/** The payload received when a user updates themselves. This includes both user updates from -the {@link update_user} endpoint and profile updates from the {@link update_profile} endpoint. - ------ - -### Example - -```json -{ - "id": 48615849987333, - "username": "foobar", - "social_credit": 42, - "badges": 0, - "permissions": 0 -} -``` */ -export interface ServerPayloadUserUpdate { - op: "USER_UPDATE"; - d: User; -} -/** The payload sent when a user's presence is updated. - -This is mainly used for when a user goes offline or online. - ------ - -### Example - -```json -{ - "user_id": 48615849987333, - "status": { - "type": "IDLE", - "text": "BURY THE LIGHT DEEP WITHIN" - } -} -``` */ -export interface ServerPayloadPresenceUpdate { - op: "PRESENCE_UPDATE"; - d: { - user_id: number; - status: Status; - }; +/** + * The UserCreate payload. + * + * This is used when a user is initially first created. For authentication payloads check + * {@link SessionCreate}. + * + * ----- + * + * ### Example + * + * ```json + * { + * "username": "yendri",d + * "email": "yendri@llamoyendri.io", + * "password": "authentícame por favor" // don't actually use this as a password + * } + * ``` + */ +export interface UserCreate { + /** + * The user's name. + * + * This is different to their `display_name` as it denotes how they're more formally + * referenced by the API. + */ + username: string; + /** The user's email. */ + email: string; + /** The user's password. */ + password: string; } -/** The payload sent when the client receives a {@link Message}. - ------ +export const ROUTES = { + /** + * Get an attachment by ID. + * This is a shortcut to {@link downloadFile} with the attachments bucket. + * + * The `Content-Deposition` header is set to `attachment`. + * Use the {@link getAttachment} endpoint to get `Content-Deposition` set to `inline`. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://cdn.eludris.gay/attachments/2199681302540/download + * + * + * ``` + */ + downloadAttachment, + /** + * Download a file by ID from a specific bucket. + * + * The `Content-Deposition` header is set to `attachment`. + * Use the {@link getFile} endpoint to get `Content-Deposition` set to `inline`. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://cdn.eludris.gay/attachments/2198189244420/download + * + * + * ``` + */ + downloadFile, + /** + * Download a static file by its name. + * Static files are added by the instance owner and cannot be externally modified. + * + * The `Content-Deposition` header is set to `attachment`. + * Use the {@link getStaticFile} endpoint to get `Content-Deposition` set to `inline`. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://cdn.eludris.gay/static/pengin.mp4/download + * + * + * ``` + */ + downloadStaticFile, + /** + * Get an attachment by ID. + * This is a shortcut to {@link getFile} with the attachments bucket. + * + * The `Content-Deposition` header is set to `inline`. + * Use the {@link downloadAttachment} endpoint to get `Content-Deposition` set to `attachment`. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://cdn.eludris.gay/2199681302540 + * + * + * ``` + */ + getAttachment, + /** + * Get a file's metadata by ID from a specific bucket. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * https://cdn.eludris.gay/2198189244420/data + * + * { + * "id": 2199681302540, + * "name": "thang-big.png", + * "bucket": "attachments", + * "metadata": { + * "type": "image", + * "width": 702, + * "height": 702 + * } + * } + * ``` + */ + getAttachmentData, + /** + * Get a file by ID from a specific bucket. + * + * The `Content-Deposition` header is set to `inline`. + * Use the {@link downloadFile} endpoint to get `Content-Deposition` set to `attachment`. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://cdn.eludris.gay/attachments/2198189244420 + * + * + * ``` + */ + getFile, + /** + * Get a file's metadata by ID from a specific bucket. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * https://cdn.eludris.gay/attachments/2198189244420/data + * + * { + * "id": 2198189244420, + * "name": "trolley.mp4", + * "bucket": "attachments", + * "spoiler": true, + * "metadata": { + * "type": "video", + * "width": 576, + * "height": 682 + * } + * } + * ``` + */ + getFileData, + /** + * Get a static file by its name. + * Static files are added by the instance owner and cannot be externally modified. + * + * The `Content-Deposition` header is set to `inline`. + * Use the {@link downloadStaticFile} endpoint to get `Content-Deposition` set to `attachment`. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://cdn.eludris.gay/static/pengin.mp4 + * + * + * ``` + */ + getStaticFile, + /** + * Upload an attachment to Effis under a specific bucket. + * This is a shortcut to {@link uploadFile} with the attachments bucket. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -F file=@thang-big.png \ + * -F spoiler=false \ + * https://cdn.eludris.gay/ + * + * { + * "id": 2199681302540, + * "name": "thang-big.png", + * "bucket": "attachments", + * "metadata": { + * "type": "image", + * "width": 702, + * "height": 702 + * } + * } + * ``` + */ + uploadAttachment, + /** + * Upload a file to Effis under a specific bucket. + * At the moment, only the attachments bucket is supported. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -F file=@trolley.mp4 \ + * -F spoiler=true \ + * https://cdn.eludris.gay/attachments/ + * + * { + * "id": 2198189244420, + * "name": "trolley.mp4", + * "bucket": "attachments", + * "spoiler": true, + * "metadata": { + * "type": "video", + * "width": 576, + * "height": 682 + * } + * } + * ``` + */ + uploadFile, + /** + * Post a message to Eludris. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * --json '{"author":"Not a weeb","content":"Hello, World!"}' \ + * https://api.eludris.gay/messages + * + * { + * "author": "Not a weeb", + * "content": "Hello, World!" + * } + * ``` + */ + createMessage, + /** + * Send a password reset code to your email. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * --json '{"email": "yendri@llamoyendri.io"}' \ + * https://api.eludris.gay/users/reset-password + * ``` + */ + createPasswordResetCode, + /** + * Create a new session. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * --json '{ + * "identifier": "yendri", + * "password": "authentícame por favor", + * "platform": "linux", + * "client": "pilfer" + * }' \ + * https://api.eludris.gay/sessions + * + * { + * "token": "", + * "session": { + * "id": 2472278163458, + * "user_id": 48615849987333, + * "platform": "linux", + * "client": "pilfer", + * "ip": "fc00:e10d:7150:b1gb:00b5:f00d:babe:1337" + * } + * } + * ``` + */ + createSession, + /** + * Create a new user. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * --json '{ + * "username": "yendri", + * "email": "yendri@llamoyendri.io", + * "password": "authentícame por favor" + * }' \ + * https://api.eludris.gay/users + * + * { + * "id": 48615849987333, + * "username": "yendri", + * "social_credit": 0, + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + createUser, + /** + * Delete a session. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -X DELETE \ + * -H "Authorization: " \ + * https://api.eludris.gay/sessions/2342734331909 + * ``` + */ + deleteSession, + /** + * Delete your user. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -X DELETE \ + * -H "Authorization: " \ + * --json '{"password": "wowsuchpassword"}' + * https://api.eludris.gay/users + * ``` + */ + deleteUser, + /** + * Get information about the instance you're sending this request to. + * + * Most of this data comes from the instance's configuration. + * + * ----- + * + * ### Example + * + * ```sh + * curl https://api.eludris.gay/?rate_limits + * + * { + * "instance_name": "eludris", + * "description": "The *almost* official Eludris instance - ooliver.", + * "version": "0.3.2", + * "message_limit": 2000, + * "oprish_url": "https://api.eludris.gay", + * "pandemonium_url": "wss://ws.eludris.gay/", + * "effis_url": "https://cdn.eludris.gay", + * "file_size": 20000000, + * "attachment_file_size": 25000000, + * "rate_limits": { + * "oprish": { + * "info": { + * "reset_after": 5, + * "limit": 2 + * }, + * "message_create": { + * "reset_after": 5, + * "limit": 10 + * } + * }, + * "pandemonium": { + * "reset_after": 10, + * "limit": 5 + * }, + * "effis": { + * "assets": { + * "reset_after": 60, + * "limit": 5, + * "file_size_limit": 30000000 + * }, + * "attachments": { + * "reset_after": 180, + * "limit": 20, + * "file_size_limit": 500000000 + * }, + * "fetch_file": { + * "reset_after": 60, + * "limit": 30 + * } + * } + * } + * } + * ``` + */ + getInstanceInfo, + /** + * Get your own user. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -H "Authorization: " \ + * https://api.eludris.gay/users/@me + * + * { + * "id": 48615849987333, + * "username": "yendri", + * "social_credit": 0, + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + getSelf, + /** + * Get all sessions. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -H "Authorization: " \ + * https://api.eludris.gay/sessions + * + * [ + * { + * "id": 2472278163458, + * "user_id": 48615849987333, + * "platform": "linux", + * "client": "pilfer", + * "ip": "fc00:e10d:7150:b1gb:00b5:f00d:babe:1337" + * }, + * { + * "id": 2472278163867, + * "user_id": 48615849987333, + * "platform": "python", + * "client": "velum", + * "ip": "127.0.0.1" + * } + * ] + * ``` + */ + getSessions, + /** + * Get a user by ID. + * + * This does not require authorization, but authorized users will get a separate rate limit + * which is usually (hopefully) higher than the guest rate limit. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -H "Authorization: " \ + * https://api.eludris.gay/users/48615849987333 + * + * { + * "id": 48615849987333, + * "username": "yendri", + * "social_credit": 0, + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + getUser, + /** + * Get a user by their username. + * + * This does not require authorization, but authorized users will get a separate rate limit + * which is usually (hopefully) higher than the guest rate limit. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -H "Authorization: " \ + * https://api.eludris.gay/users/yendri + * + * { + * "id": 48615849987333, + * "username": "yendri", + * "social_credit": 0, + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + getUserWithUsername, + /** + * Reset your password using the password reset code. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -X PATCH \ + * --json '{"code":234567,"email":"someemail@ma.il","password":"wow such security"}' \ + * https://api.eludris.gay/users/reset-password + * ``` + */ + resetPassword, + /** + * Modify your profile. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -H "Authorization: " \ + * -X PATCH + * --json '{"display_name":"HappyRu","bio":"I am very happy!"}' + * https://api.eludris.gay/users/profile + * + * { + * "id": 2346806935553 + * "username": "yendri" + * "display_name": "HappyRu" + * "social_credit": 0, + * "bio": "I am very happy!" + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + updateProfile, + /** + * Modify your user account. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -H "Authorization: " \ + * -X PATCH + * --json '{"email":"nicolas.maduro@presidencia.gob.ve","username":"nicolas"}' + * https://api.eludris.gay/users + * + * { + * "id": 2346806935553 + * "username": "nicolas" + * "display_name": "HappyRu" + * "social_credit": 0, + * "bio": "I am very happy!" + * "badges": 0, + * "permissions": 0 + * } + * ``` + */ + updateUser, + /** + * Verify your email address. + * + * ----- + * + * ### Example + * + * ```sh + * curl \ + * -X POST \ + * -H "Authorization: " \ + * https://api.eludris.gay/users/verify?code=123456 + * ``` + */ + verifyUser, +}; -### Example - -```json -{ - "op": "MESSAGE_CREATE", - "d": { - "author": "A Certain Woo", - "content": "Woo!" - } -} -``` */ -export interface ServerPayloadMessageCreate { - op: "MESSAGE_CREATE"; - d: Message; -} diff --git a/yarn.lock b/yarn.lock index e812f61..92a536f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -141,6 +141,37 @@ resolved "https://registry.yarnpkg.com/@mxssfd/typedoc-theme/-/typedoc-theme-1.1.2.tgz#cd17ef3227c7093e249a0432893c201a836d382c" integrity sha512-Q/9Z+sff8ey92PaB7bnsGOfyNa85vTjyofO8EOH8KwEdfGnV4lGXwLFt4AUth7CCqYplqI9q4JxHNt869mlEcw== +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@ts-morph/common@~0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.20.0.tgz#3f161996b085ba4519731e4d24c35f6cba5b80af" + integrity sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q== + dependencies: + fast-glob "^3.2.12" + minimatch "^7.4.3" + mkdirp "^2.1.6" + path-browserify "^1.0.1" + "@types/node@^20.2.5": version "20.2.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" @@ -179,11 +210,23 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +code-block-writer@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-12.0.0.tgz#4dd58946eb4234105aff7f0035977b2afdc2a770" + integrity sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -217,6 +260,31 @@ esbuild@~0.17.6: "@esbuild/win32-ia32" "0.17.19" "@esbuild/win32-x64" "0.17.19" +fast-glob@^3.2.12: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -239,6 +307,13 @@ get-tsconfig@^4.4.0: resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.5.0.tgz#6d52d1c7b299bd3ee9cd7638561653399ac77b0f" integrity sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ== +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -269,6 +344,23 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-valid-identifier@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-valid-identifier/-/is-valid-identifier-2.0.2.tgz#146d9dbf29821b8118580b039d2203aa4bd1da4b" @@ -291,6 +383,19 @@ marked@^4.3.0: resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -298,6 +403,13 @@ minimatch@^3.1.1: dependencies: brace-expansion "^1.1.7" +minimatch@^7.4.3: + version "7.4.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb" + integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.0: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -305,6 +417,11 @@ minimatch@^9.0.0: dependencies: brace-expansion "^2.0.1" +mkdirp@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-2.1.6.tgz#964fbcb12b2d8c5d6fbc62a963ac95a273e2cc19" + integrity sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A== + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -317,11 +434,31 @@ once@^1.3.0: dependencies: wrappy "1" +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -329,6 +466,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + shiki@^0.14.1: version "0.14.3" resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.3.tgz#d1a93c463942bdafb9866d74d619a4347d0bbf64" @@ -352,6 +496,21 @@ source-map@^0.6.0: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-morph@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-19.0.0.tgz#43e95fb0156c3fe3c77c814ac26b7d0be2f93169" + integrity sha512-D6qcpiJdn46tUqV45vr5UGM2dnIEuTGNxVhg0sk5NX11orcouwj6i1bMqZIz2mZTZB1Hcgy7C3oEVhAT+f6mbQ== + dependencies: + "@ts-morph/common" "~0.20.0" + code-block-writer "^12.0.0" + tsx@^3.12.7: version "3.12.7" resolved "https://registry.yarnpkg.com/tsx/-/tsx-3.12.7.tgz#b3b8b0fc79afc8260d1e14f9e995616c859a91e9" From 3f6d081c3d98a52f606747de14612215d4895c52 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 22:19:10 +0200 Subject: [PATCH 11/18] docs: fix typedoc.json --- typedoc.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/typedoc.json b/typedoc.json index 116e61e..c5641a1 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,10 +1,10 @@ { "$schema": "https://typedoc.org/schema.json", - "entryPoints": [".src/*"], - "out": "./docs", - "plugin": ["@mxssfd/typedoc-theme"], + "entryPoints": ["./src/*"], + "out": "./docs", + "plugin": ["@mxssfd/typedoc-theme"], "theme": "my-theme", - "name": "eludris-api-types", - "readme": "./README.md", - "hideGenerator": true + "name": "eludris-api-types", + "readme": "./README.md", + "hideGenerator": true } From 7257d4a35335448054af761f31752f35e2f6dbe3 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 22:19:36 +0200 Subject: [PATCH 12/18] chore: add docs command --- package.json | 3 ++- tinker.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 tinker.ts diff --git a/package.json b/package.json index e952eac..1e86197 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ "scripts": { "dev": "tsc -w", "clean": "rimraf dist", - "build": "tsc && find dist -type f -name \"*.js\" | xargs -I {} gen-esm-wrapper {} {}.mjs" + "build": "tsc && find dist -type f -name \"*.js\" | xargs -I {} gen-esm-wrapper {} {}.mjs", + "docs": "yarn run typedoc" }, "files": [ "dist" diff --git a/tinker.ts b/tinker.ts new file mode 100644 index 0000000..cff8347 --- /dev/null +++ b/tinker.ts @@ -0,0 +1,3 @@ +import { ROUTES } from "./src/v0.4.0-alpha1"; + +ROUTES \ No newline at end of file From 911d2ab5590023d8a7a911f7bcade14a3e3d0277 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 22:36:42 +0200 Subject: [PATCH 13/18] docs: update readme - add link to docs --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ca94ecf..3b66ea8 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -# Discord API Types +# Eludris API Types [![GitHub](https://img.shields.io/github/license/eludris-community/eludris-api-types?style=flat-square)](https://github.com/eludris-community/eludris-api-types/blob/main/LICENSE.md) [![npm](https://img.shields.io/npm/v/eludris-api-types?color=crimson&logo=npm&style=flat-square)](https://www.npmjs.com/package/eludris-api-types) +[![docs](https://img.shields.io/badge/docs-eludris--api--types-black?style=flat-square&logo=vercel)](https://next-eludris-api-types.vercel.app/) - -Simple type definitions for the [Eludris API](https://eludris.github.io/docs). +Simple type definitions and routes for the [Eludris API](https://eludevs.pages.dev/). ## Installation @@ -14,4 +14,4 @@ Install with [npm](https://www.npmjs.com/) / [yarn](https://yarnpkg.com) / [pnpm npm install eludris-api-types yarn add eludris-api-types pnpm add eludris-api-types -``` \ No newline at end of file +``` From c197bbc821068ab1590d5d2aade3ad62d6afd9e9 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 22:39:54 +0200 Subject: [PATCH 14/18] chore: remove tinker.ts --- tinker.ts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 tinker.ts diff --git a/tinker.ts b/tinker.ts deleted file mode 100644 index cff8347..0000000 --- a/tinker.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ROUTES } from "./src/v0.4.0-alpha1"; - -ROUTES \ No newline at end of file From 1a48c24b99b00713f69a4c825ee3c4d99d3641e1 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Sat, 29 Jul 2023 00:37:20 +0200 Subject: [PATCH 15/18] fix: bugs --- autotype/main.ts | 101 +++++++++++----- package.json | 2 + src/v0.4.0-alpha1.ts | 272 +++++++++++++++++++++++++------------------ yarn.lock | 10 ++ 4 files changed, 239 insertions(+), 146 deletions(-) diff --git a/autotype/main.ts b/autotype/main.ts index fb8a626..6f9240a 100644 --- a/autotype/main.ts +++ b/autotype/main.ts @@ -1,11 +1,8 @@ -import { open, stat } from "fs/promises"; +import { stat } from "fs/promises"; import { createInterface } from "readline/promises"; import { - CodeBlockWriter, Project, - Scope, SourceFile, - StructureKind, } from "ts-morph"; import { EnumInfo, @@ -16,6 +13,9 @@ import { StructInfo, VariantType, } from "./types"; + +import { snakeCase } from "lodash"; + import { argv } from "process"; main(argv[2], argv[3]); @@ -26,7 +26,8 @@ const converters: Map string> = new Map([ [/^(u|i)(size|\d\d)$/, (str) => "number"], [ /^Option<.+>/, - (str) => convertType(str.replace(/^Option<(.+)>$/, "$1")) + " | null", + (str) => + convertType(str.replace(/^(?:Option<)+([^<>]+)>*$/, "$1")) + " | null", ], [/^bool$/, (_) => "boolean"], [/^TempFile$/, (_) => "unknown"], @@ -45,8 +46,10 @@ function convertType(type: string): string { } function switchCase(content: string, newCase: string | null): string { - if (newCase == "SCREAMING_SNAKE_CASE") { - return content.replace(/(\S)([A-Z])/gm, "$1_$2").toUpperCase(); + if (newCase === "SCREAMING_SNAKE_CASE") { + return `"${snakeCase(content).toUpperCase()}"`; + } else if (newCase === "UPPERCASE") { + return content.toUpperCase(); } return content; } @@ -57,7 +60,14 @@ async function main(inventoryIndex: string, output: string) { items: string[]; } = await (await fetch(`${inventoryIndex}/index.json`)).json(); - if (await stat(`${output}/v${inventory["version"]}.ts`)) { + let exists = true; + await stat(`${output}/v${inventory["version"]}.ts`, + ).catch(() => { + exists = false; + }); + + + if (exists) { console.log( `[INFO] v${inventory["version"]}.ts already exists, do you want to overwrite it?` ); @@ -140,11 +150,7 @@ class Builder { writer.writeLine("export const ROUTES = {"); for (const route of this.routes) { //docs - writer.writeLine(`/**`); - let doc = " * " + this.convertDoc(route.doc).split("\n").join("\n * ") - doc = doc.replace(/\* \n/g, "*\n") - writer.writeLine(doc); - writer.writeLine(`*/`); + writer.writeLine(formatDocString(route.doc)); writer.writeLine(`${convertToCamelCase(route.name)},`); } @@ -194,13 +200,26 @@ class Builder { variantInterface.setIsExported(true); if (variant.type === VariantType.Unit) { - const property = variantInterface.addProperty({ - name: "type", - type: switchCase(`"${variant.name}"`, item.rename_all), - }); + if (item.tag) { + const property = variantInterface.addProperty({ + name: item.tag, + type: switchCase(`"${variant.name}"`, item.rename_all), + }); - if (variant.doc) { - property.addJsDoc(this.convertDoc(variant.doc)); + if (variant.doc) { + property.addJsDoc(this.convertDoc(variant.doc)); + } + } else { + variantInterface.remove(); + const typeAlias = this.sourceFile.addTypeAlias({ + name: name + variant.name, + type: switchCase(`"${variant.name}"`, item.rename_all), + }); + if (variant.doc) { + typeAlias.addJsDoc(this.convertDoc(variant.doc)); + } + + continue; } } else if (variant.type === VariantType.Tuple) { if (!item.tag) { @@ -235,22 +254,35 @@ class Builder { if (variant.doc) { property.addJsDoc(this.convertDoc(variant.doc)); } - - for (const field of variant.fields) { - if (field.flattened) { - variantInterface.addExtends(convertType(field.field_type)); - } else { - const property = variantInterface.addProperty({ - name: field.name, - type: convertType(field.field_type), - hasQuestionToken: field.ommitable, - }); - - if (field.doc) { - property.addJsDoc(this.convertDoc(field.doc)); + let toExtend: string[] = []; + variantInterface.addMember((writer) => { + writer.writeLine(`${item.content}: {`); + for (const field of variant.fields) { + if (field.flattened) { + toExtend.push(convertType(field.field_type)); + } else { + if (field.doc) { + writer.writeLine(formatDocString(field.doc)); + } + + writer.write(`${field.name}`); + + if (field.ommitable) { + writer.write("?"); + } + + writer.write(": "); + + writer.write(convertType(field.field_type)); + writer.write(";\n"); } } + writer.writeLine("}"); + }); + for (const type of toExtend) { + variantInterface.addExtends(type); } + } } } @@ -305,3 +337,8 @@ class Builder { function convertToCamelCase(str: string) { return str.replace(/_(\w)/g, (_, c) => c.toUpperCase()); } + +function formatDocString(doc: string): string { + const formattedDoc = " * " + doc.split("\n").join("\n * ").replace(/\* \n/g, "*\n"); + return `/**\n${formattedDoc}\n */`; +} \ No newline at end of file diff --git a/package.json b/package.json index 1e86197..9c5b6ca 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,10 @@ }, "devDependencies": { "@mxssfd/typedoc-theme": "^1.1.2", + "@types/lodash": "^4.14.196", "@types/node": "^20.2.5", "gen-esm-wrapper": "^1.1.3", + "lodash": "^4.17.21", "rimraf": "^3.0.2", "ts-morph": "^19.0.0", "tsx": "^3.12.7", diff --git a/src/v0.4.0-alpha1.ts b/src/v0.4.0-alpha1.ts index 0dafc4d..0413bc6 100644 --- a/src/v0.4.0-alpha1.ts +++ b/src/v0.4.0-alpha1.ts @@ -125,7 +125,7 @@ export interface ClientPayloadPing { * } * ``` */ - type: "_PING"; + op: "PING"; } export interface ClientPayloadAuthenticate { @@ -144,7 +144,7 @@ export interface ClientPayloadAuthenticate { * } * ``` */ - op: "_AUTHENTICATE"; + op: "AUTHENTICATE"; d: string; } @@ -246,7 +246,9 @@ export interface ErrorResponseUnauthorized extends SharedErrorData { * } * ``` */ - type: "_UNAUTHORIZED"; + type: "UNAUTHORIZED"; + null: { + } } export interface ErrorResponseForbidden extends SharedErrorData { @@ -266,7 +268,9 @@ export interface ErrorResponseForbidden extends SharedErrorData { * } * ``` */ - type: "_FORBIDDEN"; + type: "FORBIDDEN"; + null: { + } } export interface ErrorResponseNotFound extends SharedErrorData { @@ -285,7 +289,9 @@ export interface ErrorResponseNotFound extends SharedErrorData { * } * ``` */ - type: "_NOT_FOUND"; + type: "NOT_FOUND"; + null: { + } } export interface ErrorResponseConflict extends SharedErrorData { @@ -306,9 +312,13 @@ export interface ErrorResponseConflict extends SharedErrorData { * } * ``` */ - type: "_CONFLICT"; - /** The conflicting item. */ - item: string; + type: "CONFLICT"; + null: { + /** + * The conflicting item. + */ + item: string; + } } export interface ErrorResponseMisdirected extends SharedErrorData { @@ -330,9 +340,13 @@ export interface ErrorResponseMisdirected extends SharedErrorData { * } * ``` */ - type: "_MISDIRECTED"; - /** Extra information about what went wrong. */ - info: string; + type: "MISDIRECTED"; + null: { + /** + * Extra information about what went wrong. + */ + info: string; + } } export interface ErrorResponseValidation extends SharedErrorData { @@ -353,11 +367,17 @@ export interface ErrorResponseValidation extends SharedErrorData { * } * ``` */ - type: "_VALIDATION"; - /** The name of the value that failed validation. */ - value_name: string; - /** Extra information about what went wrong. */ - info: string; + type: "VALIDATION"; + null: { + /** + * The name of the value that failed validation. + */ + value_name: string; + /** + * Extra information about what went wrong. + */ + info: string; + } } export interface ErrorResponseRateLimited extends SharedErrorData { @@ -377,9 +397,13 @@ export interface ErrorResponseRateLimited extends SharedErrorData { * } * ``` */ - type: "_RATE_LIMITED"; - /** The amount of milliseconds you're still rate limited for. */ - retry_after: number; + type: "RATE_LIMITED"; + null: { + /** + * The amount of milliseconds you're still rate limited for. + */ + retry_after: number; + } } export interface ErrorResponseServer extends SharedErrorData { @@ -402,9 +426,13 @@ export interface ErrorResponseServer extends SharedErrorData { * } * ``` */ - type: "_SERVER"; - /** Extra information about what went wrong. */ - info: string; + type: "SERVER"; + null: { + /** + * Extra information about what went wrong. + */ + info: string; + } } /** @@ -469,27 +497,39 @@ export interface FileData { export type FileMetadata = FileMetadataText | FileMetadataImage | FileMetadataVideo | FileMetadataOther; export interface FileMetadataText { - type: "Text"; + type: "TEXT"; } export interface FileMetadataImage { - type: "Image"; - /** The image's width in pixels. */ - width?: number | null; - /** The image's height in pixels. */ - height?: number | null; + type: "IMAGE"; + null: { + /** + * The image's width in pixels. + */ + width?: number | null; + /** + * The image's height in pixels. + */ + height?: number | null; + } } export interface FileMetadataVideo { - type: "Video"; - /** The video's width in pixels. */ - width?: number | null; - /** The video's height in pixels. */ - height?: number | null; + type: "VIDEO"; + null: { + /** + * The video's width in pixels. + */ + width?: number | null; + /** + * The video's height in pixels. + */ + height?: number | null; + } } export interface FileMetadataOther { - type: "Other"; + type: "OTHER"; } /** @@ -866,7 +906,7 @@ export interface ServerPayloadPong { * } * ``` */ - type: "_PONG"; + op: "PONG"; } export interface ServerPayloadRateLimit { @@ -889,9 +929,13 @@ export interface ServerPayloadRateLimit { * } * ``` */ - op: "_RATE_LIMIT"; - /** The amount of milliseconds you have to wait before the rate limit ends */ - wait: number; + op: "RATE_LIMIT"; + d: { + /** + * The amount of milliseconds you have to wait before the rate limit ends + */ + wait: number; + } } export interface ServerPayloadHello { @@ -926,18 +970,24 @@ export interface ServerPayloadHello { * } * ``` */ - op: "_HELLO"; - /** The amount of milliseconds your ping interval is supposed to be. */ - heartbeat_interval: number; - /** - * The instance's info. - * - * This is the same payload you get from the {@link getInstanceInfo} payload without - * ratelimits - */ - instance_info: InstanceInfo; - /** The pandemonium ratelimit info. */ - rate_limit: RateLimitConf; + op: "HELLO"; + d: { + /** + * The amount of milliseconds your ping interval is supposed to be. + */ + heartbeat_interval: number; + /** + * The instance's info. + * + * This is the same payload you get from the [`get_instance_info`] payload without + * ratelimits + */ + instance_info: InstanceInfo; + /** + * The pandemonium ratelimit info. + */ + rate_limit: RateLimitConf; + } } export interface ServerPayloadAuthenticated { @@ -971,10 +1021,14 @@ export interface ServerPayloadAuthenticated { * } * ``` */ - op: "_AUTHENTICATED"; - user: User; - /** The currently online users who are relavent to the connector. */ - users: User[]; + op: "AUTHENTICATED"; + d: { + user: User; + /** + * The currently online users who are relavent to the connector. + */ + users: User[]; + } } export interface ServerPayloadUserUpdate { @@ -996,7 +1050,7 @@ export interface ServerPayloadUserUpdate { * } * ``` */ - op: "_USER_UPDATE"; + op: "USER_UPDATE"; d: User; } @@ -1020,9 +1074,11 @@ export interface ServerPayloadPresenceUpdate { * } * ``` */ - op: "_PRESENCE_UPDATE"; - user_id: number; - status: Status; + op: "PRESENCE_UPDATE"; + d: { + user_id: number; + status: Status; + } } export interface ServerPayloadMessageCreate { @@ -1043,7 +1099,7 @@ export interface ServerPayloadMessageCreate { * } * ``` */ - op: "_MESSAGE_CREATE"; + op: "MESSAGE_CREATE"; d: Message; } @@ -1166,22 +1222,10 @@ export interface Status { * This is a string. */ export type StatusType = StatusTypeOnline | StatusTypeOffline | StatusTypeIdle | StatusTypeBusy; - -export interface StatusTypeOnline { - type: "Online"; -} - -export interface StatusTypeOffline { - type: "Offline"; -} - -export interface StatusTypeIdle { - type: "Idle"; -} - -export interface StatusTypeBusy { - type: "Busy"; -} +type StatusTypeOnline = "ONLINE"; +type StatusTypeOffline = "OFFLINE"; +type StatusTypeIdle = "IDLE"; +type StatusTypeBusy = "BUSY"; /** * The UpdateUser payload. Any field set to `null`, `undefined` or is missing will be disregarded @@ -1228,17 +1272,17 @@ export interface UpdateUser { */ export interface UpdateUserProfile { /** The user's new display name. This field has to be between 2 and 32 characters long. */ - display_name?: string | null | null; + display_name?: string | null; /** The user's new status. This field cannot be more than 150 characters long. */ - status?: string | null | null; + status?: string | null; /** The user's new status type. This must be one of `ONLINE`, `OFFLINE`, `IDLE` and `BUSY`. */ status_type?: StatusType | null; /** The user's new bio. The upper limit is the instance's {@link InstanceInfo} `bio_limit`. */ - bio?: string | null | null; + bio?: string | null; /** The user's new avatar. This field has to be a valid file ID in the "avatar" bucket. */ - avatar?: number | null | null; + avatar?: number | null; /** The user's new banner. This field has to be a valid file ID in the "banner" bucket. */ - banner?: number | null | null; + banner?: number | null; } /** @@ -1327,10 +1371,10 @@ export interface UserCreate { export const ROUTES = { /** * Get an attachment by ID. - * This is a shortcut to {@link downloadFile} with the attachments bucket. + * This is a shortcut to [`download_file`] with the attachments bucket. * * The `Content-Deposition` header is set to `attachment`. - * Use the {@link getAttachment} endpoint to get `Content-Deposition` set to `inline`. + * Use the [`get_attachment`] endpoint to get `Content-Deposition` set to `inline`. * * ----- * @@ -1341,13 +1385,13 @@ export const ROUTES = { * * * ``` - */ + */ downloadAttachment, /** * Download a file by ID from a specific bucket. * * The `Content-Deposition` header is set to `attachment`. - * Use the {@link getFile} endpoint to get `Content-Deposition` set to `inline`. + * Use the [`get_file`] endpoint to get `Content-Deposition` set to `inline`. * * ----- * @@ -1358,14 +1402,14 @@ export const ROUTES = { * * * ``` - */ + */ downloadFile, /** * Download a static file by its name. * Static files are added by the instance owner and cannot be externally modified. * * The `Content-Deposition` header is set to `attachment`. - * Use the {@link getStaticFile} endpoint to get `Content-Deposition` set to `inline`. + * Use the [`get_static_file`] endpoint to get `Content-Deposition` set to `inline`. * * ----- * @@ -1376,14 +1420,14 @@ export const ROUTES = { * * * ``` - */ + */ downloadStaticFile, /** * Get an attachment by ID. - * This is a shortcut to {@link getFile} with the attachments bucket. + * This is a shortcut to [`get_file`] with the attachments bucket. * * The `Content-Deposition` header is set to `inline`. - * Use the {@link downloadAttachment} endpoint to get `Content-Deposition` set to `attachment`. + * Use the [`download_attachment`] endpoint to get `Content-Deposition` set to `attachment`. * * ----- * @@ -1394,7 +1438,7 @@ export const ROUTES = { * * * ``` - */ + */ getAttachment, /** * Get a file's metadata by ID from a specific bucket. @@ -1418,13 +1462,13 @@ export const ROUTES = { * } * } * ``` - */ + */ getAttachmentData, /** * Get a file by ID from a specific bucket. * * The `Content-Deposition` header is set to `inline`. - * Use the {@link downloadFile} endpoint to get `Content-Deposition` set to `attachment`. + * Use the [`download_file`] endpoint to get `Content-Deposition` set to `attachment`. * * ----- * @@ -1435,7 +1479,7 @@ export const ROUTES = { * * * ``` - */ + */ getFile, /** * Get a file's metadata by ID from a specific bucket. @@ -1460,14 +1504,14 @@ export const ROUTES = { * } * } * ``` - */ + */ getFileData, /** * Get a static file by its name. * Static files are added by the instance owner and cannot be externally modified. * * The `Content-Deposition` header is set to `inline`. - * Use the {@link downloadStaticFile} endpoint to get `Content-Deposition` set to `attachment`. + * Use the [`download_static_file`] endpoint to get `Content-Deposition` set to `attachment`. * * ----- * @@ -1478,11 +1522,11 @@ export const ROUTES = { * * * ``` - */ + */ getStaticFile, /** * Upload an attachment to Effis under a specific bucket. - * This is a shortcut to {@link uploadFile} with the attachments bucket. + * This is a shortcut to [`upload_file`] with the attachments bucket. * * ----- * @@ -1505,7 +1549,7 @@ export const ROUTES = { * } * } * ``` - */ + */ uploadAttachment, /** * Upload a file to Effis under a specific bucket. @@ -1533,7 +1577,7 @@ export const ROUTES = { * } * } * ``` - */ + */ uploadFile, /** * Post a message to Eludris. @@ -1552,7 +1596,7 @@ export const ROUTES = { * "content": "Hello, World!" * } * ``` - */ + */ createMessage, /** * Send a password reset code to your email. @@ -1566,7 +1610,7 @@ export const ROUTES = { * --json '{"email": "yendri@llamoyendri.io"}' \ * https://api.eludris.gay/users/reset-password * ``` - */ + */ createPasswordResetCode, /** * Create a new session. @@ -1596,7 +1640,7 @@ export const ROUTES = { * } * } * ``` - */ + */ createSession, /** * Create a new user. @@ -1622,7 +1666,7 @@ export const ROUTES = { * "permissions": 0 * } * ``` - */ + */ createUser, /** * Delete a session. @@ -1637,7 +1681,7 @@ export const ROUTES = { * -H "Authorization: " \ * https://api.eludris.gay/sessions/2342734331909 * ``` - */ + */ deleteSession, /** * Delete your user. @@ -1653,7 +1697,7 @@ export const ROUTES = { * --json '{"password": "wowsuchpassword"}' * https://api.eludris.gay/users * ``` - */ + */ deleteUser, /** * Get information about the instance you're sending this request to. @@ -1711,7 +1755,7 @@ export const ROUTES = { * } * } * ``` - */ + */ getInstanceInfo, /** * Get your own user. @@ -1733,7 +1777,7 @@ export const ROUTES = { * "permissions": 0 * } * ``` - */ + */ getSelf, /** * Get all sessions. @@ -1764,7 +1808,7 @@ export const ROUTES = { * } * ] * ``` - */ + */ getSessions, /** * Get a user by ID. @@ -1789,7 +1833,7 @@ export const ROUTES = { * "permissions": 0 * } * ``` - */ + */ getUser, /** * Get a user by their username. @@ -1814,7 +1858,7 @@ export const ROUTES = { * "permissions": 0 * } * ``` - */ + */ getUserWithUsername, /** * Reset your password using the password reset code. @@ -1829,7 +1873,7 @@ export const ROUTES = { * --json '{"code":234567,"email":"someemail@ma.il","password":"wow such security"}' \ * https://api.eludris.gay/users/reset-password * ``` - */ + */ resetPassword, /** * Modify your profile. @@ -1855,7 +1899,7 @@ export const ROUTES = { * "permissions": 0 * } * ``` - */ + */ updateProfile, /** * Modify your user account. @@ -1881,7 +1925,7 @@ export const ROUTES = { * "permissions": 0 * } * ``` - */ + */ updateUser, /** * Verify your email address. @@ -1896,7 +1940,7 @@ export const ROUTES = { * -H "Authorization: " \ * https://api.eludris.gay/users/verify?code=123456 * ``` - */ + */ verifyUser, }; diff --git a/yarn.lock b/yarn.lock index 92a536f..88325ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -172,6 +172,11 @@ mkdirp "^2.1.6" path-browserify "^1.0.1" +"@types/lodash@^4.14.196": + version "4.14.196" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.196.tgz#a7c3d6fc52d8d71328b764e28e080b4169ec7a95" + integrity sha512-22y3o88f4a94mKljsZcanlNWPzO0uBsBdzLAngf2tp533LzZcQzb6+eZPJ+vCTt+bqF2XnvT9gejTLsAcJAJyQ== + "@types/node@^20.2.5": version "20.2.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" @@ -373,6 +378,11 @@ jsonc-parser@^3.2.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lunr@^2.3.9: version "2.3.9" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" From 9d3ea6276521aee590026f792438db8e179c1c5c Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Fri, 28 Jul 2023 23:15:18 +0200 Subject: [PATCH 16/18] chore: bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c5b6ca..03e0201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eludris-api-types", - "version": "0.2.1-7", + "version": "0.2.1-13", "author": "teaishealthy", "license": "MIT", "exports": { From c61da8a167ffb597921f310e4d62de752596e570 Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Sat, 29 Jul 2023 14:01:48 +0200 Subject: [PATCH 17/18] docs: add api.json inventory --- typedoc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/typedoc.json b/typedoc.json index c5641a1..912337e 100644 --- a/typedoc.json +++ b/typedoc.json @@ -6,5 +6,6 @@ "theme": "my-theme", "name": "eludris-api-types", "readme": "./README.md", + "json": "./docs/api.json", "hideGenerator": true } From 8927f223c394d645ffa15f2260002003039271e6 Mon Sep 17 00:00:00 2001 From: teaishealthy <76410798+teaishealthy@users.noreply.github.com> Date: Sat, 29 Jul 2023 16:08:18 +0200 Subject: [PATCH 18/18] docs(README): change Discord to Eludris (#2) (#3) Co-authored-by: toolifelesstocode