Skip to content

Commit

Permalink
[add] GitHub API reverse proxy
Browse files Browse the repository at this point in the history
[add] Volunteer Statistic charts based on OSS Insight
[fix] some detail bugs
[optimize] update Upstream packages
  • Loading branch information
TechQuery committed Aug 21, 2024
1 parent 037a118 commit fdf96b7
Show file tree
Hide file tree
Showing 9 changed files with 1,043 additions and 1,058 deletions.
4 changes: 2 additions & 2 deletions components/Git/ArticleEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,10 @@ export class ArticleEditor extends Component {
<div className="d-flex justify-content-between align-items-center my-2">
<label>{t('content')}</label>
</div>
{editorContent && (
{(!repository || editorContent) && (
<HTMLEditor
defaultValue={editorContent}
onChange={value => (this.editorContent = value)}
onChange={value => (this.editorContent = value || '<br>')}
/>
)}
</Form.Group>
Expand Down
13 changes: 9 additions & 4 deletions models/Repository.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { HTTPClient } from 'koajax';
import {
githubClient,
RepositoryFilter,
Expand All @@ -7,6 +8,7 @@ import {
import { parseCookie } from 'mobx-i18n';
import { toggle } from 'mobx-restful';

import { ProxyBaseURL } from '../pages/api/GitHub/core';
import { API_Host, isServer } from './Base';

const GithubToken =
Expand All @@ -25,6 +27,11 @@ githubClient.use(({ request }, next) => {
});

export class GitRepositoryModel extends RepositoryModel {
downloader = new HTTPClient({
baseURI: `${ProxyBaseURL}/raw.githubusercontent.com/`,
responseType: 'arraybuffer',
});

@toggle('downloading')
async downloadRaw(
path: string,
Expand All @@ -39,10 +46,8 @@ export class GitRepositoryModel extends RepositoryModel {

ref = default_branch;
}
const { body } = await this.client.get<ArrayBuffer>(
`raw/${identity}/${ref}/${path}`,
{},
{ responseType: 'arraybuffer' },
const { body } = await this.downloader.get<ArrayBuffer>(
`${identity}/${ref}/${path}`,
);
return body!;
}
Expand Down
118 changes: 77 additions & 41 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import NextMDX from '@next/mdx';
import { withSentryConfig } from '@sentry/nextjs';
import CopyPlugin from 'copy-webpack-plugin';
import { readdirSync, statSync } from 'fs';
// @ts-ignore
import setPWA from 'next-pwa';
// @ts-ignore
import withLess from 'next-with-less';
import RemarkFrontMatter from 'remark-frontmatter';
import RemarkGfm from 'remark-gfm';
import RemarkMdxFrontMatter from 'remark-mdx-frontmatter';
import webpack from 'webpack';
import wp from 'webpack';

const { NODE_ENV, SENTRY_AUTH_TOKEN, SENTRY_ORG, SENTRY_PROJECT } = process.env;
const isDev = NODE_ENV === 'development';
Expand All @@ -26,53 +28,87 @@ const withPWA = setPWA({
disable: isDev,
});

/**
* @type {import('next').NextConfig['webpack']}
*/
const webpack = config => {
config.plugins.push(
new wp.NormalModuleReplacementPlugin(/^node:/, resource => {
resource.request = resource.request.replace(/^node:/, '');
}),
);

if (
statSync('pages/article', {
throwIfNoEntry: false,
})?.isDirectory() &&
readdirSync('pages/article')[0]
)
config.plugins.push(
new CopyPlugin({
patterns: [{ from: 'pages/article', to: 'static/article' }],
}),
);
return config;
};

/**
* @type {import('next').NextConfig['rewrites']}
*/
const rewrites = async () => ({
beforeFiles: [
{
source: '/proxy/github.com/:path*',
has: isDev
? undefined
: [
{
type: 'header',
key: 'Host',
value: 'test.oss-toolbox.kaiyuanshe.cn',
},
],
destination: 'https://github.com/:path*',
},
{
source: '/proxy/raw.githubusercontent.com/:path*',
has: isDev
? undefined
: [
{
type: 'header',
key: 'Host',
value: 'test.oss-toolbox.kaiyuanshe.cn',
},
],
destination: 'https://raw.githubusercontent.com/:path*',
},
],
afterFiles: [],
fallback: [
{
source: '/article/:path*',
destination: `/_next/static/article/:path*`,
has: [
{
type: 'header',
key: 'Accept',
value: '.*(image|audio|video|application)/.*',
},
],
},
],
});

/** @type {import('next').NextConfig} */
const nextConfig = withPWA(
withLess(
withMDX({
output: 'standalone',
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
transpilePackages: ['@sentry/browser'],
webpack: config => {
config.plugins.push(
new webpack.NormalModuleReplacementPlugin(/^node:/, resource => {
resource.request = resource.request.replace(/^node:/, '');
}),
);

if (
statSync('pages/article', {
throwIfNoEntry: false,
})?.isDirectory() &&
readdirSync('pages/article')[0]
)
config.plugins.push(
new CopyPlugin({
patterns: [
{
from: 'pages/article',
to: 'static/article',
},
],
}),
);
return config;
},
rewrites: () => ({
fallback: [
{
source: '/article/:path*',
destination: `/_next/static/article/:path*`,
has: [
{
type: 'header',
key: 'Accept',
value: '.*(image|audio|video|application)/.*',
},
],
},
],
}),
webpack,
rewrites,
}),
),
);
Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
"@mdx-js/loader": "^3.0.1",
"@mdx-js/react": "^3.0.1",
"@next/mdx": "^14.2.5",
"@sentry/nextjs": "^8.24.0",
"@sentry/nextjs": "^8.26.0",
"classnames": "^2.5.1",
"copy-webpack-plugin": "^12.0.2",
"file-type": "^19.4.0",
"file-type": "^19.4.1",
"idea-react": "^2.0.0-rc.2",
"koajax": "^1.1.2",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"license-filter": "^0.2.4",
"lodash": "^4.17.21",
"markdown-ime": "^1.0.3",
"marked": "^13.0.3",
"marked": "^14.0.0",
"mobx": "^6.13.1",
"mobx-github": "^0.3.2",
"mobx-i18n": "^0.5.0",
Expand All @@ -30,7 +30,7 @@
"mobx-restful-table": "^2.0.0-rc.1",
"next": "^14.2.5",
"next-pwa": "~5.6.0",
"next-ssr-middleware": "^0.8.2",
"next-ssr-middleware": "^0.8.5",
"next-with-less": "^3.0.1",
"primereact": "^10.8.2",
"react": "^18.3.1",
Expand All @@ -51,16 +51,16 @@
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/preset-react": "^7.24.7",
"@types/lodash": "^4.17.7",
"@types/node": "^18.19.43",
"@types/react": "^18.3.3",
"@types/node": "^18.19.45",
"@types/react": "^18.3.4",
"@types/turndown": "^5.0.5",
"eslint": "^8.57.0",
"eslint-config-next": "^14.2.5",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"get-git-folder": "^0.1.2",
"husky": "^9.1.4",
"lint-staged": "^15.2.8",
"husky": "^9.1.5",
"lint-staged": "^15.2.9",
"prettier": "^3.3.3",
"typescript": "~5.5.4"
},
Expand Down
2 changes: 1 addition & 1 deletion pages/_error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const enableSentry =
process.env.NODE_ENV === 'development' || !process.env.SENTRY_AUTH_TOKEN;

CustomErrorComponent.getInitialProps = async contextData => {
const { 'accept-language': acceptLanguage, cookie } =
const { 'accept-language': acceptLanguage, cookie = '' } =
contextData.req!.headers;
const { language } = parseCookie(cookie),
languages = parseLanguageHeader(acceptLanguage || '');
Expand Down
6 changes: 5 additions & 1 deletion pages/api/GitHub/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ export const proxyGithub = <T>(dataFilter?: (path: string, data: T) => T) =>
});

const client_id = process.env.NEXT_PUBLIC_GITHUB_OAUTH_CLIENT_ID!,
client_secret = process.env.GITHUB_OAUTH_CLIENT_SECRET!;
client_secret = process.env.GITHUB_OAUTH_CLIENT_SECRET!,
{ VERCEL } = process.env;

export const ProxyBaseURL = 'https://test.oss-toolbox.kaiyuanshe.cn/proxy';

export const githubOAuth = githubOAuth2({
rootBaseURL: VERCEL ? undefined : `${ProxyBaseURL}/github.com/`,
client_id,
client_secret,
scopes: ['user', 'repo'],
Expand Down
97 changes: 69 additions & 28 deletions pages/volunteer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Contributor } from 'mobx-github';
import { observer } from 'mobx-react';
import { InferGetServerSidePropsType } from 'next';
import { cache, compose, errorLogger } from 'next-ssr-middleware';
import { FC } from 'react';
Expand All @@ -18,34 +19,74 @@ export const getServerSideProps = compose(cache(), errorLogger, async () => {
return { props: { contributors } };
});

const Organizer: FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({
contributors,
}) => (
<Container>
<PageHead title={t('volunteer')} />
<h1 className="py-5 text-center text-md-start ps-md-4">{t('volunteer')}</h1>
const Organizer: FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
observer(({ contributors }) => (
<Container>
<PageHead title={t('volunteer')} />
<h1 className="py-5 text-center text-md-start ps-md-4">
{t('volunteer')}
</h1>

<SectionTitle count={contributors.length}>
{t('online_volunteer')}
</SectionTitle>
<Row
as="ul"
className="list-unstyled justify-content-center text-center"
xs={2}
sm={5}
md={6}
>
{contributors.map(({ login, html_url, contributions }) => (
<PersonCard
key={login}
name={login!}
avatar={`https://github.com/${login}.png`}
link={html_url}
count={contributions}
/>
))}
</Row>
</Container>
);
<section className="d-flex justify-content-around align-items-center gap-3 flex-wrap mb-5">
<a
className="d-block"
href="https://next.ossinsight.io/widgets/official/compose-org-participants-roles-ratio?owner_id=11659327&period=past_28_days"
target="_blank" rel="noreferrer"
>
<picture>
<source
media="(prefers-color-scheme: dark)"
srcSet="https://next.ossinsight.io/widgets/official/compose-org-participants-roles-ratio/thumbnail.png?owner_id=11659327&period=past_28_days&image_size=5x5&color_scheme=dark"
width="465"
/>
<img
alt="Participants roles of KaiYuanShe"
src="https://next.ossinsight.io/widgets/official/compose-org-participants-roles-ratio/thumbnail.png?owner_id=11659327&period=past_28_days&image_size=5x5&color_scheme=light"
width="465"
/>
</picture>
</a>
<a
className="d-block"
href="https://next.ossinsight.io/widgets/official/compose-org-engagement-scatter?owner_id=11659327&period=past_28_days"
target="_blank" rel="noreferrer"
>
<picture>
<source
media="(prefers-color-scheme: dark)"
srcSet="https://next.ossinsight.io/widgets/official/compose-org-engagement-scatter/thumbnail.png?owner_id=11659327&period=past_28_days&image_size=5x5&color_scheme=dark"
width="465"
/>
<img
alt="Most engaged people of KaiYuanShe"
src="https://next.ossinsight.io/widgets/official/compose-org-engagement-scatter/thumbnail.png?owner_id=11659327&period=past_28_days&image_size=5x5&color_scheme=light"
width="465"
/>
</picture>
</a>
</section>

<SectionTitle count={contributors.length}>
{t('online_volunteer')}
</SectionTitle>
<Row
as="ul"
className="list-unstyled justify-content-center text-center"
xs={2}
sm={5}
md={6}
>
{contributors.map(({ login, html_url, contributions }) => (
<PersonCard
key={login}
name={login!}
avatar={`https://github.com/${login}.png`}
link={html_url}
count={contributions}
/>
))}
</Row>
</Container>
));

export default Organizer;
Loading

1 comment on commit fdf96b7

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for oss-toolbox ready!

✅ Preview
https://oss-toolbox-9jmrgbhjt-techquerys-projects.vercel.app

Built with commit fdf96b7.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.