├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .make-package.js ├── .travis.yml ├── .vscode └── launch.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs ├── README.md └── interactions.md ├── examples ├── .eslintrc ├── native │ └── hello │ │ ├── .expo-shared │ │ └── assets.json │ │ ├── .gitignore │ │ ├── .watchmanconfig │ │ ├── App.js │ │ ├── app.json │ │ ├── assets │ │ ├── icon.png │ │ └── splash.png │ │ ├── babel.config.js │ │ ├── package-lock.json │ │ └── package.json └── web │ ├── counter │ ├── counter-component.js │ ├── counter-model.js │ ├── counter.js │ └── index.html │ ├── hello │ ├── hello.js │ └── index.html │ ├── isomorphic │ ├── .babelrc │ ├── README.md │ ├── app.js │ ├── client.js │ ├── package-lock.json │ ├── package.json │ └── server.js │ ├── lib │ ├── examples.html │ └── rx-fromstream.js │ ├── many │ ├── index.html │ ├── many-component.js │ ├── many-model.js │ └── many.js │ ├── server.js │ ├── timer │ ├── .jshintrc │ ├── index.html │ └── timer.js │ └── todomvc │ ├── app.js │ ├── index.html │ ├── local-storage-sink.js │ ├── style.css │ ├── todo-context.js │ ├── todo-item.js │ ├── todo-model.js │ ├── todo-source.js │ ├── todo-view.js │ └── window-location-source.js ├── package-lock.json ├── package.json ├── src ├── index.js ├── interactions.js ├── rxjs-adapter.js ├── rxjs.js └── util.js └── test ├── .eslintrc ├── browser ├── lib │ └── controlled.js └── render.test.js └── common └── interactions.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_style = space 7 | indent_size = 2 8 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | build/ 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "es6": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Editor-specific 2 | .settings 3 | 4 | # Installed libs 5 | node_modules/ 6 | 7 | # Generated 8 | dist/ 9 | coverage/ 10 | build/ 11 | 12 | # Misc 13 | npm-debug.log 14 | -------------------------------------------------------------------------------- /.make-package.js: -------------------------------------------------------------------------------- 1 | var pkg = require('./package.json') 2 | var fs = require('fs'); 3 | var shell = require('shelljs'); 4 | shell.cp('*', 'build/'); 5 | 6 | delete pkg.scripts; 7 | pkg.main = 'index.js'; 8 | fs.writeFileSync('build/package.json', JSON.stringify(pkg, null, 2)); 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | before_script: 5 | # for react peer dependency 6 | - npm install react react-dom 7 | script: npm run travis-test 8 | branches: 9 | only: 10 | - master 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Tests", 6 | "type": "node", 7 | "request": "launch", 8 | "program": "${workspaceRoot}/node_modules/jest/bin/jest.js", 9 | "stopOnEntry": false, 10 | "args": ["--runInBand"], 11 | "cwd": "${workspaceRoot}", 12 | "preLaunchTask": null, 13 | "runtimeExecutable": null, 14 | "runtimeArgs": [ 15 | "--nolazy" 16 | ], 17 | "env": { 18 | "NODE_ENV": "development" 19 | }, 20 | "sourceMaps": false, 21 | "outDir": null 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 7.0.0 4 | 5 | ### Breaking Changes 6 | 7 | - API is completed changed to support Hooks 8 | - React v16.8 or above is required 9 | - Support only RxJS 6 now 10 | 11 | ### Migration 12 | 13 | Almost everything for cycle-react has changed. If you're migrating 14 | your current cycle-react application to 7.0, probably jsx and model 15 | are the only parts that can be reused. 16 | 17 | Please check examples for migration guide. 18 | 19 | ## 6.0.1 20 | 21 | ### New Features 22 | 23 | - Support for [RxJS 5](https://github.com/ReactiveX/rxjs) has been implemented. 24 | - `cycle-react` now takes the advantage of React v16. Default element for empty 25 | Observable has been changed from `
` to empty fragment. 26 | 27 | ### Breaking Changes 28 | 29 | - React v16 or above is required for `cycle-react` v6. 30 | - `props.get` and `props.getAll` are removed. Use [pluck](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-pluck) 31 | instead. 32 | - `dispose` from `definitionFn` is renamed to `unsubscribe`. 33 | - `rootTagName` is removed. Default element is now empty fragment `[]`. 34 | 35 | ### Migration 36 | 37 | For migrating RxJS v4 to v5, see https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md 38 | for details. 39 | 40 | #### import 41 | 42 | ##### OLD 43 | 44 | ```js 45 | import {component} from 'cycle-react'; 46 | ``` 47 | 48 | ##### NEW 49 | 50 | ```js 51 | // RxJS v4 52 | import {component} from 'cycle-react/rx'; 53 | // RxJS v5 54 | import {component} from 'cycle-react/rxjs'; 55 | ``` 56 | 57 | #### props.get 58 | 59 | ##### OLD 60 | 61 | ```js 62 | props.get('foo').map(foo =>

{foo}

); 63 | ``` 64 | 65 | ##### NEW 66 | 67 | ```js 68 | props.pluck('foo').map(foo =>

{foo}

); 69 | // or 70 | props.map(({foo}) =>

{foo}

); 71 | ``` 72 | 73 | #### dispose 74 | 75 | ##### OLD 76 | 77 | ```js 78 | const foo = component('Foo', () => { 79 | // ... 80 | const subscription = source.subscribe(signal => console.log(signal)); 81 | return { 82 | view, 83 | dispose: subscription 84 | }; 85 | }); 86 | ``` 87 | 88 | ##### NEW 89 | 90 | If you use `cycle-react/rx`, `cycle-react` disposes the object that has either `dispose` or `unsubscribe` implemented. 91 | On the other hand, `cycle-react/rxjs` only looks the object that has `unsubscribe` ([Subscription](https://github.com/ReactiveX/rxjs/blob/master/doc/subscription.md)). 92 | 93 | ```js 94 | const foo = component('Foo', () => { 95 | // ... 96 | const subscription = source.subscribe(signal => console.log(signal)); 97 | return { 98 | view, 99 | unsubscribe: subscription 100 | }; 101 | }); 102 | ``` 103 | 104 | ## 5.1.2 105 | 106 | Compatibility fix for `create-react-app` and `react-scripts` 107 | 108 | The NPM package `cycle-react` now contains transpiled code that built 109 | by Babel. This fixes `react-scripts build`'s compatibility issue with 110 | ES6. 111 | 112 | The underlying component class has been changed from `PureComponent` 113 | to `Component`, due to implementation of `shouldComponentUpdate` raises 114 | warning message for `PureComponent`. 115 | 116 | ## 5.0.0 117 | 118 | Breaking change: Custom events is now subscribed only when listener 119 | props is provided upon componentDidMountEvent [#37] 120 | 121 | For example, if you have following component: 122 | 123 | ``` 124 | 125 | ``` 126 | 127 | And you add the event listener after the component has mounted: 128 | 129 | ``` 130 | 131 | ``` 132 | 133 | The `onTick` event will be no longer raised for this cycle-react version. 134 | 135 | Breaking change: `mixin` is removed along with the usage of `createClass` 136 | 137 | Breaking change: `self` and `renderScheduler` have been removed 138 | 139 | As a result, `lifecycles` parameter has moved to the third parameter of 140 | `definitionFn`. For handling [refs](https://facebook.github.io/react/docs/refs-and-the-dom.html), 141 | please use `interactions` for generating callback function. 142 | 143 | See ["Working with React"](/docs/working-with-react.md) for further details. 144 | 145 | Breaking change: `cycle-react` is now native ES6 146 | 147 | Use any transplier if you need backward compatibility for `cycle-react`. 148 | If you are using [Babel](https://babeljs.io/) already you should have 149 | no problem. 150 | 151 | In addition, the following features are not used in cycle-react to ensure 152 | minimum dependency and good efficiency for all browsers. 153 | 154 | - Async 155 | - Iterators and generators 156 | - Symbol 157 | - for..of 158 | - Destructuring assignment 159 | - Default, spread and rest parameters 160 | - Promise 161 | 162 | You can still use any of the features above in your project with cycle-react. 163 | In fact, using destructuring assignment with cycle-react is recommended. 164 | 165 | - Preview: View component 166 | 167 | View component is a new way to define cycle-react components by divorcing view 168 | function from the component. For example, the original component function 169 | allows you to define the component like this: 170 | 171 | ``` 172 | component('Hello', (interactions) => 173 | interactions.get('OnNameChanged') 174 | .map(ev => ev.target.value) 175 | .startWith('') 176 | .map(name => 177 |
178 | 179 | 180 |
181 |

Hello {name}

182 |
183 | ) 184 | ); 185 | ``` 186 | 187 | New view component extracts the view function out of component definition: 188 | 189 | ``` 190 | viewComponent( 191 | 'Hello', 192 | (interactions) => 193 | interactions.get('OnNameChanged') 194 | .map(ev => ev.target.value) 195 | .startWith(''), 196 | // View function 197 | (name, {OnNameChanged}) => ( 198 |
199 | 200 | 201 |
202 |

Hello {name}

203 |
204 | ) 205 | ); 206 | ``` 207 | 208 | ## 4.0.0 209 | 210 | Breaking change: `rx` is a peer dependency now [#21] 211 | 212 | Breaking change: The shortcut for React and Rx are both removed [#21] 213 | 214 | Add feature: Added render scheduler for supporting refs, 215 | see `working-with-react.md` for the details [#23] 216 | 217 | Fix: The feature of using function wrapper for view is no longer deprecated [#23] 218 | 219 | Fix: The `onCompleted` signal will be emitted for all lifecycle observables 220 | before the component being unmounted 221 | 222 | ## 3.1.0 223 | 224 | Add feature: Support lifecycle events by the fourth parameter `lifecycles` 225 | for the component's definitionFn. [#18] 226 | 227 | See `working-with-react.md` for details. 228 | 229 | ## 3.0.0 230 | 231 | Breaking change: applyToDOM and makeDOMDriver are both removed. Use `ReactDOM.render` instead. 232 | 233 | Deprecated: Deprecated `bindThis` with the function as view. 234 | 235 | ## 2.0.0 236 | 237 | Add feature: Support React Native. Thank @cem2ran for the PR. 238 | 239 | Breaking change: The peer dependency of React has been removed. 240 | 241 | > React 0.13 and React Native 0.7 are the supported versions of Cycle-React. 242 | > Cycle-React will put the dependency of React back once the isomorphic 243 | > module of [React 0.14](https://facebook.github.io/react/blog/2015/07/03/react-v0.14-beta-1.html) 244 | > has been released. 245 | 246 | > In addition, Cycle-React will move "applyToDOM" and "makeDOMDriver" 247 | > into the separated package for the upcoming "react-dom" package. 248 | 249 | ## 1.0.1 250 | 251 | MAJOR RELEASE: 1.0.1 is the stable version of Cycle-React. 252 | 253 | Add feature: `props.getAll()` returns the Observable of the whole properties object 254 | [#10] 255 | 256 | > Alternatively, you can use `props.get('*')` or simply `props` for the exact same effect. 257 | 258 | Breaking change: `props.get(propertyName)` uses (x === y) comparison instead of 259 | deep-equal comparison for the target property 260 | 261 | > Use `props.get('*')` or `props` if you have changes inside a nested object. 262 | 263 | > Alternatively, you can provide the customized comparer by 264 | `props.get(name, (x, y) => {})` 265 | 266 | Breaking change: `renderAsHTML` has been removed 267 | 268 | > Use `React.renderToString` with `Cycle.component` instead. 269 | > Examples can be found at `test/node/html-render.js` and `examples/isomorphic`. 270 | 271 | Breaking change: The `h` hyperscript helper has been removed [#11] 272 | 273 | Breaking change: Interactions API no longer uses selector for querying events 274 | [#8, #12] 275 | 276 | > The selector API cannot handle both Cycle-React components and other React 277 | components that use event handlers. We want to keep the compatibility with 278 | the original React while not confusing developers. Therefore, the selector API 279 | has been removed in favor of event handler API. 280 | > Information of the new interactions API can be found at docs/interactions.md 281 | 282 | > The migration guide can be found below. 283 | 284 | Breaking change: `on` prefix is no longer appended to event handlers for 285 | Cycle-React components 286 | 287 | Breaking change: Event detail is no longer wrapped by CustomEvent 288 | 289 | Breaking change: The option "noDOMDispatchEvent" has been removed since 290 | Cycle-React no longer dispatches events from DOM right now 291 | 292 | ### BEFORE 293 | 294 | ```js 295 | // Component: 296 | let MyComponent = Cycle.component('MyComponent', function (interactions, props) { 297 | let vtree$ = interactions.get('.myinput', 'change') 298 | .map(ev => ev.target.value) 299 | .startWith('') 300 | .map(name => 301 |
302 | 303 |

Hello {name}

304 |
305 | ); 306 | return { 307 | view: vtree$, 308 | events: { 309 | myComponentTick: Rx.Observable.interval(1000) 310 | } 311 | }; 312 | }); 313 | // Intentions: 314 | interactions.subject('tick').map(ev => ev.detail); 315 | // View: 316 | 317 | ``` 318 | 319 | ### AFTER 320 | 321 | ```js 322 | // Component: 323 | let MyComponent = Cycle.component('MyComponent', function (interactions, props) { 324 | // You must use `get` to query events 325 | // and use `listener` to create event handlers. 326 | let vtree$ = interactions.get('OnMyInputChange') 327 | .map(ev => ev.target.value) 328 | .startWith('') 329 | .map(name => 330 |
331 | 333 |

Hello {name}

334 |
335 | ); 336 | return { 337 | view: vtree$, 338 | events: { 339 | // The event handler is no longer auto-prefixed by "on" 340 | onMyComponentTick: Rx.Observable.interval(1000) 341 | } 342 | }; 343 | }); 344 | // Intentions: 345 | // Event arguments from Cycle-React components are no longer 346 | // wrapped by CustomEvent. 347 | interactions.get('tick').map(ev => ev); 348 | // View: 349 | // Use interactions.listener(name) to create event handler 350 | 351 | ``` 352 | 353 | ### Migration 354 | 355 | 1. Append the "on" prefix to every event observable inside the events object 356 | of the component 357 | 2. Rewrite the code that used `interactions.get(selector, eventType)` by using 358 | `interactions.get(eventName)` and `interactions.listener(eventName)` like the 359 | example above 360 | 3. Replace `interactions.subject(name).onEvent` with `interactions.listener(name)` 361 | 4. Replace 362 | `interactions.subject(name)` and `interactions.getEventSubject(name)` 363 | with `interactions.get(name)` 364 | 5. Replace `ev.detail` with `ev` 365 | 366 | ## 0.27.0 367 | 368 | Breaking change: Rename "createReactClass" to "component" 369 | 370 | For migrating to 0.27, simply replace the string "createReactClass" 371 | to "component". 372 | 373 | Fix: Remove unnecessary update on `props` change 374 | 375 | Add feature: New option "noDOMDispatchEvent" for skipping DOM dispatchEvent 376 | 377 | Use "noDOMDispatchEvent" if you want to handle events by using event handlers 378 | completely instead of using `interactions.get` API. 379 | 380 | ## 0.26.0 381 | 382 | Breaking change: Cycle v0.23(or v1.0 API) compatibility changes 383 | 384 | ### BEFORE 385 | 386 | ```js 387 | var MyComponent = CycleReact.createReactClass('MyComponent', 388 | function (interactions, props) { 389 | var destroy$ = interactions.get('.remove-btn', 'click'); 390 | var id$ = props.get('itemid'); 391 | // ... 392 | return { 393 | vtree$: Rx.Observable.just(

view

), 394 | destroy$: destroy$, 395 | changeColor$: changeColor$, 396 | changeWidth$: changeWidth$ 397 | }; 398 | } 399 | ); 400 | ``` 401 | 402 | ```js 403 | // Event handler usage 404 | // See docs/interactions.md 405 | 406 | ``` 407 | 408 | ### AFTER 409 | 410 | ```js 411 | var MyComponent = CycleReact.createReactClass('MyComponent', 412 | function (interactions, props) { 413 | var destroy$ = interactions.get('.remove-btn', 'click'); 414 | var id$ = props.get('itemid'); 415 | // ... 416 | return { 417 | view: Rx.Observable.just(

