Skip to content

Commit 6ec4906

Browse files
authored
feat(hub): create and delete a collection (#1584)
Issue: #271 **API doc:** - create: https://huggingface.co/docs/hub/api#post-apicollections - delete: https://huggingface.co/docs/hub/api#delete-apicollectionsnamespaceslug-id **Python client:** - create: https://huggingface.co/docs/huggingface_hub/v0.33.1/en/package_reference/hf_api#huggingface_hub.HfApi.create_collection - delete: https://huggingface.co/docs/huggingface_hub/v0.33.1/en/package_reference/hf_api#huggingface_hub.HfApi.delete_collection We don't have `delete-collection.spec.ts` as we already test deletion in `create-collection.spec.ts` (similar to how it’s done in `create-repo.spec.ts`).
1 parent ffb2bdb commit 6ec4906

File tree

7 files changed

+131
-3
lines changed

7 files changed

+131
-3
lines changed

packages/hub/src/lib/collection-info.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { collectionInfo } from "./collection-info";
55
describe("collectionInfo", () => {
66
it("should return the collection info", async () => {
77
const collection = await collectionInfo({
8-
collectionSlug: "quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
8+
slug: "quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
99
hubUrl: TEST_HUB_URL,
1010
});
1111

packages/hub/src/lib/collection-info.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export async function collectionInfo(
99
/**
1010
* The slug of the collection.
1111
*/
12-
collectionSlug: string;
12+
slug: string;
1313
hubUrl?: string;
1414
/**
1515
* Custom fetch function to use instead of the default one, for example to use a proxy or edit headers.
@@ -19,7 +19,7 @@ export async function collectionInfo(
1919
): Promise<ApiCollectionInfo & { position: number; shareUrl: string }> {
2020
const accessToken = checkCredentials(params);
2121

22-
const res = await (params.fetch ?? fetch)(`${params.hubUrl ?? HUB_URL}/api/collections/${params.collectionSlug}`, {
22+
const res = await (params.fetch ?? fetch)(`${params.hubUrl ?? HUB_URL}/api/collections/${params.slug}`, {
2323
headers: {
2424
"Content-Type": "application/json",
2525
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : undefined),
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { it, describe, expect } from "vitest";
2+
3+
import { TEST_HUB_URL, TEST_ACCESS_TOKEN } from "../test/consts";
4+
import { createCollection } from "./create-collection";
5+
import { whoAmI } from "./who-am-i";
6+
import { deleteCollection } from "./delete-collection";
7+
8+
describe("createCollection", () => {
9+
it("should create a collection", async () => {
10+
let slug: string = "";
11+
12+
try {
13+
const user = await whoAmI({
14+
hubUrl: TEST_HUB_URL,
15+
accessToken: TEST_ACCESS_TOKEN,
16+
});
17+
18+
const result = await createCollection({
19+
collection: {
20+
title: "Test Collection",
21+
namespace: user.name,
22+
description: "This is a test collection",
23+
private: false,
24+
},
25+
accessToken: TEST_ACCESS_TOKEN,
26+
hubUrl: TEST_HUB_URL,
27+
});
28+
29+
expect(result.slug.startsWith(`${user.name}/test-collection`)).toBe(true);
30+
31+
slug = result.slug;
32+
} finally {
33+
await deleteCollection({
34+
slug,
35+
accessToken: TEST_ACCESS_TOKEN,
36+
hubUrl: TEST_HUB_URL,
37+
});
38+
}
39+
});
40+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { HUB_URL } from "../consts";
2+
import { createApiError } from "../error";
3+
import type { ApiCreateCollectionPayload } from "../types/api/api-create-collection";
4+
import type { CredentialsParams } from "../types/public";
5+
import { checkCredentials } from "../utils/checkCredentials";
6+
7+
export async function createCollection(
8+
params: {
9+
collection: ApiCreateCollectionPayload;
10+
hubUrl?: string;
11+
/**
12+
* Custom fetch function to use instead of the default one, for example to use a proxy or edit headers.
13+
*/
14+
fetch?: typeof fetch;
15+
} & Partial<CredentialsParams>
16+
): Promise<{ slug: string }> {
17+
const accessToken = checkCredentials(params);
18+
19+
const res = await (params.fetch ?? fetch)(`${params.hubUrl ?? HUB_URL}/api/collections`, {
20+
method: "POST",
21+
body: JSON.stringify(params.collection),
22+
headers: {
23+
Authorization: `Bearer ${accessToken}`,
24+
"Content-Type": "application/json",
25+
},
26+
});
27+
28+
if (!res.ok) {
29+
throw await createApiError(res);
30+
}
31+
32+
const output = await res.json();
33+
34+
return { slug: output.slug };
35+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { HUB_URL } from "../consts";
2+
import { createApiError } from "../error";
3+
import type { CredentialsParams } from "../types/public";
4+
import { checkCredentials } from "../utils/checkCredentials";
5+
6+
export async function deleteCollection(
7+
params: {
8+
/**
9+
* The slug of the collection to delete.
10+
*/
11+
slug: string;
12+
hubUrl?: string;
13+
/**
14+
* Custom fetch function to use instead of the default one, for example to use a proxy or edit headers.
15+
*/
16+
fetch?: typeof fetch;
17+
} & Partial<CredentialsParams>
18+
): Promise<void> {
19+
const accessToken = checkCredentials(params);
20+
21+
const res = await (params.fetch ?? fetch)(`${params.hubUrl ?? HUB_URL}/api/collections/${params.slug}`, {
22+
method: "DELETE",
23+
headers: {
24+
Authorization: `Bearer ${accessToken}`,
25+
"Content-Type": "application/json",
26+
},
27+
});
28+
29+
if (!res.ok) {
30+
throw await createApiError(res);
31+
}
32+
}

packages/hub/src/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ export * from "./commit";
44
export * from "./count-commits";
55
export * from "./create-repo";
66
export * from "./create-branch";
7+
export * from "./create-collection";
78
export * from "./dataset-info";
89
export * from "./delete-branch";
910
export * from "./delete-file";
1011
export * from "./delete-files";
1112
export * from "./delete-repo";
13+
export * from "./delete-collection";
1214
export * from "./download-file";
1315
export * from "./download-file-to-cache-dir";
1416
export * from "./file-download-info";
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export interface ApiCreateCollectionPayload {
2+
/**
3+
* Title of the collection to create.
4+
*/
5+
title: string;
6+
/**
7+
* Namespace of the collection to create (username or org).
8+
*/
9+
namespace: string;
10+
/**
11+
* Description of the collection to create.
12+
*/
13+
description?: string;
14+
/**
15+
* Whether the collection should be private or not. Defaults to False (i.e. public collection).
16+
* @default false
17+
*/
18+
private?: boolean;
19+
}

0 commit comments

Comments
 (0)