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

feat: add types #189

Merged
merged 10 commits into from
Feb 18, 2021
Merged

feat: add types #189

merged 10 commits into from
Feb 18, 2021

Conversation

achingbrain
Copy link
Member

Adds types to all src and tests and fixes all tsc warnings.

Adds types to all src and tests and fixes all tsc warnings.
@codecov
Copy link

codecov bot commented Feb 11, 2021

Codecov Report

Merging #189 (827afd4) into master (fa50119) will decrease coverage by 19.97%.
The diff coverage is 66.66%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master     #189       +/-   ##
===========================================
- Coverage   97.57%   77.59%   -19.98%     
===========================================
  Files          16       15        -1     
  Lines         206      366      +160     
===========================================
+ Hits          201      284       +83     
- Misses          5       82       +77     
Impacted Files Coverage Δ
src/dag-link/index.js 100.00% <ø> (ø)
src/dag-node/sortLinks.js 100.00% <ø> (ø)
src/dag.js 51.57% <51.57%> (ø)
src/dag-link/dagLink.js 100.00% <100.00%> (ø)
src/dag-link/util.js 100.00% <100.00%> (ø)
src/dag-node/addLink.js 92.30% <100.00%> (ø)
src/dag-node/dagNode.js 95.65% <100.00%> (+0.53%) ⬆️
src/dag-node/rmLink.js 90.00% <100.00%> (+1.11%) ⬆️
src/dag-node/toDagLink.js 100.00% <100.00%> (ø)
src/genCid.js 100.00% <100.00%> (ø)
... and 6 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fa50119...182d0af. Read the comment docs.

@achingbrain
Copy link
Member Author

