commit 6b75d2f2a73b6fe91c6f0daf5180d099a256b218 Author: Tylor Steinberger Date: Sun Mar 12 19:48:37 2017 -0400 feat(stream): start of a stream library diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..bfa4f30 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +tab_width = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false +insert_final_newline = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..17aa990 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +output/ +src/ \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..c674f26 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": "@most/eslint-config-most", + "rules": { + "comma-dangle": "off" + } +} \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..0a230a6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,16 @@ + + +**Code to reproduce the issue:** + + +**Expected behavior:** + + +**Actual behavior:** + + +**Versions of packages used:** diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..f491eca --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ + + +- [ ] I added new tests for the issue I fixed or the feature I built +- [ ] I ran `yarn test` for the package I'm modifying +- [ ] I used `yarn commit` instead of `git commit` \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ce25bb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc* +/.psa* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..725e71a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js + +node_js: + - 7 + +cache: yarn diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..09c502b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing + +First of all, thank you so much, we need your help. + +## Contributing a fix or feature + +1. Fork the repository +2. Switch to a new branch `git checkout -b [branchName]` +3. Produce your fix or feature +4. Use `yarn commit` instead of `git commit` PLEASE! +5. Submit a pull request for review diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..4e98b1e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2016 Tylor Steinberger + +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. diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..ae51730 --- /dev/null +++ b/bower.json @@ -0,0 +1,19 @@ +{ + "name": "tempest", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "output" + ], + "dependencies": { + "purescript-eff": "^2.0.0", + "purescript-prelude": "^2.5.0", + "purescript-aff-promise": "^0.4.0", + "purescript-aff": "^2.0.3" + }, + "devDependencies": { + "purescript-console": "^2.0.0", + "purescript-psci-support": "^2.0.0" + } +} diff --git a/ffi/Control/Stream/LinkedList.js b/ffi/Control/Stream/LinkedList.js new file mode 100644 index 0000000..42086b5 --- /dev/null +++ b/ffi/Control/Stream/LinkedList.js @@ -0,0 +1,47 @@ +export class LinkedList { + constructor () { + this.head = null + this.length = 0 + } + + add (x) { + if (this.head !== null) { + this.head.prev = x + x.next = this.head + } + this.head = x + ++this.length + } + + remove (x) { // eslint-disable-line complexity + --this.length + if (x === this.head) { + this.head = this.head.next + } + if (x.next !== null) { + x.next.prev = x.prev + x.next = null + } + if (x.prev !== null) { + x.prev.next = x.next + x.prev = null + } + } + + isEmpty () { + return this.length === 0 + } + + dispose () { + if (this.isEmpty()) return + + var x = this.head + this.head = null + this.length = 0 + + while (x !== null) { + x.dispose() + x = x.next + } + } +} diff --git a/ffi/Control/Stream/Stream.js b/ffi/Control/Stream/Stream.js new file mode 100644 index 0000000..d15c6bd --- /dev/null +++ b/ffi/Control/Stream/Stream.js @@ -0,0 +1,5 @@ +export class Stream { + constructor (source) { + this.source = source + } +} diff --git a/ffi/Control/Stream/combinators/drain.js b/ffi/Control/Stream/combinators/drain.js new file mode 100644 index 0000000..1aec254 --- /dev/null +++ b/ffi/Control/Stream/combinators/drain.js @@ -0,0 +1,4 @@ +import { defaultScheduler } from '../scheduler' +import { runEffects } from '../runEffects' + +export const drain = stream => () => runEffects(stream, defaultScheduler) diff --git a/ffi/Control/Stream/combinators/index.js b/ffi/Control/Stream/combinators/index.js new file mode 100644 index 0000000..5365bd9 --- /dev/null +++ b/ffi/Control/Stream/combinators/index.js @@ -0,0 +1,2 @@ +export * from './tap' +export * from './drain' diff --git a/ffi/Control/Stream/combinators/mergeConcurrently.js b/ffi/Control/Stream/combinators/mergeConcurrently.js new file mode 100644 index 0000000..d2f5a2b --- /dev/null +++ b/ffi/Control/Stream/combinators/mergeConcurrently.js @@ -0,0 +1,123 @@ +/** @license MIT License (c) copyright 2010-2016 original author or authors */ +/** @author Brian Cavalier */ +/** @author John Hann */ + +import { LinkedList } from '../LinkedList' +import { MemoizedDisosable } from '../disposables/MemoizedDisposable' +import { id as identity } from '@most/prelude' + +export const mergeConcurrently = (concurrency, stream) => + mergeMapConcurrently(identity, concurrency, stream) + +export const mergeMapConcurrently = (f, concurrency, stream) => + new MergeConcurrently(f, concurrency, stream) + +class MergeConcurrently { + constructor (f, concurrency, source) { + this.f = f + this.concurrency = concurrency + this.source = source + } + + run (sink, scheduler) { + return new Outer(this.f, this.concurrency, this.source, sink, scheduler) + } +} + +class Outer { + constructor (f, concurrency, source, sink, scheduler) { + this.f = f + this.concurrency = concurrency + this.sink = sink + this.scheduler = scheduler + this.pending = [] + this.current = new LinkedList() + this.disposable = new MemoizedDisosable(source.run(this, scheduler)) + this.active = true + } + + event (t, x) { + this._addInner(t, x) + } + + _addInner (t, x) { + if (this.current.length < this.concurrency) { + this._startInner(t, x) + } else { + this.pending.push(x) + } + } + + _startInner (t, x) { + try { + this._initInner(t, x) + } catch (e) { + this.error(t, e) + } + } + + _initInner (t, x) { + const innerSink = new Inner(t, this, this.sink) + innerSink.disposable = mapAndRun(this.f, x, innerSink, this.scheduler) + this.current.add(innerSink) + } + + end (t, x) { + this.active = false + this.disposable.dispose() + this._checkEnd(t, x) + } + + dispose () { + this.active = false + this.pending.length = 0 + this.disposable.dispose() + this.current.dispose() + } + + _endInner (t, x, inner) { + this.current.remove(inner) + inner.dispose() + + if (this.pending.length === 0) { + this._checkEnd(t, x) + } else { + this._startInner(t, this.pending.shift()) + } + } + + _checkEnd (t, x) { + if (!this.active && this.current.isEmpty()) { + this.sink.end(t, x) + } + } +} + +const mapAndRun = (f, x, sink, scheduler) => + f(x).run(sink, scheduler) + +class Inner { + constructor (time, outer, sink) { + this.prev = this.next = null + this.time = time + this.outer = outer + this.sink = sink + this.disposable = void 0 + } + + event (t, x) { + this.sink.event(Math.max(t, this.time), x) + } + + end (t, x) { + this.outer._endInner(Math.max(t, this.time), x, this) + } + + error (t, e) { + this.outer.error(Math.max(t, this.time), e) + } + + dispose () { + return this.disposable.dispose() + } +} diff --git a/ffi/Control/Stream/combinators/tap.js b/ffi/Control/Stream/combinators/tap.js new file mode 100644 index 0000000..51e7b21 --- /dev/null +++ b/ffi/Control/Stream/combinators/tap.js @@ -0,0 +1,50 @@ +import { Stream } from '../Stream' +import { curry2 } from '@most/prelude' + +export const tapEnd = curry2((f, stream) => new Stream(new TapEnd(f, stream.source))) + +export const tapEvent = curry2((f, stream) => new Stream(new TapEvent(f, stream.source))) + +class TapEvent { + constructor (f, source) { + this.source = source + this.f = f + + this.run = sink => scheduler => + source.run(new TapSink(f, sink))(scheduler) + } +} + +class TapSink { + constructor (f, sink) { + this.event = t => x => { + f(x)() + sink.event(t)(x) + } + + this.end = t => { + sink.end(t) + } + } +} + +class TapEnd { + constructor (f, source) { + this.source = source + this.f = f + + this.run = sink => scheduler => + source.run(new TapEndSink(f, sink))(scheduler) + } +} + +class TapEndSink { + constructor (f, sink) { + this.event = t => x => sink.event(t)(x) + + this.end = t => { + f() + sink.end(t) + } + } +} diff --git a/ffi/Control/Stream/disposables/Disposable.js b/ffi/Control/Stream/disposables/Disposable.js new file mode 100644 index 0000000..afbb45e --- /dev/null +++ b/ffi/Control/Stream/disposables/Disposable.js @@ -0,0 +1,15 @@ +export class Disposable { + /** + * Create a new Disposable which will dispose its underlying resource. + * @param {function} dispose function + * @param {*?} data any data to be passed to disposer function + */ + constructor (dispose, data) { + this._dispose = dispose + this._data = data + } + + dispose () { + return this._dispose(this._data) + } +} diff --git a/ffi/Control/Stream/disposables/MemoizedDisposable.js b/ffi/Control/Stream/disposables/MemoizedDisposable.js new file mode 100644 index 0000000..5b84266 --- /dev/null +++ b/ffi/Control/Stream/disposables/MemoizedDisposable.js @@ -0,0 +1,17 @@ +export class MemoizedDisposable { + constructor (disposable) { + this.disposed = false + this.value = undefined + this.disposable = disposable + } + + dispose () { + if (!this.disposed) { + this.disposed = true + this.value = disposeSafely(this.disposable) + this.disposable = undefined + } + + return this.value + } +} diff --git a/ffi/Control/Stream/disposables/SettableDisposable.js b/ffi/Control/Stream/disposables/SettableDisposable.js new file mode 100644 index 0000000..e9ace40 --- /dev/null +++ b/ffi/Control/Stream/disposables/SettableDisposable.js @@ -0,0 +1,29 @@ +export class SettableDisposable { + constructor () { + this.disposable = void 0 + this.disposed = false + this.result = void 0 + } + + setDisposable (disposable) { + this.disposable = disposable + + if (this.disposed) { + this.result = disposable.dispose() + } + } + + dispose () { + if (this.disposed) { + return this.result + } + + this.disposed = true + + if (this.disposable !== void 0) { + this.result = this.disposable.dispose() + } + + return this.result + } +} diff --git a/ffi/Control/Stream/disposables/disposeSafely.js b/ffi/Control/Stream/disposables/disposeSafely.js new file mode 100644 index 0000000..a84900e --- /dev/null +++ b/ffi/Control/Stream/disposables/disposeSafely.js @@ -0,0 +1,3 @@ +export function disposeSafely (disposable) { + disposable.dispose() +} diff --git a/ffi/Control/Stream/disposables/index.js b/ffi/Control/Stream/disposables/index.js new file mode 100644 index 0000000..5289cbf --- /dev/null +++ b/ffi/Control/Stream/disposables/index.js @@ -0,0 +1,12 @@ +import { curry2, id, map } from '@most/prelude' + +import { Disposable } from './Disposable' +import { MemoizedDisposable } from './MemoizedDisposable' +import { disposeSafely } from './disposeSafely' + +export const createDisposable = curry2((dispose, data) => new MemoizedDisposable(new Disposable(dispose, data))) + +export const emptyDisposable = new Disposable(id, undefined) + +export const disposeAll = disposables => + createDisposable(map(disposeSafely, disposables), disposables) diff --git a/ffi/Control/Stream/index.js b/ffi/Control/Stream/index.js new file mode 100644 index 0000000..f17d98a --- /dev/null +++ b/ffi/Control/Stream/index.js @@ -0,0 +1,4 @@ +/* @flow */ +export * from './disposables' +export * from './scheduler' +export * from './combinators' diff --git a/ffi/Control/Stream/runEffects.js b/ffi/Control/Stream/runEffects.js new file mode 100644 index 0000000..94a3019 --- /dev/null +++ b/ffi/Control/Stream/runEffects.js @@ -0,0 +1,28 @@ +import { SettableDisposable } from './disposables/SettableDisposable' + +export function runEffects (stream, scheduler) { + return runSourceEffects(stream.source, scheduler) +} + +const runSourceEffects = (source, scheduler) => runSource(source, scheduler) + +function runSource (source, scheduler) { + const disposable = new SettableDisposable() + const observer = new RunEffectsSink(disposable) + + disposable.setDisposable(source.run(observer)(scheduler)) +} + +var RunEffectsSink = function RunEffectsSink (disposable) { + this._disposable = disposable + this.active = true +} + +RunEffectsSink.prototype.event = function event (t) { + return function (x) {} +} + +RunEffectsSink.prototype.end = function end (t) { + this.active = false + Promise.resolve(this._disposable).then(d => d.dispose()) +} diff --git a/ffi/Control/Stream/scheduler/ClockTimer.js b/ffi/Control/Stream/scheduler/ClockTimer.js new file mode 100644 index 0000000..ef7cb56 --- /dev/null +++ b/ffi/Control/Stream/scheduler/ClockTimer.js @@ -0,0 +1,48 @@ +/** @license MIT License (c) copyright 2010-2016 original author or authors */ +/** @author Brian Cavalier */ +/** @author John Hann */ + +/*global setTimeout, clearTimeout*/ + +export function defer (task) { + return Promise.resolve(task).then(runTask) +} + +export function runTask (task) { + return task.run() +} + +export class ClockTimer { + constructor () { + this.now = Date.now + } + + setTimer (f, dt) { + return dt <= 0 ? runAsap(f) : setTimeout(f, dt) + } + + clearTimer (t) { + return t instanceof Asap ? t.cancel() : clearTimeout(t) + } +} + +class Asap { + constructor (f) { + this.f = f + this.active = true + } + + run () { + return this.active && this.f() + } + + cancel () { + this.active = false + } +} + +function runAsap (f) { + const task = new Asap(f) + defer(task) + return task +} diff --git a/ffi/Control/Stream/scheduler/PropagateTask.js b/ffi/Control/Stream/scheduler/PropagateTask.js new file mode 100644 index 0000000..0883d75 --- /dev/null +++ b/ffi/Control/Stream/scheduler/PropagateTask.js @@ -0,0 +1,30 @@ +import { curry2, curry3 } from '@most/prelude' + +const propagateTask = + curry3((run, value, sink) => new PropagateTask(run, value, sink)) + +export const eventTask = + curry2((value, sink) => propagateTask(runEvent, value, sink)) + +export const endTask = sink => propagateTask(runEnd, void 0, sink) + +class PropagateTask { + constructor (run, value, sink) { + let active = true + + this.dispose = () => { active = false } + this.run = t => { + if (!active) return + + run(t, value, sink) + } + } +} + +function runEvent (time, value, sink) { + sink.event(time)(value) +} + +function runEnd (time, value, sink) { + sink.end(time, value) +} diff --git a/ffi/Control/Stream/scheduler/ScheduledTask.js b/ffi/Control/Stream/scheduler/ScheduledTask.js new file mode 100644 index 0000000..fb88107 --- /dev/null +++ b/ffi/Control/Stream/scheduler/ScheduledTask.js @@ -0,0 +1,14 @@ +/* @flow */ +export function ScheduledTask (delay, period, task, scheduler) { + this.time = delay + this.period = period + this.task = task + this.scheduler = scheduler + this.active = true + + this.run = () => task.run(this.time) + this.dispose = () => { + scheduler.cancel(this) + task.dispose() + } +} diff --git a/ffi/Control/Stream/scheduler/Scheduler.js b/ffi/Control/Stream/scheduler/Scheduler.js new file mode 100644 index 0000000..6dc626f --- /dev/null +++ b/ffi/Control/Stream/scheduler/Scheduler.js @@ -0,0 +1,99 @@ +/* @flow */ +import { ScheduledTask } from './ScheduledTask' + +function runTask (task) { + try { + return task.run() + } catch (e) { + console.error(e) + } +} + +export class Scheduler { + constructor (timer, timeline) { + this.timer = timer + this.timeline = timeline + + this._timer = null + this._nextArrival = Infinity + + this._runReadyTasksBound = () => this._runReadyTasks(this.now()) + } + + now () { + return this.timer.now() + } + + asap (task) { + return this.schedule(0, -1, task) + } + + delay (delay, task) { + return this.schedule(delay, -1, task) + } + + periodic (period, task) { + return this.schedule(0, period, task) + } + + schedule (delay, period, task) { + const now = this.now() + const st = new ScheduledTask(now + Math.max(0, delay), period, task, this) + + this.timeline.add(st) + this._scheduleNextRun(now) + return st + } + + cancel (task) { + task.active = false + if (this.timeline.remove(task)) { + this._reschedule() + } + } + + cancelAll (f) { + this.timeline.removeAll(f) + this._reschedule() + } + + _reschedule () { + if (this.timeline.isEmpty()) { + this._unschedule() + } else { + this._scheduleNextRun(this.now()) + } + } + + _unschedule () { + this.timer.clearTimer(this._timer) + this._timer = null + } + + _scheduleNextRun (now) { // eslint-disable-line complexity + if (this.timeline.isEmpty()) { + return + } + + const nextArrival = this.timeline.nextArrival() + + if (this._timer === null) { + this._scheduleNextArrival(nextArrival, now) + } else if (nextArrival < this._nextArrival) { + this._unschedule() + this._scheduleNextArrival(nextArrival, now) + } + } + + _scheduleNextArrival (nextArrival, now) { + this._nextArrival = nextArrival + const delay = Math.max(0, nextArrival - now) + this._timer = this.timer.setTimer(this._runReadyTasksBound, delay) + } + + _runReadyTasks (now) { + this._timer = null + this.timeline.runTasks(now, runTask) + this._scheduleNextRun(this.now()) + } +} diff --git a/ffi/Control/Stream/scheduler/Timeline.js b/ffi/Control/Stream/scheduler/Timeline.js new file mode 100644 index 0000000..8d7bb0c --- /dev/null +++ b/ffi/Control/Stream/scheduler/Timeline.js @@ -0,0 +1,124 @@ +/** @license MIT License (c) copyright 2010-2016 original author or authors */ +/** @author Brian Cavalier */ +/** @author John Hann */ + +import * as base from '@most/prelude' + +export class Timeline { + constructor () { + this.tasks = [] + } + + nextArrival () { + return this.isEmpty() ? Infinity : this.tasks[0].time + } + + isEmpty () { + return this.tasks.length === 0 + } + + add (st) { + insertByTime(st, this.tasks) + } + + remove (st) { + const i = binarySearch(st.time, this.tasks) + + if (i >= 0 && i < this.tasks.length) { + const at = base.findIndex(st, this.tasks[i].events) + if (at >= 0) { + this.tasks[i].events.splice(at, 1) + return true + } + } + + return false + } + + removeAll (f) { + for (let i = 0; i < this.tasks.length; ++i) { + removeAllFrom(f, this.tasks[i]) + } + } + + runTasks (t, runTask) { + const tasks = this.tasks + const l = tasks.length + let i = 0 + + while (i < l && tasks[i].time <= t) { + ++i + } + + this.tasks = tasks.slice(i) + + // Run all ready tasks + for (let j = 0; j < i; ++j) { + this.tasks = runReadyTasks(runTask, tasks[j].events, this.tasks) + } + } +} + +function runReadyTasks (runTask, events, tasks) { // eslint-disable-line complexity + for (let i = 0; i < events.length; ++i) { + const task = events[i] + + if (task.active) { + runTask(task) + + // Reschedule periodic repeating tasks + // Check active again, since a task may have canceled itself + if (task.period >= 0 && task.active) { + task.time = task.time + task.period + insertByTime(task, tasks) + } + } + } + + return tasks +} + +function insertByTime (task, timeslots) { // eslint-disable-line complexity + const l = timeslots.length + + if (l === 0) { + timeslots.push(newTimeslot(task.time, [task])) + return + } + + const i = binarySearch(task.time, timeslots) + + if (i >= l) { + timeslots.push(newTimeslot(task.time, [task])) + } else if (task.time === timeslots[i].time) { + timeslots[i].events.push(task) + } else { + timeslots.splice(i, 0, newTimeslot(task.time, [task])) + } +} + +function removeAllFrom (f, timeslot) { + timeslot.events = base.removeAll(f, timeslot.events) +} + +function binarySearch (t, sortedArray) { // eslint-disable-line complexity + let lo = 0 + let hi = sortedArray.length + let mid, y + + while (lo < hi) { + mid = Math.floor((lo + hi) / 2) + y = sortedArray[mid] + + if (t === y.time) { + return mid + } else if (t < y.time) { + hi = mid + } else { + lo = mid + 1 + } + } + return hi +} + +const newTimeslot = (t, events) => ({ time: t, events: events }) \ No newline at end of file diff --git a/ffi/Control/Stream/scheduler/index.js b/ffi/Control/Stream/scheduler/index.js new file mode 100644 index 0000000..0031cf6 --- /dev/null +++ b/ffi/Control/Stream/scheduler/index.js @@ -0,0 +1,16 @@ +import { ClockTimer } from './ClockTimer' +import { Scheduler } from './Scheduler' +import { Timeline } from './Timeline' +import { curry2 } from '@most/prelude' + +export { endTask, eventTask } from './PropagateTask' + +export const defaultScheduler = new Scheduler(new ClockTimer(), new Timeline()) + +export const scheduleTasks = curry2((tasks, scheduler) => { + const scheduledTasks = tasks.map(task => scheduler.asap(task)) + + return { + dispose: () => scheduledTasks.forEach(task => task.dispose()) + } +}) diff --git a/ffi/Control/Stream/sink/IndexSink.js b/ffi/Control/Stream/sink/IndexSink.js new file mode 100644 index 0000000..01cb7d9 --- /dev/null +++ b/ffi/Control/Stream/sink/IndexSink.js @@ -0,0 +1,24 @@ +export class IndexSink { + constructor (i, sink) { + this.sink = sink + this.index = i + this.active = true + this.value = void 0 + } + + event (t) { + return x => { + if (!this.active) return + + this.value = x + this.sink.event(t)(this) + } + } + + end (t, x) { + if (!this.active) return + + this.active = false + this.sink.end(t, { index: this.index, value: x }) + } +} diff --git a/ffi/Control/Stream/sink/index.js b/ffi/Control/Stream/sink/index.js new file mode 100644 index 0000000..84a112b --- /dev/null +++ b/ffi/Control/Stream/sink/index.js @@ -0,0 +1 @@ +export * from './IndexSink' diff --git a/package.json b/package.json new file mode 100644 index 0000000..0b29114 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "purescript-tempest", + "version": "0.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "rollup -c && pulp build" + }, + "author": "Tylor Steinberger", + "license": "MIT", + "devDependencies": { + "@most/eslint-config-most": "^1.0.3", + "eslint": "^3.17.1", + "eslint-config-standard": "^7.0.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^2.1.1", + "rollup": "^0.41.4", + "rollup-plugin-buble": "^0.15.0", + "rollup-plugin-flow": "^1.1.1", + "rollup-plugin-node-resolve": "^2.0.0", + "uglify-js": "^2.8.11" + }, + "dependencies": { + "@most/prelude": "^1.5.0" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..75c17e7 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,14 @@ +import buble from 'rollup-plugin-buble' +import flow from 'rollup-plugin-flow' +import resolve from 'rollup-plugin-node-resolve' + +export default { + entry: 'ffi/Control/Stream/index.js', + dest: 'src/Control/Stream.js', + format: 'cjs', + plugins: [ + flow(), + buble(), + resolve({ module: true, jsnext: true }) + ] +} diff --git a/src/Control/Stream.js b/src/Control/Stream.js new file mode 100644 index 0000000..d54467f --- /dev/null +++ b/src/Control/Stream.js @@ -0,0 +1,688 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +/** @license MIT License (c) copyright 2010-2016 original author or authors */ + +// Non-mutating array operations + +// cons :: a -> [a] -> [a] +// a with x prepended + + +// append :: a -> [a] -> [a] +// a with x appended + + +// drop :: Int -> [a] -> [a] +// drop first n elements + + +// tail :: [a] -> [a] +// drop head element + + +// copy :: [a] -> [a] +// duplicate a (shallow duplication) + + +// map :: (a -> b) -> [a] -> [b] +// transform each element with f +function map (f, a) { + var l = a.length; + var b = new Array(l); + for (var i = 0; i < l; ++i) { + b[i] = f(a[i]); + } + return b +} + +// reduce :: (a -> b -> a) -> a -> [b] -> a +// accumulate via left-fold + + +// replace :: a -> Int -> [a] +// replace element at index + + +// remove :: Int -> [a] -> [a] +// remove element at index + + +// removeAll :: (a -> boolean) -> [a] -> [a] +// remove all elements matching a predicate +function removeAll (f, a) { + var l = a.length; + var b = new Array(l); + var j = 0; + for (var x = (void 0), i = 0; i < l; ++i) { + x = a[i]; + if (!f(x)) { + b[j] = x; + ++j; + } + } + + b.length = j; + return b +} + +// findIndex :: a -> [a] -> Int +// find index of x in a, from the left +function findIndex (x, a) { + for (var i = 0, l = a.length; i < l; ++i) { + if (x === a[i]) { + return i + } + } + return -1 +} + +// isArrayLike :: * -> boolean +// Return true iff x is array-like + +/** @license MIT License (c) copyright 2010-2016 original author or authors */ + +// id :: a -> a +var id = function (x) { return x; }; + +// compose :: (b -> c) -> (a -> b) -> (a -> c) + + +// apply :: (a -> b) -> a -> b + + +// curry2 :: ((a, b) -> c) -> (a -> b -> c) +function curry2 (f) { + function curried (a, b) { + switch (arguments.length) { + case 0: return curried + case 1: return function (b) { return f(a, b); } + default: return f(a, b) + } + } + return curried +} + +// curry3 :: ((a, b, c) -> d) -> (a -> b -> c -> d) +function curry3 (f) { + function curried (a, b, c) { // eslint-disable-line complexity + switch (arguments.length) { + case 0: return curried + case 1: return curry2(function (b, c) { return f(a, b, c); }) + case 2: return function (c) { return f(a, b, c); } + default:return f(a, b, c) + } + } + return curried +} + +// curry4 :: ((a, b, c, d) -> e) -> (a -> b -> c -> d -> e) + +/** @license MIT License (c) copyright 2016 original author or authors */ + +var Disposable = function Disposable (dispose, data) { + this._dispose = dispose; + this._data = data; +}; + +Disposable.prototype.dispose = function dispose () { + return this._dispose(this._data) +}; + +var MemoizedDisposable = function MemoizedDisposable (disposable) { + this.disposed = false; + this.value = undefined; + this.disposable = disposable; +}; + +MemoizedDisposable.prototype.dispose = function dispose () { + if (!this.disposed) { + this.disposed = true; + this.value = disposeSafely(this.disposable); + this.disposable = undefined; + } + + return this.value +}; + +function disposeSafely$1 (disposable) { + disposable.dispose(); +} + +var createDisposable = curry2(function (dispose, data) { return new MemoizedDisposable(new Disposable(dispose, data)); }); + +var emptyDisposable = new Disposable(id, undefined); + +var disposeAll = function (disposables) { return createDisposable(map(disposeSafely$1, disposables), disposables); }; + +/** @license MIT License (c) copyright 2010-2016 original author or authors */ +/** @author Brian Cavalier */ +/** @author John Hann */ + +/*global setTimeout, clearTimeout*/ + +function defer (task) { + return Promise.resolve(task).then(runTask) +} + +function runTask (task) { + return task.run() +} + +var ClockTimer = function ClockTimer () { + this.now = Date.now; +}; + +ClockTimer.prototype.setTimer = function setTimer (f, dt) { + return dt <= 0 ? runAsap(f) : setTimeout(f, dt) +}; + +ClockTimer.prototype.clearTimer = function clearTimer (t) { + return t instanceof Asap ? t.cancel() : clearTimeout(t) +}; + +var Asap = function Asap (f) { + this.f = f; + this.active = true; +}; + +Asap.prototype.run = function run () { + return this.active && this.f() +}; + +Asap.prototype.cancel = function cancel () { + this.active = false; +}; + +function runAsap (f) { + var task = new Asap(f); + defer(task); + return task +} + +/* */ +function ScheduledTask (delay, period, task, scheduler) { + var this$1 = this; + + this.time = delay; + this.period = period; + this.task = task; + this.scheduler = scheduler; + this.active = true; + + this.run = function () { return task.run(this$1.time); }; + this.dispose = function () { + scheduler.cancel(this$1); + task.dispose(); + }; +} + +/* */ +function runTask$1 (task) { + try { + return task.run() + } catch (e) { + console.error(e); + } +} + +var Scheduler = function Scheduler (timer, timeline) { + var this$1 = this; + + this.timer = timer; + this.timeline = timeline; + + this._timer = null; + this._nextArrival = Infinity; + + this._runReadyTasksBound = function () { return this$1._runReadyTasks(this$1.now()); }; +}; + +Scheduler.prototype.now = function now () { + return this.timer.now() +}; + +Scheduler.prototype.asap = function asap (task) { + return this.schedule(0, -1, task) +}; + +Scheduler.prototype.delay = function delay (delay$1, task) { + return this.schedule(delay$1, -1, task) +}; + +Scheduler.prototype.periodic = function periodic (period, task) { + return this.schedule(0, period, task) +}; + +Scheduler.prototype.schedule = function schedule (delay, period, task) { + var now = this.now(); + var st = new ScheduledTask(now + Math.max(0, delay), period, task, this); + + this.timeline.add(st); + this._scheduleNextRun(now); + return st +}; + +Scheduler.prototype.cancel = function cancel (task) { + task.active = false; + if (this.timeline.remove(task)) { + this._reschedule(); + } +}; + +Scheduler.prototype.cancelAll = function cancelAll (f) { + this.timeline.removeAll(f); + this._reschedule(); +}; + +Scheduler.prototype._reschedule = function _reschedule () { + if (this.timeline.isEmpty()) { + this._unschedule(); + } else { + this._scheduleNextRun(this.now()); + } +}; + +Scheduler.prototype._unschedule = function _unschedule () { + this.timer.clearTimer(this._timer); + this._timer = null; +}; + +Scheduler.prototype._scheduleNextRun = function _scheduleNextRun (now) { // eslint-disable-line complexity + if (this.timeline.isEmpty()) { + return + } + + var nextArrival = this.timeline.nextArrival(); + + if (this._timer === null) { + this._scheduleNextArrival(nextArrival, now); + } else if (nextArrival < this._nextArrival) { + this._unschedule(); + this._scheduleNextArrival(nextArrival, now); + } +}; + +Scheduler.prototype._scheduleNextArrival = function _scheduleNextArrival (nextArrival, now) { + this._nextArrival = nextArrival; + var delay = Math.max(0, nextArrival - now); + this._timer = this.timer.setTimer(this._runReadyTasksBound, delay); +}; + +Scheduler.prototype._runReadyTasks = function _runReadyTasks (now) { + this._timer = null; + this.timeline.runTasks(now, runTask$1); + this._scheduleNextRun(this.now()); +}; + +/** @license MIT License (c) copyright 2010-2016 original author or authors */ +/** @author Brian Cavalier */ +/** @author John Hann */ + +var Timeline = function Timeline () { + this.tasks = []; +}; + +Timeline.prototype.nextArrival = function nextArrival () { + return this.isEmpty() ? Infinity : this.tasks[0].time +}; + +Timeline.prototype.isEmpty = function isEmpty () { + return this.tasks.length === 0 +}; + +Timeline.prototype.add = function add (st) { + insertByTime(st, this.tasks); +}; + +Timeline.prototype.remove = function remove$$1 (st) { + var i = binarySearch(st.time, this.tasks); + + if (i >= 0 && i < this.tasks.length) { + var at = findIndex(st, this.tasks[i].events); + if (at >= 0) { + this.tasks[i].events.splice(at, 1); + return true + } + } + + return false +}; + +Timeline.prototype.removeAll = function removeAll$$1 (f) { + var this$1 = this; + + for (var i = 0; i < this.tasks.length; ++i) { + removeAllFrom(f, this$1.tasks[i]); + } +}; + +Timeline.prototype.runTasks = function runTasks (t, runTask) { + var this$1 = this; + + var tasks = this.tasks; + var l = tasks.length; + var i = 0; + + while (i < l && tasks[i].time <= t) { + ++i; + } + + this.tasks = tasks.slice(i); + + // Run all ready tasks + for (var j = 0; j < i; ++j) { + this$1.tasks = runReadyTasks(runTask, tasks[j].events, this$1.tasks); + } +}; + +function runReadyTasks (runTask, events, tasks) { // eslint-disable-line complexity + for (var i = 0; i < events.length; ++i) { + var task = events[i]; + + if (task.active) { + runTask(task); + + // Reschedule periodic repeating tasks + // Check active again, since a task may have canceled itself + if (task.period >= 0 && task.active) { + task.time = task.time + task.period; + insertByTime(task, tasks); + } + } + } + + return tasks +} + +function insertByTime (task, timeslots) { // eslint-disable-line complexity + var l = timeslots.length; + + if (l === 0) { + timeslots.push(newTimeslot(task.time, [task])); + return + } + + var i = binarySearch(task.time, timeslots); + + if (i >= l) { + timeslots.push(newTimeslot(task.time, [task])); + } else if (task.time === timeslots[i].time) { + timeslots[i].events.push(task); + } else { + timeslots.splice(i, 0, newTimeslot(task.time, [task])); + } +} + +function removeAllFrom (f, timeslot) { + timeslot.events = removeAll(f, timeslot.events); +} + +function binarySearch (t, sortedArray) { // eslint-disable-line complexity + var lo = 0; + var hi = sortedArray.length; + var mid, y; + + while (lo < hi) { + mid = Math.floor((lo + hi) / 2); + y = sortedArray[mid]; + + if (t === y.time) { + return mid + } else if (t < y.time) { + hi = mid; + } else { + lo = mid + 1; + } + } + return hi +} + +var newTimeslot = function (t, events) { return ({ time: t, events: events }); }; + +var propagateTask = + curry3(function (run, value, sink) { return new PropagateTask(run, value, sink); }); + +var eventTask = + curry2(function (value, sink) { return propagateTask(runEvent, value, sink); }); + +var endTask = function (sink) { return propagateTask(runEnd, void 0, sink); }; + +var PropagateTask = function PropagateTask (run, value, sink) { + var active = true; + + this.dispose = function () { active = false; }; + this.run = function (t) { + if (!active) { return } + + run(t, value, sink); + }; +}; + +function runEvent (time, value, sink) { + sink.event(time)(value); +} + +function runEnd (time, value, sink) { + sink.end(time, value); +} + +var defaultScheduler = new Scheduler(new ClockTimer(), new Timeline()); + +var scheduleTasks = curry2(function (tasks, scheduler) { + var scheduledTasks = tasks.map(function (task) { return scheduler.asap(task); }); + + return { + dispose: function () { return scheduledTasks.forEach(function (task) { return task.dispose(); }); } + } +}); + +var Stream = function Stream (source) { + this.source = source; +}; + +var tapEnd = curry2(function (f, stream) { return new Stream(new TapEnd(f, stream.source)); }); + +var tapEvent = curry2(function (f, stream) { return new Stream(new TapEvent(f, stream.source)); }); + +var TapEvent = function TapEvent (f, source) { + this.source = source; + this.f = f; + + this.run = function (sink) { return function (scheduler) { return source.run(new TapSink(f, sink))(scheduler); }; }; +}; + +var TapSink = function TapSink (f, sink) { + this.event = function (t) { return function (x) { + f(x)(); + sink.event(t)(x); + }; }; + + this.end = function (t) { + sink.end(t); + }; +}; + +var TapEnd = function TapEnd (f, source) { + this.source = source; + this.f = f; + + this.run = function (sink) { return function (scheduler) { return source.run(new TapEndSink(f, sink))(scheduler); }; }; +}; + +var TapEndSink = function TapEndSink (f, sink) { + this.event = function (t) { return function (x) { return sink.event(t)(x); }; }; + + this.end = function (t) { + f(); + sink.end(t); + }; +}; + +var SettableDisposable = function SettableDisposable () { + this.disposable = void 0; + this.disposed = false; + this.result = void 0; +}; + +SettableDisposable.prototype.setDisposable = function setDisposable (disposable) { + this.disposable = disposable; + + if (this.disposed) { + this.result = disposable.dispose(); + } +}; + +SettableDisposable.prototype.dispose = function dispose () { + if (this.disposed) { + return this.result + } + + this.disposed = true; + + if (this.disposable !== void 0) { + this.result = this.disposable.dispose(); + } + + return this.result +}; + +function runEffects (stream, scheduler) { + return runSourceEffects(stream.source, scheduler) +} + +var runSourceEffects = function (source, scheduler) { return runSource(source, scheduler); }; + +function runSource (source, scheduler) { + var disposable = new SettableDisposable(); + var observer = new RunEffectsSink(disposable); + + disposable.setDisposable(source.run(observer)(scheduler)); +} + +var RunEffectsSink = function RunEffectsSink (disposable) { + this._disposable = disposable; + this.active = true; +}; + +RunEffectsSink.prototype.event = function event (t) { + return function (x) {} +}; + +RunEffectsSink.prototype.end = function end (t) { + this.active = false; + Promise.resolve(this._disposable).then(function (d) { return d.dispose(); }); +}; + +var drain = function (stream) { return function () { return runEffects(stream, defaultScheduler); }; }; + +var combine = + curry3(function (f, stream1, stream2) { return new Stream(new Combine(f, stream1.source, stream2.source)); }); + +var Combine = function Combine (f, source1, source2) { + this.f = f; + this.source1 = source1; + this.source2 = source2; +}; + +Combine.prototype.run = function run (sink) { + var this$1 = this; + + return function (scheduler) { + var disposables = Array(2); + var sinks = Array(2); + + var mergeSink = new CombineSink(disposables, sinks, sink, this$1.f); + + sinks[0] = new IndexSink(0, mergeSink); + sinks[1] = new IndexSink(1, mergeSink); + disposables[0] = this$1.source1.run(sinks[0])(scheduler); + disposables[1] = this$1.source2.run(sinks[1])(scheduler); + + return disposeAll(disposables) + } +}; + +var IndexSink = function IndexSink () {}; + +IndexSink.prototype.cosntructor = function cosntructor (i, sink) { + this.i = i; + this.sink = sink; +}; + +IndexSink.prototype.event = function event (t) { + var this$1 = this; + + return function (x) { + this$1.sink.event(t)({ index: this$1.i, value: x }); + } +}; + +IndexSink.prototype.end = function end (t) { + this.sink.end(t, this.i); +}; + +var CombineSink = function CombineSink (disposables, sinks, sink, f) { + this.disposables = disposables; + this.sinks = sinks; + this.sink = sink; + this.f = f; + + this.awaiting = 2; + this.values = Array(2); + this.hasValue = [false, false]; + this.activeCount = 2; +}; + +CombineSink.prototype.event = function event (t) { + var this$1 = this; + + return function (ref) { + var index = ref.index; + var value = ref.value; + + var f = this$1.f; + var awaiting = this$1._updateReady(index); + this$1.values[index] = value; + + if (awaiting === 0) { + var result = f(this$1.values[0])(this$1.values[1]); + this$1.sink.event(t)(result); + } + } +}; + +CombineSink.prototype._updateReady = function _updateReady (index) { + if (this.awaiting > 0) { + if (!this.hasValue[index]) { + this.hasValue[index] = true; + this.awaiting -= 1; + } + } + + return this.awaiting +}; + +CombineSink.prototype.end = function end (t, ref) { + var index = ref.index; + var value = ref.value; + + this.disposables[index].dispose(); + + if (--this.activeCount === 0) { this.sink.end(t); } +}; + +/* */ + +exports.createDisposable = createDisposable; +exports.emptyDisposable = emptyDisposable; +exports.disposeAll = disposeAll; +exports.defaultScheduler = defaultScheduler; +exports.scheduleTasks = scheduleTasks; +exports.endTask = endTask; +exports.eventTask = eventTask; +exports.tapEnd = tapEnd; +exports.tapEvent = tapEvent; +exports.drain = drain; +exports.combine = combine; diff --git a/src/Control/Stream.purs b/src/Control/Stream.purs new file mode 100644 index 0000000..e1f4db7 --- /dev/null +++ b/src/Control/Stream.purs @@ -0,0 +1,130 @@ +module Control.Stream + ( STREAM + , EffStream + , PureStream + , Stream + , Source + , Sink + , Scheduler + , Task + , ScheduledTask + , Disposable + , Time + , createStream + , getSource + , runSource + , defaultScheduler + , eventTask + , endTask + , createDisposable + , emptyDisposable + , disposeAll + , scheduleTasks + , drain + , tapEvent + , tapEnd + , just + , fromArray + ) + where + +import Control.Monad.Eff (Eff, Pure) +import Data.Array (snoc) +import Data.Functor (class Functor, map) +import Data.Unit (Unit) +import Prelude (flip) + +newtype Time = Time Int + +foreign import data STREAM :: ! + +type EffStream e a = Eff (stream :: STREAM | e) a +type PureStream a = EffStream () a + +newtype Stream a = Stream { source :: Source a } + +type Source a = { run :: Sink a -> Scheduler -> Disposable } + +type Sink a = + { event :: Time -> a -> Unit + , end :: Time -> Unit + } + +type Scheduler = + { now :: Pure Time + , asap :: Task -> ScheduledTask + , delay :: Number -> Task -> ScheduledTask + , period :: Number -> Task -> ScheduledTask + , schedule :: Number -> Number -> Task -> ScheduledTask + , cancel :: ScheduledTask -> Unit + , cancelAll :: (ScheduledTask -> Boolean) -> Unit + } + +type Task = + { run :: Time -> Unit + , dispose :: Pure Unit + } + +type ScheduledTask = + { run :: Pure Unit + , dispose :: Pure Unit + } + +type Disposable = { dispose :: Pure Unit } + +instance functorStream :: Functor Stream where + map = _map + +createStream :: forall a. (Sink a -> Scheduler -> Disposable) -> Stream a +createStream run = Stream { source: { run } } + +getSource :: forall a. Stream a -> Source a +getSource stream = case stream of Stream a -> a.source + +runSource :: forall a. Stream a -> Sink a -> Scheduler -> Disposable +runSource stream sink scheduler = (getSource stream).run sink scheduler + +just :: forall a. a -> Stream a +just a = createStream (runJust a) + +runJust :: forall a. a -> Sink a -> Scheduler -> Disposable +runJust a sink scheduler = + scheduleTasks [ eventTask a sink, endTask sink ] scheduler + +-- TODO: remove fromArray because it's not a real event stream +-- replace with a fromArray combinator +fromArray :: forall a. Array a -> Stream a +fromArray arr = createStream (runFromArray arr) + +runFromArray :: forall a. Array a -> Sink a -> Scheduler -> Disposable +runFromArray arr sink scheduler = scheduleTasks tasks scheduler + where + tasks :: Array Task + tasks = snoc eventTasks (endTask sink) + + eventTasks :: Array Task + eventTasks = map (flip eventTask sink) arr + +_map :: forall a b. (a -> b) -> Stream a -> Stream b +_map f stream = createStream runMap + where + runMap :: Sink b -> Scheduler -> Disposable + runMap sink scheduler = + runSource stream (mapSink f sink) scheduler + +mapSink :: forall a b. (a -> b) -> Sink b -> Sink a +mapSink f sink = { event: mapEvent, end: sink.end } + where + mapEvent :: Time -> a -> Unit + mapEvent time value = sink.event time (f value) + +foreign import defaultScheduler :: Scheduler +foreign import eventTask :: forall a. a -> Sink a -> Task +foreign import endTask :: forall a. Sink a -> Task +foreign import createDisposable :: forall a. (a -> Unit) -> a -> Disposable +foreign import emptyDisposable :: Disposable +foreign import disposeAll :: Array Disposable -> Disposable +foreign import scheduleTasks :: Array Task -> Scheduler -> Disposable +foreign import drain :: forall e a. Stream a -> EffStream e Unit +foreign import tapEvent :: forall e a. (a -> EffStream e Unit) -> Stream a -> Stream a +foreign import tapEnd :: forall e a. EffStream e Unit -> Stream a -> Stream a diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..3ebd012 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1033 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@most/eslint-config-most@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@most/eslint-config-most/-/eslint-config-most-1.0.3.tgz#eeca9e18d9efe87151a6e7f4d12beb97b585cd20" + dependencies: + eslint-config-standard "^5.3.5" + eslint-plugin-promise "^2.0.0" + eslint-plugin-standard "^2.0.0" + +"@most/prelude@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@most/prelude/-/prelude-1.5.0.tgz#0c8ce09f305039d4055d3deb59c9e44cd337854d" + +acorn-jsx@^3.0.0, acorn-jsx@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn-object-spread@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/acorn-object-spread/-/acorn-object-spread-1.0.0.tgz#48ead0f4a8eb16995a17a0db9ffc6acaada4ba68" + dependencies: + acorn "^3.1.0" + +acorn@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a" + +acorn@^3.0.4, acorn@^3.1.0, acorn@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0: + version "4.11.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.4.tgz#ebf3a55d4b132ea60ff5847ae85d2ef069960b45" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +babel-code-frame@^6.16.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +babylon@^6.15.0: + version "6.16.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +browser-resolve@^1.11.0: + version "1.11.2" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" + dependencies: + resolve "1.1.7" + +buble@^0.15.0: + version "0.15.2" + resolved "https://registry.yarnpkg.com/buble/-/buble-0.15.2.tgz#547fc47483f8e5e8176d82aa5ebccb183b02d613" + dependencies: + acorn "^3.3.0" + acorn-jsx "^3.0.1" + acorn-object-spread "^1.0.0" + chalk "^1.1.3" + magic-string "^0.14.0" + minimist "^1.2.0" + os-homedir "^1.0.1" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +builtin-modules@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +circular-json@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.4.6: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +d@^0.1.1, d@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309" + dependencies: + es5-ext "~0.10.2" + +debug@^2.1.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351" + dependencies: + ms "0.7.2" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7: + version "0.10.12" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047" + dependencies: + es6-iterator "2" + es6-symbol "~3.1" + +es6-iterator@2: + version "2.0.0" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac" + dependencies: + d "^0.1.1" + es5-ext "^0.10.7" + es6-symbol "3" + +es6-map@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.4.tgz#a34b147be224773a4d7da8072794cefa3632b897" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-iterator "2" + es6-set "~0.1.3" + es6-symbol "~3.1.0" + event-emitter "~0.3.4" + +es6-set@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.4.tgz#9516b6761c2964b92ff479456233a247dc707ce8" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-iterator "2" + es6-symbol "3" + event-emitter "~0.3.4" + +es6-symbol@3, es6-symbol@~3.1, es6-symbol@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + +es6-weak-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81" + dependencies: + d "^0.1.1" + es5-ext "^0.10.8" + es6-iterator "2" + es6-symbol "3" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-standard@^5.3.5: + version "5.3.5" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-5.3.5.tgz#2b42bb5c9f0049b8527868e109c34ee22b13dcf6" + +eslint-config-standard@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-7.0.1.tgz#6cec96084de9ac862c33ccb953d13a7c59872342" + +eslint-plugin-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-2.0.1.tgz#a9759cefa5e38ab11bb2ef65a04ef042309aa0a4" + +eslint-plugin-promise@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" + +eslint-plugin-standard@^2.0.0, eslint-plugin-standard@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-2.1.1.tgz#97960b1537e1718bb633877d0a650050effff3b0" + +eslint@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.17.1.tgz#b80ae12d9c406d858406fccda627afce33ea10ea" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.4.6" + debug "^2.1.1" + doctrine "^1.2.2" + escope "^3.6.0" + espree "^3.4.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d" + dependencies: + acorn "4.0.4" + acorn-jsx "^3.0.0" + +esprima@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +esrecurse@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" + dependencies: + estraverse "~4.1.0" + object-assign "^4.0.1" + +estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estraverse@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" + +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +event-emitter@~0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.4.tgz#8d63ddfb4cfe1fae3b32ca265c4c720222080bb5" + dependencies: + d "~0.1.1" + es5-ext "~0.10.7" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +flat-cache@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +flow-remove-types@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-1.2.0.tgz#c285516eabba72177a1b10bfb58f6ffb675a8877" + dependencies: + babylon "^6.15.0" + vlq "^0.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.14.0: + version "9.16.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +ignore@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.4.tgz#4055e03596729a8fabe45a43c100ad5ed815c4e8" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" + +is-buffer@^1.0.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-my-json-valid@^2.10.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + +isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +js-tokens@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" + +js-yaml@^3.5.1: + version "3.8.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" + dependencies: + argparse "^1.0.7" + esprima "^3.1.1" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +kind-of@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + dependencies: + is-buffer "^1.0.2" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lodash@^4.0.0, lodash@^4.3.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +magic-string@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.14.0.tgz#57224aef1701caeed273b17a39a956e72b172462" + dependencies: + vlq "^0.2.1" + +minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-homedir@^1.0.0, os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +readable-stream@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.3.tgz#9cf49463985df016c8ae8813097a9293a9b33729" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.6: + version "1.3.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@^2.2.8: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" + dependencies: + glob "^7.0.5" + +rollup-plugin-buble@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-buble/-/rollup-plugin-buble-0.15.0.tgz#83c3e89c7fd2266c7918f41ba3980313519c7fd0" + dependencies: + buble "^0.15.0" + rollup-pluginutils "^1.5.0" + +rollup-plugin-flow@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-flow/-/rollup-plugin-flow-1.1.1.tgz#6ce568f1dd559666b77ab76b4bae251407528db6" + dependencies: + flow-remove-types "^1.1.0" + rollup-pluginutils "^1.5.1" + +rollup-plugin-node-resolve@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-2.0.0.tgz#07e0ae94ac002a3ea36e8f33ca121d9f836b1309" + dependencies: + browser-resolve "^1.11.0" + builtin-modules "^1.1.0" + resolve "^1.1.6" + +rollup-pluginutils@^1.5.0, rollup-pluginutils@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + +rollup@^0.41.4: + version "0.41.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.4.tgz#a970580176329f9ead86854d7fd4c46de752aef8" + dependencies: + source-map-support "^0.4.0" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + +shelljs@^0.7.5: + version "0.7.6" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +source-map-support@^0.4.0: + version "0.4.11" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.11.tgz#647f939978b38535909530885303daf23279f322" + dependencies: + source-map "^0.5.3" + +source-map@^0.5.3, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +uglify-js@^2.8.11: + version "2.8.11" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.11.tgz#11a51c43d810b47bc00aee4d512cb3947ddd1ac4" + dependencies: + source-map "~0.5.1" + uglify-to-browserify "~1.0.0" + yargs "~3.10.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +vlq@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.1.tgz#14439d711891e682535467f8587c5630e4222a6c" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0"