diff --git a/src/cloudflare/internal/images-api.ts b/src/cloudflare/internal/images-api.ts index edfd7dca232..efe33b99174 100644 --- a/src/cloudflare/internal/images-api.ts +++ b/src/cloudflare/internal/images-api.ts @@ -245,14 +245,11 @@ function isDrawTransformer(input: unknown): input is DrawTransformer { } interface ServiceEntrypointStub { - details(imageId: string): Promise; - image(imageId: string): Promise | null>; + image(imageId: string): ImageHandle; upload( image: ReadableStream | ArrayBuffer, options?: ImageUploadOptions ): Promise; - update(imageId: string, options: ImageUpdateOptions): Promise; - delete(imageId: string): Promise; list(options?: ImageListOptions): Promise; } @@ -263,11 +260,7 @@ class HostedImagesBindingImpl implements HostedImagesBinding { this.#fetcher = fetcher; } - async details(imageId: string): Promise { - return this.#fetcher.details(imageId); - } - - async image(imageId: string): Promise | null> { + image(imageId: string): ImageHandle { return this.#fetcher.image(imageId); } @@ -278,17 +271,6 @@ class HostedImagesBindingImpl implements HostedImagesBinding { return this.#fetcher.upload(image, options); } - async update( - imageId: string, - options: ImageUpdateOptions - ): Promise { - return this.#fetcher.update(imageId, options); - } - - async delete(imageId: string): Promise { - return this.#fetcher.delete(imageId); - } - async list(options?: ImageListOptions): Promise { return this.#fetcher.list(options); } diff --git a/src/cloudflare/internal/images.d.ts b/src/cloudflare/internal/images.d.ts index 43a0ab53cf5..60ee8612186 100644 --- a/src/cloudflare/internal/images.d.ts +++ b/src/cloudflare/internal/images.d.ts @@ -138,48 +138,53 @@ interface ImageList { listComplete: boolean; } -interface HostedImagesBinding { +interface ImageHandle { /** * Get metadata for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns Image metadata, or null if not found */ - details(imageId: string): Promise; + details(): Promise; /** * Get the raw image data for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns ReadableStream of image bytes, or null if not found */ - image(imageId: string): Promise | null>; - - /** - * Upload a new hosted image - * @param image The image file to upload - * @param options Upload configuration - * @returns Metadata for the uploaded image - * @throws {@link ImagesError} if upload fails - */ - upload( - image: ReadableStream | ArrayBuffer, - options?: ImageUploadOptions - ): Promise; + bytes(): Promise | null>; /** * Update hosted image metadata - * @param imageId The ID of the image * @param options Properties to update * @returns Updated image metadata * @throws {@link ImagesError} if update fails */ - update(imageId: string, options: ImageUpdateOptions): Promise; + update(options: ImageUpdateOptions): Promise; /** * Delete a hosted image - * @param imageId The ID of the image * @returns True if deleted, false if not found */ - delete(imageId: string): Promise; + delete(): Promise; +} + +interface HostedImagesBinding { + /** + * Get a handle for a hosted image + * @param imageId The ID of the image (UUID or custom ID) + * @returns A handle for per-image operations + */ + image(imageId: string): ImageHandle; + + /** + * Upload a new hosted image + * @param image The image file to upload + * @param options Upload configuration + * @returns Metadata for the uploaded image + * @throws {@link ImagesError} if upload fails + */ + upload( + image: ReadableStream | ArrayBuffer, + options?: ImageUploadOptions + ): Promise; /** * List hosted images with pagination diff --git a/src/cloudflare/internal/test/images/images-api-test.js b/src/cloudflare/internal/test/images/images-api-test.js index 5200b6e73ad..00e9de64de2 100644 --- a/src/cloudflare/internal/test/images/images-api-test.js +++ b/src/cloudflare/internal/test/images/images-api-test.js @@ -458,7 +458,7 @@ export const test_images_get_success = { * @param {Env} env */ async test(_, env) { - const metadata = await env.images.hosted.details('test-image-id'); + const metadata = await env.images.hosted.image('test-image-id').details(); assert.notEqual(metadata, null); assert.equal(metadata.id, 'test-image-id'); assert.equal(metadata.filename, 'test.jpg'); @@ -473,7 +473,7 @@ export const test_images_get_not_found = { * @param {Env} env */ async test(_, env) { - const metadata = await env.images.hosted.details('not-found'); + const metadata = await env.images.hosted.image('not-found').details(); assert.equal(metadata, null); }, }; @@ -485,7 +485,7 @@ export const test_images_getImage_success = { * @param {Env} env */ async test(_, env) { - const stream = await env.images.hosted.image('test-image-id'); + const stream = await env.images.hosted.image('test-image-id').bytes(); assert.notEqual(stream, null); const reader = stream.getReader(); @@ -506,7 +506,7 @@ export const test_images_getImage_not_found = { * @param {Env} env */ async test(_, env) { - const stream = await env.images.hosted.image('not-found'); + const stream = await env.images.hosted.image('not-found').bytes(); assert.equal(stream, null); }, }; @@ -556,7 +556,7 @@ export const test_images_update_success = { * @param {Env} env */ async test(_, env) { - const metadata = await env.images.hosted.update('test-image-id', { + const metadata = await env.images.hosted.image('test-image-id').update({ requireSignedURLs: true, metadata: { updated: true }, creator: 'update-creator', @@ -580,7 +580,9 @@ export const test_images_update_not_found = { */ let e; try { - await env.images.hosted.update('not-found', { requireSignedURLs: true }); + await env.images.hosted + .image('not-found') + .update({ requireSignedURLs: true }); } catch (err) { e = err; } @@ -596,7 +598,7 @@ export const test_images_delete_success = { * @param {Env} env */ async test(_, env) { - const result = await env.images.hosted.delete('test-image-id'); + const result = await env.images.hosted.image('test-image-id').delete(); assert.equal(result, true); }, }; @@ -607,7 +609,7 @@ export const test_images_delete_not_found = { * @param {Env} env */ async test(_, env) { - const result = await env.images.hosted.delete('not-found'); + const result = await env.images.hosted.image('not-found').delete(); assert.equal(result, false); }, }; diff --git a/src/cloudflare/internal/test/images/images-upstream-mock.js b/src/cloudflare/internal/test/images/images-upstream-mock.js index a8dc867353d..3b7c65597c4 100644 --- a/src/cloudflare/internal/test/images/images-upstream-mock.js +++ b/src/cloudflare/internal/test/images/images-upstream-mock.js @@ -2,7 +2,7 @@ // Licensed under the Apache 2.0 license found in the LICENSE file or at: // https://opensource.org/licenses/Apache-2.0 -import { WorkerEntrypoint } from 'cloudflare:workers'; +import { WorkerEntrypoint, RpcTarget } from 'cloudflare:workers'; /** * @param {FormDataEntryValue | null} blob @@ -20,18 +20,23 @@ async function imageAsString(blob) { return blob.text(); } -export class ServiceEntrypoint extends WorkerEntrypoint { - /** - * @param {string} imageId - * @returns {Promise} - */ - async details(imageId) { - if (imageId === 'not-found') { +class ImageHandleMock extends RpcTarget { + /** @type {string} */ + #imageId; + + /** @param {string} imageId */ + constructor(imageId) { + super(); + this.#imageId = imageId; + } + + async details() { + if (this.#imageId === 'not-found') { return null; } return { - id: imageId, + id: this.#imageId, filename: 'test.jpg', uploaded: '2024-01-01T00:00:00Z', requireSignedURLs: false, @@ -42,15 +47,54 @@ export class ServiceEntrypoint extends WorkerEntrypoint { }; } - async image(imageId) { - if (imageId === 'not-found') { + async bytes() { + if (this.#imageId === 'not-found') { return null; } - const mockData = `MOCK_IMAGE_DATA_${imageId}`; + const mockData = `MOCK_IMAGE_DATA_${this.#imageId}`; return new Blob([mockData]).stream(); } + /** + * @param {ImageUpdateOptions} body + * @returns {Promise} + */ + async update(body) { + if (this.#imageId === 'not-found') { + throw new Error('Image not found'); + } + + return { + id: this.#imageId, + filename: 'updated.jpg', + uploaded: '2024-01-01T00:00:00Z', + requireSignedURLs: + body.requireSignedURLs !== undefined ? body.requireSignedURLs : false, + variants: ['public'], + meta: body.metadata || {}, + draft: false, + creator: body.creator, + }; + } + + /** + * @returns {Promise} + */ + async delete() { + return this.#imageId !== 'not-found'; + } +} + +export class ServiceEntrypoint extends WorkerEntrypoint { + /** + * @param {string} imageId + * @returns {ImageHandleMock} + */ + image(imageId) { + return new ImageHandleMock(imageId); + } + async upload(image, options) { // Handle both ReadableStream and ArrayBuffer const buffer = @@ -77,37 +121,6 @@ export class ServiceEntrypoint extends WorkerEntrypoint { }; } - /** - * @param {string} imageId - * @param {ImageUpdateOptions} body - * @returns {Promise} - */ - async update(imageId, body) { - if (imageId === 'not-found') { - throw new Error('Image not found'); - } - - return { - id: imageId, - filename: 'updated.jpg', - uploaded: '2024-01-01T00:00:00Z', - requireSignedURLs: - body.requireSignedURLs !== undefined ? body.requireSignedURLs : false, - variants: ['public'], - meta: body.metadata || {}, - draft: false, - creator: body.creator, - }; - } - - /** - * @param {string} imageId - * @returns {Promise} - */ - async delete(imageId) { - return imageId !== 'not-found'; - } - /** * @param {ImageListOptions} [options] * @returns {Promise} diff --git a/types/defines/images.d.ts b/types/defines/images.d.ts index 984cd6cea7f..672eabe0273 100644 --- a/types/defines/images.d.ts +++ b/types/defines/images.d.ts @@ -135,48 +135,53 @@ interface ImageList { listComplete: boolean; } -interface HostedImagesBinding { +interface ImageHandle { /** - * Get detailed metadata for a hosted image - * @param imageId The ID of the image (UUID or custom ID) + * Get metadata for a hosted image * @returns Image metadata, or null if not found */ - details(imageId: string): Promise; + details(): Promise; /** * Get the raw image data for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns ReadableStream of image bytes, or null if not found */ - image(imageId: string): Promise | null>; - - /** - * Upload a new hosted image - * @param image The image file to upload - * @param options Upload configuration - * @returns Metadata for the uploaded image - * @throws {@link ImagesError} if upload fails - */ - upload( - image: ReadableStream | ArrayBuffer, - options?: ImageUploadOptions - ): Promise; + bytes(): Promise | null>; /** * Update hosted image metadata - * @param imageId The ID of the image * @param options Properties to update * @returns Updated image metadata * @throws {@link ImagesError} if update fails */ - update(imageId: string, options: ImageUpdateOptions): Promise; + update(options: ImageUpdateOptions): Promise; /** * Delete a hosted image - * @param imageId The ID of the image * @returns True if deleted, false if not found */ - delete(imageId: string): Promise; + delete(): Promise; +} + +interface HostedImagesBinding { + /** + * Get a handle for a hosted image + * @param imageId The ID of the image (UUID or custom ID) + * @returns A handle for per-image operations + */ + image(imageId: string): ImageHandle; + + /** + * Upload a new hosted image + * @param image The image file to upload + * @param options Upload configuration + * @returns Metadata for the uploaded image + * @throws {@link ImagesError} if upload fails + */ + upload( + image: ReadableStream | ArrayBuffer, + options?: ImageUploadOptions + ): Promise; /** * List hosted images with pagination diff --git a/types/generated-snapshot/experimental/index.d.ts b/types/generated-snapshot/experimental/index.d.ts index a944dccca04..f2851bb9d12 100755 --- a/types/generated-snapshot/experimental/index.d.ts +++ b/types/generated-snapshot/experimental/index.d.ts @@ -12905,19 +12905,37 @@ interface ImageList { cursor?: string; listComplete: boolean; } -interface HostedImagesBinding { +interface ImageHandle { /** - * Get detailed metadata for a hosted image - * @param imageId The ID of the image (UUID or custom ID) + * Get metadata for a hosted image * @returns Image metadata, or null if not found */ - details(imageId: string): Promise; + details(): Promise; /** * Get the raw image data for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns ReadableStream of image bytes, or null if not found */ - image(imageId: string): Promise | null>; + bytes(): Promise | null>; + /** + * Update hosted image metadata + * @param options Properties to update + * @returns Updated image metadata + * @throws {@link ImagesError} if update fails + */ + update(options: ImageUpdateOptions): Promise; + /** + * Delete a hosted image + * @returns True if deleted, false if not found + */ + delete(): Promise; +} +interface HostedImagesBinding { + /** + * Get a handle for a hosted image + * @param imageId The ID of the image (UUID or custom ID) + * @returns A handle for per-image operations + */ + image(imageId: string): ImageHandle; /** * Upload a new hosted image * @param image The image file to upload @@ -12929,20 +12947,6 @@ interface HostedImagesBinding { image: ReadableStream | ArrayBuffer, options?: ImageUploadOptions, ): Promise; - /** - * Update hosted image metadata - * @param imageId The ID of the image - * @param options Properties to update - * @returns Updated image metadata - * @throws {@link ImagesError} if update fails - */ - update(imageId: string, options: ImageUpdateOptions): Promise; - /** - * Delete a hosted image - * @param imageId The ID of the image - * @returns True if deleted, false if not found - */ - delete(imageId: string): Promise; /** * List hosted images with pagination * @param options List configuration diff --git a/types/generated-snapshot/experimental/index.ts b/types/generated-snapshot/experimental/index.ts index 32fcda365fd..91d6bec7f69 100755 --- a/types/generated-snapshot/experimental/index.ts +++ b/types/generated-snapshot/experimental/index.ts @@ -12921,19 +12921,37 @@ export interface ImageList { cursor?: string; listComplete: boolean; } -export interface HostedImagesBinding { +export interface ImageHandle { /** - * Get detailed metadata for a hosted image - * @param imageId The ID of the image (UUID or custom ID) + * Get metadata for a hosted image * @returns Image metadata, or null if not found */ - details(imageId: string): Promise; + details(): Promise; /** * Get the raw image data for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns ReadableStream of image bytes, or null if not found */ - image(imageId: string): Promise | null>; + bytes(): Promise | null>; + /** + * Update hosted image metadata + * @param options Properties to update + * @returns Updated image metadata + * @throws {@link ImagesError} if update fails + */ + update(options: ImageUpdateOptions): Promise; + /** + * Delete a hosted image + * @returns True if deleted, false if not found + */ + delete(): Promise; +} +export interface HostedImagesBinding { + /** + * Get a handle for a hosted image + * @param imageId The ID of the image (UUID or custom ID) + * @returns A handle for per-image operations + */ + image(imageId: string): ImageHandle; /** * Upload a new hosted image * @param image The image file to upload @@ -12945,20 +12963,6 @@ export interface HostedImagesBinding { image: ReadableStream | ArrayBuffer, options?: ImageUploadOptions, ): Promise; - /** - * Update hosted image metadata - * @param imageId The ID of the image - * @param options Properties to update - * @returns Updated image metadata - * @throws {@link ImagesError} if update fails - */ - update(imageId: string, options: ImageUpdateOptions): Promise; - /** - * Delete a hosted image - * @param imageId The ID of the image - * @returns True if deleted, false if not found - */ - delete(imageId: string): Promise; /** * List hosted images with pagination * @param options List configuration diff --git a/types/generated-snapshot/latest/index.d.ts b/types/generated-snapshot/latest/index.d.ts index ae08223f3e4..80e775c3046 100755 --- a/types/generated-snapshot/latest/index.d.ts +++ b/types/generated-snapshot/latest/index.d.ts @@ -12192,19 +12192,37 @@ interface ImageList { cursor?: string; listComplete: boolean; } -interface HostedImagesBinding { +interface ImageHandle { /** - * Get detailed metadata for a hosted image - * @param imageId The ID of the image (UUID or custom ID) + * Get metadata for a hosted image * @returns Image metadata, or null if not found */ - details(imageId: string): Promise; + details(): Promise; /** * Get the raw image data for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns ReadableStream of image bytes, or null if not found */ - image(imageId: string): Promise | null>; + bytes(): Promise | null>; + /** + * Update hosted image metadata + * @param options Properties to update + * @returns Updated image metadata + * @throws {@link ImagesError} if update fails + */ + update(options: ImageUpdateOptions): Promise; + /** + * Delete a hosted image + * @returns True if deleted, false if not found + */ + delete(): Promise; +} +interface HostedImagesBinding { + /** + * Get a handle for a hosted image + * @param imageId The ID of the image (UUID or custom ID) + * @returns A handle for per-image operations + */ + image(imageId: string): ImageHandle; /** * Upload a new hosted image * @param image The image file to upload @@ -12216,20 +12234,6 @@ interface HostedImagesBinding { image: ReadableStream | ArrayBuffer, options?: ImageUploadOptions, ): Promise; - /** - * Update hosted image metadata - * @param imageId The ID of the image - * @param options Properties to update - * @returns Updated image metadata - * @throws {@link ImagesError} if update fails - */ - update(imageId: string, options: ImageUpdateOptions): Promise; - /** - * Delete a hosted image - * @param imageId The ID of the image - * @returns True if deleted, false if not found - */ - delete(imageId: string): Promise; /** * List hosted images with pagination * @param options List configuration diff --git a/types/generated-snapshot/latest/index.ts b/types/generated-snapshot/latest/index.ts index 0fb9521d84c..e3de03f5288 100755 --- a/types/generated-snapshot/latest/index.ts +++ b/types/generated-snapshot/latest/index.ts @@ -12208,19 +12208,37 @@ export interface ImageList { cursor?: string; listComplete: boolean; } -export interface HostedImagesBinding { +export interface ImageHandle { /** - * Get detailed metadata for a hosted image - * @param imageId The ID of the image (UUID or custom ID) + * Get metadata for a hosted image * @returns Image metadata, or null if not found */ - details(imageId: string): Promise; + details(): Promise; /** * Get the raw image data for a hosted image - * @param imageId The ID of the image (UUID or custom ID) * @returns ReadableStream of image bytes, or null if not found */ - image(imageId: string): Promise | null>; + bytes(): Promise | null>; + /** + * Update hosted image metadata + * @param options Properties to update + * @returns Updated image metadata + * @throws {@link ImagesError} if update fails + */ + update(options: ImageUpdateOptions): Promise; + /** + * Delete a hosted image + * @returns True if deleted, false if not found + */ + delete(): Promise; +} +export interface HostedImagesBinding { + /** + * Get a handle for a hosted image + * @param imageId The ID of the image (UUID or custom ID) + * @returns A handle for per-image operations + */ + image(imageId: string): ImageHandle; /** * Upload a new hosted image * @param image The image file to upload @@ -12232,20 +12250,6 @@ export interface HostedImagesBinding { image: ReadableStream | ArrayBuffer, options?: ImageUploadOptions, ): Promise; - /** - * Update hosted image metadata - * @param imageId The ID of the image - * @param options Properties to update - * @returns Updated image metadata - * @throws {@link ImagesError} if update fails - */ - update(imageId: string, options: ImageUpdateOptions): Promise; - /** - * Delete a hosted image - * @param imageId The ID of the image - * @returns True if deleted, false if not found - */ - delete(imageId: string): Promise; /** * List hosted images with pagination * @param options List configuration