github-pinned-repo-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# GitHub Pinned Repository SDK
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/github-pinned-repo-sdk)
|
|
4
|
+
[](https://npmjs.com/package/github-pinned-repo-sdk)
|
|
5
|
+
[](https://github.com/luisoos/github-pinned-repo-sdk/blob/main/LICENSE)
|
|
6
|
+
|
|
7
|
+
Fetch GitHub user profile + pinned repositories with full TypeScript support.
|
|
8
|
+
|
|
9
|
+
**Based on** [better-github-api](https://github.com/luisoos/better-github-api)
|
|
10
|
+
|
|
11
|
+
## ๐ Installation
|
|
12
|
+
```bash
|
|
13
|
+
npm i github-pinned-repo-sdk
|
|
14
|
+
|
|
15
|
+
// OR using yarn
|
|
16
|
+
|
|
17
|
+
yarn add github-pinned-repo-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## ๐ Usage
|
|
21
|
+
```ts
|
|
22
|
+
import { getPinnedRepos } from 'github-pinned-repo-sdk';
|
|
23
|
+
|
|
24
|
+
const data = await getPinnedRepos('sindresorhus');
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
#### TypeScript
|
|
28
|
+
Define types:
|
|
29
|
+
```ts
|
|
30
|
+
import { getPinnedRepos } from 'github-pinned-repo-sdk';
|
|
31
|
+
|
|
32
|
+
type ApiResponse = {
|
|
33
|
+
user: GithubUser;
|
|
34
|
+
pinned_repos: PinnedRepo[];
|
|
35
|
+
pinned_repos_total_stars: number;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const data: ApiResponse = await getPinnedRepos('sindresorhus');
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## ๐งช Testing
|
|
42
|
+
Run tests using vitest:
|
|
43
|
+
```bash
|
|
44
|
+
npm test
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### In node console
|
|
48
|
+
```bash
|
|
49
|
+
node -e "import('./dist/index.js').then(async m=>{const {JSDOM}=await import('jsdom');global.DOMParser=new JSDOM().window.DOMParser;const data=await m.getPinnedRepos('luisoos');console.log(data)})"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## ๐ Astro Example
|
|
53
|
+
|
|
54
|
+
```astro
|
|
55
|
+
---
|
|
56
|
+
import { getPinnedRepos } from 'github-pinned-repo-sdk';
|
|
57
|
+
const { user, pinned_repos } = await getPinnedRepos('torvalds');
|
|
58
|
+
***
|
|
59
|
+
<h1>{user.login}</h1>
|
|
60
|
+
<ul>
|
|
61
|
+
{pinned_repos.map(repo => (
|
|
62
|
+
<li>
|
|
63
|
+
<a href={repo.link}>{repo.repo}</a>
|
|
64
|
+
<span>โญ {repo.stars.toLocaleString()}</span>
|
|
65
|
+
</li>
|
|
66
|
+
))}
|
|
67
|
+
</ul>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## ๐ฆ Features
|
|
71
|
+
|
|
72
|
+
- โ
**No dependencies** (pure `fetch` + `DOMParser`)
|
|
73
|
+
- โ
**Full TypeScript** (IntelliSense ready)
|
|
74
|
+
- โ
**Browser + Node** compatible
|
|
75
|
+
- โ
**GitHub API** + HTML scraping hybrid
|
|
76
|
+
- โ
**Rate-limit safe** (User-Agent headers)
|
|
77
|
+
|
|
78
|
+
## ๐ Credits
|
|
79
|
+
|
|
80
|
+
Inspired by [better-github-api](https://github.com/luisoos/better-github-api)
|
|
81
|
+
|
|
82
|
+
## ๐ License
|
|
83
|
+
|
|
84
|
+
MIT ยฉ [luisoos](https://github.com/luisoos)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type GithubUser = {
|
|
2
|
+
login: string;
|
|
3
|
+
id: number;
|
|
4
|
+
avatar_url: string;
|
|
5
|
+
html_url: string;
|
|
6
|
+
public_repos: number;
|
|
7
|
+
followers: number;
|
|
8
|
+
following: number;
|
|
9
|
+
};
|
|
10
|
+
type PinnedRepo = {
|
|
11
|
+
owner: string;
|
|
12
|
+
repo: string;
|
|
13
|
+
internal_link?: string;
|
|
14
|
+
link?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
language?: string;
|
|
17
|
+
languageColor?: string;
|
|
18
|
+
stars: number;
|
|
19
|
+
forks: number;
|
|
20
|
+
};
|
|
21
|
+
export declare function getPinnedRepos(username: string): Promise<{
|
|
22
|
+
user: GithubUser;
|
|
23
|
+
pinned_repos: PinnedRepo[];
|
|
24
|
+
pinned_repos_total_stars: number;
|
|
25
|
+
}>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAMF,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,wBAAwB,EAAE,MAAM,CAAC;CAClC,CAAC,CA8ED"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export async function getPinnedRepos(username) {
|
|
2
|
+
// 1. Official GitHub API for user data
|
|
3
|
+
const apiUrl = `https://api.github.com/users/${username}`;
|
|
4
|
+
const apiResponse = await fetch(apiUrl, {
|
|
5
|
+
headers: { 'User-Agent': 'github-pinned-sdk/1.0.0' }
|
|
6
|
+
});
|
|
7
|
+
if (!apiResponse.ok) {
|
|
8
|
+
throw new Error(`GitHub API failed: ${apiResponse.status}`);
|
|
9
|
+
}
|
|
10
|
+
const user = await apiResponse.json();
|
|
11
|
+
// 2. Scrape page for pinned repos (no official endpoint)
|
|
12
|
+
const pageUrl = `https://github.com/${username}`;
|
|
13
|
+
const pageResponse = await fetch(pageUrl, {
|
|
14
|
+
headers: { 'User-Agent': 'github-pinned-sdk/1.0.0' }
|
|
15
|
+
});
|
|
16
|
+
if (!pageResponse.ok) {
|
|
17
|
+
throw new Error(`GitHub page fetch failed: ${pageResponse.status}`);
|
|
18
|
+
}
|
|
19
|
+
const html = await pageResponse.text();
|
|
20
|
+
const parser = new DOMParser();
|
|
21
|
+
const doc = parser.parseFromString(html, 'text/html');
|
|
22
|
+
const pinnedItems = doc.querySelectorAll('.js-pinned-items-reorder-container > ol > li');
|
|
23
|
+
const pinnedRepositories = [];
|
|
24
|
+
let pinnedRepositoriesStars = 0;
|
|
25
|
+
pinnedItems.forEach((elem) => {
|
|
26
|
+
const ownerEl = elem.querySelector('.owner');
|
|
27
|
+
const owner = ownerEl ? ownerEl.textContent?.trim() || username : username;
|
|
28
|
+
const repoEl = elem.querySelector('.repo');
|
|
29
|
+
const repo = repoEl ? repoEl.textContent?.trim() || '' : '';
|
|
30
|
+
const linkEl = elem.querySelector('a');
|
|
31
|
+
const internal_link = linkEl?.getAttribute('href') || undefined;
|
|
32
|
+
const link = internal_link ? `https://github.com${internal_link}` : undefined;
|
|
33
|
+
const descEl = elem.querySelector('.pinned-item-desc');
|
|
34
|
+
let description = descEl ? descEl.textContent?.trim() || undefined : undefined;
|
|
35
|
+
if (description) {
|
|
36
|
+
description = description.slice(9, -7).trim();
|
|
37
|
+
}
|
|
38
|
+
const langEl = elem.querySelector('[itemprop="programmingLanguage"]');
|
|
39
|
+
const language = langEl ? langEl.textContent?.trim() || undefined : undefined;
|
|
40
|
+
const langColorEl = elem.querySelector('.repo-language-color');
|
|
41
|
+
const languageColor = langColorEl ? langColorEl.getAttribute('style')?.match(/background-color:\s*(.+?);/)?.[1] || undefined : undefined;
|
|
42
|
+
const starsEl = elem.querySelector('a[href$="/stargazers"]');
|
|
43
|
+
const stars = starsEl ? parseInt(starsEl.textContent?.trim() || '0', 10) : 0;
|
|
44
|
+
const forksEl = elem.querySelector('a[href$="/forks"]');
|
|
45
|
+
const forks = forksEl ? parseInt(forksEl.textContent?.trim() || '0', 10) : 0;
|
|
46
|
+
const repoData = {
|
|
47
|
+
owner,
|
|
48
|
+
repo,
|
|
49
|
+
...(internal_link !== undefined && { internal_link }),
|
|
50
|
+
...(link !== undefined && { link }),
|
|
51
|
+
...(description !== undefined && { description }),
|
|
52
|
+
...(language !== undefined && { language }),
|
|
53
|
+
...(languageColor !== undefined && { languageColor }),
|
|
54
|
+
stars,
|
|
55
|
+
forks,
|
|
56
|
+
};
|
|
57
|
+
pinnedRepositories.push(repoData);
|
|
58
|
+
pinnedRepositoriesStars += stars;
|
|
59
|
+
});
|
|
60
|
+
return {
|
|
61
|
+
user,
|
|
62
|
+
pinned_repos: pinnedRepositories,
|
|
63
|
+
pinned_repos_total_stars: pinnedRepositoriesStars,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "github-pinned-repo-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SDK to simply fetch a GitHub user's pinned repositories and general data.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "vitest",
|
|
13
|
+
"test:ui": "vitest --ui",
|
|
14
|
+
"prepublishOnly": "npm run build && npm test"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "github.com/luisoos/github-pinned-repo-sdk"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"github",
|
|
22
|
+
"api",
|
|
23
|
+
"github-api",
|
|
24
|
+
"github-sdk",
|
|
25
|
+
"pinned-repositories",
|
|
26
|
+
"pinned-repos"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"author": "luisoos",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^25.0.3",
|
|
33
|
+
"@vitest/ui": "^4.0.16",
|
|
34
|
+
"jsdom": "^27.4.0",
|
|
35
|
+
"typescript": "^5.9.3",
|
|
36
|
+
"vitest": "^4.0.16"
|
|
37
|
+
}
|
|
38
|
+
}
|