@selkirk-systems/fetch 1.4.0 → 1.5.0

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.
@@ -37,19 +37,77 @@ export async function fetchPagedURL(url, callback, options) {
37
37
  };
38
38
  callback = callback ? callback : () => {};
39
39
  let ret = [];
40
- const proxyUrl = url.toString().split("/p/");
40
+ let cachedCallbacks = [];
41
+ let invokedCallbacks = 0;
41
42
  const [response] = await Fetch(url, finalOptions);
42
43
  const {
43
44
  data,
44
45
  status
45
46
  } = response;
46
- const size = new TextEncoder().encode(JSON.stringify(data)).length;
47
- const kiloBytes = size / 1024;
48
- const megaBytes = kiloBytes / 1024;
49
47
  if (status.code > 299 || status.code < 200) {
50
48
  return [response, null];
51
49
  }
52
- const results = {
50
+ let results = getResults(data);
51
+ const items = getEmbedded(data);
52
+ await callback(results, items);
53
+ ret.push({
54
+ id: 0,
55
+ items: items
56
+ });
57
+ if (data._links && data.page.totalPages > 1) {
58
+ const nextUrls = [];
59
+ for (let i = 1; i < data.page.totalPages; i++) {
60
+ const nextUrl = new URL(url);
61
+ nextUrl.searchParams.set("page", i);
62
+ nextUrls.push(Fetch(nextUrl, finalOptions).then(async ([response]) => {
63
+ const {
64
+ data,
65
+ status
66
+ } = response;
67
+ const results = getResults(data);
68
+ const items = getEmbedded(data);
69
+ if (i === invokedCallbacks + 1) {
70
+ invokedCallbacks++;
71
+ await callback(results, items);
72
+ } else {
73
+ cachedCallbacks.push({
74
+ index: i,
75
+ results: results,
76
+ items: items
77
+ });
78
+ }
79
+ ret.push({
80
+ id: i,
81
+ items: items
82
+ });
83
+ return results;
84
+ }));
85
+ }
86
+ const resultsArray = await Promise.all(nextUrls);
87
+ results = resultsArray[resultsArray.length - 1];
88
+ await invokeCallbacks(cachedCallbacks, callback);
89
+ ret = sortByProp(ret, "id");
90
+ ret = ret.reduce((acc, value) => acc.concat(value.items), []);
91
+ }
92
+ return [null, ret, {
93
+ ...results,
94
+ page: data.page.totalPages
95
+ }];
96
+ }
97
+ async function invokeCallbacks(array, callback) {
98
+ array = sortByProp(array, "index");
99
+ await array.map(a => {
100
+ return callback(a.results, a.items);
101
+ });
102
+ }
103
+ function getEmbedded(data) {
104
+ return data._embedded[[Object.keys(data._embedded)[0]]];
105
+ }
106
+ function getResults(data) {
107
+ const size = new TextEncoder().encode(JSON.stringify(data)).length;
108
+ const kiloBytes = size / 1024;
109
+ const megaBytes = kiloBytes / 1024;
110
+ return {
53
111
  page: data.page.number + 1,
54
112
  totalPages: data.page.totalPages,
55
113
  totalElements: data.page.totalElements,
@@ -57,17 +115,17 @@ export async function fetchPagedURL(url, callback, options) {
57
115
  kiloBytes: kiloBytes,
58
116
  megaBytes: megaBytes
59
117
  };
60
- data.items = data._embedded[[Object.keys(data._embedded)[0]]];
61
- await callback(results, data.items);
62
- ret = ret.concat(data.items || []);
63
- if (data._links && data._links.next) {
64
- const nextUrl = new URL(`${proxyUrl[0]}/p/${data._links.next.href}`);
65
- nextUrl.search = createUrlParams({}, nextUrl.searchParams);
66
- const [err, nextPage] = await fetchPagedURL(nextUrl, callback, options);
67
- if (err) return [err, nextPage];
68
- ret = ret.concat(nextPage);
69
- }
70
- return [null, ret];
118
+ }
119
+ function sortByProp(array, prop) {
120
+ return array.sort((a, b) => {
121
+ if (a[prop] < b[prop]) {
122
+ return -1;
123
+ } else if (a[prop] > b[prop]) {
124
+ return 1;
125
+ } else {
126
+ return 0;
127
+ }
128
+ });
71
129
  }
72
130
  function timeout(ms) {
73
131
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -63,20 +63,101 @@ export async function fetchPagedURL( url, callback, options ) {
63
63
 
64
64
  let ret = [];
65
65
 
66
- const proxyUrl = url.toString().split( "/p/" );
66
+ let cachedCallbacks = [];
67
+ let invokedCallbacks = 0;
67
68
 
68
69
  const [response] = await Fetch( url, finalOptions );
69
70
  const { data, status } = response;
70
71
 
71
- const size = new TextEncoder().encode( JSON.stringify( data ) ).length;
72
- const kiloBytes = size / 1024;
73
- const megaBytes = kiloBytes / 1024;
74
-
75
72
  if ( status.code > 299 || status.code < 200 ) {
76
73
  return [response, null];
77
74
  }
78
75
 
79
- const results = {
76
+ let results = getResults( data );
77
+
78
+ const items = getEmbedded( data );
79
+
80
+ await callback( results, items );
81
+
82
+ ret.push( { id: 0, items: items } );
83
+
84
+ if ( data._links && data.page.totalPages > 1 ) {
85
+
86
+ const nextUrls = [];
87
+
88
+ for ( let i = 1; i < data.page.totalPages; i++ ) {
89
+
90
+ const nextUrl = new URL( url );
91
+
92
+ nextUrl.searchParams.set( "page", i );
93
+
94
+ nextUrls.push( Fetch( nextUrl, finalOptions ).then( async ( [response] ) => {
95
+
96
+ const { data, status } = response;
97
+ const results = getResults( data );
98
+ const items = getEmbedded( data );
99
+
100
+ if ( i === ( invokedCallbacks + 1 ) ) {
101
+ invokedCallbacks++;
102
+ await callback( results, items );
103
+ }
104
+ else {
105
+ cachedCallbacks.push( { index: i, results: results, items: items } );
106
+ }
107
+
108
+ ret.push( {
109
+ id: i,
110
+ items: items
111
+ } );
112
+
113
+ return results;
114
+
115
+ } ) );
116
+ }
117
+
118
+ const resultsArray = await Promise.all( nextUrls );
119
+ results = resultsArray[resultsArray.length - 1];
120
+
121
+ await invokeCallbacks( cachedCallbacks, callback );
122
+
123
+ ret = sortByProp( ret, "id" );
124
+
125
+ ret = ret.reduce( ( acc, value ) => acc.concat( value.items ), [] );
126
+
127
+ }
128
+
129
+
130
+ return [null, ret, { ...results, page: data.page.totalPages }];
131
+
132
+ }
133
+
134
+ async function invokeCallbacks( array, callback ) {
135
+
136
+ array = sortByProp( array, "index" );
137
+
138
+ await array.map( a => {
139
+ return callback( a.results, a.items );
140
+ } )
141
+
142
+ }
143
+
144
+
145
+ function getEmbedded( data ) {
146
+
147
+
148
+ return data._embedded[[Object.keys( data._embedded )[0]]];
149
+
150
+
151
+ }
152
+
153
+
154
+ function getResults( data ) {
155
+
156
+ const size = new TextEncoder().encode( JSON.stringify( data ) ).length;
157
+ const kiloBytes = size / 1024;
158
+ const megaBytes = kiloBytes / 1024;
159
+
160
+ return {
80
161
  page: data.page.number + 1,
81
162
  totalPages: data.page.totalPages,
82
163
  totalElements: data.page.totalElements,
@@ -84,28 +165,28 @@ export async function fetchPagedURL( url, callback, options ) {
84
165
  kiloBytes: kiloBytes,
85
166
  megaBytes: megaBytes
86
167
  }
168
+ }
87
169
 
88
- data.items = data._embedded[[Object.keys( data._embedded )[0]]];
170
+ function sortByProp( array, prop ) {
89
171
 
90
- await callback( results, data.items );
91
172
 
92
- ret = ret.concat( data.items || [] );
173
+ return array.sort( ( a, b ) => {
93
174
 
94
- if ( data._links && data._links.next ) {
175
+ if ( a[prop] < b[prop] ) {
95
176
 
96
- const nextUrl = new URL( `${proxyUrl[0]}/p/${data._links.next.href}` );
177
+ return -1;
97
178
 
98
- nextUrl.search = createUrlParams( {}, nextUrl.searchParams );
179
+ } else if ( a[prop] > b[prop] ) {
99
180
 
100
- const [err, nextPage] = await fetchPagedURL( nextUrl, callback, options );
181
+ return 1;
101
182
 
102
- if ( err ) return [err, nextPage];
183
+ } else {
103
184
 
104
- ret = ret.concat( nextPage );
185
+ return 0;
105
186
 
106
- }
187
+ }
107
188
 
108
- return [null, ret];
189
+ } )
109
190
 
110
191
  }
111
192
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selkirk-systems/fetch",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Abortable fetch library",
5
5
  "keywords": [],
6
6
  "author": "Marcos Bernal <mbernal@selkirksystems.com>",
@@ -36,5 +36,5 @@
36
36
  "peerDependencies": {
37
37
  "@selkirk-systems/state-management": ">=1.0.0"
38
38
  },
39
- "gitHead": "29c0902c5e98d9679a6e4dd6977459265875ae2e"
39
+ "gitHead": "3f425f25b96a2239bea972a184391ceb709f64bb"
40
40
  }