Files
skills/docs/persistence/storage/storage-cdn-bunnycdn/src/pull-zone-client/pull-zone-client.md
2026-05-29 08:20:56 +01:00

3.4 KiB

pull-zone-client

(no submodules)

Purpose

Owns the Bunny.net management-API purge operation. purgeUrl(ctx, edgeUrl, signal?) issues POST https://api.bunny.net/purge?url=<encodedEdgeUrl> with the account-level AccessKey header. The caller composes the absolute edge URL (e.g. https://<pullZoneHostname>/<key> or the same URL with a trailing * for prefix purge) — keeping URL composition out of this module means the same helper handles single-key and wildcard purges without branching.

The function purgeApiKey from the bundle is required; missing it throws STORAGE_CDN_BUNNYCDN.PURGE_API_KEY_MISSING before any fetch happens.

Features

  • Single function with a tight contract — no class state.
  • purgeApiKey enforced at the top; missing or empty key → PURGE_API_KEY_MISSING (no fetch issued).
  • 401/403 → PURGE_AUTH_FAILED, other non-ok → UPSTREAM_ERROR.
  • Errors carry zone, region, and httpStatus for diagnostics.
  • AbortSignal threaded into the fetch init.

Usage: Basic

import { purgeUrl } from "@suaveplan/storage-cdn-bunnycdn";

await purgeUrl(
    { fetch, purgeApiKey: "key-1234", pullZoneHostname: "mycdn.b-cdn.net", zone: "myz", region: "de" },
    "https://mycdn.b-cdn.net/a/b.bin",
);

Usage: Advanced

import { purgeUrl } from "@suaveplan/storage-cdn-bunnycdn";

async function purgePrefix(ctx, prefix: string) {
    // BunnyCDN's purge endpoint treats `*` as a wildcard suffix.
    await purgeUrl(ctx, `https://${ctx.pullZoneHostname}/${encodeURI(prefix)}*`);
}

async function purgeSafelyWithKeyRotation(ctx, edgeUrl: string) {
    try {
        await purgeUrl(ctx, edgeUrl);
    } catch (err) {
        if (err instanceof StorageCdnBunnycdnError && err.code === STORAGE_CDN_BUNNYCDN_CODES.PURGE_AUTH_FAILED) {
            const refreshed = await rotateAccessKey();
            await purgeUrl({ ...ctx, purgeApiKey: refreshed }, edgeUrl);
            return;
        }
        throw err;
    }
}

API Reference

interface PullZoneCtx

{ fetch, purgeApiKey, pullZoneHostname, zone, region }. purgeApiKey is string | undefined; absent value triggers PURGE_API_KEY_MISSING.

purgeUrl(ctx, edgeUrl, signal?): Promise<void>

  • 2xx → resolves.
  • 401/403 → STORAGE_CDN_BUNNYCDN.PURGE_AUTH_FAILED.
  • other non-ok → STORAGE_CDN_BUNNYCDN.UPSTREAM_ERROR.
  • Missing purgeApiKey → STORAGE_CDN_BUNNYCDN.PURGE_API_KEY_MISSING (no fetch issued).

Implementation Notes

  • Purge URL composition is the caller's responsibility because the same endpoint handles both single keys and prefix purges (caller appends * for prefix mode). Pushing composition into the helper would force every caller through an enum or a flag.
  • The AccessKey header is the account-level key from the Bunny.net dashboard, NOT the per-zone storage key. They're rotated independently and have different scopes; conflating them is the typical "purge stopped working after I rotated the storage key" bug.
  • 404 on purge is treated as success at the caller level (we don't see it here because the BunnyCDN API returns 200 OK even when the object was already evicted) — operators relying on a 404 signal should switch to the management API's status endpoint.
  • The pullZoneHostname field is unused inside this function but is part of the bundle so callers can build edge URLs without a second context object.