From 3d4c04fcde7880bcbfd69411bb07242bbc02604d Mon Sep 17 00:00:00 2001 From: Filip Znachor Date: Wed, 26 Jun 2024 20:06:06 +0200 Subject: [PATCH] Initial commit --- package.json | 17 ++++++ src/API.ts | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 3 + 3 files changed, 181 insertions(+) create mode 100644 package.json create mode 100644 src/API.ts create mode 100644 src/index.ts diff --git a/package.json b/package.json new file mode 100644 index 0000000..9068635 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "oohost.js", + "version": "0.0.1", + "description": "TypeScript library for accessing the oohost API", + "main": "src/index.ts", + "license": "MIT", + "author": "oohost.cz", + "repository": { + "type": "git", + "url": "https://git.codespace.cz/oohost/oohost.js" + }, + "keywords": [ + "oohost", + "webhosting", + "api" + ] +} diff --git a/src/API.ts b/src/API.ts new file mode 100644 index 0000000..0217070 --- /dev/null +++ b/src/API.ts @@ -0,0 +1,161 @@ +/** + * Class for requesting API + */ +export default class API { + + /** + * Default API endpoint + */ + public static readonly defaultEndpoint = "https://api.oohost.cz/"; + + /** + * API endpoint + */ + public static endpoint = this.defaultEndpoint; + + /** + * Send request to the API and create Response + * @param url requested URL + * @param data request data + * @returns Response instance + */ + static async get(url: string, data: ComboObject = {}): Promise { + let opt: RequestInit = {method: "post", body: JSON.stringify(data), headers: {"Content-Type": "application/json"}, credentials: "include"}; + let res = (await fetch(API.endpoint + url, opt)); + return new Response(await res.json()); + } + +} + + +/** + * Response class + */ +export class Response { + + data: Response.Data = {}; + errors: Response.Error[] = []; + took: number; + success: boolean; + session?: string; + + /** + * Create Response instance from JSON response + * @param data JSON response + */ + constructor(data: ComboObject) { + + data = Object.assign({errors: ["api"], took: -1, success: false, session: undefined}, data); + + this.errors = data.errors; + delete data.errors; + + this.took = data.took; + delete data.took; + + this.success = data.success; + delete data.success; + + this.session = data.session; + delete data.session; + + this.data = data; + + } + + /** + * Get Reponse meta keys + * @returns meta keys + */ + get_meta() { + let keys: Response.MetaKeys[] = ["errors", "took", "success", "session"]; + let meta: ComboObject = {}; + keys.forEach(key => { + meta[key] = this[key]; + }); + return meta; + } + + /** + * Recreate original response + * @returns JSON response + */ + get() { + let response: Response.Main = Object.assign({}, this.data, {errors: this.errors, took: this.took, success: this.success, session: this.session}); + return response; + } + + /** + * Check if Response has specified error code + * @param error error code + * @returns boolean or ExtendedError + */ + has_error(error: string): Response.ExtendedError | boolean { + let found: boolean = false; + let response: Response.ExtendedError | undefined; + this.errors.forEach(err => { + if (typeof err == "string") { + if (error == err) found = true; + } else { + if (error == err.code) response = err; + } + }); + if (response) return response; + return found; + } + + /** + * Get all errors in Response + * @returns Response errors + */ + get_errors() { + let errors: Response.ExtendedError[] = []; + this.errors.forEach(err => { + if (typeof err == "string") errors.push({code: err}); + else errors.push(err); + }); + return errors; + } + + /** + * Get first error in Response + * @returns Response error + */ + get_error(): null | Response.ExtendedError { + let errors = this.get_errors(); + return errors[0] ? errors[0] : null; + } + + /** + * Get errors sorted by their relations + * @returns Related errors + */ + get_errors_related() { + let resp: Response.RelatedErrors = {}; + this.get_errors().forEach(e => { + let keys = ["global"]; + if (e.related_to) { + keys = Array.isArray(e.related_to) ? e.related_to : [e.related_to]; + } + keys.forEach(k => { + if (!resp[k]) resp[k] = []; + resp[k].push(e); + }); + }); + return resp; + } + +} + +export namespace Response { + export interface Main extends Data {errors: Error[], took: number | null, success: boolean} + export interface Data {[U: string]: any} + export type Error = string | ExtendedError; + export interface ExtendedError {code: string, related_to?: string | string[], [U: string]: any} + export type MetaKeys = "errors" | "took" | "success" | "session"; + export interface RelatedErrors {[U: string]: Response.ExtendedError[]} +} + +export interface ComboObject { + [U: string]: any +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..89ced82 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +import API from "./API"; + +export { API };