Convex OSS 数据组件
为您的开源项目保持 GitHub 和 npm 数据同步到您的 Convex 数据库 .
// convex/stats.ts
import { components } from "./_generated/api";
import { OssStats } from "@erquhart/convex-oss-stats";
export const ossStats = new OssStats(components.ossStats, {
// Get stats for entire owners / orgs
githubOwners: ["get-convex"],
npmOrgs: ["convex-dev"],
// Or individual repos / packages
githubRepos: ["get-convex/convex-js"],
npmPackages: ["@convex-dev/convex-js"],
});
export const {
sync,
clearAndSync,
getGithubOwner,
getNpmOrg,
getGithubRepo,
getGithubRepos,
getNpmPackage,
getNpmPackages,
} = ossStats.api();
// src/OssStats.tsx
import { useQuery } from "convex/react";
import { useNpmDownloadCounter } from "@erquhart/convex-oss-stats/react";
import { api } from "../convex/_generated/api";
const OssStats = () => {
const githubOwner = useQuery(api.stats.getGithubOwner, {
owner: "get-convex",
});
const npmOrg = useQuery(api.stats.getNpmOrg, {
org: "convex-dev",
});
// Use this hook to get a forecasted download count for an npm package or org
const liveNpmDownloadCount = useNpmDownloadCounter(npmOrg);
return (
<>
{/* If webhook is registered, this will update in realtime 🔥 */}
<div>{githubOwner.starCount}</div>
<div>{liveNpmDownloadCount.count}</div>
</>
);
};
先决条件
Convex 应用程序
你需要一个Convex App来使用组件. 跟着任何 Convex 快速启动 来设置一个.
GitHub 账户( 如果同步 GitHub 数据)
从您的 GitHub 账户获取以下证书:
- 访问托肯
- 转到账户设置并生成新访问令牌, 并读取访问到 公共仓库.
- Webhook 密钥: 为每个 org 或 repo 做此操作 .
- 注:这是可选的。 没有它,你就不会得到 活星数. 看怎么样 手动同步数据。 。 。 .
- 转到 Org/repo 的设置中并创建新的 webhook .
- 为您获取 HTTP 动作 URL 生产 对流部署设置 : https://dashboard.convex.dev/部署/设置 > HTTP 动作 URL
- 有效载荷 URL :
<http-actions-url>/events/github - 内容类型 :
application/json - 在您的 Convex 部署和 GitHub 之间创建共享密钥
- 哪些事件? > 选择个人 > 仅限恒星
Npm 数据说明
此组件访问 npm 数据是公开的,不需要任何证书.
安装
安装组件包 :
npm install @erquhart/convex-oss-stats
创建一个 convex.config.ts 应用程序中的文件 convex/ 通过调用文件夹并安装组件 use数字 :
// convex/convex.config.ts
import { defineApp } from "convex/server";
import ossStats from "@erquhart/convex-oss-stats/convex.config";
const app = defineApp();
app.use(ossStats);
export default app;
设置您的 API 证书 :
npx convex env set GITHUB_ACCESS_TOKEN=xxxxx
npx convex env set GITHUB_WEBHOOK_SECRET=xxxxx
如果你没有跑 npx convex dev 不过,你需要现在就开始.
它会生成您的组件的代码 convex/_generated/api 文件夹,
,并将在您更改文件时自动部署更改 convex/。 。 。 .
将 OssStats 组件客户端在您的应用程序中的文件进行校正 convex/ 文件夹 :
// convex/example.ts
import { OssStats } from "@erquhart/convex-oss-stats";
import { components } from "./_generated/api";
export const ossStats = new OssStats(components.ossStats, {
githubOwners: ["get-convex"],
npmOrgs: ["convex-dev"],
});
// Re-export functions for direct access from your convex instance
export const { sync, getGithubOwner, getNpmOrg } = ossStats.api();
通过创建一个 http.ts 文档中 convex/ 文件夹并使用您导出于上面的客户端 :
// http.ts
import { ossStats } from "./example";
import { httpRouter } from "convex/server";
const http = httpRouter();
ossStats.registerRoutes(http);
export default http;
从前端查询数据
使用 useQuery 钩从组件中获取数据。 以下是如何获取 GitHub 拥有者( org 或用户) 和 npm 包或 org 的数据的例子 :
// src/OssStats.tsx
import { useQuery } from 'convex/react'
import { api } from '../convex/_generated/api'
const OssStats = () => {
const githubOwner = useQuery(api.stats.getGithubOwner, {
owner: 'get-convex',
})
const npmOrg = useQuery(api.stats.getNpmOrg, {
org: 'convex-dev',
})
return (
<>
{/* If webhook is registered, this will update in realtime 🔥 */}
<div>{githubOwner.starCount}</div>
<div>{npmOrg.downloadCount}</div>
</>
)
}
可用查询
stats.getGithubOwner
const { starCount, dependentCount, dayOfWeekAverages, updatedAt } = useQuery(
api.stats.getGithubOwner,
{ owner: "get-convex" }
);
stats.getNpmOrg
const { downloadCount, dayOfWeekAverages, updatedAt } = useQuery(
api.stats.getNpmOrg,
{ org: "convex-dev" }
);
stats.getGithubRepo
const { starCount, dependentCount, dayOfWeekAverages, updatedAt } = useQuery(
api.stats.getGithubRepo,
{ name: "get-convex/convex-js" }
);
stats.getGithubRepos
const { starCount, dependentCount, dayOfWeekAverages, updatedAt } = useQuery(
api.stats.getGithubRepos,
{ names: ["get-convex/convex-js", "get-convex/convex-helpers"] }
);
stats.getNpmPackage
const { downloadCount, dayOfWeekAverages, updatedAt } = useQuery(
api.stats.getNpmPackage,
{ name: "@convex-dev/convex-js" }
);
stats.getNpmPackages
const { downloadCount, dayOfWeekAverages, updatedAt } = useQuery(
api.stats.getNpmPackages,
{ names: ["@convex-dev/convex-js", "@convex-dev/convex-helpers"] }
);
反应钩
useNpmDownloadCounter
提供 npm 软件包或 org 更新的预测下载数 一个间隔.
参数 :
npmPackageOrOrg: npmPackageOrg 对象从getNpmPackage或者说getNpmOrg查询options: 可选选项对象intervalMs: 覆盖计算间隔
回返情况:
count: 定期更新的下载数intervalMs: 更新计数的间隔(用于 配置客户端动画, 如数字花组件)
import { useNpmDownloadCounter } from "@erquhart/convex-oss-stats/react";
import NumberFlow from '@number-flow/react'
const npmOrg = useQuery(api.stats.getNpmOrg, { org: "convex-dev" });
const { count, intervalMs } = useNpmDownloadCounter(npmOrg)
return (
<NumberFlow
transformTiming={{
duration: intervalMs,
easing: 'linear',
}}
value={count}
trend={1}
continuous
willChange
/>
)
查询后端的数据
您也可以使用 ossStats 对象.
注意: 数据只提供给您配置的拥有者和 npm orgs
并同步了.
// Within a Convex query, mutation, or action:
// All of the owners you configured when initializing the OssStats object
const githubOwners = await ossStats.getAllGithubOwners(ctx);
// A single owner
const githubOwner = await ossStats.getGithubOwner(ctx, "get-convex");
// All of the npm orgs you configured when initializing the OssStats object
const npmOrgs = await ossStats.getAllNpmOrgs(ctx);
// A single npm org
const npmOrg = await ossStats.getNpmOrg(ctx, "convex-dev");
// A single github repo
const githubRepo = await ossStats.getGithubRepo(ctx, "get-convex/convex-js");
// Combined stats for a list of github repos
const githubRepos = await ossStats.getGithubRepos(ctx, [
"get-convex/convex-js",
"get-convex/convex-helpers",
]);
// A single npm package
const npmPackage = await ossStats.getNpmPackage(ctx, "@convex-dev/convex-js");
// Combined stats for a list of npm packages
const npmPackages = await ossStats.getNpmPackages(ctx, [
"@convex-dev/convex-js",
"@convex-dev/convex-helpers",
]);
选项和配置
手动同步数据
如果您不想使用 Webhook, 您可以使用 cron 任务来同步数据 :
// In convex/crons.ts
import { cronJobs } from "convex/server";
import { internal } from "./_generated/api";
export const syncStars = internalAction(async (ctx) => {
await ossStats.sync(ctx);
});
const crons = cronJobs();
crons.interval("syncStars", { minutes: 15 }, internal.stats.syncStars);
export default crons;
你可以从CLI或仪表板上调用这个:
npx convex run crons:syncStars
或者通过一个http端点来称呼它:
// In convex/http.ts
import { httpAction } from "./_generated/server";
//...
http.route({
path: "/syncStars",
method: "POST",
handler: httpAction(async (ctx, request) => {
if (request.headers.get("x-api-key") !== process.env.API_KEY) {
return new Response("Unauthorized", { status: 401 });
}
await ossStats.sync(ctx);
return new Response("ok", { status: 200 });
}),
});
API_KEY 可在仪表板上设置或通过 npx convex env set API_KEY=...
覆盖默认值 /events/github 路径
ossStats.registerRoutes(http, {
path: "/my/github/webhook",
});