diff --git a/packages/website/data/sponsors.json b/packages/website/data/sponsors.json index 5eabd5e5dcec..42de64539f59 100644 --- a/packages/website/data/sponsors.json +++ b/packages/website/data/sponsors.json @@ -1,173 +1,326 @@ [ { - "description": null, - "id": "7mywxoz3-409rl6kk-v9b6venb-dj7gk85a", - "image": "https://images.opencollective.com/deal-empire/b3f7583/logo.png", - "name": "Deal Empire", - "slug": "deal-empire", - "tier": "supporter", - "website": "https://dealempire.com/" + "id": "Nx (by Nrwl)", + "image": "https://images.opencollective.com/nx/0efbe42/logo.png", + "name": "Nx (by Nrwl)", + "tier": "sponsor", + "totalDonations": 375000, + "website": "https://nx.dev" }, { - "description": "LIVE PAIN FREE", - "id": "x8k03rey-d5agmq5m-z9b6lbwo-z7j4nxv9", - "image": "https://images.opencollective.com/my-sports-injury-ltd/518c583/logo.png", - "name": "MySportsInjury", - "slug": "my-sports-injury-ltd", + "id": "ESLint", + "image": "https://images.opencollective.com/eslint/96b09dc/logo.png", + "name": "ESLint", + "tier": "sponsor", + "totalDonations": 110000, + "website": "https://eslint.org/" + }, + { + "id": "Airbnb", + "image": "https://images.opencollective.com/airbnb/d327d66/logo.png", + "name": "Airbnb", + "tier": "sponsor", + "totalDonations": 105800, + "website": "https://www.airbnb.com/" + }, + { + "id": "Coinbase", + "image": "https://images.opencollective.com/coinbase/a202856/logo.png", + "name": "Coinbase", + "tier": "sponsor", + "totalDonations": 100000, + "website": "https://blog.coinbase.com/engineering-and-security/home" + }, + { + "id": "EY Doberman", + "image": "https://images.opencollective.com/ey-doberman/b269462/logo.png", + "name": "EY Doberman", + "tier": "sponsor", + "totalDonations": 80400, + "website": "https://doberman.co" + }, + { + "id": "n8n.io - n8n GmbH", + "image": "https://images.opencollective.com/n8n/dca2f0c/logo.png", + "name": "n8n.io - n8n GmbH", + "tier": "sponsor", + "totalDonations": 80000, + "website": "https://n8n.io" + }, + { + "id": "Future Processing", + "image": "https://images.opencollective.com/future-processing/1410d26/logo.png", + "name": "Future Processing", "tier": "supporter", - "website": "https://www.mysportsinjury.co.uk" + "totalDonations": 54000, + "website": "https://www.future-processing.com/" }, { - "description": "java learning", - "id": "jrkx5lmn-v904qjw5-xbbp8bwa-7zdygoe3", - "image": "https://images.opencollective.com/java-exp/14e869f/logo.png", - "name": "java", - "slug": "java-exp", + "id": "Sentry", + "image": "https://images.opencollective.com/sentry/9620d33/logo.png", + "name": "Sentry", "tier": "supporter", - "website": "https://explainjava.com/" + "totalDonations": 50000, + "website": "https://sentry.io/welcome/" }, { - "description": null, - "id": "03k0exgz-nm8yj64l-rn5p5wao-9r7b4dlv", - "image": "https://images.opencollective.com/codecademy/d56a48d/logo.png", - "name": "Codecademy", - "slug": "codecademy", - "tier": "sponsor", - "website": "https://codecademy.com" + "id": "Whitebox", + "image": "https://images.opencollective.com/whiteboxinc/ef0d11d/logo.png", + "name": "Whitebox", + "tier": "supporter", + "totalDonations": 40000, + "website": "https://whitebox.com" }, { - "description": null, - "id": "v349mrwg-z75lpy7g-angpa08d-jeybknox", + "id": "GitBook", "image": "https://images.opencollective.com/gitbook/d35a8e7/logo.png", "name": "GitBook", - "slug": "gitbook", "tier": "sponsor", + "totalDonations": 40000, "website": "https://www.gitbook.com" }, { - "description": "Accelerate your development work on iOS, Android and beyond with the power of ARM-based virtual devices.", - "id": "gm9bnk80-437xqryv-89jpvzeo-ljdayw5r", - "image": "https://images.opencollective.com/corellium/aa8c228/logo.png", - "name": "Corellium", - "slug": "corellium", - "tier": "supporter", - "website": "https://www.corellium.com" + "id": "Codecademy", + "image": "https://images.opencollective.com/codecademy/d56a48d/logo.png", + "name": "Codecademy", + "tier": "sponsor", + "totalDonations": 30000, + "website": "https://codecademy.com" }, { - "description": null, - "id": "ov349mrw-gz75lpyx-elzqa08d-jeybknox", - "image": "https://images.opencollective.com/gaetan-bloch/c5cfcb2/avatar.png", - "name": "Gaëtan Bloch", - "slug": "gaetan-bloch", + "id": "Monito", + "image": "https://images.opencollective.com/monito/50fc878/logo.png", + "name": "Monito", "tier": "supporter", - "website": null + "totalDonations": 27500, + "website": "https://www.monito.com" }, { - "description": "The pluggable linting utility for JavaScript and JSX", - "id": "k3z8arxv-eymko60y-73wqgl5n-bj9w704d", - "image": "https://images.opencollective.com/eslint/96b09dc/logo.png", - "name": "ESLint", - "slug": "eslint", - "tier": "sponsor", - "website": "https://eslint.org/" + "id": "revo.js", + "image": "https://images.opencollective.com/revojsro/82623a7/logo.png", + "name": "revo.js", + "tier": "supporter", + "totalDonations": 23000, + "website": "https://revojs.ro" }, { - "description": "Our mission is to create an open financial system for the world. ", - "id": "7ywz9j4a-vgod8pgn-996mr35n-xklb0e7a", - "image": "https://images.opencollective.com/coinbase/a202856/logo.png", - "name": "Coinbase", - "slug": "coinbase", - "tier": "sponsor", - "website": "https://blog.coinbase.com/engineering-and-security/home" + "id": "Ian MacLeod", + "image": "https://images.opencollective.com/nevir/35c52ef/avatar.png", + "name": "Ian MacLeod", + "tier": "supporter", + "totalDonations": 22000, + "website": "https://twitter.com/nevir" }, { - "description": null, - "id": "vjrkx5lm-nv904qjv-k0bq8bwa-7zdygoe3", - "image": "https://images.opencollective.com/jeffrey-rennie/avatar.png", - "name": "Jeffrey Rennie", - "slug": "jeffrey-rennie", + "id": "STORIS", + "image": "https://images.opencollective.com/storis/dfb0e13/logo.png", + "name": "STORIS", "tier": "supporter", - "website": null + "totalDonations": 16500, + "website": "https://www.storis.com/" }, { - "description": "We're Balsa, and we're building tools for builders.", - "id": "nmlo94zn-7x08dpov-y0e6ewga-3vjbrky5", - "image": "https://images.opencollective.com/balsa/77de498/logo.png", - "name": "Balsa", - "slug": "balsa", + "id": "Michael Ranciglio", + "image": "https://images.opencollective.com/michael-ranciglio/avatar.png", + "name": "Michael Ranciglio", "tier": "supporter", - "website": "https://balsa.com" + "totalDonations": 15000 }, { - "description": "Evil Martians is a distributed product development consultancy that works with startups and established businesses, and creates open source-based products and services.", - "id": "53kzxy4v-07wlr6md-7ve6mj9n-o8agdbe5", - "image": "https://images.opencollective.com/evilmartians/707ab4d/logo.png", - "name": "Evil Martians", - "slug": "evilmartians", + "id": "Joe Alden", + "image": "https://images.opencollective.com/joealden/44a6738/avatar.png", + "name": "Joe Alden", + "tier": "contributor", + "totalDonations": 14000, + "website": "https://joealden.com" + }, + { + "id": "David Johnston", + "image": "https://images.opencollective.com/blacksheepcode/976d69a/avatar.png", + "name": "David Johnston", "tier": "supporter", - "website": "https://evilmartians.com/" + "totalDonations": 11500, + "website": "https://blacksheepcode.com" }, { - "description": null, - "id": "nmlo94zn-7x08dpo5-nyoqewga-3vjbrky5", + "id": "Gianfranco Palumbo", + "image": "https://images.opencollective.com/gianpaj/5d62d25/avatar.png", + "name": "Gianfranco Palumbo", + "tier": "contributor", + "totalDonations": 10000, + "website": "http://gian.xyz" + }, + { + "id": "The Guardian", + "image": "https://images.opencollective.com/gdndevelopers/0b72bf0/logo.png", + "name": "The Guardian", + "tier": "contributor", + "totalDonations": 10000, + "website": "https://www.theguardian.com/" + }, + { + "id": "Tripwire, Inc.", "image": "https://images.opencollective.com/tripwire/7599e30/logo.png", "name": "Tripwire, Inc.", - "slug": "tripwire", "tier": "supporter", + "totalDonations": 7000, "website": "https://tripwire.com" }, { - "description": "Nx is an extensible development toolkit that helps teams of all sizes easily create and scale their Web applications using modern tools.", - "id": "bvrgbk35-7l4x96e0-nlaqomew-a0jdyzn8", - "image": "https://images.opencollective.com/nx/0efbe42/logo.png", - "name": "Nx (by Nrwl)", - "slug": "nx", - "tier": "sponsor", - "website": "https://nx.dev" + "id": "Evil Martians", + "image": "https://images.opencollective.com/evilmartians/707ab4d/logo.png", + "name": "Evil Martians", + "tier": "supporter", + "totalDonations": 6500, + "website": "https://evilmartians.com/" }, { - "description": "Free and open Workflow Automation tool which can be self-hosted and easily extended", - "id": "7ywz9j4a-vgod8pgv-d8ypmr35-nxklb0e7", - "image": "https://images.opencollective.com/n8n/dca2f0c/logo.png", - "name": "n8n.io - n8n GmbH", - "slug": "n8n", + "id": "Balsa", + "image": "https://images.opencollective.com/balsa/77de498/logo.png", + "name": "Balsa", "tier": "supporter", - "website": "https://n8n.io" + "totalDonations": 6500, + "website": "https://balsa.com" }, { - "description": null, - "id": "ov349mrw-gz75lpyz-0l86a08d-jeybknox", - "image": "https://images.opencollective.com/florian-studio/a713d94/logo.png", - "name": "Florian Studio", - "slug": "florian-studio", + "id": "Jeffrey Rennie", + "image": "https://images.opencollective.com/jeffrey-rennie/avatar.png", + "name": "Jeffrey Rennie", "tier": "supporter", - "website": "https://www.ceodata.com" + "totalDonations": 6000 }, { - "description": "Full Stack JavaScript Developer", - "id": "03k0exgz-nm8yj64r-wjjp5wao-9r7b4dlv", - "image": "https://images.opencollective.com/blacksheepcode/976d69a/avatar.png", - "name": "David Johnston", - "slug": "blacksheepcode", - "tier": "supporter", - "website": "https://blacksheepcode.com" + "id": "Pete Gonzalez", + "image": "https://images.opencollective.com/octogonz/513f01a/avatar.png", + "name": "Pete Gonzalez", + "tier": "contributor", + "totalDonations": 5000, + "website": "https://github.com/octogonz" }, { - "description": "Book unique homes and experience a city like a local.", - "id": "88rzownx-l9e50pxw-rwqymvbd-gk7j43a9", - "image": "https://images.opencollective.com/airbnb/d327d66/logo.png", - "name": "Airbnb", - "slug": "airbnb", + "id": "Niklas Fiekas", + "image": "https://images.opencollective.com/niklas-fiekas/ffec4a8/avatar.png", + "name": "Niklas Fiekas", + "tier": "contributor", + "totalDonations": 5000, + "website": "https://backscattering.de" + }, + { + "id": "Indeed", + "image": "https://images.opencollective.com/indeed/4b8725e/logo.png", + "name": "Indeed", + "tier": "contributor", + "totalDonations": 5000, + "website": "https://Indeed.com" + }, + { + "id": "Andrey Sitnik", + "image": "https://images.opencollective.com/andrey-sitnik/11aeb28/avatar.png", + "name": "Andrey Sitnik", + "tier": "contributor", + "totalDonations": 4500, + "website": "https://sitnik.ru" + }, + { + "id": "Corellium", + "image": "https://images.opencollective.com/corellium/aa8c228/logo.png", + "name": "Corellium", "tier": "supporter", - "website": "https://www.airbnb.com/" + "totalDonations": 3000, + "website": "https://www.corellium.com" }, { - "description": "I write code sometimes and support stuff I like on here.", - "id": "53kzxy4v-07wlr6mv-wob6mj9n-o8agdbe5", - "image": "https://images.opencollective.com/michael-ranciglio/avatar.png", - "name": "Michael Ranciglio", - "slug": "michael-ranciglio", + "id": "Kamino Ryo", + "image": "https://images.opencollective.com/kaminoryo/d1d9ff5/avatar.png", + "name": "Kamino Ryo", + "tier": "contributor", + "totalDonations": 3000 + }, + { + "id": "Kevin Smith", + "image": "https://images.opencollective.com/kevin-smith1/a343791/avatar.png", + "name": "Kevin Smith", + "tier": "contributor", + "totalDonations": 2500 + }, + { + "id": "Dani Gellis", + "image": "https://images.opencollective.com/dani-gellis1/avatar.png", + "name": "Dani Gellis", + "tier": "contributor", + "totalDonations": 2500 + }, + { + "id": "38elements", + "image": "https://images.opencollective.com/38elements/5dfbefe/avatar.png", + "name": "38elements", + "tier": "contributor", + "totalDonations": 2200, + "website": "https://japanese-document.github.io/react-redux/connect.html" + }, + { + "id": "Gaëtan Bloch", + "image": "https://images.opencollective.com/gaetan-bloch/c5cfcb2/avatar.png", + "name": "Gaëtan Bloch", + "tier": "contributor", + "totalDonations": 2100 + }, + { + "id": "Softwear, BV", + "image": "https://images.opencollective.com/softwear_dev/dc2d34e/logo.png", + "name": "Softwear, BV", + "tier": "contributor", + "totalDonations": 2000, + "website": "https://www.softwearconnect.com" + }, + { + "id": "Sean Lindsay", + "image": "https://images.opencollective.com/sean-lindsay/avatar.png", + "name": "Sean Lindsay", + "tier": "contributor", + "totalDonations": 2000 + }, + { + "id": "Jane Doe", + "image": "https://images.opencollective.com/jane-doe/avatar.png", + "name": "Jane Doe", + "tier": "contributor", + "totalDonations": 2000 + }, + { + "id": "Philip Keiter", + "image": "https://images.opencollective.com/philip-keiter/1c359c0/avatar.png", + "name": "Philip Keiter", + "tier": "contributor", + "totalDonations": 1000 + }, + { + "id": "Toru Shimogaisho", + "image": "https://images.opencollective.com/gaishimo/f620536/avatar.png", + "name": "Toru Shimogaisho", + "tier": "contributor", + "totalDonations": 1000 + }, + { + "id": "Kazuhiro Kobayashi", + "image": "https://images.opencollective.com/kazuhiro-kobayashi/a1eeb73/avatar.png", + "name": "Kazuhiro Kobayashi", + "tier": "contributor", + "totalDonations": 1000 + }, + { + "id": "Masafumi Koba", + "image": "https://images.opencollective.com/ybiquitous/6a6913d/avatar.png", + "name": "Masafumi Koba", + "tier": "contributor", + "totalDonations": 1000 + }, + { + "id": "MySportsInjury", + "image": "https://images.opencollective.com/my-sports-injury-ltd/518c583/logo.png", + "name": "MySportsInjury", "tier": "supporter", - "website": null + "totalDonations": 1000, + "website": "https://www.mysportsinjury.co.uk" } ] diff --git a/packages/website/src/components/FinancialContributors.tsx b/packages/website/src/components/FinancialContributors.tsx deleted file mode 100644 index 400442239d84..000000000000 --- a/packages/website/src/components/FinancialContributors.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import Link from '@docusaurus/Link'; -import sponsors from '@site/data/sponsors.json'; -import clsx from 'clsx'; -import React from 'react'; - -import styles from './FinancialContributors.module.css'; - -function Sponsors(props: { - description: string; - showName?: boolean; - tier: string; - title: string; -}): JSX.Element { - const tierSponsors = sponsors.filter(sponsor => sponsor.tier === props.tier); - return ( -
-

{props.title}

-

{props.description}

- -
- ); -} - -export function FinancialContributors(): JSX.Element { - return ( - <> -

- The TypeScript ESLint project would not be possible without the generous - support of our financial contributors. -

-
- - -
- - Become a financial contributor - - - ); -} diff --git a/packages/website/src/components/FinancialContributors/Sponsor.tsx b/packages/website/src/components/FinancialContributors/Sponsor.tsx new file mode 100644 index 000000000000..f43b0d3d81ee --- /dev/null +++ b/packages/website/src/components/FinancialContributors/Sponsor.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +import { SponsorData, SponsorIncludeOptions } from './types'; + +interface SponsorProps { + className?: string; + include?: SponsorIncludeOptions; + sponsor: SponsorData; +} + +export function Sponsor({ + className, + include = {}, + sponsor, +}: SponsorProps): JSX.Element { + let children = {`${sponsor.name}; + + if (include.name) { + children = ( + <> + {children} + {sponsor.name.split(' - ')[0]} + + ); + } + + if (include.link) { + children = ( + + {children} + + ); + } + + return children; +} diff --git a/packages/website/src/components/FinancialContributors/Sponsors/index.tsx b/packages/website/src/components/FinancialContributors/Sponsors/index.tsx new file mode 100644 index 000000000000..2e47b077d5b2 --- /dev/null +++ b/packages/website/src/components/FinancialContributors/Sponsors/index.tsx @@ -0,0 +1,40 @@ +import sponsors from '@site/data/sponsors.json'; +import clsx from 'clsx'; +import React from 'react'; + +import styles from './styles.module.css'; +import { Sponsor } from '../Sponsor'; +import { SponsorIncludeOptions } from '../types'; + +interface SponsorsProps { + className: string; + description: string; + include?: SponsorIncludeOptions; + expanded?: boolean; + tier?: string; + title: string; +} + +export function Sponsors({ + className, + description, + include, + tier, + title, +}: SponsorsProps): JSX.Element { + return ( +
+

{title}

+

{description}

+ +
+ ); +} diff --git a/packages/website/src/components/FinancialContributors.module.css b/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css similarity index 53% rename from packages/website/src/components/FinancialContributors.module.css rename to packages/website/src/components/FinancialContributors/Sponsors/styles.module.css index 96749add5b13..0373225a2b50 100644 --- a/packages/website/src/components/FinancialContributors.module.css +++ b/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css @@ -1,5 +1,6 @@ .tierArea { - margin: 32px 0; + margin: 32px auto; + width: 100%; } .sponsorsTier { @@ -15,6 +16,11 @@ .sponsorsTier li { list-style: none; margin: 5px; + max-width: 120px; +} + +.sponsorsTier img { + margin: auto; } .sponsorsTier a, @@ -28,35 +34,32 @@ } .tier-sponsor img { - max-height: 110px; - width: 110px; + display: inline-block; + max-height: 120px; + width: 120px; } .tier-supporter img { - max-height: 60px; - width: 60px; + max-height: 45px; + width: 45px; } -.sponsorLink { - display: inline-flex; - flex-direction: column; - gap: 8px; +.tier-contributor img { + max-height: 30px; + width: 30px; } -.become { - margin: 8px 0 24px; - font-size: 1rem; +@media screen and (min-width: 700px) { + .tierArea { + min-width: 500px; + width: 50vw; + } } @media screen and (min-width: 1150px) { - .sponsorsContainer { - display: flex; - gap: 32px; - margin: auto; - max-width: 75%; - } - .tierArea { - width: 50%; + margin: 16px 0; + width: auto; + padding: 0 60px; } } diff --git a/packages/website/src/components/FinancialContributors/index.tsx b/packages/website/src/components/FinancialContributors/index.tsx new file mode 100644 index 000000000000..9665632df417 --- /dev/null +++ b/packages/website/src/components/FinancialContributors/index.tsx @@ -0,0 +1,46 @@ +import Link from '@docusaurus/Link'; +import clsx from 'clsx'; +import React from 'react'; + +import styles from './styles.module.css'; +import { Sponsors } from './Sponsors'; + +export function FinancialContributors(): JSX.Element { + return ( + <> +

+ The TypeScript ESLint project would not be possible without the generous + support of our financial contributors. +

+
+ + + +
+ + Become a financial contributor + + + ); +} diff --git a/packages/website/src/components/FinancialContributors/styles.module.css b/packages/website/src/components/FinancialContributors/styles.module.css new file mode 100644 index 000000000000..b4de958b9021 --- /dev/null +++ b/packages/website/src/components/FinancialContributors/styles.module.css @@ -0,0 +1,37 @@ +.sponsorLink { + display: inline-flex; + flex-direction: column; + gap: 8px; +} + +.become { + margin: 8px 0 24px; + font-size: 1rem; +} + +@media screen and (min-width: 1150px) { + .sponsorsContainer { + display: grid; + grid-template-columns: 55% 45%; + margin: auto; + max-width: 100%; + } + + .tierArea { + margin: 16px 0; + width: auto; + padding: 0 60px; + } + + .tierSponsorArea { + grid-area: 1 / 1 / 3 / 2; + } + + .tierSupporterArea { + grid-area: 1 / 2 / 2 / 3; + } + + .tierOtherArea { + grid-area: 2 / 2 / 3 / 3; + } +} diff --git a/packages/website/src/components/FinancialContributors/types.ts b/packages/website/src/components/FinancialContributors/types.ts new file mode 100644 index 000000000000..fb20cb4623a0 --- /dev/null +++ b/packages/website/src/components/FinancialContributors/types.ts @@ -0,0 +1,14 @@ +export interface SponsorData { + description?: string; + id: string; + image: string; + name: string; + tier?: string; + totalDonations: number; + website?: string; +} + +export interface SponsorIncludeOptions { + link?: boolean; + name?: boolean; +} diff --git a/tools/generate-sponsors.ts b/tools/generate-sponsors.ts index 79f472879a32..140445de11ee 100644 --- a/tools/generate-sponsors.ts +++ b/tools/generate-sponsors.ts @@ -4,90 +4,198 @@ import * as path from 'path'; const graphqlEndpoint = 'https://api.opencollective.com/graphql/v2'; -const graphqlQuery = `{ - account(slug: "typescript-eslint") { - orders(status: ACTIVE, limit: 1000) { - totalCount - nodes { - tier { - slug +const queries = { + account: `{ + account(slug: "typescript-eslint") { + orders(status: ACTIVE, limit: 1000) { + totalCount + nodes { + tier { + slug + } + fromAccount { + id + imageUrl + name + website + } } - fromAccount { - id - name - slug - website - imageUrl - description + } + } + }`, + collective: `{ + collective(slug: "typescript-eslint") { + members(limit: 1000, role: BACKER) { + nodes { + account { + id + imageUrl + name + website + } + tier { + amount { + valueInCents + } + orders(limit: 100) { + nodes { + amount { + valueInCents + } + } + } + } + totalDonations { + valueInCents + } + updatedAt } } } - } -}`; + }`, +}; -const excludedIds = new Set([ - '53kzxy4v-07wlr6mr-o9epmj9n-o8agdbe5', // Josh Goldberg -]); - -interface SponsorsData { - data: { - account: { - orders: { - nodes: SponsorNode[]; - }; - }; +interface AccountData { + orders: { + nodes: OrderNode[]; }; } -interface SponsorNode { - fromAccount: { - description: string; - id: string; - imageUrl: string; - name: string; - slug: string; - twitterHandle: string; - website: string; +interface OrderNode { + fromAccount: MemberAccount; + tier?: Tier; +} + +interface Tier { + slug: string; +} + +interface CollectiveData { + members: { + nodes: MemberNode[]; }; - tier?: { - slug: string; +} + +interface MemberNode { + account: MemberAccount; + totalDonations: { + valueInCents: number; }; } -async function main(): Promise { +interface MemberAccount { + id: string; + imageUrl: string; + name: string; + twitterHandle: string; + website: string; +} + +interface MemberAccountAndTier extends MemberAccount { + tier?: Tier; +} + +const excludedNames = new Set([ + 'Guest', // Apparent anonymous donor equivalent without an avatar + 'Josh Goldberg', // Team member 💖 + + // These names *seem* to be spam websites, but we're not sure. + // If your name is mistakenly on this list, we're sorry; please let us know! + 'Deal Empire', + 'Florian Studio', + 'java', + 'Loyalty Leo', + 'Penalty.com', +]); + +async function requestGraphql(key: keyof typeof queries): Promise { const response = await fetch(graphqlEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ query: graphqlQuery }), + body: JSON.stringify({ query: queries[key] }), }); - const data = (await response.json()) as SponsorsData; - const uniqueIds = new Set(excludedIds); - const allSponsorsConfig = data.data.account.orders.nodes - .filter(node => !!node.tier) - .map(node => ({ - description: node.fromAccount.description, - id: node.fromAccount.id, - image: node.fromAccount.imageUrl, - name: node.fromAccount.name, - slug: node.fromAccount.slug, - tier: node.tier.slug, - twitterHandle: node.fromAccount.twitterHandle, - website: node.fromAccount.website, - })) - .filter(({ id }) => { - if (uniqueIds.has(id)) { + + const { data } = (await response.json()) as { + data: Record; + }; + return data[key] as Data; +} + +async function main(): Promise { + const [account, collective] = await Promise.all([ + requestGraphql('account'), + requestGraphql('collective'), + ]); + + const accountsById = account.orders.nodes.reduce< + Record + >((accumulator, account) => { + const name = account.fromAccount.name || account.fromAccount.id; + accumulator[name] = { + ...accumulator[name], + ...account.fromAccount, + tier: account.tier, + }; + return accumulator; + }, {}); + + const totalDonationsById = collective.members.nodes.reduce< + Record + >((accumulator, member) => { + const name = member.account.name || member.account.id; + accumulator[name] ||= 0; + accumulator[name] += member.totalDonations.valueInCents; + return accumulator; + }, {}); + + const uniqueNames = new Set(excludedNames); + const allSponsorsConfig = collective.members.nodes + .map(member => { + const name = member.account.name || member.account.id; + const fromAccount: MemberAccountAndTier = { + ...member.account, + ...accountsById[name], + }; + const totalDonations = totalDonationsById[name]; + const slug = fromAccount.tier?.slug ?? 'contributor'; + + return { + id: name, + image: fromAccount.imageUrl, + name: fromAccount.name, + tier: + slug === 'sponsor' || totalDonations >= 750_00 + ? 'sponsor' + : slug === 'supporter-plus' || totalDonations >= 150_00 + ? 'supporter' + : slug, + totalDonations, + twitterHandle: fromAccount.twitterHandle, + website: fromAccount.website, + }; + }) + .filter(({ id, totalDonations }) => { + if (uniqueNames.has(id) || totalDonations < 10_00) { return false; } - uniqueIds.add(id); + uniqueNames.add(id); return true; - }); + }) + .sort((a, b) => b.totalDonations - a.totalDonations); const rcPath = path.resolve( __dirname, '../packages/website/data/sponsors.json', ); - fs.writeFileSync(rcPath, JSON.stringify(allSponsorsConfig, null, 2)); + fs.writeFileSync( + rcPath, + JSON.stringify( + allSponsorsConfig, + (_, value: unknown) => value ?? undefined, + 2, + ), + ); } main().catch(error => { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy