Skip to content
This repository has been archived by the owner on Dec 30, 2021. It is now read-only.

Replace got with axios and allow isomorphic export #172

Closed
wants to merge 42 commits into from

Conversation

KenEucker
Copy link
Collaborator

This PR includes a heavy rewrite of the core of imgur@next, moving away from got and to axios which can be compiled and used in the browser. This, in conjunction with dropping support for "local file" uploads by using fs.createReadStream, allows this package to be used in nodejs and in the browser after being compiled as a umd module.

Tasks completed:

  1. Replace got with axios. Replacing Response wrapping.
  2. Add a helper method to utils.ts convert from the underlying response object to an ImgurApiResponse.
  3. Replace the use of path strings resulting in a call to createReadStream, with the string parameter to be interpreted as a "url" upload.
  4. Remove upload methods specific to videos and files in favor of streams for these upload types.
  5. Update the readme to show the external use of the fs.createReadStream for local file uploads using the API.
  6. Add readme instructions for creating streams in the browser and uploading via the browser.
  7. Reconfigure the build process for the package to include webpack bundling as a umd module.
  8. Update tests.

The only item missing from this PR that isn't complete feature parity with the current imgur@next is the lack of progress updates for uploaded items. The test for that would not succeed and I wasn't able to determine why but hope to find time to address it in the future.

@kaimallea I know that I was the one to suggest using got in the first place, and I know that you had said on a previous issue that supporting node was the singular focus of this package. The reason that I have completed this work is that I have a need for this package to be able to be used in the client, browser, as well and I found, in my discovery of trying to do so, that the only negative impact is removing a single call using fs. Please let me know if this is something you are willing to consider?

KenEucker and others added 30 commits March 8, 2021 21:34
Merging upstream changes.
Merging main from origin
Merged version 1 from upstream
…27.2

build(deps-dev): bump msw from 0.27.1 to 0.27.2
…28.0

build(deps-dev): bump msw from 0.27.2 to 0.28.0
…-7.23.0

build(deps-dev): bump eslint from 7.22.0 to 7.23.0
…6.0.0

build(deps-dev): bump husky from 5.2.0 to 6.0.0
…lint/config-conventional-12.1.1

build(deps-dev): bump @commitlint/config-conventional from 12.0.1 to 12.1.1
…28.1

build(deps-dev): bump msw from 0.28.0 to 0.28.1
…lint/cli-12.1.1

build(deps-dev): bump @commitlint/cli from 12.0.1 to 12.1.1
…-7.24.0

build(deps-dev): bump eslint from 7.23.0 to 7.24.0
…-config-prettier-8.2.0

build(deps-dev): bump eslint-config-prettier from 8.1.0 to 8.2.0
…h both the browser and nodejs

This update abstracts the http request method out a little futher than it was in a "fetcher" object
and includes a utility wrapper for conforming request responses to the ImgurApiResponse model. All
test have been updated and support for automatic filepath uploads has been dropped in favor of
cross-platform support.

BREAKING CHANGE: The package can no longer be used with string path variables pointing to local
files. This moves a single line of code, using fs.createReadStream, out of the project and places
that responsibility on the consumer. The package now supports streams in favor of the string
filepath upload.
@KenEucker KenEucker self-assigned this Apr 17, 2021
@KenEucker KenEucker changed the base branch from main to next-dev April 17, 2021 21:09
@KenEucker
Copy link
Collaborator Author

The tests are failing, due to a warning I guess?, because of this line in authorize.ts:

Screen Shot 2021-04-17 at 2 39 04 PM

The offending code:
const { username, password, allow } = req.body as any

req.body, with axios, is an object in this case. I might add an eslint ignore to this line?

… mock for authorization

this should be revisited in the future to determine the correct type of the body in order to
deconstruct it.
…t script in package.json

This update includes modifications to the scripts in package.json to allow users to run the pretty
and eslint tasks individually, and has the lint script call those individual scripts together. All
scripts now use npx to instruct npm to use the module from node_modules.
@KenEucker
Copy link
Collaborator Author

KenEucker commented Apr 20, 2021

Something is weird with the PR, and I think it's getting hung up on something related to the action's permissions. Maybe because this is coming from a branch on my repository it doesn't have access to the same secrets you have set up in yours, @kaimallea?

If I'm reading these errors correctly, it looks like the tests are failing when attempting to send a message back to GitHub stating that tests succeeded:
Screen Shot 2021-04-19 at 6 48 02 PM
Screen Shot 2021-04-19 at 6 48 26 PM

…e ImgurClient class

To provide additional context and type support for projects consuming the node-imgur api, who might
be storing ImgurCredentials in an object of their
@kaimallea
Copy link
Owner

Universal/isomorphic support will be amazing. There's a lot to digest here, I will dig in after work hours! Thanks for the PR 🙌🏾

@KenEucker
Copy link
Collaborator Author

@kaimallea I don't know if you have already taken a look at this code or not, but I wanted to provide additional context after more testing:

It seems that the UMD strategy I was using to create the bundle works fine for the browser (it is a webpack bundle, after all), but it doesn't work with node. I spent some time last night digging through the issue and will need to update this PR once again when I find the right configuration combination to produce the results we're after.

I am expecting to be able to have a single index.ts file be the entry point for both the node and the web versions, and for webpack to produce a single dist file to be consumed by both node and the browser, with the following instantiation code:

web

<script src="path-to-local-library/index.js"></script>
<script>
const imgurClient = imgur({})
</script>

