-
Notifications
You must be signed in to change notification settings - Fork 3
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
Initial PR #3
Initial PR #3
Changes from 44 commits
db7dea6
1be19e0
332527e
7a93834
6251345
aa367cc
e603535
a0c9066
a454568
2bd7b57
725845c
600baca
47beacb
502eebd
ae51106
adf4e6f
3fbdf34
dd7977f
1b52787
ea3d441
afeb3aa
2910165
815349a
34ef3fd
3b1f3e5
809d2da
00387fa
dcb81e7
51f13c9
551395c
dcc2df2
7e8ce85
69a1840
5ce9ada
bbee16b
4e28128
9031b74
3f700ab
accdf45
b3ef66b
7a8e54c
e6bd349
0fb99ff
4d6dbd1
8ebd50d
5f42911
7d6df8a
4dee2e3
90f4a47
e7efb93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/coverage/ | ||
/node_modules/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Contributing | ||
|
||
Note: __README.md__ is generated from comments in __index.js__. Do not modify | ||
__README.md__ directly. | ||
|
||
1. Update local master branch: | ||
|
||
$ git checkout master | ||
$ git pull upstream master | ||
|
||
2. Create feature branch: | ||
|
||
$ git checkout -b feature-x | ||
|
||
3. Make one or more atomic commits, and ensure that each commit has a | ||
descriptive commit message. Commit messages should be line wrapped | ||
at 72 characters. | ||
|
||
4. Run `make lint test`, and address any errors. Preferably, fix commits | ||
in place using `git rebase` or `git commit --amend` to make the changes | ||
easier to review. | ||
|
||
5. Push: | ||
|
||
$ git push origin feature-x | ||
|
||
6. Open a pull request. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2016 Sanctuary | ||
Copyright (c) 2015 Simon Friis Vindum | ||
|
||
Permission is hereby granted, free of charge, to any person | ||
obtaining a copy of this software and associated documentation | ||
files (the "Software"), to deal in the Software without | ||
restriction, including without limitation the rights to use, | ||
copy, modify, merge, publish, distribute, sublicense, and/or | ||
sell copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following | ||
conditions: | ||
|
||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
ESLINT = node_modules/.bin/eslint --config node_modules/sanctuary-style/eslint-es6.json --env es6 | ||
ISTANBUL = node_modules/.bin/istanbul | ||
NPM = npm | ||
TRANSCRIBE = node_modules/.bin/transcribe | ||
XYZ = node_modules/.bin/xyz --repo [email protected]:sanctuary-js/sanctuary-union-type.git --script scripts/prepublish | ||
|
||
|
||
.PHONY: all | ||
all: LICENSE README.md | ||
|
||
.PHONY: LICENSE | ||
LICENSE: | ||
cp -- '$@' '[email protected]' | ||
sed 's/Copyright (c) .* Sanctuary/Copyright (c) $(shell git log --date=format:%Y --pretty=format:%ad | sort -r | head -n 1) Sanctuary/' '[email protected]' >'$@' | ||
rm -- '[email protected]' | ||
|
||
README.md: index.js | ||
$(TRANSCRIBE) \ | ||
--heading-level 4 \ | ||
--url 'https://github.com/sanctuary-js/sanctuary-union-type/blob/v$(VERSION)/index.js#L{line}' \ | ||
-- '$<' \ | ||
| LC_ALL=C sed 's/<h4 name="\(.*\)#\(.*\)">\(.*\)\1#\2/<h4 name="\1.prototype.\2">\3\1#\2/' >'$@' | ||
|
||
|
||
.PHONY: lint | ||
lint: | ||
$(ESLINT) --env node -- index.js | ||
$(ESLINT) --env node --env mocha -- test/index.js | ||
|
||
|
||
.PHONY: release-major release-minor release-patch | ||
release-major release-minor release-patch: | ||
@$(XYZ) --increment $(@:release-%=%) | ||
|
||
|
||
.PHONY: setup | ||
setup: | ||
$(NPM) install | ||
|
||
|
||
.PHONY: test | ||
test: | ||
$(ISTANBUL) cover node_modules/.bin/_mocha -- --ui tdd -- test/index.js | ||
$(ISTANBUL) check-coverage --branches 100 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
dependencies: | ||
override: | ||
- printf '%s\n' color=false progress=false >.npmrc | ||
- make setup | ||
|
||
machine: | ||
node: | ||
version: 6.1.0 | ||
|
||
test: | ||
override: | ||
- make lint test |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
'use strict'; | ||
|
||
const $ = require('sanctuary-def'); | ||
const Z = require('sanctuary-type-classes'); | ||
|
||
|
||
// stripNamespace :: String -> String | ||
const stripNamespace = s => s.slice(s.indexOf('/') + 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What should happen if input is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. I've been assuming type identifiers contain one slash ( |
||
|
||
// values :: Any -> Array a | ||
const values = o => | ||
Array.isArray(o) ? o : Z.map(k => o[k], Object.keys(o)); | ||
|
||
// zipObj :: (Array String, Array a) -> StrMap a | ||
const zipObj = (ks, vs) => | ||
ks.reduce((acc, k, idx) => { acc[k] = vs[idx]; return acc; }, {}); | ||
|
||
const a = $.TypeVariable('a'); | ||
|
||
const createIterator = function() { | ||
return { | ||
idx: 0, | ||
val: this, | ||
next() { | ||
const keys = this.val._keys; | ||
return this.idx === keys.length ? | ||
{done: true} : | ||
// eslint-disable-next-line no-plusplus | ||
{value: this.val[keys[this.idx++]]}; | ||
}, | ||
}; | ||
}; | ||
|
||
const staticCase = (options, b, ...args) => | ||
b._name in options ? | ||
options[b._name](...Z.concat(Z.map(k => b[k], b._keys), args)) : | ||
options._(b); | ||
|
||
const ObjConstructorOf = (prototype, keys, name, r) => | ||
Object.assign(Object.create(prototype), r, { | ||
_keys: keys, | ||
_name: name, | ||
[Symbol.iterator]: createIterator, | ||
}); | ||
|
||
const CreateCaseConstructor = (def, prototype, typeName, cases, k) => { | ||
const unprefixedTypeName = stripNamespace(typeName); | ||
const type = cases[k]; | ||
const isArray = Array.isArray(type); | ||
const keys = Object.keys(type); | ||
const types = isArray ? type : values(type); | ||
const recordType = $.RecordType(isArray ? zipObj(keys, types) : type); | ||
|
||
return { | ||
[`${k}Of`]: | ||
def(`${unprefixedTypeName}.${k}Of`, | ||
{}, | ||
[recordType, recordType], | ||
t => ObjConstructorOf(prototype, keys, k, t)), | ||
[k]: isArray && type.length === 0 ? | ||
ObjConstructorOf(prototype, keys, k, {}) : | ||
def(`${unprefixedTypeName}.${k}`, | ||
{}, | ||
Z.concat(types, [recordType]), | ||
(...args) => | ||
ObjConstructorOf(prototype, keys, k, zipObj(keys, args))), | ||
}; | ||
}; | ||
|
||
|
||
module.exports = opts => { | ||
|
||
const def = $.create(opts); | ||
|
||
const CreateUnionType = (typeName, _cases, prototype) => { | ||
const unprefixedTypeName = stripNamespace(typeName); | ||
// Type :: Type | ||
const Type = $.NullaryType( | ||
typeName, | ||
x => x != null && x['@@type'] === typeName | ||
); | ||
const keys = Object.keys(_cases); | ||
const env = Z.concat(opts.env, [Type]); | ||
const def = $.create({checkTypes: opts.checkTypes, env}); | ||
const cases = | ||
Z.map(xs => Z.map(x => x === undefined ? Type : x, xs), | ||
_cases); | ||
const constructors = | ||
Z.map(k => CreateCaseConstructor(def, prototype, typeName, cases, k), | ||
keys); | ||
const caseRecordType = | ||
$.RecordType(Z.map(x => $.Function(Z.concat(values(x), [a])), cases)); | ||
|
||
const instanceCaseDef = | ||
def(`${unprefixedTypeName}::case`, | ||
{}, | ||
[caseRecordType, a], | ||
function(t) { return staticCase(t, this); }); | ||
|
||
Type.prototype = Object.assign(prototype, { | ||
'@@type': typeName, | ||
case: function(o, ...args) { | ||
return '_' in o ? | ||
staticCase.apply(null, [o, this]) : | ||
instanceCaseDef.apply(this, Z.concat([o], args)); | ||
}, | ||
env, | ||
}); | ||
|
||
Type.prototype.case.toString = | ||
Type.prototype.case.inspect = instanceCaseDef.toString; | ||
|
||
const staticCaseDef = | ||
def(`${unprefixedTypeName}.case`, | ||
{}, | ||
[caseRecordType, Type, a], | ||
staticCase); | ||
|
||
Type.case = function(o, ..._args) { | ||
const args = Z.concat([o], _args); | ||
return '_' in o ? | ||
def('anonymous', {}, [$.Any, $.Any, $.Any], staticCase)(...args) : | ||
staticCaseDef.apply(this, args); | ||
}; | ||
|
||
Type.case.toString = | ||
Type.case.inspect = staticCaseDef.toString; | ||
|
||
return Object.assign(Type, ...constructors); | ||
}; | ||
|
||
const Named = | ||
def('UnionType.Named', | ||
{}, | ||
[$.String, $.StrMap($.Any), $.Any], | ||
(typeName, _cases) => CreateUnionType(typeName, _cases, {})); | ||
|
||
const Anonymous = | ||
def('UnionType.Anonymous', | ||
{}, | ||
[$.StrMap($.Any), $.Any], | ||
enums => | ||
CreateUnionType(`(${Object.keys(enums).join(' | ')})`, enums, {})); | ||
|
||
const Class = | ||
def('UnionType.Class', | ||
{}, | ||
[$.String, $.StrMap($.Any), $.Object, $.Any], | ||
CreateUnionType); | ||
|
||
return {Anonymous, Named, Class}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{ | ||
"name": "sanctuary-union-type", | ||
"version": "0.0.0", | ||
"description": "Descendant of paldepind/union-type with more descriptive error messages", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/sanctuary-js/sanctuary-union-type.git" | ||
}, | ||
"scripts": { | ||
"test": "make lint test" | ||
}, | ||
"dependencies": { | ||
"sanctuary-def": "github:sanctuary-js/sanctuary-def", | ||
"sanctuary-type-classes": "0.3.x" | ||
}, | ||
"devDependencies": { | ||
"eslint": "2.9.x", | ||
"istanbul": "0.4.x", | ||
"mocha": "3.x.x", | ||
"ramda": "0.22.x", | ||
"sanctuary-style": "0.3.x", | ||
"transcribe": "0.5.x", | ||
"xyz": "1.1.x" | ||
}, | ||
"files": [ | ||
"/LICENSE", | ||
"/README.md", | ||
"/index.js", | ||
"/package.json" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/usr/bin/env bash | ||
set -e | ||
|
||
rm -f README.md | ||
make | ||
git add LICENSE README.md |
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.
Should we include the following as well?
If you just drew inspiration from union-type this isn't necessary, but if you used its source code as a starting point I believe Simon has copyright. Fortunately union-type is MIT-licensed. :)
/cc @paldepind
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.
Let's add Copyright for Simon (unless he objects), I didn't reference the source until the final stages but the API design is his.
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.
⚡