-
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?
Conversation
And requires the lowercase version for some reason. Add support for the extended error information provided by FastAPI.
Update from upstream
move pagination into `AllNext` mixin
@pyrogenic Sorry for missing this one, and thanks for all the improvements! |
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.
@pyrogenic I spent some time yesterday introducing some changes initiated in this PR:
- Add missing fields (see comments for ones I did not add)
- Improve error reporting
- Introduce result cache
- Add allowUnsafeHeaders option
- Introduce dedicated methods to iterate through pages (see comment in the review about the implemenation difference)
Let me know what you think about them!
|
||
export type ErrorResponse = t.TypeOf<typeof ErrorResponseIO> | ||
|
||
export type Pagination = t.TypeOf<typeof PaginationIO> |
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 one PaginationResponse
.
@@ -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 comment
The 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 comment
The 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.
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 comment
The 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 client.all
.
Instead of doing that, I introduced dedicated all
methods that returns async iterators:
getAllMasterVersions
getAllArtistReleases
getAllLabelReleases
getAllRecentExports
getAllInventoryForUser
getAllInventory
listAllOrders
listAllItemsByReleaseForUser
listAllItemsByRelease
listAllItemsInFolderForUser
listAllItemsInFolder
getAllSubmissionsForUser
getAllSubmissions
getAllContributionsForUser
getAllContributions
getAllListsForUser
getAllLists
getAllWantlistForUser
getAllWantlist
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 comment
The 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.
let buffer: undefined | typeof Buffer | ||
try { | ||
buffer = Buffer | ||
} catch { | ||
buffer = undefined | ||
} |
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.
What is the purpose of this?
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.
I'm guessing there was a situation in some browser where accessing Buffer
to calculate content length through. I honestly don't remember the details. Getting Chrome to be happy with those headers and their capitalization was a PITA. I myself would reject this without an explanatory comment about the circumstances of the error and the expected alternate behavior...
@aknorw thanks so much for taking the time to review, and sorry for the delayed response. I'll take a closer look outside work hours! ... and apologies for throwing a couple years of tweaks up in a single PR! |
Several additions to Discojs that I've accumulated over the years building Elephant. It's a browser-based tool to manage a Discogs collection and store listings. (source)
all
API to Discojs that retrieves all pages of a paginated endpoint given the first page:notes
toFolderReleases
,name
toArtist
,avatar_url
toUser
)ResultCache
which may be used to skip retrieving results multiple times. (My app storesGET
responses using IndexedDB.)Happy to make changes to allow the PR to be accepted.