Skip to content
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

PanoptesJS: remove superagent #6299

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft

Conversation

shaunanoordin
Copy link
Member

PR Overview

Package: panoptes-js

This PR attempts to remove superagent from the PanoptesJS client

  • Reason: superagent is a dependency that we don't technically need anymore, since the standard fetch API works fine, while maintaining superagent can be a bit of a faff.
  • Observation: superagent() is only used in the get(), post(), put(), and del() (i.e. delete) functions of panoptes.js, so replacing the dependency should be very easy.
    • (Spoiler: it wasn't)
  • Priority: low priority, for now. Removing superagent is a "nice to have" item that will eventually escalate to "gotta get it done" once the maintenance cost gets too high in the future (or the library stops getting updates, whichever comes first).

Dev Notes

As of 12 Sep 2024, this PR is in an experimental stage. The biggest lessons we've learnt are:

  1. it's actually easy to replace the superagent() calls in panoptes.js, as initially observed.
  2. however, there are MULTIPLE places in the FEM code that expects a very specific superagent-shaped response from panoptes.get()/panoptes.put()/panoptes.post()/panoptes.del(),
Comparison of the default response data we get from superagent vs the default response data we get from fetch().

Superagent response:

Screenshot 2024-09-12 at 15 56 50

Fetch API response:

Screenshot 2024-09-12 at 16 00 18

So in practice, we either need to...

  1. accept the cost of going through the hundred(s?) instances in the FEM code (and any other project that uses PanoptesJS) that expects a superagent response and make changes there, OR
  2. create a transformer/adapter that transform Fetch API responses into superagent-compatible responses.

Status

Experimental. Put on pause as of 12 Sep 2024 while higher priority items in PanoptesJS is addressed.

As of commit 96096e: panoptes.get experimental: replace superagent with fetch, the get() function has superagent() successfully replaced with fetch(), with a very rudimentary fetch-response-to-superagent-response transformer in place. You can run lib-classifier > yarn dev and load a local test project, and the data will be fetched fine for this instance.

@shaunanoordin shaunanoordin added the experiment Something to try out and gather more information on label Sep 12, 2024
Comment on lines +56 to +73
/*
Converts a query object (e.g. { foo: 'bar', img: 'http://foo.bar/baz.jpg' })
into a query string (e.g. "foo=bar&img=http%3A%2F%2Ffoo.bar%")
*/
function getQueryString (query, endpoint = '') {
const queryParams = getQueryParams(query)
let queryString = Object.entries(queryParams)
.filter(([key, val]) => val !== undefined)
.map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`)
.join('&')

if (queryString.length > 0) {
return endpoint.includes('?')
? `&${queryString}` // If endpoint already has a query '?', prepend the query string with a '&'.
: `?${queryString}` // Otherwise, prepend with a '?'.
}
return ''
}
Copy link
Contributor

@eatyourgreens eatyourgreens Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use URLSearchParams to convert an object to a query string in all browsers and in Node too.

Copy link
Contributor

@eatyourgreens eatyourgreens Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const searchParams = new URLSearchParams(queryParams)
return searchParams.toString()

@eatyourgreens
Copy link
Contributor

Might be a good idea to upgrade the code to ES6 too. At the moment, it’s written for old versions of Node that are no longer supported.


return request.query(queryParams).then(response => response)
const queryString = getQueryString(query, endpoint)
const fetchHeaders = Object.assign({
Copy link
Contributor

@eatyourgreens eatyourgreens Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.assign has been replaced by the object spread operator, which is much faster, in modern JavaScript.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object.assign should only appear in code if you need to support IE.

Comment on lines +82 to +85
const fetchHeaders = Object.assign({
'Content-Type': 'application/json',
'Accept': 'application/vnd.api+json; version=1',
}, parseHeaders(headers))
Copy link
Contributor

@eatyourgreens eatyourgreens Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const fetchHeaders = Object.assign({
'Content-Type': 'application/json',
'Accept': 'application/vnd.api+json; version=1',
}, parseHeaders(headers))
const fetchHeaders = {
'Content-Type': 'application/json',
'Accept': 'application/vnd.api+json; version=1',
...parseHeaders(headers)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
experiment Something to try out and gather more information on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants