-
Notifications
You must be signed in to change notification settings - Fork 520
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
Convert from Flow to Typescript #816
Conversation
@@ -64,11 +60,11 @@ | |||
"docgen": "node --harmony scripts/build_docs.js", | |||
"clean": "rm -rf dist/npm", | |||
"typecheck": "flow check", | |||
"compile": "babel -D --optional runtime -d dist/npm/ src/", | |||
"watch": "babel -w -D --optional runtime -d dist/npm/ src/", | |||
"compile": "mkdir -p dist/npm/common && cp -r src/common/schemas dist/npm/common/ && tsc", |
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.
typescript only handles typescript files, so we have to copy the schemas
directory here ourselves. Normally you could just move this folder to a single place outside of the src
directory and load them by relative path, but unfortunately that breaks because dist/npm
& src/
are at different levels of nesting (../
vs ../../
).
This doesn't feel too complex but if we ever need to add more here we could move this into a build script or gulp file.
getServerInfo, | ||
getFee, | ||
getLedgerVersion, | ||
connect = connect |
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.
Adding these as class properties makes them a part of the interface, vs. _.assign()
which was appending them to the prototype in a way that confused TypeScript.
@@ -3,11 +3,15 @@ import * as _ from 'lodash' | |||
import {RippleAPI} from './api' | |||
|
|||
class RippleAPIBroadcast extends RippleAPI { | |||
|
|||
// TODO: Should this default to 0, or null/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.
I think 0
is good here.
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.
> 1 > undefined
false
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.
@intelliot my concern is that 0 is a number but isn't a valid ledger number. It do mean that things like (ledger.ledgerVersion > this.ledgerVersion)
will work by default, but it also means we have to document and explain that 0 = unset/unknown. It would be more explicit if ledgerVersion = undefined
means it hasn't been looked up yet.
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's a good point. I'm fine with undefined
, but make sure to update the if condition (ledger.ledgerVersion > this.ledgerVersion
) too.
src/common/connection.ts
Outdated
private _proxyAuthorization?: string | ||
private _authorization?: string | ||
private _trustedCertificates?: string[] | ||
// TODO: options.key never used? |
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.
Looks like it's used in _createWebSocket()
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.
Ha, can't believe I missed that
Still looking at this. Hoping to try it out soon :) Any potentially breaking changes? |
Any news on this ? I'm really looking forward to 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.
This is a great start. I left comments on a few of the TODOs.
Also, ripple-lib can be used with either node or in the browser, so I think we need to make some changes to our webpack config for browser builds to work.
@@ -186,7 +212,8 @@ class Connection extends events.EventEmitter { | |||
|
|||
this._retry = 0 | |||
this._ws.on('error', error => { | |||
if (process.browser && error && error.type === 'error') { | |||
// TODO: "type" does not exist on official error type, safe to remove? |
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 not sure. Perhaps some versions of ws
included it? To be safe, we could remove it in a later release and note it in the changelog.
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.
sounds good, I'll just leave it as a TODO then
@@ -60,16 +60,19 @@ function getServerInfo(connection: Connection): Promise<GetServerInfoResponse> { | |||
}) | |||
} | |||
|
|||
// TODO: This was originally annotated to return a number, but actually | |||
// returned a toString'ed number. Should this actually be returning a number? |
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 believe this should be a string. We generally use strings for all currency amounts.
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.
sounds good.
Separately: Looking at this more closely now, should this use BigNumber
internally? Number
could cause problems with baseFeeXRP
being a float, right?
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.
Yes, it would be correct to use BigNumber
here internally.
paths.alternatives = _.filter(paths.alternatives, alt => | ||
!!alt.source_amount && | ||
!!pathfind.source.amount && | ||
// TODO: Returns false when alt.source_amount is a string. Fix? |
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.
How can alt.source_amount
be a string?
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.
alt.source_amount
is of type RippledAmount
, which can be a string. https://ripple.com/build/rippled-apis/ seems to document a few places where source_amount is a string.
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.
Looks like source_amount
is only a string when the currency is XRP, in which case there is no need for pathfinding. So I think it's fine to return false in that case.
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.
Looks like source_amount is only a string when the currency is XRP, in which case there is no need for pathfinding.
You can send XRP and use paths to send the recipient USD ...
What you mean no need for path finding ?
src/server/server.ts
Outdated
@@ -23,12 +21,14 @@ function getServerInfo(): Promise<GetServerInfoResponse> { | |||
return common.serverInfo.getServerInfo(this.connection) | |||
} | |||
|
|||
function getFee(): Promise<number> { | |||
// TODO: getFee() was originally annotated to return a number, but actually | |||
// returned a toString'ed number. Should this actually be returning a number? |
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.
This should return a string.
@@ -21,7 +19,9 @@ function compareSigners(a, b) { | |||
function combine(signedTransactions: Array<string>): Object { | |||
validate.combine({signedTransactions}) | |||
|
|||
const txs = _.map(signedTransactions, binary.decode) | |||
// TODO: signedTransactions is an array of strings in the documentation, but | |||
// tests and this code handle it as an array of objects. Fix! |
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.
Good catch 🤔
@intelliot Great catch re: webpack. I'll get that fixed for this PR. Thanks for the review! No behavior should be changing here, except for a few small bug fixes that were explicitly bugs. Anything that could have been relied on as behavior was left as-is with a TODO, so no breaking changes expected. Excited to do some more work on this over the holidays. Three branches can go into PR all together once this gets merged:
|
webpack & gulp updated for TS: FredKSchott/ripple-lib@typescript...FredKSchott:webpack It's currently in a separate branch, but I can add it directly into this PR if you'd prefer. |
That looks great! I attempted to create a PR and merge that branch to this PR, but github won't allow it since I don't have write access to your fork 😅 |
Haha np, I'll merge it in now |
Update webpack, gulpfile to support typescript
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.
This looks good. The remaining TODOs could be handled later. I'll do a bit more manual testing meanwhile.
Squashed and merged! I don't think there will be any difficulty rebasing on the squash commit, but let me know if so. |
@intelliot woo! 🎉 Thanks for your reviews Just getting back & caught up from the holidays, I'll rebase those other branches and create the next batch of PRs |
TypeScript is very similar to Flow, in that both provide a flexible typing system for JavaScript. The syntax is almost identical, so it should feel perfectly comfortable already. But TypeScript is much more powerful, so with the same syntax you catch more errors and enforce clearer code. This is a good, fair comparison of the two, and here are some examples in rippled-lib itself:
Additionally it's growing faster, adding new features, and is already fairly popular in the larger npm ecosystem. Lodash, for ex, publishes TS type definitions directly in their package, which is how I was able to catch that error above automatically. Also, type checking is a part of your build/compile, so they can't get out of date with the code.
This allows us to add function typing information to the new, main
request()
interface. That way all consumers, even those using regular JavaScript with an IDE like VSCode, will get typing help when making API requests and handling API responses. See #812 for more information./cc @intelliot This touches a lot of code so please ask if anything is confusing / looks off / could use some documentation.