From 20fd9b5d27fb4443f7b3ce451ebd4d3b3877c342 Mon Sep 17 00:00:00 2001 From: Lars Kappert Date: Mon, 10 Feb 2025 19:57:47 +0100 Subject: [PATCH] Add scripts + chart re. sponsorship activities --- bun.lockb | Bin 452080 -> 453432 bytes packages/docs/astro.config.ts | 3 + packages/docs/package.json | 1 + .../get-monthly-sponsorships-github.ts | 81 +++++++++++++++++ ...get-monthly-sponsorships-opencollective.ts | 85 ++++++++++++++++++ packages/docs/src/assets/venz-chart.svg | 7 ++ .../docs/src/components/SponsorsChart.astro | 5 ++ packages/docs/src/pages/sponsors.astro | 16 +++- 8 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 packages/docs/scripts/get-monthly-sponsorships-github.ts create mode 100644 packages/docs/scripts/get-monthly-sponsorships-opencollective.ts create mode 100644 packages/docs/src/assets/venz-chart.svg create mode 100644 packages/docs/src/components/SponsorsChart.astro diff --git a/bun.lockb b/bun.lockb index c9b91253c05ebeae734ca713f13fcfaa02860061..5a510450c158b8e3b524cc7d1c66e921c85274ba 100755 GIT binary patch delta 19228 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 delta 18528 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

