Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
# cdn-client
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Wraps the two Rackspace CDN management operations the adapter actually needs at runtime: `getCdnMetadata` (HEAD on the container's CDN URL to fetch `X-Cdn-Uri`, `X-Cdn-Ssl-Uri`, `X-Ttl`, `X-Cdn-Enabled`) and `purgeObject` (DELETE against the per-object CDN URL to invalidate the edge cache). Both functions accept a `CdnClientContext` that bundles the resolved `cdnEndpoint`, `token`, `container`, and `region`, so the calling code (the adapter) constructs the bundle once per operation and never has to thread the fields by hand.
## Features
- Two focused functions — no class to instantiate.
- `getCdnMetadata` returns `null` on 404, the parsed metadata otherwise.
- `purgeObject` resolves on 2xx and on 404 (already absent), throws `PURGE_RATE_LIMITED` on 429, and `UPSTREAM_ERROR` on other non-ok statuses.
- AbortSignal threaded into both fetch invocations.
- All errors carry `container`/`region`/`httpStatus` for diagnostics.
## Usage: Basic
```ts
import { purgeObject } from "@suaveplan/storage-cdn-rackspace";
await purgeObject(
{ fetch, token: "tok", cdnEndpoint: "https://cdn.example.com/", container: "myc", region: "LON" },
"a%2Fb.bin",
);
```
## Usage: Advanced
```ts
import { getCdnMetadata, purgeObject } from "@suaveplan/storage-cdn-rackspace";
async function purgeAfterUpload(ctx, key: string) {
const meta = await getCdnMetadata(ctx);
if (meta?.cdnEnabled !== true) return; // nothing to invalidate
await purgeObject(ctx, encodeURIComponent(key));
}
```
## API Reference
### `interface CdnClientContext`
`{ fetch, token, cdnEndpoint, container, region }` — `cdnEndpoint` is the management endpoint resolved from the service catalog.
### `interface CdnContainerMetadata`
`{ cdnUri, cdnSslUri, ttl, cdnEnabled }` — parsed verbatim from `X-Cdn-*` headers; missing headers default to empty string / 0 / false.
### `getCdnMetadata(ctx, signal?): Promise<CdnContainerMetadata | null>`
Returns `null` on 404, parsed metadata on 2xx, throws on other non-ok.
### `purgeObject(ctx, encodedKey, signal?): Promise<void>`
Issues `DELETE <cdnEndpoint><container>/<encodedKey>`. Resolves on 2xx or 404. Throws `STORAGE_CDN_RACKSPACE.PURGE_RATE_LIMITED` on 429. Other non-ok statuses surface as `UPSTREAM_ERROR`.
## Implementation Notes
- The `encodedKey` parameter is already URL-encoded by the caller — this module does not re-encode, which would double-escape values.
- 404 on purge is treated as success because Rackspace returns 404 for objects already evicted or never CDN-served; surfacing that as an error would force every caller to handle it specially.
- 429 is its own error code rather than `UPSTREAM_ERROR` because the management API has historically been rate-limited at ~25/min and operators want a dedicated alert rule.
- `cdnEnabled` parsing is case-insensitive (`true`/`True`/`TRUE`) — Rackspace has been inconsistent across documentation versions.
- The functions are intentionally not bundled into a class because there is no state worth caching across calls — the auth client already caches everything that survives between operations.