From 63f132c820dec5c55c370dddb22edf3a36d69a42 Mon Sep 17 00:00:00 2001 From: Amir Raminfar Date: Mon, 25 Nov 2019 15:26:42 -0800 Subject: [PATCH] Adds the ability to split panes and view multiple logs (#186) * Fixes css to have full containers * Adds split panes * Fixes background color * Fixes splitter * Fixes tests * Adds more tests * Updates tests * Adds vuex * Moves splitpane to app * Moves the panes to app * Fixes columns with min-width * Update packages * Updates html to have better components * Updates npm packages * Fixes scrollar * Creates a scrollable view * Fixes App specs * Adds vuex for component * Updates to use splitpanes * Styles splitter * Removes fetch-mock --- assets/App.spec.js | 51 +-- assets/App.vue | 124 +++--- assets/__snapshots__/App.spec.js.snap | 65 +-- .../LogEventSource.spec.js} | 100 +++-- assets/components/LogEventSource.vue | 21 +- assets/components/LogViewer.vue | 98 +---- assets/components/LogViewerWithSource.vue | 19 + assets/components/ScrollableView.vue | 89 ++++ assets/components/ScrollbarNotification.vue | 70 ---- assets/components/Search.vue | 77 ++++ assets/components/SideMenu.vue | 122 ++++++ .../__snapshots__/LogEventSource.spec.js.snap | 9 + assets/main.js | 3 + assets/pages/Container.vue | 21 +- .../__snapshots__/Container.spec.js.snap | 62 --- assets/store/index.js | 56 +++ assets/styles.scss | 5 + package-lock.json | 383 +++++++++--------- package.json | 18 +- 19 files changed, 791 insertions(+), 602 deletions(-) rename assets/{pages/Container.spec.js => components/LogEventSource.spec.js} (54%) create mode 100644 assets/components/LogViewerWithSource.vue create mode 100644 assets/components/ScrollableView.vue delete mode 100644 assets/components/ScrollbarNotification.vue create mode 100644 assets/components/Search.vue create mode 100644 assets/components/SideMenu.vue create mode 100644 assets/components/__snapshots__/LogEventSource.spec.js.snap delete mode 100644 assets/pages/__snapshots__/Container.spec.js.snap create mode 100644 assets/store/index.js diff --git a/assets/App.spec.js b/assets/App.spec.js index c386e616..cba6d5b3 100644 --- a/assets/App.spec.js +++ b/assets/App.spec.js @@ -1,45 +1,50 @@ -import fetchMock from "fetch-mock"; import EventSource from "eventsourcemock"; -import { shallowMount, RouterLinkStub } from "@vue/test-utils"; +import { shallowMount, RouterLinkStub, createLocalVue } from "@vue/test-utils"; +import Vuex from "vuex"; import App from "./App"; +const localVue = createLocalVue(); + +localVue.use(Vuex); + describe("", () => { const stubs = { RouterLink: RouterLinkStub, "router-view": true }; + let store; + beforeEach(() => { global.BASE_PATH = ""; global.EventSource = EventSource; - fetchMock.getOnce("/api/containers.json", [{ id: "abc", name: "Test 1" }, { id: "xyz", name: "Test 2" }]); + const state = { + containers: [ + { id: "abc", name: "Test 1" }, + { id: "xyz", name: "Test 2" } + ] + }; + + const actions = { + FETCH_CONTAINERS: () => Promise.resolve() + }; + + store = new Vuex.Store({ + state, + actions + }); }); - afterEach(() => fetchMock.reset()); test("is a Vue instance", async () => { - const wrapper = shallowMount(App, { stubs }); + const wrapper = shallowMount(App, { stubs, store, localVue }); expect(wrapper.isVueInstance()).toBeTruthy(); }); test("has right title", async () => { - const wrapper = shallowMount(App, { stubs }); - await fetchMock.flush(); + const wrapper = shallowMount(App, { stubs, store, localVue }); + await wrapper.vm.$nextTick(); expect(wrapper.vm.title).toContain("2 containers"); }); test("renders correctly", async () => { - const wrapper = shallowMount(App, { stubs }); - await fetchMock.flush(); + const wrapper = shallowMount(App, { stubs, store, localVue }); + await wrapper.vm.$nextTick(); expect(wrapper.element).toMatchSnapshot(); }); - - test("renders router-link correctly", async () => { - const wrapper = shallowMount(App, { stubs }); - await fetchMock.flush(); - expect(wrapper.find(RouterLinkStub).props().to).toMatchInlineSnapshot(` - Object { - "name": "container", - "params": Object { - "id": "abc", - "name": "Test 1", - }, - } - `); - }); }); diff --git a/assets/App.vue b/assets/App.vue index 68a7f4b1..32538a2d 100644 --- a/assets/App.vue +++ b/assets/App.vue @@ -1,38 +1,49 @@ diff --git a/assets/__snapshots__/App.spec.js.snap b/assets/__snapshots__/App.spec.js.snap index b79977e3..47f79cdd 100644 --- a/assets/__snapshots__/App.spec.js.snap +++ b/assets/__snapshots__/App.spec.js.snap @@ -4,60 +4,23 @@ exports[` renders correctly 1`] = `
- +
- + + + + + +
`; diff --git a/assets/pages/Container.spec.js b/assets/components/LogEventSource.spec.js similarity index 54% rename from assets/pages/Container.spec.js rename to assets/components/LogEventSource.spec.js index 287341cd..98f802d3 100644 --- a/assets/pages/Container.spec.js +++ b/assets/components/LogEventSource.spec.js @@ -1,11 +1,12 @@ import EventSource from "eventsourcemock"; import { sources } from "eventsourcemock"; -import { shallowMount, mount } from "@vue/test-utils"; +import { shallowMount, mount, createLocalVue } from "@vue/test-utils"; +import Vuex from "vuex"; import MockDate from "mockdate"; -import Container from "./Container"; -import LogViewer from "../components/LogViewer.vue"; +import LogEventSource from "./LogEventSource.vue"; +import LogViewer from "./LogViewer.vue"; -describe("", () => { +describe("", () => { beforeEach(() => { global.BASE_PATH = ""; global.EventSource = EventSource; @@ -15,68 +16,103 @@ describe("", () => { afterEach(() => MockDate.reset()); + function createLogEventSource(searchFilter = null) { + const localVue = createLocalVue(); + localVue.use(Vuex); + + localVue.component("log-event-source", LogEventSource); + localVue.component("log-viewer", LogViewer); + + const state = { searchFilter }; + + const store = new Vuex.Store({ + state + }); + + return mount(LogEventSource, { + localVue, + store, + scopedSlots: { + default: ` + + ` + }, + propsData: { id: "abc" } + }); + } + test("is a Vue instance", async () => { - const wrapper = shallowMount(Container); + const wrapper = shallowMount(LogEventSource); expect(wrapper.isVueInstance()).toBeTruthy(); }); test("renders correctly", async () => { - const wrapper = mount(Container); + const wrapper = createLogEventSource(); expect(wrapper.element).toMatchSnapshot(); }); test("should connect to EventSource", async () => { - mount(Container, { - propsData: { id: "abc" } - }); + shallowMount(LogEventSource); sources["/api/logs/stream?id=abc"].emitOpen(); expect(sources["/api/logs/stream?id=abc"].readyState).toBe(1); }); test("should close EventSource", async () => { - const wrapper = mount(Container, { - propsData: { id: "abc" } - }); + const wrapper = createLogEventSource(); sources["/api/logs/stream?id=abc"].emitOpen(); wrapper.destroy(); expect(sources["/api/logs/stream?id=abc"].readyState).toBe(2); }); test("should parse messages", async () => { - const wrapper = mount(Container, { - propsData: { id: "abc" } - }); + const wrapper = createLogEventSource(); + sources["/api/logs/stream?id=abc"].emitOpen(); + sources["/api/logs/stream?id=abc"].emitMessage({ data: `2019-06-12T10:55:42.459034602Z "This is a message."` }); + const [message, _] = wrapper.vm.messages; + const { key, ...messageWithoutKey } = message; + + expect(key).toBeGreaterThanOrEqual(0); + + expect(messageWithoutKey).toMatchInlineSnapshot(` + Object { + "date": 2019-06-12T10:55:42.459Z, + "message": " \\"This is a message.\\"", + } + `); + }); + + test("should pass messages to slot", async () => { + const wrapper = createLogEventSource(); sources["/api/logs/stream?id=abc"].emitOpen(); sources["/api/logs/stream?id=abc"].emitMessage({ data: `2019-06-12T10:55:42.459034602Z "This is a message."` }); const [message, _] = wrapper.find(LogViewer).vm.messages; - expect(message).toMatchInlineSnapshot(` + const { key, ...messageWithoutKey } = message; + + expect(key).toBeGreaterThanOrEqual(0); + + expect(messageWithoutKey).toMatchInlineSnapshot(` Object { "date": 2019-06-12T10:55:42.459Z, - "key": 0, "message": " \\"This is a message.\\"", } `); }); test("should render messages", async () => { - const wrapper = mount(Container, { - propsData: { id: "abc" } - }); + const wrapper = createLogEventSource(); sources["/api/logs/stream?id=abc"].emitOpen(); sources["/api/logs/stream?id=abc"].emitMessage({ data: `2019-06-12T10:55:42.459034602Z "This is a message."` }); expect(wrapper.find("ul.events")).toMatchInlineSnapshot(`
    -
  • today at 10:55 AM "This is a message."
  • +
  • today at 10:55 AM "This is a message."
`); }); test("should render messages with color", async () => { - const wrapper = mount(Container, { - propsData: { id: "abc" } - }); + const wrapper = createLogEventSource(); sources["/api/logs/stream?id=abc"].emitOpen(); sources["/api/logs/stream?id=abc"].emitMessage({ data: `2019-06-12T10:55:42.459034602Z \x1b[30mblack\x1b[37mwhite` @@ -84,15 +120,13 @@ describe("", () => { expect(wrapper.find("ul.events")).toMatchInlineSnapshot(`
    -
  • today at 10:55 AM blackwhite
  • +
  • today at 10:55 AM blackwhite
`); }); test("should render messages with html entities", async () => { - const wrapper = mount(Container, { - propsData: { id: "abc" } - }); + const wrapper = createLogEventSource(); sources["/api/logs/stream?id=abc"].emitOpen(); sources["/api/logs/stream?id=abc"].emitMessage({ data: `2019-06-12T10:55:42.459034602Z foo bar` @@ -100,15 +134,13 @@ describe("", () => { expect(wrapper.find("ul.events")).toMatchInlineSnapshot(`
    -
  • today at 10:55 AM <test>foo bar</test>
  • +
  • today at 10:55 AM <test>foo bar</test>
`); }); test("should render messages with filter", async () => { - const wrapper = mount(Container, { - propsData: { id: "abc" } - }); + const wrapper = createLogEventSource("test"); sources["/api/logs/stream?id=abc"].emitOpen(); sources["/api/logs/stream?id=abc"].emitMessage({ data: `2019-06-11T10:55:42.459034602Z Foo bar` @@ -117,11 +149,9 @@ describe("", () => { data: `2019-06-12T10:55:42.459034602Z This is a test ` }); - wrapper.find(LogViewer).setData({ filter: "test" }); - expect(wrapper.find("ul.events")).toMatchInlineSnapshot(`
    -
  • today at 10:55 AM This is a test <hi></hi>
  • +
  • today at 10:55 AM This is a test <hi></hi>
`); }); diff --git a/assets/components/LogEventSource.vue b/assets/components/LogEventSource.vue index 5753ad14..a59c9cdd 100644 --- a/assets/components/LogEventSource.vue +++ b/assets/components/LogEventSource.vue @@ -1,12 +1,11 @@ - diff --git a/assets/components/ScrollbarNotification.vue b/assets/components/ScrollbarNotification.vue deleted file mode 100644 index c0c83348..00000000 --- a/assets/components/ScrollbarNotification.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - - diff --git a/assets/components/Search.vue b/assets/components/Search.vue new file mode 100644 index 00000000..2a5fd69d --- /dev/null +++ b/assets/components/Search.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/assets/components/SideMenu.vue b/assets/components/SideMenu.vue new file mode 100644 index 00000000..d54de041 --- /dev/null +++ b/assets/components/SideMenu.vue @@ -0,0 +1,122 @@ + + + + diff --git a/assets/components/__snapshots__/LogEventSource.spec.js.snap b/assets/components/__snapshots__/LogEventSource.spec.js.snap new file mode 100644 index 00000000..a3065f6e --- /dev/null +++ b/assets/components/__snapshots__/LogEventSource.spec.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` renders correctly 1`] = ` +
+
    +
+`; diff --git a/assets/main.js b/assets/main.js index 506353c8..66f228c0 100644 --- a/assets/main.js +++ b/assets/main.js @@ -1,6 +1,8 @@ import Vue from "vue"; import VueRouter from "vue-router"; import Meta from "vue-meta"; +import Vuex from "vuex"; +import store from "./store"; import App from "./App.vue"; import Container from "./pages/Container.vue"; import Index from "./pages/Index.vue"; @@ -30,5 +32,6 @@ const router = new VueRouter({ new Vue({ router, + store, render: h => h(App) }).$mount("#app"); diff --git a/assets/pages/Container.vue b/assets/pages/Container.vue index fb576640..12dbd8b2 100644 --- a/assets/pages/Container.vue +++ b/assets/pages/Container.vue @@ -1,19 +1,24 @@ - + diff --git a/assets/pages/__snapshots__/Container.spec.js.snap b/assets/pages/__snapshots__/Container.spec.js.snap deleted file mode 100644 index 4fe01731..00000000 --- a/assets/pages/__snapshots__/Container.spec.js.snap +++ /dev/null @@ -1,62 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` renders correctly 1`] = ` - -
- - -
    - - -
-
-`; diff --git a/assets/store/index.js b/assets/store/index.js new file mode 100644 index 00000000..4526bf4d --- /dev/null +++ b/assets/store/index.js @@ -0,0 +1,56 @@ +import Vue from "vue"; +import Vuex from "vuex"; +// import storage from "store/dist/store.modern"; + +Vue.use(Vuex); + +const state = { + containers: [], + activeContainers: [], + searchFilter: null +}; + +const mutations = { + SET_CONTAINERS(state, containers) { + state.containers = containers; + }, + ADD_ACTIVE_CONTAINERS(state, container) { + state.activeContainers.push(container); + }, + REMOVE_ACTIVE_CONTAINER(state, container) { + state.activeContainers.splice(state.activeContainers.indexOf(container), 1); + }, + SET_SEARCH(state, filter) { + state.searchFilter = filter; + } +}; + +const actions = { + APPEND_ACTIVE_CONTAINER({ commit }, container) { + commit("ADD_ACTIVE_CONTAINERS", container); + }, + REMOVE_ACTIVE_CONTAINER({ commit }, container) { + commit("REMOVE_ACTIVE_CONTAINER", container); + }, + SET_SEARCH({ commit }, filter) { + commit("SET_SEARCH", filter); + }, + async FETCH_CONTAINERS({ commit }) { + const containers = await (await fetch(`${BASE_PATH}/api/containers.json`)).json(); + commit("SET_CONTAINERS", containers); + } +}; +const getters = {}; + +const es = new EventSource(`${BASE_PATH}/api/events/stream`); +es.addEventListener("containers-changed", e => setTimeout(() => store.dispatch("FETCH_CONTAINERS"), 1000), false); + +const store = new Vuex.Store({ + strict: true, + state, + getters, + actions, + mutations +}); + +export default store; diff --git a/assets/styles.scss b/assets/styles.scss index ae45140a..bc5c16cb 100644 --- a/assets/styles.scss +++ b/assets/styles.scss @@ -4,6 +4,7 @@ $menu-item-active-background-color: hsl(171, 100%, 41%); $menu-item-color: hsl(0, 6%, 87%); @import "../node_modules/bulma/bulma.sass"; +@import "../node_modules/splitpanes/dist/splitpanes.css"; .is-dark { color: #ddd; @@ -17,3 +18,7 @@ body { h1.title { font-family: "Gafata", sans-serif; } + +.column { + min-width: 0; +} diff --git a/package-lock.json b/package-lock.json index ae73dbe0..fcdda703 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,18 +14,18 @@ } }, "@babel/core": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.2.tgz", - "integrity": "sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.7.4.tgz", + "integrity": "sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helpers": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/generator": "^7.7.4", + "@babel/helpers": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -45,84 +45,84 @@ } }, "@babel/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", "dev": true, "requires": { - "@babel/types": "^7.7.2", + "@babel/types": "^7.7.4", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", - "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/helper-get-function-arity": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", - "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" } }, "@babel/parser": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.2.tgz", - "integrity": "sha512-DDaR5e0g4ZTb9aP7cpSZLkACEBdoLGwJDWgHtBhrGX7Q1RjhdoMOfexICj5cqTAtpowjGQWfcvfnQG7G2kAB5w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", + "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", "dev": true }, "@babel/template": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", - "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/traverse": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz", - "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" } }, "@babel/types": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz", - "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -612,86 +612,86 @@ } }, "@babel/helpers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz", - "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.4.tgz", + "integrity": "sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==", "dev": true, "requires": { - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@babel/types": "^7.7.4" }, "dependencies": { "@babel/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", "dev": true, "requires": { - "@babel/types": "^7.7.2", + "@babel/types": "^7.7.4", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", - "integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/helper-get-function-arity": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", - "integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.7.4" } }, "@babel/parser": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.2.tgz", - "integrity": "sha512-DDaR5e0g4ZTb9aP7cpSZLkACEBdoLGwJDWgHtBhrGX7Q1RjhdoMOfexICj5cqTAtpowjGQWfcvfnQG7G2kAB5w==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", + "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", "dev": true }, "@babel/template": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", - "integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" } }, "@babel/traverse": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.2.tgz", - "integrity": "sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.2", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/parser": "^7.7.2", - "@babel/types": "^7.7.2", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -709,9 +709,9 @@ } }, "@babel/types": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.2.tgz", - "integrity": "sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -1172,15 +1172,37 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz", - "integrity": "sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.4.tgz", + "integrity": "sha512-O8kSkS5fP74Ad/8pfsCMGa8sBRdLxYoSReaARRNSz3FbFQj3z/QUvoUmJ28gn9BO93YfnXc3j+Xyaqe8cKDNBQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-module-imports": "^7.7.4", "@babel/helper-plugin-utils": "^7.0.0", "resolve": "^1.8.1", "semver": "^5.5.1" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz", + "integrity": "sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + } } }, "@babel/plugin-transform-shorthand-properties": { @@ -1852,9 +1874,9 @@ "dev": true }, "@types/node": { - "version": "12.7.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.11.tgz", - "integrity": "sha512-Otxmr2rrZLKRYIybtdG/sgeO+tHY20GxeDjcGmUnmmlCWyEnv2a2x1ZXBo3BTec4OiTXMQCiazB8NMBf0iRlFw==", + "version": "12.12.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.9.tgz", + "integrity": "sha512-kV3w4KeLsRBW+O2rKhktBwENNJuqAUQHS3kf4ia2wIaF/MN6U7ANgTsx7tGremcA0Pk3Yh0Hl0iKiLPuBdIgmw==", "dev": true }, "@types/normalize-package-data": { @@ -2354,17 +2376,6 @@ "babel-types": "^6.24.1" } }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - } - }, "babel-preset-jest": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", @@ -3790,9 +3801,9 @@ } }, "date-fns": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.7.0.tgz", - "integrity": "sha512-wxYp2PGoUDN5ZEACc61aOtYFvSsJUylIvCjpjDOqM1UDaKIIuMJ9fAnMYFHV3TQaDpfTVxhwNK/GiCaHKuemTA==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.8.1.tgz", + "integrity": "sha512-EL/C8IHvYRwAHYgFRse4MGAPSqlJVlOrhVYZ75iQBKrnv+ZedmYsgwH3t+BCDuZDXpoo07+q9j4qgSSOa7irJg==" }, "date-now": { "version": "0.1.4", @@ -3938,9 +3949,9 @@ }, "dependencies": { "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "rimraf": { @@ -4644,28 +4655,6 @@ "bser": "^2.0.0" } }, - "fetch-mock": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-7.7.3.tgz", - "integrity": "sha512-I4OkK90JFQnjH8/n3HDtWxH/I6D1wrxoAM2ri+nb444jpuH3RTcgvXx2el+G20KO873W727/66T7QhOvFxNHPg==", - "dev": true, - "requires": { - "babel-polyfill": "^6.26.0", - "core-js": "^2.6.9", - "glob-to-regexp": "^0.4.0", - "lodash.isequal": "^4.5.0", - "path-to-regexp": "^2.2.1", - "whatwg-url": "^6.5.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==", - "dev": true - } - } - }, "figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -5407,12 +5396,6 @@ "is-glob": "^4.0.1" } }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, "globals": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", @@ -5458,9 +5441,9 @@ "dev": true }, "handlebars": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.1.tgz", - "integrity": "sha512-C29UoFzHe9yM61lOsIlCE5/mQVGrnIOrOq7maQl76L7tYPCgC1og0Ajt6uWnX4ZTxBPnjw+CUvawphwCfJgUnA==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -5760,9 +5743,9 @@ "dev": true }, "husky": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/husky/-/husky-3.0.9.tgz", - "integrity": "sha512-Yolhupm7le2/MqC1VYLk/cNmYxsSsqKkTyBhzQHhPK1jFnC89mmmNVuGtLNabjDI6Aj8UNIr0KpRNuBkiC4+sg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-3.1.0.tgz", + "integrity": "sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -7349,9 +7332,9 @@ "dev": true }, "lint-staged": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-9.4.2.tgz", - "integrity": "sha512-OFyGokJSWTn2M6vngnlLXjaHhi8n83VIZZ5/1Z26SULRUWgR3ITWpAEQC9Pnm3MC/EpCxlwts/mQWDHNji2+zA==", + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-9.4.3.tgz", + "integrity": "sha512-PejnI+rwOAmKAIO+5UuAZU9gxdej/ovSEOAY34yMfC3OS4Ac82vCBPzAWLReR9zCPOMqeVwQRaZ3bUBpAsaL2Q==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -7391,11 +7374,22 @@ } }, "commander": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz", - "integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==", + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -7406,12 +7400,12 @@ } }, "execa": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/execa/-/execa-2.0.5.tgz", - "integrity": "sha512-SwmwZZyJjflcqLSgllk4EQlMLst2p9muyzwNugKGFlpAz6rZ7M+s2nBR97GAq4Vzjwx2y9rcMcmqzojwN+xwNA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", + "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", "dev": true, "requires": { - "cross-spawn": "^6.0.5", + "cross-spawn": "^7.0.0", "get-stream": "^5.0.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", @@ -7489,6 +7483,21 @@ "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==", "dev": true }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7497,6 +7506,15 @@ "requires": { "is-number": "^7.0.0" } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -7652,12 +7670,6 @@ "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", "dev": true }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -8879,12 +8891,6 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "path-to-regexp": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", - "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==", - "dev": true - }, "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", @@ -8920,9 +8926,9 @@ "dev": true }, "picomatch": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==", "dev": true }, "pify": { @@ -9831,12 +9837,6 @@ "regenerate": "^1.4.0" } }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true - }, "regenerator-transform": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", @@ -10181,9 +10181,9 @@ } }, "sass": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.23.3.tgz", - "integrity": "sha512-1DKRZxJMOh4Bme16AbWTyYeJAjTlrvw2+fWshHHaepeJfGq2soFZTnt0YhWit+bohtDu4LdyPoEj6VFD4APHog==", + "version": "1.23.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.23.7.tgz", + "integrity": "sha512-cYgc0fanwIpi0rXisGxl+/wadVQ/HX3RhpdRcjLdj2o2ye/sxUTpAxIhbmJy3PLQgRFbf6Pn8Jsrta2vdXcoOQ==", "dev": true, "requires": { "chokidar": ">=2.0.0 <4.0.0" @@ -10585,6 +10585,11 @@ "extend-shallow": "^3.0.0" } }, + "splitpanes": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-2.1.1.tgz", + "integrity": "sha512-K4jlE6gLKElsjtoUqzX6x0Uq4k7rnSBAMmxOJNWYTTIAuO7seC0+x3ADGpUgqtazMYdq0nAfWB9+NI/t/tW0mw==" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -10695,6 +10700,11 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "store": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/store/-/store-2.0.12.tgz", + "integrity": "sha1-jFNOKguDH3K3X8XxEZhXxE711ZM=" + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -11131,9 +11141,9 @@ "dev": true }, "uglify-js": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.7.tgz", - "integrity": "sha512-4sXQDzmdnoXiO+xvmTzQsfIiwrjUCSA95rSP4SEd8tDb51W2TiDOlL76Hl+Kw0Ie42PSItCW8/t6pBNCF2R48A==", + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", + "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", "dev": true, "optional": true, "requires": { @@ -11651,6 +11661,11 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vuex": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.2.tgz", + "integrity": "sha512-ha3jNLJqNhhrAemDXcmMJMKf1Zu4sybMPr9KxJIuOpVcsDQlTBYLLladav2U+g1AvdYDG5Gs0xBTb0M5pXXYFQ==" + }, "w3c-hr-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", diff --git a/package.json b/package.json index 6ad7cbdc..60049fd4 100644 --- a/package.json +++ b/package.json @@ -26,30 +26,32 @@ "dependencies": { "ansi-to-html": "^0.6.13", "bulma": "^0.8.0", - "date-fns": "^2.7.0", + "date-fns": "^2.8.1", + "splitpanes": "^2.1.1", + "store": "^2.0.12", "vue": "^2.6.10", "vue-meta": "^2.3.1", - "vue-router": "^3.1.3" + "vue-router": "^3.1.3", + "vuex": "^3.1.2" }, "devDependencies": { - "@babel/core": "^7.7.2", - "@babel/plugin-transform-runtime": "^7.6.2", + "@babel/core": "^7.7.4", + "@babel/plugin-transform-runtime": "^7.7.4", "@vue/component-compiler-utils": "^3.0.2", "@vue/test-utils": "^1.0.0-beta.29", "babel-core": "^7.0.0-bridge.0", "babel-jest": "^24.9.0", "concurrently": "^5.0.0", "eventsourcemock": "^2.0.0", - "fetch-mock": "^7.7.3", - "husky": "^3.0.9", + "husky": "^3.1.0", "jest": "^24.9.0", "jest-serializer-vue": "^2.0.2", - "lint-staged": "^9.4.2", + "lint-staged": "^9.4.3", "mockdate": "^2.0.5", "node-fetch": "^2.6.0", "parcel-bundler": "^1.12.4", "prettier": "^1.19.1", - "sass": "^1.23.3", + "sass": "^1.23.7", "vue-hot-reload-api": "^2.3.4", "vue-jest": "^3.0.5", "vue-template-compiler": "^2.6.10"