diff --git a/.travis.yml b/.travis.yml index b6ced1c..c9b4d7c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,11 @@ node_js: - "4" before_install: + - bash ci/install-capnproto.sh - curl -o- -L https://yarnpkg.com/install.sh | bash -s - - export PATH="$HOME/.yarn/bin:$PATH" + - export PATH="$HOME/opt/bin:$HOME/.yarn/bin:$PATH" install: - yarn --frozen-lockfile - - yarn run bootstrap -- --frozen-lockfile script: yarn run ci @@ -20,5 +20,7 @@ cache: yarn: true directories: - node_modules + - js-examples/node_modules - packages/capnp-ts/node_modules - packages/capnpc-ts/node_modules + - packages/capnpc-js/node_modules diff --git a/.vscode/settings.json b/.vscode/settings.json index 0775803..cfbabb6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,8 +7,12 @@ "**/CVS": true, "**/.DS_Store": true, ".nyc_output": true, - "coverage": true, - "packages/**/lib": true, - "packages/**/lib-test": true + "coverage": true + }, + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/lib": true, + "**/lib-test": true } } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fea9a99..af1f03e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,7 @@ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "0.1.0", - "command": "make", + "command": "gulp", "isShellCommand": true, "showOutput": "always", "suppressTaskName": false, diff --git a/HUMANS.md b/HUMANS.md index 3f3cab8..ea34213 100644 --- a/HUMANS.md +++ b/HUMANS.md @@ -8,6 +8,8 @@ - Code ninja: [ishitatsuyuki](https://github.com/ishitatsuyuki) +- Code ninja: [efokschaner](https://github.com/efokschaner) + ## SPECIAL THANKS - Microsoft's dev team (VSCode, TypeScript) diff --git a/README.md b/README.md index 7098a05..8ce044f 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,11 @@ This repository is managed as a monorepo composed of separate packages. |:--------|:--------|:-------------| | [`capnp-ts`](/packages/capnp-ts) | [![npm](https://img.shields.io/npm/v/capnp-ts.svg?maxAge=2592000)](https://www.npmjs.com/package/capnp-ts) | [![Dependency Status](https://david-dm.org/jdiaz5513/capnp-ts.svg?path=packages/capnp-ts)](https://david-dm.org/jdiaz5513/capnp-ts?path=packages/capnp-ts) | | [`capnpc-ts`](/packages/capnpc-ts) | [![npm](https://img.shields.io/npm/v/capnpc-ts.svg?maxAge=2592000)](https://www.npmjs.com/package/capnpc-ts) | [![Dependency Status](https://david-dm.org/jdiaz5513/capnpc-ts.svg?path=packages/capnpc-ts)](https://david-dm.org/jdiaz5513/capnpc-ts?path=packages/capnpc-ts) | +| [`capnpc-js`](/packages/capnpc-js) | [![npm](https://img.shields.io/npm/v/capnpc-js.svg?maxAge=2592000)](https://www.npmjs.com/package/capnpc-js) | [![Dependency Status](https://david-dm.org/jdiaz5513/capnpc-js.svg?path=packages/capnpc-js)](https://david-dm.org/jdiaz5513/capnpc-js?path=packages/capnpc-js) | - `capnp-ts` is the core Cap'n Proto library for Typescript. It is a required import for all compiled schema files, and the starting point for reading/writing a Cap'n Proto message. -- `capnpc-ts` is the schema compiler. It is intended to be invoked by the [`capnp`](https://capnproto.org/capnp-tool.html) tool. +- `capnpc-ts` is the schema compiler plugin for TypeScript. It is intended to be invoked by the [`capnp`](https://capnproto.org/capnp-tool.html) tool. +- `capnpc-js` is the schema compiler plugin for JavaScript. It is intended to be invoked by the [`capnp`](https://capnproto.org/capnp-tool.html) tool. ## Project Status @@ -73,20 +75,27 @@ npm install --save capnp-ts You may want the schema compiler as well (can also be installed locally): ```shell -npm install -g capnpc-ts +npm install -g capnpc-ts # For TypeScript +# OR +npm install -g capnpc-js # For JavaScript ``` The schema compiler is a [Cap'n Proto plugin](https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) and requires the `capnpc` binary in order to do anything useful; follow the [Cap'n Proto installation instructions](https://capnproto.org/install.html) to install it on your system. ## Usage -Run the following to compile a schema file into Typescript source code: +Run the following to compile a schema file into TypeScript source code: ```shell capnpc -ots path/to/myschema.capnp ``` -Running that command will create a file named `path/to/myschema.capnp.ts`. +Or for JavaScript: +```shell +capnpc -ojs path/to/myschema.capnp +``` + +Running that command will create a file named `path/to/myschema.capnp.ts` (or `.js`). > This assumes `capnpc-ts` was installed globally and is available from `$PATH`. If not, change the `-o` option to something like `-onode_modules/.bin/capnpc-ts` so it points to your local `capnpc-ts` install. @@ -108,7 +117,19 @@ export function loadMessage(buffer: ArrayBuffer): MyStruct { ### Usage with JavaScript -JavaScript is not **yet** fully supported; the `capnp-ts` library itself can be imported as ES5 JavaScript, but the schema compiler is not yet able to transpile the emitted TypeScript schema file into JavaScript. One may do so manually, if feeling particularly adventurous. +```javascript +const capnp = require('capnp-ts'); + +const MyStruct = require('./myschema.capnp').MyStruct; + +function loadMessage(buffer) { + + const message = capnp.Message.fromArrayBuffer(buffer); + + return message.getRoot(MyStruct); + +} +``` ### Usage in a Web Browser @@ -131,14 +152,7 @@ Before building the source you will need a few prerequisites: ### Initial Setup -Run the following commands to set up the **node_modules** directories for the monorepo and each package: - -```shell -yarn install -npm run bootstrap -``` - -Bootstrap only needs to be run once; run `yarn install` again any time the packages are updated. +Run `yarn install` to set up the **node_modules** directories for the monorepo and each package. ### Build Tasks @@ -153,6 +167,7 @@ npm run build Or (preferred) using [gulp-cli](https://github.com/gulpjs/gulp-cli): ```shell +npm install --global gulp-cli # If you don't already have gulp-cli gulp build ``` diff --git a/ci/install-capnproto.sh b/ci/install-capnproto.sh new file mode 100644 index 0000000..74511e4 --- /dev/null +++ b/ci/install-capnproto.sh @@ -0,0 +1,12 @@ +#! /usr/bin/env bash +# +# Installs capnproto from a release tarball (because the versions in apt is too old) + +set -exuo pipefail + +curl -O https://capnproto.org/capnproto-c++-0.6.1.tar.gz +tar zxf capnproto-c++-0.6.1.tar.gz +cd capnproto-c++-0.6.1 +./configure --prefix=$HOME/opt +make -j6 +make install diff --git a/configs/capnpc-js/tsconfig-lib-test.json b/configs/capnpc-js/tsconfig-lib-test.json new file mode 100644 index 0000000..ac7b6fb --- /dev/null +++ b/configs/capnpc-js/tsconfig-lib-test.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "outDir": "../../packages/capnpc-js/lib-test", + "rootDir": "../../packages/capnpc-js/test" + }, + "extends": "../tsconfig-base", + "include": [ + "../../packages/capnpc-js/test/**/*.ts" + ] +} diff --git a/configs/capnpc-js/tsconfig-lib.json b/configs/capnpc-js/tsconfig-lib.json new file mode 100644 index 0000000..cd98460 --- /dev/null +++ b/configs/capnpc-js/tsconfig-lib.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "declaration": true, + "outDir": "../../packages/capnpc-js/lib", + "rootDir": "../../packages/capnpc-js/src" + }, + "extends": "../tsconfig-base", + "include": [ + "../../packages/capnpc-js/src/**/*.ts" + ] +} diff --git a/gulpfile.js b/gulpfile.js index 9a5f2c7..da3f01d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -25,6 +25,11 @@ gulp.task('build:capnpc-ts:lib', ['build:capnp-ts:lib'], function () { return build('configs/capnpc-ts/tsconfig-lib.json'); }); +/** Build the capnpc-js schema compiler. */ +gulp.task('build:capnpc-js:lib', ['build:capnp-ts:lib', 'build:capnpc-ts:lib'], function () { + return build('configs/capnpc-js/tsconfig-lib.json'); +}); + /** Build tests for capnp-ts. */ gulp.task('build:capnp-ts:test', ['build:capnp-ts:lib'], function () { return build('configs/capnp-ts/tsconfig-lib-test.json'); @@ -35,11 +40,16 @@ gulp.task('build:capnpc-ts:test', ['build:capnpc-ts:lib'], function () { return build('configs/capnpc-ts/tsconfig-lib-test.json'); }); +/** Build tests for capnpc-js. */ +gulp.task('build:capnpc-js:test', ['build:capnpc-js:lib'], function () { + return build('configs/capnpc-js/tsconfig-lib-test.json'); +}); + /** Main build task (does not build tests). */ -gulp.task('build', ['build:capnp-ts:lib', 'build:capnpc-ts:lib']); +gulp.task('build', ['build:capnp-ts:lib', 'build:capnpc-ts:lib', 'build:capnpc-js:lib']); /** Build all tests. */ -gulp.task('build-test', ['build:capnp-ts:test', 'build:capnpc-ts:test']); +gulp.task('build-test', ['build:capnp-ts:test', 'build:capnpc-ts:test', 'build:capnpc-js:test']); function test(src, coverage) { var options = glob.sync(src).concat('-J'); @@ -62,11 +72,16 @@ gulp.task('test:capnpc-ts', ['build:capnpc-ts:test'], function () { return test('packages/capnpc-ts/lib-test/**/*.spec.js', false); }); +/** Run tests for the capnpc-js schema compiler. */ +gulp.task('test:capnpc-js', ['build:capnpc-js:test'], function () { + return test('packages/capnpc-js/lib-test/**/*.spec.js', false); +}); + /** Run all tests. */ -gulp.task('test', ['test:capnp-ts', 'test:capnpc-ts']); +gulp.task('test', ['test:capnp-ts', 'test:capnpc-ts', 'test:capnpc-ts']); /** Run all tests with test coverage. */ -gulp.task('test-cov', ['build:capnp-ts:test', 'build:capnpc-ts:test'], function () { +gulp.task('test-cov', ['build:capnp-ts:test', 'build:capnpc-ts:test', 'build:capnpc-js:test'], function () { return test('packages/*/lib-test/**/*.spec.js', true); }); diff --git a/js-examples/README.md b/js-examples/README.md new file mode 100644 index 0000000..800a60e --- /dev/null +++ b/js-examples/README.md @@ -0,0 +1,3 @@ +Example of using `capnp-ts` in a JavaScript project. This is just a JavaScript version of [the official C++ samples](https://github.com/capnproto/capnproto/tree/master/c%2B%2B/samples) + +See `test.sh` for how to run them. \ No newline at end of file diff --git a/js-examples/addressbook.capnp b/js-examples/addressbook.capnp new file mode 100644 index 0000000..6f1c36d --- /dev/null +++ b/js-examples/addressbook.capnp @@ -0,0 +1,52 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# 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. + +@0xef1b5abe02e1f8d4; + +struct Person { + id @0 :UInt32; + name @1 :Text; + email @2 :Text; + phones @3 :List(PhoneNumber); + + struct PhoneNumber { + number @0 :Text; + type @1 :Type; + + enum Type { + mobile @0; + home @1; + work @2; + } + } + + employment :union { + unemployed @4 :Void; + employer @5 :Text; + school @6 :Text; + selfEmployed @7 :Void; + # We assume that a person is only one of these. + } +} + +struct AddressBook { + people @0 :List(Person); +} diff --git a/js-examples/addressbook.js b/js-examples/addressbook.js new file mode 100644 index 0000000..38c36cf --- /dev/null +++ b/js-examples/addressbook.js @@ -0,0 +1,145 @@ +// Ported from the C++ version at: +// https://github.com/capnproto/capnproto/blob/db268884b372989bac511b2eff737d1b6ce4423c/c%2B%2B/samples/addressbook.c%2B%2B + +// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// 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. + +"use strict"; + +const capnp = require('capnp-ts'); +const addressbookSchemas = require('./addressbook.capnp.js'); + +// No destructuring assignment in node 4.0 +const AddressBook = addressbookSchemas.AddressBook; +const Person = addressbookSchemas.Person; +const Person_Employment = addressbookSchemas.Person_Employment; +const Person_PhoneNumber = addressbookSchemas.Person_PhoneNumber; +const Person_PhoneNumber_Type = addressbookSchemas.Person_PhoneNumber_Type; + +function writePackedMessageToStream(writeStream, message) { + const arrayBuffer = message.toPackedArrayBuffer(); + // Beacause streams can't handle ArrayBuffers + const buffer = new Buffer(arrayBuffer); + writeStream.write(buffer); +} + +function writeAddressBook(writeStream) { + const message = new capnp.Message(); + const addressBook = message.initRoot(AddressBook); + const people = addressBook.initPeople(2); + + const alice = people.get(0); + alice.setId(123); + alice.setName("Alice"); + alice.setEmail("alice@example.com"); + const alicePhones = alice.initPhones(1); + alicePhones.get(0).setNumber("555-1212"); + alicePhones.get(0).setType(Person_PhoneNumber_Type.MOBILE); + alice.getEmployment().setSchool("MIT"); + + const bob = people.get(1); + bob.setId(456); + bob.setName("Bob"); + bob.setEmail("bob@example.com"); + const bobPhones = bob.initPhones(2); + bobPhones.get(0).setNumber("555-4567"); + bobPhones.get(0).setType(Person_PhoneNumber_Type.HOME); + bobPhones.get(1).setNumber("555-7654"); + bobPhones.get(1).setType(Person_PhoneNumber_Type.WORK); + bob.getEmployment().setUnemployed(); + + writePackedMessageToStream(writeStream, message); +} + +function readToEndOfStream(readStream) { + return new Promise(function(resolve, reject) { + let result = new Uint8Array(); + readStream.on('data', function(data) { + const oldLen = result.byteLength; + const newResult = new Uint8Array(oldLen + data.byteLength); + newResult.set(result); + newResult.set(data, oldLen); + result = newResult; + }); + readStream.on('end', function() { + resolve(result); + }); + readStream.on('error', reject); + }); +} + +function printAddressBook(readStream) { + return readToEndOfStream(readStream).then(function(data) { + const message = capnp.Message.fromPackedArrayBuffer(data); + const addressBook = message.getRoot(AddressBook); + addressBook.getPeople().forEach(function(person) { + console.log(person.getName() + ': ' + person.getEmail()); + person.getPhones().forEach(function(phone) { + let phoneTypeString = Person_PhoneNumber_Type[phone.getType()]; + console.log(' ' + phoneTypeString + ' phone: ' + phone.getNumber()); + }); + const employment = person.getEmployment(); + switch (employment.which()) { + case Person_Employment.UNEMPLOYED: + console.log(' unemployed'); + break; + case Person_Employment.EMPLOYER: + console.log(' employer: ' + employment.getEmployer()); + break; + case Person_Employment.SCHOOL: + console.log(' student at: ' + employment.getSchool()); + break; + case Person_Employment.SELF_EMPLOYED: + console.log(' self-employed'); + break; + } + }); + }); +} + +function main() { + // TODO Not sure if we have dynamic schema usage available yet + // StructSchema schema = Schema::from(); + if (process.argv.length != 3) { + throw new Error('Missing arg.'); + } else if (process.argv[2] == 'write') { + return writeAddressBook(process.stdout); + } else if (process.argv[2] == 'read') { + return printAddressBook(process.stdin); + } else if (process.argv[2] == 'dwrite') { + console.error('Unimplemented'); + // return dynamicWriteAddressBook(1, schema); + } else if (process.argv[2] == 'dread') { + console.error('Unimplemented'); + // return dynamicPrintMessage(0, schema); + } else { + throw new Error('Invalid arg: ' + process.argv[2]); + } +} + +if (require && require.main === module) { + Promise.resolve(main()).then(function(exitCode) { + process.exit(exitCode); + }).catch(function(error) { + console.error(error); + process.exit(1); + }); +} diff --git a/js-examples/package.json b/js-examples/package.json new file mode 100644 index 0000000..830de91 --- /dev/null +++ b/js-examples/package.json @@ -0,0 +1,28 @@ +{ + "author": "jdiaz5513", + "bugs": { + "url": "https://github.com/jdiaz5513/capnp-ts/issues" + }, + "dependencies": { + "capnp-ts": "0.0.1" + }, + "description": "Example of using capnproto-ts in a JavaScript project.", + "devDependencies": { + "capnpc-js": "0.0.1" + }, + "homepage": "https://github.com/jdiaz5513/capnp-ts#readme", + "keywords": [ + "capnp", + "rpc", + "typescript", + "example" + ], + "license": "MIT", + "name": "capnproto-ts/js-examples", + "private": true, + "repository": { + "type": "git", + "url": "git+https://github.com/jdiaz5513/capnp-ts.git" + }, + "version": "0.0.1" +} diff --git a/js-examples/test.sh b/js-examples/test.sh new file mode 100755 index 0000000..92896c2 --- /dev/null +++ b/js-examples/test.sh @@ -0,0 +1,27 @@ +#! /usr/bin/env bash +# +# Quick script that compiles and runs the samples, then cleans up. +# Used for release testing. + +set -exuo pipefail + +cd `dirname $0` + +capnpc -o node_modules/.bin/capnpc-js addressbook.capnp +node addressbook.js write | node addressbook.js read +node addressbook.js dwrite | node addressbook.js dread +rm -f addressbook.capnp.js addressbook.capnp.ts + +# Calculator example not yet implemented +# capnpc -oc++ calculator.capnp +# c++ -std=c++11 -Wall calculator-client.c++ calculator.capnp.c++ \ +# $(pkg-config --cflags --libs capnp-rpc) -o calculator-client +# c++ -std=c++11 -Wall calculator-server.c++ calculator.capnp.c++ \ +# $(pkg-config --cflags --libs capnp-rpc) -o calculator-server +# rm -f /tmp/capnp-calculator-example-$$ +# ./calculator-server unix:/tmp/capnp-calculator-example-$$ & +# sleep 0.1 +# ./calculator-client unix:/tmp/capnp-calculator-example-$$ +# kill %+ +# wait %+ || true +# rm calculator-client calculator-server calculator.capnp.c++ calculator.capnp.h /tmp/capnp-calculator-example-$$ \ No newline at end of file diff --git a/lerna.json b/lerna.json index 7c9333f..16ec158 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,8 @@ { "lerna": "2.0.0-rc.4", "packages": [ - "packages/*" + "packages/*", + "js-examples" ], "npmClient": "yarn", "version": "0.0.1" diff --git a/package.json b/package.json index 26010b7..17e1859 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,8 @@ }, "description": "Strongly typed Cap'n Proto implementation for the browser and Node.js using TypeScript", "devDependencies": { - "@types/benchmark": "1.0.30", - "@types/debug": "0.0.29", - "@types/node": "^8.0.11", - "@types/ramda": "^0.24.3", "codecov": "^2.2.0", + "glob": "^7.1.2", "gulp": "^3.9.1", "gulp-tslint": "^8.1.1", "lerna": "^2.0.0", @@ -35,18 +32,19 @@ "url": "git+https://github.com/jdiaz5513/capnp-ts.git" }, "scripts": { - "bootstrap": "lerna bootstrap", + "bootstrap": "lerna bootstrap --hoist", "benchmark": "gulp benchmark", "build": "gulp build", - "ci": "gulp lint && gulp coverage && codecov --disable=gcov", + "ci": "gulp lint && gulp coverage && codecov --disable=gcov && js-examples/test.sh", "coverage": "gulp coverage", + "lerna": "lerna", "lint": "gulp lint", + "postinstall": "npm run bootstrap", "test": "gulp test", "watch": "gulp watch" }, "typings": "lib/index", "version": "0.0.1", "dependencies": { - "glob": "^7.1.2" } } diff --git a/packages/capnp-ts/package.json b/packages/capnp-ts/package.json index cbc3ecc..73f68f0 100644 --- a/packages/capnp-ts/package.json +++ b/packages/capnp-ts/package.json @@ -11,8 +11,11 @@ }, "description": "Strongly typed Cap'n Proto implementation for the browser and Node.js using TypeScript", "devDependencies": { + "@types/benchmark": "^1.0.30", + "@types/debug": "0.0.29", + "@types/node": "^7.0.18", "benchmark": "^2.1.4", - "tap": "^10.3.2", + "tap": "^10.7.0", "testcheck": "^1.0.0-rc.2" }, "homepage": "https://github.com/jdiaz5513/capnp-ts#readme", diff --git a/packages/capnpc-js/bin/capnpc-js.js b/packages/capnpc-js/bin/capnpc-js.js new file mode 100755 index 0000000..06ac042 --- /dev/null +++ b/packages/capnpc-js/bin/capnpc-js.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +require('../lib').main(); diff --git a/packages/capnpc-js/bin/capnpc-js.ts b/packages/capnpc-js/bin/capnpc-js.ts new file mode 100755 index 0000000..310627b --- /dev/null +++ b/packages/capnpc-js/bin/capnpc-js.ts @@ -0,0 +1,6 @@ +#!/usr/bin/env ts-node + +import 'source-map-support/register'; +import {main} from '../src'; + +main(); diff --git a/packages/capnpc-js/package.json b/packages/capnpc-js/package.json new file mode 100644 index 0000000..f5d27f5 --- /dev/null +++ b/packages/capnpc-js/package.json @@ -0,0 +1,36 @@ +{ + "author": "jdiaz5513", + "bin": { + "capnpc-js": "./bin/capnpc-js.js" + }, + "bugs": { + "url": "https://github.com/jdiaz5513/capnp-ts/issues" + }, + "dependencies": { + "capnpc-ts": "0.0.1", + "debug": "^2.6.3", + "typescript": "^2.4.1" + }, + "description": "Cap'n Proto schema compiler for JavaScript.", + "devDependencies": { + "@types/debug": "0.0.29", + "@types/node": "^7.0.18", + "source-map-support": "^0.4.15", + "tap": "^10.7.0" + }, + "homepage": "https://github.com/jdiaz5513/capnp-ts#readme", + "keywords": [ + "capnp", + "rpc", + "typescript" + ], + "license": "MIT", + "main": "lib/index", + "name": "capnpc-js", + "repository": { + "type": "git", + "url": "git+https://github.com/jdiaz5513/capnp-ts.git" + }, + "typings": "lib/index", + "version": "0.0.1" +} diff --git a/packages/capnpc-js/src/index.ts b/packages/capnpc-js/src/index.ts new file mode 100644 index 0000000..f8d9f30 --- /dev/null +++ b/packages/capnpc-js/src/index.ts @@ -0,0 +1,92 @@ +import initTrace from 'debug'; + +import * as fs from 'fs'; + +import * as ts from 'typescript'; + +import * as capnpc_ts from 'capnpc-ts'; + +const trace = initTrace('capnpc'); +trace('load'); + +/** + * The equivalent of tsconfig.json used when compiling the emitted .ts file to .js. + * + * The output of this tool should aim to be readable, documented javascript + * for the developers consuming it. They can (and probably already do) transpile + * the JS further to meet whatever ES version / module system / minification + * needs they have. + */ +const COMPILE_OPTIONS: ts.CompilerOptions = { + module: ts.ModuleKind.None, + moduleResolution: ts.ModuleResolutionKind.NodeJs, + noEmitOnError: true, + noFallthroughCasesInSwitch: true, + noImplicitReturns: true, + noUnusedLocals: true, + noUnusedParameters: true, + preserveConstEnums: true, + removeComments: false, + sourceMap: false, + strict: true, + stripInternal: true, + target: ts.ScriptTarget.ES2015, +}; + +export async function main() { + return capnpc_ts.run().then((ctx) => { + transpileAll(ctx); + }).thenReturn().tapCatch((reason) => { + // tslint:disable-next-line:no-console + console.error(reason); + process.exit(1); + }); +} + +export function transpileAll(ctx: capnpc_ts.CodeGeneratorContext): void { + + trace('transpileAll()', ctx.files); + + const tsFilePaths = ctx.files.map((f) => f.tsPath); + + const program = ts.createProgram(tsFilePaths, COMPILE_OPTIONS); + + const emitResult = program.emit(); + + if (!emitResult.emitSkipped) { + + trace('emit succeeded'); + + tsFilePaths.forEach(fs.unlinkSync); + + } else { + + trace('emit failed'); + + const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + allDiagnostics.forEach((diagnostic) => { + + const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); + + if (diagnostic.file && diagnostic.start) { + + const {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); + + /* tslint:disable-next-line:no-console */ + console.log(`${diagnostic.file.fileName}:${line + 1}:${character + 1} ${message}`); + + } else { + + /* tslint:disable-next-line:no-console */ + console.log(`==> ${message}`); + + } + + }); + + throw new Error(capnpc_ts.errors.GEN_TS_EMIT_FAILED); + + } + +} diff --git a/packages/capnpc-js/test/index.spec.ts b/packages/capnpc-js/test/index.spec.ts new file mode 100644 index 0000000..3d38fc4 --- /dev/null +++ b/packages/capnpc-js/test/index.spec.ts @@ -0,0 +1,9 @@ +import 'source-map-support/register'; + +import {tap} from './util'; + +tap.test('test of a test', (t) => { + + t.end(); + +}); diff --git a/packages/capnpc-js/test/util/index.ts b/packages/capnpc-js/test/util/index.ts new file mode 100644 index 0000000..e2596cb --- /dev/null +++ b/packages/capnpc-js/test/util/index.ts @@ -0,0 +1 @@ +export {default as tap} from './tap'; diff --git a/packages/capnpc-js/test/util/tap.ts b/packages/capnpc-js/test/util/tap.ts new file mode 100644 index 0000000..88977d5 --- /dev/null +++ b/packages/capnpc-js/test/util/tap.ts @@ -0,0 +1,241 @@ +/** + * Dirty workaround that's necessary until https://github.com/tapjs/node-tap/pull/256 lands. + * + * @author jdiaz5513 + */ + +/* tslint:disable:no-any promise-function-async no-unsafe-any no-var-requires */ + +export declare class Test { + + // Assertions + ok: Assertions.Basic; + true: Assertions.Basic; + assert: Assertions.Basic; + + notOk: Assertions.Basic; + false: Assertions.Basic; + assertNot: Assertions.Basic; + + error: Assertions.Basic; + ifErr: Assertions.Basic; + ifError: Assertions.Basic; + + throws: Assertions.Throws; + throw: Assertions.Throws; + + doesNotThrow: Assertions.DoesNotThrow; + notThrow: Assertions.DoesNotThrow; + + equal: Assertions.Equal; + equals: Assertions.Equal; + isEqual: Assertions.Equal; + is: Assertions.Equal; + strictEqual: Assertions.Equal; + strictEquals: Assertions.Equal; + strictIs: Assertions.Equal; + isStrict: Assertions.Equal; + isStrictly: Assertions.Equal; + + notEqual: Assertions.NotEqual; + notEquals: Assertions.NotEqual; + inequal: Assertions.NotEqual; + notStrictEqual: Assertions.NotEqual; + notStrictEquals: Assertions.NotEqual; + isNotEqual: Assertions.NotEqual; + isNot: Assertions.NotEqual; + doesNotEqual: Assertions.NotEqual; + isInequal: Assertions.NotEqual; + + same: Assertions.Equal; + equivalent: Assertions.Equal; + looseEqual: Assertions.Equal; + looseEquals: Assertions.Equal; + deepEqual: Assertions.Equal; + deepEquals: Assertions.Equal; + isLoose: Assertions.Equal; + looseIs: Assertions.Equal; + + notSame: Assertions.NotEqual; + inequivalent: Assertions.NotEqual; + looseInequal: Assertions.NotEqual; + notDeep: Assertions.NotEqual; + deepInequal: Assertions.NotEqual; + notLoose: Assertions.NotEqual; + looseNot: Assertions.NotEqual; + + strictSame: Assertions.Equal; + strictEquivalent: Assertions.Equal; + strictDeepEqual: Assertions.Equal; + sameStrict: Assertions.Equal; + deepIs: Assertions.Equal; + isDeeply: Assertions.Equal; + isDeep: Assertions.Equal; + strictDeepEquals: Assertions.Equal; + + strictNotSame: Assertions.NotEqual; + strictInequivalent: Assertions.NotEqual; + strictDeepInequal: Assertions.NotEqual; + notSameStrict: Assertions.NotEqual; + deepNot: Assertions.NotEqual; + notDeeply: Assertions.NotEqual; + strictDeepInequals: Assertions.NotEqual; + notStrictSame: Assertions.NotEqual; + + match: Assertions.Match; + has: Assertions.Match; + hasFields: Assertions.Match; + matches: Assertions.Match; + similar: Assertions.Match; + like: Assertions.Match; + isLike: Assertions.Match; + includes: Assertions.Match; + include: Assertions.Match; + contains: Assertions.Match; + + notMatch: Assertions.Match; + dissimilar: Assertions.Match; + unsimilar: Assertions.Match; + notSimilar: Assertions.Match; + unlike: Assertions.Match; + isUnlike: Assertions.Match; + notLike: Assertions.Match; + isNotLike: Assertions.Match; + doesNotHave: Assertions.Match; + isNotSimilar: Assertions.Match; + isDissimilar: Assertions.Match; + + type: Assertions.Type; + isa: Assertions.Type; + isA: Assertions.Type; + + constructor(options?: Options.Test); + + tearDown(fn: (a: any) => any): void; + setTimeout(n: number): void; + endAll(): void; + threw(er: Error, extra?: Error, proxy?: Test): void; + pragma(set: Options.Pragma): void; + plan(n: number, comment?: string): void; + test(name: string, extra?: Options.Test, cb?: (t: Test) => Promise | void): Promise; + test(name: string, cb?: (t: Test) => Promise | void): Promise; + current(): Test; + stdin(name: string, extra?: Options.Bag): Promise; + spawn(cmd: string, args: string, options?: Options.Bag, name?: string, extra?: Options.Spawn): Promise; + done(): void; + passing(): boolean; + pass(message?: string, extra?: Options.Assert): boolean; + fail(message?: string, extra?: Options.Assert): boolean; + addAssert(name: string, length: number, fn: (...args: any[]) => boolean): boolean; + comment(message: string, ...args: any[]): void; + bailout(message?: string): void; + beforeEach(fn: (cb: () => any) => Promise | void): void; + afterEach(fn: (cb: () => any) => Promise | void): void; + end(): void; + +} + +// Little hack to simulate the Test class on the tap export. + +export declare interface TestConstructor { + + prototype: Test; + + new(options?: Options.Test): Test; + +} + +export declare interface Tap extends Test { + + Test: TestConstructor; + mocha: Mocha; + + mochaGlobals(): void; + +} + + +export declare namespace Options { + + export interface Bag { + + [propName: string]: any; + + } + + export interface Pragma { + + [propName: string]: boolean; + + } + + export interface Assert extends Bag { + + todo?: boolean | string; + skip?: boolean | string; + + } + + export interface Spawn extends Assert { + + bail?: boolean; + timeout?: number; + + } + + export interface Test extends Assert { + + name?: string; + timeout?: number; + bail?: boolean; + autoend?: boolean; + + } + +} + +export declare namespace Assertions { + export type Basic = + (obj: any, message?: string, extra?: Options.Assert) => boolean; + + export type Throws = + (fn?: (a: any) => any, expectedError?: Error, message?: string, extra?: Options.Assert) => boolean; + + export type DoesNotThrow = + (fn?: (a: any) => any, message?: string, extra?: Options.Assert) => boolean; + + export type Equal = + (found: any, wanted: any, message?: string, extra?: Options.Assert) => boolean; + + export type NotEqual = + (found: any, notWanted: any, message?: string, extra?: Options.Assert) => boolean; + + export type Match = + (found: any, pattern: any, message?: string, extra?: Options.Assert) => boolean; + + export type Type = + (found: any, type: string | Function, message?: string, extra?: Options.Assert) => boolean; +} + +// Super minimal description of returned Promise (which are really Bluebird promises). + +export declare interface Mocha { + + it(name?: string, fn?: (a: any) => any): void; + describe(name?: string, fn?: (a: any) => any): void; + global(): void; + +} + +/** + * Dear everyone on the planet whose device ever runs this code, + * + * I apologize. This is shitty. These next few CPU cycles could have been + * prevented had I not had the need to satisfy the typechecker gods. + * + * @author jdiaz5513 + */ + +const tap = require('tap') as Tap; + +export default tap; diff --git a/packages/capnpc-ts/package.json b/packages/capnpc-ts/package.json index 2ac3ae4..daeebee 100644 --- a/packages/capnpc-ts/package.json +++ b/packages/capnpc-ts/package.json @@ -7,14 +7,18 @@ "url": "https://github.com/jdiaz5513/capnp-ts/issues" }, "dependencies": { + "bluebird": "^3.5.0", "capnp-ts": "0.0.1", "hex2dec": "^1.0.1", "ramda": "^0.24.1", "tslib": "^1.7.1", "typescript": "^2.4.1" }, - "description": "Cap'n Proto schema compilter for capnp-ts.", + "description": "Cap'n Proto schema compiler for TypeScript.", "devDependencies": { + "@types/bluebird": "^3.5.7", + "@types/debug": "0.0.29", + "@types/node": "^7.0.18", "@types/ramda": "^0.24.3", "source-map-support": "^0.4.15", "tap": "^10.7.0" diff --git a/packages/capnpc-ts/src/code-generator-file-context.ts b/packages/capnpc-ts/src/code-generator-file-context.ts index a6c2a76..846b35a 100644 --- a/packages/capnpc-ts/src/code-generator-file-context.ts +++ b/packages/capnpc-ts/src/code-generator-file-context.ts @@ -14,8 +14,6 @@ import * as ts from 'typescript'; export class CodeGeneratorFileContext { - jsPath: string; - sourceMapPath: string; tsPath: string; concreteLists: Array<[string, s.Field]>; file: s.CodeGeneratorRequest_RequestedFile; diff --git a/packages/capnpc-ts/src/compiler.ts b/packages/capnpc-ts/src/compiler.ts index e18a4c0..4e8fa52 100644 --- a/packages/capnpc-ts/src/compiler.ts +++ b/packages/capnpc-ts/src/compiler.ts @@ -5,8 +5,7 @@ import * as ts from 'typescript'; import {CodeGeneratorContext} from './code-generator-context'; import {CodeGeneratorFileContext} from './code-generator-file-context'; -import {COMPILE_OPTIONS, SOURCE_COMMENT} from './constants'; -import * as E from './errors'; +import {SOURCE_COMMENT} from './constants'; import {loadRequestedFile, lookupNode} from './file'; import { generateCapnpImport, @@ -52,43 +51,6 @@ export function printSourceFiles(ctx: CodeGeneratorContext): string[] { } -export function transpileAll(ctx: CodeGeneratorContext): void { - - trace('transpileAll()'); - - const program = ts.createProgram(ctx.files.map((f) => f.tsPath), COMPILE_OPTIONS); - const emitResult = program.emit(); - - if (emitResult.emitSkipped) { - - trace('emit failed'); - - const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); - allDiagnostics.forEach((diagnostic) => { - - const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); - - if (diagnostic.file && diagnostic.start) { - - const {line, character} = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); - /* tslint:disable-next-line */ - console.log(`${diagnostic.file.fileName}:${line + 1}:${character + 1} ${message}`); - - } else { - - /* tslint:disable-next-line */ - console.log(`==> ${message}`); - - } - - }); - - throw new Error(E.GEN_TS_EMIT_FAILED); - - } - -} - export function writeTsFiles(ctx: CodeGeneratorContext): void { trace('writeTsFiles()'); diff --git a/packages/capnpc-ts/src/constants.ts b/packages/capnpc-ts/src/constants.ts index eb7e004..00bdef4 100644 --- a/packages/capnpc-ts/src/constants.ts +++ b/packages/capnpc-ts/src/constants.ts @@ -45,26 +45,6 @@ export const ConcreteListType = { [s.Type.UINT8]: 'capnp.Uint8List', }; -/** - * The equivalent of tsconfig.json used when compiling the emitted .ts file to .js. - * - * TODO: This should be configurable somehow? - */ - -export const COMPILE_OPTIONS: ts.CompilerOptions = { - declaration: true, - module: ts.ModuleKind.UMD, - noEmitOnError: true, - noFallthroughCasesInSwitch: true, - noImplicitReturns: true, - noUnusedLocals: true, - noUnusedParameters: true, - sourceMap: true, - strict: true, - stripInternal: true, - target: ts.ScriptTarget.ES5, -}; - /** export */ export const EXPORT = ts.createToken(ts.SyntaxKind.ExportKeyword); diff --git a/packages/capnpc-ts/src/file.ts b/packages/capnpc-ts/src/file.ts index 3c814e9..1740d91 100644 --- a/packages/capnpc-ts/src/file.ts +++ b/packages/capnpc-ts/src/file.ts @@ -150,8 +150,6 @@ export function loadRequestedFile( ctx.file = file; ctx.nodes = req.getNodes().toArray(); ctx.tsPath = filename + '.ts'; - ctx.jsPath = filename + '.js'; - ctx.sourceMapPath = filename + '.js.map'; ctx.sourceFile = ts.createSourceFile(ctx.tsPath, '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS); ctx.concreteLists = []; ctx.generatedNodeIds = []; diff --git a/packages/capnpc-ts/src/generators.ts b/packages/capnpc-ts/src/generators.ts index 4ebad04..1e2f4e8 100644 --- a/packages/capnpc-ts/src/generators.ts +++ b/packages/capnpc-ts/src/generators.ts @@ -196,6 +196,7 @@ export function generateNode(ctx: CodeGeneratorFileContext, node: s.Node): void } +const listLengthParameterName = 'length'; export function generateStructFieldMethods( ctx: CodeGeneratorFileContext, members: ts.ClassElement[], node: s.Node, field: s.Field): void { @@ -325,11 +326,19 @@ export function generateStructFieldMethods( } + const listClassIdentifier = ts.createIdentifier(listClass); + adopt = true; disown = true; get = ts.createCall( - ts.createPropertyAccess( - THIS, '_getList'), __, [offsetLiteral, ts.createIdentifier(listClass)]); + ts.createPropertyAccess(THIS, '_getList'), + __, + [offsetLiteral, listClassIdentifier]); + has = true; + init = ts.createCall( + ts.createPropertyAccess(THIS, '_initList'), + __, + [offsetLiteral, listClassIdentifier, ts.createIdentifier(listLengthParameterName)]); set = copyFromValue; break; @@ -375,6 +384,8 @@ export function generateStructFieldMethods( default: + // TODO Maybe this should be an error? + break; } @@ -433,7 +444,7 @@ export function generateStructFieldMethods( if (init) { const parameters = whichType === s.Type.DATA || whichType === s.Type.LIST - ? [ts.createParameter(__, __, __, 'length', __, NUMBER_TYPE, __)] + ? [ts.createParameter(__, __, __, listLengthParameterName, __, NUMBER_TYPE, __)] : []; const expressions = [init]; @@ -455,12 +466,24 @@ export function generateStructFieldMethods( } // setFoo(value: FooType): void { ... } - if (set) { + if (set || union) { - const parameters = [ts.createParameter(__, __, __, VALUE, __, jsTypeReference, __)]; - const expressions = [set]; + const expressions = []; + const parameters = []; - if (union) expressions.unshift(setDiscriminant); + if (set) { + + expressions.unshift(set); + + parameters.unshift(ts.createParameter(__, __, __, VALUE, __, jsTypeReference, __)); + + } + + if (union) { + + expressions.unshift(setDiscriminant); + + } members.push(createMethod(`set${properName}`, parameters, VOID_TYPE, expressions)); diff --git a/packages/capnpc-ts/src/index.ts b/packages/capnpc-ts/src/index.ts index 0c73bba..9d70601 100644 --- a/packages/capnpc-ts/src/index.ts +++ b/packages/capnpc-ts/src/index.ts @@ -1,5 +1,10 @@ +import * as Bluebird from 'bluebird'; import * as capnp from 'capnp-ts'; import * as s from 'capnp-ts/lib/std/schema.capnp'; + +import {CodeGeneratorContext} from './code-generator-context'; +export {CodeGeneratorContext} from './code-generator-context'; + import initTrace from 'debug'; import {loadRequest, writeTsFiles} from './compiler'; @@ -7,60 +12,70 @@ import {loadRequest, writeTsFiles} from './compiler'; const trace = initTrace('capnpc'); trace('load'); -const chunks: Buffer[] = []; +import * as E from './errors'; +export let errors = E; -export function main() { +export async function main(): Promise { + return run().thenReturn().tapCatch((reason) => { + // tslint:disable-next-line:no-console + console.error(reason); + process.exit(1); + }); +} - process.stdin.on('data', (chunk: Buffer) => { +export async function run(): Bluebird { - trace('reading data chunk (%d bytes)', chunk.byteLength); + return Bluebird.try(() => { - chunks.push(chunk); + const chunks: Buffer[] = []; - }); + process.stdin.on('data', (chunk: Buffer) => { - process.stdin.on('end', () => { + trace('reading data chunk (%d bytes)', chunk.byteLength); - trace('read complete'); + chunks.push(chunk); - const reqBuffer = new Buffer(chunks.reduce((l, chunk) => l + chunk.byteLength, -1)); + }); - let i = 0; + return (new Bluebird((resolve) => { - chunks.forEach((chunk, j) => { + process.stdin.on('end', () => { - if (j === chunks.length - 1) { + trace('read complete'); - // Exclude the EOF byte. + resolve(); - chunk.copy(reqBuffer, i, 0, chunk.byteLength - 1); + }); - } else { + })).then(() => { - chunk.copy(reqBuffer, i); + const reqBuffer = new Buffer(chunks.reduce((l, chunk) => l + chunk.byteLength, 0)); - } + let i = 0; - i += chunk.byteLength; + chunks.forEach((chunk) => { - }); + chunk.copy(reqBuffer, i); - trace(reqBuffer); + i += chunk.byteLength; - const message = capnp.Message.fromBuffer(reqBuffer); + }); - trace('message: %s', message.dump()); + trace('reqBuffer (length: %d)', reqBuffer.length, reqBuffer); - const req = message.getRoot(s.CodeGeneratorRequest); + const message = capnp.Message.fromBuffer(reqBuffer); - trace('%s', req); + trace('message: %s', message.dump()); - const ctx = loadRequest(req); + const req = message.getRoot(s.CodeGeneratorRequest); - writeTsFiles(ctx); - // NOTE: Uncomment this to enable transpilation to JS, kinda broken right now. - // transpileAll(ctx); + trace('%s', req); - }); + const ctx = loadRequest(req); + writeTsFiles(ctx); + + return ctx; + }); + }); } diff --git a/tsconfig.json b/tsconfig.json index ea3655e..20f3581 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,8 @@ "include": [ "packages/capnp-ts/src/**/*.ts", "packages/capnp-ts/test/**/*.ts", + "packages/capnpc-js/src/**/*.ts", + "packages/capnpc-js/test/**/*.ts", "packages/capnpc-ts/src/**/*.ts", "packages/capnpc-ts/test/**/*.ts" ] diff --git a/yarn.lock b/yarn.lock index c945858..c7078b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,17 +2,21 @@ # yarn lockfile v1 -"@types/benchmark@1.0.30": +"@types/benchmark@^1.0.30": version "1.0.30" resolved "https://registry.yarnpkg.com/@types/benchmark/-/benchmark-1.0.30.tgz#f6bea0baceb178155968b9984f94546f63677592" +"@types/bluebird@^3.5.7": + version "3.5.8" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.8.tgz#242a83379f06c90f96acf6d1aeab3af6faebdb98" + "@types/debug@0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.29.tgz#a1e514adfbd92f03a224ba54d693111dbf1f3754" -"@types/node@^8.0.11": - version "8.0.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.12.tgz#0560c3e8c9e3da0aa07d0b86e0b0a02b5fd29480" +"@types/node@^7.0.18": + version "7.0.37" + resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.37.tgz#f129fff94d14a60c3d99eadb9fe0c98119e09c8f" "@types/ramda@^0.24.3": version "0.24.4" @@ -255,11 +259,18 @@ beeper@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" +benchmark@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" + dependencies: + lodash "^4.17.4" + platform "^1.3.3" + bind-obj-methods@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/bind-obj-methods/-/bind-obj-methods-1.0.0.tgz#4f5979cac15793adf70e488161e463e209ca509c" -bluebird@^3.3.1: +bluebird@^3.3.1, bluebird@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -1016,6 +1027,10 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +format@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + fs-exists-cached@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz#cf25554ca050dc49ae6656b41de42258989dcbce" @@ -1371,6 +1386,10 @@ hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" +hex2dec@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hex2dec/-/hex2dec-1.0.1.tgz#949bb33f1fdbbeab20e06403a00fc7d5ff284207" + hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" @@ -2261,6 +2280,10 @@ object.pick@^1.2.0: dependencies: isobject "^2.1.0" +obtain-unicode@~0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/obtain-unicode/-/obtain-unicode-0.0.5.tgz#655f337a8f135280495d77a60efc601f9af5d5dc" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2437,6 +2460,10 @@ pkg-dir@^1.0.0: dependencies: find-up "^1.0.0" +platform@^1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd" + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -2465,6 +2492,10 @@ qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" +ramda@^0.24.1: + version "0.24.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -2729,7 +2760,7 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" -source-map-support@^0.4.0, source-map-support@^0.4.3: +source-map-support@^0.4.0, source-map-support@^0.4.15, source-map-support@^0.4.3: version "0.4.15" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" dependencies: @@ -2997,6 +3028,10 @@ test-exclude@^4.1.1: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" +testcheck@^1.0.0-rc.2: + version "1.0.0-rc.2" + resolved "https://registry.yarnpkg.com/testcheck/-/testcheck-1.0.0-rc.2.tgz#11356a25b84575efe0b0857451e85b5fa74ee4e4" + text-extensions@^1.0.0: version "1.5.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.5.0.tgz#d1cb2d14b5d0bc45bfdca8a08a473f68c7eb0cbc" @@ -3188,6 +3223,12 @@ user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" +utf8-encoding@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/utf8-encoding/-/utf8-encoding-0.1.2.tgz#8717015cb8b923bc0303bf4af520af96f06ae9a2" + dependencies: + obtain-unicode "~0.0.5" + util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"