@@ -9,9 +9,19 @@ const asyncWriteFile = promisify(fs.writeFile);
9
9
10
10
const REQUIRED_KEYS = [ 'totalDonations' , 'slug' , 'name' ] ;
11
11
const filename = '_supporters.json' ;
12
- const absoluteFilename = path . resolve ( __dirname , '..' , 'components' , 'Support' , filename ) ;
12
+ const absoluteFilename = path . resolve (
13
+ __dirname ,
14
+ '..' ,
15
+ 'components' ,
16
+ 'Support' ,
17
+ filename
18
+ ) ;
13
19
14
- const graphqlEndpoint = 'https://api.opencollective.com/graphql/v2' ;
20
+ const graphqlEndpoint =
21
+ 'https://api.opencollective.com/graphql/v2' ;
22
+
23
+ // https://github.com/opencollective/opencollective-api/blob/master/server/graphql/v2/query/TransactionsQuery.ts#L81
24
+ const graphqlPageSize = 1000 ;
15
25
16
26
const membersGraphqlQuery = `query account($limit: Int, $offset: Int) {
17
27
account(slug: "webpack") {
@@ -32,10 +42,12 @@ const membersGraphqlQuery = `query account($limit: Int, $offset: Int) {
32
42
}
33
43
}` ;
34
44
35
- const transactionsGraphqlQuery = `query account($limit: Int, $offset: Int) {
36
- account(slug: "webpack") {
37
- transactions(limit: $limit, offset: $offset, includeIncognitoTransactions: false) {
38
- nodes {
45
+ // only query transactions in last year
46
+ const transactionsGraphqlQuery = `query transactions($dateFrom: ISODateTime, $limit: Int, $offset: Int) {
47
+ transactions(account: {
48
+ slug: "webpack"
49
+ }, dateFrom: $dateFrom, limit: $limit, offset: $offset, includeIncognitoTransactions: false) {
50
+ nodes {
39
51
amountInHostCurrency {
40
52
value
41
53
}
@@ -47,28 +59,34 @@ const transactionsGraphqlQuery = `query account($limit: Int, $offset: Int) {
47
59
}
48
60
createdAt
49
61
}
50
- }
51
62
}
52
63
}` ;
53
64
54
- const graphqlPageSize = 5000 ;
55
-
56
- const nodeToSupporter = node => ( {
65
+ const nodeToSupporter = ( node ) => ( {
57
66
name : node . account . name ,
58
67
slug : node . account . slug ,
59
68
website : node . account . website ,
60
69
avatar : node . account . imageUrl ,
61
70
firstDonation : node . createdAt ,
62
71
totalDonations : node . totalDonations . value * 100 ,
63
- monthlyDonations : 0
72
+ monthlyDonations : 0 ,
64
73
} ) ;
65
74
66
75
const getAllNodes = async ( graphqlQuery , getNodes ) => {
67
76
const requestOptions = {
68
77
method : 'POST' ,
69
78
uri : graphqlEndpoint ,
70
- body : { query : graphqlQuery , variables : { limit : graphqlPageSize , offset : 0 } } ,
71
- json : true
79
+ body : {
80
+ query : graphqlQuery ,
81
+ variables : {
82
+ limit : graphqlPageSize ,
83
+ offset : 0 ,
84
+ dateFrom : new Date (
85
+ new Date ( ) . setFullYear ( new Date ( ) . getFullYear ( ) - 1 )
86
+ ) . toISOString ( ) , // data from last year
87
+ } ,
88
+ } ,
89
+ json : true ,
72
90
} ;
73
91
74
92
let allNodes = [ ] ;
@@ -82,15 +100,22 @@ const getAllNodes = async (graphqlQuery, getNodes) => {
82
100
requestOptions . body . variables . offset += graphqlPageSize ;
83
101
if ( nodes . length < graphqlPageSize ) {
84
102
return allNodes ;
103
+ } else {
104
+ // sleep for a while
105
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
85
106
}
86
107
}
87
108
} ;
88
109
89
- const oneYearAgo = Date . now ( ) - 365 * 24 * 60 * 60 * 1000 ;
90
110
91
111
( async ( ) => {
92
- const members = await getAllNodes ( membersGraphqlQuery , data => data . account . members . nodes ) ;
93
- let supporters = members . map ( nodeToSupporter ) . sort ( ( a , b ) => b . totalDonations - a . totalDonations ) ;
112
+ const members = await getAllNodes (
113
+ membersGraphqlQuery ,
114
+ ( data ) => data . account . members . nodes
115
+ ) ;
116
+ let supporters = members
117
+ . map ( nodeToSupporter )
118
+ . sort ( ( a , b ) => b . totalDonations - a . totalDonations ) ;
94
119
95
120
// Deduplicating supporters with multiple orders
96
121
supporters = uniqBy ( supporters , 'slug' ) ;
@@ -99,37 +124,43 @@ const oneYearAgo = Date.now() - 365 * 24 * 60 * 60 * 1000;
99
124
for ( const supporter of supporters ) {
100
125
for ( const key of REQUIRED_KEYS ) {
101
126
if ( ! supporter || typeof supporter !== 'object' ) {
102
- throw new Error ( `Supporters: ${ JSON . stringify ( supporter ) } is not an object.` ) ;
127
+ throw new Error (
128
+ `Supporters: ${ JSON . stringify ( supporter ) } is not an object.`
129
+ ) ;
103
130
}
104
131
if ( ! ( key in supporter ) ) {
105
- throw new Error ( `Supporters: ${ JSON . stringify ( supporter ) } doesn't include ${ key } .` ) ;
132
+ throw new Error (
133
+ `Supporters: ${ JSON . stringify ( supporter ) } doesn't include ${ key } .`
134
+ ) ;
106
135
}
107
136
}
108
137
supportersBySlug . set ( supporter . slug , supporter ) ;
109
138
}
110
139
111
140
// Calculate monthly amount from transactions
112
- const transactions = await getAllNodes ( transactionsGraphqlQuery , data => data . account . transactions . nodes ) ;
141
+ const transactions = await getAllNodes (
142
+ transactionsGraphqlQuery ,
143
+ ( data ) => data . transactions . nodes
144
+ ) ;
113
145
for ( const transaction of transactions ) {
114
146
if ( ! transaction . amountInHostCurrency ) continue ;
115
147
const amount = transaction . amountInHostCurrency . value ;
116
148
if ( ! amount || amount <= 0 ) continue ;
117
- const date = + new Date ( transaction . createdAt ) ;
118
- if ( date < oneYearAgo ) continue ;
119
149
const supporter = supportersBySlug . get ( transaction . fromAccount . slug ) ;
120
150
if ( ! supporter ) continue ;
121
- supporter . monthlyDonations += amount * 100 / 12 ;
151
+ supporter . monthlyDonations += ( amount * 100 ) / 12 ;
122
152
}
123
153
124
154
for ( const supporter of supporters ) {
125
155
supporter . monthlyDonations = Math . round ( supporter . monthlyDonations ) ;
126
156
}
127
157
128
158
// Write the file
129
- return asyncWriteFile ( absoluteFilename , JSON . stringify ( supporters , null , 2 ) ) . then ( ( ) =>
130
- console . log ( `Fetched 1 file: ${ filename } ` )
131
- ) ;
132
- } ) ( ) . catch ( error => {
159
+ return asyncWriteFile (
160
+ absoluteFilename ,
161
+ JSON . stringify ( supporters , null , 2 )
162
+ ) . then ( ( ) => console . log ( `Fetched 1 file: ${ filename } ` ) ) ;
163
+ } ) ( ) . catch ( ( error ) => {
133
164
console . error ( 'utilities/fetch-supporters:' , error ) ;
134
165
process . exitCode = 1 ;
135
166
} ) ;
0 commit comments