Skip to content

Commit 312da86

Browse files
authored
feat(hub): get collection (#1594)
Issue: #271 Get collection info. **API doc:** - `GET /api/collections/{namespace}/{slug}-{id}`: https://huggingface.co/docs/hub/api#get-apicollectionsnamespaceslug-id **Python client:** - `get_collection()`: https://github.com/huggingface/huggingface_hub/blob/798ea8a0daaf302997471983005e5ebb58b29297/src/huggingface_hub/hf_api.py#L8307
1 parent 66deb88 commit 312da86

File tree

4 files changed

+228
-4
lines changed

4 files changed

+228
-4
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import { describe, expect, it } from "vitest";
2+
import { TEST_HUB_URL } from "../test/consts";
3+
import { collectionInfo } from "./collection-info";
4+
5+
describe("collectionInfo", () => {
6+
it("should return the collection info", async () => {
7+
const collection = await collectionInfo({
8+
collectionSlug: "quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
9+
hubUrl: TEST_HUB_URL,
10+
});
11+
12+
if (typeof collection.lastUpdated === "string") {
13+
collection.lastUpdated = "2025-07-03T22:18:56.239Z";
14+
}
15+
16+
if (collection.items && Array.isArray(collection.items)) {
17+
collection.items.map((item) => {
18+
if ("lastModified" in item && typeof item.lastModified === "string") {
19+
item.lastModified = "2025-07-01T00:36:29.000Z";
20+
}
21+
if ("lastUpdated" in item && typeof item.lastUpdated === "string") {
22+
item.lastUpdated = "2025-07-01T00:41:27.525Z";
23+
}
24+
});
25+
}
26+
27+
const items = collection.items;
28+
collection.items = [];
29+
30+
// Check all properties of the collection except items
31+
expect(collection).deep.equal({
32+
slug: "quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
33+
title: "Test Collection",
34+
description: "This collection is only for test",
35+
gating: false,
36+
lastUpdated: "2025-07-03T22:18:56.239Z",
37+
owner: {
38+
_id: "6866ff3936a7677f427f99e3",
39+
avatarUrl: "/avatars/b51088e22fb7194888551365b1bafada.svg",
40+
fullname: "Quang-Huy Tran",
41+
name: "quanghuynt14",
42+
type: "user",
43+
isPro: false,
44+
isHf: false,
45+
isHfAdmin: false,
46+
isMod: false,
47+
},
48+
items: [],
49+
theme: "purple",
50+
position: 1,
51+
private: false,
52+
shareUrl: "https://hub-ci.huggingface.co/collections/quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
53+
upvotes: 0,
54+
isUpvotedByUser: false,
55+
});
56+
57+
// Check for item type model
58+
expect(items[0]).deep.equal({
59+
_id: "686700086ca2d2e0a193150b",
60+
position: 0,
61+
type: "model",
62+
author: "quanghuynt14",
63+
authorData: {
64+
_id: "6866ff3936a7677f427f99e3",
65+
avatarUrl: "/avatars/b51088e22fb7194888551365b1bafada.svg",
66+
fullname: "Quang-Huy Tran",
67+
name: "quanghuynt14",
68+
type: "user",
69+
isPro: false,
70+
isHf: false,
71+
isHfAdmin: false,
72+
isMod: false,
73+
},
74+
downloads: 0,
75+
gated: false,
76+
id: "quanghuynt14/TestModel",
77+
availableInferenceProviders: [],
78+
lastModified: "2025-07-01T00:36:29.000Z",
79+
likes: 0,
80+
private: false,
81+
repoType: "model",
82+
isLikedByUser: false,
83+
});
84+
85+
// Check for item type dataset
86+
expect(items[1]).deep.equal({
87+
_id: "686701cd86ea6972ba6c9da5",
88+
position: 1,
89+
type: "dataset",
90+
author: "quanghuynt14",
91+
downloads: 0,
92+
gated: false,
93+
id: "quanghuynt14/TestDataset",
94+
lastModified: "2025-07-01T00:36:29.000Z",
95+
private: false,
96+
repoType: "dataset",
97+
likes: 0,
98+
isLikedByUser: false,
99+
});
100+
101+
// Check for item type space
102+
expect(items[2]).deep.equal({
103+
_id: "6867000f6ca2d2e0a193150e",
104+
position: 2,
105+
type: "space",
106+
author: "quanghuynt14",
107+
authorData: {
108+
_id: "6866ff3936a7677f427f99e3",
109+
avatarUrl: "/avatars/b51088e22fb7194888551365b1bafada.svg",
110+
fullname: "Quang-Huy Tran",
111+
name: "quanghuynt14",
112+
type: "user",
113+
isPro: false,
114+
isHf: false,
115+
isHfAdmin: false,
116+
isMod: false,
117+
},
118+
colorFrom: "pink",
119+
colorTo: "indigo",
120+
createdAt: "2025-07-03T22:10:39.000Z",
121+
emoji: "🏆",
122+
id: "quanghuynt14/TestSpace",
123+
lastModified: "2025-07-01T00:36:29.000Z",
124+
likes: 0,
125+
pinned: false,
126+
private: false,
127+
sdk: "docker",
128+
repoType: "space",
129+
runtime: {
130+
stage: "BUILDING",
131+
hardware: {
132+
current: null,
133+
requested: "cpu-basic",
134+
},
135+
storage: null,
136+
gcTimeout: 172800,
137+
replicas: {
138+
current: 0,
139+
requested: 1,
140+
},
141+
},
142+
shortDescription: "This space is only for test",
143+
title: "TestSpace",
144+
isLikedByUser: false,
145+
trendingScore: 0,
146+
tags: ["docker", "region:us"],
147+
});
148+
149+
// Check for item type collection
150+
expect(items[3]).deep.equal({
151+
_id: "68670014f25517a0a7eaf505",
152+
position: 3,
153+
type: "collection",
154+
id: "6866ff686ca2d2e0a1931507",
155+
slug: "quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
156+
title: "Test Collection",
157+
description: "This collection is only for test",
158+
lastUpdated: "2025-07-01T00:41:27.525Z",
159+
numberItems: 5,
160+
owner: {
161+
_id: "6866ff3936a7677f427f99e3",
162+
avatarUrl: "/avatars/b51088e22fb7194888551365b1bafada.svg",
163+
fullname: "Quang-Huy Tran",
164+
name: "quanghuynt14",
165+
type: "user",
166+
isPro: false,
167+
isHf: false,
168+
isHfAdmin: false,
169+
isMod: false,
170+
},
171+
theme: "purple",
172+
shareUrl: "https://hub-ci.huggingface.co/collections/quanghuynt14/test-collection-6866ff686ca2d2e0a1931507",
173+
upvotes: 0,
174+
isUpvotedByUser: false,
175+
});
176+
177+
// Check for item type paper
178+
expect(items[4]).deep.equal({
179+
_id: "6867002186ea6972ba6c9b54",
180+
position: 4,
181+
type: "paper",
182+
id: "1910.09700",
183+
title: "Quantifying the Carbon Emissions of Machine Learning",
184+
publishedAt: "2019-10-21T23:57:32.000Z",
185+
thumbnailUrl: "https://cdn-thumbnails.huggingface.co/social-thumbnails/papers/1910.09700.png",
186+
upvotes: 0,
187+
isUpvotedByUser: false,
188+
});
189+
});
190+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { HUB_URL } from "../consts";
2+
import { createApiError } from "../error";
3+
import type { ApiCollectionInfo } from "../types/api/api-collection";
4+
import type { CredentialsParams } from "../types/public";
5+
import { checkCredentials } from "../utils/checkCredentials";
6+
7+
export async function collectionInfo(
8+
params: {
9+
/**
10+
* The slug of the collection.
11+
*/
12+
collectionSlug: string;
13+
hubUrl?: string;
14+
/**
15+
* Custom fetch function to use instead of the default one, for example to use a proxy or edit headers.
16+
*/
17+
fetch?: typeof fetch;
18+
} & Partial<CredentialsParams>
19+
): Promise<ApiCollectionInfo & { position: number; shareUrl: string }> {
20+
const accessToken = checkCredentials(params);
21+
22+
const res = await (params.fetch ?? fetch)(`${params.hubUrl ?? HUB_URL}/api/collections/${params.collectionSlug}`, {
23+
headers: {
24+
"Content-Type": "application/json",
25+
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : undefined),
26+
},
27+
});
28+
29+
if (!res.ok) {
30+
throw await createApiError(res);
31+
}
32+
33+
return await res.json();
34+
}

packages/hub/src/lib/list-collections.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { checkCredentials } from "../utils/checkCredentials";
55
import { parseLinkHeader } from "../utils/parseLinkHeader";
66
import type { ApiCollectionInfo } from "../types/api/api-collection";
77

8+
/*
9+
* When listing collections, the item list per collection is truncated to 4 items maximum.
10+
* To retrieve all items from a collection, you need to make an additional call using its collection slug.
11+
*/
812
export async function* listCollections(
913
params?: {
1014
search?: {

packages/hub/src/types/api/api-collection.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ export interface ApiCollectionInfo {
2121
}
2222
);
2323
owner: ApiAuthor;
24-
/*
25-
* The items list per collection is truncated to 4 items maximum.
26-
* To retrieve all items from a collection, you need to make an additional call using its collection slug.
27-
*/
2824
items: ApiCollectionItem[];
2925
theme: "orange" | "blue" | "green" | "purple" | "pink" | "indigo";
3026
private: boolean;

0 commit comments

Comments
 (0)