'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const DATA = { baseURL: "", headers: {}, params: {}, interceptors: { requests: [], responses: [], }, }; const addRequest = (callback) => { DATA.interceptors?.requests.push(callback); }; const addResponse = (callback) => { DATA.interceptors?.responses.push(callback); }; /** * Set the default configurations * * @param config IConfig * @returns undefined */ const setConfig = (config) => { DATA.baseURL = config?.baseURL; DATA.headers = { ...DATA.headers, ...(config?.headers ?? {}), }; DATA.params = { ...DATA.params, ...(config?.params ?? {}), }; }; const getConfig = () => { return { ...DATA, }; }; const SUFFIX_MAP = { "=": "", "<>": "$not", ">": "$gt", ">=": "$gte", "<": "$lt", "<=": "$lte", LIKE: "$like", "NOT LIKE": "$notLike", IN: "$in", "NOT IN": "$notIn", BETWEEN: "$between", "NOT BETWEEN": "$notBetween", NULL: "", "NOT NULL": "$not", }; class Resource { url; config; params; fieldArray; sortArray; q; queryPointers; overrideLogic; withPath; constructor(url) { this.config = getConfig(); this.url = url; this.params = new URLSearchParams(); this.fieldArray = []; this.sortArray = []; this.q = []; this.queryPointers = [this.q]; this.overrideLogic = undefined; this.withPath = undefined; } /** * Add additonal URLSearchParams to the request URL * * @param searchParams Record * @returns IQueryable */ searchParams(searchParams) { for (const key in searchParams) { this.params.append(key, searchParams[key]); } return this; } /** * Select the fields that will be fetched. * * Example: fields("id", "name", "surname") * * @param names string[] * @returns IQueryable */ fields(...names) { this.fieldArray = names; return this; } /** * Set the sorting option. * * Example: sort("id", "DESC") * * @param field string * @param type ASC | "DESC" * @returns IQueryable */ sort(field, type) { const expression = `${type === "DESC" ? "-" : ""}${field}`; this.sortArray.push(expression); return this; } /** * Add relation data query * * Example: .with("user{name,surname,role{title}}") * * @param field string * @returns IQueryable */ with(path) { if (!this.withPath) { this.withPath = ""; } this.withPath += `${path},`; return this; } andWhere(param1, param2, param3) { return this.applyWhere("$and", param1, param2, param3); } where(param1, param2, param3) { return this.applyWhere("$and", param1, param2, param3); } orWhere(param1, param2, param3) { return this.applyWhere("$or", param1, param2, param3); } /** * Add a not equal query * * Example: .whereNot("id", 1) * SQL: WHERE id <> 1 * * @param field string * @param value any * @returns IQueryable */ whereNot(field, value) { return this.addWhereCondition("$and", field, "<>", value); } /** * Add LIKE query * * Example: .whereLike("name", "*john*") * SQL: WHERE name LIKE '%john%' * * @param field string * @param value any * @returns IQueryable */ whereLike(field, value) { return this.addWhereCondition("$and", field, "LIKE", value); } /** * Add NOT LIKE query * * Example: .whereNotLike("name", "*john*") * SQL: WHERE name NOT LIKE '%john%' * * @param field string * @param value any * @returns IQueryable */ whereNotLike(field, value) { return this.addWhereCondition("$and", field, "NOT LIKE", value); } /** * Add IN query * * Example: .whereIn("id", [1, 2, 3]) * SQL: WHERE id IN [1, 2, 3] * * @param field string * @param value any * @returns IQueryable */ whereIn(field, value) { return this.addWhereCondition("$and", field, "IN", value); } /** * Add NOT IN query * * Example: .whereNotIn("id", [1, 2, 3]) * SQL: WHERE id NOT IN [1, 2, 3] * * @param field string * @param value any * @returns IQueryable */ whereNotIn(field, value) { return this.addWhereCondition("$and", field, "NOT IN", value); } /** * Add BETWEEN query * * Example: .whereBetween("id", 1, 100]) * SQL: WHERE id BETWEEN [1, 100] * * @param field string * @param start any * @param end any * @returns IQueryable */ whereBetween(field, start, end) { return this.addWhereCondition("$and", field, "BETWEEN", [start, end]); } /** * Add NOT BETWEEN query * * Example: .whereNotBetween("id", 1, 100]) * SQL: WHERE id NOT BETWEEN [1, 100] * * @param field string * @param start any * @param end any * @returns IQueryable */ whereNotBetween(field, start, end) { return this.addWhereCondition("$and", field, "NOT BETWEEN", [start, end]); } /** * Add NULL query * * Example: .whereNull("phone") * SQL: WHERE phone IS NULL * * @param field string * @returns IQueryable */ whereNull(field) { return this.addWhereCondition("$and", field, "NULL", null); } /** * Add NOT NULL query * * Example: .whereNotNull("phone") * SQL: WHERE phone IS NOT NULL * * @param field string * @returns IQueryable */ whereNotNull(field) { return this.addWhereCondition("$and", field, "NOT NULL", null); } /** * Add a not equal query with OR prefix * * Example: .orWhereNot("id", 1) * SQL: OR id <> 1 * * @param field string * @param value any * @returns IQueryable */ orWhereNot(field, value) { return this.addWhereCondition("$or", field, "<>", value); } /** * Add LIKE query with OR prefix * * Example: .orWhereLike("name", "*john*") * SQL: OR name LIKE '%john%' * * @param field string * @param value any * @returns IQueryable */ orWhereLike(field, value) { return this.addWhereCondition("$or", field, "LIKE", value); } /** * Add NOT LIKE query with OR prefix * * Example: .orWhereNotLike("name", "*john*") * SQL: OR name NOT LIKE '%john%' * * @param field string * @param value any * @returns IQueryable */ orWhereNotLike(field, value) { return this.addWhereCondition("$or", field, "NOT LIKE", value); } /** * Add IN query with OR prefix * * Example: .orWhereIn("id", [1, 2, 3]) * SQL: OR id IN [1, 2, 3] * * @param field string * @param value any * @returns IQueryable */ orWhereIn(field, value) { return this.addWhereCondition("$or", field, "IN", value); } /** * Add NOT IN query with OR prefix * * Example: .orWhereNotIn("id", [1, 2, 3]) * SQL: OR id NOT IN [1, 2, 3] * * @param field string * @param value any * @returns IQueryable */ orWhereNotIn(field, value) { return this.addWhereCondition("$or", field, "NOT IN", value); } /** * Add BETWEEN query with OR prefix * * Example: .orWhereBetween("id", 1, 100]) * SQL: OR id BETWEEN [1, 100] * * @param field string * @param start any * @param end any * @returns IQueryable */ orWhereBetween(field, start, end) { return this.addWhereCondition("$or", field, "BETWEEN", [start, end]); } /** * Add NOT BETWEEN query with OR Prefix * * Example: .orWhereNotBetween("id", 1, 100]) * SQL: OR id NOT BETWEEN [1, 100] * * @param field string * @param start any * @param end any * @returns IQueryable */ orWhereNotBetween(field, start, end) { return this.addWhereCondition("$or", field, "NOT BETWEEN", [start, end]); } /** * Add NULL query with OR prefix * * Example: .orWhereNull("phone") * SQL: OR phone IS NULL * * @param field string * @returns IQueryable */ orWhereNull(field) { return this.addWhereCondition("$or", field, "NULL", null); } /** * Add NOT NULL query with OR prefix * * Example: .orWhereNotNull("phone") * SQL: OR phone IS NOT NULL * * @param field string * @returns IQueryable */ orWhereNotNull(field) { return this.addWhereCondition("$or", field, "NOT NULL", null); } /** * Insert a new record to the resource * * @param data object * @returns object */ async insert(data) { return this.sendRequest("POST", data); } /** * Update the resource * * @param data object * @returns object */ async update(data) { return this.sendRequest("PUT", data); } /** * Paginate the resource * * @param query IPaginate * @returns object */ async paginate(query) { this.params.append("page", query?.page?.toString() ?? "1"); this.params.append("per_page", query?.perPage?.toString() ?? "10"); return this.sendRequest("GET"); } /** * Get the resource * * @returns object */ async get() { return this.sendRequest("GET"); } /** * Send a POSt request * * @param data FormBody * @returns object */ async post(data) { return this.sendRequest("POST", data); } /** * Send a PUT request * * @param data FormBody * @returns object */ async put(data) { return this.sendRequest("PUT", data); } /** * Send a PUT request * * @param data FormBody * @returns object */ async patch(data) { return this.sendRequest("PATCH", data); } /** * Send a DELETE request * * @returns null */ async delete() { return this.sendRequest("DELETE"); } async sendRequest(method, data) { let request = { method, headers: { "Content-Type": "application/json", }, body: data ? JSON.stringify(data) : undefined, }; // Calls the request interceptors for (const interceptor of this.config.interceptors.requests) { request = interceptor(request); } // Send the request let response = await fetch(this.toURL(), request); // Calls the response interceptors for (const interceptor of this.config.interceptors.responses) { response = interceptor(response); } return response; } toURL() { if (this.fieldArray.length > 0) { this.params.append("fields", this.fieldArray.join(",")); } if (this.sortArray.length > 0) { this.params.append("sort", this.sortArray.join(",")); } if (this.q.length > 0) { this.params.append("q", JSON.stringify(this.q)); } if (this.withPath) { this.params.append("with", this.withPath); } let params = this.params.toString(); if (params && params.length > 0) { params = `?${params}`; } return `${this.config.baseURL}/${this.url}${params}`; } applyWhere(logic, param1, param2, param3) { if (typeof param1 === "function") { // We should create a new subquery const subquery = []; // We should add a new pointer for the child query this.queryPointers.push(subquery); this.overrideLogic = logic; // Call the query function param1(this); // Getting the parent query const parentQuery = this.queryPointers[this.queryPointers.length - 2]; // Adding the subquery to the parent query parentQuery.push(subquery); // Removing the query pointer this.queryPointers.splice(this.queryPointers.length - 1); return this; } if (param3 === undefined) { this.addWhereCondition(logic, param1, "=", param2); return this; } return this.addWhereCondition(logic, param1, param2, param3); } addWhereCondition(logic, field, condition, value) { const cursor = this.queryPointers[this.queryPointers.length - 1]; let prefix = logic === "$or" ? "$or." : ""; if (this.overrideLogic) { prefix = `${this.overrideLogic}.`; this.overrideLogic = undefined; } const suffix = SUFFIX_MAP[condition] ? `.${SUFFIX_MAP[condition]}` : ""; const key = `${prefix}${field}${suffix}`; cursor.push({ [key]: value }); return this; } metadata() { return { config: this.config, url: this.url, params: this.params, fieldArray: this.fieldArray, sortArray: this.sortArray, q: this.q, queryPointers: this.queryPointers, overrideLogic: this.overrideLogic, withPath: this.withPath, }; } } const interceptors = { addRequest, addResponse, }; /** * Find the resource quickly. * * @param url string. Example: users/1 * @returns object */ const find = async (url) => { const resource = new Resource(url); return resource.get(); }; /** * Set the base resource URL. * * @param url string. Example: posts/1/comments * @returns IQueryable */ const resource = (url) => new Resource(url); const api = { find, resource, setConfig, getConfig, interceptors, }; exports.Resource = Resource; exports.SUFFIX_MAP = SUFFIX_MAP; exports.addRequest = addRequest; exports.addResponse = addResponse; exports.api = api; exports.find = find; exports.getConfig = getConfig; exports.interceptors = interceptors; exports.resource = resource; exports.setConfig = setConfig;