diff --git a/index.d.ts b/index.d.ts index 1ef9e89..ba1783a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -239,6 +239,16 @@ declare module "replicate" { list(): Promise>; }; + files: { + create( + file: Blob | Buffer, + metadata?: Record + ): Promise; + list(): Promise>; + get(file_id: string): Promise; + delete(file_id: string): Promise; + }; + hardware: { list(): Promise; }; diff --git a/index.js b/index.js index bf53449..b8c3a1f 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,7 @@ const { const accounts = require("./lib/accounts"); const collections = require("./lib/collections"); const deployments = require("./lib/deployments"); +const files = require("./lib/files"); const hardware = require("./lib/hardware"); const models = require("./lib/models"); const predictions = require("./lib/predictions"); @@ -77,6 +78,13 @@ class Replicate { }, }; + this.files = { + create: files.create.bind(this), + get: files.get.bind(this), + list: files.list.bind(this), + delete: files.delete.bind(this), + }; + this.hardware = { list: hardware.list.bind(this), }; diff --git a/index.test.ts b/index.test.ts index 8ecb5ae..e0e060c 100644 --- a/index.test.ts +++ b/index.test.ts @@ -15,6 +15,31 @@ const BASE_URL = "https://api.replicate.com/v1"; nock.disableNetConnect(); +const fileTestCases = [ + // Skip test case if File type is not available + ...(typeof File !== "undefined" + ? [ + { + type: "file", + value: new File(["hello world"], "file_hello.txt", { + type: "text/plain", + }), + expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=", + }, + ] + : []), + { + type: "blob", + value: new Blob(["hello world"], { type: "text/plain" }), + expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=", + }, + { + type: "buffer", + value: Buffer.from("hello world"), + expected: "data:application/octet-stream;base64,aGVsbG8gd29ybGQ=", + }, +]; + describe("Replicate client", () => { let unmatched: any[] = []; const handleNoMatch = (req: unknown, options: any, body: string) => @@ -264,31 +289,6 @@ describe("Replicate client", () => { } ); - const fileTestCases = [ - // Skip test case if File type is not available - ...(typeof File !== "undefined" - ? [ - { - type: "file", - value: new File(["hello world"], "file_hello.txt", { - type: "text/plain", - }), - expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=", - }, - ] - : []), - { - type: "blob", - value: new Blob(["hello world"], { type: "text/plain" }), - expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=", - }, - { - type: "buffer", - value: Buffer.from("hello world"), - expected: "data:application/octet-stream;base64,aGVsbG8gd29ybGQ=", - }, - ]; - test.each(fileTestCases)( "converts a $type input into a Replicate file URL", async ({ value: data, type }) => { @@ -1058,6 +1058,96 @@ describe("Replicate client", () => { // Add more tests for error handling, edge cases, etc. }); + describe("files.create", () => { + test("Calls the correct API route with the correct payload", async () => { + for (const testCase of fileTestCases) { + nock(BASE_URL) + .post("/files") + .reply(200, { + id: "123", + name: "test-file", + content_type: "application/octet-stream", + size: 1024, + etag: "abc123", + checksum: "sha256:1234567890abcdef", + metadata: {}, + created_at: "2023-01-01T00:00:00Z", + expires_at: null, + urls: { + get: "https://api.replicate.com/v1/files/123", + }, + }); + const file = await client.files.create(testCase.value); + expect(file.id).toBe("123"); + expect(file.name).toBe("test-file"); + } + }); + }); + + describe("files.get", () => { + test("Calls the correct API route", async () => { + nock(BASE_URL) + .get("/files/123") + .reply(200, { + id: "123", + name: "test-file", + content_type: "application/octet-stream", + size: 1024, + etag: "abc123", + checksum: "sha256:1234567890abcdef", + metadata: {}, + created_at: "2023-01-01T00:00:00Z", + expires_at: null, + urls: { + get: "https://api.replicate.com/v1/files/123", + }, + }); + + const file = await client.files.get("123"); + expect(file.id).toBe("123"); + expect(file.name).toBe("test-file"); + }); + }); + + describe("files.list", () => { + test("Calls the correct API route", async () => { + nock(BASE_URL) + .get("/files") + .reply(200, { + next: null, + previous: null, + results: [ + { + id: "123", + name: "test-file", + content_type: "application/octet-stream", + size: 1024, + etag: "abc123", + checksum: "sha256:1234567890abcdef", + metadata: {}, + created_at: "2023-01-01T00:00:00Z", + expires_at: null, + urls: { + get: "https://api.replicate.com/v1/files/123", + }, + }, + ], + }); + + const files = await client.files.list(); + expect(files.results.length).toBe(1); + expect(files.results[0].id).toBe("123"); + }); + }); + + describe("files.delete", () => { + test("Calls the correct API route", async () => { + nock(BASE_URL).delete("/files/123").reply(204); + const success = await client.files.delete("123"); + expect(success).toBe(true); + }); + }); + describe("hardware.list", () => { test("Calls the correct API route", async () => { nock(BASE_URL) diff --git a/lib/files.js b/lib/files.js index 520f2aa..de49c58 100644 --- a/lib/files.js +++ b/lib/files.js @@ -72,14 +72,14 @@ async function getFile(file_id) { * Delete a file * * @param {string} file_id - Required. The ID of the file. - * @returns {Promise} - Resolves with the deletion confirmation + * @returns {Promise} - Resolves with true if the file was deleted */ async function deleteFile(file_id) { const response = await this.request(`/files/${file_id}`, { method: "DELETE", }); - return response.json(); + return response.status === 204; } module.exports = {