├── .gitignore
├── .tool-versions
├── README.md
├── counter-example.gif
├── demo
├── .formatter.exs
├── .gitignore
├── README.md
├── assets
│ ├── .babelrc
│ ├── css
│ │ ├── app.scss
│ │ └── phoenix.css
│ ├── js
│ │ ├── app.js
│ │ └── components
│ │ │ ├── Array.js
│ │ │ ├── Counter.js
│ │ │ ├── Dictionary.js
│ │ │ └── Value.js
│ ├── package.json
│ ├── static
│ │ ├── favicon.ico
│ │ ├── images
│ │ │ └── phoenix.png
│ │ └── robots.txt
│ ├── tailwind.config.js
│ ├── webpack.config.js
│ └── yarn.lock
├── config
│ ├── config.exs
│ ├── dev.exs
│ ├── hooks.exs
│ ├── prod.exs
│ ├── prod.secret.exs
│ └── test.exs
├── lib
│ ├── demo.ex
│ ├── demo
│ │ ├── application.ex
│ │ ├── array.ex
│ │ ├── counter.ex
│ │ ├── dictionary.ex
│ │ └── random.ex
│ ├── demo_web.ex
│ └── demo_web
│ │ ├── channels
│ │ ├── hook_channel.ex
│ │ └── user_socket.ex
│ │ ├── controllers
│ │ ├── demo_controller.ex
│ │ └── page_controller.ex
│ │ ├── endpoint.ex
│ │ ├── gettext.ex
│ │ ├── router.ex
│ │ ├── templates
│ │ ├── demo
│ │ │ ├── array.html.eex
│ │ │ ├── counter.html.eex
│ │ │ ├── dictionary.html.eex
│ │ │ └── read-only.html.eex
│ │ ├── layout
│ │ │ ├── analytics.html.eex
│ │ │ └── app.html.eex
│ │ └── page
│ │ │ └── index.html.eex
│ │ └── views
│ │ ├── demo_view.ex
│ │ ├── error_helpers.ex
│ │ ├── error_view.ex
│ │ ├── layout_view.ex
│ │ └── page_view.ex
├── mix.exs
├── mix.lock
├── priv
│ └── gettext
│ │ ├── en
│ │ └── LC_MESSAGES
│ │ │ └── errors.po
│ │ └── errors.pot
└── test
│ ├── demo_web
│ ├── channels
│ │ └── hook_channel_test.exs
│ ├── controllers
│ │ └── page_controller_test.exs
│ └── views
│ │ ├── error_view_test.exs
│ │ ├── layout_view_test.exs
│ │ └── page_view_test.exs
│ ├── support
│ ├── channel_case.ex
│ └── conn_case.ex
│ └── test_helper.exs
├── elixir_buildpack.config
├── examples
├── README.md
└── minimal.md
├── glue
├── .formatter.exs
├── .gitignore
├── README.md
├── lib
│ ├── glue.ex
│ └── glue
│ │ ├── generator.ex
│ │ └── view.ex
├── mix.exs
└── test
│ ├── glue_test.exs
│ └── test_helper.exs
├── lerna.json
├── package.json
└── packages
├── README.md
├── core
├── .gitignore
├── package.json
├── src
│ ├── index.js
│ └── socket.js
└── yarn.lock
└── react
├── .gitignore
├── package-lock.json
├── package.json
├── src
└── index.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /yarn.lock
3 |
--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | elixir 1.9.0
2 | erlang 21.2.3
3 | nodejs 12.4.0
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Easy server-side state with React & Phoenix
2 |
3 | React is great at rendering HTML, but sharing state can be tricky.
4 |
5 | One technology that is designed for managing large amounts of shared state is the [Actor Model](https://en.wikipedia.org/wiki/Actor_model), known in Erlang as `GenServer`.
6 |
7 | By relying on Erlang for state management, it frees us from needing to write boilerplate Redux, hooks and/or GraphQL/REST wrappers and just write GenServer code. The React hooks and Websocket code is then generated for you.
8 |
9 | [View live demo](http://react-use-server-state.gigalixirapp.com/)
10 |
11 | ## Counter Example
12 |
13 | Let's take the example of a simple counter. This is what it looks like with React's `useState()` hook:
14 |
15 | ```js
16 | import React, {useState} from 'react'
17 |
18 | export default function() {
19 | const [count, set] = useState(0)
20 |
21 | return (
22 |
23 |
24 |
25 |
26 |
{count}
27 |
28 | )
29 | }
30 | ```
31 |
32 | Instead of storing state in the local browser's memory with `useState()`, we can switch to server-side state by simply swapping `useState()` to `useServerState()`:
33 |
34 | ```js
35 | import React from 'react'
36 | import {useServerState} from '@glue/react'
37 |
38 | export default function() {
39 | const {count, increment, decrement} = useServerState('counter', {sync: true})
40 |
41 | return (
42 |
43 |
44 |
45 |
46 |
{count}
47 |
48 | )
49 | }
50 | ```
51 |
52 | The state will first be queried from the server. Subsequent changes will be synced back to the server and then between all connected users via Websockets.
53 |
54 | Now we just need to define a `GenServer` to hold the state in the backend:
55 |
56 | ```elixir
57 | defmodule Counter do
58 | use Agent
59 |
60 | @name :counter
61 |
62 | def start_link(_opts),
63 | do: Agent.start_link(fn -> 0 end, name: @name)
64 |
65 | def get(), do: Agent.get(@name, & &1)
66 | def increment(), do: apply(+1)
67 | def decrement(), do: apply(-1)
68 |
69 | defp apply(delta) do
70 | Agent.get_and_update(@name, &{&1 + delta, &1 + delta})
71 | end
72 | end
73 | ```
74 |
75 | That's it! Just `GenServer`'s and pure JSX components.
76 |
77 | 
78 |
79 | ### This is alpha software.
80 |
--------------------------------------------------------------------------------
/counter-example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshnuss/glue/d8d406e34c68d4f8f520a9b81b6774cdd838e0dc/counter-example.gif
--------------------------------------------------------------------------------
/demo/.formatter.exs:
--------------------------------------------------------------------------------
1 | [
2 | import_deps: [:phoenix],
3 | inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}"]
4 | ]
5 |
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where 3rd-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Ignore package tarball (built via "mix hex.build").
23 | phx_hooks-*.tar
24 |
25 | # If NPM crashes, it generates a log, let's ignore it too.
26 | npm-debug.log
27 |
28 | # The directory NPM downloads your dependencies sources to.
29 | /assets/node_modules/
30 |
31 | # Since we are building assets from assets/,
32 | # we ignore priv/static. You may want to comment
33 | # this depending on your deployment strategy.
34 | /priv/static/
35 |
--------------------------------------------------------------------------------
/demo/README.md:
--------------------------------------------------------------------------------
1 | # Demo App
2 |
3 | A phoenix app that provides demos.
4 |
5 | ## Development
6 |
7 | To start the dev server:
8 |
9 | ```bash
10 | cd demo && mix phx.server
11 | ```
12 |
--------------------------------------------------------------------------------
/demo/assets/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-react"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-transform-runtime"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/demo/assets/css/app.scss:
--------------------------------------------------------------------------------
1 | /* @import "font-awesome"; */
2 | @import "tailwindcss/base";
3 | @import "tailwindcss/components";
4 | @import "tailwindcss/utilities";
5 |
--------------------------------------------------------------------------------
/demo/assets/css/phoenix.css:
--------------------------------------------------------------------------------
1 | /* Includes some default style for the starter application.
2 | * This can be safely deleted to start fresh.
3 | */
4 |
5 | /* Milligram v1.3.0 https://milligram.github.io
6 | * Copyright (c) 2017 CJ Patoilo Licensed under the MIT license
7 | */
8 |
9 | *,*:after,*:before{box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%}body{color:#000000;font-family:'Helvetica', 'Arial', sans-serif;font-size:1.6em;font-weight:300;line-height:1.6}blockquote{border-left:0.3rem solid #d1d1d1;margin-left:0;margin-right:0;padding:1rem 1.5rem}blockquote *:last-child{margin-bottom:0}.button,button,input[type='button'],input[type='reset'],input[type='submit']{background-color:#0069d9;border:0.1rem solid #0069d9;border-radius:.4rem;color:#fff;cursor:pointer;display:inline-block;font-size:1.1rem;font-weight:700;height:3.8rem;letter-spacing:.1rem;line-height:3.8rem;padding:0 3.0rem;text-align:center;text-decoration:none;text-transform:uppercase;white-space:nowrap}.button:focus,.button:hover,button:focus,button:hover,input[type='button']:focus,input[type='button']:hover,input[type='reset']:focus,input[type='reset']:hover,input[type='submit']:focus,input[type='submit']:hover{background-color:#606c76;border-color:#606c76;color:#fff;outline:0}.button[disabled],button[disabled],input[type='button'][disabled],input[type='reset'][disabled],input[type='submit'][disabled]{cursor:default;opacity:.5}.button[disabled]:focus,.button[disabled]:hover,button[disabled]:focus,button[disabled]:hover,input[type='button'][disabled]:focus,input[type='button'][disabled]:hover,input[type='reset'][disabled]:focus,input[type='reset'][disabled]:hover,input[type='submit'][disabled]:focus,input[type='submit'][disabled]:hover{background-color:#0069d9;border-color:#0069d9}.button.button-outline,button.button-outline,input[type='button'].button-outline,input[type='reset'].button-outline,input[type='submit'].button-outline{background-color:transparent;color:#0069d9}.button.button-outline:focus,.button.button-outline:hover,button.button-outline:focus,button.button-outline:hover,input[type='button'].button-outline:focus,input[type='button'].button-outline:hover,input[type='reset'].button-outline:focus,input[type='reset'].button-outline:hover,input[type='submit'].button-outline:focus,input[type='submit'].button-outline:hover{background-color:transparent;border-color:#606c76;color:#606c76}.button.button-outline[disabled]:focus,.button.button-outline[disabled]:hover,button.button-outline[disabled]:focus,button.button-outline[disabled]:hover,input[type='button'].button-outline[disabled]:focus,input[type='button'].button-outline[disabled]:hover,input[type='reset'].button-outline[disabled]:focus,input[type='reset'].button-outline[disabled]:hover,input[type='submit'].button-outline[disabled]:focus,input[type='submit'].button-outline[disabled]:hover{border-color:inherit;color:#0069d9}.button.button-clear,button.button-clear,input[type='button'].button-clear,input[type='reset'].button-clear,input[type='submit'].button-clear{background-color:transparent;border-color:transparent;color:#0069d9}.button.button-clear:focus,.button.button-clear:hover,button.button-clear:focus,button.button-clear:hover,input[type='button'].button-clear:focus,input[type='button'].button-clear:hover,input[type='reset'].button-clear:focus,input[type='reset'].button-clear:hover,input[type='submit'].button-clear:focus,input[type='submit'].button-clear:hover{background-color:transparent;border-color:transparent;color:#606c76}.button.button-clear[disabled]:focus,.button.button-clear[disabled]:hover,button.button-clear[disabled]:focus,button.button-clear[disabled]:hover,input[type='button'].button-clear[disabled]:focus,input[type='button'].button-clear[disabled]:hover,input[type='reset'].button-clear[disabled]:focus,input[type='reset'].button-clear[disabled]:hover,input[type='submit'].button-clear[disabled]:focus,input[type='submit'].button-clear[disabled]:hover{color:#0069d9}code{background:#f4f5f6;border-radius:.4rem;font-size:86%;margin:0 .2rem;padding:.2rem .5rem;white-space:nowrap}pre{background:#f4f5f6;border-left:0.3rem solid #0069d9;overflow-y:hidden}pre>code{border-radius:0;display:block;padding:1rem 1.5rem;white-space:pre}hr{border:0;border-top:0.1rem solid #f4f5f6;margin:3.0rem 0}input[type='email'],input[type='number'],input[type='password'],input[type='search'],input[type='tel'],input[type='text'],input[type='url'],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:0.1rem solid #d1d1d1;border-radius:.4rem;box-shadow:none;box-sizing:inherit;height:3.8rem;padding:.6rem 1.0rem;width:100%}input[type='email']:focus,input[type='number']:focus,input[type='password']:focus,input[type='search']:focus,input[type='tel']:focus,input[type='text']:focus,input[type='url']:focus,textarea:focus,select:focus{border-color:#0069d9;outline:0}select{background:url('data:image/svg+xml;utf8,') center right no-repeat;padding-right:3.0rem}select:focus{background-image:url('data:image/svg+xml;utf8,')}textarea{min-height:6.5rem}label,legend{display:block;font-size:1.6rem;font-weight:700;margin-bottom:.5rem}fieldset{border-width:0;padding:0}input[type='checkbox'],input[type='radio']{display:inline}.label-inline{display:inline-block;font-weight:normal;margin-left:.5rem}.row{display:flex;flex-direction:column;padding:0;width:100%}.row.row-no-padding{padding:0}.row.row-no-padding>.column{padding:0}.row.row-wrap{flex-wrap:wrap}.row.row-top{align-items:flex-start}.row.row-bottom{align-items:flex-end}.row.row-center{align-items:center}.row.row-stretch{align-items:stretch}.row.row-baseline{align-items:baseline}.row .column{display:block;flex:1 1 auto;margin-left:0;max-width:100%;width:100%}.row .column.column-offset-10{margin-left:10%}.row .column.column-offset-20{margin-left:20%}.row .column.column-offset-25{margin-left:25%}.row .column.column-offset-33,.row .column.column-offset-34{margin-left:33.3333%}.row .column.column-offset-50{margin-left:50%}.row .column.column-offset-66,.row .column.column-offset-67{margin-left:66.6666%}.row .column.column-offset-75{margin-left:75%}.row .column.column-offset-80{margin-left:80%}.row .column.column-offset-90{margin-left:90%}.row .column.column-10{flex:0 0 10%;max-width:10%}.row .column.column-20{flex:0 0 20%;max-width:20%}.row .column.column-25{flex:0 0 25%;max-width:25%}.row .column.column-33,.row .column.column-34{flex:0 0 33.3333%;max-width:33.3333%}.row .column.column-40{flex:0 0 40%;max-width:40%}.row .column.column-50{flex:0 0 50%;max-width:50%}.row .column.column-60{flex:0 0 60%;max-width:60%}.row .column.column-66,.row .column.column-67{flex:0 0 66.6666%;max-width:66.6666%}.row .column.column-75{flex:0 0 75%;max-width:75%}.row .column.column-80{flex:0 0 80%;max-width:80%}.row .column.column-90{flex:0 0 90%;max-width:90%}.row .column .column-top{align-self:flex-start}.row .column .column-bottom{align-self:flex-end}.row .column .column-center{-ms-grid-row-align:center;align-self:center}@media (min-width: 40rem){.row{flex-direction:row;margin-left:-1.0rem;width:calc(100% + 2.0rem)}.row .column{margin-bottom:inherit;padding:0 1.0rem}}a{color:#0069d9;text-decoration:none}a:focus,a:hover{color:#606c76}dl,ol,ul{list-style:none;margin-top:0;padding-left:0}dl dl,dl ol,dl ul,ol dl,ol ol,ol ul,ul dl,ul ol,ul ul{font-size:90%;margin:1.5rem 0 1.5rem 3.0rem}ol{list-style:decimal inside}ul{list-style:circle inside}.button,button,dd,dt,li{margin-bottom:1.0rem}fieldset,input,select,textarea{margin-bottom:1.5rem}blockquote,dl,figure,form,ol,p,pre,table,ul{margin-bottom:2.5rem}table{border-spacing:0;width:100%}td,th{border-bottom:0.1rem solid #e1e1e1;padding:1.2rem 1.5rem;text-align:left}td:first-child,th:first-child{padding-left:0}td:last-child,th:last-child{padding-right:0}b,strong{font-weight:bold}p{margin-top:0}h1,h2,h3,h4,h5,h6{font-weight:300;letter-spacing:-.1rem;margin-bottom:2.0rem;margin-top:0}h1{font-size:4.6rem;line-height:1.2}h2{font-size:3.6rem;line-height:1.25}h3{font-size:2.8rem;line-height:1.3}h4{font-size:2.2rem;letter-spacing:-.08rem;line-height:1.35}h5{font-size:1.8rem;letter-spacing:-.05rem;line-height:1.5}h6{font-size:1.6rem;letter-spacing:0;line-height:1.4}img{max-width:100%}.clearfix:after{clear:both;content:' ';display:table}.float-left{float:left}.float-right{float:right}
10 |
11 | /* General style */
12 | h1{font-size: 3.6rem; line-height: 1.25}
13 | h2{font-size: 2.8rem; line-height: 1.3}
14 | h3{font-size: 2.2rem; letter-spacing: -.08rem; line-height: 1.35}
15 | h4{font-size: 1.8rem; letter-spacing: -.05rem; line-height: 1.5}
16 | h5{font-size: 1.6rem; letter-spacing: 0; line-height: 1.4}
17 | h6{font-size: 1.4rem; letter-spacing: 0; line-height: 1.2}
18 |
19 | .container{
20 | margin: 0 auto;
21 | max-width: 80.0rem;
22 | padding: 0 2.0rem;
23 | position: relative;
24 | width: 100%
25 | }
26 | select {
27 | width: auto;
28 | }
29 |
30 | /* Alerts and form errors */
31 | .alert {
32 | padding: 15px;
33 | margin-bottom: 20px;
34 | border: 1px solid transparent;
35 | border-radius: 4px;
36 | }
37 | .alert-info {
38 | color: #31708f;
39 | background-color: #d9edf7;
40 | border-color: #bce8f1;
41 | }
42 | .alert-warning {
43 | color: #8a6d3b;
44 | background-color: #fcf8e3;
45 | border-color: #faebcc;
46 | }
47 | .alert-danger {
48 | color: #a94442;
49 | background-color: #f2dede;
50 | border-color: #ebccd1;
51 | }
52 | .alert p {
53 | margin-bottom: 0;
54 | }
55 | .alert:empty {
56 | display: none;
57 | }
58 | .help-block {
59 | color: #a94442;
60 | display: block;
61 | margin: -1rem 0 2rem;
62 | }
63 |
64 | /* Phoenix promo and logo */
65 | .phx-hero {
66 | text-align: center;
67 | border-bottom: 1px solid #e3e3e3;
68 | background: #eee;
69 | border-radius: 6px;
70 | padding: 3em;
71 | margin-bottom: 3rem;
72 | font-weight: 200;
73 | font-size: 120%;
74 | }
75 | .phx-hero p {
76 | margin: 0;
77 | }
78 | .phx-logo {
79 | min-width: 300px;
80 | margin: 1rem;
81 | display: block;
82 | }
83 | .phx-logo img {
84 | width: auto;
85 | display: block;
86 | }
87 |
88 | /* Headers */
89 | header {
90 | width: 100%;
91 | background: #fdfdfd;
92 | border-bottom: 1px solid #eaeaea;
93 | margin-bottom: 2rem;
94 | }
95 | header section {
96 | align-items: center;
97 | display: flex;
98 | flex-direction: column;
99 | justify-content: space-between;
100 | }
101 | header section :first-child {
102 | order: 2;
103 | }
104 | header section :last-child {
105 | order: 1;
106 | }
107 | header nav ul,
108 | header nav li {
109 | margin: 0;
110 | padding: 0;
111 | display: block;
112 | text-align: right;
113 | white-space: nowrap;
114 | }
115 | header nav ul {
116 | margin: 1rem;
117 | margin-top: 0;
118 | }
119 | header nav a {
120 | display: block;
121 | }
122 |
123 | @media (min-width: 40.0rem) { /* Small devices (landscape phones, 576px and up) */
124 | header section {
125 | flex-direction: row;
126 | }
127 | header nav ul {
128 | margin: 1rem;
129 | }
130 | .phx-logo {
131 | flex-basis: 527px;
132 | margin: 2rem 1rem;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/demo/assets/js/app.js:
--------------------------------------------------------------------------------
1 | // We need to import the CSS so that webpack will load it.
2 | // The MiniCssExtractPlugin is used to separate it out into
3 | // its own CSS file.
4 | import css from '../css/app.scss'
5 |
6 | // webpack automatically bundles all modules in your
7 | // entry points. Those entry points can be configured
8 | // in "webpack.config.js".
9 | //
10 | // Import dependencies
11 | //
12 | import 'phoenix_html'
13 |
14 | // Import local files
15 | //
16 | // Local files can be imported directly using relative paths, for example:
17 | import React from 'react'
18 | import ReactDOM from 'react-dom'
19 | import {init} from '@glue/core'
20 | import Counter from './components/Counter'
21 | import Value from './components/Value'
22 | import Dictionary from './components/Dictionary'
23 | import ArrayComponent from './components/Array'
24 |
25 | const apps = {
26 | "counter-app": Counter,
27 | "read-only-app": Value,
28 | "array-app": ArrayComponent,
29 | "dictionary-app": Dictionary
30 | }
31 |
32 | init()
33 | .then(() => {
34 | Object.entries(apps).forEach(([id, Component]) => {
35 | const element = document.getElementById(id)
36 |
37 | if (element) {
38 | ReactDOM.render(, element)
39 | }
40 | })
41 | })
42 | .catch(error => console.log('Unable to join', error))
43 |
--------------------------------------------------------------------------------
/demo/assets/js/components/Array.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {useServerState} from '@glue/react'
3 |
4 | const Item = ({value, onRemove}) => {
5 | const confirmRemove = () => {
6 | if (confirm(`Are you sure you want to remove ${value}?`)) {
7 | onRemove()
8 | }
9 | }
10 |
11 | return (
12 |
13 | {value} |
14 | |
15 |
16 | )
17 | }
18 |
19 | const Items = ({array, onDelete}) => {
20 | return array.map((value, index) =>
21 | - onDelete(index)}/>
22 | )
23 | }
24 |
25 | const AddForm = () => {
26 | return (
27 |
28 | |
29 | |
30 |
31 | )
32 | }
33 |
34 | export default function() {
35 | const {array, push, del, clear} = useServerState('array', {sync: true})
36 | const submit = (e) => {
37 | e.preventDefault()
38 |
39 | const form = e.target
40 | const elements = form.elements
41 |
42 | push(elements.value.value)
43 |
44 | form.reset()
45 | elements.value.focus()
46 | }
47 |
48 | return (
49 |
50 |
66 |
67 | {array.length > 0 &&
clear()}>clear}
68 |
69 |
{JSON.stringify(array, null, 2)}
70 |
71 | )
72 | }
73 |
--------------------------------------------------------------------------------
/demo/assets/js/components/Counter.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {useServerState} from '@glue/react'
3 |
4 | function randomNumber() {
5 | return Math.floor(Math.random()*100)
6 | }
7 |
8 | export default function() {
9 | const {count, increment, decrement, update} = useServerState('counter', {sync: true})
10 |
11 | return (
12 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/demo/assets/js/components/Dictionary.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {useServerState} from '@glue/react'
3 |
4 | const Pair = ({id, value, onRemove}) => {
5 | const confirmRemove = () => {
6 | if (confirm(`Are you sure you want to remove ${id}?`)) {
7 | onRemove()
8 | }
9 | }
10 |
11 | return (
12 |
13 | {id} |
14 | {value} |
15 | |
16 |
17 | )
18 | }
19 |
20 | const Pairs = ({pairs, onDelete}) => {
21 | return pairs.map(([key, value]) =>
22 | onDelete(key)}/>
23 | )
24 | }
25 |
26 | const AddForm = () => {
27 | return (
28 |
29 | |
30 | |
31 | |
32 |
33 | )
34 | }
35 |
36 | export default function() {
37 | const {value, put, del, clear} = useServerState('dictionary', {sync: true})
38 | const pairs = Object.entries(value)
39 | const submit = (e) => {
40 | e.preventDefault()
41 |
42 | const form = e.target
43 | const elements = form.elements
44 |
45 | put(elements.key.value, elements.value.value)
46 |
47 | form.reset()
48 | elements.key.focus()
49 | }
50 |
51 |
52 | return (
53 |
54 |
71 |
72 | {pairs.length > 0 &&
clear()}>clear}
73 |
74 |
{JSON.stringify(value, null, 2)}
75 |
76 | )
77 | }
78 |
--------------------------------------------------------------------------------
/demo/assets/js/components/Value.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {useServerState} from '@glue/react'
3 |
4 | export default function() {
5 | const {value} = useServerState('random')
6 |
7 | return {value}
8 | }
9 |
--------------------------------------------------------------------------------
/demo/assets/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "repository": {},
3 | "license": "MIT",
4 | "scripts": {
5 | "deploy": "webpack --mode production",
6 | "watch": "webpack --mode development --watch"
7 | },
8 | "dependencies": {
9 | "@babel/plugin-transform-runtime": "^7.5.5",
10 | "@babel/runtime": "^7.5.5",
11 | "@glue/core": "file:../../packages/core",
12 | "@glue/react": "file:../../packages/react",
13 | "font-awesome": "^4.7.0",
14 | "js-yaml": "^3.13.1",
15 | "mem": "5.1.1",
16 | "phoenix": "file:../deps/phoenix",
17 | "phoenix_html": "file:../deps/phoenix_html"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.5.5",
21 | "@babel/preset-env": "^7.5.5",
22 | "@babel/preset-react": "^7.0.0",
23 | "babel-loader": "^8.0.6",
24 | "copy-webpack-plugin": "^5.0.4",
25 | "css-loader": "^3.2.0",
26 | "file-loader": "^4.2.0",
27 | "mini-css-extract-plugin": "^0.8.0",
28 | "optimize-css-assets-webpack-plugin": "^5.0.3",
29 | "postcss-import": "^12.0.1",
30 | "postcss-loader": "^3.0.0",
31 | "react": "^16.9.0",
32 | "react-dom": "^16.9.0",
33 | "sass": "^1.22.10",
34 | "sass-loader": "^7.3.1",
35 | "tailwindcss": "^1.1.2",
36 | "uglifyjs-webpack-plugin": "^2.2.0",
37 | "webpack": "4.39.2",
38 | "webpack-cli": "^3.3.7"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/demo/assets/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshnuss/glue/d8d406e34c68d4f8f520a9b81b6774cdd838e0dc/demo/assets/static/favicon.ico
--------------------------------------------------------------------------------
/demo/assets/static/images/phoenix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joshnuss/glue/d8d406e34c68d4f8f520a9b81b6774cdd838e0dc/demo/assets/static/images/phoenix.png
--------------------------------------------------------------------------------
/demo/assets/static/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/demo/assets/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | theme: {
3 | extend: {}
4 | },
5 | variants: {},
6 | plugins: []
7 | }
8 |
--------------------------------------------------------------------------------
/demo/assets/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const glob = require('glob');
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
4 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
5 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
6 | const CopyWebpackPlugin = require('copy-webpack-plugin');
7 |
8 | module.exports = (env, options) => ({
9 | optimization: {
10 | minimizer: [
11 | new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
12 | new OptimizeCSSAssetsPlugin({})
13 | ]
14 | },
15 | entry: {
16 | './js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
17 | },
18 | output: {
19 | filename: 'app.js',
20 | path: path.resolve(__dirname, '../priv/static/js')
21 | },
22 | module: {
23 | rules: [
24 | {
25 | test: /\.js$/,
26 | exclude: /node_modules/,
27 | use: {
28 | loader: 'babel-loader'
29 | }
30 | },
31 | {
32 | test: /\.css$/,
33 | use: [MiniCssExtractPlugin.loader, 'css-loader']
34 | },
35 | {
36 | test: /\.s[ac]ss$/i,
37 | use: [
38 | MiniCssExtractPlugin.loader,
39 | 'css-loader',
40 | 'sass-loader',
41 | {
42 | loader: 'postcss-loader',
43 | options: {
44 | ident: 'postcss',
45 | plugins: [
46 | require('postcss-import'),
47 | require('tailwindcss'),
48 | require('autoprefixer'),
49 | ],
50 | },
51 | },
52 | ],
53 | },
54 | {
55 | test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
56 | use: [
57 | {
58 | loader: 'file-loader',
59 | options: {
60 | name: '[name].[ext]',
61 | outputPath: '../fonts'
62 | }
63 | }
64 | ]
65 | }
66 | ]
67 | },
68 | plugins: [
69 | new MiniCssExtractPlugin({ filename: '../css/app.css' }),
70 | new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
71 | ]
72 | });
73 |
--------------------------------------------------------------------------------
/demo/config/config.exs:
--------------------------------------------------------------------------------
1 | # This file is responsible for configuring your application
2 | # and its dependencies with the aid of the Mix.Config module.
3 | #
4 | # This configuration file is loaded before any dependency and
5 | # is restricted to this project.
6 |
7 | # General application configuration
8 | use Mix.Config
9 |
10 | # Configures the endpoint
11 | config :demo, DemoWeb.Endpoint,
12 | url: [host: "localhost"],
13 | secret_key_base: "6rIwsZ0cDNSH9UOkP4oJ9Xv4cuHxKg6N1Cymoqzo5iWUEGxwQVJGyHWENCt3EMgY",
14 | render_errors: [view: DemoWeb.ErrorView, accepts: ~w(html json)],
15 | pubsub: [name: Demo.PubSub, adapter: Phoenix.PubSub.PG2]
16 |
17 | # Configures Elixir's Logger
18 | config :logger, :console,
19 | format: "$time $metadata[$level] $message\n",
20 | metadata: [:request_id]
21 |
22 | # Use Jason for JSON parsing in Phoenix
23 | config :phoenix, :json_library, Jason
24 |
25 | import_config "hooks.exs"
26 | # Import environment specific config. This must remain at the bottom
27 | # of this file so it overrides the configuration defined above.
28 | import_config "#{Mix.env()}.exs"
29 |
--------------------------------------------------------------------------------
/demo/config/dev.exs:
--------------------------------------------------------------------------------
1 | use Mix.Config
2 |
3 | # For development, we disable any cache and enable
4 | # debugging and code reloading.
5 | #
6 | # The watchers configuration can be used to run external
7 | # watchers to your application. For example, we use it
8 | # with webpack to recompile .js and .css sources.
9 | config :demo, DemoWeb.Endpoint,
10 | http: [port: 4000],
11 | debug_errors: true,
12 | code_reloader: true,
13 | check_origin: false,
14 | watchers: [
15 | node: [
16 | "node_modules/webpack/bin/webpack.js",
17 | "--mode",
18 | "development",
19 | "--watch-stdin",
20 | cd: Path.expand("../assets", __DIR__)
21 | ]
22 | ]
23 |
24 | # ## SSL Support
25 | #
26 | # In order to use HTTPS in development, a self-signed
27 | # certificate can be generated by running the following
28 | # Mix task:
29 | #
30 | # mix phx.gen.cert
31 | #
32 | # Note that this task requires Erlang/OTP 20 or later.
33 | # Run `mix help phx.gen.cert` for more information.
34 | #
35 | # The `http:` config above can be replaced with:
36 | #
37 | # https: [
38 | # port: 4001,
39 | # cipher_suite: :strong,
40 | # keyfile: "priv/cert/selfsigned_key.pem",
41 | # certfile: "priv/cert/selfsigned.pem"
42 | # ],
43 | #
44 | # If desired, both `http:` and `https:` keys can be
45 | # configured to run both http and https servers on
46 | # different ports.
47 |
48 | # Watch static and templates for browser reloading.
49 | config :demo, DemoWeb.Endpoint,
50 | live_reload: [
51 | patterns: [
52 | ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
53 | ~r"priv/gettext/.*(po)$",
54 | ~r"lib/demo_web/{live,views}/.*(ex)$",
55 | ~r"lib/demo_web/templates/.*(eex)$"
56 | ]
57 | ]
58 |
59 | # Do not include metadata nor timestamps in development logs
60 | config :logger, :console, format: "[$level] $message\n"
61 |
62 | # Set a higher stacktrace during development. Avoid configuring such
63 | # in production as building large stacktraces may be expensive.
64 | config :phoenix, :stacktrace_depth, 20
65 |
66 | # Initialize plugs at runtime for faster development compilation
67 | config :phoenix, :plug_init_mode, :runtime
68 |
--------------------------------------------------------------------------------
/demo/config/hooks.exs:
--------------------------------------------------------------------------------
1 | use Mix.Config
2 |
3 | config :demo, :hooks, %{
4 | random: %{
5 | mod: Demo.Random,
6 | access: %{
7 | action: :value
8 | }
9 | },
10 | counter: %{
11 | mod: Demo.Counter,
12 | access: %{
13 | action: :get,
14 | label: :count,
15 | default: "..."
16 | },
17 | calls: [:increment, :decrement, :update]
18 | },
19 | array: %{
20 | mod: Demo.Array,
21 | access: %{
22 | action: :value,
23 | label: :array,
24 | default: []
25 | },
26 | calls: [:push, :get, :del, :clear]
27 | },
28 | dictionary: %{
29 | mod: Demo.Dictionary,
30 | access: %{
31 | action: :value,
32 | default: %{}
33 | },
34 | calls: [:put, :get, :del, :clear]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/demo/config/prod.exs:
--------------------------------------------------------------------------------
1 | use Mix.Config
2 |
3 | # For production, don't forget to configure the url host
4 | # to something meaningful, Phoenix uses this information
5 | # when generating URLs.
6 | #
7 | # Note we also include the path to a cache manifest
8 | # containing the digested version of static files. This
9 | # manifest is generated by the `mix phx.digest` task,
10 | # which you should run after static files are built and
11 | # before starting your production server.
12 | config :demo, DemoWeb.Endpoint,
13 | url: [host: "react-use-server-state.gigalixirapp.com", port: 4000],
14 | cache_static_manifest: "priv/static/cache_manifest.json"
15 |
16 | # Do not print debug messages in production
17 | config :logger, level: :info
18 |
19 | # ## SSL Support
20 | #
21 | # To get SSL working, you will need to add the `https` key
22 | # to the previous section and set your `:url` port to 443:
23 | #
24 | # config :demo, DemoWeb.Endpoint,
25 | # ...
26 | # url: [host: "example.com", port: 443],
27 | # https: [
28 | # :inet6,
29 | # port: 443,
30 | # cipher_suite: :strong,
31 | # keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
32 | # certfile: System.get_env("SOME_APP_SSL_CERT_PATH")
33 | # ]
34 | #
35 | # The `cipher_suite` is set to `:strong` to support only the
36 | # latest and more secure SSL ciphers. This means old browsers
37 | # and clients may not be supported. You can set it to
38 | # `:compatible` for wider support.
39 | #
40 | # `:keyfile` and `:certfile` expect an absolute path to the key
41 | # and cert in disk or a relative path inside priv, for example
42 | # "priv/ssl/server.key". For all supported SSL configuration
43 | # options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1
44 | #
45 | # We also recommend setting `force_ssl` in your endpoint, ensuring
46 | # no data is ever sent via http, always redirecting to https:
47 | #
48 | # config :demo, DemoWeb.Endpoint,
49 | # force_ssl: [hsts: true]
50 | #
51 | # Check `Plug.SSL` for all available options in `force_ssl`.
52 |
53 | # Finally import the config/prod.secret.exs which loads secrets
54 | # and configuration from environment variables.
55 | import_config "prod.secret.exs"
56 |
--------------------------------------------------------------------------------
/demo/config/prod.secret.exs:
--------------------------------------------------------------------------------
1 | # In this file, we load production configuration and secrets
2 | # from environment variables. You can also hardcode secrets,
3 | # although such is generally not recommended and you have to
4 | # remember to add this file to your .gitignore.
5 | use Mix.Config
6 |
7 | secret_key_base =
8 | System.get_env("SECRET_KEY_BASE") ||
9 | raise """
10 | environment variable SECRET_KEY_BASE is missing.
11 | You can generate one by calling: mix phx.gen.secret
12 | """
13 |
14 | config :demo, DemoWeb.Endpoint,
15 | http: [:inet6, port: String.to_integer(System.get_env("PORT") || "4000")],
16 | secret_key_base: secret_key_base
17 |
18 | # ## Using releases (Elixir v1.9+)
19 | #
20 | # If you are doing OTP releases, you need to instruct Phoenix
21 | # to start each relevant endpoint:
22 | #
23 | # config :demo, DemoWeb.Endpoint, server: true
24 | #
25 | # Then you can assemble a release by calling `mix release`.
26 | # See `mix help release` for more information.
27 |
--------------------------------------------------------------------------------
/demo/config/test.exs:
--------------------------------------------------------------------------------
1 | use Mix.Config
2 |
3 | # We don't run a server during test. If one is required,
4 | # you can enable the server option below.
5 | config :demo, DemoWeb.Endpoint,
6 | http: [port: 4002],
7 | server: false
8 |
9 | # Print only warnings and errors during test
10 | config :logger, level: :warn
11 |
--------------------------------------------------------------------------------
/demo/lib/demo.ex:
--------------------------------------------------------------------------------
1 | defmodule Demo do
2 | @moduledoc """
3 | Demo keeps the contexts that define your domain
4 | and business logic.
5 |
6 | Contexts are also responsible for managing your data, regardless
7 | if it comes from the database, an external API or others.
8 | """
9 | end
10 |
--------------------------------------------------------------------------------
/demo/lib/demo/application.ex:
--------------------------------------------------------------------------------
1 | defmodule Demo.Application do
2 | # See https://hexdocs.pm/elixir/Application.html
3 | # for more information on OTP Applications
4 | @moduledoc false
5 |
6 | use Application
7 |
8 | def start(_type, _args) do
9 | # List all child processes to be supervised
10 | children = [
11 | # Start the endpoint when the application starts
12 | DemoWeb.Endpoint,
13 | Demo.Counter,
14 | Demo.Array,
15 | Demo.Dictionary
16 | ]
17 |
18 | # See https://hexdocs.pm/elixir/Supervisor.html
19 | # for other strategies and supported options
20 | opts = [strategy: :one_for_one, name: Demo.Supervisor]
21 | Supervisor.start_link(children, opts)
22 | end
23 |
24 | # Tell Phoenix to update the endpoint configuration
25 | # whenever the application is updated.
26 | def config_change(changed, _new, removed) do
27 | DemoWeb.Endpoint.config_change(changed, removed)
28 | :ok
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/demo/lib/demo/array.ex:
--------------------------------------------------------------------------------
1 | defmodule Demo.Array do
2 | use Agent
3 |
4 | @name __MODULE__
5 |
6 | def start_link(_opts) do
7 | Agent.start_link(fn -> [] end, name: @name)
8 | end
9 |
10 | def value, do: Agent.get(@name, & &1)
11 |
12 | def push(item) do
13 | Agent.get_and_update(@name, fn state ->
14 | new_state = [item | state]
15 | {new_state, new_state}
16 | end)
17 | end
18 |
19 | def get(index) do
20 | Agent.get(@name, fn state ->
21 | value = Enum.at(state, index)
22 |
23 | {:ok, value, state}
24 | end)
25 | end
26 |
27 | def del(index) do
28 | Agent.get_and_update(@name, fn state ->
29 | new_state = List.delete_at(state, index)
30 | {new_state, new_state}
31 | end)
32 | end
33 |
34 | def clear() do
35 | Agent.update(@name, fn _ -> [] end)
36 | []
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/demo/lib/demo/counter.ex:
--------------------------------------------------------------------------------
1 | defmodule Demo.Counter do
2 | use Agent
3 |
4 | @name __MODULE__
5 |
6 | def start_link(_opts) do
7 | Agent.start_link(fn -> 0 end, name: @name)
8 | end
9 |
10 | def get, do: Agent.get(@name, & &1)
11 | def increment, do: change(&(&1 + 1))
12 | def decrement, do: change(&(&1 - 1))
13 | def update(value), do: change(fn _ -> value end)
14 |
15 | defp change(fun) do
16 | Agent.get_and_update(@name, &{fun.(&1), fun.(&1)})
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/demo/lib/demo/dictionary.ex:
--------------------------------------------------------------------------------
1 | defmodule Demo.Dictionary do
2 | use Agent
3 |
4 | @name __MODULE__
5 |
6 | def start_link(_opts) do
7 | Agent.start_link(fn -> %{} end, name: @name)
8 | end
9 |
10 | def value, do: Agent.get(@name, & &1)
11 |
12 | def put(key, value) do
13 | Agent.get_and_update(@name, fn state ->
14 | new_state = Map.put(state, key, value)
15 | {new_state, new_state}
16 | end)
17 | end
18 |
19 | def get(key) do
20 | Agent.get(@name, fn state ->
21 | value = Map.get(state, key)
22 |
23 | {:ok, value, state}
24 | end)
25 | end
26 |
27 | def del(key) do
28 | Agent.get_and_update(@name, fn state ->
29 | new_state = Map.delete(state, key)
30 | {new_state, new_state}
31 | end)
32 | end
33 |
34 | def clear() do
35 | Agent.update(@name, fn _ -> %{} end)
36 | %{}
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/demo/lib/demo/random.ex:
--------------------------------------------------------------------------------
1 | defmodule Demo.Random do
2 | def value, do: :rand.uniform(1000)
3 | end
4 |
--------------------------------------------------------------------------------
/demo/lib/demo_web.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb do
2 | @moduledoc """
3 | The entrypoint for defining your web interface, such
4 | as controllers, views, channels and so on.
5 |
6 | This can be used in your application as:
7 |
8 | use DemoWeb, :controller
9 | use DemoWeb, :view
10 |
11 | The definitions below will be executed for every view,
12 | controller, etc, so keep them short and clean, focused
13 | on imports, uses and aliases.
14 |
15 | Do NOT define functions inside the quoted expressions
16 | below. Instead, define any helper function in modules
17 | and import those modules here.
18 | """
19 |
20 | def controller do
21 | quote do
22 | use Phoenix.Controller, namespace: DemoWeb
23 |
24 | import Plug.Conn
25 | import DemoWeb.Gettext
26 | alias DemoWeb.Router.Helpers, as: Routes
27 | end
28 | end
29 |
30 | def view do
31 | quote do
32 | use Phoenix.View,
33 | root: "lib/demo_web/templates",
34 | namespace: DemoWeb
35 |
36 | # Import convenience functions from controllers
37 | import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
38 |
39 | # Use all HTML functionality (forms, tags, etc)
40 | use Phoenix.HTML
41 |
42 | import DemoWeb.ErrorHelpers
43 | import DemoWeb.Gettext
44 | alias DemoWeb.Router.Helpers, as: Routes
45 | end
46 | end
47 |
48 | def router do
49 | quote do
50 | use Phoenix.Router
51 | import Plug.Conn
52 | import Phoenix.Controller
53 | end
54 | end
55 |
56 | def channel do
57 | quote do
58 | use Phoenix.Channel
59 | import DemoWeb.Gettext
60 | end
61 | end
62 |
63 | @doc """
64 | When used, dispatch to the appropriate controller/view/etc.
65 | """
66 | defmacro __using__(which) when is_atom(which) do
67 | apply(__MODULE__, which, [])
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/channels/hook_channel.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.HookChannel do
2 | use DemoWeb, :channel
3 | import Glue.Generator
4 |
5 | def join("hook:lobby", payload, socket) do
6 | if authorized?(payload) do
7 | {:ok, socket}
8 | else
9 | {:error, %{reason: "unauthorized"}}
10 | end
11 | end
12 |
13 | generate_hooks(:demo)
14 |
15 | # Add authorization logic here as required.
16 | defp authorized?(_payload) do
17 | true
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/channels/user_socket.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.UserSocket do
2 | use Phoenix.Socket
3 |
4 | ## Channels
5 | # channel "room:*", DemoWeb.RoomChannel
6 | channel "hook:*", DemoWeb.HookChannel
7 |
8 | # Socket params are passed from the client and can
9 | # be used to verify and authenticate a user. After
10 | # verification, you can put default assigns into
11 | # the socket that will be set for all channels, ie
12 | #
13 | # {:ok, assign(socket, :user_id, verified_user_id)}
14 | #
15 | # To deny connection, return `:error`.
16 | #
17 | # See `Phoenix.Token` documentation for examples in
18 | # performing token verification on connect.
19 | def connect(_params, socket, _connect_info) do
20 | {:ok, socket}
21 | end
22 |
23 | # Socket id's are topics that allow you to identify all sockets for a given user:
24 | #
25 | # def id(socket), do: "user_socket:#{socket.assigns.user_id}"
26 | #
27 | # Would allow you to broadcast a "disconnect" event and terminate
28 | # all active sockets and channels for a given user:
29 | #
30 | # DemoWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
31 | #
32 | # Returning `nil` makes this socket anonymous.
33 | def id(_socket), do: nil
34 | end
35 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/controllers/demo_controller.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.DemoController do
2 | use DemoWeb, :controller
3 |
4 | def show(conn, params) do
5 | render(conn, "#{params["id"]}.html")
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/controllers/page_controller.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.PageController do
2 | use DemoWeb, :controller
3 |
4 | def index(conn, _params) do
5 | render(conn, "index.html")
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/endpoint.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.Endpoint do
2 | use Phoenix.Endpoint, otp_app: :demo
3 |
4 | socket "/socket", DemoWeb.UserSocket,
5 | websocket: true,
6 | longpoll: false
7 |
8 | # Serve at "/" the static files from "priv/static" directory.
9 | #
10 | # You should set gzip to true if you are running phx.digest
11 | # when deploying your static files in production.
12 | plug Plug.Static,
13 | at: "/",
14 | from: :demo,
15 | gzip: false,
16 | only: ~w(css fonts images js favicon.ico robots.txt)
17 |
18 | # Code reloading can be explicitly enabled under the
19 | # :code_reloader configuration of your endpoint.
20 | if code_reloading? do
21 | socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
22 | plug Phoenix.LiveReloader
23 | plug Phoenix.CodeReloader
24 | end
25 |
26 | plug Plug.RequestId
27 | plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
28 |
29 | plug Plug.Parsers,
30 | parsers: [:urlencoded, :multipart, :json],
31 | pass: ["*/*"],
32 | json_decoder: Phoenix.json_library()
33 |
34 | plug Plug.MethodOverride
35 | plug Plug.Head
36 |
37 | # The session will be stored in the cookie and signed,
38 | # this means its contents can be read but not tampered with.
39 | # Set :encryption_salt if you would also like to encrypt it.
40 | plug Plug.Session,
41 | store: :cookie,
42 | key: "_demo_key",
43 | signing_salt: "fGL1bCE3"
44 |
45 | plug DemoWeb.Router
46 | end
47 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/gettext.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.Gettext do
2 | @moduledoc """
3 | A module providing Internationalization with a gettext-based API.
4 |
5 | By using [Gettext](https://hexdocs.pm/gettext),
6 | your module gains a set of macros for translations, for example:
7 |
8 | import DemoWeb.Gettext
9 |
10 | # Simple translation
11 | gettext("Here is the string to translate")
12 |
13 | # Plural translation
14 | ngettext("Here is the string to translate",
15 | "Here are the strings to translate",
16 | 3)
17 |
18 | # Domain-based translation
19 | dgettext("errors", "Here is the error message to translate")
20 |
21 | See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
22 | """
23 | use Gettext, otp_app: :demo
24 | end
25 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/router.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.Router do
2 | use DemoWeb, :router
3 |
4 | pipeline :browser do
5 | plug :accepts, ["html"]
6 | plug :fetch_session
7 | plug :fetch_flash
8 | plug :protect_from_forgery
9 | plug :put_secure_browser_headers
10 | end
11 |
12 | pipeline :api do
13 | plug :accepts, ["json"]
14 | end
15 |
16 | scope "/", DemoWeb do
17 | pipe_through :browser
18 |
19 | get "/", PageController, :index
20 | get "/demos/:id", DemoController, :show
21 | end
22 |
23 | # Other scopes may use custom stacks.
24 | # scope "/api", DemoWeb do
25 | # pipe_through :api
26 | # end
27 | end
28 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/demo/array.html.eex:
--------------------------------------------------------------------------------
1 | Array Demo
2 |
3 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/demo/counter.html.eex:
--------------------------------------------------------------------------------
1 | Counter Demo
2 |
3 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/demo/dictionary.html.eex:
--------------------------------------------------------------------------------
1 | Dictionary Demo
2 |
3 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/demo/read-only.html.eex:
--------------------------------------------------------------------------------
1 | Read-only Demo
2 |
3 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/layout/analytics.html.eex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/layout/app.html.eex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | useServerState() · Phoenix Framework
8 | "/>
9 |
10 |
11 |
12 |
19 |
20 | <%= get_flash(@conn, :info) %>
21 | <%= get_flash(@conn, :error) %>
22 | <%= render @view_module, @view_template, assigns %>
23 |
24 |
25 | <%= render "analytics.html" %>
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/templates/page/index.html.eex:
--------------------------------------------------------------------------------
1 |
2 | Demos
3 |
9 |
10 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/views/demo_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.DemoView do
2 | use DemoWeb, :view
3 | end
4 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/views/error_helpers.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ErrorHelpers do
2 | @moduledoc """
3 | Conveniences for translating and building error messages.
4 | """
5 |
6 | use Phoenix.HTML
7 |
8 | @doc """
9 | Generates tag for inlined form input errors.
10 | """
11 | def error_tag(form, field) do
12 | Enum.map(Keyword.get_values(form.errors, field), fn error ->
13 | content_tag(:span, translate_error(error), class: "help-block")
14 | end)
15 | end
16 |
17 | @doc """
18 | Translates an error message using gettext.
19 | """
20 | def translate_error({msg, opts}) do
21 | # When using gettext, we typically pass the strings we want
22 | # to translate as a static argument:
23 | #
24 | # # Translate "is invalid" in the "errors" domain
25 | # dgettext("errors", "is invalid")
26 | #
27 | # # Translate the number of files with plural rules
28 | # dngettext("errors", "1 file", "%{count} files", count)
29 | #
30 | # Because the error messages we show in our forms and APIs
31 | # are defined inside Ecto, we need to translate them dynamically.
32 | # This requires us to call the Gettext module passing our gettext
33 | # backend as first argument.
34 | #
35 | # Note we use the "errors" domain, which means translations
36 | # should be written to the errors.po file. The :count option is
37 | # set by Ecto and indicates we should also apply plural rules.
38 | if count = opts[:count] do
39 | Gettext.dngettext(DemoWeb.Gettext, "errors", msg, msg, count, opts)
40 | else
41 | Gettext.dgettext(DemoWeb.Gettext, "errors", msg, opts)
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/views/error_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ErrorView do
2 | use DemoWeb, :view
3 |
4 | # If you want to customize a particular status code
5 | # for a certain format, you may uncomment below.
6 | # def render("500.html", _assigns) do
7 | # "Internal Server Error"
8 | # end
9 |
10 | # By default, Phoenix returns the status message from
11 | # the template name. For example, "404.html" becomes
12 | # "Not Found".
13 | def template_not_found(template, _assigns) do
14 | Phoenix.Controller.status_message_from_template(template)
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/views/layout_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.LayoutView do
2 | use DemoWeb, :view
3 | end
4 |
--------------------------------------------------------------------------------
/demo/lib/demo_web/views/page_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.PageView do
2 | use DemoWeb, :view
3 | end
4 |
--------------------------------------------------------------------------------
/demo/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule Demo.MixProject do
2 | use Mix.Project
3 |
4 | def project do
5 | [
6 | app: :demo,
7 | version: "0.1.0",
8 | elixir: "~> 1.5",
9 | elixirc_paths: elixirc_paths(Mix.env()),
10 | compilers: [:phoenix, :gettext] ++ Mix.compilers(),
11 | start_permanent: Mix.env() == :prod,
12 | deps: deps()
13 | ]
14 | end
15 |
16 | # Configuration for the OTP application.
17 | #
18 | # Type `mix help compile.app` for more information.
19 | def application do
20 | [
21 | mod: {Demo.Application, []},
22 | extra_applications: [:logger, :runtime_tools]
23 | ]
24 | end
25 |
26 | # Specifies which paths to compile per environment.
27 | defp elixirc_paths(:test), do: ["lib", "test/support"]
28 | defp elixirc_paths(_), do: ["lib"]
29 |
30 | # Specifies your project dependencies.
31 | #
32 | # Type `mix help deps` for examples and options.
33 | defp deps do
34 | [
35 | {:phoenix, "~> 1.4.9"},
36 | {:phoenix_pubsub, "~> 1.1"},
37 | {:phoenix_html, "~> 2.11"},
38 | {:phoenix_live_reload, "~> 1.2", only: :dev},
39 | {:gettext, "~> 0.11"},
40 | {:jason, "~> 1.0"},
41 | {:plug_cowboy, "~> 2.0"},
42 | {:glue, path: "../glue"}
43 | ]
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/demo/mix.lock:
--------------------------------------------------------------------------------
1 | %{
2 | "cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
3 | "cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm"},
4 | "file_system": {:hex, :file_system, "0.2.7", "e6f7f155970975789f26e77b8b8d8ab084c59844d8ecfaf58cbda31c494d14aa", [:mix], [], "hexpm"},
5 | "gettext": {:hex, :gettext, "0.17.0", "abe21542c831887a2b16f4c94556db9c421ab301aee417b7c4fbde7fbdbe01ec", [:mix], [], "hexpm"},
6 | "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
7 | "mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
8 | "phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
9 | "phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
10 | "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.1", "274a4b07c4adbdd7785d45a8b0bb57634d0b4f45b18d2c508b26c0344bd59b8f", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
11 | "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
12 | "plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
13 | "plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
14 | "plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
15 | "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
16 | "telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
17 | }
18 |
--------------------------------------------------------------------------------
/demo/priv/gettext/en/LC_MESSAGES/errors.po:
--------------------------------------------------------------------------------
1 | ## `msgid`s in this file come from POT (.pot) files.
2 | ##
3 | ## Do not add, change, or remove `msgid`s manually here as
4 | ## they're tied to the ones in the corresponding POT file
5 | ## (with the same domain).
6 | ##
7 | ## Use `mix gettext.extract --merge` or `mix gettext.merge`
8 | ## to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: en\n"
12 |
--------------------------------------------------------------------------------
/demo/priv/gettext/errors.pot:
--------------------------------------------------------------------------------
1 | ## This is a PO Template file.
2 | ##
3 | ## `msgid`s here are often extracted from source code.
4 | ## Add new translations manually only if they're dynamic
5 | ## translations that can't be statically extracted.
6 | ##
7 | ## Run `mix gettext.extract` to bring this file up to
8 | ## date. Leave `msgstr`s empty as changing them here has no
9 | ## effect: edit them in PO (`.po`) files instead.
10 |
11 |
--------------------------------------------------------------------------------
/demo/test/demo_web/channels/hook_channel_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.HookChannelTest do
2 | use DemoWeb.ChannelCase
3 |
4 | setup do
5 | {:ok, _, socket} =
6 | socket(DemoWeb.UserSocket, "user_id", %{some: :assign})
7 | |> subscribe_and_join(DemoWeb.HookChannel, "hook:lobby")
8 |
9 | {:ok, socket: socket}
10 | end
11 |
12 | test "ping replies with status ok", %{socket: socket} do
13 | ref = push socket, "ping", %{"hello" => "there"}
14 | assert_reply ref, :ok, %{"hello" => "there"}
15 | end
16 |
17 | test "shout broadcasts to hook:lobby", %{socket: socket} do
18 | push socket, "shout", %{"hello" => "all"}
19 | assert_broadcast "shout", %{"hello" => "all"}
20 | end
21 |
22 | test "broadcasts are pushed to the client", %{socket: socket} do
23 | broadcast_from! socket, "broadcast", %{"some" => "data"}
24 | assert_push "broadcast", %{"some" => "data"}
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/demo/test/demo_web/controllers/page_controller_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.PageControllerTest do
2 | use DemoWeb.ConnCase
3 |
4 | test "GET /", %{conn: conn} do
5 | conn = get(conn, "/")
6 | assert html_response(conn, 200) =~ "Welcome to Phoenix!"
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/demo/test/demo_web/views/error_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ErrorViewTest do
2 | use DemoWeb.ConnCase, async: true
3 |
4 | # Bring render/3 and render_to_string/3 for testing custom views
5 | import Phoenix.View
6 |
7 | test "renders 404.html" do
8 | assert render_to_string(DemoWeb.ErrorView, "404.html", []) == "Not Found"
9 | end
10 |
11 | test "renders 500.html" do
12 | assert render_to_string(DemoWeb.ErrorView, "500.html", []) == "Internal Server Error"
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/demo/test/demo_web/views/layout_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.LayoutViewTest do
2 | use DemoWeb.ConnCase, async: true
3 | end
4 |
--------------------------------------------------------------------------------
/demo/test/demo_web/views/page_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.PageViewTest do
2 | use DemoWeb.ConnCase, async: true
3 | end
4 |
--------------------------------------------------------------------------------
/demo/test/support/channel_case.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ChannelCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | channel tests.
5 |
6 | Such tests rely on `Phoenix.ChannelTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | it cannot be async. For this reason, every test runs
12 | inside a transaction which is reset at the beginning
13 | of the test unless the test case is marked as async.
14 | """
15 |
16 | use ExUnit.CaseTemplate
17 |
18 | using do
19 | quote do
20 | # Import conveniences for testing with channels
21 | use Phoenix.ChannelTest
22 |
23 | # The default endpoint for testing
24 | @endpoint DemoWeb.Endpoint
25 | end
26 | end
27 |
28 | setup _tags do
29 | :ok
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/demo/test/support/conn_case.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ConnCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | tests that require setting up a connection.
5 |
6 | Such tests rely on `Phoenix.ConnTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | it cannot be async. For this reason, every test runs
12 | inside a transaction which is reset at the beginning
13 | of the test unless the test case is marked as async.
14 | """
15 |
16 | use ExUnit.CaseTemplate
17 |
18 | using do
19 | quote do
20 | # Import conveniences for testing with connections
21 | use Phoenix.ConnTest
22 | alias DemoWeb.Router.Helpers, as: Routes
23 |
24 | # The default endpoint for testing
25 | @endpoint DemoWeb.Endpoint
26 | end
27 | end
28 |
29 | setup _tags do
30 | {:ok, conn: Phoenix.ConnTest.build_conn()}
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/demo/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 |
--------------------------------------------------------------------------------
/elixir_buildpack.config:
--------------------------------------------------------------------------------
1 | elixir_version=1.9
2 | erlang_version=21.3
3 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | This folder contains a list of example instructions.
4 |
--------------------------------------------------------------------------------
/examples/minimal.md:
--------------------------------------------------------------------------------
1 | # Minimal Example
2 |
3 | The most basic example is using read-only state.
4 |
5 | ## Server Side
6 |
7 | All you need is a module:
8 |
9 | ```elixir
10 | # in lib/magic.ex
11 | defmodule Magic do
12 | # read-only value
13 | def value, do: 42
14 | end
15 | ```
16 |
17 | Make the hook public:
18 |
19 | ```elixir
20 | # in config/hooks.ex
21 | config :my_app, :hooks, %{
22 | # `magic` is the name of the hook
23 | magic: %{
24 | # it uses the `Magic` module
25 | mod: Magic,
26 | # we allow the client to access `Magic.value/0`
27 | access: %{
28 | action: :value,
29 | }
30 | }
31 | }
32 | ```
33 |
34 | ## Client side
35 |
36 | Now we can retreive the state with the `useServerState()` hook.
37 |
38 | ```javascript
39 | // in src/components/Magic.js
40 | import {useServerState} from '@glue/react'
41 |
42 | export default () => {
43 | const {value} = useServerState('magic')
44 |
45 | return {value}
46 | }
47 | ```
48 |
--------------------------------------------------------------------------------
/glue/.formatter.exs:
--------------------------------------------------------------------------------
1 | # Used by "mix format"
2 | [
3 | inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
4 | ]
5 |
--------------------------------------------------------------------------------
/glue/.gitignore:
--------------------------------------------------------------------------------
1 | # The directory Mix will write compiled artifacts to.
2 | /_build/
3 |
4 | # If you run "mix test --cover", coverage assets end up here.
5 | /cover/
6 |
7 | # The directory Mix downloads your dependencies sources to.
8 | /deps/
9 |
10 | # Where third-party dependencies like ExDoc output generated docs.
11 | /doc/
12 |
13 | # Ignore .fetch files in case you like to edit your project deps locally.
14 | /.fetch
15 |
16 | # If the VM crashes, it generates a dump, let's ignore it too.
17 | erl_crash.dump
18 |
19 | # Also ignore archive artifacts (built via "mix archive.build").
20 | *.ez
21 |
22 | # Ignore package tarball (built via "mix hex.build").
23 | glue-*.tar
24 |
25 |
--------------------------------------------------------------------------------
/glue/README.md:
--------------------------------------------------------------------------------
1 | # Glue
2 |
3 | A package for Phoenix that generates socket code for you.
4 |
5 | ## Installation
6 |
7 | Add `glue` to your list of dependencies in `mix.exs`:
8 |
9 | ```elixir
10 | def deps do
11 | [
12 | {:glue, "~> 0.1.0"}
13 | ]
14 | end
15 | ```
16 |
--------------------------------------------------------------------------------
/glue/lib/glue.ex:
--------------------------------------------------------------------------------
1 | defmodule Glue do
2 | end
3 |
--------------------------------------------------------------------------------
/glue/lib/glue/generator.ex:
--------------------------------------------------------------------------------
1 | defmodule Glue.Generator do
2 | defmacro generate_hooks(app) do
3 | hooks = Application.get_env(app, :hooks)
4 |
5 | Enum.map(hooks, fn {key, config} ->
6 | access_name = "#{key}:#{config.access.action}"
7 |
8 | base =
9 | quote do
10 | def handle_in(unquote(access_name), payload, socket) do
11 | value =
12 | apply(
13 | unquote(config.mod),
14 | unquote(config.access.action),
15 | payload["keys"] ++ payload["args"]
16 | )
17 |
18 | result = extract_result(value)
19 |
20 | {:reply, {:ok, result}, socket}
21 | end
22 |
23 | defp broadcast_change(socket, key, keys, state) do
24 | ids = Enum.join(keys, ":")
25 | broadcast_from!(socket, "#{key}:changed:#{ids}", %{state: state})
26 | end
27 |
28 | defp extract_result(value) do
29 | case value do
30 | {:ok, x} -> %{success: true, value: x, state: x}
31 | {:ok, x, state} -> %{success: true, value: x, state: x}
32 | {:error, x} -> %{success: false, value: x}
33 | x -> %{success: true, value: x, state: x}
34 | end
35 | end
36 | end
37 |
38 | calls =
39 | Enum.map(config[:calls] || [], fn call ->
40 | call_name = "#{key}:#{call}"
41 |
42 | quote do
43 | def handle_in(unquote(call_name), payload, socket) do
44 | keys = payload["keys"]
45 | value = apply(unquote(config.mod), unquote(call), keys ++ payload["args"])
46 |
47 | result = extract_result(value)
48 |
49 | if result.success do
50 | broadcast_change(socket, unquote(key), keys, result.state)
51 | end
52 |
53 | {:reply, {:ok, result}, socket}
54 | end
55 | end
56 | end)
57 |
58 | [base, calls]
59 | end)
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/glue/lib/glue/view.ex:
--------------------------------------------------------------------------------
1 | defmodule Glue.View do
2 | use Phoenix.HTML
3 |
4 | def hooks_config(app) do
5 | config = Application.get_env(app, :hooks)
6 |
7 | config
8 | |> Enum.map(fn {k, v} ->
9 | {k,
10 | %{
11 | access: v.access,
12 | calls: v[:calls] || []
13 | }}
14 | end)
15 | |> Enum.into(%{})
16 | |> Jason.encode!()
17 | |> raw()
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/glue/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule Glue.MixProject do
2 | use Mix.Project
3 |
4 | def project do
5 | [
6 | app: :glue,
7 | version: "0.1.0",
8 | elixir: "~> 1.9",
9 | start_permanent: Mix.env() == :prod,
10 | deps: deps()
11 | ]
12 | end
13 |
14 | # Run "mix help compile.app" to learn about applications.
15 | def application do
16 | [
17 | extra_applications: [:logger]
18 | ]
19 | end
20 |
21 | # Run "mix help deps" to learn about dependencies.
22 | defp deps do
23 | [
24 | {:phoenix, ">= 1.4.0"},
25 | ]
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/glue/test/glue_test.exs:
--------------------------------------------------------------------------------
1 | defmodule GlueTest do
2 | use ExUnit.Case
3 | doctest Glue
4 | end
5 |
--------------------------------------------------------------------------------
/glue/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/*"
4 | ],
5 | "version": "0.0.0"
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "root",
3 | "private": true,
4 | "devDependencies": {
5 | "lerna": "^3.16.4"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript Packages
2 |
3 | All these packages are managed via `lerna`
4 |
--------------------------------------------------------------------------------
/packages/core/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /index.js
3 |
--------------------------------------------------------------------------------
/packages/core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@glue/core",
3 | "version": "0.0.1",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Josh Nussbaum",
10 | "license": "ISC",
11 | "peerDependencies": {
12 | "phoenix": "^1.4.9"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/core/src/index.js:
--------------------------------------------------------------------------------
1 | import socket from "./socket"
2 |
3 | let channel
4 |
5 | export function init() {
6 | return new Promise((resolve, reject) => {
7 | channel = socket.channel("hook:lobby")
8 |
9 | channel.join()
10 | .receive("ok", () => resolve(channel))
11 | .receive("timeout", () => reject('timeout'))
12 | .receive("error", error => reject(error))
13 | })
14 | }
15 |
16 | export function subscribe(name, callback) {
17 | return channel.on(name, callback)
18 | }
19 |
20 | export function unsubscribe(name, ref) {
21 | channel.off(name, ref)
22 | }
23 |
24 | export function call(name, keys, args=[]) {
25 | return new Promise((resolve, reject) => {
26 | channel.push(name, {keys, args})
27 | .receive("ok", resolve)
28 | .receive("timeout", () => {
29 | console.error(`call to ${name} timed out`)
30 | reject('timeout')
31 | })
32 | .receive("error", error => {
33 | console.error(`call to ${name} errored`, error)
34 | reject(error)
35 | })
36 | })
37 | }
38 |
--------------------------------------------------------------------------------
/packages/core/src/socket.js:
--------------------------------------------------------------------------------
1 | import {Socket} from "phoenix"
2 |
3 | const socket = new Socket("/socket", {params: {token: window.userToken}})
4 |
5 | socket.connect()
6 |
7 | export default socket
8 |
--------------------------------------------------------------------------------
/packages/core/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | phoenix@^1.4.9:
6 | version "1.4.9"
7 | resolved "https://registry.yarnpkg.com/phoenix/-/phoenix-1.4.9.tgz#0e251514af9627d61924ce9194e6e414f392b58d"
8 | integrity sha512-x7UMemlq0w03S0R3fmklkUuYhjPXC6K2FXz6q7oBbUw17LIAYexiuFaOxPk/pMWSX69AZPZlQeEHytnIyTAw/w==
9 |
--------------------------------------------------------------------------------
/packages/react/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /index.js
3 |
--------------------------------------------------------------------------------
/packages/react/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@glue/react",
3 | "version": "0.0.1",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@babel/cli": {
8 | "version": "7.5.5",
9 | "dev": true,
10 | "requires": {
11 | "chokidar": "^2.0.4",
12 | "commander": "^2.8.1",
13 | "convert-source-map": "^1.1.0",
14 | "fs-readdir-recursive": "^1.1.0",
15 | "glob": "^7.0.0",
16 | "lodash": "^4.17.13",
17 | "mkdirp": "^0.5.1",
18 | "output-file-sync": "^2.0.0",
19 | "slash": "^2.0.0",
20 | "source-map": "^0.5.0"
21 | }
22 | },
23 | "@babel/code-frame": {
24 | "version": "7.5.5",
25 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
26 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
27 | "dev": true,
28 | "requires": {
29 | "@babel/highlight": "^7.0.0"
30 | }
31 | },
32 | "@babel/core": {
33 | "version": "7.5.5",
34 | "dev": true,
35 | "requires": {
36 | "@babel/code-frame": "^7.5.5",
37 | "@babel/generator": "^7.5.5",
38 | "@babel/helpers": "^7.5.5",
39 | "@babel/parser": "^7.5.5",
40 | "@babel/template": "^7.4.4",
41 | "@babel/traverse": "^7.5.5",
42 | "@babel/types": "^7.5.5",
43 | "convert-source-map": "^1.1.0",
44 | "debug": "^4.1.0",
45 | "json5": "^2.1.0",
46 | "lodash": "^4.17.13",
47 | "resolve": "^1.3.2",
48 | "semver": "^5.4.1",
49 | "source-map": "^0.5.0"
50 | },
51 | "dependencies": {
52 | "debug": {
53 | "version": "4.1.1",
54 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
55 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
56 | "dev": true,
57 | "requires": {
58 | "ms": "^2.1.1"
59 | }
60 | }
61 | }
62 | },
63 | "@babel/generator": {
64 | "version": "7.5.5",
65 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz",
66 | "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==",
67 | "dev": true,
68 | "requires": {
69 | "@babel/types": "^7.5.5",
70 | "jsesc": "^2.5.1",
71 | "lodash": "^4.17.13",
72 | "source-map": "^0.5.0",
73 | "trim-right": "^1.0.1"
74 | }
75 | },
76 | "@babel/helper-annotate-as-pure": {
77 | "version": "7.0.0",
78 | "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz",
79 | "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==",
80 | "dev": true,
81 | "requires": {
82 | "@babel/types": "^7.0.0"
83 | }
84 | },
85 | "@babel/helper-builder-binary-assignment-operator-visitor": {
86 | "version": "7.1.0",
87 | "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
88 | "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==",
89 | "dev": true,
90 | "requires": {
91 | "@babel/helper-explode-assignable-expression": "^7.1.0",
92 | "@babel/types": "^7.0.0"
93 | }
94 | },
95 | "@babel/helper-builder-react-jsx": {
96 | "version": "7.3.0",
97 | "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.3.0.tgz",
98 | "integrity": "sha512-MjA9KgwCuPEkQd9ncSXvSyJ5y+j2sICHyrI0M3L+6fnS4wMSNDc1ARXsbTfbb2cXHn17VisSnU/sHFTCxVxSMw==",
99 | "dev": true,
100 | "requires": {
101 | "@babel/types": "^7.3.0",
102 | "esutils": "^2.0.0"
103 | }
104 | },
105 | "@babel/helper-call-delegate": {
106 | "version": "7.4.4",
107 | "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz",
108 | "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==",
109 | "dev": true,
110 | "requires": {
111 | "@babel/helper-hoist-variables": "^7.4.4",
112 | "@babel/traverse": "^7.4.4",
113 | "@babel/types": "^7.4.4"
114 | }
115 | },
116 | "@babel/helper-define-map": {
117 | "version": "7.5.5",
118 | "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz",
119 | "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==",
120 | "dev": true,
121 | "requires": {
122 | "@babel/helper-function-name": "^7.1.0",
123 | "@babel/types": "^7.5.5",
124 | "lodash": "^4.17.13"
125 | }
126 | },
127 | "@babel/helper-explode-assignable-expression": {
128 | "version": "7.1.0",
129 | "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz",
130 | "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==",
131 | "dev": true,
132 | "requires": {
133 | "@babel/traverse": "^7.1.0",
134 | "@babel/types": "^7.0.0"
135 | }
136 | },
137 | "@babel/helper-function-name": {
138 | "version": "7.1.0",
139 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
140 | "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
141 | "dev": true,
142 | "requires": {
143 | "@babel/helper-get-function-arity": "^7.0.0",
144 | "@babel/template": "^7.1.0",
145 | "@babel/types": "^7.0.0"
146 | }
147 | },
148 | "@babel/helper-get-function-arity": {
149 | "version": "7.0.0",
150 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
151 | "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
152 | "dev": true,
153 | "requires": {
154 | "@babel/types": "^7.0.0"
155 | }
156 | },
157 | "@babel/helper-hoist-variables": {
158 | "version": "7.4.4",
159 | "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz",
160 | "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==",
161 | "dev": true,
162 | "requires": {
163 | "@babel/types": "^7.4.4"
164 | }
165 | },
166 | "@babel/helper-member-expression-to-functions": {
167 | "version": "7.5.5",
168 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz",
169 | "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==",
170 | "dev": true,
171 | "requires": {
172 | "@babel/types": "^7.5.5"
173 | }
174 | },
175 | "@babel/helper-module-imports": {
176 | "version": "7.0.0",
177 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz",
178 | "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==",
179 | "dev": true,
180 | "requires": {
181 | "@babel/types": "^7.0.0"
182 | }
183 | },
184 | "@babel/helper-module-transforms": {
185 | "version": "7.5.5",
186 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz",
187 | "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==",
188 | "dev": true,
189 | "requires": {
190 | "@babel/helper-module-imports": "^7.0.0",
191 | "@babel/helper-simple-access": "^7.1.0",
192 | "@babel/helper-split-export-declaration": "^7.4.4",
193 | "@babel/template": "^7.4.4",
194 | "@babel/types": "^7.5.5",
195 | "lodash": "^4.17.13"
196 | }
197 | },
198 | "@babel/helper-optimise-call-expression": {
199 | "version": "7.0.0",
200 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz",
201 | "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==",
202 | "dev": true,
203 | "requires": {
204 | "@babel/types": "^7.0.0"
205 | }
206 | },
207 | "@babel/helper-plugin-utils": {
208 | "version": "7.0.0",
209 | "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
210 | "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
211 | "dev": true
212 | },
213 | "@babel/helper-regex": {
214 | "version": "7.5.5",
215 | "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz",
216 | "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==",
217 | "dev": true,
218 | "requires": {
219 | "lodash": "^4.17.13"
220 | }
221 | },
222 | "@babel/helper-remap-async-to-generator": {
223 | "version": "7.1.0",
224 | "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz",
225 | "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==",
226 | "dev": true,
227 | "requires": {
228 | "@babel/helper-annotate-as-pure": "^7.0.0",
229 | "@babel/helper-wrap-function": "^7.1.0",
230 | "@babel/template": "^7.1.0",
231 | "@babel/traverse": "^7.1.0",
232 | "@babel/types": "^7.0.0"
233 | }
234 | },
235 | "@babel/helper-replace-supers": {
236 | "version": "7.5.5",
237 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz",
238 | "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==",
239 | "dev": true,
240 | "requires": {
241 | "@babel/helper-member-expression-to-functions": "^7.5.5",
242 | "@babel/helper-optimise-call-expression": "^7.0.0",
243 | "@babel/traverse": "^7.5.5",
244 | "@babel/types": "^7.5.5"
245 | }
246 | },
247 | "@babel/helper-simple-access": {
248 | "version": "7.1.0",
249 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz",
250 | "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==",
251 | "dev": true,
252 | "requires": {
253 | "@babel/template": "^7.1.0",
254 | "@babel/types": "^7.0.0"
255 | }
256 | },
257 | "@babel/helper-split-export-declaration": {
258 | "version": "7.4.4",
259 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
260 | "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
261 | "dev": true,
262 | "requires": {
263 | "@babel/types": "^7.4.4"
264 | }
265 | },
266 | "@babel/helper-wrap-function": {
267 | "version": "7.2.0",
268 | "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
269 | "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==",
270 | "dev": true,
271 | "requires": {
272 | "@babel/helper-function-name": "^7.1.0",
273 | "@babel/template": "^7.1.0",
274 | "@babel/traverse": "^7.1.0",
275 | "@babel/types": "^7.2.0"
276 | }
277 | },
278 | "@babel/helpers": {
279 | "version": "7.5.5",
280 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz",
281 | "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==",
282 | "dev": true,
283 | "requires": {
284 | "@babel/template": "^7.4.4",
285 | "@babel/traverse": "^7.5.5",
286 | "@babel/types": "^7.5.5"
287 | }
288 | },
289 | "@babel/highlight": {
290 | "version": "7.5.0",
291 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
292 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
293 | "dev": true,
294 | "requires": {
295 | "chalk": "^2.0.0",
296 | "esutils": "^2.0.2",
297 | "js-tokens": "^4.0.0"
298 | }
299 | },
300 | "@babel/parser": {
301 | "version": "7.5.5",
302 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz",
303 | "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==",
304 | "dev": true
305 | },
306 | "@babel/plugin-proposal-async-generator-functions": {
307 | "version": "7.2.0",
308 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz",
309 | "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==",
310 | "dev": true,
311 | "requires": {
312 | "@babel/helper-plugin-utils": "^7.0.0",
313 | "@babel/helper-remap-async-to-generator": "^7.1.0",
314 | "@babel/plugin-syntax-async-generators": "^7.2.0"
315 | }
316 | },
317 | "@babel/plugin-proposal-dynamic-import": {
318 | "version": "7.5.0",
319 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz",
320 | "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==",
321 | "dev": true,
322 | "requires": {
323 | "@babel/helper-plugin-utils": "^7.0.0",
324 | "@babel/plugin-syntax-dynamic-import": "^7.2.0"
325 | }
326 | },
327 | "@babel/plugin-proposal-json-strings": {
328 | "version": "7.2.0",
329 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
330 | "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
331 | "dev": true,
332 | "requires": {
333 | "@babel/helper-plugin-utils": "^7.0.0",
334 | "@babel/plugin-syntax-json-strings": "^7.2.0"
335 | }
336 | },
337 | "@babel/plugin-proposal-object-rest-spread": {
338 | "version": "7.5.5",
339 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz",
340 | "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==",
341 | "dev": true,
342 | "requires": {
343 | "@babel/helper-plugin-utils": "^7.0.0",
344 | "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
345 | }
346 | },
347 | "@babel/plugin-proposal-optional-catch-binding": {
348 | "version": "7.2.0",
349 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
350 | "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
351 | "dev": true,
352 | "requires": {
353 | "@babel/helper-plugin-utils": "^7.0.0",
354 | "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
355 | }
356 | },
357 | "@babel/plugin-proposal-unicode-property-regex": {
358 | "version": "7.4.4",
359 | "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz",
360 | "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==",
361 | "dev": true,
362 | "requires": {
363 | "@babel/helper-plugin-utils": "^7.0.0",
364 | "@babel/helper-regex": "^7.4.4",
365 | "regexpu-core": "^4.5.4"
366 | }
367 | },
368 | "@babel/plugin-syntax-async-generators": {
369 | "version": "7.2.0",
370 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
371 | "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
372 | "dev": true,
373 | "requires": {
374 | "@babel/helper-plugin-utils": "^7.0.0"
375 | }
376 | },
377 | "@babel/plugin-syntax-dynamic-import": {
378 | "version": "7.2.0",
379 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz",
380 | "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==",
381 | "dev": true,
382 | "requires": {
383 | "@babel/helper-plugin-utils": "^7.0.0"
384 | }
385 | },
386 | "@babel/plugin-syntax-json-strings": {
387 | "version": "7.2.0",
388 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
389 | "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
390 | "dev": true,
391 | "requires": {
392 | "@babel/helper-plugin-utils": "^7.0.0"
393 | }
394 | },
395 | "@babel/plugin-syntax-jsx": {
396 | "version": "7.2.0",
397 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz",
398 | "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==",
399 | "dev": true,
400 | "requires": {
401 | "@babel/helper-plugin-utils": "^7.0.0"
402 | }
403 | },
404 | "@babel/plugin-syntax-object-rest-spread": {
405 | "version": "7.2.0",
406 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
407 | "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
408 | "dev": true,
409 | "requires": {
410 | "@babel/helper-plugin-utils": "^7.0.0"
411 | }
412 | },
413 | "@babel/plugin-syntax-optional-catch-binding": {
414 | "version": "7.2.0",
415 | "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
416 | "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
417 | "dev": true,
418 | "requires": {
419 | "@babel/helper-plugin-utils": "^7.0.0"
420 | }
421 | },
422 | "@babel/plugin-transform-arrow-functions": {
423 | "version": "7.2.0",
424 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
425 | "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
426 | "dev": true,
427 | "requires": {
428 | "@babel/helper-plugin-utils": "^7.0.0"
429 | }
430 | },
431 | "@babel/plugin-transform-async-to-generator": {
432 | "version": "7.5.0",
433 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz",
434 | "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==",
435 | "dev": true,
436 | "requires": {
437 | "@babel/helper-module-imports": "^7.0.0",
438 | "@babel/helper-plugin-utils": "^7.0.0",
439 | "@babel/helper-remap-async-to-generator": "^7.1.0"
440 | }
441 | },
442 | "@babel/plugin-transform-block-scoped-functions": {
443 | "version": "7.2.0",
444 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
445 | "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
446 | "dev": true,
447 | "requires": {
448 | "@babel/helper-plugin-utils": "^7.0.0"
449 | }
450 | },
451 | "@babel/plugin-transform-block-scoping": {
452 | "version": "7.5.5",
453 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz",
454 | "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==",
455 | "dev": true,
456 | "requires": {
457 | "@babel/helper-plugin-utils": "^7.0.0",
458 | "lodash": "^4.17.13"
459 | }
460 | },
461 | "@babel/plugin-transform-classes": {
462 | "version": "7.5.5",
463 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz",
464 | "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==",
465 | "dev": true,
466 | "requires": {
467 | "@babel/helper-annotate-as-pure": "^7.0.0",
468 | "@babel/helper-define-map": "^7.5.5",
469 | "@babel/helper-function-name": "^7.1.0",
470 | "@babel/helper-optimise-call-expression": "^7.0.0",
471 | "@babel/helper-plugin-utils": "^7.0.0",
472 | "@babel/helper-replace-supers": "^7.5.5",
473 | "@babel/helper-split-export-declaration": "^7.4.4",
474 | "globals": "^11.1.0"
475 | }
476 | },
477 | "@babel/plugin-transform-computed-properties": {
478 | "version": "7.2.0",
479 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
480 | "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
481 | "dev": true,
482 | "requires": {
483 | "@babel/helper-plugin-utils": "^7.0.0"
484 | }
485 | },
486 | "@babel/plugin-transform-destructuring": {
487 | "version": "7.5.0",
488 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz",
489 | "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==",
490 | "dev": true,
491 | "requires": {
492 | "@babel/helper-plugin-utils": "^7.0.0"
493 | }
494 | },
495 | "@babel/plugin-transform-dotall-regex": {
496 | "version": "7.4.4",
497 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz",
498 | "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==",
499 | "dev": true,
500 | "requires": {
501 | "@babel/helper-plugin-utils": "^7.0.0",
502 | "@babel/helper-regex": "^7.4.4",
503 | "regexpu-core": "^4.5.4"
504 | }
505 | },
506 | "@babel/plugin-transform-duplicate-keys": {
507 | "version": "7.5.0",
508 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz",
509 | "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==",
510 | "dev": true,
511 | "requires": {
512 | "@babel/helper-plugin-utils": "^7.0.0"
513 | }
514 | },
515 | "@babel/plugin-transform-exponentiation-operator": {
516 | "version": "7.2.0",
517 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
518 | "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
519 | "dev": true,
520 | "requires": {
521 | "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
522 | "@babel/helper-plugin-utils": "^7.0.0"
523 | }
524 | },
525 | "@babel/plugin-transform-for-of": {
526 | "version": "7.4.4",
527 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz",
528 | "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==",
529 | "dev": true,
530 | "requires": {
531 | "@babel/helper-plugin-utils": "^7.0.0"
532 | }
533 | },
534 | "@babel/plugin-transform-function-name": {
535 | "version": "7.4.4",
536 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz",
537 | "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==",
538 | "dev": true,
539 | "requires": {
540 | "@babel/helper-function-name": "^7.1.0",
541 | "@babel/helper-plugin-utils": "^7.0.0"
542 | }
543 | },
544 | "@babel/plugin-transform-literals": {
545 | "version": "7.2.0",
546 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
547 | "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
548 | "dev": true,
549 | "requires": {
550 | "@babel/helper-plugin-utils": "^7.0.0"
551 | }
552 | },
553 | "@babel/plugin-transform-member-expression-literals": {
554 | "version": "7.2.0",
555 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz",
556 | "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==",
557 | "dev": true,
558 | "requires": {
559 | "@babel/helper-plugin-utils": "^7.0.0"
560 | }
561 | },
562 | "@babel/plugin-transform-modules-amd": {
563 | "version": "7.5.0",
564 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz",
565 | "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==",
566 | "dev": true,
567 | "requires": {
568 | "@babel/helper-module-transforms": "^7.1.0",
569 | "@babel/helper-plugin-utils": "^7.0.0",
570 | "babel-plugin-dynamic-import-node": "^2.3.0"
571 | }
572 | },
573 | "@babel/plugin-transform-modules-commonjs": {
574 | "version": "7.5.0",
575 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz",
576 | "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==",
577 | "dev": true,
578 | "requires": {
579 | "@babel/helper-module-transforms": "^7.4.4",
580 | "@babel/helper-plugin-utils": "^7.0.0",
581 | "@babel/helper-simple-access": "^7.1.0",
582 | "babel-plugin-dynamic-import-node": "^2.3.0"
583 | }
584 | },
585 | "@babel/plugin-transform-modules-systemjs": {
586 | "version": "7.5.0",
587 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz",
588 | "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==",
589 | "dev": true,
590 | "requires": {
591 | "@babel/helper-hoist-variables": "^7.4.4",
592 | "@babel/helper-plugin-utils": "^7.0.0",
593 | "babel-plugin-dynamic-import-node": "^2.3.0"
594 | }
595 | },
596 | "@babel/plugin-transform-modules-umd": {
597 | "version": "7.2.0",
598 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz",
599 | "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==",
600 | "dev": true,
601 | "requires": {
602 | "@babel/helper-module-transforms": "^7.1.0",
603 | "@babel/helper-plugin-utils": "^7.0.0"
604 | }
605 | },
606 | "@babel/plugin-transform-named-capturing-groups-regex": {
607 | "version": "7.4.5",
608 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz",
609 | "integrity": "sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg==",
610 | "dev": true,
611 | "requires": {
612 | "regexp-tree": "^0.1.6"
613 | }
614 | },
615 | "@babel/plugin-transform-new-target": {
616 | "version": "7.4.4",
617 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz",
618 | "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==",
619 | "dev": true,
620 | "requires": {
621 | "@babel/helper-plugin-utils": "^7.0.0"
622 | }
623 | },
624 | "@babel/plugin-transform-object-super": {
625 | "version": "7.5.5",
626 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz",
627 | "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==",
628 | "dev": true,
629 | "requires": {
630 | "@babel/helper-plugin-utils": "^7.0.0",
631 | "@babel/helper-replace-supers": "^7.5.5"
632 | }
633 | },
634 | "@babel/plugin-transform-parameters": {
635 | "version": "7.4.4",
636 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz",
637 | "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==",
638 | "dev": true,
639 | "requires": {
640 | "@babel/helper-call-delegate": "^7.4.4",
641 | "@babel/helper-get-function-arity": "^7.0.0",
642 | "@babel/helper-plugin-utils": "^7.0.0"
643 | }
644 | },
645 | "@babel/plugin-transform-property-literals": {
646 | "version": "7.2.0",
647 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz",
648 | "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==",
649 | "dev": true,
650 | "requires": {
651 | "@babel/helper-plugin-utils": "^7.0.0"
652 | }
653 | },
654 | "@babel/plugin-transform-react-display-name": {
655 | "version": "7.2.0",
656 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz",
657 | "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==",
658 | "dev": true,
659 | "requires": {
660 | "@babel/helper-plugin-utils": "^7.0.0"
661 | }
662 | },
663 | "@babel/plugin-transform-react-jsx": {
664 | "version": "7.3.0",
665 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.3.0.tgz",
666 | "integrity": "sha512-a/+aRb7R06WcKvQLOu4/TpjKOdvVEKRLWFpKcNuHhiREPgGRB4TQJxq07+EZLS8LFVYpfq1a5lDUnuMdcCpBKg==",
667 | "dev": true,
668 | "requires": {
669 | "@babel/helper-builder-react-jsx": "^7.3.0",
670 | "@babel/helper-plugin-utils": "^7.0.0",
671 | "@babel/plugin-syntax-jsx": "^7.2.0"
672 | }
673 | },
674 | "@babel/plugin-transform-react-jsx-self": {
675 | "version": "7.2.0",
676 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz",
677 | "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==",
678 | "dev": true,
679 | "requires": {
680 | "@babel/helper-plugin-utils": "^7.0.0",
681 | "@babel/plugin-syntax-jsx": "^7.2.0"
682 | }
683 | },
684 | "@babel/plugin-transform-react-jsx-source": {
685 | "version": "7.5.0",
686 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.5.0.tgz",
687 | "integrity": "sha512-58Q+Jsy4IDCZx7kqEZuSDdam/1oW8OdDX8f+Loo6xyxdfg1yF0GE2XNJQSTZCaMol93+FBzpWiPEwtbMloAcPg==",
688 | "dev": true,
689 | "requires": {
690 | "@babel/helper-plugin-utils": "^7.0.0",
691 | "@babel/plugin-syntax-jsx": "^7.2.0"
692 | }
693 | },
694 | "@babel/plugin-transform-regenerator": {
695 | "version": "7.4.5",
696 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz",
697 | "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==",
698 | "dev": true,
699 | "requires": {
700 | "regenerator-transform": "^0.14.0"
701 | }
702 | },
703 | "@babel/plugin-transform-reserved-words": {
704 | "version": "7.2.0",
705 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz",
706 | "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==",
707 | "dev": true,
708 | "requires": {
709 | "@babel/helper-plugin-utils": "^7.0.0"
710 | }
711 | },
712 | "@babel/plugin-transform-shorthand-properties": {
713 | "version": "7.2.0",
714 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
715 | "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
716 | "dev": true,
717 | "requires": {
718 | "@babel/helper-plugin-utils": "^7.0.0"
719 | }
720 | },
721 | "@babel/plugin-transform-spread": {
722 | "version": "7.2.2",
723 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz",
724 | "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==",
725 | "dev": true,
726 | "requires": {
727 | "@babel/helper-plugin-utils": "^7.0.0"
728 | }
729 | },
730 | "@babel/plugin-transform-sticky-regex": {
731 | "version": "7.2.0",
732 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
733 | "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
734 | "dev": true,
735 | "requires": {
736 | "@babel/helper-plugin-utils": "^7.0.0",
737 | "@babel/helper-regex": "^7.0.0"
738 | }
739 | },
740 | "@babel/plugin-transform-template-literals": {
741 | "version": "7.4.4",
742 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz",
743 | "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==",
744 | "dev": true,
745 | "requires": {
746 | "@babel/helper-annotate-as-pure": "^7.0.0",
747 | "@babel/helper-plugin-utils": "^7.0.0"
748 | }
749 | },
750 | "@babel/plugin-transform-typeof-symbol": {
751 | "version": "7.2.0",
752 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
753 | "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
754 | "dev": true,
755 | "requires": {
756 | "@babel/helper-plugin-utils": "^7.0.0"
757 | }
758 | },
759 | "@babel/plugin-transform-unicode-regex": {
760 | "version": "7.4.4",
761 | "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz",
762 | "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==",
763 | "dev": true,
764 | "requires": {
765 | "@babel/helper-plugin-utils": "^7.0.0",
766 | "@babel/helper-regex": "^7.4.4",
767 | "regexpu-core": "^4.5.4"
768 | }
769 | },
770 | "@babel/preset-env": {
771 | "version": "7.5.5",
772 | "dev": true,
773 | "requires": {
774 | "@babel/helper-module-imports": "^7.0.0",
775 | "@babel/helper-plugin-utils": "^7.0.0",
776 | "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
777 | "@babel/plugin-proposal-dynamic-import": "^7.5.0",
778 | "@babel/plugin-proposal-json-strings": "^7.2.0",
779 | "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
780 | "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
781 | "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
782 | "@babel/plugin-syntax-async-generators": "^7.2.0",
783 | "@babel/plugin-syntax-dynamic-import": "^7.2.0",
784 | "@babel/plugin-syntax-json-strings": "^7.2.0",
785 | "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
786 | "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
787 | "@babel/plugin-transform-arrow-functions": "^7.2.0",
788 | "@babel/plugin-transform-async-to-generator": "^7.5.0",
789 | "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
790 | "@babel/plugin-transform-block-scoping": "^7.5.5",
791 | "@babel/plugin-transform-classes": "^7.5.5",
792 | "@babel/plugin-transform-computed-properties": "^7.2.0",
793 | "@babel/plugin-transform-destructuring": "^7.5.0",
794 | "@babel/plugin-transform-dotall-regex": "^7.4.4",
795 | "@babel/plugin-transform-duplicate-keys": "^7.5.0",
796 | "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
797 | "@babel/plugin-transform-for-of": "^7.4.4",
798 | "@babel/plugin-transform-function-name": "^7.4.4",
799 | "@babel/plugin-transform-literals": "^7.2.0",
800 | "@babel/plugin-transform-member-expression-literals": "^7.2.0",
801 | "@babel/plugin-transform-modules-amd": "^7.5.0",
802 | "@babel/plugin-transform-modules-commonjs": "^7.5.0",
803 | "@babel/plugin-transform-modules-systemjs": "^7.5.0",
804 | "@babel/plugin-transform-modules-umd": "^7.2.0",
805 | "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5",
806 | "@babel/plugin-transform-new-target": "^7.4.4",
807 | "@babel/plugin-transform-object-super": "^7.5.5",
808 | "@babel/plugin-transform-parameters": "^7.4.4",
809 | "@babel/plugin-transform-property-literals": "^7.2.0",
810 | "@babel/plugin-transform-regenerator": "^7.4.5",
811 | "@babel/plugin-transform-reserved-words": "^7.2.0",
812 | "@babel/plugin-transform-shorthand-properties": "^7.2.0",
813 | "@babel/plugin-transform-spread": "^7.2.0",
814 | "@babel/plugin-transform-sticky-regex": "^7.2.0",
815 | "@babel/plugin-transform-template-literals": "^7.4.4",
816 | "@babel/plugin-transform-typeof-symbol": "^7.2.0",
817 | "@babel/plugin-transform-unicode-regex": "^7.4.4",
818 | "@babel/types": "^7.5.5",
819 | "browserslist": "^4.6.0",
820 | "core-js-compat": "^3.1.1",
821 | "invariant": "^2.2.2",
822 | "js-levenshtein": "^1.1.3",
823 | "semver": "^5.5.0"
824 | }
825 | },
826 | "@babel/preset-react": {
827 | "version": "7.0.0",
828 | "dev": true,
829 | "requires": {
830 | "@babel/helper-plugin-utils": "^7.0.0",
831 | "@babel/plugin-transform-react-display-name": "^7.0.0",
832 | "@babel/plugin-transform-react-jsx": "^7.0.0",
833 | "@babel/plugin-transform-react-jsx-self": "^7.0.0",
834 | "@babel/plugin-transform-react-jsx-source": "^7.0.0"
835 | }
836 | },
837 | "@babel/template": {
838 | "version": "7.4.4",
839 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
840 | "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==",
841 | "dev": true,
842 | "requires": {
843 | "@babel/code-frame": "^7.0.0",
844 | "@babel/parser": "^7.4.4",
845 | "@babel/types": "^7.4.4"
846 | }
847 | },
848 | "@babel/traverse": {
849 | "version": "7.5.5",
850 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz",
851 | "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==",
852 | "dev": true,
853 | "requires": {
854 | "@babel/code-frame": "^7.5.5",
855 | "@babel/generator": "^7.5.5",
856 | "@babel/helper-function-name": "^7.1.0",
857 | "@babel/helper-split-export-declaration": "^7.4.4",
858 | "@babel/parser": "^7.5.5",
859 | "@babel/types": "^7.5.5",
860 | "debug": "^4.1.0",
861 | "globals": "^11.1.0",
862 | "lodash": "^4.17.13"
863 | },
864 | "dependencies": {
865 | "debug": {
866 | "version": "4.1.1",
867 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
868 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
869 | "dev": true,
870 | "requires": {
871 | "ms": "^2.1.1"
872 | }
873 | }
874 | }
875 | },
876 | "@babel/types": {
877 | "version": "7.5.5",
878 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz",
879 | "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==",
880 | "dev": true,
881 | "requires": {
882 | "esutils": "^2.0.2",
883 | "lodash": "^4.17.13",
884 | "to-fast-properties": "^2.0.0"
885 | }
886 | },
887 | "ansi-styles": {
888 | "version": "3.2.1",
889 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
890 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
891 | "dev": true,
892 | "requires": {
893 | "color-convert": "^1.9.0"
894 | }
895 | },
896 | "anymatch": {
897 | "version": "2.0.0",
898 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
899 | "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
900 | "dev": true,
901 | "optional": true,
902 | "requires": {
903 | "micromatch": "^3.1.4",
904 | "normalize-path": "^2.1.1"
905 | },
906 | "dependencies": {
907 | "normalize-path": {
908 | "version": "2.1.1",
909 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
910 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
911 | "dev": true,
912 | "optional": true,
913 | "requires": {
914 | "remove-trailing-separator": "^1.0.1"
915 | }
916 | }
917 | }
918 | },
919 | "arr-diff": {
920 | "version": "4.0.0",
921 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
922 | "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
923 | "dev": true,
924 | "optional": true
925 | },
926 | "arr-flatten": {
927 | "version": "1.1.0",
928 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
929 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
930 | "dev": true,
931 | "optional": true
932 | },
933 | "arr-union": {
934 | "version": "3.1.0",
935 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
936 | "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
937 | "dev": true,
938 | "optional": true
939 | },
940 | "array-unique": {
941 | "version": "0.3.2",
942 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
943 | "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
944 | "dev": true,
945 | "optional": true
946 | },
947 | "assign-symbols": {
948 | "version": "1.0.0",
949 | "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
950 | "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
951 | "dev": true,
952 | "optional": true
953 | },
954 | "async-each": {
955 | "version": "1.0.3",
956 | "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
957 | "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
958 | "dev": true,
959 | "optional": true
960 | },
961 | "atob": {
962 | "version": "2.1.2",
963 | "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
964 | "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
965 | "dev": true,
966 | "optional": true
967 | },
968 | "babel-plugin-dynamic-import-node": {
969 | "version": "2.3.0",
970 | "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
971 | "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==",
972 | "dev": true,
973 | "requires": {
974 | "object.assign": "^4.1.0"
975 | }
976 | },
977 | "balanced-match": {
978 | "version": "1.0.0",
979 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
980 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
981 | "dev": true
982 | },
983 | "base": {
984 | "version": "0.11.2",
985 | "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
986 | "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
987 | "dev": true,
988 | "optional": true,
989 | "requires": {
990 | "cache-base": "^1.0.1",
991 | "class-utils": "^0.3.5",
992 | "component-emitter": "^1.2.1",
993 | "define-property": "^1.0.0",
994 | "isobject": "^3.0.1",
995 | "mixin-deep": "^1.2.0",
996 | "pascalcase": "^0.1.1"
997 | },
998 | "dependencies": {
999 | "define-property": {
1000 | "version": "1.0.0",
1001 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
1002 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
1003 | "dev": true,
1004 | "optional": true,
1005 | "requires": {
1006 | "is-descriptor": "^1.0.0"
1007 | }
1008 | },
1009 | "is-accessor-descriptor": {
1010 | "version": "1.0.0",
1011 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
1012 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
1013 | "dev": true,
1014 | "optional": true,
1015 | "requires": {
1016 | "kind-of": "^6.0.0"
1017 | }
1018 | },
1019 | "is-data-descriptor": {
1020 | "version": "1.0.0",
1021 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
1022 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
1023 | "dev": true,
1024 | "optional": true,
1025 | "requires": {
1026 | "kind-of": "^6.0.0"
1027 | }
1028 | },
1029 | "is-descriptor": {
1030 | "version": "1.0.2",
1031 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
1032 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
1033 | "dev": true,
1034 | "optional": true,
1035 | "requires": {
1036 | "is-accessor-descriptor": "^1.0.0",
1037 | "is-data-descriptor": "^1.0.0",
1038 | "kind-of": "^6.0.2"
1039 | }
1040 | }
1041 | }
1042 | },
1043 | "binary-extensions": {
1044 | "version": "1.13.1",
1045 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
1046 | "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
1047 | "dev": true,
1048 | "optional": true
1049 | },
1050 | "brace-expansion": {
1051 | "version": "1.1.11",
1052 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1053 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1054 | "dev": true,
1055 | "requires": {
1056 | "balanced-match": "^1.0.0",
1057 | "concat-map": "0.0.1"
1058 | }
1059 | },
1060 | "braces": {
1061 | "version": "2.3.2",
1062 | "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
1063 | "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
1064 | "dev": true,
1065 | "optional": true,
1066 | "requires": {
1067 | "arr-flatten": "^1.1.0",
1068 | "array-unique": "^0.3.2",
1069 | "extend-shallow": "^2.0.1",
1070 | "fill-range": "^4.0.0",
1071 | "isobject": "^3.0.1",
1072 | "repeat-element": "^1.1.2",
1073 | "snapdragon": "^0.8.1",
1074 | "snapdragon-node": "^2.0.1",
1075 | "split-string": "^3.0.2",
1076 | "to-regex": "^3.0.1"
1077 | },
1078 | "dependencies": {
1079 | "extend-shallow": {
1080 | "version": "2.0.1",
1081 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
1082 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
1083 | "dev": true,
1084 | "optional": true,
1085 | "requires": {
1086 | "is-extendable": "^0.1.0"
1087 | }
1088 | }
1089 | }
1090 | },
1091 | "browserslist": {
1092 | "version": "4.6.6",
1093 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
1094 | "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
1095 | "dev": true,
1096 | "requires": {
1097 | "caniuse-lite": "^1.0.30000984",
1098 | "electron-to-chromium": "^1.3.191",
1099 | "node-releases": "^1.1.25"
1100 | }
1101 | },
1102 | "cache-base": {
1103 | "version": "1.0.1",
1104 | "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
1105 | "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
1106 | "dev": true,
1107 | "optional": true,
1108 | "requires": {
1109 | "collection-visit": "^1.0.0",
1110 | "component-emitter": "^1.2.1",
1111 | "get-value": "^2.0.6",
1112 | "has-value": "^1.0.0",
1113 | "isobject": "^3.0.1",
1114 | "set-value": "^2.0.0",
1115 | "to-object-path": "^0.3.0",
1116 | "union-value": "^1.0.0",
1117 | "unset-value": "^1.0.0"
1118 | }
1119 | },
1120 | "caniuse-lite": {
1121 | "version": "1.0.30000989",
1122 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz",
1123 | "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==",
1124 | "dev": true
1125 | },
1126 | "chalk": {
1127 | "version": "2.4.2",
1128 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
1129 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
1130 | "dev": true,
1131 | "requires": {
1132 | "ansi-styles": "^3.2.1",
1133 | "escape-string-regexp": "^1.0.5",
1134 | "supports-color": "^5.3.0"
1135 | }
1136 | },
1137 | "chokidar": {
1138 | "version": "2.1.6",
1139 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz",
1140 | "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==",
1141 | "dev": true,
1142 | "optional": true,
1143 | "requires": {
1144 | "anymatch": "^2.0.0",
1145 | "async-each": "^1.0.1",
1146 | "braces": "^2.3.2",
1147 | "fsevents": "^1.2.7",
1148 | "glob-parent": "^3.1.0",
1149 | "inherits": "^2.0.3",
1150 | "is-binary-path": "^1.0.0",
1151 | "is-glob": "^4.0.0",
1152 | "normalize-path": "^3.0.0",
1153 | "path-is-absolute": "^1.0.0",
1154 | "readdirp": "^2.2.1",
1155 | "upath": "^1.1.1"
1156 | }
1157 | },
1158 | "class-utils": {
1159 | "version": "0.3.6",
1160 | "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
1161 | "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
1162 | "dev": true,
1163 | "optional": true,
1164 | "requires": {
1165 | "arr-union": "^3.1.0",
1166 | "define-property": "^0.2.5",
1167 | "isobject": "^3.0.0",
1168 | "static-extend": "^0.1.1"
1169 | },
1170 | "dependencies": {
1171 | "define-property": {
1172 | "version": "0.2.5",
1173 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
1174 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
1175 | "dev": true,
1176 | "optional": true,
1177 | "requires": {
1178 | "is-descriptor": "^0.1.0"
1179 | }
1180 | }
1181 | }
1182 | },
1183 | "collection-visit": {
1184 | "version": "1.0.0",
1185 | "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
1186 | "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
1187 | "dev": true,
1188 | "optional": true,
1189 | "requires": {
1190 | "map-visit": "^1.0.0",
1191 | "object-visit": "^1.0.0"
1192 | }
1193 | },
1194 | "color-convert": {
1195 | "version": "1.9.3",
1196 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
1197 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
1198 | "dev": true,
1199 | "requires": {
1200 | "color-name": "1.1.3"
1201 | }
1202 | },
1203 | "color-name": {
1204 | "version": "1.1.3",
1205 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
1206 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
1207 | "dev": true
1208 | },
1209 | "commander": {
1210 | "version": "2.20.0",
1211 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
1212 | "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
1213 | "dev": true
1214 | },
1215 | "component-emitter": {
1216 | "version": "1.3.0",
1217 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
1218 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
1219 | "dev": true,
1220 | "optional": true
1221 | },
1222 | "concat-map": {
1223 | "version": "0.0.1",
1224 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1225 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
1226 | "dev": true
1227 | },
1228 | "convert-source-map": {
1229 | "version": "1.6.0",
1230 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
1231 | "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
1232 | "dev": true,
1233 | "requires": {
1234 | "safe-buffer": "~5.1.1"
1235 | }
1236 | },
1237 | "copy-descriptor": {
1238 | "version": "0.1.1",
1239 | "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
1240 | "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
1241 | "dev": true,
1242 | "optional": true
1243 | },
1244 | "core-js-compat": {
1245 | "version": "3.2.1",
1246 | "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.2.1.tgz",
1247 | "integrity": "sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A==",
1248 | "dev": true,
1249 | "requires": {
1250 | "browserslist": "^4.6.6",
1251 | "semver": "^6.3.0"
1252 | },
1253 | "dependencies": {
1254 | "semver": {
1255 | "version": "6.3.0",
1256 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
1257 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
1258 | "dev": true
1259 | }
1260 | }
1261 | },
1262 | "core-util-is": {
1263 | "version": "1.0.2",
1264 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
1265 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
1266 | "dev": true,
1267 | "optional": true
1268 | },
1269 | "debug": {
1270 | "version": "2.6.9",
1271 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1272 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1273 | "dev": true,
1274 | "optional": true,
1275 | "requires": {
1276 | "ms": "2.0.0"
1277 | },
1278 | "dependencies": {
1279 | "ms": {
1280 | "version": "2.0.0",
1281 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1282 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
1283 | "dev": true,
1284 | "optional": true
1285 | }
1286 | }
1287 | },
1288 | "decode-uri-component": {
1289 | "version": "0.2.0",
1290 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
1291 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
1292 | "dev": true,
1293 | "optional": true
1294 | },
1295 | "define-properties": {
1296 | "version": "1.1.3",
1297 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
1298 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
1299 | "dev": true,
1300 | "requires": {
1301 | "object-keys": "^1.0.12"
1302 | }
1303 | },
1304 | "define-property": {
1305 | "version": "2.0.2",
1306 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
1307 | "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
1308 | "dev": true,
1309 | "optional": true,
1310 | "requires": {
1311 | "is-descriptor": "^1.0.2",
1312 | "isobject": "^3.0.1"
1313 | },
1314 | "dependencies": {
1315 | "is-accessor-descriptor": {
1316 | "version": "1.0.0",
1317 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
1318 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
1319 | "dev": true,
1320 | "optional": true,
1321 | "requires": {
1322 | "kind-of": "^6.0.0"
1323 | }
1324 | },
1325 | "is-data-descriptor": {
1326 | "version": "1.0.0",
1327 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
1328 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
1329 | "dev": true,
1330 | "optional": true,
1331 | "requires": {
1332 | "kind-of": "^6.0.0"
1333 | }
1334 | },
1335 | "is-descriptor": {
1336 | "version": "1.0.2",
1337 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
1338 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
1339 | "dev": true,
1340 | "optional": true,
1341 | "requires": {
1342 | "is-accessor-descriptor": "^1.0.0",
1343 | "is-data-descriptor": "^1.0.0",
1344 | "kind-of": "^6.0.2"
1345 | }
1346 | }
1347 | }
1348 | },
1349 | "electron-to-chromium": {
1350 | "version": "1.3.235",
1351 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.235.tgz",
1352 | "integrity": "sha512-xNabEDbMIKPLQd6xgv4nyyeMaWXIKSJr6G51ZhUemHhbz6kjZAYcygA8CvfEcMF+Mt5eLmDWaLmfSOWdQxzBVQ==",
1353 | "dev": true
1354 | },
1355 | "escape-string-regexp": {
1356 | "version": "1.0.5",
1357 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
1358 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
1359 | "dev": true
1360 | },
1361 | "esutils": {
1362 | "version": "2.0.3",
1363 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
1364 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
1365 | "dev": true
1366 | },
1367 | "expand-brackets": {
1368 | "version": "2.1.4",
1369 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
1370 | "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
1371 | "dev": true,
1372 | "optional": true,
1373 | "requires": {
1374 | "debug": "^2.3.3",
1375 | "define-property": "^0.2.5",
1376 | "extend-shallow": "^2.0.1",
1377 | "posix-character-classes": "^0.1.0",
1378 | "regex-not": "^1.0.0",
1379 | "snapdragon": "^0.8.1",
1380 | "to-regex": "^3.0.1"
1381 | },
1382 | "dependencies": {
1383 | "define-property": {
1384 | "version": "0.2.5",
1385 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
1386 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
1387 | "dev": true,
1388 | "optional": true,
1389 | "requires": {
1390 | "is-descriptor": "^0.1.0"
1391 | }
1392 | },
1393 | "extend-shallow": {
1394 | "version": "2.0.1",
1395 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
1396 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
1397 | "dev": true,
1398 | "optional": true,
1399 | "requires": {
1400 | "is-extendable": "^0.1.0"
1401 | }
1402 | }
1403 | }
1404 | },
1405 | "extend-shallow": {
1406 | "version": "3.0.2",
1407 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
1408 | "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
1409 | "dev": true,
1410 | "optional": true,
1411 | "requires": {
1412 | "assign-symbols": "^1.0.0",
1413 | "is-extendable": "^1.0.1"
1414 | },
1415 | "dependencies": {
1416 | "is-extendable": {
1417 | "version": "1.0.1",
1418 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
1419 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
1420 | "dev": true,
1421 | "optional": true,
1422 | "requires": {
1423 | "is-plain-object": "^2.0.4"
1424 | }
1425 | }
1426 | }
1427 | },
1428 | "extglob": {
1429 | "version": "2.0.4",
1430 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
1431 | "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
1432 | "dev": true,
1433 | "optional": true,
1434 | "requires": {
1435 | "array-unique": "^0.3.2",
1436 | "define-property": "^1.0.0",
1437 | "expand-brackets": "^2.1.4",
1438 | "extend-shallow": "^2.0.1",
1439 | "fragment-cache": "^0.2.1",
1440 | "regex-not": "^1.0.0",
1441 | "snapdragon": "^0.8.1",
1442 | "to-regex": "^3.0.1"
1443 | },
1444 | "dependencies": {
1445 | "define-property": {
1446 | "version": "1.0.0",
1447 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
1448 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
1449 | "dev": true,
1450 | "optional": true,
1451 | "requires": {
1452 | "is-descriptor": "^1.0.0"
1453 | }
1454 | },
1455 | "extend-shallow": {
1456 | "version": "2.0.1",
1457 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
1458 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
1459 | "dev": true,
1460 | "optional": true,
1461 | "requires": {
1462 | "is-extendable": "^0.1.0"
1463 | }
1464 | },
1465 | "is-accessor-descriptor": {
1466 | "version": "1.0.0",
1467 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
1468 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
1469 | "dev": true,
1470 | "optional": true,
1471 | "requires": {
1472 | "kind-of": "^6.0.0"
1473 | }
1474 | },
1475 | "is-data-descriptor": {
1476 | "version": "1.0.0",
1477 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
1478 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
1479 | "dev": true,
1480 | "optional": true,
1481 | "requires": {
1482 | "kind-of": "^6.0.0"
1483 | }
1484 | },
1485 | "is-descriptor": {
1486 | "version": "1.0.2",
1487 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
1488 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
1489 | "dev": true,
1490 | "optional": true,
1491 | "requires": {
1492 | "is-accessor-descriptor": "^1.0.0",
1493 | "is-data-descriptor": "^1.0.0",
1494 | "kind-of": "^6.0.2"
1495 | }
1496 | }
1497 | }
1498 | },
1499 | "fill-range": {
1500 | "version": "4.0.0",
1501 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
1502 | "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
1503 | "dev": true,
1504 | "optional": true,
1505 | "requires": {
1506 | "extend-shallow": "^2.0.1",
1507 | "is-number": "^3.0.0",
1508 | "repeat-string": "^1.6.1",
1509 | "to-regex-range": "^2.1.0"
1510 | },
1511 | "dependencies": {
1512 | "extend-shallow": {
1513 | "version": "2.0.1",
1514 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
1515 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
1516 | "dev": true,
1517 | "optional": true,
1518 | "requires": {
1519 | "is-extendable": "^0.1.0"
1520 | }
1521 | }
1522 | }
1523 | },
1524 | "for-in": {
1525 | "version": "1.0.2",
1526 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
1527 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
1528 | "dev": true,
1529 | "optional": true
1530 | },
1531 | "fragment-cache": {
1532 | "version": "0.2.1",
1533 | "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
1534 | "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
1535 | "dev": true,
1536 | "optional": true,
1537 | "requires": {
1538 | "map-cache": "^0.2.2"
1539 | }
1540 | },
1541 | "fs-readdir-recursive": {
1542 | "version": "1.1.0",
1543 | "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
1544 | "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
1545 | "dev": true
1546 | },
1547 | "fs.realpath": {
1548 | "version": "1.0.0",
1549 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1550 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
1551 | "dev": true
1552 | },
1553 | "fsevents": {
1554 | "version": "1.2.9",
1555 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
1556 | "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
1557 | "dev": true,
1558 | "optional": true,
1559 | "requires": {
1560 | "nan": "^2.12.1",
1561 | "node-pre-gyp": "^0.12.0"
1562 | },
1563 | "dependencies": {
1564 | "abbrev": {
1565 | "version": "1.1.1",
1566 | "bundled": true,
1567 | "dev": true,
1568 | "optional": true
1569 | },
1570 | "ansi-regex": {
1571 | "version": "2.1.1",
1572 | "bundled": true,
1573 | "dev": true,
1574 | "optional": true
1575 | },
1576 | "aproba": {
1577 | "version": "1.2.0",
1578 | "bundled": true,
1579 | "dev": true,
1580 | "optional": true
1581 | },
1582 | "are-we-there-yet": {
1583 | "version": "1.1.5",
1584 | "bundled": true,
1585 | "dev": true,
1586 | "optional": true,
1587 | "requires": {
1588 | "delegates": "^1.0.0",
1589 | "readable-stream": "^2.0.6"
1590 | }
1591 | },
1592 | "balanced-match": {
1593 | "version": "1.0.0",
1594 | "bundled": true,
1595 | "dev": true,
1596 | "optional": true
1597 | },
1598 | "brace-expansion": {
1599 | "version": "1.1.11",
1600 | "bundled": true,
1601 | "dev": true,
1602 | "optional": true,
1603 | "requires": {
1604 | "balanced-match": "^1.0.0",
1605 | "concat-map": "0.0.1"
1606 | }
1607 | },
1608 | "chownr": {
1609 | "version": "1.1.1",
1610 | "bundled": true,
1611 | "dev": true,
1612 | "optional": true
1613 | },
1614 | "code-point-at": {
1615 | "version": "1.1.0",
1616 | "bundled": true,
1617 | "dev": true,
1618 | "optional": true
1619 | },
1620 | "concat-map": {
1621 | "version": "0.0.1",
1622 | "bundled": true,
1623 | "dev": true,
1624 | "optional": true
1625 | },
1626 | "console-control-strings": {
1627 | "version": "1.1.0",
1628 | "bundled": true,
1629 | "dev": true,
1630 | "optional": true
1631 | },
1632 | "core-util-is": {
1633 | "version": "1.0.2",
1634 | "bundled": true,
1635 | "dev": true,
1636 | "optional": true
1637 | },
1638 | "debug": {
1639 | "version": "4.1.1",
1640 | "bundled": true,
1641 | "dev": true,
1642 | "optional": true,
1643 | "requires": {
1644 | "ms": "^2.1.1"
1645 | }
1646 | },
1647 | "deep-extend": {
1648 | "version": "0.6.0",
1649 | "bundled": true,
1650 | "dev": true,
1651 | "optional": true
1652 | },
1653 | "delegates": {
1654 | "version": "1.0.0",
1655 | "bundled": true,
1656 | "dev": true,
1657 | "optional": true
1658 | },
1659 | "detect-libc": {
1660 | "version": "1.0.3",
1661 | "bundled": true,
1662 | "dev": true,
1663 | "optional": true
1664 | },
1665 | "fs-minipass": {
1666 | "version": "1.2.5",
1667 | "bundled": true,
1668 | "dev": true,
1669 | "optional": true,
1670 | "requires": {
1671 | "minipass": "^2.2.1"
1672 | }
1673 | },
1674 | "fs.realpath": {
1675 | "version": "1.0.0",
1676 | "bundled": true,
1677 | "dev": true,
1678 | "optional": true
1679 | },
1680 | "gauge": {
1681 | "version": "2.7.4",
1682 | "bundled": true,
1683 | "dev": true,
1684 | "optional": true,
1685 | "requires": {
1686 | "aproba": "^1.0.3",
1687 | "console-control-strings": "^1.0.0",
1688 | "has-unicode": "^2.0.0",
1689 | "object-assign": "^4.1.0",
1690 | "signal-exit": "^3.0.0",
1691 | "string-width": "^1.0.1",
1692 | "strip-ansi": "^3.0.1",
1693 | "wide-align": "^1.1.0"
1694 | }
1695 | },
1696 | "glob": {
1697 | "version": "7.1.3",
1698 | "bundled": true,
1699 | "dev": true,
1700 | "optional": true,
1701 | "requires": {
1702 | "fs.realpath": "^1.0.0",
1703 | "inflight": "^1.0.4",
1704 | "inherits": "2",
1705 | "minimatch": "^3.0.4",
1706 | "once": "^1.3.0",
1707 | "path-is-absolute": "^1.0.0"
1708 | }
1709 | },
1710 | "has-unicode": {
1711 | "version": "2.0.1",
1712 | "bundled": true,
1713 | "dev": true,
1714 | "optional": true
1715 | },
1716 | "iconv-lite": {
1717 | "version": "0.4.24",
1718 | "bundled": true,
1719 | "dev": true,
1720 | "optional": true,
1721 | "requires": {
1722 | "safer-buffer": ">= 2.1.2 < 3"
1723 | }
1724 | },
1725 | "ignore-walk": {
1726 | "version": "3.0.1",
1727 | "bundled": true,
1728 | "dev": true,
1729 | "optional": true,
1730 | "requires": {
1731 | "minimatch": "^3.0.4"
1732 | }
1733 | },
1734 | "inflight": {
1735 | "version": "1.0.6",
1736 | "bundled": true,
1737 | "dev": true,
1738 | "optional": true,
1739 | "requires": {
1740 | "once": "^1.3.0",
1741 | "wrappy": "1"
1742 | }
1743 | },
1744 | "inherits": {
1745 | "version": "2.0.3",
1746 | "bundled": true,
1747 | "dev": true,
1748 | "optional": true
1749 | },
1750 | "ini": {
1751 | "version": "1.3.5",
1752 | "bundled": true,
1753 | "dev": true,
1754 | "optional": true
1755 | },
1756 | "is-fullwidth-code-point": {
1757 | "version": "1.0.0",
1758 | "bundled": true,
1759 | "dev": true,
1760 | "optional": true,
1761 | "requires": {
1762 | "number-is-nan": "^1.0.0"
1763 | }
1764 | },
1765 | "isarray": {
1766 | "version": "1.0.0",
1767 | "bundled": true,
1768 | "dev": true,
1769 | "optional": true
1770 | },
1771 | "minimatch": {
1772 | "version": "3.0.4",
1773 | "bundled": true,
1774 | "dev": true,
1775 | "optional": true,
1776 | "requires": {
1777 | "brace-expansion": "^1.1.7"
1778 | }
1779 | },
1780 | "minimist": {
1781 | "version": "0.0.8",
1782 | "bundled": true,
1783 | "dev": true,
1784 | "optional": true
1785 | },
1786 | "minipass": {
1787 | "version": "2.3.5",
1788 | "bundled": true,
1789 | "dev": true,
1790 | "optional": true,
1791 | "requires": {
1792 | "safe-buffer": "^5.1.2",
1793 | "yallist": "^3.0.0"
1794 | }
1795 | },
1796 | "minizlib": {
1797 | "version": "1.2.1",
1798 | "bundled": true,
1799 | "dev": true,
1800 | "optional": true,
1801 | "requires": {
1802 | "minipass": "^2.2.1"
1803 | }
1804 | },
1805 | "mkdirp": {
1806 | "version": "0.5.1",
1807 | "bundled": true,
1808 | "dev": true,
1809 | "optional": true,
1810 | "requires": {
1811 | "minimist": "0.0.8"
1812 | }
1813 | },
1814 | "ms": {
1815 | "version": "2.1.1",
1816 | "bundled": true,
1817 | "dev": true,
1818 | "optional": true
1819 | },
1820 | "needle": {
1821 | "version": "2.3.0",
1822 | "bundled": true,
1823 | "dev": true,
1824 | "optional": true,
1825 | "requires": {
1826 | "debug": "^4.1.0",
1827 | "iconv-lite": "^0.4.4",
1828 | "sax": "^1.2.4"
1829 | }
1830 | },
1831 | "node-pre-gyp": {
1832 | "version": "0.12.0",
1833 | "bundled": true,
1834 | "dev": true,
1835 | "optional": true,
1836 | "requires": {
1837 | "detect-libc": "^1.0.2",
1838 | "mkdirp": "^0.5.1",
1839 | "needle": "^2.2.1",
1840 | "nopt": "^4.0.1",
1841 | "npm-packlist": "^1.1.6",
1842 | "npmlog": "^4.0.2",
1843 | "rc": "^1.2.7",
1844 | "rimraf": "^2.6.1",
1845 | "semver": "^5.3.0",
1846 | "tar": "^4"
1847 | }
1848 | },
1849 | "nopt": {
1850 | "version": "4.0.1",
1851 | "bundled": true,
1852 | "dev": true,
1853 | "optional": true,
1854 | "requires": {
1855 | "abbrev": "1",
1856 | "osenv": "^0.1.4"
1857 | }
1858 | },
1859 | "npm-bundled": {
1860 | "version": "1.0.6",
1861 | "bundled": true,
1862 | "dev": true,
1863 | "optional": true
1864 | },
1865 | "npm-packlist": {
1866 | "version": "1.4.1",
1867 | "bundled": true,
1868 | "dev": true,
1869 | "optional": true,
1870 | "requires": {
1871 | "ignore-walk": "^3.0.1",
1872 | "npm-bundled": "^1.0.1"
1873 | }
1874 | },
1875 | "npmlog": {
1876 | "version": "4.1.2",
1877 | "bundled": true,
1878 | "dev": true,
1879 | "optional": true,
1880 | "requires": {
1881 | "are-we-there-yet": "~1.1.2",
1882 | "console-control-strings": "~1.1.0",
1883 | "gauge": "~2.7.3",
1884 | "set-blocking": "~2.0.0"
1885 | }
1886 | },
1887 | "number-is-nan": {
1888 | "version": "1.0.1",
1889 | "bundled": true,
1890 | "dev": true,
1891 | "optional": true
1892 | },
1893 | "object-assign": {
1894 | "version": "4.1.1",
1895 | "bundled": true,
1896 | "dev": true,
1897 | "optional": true
1898 | },
1899 | "once": {
1900 | "version": "1.4.0",
1901 | "bundled": true,
1902 | "dev": true,
1903 | "optional": true,
1904 | "requires": {
1905 | "wrappy": "1"
1906 | }
1907 | },
1908 | "os-homedir": {
1909 | "version": "1.0.2",
1910 | "bundled": true,
1911 | "dev": true,
1912 | "optional": true
1913 | },
1914 | "os-tmpdir": {
1915 | "version": "1.0.2",
1916 | "bundled": true,
1917 | "dev": true,
1918 | "optional": true
1919 | },
1920 | "osenv": {
1921 | "version": "0.1.5",
1922 | "bundled": true,
1923 | "dev": true,
1924 | "optional": true,
1925 | "requires": {
1926 | "os-homedir": "^1.0.0",
1927 | "os-tmpdir": "^1.0.0"
1928 | }
1929 | },
1930 | "path-is-absolute": {
1931 | "version": "1.0.1",
1932 | "bundled": true,
1933 | "dev": true,
1934 | "optional": true
1935 | },
1936 | "process-nextick-args": {
1937 | "version": "2.0.0",
1938 | "bundled": true,
1939 | "dev": true,
1940 | "optional": true
1941 | },
1942 | "rc": {
1943 | "version": "1.2.8",
1944 | "bundled": true,
1945 | "dev": true,
1946 | "optional": true,
1947 | "requires": {
1948 | "deep-extend": "^0.6.0",
1949 | "ini": "~1.3.0",
1950 | "minimist": "^1.2.0",
1951 | "strip-json-comments": "~2.0.1"
1952 | },
1953 | "dependencies": {
1954 | "minimist": {
1955 | "version": "1.2.0",
1956 | "bundled": true,
1957 | "dev": true,
1958 | "optional": true
1959 | }
1960 | }
1961 | },
1962 | "readable-stream": {
1963 | "version": "2.3.6",
1964 | "bundled": true,
1965 | "dev": true,
1966 | "optional": true,
1967 | "requires": {
1968 | "core-util-is": "~1.0.0",
1969 | "inherits": "~2.0.3",
1970 | "isarray": "~1.0.0",
1971 | "process-nextick-args": "~2.0.0",
1972 | "safe-buffer": "~5.1.1",
1973 | "string_decoder": "~1.1.1",
1974 | "util-deprecate": "~1.0.1"
1975 | }
1976 | },
1977 | "rimraf": {
1978 | "version": "2.6.3",
1979 | "bundled": true,
1980 | "dev": true,
1981 | "optional": true,
1982 | "requires": {
1983 | "glob": "^7.1.3"
1984 | }
1985 | },
1986 | "safe-buffer": {
1987 | "version": "5.1.2",
1988 | "bundled": true,
1989 | "dev": true,
1990 | "optional": true
1991 | },
1992 | "safer-buffer": {
1993 | "version": "2.1.2",
1994 | "bundled": true,
1995 | "dev": true,
1996 | "optional": true
1997 | },
1998 | "sax": {
1999 | "version": "1.2.4",
2000 | "bundled": true,
2001 | "dev": true,
2002 | "optional": true
2003 | },
2004 | "semver": {
2005 | "version": "5.7.0",
2006 | "bundled": true,
2007 | "dev": true,
2008 | "optional": true
2009 | },
2010 | "set-blocking": {
2011 | "version": "2.0.0",
2012 | "bundled": true,
2013 | "dev": true,
2014 | "optional": true
2015 | },
2016 | "signal-exit": {
2017 | "version": "3.0.2",
2018 | "bundled": true,
2019 | "dev": true,
2020 | "optional": true
2021 | },
2022 | "string-width": {
2023 | "version": "1.0.2",
2024 | "bundled": true,
2025 | "dev": true,
2026 | "optional": true,
2027 | "requires": {
2028 | "code-point-at": "^1.0.0",
2029 | "is-fullwidth-code-point": "^1.0.0",
2030 | "strip-ansi": "^3.0.0"
2031 | }
2032 | },
2033 | "string_decoder": {
2034 | "version": "1.1.1",
2035 | "bundled": true,
2036 | "dev": true,
2037 | "optional": true,
2038 | "requires": {
2039 | "safe-buffer": "~5.1.0"
2040 | }
2041 | },
2042 | "strip-ansi": {
2043 | "version": "3.0.1",
2044 | "bundled": true,
2045 | "dev": true,
2046 | "optional": true,
2047 | "requires": {
2048 | "ansi-regex": "^2.0.0"
2049 | }
2050 | },
2051 | "strip-json-comments": {
2052 | "version": "2.0.1",
2053 | "bundled": true,
2054 | "dev": true,
2055 | "optional": true
2056 | },
2057 | "tar": {
2058 | "version": "4.4.8",
2059 | "bundled": true,
2060 | "dev": true,
2061 | "optional": true,
2062 | "requires": {
2063 | "chownr": "^1.1.1",
2064 | "fs-minipass": "^1.2.5",
2065 | "minipass": "^2.3.4",
2066 | "minizlib": "^1.1.1",
2067 | "mkdirp": "^0.5.0",
2068 | "safe-buffer": "^5.1.2",
2069 | "yallist": "^3.0.2"
2070 | }
2071 | },
2072 | "util-deprecate": {
2073 | "version": "1.0.2",
2074 | "bundled": true,
2075 | "dev": true,
2076 | "optional": true
2077 | },
2078 | "wide-align": {
2079 | "version": "1.1.3",
2080 | "bundled": true,
2081 | "dev": true,
2082 | "optional": true,
2083 | "requires": {
2084 | "string-width": "^1.0.2 || 2"
2085 | }
2086 | },
2087 | "wrappy": {
2088 | "version": "1.0.2",
2089 | "bundled": true,
2090 | "dev": true,
2091 | "optional": true
2092 | },
2093 | "yallist": {
2094 | "version": "3.0.3",
2095 | "bundled": true,
2096 | "dev": true,
2097 | "optional": true
2098 | }
2099 | }
2100 | },
2101 | "function-bind": {
2102 | "version": "1.1.1",
2103 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
2104 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
2105 | "dev": true
2106 | },
2107 | "get-value": {
2108 | "version": "2.0.6",
2109 | "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
2110 | "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
2111 | "dev": true,
2112 | "optional": true
2113 | },
2114 | "glob": {
2115 | "version": "7.1.4",
2116 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
2117 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
2118 | "dev": true,
2119 | "requires": {
2120 | "fs.realpath": "^1.0.0",
2121 | "inflight": "^1.0.4",
2122 | "inherits": "2",
2123 | "minimatch": "^3.0.4",
2124 | "once": "^1.3.0",
2125 | "path-is-absolute": "^1.0.0"
2126 | }
2127 | },
2128 | "glob-parent": {
2129 | "version": "3.1.0",
2130 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
2131 | "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
2132 | "dev": true,
2133 | "optional": true,
2134 | "requires": {
2135 | "is-glob": "^3.1.0",
2136 | "path-dirname": "^1.0.0"
2137 | },
2138 | "dependencies": {
2139 | "is-glob": {
2140 | "version": "3.1.0",
2141 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
2142 | "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
2143 | "dev": true,
2144 | "optional": true,
2145 | "requires": {
2146 | "is-extglob": "^2.1.0"
2147 | }
2148 | }
2149 | }
2150 | },
2151 | "globals": {
2152 | "version": "11.12.0",
2153 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
2154 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
2155 | "dev": true
2156 | },
2157 | "graceful-fs": {
2158 | "version": "4.2.2",
2159 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
2160 | "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
2161 | "dev": true
2162 | },
2163 | "has-flag": {
2164 | "version": "3.0.0",
2165 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
2166 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
2167 | "dev": true
2168 | },
2169 | "has-symbols": {
2170 | "version": "1.0.0",
2171 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
2172 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
2173 | "dev": true
2174 | },
2175 | "has-value": {
2176 | "version": "1.0.0",
2177 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
2178 | "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
2179 | "dev": true,
2180 | "optional": true,
2181 | "requires": {
2182 | "get-value": "^2.0.6",
2183 | "has-values": "^1.0.0",
2184 | "isobject": "^3.0.0"
2185 | }
2186 | },
2187 | "has-values": {
2188 | "version": "1.0.0",
2189 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
2190 | "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
2191 | "dev": true,
2192 | "optional": true,
2193 | "requires": {
2194 | "is-number": "^3.0.0",
2195 | "kind-of": "^4.0.0"
2196 | },
2197 | "dependencies": {
2198 | "kind-of": {
2199 | "version": "4.0.0",
2200 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
2201 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
2202 | "dev": true,
2203 | "optional": true,
2204 | "requires": {
2205 | "is-buffer": "^1.1.5"
2206 | }
2207 | }
2208 | }
2209 | },
2210 | "inflight": {
2211 | "version": "1.0.6",
2212 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
2213 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
2214 | "dev": true,
2215 | "requires": {
2216 | "once": "^1.3.0",
2217 | "wrappy": "1"
2218 | }
2219 | },
2220 | "inherits": {
2221 | "version": "2.0.4",
2222 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
2223 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
2224 | "dev": true
2225 | },
2226 | "invariant": {
2227 | "version": "2.2.4",
2228 | "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
2229 | "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
2230 | "dev": true,
2231 | "requires": {
2232 | "loose-envify": "^1.0.0"
2233 | }
2234 | },
2235 | "is-accessor-descriptor": {
2236 | "version": "0.1.6",
2237 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
2238 | "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
2239 | "dev": true,
2240 | "optional": true,
2241 | "requires": {
2242 | "kind-of": "^3.0.2"
2243 | },
2244 | "dependencies": {
2245 | "kind-of": {
2246 | "version": "3.2.2",
2247 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
2248 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
2249 | "dev": true,
2250 | "optional": true,
2251 | "requires": {
2252 | "is-buffer": "^1.1.5"
2253 | }
2254 | }
2255 | }
2256 | },
2257 | "is-binary-path": {
2258 | "version": "1.0.1",
2259 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
2260 | "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
2261 | "dev": true,
2262 | "optional": true,
2263 | "requires": {
2264 | "binary-extensions": "^1.0.0"
2265 | }
2266 | },
2267 | "is-buffer": {
2268 | "version": "1.1.6",
2269 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
2270 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
2271 | "dev": true,
2272 | "optional": true
2273 | },
2274 | "is-data-descriptor": {
2275 | "version": "0.1.4",
2276 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
2277 | "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
2278 | "dev": true,
2279 | "optional": true,
2280 | "requires": {
2281 | "kind-of": "^3.0.2"
2282 | },
2283 | "dependencies": {
2284 | "kind-of": {
2285 | "version": "3.2.2",
2286 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
2287 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
2288 | "dev": true,
2289 | "optional": true,
2290 | "requires": {
2291 | "is-buffer": "^1.1.5"
2292 | }
2293 | }
2294 | }
2295 | },
2296 | "is-descriptor": {
2297 | "version": "0.1.6",
2298 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
2299 | "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
2300 | "dev": true,
2301 | "optional": true,
2302 | "requires": {
2303 | "is-accessor-descriptor": "^0.1.6",
2304 | "is-data-descriptor": "^0.1.4",
2305 | "kind-of": "^5.0.0"
2306 | },
2307 | "dependencies": {
2308 | "kind-of": {
2309 | "version": "5.1.0",
2310 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
2311 | "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
2312 | "dev": true,
2313 | "optional": true
2314 | }
2315 | }
2316 | },
2317 | "is-extendable": {
2318 | "version": "0.1.1",
2319 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
2320 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
2321 | "dev": true,
2322 | "optional": true
2323 | },
2324 | "is-extglob": {
2325 | "version": "2.1.1",
2326 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
2327 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
2328 | "dev": true,
2329 | "optional": true
2330 | },
2331 | "is-glob": {
2332 | "version": "4.0.1",
2333 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
2334 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
2335 | "dev": true,
2336 | "optional": true,
2337 | "requires": {
2338 | "is-extglob": "^2.1.1"
2339 | }
2340 | },
2341 | "is-number": {
2342 | "version": "3.0.0",
2343 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
2344 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
2345 | "dev": true,
2346 | "optional": true,
2347 | "requires": {
2348 | "kind-of": "^3.0.2"
2349 | },
2350 | "dependencies": {
2351 | "kind-of": {
2352 | "version": "3.2.2",
2353 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
2354 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
2355 | "dev": true,
2356 | "optional": true,
2357 | "requires": {
2358 | "is-buffer": "^1.1.5"
2359 | }
2360 | }
2361 | }
2362 | },
2363 | "is-plain-obj": {
2364 | "version": "1.1.0",
2365 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
2366 | "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
2367 | "dev": true
2368 | },
2369 | "is-plain-object": {
2370 | "version": "2.0.4",
2371 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
2372 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
2373 | "dev": true,
2374 | "optional": true,
2375 | "requires": {
2376 | "isobject": "^3.0.1"
2377 | }
2378 | },
2379 | "is-windows": {
2380 | "version": "1.0.2",
2381 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
2382 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
2383 | "dev": true,
2384 | "optional": true
2385 | },
2386 | "isarray": {
2387 | "version": "1.0.0",
2388 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
2389 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
2390 | "dev": true,
2391 | "optional": true
2392 | },
2393 | "isobject": {
2394 | "version": "3.0.1",
2395 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
2396 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
2397 | "dev": true,
2398 | "optional": true
2399 | },
2400 | "js-levenshtein": {
2401 | "version": "1.1.6",
2402 | "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
2403 | "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
2404 | "dev": true
2405 | },
2406 | "js-tokens": {
2407 | "version": "4.0.0",
2408 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
2409 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
2410 | },
2411 | "jsesc": {
2412 | "version": "2.5.2",
2413 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
2414 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
2415 | "dev": true
2416 | },
2417 | "json5": {
2418 | "version": "2.1.0",
2419 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
2420 | "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
2421 | "dev": true,
2422 | "requires": {
2423 | "minimist": "^1.2.0"
2424 | }
2425 | },
2426 | "kind-of": {
2427 | "version": "6.0.2",
2428 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
2429 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
2430 | "dev": true,
2431 | "optional": true
2432 | },
2433 | "lodash": {
2434 | "version": "4.17.15",
2435 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
2436 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
2437 | "dev": true
2438 | },
2439 | "loose-envify": {
2440 | "version": "1.4.0",
2441 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
2442 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
2443 | "requires": {
2444 | "js-tokens": "^3.0.0 || ^4.0.0"
2445 | }
2446 | },
2447 | "map-cache": {
2448 | "version": "0.2.2",
2449 | "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
2450 | "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
2451 | "dev": true,
2452 | "optional": true
2453 | },
2454 | "map-visit": {
2455 | "version": "1.0.0",
2456 | "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
2457 | "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
2458 | "dev": true,
2459 | "optional": true,
2460 | "requires": {
2461 | "object-visit": "^1.0.0"
2462 | }
2463 | },
2464 | "micromatch": {
2465 | "version": "3.1.10",
2466 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
2467 | "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
2468 | "dev": true,
2469 | "optional": true,
2470 | "requires": {
2471 | "arr-diff": "^4.0.0",
2472 | "array-unique": "^0.3.2",
2473 | "braces": "^2.3.1",
2474 | "define-property": "^2.0.2",
2475 | "extend-shallow": "^3.0.2",
2476 | "extglob": "^2.0.4",
2477 | "fragment-cache": "^0.2.1",
2478 | "kind-of": "^6.0.2",
2479 | "nanomatch": "^1.2.9",
2480 | "object.pick": "^1.3.0",
2481 | "regex-not": "^1.0.0",
2482 | "snapdragon": "^0.8.1",
2483 | "to-regex": "^3.0.2"
2484 | }
2485 | },
2486 | "minimatch": {
2487 | "version": "3.0.4",
2488 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
2489 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
2490 | "dev": true,
2491 | "requires": {
2492 | "brace-expansion": "^1.1.7"
2493 | }
2494 | },
2495 | "minimist": {
2496 | "version": "1.2.0",
2497 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
2498 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
2499 | "dev": true
2500 | },
2501 | "mixin-deep": {
2502 | "version": "1.3.2",
2503 | "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
2504 | "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
2505 | "dev": true,
2506 | "optional": true,
2507 | "requires": {
2508 | "for-in": "^1.0.2",
2509 | "is-extendable": "^1.0.1"
2510 | },
2511 | "dependencies": {
2512 | "is-extendable": {
2513 | "version": "1.0.1",
2514 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
2515 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
2516 | "dev": true,
2517 | "optional": true,
2518 | "requires": {
2519 | "is-plain-object": "^2.0.4"
2520 | }
2521 | }
2522 | }
2523 | },
2524 | "mkdirp": {
2525 | "version": "0.5.1",
2526 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
2527 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
2528 | "dev": true,
2529 | "requires": {
2530 | "minimist": "0.0.8"
2531 | },
2532 | "dependencies": {
2533 | "minimist": {
2534 | "version": "0.0.8",
2535 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
2536 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
2537 | "dev": true
2538 | }
2539 | }
2540 | },
2541 | "ms": {
2542 | "version": "2.1.2",
2543 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
2544 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
2545 | "dev": true
2546 | },
2547 | "nan": {
2548 | "version": "2.14.0",
2549 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
2550 | "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
2551 | "dev": true,
2552 | "optional": true
2553 | },
2554 | "nanomatch": {
2555 | "version": "1.2.13",
2556 | "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
2557 | "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
2558 | "dev": true,
2559 | "optional": true,
2560 | "requires": {
2561 | "arr-diff": "^4.0.0",
2562 | "array-unique": "^0.3.2",
2563 | "define-property": "^2.0.2",
2564 | "extend-shallow": "^3.0.2",
2565 | "fragment-cache": "^0.2.1",
2566 | "is-windows": "^1.0.2",
2567 | "kind-of": "^6.0.2",
2568 | "object.pick": "^1.3.0",
2569 | "regex-not": "^1.0.0",
2570 | "snapdragon": "^0.8.1",
2571 | "to-regex": "^3.0.1"
2572 | }
2573 | },
2574 | "node-releases": {
2575 | "version": "1.1.27",
2576 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.27.tgz",
2577 | "integrity": "sha512-9iXUqHKSGo6ph/tdXVbHFbhRVQln4ZDTIBJCzsa90HimnBYc5jw8RWYt4wBYFHehGyC3koIz5O4mb2fHrbPOuA==",
2578 | "dev": true,
2579 | "requires": {
2580 | "semver": "^5.3.0"
2581 | }
2582 | },
2583 | "normalize-path": {
2584 | "version": "3.0.0",
2585 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
2586 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
2587 | "dev": true,
2588 | "optional": true
2589 | },
2590 | "object-assign": {
2591 | "version": "4.1.1",
2592 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
2593 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
2594 | },
2595 | "object-copy": {
2596 | "version": "0.1.0",
2597 | "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
2598 | "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
2599 | "dev": true,
2600 | "optional": true,
2601 | "requires": {
2602 | "copy-descriptor": "^0.1.0",
2603 | "define-property": "^0.2.5",
2604 | "kind-of": "^3.0.3"
2605 | },
2606 | "dependencies": {
2607 | "define-property": {
2608 | "version": "0.2.5",
2609 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
2610 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
2611 | "dev": true,
2612 | "optional": true,
2613 | "requires": {
2614 | "is-descriptor": "^0.1.0"
2615 | }
2616 | },
2617 | "kind-of": {
2618 | "version": "3.2.2",
2619 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
2620 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
2621 | "dev": true,
2622 | "optional": true,
2623 | "requires": {
2624 | "is-buffer": "^1.1.5"
2625 | }
2626 | }
2627 | }
2628 | },
2629 | "object-keys": {
2630 | "version": "1.1.1",
2631 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
2632 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
2633 | "dev": true
2634 | },
2635 | "object-visit": {
2636 | "version": "1.0.1",
2637 | "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
2638 | "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
2639 | "dev": true,
2640 | "optional": true,
2641 | "requires": {
2642 | "isobject": "^3.0.0"
2643 | }
2644 | },
2645 | "object.assign": {
2646 | "version": "4.1.0",
2647 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
2648 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
2649 | "dev": true,
2650 | "requires": {
2651 | "define-properties": "^1.1.2",
2652 | "function-bind": "^1.1.1",
2653 | "has-symbols": "^1.0.0",
2654 | "object-keys": "^1.0.11"
2655 | }
2656 | },
2657 | "object.pick": {
2658 | "version": "1.3.0",
2659 | "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
2660 | "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
2661 | "dev": true,
2662 | "optional": true,
2663 | "requires": {
2664 | "isobject": "^3.0.1"
2665 | }
2666 | },
2667 | "once": {
2668 | "version": "1.4.0",
2669 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
2670 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
2671 | "dev": true,
2672 | "requires": {
2673 | "wrappy": "1"
2674 | }
2675 | },
2676 | "output-file-sync": {
2677 | "version": "2.0.1",
2678 | "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz",
2679 | "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==",
2680 | "dev": true,
2681 | "requires": {
2682 | "graceful-fs": "^4.1.11",
2683 | "is-plain-obj": "^1.1.0",
2684 | "mkdirp": "^0.5.1"
2685 | }
2686 | },
2687 | "pascalcase": {
2688 | "version": "0.1.1",
2689 | "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
2690 | "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
2691 | "dev": true,
2692 | "optional": true
2693 | },
2694 | "path-dirname": {
2695 | "version": "1.0.2",
2696 | "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
2697 | "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
2698 | "dev": true,
2699 | "optional": true
2700 | },
2701 | "path-is-absolute": {
2702 | "version": "1.0.1",
2703 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
2704 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
2705 | "dev": true
2706 | },
2707 | "path-parse": {
2708 | "version": "1.0.6",
2709 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
2710 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
2711 | "dev": true
2712 | },
2713 | "posix-character-classes": {
2714 | "version": "0.1.1",
2715 | "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
2716 | "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
2717 | "dev": true,
2718 | "optional": true
2719 | },
2720 | "private": {
2721 | "version": "0.1.8",
2722 | "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
2723 | "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
2724 | "dev": true
2725 | },
2726 | "process-nextick-args": {
2727 | "version": "2.0.1",
2728 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
2729 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
2730 | "dev": true,
2731 | "optional": true
2732 | },
2733 | "prop-types": {
2734 | "version": "15.7.2",
2735 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
2736 | "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
2737 | "requires": {
2738 | "loose-envify": "^1.4.0",
2739 | "object-assign": "^4.1.1",
2740 | "react-is": "^16.8.1"
2741 | }
2742 | },
2743 | "react": {
2744 | "version": "16.9.0",
2745 | "resolved": "https://registry.npmjs.org/react/-/react-16.9.0.tgz",
2746 | "integrity": "sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==",
2747 | "requires": {
2748 | "loose-envify": "^1.1.0",
2749 | "object-assign": "^4.1.1",
2750 | "prop-types": "^15.6.2"
2751 | }
2752 | },
2753 | "react-is": {
2754 | "version": "16.9.0",
2755 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
2756 | "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw=="
2757 | },
2758 | "readable-stream": {
2759 | "version": "2.3.6",
2760 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
2761 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
2762 | "dev": true,
2763 | "optional": true,
2764 | "requires": {
2765 | "core-util-is": "~1.0.0",
2766 | "inherits": "~2.0.3",
2767 | "isarray": "~1.0.0",
2768 | "process-nextick-args": "~2.0.0",
2769 | "safe-buffer": "~5.1.1",
2770 | "string_decoder": "~1.1.1",
2771 | "util-deprecate": "~1.0.1"
2772 | }
2773 | },
2774 | "readdirp": {
2775 | "version": "2.2.1",
2776 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
2777 | "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
2778 | "dev": true,
2779 | "optional": true,
2780 | "requires": {
2781 | "graceful-fs": "^4.1.11",
2782 | "micromatch": "^3.1.10",
2783 | "readable-stream": "^2.0.2"
2784 | }
2785 | },
2786 | "regenerate": {
2787 | "version": "1.4.0",
2788 | "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
2789 | "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
2790 | "dev": true
2791 | },
2792 | "regenerate-unicode-properties": {
2793 | "version": "8.1.0",
2794 | "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz",
2795 | "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==",
2796 | "dev": true,
2797 | "requires": {
2798 | "regenerate": "^1.4.0"
2799 | }
2800 | },
2801 | "regenerator-transform": {
2802 | "version": "0.14.1",
2803 | "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz",
2804 | "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==",
2805 | "dev": true,
2806 | "requires": {
2807 | "private": "^0.1.6"
2808 | }
2809 | },
2810 | "regex-not": {
2811 | "version": "1.0.2",
2812 | "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
2813 | "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
2814 | "dev": true,
2815 | "optional": true,
2816 | "requires": {
2817 | "extend-shallow": "^3.0.2",
2818 | "safe-regex": "^1.1.0"
2819 | }
2820 | },
2821 | "regexp-tree": {
2822 | "version": "0.1.11",
2823 | "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.11.tgz",
2824 | "integrity": "sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg==",
2825 | "dev": true
2826 | },
2827 | "regexpu-core": {
2828 | "version": "4.5.5",
2829 | "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz",
2830 | "integrity": "sha512-FpI67+ky9J+cDizQUJlIlNZFKual/lUkFr1AG6zOCpwZ9cLrg8UUVakyUQJD7fCDIe9Z2nwTQJNPyonatNmDFQ==",
2831 | "dev": true,
2832 | "requires": {
2833 | "regenerate": "^1.4.0",
2834 | "regenerate-unicode-properties": "^8.1.0",
2835 | "regjsgen": "^0.5.0",
2836 | "regjsparser": "^0.6.0",
2837 | "unicode-match-property-ecmascript": "^1.0.4",
2838 | "unicode-match-property-value-ecmascript": "^1.1.0"
2839 | }
2840 | },
2841 | "regjsgen": {
2842 | "version": "0.5.0",
2843 | "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz",
2844 | "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==",
2845 | "dev": true
2846 | },
2847 | "regjsparser": {
2848 | "version": "0.6.0",
2849 | "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz",
2850 | "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==",
2851 | "dev": true,
2852 | "requires": {
2853 | "jsesc": "~0.5.0"
2854 | },
2855 | "dependencies": {
2856 | "jsesc": {
2857 | "version": "0.5.0",
2858 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
2859 | "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
2860 | "dev": true
2861 | }
2862 | }
2863 | },
2864 | "remove-trailing-separator": {
2865 | "version": "1.1.0",
2866 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
2867 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
2868 | "dev": true,
2869 | "optional": true
2870 | },
2871 | "repeat-element": {
2872 | "version": "1.1.3",
2873 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
2874 | "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
2875 | "dev": true,
2876 | "optional": true
2877 | },
2878 | "repeat-string": {
2879 | "version": "1.6.1",
2880 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
2881 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
2882 | "dev": true,
2883 | "optional": true
2884 | },
2885 | "resolve": {
2886 | "version": "1.12.0",
2887 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
2888 | "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
2889 | "dev": true,
2890 | "requires": {
2891 | "path-parse": "^1.0.6"
2892 | }
2893 | },
2894 | "resolve-url": {
2895 | "version": "0.2.1",
2896 | "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
2897 | "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
2898 | "dev": true,
2899 | "optional": true
2900 | },
2901 | "ret": {
2902 | "version": "0.1.15",
2903 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
2904 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
2905 | "dev": true,
2906 | "optional": true
2907 | },
2908 | "safe-buffer": {
2909 | "version": "5.1.2",
2910 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
2911 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
2912 | "dev": true
2913 | },
2914 | "safe-regex": {
2915 | "version": "1.1.0",
2916 | "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
2917 | "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
2918 | "dev": true,
2919 | "optional": true,
2920 | "requires": {
2921 | "ret": "~0.1.10"
2922 | }
2923 | },
2924 | "semver": {
2925 | "version": "5.7.1",
2926 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
2927 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
2928 | "dev": true
2929 | },
2930 | "set-value": {
2931 | "version": "2.0.1",
2932 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
2933 | "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
2934 | "dev": true,
2935 | "optional": true,
2936 | "requires": {
2937 | "extend-shallow": "^2.0.1",
2938 | "is-extendable": "^0.1.1",
2939 | "is-plain-object": "^2.0.3",
2940 | "split-string": "^3.0.1"
2941 | },
2942 | "dependencies": {
2943 | "extend-shallow": {
2944 | "version": "2.0.1",
2945 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
2946 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
2947 | "dev": true,
2948 | "optional": true,
2949 | "requires": {
2950 | "is-extendable": "^0.1.0"
2951 | }
2952 | }
2953 | }
2954 | },
2955 | "slash": {
2956 | "version": "2.0.0",
2957 | "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
2958 | "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
2959 | "dev": true
2960 | },
2961 | "snapdragon": {
2962 | "version": "0.8.2",
2963 | "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
2964 | "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
2965 | "dev": true,
2966 | "optional": true,
2967 | "requires": {
2968 | "base": "^0.11.1",
2969 | "debug": "^2.2.0",
2970 | "define-property": "^0.2.5",
2971 | "extend-shallow": "^2.0.1",
2972 | "map-cache": "^0.2.2",
2973 | "source-map": "^0.5.6",
2974 | "source-map-resolve": "^0.5.0",
2975 | "use": "^3.1.0"
2976 | },
2977 | "dependencies": {
2978 | "define-property": {
2979 | "version": "0.2.5",
2980 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
2981 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
2982 | "dev": true,
2983 | "optional": true,
2984 | "requires": {
2985 | "is-descriptor": "^0.1.0"
2986 | }
2987 | },
2988 | "extend-shallow": {
2989 | "version": "2.0.1",
2990 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
2991 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
2992 | "dev": true,
2993 | "optional": true,
2994 | "requires": {
2995 | "is-extendable": "^0.1.0"
2996 | }
2997 | }
2998 | }
2999 | },
3000 | "snapdragon-node": {
3001 | "version": "2.1.1",
3002 | "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
3003 | "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
3004 | "dev": true,
3005 | "optional": true,
3006 | "requires": {
3007 | "define-property": "^1.0.0",
3008 | "isobject": "^3.0.0",
3009 | "snapdragon-util": "^3.0.1"
3010 | },
3011 | "dependencies": {
3012 | "define-property": {
3013 | "version": "1.0.0",
3014 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
3015 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
3016 | "dev": true,
3017 | "optional": true,
3018 | "requires": {
3019 | "is-descriptor": "^1.0.0"
3020 | }
3021 | },
3022 | "is-accessor-descriptor": {
3023 | "version": "1.0.0",
3024 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
3025 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
3026 | "dev": true,
3027 | "optional": true,
3028 | "requires": {
3029 | "kind-of": "^6.0.0"
3030 | }
3031 | },
3032 | "is-data-descriptor": {
3033 | "version": "1.0.0",
3034 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
3035 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
3036 | "dev": true,
3037 | "optional": true,
3038 | "requires": {
3039 | "kind-of": "^6.0.0"
3040 | }
3041 | },
3042 | "is-descriptor": {
3043 | "version": "1.0.2",
3044 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
3045 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
3046 | "dev": true,
3047 | "optional": true,
3048 | "requires": {
3049 | "is-accessor-descriptor": "^1.0.0",
3050 | "is-data-descriptor": "^1.0.0",
3051 | "kind-of": "^6.0.2"
3052 | }
3053 | }
3054 | }
3055 | },
3056 | "snapdragon-util": {
3057 | "version": "3.0.1",
3058 | "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
3059 | "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
3060 | "dev": true,
3061 | "optional": true,
3062 | "requires": {
3063 | "kind-of": "^3.2.0"
3064 | },
3065 | "dependencies": {
3066 | "kind-of": {
3067 | "version": "3.2.2",
3068 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
3069 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
3070 | "dev": true,
3071 | "optional": true,
3072 | "requires": {
3073 | "is-buffer": "^1.1.5"
3074 | }
3075 | }
3076 | }
3077 | },
3078 | "source-map": {
3079 | "version": "0.5.7",
3080 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
3081 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
3082 | "dev": true
3083 | },
3084 | "source-map-resolve": {
3085 | "version": "0.5.2",
3086 | "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
3087 | "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
3088 | "dev": true,
3089 | "optional": true,
3090 | "requires": {
3091 | "atob": "^2.1.1",
3092 | "decode-uri-component": "^0.2.0",
3093 | "resolve-url": "^0.2.1",
3094 | "source-map-url": "^0.4.0",
3095 | "urix": "^0.1.0"
3096 | }
3097 | },
3098 | "source-map-url": {
3099 | "version": "0.4.0",
3100 | "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
3101 | "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
3102 | "dev": true,
3103 | "optional": true
3104 | },
3105 | "split-string": {
3106 | "version": "3.1.0",
3107 | "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
3108 | "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
3109 | "dev": true,
3110 | "optional": true,
3111 | "requires": {
3112 | "extend-shallow": "^3.0.0"
3113 | }
3114 | },
3115 | "static-extend": {
3116 | "version": "0.1.2",
3117 | "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
3118 | "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
3119 | "dev": true,
3120 | "optional": true,
3121 | "requires": {
3122 | "define-property": "^0.2.5",
3123 | "object-copy": "^0.1.0"
3124 | },
3125 | "dependencies": {
3126 | "define-property": {
3127 | "version": "0.2.5",
3128 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
3129 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
3130 | "dev": true,
3131 | "optional": true,
3132 | "requires": {
3133 | "is-descriptor": "^0.1.0"
3134 | }
3135 | }
3136 | }
3137 | },
3138 | "string_decoder": {
3139 | "version": "1.1.1",
3140 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
3141 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
3142 | "dev": true,
3143 | "optional": true,
3144 | "requires": {
3145 | "safe-buffer": "~5.1.0"
3146 | }
3147 | },
3148 | "supports-color": {
3149 | "version": "5.5.0",
3150 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
3151 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
3152 | "dev": true,
3153 | "requires": {
3154 | "has-flag": "^3.0.0"
3155 | }
3156 | },
3157 | "to-fast-properties": {
3158 | "version": "2.0.0",
3159 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
3160 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
3161 | "dev": true
3162 | },
3163 | "to-object-path": {
3164 | "version": "0.3.0",
3165 | "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
3166 | "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
3167 | "dev": true,
3168 | "optional": true,
3169 | "requires": {
3170 | "kind-of": "^3.0.2"
3171 | },
3172 | "dependencies": {
3173 | "kind-of": {
3174 | "version": "3.2.2",
3175 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
3176 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
3177 | "dev": true,
3178 | "optional": true,
3179 | "requires": {
3180 | "is-buffer": "^1.1.5"
3181 | }
3182 | }
3183 | }
3184 | },
3185 | "to-regex": {
3186 | "version": "3.0.2",
3187 | "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
3188 | "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
3189 | "dev": true,
3190 | "optional": true,
3191 | "requires": {
3192 | "define-property": "^2.0.2",
3193 | "extend-shallow": "^3.0.2",
3194 | "regex-not": "^1.0.2",
3195 | "safe-regex": "^1.1.0"
3196 | }
3197 | },
3198 | "to-regex-range": {
3199 | "version": "2.1.1",
3200 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
3201 | "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
3202 | "dev": true,
3203 | "optional": true,
3204 | "requires": {
3205 | "is-number": "^3.0.0",
3206 | "repeat-string": "^1.6.1"
3207 | }
3208 | },
3209 | "trim-right": {
3210 | "version": "1.0.1",
3211 | "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
3212 | "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
3213 | "dev": true
3214 | },
3215 | "unicode-canonical-property-names-ecmascript": {
3216 | "version": "1.0.4",
3217 | "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
3218 | "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==",
3219 | "dev": true
3220 | },
3221 | "unicode-match-property-ecmascript": {
3222 | "version": "1.0.4",
3223 | "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
3224 | "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
3225 | "dev": true,
3226 | "requires": {
3227 | "unicode-canonical-property-names-ecmascript": "^1.0.4",
3228 | "unicode-property-aliases-ecmascript": "^1.0.4"
3229 | }
3230 | },
3231 | "unicode-match-property-value-ecmascript": {
3232 | "version": "1.1.0",
3233 | "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz",
3234 | "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==",
3235 | "dev": true
3236 | },
3237 | "unicode-property-aliases-ecmascript": {
3238 | "version": "1.0.5",
3239 | "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz",
3240 | "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==",
3241 | "dev": true
3242 | },
3243 | "union-value": {
3244 | "version": "1.0.1",
3245 | "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
3246 | "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
3247 | "dev": true,
3248 | "optional": true,
3249 | "requires": {
3250 | "arr-union": "^3.1.0",
3251 | "get-value": "^2.0.6",
3252 | "is-extendable": "^0.1.1",
3253 | "set-value": "^2.0.1"
3254 | }
3255 | },
3256 | "unset-value": {
3257 | "version": "1.0.0",
3258 | "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
3259 | "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
3260 | "dev": true,
3261 | "optional": true,
3262 | "requires": {
3263 | "has-value": "^0.3.1",
3264 | "isobject": "^3.0.0"
3265 | },
3266 | "dependencies": {
3267 | "has-value": {
3268 | "version": "0.3.1",
3269 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
3270 | "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
3271 | "dev": true,
3272 | "optional": true,
3273 | "requires": {
3274 | "get-value": "^2.0.3",
3275 | "has-values": "^0.1.4",
3276 | "isobject": "^2.0.0"
3277 | },
3278 | "dependencies": {
3279 | "isobject": {
3280 | "version": "2.1.0",
3281 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
3282 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
3283 | "dev": true,
3284 | "optional": true,
3285 | "requires": {
3286 | "isarray": "1.0.0"
3287 | }
3288 | }
3289 | }
3290 | },
3291 | "has-values": {
3292 | "version": "0.1.4",
3293 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
3294 | "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
3295 | "dev": true,
3296 | "optional": true
3297 | }
3298 | }
3299 | },
3300 | "upath": {
3301 | "version": "1.1.2",
3302 | "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
3303 | "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
3304 | "dev": true,
3305 | "optional": true
3306 | },
3307 | "urix": {
3308 | "version": "0.1.0",
3309 | "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
3310 | "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
3311 | "dev": true,
3312 | "optional": true
3313 | },
3314 | "use": {
3315 | "version": "3.1.1",
3316 | "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
3317 | "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
3318 | "dev": true,
3319 | "optional": true
3320 | },
3321 | "util-deprecate": {
3322 | "version": "1.0.2",
3323 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
3324 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
3325 | "dev": true,
3326 | "optional": true
3327 | },
3328 | "wrappy": {
3329 | "version": "1.0.2",
3330 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
3331 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
3332 | "dev": true
3333 | }
3334 | }
3335 | }
3336 |
--------------------------------------------------------------------------------
/packages/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@glue/react",
3 | "version": "0.0.1",
4 | "description": "",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Josh Nussbaum",
10 | "license": "ISC",
11 | "peerDependencies": {
12 | "react": "16.x",
13 | "@glue/core": "../core"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/react/src/index.js:
--------------------------------------------------------------------------------
1 | import {useState, useEffect} from 'react'
2 | import {call, subscribe, unsubscribe} from '@glue/core'
3 |
4 | const hooks = JSON.parse(document.querySelector('script#hooks').innerHTML)
5 | const actors = new Map()
6 |
7 | function parseKeys(options) {
8 | const key = options['key']
9 |
10 | if (!key) return []
11 | if (Array.isArray(key)) return key
12 |
13 | return [key]
14 | }
15 |
16 | function getOrCreateActor(actorName, keys, config, options) {
17 | const {access} = config
18 | const fullName = [actorName, ...keys]
19 | const eventName = `${actorName}:changed:${keys.join(':')}`
20 | let actor = actors[fullName]
21 |
22 | if (actor) return actor
23 |
24 | actor = {
25 | value: access.default,
26 | sync: options.sync,
27 | listeners: [],
28 | subscription: null,
29 | addListener(callback) {
30 | this.listeners.push(callback)
31 |
32 | if (this.sync && !this.subscription) {
33 | this.subscription = subscribe(eventName, ({state}) => this.update(state))
34 | }
35 |
36 | callback(this.value)
37 | },
38 | removeListener(callback) {
39 | const index = this.listeners.indexOf(callback)
40 | if (index) this.listeners.splice(index, 1)
41 |
42 | if (this.sync && this.listeners.length === 0) {
43 | unsubscribe(eventName, this.subscription)
44 | }
45 | },
46 | update(newValue) {
47 | this.value = newValue
48 | this.listeners.forEach(cb => cb(newValue))
49 | }
50 | }
51 |
52 | actors[fullName] = actor
53 |
54 | call(`${actorName}:${access.action}`, keys).then(({state}) => actor.update(state))
55 |
56 | return actor
57 | }
58 |
59 | export function useServerState(actorName, options={}) {
60 | const config = hooks[actorName]
61 |
62 | if (!config) {
63 | console.error(`Hook not defined in config/hooks.exs for ${name}`)
64 | return
65 | }
66 |
67 | const {access, calls} = config
68 | const keys = parseKeys(options)
69 | const label = access['label'] || access.action
70 | const actor = getOrCreateActor(actorName, keys, config, options)
71 | const [value, set] = useState(actor.value)
72 |
73 | useEffect(() => {
74 | actor.addListener(set)
75 |
76 | return () => actor.removeListener(set)
77 | }, [actorName])
78 |
79 | const operations = {}
80 |
81 | operations[label] = value
82 |
83 | calls.forEach(callName => {
84 | operations[callName] = async (...args) => {
85 | const result = await call(`${actorName}:${callName}`, keys, args)
86 |
87 | if (!result.success) {
88 | throw Error(result.value)
89 | }
90 |
91 | actor.update(result.state)
92 |
93 | return result.value
94 | }
95 | })
96 |
97 | return operations
98 | }
99 |
--------------------------------------------------------------------------------
/packages/react/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 |
--------------------------------------------------------------------------------