~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
61 lines · 2.0 KB Raw History
// A minimal Cloudflare API client. Calls ride through the PDS's /cf-api
// passthrough, which forwards the Authorization header and keeps nothing;
// api.cloudflare.com itself answers no CORS preflight.

/** @param {string} token @param {string} [base] */
export function cfClient(token, base = '/cf-api') {
  /**
   * @param {string} path
   * @param {RequestInit} [init]
   */
  async function call(path, init = {}) {
    const response = await fetch(`${base}${path}`, {
      ...init,
      headers: {
        Authorization: `Bearer ${token}`,
        ...(init.body && !(init.body instanceof FormData)
          ? { 'Content-Type': 'application/json' }
          : {}),
        ...init.headers,
      },
    });
    const body = await response.json().catch(() => null);
    if (!body) {
      throw new Error(`Cloudflare API returned ${response.status}`);
    }
    if (!body.success) {
      const messages = (body.errors ?? [])
        .map((/** @type {{code?: number, message: string}} */ e) =>
          e.code ? `${e.message} (code ${e.code})` : e.message,
        )
        .join('; ');
      const error = new Error(
        messages || `Cloudflare API error ${response.status}`,
      );
      /** @type {any} */ (error).codes = (body.errors ?? []).map(
        (/** @type {{code?: number}} */ e) => e.code,
      );
      throw error;
    }
    return body.result;
  }

  return {
    /** @param {string} path */
    get: (path) => call(path),
    /** @param {string} path @param {unknown} [body] */
    post: (path, body) =>
      call(path, {
        method: 'POST',
        body: body ? JSON.stringify(body) : undefined,
      }),
    /** @param {string} path @param {unknown} body */
    put: (path, body) =>
      call(path, { method: 'PUT', body: JSON.stringify(body) }),
    /** @param {string} path @param {unknown} body */
    patch: (path, body) =>
      call(path, { method: 'PATCH', body: JSON.stringify(body) }),
    /** @param {string} path @param {FormData} form */
    putForm: (path, form) => call(path, { method: 'PUT', body: form }),
  };
}