/** * @license * @preserve * * Copyright 2023 KeeeX SAS * * 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. * */ import { type Awaitable } from "@keeex/utils/types/types.js"; import * as filterSrv from "./full/filter.js"; import * as attachment from "./raw/attachment.js"; import { type ProgressFunc } from "./raw/progresscallback.js"; import { RequestError } from "./requesterror.js"; import type { RequestSettings } from "./raw/axios.js"; import type * as pagination from "./raw/pagination.js"; import type * as axios from "axios"; export type ErrorHandler = (error: Error) => void; export interface Hooks { /** Called before filtering input data */ preSend?: (input: InputDataType) => Awaitable; /** * Called right after Axios returns (and after the global postcall hook), but before the returned * values are processed. */ postCall?: (axiosResult: axios.AxiosResponse) => Awaitable; /** * Called after invalid status reply * * Not called for network/filtering error. * Should throw to propagate an exception to the caller; can also return with a valid input to * retrigger the call */ postError?: (error: RequestError, input: InputDataType) => Awaitable; /** Called after successful (valid status) Api call and after filtering reply */ postSuccess?: (result: ResultDataType) => Awaitable; } type AllowedPropsFilter = { [key in keyof Required]: InputType[key] extends object ? AllowedPropsFilter | boolean : boolean; }; /** Description of a single Api call */ interface ApiCallDescriptionBase { /** If defined, only fields set to true here will be used from input */ allowedProps?: AllowedPropsFilter; /** * Process input as an `AttachmentInput` object. * * If set, this overrides the behavior of all other input parameters. */ attachment?: boolean; /** Do the route require authentication? */ authenticated?: boolean; /** Extra custom axios options */ axiosOptions?: axios.AxiosRequestConfig; /** List of properties to take from the call input and put in the body */ bodyParams?: "raw" | Array; /** List of properties to take from the call input and handle as files */ fileParams?: Array; /** List of filters to apply to the input/output data */ filters?: filterSrv.ApiFilters; hooks?: Hooks; /** HTTP method */ method: axios.Method; /** * Is the request/result paginated? * * Use the new method with `paginatedApiCall()` instead of setting this flag manually. */ paginated?: boolean; /** List of properties to take from the call input and put in the query arguments */ queryParams?: Array; /** Queue name; requests from different queues will be executed in parallel. */ queue?: string; /** Route relative to the base URL provided in Sdk constructor */ route: string; /** * Expected "valid" status codes. * * If the reply have a status code not in that array, an exception is raised. * * Defaults to [HttpCodes.OK] */ validStatuses?: Array; } interface ApiCallDescriptionJson extends ApiCallDescriptionBase { /** Is the reply a binary buffer */ binaryReply?: false; } interface ApiCallDescriptionBinary extends ApiCallDescriptionBase { /** Is the reply a binary buffer */ binaryReply: true; } export type ApiCallDescription< /** Input provided by the caller */ InputDataType = undefined, /** Value returned to the caller */ ResultDataType = undefined, /** Reply value from Axios */ ReplyDataType = undefined> = ResultDataType extends Uint8Array ? ApiCallDescriptionBinary : ApiCallDescriptionJson; /** A single Api call created by the Sdk class */ export type ApiCall = I extends undefined ? (input?: I, progressCb?: ProgressFunc) => Promise : (input: I, progressCb?: ProgressFunc) => Promise; /** A single Api call created by the Sdk class that directly returns its result */ export type DirectApiCall = (input: I, progressCb?: ProgressFunc) => Promise; /** Same as above but without input. It helps with type definition (see issue #28) */ export type DirectApiCallNoParams = (progressCb?: ProgressFunc) => Promise; /** Put the authorization token in a HTTP header */ export interface AuthorizationSettingsHeader { /** * Name of the header * * Defaults to "Authorization" */ headerName?: string; type: "header"; /** * String to use the authorization token. * * The string %token% will be replaced by the provided token value. * * Defaults to "Bearer %token%" */ valueTemplate?: string; } /** * Use an authorization cookie. * * The cookie is automatically provided and reused by the underlying HTTP engine. */ export interface AuthorizationSettingsAutoCookie { type: "autocookie"; } /** Valid authorization modes */ export type AuthorizationSettings = AuthorizationSettingsHeader | AuthorizationSettingsAutoCookie; export type AuthToken = string | boolean; /** Base class to build an Sdk that perform semi-automatised Api calls */ export default class Sdk { #private; private readonly rawSdk; private readonly authorizationSettings?; private authToken?; constructor(requestSettings: RequestSettings, authorizationSettings?: AuthorizationSettings); /** Set an auth token for future Api calls */ setAuthToken: (authToken?: AuthToken) => void; private readonly createApiCallLow; private readonly createApiCall; /** Alternative to `createApiCall()` that only returns the result data */ directApiCall: (apiCallDescription: ApiCallDescription) => DirectApiCall; /** Alternative to `directApiCall()` that takes no input (helps with type definition) */ directApiCallNoParams: (apiCallDescription: ApiCallDescription) => DirectApiCallNoParams; /** * Alternative to `createApiCall()` that only returns the result data using pagination. * * The pagination used here does not honor the deprecated `pagination` setting in the Sdk * constructor. */ paginatedApiCall: (apiCallDescription: ApiCallDescription, pagination.PaginatedResponse, ReplyDataType> & { paginated?: true; }) => DirectApiCall, pagination.PaginatedResponse>; /** Alternative to `createApiCall()` to send a raw file as attachment */ attachmentApiCall: (apiCallDescription: ApiCallDescription & { allowedProps?: never; attachment?: true; bodyParams?: "raw"; fileParams?: never; filters?: never; paginated?: false; }) => DirectApiCall; } export {};