@remcostoeten/fync
Version:
A unified TypeScript library for easy access to popular APIs (GitHub, Spotify, GitLab, etc.)
104 lines (103 loc) • 3.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createChainableClient = createChainableClient;
var _memoize = require("../http/memoize");
function createChainableClient(config, httpClient, serviceConfig, pathSegments = []) {
function buildPath() {
return "/" + pathSegments.join("/");
}
async function executeRequest(method, data, options) {
const path = buildPath();
const mergedOptions = {
...serviceConfig.defaultOptions,
...options
};
const {
params,
cache = config.cache !== false
} = mergedOptions;
async function requestFn() {
if (mergedOptions.paginate || mergedOptions.allPages) {
return handlePagination(path, params, mergedOptions);
}
return (await httpClient.get(path, params)).data;
}
if (cache) {
const cacheKey = `${serviceConfig.cacheKeyPrefix}:${path}:${JSON.stringify(params || {})}`;
function getCacheKey() {
return cacheKey;
}
const memoizedFn = (0, _memoize.memoize)(requestFn, getCacheKey, {
ttl: mergedOptions.cacheTTL ?? config.cacheTTL ?? 300000
});
return memoizedFn();
}
return requestFn();
}
async function handlePagination(path, params, options) {
if (!serviceConfig.supportsPagination || !httpClient.getPaginated) {
throw new Error("Pagination not supported for this service");
}
const response = await httpClient.getPaginated(path, params);
if (options?.allPages && response.nextUrl) {
const allData = [...response.data];
let nextUrl = response.nextUrl;
while (nextUrl) {
const nextResponse = await httpClient.getPaginated(nextUrl);
allData.push(...nextResponse.data);
nextUrl = nextResponse.nextUrl;
}
return allData;
}
return response.data;
}
async function* streamPages(options) {
if (!serviceConfig.supportsPagination || !httpClient.getPaginated) {
throw new Error("Streaming not supported for this service");
}
const path = buildPath();
const {
params
} = options || {};
let response = await httpClient.getPaginated(path, params);
yield* response.data;
while (response.nextUrl) {
response = await httpClient.getPaginated(response.nextUrl);
yield* response.data;
}
}
function createMethodHandler(method) {
function getHandler(options) {
return executeRequest(method, undefined, options);
}
return getHandler;
}
return new Proxy({}, {
get(target, prop) {
if (prop === "get") {
return createMethodHandler("GET");
}
if (prop === "paginate") {
function paginateHandler(options) {
return executeRequest("GET", undefined, {
...options,
paginate: true
});
}
return paginateHandler;
}
if (prop === "stream") {
function streamHandler(options) {
return streamPages(options);
}
return streamHandler;
}
if (prop === "path") {
return buildPath;
}
return createChainableClient(config, httpClient, serviceConfig, [...pathSegments, String(prop)]);
}
});
}