@remcostoeten/fync
Version:
A unified TypeScript library for easy access to popular APIs (GitHub, Spotify, GitLab, etc.)
94 lines • 3.6 kB
JavaScript
import { memoize } from "../http/memoize";
export 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 = 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),
]);
},
});
}
//# sourceMappingURL=factory.js.map