or with bundlers
import { ImgurClient } from 'imgur';
const imgur = require('imgur');

node

// ESModule syntax
import { ImgurClient } from 'imgur'

// CommonJS syntax
const { ImgurClient } = require('imgur')

This is work I am committed to completing for the BikeTag API and would love to be able to bring it back to this project.

Universal Javascript is bae, Isomorphic Support is life.

@kaimallea kaimallea changed the base branch from next-dev to next April 23, 2021 23:02
@kaimallea kaimallea changed the base branch from next to next-dev April 23, 2021 23:02
Copy link
Owner

@kaimallea kaimallea left a comment

Choose a reason for hiding this comment

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

I think I would have preferred a more iterative approach to limit the total number of changes happening at once. For example, just replacing got with axios, and no other changes, to isolate those changes and tests. And then after that's done and merged, more iterative changes to make it more isomorphic/universal. I think that makes it easier/faster to make changes, and review, too.

package.json Outdated
Comment on lines 24 to 35
"test": "npx jest",
"test:ci": "npx jest --ci --coverage --runInBand",
"build": "npx tsc",
"compile": "npx webpack",
"typecheck": "npx tsc --noEmit",
"eslint": "npx eslint . ",
"pretty": "npx prettier . --check ",
"pretty:write": "npx prettier . --write ",
"clean": "rm -rf lib",
"prepare": "husky install",
"lint": "eslint . && prettier --check . && npm run typecheck",
"commit": "cz"
"prepare": "npx husky install",
"lint": "npm run eslint && npm run pretty && npm run typecheck",
"commit": "npx cz"
Copy link
Owner

Choose a reason for hiding this comment

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

why are you adding npx in front of all of these commands? these are dev dependencies, so after the initial npm install they will be automatically resolved via node_modules/,bin. Reference.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought that when running npm scripts that it used the most local node_modules, but when I tried running it with this and other projects recently it does not. I found that I either had to install eslint globally or these commands would not work for me. Maybe that's a my machine problem?

if (typeof payload === 'string') {
return false;
}

return typeof payload.video === 'string';
Copy link
Owner

Choose a reason for hiding this comment

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

how is someone supposed to upload a video with this removed? The Imgur API requires that the video property is set in the formdata. sure, you can stream in a video file, but how is Imgur API supposed to differentiate a video from an image?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I assume through a stream, but this line looks incorrect. I think this should be compared to a type of stream.

The code will pass along the video as a stream into the form to be set as the 'video' field, from what I understand of it.

if (typeof payload === 'string') {
return payload;
}

if (isVideo(payload)) {
return payload.video as string;
if (isBase64(payload)) {
Copy link
Owner

Choose a reason for hiding this comment

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

base64 is already supported, so not sure why it's even more explicit? is this to better support browser environment?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added this method following what I saw from the code for checking other types. I thought this would add more of the same typechecking. If this is not needed, then it should be removed.

@@ -8,9 +8,17 @@ import * as gallery from './gallery';
import * as credits from './credits';
import * as album from './album';

// import axios from 'axios';
// import MockAdapter from 'axios-mock-adapter';
// const mock = new MockAdapter(axios);
Copy link
Owner

Choose a reason for hiding this comment

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

🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, I didn't realize that these lines were in this file. This should also be removed.

} else {
form.append(key, value);
}
}
return form;
}

export function getImgurApiResponseFromResponse(
Copy link
Owner

Choose a reason for hiding this comment

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

is the idea that this replace resolveBodyOnly prop from got?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@kaimallea I suppose so. I feel that a helper method here makes the package a bit more modular. This might be solvable by an option with axios that I'm not aware of.

title: 'dank meme',
description: 'the dankiest of dank memes',
});
expect(response).toMatchInlineSnapshot(`
Object {
"data": Object {
"deletehash": "jyby9KJ",
"description": "the dankiest of dank memes",
"description": null,
Copy link
Owner

Choose a reason for hiding this comment

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

🤔

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Woops. It looks like I bungled a jest -u here and didn't resolve it?

"id": "JK9ybyj",
"link": "https://i.imgur.com/JK9ybyj.jpg",
"title": "dank meme",
"title": null,
Copy link
Owner

Choose a reason for hiding this comment

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

🤔

@KenEucker
Copy link
Collaborator Author

@kaimallea I hear you. I can break up the changes, but what I thought I had to do was make all of the tests pass before I could make a commit. How are you envisioning I could break up this commit into something more iterative?

@kaimallea
Copy link
Owner

Going to make a draft PR as an example of something more iterative

@KenEucker KenEucker changed the title Replace got with axios and add cross-platform support for this imgur package. Replace got with axios and allow isomorphic export Oct 29, 2021
@KenEucker
Copy link
Collaborator Author

@kaimallea I wanted to circle back with you after recent success in using this version of node-imgur next with axios including isomorphic compilation using webpack. You can see it both here: https://github.com/KenEucker/node-imgur/tree/next and as a release here: https://github.com/KenEucker/node-imgur/tree/release

I am using this version of this package so that the BikeTag API is also isomorphic. You can see it being included in this project: https://github.com/KenEucker/biketag-api.

The tests are failing due to a lack of access, it seems, so those might need to be run by your user account and not mine.

If you get a chance to read this I hope you can consider this PR once again.

this package is now being published under imanagur, as it has diverged from node-imgur, and
node-imgur remains stale.
@KenEucker KenEucker closed this Dec 8, 2021
@KenEucker KenEucker deleted the next branch December 8, 2021 00:31
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants