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

Conversation

@teogeb
Copy link
Contributor

@teogeb teogeb commented Mar 1, 2021

createStream, getStream, getStreamByName and getOrCreateStream reject the promise if there is an API error.

To support this functionality, a new errorCode field was added to AuthFetchError. Currently the ErrorCode enum lists the most typical API error codes: VALIDATION_ERROR and NOT_FOUND. Other codes can be added later, if needed.

@teogeb teogeb requested review from jtakalai and timoxley March 1, 2021 19:25
@teogeb teogeb merged commit d35841c into 5.x Mar 2, 2021
@teogeb teogeb deleted the stream-reject-on-error branch March 2, 2021 11:52
Copy link
Contributor

@timoxley timoxley left a comment

Choose a reason for hiding this comment

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

Some nitpicking and suggestions to improve test robustness, but otherwise lgtm.

} catch (err) {
return ErrorCode.UNKNOWN
}
const code = json.code
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah follow the eslint warning here, use object destructuring

const keys = Object.keys(ErrorCode)
if (keys.includes(code)) {
return code as ErrorCode
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Using in operator should get around the need to add the as ErrorCode type assertion.

return code in ErrorCode ? code : ErrorCode.UNKNOWN

errorCode?: ErrorCode

constructor(message: string, response: Response, body?: any) {
constructor(message: string, response?: Response, body?: any, errorCode?: ErrorCode) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe instead of passing errorCode in, just have it read it from the body since it's right there?

@@ -0,0 +1,20 @@
export enum ErrorCode {
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO this file's contents should probably live in authFetch.ts.

return new Stream(this.client, json)
}

async getOrCreateStream(props: { id?: string, name?: string }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should probably be:

props: { id: string } | { name: string }

then

if ('id' in props) {
  // etc
}

})

it('invalid id', () => {
return expect(() => client.createStream({ id: 'invalid.eth/foobar' })).rejects.toThrow()
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't always add them myself, but should probably put something in toThrow, even if it's just a partial string match, otherwise should your failure pathway have a programmer error e.g. entirely possible it's throwing on a ReferenceError or SyntaxError, this test could be mistakenly seeing that instead of an actual expected error.

public: false,
})
return json[0] ? new Stream(this.client, json[0]) : undefined
return json[0] ? new Stream(this.client, json[0]) : Promise.reject(new AuthFetchError('', undefined, undefined, ErrorCode.NOT_FOUND))
Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh I see why you left errorCode as a parameter. This '', undefined, undefined, is pretty terrible though.

Maybe could wrap that messiness up and expose an API like:

AuthFetchError.NotFound = class NotFoundError extends AuthFetchError {
    constructor(msg = '') {
        super(AuthFetchError(msg, undefined, undefined, ErrorCode.NOT_FOUND))
    }
}

new AuthFetchError.NotFound(`Could not find stream by name: ${name}`)

Then later you could do if (err instanceof AuthFetchError.NotFound) instead of if (err instanceof AuthFetchError) && (err.errorCode === ErrorCode.NOT_FOUND)

uh, though I guess this would be misleading since other non-AuthFetchError.NotFound errors could have err.errorCode === ErrorCode.NOT_FOUND, so you'd need a factory that creates the appropriate error instance:

export function createAuthFetchError(msg, response, body) {
    switch (parseErrorCode(body)) {
        case ErrorCode.NOT_FOUND: return new AuthFetchError.NotFound(msg, response, body)
        case ErrorCode. VALIDATION_ERROR: return new AuthFetchError.ValidationError(msg, response, body)
        default: return new AuthFetchError(msg, response, body)
    }
}

Just a suggestion though, might not be worth it, your call.

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.

4 participants