Skip to content

API gateway utilities: retry, rate limiting, pagination, request logging

License

Notifications You must be signed in to change notification settings

systemoperators/gateway

Repository files navigation

@systemoperator/gateway

API gateway utilities: retry with exponential backoff, rate limit handling, pagination, request logging, response storage. Zero dependencies, works everywhere (Cloudflare Workers, Node, Deno, Bun).

install

npm install @systemoperator/gateway

usage

create a gateway

import { ApiGateway } from '@systemoperator/gateway';

const gateway = new ApiGateway({
  name: 'linear',
  baseUrl: 'https://api.linear.app',
  tokenProvider: { getToken: (connectionId) => loadFromDb(connectionId) },
  logger: myRequestLogger,        // optional
  responseStore: myR2Store,        // optional
  retry: { maxRetries: 5 },       // optional, has defaults
});

REST requests

const result = await gateway.fetch<IssueData>('/rest/issues', { method: 'GET' }, connectionId, ctx);

GraphQL

const result = await gateway.graphql<IssueData>(query, variables, connectionId, ctx);

checks .errors array even on 200 status.

pagination

import { paginators } from '@systemoperator/gateway';

const allItems = await gateway.paginate<Issue>('/rest/issues', paginators.notion(), connectionId, ctx);

4 built-in strategies: paginators.notion(), paginators.relay(), paginators.pageToken(), paginators.offset().

store interfaces

the package never touches databases or R2 directly. products inject implementations:

import type { TokenProvider, RequestLogger, ResponseStore } from '@systemoperator/gateway';

const tokenProvider: TokenProvider = {
  async getToken(connectionId) { /* load from DB */ },
};

const logger: RequestLogger = {
  async log(entry) { /* insert into request_logs table */ },
};

const responseStore: ResponseStore = {
  async store(gatewayName, reqId, data) { /* store in R2/S3/disk */ },
};

R2 response store

helper for Cloudflare R2 (separate import to avoid R2 type dependency):

import { createR2ResponseStore } from '@systemoperator/gateway/r2';

const responseStore = createR2ResponseStore(env.R2_BUCKET);

retry and utilities

import { retryFetch, extractShape, countRecords } from '@systemoperator/gateway';

// standalone retry fetch
const result = await retryFetch<Data>(url, options, { maxRetries: 3 });

// response shape extraction for logging
const shape = extractShape(responseData);
const count = countRecords(responseData);

defaults

  • maxRetries: 5
  • initialDelayMs: 1000
  • maxDelayMs: 60000
  • backoffMultiplier: 2
  • rateLimitHeader: x-ratelimit-remaining
  • rateLimitThreshold: 10 (sleeps 500ms when below)
  • authScheme: Bearer

license

MIT

About

API gateway utilities: retry, rate limiting, pagination, request logging

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published