view

), 418 | events: { 419 | destroy: destroy$, 420 | changeColor: changeColor$, 421 | changeWidth: changeWidth$ 422 | } 423 | }; 424 | } 425 | ); 426 | ``` 427 | 428 | ```js 429 | // Event handler usage 430 | // See docs/interactions.md 431 | 432 | ``` 433 | 434 | ### Migration 435 | 436 | 1. Replace the return of the definition function from return 437 | {vtree$, myEvent$, ...} to return {view: vtree$, events: ...}, 438 | where events: ... is an object where keys are the event name (notice no more 439 | dollar sign $ convention!) and values are Observables 440 | 2. Remove the $ sign from event handlers 441 | 3. You're good to go 442 | 443 | Unlike Cycle.js 0.23 which `interactions` and `props` are replaced by drivers, 444 | Cycle-React keeps these parameters because Cycle-React allows you to create 445 | React components outside the context of `Cycle.run`. 446 | 447 | Additionally, Cycle-React will keep `applyToDOM` and `renderAsHTML` for 448 | simple web-app development usage. 449 | 450 | Add feature: Cycle.js driver 451 | 452 | See docs/cycle-js-driver.md for details. 453 | 454 | ## 0.25.0 455 | 456 | Breaking change: shouldComponentUpdate is now built-in and no longer being 457 | able to be overridden by mixins 458 | 459 | Breaking change: like 460 | [Cycle.js 0.22](https://github.com/staltz/cycle/releases/tag/v0.22.0), 461 | `event.detail` is now used instead of `event.data` 462 | 463 | Breaking change: `interactions.get` is now implemented as: 464 | 465 | ``` 466 | Rx.Observable.fromEvent(RootElement, eventName) 467 | .filter(e => e.target.matches(selector)) 468 | ``` 469 | 470 | Instead of: 471 | 472 | ``` 473 | Rx.Observable.fromEvent(RootElement.querySelector(selector), eventName) 474 | ``` 475 | 476 | ## 0.24.0 477 | 478 | Breaking change: createEventSubject has been removed 479 | 480 | Use `interactions.getEventSubject(name)` and 481 | `interactions.subject(name)`(alias) instead. It's a better design to have 482 | event subscriptions stay within the interactions. See `interactions.md` for 483 | details. 484 | 485 | Add feature: Disposable element 486 | 487 | Sometimes, it's not an easy task to manage all your disposables by 488 | using `Observable.using`. This new property of custom-element allows 489 | you to dispose resources when React triggered the `componentWillUnmount` 490 | lifecycle method. 491 | 492 | ```js 493 | Cycle.createReactClass('MyElement', () => { 494 | return { 495 | vtree$: ..., 496 | dispose: function dispose() { 497 | // This function will be called during the 498 | // componentWillUnmount lifecycle event 499 | } 500 | // You can set Rx.Disposable objects(e.g. subscription) 501 | // instead of function to the dispose property, too. 502 | } 503 | }); 504 | ``` 505 | 506 | Add feature: Refs compatibility 507 | 508 | See `working-with-react.md` for details. 509 | 510 | ## 0.23.0 511 | 512 | Add feature: Support react-hot-loader 513 | 514 | Cycle-React now overrides `forceUpdate` when `module.hot == true` 515 | (webpack hot module enabled). No extra configuration needed. 516 | This overriding behavior only affects the ReactClass created by Cycle-React 517 | and has no effect if webpack-hot-module was disabled. 518 | 519 | Add feature: createReactClass options, see docs/api.md for details 520 | 521 | Change: "react" is moved to peer dependencies 522 | 523 | ## 0.22.0 524 | 525 | Add feature: props.get('\*') for custom elements 526 | 527 | props.get('\*') returns the Observable of the whole properties object, 528 | as given to the custom element in the parent vtree context. 529 | 530 | Additionally, props equals to props.get('\*') in Cycle-React. Which means you 531 | can skip `.get('*')` and get the Observable of the properties object. 532 | This shortcut is not available for the original Cycle.js. 533 | 534 | Add feature: createEventSubject, a helper for using Rx subject as event handler 535 | 536 | Details can be found at API docs. 537 | 538 | ## 0.21.0 539 | 540 | The alpha. 541 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | First of all, thank you for contributing. It’s appreciated. 2 | 3 | 1. Clone the repo and install dependencies with `npm install`. 4 | 2. Make a GitHub issue before doing significant amount of work. 5 | 3. Run `npm test` to lint and test. Don’t commit before fixing all errors and warnings. 6 | 4. Reference the issue’s number in your commit. E.g.: “Did this #12” 7 | 5. Make a pull request. 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ting-Yu Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cycle-React 2 | 3 | [![Build Status](https://travis-ci.org/pH200/cycle-react.svg?branch=master)](https://travis-ci.org/pH200/cycle-react) 4 | 5 | An [RxJS](https://github.com/ReactiveX/rxjs) functional interface 6 | to [Facebook's React](https://reactjs.org/). 7 | 8 | Cycle-React creates custom [React](https://github.com/facebook/react) 9 | [Hooks](https://reactjs.org/docs/hooks-intro.html) and allow applications 10 | to be written in functional style and control data flow with Observables. 11 | 12 | Additionally, Cycle-React is inspired by a beautiful 13 | framework called [Cycle.js](https://github.com/cyclejs/cycle-core). 14 | 15 | ## Installing 16 | 17 | ``` 18 | npm install cycle-react react rxjs 19 | ``` 20 | 21 | React v16.8 or later is **required**. 22 | 23 | Currently, Only RxJS 6 is supported. For migrating RxJS with cycle-react v7, see release note for details. 24 | 25 | ## Example 26 | 27 | ```js 28 | import React from 'react'; 29 | import ReactDOM from 'react-dom'; 30 | import { useInteractions } from 'cycle-react'; 31 | import { map } from 'rxjs/operators' 32 | 33 | const [interactions, useCycle] = useInteractions( 34 | '', // Initial state 35 | { // Interaction operators 36 | onNameChange: map(ev => currentState => ev.target.value) 37 | } 38 | ); 39 | 40 | function View() { 41 | const name = useCycle(); 42 | return ( 43 |
44 | 45 | 47 |
48 |

Hello {name}

49 |
50 | ); 51 | } 52 | 53 | ReactDOM.render( 54 | , 55 | document.querySelector('.js-container') 56 | ); 57 | ``` 58 | 59 | `interactions` is a collection containing all user interaction events happening 60 | on the user-defined event handlers on the DOM, which you can define by providing 61 | `Object.`. And the event handler for DOM can be defined by 62 | `interactions.listener(eventName)` or simply `interactions(eventName)`. 63 | 64 | Function `useInteractions` subscribes the Observable which is the combination of all 65 | interactions merged together, and calls `setState` from `useState(initialState)`. 66 | By connecting `interactions` and `setState`, the Observable of user interactions and 67 | state changes is completed. 68 | 69 | You can learn more about the concept behind `interactions` and `Cycle` from 70 | André's amazing presentation: 71 | ["What if the user was a function?"](https://youtu.be/1zj7M1LnJV4) 72 | 73 | ## From Redux to Cycle-React 74 | 75 | Redux | Cycle-React 76 | --- | --- 77 | Actions | Interactions name 78 | Reducers | Interactions operator 79 | Store | Interactions object and side-effect from useCycle 80 | Provider | [createContext](https://reactjs.org/docs/context.html) - Check example TodoMVC for details. 81 | dispatch(action) | interactions(action) 82 | 83 | ## Learn more 84 | 85 | Cycle-React is a React-style implementation of Cycle.js, so we have the same 86 | concept of handling user interactions. Learn more on: 87 | http://cycle.js.org/dialogue.html 88 | 89 | In addition, we're working on the documentation site for Cycle-React with more 90 | useful examples, too. Stay tuned! 91 | 92 | ## React Native 93 | 94 | Example can be found at [examples/native](/examples/native) 95 | 96 | ## FAQ 97 | 98 | ### What operators are used from RxJS 6? 99 | 100 | [src/rxjs-adapter.js](/src/rxjs-adapter.js) 101 | 102 | Specifically, `merge` and `Subject` from `rxjs`, and `scan`, `startWith` from `rxjs/operators`. 103 | 104 | ### Can I use Cycle-React with [Redux](https://redux.js.org/)? 105 | 106 | Not recommended anymore after Cycle-React 7.0. Think Cycle-React as a concise RxJS version of Redux. 107 | 108 | ### Can I host a Cycle-React application in another Cycle-React application? 109 | 110 | Nested composition has not supported yet. 111 | 112 | ## Run examples 113 | 114 | `npm run examples` starts an HTTP server that shows examples 115 | 116 | ## Community 117 | 118 | * Ask "_how do I...?_" questions in Cycle-React's Gitter:
119 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pH200/cycle-react?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 120 | * Propose and discuss significant changes as a GitHub issues 121 | 122 | ## Contributions and thanks 123 | 124 | - [@cem2ran](https://github.com/cem2ran) for adding the support of React Native 125 | - [@corps](https://github.com/corps) for implementing the render scheduler feature 126 | 127 | ## License 128 | 129 | [The MIT License](/LICENSE) 130 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ### Documentations 2 | 3 | - [Interactions API](/docs/interactions.md) 4 | 5 | ### Where to ask for help? 6 | 7 | Join the Gitter chat room
8 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/pH200/cycle-react?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 9 | -------------------------------------------------------------------------------- /docs/interactions.md: -------------------------------------------------------------------------------- 1 | # Interactions API 2 | 3 | ## interactions.get 4 | 5 | Get the event observable from interactions collection. 6 | 7 | Example: 8 | 9 | ```js 10 | Cycle.component('MyElement', function computer(interactions) { 11 | // get(eventName: string): Observable 12 | return interactions.get('OnMyInput') 13 | .map(ev => ev.target.value) 14 | .startWith('') 15 | .map(inputValue => 16 | 19 | ); 20 | }); 21 | ``` 22 | 23 | ## interactions.listener 24 | 25 | Create an event listener for receiving events from React components. 26 | 27 | Example: 28 | 29 | ```js 30 | // listener(eventName: string): (ev: any) => void 31 | 32 | ``` 33 | 34 | ## interactions.bindListeners 35 | 36 | Create an object with event listeners that have the property names mapped from 37 | the `interactionTypes` parameter. 38 | 39 | This helper method is inspired by `bindActionCreators` from 40 | [redux](https://github.com/gaearon/redux). 41 | 42 | Example: 43 | 44 | ```js 45 | // Define interaction types 46 | let interactionTypes = { 47 | IncrementCounter: 'INCREMENT_COUNTER', 48 | DecrementCounter: 'DECREMENT_COUNTER' 49 | }; 50 | // bindListeners(interactionsTypes: any): any 51 | let listeners = interactions.bindListeners(interactionsTypes); 52 | // View 53 | 54 | ``` 55 | 56 | ```js 57 | // Intentions 58 | import {IncrementCounter, DecrementCounter} from './interaction-types'; 59 | export default function intent(interactions) { 60 | return { 61 | incrementCounterObservable: interactions.get(IncrementCounter), 62 | decrementCounterObservable: interactions.get(DecrementCounter) 63 | }; 64 | } 65 | ``` 66 | -------------------------------------------------------------------------------- /examples/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "browser": true, 5 | "es6": true 6 | }, 7 | "parserOptions": { 8 | "sourceType": "module", 9 | "ecmaFeatures": { 10 | "jsx": true 11 | } 12 | }, 13 | "extends": [ 14 | "eslint:recommended" 15 | ], 16 | "rules": { 17 | "no-console": 0, 18 | "no-unused-vars": 0 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/native/hello/.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "f9155ac790fd02fadcdeca367b02581c04a353aa6d5aa84409a59f6804c87acd": true, 3 | "89ed26367cdb9b771858e026f2eb95bfdb90e5ae943e716575327ec325f39c44": true 4 | } -------------------------------------------------------------------------------- /examples/native/hello/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | web-build/ 11 | web-report/ 12 | -------------------------------------------------------------------------------- /examples/native/hello/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /examples/native/hello/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | StyleSheet, 4 | Text, 5 | TextInput, 6 | View 7 | } from 'react-native'; 8 | import { useInteractions } from 'cycle-react/rxjs'; 9 | import { map } from 'rxjs/operators'; 10 | 11 | const [interactions, useCycle] = useInteractions( 12 | '', 13 | { 14 | onInputChange: map(ev => () => ev.nativeEvent.text) 15 | } 16 | ); 17 | 18 | export default function Hello() { 19 | const name = useCycle(); 20 | return ( 21 | 22 | Name: 23 | 26 | Hello {name} 27 | 28 | ); 29 | } 30 | 31 | const styles = StyleSheet.create({ 32 | container: { 33 | flex: 1, 34 | justifyContent: 'center', 35 | alignItems: 'center', 36 | backgroundColor: '#F5FCFF', 37 | }, 38 | welcome: { 39 | fontSize: 20, 40 | textAlign: 'center', 41 | margin: 10, 42 | }, 43 | instructions: { 44 | textAlign: 'center', 45 | color: '#333333', 46 | marginBottom: 5, 47 | }, 48 | }); 49 | -------------------------------------------------------------------------------- /examples/native/hello/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "Hello", 4 | "slug": "hello", 5 | "privacy": "public", 6 | "sdkVersion": "34.0.0", 7 | "platforms": [ 8 | "ios", 9 | "android", 10 | "web" 11 | ], 12 | "version": "1.0.0", 13 | "orientation": "portrait", 14 | "icon": "./assets/icon.png", 15 | "splash": { 16 | "image": "./assets/splash.png", 17 | "resizeMode": "contain", 18 | "backgroundColor": "#ffffff" 19 | }, 20 | "updates": { 21 | "fallbackToCacheTimeout": 0 22 | }, 23 | "assetBundlePatterns": [ 24 | "**/*" 25 | ], 26 | "ios": { 27 | "supportsTablet": true 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /examples/native/hello/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pH200/cycle-react/5a79abe1c08fd991310ab2d3ab86a737f99a94c2/examples/native/hello/assets/icon.png -------------------------------------------------------------------------------- /examples/native/hello/assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pH200/cycle-react/5a79abe1c08fd991310ab2d3ab86a737f99a94c2/examples/native/hello/assets/splash.png -------------------------------------------------------------------------------- /examples/native/hello/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'], 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /examples/native/hello/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "cycle-react": "^7.0.0", 12 | "expo": "^34.0.1", 13 | "react": "16.8.3", 14 | "react-dom": "^16.8.6", 15 | "react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz", 16 | "react-native-web": "^0.11.4", 17 | "rxjs": "^6.5.2" 18 | }, 19 | "devDependencies": { 20 | "babel-preset-expo": "^6.0.0" 21 | }, 22 | "private": true 23 | } 24 | -------------------------------------------------------------------------------- /examples/web/counter/counter-component.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function Counter(props) { 4 | function incrementIfOdd() { 5 | if (props.value % 2 !== 0) { 6 | props.onIncrement() 7 | } 8 | } 9 | 10 | function incrementAsync() { 11 | setTimeout(props.onIncrement, 1000) 12 | } 13 | 14 | return ( 15 |

16 | Clicked: {props.value} times 17 | {' '} 18 | 21 | {' '} 22 | 25 | {' '} 26 | 29 | {' '} 30 | 33 |

34 | ); 35 | } 36 | 37 | export default Counter 38 | -------------------------------------------------------------------------------- /examples/web/counter/counter-model.js: -------------------------------------------------------------------------------- 1 | // This example merges the "intent" tier into the "model" tier. 2 | // See "many" and "todomvc" for MVI examples. 3 | import {map} from 'rxjs/operators' 4 | 5 | export default function model() { 6 | return { 7 | // equal to: observable => map(() => counter => counter + 1)(observable) 8 | onIncrement: map(() => counter => counter + 1), 9 | onDecrement: map(() => counter => counter - 1) 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /examples/web/counter/counter.js: -------------------------------------------------------------------------------- 1 | import model from './counter-model'; 2 | import Counter from './counter-component'; 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import {useInteractions} from 'cycle-react/rxjs'; 6 | 7 | const [interactions, useCycle] = useInteractions( 8 | 0, // initial state 9 | model() // model 10 | ); 11 | 12 | function Root() { 13 | // Setup useState, useEffect and get state from useState 14 | const state = useCycle(); 15 | return ( 16 |
17 | 20 |
21 |

Compare with redux

