first commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# pull-zone-client
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user