7 Commits

Author SHA1 Message Date
William Chargin
c890fe03b4
Add Node’s path.normalize for the browser (#650)
Summary:
This function normalizes paths like `foo/bar//../baz` to `foo/baz`. The
implementation is directly copied from Node’s source code, which is
available under an MIT License.

I looked for a suitable NPM package, and rejected `path-normalize` and
`normalize-path`. (The former is closer and explicitly purports to be
the right thing, but actually isn’t.)

Test Plan:
Unit tests added, with full coverage except for one branch; I include a
proof that the branch is unreachable.

Tested on Node v8.9.4, Node v10.0.0, and Node v10.8.0. Tests pass in
each case. In the latter two cases, inconsistencies between the
implementation and the actual `path.posix.normalize` would cause a test
failure. In the former case, they do not. (All such cases verified.)

wchargin-branch: path-normalize
2018-08-14 13:04:53 -07:00
William Chargin
4058a3fd85
Extract dedent to util, adding tests (#538)
Summary:
There have been a couple of occasions on which we’ve considered using
it, but didn’t want to require from `app/`.

Test Plan:
Unit tests added, with full coverage.

wchargin-branch: extract-dedent
2018-07-27 12:30:28 -07:00
William Chargin
4af8ff2471
Add utilities for working with nullable types (#505)
Summary:
This commit adds a module with four functions: `get`, `orThrow`, `map`,
and `orElse`.

Here is a common pattern wherein `get` is useful:

```js
sortBy(Array.from(map.keys()), (x) => {
  const result = map.get(x);
  if (result == null) {
    throw new Error("Cannot happen");
  }
  return result.score;
});

// versus

sortBy(Array.from(map.keys()), (x) => NullUtil.get(map.get(x)).score)
```

(The variant `orThrow` allows specifying a custom message that is only
computed in the case where the error will be thrown.)

Here is a common pattern where `map` is useful:

```js
arr.map((x) => {
  const result = complicatedComputation(x);
  return result == null ? result : processResult(result);
});

// versus

arr.map((x) => NullUtil.map(complicatedComputation(x), processResult))
```

In each of these cases, by using these functions we gain a dose of
safety in addition to our concision: it is tempting to “shorten” the
expression `x == null ? y : z` to simply `x ? y : z`, while forgetting
that the latter behaves incorrectly for `0`, `false`, `""`, and `NaN`.
Similar patterns like `x || defaultValue` also suffer from this problem,
and can now be replaced with `orElse`.

Designed with @decentralion.

Test Plan:
Unit tests included; run `yarn travis`.

wchargin-branch: null-util
2018-07-09 14:47:10 -07:00
William Chargin
812b2d322e
Add utilities for working with ES6 Maps (#495)
Summary:
We’d like to like ES6 `Map`s, because they provide better type safety
than objects (primarily, `Map.prototype.get` has nullable result type).
However, the vanilla APIs are weak. Prominent problems are that `Map`s
always become `"{}"` under `JSON.stringify`, that there is no easy way
to convert between `Map`s and objects, and that there are no functions
to map over the keys and values of `Map`s.

In this commit, we add versions of those functions to a utility module.
The value-level implementations are straightforward, but these functions
nevertheless deserve a utility module because the types are somewhat
tricky to get right. The implementation requires casts through `any`,
and these should be written, analyzed, and proven correct just once. (In
particular, it would be easy to write an unsound type for `fromObject`.)

In a followup commit, we will amend existing portions of the codebase to
use these functions.

Test Plan:
Unit tests added; run `yarn travis`.

wchargin-branch: map-util
2018-07-06 22:08:38 -07:00
Dandelion Mané
24cf35da22
Change src/v3/ to src/ and remove v3 naming (#474)
Test plan:
`git grep -i v3` only shows incidental hits in longer strings
`yarn travis --full` passes
`yarn backend` works
`yarn build` works
`yarn start` works
`node bin/sourcecred.js start` works
`node bin/sourcecred.js load sourcecred example-github` works

Paired with @wchargin
2018-06-30 16:01:54 -07:00
Dandelion Mané
ba721a6fbb
Fork project to v1/ and v2/ in preparation for v3 (#327)
We want to reset some of our basic assumptions, and make `Graph` into a
pure graph implementation, rather than a hybrid graph and key-value
store.

This is a substantial rewrite, so we want to start from scratch in a v3/
directory and pull code into v3 as necessary. So that we can do this in
a relatively clean fashion, we're first moving the v1 and v2 code into
their own directories.

Paired with @wchargin

Test plan:  Travis, and `yarn backend`, `node bin/sourcecred.js start`.

Note that `yarn backend` and `node bin/sourcecred.js start` both use the
v1 versions. We'll migrate those (by changing paths.js) to v3 when
appropriate.
2018-06-01 17:17:44 -07:00
Dandelion Mané
1fc860bd56
Add data versioning utilities (#292)
This commit adds the `src/util/compat` module, which is responsible for
data compatibility. It provides two methods: `toCompat` and
`fromCompat`.

`toCompat` allows an object to be versioned with a type and version
string. Doing so wraps the object in an array whose first element has
`version` and `type` fields.

`fromCompat` allows loading compatibilized data. It takes a `type` and
`version` expectation, as well as optional processors for various data
versions. It throws an error if the data was not compatibilized, or if
it is the wrong type, or if it has an unsupported version.

The versioning is designed to be composable; see the final test block
for an example of loading a structure with nested versioning.

Test plan: Carefully inspect the included unit tests, and feel free to
propose more.

For context, see #280.
2018-05-21 11:21:05 -07:00