import type { APIPromise } from '../core/api-promise'; import type { RequestOptions } from '../internal/request-options'; import { Assets, type AssetRetrieveParams, type AssetRetrieveResponse, type AssetUpdateParams, type AssetUpdateResponse, } from '../resources/assets/assets'; /** Asset methods added on top of the original asset fields. */ export class AssetMethods { /** * Fetch the asset's content as bytes, using the signed `url` field on the * asset. Works in Node ≥18 and in browsers with no extra setup. * * This is a thin wrapper around `fetch(asset.url)` — use `asset.url` * directly if you need streaming or a Response object. * * @example * ```ts * const res = await client.assets.retrieve(assetId); * const bytes = await res.asset.download(); * await fs.writeFile('out.png', bytes); * ``` */ async download(this: Asset): Promise { const res = await fetch(this.url); if (!res.ok) { throw new Error(`Failed to download asset ${this.id}: ${res.status} ${res.statusText}`); } return new Uint8Array(await res.arrayBuffer()); } /** @internal Create an Asset from raw asset data. */ static from(data: AssetRetrieveResponse['asset']): Asset { return Object.assign(Object.create(AssetMethods.prototype), data) as Asset; } } /** An asset with all original fields plus `.download()`. */ export type Asset = AssetRetrieveResponse.Asset & AssetMethods; export const Asset = AssetMethods; /** * @internal Helper type: adds `.download()` to the `asset` field of a response. * Uses intersection so the original response type is preserved — a `WithAsset` is still assignable to `T`. */ export type WithAsset = T & { asset: AssetMethods }; /** * @internal Wrap `_thenUnwrap` to replace `response.asset` with an enhanced Asset. */ export function enhanceAsset( promise: APIPromise, ): APIPromise> { return promise._thenUnwrap((data) => ({ ...data, asset: Asset.from(data.asset as AssetRetrieveResponse['asset']), })); } /** * Enhanced Assets resource. * All original methods (and subresources like `download`, `public`) are * inherited. `retrieve` and `update` responses' `asset` field gains a * `.download()` helper for fetching the asset's bytes. */ export class EnhancedAssets extends Assets { override retrieve( assetID: string, query: AssetRetrieveParams | null | undefined = {}, options?: RequestOptions, ): APIPromise> { return enhanceAsset(super.retrieve(assetID, query, options)); } override update( assetID: string, params: AssetUpdateParams, options?: RequestOptions, ): APIPromise> { return enhanceAsset(super.update(assetID, params, options)); } }