@forgeportal/plugin-github-insights 1.3.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/.turbo/turbo-build.log +4 -0
- package/LICENSE +21 -0
- package/dist/GitHubInsightsTab.d.ts +8 -0
- package/dist/GitHubInsightsTab.d.ts.map +1 -0
- package/dist/GitHubInsightsTab.js +111 -0
- package/dist/GitHubInsightsTab.js.map +1 -0
- package/dist/__tests__/api-client.test.d.ts +2 -0
- package/dist/__tests__/api-client.test.d.ts.map +1 -0
- package/dist/__tests__/api-client.test.js +159 -0
- package/dist/__tests__/api-client.test.js.map +1 -0
- package/dist/api-client.d.ts +34 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +85 -0
- package/dist/api-client.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/routes.d.ts +14 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +115 -0
- package/dist/routes.js.map +1 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ui.d.ts +11 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +17 -0
- package/dist/ui.js.map +1 -0
- package/forgeportal-plugin.json +23 -0
- package/package.json +50 -0
- package/src/GitHubInsightsTab.tsx +421 -0
- package/src/__tests__/api-client.test.ts +192 -0
- package/src/api-client.ts +120 -0
- package/src/index.ts +42 -0
- package/src/routes.ts +151 -0
- package/src/types.ts +86 -0
- package/src/ui.ts +18 -0
- package/tsconfig.json +11 -0
package/dist/routes.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { GitHubInsightsClient } from './api-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates Fastify route handlers for the GitHub Insights plugin.
|
|
4
|
+
* All routes mounted under /api/v1/plugins/github-insights/ by the plugin loader.
|
|
5
|
+
*
|
|
6
|
+
* Routes:
|
|
7
|
+
* GET entities/:entityId/overview — repo info + open PR count + latest commit
|
|
8
|
+
* GET entities/:entityId/prs — paginated open PRs
|
|
9
|
+
* GET entities/:entityId/commits — last 20 commits
|
|
10
|
+
* GET entities/:entityId/contributors — top contributors
|
|
11
|
+
*/
|
|
12
|
+
export function createRoutes(config) {
|
|
13
|
+
const client = new GitHubInsightsClient(config);
|
|
14
|
+
return async function handler(fastify) {
|
|
15
|
+
function requireOwnerRepo(request, reply) {
|
|
16
|
+
const { owner, repo } = request.query;
|
|
17
|
+
if (!owner || !repo) {
|
|
18
|
+
void reply.status(400).send({
|
|
19
|
+
error: 'Bad Request',
|
|
20
|
+
message: 'Query parameters "owner" and "repo" are required.',
|
|
21
|
+
});
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return { owner, repo };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* GET /entities/:entityId/overview?owner=&repo=
|
|
28
|
+
* Returns: repo metadata + open PR count + latest commit.
|
|
29
|
+
*/
|
|
30
|
+
fastify.get('entities/:entityId/overview', async (request, reply) => {
|
|
31
|
+
const ref = requireOwnerRepo(request, reply);
|
|
32
|
+
if (!ref)
|
|
33
|
+
return;
|
|
34
|
+
try {
|
|
35
|
+
const [repoData, prs, commits] = await Promise.allSettled([
|
|
36
|
+
client.getRepo(ref.owner, ref.repo),
|
|
37
|
+
client.getOpenPRs(ref.owner, ref.repo),
|
|
38
|
+
client.getRecentCommits(ref.owner, ref.repo),
|
|
39
|
+
]);
|
|
40
|
+
const repo = repoData.status === 'fulfilled' ? repoData.value : null;
|
|
41
|
+
const openPRCount = prs.status === 'fulfilled' ? prs.value.length : 0;
|
|
42
|
+
const latestCommit = commits.status === 'fulfilled' ? (commits.value[0] ?? null) : null;
|
|
43
|
+
if (!repo) {
|
|
44
|
+
const err = repoData.status === 'rejected' ? repoData.reason : new Error('Unknown');
|
|
45
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
46
|
+
if (message.includes('not found')) {
|
|
47
|
+
return reply.status(404).send({ error: 'Not Found', message });
|
|
48
|
+
}
|
|
49
|
+
return reply.status(502).send({ error: 'Bad Gateway', message });
|
|
50
|
+
}
|
|
51
|
+
return reply.send({ data: { repo, openPRCount, latestCommit } });
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
55
|
+
request.log.error({ err }, 'github-insights: getOverview failed');
|
|
56
|
+
return reply.status(502).send({ error: 'Bad Gateway', message });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* GET /entities/:entityId/prs?owner=&repo=
|
|
61
|
+
* Returns up to 25 open pull requests.
|
|
62
|
+
*/
|
|
63
|
+
fastify.get('entities/:entityId/prs', async (request, reply) => {
|
|
64
|
+
const ref = requireOwnerRepo(request, reply);
|
|
65
|
+
if (!ref)
|
|
66
|
+
return;
|
|
67
|
+
try {
|
|
68
|
+
const prs = await client.getOpenPRs(ref.owner, ref.repo);
|
|
69
|
+
return reply.send({ data: prs });
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
73
|
+
request.log.error({ err }, 'github-insights: getPRs failed');
|
|
74
|
+
return reply.status(502).send({ error: 'Bad Gateway', message });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* GET /entities/:entityId/commits?owner=&repo=
|
|
79
|
+
* Returns the last 20 commits.
|
|
80
|
+
*/
|
|
81
|
+
fastify.get('entities/:entityId/commits', async (request, reply) => {
|
|
82
|
+
const ref = requireOwnerRepo(request, reply);
|
|
83
|
+
if (!ref)
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
const commits = await client.getRecentCommits(ref.owner, ref.repo);
|
|
87
|
+
return reply.send({ data: commits });
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
91
|
+
request.log.error({ err }, 'github-insights: getCommits failed');
|
|
92
|
+
return reply.status(502).send({ error: 'Bad Gateway', message });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* GET /entities/:entityId/contributors?owner=&repo=
|
|
97
|
+
* Returns top contributors by commit count.
|
|
98
|
+
*/
|
|
99
|
+
fastify.get('entities/:entityId/contributors', async (request, reply) => {
|
|
100
|
+
const ref = requireOwnerRepo(request, reply);
|
|
101
|
+
if (!ref)
|
|
102
|
+
return;
|
|
103
|
+
try {
|
|
104
|
+
const contributors = await client.getContributors(ref.owner, ref.repo);
|
|
105
|
+
return reply.send({ data: contributors.slice(0, 5) });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
109
|
+
request.log.error({ err }, 'github-insights: getContributors failed');
|
|
110
|
+
return reply.status(502).send({ error: 'Bad Gateway', message });
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export interface GHRepo {
|
|
2
|
+
full_name: string;
|
|
3
|
+
description: string | null;
|
|
4
|
+
default_branch: string;
|
|
5
|
+
language: string | null;
|
|
6
|
+
stargazers_count: number;
|
|
7
|
+
forks_count: number;
|
|
8
|
+
open_issues_count: number;
|
|
9
|
+
html_url: string;
|
|
10
|
+
private: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface GHPRLabel {
|
|
13
|
+
name: string;
|
|
14
|
+
color: string;
|
|
15
|
+
}
|
|
16
|
+
export interface GHPR {
|
|
17
|
+
number: number;
|
|
18
|
+
title: string;
|
|
19
|
+
html_url: string;
|
|
20
|
+
state: string;
|
|
21
|
+
created_at: string;
|
|
22
|
+
updated_at: string;
|
|
23
|
+
user: {
|
|
24
|
+
login: string;
|
|
25
|
+
avatar_url: string;
|
|
26
|
+
};
|
|
27
|
+
labels: GHPRLabel[];
|
|
28
|
+
draft: boolean;
|
|
29
|
+
head: {
|
|
30
|
+
ref: string;
|
|
31
|
+
};
|
|
32
|
+
base: {
|
|
33
|
+
ref: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export interface GHCommitAuthor {
|
|
37
|
+
name: string;
|
|
38
|
+
email: string;
|
|
39
|
+
date: string;
|
|
40
|
+
}
|
|
41
|
+
export interface GHCommit {
|
|
42
|
+
sha: string;
|
|
43
|
+
html_url: string;
|
|
44
|
+
commit: {
|
|
45
|
+
message: string;
|
|
46
|
+
author: GHCommitAuthor;
|
|
47
|
+
committer: GHCommitAuthor;
|
|
48
|
+
};
|
|
49
|
+
author: {
|
|
50
|
+
login: string;
|
|
51
|
+
avatar_url: string;
|
|
52
|
+
} | null;
|
|
53
|
+
}
|
|
54
|
+
export interface GHContributor {
|
|
55
|
+
login: string;
|
|
56
|
+
avatar_url: string;
|
|
57
|
+
html_url: string;
|
|
58
|
+
contributions: number;
|
|
59
|
+
}
|
|
60
|
+
export interface GHWorkflowRun {
|
|
61
|
+
id: number;
|
|
62
|
+
name: string | null;
|
|
63
|
+
display_title: string;
|
|
64
|
+
status: string | null;
|
|
65
|
+
conclusion: string | null;
|
|
66
|
+
html_url: string;
|
|
67
|
+
created_at: string;
|
|
68
|
+
head_branch: string | null;
|
|
69
|
+
}
|
|
70
|
+
export interface GitHubOverview {
|
|
71
|
+
repo: GHRepo;
|
|
72
|
+
openPRCount: number;
|
|
73
|
+
latestCommit: GHCommit | null;
|
|
74
|
+
}
|
|
75
|
+
export interface GitHubInsightsConfig {
|
|
76
|
+
token: string;
|
|
77
|
+
cacheTTLSeconds: number;
|
|
78
|
+
}
|
|
79
|
+
export interface CacheEntry<T> {
|
|
80
|
+
data: T;
|
|
81
|
+
expiresAt: number;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM;IACrB,SAAS,EAAS,MAAM,CAAC;IACzB,WAAW,EAAO,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAI,MAAM,CAAC;IACzB,QAAQ,EAAU,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAO,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAU,MAAM,CAAC;IACzB,OAAO,EAAW,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAE1D,MAAM,WAAW,IAAI;IACnB,MAAM,EAAM,MAAM,CAAC;IACnB,KAAK,EAAO,MAAM,CAAC;IACnB,QAAQ,EAAI,MAAM,CAAC;IACnB,KAAK,EAAO,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAQ;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,MAAM,EAAM,SAAS,EAAE,CAAC;IACxB,KAAK,EAAO,OAAO,CAAC;IACpB,IAAI,EAAQ;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,IAAI,EAAQ;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAG,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAG,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAQ,MAAM,CAAC;IAClB,QAAQ,EAAG,MAAM,CAAC;IAClB,MAAM,EAAE;QACN,OAAO,EAAI,MAAM,CAAC;QAClB,MAAM,EAAK,cAAc,CAAC;QAC1B,SAAS,EAAE,cAAc,CAAC;KAC3B,CAAC;IACF,MAAM,EAAK;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACzD;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAS,MAAM,CAAC;IACrB,UAAU,EAAI,MAAM,CAAC;IACrB,QAAQ,EAAM,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAY,MAAM,CAAC;IACrB,IAAI,EAAU,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAQ,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAI,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAM,MAAM,CAAC;IACrB,UAAU,EAAI,MAAM,CAAC;IACrB,WAAW,EAAG,MAAM,GAAG,IAAI,CAAC;CAC7B;AAID,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAY,MAAM,CAAC;IACvB,WAAW,EAAK,MAAM,CAAC;IACvB,YAAY,EAAI,QAAQ,GAAG,IAAI,CAAC;CACjC;AAID,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAW,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;CACzB;AAID,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAO,CAAC,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+EAA+E"}
|
package/dist/ui.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ForgePluginSDK } from '@forgeportal/plugin-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* UI entry point for the GitHub Insights plugin.
|
|
4
|
+
* Called by the ForgePortal UI shell at startup.
|
|
5
|
+
*
|
|
6
|
+
* Registration in apps/ui/src/plugins/index.ts:
|
|
7
|
+
* import { registerPlugin as registerGitHubInsights } from '@forgeportal/plugin-github-insights/ui';
|
|
8
|
+
* registerPluginById('github-insights', registerGitHubInsights);
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerPlugin(sdk: ForgePluginSDK): void;
|
|
11
|
+
//# sourceMappingURL=ui.d.ts.map
|
package/dist/ui.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAG9D;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAMxD"}
|
package/dist/ui.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { GitHubInsightsTab } from './GitHubInsightsTab.js';
|
|
2
|
+
/**
|
|
3
|
+
* UI entry point for the GitHub Insights plugin.
|
|
4
|
+
* Called by the ForgePortal UI shell at startup.
|
|
5
|
+
*
|
|
6
|
+
* Registration in apps/ui/src/plugins/index.ts:
|
|
7
|
+
* import { registerPlugin as registerGitHubInsights } from '@forgeportal/plugin-github-insights/ui';
|
|
8
|
+
* registerPluginById('github-insights', registerGitHubInsights);
|
|
9
|
+
*/
|
|
10
|
+
export function registerPlugin(sdk) {
|
|
11
|
+
sdk.registerEntityTab({
|
|
12
|
+
id: 'github-insights-tab',
|
|
13
|
+
title: 'GitHub',
|
|
14
|
+
component: GitHubInsightsTab,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,GAAmB;IAChD,GAAG,CAAC,iBAAiB,CAAC;QACpB,EAAE,EAAS,qBAAqB;QAChC,KAAK,EAAM,QAAQ;QACnB,SAAS,EAAE,iBAAiB;KAC7B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forgeportal/plugin-github-insights",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"forgeportal": {
|
|
5
|
+
"engineVersion": "^1.0.0",
|
|
6
|
+
"type": "fullstack",
|
|
7
|
+
"capabilities": {
|
|
8
|
+
"ui": {
|
|
9
|
+
"entityTabs": ["github-insights-tab"]
|
|
10
|
+
},
|
|
11
|
+
"backend": {
|
|
12
|
+
"routes": ["/api/v1/plugins/github-insights"]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"config": {
|
|
16
|
+
"cacheTTLSeconds": {
|
|
17
|
+
"type": "number",
|
|
18
|
+
"description": "Cache TTL for GitHub API responses (default: 300s). Set to 0 to disable caching.",
|
|
19
|
+
"required": false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forgeportal/plugin-github-insights",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"./ui": {
|
|
11
|
+
"types": "./dist/ui.d.ts",
|
|
12
|
+
"import": "./dist/ui.js"
|
|
13
|
+
},
|
|
14
|
+
"./package.json": "./package.json",
|
|
15
|
+
"./forgeportal-plugin.json": "./forgeportal-plugin.json"
|
|
16
|
+
},
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"types": "dist/index.d.ts",
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@forgeportal/plugin-sdk": "1.3.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@tanstack/react-query": "*",
|
|
27
|
+
"@types/react": "*",
|
|
28
|
+
"fastify": "^5.3.3",
|
|
29
|
+
"react": "*",
|
|
30
|
+
"vitest": "*"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@tanstack/react-query": ">=5",
|
|
34
|
+
"react": ">=19"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"react": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"@tanstack/react-query": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"lint": "eslint src/",
|
|
48
|
+
"clean": "rm -rf dist"
|
|
49
|
+
}
|
|
50
|
+
}
|