startgg-helper 2.3.2 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/query.js +56 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "startgg-helper",
3
- "version": "2.3.2",
3
+ "version": "2.4.1",
4
4
  "description": "A set of functions and classes useful to communicate with the start.gg API, using any client (YOU NEED TO PROVIDE A CLIENT YOURSELF, SEE README)",
5
5
  "main": "main.js",
6
6
  "module": "main.js",
package/src/query.js CHANGED
@@ -5,6 +5,17 @@ function isConnection(val){
5
5
  return val instanceof Object && val.nodes instanceof Array
6
6
  }
7
7
 
8
+ export class PageResult {
9
+ /**
10
+ * @param {any} result
11
+ * @param {boolean} stop
12
+ */
13
+ constructor(result, stop){
14
+ this.result = result;
15
+ this.stop = stop;
16
+ }
17
+ }
18
+
8
19
  /**
9
20
  * A GraphQL Document/Schema. Allows easily batch-requesting with the same schema but different parameters.
10
21
  */
@@ -76,7 +87,7 @@ export class Query {
76
87
  }
77
88
 
78
89
  /**
79
- * @param {GraphQLClient} client A client object ; not provided by this package, either use startgg-helper-node (or-browser) or refer to README.md
90
+ * @param {GraphQLClient} client A client object ; not provided by this package, either use startgg-helper-node (or -browser) or refer to README.md
80
91
  * @param {{[varName: string]: value}} params GraphQL variables
81
92
  * @param {TimedQuerySemaphore} limiter A request limiter object; see TimedQuerySemaphore
82
93
  * @param {boolean} silentErrors No effect, exists only for legacy purposes
@@ -94,6 +105,8 @@ export class Query {
94
105
  OUT: 3
95
106
  }
96
107
 
108
+ /** @typedef {(localResult: T[], currentResult: T[], pageIndex: number) => (T[]|PageResult|boolean)?} PageCallback*/
109
+
97
110
  /**
98
111
  * Queries a whole paginated collection (of a *Connection type). See the start.gg API doc or this package's documentation for more info about pagniated collections. This is done through executing the query repeatedly while increasing the page index each time.
99
112
  * The target collection must be pointed to by the "path" argument, and will be agregated in a single array. The schema must have a variable (whose name can be specified in parameters) that is used as the page index of the paginated field.
@@ -103,7 +116,7 @@ export class Query {
103
116
  * @param {{[varName: string]: value}} params GraphQL variables ; does not include the page index variable.
104
117
  * @param {string} connectionPathInQuery JSON path to the paginated collection that must be aggregated in the query (JSON path : property names separated by dots, see deep_get())
105
118
  * @param {TimedQuerySemaphore} limiter A request limiter object; see TimedQuerySemaphore
106
- * @param {{pageParamName?: string, perPageParamName?: string, perPage?: number, delay?: number, maxElements?: number, includeWholeQuery?: number, callback: (localResult: T[]) => T[]?}} config
119
+ * @param {{pageParamName?: string, perPageParamName?: string, perPage?: number, startingPage: number, initialData: any, delay?: number, maxElements?: number, includeWholeQuery?: number, callback: PageCallback?}} config
107
120
  * @param config.pageParamName name of the variable representing the page index. This variable must exist in your query, and be used as an argument in a paginated collection field
108
121
  * @param config.delay number of miliseconds to wait for between each query. No delay if absent.
109
122
  * @param config.maxElements if present, queries will stop once this many elements have been fetched
@@ -114,15 +127,14 @@ export class Query {
114
127
  * @returns See config.includeWholeQuery
115
128
  */
116
129
  async executePaginated(client, params, connectionPathInQuery, limiter = null, config = {}, silentErrors = false, maxTries = null){
117
- let result = [];
118
- //delay = null, perPage = undefined, pageParamName = "page", perPageParamName = "perPage", silentErrors = false, maxTries = null
130
+ let result = config.initialData ?? [];
119
131
  const pageParamName = config.pageParamName ?? "page";
120
132
  const perPageParamName = config.perPageParamName ?? "perPage";
121
133
  const perPage = config.perPage ?? params[perPageParamName];
122
134
  const delay = config.delay;
123
135
  const maxElements = config.maxElements ?? undefined; //eliminating null
124
136
 
125
- let currentPage = 1;
137
+ let currentPage = config.startingPage ?? 1;
126
138
 
127
139
  params = Object.assign({}, params);
128
140
  params[pageParamName] = currentPage;
@@ -150,29 +162,56 @@ export class Query {
150
162
 
151
163
  let localResult = connection.nodes;
152
164
 
153
- if (connection.pageInfo && connection.pageInfo.totalPages){
165
+ if (connection.pageInfo && connection.pageInfo.totalPages){ //if the query contains pageInfo we use that to determine if we're at the last page
154
166
  let totalPages = connection.pageInfo.totalPages;
155
- if (!totalPages || currentPage >= totalPages) {
167
+ if (currentPage >= totalPages) {
156
168
  if (config.callback){
157
- let cbRes = config.callback(localResult, currentPage);
158
- if (!cbRes) break;
159
- localResult = cbRes;
169
+ let cbRes = config.callback(localResult, result, currentPage)
170
+
171
+ if (cbRes instanceof PageResult){
172
+ if (cbRes.result){ //If the user gives us a result we take it ofc
173
+ result = cbRes.result;
174
+ } else {
175
+ result = result.concat(localResult);
176
+ }
177
+ } else if (cbRes && cbRes !== true) { //cbres isn't one that means something loop-control-related (it's over anyways so we don't care!)
178
+ result = result.concat(cbRes);
179
+ }
180
+ } else {
181
+ result = result.concat(localResult);
160
182
  }
161
- result = result.concat(localResult);
162
183
  break;
163
184
  }
164
- } else {
185
+ } else { //if not, we only know when we get an empty page
165
186
  if (localResult.length < 1) break;
166
187
  }
167
188
 
168
189
  if (config.callback){
169
- let cbRes = config.callback(localResult, currentPage);
170
- if (!cbRes) break;
171
- localResult = cbRes;
172
- }
190
+ let cbRes = config.callback(localResult, result, currentPage);
173
191
 
174
- result = result.concat(localResult);
192
+ if (cbRes instanceof PageResult){
193
+ if (cbRes.result){ //If the user gives us a result we take it ofc
194
+ result = cbRes.result;
195
+ } else {
196
+ result = result.concat(localResult);
197
+ }
198
+ if (cbRes.stop){
199
+ break;
200
+ }
201
+ } else if (!cbRes) { //"normal case" : basic callback that doesn't touch the flow of the pexecution, we concat and increment normally
202
+ result = result.concat(localResult)
203
+ } else if (cbRes === true){ //callback is asking us to stop by returning true
204
+ break;
205
+ } else { //callback returns a non-boolean value : it's the local result (and we increment normally)
206
+ result = result.concat(cbRes);
207
+ }
208
+
209
+ } else {
210
+ result = result.concat(localResult);
211
+ }
212
+
175
213
  currentPage++;
214
+
176
215
  params[pageParamName] = currentPage;
177
216
 
178
217
  if (delay)