22 |
23 | ); 24 | } 25 | 26 | ReactDOM.render( 27 | , 28 | document.querySelector('.js-container') 29 | ); 30 | -------------------------------------------------------------------------------- /examples/web/counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Counter Example - The Cycle-React's implementation to redux' counter example 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/web/hello/hello.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { useInteractions } from 'cycle-react/rxjs'; 4 | import { map } from 'rxjs/operators' 5 | 6 | const [interactions, useCycle] = useInteractions( 7 | '', // initial state 8 | {onNameChange: map(ev => currentState => ev.target.value)} 9 | ); 10 | 11 | 12 | function View() { 13 | const name = useCycle(); 14 | return ( 15 |
16 | 17 | 19 |
20 |

Hello {name}

21 |
22 | ); 23 | } 24 | 25 | ReactDOM.render( 26 | , 27 | document.querySelector('.js-container') 28 | ); 29 | -------------------------------------------------------------------------------- /examples/web/hello/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hello World Example 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/web/isomorphic/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/web/isomorphic/README.md: -------------------------------------------------------------------------------- 1 | `npm install && npm run start` 2 | 3 | - `server.js` Server block 4 | - `app.js` The web app 5 | - `client.js` Client-side bootstrapper 6 | -------------------------------------------------------------------------------- /examples/web/isomorphic/app.js: -------------------------------------------------------------------------------- 1 | const { useInteractions } = require('../../../src/rxjs'); 2 | const { fromEvent, pipe } = require('rxjs'); 3 | const { map, distinctUntilChanged, tap } = require('rxjs/operators'); 4 | const React = require('react'); 5 | 6 | function Menu(props) { 7 | return ( 8 | 12 | ); 13 | } 14 | 15 | function HomePage(props) { 16 | return ( 17 |
18 |

The homepage

19 |

Welcome to our spectacular web page with literally nothing special here.

20 | 21 |
22 | ); 23 | } 24 | 25 | function AboutPage(props) { 26 | return ( 27 |
28 |

Read more about us

29 |

This is the page where we describe ourselves.

30 |

In reality, I have no idea what I'm doing.

{/*'close quote*/} 31 | 32 |
33 | ); 34 | } 35 | 36 | function createApp(initialState) { 37 | const sinks = []; 38 | if (typeof window !== 'undefined' && typeof document !== 'undefined') { 39 | sinks.push( 40 | fromEvent(window, 'popstate').pipe( 41 | map(() => document.location.pathname), 42 | tap(route => console.log('pop: ' + route)), 43 | map(route => () => ({route})) 44 | ) 45 | ); 46 | } 47 | 48 | const [interactions, useCycle] = useInteractions( 49 | initialState, 50 | { 51 | RouteClick: pipe( 52 | distinctUntilChanged(), 53 | tap(route => { 54 | if (typeof window !== 'undefined') { 55 | console.log('push: ' + route); 56 | window.history.pushState(null, '', route); 57 | } 58 | }), 59 | map(route => state => ({route})) 60 | ) 61 | }, 62 | sinks 63 | ); 64 | return function App() { 65 | const state = useCycle(); 66 | 67 | function onRouteClick(ev) { 68 | ev.preventDefault(); 69 | interactions('RouteClick')(ev.target.attributes.href.value); 70 | } 71 | 72 | const route = state.route; 73 | switch (route) { 74 | case '/': return ; 75 | case '/about': return ; 76 | default: return
Unknown page {route}
; 77 | } 78 | }; 79 | } 80 | 81 | module.exports = { createApp }; 82 | -------------------------------------------------------------------------------- /examples/web/isomorphic/client.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactDOM = require('react-dom'); 3 | const {createApp} = require('./app'); 4 | 5 | ReactDOM.hydrate( 6 | React.createElement(createApp(window.appContext)), 7 | document.querySelector('.app-container') 8 | ); 9 | -------------------------------------------------------------------------------- /examples/web/isomorphic/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cycle-isomorphic-example", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.5.5", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", 10 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", 11 | "requires": { 12 | "@babel/highlight": "^7.0.0" 13 | } 14 | }, 15 | "@babel/core": { 16 | "version": "7.5.5", 17 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", 18 | "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", 19 | "requires": { 20 | "@babel/code-frame": "^7.5.5", 21 | "@babel/generator": "^7.5.5", 22 | "@babel/helpers": "^7.5.5", 23 | "@babel/parser": "^7.5.5", 24 | "@babel/template": "^7.4.4", 25 | "@babel/traverse": "^7.5.5", 26 | "@babel/types": "^7.5.5", 27 | "convert-source-map": "^1.1.0", 28 | "debug": "^4.1.0", 29 | "json5": "^2.1.0", 30 | "lodash": "^4.17.13", 31 | "resolve": "^1.3.2", 32 | "semver": "^5.4.1", 33 | "source-map": "^0.5.0" 34 | }, 35 | "dependencies": { 36 | "debug": { 37 | "version": "4.1.1", 38 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 39 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 40 | "requires": { 41 | "ms": "^2.1.1" 42 | } 43 | }, 44 | "ms": { 45 | "version": "2.1.2", 46 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 47 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 48 | } 49 | } 50 | }, 51 | "@babel/generator": { 52 | "version": "7.5.5", 53 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", 54 | "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", 55 | "requires": { 56 | "@babel/types": "^7.5.5", 57 | "jsesc": "^2.5.1", 58 | "lodash": "^4.17.13", 59 | "source-map": "^0.5.0", 60 | "trim-right": "^1.0.1" 61 | } 62 | }, 63 | "@babel/helper-builder-react-jsx": { 64 | "version": "7.3.0", 65 | "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.3.0.tgz", 66 | "integrity": "sha512-MjA9KgwCuPEkQd9ncSXvSyJ5y+j2sICHyrI0M3L+6fnS4wMSNDc1ARXsbTfbb2cXHn17VisSnU/sHFTCxVxSMw==", 67 | "requires": { 68 | "@babel/types": "^7.3.0", 69 | "esutils": "^2.0.0" 70 | } 71 | }, 72 | "@babel/helper-function-name": { 73 | "version": "7.1.0", 74 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", 75 | "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", 76 | "requires": { 77 | "@babel/helper-get-function-arity": "^7.0.0", 78 | "@babel/template": "^7.1.0", 79 | "@babel/types": "^7.0.0" 80 | } 81 | }, 82 | "@babel/helper-get-function-arity": { 83 | "version": "7.0.0", 84 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", 85 | "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", 86 | "requires": { 87 | "@babel/types": "^7.0.0" 88 | } 89 | }, 90 | "@babel/helper-plugin-utils": { 91 | "version": "7.0.0", 92 | "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", 93 | "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" 94 | }, 95 | "@babel/helper-split-export-declaration": { 96 | "version": "7.4.4", 97 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", 98 | "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", 99 | "requires": { 100 | "@babel/types": "^7.4.4" 101 | } 102 | }, 103 | "@babel/helpers": { 104 | "version": "7.5.5", 105 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", 106 | "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", 107 | "requires": { 108 | "@babel/template": "^7.4.4", 109 | "@babel/traverse": "^7.5.5", 110 | "@babel/types": "^7.5.5" 111 | } 112 | }, 113 | "@babel/highlight": { 114 | "version": "7.5.0", 115 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", 116 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", 117 | "requires": { 118 | "chalk": "^2.0.0", 119 | "esutils": "^2.0.2", 120 | "js-tokens": "^4.0.0" 121 | } 122 | }, 123 | "@babel/node": { 124 | "version": "7.5.5", 125 | "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.5.5.tgz", 126 | "integrity": "sha512-xsW6il+yY+lzXMsQuvIJNA7tU8ix/f4G6bDt4DrnCkVpsR6clk9XgEbp7QF+xGNDdoD7M7QYokCH83pm+UjD0w==", 127 | "dev": true, 128 | "requires": { 129 | "@babel/polyfill": "^7.0.0", 130 | "@babel/register": "^7.5.5", 131 | "commander": "^2.8.1", 132 | "lodash": "^4.17.13", 133 | "node-environment-flags": "^1.0.5", 134 | "v8flags": "^3.1.1" 135 | } 136 | }, 137 | "@babel/parser": { 138 | "version": "7.5.5", 139 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", 140 | "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==" 141 | }, 142 | "@babel/plugin-syntax-jsx": { 143 | "version": "7.2.0", 144 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz", 145 | "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==", 146 | "requires": { 147 | "@babel/helper-plugin-utils": "^7.0.0" 148 | } 149 | }, 150 | "@babel/plugin-transform-react-display-name": { 151 | "version": "7.2.0", 152 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz", 153 | "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==", 154 | "requires": { 155 | "@babel/helper-plugin-utils": "^7.0.0" 156 | } 157 | }, 158 | "@babel/plugin-transform-react-jsx": { 159 | "version": "7.3.0", 160 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.3.0.tgz", 161 | "integrity": "sha512-a/+aRb7R06WcKvQLOu4/TpjKOdvVEKRLWFpKcNuHhiREPgGRB4TQJxq07+EZLS8LFVYpfq1a5lDUnuMdcCpBKg==", 162 | "requires": { 163 | "@babel/helper-builder-react-jsx": "^7.3.0", 164 | "@babel/helper-plugin-utils": "^7.0.0", 165 | "@babel/plugin-syntax-jsx": "^7.2.0" 166 | } 167 | }, 168 | "@babel/plugin-transform-react-jsx-self": { 169 | "version": "7.2.0", 170 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz", 171 | "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==", 172 | "requires": { 173 | "@babel/helper-plugin-utils": "^7.0.0", 174 | "@babel/plugin-syntax-jsx": "^7.2.0" 175 | } 176 | }, 177 | "@babel/plugin-transform-react-jsx-source": { 178 | "version": "7.5.0", 179 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz", 180 | "integrity": "sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg==", 181 | "requires": { 182 | "@babel/helper-plugin-utils": "^7.0.0", 183 | "@babel/plugin-syntax-jsx": "^7.2.0" 184 | } 185 | }, 186 | "@babel/polyfill": { 187 | "version": "7.4.4", 188 | "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.4.4.tgz", 189 | "integrity": "sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg==", 190 | "dev": true, 191 | "requires": { 192 | "core-js": "^2.6.5", 193 | "regenerator-runtime": "^0.13.2" 194 | } 195 | }, 196 | "@babel/preset-react": { 197 | "version": "7.0.0", 198 | "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz", 199 | "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==", 200 | "requires": { 201 | "@babel/helper-plugin-utils": "^7.0.0", 202 | "@babel/plugin-transform-react-display-name": "^7.0.0", 203 | "@babel/plugin-transform-react-jsx": "^7.0.0", 204 | "@babel/plugin-transform-react-jsx-self": "^7.0.0", 205 | "@babel/plugin-transform-react-jsx-source": "^7.0.0" 206 | } 207 | }, 208 | "@babel/register": { 209 | "version": "7.5.5", 210 | "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.5.5.tgz", 211 | "integrity": "sha512-pdd5nNR+g2qDkXZlW1yRCWFlNrAn2PPdnZUB72zjX4l1Vv4fMRRLwyf+n/idFCLI1UgVGboUU8oVziwTBiyNKQ==", 212 | "dev": true, 213 | "requires": { 214 | "core-js": "^3.0.0", 215 | "find-cache-dir": "^2.0.0", 216 | "lodash": "^4.17.13", 217 | "mkdirp": "^0.5.1", 218 | "pirates": "^4.0.0", 219 | "source-map-support": "^0.5.9" 220 | }, 221 | "dependencies": { 222 | "core-js": { 223 | "version": "3.2.1", 224 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", 225 | "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==", 226 | "dev": true 227 | } 228 | } 229 | }, 230 | "@babel/template": { 231 | "version": "7.4.4", 232 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", 233 | "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", 234 | "requires": { 235 | "@babel/code-frame": "^7.0.0", 236 | "@babel/parser": "^7.4.4", 237 | "@babel/types": "^7.4.4" 238 | } 239 | }, 240 | "@babel/traverse": { 241 | "version": "7.5.5", 242 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", 243 | "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", 244 | "requires": { 245 | "@babel/code-frame": "^7.5.5", 246 | "@babel/generator": "^7.5.5", 247 | "@babel/helper-function-name": "^7.1.0", 248 | "@babel/helper-split-export-declaration": "^7.4.4", 249 | "@babel/parser": "^7.5.5", 250 | "@babel/types": "^7.5.5", 251 | "debug": "^4.1.0", 252 | "globals": "^11.1.0", 253 | "lodash": "^4.17.13" 254 | }, 255 | "dependencies": { 256 | "debug": { 257 | "version": "4.1.1", 258 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 259 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 260 | "requires": { 261 | "ms": "^2.1.1" 262 | } 263 | }, 264 | "ms": { 265 | "version": "2.1.2", 266 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 267 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 268 | } 269 | } 270 | }, 271 | "@babel/types": { 272 | "version": "7.5.5", 273 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", 274 | "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", 275 | "requires": { 276 | "esutils": "^2.0.2", 277 | "lodash": "^4.17.13", 278 | "to-fast-properties": "^2.0.0" 279 | } 280 | }, 281 | "JSONStream": { 282 | "version": "1.3.5", 283 | "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", 284 | "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", 285 | "requires": { 286 | "jsonparse": "^1.2.0", 287 | "through": ">=2.2.7 <3" 288 | } 289 | }, 290 | "accepts": { 291 | "version": "1.3.7", 292 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 293 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 294 | "requires": { 295 | "mime-types": "~2.1.24", 296 | "negotiator": "0.6.2" 297 | } 298 | }, 299 | "acorn": { 300 | "version": "6.3.0", 301 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", 302 | "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" 303 | }, 304 | "acorn-dynamic-import": { 305 | "version": "4.0.0", 306 | "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", 307 | "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==" 308 | }, 309 | "acorn-node": { 310 | "version": "1.7.0", 311 | "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.7.0.tgz", 312 | "integrity": "sha512-XhahLSsCB6X6CJbe+uNu3Mn9sJBNFxtBN9NLgAOQovfS6Kh0lDUtmlclhjn9CvEK7A7YyRU13PXlNcpSiLI9Yw==", 313 | "requires": { 314 | "acorn": "^6.1.1", 315 | "acorn-dynamic-import": "^4.0.0", 316 | "acorn-walk": "^6.1.1", 317 | "xtend": "^4.0.1" 318 | } 319 | }, 320 | "acorn-walk": { 321 | "version": "6.2.0", 322 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", 323 | "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" 324 | }, 325 | "ansi-styles": { 326 | "version": "3.2.1", 327 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 328 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 329 | "requires": { 330 | "color-convert": "^1.9.0" 331 | } 332 | }, 333 | "array-flatten": { 334 | "version": "1.1.1", 335 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 336 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 337 | }, 338 | "asn1.js": { 339 | "version": "4.10.1", 340 | "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", 341 | "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", 342 | "requires": { 343 | "bn.js": "^4.0.0", 344 | "inherits": "^2.0.1", 345 | "minimalistic-assert": "^1.0.0" 346 | } 347 | }, 348 | "assert": { 349 | "version": "1.5.0", 350 | "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", 351 | "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", 352 | "requires": { 353 | "object-assign": "^4.1.1", 354 | "util": "0.10.3" 355 | }, 356 | "dependencies": { 357 | "inherits": { 358 | "version": "2.0.1", 359 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 360 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 361 | }, 362 | "util": { 363 | "version": "0.10.3", 364 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", 365 | "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", 366 | "requires": { 367 | "inherits": "2.0.1" 368 | } 369 | } 370 | } 371 | }, 372 | "babelify": { 373 | "version": "10.0.0", 374 | "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", 375 | "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==" 376 | }, 377 | "balanced-match": { 378 | "version": "1.0.0", 379 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 380 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 381 | }, 382 | "base64-js": { 383 | "version": "1.3.1", 384 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", 385 | "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" 386 | }, 387 | "bn.js": { 388 | "version": "4.11.8", 389 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", 390 | "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" 391 | }, 392 | "body-parser": { 393 | "version": "1.19.0", 394 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 395 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 396 | "requires": { 397 | "bytes": "3.1.0", 398 | "content-type": "~1.0.4", 399 | "debug": "2.6.9", 400 | "depd": "~1.1.2", 401 | "http-errors": "1.7.2", 402 | "iconv-lite": "0.4.24", 403 | "on-finished": "~2.3.0", 404 | "qs": "6.7.0", 405 | "raw-body": "2.4.0", 406 | "type-is": "~1.6.17" 407 | } 408 | }, 409 | "brace-expansion": { 410 | "version": "1.1.11", 411 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 412 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 413 | "requires": { 414 | "balanced-match": "^1.0.0", 415 | "concat-map": "0.0.1" 416 | } 417 | }, 418 | "brorand": { 419 | "version": "1.1.0", 420 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 421 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" 422 | }, 423 | "browser-pack": { 424 | "version": "6.1.0", 425 | "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", 426 | "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", 427 | "requires": { 428 | "JSONStream": "^1.0.3", 429 | "combine-source-map": "~0.8.0", 430 | "defined": "^1.0.0", 431 | "safe-buffer": "^5.1.1", 432 | "through2": "^2.0.0", 433 | "umd": "^3.0.0" 434 | } 435 | }, 436 | "browser-resolve": { 437 | "version": "1.11.3", 438 | "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", 439 | "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", 440 | "requires": { 441 | "resolve": "1.1.7" 442 | }, 443 | "dependencies": { 444 | "resolve": { 445 | "version": "1.1.7", 446 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 447 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" 448 | } 449 | } 450 | }, 451 | "browserify": { 452 | "version": "16.5.0", 453 | "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.0.tgz", 454 | "integrity": "sha512-6bfI3cl76YLAnCZ75AGu/XPOsqUhRyc0F/olGIJeCxtfxF2HvPKEcmjU9M8oAPxl4uBY1U7Nry33Q6koV3f2iw==", 455 | "requires": { 456 | "JSONStream": "^1.0.3", 457 | "assert": "^1.4.0", 458 | "browser-pack": "^6.0.1", 459 | "browser-resolve": "^1.11.0", 460 | "browserify-zlib": "~0.2.0", 461 | "buffer": "^5.0.2", 462 | "cached-path-relative": "^1.0.0", 463 | "concat-stream": "^1.6.0", 464 | "console-browserify": "^1.1.0", 465 | "constants-browserify": "~1.0.0", 466 | "crypto-browserify": "^3.0.0", 467 | "defined": "^1.0.0", 468 | "deps-sort": "^2.0.0", 469 | "domain-browser": "^1.2.0", 470 | "duplexer2": "~0.1.2", 471 | "events": "^2.0.0", 472 | "glob": "^7.1.0", 473 | "has": "^1.0.0", 474 | "htmlescape": "^1.1.0", 475 | "https-browserify": "^1.0.0", 476 | "inherits": "~2.0.1", 477 | "insert-module-globals": "^7.0.0", 478 | "labeled-stream-splicer": "^2.0.0", 479 | "mkdirp": "^0.5.0", 480 | "module-deps": "^6.0.0", 481 | "os-browserify": "~0.3.0", 482 | "parents": "^1.0.1", 483 | "path-browserify": "~0.0.0", 484 | "process": "~0.11.0", 485 | "punycode": "^1.3.2", 486 | "querystring-es3": "~0.2.0", 487 | "read-only-stream": "^2.0.0", 488 | "readable-stream": "^2.0.2", 489 | "resolve": "^1.1.4", 490 | "shasum": "^1.0.0", 491 | "shell-quote": "^1.6.1", 492 | "stream-browserify": "^2.0.0", 493 | "stream-http": "^3.0.0", 494 | "string_decoder": "^1.1.1", 495 | "subarg": "^1.0.0", 496 | "syntax-error": "^1.1.1", 497 | "through2": "^2.0.0", 498 | "timers-browserify": "^1.0.1", 499 | "tty-browserify": "0.0.1", 500 | "url": "~0.11.0", 501 | "util": "~0.10.1", 502 | "vm-browserify": "^1.0.0", 503 | "xtend": "^4.0.0" 504 | } 505 | }, 506 | "browserify-aes": { 507 | "version": "1.2.0", 508 | "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", 509 | "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", 510 | "requires": { 511 | "buffer-xor": "^1.0.3", 512 | "cipher-base": "^1.0.0", 513 | "create-hash": "^1.1.0", 514 | "evp_bytestokey": "^1.0.3", 515 | "inherits": "^2.0.1", 516 | "safe-buffer": "^5.0.1" 517 | } 518 | }, 519 | "browserify-cipher": { 520 | "version": "1.0.1", 521 | "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", 522 | "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", 523 | "requires": { 524 | "browserify-aes": "^1.0.4", 525 | "browserify-des": "^1.0.0", 526 | "evp_bytestokey": "^1.0.0" 527 | } 528 | }, 529 | "browserify-des": { 530 | "version": "1.0.2", 531 | "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", 532 | "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", 533 | "requires": { 534 | "cipher-base": "^1.0.1", 535 | "des.js": "^1.0.0", 536 | "inherits": "^2.0.1", 537 | "safe-buffer": "^5.1.2" 538 | } 539 | }, 540 | "browserify-rsa": { 541 | "version": "4.0.1", 542 | "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", 543 | "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", 544 | "requires": { 545 | "bn.js": "^4.1.0", 546 | "randombytes": "^2.0.1" 547 | } 548 | }, 549 | "browserify-sign": { 550 | "version": "4.0.4", 551 | "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", 552 | "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", 553 | "requires": { 554 | "bn.js": "^4.1.1", 555 | "browserify-rsa": "^4.0.0", 556 | "create-hash": "^1.1.0", 557 | "create-hmac": "^1.1.2", 558 | "elliptic": "^6.0.0", 559 | "inherits": "^2.0.1", 560 | "parse-asn1": "^5.0.0" 561 | } 562 | }, 563 | "browserify-zlib": { 564 | "version": "0.2.0", 565 | "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", 566 | "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", 567 | "requires": { 568 | "pako": "~1.0.5" 569 | } 570 | }, 571 | "buffer": { 572 | "version": "5.3.0", 573 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.3.0.tgz", 574 | "integrity": "sha512-XykNc84nIOC32vZ9euOKbmGAP69JUkXDtBQfLq88c8/6J/gZi/t14A+l/p/9EM2TcT5xNC1MKPCrvO3LVUpVPw==", 575 | "requires": { 576 | "base64-js": "^1.0.2", 577 | "ieee754": "^1.1.4" 578 | } 579 | }, 580 | "buffer-from": { 581 | "version": "1.1.1", 582 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 583 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 584 | }, 585 | "buffer-xor": { 586 | "version": "1.0.3", 587 | "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", 588 | "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" 589 | }, 590 | "builtin-status-codes": { 591 | "version": "3.0.0", 592 | "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", 593 | "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" 594 | }, 595 | "bytes": { 596 | "version": "3.1.0", 597 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 598 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 599 | }, 600 | "cached-path-relative": { 601 | "version": "1.0.2", 602 | "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", 603 | "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" 604 | }, 605 | "chalk": { 606 | "version": "2.4.2", 607 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 608 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 609 | "requires": { 610 | "ansi-styles": "^3.2.1", 611 | "escape-string-regexp": "^1.0.5", 612 | "supports-color": "^5.3.0" 613 | } 614 | }, 615 | "cipher-base": { 616 | "version": "1.0.4", 617 | "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", 618 | "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", 619 | "requires": { 620 | "inherits": "^2.0.1", 621 | "safe-buffer": "^5.0.1" 622 | } 623 | }, 624 | "color-convert": { 625 | "version": "1.9.3", 626 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 627 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 628 | "requires": { 629 | "color-name": "1.1.3" 630 | } 631 | }, 632 | "color-name": { 633 | "version": "1.1.3", 634 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 635 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 636 | }, 637 | "combine-source-map": { 638 | "version": "0.8.0", 639 | "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", 640 | "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", 641 | "requires": { 642 | "convert-source-map": "~1.1.0", 643 | "inline-source-map": "~0.6.0", 644 | "lodash.memoize": "~3.0.3", 645 | "source-map": "~0.5.3" 646 | } 647 | }, 648 | "commander": { 649 | "version": "2.20.0", 650 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", 651 | "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", 652 | "dev": true 653 | }, 654 | "commondir": { 655 | "version": "1.0.1", 656 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 657 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 658 | "dev": true 659 | }, 660 | "concat-map": { 661 | "version": "0.0.1", 662 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 663 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 664 | }, 665 | "concat-stream": { 666 | "version": "1.6.2", 667 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 668 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 669 | "requires": { 670 | "buffer-from": "^1.0.0", 671 | "inherits": "^2.0.3", 672 | "readable-stream": "^2.2.2", 673 | "typedarray": "^0.0.6" 674 | } 675 | }, 676 | "console-browserify": { 677 | "version": "1.1.0", 678 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", 679 | "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", 680 | "requires": { 681 | "date-now": "^0.1.4" 682 | } 683 | }, 684 | "constants-browserify": { 685 | "version": "1.0.0", 686 | "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", 687 | "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" 688 | }, 689 | "content-disposition": { 690 | "version": "0.5.3", 691 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 692 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 693 | "requires": { 694 | "safe-buffer": "5.1.2" 695 | }, 696 | "dependencies": { 697 | "safe-buffer": { 698 | "version": "5.1.2", 699 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 700 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 701 | } 702 | } 703 | }, 704 | "content-type": { 705 | "version": "1.0.4", 706 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 707 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 708 | }, 709 | "convert-source-map": { 710 | "version": "1.1.3", 711 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", 712 | "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" 713 | }, 714 | "cookie": { 715 | "version": "0.4.0", 716 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 717 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 718 | }, 719 | "cookie-signature": { 720 | "version": "1.0.6", 721 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 722 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 723 | }, 724 | "core-js": { 725 | "version": "2.6.9", 726 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", 727 | "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", 728 | "dev": true 729 | }, 730 | "core-util-is": { 731 | "version": "1.0.2", 732 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 733 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 734 | }, 735 | "create-ecdh": { 736 | "version": "4.0.3", 737 | "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", 738 | "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", 739 | "requires": { 740 | "bn.js": "^4.1.0", 741 | "elliptic": "^6.0.0" 742 | } 743 | }, 744 | "create-hash": { 745 | "version": "1.2.0", 746 | "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", 747 | "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", 748 | "requires": { 749 | "cipher-base": "^1.0.1", 750 | "inherits": "^2.0.1", 751 | "md5.js": "^1.3.4", 752 | "ripemd160": "^2.0.1", 753 | "sha.js": "^2.4.0" 754 | } 755 | }, 756 | "create-hmac": { 757 | "version": "1.1.7", 758 | "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", 759 | "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", 760 | "requires": { 761 | "cipher-base": "^1.0.3", 762 | "create-hash": "^1.1.0", 763 | "inherits": "^2.0.1", 764 | "ripemd160": "^2.0.0", 765 | "safe-buffer": "^5.0.1", 766 | "sha.js": "^2.4.8" 767 | } 768 | }, 769 | "crypto-browserify": { 770 | "version": "3.12.0", 771 | "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", 772 | "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", 773 | "requires": { 774 | "browserify-cipher": "^1.0.0", 775 | "browserify-sign": "^4.0.0", 776 | "create-ecdh": "^4.0.0", 777 | "create-hash": "^1.1.0", 778 | "create-hmac": "^1.1.0", 779 | "diffie-hellman": "^5.0.0", 780 | "inherits": "^2.0.1", 781 | "pbkdf2": "^3.0.3", 782 | "public-encrypt": "^4.0.0", 783 | "randombytes": "^2.0.0", 784 | "randomfill": "^1.0.3" 785 | } 786 | }, 787 | "dash-ast": { 788 | "version": "1.0.0", 789 | "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", 790 | "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" 791 | }, 792 | "date-now": { 793 | "version": "0.1.4", 794 | "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", 795 | "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" 796 | }, 797 | "debug": { 798 | "version": "2.6.9", 799 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 800 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 801 | "requires": { 802 | "ms": "2.0.0" 803 | } 804 | }, 805 | "define-properties": { 806 | "version": "1.1.3", 807 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 808 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 809 | "dev": true, 810 | "requires": { 811 | "object-keys": "^1.0.12" 812 | } 813 | }, 814 | "defined": { 815 | "version": "1.0.0", 816 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", 817 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" 818 | }, 819 | "depd": { 820 | "version": "1.1.2", 821 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 822 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 823 | }, 824 | "deps-sort": { 825 | "version": "2.0.0", 826 | "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", 827 | "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", 828 | "requires": { 829 | "JSONStream": "^1.0.3", 830 | "shasum": "^1.0.0", 831 | "subarg": "^1.0.0", 832 | "through2": "^2.0.0" 833 | } 834 | }, 835 | "des.js": { 836 | "version": "1.0.0", 837 | "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", 838 | "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", 839 | "requires": { 840 | "inherits": "^2.0.1", 841 | "minimalistic-assert": "^1.0.0" 842 | } 843 | }, 844 | "destroy": { 845 | "version": "1.0.4", 846 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 847 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 848 | }, 849 | "detective": { 850 | "version": "5.2.0", 851 | "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", 852 | "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", 853 | "requires": { 854 | "acorn-node": "^1.6.1", 855 | "defined": "^1.0.0", 856 | "minimist": "^1.1.1" 857 | } 858 | }, 859 | "diffie-hellman": { 860 | "version": "5.0.3", 861 | "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", 862 | "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", 863 | "requires": { 864 | "bn.js": "^4.1.0", 865 | "miller-rabin": "^4.0.0", 866 | "randombytes": "^2.0.0" 867 | } 868 | }, 869 | "domain-browser": { 870 | "version": "1.2.0", 871 | "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", 872 | "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" 873 | }, 874 | "duplexer2": { 875 | "version": "0.1.4", 876 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", 877 | "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", 878 | "requires": { 879 | "readable-stream": "^2.0.2" 880 | } 881 | }, 882 | "ee-first": { 883 | "version": "1.1.1", 884 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 885 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 886 | }, 887 | "elliptic": { 888 | "version": "6.5.0", 889 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.0.tgz", 890 | "integrity": "sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg==", 891 | "requires": { 892 | "bn.js": "^4.4.0", 893 | "brorand": "^1.0.1", 894 | "hash.js": "^1.0.0", 895 | "hmac-drbg": "^1.0.0", 896 | "inherits": "^2.0.1", 897 | "minimalistic-assert": "^1.0.0", 898 | "minimalistic-crypto-utils": "^1.0.0" 899 | } 900 | }, 901 | "encodeurl": { 902 | "version": "1.0.2", 903 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 904 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 905 | }, 906 | "es-abstract": { 907 | "version": "1.13.0", 908 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", 909 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", 910 | "dev": true, 911 | "requires": { 912 | "es-to-primitive": "^1.2.0", 913 | "function-bind": "^1.1.1", 914 | "has": "^1.0.3", 915 | "is-callable": "^1.1.4", 916 | "is-regex": "^1.0.4", 917 | "object-keys": "^1.0.12" 918 | } 919 | }, 920 | "es-to-primitive": { 921 | "version": "1.2.0", 922 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", 923 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", 924 | "dev": true, 925 | "requires": { 926 | "is-callable": "^1.1.4", 927 | "is-date-object": "^1.0.1", 928 | "is-symbol": "^1.0.2" 929 | } 930 | }, 931 | "escape-html": { 932 | "version": "1.0.3", 933 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 934 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 935 | }, 936 | "escape-string-regexp": { 937 | "version": "1.0.5", 938 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 939 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 940 | }, 941 | "esutils": { 942 | "version": "2.0.3", 943 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 944 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" 945 | }, 946 | "etag": { 947 | "version": "1.8.1", 948 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 949 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 950 | }, 951 | "events": { 952 | "version": "2.1.0", 953 | "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", 954 | "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" 955 | }, 956 | "evp_bytestokey": { 957 | "version": "1.0.3", 958 | "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", 959 | "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", 960 | "requires": { 961 | "md5.js": "^1.3.4", 962 | "safe-buffer": "^5.1.1" 963 | } 964 | }, 965 | "express": { 966 | "version": "4.17.1", 967 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 968 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 969 | "requires": { 970 | "accepts": "~1.3.7", 971 | "array-flatten": "1.1.1", 972 | "body-parser": "1.19.0", 973 | "content-disposition": "0.5.3", 974 | "content-type": "~1.0.4", 975 | "cookie": "0.4.0", 976 | "cookie-signature": "1.0.6", 977 | "debug": "2.6.9", 978 | "depd": "~1.1.2", 979 | "encodeurl": "~1.0.2", 980 | "escape-html": "~1.0.3", 981 | "etag": "~1.8.1", 982 | "finalhandler": "~1.1.2", 983 | "fresh": "0.5.2", 984 | "merge-descriptors": "1.0.1", 985 | "methods": "~1.1.2", 986 | "on-finished": "~2.3.0", 987 | "parseurl": "~1.3.3", 988 | "path-to-regexp": "0.1.7", 989 | "proxy-addr": "~2.0.5", 990 | "qs": "6.7.0", 991 | "range-parser": "~1.2.1", 992 | "safe-buffer": "5.1.2", 993 | "send": "0.17.1", 994 | "serve-static": "1.14.1", 995 | "setprototypeof": "1.1.1", 996 | "statuses": "~1.5.0", 997 | "type-is": "~1.6.18", 998 | "utils-merge": "1.0.1", 999 | "vary": "~1.1.2" 1000 | }, 1001 | "dependencies": { 1002 | "safe-buffer": { 1003 | "version": "5.1.2", 1004 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1005 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1006 | } 1007 | } 1008 | }, 1009 | "finalhandler": { 1010 | "version": "1.1.2", 1011 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 1012 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 1013 | "requires": { 1014 | "debug": "2.6.9", 1015 | "encodeurl": "~1.0.2", 1016 | "escape-html": "~1.0.3", 1017 | "on-finished": "~2.3.0", 1018 | "parseurl": "~1.3.3", 1019 | "statuses": "~1.5.0", 1020 | "unpipe": "~1.0.0" 1021 | } 1022 | }, 1023 | "find-cache-dir": { 1024 | "version": "2.1.0", 1025 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", 1026 | "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", 1027 | "dev": true, 1028 | "requires": { 1029 | "commondir": "^1.0.1", 1030 | "make-dir": "^2.0.0", 1031 | "pkg-dir": "^3.0.0" 1032 | } 1033 | }, 1034 | "find-up": { 1035 | "version": "3.0.0", 1036 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1037 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1038 | "dev": true, 1039 | "requires": { 1040 | "locate-path": "^3.0.0" 1041 | } 1042 | }, 1043 | "forwarded": { 1044 | "version": "0.1.2", 1045 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 1046 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 1047 | }, 1048 | "fresh": { 1049 | "version": "0.5.2", 1050 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1051 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 1052 | }, 1053 | "fs.realpath": { 1054 | "version": "1.0.0", 1055 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1056 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 1057 | }, 1058 | "function-bind": { 1059 | "version": "1.1.1", 1060 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1061 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 1062 | }, 1063 | "get-assigned-identifiers": { 1064 | "version": "1.2.0", 1065 | "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", 1066 | "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" 1067 | }, 1068 | "glob": { 1069 | "version": "7.1.4", 1070 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 1071 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 1072 | "requires": { 1073 | "fs.realpath": "^1.0.0", 1074 | "inflight": "^1.0.4", 1075 | "inherits": "2", 1076 | "minimatch": "^3.0.4", 1077 | "once": "^1.3.0", 1078 | "path-is-absolute": "^1.0.0" 1079 | } 1080 | }, 1081 | "globals": { 1082 | "version": "11.12.0", 1083 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 1084 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" 1085 | }, 1086 | "has": { 1087 | "version": "1.0.3", 1088 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1089 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1090 | "requires": { 1091 | "function-bind": "^1.1.1" 1092 | } 1093 | }, 1094 | "has-flag": { 1095 | "version": "3.0.0", 1096 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1097 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 1098 | }, 1099 | "has-symbols": { 1100 | "version": "1.0.0", 1101 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", 1102 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", 1103 | "dev": true 1104 | }, 1105 | "hash-base": { 1106 | "version": "3.0.4", 1107 | "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", 1108 | "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", 1109 | "requires": { 1110 | "inherits": "^2.0.1", 1111 | "safe-buffer": "^5.0.1" 1112 | } 1113 | }, 1114 | "hash.js": { 1115 | "version": "1.1.7", 1116 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 1117 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 1118 | "requires": { 1119 | "inherits": "^2.0.3", 1120 | "minimalistic-assert": "^1.0.1" 1121 | } 1122 | }, 1123 | "hmac-drbg": { 1124 | "version": "1.0.1", 1125 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 1126 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 1127 | "requires": { 1128 | "hash.js": "^1.0.3", 1129 | "minimalistic-assert": "^1.0.0", 1130 | "minimalistic-crypto-utils": "^1.0.1" 1131 | } 1132 | }, 1133 | "homedir-polyfill": { 1134 | "version": "1.0.3", 1135 | "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", 1136 | "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", 1137 | "dev": true, 1138 | "requires": { 1139 | "parse-passwd": "^1.0.0" 1140 | } 1141 | }, 1142 | "htmlescape": { 1143 | "version": "1.1.1", 1144 | "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", 1145 | "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" 1146 | }, 1147 | "http-errors": { 1148 | "version": "1.7.2", 1149 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 1150 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 1151 | "requires": { 1152 | "depd": "~1.1.2", 1153 | "inherits": "2.0.3", 1154 | "setprototypeof": "1.1.1", 1155 | "statuses": ">= 1.5.0 < 2", 1156 | "toidentifier": "1.0.0" 1157 | }, 1158 | "dependencies": { 1159 | "inherits": { 1160 | "version": "2.0.3", 1161 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1162 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 1163 | } 1164 | } 1165 | }, 1166 | "https-browserify": { 1167 | "version": "1.0.0", 1168 | "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", 1169 | "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" 1170 | }, 1171 | "iconv-lite": { 1172 | "version": "0.4.24", 1173 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1174 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1175 | "requires": { 1176 | "safer-buffer": ">= 2.1.2 < 3" 1177 | } 1178 | }, 1179 | "ieee754": { 1180 | "version": "1.1.13", 1181 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 1182 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 1183 | }, 1184 | "inflight": { 1185 | "version": "1.0.6", 1186 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1187 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1188 | "requires": { 1189 | "once": "^1.3.0", 1190 | "wrappy": "1" 1191 | } 1192 | }, 1193 | "inherits": { 1194 | "version": "2.0.4", 1195 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1196 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1197 | }, 1198 | "inline-source-map": { 1199 | "version": "0.6.2", 1200 | "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", 1201 | "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", 1202 | "requires": { 1203 | "source-map": "~0.5.3" 1204 | } 1205 | }, 1206 | "insert-module-globals": { 1207 | "version": "7.2.0", 1208 | "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", 1209 | "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", 1210 | "requires": { 1211 | "JSONStream": "^1.0.3", 1212 | "acorn-node": "^1.5.2", 1213 | "combine-source-map": "^0.8.0", 1214 | "concat-stream": "^1.6.1", 1215 | "is-buffer": "^1.1.0", 1216 | "path-is-absolute": "^1.0.1", 1217 | "process": "~0.11.0", 1218 | "through2": "^2.0.0", 1219 | "undeclared-identifiers": "^1.1.2", 1220 | "xtend": "^4.0.0" 1221 | } 1222 | }, 1223 | "ipaddr.js": { 1224 | "version": "1.9.0", 1225 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 1226 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" 1227 | }, 1228 | "is-buffer": { 1229 | "version": "1.1.6", 1230 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1231 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 1232 | }, 1233 | "is-callable": { 1234 | "version": "1.1.4", 1235 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 1236 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", 1237 | "dev": true 1238 | }, 1239 | "is-date-object": { 1240 | "version": "1.0.1", 1241 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 1242 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", 1243 | "dev": true 1244 | }, 1245 | "is-regex": { 1246 | "version": "1.0.4", 1247 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 1248 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 1249 | "dev": true, 1250 | "requires": { 1251 | "has": "^1.0.1" 1252 | } 1253 | }, 1254 | "is-symbol": { 1255 | "version": "1.0.2", 1256 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", 1257 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", 1258 | "dev": true, 1259 | "requires": { 1260 | "has-symbols": "^1.0.0" 1261 | } 1262 | }, 1263 | "isarray": { 1264 | "version": "1.0.0", 1265 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1266 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1267 | }, 1268 | "js-tokens": { 1269 | "version": "4.0.0", 1270 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1271 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 1272 | }, 1273 | "jsesc": { 1274 | "version": "2.5.2", 1275 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1276 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" 1277 | }, 1278 | "json-stable-stringify": { 1279 | "version": "0.0.1", 1280 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", 1281 | "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", 1282 | "requires": { 1283 | "jsonify": "~0.0.0" 1284 | } 1285 | }, 1286 | "json5": { 1287 | "version": "2.1.0", 1288 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", 1289 | "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", 1290 | "requires": { 1291 | "minimist": "^1.2.0" 1292 | } 1293 | }, 1294 | "jsonify": { 1295 | "version": "0.0.0", 1296 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 1297 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" 1298 | }, 1299 | "jsonparse": { 1300 | "version": "1.3.1", 1301 | "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", 1302 | "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" 1303 | }, 1304 | "labeled-stream-splicer": { 1305 | "version": "2.0.2", 1306 | "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", 1307 | "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", 1308 | "requires": { 1309 | "inherits": "^2.0.1", 1310 | "stream-splicer": "^2.0.0" 1311 | } 1312 | }, 1313 | "locate-path": { 1314 | "version": "3.0.0", 1315 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1316 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1317 | "dev": true, 1318 | "requires": { 1319 | "p-locate": "^3.0.0", 1320 | "path-exists": "^3.0.0" 1321 | } 1322 | }, 1323 | "lodash": { 1324 | "version": "4.17.15", 1325 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1326 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 1327 | }, 1328 | "lodash.memoize": { 1329 | "version": "3.0.4", 1330 | "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", 1331 | "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" 1332 | }, 1333 | "make-dir": { 1334 | "version": "2.1.0", 1335 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", 1336 | "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", 1337 | "dev": true, 1338 | "requires": { 1339 | "pify": "^4.0.1", 1340 | "semver": "^5.6.0" 1341 | } 1342 | }, 1343 | "md5.js": { 1344 | "version": "1.3.5", 1345 | "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", 1346 | "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", 1347 | "requires": { 1348 | "hash-base": "^3.0.0", 1349 | "inherits": "^2.0.1", 1350 | "safe-buffer": "^5.1.2" 1351 | } 1352 | }, 1353 | "media-typer": { 1354 | "version": "0.3.0", 1355 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1356 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1357 | }, 1358 | "merge-descriptors": { 1359 | "version": "1.0.1", 1360 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1361 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1362 | }, 1363 | "methods": { 1364 | "version": "1.1.2", 1365 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1366 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1367 | }, 1368 | "miller-rabin": { 1369 | "version": "4.0.1", 1370 | "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", 1371 | "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", 1372 | "requires": { 1373 | "bn.js": "^4.0.0", 1374 | "brorand": "^1.0.1" 1375 | } 1376 | }, 1377 | "mime": { 1378 | "version": "1.6.0", 1379 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1380 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1381 | }, 1382 | "mime-db": { 1383 | "version": "1.40.0", 1384 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 1385 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 1386 | }, 1387 | "mime-types": { 1388 | "version": "2.1.24", 1389 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 1390 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 1391 | "requires": { 1392 | "mime-db": "1.40.0" 1393 | } 1394 | }, 1395 | "minimalistic-assert": { 1396 | "version": "1.0.1", 1397 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 1398 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 1399 | }, 1400 | "minimalistic-crypto-utils": { 1401 | "version": "1.0.1", 1402 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 1403 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 1404 | }, 1405 | "minimatch": { 1406 | "version": "3.0.4", 1407 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1408 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1409 | "requires": { 1410 | "brace-expansion": "^1.1.7" 1411 | } 1412 | }, 1413 | "minimist": { 1414 | "version": "1.2.0", 1415 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 1416 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 1417 | }, 1418 | "mkdirp": { 1419 | "version": "0.5.1", 1420 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1421 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1422 | "requires": { 1423 | "minimist": "0.0.8" 1424 | }, 1425 | "dependencies": { 1426 | "minimist": { 1427 | "version": "0.0.8", 1428 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1429 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 1430 | } 1431 | } 1432 | }, 1433 | "module-deps": { 1434 | "version": "6.2.1", 1435 | "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.1.tgz", 1436 | "integrity": "sha512-UnEn6Ah36Tu4jFiBbJVUtt0h+iXqxpLqDvPS8nllbw5RZFmNJ1+Mz5BjYnM9ieH80zyxHkARGLnMIHlPK5bu6A==", 1437 | "requires": { 1438 | "JSONStream": "^1.0.3", 1439 | "browser-resolve": "^1.7.0", 1440 | "cached-path-relative": "^1.0.2", 1441 | "concat-stream": "~1.6.0", 1442 | "defined": "^1.0.0", 1443 | "detective": "^5.0.2", 1444 | "duplexer2": "^0.1.2", 1445 | "inherits": "^2.0.1", 1446 | "parents": "^1.0.0", 1447 | "readable-stream": "^2.0.2", 1448 | "resolve": "^1.4.0", 1449 | "stream-combiner2": "^1.1.1", 1450 | "subarg": "^1.0.0", 1451 | "through2": "^2.0.0", 1452 | "xtend": "^4.0.0" 1453 | } 1454 | }, 1455 | "ms": { 1456 | "version": "2.0.0", 1457 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1458 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1459 | }, 1460 | "negotiator": { 1461 | "version": "0.6.2", 1462 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1463 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 1464 | }, 1465 | "node-environment-flags": { 1466 | "version": "1.0.6", 1467 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", 1468 | "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", 1469 | "dev": true, 1470 | "requires": { 1471 | "object.getownpropertydescriptors": "^2.0.3", 1472 | "semver": "^5.7.0" 1473 | } 1474 | }, 1475 | "node-modules-regexp": { 1476 | "version": "1.0.0", 1477 | "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", 1478 | "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", 1479 | "dev": true 1480 | }, 1481 | "object-assign": { 1482 | "version": "4.1.1", 1483 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1484 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1485 | }, 1486 | "object-keys": { 1487 | "version": "1.1.1", 1488 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1489 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1490 | "dev": true 1491 | }, 1492 | "object.getownpropertydescriptors": { 1493 | "version": "2.0.3", 1494 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", 1495 | "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", 1496 | "dev": true, 1497 | "requires": { 1498 | "define-properties": "^1.1.2", 1499 | "es-abstract": "^1.5.1" 1500 | } 1501 | }, 1502 | "on-finished": { 1503 | "version": "2.3.0", 1504 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1505 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1506 | "requires": { 1507 | "ee-first": "1.1.1" 1508 | } 1509 | }, 1510 | "once": { 1511 | "version": "1.4.0", 1512 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1513 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1514 | "requires": { 1515 | "wrappy": "1" 1516 | } 1517 | }, 1518 | "os-browserify": { 1519 | "version": "0.3.0", 1520 | "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", 1521 | "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" 1522 | }, 1523 | "p-limit": { 1524 | "version": "2.2.0", 1525 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", 1526 | "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", 1527 | "dev": true, 1528 | "requires": { 1529 | "p-try": "^2.0.0" 1530 | } 1531 | }, 1532 | "p-locate": { 1533 | "version": "3.0.0", 1534 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1535 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1536 | "dev": true, 1537 | "requires": { 1538 | "p-limit": "^2.0.0" 1539 | } 1540 | }, 1541 | "p-try": { 1542 | "version": "2.2.0", 1543 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1544 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1545 | "dev": true 1546 | }, 1547 | "pako": { 1548 | "version": "1.0.10", 1549 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", 1550 | "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" 1551 | }, 1552 | "parents": { 1553 | "version": "1.0.1", 1554 | "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", 1555 | "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", 1556 | "requires": { 1557 | "path-platform": "~0.11.15" 1558 | } 1559 | }, 1560 | "parse-asn1": { 1561 | "version": "5.1.4", 1562 | "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", 1563 | "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", 1564 | "requires": { 1565 | "asn1.js": "^4.0.0", 1566 | "browserify-aes": "^1.0.0", 1567 | "create-hash": "^1.1.0", 1568 | "evp_bytestokey": "^1.0.0", 1569 | "pbkdf2": "^3.0.3", 1570 | "safe-buffer": "^5.1.1" 1571 | } 1572 | }, 1573 | "parse-passwd": { 1574 | "version": "1.0.0", 1575 | "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", 1576 | "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", 1577 | "dev": true 1578 | }, 1579 | "parseurl": { 1580 | "version": "1.3.3", 1581 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1582 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1583 | }, 1584 | "path-browserify": { 1585 | "version": "0.0.1", 1586 | "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", 1587 | "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" 1588 | }, 1589 | "path-exists": { 1590 | "version": "3.0.0", 1591 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1592 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1593 | "dev": true 1594 | }, 1595 | "path-is-absolute": { 1596 | "version": "1.0.1", 1597 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1598 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1599 | }, 1600 | "path-parse": { 1601 | "version": "1.0.6", 1602 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1603 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" 1604 | }, 1605 | "path-platform": { 1606 | "version": "0.11.15", 1607 | "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", 1608 | "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" 1609 | }, 1610 | "path-to-regexp": { 1611 | "version": "0.1.7", 1612 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1613 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1614 | }, 1615 | "pbkdf2": { 1616 | "version": "3.0.17", 1617 | "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", 1618 | "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", 1619 | "requires": { 1620 | "create-hash": "^1.1.2", 1621 | "create-hmac": "^1.1.4", 1622 | "ripemd160": "^2.0.1", 1623 | "safe-buffer": "^5.0.1", 1624 | "sha.js": "^2.4.8" 1625 | } 1626 | }, 1627 | "pify": { 1628 | "version": "4.0.1", 1629 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 1630 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 1631 | "dev": true 1632 | }, 1633 | "pirates": { 1634 | "version": "4.0.1", 1635 | "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", 1636 | "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", 1637 | "dev": true, 1638 | "requires": { 1639 | "node-modules-regexp": "^1.0.0" 1640 | } 1641 | }, 1642 | "pkg-dir": { 1643 | "version": "3.0.0", 1644 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", 1645 | "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", 1646 | "dev": true, 1647 | "requires": { 1648 | "find-up": "^3.0.0" 1649 | } 1650 | }, 1651 | "process": { 1652 | "version": "0.11.10", 1653 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 1654 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" 1655 | }, 1656 | "process-nextick-args": { 1657 | "version": "2.0.1", 1658 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1659 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1660 | }, 1661 | "proxy-addr": { 1662 | "version": "2.0.5", 1663 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 1664 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 1665 | "requires": { 1666 | "forwarded": "~0.1.2", 1667 | "ipaddr.js": "1.9.0" 1668 | } 1669 | }, 1670 | "public-encrypt": { 1671 | "version": "4.0.3", 1672 | "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", 1673 | "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", 1674 | "requires": { 1675 | "bn.js": "^4.1.0", 1676 | "browserify-rsa": "^4.0.0", 1677 | "create-hash": "^1.1.0", 1678 | "parse-asn1": "^5.0.0", 1679 | "randombytes": "^2.0.1", 1680 | "safe-buffer": "^5.1.2" 1681 | } 1682 | }, 1683 | "punycode": { 1684 | "version": "1.4.1", 1685 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1686 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1687 | }, 1688 | "qs": { 1689 | "version": "6.7.0", 1690 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1691 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 1692 | }, 1693 | "querystring": { 1694 | "version": "0.2.0", 1695 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1696 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1697 | }, 1698 | "querystring-es3": { 1699 | "version": "0.2.1", 1700 | "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", 1701 | "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" 1702 | }, 1703 | "randombytes": { 1704 | "version": "2.1.0", 1705 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1706 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1707 | "requires": { 1708 | "safe-buffer": "^5.1.0" 1709 | } 1710 | }, 1711 | "randomfill": { 1712 | "version": "1.0.4", 1713 | "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", 1714 | "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", 1715 | "requires": { 1716 | "randombytes": "^2.0.5", 1717 | "safe-buffer": "^5.1.0" 1718 | } 1719 | }, 1720 | "range-parser": { 1721 | "version": "1.2.1", 1722 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1723 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1724 | }, 1725 | "raw-body": { 1726 | "version": "2.4.0", 1727 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1728 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1729 | "requires": { 1730 | "bytes": "3.1.0", 1731 | "http-errors": "1.7.2", 1732 | "iconv-lite": "0.4.24", 1733 | "unpipe": "1.0.0" 1734 | } 1735 | }, 1736 | "read-only-stream": { 1737 | "version": "2.0.0", 1738 | "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", 1739 | "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", 1740 | "requires": { 1741 | "readable-stream": "^2.0.2" 1742 | } 1743 | }, 1744 | "readable-stream": { 1745 | "version": "2.3.6", 1746 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1747 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1748 | "requires": { 1749 | "core-util-is": "~1.0.0", 1750 | "inherits": "~2.0.3", 1751 | "isarray": "~1.0.0", 1752 | "process-nextick-args": "~2.0.0", 1753 | "safe-buffer": "~5.1.1", 1754 | "string_decoder": "~1.1.1", 1755 | "util-deprecate": "~1.0.1" 1756 | }, 1757 | "dependencies": { 1758 | "safe-buffer": { 1759 | "version": "5.1.2", 1760 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1761 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1762 | }, 1763 | "string_decoder": { 1764 | "version": "1.1.1", 1765 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1766 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1767 | "requires": { 1768 | "safe-buffer": "~5.1.0" 1769 | } 1770 | } 1771 | } 1772 | }, 1773 | "regenerator-runtime": { 1774 | "version": "0.13.3", 1775 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", 1776 | "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", 1777 | "dev": true 1778 | }, 1779 | "resolve": { 1780 | "version": "1.12.0", 1781 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", 1782 | "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", 1783 | "requires": { 1784 | "path-parse": "^1.0.6" 1785 | } 1786 | }, 1787 | "ripemd160": { 1788 | "version": "2.0.2", 1789 | "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", 1790 | "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", 1791 | "requires": { 1792 | "hash-base": "^3.0.0", 1793 | "inherits": "^2.0.1" 1794 | } 1795 | }, 1796 | "rxjs": { 1797 | "version": "6.5.2", 1798 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", 1799 | "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", 1800 | "requires": { 1801 | "tslib": "^1.9.0" 1802 | } 1803 | }, 1804 | "safe-buffer": { 1805 | "version": "5.2.0", 1806 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 1807 | "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" 1808 | }, 1809 | "safer-buffer": { 1810 | "version": "2.1.2", 1811 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1812 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1813 | }, 1814 | "semver": { 1815 | "version": "5.7.1", 1816 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1817 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 1818 | }, 1819 | "send": { 1820 | "version": "0.17.1", 1821 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1822 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1823 | "requires": { 1824 | "debug": "2.6.9", 1825 | "depd": "~1.1.2", 1826 | "destroy": "~1.0.4", 1827 | "encodeurl": "~1.0.2", 1828 | "escape-html": "~1.0.3", 1829 | "etag": "~1.8.1", 1830 | "fresh": "0.5.2", 1831 | "http-errors": "~1.7.2", 1832 | "mime": "1.6.0", 1833 | "ms": "2.1.1", 1834 | "on-finished": "~2.3.0", 1835 | "range-parser": "~1.2.1", 1836 | "statuses": "~1.5.0" 1837 | }, 1838 | "dependencies": { 1839 | "ms": { 1840 | "version": "2.1.1", 1841 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1842 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1843 | } 1844 | } 1845 | }, 1846 | "serialize-javascript": { 1847 | "version": "1.7.0", 1848 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", 1849 | "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==" 1850 | }, 1851 | "serve-static": { 1852 | "version": "1.14.1", 1853 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1854 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1855 | "requires": { 1856 | "encodeurl": "~1.0.2", 1857 | "escape-html": "~1.0.3", 1858 | "parseurl": "~1.3.3", 1859 | "send": "0.17.1" 1860 | } 1861 | }, 1862 | "setprototypeof": { 1863 | "version": "1.1.1", 1864 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1865 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1866 | }, 1867 | "sha.js": { 1868 | "version": "2.4.11", 1869 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 1870 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 1871 | "requires": { 1872 | "inherits": "^2.0.1", 1873 | "safe-buffer": "^5.0.1" 1874 | } 1875 | }, 1876 | "shasum": { 1877 | "version": "1.0.2", 1878 | "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", 1879 | "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", 1880 | "requires": { 1881 | "json-stable-stringify": "~0.0.0", 1882 | "sha.js": "~2.4.4" 1883 | } 1884 | }, 1885 | "shell-quote": { 1886 | "version": "1.7.0", 1887 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.0.tgz", 1888 | "integrity": "sha512-+zdNWhJbPD3h5jR1LtZwVH+SpSBEzUhHUCHgAZFDKLGvIMR+PnJdsIx6ox7l1WYDT7s2mtjBiahyFAIT/+1ybw==" 1889 | }, 1890 | "simple-concat": { 1891 | "version": "1.0.0", 1892 | "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", 1893 | "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" 1894 | }, 1895 | "source-map": { 1896 | "version": "0.5.7", 1897 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1898 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 1899 | }, 1900 | "source-map-support": { 1901 | "version": "0.5.13", 1902 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", 1903 | "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", 1904 | "dev": true, 1905 | "requires": { 1906 | "buffer-from": "^1.0.0", 1907 | "source-map": "^0.6.0" 1908 | }, 1909 | "dependencies": { 1910 | "source-map": { 1911 | "version": "0.6.1", 1912 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1913 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1914 | "dev": true 1915 | } 1916 | } 1917 | }, 1918 | "statuses": { 1919 | "version": "1.5.0", 1920 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1921 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1922 | }, 1923 | "stream-browserify": { 1924 | "version": "2.0.2", 1925 | "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", 1926 | "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", 1927 | "requires": { 1928 | "inherits": "~2.0.1", 1929 | "readable-stream": "^2.0.2" 1930 | } 1931 | }, 1932 | "stream-combiner2": { 1933 | "version": "1.1.1", 1934 | "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", 1935 | "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", 1936 | "requires": { 1937 | "duplexer2": "~0.1.0", 1938 | "readable-stream": "^2.0.2" 1939 | } 1940 | }, 1941 | "stream-http": { 1942 | "version": "3.1.0", 1943 | "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.0.tgz", 1944 | "integrity": "sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw==", 1945 | "requires": { 1946 | "builtin-status-codes": "^3.0.0", 1947 | "inherits": "^2.0.1", 1948 | "readable-stream": "^3.0.6", 1949 | "xtend": "^4.0.0" 1950 | }, 1951 | "dependencies": { 1952 | "readable-stream": { 1953 | "version": "3.4.0", 1954 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", 1955 | "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", 1956 | "requires": { 1957 | "inherits": "^2.0.3", 1958 | "string_decoder": "^1.1.1", 1959 | "util-deprecate": "^1.0.1" 1960 | } 1961 | } 1962 | } 1963 | }, 1964 | "stream-splicer": { 1965 | "version": "2.0.1", 1966 | "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", 1967 | "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", 1968 | "requires": { 1969 | "inherits": "^2.0.1", 1970 | "readable-stream": "^2.0.2" 1971 | } 1972 | }, 1973 | "string_decoder": { 1974 | "version": "1.3.0", 1975 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1976 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1977 | "requires": { 1978 | "safe-buffer": "~5.2.0" 1979 | } 1980 | }, 1981 | "subarg": { 1982 | "version": "1.0.0", 1983 | "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", 1984 | "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", 1985 | "requires": { 1986 | "minimist": "^1.1.0" 1987 | } 1988 | }, 1989 | "supports-color": { 1990 | "version": "5.5.0", 1991 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1992 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1993 | "requires": { 1994 | "has-flag": "^3.0.0" 1995 | } 1996 | }, 1997 | "syntax-error": { 1998 | "version": "1.4.0", 1999 | "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", 2000 | "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", 2001 | "requires": { 2002 | "acorn-node": "^1.2.0" 2003 | } 2004 | }, 2005 | "through": { 2006 | "version": "2.3.8", 2007 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2008 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 2009 | }, 2010 | "through2": { 2011 | "version": "2.0.5", 2012 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 2013 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 2014 | "requires": { 2015 | "readable-stream": "~2.3.6", 2016 | "xtend": "~4.0.1" 2017 | } 2018 | }, 2019 | "timers-browserify": { 2020 | "version": "1.4.2", 2021 | "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", 2022 | "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", 2023 | "requires": { 2024 | "process": "~0.11.0" 2025 | } 2026 | }, 2027 | "to-fast-properties": { 2028 | "version": "2.0.0", 2029 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 2030 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" 2031 | }, 2032 | "toidentifier": { 2033 | "version": "1.0.0", 2034 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 2035 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 2036 | }, 2037 | "trim-right": { 2038 | "version": "1.0.1", 2039 | "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", 2040 | "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" 2041 | }, 2042 | "tslib": { 2043 | "version": "1.10.0", 2044 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 2045 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" 2046 | }, 2047 | "tty-browserify": { 2048 | "version": "0.0.1", 2049 | "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", 2050 | "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" 2051 | }, 2052 | "type-is": { 2053 | "version": "1.6.18", 2054 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 2055 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 2056 | "requires": { 2057 | "media-typer": "0.3.0", 2058 | "mime-types": "~2.1.24" 2059 | } 2060 | }, 2061 | "typedarray": { 2062 | "version": "0.0.6", 2063 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2064 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" 2065 | }, 2066 | "umd": { 2067 | "version": "3.0.3", 2068 | "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", 2069 | "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" 2070 | }, 2071 | "undeclared-identifiers": { 2072 | "version": "1.1.3", 2073 | "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", 2074 | "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", 2075 | "requires": { 2076 | "acorn-node": "^1.3.0", 2077 | "dash-ast": "^1.0.0", 2078 | "get-assigned-identifiers": "^1.2.0", 2079 | "simple-concat": "^1.0.0", 2080 | "xtend": "^4.0.1" 2081 | } 2082 | }, 2083 | "unpipe": { 2084 | "version": "1.0.0", 2085 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2086 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 2087 | }, 2088 | "url": { 2089 | "version": "0.11.0", 2090 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 2091 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 2092 | "requires": { 2093 | "punycode": "1.3.2", 2094 | "querystring": "0.2.0" 2095 | }, 2096 | "dependencies": { 2097 | "punycode": { 2098 | "version": "1.3.2", 2099 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 2100 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 2101 | } 2102 | } 2103 | }, 2104 | "util": { 2105 | "version": "0.10.4", 2106 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", 2107 | "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", 2108 | "requires": { 2109 | "inherits": "2.0.3" 2110 | }, 2111 | "dependencies": { 2112 | "inherits": { 2113 | "version": "2.0.3", 2114 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2115 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 2116 | } 2117 | } 2118 | }, 2119 | "util-deprecate": { 2120 | "version": "1.0.2", 2121 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2122 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2123 | }, 2124 | "utils-merge": { 2125 | "version": "1.0.1", 2126 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2127 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 2128 | }, 2129 | "v8flags": { 2130 | "version": "3.1.3", 2131 | "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", 2132 | "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", 2133 | "dev": true, 2134 | "requires": { 2135 | "homedir-polyfill": "^1.0.1" 2136 | } 2137 | }, 2138 | "vary": { 2139 | "version": "1.1.2", 2140 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2141 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 2142 | }, 2143 | "vm-browserify": { 2144 | "version": "1.1.0", 2145 | "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", 2146 | "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==" 2147 | }, 2148 | "wrappy": { 2149 | "version": "1.0.2", 2150 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2151 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 2152 | }, 2153 | "xtend": { 2154 | "version": "4.0.2", 2155 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2156 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 2157 | } 2158 | } 2159 | } 2160 | -------------------------------------------------------------------------------- /examples/web/isomorphic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cycle-isomorphic-example", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "@babel/core": "^7.5.5", 6 | "@babel/preset-react": "^7.0.0", 7 | "babelify": "^10.0.0", 8 | "browserify": "^16.5.0", 9 | "express": "^4.17.1", 10 | "rxjs": "^6.5.2", 11 | "serialize-javascript": "^1.7.0" 12 | }, 13 | "scripts": { 14 | "start": "babel-node --presets @babel/preset-react ./server.js" 15 | }, 16 | "devDependencies": { 17 | "@babel/node": "^7.5.5" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/web/isomorphic/server.js: -------------------------------------------------------------------------------- 1 | const React = require('react'); 2 | const ReactDOMServer = require('react-dom/server'); 3 | const express = require('express'); 4 | const browserify = require('browserify'); 5 | const serialize = require('serialize-javascript'); 6 | const Rx = require('rx'); 7 | const fromStream = require('../lib/rx-fromstream'); 8 | const {createApp} = require('./app'); 9 | 10 | function wrapVTreeWithHTMLBoilerplate(vtree, context, clientBundle) { 11 | return ` 12 | 13 | 14 | Cycle-React Isomorphism Example 15 | 16 | 17 |
${vtree}
18 | 19 | 20 | 21 | 22 | `; 23 | } 24 | 25 | const clientBundle$ = Rx.Observable.just('./client.js') 26 | .tap(js => console.log('Compiling client bundle ' + js)) 27 | .flatMap(js => { 28 | const bundleStream = browserify() 29 | .transform('babelify') 30 | .add(js) 31 | .bundle(); 32 | return fromStream(bundleStream).reduce((acc, x) => acc + x); 33 | }) 34 | .tap(() => console.log('Client bundle successfully compiled.')) 35 | .shareReplay(1); 36 | // pre-compile bundle 37 | // clientBundle$.subscribe(); 38 | 39 | const server = express(); 40 | 41 | server.use(function (req, res) { 42 | // Ignore favicon requests 43 | if (req.url === '/favicon.ico') { 44 | res.writeHead(200, {'Content-Type': 'image/x-icon'}); 45 | res.end(); 46 | return; 47 | } 48 | 49 | console.log(`req: ${req.method} ${req.url}`); 50 | 51 | const context = {route: req.url}; 52 | const componentHtml = ReactDOMServer.renderToString( 53 | React.createElement(createApp(context)) 54 | ); 55 | const html$ = Rx.Observable.combineLatest( 56 | Rx.Observable.just(componentHtml), 57 | Rx.Observable.just(context), 58 | clientBundle$, 59 | wrapVTreeWithHTMLBoilerplate 60 | ); 61 | html$.take(1).subscribe(html => res.send(html)); 62 | }); 63 | 64 | const port = process.env.PORT || 3000; 65 | server.listen(port); 66 | console.log(`Listening on port ${port}`); 67 | -------------------------------------------------------------------------------- /examples/web/lib/examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cycle-React Examples 6 | 7 | 77 | 78 | 79 |

Cycle-React Examples

80 |
    81 |
  1. hello
  2. 82 |
  3. timer
  4. 83 |
  5. counter
  6. 84 |
  7. many
  8. 85 |
  9. todomvc
  10. 86 |
87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/web/lib/rx-fromstream.js: -------------------------------------------------------------------------------- 1 | // https://github.com/Reactive-Extensions/rx-node/blob/master/index.js 2 | 'use strict'; 3 | var Rx = require('rx'); 4 | var Observable = Rx.Observable; 5 | /** 6 | * Converts a flowing stream to an Observable sequence. 7 | * @param {Stream} stream A stream to convert to a observable sequence. 8 | * @param {String} [finishEventName] Event that notifies about closed stream. 9 | * ("end" by default) 10 | * @returns {Observable} An observable sequence which fires on each 'data' event 11 | * as well as handling 'error' and finish events like `end` or `finish`. 12 | */ 13 | module.exports = function fromStream(stream, finishEventName) { 14 | stream.pause(); 15 | 16 | var finishEventNameDefault = finishEventName || 'end'; 17 | 18 | return Observable.create(function (observer) { 19 | function dataHandler(data) { 20 | observer.onNext(data); 21 | } 22 | 23 | function errorHandler(err) { 24 | observer.onError(err); 25 | } 26 | 27 | function endHandler() { 28 | observer.onCompleted(); 29 | } 30 | 31 | stream.addListener('data', dataHandler); 32 | stream.addListener('error', errorHandler); 33 | stream.addListener(finishEventNameDefault, endHandler); 34 | 35 | stream.resume(); 36 | 37 | return function () { 38 | stream.removeListener('data', dataHandler); 39 | stream.removeListener('error', errorHandler); 40 | stream.removeListener(finishEventNameDefault, endHandler); 41 | }; 42 | }).publish().refCount(); 43 | }; 44 | -------------------------------------------------------------------------------- /examples/web/many/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Many elements Example 8 | 9 | 10 | 15 |
16 |
17 |

18 | Built with Cycle-React. 19 |
20 | Compare with React 21 |

22 | 23 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/web/many/many-component.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export function ManyItem(props) { 4 | const style = { 5 | border: '1px solid #000', 6 | background: 'none repeat scroll 0% 0% ' + props.color, 7 | width: props.width + 'px', 8 | height: '70px', 9 | display: 'block', 10 | padding: '20px', 11 | margin: '10px 0px' 12 | }; 13 | function onRemoveClick() { 14 | props.onRemove(props.itemid); 15 | } 16 | function onChangeColor(ev) { 17 | props.onChangeColor({ 18 | id: props.itemid, 19 | color: ev.target.value 20 | }); 21 | } 22 | function onChangeWidth(ev) { 23 | props.onChangeWidth({ 24 | id: props.itemid, 25 | width: ev.target.value | 0 26 | }); 27 | } 28 | return
29 | 33 |
39 |
{props.width}
40 | 44 |
; 45 | } 46 | 47 | export function TopButtons(props) { 48 | function onAddOne() { 49 | props.onAddOne(1); 50 | } 51 | function onAddMany() { 52 | props.onAddMany(1000); 53 | } 54 | return ( 55 |
56 | 60 | 64 |
65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /examples/web/many/many-model.js: -------------------------------------------------------------------------------- 1 | import { map } from 'rxjs/operators' 2 | import { Map } from 'immutable'; 3 | import cuid from 'cuid'; 4 | 5 | function manyModel() { 6 | function createRandomItem() { 7 | let hexColor = Math.floor(Math.random() * 16777215).toString(16); 8 | while (hexColor.length < 6) { 9 | hexColor = '0' + hexColor; 10 | } 11 | hexColor = '#' + hexColor; 12 | const randomWidth = Math.floor(Math.random() * 800 + 200); 13 | return Map({ 14 | id: cuid(), 15 | color: hexColor, 16 | width: randomWidth 17 | }); 18 | } 19 | 20 | return { 21 | addItemMod: map(amount => listItems => { 22 | return listItems.withMutations(state => { 23 | for (let i = 0; i < amount; i++) { 24 | state.push(createRandomItem()); 25 | } 26 | }); 27 | }), 28 | removeItemMod: map(id => listItems => { 29 | return listItems.filter(item => item.get('id') !== id); 30 | }), 31 | colorChangedMod: map(x => listItems => { 32 | const index = listItems.findIndex(item => item.get('id') === x.id); 33 | return listItems.setIn([index, 'color'], x.color); 34 | }), 35 | widthChangedMod: map(x => listItems => { 36 | const index = listItems.findIndex(item => item.get('id') === x.id); 37 | return listItems.setIn([index, 'width'], x.width); 38 | }) 39 | }; 40 | } 41 | 42 | export default manyModel; 43 | -------------------------------------------------------------------------------- /examples/web/many/many.js: -------------------------------------------------------------------------------- 1 | import makeModel from './many-model'; 2 | import {ManyItem, TopButtons} from './many-component'; 3 | import {useInteractions} from 'cycle-react/rxjs'; 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | import {fromJS} from 'immutable'; 7 | 8 | const model = makeModel(); 9 | const [interactions, useCycle] = useInteractions( 10 | fromJS([{id: 0, color: 'red', width: 300}]), 11 | { 12 | Add: model.addItemMod, 13 | ItemChangeColor: model.colorChangedMod, 14 | ItemChangeWidth: model.widthChangedMod, 15 | ItemDestroy: model.removeItemMod 16 | } 17 | ); 18 | 19 | function renderItem(item) { 20 | return ( 21 | 29 | ); 30 | } 31 | 32 | function View() { 33 | const itemsData = useCycle(); 34 | return ( 35 |
36 | 38 | {itemsData.toJS().map(renderItem)} 39 |
40 | ); 41 | } 42 | 43 | ReactDOM.render( 44 | , 45 | document.querySelector('.js-container') 46 | ); 47 | -------------------------------------------------------------------------------- /examples/web/server.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var express = require('express'); 3 | var browserify = require('browserify'); 4 | var envify = require('envify/custom'); 5 | var Rx = require('rx'); 6 | var fromStream = require('./lib/rx-fromstream'); 7 | var app = express(); 8 | app.use(express.static(__dirname)); 9 | 10 | function add(x, y) { 11 | return x + y; 12 | } 13 | 14 | function compileExample(exampleName, examplePath) { 15 | var cyclePath = path.resolve(__dirname, '../../src/index.js'); 16 | var cycleRxjsPath = path.resolve(__dirname, '../../src/rxjs.js'); 17 | 18 | // shareReplay(1) to cache compiled js 19 | return Rx.Observable.defer(function () { 20 | console.log('[' + exampleName + '] compiling'); 21 | 22 | var exampleStream = browserify() 23 | .transform(envify({NODE_ENV: 'production'})) 24 | .transform('babelify', {presets: ["@babel/preset-env", "@babel/preset-react"]}) 25 | .require(cyclePath, {expose: 'cycle-react'}) 26 | .require(cycleRxjsPath, {expose: 'cycle-react/rxjs'}) 27 | .add(examplePath) 28 | .bundle(); 29 | 30 | return fromStream(exampleStream) 31 | .reduce(add) 32 | .tap(function () { 33 | console.log('[' + exampleName + '] build completed'); 34 | }); 35 | }); 36 | } 37 | 38 | var examples = { 39 | hello: compileExample('hello', path.join(__dirname, './hello/hello.js')), 40 | timer: compileExample('timer', path.join(__dirname, './timer/timer.js')), 41 | counter: compileExample('counter', path.join(__dirname, './counter/counter.js')), 42 | many: compileExample('many', path.join(__dirname, './many/many.js')), 43 | todomvc: compileExample('todomvc', path.join(__dirname, './todomvc/app.js')) 44 | }; 45 | 46 | function compiledJsRoute(req, res) { 47 | var exampleName = req.params.example; 48 | var exampleJs = examples[exampleName]; 49 | if (exampleJs) { 50 | exampleJs.subscribe(function (js) { 51 | res.set('Content-Type', 'text/javascript'); 52 | res.send(js); 53 | }); 54 | } else { 55 | res.sendStatus(404); 56 | } 57 | } 58 | 59 | app.get('/:example/compiled.js', compiledJsRoute); 60 | app.get('/synthetic-examples/:example/compiled.js', compiledJsRoute); 61 | 62 | app.get('/', function (req, res) { 63 | res.sendFile(path.resolve(__dirname, './lib/examples.html')); 64 | }); 65 | 66 | var server = app.listen(5566, 'localhost', function () { 67 | var host = server.address().address; 68 | var port = server.address().port; 69 | console.log('Example app listening at http://%s:%s', host, port); 70 | }); 71 | -------------------------------------------------------------------------------- /examples/web/timer/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": ["Cycle"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/web/timer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Timer Example 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/web/timer/timer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { useInteractions } from 'cycle-react/rxjs'; 4 | import { interval } from 'rxjs' 5 | import { map } from 'rxjs/operators' 6 | 7 | const [interactions, useCycle] = useInteractions( 8 | 0, // initial state 9 | {}, // no interactions 10 | [interval(1000).pipe(map(() => counter => counter + 1 ))] // sinks 11 | ); 12 | 13 | function Counter({counter}) { 14 | return

Seconds Elapsed: {counter}

15 | } 16 | 17 | function Timer() { 18 | const i = useCycle(); 19 | return ( 20 | 21 | ); 22 | } 23 | 24 | ReactDOM.render( 25 | , 26 | document.querySelector('.js-container') 27 | ); 28 | -------------------------------------------------------------------------------- /examples/web/todomvc/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { makeModel } from './todo-model'; 4 | import { getSource } from './todo-source'; 5 | import { Main } from './todo-view'; 6 | import { TodoContext } from './todo-context'; 7 | import { routeSource } from './window-location-source'; 8 | import { localStorageSink } from './local-storage-sink'; 9 | import { useInteractions } from 'cycle-react/rxjs'; 10 | import { scan, tap } from 'rxjs/operators' 11 | 12 | const sinks = [routeSource()]; 13 | const [interactions, useCycle] = useInteractions( 14 | getSource(), 15 | makeModel(), 16 | sinks, 17 | stateObservable => { 18 | return stateObservable.pipe( 19 | scan(function scan(state, mod) { 20 | if (typeof mod === 'function') { 21 | return mod(state); 22 | } else { 23 | console.warn('Interaction is not defined as operator (function).'); 24 | } 25 | }), 26 | tap(data => localStorageSink(data.toObject())) 27 | ); 28 | } 29 | ); 30 | 31 | function View() { 32 | const state = useCycle(); 33 | return ( 34 | 35 |
36 | 37 | ); 38 | } 39 | 40 | ReactDOM.render( 41 | , 42 | document.querySelector('.todoapp') 43 | ); 44 | -------------------------------------------------------------------------------- /examples/web/todomvc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cycle-React TodoMVC 6 | 7 | 8 | 9 |
10 |
11 |

Double-click to edit a todo

12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/web/todomvc/local-storage-sink.js: -------------------------------------------------------------------------------- 1 | export function localStorageSink(todosData) { 2 | // Observe all todos data and save them to localStorage 3 | let todosList = todosData.list.toJS(); 4 | localStorage.setItem('todos-cycle-react@2', JSON.stringify(todosList)); 5 | } 6 | -------------------------------------------------------------------------------- /examples/web/todomvc/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | button { 8 | margin: 0; 9 | padding: 0; 10 | border: 0; 11 | background: none; 12 | font-size: 100%; 13 | vertical-align: baseline; 14 | font-family: inherit; 15 | font-weight: inherit; 16 | color: inherit; 17 | -webkit-appearance: none; 18 | appearance: none; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-osx-font-smoothing: grayscale; 21 | } 22 | 23 | body { 24 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 25 | line-height: 1.4em; 26 | background: #f5f5f5; 27 | color: #4d4d4d; 28 | min-width: 230px; 29 | max-width: 550px; 30 | margin: 0 auto; 31 | -webkit-font-smoothing: antialiased; 32 | -moz-osx-font-smoothing: grayscale; 33 | font-weight: 300; 34 | } 35 | 36 | :focus { 37 | outline: 0; 38 | } 39 | 40 | .hidden { 41 | display: none; 42 | } 43 | 44 | .todoapp { 45 | background: #fff; 46 | margin: 130px 0 40px 0; 47 | position: relative; 48 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 49 | 0 25px 50px 0 rgba(0, 0, 0, 0.1); 50 | } 51 | 52 | .todoapp input::-webkit-input-placeholder { 53 | font-style: italic; 54 | font-weight: 300; 55 | color: #e6e6e6; 56 | } 57 | 58 | .todoapp input::-moz-placeholder { 59 | font-style: italic; 60 | font-weight: 300; 61 | color: #e6e6e6; 62 | } 63 | 64 | .todoapp input::input-placeholder { 65 | font-style: italic; 66 | font-weight: 300; 67 | color: #e6e6e6; 68 | } 69 | 70 | .todoapp h1 { 71 | position: absolute; 72 | top: -155px; 73 | width: 100%; 74 | font-size: 100px; 75 | font-weight: 100; 76 | text-align: center; 77 | color: rgba(175, 47, 47, 0.15); 78 | -webkit-text-rendering: optimizeLegibility; 79 | -moz-text-rendering: optimizeLegibility; 80 | text-rendering: optimizeLegibility; 81 | } 82 | 83 | .new-todo, 84 | .edit { 85 | position: relative; 86 | margin: 0; 87 | width: 100%; 88 | font-size: 24px; 89 | font-family: inherit; 90 | font-weight: inherit; 91 | line-height: 1.4em; 92 | border: 0; 93 | color: inherit; 94 | padding: 6px; 95 | border: 1px solid #999; 96 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 97 | box-sizing: border-box; 98 | -webkit-font-smoothing: antialiased; 99 | -moz-osx-font-smoothing: grayscale; 100 | } 101 | 102 | .new-todo { 103 | padding: 16px 16px 16px 60px; 104 | border: none; 105 | background: rgba(0, 0, 0, 0.003); 106 | box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); 107 | } 108 | 109 | .main { 110 | position: relative; 111 | z-index: 2; 112 | border-top: 1px solid #e6e6e6; 113 | } 114 | 115 | .toggle-all { 116 | text-align: center; 117 | border: none; /* Mobile Safari */ 118 | opacity: 0; 119 | position: absolute; 120 | } 121 | 122 | .toggle-all + label { 123 | width: 60px; 124 | height: 34px; 125 | font-size: 0; 126 | position: absolute; 127 | top: -52px; 128 | left: -13px; 129 | -webkit-transform: rotate(90deg); 130 | transform: rotate(90deg); 131 | } 132 | 133 | .toggle-all + label:before { 134 | content: '❯'; 135 | font-size: 22px; 136 | color: #e6e6e6; 137 | padding: 10px 27px 10px 27px; 138 | } 139 | 140 | .toggle-all:checked + label:before { 141 | color: #737373; 142 | } 143 | 144 | .todo-list { 145 | margin: 0; 146 | padding: 0; 147 | list-style: none; 148 | } 149 | 150 | .todo-list li { 151 | position: relative; 152 | font-size: 24px; 153 | border-bottom: 1px solid #ededed; 154 | } 155 | 156 | .todo-list li:last-child { 157 | border-bottom: none; 158 | } 159 | 160 | .todo-list li.editing { 161 | border-bottom: none; 162 | padding: 0; 163 | } 164 | 165 | .todo-list li.editing .edit { 166 | display: block; 167 | width: 506px; 168 | padding: 12px 16px; 169 | margin: 0 0 0 43px; 170 | } 171 | 172 | .todo-list li.editing .view { 173 | display: none; 174 | } 175 | 176 | .todo-list li .toggle { 177 | text-align: center; 178 | width: 40px; 179 | /* auto, since non-WebKit browsers doesn't support input styling */ 180 | height: auto; 181 | position: absolute; 182 | top: 0; 183 | bottom: 0; 184 | margin: auto 0; 185 | border: none; /* Mobile Safari */ 186 | -webkit-appearance: none; 187 | appearance: none; 188 | } 189 | 190 | .todo-list li .toggle { 191 | opacity: 0; 192 | } 193 | 194 | .todo-list li .toggle + label { 195 | /* 196 | Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433 197 | IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/ 198 | */ 199 | background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E'); 200 | background-repeat: no-repeat; 201 | background-position: center left; 202 | } 203 | 204 | .todo-list li .toggle:checked + label { 205 | background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E'); 206 | } 207 | 208 | .todo-list li label { 209 | word-break: break-all; 210 | padding: 15px 15px 15px 60px; 211 | display: block; 212 | line-height: 1.2; 213 | transition: color 0.4s; 214 | } 215 | 216 | .todo-list li.completed label { 217 | color: #d9d9d9; 218 | text-decoration: line-through; 219 | } 220 | 221 | .todo-list li .destroy { 222 | display: none; 223 | position: absolute; 224 | top: 0; 225 | right: 10px; 226 | bottom: 0; 227 | width: 40px; 228 | height: 40px; 229 | margin: auto 0; 230 | font-size: 30px; 231 | color: #cc9a9a; 232 | margin-bottom: 11px; 233 | transition: color 0.2s ease-out; 234 | } 235 | 236 | .todo-list li .destroy:hover { 237 | color: #af5b5e; 238 | } 239 | 240 | .todo-list li .destroy:after { 241 | content: '×'; 242 | } 243 | 244 | .todo-list li:hover .destroy { 245 | display: block; 246 | } 247 | 248 | .todo-list li .edit { 249 | display: none; 250 | } 251 | 252 | .todo-list li.editing:last-child { 253 | margin-bottom: -1px; 254 | } 255 | 256 | .footer { 257 | color: #777; 258 | padding: 10px 15px; 259 | height: 20px; 260 | text-align: center; 261 | border-top: 1px solid #e6e6e6; 262 | } 263 | 264 | .footer:before { 265 | content: ''; 266 | position: absolute; 267 | right: 0; 268 | bottom: 0; 269 | left: 0; 270 | height: 50px; 271 | overflow: hidden; 272 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 273 | 0 8px 0 -3px #f6f6f6, 274 | 0 9px 1px -3px rgba(0, 0, 0, 0.2), 275 | 0 16px 0 -6px #f6f6f6, 276 | 0 17px 2px -6px rgba(0, 0, 0, 0.2); 277 | } 278 | 279 | .todo-count { 280 | float: left; 281 | text-align: left; 282 | } 283 | 284 | .todo-count strong { 285 | font-weight: 300; 286 | } 287 | 288 | .filters { 289 | margin: 0; 290 | padding: 0; 291 | list-style: none; 292 | position: absolute; 293 | right: 0; 294 | left: 0; 295 | } 296 | 297 | .filters li { 298 | display: inline; 299 | } 300 | 301 | .filters li a { 302 | color: inherit; 303 | margin: 3px; 304 | padding: 3px 7px; 305 | text-decoration: none; 306 | border: 1px solid transparent; 307 | border-radius: 3px; 308 | } 309 | 310 | .filters li a:hover { 311 | border-color: rgba(175, 47, 47, 0.1); 312 | } 313 | 314 | .filters li a.selected { 315 | border-color: rgba(175, 47, 47, 0.2); 316 | } 317 | 318 | .clear-completed, 319 | html .clear-completed:active { 320 | float: right; 321 | position: relative; 322 | line-height: 20px; 323 | text-decoration: none; 324 | cursor: pointer; 325 | } 326 | 327 | .clear-completed:hover { 328 | text-decoration: underline; 329 | } 330 | 331 | .info { 332 | margin: 65px auto 0; 333 | color: #bfbfbf; 334 | font-size: 10px; 335 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 336 | text-align: center; 337 | } 338 | 339 | .info p { 340 | line-height: 1; 341 | } 342 | 343 | .info a { 344 | color: inherit; 345 | text-decoration: none; 346 | font-weight: 400; 347 | } 348 | 349 | .info a:hover { 350 | text-decoration: underline; 351 | } 352 | 353 | /* 354 | Hack to remove background from Mobile Safari. 355 | Can't use it globally since it destroys checkboxes in Firefox 356 | */ 357 | @media screen and (-webkit-min-device-pixel-ratio:0) { 358 | .toggle-all, 359 | .todo-list li .toggle { 360 | background: none; 361 | } 362 | 363 | .todo-list li .toggle { 364 | height: 40px; 365 | } 366 | } 367 | 368 | @media (max-width: 430px) { 369 | .footer { 370 | height: 50px; 371 | } 372 | 373 | .filters { 374 | bottom: 10px; 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /examples/web/todomvc/todo-context.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const TodoContext = React.createContext({ 4 | changeInput: todoText => {}, 5 | clearInput: () => {}, 6 | insertTodo: todoText => {}, 7 | editTodo: (id, content) => {}, 8 | toggleTodo: id => {}, 9 | toggleAll: () => {}, 10 | deleteTodo: id => {}, 11 | deleteCompleted: () => {} 12 | }); 13 | -------------------------------------------------------------------------------- /examples/web/todomvc/todo-item.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | const ESC_KEY = 27; 4 | 5 | export class TodoItem extends Component { 6 | constructor(props) { 7 | super(props); 8 | this.state = { 9 | editContent: '', 10 | editing: false 11 | }; 12 | } 13 | onSubmitHandler(e) { 14 | e.preventDefault(); 15 | /*eslint-disable dot-notation */ 16 | this.stopEdit(e.target.elements['contentedit'].value); 17 | /*eslint-enable dot-notation */ 18 | } 19 | onChange(ev) { 20 | this.setState({ 21 | editContent: ev.target.value, 22 | editing: true 23 | }); 24 | } 25 | onKeyUp(ev) { 26 | if (ev.keyCode === ESC_KEY) { 27 | this.stopEdit(ev.target.value); 28 | } 29 | } 30 | startEdit() { 31 | this.setState({ 32 | editContent: this.props.content, 33 | editing: true 34 | }); 35 | } 36 | stopEdit(content) { 37 | this.setState({ 38 | editContent: content, 39 | editing: false 40 | }); 41 | if (content.trim() !== '') { 42 | this.props.onNewContent({ 43 | id: this.props.todoid, 44 | content: content.trim() 45 | }); 46 | } 47 | } 48 | render() { 49 | const className = (this.props.completed ? 'completed ' : '') + 50 | (this.state.editing ? 'editing' : ''); 51 | if (this.state.editing) { 52 | return
  • 53 |
    55 | this.stopEdit(ev.target.value)} /> 62 |
    63 |
  • ; 64 | } 65 | return
  • 66 |
    67 | this.props.onToggle(this.props.todoid)} /> 71 | 74 |
    77 |
  • ; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/web/todomvc/todo-model.js: -------------------------------------------------------------------------------- 1 | import cuid from 'cuid'; 2 | import { Map } from 'immutable'; 3 | import { map } from 'rxjs/operators' 4 | 5 | export function makeModel() { 6 | return { 7 | changeInput: map(content => todosData => todosData.set('input', content)), 8 | clearInput: map(() => todosData => todosData.set('input', '')), 9 | insertTodo: map(todoTitle => (todosData) => { 10 | return todosData.withMutations(m => { 11 | m.update('list', list => list.push(Map({ 12 | id: cuid(), 13 | title: todoTitle, 14 | completed: false 15 | }))); 16 | m.set('input', ''); 17 | }); 18 | }), 19 | editTodo: map(({id, content}) => todosData => { 20 | return todosData.update('list', list => { 21 | const index = list.findIndex(item => item.get('id') === id); 22 | return list.setIn([index, 'title'], content); 23 | }); 24 | }), 25 | toggleTodo: map(id => todosData => { 26 | return todosData.update('list', list => { 27 | const index = list.findIndex(item => item.get('id') === id); 28 | return list.updateIn([index, 'completed'], completed => !completed); 29 | }); 30 | }), 31 | toggleAll: map(() => todosData => { 32 | const allAreCompleted = todosData.get('list') 33 | .every(item => item.get('completed')); 34 | return todosData.update( 35 | 'list', 36 | list => list.map(item => item.set('completed', !allAreCompleted)).toList() 37 | ); 38 | }), 39 | deleteTodo: map(todoid => todosData => { 40 | const index = todosData.get('list').findIndex(item => item.get('id') === todoid); 41 | return todosData.deleteIn(['list', index]); 42 | }), 43 | deleteCompleted: map(() => todosData => { 44 | return todosData.update( 45 | 'list', 46 | list => list.filter(item => !item.get('completed')).toList() 47 | ); 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/web/todomvc/todo-source.js: -------------------------------------------------------------------------------- 1 | import { fromJS } from 'immutable'; 2 | 3 | export function getSource() { 4 | const storedTodosList = JSON.parse(localStorage.getItem('todos-cycle-react@2')); 5 | const initialTodosData = fromJS({ 6 | list: storedTodosList || [], 7 | input: '', 8 | filter: '', 9 | filterFn: () => true // allow anything 10 | }); 11 | return initialTodosData; 12 | } 13 | -------------------------------------------------------------------------------- /examples/web/todomvc/todo-view.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TodoItem } from './todo-item'; 3 | import { TodoContext } from './todo-context'; 4 | 5 | function Header(props) { 6 | function onInputSubmit(e) { 7 | e.preventDefault(); 8 | props.onInputSubmit(e.target.elements.newTodo.value); 9 | } 10 | function onClearInput(e) { 11 | const ESC_KEY = 27; 12 | if (e.keyCode === ESC_KEY) { 13 | props.onClearInput(); 14 | } 15 | } 16 | function onInputChange(e) { 17 | props.onInputChange(e.target.value); 18 | } 19 | 20 | return ( 21 |
    22 |

    todos

    23 |
    25 | 33 |
    34 |
    35 | ); 36 | } 37 | 38 | function MainSection(props) { 39 | const {list, filterFn} = props; 40 | const allCompleted = list.reduce((x, y) => x && y.get('completed'), true); 41 | const style = {display: list.size ? 'inherit' : 'none'}; 42 | return ( 43 | 44 | {(ev) => ( 45 |
    46 | 50 |
      51 | {list 52 | .filter(filterFn) 53 | .map(item => 54 | 61 | ).toArray()} 62 |
    63 |
    64 | )} 65 |
    66 | ); 67 | } 68 | 69 | function CompleteButton({amountCompleted, onClearCompleted}) { 70 | if (amountCompleted > 0) { 71 | return ; 75 | } 76 | return
    ; 77 | } 78 | 79 | function Footer(props) { 80 | const {list, filter, onClearCompleted} = props; 81 | const amountCompleted = list.count(item => item.get('completed')); 82 | const amountActive = list.size - amountCompleted; 83 | const style = {display: list.size ? 'inherit' : 'none'}; 84 | 85 | return ( 86 | 113 | ); 114 | } 115 | 116 | export function Main(props) { 117 | return ( 118 | 119 | {(ev) => ( 120 |
    121 |
    125 | 127 |
    131 | )} 132 |
    133 | ); 134 | } 135 | -------------------------------------------------------------------------------- /examples/web/todomvc/window-location-source.js: -------------------------------------------------------------------------------- 1 | import { fromEvent } from 'rxjs'; 2 | import { map, startWith } from 'rxjs/operators' 3 | 4 | function getFilterFn(route) { 5 | switch (route) { 6 | case '/active': return task => task.get('completed') === false; 7 | case '/completed': return task => task.get('completed') === true; 8 | default: return () => true; // allow anything 9 | } 10 | } 11 | 12 | export function routeSource() { 13 | return fromEvent(window, 'hashchange') 14 | .pipe( 15 | map(ev => ev.newURL.match(/#[^#]*$/)[0].replace('#', '')), 16 | startWith(window.location.hash.replace('#', '')), 17 | map(route => todosData => { 18 | return todosData.withMutations(m => { 19 | m.set('filter', route.replace('/', '').trim()); 20 | m.set('filterFn', getFilterFn(route)); 21 | }); 22 | }) 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cycle-react", 3 | "version": "7.0.0", 4 | "author": { 5 | "name": "pH200", 6 | "email": "ph.minamo@cytisan.com" 7 | }, 8 | "description": "Rx functional interface to Facebook's React", 9 | "license": "MIT", 10 | "homepage": "https://github.com/pH200/cycle-react", 11 | "bugs": "https://github.com/pH200/cycle-react/issues", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/pH200/cycle-react" 15 | }, 16 | "keywords": [ 17 | "react", 18 | "hooks", 19 | "Rx", 20 | "RxJS", 21 | "web", 22 | "mvi", 23 | "frontend", 24 | "functional" 25 | ], 26 | "main": "build/index.js", 27 | "devDependencies": { 28 | "@babel/cli": "^7.5.5", 29 | "@babel/core": "^7.5.5", 30 | "@babel/preset-env": "^7.5.5", 31 | "@babel/preset-react": "^7.0.0", 32 | "babelify": "^10.0.0", 33 | "browserify": "^16.5.0", 34 | "cuid": "^2.1.6", 35 | "envify": "^4.1.0", 36 | "eslint": "^6.1.0", 37 | "express": "^4.17.1", 38 | "immutable": "^3.8.2", 39 | "jest": "^24.8.0", 40 | "lodash": "^4.17.15", 41 | "prop-types": "^15.7.2", 42 | "react": "^16.9.0", 43 | "react-dom": "^16.9.0", 44 | "react-test-renderer": "^16.9.0", 45 | "rx": "^4.1.0", 46 | "rxjs": "^6.5.2", 47 | "rxjs-compat": "^6.5.2", 48 | "shelljs": "^0.8.3" 49 | }, 50 | "engines": { 51 | "node": ">=6.9.0" 52 | }, 53 | "scripts": { 54 | "lint": "eslint src examples test", 55 | "test-jest": "jest", 56 | "test": "npm run lint && jest", 57 | "travis-test": "npm run lint && jest --verbose", 58 | "examples": "node examples/web/server.js", 59 | "build": "babel src --presets=@babel/preset-env --out-dir build", 60 | "_publish": "npm test && npm run build && node .make-package.js" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const { 2 | scan, 3 | startWith, 4 | createEventSubject, 5 | mergeObservable } = require('./rxjs-adapter'); 6 | const { safeWarn } = require('./util'); 7 | const makeInteractions = require('./interactions'); 8 | const { useState, useEffect } = require('react'); 9 | 10 | function defaultMapStateObservable(observable) { 11 | return scan(function scan(state, mod) { 12 | if (typeof mod === 'function') { 13 | return mod(state); 14 | } else { 15 | safeWarn('Interaction is not defined as operator (function).'); 16 | } 17 | })(observable); 18 | } 19 | 20 | function useInteractions(initialState, defineInteractions, sinks, mapStateObservable) { 21 | const interactions = makeInteractions(createEventSubject); 22 | const interactionList = Array.isArray(sinks) ? sinks : []; 23 | const names = Object.keys(defineInteractions); 24 | for (let i = 0; i < names.length; i++) { 25 | const name = names[i]; 26 | const definitionFn = defineInteractions[name]; 27 | const interactionObs = interactions.get(name); 28 | const mappedInteractionObs = definitionFn.call( 29 | defineInteractions, 30 | interactionObs 31 | ); 32 | if (!mappedInteractionObs) { 33 | throw new Error(`Interaction ${name} is undefined.`); 34 | } 35 | if (typeof mappedInteractionObs.subscribe !== 'function') { 36 | throw new Error(`Interaction ${name} does not return Observable.`); 37 | } 38 | interactionList.push(mappedInteractionObs); 39 | } 40 | 41 | const cycle = { 42 | subscribe() { 43 | const observable = startWith(initialState)(mergeObservable(interactionList)); 44 | const mappedObs = mapStateObservable 45 | ? mapStateObservable(observable) 46 | : defaultMapStateObservable(observable); 47 | const subscription = mappedObs.subscribe(function next(value) { 48 | cycle.setState(value); 49 | }); 50 | return function unsubscribe() { 51 | subscription.unsubscribe(); 52 | }; 53 | }, 54 | // setState: To be replaced in useCycle. 55 | setState() { 56 | safeWarn('setState is called before component is mounted'); 57 | }, 58 | interactions 59 | }; 60 | const subscribe = cycle.subscribe.bind(cycle); 61 | function useCycle() { 62 | const [state, setState] = useState(initialState); 63 | cycle.setState = setState; 64 | useEffect(subscribe, []); 65 | return state; 66 | } 67 | return [interactions, useCycle]; 68 | } 69 | 70 | module.exports = { 71 | useInteractions 72 | }; 73 | -------------------------------------------------------------------------------- /src/interactions.js: -------------------------------------------------------------------------------- 1 | const { safeWarn } = require('./util'); 2 | 3 | function makeInteractions(createEventSubject) { 4 | const subjects = {}; 5 | 6 | function get(name) { 7 | if (name === null || typeof name !== 'string') { 8 | throw new Error('Invalid name for the interaction collection.'); 9 | } 10 | if (!subjects[name]) { 11 | subjects[name] = createEventSubject(); 12 | } 13 | return subjects[name]; 14 | } 15 | 16 | function listener(name) { 17 | const eventSubject = subjects[name]; 18 | if (!eventSubject) { 19 | safeWarn( 20 | 'Listening event "' + name + '" before using interactions.get("' + 21 | name + '")' 22 | ); 23 | } 24 | return (eventSubject || get(name)).onEvent; 25 | } 26 | 27 | function bindListeners(interactionTypes) { 28 | const result = {}; 29 | const names = Object.keys(interactionTypes); 30 | for (let i = 0; i < names.length; i++) { 31 | const name = names[i]; 32 | result[name] = listener(interactionTypes[name]); 33 | } 34 | return result; 35 | } 36 | 37 | function bindAllListeners() { 38 | const result = {}; 39 | const names = Object.keys(subjects); 40 | for (let i = 0; i < names.length; i++) { 41 | const name = names[i]; 42 | result[name] = listener(name); 43 | } 44 | return result; 45 | } 46 | 47 | function _getCurrentListeners() { 48 | const result = {}; 49 | const names = Object.keys(subjects); 50 | for (let i = 0; i < names.length; i++) { 51 | const name = names[i]; 52 | result[name] = listener(name); 53 | } 54 | return result; 55 | } 56 | 57 | listener.get = get; 58 | listener.listener = listener; 59 | listener.bindListeners = bindListeners ; 60 | listener.bindAllListeners = bindAllListeners; 61 | listener._getCurrentListeners = _getCurrentListeners; 62 | 63 | return listener; 64 | } 65 | 66 | module.exports = makeInteractions; 67 | -------------------------------------------------------------------------------- /src/rxjs-adapter.js: -------------------------------------------------------------------------------- 1 | const { merge, Subject } = require('rxjs'); 2 | const { scan, startWith } = require('rxjs/operators'); 3 | 4 | module.exports = { 5 | scan, 6 | startWith, 7 | createEventSubject() { 8 | const subject = new Subject(); 9 | subject.onEvent = function onEvent(value) { 10 | subject.next(value); 11 | }; 12 | return subject; 13 | }, 14 | mergeObservable(array) { 15 | return merge.apply(merge, array); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /src/rxjs.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = require('./index'); 3 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | safeWarn(warn) { 3 | /* eslint-disable no-console */ 4 | if (process.env.NODE_ENV !== 'production' && typeof console !== 'undefined') { 5 | console.warn(warn); 6 | } 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /test/browser/lib/controlled.js: -------------------------------------------------------------------------------- 1 | const {Subject} = require('rxjs/Subject'); 2 | const {range} = require('lodash'); 3 | 4 | module.exports = function controlled(values) { 5 | const subject = new Subject(); 6 | let startIndex = 0; 7 | function request(number) { 8 | if (number <= 0) { 9 | return; 10 | } 11 | const from = startIndex; 12 | const to = Math.min(from + number, values.length); 13 | if (from >= values.length) { 14 | return; 15 | } 16 | for (const i of range(from, to)) { 17 | subject.next(values[i]); 18 | } 19 | if (to === values.length) { 20 | subject.complete(); 21 | } 22 | 23 | startIndex = to; 24 | } 25 | const observable = subject.asObservable(); 26 | observable.request = request; 27 | return { 28 | observable, 29 | request 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /test/browser/render.test.js: -------------------------------------------------------------------------------- 1 | const r = require('react').createElement; 2 | const renderer = require('react-test-renderer'); 3 | //const {useInteractions} = require('../../src/rxjs'); 4 | 5 | describe.skip('render', () => { 6 | jest.useRealTimers(); 7 | afterEach(done => setTimeout(done, 1)); 8 | 9 | it('should throw if definitionFn returns bad output', () => { 10 | /* eslint-disable no-console */ 11 | const tempConsoleError = console.error; 12 | console.error = jest.fn(); 13 | 14 | expect(() => { 15 | renderer.create(r('div')); 16 | }).toThrowError(/Invalid definitionFn/); 17 | 18 | console.error = tempConsoleError; 19 | }); 20 | 21 | it('should throw if templateFn returns bad output', () => { 22 | /* eslint-disable no-console */ 23 | const tempConsoleError = console.error; 24 | console.error = jest.fn(); 25 | 26 | expect(() => { 27 | renderer.create(r('div')); 28 | }).toThrowError(/Invalid templateFn/); 29 | 30 | console.error = tempConsoleError; 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/common/interactions.test.js: -------------------------------------------------------------------------------- 1 | const makeInteractions = require('../../src/interactions'); 2 | 3 | function mockCreateEventSubject() { 4 | const mockSubject = { 5 | onEvent: jest.fn(), 6 | subscribe: jest.fn() 7 | }; 8 | return { 9 | mockFn: jest.fn(() => mockSubject), 10 | mockSubject 11 | }; 12 | } 13 | 14 | describe('interactions', () => { 15 | it('should provide collection of interactions', () => { 16 | const {mockFn, mockSubject} = mockCreateEventSubject(); 17 | const interactions = makeInteractions(mockFn); 18 | const observable = interactions.get('foo'); 19 | expect(observable).toBe(mockSubject); 20 | const proxyHandler = interactions.listener('foo'); 21 | proxyHandler('bar'); 22 | expect(mockSubject.onEvent).toBeCalledWith('bar'); 23 | }); 24 | 25 | it('should return the same interaction observable from the same key', () => { 26 | const interactions = makeInteractions(jest.fn(() => [])); 27 | expect(interactions.get('foo')) 28 | .toBe(interactions.get('foo')); 29 | }); 30 | 31 | it('should return the object of listeners by bindListeners', () => { 32 | const {mockFn, mockSubject} = mockCreateEventSubject(); 33 | const interactions = makeInteractions(mockFn); 34 | const interactionTypes = { 35 | foo: 'onFoo', 36 | foo2: 'onFoo2' 37 | }; 38 | interactions.get(interactionTypes.foo); 39 | interactions.get(interactionTypes.foo2); 40 | 41 | const listeners = interactions.bindListeners(interactionTypes); 42 | expect(listeners.foo).toBeDefined(); 43 | expect(listeners.foo2).toBeDefined(); 44 | // test listeners 45 | listeners.foo('bar'); 46 | expect(mockSubject.onEvent).toBeCalledWith('bar'); 47 | // test listener key 48 | interactions.listener(interactionTypes.foo2)('bar2'); 49 | expect(mockSubject.onEvent).toBeCalledWith('bar2'); 50 | }); 51 | 52 | it('should return the object of all listeners by bindAllListeners', () => { 53 | const {mockFn, mockSubject} = mockCreateEventSubject(); 54 | const interactions = makeInteractions(mockFn); 55 | interactions.get('foo'); 56 | interactions.get('foo2'); 57 | 58 | const listeners = interactions.bindAllListeners(); 59 | expect(listeners.foo).toBeDefined(); 60 | expect(listeners.foo2).toBeDefined(); 61 | // test listeners 62 | listeners.foo('bar'); 63 | expect(mockSubject.onEvent).toBeCalledWith('bar'); 64 | // test listener key 65 | interactions.listener('foo2')('bar2'); 66 | expect(mockSubject.onEvent).toBeCalledWith('bar2'); 67 | }); 68 | 69 | it('should throw error when the key is null', () => { 70 | const interactions = makeInteractions(mockCreateEventSubject); 71 | expect(() => interactions.get()).toThrowError(/Invalid name/i); 72 | expect(() => interactions.get(null)).toThrowError(/Invalid name/i); 73 | }); 74 | 75 | it('should warn when `listener` is used before `get`', (done) => { 76 | /* eslint-disable no-console */ 77 | const interactions = makeInteractions(mockCreateEventSubject); 78 | const tempConsoleWarn = console.warn; 79 | console.warn = function warn(message) { 80 | expect(message).toMatch(/foo/); 81 | console.warn = tempConsoleWarn; 82 | done(); 83 | }; 84 | interactions.listener('foo'); 85 | }); 86 | }); 87 | --------------------------------------------------------------------------------