Skip to content

Commit 7f2bd81

Browse files
authored
Export files methods to client (#278)
* Export files methods to client * Add type definition for file operations * Add test coverage for file methods
1 parent a3adcb3 commit 7f2bd81

File tree

4 files changed

+135
-27
lines changed

4 files changed

+135
-27
lines changed

index.d.ts

+10
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,16 @@ declare module "replicate" {
243243
list(): Promise<Page<Deployment>>;
244244
};
245245

246+
files: {
247+
create(
248+
file: Blob | Buffer,
249+
metadata?: Record<string, unknown>
250+
): Promise<FileObject>;
251+
list(): Promise<Page<FileObject>>;
252+
get(file_id: string): Promise<FileObject>;
253+
delete(file_id: string): Promise<boolean>;
254+
};
255+
246256
hardware: {
247257
list(): Promise<Hardware[]>;
248258
};

index.js

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
const accounts = require("./lib/accounts");
1212
const collections = require("./lib/collections");
1313
const deployments = require("./lib/deployments");
14+
const files = require("./lib/files");
1415
const hardware = require("./lib/hardware");
1516
const models = require("./lib/models");
1617
const predictions = require("./lib/predictions");
@@ -78,6 +79,13 @@ class Replicate {
7879
},
7980
};
8081

82+
this.files = {
83+
create: files.create.bind(this),
84+
get: files.get.bind(this),
85+
list: files.list.bind(this),
86+
delete: files.delete.bind(this),
87+
};
88+
8189
this.hardware = {
8290
list: hardware.list.bind(this),
8391
};

index.test.ts

+115-25
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,31 @@ const BASE_URL = "https://api.replicate.com/v1";
1515

1616
nock.disableNetConnect();
1717

18+
const fileTestCases = [
19+
// Skip test case if File type is not available
20+
...(typeof File !== "undefined"
21+
? [
22+
{
23+
type: "file",
24+
value: new File(["hello world"], "file_hello.txt", {
25+
type: "text/plain",
26+
}),
27+
expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=",
28+
},
29+
]
30+
: []),
31+
{
32+
type: "blob",
33+
value: new Blob(["hello world"], { type: "text/plain" }),
34+
expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=",
35+
},
36+
{
37+
type: "buffer",
38+
value: Buffer.from("hello world"),
39+
expected: "data:application/octet-stream;base64,aGVsbG8gd29ybGQ=",
40+
},
41+
];
42+
1843
describe("Replicate client", () => {
1944
let unmatched: any[] = [];
2045
const handleNoMatch = (req: unknown, options: any, body: string) =>
@@ -264,31 +289,6 @@ describe("Replicate client", () => {
264289
}
265290
);
266291

267-
const fileTestCases = [
268-
// Skip test case if File type is not available
269-
...(typeof File !== "undefined"
270-
? [
271-
{
272-
type: "file",
273-
value: new File(["hello world"], "file_hello.txt", {
274-
type: "text/plain",
275-
}),
276-
expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=",
277-
},
278-
]
279-
: []),
280-
{
281-
type: "blob",
282-
value: new Blob(["hello world"], { type: "text/plain" }),
283-
expected: "data:text/plain;base64,aGVsbG8gd29ybGQ=",
284-
},
285-
{
286-
type: "buffer",
287-
value: Buffer.from("hello world"),
288-
expected: "data:application/octet-stream;base64,aGVsbG8gd29ybGQ=",
289-
},
290-
];
291-
292292
test.each(fileTestCases)(
293293
"converts a $type input into a Replicate file URL",
294294
async ({ value: data, type }) => {
@@ -1072,6 +1072,96 @@ describe("Replicate client", () => {
10721072
// Add more tests for error handling, edge cases, etc.
10731073
});
10741074

1075+
describe("files.create", () => {
1076+
test("Calls the correct API route with the correct payload", async () => {
1077+
for (const testCase of fileTestCases) {
1078+
nock(BASE_URL)
1079+
.post("/files")
1080+
.reply(200, {
1081+
id: "123",
1082+
name: "test-file",
1083+
content_type: "application/octet-stream",
1084+
size: 1024,
1085+
etag: "abc123",
1086+
checksum: "sha256:1234567890abcdef",
1087+
metadata: {},
1088+
created_at: "2023-01-01T00:00:00Z",
1089+
expires_at: null,
1090+
urls: {
1091+
get: "https://api.replicate.com/v1/files/123",
1092+
},
1093+
});
1094+
const file = await client.files.create(testCase.value);
1095+
expect(file.id).toBe("123");
1096+
expect(file.name).toBe("test-file");
1097+
}
1098+
});
1099+
});
1100+
1101+
describe("files.get", () => {
1102+
test("Calls the correct API route", async () => {
1103+
nock(BASE_URL)
1104+
.get("/files/123")
1105+
.reply(200, {
1106+
id: "123",
1107+
name: "test-file",
1108+
content_type: "application/octet-stream",
1109+
size: 1024,
1110+
etag: "abc123",
1111+
checksum: "sha256:1234567890abcdef",
1112+
metadata: {},
1113+
created_at: "2023-01-01T00:00:00Z",
1114+
expires_at: null,
1115+
urls: {
1116+
get: "https://api.replicate.com/v1/files/123",
1117+
},
1118+
});
1119+
1120+
const file = await client.files.get("123");
1121+
expect(file.id).toBe("123");
1122+
expect(file.name).toBe("test-file");
1123+
});
1124+
});
1125+
1126+
describe("files.list", () => {
1127+
test("Calls the correct API route", async () => {
1128+
nock(BASE_URL)
1129+
.get("/files")
1130+
.reply(200, {
1131+
next: null,
1132+
previous: null,
1133+
results: [
1134+
{
1135+
id: "123",
1136+
name: "test-file",
1137+
content_type: "application/octet-stream",
1138+
size: 1024,
1139+
etag: "abc123",
1140+
checksum: "sha256:1234567890abcdef",
1141+
metadata: {},
1142+
created_at: "2023-01-01T00:00:00Z",
1143+
expires_at: null,
1144+
urls: {
1145+
get: "https://api.replicate.com/v1/files/123",
1146+
},
1147+
},
1148+
],
1149+
});
1150+
1151+
const files = await client.files.list();
1152+
expect(files.results.length).toBe(1);
1153+
expect(files.results[0].id).toBe("123");
1154+
});
1155+
});
1156+
1157+
describe("files.delete", () => {
1158+
test("Calls the correct API route", async () => {
1159+
nock(BASE_URL).delete("/files/123").reply(204);
1160+
const success = await client.files.delete("123");
1161+
expect(success).toBe(true);
1162+
});
1163+
});
1164+
10751165
describe("hardware.list", () => {
10761166
test("Calls the correct API route", async () => {
10771167
nock(BASE_URL)

lib/files.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,14 @@ async function getFile(file_id) {
7272
* Delete a file
7373
*
7474
* @param {string} file_id - Required. The ID of the file.
75-
* @returns {Promise<object>} - Resolves with the deletion confirmation
75+
* @returns {Promise<boolean>} - Resolves with true if the file was deleted
7676
*/
7777
async function deleteFile(file_id) {
7878
const response = await this.request(`/files/${file_id}`, {
7979
method: "DELETE",
8080
});
8181

82-
return response.json();
82+
return response.status === 204;
8383
}
8484

8585
module.exports = {

0 commit comments

Comments
 (0)