Also of note: removes protons and class-is in favour of protobufjs (because it's used elsewhere in the stack so cuts down on duplication) and just using instanceof because if we have multiple versions of a module in the dep tree, and they are not semver compatible, they are not compatible and we should fix that.

Copy link
Member

@vmx vmx left a comment

Choose a reason for hiding this comment

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

I only did a brief review. This contains lots of breaking changes. I fear that it would result in a release that breaks many things and it would be a lot of work to fix all those. So I'm not sure if an in-depth review with additional testing makes is time well spent. Or if we e.g. just cut a major release without much thoughts and don't upgrade js-ipld to it (which would mean that js-ipfs would bundle two versions of js-ipld-dag-pb.

I'd prefer if it would just add types and won't do anything else. Especially with the background that we hopefully will use js-dag-pb instead.

Comment on lines +3 to +6
branches:
only:
- master
- /^release\/.*$/
Copy link
Member

Choose a reason for hiding this comment

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

Does it mean that it doesn't run CI if a branch is pushed without doing a PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

If it's not enabled, you can configure this setting in travis to build every non-pr branch

package.json Show resolved Hide resolved
src/genCid.js Outdated
const cid = async (binaryBlob, userOptions = {}) => {
const options = {
cidVersion: userOptions.cidVersion == null ? 1 : userOptions.cidVersion,
hashAlg: userOptions.hashAlg || defaultHashAlg
Copy link
Member

Choose a reason for hiding this comment

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

That would break if you use the identity hash 0x00.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

src/dag-link/dagLink.js Outdated Show resolved Hide resolved
@achingbrain
Copy link
Member Author

This should definitely go out as a major release, that's how we're handling all the TS stuff as setups that are already using typecheckers may suddenly find what they thought was the API was not actually the API (intentional breaking changes/API simplifications aside).

we hopefully will use js-dag-pb instead.

I see that as separate to the typing effort.

@vmx
Copy link
Member

vmx commented Feb 11, 2021

This should definitely go out as a major release.

Yes for sure. Though I don't know if it makes sense to introduce breaking changes like having some properties enumerable that weren't before, which I don't think add much value. I'd keep breaking changes to a minimum in order to minimize potential breakage and time for review and testing.

Anyway, if you think it makes sense I'll spend some time on it to make sure it doesn't break anything in unexpected ways.

@achingbrain achingbrain marked this pull request as draft February 12, 2021 08:50
@achingbrain
Copy link
Member Author

I've made it a draft PR for now, I'll bubble this all the way up to IPFS and we can merge it then (doing the UnixFS importer/exporter types now).

Copy link
Member

@vmx vmx left a comment

Choose a reason for hiding this comment

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

Some type information has no return value defined, sometimes it was even removed. What is the reason for that?

It would be great if you could list all the breaking changes in the commit message, so that it automatically shows up in the changelog.

Comment on lines +23 to +25
this.Name = name || ''
this.Tsize = size
this.Hash = new CID(cid)
Copy link
Member

Choose a reason for hiding this comment

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

Having the values read-only is something dag-pb did (IIRC) from the very beginning. I'm not sure if it is important or not (if it's not important for unixfs, it is probably not).

@rvagg do you have oponions on that?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not something that unixfs uses.

Copy link
Member

Choose a reason for hiding this comment

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

Please change it back to the original code. I don't see a reason to make a change that might break things in a subtle way if we don't have to.

return serializeDAGNode(this)
const buf = serializeDAGNode(this)

this._serializedSize = buf.length
Copy link
Member

Choose a reason for hiding this comment

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

A test for that fix would be great.

predicate = (/** @type {DAGLink} */ link) => link.Name === nameOrCid
} else if (nameOrCid instanceof Uint8Array) {
predicate = (/** @type {DAGLink} */ link) => uint8ArrayEquals(link.Hash.bytes, nameOrCid)
} else if (CID.isCID(nameOrCid)) {
Copy link
Member

Choose a reason for hiding this comment

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

A test for this fix would be great.

Copy link
Member Author

Choose a reason for hiding this comment

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

TBH DAGNode.rmLink accepts DAGLink | string | CID so the type checker would object to you passing a Uint8Array in, but not everyone uses a type checker.

Comment on lines +23 to +27
const cid = async (binaryBlob, userOptions = {}) => {
const options = {
cidVersion: userOptions.cidVersion == null ? 1 : userOptions.cidVersion,
hashAlg: userOptions.hashAlg == null ? defaultHashAlg : userOptions.hashAlg
}
Copy link
Member

Choose a reason for hiding this comment

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

Was the old code buggy? I'm asking as I find the old code clearer then the new one, but I might miss some subtle difference.

Copy link
Member Author

Choose a reason for hiding this comment

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

This change wasn't necessary - I think there was a complaint from tsc but it looks like this wasn't the problem, I can revert if preferred.

Copy link
Member

Choose a reason for hiding this comment

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

I always prefer smaller diffs :) But if it's a hassle, it doesn't bother me much. I was more interested in the reason why.

src/resolver.js Show resolved Hide resolved
src/resolver.js Outdated
@@ -37,9 +40,11 @@ exports.resolve = (binaryBlob, path) => {

// There wasn't even a matching named link
throw new Error(`Object has no property '${key}'`)
} else {
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure about this change. I usually use if … else if it is a branch whether either one thing or the other happens and the computation goes on with either of them. I you only and if if it is an early return. And in this case it is an early return, the if branch never continues to later parts of the code.

Copy link
Member Author

Choose a reason for hiding this comment

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

It was mostly to shut the type checker up. Will remove.

Links: links
}))
Links: links.map((link) => {
return createDagLinkFromB58EncodedHash(link)
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick (no need to change): other similar cases in the code base still have an instanceof DagLink test if something is already a link.

}

exports.serializeDAGNode = serializeDAGNode
exports.serializeDAGNodeLike = serializeDAGNodeLike
/**
Copy link
Member

Choose a reason for hiding this comment

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

Should there be some test so that future changes already get noticed when run this libraries tests (I'm not sure how hard it is to make a proper test and whether it's worth the effort or not)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Given the likely lifespan of this module it's probably not worth the effort.

Copy link
Member Author

Choose a reason for hiding this comment

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

Famous last words..

@@ -58,9 +59,4 @@ describe('DAGLink', () => {
const link = new DAGLink('hello', 3, cid)
expect(link.Hash.toBaseEncodedString()).to.equal(cid)
})

it('has an immutable CID', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Is this a breaking change because it makes sense or because of breaking things while we can?

Copy link
Member Author

Choose a reason for hiding this comment

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

Using Object.defineProperties makes it had to infer what's a class property and what's a dynamically assigned property.

Immutability of programatic structures at this level doesn't really give us much so it seemed simpler to remove it..

Comment on lines 539 to 546
it('creates links from objects with .Size properties', () => {
const node = new DAGNode(uint8ArrayFromString('some data'), [{
Hash: 'QmUxD5gZfKzm8UN4WaguAMAZjw2TzZ2ZUmcqm2qXPtais7',
Size: 9001
}])

expect(node.Links[0].Tsize).to.eql(9001)
})
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this still work (I guess with Tsize instead of Size).

Copy link
Member Author

Choose a reason for hiding this comment

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

It's more that Hash should be a CID but we do still handle the case. Will reinstate.

@achingbrain
Copy link
Member Author

Some type information has no return value defined, sometimes it was even removed. What is the reason for that?

The idea is you let TSC derive the return type of a function - you can see what it'll be by mousing over the function definition or using IntelliSense or looking at the generated .d.ts file.

If you manually specify the return type, TSC will take what you specify, which sometimes is useful but more often can cause bugs because the return type of a method is not what you think it is, so it's usually better to just let the tool figure it out.

@vmx
Copy link
Member

vmx commented Feb 15, 2021

The idea is you let TSC derive the return type of a function

Make sense. Will the API docs TypeScript generates auto-fill the return values? For me (likely a minority) as API docs reader it would be unfortunate if I won't get information what the return values of a function are. Though I can totally see the point of not having return values.

@achingbrain achingbrain marked this pull request as ready for review February 17, 2021 17:34
@achingbrain
Copy link
Member Author

Will the API docs TypeScript generates auto-fill the return values?

Yes, they all appear in the swanky new API docs aegir generates.

This has been rolled up to js-ipfs here: ipfs/js-ipfs#3550

Copy link
Member

@vmx vmx left a comment

Choose a reason for hiding this comment

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

Almost there.

@@ -13,7 +18,6 @@
"release": "aegir release",
"release-minor": "aegir release --type minor",
"release-major": "aegir release --type major",
"build": "aegir build",
Copy link
Member

Choose a reason for hiding this comment

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

I guess the removal of the build command is intentional?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes - prepare is run after installing and before publishing so there's no need for a separate build command.

package.json Show resolved Hide resolved
Comment on lines +23 to +25
this.Name = name || ''
this.Tsize = size
this.Hash = new CID(cid)
Copy link
Member

Choose a reason for hiding this comment

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

Please change it back to the original code. I don't see a reason to make a change that might break things in a subtle way if we don't have to.

Comment on lines 47 to 50
this.Data = data
this.Links = sortedLinks
this._serializedSize = serializedSize
this._size = null
Copy link
Member

Choose a reason for hiding this comment

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

This is still an issue. I propose changing it back to the original code.

@vmx vmx merged commit 76cfef8 into master Feb 18, 2021
@vmx vmx deleted the feat/add-types branch February 18, 2021 13:43
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