-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convenient Pagination API, Browser Support, Missing API fields #60
base: master
Are you sure you want to change the base?
Changes from all commits
9396cd3
bb7817b
ec550c8
37fb0ff
7258359
e2fc3dc
2a3b68f
ddaae5e
2b48c95
247cd25
35e5636
8f76c28
a63f437
8f65975
3f59c72
16fe299
3d6cb6c
871b35e
4a24c56
25d57a7
7741df9
e971854
08db146
4d5ace0
e70dc85
958f48c
a2aa543
26cd6a6
c10f132
88e694d
427c50a
277a9f2
37f9633
4eecc6d
2ef0508
3f7dc7a
b359ebc
51eca9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ import { makeEnumIOType } from './helpers' | |
import { | ||
CurrenciesEnum, | ||
EditOrderStatusesEnum, | ||
ListingStatusesEnum, | ||
InventoryStatusesEnum, | ||
OrderMessageTypesEnum, | ||
ReleaseConditionsEnum, | ||
SleeveConditionsEnum, | ||
|
@@ -70,7 +70,7 @@ export const ListingIO = t.intersection([ | |
ResourceURLIO, | ||
t.type({ | ||
id: t.Integer, | ||
status: makeEnumIOType(ListingStatusesEnum), | ||
status: makeEnumIOType(InventoryStatusesEnum), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I chose not to introduce this change yet, as this is only the case when users are authenticated. IMHO we should have 2 different codecs/types depending on whether the user is authenticated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I didn't know that difference, I only saw it not match. Is it the user being authenticated at all, or the authenticated user being the owner of the listing? I'll check out the code paths I encounter this and see what might make sense. |
||
release: t.intersection([ | ||
ResourceURLIO, | ||
t.type({ | ||
|
@@ -113,9 +113,20 @@ export const ListingIO = t.intersection([ | |
audio: t.boolean, | ||
uri: t.string, | ||
}), | ||
// If the user is authorized, the listing will contain a in_cart boolean field indicating whether or not this listing is in their cart. | ||
t.partial({ | ||
in_cart: t.boolean, | ||
}), | ||
// If the authorized user is the listing owner the listing will include the weight, format_quantity, external_id, and location keys. | ||
t.intersection([ | ||
t.type({ | ||
weight: t.number, | ||
format_quantity: t.number, | ||
external_id: t.string, | ||
location: t.string, | ||
}), | ||
t.type({}), | ||
]), | ||
]) | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { IPaginated } from '../models/api' | ||
import type { Discojs } from './discojs' | ||
|
||
export class AllNext { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I felt this implementation was a bit hard to follow, as you first have to call a method, then call
The example you have in the PR description would become: async function updateCollection() {
for await (const { releases } of client.listAllItemsInFolder()) {
for (const release of releases) {
await addToCollection(release)
}
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That seems much more user-friendly, if less magical. 😉 I probably chose my method based on writing the least code and exercising some TypeScript-fu. |
||
/** | ||
* @internal | ||
* | ||
* Gets the next page of a paginated result | ||
*/ | ||
next<TResponse extends IPaginated>(this: Discojs, response: TResponse) { | ||
const { next } = response.pagination.urls | ||
if (next === undefined) { | ||
return Promise.resolve(undefined) | ||
} | ||
return this.fetcher.schedule<TResponse>(next) | ||
} | ||
|
||
/** | ||
* Retrieve all resources from a paginated endpoint. | ||
* @param this | ||
* @param key the name of the field in `TResponse` you wish to aggregate | ||
* @param response the starting page for the paginated response | ||
* @param onProgress optional callback to invoke as each page is retrieved | ||
* @typeparam TKey the name of the field in `TResponse` you wish to aggregate (inferred from `key`) | ||
* @typeparam TResultElement the type of record (inferred from `key` and `response`) | ||
* @typeparam TResponse the type of the response (inferred from `response`) | ||
* @returns an array containing all elements from the different pages concatenated together | ||
*/ | ||
async all<TKey extends string, TResultElement, TResponse extends IPaginated & { [K in TKey]: TResultElement[] }>( | ||
this: Discojs, | ||
key: TKey, | ||
response: TResponse | undefined, | ||
onProgress?: (data: TResultElement[]) => void, | ||
) { | ||
let result: TResultElement[] = [] | ||
while (response !== undefined) { | ||
const data = response[key] | ||
onProgress?.(data) | ||
result = result.concat(data) | ||
// eslint-disable-next-line no-await-in-loop, no-param-reassign | ||
response = await this.next(response) | ||
if (response === undefined) { | ||
break | ||
} | ||
} | ||
return result | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from './discojs' | ||
export * from './enums' | ||
export * from './errors' | ||
export { SortOrdersEnum } from './utils' | ||
export { ResultCache, SortOrdersEnum } from './utils' | ||
export { IPaginated, Pagination } from '../models/api' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a
Pagination
type, named this onePaginationResponse
.