UNPKG

openblox

Version:

Roblox API Wrapper For Both Classic And OpenCloud APIs.

155 lines (154 loc) 7.37 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var apiGroup_exports = {}; __export(apiGroup_exports, { createApiGroup: () => createApiGroup }); module.exports = __toCommonJS(apiGroup_exports); var import_config = require("../../config"); var import_httpHandler = require("../../http/httpHandler"); var import_utils = require("../../utils/utils"); var import_http = require("../../http/http.utils"); var import_helpers = require("../../helpers"); const operationPrefixRegexWithVersion = /((?:.+)(?:v[1-9]+\/))(?:.+)/; const operationPrefixRegexWithoutVersion = /(.+\/)(cloud\/)(?:v[1-9]+)(?:.+)/; const getParams = (func) => { let str = func.toString(); const argsStr = /(?:async) (?:\((?:\{ (.+) \})\))/.exec(str)?.[1]; if (!argsStr) return []; return argsStr.replaceAll(/{(.*)}/g, "").replaceAll(/ = ([^,]+)/g, "").replaceAll(/:( *)/g, "").split(", "); }; const formatSearchParams = (params) => { if (typeof params == "string") return params; if (!params) return ""; const [paramsKeys, paramsValues] = [Object.keys(params), Object.values(params)]; const formattedParams = {}; paramsValues.forEach((param, i) => { if (param == void 0 || param == null) return; if (typeof param == "string") return formattedParams[paramsKeys[i]] = param; if (Array.isArray(param)) return formattedParams[paramsKeys[i]] = param.join(","); if (param instanceof Date) return formattedParams[paramsKeys[i]] = param.toISOString(); return formattedParams[paramsKeys[i]] = param.toString(); }); return formattedParams; }; const defaultGetCursors = (rawData) => { return [rawData.previousPageCursor, rawData.nextPageCursor]; }; function isObjectEmpty(obj) { for (var prop in obj) if (obj.hasOwnProperty(prop)) return false; return true; } const isNoMoreData = (data) => { if (data?.constructor == Object) return isObjectEmpty(data); if (Array.isArray(data)) return !data.length; return !!data; }; const isCursorEmpty = (cursor) => !cursor || typeof cursor == "string" && cursor.length === 0; const paginate = (initialResponse, callApiMethod, args, overrides, handlerFnCursorArg) => async function* () { if (isNoMoreData(initialResponse.data)) return; yield initialResponse; let nextCursor = initialResponse.cursors?.next; if (isCursorEmpty(nextCursor)) return; while (true) { const newValue = await callApiMethod.call(overrides, { ...args, [handlerFnCursorArg]: nextCursor }); if (isNoMoreData(newValue.data)) return; yield newValue; nextCursor = newValue.cursors?.next; if (isCursorEmpty(nextCursor)) return; } }; const pollForResponse = async (url, operationPath, cloudKey) => { const operationPrefix = operationPath.match(/^(\/?)cloud\/v[1-9]+(\/?)/) ? operationPrefixRegexWithoutVersion.exec(url)?.[1] : operationPrefixRegexWithVersion.exec(url)?.[1]; const operationUrl = `${operationPrefix}${operationPath}`; const headers = { "x-api-key": cloudKey }; let response; await (0, import_helpers.pollHttp)({ method: "GET", url: operationUrl, headers }, async (polledResponse, stopPolling) => { if (!polledResponse.body.done) return; response = polledResponse; stopPolling(); }); return response; }; const createApiGroup = ({ name: groupName, baseUrl, defaultGetCursors: groupDefaultGetCursors }) => ({ // createApiMethod. createApiMethod: (handlerFn) => { const handlerFnArgs = getParams(handlerFn); const handlerFnCursorArg = handlerFnArgs.includes("cursor") ? "cursor" : handlerFnArgs.includes("startRowIndex") ? "startRowIndex" : handlerFnArgs.includes("pageNumber") ? "pageNumber" : null; const thisDefaultGetCursors = groupDefaultGetCursors ?? defaultGetCursors; const createCallApiMethod = (_baseUrl = baseUrl) => async function(args) { const overrides = this; const cookie = overrides?.cookie || import_config.config?.cookie; const cloudKey = overrides?.cloudKey || import_config.config?.cloudKey; const oauthToken = overrides?.oauthToken; const handlerFnData = await handlerFn(args); let { path, method, searchParams, applyFieldMask, body, formData, headers, getCursorsFn, pathToPoll, name } = handlerFnData; const formatRawDataFn = handlerFnData.formatRawDataFn; let formattedSearchParams = formatSearchParams(searchParams); if (applyFieldMask && body && (0, import_utils.isObject)(body)) formattedSearchParams += `&updateMask=${(0, import_utils.objectToFieldMask)(body)}`; const url = `${_baseUrl}${path}${formattedSearchParams ? `?${new URLSearchParams(formattedSearchParams).toString()}` : ""}`; if (cookie || cloudKey || oauthToken) { if (!headers) headers = {}; if (cookie) headers["Cookie"] = cookie; if (cloudKey) headers["x-api-key"] = cloudKey; if (oauthToken) headers["Authorization"] = `Bearer ${oauthToken}`; } let main; main = async () => { let response = await (0, import_httpHandler.HttpHandler)({ method, url, body, formData, headers }); if (!(response instanceof import_http.HttpResponse)) throw response; let rawData = response.body; let opPath = rawData?.path; if (opPath && rawData?.done === false && (0, import_httpHandler.isOpenCloudUrl)(url)) { console.warn(`Polling '${groupName}.${name}' (Please be patient)...`); response = await pollForResponse(url, pathToPoll ? pathToPoll(rawData) : opPath, cloudKey); rawData = response.body; } let apiMethodResult = formatRawDataFn ? { response, again: main, get data() { return formatRawDataFn(rawData, response); } } : { response, again: main, data: rawData }; if (handlerFnCursorArg) { let [previousCursor, nextCursor] = (getCursorsFn ?? thisDefaultGetCursors)(rawData); apiMethodResult.cursors = { previous: previousCursor, next: nextCursor }; if (args && !("__notRoot" in args)) { apiMethodResult[Symbol.asyncIterator] = paginate( apiMethodResult, callApiMethod, args, overrides, handlerFnCursorArg ); } } return apiMethodResult; }; return await main(); }; const callApiMethod = createCallApiMethod(); callApiMethod._deriveWithDifferentBaseUrl = (baseUrl2) => createCallApiMethod(baseUrl2); return callApiMethod; }, addExistingApiMethod: (method) => { return method._deriveWithDifferentBaseUrl(baseUrl); } }); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createApiGroup });