All files / packages/design-system-2-site/src/lib/zeroheight api-client.js

8.33% Statements 1/12
0% Branches 0/5
0% Functions 0/5
10% Lines 1/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61              1x                                                                                                          
/**
 * Minimal Zeroheight REST client (`open_api/v2`). Only used for what the MCP
 * can't give us: hidden pages/tabs and display tab `order`.
 */
 
import { HttpError, retryAfterMs, withRetry } from './http.js';
 
export const API_BASE = 'https://zeroheight.com/open_api/v2';
 
/**
 * @typedef {Object} ApiTab
 * @property {string} name
 * @property {string} uid
 * @property {number} order
 * @property {boolean} hidden
 * @property {string} url
 * @property {string} [content]
 *
 * @typedef {Object} ApiPage
 * @property {number} id
 * @property {string} uid
 * @property {string} name
 * @property {boolean} hidden
 * @property {string} url
 * @property {string} [introduction]
 * @property {string} [content]  untabbed pages only
 * @property {ApiTab[]} [tabs]   tabbed pages only
 */
 
/**
 * @param {{ clientId: string, apiKey: string, styleguideId: string, fetchImpl?: typeof fetch }} opts
 */
export function createApiClient({ clientId, apiKey, styleguideId, fetchImpl = fetch }) {
  /** @param {string} path */
  async function get(path) {
    return withRetry(async () => {
      const res = await fetchImpl(`${API_BASE}${path}`, {
        headers: { 'X-API-CLIENT': clientId, 'X-API-KEY': apiKey, Accept: 'application/json' },
      });
      if (!res.ok) throw new HttpError(`API ${path}: HTTP ${res.status}`, res.status, retryAfterMs(res));
      const body = await res.json();
      if (body.status !== 'success') throw new Error(`API ${path}: status ${body.status}`);
      return body.data;
    });
  }
 
  return {
    /**
     * Every page in the styleguide, hidden ones included. The API ignores
     * pagination params and returns all pages in one response.
     * @returns {Promise<{ id: number, name: string, hidden: boolean }[]>}
     */
    listPages: async () => (await get(`/styleguides/${styleguideId}/pages`)).pages,
    /**
     * @param {number} id
     * @returns {Promise<ApiPage>}
     */
    getPage: async (id) => (await get(`/pages/${id}`)).page,
  };
}