Skip to content

Commit

Permalink
[DO NOT MERGE] fetch sponsors at build time; closes #4271
Browse files Browse the repository at this point in the history
  • Loading branch information
boneskull committed May 7, 2020
1 parent c0137eb commit 8e0ecec
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 59 deletions.
117 changes: 117 additions & 0 deletions docs/_data/supporters.js
@@ -0,0 +1,117 @@
#!/usr/bin/env node
'use strict';

const debug = require('debug')('mocha:docs:data:supporters');
const needle = require('needle');

const REQUIRED_KEYS = ['totalDonations', 'slug', 'name'];

const API_ENDPOINT = 'https://api.opencollective.com/graphql/v2';

const query = `query account($limit: Int, $offset: Int, $slug: String) {
account(slug: $slug) {
orders(limit: $limit, offset: $offset) {
limit
offset
totalCount
nodes {
fromAccount {
name
slug
website
imageUrl(height:32)
}
totalDonations {
value
}
tier {
slug
}
createdAt
}
}
}
}`;

const graphqlPageSize = 1000;

const nodeToSupporter = node => ({
name: node.fromAccount.name,
slug: node.fromAccount.slug,
website: node.fromAccount.website,
avatar: node.fromAccount.imageUrl,
tier: node.tier ? node.tier.slug : 'sponsors',
firstDonation: node.createdAt,
totalDonations: node.totalDonations.value * 100
});

const getAllOrders = async (slug = 'mochajs') => {
let allOrders = [];
const variables = {limit: graphqlPageSize, offset: 0, slug};

// Handling pagination if necessary (2 pages for ~1400 results in May 2019)
// eslint-disable-next-line
while (true) {
const result = await needle(
'post',
API_ENDPOINT,
{query, variables},
{json: true}
);
const orders = result.body.data.account.orders.nodes;
allOrders = [...allOrders, ...orders];
variables.offset += graphqlPageSize;
if (orders.length < graphqlPageSize) {
debug('retrieved %d orders', allOrders.length);
return allOrders;
} else {
debug(
'loading page %d of orders...',
Math.floor(variables.offset / graphqlPageSize)
);
}
}
};

module.exports = async () => {
const orders = await getAllOrders();
let supporters = orders
.map(nodeToSupporter)
.sort((a, b) => b.totalDonations - a.totalDonations);

// Deduplicating supporters with multiple orders
const seenSupporters = new Set();
supporters = supporters.reduce((supporters, supporter) => {
if (!seenSupporters.has(supporter.slug)) {
seenSupporters.add(supporter.slug);
supporters.push(supporter);
}
return supporters;
}, []);

if (!Array.isArray(supporters)) {
throw new Error('Supporters data is not an array.');
}

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}.`
);
}
}
}

// sort into buckets by tier
const backers = supporters.filter(supporter => supporter.tier === 'backers');
const sponsors = supporters.filter(supporter => supporter.tier === 'sponsors');

debug('found %d backers and %d sponsors', backers.length, sponsors.length);
return {backers, sponsors};
};
11 changes: 7 additions & 4 deletions docs/_includes/backers.md
@@ -1,7 +1,10 @@
## Backers

Find Mocha helpful? Become a [backer](https://opencollective.com/mochajs#support) and support Mocha with a monthly donation.
Find Mocha helpful? Become a [backer](https://opencollective.com/mochajs#support) and support Mocha with a monthly donation.

<!-- markdownlint-disable MD034 -->
{% for i in (0..29) %}[![](https://opencollective.com/mochajs/backer/{{ i }}/avatar.jpg)](https://opencollective.com/mochajs/backer/{{ i }}/website){: target="_blank" rel="noopener"}{% endfor %}
{: .image-list id="_backers" }
{% for supporter in supporters.backers %}
<a href="{{ supporter.website }}" target="_blank" rel="noopener" title="{{ supporter.name }}">
<img src="{{ supporter.avatar }}" alt="{{ supporter.name }}" />
</a>
{% endfor %}
{: .image-list id="\_backers" }
2 changes: 2 additions & 0 deletions docs/_includes/default.html
Expand Up @@ -170,5 +170,7 @@ <h1>
</dd>
</dl>
</footer>

<script src="js/avatars.js"></script>
</body>
</html>
12 changes: 6 additions & 6 deletions docs/_includes/sponsors.md
Expand Up @@ -2,9 +2,9 @@

Use Mocha at Work? Ask your manager or marketing team if they'd help [support](https://opencollective.com/mochajs#support) our project. Your company's logo will also be displayed on [npmjs.com](http://npmjs.com/package/mocha) and our [GitHub repository](https://github.com/mochajs/mocha#sponsors).

<!-- markdownlint-disable MD034 -->

{% for i in (0..15) %}[![](https://opencollective.com/mochajs/sponsor/{{ i }}/avatar.png)](https://opencollective.com/mochajs/sponsor/{{ i }}/website){: target="\_blank"} {% endfor %}
{: .image-list .faded-images}

<script src="js/avatars.js"></script>
{% for supporter in supporters.sponsors %}
<a href="{{ supporter.website }}" target="_blank" rel="noopener" title="{{ supporter.name }}">
<img src="{{ supporter.avatar }}" alt="{{ supporter.name }}" />
</a>
{% endfor %}
{: .image-list id="\_sponsors" }
2 changes: 1 addition & 1 deletion docs/index.md
Expand Up @@ -822,7 +822,7 @@ Mocha supports the `err.expected` and `err.actual` properties of any thrown `Ass

<!-- AUTO-GENERATED-CONTENT:START (usage:executable=bin/mocha) -->

```text
```
mocha [spec..]
Expand Down

0 comments on commit 8e0ecec

Please sign in to comment.