diff --git a/src/components/Support/Support.jsx b/src/components/Support/Support.jsx index ffa8a8e3ada1..efdaff9163ae 100644 --- a/src/components/Support/Support.jsx +++ b/src/components/Support/Support.jsx @@ -144,7 +144,7 @@ export default class Support extends React.Component { { supporters.map((supporter, index) => ( - { - // Basic validation - const content = JSON.parse(body); +const graphqlEndpoint = 'https://api.opencollective.com/graphql/v2'; - if (!Array.isArray(content)) { +const graphqlQuery = `query account($limit: Int, $offset: Int) { + account(slug: "webpack") { + orders(limit: $limit, offset: $offset) { + limit + offset + totalCount + nodes { + fromAccount { + name + slug + website + imageUrl + } + totalDonations { + value + } + createdAt + } + } + } +}`; + +const graphqlPageSize = 1000; + +const nodeToSupporter = node => ({ + name: node.fromAccount.name, + slug: node.fromAccount.slug, + website: node.fromAccount.website, + avatar: node.fromAccount.imageUrl, + firstDonation: node.createdAt, + totalDonations: node.totalDonations.value * 100 +}); + +const getAllOrders = async () => { + const requestOptions = { + method: 'POST', + uri: graphqlEndpoint, + body: { query: graphqlQuery, variables: { limit: graphqlPageSize, offset: 0 } }, + json: true + }; + + let allOrders = []; + + // Handling pagination if necessary (2 pages for ~1400 results in May 2019) + // eslint-disable-next-line + while (true) { + const result = await request(requestOptions); + const orders = result.data.account.orders.nodes; + allOrders = [...allOrders, ...orders]; + requestOptions.body.variables.offset += graphqlPageSize; + if (orders.length < graphqlPageSize) { + return allOrders; + } + } +}; + +getAllOrders() + .then(orders => { + let supporters = orders.map(nodeToSupporter).sort((a, b) => b.totalDonations - a.totalDonations); + + // Deduplicating supporters with multiple orders + supporters = uniqBy(supporters, 'slug'); + + if (!Array.isArray(supporters)) { throw new Error('Supporters data is not an array.'); } - for (const item of content) { + for (const item of supporters) { for (const key of REQUIRED_KEYS) { - if (!item || typeof item !== 'object') throw new Error(`Supporters: ${JSON.stringify(item)} is not an object.`); - if (!(key in item)) throw new Error(`Supporters: ${JSON.stringify(item)} doesn't include ${key}.`); + if (!item || typeof item !== 'object') { + throw new Error(`Supporters: ${JSON.stringify(item)} is not an object.`); + } + if (!(key in item)) { + throw new Error(`Supporters: ${JSON.stringify(item)} doesn't include ${key}.`); + } } } // Write the file - return asyncWriteFile(`./src/components/Support/${filename}`, body).then(() => console.log('Fetched 1 file: _supporters.json')); + return asyncWriteFile(absoluteFilename, JSON.stringify(supporters, null, 2)).then(() => + console.log(`Fetched 1 file: ${filename}`) + ); }) .catch(error => { console.error('utilities/fetch-supporters:', error);