hpBuDvPd_nP^& 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 diff --git a/packages/docs/astro.config.ts b/packages/docs/astro.config.ts index c60e89b8f..7b0f7e197 100644 --- a/packages/docs/astro.config.ts +++ b/packages/docs/astro.config.ts @@ -25,6 +25,9 @@ export default defineConfig({ remarkPlugins: [fixInternalLinks, transformDirectives, remarkDirective], rehypePlugins: [rehypeHeadingIds, rehypeAutolinkHeadings], }, + experimental: { + svg: true, + }, integrations: [ starlight({ title: 'Knip', diff --git a/packages/docs/package.json b/packages/docs/package.json index 809628e1e..25c2ee679 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -30,6 +30,7 @@ "devDependencies": { "@astrojs/check": "0.9.4", "@astrojs/markdown-remark": "^6.1.0", + "@octokit/graphql": "^8.2.0", "@types/mdast": "4.0.4", "@types/unist": "3.0.3", "astro": "5.2.5", diff --git a/packages/docs/scripts/get-monthly-sponsorships-github.ts b/packages/docs/scripts/get-monthly-sponsorships-github.ts new file mode 100644 index 000000000..d20aa3561 --- /dev/null +++ b/packages/docs/scripts/get-monthly-sponsorships-github.ts @@ -0,0 +1,81 @@ +import { graphql } from '@octokit/graphql'; + +const START_DATE = new Date('2023-11-01'); + +const getMonthlyTotals = async (token: string) => { + const { viewer } = await graphql({ + query: ` + query { + viewer { + sponsorsActivities(first: 100, period: ALL) { + nodes { + action + timestamp + sponsorsTier { + monthlyPriceInDollars + isOneTime + } + sponsor { + ... on User { login } + ... on Organization { login } + } + } + } + } + } + `, + headers: { + authorization: `token ${token}`, + }, + }); + + const activities = [...viewer.sponsorsActivities.nodes].sort( + (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() + ); + + const activeRecurring = new Map(); + const monthlyTotals = new Map(); + const now = new Date(); + + for (let d = new Date(START_DATE); d <= now; d.setMonth(d.getMonth() + 1)) { + monthlyTotals.set(d.toISOString().substring(0, 7), 0); + } + + for (const activity of activities) { + const { action, sponsor, sponsorsTier, timestamp } = activity; + const amount = sponsorsTier?.monthlyPriceInDollars || 0; + const monthYear = new Date(timestamp).toISOString().substring(0, 7); + + if (sponsorsTier?.isOneTime) { + if (action === 'NEW_SPONSORSHIP' && monthYear >= START_DATE.toISOString().substring(0, 7)) { + monthlyTotals.set(monthYear, (monthlyTotals.get(monthYear) || 0) + amount); + } + } else { + if (action === 'NEW_SPONSORSHIP') activeRecurring.set(sponsor.login, amount); + else if (action === 'CANCELLED_SPONSORSHIP') activeRecurring.delete(sponsor.login); + const recurringTotal = Array.from(activeRecurring.values()).reduce((sum, a) => sum + a, 0); + for (const [month] of monthlyTotals) if (month >= monthYear) monthlyTotals.set(month, recurringTotal); + } + } + + return monthlyTotals; +}; + +const main = async () => { + const token = process.env.GITHUB_TOKEN; + if (!token) { + throw new Error('GITHUB_TOKEN environment variable is not set'); + } + const monthlyData = await getMonthlyTotals(token); + + let grandTotal = 0; + + for (const [month, amount] of [...monthlyData.entries()].sort()) { + console.log(`${month} ${amount}`); + grandTotal += amount; + } + + console.log(`\nGrand total: ${grandTotal} (${monthlyData.size} months)`); +}; + +main().catch(console.error); diff --git a/packages/docs/scripts/get-monthly-sponsorships-opencollective.ts b/packages/docs/scripts/get-monthly-sponsorships-opencollective.ts new file mode 100644 index 000000000..aafc1bacf --- /dev/null +++ b/packages/docs/scripts/get-monthly-sponsorships-opencollective.ts @@ -0,0 +1,85 @@ +import { graphql } from '@octokit/graphql'; + +const START_DATE = new Date('2023-11-01'); +const RATE_EUR_TO_USD = 1.08; + +const getMonthlyTotals = async (token: string): Promise> => { + const { account, expenses } = await graphql({ + query: ` + query { + account(slug: "knip") { + transactions(type: CREDIT) { + nodes { + id + type + kind + amount { + value + currency + } + createdAt + fromAccount { + name + } + } + } + } + expenses(fromAccount: { slug: "webpro" }) { + nodes { + id + amount + currency + createdAt + type + status + } + } + } + `, + url: 'https://api.opencollective.com/graphql/v2', + headers: { + 'Api-Key': token, + Accept: 'application/json', + }, + }); + + const monthlyTotals = new Map(); + const now = new Date(); + + for (let d = new Date(START_DATE); d <= now; d.setMonth(d.getMonth() + 1)) { + monthlyTotals.set(d.toISOString().substring(0, 7), 0); + } + + for (const transaction of account.transactions.nodes) { + const month = new Date(transaction.createdAt).toISOString().substring(0, 7); + const amount = Math.round(transaction.amount.value); + monthlyTotals.set(month, (monthlyTotals.get(month) || 0) + amount); + } + + for (const expense of expenses.nodes) { + const month = new Date(expense.createdAt).toISOString().substring(0, 7); + const amount = + expense.currency === 'EUR' + ? Math.round((expense.amount / 100) * RATE_EUR_TO_USD) + : Math.round(expense.amount / 100); + monthlyTotals.set(month, (monthlyTotals.get(month) || 0) + amount); + } + + return monthlyTotals; +}; + +const main = async () => { + const token = process.env.OPENCOLLECTIVE_TOKEN; + if (!token) throw new Error('OPENCOLLECTIVE_TOKEN is not set'); + const monthlyData = await getMonthlyTotals(token); + + let grandTotal = 0; + for (const [month, amount] of [...monthlyData.entries()].sort()) { + console.log(`${month} ${amount}`); + grandTotal += amount; + } + + console.log(`\nGrand total: ${grandTotal} (${monthlyData.size} months)`); +}; + +main().catch(console.error); diff --git a/packages/docs/src/assets/venz-chart.svg b/packages/docs/src/assets/venz-chart.svg new file mode 100644 index 000000000..fb18fb86f --- /dev/null +++ b/packages/docs/src/assets/venz-chart.svg @@ -0,0 +1,7 @@ +Chart for Knip Sponsorships02004006008001,0001,2001,4001,6001,8002,0002,2002,4002,6002,8002023-112023-122024-012024-022024-032024-042024-052024-062024-072024-082024-092024-102024-112024-122025-012025-02monthamount ($)GitHub SponsorsOpenCollective974239489189204304120420422927294102222223422220000075010103525254545145145145 \ No newline at end of file diff --git a/packages/docs/src/components/SponsorsChart.astro b/packages/docs/src/components/SponsorsChart.astro new file mode 100644 index 000000000..44fe507d6 --- /dev/null +++ b/packages/docs/src/components/SponsorsChart.astro @@ -0,0 +1,5 @@ +--- +import Chart from '../assets/venz-chart.svg'; +--- + + diff --git a/packages/docs/src/pages/sponsors.astro b/packages/docs/src/pages/sponsors.astro index c6e74267e..9a61dd94c 100644 --- a/packages/docs/src/pages/sponsors.astro +++ b/packages/docs/src/pages/sponsors.astro @@ -3,6 +3,7 @@ import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro'; import Posts from '../components/Posts.astro'; import Projects from '../components/Projects.astro'; import SponsorsComponent from '../components/Sponsors.astro'; +import SponsorsChart from '../components/SponsorsChart.astro'; import SponsorsPast from '../components/SponsorsPast.astro'; --- @@ -38,13 +39,12 @@ import SponsorsPast from '../components/SponsorsPast.astro';

You or your company logo will be added to this page if you decide to support the project on an ongoing basis. Eternal gratitude to the - companies and people that are already supporters: + companies and people supporting the project!

@@ -57,6 +57,18 @@ import SponsorsPast from '../components/SponsorsPast.astro'; +

🧡 Monthly Overview

+ +

+ Overview of gross debit GitHub and OpenCollective sponsorships and invoices, + since it was openly asked for. The monthly aggregated average over the + charted period is $533, actual development started one year before that. + GitHub Sponsors is for my GitHub account, which has more repositories, but + in practice targets mostly Knip. +

+ + +

🧡 Past Sponsors